fil.c (128019) | fil.c (130886) |
---|---|
1/* 2 * Copyright (C) 1993-2001 by Darren Reed. 3 * 4 * See the IPFILTER.LICENCE file for details on licencing. 5 */ 6#if defined(__sgi) && (IRIX > 602) 7# include <sys/ptimers.h> 8#endif --- 28 unchanged lines hidden (view full) --- 37# include <string.h> 38# include <stdlib.h> 39#endif 40#if !defined(__SVR4) && !defined(__svr4__) 41# ifndef linux 42# include <sys/mbuf.h> 43# endif 44#else | 1/* 2 * Copyright (C) 1993-2001 by Darren Reed. 3 * 4 * See the IPFILTER.LICENCE file for details on licencing. 5 */ 6#if defined(__sgi) && (IRIX > 602) 7# include <sys/ptimers.h> 8#endif --- 28 unchanged lines hidden (view full) --- 37# include <string.h> 38# include <stdlib.h> 39#endif 40#if !defined(__SVR4) && !defined(__svr4__) 41# ifndef linux 42# include <sys/mbuf.h> 43# endif 44#else |
45# include <sys/cmn_err.h> |
|
45# include <sys/byteorder.h> 46# if SOLARIS2 < 5 47# include <sys/dditypes.h> 48# endif 49# include <sys/stream.h> 50#endif 51#ifndef linux 52# include <sys/protosw.h> --- 41 unchanged lines hidden (view full) --- 94# define MIN(a,b) (((a)<(b))?(a):(b)) 95#endif 96#include "netinet/ipl.h" 97 98#include <machine/in_cksum.h> 99 100#if !defined(lint) 101static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-2000 Darren Reed"; | 46# include <sys/byteorder.h> 47# if SOLARIS2 < 5 48# include <sys/dditypes.h> 49# endif 50# include <sys/stream.h> 51#endif 52#ifndef linux 53# include <sys/protosw.h> --- 41 unchanged lines hidden (view full) --- 95# define MIN(a,b) (((a)<(b))?(a):(b)) 96#endif 97#include "netinet/ipl.h" 98 99#include <machine/in_cksum.h> 100 101#if !defined(lint) 102static const char sccsid[] = "@(#)fil.c 1.36 6/5/96 (C) 1993-2000 Darren Reed"; |
102static const char rcsid[] = "@(#)$FreeBSD: head/sys/contrib/ipfilter/netinet/fil.c 128019 2004-04-07 20:46:16Z imp $"; | 103static const char rcsid[] = "@(#)$FreeBSD: head/sys/contrib/ipfilter/netinet/fil.c 130886 2004-06-21 22:46:36Z darrenr $"; |
103#endif 104 105#ifndef _KERNEL 106# include "ipf.h" 107# include "ipt.h" 108extern int opts; 109 110# define FR_VERBOSE(verb_pr) verbose verb_pr --- 30 unchanged lines hidden (view full) --- 141#endif 142char ipfilter_version[] = IPL_VERSION; 143 144fr_info_t frcache[2]; 145 146static int frflushlist __P((int, minor_t, int *, frentry_t **)); 147#ifdef _KERNEL 148static void frsynclist __P((frentry_t *)); | 104#endif 105 106#ifndef _KERNEL 107# include "ipf.h" 108# include "ipt.h" 109extern int opts; 110 111# define FR_VERBOSE(verb_pr) verbose verb_pr --- 30 unchanged lines hidden (view full) --- 142#endif 143char ipfilter_version[] = IPL_VERSION; 144 145fr_info_t frcache[2]; 146 147static int frflushlist __P((int, minor_t, int *, frentry_t **)); 148#ifdef _KERNEL 149static void frsynclist __P((frentry_t *)); |
150# ifndef __sgi 151static void *ipf_pullup __P((mb_t *, fr_info_t *, int, void *)); 152# endif |
|
149#endif 150 151 152/* 153 * bit values for identifying presence of individual IP options 154 */ 155struct optlist ipopts[20] = { 156 { IPOPT_NOP, 0x000001 }, --- 32 unchanged lines hidden (view full) --- 189 { IPSO_CLASS_RES1, 0x80 } 190}; 191 192 193/* 194 * compact the IP header into a structure which contains just the info. 195 * which is useful for comparing IP headers with. 196 */ | 153#endif 154 155 156/* 157 * bit values for identifying presence of individual IP options 158 */ 159struct optlist ipopts[20] = { 160 { IPOPT_NOP, 0x000001 }, --- 32 unchanged lines hidden (view full) --- 193 { IPSO_CLASS_RES1, 0x80 } 194}; 195 196 197/* 198 * compact the IP header into a structure which contains just the info. 199 * which is useful for comparing IP headers with. 200 */ |
197void fr_makefrip(hlen, ip, fin) | 201int fr_makefrip(hlen, ip, fin) |
198int hlen; 199ip_t *ip; 200fr_info_t *fin; 201{ 202 u_short optmsk = 0, secmsk = 0, auth = 0; 203 int i, mv, ol, off, p, plen, v; | 202int hlen; 203ip_t *ip; 204fr_info_t *fin; 205{ 206 u_short optmsk = 0, secmsk = 0, auth = 0; 207 int i, mv, ol, off, p, plen, v; |
208#if defined(_KERNEL) 209# if SOLARIS 210 mb_t *m = fin->fin_qfm; 211# else 212 mb_t *m = fin->fin_mp ? *fin->fin_mp : NULL; 213# endif 214#endif |
|
204 fr_ip_t *fi = &fin->fin_fi; 205 struct optlist *op; 206 u_char *s, opt; 207 tcphdr_t *tcp; 208 209 fin->fin_rev = 0; | 215 fr_ip_t *fi = &fin->fin_fi; 216 struct optlist *op; 217 u_char *s, opt; 218 tcphdr_t *tcp; 219 220 fin->fin_rev = 0; |
221 fin->fin_dp = NULL; |
|
210 fin->fin_fr = NULL; 211 fin->fin_tcpf = 0; 212 fin->fin_data[0] = 0; 213 fin->fin_data[1] = 0; 214 fin->fin_rule = -1; 215 fin->fin_group = -1; 216 fin->fin_icode = ipl_unreach; 217 v = fin->fin_v; 218 fi->fi_v = v; 219 fin->fin_hlen = hlen; 220 if (v == 4) { 221 fin->fin_id = ip->ip_id; 222 fi->fi_tos = ip->ip_tos; | 222 fin->fin_fr = NULL; 223 fin->fin_tcpf = 0; 224 fin->fin_data[0] = 0; 225 fin->fin_data[1] = 0; 226 fin->fin_rule = -1; 227 fin->fin_group = -1; 228 fin->fin_icode = ipl_unreach; 229 v = fin->fin_v; 230 fi->fi_v = v; 231 fin->fin_hlen = hlen; 232 if (v == 4) { 233 fin->fin_id = ip->ip_id; 234 fi->fi_tos = ip->ip_tos; |
235#if (OpenBSD >= 200311) && defined(_KERNEL) 236 ip->ip_off = ntohs(ip->ip_off); 237#endif |
|
223 off = (ip->ip_off & IP_OFFMASK); | 238 off = (ip->ip_off & IP_OFFMASK); |
224 tcp = (tcphdr_t *)((char *)ip + hlen); | |
225 (*(((u_short *)fi) + 1)) = (*(((u_short *)ip) + 4)); 226 fi->fi_src.i6[1] = 0; 227 fi->fi_src.i6[2] = 0; 228 fi->fi_src.i6[3] = 0; 229 fi->fi_dst.i6[1] = 0; 230 fi->fi_dst.i6[2] = 0; 231 fi->fi_dst.i6[3] = 0; 232 fi->fi_saddr = ip->ip_src.s_addr; 233 fi->fi_daddr = ip->ip_dst.s_addr; 234 p = ip->ip_p; 235 fi->fi_fl = (hlen > sizeof(ip_t)) ? FI_OPTIONS : 0; 236 if (ip->ip_off & (IP_MF|IP_OFFMASK)) 237 fi->fi_fl |= FI_FRAG; | 239 (*(((u_short *)fi) + 1)) = (*(((u_short *)ip) + 4)); 240 fi->fi_src.i6[1] = 0; 241 fi->fi_src.i6[2] = 0; 242 fi->fi_src.i6[3] = 0; 243 fi->fi_dst.i6[1] = 0; 244 fi->fi_dst.i6[2] = 0; 245 fi->fi_dst.i6[3] = 0; 246 fi->fi_saddr = ip->ip_src.s_addr; 247 fi->fi_daddr = ip->ip_dst.s_addr; 248 p = ip->ip_p; 249 fi->fi_fl = (hlen > sizeof(ip_t)) ? FI_OPTIONS : 0; 250 if (ip->ip_off & (IP_MF|IP_OFFMASK)) 251 fi->fi_fl |= FI_FRAG; |
252#if (OpenBSD >= 200311) && defined(_KERNEL) 253 ip->ip_len = ntohs(ip->ip_len); 254#endif |
|
238 plen = ip->ip_len; 239 fin->fin_dlen = plen - hlen; 240 } 241#ifdef USE_INET6 242 else if (v == 6) { 243 ip6_t *ip6 = (ip6_t *)ip; 244 245 off = 0; 246 p = ip6->ip6_nxt; 247 fi->fi_p = p; 248 fi->fi_ttl = ip6->ip6_hlim; | 255 plen = ip->ip_len; 256 fin->fin_dlen = plen - hlen; 257 } 258#ifdef USE_INET6 259 else if (v == 6) { 260 ip6_t *ip6 = (ip6_t *)ip; 261 262 off = 0; 263 p = ip6->ip6_nxt; 264 fi->fi_p = p; 265 fi->fi_ttl = ip6->ip6_hlim; |
249 tcp = (tcphdr_t *)(ip6 + 1); | |
250 fi->fi_src.in6 = ip6->ip6_src; 251 fi->fi_dst.in6 = ip6->ip6_dst; 252 fin->fin_id = (u_short)(ip6->ip6_flow & 0xffff); 253 fi->fi_tos = 0; 254 fi->fi_fl = 0; 255 plen = ntohs(ip6->ip6_plen); 256 fin->fin_dlen = plen; 257 plen += sizeof(*ip6); 258 } 259#endif 260 else | 266 fi->fi_src.in6 = ip6->ip6_src; 267 fi->fi_dst.in6 = ip6->ip6_dst; 268 fin->fin_id = (u_short)(ip6->ip6_flow & 0xffff); 269 fi->fi_tos = 0; 270 fi->fi_fl = 0; 271 plen = ntohs(ip6->ip6_plen); 272 fin->fin_dlen = plen; 273 plen += sizeof(*ip6); 274 } 275#endif 276 else |
261 return; | 277 return -1; |
262 263 fin->fin_off = off; 264 fin->fin_plen = plen; | 278 279 fin->fin_off = off; 280 fin->fin_plen = plen; |
265 fin->fin_dp = (char *)tcp; | 281 tcp = (tcphdr_t *)((char *)ip + hlen); |
266 fin->fin_misc = 0; 267 off <<= 3; 268 | 282 fin->fin_misc = 0; 283 off <<= 3; 284 |
285 /* 286 * For both ICMPV6 & ICMP, we attempt to pullup the entire packet into 287 * a single buffer for recognised error return packets. Why? Because 288 * the entire data section of the ICMP payload is considered to be of 289 * significance and maybe required in NAT/state processing, so rather 290 * than be careful later, attempt to get it all in one buffeer first. 291 * For TCP we just make sure the _entire_ TCP header is in the first 292 * buffer for convienience. 293 */ |
|
269 switch (p) 270 { 271#ifdef USE_INET6 272 case IPPROTO_ICMPV6 : 273 { 274 int minicmpsz = sizeof(struct icmp6_hdr); 275 struct icmp6_hdr *icmp6; 276 | 294 switch (p) 295 { 296#ifdef USE_INET6 297 case IPPROTO_ICMPV6 : 298 { 299 int minicmpsz = sizeof(struct icmp6_hdr); 300 struct icmp6_hdr *icmp6; 301 |
277 if (fin->fin_dlen > 1) { | 302 if (!(fin->fin_fl & FI_SHORT) && (fin->fin_dlen > 1)) { |
278 fin->fin_data[0] = *(u_short *)tcp; 279 280 icmp6 = (struct icmp6_hdr *)tcp; 281 282 switch (icmp6->icmp6_type) 283 { 284 case ICMP6_ECHO_REPLY : 285 case ICMP6_ECHO_REQUEST : 286 minicmpsz = ICMP6_MINLEN; 287 break; 288 case ICMP6_DST_UNREACH : 289 case ICMP6_PACKET_TOO_BIG : 290 case ICMP6_TIME_EXCEEDED : 291 case ICMP6_PARAM_PROB : | 303 fin->fin_data[0] = *(u_short *)tcp; 304 305 icmp6 = (struct icmp6_hdr *)tcp; 306 307 switch (icmp6->icmp6_type) 308 { 309 case ICMP6_ECHO_REPLY : 310 case ICMP6_ECHO_REQUEST : 311 minicmpsz = ICMP6_MINLEN; 312 break; 313 case ICMP6_DST_UNREACH : 314 case ICMP6_PACKET_TOO_BIG : 315 case ICMP6_TIME_EXCEEDED : 316 case ICMP6_PARAM_PROB : |
317# if defined(KERNEL) && !defined(__sgi) 318 if ((m != NULL) && (M_BLEN(m) < plen)) { 319 ip = ipf_pullup(m, fin, plen, ip); 320 if (ip == NULL) 321 return -1; 322 tcp = (tcphdr_t *)((char *)ip + hlen); 323 } 324# endif /* KERNEL && !__sgi */ |
|
292 minicmpsz = ICMP6ERR_IPICMPHLEN; 293 break; 294 default : 295 break; 296 } 297 } 298 | 325 minicmpsz = ICMP6ERR_IPICMPHLEN; 326 break; 327 default : 328 break; 329 } 330 } 331 |
299 if (!(plen >= minicmpsz)) | 332 if (!(fin->fin_dlen >= minicmpsz)) |
300 fi->fi_fl |= FI_SHORT; 301 302 break; 303 } | 333 fi->fi_fl |= FI_SHORT; 334 335 break; 336 } |
304#endif | 337#endif /* USE_INET6 */ 338 |
305 case IPPROTO_ICMP : 306 { 307 int minicmpsz = sizeof(struct icmp); 308 icmphdr_t *icmp; 309 | 339 case IPPROTO_ICMP : 340 { 341 int minicmpsz = sizeof(struct icmp); 342 icmphdr_t *icmp; 343 |
310 if (!off && (fin->fin_dlen > 1)) { | 344 if (!off && (fin->fin_dlen > 1) && !(fin->fin_fl & FI_SHORT)) { |
311 fin->fin_data[0] = *(u_short *)tcp; 312 313 icmp = (icmphdr_t *)tcp; 314 | 345 fin->fin_data[0] = *(u_short *)tcp; 346 347 icmp = (icmphdr_t *)tcp; 348 |
349 /* 350 * Minimum ICMP packet is type(1) code(1) cksum(2) 351 * plus 4 bytes following, totalling 8 bytes. 352 */ |
|
315 switch (icmp->icmp_type) 316 { 317 case ICMP_ECHOREPLY : 318 case ICMP_ECHO : 319 /* Router discovery messages - RFC 1256 */ 320 case ICMP_ROUTERADVERT : 321 case ICMP_ROUTERSOLICIT : 322 minicmpsz = ICMP_MINLEN; 323 break; 324 /* 325 * type(1) + code(1) + cksum(2) + id(2) seq(2) + 326 * 3*timestamp(3*4) 327 */ 328 case ICMP_TSTAMP : 329 case ICMP_TSTAMPREPLY : | 353 switch (icmp->icmp_type) 354 { 355 case ICMP_ECHOREPLY : 356 case ICMP_ECHO : 357 /* Router discovery messages - RFC 1256 */ 358 case ICMP_ROUTERADVERT : 359 case ICMP_ROUTERSOLICIT : 360 minicmpsz = ICMP_MINLEN; 361 break; 362 /* 363 * type(1) + code(1) + cksum(2) + id(2) seq(2) + 364 * 3*timestamp(3*4) 365 */ 366 case ICMP_TSTAMP : 367 case ICMP_TSTAMPREPLY : |
330 minicmpsz = 20; | 368 minicmpsz = ICMP_MINLEN + 12; |
331 break; 332 /* 333 * type(1) + code(1) + cksum(2) + id(2) seq(2) + 334 * mask(4) 335 */ 336 case ICMP_MASKREQ : 337 case ICMP_MASKREPLY : | 369 break; 370 /* 371 * type(1) + code(1) + cksum(2) + id(2) seq(2) + 372 * mask(4) 373 */ 374 case ICMP_MASKREQ : 375 case ICMP_MASKREPLY : |
338 minicmpsz = 12; | 376 minicmpsz = ICMP_MINLEN + 4; |
339 break; | 377 break; |
378 /* 379 * type(1) + code(1) + cksum(2) + arg(4) ip(20+) 380 */ 381 case ICMP_UNREACH : 382 case ICMP_SOURCEQUENCH : 383 case ICMP_REDIRECT : 384 case ICMP_TIMXCEED : 385 case ICMP_PARAMPROB : 386#if defined(KERNEL) && !defined(__sgi) 387 if ((m != NULL) && (M_BLEN(m) < plen)) { 388 ip = ipf_pullup(m, fin, plen, ip); 389 if (ip == NULL) 390 return -1; 391 tcp = (tcphdr_t *)((char *)ip + hlen); 392 } 393#endif /* KERNEL && !__sgi */ 394 minicmpsz = ICMPERR_MINPKTLEN - sizeof(ip_t); 395 break; |
|
340 default : | 396 default : |
397 minicmpsz = ICMP_MINLEN; |
|
341 break; 342 } 343 } 344 345 if ((!(plen >= hlen + minicmpsz) && !off) || 346 (off && off < sizeof(struct icmp))) 347 fi->fi_fl |= FI_SHORT; | 398 break; 399 } 400 } 401 402 if ((!(plen >= hlen + minicmpsz) && !off) || 403 (off && off < sizeof(struct icmp))) 404 fi->fi_fl |= FI_SHORT; |
348 | |
349 break; 350 } | 405 break; 406 } |
407 |
|
351 case IPPROTO_TCP : 352 fi->fi_fl |= FI_TCPUDP; 353#ifdef USE_INET6 354 if (v == 6) { 355 if (plen < sizeof(struct tcphdr)) 356 fi->fi_fl |= FI_SHORT; 357 } else 358#endif 359 if (v == 4) { 360 if ((!IPMINLEN(ip, tcphdr) && !off) || 361 (off && off < sizeof(struct tcphdr))) 362 fi->fi_fl |= FI_SHORT; 363 } | 408 case IPPROTO_TCP : 409 fi->fi_fl |= FI_TCPUDP; 410#ifdef USE_INET6 411 if (v == 6) { 412 if (plen < sizeof(struct tcphdr)) 413 fi->fi_fl |= FI_SHORT; 414 } else 415#endif 416 if (v == 4) { 417 if ((!IPMINLEN(ip, tcphdr) && !off) || 418 (off && off < sizeof(struct tcphdr))) 419 fi->fi_fl |= FI_SHORT; 420 } |
421 422#if defined(KERNEL) && !defined(__sgi) 423 if (!off && !(fi->fi_fl & FI_SHORT)) { 424 int tlen = hlen + (tcp->th_off << 2); 425 426 if ((m != NULL) && (M_BLEN(m) < tlen)) { 427 ip = ipf_pullup(m, fin, tlen, ip); 428 if (ip == NULL) 429 return -1; 430 tcp = (tcphdr_t *)((char *)ip + hlen); 431 } 432 } 433#endif /* _KERNEL && !_sgi */ 434 |
|
364 if (!(fi->fi_fl & FI_SHORT) && !off) 365 fin->fin_tcpf = tcp->th_flags; 366 goto getports; 367 case IPPROTO_UDP : 368 fi->fi_fl |= FI_TCPUDP; 369#ifdef USE_INET6 370 if (v == 6) { 371 if (plen < sizeof(struct udphdr)) --- 23 unchanged lines hidden (view full) --- 395 (off && off < 8)) 396 fi->fi_fl |= FI_SHORT; 397 } 398 break; 399 default : 400 break; 401 } 402 | 435 if (!(fi->fi_fl & FI_SHORT) && !off) 436 fin->fin_tcpf = tcp->th_flags; 437 goto getports; 438 case IPPROTO_UDP : 439 fi->fi_fl |= FI_TCPUDP; 440#ifdef USE_INET6 441 if (v == 6) { 442 if (plen < sizeof(struct udphdr)) --- 23 unchanged lines hidden (view full) --- 466 (off && off < 8)) 467 fi->fi_fl |= FI_SHORT; 468 } 469 break; 470 default : 471 break; 472 } 473 |
474 fin->fin_dp = (char *)tcp; 475 |
|
403#ifdef USE_INET6 404 if (v == 6) { 405 fi->fi_optmsk = 0; 406 fi->fi_secmsk = 0; 407 fi->fi_auth = 0; | 476#ifdef USE_INET6 477 if (v == 6) { 478 fi->fi_optmsk = 0; 479 fi->fi_secmsk = 0; 480 fi->fi_auth = 0; |
408 return; | 481 return 0; |
409 } 410#endif 411 412 for (s = (u_char *)(ip + 1), hlen -= (int)sizeof(*ip); hlen > 0; ) { 413 opt = *s; 414 if (opt == '\0') 415 break; 416 else if (opt == IPOPT_NOP) --- 40 unchanged lines hidden (view full) --- 457 hlen -= ol; 458 s += ol; 459 } 460 if (auth && !(auth & 0x0100)) 461 auth &= 0xff00; 462 fi->fi_optmsk = optmsk; 463 fi->fi_secmsk = secmsk; 464 fi->fi_auth = auth; | 482 } 483#endif 484 485 for (s = (u_char *)(ip + 1), hlen -= (int)sizeof(*ip); hlen > 0; ) { 486 opt = *s; 487 if (opt == '\0') 488 break; 489 else if (opt == IPOPT_NOP) --- 40 unchanged lines hidden (view full) --- 530 hlen -= ol; 531 s += ol; 532 } 533 if (auth && !(auth & 0x0100)) 534 auth &= 0xff00; 535 fi->fi_optmsk = optmsk; 536 fi->fi_secmsk = secmsk; 537 fi->fi_auth = auth; |
538 return 0; |
|
465} 466 467 468/* 469 * check an IP packet for TCP/UDP characteristics such as ports and flags. 470 */ 471int fr_tcpudpchk(ft, fin) 472frtuc_t *ft; --- 271 unchanged lines hidden (view full) --- 744 ATOMIC_INCL(frstats[fin->fin_out].fr_skip); 745 } 746 ATOMIC_INCL(frstats[fin->fin_out].fr_pkl); 747 logged = 1; 748 } 749#endif /* IPFILTER_LOG */ 750 ATOMIC_INCL(fr->fr_hits); 751 if (passt & FR_ACCOUNT) | 539} 540 541 542/* 543 * check an IP packet for TCP/UDP characteristics such as ports and flags. 544 */ 545int fr_tcpudpchk(ft, fin) 546frtuc_t *ft; --- 271 unchanged lines hidden (view full) --- 818 ATOMIC_INCL(frstats[fin->fin_out].fr_skip); 819 } 820 ATOMIC_INCL(frstats[fin->fin_out].fr_pkl); 821 logged = 1; 822 } 823#endif /* IPFILTER_LOG */ 824 ATOMIC_INCL(fr->fr_hits); 825 if (passt & FR_ACCOUNT) |
752 fr->fr_bytes += (U_QUAD_T)ip->ip_len; | 826 fr->fr_bytes += (U_QUAD_T)fin->fin_plen; |
753 else 754 fin->fin_icode = fr->fr_icode; 755 fin->fin_rule = rulen; 756 fin->fin_group = fr->fr_group; 757 if (fr->fr_grp != NULL) { 758 fin->fin_fr = fr->fr_grp; 759 passt = fr_scanlist(passt, ip, fin, m); 760 if (fin->fin_fr == NULL) { --- 46 unchanged lines hidden (view full) --- 807#if !SOLARIS || !defined(_KERNEL) 808 register mb_t *m = *mp; 809#endif 810 811#ifdef _KERNEL 812 int p, len, drop = 0, logit = 0; 813 mb_t *mc = NULL; 814# if !defined(__SVR4) && !defined(__svr4__) | 827 else 828 fin->fin_icode = fr->fr_icode; 829 fin->fin_rule = rulen; 830 fin->fin_group = fr->fr_group; 831 if (fr->fr_grp != NULL) { 832 fin->fin_fr = fr->fr_grp; 833 passt = fr_scanlist(passt, ip, fin, m); 834 if (fin->fin_fr == NULL) { --- 46 unchanged lines hidden (view full) --- 881#if !SOLARIS || !defined(_KERNEL) 882 register mb_t *m = *mp; 883#endif 884 885#ifdef _KERNEL 886 int p, len, drop = 0, logit = 0; 887 mb_t *mc = NULL; 888# if !defined(__SVR4) && !defined(__svr4__) |
889 /* 890 * We don't do this section for Solaris because fr_precheck() does a 891 * pullupmsg() instead, effectively achieving the same result as here 892 * so no need to duplicate it. 893 */ |
|
815# ifdef __sgi 816 char hbuf[128]; 817# endif 818 int up; 819 | 894# ifdef __sgi 895 char hbuf[128]; 896# endif 897 int up; 898 |
820# if !SOLARIS && !defined(NETBSD_PF) && \ | 899# if !defined(NETBSD_PF) && \ |
821 ((defined(__FreeBSD__) && (__FreeBSD_version < 500011)) || \ 822 defined(__OpenBSD__) || defined(_BSDI_VERSION)) 823 if (fr_checkp != fr_check && fr_running > 0) { 824 static int counter = 0; 825 826 if (counter == 0) { 827 printf("WARNING: fr_checkp corrupt: value %lx\n", 828 (u_long)fr_checkp); --- 21 unchanged lines hidden (view full) --- 850 * disable delayed checksums. 851 */ 852 if ((out != 0) && (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA)) { 853 in_delayed_cksum(m); 854 m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; 855 } 856# endif /* CSUM_DELAY_DATA */ 857 | 900 ((defined(__FreeBSD__) && (__FreeBSD_version < 500011)) || \ 901 defined(__OpenBSD__) || defined(_BSDI_VERSION)) 902 if (fr_checkp != fr_check && fr_running > 0) { 903 static int counter = 0; 904 905 if (counter == 0) { 906 printf("WARNING: fr_checkp corrupt: value %lx\n", 907 (u_long)fr_checkp); --- 21 unchanged lines hidden (view full) --- 929 * disable delayed checksums. 930 */ 931 if ((out != 0) && (m->m_pkthdr.csum_flags & CSUM_DELAY_DATA)) { 932 in_delayed_cksum(m); 933 m->m_pkthdr.csum_flags &= ~CSUM_DELAY_DATA; 934 } 935# endif /* CSUM_DELAY_DATA */ 936 |
858# ifdef USE_INET6 | 937# ifdef USE_INET6 |
859 if (v == 6) { 860 len = ntohs(((ip6_t*)ip)->ip6_plen); 861 if (!len) 862 return -1; /* potential jumbo gram */ 863 len += sizeof(ip6_t); 864 p = ((ip6_t *)ip)->ip6_nxt; 865 } else | 938 if (v == 6) { 939 len = ntohs(((ip6_t*)ip)->ip6_plen); 940 if (!len) 941 return -1; /* potential jumbo gram */ 942 len += sizeof(ip6_t); 943 p = ((ip6_t *)ip)->ip6_nxt; 944 } else |
866# endif | 945# endif |
867 { 868 p = ip->ip_p; 869 len = ip->ip_len; 870 } 871 | 946 { 947 p = ip->ip_p; 948 len = ip->ip_len; 949 } 950 |
951 fin->fin_mp = mp; 952 fin->fin_out = out; 953 |
|
872 if ((p == IPPROTO_TCP || p == IPPROTO_UDP || 873 (v == 4 && p == IPPROTO_ICMP) | 954 if ((p == IPPROTO_TCP || p == IPPROTO_UDP || 955 (v == 4 && p == IPPROTO_ICMP) |
874# ifdef USE_INET6 | 956# ifdef USE_INET6 |
875 || (v == 6 && p == IPPROTO_ICMPV6) | 957 || (v == 6 && p == IPPROTO_ICMPV6) |
876# endif | 958# endif |
877 )) { 878 int plen = 0; 879 880 if ((v == 6) || (ip->ip_off & IP_OFFMASK) == 0) 881 switch(p) 882 { 883 case IPPROTO_TCP: 884 plen = sizeof(tcphdr_t); 885 break; 886 case IPPROTO_UDP: 887 plen = sizeof(udphdr_t); 888 break; 889 /* 96 - enough for complete ICMP error IP header */ 890 case IPPROTO_ICMP: 891 plen = ICMPERR_MAXPKTLEN - sizeof(ip_t); 892 break; 893 case IPPROTO_ESP: 894 plen = 8; 895 break; | 959 )) { 960 int plen = 0; 961 962 if ((v == 6) || (ip->ip_off & IP_OFFMASK) == 0) 963 switch(p) 964 { 965 case IPPROTO_TCP: 966 plen = sizeof(tcphdr_t); 967 break; 968 case IPPROTO_UDP: 969 plen = sizeof(udphdr_t); 970 break; 971 /* 96 - enough for complete ICMP error IP header */ 972 case IPPROTO_ICMP: 973 plen = ICMPERR_MAXPKTLEN - sizeof(ip_t); 974 break; 975 case IPPROTO_ESP: 976 plen = 8; 977 break; |
896# ifdef USE_INET6 | 978# ifdef USE_INET6 |
897 case IPPROTO_ICMPV6 : 898 /* 899 * XXX does not take intermediate header 900 * into account 901 */ 902 plen = ICMP6ERR_MINPKTLEN + 8 - sizeof(ip6_t); 903 break; | 979 case IPPROTO_ICMPV6 : 980 /* 981 * XXX does not take intermediate header 982 * into account 983 */ 984 plen = ICMP6ERR_MINPKTLEN + 8 - sizeof(ip6_t); 985 break; |
904# endif | 986# endif |
905 } | 987 } |
988 if ((plen > 0) && (len < hlen + plen)) 989 fin->fin_fl |= FI_SHORT; |
|
906 up = MIN(hlen + plen, len); 907 908 if (up > m->m_len) { 909# ifdef __sgi 910 /* Under IRIX, avoid m_pullup as it makes ping <hostname> panic */ 911 if ((up > sizeof(hbuf)) || (m_length(m) < up)) { 912 ATOMIC_INCL(frstats[out].fr_pull[1]); 913 return -1; 914 } 915 m_copydata(m, 0, up, hbuf); 916 ATOMIC_INCL(frstats[out].fr_pull[0]); 917 ip = (ip_t *)hbuf; 918# else /* __ sgi */ 919# ifndef linux | 990 up = MIN(hlen + plen, len); 991 992 if (up > m->m_len) { 993# ifdef __sgi 994 /* Under IRIX, avoid m_pullup as it makes ping <hostname> panic */ 995 if ((up > sizeof(hbuf)) || (m_length(m) < up)) { 996 ATOMIC_INCL(frstats[out].fr_pull[1]); 997 return -1; 998 } 999 m_copydata(m, 0, up, hbuf); 1000 ATOMIC_INCL(frstats[out].fr_pull[0]); 1001 ip = (ip_t *)hbuf; 1002# else /* __ sgi */ 1003# ifndef linux |
920 if ((*mp = m_pullup(m, up)) == 0) { 921 ATOMIC_INCL(frstats[out].fr_pull[1]); | 1004 /* 1005 * Having determined that we need to pullup some data, 1006 * try to bring as much of the packet up into a single 1007 * buffer with the first pullup. This hopefully means 1008 * less need for doing futher pullups. Not needed for 1009 * Solaris because fr_precheck() does it anyway. 1010 * 1011 * The main potential for trouble here is if MLEN/MHLEN 1012 * become quite small, lets say < 64 bytes...but if 1013 * that did happen, BSD networking as a whole would be 1014 * slow/inefficient. 1015 */ 1016# ifdef MHLEN 1017 /* 1018 * Assume that M_PKTHDR is set and just work with what 1019 * is left rather than check.. Should not make any 1020 * real difference, anyway. 1021 */ 1022 if ((MHLEN > up) && (len > up)) 1023 up = MIN(len, MHLEN); 1024# else 1025 if ((MLEN > up) && (len > up)) 1026 up = MIN(len, MLEN); 1027# endif 1028 ip = ipf_pullup(m, fin, up, ip); 1029 if (ip == NULL) |
922 return -1; | 1030 return -1; |
923 } else { 924 ATOMIC_INCL(frstats[out].fr_pull[0]); 925 m = *mp; 926 ip = mtod(m, ip_t *); 927 } | 1031 m = *mp; |
928# endif /* !linux */ 929# endif /* __sgi */ 930 } else 931 up = 0; 932 } else 933 up = 0; 934# endif /* !defined(__SVR4) && !defined(__svr4__) */ 935# if SOLARIS 936 mb_t *m = qif->qf_m; 937 938 if ((u_int)ip & 0x3) 939 return 2; | 1032# endif /* !linux */ 1033# endif /* __sgi */ 1034 } else 1035 up = 0; 1036 } else 1037 up = 0; 1038# endif /* !defined(__SVR4) && !defined(__svr4__) */ 1039# if SOLARIS 1040 mb_t *m = qif->qf_m; 1041 1042 if ((u_int)ip & 0x3) 1043 return 2; |
1044 fin->fin_mp = mp; 1045 fin->fin_out = out; |
|
940 fin->fin_qfm = m; 941 fin->fin_qif = qif; 942# endif | 1046 fin->fin_qfm = m; 1047 fin->fin_qif = qif; 1048# endif |
1049#else 1050 fin->fin_mp = mp; 1051 fin->fin_out = out; |
|
943#endif /* _KERNEL */ 944 945#ifndef __FreeBSD__ 946 /* 947 * Be careful here: ip_id is in network byte order when called 948 * from ip_output() 949 */ 950 if ((out) && (v == 4)) 951 ip->ip_id = ntohs(ip->ip_id); 952#endif 953 954 changed = 0; | 1052#endif /* _KERNEL */ 1053 1054#ifndef __FreeBSD__ 1055 /* 1056 * Be careful here: ip_id is in network byte order when called 1057 * from ip_output() 1058 */ 1059 if ((out) && (v == 4)) 1060 ip->ip_id = ntohs(ip->ip_id); 1061#endif 1062 1063 changed = 0; |
955 fin->fin_ifp = ifp; | |
956 fin->fin_v = v; | 1064 fin->fin_v = v; |
957 fin->fin_out = out; 958 fin->fin_mp = mp; 959 fr_makefrip(hlen, ip, fin); | 1065 fin->fin_ifp = ifp; 1066 if (fr_makefrip(hlen, ip, fin) == -1) 1067 return -1; |
960 961#ifdef _KERNEL 962# ifdef USE_INET6 963 if (v == 6) { 964 ATOMIC_INCL(frstats[0].fr_ipv6[out]); 965 if (((ip6_t *)ip)->ip6_hlim < fr_minttl) { 966 ATOMIC_INCL(frstats[0].fr_badttl); 967 if (fr_minttllog & 1) --- 147 unchanged lines hidden (view full) --- 1115 } 1116 } else { 1117 ATOMIC_INCL(frstats[out].fr_cfr); 1118 } 1119 } 1120 if (pass & FR_KEEPSTATE) { 1121 if (fr_addstate(ip, fin, NULL, 0) == NULL) { 1122 ATOMIC_INCL(frstats[out].fr_bads); | 1068 1069#ifdef _KERNEL 1070# ifdef USE_INET6 1071 if (v == 6) { 1072 ATOMIC_INCL(frstats[0].fr_ipv6[out]); 1073 if (((ip6_t *)ip)->ip6_hlim < fr_minttl) { 1074 ATOMIC_INCL(frstats[0].fr_badttl); 1075 if (fr_minttllog & 1) --- 147 unchanged lines hidden (view full) --- 1223 } 1224 } else { 1225 ATOMIC_INCL(frstats[out].fr_cfr); 1226 } 1227 } 1228 if (pass & FR_KEEPSTATE) { 1229 if (fr_addstate(ip, fin, NULL, 0) == NULL) { 1230 ATOMIC_INCL(frstats[out].fr_bads); |
1231 if (pass & FR_PASS) { 1232 pass &= ~FR_PASS; 1233 pass |= FR_BLOCK; 1234 } |
|
1123 } else { 1124 ATOMIC_INCL(frstats[out].fr_ads); 1125 } 1126 } 1127 } else if (fr != NULL) { 1128 pass = fr->fr_flags; 1129 if (pass & FR_LOGFIRST) 1130 pass &= ~(FR_LOGFIRST|FR_LOG); --- 170 unchanged lines hidden (view full) --- 1301 if (((pass & FR_FASTROUTE) && !out) || 1302 (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) 1303 (void) ipfr_fastroute(ip, m, mp, fin, fdp); 1304 1305 if (mc != NULL) 1306 (void) ipfr_fastroute(ip, mc, &mc, fin, &fr->fr_dif); 1307 } 1308# endif /* !SOLARIS */ | 1235 } else { 1236 ATOMIC_INCL(frstats[out].fr_ads); 1237 } 1238 } 1239 } else if (fr != NULL) { 1240 pass = fr->fr_flags; 1241 if (pass & FR_LOGFIRST) 1242 pass &= ~(FR_LOGFIRST|FR_LOG); --- 170 unchanged lines hidden (view full) --- 1413 if (((pass & FR_FASTROUTE) && !out) || 1414 (fdp->fd_ifp && fdp->fd_ifp != (struct ifnet *)-1)) 1415 (void) ipfr_fastroute(ip, m, mp, fin, fdp); 1416 1417 if (mc != NULL) 1418 (void) ipfr_fastroute(ip, mc, &mc, fin, &fr->fr_dif); 1419 } 1420# endif /* !SOLARIS */ |
1421#if (OpenBSD >= 200311) && defined(_KERNEL) 1422 if (pass & FR_PASS) { 1423 ip->ip_len = htons(ip->ip_len); 1424 ip->ip_off = htons(ip->ip_off); 1425 } 1426#endif |
|
1309 return (pass & FR_PASS) ? 0 : error; 1310#else /* _KERNEL */ 1311 if (pass & FR_NOMATCH) 1312 return 1; 1313 if (pass & FR_PASS) 1314 return 0; 1315 if (pass & FR_AUTH) 1316 return -2; --- 81 unchanged lines hidden (view full) --- 1398# if BSD >= 199306 1399 m->m_data -= hlen; 1400# else 1401 m->m_off -= hlen; 1402# endif 1403 /* 1404 * Both sum and sum2 are partial sums, so combine them together. 1405 */ | 1427 return (pass & FR_PASS) ? 0 : error; 1428#else /* _KERNEL */ 1429 if (pass & FR_NOMATCH) 1430 return 1; 1431 if (pass & FR_PASS) 1432 return 0; 1433 if (pass & FR_AUTH) 1434 return -2; --- 81 unchanged lines hidden (view full) --- 1516# if BSD >= 199306 1517 m->m_data -= hlen; 1518# else 1519 m->m_off -= hlen; 1520# endif 1521 /* 1522 * Both sum and sum2 are partial sums, so combine them together. 1523 */ |
1406 sum = (sum & 0xffff) + (sum >> 16); 1407 sum = ~sum & 0xffff; 1408 sum2 += sum; 1409 sum2 = (sum2 & 0xffff) + (sum2 >> 16); | 1524 sum += ~sum2 & 0xffff; 1525 while (sum > 0xffff) 1526 sum = (sum & 0xffff) + (sum >> 16); 1527 sum2 = ~sum & 0xffff; |
1410# else /* defined(BSD) || defined(sun) */ 1411{ 1412 union { 1413 u_char c[2]; 1414 u_short s; 1415 } bytes; 1416 u_short len = ip->ip_len; 1417# if defined(__sgi) --- 120 unchanged lines hidden (view full) --- 1538 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 1539 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 1540 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 1541 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 1542 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 1543 * SUCH DAMAGE. 1544 * 1545 * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 | 1528# else /* defined(BSD) || defined(sun) */ 1529{ 1530 union { 1531 u_char c[2]; 1532 u_short s; 1533 } bytes; 1534 u_short len = ip->ip_len; 1535# if defined(__sgi) --- 120 unchanged lines hidden (view full) --- 1656 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 1657 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 1658 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 1659 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 1660 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 1661 * SUCH DAMAGE. 1662 * 1663 * @(#)uipc_mbuf.c 8.2 (Berkeley) 1/4/94 |
1546 * $Id: fil.c,v 2.35.2.67 2002/12/06 13:28:05 darrenr Exp $ | 1664 * $Id: fil.c,v 2.35.2.82 2004/06/20 10:27:47 darrenr Exp $ |
1547 */ 1548/* 1549 * Copy data from an mbuf chain starting "off" bytes from the beginning, 1550 * continuing for "len" bytes, into the indicated buffer. 1551 */ 1552void 1553m_copydata(m, off, len, cp) 1554 register mb_t *m; --- 415 unchanged lines hidden (view full) --- 1970# endif /* SOLARIS */ 1971 return 0; 1972} 1973 1974 1975static void frsynclist(fr) 1976register frentry_t *fr; 1977{ | 1665 */ 1666/* 1667 * Copy data from an mbuf chain starting "off" bytes from the beginning, 1668 * continuing for "len" bytes, into the indicated buffer. 1669 */ 1670void 1671m_copydata(m, off, len, cp) 1672 register mb_t *m; --- 415 unchanged lines hidden (view full) --- 2088# endif /* SOLARIS */ 2089 return 0; 2090} 2091 2092 2093static void frsynclist(fr) 2094register frentry_t *fr; 2095{ |
2096 frdest_t *fdp; 2097 int i; 2098 |
|
1978 for (; fr; fr = fr->fr_next) { | 2099 for (; fr; fr = fr->fr_next) { |
1979 if (fr->fr_ifa != NULL) { 1980 fr->fr_ifa = GETUNIT(fr->fr_ifname, fr->fr_ip.fi_v); 1981 if (fr->fr_ifa == NULL) 1982 fr->fr_ifa = (void *)-1; | 2100 for (i = 0; i < 4; i++) { 2101 if ((fr->fr_ifnames[i][1] == '\0') && 2102 ((fr->fr_ifnames[i][0] == '-') || 2103 (fr->fr_ifnames[i][0] == '*'))) { 2104 fr->fr_ifas[i] = NULL; 2105 } else if (*fr->fr_ifnames[i]) { 2106 fr->fr_ifas[i] = GETUNIT(fr->fr_ifnames[i], 2107 fr->fr_v); 2108 if (!fr->fr_ifas[i]) 2109 fr->fr_ifas[i] = (void *)-1; 2110 } |
1983 } | 2111 } |
2112 2113 fdp = &fr->fr_dif; 2114 fr->fr_flags &= ~FR_DUP; 2115 if (*fdp->fd_ifname) { 2116 fdp->fd_ifp = GETUNIT(fdp->fd_ifname, fr->fr_v); 2117 if (!fdp->fd_ifp) 2118 fdp->fd_ifp = (struct ifnet *)-1; 2119 else 2120 fr->fr_flags |= FR_DUP; 2121 } 2122 2123 fdp = &fr->fr_tif; 2124 if (*fdp->fd_ifname) { 2125 fdp->fd_ifp = GETUNIT(fdp->fd_ifname, fr->fr_v); 2126 if (!fdp->fd_ifp) 2127 fdp->fd_ifp = (struct ifnet *)-1; 2128 } 2129 |
|
1984 if (fr->fr_grp) 1985 frsynclist(fr->fr_grp); 1986 } 1987} 1988 1989 1990void frsync() 1991{ --- 16 unchanged lines hidden (view full) --- 2008 { 2009 ip_natsync(ifp); 2010 ip_statesync(ifp); 2011 } 2012# if defined(__FreeBSD_version) && (__FreeBSD_version >= 500043) 2013 IFNET_RUNLOCK(); 2014# endif 2015 ip_natsync((struct ifnet *)-1); | 2130 if (fr->fr_grp) 2131 frsynclist(fr->fr_grp); 2132 } 2133} 2134 2135 2136void frsync() 2137{ --- 16 unchanged lines hidden (view full) --- 2154 { 2155 ip_natsync(ifp); 2156 ip_statesync(ifp); 2157 } 2158# if defined(__FreeBSD_version) && (__FreeBSD_version >= 500043) 2159 IFNET_RUNLOCK(); 2160# endif 2161 ip_natsync((struct ifnet *)-1); |
2162# if defined(__FreeBSD_version) && (__FreeBSD_version >= 500043) 2163 IFNET_RUNLOCK(); 2164# endif |
|
2016# endif /* !SOLARIS */ 2017 2018 WRITE_ENTER(&ipf_mutex); 2019 frsynclist(ipacct[0][fr_active]); 2020 frsynclist(ipacct[1][fr_active]); 2021 frsynclist(ipfilter[0][fr_active]); 2022 frsynclist(ipfilter[1][fr_active]); 2023#ifdef USE_INET6 --- 212 unchanged lines hidden (view full) --- 2236mb_t *buf; 2237{ 2238 ip_t *ip; 2239 2240 ip = (ip_t *)buf; 2241 return ip->ip_len; 2242} 2243#endif | 2165# endif /* !SOLARIS */ 2166 2167 WRITE_ENTER(&ipf_mutex); 2168 frsynclist(ipacct[0][fr_active]); 2169 frsynclist(ipacct[1][fr_active]); 2170 frsynclist(ipfilter[0][fr_active]); 2171 frsynclist(ipfilter[1][fr_active]); 2172#ifdef USE_INET6 --- 212 unchanged lines hidden (view full) --- 2385mb_t *buf; 2386{ 2387 ip_t *ip; 2388 2389 ip = (ip_t *)buf; 2390 return ip->ip_len; 2391} 2392#endif |
2393 2394 2395#if defined(_KERNEL) && !defined(__sgi) 2396void *ipf_pullup(m, fin, len, ipin) 2397mb_t *m; 2398fr_info_t *fin; 2399int len; 2400void *ipin; 2401{ 2402# if SOLARIS 2403 qif_t *qf = fin->fin_qif; 2404# endif 2405 int out = fin->fin_out, dpoff, ipoff; 2406 char *ip; 2407 2408 if (m == NULL) 2409 return NULL; 2410 2411 ipoff = (char *)ipin - MTOD(m, char *); 2412 if (fin->fin_dp != NULL) 2413 dpoff = (char *)fin->fin_dp - (char *)ipin; 2414 else 2415 dpoff = 0; 2416 2417 if (M_BLEN(m) < len) { 2418# if SOLARIS 2419 qif_t *qf = fin->fin_qif; 2420 int inc = 0; 2421 2422 if (ipoff > 0) { 2423 if ((ipoff & 3) != 0) { 2424 inc = 4 - (ipoff & 3); 2425 if (m->b_rptr - inc >= m->b_datap->db_base) 2426 m->b_rptr -= inc; 2427 else 2428 inc = 0; 2429 } 2430 } 2431 if (!pullupmsg(m, len + ipoff + inc)) { 2432 ATOMIC_INCL(frstats[out].fr_pull[1]); 2433 return NULL; 2434 } 2435 m->b_rptr += inc; 2436 ATOMIC_INCL(frstats[out].fr_pull[0]); 2437 qf->qf_data = MTOD(m, char *) + ipoff; 2438# else 2439 m = m_pullup(m, len); 2440 *fin->fin_mp = m; 2441 if (m == NULL) { 2442 ATOMIC_INCL(frstats[out].fr_pull[1]); 2443 return NULL; 2444 } 2445 ATOMIC_INCL(frstats[out].fr_pull[0]); 2446# endif /* SOLARIS */ 2447 } 2448 ip = MTOD(m, char *) + ipoff; 2449 if (fin->fin_dp != NULL) 2450 fin->fin_dp = (char *)ip + dpoff; 2451 return ip; 2452} 2453#endif /* _KERNEL */ |
|