4 * Copyright (C) 2001-2006 by Darren Reed.
6 * See the IPFILTER.LICENCE file for details on licencing.
9 #define SOLARIS (defined(__SVR4) || defined(__svr4__)) && defined(sun)
12 #include <sys/types.h>
14 #include <sys/param.h>
20 #include <sys/socket.h>
21 #include <sys/ioctl.h>
29 #if !defined(__SVR4) && !defined(__svr4__)
30 # if (__FreeBSD_version >= 300000)
31 # include <sys/dirent.h>
36 # include <sys/filio.h>
37 # include <sys/byteorder.h>
39 #if !defined(__hpux) && (!defined(__SVR4) && !defined(__GNUC__))
45 #include <netinet/in.h>
46 #include <netinet/in_systm.h>
48 #include <netinet/ip.h>
49 #if !defined(__hpux) && !defined(linux)
50 # include <netinet/tcp_fsm.h>
53 #include <arpa/inet.h>
54 #include <arpa/nameser.h>
61 # include <sys/protosw.h>
62 # include <netinet/ip_var.h>
65 #include <netinet/tcp.h>
66 #include <netinet/ip_icmp.h>
71 #include "netinet/ip_compat.h"
72 #include <netinet/tcpip.h>
73 #include "netinet/ip_fil.h"
74 #include "netinet/ip_nat.h"
75 #include "netinet/ip_state.h"
76 #include "netinet/ip_proxy.h"
80 static const char sccsid
[] = "@(#)ipmon.c 1.21 6/5/96 (C)1993-2000 Darren Reed";
81 static const char rcsid
[] = "@(#)Id: ipmon.c,v 1.33.2.24 2009/07/21 22:32:53 darrenr Exp";
85 #if defined(sun) && !defined(SOLARIS2)
86 #define STRERROR(x) sys_errlist[x]
87 extern char *sys_errlist
[];
89 #define STRERROR(x) strerror(x)
99 typedef struct icmp_subtype
{
104 typedef struct icmp_type
{
106 struct icmp_subtype
*it_subtable
;
112 #define IST_SZ(x) (sizeof(x)/sizeof(icmp_subtype_t))
115 struct flags tcpfl
[] = {
128 static char *pidfile
= "/etc/opt/ipf/ipmon.pid";
131 static char *pidfile
= "/var/run/ipmon.pid";
133 static char *pidfile
= "/etc/ipmon.pid";
137 static char line
[2048];
139 static char *logfile
= NULL
;
140 static FILE *binarylog
= NULL
;
141 static char *binarylogfile
= NULL
;
142 static int donehup
= 0;
143 static void usage
__P((char *));
144 static void handlehup
__P((int));
145 static void flushlogs
__P((char *, FILE *));
146 static void print_log
__P((int, FILE *, char *, int));
147 static void print_ipflog
__P((FILE *, char *, int));
148 static void print_natlog
__P((FILE *, char *, int));
149 static void print_statelog
__P((FILE *, char *, int));
150 static int read_log
__P((int, int *, char *, int));
151 static void write_pid
__P((char *));
152 static char *icmpname
__P((u_int
, u_int
));
153 static char *icmpname6
__P((u_int
, u_int
));
154 static icmp_type_t
*find_icmptype
__P((int, icmp_type_t
*, size_t));
155 static icmp_subtype_t
*find_icmpsubtype
__P((int, icmp_subtype_t
*, size_t));
157 static struct tm
*get_tm
__P((u_32_t
));
159 static struct tm
*get_tm
__P((time_t));
162 char *hostname
__P((int, int, u_32_t
*));
163 char *portname
__P((int, char *, u_int
));
164 int main
__P((int, char *[]));
166 static void logopts
__P((int, char *));
167 static void init_tabs
__P((void));
168 static char *getproto
__P((u_int
));
170 static char **protocols
= NULL
;
171 static char **udp_ports
= NULL
;
172 static char **tcp_ports
= NULL
;
173 static char *conf_file
= NULL
;
176 #define OPT_SYSLOG 0x001
177 #define OPT_RESOLVE 0x002
178 #define OPT_HEXBODY 0x004
179 #define OPT_VERBOSE 0x008
180 #define OPT_HEXHDR 0x010
181 #define OPT_TAIL 0x020
182 #define OPT_NAT 0x080
183 #define OPT_STATE 0x100
184 #define OPT_FILTER 0x200
185 #define OPT_PORTNUM 0x400
186 #define OPT_LOGALL (OPT_NAT|OPT_STATE|OPT_FILTER)
187 #define OPT_LOGBODY 0x800
189 #define HOSTNAME_V4(a,b) hostname((a), 4, (u_32_t *)&(b))
192 #define LOGFAC LOG_LOCAL0
197 static icmp_subtype_t icmpunreachnames
[] = {
198 { ICMP_UNREACH_NET
, "net" },
199 { ICMP_UNREACH_HOST
, "host" },
200 { ICMP_UNREACH_PROTOCOL
, "protocol" },
201 { ICMP_UNREACH_PORT
, "port" },
202 { ICMP_UNREACH_NEEDFRAG
, "needfrag" },
203 { ICMP_UNREACH_SRCFAIL
, "srcfail" },
204 { ICMP_UNREACH_NET_UNKNOWN
, "net_unknown" },
205 { ICMP_UNREACH_HOST_UNKNOWN
, "host_unknown" },
206 { ICMP_UNREACH_NET
, "isolated" },
207 { ICMP_UNREACH_NET_PROHIB
, "net_prohib" },
208 { ICMP_UNREACH_NET_PROHIB
, "host_prohib" },
209 { ICMP_UNREACH_TOSNET
, "tosnet" },
210 { ICMP_UNREACH_TOSHOST
, "toshost" },
211 { ICMP_UNREACH_ADMIN_PROHIBIT
, "admin_prohibit" },
215 static icmp_subtype_t redirectnames
[] = {
216 { ICMP_REDIRECT_NET
, "net" },
217 { ICMP_REDIRECT_HOST
, "host" },
218 { ICMP_REDIRECT_TOSNET
, "tosnet" },
219 { ICMP_REDIRECT_TOSHOST
, "toshost" },
223 static icmp_subtype_t timxceednames
[] = {
224 { ICMP_TIMXCEED_INTRANS
, "transit" },
225 { ICMP_TIMXCEED_REASS
, "reassem" },
229 static icmp_subtype_t paramnames
[] = {
230 { ICMP_PARAMPROB_ERRATPTR
, "errata_pointer" },
231 { ICMP_PARAMPROB_OPTABSENT
, "optmissing" },
232 { ICMP_PARAMPROB_LENGTH
, "length" },
236 static icmp_type_t icmptypes
[] = {
237 { ICMP_ECHOREPLY
, NULL
, 0, "echoreply" },
238 { -1, NULL
, 0, NULL
},
239 { -1, NULL
, 0, NULL
},
240 { ICMP_UNREACH
, icmpunreachnames
,
241 IST_SZ(icmpunreachnames
),"unreach" },
242 { ICMP_SOURCEQUENCH
, NULL
, 0, "sourcequench" },
243 { ICMP_REDIRECT
, redirectnames
,
244 IST_SZ(redirectnames
), "redirect" },
245 { -1, NULL
, 0, NULL
},
246 { -1, NULL
, 0, NULL
},
247 { ICMP_ECHO
, NULL
, 0, "echo" },
248 { ICMP_ROUTERADVERT
, NULL
, 0, "routeradvert" },
249 { ICMP_ROUTERSOLICIT
, NULL
, 0, "routersolicit" },
250 { ICMP_TIMXCEED
, timxceednames
,
251 IST_SZ(timxceednames
), "timxceed" },
252 { ICMP_PARAMPROB
, paramnames
,
253 IST_SZ(paramnames
), "paramprob" },
254 { ICMP_TSTAMP
, NULL
, 0, "timestamp" },
255 { ICMP_TSTAMPREPLY
, NULL
, 0, "timestampreply" },
256 { ICMP_IREQ
, NULL
, 0, "inforeq" },
257 { ICMP_IREQREPLY
, NULL
, 0, "inforeply" },
258 { ICMP_MASKREQ
, NULL
, 0, "maskreq" },
259 { ICMP_MASKREPLY
, NULL
, 0, "maskreply" },
260 { -2, NULL
, 0, NULL
}
263 static icmp_subtype_t icmpredirect6
[] = {
264 { ICMP6_DST_UNREACH_NOROUTE
, "noroute" },
265 { ICMP6_DST_UNREACH_ADMIN
, "admin" },
266 { ICMP6_DST_UNREACH_NOTNEIGHBOR
, "neighbour" },
267 { ICMP6_DST_UNREACH_ADDR
, "address" },
268 { ICMP6_DST_UNREACH_NOPORT
, "noport" },
272 static icmp_subtype_t icmptimexceed6
[] = {
273 { ICMP6_TIME_EXCEED_TRANSIT
, "intransit" },
274 { ICMP6_TIME_EXCEED_REASSEMBLY
, "reassem" },
278 static icmp_subtype_t icmpparamprob6
[] = {
279 { ICMP6_PARAMPROB_HEADER
, "header" },
280 { ICMP6_PARAMPROB_NEXTHEADER
, "nextheader" },
281 { ICMP6_PARAMPROB_OPTION
, "option" },
285 static icmp_subtype_t icmpquerysubject6
[] = {
286 { ICMP6_NI_SUBJ_IPV6
, "ipv6" },
287 { ICMP6_NI_SUBJ_FQDN
, "fqdn" },
288 { ICMP6_NI_SUBJ_IPV4
, "ipv4" },
292 static icmp_subtype_t icmpnodeinfo6
[] = {
293 { ICMP6_NI_SUCCESS
, "success" },
294 { ICMP6_NI_REFUSED
, "refused" },
295 { ICMP6_NI_UNKNOWN
, "unknown" },
299 static icmp_subtype_t icmprenumber6
[] = {
300 { ICMP6_ROUTER_RENUMBERING_COMMAND
, "command" },
301 { ICMP6_ROUTER_RENUMBERING_RESULT
, "result" },
302 { ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET
, "seqnum_reset" },
306 static icmp_type_t icmptypes6
[] = {
307 { 0, NULL
, 0, NULL
},
308 { ICMP6_DST_UNREACH
, icmpredirect6
,
309 IST_SZ(icmpredirect6
), "unreach" },
310 { ICMP6_PACKET_TOO_BIG
, NULL
, 0, "toobig" },
311 { ICMP6_TIME_EXCEEDED
, icmptimexceed6
,
312 IST_SZ(icmptimexceed6
), "timxceed" },
313 { ICMP6_PARAM_PROB
, icmpparamprob6
,
314 IST_SZ(icmpparamprob6
), "paramprob" },
315 { ICMP6_ECHO_REQUEST
, NULL
, 0, "echo" },
316 { ICMP6_ECHO_REPLY
, NULL
, 0, "echoreply" },
317 { ICMP6_MEMBERSHIP_QUERY
, icmpquerysubject6
,
318 IST_SZ(icmpquerysubject6
), "groupmemberquery" },
319 { ICMP6_MEMBERSHIP_REPORT
,NULL
, 0, "groupmemberreport" },
320 { ICMP6_MEMBERSHIP_REDUCTION
,NULL
, 0, "groupmemberterm" },
321 { ND_ROUTER_SOLICIT
, NULL
, 0, "routersolicit" },
322 { ND_ROUTER_ADVERT
, NULL
, 0, "routeradvert" },
323 { ND_NEIGHBOR_SOLICIT
, NULL
, 0, "neighborsolicit" },
324 { ND_NEIGHBOR_ADVERT
, NULL
, 0, "neighboradvert" },
325 { ND_REDIRECT
, NULL
, 0, "redirect" },
326 { ICMP6_ROUTER_RENUMBERING
, icmprenumber6
,
327 IST_SZ(icmprenumber6
), "routerrenumber" },
328 { ICMP6_WRUREQUEST
, NULL
, 0, "whoareyourequest" },
329 { ICMP6_WRUREPLY
, NULL
, 0, "whoareyoureply" },
330 { ICMP6_FQDN_QUERY
, NULL
, 0, "fqdnquery" },
331 { ICMP6_FQDN_REPLY
, NULL
, 0, "fqdnreply" },
332 { ICMP6_NI_QUERY
, icmpnodeinfo6
,
333 IST_SZ(icmpnodeinfo6
), "nodeinforequest" },
334 { ICMP6_NI_REPLY
, NULL
, 0, "nodeinforeply" },
335 { MLD6_MTRACE_RESP
, NULL
, 0, "mtraceresponse" },
336 { MLD6_MTRACE
, NULL
, 0, "mtracerequest" },
337 { -2, NULL
, 0, NULL
}
340 static icmp_subtype_t
*find_icmpsubtype(type
, table
, tablesz
)
342 icmp_subtype_t
*table
;
351 if ((type
< 0) || (type
> table
[tablesz
- 2].ist_val
))
355 if (table
[type
].ist_val
== type
)
358 for (i
= 0, ist
= table
; ist
->ist_val
!= -2; i
++, ist
++)
359 if (ist
->ist_val
== type
)
365 static icmp_type_t
*find_icmptype(type
, table
, tablesz
)
376 if ((type
< 0) || (type
> table
[tablesz
- 2].it_val
))
380 if (table
[type
].it_val
== type
)
383 for (i
= 0, it
= table
; it
->it_val
!= -2; i
++, it
++)
384 if (it
->it_val
== type
)
390 static void handlehup(sig
)
393 signal(SIGHUP
, handlehup
);
398 static void init_tabs()
405 if (protocols
!= NULL
) {
406 for (i
= 0; i
< 256; i
++)
407 if (protocols
[i
] != NULL
) {
414 protocols
= (char **)malloc(256 * sizeof(*protocols
));
415 if (protocols
!= NULL
) {
416 bzero((char *)protocols
, 256 * sizeof(*protocols
));
419 while ((p
= getprotoent()) != NULL
)
420 if (p
->p_proto
>= 0 && p
->p_proto
<= 255 &&
421 p
->p_name
!= NULL
&& protocols
[p
->p_proto
] == NULL
)
422 protocols
[p
->p_proto
] = strdup(p
->p_name
);
426 protocols
[0] = strdup("ip");
429 free(protocols
[252]);
430 protocols
[252] = NULL
;
434 if (udp_ports
!= NULL
) {
435 for (i
= 0; i
< 65536; i
++)
436 if (udp_ports
[i
] != NULL
) {
443 udp_ports
= (char **)malloc(65536 * sizeof(*udp_ports
));
444 if (udp_ports
!= NULL
)
445 bzero((char *)udp_ports
, 65536 * sizeof(*udp_ports
));
447 if (tcp_ports
!= NULL
) {
448 for (i
= 0; i
< 65536; i
++)
449 if (tcp_ports
[i
] != NULL
) {
456 tcp_ports
= (char **)malloc(65536 * sizeof(*tcp_ports
));
457 if (tcp_ports
!= NULL
)
458 bzero((char *)tcp_ports
, 65536 * sizeof(*tcp_ports
));
461 while ((s
= getservent()) != NULL
) {
462 if (s
->s_proto
== NULL
)
464 else if (!strcmp(s
->s_proto
, "tcp")) {
465 port
= ntohs(s
->s_port
);
468 } else if (!strcmp(s
->s_proto
, "udp")) {
469 port
= ntohs(s
->s_port
);
474 if ((port
< 0 || port
> 65535) || (name
== NULL
))
477 tab
[port
] = strdup(name
);
483 static char *getproto(p
)
490 s
= protocols
? protocols
[p
] : NULL
;
492 sprintf(pnum
, "%u", p
);
499 static int read_log(fd
, lenp
, buf
, bufsize
)
500 int fd
, bufsize
, *lenp
;
505 nr
= read(fd
, buf
, bufsize
);
508 if ((nr
< 0) && (errno
!= EINTR
))
515 char *hostname(res
, v
, ip
)
519 # define MAX_INETA 16
520 static char hname
[MAXHOSTNAMELEN
+ MAX_INETA
+ 3];
522 static char hostbuf
[MAXHOSTNAMELEN
+1];
530 return inet_ntoa(ipa
);
531 hp
= gethostbyaddr((char *)ip
, sizeof(*ip
), AF_INET
);
533 return inet_ntoa(ipa
);
534 sprintf(hname
, "%.*s[%s]", MAXHOSTNAMELEN
, hp
->h_name
,
539 (void) inet_ntop(AF_INET6
, ip
, hostbuf
, sizeof(hostbuf
) - 1);
540 hostbuf
[MAXHOSTNAMELEN
] = '\0';
548 char *portname(res
, proto
, port
)
553 static char pname
[8];
558 (void) sprintf(pname
, "%u", port
);
559 if (!res
|| (opts
& OPT_PORTNUM
))
562 if (!strcmp(proto
, "tcp"))
564 else if (!strcmp(proto
, "udp"))
572 static char *icmpname(type
, code
)
576 static char name
[80];
582 it
= find_icmptype(type
, icmptypes
, sizeof(icmptypes
) / sizeof(*it
));
587 sprintf(name
, "icmptype(%d)/", type
);
589 sprintf(name
, "%s/", s
);
592 if (it
!= NULL
&& it
->it_subtable
!= NULL
)
593 ist
= find_icmpsubtype(code
, it
->it_subtable
, it
->it_stsize
);
595 if (ist
!= NULL
&& ist
->ist_name
!= NULL
)
596 strcat(name
, ist
->ist_name
);
598 sprintf(name
+ strlen(name
), "%d", code
);
603 static char *icmpname6(type
, code
)
607 static char name
[80];
613 it
= find_icmptype(type
, icmptypes6
, sizeof(icmptypes6
) / sizeof(*it
));
618 sprintf(name
, "icmpv6type(%d)/", type
);
620 sprintf(name
, "%s/", s
);
623 if (it
!= NULL
&& it
->it_subtable
!= NULL
)
624 ist
= find_icmpsubtype(code
, it
->it_subtable
, it
->it_stsize
);
626 if (ist
!= NULL
&& ist
->ist_name
!= NULL
)
627 strcat(name
, ist
->ist_name
);
629 sprintf(name
+ strlen(name
), "%d", code
);
635 void dumphex(log
, dopts
, buf
, len
)
643 u_char
*s
= (u_char
*)buf
, *t
= (u_char
*)hline
;
645 if (buf
== NULL
|| len
== 0)
650 for (i
= len
, j
= 0; i
; i
--, j
++, s
++) {
651 if (j
&& !(j
& 0xf)) {
654 if ((dopts
& OPT_SYSLOG
))
655 syslog(LOG_INFO
, "%s", hline
);
656 else if (log
!= NULL
)
661 sprintf((char *)t
, "%02x", *s
& 0xff);
663 if (!((j
+ 1) & 0xf)) {
665 sprintf((char *)t
, " ");
667 for (k
= 16; k
; k
--, s
++)
668 *t
++ = (ISPRINT(*s
) ? *s
: '.');
677 for (k
= 16 - (j
& 0xf); k
; k
--) {
682 sprintf((char *)t
, " ");
685 for (k
= j
& 0xf; k
; k
--, s
++)
686 *t
++ = (ISPRINT(*s
) ? *s
: '.');
690 if ((dopts
& OPT_SYSLOG
) != 0)
691 syslog(LOG_INFO
, "%s", hline
);
692 else if (log
!= NULL
) {
699 static struct tm
*get_tm(sec
)
714 static void print_natlog(log
, buf
, blen
)
720 iplog_t
*ipl
= (iplog_t
*)buf
;
726 nl
= (struct natlog
*)((char *)ipl
+ sizeof(*ipl
));
727 res
= (opts
& OPT_RESOLVE
) ? 1 : 0;
728 tm
= get_tm(ipl
->ipl_sec
);
730 if (!(opts
& OPT_SYSLOG
)) {
731 (void) strftime(t
, len
, "%d/%m/%Y ", tm
);
736 (void) strftime(t
, len
, "%T", tm
);
738 (void) sprintf(t
, ".%-.6ld @%hd ", (long)ipl
->ipl_usec
,
742 if (nl
->nl_type
== NL_NEWMAP
)
743 strcpy(t
, "NAT:MAP ");
744 else if (nl
->nl_type
== NL_NEWRDR
)
745 strcpy(t
, "NAT:RDR ");
746 else if (nl
->nl_type
== NL_FLUSH
)
747 strcpy(t
, "NAT:FLUSH ");
748 else if (nl
->nl_type
== NL_EXPIRE
)
749 strcpy(t
, "NAT:EXPIRE ");
750 else if (nl
->nl_type
== NL_NEWBIMAP
)
751 strcpy(t
, "NAT:BIMAP ");
752 else if (nl
->nl_type
== NL_NEWBLOCK
)
753 strcpy(t
, "NAT:MAPBLOCK ");
754 else if (nl
->nl_type
== NL_CLONE
)
755 strcpy(t
, "NAT:CLONE ");
756 else if (nl
->nl_type
== NL_DESTROY
)
757 strcpy(t
, "NAT:DESTROY ");
759 sprintf(t
, "Type: %d ", nl
->nl_type
);
762 proto
= getproto(nl
->nl_p
);
764 (void) sprintf(t
, "%s,%s <- -> ", HOSTNAME_V4(res
, nl
->nl_inip
),
765 portname(res
, proto
, (u_int
)nl
->nl_inport
));
767 (void) sprintf(t
, "%s,%s ", HOSTNAME_V4(res
, nl
->nl_outip
),
768 portname(res
, proto
, (u_int
)nl
->nl_outport
));
770 (void) sprintf(t
, "[%s,%s PR %s]", HOSTNAME_V4(res
, nl
->nl_origip
),
771 portname(res
, proto
, (u_int
)nl
->nl_origport
),
774 if (nl
->nl_type
== NL_EXPIRE
) {
776 (void) sprintf(t
, " Pkts %qd/%qd Bytes %qd/%qd",
777 (long long)nl
->nl_pkts
[0],
778 (long long)nl
->nl_pkts
[1],
779 (long long)nl
->nl_bytes
[0],
780 (long long)nl
->nl_bytes
[1]);
782 (void) sprintf(t
, " Pkts %ld/%ld Bytes %ld/%ld",
783 nl
->nl_pkts
[0], nl
->nl_pkts
[1],
784 nl
->nl_bytes
[0], nl
->nl_bytes
[1]);
791 if (opts
& OPT_SYSLOG
)
792 syslog(LOG_INFO
, "%s", line
);
793 else if (log
!= NULL
)
794 (void) fprintf(log
, "%s", line
);
798 static void print_statelog(log
, buf
, blen
)
804 iplog_t
*ipl
= (iplog_t
*)buf
;
805 char *t
= line
, *proto
;
809 sl
= (struct ipslog
*)((char *)ipl
+ sizeof(*ipl
));
810 res
= (opts
& OPT_RESOLVE
) ? 1 : 0;
811 tm
= get_tm(ipl
->ipl_sec
);
813 if (!(opts
& OPT_SYSLOG
)) {
814 (void) strftime(t
, len
, "%d/%m/%Y ", tm
);
819 (void) strftime(t
, len
, "%T", tm
);
821 (void) sprintf(t
, ".%-.6ld ", (long)ipl
->ipl_usec
);
824 switch (sl
->isl_type
)
827 strcpy(t
, "STATE:NEW ");
831 strcpy(t
, "STATE:CLONED ");
835 if ((sl
->isl_p
== IPPROTO_TCP
) &&
836 (sl
->isl_state
[0] > IPF_TCPS_ESTABLISHED
||
837 sl
->isl_state
[1] > IPF_TCPS_ESTABLISHED
))
838 strcpy(t
, "STATE:CLOSE ");
840 strcpy(t
, "STATE:EXPIRE ");
844 strcpy(t
, "STATE:FLUSH ");
847 case ISL_INTERMEDIATE
:
848 strcpy(t
, "STATE:INTERMEDIATE ");
852 strcpy(t
, "STATE:REMOVE ");
856 strcpy(t
, "STATE:KILLED ");
860 strcpy(t
, "STATE:UNLOAD ");
864 sprintf(t
, "Type: %d ", sl
->isl_type
);
869 proto
= getproto(sl
->isl_p
);
871 if (sl
->isl_p
== IPPROTO_TCP
|| sl
->isl_p
== IPPROTO_UDP
) {
872 (void) sprintf(t
, "%s,%s -> ",
873 hostname(res
, sl
->isl_v
, (u_32_t
*)&sl
->isl_src
),
874 portname(res
, proto
, (u_int
)sl
->isl_sport
));
876 (void) sprintf(t
, "%s,%s PR %s",
877 hostname(res
, sl
->isl_v
, (u_32_t
*)&sl
->isl_dst
),
878 portname(res
, proto
, (u_int
)sl
->isl_dport
), proto
);
879 } else if (sl
->isl_p
== IPPROTO_ICMP
) {
880 (void) sprintf(t
, "%s -> ", hostname(res
, sl
->isl_v
,
881 (u_32_t
*)&sl
->isl_src
));
883 (void) sprintf(t
, "%s PR icmp %d",
884 hostname(res
, sl
->isl_v
, (u_32_t
*)&sl
->isl_dst
),
886 } else if (sl
->isl_p
== IPPROTO_ICMPV6
) {
887 (void) sprintf(t
, "%s -> ", hostname(res
, sl
->isl_v
,
888 (u_32_t
*)&sl
->isl_src
));
890 (void) sprintf(t
, "%s PR icmpv6 %d",
891 hostname(res
, sl
->isl_v
, (u_32_t
*)&sl
->isl_dst
),
894 (void) sprintf(t
, "%s -> ",
895 hostname(res
, sl
->isl_v
, (u_32_t
*)&sl
->isl_src
));
897 (void) sprintf(t
, "%s PR %s",
898 hostname(res
, sl
->isl_v
, (u_32_t
*)&sl
->isl_dst
),
902 if (sl
->isl_tag
!= FR_NOLOGTAG
) {
903 (void) sprintf(t
, " tag %u", sl
->isl_tag
);
906 if (sl
->isl_type
!= ISL_NEW
) {
910 " Forward: Pkts in %" PRId64
" Bytes in %" PRId64
911 " Pkts out %" PRId64
" Bytes out %" PRId64
912 " Backward: Pkts in %" PRId64
" Bytes in %" PRId64
913 " Pkts out %" PRId64
" Bytes out %" PRId64
,
915 " 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",
918 " 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",
920 sl
->isl_pkts
[0], sl
->isl_bytes
[0],
921 sl
->isl_pkts
[1], sl
->isl_bytes
[1],
922 sl
->isl_pkts
[2], sl
->isl_bytes
[2],
923 sl
->isl_pkts
[3], sl
->isl_bytes
[3]);
930 if (opts
& OPT_SYSLOG
)
931 syslog(LOG_INFO
, "%s", line
);
932 else if (log
!= NULL
)
933 (void) fprintf(log
, "%s", line
);
937 static void print_log(logtype
, log
, buf
, blen
)
943 char *bp
= NULL
, *bpo
= NULL
;
947 ipl
= (iplog_t
*)buf
;
948 if ((u_long
)ipl
& (sizeof(long)-1)) {
951 bp
= (char *)malloc(blen
);
952 bcopy((char *)ipl
, bp
, blen
);
961 psize
= ipl
->ipl_dsize
;
966 fwrite(buf
, psize
, 1, binarylog
);
970 if (logtype
== IPL_LOGIPF
) {
971 if (ipl
->ipl_magic
== IPL_MAGIC
)
972 print_ipflog(log
, buf
, psize
);
974 } else if (logtype
== IPL_LOGNAT
) {
975 if (ipl
->ipl_magic
== IPL_MAGIC_NAT
)
976 print_natlog(log
, buf
, psize
);
978 } else if (logtype
== IPL_LOGSTATE
) {
979 if (ipl
->ipl_magic
== IPL_MAGIC_STATE
)
980 print_statelog(log
, buf
, psize
);
992 static void print_ipflog(log
, buf
, blen
)
1002 int i
, v
, lvl
, res
, len
, off
, plen
, ipoff
, defaction
;
1009 struct ip6_ext
*ehp
;
1015 ipl
= (iplog_t
*)buf
;
1016 ipf
= (ipflog_t
*)((char *)buf
+ sizeof(*ipl
));
1017 ip
= (ip_t
*)((char *)ipf
+ sizeof(*ipf
));
1019 res
= (opts
& OPT_RESOLVE
) ? 1 : 0;
1022 tm
= get_tm(ipl
->ipl_sec
);
1025 if (!(opts
& OPT_SYSLOG
)) {
1026 (void) strftime(t
, len
, "%d/%m/%Y ", tm
);
1031 (void) strftime(t
, len
, "%T", tm
);
1033 (void) sprintf(t
, ".%-.6ld ", (long)ipl
->ipl_usec
);
1035 if (ipl
->ipl_count
> 1) {
1036 (void) sprintf(t
, "%dx ", ipl
->ipl_count
);
1039 #if (defined(MENTAT) || \
1040 (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \
1041 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) || \
1042 (defined(OpenBSD) && (OpenBSD >= 199603))) || defined(linux)
1044 char ifname
[sizeof(ipf
->fl_ifname
) + 1];
1046 strncpy(ifname
, ipf
->fl_ifname
, sizeof(ipf
->fl_ifname
));
1047 ifname
[sizeof(ipf
->fl_ifname
)] = '\0';
1048 (void) sprintf(t
, "%s", ifname
);
1050 # if defined(MENTAT) || defined(linux)
1053 * On Linux, the loopback interface is just "lo", not "lo0".
1055 if (strcmp(ifname
, "lo") != 0)
1057 if (ISALPHA(*(t
- 1))) {
1058 sprintf(t
, "%d", ipf
->fl_unit
);
1064 for (len
= 0; len
< 3; len
++)
1065 if (ipf
->fl_ifname
[len
] == '\0')
1067 if (ipf
->fl_ifname
[len
])
1069 (void) sprintf(t
, "%*.*s%u", len
, len
, ipf
->fl_ifname
, ipf
->fl_unit
);
1072 if ((ipf
->fl_group
[0] == (char)~0) && (ipf
->fl_group
[1] == '\0'))
1074 else if (ipf
->fl_group
[0] == '\0')
1075 (void) strcpy(t
, " @0:");
1077 (void) sprintf(t
, " @%s:", ipf
->fl_group
);
1079 if (ipf
->fl_rule
== 0xffffffff)
1082 (void) sprintf(t
, "%u ", ipf
->fl_rule
+ 1);
1087 if (ipf
->fl_lflags
& FI_SHORT
) {
1092 if (FR_ISPASS(ipf
->fl_flags
)) {
1093 if (ipf
->fl_flags
& FR_LOGP
)
1097 } else if (FR_ISBLOCK(ipf
->fl_flags
)) {
1098 if (ipf
->fl_flags
& FR_LOGB
)
1103 } else if ((ipf
->fl_flags
& FR_LOGMASK
) == FR_LOG
) {
1106 } else if (ipf
->fl_flags
& FF_LOGNOMATCH
) {
1112 if (ipf
->fl_loglevel
!= 0xffff)
1113 lvl
= ipf
->fl_loglevel
;
1123 p
= (u_short
)ip6
->ip6_nxt
;
1124 s
= (u_32_t
*)&ip6
->ip6_src
;
1125 d
= (u_32_t
*)&ip6
->ip6_dst
;
1126 plen
= hl
+ ntohs(ip6
->ip6_plen
);
1128 ehp
= (struct ip6_ext
*)((char *)ip6
+ hl
);
1132 case IPPROTO_HOPOPTS
:
1133 case IPPROTO_MOBILITY
:
1134 case IPPROTO_DSTOPTS
:
1135 case IPPROTO_ROUTING
:
1138 ehl
= 8 + (ehp
->ip6e_len
<< 3);
1140 ehp
= (struct ip6_ext
*)((char *)ehp
+ ehl
);
1142 case IPPROTO_FRAGMENT
:
1143 hl
+= sizeof(struct ip6_frag
);
1154 } else if (v
== 4) {
1155 hl
= IP_HL(ip
) << 2;
1157 off
= ipoff
& IP_OFFMASK
;
1158 p
= (u_short
)ip
->ip_p
;
1159 s
= (u_32_t
*)&ip
->ip_src
;
1160 d
= (u_32_t
*)&ip
->ip_dst
;
1165 proto
= getproto(p
);
1167 if ((p
== IPPROTO_TCP
|| p
== IPPROTO_UDP
) && !off
) {
1168 tp
= (tcphdr_t
*)((char *)ip
+ hl
);
1169 if (!(ipf
->fl_lflags
& FI_SHORT
)) {
1170 (void) sprintf(t
, "%s,%s -> ", hostname(res
, v
, s
),
1171 portname(res
, proto
, (u_int
)tp
->th_sport
));
1173 (void) sprintf(t
, "%s,%s PR %s len %hu %hu",
1174 hostname(res
, v
, d
),
1175 portname(res
, proto
, (u_int
)tp
->th_dport
),
1179 if (p
== IPPROTO_TCP
) {
1182 for (i
= 0; tcpfl
[i
].value
; i
++)
1183 if (tp
->th_flags
& tcpfl
[i
].value
)
1184 *t
++ = tcpfl
[i
].flag
;
1185 if (opts
& OPT_VERBOSE
) {
1186 (void) sprintf(t
, " %lu %lu %hu",
1187 (u_long
)(ntohl(tp
->th_seq
)),
1188 (u_long
)(ntohl(tp
->th_ack
)),
1195 (void) sprintf(t
, "%s -> ", hostname(res
, v
, s
));
1197 (void) sprintf(t
, "%s PR %s len %hu %hu",
1198 hostname(res
, v
, d
), proto
, hl
, plen
);
1200 } else if ((p
== IPPROTO_ICMPV6
) && !off
&& (v
== 6)) {
1201 ic
= (struct icmp
*)((char *)ip
+ hl
);
1202 (void) sprintf(t
, "%s -> ", hostname(res
, v
, s
));
1204 (void) sprintf(t
, "%s PR icmpv6 len %hu %hu icmpv6 %s",
1205 hostname(res
, v
, d
), hl
, plen
,
1206 icmpname6(ic
->icmp_type
, ic
->icmp_code
));
1207 } else if ((p
== IPPROTO_ICMP
) && !off
&& (v
== 4)) {
1208 ic
= (struct icmp
*)((char *)ip
+ hl
);
1209 (void) sprintf(t
, "%s -> ", hostname(res
, v
, s
));
1211 (void) sprintf(t
, "%s PR icmp len %hu %hu icmp %s",
1212 hostname(res
, v
, d
), hl
, plen
,
1213 icmpname(ic
->icmp_type
, ic
->icmp_code
));
1214 if (ic
->icmp_type
== ICMP_UNREACH
||
1215 ic
->icmp_type
== ICMP_SOURCEQUENCH
||
1216 ic
->icmp_type
== ICMP_PARAMPROB
||
1217 ic
->icmp_type
== ICMP_REDIRECT
||
1218 ic
->icmp_type
== ICMP_TIMXCEED
) {
1220 i
= ntohs(ipc
->ip_len
);
1222 * XXX - try to guess endian of ip_len in ICMP
1227 ipoff
= ntohs(ipc
->ip_off
);
1228 proto
= getproto(ipc
->ip_p
);
1230 if (!(ipoff
& IP_OFFMASK
) &&
1231 ((ipc
->ip_p
== IPPROTO_TCP
) ||
1232 (ipc
->ip_p
== IPPROTO_UDP
))) {
1233 tp
= (tcphdr_t
*)((char *)ipc
+ hl
);
1235 (void) sprintf(t
, " for %s,%s -",
1236 HOSTNAME_V4(res
, ipc
->ip_src
),
1237 portname(res
, proto
,
1238 (u_int
)tp
->th_sport
));
1240 (void) sprintf(t
, " %s,%s PR %s len %hu %hu",
1241 HOSTNAME_V4(res
, ipc
->ip_dst
),
1242 portname(res
, proto
,
1243 (u_int
)tp
->th_dport
),
1244 proto
, IP_HL(ipc
) << 2, i
);
1245 } else if (!(ipoff
& IP_OFFMASK
) &&
1246 (ipc
->ip_p
== IPPROTO_ICMP
)) {
1247 icmp
= (icmphdr_t
*)((char *)ipc
+ hl
);
1250 (void) sprintf(t
, " for %s -",
1251 HOSTNAME_V4(res
, ipc
->ip_src
));
1254 " %s PR icmp len %hu %hu icmp %d/%d",
1255 HOSTNAME_V4(res
, ipc
->ip_dst
),
1257 icmp
->icmp_type
, icmp
->icmp_code
);
1260 (void) sprintf(t
, " for %s -",
1261 HOSTNAME_V4(res
, ipc
->ip_src
));
1263 (void) sprintf(t
, " %s PR %s len %hu (%hu)",
1264 HOSTNAME_V4(res
, ipc
->ip_dst
), proto
,
1265 IP_HL(ipc
) << 2, i
);
1267 if (ipoff
& IP_OFFMASK
) {
1269 "(frag %d:%hu@%hu%s%s)",
1271 i
- (IP_HL(ipc
) << 2),
1272 (ipoff
& IP_OFFMASK
) << 3,
1273 ipoff
& IP_MF
? "+" : "",
1274 ipoff
& IP_DF
? "-" : "");
1280 (void) sprintf(t
, "%s -> ", hostname(res
, v
, s
));
1282 (void) sprintf(t
, "%s PR %s len %hu (%hu)",
1283 hostname(res
, v
, d
), proto
, hl
, plen
);
1285 if (off
& IP_OFFMASK
)
1286 (void) sprintf(t
, " (frag %d:%hu@%hu%s%s)",
1288 plen
- hl
, (off
& IP_OFFMASK
) << 3,
1289 ipoff
& IP_MF
? "+" : "",
1290 ipoff
& IP_DF
? "-" : "");
1295 if (ipf
->fl_flags
& FR_KEEPSTATE
) {
1296 (void) strcpy(t
, " K-S");
1300 if (ipf
->fl_flags
& FR_KEEPFRAG
) {
1301 (void) strcpy(t
, " K-F");
1305 if (ipf
->fl_dir
== 0)
1307 else if (ipf
->fl_dir
== 1)
1310 if (ipf
->fl_logtag
!= 0) {
1311 sprintf(t
, " log-tag %d", ipf
->fl_logtag
);
1314 if (ipf
->fl_nattag
.ipt_num
[0] != 0) {
1315 strcpy(t
, " nat-tag ");
1317 strncpy(t
, ipf
->fl_nattag
.ipt_tag
, sizeof(ipf
->fl_nattag
));
1320 if ((ipf
->fl_lflags
& FI_LOWTTL
) != 0) {
1321 strcpy(t
, " low-ttl");
1324 if ((ipf
->fl_lflags
& FI_OOW
) != 0) {
1328 if ((ipf
->fl_lflags
& FI_BAD
) != 0) {
1332 if ((ipf
->fl_lflags
& FI_NATED
) != 0) {
1336 if ((ipf
->fl_lflags
& FI_BADNAT
) != 0) {
1337 strcpy(t
, " bad-NAT");
1340 if ((ipf
->fl_lflags
& FI_BADSRC
) != 0) {
1341 strcpy(t
, " bad-src");
1344 if ((ipf
->fl_lflags
& FI_MULTICAST
) != 0) {
1345 strcpy(t
, " multicast");
1348 if ((ipf
->fl_lflags
& FI_BROADCAST
) != 0) {
1349 strcpy(t
, " broadcast");
1352 if ((ipf
->fl_lflags
& (FI_MULTICAST
|FI_BROADCAST
|FI_MBCAST
)) ==
1354 strcpy(t
, " mbcast");
1360 if (conf_file
!= NULL
)
1361 defaction
= check_action(buf
, line
, opts
, lvl
);
1362 if (defaction
== 0) {
1363 if (opts
& OPT_SYSLOG
)
1364 syslog(lvl
, "%s", line
);
1365 else if (log
!= NULL
)
1366 (void) fprintf(log
, "%s", line
);
1368 if (opts
& OPT_HEXHDR
)
1369 dumphex(log
, opts
, buf
,
1370 sizeof(iplog_t
) + sizeof(*ipf
));
1371 if (opts
& OPT_HEXBODY
)
1372 dumphex(log
, opts
, (char *)ip
,
1373 ipf
->fl_plen
+ ipf
->fl_hlen
);
1374 else if ((opts
& OPT_LOGBODY
) && (ipf
->fl_flags
& FR_LOGBODY
))
1375 dumphex(log
, opts
, (char *)ip
+ ipf
->fl_hlen
,
1381 static void usage(prog
)
1384 fprintf(stderr
, "%s: [-NFhstvxX] [-f <logfile>]\n", prog
);
1389 static void write_pid(file
)
1395 if ((fd
= open(file
, O_CREAT
|O_TRUNC
|O_WRONLY
, 0644)) >= 0) {
1396 fp
= fdopen(fd
, "w");
1400 "unable to open/create pid file: %s\n", file
);
1403 fprintf(fp
, "%d", getpid());
1409 static void flushlogs(file
, log
)
1413 int fd
, flushed
= 0;
1415 if ((fd
= open(file
, O_RDWR
)) == -1) {
1416 (void) fprintf(stderr
, "%s: open: %s\n",
1417 file
, STRERROR(errno
));
1421 if (ioctl(fd
, SIOCIPFFB
, &flushed
) == 0) {
1422 printf("%d bytes flushed from log buffer\n",
1426 perror("SIOCIPFFB");
1430 if (opts
& OPT_SYSLOG
) {
1431 syslog(LOG_INFO
, "%d bytes flushed from log\n",
1433 } else if ((log
!= stdout
) && (log
!= NULL
)) {
1434 fprintf(log
, "%d bytes flushed from log\n", flushed
);
1440 static void logopts(turnon
, options
)
1447 for (s
= options
; *s
; s
++)
1458 flags
|= OPT_FILTER
;
1461 fprintf(stderr
, "Unknown log option %c\n", *s
);
1473 int main(argc
, argv
)
1480 int fd
[3], doread
, n
, i
;
1481 int tr
, nr
, regular
[3], c
;
1482 int fdt
[3], devices
= 0, make_daemon
= 0;
1483 char buf
[DEFAULT_IPFLOGSIZE
], *iplfile
[3], *prog
;
1485 extern char *optarg
;
1487 n
= 0; /* XXX gcc */
1489 prog
= strrchr(argv
[0], '/');
1494 fd
[0] = fd
[1] = fd
[2] = -1;
1495 fdt
[0] = fdt
[1] = fdt
[2] = -1;
1496 iplfile
[0] = IPL_NAME
;
1497 iplfile
[1] = IPNAT_NAME
;
1498 iplfile
[2] = IPSTATE_NAME
;
1500 while ((c
= getopt(argc
, argv
,
1501 "?abB:C:Df:FhL:nN:o:O:pP:sS:tvxX")) != -1)
1506 fdt
[0] = IPL_LOGIPF
;
1507 fdt
[1] = IPL_LOGNAT
;
1508 fdt
[2] = IPL_LOGSTATE
;
1511 opts
|= OPT_LOGBODY
;
1514 binarylogfile
= optarg
;
1515 binarylog
= fopen(optarg
, "a");
1523 case 'f' : case 'I' :
1525 fdt
[0] = IPL_LOGIPF
;
1526 iplfile
[0] = optarg
;
1529 flushlogs(iplfile
[0], log
);
1530 flushlogs(iplfile
[1], log
);
1531 flushlogs(iplfile
[2], log
);
1534 logfac
= fac_findname(optarg
);
1537 "Unknown syslog facility '%s'\n",
1543 opts
|= OPT_RESOLVE
;
1547 fdt
[1] = IPL_LOGNAT
;
1548 iplfile
[1] = optarg
;
1550 case 'o' : case 'O' :
1551 logopts(c
== 'o', optarg
);
1552 fdt
[0] = fdt
[1] = fdt
[2] = -1;
1553 if (opts
& OPT_FILTER
)
1554 fdt
[0] = IPL_LOGIPF
;
1556 fdt
[1] = IPL_LOGNAT
;
1557 if (opts
& OPT_STATE
)
1558 fdt
[2] = IPL_LOGSTATE
;
1561 opts
|= OPT_PORTNUM
;
1572 fdt
[2] = IPL_LOGSTATE
;
1573 iplfile
[2] = optarg
;
1579 opts
|= OPT_VERBOSE
;
1582 opts
|= OPT_HEXBODY
;
1593 if (opts
& OPT_SYSLOG
)
1594 openlog(prog
, LOG_NDELAY
|LOG_PID
, logfac
);
1598 if (load_config(conf_file
) == -1)
1602 * Default action is to only open the filter log file.
1604 if ((fdt
[0] == -1) && (fdt
[1] == -1) && (fdt
[2] == -1))
1605 fdt
[0] = IPL_LOGIPF
;
1607 for (i
= 0; i
< 3; i
++) {
1610 if (!strcmp(iplfile
[i
], "-"))
1613 if ((fd
[i
] = open(iplfile
[i
], O_RDONLY
)) == -1) {
1614 (void) fprintf(stderr
,
1615 "%s: open: %s\n", iplfile
[i
],
1620 if (fstat(fd
[i
], &sb
) == -1) {
1621 (void) fprintf(stderr
, "%d: fstat: %s\n",
1622 fd
[i
], STRERROR(errno
));
1626 if (!(regular
[i
] = !S_ISCHR(sb
.st_mode
)))
1631 if (!(opts
& OPT_SYSLOG
)) {
1632 logfile
= argv
[optind
];
1633 log
= logfile
? fopen(logfile
, "a") : stdout
;
1635 (void) fprintf(stderr
, "%s: fopen: %s\n",
1636 argv
[optind
], STRERROR(errno
));
1640 setvbuf(log
, NULL
, _IONBF
, 0);
1644 if (make_daemon
&& ((log
!= stdout
) || (opts
& OPT_SYSLOG
))) {
1646 daemon(0, !(opts
& OPT_SYSLOG
));
1649 if ((pid
= fork()) > 0)
1652 (void) fprintf(stderr
, "%s: fork() failed: %s\n",
1653 argv
[0], STRERROR(errno
));
1658 if ((opts
& OPT_SYSLOG
))
1666 signal(SIGHUP
, handlehup
);
1668 for (doread
= 1; doread
; ) {
1671 for (i
= 0; i
< 3; i
++) {
1676 if (ioctl(fd
[i
], FIONREAD
, &tr
) == -1) {
1677 if (opts
& OPT_SYSLOG
)
1679 "ioctl(FIONREAD): %m");
1681 perror("ioctl(FIONREAD)");
1686 tr
= (lseek(fd
[i
], 0, SEEK_CUR
) < sb
.st_size
);
1687 if (!tr
&& !(opts
& OPT_TAIL
))
1695 tr
= read_log(fd
[i
], &n
, buf
, sizeof(buf
));
1697 if (logfile
&& (fp
= fopen(logfile
, "a"))) {
1701 if (binarylogfile
&&
1702 (fp
= fopen(binarylogfile
, "a"))) {
1707 if (conf_file
!= NULL
)
1708 load_config(conf_file
);
1715 if (opts
& OPT_SYSLOG
)
1716 syslog(LOG_CRIT
, "read: %m\n");
1722 if (opts
& OPT_SYSLOG
)
1723 syslog(LOG_CRIT
, "aborting logging\n");
1724 else if (log
!= NULL
)
1725 fprintf(log
, "aborting logging\n");
1732 print_log(fdt
[i
], log
, buf
, n
);
1733 if (!(opts
& OPT_SYSLOG
))
1739 if (!nr
&& ((opts
& OPT_TAIL
) || devices
))