2 * Copyright (C) 2001-2008 by Darren Reed.
4 * See the IPFILTER.LICENCE file for details on licencing.
6 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
7 * Use is subject to license terms.
9 * Copyright (c) 2014, Joyent, Inc. All rights reserved.
14 #define SOLARIS (defined(__SVR4) || defined(__svr4__)) && defined(sun)
17 #include <sys/types.h>
19 #include <sys/param.h>
25 #include <sys/socket.h>
26 #include <sys/ioctl.h>
34 #if !defined(__SVR4) && !defined(__svr4__)
35 # if (__FreeBSD_version >= 300000)
36 # include <sys/dirent.h>
41 # include <sys/filio.h>
42 # include <sys/byteorder.h>
44 #if !defined(__hpux) && (!defined(__SVR4) && !defined(__GNUC__))
50 #include <netinet/in.h>
51 #include <netinet/in_systm.h>
53 #include <netinet/ip.h>
54 #if !defined(__hpux) && !defined(linux)
55 # include <netinet/tcp_fsm.h>
58 #include <arpa/inet.h>
59 #include <arpa/nameser.h>
66 # include <sys/protosw.h>
67 # include <netinet/ip_var.h>
70 #include <netinet/tcp.h>
71 #include <netinet/ip_icmp.h>
76 #include "netinet/ip_compat.h"
77 #include <netinet/tcpip.h>
78 #include "netinet/ip_fil.h"
79 #include "netinet/ip_nat.h"
80 #include "netinet/ip_state.h"
81 #include "netinet/ip_proxy.h"
86 static const char sccsid
[] = "@(#)ipmon.c 1.21 6/5/96 (C)1993-2000 Darren Reed";
87 static const char rcsid
[] = "@(#)$Id: ipmon.c,v 1.33.2.10 2005/06/18 02:41:35 darrenr Exp $";
91 #if defined(sun) && !defined(SOLARIS2)
92 #define STRERROR(x) sys_errlist[x]
93 extern char *sys_errlist
[];
95 #define STRERROR(x) strerror(x)
105 typedef struct icmp_subtype
{
110 typedef struct icmp_type
{
112 struct icmp_subtype
*it_subtable
;
118 #define IST_SZ(x) (sizeof(x)/sizeof(icmp_subtype_t))
121 struct flags tcpfl
[] = {
133 #if defined(__hpux) || (defined(SOLARIS) && (SOLARIS2 < 10))
134 static char *pidfile
= "/etc/ipf/ipmon.pid";
136 # if (BSD >= 199306) || defined(SOLARIS)
137 static char *pidfile
= "/var/run/ipmon.pid";
139 static char *pidfile
= "/etc/ipmon.pid";
143 static char line
[2048];
145 static char *logfile
= NULL
;
146 static FILE *binarylog
= NULL
;
147 static char *binarylogfile
= NULL
;
148 static int donehup
= 0;
149 static void usage
__P((char *));
150 static void handlehup
__P((int));
151 static void flushlogs
__P((char *, FILE *));
152 static void print_log
__P((int, FILE *, char *, int));
153 static void print_ipflog
__P((FILE *, char *, int));
154 static void print_natlog
__P((FILE *, char *, int));
155 static void print_statelog
__P((FILE *, char *, int));
156 static int read_log
__P((int, int *, char *, int));
157 static void write_pid
__P((char *));
158 static char *icmpname
__P((u_int
, u_int
));
159 static char *icmpname6
__P((u_int
, u_int
));
160 static icmp_type_t
*find_icmptype
__P((int, icmp_type_t
*, size_t));
161 static icmp_subtype_t
*find_icmpsubtype
__P((int, icmp_subtype_t
*, size_t));
163 static struct tm
*get_tm
__P((u_32_t
));
165 static struct tm
*get_tm
__P((time_t));
168 char *hostname
__P((int, int, u_32_t
*));
169 char *portname
__P((int, char *, u_int
));
170 int main
__P((int, char *[]));
172 static void logopts
__P((int, char *));
173 static void init_tabs
__P((void));
174 static char *getproto
__P((u_int
));
176 static char **protocols
= NULL
;
177 static char **udp_ports
= NULL
;
178 static char **tcp_ports
= NULL
;
179 static char *conf_file
= NULL
;
182 #define OPT_SYSLOG 0x001
183 #define OPT_RESOLVE 0x002
184 #define OPT_HEXBODY 0x004
185 #define OPT_VERBOSE 0x008
186 #define OPT_HEXHDR 0x010
187 #define OPT_TAIL 0x020
188 #define OPT_NAT 0x080
189 #define OPT_STATE 0x100
190 #define OPT_FILTER 0x200
191 #define OPT_PORTNUM 0x400
192 #define OPT_LOGALL (OPT_NAT|OPT_STATE|OPT_FILTER)
193 #define OPT_LOGBODY 0x800
195 #define HOSTNAME_V4(a,b) hostname((a), 4, (u_32_t *)&(b))
198 #define LOGFAC LOG_LOCAL0
202 static icmp_subtype_t icmpunreachnames
[] = {
203 { ICMP_UNREACH_NET
, "net" },
204 { ICMP_UNREACH_HOST
, "host" },
205 { ICMP_UNREACH_PROTOCOL
, "protocol" },
206 { ICMP_UNREACH_PORT
, "port" },
207 { ICMP_UNREACH_NEEDFRAG
, "needfrag" },
208 { ICMP_UNREACH_SRCFAIL
, "srcfail" },
209 { ICMP_UNREACH_NET_UNKNOWN
, "net_unknown" },
210 { ICMP_UNREACH_HOST_UNKNOWN
, "host_unknown" },
211 { ICMP_UNREACH_NET
, "isolated" },
212 { ICMP_UNREACH_NET_PROHIB
, "net_prohib" },
213 { ICMP_UNREACH_NET_PROHIB
, "host_prohib" },
214 { ICMP_UNREACH_TOSNET
, "tosnet" },
215 { ICMP_UNREACH_TOSHOST
, "toshost" },
216 { ICMP_UNREACH_ADMIN_PROHIBIT
, "admin_prohibit" },
220 static icmp_subtype_t redirectnames
[] = {
221 { ICMP_REDIRECT_NET
, "net" },
222 { ICMP_REDIRECT_HOST
, "host" },
223 { ICMP_REDIRECT_TOSNET
, "tosnet" },
224 { ICMP_REDIRECT_TOSHOST
, "toshost" },
228 static icmp_subtype_t timxceednames
[] = {
229 { ICMP_TIMXCEED_INTRANS
, "transit" },
230 { ICMP_TIMXCEED_REASS
, "reassem" },
234 static icmp_subtype_t paramnames
[] = {
235 { ICMP_PARAMPROB_ERRATPTR
, "errata_pointer" },
236 { ICMP_PARAMPROB_OPTABSENT
, "optmissing" },
237 { ICMP_PARAMPROB_LENGTH
, "length" },
241 static icmp_type_t icmptypes
[] = {
242 { ICMP_ECHOREPLY
, NULL
, 0, "echoreply" },
243 { -1, NULL
, 0, NULL
},
244 { -1, NULL
, 0, NULL
},
245 { ICMP_UNREACH
, icmpunreachnames
,
246 IST_SZ(icmpunreachnames
),"unreach" },
247 { ICMP_SOURCEQUENCH
, NULL
, 0, "sourcequench" },
248 { ICMP_REDIRECT
, redirectnames
,
249 IST_SZ(redirectnames
), "redirect" },
250 { -1, NULL
, 0, NULL
},
251 { -1, NULL
, 0, NULL
},
252 { ICMP_ECHO
, NULL
, 0, "echo" },
253 { ICMP_ROUTERADVERT
, NULL
, 0, "routeradvert" },
254 { ICMP_ROUTERSOLICIT
, NULL
, 0, "routersolicit" },
255 { ICMP_TIMXCEED
, timxceednames
,
256 IST_SZ(timxceednames
), "timxceed" },
257 { ICMP_PARAMPROB
, paramnames
,
258 IST_SZ(paramnames
), "paramprob" },
259 { ICMP_TSTAMP
, NULL
, 0, "timestamp" },
260 { ICMP_TSTAMPREPLY
, NULL
, 0, "timestampreply" },
261 { ICMP_IREQ
, NULL
, 0, "inforeq" },
262 { ICMP_IREQREPLY
, NULL
, 0, "inforeply" },
263 { ICMP_MASKREQ
, NULL
, 0, "maskreq" },
264 { ICMP_MASKREPLY
, NULL
, 0, "maskreply" },
265 { -2, NULL
, 0, NULL
}
268 static icmp_subtype_t icmpredirect6
[] = {
269 { ICMP6_DST_UNREACH_NOROUTE
, "noroute" },
270 { ICMP6_DST_UNREACH_ADMIN
, "admin" },
271 { ICMP6_DST_UNREACH_NOTNEIGHBOR
, "neighbour" },
272 { ICMP6_DST_UNREACH_ADDR
, "address" },
273 { ICMP6_DST_UNREACH_NOPORT
, "noport" },
277 static icmp_subtype_t icmptimexceed6
[] = {
278 { ICMP6_TIME_EXCEED_TRANSIT
, "intransit" },
279 { ICMP6_TIME_EXCEED_REASSEMBLY
, "reassem" },
283 static icmp_subtype_t icmpparamprob6
[] = {
284 { ICMP6_PARAMPROB_HEADER
, "header" },
285 { ICMP6_PARAMPROB_NEXTHEADER
, "nextheader" },
286 { ICMP6_PARAMPROB_OPTION
, "option" },
290 static icmp_subtype_t icmpquerysubject6
[] = {
291 { ICMP6_NI_SUBJ_IPV6
, "ipv6" },
292 { ICMP6_NI_SUBJ_FQDN
, "fqdn" },
293 { ICMP6_NI_SUBJ_IPV4
, "ipv4" },
297 static icmp_subtype_t icmpnodeinfo6
[] = {
298 { ICMP6_NI_SUCCESS
, "success" },
299 { ICMP6_NI_REFUSED
, "refused" },
300 { ICMP6_NI_UNKNOWN
, "unknown" },
304 static icmp_subtype_t icmprenumber6
[] = {
305 { ICMP6_ROUTER_RENUMBERING_COMMAND
, "command" },
306 { ICMP6_ROUTER_RENUMBERING_RESULT
, "result" },
307 { ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET
, "seqnum_reset" },
311 static icmp_type_t icmptypes6
[] = {
312 { 0, NULL
, 0, NULL
},
313 { ICMP6_DST_UNREACH
, icmpredirect6
,
314 IST_SZ(icmpredirect6
), "unreach" },
315 { ICMP6_PACKET_TOO_BIG
, NULL
, 0, "toobig" },
316 { ICMP6_TIME_EXCEEDED
, icmptimexceed6
,
317 IST_SZ(icmptimexceed6
), "timxceed" },
318 { ICMP6_PARAM_PROB
, icmpparamprob6
,
319 IST_SZ(icmpparamprob6
), "paramprob" },
320 { ICMP6_ECHO_REQUEST
, NULL
, 0, "echo" },
321 { ICMP6_ECHO_REPLY
, NULL
, 0, "echoreply" },
322 { ICMP6_MEMBERSHIP_QUERY
, icmpquerysubject6
,
323 IST_SZ(icmpquerysubject6
), "groupmemberquery" },
324 { ICMP6_MEMBERSHIP_REPORT
,NULL
, 0, "groupmemberreport" },
325 { ICMP6_MEMBERSHIP_REDUCTION
,NULL
, 0, "groupmemberterm" },
326 { ND_ROUTER_SOLICIT
, NULL
, 0, "routersolicit" },
327 { ND_ROUTER_ADVERT
, NULL
, 0, "routeradvert" },
328 { ND_NEIGHBOR_SOLICIT
, NULL
, 0, "neighborsolicit" },
329 { ND_NEIGHBOR_ADVERT
, NULL
, 0, "neighboradvert" },
330 { ND_REDIRECT
, NULL
, 0, "redirect" },
331 { ICMP6_ROUTER_RENUMBERING
, icmprenumber6
,
332 IST_SZ(icmprenumber6
), "routerrenumber" },
333 { ICMP6_WRUREQUEST
, NULL
, 0, "whoareyourequest" },
334 { ICMP6_WRUREPLY
, NULL
, 0, "whoareyoureply" },
335 { ICMP6_FQDN_QUERY
, NULL
, 0, "fqdnquery" },
336 { ICMP6_FQDN_REPLY
, NULL
, 0, "fqdnreply" },
337 { ICMP6_NI_QUERY
, icmpnodeinfo6
,
338 IST_SZ(icmpnodeinfo6
), "nodeinforequest" },
339 { ICMP6_NI_REPLY
, NULL
, 0, "nodeinforeply" },
340 { MLD6_MTRACE_RESP
, NULL
, 0, "mtraceresponse" },
341 { MLD6_MTRACE
, NULL
, 0, "mtracerequest" },
342 { -2, NULL
, 0, NULL
}
345 static icmp_subtype_t
*find_icmpsubtype(type
, table
, tablesz
)
347 icmp_subtype_t
*table
;
356 if ((type
< 0) || (type
> table
[tablesz
- 2].ist_val
))
360 if (table
[type
].ist_val
== type
)
363 for (i
= 0, ist
= table
; ist
->ist_val
!= -2; i
++, ist
++)
364 if (ist
->ist_val
== type
)
370 static icmp_type_t
*find_icmptype(type
, table
, tablesz
)
381 if ((type
< 0) || (type
> table
[tablesz
- 2].it_val
))
385 if (table
[type
].it_val
== type
)
388 for (i
= 0, it
= table
; it
->it_val
!= -2; i
++, it
++)
389 if (it
->it_val
== type
)
395 static void handlehup(sig
)
398 signal(SIGHUP
, handlehup
);
403 static void init_tabs()
410 if (protocols
!= NULL
) {
411 for (i
= 0; i
< 256; i
++)
412 if (protocols
[i
] != NULL
) {
419 protocols
= (char **)malloc(256 * sizeof(*protocols
));
420 if (protocols
!= NULL
) {
421 bzero((char *)protocols
, 256 * sizeof(*protocols
));
424 while ((p
= getprotoent()) != NULL
)
425 if (p
->p_proto
>= 0 && p
->p_proto
<= 255 &&
426 p
->p_name
!= NULL
&& protocols
[p
->p_proto
] == NULL
)
427 protocols
[p
->p_proto
] = strdup(p
->p_name
);
433 free(protocols
[252]);
435 protocols
[252] = NULL
;
439 if (udp_ports
!= NULL
) {
440 for (i
= 0; i
< 65536; i
++)
441 if (udp_ports
[i
] != NULL
) {
448 udp_ports
= (char **)malloc(65536 * sizeof(*udp_ports
));
449 if (udp_ports
!= NULL
)
450 bzero((char *)udp_ports
, 65536 * sizeof(*udp_ports
));
452 if (tcp_ports
!= NULL
) {
453 for (i
= 0; i
< 65536; i
++)
454 if (tcp_ports
[i
] != NULL
) {
461 tcp_ports
= (char **)malloc(65536 * sizeof(*tcp_ports
));
462 if (tcp_ports
!= NULL
)
463 bzero((char *)tcp_ports
, 65536 * sizeof(*tcp_ports
));
466 while ((s
= getservent()) != NULL
) {
467 if (s
->s_proto
== NULL
)
469 else if (!strcmp(s
->s_proto
, "tcp")) {
470 port
= ntohs(s
->s_port
);
473 } else if (!strcmp(s
->s_proto
, "udp")) {
474 port
= ntohs(s
->s_port
);
479 if ((port
< 0 || port
> 65535) || (name
== NULL
))
482 tab
[port
] = strdup(name
);
488 static char *getproto(p
)
495 s
= protocols
? protocols
[p
] : NULL
;
497 sprintf(pnum
, "%u", p
);
504 static int read_log(fd
, lenp
, buf
, bufsize
)
505 int fd
, bufsize
, *lenp
;
510 nr
= read(fd
, buf
, bufsize
);
513 if ((nr
< 0) && (errno
!= EINTR
))
520 char *hostname(res
, v
, ip
)
524 # define MAX_INETA 16
525 static char hname
[MAXHOSTNAMELEN
+ MAX_INETA
+ 3];
527 static char hostbuf
[MAXHOSTNAMELEN
+1];
535 return inet_ntoa(ipa
);
536 hp
= gethostbyaddr((char *)ip
, sizeof(*ip
), AF_INET
);
538 return inet_ntoa(ipa
);
539 sprintf(hname
, "%.*s[%s]", MAXHOSTNAMELEN
, hp
->h_name
,
544 (void) inet_ntop(AF_INET6
, ip
, hostbuf
, sizeof(hostbuf
) - 1);
545 hostbuf
[MAXHOSTNAMELEN
] = '\0';
553 char *portname(res
, proto
, port
)
558 static char pname
[8];
563 (void) sprintf(pname
, "%u", port
);
564 if (!res
|| (opts
& OPT_PORTNUM
))
567 if (!strcmp(proto
, "tcp"))
569 else if (!strcmp(proto
, "udp"))
577 static char *icmpname(type
, code
)
581 static char name
[80];
587 it
= find_icmptype(type
, icmptypes
, sizeof(icmptypes
) / sizeof(*it
));
592 sprintf(name
, "icmptype(%d)/", type
);
594 sprintf(name
, "%s/", s
);
597 if (it
!= NULL
&& it
->it_subtable
!= NULL
)
598 ist
= find_icmpsubtype(code
, it
->it_subtable
, it
->it_stsize
);
600 if (ist
!= NULL
&& ist
->ist_name
!= NULL
)
601 strcat(name
, ist
->ist_name
);
603 sprintf(name
+ strlen(name
), "%d", code
);
608 static char *icmpname6(type
, code
)
612 static char name
[80];
618 it
= find_icmptype(type
, icmptypes6
, sizeof(icmptypes6
) / sizeof(*it
));
623 sprintf(name
, "icmpv6type(%d)/", type
);
625 sprintf(name
, "%s/", s
);
628 if (it
!= NULL
&& it
->it_subtable
!= NULL
)
629 ist
= find_icmpsubtype(code
, it
->it_subtable
, it
->it_stsize
);
631 if (ist
!= NULL
&& ist
->ist_name
!= NULL
)
632 strcat(name
, ist
->ist_name
);
634 sprintf(name
+ strlen(name
), "%d", code
);
640 void dumphex(log
, dopts
, buf
, len
)
648 u_char
*s
= (u_char
*)buf
, *t
= (u_char
*)hline
;
650 if (buf
== NULL
|| len
== 0)
655 for (i
= len
, j
= 0; i
; i
--, j
++, s
++) {
656 if (j
&& !(j
& 0xf)) {
659 if (!(dopts
& OPT_SYSLOG
))
662 syslog(LOG_INFO
, "%s", hline
);
666 sprintf((char *)t
, "%02x", *s
& 0xff);
668 if (!((j
+ 1) & 0xf)) {
670 sprintf((char *)t
, " ");
672 for (k
= 16; k
; k
--, s
++)
673 *t
++ = (ISPRINT(*s
) ? *s
: '.');
682 for (k
= 16 - (j
& 0xf); k
; k
--) {
687 sprintf((char *)t
, " ");
690 for (k
= j
& 0xf; k
; k
--, s
++)
691 *t
++ = (ISPRINT(*s
) ? *s
: '.');
695 if (!(dopts
& OPT_SYSLOG
)) {
699 syslog(LOG_INFO
, "%s", hline
);
703 static struct tm
*get_tm(sec
)
718 static void print_natlog(log
, buf
, blen
)
724 iplog_t
*ipl
= (iplog_t
*)buf
;
730 nl
= (struct natlog
*)((char *)ipl
+ sizeof(*ipl
));
731 res
= (opts
& OPT_RESOLVE
) ? 1 : 0;
732 tm
= get_tm(ipl
->ipl_sec
);
734 if (!(opts
& OPT_SYSLOG
)) {
735 (void) strftime(t
, len
, "%d/%m/%Y ", tm
);
740 (void) strftime(t
, len
, "%T", tm
);
742 (void) sprintf(t
, ".%-.6ld @%hd ", ipl
->ipl_usec
, nl
->nlg_rule
+ 1);
745 if (nl
->nlg_type
== NL_NEWMAP
)
746 strcpy(t
, "NAT:MAP ");
747 else if (nl
->nlg_type
== NL_NEWRDR
)
748 strcpy(t
, "NAT:RDR ");
749 else if (nl
->nlg_type
== NL_FLUSH
)
750 strcpy(t
, "NAT:FLUSH ");
751 else if (nl
->nlg_type
== NL_EXPIRE
)
752 strcpy(t
, "NAT:EXPIRE ");
753 else if (nl
->nlg_type
== NL_NEWBIMAP
)
754 strcpy(t
, "NAT:BIMAP ");
755 else if (nl
->nlg_type
== NL_NEWBLOCK
)
756 strcpy(t
, "NAT:MAPBLOCK ");
757 else if (nl
->nlg_type
== NL_CLONE
)
758 strcpy(t
, "NAT:CLONE ");
760 sprintf(t
, "Type: %d ", nl
->nlg_type
);
763 proto
= getproto(nl
->nlg_p
);
765 (void) sprintf(t
, "%s,%s <- -> ", hostname(res
, nl
->nlg_v
,
766 (u_32_t
*)&nl
->nlg_inip
),
767 portname(res
, proto
, (u_int
)nl
->nlg_inport
));
769 (void) sprintf(t
, "%s,%s ", hostname(res
, nl
->nlg_v
,
770 (u_32_t
*)&nl
->nlg_outip
),
771 portname(res
, proto
, (u_int
)nl
->nlg_outport
));
773 (void) sprintf(t
, "[%s,%s]", hostname(res
, nl
->nlg_v
,
774 (u_32_t
*)&nl
->nlg_origip
),
775 portname(res
, proto
, (u_int
)nl
->nlg_origport
));
777 if (nl
->nlg_type
== NL_EXPIRE
) {
779 (void) sprintf(t
, " Pkts %qd/%qd Bytes %qd/%qd",
780 (long long)nl
->nlg_pkts
[0],
781 (long long)nl
->nlg_pkts
[1],
782 (long long)nl
->nlg_bytes
[0],
783 (long long)nl
->nlg_bytes
[1]);
785 (void) sprintf(t
, " Pkts %ld/%ld Bytes %ld/%ld",
786 nl
->nlg_pkts
[0], nl
->nlg_pkts
[1],
787 nl
->nlg_bytes
[0], nl
->nlg_bytes
[1]);
794 if (opts
& OPT_SYSLOG
)
795 syslog(LOG_INFO
, "%s", line
);
797 (void) fprintf(log
, "%s", line
);
801 static void print_statelog(log
, buf
, blen
)
807 iplog_t
*ipl
= (iplog_t
*)buf
;
808 char *t
= line
, *proto
;
812 sl
= (struct ipslog
*)((char *)ipl
+ sizeof(*ipl
));
813 res
= (opts
& OPT_RESOLVE
) ? 1 : 0;
814 tm
= get_tm(ipl
->ipl_sec
);
816 if (!(opts
& OPT_SYSLOG
)) {
817 (void) strftime(t
, len
, "%d/%m/%Y ", tm
);
822 (void) strftime(t
, len
, "%T", tm
);
824 (void) sprintf(t
, ".%-.6ld ", ipl
->ipl_usec
);
827 if (sl
->isl_type
== ISL_NEW
)
828 strcpy(t
, "STATE:NEW ");
829 else if (sl
->isl_type
== ISL_CLONE
)
830 strcpy(t
, "STATE:CLONED ");
831 else if (sl
->isl_type
== ISL_EXPIRE
) {
832 if ((sl
->isl_p
== IPPROTO_TCP
) &&
833 (sl
->isl_state
[0] > IPF_TCPS_ESTABLISHED
||
834 sl
->isl_state
[1] > IPF_TCPS_ESTABLISHED
))
835 strcpy(t
, "STATE:CLOSE ");
837 strcpy(t
, "STATE:EXPIRE ");
838 } else if (sl
->isl_type
== ISL_FLUSH
)
839 strcpy(t
, "STATE:FLUSH ");
840 else if (sl
->isl_type
== ISL_INTERMEDIATE
)
841 strcpy(t
, "STATE:INTERMEDIATE ");
842 else if (sl
->isl_type
== ISL_REMOVE
)
843 strcpy(t
, "STATE:REMOVE ");
844 else if (sl
->isl_type
== ISL_KILLED
)
845 strcpy(t
, "STATE:KILLED ");
847 sprintf(t
, "Type: %d ", sl
->isl_type
);
850 proto
= getproto(sl
->isl_p
);
852 if (sl
->isl_p
== IPPROTO_TCP
|| sl
->isl_p
== IPPROTO_UDP
) {
853 (void) sprintf(t
, "%s,%s -> ",
854 hostname(res
, sl
->isl_v
, (u_32_t
*)&sl
->isl_src
),
855 portname(res
, proto
, (u_int
)sl
->isl_sport
));
857 (void) sprintf(t
, "%s,%s PR %s",
858 hostname(res
, sl
->isl_v
, (u_32_t
*)&sl
->isl_dst
),
859 portname(res
, proto
, (u_int
)sl
->isl_dport
), proto
);
860 } else if (sl
->isl_p
== IPPROTO_ICMP
) {
861 (void) sprintf(t
, "%s -> ", hostname(res
, sl
->isl_v
,
862 (u_32_t
*)&sl
->isl_src
));
864 (void) sprintf(t
, "%s PR icmp %d",
865 hostname(res
, sl
->isl_v
, (u_32_t
*)&sl
->isl_dst
),
867 } else if (sl
->isl_p
== IPPROTO_ICMPV6
) {
868 (void) sprintf(t
, "%s -> ", hostname(res
, sl
->isl_v
,
869 (u_32_t
*)&sl
->isl_src
));
871 (void) sprintf(t
, "%s PR icmpv6 %d",
872 hostname(res
, sl
->isl_v
, (u_32_t
*)&sl
->isl_dst
),
875 (void) sprintf(t
, "%s -> ",
876 hostname(res
, sl
->isl_v
, (u_32_t
*)&sl
->isl_src
));
878 (void) sprintf(t
, "%s PR %s",
879 hostname(res
, sl
->isl_v
, (u_32_t
*)&sl
->isl_dst
),
883 if (sl
->isl_tag
!= FR_NOLOGTAG
) {
884 (void) sprintf(t
, " tag %u", sl
->isl_tag
);
887 if (sl
->isl_type
!= ISL_NEW
) {
891 " Forward: Pkts in %" PRId64
" Bytes in %" PRId64
892 " Pkts out %" PRId64
" Bytes out %" PRId64
893 " Backward: Pkts in %" PRId64
" Bytes in %" PRId64
894 " Pkts out %" PRId64
" Bytes out %" PRId64
,
896 " 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",
899 " 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",
901 sl
->isl_pkts
[0], sl
->isl_bytes
[0],
902 sl
->isl_pkts
[1], sl
->isl_bytes
[1],
903 sl
->isl_pkts
[2], sl
->isl_bytes
[2],
904 sl
->isl_pkts
[3], sl
->isl_bytes
[3]);
911 if (opts
& OPT_SYSLOG
)
912 syslog(LOG_INFO
, "%s", line
);
914 (void) fprintf(log
, "%s", line
);
918 static void print_log(logtype
, log
, buf
, blen
)
924 char *bp
= NULL
, *bpo
= NULL
;
928 ipl
= (iplog_t
*)buf
;
929 if ((u_long
)ipl
& (sizeof(long)-1)) {
932 bp
= (char *)malloc(blen
);
937 bcopy((char *)ipl
, bp
, blen
);
946 psize
= ipl
->ipl_dsize
;
951 fwrite(buf
, psize
, 1, binarylog
);
955 if (logtype
== IPL_LOGIPF
) {
956 if (ipl
->ipl_magic
== IPL_MAGIC
)
957 print_ipflog(log
, buf
, psize
);
959 } else if (logtype
== IPL_LOGNAT
) {
960 if (ipl
->ipl_magic
== IPL_MAGIC_NAT
)
961 print_natlog(log
, buf
, psize
);
963 } else if (logtype
== IPL_LOGSTATE
) {
964 if (ipl
->ipl_magic
== IPL_MAGIC_STATE
)
965 print_statelog(log
, buf
, psize
);
977 static void print_ipflog(log
, buf
, blen
)
987 int i
, v
, lvl
, res
, len
, off
, plen
, ipoff
, defaction
;
997 ipl
= (iplog_t
*)buf
;
998 ipf
= (ipflog_t
*)((char *)buf
+ sizeof(*ipl
));
999 ip
= (ip_t
*)((char *)ipf
+ sizeof(*ipf
));
1001 res
= (opts
& OPT_RESOLVE
) ? 1 : 0;
1004 tm
= get_tm(ipl
->ipl_sec
);
1007 if (!(opts
& OPT_SYSLOG
)) {
1008 (void) strftime(t
, len
, "%d/%m/%Y ", tm
);
1013 (void) strftime(t
, len
, "%T", tm
);
1015 (void) sprintf(t
, ".%-.6ld ", ipl
->ipl_usec
);
1017 if (ipl
->ipl_count
> 1) {
1018 (void) sprintf(t
, "%dx ", ipl
->ipl_count
);
1021 #if (defined(MENTAT) || \
1022 (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \
1023 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) || \
1024 (defined(OpenBSD) && (OpenBSD >= 199603))) || defined(linux)
1026 char ifname
[sizeof(ipf
->fl_ifname
) + 1];
1028 strncpy(ifname
, ipf
->fl_ifname
, sizeof(ipf
->fl_ifname
));
1029 ifname
[sizeof(ipf
->fl_ifname
)] = '\0';
1030 (void) sprintf(t
, "%s", ifname
);
1032 # if defined(MENTAT) || defined(linux)
1033 if (ISALPHA(*(t
- 1))) {
1034 sprintf(t
, "%d", ipf
->fl_unit
);
1040 for (len
= 0; len
< 3; len
++)
1041 if (ipf
->fl_ifname
[len
] == '\0')
1043 if (ipf
->fl_ifname
[len
])
1045 (void) sprintf(t
, "%*.*s%u", len
, len
, ipf
->fl_ifname
, ipf
->fl_unit
);
1048 #if defined(__sgi) || defined(_AIX51) || defined(__powerpc__) || \
1050 if ((ipf
->fl_group
[0] == 255) && (ipf
->fl_group
[1] == '\0'))
1052 if ((ipf
->fl_group
[0] == -1) && (ipf
->fl_group
[1] == '\0'))
1055 else if (ipf
->fl_group
[0] == '\0')
1056 (void) strcpy(t
, " @0:");
1058 (void) sprintf(t
, " @%s:", ipf
->fl_group
);
1060 if (ipf
->fl_rule
== 0xffffffff)
1063 (void) sprintf(t
, "%u ", ipf
->fl_rule
+ 1);
1068 if (ipf
->fl_lflags
& FI_SHORT
) {
1073 if (FR_ISPASS(ipf
->fl_flags
)) {
1074 if (ipf
->fl_flags
& FR_LOGP
)
1078 } else if (FR_ISBLOCK(ipf
->fl_flags
)) {
1079 if (ipf
->fl_flags
& FR_LOGB
)
1084 } else if ((ipf
->fl_flags
& FR_LOGMASK
) == FR_LOG
) {
1087 } else if (ipf
->fl_flags
& FF_LOGNOMATCH
) {
1093 if (ipf
->fl_loglevel
!= 0xffff)
1094 lvl
= ipf
->fl_loglevel
;
1104 p
= (u_short
)ip6
->ip6_nxt
;
1105 s
= (u_32_t
*)&ip6
->ip6_src
;
1106 d
= (u_32_t
*)&ip6
->ip6_dst
;
1107 plen
= hl
+ ntohs(ip6
->ip6_plen
);
1112 } else if (v
== 4) {
1113 hl
= IP_HL(ip
) << 2;
1115 off
= ipoff
& IP_OFFMASK
;
1116 p
= (u_short
)ip
->ip_p
;
1117 s
= (u_32_t
*)&ip
->ip_src
;
1118 d
= (u_32_t
*)&ip
->ip_dst
;
1123 proto
= getproto(p
);
1125 if ((p
== IPPROTO_TCP
|| p
== IPPROTO_UDP
) && !off
) {
1126 tp
= (tcphdr_t
*)((char *)ip
+ hl
);
1127 if (!(ipf
->fl_lflags
& FI_SHORT
)) {
1128 (void) sprintf(t
, "%s,%s -> ", hostname(res
, v
, s
),
1129 portname(res
, proto
, (u_int
)tp
->th_sport
));
1131 (void) sprintf(t
, "%s,%s PR %s len %hu %hu",
1132 hostname(res
, v
, d
),
1133 portname(res
, proto
, (u_int
)tp
->th_dport
),
1137 if (p
== IPPROTO_TCP
) {
1140 for (i
= 0; tcpfl
[i
].value
; i
++)
1141 if (tp
->th_flags
& tcpfl
[i
].value
)
1142 *t
++ = tcpfl
[i
].flag
;
1143 if (opts
& OPT_VERBOSE
) {
1144 (void) sprintf(t
, " %lu %lu %hu",
1145 (u_long
)(ntohl(tp
->th_seq
)),
1146 (u_long
)(ntohl(tp
->th_ack
)),
1153 (void) sprintf(t
, "%s -> ", hostname(res
, v
, s
));
1155 (void) sprintf(t
, "%s PR %s len %hu %hu",
1156 hostname(res
, v
, d
), proto
, hl
, plen
);
1158 } else if ((p
== IPPROTO_ICMPV6
) && !off
&& (v
== 6)) {
1159 ic
= (struct icmp
*)((char *)ip
+ hl
);
1160 (void) sprintf(t
, "%s -> ", hostname(res
, v
, s
));
1162 (void) sprintf(t
, "%s PR icmpv6 len %hu %hu icmpv6 %s",
1163 hostname(res
, v
, d
), hl
, plen
,
1164 icmpname6(ic
->icmp_type
, ic
->icmp_code
));
1165 } else if ((p
== IPPROTO_ICMP
) && !off
&& (v
== 4)) {
1166 ic
= (struct icmp
*)((char *)ip
+ hl
);
1167 (void) sprintf(t
, "%s -> ", hostname(res
, v
, s
));
1169 (void) sprintf(t
, "%s PR icmp len %hu %hu icmp %s",
1170 hostname(res
, v
, d
), hl
, plen
,
1171 icmpname(ic
->icmp_type
, ic
->icmp_code
));
1172 if (ic
->icmp_type
== ICMP_UNREACH
||
1173 ic
->icmp_type
== ICMP_SOURCEQUENCH
||
1174 ic
->icmp_type
== ICMP_PARAMPROB
||
1175 ic
->icmp_type
== ICMP_REDIRECT
||
1176 ic
->icmp_type
== ICMP_TIMXCEED
) {
1178 i
= ntohs(ipc
->ip_len
);
1180 * XXX - try to guess endian of ip_len in ICMP
1185 ipoff
= ntohs(ipc
->ip_off
);
1186 proto
= getproto(ipc
->ip_p
);
1188 if (!(ipoff
& IP_OFFMASK
) &&
1189 ((ipc
->ip_p
== IPPROTO_TCP
) ||
1190 (ipc
->ip_p
== IPPROTO_UDP
))) {
1191 tp
= (tcphdr_t
*)((char *)ipc
+ hl
);
1193 (void) sprintf(t
, " for %s,%s -",
1194 HOSTNAME_V4(res
, ipc
->ip_src
),
1195 portname(res
, proto
,
1196 (u_int
)tp
->th_sport
));
1198 (void) sprintf(t
, " %s,%s PR %s len %hu %hu",
1199 HOSTNAME_V4(res
, ipc
->ip_dst
),
1200 portname(res
, proto
,
1201 (u_int
)tp
->th_dport
),
1202 proto
, IP_HL(ipc
) << 2, i
);
1203 } else if (!(ipoff
& IP_OFFMASK
) &&
1204 (ipc
->ip_p
== IPPROTO_ICMP
)) {
1205 icmp
= (icmphdr_t
*)((char *)ipc
+ hl
);
1208 (void) sprintf(t
, " for %s -",
1209 HOSTNAME_V4(res
, ipc
->ip_src
));
1212 " %s PR icmp len %hu %hu icmp %d/%d",
1213 HOSTNAME_V4(res
, ipc
->ip_dst
),
1215 icmp
->icmp_type
, icmp
->icmp_code
);
1218 (void) sprintf(t
, " for %s -",
1219 HOSTNAME_V4(res
, ipc
->ip_src
));
1221 (void) sprintf(t
, " %s PR %s len %hu (%hu)",
1222 HOSTNAME_V4(res
, ipc
->ip_dst
), proto
,
1223 IP_HL(ipc
) << 2, i
);
1225 if (ipoff
& IP_OFFMASK
) {
1227 "(frag %d:%hu@%hu%s%s)",
1229 i
- (IP_HL(ipc
) << 2),
1230 (ipoff
& IP_OFFMASK
) << 3,
1231 ipoff
& IP_MF
? "+" : "",
1232 ipoff
& IP_DF
? "-" : "");
1238 (void) sprintf(t
, "%s -> ", hostname(res
, v
, s
));
1240 (void) sprintf(t
, "%s PR %s len %hu (%hu)",
1241 hostname(res
, v
, d
), proto
, hl
, plen
);
1243 if (off
& IP_OFFMASK
)
1244 (void) sprintf(t
, " (frag %d:%hu@%hu%s%s)",
1246 plen
- hl
, (off
& IP_OFFMASK
) << 3,
1247 ipoff
& IP_MF
? "+" : "",
1248 ipoff
& IP_DF
? "-" : "");
1253 if (ipf
->fl_flags
& FR_KEEPSTATE
) {
1254 (void) strcpy(t
, " K-S");
1258 if (ipf
->fl_flags
& FR_KEEPFRAG
) {
1259 (void) strcpy(t
, " K-F");
1263 if (ipf
->fl_dir
== 0)
1265 else if (ipf
->fl_dir
== 1)
1268 if (ipf
->fl_logtag
!= 0) {
1269 sprintf(t
, " log-tag %d", ipf
->fl_logtag
);
1272 if (ipf
->fl_nattag
.ipt_num
[0] != 0) {
1273 strcpy(t
, " nat-tag ");
1275 strncpy(t
, ipf
->fl_nattag
.ipt_tag
, sizeof(ipf
->fl_nattag
));
1278 if ((ipf
->fl_lflags
& FI_LOWTTL
) != 0) {
1279 strcpy(t
, " low-ttl");
1282 if ((ipf
->fl_lflags
& FI_OOW
) != 0) {
1283 if (ipf
->fl_lflags
& FI_NEG_OOW
) {
1284 strcpy(t
, " NEG_OOW");
1285 t
+= sizeof (" NEG_OOW") - 1;
1288 t
+= sizeof (" OOW") - 1;
1291 if ((ipf
->fl_lflags
& FI_BAD
) != 0) {
1295 if ((ipf
->fl_lflags
& FI_NATED
) != 0) {
1299 if ((ipf
->fl_lflags
& FI_BADNAT
) != 0) {
1300 strcpy(t
, " bad-NAT");
1303 if ((ipf
->fl_lflags
& FI_BADSRC
) != 0) {
1304 strcpy(t
, " bad-src");
1307 if ((ipf
->fl_lflags
& FI_MULTICAST
) != 0) {
1308 strcpy(t
, " multicast");
1311 if ((ipf
->fl_lflags
& FI_BROADCAST
) != 0) {
1312 strcpy(t
, " broadcast");
1315 if ((ipf
->fl_lflags
& (FI_MULTICAST
|FI_BROADCAST
|FI_MBCAST
)) ==
1317 strcpy(t
, " mbcast");
1323 if (conf_file
!= NULL
)
1324 defaction
= check_action(buf
, line
, opts
, lvl
);
1325 if (defaction
== 0) {
1326 if (opts
& OPT_SYSLOG
)
1327 syslog(lvl
, "%s", line
);
1329 (void) fprintf(log
, "%s", line
);
1330 if (opts
& OPT_HEXHDR
)
1331 dumphex(log
, opts
, buf
,
1332 sizeof(iplog_t
) + sizeof(*ipf
));
1333 if (opts
& OPT_HEXBODY
)
1334 dumphex(log
, opts
, (char *)ip
,
1335 ipf
->fl_plen
+ ipf
->fl_hlen
);
1336 else if ((opts
& OPT_LOGBODY
) && (ipf
->fl_flags
& FR_LOGBODY
))
1337 dumphex(log
, opts
, (char *)ip
+ ipf
->fl_hlen
,
1343 static void usage(prog
)
1346 fprintf(stderr
, "%s: [-abDFhnpstvxX] %s %s %s %s %s %s %s\n",
1347 prog
, "[-G|-z zonename]", "[-N device]",
1348 "[ [-o [NSI]] [-O [NSI]]", "[-P pidfile]", "[-S device]",
1349 "[-f device]", "filename");
1354 static void write_pid(file
)
1360 if ((fd
= open(file
, O_CREAT
|O_TRUNC
|O_WRONLY
, 0644)) >= 0) {
1361 fp
= fdopen(fd
, "w");
1365 "unable to open/create pid file: %s\n", file
);
1368 fprintf(fp
, "%d", getpid());
1374 static void flushlogs(file
, log
)
1378 int fd
, flushed
= 0;
1380 if ((fd
= open(file
, O_RDWR
)) == -1) {
1381 (void) fprintf(stderr
, "%s: open: %s\n",
1382 file
, STRERROR(errno
));
1386 if (setzone(fd
) != 0) {
1391 if (ioctl(fd
, SIOCIPFFB
, &flushed
) == 0) {
1392 printf("%d bytes flushed from log buffer\n",
1396 perror("SIOCIPFFB");
1400 if (opts
& OPT_SYSLOG
)
1401 syslog(LOG_INFO
, "%d bytes flushed from log\n",
1403 else if (log
!= stdout
)
1404 fprintf(log
, "%d bytes flushed from log\n", flushed
);
1409 static void logopts(turnon
, options
)
1416 for (s
= options
; *s
; s
++)
1427 flags
|= OPT_FILTER
;
1430 fprintf(stderr
, "Unknown log option %c\n", *s
);
1442 int main(argc
, argv
)
1449 int fd
[3], doread
, n
, i
;
1450 int tr
, nr
, regular
[3], c
;
1451 int fdt
[3], devices
= 0, make_daemon
= 0;
1452 char buf
[DEFAULT_IPFLOGSIZE
], *iplfile
[3], *s
;
1454 extern char *optarg
;
1455 const char *optstr
= "?abB:C:Df:G:FhnN:o:O:pP:sS:tvxXz:";
1457 fd
[0] = fd
[1] = fd
[2] = -1;
1458 fdt
[0] = fdt
[1] = fdt
[2] = -1;
1459 iplfile
[0] = IPL_NAME
;
1460 iplfile
[1] = IPNAT_NAME
;
1461 iplfile
[2] = IPSTATE_NAME
;
1464 * We need to set the zone name before calling openlog in
1465 * the switch statement below
1467 getzoneopt(argc
, argv
, optstr
);
1469 while ((c
= getopt(argc
, argv
, optstr
)) != -1)
1474 fdt
[0] = IPL_LOGIPF
;
1475 fdt
[1] = IPL_LOGNAT
;
1476 fdt
[2] = IPL_LOGSTATE
;
1479 opts
|= OPT_LOGBODY
;
1482 binarylogfile
= optarg
;
1483 binarylog
= fopen(optarg
, "a");
1491 case 'f' : case 'I' :
1493 fdt
[0] = IPL_LOGIPF
;
1494 iplfile
[0] = optarg
;
1497 flushlogs(iplfile
[0], log
);
1498 flushlogs(iplfile
[1], log
);
1499 flushlogs(iplfile
[2], log
);
1502 /* Already handled by getzoneopt() above */
1505 opts
|= OPT_RESOLVE
;
1509 fdt
[1] = IPL_LOGNAT
;
1510 iplfile
[1] = optarg
;
1512 case 'o' : case 'O' :
1513 logopts(c
== 'o', optarg
);
1514 fdt
[0] = fdt
[1] = fdt
[2] = -1;
1515 if (opts
& OPT_FILTER
)
1516 fdt
[0] = IPL_LOGIPF
;
1518 fdt
[1] = IPL_LOGNAT
;
1519 if (opts
& OPT_STATE
)
1520 fdt
[2] = IPL_LOGSTATE
;
1523 opts
|= OPT_PORTNUM
;
1529 s
= strrchr(argv
[0], '/');
1534 openlog(s
, LOG_NDELAY
|LOG_PID
, LOGFAC
);
1541 fdt
[2] = IPL_LOGSTATE
;
1542 iplfile
[2] = optarg
;
1548 opts
|= OPT_VERBOSE
;
1551 opts
|= OPT_HEXBODY
;
1557 /* Already handled by getzoneopt() above */
1567 if (load_config(conf_file
) == -1)
1571 * Default action is to only open the filter log file.
1573 if ((fdt
[0] == -1) && (fdt
[1] == -1) && (fdt
[2] == -1))
1574 fdt
[0] = IPL_LOGIPF
;
1576 for (i
= 0; i
< 3; i
++) {
1579 if (!strcmp(iplfile
[i
], "-"))
1582 if ((fd
[i
] = open(iplfile
[i
], O_RDONLY
)) == -1) {
1583 (void) fprintf(stderr
,
1584 "%s: open: %s\n", iplfile
[i
],
1589 if (fstat(fd
[i
], &sb
) == -1) {
1590 (void) fprintf(stderr
, "%d: fstat: %s\n",
1591 fd
[i
], STRERROR(errno
));
1596 if (setzone(fd
[i
]) != 0) {
1601 if (!(regular
[i
] = !S_ISCHR(sb
.st_mode
)))
1606 if (!(opts
& OPT_SYSLOG
)) {
1607 logfile
= argv
[optind
];
1608 log
= logfile
? fopen(logfile
, "a") : stdout
;
1610 (void) fprintf(stderr
, "%s: fopen: %s\n",
1611 argv
[optind
], STRERROR(errno
));
1615 setvbuf(log
, NULL
, _IONBF
, 0);
1619 if (make_daemon
&& ((log
!= stdout
) || (opts
& OPT_SYSLOG
))) {
1621 daemon(0, !(opts
& OPT_SYSLOG
));
1624 if ((pid
= fork()) > 0)
1627 (void) fprintf(stderr
, "%s: fork() failed: %s\n",
1628 argv
[0], STRERROR(errno
));
1633 if ((opts
& OPT_SYSLOG
))
1641 signal(SIGHUP
, handlehup
);
1643 for (doread
= 1; doread
; ) {
1646 for (i
= 0; i
< 3; i
++) {
1651 if (ioctl(fd
[i
], FIONREAD
, &tr
) == -1) {
1652 if (opts
& OPT_SYSLOG
)
1654 "ioctl(FIONREAD): %m");
1656 perror("ioctl(FIONREAD)");
1661 tr
= (lseek(fd
[i
], 0, SEEK_CUR
) < sb
.st_size
);
1662 if (!tr
&& !(opts
& OPT_TAIL
))
1669 tr
= read_log(fd
[i
], &n
, buf
, sizeof(buf
));
1671 if (logfile
&& (fp
= fopen(logfile
, "a"))) {
1675 if (binarylogfile
&& (fp
= fopen(binarylogfile
, "a"))) {
1680 if (conf_file
!= NULL
)
1681 load_config(conf_file
);
1688 if (opts
& OPT_SYSLOG
)
1689 syslog(LOG_CRIT
, "read: %m\n");
1695 if (opts
& OPT_SYSLOG
)
1696 syslog(LOG_CRIT
, "aborting logging\n");
1698 fprintf(log
, "aborting logging\n");
1705 print_log(fdt
[i
], log
, buf
, n
);
1706 if (!(opts
& OPT_SYSLOG
))
1712 if (!nr
&& ((opts
& OPT_TAIL
) || devices
))