added -y/--side-by-side option
[dfdiff.git] / contrib / ipfilter / ip_lfil.c
blob196d64e0fedf269566642bd5cda7711ec7d813f4
1 /*
2 * Copyright (C) 1993-2001 by Darren Reed.
4 * See the IPFILTER.LICENCE file for details on licencing.
5 */
6 #if !defined(lint)
7 static const char rcsid[] = "@(#)$Id: ip_lfil.c,v 2.6.2.5 2002/10/03 13:47:19 darrenr Exp $";
8 #endif
10 #if defined(KERNEL) && !defined(_KERNEL)
11 # define _KERNEL
12 #endif
13 #include <sys/errno.h>
14 #include <sys/types.h>
15 #include <sys/param.h>
16 #include <sys/file.h>
17 #include <sys/ioctl.h>
18 #include <sys/time.h>
19 #include <sys/dir.h>
20 #include <sys/socket.h>
21 #ifndef _KERNEL
22 # include <stdio.h>
23 # include <string.h>
24 # include <stdlib.h>
25 # include <ctype.h>
26 #else
27 # include <linux/module.h>
28 #endif
30 #include <net/if.h>
31 #include <net/route.h>
32 #include <netinet/in.h>
33 #include <netinet/in_systm.h>
34 #include <netinet/ip.h>
35 #include <netinet/tcp.h>
36 #include <netinet/udp.h>
37 #include <netinet/ip_icmp.h>
38 #ifndef _KERNEL
39 # include <syslog.h>
40 #endif
41 #include "netinet/ip_compat.h"
42 #include <netinet/tcpip.h>
43 #include "netinet/ip_fil.h"
44 #include "netinet/ip_nat.h"
45 #include "netinet/ip_proxy.h"
46 #include "netinet/ip_frag.h"
47 #include "netinet/ip_state.h"
48 #include "netinet/ip_auth.h"
49 #ifdef _KERNEL
50 #include <net/ip_forward.h>
51 #endif
52 #ifndef MIN
53 #define MIN(a,b) (((a)<(b))?(a):(b))
54 #endif
57 #ifndef _KERNEL
58 # include "ipt.h"
59 static struct ifnet **ifneta = NULL;
60 static int nifs = 0;
61 #endif
63 int fr_running = 0;
64 int ipl_unreach = ICMP_UNREACH_FILTER;
65 u_long ipl_frouteok[2] = {0, 0};
67 static int frzerostats __P((caddr_t));
68 static void frsync __P((void));
69 #if defined(__NetBSD__) || defined(__OpenBSD__)
70 static int frrequest __P((int, u_long, caddr_t, int));
71 #else
72 static int frrequest __P((int, u_long, caddr_t, int));
73 #endif
74 #ifdef _KERNEL
75 static int (*fr_savep) __P((ip_t *, int, void *, int, mb_t **));
76 #else
77 int ipllog __P((void));
78 void init_ifp __P((void));
79 static int no_output __P((mb_t *, struct ifnet *));
80 static int write_output __P((mb_t *, struct ifnet *));
81 #endif
83 #ifdef _KERNEL
85 int fr_precheck(struct iphdr *ip, struct device *dev, int out, struct device **ifp)
87 int hlen = ip->ihl << 2;
89 return fr_check((ip_t *)ip, hlen, dev, out, (mb_t **)ifp);
93 int iplattach()
95 char *defpass;
96 int s;
98 if (fr_running || (fr_checkp == fr_precheck)) {
99 printk("IP Filter: already initialized\n");
100 return EBUSY;
103 fr_running = 1;
104 bzero((char *)frcache, sizeof(frcache));
105 bzero((char *)nat_table, sizeof(nat_table));
106 fr_savep = fr_checkp;
107 fr_checkp = fr_precheck;
109 # ifdef IPFILTER_LOG
110 ipflog_init();
111 # endif
112 if (fr_pass & FR_PASS)
113 defpass = "pass";
114 else if (fr_pass & FR_BLOCK)
115 defpass = "block";
116 else
117 defpass = "no-match -> block";
119 printk("IP Filter: initialized. Default = %s all, Logging = %s\n",
120 defpass,
121 # ifdef IPFILTER_LOG
122 "enabled");
123 # else
124 "disabled");
125 # endif
126 return 0;
131 * Disable the filter by removing the hooks from the IP input/output
132 * stream.
134 int ipldetach()
136 int s, i = FR_INQUE|FR_OUTQUE;
138 if (!fr_running)
140 printk("IP Filter: not initialized\n");
141 return 0;
144 fr_checkp = fr_savep;
145 i = frflush(IPL_LOGIPF, i);
146 fr_running = 0;
148 ipfr_unload();
149 ip_natunload();
150 fr_stateunload();
151 fr_authunload();
153 printk("IP Filter: unloaded\n");
155 return 0;
157 #endif /* _KERNEL */
160 static int frzerostats(data)
161 caddr_t data;
163 struct friostat fio;
164 int error;
166 bcopy((char *)frstats, (char *)fio.f_st,
167 sizeof(struct filterstats) * 2);
168 fio.f_fin[0] = ipfilter[0][0];
169 fio.f_fin[1] = ipfilter[0][1];
170 fio.f_fout[0] = ipfilter[1][0];
171 fio.f_fout[1] = ipfilter[1][1];
172 fio.f_acctin[0] = ipacct[0][0];
173 fio.f_acctin[1] = ipacct[0][1];
174 fio.f_acctout[0] = ipacct[1][0];
175 fio.f_acctout[1] = ipacct[1][1];
176 fio.f_active = fr_active;
177 fio.f_froute[0] = ipl_frouteok[0];
178 fio.f_froute[1] = ipl_frouteok[1];
179 error = IWCOPYPTR((caddr_t)&fio, data, sizeof(fio));
180 if (!error)
181 bzero((char *)frstats, sizeof(*frstats) * 2);
182 return error;
187 * Filter ioctl interface.
189 #if defined(_KERNEL)
190 int iplioctl(struct inode *inode, struct file *file, u_int cmd, u_long arg)
192 int s;
193 caddr_t data = (caddr_t)arg;
195 int mode = file->f_mode;
196 #else
197 int iplioctl(dev_t dev, int cmd, caddr_t data, int mode)
199 #endif
200 int error = 0, unit = 0, tmp;
202 #ifdef _KERNEL
203 unit = GET_MINOR(inode->i_rdev);
204 if ((IPL_LOGMAX < unit) || (unit < 0))
205 return ENXIO;
206 #endif
208 if (unit == IPL_LOGNAT) {
209 error = nat_ioctl(data, cmd, mode);
210 return error;
212 if (unit == IPL_LOGSTATE) {
213 error = fr_state_ioctl(data, cmd, mode);
214 return error;
217 switch (cmd) {
218 case FIONREAD :
219 #ifdef IPFILTER_LOG
220 error = IWCOPY((caddr_t)&iplused[IPL_LOGIPF], data,
221 sizeof(iplused[IPL_LOGIPF]));
222 #endif
223 break;
224 #if !defined(IPFILTER_LKM) && defined(_KERNEL)
225 case SIOCFRENB :
227 u_int enable;
229 if (!(mode & FWRITE))
230 error = EPERM;
231 else {
232 error = IRCOPY(data, (caddr_t)&enable, sizeof(enable));
233 if (error)
234 break;
235 if (enable)
236 error = iplattach();
237 else
238 error = ipldetach();
240 break;
242 #endif
243 case SIOCSETFF :
244 if (!(mode & FWRITE))
245 error = EPERM;
246 else
247 error = IRCOPY(data, (caddr_t)&fr_flags,
248 sizeof(fr_flags));
249 break;
250 case SIOCGETFF :
251 error = IWCOPY((caddr_t)&fr_flags, data, sizeof(fr_flags));
252 break;
253 case SIOCINAFR :
254 case SIOCRMAFR :
255 case SIOCADAFR :
256 case SIOCZRLST :
257 if (!(mode & FWRITE))
258 error = EPERM;
259 else
260 error = frrequest(unit, cmd, data, fr_active);
261 break;
262 case SIOCINIFR :
263 case SIOCRMIFR :
264 case SIOCADIFR :
265 if (!(mode & FWRITE))
266 error = EPERM;
267 else
268 error = frrequest(unit, cmd, data, 1 - fr_active);
269 break;
270 case SIOCSWAPA :
271 if (!(mode & FWRITE))
272 error = EPERM;
273 else {
274 bzero((char *)frcache, sizeof(frcache[0]) * 2);
275 *(u_int *)data = fr_active;
276 fr_active = 1 - fr_active;
278 break;
279 case SIOCGETFS :
281 struct friostat fio;
283 bcopy((char *)frstats, (char *)fio.f_st,
284 sizeof(struct filterstats) * 2);
285 fio.f_fin[0] = ipfilter[0][0];
286 fio.f_fin[1] = ipfilter[0][1];
287 fio.f_fout[0] = ipfilter[1][0];
288 fio.f_fout[1] = ipfilter[1][1];
289 fio.f_acctin[0] = ipacct[0][0];
290 fio.f_acctin[1] = ipacct[0][1];
291 fio.f_acctout[0] = ipacct[1][0];
292 fio.f_acctout[1] = ipacct[1][1];
293 fio.f_auth = ipauth;
294 fio.f_active = fr_active;
295 fio.f_froute[0] = ipl_frouteok[0];
296 fio.f_froute[1] = ipl_frouteok[1];
297 error = IWCOPYPTR((caddr_t)&fio, data, sizeof(fio));
298 break;
300 case SIOCFRZST :
301 if (!(mode & FWRITE))
302 error = EPERM;
303 else
304 error = frzerostats(data);
305 break;
306 case SIOCIPFFL :
307 if (!(mode & FWRITE))
308 error = EPERM;
309 else {
310 error = IRCOPY(data, (caddr_t)&tmp, sizeof(tmp));
311 if (!error) {
312 tmp = frflush(unit, tmp);
313 error = IWCOPY((caddr_t)&tmp, data,
314 sizeof(tmp));
317 break;
318 #ifdef IPFILTER_LOG
319 case SIOCIPFFB :
320 if (!(mode & FWRITE))
321 error = EPERM;
322 else
323 *(int *)data = ipflog_clear(unit);
324 break;
325 #endif /* IPFILTER_LOG */
326 case SIOCGFRST :
327 error = IWCOPYPTR((caddr_t)ipfr_fragstats(), data,
328 sizeof(ipfrstat_t));
329 break;
330 case SIOCFRSYN :
331 if (!(mode & FWRITE))
332 error = EPERM;
333 else {
334 #if defined(_KERNEL) && defined(__sgi)
335 ipfsync();
336 #endif
337 frsync();
339 break;
340 default :
341 error = EINVAL;
342 break;
344 return error;
348 static void frsync()
350 #ifdef _KERNEL
351 struct device *dev;
353 for (dev = dev_base; dev; dev = dev->next)
354 ip_natsync(dev);
355 #endif
359 static int frrequest(unit, req, data, set)
360 int unit;
361 u_long req;
362 int set;
363 caddr_t data;
365 register frentry_t *fp, *f, **fprev;
366 register frentry_t **ftail;
367 frentry_t frd;
368 frdest_t *fdp;
369 frgroup_t *fg = NULL;
370 int error = 0, in;
371 u_int group;
373 fp = &frd;
374 error = IRCOPYPTR(data, (caddr_t)fp, sizeof(*fp));
375 if (error)
376 return error;
379 * Check that the group number does exist and that if a head group
380 * has been specified, doesn't exist.
382 if (fp->fr_grhead &&
383 fr_findgroup((u_int)fp->fr_grhead, fp->fr_flags, unit, set, NULL))
384 return EEXIST;
385 if (fp->fr_group &&
386 !fr_findgroup((u_int)fp->fr_group, fp->fr_flags, unit, set, NULL))
387 return ESRCH;
389 in = (fp->fr_flags & FR_INQUE) ? 0 : 1;
391 if (unit == IPL_LOGAUTH)
392 ftail = fprev = &ipauth;
393 else if (fp->fr_flags & FR_ACCOUNT)
394 ftail = fprev = &ipacct[in][set];
395 else if (fp->fr_flags & (FR_OUTQUE|FR_INQUE))
396 ftail = fprev = &ipfilter[in][set];
397 else
398 return ESRCH;
400 if ((group = fp->fr_group)) {
401 if (!(fg = fr_findgroup(group, fp->fr_flags, unit, set, NULL)))
402 return ESRCH;
403 ftail = fprev = fg->fg_start;
406 bzero((char *)frcache, sizeof(frcache[0]) * 2);
408 if (*fp->fr_ifname) {
409 fp->fr_ifa = GETUNIT(fp->fr_ifname, fp->fr_ip.fi_v);
410 if (!fp->fr_ifa)
411 fp->fr_ifa = (void *)-1;
414 fdp = &fp->fr_dif;
415 fp->fr_flags &= ~FR_DUP;
416 if (*fdp->fd_ifname) {
417 fdp->fd_ifp = GETUNIT(fdp->fd_ifname, fp->fr_ip.fi_v);
418 if (!fdp->fd_ifp)
419 fdp->fd_ifp = (struct ifnet *)-1;
420 else
421 fp->fr_flags |= FR_DUP;
424 fdp = &fp->fr_tif;
425 if (*fdp->fd_ifname) {
426 fdp->fd_ifp = GETUNIT(fdp->fd_ifname, fp->fr_ip.fi_v);
427 if (!fdp->fd_ifp)
428 fdp->fd_ifp = (struct ifnet *)-1;
432 * Look for a matching filter rule, but don't include the next or
433 * interface pointer in the comparison (fr_next, fr_ifa).
435 for (; (f = *ftail); ftail = &f->fr_next)
436 if (bcmp((char *)&f->fr_ip, (char *)&fp->fr_ip,
437 FR_CMPSIZ) == 0)
438 break;
441 * If zero'ing statistics, copy current to caller and zero.
443 if (req == SIOCZRLST) {
444 if (!f)
445 return ESRCH;
446 error = IWCOPYPTR((caddr_t)f, data, sizeof(*f));
447 if (error)
448 return error;
449 f->fr_hits = 0;
450 f->fr_bytes = 0;
451 return 0;
454 if (!f) {
455 if (req == SIOCINAFR || req == SIOCINIFR) {
456 ftail = fprev;
457 if (fp->fr_hits) {
458 while (--fp->fr_hits && (f = *ftail)) {
459 ftail = &f->fr_next;
463 f = NULL;
466 if (req == SIOCRMAFR || req == SIOCRMIFR) {
467 if (!f)
468 error = ESRCH;
469 else {
470 if (f->fr_ref > 1)
471 return EBUSY;
472 if (fg && fg->fg_head)
473 fg->fg_head->fr_ref--;
474 if (unit == IPL_LOGAUTH)
475 return fr_auth_ioctl(data, mode, req, f, ftail);
476 if (f->fr_grhead)
477 fr_delgroup((u_int)f->fr_grhead, fp->fr_flags,
478 unit, set);
479 fixskip(fprev, f, -1);
480 *ftail = f->fr_next;
481 KFREE(f);
483 } else {
484 if (f)
485 error = EEXIST;
486 else {
487 if (unit == IPL_LOGAUTH)
488 return fr_auth_ioctl(data, mode, req, f, ftail);
489 KMALLOC(f, frentry_t *);
490 if (f != NULL) {
491 if (fg && fg->fg_head)
492 fg->fg_head->fr_ref++;
493 bcopy((char *)fp, (char *)f, sizeof(*f));
494 f->fr_ref = 1;
495 f->fr_hits = 0;
496 f->fr_next = *ftail;
497 *ftail = f;
498 if (req == SIOCINIFR || req == SIOCINAFR)
499 fixskip(fprev, f, 1);
500 f->fr_grp = NULL;
501 if ((group = f->fr_grhead))
502 fg = fr_addgroup(group, f, unit, set);
503 } else
504 error = ENOMEM;
507 return (error);
511 #ifdef _KERNEL
513 * routines below for saving IP headers to buffer
515 int iplopen(struct inode *inode, struct file *file)
517 u_int min = GET_MINOR(inode->i_rdev);
519 if (IPL_LOGMAX < min)
520 min = ENXIO;
521 else {
522 MOD_INC_USE_COUNT;
523 min = 0;
525 return min;
529 void iplclose(struct inode *inode, struct file *file)
531 u_int min = GET_MINOR(inode->i_rdev);
533 if (IPL_LOGMAX >= min) {
534 MOD_DEC_USE_COUNT;
539 * iplread/ipllog
540 * both of these must operate with at least splnet() lest they be
541 * called during packet processing and cause an inconsistancy to appear in
542 * the filter lists.
544 int iplread(struct inode *inode, struct file *file, char *buf, int nbytes)
546 struct uio uiob, *uio = &uiob;
548 uio->uio_buf = buf;
549 uio->uio_resid = nbytes;
550 # ifdef IPFILTER_LOG
551 return ipflog_read(GET_MINOR(inode->i_rdev), uio);
552 # else
553 return ENXIO;
554 # endif
559 * send_reset - this could conceivably be a call to tcp_respond(), but that
560 * requires a large amount of setting up and isn't any more efficient.
562 int send_reset(ti, ifp)
563 struct tcpiphdr *ti;
564 struct ifnet *ifp;
566 tcphdr_t *tcp;
567 int tlen = 0;
568 ip_t *ip;
569 mb_t *m;
571 if (ti->ti_flags & TH_RST)
572 return -1; /* feedback loop */
574 m = alloc_skb(sizeof(tcpiphdr_t), GFP_ATOMIC);
575 if (m == NULL)
576 return -1;
578 if (ti->ti_flags & TH_SYN)
579 tlen = 1;
581 m->dev = ifp;
582 m->csum = 0;
583 ip = mtod(m, ip_t *);
584 m->h.iph = ip;
585 m->ip_hdr = NULL;
586 m->m_len = sizeof(tcpiphdr_t);
587 tcp = (tcphdr_t *)((char *)ip + sizeof(ip_t));
588 bzero((char *)ip, sizeof(tcpiphdr_t));
590 ip->ip_v = IPVERSION;
591 ip->ip_hl = sizeof(ip_t) >> 2;
592 ip->ip_tos = ((ip_t *)ti)->ip_tos;
593 ip->ip_p = ((ip_t *)ti)->ip_p;
594 ip->ip_id = ((ip_t *)ti)->ip_id;
595 ip->ip_len = htons(sizeof(tcpiphdr_t));
596 ip->ip_ttl = 127;
597 ip->ip_src.s_addr = ti->ti_dst.s_addr;
598 ip->ip_dst.s_addr = ti->ti_src.s_addr;
599 tcp->th_dport = ti->ti_sport;
600 tcp->th_sport = ti->ti_dport;
601 tcp->th_ack = htonl(ntohl(ti->ti_seq) + tlen);
602 tcp->th_off = sizeof(tcphdr_t) >> 2;
603 tcp->th_flags = TH_RST|TH_ACK;
605 ip->ip_sum = 0;
606 ip->ip_sum = ipf_cksum((u_short *)ip, sizeof(ip_t));
607 tcp->th_sum = fr_tcpsum(m, ip, tcp);
608 return ip_forward(m, NULL, IPFWD_NOTTLDEC, ip->ip_dst.s_addr);
612 size_t mbufchainlen(m0)
613 register mb_t *m0;
615 register size_t len = 0;
617 for (; m0; m0 = m0->m_next)
618 len += m0->m_len;
619 return len;
623 void ipfr_fastroute(m0, fin, fdp)
624 mb_t *m0;
625 fr_info_t *fin;
626 frdest_t *fdp;
628 #if notyet
629 register ip_t *ip, *mhip;
630 register mb_t *m = m0;
631 register struct route *ro;
632 struct ifnet *ifp = fdp->fd_ifp;
633 int len, off, error = 0;
634 int hlen = fin->fin_hlen;
635 struct route iproute;
636 struct sockaddr_in *dst;
638 ip = mtod(m0, ip_t *);
640 * Route packet.
642 ro = &iproute;
643 bzero((caddr_t)ro, sizeof (*ro));
644 dst = (struct sockaddr_in *)&ro->ro_dst;
645 dst->sin_family = AF_INET;
646 dst->sin_addr = fdp->fd_ip.s_addr ? fdp->fd_ip : ip->ip_dst;
648 * XXX -allocate route here
650 if (!ifp) {
651 if (!(fin->fin_fr->fr_flags & FR_FASTROUTE)) {
652 error = -2;
653 goto bad;
655 if (ro->ro_rt == 0 || (ifp = ro->ro_rt->rt_ifp) == 0) {
656 if (in_localaddr(ip->ip_dst))
657 error = EHOSTUNREACH;
658 else
659 error = ENETUNREACH;
660 goto bad;
662 if (ro->ro_rt->rt_flags & RTF_GATEWAY)
663 dst = (struct sockaddr_in *)&ro->ro_rt->rt_gateway;
665 ro->ro_rt->rt_use++;
668 * For input packets which are being "fastrouted", they won't
669 * go back through output filtering and miss their chance to get
670 * NAT'd.
672 (void) ip_natout(ip, hlen, fin);
673 if (fin->fin_out)
674 ip->ip_sum = 0;
676 * If small enough for interface, can just send directly.
678 if (ip->ip_len <= ifp->if_mtu) {
679 # ifndef sparc
680 ip->ip_id = htons(ip->ip_id);
681 ip->ip_len = htons(ip->ip_len);
682 ip->ip_off = htons(ip->ip_off);
683 # endif
684 if (!ip->ip_sum)
685 ip->ip_sum = in_cksum(m, hlen);
686 error = (*ifp->hard_start_xmit)(m, ifp, m);
687 goto done;
690 * Too large for interface; fragment if possible.
691 * Must be able to put at least 8 bytes per fragment.
693 if (ip->ip_off & IP_DF) {
694 error = EMSGSIZE;
695 goto bad;
697 len = (ifp->if_mtu - hlen) &~ 7;
698 if (len < 8) {
699 error = EMSGSIZE;
700 goto bad;
704 int mhlen, firstlen = len;
705 mb_t **mnext = &m->m_act;
708 * Loop through length of segment after first fragment,
709 * make new header and copy data of each part and link onto chain.
711 m0 = m;
712 mhlen = sizeof (struct ip);
713 for (off = hlen + len; off < ip->ip_len; off += len) {
714 MGET(m, M_DONTWAIT, MT_HEADER);
715 if (m == 0) {
716 error = ENOBUFS;
717 goto bad;
719 m->m_data += max_linkhdr;
720 mhip = mtod(m, struct ip *);
721 bcopy((char *)ip, (char *)mhip, sizeof(*ip));
722 if (hlen > sizeof (struct ip)) {
723 mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
724 mhip->ip_hl = mhlen >> 2;
726 m->m_len = mhlen;
727 mhip->ip_off = ((off - hlen) >> 3) + (ip->ip_off & ~IP_MF);
728 if (ip->ip_off & IP_MF)
729 mhip->ip_off |= IP_MF;
730 if (off + len >= ip->ip_len)
731 len = ip->ip_len - off;
732 else
733 mhip->ip_off |= IP_MF;
734 mhip->ip_len = htons((u_short)(len + mhlen));
735 m->m_next = m_copy(m0, off, len);
736 if (m->m_next == 0) {
737 error = ENOBUFS; /* ??? */
738 goto sendorfree;
740 # ifndef sparc
741 mhip->ip_off = htons((u_short)mhip->ip_off);
742 # endif
743 mhip->ip_sum = 0;
744 mhip->ip_sum = in_cksum(m, mhlen);
745 *mnext = m;
746 mnext = &m->m_act;
749 * Update first fragment by trimming what's been copied out
750 * and updating header, then send each fragment (in order).
752 m_adj(m0, hlen + firstlen - ip->ip_len);
753 ip->ip_len = htons((u_short)(hlen + firstlen));
754 ip->ip_off = htons((u_short)(ip->ip_off | IP_MF));
755 ip->ip_sum = 0;
756 ip->ip_sum = in_cksum(m0, hlen);
757 sendorfree:
758 for (m = m0; m; m = m0) {
759 m0 = m->m_act;
760 m->m_act = 0;
761 if (error == 0)
762 error = (*ifp->if_output)(ifp, m,
763 (struct sockaddr *)dst);
764 else
765 m_freem(m);
768 done:
769 if (!error)
770 ipl_frouteok[0]++;
771 else
772 ipl_frouteok[1]++;
774 if (ro->ro_rt) {
775 RTFREE(ro->ro_rt);
777 return;
778 bad:
779 m_freem(m);
780 goto done;
781 # endif
786 * Fake BSD uiomove() call.
788 int uiomove(caddr_t src, size_t ssize, int rw, struct uio *uio)
790 int error;
791 size_t mv = MIN(ssize, uio->uio_resid);
793 if (rw == UIO_READ) {
794 error = IWCOPY(src, (caddr_t)uio->uio_buf, mv);
795 } else if (rw == UIO_WRITE) {
796 error = IRCOPY((caddr_t)uio->uio_buf, src, mv);
797 } else
798 error = EINVAL;
799 if (!error) {
800 uio->uio_resid -= mv;
801 uio->uio_buf += mv;
803 return error;
806 # ifdef IPFILTER_LKM
807 # ifndef IPL_MAJOR
808 # define IPL_MAJOR 95
809 # endif
811 # ifndef IPL_NAME
812 # define IPL_NAME "/dev/ipl"
813 # endif
815 static struct file_operations ipl_fops = {
816 NULL, /* lseek */
817 iplread, /* read */
818 NULL, /* write */
819 NULL, /* readdir */
820 NULL, /* select */
821 iplioctl, /* ioctl */
822 NULL, /* mmap */
823 iplopen, /* open */
824 iplclose, /* release */
825 NULL, /* fsync */
826 NULL, /* fasync */
827 NULL, /* check_media_change */
828 NULL, /* revalidate */
832 int init_module(void)
834 int error = 0, major;
836 if (register_chrdev(IPL_MAJOR, "ipf", &ipl_fops)) {
837 printk("ipf: unable to get major number: %d\n", IPL_MAJOR);
838 return -EIO;
841 error = iplattach();
842 if (!error)
843 register_symtab(0);
844 return -error;
847 void cleanup_module(void)
849 unregister_chrdev(IPL_MAJOR, "ipf");
850 (void) ipldetach();
852 # endif /* IPFILTER_LKM */
853 #else /* #ifdef _KERNEL */
856 static int no_output __P((mb_t *m, struct ifnet *ifp))
858 return 0;
862 static int write_output __P((mb_t *m, struct ifnet *ifp))
864 FILE *fp;
865 char fname[32];
866 ip_t *ip;
868 ip = mtod(m, ip_t *);
869 sprintf(fname, "/tmp/%s", ifp->name);
870 if ((fp = fopen(fname, "a"))) {
871 fwrite((char *)ip, ntohs(ip->ip_len), 1, fp);
872 fclose(fp);
874 return 0;
878 struct ifnet *get_unit(name, v)
879 char *name;
880 int v;
882 struct ifnet *ifp, **ifa;
883 char ifname[32], *s;
885 for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) {
886 (void) sprintf(ifname, "%s", ifp->name);
887 if (!strcmp(name, ifname))
888 return ifp;
891 if (!ifneta) {
892 ifneta = (struct ifnet **)malloc(sizeof(ifp) * 2);
893 ifneta[1] = NULL;
894 ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp));
895 nifs = 1;
896 } else {
897 nifs++;
898 ifneta = (struct ifnet **)realloc(ifneta,
899 (nifs + 1) * sizeof(*ifa));
900 ifneta[nifs] = NULL;
901 ifneta[nifs - 1] = (struct ifnet *)malloc(sizeof(*ifp));
903 ifp = ifneta[nifs - 1];
905 for (s = name; *s && !isdigit(*s); s++)
907 if (*s && isdigit(*s)) {
908 ifp->name = (char *)malloc(s - name + 1);
909 strncpy(ifp->name, name, s - name);
910 ifp->name[s - name] = '\0';
911 } else {
912 ifp->name = strdup(name);
914 ifp->hard_start_xmit = no_output;
915 return ifp;
920 void init_ifp()
922 FILE *fp;
923 struct ifnet *ifp, **ifa;
924 char fname[32];
926 for (ifa = ifneta; ifa && (ifp = *ifa); ifa++) {
927 ifp->hard_start_xmit = write_output;
928 sprintf(fname, "/tmp/%s", ifp->name);
929 if ((fp = fopen(fname, "w")))
930 fclose(fp);
935 void ipfr_fastroute(ip, fin, fdp)
936 ip_t *ip;
937 fr_info_t *fin;
938 frdest_t *fdp;
940 struct ifnet *ifp = fdp->fd_ifp;
942 if (!ifp)
943 return; /* no routing table out here */
945 ip->ip_len = htons((u_short)ip->ip_len);
946 ip->ip_off = htons((u_short)(ip->ip_off | IP_MF));
947 ip->ip_sum = 0;
948 (*ifp->hard_start_xmit)((mb_t *)ip, ifp);
952 int ipllog __P((void))
954 verbose("l");
955 return 0;
959 int send_reset(ip, ifp)
960 ip_t *ip;
961 struct ifnet *ifp;
963 verbose("- TCP RST sent\n");
964 return 0;
968 int icmp_error(ip, ifp)
969 ip_t *ip;
970 struct ifnet *ifp;
972 verbose("- TCP RST sent\n");
973 return 0;
975 #endif /* _KERNEL */