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"
23 static GHashTable *g_pcap_tables = NULL;
24 static bool g_pcap_start_fm = false;
25 static struct timeval g_pcap_tv = { 0, };
27 static void __pcap_data_free(gpointer value)
29 stc_pcap_data_s *data = (stc_pcap_data_s *)value;
31 g_thread_unref(data->thread);
38 static void __pcap_data_info(const u_char *packet, int len)
42 data = g_string_sized_new(len);
47 g_string_append_printf(data, "%02x", *(packet++));
49 STC_LOGD("[%s]", g_string_free(data, FALSE));
53 static void __pcap_ntp_time_info(uint32_t s, char *time)
58 uint32_t sec = ntohl(s);
61 seconds = sec - NTP_JAN_1970;
62 curr = ctime(&seconds);
66 snprintf(time, len, "%s", curr);
68 snprintf(time, 10, "00:00:00");
72 static void __pcap_ntp_refid_info(ntp_t *ntp_h, char *refid)
74 switch (ntp_h->stratum) {
75 case NTP_STRATUM_UNSPECIFIED:
76 snprintf(refid, BUFF_SIZE_ID, "%s", "(unspec)");
78 case NTP_STRATUM_PRIM_REF:
79 snprintf(refid, BUFF_SIZE_ID, "%s", "(prim_ref)");
81 case NTP_STRATUM_INFO_QUERY:
82 snprintf(refid, BUFF_SIZE_ID, "%s INFO_QEURY",
83 inet_ntoa(*((struct in_addr *)&ntp_h->refid)));
85 case NTP_STRATUM_INFO_REPLY:
86 snprintf(refid, BUFF_SIZE_ID, "%s INFO_REPLY",
87 inet_ntoa(*((struct in_addr *)&ntp_h->refid)));
90 snprintf(refid, BUFF_SIZE_ID, "%s",
91 inet_ntoa(*((struct in_addr *)&ntp_h->refid)));
96 static uint16_t __pcap_ntp_fraction_info(uint16_t f)
101 ff = ntohs(f) / 65536.0;
102 fraction = (uint16_t)(ff * 1000000.0);
107 static void __pcap_ntp_info(const u_char *packet)
109 ntp_t *ntp_h = (ntp_t *)(packet +
110 SIZE_ETHER_HEADER + SIZE_IP_HEADER + SIZE_UDP_HEADER);
111 char refid[BUFF_SIZE_ID];
112 char reftime[BUFF_SIZE_TIME];
113 char orgtime[BUFF_SIZE_TIME];
114 char rectime[BUFF_SIZE_TIME];
115 char xmttime[BUFF_SIZE_TIME];
117 __pcap_ntp_refid_info(ntp_h, refid);
118 __pcap_ntp_time_info(ntp_h->reftime.second, reftime);
119 __pcap_ntp_time_info(ntp_h->orgtime.second, orgtime);
120 __pcap_ntp_time_info(ntp_h->rectime.second, rectime);
121 __pcap_ntp_time_info(ntp_h->xmttime.second, xmttime);
123 if (STC_DEBUG_LOG && STC_PCAP_LOG)
124 STC_LOGD("Flags[0x%02x] Stratum[%u] Poll[%u:%us] Precision[%u] "
125 "Root delay[%u.%06us] Root dispersion[%u.%06us] Ref ID[%s]",
126 ntp_h->flags, ntp_h->stratum, ntp_h->poll,
127 ntp_h->precision, 1 << ntp_h->precision,
128 ntohs(ntp_h->rootdelay.second),
129 __pcap_ntp_fraction_info(ntp_h->rootdelay.fraction),
130 ntohs(ntp_h->rootdisp.second),
131 __pcap_ntp_fraction_info(ntp_h->rootdisp.fraction),
134 if (STC_DEBUG_LOG && STC_PCAP_LOG)
135 STC_LOGD("Reference[%s] Origin[%s] Receive[%s] Transmit[%s]",
136 reftime, orgtime, rectime, xmttime);
139 static const char *__pcap_dhcp_client_id_info(uint8_t data)
144 case DHCP_CLIENT_ID_ETHERNET:
147 case DHCP_CLIENT_ID_IEEE802:
148 info = "IEEE 802 Networks";
150 case DHCP_CLIENT_ID_ARCNET:
153 case DHCP_CLIENT_ID_LOCALTALK:
156 case DHCP_CLIENT_ID_LOCALNET:
159 case DHCP_CLIENT_ID_SMDS:
162 case DHCP_CLIENT_ID_FRAMERELAY:
163 info = "Frame Relay";
165 case DHCP_CLIENT_ID_ATM1:
166 info = "ATM(Async Transfer Mode)";
168 case DHCP_CLIENT_ID_HDLC:
171 case DHCP_CLIENT_ID_FIBRECHANNEL:
172 info = "Fibre Channel";
174 case DHCP_CLIENT_ID_ATM2:
175 info = "ATM(Async Transfer Mode)";
177 case DHCP_CLIENT_ID_SERIALLINE:
178 info = "Serial Line";
188 static const char *__pcap_dhcp_msg_type_info(uint8_t type)
193 case DHCP_MSG_TYPE_DISCOVER:
196 case DHCP_MSG_TYPE_OFFER:
199 case DHCP_MSG_TYPE_REQUEST:
202 case DHCP_MSG_TYPE_DECLINE:
205 case DHCP_MSG_TYPE_ACK:
208 case DHCP_MSG_TYPE_NAK:
211 case DHCP_MSG_TYPE_RELEASE:
214 case DHCP_MSG_TYPE_INFORM:
225 static void __pcap_bootp_magic_info(uint32_t magic,
226 uint8_t *moption, u_int16_t len)
228 if (ntohl(magic) == BOOTP_MAGIC_DHCP) {
229 char buf[BOOTP_MOPTION_LEN];
230 uint8_t *opt = moption;
232 if (STC_DEBUG_LOG && STC_PCAP_LOG)
233 STC_LOGD("Magic cookie[DHCP]");
236 uint8_t tag = opt[0];
237 uint8_t length = opt[1];
238 uint8_t *data = &opt[2];
239 char addr[BUFF_SIZE_IP];
240 char host[BUFF_SIZE_HOST];
243 case DHCP_TAG_SUBNET_MASK:
244 inet_ntop(AF_INET, (struct in_addr *)data,
246 if (STC_DEBUG_LOG && STC_PCAP_LOG)
247 STC_LOGD("Subnet mask[%s]", addr);
249 case DHCP_TAG_ROUTER:
250 inet_ntop(AF_INET, (struct in_addr *)data,
252 if (STC_DEBUG_LOG && STC_PCAP_LOG)
253 STC_LOGD("Router[%s]", addr);
256 inet_ntop(AF_INET, (struct in_addr *)data,
258 if (STC_DEBUG_LOG && STC_PCAP_LOG)
259 STC_LOGD("Domain name server[%s]", addr);
261 case DHCP_TAG_HOST_NAME:
262 snprintf(buf, ((length < BOOTP_MOPTION_LEN) ?
263 (length + 1) : BOOTP_MOPTION_LEN), "%s", (char *)data);
264 if (STC_DEBUG_LOG && STC_PCAP_LOG)
265 STC_LOGD("Host name[%s]", buf);
267 case DHCP_TAG_REQUESTED_IP:
268 inet_ntop(AF_INET, (struct in_addr *)data,
270 if (STC_DEBUG_LOG && STC_PCAP_LOG)
271 STC_LOGD("Requested IP[%s]", addr);
273 case DHCP_TAG_IP_LEASE_TIME:
274 if (STC_DEBUG_LOG && STC_PCAP_LOG)
275 STC_LOGD("IP address lease time[%us]",
276 ntohl(*(uint32_t *)data));
278 case DHCP_TAG_MSG_TYPE:
279 if (STC_DEBUG_LOG && STC_PCAP_LOG)
280 STC_LOGD("DHCP message type[%u:%s]", *data,
281 __pcap_dhcp_msg_type_info(*data));
283 case DHCP_TAG_SERVER_ID:
284 inet_ntop(AF_INET, (struct in_addr *)data,
286 if (STC_DEBUG_LOG && STC_PCAP_LOG)
287 STC_LOGD("DHCP server identifier[%s]", addr);
289 case DHCP_TAG_MSG_SIZE:
290 if (STC_DEBUG_LOG && STC_PCAP_LOG)
291 STC_LOGD("Maximum DHCP message size[%u]",
292 ntohs(*(uint16_t *)data));
294 case DHCP_TAG_CLIENT_ID:
295 if (STC_DEBUG_LOG && STC_PCAP_LOG)
296 STC_LOGD("Client identifier HW type[0x%02x:%s]", *data,
297 __pcap_dhcp_client_id_info(*data));
298 if (*data == DHCP_CLIENT_ID_ETHERNET) {
300 ether_ntoa((const struct ether_addr *)&data[1]),
302 if (STC_DEBUG_LOG && STC_PCAP_LOG)
303 STC_LOGD("Client identifier MAC[%s]", host);
307 if (STC_DEBUG_LOG && STC_PCAP_LOG)
311 if (STC_DEBUG_LOG && STC_PCAP_LOG)
312 STC_LOGD("Unknown[%u]", tag);
322 static const char *__pcap_bootp_op_info(uint8_t op)
341 static void __pcap_bootp_info(const u_char *packet)
343 udp_t *udp_h = (udp_t *)(packet
344 + SIZE_ETHER_HEADER + SIZE_IP_HEADER);
345 bootp_t *bootp_h = (bootp_t *)(packet +
346 SIZE_ETHER_HEADER + SIZE_IP_HEADER + SIZE_UDP_HEADER);
347 char ciaddr[BUFF_SIZE_IP];
348 char yiaddr[BUFF_SIZE_IP];
349 char siaddr[BUFF_SIZE_IP];
350 char giaddr[BUFF_SIZE_IP];
351 char chaddr[BUFF_SIZE_HOST];
354 inet_ntop(AF_INET, &bootp_h->ciaddr, ciaddr, BUFF_SIZE_IP);
355 inet_ntop(AF_INET, &bootp_h->yiaddr, yiaddr, BUFF_SIZE_IP);
356 inet_ntop(AF_INET, &bootp_h->siaddr, siaddr, BUFF_SIZE_IP);
357 inet_ntop(AF_INET, &bootp_h->giaddr, giaddr, BUFF_SIZE_IP);
360 ether_ntoa((const struct ether_addr *)bootp_h->chaddr),
363 if (STC_DEBUG_LOG && STC_PCAP_LOG)
364 STC_LOGD("Message type[%u:%s] HW type[0x%02x] HW len[%u] Hops[%u] "
365 "Transaction ID[0x%08x] Seconds elapsed[%u] Flags[0x%04x]",
366 bootp_h->op, __pcap_bootp_op_info(bootp_h->op),
367 bootp_h->htype, bootp_h->hlen, bootp_h->hops,
368 ntohl(bootp_h->xid), ntohs(bootp_h->secs), ntohs(bootp_h->flags));
370 if (STC_DEBUG_LOG && STC_PCAP_LOG)
371 STC_LOGD("Client[%s] Your(client)[%s] Next server[%s] "
372 "Relay agent[%s] Client MAC[%s]",
373 ciaddr, yiaddr, siaddr, giaddr, chaddr);
375 len = ntohs(udp_h->len);
376 __pcap_bootp_magic_info(bootp_h->magic, bootp_h->moption, len);
379 static char *__pcap_dns_type_info(uint16_t type)
387 case DNS_QTYPE_CNAME:
401 static char *__pcap_dns_class_info(uint16_t class)
409 case DNS_QCLASS_CHAOS:
426 static uint8_t * __pcap_dns_name_info(uint8_t *dns_h,
427 uint8_t *data, u_char *name)
430 u_char *dname = name;
437 sec = (uint8_t *)dns_h +
438 (htons(*(uint16_t *)sec) & 0x3FFF);
446 if (dname - name + *sec + 1 > BUFF_SIZE_NAME - 1) {
451 memcpy(dname, sec + 1, *sec);
464 return (uint8_t *)nxt;
467 static void __pcap_dns_data_info(const u_char *packet)
469 dns_t *dns_h = (dns_t *)(packet +
470 SIZE_ETHER_HEADER + SIZE_IP_HEADER +
472 uint8_t *data = (uint8_t *)(packet +
473 SIZE_ETHER_HEADER + SIZE_IP_HEADER +
474 SIZE_UDP_HEADER + SIZE_DNS_HEADER);
475 uint16_t qdcount = ntohs(dns_h->questions);
476 uint16_t ancount = ntohs(dns_h->answerRR);
479 for (i = 0; i < qdcount; ++i) {
480 u_char name[BUFF_SIZE_NAME];
485 if (STC_DEBUG_LOG && STC_PCAP_LOG)
486 STC_LOGD("[Queries]");
489 data = __pcap_dns_name_info((uint8_t *)dns_h, data, name);
493 type = ntohs(*(uint16_t *)&data[0]);
494 class = ntohs(*(uint16_t *)&data[2]);
496 if (STC_DEBUG_LOG && STC_PCAP_LOG)
497 STC_LOGD("Name[%s] Type[%u:%s] Class[0x%04x:%s]",
498 name, type, __pcap_dns_type_info(type),
499 class, __pcap_dns_class_info(class));
504 for (i = 0; i < ancount; ++i) {
505 u_char name[BUFF_SIZE_NAME];
506 u_char cname[BUFF_SIZE_NAME];
511 char ip[BUFF_SIZE_IP];
514 if (STC_DEBUG_LOG && STC_PCAP_LOG)
515 STC_LOGD("[Answers]");
518 data = __pcap_dns_name_info((uint8_t *)dns_h, data, name);
522 type = ntohs(*(uint16_t *)&data[0]);
523 class = ntohs(*(uint16_t *)&data[2]);
524 ttl = ntohl(*(uint32_t *)&data[4]);
525 length = ntohs(*(uint16_t *)&data[8]);
527 if (class == DNS_QCLASS_IN) {
530 inet_ntop(AF_INET, (struct in_addr *)&data[10],
532 if (STC_DEBUG_LOG && STC_PCAP_LOG)
533 STC_LOGD("Name[%s] Type[%u:%s] Class[0x%04x:%s] "
534 "TTL[%u] Data length[%u] Address[%s]",
535 name, type, __pcap_dns_type_info(type),
536 class, __pcap_dns_class_info(class),
539 case DNS_QTYPE_CNAME:
540 __pcap_dns_name_info((uint8_t *)dns_h, &data[10], cname);
543 if (STC_DEBUG_LOG && STC_PCAP_LOG)
544 STC_LOGD("Name[%s] Type[%u:%s] Class[0x%04x:%s] "
545 "TTL[%u] Data length[%u] CName[%s]",
546 name, type, __pcap_dns_type_info(type),
547 class, __pcap_dns_class_info(class),
553 if (STC_DEBUG_LOG && STC_PCAP_LOG)
554 STC_LOGD("Name[%s] Type[%u:%s] Class[0x%04x:%s] "
555 "TTL[%u] Data length[%u]",
556 name, type, __pcap_dns_type_info(type),
557 class, __pcap_dns_class_info(class),
563 data += (length + 10);
567 static void __pcap_dns_info(const u_char *packet)
569 dns_t *dns_h = (dns_t *)(packet +
570 SIZE_ETHER_HEADER + SIZE_IP_HEADER + SIZE_UDP_HEADER);
572 if (STC_DEBUG_LOG && STC_PCAP_LOG)
573 STC_LOGD("Transaction ID[0x%x] Flags[0x%x] Questions[%u] "
574 "Answer RRs[%u] Authority RRs[%u] Additional RRs[%u]",
575 ntohs(dns_h->id), ntohs(dns_h->flags),
576 ntohs(dns_h->questions), ntohs(dns_h->answerRR),
577 ntohs(dns_h->authorityRR), ntohs(dns_h->additionalRR));
579 __pcap_dns_data_info(packet);
582 static const char *__pcap_icmp_code_info(u_int8_t type, u_int8_t code)
587 case ICMP_DEST_UNREACH:
589 case ICMP_NET_UNREACH:
590 info = "Network Unreachable";
592 case ICMP_HOST_UNREACH:
593 info = "Host Unreachable";
595 case ICMP_PROT_UNREACH:
596 info = "Protocol Unreachable";
598 case ICMP_PORT_UNREACH:
599 info = "Port Unreachable";
601 case ICMP_FRAG_NEEDED:
602 info = "Fragmentation Needed/DF set";
605 info = "Source Route failed";
607 case ICMP_NET_UNKNOWN:
609 case ICMP_HOST_UNKNOWN:
611 case ICMP_HOST_ISOLATED:
617 case ICMP_NET_UNR_TOS:
619 case ICMP_HOST_UNR_TOS:
621 case ICMP_PKT_FILTERED:
622 info = "Packet filtered";
624 case ICMP_PREC_VIOLATION:
625 info = "Precedence violation";
627 case ICMP_PREC_CUTOFF:
628 info = "Precedence cut off";
638 info = "Redirect Net";
640 case ICMP_REDIR_HOST:
641 info = "Redirect Host";
643 case ICMP_REDIR_NETTOS:
644 info = "Redirect Net for TOS";
646 case ICMP_REDIR_HOSTTOS:
647 info = "Redirect Host for TOS";
654 case ICMP_TIME_EXCEEDED:
657 info = "TTL count exceeded";
659 case ICMP_EXC_FRAGTIME:
660 info = "Fragment Reass time exceeded";
675 static const char *__pcap_icmp_type_info(u_int8_t type)
683 case ICMP_DEST_UNREACH:
684 info = "Destination Unreachable";
686 case ICMP_SOURCE_QUENCH:
687 info = "Source Quench";
693 info = "Echo Request";
695 case ICMP_TIME_EXCEEDED:
696 info = "Time Exceeded";
698 case ICMP_PARAMETERPROB:
699 info = "Parameter Problem";
702 info = "Timestamp Request";
704 case ICMP_TIMESTAMPREPLY:
705 info = "Timestamp Reply";
707 case ICMP_INFO_REQUEST:
708 info = "Information Request";
710 case ICMP_INFO_REPLY:
711 info = "Information Reply";
714 info = "Address Mask Request";
716 case ICMP_ADDRESSREPLY:
717 info = "Address Mask Reply";
727 static void __pcap_icmp_info(const u_char *packet)
729 icmp_t *icmp_h = (icmp_t *)(packet +
730 SIZE_ETHER_HEADER + SIZE_IP_HEADER);
732 if (STC_DEBUG_LOG && STC_PCAP_LOG)
733 STC_LOGD("Type[%u:%s] Code[%u:%s] Checksum[0x%x]",
734 icmp_h->type, __pcap_icmp_type_info(icmp_h->type),
735 icmp_h->code, __pcap_icmp_code_info(icmp_h->type, icmp_h->code),
736 ntohs(icmp_h->checksum));
739 static void __pcap_tcp_info(const u_char *packet)
741 tcp_t *tcp_h = (tcp_t *)(packet +
742 SIZE_ETHER_HEADER + SIZE_IP_HEADER);
743 u_int16_t source = ntohs(tcp_h->source);
744 u_int16_t dest = ntohs(tcp_h->dest);
746 if (STC_DEBUG_LOG && STC_PCAP_LOG)
747 STC_LOGD("Source[%u] Destination[%u] Sequence[%u] "
748 "Acknowledgment seq[%u] Window size[%u] ",
749 ntohs(tcp_h->source), ntohs(tcp_h->dest),
750 ntohl(tcp_h->seq), ntohl(tcp_h->ack_seq),
751 ntohs(tcp_h->window));
753 if (STC_DEBUG_LOG && STC_PCAP_LOG)
754 STC_LOGD("Checksum[0x%x] URG[%u] ACK[%u] PUSH[%u] "
755 "RST[%u] SYN[%u] FIN[%u]",
757 tcp_h->urg, tcp_h->ack, tcp_h->psh,
758 tcp_h->rst, tcp_h->syn, tcp_h->fin);
760 if (IS_SRC_OR_DST_PORT(PORT_DNS))
761 __pcap_dns_info(packet);
764 static void __pcap_udp_info(const u_char *packet)
766 udp_t *udp_h = (udp_t *)(packet
767 + SIZE_ETHER_HEADER + SIZE_IP_HEADER);
768 u_int16_t source = ntohs(udp_h->source);
769 u_int16_t dest = ntohs(udp_h->dest);
771 if (STC_DEBUG_LOG && STC_PCAP_LOG)
772 STC_LOGD("Source[%u] Destination[%u] Len[%u] Checksum[0x%x]",
773 source, dest, ntohs(udp_h->len), ntohs(udp_h->check));
775 if (IS_SRC_OR_DST_PORT(PORT_DNS))
776 __pcap_dns_info(packet);
777 else if (IS_SRC_OR_DST_PORT(PORT_BOOTP_C) ||
778 IS_SRC_OR_DST_PORT(PORT_BOOTP_S))
779 __pcap_bootp_info(packet);
780 else if (IS_SRC_OR_DST_PORT(PORT_NTP))
781 __pcap_ntp_info(packet);
784 static const char *__pcap_eth_type_info(u_int16_t type)
798 case ETHERTYPE_REVARP:
801 case ETHERTYPE_LOOPBACK:
812 static const char *__pcap_arp_opcode_info(u_int16_t opcode)
837 static void __pcap_arp_info(const u_char *packet)
839 arp_t *arp_h = (arp_t *)(packet + SIZE_ETHER_HEADER);
840 u_int8_t *sha = (u_int8_t *)(packet +
841 SIZE_ETHER_HEADER + SIZE_ARP_HEADER);
842 u_int8_t *spa = (u_int8_t *)(sha + arp_h->ar_hln);
843 u_int8_t *tha = (u_int8_t *)(spa + arp_h->ar_pln);
844 u_int8_t *tpa = (u_int8_t *)(tha + arp_h->ar_hln);
845 u_int16_t ar_op = ntohs(arp_h->ar_op);
846 char sma[BUFF_SIZE_HOST];
847 char sia[BUFF_SIZE_IP];
848 char tma[BUFF_SIZE_HOST];
849 char tia[BUFF_SIZE_IP];
853 ether_ntoa((const struct ether_addr *)sha),
856 ether_ntoa((const struct ether_addr *)tha),
859 inet_ntop(AF_INET, (struct in_addr *)spa, sia, BUFF_SIZE_IP);
860 inet_ntop(AF_INET, (struct in_addr *)tpa, tia, BUFF_SIZE_IP);
862 ar_pro = ntohs(arp_h->ar_pro);
864 if (STC_DEBUG_LOG && STC_PCAP_LOG)
865 STC_LOGD("HW type[%u] Protocol type[0x%04x:%s] "
866 "HW size[%u] Protocol size[%u] Opcode[%u:%s] ",
867 ntohs(arp_h->ar_hrd), ar_pro,
868 __pcap_eth_type_info(ar_pro),
869 arp_h->ar_hln, arp_h->ar_pln,
870 ar_op, __pcap_arp_opcode_info(ar_op));
872 if (STC_DEBUG_LOG && STC_PCAP_LOG)
873 STC_LOGD("Sender MAC[%s] Sender IP[%s] "
874 "Target MAC[%s] Target IP[%s]",
878 static const char *__pcap_ip_protocol_info(u_int8_t p)
912 static void __pcap_ipv6_info(const u_char *packet)
914 ip6_t *ip6_h = (ip6_t *)(packet + SIZE_ETHER_HEADER);
915 char ip6_src[BUFF_SIZE_IP6];
916 char ip6_dst[BUFF_SIZE_IP6];
918 inet_ntop(AF_INET6, &ip6_h->ip6_src, ip6_src, BUFF_SIZE_IP6);
919 inet_ntop(AF_INET6, &ip6_h->ip6_dst, ip6_dst, BUFF_SIZE_IP6);
921 if (STC_DEBUG_LOG && STC_PCAP_LOG)
922 STC_LOGD("Flow[0x%08x] Payload len[%u] Next hdr[%u:%s] "
923 "Hop limit[%u] Source[%s] Destination[%s]",
924 ntohl(ip6_h->ip6_flow), ntohs(ip6_h->ip6_plen),
925 ip6_h->ip6_nxt, __pcap_ip_protocol_info(ip6_h->ip6_nxt),
926 ip6_h->ip6_hlim, ip6_src, ip6_dst);
928 switch (ip6_h->ip6_nxt) {
948 static void __pcap_ip_info(const u_char *packet)
950 ip_t *ip_h = (ip_t *)(packet + SIZE_ETHER_HEADER);
951 char ip_src[BUFF_SIZE_IP];
952 char ip_dst[BUFF_SIZE_IP];
954 inet_ntop(AF_INET, &ip_h->ip_src, ip_src, BUFF_SIZE_IP);
955 inet_ntop(AF_INET, &ip_h->ip_dst, ip_dst, BUFF_SIZE_IP);
957 if (STC_DEBUG_LOG && STC_PCAP_LOG)
958 STC_LOGD("Header len[%u] TOS[0x%02x] Total len[%u] "
959 "ID[0x%04x] Flags[0x%02x] TTL[%u] Protocol[%u:%s] "
960 "Checksum[0x%04x] Source[%s] Destination[%s]",
961 ip_h->ip_hl << 2, ip_h->ip_tos,
962 ntohs(ip_h->ip_len), ntohs(ip_h->ip_id),
963 (ntohs(ip_h->ip_off) & 0xe000) >> 13,
964 ip_h->ip_ttl, ip_h->ip_p,
965 __pcap_ip_protocol_info(ip_h->ip_p),
966 ntohs(ip_h->ip_sum), ip_src, ip_dst);
968 switch (ip_h->ip_p) {
970 __pcap_icmp_info(packet);
973 __pcap_tcp_info(packet);
976 __pcap_udp_info(packet);
983 static void __pcap_eth_info(const u_char *packet)
985 eth_t *eth_h = (eth_t *)packet;
986 u_int8_t *eth_shost = eth_h->ether_shost;
987 u_int8_t *eth_dhost = eth_h->ether_dhost;
988 char shost[BUFF_SIZE_HOST];
989 char dhost[BUFF_SIZE_HOST];
990 u_int16_t ether_type;
993 ether_ntoa((const struct ether_addr *)eth_shost),
997 ether_ntoa((const struct ether_addr *)eth_dhost),
1000 ether_type = ntohs(eth_h->ether_type);
1002 if (STC_DEBUG_LOG && STC_PCAP_LOG)
1003 STC_LOGD("Source[%s] Destination[%s] Type[0x%04x:%s]",
1004 shost, dhost, ether_type, __pcap_eth_type_info(ether_type));
1007 static void __pcap_fm_info(const struct pcap_pkthdr *pkthdr)
1011 struct timeval ts = pkthdr->ts;
1012 __time_t tv_sec = ts.tv_sec;
1013 __suseconds_t tv_usec = tv_usec;
1015 if (g_pcap_start_fm == false) {
1017 g_pcap_start_fm = true;
1020 curr = ctime((const time_t *)&tv_sec);
1022 curr[len - 1] = '\0';
1024 if (STC_DEBUG_LOG && STC_PCAP_LOG)
1025 STC_LOGD("Arrival time[%s] Timeval[%.06f] "
1026 "Frame len[%u] Capture len[%u]", curr,
1027 (float)((tv_sec - g_pcap_tv.tv_sec) * 1000000 +
1028 (tv_usec - g_pcap_tv.tv_usec)) / 1000000,
1029 pkthdr->len, pkthdr->caplen);
1032 static void __pcap_handler(u_char *param,
1033 const struct pcap_pkthdr *pkthdr,
1034 const u_char *packet) {
1036 unsigned short eth_type;
1037 /* int len = pkthdr->len; */
1039 __pcap_fm_info(pkthdr);
1041 eth_h = (eth_t *)packet;
1042 __pcap_eth_info(packet);
1044 eth_type = ntohs(eth_h->ether_type);
1047 __pcap_ip_info(packet);
1048 /* __pcap_data_info(pcaket, len); */
1050 case ETHERTYPE_IPV6:
1051 __pcap_ipv6_info(packet);
1054 case ETHERTYPE_REVARP:
1055 __pcap_arp_info(packet);
1057 case ETHERTYPE_LOOPBACK:
1064 static gboolean __pcap_thread_source_func(gpointer data)
1066 char buf[MAX_IFACE_LENGTH];
1067 stc_pcap_data_s *lookup;
1068 stc_pcap_data_s *pcap_data = (stc_pcap_data_s *)data;
1070 g_pcap_tv.tv_sec = 0;
1071 g_pcap_tv.tv_usec = 0;
1072 g_pcap_start_fm = false;
1074 if (g_pcap_tables == NULL)
1077 snprintf(buf, sizeof(buf), "%s_%d",
1078 pcap_data->ifname, pcap_data->nflog_group);
1080 lookup = g_hash_table_lookup(g_pcap_tables, buf);
1082 STC_LOGE("pcap loop not found");
1086 g_hash_table_remove(g_pcap_tables, buf);
1087 STC_LOGD("Successfully removed pcap loop [%s]", buf);
1092 static gpointer __pcap_thread_func(gpointer data)
1094 __STC_LOG_FUNC_ENTER__;
1096 char errbuf[PCAP_ERRBUF_SIZE];
1097 pcap_if_t *alldevs = NULL;
1098 pcap_if_t *dev = NULL;
1100 GSource *source = NULL;
1101 GMainContext *context = NULL;
1102 stc_pcap_data_s *pcap_data = (stc_pcap_data_s *)data;
1104 if (pcap_findalldevs(&alldevs, errbuf) < 0 ||
1106 STC_LOGE("Failed to find all devs [%s]", errbuf);
1110 for (dev = alldevs; dev; dev = dev->next) {
1111 if (g_strcmp0(dev->name, pcap_data->ifname) == 0) {
1112 name = g_strdup(dev->name);
1117 pcap_freealldevs(alldevs);
1120 STC_LOGE("Failed to find dev [%s]", pcap_data->ifname);
1124 STC_LOGD("Pcap source dev [%s]", name);
1126 pcap_data->handle = pcap_open_live(name, 65535, 1, 1000, errbuf);
1127 if (pcap_data->handle == NULL) {
1128 STC_LOGE("Failed to open live [%s]", errbuf);
1132 STC_LOGD("Pcap loop start [%s]", name);
1133 pcap_loop(pcap_data->handle, 0, __pcap_handler, NULL);
1134 STC_LOGD("Pcap loop end [%s]", name);
1136 pcap_close(pcap_data->handle);
1137 STC_LOGD("Pcap closed [%s]", name);
1142 context = g_main_context_default();
1144 source = g_idle_source_new();
1146 g_source_set_callback(source,
1147 __pcap_thread_source_func, pcap_data, NULL);
1148 g_source_attach(source, context);
1150 g_source_unref(source);
1152 __STC_LOG_FUNC_EXIT__;
1156 static void __pcap_make_params(gpointer key, gpointer value,
1159 stc_pcap_data_s *data = (stc_pcap_data_s *)value;
1160 GVariantBuilder *builder = (GVariantBuilder *)user_data;
1161 GVariantBuilder sub_builder;
1163 g_variant_builder_init(&sub_builder, G_VARIANT_TYPE("a{sv}"));
1165 g_variant_builder_add(&sub_builder, "{sv}", PCAP_IFNAME,
1166 g_variant_new_string(data->ifname));
1168 g_variant_builder_add(&sub_builder, "{sv}", PCAP_NFLOG_GROUP,
1169 g_variant_new_uint32(data->nflog_group));
1171 g_variant_builder_add_value(builder, g_variant_builder_end(&sub_builder));
1174 int stc_plugin_pcap_initialize(void)
1176 __STC_LOG_FUNC_ENTER__;
1178 g_pcap_tables = g_hash_table_new_full(g_str_hash,
1179 g_str_equal, g_free, __pcap_data_free);
1181 __STC_LOG_FUNC_EXIT__;
1182 return STC_ERROR_NONE;
1185 int stc_plugin_pcap_deinitialize(void)
1187 __STC_LOG_FUNC_ENTER__;
1189 if (g_pcap_tables) {
1190 g_hash_table_destroy(g_pcap_tables);
1191 g_pcap_tables = NULL;
1194 __STC_LOG_FUNC_EXIT__;
1195 return STC_ERROR_NONE;
1198 int stc_plugin_pcap_lookup_dev(void)
1201 char errbuf[PCAP_ERRBUF_SIZE];
1203 dev = pcap_lookupdev(errbuf);
1205 STC_LOGE("Failed to look up dev [%s]", errbuf);
1206 return STC_ERROR_FAIL;
1209 STC_LOGD("Dev [%s]", dev);
1211 return STC_ERROR_NONE;
1214 int stc_plugin_pcap_lookup_net(void)
1217 char net[BUFF_SIZE_IP];
1218 char mask[BUFF_SIZE_IP];
1219 char errbuf[PCAP_ERRBUF_SIZE];
1224 dev = pcap_lookupdev(errbuf);
1226 STC_LOGE("Failed to look up dev [%s]", errbuf);
1227 return STC_ERROR_FAIL;
1230 STC_LOGD("Dev [%s]", dev);
1232 ret = pcap_lookupnet(dev, &netp, &maskp, errbuf);
1234 STC_LOGE("Failed to look up net [%s]", errbuf);
1235 return STC_ERROR_FAIL;
1238 inet_ntop(AF_INET, &netp, net, BUFF_SIZE_IP);
1239 STC_LOGD("Net [%s]", net);
1241 inet_ntop(AF_INET, &maskp, mask, BUFF_SIZE_IP);
1242 STC_LOGD("Mask [%s]", mask);
1244 return STC_ERROR_NONE;
1247 int stc_plugin_pcap_find_alldevs(void)
1249 char net[BUFF_SIZE_IP];
1250 char mask[BUFF_SIZE_IP];
1251 char errbuf[PCAP_ERRBUF_SIZE];
1252 pcap_if_t *alldevs = NULL;
1253 pcap_if_t *dev = NULL;
1257 if (pcap_findalldevs(&alldevs, errbuf) < 0 ||
1259 STC_LOGE("Failed to find all devs [%s]", errbuf);
1260 return STC_ERROR_FAIL;
1263 for (dev = alldevs; dev; dev = dev->next) {
1264 STC_LOGD("Dev [%s]", dev->name);
1266 if (dev->description)
1267 STC_LOGD("Decs [%s]", dev->description);
1269 if (pcap_lookupnet(dev->name, &netp, &maskp, errbuf) == -1) {
1270 STC_LOGE("Failed to look up net [%s]", errbuf);
1274 inet_ntop(AF_INET, &netp, net, BUFF_SIZE_IP);
1275 STC_LOGD("Net [%s]", net);
1277 inet_ntop(AF_INET, &maskp, mask, BUFF_SIZE_IP);
1278 STC_LOGD("Mask [%s]", mask);
1281 pcap_freealldevs(alldevs);
1283 return STC_ERROR_NONE;
1286 int stc_plugin_pcap_register_loop(const char *ifname,
1289 stc_pcap_data_s *data;
1290 stc_pcap_data_s *lookup;
1291 char buf[MAX_IFACE_LENGTH];
1293 ret_value_msg_if(g_pcap_tables == NULL,
1295 "pcap tables is not initialized!");
1297 ret_value_msg_if(ifname == NULL,
1299 "Invalid parameter [ifname]");
1301 snprintf(buf, sizeof(buf), "%s_%d", ifname, nflog_group);
1303 lookup = g_hash_table_lookup(g_pcap_tables, buf);
1305 STC_LOGD("pcap loop already present");
1306 return STC_ERROR_ALREADY_DATA;
1309 data = MALLOC0(stc_pcap_data_s, 1);
1311 STC_LOGE("data allocation failed");
1312 return STC_ERROR_OUT_OF_MEMORY;
1315 data->ifname = g_strdup(ifname);
1316 data->nflog_group = nflog_group;
1317 data->thread = g_thread_new(buf, __pcap_thread_func, data);
1319 g_hash_table_insert(g_pcap_tables, g_strdup(buf), data);
1320 STC_LOGD("Successfully added pcap loop [%s]", buf);
1322 return STC_ERROR_NONE;
1325 int stc_plugin_pcap_unregister_loop(const char *ifname,
1328 stc_pcap_data_s *lookup;
1329 char buf[MAX_IFACE_LENGTH];
1331 ret_value_msg_if(g_pcap_tables == NULL,
1333 "pcap tables is not initialized!");
1335 ret_value_msg_if(ifname == NULL,
1337 "Invalid parameter [ifname]");
1339 snprintf(buf, sizeof(buf), "%s_%d", ifname, nflog_group);
1341 lookup = g_hash_table_lookup(g_pcap_tables, buf);
1343 STC_LOGE("pcap loop not found");
1344 __STC_LOG_FUNC_EXIT__;
1345 return STC_ERROR_NO_DATA;
1348 pcap_breakloop(lookup->handle);
1349 STC_LOGD("Successfully removed pcap loop [%s]", buf);
1351 return STC_ERROR_NONE;
1354 int stc_plugin_pcap_get_all_loop(GVariantBuilder *builder)
1356 ret_value_msg_if(g_pcap_tables == NULL,
1358 "pcap tables is not initialized!");
1360 g_hash_table_foreach(g_pcap_tables, __pcap_make_params, builder);
1362 return STC_ERROR_NONE;
1365 API stc_plugin_pcap_s stc_plugin_pcap = {
1366 .initialize_plugin =
1367 stc_plugin_pcap_initialize,
1368 .deinitialize_plugin =
1369 stc_plugin_pcap_deinitialize,
1371 stc_plugin_pcap_lookup_dev,
1373 stc_plugin_pcap_lookup_net,
1375 stc_plugin_pcap_find_alldevs,
1377 stc_plugin_pcap_register_loop,
1379 stc_plugin_pcap_unregister_loop,
1381 stc_plugin_pcap_get_all_loop