]>
git.saurik.com Git - apple/xnu.git/blob - bsd/netinet/ip_log.c
2 * Copyright (c) 2000 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
20 * @APPLE_LICENSE_HEADER_END@
23 * Copyright (C) 1997 by Darren Reed.
25 * Redistribution and use in source and binary forms are permitted
26 * provided that this notice is preserved and due credit is given
27 * to the original author and the contributors.
30 #include "opt_ipfilter.h"
34 # define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
37 # if defined(KERNEL) && !defined(_KERNEL)
41 # if defined(_KERNEL) && !defined(IPFILTER_LKM)
42 # define __FreeBSD_version 300000 /* this will do as a hack */
44 # include <osreldate.h>
53 # include <sys/errno.h>
54 # include <sys/types.h>
55 # include <sys/param.h>
56 # include <sys/file.h>
57 # if __FreeBSD_version >= 220000 && defined(_KERNEL)
58 # include <sys/fcntl.h>
59 # include <sys/filio.h>
61 # include <sys/ioctl.h>
63 # include <sys/time.h>
64 # if defined(_KERNEL) && !defined(linux)
65 # include <sys/systm.h>
69 # if (NetBSD > 199609) || (OpenBSD > 199603) || defined(__FreeBSD__)
70 # include <sys/dirent.h>
75 # include <sys/mbuf.h>
78 # include <sys/filio.h>
79 # include <sys/cred.h>
81 # include <sys/sunddi.h>
82 # include <sys/ksynch.h>
83 # include <sys/kmem.h>
84 # include <sys/mkdev.h>
85 # include <sys/dditypes.h>
86 # include <sys/cmn_err.h>
89 # include <sys/protosw.h>
91 # include <sys/socket.h>
97 # if __FreeBSD_version >= 300000
98 # include <sys/malloc.h>
99 # include <machine/random.h>
101 # include <net/route.h>
102 # include <netinet/in.h>
104 # include <sys/ddi.h>
105 # ifdef IFF_DRVRLOCK /* IRIX6 */
106 # include <sys/hashing.h>
109 # if !defined(linux) && !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /*IRIX<6*/
110 # include <netinet/in_var.h>
112 # include <netinet/in_systm.h>
113 # include <netinet/ip.h>
114 # include <netinet/tcp.h>
115 # include <netinet/udp.h>
116 # include <netinet/ip_icmp.h>
118 # include <netinet/ip_var.h>
123 # include "netinet/ip_compat.h"
124 # include <netinet/tcpip.h>
125 # include "netinet/ip_fil.h"
126 # include "netinet/ip_proxy.h"
127 # include "netinet/ip_nat.h"
128 # include "netinet/ip_frag.h"
129 # include "netinet/ip_state.h"
130 # include "netinet/ip_auth.h"
132 # define MIN(a,b) (((a)<(b))?(a):(b))
136 # if SOLARIS || defined(__sgi)
137 extern kmutex_t ipl_mutex
;
139 extern kcondvar_t iplwait
;
143 iplog_t
**iplh
[IPL_LOGMAX
+1], *iplt
[IPL_LOGMAX
+1];
144 int iplused
[IPL_LOGMAX
+1];
145 static u_long iplcrc
[IPL_LOGMAX
+1];
146 static u_long iplcrcinit
;
148 static struct wait_queue
*iplwait
[IPL_LOGMAX
+1];
153 * Initialise log buffers & pointers. Also iniialised the CRC to a local
154 * secret for use in calculating the "last log checksum".
160 for (i
= IPL_LOGMAX
; i
>= 0; i
--) {
165 # if defined(__FreeBSD__) && __FreeBSD_version >= 300000
166 read_random(&iplcrcinit
, sizeof iplcrcinit
);
171 #if BSD >= 199306 || defined(__FreeBSD__) || defined(__sgi)
176 iplcrcinit
= tv
.tv_sec
^ (tv
.tv_usec
<< 8) ^ tv
.tv_usec
;
184 * Create a log record for a packet given that it has been triggered by a
185 * rule (or the default setting). Calculate the transport protocol header
186 * size using predetermined size of a couple of popular protocols and thus
187 * how much data to copy into the log, including part of the data body if
190 int ipflog(flags
, ip
, fin
, m
)
197 register int mlen
, hlen
;
203 ill_t
*ifp
= fin
->fin_ifp
;
205 struct ifnet
*ifp
= fin
->fin_ifp
;
209 * calculate header size.
211 hlen
= fin
->fin_hlen
;
212 if (ip
->ip_p
== IPPROTO_TCP
)
213 hlen
+= MIN(sizeof(tcphdr_t
), fin
->fin_dlen
);
214 else if (ip
->ip_p
== IPPROTO_UDP
)
215 hlen
+= MIN(sizeof(udphdr_t
), fin
->fin_dlen
);
216 else if (ip
->ip_p
== IPPROTO_ICMP
) {
217 struct icmp
*icmp
= (struct icmp
*)((char *)ip
+ hlen
);
220 * For ICMP, if the packet is an error packet, also include
221 * the information about the packet which caused the error.
223 switch (icmp
->icmp_type
)
226 case ICMP_SOURCEQUENCH
:
229 case ICMP_PARAMPROB
:
230 hlen
+= MIN(sizeof(struct icmp
) + 8, fin
->fin_dlen
);
233 hlen
+= MIN(sizeof(struct icmp
), fin
->fin_dlen
);
238 * Get the interface number and name to which this packet is
239 * currently associated.
242 ipfl
.fl_unit
= (u_char
)ifp
->ill_ppa
;
243 bcopy(ifp
->ill_name
, ipfl
.fl_ifname
, MIN(ifp
->ill_name_length
, 4));
244 mlen
= (flags
& FR_LOGBODY
) ? MIN(msgdsize(m
) - hlen
, 128) : 0;
246 # if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \
247 (defined(OpenBSD) && (OpenBSD >= 199603))
248 strncpy(ipfl
.fl_ifname
, ifp
->if_xname
, IFNAMSIZ
);
251 ipfl
.fl_unit
= (u_char
)ifp
->if_unit
;
253 if ((ipfl
.fl_ifname
[0] = ifp
->if_name
[0]))
254 if ((ipfl
.fl_ifname
[1] = ifp
->if_name
[1]))
255 if ((ipfl
.fl_ifname
[2] = ifp
->if_name
[2]))
256 ipfl
.fl_ifname
[3] = ifp
->if_name
[3];
258 mlen
= (flags
& FR_LOGBODY
) ? MIN(ip
->ip_len
- hlen
, 128) : 0;
260 ipfl
.fl_plen
= (u_char
)mlen
;
261 ipfl
.fl_hlen
= (u_char
)hlen
;
262 ipfl
.fl_rule
= fin
->fin_rule
;
263 ipfl
.fl_group
= fin
->fin_group
;
264 ipfl
.fl_flags
= flags
;
265 ptrs
[0] = (void *)&ipfl
;
266 sizes
[0] = sizeof(ipfl
);
270 * Are we copied from the mblk or an aligned array ?
272 if (ip
== (ip_t
*)m
->b_rptr
) {
274 sizes
[1] = hlen
+ mlen
;
278 sizes
[1] = hlen
+ mlen
;
283 sizes
[1] = hlen
+ mlen
;
286 crc
= (ipf_cksum((u_short
*)fin
, FI_CSIZE
) << 8) + iplcrcinit
;
287 return ipllog(IPL_LOGIPF
, crc
, ptrs
, sizes
, types
, 2);
294 int ipllog(dev
, crc
, items
, itemsz
, types
, cnt
)
306 * Check to see if this log record has a CRC which matches the last
307 * record logged. If it does, just up the count on the previous one
308 * rather than create a new one.
311 MUTEX_ENTER(&ipl_mutex
);
312 if ((iplcrc
[dev
] == crc
) && *iplh
[dev
]) {
313 (*iplh
[dev
])->ipl_count
++;
314 MUTEX_EXIT(&ipl_mutex
);
318 MUTEX_EXIT(&ipl_mutex
);
322 * Get the total amount of data to be logged.
324 for (i
= 0, len
= sizeof(iplog_t
); i
< cnt
; i
++)
328 * check that we have space to record this information and can
329 * allocate that much.
331 KMALLOC(buf
, caddr_t
, len
);
334 MUTEX_ENTER(&ipl_mutex
);
335 if ((iplused
[dev
] + len
) > IPLLOGSIZE
) {
336 MUTEX_EXIT(&ipl_mutex
);
341 MUTEX_EXIT(&ipl_mutex
);
344 * advance the log pointer to the next empty record and deduct the
345 * amount of space we're going to use.
347 ipl
= (iplog_t
*)buf
;
348 ipl
->ipl_magic
= IPL_MAGIC
;
350 ipl
->ipl_next
= NULL
;
351 ipl
->ipl_dsize
= len
;
352 # if SOLARIS || defined(sun) || defined(linux)
353 uniqtime((struct timeval
*)&ipl
->ipl_sec
);
355 # if BSD >= 199306 || defined(__FreeBSD__) || defined(__sgi)
356 microtime((struct timeval
*)&ipl
->ipl_sec
);
361 * Loop through all the items to be logged, copying each one to the
362 * buffer. Use bcopy for normal data or the mb_t copyout routine.
364 for (i
= 0, s
= buf
+ sizeof(*ipl
); i
< cnt
; i
++) {
366 bcopy(items
[i
], s
, itemsz
[i
]);
367 else if (types
[i
] == 1) {
369 copyout_mblk(items
[i
], 0, itemsz
[i
], s
);
371 m_copydata(items
[i
], 0, itemsz
[i
], s
);
376 MUTEX_ENTER(&ipl_mutex
);
378 iplh
[dev
] = &ipl
->ipl_next
;
381 mutex_exit(&ipl_mutex
);
383 MUTEX_EXIT(&ipl_mutex
);
385 wake_up_interruptible(&iplwait
[dev
]);
394 int ipflog_read(unit
, uio
)
399 int error
= 0, dlen
, copied
;
400 # if defined(_KERNEL) && !SOLARIS
405 * Sanity checks. Make sure the minor # is valid and we're copying
406 * a valid chunk of data.
408 if ((IPL_LOGMAX
< unit
) || (unit
< 0))
412 if ((uio
->uio_resid
< sizeof(iplog_t
)) ||
413 (uio
->uio_resid
> IPLLOGSIZE
))
417 * Lock the log so we can snapshot the variables. Wait for a signal
418 * if the log is empty.
421 MUTEX_ENTER(&ipl_mutex
);
423 while (!iplused
[unit
] || !iplt
[unit
]) {
424 # if SOLARIS && defined(_KERNEL)
425 if (!cv_wait_sig(&iplwait
, &ipl_mutex
)) {
426 MUTEX_EXIT(&ipl_mutex
);
431 interruptible_sleep_on(&iplwait
[unit
]);
432 if (current
->signal
& ~current
->blocked
)
435 MUTEX_EXIT(&ipl_mutex
);
437 error
= SLEEP(&iplh
[unit
], "ipl sleep");
441 MUTEX_ENTER(&ipl_mutex
);
443 # endif /* SOLARIS */
446 # if BSD >= 199306 || defined(__FreeBSD__)
447 uio
->uio_rw
= UIO_READ
;
450 for (copied
= 0; (ipl
= iplt
[unit
]); copied
+= dlen
) {
451 dlen
= ipl
->ipl_dsize
;
452 if (dlen
+ sizeof(iplog_t
) > uio
->uio_resid
)
455 * Don't hold the mutex over the uiomove call.
457 iplt
[unit
] = ipl
->ipl_next
;
458 MUTEX_EXIT(&ipl_mutex
);
460 error
= UIOMOVE((caddr_t
)ipl
, ipl
->ipl_dsize
, UIO_READ
, uio
);
461 KFREES((caddr_t
)ipl
, ipl
->ipl_dsize
);
465 MUTEX_ENTER(&ipl_mutex
);
466 iplused
[unit
] -= dlen
;
470 iplh
[unit
] = &iplt
[unit
];
474 MUTEX_EXIT(&ipl_mutex
);
487 int ipflog_clear(unit
)
493 while ((ipl
= iplt
[unit
])) {
494 iplt
[unit
] = ipl
->ipl_next
;
495 KFREES((caddr_t
)ipl
, ipl
->ipl_dsize
);
497 iplh
[unit
] = &iplt
[unit
];
498 used
= iplused
[unit
];
503 #endif /* IPFILTER_LOG */