add UNLEASHED_OBJ to unleashed.mk
[unleashed/tickless.git] / usr / src / cmd / ipf / tools / ip_fil.c
blob8968436b774eeb0282934642cc33f582deca7fff
1 /*
2 * Copyright (C) 1993-2001, 2003 by Darren Reed.
4 * See the IPFILTER.LICENCE file for details on licencing.
6 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
7 * Use is subject to license terms.
8 */
10 #ifndef SOLARIS
11 #define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
12 #endif
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>
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>
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"
140 #if !defined(__osf__)
141 extern struct protosw inetsw[];
142 #endif
144 #include "ipt.h"
145 static struct ifnet **ifneta = NULL;
146 static int nifs = 0;
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
171 int iplattach(ifs)
172 ipf_stack_t *ifs;
174 ifs->ifs_fr_running = 1;
175 return 0;
179 int ipldetach(ifs)
180 ipf_stack_t *ifs;
182 ifs->ifs_fr_running = -1;
183 return 0;
187 static int frzerostats(data, ifs)
188 caddr_t data;
189 ipf_stack_t *ifs;
191 friostat_t fio;
192 int error;
194 fr_getstat(&fio, ifs);
195 error = copyoutptr(&fio, data, sizeof(fio));
196 if (error)
197 return EFAULT;
199 bzero((char *)ifs->ifs_frstats, sizeof(*ifs->ifs_frstats) * 2);
201 return 0;
206 * Filter ioctl interface.
208 int iplioctl(dev, cmd, data, mode)
209 int dev;
210 ioctlcmd_t cmd;
211 caddr_t data;
212 int mode;
214 int error = 0, unit = 0, tmp, uid;
215 friostat_t fio;
216 ipf_stack_t *ifs;
217 extern ipf_stack_t *get_ifs();
219 unit = dev;
220 uid = getuid();
222 ifs = get_ifs();
224 SPL_NET(s);
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;
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;
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);
252 } else {
253 error = fr_auth_ioctl(data, cmd, mode, uid,
254 NULL, ifs);
256 } else
257 error = EIO;
258 SPL_X(s);
259 return error;
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;
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;
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;
291 switch (cmd)
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);
311 break;
312 case SIOCIPFSET :
313 if (!(mode & FWRITE)) {
314 error = EPERM;
315 break;
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;
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));
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));
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);
424 break;
425 default :
426 error = EINVAL;
427 break;
429 SPL_X(s);
430 return error;
434 void fr_forgetifp(ifp, ifs)
435 void *ifp;
436 ipf_stack_t *ifs;
438 register frentry_t *f;
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);
481 void fr_resolvedest(fdp, v, ifs)
482 frdest_t *fdp;
483 int v;
484 ipf_stack_t *ifs;
486 fdp->fd_ifp = NULL;
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;
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;
511 return 0;
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;
530 char fname[32];
531 mb_t *mb;
532 ip_t *ip;
533 int fd;
535 mb = (mb_t *)m;
536 ip = MTOD(mb, ip_t *);
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;
550 write(fd, (char *)ip, ntohs(ip->ip_len));
551 close(fd);
552 return 0;
556 static void fr_setifpaddr(ifp, addr)
557 struct ifnet *ifp;
558 char *addr;
560 #ifdef __sgi
561 struct in_ifaddr *ifa;
562 #else
563 struct ifaddr *ifa;
564 #endif
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;
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
588 if (ifa != NULL) {
589 struct sockaddr_in *sin;
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();
602 /*ARGSUSED*/
603 struct ifnet *get_unit(name, v, ifs)
604 char *name;
605 int v;
606 ipf_stack_t *ifs;
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))
614 if (name == NULL)
615 name = "anon0";
617 addr = strchr(name, '=');
618 if (addr != NULL)
619 *addr++ = '\0';
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;
628 #else
629 char *s, ifname[LIFNAMSIZ+1];
631 if (name == NULL)
632 name = "anon0";
634 addr = strchr(name, '=');
635 if (addr != NULL)
636 *addr++ = '\0';
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;
646 #endif
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;
658 nifs = 1;
659 } else {
660 old_ifneta = ifneta;
661 nifs++;
662 ifneta = (struct ifnet **)reallocarray(ifneta, nifs + 1,
663 sizeof (ifp));
664 if (!ifneta) {
665 free(old_ifneta);
666 nifs = 0;
667 return NULL;
669 ifneta[nifs] = NULL;
670 ifneta[nifs - 1] = (struct ifnet *)malloc(sizeof(*ifp));
671 if (!ifneta[nifs - 1]) {
672 nifs--;
673 return NULL;
676 ifp = ifneta[nifs - 1];
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++)
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) {
690 * XXX do it more elegantly: free up mem,
691 * return NULL
693 perror("malloc");
694 exit(1);
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;
702 #endif
703 ifp->if_output = no_output;
705 if (addr != NULL) {
706 fr_setifpaddr(ifp, addr);
709 return ifp;
713 char *get_ifname(ifp)
714 struct ifnet *ifp;
716 static char ifname[LIFNAMSIZ];
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;
729 void init_ifp()
731 struct ifnet *ifp, **ifpp;
732 char fname[32];
733 int fd;
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);
747 #else
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);
758 #endif
762 int fr_fastroute(m, mpp, fin, fdp)
763 mb_t *m, **mpp;
764 fr_info_t *fin;
765 frdest_t *fdp;
767 struct ifnet *ifp = fdp->fd_ifp;
768 ip_t *ip = fin->fin_ip;
770 if (!ifp)
771 return 0; /* no routing table out here */
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;
788 int fr_send_reset(fin)
789 fr_info_t *fin;
791 verbose("- TCP RST sent\n");
792 return 0;
796 int fr_send_icmp_err(type, fin, dst)
797 int type;
798 fr_info_t *fin;
799 int dst;
801 verbose("- ICMP unreachable sent\n");
802 return 0;
806 void frsync(command, version, nic, data, ifs)
807 int command, version;
808 void *nic;
809 char *data;
810 ipf_stack_t *ifs;
812 return;
816 void m_freem(m)
817 mb_t *m;
819 return;
823 void m_copydata(m, off, len, cp)
824 mb_t *m;
825 int off, len;
826 caddr_t cp;
828 bcopy((char *)m + off, cp, len);
832 int ipfuiomove(buf, len, rwflag, uio)
833 caddr_t buf;
834 int len, rwflag;
835 struct uio *uio;
837 int left, ioc, num, offset;
838 struct iovec *io;
839 char *start;
841 if (rwflag == UIO_READ) {
842 left = len;
843 ioc = 0;
845 offset = uio->uio_offset;
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;
858 bcopy(buf, start, num);
859 uio->uio_resid -= num;
860 uio->uio_offset += num;
861 left -= num;
862 if (left > 0)
863 ioc++;
865 if (left > 0)
866 return EFAULT;
868 return 0;
872 u_32_t fr_newisn(fin)
873 fr_info_t *fin;
875 static int iss_seq_off = 0;
876 u_char hash[16];
877 u_32_t newiss;
878 MD5_CTX ctx;
881 * Compute the base value of the ISS. It is a hash
882 * of (saddr, sport, daddr, dport, secret).
884 MD5Init(&ctx);
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));
892 /* MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); */
894 MD5Final(hash, &ctx);
896 memcpy(&newiss, hash, sizeof(newiss));
899 * Now increment our "timer", and add it in to
900 * the computed value.
902 * XXX Use `addin'?
903 * XXX TCP_ISSINCR too large to use?
905 iss_seq_off += 0x00010000;
906 newiss += iss_seq_off;
907 return newiss;
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;
921 static u_short ipid = 0;
922 u_short id;
923 ipf_stack_t *ifs = fin->fin_ifs;
925 MUTEX_ENTER(&ifs->ifs_ipf_rw);
926 id = ipid++;
927 MUTEX_EXIT(&ifs->ifs_ipf_rw);
929 return id;
933 INLINE void fr_checkv4sum(fin)
934 fr_info_t *fin;
936 if (fr_checkl4sum(fin) == -1)
937 fin->fin_flx |= FI_BAD;
941 #ifdef USE_INET6
942 INLINE void fr_checkv6sum(fin)
943 fr_info_t *fin;
945 if (fr_checkl4sum(fin) == -1)
946 fin->fin_flx |= FI_BAD;
948 #endif
952 * See above for description, except that all addressing is in user space.
954 int copyoutptr(src, dst, size)
955 void *src, *dst;
956 size_t size;
958 caddr_t ca;
960 bcopy(dst, (char *)&ca, sizeof(ca));
961 bcopy(src, ca, size);
962 return 0;
967 * See above for description, except that all addressing is in user space.
969 int copyinptr(src, dst, size)
970 void *src, *dst;
971 size_t size;
973 caddr_t ca;
975 bcopy(src, (char *)&ca, sizeof(ca));
976 bcopy(ca, dst, size);
977 return 0;
982 * return the first IP Address associated with an interface
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;
990 struct ifnet *ifp = ifptr;
991 #ifdef __sgi
992 struct in_ifaddr *ifa;
993 #else
994 struct ifaddr *ifa;
995 #endif
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;
1009 mask.sin_addr.s_addr = 0xffffffff;
1011 #ifdef __sgi
1012 sin = (struct sockaddr_in *)&ifa->ia_addr;
1013 #else
1014 sin = (struct sockaddr_in *)&ifa->ifa_addr;
1015 #endif
1017 return fr_ifpfillv4addr(atype, sin, &mask, inp, inpmask);
1019 return 0;
1024 * This function is not meant to be random, rather just produce a
1025 * sequence of numbers that isn't linear to show "randomness".
1027 u_32_t ipf_random()
1029 static u_int last = 0xa5a5a5a5;
1030 static int calls = 0;
1031 int number;
1033 calls++;
1036 * These are deliberately chosen to ensure that there is some
1037 * attempt to test whether the output covers the range in test n18.
1039 switch (calls)
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;
1066 return number;