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