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