30# endif 31#endif 32#ifdef IPFILTER_LOG 33# ifndef SOLARIS 34# define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) 35# endif 36# ifndef _KERNEL 37# include <stdio.h> 38# include <string.h> 39# include <stdlib.h> 40# include <ctype.h> 41# endif 42# include <sys/errno.h> 43# include <sys/types.h> 44# include <sys/file.h> 45# if __FreeBSD_version >= 220000 && defined(_KERNEL) 46# include <sys/fcntl.h> 47# include <sys/filio.h> 48# else 49# include <sys/ioctl.h> 50# endif 51# include <sys/time.h> 52# if defined(_KERNEL) && !defined(linux) 53# include <sys/systm.h> 54# endif 55# include <sys/uio.h> 56# if !SOLARIS 57# if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000) 58# include <sys/dirent.h> 59# else 60# include <sys/dir.h> 61# endif 62# ifndef linux 63# include <sys/mbuf.h> 64# endif 65# else 66# include <sys/filio.h> 67# include <sys/cred.h> 68# include <sys/ddi.h> 69# include <sys/sunddi.h> 70# include <sys/ksynch.h> 71# include <sys/kmem.h> 72# include <sys/mkdev.h> 73# include <sys/dditypes.h> 74# include <sys/cmn_err.h> 75# endif 76# ifndef linux 77# include <sys/protosw.h> 78# endif 79# include <sys/socket.h> 80 81# include <net/if.h> 82# ifdef sun 83# include <net/af.h> 84# endif 85# if __FreeBSD_version >= 300000 86# include <net/if_var.h> 87# endif 88# include <net/route.h> 89# include <netinet/in.h> 90# ifdef __sgi 91# include <sys/ddi.h> 92# ifdef IFF_DRVRLOCK /* IRIX6 */ 93# include <sys/hashing.h> 94# endif 95# endif 96# if !defined(linux) && !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /*IRIX<6*/ 97# include <netinet/in_var.h> 98# endif 99# include <netinet/in_systm.h> 100# include <netinet/ip.h> 101# include <netinet/tcp.h> 102# include <netinet/udp.h> 103# include <netinet/ip_icmp.h> 104# ifndef linux 105# include <netinet/ip_var.h> 106# endif 107# ifndef _KERNEL 108# include <syslog.h> 109# endif 110# include "netinet/ip_compat.h" 111# include <netinet/tcpip.h> 112# include "netinet/ip_fil.h" 113# include "netinet/ip_proxy.h" 114# include "netinet/ip_nat.h" 115# include "netinet/ip_frag.h" 116# include "netinet/ip_state.h" 117# include "netinet/ip_auth.h" 118# if (__FreeBSD_version >= 300000) 119# include <sys/malloc.h> 120# endif 121 122# ifndef MIN 123# define MIN(a,b) (((a)<(b))?(a):(b)) 124# endif 125 126 127# if SOLARIS || defined(__sgi) 128extern kmutex_t ipl_mutex; 129# if SOLARIS 130extern kcondvar_t iplwait; 131# endif 132# endif 133 134iplog_t **iplh[IPL_LOGMAX+1], *iplt[IPL_LOGMAX+1], *ipll[IPL_LOGMAX+1]; 135size_t iplused[IPL_LOGMAX+1]; 136static fr_info_t iplcrc[IPL_LOGMAX+1]; 137# ifdef linux 138static struct wait_queue *iplwait[IPL_LOGMAX+1]; 139# endif 140 141 142/* 143 * Initialise log buffers & pointers. Also iniialised the CRC to a local 144 * secret for use in calculating the "last log checksum". 145 */ 146void ipflog_init() 147{ 148 int i; 149 150 for (i = IPL_LOGMAX; i >= 0; i--) { 151 iplt[i] = NULL; 152 ipll[i] = NULL; 153 iplh[i] = &iplt[i]; 154 iplused[i] = 0; 155 bzero((char *)&iplcrc[i], sizeof(iplcrc[i])); 156 } 157} 158 159 160/* 161 * ipflog 162 * Create a log record for a packet given that it has been triggered by a 163 * rule (or the default setting). Calculate the transport protocol header 164 * size using predetermined size of a couple of popular protocols and thus 165 * how much data to copy into the log, including part of the data body if 166 * requested. 167 */ 168int ipflog(flags, ip, fin, m) 169u_int flags; 170ip_t *ip; 171fr_info_t *fin; 172mb_t *m; 173{ 174 ipflog_t ipfl; 175 register size_t mlen, hlen; 176 size_t sizes[2]; 177 void *ptrs[2]; 178 int types[2]; 179 u_char p; 180# if SOLARIS 181 ill_t *ifp = fin->fin_ifp; 182# else 183 struct ifnet *ifp = fin->fin_ifp; 184# endif 185 186 /* 187 * calculate header size. 188 */ 189 hlen = fin->fin_hlen; 190 if (fin->fin_off == 0) { 191 p = fin->fin_fi.fi_p; 192 if (p == IPPROTO_TCP) 193 hlen += MIN(sizeof(tcphdr_t), fin->fin_dlen); 194 else if (p == IPPROTO_UDP) 195 hlen += MIN(sizeof(udphdr_t), fin->fin_dlen); 196 else if (p == IPPROTO_ICMP) { 197 struct icmp *icmp; 198 199 icmp = (struct icmp *)fin->fin_dp; 200 201 /* 202 * For ICMP, if the packet is an error packet, also 203 * include the information about the packet which 204 * caused the error. 205 */ 206 switch (icmp->icmp_type) 207 { 208 case ICMP_UNREACH : 209 case ICMP_SOURCEQUENCH : 210 case ICMP_REDIRECT : 211 case ICMP_TIMXCEED : 212 case ICMP_PARAMPROB : 213 hlen += MIN(sizeof(struct icmp) + 8, 214 fin->fin_dlen); 215 break; 216 default : 217 hlen += MIN(sizeof(struct icmp), 218 fin->fin_dlen); 219 break; 220 } 221 } 222 } 223 /* 224 * Get the interface number and name to which this packet is 225 * currently associated. 226 */ 227# if SOLARIS 228 ipfl.fl_unit = (u_char)ifp->ill_ppa; 229 bcopy(ifp->ill_name, ipfl.fl_ifname, MIN(ifp->ill_name_length, 4)); 230 mlen = (flags & FR_LOGBODY) ? MIN(msgdsize(m) - hlen, 128) : 0; 231# else 232# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \ 233 (defined(OpenBSD) && (OpenBSD >= 199603)) 234 strncpy(ipfl.fl_ifname, ifp->if_xname, IFNAMSIZ); 235# else 236# ifndef linux 237 ipfl.fl_unit = (u_char)ifp->if_unit; 238# endif 239 if ((ipfl.fl_ifname[0] = ifp->if_name[0])) 240 if ((ipfl.fl_ifname[1] = ifp->if_name[1])) 241 if ((ipfl.fl_ifname[2] = ifp->if_name[2])) 242 ipfl.fl_ifname[3] = ifp->if_name[3]; 243# endif 244 mlen = (flags & FR_LOGBODY) ? MIN(fin->fin_plen - hlen, 128) : 0; 245# endif 246 ipfl.fl_plen = (u_char)mlen; 247 ipfl.fl_hlen = (u_char)hlen; 248 ipfl.fl_rule = fin->fin_rule; 249 ipfl.fl_group = fin->fin_group; 250 if (fin->fin_fr != NULL) 251 ipfl.fl_loglevel = fin->fin_fr->fr_loglevel; 252 else 253 ipfl.fl_loglevel = 0xffff; 254 ipfl.fl_flags = flags; 255 ptrs[0] = (void *)&ipfl; 256 sizes[0] = sizeof(ipfl); 257 types[0] = 0; 258# if SOLARIS 259 /* 260 * Are we copied from the mblk or an aligned array ? 261 */ 262 if (ip == (ip_t *)m->b_rptr) { 263 ptrs[1] = m; 264 sizes[1] = hlen + mlen; 265 types[1] = 1; 266 } else { 267 ptrs[1] = ip; 268 sizes[1] = hlen + mlen; 269 types[1] = 0; 270 } 271# else 272 ptrs[1] = m; 273 sizes[1] = hlen + mlen; 274 types[1] = 1; 275# endif 276 return ipllog(IPL_LOGIPF, fin, ptrs, sizes, types, 2); 277} 278 279 280/* 281 * ipllog 282 */ 283int ipllog(dev, fin, items, itemsz, types, cnt) 284int dev; 285fr_info_t *fin; 286void **items; 287size_t *itemsz; 288int *types, cnt; 289{ 290 caddr_t buf, s; 291 iplog_t *ipl; 292 size_t len; 293 int i; 294 295 /* 296 * Check to see if this log record has a CRC which matches the last 297 * record logged. If it does, just up the count on the previous one 298 * rather than create a new one. 299 */ 300 MUTEX_ENTER(&ipl_mutex); 301 if (fin != NULL) { 302 if ((ipll[dev] != NULL) && 303 bcmp((char *)fin, (char *)&iplcrc[dev], FI_CSIZE) == 0) { 304 ipll[dev]->ipl_count++; 305 MUTEX_EXIT(&ipl_mutex); 306 return 1; 307 } 308 bcopy((char *)fin, (char *)&iplcrc[dev], FI_CSIZE); 309 } else 310 bzero((char *)&iplcrc[dev], FI_CSIZE); 311 MUTEX_EXIT(&ipl_mutex); 312 313 /* 314 * Get the total amount of data to be logged. 315 */ 316 for (i = 0, len = sizeof(iplog_t); i < cnt; i++) 317 len += itemsz[i]; 318 319 /* 320 * check that we have space to record this information and can 321 * allocate that much. 322 */ 323 KMALLOCS(buf, caddr_t, len); 324 if (!buf) 325 return 0; 326 MUTEX_ENTER(&ipl_mutex); 327 if ((iplused[dev] + len) > IPLLOGSIZE) { 328 MUTEX_EXIT(&ipl_mutex); 329 KFREES(buf, len); 330 return 0; 331 } 332 iplused[dev] += len; 333 MUTEX_EXIT(&ipl_mutex); 334 335 /* 336 * advance the log pointer to the next empty record and deduct the 337 * amount of space we're going to use. 338 */ 339 ipl = (iplog_t *)buf; 340 ipl->ipl_magic = IPL_MAGIC; 341 ipl->ipl_count = 1; 342 ipl->ipl_next = NULL; 343 ipl->ipl_dsize = len; 344# if SOLARIS || defined(sun) || defined(linux) 345 uniqtime((struct timeval *)&ipl->ipl_sec); 346# else 347# if BSD >= 199306 || defined(__FreeBSD__) || defined(__sgi) 348 microtime((struct timeval *)&ipl->ipl_sec); 349# endif 350# endif 351 352 /* 353 * Loop through all the items to be logged, copying each one to the 354 * buffer. Use bcopy for normal data or the mb_t copyout routine. 355 */ 356 for (i = 0, s = buf + sizeof(*ipl); i < cnt; i++) { 357 if (types[i] == 0) 358 bcopy(items[i], s, itemsz[i]); 359 else if (types[i] == 1) { 360# if SOLARIS 361 copyout_mblk(items[i], 0, itemsz[i], s); 362# else 363 m_copydata(items[i], 0, itemsz[i], s); 364# endif 365 } 366 s += itemsz[i]; 367 } 368 MUTEX_ENTER(&ipl_mutex); 369 ipll[dev] = ipl; 370 *iplh[dev] = ipl; 371 iplh[dev] = &ipl->ipl_next; 372# if SOLARIS 373 cv_signal(&iplwait); 374 mutex_exit(&ipl_mutex); 375# else 376 MUTEX_EXIT(&ipl_mutex); 377# ifdef linux 378 wake_up_interruptible(&iplwait[dev]); 379# else 380 wakeup(&iplh[dev]); 381# endif 382# endif 383 return 1; 384} 385 386 387int ipflog_read(unit, uio) 388minor_t unit; 389struct uio *uio; 390{ 391 size_t dlen, copied; 392 int error = 0; 393 iplog_t *ipl; 394# if defined(_KERNEL) && !SOLARIS 395 int s; 396# endif 397 398 /* 399 * Sanity checks. Make sure the minor # is valid and we're copying 400 * a valid chunk of data. 401 */ 402 if (IPL_LOGMAX < unit) 403 return ENXIO; 404 if (!uio->uio_resid) 405 return 0; 406 if ((uio->uio_resid < sizeof(iplog_t)) || 407 (uio->uio_resid > IPLLOGSIZE)) 408 return EINVAL; 409 410 /* 411 * Lock the log so we can snapshot the variables. Wait for a signal 412 * if the log is empty. 413 */ 414 SPL_NET(s); 415 MUTEX_ENTER(&ipl_mutex); 416 417 while (!iplused[unit] || !iplt[unit]) { 418# if SOLARIS && defined(_KERNEL) 419 if (!cv_wait_sig(&iplwait, &ipl_mutex)) { 420 MUTEX_EXIT(&ipl_mutex); 421 return EINTR; 422 } 423# else 424# ifdef linux 425 interruptible_sleep_on(&iplwait[unit]); 426 if (current->signal & ~current->blocked) 427 return -EINTR; 428# else 429 MUTEX_EXIT(&ipl_mutex); 430 SPL_X(s); 431 error = SLEEP(&iplh[unit], "ipl sleep"); 432 if (error) 433 return error; 434 SPL_NET(s); 435 MUTEX_ENTER(&ipl_mutex); 436# endif /* linux */ 437# endif /* SOLARIS */ 438 } 439 440# if BSD >= 199306 || defined(__FreeBSD__) 441 uio->uio_rw = UIO_READ; 442# endif 443 444 for (copied = 0; (ipl = iplt[unit]); copied += dlen) { 445 dlen = ipl->ipl_dsize; 446 if (dlen > uio->uio_resid) 447 break; 448 /* 449 * Don't hold the mutex over the uiomove call. 450 */ 451 iplt[unit] = ipl->ipl_next; 452 iplused[unit] -= dlen; 453 MUTEX_EXIT(&ipl_mutex); 454 SPL_X(s); 455 error = UIOMOVE((caddr_t)ipl, dlen, UIO_READ, uio); 456 if (error) { 457 SPL_NET(s); 458 MUTEX_ENTER(&ipl_mutex); 459 ipl->ipl_next = iplt[unit]; 460 iplt[unit] = ipl; 461 iplused[unit] += dlen; 462 break; 463 } 464 KFREES((caddr_t)ipl, dlen); 465 SPL_NET(s); 466 MUTEX_ENTER(&ipl_mutex); 467 } 468 if (!iplt[unit]) { 469 iplused[unit] = 0; 470 iplh[unit] = &iplt[unit]; 471 ipll[unit] = NULL; 472 } 473 474 MUTEX_EXIT(&ipl_mutex); 475 SPL_X(s); 476# ifdef linux 477 if (!error) 478 return (int)copied; 479 return -error; 480# else 481 return error; 482# endif 483} 484 485 486int ipflog_clear(unit) 487minor_t unit; 488{ 489 iplog_t *ipl; 490 int used; 491 492 MUTEX_ENTER(&ipl_mutex); 493 while ((ipl = iplt[unit])) { 494 iplt[unit] = ipl->ipl_next; 495 KFREES((caddr_t)ipl, ipl->ipl_dsize); 496 } 497 iplh[unit] = &iplt[unit]; 498 ipll[unit] = NULL; 499 used = iplused[unit]; 500 iplused[unit] = 0; 501 bzero((char *)&iplcrc[unit], FI_CSIZE); 502 MUTEX_EXIT(&ipl_mutex); 503 return used; 504} 505#endif /* IPFILTER_LOG */
| 34# endif 35#endif 36#ifdef IPFILTER_LOG 37# ifndef SOLARIS 38# define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) 39# endif 40# ifndef _KERNEL 41# include <stdio.h> 42# include <string.h> 43# include <stdlib.h> 44# include <ctype.h> 45# endif 46# include <sys/errno.h> 47# include <sys/types.h> 48# include <sys/file.h> 49# if __FreeBSD_version >= 220000 && defined(_KERNEL) 50# include <sys/fcntl.h> 51# include <sys/filio.h> 52# else 53# include <sys/ioctl.h> 54# endif 55# include <sys/time.h> 56# if defined(_KERNEL) && !defined(linux) 57# include <sys/systm.h> 58# endif 59# include <sys/uio.h> 60# if !SOLARIS 61# if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000) 62# include <sys/dirent.h> 63# else 64# include <sys/dir.h> 65# endif 66# ifndef linux 67# include <sys/mbuf.h> 68# endif 69# else 70# include <sys/filio.h> 71# include <sys/cred.h> 72# include <sys/ddi.h> 73# include <sys/sunddi.h> 74# include <sys/ksynch.h> 75# include <sys/kmem.h> 76# include <sys/mkdev.h> 77# include <sys/dditypes.h> 78# include <sys/cmn_err.h> 79# endif 80# ifndef linux 81# include <sys/protosw.h> 82# endif 83# include <sys/socket.h> 84 85# include <net/if.h> 86# ifdef sun 87# include <net/af.h> 88# endif 89# if __FreeBSD_version >= 300000 90# include <net/if_var.h> 91# endif 92# include <net/route.h> 93# include <netinet/in.h> 94# ifdef __sgi 95# include <sys/ddi.h> 96# ifdef IFF_DRVRLOCK /* IRIX6 */ 97# include <sys/hashing.h> 98# endif 99# endif 100# if !defined(linux) && !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /*IRIX<6*/ 101# include <netinet/in_var.h> 102# endif 103# include <netinet/in_systm.h> 104# include <netinet/ip.h> 105# include <netinet/tcp.h> 106# include <netinet/udp.h> 107# include <netinet/ip_icmp.h> 108# ifndef linux 109# include <netinet/ip_var.h> 110# endif 111# ifndef _KERNEL 112# include <syslog.h> 113# endif 114# include "netinet/ip_compat.h" 115# include <netinet/tcpip.h> 116# include "netinet/ip_fil.h" 117# include "netinet/ip_proxy.h" 118# include "netinet/ip_nat.h" 119# include "netinet/ip_frag.h" 120# include "netinet/ip_state.h" 121# include "netinet/ip_auth.h" 122# if (__FreeBSD_version >= 300000) 123# include <sys/malloc.h> 124# endif 125 126# ifndef MIN 127# define MIN(a,b) (((a)<(b))?(a):(b)) 128# endif 129 130 131# if SOLARIS || defined(__sgi) 132extern kmutex_t ipl_mutex; 133# if SOLARIS 134extern kcondvar_t iplwait; 135# endif 136# endif 137 138iplog_t **iplh[IPL_LOGMAX+1], *iplt[IPL_LOGMAX+1], *ipll[IPL_LOGMAX+1]; 139size_t iplused[IPL_LOGMAX+1]; 140static fr_info_t iplcrc[IPL_LOGMAX+1]; 141# ifdef linux 142static struct wait_queue *iplwait[IPL_LOGMAX+1]; 143# endif 144 145 146/* 147 * Initialise log buffers & pointers. Also iniialised the CRC to a local 148 * secret for use in calculating the "last log checksum". 149 */ 150void ipflog_init() 151{ 152 int i; 153 154 for (i = IPL_LOGMAX; i >= 0; i--) { 155 iplt[i] = NULL; 156 ipll[i] = NULL; 157 iplh[i] = &iplt[i]; 158 iplused[i] = 0; 159 bzero((char *)&iplcrc[i], sizeof(iplcrc[i])); 160 } 161} 162 163 164/* 165 * ipflog 166 * Create a log record for a packet given that it has been triggered by a 167 * rule (or the default setting). Calculate the transport protocol header 168 * size using predetermined size of a couple of popular protocols and thus 169 * how much data to copy into the log, including part of the data body if 170 * requested. 171 */ 172int ipflog(flags, ip, fin, m) 173u_int flags; 174ip_t *ip; 175fr_info_t *fin; 176mb_t *m; 177{ 178 ipflog_t ipfl; 179 register size_t mlen, hlen; 180 size_t sizes[2]; 181 void *ptrs[2]; 182 int types[2]; 183 u_char p; 184# if SOLARIS 185 ill_t *ifp = fin->fin_ifp; 186# else 187 struct ifnet *ifp = fin->fin_ifp; 188# endif 189 190 /* 191 * calculate header size. 192 */ 193 hlen = fin->fin_hlen; 194 if (fin->fin_off == 0) { 195 p = fin->fin_fi.fi_p; 196 if (p == IPPROTO_TCP) 197 hlen += MIN(sizeof(tcphdr_t), fin->fin_dlen); 198 else if (p == IPPROTO_UDP) 199 hlen += MIN(sizeof(udphdr_t), fin->fin_dlen); 200 else if (p == IPPROTO_ICMP) { 201 struct icmp *icmp; 202 203 icmp = (struct icmp *)fin->fin_dp; 204 205 /* 206 * For ICMP, if the packet is an error packet, also 207 * include the information about the packet which 208 * caused the error. 209 */ 210 switch (icmp->icmp_type) 211 { 212 case ICMP_UNREACH : 213 case ICMP_SOURCEQUENCH : 214 case ICMP_REDIRECT : 215 case ICMP_TIMXCEED : 216 case ICMP_PARAMPROB : 217 hlen += MIN(sizeof(struct icmp) + 8, 218 fin->fin_dlen); 219 break; 220 default : 221 hlen += MIN(sizeof(struct icmp), 222 fin->fin_dlen); 223 break; 224 } 225 } 226 } 227 /* 228 * Get the interface number and name to which this packet is 229 * currently associated. 230 */ 231# if SOLARIS 232 ipfl.fl_unit = (u_char)ifp->ill_ppa; 233 bcopy(ifp->ill_name, ipfl.fl_ifname, MIN(ifp->ill_name_length, 4)); 234 mlen = (flags & FR_LOGBODY) ? MIN(msgdsize(m) - hlen, 128) : 0; 235# else 236# if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199603)) || \ 237 (defined(OpenBSD) && (OpenBSD >= 199603)) 238 strncpy(ipfl.fl_ifname, ifp->if_xname, IFNAMSIZ); 239# else 240# ifndef linux 241 ipfl.fl_unit = (u_char)ifp->if_unit; 242# endif 243 if ((ipfl.fl_ifname[0] = ifp->if_name[0])) 244 if ((ipfl.fl_ifname[1] = ifp->if_name[1])) 245 if ((ipfl.fl_ifname[2] = ifp->if_name[2])) 246 ipfl.fl_ifname[3] = ifp->if_name[3]; 247# endif 248 mlen = (flags & FR_LOGBODY) ? MIN(fin->fin_plen - hlen, 128) : 0; 249# endif 250 ipfl.fl_plen = (u_char)mlen; 251 ipfl.fl_hlen = (u_char)hlen; 252 ipfl.fl_rule = fin->fin_rule; 253 ipfl.fl_group = fin->fin_group; 254 if (fin->fin_fr != NULL) 255 ipfl.fl_loglevel = fin->fin_fr->fr_loglevel; 256 else 257 ipfl.fl_loglevel = 0xffff; 258 ipfl.fl_flags = flags; 259 ptrs[0] = (void *)&ipfl; 260 sizes[0] = sizeof(ipfl); 261 types[0] = 0; 262# if SOLARIS 263 /* 264 * Are we copied from the mblk or an aligned array ? 265 */ 266 if (ip == (ip_t *)m->b_rptr) { 267 ptrs[1] = m; 268 sizes[1] = hlen + mlen; 269 types[1] = 1; 270 } else { 271 ptrs[1] = ip; 272 sizes[1] = hlen + mlen; 273 types[1] = 0; 274 } 275# else 276 ptrs[1] = m; 277 sizes[1] = hlen + mlen; 278 types[1] = 1; 279# endif 280 return ipllog(IPL_LOGIPF, fin, ptrs, sizes, types, 2); 281} 282 283 284/* 285 * ipllog 286 */ 287int ipllog(dev, fin, items, itemsz, types, cnt) 288int dev; 289fr_info_t *fin; 290void **items; 291size_t *itemsz; 292int *types, cnt; 293{ 294 caddr_t buf, s; 295 iplog_t *ipl; 296 size_t len; 297 int i; 298 299 /* 300 * Check to see if this log record has a CRC which matches the last 301 * record logged. If it does, just up the count on the previous one 302 * rather than create a new one. 303 */ 304 MUTEX_ENTER(&ipl_mutex); 305 if (fin != NULL) { 306 if ((ipll[dev] != NULL) && 307 bcmp((char *)fin, (char *)&iplcrc[dev], FI_CSIZE) == 0) { 308 ipll[dev]->ipl_count++; 309 MUTEX_EXIT(&ipl_mutex); 310 return 1; 311 } 312 bcopy((char *)fin, (char *)&iplcrc[dev], FI_CSIZE); 313 } else 314 bzero((char *)&iplcrc[dev], FI_CSIZE); 315 MUTEX_EXIT(&ipl_mutex); 316 317 /* 318 * Get the total amount of data to be logged. 319 */ 320 for (i = 0, len = sizeof(iplog_t); i < cnt; i++) 321 len += itemsz[i]; 322 323 /* 324 * check that we have space to record this information and can 325 * allocate that much. 326 */ 327 KMALLOCS(buf, caddr_t, len); 328 if (!buf) 329 return 0; 330 MUTEX_ENTER(&ipl_mutex); 331 if ((iplused[dev] + len) > IPLLOGSIZE) { 332 MUTEX_EXIT(&ipl_mutex); 333 KFREES(buf, len); 334 return 0; 335 } 336 iplused[dev] += len; 337 MUTEX_EXIT(&ipl_mutex); 338 339 /* 340 * advance the log pointer to the next empty record and deduct the 341 * amount of space we're going to use. 342 */ 343 ipl = (iplog_t *)buf; 344 ipl->ipl_magic = IPL_MAGIC; 345 ipl->ipl_count = 1; 346 ipl->ipl_next = NULL; 347 ipl->ipl_dsize = len; 348# if SOLARIS || defined(sun) || defined(linux) 349 uniqtime((struct timeval *)&ipl->ipl_sec); 350# else 351# if BSD >= 199306 || defined(__FreeBSD__) || defined(__sgi) 352 microtime((struct timeval *)&ipl->ipl_sec); 353# endif 354# endif 355 356 /* 357 * Loop through all the items to be logged, copying each one to the 358 * buffer. Use bcopy for normal data or the mb_t copyout routine. 359 */ 360 for (i = 0, s = buf + sizeof(*ipl); i < cnt; i++) { 361 if (types[i] == 0) 362 bcopy(items[i], s, itemsz[i]); 363 else if (types[i] == 1) { 364# if SOLARIS 365 copyout_mblk(items[i], 0, itemsz[i], s); 366# else 367 m_copydata(items[i], 0, itemsz[i], s); 368# endif 369 } 370 s += itemsz[i]; 371 } 372 MUTEX_ENTER(&ipl_mutex); 373 ipll[dev] = ipl; 374 *iplh[dev] = ipl; 375 iplh[dev] = &ipl->ipl_next; 376# if SOLARIS 377 cv_signal(&iplwait); 378 mutex_exit(&ipl_mutex); 379# else 380 MUTEX_EXIT(&ipl_mutex); 381# ifdef linux 382 wake_up_interruptible(&iplwait[dev]); 383# else 384 wakeup(&iplh[dev]); 385# endif 386# endif 387 return 1; 388} 389 390 391int ipflog_read(unit, uio) 392minor_t unit; 393struct uio *uio; 394{ 395 size_t dlen, copied; 396 int error = 0; 397 iplog_t *ipl; 398# if defined(_KERNEL) && !SOLARIS 399 int s; 400# endif 401 402 /* 403 * Sanity checks. Make sure the minor # is valid and we're copying 404 * a valid chunk of data. 405 */ 406 if (IPL_LOGMAX < unit) 407 return ENXIO; 408 if (!uio->uio_resid) 409 return 0; 410 if ((uio->uio_resid < sizeof(iplog_t)) || 411 (uio->uio_resid > IPLLOGSIZE)) 412 return EINVAL; 413 414 /* 415 * Lock the log so we can snapshot the variables. Wait for a signal 416 * if the log is empty. 417 */ 418 SPL_NET(s); 419 MUTEX_ENTER(&ipl_mutex); 420 421 while (!iplused[unit] || !iplt[unit]) { 422# if SOLARIS && defined(_KERNEL) 423 if (!cv_wait_sig(&iplwait, &ipl_mutex)) { 424 MUTEX_EXIT(&ipl_mutex); 425 return EINTR; 426 } 427# else 428# ifdef linux 429 interruptible_sleep_on(&iplwait[unit]); 430 if (current->signal & ~current->blocked) 431 return -EINTR; 432# else 433 MUTEX_EXIT(&ipl_mutex); 434 SPL_X(s); 435 error = SLEEP(&iplh[unit], "ipl sleep"); 436 if (error) 437 return error; 438 SPL_NET(s); 439 MUTEX_ENTER(&ipl_mutex); 440# endif /* linux */ 441# endif /* SOLARIS */ 442 } 443 444# if BSD >= 199306 || defined(__FreeBSD__) 445 uio->uio_rw = UIO_READ; 446# endif 447 448 for (copied = 0; (ipl = iplt[unit]); copied += dlen) { 449 dlen = ipl->ipl_dsize; 450 if (dlen > uio->uio_resid) 451 break; 452 /* 453 * Don't hold the mutex over the uiomove call. 454 */ 455 iplt[unit] = ipl->ipl_next; 456 iplused[unit] -= dlen; 457 MUTEX_EXIT(&ipl_mutex); 458 SPL_X(s); 459 error = UIOMOVE((caddr_t)ipl, dlen, UIO_READ, uio); 460 if (error) { 461 SPL_NET(s); 462 MUTEX_ENTER(&ipl_mutex); 463 ipl->ipl_next = iplt[unit]; 464 iplt[unit] = ipl; 465 iplused[unit] += dlen; 466 break; 467 } 468 KFREES((caddr_t)ipl, dlen); 469 SPL_NET(s); 470 MUTEX_ENTER(&ipl_mutex); 471 } 472 if (!iplt[unit]) { 473 iplused[unit] = 0; 474 iplh[unit] = &iplt[unit]; 475 ipll[unit] = NULL; 476 } 477 478 MUTEX_EXIT(&ipl_mutex); 479 SPL_X(s); 480# ifdef linux 481 if (!error) 482 return (int)copied; 483 return -error; 484# else 485 return error; 486# endif 487} 488 489 490int ipflog_clear(unit) 491minor_t unit; 492{ 493 iplog_t *ipl; 494 int used; 495 496 MUTEX_ENTER(&ipl_mutex); 497 while ((ipl = iplt[unit])) { 498 iplt[unit] = ipl->ipl_next; 499 KFREES((caddr_t)ipl, ipl->ipl_dsize); 500 } 501 iplh[unit] = &iplt[unit]; 502 ipll[unit] = NULL; 503 used = iplused[unit]; 504 iplused[unit] = 0; 505 bzero((char *)&iplcrc[unit], FI_CSIZE); 506 MUTEX_EXIT(&ipl_mutex); 507 return used; 508} 509#endif /* IPFILTER_LOG */
|