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