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