1 /*
2 * Copyright (c) 2010 Daisuke Miyamoto. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 *
25 */
26
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <unistd.h>
31 #include <fcntl.h>
32 #include <time.h>
33 #include <signal.h>
34 #include <sys/types.h>
35 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <sys/un.h>
38 #include <arpa/inet.h>
39 #include <sys/time.h>
40 #include <netdb.h>
41
42 #include <pcap.h>
43 #include <glib.h>
44 #include <openssl/md5.h>
45
46 #include "pt_std.h"
47 #include "pt_thmon.h"
48 #include "pt_pcap.h"
49 #include "pt_datalink.h"
50 #include "pt_ip.h"
51 #include "pt_ip6.h"
52 #include "pt_tcp.h"
53 #include "pt_udp.h"
54 #include "pt_icmp.h"
55 #include "pt_icmp6.h"
56 #include "pt_iptbhash.h"
57 #include "pt_send.h"
58 #include "pt_mesg.h"
59 #include "pt_util.h"
60
61 void packter_addstring_hash(char *buf, char *key);
62 int packter_is_exist_key_str(char *key);
63
64 #include "proto_ether.h"
65 #include "proto_ip.h"
66 #include "proto_ip6.h"
67 #include "proto_ipproto.h"
68 #include "proto_icmp.h"
69 #include "proto_icmp6.h"
70 #include "proto_tcp.h"
71 #include "proto_udp.h"
72
73 char *progname;
74 int debug = PACKTER_FALSE;
75
76 int sock;
77 struct sockaddr_in addr;
78
79 /* for IPv6 */
80 #ifdef USE_INET6
81 struct sockaddr_in6 addr6;
82 #endif
83 int use6 = PACKTER_FALSE;
84
85 /* for thresohold */
86 struct pt_threshold th;
87
88 /* interval */
89 int interval = PACKTER_INTVAL;
90
91 /* sound */
92 int enable_sound = PACKTER_FALSE;
93
94 /* flagbase */
95 int packter_flagbase = 0;
96
97 /* config */
98 GHashTable *config = NULL;
99 char *configfile = NULL ;
100
main(int argc,char * argv[])101 int main(int argc, char *argv[])
102 {
103 /* pcap */
104 char *dumpfile = NULL ; /* pcap dumpfile */
105 char *device = NULL; /* interface */
106 char *filter = NULL; /* pcap filter */
107
108 /* viewer */
109 char *ip = NULL;
110 int port = 0;
111
112 /* misc */
113 int op;
114 int viewer = PACKTER_FALSE;
115
116 progname = argv[0];
117
118 packter_thmon_init();
119
120 /* getopt */
121 #ifdef USE_INET6
122 while ((op = getopt(argc, argv, "v:i:r:p:S:F:R:I:U:P:C:w:c:f:s6dh?")) != -1)
123 #else
124 while ((op = getopt(argc, argv, "v:i:r:p:S:F:R:I:U:P:C:w:c:f:sdh?")) != -1)
125 #endif
126 {
127 switch (op) {
128 case 'f': /* packter flag base */
129 packter_flagbase = atoi(optarg);
130 break;
131
132 case 'd': /* show debug */
133 debug = PACKTER_TRUE;
134 break;
135
136 #ifdef USE_INET6
137 case '6': /* use inet6 */
138 use6 = PACKTER_TRUE;
139 break;
140 #endif
141
142 case 'v': /* viewer ip */
143 ip = optarg;
144 viewer = PACKTER_TRUE;
145 break;
146
147 case 'p': /* viewer port */
148 port = atoi(optarg);
149 break;
150
151 case 'i': /* interface specified */
152 device = optarg;
153 break;
154
155 case 'r': /* read local files */
156 dumpfile = optarg;
157 break;
158
159 /* Threshold */
160 case 'S': /* SYN */
161 th.rate_syn = atof(optarg);
162 break;
163
164 case 'F': /* FIN */
165 th.rate_fin = atof(optarg);
166 break;
167
168 case 'R': /* RST */
169 th.rate_rst = atof(optarg);
170 break;
171
172 case 'I': /* ICMP */
173 th.rate_icmp = atof(optarg);
174 break;
175
176 case 'U': /* UDP */
177 th.rate_udp = atof(optarg);
178 break;
179
180 case 'P': /* PPS */
181 th.rate_pps = atof(optarg);
182 break;
183
184 case 'C': /* Count */
185 th.count_max = atoi(optarg);
186 break;
187
188 case 'w': /* interval */
189 interval = atoi(optarg);
190 break;
191
192 case 's': /* enable sound */
193 enable_sound = PACKTER_TRUE;
194 break;
195
196 case 'c': /* config */
197 configfile = optarg;
198 break;
199
200 case 'h':
201 case '?': /* usage */
202 packter_thmon_usage();
203 break;
204 }
205 }
206
207 if (argv[optind] != NULL){
208 filter = argv[optind];
209 }
210
211 if (viewer != PACKTER_TRUE){
212 packter_thmon_usage();
213 }
214
215 if (packter_config_parse(configfile) < 0){
216 packter_thmon_usage();
217 }
218
219 /* If no threshold specified */
220 if (th.rate_syn < 0 && th.rate_fin < 0 && th.rate_rst < 0 &&
221 th.rate_udp < 0 && th.rate_icmp < 0 && th.rate_pps < 0){
222 printf("*** No threhold is givn : %s will not alert to viewer. ***\n", progname);
223 }
224
225 #ifdef USE_INET6
226 if (use6 == PACKTER_TRUE){
227 if ((sock = socket(PF_INET6, SOCK_DGRAM, 0)) < 0){
228 perror("socket");
229 exit(EXIT_FAILURE);
230 }
231 if (inet_pton(AF_INET6, ip, (void *)&(addr6.sin6_addr)) < 0){
232 perror("inet_pton");
233 exit(EXIT_FAILURE);
234 }
235 if (port > 0){
236 addr6.sin6_port = htons(port);
237 }
238 else {
239 addr6.sin6_port = htons(PACKTER_VIEWER_PORT);
240 }
241 }
242 else {
243 #endif
244 if ((sock = socket(PF_INET, SOCK_DGRAM, 0)) < 0){
245 perror("socket");
246 exit(EXIT_FAILURE);
247 }
248 if (inet_pton(AF_INET, ip, (void *)&(addr.sin_addr)) < 0){
249 perror("inet_pton");
250 exit(EXIT_FAILURE);
251 }
252 if (port > 0){
253 addr.sin_port = htons(port);
254 }
255 else {
256 addr.sin_port = htons(PACKTER_VIEWER_PORT);
257 }
258 #ifdef USE_INET6
259 }
260 #endif
261
262 packter_pcap(dumpfile, device, filter);
263
264 exit(EXIT_SUCCESS);
265 }
266
packter_thmon_init()267 void packter_thmon_init()
268 {
269 memset((void *)&addr, 0, sizeof(struct sockaddr_in));
270 addr.sin_family = AF_INET;
271
272 #ifdef USE_INET6
273 memset((void *)&addr6, 0, sizeof(struct sockaddr_in6));
274 addr6.sin6_family = AF_INET6;
275 #endif
276
277 srand((unsigned)time(NULL));
278
279 th.count_max = PACKTER_THCOUNT;
280 th.rate_syn = -1;
281 th.rate_fin = -1;
282 th.rate_rst = -1;
283 th.rate_icmp = -1;
284 th.rate_udp = -1;
285 th.rate_pps = -1;
286
287 th.stop.tv_sec = 0;
288 th.stop.tv_usec = 0;
289
290 packter_count_init();
291
292 config = g_hash_table_new((GHashFunc)g_str_hash, (GCompareFunc)g_str_equal);
293 signal(SIGHUP, packter_sig_handler);
294
295 return;
296 }
297
packter_count_init()298 void packter_count_init()
299 {
300 th.count_all = 0;
301 th.count_syn = 0;
302 th.count_fin = 0;
303 th.count_rst = 0;
304 th.count_icmp = 0;
305 th.count_udp = 0;
306 }
307
packter_pcap(char * dumpfile,char * device,char * filter)308 void packter_pcap(char *dumpfile, char *device, char *filter)
309 {
310 /* pcap */
311 pcap_t *pd; /* pcap descriptor */
312 char errbuf [PCAP_ERRBUF_SIZE]; /* errbuf for pcap */
313 uint32_t localnet, netmask; /* network for interface */
314 pcap_handler callback; /* pcap callback function */
315 int datalink; /* pcap datalink */
316
317 /* pcap filter */
318 struct bpf_program fcode; /* compiled pcap filter */
319
320 if (dumpfile != NULL) {
321 /* pcap offline mode : read dump file */
322 if ((pd = pcap_open_offline(dumpfile, errbuf)) == NULL) {
323 fprintf(stderr, "pcap_open_offline: %s\n", errbuf);
324 exit(EXIT_FAILURE);
325 }
326 localnet = 0;
327 netmask = 0;
328 }
329 else {
330 if (device == NULL) {
331 if ((device = pcap_lookupdev(errbuf)) == NULL) {
332 fprintf(stderr, "pcap_lookup: %s", errbuf);
333 exit(EXIT_FAILURE);
334 }
335 }
336 if (debug == PACKTER_TRUE){
337 printf("device = %s\n", device);
338 }
339
340 /* open pcap with promisc mode */
341 if ((pd = pcap_open_live(device, PACKTER_SNAPLEN, 1, 500, errbuf))
342 == NULL) {
343 fprintf(stderr, "pcap_open_live: %s\n", errbuf);
344 exit(EXIT_FAILURE);
345 }
346 /* get netmask */
347 if (pcap_lookupnet(device, &localnet, &netmask, errbuf) < 0) {
348 fprintf(stderr, "pcap_lookupnet: %s\n", errbuf);
349 }
350 }
351
352 if (pcap_compile(pd, &fcode, filter, 0, netmask) < 0) {
353 fprintf(stderr, "pcap_compile: %s\n", pcap_geterr(pd));
354 exit(EXIT_FAILURE);
355 }
356
357 /* set filter */
358 if (pcap_setfilter(pd, &fcode) < 0) {
359 fprintf(stderr, "pcap_setfilter: %s\n", pcap_geterr(pd));
360 exit(EXIT_FAILURE);
361 }
362 /* get datalink type */
363 if ((datalink = pcap_datalink(pd)) < 0) {
364 fprintf(stderr, "pcap_datalink: %s\n", pcap_geterr(pd));
365 exit(EXIT_FAILURE);
366 }
367 /* select callback function */
368 switch (datalink) {
369 case DLT_NULL:
370 if (debug == PACKTER_TRUE){
371 printf("linktype = LoopBack\n");
372 }
373 callback = packter_lback;
374 break;
375
376 case DLT_EN10MB:
377 if (debug == PACKTER_TRUE){
378 printf("linktype = Ethernet\n");
379 }
380 callback = packter_ether;
381 break;
382
383 default:
384 fprintf(stderr, "linktype = change other link\n");
385 exit(EXIT_FAILURE);
386 }
387
388 /* Loop -> pcap read packets and excute callback funcation */
389 if (pcap_loop(pd, -1, callback, NULL) < 0) {
390 fprintf(stderr, "pcap_loop: %s\n", pcap_geterr(pd));
391 exit(EXIT_FAILURE);
392 }
393 pcap_close(pd);
394
395 return;
396 }
397
398 void
packter_thmon_usage(void)399 packter_thmon_usage(void)
400 {
401 printf("usage: %s \n", progname);
402 printf(" -v [ Viewer IP address ]\n");
403 printf(" -p [ Viewer Port number ] (optional: default 11300)\n");
404 printf(" -i [ Monitor device ] (optional)\n");
405 printf(" -r [ Pcap dump file ] (optional)\n");
406 printf(" -d ( Show debug information: optional)\n");
407 printf(" -w [ Waint Interval ] (optional: default 30)\n");
408 printf(" -c [ config file ] (optional: default %s)\n", PACKTER_THCONFIG);
409 printf(" -s ( Enable Sound: optional: default no)\n", PACKTER_THCONFIG);
410 printf(" -C [ Number of couting packet ] (optional: default 500)\n");
411 printf(" -S [ TCP SYN Threshold ] (optional)\n");
412 printf(" -F [ TCP FIN Threshold ] (optional)\n");
413 printf(" -R [ TCP RST Threshold ] (optional)\n");
414 printf(" -I [ ICMP Threshold ] (optional)\n");
415 printf(" -U [ UDP Threshold ] (optional)\n");
416 printf(" -P [ PPS Threshold ] (optional)\n");
417 printf(" [ pcap filter expression ] (optional)\n");
418 printf("\n");
419 printf(" ex) %s -v 192.168.1.1 \"port not 11300 and port not 22\"\n", progname);
420 printf("\n");
421
422 exit(EXIT_SUCCESS);
423 }
424
425 /* process Loop Back */
426 void
packter_lback(u_char * userdata,const struct pcap_pkthdr * h,const u_char * p)427 packter_lback(u_char * userdata, const struct pcap_pkthdr *h, const u_char * p)
428 {
429 /* paranoia NULL check */
430 if (userdata == NULL || h == NULL || p == NULL)
431 return;
432 /* if capture size is too short */
433 if (h->caplen < NULL_HDRLEN)
434 return;
435 else
436 packter_ip((u_char *)(p + NULL_HDRLEN), (u_int)(h->len - NULL_HDRLEN));
437 return;
438 }
439
440 /* process IEEE 802.3 Ethernet */
441 void
packter_ether(u_char * userdata,const struct pcap_pkthdr * h,const u_char * p)442 packter_ether(u_char * userdata, const struct pcap_pkthdr *h, const u_char * p)
443 {
444 struct ether_header *ep;
445 u_int ether_type;
446 int skiplen = ETHER_HDRLEN;
447
448 /* if capture size is too short */
449 if (h->caplen < ETHER_HDRLEN)
450 return;
451 else
452 ep = (struct ether_header *)p;
453
454 ether_type = ntohs(ep->ether_type);
455
456 if (ether_type == ETHERTYPE_8021Q){
457 ep = (struct ether_header *)(p + 4);
458 ether_type = ntohs(ep->ether_type);
459 skiplen += 4;
460 }
461
462 switch(ether_type){
463 case ETHERTYPE_IP:
464 if (th.count_all == 0){
465 gettimeofday(&th.start, NULL);
466 }
467
468 /* check interval */
469 if (th.start.tv_sec - th.stop.tv_sec > interval){
470 th.count_all = th.count_all + 1;
471 packter_ip((u_char *)(p + skiplen), (u_int)(h->len - skiplen));
472 }
473 break;
474
475 case ETHERTYPE_IPV6:
476 if (th.count_all == 0){
477 gettimeofday(&th.start, NULL);
478 }
479 /* check interval */
480 if (th.start.tv_sec - th.stop.tv_sec > interval){
481 th.count_all = th.count_all + 1;
482 packter_ip6((u_char *)(p + skiplen), (u_int)(h->len - skiplen));
483 }
484 break;
485
486 default:
487 break;
488 }
489 /* after packter_ip() ends */
490
491 if (th.count_all >= th.count_max){
492 packter_analy();
493 packter_count_init();
494 }
495 return;
496 }
497
498 void
packter_analy()499 packter_analy()
500 {
501 int alert = PACKTER_FALSE;
502 char mesg[PACKTER_BUFSIZ];
503 char sound[PACKTER_BUFSIZ];
504 char voice[PACKTER_BUFSIZ];
505 char skydome[PACKTER_BUFSIZ];
506 float diff = 0;
507 float mon_syn, mon_fin, mon_rst, mon_icmp, mon_udp, mon_pps;
508
509 /* Finalize Counter Variable */
510 gettimeofday(&th.stop, NULL);
511 mon_syn = (float)th.count_syn/(float)th.count_all;
512 mon_fin = (float)th.count_fin/(float)th.count_all;
513 mon_rst = (float)th.count_rst/(float)th.count_all;
514 mon_icmp = (float)th.count_icmp/(float)th.count_all;
515 mon_udp = (float)th.count_udp/(float)th.count_all;
516
517 diff = (float)(th.stop.tv_sec - th.start.tv_sec) +
518 (float)(th.stop.tv_usec - th.start.tv_usec)/(float)1000000;
519 if (diff < 1){
520 diff = 1;
521 }
522 mon_pps = (float)th.count_all/(float)diff;
523
524 /* Initialize PACKTER Protocol Header */
525 snprintf(mesg, PACKTER_BUFSIZ, "%s", PACKTER_MSG);
526 snprintf(sound, PACKTER_BUFSIZ, "%s", PACKTER_SOUND);
527 snprintf(voice, PACKTER_BUFSIZ, "%s", PACKTER_VOICE);
528 snprintf(skydome, PACKTER_BUFSIZ, "%s", PACKTER_SKYDOME);
529
530 printf ("-------------------------\n");
531 printf ("Statistics of %d packet\n", th.count_all);
532 printf ("Observed: %d.%d - %d.%d\n", th.start.tv_sec, th.start.tv_usec, th.stop.tv_sec, th.stop.tv_usec);
533 printf ("SYN : %.4f FIN : %.4f RST: %.4f\n", mon_syn, mon_fin, mon_rst);
534 printf ("ICMP: %.4f UDP : %.4f PPS: %.4f\n", mon_icmp, mon_udp, mon_pps);
535 printf ("-------------------------\n");
536
537 if (mon_syn > th.rate_syn && th.rate_syn > 0){
538 alert = packter_generate_alert(alert, mesg, sound, voice,
539 "MON_SYN_PIC", "MON_SYN_MSG", "MON_SYN_SOUND", "MON_SYN_VOICE",
540 mon_syn * 100, th.rate_syn * 100);
541 }
542
543 if (mon_fin > th.rate_fin && th.rate_fin > 0){
544 alert = packter_generate_alert(alert, mesg, sound, voice,
545 "MON_FIN_PIC", "MON_FIN_MSG", "MON_FIN_SOUND", "MON_FIN_VOICE",
546 mon_fin * 100, th.rate_fin * 100);
547 }
548
549 if (mon_rst > th.rate_rst && th.rate_rst > 0){
550 alert = packter_generate_alert(alert, mesg, sound, voice,
551 "MON_RST_PIC", "MON_RST_MSG", "MON_RST_SOUND", "MON_RST_VOICE",
552 mon_rst * 100, th.rate_rst * 100);
553 }
554
555 if (mon_icmp > th.rate_icmp && th.rate_icmp > 0){
556 alert = packter_generate_alert(alert, mesg, sound, voice,
557 "MON_ICMP_PIC", "MON_ICMP_MSG", "MON_ICMP_SOUND", "MON_ICMP_VOICE",
558 mon_icmp * 100, th.rate_icmp * 100);
559 }
560
561 if (mon_udp > th.rate_udp && th.rate_udp > 0){
562 alert = packter_generate_alert(alert, mesg, sound, voice,
563 "MON_UDP_PIC", "MON_UDP_MSG", "MON_UDP_SOUND", "MON_UDP_VOICE",
564 mon_udp * 100, th.rate_udp * 100);
565 }
566
567 if (mon_pps > th.rate_pps && th.rate_pps > 0){
568 alert = packter_generate_alert(alert, mesg, sound, voice,
569 "MON_PPS_PIC", "MON_PPS_MSG", "MON_PPS_SOUND", "MON_PPS_VOICE",
570 mon_pps, th.rate_pps);
571 }
572
573 if (alert == PACKTER_TRUE){
574 if (packter_is_exist_key_str("MON_OPT_MSG_FOOT") == PACKTER_TRUE){
575 packter_addstring_hash(mesg, "MON_OPT_MSG_FOOT");
576 }
577 packter_send(mesg);
578
579 if (enable_sound == PACKTER_TRUE){
580 /* PACKTERSOUND uses no footer, but codes are prepared */
581 if (packter_is_exist_key_str("MON_OPT_SOUND_FOOT") == PACKTER_TRUE){
582 packter_addstring_hash(voice, "MON_OPT_SOUND");
583 }
584 packter_send(sound);
585
586 /* PACKTERVOICE sometimes needs footer */
587 if (packter_is_exist_key_str("MON_OPT_VOICE_FOOT") == PACKTER_TRUE){
588 packter_addstring_hash(voice, "MON_OPT_VOICE_FOOT");
589 }
590 packter_send(voice);
591
592 /* PACKTER_SKYDOME sends only skydome texture is specified */
593 if (packter_is_exist_key_str("MON_SKYDOME_START") == PACKTER_TRUE){
594 packter_addstring_hash(skydome, "MON_SKYDOME_START");
595 packter_send(skydome);
596 }
597 }
598 }
599
600 return;
601 }
602
603 /* process ip header */
604 void
packter_ip(u_char * p,u_int len)605 packter_ip(u_char * p, u_int len)
606 {
607 struct ip *ip;
608 char srcip[PACKTER_BUFSIZ];
609 char dstip[PACKTER_BUFSIZ];
610 char mesgbuf[PACKTER_BUFSIZ];
611
612 /* if ip is too short */
613 if (len < sizeof(struct ip))
614 return;
615 else
616 ip = (struct ip *)p;
617
618 /* if not ipv4 or not tcp or udp */
619 if (ip->ip_v != IPVERSION){
620 return;
621 }
622
623 memset((void *)&srcip, '\0', PACKTER_BUFSIZ);
624 memset((void *)&dstip, '\0', PACKTER_BUFSIZ);
625 inet_ntop(AF_INET, (void *)(&ip->ip_src), srcip, PACKTER_BUFSIZ);
626 inet_ntop(AF_INET, (void *)(&ip->ip_dst), dstip, PACKTER_BUFSIZ);
627
628 switch (ip->ip_p) {
629 case IPPROTO_TCP:
630 packter_tcp((u_char *)(p + ip->ip_hl * 4), (u_int)(len - ip->ip_hl*4),
631 srcip, dstip, PACKTER_TCP_ACK, mesgbuf);
632 break;
633
634 case IPPROTO_UDP:
635 th.count_udp = th.count_udp + 1;
636 break;
637
638 case IPPROTO_ICMP:
639 th.count_icmp = th.count_icmp + 1;
640 break;
641
642 default:
643 return;
644 }
645 return;
646 }
647
648 /* process ipv6 header */
649 void
packter_ip6(u_char * p,u_int len)650 packter_ip6(u_char * p, u_int len)
651 {
652 struct ip6_hdr *ip6;
653 char srcip[PACKTER_BUFSIZ];
654 char dstip[PACKTER_BUFSIZ];
655 char mesgbuf[PACKTER_BUFSIZ];
656
657 if (len < sizeof(struct ip6_hdr)){
658 return;
659 }
660 else {
661 ip6 = (struct ip6_hdr *)p;
662 }
663
664 memset((void *)&srcip, '\0', PACKTER_BUFSIZ);
665 memset((void *)&dstip, '\0', PACKTER_BUFSIZ);
666 inet_ntop(AF_INET6, (void *)(&ip6->ip6_src), srcip, PACKTER_BUFSIZ);
667 inet_ntop(AF_INET6, (void *)(&ip6->ip6_dst), dstip, PACKTER_BUFSIZ);
668
669 switch(ip6->ip6_nxt){
670 case IPPROTO_TCP:
671 packter_tcp((u_char *)(p + ntohs(ip6->ip6_plen)),
672 (u_int)(len - ntohs(ip6->ip6_plen)),
673 srcip, dstip, PACKTER_TCP_ACK6, mesgbuf);
674 break;
675
676 case IPPROTO_UDP:
677 th.count_udp = th.count_udp + 1;
678 break;
679
680 case IPPROTO_ICMPV6:
681 th.count_icmp = th.count_icmp + 1;
682 break;
683
684 default:
685 return;
686 }
687 }
688
689
690 /* process tcp header */
691 void
packter_tcp(u_char * p,u_int len,char * srcip,char * dstip,int flag,char * mesgbuf)692 packter_tcp(u_char *p, u_int len, char *srcip, char *dstip, int flag, char *mesgbuf)
693 {
694 struct tcphdr *tcph;
695
696 if (len < TCP_HDRLEN){
697 return;
698 }
699 else {
700 tcph = (struct tcphdr *)p;
701 }
702
703
704 if (tcph->th_flags & TH_SYN){
705 th.count_syn = th.count_syn + 1;
706 }
707
708 if (tcph->th_flags & TH_FIN){
709 th.count_fin = th.count_fin + 1;
710 }
711
712 if (tcph->th_flags & TH_RST){
713 th.count_rst = th.count_rst + 1;
714 }
715
716 return;
717 }
718
packter_send(char * mesg)719 void packter_send(char *mesg)
720 {
721 /* check the limit */
722
723 if (debug == PACKTER_TRUE){
724 printf("%s\n", mesg);
725 }
726
727 #ifdef USE_INET6
728 if (use6 == PACKTER_TRUE){
729 if (sendto(sock, mesg, strlen(mesg), 0,
730 (struct sockaddr *)&addr6, sizeof(struct sockaddr_in6)) < 0){
731 perror("sendto");
732 }
733 }
734 else {
735 #endif
736
737 if (sendto(sock, mesg, strlen(mesg), 0,
738 (struct sockaddr *)&addr, sizeof(struct sockaddr)) < 0){
739 perror("sendto");
740 }
741
742 #ifdef USE_INET6
743 }
744 #endif
745 return;
746 }
747
packter_config_trim(char buf[])748 int packter_config_trim(char buf[])
749 {
750 char newbuf[PACKTER_BUFSIZ];
751 int i, j, space, frontspace;
752
753 /* init variables */
754 frontspace = space = i = j = 0;
755
756 for (i = 0; i < strlen(buf); i++){
757 if (frontspace == 0 && (buf[i] == '\t' || buf[i] == ' ')){
758 continue;
759 }
760 else {
761 frontspace = 1;
762 }
763
764 switch(buf[i]){
765 case '\r':
766 case '\n':
767 break;
768
769 case '\t':
770 case ' ':
771 if (space == 0){
772 newbuf[j++] = ' ';
773 space = 1;
774 }
775 break;
776
777 default:
778 newbuf[j++] = buf[i];
779 space = 0;
780 break;
781 }
782 }
783 newbuf[j] = '\0';
784
785 /* copy */
786 memcpy((void *)buf, (void *)newbuf, PACKTER_BUFSIZ);
787
788 return j;
789 }
790
packter_config_parse(char * configfile)791 int packter_config_parse(char *configfile)
792 {
793 FILE *fp;
794 GHashTable *hash = NULL;
795 char buf[PACKTER_BUFSIZ];
796 char key[PACKTER_BUFSIZ];
797 char val[PACKTER_BUFSIZ];
798 char *tmp;
799
800 if (configfile == NULL){
801 if ((fp = fopen(PACKTER_THCONFIG, "r")) == NULL){
802 fprintf(stderr, "configuration file %s is not readable\n", PACKTER_THCONFIG);
803 return PACKTER_FALSE;
804 }
805 }
806 else {
807 if ((fp = fopen(configfile, "r")) == NULL){
808 fprintf(stderr, "configuration file %s is not readable\n", configfile);
809 return PACKTER_FALSE;
810 }
811 }
812
813 while(fgets(buf, PACKTER_BUFSIZ, fp) != NULL){
814 if (buf == NULL || strlen(buf) < 1 ){
815 break;
816 }
817 if (buf[0] == '#'){
818 continue;
819 }
820 if (packter_config_trim(buf) < 1){
821 continue;
822 }
823
824 if ((tmp = strchr(buf, '=')) != NULL){
825 *(tmp++) = '\0';
826 strncpy(key, buf, PACKTER_BUFSIZ);
827 strncpy(val, tmp, PACKTER_BUFSIZ);
828 if (strlen(key) < 1 || strlen(val) < 1){
829 continue;
830 }
831 if (g_hash_table_lookup(config, (gconstpointer)key) == NULL){
832 g_hash_table_insert(config, g_strdup(key), g_strdup(val));
833 }
834 }
835 }
836 return PACKTER_TRUE;
837 }
838
packter_generate_alert(int alert,char * mesg,char * sound,char * voice,char * mon_pic,char * mon_mesg,char * mon_sound,char * mon_voice,float mon_th,float given_th)839 int packter_generate_alert(int alert, char *mesg, char *sound, char *voice, char *mon_pic, char *mon_mesg, char *mon_sound, char *mon_voice, float mon_th, float given_th)
840 {
841 char tmp[PACKTER_BUFSIZ];
842 memset((void *)tmp, '\0', PACKTER_BUFSIZ);
843
844 if (alert == PACKTER_FALSE){
845 /*
846 * PACKTERMESG
847 * PIC,CONTENT(HEAD+BODY+FOOT)
848 */
849
850 /* PIC for PACKTERMESG called at once */
851 if (packter_is_exist_key_str(mon_pic) == PACKTER_TRUE){
852 packter_addstring_hash(mesg, mon_pic);
853 }
854 packter_addstring(mesg, ",");
855 /* Header for PACKTERMESG called at once */
856 if (packter_is_exist_key_str("MON_OPT_MSG_HEAD") == PACKTER_TRUE){
857 packter_addstring_hash(mesg, "MON_OPT_MSG_HEAD");
858 }
859
860 /*
861 * PACKTERSOUND
862 * PLAYTIME,FILENAME(HEAD+BODY+FOOT)
863 */
864
865 /* Header for PACKTERSOUND called at once */
866 if (packter_is_exist_key_str("MON_OPT_SOUND_HEAD") == PACKTER_TRUE){
867 packter_addstring_hash(voice, "MON_OPT_SOUND_HEAD");
868 }
869 /* PACKTERSOUND called at once */
870 if (packter_is_exist_key_str(mon_sound) == PACKTER_TRUE){
871 packter_addstring_hash(sound, mon_sound);
872 }
873
874 /*
875 * PACKTERVOICE
876 * CONTENT(HEAD+BODY+FOOT)
877 */
878 /* Header for PACKTERVOICE called at once */
879 if (packter_is_exist_key_str("MON_OPT_VOICE_HEAD") == PACKTER_TRUE){
880 packter_addstring_hash(voice, "MON_OPT_VOICE_HEAD");
881 }
882
883 alert = PACKTER_TRUE;
884 }
885
886 /* PACKTERMESG main content */
887 if (packter_is_exist_key_str(mon_mesg) == PACKTER_TRUE){
888 packter_addstring_hash(mesg, mon_mesg);
889 }
890
891 /* PACKTERMESG for Observed Variable */
892 if (packter_is_exist_key_str("MONITOR") == PACKTER_TRUE){
893 packter_addstring_hash(mesg, "MONITOR");
894 }
895 else {
896 packter_addstring(mesg, " Observed:");
897 }
898 packter_addfloat(mesg, mon_th);
899
900 /* PACKTERMESG for Thershold Variable */
901 if (packter_is_exist_key_str("THRESHOLD") == PACKTER_TRUE){
902 packter_addstring_hash(mesg, "THRESHOLD");
903 }
904 else {
905 packter_addstring(mesg, " Threshold:");
906 }
907 packter_addfloat(mesg, given_th);
908
909 /* PACKTERVOICE */
910 if (packter_is_exist_key_str(mon_voice) == PACKTER_TRUE){
911 packter_addstring_hash(voice, mon_voice);
912 }
913 return alert;
914 }
915
packter_sig_handler(int sig)916 void packter_sig_handler(int sig){
917 switch(sig){
918 case SIGHUP:
919 g_hash_table_destroy(config);
920 config = g_hash_table_new((GHashFunc)g_str_hash, (GCompareFunc)g_str_equal);
921 if (packter_config_parse(configfile) < 0){
922 printf("reload configfile failed\n");
923 }
924 else {
925 printf("reload configfile succeeded\n");
926 }
927 break;
928 default:
929 break;
930 }
931 return;
932 }
933