1 /* 2 * Copyright (C) 1993-2001, 2003 by Darren Reed. 3 * 4 * See the IPFILTER.LICENCE file for details on licencing. 5 * 6 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 7 * Use is subject to license terms. 8 */ 9 10 #if !defined(lint) 11 static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed"; 12 static const char rcsid[] = "@(#)$Id: ip_fil.c,v 2.133.2.9 2005/01/08 14:22:18 darrenr Exp $"; 13 #endif 14 15 #ifndef SOLARIS 16 #define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4))) 17 #endif 18 19 #include <sys/param.h> 20 #if defined(__FreeBSD__) && !defined(__FreeBSD_version) 21 # if defined(IPFILTER_LKM) 22 # ifndef __FreeBSD_cc_version 23 # include <osreldate.h> 24 # else 25 # if __FreeBSD_cc_version < 430000 26 # include <osreldate.h> 27 # endif 28 # endif 29 # endif 30 #endif 31 #include <sys/errno.h> 32 #if defined(__hpux) && (HPUXREV >= 1111) && !defined(_KERNEL) 33 # include <sys/kern_svcs.h> 34 #endif 35 #include <sys/types.h> 36 #define _KERNEL 37 #define KERNEL 38 #ifdef __OpenBSD__ 39 struct file; 40 #endif 41 #include <sys/uio.h> 42 #undef _KERNEL 43 #undef KERNEL 44 #include <sys/file.h> 45 #include <sys/ioctl.h> 46 #ifdef __sgi 47 # include <sys/ptimers.h> 48 #endif 49 #include <sys/time.h> 50 #if !SOLARIS 51 # if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000) 52 # include <sys/dirent.h> 53 # else 54 # include <sys/dir.h> 55 # endif 56 #else 57 # include <sys/filio.h> 58 #endif 59 #ifndef linux 60 # include <sys/protosw.h> 61 #endif 62 #include <sys/socket.h> 63 64 #include <stdio.h> 65 #include <string.h> 66 #include <stdlib.h> 67 #include <ctype.h> 68 #include <fcntl.h> 69 #include <sys/zone.h> 70 #include <arpa/inet.h> 71 72 #ifdef __hpux 73 # define _NET_ROUTE_INCLUDED 74 #endif 75 #include <net/if.h> 76 #ifdef sun 77 # include <net/af.h> 78 #endif 79 #if __FreeBSD_version >= 300000 80 # include <net/if_var.h> 81 #endif 82 #ifdef __sgi 83 #include <sys/debug.h> 84 # ifdef IFF_DRVRLOCK /* IRIX6 */ 85 #include <sys/hashing.h> 86 # endif 87 #endif 88 #if defined(__FreeBSD__) 89 # include "radix_ipf.h" 90 #endif 91 #include <net/route.h> 92 #include <netinet/in.h> 93 #if !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /* IRIX < 6 */ && \ 94 !defined(__hpux) && !defined(linux) 95 # include <netinet/in_var.h> 96 #endif 97 #include <netinet/in_systm.h> 98 #include <netinet/ip.h> 99 #if !defined(linux) 100 # include <netinet/ip_var.h> 101 #endif 102 #include <netinet/tcp.h> 103 #if defined(__osf__) 104 # include <netinet/tcp_timer.h> 105 #endif 106 #if defined(__osf__) || defined(__hpux) || defined(__sgi) 107 # include "radix_ipf_local.h" 108 # define _RADIX_H_ 109 #endif 110 #include <netinet/udp.h> 111 #include <netinet/tcpip.h> 112 #include <netinet/ip_icmp.h> 113 #include <unistd.h> 114 #include <syslog.h> 115 #ifdef __hpux 116 # undef _NET_ROUTE_INCLUDED 117 #endif 118 #include "netinet/ip_compat.h" 119 #include "netinet/ip_fil.h" 120 #include "netinet/ip_nat.h" 121 #include "netinet/ip_frag.h" 122 #include "netinet/ip_state.h" 123 #include "netinet/ip_proxy.h" 124 #include "netinet/ip_auth.h" 125 #ifdef IPFILTER_SYNC 126 #include "netinet/ip_sync.h" 127 #endif 128 #ifdef IPFILTER_SCAN 129 #include "netinet/ip_scan.h" 130 #endif 131 #include "netinet/ip_pool.h" 132 #ifdef IPFILTER_COMPILED 133 # include "netinet/ip_rules.h" 134 #endif 135 #include "netinet/ipf_stack.h" 136 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000) 137 # include <sys/malloc.h> 138 #endif 139 #ifdef __hpux 140 struct rtentry; 141 #endif 142 #include "md5.h" 143 144 145 #if !defined(__osf__) 146 extern struct protosw inetsw[]; 147 #endif 148 149 #include "ipt.h" 150 static struct ifnet **ifneta = NULL; 151 static int nifs = 0; 152 153 static int frzerostats __P((caddr_t, ipf_stack_t *ifs)); 154 static void fr_setifpaddr __P((struct ifnet *, char *)); 155 void init_ifp __P((void)); 156 #if defined(__sgi) && (IRIX < 60500) 157 static int no_output __P((struct ifnet *, struct mbuf *, 158 struct sockaddr *)); 159 static int write_output __P((struct ifnet *, struct mbuf *, 160 struct sockaddr *)); 161 #else 162 # if TRU64 >= 1885 163 static int no_output __P((struct ifnet *, struct mbuf *, 164 struct sockaddr *, struct rtentry *, char *)); 165 static int write_output __P((struct ifnet *, struct mbuf *, 166 struct sockaddr *, struct rtentry *, char *)); 167 # else 168 static int no_output __P((struct ifnet *, struct mbuf *, 169 struct sockaddr *, struct rtentry *)); 170 static int write_output __P((struct ifnet *, struct mbuf *, 171 struct sockaddr *, struct rtentry *)); 172 # endif 173 #endif 174 175 176 int iplattach(ifs) 177 ipf_stack_t *ifs; 178 { 179 ifs->ifs_fr_running = 1; 180 return 0; 181 } 182 183 184 int ipldetach(ifs) 185 ipf_stack_t *ifs; 186 { 187 ifs->ifs_fr_running = -1; 188 return 0; 189 } 190 191 192 static int frzerostats(data, ifs) 193 caddr_t data; 194 ipf_stack_t *ifs; 195 { 196 friostat_t fio; 197 int error; 198 199 fr_getstat(&fio, ifs); 200 error = copyoutptr(&fio, data, sizeof(fio)); 201 if (error) 202 return EFAULT; 203 204 bzero((char *)ifs->ifs_frstats, sizeof(*ifs->ifs_frstats) * 2); 205 206 return 0; 207 } 208 209 210 /* 211 * Filter ioctl interface. 212 */ 213 int iplioctl(dev, cmd, data, mode) 214 int dev; 215 ioctlcmd_t cmd; 216 caddr_t data; 217 int mode; 218 { 219 int error = 0, unit = 0, tmp, uid; 220 friostat_t fio; 221 ipf_stack_t *ifs; 222 extern ipf_stack_t *get_ifs(); 223 224 unit = dev; 225 uid = getuid(); 226 227 ifs = get_ifs(); 228 229 SPL_NET(s); 230 231 if (unit == IPL_LOGNAT) { 232 if (ifs->ifs_fr_running > 0) 233 error = fr_nat_ioctl(data, cmd, mode, uid, NULL, ifs); 234 else 235 error = EIO; 236 SPL_X(s); 237 return error; 238 } 239 if (unit == IPL_LOGSTATE) { 240 if (ifs->ifs_fr_running > 0) 241 error = fr_state_ioctl(data, cmd, mode, uid, NULL, ifs); 242 else 243 error = EIO; 244 SPL_X(s); 245 return error; 246 } 247 if (unit == IPL_LOGAUTH) { 248 if (ifs->ifs_fr_running > 0) { 249 if ((cmd == (ioctlcmd_t)SIOCADAFR) || 250 (cmd == (ioctlcmd_t)SIOCRMAFR)) { 251 if (!(mode & FWRITE)) { 252 error = EPERM; 253 } else { 254 error = frrequest(unit, cmd, data, 255 ifs->ifs_fr_active, 1, ifs); 256 } 257 } else { 258 error = fr_auth_ioctl(data, mode, cmd, uid, NULL, ifs); 259 } 260 } else 261 error = EIO; 262 SPL_X(s); 263 return error; 264 } 265 if (unit == IPL_LOGSYNC) { 266 #ifdef IPFILTER_SYNC 267 if (ifs->ifs_fr_running > 0) 268 error = fr_sync_ioctl(data, cmd, mode); 269 else 270 #endif 271 error = EIO; 272 SPL_X(s); 273 return error; 274 } 275 if (unit == IPL_LOGSCAN) { 276 #ifdef IPFILTER_SCAN 277 if (ifs->ifs_fr_running > 0) 278 error = fr_scan_ioctl(data, cmd, mode); 279 else 280 #endif 281 error = EIO; 282 SPL_X(s); 283 return error; 284 } 285 if (unit == IPL_LOGLOOKUP) { 286 if (ifs->ifs_fr_running > 0) 287 error = ip_lookup_ioctl(data, cmd, mode, uid, 288 NULL, ifs); 289 else 290 error = EIO; 291 SPL_X(s); 292 return error; 293 } 294 295 switch (cmd) 296 { 297 case FIONREAD : 298 #ifdef IPFILTER_LOG 299 error = COPYOUT(&ifs->ifs_iplused[IPL_LOGIPF], (caddr_t)data, 300 sizeof(ifs->ifs_iplused[IPL_LOGIPF])); 301 #endif 302 break; 303 case SIOCFRENB : 304 if (!(mode & FWRITE)) 305 error = EPERM; 306 else { 307 error = COPYIN(data, &tmp, sizeof(tmp)); 308 if (error) 309 break; 310 if (tmp) 311 error = iplattach(ifs); 312 else 313 error = ipldetach(ifs); 314 } 315 break; 316 case SIOCIPFSET : 317 if (!(mode & FWRITE)) { 318 error = EPERM; 319 break; 320 } 321 case SIOCIPFGETNEXT : 322 case SIOCIPFGET : 323 error = fr_ipftune(cmd, (void *)data, ifs); 324 break; 325 case SIOCSETFF : 326 if (!(mode & FWRITE)) 327 error = EPERM; 328 else 329 error = COPYIN(data, &ifs->ifs_fr_flags, 330 sizeof(ifs->ifs_fr_flags)); 331 break; 332 case SIOCGETFF : 333 error = COPYOUT(&ifs->ifs_fr_flags, data, 334 sizeof(ifs->ifs_fr_flags)); 335 break; 336 case SIOCFUNCL : 337 error = fr_resolvefunc(data); 338 break; 339 case SIOCINAFR : 340 case SIOCRMAFR : 341 case SIOCADAFR : 342 case SIOCZRLST : 343 if (!(mode & FWRITE)) 344 error = EPERM; 345 else 346 error = frrequest(unit, cmd, data, 347 ifs->ifs_fr_active, 1, ifs); 348 break; 349 case SIOCINIFR : 350 case SIOCRMIFR : 351 case SIOCADIFR : 352 if (!(mode & FWRITE)) 353 error = EPERM; 354 else 355 error = frrequest(unit, cmd, data, 356 1 - ifs->ifs_fr_active, 1, ifs); 357 break; 358 case SIOCSWAPA : 359 if (!(mode & FWRITE)) 360 error = EPERM; 361 else { 362 *(u_int *)data = ifs->ifs_fr_active; 363 ifs->ifs_fr_active = 1 - ifs->ifs_fr_active; 364 } 365 break; 366 case SIOCGETFS : 367 fr_getstat(&fio, ifs); 368 error = fr_outobj(data, &fio, IPFOBJ_IPFSTAT); 369 break; 370 case SIOCFRZST : 371 if (!(mode & FWRITE)) 372 error = EPERM; 373 else 374 error = frzerostats(data, ifs); 375 break; 376 case SIOCIPFFL : 377 if (!(mode & FWRITE)) 378 error = EPERM; 379 else { 380 error = COPYIN(data, &tmp, sizeof(tmp)); 381 if (!error) { 382 tmp = frflush(unit, 4, tmp, ifs); 383 error = COPYOUT(&tmp, data, sizeof(tmp)); 384 } 385 } 386 break; 387 #ifdef USE_INET6 388 case SIOCIPFL6 : 389 if (!(mode & FWRITE)) 390 error = EPERM; 391 else { 392 error = COPYIN(data, &tmp, sizeof(tmp)); 393 if (!error) { 394 tmp = frflush(unit, 6, tmp, ifs); 395 error = COPYOUT(&tmp, data, sizeof(tmp)); 396 } 397 } 398 break; 399 #endif 400 case SIOCSTLCK : 401 error = COPYIN(data, &tmp, sizeof(tmp)); 402 if (error == 0) { 403 ifs->ifs_fr_state_lock = tmp; 404 ifs->ifs_fr_nat_lock = tmp; 405 ifs->ifs_fr_frag_lock = tmp; 406 ifs->ifs_fr_auth_lock = tmp; 407 } else 408 error = EFAULT; 409 break; 410 #ifdef IPFILTER_LOG 411 case SIOCIPFFB : 412 if (!(mode & FWRITE)) 413 error = EPERM; 414 else 415 *(int *)data = ipflog_clear(unit, ifs); 416 break; 417 #endif /* IPFILTER_LOG */ 418 case SIOCGFRST : 419 error = fr_outobj(data, fr_fragstats(ifs), IPFOBJ_FRAGSTAT); 420 break; 421 case SIOCFRSYN : 422 if (!(mode & FWRITE)) 423 error = EPERM; 424 else { 425 frsync(IPFSYNC_RESYNC, IPFSYNC_RESYNC, NULL, NULL, ifs); 426 } 427 break; 428 default : 429 error = EINVAL; 430 break; 431 } 432 SPL_X(s); 433 return error; 434 } 435 436 437 void fr_forgetifp(ifp, ifs) 438 void *ifp; 439 ipf_stack_t *ifs; 440 { 441 register frentry_t *f; 442 443 WRITE_ENTER(&ifs->ifs_ipf_mutex); 444 for (f = ifs->ifs_ipacct[0][ifs->ifs_fr_active]; (f != NULL); 445 f = f->fr_next) 446 if (f->fr_ifa == ifp) 447 f->fr_ifa = (void *)-1; 448 for (f = ifs->ifs_ipacct[1][ifs->ifs_fr_active]; (f != NULL); 449 f = f->fr_next) 450 if (f->fr_ifa == ifp) 451 f->fr_ifa = (void *)-1; 452 for (f = ifs->ifs_ipfilter[0][ifs->ifs_fr_active]; (f != NULL); 453 f = f->fr_next) 454 if (f->fr_ifa == ifp) 455 f->fr_ifa = (void *)-1; 456 for (f = ifs->ifs_ipfilter[1][ifs->ifs_fr_active]; (f != NULL); 457 f = f->fr_next) 458 if (f->fr_ifa == ifp) 459 f->fr_ifa = (void *)-1; 460 #ifdef USE_INET6 461 for (f = ifs->ifs_ipacct6[0][ifs->ifs_fr_active]; (f != NULL); 462 f = f->fr_next) 463 if (f->fr_ifa == ifp) 464 f->fr_ifa = (void *)-1; 465 for (f = ifs->ifs_ipacct6[1][ifs->ifs_fr_active]; (f != NULL); 466 f = f->fr_next) 467 if (f->fr_ifa == ifp) 468 f->fr_ifa = (void *)-1; 469 for (f = ifs->ifs_ipfilter6[0][ifs->ifs_fr_active]; (f != NULL); 470 f = f->fr_next) 471 if (f->fr_ifa == ifp) 472 f->fr_ifa = (void *)-1; 473 for (f = ifs->ifs_ipfilter6[1][ifs->ifs_fr_active]; (f != NULL); 474 f = f->fr_next) 475 if (f->fr_ifa == ifp) 476 f->fr_ifa = (void *)-1; 477 #endif 478 RWLOCK_EXIT(&ifs->ifs_ipf_mutex); 479 fr_natifpsync(IPFSYNC_OLDIFP, 4, ifp, NULL, ifs); 480 fr_natifpsync(IPFSYNC_OLDIFP, 6, ifp, NULL, ifs); 481 } 482 483 484 void fr_resolvedest(fdp, v, ifs) 485 frdest_t *fdp; 486 int v; 487 ipf_stack_t *ifs; 488 { 489 fdp->fd_ifp = NULL; 490 491 if (*fdp->fd_ifname) { 492 fdp->fd_ifp = GETIFP(fdp->fd_ifname, v, ifs); 493 if (!fdp->fd_ifp) 494 fdp->fd_ifp = (struct ifnet *)-1; 495 } 496 } 497 498 499 #if defined(__sgi) && (IRIX < 60500) 500 static int no_output(ifp, m, s) 501 #else 502 # if TRU64 >= 1885 503 static int no_output (ifp, m, s, rt, cp) 504 char *cp; 505 # else 506 static int no_output(ifp, m, s, rt) 507 # endif 508 struct rtentry *rt; 509 #endif 510 struct ifnet *ifp; 511 struct mbuf *m; 512 struct sockaddr *s; 513 { 514 return 0; 515 } 516 517 518 #if defined(__sgi) && (IRIX < 60500) 519 static int write_output(ifp, m, s) 520 #else 521 # if TRU64 >= 1885 522 static int write_output (ifp, m, s, rt, cp) 523 char *cp; 524 # else 525 static int write_output(ifp, m, s, rt) 526 # endif 527 struct rtentry *rt; 528 #endif 529 struct ifnet *ifp; 530 struct mbuf *m; 531 struct sockaddr *s; 532 { 533 char fname[32]; 534 mb_t *mb; 535 ip_t *ip; 536 int fd; 537 538 mb = (mb_t *)m; 539 ip = MTOD(mb, ip_t *); 540 541 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ 542 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ 543 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) 544 sprintf(fname, "/tmp/%s", ifp->if_xname); 545 #else 546 sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit); 547 #endif 548 fd = open(fname, O_WRONLY|O_APPEND); 549 if (fd == -1) { 550 perror("open"); 551 return -1; 552 } 553 write(fd, (char *)ip, ntohs(ip->ip_len)); 554 close(fd); 555 return 0; 556 } 557 558 559 static void fr_setifpaddr(ifp, addr) 560 struct ifnet *ifp; 561 char *addr; 562 { 563 #ifdef __sgi 564 struct in_ifaddr *ifa; 565 #else 566 struct ifaddr *ifa; 567 #endif 568 569 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) 570 if (ifp->if_addrlist.tqh_first != NULL) 571 #else 572 # ifdef __sgi 573 if (ifp->in_ifaddr != NULL) 574 # else 575 if (ifp->if_addrlist != NULL) 576 # endif 577 #endif 578 return; 579 580 ifa = (struct ifaddr *)malloc(sizeof(*ifa)); 581 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) 582 ifp->if_addrlist.tqh_first = ifa; 583 #else 584 # ifdef __sgi 585 ifp->in_ifaddr = ifa; 586 # else 587 ifp->if_addrlist = ifa; 588 # endif 589 #endif 590 591 if (ifa != NULL) { 592 struct sockaddr_in *sin; 593 594 #ifdef __sgi 595 sin = (struct sockaddr_in *)&ifa->ia_addr; 596 #else 597 sin = (struct sockaddr_in *)&ifa->ifa_addr; 598 #endif 599 sin->sin_addr.s_addr = inet_addr(addr); 600 if (sin->sin_addr.s_addr == 0) 601 abort(); 602 } 603 } 604 605 /*ARGSUSED*/ 606 struct ifnet *get_unit(name, v, ifs) 607 char *name; 608 int v; 609 ipf_stack_t *ifs; 610 { 611 struct ifnet *ifp, **ifpp, **old_ifneta; 612 char *addr; 613 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ 614 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ 615 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) 616 617 if (name == NULL) 618 name = "anon0"; 619 620 addr = strchr(name, '='); 621 if (addr != NULL) 622 *addr++ = '\0'; 623 624 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { 625 if (!strcmp(name, ifp->if_xname)) { 626 if (addr != NULL) 627 fr_setifpaddr(ifp, addr); 628 return ifp; 629 } 630 } 631 #else 632 char *s, ifname[LIFNAMSIZ+1]; 633 634 if (name == NULL) 635 name = "anon0"; 636 637 addr = strchr(name, '='); 638 if (addr != NULL) 639 *addr++ = '\0'; 640 641 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { 642 COPYIFNAME(ifp, ifname, 0); 643 if (!strcmp(name, ifname)) { 644 if (addr != NULL) 645 fr_setifpaddr(ifp, addr); 646 return ifp; 647 } 648 } 649 #endif 650 651 if (!ifneta) { 652 ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2); 653 if (!ifneta) 654 return NULL; 655 ifneta[1] = NULL; 656 ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp)); 657 if (!ifneta[0]) { 658 free(ifneta); 659 return NULL; 660 } 661 nifs = 1; 662 } else { 663 old_ifneta = ifneta; 664 nifs++; 665 ifneta = (struct ifnet **)realloc(ifneta, 666 (nifs + 1) * sizeof(ifp)); 667 if (!ifneta) { 668 free(old_ifneta); 669 nifs = 0; 670 return NULL; 671 } 672 ifneta[nifs] = NULL; 673 ifneta[nifs - 1] = (struct ifnet *)malloc(sizeof(*ifp)); 674 if (!ifneta[nifs - 1]) { 675 nifs--; 676 return NULL; 677 } 678 } 679 ifp = ifneta[nifs - 1]; 680 681 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ 682 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ 683 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) 684 (void) strncpy(ifp->if_xname, name, sizeof(ifp->if_xname)); 685 #else 686 for (s = name; *s && !ISDIGIT(*s); s++) 687 ; 688 if (*s && ISDIGIT(*s)) { 689 ifp->if_unit = atoi(s); 690 ifp->if_name = (char *)malloc(s - name + 1); 691 if (ifp->if_name == NULL) { 692 /* 693 * XXX do it more elegantly: free up mem, 694 * return NULL 695 */ 696 perror("malloc"); 697 exit(1); 698 } 699 (void) strncpy(ifp->if_name, name, s - name); 700 ifp->if_name[s - name] = '\0'; 701 } else { 702 ifp->if_name = strdup(name); 703 ifp->if_unit = -1; 704 } 705 #endif 706 ifp->if_output = no_output; 707 708 if (addr != NULL) { 709 fr_setifpaddr(ifp, addr); 710 } 711 712 return ifp; 713 } 714 715 716 char *get_ifname(ifp) 717 struct ifnet *ifp; 718 { 719 static char ifname[LIFNAMSIZ]; 720 721 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(linux) || \ 722 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) 723 sprintf(ifname, "%s", ifp->if_xname); 724 #else 725 sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit); 726 #endif 727 return ifname; 728 } 729 730 731 732 void init_ifp() 733 { 734 struct ifnet *ifp, **ifpp; 735 char fname[32]; 736 int fd; 737 738 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ 739 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ 740 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) 741 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { 742 ifp->if_output = write_output; 743 sprintf(fname, "/tmp/%s", ifp->if_xname); 744 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600); 745 if (fd == -1) 746 perror("open"); 747 else 748 close(fd); 749 } 750 #else 751 752 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { 753 ifp->if_output = write_output; 754 sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit); 755 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600); 756 if (fd == -1) 757 perror("open"); 758 else 759 close(fd); 760 } 761 #endif 762 } 763 764 765 int fr_fastroute(m, mpp, fin, fdp) 766 mb_t *m, **mpp; 767 fr_info_t *fin; 768 frdest_t *fdp; 769 { 770 struct ifnet *ifp = fdp->fd_ifp; 771 ip_t *ip = fin->fin_ip; 772 773 if (!ifp) 774 return 0; /* no routing table out here */ 775 776 ip->ip_len = htons((u_short)ip->ip_len); 777 ip->ip_off = htons((u_short)(ip->ip_off | IP_MF)); 778 ip->ip_sum = 0; 779 #if defined(__sgi) && (IRIX < 60500) 780 (*ifp->if_output)(ifp, (void *)ip, NULL); 781 # if TRU64 >= 1885 782 (*ifp->if_output)(ifp, (void *)m, NULL, 0, 0); 783 # else 784 (*ifp->if_output)(ifp, (void *)m, NULL, 0); 785 # endif 786 #endif 787 return 0; 788 } 789 790 791 int fr_send_reset(fin) 792 fr_info_t *fin; 793 { 794 verbose("- TCP RST sent\n"); 795 return 0; 796 } 797 798 799 int fr_send_icmp_err(type, fin, dst) 800 int type; 801 fr_info_t *fin; 802 int dst; 803 { 804 verbose("- ICMP unreachable sent\n"); 805 return 0; 806 } 807 808 809 void frsync(command, version, nic, data, ifs) 810 int command, version; 811 void *nic; 812 char *data; 813 ipf_stack_t *ifs; 814 { 815 return; 816 } 817 818 819 void m_freem(m) 820 mb_t *m; 821 { 822 return; 823 } 824 825 826 void m_copydata(m, off, len, cp) 827 mb_t *m; 828 int off, len; 829 caddr_t cp; 830 { 831 bcopy((char *)m + off, cp, len); 832 } 833 834 835 int ipfuiomove(buf, len, rwflag, uio) 836 caddr_t buf; 837 int len, rwflag; 838 struct uio *uio; 839 { 840 int left, ioc, num, offset; 841 struct iovec *io; 842 char *start; 843 844 if (rwflag == UIO_READ) { 845 left = len; 846 ioc = 0; 847 848 offset = uio->uio_offset; 849 850 while ((left > 0) && (ioc < uio->uio_iovcnt)) { 851 io = uio->uio_iov + ioc; 852 num = io->iov_len; 853 if (num > left) 854 num = left; 855 start = (char *)io->iov_base + offset; 856 if (start > (char *)io->iov_base + io->iov_len) { 857 offset -= io->iov_len; 858 ioc++; 859 continue; 860 } 861 bcopy(buf, start, num); 862 uio->uio_resid -= num; 863 uio->uio_offset += num; 864 left -= num; 865 if (left > 0) 866 ioc++; 867 } 868 if (left > 0) 869 return EFAULT; 870 } 871 return 0; 872 } 873 874 875 u_32_t fr_newisn(fin) 876 fr_info_t *fin; 877 { 878 static int iss_seq_off = 0; 879 u_char hash[16]; 880 u_32_t newiss; 881 MD5_CTX ctx; 882 883 /* 884 * Compute the base value of the ISS. It is a hash 885 * of (saddr, sport, daddr, dport, secret). 886 */ 887 MD5Init(&ctx); 888 889 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src, 890 sizeof(fin->fin_fi.fi_src)); 891 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst, 892 sizeof(fin->fin_fi.fi_dst)); 893 MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat)); 894 895 /* MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); */ 896 897 MD5Final(hash, &ctx); 898 899 memcpy(&newiss, hash, sizeof(newiss)); 900 901 /* 902 * Now increment our "timer", and add it in to 903 * the computed value. 904 * 905 * XXX Use `addin'? 906 * XXX TCP_ISSINCR too large to use? 907 */ 908 iss_seq_off += 0x00010000; 909 newiss += iss_seq_off; 910 return newiss; 911 } 912 913 914 /* ------------------------------------------------------------------------ */ 915 /* Function: fr_nextipid */ 916 /* Returns: int - 0 == success, -1 == error (packet should be droppped) */ 917 /* Parameters: fin(I) - pointer to packet information */ 918 /* */ 919 /* Returns the next IPv4 ID to use for this packet. */ 920 /* ------------------------------------------------------------------------ */ 921 INLINE u_short fr_nextipid(fin) 922 fr_info_t *fin; 923 { 924 static u_short ipid = 0; 925 u_short id; 926 ipf_stack_t *ifs = fin->fin_ifs; 927 928 MUTEX_ENTER(&ifs->ifs_ipf_rw); 929 id = ipid++; 930 MUTEX_EXIT(&ifs->ifs_ipf_rw); 931 932 return id; 933 } 934 935 936 INLINE void fr_checkv4sum(fin) 937 fr_info_t *fin; 938 { 939 if (fr_checkl4sum(fin) == -1) 940 fin->fin_flx |= FI_BAD; 941 } 942 943 944 #ifdef USE_INET6 945 INLINE void fr_checkv6sum(fin) 946 fr_info_t *fin; 947 { 948 if (fr_checkl4sum(fin) == -1) 949 fin->fin_flx |= FI_BAD; 950 } 951 #endif 952 953 954 /* 955 * See above for description, except that all addressing is in user space. 956 */ 957 int copyoutptr(src, dst, size) 958 void *src, *dst; 959 size_t size; 960 { 961 caddr_t ca; 962 963 bcopy(dst, (char *)&ca, sizeof(ca)); 964 bcopy(src, ca, size); 965 return 0; 966 } 967 968 969 /* 970 * See above for description, except that all addressing is in user space. 971 */ 972 int copyinptr(src, dst, size) 973 void *src, *dst; 974 size_t size; 975 { 976 caddr_t ca; 977 978 bcopy(src, (char *)&ca, sizeof(ca)); 979 bcopy(ca, dst, size); 980 return 0; 981 } 982 983 984 /* 985 * return the first IP Address associated with an interface 986 */ 987 int fr_ifpaddr(v, atype, ifptr, inp, inpmask, ifs) 988 int v, atype; 989 void *ifptr; 990 struct in_addr *inp, *inpmask; 991 ipf_stack_t *ifs; 992 { 993 struct ifnet *ifp = ifptr; 994 #ifdef __sgi 995 struct in_ifaddr *ifa; 996 #else 997 struct ifaddr *ifa; 998 #endif 999 1000 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) 1001 ifa = ifp->if_addrlist.tqh_first; 1002 #else 1003 # ifdef __sgi 1004 ifa = (struct in_ifaddr *)ifp->in_ifaddr; 1005 # else 1006 ifa = ifp->if_addrlist; 1007 # endif 1008 #endif 1009 if (ifa != NULL) { 1010 struct sockaddr_in *sin, mask; 1011 1012 mask.sin_addr.s_addr = 0xffffffff; 1013 1014 #ifdef __sgi 1015 sin = (struct sockaddr_in *)&ifa->ia_addr; 1016 #else 1017 sin = (struct sockaddr_in *)&ifa->ifa_addr; 1018 #endif 1019 1020 return fr_ifpfillv4addr(atype, sin, &mask, inp, inpmask); 1021 } 1022 return 0; 1023 } 1024 1025 1026 /* 1027 * This function is not meant to be random, rather just produce a 1028 * sequence of numbers that isn't linear to show "randomness". 1029 */ 1030 u_32_t ipf_random() 1031 { 1032 static u_int last = 0xa5a5a5a5; 1033 static int calls = 0; 1034 int number; 1035 1036 calls++; 1037 1038 /* 1039 * These are deliberately chosen to ensure that there is some 1040 * attempt to test whether the output covers the range in test n18. 1041 */ 1042 switch (calls) 1043 { 1044 case 1 : 1045 number = 0; 1046 break; 1047 case 2 : 1048 number = 4; 1049 break; 1050 case 3 : 1051 number = 3999; 1052 break; 1053 case 4 : 1054 number = 4000; 1055 break; 1056 case 5 : 1057 number = 48999; 1058 break; 1059 case 6 : 1060 number = 49000; 1061 break; 1062 default : 1063 number = last; 1064 last *= calls; 1065 last++; 1066 number ^= last; 1067 break; 1068 } 1069 return number; 1070 } 1071