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