1 /* $FreeBSD: stable/9/sys/contrib/ipfilter/netinet/ip_fil_freebsd.c 289211 2015-10-13 04:23:21Z cy $ */
2
3 /*
4 * Copyright (C) 1993-2003 by Darren Reed.
5 *
6 * See the IPFILTER.LICENCE file for details on licencing.
7 */
8 #if !defined(lint)
9 static const char sccsid[] = "@(#)ip_fil.c 2.41 6/5/96 (C) 1993-2000 Darren Reed";
10 static const char rcsid[] = "@(#)$Id: ip_fil_freebsd.c,v 2.53.2.50 2007/09/20 12:51:50 darrenr Exp $";
11 #endif
12
13 #if defined(KERNEL) || defined(_KERNEL)
14 # undef KERNEL
15 # undef _KERNEL
16 # define KERNEL 1
17 # define _KERNEL 1
18 #endif
19 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 400000) && \
20 !defined(KLD_MODULE) && !defined(IPFILTER_LKM)
21 # include "opt_inet6.h"
22 #endif
23 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 440000) && \
24 !defined(KLD_MODULE) && !defined(IPFILTER_LKM)
25 # include "opt_random_ip_id.h"
26 #endif
27 #include <sys/param.h>
28 #if defined(__FreeBSD__) && !defined(__FreeBSD_version)
29 # if defined(IPFILTER_LKM)
30 # ifndef __FreeBSD_cc_version
31 # include <osreldate.h>
32 # else
33 # if __FreeBSD_cc_version < 430000
34 # include <osreldate.h>
35 # endif
36 # endif
37 # endif
38 #endif
39 #include <sys/errno.h>
40 #include <sys/types.h>
41 #include <sys/file.h>
42 #if __FreeBSD_version >= 220000
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 #include <sys/systm.h>
50 # include <sys/dirent.h>
51 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 800000)
52 #include <sys/jail.h>
53 #endif
54 # include <sys/mbuf.h>
55 # include <sys/sockopt.h>
56 #if !defined(__hpux)
57 # include <sys/mbuf.h>
58 #endif
59 #include <sys/protosw.h>
60 #include <sys/socket.h>
61 #if __FreeBSD_version >= 500043
62 # include <sys/selinfo.h>
63 #else
64 # include <sys/select.h>
65 #endif
66 #if __FreeBSD_version >= 800044
67 # include <netinet/tcp_var.h>
68 #else
69 #define V_path_mtu_discovery path_mtu_discovery
70 #define V_ipforwarding ipforwarding
71 #endif
72
73 #include <net/if.h>
74 #if __FreeBSD_version >= 300000
75 # include <net/if_var.h>
76 # if __FreeBSD_version >= 500043
77 # include <net/netisr.h>
78 # endif
79 # if !defined(IPFILTER_LKM)
80 # include "opt_ipfilter.h"
81 # endif
82 #endif
83 #include <net/route.h>
84 #include <netinet/in.h>
85 #include <netinet/in_var.h>
86 #include <netinet/in_systm.h>
87 #include <netinet/ip.h>
88 #include <netinet/ip_var.h>
89 #include <netinet/tcp.h>
90 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 800000)
91 #include <net/vnet.h>
92 #else
93 #define CURVNET_SET(arg)
94 #define CURVNET_RESTORE()
95 #endif
96 #if defined(__osf__)
97 # include <netinet/tcp_timer.h>
98 #endif
99 #include <netinet/udp.h>
100 #include <netinet/tcpip.h>
101 #include <netinet/ip_icmp.h>
102 #ifndef _KERNEL
103 # include "netinet/ipf.h"
104 #endif
105 #include "netinet/ip_compat.h"
106 #ifdef USE_INET6
107 # include <netinet/icmp6.h>
108 #endif
109 #include "netinet/ip_fil.h"
110 #include "netinet/ip_nat.h"
111 #include "netinet/ip_frag.h"
112 #include "netinet/ip_state.h"
113 #include "netinet/ip_proxy.h"
114 #include "netinet/ip_auth.h"
115 #ifdef IPFILTER_SYNC
116 #include "netinet/ip_sync.h"
117 #endif
118 #ifdef IPFILTER_SCAN
119 #include "netinet/ip_scan.h"
120 #endif
121 #include "netinet/ip_pool.h"
122 #if defined(__FreeBSD_version) && (__FreeBSD_version >= 300000)
123 # include <sys/malloc.h>
124 #endif
125 #include <sys/kernel.h>
126 #ifdef CSUM_DATA_VALID
127 #include <machine/in_cksum.h>
128 #endif
129 extern int ip_optcopy __P((struct ip *, struct ip *));
130
131 #if (__FreeBSD_version > 460000) && (__FreeBSD_version < 800055)
132 extern int path_mtu_discovery;
133 #endif
134
135 # ifdef IPFILTER_M_IPFILTER
136 MALLOC_DEFINE(M_IPFILTER, "ipfilter", "IP Filter packet filter data structures");
137 # endif
138
139
140 #if !defined(__osf__)
141 extern struct protosw inetsw[];
142 #endif
143
144 static int (*fr_savep) __P((ip_t *, int, void *, int, struct mbuf **));
145 static int fr_send_ip __P((fr_info_t *, mb_t *, mb_t **));
146 # ifdef USE_MUTEXES
147 ipfmutex_t ipl_mutex, ipf_authmx, ipf_rw, ipf_stinsert;
148 ipfmutex_t ipf_nat_new, ipf_natio, ipf_timeoutlock;
149 ipfrwlock_t ipf_mutex, ipf_global, ipf_ipidfrag, ipf_frcache, ipf_tokens;
150 ipfrwlock_t ipf_frag, ipf_state, ipf_nat, ipf_natfrag, ipf_auth;
151 # endif
152 int ipf_locks_done = 0;
153
154 #if (__FreeBSD_version >= 300000)
155 struct callout_handle fr_slowtimer_ch;
156 #endif
157 struct selinfo ipfselwait[IPL_LOGSIZE];
158
159 #if (__FreeBSD_version >= 500011)
160 # include <sys/conf.h>
161 # if defined(NETBSD_PF)
162 # include <net/pfil.h>
163 # if (__FreeBSD_version < 501108)
164 # include <netinet/ipprotosw.h>
165 # endif
166 /*
167 * We provide the fr_checkp name just to minimize changes later.
168 */
169 int (*fr_checkp) __P((ip_t *ip, int hlen, void *ifp, int out, mb_t **mp));
170 # endif /* NETBSD_PF */
171 #endif /* __FreeBSD_version >= 500011 */
172
173
174 #if (__FreeBSD_version >= 502103)
175 static eventhandler_tag ipf_arrivetag, ipf_departtag, ipf_clonetag;
176
177 static void ipf_ifevent(void *arg);
178
ipf_ifevent(arg)179 static void ipf_ifevent(arg)
180 void *arg;
181 {
182 frsync(NULL);
183 }
184 #endif
185
186
187 #if (__FreeBSD_version >= 501108) && defined(_KERNEL)
188
189 static int
fr_check_wrapper(void * arg,struct mbuf ** mp,struct ifnet * ifp,int dir)190 fr_check_wrapper(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir)
191 {
192 struct ip *ip = mtod(*mp, struct ip *);
193 return fr_check(ip, ip->ip_hl << 2, ifp, (dir == PFIL_OUT), mp);
194 }
195
196 # ifdef USE_INET6
197 # include <netinet/ip6.h>
198
199 static int
fr_check_wrapper6(void * arg,struct mbuf ** mp,struct ifnet * ifp,int dir)200 fr_check_wrapper6(void *arg, struct mbuf **mp, struct ifnet *ifp, int dir)
201 {
202 return (fr_check(mtod(*mp, struct ip *), sizeof(struct ip6_hdr),
203 ifp, (dir == PFIL_OUT), mp));
204 }
205 # endif
206 #endif /* __FreeBSD_version >= 501108 */
207 #if defined(IPFILTER_LKM)
iplidentify(s)208 int iplidentify(s)
209 char *s;
210 {
211 if (strcmp(s, "ipl") == 0)
212 return 1;
213 return 0;
214 }
215 #endif /* IPFILTER_LKM */
216
217
ipfattach()218 int ipfattach()
219 {
220 #ifdef USE_SPL
221 int s;
222 #endif
223
224 SPL_NET(s);
225 if (fr_running > 0) {
226 SPL_X(s);
227 return EBUSY;
228 }
229
230 MUTEX_INIT(&ipf_rw, "ipf rw mutex");
231 MUTEX_INIT(&ipf_timeoutlock, "ipf timeout queue mutex");
232 RWLOCK_INIT(&ipf_ipidfrag, "ipf IP NAT-Frag rwlock");
233 RWLOCK_INIT(&ipf_tokens, "ipf token rwlock");
234 ipf_locks_done = 1;
235
236 if (fr_initialise() < 0) {
237 SPL_X(s);
238 return EIO;
239 }
240
241
242 if (fr_checkp != fr_check) {
243 fr_savep = fr_checkp;
244 fr_checkp = fr_check;
245 }
246
247 bzero((char *)ipfselwait, sizeof(ipfselwait));
248 bzero((char *)frcache, sizeof(frcache));
249 fr_running = 1;
250
251 if (fr_control_forwarding & 1)
252 V_ipforwarding = 1;
253
254 SPL_X(s);
255 #if (__FreeBSD_version >= 300000)
256 fr_slowtimer_ch = timeout(fr_slowtimer, NULL,
257 (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT);
258 #else
259 timeout(fr_slowtimer, NULL, (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT);
260 #endif
261 return 0;
262 }
263
264
265 /*
266 * Disable the filter by removing the hooks from the IP input/output
267 * stream.
268 */
ipfdetach()269 int ipfdetach()
270 {
271 #ifdef USE_SPL
272 int s;
273 #endif
274 if (fr_control_forwarding & 2)
275 V_ipforwarding = 0;
276
277 SPL_NET(s);
278
279 #if (__FreeBSD_version >= 300000)
280 if (fr_slowtimer_ch.callout != NULL)
281 untimeout(fr_slowtimer, NULL, fr_slowtimer_ch);
282 bzero(&fr_slowtimer_ch, sizeof(fr_slowtimer_ch));
283 #else
284 untimeout(fr_slowtimer, NULL);
285 #endif /* FreeBSD */
286
287 #ifndef NETBSD_PF
288 if (fr_checkp != NULL)
289 fr_checkp = fr_savep;
290 fr_savep = NULL;
291 #endif
292
293 fr_deinitialise();
294
295 fr_running = -2;
296
297 (void) frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE|FR_INACTIVE);
298 (void) frflush(IPL_LOGIPF, 0, FR_INQUE|FR_OUTQUE);
299
300 if (ipf_locks_done == 1) {
301 MUTEX_DESTROY(&ipf_timeoutlock);
302 MUTEX_DESTROY(&ipf_rw);
303 RW_DESTROY(&ipf_ipidfrag);
304 RW_DESTROY(&ipf_tokens);
305 ipf_locks_done = 0;
306 }
307
308 SPL_X(s);
309
310 return 0;
311 }
312
313
314 /*
315 * Filter ioctl interface.
316 */
iplioctl(dev,cmd,data,mode,p)317 int iplioctl(dev, cmd, data, mode
318 # if defined(_KERNEL) && ((BSD >= 199506) || (__FreeBSD_version >= 220000))
319 , p)
320 # if (__FreeBSD_version >= 500024)
321 struct thread *p;
322 # if (__FreeBSD_version >= 500043)
323 # define p_cred td_ucred
324 # define p_uid td_ucred->cr_ruid
325 # else
326 # define p_cred t_proc->p_cred
327 # define p_uid t_proc->p_cred->p_ruid
328 # endif
329 # else
330 struct proc *p;
331 # define p_uid p_cred->p_ruid
332 # endif /* __FreeBSD_version >= 500024 */
333 # else
334 )
335 # endif
336 #if defined(_KERNEL) && (__FreeBSD_version >= 502116)
337 struct cdev *dev;
338 #else
339 dev_t dev;
340 #endif
341 ioctlcmd_t cmd;
342 caddr_t data;
343 int mode;
344 {
345 int error = 0, unit = 0;
346 SPL_INT(s);
347
348 #if (BSD >= 199306) && defined(_KERNEL)
349 # if (__FreeBSD_version >= 500034)
350 if (securelevel_ge(p->p_cred, 3) && (mode & FWRITE))
351 # else
352 if ((securelevel >= 3) && (mode & FWRITE))
353 # endif
354 return EPERM;
355 #endif
356
357 unit = GET_MINOR(dev);
358 if ((IPL_LOGMAX < unit) || (unit < 0))
359 return ENXIO;
360
361 if (fr_running <= 0) {
362 if (unit != IPL_LOGIPF)
363 return EIO;
364 if (cmd != SIOCIPFGETNEXT && cmd != SIOCIPFGET &&
365 cmd != SIOCIPFSET && cmd != SIOCFRENB &&
366 cmd != SIOCGETFS && cmd != SIOCGETFF)
367 return EIO;
368 }
369
370 SPL_NET(s);
371
372 CURVNET_SET(TD_TO_VNET(p));
373 error = fr_ioctlswitch(unit, data, cmd, mode, p->p_uid, p);
374 CURVNET_RESTORE();
375 if (error != -1) {
376 SPL_X(s);
377 return error;
378 }
379
380 SPL_X(s);
381
382 return error;
383 }
384
385
386 #if 0
387 void fr_forgetifp(ifp)
388 void *ifp;
389 {
390 register frentry_t *f;
391
392 WRITE_ENTER(&ipf_mutex);
393 for (f = ipacct[0][fr_active]; (f != NULL); f = f->fr_next)
394 if (f->fr_ifa == ifp)
395 f->fr_ifa = (void *)-1;
396 for (f = ipacct[1][fr_active]; (f != NULL); f = f->fr_next)
397 if (f->fr_ifa == ifp)
398 f->fr_ifa = (void *)-1;
399 for (f = ipfilter[0][fr_active]; (f != NULL); f = f->fr_next)
400 if (f->fr_ifa == ifp)
401 f->fr_ifa = (void *)-1;
402 for (f = ipfilter[1][fr_active]; (f != NULL); f = f->fr_next)
403 if (f->fr_ifa == ifp)
404 f->fr_ifa = (void *)-1;
405 #ifdef USE_INET6
406 for (f = ipacct6[0][fr_active]; (f != NULL); f = f->fr_next)
407 if (f->fr_ifa == ifp)
408 f->fr_ifa = (void *)-1;
409 for (f = ipacct6[1][fr_active]; (f != NULL); f = f->fr_next)
410 if (f->fr_ifa == ifp)
411 f->fr_ifa = (void *)-1;
412 for (f = ipfilter6[0][fr_active]; (f != NULL); f = f->fr_next)
413 if (f->fr_ifa == ifp)
414 f->fr_ifa = (void *)-1;
415 for (f = ipfilter6[1][fr_active]; (f != NULL); f = f->fr_next)
416 if (f->fr_ifa == ifp)
417 f->fr_ifa = (void *)-1;
418 #endif
419 RWLOCK_EXIT(&ipf_mutex);
420 fr_natsync(ifp);
421 }
422 #endif
423
424
425 /*
426 * routines below for saving IP headers to buffer
427 */
iplopen(dev,flags,devtype,p)428 int iplopen(dev, flags
429 #if ((BSD >= 199506) || (__FreeBSD_version >= 220000)) && defined(_KERNEL)
430 , devtype, p)
431 int devtype;
432 # if (__FreeBSD_version >= 500024)
433 struct thread *p;
434 # else
435 struct proc *p;
436 # endif /* __FreeBSD_version >= 500024 */
437 #else
438 )
439 #endif
440 #if defined(_KERNEL) && (__FreeBSD_version >= 502116)
441 struct cdev *dev;
442 #else
443 dev_t dev;
444 #endif
445 int flags;
446 {
447 u_int min = GET_MINOR(dev);
448
449 if (IPL_LOGMAX < min)
450 min = ENXIO;
451 else
452 min = 0;
453 return min;
454 }
455
456
iplclose(dev,flags,devtype,p)457 int iplclose(dev, flags
458 #if ((BSD >= 199506) || (__FreeBSD_version >= 220000)) && defined(_KERNEL)
459 , devtype, p)
460 int devtype;
461 # if (__FreeBSD_version >= 500024)
462 struct thread *p;
463 # else
464 struct proc *p;
465 # endif /* __FreeBSD_version >= 500024 */
466 #else
467 )
468 #endif
469 #if defined(_KERNEL) && (__FreeBSD_version >= 502116)
470 struct cdev *dev;
471 #else
472 dev_t dev;
473 #endif
474 int flags;
475 {
476 u_int min = GET_MINOR(dev);
477
478 if (IPL_LOGMAX < min)
479 min = ENXIO;
480 else
481 min = 0;
482 return min;
483 }
484
485 /*
486 * iplread/ipllog
487 * both of these must operate with at least splnet() lest they be
488 * called during packet processing and cause an inconsistancy to appear in
489 * the filter lists.
490 */
491 #if (BSD >= 199306)
iplread(dev,uio,ioflag)492 int iplread(dev, uio, ioflag)
493 int ioflag;
494 #else
495 int iplread(dev, uio)
496 #endif
497 #if defined(_KERNEL) && (__FreeBSD_version >= 502116)
498 struct cdev *dev;
499 #else
500 dev_t dev;
501 #endif
502 register struct uio *uio;
503 {
504 u_int xmin = GET_MINOR(dev);
505
506 if (fr_running < 1)
507 return EIO;
508
509 if (xmin < 0)
510 return ENXIO;
511
512 # ifdef IPFILTER_SYNC
513 if (xmin == IPL_LOGSYNC)
514 return ipfsync_read(uio);
515 # endif
516
517 #ifdef IPFILTER_LOG
518 return ipflog_read(xmin, uio);
519 #else
520 return ENXIO;
521 #endif
522 }
523
524
525 /*
526 * iplwrite
527 * both of these must operate with at least splnet() lest they be
528 * called during packet processing and cause an inconsistancy to appear in
529 * the filter lists.
530 */
531 #if (BSD >= 199306)
iplwrite(dev,uio,ioflag)532 int iplwrite(dev, uio, ioflag)
533 int ioflag;
534 #else
535 int iplwrite(dev, uio)
536 #endif
537 #if defined(_KERNEL) && (__FreeBSD_version >= 502116)
538 struct cdev *dev;
539 #else
540 dev_t dev;
541 #endif
542 register struct uio *uio;
543 {
544
545 if (fr_running < 1)
546 return EIO;
547
548 #ifdef IPFILTER_SYNC
549 if (GET_MINOR(dev) == IPL_LOGSYNC)
550 return ipfsync_write(uio);
551 #endif
552 return ENXIO;
553 }
554
555
556 /*
557 * fr_send_reset - this could conceivably be a call to tcp_respond(), but that
558 * requires a large amount of setting up and isn't any more efficient.
559 */
fr_send_reset(fin)560 int fr_send_reset(fin)
561 fr_info_t *fin;
562 {
563 struct tcphdr *tcp, *tcp2;
564 int tlen = 0, hlen;
565 struct mbuf *m;
566 #ifdef USE_INET6
567 ip6_t *ip6;
568 #endif
569 ip_t *ip;
570
571 tcp = fin->fin_dp;
572 if (tcp->th_flags & TH_RST)
573 return -1; /* feedback loop */
574
575 if (fr_checkl4sum(fin) == -1)
576 return -1;
577
578 tlen = fin->fin_dlen - (TCP_OFF(tcp) << 2) +
579 ((tcp->th_flags & TH_SYN) ? 1 : 0) +
580 ((tcp->th_flags & TH_FIN) ? 1 : 0);
581
582 #ifdef USE_INET6
583 hlen = (fin->fin_v == 6) ? sizeof(ip6_t) : sizeof(ip_t);
584 #else
585 hlen = sizeof(ip_t);
586 #endif
587 #ifdef MGETHDR
588 MGETHDR(m, M_DONTWAIT, MT_HEADER);
589 #else
590 MGET(m, M_DONTWAIT, MT_HEADER);
591 #endif
592 if (m == NULL)
593 return -1;
594 if (sizeof(*tcp2) + hlen > MLEN) {
595 MCLGET(m, M_DONTWAIT);
596 if ((m->m_flags & M_EXT) == 0) {
597 FREE_MB_T(m);
598 return -1;
599 }
600 }
601
602 m->m_len = sizeof(*tcp2) + hlen;
603 #if (BSD >= 199103)
604 m->m_data += max_linkhdr;
605 m->m_pkthdr.len = m->m_len;
606 m->m_pkthdr.rcvif = (struct ifnet *)0;
607 #endif
608 ip = mtod(m, struct ip *);
609 bzero((char *)ip, hlen);
610 #ifdef USE_INET6
611 ip6 = (ip6_t *)ip;
612 #endif
613 tcp2 = (struct tcphdr *)((char *)ip + hlen);
614 tcp2->th_sport = tcp->th_dport;
615 tcp2->th_dport = tcp->th_sport;
616
617 if (tcp->th_flags & TH_ACK) {
618 tcp2->th_seq = tcp->th_ack;
619 tcp2->th_flags = TH_RST;
620 tcp2->th_ack = 0;
621 } else {
622 tcp2->th_seq = 0;
623 tcp2->th_ack = ntohl(tcp->th_seq);
624 tcp2->th_ack += tlen;
625 tcp2->th_ack = htonl(tcp2->th_ack);
626 tcp2->th_flags = TH_RST|TH_ACK;
627 }
628 TCP_X2_A(tcp2, 0);
629 TCP_OFF_A(tcp2, sizeof(*tcp2) >> 2);
630 tcp2->th_win = tcp->th_win;
631 tcp2->th_sum = 0;
632 tcp2->th_urp = 0;
633
634 #ifdef USE_INET6
635 if (fin->fin_v == 6) {
636 ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow;
637 ip6->ip6_plen = htons(sizeof(struct tcphdr));
638 ip6->ip6_nxt = IPPROTO_TCP;
639 ip6->ip6_hlim = 0;
640 ip6->ip6_src = fin->fin_dst6;
641 ip6->ip6_dst = fin->fin_src6;
642 tcp2->th_sum = in6_cksum(m, IPPROTO_TCP,
643 sizeof(*ip6), sizeof(*tcp2));
644 return fr_send_ip(fin, m, &m);
645 }
646 #endif
647 ip->ip_p = IPPROTO_TCP;
648 ip->ip_len = htons(sizeof(struct tcphdr));
649 ip->ip_src.s_addr = fin->fin_daddr;
650 ip->ip_dst.s_addr = fin->fin_saddr;
651 tcp2->th_sum = in_cksum(m, hlen + sizeof(*tcp2));
652 ip->ip_len = hlen + sizeof(*tcp2);
653 return fr_send_ip(fin, m, &m);
654 }
655
656
fr_send_ip(fin,m,mpp)657 static int fr_send_ip(fin, m, mpp)
658 fr_info_t *fin;
659 mb_t *m, **mpp;
660 {
661 fr_info_t fnew;
662 ip_t *ip, *oip;
663 int hlen;
664
665 ip = mtod(m, ip_t *);
666 bzero((char *)&fnew, sizeof(fnew));
667
668 IP_V_A(ip, fin->fin_v);
669 switch (fin->fin_v)
670 {
671 case 4 :
672 fnew.fin_v = 4;
673 oip = fin->fin_ip;
674 IP_HL_A(ip, sizeof(*oip) >> 2);
675 ip->ip_tos = oip->ip_tos;
676 ip->ip_id = fin->fin_ip->ip_id;
677 #if (__FreeBSD_version > 460000)
678 ip->ip_off = V_path_mtu_discovery ? IP_DF : 0;
679 #else
680 ip->ip_off = 0;
681 #endif
682 ip->ip_ttl = V_ip_defttl;
683 ip->ip_sum = 0;
684 hlen = sizeof(*oip);
685 break;
686 #ifdef USE_INET6
687 case 6 :
688 {
689 ip6_t *ip6 = (ip6_t *)ip;
690
691 ip6->ip6_vfc = 0x60;
692 ip6->ip6_hlim = IPDEFTTL;
693
694 fnew.fin_v = 6;
695 hlen = sizeof(*ip6);
696 break;
697 }
698 #endif
699 default :
700 return EINVAL;
701 }
702 #ifdef IPSEC
703 m->m_pkthdr.rcvif = NULL;
704 #endif
705
706 fnew.fin_ifp = fin->fin_ifp;
707 fnew.fin_flx = FI_NOCKSUM;
708 fnew.fin_m = m;
709 fnew.fin_ip = ip;
710 fnew.fin_mp = mpp;
711 fnew.fin_hlen = hlen;
712 fnew.fin_dp = (char *)ip + hlen;
713 (void) fr_makefrip(hlen, ip, &fnew);
714
715 return fr_fastroute(m, mpp, &fnew, NULL);
716 }
717
718
fr_send_icmp_err(type,fin,dst)719 int fr_send_icmp_err(type, fin, dst)
720 int type;
721 fr_info_t *fin;
722 int dst;
723 {
724 int err, hlen, xtra, iclen, ohlen, avail, code;
725 struct in_addr dst4;
726 struct icmp *icmp;
727 struct mbuf *m;
728 void *ifp;
729 #ifdef USE_INET6
730 ip6_t *ip6;
731 struct in6_addr dst6;
732 #endif
733 ip_t *ip, *ip2;
734
735 if ((type < 0) || (type >= ICMP_MAXTYPE))
736 return -1;
737
738 code = fin->fin_icode;
739 #ifdef USE_INET6
740 if ((code < 0) || (code > sizeof(icmptoicmp6unreach)/sizeof(int)))
741 return -1;
742 #endif
743
744 if (fr_checkl4sum(fin) == -1)
745 return -1;
746 #ifdef MGETHDR
747 MGETHDR(m, M_DONTWAIT, MT_HEADER);
748 #else
749 MGET(m, M_DONTWAIT, MT_HEADER);
750 #endif
751 if (m == NULL)
752 return -1;
753 avail = MHLEN;
754
755 xtra = 0;
756 hlen = 0;
757 ohlen = 0;
758 ifp = fin->fin_ifp;
759 if (fin->fin_v == 4) {
760 if ((fin->fin_p == IPPROTO_ICMP) &&
761 !(fin->fin_flx & FI_SHORT))
762 switch (ntohs(fin->fin_data[0]) >> 8)
763 {
764 case ICMP_ECHO :
765 case ICMP_TSTAMP :
766 case ICMP_IREQ :
767 case ICMP_MASKREQ :
768 break;
769 default :
770 FREE_MB_T(m);
771 return 0;
772 }
773
774 if (dst == 0) {
775 if (fr_ifpaddr(4, FRI_NORMAL, ifp,
776 &dst4, NULL) == -1) {
777 FREE_MB_T(m);
778 return -1;
779 }
780 } else
781 dst4.s_addr = fin->fin_daddr;
782
783 hlen = sizeof(ip_t);
784 ohlen = fin->fin_hlen;
785 if (fin->fin_hlen < fin->fin_plen)
786 xtra = MIN(fin->fin_dlen, 8);
787 else
788 xtra = 0;
789 }
790
791 #ifdef USE_INET6
792 else if (fin->fin_v == 6) {
793 hlen = sizeof(ip6_t);
794 ohlen = sizeof(ip6_t);
795 type = icmptoicmp6types[type];
796 if (type == ICMP6_DST_UNREACH)
797 code = icmptoicmp6unreach[code];
798
799 if (hlen + sizeof(*icmp) + max_linkhdr +
800 fin->fin_plen > avail) {
801 MCLGET(m, M_DONTWAIT);
802 if ((m->m_flags & M_EXT) == 0) {
803 FREE_MB_T(m);
804 return -1;
805 }
806 avail = MCLBYTES;
807 }
808 xtra = MIN(fin->fin_plen,
809 avail - hlen - sizeof(*icmp) - max_linkhdr);
810 if (dst == 0) {
811 if (fr_ifpaddr(6, FRI_NORMAL, ifp,
812 (struct in_addr *)&dst6, NULL) == -1) {
813 FREE_MB_T(m);
814 return -1;
815 }
816 } else
817 dst6 = fin->fin_dst6;
818 }
819 #endif
820 else {
821 FREE_MB_T(m);
822 return -1;
823 }
824
825 iclen = hlen + sizeof(*icmp);
826 avail -= (max_linkhdr + iclen);
827 if (avail < 0) {
828 FREE_MB_T(m);
829 return -1;
830 }
831 if (xtra > avail)
832 xtra = avail;
833 iclen += xtra;
834 m->m_data += max_linkhdr;
835 m->m_pkthdr.rcvif = (struct ifnet *)0;
836 m->m_pkthdr.len = iclen;
837 m->m_len = iclen;
838 ip = mtod(m, ip_t *);
839 icmp = (struct icmp *)((char *)ip + hlen);
840 ip2 = (ip_t *)&icmp->icmp_ip;
841
842 icmp->icmp_type = type;
843 icmp->icmp_code = fin->fin_icode;
844 icmp->icmp_cksum = 0;
845 #ifdef icmp_nextmtu
846 if (type == ICMP_UNREACH &&
847 fin->fin_icode == ICMP_UNREACH_NEEDFRAG && ifp)
848 icmp->icmp_nextmtu = htons(((struct ifnet *)ifp)->if_mtu);
849 #endif
850
851 bcopy((char *)fin->fin_ip, (char *)ip2, ohlen);
852
853 #ifdef USE_INET6
854 ip6 = (ip6_t *)ip;
855 if (fin->fin_v == 6) {
856 ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow;
857 ip6->ip6_plen = htons(iclen - hlen);
858 ip6->ip6_nxt = IPPROTO_ICMPV6;
859 ip6->ip6_hlim = 0;
860 ip6->ip6_src = dst6;
861 ip6->ip6_dst = fin->fin_src6;
862 if (xtra > 0)
863 bcopy((char *)fin->fin_ip + ohlen,
864 (char *)&icmp->icmp_ip + ohlen, xtra);
865 icmp->icmp_cksum = in6_cksum(m, IPPROTO_ICMPV6,
866 sizeof(*ip6), iclen - hlen);
867 } else
868 #endif
869 {
870 ip2->ip_len = htons(ip2->ip_len);
871 ip2->ip_off = htons(ip2->ip_off);
872 ip->ip_p = IPPROTO_ICMP;
873 ip->ip_src.s_addr = dst4.s_addr;
874 ip->ip_dst.s_addr = fin->fin_saddr;
875
876 if (xtra > 0)
877 bcopy((char *)fin->fin_ip + ohlen,
878 (char *)&icmp->icmp_ip + ohlen, xtra);
879 icmp->icmp_cksum = ipf_cksum((u_short *)icmp,
880 sizeof(*icmp) + 8);
881 ip->ip_len = iclen;
882 ip->ip_p = IPPROTO_ICMP;
883 }
884 err = fr_send_ip(fin, m, &m);
885 return err;
886 }
887
888
889 #if !defined(IPFILTER_LKM) && (__FreeBSD_version < 300000)
890 # if (BSD < 199306)
891 int iplinit __P((void));
892
893 int
894 # else
895 void iplinit __P((void));
896
897 void
898 # endif
iplinit()899 iplinit()
900 {
901 if (ipfattach() != 0)
902 printf("IP Filter failed to attach\n");
903 ip_init();
904 }
905 #endif /* __FreeBSD_version < 300000 */
906
907
908 /*
909 * m0 - pointer to mbuf where the IP packet starts
910 * mpp - pointer to the mbuf pointer that is the start of the mbuf chain
911 */
fr_fastroute(m0,mpp,fin,fdp)912 int fr_fastroute(m0, mpp, fin, fdp)
913 mb_t *m0, **mpp;
914 fr_info_t *fin;
915 frdest_t *fdp;
916 {
917 register struct ip *ip, *mhip;
918 register struct mbuf *m = *mpp;
919 register struct route *ro;
920 int len, off, error = 0, hlen, code;
921 struct ifnet *ifp, *sifp;
922 struct sockaddr_in *dst;
923 struct route iproute;
924 u_short ip_off;
925 frentry_t *fr;
926
927 ro = NULL;
928
929 #ifdef M_WRITABLE
930 /*
931 * HOT FIX/KLUDGE:
932 *
933 * If the mbuf we're about to send is not writable (because of
934 * a cluster reference, for example) we'll need to make a copy
935 * of it since this routine modifies the contents.
936 *
937 * If you have non-crappy network hardware that can transmit data
938 * from the mbuf, rather than making a copy, this is gonna be a
939 * problem.
940 */
941 if (M_WRITABLE(m) == 0) {
942 m0 = m_dup(m, M_DONTWAIT);
943 if (m0 != 0) {
944 FREE_MB_T(m);
945 m = m0;
946 *mpp = m;
947 } else {
948 error = ENOBUFS;
949 FREE_MB_T(m);
950 goto done;
951 }
952 }
953 #endif
954
955 #ifdef USE_INET6
956 if (fin->fin_v == 6) {
957 /*
958 * currently "to <if>" and "to <if>:ip#" are not supported
959 * for IPv6
960 */
961 #if (__FreeBSD_version >= 490000)
962 return ip6_output(m0, NULL, NULL, 0, NULL, NULL, NULL);
963 #else
964 return ip6_output(m0, NULL, NULL, 0, NULL, NULL);
965 #endif
966 }
967 #endif
968
969 hlen = fin->fin_hlen;
970 ip = mtod(m0, struct ip *);
971
972 /*
973 * Route packet.
974 */
975 ro = &iproute;
976 bzero((caddr_t)ro, sizeof (*ro));
977 dst = (struct sockaddr_in *)&ro->ro_dst;
978 dst->sin_family = AF_INET;
979 dst->sin_addr = ip->ip_dst;
980
981 fr = fin->fin_fr;
982 if (fdp != NULL)
983 ifp = fdp->fd_ifp;
984 else
985 ifp = fin->fin_ifp;
986
987 if ((ifp == NULL) && (!fr || !(fr->fr_flags & FR_FASTROUTE))) {
988 error = -2;
989 goto bad;
990 }
991
992 if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0))
993 dst->sin_addr = fdp->fd_ip;
994
995 dst->sin_len = sizeof(*dst);
996 in_rtalloc(ro, 0);
997
998 if ((ifp == NULL) && (ro->ro_rt != NULL))
999 ifp = ro->ro_rt->rt_ifp;
1000
1001 if ((ro->ro_rt == NULL) || (ifp == NULL)) {
1002 if (in_localaddr(ip->ip_dst))
1003 error = EHOSTUNREACH;
1004 else
1005 error = ENETUNREACH;
1006 goto bad;
1007 }
1008 if (ro->ro_rt->rt_flags & RTF_GATEWAY)
1009 dst = (struct sockaddr_in *)ro->ro_rt->rt_gateway;
1010 if (ro->ro_rt)
1011 ro->ro_rt->rt_use++;
1012
1013 /*
1014 * For input packets which are being "fastrouted", they won't
1015 * go back through output filtering and miss their chance to get
1016 * NAT'd and counted. Duplicated packets aren't considered to be
1017 * part of the normal packet stream, so do not NAT them or pass
1018 * them through stateful checking, etc.
1019 */
1020 if ((fdp != &fr->fr_dif) && (fin->fin_out == 0)) {
1021 sifp = fin->fin_ifp;
1022 fin->fin_ifp = ifp;
1023 fin->fin_out = 1;
1024 (void) fr_acctpkt(fin, NULL);
1025 fin->fin_fr = NULL;
1026 if (!fr || !(fr->fr_flags & FR_RETMASK)) {
1027 u_32_t pass;
1028
1029 if (fr_checkstate(fin, &pass) != NULL)
1030 fr_statederef((ipstate_t **)&fin->fin_state);
1031 }
1032
1033 switch (fr_checknatout(fin, NULL))
1034 {
1035 case 0 :
1036 break;
1037 case 1 :
1038 fr_natderef((nat_t **)&fin->fin_nat);
1039 ip->ip_sum = 0;
1040 break;
1041 case -1 :
1042 error = -1;
1043 goto bad;
1044 break;
1045 }
1046
1047 fin->fin_ifp = sifp;
1048 fin->fin_out = 0;
1049 } else
1050 ip->ip_sum = 0;
1051 /*
1052 * If small enough for interface, can just send directly.
1053 */
1054 if (ip->ip_len <= ifp->if_mtu) {
1055 ip->ip_len = htons(ip->ip_len);
1056 ip->ip_off = htons(ip->ip_off);
1057
1058 if (!ip->ip_sum)
1059 ip->ip_sum = in_cksum(m, hlen);
1060 error = (*ifp->if_output)(ifp, m, (struct sockaddr *)dst,
1061 ro);
1062 goto done;
1063 }
1064 /*
1065 * Too large for interface; fragment if possible.
1066 * Must be able to put at least 8 bytes per fragment.
1067 */
1068 ip_off = ntohs(ip->ip_off);
1069 if (ip_off & IP_DF) {
1070 error = EMSGSIZE;
1071 goto bad;
1072 }
1073 len = (ifp->if_mtu - hlen) &~ 7;
1074 if (len < 8) {
1075 error = EMSGSIZE;
1076 goto bad;
1077 }
1078
1079 {
1080 int mhlen, firstlen = len;
1081 struct mbuf **mnext = &m->m_act;
1082
1083 /*
1084 * Loop through length of segment after first fragment,
1085 * make new header and copy data of each part and link onto chain.
1086 */
1087 m0 = m;
1088 mhlen = sizeof (struct ip);
1089 for (off = hlen + len; off < ip->ip_len; off += len) {
1090 #ifdef MGETHDR
1091 MGETHDR(m, M_DONTWAIT, MT_HEADER);
1092 #else
1093 MGET(m, M_DONTWAIT, MT_HEADER);
1094 #endif
1095 if (m == 0) {
1096 m = m0;
1097 error = ENOBUFS;
1098 goto bad;
1099 }
1100 m->m_data += max_linkhdr;
1101 mhip = mtod(m, struct ip *);
1102 bcopy((char *)ip, (char *)mhip, sizeof(*ip));
1103 if (hlen > sizeof (struct ip)) {
1104 mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
1105 IP_HL_A(mhip, mhlen >> 2);
1106 }
1107 m->m_len = mhlen;
1108 mhip->ip_off = ((off - hlen) >> 3) + ip_off;
1109 if (off + len >= ip->ip_len)
1110 len = ip->ip_len - off;
1111 else
1112 mhip->ip_off |= IP_MF;
1113 mhip->ip_len = htons((u_short)(len + mhlen));
1114 *mnext = m;
1115 m->m_next = m_copy(m0, off, len);
1116 if (m->m_next == 0) {
1117 error = ENOBUFS; /* ??? */
1118 goto sendorfree;
1119 }
1120 m->m_pkthdr.len = mhlen + len;
1121 m->m_pkthdr.rcvif = NULL;
1122 mhip->ip_off = htons((u_short)mhip->ip_off);
1123 mhip->ip_sum = 0;
1124 mhip->ip_sum = in_cksum(m, mhlen);
1125 mnext = &m->m_act;
1126 }
1127 /*
1128 * Update first fragment by trimming what's been copied out
1129 * and updating header, then send each fragment (in order).
1130 */
1131 m_adj(m0, hlen + firstlen - ip->ip_len);
1132 ip->ip_len = htons((u_short)(hlen + firstlen));
1133 ip->ip_off = htons((u_short)IP_MF);
1134 ip->ip_sum = 0;
1135 ip->ip_sum = in_cksum(m0, hlen);
1136 sendorfree:
1137 for (m = m0; m; m = m0) {
1138 m0 = m->m_act;
1139 m->m_act = 0;
1140 if (error == 0)
1141 error = (*ifp->if_output)(ifp, m,
1142 (struct sockaddr *)dst, ro);
1143 else
1144 FREE_MB_T(m);
1145 }
1146 }
1147 done:
1148 if (!error)
1149 fr_frouteok[0]++;
1150 else
1151 fr_frouteok[1]++;
1152
1153 if ((ro != NULL) && (ro->ro_rt != NULL)) {
1154 RTFREE(ro->ro_rt);
1155 }
1156 *mpp = NULL;
1157 return 0;
1158 bad:
1159 if (error == EMSGSIZE) {
1160 sifp = fin->fin_ifp;
1161 code = fin->fin_icode;
1162 fin->fin_icode = ICMP_UNREACH_NEEDFRAG;
1163 fin->fin_ifp = ifp;
1164 (void) fr_send_icmp_err(ICMP_UNREACH, fin, 1);
1165 fin->fin_ifp = sifp;
1166 fin->fin_icode = code;
1167 }
1168 FREE_MB_T(m);
1169 goto done;
1170 }
1171
1172
fr_verifysrc(fin)1173 int fr_verifysrc(fin)
1174 fr_info_t *fin;
1175 {
1176 struct sockaddr_in *dst;
1177 struct route iproute;
1178
1179 bzero((char *)&iproute, sizeof(iproute));
1180 dst = (struct sockaddr_in *)&iproute.ro_dst;
1181 dst->sin_len = sizeof(*dst);
1182 dst->sin_family = AF_INET;
1183 dst->sin_addr = fin->fin_src;
1184 in_rtalloc(&iproute, 0);
1185 if (iproute.ro_rt == NULL)
1186 return 0;
1187 return (fin->fin_ifp == iproute.ro_rt->rt_ifp);
1188 }
1189
1190
1191 /*
1192 * return the first IP Address associated with an interface
1193 */
fr_ifpaddr(v,atype,ifptr,inp,inpmask)1194 int fr_ifpaddr(v, atype, ifptr, inp, inpmask)
1195 int v, atype;
1196 void *ifptr;
1197 struct in_addr *inp, *inpmask;
1198 {
1199 #ifdef USE_INET6
1200 struct in6_addr *inp6 = NULL;
1201 #endif
1202 struct sockaddr *sock, *mask;
1203 struct sockaddr_in *sin;
1204 struct ifaddr *ifa;
1205 struct ifnet *ifp;
1206
1207 if ((ifptr == NULL) || (ifptr == (void *)-1))
1208 return -1;
1209
1210 sin = NULL;
1211 ifp = ifptr;
1212
1213 if (v == 4)
1214 inp->s_addr = 0;
1215 #ifdef USE_INET6
1216 else if (v == 6)
1217 bzero((char *)inp, sizeof(struct in6_addr));
1218 #endif
1219 #if (__FreeBSD_version >= 300000)
1220 ifa = TAILQ_FIRST(&ifp->if_addrhead);
1221 #else
1222 ifa = ifp->if_addrlist;
1223 #endif /* __FreeBSD_version >= 300000 */
1224
1225 sock = ifa->ifa_addr;
1226 while (sock != NULL && ifa != NULL) {
1227 sin = (struct sockaddr_in *)sock;
1228 if ((v == 4) && (sin->sin_family == AF_INET))
1229 break;
1230 #ifdef USE_INET6
1231 if ((v == 6) && (sin->sin_family == AF_INET6)) {
1232 inp6 = &((struct sockaddr_in6 *)sin)->sin6_addr;
1233 if (!IN6_IS_ADDR_LINKLOCAL(inp6) &&
1234 !IN6_IS_ADDR_LOOPBACK(inp6))
1235 break;
1236 }
1237 #endif
1238 #if (__FreeBSD_version >= 300000)
1239 ifa = TAILQ_NEXT(ifa, ifa_link);
1240 #else
1241 ifa = ifa->ifa_next;
1242 #endif /* __FreeBSD_version >= 300000 */
1243 if (ifa != NULL)
1244 sock = ifa->ifa_addr;
1245 }
1246
1247 if (ifa == NULL || sin == NULL)
1248 return -1;
1249
1250 mask = ifa->ifa_netmask;
1251 if (atype == FRI_BROADCAST)
1252 sock = ifa->ifa_broadaddr;
1253 else if (atype == FRI_PEERADDR)
1254 sock = ifa->ifa_dstaddr;
1255
1256 if (sock == NULL)
1257 return -1;
1258
1259 #ifdef USE_INET6
1260 if (v == 6) {
1261 return fr_ifpfillv6addr(atype, (struct sockaddr_in6 *)sock,
1262 (struct sockaddr_in6 *)mask,
1263 inp, inpmask);
1264 }
1265 #endif
1266 return fr_ifpfillv4addr(atype, (struct sockaddr_in *)sock,
1267 (struct sockaddr_in *)mask, inp, inpmask);
1268 }
1269
1270
fr_newisn(fin)1271 u_32_t fr_newisn(fin)
1272 fr_info_t *fin;
1273 {
1274 u_32_t newiss;
1275 #if (__FreeBSD_version >= 400000)
1276 newiss = arc4random();
1277 #else
1278 static iss_seq_off = 0;
1279 u_char hash[16];
1280 MD5_CTX ctx;
1281
1282 /*
1283 * Compute the base value of the ISS. It is a hash
1284 * of (saddr, sport, daddr, dport, secret).
1285 */
1286 MD5Init(&ctx);
1287
1288 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src,
1289 sizeof(fin->fin_fi.fi_src));
1290 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst,
1291 sizeof(fin->fin_fi.fi_dst));
1292 MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat));
1293
1294 MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret));
1295
1296 MD5Final(hash, &ctx);
1297
1298 memcpy(&newiss, hash, sizeof(newiss));
1299
1300 /*
1301 * Now increment our "timer", and add it in to
1302 * the computed value.
1303 *
1304 * XXX Use `addin'?
1305 * XXX TCP_ISSINCR too large to use?
1306 */
1307 iss_seq_off += 0x00010000;
1308 newiss += iss_seq_off;
1309 #endif
1310 return newiss;
1311 }
1312
1313
1314 /* ------------------------------------------------------------------------ */
1315 /* Function: fr_nextipid */
1316 /* Returns: int - 0 == success, -1 == error (packet should be droppped) */
1317 /* Parameters: fin(I) - pointer to packet information */
1318 /* */
1319 /* Returns the next IPv4 ID to use for this packet. */
1320 /* ------------------------------------------------------------------------ */
fr_nextipid(fin)1321 u_short fr_nextipid(fin)
1322 fr_info_t *fin;
1323 {
1324 #ifndef RANDOM_IP_ID
1325 static u_short ipid = 0;
1326 u_short id;
1327
1328 MUTEX_ENTER(&ipf_rw);
1329 id = ipid++;
1330 MUTEX_EXIT(&ipf_rw);
1331 #else
1332 u_short id;
1333
1334 id = ip_randomid();
1335 #endif
1336
1337 return id;
1338 }
1339
1340
fr_checkv4sum(fin)1341 INLINE void fr_checkv4sum(fin)
1342 fr_info_t *fin;
1343 {
1344 #ifdef CSUM_DATA_VALID
1345 int manual = 0;
1346 u_short sum;
1347 ip_t *ip;
1348 mb_t *m;
1349
1350 if ((fin->fin_flx & FI_NOCKSUM) != 0)
1351 return;
1352
1353 if (fin->fin_cksum != 0)
1354 return;
1355
1356 m = fin->fin_m;
1357 if (m == NULL) {
1358 manual = 1;
1359 goto skipauto;
1360 }
1361 ip = fin->fin_ip;
1362
1363 if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) {
1364 /* Depending on the driver, UDP may have zero checksum */
1365 if (fin->fin_p == IPPROTO_UDP && (fin->fin_flx &
1366 (FI_FRAG|FI_SHORT|FI_BAD)) == 0) {
1367 udphdr_t *udp = fin->fin_dp;
1368 if (udp->uh_sum == 0) {
1369 /*
1370 * we're good no matter what the hardware
1371 * checksum flags and csum_data say (handling
1372 * of csum_data for zero UDP checksum is not
1373 * consistent across all drivers)
1374 */
1375 fin->fin_cksum = 1;
1376 return;
1377 }
1378 }
1379
1380 if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR)
1381 sum = m->m_pkthdr.csum_data;
1382 else
1383 sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr,
1384 htonl(m->m_pkthdr.csum_data +
1385 fin->fin_ip->ip_len -
1386 (fin->fin_ip->ip_hl << 2) +
1387 fin->fin_p));
1388 sum ^= 0xffff;
1389 if (sum != 0) {
1390 fin->fin_flx |= FI_BAD;
1391 fin->fin_cksum = -1;
1392 } else {
1393 fin->fin_cksum = 1;
1394 }
1395 } else
1396 manual = 1;
1397 skipauto:
1398 # ifdef IPFILTER_CKSUM
1399 if (manual != 0)
1400 if (fr_checkl4sum(fin) == -1)
1401 fin->fin_flx |= FI_BAD;
1402 # else
1403 ;
1404 # endif
1405 #else
1406 # ifdef IPFILTER_CKSUM
1407 if (fr_checkl4sum(fin) == -1)
1408 fin->fin_flx |= FI_BAD;
1409 # endif
1410 #endif
1411 }
1412
1413
1414 #ifdef USE_INET6
fr_checkv6sum(fin)1415 INLINE void fr_checkv6sum(fin)
1416 fr_info_t *fin;
1417 {
1418 # ifdef IPFILTER_CKSUM
1419 if (fr_checkl4sum(fin) == -1)
1420 fin->fin_flx |= FI_BAD;
1421 # endif
1422 }
1423 #endif /* USE_INET6 */
1424
1425
mbufchainlen(m0)1426 size_t mbufchainlen(m0)
1427 struct mbuf *m0;
1428 {
1429 size_t len;
1430
1431 if ((m0->m_flags & M_PKTHDR) != 0) {
1432 len = m0->m_pkthdr.len;
1433 } else {
1434 struct mbuf *m;
1435
1436 for (m = m0, len = 0; m != NULL; m = m->m_next)
1437 len += m->m_len;
1438 }
1439 return len;
1440 }
1441
1442
1443 /* ------------------------------------------------------------------------ */
1444 /* Function: fr_pullup */
1445 /* Returns: NULL == pullup failed, else pointer to protocol header */
1446 /* Parameters: m(I) - pointer to buffer where data packet starts */
1447 /* fin(I) - pointer to packet information */
1448 /* len(I) - number of bytes to pullup */
1449 /* */
1450 /* Attempt to move at least len bytes (from the start of the buffer) into a */
1451 /* single buffer for ease of access. Operating system native functions are */
1452 /* used to manage buffers - if necessary. If the entire packet ends up in */
1453 /* a single buffer, set the FI_COALESCE flag even though fr_coalesce() has */
1454 /* not been called. Both fin_ip and fin_dp are updated before exiting _IF_ */
1455 /* and ONLY if the pullup succeeds. */
1456 /* */
1457 /* We assume that 'min' is a pointer to a buffer that is part of the chain */
1458 /* of buffers that starts at *fin->fin_mp. */
1459 /* ------------------------------------------------------------------------ */
fr_pullup(min,fin,len)1460 void *fr_pullup(min, fin, len)
1461 mb_t *min;
1462 fr_info_t *fin;
1463 int len;
1464 {
1465 int out = fin->fin_out, dpoff, ipoff;
1466 mb_t *m = min;
1467 char *ip;
1468
1469 if (m == NULL)
1470 return NULL;
1471
1472 ip = (char *)fin->fin_ip;
1473 if ((fin->fin_flx & FI_COALESCE) != 0)
1474 return ip;
1475
1476 ipoff = fin->fin_ipoff;
1477 if (fin->fin_dp != NULL)
1478 dpoff = (char *)fin->fin_dp - (char *)ip;
1479 else
1480 dpoff = 0;
1481
1482 if (M_LEN(m) < len) {
1483 #ifdef MHLEN
1484 /*
1485 * Assume that M_PKTHDR is set and just work with what is left
1486 * rather than check..
1487 * Should not make any real difference, anyway.
1488 */
1489 if (len > MHLEN)
1490 #else
1491 if (len > MLEN)
1492 #endif
1493 {
1494 #ifdef HAVE_M_PULLDOWN
1495 if (m_pulldown(m, 0, len, NULL) == NULL)
1496 m = NULL;
1497 #else
1498 FREE_MB_T(*fin->fin_mp);
1499 m = NULL;
1500 #endif
1501 } else
1502 {
1503 m = m_pullup(m, len);
1504 }
1505 *fin->fin_mp = m;
1506 if (m == NULL) {
1507 fin->fin_m = NULL;
1508 ATOMIC_INCL(frstats[out].fr_pull[1]);
1509 return NULL;
1510 }
1511
1512 while (M_LEN(m) == 0) {
1513 m = m->m_next;
1514 }
1515 fin->fin_m = m;
1516 ip = MTOD(m, char *) + ipoff;
1517 }
1518
1519 ATOMIC_INCL(frstats[out].fr_pull[0]);
1520 fin->fin_ip = (ip_t *)ip;
1521 if (fin->fin_dp != NULL)
1522 fin->fin_dp = (char *)fin->fin_ip + dpoff;
1523
1524 if (len == fin->fin_plen)
1525 fin->fin_flx |= FI_COALESCE;
1526 return ip;
1527 }
1528
1529
ipf_inject(fin,m)1530 int ipf_inject(fin, m)
1531 fr_info_t *fin;
1532 mb_t *m;
1533 {
1534 int error = 0;
1535
1536 if (fin->fin_out == 0) {
1537 #if (__FreeBSD_version >= 501000)
1538 netisr_dispatch(NETISR_IP, m);
1539 #else
1540 struct ifqueue *ifq;
1541
1542 ifq = &ipintrq;
1543
1544 # ifdef _IF_QFULL
1545 if (_IF_QFULL(ifq))
1546 # else
1547 if (IF_QFULL(ifq))
1548 # endif
1549 {
1550 # ifdef _IF_DROP
1551 _IF_DROP(ifq);
1552 # else
1553 IF_DROP(ifq);
1554 # endif
1555 FREE_MB_T(m);
1556 error = ENOBUFS;
1557 } else {
1558 IF_ENQUEUE(ifq, m);
1559 }
1560 #endif
1561 } else {
1562 fin->fin_ip->ip_len = ntohs(fin->fin_ip->ip_len);
1563 fin->fin_ip->ip_off = ntohs(fin->fin_ip->ip_off);
1564 #if (__FreeBSD_version >= 470102)
1565 error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL);
1566 #else
1567 error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL);
1568 #endif
1569 }
1570
1571 return error;
1572 }
1573
ipf_pfil_unhook(void)1574 int ipf_pfil_unhook(void) {
1575 #if defined(NETBSD_PF) && (__FreeBSD_version >= 500011)
1576 # if __FreeBSD_version >= 501108
1577 struct pfil_head *ph_inet;
1578 # ifdef USE_INET6
1579 struct pfil_head *ph_inet6;
1580 # endif
1581 # endif
1582 #endif
1583
1584 #ifdef NETBSD_PF
1585 # if (__FreeBSD_version >= 500011)
1586 # if (__FreeBSD_version >= 501108)
1587 ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
1588 if (ph_inet != NULL)
1589 pfil_remove_hook((void *)fr_check_wrapper, NULL,
1590 PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet);
1591 # else
1592 pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK,
1593 &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
1594 # endif
1595 # else
1596 pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK);
1597 # endif
1598 # ifdef USE_INET6
1599 # if (__FreeBSD_version >= 501108)
1600 ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
1601 if (ph_inet6 != NULL)
1602 pfil_remove_hook((void *)fr_check_wrapper6, NULL,
1603 PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet6);
1604 # else
1605 pfil_remove_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK,
1606 &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh);
1607 # endif
1608 # endif
1609 #endif
1610
1611 return (0);
1612 }
1613
ipf_pfil_hook(void)1614 int ipf_pfil_hook(void) {
1615 #if defined(NETBSD_PF) && (__FreeBSD_version >= 500011)
1616 # if __FreeBSD_version >= 501108
1617 struct pfil_head *ph_inet;
1618 # ifdef USE_INET6
1619 struct pfil_head *ph_inet6;
1620 # endif
1621 # endif
1622 #endif
1623
1624 # ifdef NETBSD_PF
1625 # if __FreeBSD_version >= 500011
1626 # if __FreeBSD_version >= 501108
1627 ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
1628 # ifdef USE_INET6
1629 ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
1630 # endif
1631 if (ph_inet == NULL
1632 # ifdef USE_INET6
1633 && ph_inet6 == NULL
1634 # endif
1635 )
1636 return ENODEV;
1637
1638 if (ph_inet != NULL)
1639 pfil_add_hook((void *)fr_check_wrapper, NULL,
1640 PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet);
1641 # else
1642 pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK,
1643 &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
1644 # endif
1645 # else
1646 pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK);
1647 # endif
1648 # ifdef USE_INET6
1649 # if __FreeBSD_version >= 501108
1650 if (ph_inet6 != NULL)
1651 pfil_add_hook((void *)fr_check_wrapper6, NULL,
1652 PFIL_IN|PFIL_OUT|PFIL_WAITOK, ph_inet6);
1653 # else
1654 pfil_add_hook((void *)fr_check, PFIL_IN|PFIL_OUT|PFIL_WAITOK,
1655 &inet6sw[ip6_protox[IPPROTO_IPV6]].pr_pfh);
1656 # endif
1657 # endif
1658 # endif
1659 return (0);
1660 }
1661
1662 void
ipf_event_reg(void)1663 ipf_event_reg(void)
1664 {
1665 #if (__FreeBSD_version >= 502103)
1666 ipf_arrivetag = EVENTHANDLER_REGISTER(ifnet_arrival_event, \
1667 ipf_ifevent, NULL, \
1668 EVENTHANDLER_PRI_ANY);
1669 ipf_departtag = EVENTHANDLER_REGISTER(ifnet_departure_event, \
1670 ipf_ifevent, NULL, \
1671 EVENTHANDLER_PRI_ANY);
1672 ipf_clonetag = EVENTHANDLER_REGISTER(if_clone_event, ipf_ifevent, \
1673 NULL, EVENTHANDLER_PRI_ANY);
1674 #endif
1675 }
1676
1677 void
ipf_event_dereg(void)1678 ipf_event_dereg(void)
1679 {
1680 #if (__FreeBSD_version >= 502103)
1681 if (ipf_arrivetag != NULL) {
1682 EVENTHANDLER_DEREGISTER(ifnet_arrival_event, ipf_arrivetag);
1683 }
1684 if (ipf_departtag != NULL) {
1685 EVENTHANDLER_DEREGISTER(ifnet_departure_event, ipf_departtag);
1686 }
1687 if (ipf_clonetag != NULL) {
1688 EVENTHANDLER_DEREGISTER(if_clone_event, ipf_clonetag);
1689 }
1690 #endif
1691 }
1692