]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ipfilter/ip_fil.c
This commit was generated by cvs2svn to compensate for changes in r167612,
[FreeBSD/FreeBSD.git] / contrib / ipfilter / ip_fil.c
1 /*      $FreeBSD$       */
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)
9 static const char sccsid[] = "@(#)ip_fil.c      2.41 6/5/96 (C) 1993-2000 Darren Reed";
10 static const char rcsid[] = "@(#)$Id: ip_fil.c,v 2.133.2.11 2006/03/25 11:15:30 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__
37 struct 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
136 struct rtentry;
137 #endif
138 #include "md5.h"
139
140
141 #if !defined(__osf__) && !defined(__linux__)
142 extern  struct  protosw inetsw[];
143 #endif
144
145 #include "ipt.h"
146 static  struct  ifnet **ifneta = NULL;
147 static  int     nifs = 0;
148
149 static  int     frzerostats __P((caddr_t));
150 static  void    fr_setifpaddr __P((struct ifnet *, char *));
151 void    init_ifp __P((void));
152 #if defined(__sgi) && (IRIX < 60500)
153 static int      no_output __P((struct ifnet *, struct mbuf *,
154                                struct sockaddr *));
155 static int      write_output __P((struct ifnet *, struct mbuf *,
156                                   struct sockaddr *));
157 #else
158 # if TRU64 >= 1885
159 static int      no_output __P((struct ifnet *, struct mbuf *,
160                                struct sockaddr *, struct rtentry *, char *));
161 static int      write_output __P((struct ifnet *, struct mbuf *,
162                                   struct sockaddr *, struct rtentry *, char *));
163 # else
164 static int      no_output __P((struct ifnet *, struct mbuf *,
165                                struct sockaddr *, struct rtentry *));
166 static int      write_output __P((struct ifnet *, struct mbuf *,
167                                   struct sockaddr *, struct rtentry *));
168 # endif
169 #endif
170
171
172 int iplattach()
173 {
174         fr_running = 1;
175         return 0;
176 }
177
178
179 int ipldetach()
180 {
181         fr_running = -1;
182         return 0;
183 }
184
185
186 static  int     frzerostats(data)
187 caddr_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  */
206 int iplioctl(dev, cmd, data, mode)
207 int dev;
208 ioctlcmd_t cmd;
209 caddr_t data;
210 int 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
421 void fr_forgetifp(ifp)
422 void *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)
459 static int no_output(ifp, m, s)
460 #else
461 # if TRU64 >= 1885
462 static int no_output (ifp, m, s, rt, cp)
463 char *cp;
464 # else
465 static int no_output(ifp, m, s, rt)
466 # endif
467 struct rtentry *rt;
468 #endif
469 struct ifnet *ifp;
470 struct mbuf *m;
471 struct sockaddr *s;
472 {
473         return 0;
474 }
475
476
477 #if defined(__sgi) && (IRIX < 60500)
478 static int write_output(ifp, m, s)
479 #else
480 # if TRU64 >= 1885
481 static int write_output (ifp, m, s, rt, cp)
482 char *cp;
483 # else
484 static int write_output(ifp, m, s, rt)
485 # endif
486 struct rtentry *rt;
487 #endif
488 struct ifnet *ifp;
489 struct mbuf *m;
490 struct 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
518 static void fr_setifpaddr(ifp, addr)
519 struct ifnet *ifp;
520 char *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
564 struct ifnet *get_unit(name, v)
565 char *name;
566 int 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
665 char *get_ifname(ifp)
666 struct 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
681 void 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
714 int fr_fastroute(m, mpp, fin, fdp)
715 mb_t *m, **mpp;
716 fr_info_t *fin;
717 frdest_t *fdp;
718 {
719         struct ifnet *ifp = fdp->fd_ifp;
720         ip_t *ip = fin->fin_ip;
721         int error = 0;
722         frentry_t *fr;
723         void *sifp;
724
725         if (!ifp)
726                 return 0;       /* no routing table out here */
727
728         fr = fin->fin_fr;
729         ip->ip_sum = 0;
730
731         if (fin->fin_out == 0) {
732                 sifp = fin->fin_ifp;
733                 fin->fin_ifp = ifp;
734                 fin->fin_out = 1;
735                 (void) fr_acctpkt(fin, NULL);
736                 fin->fin_fr = NULL;
737                 if (!fr || !(fr->fr_flags & FR_RETMASK)) {
738                         u_32_t pass;
739
740                         (void) fr_checkstate(fin, &pass);
741                 }
742
743                 switch (fr_checknatout(fin, NULL))
744                 {
745                 case 0 :
746                         break;
747                 case 1 :
748                         ip->ip_sum = 0;
749                         break;
750                 case -1 :
751                         error = -1;
752                         goto done;
753                         break;
754                 }
755
756                 fin->fin_ifp = sifp;
757                 fin->fin_out = 0;
758         }
759
760 #if defined(__sgi) && (IRIX < 60500)
761         (*ifp->if_output)(ifp, (void *)ip, NULL);
762 # if TRU64 >= 1885
763         (*ifp->if_output)(ifp, (void *)m, NULL, 0, 0);
764 # else
765         (*ifp->if_output)(ifp, (void *)m, NULL, 0);
766 # endif
767 #endif
768 done:
769         return error;
770 }
771
772
773 int fr_send_reset(fin)
774 fr_info_t *fin;
775 {
776         verbose("- TCP RST sent\n");
777         return 0;
778 }
779
780
781 int fr_send_icmp_err(type, fin, dst)
782 int type;
783 fr_info_t *fin;
784 int dst;
785 {
786         verbose("- ICMP unreachable sent\n");
787         return 0;
788 }
789
790
791 void frsync(ifp)
792 void *ifp;
793 {
794         return;
795 }
796
797
798 void m_freem(m)
799 mb_t *m;
800 {
801         return;
802 }
803
804
805 void m_copydata(m, off, len, cp)
806 mb_t *m;
807 int off, len;
808 caddr_t cp;
809 {
810         bcopy((char *)m + off, cp, len);
811 }
812
813
814 int ipfuiomove(buf, len, rwflag, uio)
815 caddr_t buf;
816 int len, rwflag;
817 struct uio *uio;
818 {
819         int left, ioc, num, offset;
820         struct iovec *io;
821         char *start;
822
823         if (rwflag == UIO_READ) {
824                 left = len;
825                 ioc = 0;
826
827                 offset = uio->uio_offset;
828
829                 while ((left > 0) && (ioc < uio->uio_iovcnt)) {
830                         io = uio->uio_iov + ioc;
831                         num = io->iov_len;
832                         if (num > left)
833                                 num = left;
834                         start = (char *)io->iov_base + offset;
835                         if (start > (char *)io->iov_base + io->iov_len) {
836                                 offset -= io->iov_len;
837                                 ioc++;
838                                 continue;
839                         }
840                         bcopy(buf, start, num);
841                         uio->uio_resid -= num;
842                         uio->uio_offset += num;
843                         left -= num;
844                         if (left > 0)
845                                 ioc++;
846                 }
847                 if (left > 0)
848                         return EFAULT;
849         }
850         return 0;
851 }
852
853
854 u_32_t fr_newisn(fin)
855 fr_info_t *fin;
856 {
857         static int iss_seq_off = 0;
858         u_char hash[16];
859         u_32_t newiss;
860         MD5_CTX ctx;
861
862         /*
863          * Compute the base value of the ISS.  It is a hash
864          * of (saddr, sport, daddr, dport, secret).
865          */
866         MD5Init(&ctx);
867
868         MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src,
869                   sizeof(fin->fin_fi.fi_src));
870         MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst,
871                   sizeof(fin->fin_fi.fi_dst));
872         MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat));
873
874         /* MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); */
875
876         MD5Final(hash, &ctx);
877
878         memcpy(&newiss, hash, sizeof(newiss));
879
880         /*
881          * Now increment our "timer", and add it in to
882          * the computed value.
883          *
884          * XXX Use `addin'?
885          * XXX TCP_ISSINCR too large to use?
886          */
887         iss_seq_off += 0x00010000;
888         newiss += iss_seq_off;
889         return newiss;
890 }
891
892
893 /* ------------------------------------------------------------------------ */
894 /* Function:    fr_nextipid                                                 */
895 /* Returns:     int - 0 == success, -1 == error (packet should be droppped) */
896 /* Parameters:  fin(I) - pointer to packet information                      */
897 /*                                                                          */
898 /* Returns the next IPv4 ID to use for this packet.                         */
899 /* ------------------------------------------------------------------------ */
900 INLINE u_short fr_nextipid(fin)
901 fr_info_t *fin;
902 {
903         static u_short ipid = 0;
904         u_short id;
905
906         MUTEX_ENTER(&ipf_rw);
907         id = ipid++;
908         MUTEX_EXIT(&ipf_rw);
909
910         return id;
911 }
912
913
914 INLINE void fr_checkv4sum(fin)
915 fr_info_t *fin;
916 {
917         if (fr_checkl4sum(fin) == -1)
918                 fin->fin_flx |= FI_BAD;
919 }
920
921
922 #ifdef  USE_INET6
923 INLINE void fr_checkv6sum(fin)
924 fr_info_t *fin;
925 {
926         if (fr_checkl4sum(fin) == -1)
927                 fin->fin_flx |= FI_BAD;
928 }
929 #endif
930
931
932 /*
933  * See above for description, except that all addressing is in user space.
934  */
935 int copyoutptr(src, dst, size)
936 void *src, *dst;
937 size_t size;
938 {
939         caddr_t ca;
940
941         bcopy(dst, (char *)&ca, sizeof(ca));
942         bcopy(src, ca, size);
943         return 0;
944 }
945
946
947 /*
948  * See above for description, except that all addressing is in user space.
949  */
950 int copyinptr(src, dst, size)
951 void *src, *dst;
952 size_t size;
953 {
954         caddr_t ca;
955
956         bcopy(src, (char *)&ca, sizeof(ca));
957         bcopy(ca, dst, size);
958         return 0;
959 }
960
961
962 /*
963  * return the first IP Address associated with an interface
964  */
965 int fr_ifpaddr(v, atype, ifptr, inp, inpmask)
966 int v, atype;
967 void *ifptr;
968 struct in_addr *inp, *inpmask;
969 {
970         struct ifnet *ifp = ifptr;
971 #ifdef __sgi
972         struct in_ifaddr *ifa;
973 #else
974         struct ifaddr *ifa;
975 #endif
976
977 #if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
978         ifa = ifp->if_addrlist.tqh_first;
979 #else
980 # ifdef __sgi
981         ifa = (struct in_ifaddr *)ifp->in_ifaddr;
982 # else
983         ifa = ifp->if_addrlist;
984 # endif
985 #endif
986         if (ifa != NULL) {
987                 struct sockaddr_in *sin, mask;
988
989                 mask.sin_addr.s_addr = 0xffffffff;
990
991 #ifdef __sgi
992                 sin = (struct sockaddr_in *)&ifa->ia_addr;
993 #else
994                 sin = (struct sockaddr_in *)&ifa->ifa_addr;
995 #endif
996
997                 return fr_ifpfillv4addr(atype, sin, &mask, inp, inpmask);
998         }
999         return 0;
1000 }