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