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(¬hingsaver);
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