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"
18 #include "stc-plugin-pcap-internal.h"
20 #define ENCAPTYPE_ETHERNET 1
21 #define ENCAPTYPE_NFLOG 141
23 #define PCAP_IFNAME "ifname"
24 #define PCAP_NFLOG_GROUP "nflog_group"
25 #define PCAP_DEV_NAME "dev"
26 #define PCAP_DEV_DECS "decs"
27 #define PCAP_DEV_NET "net"
28 #define PCAP_DEV_MASK "mask"
30 #define NFLOG_IFNAME "nflog"
33 static GHashTable *g_pcap_tables = NULL;
34 static bool g_pcap_start_fm = false;
35 static struct timeval g_pcap_tv = { 0, };
37 static void __pcap_data_free(gpointer value)
39 stc_pcap_data_s *data = (stc_pcap_data_s *)value;
41 g_thread_unref(data->thread);
49 static void __pcap_data_info(const u_char *packet, int len)
53 data = g_string_sized_new(len);
58 g_string_append_printf(data, "%02x", *(packet++));
60 STC_LOGD("[%s]", g_string_free(data, FALSE));
64 static void __pcap_ntp_time_info(uint32_t s, char *time)
69 uint32_t sec = ntohl(s);
72 seconds = sec - NTP_JAN_1970;
73 curr = ctime(&seconds);
77 snprintf(time, len, "%s", curr);
79 snprintf(time, 10, "00:00:00");
83 static void __pcap_ntp_refid_info(ntp_t *ntp_h, char *refid)
85 switch (ntp_h->stratum) {
86 case NTP_STRATUM_UNSPECIFIED:
87 snprintf(refid, BUFF_SIZE_ID, "%s", "(unspec)");
89 case NTP_STRATUM_PRIM_REF:
90 snprintf(refid, BUFF_SIZE_ID, "%s", "(prim_ref)");
92 case NTP_STRATUM_INFO_QUERY:
93 snprintf(refid, BUFF_SIZE_ID, "%s INFO_QEURY",
94 inet_ntoa(*((struct in_addr *)&ntp_h->refid)));
96 case NTP_STRATUM_INFO_REPLY:
97 snprintf(refid, BUFF_SIZE_ID, "%s INFO_REPLY",
98 inet_ntoa(*((struct in_addr *)&ntp_h->refid)));
101 snprintf(refid, BUFF_SIZE_ID, "%s",
102 inet_ntoa(*((struct in_addr *)&ntp_h->refid)));
107 static uint16_t __pcap_ntp_fraction_info(uint16_t f)
112 ff = ntohs(f) / 65536.0;
113 fraction = (uint16_t)(ff * 1000000.0);
118 static void __pcap_ntp_info(const u_char **packet, uint32_t *pktlen)
120 ntp_t *ntp_h = (ntp_t *)*packet;
121 char refid[BUFF_SIZE_ID];
122 char reftime[BUFF_SIZE_TIME];
123 char orgtime[BUFF_SIZE_TIME];
124 char rectime[BUFF_SIZE_TIME];
125 char xmttime[BUFF_SIZE_TIME];
127 __pcap_ntp_refid_info(ntp_h, refid);
128 __pcap_ntp_time_info(ntp_h->reftime.second, reftime);
129 __pcap_ntp_time_info(ntp_h->orgtime.second, orgtime);
130 __pcap_ntp_time_info(ntp_h->rectime.second, rectime);
131 __pcap_ntp_time_info(ntp_h->xmttime.second, xmttime);
135 STC_LOGD("Flags[0x%02x] Stratum[%u] Poll[%u:%us] Precision[%u] "
136 "Root delay[%u.%06us] Root dispersion[%u.%06us] Ref ID[%s]",
137 ntp_h->flags, ntp_h->stratum, ntp_h->poll,
138 ntp_h->precision, 1 << ntp_h->precision,
139 ntohs(ntp_h->rootdelay.second),
140 __pcap_ntp_fraction_info(ntp_h->rootdelay.fraction),
141 ntohs(ntp_h->rootdisp.second),
142 __pcap_ntp_fraction_info(ntp_h->rootdisp.fraction),
144 STC_LOGD("Reference[%s] Origin[%s] Receive[%s] Transmit[%s]",
145 reftime, orgtime, rectime, xmttime);
150 static const char *__pcap_dhcp_client_id_info(uint8_t data)
155 case DHCP_CLIENT_ID_ETHERNET:
158 case DHCP_CLIENT_ID_IEEE802:
159 info = "IEEE 802 Networks";
161 case DHCP_CLIENT_ID_ARCNET:
164 case DHCP_CLIENT_ID_LOCALTALK:
167 case DHCP_CLIENT_ID_LOCALNET:
170 case DHCP_CLIENT_ID_SMDS:
173 case DHCP_CLIENT_ID_FRAMERELAY:
174 info = "Frame Relay";
176 case DHCP_CLIENT_ID_ATM1:
177 info = "ATM(Async Transfer Mode)";
179 case DHCP_CLIENT_ID_HDLC:
182 case DHCP_CLIENT_ID_FIBRECHANNEL:
183 info = "Fibre Channel";
185 case DHCP_CLIENT_ID_ATM2:
186 info = "ATM(Async Transfer Mode)";
188 case DHCP_CLIENT_ID_SERIALLINE:
189 info = "Serial Line";
199 static const char *__pcap_dhcp_msg_type_info(uint8_t type)
204 case DHCP_MSG_TYPE_DISCOVER:
207 case DHCP_MSG_TYPE_OFFER:
210 case DHCP_MSG_TYPE_REQUEST:
213 case DHCP_MSG_TYPE_DECLINE:
216 case DHCP_MSG_TYPE_ACK:
219 case DHCP_MSG_TYPE_NAK:
222 case DHCP_MSG_TYPE_RELEASE:
225 case DHCP_MSG_TYPE_INFORM:
236 static void __pcap_bootp_magic_info(uint32_t magic,
237 uint8_t *moption, u_int16_t len)
239 if (ntohl(magic) == BOOTP_MAGIC_DHCP) {
240 char buf[BOOTP_MOPTION_LEN];
241 uint8_t *opt = moption;
244 STC_LOGD("Magic cookie[DHCP]");
247 uint8_t tag = opt[0];
248 uint8_t length = opt[1];
249 uint8_t *data = &opt[2];
250 char addr[BUFF_SIZE_IP];
251 char host[BUFF_SIZE_HOST];
254 case DHCP_TAG_SUBNET_MASK:
255 inet_ntop(AF_INET, (struct in_addr *)data,
258 STC_LOGD("Subnet mask[%s]", addr);
260 case DHCP_TAG_ROUTER:
261 inet_ntop(AF_INET, (struct in_addr *)data,
264 STC_LOGD("Router[%s]", addr);
267 inet_ntop(AF_INET, (struct in_addr *)data,
270 STC_LOGD("Domain name server[%s]", addr);
272 case DHCP_TAG_HOST_NAME:
273 snprintf(buf, ((length < BOOTP_MOPTION_LEN) ?
274 (length + 1) : BOOTP_MOPTION_LEN), "%s", (char *)data);
276 STC_LOGD("Host name[%s]", buf);
278 case DHCP_TAG_REQUESTED_IP:
279 inet_ntop(AF_INET, (struct in_addr *)data,
282 STC_LOGD("Requested IP[%s]", addr);
284 case DHCP_TAG_IP_LEASE_TIME:
286 STC_LOGD("IP address lease time[%us]",
287 ntohl(*(uint32_t *)data));
289 case DHCP_TAG_MSG_TYPE:
291 STC_LOGD("DHCP message type[%u:%s]", *data,
292 __pcap_dhcp_msg_type_info(*data));
294 case DHCP_TAG_SERVER_ID:
295 inet_ntop(AF_INET, (struct in_addr *)data,
298 STC_LOGD("DHCP server identifier[%s]", addr);
300 case DHCP_TAG_MSG_SIZE:
302 STC_LOGD("Maximum DHCP message size[%u]",
303 ntohs(*(uint16_t *)data));
305 case DHCP_TAG_CLIENT_ID:
307 STC_LOGD("Client identifier HW type[0x%02x:%s]", *data,
308 __pcap_dhcp_client_id_info(*data));
309 if (*data == DHCP_CLIENT_ID_ETHERNET) {
311 ether_ntoa((const struct ether_addr *)&data[1]),
314 STC_LOGD("Client identifier MAC[%s]", host);
323 STC_LOGD("Unknown[%u]", tag);
333 static const char *__pcap_bootp_op_info(uint8_t op)
352 static void __pcap_bootp_info(const u_char **packet, u_int16_t len)
354 bootp_t *bootp_h = (bootp_t *)*packet;
355 char ciaddr[BUFF_SIZE_IP];
356 char yiaddr[BUFF_SIZE_IP];
357 char siaddr[BUFF_SIZE_IP];
358 char giaddr[BUFF_SIZE_IP];
359 char chaddr[BUFF_SIZE_HOST];
361 inet_ntop(AF_INET, &bootp_h->ciaddr, ciaddr, BUFF_SIZE_IP);
362 inet_ntop(AF_INET, &bootp_h->yiaddr, yiaddr, BUFF_SIZE_IP);
363 inet_ntop(AF_INET, &bootp_h->siaddr, siaddr, BUFF_SIZE_IP);
364 inet_ntop(AF_INET, &bootp_h->giaddr, giaddr, BUFF_SIZE_IP);
367 ether_ntoa((const struct ether_addr *)bootp_h->chaddr),
372 STC_LOGD("Message type[%u:%s] HW type[0x%02x] HW len[%u] Hops[%u] "
373 "Transaction ID[0x%08x] Seconds elapsed[%u] Flags[0x%04x]",
374 bootp_h->op, __pcap_bootp_op_info(bootp_h->op),
375 bootp_h->htype, bootp_h->hlen, bootp_h->hops,
376 ntohl(bootp_h->xid), ntohs(bootp_h->secs), ntohs(bootp_h->flags));
377 STC_LOGD("Client[%s] Your(client)[%s] Next server[%s] "
378 "Relay agent[%s] Client MAC[%s]",
379 ciaddr, yiaddr, siaddr, giaddr, chaddr);
382 __pcap_bootp_magic_info(bootp_h->magic, bootp_h->moption, len);
388 static char *__pcap_dns_type_info(uint16_t type)
396 case DNS_QTYPE_CNAME:
410 static char *__pcap_dns_class_info(uint16_t class)
418 case DNS_QCLASS_CHAOS:
435 static uint8_t * __pcap_dns_name_info(uint8_t *dns_h,
436 uint8_t *data, u_char *name)
439 u_char *dname = name;
446 sec = (uint8_t *)dns_h +
447 (htons(*(uint16_t *)sec) & 0x3FFF);
455 if (dname + *sec >= name + BUFF_SIZE_NAME) {
460 memcpy(dname, sec + 1, *sec);
473 return (uint8_t *)nxt;
476 static void __pcap_dns_data_info(const u_char **packet, dns_t *dns_h, uint32_t *pktlen)
478 uint8_t *data = (uint8_t *)*packet;
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];
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]);
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];
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],
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);
546 STC_LOGD("Name[%s] Type[%u:%s] Class[0x%04x:%s] "
547 "TTL[%u] Data length[%u] CName[%s]",
548 name, type, __pcap_dns_type_info(type),
549 class, __pcap_dns_class_info(class),
556 STC_LOGD("Name[%s] Type[%u:%s] Class[0x%04x:%s] "
557 "TTL[%u] Data length[%u]",
558 name, type, __pcap_dns_type_info(type),
559 class, __pcap_dns_class_info(class),
565 data += (length + 10);
569 static void __pcap_dns_info(const u_char **packet, uint32_t *pktlen)
571 dns_t *dns_h = (dns_t *)*packet;
575 STC_LOGD("Transaction ID[0x%x] Flags[0x%x] Questions[%u] "
576 "Answer RRs[%u] Authority RRs[%u] Additional RRs[%u]",
577 ntohs(dns_h->id), ntohs(dns_h->flags),
578 ntohs(dns_h->questions), ntohs(dns_h->answerRR),
579 ntohs(dns_h->authorityRR), ntohs(dns_h->additionalRR));
582 *packet += SIZE_DNS_HEADER;
583 *pktlen -= SIZE_DNS_HEADER;
585 __pcap_dns_data_info(packet, dns_h, pktlen);
591 static const char *__pcap_icmp_code_info(u_int8_t type, u_int8_t code)
596 case ICMP_DEST_UNREACH:
598 case ICMP_NET_UNREACH:
599 info = "Network Unreachable";
601 case ICMP_HOST_UNREACH:
602 info = "Host Unreachable";
604 case ICMP_PROT_UNREACH:
605 info = "Protocol Unreachable";
607 case ICMP_PORT_UNREACH:
608 info = "Port Unreachable";
610 case ICMP_FRAG_NEEDED:
611 info = "Fragmentation Needed/DF set";
614 info = "Source Route failed";
616 case ICMP_NET_UNKNOWN:
618 case ICMP_HOST_UNKNOWN:
620 case ICMP_HOST_ISOLATED:
626 case ICMP_NET_UNR_TOS:
628 case ICMP_HOST_UNR_TOS:
630 case ICMP_PKT_FILTERED:
631 info = "Packet filtered";
633 case ICMP_PREC_VIOLATION:
634 info = "Precedence violation";
636 case ICMP_PREC_CUTOFF:
637 info = "Precedence cut off";
647 info = "Redirect Net";
649 case ICMP_REDIR_HOST:
650 info = "Redirect Host";
652 case ICMP_REDIR_NETTOS:
653 info = "Redirect Net for TOS";
655 case ICMP_REDIR_HOSTTOS:
656 info = "Redirect Host for TOS";
663 case ICMP_TIME_EXCEEDED:
666 info = "TTL count exceeded";
668 case ICMP_EXC_FRAGTIME:
669 info = "Fragment Reass time exceeded";
684 static const char *__pcap_icmp_type_info(u_int8_t type)
692 case ICMP_DEST_UNREACH:
693 info = "Destination Unreachable";
695 case ICMP_SOURCE_QUENCH:
696 info = "Source Quench";
702 info = "Echo Request";
704 case ICMP_TIME_EXCEEDED:
705 info = "Time Exceeded";
707 case ICMP_PARAMETERPROB:
708 info = "Parameter Problem";
711 info = "Timestamp Request";
713 case ICMP_TIMESTAMPREPLY:
714 info = "Timestamp Reply";
716 case ICMP_INFO_REQUEST:
717 info = "Information Request";
719 case ICMP_INFO_REPLY:
720 info = "Information Reply";
723 info = "Address Mask Request";
725 case ICMP_ADDRESSREPLY:
726 info = "Address Mask Reply";
736 static void __pcap_icmp_info(const u_char **packet, uint32_t *pktlen)
738 icmp_t *icmp_h = (icmp_t *)*packet;
741 STC_LOGD("Type[%u:%s] Code[%u:%s] Checksum[0x%x]",
742 icmp_h->type, __pcap_icmp_type_info(icmp_h->type),
743 icmp_h->code, __pcap_icmp_code_info(icmp_h->type, icmp_h->code),
744 ntohs(icmp_h->checksum));
746 *packet += SIZE_ICMP_HEADER;
747 *pktlen -= SIZE_ICMP_HEADER;
750 static void __pcap_http_info(const u_char **packet, uint32_t *pktlen)
754 u_char *value_pos = NULL;
755 gchar *value_str = NULL;
758 value = g_string_sized_new(value_len);
760 value_pos = (u_char *)*packet;
762 g_string_append_printf(value, "%c", *(value_pos++));
763 value_str = g_string_free(value, FALSE);
767 STC_LOGD(HR_SINGLE "\n%s", value_str);
774 static void __pcap_tcp_info(const u_char **packet, uint32_t *pktlen)
776 tcp_t *tcp_h = (tcp_t *)*packet;
777 u_int16_t source = ntohs(tcp_h->source);
778 u_int16_t dest = ntohs(tcp_h->dest);
781 STC_LOGD("Source[%u] Destination[%u] Sequence[%u] "
782 "Acknowledgment seq[%u] Window size[%u] ",
783 ntohs(tcp_h->source), ntohs(tcp_h->dest),
784 ntohl(tcp_h->seq), ntohl(tcp_h->ack_seq),
785 ntohs(tcp_h->window));
788 STC_LOGD("Checksum[0x%x] URG[%u] ACK[%u] PUSH[%u] "
789 "RST[%u] SYN[%u] FIN[%u]",
791 tcp_h->urg, tcp_h->ack, tcp_h->psh,
792 tcp_h->rst, tcp_h->syn, tcp_h->fin);
794 *packet += (tcp_h->th_off * 4);
795 *pktlen -= (tcp_h->th_off * 4);
798 if (IS_SRC_OR_DST_PORT(PORT_DNS))
799 __pcap_dns_info(packet, pktlen);
800 else if (IS_SRC_OR_DST_PORT(PORT_HTTP) ||
801 IS_SRC_OR_DST_PORT(PORT_HTTP_ALT))
802 __pcap_http_info(packet, pktlen);
806 static void __pcap_udp_info(const u_char **packet, uint32_t *pktlen)
808 udp_t *udp_h = (udp_t *)*packet;
809 u_int16_t source = ntohs(udp_h->source);
810 u_int16_t dest = ntohs(udp_h->dest);
811 u_int16_t len = ntohs(udp_h->len);
814 STC_LOGD("Source[%u] Destination[%u] Len[%u] Checksum[0x%x]",
815 source, dest, len, ntohs(udp_h->check));
817 *packet += SIZE_UDP_HEADER;
818 *pktlen -= SIZE_UDP_HEADER;
821 if (IS_SRC_OR_DST_PORT(PORT_DNS))
822 __pcap_dns_info(packet, pktlen);
823 else if (IS_SRC_OR_DST_PORT(PORT_BOOTP_C) ||
824 IS_SRC_OR_DST_PORT(PORT_BOOTP_S))
825 __pcap_bootp_info(packet, len);
826 else if (IS_SRC_OR_DST_PORT(PORT_NTP))
827 __pcap_ntp_info(packet, pktlen);
831 static const char *__pcap_eth_type_info(u_int16_t type)
845 case ETHERTYPE_REVARP:
848 case ETHERTYPE_LOOPBACK:
859 static void __pcap_eapol_info(const u_char **packet, uint32_t *pktlen)
863 static const char *__pcap_arp_opcode_info(u_int16_t opcode)
888 static void __pcap_arp_info(const u_char **packet, uint32_t *pktlen)
890 arp_t *arp_h = (arp_t *)*packet;
891 u_int8_t *sha = (u_int8_t *)(*packet + SIZE_ARP_HEADER);
892 u_int8_t *spa = (u_int8_t *)(sha + arp_h->ar_hln);
893 u_int8_t *tha = (u_int8_t *)(spa + arp_h->ar_pln);
894 u_int8_t *tpa = (u_int8_t *)(tha + arp_h->ar_hln);
895 u_int16_t ar_op = ntohs(arp_h->ar_op);
896 char sma[BUFF_SIZE_HOST];
897 char sia[BUFF_SIZE_IP];
898 char tma[BUFF_SIZE_HOST];
899 char tia[BUFF_SIZE_IP];
903 ether_ntoa((const struct ether_addr *)sha),
906 ether_ntoa((const struct ether_addr *)tha),
909 inet_ntop(AF_INET, (struct in_addr *)spa, sia, BUFF_SIZE_IP);
910 inet_ntop(AF_INET, (struct in_addr *)tpa, tia, BUFF_SIZE_IP);
912 ar_pro = ntohs(arp_h->ar_pro);
915 STC_LOGD("HW type[%u] Protocol type[0x%04x:%s] "
916 "HW size[%u] Protocol size[%u] Opcode[%u:%s] ",
917 ntohs(arp_h->ar_hrd), ar_pro,
918 __pcap_eth_type_info(ar_pro),
919 arp_h->ar_hln, arp_h->ar_pln,
920 ar_op, __pcap_arp_opcode_info(ar_op));
923 STC_LOGD("Sender MAC[%s] Sender IP[%s] "
924 "Target MAC[%s] Target IP[%s]",
927 *packet += SIZE_ARP_HEADER;
928 *pktlen -= SIZE_ARP_HEADER;
931 static const char *__pcap_ip_protocol_info(u_int8_t p)
965 static void __pcap_ipv6_info(const u_char **packet, uint32_t *pktlen)
967 ip6_t *ip6_h = (ip6_t *)*packet;
968 char ip6_src[BUFF_SIZE_IP6];
969 char ip6_dst[BUFF_SIZE_IP6];
971 inet_ntop(AF_INET6, &ip6_h->ip6_src, ip6_src, BUFF_SIZE_IP6);
972 inet_ntop(AF_INET6, &ip6_h->ip6_dst, ip6_dst, BUFF_SIZE_IP6);
975 STC_LOGD("Flow[0x%08x] Payload len[%u] Next hdr[%u:%s] "
976 "Hop limit[%u] Source[%s] Destination[%s]",
977 ntohl(ip6_h->ip6_flow), ntohs(ip6_h->ip6_plen),
978 ip6_h->ip6_nxt, __pcap_ip_protocol_info(ip6_h->ip6_nxt),
979 ip6_h->ip6_hlim, ip6_src, ip6_dst);
981 *packet += SIZE_IP6_HEADER;
982 *pktlen -= SIZE_IP6_HEADER;
984 switch (ip6_h->ip6_nxt) {
986 __pcap_tcp_info(packet, pktlen);
989 __pcap_udp_info(packet, pktlen);
992 __pcap_icmp_info(packet, pktlen);
999 static void __pcap_ip_info(const u_char **packet, uint32_t *pktlen)
1001 ip_t *ip_h = (ip_t *)*packet;
1002 char ip_src[BUFF_SIZE_IP];
1003 char ip_dst[BUFF_SIZE_IP];
1005 inet_ntop(AF_INET, &ip_h->ip_src, ip_src, BUFF_SIZE_IP);
1006 inet_ntop(AF_INET, &ip_h->ip_dst, ip_dst, BUFF_SIZE_IP);
1009 STC_LOGD("Header len[%u] TOS[0x%02x] Total len[%u] "
1010 "ID[0x%04x] Flags[0x%02x] TTL[%u] Protocol[%u:%s] "
1011 "Checksum[0x%04x] Source[%s] Destination[%s]",
1012 ip_h->ip_hl << 2, ip_h->ip_tos,
1013 ntohs(ip_h->ip_len), ntohs(ip_h->ip_id),
1014 (ntohs(ip_h->ip_off) & 0xe000) >> 13,
1015 ip_h->ip_ttl, ip_h->ip_p,
1016 __pcap_ip_protocol_info(ip_h->ip_p),
1017 ntohs(ip_h->ip_sum), ip_src, ip_dst);
1019 *packet += SIZE_IP_HEADER;
1020 *pktlen -= SIZE_IP_HEADER;
1022 switch (ip_h->ip_p) {
1024 __pcap_icmp_info(packet, pktlen);
1027 __pcap_tcp_info(packet, pktlen);
1030 __pcap_udp_info(packet, pktlen);
1037 static void __pcap_eth_info(const u_char **packet, uint32_t *pktlen)
1039 eth_t *eth_h = (eth_t *)*packet;
1040 u_int8_t *eth_shost = eth_h->ether_shost;
1041 u_int8_t *eth_dhost = eth_h->ether_dhost;
1042 char shost[BUFF_SIZE_HOST];
1043 char dhost[BUFF_SIZE_HOST];
1044 u_int16_t ether_type;
1047 ether_ntoa((const struct ether_addr *)eth_shost),
1051 ether_ntoa((const struct ether_addr *)eth_dhost),
1054 ether_type = ntohs(eth_h->ether_type);
1057 STC_LOGD("Source[%s] Destination[%s] Type[0x%04x:%s]",
1058 shost, dhost, ether_type, __pcap_eth_type_info(ether_type));
1060 *packet += SIZE_ETHER_HEADER;
1061 *pktlen -= SIZE_ETHER_HEADER;
1064 static const char *__pcap_family_info(u_int8_t family)
1083 static const char *__pcap_tlv_type_info(u_int16_t type)
1088 case NFULA_PACKET_HDR:
1089 info = "NFULA_PACKET_HDR";
1092 info = "NFULA_MARK";
1094 case NFULA_TIMESTAMP:
1095 info = "NFULA_TIMESTAMP";
1097 case NFULA_IFINDEX_INDEV:
1098 info = "NFULA_IFINDEX_INDEV";
1100 case NFULA_IFINDEX_OUTDEV:
1101 info = "NFULA_IFINDEX_OUTDEV";
1103 case NFULA_IFINDEX_PHYSINDEV:
1104 info = "NFULA_IFINDEX_PHYSINDEV";
1106 case NFULA_IFINDEX_PHYSOUTDEV:
1107 info = "NFULA_IFINDEX_PHYSOUTDEV";
1110 info = "NFULA_HWADDR";
1113 info = "NFULA_PAYLOAD";
1116 info = "NFULA_PREFIX";
1124 case NFULA_SEQ_GLOBAL:
1125 info = "NFULA_SEQ_GLOBAL";
1131 info = "NFULA_HWTYPE";
1133 case NFULA_HWHEADER:
1134 info = "NFULA_HWHEADER";
1137 info = "NFULA_HWLEN";
1147 static void __pcap_nflog_tlv_info(const u_char **packet,
1151 u_int16_t tlv_length;
1154 u_int16_t value_len;
1155 u_char *value_pos = NULL;
1156 gchar *value_str = NULL;
1158 *pktlen -= SIZE_NFLOG_HDR;
1160 while (*pktlen > 0) {
1161 if (*pktlen < SIZE_NFLOG_TLV)
1164 tlv_h = (nflog_tlv_t *)*packet;
1165 tlv_length = tlv_h->tlv_length;
1166 if (tlv_length % 4 != 0)
1167 tlv_length += 4 - tlv_length % 4;
1168 tlv_type = tlv_h->tlv_type;
1170 if (tlv_length < SIZE_NFLOG_TLV)
1173 if (*pktlen < tlv_length)
1177 if (tlv_type != NFULA_PAYLOAD) {
1178 nflog_hwaddr_t *hwaddr;
1179 nflog_timestamp_s *timestamp;
1180 char host[BUFF_SIZE_HOST];
1187 hwaddr = (nflog_hwaddr_t *)((u_char *)tlv_h + SIZE_NFLOG_TLV);
1189 ether_ntoa((const struct ether_addr *)hwaddr->hw_addr),
1191 STC_LOGD("Type[%s:%u] Length[%u] Hwaddr[%s]",
1192 __pcap_tlv_type_info(tlv_type), tlv_type,
1193 tlv_h->tlv_length, host);
1195 case NFULA_TIMESTAMP:
1196 timestamp = (nflog_timestamp_s *)((u_char *)tlv_h + SIZE_NFLOG_TLV);
1197 sec = ntohl(timestamp->ts[1]);
1198 time = ctime((const time_t *)&sec);
1200 time[len - 1] = '\0';
1202 STC_LOGD("Type[%s:%u] Length[%u] Timestamp[%s]",
1203 __pcap_tlv_type_info(tlv_type), tlv_type,
1204 tlv_h->tlv_length, time);
1207 value_len = tlv_h->tlv_length - SIZE_NFLOG_TLV;
1208 value = g_string_sized_new(value_len);
1210 value_pos = (u_char *)tlv_h + SIZE_NFLOG_TLV;
1212 g_string_append_printf(value, "%c", *(value_pos++));
1213 value_str = g_string_free(value, FALSE);
1216 STC_LOGD("Type[%s:%u] Length[%u] Prefix[%s]",
1217 __pcap_tlv_type_info(tlv_type), tlv_type,
1218 tlv_h->tlv_length, value_str);
1223 value_len = tlv_h->tlv_length - SIZE_NFLOG_TLV;
1224 value = g_string_sized_new(value_len);
1226 value_pos = (u_char *)tlv_h + SIZE_NFLOG_TLV;
1228 g_string_append_printf(value, "%02x", *(value_pos++));
1229 value_str = g_string_free(value, FALSE);
1232 STC_LOGD("Type[%s:%u] Length[%u] Value[%s]",
1233 __pcap_tlv_type_info(tlv_type), tlv_type,
1234 tlv_h->tlv_length, value_str);
1240 STC_LOGD("Type[%s:%u] Length[%u]",
1241 __pcap_tlv_type_info(tlv_type),
1242 tlv_type, tlv_h->tlv_length);
1246 if (tlv_type == NFULA_PAYLOAD) {
1247 *packet += SIZE_NFLOG_TLV;
1248 *pktlen -= SIZE_NFLOG_TLV;
1252 *packet += tlv_length;
1253 *pktlen -= tlv_length;
1257 static void __pcap_nflog_hdr_info(const u_char **packet, uint32_t *pktlen)
1259 nflog_hdr_t *hdr_h = (nflog_hdr_t *)*packet;
1260 u_int8_t family = hdr_h->nflog_family;
1261 u_int8_t version = hdr_h->nflog_version;
1262 u_int16_t resource_id = ntohs(hdr_h->nflog_rid);
1265 STC_LOGD("Family[%s:%u] Version[%u] Resource id[%u]",
1266 __pcap_family_info(family), family, version, resource_id);
1268 *packet += SIZE_NFLOG_HDR;
1269 *pktlen -= SIZE_NFLOG_HDR;
1272 static void __pcap_fm_info(const struct pcap_pkthdr *pkthdr)
1276 struct timeval ts = pkthdr->ts;
1277 __time_t tv_sec = ts.tv_sec;
1278 __suseconds_t tv_usec = ts.tv_usec;
1280 if (g_pcap_start_fm == false) {
1282 g_pcap_start_fm = true;
1285 curr = ctime((const time_t *)&tv_sec);
1287 curr[len - 1] = '\0';
1290 STC_LOGD("Arrival time[%s] Timeval[%.06f] "
1291 "Frame len[%u] Capture len[%u]", curr,
1292 (float)((tv_sec - g_pcap_tv.tv_sec) * 1000000 +
1293 (tv_usec - g_pcap_tv.tv_usec)) / 1000000,
1294 pkthdr->len, pkthdr->caplen);
1297 static void __pcap_handler(u_char *param,
1298 const struct pcap_pkthdr *pkthdr,
1299 const u_char *packet) {
1300 uint32_t pktlen = pkthdr->len;
1301 stc_pcap_data_s *pcap_data = (stc_pcap_data_s *)param;
1304 nflog_hdr_t *nflog_h;
1305 uint8_t nflog_family;
1307 STC_LOGD(HR_DOUBLE);
1309 __pcap_fm_info(pkthdr);
1311 switch (pcap_data->encap_type) {
1312 case ENCAPTYPE_ETHERNET:
1313 eth_h = (eth_t *)packet;
1314 eth_type = ntohs(eth_h->ether_type);
1316 __pcap_eth_info(&packet, &pktlen);
1320 __pcap_ip_info(&packet, &pktlen);
1321 /* __pcap_data_info(pcaket, pktlen); */
1323 case ETHERTYPE_IPV6:
1324 __pcap_ipv6_info(&packet, &pktlen);
1327 case ETHERTYPE_REVARP:
1328 __pcap_arp_info(&packet, &pktlen);
1330 case ETHERTYPE_LOOPBACK:
1332 case ETHERTYPE_EAPOL:
1333 __pcap_eapol_info(&packet, &pktlen);
1339 case ENCAPTYPE_NFLOG:
1340 nflog_h = (nflog_hdr_t *)packet;
1341 nflog_family = nflog_h->nflog_family;
1343 __pcap_nflog_hdr_info(&packet, &pktlen);
1344 __pcap_nflog_tlv_info(&packet, &pktlen);
1346 switch (nflog_family) {
1348 __pcap_ip_info(&packet, &pktlen);
1351 __pcap_ipv6_info(&packet, &pktlen);
1361 STC_LOGD(HR_DOUBLE);
1364 static gboolean __pcap_thread_source_func(gpointer data)
1366 char buf[MAX_IFACE_LENGTH];
1367 stc_pcap_data_s *lookup;
1368 stc_pcap_data_s *pcap_data = (stc_pcap_data_s *)data;
1370 g_pcap_tv.tv_sec = 0;
1371 g_pcap_tv.tv_usec = 0;
1372 g_pcap_start_fm = false;
1374 if (g_pcap_tables == NULL)
1377 snprintf(buf, sizeof(buf), "%s:%d",
1378 pcap_data->ifname, pcap_data->nflog_group);
1380 lookup = g_hash_table_lookup(g_pcap_tables, buf);
1382 STC_LOGE("pcap loop not found");
1386 g_hash_table_remove(g_pcap_tables, buf);
1387 STC_LOGD("Successfully removed pcap loop [%s]", buf);
1392 static gpointer __pcap_thread_func(gpointer data)
1394 __STC_LOG_FUNC_ENTER__;
1396 char errbuf[PCAP_ERRBUF_SIZE];
1397 pcap_if_t *alldevs = NULL;
1398 pcap_if_t *dev = NULL;
1400 GSource *source = NULL;
1401 GMainContext *context = NULL;
1402 stc_pcap_data_s *pcap_data = (stc_pcap_data_s *)data;
1404 if (pcap_findalldevs(&alldevs, errbuf) < 0 ||
1406 STC_LOGE("Failed to find all devs [%s]", errbuf);
1410 for (dev = alldevs; dev; dev = dev->next) {
1411 if (g_strcmp0(dev->name, pcap_data->ifname) == 0) {
1412 if (g_strcmp0(dev->name, NFLOG_IFNAME) == 0) {
1413 name = g_strdup(pcap_data->nfname);
1414 pcap_data->encap_type = ENCAPTYPE_NFLOG;
1416 name = g_strdup(pcap_data->ifname);
1417 pcap_data->encap_type = ENCAPTYPE_ETHERNET;
1423 pcap_freealldevs(alldevs);
1426 STC_LOGE("Failed to find dev [%s]", pcap_data->ifname);
1430 STC_LOGD("Pcap source dev [%s]", name);
1432 pcap_data->handle = pcap_open_live(name, 65535, 1, 1000, errbuf);
1433 if (pcap_data->handle == NULL) {
1434 STC_LOGE("Failed to open live [%s]", errbuf);
1438 STC_LOGD("Pcap open live [%p]", pcap_data->handle);
1440 STC_LOGD("Pcap loop start [%s]", name);
1441 pcap_loop(pcap_data->handle, 0, __pcap_handler, (u_char *)pcap_data);
1442 STC_LOGD("Pcap loop end [%s]", name);
1444 STC_LOGD("Pcap before closing [%p]", pcap_data->handle);
1445 pcap_close(pcap_data->handle);
1450 context = g_main_context_default();
1452 source = g_idle_source_new();
1454 g_source_set_callback(source,
1455 __pcap_thread_source_func, pcap_data, NULL);
1456 g_source_attach(source, context);
1458 g_source_unref(source);
1460 __STC_LOG_FUNC_EXIT__;
1464 static void __pcap_make_params(gpointer key, gpointer value,
1467 stc_pcap_data_s *data = (stc_pcap_data_s *)value;
1468 GVariantBuilder *builder = (GVariantBuilder *)user_data;
1469 GVariantBuilder sub_builder;
1471 g_variant_builder_init(&sub_builder, G_VARIANT_TYPE("a{sv}"));
1473 g_variant_builder_add(&sub_builder, "{sv}", PCAP_IFNAME,
1474 g_variant_new_string(data->ifname));
1476 g_variant_builder_add(&sub_builder, "{sv}", PCAP_NFLOG_GROUP,
1477 g_variant_new_uint32(data->nflog_group));
1479 g_variant_builder_add_value(builder, g_variant_builder_end(&sub_builder));
1482 int stc_plugin_pcap_initialize(void)
1484 __STC_LOG_FUNC_ENTER__;
1486 g_pcap_tables = g_hash_table_new_full(g_str_hash,
1487 g_str_equal, g_free, __pcap_data_free);
1489 __STC_LOG_FUNC_EXIT__;
1490 return STC_ERROR_NONE;
1493 int stc_plugin_pcap_deinitialize(void)
1495 __STC_LOG_FUNC_ENTER__;
1497 if (g_pcap_tables) {
1498 g_hash_table_destroy(g_pcap_tables);
1499 g_pcap_tables = NULL;
1502 __STC_LOG_FUNC_EXIT__;
1503 return STC_ERROR_NONE;
1506 int stc_plugin_pcap_lookup_dev(void)
1509 char errbuf[PCAP_ERRBUF_SIZE];
1511 dev = pcap_lookupdev(errbuf);
1513 STC_LOGE("Failed to look up dev [%s]", errbuf);
1514 return STC_ERROR_FAIL;
1517 STC_LOGD("Dev [%s]", dev);
1519 return STC_ERROR_NONE;
1522 int stc_plugin_pcap_lookup_net(void)
1525 char net[BUFF_SIZE_IP];
1526 char mask[BUFF_SIZE_IP];
1527 char errbuf[PCAP_ERRBUF_SIZE];
1532 dev = pcap_lookupdev(errbuf);
1534 STC_LOGE("Failed to look up dev [%s]", errbuf);
1535 return STC_ERROR_FAIL;
1538 STC_LOGD("Dev [%s]", dev);
1540 ret = pcap_lookupnet(dev, &netp, &maskp, errbuf);
1542 STC_LOGE("Failed to look up net [%s]", errbuf);
1543 return STC_ERROR_FAIL;
1546 inet_ntop(AF_INET, &netp, net, BUFF_SIZE_IP);
1547 STC_LOGD("Net [%s]", net);
1549 inet_ntop(AF_INET, &maskp, mask, BUFF_SIZE_IP);
1550 STC_LOGD("Mask [%s]", mask);
1552 return STC_ERROR_NONE;
1555 int stc_plugin_pcap_find_all_devs(GVariantBuilder *builder)
1557 char net[BUFF_SIZE_IP];
1558 char mask[BUFF_SIZE_IP];
1559 char errbuf[PCAP_ERRBUF_SIZE];
1560 pcap_if_t *alldevs = NULL;
1561 pcap_if_t *dev = NULL;
1565 if (pcap_findalldevs(&alldevs, errbuf) < 0 ||
1567 STC_LOGE("Failed to find all devs [%s]", errbuf);
1568 return STC_ERROR_FAIL;
1571 for (dev = alldevs; dev; dev = dev->next) {
1572 GVariantBuilder sub_builder;
1574 g_variant_builder_init(&sub_builder, G_VARIANT_TYPE("a{sv}"));
1576 STC_LOGD("Dev [%s]", dev->name);
1577 g_variant_builder_add(&sub_builder, "{sv}", PCAP_DEV_NAME,
1578 g_variant_new_string(dev->name));
1580 if (dev->description) {
1581 STC_LOGD("Decs [%s]", dev->description);
1582 g_variant_builder_add(&sub_builder, "{sv}", PCAP_DEV_DECS,
1583 g_variant_new_string(dev->description));
1586 if (pcap_lookupnet(dev->name, &netp, &maskp, errbuf) == -1) {
1587 STC_LOGE("Failed to look up net [%s]", errbuf);
1588 g_variant_builder_add_value(builder, g_variant_builder_end(&sub_builder));
1592 inet_ntop(AF_INET, &netp, net, BUFF_SIZE_IP);
1593 STC_LOGD("Net [%s]", net);
1594 g_variant_builder_add(&sub_builder, "{sv}", PCAP_DEV_NET,
1595 g_variant_new_string(net));
1597 inet_ntop(AF_INET, &maskp, mask, BUFF_SIZE_IP);
1598 STC_LOGD("Mask [%s]", mask);
1599 g_variant_builder_add(&sub_builder, "{sv}", PCAP_DEV_MASK,
1600 g_variant_new_string(mask));
1602 g_variant_builder_add_value(builder, g_variant_builder_end(&sub_builder));
1605 pcap_freealldevs(alldevs);
1607 return STC_ERROR_NONE;
1610 int stc_plugin_pcap_register_loop(const char *ifname,
1613 stc_pcap_data_s *data;
1614 stc_pcap_data_s *lookup;
1615 char buf[MAX_IFACE_LENGTH];
1617 ret_value_msg_if(g_pcap_tables == NULL,
1619 "pcap tables is not initialized!");
1621 ret_value_msg_if(ifname == NULL,
1623 "Invalid parameter [ifname]");
1625 snprintf(buf, sizeof(buf), "%s:%d", ifname, nflog_group);
1627 lookup = g_hash_table_lookup(g_pcap_tables, buf);
1629 STC_LOGD("pcap loop already present");
1630 return STC_ERROR_ALREADY_DATA;
1633 data = MALLOC0(stc_pcap_data_s, 1);
1635 STC_LOGE("data allocation failed");
1636 return STC_ERROR_OUT_OF_MEMORY;
1639 data->ifname = g_strdup(ifname);
1640 data->nfname = g_strdup(buf);
1641 data->nflog_group = nflog_group;
1642 data->thread = g_thread_new(buf, __pcap_thread_func, data);
1644 g_hash_table_insert(g_pcap_tables, g_strdup(buf), data);
1645 STC_LOGD("Successfully added pcap loop [%s]", buf);
1647 return STC_ERROR_NONE;
1650 int stc_plugin_pcap_unregister_loop(const char *ifname,
1653 stc_pcap_data_s *lookup;
1654 char buf[MAX_IFACE_LENGTH];
1656 ret_value_msg_if(g_pcap_tables == NULL,
1658 "pcap tables is not initialized!");
1660 ret_value_msg_if(ifname == NULL,
1662 "Invalid parameter [ifname]");
1664 snprintf(buf, sizeof(buf), "%s:%d", ifname, nflog_group);
1666 lookup = g_hash_table_lookup(g_pcap_tables, buf);
1668 STC_LOGE("pcap loop not found");
1669 __STC_LOG_FUNC_EXIT__;
1670 return STC_ERROR_NO_DATA;
1673 pcap_breakloop(lookup->handle);
1674 STC_LOGD("Successfully removed pcap loop [%s]", buf);
1676 return STC_ERROR_NONE;
1679 int stc_plugin_pcap_get_all_loop(GVariantBuilder *builder)
1681 ret_value_msg_if(g_pcap_tables == NULL,
1683 "pcap tables is not initialized!");
1685 g_hash_table_foreach(g_pcap_tables, __pcap_make_params, builder);
1687 return STC_ERROR_NONE;
1690 API stc_plugin_pcap_s stc_plugin_pcap = {
1691 .initialize_plugin =
1692 stc_plugin_pcap_initialize,
1693 .deinitialize_plugin =
1694 stc_plugin_pcap_deinitialize,
1696 stc_plugin_pcap_lookup_dev,
1698 stc_plugin_pcap_lookup_net,
1700 stc_plugin_pcap_find_all_devs,
1702 stc_plugin_pcap_register_loop,
1704 stc_plugin_pcap_unregister_loop,
1706 stc_plugin_pcap_get_all_loop