1 /* $FreeBSD: src/contrib/ipfilter/ipmon.c,v 1.5.2.7 2003/03/01 03:55:51 darrenr Exp $ */
2 /* $FreeBSD: src/contrib/ipfilter/ipmon.c,v 1.5.2.8 2004/07/04 09:24:39 darrenr Exp $ */
4 * Copyright (C) 1993-2002 by Darren Reed.
6 * See the IPFILTER.LICENCE file for details on licencing.
9 #define SOLARIS (defined(__SVR4) || defined(__svr4__)) && defined(sun)
12 #if defined(__sgi) && (IRIX > 602)
13 # include <sys/ptimers.h>
15 #include <sys/types.h>
17 #include <sys/param.h>
20 #include <sys/socket.h>
21 #include <sys/ioctl.h>
28 #if !defined(__SVR4) && !defined(__svr4__)
29 # if (__FreeBSD_version >= 300000)
30 # include <sys/dirent.h>
32 # include <sys/dirent.h>
35 # include <sys/filio.h>
36 # include <sys/byteorder.h>
38 #if !defined(__SVR4) && !defined(__GNUC__)
44 #include <netinet/in.h>
45 #include <netinet/in_systm.h>
47 #include <netinet/ip.h>
48 #include <netinet/tcp_fsm.h>
50 #include <arpa/inet.h>
51 #include <arpa/nameser.h>
55 # include <sys/protosw.h>
56 # include <netinet/ip_var.h>
59 #include <netinet/tcp.h>
60 #include <netinet/ip_icmp.h>
65 #include "netinet/ip_compat.h"
66 #include <netinet/tcpip.h>
67 #include "netinet/ip_fil.h"
68 #include "netinet/ip_nat.h"
69 #include "netinet/ip_state.h"
72 static const char sccsid
[] = "@(#)ipmon.c 1.21 6/5/96 (C)1993-2000 Darren Reed";
73 static const char rcsid
[] = "@(#)$Id: ipmon.c,v 2.12.2.37 2002/12/06 11:40:26 darrenr Exp $";
77 #if defined(sun) && !defined(SOLARIS2)
78 #define STRERROR(x) sys_errlist[x]
79 extern char *sys_errlist
[];
81 #define STRERROR(x) strerror(x)
91 typedef struct icmp_subtype
{
96 typedef struct icmp_type
{
98 struct icmp_subtype
*it_subtable
;
104 #define IST_SZ(x) (sizeof(x)/sizeof(icmp_subtype_t))
107 struct flags tcpfl
[] = {
120 static char *pidfile
= "/etc/opt/ipf/ipmon.pid";
123 static char *pidfile
= "/var/run/ipmon.pid";
125 static char *pidfile
= "/etc/ipmon.pid";
129 static char line
[2048];
131 static FILE *newlog
= NULL
;
132 static char *logfile
= NULL
;
133 static int donehup
= 0;
134 static void usage
__P((char *));
135 static void handlehup
__P((int));
136 static void flushlogs
__P((char *, FILE *));
137 static void print_log
__P((int, FILE *, char *, int));
138 static void print_ipflog
__P((FILE *, char *, int));
139 static void print_natlog
__P((FILE *, char *, int));
140 static void print_statelog
__P((FILE *, char *, int));
141 static void dumphex
__P((FILE *, u_char
*, int));
142 static int read_log
__P((int, int *, char *, int));
143 static void write_pid
__P((char *));
144 static char *icmpname
__P((u_int
, u_int
));
145 static char *icmpname6
__P((u_int
, u_int
));
146 static icmp_type_t
*find_icmptype
__P((int, icmp_type_t
*, size_t));
147 static icmp_subtype_t
*find_icmpsubtype
__P((int, icmp_subtype_t
*, size_t));
149 char *hostname
__P((int, int, u_32_t
*));
150 char *portname
__P((int, char *, u_int
));
151 int main
__P((int, char *[]));
153 static void logopts
__P((int, char *));
154 static void init_tabs
__P((void));
155 static char *getproto
__P((u_int
));
157 static char **protocols
= NULL
;
158 static char **udp_ports
= NULL
;
159 static char **tcp_ports
= NULL
;
161 #define OPT_SYSLOG 0x001
162 #define OPT_RESOLVE 0x002
163 #define OPT_HEXBODY 0x004
164 #define OPT_VERBOSE 0x008
165 #define OPT_HEXHDR 0x010
166 #define OPT_TAIL 0x020
167 #define OPT_NAT 0x080
168 #define OPT_STATE 0x100
169 #define OPT_FILTER 0x200
170 #define OPT_PORTNUM 0x400
171 #define OPT_LOGALL (OPT_NAT|OPT_STATE|OPT_FILTER)
172 #define OPT_LOGBODY 0x800
174 #define HOSTNAME_V4(a,b) hostname((a), 4, (u_32_t *)&(b))
177 #define LOGFAC LOG_LOCAL0
181 static icmp_subtype_t icmpunreachnames
[] = {
182 { ICMP_UNREACH_NET
, "net" },
183 { ICMP_UNREACH_HOST
, "host" },
184 { ICMP_UNREACH_PROTOCOL
, "protocol" },
185 { ICMP_UNREACH_PORT
, "port" },
186 { ICMP_UNREACH_NEEDFRAG
, "needfrag" },
187 { ICMP_UNREACH_SRCFAIL
, "srcfail" },
188 { ICMP_UNREACH_NET_UNKNOWN
, "net_unknown" },
189 { ICMP_UNREACH_HOST_UNKNOWN
, "host_unknown" },
190 { ICMP_UNREACH_NET
, "isolated" },
191 { ICMP_UNREACH_NET_PROHIB
, "net_prohib" },
192 { ICMP_UNREACH_NET_PROHIB
, "host_prohib" },
193 { ICMP_UNREACH_TOSNET
, "tosnet" },
194 { ICMP_UNREACH_TOSHOST
, "toshost" },
195 { ICMP_UNREACH_ADMIN_PROHIBIT
, "admin_prohibit" },
199 static icmp_subtype_t redirectnames
[] = {
200 { ICMP_REDIRECT_NET
, "net" },
201 { ICMP_REDIRECT_HOST
, "host" },
202 { ICMP_REDIRECT_TOSNET
, "tosnet" },
203 { ICMP_REDIRECT_TOSHOST
, "toshost" },
207 static icmp_subtype_t timxceednames
[] = {
208 { ICMP_TIMXCEED_INTRANS
, "transit" },
209 { ICMP_TIMXCEED_REASS
, "reassem" },
213 static icmp_subtype_t paramnames
[] = {
214 { ICMP_PARAMPROB_ERRATPTR
, "errata_pointer" },
215 { ICMP_PARAMPROB_OPTABSENT
, "optmissing" },
216 { ICMP_PARAMPROB_LENGTH
, "length" },
220 static icmp_type_t icmptypes
[] = {
221 { ICMP_ECHOREPLY
, NULL
, 0, "echoreply" },
222 { -1, NULL
, 0, NULL
},
223 { -1, NULL
, 0, NULL
},
224 { ICMP_UNREACH
, icmpunreachnames
,
225 IST_SZ(icmpunreachnames
),"unreach" },
226 { ICMP_SOURCEQUENCH
, NULL
, 0, "sourcequench" },
227 { ICMP_REDIRECT
, redirectnames
,
228 IST_SZ(redirectnames
), "redirect" },
229 { -1, NULL
, 0, NULL
},
230 { -1, NULL
, 0, NULL
},
231 { ICMP_ECHO
, NULL
, 0, "echo" },
232 { ICMP_ROUTERADVERT
, NULL
, 0, "routeradvert" },
233 { ICMP_ROUTERSOLICIT
, NULL
, 0, "routersolicit" },
234 { ICMP_TIMXCEED
, timxceednames
,
235 IST_SZ(timxceednames
), "timxceed" },
236 { ICMP_PARAMPROB
, paramnames
,
237 IST_SZ(paramnames
), "paramprob" },
238 { ICMP_TSTAMP
, NULL
, 0, "timestamp" },
239 { ICMP_TSTAMPREPLY
, NULL
, 0, "timestampreply" },
240 { ICMP_IREQ
, NULL
, 0, "inforeq" },
241 { ICMP_IREQREPLY
, NULL
, 0, "inforeply" },
242 { ICMP_MASKREQ
, NULL
, 0, "maskreq" },
243 { ICMP_MASKREPLY
, NULL
, 0, "maskreply" },
244 { -2, NULL
, 0, NULL
}
247 static icmp_subtype_t icmpredirect6
[] = {
248 { ICMP6_DST_UNREACH_NOROUTE
, "noroute" },
249 { ICMP6_DST_UNREACH_ADMIN
, "admin" },
250 { ICMP6_DST_UNREACH_NOTNEIGHBOR
, "neighbour" },
251 { ICMP6_DST_UNREACH_ADDR
, "address" },
252 { ICMP6_DST_UNREACH_NOPORT
, "noport" },
256 static icmp_subtype_t icmptimexceed6
[] = {
257 { ICMP6_TIME_EXCEED_TRANSIT
, "intransit" },
258 { ICMP6_TIME_EXCEED_REASSEMBLY
, "reassem" },
262 static icmp_subtype_t icmpparamprob6
[] = {
263 { ICMP6_PARAMPROB_HEADER
, "header" },
264 { ICMP6_PARAMPROB_NEXTHEADER
, "nextheader" },
265 { ICMP6_PARAMPROB_OPTION
, "option" },
269 static icmp_subtype_t icmpquerysubject6
[] = {
270 { ICMP6_NI_SUBJ_IPV6
, "ipv6" },
271 { ICMP6_NI_SUBJ_FQDN
, "fqdn" },
272 { ICMP6_NI_SUBJ_IPV4
, "ipv4" },
276 static icmp_subtype_t icmpnodeinfo6
[] = {
277 { ICMP6_NI_SUCCESS
, "success" },
278 { ICMP6_NI_REFUSED
, "refused" },
279 { ICMP6_NI_UNKNOWN
, "unknown" },
283 static icmp_subtype_t icmprenumber6
[] = {
284 { ICMP6_ROUTER_RENUMBERING_COMMAND
, "command" },
285 { ICMP6_ROUTER_RENUMBERING_RESULT
, "result" },
286 { ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET
, "seqnum_reset" },
290 static icmp_type_t icmptypes6
[] = {
291 { 0, NULL
, 0, NULL
},
292 { ICMP6_DST_UNREACH
, icmpredirect6
,
293 IST_SZ(icmpredirect6
), "unreach" },
294 { ICMP6_PACKET_TOO_BIG
, NULL
, 0, "toobig" },
295 { ICMP6_TIME_EXCEEDED
, icmptimexceed6
,
296 IST_SZ(icmptimexceed6
), "timxceed" },
297 { ICMP6_PARAM_PROB
, icmpparamprob6
,
298 IST_SZ(icmpparamprob6
), "paramprob" },
299 { ICMP6_ECHO_REQUEST
, NULL
, 0, "echo" },
300 { ICMP6_ECHO_REPLY
, NULL
, 0, "echoreply" },
301 { ICMP6_MEMBERSHIP_QUERY
, icmpquerysubject6
,
302 IST_SZ(icmpquerysubject6
), "groupmemberquery" },
303 { ICMP6_MEMBERSHIP_REPORT
,NULL
, 0, "groupmemberreport" },
304 { ICMP6_MEMBERSHIP_REDUCTION
,NULL
, 0, "groupmemberterm" },
305 { ND_ROUTER_SOLICIT
, NULL
, 0, "routersolicit" },
306 { ND_ROUTER_ADVERT
, NULL
, 0, "routeradvert" },
307 { ND_NEIGHBOR_SOLICIT
, NULL
, 0, "neighborsolicit" },
308 { ND_NEIGHBOR_ADVERT
, NULL
, 0, "neighboradvert" },
309 { ND_REDIRECT
, NULL
, 0, "redirect" },
310 { ICMP6_ROUTER_RENUMBERING
, icmprenumber6
,
311 IST_SZ(icmprenumber6
), "routerrenumber" },
312 { ICMP6_WRUREQUEST
, NULL
, 0, "whoareyourequest" },
313 { ICMP6_WRUREPLY
, NULL
, 0, "whoareyoureply" },
314 { ICMP6_FQDN_QUERY
, NULL
, 0, "fqdnquery" },
315 { ICMP6_FQDN_REPLY
, NULL
, 0, "fqdnreply" },
316 { ICMP6_NI_QUERY
, icmpnodeinfo6
,
317 IST_SZ(icmpnodeinfo6
), "nodeinforequest" },
318 { ICMP6_NI_REPLY
, NULL
, 0, "nodeinforeply" },
319 { MLD6_MTRACE_RESP
, NULL
, 0, "mtraceresponse" },
320 { MLD6_MTRACE
, NULL
, 0, "mtracerequest" },
321 { -2, NULL
, 0, NULL
}
324 static icmp_subtype_t
*find_icmpsubtype(type
, table
, tablesz
)
326 icmp_subtype_t
*table
;
335 if ((type
< 0) || (type
> table
[tablesz
- 2].ist_val
))
339 if (table
[type
].ist_val
== type
)
342 for (i
= 0, ist
= table
; ist
->ist_val
!= -2; i
++, ist
++)
343 if (ist
->ist_val
== type
)
349 static icmp_type_t
*find_icmptype(type
, table
, tablesz
)
360 if ((type
< 0) || (type
> table
[tablesz
- 2].it_val
))
364 if (table
[type
].it_val
== type
)
367 for (i
= 0, it
= table
; it
->it_val
!= -2; i
++, it
++)
368 if (it
->it_val
== type
)
374 static void handlehup(sig
)
379 signal(SIGHUP
, handlehup
);
380 if (logfile
&& (fp
= fopen(logfile
, "a")))
387 static void init_tabs()
394 if (protocols
!= NULL
) {
398 protocols
= (char **)malloc(256 * sizeof(*protocols
));
399 if (protocols
!= NULL
) {
400 bzero((char *)protocols
, 256 * sizeof(*protocols
));
403 while ((p
= getprotoent()) != NULL
)
404 if (p
->p_proto
>= 0 && p
->p_proto
<= 255 &&
405 p
->p_name
!= NULL
&& protocols
[p
->p_proto
] == NULL
)
406 protocols
[p
->p_proto
] = strdup(p
->p_name
);
410 if (udp_ports
!= NULL
) {
414 udp_ports
= (char **)malloc(65536 * sizeof(*udp_ports
));
415 if (udp_ports
!= NULL
)
416 bzero((char *)udp_ports
, 65536 * sizeof(*udp_ports
));
418 if (tcp_ports
!= NULL
) {
422 tcp_ports
= (char **)malloc(65536 * sizeof(*tcp_ports
));
423 if (tcp_ports
!= NULL
)
424 bzero((char *)tcp_ports
, 65536 * sizeof(*tcp_ports
));
427 while ((s
= getservent()) != NULL
) {
428 if (s
->s_proto
== NULL
)
430 else if (!strcmp(s
->s_proto
, "tcp")) {
431 port
= ntohs(s
->s_port
);
434 } else if (!strcmp(s
->s_proto
, "udp")) {
435 port
= ntohs(s
->s_port
);
440 if ((port
< 0 || port
> 65535) || (name
== NULL
))
442 tab
[port
] = strdup(name
);
448 static char *getproto(p
)
455 s
= protocols
? protocols
[p
] : NULL
;
457 sprintf(pnum
, "%u", p
);
464 static int read_log(fd
, lenp
, buf
, bufsize
)
465 int fd
, bufsize
, *lenp
;
470 nr
= read(fd
, buf
, bufsize
);
473 if ((nr
< 0) && (errno
!= EINTR
))
480 char *hostname(res
, v
, ip
)
484 # define MAX_INETA 16
485 static char hname
[MAXHOSTNAMELEN
+ MAX_INETA
+ 3];
487 static char hostbuf
[MAXHOSTNAMELEN
+1];
495 return inet_ntoa(ipa
);
496 hp
= gethostbyaddr((char *)ip
, sizeof(*ip
), AF_INET
);
498 return inet_ntoa(ipa
);
499 sprintf(hname
, "%.*s[%s]", MAXHOSTNAMELEN
, hp
->h_name
,
504 (void) inet_ntop(AF_INET6
, ip
, hostbuf
, sizeof(hostbuf
) - 1);
505 hostbuf
[MAXHOSTNAMELEN
] = '\0';
513 char *portname(res
, proto
, port
)
518 static char pname
[8];
523 (void) sprintf(pname
, "%u", port
);
524 if (!res
|| (opts
& OPT_PORTNUM
))
527 if (!strcmp(proto
, "tcp"))
529 else if (!strcmp(proto
, "udp"))
537 static char *icmpname(type
, code
)
541 static char name
[80];
547 it
= find_icmptype(type
, icmptypes
, sizeof(icmptypes
) / sizeof(*it
));
552 sprintf(name
, "icmptype(%d)/", type
);
554 sprintf(name
, "%s/", s
);
557 if (it
!= NULL
&& it
->it_subtable
!= NULL
)
558 ist
= find_icmpsubtype(code
, it
->it_subtable
, it
->it_stsize
);
560 if (ist
!= NULL
&& ist
->ist_name
!= NULL
)
561 strcat(name
, ist
->ist_name
);
563 sprintf(name
+ strlen(name
), "%d", code
);
568 static char *icmpname6(type
, code
)
572 static char name
[80];
578 it
= find_icmptype(type
, icmptypes6
, sizeof(icmptypes6
) / sizeof(*it
));
583 sprintf(name
, "icmpv6type(%d)/", type
);
585 sprintf(name
, "%s/", s
);
588 if (it
!= NULL
&& it
->it_subtable
!= NULL
)
589 ist
= find_icmpsubtype(code
, it
->it_subtable
, it
->it_stsize
);
591 if (ist
!= NULL
&& ist
->ist_name
!= NULL
)
592 strcat(name
, ist
->ist_name
);
594 sprintf(name
+ strlen(name
), "%d", code
);
600 static void dumphex(log
, buf
, len
)
607 u_char
*s
= buf
, *t
= (u_char
*)line
;
609 if (len
== 0 || buf
== 0)
613 for (i
= len
, j
= 0; i
; i
--, j
++, s
++) {
614 if (j
&& !(j
& 0xf)) {
617 if (!(opts
& OPT_SYSLOG
))
620 syslog(LOG_INFO
, "%s", line
);
624 sprintf((char *)t
, "%02x", *s
& 0xff);
626 if (!((j
+ 1) & 0xf)) {
628 sprintf((char *)t
, " ");
630 for (k
= 16; k
; k
--, s
++)
631 *t
++ = (isprint(*s
) ? *s
: '.');
640 for (k
= 16 - (j
& 0xf); k
; k
--) {
645 sprintf((char *)t
, " ");
648 for (k
= j
& 0xf; k
; k
--, s
++)
649 *t
++ = (isprint(*s
) ? *s
: '.');
653 if (!(opts
& OPT_SYSLOG
)) {
657 syslog(LOG_INFO
, "%s", line
);
660 static void print_natlog(log
, buf
, blen
)
666 iplog_t
*ipl
= (iplog_t
*)buf
;
672 nl
= (struct natlog
*)((char *)ipl
+ IPLOG_SIZE
);
673 res
= (opts
& OPT_RESOLVE
) ? 1 : 0;
674 tm
= localtime((time_t *)&ipl
->ipl_sec
);
676 if (!(opts
& OPT_SYSLOG
)) {
677 (void) strftime(t
, len
, "%d/%m/%Y ", tm
);
682 (void) strftime(t
, len
, "%T", tm
);
684 (void) sprintf(t
, ".%-.6ld @%hd ", ipl
->ipl_usec
, nl
->nl_rule
+ 1);
687 if (nl
->nl_type
== NL_NEWMAP
)
688 strcpy(t
, "NAT:MAP ");
689 else if (nl
->nl_type
== NL_NEWRDR
)
690 strcpy(t
, "NAT:RDR ");
691 else if (nl
->nl_type
== NL_EXPIRE
)
692 strcpy(t
, "NAT:EXPIRE ");
693 else if (nl
->nl_type
== NL_FLUSH
)
694 strcpy(t
, "NAT:FLUSH ");
695 else if (nl
->nl_type
== NL_NEWBIMAP
)
696 strcpy(t
, "NAT:BIMAP ");
697 else if (nl
->nl_type
== NL_NEWBLOCK
)
698 strcpy(t
, "NAT:MAPBLOCK ");
700 sprintf(t
, "Type: %d ", nl
->nl_type
);
703 proto
= getproto(nl
->nl_p
);
705 (void) sprintf(t
, "%s,%s <- -> ", HOSTNAME_V4(res
, nl
->nl_inip
),
706 portname(res
, proto
, (u_int
)nl
->nl_inport
));
708 (void) sprintf(t
, "%s,%s ", HOSTNAME_V4(res
, nl
->nl_outip
),
709 portname(res
, proto
, (u_int
)nl
->nl_outport
));
711 (void) sprintf(t
, "[%s,%s]", HOSTNAME_V4(res
, nl
->nl_origip
),
712 portname(res
, proto
, (u_int
)nl
->nl_origport
));
714 if (nl
->nl_type
== NL_EXPIRE
) {
716 (void) sprintf(t
, " Pkts %qd Bytes %qd",
717 (long long)nl
->nl_pkts
,
718 (long long)nl
->nl_bytes
);
720 (void) sprintf(t
, " Pkts %ld Bytes %ld",
721 nl
->nl_pkts
, nl
->nl_bytes
);
728 if (opts
& OPT_SYSLOG
)
729 syslog(LOG_INFO
, "%s", line
);
731 (void) fprintf(log
, "%s", line
);
735 static void print_statelog(log
, buf
, blen
)
741 iplog_t
*ipl
= (iplog_t
*)buf
;
742 char *t
= line
, *proto
;
746 sl
= (struct ipslog
*)((char *)ipl
+ IPLOG_SIZE
);
747 res
= (opts
& OPT_RESOLVE
) ? 1 : 0;
748 tm
= localtime((time_t *)&ipl
->ipl_sec
);
750 if (!(opts
& OPT_SYSLOG
)) {
751 (void) strftime(t
, len
, "%d/%m/%Y ", tm
);
756 (void) strftime(t
, len
, "%T", tm
);
758 (void) sprintf(t
, ".%-.6ld ", ipl
->ipl_usec
);
761 if (sl
->isl_type
== ISL_NEW
)
762 strcpy(t
, "STATE:NEW ");
763 else if (sl
->isl_type
== ISL_EXPIRE
) {
764 if ((sl
->isl_p
== IPPROTO_TCP
) &&
765 (sl
->isl_state
[0] > TCPS_ESTABLISHED
||
766 sl
->isl_state
[1] > TCPS_ESTABLISHED
))
767 strcpy(t
, "STATE:CLOSE ");
769 strcpy(t
, "STATE:EXPIRE ");
770 } else if (sl
->isl_type
== ISL_FLUSH
)
771 strcpy(t
, "STATE:FLUSH ");
772 else if (sl
->isl_type
== ISL_REMOVE
)
773 strcpy(t
, "STATE:REMOVE ");
775 sprintf(t
, "Type: %d ", sl
->isl_type
);
778 proto
= getproto(sl
->isl_p
);
780 if (sl
->isl_p
== IPPROTO_TCP
|| sl
->isl_p
== IPPROTO_UDP
) {
781 (void) sprintf(t
, "%s,%s -> ",
782 hostname(res
, sl
->isl_v
, (u_32_t
*)&sl
->isl_src
),
783 portname(res
, proto
, (u_int
)sl
->isl_sport
));
785 (void) sprintf(t
, "%s,%s PR %s",
786 hostname(res
, sl
->isl_v
, (u_32_t
*)&sl
->isl_dst
),
787 portname(res
, proto
, (u_int
)sl
->isl_dport
), proto
);
788 } else if (sl
->isl_p
== IPPROTO_ICMP
) {
789 (void) sprintf(t
, "%s -> ", hostname(res
, sl
->isl_v
,
790 (u_32_t
*)&sl
->isl_src
));
792 (void) sprintf(t
, "%s PR icmp %d",
793 hostname(res
, sl
->isl_v
, (u_32_t
*)&sl
->isl_dst
),
795 } else if (sl
->isl_p
== IPPROTO_ICMPV6
) {
796 (void) sprintf(t
, "%s -> ", hostname(res
, sl
->isl_v
,
797 (u_32_t
*)&sl
->isl_src
));
799 (void) sprintf(t
, "%s PR icmpv6 %d",
800 hostname(res
, sl
->isl_v
, (u_32_t
*)&sl
->isl_dst
),
804 if (sl
->isl_type
!= ISL_NEW
) {
806 (void) sprintf(t
, " Pkts %qd Bytes %qd",
807 (long long)sl
->isl_pkts
,
808 (long long)sl
->isl_bytes
);
810 (void) sprintf(t
, " Pkts %ld Bytes %ld",
811 sl
->isl_pkts
, sl
->isl_bytes
);
818 if (opts
& OPT_SYSLOG
)
819 syslog(LOG_INFO
, "%s", line
);
821 (void) fprintf(log
, "%s", line
);
825 static void print_log(logtype
, log
, buf
, blen
)
831 char *bp
= NULL
, *bpo
= NULL
;
835 ipl
= (iplog_t
*)buf
;
836 if ((u_long
)ipl
& (sizeof(long)-1)) {
839 bp
= (char *)malloc(blen
);
840 bcopy((char *)ipl
, bp
, blen
);
848 if (ipl
->ipl_magic
!= IPL_MAGIC
) {
849 /* invalid data or out of sync */
852 psize
= ipl
->ipl_dsize
;
856 print_ipflog(log
, buf
, psize
);
859 print_natlog(log
, buf
, psize
);
862 print_statelog(log
, buf
, psize
);
875 static void print_ipflog(log
, buf
, blen
)
885 int i
, v
, lvl
, res
, len
, off
, plen
, ipoff
;
895 ipl
= (iplog_t
*)buf
;
896 ipf
= (ipflog_t
*)((char *)buf
+ IPLOG_SIZE
);
897 ip
= (ip_t
*)((char *)ipf
+ sizeof(*ipf
));
899 res
= (opts
& OPT_RESOLVE
) ? 1 : 0;
902 tm
= localtime((time_t *)&ipl
->ipl_sec
);
905 ip
->ip_len
= ntohs(ip
->ip_len
);
909 if (!(opts
& OPT_SYSLOG
)) {
910 (void) strftime(t
, len
, "%d/%m/%Y ", tm
);
915 (void) strftime(t
, len
, "%T", tm
);
917 (void) sprintf(t
, ".%-.6ld ", ipl
->ipl_usec
);
919 if (ipl
->ipl_count
> 1) {
920 (void) sprintf(t
, "%dx ", ipl
->ipl_count
);
924 (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \
925 (defined(OpenBSD) && (OpenBSD >= 199603))) || defined(linux) || \
926 defined(__DragonFly__)
928 char ifname
[sizeof(ipf
->fl_ifname
) + 1];
930 strncpy(ifname
, (char *)ipf
->fl_ifname
, sizeof(ipf
->fl_ifname
));
931 ifname
[sizeof(ipf
->fl_ifname
)] = '\0';
932 (void) sprintf(t
, "%s", ifname
);
935 if (isalpha(*(t
- 1))) {
936 sprintf(t
, "%d", ipf
->fl_unit
);
942 for (len
= 0; len
< 3; len
++)
943 if (ipf
->fl_ifname
[len
] == '\0')
945 if (ipf
->fl_ifname
[len
])
947 (void) sprintf(t
, "%*.*s%u", len
, len
, ipf
->fl_ifname
, ipf
->fl_unit
);
950 if (ipf
->fl_group
== 0xffffffff)
953 (void) sprintf(t
, " @%u:", ipf
->fl_group
);
955 if (ipf
->fl_rule
== 0xffffffff)
958 (void) sprintf(t
, "%u ", ipf
->fl_rule
+ 1);
961 if (ipf
->fl_flags
& FF_SHORT
) {
964 } else if (ipf
->fl_flags
& FR_PASS
) {
965 if (ipf
->fl_flags
& FR_LOG
)
970 } else if (ipf
->fl_flags
& FR_BLOCK
) {
971 if (ipf
->fl_flags
& FR_LOG
)
976 } else if (ipf
->fl_flags
& FF_LOGNOMATCH
) {
983 if (ipf
->fl_loglevel
!= 0xffff)
984 lvl
= ipf
->fl_loglevel
;
994 p
= (u_short
)ip6
->ip6_nxt
;
995 s
= (u_32_t
*)&ip6
->ip6_src
;
996 d
= (u_32_t
*)&ip6
->ip6_dst
;
997 plen
= hl
+ ntohs(ip6
->ip6_plen
);
1002 } else if (v
== 4) {
1003 hl
= (ip
->ip_hl
<< 2);
1005 off
= ipoff
& IP_OFFMASK
;
1006 p
= (u_short
)ip
->ip_p
;
1007 s
= (u_32_t
*)&ip
->ip_src
;
1008 d
= (u_32_t
*)&ip
->ip_dst
;
1013 proto
= getproto(p
);
1015 if ((p
== IPPROTO_TCP
|| p
== IPPROTO_UDP
) && !off
) {
1016 tp
= (tcphdr_t
*)((char *)ip
+ hl
);
1017 if (!(ipf
->fl_flags
& FF_SHORT
)) {
1018 (void) sprintf(t
, "%s,%s -> ", hostname(res
, v
, s
),
1019 portname(res
, proto
, (u_int
)tp
->th_sport
));
1021 (void) sprintf(t
, "%s,%s PR %s len %hu %hu",
1022 hostname(res
, v
, d
),
1023 portname(res
, proto
, (u_int
)tp
->th_dport
),
1027 if (p
== IPPROTO_TCP
) {
1030 for (i
= 0; tcpfl
[i
].value
; i
++)
1031 if (tp
->th_flags
& tcpfl
[i
].value
)
1032 *t
++ = tcpfl
[i
].flag
;
1033 if (opts
& OPT_VERBOSE
) {
1034 (void) sprintf(t
, " %lu %lu %hu",
1035 (u_long
)(ntohl(tp
->th_seq
)),
1036 (u_long
)(ntohl(tp
->th_ack
)),
1043 (void) sprintf(t
, "%s -> ", hostname(res
, v
, s
));
1045 (void) sprintf(t
, "%s PR %s len %hu %hu",
1046 hostname(res
, v
, d
), proto
, hl
, plen
);
1048 } else if ((p
== IPPROTO_ICMPV6
) && !off
&& (v
== 6)) {
1049 ic
= (struct icmp
*)((char *)ip
+ hl
);
1050 (void) sprintf(t
, "%s -> ", hostname(res
, v
, s
));
1052 (void) sprintf(t
, "%s PR icmpv6 len %hu %hu icmpv6 %s",
1053 hostname(res
, v
, d
), hl
, plen
,
1054 icmpname6(ic
->icmp_type
, ic
->icmp_code
));
1055 } else if ((p
== IPPROTO_ICMP
) && !off
&& (v
== 4)) {
1056 ic
= (struct icmp
*)((char *)ip
+ hl
);
1057 (void) sprintf(t
, "%s -> ", hostname(res
, v
, s
));
1059 (void) sprintf(t
, "%s PR icmp len %hu %hu icmp %s",
1060 hostname(res
, v
, d
), hl
, plen
,
1061 icmpname(ic
->icmp_type
, ic
->icmp_code
));
1062 if (ic
->icmp_type
== ICMP_UNREACH
||
1063 ic
->icmp_type
== ICMP_SOURCEQUENCH
||
1064 ic
->icmp_type
== ICMP_PARAMPROB
||
1065 ic
->icmp_type
== ICMP_REDIRECT
||
1066 ic
->icmp_type
== ICMP_TIMXCEED
) {
1068 i
= ntohs(ipc
->ip_len
);
1069 ipoff
= ntohs(ipc
->ip_off
);
1070 proto
= getproto(ipc
->ip_p
);
1072 if (!(ipoff
& IP_OFFMASK
) &&
1073 ((ipc
->ip_p
== IPPROTO_TCP
) ||
1074 (ipc
->ip_p
== IPPROTO_UDP
))) {
1075 tp
= (tcphdr_t
*)((char *)ipc
+ hl
);
1077 (void) sprintf(t
, " for %s,%s -",
1078 HOSTNAME_V4(res
, ipc
->ip_src
),
1079 portname(res
, proto
,
1080 (u_int
)tp
->th_sport
));
1082 (void) sprintf(t
, " %s,%s PR %s len %hu %hu",
1083 HOSTNAME_V4(res
, ipc
->ip_dst
),
1084 portname(res
, proto
,
1085 (u_int
)tp
->th_dport
),
1086 proto
, ipc
->ip_hl
<< 2, i
);
1087 } else if (!(ipoff
& IP_OFFMASK
) &&
1088 (ipc
->ip_p
== IPPROTO_ICMP
)) {
1089 icmp
= (icmphdr_t
*)((char *)ipc
+ hl
);
1092 (void) sprintf(t
, " for %s -",
1093 HOSTNAME_V4(res
, ipc
->ip_src
));
1096 " %s PR icmp len %hu %hu icmp %d/%d",
1097 HOSTNAME_V4(res
, ipc
->ip_dst
),
1099 icmp
->icmp_type
, icmp
->icmp_code
);
1103 (void) sprintf(t
, " for %s -",
1104 HOSTNAME_V4(res
, ipc
->ip_src
));
1106 (void) sprintf(t
, " %s PR %s len %hu (%hu)",
1107 HOSTNAME_V4(res
, ipc
->ip_dst
), proto
,
1108 ipc
->ip_hl
<< 2, i
);
1110 if (ipoff
& IP_OFFMASK
) {
1111 (void) sprintf(t
, " (frag %d:%hu@%hu%s%s)",
1113 i
- (ipc
->ip_hl
<<2),
1114 (ipoff
& IP_OFFMASK
) << 3,
1115 ipoff
& IP_MF
? "+" : "",
1116 ipoff
& IP_DF
? "-" : "");
1121 (void) sprintf(t
, "%s -> ", hostname(res
, v
, s
));
1123 (void) sprintf(t
, "%s PR %s len %hu (%hu)",
1124 hostname(res
, v
, d
), proto
, hl
, plen
);
1126 if (off
& IP_OFFMASK
)
1127 (void) sprintf(t
, " (frag %d:%hu@%hu%s%s)",
1129 plen
- hl
, (off
& IP_OFFMASK
) << 3,
1130 ipoff
& IP_MF
? "+" : "",
1131 ipoff
& IP_DF
? "-" : "");
1135 if (ipf
->fl_flags
& FR_KEEPSTATE
) {
1136 (void) strcpy(t
, " K-S");
1140 if (ipf
->fl_flags
& FR_KEEPFRAG
) {
1141 (void) strcpy(t
, " K-F");
1145 if (ipf
->fl_dir
== 0)
1147 else if (ipf
->fl_dir
== 1)
1153 if (opts
& OPT_SYSLOG
)
1154 syslog(lvl
, "%s", line
);
1156 (void) fprintf(log
, "%s", line
);
1157 if (opts
& OPT_HEXHDR
)
1158 dumphex(log
, (u_char
*)buf
, sizeof(iplog_t
) + sizeof(*ipf
));
1159 if (opts
& OPT_HEXBODY
)
1160 dumphex(log
, (u_char
*)ip
, ipf
->fl_plen
+ ipf
->fl_hlen
);
1161 else if ((opts
& OPT_LOGBODY
) && (ipf
->fl_flags
& FR_LOGBODY
))
1162 dumphex(log
, (u_char
*)ip
+ ipf
->fl_hlen
, ipf
->fl_plen
);
1166 static void usage(prog
)
1169 fprintf(stderr
, "%s: [-NFhstvxX] [-f <logfile>]\n", prog
);
1174 static void write_pid(file
)
1180 if ((fd
= open(file
, O_CREAT
|O_TRUNC
|O_WRONLY
, 0644)) >= 0)
1181 fp
= fdopen(fd
, "w");
1184 fprintf(stderr
, "unable to open/create pid file: %s\n", file
);
1187 fprintf(fp
, "%d", getpid());
1193 static void flushlogs(file
, log
)
1197 int fd
, flushed
= 0;
1199 if ((fd
= open(file
, O_RDWR
)) == -1) {
1200 (void) fprintf(stderr
, "%s: open: %s\n",
1201 file
, STRERROR(errno
));
1205 if (ioctl(fd
, SIOCIPFFB
, &flushed
) == 0) {
1206 printf("%d bytes flushed from log buffer\n",
1210 perror("SIOCIPFFB");
1214 if (opts
& OPT_SYSLOG
)
1215 syslog(LOG_INFO
, "%d bytes flushed from log\n",
1217 else if (log
!= stdout
)
1218 fprintf(log
, "%d bytes flushed from log\n", flushed
);
1223 static void logopts(turnon
, options
)
1230 for (s
= options
; *s
; s
++)
1241 flags
|= OPT_FILTER
;
1244 fprintf(stderr
, "Unknown log option %c\n", *s
);
1256 int main(argc
, argv
)
1260 int fdt
[3], devices
= 0, make_daemon
= 0;
1261 char buf
[IPLLOGSIZE
], *iplfile
[3], *s
;
1262 int fd
[3], doread
, n
, i
;
1263 extern char *optarg
;
1270 fd
[0] = fd
[1] = fd
[2] = -1;
1271 fdt
[0] = fdt
[1] = fdt
[2] = -1;
1272 iplfile
[0] = IPL_NAME
;
1273 iplfile
[1] = IPNAT_NAME
;
1274 iplfile
[2] = IPSTATE_NAME
;
1276 while ((c
= getopt(argc
, argv
, "?abDf:FhnN:o:O:pP:sS:tvxX")) != -1)
1281 fdt
[0] = IPL_LOGIPF
;
1282 fdt
[1] = IPL_LOGNAT
;
1283 fdt
[2] = IPL_LOGSTATE
;
1286 opts
|= OPT_LOGBODY
;
1291 case 'f' : case 'I' :
1293 fdt
[0] = IPL_LOGIPF
;
1294 iplfile
[0] = optarg
;
1297 flushlogs(iplfile
[0], log
);
1298 flushlogs(iplfile
[1], log
);
1299 flushlogs(iplfile
[2], log
);
1302 opts
|= OPT_RESOLVE
;
1306 fdt
[1] = IPL_LOGNAT
;
1307 iplfile
[1] = optarg
;
1309 case 'o' : case 'O' :
1310 logopts(c
== 'o', optarg
);
1311 fdt
[0] = fdt
[1] = fdt
[2] = -1;
1312 if (opts
& OPT_FILTER
)
1313 fdt
[0] = IPL_LOGIPF
;
1315 fdt
[1] = IPL_LOGNAT
;
1316 if (opts
& OPT_STATE
)
1317 fdt
[2] = IPL_LOGSTATE
;
1320 opts
|= OPT_PORTNUM
;
1326 s
= strrchr(argv
[0], '/');
1331 openlog(s
, LOG_NDELAY
|LOG_PID
, LOGFAC
);
1337 fdt
[2] = IPL_LOGSTATE
;
1338 iplfile
[2] = optarg
;
1344 opts
|= OPT_VERBOSE
;
1347 opts
|= OPT_HEXBODY
;
1361 * Default action is to only open the filter log file.
1363 if ((fdt
[0] == -1) && (fdt
[1] == -1) && (fdt
[2] == -1))
1364 fdt
[0] = IPL_LOGIPF
;
1366 for (i
= 0; i
< 3; i
++) {
1369 if (!strcmp(iplfile
[i
], "-"))
1372 if ((fd
[i
] = open(iplfile
[i
], O_RDONLY
)) == -1) {
1373 (void) fprintf(stderr
,
1374 "%s: open: %s\n", iplfile
[i
],
1379 if (fstat(fd
[i
], &sb
) == -1) {
1380 (void) fprintf(stderr
, "%d: fstat: %s\n",
1381 fd
[i
], STRERROR(errno
));
1385 if (!(regular
[i
] = !S_ISCHR(sb
.st_mode
)))
1390 if (!(opts
& OPT_SYSLOG
)) {
1391 logfile
= argv
[optind
];
1392 log
= logfile
? fopen(logfile
, "a") : stdout
;
1394 (void) fprintf(stderr
, "%s: fopen: %s\n",
1395 argv
[optind
], STRERROR(errno
));
1399 setvbuf(log
, NULL
, _IONBF
, 0);
1403 if (make_daemon
&& ((log
!= stdout
) || (opts
& OPT_SYSLOG
))) {
1405 daemon(0, !(opts
& OPT_SYSLOG
));
1408 if ((pid
= fork()) > 0)
1411 (void) fprintf(stderr
, "%s: fork() failed: %s\n",
1412 argv
[0], STRERROR(errno
));
1417 if ((opts
& OPT_SYSLOG
))
1425 signal(SIGHUP
, handlehup
);
1427 for (doread
= 1; doread
; ) {
1430 for (i
= 0; i
< 3; i
++) {
1435 if (ioctl(fd
[i
], FIONREAD
, &tr
) == -1) {
1436 if (opts
& OPT_SYSLOG
)
1438 "ioctl(FIONREAD): %m");
1440 perror("ioctl(FIONREAD)");
1445 tr
= (lseek(fd
[i
], 0, SEEK_CUR
) < sb
.st_size
);
1446 if (!tr
&& !(opts
& OPT_TAIL
))
1453 tr
= read_log(fd
[i
], &n
, buf
, sizeof(buf
));
1466 if (opts
& OPT_SYSLOG
)
1467 syslog(LOG_CRIT
, "read: %m\n");
1473 if (opts
& OPT_SYSLOG
)
1474 syslog(LOG_CRIT
, "aborting logging\n");
1476 fprintf(log
, "aborting logging\n");
1483 print_log(fdt
[i
], log
, buf
, n
);
1484 if (!(opts
& OPT_SYSLOG
))
1490 if (!nr
&& ((opts
& OPT_TAIL
) || devices
))