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