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.
15 #if (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
21 #include <sys/types.h>
23 #include <sys/param.h>
29 #include <sys/socket.h>
30 #include <sys/ioctl.h>
38 #if !defined(__SVR4) && !defined(__svr4__)
39 # if (__FreeBSD_version >= 300000)
40 # include <sys/dirent.h>
45 # include <sys/filio.h>
46 # include <sys/byteorder.h>
48 #if !defined(__hpux) && (!defined(__SVR4) && !defined(__GNUC__))
54 #include <netinet/in.h>
55 #include <netinet/in_systm.h>
57 #include <netinet/ip.h>
58 #if !defined(__hpux) && !defined(linux)
59 # include <netinet/tcp_fsm.h>
62 #include <arpa/inet.h>
63 #include <arpa/nameser.h>
70 # include <sys/protosw.h>
71 # include <netinet/ip_var.h>
74 #include <netinet/tcp.h>
75 #include <netinet/ip_icmp.h>
80 #include "netinet/ip_compat.h"
81 #include <netinet/tcpip.h>
82 #include "netinet/ip_fil.h"
83 #include "netinet/ip_nat.h"
84 #include "netinet/ip_state.h"
85 #include "netinet/ip_proxy.h"
89 static const char sccsid
[] = "@(#)ipmon.c 1.21 6/5/96 (C)1993-2000 Darren Reed";
90 static const char rcsid
[] = "@(#)$Id: ipmon.c,v 1.33.2.10 2005/06/18 02:41:35 darrenr Exp $";
93 #if defined(sun) && !defined(SOLARIS2)
94 #define STRERROR(x) sys_errlist[x]
95 extern char *sys_errlist
[];
97 #define STRERROR(x) strerror(x)
107 typedef struct icmp_subtype
{
112 typedef struct icmp_type
{
114 struct icmp_subtype
*it_subtable
;
120 #define IST_SZ(x) (sizeof(x)/sizeof(icmp_subtype_t))
123 struct flags tcpfl
[] = {
135 #if defined(__hpux) || (defined(SOLARIS) && (SOLARIS2 < 10))
136 static char *pidfile
= "/etc/ipf/ipmon.pid";
138 # if (BSD >= 199306) || defined(SOLARIS)
139 static char *pidfile
= "/var/run/ipmon.pid";
141 static char *pidfile
= "/etc/ipmon.pid";
145 static char line
[2048];
147 static char *logfile
= NULL
;
148 static FILE *binarylog
= NULL
;
149 static char *binarylogfile
= NULL
;
150 static int donehup
= 0;
151 static void usage
__P((char *));
152 static void handlehup
__P((int));
153 static void flushlogs
__P((char *, FILE *));
154 static void print_log
__P((int, FILE *, char *, int));
155 static void print_ipflog
__P((FILE *, char *, int));
156 static void print_natlog
__P((FILE *, char *, int));
157 static void print_statelog
__P((FILE *, char *, int));
158 static int read_log
__P((int, int *, char *, int));
159 static void write_pid
__P((char *));
160 static char *icmpname
__P((u_int
, u_int
));
161 static char *icmpname6
__P((u_int
, u_int
));
162 static icmp_type_t
*find_icmptype
__P((int, icmp_type_t
*, size_t));
163 static icmp_subtype_t
*find_icmpsubtype
__P((int, icmp_subtype_t
*, size_t));
165 static struct tm
*get_tm
__P((u_32_t
));
167 static struct tm
*get_tm
__P((time_t));
170 char *hostname
__P((int, int, u_32_t
*));
171 char *portname
__P((int, char *, u_int
));
172 int main
__P((int, char *[]));
174 static void logopts
__P((int, char *));
175 static void init_tabs
__P((void));
176 static char *getproto
__P((u_int
));
178 static char **protocols
= NULL
;
179 static char **udp_ports
= NULL
;
180 static char **tcp_ports
= NULL
;
181 static char *conf_file
= NULL
;
184 #define OPT_SYSLOG 0x001
185 #define OPT_RESOLVE 0x002
186 #define OPT_HEXBODY 0x004
187 #define OPT_VERBOSE 0x008
188 #define OPT_HEXHDR 0x010
189 #define OPT_TAIL 0x020
190 #define OPT_NAT 0x080
191 #define OPT_STATE 0x100
192 #define OPT_FILTER 0x200
193 #define OPT_PORTNUM 0x400
194 #define OPT_LOGALL (OPT_NAT|OPT_STATE|OPT_FILTER)
195 #define OPT_LOGBODY 0x800
197 #define HOSTNAME_V4(a,b) hostname((a), 4, (u_32_t *)&(b))
200 #define LOGFAC LOG_LOCAL0
204 static icmp_subtype_t icmpunreachnames
[] = {
205 { ICMP_UNREACH_NET
, "net" },
206 { ICMP_UNREACH_HOST
, "host" },
207 { ICMP_UNREACH_PROTOCOL
, "protocol" },
208 { ICMP_UNREACH_PORT
, "port" },
209 { ICMP_UNREACH_NEEDFRAG
, "needfrag" },
210 { ICMP_UNREACH_SRCFAIL
, "srcfail" },
211 { ICMP_UNREACH_NET_UNKNOWN
, "net_unknown" },
212 { ICMP_UNREACH_HOST_UNKNOWN
, "host_unknown" },
213 { ICMP_UNREACH_NET
, "isolated" },
214 { ICMP_UNREACH_NET_PROHIB
, "net_prohib" },
215 { ICMP_UNREACH_NET_PROHIB
, "host_prohib" },
216 { ICMP_UNREACH_TOSNET
, "tosnet" },
217 { ICMP_UNREACH_TOSHOST
, "toshost" },
218 { ICMP_UNREACH_ADMIN_PROHIBIT
, "admin_prohibit" },
222 static icmp_subtype_t redirectnames
[] = {
223 { ICMP_REDIRECT_NET
, "net" },
224 { ICMP_REDIRECT_HOST
, "host" },
225 { ICMP_REDIRECT_TOSNET
, "tosnet" },
226 { ICMP_REDIRECT_TOSHOST
, "toshost" },
230 static icmp_subtype_t timxceednames
[] = {
231 { ICMP_TIMXCEED_INTRANS
, "transit" },
232 { ICMP_TIMXCEED_REASS
, "reassem" },
236 static icmp_subtype_t paramnames
[] = {
237 { ICMP_PARAMPROB_ERRATPTR
, "errata_pointer" },
238 { ICMP_PARAMPROB_OPTABSENT
, "optmissing" },
239 { ICMP_PARAMPROB_LENGTH
, "length" },
243 static icmp_type_t icmptypes
[] = {
244 { ICMP_ECHOREPLY
, NULL
, 0, "echoreply" },
245 { -1, NULL
, 0, NULL
},
246 { -1, NULL
, 0, NULL
},
247 { ICMP_UNREACH
, icmpunreachnames
,
248 IST_SZ(icmpunreachnames
),"unreach" },
249 { ICMP_SOURCEQUENCH
, NULL
, 0, "sourcequench" },
250 { ICMP_REDIRECT
, redirectnames
,
251 IST_SZ(redirectnames
), "redirect" },
252 { -1, NULL
, 0, NULL
},
253 { -1, NULL
, 0, NULL
},
254 { ICMP_ECHO
, NULL
, 0, "echo" },
255 { ICMP_ROUTERADVERT
, NULL
, 0, "routeradvert" },
256 { ICMP_ROUTERSOLICIT
, NULL
, 0, "routersolicit" },
257 { ICMP_TIMXCEED
, timxceednames
,
258 IST_SZ(timxceednames
), "timxceed" },
259 { ICMP_PARAMPROB
, paramnames
,
260 IST_SZ(paramnames
), "paramprob" },
261 { ICMP_TSTAMP
, NULL
, 0, "timestamp" },
262 { ICMP_TSTAMPREPLY
, NULL
, 0, "timestampreply" },
263 { ICMP_IREQ
, NULL
, 0, "inforeq" },
264 { ICMP_IREQREPLY
, NULL
, 0, "inforeply" },
265 { ICMP_MASKREQ
, NULL
, 0, "maskreq" },
266 { ICMP_MASKREPLY
, NULL
, 0, "maskreply" },
267 { -2, NULL
, 0, NULL
}
270 static icmp_subtype_t icmpredirect6
[] = {
271 { ICMP6_DST_UNREACH_NOROUTE
, "noroute" },
272 { ICMP6_DST_UNREACH_ADMIN
, "admin" },
273 { ICMP6_DST_UNREACH_NOTNEIGHBOR
, "neighbour" },
274 { ICMP6_DST_UNREACH_ADDR
, "address" },
275 { ICMP6_DST_UNREACH_NOPORT
, "noport" },
279 static icmp_subtype_t icmptimexceed6
[] = {
280 { ICMP6_TIME_EXCEED_TRANSIT
, "intransit" },
281 { ICMP6_TIME_EXCEED_REASSEMBLY
, "reassem" },
285 static icmp_subtype_t icmpparamprob6
[] = {
286 { ICMP6_PARAMPROB_HEADER
, "header" },
287 { ICMP6_PARAMPROB_NEXTHEADER
, "nextheader" },
288 { ICMP6_PARAMPROB_OPTION
, "option" },
292 static icmp_subtype_t icmpquerysubject6
[] = {
293 { ICMP6_NI_SUBJ_IPV6
, "ipv6" },
294 { ICMP6_NI_SUBJ_FQDN
, "fqdn" },
295 { ICMP6_NI_SUBJ_IPV4
, "ipv4" },
299 static icmp_subtype_t icmpnodeinfo6
[] = {
300 { ICMP6_NI_SUCCESS
, "success" },
301 { ICMP6_NI_REFUSED
, "refused" },
302 { ICMP6_NI_UNKNOWN
, "unknown" },
306 static icmp_subtype_t icmprenumber6
[] = {
307 { ICMP6_ROUTER_RENUMBERING_COMMAND
, "command" },
308 { ICMP6_ROUTER_RENUMBERING_RESULT
, "result" },
309 { ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET
, "seqnum_reset" },
313 static icmp_type_t icmptypes6
[] = {
314 { 0, NULL
, 0, NULL
},
315 { ICMP6_DST_UNREACH
, icmpredirect6
,
316 IST_SZ(icmpredirect6
), "unreach" },
317 { ICMP6_PACKET_TOO_BIG
, NULL
, 0, "toobig" },
318 { ICMP6_TIME_EXCEEDED
, icmptimexceed6
,
319 IST_SZ(icmptimexceed6
), "timxceed" },
320 { ICMP6_PARAM_PROB
, icmpparamprob6
,
321 IST_SZ(icmpparamprob6
), "paramprob" },
322 { ICMP6_ECHO_REQUEST
, NULL
, 0, "echo" },
323 { ICMP6_ECHO_REPLY
, NULL
, 0, "echoreply" },
324 { ICMP6_MEMBERSHIP_QUERY
, icmpquerysubject6
,
325 IST_SZ(icmpquerysubject6
), "groupmemberquery" },
326 { ICMP6_MEMBERSHIP_REPORT
,NULL
, 0, "groupmemberreport" },
327 { ICMP6_MEMBERSHIP_REDUCTION
,NULL
, 0, "groupmemberterm" },
328 { ND_ROUTER_SOLICIT
, NULL
, 0, "routersolicit" },
329 { ND_ROUTER_ADVERT
, NULL
, 0, "routeradvert" },
330 { ND_NEIGHBOR_SOLICIT
, NULL
, 0, "neighborsolicit" },
331 { ND_NEIGHBOR_ADVERT
, NULL
, 0, "neighboradvert" },
332 { ND_REDIRECT
, NULL
, 0, "redirect" },
333 { ICMP6_ROUTER_RENUMBERING
, icmprenumber6
,
334 IST_SZ(icmprenumber6
), "routerrenumber" },
335 { ICMP6_WRUREQUEST
, NULL
, 0, "whoareyourequest" },
336 { ICMP6_WRUREPLY
, NULL
, 0, "whoareyoureply" },
337 { ICMP6_FQDN_QUERY
, NULL
, 0, "fqdnquery" },
338 { ICMP6_FQDN_REPLY
, NULL
, 0, "fqdnreply" },
339 { ICMP6_NI_QUERY
, icmpnodeinfo6
,
340 IST_SZ(icmpnodeinfo6
), "nodeinforequest" },
341 { ICMP6_NI_REPLY
, NULL
, 0, "nodeinforeply" },
342 { MLD6_MTRACE_RESP
, NULL
, 0, "mtraceresponse" },
343 { MLD6_MTRACE
, NULL
, 0, "mtracerequest" },
344 { -2, NULL
, 0, NULL
}
347 static icmp_subtype_t
*find_icmpsubtype(type
, table
, tablesz
)
349 icmp_subtype_t
*table
;
358 if ((type
< 0) || (type
> table
[tablesz
- 2].ist_val
))
362 if (table
[type
].ist_val
== type
)
365 for (i
= 0, ist
= table
; ist
->ist_val
!= -2; i
++, ist
++)
366 if (ist
->ist_val
== type
)
372 static icmp_type_t
*find_icmptype(type
, table
, tablesz
)
383 if ((type
< 0) || (type
> table
[tablesz
- 2].it_val
))
387 if (table
[type
].it_val
== type
)
390 for (i
= 0, it
= table
; it
->it_val
!= -2; i
++, it
++)
391 if (it
->it_val
== type
)
397 static void handlehup(sig
)
400 signal(SIGHUP
, handlehup
);
405 static void init_tabs()
412 if (protocols
!= NULL
) {
413 for (i
= 0; i
< 256; i
++)
414 if (protocols
[i
] != NULL
) {
421 protocols
= (char **)malloc(256 * sizeof(*protocols
));
422 if (protocols
!= NULL
) {
423 bzero((char *)protocols
, 256 * sizeof(*protocols
));
426 while ((p
= getprotoent()) != NULL
)
427 if (p
->p_proto
>= 0 && p
->p_proto
<= 255 &&
428 p
->p_name
!= NULL
&& protocols
[p
->p_proto
] == NULL
)
429 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
);
976 static void print_ipflog(log
, buf
, blen
)
986 int i
, v
, lvl
, res
, len
, off
, plen
, ipoff
, defaction
;
996 ipl
= (iplog_t
*)buf
;
997 ipf
= (ipflog_t
*)((char *)buf
+ sizeof(*ipl
));
998 ip
= (ip_t
*)((char *)ipf
+ sizeof(*ipf
));
1000 res
= (opts
& OPT_RESOLVE
) ? 1 : 0;
1003 tm
= get_tm(ipl
->ipl_sec
);
1006 if (!(opts
& OPT_SYSLOG
)) {
1007 (void) strftime(t
, len
, "%d/%m/%Y ", tm
);
1012 (void) strftime(t
, len
, "%T", tm
);
1014 (void) sprintf(t
, ".%-.6ld ", ipl
->ipl_usec
);
1016 if (ipl
->ipl_count
> 1) {
1017 (void) sprintf(t
, "%dx ", ipl
->ipl_count
);
1020 #if (defined(MENTAT) || \
1021 (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \
1022 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) || \
1023 (defined(OpenBSD) && (OpenBSD >= 199603))) || defined(linux)
1025 char ifname
[sizeof(ipf
->fl_ifname
) + 1];
1027 strncpy(ifname
, ipf
->fl_ifname
, sizeof(ipf
->fl_ifname
));
1028 ifname
[sizeof(ipf
->fl_ifname
)] = '\0';
1029 (void) sprintf(t
, "%s", ifname
);
1031 # if defined(MENTAT) || defined(linux)
1032 if (ISALPHA(*(t
- 1))) {
1033 sprintf(t
, "%d", ipf
->fl_unit
);
1039 for (len
= 0; len
< 3; len
++)
1040 if (ipf
->fl_ifname
[len
] == '\0')
1042 if (ipf
->fl_ifname
[len
])
1044 (void) sprintf(t
, "%*.*s%u", len
, len
, ipf
->fl_ifname
, ipf
->fl_unit
);
1047 #if defined(__sgi) || defined(_AIX51) || defined(__powerpc__) || \
1049 if ((ipf
->fl_group
[0] == 255) && (ipf
->fl_group
[1] == '\0'))
1051 if ((ipf
->fl_group
[0] == -1) && (ipf
->fl_group
[1] == '\0'))
1054 else if (ipf
->fl_group
[0] == '\0')
1055 (void) strcpy(t
, " @0:");
1057 (void) sprintf(t
, " @%s:", ipf
->fl_group
);
1059 if (ipf
->fl_rule
== 0xffffffff)
1062 (void) sprintf(t
, "%u ", ipf
->fl_rule
+ 1);
1067 if (ipf
->fl_lflags
& FI_SHORT
) {
1072 if (FR_ISPASS(ipf
->fl_flags
)) {
1073 if (ipf
->fl_flags
& FR_LOGP
)
1077 } else if (FR_ISBLOCK(ipf
->fl_flags
)) {
1078 if (ipf
->fl_flags
& FR_LOGB
)
1083 } else if ((ipf
->fl_flags
& FR_LOGMASK
) == FR_LOG
) {
1086 } else if (ipf
->fl_flags
& FF_LOGNOMATCH
) {
1092 if (ipf
->fl_loglevel
!= 0xffff)
1093 lvl
= ipf
->fl_loglevel
;
1103 p
= (u_short
)ip6
->ip6_nxt
;
1104 s
= (u_32_t
*)&ip6
->ip6_src
;
1105 d
= (u_32_t
*)&ip6
->ip6_dst
;
1106 plen
= hl
+ ntohs(ip6
->ip6_plen
);
1111 } else if (v
== 4) {
1112 hl
= IP_HL(ip
) << 2;
1114 off
= ipoff
& IP_OFFMASK
;
1115 p
= (u_short
)ip
->ip_p
;
1116 s
= (u_32_t
*)&ip
->ip_src
;
1117 d
= (u_32_t
*)&ip
->ip_dst
;
1122 proto
= getproto(p
);
1124 if ((p
== IPPROTO_TCP
|| p
== IPPROTO_UDP
) && !off
) {
1125 tp
= (tcphdr_t
*)((char *)ip
+ hl
);
1126 if (!(ipf
->fl_lflags
& FI_SHORT
)) {
1127 (void) sprintf(t
, "%s,%s -> ", hostname(res
, v
, s
),
1128 portname(res
, proto
, (u_int
)tp
->th_sport
));
1130 (void) sprintf(t
, "%s,%s PR %s len %hu %hu",
1131 hostname(res
, v
, d
),
1132 portname(res
, proto
, (u_int
)tp
->th_dport
),
1136 if (p
== IPPROTO_TCP
) {
1139 for (i
= 0; tcpfl
[i
].value
; i
++)
1140 if (tp
->th_flags
& tcpfl
[i
].value
)
1141 *t
++ = tcpfl
[i
].flag
;
1142 if (opts
& OPT_VERBOSE
) {
1143 (void) sprintf(t
, " %lu %lu %hu",
1144 (u_long
)(ntohl(tp
->th_seq
)),
1145 (u_long
)(ntohl(tp
->th_ack
)),
1152 (void) sprintf(t
, "%s -> ", hostname(res
, v
, s
));
1154 (void) sprintf(t
, "%s PR %s len %hu %hu",
1155 hostname(res
, v
, d
), proto
, hl
, plen
);
1157 } else if ((p
== IPPROTO_ICMPV6
) && !off
&& (v
== 6)) {
1158 ic
= (struct icmp
*)((char *)ip
+ hl
);
1159 (void) sprintf(t
, "%s -> ", hostname(res
, v
, s
));
1161 (void) sprintf(t
, "%s PR icmpv6 len %hu %hu icmpv6 %s",
1162 hostname(res
, v
, d
), hl
, plen
,
1163 icmpname6(ic
->icmp_type
, ic
->icmp_code
));
1164 } else if ((p
== IPPROTO_ICMP
) && !off
&& (v
== 4)) {
1165 ic
= (struct icmp
*)((char *)ip
+ hl
);
1166 (void) sprintf(t
, "%s -> ", hostname(res
, v
, s
));
1168 (void) sprintf(t
, "%s PR icmp len %hu %hu icmp %s",
1169 hostname(res
, v
, d
), hl
, plen
,
1170 icmpname(ic
->icmp_type
, ic
->icmp_code
));
1171 if (ic
->icmp_type
== ICMP_UNREACH
||
1172 ic
->icmp_type
== ICMP_SOURCEQUENCH
||
1173 ic
->icmp_type
== ICMP_PARAMPROB
||
1174 ic
->icmp_type
== ICMP_REDIRECT
||
1175 ic
->icmp_type
== ICMP_TIMXCEED
) {
1177 i
= ntohs(ipc
->ip_len
);
1179 * XXX - try to guess endian of ip_len in ICMP
1184 ipoff
= ntohs(ipc
->ip_off
);
1185 proto
= getproto(ipc
->ip_p
);
1187 if (!(ipoff
& IP_OFFMASK
) &&
1188 ((ipc
->ip_p
== IPPROTO_TCP
) ||
1189 (ipc
->ip_p
== IPPROTO_UDP
))) {
1190 tp
= (tcphdr_t
*)((char *)ipc
+ hl
);
1192 (void) sprintf(t
, " for %s,%s -",
1193 HOSTNAME_V4(res
, ipc
->ip_src
),
1194 portname(res
, proto
,
1195 (u_int
)tp
->th_sport
));
1197 (void) sprintf(t
, " %s,%s PR %s len %hu %hu",
1198 HOSTNAME_V4(res
, ipc
->ip_dst
),
1199 portname(res
, proto
,
1200 (u_int
)tp
->th_dport
),
1201 proto
, IP_HL(ipc
) << 2, i
);
1202 } else if (!(ipoff
& IP_OFFMASK
) &&
1203 (ipc
->ip_p
== IPPROTO_ICMP
)) {
1204 icmp
= (icmphdr_t
*)((char *)ipc
+ hl
);
1207 (void) sprintf(t
, " for %s -",
1208 HOSTNAME_V4(res
, ipc
->ip_src
));
1211 " %s PR icmp len %hu %hu icmp %d/%d",
1212 HOSTNAME_V4(res
, ipc
->ip_dst
),
1214 icmp
->icmp_type
, icmp
->icmp_code
);
1217 (void) sprintf(t
, " for %s -",
1218 HOSTNAME_V4(res
, ipc
->ip_src
));
1220 (void) sprintf(t
, " %s PR %s len %hu (%hu)",
1221 HOSTNAME_V4(res
, ipc
->ip_dst
), proto
,
1222 IP_HL(ipc
) << 2, i
);
1224 if (ipoff
& IP_OFFMASK
) {
1226 "(frag %d:%hu@%hu%s%s)",
1228 i
- (IP_HL(ipc
) << 2),
1229 (ipoff
& IP_OFFMASK
) << 3,
1230 ipoff
& IP_MF
? "+" : "",
1231 ipoff
& IP_DF
? "-" : "");
1237 (void) sprintf(t
, "%s -> ", hostname(res
, v
, s
));
1239 (void) sprintf(t
, "%s PR %s len %hu (%hu)",
1240 hostname(res
, v
, d
), proto
, hl
, plen
);
1242 if (off
& IP_OFFMASK
)
1243 (void) sprintf(t
, " (frag %d:%hu@%hu%s%s)",
1245 plen
- hl
, (off
& IP_OFFMASK
) << 3,
1246 ipoff
& IP_MF
? "+" : "",
1247 ipoff
& IP_DF
? "-" : "");
1252 if (ipf
->fl_flags
& FR_KEEPSTATE
) {
1253 (void) strcpy(t
, " K-S");
1257 if (ipf
->fl_flags
& FR_KEEPFRAG
) {
1258 (void) strcpy(t
, " K-F");
1262 if (ipf
->fl_dir
== 0)
1264 else if (ipf
->fl_dir
== 1)
1267 if (ipf
->fl_logtag
!= 0) {
1268 sprintf(t
, " log-tag %d", ipf
->fl_logtag
);
1271 if (ipf
->fl_nattag
.ipt_num
[0] != 0) {
1272 strcpy(t
, " nat-tag ");
1274 strncpy(t
, ipf
->fl_nattag
.ipt_tag
, sizeof(ipf
->fl_nattag
));
1277 if ((ipf
->fl_lflags
& FI_LOWTTL
) != 0) {
1278 strcpy(t
, " low-ttl");
1281 if ((ipf
->fl_lflags
& FI_OOW
) != 0) {
1282 if (ipf
->fl_lflags
& FI_NEG_OOW
) {
1283 strcpy(t
, " NEG_OOW");
1284 t
+= sizeof (" NEG_OOW") - 1;
1287 t
+= sizeof (" OOW") - 1;
1290 if ((ipf
->fl_lflags
& FI_BAD
) != 0) {
1294 if ((ipf
->fl_lflags
& FI_NATED
) != 0) {
1298 if ((ipf
->fl_lflags
& FI_BADNAT
) != 0) {
1299 strcpy(t
, " bad-NAT");
1302 if ((ipf
->fl_lflags
& FI_BADSRC
) != 0) {
1303 strcpy(t
, " bad-src");
1306 if ((ipf
->fl_lflags
& FI_MULTICAST
) != 0) {
1307 strcpy(t
, " multicast");
1310 if ((ipf
->fl_lflags
& FI_BROADCAST
) != 0) {
1311 strcpy(t
, " broadcast");
1314 if ((ipf
->fl_lflags
& (FI_MULTICAST
|FI_BROADCAST
|FI_MBCAST
)) ==
1316 strcpy(t
, " mbcast");
1322 if (conf_file
!= NULL
)
1323 defaction
= check_action(buf
, line
, opts
, lvl
);
1324 if (defaction
== 0) {
1325 if (opts
& OPT_SYSLOG
)
1326 syslog(lvl
, "%s", line
);
1328 (void) fprintf(log
, "%s", line
);
1329 if (opts
& OPT_HEXHDR
)
1330 dumphex(log
, opts
, buf
,
1331 sizeof(iplog_t
) + sizeof(*ipf
));
1332 if (opts
& OPT_HEXBODY
)
1333 dumphex(log
, opts
, (char *)ip
,
1334 ipf
->fl_plen
+ ipf
->fl_hlen
);
1335 else if ((opts
& OPT_LOGBODY
) && (ipf
->fl_flags
& FR_LOGBODY
))
1336 dumphex(log
, opts
, (char *)ip
+ ipf
->fl_hlen
,
1342 static void usage(prog
)
1345 fprintf(stderr
, "%s: [-abDFhnpstvxX] %s %s %s %s %s %s %s\n",
1346 prog
, "[-G|-z zonename]", "[-N device]",
1347 "[ [-o [NSI]] [-O [NSI]]", "[-P pidfile]", "[-S device]",
1348 "[-f device]", "filename");
1353 static void write_pid(file
)
1359 if ((fd
= open(file
, O_CREAT
|O_TRUNC
|O_WRONLY
, 0644)) >= 0) {
1360 fp
= fdopen(fd
, "w");
1364 "unable to open/create pid file: %s\n", file
);
1367 fprintf(fp
, "%d", getpid());
1373 static void flushlogs(file
, log
)
1377 int fd
, flushed
= 0;
1379 if ((fd
= open(file
, O_RDWR
)) == -1) {
1380 (void) fprintf(stderr
, "%s: open: %s\n",
1381 file
, STRERROR(errno
));
1385 if (setzone(fd
) != 0) {
1390 if (ioctl(fd
, SIOCIPFFB
, &flushed
) == 0) {
1391 printf("%d bytes flushed from log buffer\n",
1395 perror("SIOCIPFFB");
1399 if (opts
& OPT_SYSLOG
)
1400 syslog(LOG_INFO
, "%d bytes flushed from log\n",
1402 else if (log
!= stdout
)
1403 fprintf(log
, "%d bytes flushed from log\n", flushed
);
1408 static void logopts(turnon
, options
)
1415 for (s
= options
; *s
; s
++)
1426 flags
|= OPT_FILTER
;
1429 fprintf(stderr
, "Unknown log option %c\n", *s
);
1441 int main(argc
, argv
)
1448 int fd
[3], doread
, n
, i
;
1449 int tr
, nr
, regular
[3], c
;
1450 int fdt
[3], devices
= 0, make_daemon
= 0;
1451 char buf
[DEFAULT_IPFLOGSIZE
], *iplfile
[3], *s
;
1453 extern char *optarg
;
1454 const char *optstr
= "?abB:C:Df:G:FhnN:o:O:pP:sS:tvxXz:";
1456 fd
[0] = fd
[1] = fd
[2] = -1;
1457 fdt
[0] = fdt
[1] = fdt
[2] = -1;
1458 iplfile
[0] = IPL_NAME
;
1459 iplfile
[1] = IPNAT_NAME
;
1460 iplfile
[2] = IPSTATE_NAME
;
1463 * We need to set the zone name before calling openlog in
1464 * the switch statement below
1466 getzoneopt(argc
, argv
, optstr
);
1468 while ((c
= getopt(argc
, argv
, optstr
)) != -1)
1473 fdt
[0] = IPL_LOGIPF
;
1474 fdt
[1] = IPL_LOGNAT
;
1475 fdt
[2] = IPL_LOGSTATE
;
1478 opts
|= OPT_LOGBODY
;
1481 binarylogfile
= optarg
;
1482 binarylog
= fopen(optarg
, "a");
1490 case 'f' : case 'I' :
1492 fdt
[0] = IPL_LOGIPF
;
1493 iplfile
[0] = optarg
;
1496 flushlogs(iplfile
[0], log
);
1497 flushlogs(iplfile
[1], log
);
1498 flushlogs(iplfile
[2], log
);
1501 /* Already handled by getzoneopt() above */
1504 opts
|= OPT_RESOLVE
;
1508 fdt
[1] = IPL_LOGNAT
;
1509 iplfile
[1] = optarg
;
1511 case 'o' : case 'O' :
1512 logopts(c
== 'o', optarg
);
1513 fdt
[0] = fdt
[1] = fdt
[2] = -1;
1514 if (opts
& OPT_FILTER
)
1515 fdt
[0] = IPL_LOGIPF
;
1517 fdt
[1] = IPL_LOGNAT
;
1518 if (opts
& OPT_STATE
)
1519 fdt
[2] = IPL_LOGSTATE
;
1522 opts
|= OPT_PORTNUM
;
1528 s
= strrchr(argv
[0], '/');
1533 openlog(s
, LOG_NDELAY
|LOG_PID
, LOGFAC
);
1540 fdt
[2] = IPL_LOGSTATE
;
1541 iplfile
[2] = optarg
;
1547 opts
|= OPT_VERBOSE
;
1550 opts
|= OPT_HEXBODY
;
1556 /* Already handled by getzoneopt() above */
1566 if (load_config(conf_file
) == -1)
1570 * Default action is to only open the filter log file.
1572 if ((fdt
[0] == -1) && (fdt
[1] == -1) && (fdt
[2] == -1))
1573 fdt
[0] = IPL_LOGIPF
;
1575 for (i
= 0; i
< 3; i
++) {
1578 if (!strcmp(iplfile
[i
], "-"))
1581 if ((fd
[i
] = open(iplfile
[i
], O_RDONLY
)) == -1) {
1582 (void) fprintf(stderr
,
1583 "%s: open: %s\n", iplfile
[i
],
1588 if (fstat(fd
[i
], &sb
) == -1) {
1589 (void) fprintf(stderr
, "%d: fstat: %s\n",
1590 fd
[i
], STRERROR(errno
));
1595 if (setzone(fd
[i
]) != 0) {
1600 if (!(regular
[i
] = !S_ISCHR(sb
.st_mode
)))
1605 if (!(opts
& OPT_SYSLOG
)) {
1606 logfile
= argv
[optind
];
1607 log
= logfile
? fopen(logfile
, "a") : stdout
;
1609 (void) fprintf(stderr
, "%s: fopen: %s\n",
1610 argv
[optind
], STRERROR(errno
));
1614 setvbuf(log
, NULL
, _IONBF
, 0);
1618 if (make_daemon
&& ((log
!= stdout
) || (opts
& OPT_SYSLOG
))) {
1620 daemon(0, !(opts
& OPT_SYSLOG
));
1623 if ((pid
= fork()) > 0)
1626 (void) fprintf(stderr
, "%s: fork() failed: %s\n",
1627 argv
[0], STRERROR(errno
));
1632 if ((opts
& OPT_SYSLOG
))
1640 signal(SIGHUP
, handlehup
);
1642 for (doread
= 1; doread
; ) {
1645 for (i
= 0; i
< 3; i
++) {
1650 if (ioctl(fd
[i
], FIONREAD
, &tr
) == -1) {
1651 if (opts
& OPT_SYSLOG
)
1653 "ioctl(FIONREAD): %m");
1655 perror("ioctl(FIONREAD)");
1660 tr
= (lseek(fd
[i
], 0, SEEK_CUR
) < sb
.st_size
);
1661 if (!tr
&& !(opts
& OPT_TAIL
))
1668 tr
= read_log(fd
[i
], &n
, buf
, sizeof(buf
));
1670 if (logfile
&& (fp
= fopen(logfile
, "a"))) {
1674 if (binarylogfile
&& (fp
= fopen(binarylogfile
, "a"))) {
1679 if (conf_file
!= NULL
)
1680 load_config(conf_file
);
1687 if (opts
& OPT_SYSLOG
)
1688 syslog(LOG_CRIT
, "read: %m\n");
1694 if (opts
& OPT_SYSLOG
)
1695 syslog(LOG_CRIT
, "aborting logging\n");
1697 fprintf(log
, "aborting logging\n");
1704 print_log(fdt
[i
], log
, buf
, n
);
1705 if (!(opts
& OPT_SYSLOG
))
1711 if (!nr
&& ((opts
& OPT_TAIL
) || devices
))