2 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 #include "stc-plugin-pcap.h"
19 #define PCAP_IFNAME "ifname"
20 #define PCAP_NFLOG_GROUP "nflog_group"
21 #define PCAP_DEV_NAME "dev"
22 #define PCAP_DEV_DECS "decs"
23 #define PCAP_DEV_NET "net"
24 #define PCAP_DEV_MASK "mask"
27 static GHashTable *g_pcap_tables = NULL;
28 static bool g_pcap_start_fm = false;
29 static struct timeval g_pcap_tv = { 0, };
31 static void __pcap_data_free(gpointer value)
33 stc_pcap_data_s *data = (stc_pcap_data_s *)value;
35 g_thread_unref(data->thread);
42 static void __pcap_data_info(const u_char *packet, int len)
46 data = g_string_sized_new(len);
51 g_string_append_printf(data, "%02x", *(packet++));
53 STC_LOGD("[%s]", g_string_free(data, FALSE));
57 static void __pcap_ntp_time_info(uint32_t s, char *time)
62 uint32_t sec = ntohl(s);
65 seconds = sec - NTP_JAN_1970;
66 curr = ctime(&seconds);
70 snprintf(time, len, "%s", curr);
72 snprintf(time, 10, "00:00:00");
76 static void __pcap_ntp_refid_info(ntp_t *ntp_h, char *refid)
78 switch (ntp_h->stratum) {
79 case NTP_STRATUM_UNSPECIFIED:
80 snprintf(refid, BUFF_SIZE_ID, "%s", "(unspec)");
82 case NTP_STRATUM_PRIM_REF:
83 snprintf(refid, BUFF_SIZE_ID, "%s", "(prim_ref)");
85 case NTP_STRATUM_INFO_QUERY:
86 snprintf(refid, BUFF_SIZE_ID, "%s INFO_QEURY",
87 inet_ntoa(*((struct in_addr *)&ntp_h->refid)));
89 case NTP_STRATUM_INFO_REPLY:
90 snprintf(refid, BUFF_SIZE_ID, "%s INFO_REPLY",
91 inet_ntoa(*((struct in_addr *)&ntp_h->refid)));
94 snprintf(refid, BUFF_SIZE_ID, "%s",
95 inet_ntoa(*((struct in_addr *)&ntp_h->refid)));
100 static uint16_t __pcap_ntp_fraction_info(uint16_t f)
105 ff = ntohs(f) / 65536.0;
106 fraction = (uint16_t)(ff * 1000000.0);
111 static void __pcap_ntp_info(const u_char *packet)
113 ntp_t *ntp_h = (ntp_t *)(packet +
114 SIZE_ETHER_HEADER + SIZE_IP_HEADER + SIZE_UDP_HEADER);
115 char refid[BUFF_SIZE_ID];
116 char reftime[BUFF_SIZE_TIME];
117 char orgtime[BUFF_SIZE_TIME];
118 char rectime[BUFF_SIZE_TIME];
119 char xmttime[BUFF_SIZE_TIME];
121 __pcap_ntp_refid_info(ntp_h, refid);
122 __pcap_ntp_time_info(ntp_h->reftime.second, reftime);
123 __pcap_ntp_time_info(ntp_h->orgtime.second, orgtime);
124 __pcap_ntp_time_info(ntp_h->rectime.second, rectime);
125 __pcap_ntp_time_info(ntp_h->xmttime.second, xmttime);
127 if (STC_DEBUG_LOG && STC_PCAP_LOG)
128 STC_LOGD("Flags[0x%02x] Stratum[%u] Poll[%u:%us] Precision[%u] "
129 "Root delay[%u.%06us] Root dispersion[%u.%06us] Ref ID[%s]",
130 ntp_h->flags, ntp_h->stratum, ntp_h->poll,
131 ntp_h->precision, 1 << ntp_h->precision,
132 ntohs(ntp_h->rootdelay.second),
133 __pcap_ntp_fraction_info(ntp_h->rootdelay.fraction),
134 ntohs(ntp_h->rootdisp.second),
135 __pcap_ntp_fraction_info(ntp_h->rootdisp.fraction),
138 if (STC_DEBUG_LOG && STC_PCAP_LOG)
139 STC_LOGD("Reference[%s] Origin[%s] Receive[%s] Transmit[%s]",
140 reftime, orgtime, rectime, xmttime);
143 static const char *__pcap_dhcp_client_id_info(uint8_t data)
148 case DHCP_CLIENT_ID_ETHERNET:
151 case DHCP_CLIENT_ID_IEEE802:
152 info = "IEEE 802 Networks";
154 case DHCP_CLIENT_ID_ARCNET:
157 case DHCP_CLIENT_ID_LOCALTALK:
160 case DHCP_CLIENT_ID_LOCALNET:
163 case DHCP_CLIENT_ID_SMDS:
166 case DHCP_CLIENT_ID_FRAMERELAY:
167 info = "Frame Relay";
169 case DHCP_CLIENT_ID_ATM1:
170 info = "ATM(Async Transfer Mode)";
172 case DHCP_CLIENT_ID_HDLC:
175 case DHCP_CLIENT_ID_FIBRECHANNEL:
176 info = "Fibre Channel";
178 case DHCP_CLIENT_ID_ATM2:
179 info = "ATM(Async Transfer Mode)";
181 case DHCP_CLIENT_ID_SERIALLINE:
182 info = "Serial Line";
192 static const char *__pcap_dhcp_msg_type_info(uint8_t type)
197 case DHCP_MSG_TYPE_DISCOVER:
200 case DHCP_MSG_TYPE_OFFER:
203 case DHCP_MSG_TYPE_REQUEST:
206 case DHCP_MSG_TYPE_DECLINE:
209 case DHCP_MSG_TYPE_ACK:
212 case DHCP_MSG_TYPE_NAK:
215 case DHCP_MSG_TYPE_RELEASE:
218 case DHCP_MSG_TYPE_INFORM:
229 static void __pcap_bootp_magic_info(uint32_t magic,
230 uint8_t *moption, u_int16_t len)
232 if (ntohl(magic) == BOOTP_MAGIC_DHCP) {
233 char buf[BOOTP_MOPTION_LEN];
234 uint8_t *opt = moption;
236 if (STC_DEBUG_LOG && STC_PCAP_LOG)
237 STC_LOGD("Magic cookie[DHCP]");
240 uint8_t tag = opt[0];
241 uint8_t length = opt[1];
242 uint8_t *data = &opt[2];
243 char addr[BUFF_SIZE_IP];
244 char host[BUFF_SIZE_HOST];
247 case DHCP_TAG_SUBNET_MASK:
248 inet_ntop(AF_INET, (struct in_addr *)data,
250 if (STC_DEBUG_LOG && STC_PCAP_LOG)
251 STC_LOGD("Subnet mask[%s]", addr);
253 case DHCP_TAG_ROUTER:
254 inet_ntop(AF_INET, (struct in_addr *)data,
256 if (STC_DEBUG_LOG && STC_PCAP_LOG)
257 STC_LOGD("Router[%s]", addr);
260 inet_ntop(AF_INET, (struct in_addr *)data,
262 if (STC_DEBUG_LOG && STC_PCAP_LOG)
263 STC_LOGD("Domain name server[%s]", addr);
265 case DHCP_TAG_HOST_NAME:
266 snprintf(buf, ((length < BOOTP_MOPTION_LEN) ?
267 (length + 1) : BOOTP_MOPTION_LEN), "%s", (char *)data);
268 if (STC_DEBUG_LOG && STC_PCAP_LOG)
269 STC_LOGD("Host name[%s]", buf);
271 case DHCP_TAG_REQUESTED_IP:
272 inet_ntop(AF_INET, (struct in_addr *)data,
274 if (STC_DEBUG_LOG && STC_PCAP_LOG)
275 STC_LOGD("Requested IP[%s]", addr);
277 case DHCP_TAG_IP_LEASE_TIME:
278 if (STC_DEBUG_LOG && STC_PCAP_LOG)
279 STC_LOGD("IP address lease time[%us]",
280 ntohl(*(uint32_t *)data));
282 case DHCP_TAG_MSG_TYPE:
283 if (STC_DEBUG_LOG && STC_PCAP_LOG)
284 STC_LOGD("DHCP message type[%u:%s]", *data,
285 __pcap_dhcp_msg_type_info(*data));
287 case DHCP_TAG_SERVER_ID:
288 inet_ntop(AF_INET, (struct in_addr *)data,
290 if (STC_DEBUG_LOG && STC_PCAP_LOG)
291 STC_LOGD("DHCP server identifier[%s]", addr);
293 case DHCP_TAG_MSG_SIZE:
294 if (STC_DEBUG_LOG && STC_PCAP_LOG)
295 STC_LOGD("Maximum DHCP message size[%u]",
296 ntohs(*(uint16_t *)data));
298 case DHCP_TAG_CLIENT_ID:
299 if (STC_DEBUG_LOG && STC_PCAP_LOG)
300 STC_LOGD("Client identifier HW type[0x%02x:%s]", *data,
301 __pcap_dhcp_client_id_info(*data));
302 if (*data == DHCP_CLIENT_ID_ETHERNET) {
304 ether_ntoa((const struct ether_addr *)&data[1]),
306 if (STC_DEBUG_LOG && STC_PCAP_LOG)
307 STC_LOGD("Client identifier MAC[%s]", host);
311 if (STC_DEBUG_LOG && STC_PCAP_LOG)
315 if (STC_DEBUG_LOG && STC_PCAP_LOG)
316 STC_LOGD("Unknown[%u]", tag);
326 static const char *__pcap_bootp_op_info(uint8_t op)
345 static void __pcap_bootp_info(const u_char *packet)
347 udp_t *udp_h = (udp_t *)(packet
348 + SIZE_ETHER_HEADER + SIZE_IP_HEADER);
349 bootp_t *bootp_h = (bootp_t *)(packet +
350 SIZE_ETHER_HEADER + SIZE_IP_HEADER + SIZE_UDP_HEADER);
351 char ciaddr[BUFF_SIZE_IP];
352 char yiaddr[BUFF_SIZE_IP];
353 char siaddr[BUFF_SIZE_IP];
354 char giaddr[BUFF_SIZE_IP];
355 char chaddr[BUFF_SIZE_HOST];
358 inet_ntop(AF_INET, &bootp_h->ciaddr, ciaddr, BUFF_SIZE_IP);
359 inet_ntop(AF_INET, &bootp_h->yiaddr, yiaddr, BUFF_SIZE_IP);
360 inet_ntop(AF_INET, &bootp_h->siaddr, siaddr, BUFF_SIZE_IP);
361 inet_ntop(AF_INET, &bootp_h->giaddr, giaddr, BUFF_SIZE_IP);
364 ether_ntoa((const struct ether_addr *)bootp_h->chaddr),
367 if (STC_DEBUG_LOG && STC_PCAP_LOG)
368 STC_LOGD("Message type[%u:%s] HW type[0x%02x] HW len[%u] Hops[%u] "
369 "Transaction ID[0x%08x] Seconds elapsed[%u] Flags[0x%04x]",
370 bootp_h->op, __pcap_bootp_op_info(bootp_h->op),
371 bootp_h->htype, bootp_h->hlen, bootp_h->hops,
372 ntohl(bootp_h->xid), ntohs(bootp_h->secs), ntohs(bootp_h->flags));
374 if (STC_DEBUG_LOG && STC_PCAP_LOG)
375 STC_LOGD("Client[%s] Your(client)[%s] Next server[%s] "
376 "Relay agent[%s] Client MAC[%s]",
377 ciaddr, yiaddr, siaddr, giaddr, chaddr);
379 len = ntohs(udp_h->len);
380 __pcap_bootp_magic_info(bootp_h->magic, bootp_h->moption, len);
383 static char *__pcap_dns_type_info(uint16_t type)
391 case DNS_QTYPE_CNAME:
405 static char *__pcap_dns_class_info(uint16_t class)
413 case DNS_QCLASS_CHAOS:
430 static uint8_t * __pcap_dns_name_info(uint8_t *dns_h,
431 uint8_t *data, u_char *name)
434 u_char *dname = name;
441 sec = (uint8_t *)dns_h +
442 (htons(*(uint16_t *)sec) & 0x3FFF);
450 if (dname - name + *sec + 1 > BUFF_SIZE_NAME - 1) {
455 memcpy(dname, sec + 1, *sec);
468 return (uint8_t *)nxt;
471 static void __pcap_dns_data_info(const u_char *packet)
473 dns_t *dns_h = (dns_t *)(packet +
474 SIZE_ETHER_HEADER + SIZE_IP_HEADER +
476 uint8_t *data = (uint8_t *)(packet +
477 SIZE_ETHER_HEADER + SIZE_IP_HEADER +
478 SIZE_UDP_HEADER + SIZE_DNS_HEADER);
479 uint16_t qdcount = ntohs(dns_h->questions);
480 uint16_t ancount = ntohs(dns_h->answerRR);
483 for (i = 0; i < qdcount; ++i) {
484 u_char name[BUFF_SIZE_NAME];
489 if (STC_DEBUG_LOG && STC_PCAP_LOG)
490 STC_LOGD("[Queries]");
493 data = __pcap_dns_name_info((uint8_t *)dns_h, data, name);
497 type = ntohs(*(uint16_t *)&data[0]);
498 class = ntohs(*(uint16_t *)&data[2]);
500 if (STC_DEBUG_LOG && STC_PCAP_LOG)
501 STC_LOGD("Name[%s] Type[%u:%s] Class[0x%04x:%s]",
502 name, type, __pcap_dns_type_info(type),
503 class, __pcap_dns_class_info(class));
508 for (i = 0; i < ancount; ++i) {
509 u_char name[BUFF_SIZE_NAME];
510 u_char cname[BUFF_SIZE_NAME];
515 char ip[BUFF_SIZE_IP];
518 if (STC_DEBUG_LOG && STC_PCAP_LOG)
519 STC_LOGD("[Answers]");
522 data = __pcap_dns_name_info((uint8_t *)dns_h, data, name);
526 type = ntohs(*(uint16_t *)&data[0]);
527 class = ntohs(*(uint16_t *)&data[2]);
528 ttl = ntohl(*(uint32_t *)&data[4]);
529 length = ntohs(*(uint16_t *)&data[8]);
531 if (class == DNS_QCLASS_IN) {
534 inet_ntop(AF_INET, (struct in_addr *)&data[10],
536 if (STC_DEBUG_LOG && STC_PCAP_LOG)
537 STC_LOGD("Name[%s] Type[%u:%s] Class[0x%04x:%s] "
538 "TTL[%u] Data length[%u] Address[%s]",
539 name, type, __pcap_dns_type_info(type),
540 class, __pcap_dns_class_info(class),
543 case DNS_QTYPE_CNAME:
544 __pcap_dns_name_info((uint8_t *)dns_h, &data[10], cname);
547 if (STC_DEBUG_LOG && STC_PCAP_LOG)
548 STC_LOGD("Name[%s] Type[%u:%s] Class[0x%04x:%s] "
549 "TTL[%u] Data length[%u] CName[%s]",
550 name, type, __pcap_dns_type_info(type),
551 class, __pcap_dns_class_info(class),
557 if (STC_DEBUG_LOG && STC_PCAP_LOG)
558 STC_LOGD("Name[%s] Type[%u:%s] Class[0x%04x:%s] "
559 "TTL[%u] Data length[%u]",
560 name, type, __pcap_dns_type_info(type),
561 class, __pcap_dns_class_info(class),
567 data += (length + 10);
571 static void __pcap_dns_info(const u_char *packet)
573 dns_t *dns_h = (dns_t *)(packet +
574 SIZE_ETHER_HEADER + SIZE_IP_HEADER + SIZE_UDP_HEADER);
576 if (STC_DEBUG_LOG && STC_PCAP_LOG)
577 STC_LOGD("Transaction ID[0x%x] Flags[0x%x] Questions[%u] "
578 "Answer RRs[%u] Authority RRs[%u] Additional RRs[%u]",
579 ntohs(dns_h->id), ntohs(dns_h->flags),
580 ntohs(dns_h->questions), ntohs(dns_h->answerRR),
581 ntohs(dns_h->authorityRR), ntohs(dns_h->additionalRR));
583 __pcap_dns_data_info(packet);
586 static const char *__pcap_icmp_code_info(u_int8_t type, u_int8_t code)
591 case ICMP_DEST_UNREACH:
593 case ICMP_NET_UNREACH:
594 info = "Network Unreachable";
596 case ICMP_HOST_UNREACH:
597 info = "Host Unreachable";
599 case ICMP_PROT_UNREACH:
600 info = "Protocol Unreachable";
602 case ICMP_PORT_UNREACH:
603 info = "Port Unreachable";
605 case ICMP_FRAG_NEEDED:
606 info = "Fragmentation Needed/DF set";
609 info = "Source Route failed";
611 case ICMP_NET_UNKNOWN:
613 case ICMP_HOST_UNKNOWN:
615 case ICMP_HOST_ISOLATED:
621 case ICMP_NET_UNR_TOS:
623 case ICMP_HOST_UNR_TOS:
625 case ICMP_PKT_FILTERED:
626 info = "Packet filtered";
628 case ICMP_PREC_VIOLATION:
629 info = "Precedence violation";
631 case ICMP_PREC_CUTOFF:
632 info = "Precedence cut off";
642 info = "Redirect Net";
644 case ICMP_REDIR_HOST:
645 info = "Redirect Host";
647 case ICMP_REDIR_NETTOS:
648 info = "Redirect Net for TOS";
650 case ICMP_REDIR_HOSTTOS:
651 info = "Redirect Host for TOS";
658 case ICMP_TIME_EXCEEDED:
661 info = "TTL count exceeded";
663 case ICMP_EXC_FRAGTIME:
664 info = "Fragment Reass time exceeded";
679 static const char *__pcap_icmp_type_info(u_int8_t type)
687 case ICMP_DEST_UNREACH:
688 info = "Destination Unreachable";
690 case ICMP_SOURCE_QUENCH:
691 info = "Source Quench";
697 info = "Echo Request";
699 case ICMP_TIME_EXCEEDED:
700 info = "Time Exceeded";
702 case ICMP_PARAMETERPROB:
703 info = "Parameter Problem";
706 info = "Timestamp Request";
708 case ICMP_TIMESTAMPREPLY:
709 info = "Timestamp Reply";
711 case ICMP_INFO_REQUEST:
712 info = "Information Request";
714 case ICMP_INFO_REPLY:
715 info = "Information Reply";
718 info = "Address Mask Request";
720 case ICMP_ADDRESSREPLY:
721 info = "Address Mask Reply";
731 static void __pcap_icmp_info(const u_char *packet)
733 icmp_t *icmp_h = (icmp_t *)(packet +
734 SIZE_ETHER_HEADER + SIZE_IP_HEADER);
736 if (STC_DEBUG_LOG && STC_PCAP_LOG)
737 STC_LOGD("Type[%u:%s] Code[%u:%s] Checksum[0x%x]",
738 icmp_h->type, __pcap_icmp_type_info(icmp_h->type),
739 icmp_h->code, __pcap_icmp_code_info(icmp_h->type, icmp_h->code),
740 ntohs(icmp_h->checksum));
743 static void __pcap_tcp_info(const u_char *packet)
745 tcp_t *tcp_h = (tcp_t *)(packet +
746 SIZE_ETHER_HEADER + SIZE_IP_HEADER);
747 u_int16_t source = ntohs(tcp_h->source);
748 u_int16_t dest = ntohs(tcp_h->dest);
750 if (STC_DEBUG_LOG && STC_PCAP_LOG)
751 STC_LOGD("Source[%u] Destination[%u] Sequence[%u] "
752 "Acknowledgment seq[%u] Window size[%u] ",
753 ntohs(tcp_h->source), ntohs(tcp_h->dest),
754 ntohl(tcp_h->seq), ntohl(tcp_h->ack_seq),
755 ntohs(tcp_h->window));
757 if (STC_DEBUG_LOG && STC_PCAP_LOG)
758 STC_LOGD("Checksum[0x%x] URG[%u] ACK[%u] PUSH[%u] "
759 "RST[%u] SYN[%u] FIN[%u]",
761 tcp_h->urg, tcp_h->ack, tcp_h->psh,
762 tcp_h->rst, tcp_h->syn, tcp_h->fin);
764 if (IS_SRC_OR_DST_PORT(PORT_DNS))
765 __pcap_dns_info(packet);
768 static void __pcap_udp_info(const u_char *packet)
770 udp_t *udp_h = (udp_t *)(packet
771 + SIZE_ETHER_HEADER + SIZE_IP_HEADER);
772 u_int16_t source = ntohs(udp_h->source);
773 u_int16_t dest = ntohs(udp_h->dest);
775 if (STC_DEBUG_LOG && STC_PCAP_LOG)
776 STC_LOGD("Source[%u] Destination[%u] Len[%u] Checksum[0x%x]",
777 source, dest, ntohs(udp_h->len), ntohs(udp_h->check));
779 if (IS_SRC_OR_DST_PORT(PORT_DNS))
780 __pcap_dns_info(packet);
781 else if (IS_SRC_OR_DST_PORT(PORT_BOOTP_C) ||
782 IS_SRC_OR_DST_PORT(PORT_BOOTP_S))
783 __pcap_bootp_info(packet);
784 else if (IS_SRC_OR_DST_PORT(PORT_NTP))
785 __pcap_ntp_info(packet);
788 static const char *__pcap_eth_type_info(u_int16_t type)
802 case ETHERTYPE_REVARP:
805 case ETHERTYPE_LOOPBACK:
816 static const char *__pcap_arp_opcode_info(u_int16_t opcode)
841 static void __pcap_arp_info(const u_char *packet)
843 arp_t *arp_h = (arp_t *)(packet + SIZE_ETHER_HEADER);
844 u_int8_t *sha = (u_int8_t *)(packet +
845 SIZE_ETHER_HEADER + SIZE_ARP_HEADER);
846 u_int8_t *spa = (u_int8_t *)(sha + arp_h->ar_hln);
847 u_int8_t *tha = (u_int8_t *)(spa + arp_h->ar_pln);
848 u_int8_t *tpa = (u_int8_t *)(tha + arp_h->ar_hln);
849 u_int16_t ar_op = ntohs(arp_h->ar_op);
850 char sma[BUFF_SIZE_HOST];
851 char sia[BUFF_SIZE_IP];
852 char tma[BUFF_SIZE_HOST];
853 char tia[BUFF_SIZE_IP];
857 ether_ntoa((const struct ether_addr *)sha),
860 ether_ntoa((const struct ether_addr *)tha),
863 inet_ntop(AF_INET, (struct in_addr *)spa, sia, BUFF_SIZE_IP);
864 inet_ntop(AF_INET, (struct in_addr *)tpa, tia, BUFF_SIZE_IP);
866 ar_pro = ntohs(arp_h->ar_pro);
868 if (STC_DEBUG_LOG && STC_PCAP_LOG)
869 STC_LOGD("HW type[%u] Protocol type[0x%04x:%s] "
870 "HW size[%u] Protocol size[%u] Opcode[%u:%s] ",
871 ntohs(arp_h->ar_hrd), ar_pro,
872 __pcap_eth_type_info(ar_pro),
873 arp_h->ar_hln, arp_h->ar_pln,
874 ar_op, __pcap_arp_opcode_info(ar_op));
876 if (STC_DEBUG_LOG && STC_PCAP_LOG)
877 STC_LOGD("Sender MAC[%s] Sender IP[%s] "
878 "Target MAC[%s] Target IP[%s]",
882 static const char *__pcap_ip_protocol_info(u_int8_t p)
916 static void __pcap_ipv6_info(const u_char *packet)
918 ip6_t *ip6_h = (ip6_t *)(packet + SIZE_ETHER_HEADER);
919 char ip6_src[BUFF_SIZE_IP6];
920 char ip6_dst[BUFF_SIZE_IP6];
922 inet_ntop(AF_INET6, &ip6_h->ip6_src, ip6_src, BUFF_SIZE_IP6);
923 inet_ntop(AF_INET6, &ip6_h->ip6_dst, ip6_dst, BUFF_SIZE_IP6);
925 if (STC_DEBUG_LOG && STC_PCAP_LOG)
926 STC_LOGD("Flow[0x%08x] Payload len[%u] Next hdr[%u:%s] "
927 "Hop limit[%u] Source[%s] Destination[%s]",
928 ntohl(ip6_h->ip6_flow), ntohs(ip6_h->ip6_plen),
929 ip6_h->ip6_nxt, __pcap_ip_protocol_info(ip6_h->ip6_nxt),
930 ip6_h->ip6_hlim, ip6_src, ip6_dst);
932 switch (ip6_h->ip6_nxt) {
952 static void __pcap_ip_info(const u_char *packet)
954 ip_t *ip_h = (ip_t *)(packet + SIZE_ETHER_HEADER);
955 char ip_src[BUFF_SIZE_IP];
956 char ip_dst[BUFF_SIZE_IP];
958 inet_ntop(AF_INET, &ip_h->ip_src, ip_src, BUFF_SIZE_IP);
959 inet_ntop(AF_INET, &ip_h->ip_dst, ip_dst, BUFF_SIZE_IP);
961 if (STC_DEBUG_LOG && STC_PCAP_LOG)
962 STC_LOGD("Header len[%u] TOS[0x%02x] Total len[%u] "
963 "ID[0x%04x] Flags[0x%02x] TTL[%u] Protocol[%u:%s] "
964 "Checksum[0x%04x] Source[%s] Destination[%s]",
965 ip_h->ip_hl << 2, ip_h->ip_tos,
966 ntohs(ip_h->ip_len), ntohs(ip_h->ip_id),
967 (ntohs(ip_h->ip_off) & 0xe000) >> 13,
968 ip_h->ip_ttl, ip_h->ip_p,
969 __pcap_ip_protocol_info(ip_h->ip_p),
970 ntohs(ip_h->ip_sum), ip_src, ip_dst);
972 switch (ip_h->ip_p) {
974 __pcap_icmp_info(packet);
977 __pcap_tcp_info(packet);
980 __pcap_udp_info(packet);
987 static void __pcap_eth_info(const u_char *packet)
989 eth_t *eth_h = (eth_t *)packet;
990 u_int8_t *eth_shost = eth_h->ether_shost;
991 u_int8_t *eth_dhost = eth_h->ether_dhost;
992 char shost[BUFF_SIZE_HOST];
993 char dhost[BUFF_SIZE_HOST];
994 u_int16_t ether_type;
997 ether_ntoa((const struct ether_addr *)eth_shost),
1001 ether_ntoa((const struct ether_addr *)eth_dhost),
1004 ether_type = ntohs(eth_h->ether_type);
1006 if (STC_DEBUG_LOG && STC_PCAP_LOG)
1007 STC_LOGD("Source[%s] Destination[%s] Type[0x%04x:%s]",
1008 shost, dhost, ether_type, __pcap_eth_type_info(ether_type));
1011 static void __pcap_fm_info(const struct pcap_pkthdr *pkthdr)
1015 struct timeval ts = pkthdr->ts;
1016 __time_t tv_sec = ts.tv_sec;
1017 __suseconds_t tv_usec = tv_usec;
1019 if (g_pcap_start_fm == false) {
1021 g_pcap_start_fm = true;
1024 curr = ctime((const time_t *)&tv_sec);
1026 curr[len - 1] = '\0';
1028 if (STC_DEBUG_LOG && STC_PCAP_LOG)
1029 STC_LOGD("Arrival time[%s] Timeval[%.06f] "
1030 "Frame len[%u] Capture len[%u]", curr,
1031 (float)((tv_sec - g_pcap_tv.tv_sec) * 1000000 +
1032 (tv_usec - g_pcap_tv.tv_usec)) / 1000000,
1033 pkthdr->len, pkthdr->caplen);
1036 static void __pcap_handler(u_char *param,
1037 const struct pcap_pkthdr *pkthdr,
1038 const u_char *packet) {
1040 unsigned short eth_type;
1041 /* int len = pkthdr->len; */
1043 __pcap_fm_info(pkthdr);
1045 eth_h = (eth_t *)packet;
1046 __pcap_eth_info(packet);
1048 eth_type = ntohs(eth_h->ether_type);
1051 __pcap_ip_info(packet);
1052 /* __pcap_data_info(pcaket, len); */
1054 case ETHERTYPE_IPV6:
1055 __pcap_ipv6_info(packet);
1058 case ETHERTYPE_REVARP:
1059 __pcap_arp_info(packet);
1061 case ETHERTYPE_LOOPBACK:
1068 static gboolean __pcap_thread_source_func(gpointer data)
1070 char buf[MAX_IFACE_LENGTH];
1071 stc_pcap_data_s *lookup;
1072 stc_pcap_data_s *pcap_data = (stc_pcap_data_s *)data;
1074 g_pcap_tv.tv_sec = 0;
1075 g_pcap_tv.tv_usec = 0;
1076 g_pcap_start_fm = false;
1078 if (g_pcap_tables == NULL)
1081 snprintf(buf, sizeof(buf), "%s_%d",
1082 pcap_data->ifname, pcap_data->nflog_group);
1084 lookup = g_hash_table_lookup(g_pcap_tables, buf);
1086 STC_LOGE("pcap loop not found");
1090 g_hash_table_remove(g_pcap_tables, buf);
1091 STC_LOGD("Successfully removed pcap loop [%s]", buf);
1096 static gpointer __pcap_thread_func(gpointer data)
1098 __STC_LOG_FUNC_ENTER__;
1100 char errbuf[PCAP_ERRBUF_SIZE];
1101 pcap_if_t *alldevs = NULL;
1102 pcap_if_t *dev = NULL;
1104 GSource *source = NULL;
1105 GMainContext *context = NULL;
1106 stc_pcap_data_s *pcap_data = (stc_pcap_data_s *)data;
1108 if (pcap_findalldevs(&alldevs, errbuf) < 0 ||
1110 STC_LOGE("Failed to find all devs [%s]", errbuf);
1114 for (dev = alldevs; dev; dev = dev->next) {
1115 if (g_strcmp0(dev->name, pcap_data->ifname) == 0) {
1116 name = g_strdup(dev->name);
1121 pcap_freealldevs(alldevs);
1124 STC_LOGE("Failed to find dev [%s]", pcap_data->ifname);
1128 STC_LOGD("Pcap source dev [%s]", name);
1130 pcap_data->handle = pcap_open_live(name, 65535, 1, 1000, errbuf);
1131 if (pcap_data->handle == NULL) {
1132 STC_LOGE("Failed to open live [%s]", errbuf);
1136 STC_LOGD("Pcap loop start [%s]", name);
1137 pcap_loop(pcap_data->handle, 0, __pcap_handler, NULL);
1138 STC_LOGD("Pcap loop end [%s]", name);
1140 pcap_close(pcap_data->handle);
1141 STC_LOGD("Pcap closed [%s]", name);
1146 context = g_main_context_default();
1148 source = g_idle_source_new();
1150 g_source_set_callback(source,
1151 __pcap_thread_source_func, pcap_data, NULL);
1152 g_source_attach(source, context);
1154 g_source_unref(source);
1156 __STC_LOG_FUNC_EXIT__;
1160 static void __pcap_make_params(gpointer key, gpointer value,
1163 stc_pcap_data_s *data = (stc_pcap_data_s *)value;
1164 GVariantBuilder *builder = (GVariantBuilder *)user_data;
1165 GVariantBuilder sub_builder;
1167 g_variant_builder_init(&sub_builder, G_VARIANT_TYPE("a{sv}"));
1169 g_variant_builder_add(&sub_builder, "{sv}", PCAP_IFNAME,
1170 g_variant_new_string(data->ifname));
1172 g_variant_builder_add(&sub_builder, "{sv}", PCAP_NFLOG_GROUP,
1173 g_variant_new_uint32(data->nflog_group));
1175 g_variant_builder_add_value(builder, g_variant_builder_end(&sub_builder));
1178 int stc_plugin_pcap_initialize(void)
1180 __STC_LOG_FUNC_ENTER__;
1182 g_pcap_tables = g_hash_table_new_full(g_str_hash,
1183 g_str_equal, g_free, __pcap_data_free);
1185 __STC_LOG_FUNC_EXIT__;
1186 return STC_ERROR_NONE;
1189 int stc_plugin_pcap_deinitialize(void)
1191 __STC_LOG_FUNC_ENTER__;
1193 if (g_pcap_tables) {
1194 g_hash_table_destroy(g_pcap_tables);
1195 g_pcap_tables = NULL;
1198 __STC_LOG_FUNC_EXIT__;
1199 return STC_ERROR_NONE;
1202 int stc_plugin_pcap_lookup_dev(void)
1205 char errbuf[PCAP_ERRBUF_SIZE];
1207 dev = pcap_lookupdev(errbuf);
1209 STC_LOGE("Failed to look up dev [%s]", errbuf);
1210 return STC_ERROR_FAIL;
1213 STC_LOGD("Dev [%s]", dev);
1215 return STC_ERROR_NONE;
1218 int stc_plugin_pcap_lookup_net(void)
1221 char net[BUFF_SIZE_IP];
1222 char mask[BUFF_SIZE_IP];
1223 char errbuf[PCAP_ERRBUF_SIZE];
1228 dev = pcap_lookupdev(errbuf);
1230 STC_LOGE("Failed to look up dev [%s]", errbuf);
1231 return STC_ERROR_FAIL;
1234 STC_LOGD("Dev [%s]", dev);
1236 ret = pcap_lookupnet(dev, &netp, &maskp, errbuf);
1238 STC_LOGE("Failed to look up net [%s]", errbuf);
1239 return STC_ERROR_FAIL;
1242 inet_ntop(AF_INET, &netp, net, BUFF_SIZE_IP);
1243 STC_LOGD("Net [%s]", net);
1245 inet_ntop(AF_INET, &maskp, mask, BUFF_SIZE_IP);
1246 STC_LOGD("Mask [%s]", mask);
1248 return STC_ERROR_NONE;
1251 int stc_plugin_pcap_find_all_devs(GVariantBuilder *builder)
1253 char net[BUFF_SIZE_IP];
1254 char mask[BUFF_SIZE_IP];
1255 char errbuf[PCAP_ERRBUF_SIZE];
1256 pcap_if_t *alldevs = NULL;
1257 pcap_if_t *dev = NULL;
1261 if (pcap_findalldevs(&alldevs, errbuf) < 0 ||
1263 STC_LOGE("Failed to find all devs [%s]", errbuf);
1264 return STC_ERROR_FAIL;
1267 for (dev = alldevs; dev; dev = dev->next) {
1268 GVariantBuilder sub_builder;
1270 g_variant_builder_init(&sub_builder, G_VARIANT_TYPE("a{sv}"));
1272 STC_LOGD("Dev [%s]", dev->name);
1273 g_variant_builder_add(&sub_builder, "{sv}", PCAP_DEV_NAME,
1274 g_variant_new_string(dev->name));
1276 if (dev->description) {
1277 STC_LOGD("Decs [%s]", dev->description);
1278 g_variant_builder_add(&sub_builder, "{sv}", PCAP_DEV_DECS,
1279 g_variant_new_string(dev->description));
1282 if (pcap_lookupnet(dev->name, &netp, &maskp, errbuf) == -1) {
1283 STC_LOGE("Failed to look up net [%s]", errbuf);
1284 g_variant_builder_add_value(builder, g_variant_builder_end(&sub_builder));
1288 inet_ntop(AF_INET, &netp, net, BUFF_SIZE_IP);
1289 STC_LOGD("Net [%s]", net);
1290 g_variant_builder_add(&sub_builder, "{sv}", PCAP_DEV_NET,
1291 g_variant_new_string(net));
1293 inet_ntop(AF_INET, &maskp, mask, BUFF_SIZE_IP);
1294 STC_LOGD("Mask [%s]", mask);
1295 g_variant_builder_add(&sub_builder, "{sv}", PCAP_DEV_MASK,
1296 g_variant_new_string(mask));
1298 g_variant_builder_add_value(builder, g_variant_builder_end(&sub_builder));
1301 pcap_freealldevs(alldevs);
1303 return STC_ERROR_NONE;
1306 int stc_plugin_pcap_register_loop(const char *ifname,
1309 stc_pcap_data_s *data;
1310 stc_pcap_data_s *lookup;
1311 char buf[MAX_IFACE_LENGTH];
1313 ret_value_msg_if(g_pcap_tables == NULL,
1315 "pcap tables is not initialized!");
1317 ret_value_msg_if(ifname == NULL,
1319 "Invalid parameter [ifname]");
1321 snprintf(buf, sizeof(buf), "%s_%d", ifname, nflog_group);
1323 lookup = g_hash_table_lookup(g_pcap_tables, buf);
1325 STC_LOGD("pcap loop already present");
1326 return STC_ERROR_ALREADY_DATA;
1329 data = MALLOC0(stc_pcap_data_s, 1);
1331 STC_LOGE("data allocation failed");
1332 return STC_ERROR_OUT_OF_MEMORY;
1335 data->ifname = g_strdup(ifname);
1336 data->nflog_group = nflog_group;
1337 data->thread = g_thread_new(buf, __pcap_thread_func, data);
1339 g_hash_table_insert(g_pcap_tables, g_strdup(buf), data);
1340 STC_LOGD("Successfully added pcap loop [%s]", buf);
1342 return STC_ERROR_NONE;
1345 int stc_plugin_pcap_unregister_loop(const char *ifname,
1348 stc_pcap_data_s *lookup;
1349 char buf[MAX_IFACE_LENGTH];
1351 ret_value_msg_if(g_pcap_tables == NULL,
1353 "pcap tables is not initialized!");
1355 ret_value_msg_if(ifname == NULL,
1357 "Invalid parameter [ifname]");
1359 snprintf(buf, sizeof(buf), "%s_%d", ifname, nflog_group);
1361 lookup = g_hash_table_lookup(g_pcap_tables, buf);
1363 STC_LOGE("pcap loop not found");
1364 __STC_LOG_FUNC_EXIT__;
1365 return STC_ERROR_NO_DATA;
1368 pcap_breakloop(lookup->handle);
1369 STC_LOGD("Successfully removed pcap loop [%s]", buf);
1371 return STC_ERROR_NONE;
1374 int stc_plugin_pcap_get_all_loop(GVariantBuilder *builder)
1376 ret_value_msg_if(g_pcap_tables == NULL,
1378 "pcap tables is not initialized!");
1380 g_hash_table_foreach(g_pcap_tables, __pcap_make_params, builder);
1382 return STC_ERROR_NONE;
1385 API stc_plugin_pcap_s stc_plugin_pcap = {
1386 .initialize_plugin =
1387 stc_plugin_pcap_initialize,
1388 .deinitialize_plugin =
1389 stc_plugin_pcap_deinitialize,
1391 stc_plugin_pcap_lookup_dev,
1393 stc_plugin_pcap_lookup_net,
1395 stc_plugin_pcap_find_all_devs,
1397 stc_plugin_pcap_register_loop,
1399 stc_plugin_pcap_unregister_loop,
1401 stc_plugin_pcap_get_all_loop