]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/ipfilter/ip_fil.c
This commit was generated by cvs2svn to compensate for changes in r53790,
[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.7 1999/10/15 13:49:43 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_inited = 0;
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 # 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 (ipl_inited || (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         ipl_inited = 1;
261         bzero((char *)frcache, sizeof(frcache));
262         fr_savep = fr_checkp;
263         fr_checkp = fr_check;
264
265         SPL_X(s);
266         if (fr_pass & FR_PASS)
267                 defpass = "pass";
268         else if (fr_pass & FR_BLOCK)
269                 defpass = "block";
270         else
271                 defpass = "no-match -> block";
272
273         printf("IP Filter: initialized.  Default = %s all, Logging = %s\n",
274                 defpass,
275 # ifdef IPFILTER_LOG
276                 "enabled");
277 # else
278                 "disabled");
279 # endif
280         printf("%s\n", ipfilter_version);
281 #ifdef  _KERNEL
282 # if (__FreeBSD_version >= 300000) && defined(_KERNEL)
283         ipfr_slowtimer_ch = timeout(ipfr_slowtimer, NULL, hz/2);
284 # else
285         timeout(ipfr_slowtimer, NULL, hz/2);
286 # endif
287 #endif
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 (!ipl_inited)
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         ipl_inited = 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                 error = nat_ioctl(data, cmd, mode);
415                 SPL_X(s);
416                 return error;
417         }
418         if (unit == IPL_LOGSTATE) {
419                 error = fr_state_ioctl(data, cmd, mode);
420                 SPL_X(s);
421                 return error;
422         }
423         switch (cmd) {
424         case FIONREAD :
425 #ifdef IPFILTER_LOG
426                 IWCOPY((caddr_t)&iplused[IPL_LOGIPF], (caddr_t)data,
427                        sizeof(iplused[IPL_LOGIPF]));
428 #endif
429                 break;
430 #if !defined(IPFILTER_LKM) && defined(_KERNEL)
431         case SIOCFRENB :
432         {
433                 u_int   enable;
434
435                 if (!(mode & FWRITE))
436                         error = EPERM;
437                 else {
438                         IRCOPY(data, (caddr_t)&enable, sizeof(enable));
439                         if (enable) {
440                                 error = iplattach();
441                                 if (error == 0)
442                                         fr_running = 1;
443                         } else {
444                                 error = ipldetach();
445                                 if (error == 0)
446                                         fr_running = 0;
447                         }
448                 }
449                 break;
450         }
451 #endif
452         case SIOCSETFF :
453                 if (!(mode & FWRITE))
454                         error = EPERM;
455                 else
456                         IRCOPY(data, (caddr_t)&fr_flags, sizeof(fr_flags));
457                 break;
458         case SIOCGETFF :
459                 IWCOPY((caddr_t)&fr_flags, data, sizeof(fr_flags));
460                 break;
461         case SIOCINAFR :
462         case SIOCRMAFR :
463         case SIOCADAFR :
464         case SIOCZRLST :
465                 if (!(mode & FWRITE))
466                         error = EPERM;
467                 else
468                         error = frrequest(unit, cmd, data, fr_active);
469                 break;
470         case SIOCINIFR :
471         case SIOCRMIFR :
472         case SIOCADIFR :
473                 if (!(mode & FWRITE))
474                         error = EPERM;
475                 else
476                         error = frrequest(unit, cmd, data, 1 - fr_active);
477                 break;
478         case SIOCSWAPA :
479                 if (!(mode & FWRITE))
480                         error = EPERM;
481                 else {
482                         bzero((char *)frcache, sizeof(frcache[0]) * 2);
483                         *(u_int *)data = fr_active;
484                         fr_active = 1 - fr_active;
485                 }
486                 break;
487         case SIOCGETFS :
488         {
489                 struct  friostat        fio;
490
491                 bcopy((char *)frstats, (char *)fio.f_st,
492                         sizeof(struct filterstats) * 2);
493                 fio.f_fin[0] = ipfilter[0][0];
494                 fio.f_fin[1] = ipfilter[0][1];
495                 fio.f_fout[0] = ipfilter[1][0];
496                 fio.f_fout[1] = ipfilter[1][1];
497                 fio.f_acctin[0] = ipacct[0][0];
498                 fio.f_acctin[1] = ipacct[0][1];
499                 fio.f_acctout[0] = ipacct[1][0];
500                 fio.f_acctout[1] = ipacct[1][1];
501                 fio.f_auth = ipauth;
502                 fio.f_active = fr_active;
503                 fio.f_froute[0] = ipl_frouteok[0];
504                 fio.f_froute[1] = ipl_frouteok[1];
505                 fio.f_running = fr_running;
506                 fio.f_groups[0][0] = ipfgroups[0][0];
507                 fio.f_groups[0][1] = ipfgroups[0][1];
508                 fio.f_groups[1][0] = ipfgroups[1][0];
509                 fio.f_groups[1][1] = ipfgroups[1][1];
510                 fio.f_groups[2][0] = ipfgroups[2][0];
511                 fio.f_groups[2][1] = ipfgroups[2][1];
512 #ifdef  IPFILTER_LOG
513                 fio.f_logging = 1;
514 #else
515                 fio.f_logging = 0;
516 #endif
517                 fio.f_defpass = fr_pass;
518                 strncpy(fio.f_version, ipfilter_version,
519                         sizeof(fio.f_version));
520                 IWCOPY((caddr_t)&fio, data, sizeof(fio));
521                 break;
522         }
523         case    SIOCFRZST :
524                 if (!(mode & FWRITE))
525                         error = EPERM;
526                 else
527                         frzerostats(data);
528                 break;
529         case    SIOCIPFFL :
530                 if (!(mode & FWRITE))
531                         error = EPERM;
532                 else {
533                         IRCOPY(data, (caddr_t)&tmp, sizeof(tmp));
534                         tmp = frflush(unit, tmp);
535                         IWCOPY((caddr_t)&tmp, data, sizeof(tmp));
536                 }
537                 break;
538 #ifdef  IPFILTER_LOG
539         case    SIOCIPFFB :
540                 if (!(mode & FWRITE))
541                         error = EPERM;
542                 else
543                         *(int *)data = ipflog_clear(unit);
544                 break;
545 #endif /* IPFILTER_LOG */
546         case SIOCGFRST :
547                 IWCOPY((caddr_t)ipfr_fragstats(), data, sizeof(ipfrstat_t));
548                 break;
549         case SIOCAUTHW :
550         case SIOCAUTHR :
551                 if (!(mode & FWRITE)) {
552                         error = EPERM;
553                         break;
554                 }
555         case SIOCATHST :
556                 error = fr_auth_ioctl(data, cmd, NULL, NULL);
557                 break;
558         case SIOCFRSYN :
559                 if (!(mode & FWRITE))
560                         error = EPERM;
561                 else {
562 #if defined(_KERNEL) && defined(__sgi)
563                         ipfsync();
564 #endif
565                         frsync();
566                 }
567                 break;
568         default :
569                 error = EINVAL;
570                 break;
571         }
572         SPL_X(s);
573         return error;
574 }
575
576
577 void frsync()
578 {
579 #ifdef _KERNEL
580         register frentry_t *f;
581         register struct ifnet *ifp;
582
583 # if defined(__OpenBSD__) || ((NetBSD >= 199511) && (NetBSD < 1991011)) || \
584      (defined(__FreeBSD_version) && (__FreeBSD_version >= 300000))
585 #  if (NetBSD >= 199905) || defined(__OpenBSD__)
586         for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_list.tqe_next)
587 #  else
588         for (ifp = ifnet.tqh_first; ifp; ifp = ifp->if_link.tqe_next)
589 #  endif
590 # else
591         for (ifp = ifnet; ifp; ifp = ifp->if_next)
592 # endif
593                 ip_natsync(ifp);
594
595         WRITE_ENTER(&ipf_mutex);
596         for (f = ipacct[0][fr_active]; (f != NULL); f = f->fr_next)
597                 if (f->fr_ifa == (void *)-1)
598                         f->fr_ifa = GETUNIT(f->fr_ifname);
599         for (f = ipacct[1][fr_active]; (f != NULL); f = f->fr_next)
600                 if (f->fr_ifa == (void *)-1)
601                         f->fr_ifa = GETUNIT(f->fr_ifname);
602         for (f = ipfilter[0][fr_active]; (f != NULL); f = f->fr_next)
603                 if (f->fr_ifa == (void *)-1)
604                         f->fr_ifa = GETUNIT(f->fr_ifname);
605         for (f = ipfilter[1][fr_active]; (f != NULL); f = f->fr_next)
606                 if (f->fr_ifa == (void *)-1)
607                         f->fr_ifa = GETUNIT(f->fr_ifname);
608         RWLOCK_EXIT(&ipf_mutex);
609 #endif
610 }
611
612
613 void fr_forgetifp(ifp)
614 void *ifp;
615 {
616         register frentry_t *f;
617
618         WRITE_ENTER(&ipf_mutex);
619         for (f = ipacct[0][fr_active]; (f != NULL); f = f->fr_next)
620                 if (f->fr_ifa == ifp)
621                         f->fr_ifa = (void *)-1;
622         for (f = ipacct[1][fr_active]; (f != NULL); f = f->fr_next)
623                 if (f->fr_ifa == ifp)
624                         f->fr_ifa = (void *)-1;
625         for (f = ipfilter[0][fr_active]; (f != NULL); f = f->fr_next)
626                 if (f->fr_ifa == ifp)
627                         f->fr_ifa = (void *)-1;
628         for (f = ipfilter[1][fr_active]; (f != NULL); f = f->fr_next)
629                 if (f->fr_ifa == ifp)
630                         f->fr_ifa = (void *)-1;
631         RWLOCK_EXIT(&ipf_mutex);
632         ip_natsync(ifp);
633 }
634
635
636 static int frrequest(unit, req, data, set)
637 int unit;
638 #if defined(__NetBSD__) || defined(__OpenBSD__)
639 u_long req;
640 #else
641 int req;
642 #endif
643 int set;
644 caddr_t data;
645 {
646         register frentry_t *fp, *f, **fprev;
647         register frentry_t **ftail;
648         frentry_t frd;
649         frdest_t *fdp;
650         frgroup_t *fg = NULL;
651         int error = 0, in;
652         u_int group;
653
654         fp = &frd;
655         IRCOPY(data, (caddr_t)fp, sizeof(*fp));
656         fp->fr_ref = 0;
657
658         /*
659          * Check that the group number does exist and that if a head group
660          * has been specified, doesn't exist.
661          */
662         if ((req != SIOCZRLST) && fp->fr_grhead &&
663             fr_findgroup((u_int)fp->fr_grhead, fp->fr_flags, unit, set, NULL))
664                 return EEXIST;
665         if ((req != SIOCZRLST) && fp->fr_group &&
666             !fr_findgroup((u_int)fp->fr_group, fp->fr_flags, unit, set, NULL))
667                 return ESRCH;
668
669         in = (fp->fr_flags & FR_INQUE) ? 0 : 1;
670
671         if (unit == IPL_LOGAUTH)
672                 ftail = fprev = &ipauth;
673         else if (fp->fr_flags & FR_ACCOUNT)
674                 ftail = fprev = &ipacct[in][set];
675         else if (fp->fr_flags & (FR_OUTQUE|FR_INQUE))
676                 ftail = fprev = &ipfilter[in][set];
677         else
678                 return ESRCH;
679
680         if ((group = fp->fr_group)) {
681                 if (!(fg = fr_findgroup(group, fp->fr_flags, unit, set, NULL)))
682                         return ESRCH;
683                 ftail = fprev = fg->fg_start;
684         }
685
686         bzero((char *)frcache, sizeof(frcache[0]) * 2);
687
688         if (*fp->fr_ifname) {
689                 fp->fr_ifa = GETUNIT(fp->fr_ifname);
690                 if (!fp->fr_ifa)
691                         fp->fr_ifa = (void *)-1;
692         }
693 #if BSD >= 199306
694         if (*fp->fr_oifname) {
695                 fp->fr_oifa = GETUNIT(fp->fr_oifname);
696                 if (!fp->fr_oifa)
697                         fp->fr_oifa = (void *)-1;
698         }
699 #endif
700
701         fdp = &fp->fr_dif;
702         fp->fr_flags &= ~FR_DUP;
703         if (*fdp->fd_ifname) {
704                 fdp->fd_ifp = GETUNIT(fdp->fd_ifname);
705                 if (!fdp->fd_ifp)
706                         fdp->fd_ifp = (struct ifnet *)-1;
707                 else
708                         fp->fr_flags |= FR_DUP;
709         }
710
711         fdp = &fp->fr_tif;
712         if (*fdp->fd_ifname) {
713                 fdp->fd_ifp = GETUNIT(fdp->fd_ifname);
714                 if (!fdp->fd_ifp)
715                         fdp->fd_ifp = (struct ifnet *)-1;
716         }
717
718         /*
719          * Look for a matching filter rule, but don't include the next or
720          * interface pointer in the comparison (fr_next, fr_ifa).
721          */
722         for (; (f = *ftail); ftail = &f->fr_next)
723                 if (bcmp((char *)&f->fr_ip, (char *)&fp->fr_ip,
724                          FR_CMPSIZ) == 0)
725                         break;
726
727         /*
728          * If zero'ing statistics, copy current to caller and zero.
729          */
730         if (req == SIOCZRLST) {
731                 if (!f)
732                         return ESRCH;
733                 IWCOPY((caddr_t)f, data, sizeof(*f));
734                 f->fr_hits = 0;
735                 f->fr_bytes = 0;
736                 return 0;
737         }
738
739         if (!f) {
740                 ftail = fprev;
741                 if (req != SIOCINAFR && req != SIOCINIFR)
742                         while ((f = *ftail))
743                                 ftail = &f->fr_next;
744                 else if (fp->fr_hits)
745                         while (--fp->fr_hits && (f = *ftail))
746                                 ftail = &f->fr_next;
747                 f = NULL;
748         }
749
750         if (req == SIOCDELFR || req == SIOCRMIFR) {
751                 if (!f)
752                         error = ESRCH;
753                 else {
754                         if (f->fr_ref > 1)
755                                 return EBUSY;
756                         if (fg && fg->fg_head)
757                                 fg->fg_head->fr_ref--;
758                         if (unit == IPL_LOGAUTH)
759                                 return fr_auth_ioctl(data, req, f, ftail);
760                         if (f->fr_grhead)
761                                 fr_delgroup((u_int)f->fr_grhead, fp->fr_flags,
762                                             unit, set);
763                         fixskip(fprev, f, -1);
764                         *ftail = f->fr_next;
765                         KFREE(f);
766                 }
767         } else {
768                 if (f)
769                         error = EEXIST;
770                 else {
771                         if (unit == IPL_LOGAUTH)
772                                 return fr_auth_ioctl(data, req, f, ftail);
773                         KMALLOC(f, frentry_t *);
774                         if (f != NULL) {
775                                 if (fg && fg->fg_head)
776                                         fg->fg_head->fr_ref++;
777                                 bcopy((char *)fp, (char *)f, sizeof(*f));
778                                 f->fr_ref = 1;
779                                 f->fr_hits = 0;
780                                 f->fr_next = *ftail;
781                                 *ftail = f;
782                                 if (req == SIOCINIFR || req == SIOCINAFR)
783                                         fixskip(fprev, f, 1);
784                                 f->fr_grp = NULL;
785                                 if ((group = f->fr_grhead))
786                                         fg = fr_addgroup(group, f, unit, set);
787                         } else
788                                 error = ENOMEM;
789                 }
790         }
791         return (error);
792 }
793
794
795 #ifdef  _KERNEL
796 /*
797  * routines below for saving IP headers to buffer
798  */
799 # ifdef __sgi
800 #  ifdef _KERNEL
801 int IPL_EXTERN(open)(dev_t *pdev, int flags, int devtype, cred_t *cp)
802 #  else
803 int IPL_EXTERN(open)(dev_t dev, int flags)
804 #  endif
805 # else
806 int IPL_EXTERN(open)(dev, flags
807 #  if ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || (NetBSD >= 199511) || \
808      (__FreeBSD_version >= 220000) || defined(__OpenBSD__)) && defined(_KERNEL)
809 , devtype, p)
810 int devtype;
811 struct proc *p;
812 #  else
813 )
814 #  endif
815 dev_t dev;
816 int flags;
817 # endif /* __sgi */
818 {
819 # if defined(__sgi) && defined(_KERNEL)
820         u_int min = geteminor(*pdev);
821 # else
822         u_int min = GET_MINOR(dev);
823 # endif
824
825         if (IPL_LOGMAX < min)
826                 min = ENXIO;
827         else
828                 min = 0;
829         return min;
830 }
831
832
833 # ifdef __sgi
834 int IPL_EXTERN(close)(dev_t dev, int flags, int devtype, cred_t *cp)
835 #else
836 int IPL_EXTERN(close)(dev, flags
837 #  if ((_BSDI_VERSION >= 199510) || (BSD >= 199506) || (NetBSD >= 199511) || \
838      (__FreeBSD_version >= 220000) || defined(__OpenBSD__)) && defined(_KERNEL)
839 , devtype, p)
840 int devtype;
841 struct proc *p;
842 #  else
843 )
844 #  endif
845 dev_t dev;
846 int flags;
847 # endif /* __sgi */
848 {
849         u_int   min = GET_MINOR(dev);
850
851         if (IPL_LOGMAX < min)
852                 min = ENXIO;
853         else
854                 min = 0;
855         return min;
856 }
857
858 /*
859  * iplread/ipllog
860  * both of these must operate with at least splnet() lest they be
861  * called during packet processing and cause an inconsistancy to appear in
862  * the filter lists.
863  */
864 # ifdef __sgi
865 int IPL_EXTERN(read)(dev_t dev, uio_t *uio, cred_t *crp)
866 # else
867 #  if BSD >= 199306
868 int IPL_EXTERN(read)(dev, uio, ioflag)
869 int ioflag;
870 #  else
871 int IPL_EXTERN(read)(dev, uio)
872 #  endif
873 dev_t dev;
874 register struct uio *uio;
875 # endif /* __sgi */
876 {
877 # ifdef IPFILTER_LOG
878         return ipflog_read(GET_MINOR(dev), uio);
879 # else
880         return ENXIO;
881 # endif
882 }
883
884
885 /*
886  * send_reset - this could conceivably be a call to tcp_respond(), but that
887  * requires a large amount of setting up and isn't any more efficient.
888  */
889 int send_reset(fin, oip)
890 fr_info_t *fin;
891 struct ip *oip;
892 {
893         struct tcphdr *tcp, *tcp2;
894         struct tcpiphdr *tp;
895         struct mbuf *m;
896         int tlen = 0;
897         ip_t *ip;
898
899         tcp = (struct tcphdr *)fin->fin_dp;
900         if (tcp->th_flags & TH_RST)
901                 return -1;              /* feedback loop */
902 # if    (BSD < 199306) || defined(__sgi)
903         m = m_get(M_DONTWAIT, MT_HEADER);
904 # else
905         m = m_gethdr(M_DONTWAIT, MT_HEADER);
906 # endif
907         if (m == NULL)
908                 return ENOBUFS;
909         if (m == NULL)
910                 return -1;
911
912         if (tcp->th_flags & TH_SYN)
913                 tlen = 1;
914         m->m_len = sizeof(*tcp2) + sizeof(*ip);
915 # if    BSD >= 199306
916         m->m_data += max_linkhdr;
917         m->m_pkthdr.len = m->m_len;
918         m->m_pkthdr.rcvif = (struct ifnet *)0;
919 # endif
920         bzero(mtod(m, char *), sizeof(struct tcpiphdr));
921         ip = mtod(m, struct ip *);
922         tp = mtod(m, struct tcpiphdr *);
923         tcp2 = (struct tcphdr *)((char *)ip + sizeof(*ip));
924
925         ip->ip_src.s_addr = oip->ip_dst.s_addr;
926         ip->ip_dst.s_addr = oip->ip_src.s_addr;
927         tcp2->th_dport = tcp->th_sport;
928         tcp2->th_sport = tcp->th_dport;
929         tcp2->th_ack = ntohl(tcp->th_seq);
930         tcp2->th_ack += tlen;
931         tcp2->th_ack = htonl(tcp2->th_ack);
932         tcp2->th_off = sizeof(*tcp2) >> 2;
933         tcp2->th_flags = TH_RST|TH_ACK;
934         tp->ti_pr = oip->ip_p;
935         tp->ti_len = htons(sizeof(struct tcphdr));
936         tcp2->th_sum = in_cksum(m, sizeof(*ip) + sizeof(*tcp2));
937
938         ip->ip_tos = oip->ip_tos;
939         ip->ip_p = oip->ip_p;
940         ip->ip_len = sizeof(*ip) + sizeof(*tcp2);
941
942         return send_ip(m, ip);
943 }
944
945
946 static int send_ip(m, ip)
947 struct mbuf *m;
948 ip_t *ip;
949 {
950 # if (defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)) || \
951      (defined(_BSDI_VERSION) && (_BSDI_VERSION >= 199802))
952         struct route ro;
953 # endif
954
955 # if (BSD < 199306) || defined(__sgi)
956         ip->ip_ttl = tcp_ttl;
957 # else
958         ip->ip_ttl = ip_defttl;
959 # endif
960
961 # if defined(__FreeBSD_version) && (__FreeBSD_version >= 220000)
962         {
963         int err;
964
965         bzero((char *)&ro, sizeof(ro));
966         err = ip_output(m, (struct mbuf *)0, &ro, 0, 0);
967         if (ro.ro_rt)
968                 RTFREE(ro.ro_rt);
969         return err;
970         }
971 # else
972         /*
973          * extra 0 in case of multicast
974          */
975 #  if _BSDI_VERSION >= 199802
976         return ip_output(m, (struct mbuf *)0, &ro, 0, 0, NULL);
977 #  else
978         return ip_output(m, (struct mbuf *)0, 0, 0, 0);
979 #  endif
980 # endif
981 }
982
983
984 int send_icmp_err(oip, type, code, ifp, dst)
985 ip_t *oip;
986 int type, code;
987 void *ifp;
988 struct in_addr  dst;
989 {
990         struct icmp *icmp;
991         struct mbuf *m;
992         ip_t *nip;
993
994 # if    (BSD < 199306) || defined(__sgi)
995         m = m_get(M_DONTWAIT, MT_HEADER);
996 # else
997         m = m_gethdr(M_DONTWAIT, MT_HEADER);
998 # endif
999         if (m == NULL)
1000                 return ENOBUFS;
1001         m->m_len = sizeof(*nip) + sizeof(*icmp) + 8;
1002 # if    BSD >= 199306
1003         m->m_data += max_linkhdr;
1004         m->m_pkthdr.len = sizeof(*nip) + sizeof(*icmp) + 8;
1005         m->m_pkthdr.rcvif = (struct ifnet *)0;
1006 # endif
1007
1008         bzero(mtod(m, char *), (size_t)sizeof(*nip) + sizeof(*icmp) + 8);
1009         nip = mtod(m, ip_t *);
1010         icmp = (struct icmp *)(nip + 1);
1011
1012         nip->ip_v = IPVERSION;
1013         nip->ip_hl = (sizeof(*nip) >> 2);
1014         nip->ip_p = IPPROTO_ICMP;
1015         nip->ip_id = oip->ip_id;
1016         nip->ip_sum = 0;
1017         nip->ip_ttl = 60;
1018         nip->ip_tos = oip->ip_tos;
1019         nip->ip_len = sizeof(*nip) + sizeof(*icmp) + 8;
1020         if (dst.s_addr == 0) {
1021                 if (fr_ifpaddr(ifp, &dst) == -1)
1022                         return -1;
1023                 dst.s_addr = htonl(dst.s_addr);
1024         }
1025         nip->ip_src = dst;
1026         nip->ip_dst = oip->ip_src;
1027
1028         icmp->icmp_type = type;
1029         icmp->icmp_code = code;
1030         icmp->icmp_cksum = 0;
1031         bcopy((char *)oip, (char *)&icmp->icmp_ip, sizeof(*oip));
1032         bcopy((char *)oip + (oip->ip_hl << 2),
1033               (char *)&icmp->icmp_ip + sizeof(*oip), 8);        /* 64 bits */
1034 # ifndef        sparc
1035         {
1036         register u_short        __iplen, __ipoff;
1037         ip_t *ip = &icmp->icmp_ip;
1038
1039         __iplen = ip->ip_len;
1040         __ipoff = ip->ip_off;
1041         ip->ip_len = htons(__iplen);
1042         ip->ip_off = htons(__ipoff);
1043         }
1044 # endif
1045         icmp->icmp_cksum = ipf_cksum((u_short *)icmp, sizeof(*icmp) + 8);
1046         return send_ip(m, nip);
1047 }
1048
1049
1050 # if !defined(IPFILTER_LKM) && (__FreeBSD_version < 300000) && !defined(__sgi)
1051 #  if   (BSD < 199306)
1052 int iplinit __P((void));
1053
1054 int
1055 #  else
1056 void iplinit __P((void));
1057
1058 void
1059 #  endif
1060 iplinit()
1061 {
1062         if (iplattach() != 0)
1063                 printf("IP Filter failed to attach\n");
1064         ip_init();
1065 }
1066 # endif /* ! __NetBSD__ */
1067
1068
1069 size_t mbufchainlen(m0)
1070 register struct mbuf *m0;
1071 {
1072         register size_t len = 0;
1073
1074         for (; m0; m0 = m0->m_next)
1075                 len += m0->m_len;
1076         return len;
1077 }
1078
1079
1080 int ipfr_fastroute(m0, fin, fdp)
1081 struct mbuf *m0;
1082 fr_info_t *fin;
1083 frdest_t *fdp;
1084 {
1085         register struct ip *ip, *mhip;
1086         register struct mbuf *m = m0;
1087         register struct route *ro;
1088         int len, off, error = 0, hlen;
1089         struct sockaddr_in *dst;
1090         struct route iproute;
1091         struct ifnet *ifp;
1092         frentry_t *fr;
1093
1094         hlen = fin->fin_hlen;
1095         ip = mtod(m0, struct ip *);
1096         /*
1097          * Route packet.
1098          */
1099         ro = &iproute;
1100         bzero((caddr_t)ro, sizeof (*ro));
1101         dst = (struct sockaddr_in *)&ro->ro_dst;
1102         dst->sin_family = AF_INET;
1103
1104         fr = fin->fin_fr;
1105         ifp = fdp->fd_ifp;
1106         /*
1107          * In case we're here due to "to <if>" being used with "keep state",
1108          * check that we're going in the correct direction.
1109          */
1110         if ((fr != NULL) && (ifp != NULL) && (fin->fin_rev != 0) &&
1111             (fdp == &fr->fr_tif))
1112                 return -1;
1113 # ifdef __bsdi__
1114         dst->sin_len = sizeof(*dst);
1115 # endif
1116 # if    (BSD >= 199306) && !defined(__NetBSD__) && !defined(__bsdi__) && \
1117         !defined(__OpenBSD__)
1118 #  ifdef        RTF_CLONING
1119         rtalloc_ign(ro, RTF_CLONING);
1120 #  else
1121         rtalloc_ign(ro, RTF_PRCLONING);
1122 #  endif
1123 # else
1124         rtalloc(ro);
1125 # endif
1126         if (!ifp) {
1127                 if (!(fin->fin_fr->fr_flags & FR_FASTROUTE)) {
1128                         error = -2;
1129                         goto bad;
1130                 }
1131                 if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) {
1132                         if (in_localaddr(ip->ip_dst))
1133                                 error = EHOSTUNREACH;
1134                         else
1135                                 error = ENETUNREACH;
1136                         goto bad;
1137                 }
1138                 if (ro->ro_rt->rt_flags & RTF_GATEWAY)
1139                         dst = (struct sockaddr_in *)&ro->ro_rt->rt_gateway;
1140         }
1141         if (ro->ro_rt)
1142                 ro->ro_rt->rt_use++;
1143
1144         /*
1145          * For input packets which are being "fastrouted", they won't
1146          * go back through output filtering and miss their chance to get
1147          * NAT'd and counted.
1148          */
1149         fin->fin_ifp = ifp;
1150         if (fin->fin_out == 0) {
1151                 fin->fin_out = 1;
1152                 if ((fin->fin_fr = ipacct[1][fr_active]) &&
1153                     (fr_scanlist(FR_NOMATCH, ip, fin, m) & FR_ACCOUNT)) {
1154                         ATOMIC_INC(frstats[1].fr_acct);
1155                 }
1156                 fin->fin_fr = NULL;
1157                 (void) fr_checkstate(ip, fin);
1158                 (void) ip_natout(ip, fin);
1159         } else
1160                 ip->ip_sum = 0;
1161         /*
1162          * If small enough for interface, can just send directly.
1163          */
1164         if (ip->ip_len <= ifp->if_mtu) {
1165 # ifndef sparc
1166                 ip->ip_id = htons(ip->ip_id);
1167                 ip->ip_len = htons(ip->ip_len);
1168                 ip->ip_off = htons(ip->ip_off);
1169 # endif
1170                 if (!ip->ip_sum)
1171                         ip->ip_sum = in_cksum(m, hlen);
1172 # if    BSD >= 199306
1173                 error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst,
1174                                           ro->ro_rt);
1175 # else
1176                 error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst);
1177 # endif
1178                 goto done;
1179         }
1180         /*
1181          * Too large for interface; fragment if possible.
1182          * Must be able to put at least 8 bytes per fragment.
1183          */
1184         if (ip->ip_off & IP_DF) {
1185                 error = EMSGSIZE;
1186                 goto bad;
1187         }
1188         len = (ifp->if_mtu - hlen) &~ 7;
1189         if (len < 8) {
1190                 error = EMSGSIZE;
1191                 goto bad;
1192         }
1193
1194     {
1195         int mhlen, firstlen = len;
1196         struct mbuf **mnext = &m->m_act;
1197
1198         /*
1199          * Loop through length of segment after first fragment,
1200          * make new header and copy data of each part and link onto chain.
1201          */
1202         m0 = m;
1203         mhlen = sizeof (struct ip);
1204         for (off = hlen + len; off < ip->ip_len; off += len) {
1205 # ifdef MGETHDR
1206                 MGETHDR(m, M_DONTWAIT, MT_HEADER);
1207 # else
1208                 MGET(m, M_DONTWAIT, MT_HEADER);
1209 # endif
1210                 if (m == 0) {
1211                         error = ENOBUFS;
1212                         goto bad;
1213                 }
1214 # if BSD >= 199306
1215                 m->m_data += max_linkhdr;
1216 # else
1217                 m->m_off = MMAXOFF - hlen;
1218 # endif
1219                 mhip = mtod(m, struct ip *);
1220                 bcopy((char *)ip, (char *)mhip, sizeof(*ip));
1221                 if (hlen > sizeof (struct ip)) {
1222                         mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
1223                         mhip->ip_hl = mhlen >> 2;
1224                 }
1225                 m->m_len = mhlen;
1226                 mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);
1227                 if (ip->ip_off & IP_MF)
1228                         mhip->ip_off |= IP_MF;
1229                 if (off + len >= ip->ip_len)
1230                         len = ip->ip_len - off;
1231                 else
1232                         mhip->ip_off |= IP_MF;
1233                 mhip->ip_len = htons((u_short)(len + mhlen));
1234                 m->m_next = m_copy(m0, off, len);
1235                 if (m->m_next == 0) {
1236                         error = ENOBUFS;        /* ??? */
1237                         goto sendorfree;
1238                 }
1239 # ifndef sparc
1240                 mhip->ip_off = htons((u_short)mhip->ip_off);
1241 # endif
1242                 mhip->ip_sum = 0;
1243                 mhip->ip_sum = in_cksum(m, mhlen);
1244                 *mnext = m;
1245                 mnext = &m->m_act;
1246         }
1247         /*
1248          * Update first fragment by trimming what's been copied out
1249          * and updating header, then send each fragment (in order).
1250          */
1251         m_adj(m0, hlen + firstlen - ip->ip_len);
1252         ip->ip_len = htons((u_short)(hlen + firstlen));
1253         ip->ip_off = htons((u_short)(ip->ip_off | IP_MF));
1254         ip->ip_sum = 0;
1255         ip->ip_sum = in_cksum(m0, hlen);
1256 sendorfree:
1257         for (m = m0; m; m = m0) {
1258                 m0 = m->m_act;
1259                 m->m_act = 0;
1260                 if (error == 0)
1261 # if BSD >= 199306
1262                         error = (*ifp->if_output)(ifp, m,
1263                             (struct sockaddr *)dst, ro->ro_rt);
1264 # else
1265                         error = (*ifp->if_output)(ifp, m,
1266                             (struct sockaddr *)dst);
1267 # endif
1268                 else
1269                         m_freem(m);
1270         }
1271     }   
1272 done:
1273         if (!error)
1274                 ipl_frouteok[0]++;
1275         else
1276                 ipl_frouteok[1]++;
1277
1278         if (ro->ro_rt)
1279                 RTFREE(ro->ro_rt);
1280         return 0;
1281 bad:
1282         m_freem(m);
1283         goto done;
1284 }
1285 #else /* #ifdef _KERNEL */
1286
1287
1288 # ifdef __sgi
1289 static int no_output __P((struct ifnet *ifp, struct mbuf *m,
1290                            struct sockaddr *s))
1291 # else
1292 static int no_output __P((struct ifnet *ifp, struct mbuf *m,
1293                            struct sockaddr *s, struct rtentry *rt))
1294 # endif
1295 {
1296         return 0;
1297 }
1298
1299
1300 # ifdef __STDC__
1301 #  ifdef __sgi
1302 static int write_output __P((struct ifnet *ifp, struct mbuf *m,
1303                              struct sockaddr *s))
1304 #  else
1305 static int write_output __P((struct ifnet *ifp, struct mbuf *m,
1306                              struct sockaddr *s, struct rtentry *rt))
1307 #  endif
1308 {
1309         ip_t *ip = (ip_t *)m;
1310 # else
1311 static int write_output(ifp, ip)
1312 struct ifnet *ifp;
1313 ip_t *ip;
1314 {
1315 # endif
1316         char fname[32];
1317         int fd;
1318
1319 # if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
1320         (defined(OpenBSD) && (OpenBSD >= 199603))
1321         sprintf(fname, "/tmp/%s", ifp->if_xname);
1322 # else
1323         sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
1324 # endif
1325         fd = open(fname, O_WRONLY|O_APPEND);
1326         if (fd == -1) {
1327                 perror("open");
1328                 return -1;
1329         }
1330         write(fd, (char *)ip, ntohs(ip->ip_len));
1331         close(fd);
1332         return 0;
1333 }
1334
1335
1336 struct ifnet *get_unit(name)
1337 char *name;
1338 {
1339         struct ifnet *ifp, **ifa;
1340 # if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
1341         (defined(OpenBSD) && (OpenBSD >= 199603))
1342         for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) {
1343                 if (!strcmp(name, ifp->if_xname))
1344                         return ifp;
1345         }
1346 # else
1347         char ifname[32], *s;
1348
1349         for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) {
1350                 (void) sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit);
1351                 if (!strcmp(name, ifname))
1352                         return ifp;
1353         }
1354 # endif
1355
1356         if (!ifneta) {
1357                 ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2);
1358                 ifneta[1] = NULL;
1359                 ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp));
1360                 nifs = 1;
1361         } else {
1362                 nifs++;
1363                 ifneta = (struct ifnet **)realloc(ifneta,
1364                                                   (nifs + 1) * sizeof(*ifa));
1365                 ifneta[nifs] = NULL;
1366                 ifneta[nifs - 1] = (struct ifnet *)malloc(sizeof(*ifp));
1367         }
1368         ifp = ifneta[nifs - 1];
1369
1370 # if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
1371         (defined(OpenBSD) && (OpenBSD >= 199603))
1372         strncpy(ifp->if_xname, name, sizeof(ifp->if_xname));
1373 # else
1374         for (s = name; *s && !isdigit(*s); s++)
1375                 ;
1376         if (*s && isdigit(*s)) {
1377                 ifp->if_unit = atoi(s);
1378                 ifp->if_name = (char *)malloc(s - name + 1);
1379                 strncpy(ifp->if_name, name, s - name);
1380                 ifp->if_name[s - name] = '\0';
1381         } else {
1382                 ifp->if_name = strdup(name);
1383                 ifp->if_unit = -1;
1384         }
1385 # endif
1386         ifp->if_output = no_output;
1387         return ifp;
1388 }
1389
1390
1391
1392 void init_ifp()
1393 {
1394         struct ifnet *ifp, **ifa;
1395         char fname[32];
1396         int fd;
1397
1398 # if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
1399         (defined(OpenBSD) && (OpenBSD >= 199603))
1400         for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) {
1401                 ifp->if_output = write_output;
1402                 sprintf(fname, "/tmp/%s", ifp->if_xname);
1403                 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
1404                 if (fd == -1)
1405                         perror("open");
1406                 else
1407                         close(fd);
1408         }
1409 # else
1410
1411         for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) {
1412                 ifp->if_output = write_output;
1413                 sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
1414                 fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
1415                 if (fd == -1)
1416                         perror("open");
1417                 else
1418                         close(fd);
1419         }
1420 # endif
1421 }
1422
1423
1424 int ipfr_fastroute(ip, fin, fdp)
1425 ip_t *ip;
1426 fr_info_t *fin;
1427 frdest_t *fdp;
1428 {
1429         struct ifnet *ifp = fdp->fd_ifp;
1430
1431         if (!ifp)
1432                 return 0;       /* no routing table out here */
1433
1434         ip->ip_len = htons((u_short)ip->ip_len);
1435         ip->ip_off = htons((u_short)(ip->ip_off | IP_MF));
1436         ip->ip_sum = 0;
1437 #ifdef __sgi
1438         (*ifp->if_output)(ifp, (void *)ip, NULL);
1439 #else
1440         (*ifp->if_output)(ifp, (void *)ip, NULL, 0);
1441 #endif
1442         return 0;
1443 }
1444
1445
1446 int ipllog __P((void))
1447 {
1448         verbose("l");
1449         return 0;
1450 }
1451
1452
1453 int send_reset(ip, ifp)
1454 ip_t *ip;
1455 struct ifnet *ifp;
1456 {
1457         verbose("- TCP RST sent\n");
1458         return 0;
1459 }
1460
1461
1462 int icmp_error(ip, ifp)
1463 ip_t *ip;
1464 struct ifnet *ifp;
1465 {
1466         verbose("- TCP RST sent\n");
1467         return 0;
1468 }
1469 #endif /* _KERNEL */