Add http infomation for pcap and checking length of packet
[platform/core/connectivity/stc-manager.git] / plugin / pcap / stc-plugin-pcap.c
1 /*
2  * Copyright (c) 2017 Samsung Electronics Co., Ltd.
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include "stc-plugin-pcap.h"
18
19 #define ENCAPTYPE_ETHERNET  1
20 #define ENCAPTYPE_NFLOG     141
21
22 #define PCAP_IFNAME         "ifname"
23 #define PCAP_NFLOG_GROUP    "nflog_group"
24 #define PCAP_DEV_NAME       "dev"
25 #define PCAP_DEV_DECS       "decs"
26 #define PCAP_DEV_NET        "net"
27 #define PCAP_DEV_MASK       "mask"
28
29 #define NFLOG_IFNAME        "nflog"
30
31 //LCOV_EXCL_START
32 static GHashTable *g_pcap_tables = NULL;
33 static bool g_pcap_start_fm = false;
34 static struct timeval g_pcap_tv = { 0, };
35
36 static void __pcap_data_free(gpointer value)
37 {
38         stc_pcap_data_s *data = (stc_pcap_data_s *)value;
39
40         g_thread_unref(data->thread);
41
42         FREE(data->ifname);
43         FREE(data->nfname);
44         FREE(data);
45 }
46
47 /*
48 static void __pcap_data_info(const u_char *packet, int len)
49 {
50         GString *data;
51
52         data = g_string_sized_new(len);
53         if (data == NULL)
54                 return;
55
56         while(len--)
57                 g_string_append_printf(data, "%02x", *(packet++));
58
59         STC_LOGD("[%s]", g_string_free(data, FALSE));
60 }
61 */
62
63 static void __pcap_ntp_time_info(uint32_t s, char *time)
64 {
65         time_t seconds;
66         char *curr = NULL;
67         int len = 0;
68         uint32_t sec = ntohl(s);
69
70         if (sec) {
71                 seconds = sec - NTP_JAN_1970;
72                 curr = ctime(&seconds);
73                 len = strlen(curr);
74                 curr[len - 1] = '\0';
75
76                 snprintf(time, len, "%s", curr);
77         } else {
78                 snprintf(time, 10, "00:00:00");
79         }
80 }
81
82 static void __pcap_ntp_refid_info(ntp_t *ntp_h, char *refid)
83 {
84         switch (ntp_h->stratum) {
85         case NTP_STRATUM_UNSPECIFIED:
86                 snprintf(refid, BUFF_SIZE_ID, "%s", "(unspec)");
87                 break;
88         case NTP_STRATUM_PRIM_REF:
89                 snprintf(refid, BUFF_SIZE_ID, "%s", "(prim_ref)");
90                 break;
91         case NTP_STRATUM_INFO_QUERY:
92                 snprintf(refid, BUFF_SIZE_ID, "%s INFO_QEURY",
93                         inet_ntoa(*((struct in_addr *)&ntp_h->refid)));
94                 break;
95         case NTP_STRATUM_INFO_REPLY:
96                 snprintf(refid, BUFF_SIZE_ID, "%s INFO_REPLY",
97                         inet_ntoa(*((struct in_addr *)&ntp_h->refid)));
98                 break;
99         default:
100                 snprintf(refid, BUFF_SIZE_ID, "%s",
101                         inet_ntoa(*((struct in_addr *)&ntp_h->refid)));
102                 break;
103         }
104 }
105
106 static uint16_t __pcap_ntp_fraction_info(uint16_t f)
107 {
108         uint16_t fraction;
109         double ff;
110
111         ff = ntohs(f) / 65536.0;
112         fraction = (uint16_t)(ff * 1000000.0);
113
114         return fraction;
115 }
116
117 static void __pcap_ntp_info(const u_char **packet, uint32_t *pktlen)
118 {
119         ntp_t *ntp_h = (ntp_t *)*packet;
120         char refid[BUFF_SIZE_ID];
121         char reftime[BUFF_SIZE_TIME];
122         char orgtime[BUFF_SIZE_TIME];
123         char rectime[BUFF_SIZE_TIME];
124         char xmttime[BUFF_SIZE_TIME];
125
126         __pcap_ntp_refid_info(ntp_h, refid);
127         __pcap_ntp_time_info(ntp_h->reftime.second, reftime);
128         __pcap_ntp_time_info(ntp_h->orgtime.second, orgtime);
129         __pcap_ntp_time_info(ntp_h->rectime.second, rectime);
130         __pcap_ntp_time_info(ntp_h->xmttime.second, xmttime);
131
132         if (STC_PCAP_LOG) {
133                 STC_LOGD(HR_SINGLE);
134                 STC_LOGD("Flags[0x%02x] Stratum[%u] Poll[%u:%us] Precision[%u] "
135                         "Root delay[%u.%06us] Root dispersion[%u.%06us] Ref ID[%s]",
136                         ntp_h->flags, ntp_h->stratum, ntp_h->poll,
137                         ntp_h->precision, 1 << ntp_h->precision,
138                         ntohs(ntp_h->rootdelay.second),
139                         __pcap_ntp_fraction_info(ntp_h->rootdelay.fraction),
140                         ntohs(ntp_h->rootdisp.second),
141                         __pcap_ntp_fraction_info(ntp_h->rootdisp.fraction),
142                         refid);
143                 STC_LOGD("Reference[%s] Origin[%s] Receive[%s] Transmit[%s]",
144                         reftime, orgtime, rectime, xmttime);
145                 STC_LOGD(HR_SINGLE);
146         }
147 }
148
149 static const char *__pcap_dhcp_client_id_info(uint8_t data)
150 {
151         char *info = NULL;
152
153         switch (data) {
154         case DHCP_CLIENT_ID_ETHERNET:
155                 info = "Ethernet";
156                 break;
157         case DHCP_CLIENT_ID_IEEE802:
158                 info = "IEEE 802 Networks";
159                 break;
160         case DHCP_CLIENT_ID_ARCNET:
161                 info = "ARCNET";
162                 break;
163         case DHCP_CLIENT_ID_LOCALTALK:
164                 info = "LocalTalk";
165                 break;
166         case DHCP_CLIENT_ID_LOCALNET:
167                 info = "LocalNet";
168                 break;
169         case DHCP_CLIENT_ID_SMDS:
170                 info = "SMDS";
171                 break;
172         case DHCP_CLIENT_ID_FRAMERELAY:
173                 info = "Frame Relay";
174                 break;
175         case DHCP_CLIENT_ID_ATM1:
176                 info = "ATM(Async Transfer Mode)";
177                 break;
178         case DHCP_CLIENT_ID_HDLC:
179                 info = "HDLC";
180                 break;
181         case DHCP_CLIENT_ID_FIBRECHANNEL:
182                 info = "Fibre Channel";
183                 break;
184         case DHCP_CLIENT_ID_ATM2:
185                 info = "ATM(Async Transfer Mode)";
186                 break;
187         case DHCP_CLIENT_ID_SERIALLINE:
188                 info = "Serial Line";
189                 break;
190         default:
191                 info = "Unknown";
192                 break;
193         }
194
195         return info;
196 }
197
198 static const char *__pcap_dhcp_msg_type_info(uint8_t type)
199 {
200         char *info = NULL;
201
202         switch (type) {
203         case DHCP_MSG_TYPE_DISCOVER:
204                 info = "Discover";
205                 break;
206         case DHCP_MSG_TYPE_OFFER:
207                 info = "Offer";
208                 break;
209         case DHCP_MSG_TYPE_REQUEST:
210                 info = "Request";
211                 break;
212         case DHCP_MSG_TYPE_DECLINE:
213                 info = "Decline";
214                 break;
215         case DHCP_MSG_TYPE_ACK:
216                 info = "ACK";
217                 break;
218         case DHCP_MSG_TYPE_NAK:
219                 info = "NAK";
220                 break;
221         case DHCP_MSG_TYPE_RELEASE:
222                 info = "Release";
223                 break;
224         case DHCP_MSG_TYPE_INFORM:
225                 info = "Inform";
226                 break;
227         default:
228                 info = "Unknown";
229                 break;
230         }
231
232         return info;
233 }
234
235 static void __pcap_bootp_magic_info(uint32_t magic,
236                                         uint8_t *moption, u_int16_t len)
237 {
238         if (ntohl(magic) == BOOTP_MAGIC_DHCP) {
239                 char buf[BOOTP_MOPTION_LEN];
240                 uint8_t *opt = moption;
241
242                 if (STC_PCAP_LOG)
243                         STC_LOGD("Magic cookie[DHCP]");
244
245                 while (len > 0) {
246                         uint8_t tag = opt[0];
247                         uint8_t length = opt[1];
248                         uint8_t *data = &opt[2];
249                         char addr[BUFF_SIZE_IP];
250                         char host[BUFF_SIZE_HOST];
251
252                         switch (tag) {
253                         case DHCP_TAG_SUBNET_MASK:
254                                 inet_ntop(AF_INET, (struct in_addr *)data,
255                                         addr, BUFF_SIZE_IP);
256                                 if (STC_PCAP_LOG)
257                                         STC_LOGD("Subnet mask[%s]", addr);
258                                 break;
259                         case DHCP_TAG_ROUTER:
260                                 inet_ntop(AF_INET, (struct in_addr *)data,
261                                         addr, BUFF_SIZE_IP);
262                                 if (STC_PCAP_LOG)
263                                         STC_LOGD("Router[%s]", addr);
264                                 break;
265                         case DHCP_TAG_DNS:
266                                 inet_ntop(AF_INET, (struct in_addr *)data,
267                                         addr, BUFF_SIZE_IP);
268                                 if (STC_PCAP_LOG)
269                                         STC_LOGD("Domain name server[%s]", addr);
270                                 break;
271                         case DHCP_TAG_HOST_NAME:
272                                 snprintf(buf, ((length < BOOTP_MOPTION_LEN) ?
273                                                 (length + 1) : BOOTP_MOPTION_LEN), "%s", (char *)data);
274                                 if (STC_PCAP_LOG)
275                                         STC_LOGD("Host name[%s]", buf);
276                                 break;
277                         case DHCP_TAG_REQUESTED_IP:
278                                 inet_ntop(AF_INET, (struct in_addr *)data,
279                                         addr, BUFF_SIZE_IP);
280                                 if (STC_PCAP_LOG)
281                                         STC_LOGD("Requested IP[%s]", addr);
282                                 break;
283                         case DHCP_TAG_IP_LEASE_TIME:
284                                 if (STC_PCAP_LOG)
285                                         STC_LOGD("IP address lease time[%us]",
286                                                 ntohl(*(uint32_t *)data));
287                                 break;
288                         case DHCP_TAG_MSG_TYPE:
289                                 if (STC_PCAP_LOG)
290                                         STC_LOGD("DHCP message type[%u:%s]", *data,
291                                                 __pcap_dhcp_msg_type_info(*data));
292                                 break;
293                         case DHCP_TAG_SERVER_ID:
294                                 inet_ntop(AF_INET, (struct in_addr *)data,
295                                         addr, BUFF_SIZE_IP);
296                                 if (STC_PCAP_LOG)
297                                         STC_LOGD("DHCP server identifier[%s]", addr);
298                                 break;
299                         case DHCP_TAG_MSG_SIZE:
300                                 if (STC_PCAP_LOG)
301                                         STC_LOGD("Maximum DHCP message size[%u]",
302                                                 ntohs(*(uint16_t *)data));
303                                 break;
304                         case DHCP_TAG_CLIENT_ID:
305                                 if (STC_PCAP_LOG)
306                                         STC_LOGD("Client identifier HW type[0x%02x:%s]", *data,
307                                                 __pcap_dhcp_client_id_info(*data));
308                                 if (*data == DHCP_CLIENT_ID_ETHERNET) {
309                                         g_strlcpy(host,
310                                                 ether_ntoa((const struct ether_addr *)&data[1]),
311                                                 sizeof(host));
312                                         if (STC_PCAP_LOG)
313                                                 STC_LOGD("Client identifier MAC[%s]", host);
314                                 }
315                                 break;
316                         case DHCP_TAG_END:
317                                 if (STC_PCAP_LOG)
318                                         STC_LOGD("End");
319                                 return;
320                         default:
321                                 if (STC_PCAP_LOG)
322                                         STC_LOGD("Unknown[%u]", tag);
323                                 break;
324                         }
325
326                         opt += (2 + length);
327                         len -= (2 + length);
328                 }
329         }
330 }
331
332 static const char *__pcap_bootp_op_info(uint8_t op)
333 {
334         char *info = NULL;
335
336         switch (op) {
337         case BOOTP_REQUEST:
338                 info = "Request";
339                 break;
340         case BOOTP_REPLY:
341                 info = "Reply";
342                 break;
343         default:
344                 info = "Unknown";
345                 break;
346         }
347
348         return info;
349 }
350
351 static void __pcap_bootp_info(const u_char **packet, u_int16_t len)
352 {
353         bootp_t *bootp_h = (bootp_t *)*packet;
354         char ciaddr[BUFF_SIZE_IP];
355         char yiaddr[BUFF_SIZE_IP];
356         char siaddr[BUFF_SIZE_IP];
357         char giaddr[BUFF_SIZE_IP];
358         char chaddr[BUFF_SIZE_HOST];
359
360         inet_ntop(AF_INET, &bootp_h->ciaddr, ciaddr, BUFF_SIZE_IP);
361         inet_ntop(AF_INET, &bootp_h->yiaddr, yiaddr, BUFF_SIZE_IP);
362         inet_ntop(AF_INET, &bootp_h->siaddr, siaddr, BUFF_SIZE_IP);
363         inet_ntop(AF_INET, &bootp_h->giaddr, giaddr, BUFF_SIZE_IP);
364
365         g_strlcpy(chaddr,
366                 ether_ntoa((const struct ether_addr *)bootp_h->chaddr),
367                 sizeof(chaddr));
368
369         if (STC_PCAP_LOG) {
370                 STC_LOGD(HR_SINGLE);
371                 STC_LOGD("Message type[%u:%s] HW type[0x%02x] HW len[%u] Hops[%u] "
372                         "Transaction ID[0x%08x] Seconds elapsed[%u] Flags[0x%04x]",
373                         bootp_h->op, __pcap_bootp_op_info(bootp_h->op),
374                         bootp_h->htype, bootp_h->hlen, bootp_h->hops,
375                         ntohl(bootp_h->xid), ntohs(bootp_h->secs), ntohs(bootp_h->flags));
376                 STC_LOGD("Client[%s] Your(client)[%s] Next server[%s] "
377                         "Relay agent[%s] Client MAC[%s]",
378                         ciaddr, yiaddr, siaddr, giaddr, chaddr);
379         }
380
381         __pcap_bootp_magic_info(bootp_h->magic, bootp_h->moption, len);
382
383         if (STC_PCAP_LOG)
384                 STC_LOGD(HR_SINGLE);
385 }
386
387 static char *__pcap_dns_type_info(uint16_t type)
388 {
389         char *info = NULL;
390
391         switch (type) {
392         case DNS_QTYPE_A:
393                 info = "A";
394                 break;
395         case DNS_QTYPE_CNAME:
396                 info = "CNAME";
397                 break;
398         case DNS_QTYPE_AAAA:
399                 info = "AAAA";
400                 break;
401         default:
402                 info = "Unknown";
403                 break;
404         }
405
406         return info;
407 }
408
409 static char *__pcap_dns_class_info(uint16_t class)
410 {
411         char *info = NULL;
412
413         switch (class) {
414         case DNS_QCLASS_IN:
415                 info = "IN";
416                 break;
417         case DNS_QCLASS_CHAOS:
418                 info = "CHAOS";
419                 break;
420         case DNS_QCLASS_HS:
421                 info = "HS";
422                 break;
423         case DNS_QCLASS_ANY:
424                 info = "ANY";
425                 break;
426         default:
427                 info = "Unknown";
428                 break;
429         }
430
431         return info;
432 }
433
434 static uint8_t * __pcap_dns_name_info(uint8_t *dns_h,
435                                 uint8_t *data, u_char *name)
436 {
437         uint8_t *sec = data;
438         u_char *dname = name;
439         uint8_t *nxt = NULL;
440
441         *name = '\0';
442         while (1) {
443                 if ((*sec & 0xC0)) {
444                         nxt = sec + 2;
445                         sec = (uint8_t *)dns_h +
446                                 (htons(*(uint16_t *)sec) & 0x3FFF);
447                 } else {
448                         if (*sec == 0) {
449                                 *dname = '\0';
450                                 sec += 1;
451                                 break;
452                         }
453
454                         if (dname + *sec >= name + BUFF_SIZE_NAME) {
455                                 *name = '\0';
456                                 return NULL;
457                         }
458
459                         memcpy(dname, sec + 1, *sec);
460                         dname += *sec;
461                         sec += *sec + 1;
462                         *dname = '.';
463                         dname++;
464                 }
465         }
466
467         *(--dname) = '\0';
468
469         if (nxt == NULL)
470                 nxt = sec;
471
472         return (uint8_t *)nxt;
473 }
474
475 static void __pcap_dns_data_info(const u_char **packet, dns_t *dns_h, uint32_t *pktlen)
476 {
477         uint8_t *data = (uint8_t *)*packet;
478         uint16_t qdcount = ntohs(dns_h->questions);
479         uint16_t ancount = ntohs(dns_h->answerRR);
480         int i = 0;
481
482         for (i = 0; i < qdcount; ++i) {
483                 u_char name[BUFF_SIZE_NAME];
484                 uint16_t type;
485                 uint16_t class;
486
487                 if (i == 0) {
488                         if (STC_PCAP_LOG)
489                                 STC_LOGD("[Queries]");
490                 }
491
492                 data = __pcap_dns_name_info((uint8_t *)dns_h, data, name);
493                 if (data == NULL)
494                         return;
495
496                 type = ntohs(*(uint16_t *)&data[0]);
497                 class = ntohs(*(uint16_t *)&data[2]);
498
499                 if (STC_PCAP_LOG)
500                         STC_LOGD("Name[%s] Type[%u:%s] Class[0x%04x:%s]",
501                                 name, type, __pcap_dns_type_info(type),
502                                 class, __pcap_dns_class_info(class));
503
504                 data += 4;
505         }
506
507         for (i = 0; i < ancount; ++i) {
508                 u_char name[BUFF_SIZE_NAME];
509                 u_char cname[BUFF_SIZE_NAME];
510                 uint16_t type;
511                 uint16_t class;
512                 uint32_t ttl;
513                 uint16_t length;
514                 char ip[BUFF_SIZE_IP];
515
516                 if (i == 0) {
517                         if (STC_PCAP_LOG)
518                                 STC_LOGD("[Answers]");
519                 }
520
521                 data = __pcap_dns_name_info((uint8_t *)dns_h, data, name);
522                 if (data == NULL)
523                         return;
524
525                 type = ntohs(*(uint16_t *)&data[0]);
526                 class = ntohs(*(uint16_t *)&data[2]);
527                 ttl = ntohl(*(uint32_t *)&data[4]);
528                 length = ntohs(*(uint16_t *)&data[8]);
529
530                 if (class == DNS_QCLASS_IN) {
531                         switch (type) {
532                         case DNS_QTYPE_A:
533                                 inet_ntop(AF_INET, (struct in_addr *)&data[10],
534                                         ip, BUFF_SIZE_IP);
535                                 if (STC_PCAP_LOG)
536                                         STC_LOGD("Name[%s] Type[%u:%s] Class[0x%04x:%s] "
537                                                 "TTL[%u] Data length[%u] Address[%s]",
538                                                 name, type, __pcap_dns_type_info(type),
539                                                 class, __pcap_dns_class_info(class),
540                                                 ttl, length, ip);
541                                 break;
542                         case DNS_QTYPE_CNAME:
543                                 __pcap_dns_name_info((uint8_t *)dns_h, &data[10], cname);
544                                 if (data == NULL)
545                                         return;
546                                 if (STC_PCAP_LOG)
547                                         STC_LOGD("Name[%s] Type[%u:%s] Class[0x%04x:%s] "
548                                                 "TTL[%u] Data length[%u] CName[%s]",
549                                                 name, type, __pcap_dns_type_info(type),
550                                                 class, __pcap_dns_class_info(class),
551                                                 ttl, length, cname);
552                                 break;
553                         case DNS_QTYPE_AAAA:
554                                 break;
555                         default:
556                                 if (STC_PCAP_LOG)
557                                         STC_LOGD("Name[%s] Type[%u:%s] Class[0x%04x:%s] "
558                                                 "TTL[%u] Data length[%u]",
559                                                 name, type, __pcap_dns_type_info(type),
560                                                 class, __pcap_dns_class_info(class),
561                                                 ttl, length);
562                                 break;
563                         }
564                 }
565
566                 data += (length + 10);
567         }
568 }
569
570 static void __pcap_dns_info(const u_char **packet, uint32_t *pktlen)
571 {
572         dns_t *dns_h = (dns_t *)*packet;
573
574         if (STC_PCAP_LOG) {
575                 STC_LOGD(HR_SINGLE);
576                 STC_LOGD("Transaction ID[0x%x] Flags[0x%x] Questions[%u] "
577                         "Answer RRs[%u] Authority RRs[%u] Additional RRs[%u]",
578                         ntohs(dns_h->id), ntohs(dns_h->flags),
579                         ntohs(dns_h->questions), ntohs(dns_h->answerRR),
580                         ntohs(dns_h->authorityRR), ntohs(dns_h->additionalRR));
581         }
582
583         *packet += SIZE_DNS_HEADER;
584         *pktlen -= SIZE_DNS_HEADER;
585
586         __pcap_dns_data_info(packet, dns_h, pktlen);
587
588         if (STC_PCAP_LOG)
589                 STC_LOGD(HR_SINGLE);
590 }
591
592 static const char *__pcap_icmp_code_info(u_int8_t type, u_int8_t code)
593 {
594         char *info = NULL;
595
596         switch (type) {
597         case ICMP_DEST_UNREACH:
598                 switch (code) {
599                 case ICMP_NET_UNREACH:
600                         info = "Network Unreachable";
601                         break;
602                 case ICMP_HOST_UNREACH:
603                         info = "Host Unreachable";
604                         break;
605                 case ICMP_PROT_UNREACH:
606                         info = "Protocol Unreachable";
607                         break;
608                 case ICMP_PORT_UNREACH:
609                         info = "Port Unreachable";
610                         break;
611                 case ICMP_FRAG_NEEDED:
612                         info = "Fragmentation Needed/DF set";
613                         break;
614                 case ICMP_SR_FAILED:
615                         info = "Source Route failed";
616                         break;
617                 case ICMP_NET_UNKNOWN:
618                         break;
619                 case ICMP_HOST_UNKNOWN:
620                         break;
621                 case ICMP_HOST_ISOLATED:
622                         break;
623                 case ICMP_NET_ANO:
624                         break;
625                 case ICMP_HOST_ANO:
626                         break;
627                 case ICMP_NET_UNR_TOS:
628                         break;
629                 case ICMP_HOST_UNR_TOS:
630                         break;
631                 case ICMP_PKT_FILTERED:
632                         info = "Packet filtered";
633                         break;
634                 case ICMP_PREC_VIOLATION:
635                         info = "Precedence violation";
636                         break;
637                 case ICMP_PREC_CUTOFF:
638                         info = "Precedence cut off";
639                         break;
640                 default:
641                         info = "Unknown";
642                         break;
643                 }
644                 break;
645         case ICMP_REDIRECT:
646                 switch (code) {
647                 case ICMP_REDIR_NET:
648                         info = "Redirect Net";
649                         break;
650                 case ICMP_REDIR_HOST:
651                         info = "Redirect Host";
652                         break;
653                 case ICMP_REDIR_NETTOS:
654                         info = "Redirect Net for TOS";
655                         break;
656                 case ICMP_REDIR_HOSTTOS:
657                         info = "Redirect Host for TOS";
658                         break;
659                 default:
660                         info = "Unknown";
661                         break;
662                 }
663                 break;
664         case ICMP_TIME_EXCEEDED:
665                 switch (code) {
666                 case ICMP_EXC_TTL:
667                         info = "TTL count exceeded";
668                         break;
669                 case ICMP_EXC_FRAGTIME:
670                         info = "Fragment Reass time exceeded";
671                         break;
672                 default:
673                         info = "Unknown";
674                         break;
675                 }
676                 break;
677         default:
678                 info = "Unknown";
679                 break;
680         }
681
682         return info;
683 }
684
685 static const char *__pcap_icmp_type_info(u_int8_t type)
686 {
687         char *info = NULL;
688
689         switch (type) {
690         case ICMP_ECHOREPLY:
691                 info = "Echo Reply";
692                 break;
693         case ICMP_DEST_UNREACH:
694                 info = "Destination Unreachable";
695                 break;
696         case ICMP_SOURCE_QUENCH:
697                 info = "Source Quench";
698                 break;
699         case ICMP_REDIRECT:
700                 info = "Redirect";
701                 break;
702         case ICMP_ECHO:
703                 info = "Echo Request";
704                 break;
705         case ICMP_TIME_EXCEEDED:
706                 info = "Time Exceeded";
707                 break;
708         case ICMP_PARAMETERPROB:
709                 info = "Parameter Problem";
710                 break;
711         case ICMP_TIMESTAMP:
712                 info = "Timestamp Request";
713                 break;
714         case ICMP_TIMESTAMPREPLY:
715                 info = "Timestamp Reply";
716                 break;
717         case ICMP_INFO_REQUEST:
718                 info = "Information Request";
719                 break;
720         case ICMP_INFO_REPLY:
721                 info = "Information Reply";
722                 break;
723         case ICMP_ADDRESS:
724                 info = "Address Mask Request";
725                 break;
726         case ICMP_ADDRESSREPLY:
727                 info = "Address Mask Reply";
728                 break;
729         default:
730                 info = "Unknown";
731                 break;
732         }
733
734         return info;
735 }
736
737 static void __pcap_icmp_info(const u_char **packet, uint32_t *pktlen)
738 {
739         icmp_t *icmp_h = (icmp_t *)*packet;
740
741         if (STC_PCAP_LOG)
742                 STC_LOGD("Type[%u:%s] Code[%u:%s] Checksum[0x%x]",
743                         icmp_h->type, __pcap_icmp_type_info(icmp_h->type),
744                         icmp_h->code, __pcap_icmp_code_info(icmp_h->type, icmp_h->code),
745                         ntohs(icmp_h->checksum));
746
747         *packet += SIZE_ICMP_HEADER;
748         *pktlen -= SIZE_ICMP_HEADER;
749 }
750
751 static void __pcap_http_info(const u_char **packet, uint32_t *pktlen)
752 {
753         GString *value;
754         gsize value_len;
755         u_char *value_pos = NULL;
756         gchar *value_str = NULL;
757
758         value_len = *pktlen;
759         value = g_string_sized_new(value_len);
760         if (value) {
761                 value_pos = (u_char *)*packet;
762                 while (value_len--)
763                         g_string_append_printf(value, "%c", *(value_pos++));
764                 value_str = g_string_free(value, FALSE);
765         }
766
767         if (STC_PCAP_LOG) {
768                 STC_LOGD(HR_SINGLE "\n%s", value_str);
769                 STC_LOGD(HR_SINGLE);
770         }
771
772         FREE(value_str);
773 }
774
775 static void __pcap_tcp_info(const u_char **packet, uint32_t *pktlen)
776 {
777         tcp_t *tcp_h = (tcp_t *)*packet;
778         u_int16_t source = ntohs(tcp_h->source);
779         u_int16_t dest = ntohs(tcp_h->dest);
780
781         if (STC_PCAP_LOG)
782                 STC_LOGD("Source[%u] Destination[%u] Sequence[%u] "
783                         "Acknowledgment seq[%u] Window size[%u] ",
784                         ntohs(tcp_h->source), ntohs(tcp_h->dest),
785                         ntohl(tcp_h->seq), ntohl(tcp_h->ack_seq),
786                         ntohs(tcp_h->window));
787
788         if (STC_PCAP_LOG)
789                 STC_LOGD("Checksum[0x%x] URG[%u] ACK[%u] PUSH[%u] "
790                 "RST[%u] SYN[%u] FIN[%u]",
791                 ntohs(tcp_h->check),
792                 tcp_h->urg, tcp_h->ack, tcp_h->psh,
793                 tcp_h->rst, tcp_h->syn, tcp_h->fin);
794
795         *packet += (tcp_h->th_off * 4);
796         *pktlen -= (tcp_h->th_off * 4);
797
798         if (*pktlen > 0) {
799                 if (IS_SRC_OR_DST_PORT(PORT_DNS))
800                         __pcap_dns_info(packet, pktlen);
801                 else if (IS_SRC_OR_DST_PORT(PORT_HTTP) ||
802                         IS_SRC_OR_DST_PORT(PORT_HTTP_ALT))
803                         __pcap_http_info(packet, pktlen);
804         }
805 }
806
807 static void __pcap_udp_info(const u_char **packet, uint32_t *pktlen)
808 {
809         udp_t *udp_h = (udp_t *)*packet;
810         u_int16_t source = ntohs(udp_h->source);
811         u_int16_t dest = ntohs(udp_h->dest);
812         u_int16_t len = ntohs(udp_h->len);
813
814         if (STC_PCAP_LOG)
815                 STC_LOGD("Source[%u] Destination[%u] Len[%u] Checksum[0x%x]",
816                         source, dest, len, ntohs(udp_h->check));
817
818         *packet += SIZE_UDP_HEADER;
819         *pktlen -= SIZE_UDP_HEADER;
820
821         if (*pktlen > 0) {
822                 if (IS_SRC_OR_DST_PORT(PORT_DNS))
823                         __pcap_dns_info(packet, pktlen);
824                 else if (IS_SRC_OR_DST_PORT(PORT_BOOTP_C) ||
825                         IS_SRC_OR_DST_PORT(PORT_BOOTP_S))
826                         __pcap_bootp_info(packet, len);
827                 else if (IS_SRC_OR_DST_PORT(PORT_NTP))
828                         __pcap_ntp_info(packet, pktlen);
829         }
830 }
831
832 static const char *__pcap_eth_type_info(u_int16_t type)
833 {
834         char *info = NULL;
835
836         switch (type) {
837         case ETHERTYPE_IP:
838                 info = "IP";
839                 break;
840         case ETHERTYPE_IPV6:
841                 info = "IPv6";
842                 break;
843         case ETHERTYPE_ARP:
844                 info = "ARP";
845                 break;
846         case ETHERTYPE_REVARP:
847                 info = "REVARP";
848                 break;
849         case ETHERTYPE_LOOPBACK:
850                 info = "LOOPBACK";
851                 break;
852         default:
853                 info = "Unknown";
854                 break;
855         }
856
857         return info;
858 }
859
860 static void __pcap_eapol_info(const u_char **packet, uint32_t *pktlen)
861 {
862 }
863
864 static const char *__pcap_arp_opcode_info(u_int16_t opcode)
865 {
866         char *info = NULL;
867
868         switch (opcode) {
869         case ARP_REQUEST:
870                 info = "Request";
871                 break;
872         case ARP_REPLY:
873                 info = "Reply";
874                 break;
875         case ARP_RREQUEST:
876                 info = "RRequest";
877                 break;
878         case ARP_RREPLY:
879                 info = "RReply";
880                 break;
881         default:
882                 info = "Unknown";
883                 break;
884         }
885
886         return info;
887 }
888
889 static void __pcap_arp_info(const u_char **packet, uint32_t *pktlen)
890 {
891         arp_t *arp_h = (arp_t *)*packet;
892         u_int8_t *sha = (u_int8_t *)(*packet + SIZE_ARP_HEADER);
893         u_int8_t *spa = (u_int8_t *)(sha + arp_h->ar_hln);
894         u_int8_t *tha = (u_int8_t *)(spa + arp_h->ar_pln);
895         u_int8_t *tpa = (u_int8_t *)(tha + arp_h->ar_hln);
896         u_int16_t ar_op = ntohs(arp_h->ar_op);
897         char sma[BUFF_SIZE_HOST];
898         char sia[BUFF_SIZE_IP];
899         char tma[BUFF_SIZE_HOST];
900         char tia[BUFF_SIZE_IP];
901         u_int16_t ar_pro;
902
903         g_strlcpy(sma,
904                 ether_ntoa((const struct ether_addr *)sha),
905                 sizeof(sma));
906         g_strlcpy(tma,
907                 ether_ntoa((const struct ether_addr *)tha),
908                 sizeof(tma));
909
910         inet_ntop(AF_INET, (struct in_addr *)spa, sia, BUFF_SIZE_IP);
911         inet_ntop(AF_INET, (struct in_addr *)tpa, tia, BUFF_SIZE_IP);
912
913         ar_pro = ntohs(arp_h->ar_pro);
914
915         if (STC_PCAP_LOG)
916                 STC_LOGD("HW type[%u] Protocol type[0x%04x:%s] "
917                         "HW size[%u] Protocol size[%u] Opcode[%u:%s] ",
918                         ntohs(arp_h->ar_hrd), ar_pro,
919                         __pcap_eth_type_info(ar_pro),
920                         arp_h->ar_hln, arp_h->ar_pln,
921                         ar_op, __pcap_arp_opcode_info(ar_op));
922
923         if (STC_PCAP_LOG)
924                 STC_LOGD("Sender MAC[%s] Sender IP[%s] "
925                         "Target MAC[%s] Target IP[%s]",
926                         sma, sia, tma, tia);
927
928         *packet += SIZE_ARP_HEADER;
929         *pktlen -= SIZE_ARP_HEADER;
930 }
931
932 static const char *__pcap_ip_protocol_info(u_int8_t p)
933 {
934         char *info = NULL;
935
936         switch (p) {
937         case IPPROTO_IP:
938                 info = "IP";
939                 break;
940         case IPPROTO_ICMP:
941                 info = "ICMP";
942                 break;
943         case IPPROTO_IPIP:
944                 info = "IPIP";
945                 break;
946         case IPPROTO_TCP:
947                 info = "TCP";
948                 break;
949         case IPPROTO_UDP:
950                 info = "UDP";
951                 break;
952         case IPPROTO_IPV6:
953                 info = "IPv6";
954                 break;
955         case IPPROTO_ICMPV6:
956                 info = "ICMPv6";
957                 break;
958         default:
959                 info = "Unknown";
960                 break;
961         }
962
963         return info;
964 }
965
966 static void __pcap_ipv6_info(const u_char **packet, uint32_t *pktlen)
967 {
968         ip6_t *ip6_h = (ip6_t *)*packet;
969         char ip6_src[BUFF_SIZE_IP6];
970         char ip6_dst[BUFF_SIZE_IP6];
971
972         inet_ntop(AF_INET6, &ip6_h->ip6_src, ip6_src, BUFF_SIZE_IP6);
973         inet_ntop(AF_INET6, &ip6_h->ip6_dst, ip6_dst, BUFF_SIZE_IP6);
974
975         if (STC_PCAP_LOG)
976                 STC_LOGD("Flow[0x%08x] Payload len[%u] Next hdr[%u:%s] "
977                         "Hop limit[%u] Source[%s] Destination[%s]",
978                         ntohl(ip6_h->ip6_flow), ntohs(ip6_h->ip6_plen),
979                         ip6_h->ip6_nxt, __pcap_ip_protocol_info(ip6_h->ip6_nxt),
980                         ip6_h->ip6_hlim, ip6_src, ip6_dst);
981
982         *packet += SIZE_IP6_HEADER;
983         *pktlen -= SIZE_IP6_HEADER;
984
985         switch (ip6_h->ip6_nxt) {
986         case IPPROTO_TCP:
987                 __pcap_tcp_info(packet, pktlen);
988                 break;
989         case IPPROTO_UDP:
990                 __pcap_udp_info(packet, pktlen);
991                 break;
992         case IPPROTO_ICMPV6:
993                 __pcap_icmp_info(packet, pktlen);
994                 break;
995         default:
996                 break;
997         }
998 }
999
1000 static void __pcap_ip_info(const u_char **packet, uint32_t *pktlen)
1001 {
1002         ip_t *ip_h = (ip_t *)*packet;
1003         char ip_src[BUFF_SIZE_IP];
1004         char ip_dst[BUFF_SIZE_IP];
1005
1006         inet_ntop(AF_INET, &ip_h->ip_src, ip_src, BUFF_SIZE_IP);
1007         inet_ntop(AF_INET, &ip_h->ip_dst, ip_dst, BUFF_SIZE_IP);
1008
1009         if (STC_PCAP_LOG)
1010                 STC_LOGD("Header len[%u] TOS[0x%02x] Total len[%u] "
1011                         "ID[0x%04x] Flags[0x%02x] TTL[%u] Protocol[%u:%s] "
1012                         "Checksum[0x%04x] Source[%s] Destination[%s]",
1013                         ip_h->ip_hl << 2, ip_h->ip_tos,
1014                         ntohs(ip_h->ip_len), ntohs(ip_h->ip_id),
1015                         (ntohs(ip_h->ip_off) & 0xe000) >> 13,
1016                         ip_h->ip_ttl, ip_h->ip_p,
1017                         __pcap_ip_protocol_info(ip_h->ip_p),
1018                         ntohs(ip_h->ip_sum), ip_src, ip_dst);
1019
1020         *packet += SIZE_IP_HEADER;
1021         *pktlen -= SIZE_IP_HEADER;
1022
1023         switch (ip_h->ip_p) {
1024         case IPPROTO_ICMP:
1025                 __pcap_icmp_info(packet, pktlen);
1026                 break;
1027         case IPPROTO_TCP:
1028                 __pcap_tcp_info(packet, pktlen);
1029                 break;
1030         case IPPROTO_UDP:
1031                 __pcap_udp_info(packet, pktlen);
1032                 break;
1033         default:
1034                 break;
1035         }
1036 }
1037
1038 static void __pcap_eth_info(const u_char **packet, uint32_t *pktlen)
1039 {
1040         eth_t *eth_h = (eth_t *)*packet;
1041         u_int8_t *eth_shost = eth_h->ether_shost;
1042         u_int8_t *eth_dhost = eth_h->ether_dhost;
1043         char shost[BUFF_SIZE_HOST];
1044         char dhost[BUFF_SIZE_HOST];
1045         u_int16_t ether_type;
1046
1047         g_strlcpy(shost,
1048                 ether_ntoa((const struct ether_addr *)eth_shost),
1049                 sizeof(shost));
1050
1051         g_strlcpy(dhost,
1052                 ether_ntoa((const struct ether_addr *)eth_dhost),
1053                 sizeof(dhost));
1054
1055         ether_type = ntohs(eth_h->ether_type);
1056
1057         if (STC_PCAP_LOG)
1058                 STC_LOGD("Source[%s] Destination[%s] Type[0x%04x:%s]",
1059                         shost, dhost, ether_type, __pcap_eth_type_info(ether_type));
1060
1061         *packet += SIZE_ETHER_HEADER;
1062         *pktlen -= SIZE_ETHER_HEADER;
1063 }
1064
1065 static const char *__pcap_family_info(u_int8_t family)
1066 {
1067         char *info = NULL;
1068
1069         switch (family) {
1070         case AF_INET:
1071                 info = "IPv4";
1072                 break;
1073         case AF_INET6:
1074                 info = "IPv6";
1075                 break;
1076         default:
1077                 info = "Unknown";
1078                 break;
1079         }
1080
1081         return info;
1082 }
1083
1084 static const char *__pcap_tlv_type_info(u_int16_t type)
1085 {
1086         char *info = NULL;
1087
1088         switch (type) {
1089         case NFULA_PACKET_HDR:
1090                 info = "NFULA_PACKET_HDR";
1091                 break;
1092         case NFULA_MARK:
1093                 info = "NFULA_MARK";
1094                 break;
1095         case NFULA_TIMESTAMP:
1096                 info = "NFULA_TIMESTAMP";
1097                 break;
1098         case NFULA_IFINDEX_INDEV:
1099                 info = "NFULA_IFINDEX_INDEV";
1100                 break;
1101         case NFULA_IFINDEX_OUTDEV:
1102                 info = "NFULA_IFINDEX_OUTDEV";
1103                 break;
1104         case NFULA_IFINDEX_PHYSINDEV:
1105                 info = "NFULA_IFINDEX_PHYSINDEV";
1106                 break;
1107         case NFULA_IFINDEX_PHYSOUTDEV:
1108                 info = "NFULA_IFINDEX_PHYSOUTDEV";
1109                 break;
1110         case NFULA_HWADDR:
1111                 info = "NFULA_HWADDR";
1112                 break;
1113         case NFULA_PAYLOAD:
1114                 info = "NFULA_PAYLOAD";
1115                 break;
1116         case NFULA_PREFIX:
1117                 info = "NFULA_PREFIX";
1118                 break;
1119         case NFULA_UID:
1120                 info = "NFULA_UID";
1121                 break;
1122         case NFULA_SEQ:
1123                 info = "NFULA_SEQ";
1124                 break;
1125         case NFULA_SEQ_GLOBAL:
1126                 info = "NFULA_SEQ_GLOBAL";
1127                 break;
1128         case NFULA_GID:
1129                 info = "NFULA_GID";
1130                 break;
1131         case NFULA_HWTYPE:
1132                 info = "NFULA_HWTYPE";
1133                 break;
1134         case NFULA_HWHEADER:
1135                 info = "NFULA_HWHEADER";
1136                 break;
1137         case NFULA_HWLEN:
1138                 info = "NFULA_HWLEN";
1139                 break;
1140         default:
1141                 info = "Unknown";
1142                 break;
1143         }
1144
1145         return info;
1146 }
1147
1148 static void __pcap_nflog_tlv_info(const u_char **packet,
1149                                 u_int32_t *pktlen)
1150 {
1151         nflog_tlv_t *tlv_h;
1152         u_int16_t tlv_length;
1153         u_int16_t tlv_type;
1154         GString *value;
1155         u_int16_t value_len;
1156         u_char *value_pos = NULL;
1157         gchar *value_str = NULL;
1158
1159         *pktlen -= SIZE_NFLOG_HDR;
1160
1161         while (*pktlen > 0) {
1162                 if (*pktlen < SIZE_NFLOG_TLV)
1163                         break;
1164
1165                 tlv_h = (nflog_tlv_t *)*packet;
1166                 tlv_length = tlv_h->tlv_length;
1167                 if (tlv_length % 4 != 0)
1168                         tlv_length += 4 - tlv_length % 4;
1169                 tlv_type = tlv_h->tlv_type;
1170
1171                 if (tlv_length < SIZE_NFLOG_TLV)
1172                         break;
1173
1174                 if (*pktlen < tlv_length)
1175                         break;
1176
1177                 if (STC_PCAP_LOG) {
1178                         if (tlv_type != NFULA_PAYLOAD) {
1179                                 nflog_hwaddr_t *hwaddr;
1180                                 nflog_timestamp_s *timestamp;
1181                                 char host[BUFF_SIZE_HOST];
1182                                 u_int32_t sec;
1183                                 int len = 0;
1184                                 char *time = NULL;
1185
1186                                 switch (tlv_type) {
1187                                 case NFULA_HWADDR:
1188                                         hwaddr = (nflog_hwaddr_t *)((u_char *)tlv_h + SIZE_NFLOG_TLV);
1189                                         g_strlcpy(host,
1190                                                 ether_ntoa((const struct ether_addr *)hwaddr->hw_addr),
1191                                                 sizeof(host));
1192                                         STC_LOGD("Type[%s:%u] Length[%u] Hwaddr[%s]",
1193                                                 __pcap_tlv_type_info(tlv_type), tlv_type,
1194                                                 tlv_h->tlv_length, host);
1195                                         break;
1196                                 case NFULA_TIMESTAMP:
1197                                         timestamp = (nflog_timestamp_s *)((u_char *)tlv_h + SIZE_NFLOG_TLV);
1198                                         sec = ntohl(timestamp->ts[1]);
1199                                         time = ctime((const time_t *)&sec);
1200                                         len = strlen(time);
1201                                         time[len - 1] = '\0';
1202
1203                                         STC_LOGD("Type[%s:%u] Length[%u] Timestamp[%s]",
1204                                                 __pcap_tlv_type_info(tlv_type), tlv_type,
1205                                                 tlv_h->tlv_length, time);
1206                                         break;
1207                                 case NFULA_PREFIX:
1208                                         value_len = tlv_h->tlv_length - SIZE_NFLOG_TLV;
1209                                         value = g_string_sized_new(value_len);
1210                                         if (value) {
1211                                                 value_pos = (u_char *)tlv_h + SIZE_NFLOG_TLV;
1212                                                 while (value_len--)
1213                                                         g_string_append_printf(value, "%c", *(value_pos++));
1214                                                 value_str = g_string_free(value, FALSE);
1215                                         }
1216
1217                                         STC_LOGD("Type[%s:%u] Length[%u] Prefix[%s]",
1218                                                 __pcap_tlv_type_info(tlv_type), tlv_type,
1219                                                 tlv_h->tlv_length, value_str);
1220
1221                                         FREE(value_str);
1222                                         break;
1223                                 default:
1224                                         value_len = tlv_h->tlv_length - SIZE_NFLOG_TLV;
1225                                         value = g_string_sized_new(value_len);
1226                                         if (value) {
1227                                                 value_pos = (u_char *)tlv_h + SIZE_NFLOG_TLV;
1228                                                 while (value_len--)
1229                                                         g_string_append_printf(value, "%02x", *(value_pos++));
1230                                                 value_str = g_string_free(value, FALSE);
1231                                         }
1232
1233                                         STC_LOGD("Type[%s:%u] Length[%u] Value[%s]",
1234                                                 __pcap_tlv_type_info(tlv_type), tlv_type,
1235                                                 tlv_h->tlv_length, value_str);
1236
1237                                         FREE(value_str);
1238                                         break;
1239                                 }
1240                         } else {
1241                                 STC_LOGD("Type[%s:%u] Length[%u]",
1242                                         __pcap_tlv_type_info(tlv_type),
1243                                         tlv_type, tlv_h->tlv_length);
1244                         }
1245                 }
1246
1247                 if (tlv_type == NFULA_PAYLOAD) {
1248                         *packet += SIZE_NFLOG_TLV;
1249                         *pktlen -= SIZE_NFLOG_TLV;
1250                         break;
1251                 }
1252
1253                 *packet += tlv_length;
1254                 *pktlen -= tlv_length;
1255         }
1256 }
1257
1258 static void __pcap_nflog_hdr_info(const u_char **packet, uint32_t *pktlen)
1259 {
1260         nflog_hdr_t *hdr_h = (nflog_hdr_t *)*packet;
1261         u_int8_t family = hdr_h->nflog_family;
1262         u_int8_t version = hdr_h->nflog_version;
1263         u_int16_t resource_id = ntohs(hdr_h->nflog_rid);
1264
1265         if (STC_PCAP_LOG)
1266                 STC_LOGD("Family[%s:%u] Version[%u] Resource id[%u]",
1267                         __pcap_family_info(family), family, version, resource_id);
1268
1269         *packet += SIZE_NFLOG_HDR;
1270         *pktlen -= SIZE_NFLOG_HDR;
1271 }
1272
1273 static void __pcap_fm_info(const struct pcap_pkthdr *pkthdr)
1274 {
1275         char *curr = NULL;
1276         int len = 0;
1277         struct timeval ts = pkthdr->ts;
1278         __time_t tv_sec = ts.tv_sec;
1279         __suseconds_t tv_usec = ts.tv_usec;
1280
1281         if (g_pcap_start_fm == false) {
1282                 g_pcap_tv = ts;
1283                 g_pcap_start_fm = true;
1284         }
1285
1286         curr = ctime((const time_t *)&tv_sec);
1287         len = strlen(curr);
1288         curr[len - 1] = '\0';
1289
1290         if (STC_PCAP_LOG)
1291                 STC_LOGD("Arrival time[%s] Timeval[%.06f] "
1292                         "Frame len[%u] Capture len[%u]", curr,
1293                         (float)((tv_sec - g_pcap_tv.tv_sec) * 1000000 +
1294                         (tv_usec - g_pcap_tv.tv_usec)) / 1000000,
1295                         pkthdr->len, pkthdr->caplen);
1296 }
1297
1298 static void __pcap_handler(u_char *param,
1299                         const struct pcap_pkthdr *pkthdr,
1300                         const u_char *packet) {
1301         uint32_t pktlen = pkthdr->len;
1302         stc_pcap_data_s *pcap_data = (stc_pcap_data_s *)param;
1303         eth_t *eth_h;
1304         uint16_t eth_type;
1305         nflog_hdr_t *nflog_h;
1306         uint8_t nflog_family;
1307
1308         STC_LOGD(HR_DOUBLE);
1309
1310         __pcap_fm_info(pkthdr);
1311
1312         switch (pcap_data->encap_type) {
1313         case ENCAPTYPE_ETHERNET:
1314                 eth_h = (eth_t *)packet;
1315                 eth_type = ntohs(eth_h->ether_type);
1316
1317                 __pcap_eth_info(&packet, &pktlen);
1318
1319                 switch (eth_type) {
1320                 case ETHERTYPE_IP:
1321                         __pcap_ip_info(&packet, &pktlen);
1322                         /* __pcap_data_info(pcaket, pktlen); */
1323                         break;
1324                 case ETHERTYPE_IPV6:
1325                         __pcap_ipv6_info(&packet, &pktlen);
1326                         break;
1327                 case ETHERTYPE_ARP:
1328                 case ETHERTYPE_REVARP:
1329                         __pcap_arp_info(&packet, &pktlen);
1330                         break;
1331                 case ETHERTYPE_LOOPBACK:
1332                         break;
1333                 case ETHERTYPE_EAPOL:
1334                         __pcap_eapol_info(&packet, &pktlen);
1335                         break;
1336                 default:
1337                         break;
1338                 }
1339                 break;
1340         case ENCAPTYPE_NFLOG:
1341                 nflog_h = (nflog_hdr_t *)packet;
1342                 nflog_family = nflog_h->nflog_family;
1343
1344                 __pcap_nflog_hdr_info(&packet, &pktlen);
1345                 __pcap_nflog_tlv_info(&packet, &pktlen);
1346
1347                 switch (nflog_family) {
1348                 case AF_INET:
1349                         __pcap_ip_info(&packet, &pktlen);
1350                         break;
1351                 case AF_INET6:
1352                         __pcap_ipv6_info(&packet, &pktlen);
1353                         break;
1354                 default:
1355                         break;
1356                 }
1357                 break;
1358         default:
1359                 break;
1360         }
1361
1362         STC_LOGD(HR_DOUBLE);
1363 }
1364
1365 static gboolean __pcap_thread_source_func(gpointer data)
1366 {
1367         char buf[MAX_IFACE_LENGTH];
1368         stc_pcap_data_s *lookup;
1369         stc_pcap_data_s *pcap_data = (stc_pcap_data_s *)data;
1370
1371         g_pcap_tv.tv_sec = 0;
1372         g_pcap_tv.tv_usec = 0;
1373         g_pcap_start_fm = false;
1374
1375         if (g_pcap_tables == NULL)
1376                 return false;
1377
1378         snprintf(buf, sizeof(buf), "%s:%d",
1379                 pcap_data->ifname, pcap_data->nflog_group);
1380
1381         lookup = g_hash_table_lookup(g_pcap_tables, buf);
1382         if (!lookup) {
1383                 STC_LOGE("pcap loop not found");
1384                 return false;
1385         }
1386
1387         g_hash_table_remove(g_pcap_tables, buf);
1388         STC_LOGD("Successfully removed pcap loop [%s]", buf);
1389
1390         return false;
1391 }
1392
1393 static gpointer __pcap_thread_func(gpointer data)
1394 {
1395         __STC_LOG_FUNC_ENTER__;
1396
1397         char errbuf[PCAP_ERRBUF_SIZE];
1398         pcap_if_t *alldevs = NULL;
1399         pcap_if_t *dev = NULL;
1400         char *name = NULL;
1401         GSource *source = NULL;
1402         GMainContext *context = NULL;
1403         stc_pcap_data_s *pcap_data = (stc_pcap_data_s *)data;
1404
1405         if (pcap_findalldevs(&alldevs, errbuf) < 0 ||
1406                 alldevs == NULL) {
1407                 STC_LOGE("Failed to find all devs [%s]", errbuf);
1408                 goto thread_exit;
1409         }
1410
1411         for (dev = alldevs; dev; dev = dev->next) {
1412                 if (g_strcmp0(dev->name, pcap_data->ifname) == 0) {
1413                         if (g_strcmp0(dev->name, NFLOG_IFNAME) == 0) {
1414                                 name = g_strdup(pcap_data->nfname);
1415                                 pcap_data->encap_type = ENCAPTYPE_NFLOG;
1416                         } else {
1417                                 name = g_strdup(pcap_data->ifname);
1418                                 pcap_data->encap_type = ENCAPTYPE_ETHERNET;
1419                         }
1420                         break;
1421                 }
1422         }
1423
1424         pcap_freealldevs(alldevs);
1425
1426         if (name == NULL) {
1427                 STC_LOGE("Failed to find dev [%s]", pcap_data->ifname);
1428                 goto thread_exit;
1429         }
1430
1431         STC_LOGD("Pcap source dev [%s]", name);
1432
1433         pcap_data->handle = pcap_open_live(name, 65535, 1, 1000, errbuf);
1434         if (pcap_data->handle == NULL) {
1435                 STC_LOGE("Failed to open live [%s]", errbuf);
1436                 goto thread_exit;
1437         }
1438
1439         STC_LOGD("Pcap open live [%p]", pcap_data->handle);
1440
1441         STC_LOGD("Pcap loop start [%s]", name);
1442         pcap_loop(pcap_data->handle, 0, __pcap_handler, (u_char *)pcap_data);
1443         STC_LOGD("Pcap loop end [%s]", name);
1444
1445         pcap_close(pcap_data->handle);
1446         STC_LOGD("Pcap closed [%p]", pcap_data->handle);
1447
1448 thread_exit:
1449         FREE(name);
1450
1451         context = g_main_context_default();
1452
1453         source = g_idle_source_new();
1454
1455         g_source_set_callback(source,
1456                 __pcap_thread_source_func, pcap_data, NULL);
1457         g_source_attach(source, context);
1458
1459         g_source_unref(source);
1460
1461         __STC_LOG_FUNC_EXIT__;
1462         return NULL;
1463 }
1464
1465 static void __pcap_make_params(gpointer key, gpointer value,
1466                                 gpointer user_data)
1467 {
1468         stc_pcap_data_s *data = (stc_pcap_data_s *)value;
1469         GVariantBuilder *builder = (GVariantBuilder *)user_data;
1470         GVariantBuilder sub_builder;
1471
1472         g_variant_builder_init(&sub_builder, G_VARIANT_TYPE("a{sv}"));
1473
1474         g_variant_builder_add(&sub_builder, "{sv}", PCAP_IFNAME,
1475                                         g_variant_new_string(data->ifname));
1476
1477         g_variant_builder_add(&sub_builder, "{sv}", PCAP_NFLOG_GROUP,
1478                                 g_variant_new_uint32(data->nflog_group));
1479
1480         g_variant_builder_add_value(builder, g_variant_builder_end(&sub_builder));
1481 }
1482
1483 int stc_plugin_pcap_initialize(void)
1484 {
1485         __STC_LOG_FUNC_ENTER__;
1486
1487         g_pcap_tables = g_hash_table_new_full(g_str_hash,
1488                 g_str_equal, g_free, __pcap_data_free);
1489
1490         __STC_LOG_FUNC_EXIT__;
1491         return STC_ERROR_NONE;
1492 }
1493
1494 int stc_plugin_pcap_deinitialize(void)
1495 {
1496         __STC_LOG_FUNC_ENTER__;
1497
1498         if (g_pcap_tables) {
1499                 g_hash_table_destroy(g_pcap_tables);
1500                 g_pcap_tables = NULL;
1501         }
1502
1503         __STC_LOG_FUNC_EXIT__;
1504         return STC_ERROR_NONE;
1505 }
1506
1507 int stc_plugin_pcap_lookup_dev(void)
1508 {
1509         char *dev = NULL;
1510         char errbuf[PCAP_ERRBUF_SIZE];
1511
1512         dev = pcap_lookupdev(errbuf);
1513         if (dev == NULL) {
1514                 STC_LOGE("Failed to look up dev [%s]", errbuf);
1515                 return STC_ERROR_FAIL;
1516         }
1517
1518         STC_LOGD("Dev [%s]", dev);
1519
1520         return STC_ERROR_NONE;
1521 }
1522
1523 int stc_plugin_pcap_lookup_net(void)
1524 {
1525         char *dev = NULL;
1526         char net[BUFF_SIZE_IP];
1527         char mask[BUFF_SIZE_IP];
1528         char errbuf[PCAP_ERRBUF_SIZE];
1529         int ret;
1530         bpf_u_int32 netp;
1531         bpf_u_int32 maskp;
1532
1533         dev = pcap_lookupdev(errbuf);
1534         if (dev == NULL) {
1535                 STC_LOGE("Failed to look up dev [%s]", errbuf);
1536                 return STC_ERROR_FAIL;
1537         }
1538
1539         STC_LOGD("Dev [%s]", dev);
1540
1541         ret = pcap_lookupnet(dev, &netp, &maskp, errbuf);
1542         if (ret == -1) {
1543                 STC_LOGE("Failed to look up net [%s]", errbuf);
1544                 return STC_ERROR_FAIL;
1545         }
1546
1547         inet_ntop(AF_INET, &netp, net, BUFF_SIZE_IP);
1548         STC_LOGD("Net [%s]", net);
1549
1550         inet_ntop(AF_INET, &maskp, mask, BUFF_SIZE_IP);
1551         STC_LOGD("Mask [%s]", mask);
1552
1553         return STC_ERROR_NONE;
1554 }
1555
1556 int stc_plugin_pcap_find_all_devs(GVariantBuilder *builder)
1557 {
1558         char net[BUFF_SIZE_IP];
1559         char mask[BUFF_SIZE_IP];
1560         char errbuf[PCAP_ERRBUF_SIZE];
1561         pcap_if_t *alldevs = NULL;
1562         pcap_if_t *dev = NULL;
1563         bpf_u_int32 netp;
1564         bpf_u_int32 maskp;
1565
1566         if (pcap_findalldevs(&alldevs, errbuf) < 0 ||
1567                 alldevs == NULL) {
1568                 STC_LOGE("Failed to find all devs [%s]", errbuf);
1569                 return STC_ERROR_FAIL;
1570         }
1571
1572         for (dev = alldevs; dev; dev = dev->next) {
1573                 GVariantBuilder sub_builder;
1574
1575                 g_variant_builder_init(&sub_builder, G_VARIANT_TYPE("a{sv}"));
1576
1577                 STC_LOGD("Dev [%s]", dev->name);
1578                 g_variant_builder_add(&sub_builder, "{sv}", PCAP_DEV_NAME,
1579                                                 g_variant_new_string(dev->name));
1580
1581                 if (dev->description) {
1582                         STC_LOGD("Decs [%s]", dev->description);
1583                         g_variant_builder_add(&sub_builder, "{sv}", PCAP_DEV_DECS,
1584                                                 g_variant_new_string(dev->description));
1585                 }
1586
1587                 if (pcap_lookupnet(dev->name, &netp, &maskp, errbuf) == -1) {
1588                         STC_LOGE("Failed to look up net [%s]", errbuf);
1589                         g_variant_builder_add_value(builder, g_variant_builder_end(&sub_builder));
1590                         continue;
1591                 }
1592
1593                 inet_ntop(AF_INET, &netp, net, BUFF_SIZE_IP);
1594                 STC_LOGD("Net [%s]", net);
1595                 g_variant_builder_add(&sub_builder, "{sv}", PCAP_DEV_NET,
1596                                                 g_variant_new_string(net));
1597
1598                 inet_ntop(AF_INET, &maskp, mask, BUFF_SIZE_IP);
1599                 STC_LOGD("Mask [%s]", mask);
1600                 g_variant_builder_add(&sub_builder, "{sv}", PCAP_DEV_MASK,
1601                                                 g_variant_new_string(mask));
1602
1603                 g_variant_builder_add_value(builder, g_variant_builder_end(&sub_builder));
1604         }
1605
1606         pcap_freealldevs(alldevs);
1607
1608         return STC_ERROR_NONE;
1609 }
1610
1611 int stc_plugin_pcap_register_loop(const char *ifname,
1612                         int nflog_group)
1613 {
1614         stc_pcap_data_s *data;
1615         stc_pcap_data_s *lookup;
1616         char buf[MAX_IFACE_LENGTH];
1617
1618         ret_value_msg_if(g_pcap_tables == NULL,
1619                 STC_ERROR_FAIL,
1620                 "pcap tables is not initialized!");
1621
1622         ret_value_msg_if(ifname == NULL,
1623                 STC_ERROR_FAIL,
1624                 "Invalid parameter [ifname]");
1625
1626         snprintf(buf, sizeof(buf), "%s:%d", ifname, nflog_group);
1627
1628         lookup = g_hash_table_lookup(g_pcap_tables, buf);
1629         if (lookup) {
1630                 STC_LOGD("pcap loop already present");
1631                 return STC_ERROR_ALREADY_DATA;
1632         }
1633
1634         data = MALLOC0(stc_pcap_data_s, 1);
1635         if (!data) {
1636                 STC_LOGE("data allocation failed");
1637                 return STC_ERROR_OUT_OF_MEMORY;
1638         }
1639
1640         data->ifname = g_strdup(ifname);
1641         data->nfname = g_strdup(buf);
1642         data->nflog_group = nflog_group;
1643         data->thread = g_thread_new(buf, __pcap_thread_func, data);
1644
1645         g_hash_table_insert(g_pcap_tables, g_strdup(buf), data);
1646         STC_LOGD("Successfully added pcap loop [%s]", buf);
1647
1648         return STC_ERROR_NONE;
1649 }
1650
1651 int stc_plugin_pcap_unregister_loop(const char *ifname,
1652                         int nflog_group)
1653 {
1654         stc_pcap_data_s *lookup;
1655         char buf[MAX_IFACE_LENGTH];
1656
1657         ret_value_msg_if(g_pcap_tables == NULL,
1658                 STC_ERROR_FAIL,
1659                 "pcap tables is not initialized!");
1660
1661         ret_value_msg_if(ifname == NULL,
1662                 STC_ERROR_FAIL,
1663                 "Invalid parameter [ifname]");
1664
1665         snprintf(buf, sizeof(buf), "%s:%d", ifname, nflog_group);
1666
1667         lookup = g_hash_table_lookup(g_pcap_tables, buf);
1668         if (!lookup) {
1669                 STC_LOGE("pcap loop not found");
1670                 __STC_LOG_FUNC_EXIT__;
1671                 return STC_ERROR_NO_DATA;
1672         }
1673
1674         pcap_breakloop(lookup->handle);
1675         STC_LOGD("Successfully removed pcap loop [%s]", buf);
1676
1677         return STC_ERROR_NONE;
1678 }
1679
1680 int stc_plugin_pcap_get_all_loop(GVariantBuilder *builder)
1681 {
1682         ret_value_msg_if(g_pcap_tables == NULL,
1683                 STC_ERROR_FAIL,
1684                 "pcap tables is not initialized!");
1685
1686         g_hash_table_foreach(g_pcap_tables, __pcap_make_params, builder);
1687
1688         return STC_ERROR_NONE;
1689 }
1690
1691 API stc_plugin_pcap_s stc_plugin_pcap = {
1692         .initialize_plugin =
1693                 stc_plugin_pcap_initialize,
1694         .deinitialize_plugin =
1695                 stc_plugin_pcap_deinitialize,
1696         .lookup_dev =
1697                 stc_plugin_pcap_lookup_dev,
1698         .lookup_net =
1699                 stc_plugin_pcap_lookup_net,
1700         .find_all_devs =
1701                 stc_plugin_pcap_find_all_devs,
1702         .register_loop =
1703                 stc_plugin_pcap_register_loop,
1704         .unregister_loop =
1705                 stc_plugin_pcap_unregister_loop,
1706         .get_all_loop =
1707                 stc_plugin_pcap_get_all_loop
1708 };
1709 //LCOV_EXCL_STOP