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