xref: /NextBSD/contrib/ipfilter/tools/ipmon.c (revision e1dd16d965b177f109afb771e59432e36f335d0a)
1 /*	$FreeBSD$	*/
2 
3 /*
4  * Copyright (C) 2012 by Darren Reed.
5  *
6  * See the IPFILTER.LICENCE file for details on licencing.
7  */
8 #include "ipf.h"
9 #include "ipmon.h"
10 #include <sys/ioctl.h>
11 #include <sys/stat.h>
12 #include <syslog.h>
13 #include <ctype.h>
14 #include <fcntl.h>
15 #include <signal.h>
16 
17 #if !defined(lint)
18 static const char sccsid[] = "@(#)ipmon.c	1.21 6/5/96 (C)1993-2000 Darren Reed";
19 static const char rcsid[] = "@(#)$Id$";
20 #endif
21 
22 
23 #if	defined(sun) && !defined(SOLARIS2)
24 #define	STRERROR(x)	sys_errlist[x]
25 extern	char	*sys_errlist[];
26 #else
27 #define	STRERROR(x)	strerror(x)
28 #endif
29 
30 extern	int	optind;
31 extern	char	*optarg;
32 
33 extern	ipmon_saver_t	executesaver;
34 extern	ipmon_saver_t	filesaver;
35 extern	ipmon_saver_t	nothingsaver;
36 extern	ipmon_saver_t	snmpv1saver;
37 extern	ipmon_saver_t	snmpv2saver;
38 extern	ipmon_saver_t	syslogsaver;
39 
40 
41 struct	flags {
42 	int	value;
43 	char	flag;
44 };
45 
46 typedef	struct	logsource {
47 	int	fd;
48 	int	logtype;
49 	char	*file;
50 	int	regular;
51 	size_t	size;
52 } logsource_t;
53 
54 typedef struct config {
55 	int		opts;
56 	int		maxfd;
57 	logsource_t	logsrc[3];
58 	fd_set		fdmr;
59 	FILE		*blog;
60 	char		*bfile;
61 	FILE		*log;
62 	char		*file;
63 	char		*cfile;
64 } config_t;
65 
66 typedef	struct	icmp_subtype {
67 	int	ist_val;
68 	char	*ist_name;
69 } icmp_subtype_t;
70 
71 typedef	struct	icmp_type {
72 	int	it_val;
73 	struct	icmp_subtype *it_subtable;
74 	size_t	it_stsize;
75 	char	*it_name;
76 } icmp_type_t;
77 
78 
79 #define	IST_SZ(x)	(sizeof(x)/sizeof(icmp_subtype_t))
80 
81 
82 struct	flags	tcpfl[] = {
83 	{ TH_ACK, 'A' },
84 	{ TH_RST, 'R' },
85 	{ TH_SYN, 'S' },
86 	{ TH_FIN, 'F' },
87 	{ TH_URG, 'U' },
88 	{ TH_PUSH,'P' },
89 	{ TH_ECN, 'E' },
90 	{ TH_CWR, 'C' },
91 	{ 0, '\0' }
92 };
93 
94 char *reasons[] = {
95 	"filter-rule",
96 	"log-or-block_1",
97 	"pps-rate",
98 	"jumbogram",
99 	"makefrip-fail",
100 	"state_add-fail",
101 	"updateipid-fail",
102 	"log-or-block_2",
103 	"decap-fail",
104 	"auth_new-fail",
105 	"auth_captured",
106 	"coalesce-fail",
107 	"pullup-fail",
108 	"auth-feedback",
109 	"bad-frag",
110 	"natv4_out-fail",
111 	"natv4_in-fail",
112 	"natv6_out-fail",
113 	"natv6_in-fail",
114 };
115 
116 #ifdef	MENTAT
117 static	char	*pidfile = "/etc/opt/ipf/ipmon.pid";
118 #else
119 # if BSD >= 199306
120 static	char	*pidfile = "/var/run/ipmon.pid";
121 # else
122 static	char	*pidfile = "/etc/ipmon.pid";
123 # endif
124 #endif
125 
126 static	char	line[2048];
127 static	int	donehup = 0;
128 static	void	usage __P((char *));
129 static	void	handlehup __P((int));
130 static	void	flushlogs __P((char *, FILE *));
131 static	void	print_log __P((config_t *, logsource_t *, char *, int));
132 static	void	print_ipflog __P((config_t *, char *, int));
133 static	void	print_natlog __P((config_t *, char *, int));
134 static	void	print_statelog __P((config_t *, char *, int));
135 static	int	read_log __P((int, int *, char *, int));
136 static	void	write_pid __P((char *));
137 static	char	*icmpname __P((u_int, u_int));
138 static	char	*icmpname6 __P((u_int, u_int));
139 static	icmp_type_t *find_icmptype __P((int, icmp_type_t *, size_t));
140 static	icmp_subtype_t *find_icmpsubtype __P((int, icmp_subtype_t *, size_t));
141 #ifdef __hpux
142 static	struct	tm	*get_tm __P((u_32_t));
143 #else
144 static	struct	tm	*get_tm __P((time_t));
145 #endif
146 
147 char	*portlocalname __P((int, char *, u_int));
148 int	main __P((int, char *[]));
149 
150 static	void	logopts __P((int, char *));
151 static	void	init_tabs __P((void));
152 static	char	*getlocalproto __P((u_int));
153 static	void	openlogs __P((config_t *conf));
154 static	int	read_loginfo __P((config_t *conf));
155 static	void	initconfig __P((config_t *conf));
156 
157 static	char	**protocols = NULL;
158 static	char	**udp_ports = NULL;
159 static	char	**tcp_ports = NULL;
160 
161 
162 #define	HOSTNAMEV4(b)	hostname(AF_INET, (u_32_t *)&(b))
163 
164 #ifndef	LOGFAC
165 #define	LOGFAC	LOG_LOCAL0
166 #endif
167 int	logfac = LOGFAC;
168 int	ipmonopts = 0;
169 int	opts = OPT_NORESOLVE;
170 int	use_inet6 = 0;
171 
172 
173 static icmp_subtype_t icmpunreachnames[] = {
174 	{ ICMP_UNREACH_NET,		"net" },
175 	{ ICMP_UNREACH_HOST,		"host" },
176 	{ ICMP_UNREACH_PROTOCOL,	"protocol" },
177 	{ ICMP_UNREACH_PORT,		"port" },
178 	{ ICMP_UNREACH_NEEDFRAG,	"needfrag" },
179 	{ ICMP_UNREACH_SRCFAIL,		"srcfail" },
180 	{ ICMP_UNREACH_NET_UNKNOWN,	"net_unknown" },
181 	{ ICMP_UNREACH_HOST_UNKNOWN,	"host_unknown" },
182 	{ ICMP_UNREACH_NET,		"isolated" },
183 	{ ICMP_UNREACH_NET_PROHIB,	"net_prohib" },
184 	{ ICMP_UNREACH_NET_PROHIB,	"host_prohib" },
185 	{ ICMP_UNREACH_TOSNET,		"tosnet" },
186 	{ ICMP_UNREACH_TOSHOST,		"toshost" },
187 	{ ICMP_UNREACH_ADMIN_PROHIBIT,	"admin_prohibit" },
188 	{ -2,				NULL }
189 };
190 
191 static icmp_subtype_t redirectnames[] = {
192 	{ ICMP_REDIRECT_NET,		"net" },
193 	{ ICMP_REDIRECT_HOST,		"host" },
194 	{ ICMP_REDIRECT_TOSNET,		"tosnet" },
195 	{ ICMP_REDIRECT_TOSHOST,	"toshost" },
196 	{ -2,				NULL }
197 };
198 
199 static icmp_subtype_t timxceednames[] = {
200 	{ ICMP_TIMXCEED_INTRANS,	"transit" },
201 	{ ICMP_TIMXCEED_REASS,		"reassem" },
202 	{ -2,				NULL }
203 };
204 
205 static icmp_subtype_t paramnames[] = {
206 	{ ICMP_PARAMPROB_ERRATPTR,	"errata_pointer" },
207 	{ ICMP_PARAMPROB_OPTABSENT,	"optmissing" },
208 	{ ICMP_PARAMPROB_LENGTH,	"length" },
209 	{ -2,				NULL }
210 };
211 
212 static icmp_type_t icmptypes4[] = {
213 	{ ICMP_ECHOREPLY,	NULL,	0,		"echoreply" },
214 	{ -1,			NULL,	0,		NULL },
215 	{ -1,			NULL,	0,		NULL },
216 	{ ICMP_UNREACH,		icmpunreachnames,
217 				IST_SZ(icmpunreachnames),"unreach" },
218 	{ ICMP_SOURCEQUENCH,	NULL,	0,		"sourcequench" },
219 	{ ICMP_REDIRECT,	redirectnames,
220 				IST_SZ(redirectnames),	"redirect" },
221 	{ -1,			NULL,	0,		NULL },
222 	{ -1,			NULL,	0,		NULL },
223 	{ ICMP_ECHO,		NULL,	0,		"echo" },
224 	{ ICMP_ROUTERADVERT,	NULL,	0,		"routeradvert" },
225 	{ ICMP_ROUTERSOLICIT,	NULL,	0,		"routersolicit" },
226 	{ ICMP_TIMXCEED,	timxceednames,
227 				IST_SZ(timxceednames),	"timxceed" },
228 	{ ICMP_PARAMPROB,	paramnames,
229 				IST_SZ(paramnames),	"paramprob" },
230 	{ ICMP_TSTAMP,		NULL,	0,		"timestamp" },
231 	{ ICMP_TSTAMPREPLY,	NULL,	0,		"timestampreply" },
232 	{ ICMP_IREQ,		NULL,	0,		"inforeq" },
233 	{ ICMP_IREQREPLY,	NULL,	0,		"inforeply" },
234 	{ ICMP_MASKREQ,		NULL,	0,		"maskreq" },
235 	{ ICMP_MASKREPLY,	NULL,	0,		"maskreply" },
236 	{ -2,			NULL,	0,		NULL }
237 };
238 
239 static icmp_subtype_t icmpredirect6[] = {
240 	{ ICMP6_DST_UNREACH_NOROUTE,		"noroute" },
241 	{ ICMP6_DST_UNREACH_ADMIN,		"admin" },
242 	{ ICMP6_DST_UNREACH_NOTNEIGHBOR,	"neighbour" },
243 	{ ICMP6_DST_UNREACH_ADDR,		"address" },
244 	{ ICMP6_DST_UNREACH_NOPORT,		"noport" },
245 	{ -2,					NULL }
246 };
247 
248 static icmp_subtype_t icmptimexceed6[] = {
249 	{ ICMP6_TIME_EXCEED_TRANSIT,		"intransit" },
250 	{ ICMP6_TIME_EXCEED_REASSEMBLY,		"reassem" },
251 	{ -2,					NULL }
252 };
253 
254 static icmp_subtype_t icmpparamprob6[] = {
255 	{ ICMP6_PARAMPROB_HEADER,		"header" },
256 	{ ICMP6_PARAMPROB_NEXTHEADER,		"nextheader" },
257 	{ ICMP6_PARAMPROB_OPTION,		"option" },
258 	{ -2,					NULL }
259 };
260 
261 static icmp_subtype_t icmpquerysubject6[] = {
262 	{ ICMP6_NI_SUBJ_IPV6,			"ipv6" },
263 	{ ICMP6_NI_SUBJ_FQDN,			"fqdn" },
264 	{ ICMP6_NI_SUBJ_IPV4,			"ipv4" },
265 	{ -2,					NULL },
266 };
267 
268 static icmp_subtype_t icmpnodeinfo6[] = {
269 	{ ICMP6_NI_SUCCESS,			"success" },
270 	{ ICMP6_NI_REFUSED,			"refused" },
271 	{ ICMP6_NI_UNKNOWN,			"unknown" },
272 	{ -2,					NULL }
273 };
274 
275 static icmp_subtype_t icmprenumber6[] = {
276 	{ ICMP6_ROUTER_RENUMBERING_COMMAND,		"command" },
277 	{ ICMP6_ROUTER_RENUMBERING_RESULT,		"result" },
278 	{ ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET,	"seqnum_reset" },
279 	{ -2,						NULL }
280 };
281 
282 static icmp_type_t icmptypes6[] = {
283 	{ 0,			NULL,	0,		NULL },
284 	{ ICMP6_DST_UNREACH,	icmpredirect6,
285 			IST_SZ(icmpredirect6),		"unreach" },
286 	{ ICMP6_PACKET_TOO_BIG,	NULL,	0,		"toobig" },
287 	{ ICMP6_TIME_EXCEEDED,	icmptimexceed6,
288 			IST_SZ(icmptimexceed6),		"timxceed" },
289 	{ ICMP6_PARAM_PROB,	icmpparamprob6,
290 			IST_SZ(icmpparamprob6),		"paramprob" },
291 	{ ICMP6_ECHO_REQUEST,	NULL,	0,		"echo" },
292 	{ ICMP6_ECHO_REPLY,	NULL,	0,		"echoreply" },
293 	{ ICMP6_MEMBERSHIP_QUERY, icmpquerysubject6,
294 			IST_SZ(icmpquerysubject6),	"groupmemberquery" },
295 	{ ICMP6_MEMBERSHIP_REPORT,NULL,	0,		"groupmemberreport" },
296 	{ ICMP6_MEMBERSHIP_REDUCTION,NULL,	0,	"groupmemberterm" },
297 	{ ND_ROUTER_SOLICIT,	NULL,	0,		"routersolicit" },
298 	{ ND_ROUTER_ADVERT,	NULL,	0,		"routeradvert" },
299 	{ ND_NEIGHBOR_SOLICIT,	NULL,	0,		"neighborsolicit" },
300 	{ ND_NEIGHBOR_ADVERT,	NULL,	0,		"neighboradvert" },
301 	{ ND_REDIRECT,		NULL,	0,		"redirect" },
302 	{ ICMP6_ROUTER_RENUMBERING,	icmprenumber6,
303 			IST_SZ(icmprenumber6),		"routerrenumber" },
304 	{ ICMP6_WRUREQUEST,	NULL,	0,		"whoareyourequest" },
305 	{ ICMP6_WRUREPLY,	NULL,	0,		"whoareyoureply" },
306 	{ ICMP6_FQDN_QUERY,	NULL,	0,		"fqdnquery" },
307 	{ ICMP6_FQDN_REPLY,	NULL,	0,		"fqdnreply" },
308 	{ ICMP6_NI_QUERY,	icmpnodeinfo6,
309 			IST_SZ(icmpnodeinfo6),		"nodeinforequest" },
310 	{ ICMP6_NI_REPLY,	NULL,	0,		"nodeinforeply" },
311 	{ MLD6_MTRACE_RESP,	NULL,	0,		"mtraceresponse" },
312 	{ MLD6_MTRACE,		NULL,	0,		"mtracerequest" },
313 	{ -2,			NULL,	0,		NULL }
314 };
315 
find_icmpsubtype(type,table,tablesz)316 static icmp_subtype_t *find_icmpsubtype(type, table, tablesz)
317 	int type;
318 	icmp_subtype_t *table;
319 	size_t tablesz;
320 {
321 	icmp_subtype_t *ist;
322 	int i;
323 
324 	if (tablesz < 2)
325 		return NULL;
326 
327 	if ((type < 0) || (type > table[tablesz - 2].ist_val))
328 		return NULL;
329 
330 	i = type;
331 	if (table[type].ist_val == type)
332 		return table + type;
333 
334 	for (i = 0, ist = table; ist->ist_val != -2; i++, ist++)
335 		if (ist->ist_val == type)
336 			return ist;
337 	return NULL;
338 }
339 
340 
find_icmptype(type,table,tablesz)341 static icmp_type_t *find_icmptype(type, table, tablesz)
342 	int type;
343 	icmp_type_t *table;
344 	size_t tablesz;
345 {
346 	icmp_type_t *it;
347 	int i;
348 
349 	if (tablesz < 2)
350 		return NULL;
351 
352 	if ((type < 0) || (type > table[tablesz - 2].it_val))
353 		return NULL;
354 
355 	i = type;
356 	if (table[type].it_val == type)
357 		return table + type;
358 
359 	for (i = 0, it = table; it->it_val != -2; i++, it++)
360 		if (it->it_val == type)
361 			return it;
362 	return NULL;
363 }
364 
365 
handlehup(sig)366 static void handlehup(sig)
367 	int sig;
368 {
369 	signal(SIGHUP, handlehup);
370 	donehup = 1;
371 }
372 
373 
init_tabs()374 static void init_tabs()
375 {
376 	struct	protoent	*p;
377 	struct	servent	*s;
378 	char	*name, **tab;
379 	int	port, i;
380 
381 	if (protocols != NULL) {
382 		for (i = 0; i < 256; i++)
383 			if (protocols[i] != NULL) {
384 				free(protocols[i]);
385 				protocols[i] = NULL;
386 			}
387 		free(protocols);
388 		protocols = NULL;
389 	}
390 	protocols = (char **)malloc(256 * sizeof(*protocols));
391 	if (protocols != NULL) {
392 		bzero((char *)protocols, 256 * sizeof(*protocols));
393 
394 		setprotoent(1);
395 		while ((p = getprotoent()) != NULL)
396 			if (p->p_proto >= 0 && p->p_proto <= 255 &&
397 			    p->p_name != NULL && protocols[p->p_proto] == NULL)
398 				protocols[p->p_proto] = strdup(p->p_name);
399 		endprotoent();
400 		if (protocols[0])
401 			free(protocols[0]);
402 		protocols[0] = strdup("ip");
403 #if defined(_AIX51)
404 		if (protocols[252])
405 			free(protocols[252]);
406 		protocols[252] = NULL;
407 #endif
408 	}
409 
410 	if (udp_ports != NULL) {
411 		for (i = 0; i < 65536; i++)
412 			if (udp_ports[i] != NULL) {
413 				free(udp_ports[i]);
414 				udp_ports[i] = NULL;
415 			}
416 		free(udp_ports);
417 		udp_ports = NULL;
418 	}
419 	udp_ports = (char **)malloc(65536 * sizeof(*udp_ports));
420 	if (udp_ports != NULL)
421 		bzero((char *)udp_ports, 65536 * sizeof(*udp_ports));
422 
423 	if (tcp_ports != NULL) {
424 		for (i = 0; i < 65536; i++)
425 			if (tcp_ports[i] != NULL) {
426 				free(tcp_ports[i]);
427 				tcp_ports[i] = NULL;
428 			}
429 		free(tcp_ports);
430 		tcp_ports = NULL;
431 	}
432 	tcp_ports = (char **)malloc(65536 * sizeof(*tcp_ports));
433 	if (tcp_ports != NULL)
434 		bzero((char *)tcp_ports, 65536 * sizeof(*tcp_ports));
435 
436 	setservent(1);
437 	while ((s = getservent()) != NULL) {
438 		if (s->s_proto == NULL)
439 			continue;
440 		else if (!strcmp(s->s_proto, "tcp")) {
441 			port = ntohs(s->s_port);
442 			name = s->s_name;
443 			tab = tcp_ports;
444 		} else if (!strcmp(s->s_proto, "udp")) {
445 			port = ntohs(s->s_port);
446 			name = s->s_name;
447 			tab = udp_ports;
448 		} else
449 			continue;
450 		if ((port < 0 || port > 65535) || (name == NULL))
451 			continue;
452 		if (tab != NULL)
453 			tab[port] = strdup(name);
454 	}
455 	endservent();
456 }
457 
458 
getlocalproto(p)459 static char *getlocalproto(p)
460 	u_int p;
461 {
462 	static char pnum[4];
463 	char *s;
464 
465 	p &= 0xff;
466 	s = protocols ? protocols[p] : NULL;
467 	if (s == NULL) {
468 		sprintf(pnum, "%u", p);
469 		s = pnum;
470 	}
471 	return s;
472 }
473 
474 
read_log(fd,lenp,buf,bufsize)475 static int read_log(fd, lenp, buf, bufsize)
476 	int fd, bufsize, *lenp;
477 	char *buf;
478 {
479 	int	nr;
480 
481 	if (bufsize > IPFILTER_LOGSIZE)
482 		bufsize = IPFILTER_LOGSIZE;
483 
484 	nr = read(fd, buf, bufsize);
485 	if (!nr)
486 		return 2;
487 	if ((nr < 0) && (errno != EINTR))
488 		return -1;
489 	*lenp = nr;
490 	return 0;
491 }
492 
493 
portlocalname(res,proto,port)494 char *portlocalname(res, proto, port)
495 	int res;
496 	char *proto;
497 	u_int port;
498 {
499 	static char pname[8];
500 	char *s;
501 
502 	port = ntohs(port);
503 	port &= 0xffff;
504 	sprintf(pname, "%u", port);
505 	if (!res || (ipmonopts & IPMON_PORTNUM))
506 		return pname;
507 	s = NULL;
508 	if (!strcmp(proto, "tcp"))
509 		s = tcp_ports[port];
510 	else if (!strcmp(proto, "udp"))
511 		s = udp_ports[port];
512 	if (s == NULL)
513 		s = pname;
514 	return s;
515 }
516 
517 
icmpname(type,code)518 static char *icmpname(type, code)
519 	u_int type;
520 	u_int code;
521 {
522 	static char name[80];
523 	icmp_subtype_t *ist;
524 	icmp_type_t *it;
525 	char *s;
526 
527 	s = NULL;
528 	it = find_icmptype(type, icmptypes4, sizeof(icmptypes4) / sizeof(*it));
529 	if (it != NULL)
530 		s = it->it_name;
531 
532 	if (s == NULL)
533 		sprintf(name, "icmptype(%d)/", type);
534 	else
535 		sprintf(name, "%s/", s);
536 
537 	ist = NULL;
538 	if (it != NULL && it->it_subtable != NULL)
539 		ist = find_icmpsubtype(code, it->it_subtable, it->it_stsize);
540 
541 	if (ist != NULL && ist->ist_name != NULL)
542 		strcat(name, ist->ist_name);
543 	else
544 		sprintf(name + strlen(name), "%d", code);
545 
546 	return name;
547 }
548 
icmpname6(type,code)549 static char *icmpname6(type, code)
550 	u_int type;
551 	u_int code;
552 {
553 	static char name[80];
554 	icmp_subtype_t *ist;
555 	icmp_type_t *it;
556 	char *s;
557 
558 	s = NULL;
559 	it = find_icmptype(type, icmptypes6, sizeof(icmptypes6) / sizeof(*it));
560 	if (it != NULL)
561 		s = it->it_name;
562 
563 	if (s == NULL)
564 		sprintf(name, "icmpv6type(%d)/", type);
565 	else
566 		sprintf(name, "%s/", s);
567 
568 	ist = NULL;
569 	if (it != NULL && it->it_subtable != NULL)
570 		ist = find_icmpsubtype(code, it->it_subtable, it->it_stsize);
571 
572 	if (ist != NULL && ist->ist_name != NULL)
573 		strcat(name, ist->ist_name);
574 	else
575 		sprintf(name + strlen(name), "%d", code);
576 
577 	return name;
578 }
579 
580 
dumphex(log,dopts,buf,len)581 void dumphex(log, dopts, buf, len)
582 	FILE *log;
583 	int dopts;
584 	char *buf;
585 	int len;
586 {
587 	char	hline[80];
588 	int	i, j, k;
589 	u_char	*s = (u_char *)buf, *t = (u_char *)hline;
590 
591 	if (buf == NULL || len == 0)
592 		return;
593 
594 	*hline = '\0';
595 
596 	for (i = len, j = 0; i; i--, j++, s++) {
597 		if (j && !(j & 0xf)) {
598 			*t++ = '\n';
599 			*t = '\0';
600 			if ((dopts & IPMON_SYSLOG))
601 				syslog(LOG_INFO, "%s", hline);
602 			else if (log != NULL)
603 				fputs(hline, log);
604 			t = (u_char *)hline;
605 			*t = '\0';
606 		}
607 		sprintf((char *)t, "%02x", *s & 0xff);
608 		t += 2;
609 		if (!((j + 1) & 0xf)) {
610 			s -= 15;
611 			sprintf((char *)t, "        ");
612 			t += 8;
613 			for (k = 16; k; k--, s++)
614 				*t++ = (isprint(*s) ? *s : '.');
615 			s--;
616 		}
617 
618 		if ((j + 1) & 0xf)
619 			*t++ = ' ';;
620 	}
621 
622 	if (j & 0xf) {
623 		for (k = 16 - (j & 0xf); k; k--) {
624 			*t++ = ' ';
625 			*t++ = ' ';
626 			*t++ = ' ';
627 		}
628 		sprintf((char *)t, "       ");
629 		t += 7;
630 		s -= j & 0xf;
631 		for (k = j & 0xf; k; k--, s++)
632 			*t++ = (isprint(*s) ? *s : '.');
633 		*t++ = '\n';
634 		*t = '\0';
635 	}
636 	if ((dopts & IPMON_SYSLOG) != 0)
637 		syslog(LOG_INFO, "%s", hline);
638 	else if (log != NULL) {
639 		fputs(hline, log);
640 		fflush(log);
641 	}
642 }
643 
644 
get_tm(sec)645 static struct tm *get_tm(sec)
646 #ifdef __hpux
647 	u_32_t sec;
648 #else
649 	time_t sec;
650 #endif
651 {
652 	struct tm *tm;
653 	time_t t;
654 
655 	t = sec;
656 	tm = localtime(&t);
657 	return tm;
658 }
659 
print_natlog(conf,buf,blen)660 static void print_natlog(conf, buf, blen)
661 	config_t *conf;
662 	char *buf;
663 	int blen;
664 {
665 	static u_32_t seqnum = 0;
666 	int res, i, len, family;
667 	struct natlog *nl;
668 	struct tm *tm;
669 	iplog_t	*ipl;
670 	char *proto;
671 	int simple;
672 	char *t;
673 
674 	t = line;
675 	simple = 0;
676 	ipl = (iplog_t *)buf;
677 	if (ipl->ipl_seqnum != seqnum) {
678 		if ((ipmonopts & IPMON_SYSLOG) != 0) {
679 			syslog(LOG_WARNING,
680 			       "missed %u NAT log entries: %u %u",
681 			       ipl->ipl_seqnum - seqnum, seqnum,
682 			       ipl->ipl_seqnum);
683 		} else {
684 			(void) fprintf(conf->log,
685 				"missed %u NAT log entries: %u %u\n",
686 			       ipl->ipl_seqnum - seqnum, seqnum,
687 			       ipl->ipl_seqnum);
688 		}
689 	}
690 	seqnum = ipl->ipl_seqnum + ipl->ipl_count;
691 
692 	nl = (struct natlog *)((char *)ipl + sizeof(*ipl));
693 	res = (ipmonopts & IPMON_RESOLVE) ? 1 : 0;
694 	tm = get_tm(ipl->ipl_sec);
695 	len = sizeof(line);
696 
697 	if (!(ipmonopts & IPMON_SYSLOG)) {
698 		(void) strftime(t, len, "%d/%m/%Y ", tm);
699 		i = strlen(t);
700 		len -= i;
701 		t += i;
702 	}
703 	(void) strftime(t, len, "%T", tm);
704 	t += strlen(t);
705 	sprintf(t, ".%-.6ld @%hd ", (long)ipl->ipl_usec, nl->nl_rule + 1);
706 	t += strlen(t);
707 
708 	switch (nl->nl_action)
709 	{
710 	case NL_NEW :
711 		strcpy(t, "NAT:NEW");
712 		break;
713 
714 	case NL_FLUSH :
715 		strcpy(t, "NAT:FLUSH");
716 		break;
717 
718 	case NL_CLONE :
719 		strcpy(t, "NAT:CLONE");
720 		break;
721 
722 	case NL_EXPIRE :
723 		strcpy(t, "NAT:EXPIRE");
724 		break;
725 
726 	case NL_DESTROY :
727 		strcpy(t, "NAT:DESTROY");
728 		break;
729 
730 	case NL_PURGE :
731 		strcpy(t, "NAT:PURGE");
732 		break;
733 
734 	default :
735 		sprintf(t, "NAT:Action(%d)", nl->nl_action);
736 		break;
737 	}
738 	t += strlen(t);
739 
740 
741 	switch (nl->nl_type)
742 	{
743 	case NAT_MAP :
744 		strcpy(t, "-MAP ");
745 		simple = 1;
746 		break;
747 
748 	case NAT_REDIRECT :
749 		strcpy(t, "-RDR ");
750 		simple = 1;
751 		break;
752 
753 	case NAT_BIMAP :
754 		strcpy(t, "-BIMAP ");
755 		simple = 1;
756 		break;
757 
758 	case NAT_MAPBLK :
759 		strcpy(t, "-MAPBLOCK ");
760 		simple = 1;
761 		break;
762 
763 	case NAT_REWRITE|NAT_MAP :
764 		strcpy(t, "-RWR_MAP ");
765 		break;
766 
767 	case NAT_REWRITE|NAT_REDIRECT :
768 		strcpy(t, "-RWR_RDR ");
769 		break;
770 
771 	case NAT_ENCAP|NAT_MAP :
772 		strcpy(t, "-ENC_MAP ");
773 		break;
774 
775 	case NAT_ENCAP|NAT_REDIRECT :
776 		strcpy(t, "-ENC_RDR ");
777 		break;
778 
779 	case NAT_DIVERTUDP|NAT_MAP :
780 		strcpy(t, "-DIV_MAP ");
781 		break;
782 
783 	case NAT_DIVERTUDP|NAT_REDIRECT :
784 		strcpy(t, "-DIV_RDR ");
785 		break;
786 
787 	default :
788 		sprintf(t, "-Type(%d) ", nl->nl_type);
789 		break;
790 	}
791 	t += strlen(t);
792 
793 	proto = getlocalproto(nl->nl_p[0]);
794 
795 	family = vtof(nl->nl_v[0]);
796 
797 	if (simple == 1) {
798 		sprintf(t, "%s,%s <- -> ", hostname(family, nl->nl_osrcip.i6),
799 			portlocalname(res, proto, (u_int)nl->nl_osrcport));
800 		t += strlen(t);
801 		sprintf(t, "%s,%s ", hostname(family, nl->nl_nsrcip.i6),
802 			portlocalname(res, proto, (u_int)nl->nl_nsrcport));
803 		t += strlen(t);
804 		sprintf(t, "[%s,%s] ", hostname(family, nl->nl_odstip.i6),
805 			portlocalname(res, proto, (u_int)nl->nl_odstport));
806 	} else {
807 		sprintf(t, "%s,%s ", hostname(family, nl->nl_osrcip.i6),
808 			portlocalname(res, proto, (u_int)nl->nl_osrcport));
809 		t += strlen(t);
810 		sprintf(t, "%s,%s <- -> ", hostname(family, nl->nl_odstip.i6),
811 			portlocalname(res, proto, (u_int)nl->nl_odstport));
812 		t += strlen(t);
813 		sprintf(t, "%s,%s ", hostname(family, nl->nl_nsrcip.i6),
814 			portlocalname(res, proto, (u_int)nl->nl_nsrcport));
815 		t += strlen(t);
816 		sprintf(t, "%s,%s ", hostname(family, nl->nl_ndstip.i6),
817 			portlocalname(res, proto, (u_int)nl->nl_ndstport));
818 	}
819 	t += strlen(t);
820 
821 	strcpy(t, getlocalproto(nl->nl_p[0]));
822 	t += strlen(t);
823 
824 	if (nl->nl_action == NL_EXPIRE || nl->nl_action == NL_FLUSH) {
825 #ifdef	USE_QUAD_T
826 # ifdef	PRId64
827 		sprintf(t, " Pkts %" PRId64 "/%" PRId64 " Bytes %" PRId64 "/%"
828 			PRId64,
829 # else
830 		sprintf(t, " Pkts %qd/%qd Bytes %qd/%qd",
831 # endif
832 #else
833 		sprintf(t, " Pkts %ld/%ld Bytes %ld/%ld",
834 #endif
835 				nl->nl_pkts[0], nl->nl_pkts[1],
836 				nl->nl_bytes[0], nl->nl_bytes[1]);
837 		t += strlen(t);
838 	}
839 
840 	*t++ = '\n';
841 	*t++ = '\0';
842 	if (ipmonopts & IPMON_SYSLOG)
843 		syslog(LOG_INFO, "%s", line);
844 	else if (conf->log != NULL)
845 		(void) fprintf(conf->log, "%s", line);
846 }
847 
848 
print_statelog(conf,buf,blen)849 static void print_statelog(conf, buf, blen)
850 	config_t *conf;
851 	char *buf;
852 	int blen;
853 {
854 	static u_32_t seqnum = 0;
855 	int res, i, len, family;
856 	struct ipslog *sl;
857 	char *t, *proto;
858 	struct tm *tm;
859 	iplog_t *ipl;
860 
861 	t = line;
862 	ipl = (iplog_t *)buf;
863 	if (ipl->ipl_seqnum != seqnum) {
864 		if ((ipmonopts & IPMON_SYSLOG) != 0) {
865 			syslog(LOG_WARNING,
866 			       "missed %u state log entries: %u %u",
867 			       ipl->ipl_seqnum - seqnum, seqnum,
868 			       ipl->ipl_seqnum);
869 		} else {
870 			(void) fprintf(conf->log,
871 				"missed %u state log entries: %u %u\n",
872 			       ipl->ipl_seqnum - seqnum, seqnum,
873 			       ipl->ipl_seqnum);
874 		}
875 	}
876 	seqnum = ipl->ipl_seqnum + ipl->ipl_count;
877 
878 	sl = (struct ipslog *)((char *)ipl + sizeof(*ipl));
879 	res = (ipmonopts & IPMON_RESOLVE) ? 1 : 0;
880 	tm = get_tm(ipl->ipl_sec);
881 	len = sizeof(line);
882 	if (!(ipmonopts & IPMON_SYSLOG)) {
883 		(void) strftime(t, len, "%d/%m/%Y ", tm);
884 		i = strlen(t);
885 		len -= i;
886 		t += i;
887 	}
888 	(void) strftime(t, len, "%T", tm);
889 	t += strlen(t);
890 	sprintf(t, ".%-.6ld ", (long)ipl->ipl_usec);
891 	t += strlen(t);
892 
893 	family = vtof(sl->isl_v);
894 
895 	switch (sl->isl_type)
896 	{
897 	case ISL_NEW :
898 		strcpy(t, "STATE:NEW ");
899 		break;
900 
901 	case ISL_CLONE :
902 		strcpy(t, "STATE:CLONED ");
903 		break;
904 
905 	case ISL_EXPIRE :
906 		if ((sl->isl_p == IPPROTO_TCP) &&
907 		    (sl->isl_state[0] > IPF_TCPS_ESTABLISHED ||
908 		     sl->isl_state[1] > IPF_TCPS_ESTABLISHED))
909 			strcpy(t, "STATE:CLOSE ");
910 		else
911 			strcpy(t, "STATE:EXPIRE ");
912 		break;
913 
914 	case ISL_FLUSH :
915 		strcpy(t, "STATE:FLUSH ");
916 		break;
917 
918 	case ISL_INTERMEDIATE :
919 		strcpy(t, "STATE:INTERMEDIATE ");
920 		break;
921 
922 	case ISL_REMOVE :
923 		strcpy(t, "STATE:REMOVE ");
924 		break;
925 
926 	case ISL_KILLED :
927 		strcpy(t, "STATE:KILLED ");
928 		break;
929 
930 	case ISL_UNLOAD :
931 		strcpy(t, "STATE:UNLOAD ");
932 		break;
933 
934 	default :
935 		sprintf(t, "Type: %d ", sl->isl_type);
936 		break;
937 	}
938 	t += strlen(t);
939 
940 	proto = getlocalproto(sl->isl_p);
941 
942 	if (sl->isl_p == IPPROTO_TCP || sl->isl_p == IPPROTO_UDP) {
943 		sprintf(t, "%s,%s -> ",
944 			hostname(family, (u_32_t *)&sl->isl_src),
945 			portlocalname(res, proto, (u_int)sl->isl_sport));
946 		t += strlen(t);
947 		sprintf(t, "%s,%s PR %s",
948 			hostname(family, (u_32_t *)&sl->isl_dst),
949 			portlocalname(res, proto, (u_int)sl->isl_dport), proto);
950 	} else if (sl->isl_p == IPPROTO_ICMP) {
951 		sprintf(t, "%s -> ", hostname(family, (u_32_t *)&sl->isl_src));
952 		t += strlen(t);
953 		sprintf(t, "%s PR icmp %d",
954 			hostname(family, (u_32_t *)&sl->isl_dst),
955 			sl->isl_itype);
956 	} else if (sl->isl_p == IPPROTO_ICMPV6) {
957 		sprintf(t, "%s -> ", hostname(family, (u_32_t *)&sl->isl_src));
958 		t += strlen(t);
959 		sprintf(t, "%s PR icmpv6 %d",
960 			hostname(family, (u_32_t *)&sl->isl_dst),
961 			sl->isl_itype);
962 	} else {
963 		sprintf(t, "%s -> ", hostname(family, (u_32_t *)&sl->isl_src));
964 		t += strlen(t);
965 		sprintf(t, "%s PR %s",
966 			hostname(family, (u_32_t *)&sl->isl_dst), proto);
967 	}
968 	t += strlen(t);
969 	if (sl->isl_tag != FR_NOLOGTAG) {
970 		sprintf(t, " tag %u", sl->isl_tag);
971 		t += strlen(t);
972 	}
973 	if (sl->isl_type != ISL_NEW) {
974 		sprintf(t,
975 #ifdef	USE_QUAD_T
976 #ifdef	PRId64
977 			" Forward: Pkts in %" PRId64 " Bytes in %" PRId64
978 			" Pkts out %" PRId64 " Bytes out %" PRId64
979 			" Backward: Pkts in %" PRId64 " Bytes in %" PRId64
980 			" Pkts out %" PRId64 " Bytes out %" PRId64,
981 #else
982 			" Forward: Pkts in %qd Bytes in %qd Pkts out %qd Bytes out %qd Backward: Pkts in %qd Bytes in %qd Pkts out %qd Bytes out %qd",
983 #endif /* PRId64 */
984 #else
985 			" Forward: Pkts in %ld Bytes in %ld Pkts out %ld Bytes out %ld Backward: Pkts in %ld Bytes in %ld Pkts out %ld Bytes out %ld",
986 #endif
987 			sl->isl_pkts[0], sl->isl_bytes[0],
988 			sl->isl_pkts[1], sl->isl_bytes[1],
989 			sl->isl_pkts[2], sl->isl_bytes[2],
990 			sl->isl_pkts[3], sl->isl_bytes[3]);
991 
992 		t += strlen(t);
993 	}
994 
995 	*t++ = '\n';
996 	*t++ = '\0';
997 	if (ipmonopts & IPMON_SYSLOG)
998 		syslog(LOG_INFO, "%s", line);
999 	else if (conf->log != NULL)
1000 		(void) fprintf(conf->log, "%s", line);
1001 }
1002 
1003 
print_log(conf,log,buf,blen)1004 static void print_log(conf, log, buf, blen)
1005 	config_t *conf;
1006 	logsource_t *log;
1007 	char *buf;
1008 	int blen;
1009 {
1010 	char *bp, *bpo;
1011 	iplog_t	*ipl;
1012 	int psize;
1013 
1014 	bp = NULL;
1015 	bpo = NULL;
1016 
1017 	while (blen > 0) {
1018 		ipl = (iplog_t *)buf;
1019 		if ((u_long)ipl & (sizeof(long)-1)) {
1020 			if (bp)
1021 				bpo = bp;
1022 			bp = (char *)malloc(blen);
1023 			bcopy((char *)ipl, bp, blen);
1024 			if (bpo) {
1025 				free(bpo);
1026 				bpo = NULL;
1027 			}
1028 			buf = bp;
1029 			continue;
1030 		}
1031 
1032 		psize = ipl->ipl_dsize;
1033 		if (psize > blen)
1034 			break;
1035 
1036 		if (conf->blog != NULL) {
1037 			fwrite(buf, psize, 1, conf->blog);
1038 			fflush(conf->blog);
1039 		}
1040 
1041 		if (log->logtype == IPL_LOGIPF) {
1042 			if (ipl->ipl_magic == IPL_MAGIC)
1043 				print_ipflog(conf, buf, psize);
1044 
1045 		} else if (log->logtype == IPL_LOGNAT) {
1046 			if (ipl->ipl_magic == IPL_MAGIC_NAT)
1047 				print_natlog(conf, buf, psize);
1048 
1049 		} else if (log->logtype == IPL_LOGSTATE) {
1050 			if (ipl->ipl_magic == IPL_MAGIC_STATE)
1051 				print_statelog(conf, buf, psize);
1052 		}
1053 
1054 		blen -= psize;
1055 		buf += psize;
1056 	}
1057 	if (bp)
1058 		free(bp);
1059 	return;
1060 }
1061 
1062 
print_ipflog(conf,buf,blen)1063 static void print_ipflog(conf, buf, blen)
1064 	config_t *conf;
1065 	char *buf;
1066 	int blen;
1067 {
1068 	static u_32_t seqnum = 0;
1069 	int i, f, lvl, res, len, off, plen, ipoff, defaction;
1070 	struct icmp *icmp;
1071 	struct icmp *ic;
1072 	char *t, *proto;
1073 	ip_t *ipc, *ip;
1074 	struct tm *tm;
1075 	u_32_t *s, *d;
1076 	u_short hl, p;
1077 	ipflog_t *ipf;
1078 	iplog_t *ipl;
1079 	tcphdr_t *tp;
1080 #ifdef	USE_INET6
1081 	struct ip6_ext *ehp;
1082 	u_short ehl;
1083 	ip6_t *ip6;
1084 	int go;
1085 #endif
1086 
1087 	ipl = (iplog_t *)buf;
1088 	if (ipl->ipl_seqnum != seqnum) {
1089 		if ((ipmonopts & IPMON_SYSLOG) != 0) {
1090 			syslog(LOG_WARNING,
1091 			       "missed %u ipf log entries: %u %u",
1092 			       ipl->ipl_seqnum - seqnum, seqnum,
1093 			       ipl->ipl_seqnum);
1094 		} else {
1095 			(void) fprintf(conf->log,
1096 				"missed %u ipf log entries: %u %u\n",
1097 			       ipl->ipl_seqnum - seqnum, seqnum,
1098 			       ipl->ipl_seqnum);
1099 		}
1100 	}
1101 	seqnum = ipl->ipl_seqnum + ipl->ipl_count;
1102 
1103 	ipf = (ipflog_t *)((char *)buf + sizeof(*ipl));
1104 	ip = (ip_t *)((char *)ipf + sizeof(*ipf));
1105 	f = ipf->fl_family;
1106 	res = (ipmonopts & IPMON_RESOLVE) ? 1 : 0;
1107 	t = line;
1108 	*t = '\0';
1109 	tm = get_tm(ipl->ipl_sec);
1110 
1111 	len = sizeof(line);
1112 	if (!(ipmonopts & IPMON_SYSLOG)) {
1113 		(void) strftime(t, len, "%d/%m/%Y ", tm);
1114 		i = strlen(t);
1115 		len -= i;
1116 		t += i;
1117 	}
1118 	(void) strftime(t, len, "%T", tm);
1119 	t += strlen(t);
1120 	sprintf(t, ".%-.6ld ", (long)ipl->ipl_usec);
1121 	t += strlen(t);
1122 	if (ipl->ipl_count > 1) {
1123 		sprintf(t, "%dx ", ipl->ipl_count);
1124 		t += strlen(t);
1125 	}
1126 #if (defined(MENTAT) || \
1127 	(defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \
1128 	(defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) || \
1129 	(defined(OpenBSD) && (OpenBSD >= 199603))) || defined(linux)
1130 	{
1131 	char	ifname[sizeof(ipf->fl_ifname) + 1];
1132 
1133 	strncpy(ifname, ipf->fl_ifname, sizeof(ipf->fl_ifname));
1134 	ifname[sizeof(ipf->fl_ifname)] = '\0';
1135 	sprintf(t, "%s", ifname);
1136 	t += strlen(t);
1137 # if defined(MENTAT) || defined(linux)
1138 #  if defined(linux)
1139 	/*
1140 	 * On Linux, the loopback interface is just "lo", not "lo0".
1141 	 */
1142 	if (strcmp(ifname, "lo") != 0)
1143 #  endif
1144 		if (ISALPHA(*(t - 1))) {
1145 			sprintf(t, "%d", ipf->fl_unit);
1146 			t += strlen(t);
1147 		}
1148 # endif
1149 	}
1150 #else
1151 	for (len = 0; len < 3; len++)
1152 		if (ipf->fl_ifname[len] == '\0')
1153 			break;
1154 	if (ipf->fl_ifname[len])
1155 		len++;
1156 	sprintf(t, "%*.*s%u", len, len, ipf->fl_ifname, ipf->fl_unit);
1157 	t += strlen(t);
1158 #endif
1159 	if ((ipf->fl_group[0] == (char)~0) && (ipf->fl_group[1] == '\0'))
1160 		strcat(t, " @-1:");
1161 	else if (ipf->fl_group[0] == '\0')
1162 		(void) strcpy(t, " @0:");
1163 	else
1164 		sprintf(t, " @%s:", ipf->fl_group);
1165 	t += strlen(t);
1166 	if (ipf->fl_rule == 0xffffffff)
1167 		strcat(t, "-1 ");
1168 	else
1169 		sprintf(t, "%u ", ipf->fl_rule + 1);
1170 	t += strlen(t);
1171 
1172 	lvl = LOG_NOTICE;
1173 
1174  	if (ipf->fl_lflags & FI_SHORT) {
1175 		*t++ = 'S';
1176 		lvl = LOG_ERR;
1177 	}
1178 
1179 	if (FR_ISPASS(ipf->fl_flags)) {
1180 		if (ipf->fl_flags & FR_LOGP)
1181 			*t++ = 'p';
1182 		else
1183 			*t++ = 'P';
1184 	} else if (FR_ISBLOCK(ipf->fl_flags)) {
1185 		if (ipf->fl_flags & FR_LOGB)
1186 			*t++ = 'b';
1187 		else
1188 			*t++ = 'B';
1189 		lvl = LOG_WARNING;
1190 	} else if ((ipf->fl_flags & FR_LOGMASK) == FR_LOG) {
1191 		*t++ = 'L';
1192 		lvl = LOG_INFO;
1193 	} else if (ipf->fl_flags & FF_LOGNOMATCH) {
1194 		*t++ = 'n';
1195 	} else {
1196 		*t++ = '?';
1197 		lvl = LOG_EMERG;
1198 	}
1199 	if (ipf->fl_loglevel != 0xffff)
1200 		lvl = ipf->fl_loglevel;
1201 	*t++ = ' ';
1202 	*t = '\0';
1203 
1204 	if (f == AF_INET) {
1205 		hl = IP_HL(ip) << 2;
1206 		ipoff = ntohs(ip->ip_off);
1207 		off = ipoff & IP_OFFMASK;
1208 		p = (u_short)ip->ip_p;
1209 		s = (u_32_t *)&ip->ip_src;
1210 		d = (u_32_t *)&ip->ip_dst;
1211 		plen = ntohs(ip->ip_len);
1212 	} else
1213 #ifdef	USE_INET6
1214 	if (f == AF_INET6) {
1215 		off = 0;
1216 		ipoff = 0;
1217 		hl = sizeof(ip6_t);
1218 		ip6 = (ip6_t *)ip;
1219 		p = (u_short)ip6->ip6_nxt;
1220 		s = (u_32_t *)&ip6->ip6_src;
1221 		d = (u_32_t *)&ip6->ip6_dst;
1222 		plen = hl + ntohs(ip6->ip6_plen);
1223 		go = 1;
1224 		ehp = (struct ip6_ext *)((char *)ip6 + hl);
1225 		while (go == 1) {
1226 			switch (p)
1227 			{
1228 			case IPPROTO_HOPOPTS :
1229 			case IPPROTO_MOBILITY :
1230 			case IPPROTO_DSTOPTS :
1231 			case IPPROTO_ROUTING :
1232 			case IPPROTO_AH :
1233 				p = ehp->ip6e_nxt;
1234 				ehl = 8 + (ehp->ip6e_len << 3);
1235 				hl += ehl;
1236 				ehp = (struct ip6_ext *)((char *)ehp + ehl);
1237 				break;
1238 			case IPPROTO_FRAGMENT :
1239 				hl += sizeof(struct ip6_frag);
1240 				/* FALLTHROUGH */
1241 			default :
1242 				go = 0;
1243 				break;
1244 			}
1245 		}
1246 	} else
1247 #endif
1248 	{
1249 		goto printipflog;
1250 	}
1251 	proto = getlocalproto(p);
1252 
1253 	if ((p == IPPROTO_TCP || p == IPPROTO_UDP) && !off) {
1254 		tp = (tcphdr_t *)((char *)ip + hl);
1255 		if (!(ipf->fl_lflags & FI_SHORT)) {
1256 			sprintf(t, "%s,%s -> ", hostname(f, s),
1257 				portlocalname(res, proto, (u_int)tp->th_sport));
1258 			t += strlen(t);
1259 			sprintf(t, "%s,%s PR %s len %hu %hu",
1260 				hostname(f, d),
1261 				portlocalname(res, proto, (u_int)tp->th_dport),
1262 				proto, hl, plen);
1263 			t += strlen(t);
1264 
1265 			if (p == IPPROTO_TCP) {
1266 				*t++ = ' ';
1267 				*t++ = '-';
1268 				for (i = 0; tcpfl[i].value; i++)
1269 					if (tp->th_flags & tcpfl[i].value)
1270 						*t++ = tcpfl[i].flag;
1271 				if (ipmonopts & IPMON_VERBOSE) {
1272 					sprintf(t, " %lu %lu %hu",
1273 						(u_long)(ntohl(tp->th_seq)),
1274 						(u_long)(ntohl(tp->th_ack)),
1275 						ntohs(tp->th_win));
1276 					t += strlen(t);
1277 				}
1278 			}
1279 			*t = '\0';
1280 		} else {
1281 			sprintf(t, "%s -> ", hostname(f, s));
1282 			t += strlen(t);
1283 			sprintf(t, "%s PR %s len %hu %hu",
1284 				hostname(f, d), proto, hl, plen);
1285 		}
1286 #if defined(AF_INET6) && defined(IPPROTO_ICMPV6)
1287 	} else if ((p == IPPROTO_ICMPV6) && !off && (f == AF_INET6)) {
1288 		ic = (struct icmp *)((char *)ip + hl);
1289 		sprintf(t, "%s -> ", hostname(f, s));
1290 		t += strlen(t);
1291 		sprintf(t, "%s PR icmpv6 len %hu %hu icmpv6 %s",
1292 			hostname(f, d), hl, plen,
1293 			icmpname6(ic->icmp_type, ic->icmp_code));
1294 #endif
1295 	} else if ((p == IPPROTO_ICMP) && !off && (f == AF_INET)) {
1296 		ic = (struct icmp *)((char *)ip + hl);
1297 		sprintf(t, "%s -> ", hostname(f, s));
1298 		t += strlen(t);
1299 		sprintf(t, "%s PR icmp len %hu %hu icmp %s",
1300 			hostname(f, d), hl, plen,
1301 			icmpname(ic->icmp_type, ic->icmp_code));
1302 		if (ic->icmp_type == ICMP_UNREACH ||
1303 		    ic->icmp_type == ICMP_SOURCEQUENCH ||
1304 		    ic->icmp_type == ICMP_PARAMPROB ||
1305 		    ic->icmp_type == ICMP_REDIRECT ||
1306 		    ic->icmp_type == ICMP_TIMXCEED) {
1307 			ipc = &ic->icmp_ip;
1308 			i = ntohs(ipc->ip_len);
1309 			/*
1310 			 * XXX - try to guess endian of ip_len in ICMP
1311 			 * returned data.
1312 			 */
1313 			if (i > 1500)
1314 				i = ipc->ip_len;
1315 			ipoff = ntohs(ipc->ip_off);
1316 			proto = getlocalproto(ipc->ip_p);
1317 
1318 			if (!(ipoff & IP_OFFMASK) &&
1319 			    ((ipc->ip_p == IPPROTO_TCP) ||
1320 			     (ipc->ip_p == IPPROTO_UDP))) {
1321 				tp = (tcphdr_t *)((char *)ipc + hl);
1322 				t += strlen(t);
1323 				sprintf(t, " for %s,%s -",
1324 					HOSTNAMEV4(ipc->ip_src),
1325 					portlocalname(res, proto,
1326 						 (u_int)tp->th_sport));
1327 				t += strlen(t);
1328 				sprintf(t, " %s,%s PR %s len %hu %hu",
1329 					HOSTNAMEV4(ipc->ip_dst),
1330 					portlocalname(res, proto,
1331 						 (u_int)tp->th_dport),
1332 					proto, IP_HL(ipc) << 2, i);
1333 			} else if (!(ipoff & IP_OFFMASK) &&
1334 				   (ipc->ip_p == IPPROTO_ICMP)) {
1335 				icmp = (icmphdr_t *)((char *)ipc + hl);
1336 
1337 				t += strlen(t);
1338 				sprintf(t, " for %s -",
1339 					HOSTNAMEV4(ipc->ip_src));
1340 				t += strlen(t);
1341 				sprintf(t,
1342 					" %s PR icmp len %hu %hu icmp %d/%d",
1343 					HOSTNAMEV4(ipc->ip_dst),
1344 					IP_HL(ipc) << 2, i,
1345 					icmp->icmp_type, icmp->icmp_code);
1346 			} else {
1347 				t += strlen(t);
1348 				sprintf(t, " for %s -",
1349 					HOSTNAMEV4(ipc->ip_src));
1350 				t += strlen(t);
1351 				sprintf(t, " %s PR %s len %hu (%hu)",
1352 					HOSTNAMEV4(ipc->ip_dst), proto,
1353 					IP_HL(ipc) << 2, i);
1354 				t += strlen(t);
1355 				if (ipoff & IP_OFFMASK) {
1356 					sprintf(t, "(frag %d:%hu@%hu%s%s)",
1357 						ntohs(ipc->ip_id),
1358 						i - (IP_HL(ipc) << 2),
1359 						(ipoff & IP_OFFMASK) << 3,
1360 						ipoff & IP_MF ? "+" : "",
1361 						ipoff & IP_DF ? "-" : "");
1362 				}
1363 			}
1364 
1365 		}
1366 	} else {
1367 		sprintf(t, "%s -> ", hostname(f, s));
1368 		t += strlen(t);
1369 		sprintf(t, "%s PR %s len %hu (%hu)",
1370 			hostname(f, d), proto, hl, plen);
1371 		t += strlen(t);
1372 		if (off & IP_OFFMASK)
1373 			sprintf(t, " (frag %d:%hu@%hu%s%s)",
1374 				ntohs(ip->ip_id),
1375 				plen - hl, (off & IP_OFFMASK) << 3,
1376 				ipoff & IP_MF ? "+" : "",
1377 				ipoff & IP_DF ? "-" : "");
1378 	}
1379 	t += strlen(t);
1380 
1381 printipflog:
1382 	if (ipf->fl_flags & FR_KEEPSTATE) {
1383 		(void) strcpy(t, " K-S");
1384 		t += strlen(t);
1385 	}
1386 
1387 	if (ipf->fl_flags & FR_KEEPFRAG) {
1388 		(void) strcpy(t, " K-F");
1389 		t += strlen(t);
1390 	}
1391 
1392 	if (ipf->fl_dir == 0)
1393 		strcpy(t, " IN");
1394 	else if (ipf->fl_dir == 1)
1395 		strcpy(t, " OUT");
1396 	t += strlen(t);
1397 	if (ipf->fl_logtag != 0) {
1398 		sprintf(t, " log-tag %d", ipf->fl_logtag);
1399 		t += strlen(t);
1400 	}
1401 	if (ipf->fl_nattag.ipt_num[0] != 0) {
1402 		strcpy(t, " nat-tag ");
1403 		t += strlen(t);
1404 		strncpy(t, ipf->fl_nattag.ipt_tag, sizeof(ipf->fl_nattag));
1405 		t += strlen(t);
1406 	}
1407 	if ((ipf->fl_lflags & FI_LOWTTL) != 0) {
1408 			strcpy(t, " low-ttl");
1409 			t += 8;
1410 	}
1411 	if ((ipf->fl_lflags & FI_OOW) != 0) {
1412 			strcpy(t, " OOW");
1413 			t += 4;
1414 	}
1415 	if ((ipf->fl_lflags & FI_BAD) != 0) {
1416 			strcpy(t, " bad");
1417 			t += 4;
1418 	}
1419 	if ((ipf->fl_lflags & FI_NATED) != 0) {
1420 			strcpy(t, " NAT");
1421 			t += 4;
1422 	}
1423 	if ((ipf->fl_lflags & FI_BADNAT) != 0) {
1424 			strcpy(t, " bad-NAT");
1425 			t += 8;
1426 	}
1427 	if ((ipf->fl_lflags & FI_BADSRC) != 0) {
1428 			strcpy(t, " bad-src");
1429 			t += 8;
1430 	}
1431 	if ((ipf->fl_lflags & FI_MULTICAST) != 0) {
1432 			strcpy(t, " multicast");
1433 			t += 10;
1434 	}
1435 	if ((ipf->fl_lflags & FI_BROADCAST) != 0) {
1436 			strcpy(t, " broadcast");
1437 			t += 10;
1438 	}
1439 	if ((ipf->fl_lflags & (FI_MULTICAST|FI_BROADCAST|FI_MBCAST)) ==
1440 	    FI_MBCAST) {
1441 			strcpy(t, " mbcast");
1442 			t += 7;
1443 	}
1444 	if (ipf->fl_breason != 0) {
1445 		strcpy(t, " reason:");
1446 		t += 8;
1447 		strcpy(t, reasons[ipf->fl_breason]);
1448 		t += strlen(reasons[ipf->fl_breason]);
1449 	}
1450 	*t++ = '\n';
1451 	*t++ = '\0';
1452 	defaction = 0;
1453 	if (conf->cfile != NULL)
1454 		defaction = check_action(buf, line, ipmonopts, lvl);
1455 
1456 	if (defaction == 0) {
1457 		if (ipmonopts & IPMON_SYSLOG) {
1458 			syslog(lvl, "%s", line);
1459 		} else if (conf->log != NULL) {
1460 			(void) fprintf(conf->log, "%s", line);
1461 		}
1462 
1463 		if (ipmonopts & IPMON_HEXHDR) {
1464 			dumphex(conf->log, ipmonopts, buf,
1465 				sizeof(iplog_t) + sizeof(*ipf));
1466 		}
1467 		if (ipmonopts & IPMON_HEXBODY) {
1468 			dumphex(conf->log, ipmonopts, (char *)ip,
1469 				ipf->fl_plen + ipf->fl_hlen);
1470 		} else if ((ipmonopts & IPMON_LOGBODY) &&
1471 			   (ipf->fl_flags & FR_LOGBODY)) {
1472 			dumphex(conf->log, ipmonopts, (char *)ip + ipf->fl_hlen,
1473 				ipf->fl_plen);
1474 		}
1475 	}
1476 }
1477 
1478 
usage(prog)1479 static void usage(prog)
1480 	char *prog;
1481 {
1482 	fprintf(stderr, "%s: [-NFhstvxX] [-f <logfile>]\n", prog);
1483 	exit(1);
1484 }
1485 
1486 
write_pid(file)1487 static void write_pid(file)
1488 	char *file;
1489 {
1490 	FILE *fp = NULL;
1491 	int fd;
1492 
1493 	if ((fd = open(file, O_CREAT|O_TRUNC|O_WRONLY, 0644)) >= 0) {
1494 		fp = fdopen(fd, "w");
1495 		if (fp == NULL) {
1496 			close(fd);
1497 			fprintf(stderr,
1498 				"unable to open/create pid file: %s\n", file);
1499 			return;
1500 		}
1501 		fprintf(fp, "%d", getpid());
1502 		fclose(fp);
1503 	}
1504 }
1505 
1506 
flushlogs(file,log)1507 static void flushlogs(file, log)
1508 	char *file;
1509 	FILE *log;
1510 {
1511 	int	fd, flushed = 0;
1512 
1513 	if ((fd = open(file, O_RDWR)) == -1) {
1514 		(void) fprintf(stderr, "%s: open: %s\n",
1515 			       file, STRERROR(errno));
1516 		exit(1);
1517 	}
1518 
1519 	if (ioctl(fd, SIOCIPFFB, &flushed) == 0) {
1520 		printf("%d bytes flushed from log buffer\n",
1521 			flushed);
1522 		fflush(stdout);
1523 	} else
1524 		ipferror(fd, "SIOCIPFFB");
1525 	(void) close(fd);
1526 
1527 	if (flushed) {
1528 		if (ipmonopts & IPMON_SYSLOG) {
1529 			syslog(LOG_INFO, "%d bytes flushed from log\n",
1530 				flushed);
1531 		} else if ((log != stdout) && (log != NULL)) {
1532 			fprintf(log, "%d bytes flushed from log\n", flushed);
1533 		}
1534 	}
1535 }
1536 
1537 
logopts(turnon,options)1538 static void logopts(turnon, options)
1539 	int turnon;
1540 	char *options;
1541 {
1542 	int flags = 0;
1543 	char *s;
1544 
1545 	for (s = options; *s; s++)
1546 	{
1547 		switch (*s)
1548 		{
1549 		case 'N' :
1550 			flags |= IPMON_NAT;
1551 			break;
1552 		case 'S' :
1553 			flags |= IPMON_STATE;
1554 			break;
1555 		case 'I' :
1556 			flags |= IPMON_FILTER;
1557 			break;
1558 		default :
1559 			fprintf(stderr, "Unknown log option %c\n", *s);
1560 			exit(1);
1561 		}
1562 	}
1563 
1564 	if (turnon)
1565 		ipmonopts |= flags;
1566 	else
1567 		ipmonopts &= ~(flags);
1568 }
1569 
initconfig(config_t * conf)1570 static void initconfig(config_t *conf)
1571 {
1572 	int i;
1573 
1574 	memset(conf, 0, sizeof(*conf));
1575 
1576 	conf->log = stdout;
1577 	conf->maxfd = -1;
1578 
1579 	for (i = 0; i < 3; i++) {
1580 		conf->logsrc[i].fd = -1;
1581 		conf->logsrc[i].logtype = -1;
1582 		conf->logsrc[i].regular = -1;
1583 	}
1584 
1585 	conf->logsrc[0].file = IPL_NAME;
1586 	conf->logsrc[1].file = IPNAT_NAME;
1587 	conf->logsrc[2].file = IPSTATE_NAME;
1588 
1589 	add_doing(&executesaver);
1590 	add_doing(&snmpv1saver);
1591 	add_doing(&snmpv2saver);
1592 	add_doing(&syslogsaver);
1593 	add_doing(&filesaver);
1594 	add_doing(&nothingsaver);
1595 }
1596 
1597 
main(argc,argv)1598 int main(argc, argv)
1599 	int argc;
1600 	char *argv[];
1601 {
1602 	int	doread, c, make_daemon = 0;
1603 	char	*prog;
1604 	config_t	config;
1605 
1606 	prog = strrchr(argv[0], '/');
1607 	if (prog == NULL)
1608 		prog = argv[0];
1609 	else
1610 		prog++;
1611 
1612 	initconfig(&config);
1613 
1614 	while ((c = getopt(argc, argv,
1615 			   "?abB:C:Df:FhL:nN:o:O:pP:sS:tvxX")) != -1)
1616 		switch (c)
1617 		{
1618 		case 'a' :
1619 			ipmonopts |= IPMON_LOGALL;
1620 			config.logsrc[0].logtype = IPL_LOGIPF;
1621 			config.logsrc[1].logtype = IPL_LOGNAT;
1622 			config.logsrc[2].logtype = IPL_LOGSTATE;
1623 			break;
1624 		case 'b' :
1625 			ipmonopts |= IPMON_LOGBODY;
1626 			break;
1627 		case 'B' :
1628 			config.bfile = optarg;
1629 			config.blog = fopen(optarg, "a");
1630 			break;
1631 		case 'C' :
1632 			config.cfile = optarg;
1633 			break;
1634 		case 'D' :
1635 			make_daemon = 1;
1636 			break;
1637 		case 'f' : case 'I' :
1638 			ipmonopts |= IPMON_FILTER;
1639 			config.logsrc[0].logtype = IPL_LOGIPF;
1640 			config.logsrc[0].file = optarg;
1641 			break;
1642 		case 'F' :
1643 			flushlogs(config.logsrc[0].file, config.log);
1644 			flushlogs(config.logsrc[1].file, config.log);
1645 			flushlogs(config.logsrc[2].file, config.log);
1646 			break;
1647 		case 'L' :
1648 			logfac = fac_findname(optarg);
1649 			if (logfac == -1) {
1650 				fprintf(stderr,
1651 					"Unknown syslog facility '%s'\n",
1652 					 optarg);
1653 				exit(1);
1654 			}
1655 			break;
1656 		case 'n' :
1657 			ipmonopts |= IPMON_RESOLVE;
1658 			opts &= ~OPT_NORESOLVE;
1659 			break;
1660 		case 'N' :
1661 			ipmonopts |= IPMON_NAT;
1662 			config.logsrc[1].logtype = IPL_LOGNAT;
1663 			config.logsrc[1].file = optarg;
1664 			break;
1665 		case 'o' : case 'O' :
1666 			logopts(c == 'o', optarg);
1667 			if (ipmonopts & IPMON_FILTER)
1668 				config.logsrc[0].logtype = IPL_LOGIPF;
1669 			if (ipmonopts & IPMON_NAT)
1670 				config.logsrc[1].logtype = IPL_LOGNAT;
1671 			if (ipmonopts & IPMON_STATE)
1672 				config.logsrc[2].logtype = IPL_LOGSTATE;
1673 			break;
1674 		case 'p' :
1675 			ipmonopts |= IPMON_PORTNUM;
1676 			break;
1677 		case 'P' :
1678 			pidfile = optarg;
1679 			break;
1680 		case 's' :
1681 			ipmonopts |= IPMON_SYSLOG;
1682 			config.log = NULL;
1683 			break;
1684 		case 'S' :
1685 			ipmonopts |= IPMON_STATE;
1686 			config.logsrc[2].logtype = IPL_LOGSTATE;
1687 			config.logsrc[2].file = optarg;
1688 			break;
1689 		case 't' :
1690 			ipmonopts |= IPMON_TAIL;
1691 			break;
1692 		case 'v' :
1693 			ipmonopts |= IPMON_VERBOSE;
1694 			break;
1695 		case 'x' :
1696 			ipmonopts |= IPMON_HEXBODY;
1697 			break;
1698 		case 'X' :
1699 			ipmonopts |= IPMON_HEXHDR;
1700 			break;
1701 		default :
1702 		case 'h' :
1703 		case '?' :
1704 			usage(argv[0]);
1705 		}
1706 
1707 	if (ipmonopts & IPMON_SYSLOG)
1708 		openlog(prog, LOG_NDELAY|LOG_PID, logfac);
1709 
1710 	init_tabs();
1711 	if (config.cfile)
1712 		if (load_config(config.cfile) == -1) {
1713 			unload_config();
1714 			exit(1);
1715 		}
1716 
1717 	/*
1718 	 * Default action is to only open the filter log file.
1719 	 */
1720 	if ((config.logsrc[0].logtype == -1) &&
1721 	    (config.logsrc[0].logtype == -1) &&
1722 	    (config.logsrc[0].logtype == -1))
1723 		config.logsrc[0].logtype = IPL_LOGIPF;
1724 
1725 	openlogs(&config);
1726 
1727 	if (!(ipmonopts & IPMON_SYSLOG)) {
1728 		config.file = argv[optind];
1729 		config.log = config.file ? fopen(config.file, "a") : stdout;
1730 		if (config.log == NULL) {
1731 			(void) fprintf(stderr, "%s: fopen: %s\n",
1732 				       argv[optind], STRERROR(errno));
1733 			exit(1);
1734 			/* NOTREACHED */
1735 		}
1736 		setvbuf(config.log, NULL, _IONBF, 0);
1737 	} else {
1738 		config.log = NULL;
1739 	}
1740 
1741 	if (make_daemon &&
1742 	    ((config.log != stdout) || (ipmonopts & IPMON_SYSLOG))) {
1743 #if BSD >= 199306
1744 		daemon(0, !(ipmonopts & IPMON_SYSLOG));
1745 #else
1746 		int pid;
1747 
1748 		switch (fork())
1749 		{
1750 		case -1 :
1751 			(void) fprintf(stderr, "%s: fork() failed: %s\n",
1752 				       argv[0], STRERROR(errno));
1753 			exit(1);
1754 			/* NOTREACHED */
1755 		case 0 :
1756 			break;
1757 		default :
1758 			exit(0);
1759 		}
1760 
1761 		setsid();
1762 		if ((ipmonopts & IPMON_SYSLOG))
1763 			close(2);
1764 #endif /* !BSD */
1765 		close(0);
1766 		close(1);
1767 		write_pid(pidfile);
1768 	}
1769 
1770 	signal(SIGHUP, handlehup);
1771 
1772 	for (doread = 1; doread; )
1773 		doread = read_loginfo(&config);
1774 
1775 	unload_config();
1776 
1777 	return(0);
1778 	/* NOTREACHED */
1779 }
1780 
1781 
openlogs(config_t * conf)1782 static void openlogs(config_t *conf)
1783 {
1784 	logsource_t *l;
1785 	struct stat sb;
1786 	int i;
1787 
1788 	for (i = 0; i < 3; i++) {
1789 		l = &conf->logsrc[i];
1790 		if (l->logtype == -1)
1791 			continue;
1792 		if (!strcmp(l->file, "-"))
1793 			l->fd = 0;
1794 		else {
1795 			if ((l->fd= open(l->file, O_RDONLY)) == -1) {
1796 				(void) fprintf(stderr,
1797 					       "%s: open: %s\n", l->file,
1798 					       STRERROR(errno));
1799 				exit(1);
1800 				/* NOTREACHED */
1801 			}
1802 
1803 			if (fstat(l->fd, &sb) == -1) {
1804 				(void) fprintf(stderr, "%d: fstat: %s\n",
1805 					       l->fd, STRERROR(errno));
1806 				exit(1);
1807 				/* NOTREACHED */
1808 			}
1809 
1810 			l->regular = !S_ISCHR(sb.st_mode);
1811 			if (l->regular)
1812 				l->size = sb.st_size;
1813 
1814 			FD_SET(l->fd, &conf->fdmr);
1815 			if (l->fd > conf->maxfd)
1816 				conf->maxfd = l->fd;
1817 		}
1818 	}
1819 }
1820 
1821 
read_loginfo(config_t * conf)1822 static int read_loginfo(config_t *conf)
1823 {
1824 	iplog_t buf[DEFAULT_IPFLOGSIZE/sizeof(iplog_t)+1];
1825 	int n, tr, nr, i;
1826 	logsource_t *l;
1827 	fd_set fdr;
1828 
1829 	fdr = conf->fdmr;
1830 
1831 	n = select(conf->maxfd + 1, &fdr, NULL, NULL, NULL);
1832 	if (n == 0)
1833 		return 1;
1834 	if (n == -1) {
1835 		if (errno == EINTR)
1836 			return 1;
1837 		return -1;
1838 	}
1839 
1840 	for (i = 0, nr = 0; i < 3; i++) {
1841 		l = &conf->logsrc[i];
1842 
1843 		if ((l->logtype == -1) || !FD_ISSET(l->fd, &fdr))
1844 			continue;
1845 
1846 		tr = 0;
1847 		if (l->regular) {
1848 			tr = (lseek(l->fd, 0, SEEK_CUR) < l->size);
1849 			if (!tr && !(ipmonopts & IPMON_TAIL))
1850 				return 0;
1851 		}
1852 
1853 		n = 0;
1854 		tr = read_log(l->fd, &n, (char *)buf, sizeof(buf));
1855 		if (donehup) {
1856 			if (conf->file != NULL) {
1857 				if (conf->log != NULL) {
1858 					fclose(conf->log);
1859 					conf->log = NULL;
1860 				}
1861 				conf->log = fopen(conf->file, "a");
1862 			}
1863 
1864 			if (conf->bfile != NULL) {
1865 				if (conf->blog != NULL) {
1866 					fclose(conf->blog);
1867 					conf->blog = NULL;
1868 				}
1869 				conf->blog = fopen(conf->bfile, "a");
1870 			}
1871 
1872 			init_tabs();
1873 			if (conf->cfile != NULL)
1874 				load_config(conf->cfile);
1875 			donehup = 0;
1876 		}
1877 
1878 		switch (tr)
1879 		{
1880 		case -1 :
1881 			if (ipmonopts & IPMON_SYSLOG)
1882 				syslog(LOG_CRIT, "read: %m\n");
1883 			else {
1884 				ipferror(l->fd, "read");
1885 			}
1886 			return 0;
1887 		case 1 :
1888 			if (ipmonopts & IPMON_SYSLOG)
1889 				syslog(LOG_CRIT, "aborting logging\n");
1890 			else if (conf->log != NULL)
1891 				fprintf(conf->log, "aborting logging\n");
1892 			return 0;
1893 		case 2 :
1894 			break;
1895 		case 0 :
1896 			nr += tr;
1897 			if (n > 0) {
1898 				print_log(conf, l, (char *)buf, n);
1899 				if (!(ipmonopts & IPMON_SYSLOG))
1900 					fflush(conf->log);
1901 			}
1902 			break;
1903 		}
1904 	}
1905 
1906 	if (!nr && (ipmonopts & IPMON_TAIL))
1907 		sleep(1);
1908 
1909 	return 1;
1910 }
1911