1 /* 2 * Copyright (C) 1993-2001, 2003 by Darren Reed. 3 * 4 * See the IPFILTER.LICENCE file for details on licencing. 5 * 6 * Copyright 2009 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, cmd, mode, uid, 259 NULL, ifs); 260 } 261 } else 262 error = EIO; 263 SPL_X(s); 264 return error; 265 } 266 if (unit == IPL_LOGSYNC) { 267 #ifdef IPFILTER_SYNC 268 if (ifs->ifs_fr_running > 0) 269 error = fr_sync_ioctl(data, cmd, mode); 270 else 271 #endif 272 error = EIO; 273 SPL_X(s); 274 return error; 275 } 276 if (unit == IPL_LOGSCAN) { 277 #ifdef IPFILTER_SCAN 278 if (ifs->ifs_fr_running > 0) 279 error = fr_scan_ioctl(data, cmd, mode); 280 else 281 #endif 282 error = EIO; 283 SPL_X(s); 284 return error; 285 } 286 if (unit == IPL_LOGLOOKUP) { 287 if (ifs->ifs_fr_running > 0) 288 error = ip_lookup_ioctl(data, cmd, mode, uid, 289 NULL, ifs); 290 else 291 error = EIO; 292 SPL_X(s); 293 return error; 294 } 295 296 switch (cmd) 297 { 298 case FIONREAD : 299 #ifdef IPFILTER_LOG 300 error = COPYOUT(&ifs->ifs_iplused[IPL_LOGIPF], (caddr_t)data, 301 sizeof(ifs->ifs_iplused[IPL_LOGIPF])); 302 #endif 303 break; 304 case SIOCFRENB : 305 if (!(mode & FWRITE)) 306 error = EPERM; 307 else { 308 error = COPYIN(data, &tmp, sizeof(tmp)); 309 if (error) 310 break; 311 if (tmp) 312 error = iplattach(ifs); 313 else 314 error = ipldetach(ifs); 315 } 316 break; 317 case SIOCIPFSET : 318 if (!(mode & FWRITE)) { 319 error = EPERM; 320 break; 321 } 322 case SIOCIPFGETNEXT : 323 case SIOCIPFGET : 324 error = fr_ipftune(cmd, (void *)data, ifs); 325 break; 326 case SIOCSETFF : 327 if (!(mode & FWRITE)) 328 error = EPERM; 329 else 330 error = COPYIN(data, &ifs->ifs_fr_flags, 331 sizeof(ifs->ifs_fr_flags)); 332 break; 333 case SIOCGETFF : 334 error = COPYOUT(&ifs->ifs_fr_flags, data, 335 sizeof(ifs->ifs_fr_flags)); 336 break; 337 case SIOCFUNCL : 338 error = fr_resolvefunc(data); 339 break; 340 case SIOCINAFR : 341 case SIOCRMAFR : 342 case SIOCADAFR : 343 case SIOCZRLST : 344 if (!(mode & FWRITE)) 345 error = EPERM; 346 else 347 error = frrequest(unit, cmd, data, 348 ifs->ifs_fr_active, 1, ifs); 349 break; 350 case SIOCINIFR : 351 case SIOCRMIFR : 352 case SIOCADIFR : 353 if (!(mode & FWRITE)) 354 error = EPERM; 355 else 356 error = frrequest(unit, cmd, data, 357 1 - ifs->ifs_fr_active, 1, ifs); 358 break; 359 case SIOCSWAPA : 360 if (!(mode & FWRITE)) 361 error = EPERM; 362 else { 363 *(u_int *)data = ifs->ifs_fr_active; 364 ifs->ifs_fr_active = 1 - ifs->ifs_fr_active; 365 } 366 break; 367 case SIOCGETFS : 368 fr_getstat(&fio, ifs); 369 error = fr_outobj(data, &fio, IPFOBJ_IPFSTAT); 370 break; 371 case SIOCFRZST : 372 if (!(mode & FWRITE)) 373 error = EPERM; 374 else 375 error = frzerostats(data, ifs); 376 break; 377 case SIOCIPFFL : 378 if (!(mode & FWRITE)) 379 error = EPERM; 380 else { 381 error = COPYIN(data, &tmp, sizeof(tmp)); 382 if (!error) { 383 tmp = frflush(unit, 4, tmp, ifs); 384 error = COPYOUT(&tmp, data, sizeof(tmp)); 385 } 386 } 387 break; 388 #ifdef USE_INET6 389 case SIOCIPFL6 : 390 if (!(mode & FWRITE)) 391 error = EPERM; 392 else { 393 error = COPYIN(data, &tmp, sizeof(tmp)); 394 if (!error) { 395 tmp = frflush(unit, 6, tmp, ifs); 396 error = COPYOUT(&tmp, data, sizeof(tmp)); 397 } 398 } 399 break; 400 #endif 401 case SIOCSTLCK : 402 error = COPYIN(data, &tmp, sizeof(tmp)); 403 if (error == 0) { 404 ifs->ifs_fr_state_lock = tmp; 405 ifs->ifs_fr_nat_lock = tmp; 406 ifs->ifs_fr_frag_lock = tmp; 407 ifs->ifs_fr_auth_lock = tmp; 408 } else 409 error = EFAULT; 410 break; 411 #ifdef IPFILTER_LOG 412 case SIOCIPFFB : 413 if (!(mode & FWRITE)) 414 error = EPERM; 415 else 416 *(int *)data = ipflog_clear(unit, ifs); 417 break; 418 #endif /* IPFILTER_LOG */ 419 case SIOCGFRST : 420 error = fr_outobj(data, fr_fragstats(ifs), IPFOBJ_FRAGSTAT); 421 break; 422 case SIOCFRSYN : 423 if (!(mode & FWRITE)) 424 error = EPERM; 425 else { 426 frsync(IPFSYNC_RESYNC, IPFSYNC_RESYNC, NULL, NULL, ifs); 427 } 428 break; 429 default : 430 error = EINVAL; 431 break; 432 } 433 SPL_X(s); 434 return error; 435 } 436 437 438 void fr_forgetifp(ifp, ifs) 439 void *ifp; 440 ipf_stack_t *ifs; 441 { 442 register frentry_t *f; 443 444 WRITE_ENTER(&ifs->ifs_ipf_mutex); 445 for (f = ifs->ifs_ipacct[0][ifs->ifs_fr_active]; (f != NULL); 446 f = f->fr_next) 447 if (f->fr_ifa == ifp) 448 f->fr_ifa = (void *)-1; 449 for (f = ifs->ifs_ipacct[1][ifs->ifs_fr_active]; (f != NULL); 450 f = f->fr_next) 451 if (f->fr_ifa == ifp) 452 f->fr_ifa = (void *)-1; 453 for (f = ifs->ifs_ipfilter[0][ifs->ifs_fr_active]; (f != NULL); 454 f = f->fr_next) 455 if (f->fr_ifa == ifp) 456 f->fr_ifa = (void *)-1; 457 for (f = ifs->ifs_ipfilter[1][ifs->ifs_fr_active]; (f != NULL); 458 f = f->fr_next) 459 if (f->fr_ifa == ifp) 460 f->fr_ifa = (void *)-1; 461 #ifdef USE_INET6 462 for (f = ifs->ifs_ipacct6[0][ifs->ifs_fr_active]; (f != NULL); 463 f = f->fr_next) 464 if (f->fr_ifa == ifp) 465 f->fr_ifa = (void *)-1; 466 for (f = ifs->ifs_ipacct6[1][ifs->ifs_fr_active]; (f != NULL); 467 f = f->fr_next) 468 if (f->fr_ifa == ifp) 469 f->fr_ifa = (void *)-1; 470 for (f = ifs->ifs_ipfilter6[0][ifs->ifs_fr_active]; (f != NULL); 471 f = f->fr_next) 472 if (f->fr_ifa == ifp) 473 f->fr_ifa = (void *)-1; 474 for (f = ifs->ifs_ipfilter6[1][ifs->ifs_fr_active]; (f != NULL); 475 f = f->fr_next) 476 if (f->fr_ifa == ifp) 477 f->fr_ifa = (void *)-1; 478 #endif 479 RWLOCK_EXIT(&ifs->ifs_ipf_mutex); 480 fr_natifpsync(IPFSYNC_OLDIFP, 4, ifp, NULL, ifs); 481 fr_natifpsync(IPFSYNC_OLDIFP, 6, ifp, NULL, ifs); 482 } 483 484 485 void fr_resolvedest(fdp, v, ifs) 486 frdest_t *fdp; 487 int v; 488 ipf_stack_t *ifs; 489 { 490 fdp->fd_ifp = NULL; 491 492 if (*fdp->fd_ifname) { 493 fdp->fd_ifp = GETIFP(fdp->fd_ifname, v, ifs); 494 if (!fdp->fd_ifp) 495 fdp->fd_ifp = (struct ifnet *)-1; 496 } 497 } 498 499 500 #if defined(__sgi) && (IRIX < 60500) 501 static int no_output(ifp, m, s) 502 #else 503 # if TRU64 >= 1885 504 static int no_output (ifp, m, s, rt, cp) 505 char *cp; 506 # else 507 static int no_output(ifp, m, s, rt) 508 # endif 509 struct rtentry *rt; 510 #endif 511 struct ifnet *ifp; 512 struct mbuf *m; 513 struct sockaddr *s; 514 { 515 return 0; 516 } 517 518 519 #if defined(__sgi) && (IRIX < 60500) 520 static int write_output(ifp, m, s) 521 #else 522 # if TRU64 >= 1885 523 static int write_output (ifp, m, s, rt, cp) 524 char *cp; 525 # else 526 static int write_output(ifp, m, s, rt) 527 # endif 528 struct rtentry *rt; 529 #endif 530 struct ifnet *ifp; 531 struct mbuf *m; 532 struct sockaddr *s; 533 { 534 char fname[32]; 535 mb_t *mb; 536 ip_t *ip; 537 int fd; 538 539 mb = (mb_t *)m; 540 ip = MTOD(mb, ip_t *); 541 542 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ 543 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ 544 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) 545 sprintf(fname, "/tmp/%s", ifp->if_xname); 546 #else 547 sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit); 548 #endif 549 fd = open(fname, O_WRONLY|O_APPEND); 550 if (fd == -1) { 551 perror("open"); 552 return -1; 553 } 554 write(fd, (char *)ip, ntohs(ip->ip_len)); 555 close(fd); 556 return 0; 557 } 558 559 560 static void fr_setifpaddr(ifp, addr) 561 struct ifnet *ifp; 562 char *addr; 563 { 564 #ifdef __sgi 565 struct in_ifaddr *ifa; 566 #else 567 struct ifaddr *ifa; 568 #endif 569 570 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) 571 if (ifp->if_addrlist.tqh_first != NULL) 572 #else 573 # ifdef __sgi 574 if (ifp->in_ifaddr != NULL) 575 # else 576 if (ifp->if_addrlist != NULL) 577 # endif 578 #endif 579 return; 580 581 ifa = (struct ifaddr *)malloc(sizeof(*ifa)); 582 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) 583 ifp->if_addrlist.tqh_first = ifa; 584 #else 585 # ifdef __sgi 586 ifp->in_ifaddr = ifa; 587 # else 588 ifp->if_addrlist = ifa; 589 # endif 590 #endif 591 592 if (ifa != NULL) { 593 struct sockaddr_in *sin; 594 595 #ifdef __sgi 596 sin = (struct sockaddr_in *)&ifa->ia_addr; 597 #else 598 sin = (struct sockaddr_in *)&ifa->ifa_addr; 599 #endif 600 sin->sin_addr.s_addr = inet_addr(addr); 601 if (sin->sin_addr.s_addr == 0) 602 abort(); 603 } 604 } 605 606 /*ARGSUSED*/ 607 struct ifnet *get_unit(name, v, ifs) 608 char *name; 609 int v; 610 ipf_stack_t *ifs; 611 { 612 struct ifnet *ifp, **ifpp, **old_ifneta; 613 char *addr; 614 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ 615 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ 616 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) 617 618 if (name == NULL) 619 name = "anon0"; 620 621 addr = strchr(name, '='); 622 if (addr != NULL) 623 *addr++ = '\0'; 624 625 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { 626 if (!strcmp(name, ifp->if_xname)) { 627 if (addr != NULL) 628 fr_setifpaddr(ifp, addr); 629 return ifp; 630 } 631 } 632 #else 633 char *s, ifname[LIFNAMSIZ+1]; 634 635 if (name == NULL) 636 name = "anon0"; 637 638 addr = strchr(name, '='); 639 if (addr != NULL) 640 *addr++ = '\0'; 641 642 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { 643 COPYIFNAME(ifp, ifname, 0); 644 if (!strcmp(name, ifname)) { 645 if (addr != NULL) 646 fr_setifpaddr(ifp, addr); 647 return ifp; 648 } 649 } 650 #endif 651 652 if (!ifneta) { 653 ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2); 654 if (!ifneta) 655 return NULL; 656 ifneta[1] = NULL; 657 ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp)); 658 if (!ifneta[0]) { 659 free(ifneta); 660 return NULL; 661 } 662 nifs = 1; 663 } else { 664 old_ifneta = ifneta; 665 nifs++; 666 ifneta = (struct ifnet **)realloc(ifneta, 667 (nifs + 1) * sizeof(ifp)); 668 if (!ifneta) { 669 free(old_ifneta); 670 nifs = 0; 671 return NULL; 672 } 673 ifneta[nifs] = NULL; 674 ifneta[nifs - 1] = (struct ifnet *)malloc(sizeof(*ifp)); 675 if (!ifneta[nifs - 1]) { 676 nifs--; 677 return NULL; 678 } 679 } 680 ifp = ifneta[nifs - 1]; 681 682 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ 683 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ 684 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) 685 (void) strncpy(ifp->if_xname, name, sizeof(ifp->if_xname)); 686 #else 687 for (s = name; *s && !ISDIGIT(*s); s++) 688 ; 689 if (*s && ISDIGIT(*s)) { 690 ifp->if_unit = atoi(s); 691 ifp->if_name = (char *)malloc(s - name + 1); 692 if (ifp->if_name == NULL) { 693 /* 694 * XXX do it more elegantly: free up mem, 695 * return NULL 696 */ 697 perror("malloc"); 698 exit(1); 699 } 700 (void) strncpy(ifp->if_name, name, s - name); 701 ifp->if_name[s - name] = '\0'; 702 } else { 703 ifp->if_name = strdup(name); 704 ifp->if_unit = -1; 705 } 706 #endif 707 ifp->if_output = no_output; 708 709 if (addr != NULL) { 710 fr_setifpaddr(ifp, addr); 711 } 712 713 return ifp; 714 } 715 716 717 char *get_ifname(ifp) 718 struct ifnet *ifp; 719 { 720 static char ifname[LIFNAMSIZ]; 721 722 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(linux) || \ 723 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) 724 sprintf(ifname, "%s", ifp->if_xname); 725 #else 726 sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit); 727 #endif 728 return ifname; 729 } 730 731 732 733 void init_ifp() 734 { 735 struct ifnet *ifp, **ifpp; 736 char fname[32]; 737 int fd; 738 739 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \ 740 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \ 741 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113)) 742 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { 743 ifp->if_output = write_output; 744 sprintf(fname, "/tmp/%s", ifp->if_xname); 745 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600); 746 if (fd == -1) 747 perror("open"); 748 else 749 close(fd); 750 } 751 #else 752 753 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) { 754 ifp->if_output = write_output; 755 sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit); 756 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600); 757 if (fd == -1) 758 perror("open"); 759 else 760 close(fd); 761 } 762 #endif 763 } 764 765 766 int fr_fastroute(m, mpp, fin, fdp) 767 mb_t *m, **mpp; 768 fr_info_t *fin; 769 frdest_t *fdp; 770 { 771 struct ifnet *ifp = fdp->fd_ifp; 772 ip_t *ip = fin->fin_ip; 773 774 if (!ifp) 775 return 0; /* no routing table out here */ 776 777 ip->ip_len = htons((u_short)ip->ip_len); 778 ip->ip_off = htons((u_short)(ip->ip_off | IP_MF)); 779 ip->ip_sum = 0; 780 #if defined(__sgi) && (IRIX < 60500) 781 (*ifp->if_output)(ifp, (void *)ip, NULL); 782 # if TRU64 >= 1885 783 (*ifp->if_output)(ifp, (void *)m, NULL, 0, 0); 784 # else 785 (*ifp->if_output)(ifp, (void *)m, NULL, 0); 786 # endif 787 #endif 788 return 0; 789 } 790 791 792 int fr_send_reset(fin) 793 fr_info_t *fin; 794 { 795 verbose("- TCP RST sent\n"); 796 return 0; 797 } 798 799 800 int fr_send_icmp_err(type, fin, dst) 801 int type; 802 fr_info_t *fin; 803 int dst; 804 { 805 verbose("- ICMP unreachable sent\n"); 806 return 0; 807 } 808 809 810 void frsync(command, version, nic, data, ifs) 811 int command, version; 812 void *nic; 813 char *data; 814 ipf_stack_t *ifs; 815 { 816 return; 817 } 818 819 820 void m_freem(m) 821 mb_t *m; 822 { 823 return; 824 } 825 826 827 void m_copydata(m, off, len, cp) 828 mb_t *m; 829 int off, len; 830 caddr_t cp; 831 { 832 bcopy((char *)m + off, cp, len); 833 } 834 835 836 int ipfuiomove(buf, len, rwflag, uio) 837 caddr_t buf; 838 int len, rwflag; 839 struct uio *uio; 840 { 841 int left, ioc, num, offset; 842 struct iovec *io; 843 char *start; 844 845 if (rwflag == UIO_READ) { 846 left = len; 847 ioc = 0; 848 849 offset = uio->uio_offset; 850 851 while ((left > 0) && (ioc < uio->uio_iovcnt)) { 852 io = uio->uio_iov + ioc; 853 num = io->iov_len; 854 if (num > left) 855 num = left; 856 start = (char *)io->iov_base + offset; 857 if (start > (char *)io->iov_base + io->iov_len) { 858 offset -= io->iov_len; 859 ioc++; 860 continue; 861 } 862 bcopy(buf, start, num); 863 uio->uio_resid -= num; 864 uio->uio_offset += num; 865 left -= num; 866 if (left > 0) 867 ioc++; 868 } 869 if (left > 0) 870 return EFAULT; 871 } 872 return 0; 873 } 874 875 876 u_32_t fr_newisn(fin) 877 fr_info_t *fin; 878 { 879 static int iss_seq_off = 0; 880 u_char hash[16]; 881 u_32_t newiss; 882 MD5_CTX ctx; 883 884 /* 885 * Compute the base value of the ISS. It is a hash 886 * of (saddr, sport, daddr, dport, secret). 887 */ 888 MD5Init(&ctx); 889 890 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src, 891 sizeof(fin->fin_fi.fi_src)); 892 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst, 893 sizeof(fin->fin_fi.fi_dst)); 894 MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat)); 895 896 /* MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); */ 897 898 MD5Final(hash, &ctx); 899 900 memcpy(&newiss, hash, sizeof(newiss)); 901 902 /* 903 * Now increment our "timer", and add it in to 904 * the computed value. 905 * 906 * XXX Use `addin'? 907 * XXX TCP_ISSINCR too large to use? 908 */ 909 iss_seq_off += 0x00010000; 910 newiss += iss_seq_off; 911 return newiss; 912 } 913 914 915 /* ------------------------------------------------------------------------ */ 916 /* Function: fr_nextipid */ 917 /* Returns: int - 0 == success, -1 == error (packet should be droppped) */ 918 /* Parameters: fin(I) - pointer to packet information */ 919 /* */ 920 /* Returns the next IPv4 ID to use for this packet. */ 921 /* ------------------------------------------------------------------------ */ 922 INLINE u_short fr_nextipid(fin) 923 fr_info_t *fin; 924 { 925 static u_short ipid = 0; 926 u_short id; 927 ipf_stack_t *ifs = fin->fin_ifs; 928 929 MUTEX_ENTER(&ifs->ifs_ipf_rw); 930 id = ipid++; 931 MUTEX_EXIT(&ifs->ifs_ipf_rw); 932 933 return id; 934 } 935 936 937 INLINE void fr_checkv4sum(fin) 938 fr_info_t *fin; 939 { 940 if (fr_checkl4sum(fin) == -1) 941 fin->fin_flx |= FI_BAD; 942 } 943 944 945 #ifdef USE_INET6 946 INLINE void fr_checkv6sum(fin) 947 fr_info_t *fin; 948 { 949 if (fr_checkl4sum(fin) == -1) 950 fin->fin_flx |= FI_BAD; 951 } 952 #endif 953 954 955 /* 956 * See above for description, except that all addressing is in user space. 957 */ 958 int copyoutptr(src, dst, size) 959 void *src, *dst; 960 size_t size; 961 { 962 caddr_t ca; 963 964 bcopy(dst, (char *)&ca, sizeof(ca)); 965 bcopy(src, ca, size); 966 return 0; 967 } 968 969 970 /* 971 * See above for description, except that all addressing is in user space. 972 */ 973 int copyinptr(src, dst, size) 974 void *src, *dst; 975 size_t size; 976 { 977 caddr_t ca; 978 979 bcopy(src, (char *)&ca, sizeof(ca)); 980 bcopy(ca, dst, size); 981 return 0; 982 } 983 984 985 /* 986 * return the first IP Address associated with an interface 987 */ 988 int fr_ifpaddr(v, atype, ifptr, inp, inpmask, ifs) 989 int v, atype; 990 void *ifptr; 991 struct in_addr *inp, *inpmask; 992 ipf_stack_t *ifs; 993 { 994 struct ifnet *ifp = ifptr; 995 #ifdef __sgi 996 struct in_ifaddr *ifa; 997 #else 998 struct ifaddr *ifa; 999 #endif 1000 1001 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) 1002 ifa = ifp->if_addrlist.tqh_first; 1003 #else 1004 # ifdef __sgi 1005 ifa = (struct in_ifaddr *)ifp->in_ifaddr; 1006 # else 1007 ifa = ifp->if_addrlist; 1008 # endif 1009 #endif 1010 if (ifa != NULL) { 1011 struct sockaddr_in *sin, mask; 1012 1013 mask.sin_addr.s_addr = 0xffffffff; 1014 1015 #ifdef __sgi 1016 sin = (struct sockaddr_in *)&ifa->ia_addr; 1017 #else 1018 sin = (struct sockaddr_in *)&ifa->ifa_addr; 1019 #endif 1020 1021 return fr_ifpfillv4addr(atype, sin, &mask, inp, inpmask); 1022 } 1023 return 0; 1024 } 1025 1026 1027 /* 1028 * This function is not meant to be random, rather just produce a 1029 * sequence of numbers that isn't linear to show "randomness". 1030 */ 1031 u_32_t ipf_random() 1032 { 1033 static u_int last = 0xa5a5a5a5; 1034 static int calls = 0; 1035 int number; 1036 1037 calls++; 1038 1039 /* 1040 * These are deliberately chosen to ensure that there is some 1041 * attempt to test whether the output covers the range in test n18. 1042 */ 1043 switch (calls) 1044 { 1045 case 1 : 1046 number = 0; 1047 break; 1048 case 2 : 1049 number = 4; 1050 break; 1051 case 3 : 1052 number = 3999; 1053 break; 1054 case 4 : 1055 number = 4000; 1056 break; 1057 case 5 : 1058 number = 48999; 1059 break; 1060 case 6 : 1061 number = 49000; 1062 break; 1063 default : 1064 number = last; 1065 last *= calls; 1066 last++; 1067 number ^= last; 1068 break; 1069 } 1070 return number; 1071 } 1072