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