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