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