]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ipfilter/ip_fil.c
This commit was generated by cvs2svn to compensate for changes in r58809,
[FreeBSD/FreeBSD.git] / contrib / ipfilter / ip_fil.c
1 /*
2  * Copyright (C) 1993-1998 by Darren Reed.
3  *
4  * Redistribution and use in source and binary forms are permitted
5  * provided that this notice is preserved and due credit is given
6  * to the original author and the contributors.
7  */
8 #if !defined(lint)
9 static const char sccsid[] = "@(#)ip_fil.c      2.41 6/5/96 (C) 1993-1995 Darren Reed";
10 static const char rcsid[] = "@(#)$Id: ip_fil.c,v 2.4.2.16 2000/01/16 10:12:42 darrenr Exp $";
11 #endif
12
13 #ifndef SOLARIS
14 #define SOLARIS (defined(sun) && (defined(__svr4__) || defined(__SVR4)))
15 #endif
16
17 #if defined(KERNEL) && !defined(_KERNEL)
18 # define        _KERNEL
19 #endif
20 #include <sys/param.h>
21 #if defined(__NetBSD__) && (NetBSD >= 199905) && !defined(IPFILTER_LKM) && \
22     defined(_KERNEL)
23 # include "opt_ipfilter_log.h"
24 #endif
25 #ifdef  __FreeBSD__
26 # if defined(_KERNEL) && !defined(IPFILTER_LKM)
27 #  include <sys/osreldate.h>
28 # else
29 #  include <osreldate.h>
30 # endif
31 #endif
32 #ifndef _KERNEL
33 # include <stdio.h>
34 # include <string.h>
35 # include <stdlib.h>
36 # include <ctype.h>
37 # include <fcntl.h>
38 #endif
39 #include <sys/errno.h>
40 #include <sys/types.h>
41 #include <sys/file.h>
42 #if __FreeBSD_version >= 220000 && defined(_KERNEL)
43 # include <sys/fcntl.h>
44 # include <sys/filio.h>
45 #else
46 # include <sys/ioctl.h>
47 #endif
48 #include <sys/time.h>
49 #ifdef  _KERNEL
50 # include <sys/systm.h>
51 #endif
52 #include <sys/uio.h>
53 #if !SOLARIS
54 # if (NetBSD > 199609) || (OpenBSD > 199603) || (__FreeBSD_version >= 300000)
55 #  include <sys/dirent.h>
56 # else
57 #  include <sys/dir.h>
58 # endif
59 # include <sys/mbuf.h>
60 #else
61 # include <sys/filio.h>
62 #endif
63 #include <sys/protosw.h>
64 #include <sys/socket.h>
65
66 #include <net/if.h>
67 #ifdef sun
68 # include <net/af.h>
69 #endif
70 #if __FreeBSD_version >= 300000
71 # include <net/if_var.h>
72 # if defined(_KERNEL) && !defined(IPFILTER_LKM)
73 #  include "opt_ipfilter.h"
74 # endif
75 #endif
76 #ifdef __sgi
77 #include <sys/debug.h>
78 # ifdef IFF_DRVRLOCK /* IRIX6 */
79 #include <sys/hashing.h>
80 # endif
81 #endif
82 #include <net/route.h>
83 #include <netinet/in.h>
84 #if !(defined(__sgi) && !defined(IFF_DRVRLOCK)) /* IRIX < 6 */
85 # include <netinet/in_var.h>
86 #endif
87 #include <netinet/in_systm.h>
88 #include <netinet/ip.h>
89 #include <netinet/ip_var.h>
90 #include <netinet/tcp.h>
91 #include <netinet/udp.h>
92 #include <netinet/tcpip.h>
93 #include <netinet/ip_icmp.h>
94 #ifndef _KERNEL
95 # include <unistd.h>
96 # include <syslog.h>
97 #endif
98 #include "netinet/ip_compat.h"
99 #include "netinet/ip_fil.h"
100 #include "netinet/ip_proxy.h"
101 #include "netinet/ip_nat.h"
102 #include "netinet/ip_frag.h"
103 #include "netinet/ip_state.h"
104 #include "netinet/ip_auth.h"
105 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
106 # include <sys/malloc.h>
107 #endif
108 #ifndef MIN
109 # define        MIN(a,b)        (((a)<(b))?(a):(b))
110 #endif
111 #if !SOLARIS && defined(_KERNEL) && !defined(__sgi)
112 # include <sys/kernel.h>
113 extern  int     ip_optcopy __P((struct ip *, struct ip *));
114 #endif
115
116
117 extern  struct  protosw inetsw[];
118
119 #ifndef _KERNEL
120 # include "ipt.h"
121 static  struct  ifnet **ifneta = NULL;
122 static  int     nifs = 0;
123 #else
124 # if    (BSD < 199306) || defined(__sgi)
125 extern  int     tcp_ttl;
126 # endif
127 #endif
128
129 int     ipl_unreach = ICMP_UNREACH_FILTER;
130 u_long  ipl_frouteok[2] = {0, 0};
131
132 static  void    frzerostats __P((caddr_t));
133 #if defined(__NetBSD__) || defined(__OpenBSD__)
134 static  int     frrequest __P((int, u_long, caddr_t, int));
135 #else
136 static  int     frrequest __P((int, int, caddr_t, int));
137 #endif
138 #ifdef  _KERNEL
139 static  int     (*fr_savep) __P((ip_t *, int, void *, int, struct mbuf **));
140 static  int     send_ip __P((struct mbuf *, ip_t *));
141 # ifdef __sgi
142 extern  kmutex_t        ipf_rw;
143 extern  KRWLOCK_T       ipf_mutex;
144 # endif
145 #else
146 int     ipllog __P((void));
147 void    init_ifp __P((void));
148 # ifdef __sgi
149 static int      no_output __P((struct ifnet *, struct mbuf *,
150                                struct sockaddr *));
151 static int      write_output __P((struct ifnet *, struct mbuf *,
152                                   struct sockaddr *));
153 # else
154 static int      no_output __P((struct ifnet *, struct mbuf *,
155                                struct sockaddr *, struct rtentry *));
156 static int      write_output __P((struct ifnet *, struct mbuf *,
157                                   struct sockaddr *, struct rtentry *));
158 # endif
159 #endif
160 #if defined(IPFILTER_LKM)
161 int     fr_running = 1;
162 #else
163 int     fr_running = 0;
164 #endif
165
166 #if (__FreeBSD_version >= 300000) && defined(_KERNEL)
167 struct callout_handle ipfr_slowtimer_ch;
168 #endif
169
170 #if (_BSDI_VERSION >= 199510) && defined(_KERNEL)
171 # include <sys/device.h>
172 # include <sys/conf.h>
173
174 struct cfdriver iplcd = {
175         NULL, "ipl", NULL, NULL, DV_DULL, 0
176 };
177
178 struct devsw iplsw = {
179         &iplcd,
180         iplopen, iplclose, iplread, nowrite, iplioctl, noselect, nommap,
181         nostrat, nodump, nopsize, 0,
182         nostop
183 };
184 #endif /* _BSDI_VERSION >= 199510  && _KERNEL */
185
186 #if defined(__NetBSD__) || defined(__OpenBSD__)  || (_BSDI_VERSION >= 199701)
187 # include <sys/conf.h>
188 # if defined(NETBSD_PF)
189 #  include <net/pfil.h>
190 /*
191  * We provide the fr_checkp name just to minimize changes later.
192  */
193 int (*fr_checkp) __P((ip_t *ip, int hlen, void *ifp, int out, mb_t **mp));
194 # endif /* NETBSD_PF */
195 #endif /* __NetBSD__ */
196
197 #ifdef  _KERNEL
198 # if    defined(IPFILTER_LKM) && !defined(__sgi)
199 int iplidentify(s)
200 char *s;
201 {
202         if (strcmp(s, "ipl") == 0)
203                 return 1;
204         return 0;
205 }
206 # endif /* IPFILTER_LKM */
207
208
209 /*
210  * Try to detect the case when compiling for NetBSD with pseudo-device
211  */
212 # if defined(__NetBSD__) && defined(PFIL_HOOKS)
213 void
214 ipfilterattach(count)
215 int count;
216 {
217         if (iplattach() != 0)
218                 printf("IP Filter failed to attach\n");
219 }
220 # endif
221
222
223 int iplattach()
224 {
225         char *defpass;
226         int s;
227 # ifdef __sgi
228         int error;
229 # endif
230
231         SPL_NET(s);
232         if (fr_running || (fr_checkp == fr_check)) {
233                 printf("IP Filter: already initialized\n");
234                 SPL_X(s);
235                 return EBUSY;
236         }
237
238 # ifdef IPFILTER_LOG
239         ipflog_init();
240 # endif
241         if (nat_init() == -1)
242                 return -1;
243         if (fr_stateinit() == -1)
244                 return -1;
245         if (appr_init() == -1)
246                 return -1;
247
248 # ifdef NETBSD_PF
249         pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT);
250 # endif
251
252 # ifdef __sgi
253         error = ipfilter_sgi_attach();
254         if (error) {
255                 SPL_X(s);
256                 return error;
257         }
258 # endif
259
260         bzero((char *)frcache, sizeof(frcache));
261         fr_savep = fr_checkp;
262         fr_checkp = fr_check;
263
264         SPL_X(s);
265         if (fr_pass & FR_PASS)
266                 defpass = "pass";
267         else if (fr_pass & FR_BLOCK)
268                 defpass = "block";
269         else
270                 defpass = "no-match -> block";
271
272         printf("IP Filter: initialized.  Default = %s all, Logging = %s\n",
273                 defpass,
274 # ifdef IPFILTER_LOG
275                 "enabled");
276 # else
277                 "disabled");
278 # endif
279         printf("%s\n", ipfilter_version);
280 #ifdef  _KERNEL
281 # if (__FreeBSD_version >= 300000) && defined(_KERNEL)
282         ipfr_slowtimer_ch = timeout(ipfr_slowtimer, NULL, hz/2);
283 # else
284         timeout(ipfr_slowtimer, NULL, hz/2);
285 # endif
286 #endif
287         fr_running = 1;
288         return 0;
289 }
290
291
292 /*
293  * Disable the filter by removing the hooks from the IP input/output
294  * stream.
295  */
296 int ipldetach()
297 {
298         int s, i = FR_INQUE|FR_OUTQUE;
299
300 #ifdef  _KERNEL
301 # if (__FreeBSD_version >= 300000)
302         untimeout(ipfr_slowtimer, NULL, ipfr_slowtimer_ch);
303 # else
304 #  ifdef __sgi
305         untimeout(ipfr_slowtimer);
306 #  else
307         untimeout(ipfr_slowtimer, NULL);
308 #  endif
309 # endif
310 #endif
311         SPL_NET(s);
312         if (!fr_running)
313         {
314                 printf("IP Filter: not initialized\n");
315                 SPL_X(s);
316                 return 0;
317         }
318
319         fr_checkp = fr_savep;
320         i = frflush(IPL_LOGIPF, i);
321         fr_running = 0;
322
323 # ifdef NETBSD_PF
324         pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT);
325 # endif
326
327 # ifdef __sgi
328         ipfilter_sgi_detach();
329 # endif
330
331         ipfr_unload();
332         ip_natunload();
333         fr_stateunload();
334         fr_authunload();
335
336         SPL_X(s);
337         return 0;
338 }
339 #endif /* _KERNEL */
340
341
342 static  void    frzerostats(data)
343 caddr_t data;
344 {
345         friostat_t fio;
346
347         bcopy((char *)frstats, (char *)fio.f_st,
348                 sizeof(struct filterstats) * 2);
349         fio.f_fin[0] = ipfilter[0][0];
350         fio.f_fin[1] = ipfilter[0][1];
351         fio.f_fout[0] = ipfilter[1][0];
352         fio.f_fout[1] = ipfilter[1][1];
353         fio.f_acctin[0] = ipacct[0][0];
354         fio.f_acctin[1] = ipacct[0][1];
355         fio.f_acctout[0] = ipacct[1][0];
356         fio.f_acctout[1] = ipacct[1][1];
357         fio.f_active = fr_active;
358         fio.f_froute[0] = ipl_frouteok[0];
359         fio.f_froute[1] = ipl_frouteok[1];
360         IWCOPY((caddr_t)&fio, data, sizeof(fio));
361         bzero((char *)frstats, sizeof(*frstats) * 2);
362 }
363
364
365 /*
366  * Filter ioctl interface.
367  */
368 #ifdef __sgi
369 int IPL_EXTERN(ioctl)(dev_t dev, int cmd, caddr_t data, int mode
370 # ifdef _KERNEL
371         , cred_t *cp, int *rp
372 # endif
373 )
374 #else
375 int IPL_EXTERN(ioctl)(dev, cmd, data, mode
376 #if ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || (NetBSD >= 199511) || \
377      (__FreeBSD_version >= 220000) || defined(__OpenBSD__)) && defined(_KERNEL)
378 , p)
379 struct proc *p;
380 #else
381 )
382 #endif
383 dev_t dev;
384 #if defined(__NetBSD__) || defined(__OpenBSD__) || \
385          (_BSDI_VERSION >= 199701) || (__FreeBSD_version >= 300000)
386 u_long cmd;
387 #else
388 int cmd;
389 #endif
390 caddr_t data;
391 int mode;
392 #endif /* __sgi */
393 {
394 #if defined(_KERNEL) && !SOLARIS
395         int s;
396 #endif
397         int error = 0, unit = 0, tmp;
398
399 #if (BSD >= 199306) && defined(_KERNEL)
400         if ((securelevel >= 2) && (mode & FWRITE))
401                 return EPERM;
402 #endif
403 #ifdef  _KERNEL
404         unit = GET_MINOR(dev);
405         if ((IPL_LOGMAX < unit) || (unit < 0))
406                 return ENXIO;
407 #else
408         unit = dev;
409 #endif
410
411         SPL_NET(s);
412
413         if (unit == IPL_LOGNAT) {
414                 if (!fr_running)
415                         return EIO;
416                 error = nat_ioctl(data, cmd, mode);
417                 SPL_X(s);
418                 return error;
419         }
420         if (unit == IPL_LOGSTATE) {
421                 if (!fr_running)
422                         return EIO;
423                 error = fr_state_ioctl(data, cmd, mode);
424                 SPL_X(s);
425                 return error;
426         }
427         switch (cmd) {
428         case FIONREAD :
429 #ifdef IPFILTER_LOG
430                 IWCOPY((caddr_t)&iplused[IPL_LOGIPF], (caddr_t)data,
431                        sizeof(iplused[IPL_LOGIPF]));
432 #endif
433                 break;
434 #if !defined(IPFILTER_LKM) && defined(_KERNEL)
435         case SIOCFRENB :
436         {
437                 u_int   enable;
438
439                 if (!(mode & FWRITE))
440                         error = EPERM;
441                 else {
442                         IRCOPY(data, (caddr_t)&enable, sizeof(enable));
443                         if (enable)
444                                 error = iplattach();
445                         else
446                                 error = ipldetach();
447                 }
448                 break;
449         }
450 #endif
451         case SIOCSETFF :
452                 if (!(mode & FWRITE))
453                         error = EPERM;
454                 else
455                         IRCOPY(data, (caddr_t)&fr_flags, sizeof(fr_flags));
456                 break;
457         case SIOCGETFF :
458                 IWCOPY((caddr_t)&fr_flags, data, sizeof(fr_flags));
459                 break;
460         case SIOCINAFR :
461         case SIOCRMAFR :
462         case SIOCADAFR :
463         case SIOCZRLST :
464                 if (!(mode & FWRITE))
465                         error = EPERM;
466                 else
467                         error = frrequest(unit, cmd, data, fr_active);
468                 break;
469         case SIOCINIFR :
470         case SIOCRMIFR :
471         case SIOCADIFR :
472                 if (!(mode & FWRITE))
473                         error = EPERM;
474                 else
475                         error = frrequest(unit, cmd, data, 1 - fr_active);
476                 break;
477         case SIOCSWAPA :
478                 if (!(mode & FWRITE))
479                         error = EPERM;
480                 else {
481                         bzero((char *)frcache, sizeof(frcache[0]) * 2);
482                         *(u_int *)data = fr_active;
483                         fr_active = 1 - fr_active;
484                 }
485                 break;
486         case SIOCGETFS :
487         {
488                 struct  friostat        fio;
489
490                 bcopy((char *)frstats, (char *)fio.f_st,
491                         sizeof(struct filterstats) * 2);
492                 fio.f_fin[0] = ipfilter[0][0];
493                 fio.f_fin[1] = ipfilter[0][1];
494                 fio.f_fout[0] = ipfilter[1][0];
495                 fio.f_fout[1] = ipfilter[1][1];
496                 fio.f_acctin[0] = ipacct[0][0];
497                 fio.f_acctin[1] = ipacct[0][1];
498                 fio.f_acctout[0] = ipacct[1][0];
499                 fio.f_acctout[1] = ipacct[1][1];
500                 fio.f_auth = ipauth;
501                 fio.f_active = fr_active;
502                 fio.f_froute[0] = ipl_frouteok[0];
503                 fio.f_froute[1] = ipl_frouteok[1];
504                 fio.f_running = fr_running;
505                 fio.f_groups[0][0] = ipfgroups[0][0];
506                 fio.f_groups[0][1] = ipfgroups[0][1];
507                 fio.f_groups[1][0] = ipfgroups[1][0];
508                 fio.f_groups[1][1] = ipfgroups[1][1];
509                 fio.f_groups[2][0] = ipfgroups[2][0];
510                 fio.f_groups[2][1] = ipfgroups[2][1];
511 #ifdef  IPFILTER_LOG
512                 fio.f_logging = 1;
513 #else
514                 fio.f_logging = 0;
515 #endif
516                 fio.f_defpass = fr_pass;
517                 strncpy(fio.f_version, ipfilter_version,
518                         sizeof(fio.f_version));
519                 IWCOPY((caddr_t)&fio, data, sizeof(fio));
520                 break;
521         }
522         case    SIOCFRZST :
523                 if (!(mode & FWRITE))
524                         error = EPERM;
525                 else
526                         frzerostats(data);
527                 break;
528         case    SIOCIPFFL :
529                 if (!(mode & FWRITE))
530                         error = EPERM;
531                 else {
532                         IRCOPY(data, (caddr_t)&tmp, sizeof(tmp));
533                         tmp = frflush(unit, tmp);
534                         IWCOPY((caddr_t)&tmp, data, sizeof(tmp));
535                 }
536                 break;
537 #ifdef  IPFILTER_LOG
538         case    SIOCIPFFB :
539                 if (!(mode & FWRITE))
540                         error = EPERM;
541                 else
542                         *(int *)data = ipflog_clear(unit);
543                 break;
544 #endif /* IPFILTER_LOG */
545         case SIOCGFRST :
546                 IWCOPY((caddr_t)ipfr_fragstats(), data, sizeof(ipfrstat_t));
547                 break;
548         case SIOCAUTHW :
549         case SIOCAUTHR :
550                 if (!(mode & FWRITE)) {
551                         error = EPERM;
552                         break;
553                 }
554         case SIOCATHST :
555                 error = fr_auth_ioctl(data, cmd, NULL, NULL);
556                 break;
557         case SIOCFRSYN :
558                 if (!(mode & FWRITE))
559                         error = EPERM;
560                 else {
561 #if defined(_KERNEL) && defined(__sgi)
562                         ipfsync();
563 #endif
564                         frsync();
565                 }
566                 break;
567         default :
568                 error = EINVAL;
569                 break;
570         }
571         SPL_X(s);
572         return error;
573 }
574
575
576 void fr_forgetifp(ifp)
577 void *ifp;
578 {
579         register frentry_t *f;
580
581         WRITE_ENTER(&ipf_mutex);
582         for (f = ipacct[0][fr_active]; (f != NULL); f = f->fr_next)
583                 if (f->fr_ifa == ifp)
584                         f->fr_ifa = (void *)-1;
585         for (f = ipacct[1][fr_active]; (f != NULL); f = f->fr_next)
586                 if (f->fr_ifa == ifp)
587                         f->fr_ifa = (void *)-1;
588         for (f = ipfilter[0][fr_active]; (f != NULL); f = f->fr_next)
589                 if (f->fr_ifa == ifp)
590                         f->fr_ifa = (void *)-1;
591         for (f = ipfilter[1][fr_active]; (f != NULL); f = f->fr_next)
592                 if (f->fr_ifa == ifp)
593                         f->fr_ifa = (void *)-1;
594         RWLOCK_EXIT(&ipf_mutex);
595         ip_natsync(ifp);
596 }
597
598
599 static int frrequest(unit, req, data, set)
600 int unit;
601 #if defined(__NetBSD__) || defined(__OpenBSD__)
602 u_long req;
603 #else
604 int req;
605 #endif
606 int set;
607 caddr_t data;
608 {
609         register frentry_t *fp, *f, **fprev;
610         register frentry_t **ftail;
611         frentry_t frd;
612         frdest_t *fdp;
613         frgroup_t *fg = NULL;
614         int error = 0, in;
615         u_int group;
616
617         fp = &frd;
618         IRCOPY(data, (caddr_t)fp, sizeof(*fp));
619         fp->fr_ref = 0;
620
621         /*
622          * Check that the group number does exist and that if a head group
623          * has been specified, doesn't exist.
624          */
625         if ((req != SIOCZRLST) && fp->fr_grhead &&
626             fr_findgroup((u_int)fp->fr_grhead, fp->fr_flags, unit, set, NULL))
627                 return EEXIST;
628         if ((req != SIOCZRLST) && fp->fr_group &&
629             !fr_findgroup((u_int)fp->fr_group, fp->fr_flags, unit, set, NULL))
630                 return ESRCH;
631
632         in = (fp->fr_flags & FR_INQUE) ? 0 : 1;
633
634         if (unit == IPL_LOGAUTH)
635                 ftail = fprev = &ipauth;
636         else if (fp->fr_flags & FR_ACCOUNT)
637                 ftail = fprev = &ipacct[in][set];
638         else if (fp->fr_flags & (FR_OUTQUE|FR_INQUE))
639                 ftail = fprev = &ipfilter[in][set];
640         else
641                 return ESRCH;
642
643         if ((group = fp->fr_group)) {
644                 if (!(fg = fr_findgroup(group, fp->fr_flags, unit, set, NULL)))
645                         return ESRCH;
646                 ftail = fprev = fg->fg_start;
647         }
648
649         bzero((char *)frcache, sizeof(frcache[0]) * 2);
650
651         if (*fp->fr_ifname) {
652                 fp->fr_ifa = GETUNIT(fp->fr_ifname);
653                 if (!fp->fr_ifa)
654                         fp->fr_ifa = (void *)-1;
655         }
656 #if BSD >= 199306
657         if (*fp->fr_oifname) {
658                 fp->fr_oifa = GETUNIT(fp->fr_oifname);
659                 if (!fp->fr_oifa)
660                         fp->fr_oifa = (void *)-1;
661         }
662 #endif
663
664         fdp = &fp->fr_dif;
665         fp->fr_flags &= ~FR_DUP;
666         if (*fdp->fd_ifname) {
667                 fdp->fd_ifp = GETUNIT(fdp->fd_ifname);
668                 if (!fdp->fd_ifp)
669                         fdp->fd_ifp = (struct ifnet *)-1;
670                 else
671                         fp->fr_flags |= FR_DUP;
672         }
673
674         fdp = &fp->fr_tif;
675         if (*fdp->fd_ifname) {
676                 fdp->fd_ifp = GETUNIT(fdp->fd_ifname);
677                 if (!fdp->fd_ifp)
678                         fdp->fd_ifp = (struct ifnet *)-1;
679         }
680
681         /*
682          * Look for a matching filter rule, but don't include the next or
683          * interface pointer in the comparison (fr_next, fr_ifa).
684          */
685         for (; (f = *ftail); ftail = &f->fr_next)
686                 if (bcmp((char *)&f->fr_ip, (char *)&fp->fr_ip,
687                          FR_CMPSIZ) == 0)
688                         break;
689
690         /*
691          * If zero'ing statistics, copy current to caller and zero.
692          */
693         if (req == SIOCZRLST) {
694                 if (!f)
695                         return ESRCH;
696                 IWCOPY((caddr_t)f, data, sizeof(*f));
697                 f->fr_hits = 0;
698                 f->fr_bytes = 0;
699                 return 0;
700         }
701
702         if (!f) {
703                 if (req != SIOCINAFR && req != SIOCINIFR)
704                         while ((f = *ftail))
705                                 ftail = &f->fr_next;
706                 else {
707                         if (fp->fr_hits) {
708                                 ftail = fprev;
709                                 while (--fp->fr_hits && (f = *ftail))
710                                         ftail = &f->fr_next;
711                         }
712                         f = NULL;
713                 }
714         }
715
716         if (req == SIOCDELFR || req == SIOCRMIFR) {
717                 if (!f)
718                         error = ESRCH;
719                 else {
720                         if (f->fr_ref > 1)
721                                 return EBUSY;
722                         if (fg && fg->fg_head)
723                                 fg->fg_head->fr_ref--;
724                         if (unit == IPL_LOGAUTH)
725                                 return fr_auth_ioctl(data, req, f, ftail);
726                         if (f->fr_grhead)
727                                 fr_delgroup((u_int)f->fr_grhead, fp->fr_flags,
728                                             unit, set);
729                         fixskip(fprev, f, -1);
730                         *ftail = f->fr_next;
731                         KFREE(f);
732                 }
733         } else {
734                 if (f)
735                         error = EEXIST;
736                 else {
737                         if (unit == IPL_LOGAUTH)
738                                 return fr_auth_ioctl(data, req, fp, ftail);
739                         KMALLOC(f, frentry_t *);
740                         if (f != NULL) {
741                                 if (fg && fg->fg_head)
742                                         fg->fg_head->fr_ref++;
743                                 bcopy((char *)fp, (char *)f, sizeof(*f));
744                                 f->fr_ref = 1;
745                                 f->fr_hits = 0;
746                                 f->fr_next = *ftail;
747                                 *ftail = f;
748                                 if (req == SIOCINIFR || req == SIOCINAFR)
749                                         fixskip(fprev, f, 1);
750                                 f->fr_grp = NULL;
751                                 if ((group = f->fr_grhead))
752                                         fg = fr_addgroup(group, f, unit, set);
753                         } else
754                                 error = ENOMEM;
755                 }
756         }
757         return (error);
758 }
759
760
761 #ifdef  _KERNEL
762 /*
763  * routines below for saving IP headers to buffer
764  */
765 # ifdef __sgi
766 #  ifdef _KERNEL
767 int IPL_EXTERN(open)(dev_t *pdev, int flags, int devtype, cred_t *cp)
768 #  else
769 int IPL_EXTERN(open)(dev_t dev, int flags)
770 #  endif
771 # else
772 int IPL_EXTERN(open)(dev, flags
773 #  if ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || (NetBSD >= 199511) || \
774      (__FreeBSD_version >= 220000) || defined(__OpenBSD__)) && defined(_KERNEL)
775 , devtype, p)
776 int devtype;
777 struct proc *p;
778 #  else
779 )
780 #  endif
781 dev_t dev;
782 int flags;
783 # endif /* __sgi */
784 {
785 # if defined(__sgi) && defined(_KERNEL)
786         u_int min = geteminor(*pdev);
787 # else
788         u_int min = GET_MINOR(dev);
789 # endif
790
791         if (IPL_LOGMAX < min)
792                 min = ENXIO;
793         else
794                 min = 0;
795         return min;
796 }
797
798
799 # ifdef __sgi
800 int IPL_EXTERN(close)(dev_t dev, int flags, int devtype, cred_t *cp)
801 #else
802 int IPL_EXTERN(close)(dev, flags
803 #  if ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || (NetBSD >= 199511) || \
804      (__FreeBSD_version >= 220000) || defined(__OpenBSD__)) && defined(_KERNEL)
805 , devtype, p)
806 int devtype;
807 struct proc *p;
808 #  else
809 )
810 #  endif
811 dev_t dev;
812 int flags;
813 # endif /* __sgi */
814 {
815         u_int   min = GET_MINOR(dev);
816
817         if (IPL_LOGMAX < min)
818                 min = ENXIO;
819         else
820                 min = 0;
821         return min;
822 }
823
824 /*
825  * iplread/ipllog
826  * both of these must operate with at least splnet() lest they be
827  * called during packet processing and cause an inconsistancy to appear in
828  * the filter lists.
829  */
830 # ifdef __sgi
831 int IPL_EXTERN(read)(dev_t dev, uio_t *uio, cred_t *crp)
832 # else
833 #  if BSD >= 199306
834 int IPL_EXTERN(read)(dev, uio, ioflag)
835 int ioflag;
836 #  else
837 int IPL_EXTERN(read)(dev, uio)
838 #  endif
839 dev_t dev;
840 register struct uio *uio;
841 # endif /* __sgi */
842 {
843 # ifdef IPFILTER_LOG
844         return ipflog_read(GET_MINOR(dev), uio);
845 # else
846         return ENXIO;
847 # endif
848 }
849
850
851 /*
852  * send_reset - this could conceivably be a call to tcp_respond(), but that
853  * requires a large amount of setting up and isn't any more efficient.
854  */
855 int send_reset(fin, oip)
856 fr_info_t *fin;
857 struct ip *oip;
858 {
859         struct tcphdr *tcp, *tcp2;
860         struct tcpiphdr *tp;
861         struct mbuf *m;
862         int tlen = 0;
863         ip_t *ip;
864
865         tcp = (struct tcphdr *)fin->fin_dp;
866         if (tcp->th_flags & TH_RST)
867                 return -1;              /* feedback loop */
868 # if    (BSD < 199306) || defined(__sgi)
869         m = m_get(M_DONTWAIT, MT_HEADER);
870 # else
871         m = m_gethdr(M_DONTWAIT, MT_HEADER);
872 # endif
873         if (m == NULL)
874                 return ENOBUFS;
875         if (m == NULL)
876                 return -1;
877
878         if (tcp->th_flags & TH_SYN)
879                 tlen = 1;
880         m->m_len = sizeof(*tcp2) + sizeof(*ip);
881 # if    BSD >= 199306
882         m->m_data += max_linkhdr;
883         m->m_pkthdr.len = m->m_len;
884         m->m_pkthdr.rcvif = (struct ifnet *)0;
885 # endif
886         bzero(mtod(m, char *), sizeof(struct tcpiphdr));
887         ip = mtod(m, struct ip *);
888         tp = mtod(m, struct tcpiphdr *);
889         tcp2 = (struct tcphdr *)((char *)ip + sizeof(*ip));
890
891         ip->ip_src.s_addr = oip->ip_dst.s_addr;
892         ip->ip_dst.s_addr = oip->ip_src.s_addr;
893         tcp2->th_dport = tcp->th_sport;
894         tcp2->th_sport = tcp->th_dport;
895         tcp2->th_ack = ntohl(tcp->th_seq);
896         tcp2->th_ack += tlen;
897         tcp2->th_ack = htonl(tcp2->th_ack);
898         tcp2->th_off = sizeof(*tcp2) >> 2;
899         tcp2->th_flags = TH_RST|TH_ACK;
900         tp->ti_pr = oip->ip_p;
901         tp->ti_len = htons(sizeof(struct tcphdr));
902         tcp2->th_sum = in_cksum(m, sizeof(*ip) + sizeof(*tcp2));
903
904         ip->ip_tos = oip->ip_tos;
905         ip->ip_p = oip->ip_p;
906         ip->ip_len = sizeof(*ip) + sizeof(*tcp2);
907
908         return send_ip(m, ip);
909 }
910
911
912 static int send_ip(m, ip)
913 struct mbuf *m;
914 ip_t *ip;
915 {
916 # if (defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)) || \
917      (defined(_BSDI_VERSION) && (_BSDI_VERSION >= 199802))
918         struct route ro;
919 # endif
920
921 # if (BSD < 199306) || defined(__sgi)
922         ip->ip_ttl = tcp_ttl;
923 # else
924         ip->ip_ttl = ip_defttl;
925 # endif
926
927 # ifdef IPSEC
928         m->m_pkthdr.rcvif = NULL;
929 # endif
930 # if defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)
931         {
932         int err;
933
934         bzero((char *)&ro, sizeof(ro));
935         err = ip_output(m, (struct mbuf *)0, &ro, 0, 0);
936         if (ro.ro_rt)
937                 RTFREE(ro.ro_rt);
938         return err;
939         }
940 # else
941         /*
942          * extra 0 in case of multicast
943          */
944 #  if _BSDI_VERSION >= 199802
945         return ip_output(m, (struct mbuf *)0, &ro, 0, 0, NULL);
946 #  else
947 #   if  defined(__OpenBSD__)
948         return ip_output(m, (struct mbuf *)0, 0, 0, 0, NULL);
949 #   else
950         return ip_output(m, (struct mbuf *)0, 0, 0, 0);
951 #   endif
952 #  endif
953 # endif
954 }
955
956
957 int send_icmp_err(oip, type, code, ifp, dst)
958 ip_t *oip;
959 int type, code;
960 void *ifp;
961 struct in_addr dst;
962 {
963         struct icmp *icmp;
964         struct mbuf *m;
965         ip_t *nip;
966
967 # if    (BSD < 199306) || defined(__sgi)
968         m = m_get(M_DONTWAIT, MT_HEADER);
969 # else
970         m = m_gethdr(M_DONTWAIT, MT_HEADER);
971 # endif
972         if (m == NULL)
973                 return ENOBUFS;
974         m->m_len = sizeof(*nip) + sizeof(*icmp) + 8;
975 # if    BSD >= 199306
976         m->m_data += max_linkhdr;
977         m->m_pkthdr.len = sizeof(*nip) + sizeof(*icmp) + 8;
978         m->m_pkthdr.rcvif = (struct ifnet *)0;
979 # endif
980
981         bzero(mtod(m, char *), (size_t)sizeof(*nip) + sizeof(*icmp) + 8);
982         nip = mtod(m, ip_t *);
983         icmp = (struct icmp *)(nip + 1);
984
985         nip->ip_v = IPVERSION;
986         nip->ip_hl = (sizeof(*nip) >> 2);
987         nip->ip_p = IPPROTO_ICMP;
988         nip->ip_id = oip->ip_id;
989         nip->ip_sum = 0;
990         nip->ip_ttl = 60;
991         nip->ip_tos = oip->ip_tos;
992         nip->ip_len = sizeof(*nip) + sizeof(*icmp) + 8;
993         if (dst.s_addr == 0) {
994                 if (fr_ifpaddr(ifp, &dst) == -1)
995                         return -1;
996         }
997         nip->ip_src = dst;
998         nip->ip_dst = oip->ip_src;
999
1000         icmp->icmp_type = type;
1001         icmp->icmp_code = code;
1002         icmp->icmp_cksum = 0;
1003         bcopy((char *)oip, (char *)&icmp->icmp_ip, sizeof(*oip));
1004         bcopy((char *)oip + (oip->ip_hl << 2),
1005               (char *)&icmp->icmp_ip + sizeof(*oip), 8);        /* 64 bits */
1006 # ifndef        sparc
1007         {
1008         register u_short        __iplen, __ipoff;
1009         ip_t *ip = &icmp->icmp_ip;
1010
1011         __iplen = ip->ip_len;
1012         __ipoff = ip->ip_off;
1013         ip->ip_len = htons(__iplen);
1014         ip->ip_off = htons(__ipoff);
1015         }
1016 # endif
1017         icmp->icmp_cksum = ipf_cksum((u_short *)icmp, sizeof(*icmp) + 8);
1018         return send_ip(m, nip);
1019 }
1020
1021
1022 # if !defined(IPFILTER_LKM) && (__FreeBSD_version < 300000) && !defined(__sgi)
1023 #  if   (BSD < 199306)
1024 int iplinit __P((void));
1025
1026 int
1027 #  else
1028 void iplinit __P((void));
1029
1030 void
1031 #  endif
1032 iplinit()
1033 {
1034         if (iplattach() != 0)
1035                 printf("IP Filter failed to attach\n");
1036         ip_init();
1037 }
1038 # endif /* ! __NetBSD__ */
1039
1040
1041 size_t mbufchainlen(m0)
1042 register struct mbuf *m0;
1043 {
1044         register size_t len = 0;
1045
1046         for (; m0; m0 = m0->m_next)
1047                 len += m0->m_len;
1048         return len;
1049 }
1050
1051
1052 int ipfr_fastroute(m0, fin, fdp)
1053 struct mbuf *m0;
1054 fr_info_t *fin;
1055 frdest_t *fdp;
1056 {
1057         register struct ip *ip, *mhip;
1058         register struct mbuf *m = m0;
1059         register struct route *ro;
1060         int len, off, error = 0, hlen;
1061         struct sockaddr_in *dst;
1062         struct route iproute;
1063         struct ifnet *ifp;
1064         frentry_t *fr;
1065
1066         hlen = fin->fin_hlen;
1067         ip = mtod(m0, struct ip *);
1068         /*
1069          * Route packet.
1070          */
1071         ro = &iproute;
1072         bzero((caddr_t)ro, sizeof (*ro));
1073         dst = (struct sockaddr_in *)&ro->ro_dst;
1074         dst->sin_family = AF_INET;
1075
1076         fr = fin->fin_fr;
1077         ifp = fdp->fd_ifp;
1078         /*
1079          * In case we're here due to "to <if>" being used with "keep state",
1080          * check that we're going in the correct direction.
1081          */
1082         if ((fr != NULL) && (fin->fin_rev != 0)) {
1083                 if ((ifp != NULL) && (fdp == &fr->fr_tif))
1084                         return -1;
1085                 dst->sin_addr = ip->ip_dst;
1086         } else
1087                 dst->sin_addr = fdp->fd_ip.s_addr ? fdp->fd_ip : ip->ip_dst;
1088 # ifdef __bsdi__
1089         dst->sin_len = sizeof(*dst);
1090 # endif
1091 # if    (BSD >= 199306) && !defined(__NetBSD__) && !defined(__bsdi__) && \
1092         !defined(__OpenBSD__)
1093 #  ifdef        RTF_CLONING
1094         rtalloc_ign(ro, RTF_CLONING);
1095 #  else
1096         rtalloc_ign(ro, RTF_PRCLONING);
1097 #  endif
1098 # else
1099         rtalloc(ro);
1100 # endif
1101         if (!ifp) {
1102                 if (!(fin->fin_fr->fr_flags & FR_FASTROUTE)) {
1103                         error = -2;
1104                         goto bad;
1105                 }
1106                 if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) {
1107                         if (in_localaddr(ip->ip_dst))
1108                                 error = EHOSTUNREACH;
1109                         else
1110                                 error = ENETUNREACH;
1111                         goto bad;
1112                 }
1113                 if (ro->ro_rt->rt_flags & RTF_GATEWAY)
1114                         dst = (struct sockaddr_in *)&ro->ro_rt->rt_gateway;
1115         }
1116         if (ro->ro_rt)
1117                 ro->ro_rt->rt_use++;
1118
1119         /*
1120          * For input packets which are being "fastrouted", they won't
1121          * go back through output filtering and miss their chance to get
1122          * NAT'd and counted.
1123          */
1124         fin->fin_ifp = ifp;
1125         if (fin->fin_out == 0) {
1126                 fin->fin_out = 1;
1127                 if ((fin->fin_fr = ipacct[1][fr_active]) &&
1128                     (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) {
1129                         ATOMIC_INC(frstats[1].fr_acct);
1130                 }
1131                 fin->fin_fr = NULL;
1132                 (void) fr_checkstate(ip, fin);
1133                 (void) ip_natout(ip, fin);
1134         } else
1135                 ip->ip_sum = 0;
1136         /*
1137          * If small enough for interface, can just send directly.
1138          */
1139         if (ip->ip_len <= ifp->if_mtu) {
1140 # ifndef sparc
1141                 ip->ip_id = htons(ip->ip_id);
1142                 ip->ip_len = htons(ip->ip_len);
1143                 ip->ip_off = htons(ip->ip_off);
1144 # endif
1145                 if (!ip->ip_sum)
1146                         ip->ip_sum = in_cksum(m, hlen);
1147 # if    BSD >= 199306
1148                 error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst,
1149                                           ro->ro_rt);
1150 # else
1151                 error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst);
1152 # endif
1153                 goto done;
1154         }
1155         /*
1156          * Too large for interface; fragment if possible.
1157          * Must be able to put at least 8 bytes per fragment.
1158          */
1159         if (ip->ip_off & IP_DF) {
1160                 error = EMSGSIZE;
1161                 goto bad;
1162         }
1163         len = (ifp->if_mtu - hlen) &~ 7;
1164         if (len < 8) {
1165                 error = EMSGSIZE;
1166                 goto bad;
1167         }
1168
1169     {
1170         int mhlen, firstlen = len;
1171         struct mbuf **mnext = &m->m_act;
1172
1173         /*
1174          * Loop through length of segment after first fragment,
1175          * make new header and copy data of each part and link onto chain.
1176          */
1177         m0 = m;
1178         mhlen = sizeof (struct ip);
1179         for (off = hlen + len; off < ip->ip_len; off += len) {
1180 # ifdef MGETHDR
1181                 MGETHDR(m, M_DONTWAIT, MT_HEADER);
1182 # else
1183                 MGET(m, M_DONTWAIT, MT_HEADER);
1184 # endif
1185                 if (m == 0) {
1186                         error = ENOBUFS;
1187                         goto bad;
1188                 }
1189 # if BSD >= 199306
1190                 m->m_data += max_linkhdr;
1191 # else
1192                 m->m_off = MMAXOFF - hlen;
1193 # endif
1194                 mhip = mtod(m, struct ip *);
1195                 bcopy((char *)ip, (char *)mhip, sizeof(*ip));
1196                 if (hlen > sizeof (struct ip)) {
1197                         mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
1198                         mhip->ip_hl = mhlen >> 2;
1199                 }
1200                 m->m_len = mhlen;
1201                 mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);
1202                 if (ip->ip_off & IP_MF)
1203                         mhip->ip_off |= IP_MF;
1204                 if (off + len >= ip->ip_len)
1205                         len = ip->ip_len - off;
1206                 else
1207                         mhip->ip_off |= IP_MF;
1208                 mhip->ip_len = htons((u_short)(len + mhlen));
1209                 m->m_next = m_copy(m0, off, len);
1210                 if (m->m_next == 0) {
1211                         error = ENOBUFS;        /* ??? */
1212                         goto sendorfree;
1213                 }
1214 # if BSD >= 199306
1215                 m->m_pkthdr.len = mhlen + len;
1216                 m->m_pkthdr.rcvif = NULL;
1217 # endif
1218 # ifndef sparc
1219                 mhip->ip_off = htons((u_short)mhip->ip_off);
1220 # endif
1221                 mhip->ip_sum = 0;
1222                 mhip->ip_sum = in_cksum(m, mhlen);
1223                 *mnext = m;
1224                 mnext = &m->m_act;
1225         }
1226         /*
1227          * Update first fragment by trimming what's been copied out
1228          * and updating header, then send each fragment (in order).
1229          */
1230         m_adj(m0, hlen + firstlen - ip->ip_len);
1231         ip->ip_len = htons((u_short)(hlen + firstlen));
1232         ip->ip_off = htons((u_short)(ip->ip_off | IP_MF));
1233         ip->ip_sum = 0;
1234         ip->ip_sum = in_cksum(m0, hlen);
1235 sendorfree:
1236         for (m = m0; m; m = m0) {
1237                 m0 = m->m_act;
1238                 m->m_act = 0;
1239                 if (error == 0)
1240 # if BSD >= 199306
1241                         error = (*ifp->if_output)(ifp, m,
1242                             (struct sockaddr *)dst, ro->ro_rt);
1243 # else
1244                         error = (*ifp->if_output)(ifp, m,
1245                             (struct sockaddr *)dst);
1246 # endif
1247                 else
1248                         m_freem(m);
1249         }
1250     }   
1251 done:
1252         if (!error)
1253                 ipl_frouteok[0]++;
1254         else
1255                 ipl_frouteok[1]++;
1256
1257         if (ro->ro_rt)
1258                 RTFREE(ro->ro_rt);
1259         return 0;
1260 bad:
1261         if (error == EMSGSIZE)
1262                 (void) send_icmp_err(ip, ICMP_UNREACH, ICMP_UNREACH_NEEDFRAG,
1263                                      ifp, ip->ip_dst);
1264         m_freem(m);
1265         goto done;
1266 }
1267 #else /* #ifdef _KERNEL */
1268
1269
1270 # ifdef __sgi
1271 static int no_output __P((struct ifnet *ifp, struct mbuf *m,
1272                            struct sockaddr *s))
1273 # else
1274 static int no_output __P((struct ifnet *ifp, struct mbuf *m,
1275                            struct sockaddr *s, struct rtentry *rt))
1276 # endif
1277 {
1278         return 0;
1279 }
1280
1281
1282 # ifdef __STDC__
1283 #  ifdef __sgi
1284 static int write_output __P((struct ifnet *ifp, struct mbuf *m,
1285                              struct sockaddr *s))
1286 #  else
1287 static int write_output __P((struct ifnet *ifp, struct mbuf *m,
1288                              struct sockaddr *s, struct rtentry *rt))
1289 #  endif
1290 {
1291         ip_t *ip = (ip_t *)m;
1292 # else
1293 static int write_output(ifp, ip)
1294 struct ifnet *ifp;
1295 ip_t *ip;
1296 {
1297 # endif
1298         char fname[32];
1299         int fd;
1300
1301 # if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
1302         (defined(OpenBSD) && (OpenBSD >= 199603))
1303         sprintf(fname, "/tmp/%s", ifp->if_xname);
1304 # else
1305         sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
1306 # endif
1307         fd = open(fname, O_WRONLY|O_APPEND);
1308         if (fd == -1) {
1309                 perror("open");
1310                 return -1;
1311         }
1312         write(fd, (char *)ip, ntohs(ip->ip_len));
1313         close(fd);
1314         return 0;
1315 }
1316
1317
1318 struct ifnet *get_unit(name)
1319 char *name;
1320 {
1321         struct ifnet *ifp, **ifa;
1322 # if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
1323         (defined(OpenBSD) && (OpenBSD >= 199603))
1324         for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) {
1325                 if (!strcmp(name, ifp->if_xname))
1326                         return ifp;
1327         }
1328 # else
1329         char ifname[32], *s;
1330
1331         for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) {
1332                 (void) sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit);
1333                 if (!strcmp(name, ifname))
1334                         return ifp;
1335         }
1336 # endif
1337
1338         if (!ifneta) {
1339                 ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2);
1340                 ifneta[1] = NULL;
1341                 ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp));
1342                 nifs = 1;
1343         } else {
1344                 nifs++;
1345                 ifneta = (struct ifnet **)realloc(ifneta,
1346                                                   (nifs + 1) * sizeof(*ifa));
1347                 ifneta[nifs] = NULL;
1348                 ifneta[nifs - 1] = (struct ifnet *)malloc(sizeof(*ifp));
1349         }
1350         ifp = ifneta[nifs - 1];
1351
1352 # if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
1353         (defined(OpenBSD) && (OpenBSD >= 199603))
1354         strncpy(ifp->if_xname, name, sizeof(ifp->if_xname));
1355 # else
1356         for (s = name; *s && !isdigit(*s); s++)
1357                 ;
1358         if (*s && isdigit(*s)) {
1359                 ifp->if_unit = atoi(s);
1360                 ifp->if_name = (char *)malloc(s - name + 1);
1361                 strncpy(ifp->if_name, name, s - name);
1362                 ifp->if_name[s - name] = '\0';
1363         } else {
1364                 ifp->if_name = strdup(name);
1365                 ifp->if_unit = -1;
1366         }
1367 # endif
1368         ifp->if_output = no_output;
1369         return ifp;
1370 }
1371
1372
1373
1374 void init_ifp()
1375 {
1376         struct ifnet *ifp, **ifa;
1377         char fname[32];
1378         int fd;
1379
1380 # if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
1381         (defined(OpenBSD) && (OpenBSD >= 199603))
1382         for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) {
1383                 ifp->if_output = write_output;
1384                 sprintf(fname, "/tmp/%s", ifp->if_xname);
1385                 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
1386                 if (fd == -1)
1387                         perror("open");
1388                 else
1389                         close(fd);
1390         }
1391 # else
1392
1393         for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) {
1394                 ifp->if_output = write_output;
1395                 sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
1396                 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
1397                 if (fd == -1)
1398                         perror("open");
1399                 else
1400                         close(fd);
1401         }
1402 # endif
1403 }
1404
1405
1406 int ipfr_fastroute(ip, fin, fdp)
1407 ip_t *ip;
1408 fr_info_t *fin;
1409 frdest_t *fdp;
1410 {
1411         struct ifnet *ifp = fdp->fd_ifp;
1412
1413         if (!ifp)
1414                 return 0;       /* no routing table out here */
1415
1416         ip->ip_len = htons((u_short)ip->ip_len);
1417         ip->ip_off = htons((u_short)(ip->ip_off | IP_MF));
1418         ip->ip_sum = 0;
1419 #ifdef __sgi
1420         (*ifp->if_output)(ifp, (void *)ip, NULL);
1421 #else
1422         (*ifp->if_output)(ifp, (void *)ip, NULL, 0);
1423 #endif
1424         return 0;
1425 }
1426
1427
1428 int ipllog __P((void))
1429 {
1430         verbose("l");
1431         return 0;
1432 }
1433
1434
1435 int send_reset(ip, ifp)
1436 ip_t *ip;
1437 struct ifnet *ifp;
1438 {
1439         verbose("- TCP RST sent\n");
1440         return 0;
1441 }
1442
1443
1444 int icmp_error(ip, ifp)
1445 ip_t *ip;
1446 struct ifnet *ifp;
1447 {
1448         verbose("- TCP RST sent\n");
1449         return 0;
1450 }
1451
1452
1453 void frsync()
1454 {
1455         return;
1456 }
1457 #endif /* _KERNEL */