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 #if !defined(lint)
11 static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
12 static const char rcsid[] = "@(#)$Id: ip_fil.c,v 2.133.2.9 2005/01/08 14:22:18 darrenr Exp $";
13 #endif
14
15 #ifndef SOLARIS
16 #define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
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 !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 case SIOCIPFGETNEXT :
323 case SIOCIPFGET :
324 error = fr_ipftune(cmd, (void *)data, ifs);
325 break;
326 case SIOCSETFF :
327 if (!(mode & FWRITE))
328 error = EPERM;
329 else
330 error = COPYIN(data, &ifs->ifs_fr_flags,
331 sizeof(ifs->ifs_fr_flags));
332 break;
333 case SIOCGETFF :
334 error = COPYOUT(&ifs->ifs_fr_flags, data,
335 sizeof(ifs->ifs_fr_flags));
336 break;
337 case SIOCFUNCL :
338 error = fr_resolvefunc(data);
339 break;
340 case SIOCINAFR :
341 case SIOCRMAFR :
342 case SIOCADAFR :
343 case SIOCZRLST :
344 if (!(mode & FWRITE))
345 error = EPERM;
346 else
347 error = frrequest(unit, cmd, data,
348 ifs->ifs_fr_active, 1, ifs);
349 break;
350 case SIOCINIFR :
351 case SIOCRMIFR :
352 case SIOCADIFR :
353 if (!(mode & FWRITE))
354 error = EPERM;
355 else
356 error = frrequest(unit, cmd, data,
357 1 - ifs->ifs_fr_active, 1, ifs);
358 break;
359 case SIOCSWAPA :
360 if (!(mode & FWRITE))
361 error = EPERM;
362 else {
363 *(u_int *)data = ifs->ifs_fr_active;
364 ifs->ifs_fr_active = 1 - ifs->ifs_fr_active;
365 }
366 break;
367 case SIOCGETFS :
368 fr_getstat(&fio, ifs);
369 error = fr_outobj(data, &fio, IPFOBJ_IPFSTAT);
370 break;
371 case SIOCFRZST :
372 if (!(mode & FWRITE))
373 error = EPERM;
374 else
375 error = frzerostats(data, ifs);
376 break;
377 case SIOCIPFFL :
378 if (!(mode & FWRITE))
379 error = EPERM;
380 else {
381 error = COPYIN(data, &tmp, sizeof(tmp));
382 if (!error) {
383 tmp = frflush(unit, 4, tmp, ifs);
384 error = COPYOUT(&tmp, data, sizeof(tmp));
385 }
386 }
387 break;
388 #ifdef USE_INET6
389 case SIOCIPFL6 :
390 if (!(mode & FWRITE))
391 error = EPERM;
392 else {
393 error = COPYIN(data, &tmp, sizeof(tmp));
394 if (!error) {
395 tmp = frflush(unit, 6, tmp, ifs);
396 error = COPYOUT(&tmp, data, sizeof(tmp));
397 }
398 }
399 break;
400 #endif
401 case SIOCSTLCK :
402 error = COPYIN(data, &tmp, sizeof(tmp));
403 if (error == 0) {
404 ifs->ifs_fr_state_lock = tmp;
405 ifs->ifs_fr_nat_lock = tmp;
406 ifs->ifs_fr_frag_lock = tmp;
407 ifs->ifs_fr_auth_lock = tmp;
408 } else
409 error = EFAULT;
410 break;
411 #ifdef IPFILTER_LOG
412 case SIOCIPFFB :
413 if (!(mode & FWRITE))
414 error = EPERM;
415 else
416 *(int *)data = ipflog_clear(unit, ifs);
417 break;
418 #endif /* IPFILTER_LOG */
419 case SIOCGFRST :
420 error = fr_outobj(data, fr_fragstats(ifs), IPFOBJ_FRAGSTAT);
421 break;
422 case SIOCFRSYN :
423 if (!(mode & FWRITE))
424 error = EPERM;
425 else {
426 frsync(IPFSYNC_RESYNC, IPFSYNC_RESYNC, NULL, NULL, ifs);
427 }
428 break;
429 default :
430 error = EINVAL;
431 break;
432 }
433 SPL_X(s);
434 return error;
435 }
436
437
fr_forgetifp(ifp,ifs)438 void fr_forgetifp(ifp, ifs)
439 void *ifp;
440 ipf_stack_t *ifs;
441 {
442 register frentry_t *f;
443
444 WRITE_ENTER(&ifs->ifs_ipf_mutex);
445 for (f = ifs->ifs_ipacct[0][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_ipacct[1][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[0][ifs->ifs_fr_active]; (f != NULL);
454 f = f->fr_next)
455 if (f->fr_ifa == ifp)
456 f->fr_ifa = (void *)-1;
457 for (f = ifs->ifs_ipfilter[1][ifs->ifs_fr_active]; (f != NULL);
458 f = f->fr_next)
459 if (f->fr_ifa == ifp)
460 f->fr_ifa = (void *)-1;
461 #ifdef USE_INET6
462 for (f = ifs->ifs_ipacct6[0][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_ipacct6[1][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[0][ifs->ifs_fr_active]; (f != NULL);
471 f = f->fr_next)
472 if (f->fr_ifa == ifp)
473 f->fr_ifa = (void *)-1;
474 for (f = ifs->ifs_ipfilter6[1][ifs->ifs_fr_active]; (f != NULL);
475 f = f->fr_next)
476 if (f->fr_ifa == ifp)
477 f->fr_ifa = (void *)-1;
478 #endif
479 RWLOCK_EXIT(&ifs->ifs_ipf_mutex);
480 fr_natifpsync(IPFSYNC_OLDIFP, 4, ifp, NULL, ifs);
481 fr_natifpsync(IPFSYNC_OLDIFP, 6, ifp, NULL, ifs);
482 }
483
484
fr_resolvedest(fdp,v,ifs)485 void fr_resolvedest(fdp, v, ifs)
486 frdest_t *fdp;
487 int v;
488 ipf_stack_t *ifs;
489 {
490 fdp->fd_ifp = NULL;
491
492 if (*fdp->fd_ifname) {
493 fdp->fd_ifp = GETIFP(fdp->fd_ifname, v, ifs);
494 if (!fdp->fd_ifp)
495 fdp->fd_ifp = (struct ifnet *)-1;
496 }
497 }
498
499
500 #if defined(__sgi) && (IRIX < 60500)
no_output(ifp,m,s)501 static int no_output(ifp, m, s)
502 #else
503 # if TRU64 >= 1885
504 static int no_output (ifp, m, s, rt, cp)
505 char *cp;
506 # else
507 static int no_output(ifp, m, s, rt)
508 # endif
509 struct rtentry *rt;
510 #endif
511 struct ifnet *ifp;
512 struct mbuf *m;
513 struct sockaddr *s;
514 {
515 return 0;
516 }
517
518
519 #if defined(__sgi) && (IRIX < 60500)
write_output(ifp,m,s)520 static int write_output(ifp, m, s)
521 #else
522 # if TRU64 >= 1885
523 static int write_output (ifp, m, s, rt, cp)
524 char *cp;
525 # else
526 static int write_output(ifp, m, s, rt)
527 # endif
528 struct rtentry *rt;
529 #endif
530 struct ifnet *ifp;
531 struct mbuf *m;
532 struct sockaddr *s;
533 {
534 char fname[32];
535 mb_t *mb;
536 ip_t *ip;
537 int fd;
538
539 mb = (mb_t *)m;
540 ip = MTOD(mb, ip_t *);
541
542 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
543 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
544 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
545 sprintf(fname, "/tmp/%s", ifp->if_xname);
546 #else
547 sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
548 #endif
549 fd = open(fname, O_WRONLY|O_APPEND);
550 if (fd == -1) {
551 perror("open");
552 return -1;
553 }
554 write(fd, (char *)ip, ntohs(ip->ip_len));
555 close(fd);
556 return 0;
557 }
558
559
fr_setifpaddr(ifp,addr)560 static void fr_setifpaddr(ifp, addr)
561 struct ifnet *ifp;
562 char *addr;
563 {
564 #ifdef __sgi
565 struct in_ifaddr *ifa;
566 #else
567 struct ifaddr *ifa;
568 #endif
569
570 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
571 if (ifp->if_addrlist.tqh_first != NULL)
572 #else
573 # ifdef __sgi
574 if (ifp->in_ifaddr != NULL)
575 # else
576 if (ifp->if_addrlist != NULL)
577 # endif
578 #endif
579 return;
580
581 ifa = (struct ifaddr *)malloc(sizeof(*ifa));
582 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
583 ifp->if_addrlist.tqh_first = ifa;
584 #else
585 # ifdef __sgi
586 ifp->in_ifaddr = ifa;
587 # else
588 ifp->if_addrlist = ifa;
589 # endif
590 #endif
591
592 if (ifa != NULL) {
593 struct sockaddr_in *sin;
594
595 #ifdef __sgi
596 sin = (struct sockaddr_in *)&ifa->ia_addr;
597 #else
598 sin = (struct sockaddr_in *)&ifa->ifa_addr;
599 #endif
600 sin->sin_addr.s_addr = inet_addr(addr);
601 if (sin->sin_addr.s_addr == 0)
602 abort();
603 }
604 }
605
606 /*ARGSUSED*/
get_unit(name,v,ifs)607 struct ifnet *get_unit(name, v, ifs)
608 char *name;
609 int v;
610 ipf_stack_t *ifs;
611 {
612 struct ifnet *ifp, **ifpp, **old_ifneta;
613 char *addr;
614 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
615 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
616 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
617
618 if (name == NULL)
619 name = "anon0";
620
621 addr = strchr(name, '=');
622 if (addr != NULL)
623 *addr++ = '\0';
624
625 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
626 if (!strcmp(name, ifp->if_xname)) {
627 if (addr != NULL)
628 fr_setifpaddr(ifp, addr);
629 return ifp;
630 }
631 }
632 #else
633 char *s, ifname[LIFNAMSIZ+1];
634
635 if (name == NULL)
636 name = "anon0";
637
638 addr = strchr(name, '=');
639 if (addr != NULL)
640 *addr++ = '\0';
641
642 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
643 COPYIFNAME(ifp, ifname, 0);
644 if (!strcmp(name, ifname)) {
645 if (addr != NULL)
646 fr_setifpaddr(ifp, addr);
647 return ifp;
648 }
649 }
650 #endif
651
652 if (!ifneta) {
653 ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2);
654 if (!ifneta)
655 return NULL;
656 ifneta[1] = NULL;
657 ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp));
658 if (!ifneta[0]) {
659 free(ifneta);
660 return NULL;
661 }
662 nifs = 1;
663 } else {
664 old_ifneta = ifneta;
665 nifs++;
666 ifneta = (struct ifnet **)realloc(ifneta,
667 (nifs + 1) * sizeof(ifp));
668 if (!ifneta) {
669 free(old_ifneta);
670 nifs = 0;
671 return NULL;
672 }
673 ifneta[nifs] = NULL;
674 ifneta[nifs - 1] = (struct ifnet *)malloc(sizeof(*ifp));
675 if (!ifneta[nifs - 1]) {
676 nifs--;
677 return NULL;
678 }
679 }
680 ifp = ifneta[nifs - 1];
681
682 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
683 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
684 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
685 (void) strncpy(ifp->if_xname, name, sizeof(ifp->if_xname));
686 #else
687 for (s = name; *s && !ISDIGIT(*s); s++)
688 ;
689 if (*s && ISDIGIT(*s)) {
690 ifp->if_unit = atoi(s);
691 ifp->if_name = (char *)malloc(s - name + 1);
692 if (ifp->if_name == NULL) {
693 /*
694 * XXX do it more elegantly: free up mem,
695 * return NULL
696 */
697 perror("malloc");
698 exit(1);
699 }
700 (void) strncpy(ifp->if_name, name, s - name);
701 ifp->if_name[s - name] = '\0';
702 } else {
703 ifp->if_name = strdup(name);
704 ifp->if_unit = -1;
705 }
706 #endif
707 ifp->if_output = no_output;
708
709 if (addr != NULL) {
710 fr_setifpaddr(ifp, addr);
711 }
712
713 return ifp;
714 }
715
716
get_ifname(ifp)717 char *get_ifname(ifp)
718 struct ifnet *ifp;
719 {
720 static char ifname[LIFNAMSIZ];
721
722 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(linux) || \
723 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
724 sprintf(ifname, "%s", ifp->if_xname);
725 #else
726 sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit);
727 #endif
728 return ifname;
729 }
730
731
732
init_ifp()733 void init_ifp()
734 {
735 struct ifnet *ifp, **ifpp;
736 char fname[32];
737 int fd;
738
739 #if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
740 (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
741 (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
742 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
743 ifp->if_output = write_output;
744 sprintf(fname, "/tmp/%s", ifp->if_xname);
745 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
746 if (fd == -1)
747 perror("open");
748 else
749 close(fd);
750 }
751 #else
752
753 for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
754 ifp->if_output = write_output;
755 sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
756 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
757 if (fd == -1)
758 perror("open");
759 else
760 close(fd);
761 }
762 #endif
763 }
764
765
fr_fastroute(m,mpp,fin,fdp)766 int fr_fastroute(m, mpp, fin, fdp)
767 mb_t *m, **mpp;
768 fr_info_t *fin;
769 frdest_t *fdp;
770 {
771 struct ifnet *ifp = fdp->fd_ifp;
772 ip_t *ip = fin->fin_ip;
773
774 if (!ifp)
775 return 0; /* no routing table out here */
776
777 ip->ip_len = htons((u_short)ip->ip_len);
778 ip->ip_off = htons((u_short)(ip->ip_off | IP_MF));
779 ip->ip_sum = 0;
780 #if defined(__sgi) && (IRIX < 60500)
781 (*ifp->if_output)(ifp, (void *)ip, NULL);
782 # if TRU64 >= 1885
783 (*ifp->if_output)(ifp, (void *)m, NULL, 0, 0);
784 # else
785 (*ifp->if_output)(ifp, (void *)m, NULL, 0);
786 # endif
787 #endif
788 return 0;
789 }
790
791
fr_send_reset(fin)792 int fr_send_reset(fin)
793 fr_info_t *fin;
794 {
795 verbose("- TCP RST sent\n");
796 return 0;
797 }
798
799
fr_send_icmp_err(type,fin,dst)800 int fr_send_icmp_err(type, fin, dst)
801 int type;
802 fr_info_t *fin;
803 int dst;
804 {
805 verbose("- ICMP unreachable sent\n");
806 return 0;
807 }
808
809
frsync(command,version,nic,data,ifs)810 void frsync(command, version, nic, data, ifs)
811 int command, version;
812 void *nic;
813 char *data;
814 ipf_stack_t *ifs;
815 {
816 return;
817 }
818
819
m_freem(m)820 void m_freem(m)
821 mb_t *m;
822 {
823 return;
824 }
825
826
m_copydata(m,off,len,cp)827 void m_copydata(m, off, len, cp)
828 mb_t *m;
829 int off, len;
830 caddr_t cp;
831 {
832 bcopy((char *)m + off, cp, len);
833 }
834
835
ipfuiomove(buf,len,rwflag,uio)836 int ipfuiomove(buf, len, rwflag, uio)
837 caddr_t buf;
838 int len, rwflag;
839 struct uio *uio;
840 {
841 int left, ioc, num, offset;
842 struct iovec *io;
843 char *start;
844
845 if (rwflag == UIO_READ) {
846 left = len;
847 ioc = 0;
848
849 offset = uio->uio_offset;
850
851 while ((left > 0) && (ioc < uio->uio_iovcnt)) {
852 io = uio->uio_iov + ioc;
853 num = io->iov_len;
854 if (num > left)
855 num = left;
856 start = (char *)io->iov_base + offset;
857 if (start > (char *)io->iov_base + io->iov_len) {
858 offset -= io->iov_len;
859 ioc++;
860 continue;
861 }
862 bcopy(buf, start, num);
863 uio->uio_resid -= num;
864 uio->uio_offset += num;
865 left -= num;
866 if (left > 0)
867 ioc++;
868 }
869 if (left > 0)
870 return EFAULT;
871 }
872 return 0;
873 }
874
875
fr_newisn(fin)876 u_32_t fr_newisn(fin)
877 fr_info_t *fin;
878 {
879 static int iss_seq_off = 0;
880 u_char hash[16];
881 u_32_t newiss;
882 MD5_CTX ctx;
883
884 /*
885 * Compute the base value of the ISS. It is a hash
886 * of (saddr, sport, daddr, dport, secret).
887 */
888 MD5Init(&ctx);
889
890 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src,
891 sizeof(fin->fin_fi.fi_src));
892 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst,
893 sizeof(fin->fin_fi.fi_dst));
894 MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat));
895
896 /* MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); */
897
898 MD5Final(hash, &ctx);
899
900 memcpy(&newiss, hash, sizeof(newiss));
901
902 /*
903 * Now increment our "timer", and add it in to
904 * the computed value.
905 *
906 * XXX Use `addin'?
907 * XXX TCP_ISSINCR too large to use?
908 */
909 iss_seq_off += 0x00010000;
910 newiss += iss_seq_off;
911 return newiss;
912 }
913
914
915 /* ------------------------------------------------------------------------ */
916 /* Function: fr_nextipid */
917 /* Returns: int - 0 == success, -1 == error (packet should be droppped) */
918 /* Parameters: fin(I) - pointer to packet information */
919 /* */
920 /* Returns the next IPv4 ID to use for this packet. */
921 /* ------------------------------------------------------------------------ */
fr_nextipid(fin)922 INLINE u_short fr_nextipid(fin)
923 fr_info_t *fin;
924 {
925 static u_short ipid = 0;
926 u_short id;
927 ipf_stack_t *ifs = fin->fin_ifs;
928
929 MUTEX_ENTER(&ifs->ifs_ipf_rw);
930 id = ipid++;
931 MUTEX_EXIT(&ifs->ifs_ipf_rw);
932
933 return id;
934 }
935
936
fr_checkv4sum(fin)937 INLINE void fr_checkv4sum(fin)
938 fr_info_t *fin;
939 {
940 if (fr_checkl4sum(fin) == -1)
941 fin->fin_flx |= FI_BAD;
942 }
943
944
945 #ifdef USE_INET6
fr_checkv6sum(fin)946 INLINE void fr_checkv6sum(fin)
947 fr_info_t *fin;
948 {
949 if (fr_checkl4sum(fin) == -1)
950 fin->fin_flx |= FI_BAD;
951 }
952 #endif
953
954
955 /*
956 * See above for description, except that all addressing is in user space.
957 */
copyoutptr(src,dst,size)958 int copyoutptr(src, dst, size)
959 void *src, *dst;
960 size_t size;
961 {
962 caddr_t ca;
963
964 bcopy(dst, (char *)&ca, sizeof(ca));
965 bcopy(src, ca, size);
966 return 0;
967 }
968
969
970 /*
971 * See above for description, except that all addressing is in user space.
972 */
copyinptr(src,dst,size)973 int copyinptr(src, dst, size)
974 void *src, *dst;
975 size_t size;
976 {
977 caddr_t ca;
978
979 bcopy(src, (char *)&ca, sizeof(ca));
980 bcopy(ca, dst, size);
981 return 0;
982 }
983
984
985 /*
986 * return the first IP Address associated with an interface
987 */
fr_ifpaddr(v,atype,ifptr,inp,inpmask,ifs)988 int fr_ifpaddr(v, atype, ifptr, inp, inpmask, ifs)
989 int v, atype;
990 void *ifptr;
991 struct in_addr *inp, *inpmask;
992 ipf_stack_t *ifs;
993 {
994 struct ifnet *ifp = ifptr;
995 #ifdef __sgi
996 struct in_ifaddr *ifa;
997 #else
998 struct ifaddr *ifa;
999 #endif
1000
1001 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
1002 ifa = ifp->if_addrlist.tqh_first;
1003 #else
1004 # ifdef __sgi
1005 ifa = (struct in_ifaddr *)ifp->in_ifaddr;
1006 # else
1007 ifa = ifp->if_addrlist;
1008 # endif
1009 #endif
1010 if (ifa != NULL) {
1011 struct sockaddr_in *sin, mask;
1012
1013 mask.sin_addr.s_addr = 0xffffffff;
1014
1015 #ifdef __sgi
1016 sin = (struct sockaddr_in *)&ifa->ia_addr;
1017 #else
1018 sin = (struct sockaddr_in *)&ifa->ifa_addr;
1019 #endif
1020
1021 return fr_ifpfillv4addr(atype, sin, &mask, inp, inpmask);
1022 }
1023 return 0;
1024 }
1025
1026
1027 /*
1028 * This function is not meant to be random, rather just produce a
1029 * sequence of numbers that isn't linear to show "randomness".
1030 */
ipf_random()1031 u_32_t ipf_random()
1032 {
1033 static u_int last = 0xa5a5a5a5;
1034 static int calls = 0;
1035 int number;
1036
1037 calls++;
1038
1039 /*
1040 * These are deliberately chosen to ensure that there is some
1041 * attempt to test whether the output covers the range in test n18.
1042 */
1043 switch (calls)
1044 {
1045 case 1 :
1046 number = 0;
1047 break;
1048 case 2 :
1049 number = 4;
1050 break;
1051 case 3 :
1052 number = 3999;
1053 break;
1054 case 4 :
1055 number = 4000;
1056 break;
1057 case 5 :
1058 number = 48999;
1059 break;
1060 case 6 :
1061 number = 49000;
1062 break;
1063 default :
1064 number = last;
1065 last *= calls;
1066 last++;
1067 number ^= last;
1068 break;
1069 }
1070 return number;
1071 }
1072