1
2 /*
3 * Copyright (C) 2012 by Darren Reed.
4 *
5 * See the IPFILTER.LICENCE file for details on licencing.
6 */
7
8 #if defined(KERNEL) || defined(_KERNEL)
9 # undef KERNEL
10 # undef _KERNEL
11 # define KERNEL 1
12 # define _KERNEL 1
13 #endif
14 #if defined(__FreeBSD__) && \
15 !defined(KLD_MODULE) && !defined(IPFILTER_LKM)
16 # include "opt_inet6.h"
17 #endif
18 #include <sys/param.h>
19 #include <sys/eventhandler.h>
20 #include <sys/conf.h>
21 #include <sys/errno.h>
22 #include <sys/types.h>
23 #include <sys/file.h>
24 #include <sys/fcntl.h>
25 #include <sys/filio.h>
26 #include <sys/time.h>
27 #include <sys/systm.h>
28 #include <sys/dirent.h>
29 #if defined(__FreeBSD__)
30 # include <sys/jail.h>
31 #endif
32 #include <sys/malloc.h>
33 #include <sys/mbuf.h>
34 #include <sys/sockopt.h>
35 #include <sys/socket.h>
36 #include <sys/selinfo.h>
37 #include <net/if.h>
38 #include <net/if_var.h>
39 #include <net/netisr.h>
40 #include <net/route.h>
41 #include <net/route/nhop.h>
42 #include <netinet/in.h>
43 #include <netinet/in_fib.h>
44 #include <netinet/in_pcb.h>
45 #include <netinet/in_var.h>
46 #include <netinet/in_systm.h>
47 #include <netinet/ip.h>
48 #include <netinet/ip_var.h>
49 #include <netinet/tcp.h>
50 #include <netinet/tcp_var.h>
51 #include <net/vnet.h>
52 #include <netinet/udp.h>
53 #include <netinet/tcpip.h>
54 #include <netinet/ip_icmp.h>
55 #include "netinet/ip_compat.h"
56 #ifdef USE_INET6
57 # include <netinet/icmp6.h>
58 #endif
59 #include "netinet/ip_fil.h"
60 #include "netinet/ip_nat.h"
61 #include "netinet/ip_frag.h"
62 #include "netinet/ip_state.h"
63 #include "netinet/ip_proxy.h"
64 #include "netinet/ip_auth.h"
65 #include "netinet/ip_sync.h"
66 #include "netinet/ip_lookup.h"
67 #include "netinet/ip_dstlist.h"
68 #ifdef IPFILTER_SCAN
69 # include "netinet/ip_scan.h"
70 #endif
71 #include "netinet/ip_pool.h"
72 #include <sys/malloc.h>
73 #include <sys/kernel.h>
74 #ifdef CSUM_DATA_VALID
75 # include <machine/in_cksum.h>
76 #endif
77 extern int ip_optcopy(struct ip *, struct ip *);
78
79 #ifdef IPFILTER_M_IPFILTER
80 MALLOC_DEFINE(M_IPFILTER, "ipfilter", "IP Filter packet filter data structures");
81 #endif
82
83
84 static int ipf_send_ip(fr_info_t *, mb_t *);
85 static void ipf_timer_func(void *arg);
86
87 VNET_DEFINE(ipf_main_softc_t, ipfmain) = {
88 .ipf_running = -2,
89 };
90 #define V_ipfmain VNET(ipfmain)
91
92 #include <sys/conf.h>
93 #include <net/pfil.h>
94
95 VNET_DEFINE_STATIC(eventhandler_tag, ipf_arrivetag);
96 VNET_DEFINE_STATIC(eventhandler_tag, ipf_departtag);
97 #define V_ipf_arrivetag VNET(ipf_arrivetag)
98 #define V_ipf_departtag VNET(ipf_departtag)
99
100 static void ipf_ifevent(void *arg, struct ifnet *ifp);
101
ipf_ifevent(void * arg,struct ifnet * ifp)102 static void ipf_ifevent(void *arg, struct ifnet *ifp)
103 {
104
105 CURVNET_SET(ifp->if_vnet);
106 if (V_ipfmain.ipf_running > 0)
107 ipf_sync(&V_ipfmain, NULL);
108 CURVNET_RESTORE();
109 }
110
111
112
113 static pfil_return_t
ipf_check_wrapper(struct mbuf ** mp,struct ifnet * ifp,int flags,void * ruleset __unused,struct inpcb * inp)114 ipf_check_wrapper(struct mbuf **mp, struct ifnet *ifp, int flags,
115 void *ruleset __unused, struct inpcb *inp)
116 {
117 struct ip *ip = mtod(*mp, struct ip *);
118 pfil_return_t rv;
119
120 CURVNET_SET(ifp->if_vnet);
121 rv = ipf_check(&V_ipfmain, ip, ip->ip_hl << 2, ifp,
122 !!(flags & PFIL_OUT), mp);
123 CURVNET_RESTORE();
124 if (rv == 0 && *mp == NULL)
125 return (PFIL_CONSUMED);
126 return (rv == 0 ? PFIL_PASS : PFIL_DROPPED);
127 }
128
129 #ifdef USE_INET6
130 static pfil_return_t
ipf_check_wrapper6(struct mbuf ** mp,struct ifnet * ifp,int flags,void * ruleset __unused,struct inpcb * inp)131 ipf_check_wrapper6(struct mbuf **mp, struct ifnet *ifp, int flags,
132 void *ruleset __unused, struct inpcb *inp)
133 {
134 pfil_return_t rv;
135
136 CURVNET_SET(ifp->if_vnet);
137 rv = ipf_check(&V_ipfmain, mtod(*mp, struct ip *),
138 sizeof(struct ip6_hdr), ifp, !!(flags & PFIL_OUT), mp);
139 CURVNET_RESTORE();
140 if (rv == 0 && *mp == NULL)
141 return (PFIL_CONSUMED);
142
143 return (rv == 0 ? PFIL_PASS : PFIL_DROPPED);
144 }
145 # endif
146 #if defined(IPFILTER_LKM)
ipf_identify(char * s)147 int ipf_identify(char *s)
148 {
149 if (strcmp(s, "ipl") == 0)
150 return (1);
151 return (0);
152 }
153 #endif /* IPFILTER_LKM */
154
155
156 static void
ipf_timer_func(void * arg)157 ipf_timer_func(void *arg)
158 {
159 ipf_main_softc_t *softc = arg;
160 SPL_INT(s);
161
162 SPL_NET(s);
163
164 if (softc->ipf_running > 0)
165 ipf_slowtimer(softc);
166
167 if (softc->ipf_running == -1 || softc->ipf_running == 1) {
168 callout_reset(&softc->ipf_slow_ch,
169 (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT,
170 ipf_timer_func, softc);
171 }
172 SPL_X(s);
173 }
174
175
176 int
ipfattach(ipf_main_softc_t * softc)177 ipfattach(ipf_main_softc_t *softc)
178 {
179 #ifdef USE_SPL
180 int s;
181 #endif
182
183 SPL_NET(s);
184 if (softc->ipf_running > 0) {
185 SPL_X(s);
186 return (EBUSY);
187 }
188
189 if (ipf_init_all(softc) < 0) {
190 SPL_X(s);
191 return (EIO);
192 }
193
194
195 bzero((char *)V_ipfmain.ipf_selwait, sizeof(V_ipfmain.ipf_selwait));
196 softc->ipf_running = 1;
197
198 if (softc->ipf_control_forwarding & 1)
199 V_ipforwarding = 1;
200
201 SPL_X(s);
202 callout_init_rw(&softc->ipf_slow_ch, &softc->ipf_global.ipf_lk, CALLOUT_SHAREDLOCK);
203 callout_reset(&softc->ipf_slow_ch, (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT,
204 ipf_timer_func, softc);
205 return (0);
206 }
207
208
209 /*
210 * Disable the filter by removing the hooks from the IP input/output
211 * stream.
212 */
213 int
ipfdetach(ipf_main_softc_t * softc)214 ipfdetach(ipf_main_softc_t *softc)
215 {
216 #ifdef USE_SPL
217 int s;
218 #endif
219
220 if (softc->ipf_control_forwarding & 2)
221 V_ipforwarding = 0;
222
223 SPL_NET(s);
224
225 callout_drain(&softc->ipf_slow_ch);
226
227 ipf_fini_all(softc);
228
229 softc->ipf_running = -2;
230
231 SPL_X(s);
232
233 return (0);
234 }
235
236
237 /*
238 * Filter ioctl interface.
239 */
240 int
ipfioctl(struct cdev * dev,ioctlcmd_t cmd,caddr_t data,int mode,struct thread * p)241 ipfioctl(struct cdev *dev, ioctlcmd_t cmd, caddr_t data,
242 int mode, struct thread *p)
243 #define p_cred td_ucred
244 #define p_uid td_ucred->cr_ruid
245 {
246 int error = 0, unit = 0;
247 SPL_INT(s);
248
249 CURVNET_SET(TD_TO_VNET(p));
250 if (securelevel_ge(p->p_cred, 3) && (mode & FWRITE))
251 {
252 V_ipfmain.ipf_interror = 130001;
253 CURVNET_RESTORE();
254 return (EPERM);
255 }
256
257 if (jailed_without_vnet(p->p_cred)) {
258 V_ipfmain.ipf_interror = 130018;
259 CURVNET_RESTORE();
260 return (EOPNOTSUPP);
261 }
262
263 unit = GET_MINOR(dev);
264 if ((IPL_LOGMAX < unit) || (unit < 0)) {
265 V_ipfmain.ipf_interror = 130002;
266 CURVNET_RESTORE();
267 return (ENXIO);
268 }
269
270 if (V_ipfmain.ipf_running <= 0) {
271 if (unit != IPL_LOGIPF && cmd != SIOCIPFINTERROR) {
272 V_ipfmain.ipf_interror = 130003;
273 CURVNET_RESTORE();
274 return (EIO);
275 }
276 if (cmd != SIOCIPFGETNEXT && cmd != SIOCIPFGET &&
277 cmd != SIOCIPFSET && cmd != SIOCFRENB &&
278 cmd != SIOCGETFS && cmd != SIOCGETFF &&
279 cmd != SIOCIPFINTERROR) {
280 V_ipfmain.ipf_interror = 130004;
281 CURVNET_RESTORE();
282 return (EIO);
283 }
284 }
285
286 SPL_NET(s);
287
288 error = ipf_ioctlswitch(&V_ipfmain, unit, data, cmd, mode, p->p_uid, p);
289 CURVNET_RESTORE();
290 if (error != -1) {
291 SPL_X(s);
292 return (error);
293 }
294
295 SPL_X(s);
296
297 return (error);
298 }
299
300
301 /*
302 * ipf_send_reset - this could conceivably be a call to tcp_respond(), but that
303 * requires a large amount of setting up and isn't any more efficient.
304 */
305 int
ipf_send_reset(fr_info_t * fin)306 ipf_send_reset(fr_info_t *fin)
307 {
308 struct tcphdr *tcp, *tcp2;
309 int tlen = 0, hlen;
310 struct mbuf *m;
311 #ifdef USE_INET6
312 ip6_t *ip6;
313 #endif
314 ip_t *ip;
315
316 tcp = fin->fin_dp;
317 if (tcp_get_flags(tcp) & TH_RST)
318 return (-1); /* feedback loop */
319
320 if (ipf_checkl4sum(fin) == -1)
321 return (-1);
322
323 tlen = fin->fin_dlen - (TCP_OFF(tcp) << 2) +
324 ((tcp_get_flags(tcp) & TH_SYN) ? 1 : 0) +
325 ((tcp_get_flags(tcp) & TH_FIN) ? 1 : 0);
326
327 #ifdef USE_INET6
328 hlen = (fin->fin_v == 6) ? sizeof(ip6_t) : sizeof(ip_t);
329 #else
330 hlen = sizeof(ip_t);
331 #endif
332 #ifdef MGETHDR
333 MGETHDR(m, M_NOWAIT, MT_HEADER);
334 #else
335 MGET(m, M_NOWAIT, MT_HEADER);
336 #endif
337 if (m == NULL)
338 return (-1);
339 if (sizeof(*tcp2) + hlen > MLEN) {
340 if (!(MCLGET(m, M_NOWAIT))) {
341 FREE_MB_T(m);
342 return (-1);
343 }
344 }
345
346 m->m_len = sizeof(*tcp2) + hlen;
347 m->m_data += max_linkhdr;
348 m->m_pkthdr.len = m->m_len;
349 m->m_pkthdr.rcvif = (struct ifnet *)0;
350 ip = mtod(m, struct ip *);
351 bzero((char *)ip, hlen);
352 #ifdef USE_INET6
353 ip6 = (ip6_t *)ip;
354 #endif
355 tcp2 = (struct tcphdr *)((char *)ip + hlen);
356 tcp2->th_sport = tcp->th_dport;
357 tcp2->th_dport = tcp->th_sport;
358
359 if (tcp_get_flags(tcp) & TH_ACK) {
360 tcp2->th_seq = tcp->th_ack;
361 tcp_set_flags(tcp2, TH_RST);
362 tcp2->th_ack = 0;
363 } else {
364 tcp2->th_seq = 0;
365 tcp2->th_ack = ntohl(tcp->th_seq);
366 tcp2->th_ack += tlen;
367 tcp2->th_ack = htonl(tcp2->th_ack);
368 tcp_set_flags(tcp2, TH_RST|TH_ACK);
369 }
370 TCP_OFF_A(tcp2, sizeof(*tcp2) >> 2);
371 tcp2->th_win = tcp->th_win;
372 tcp2->th_sum = 0;
373 tcp2->th_urp = 0;
374
375 #ifdef USE_INET6
376 if (fin->fin_v == 6) {
377 ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow;
378 ip6->ip6_plen = htons(sizeof(struct tcphdr));
379 ip6->ip6_nxt = IPPROTO_TCP;
380 ip6->ip6_hlim = 0;
381 ip6->ip6_src = fin->fin_dst6.in6;
382 ip6->ip6_dst = fin->fin_src6.in6;
383 tcp2->th_sum = in6_cksum(m, IPPROTO_TCP,
384 sizeof(*ip6), sizeof(*tcp2));
385 return (ipf_send_ip(fin, m));
386 }
387 #endif
388 ip->ip_p = IPPROTO_TCP;
389 ip->ip_len = htons(sizeof(struct tcphdr));
390 ip->ip_src.s_addr = fin->fin_daddr;
391 ip->ip_dst.s_addr = fin->fin_saddr;
392 tcp2->th_sum = in_cksum(m, hlen + sizeof(*tcp2));
393 ip->ip_len = htons(hlen + sizeof(*tcp2));
394 return (ipf_send_ip(fin, m));
395 }
396
397
398 /*
399 * ip_len must be in network byte order when called.
400 */
401 static int
ipf_send_ip(fr_info_t * fin,mb_t * m)402 ipf_send_ip(fr_info_t *fin, mb_t *m)
403 {
404 fr_info_t fnew;
405 ip_t *ip, *oip;
406 int hlen;
407
408 ip = mtod(m, ip_t *);
409 bzero((char *)&fnew, sizeof(fnew));
410 fnew.fin_main_soft = fin->fin_main_soft;
411
412 IP_V_A(ip, fin->fin_v);
413 switch (fin->fin_v)
414 {
415 case 4 :
416 oip = fin->fin_ip;
417 hlen = sizeof(*oip);
418 fnew.fin_v = 4;
419 fnew.fin_p = ip->ip_p;
420 fnew.fin_plen = ntohs(ip->ip_len);
421 IP_HL_A(ip, sizeof(*oip) >> 2);
422 ip->ip_tos = oip->ip_tos;
423 ip->ip_id = fin->fin_ip->ip_id;
424 ip->ip_off = htons(V_path_mtu_discovery ? IP_DF : 0);
425 ip->ip_ttl = V_ip_defttl;
426 ip->ip_sum = 0;
427 break;
428 #ifdef USE_INET6
429 case 6 :
430 {
431 ip6_t *ip6 = (ip6_t *)ip;
432
433 ip6->ip6_vfc = 0x60;
434 ip6->ip6_hlim = IPDEFTTL;
435
436 hlen = sizeof(*ip6);
437 fnew.fin_p = ip6->ip6_nxt;
438 fnew.fin_v = 6;
439 fnew.fin_plen = ntohs(ip6->ip6_plen) + hlen;
440 break;
441 }
442 #endif
443 default :
444 return (EINVAL);
445 }
446 #ifdef IPSEC_SUPPORT
447 m->m_pkthdr.rcvif = NULL;
448 #endif
449
450 fnew.fin_ifp = fin->fin_ifp;
451 fnew.fin_flx = FI_NOCKSUM;
452 fnew.fin_m = m;
453 fnew.fin_ip = ip;
454 fnew.fin_mp = &m;
455 fnew.fin_hlen = hlen;
456 fnew.fin_dp = (char *)ip + hlen;
457 (void) ipf_makefrip(hlen, ip, &fnew);
458
459 return (ipf_fastroute(m, &m, &fnew, NULL));
460 }
461
462
463 int
ipf_send_icmp_err(int type,fr_info_t * fin,int dst)464 ipf_send_icmp_err(int type, fr_info_t *fin, int dst)
465 {
466 int err, hlen, xtra, iclen, ohlen, avail, code;
467 struct in_addr dst4;
468 struct icmp *icmp;
469 struct mbuf *m;
470 i6addr_t dst6;
471 void *ifp;
472 #ifdef USE_INET6
473 ip6_t *ip6;
474 #endif
475 ip_t *ip, *ip2;
476
477 if ((type < 0) || (type >= ICMP_MAXTYPE))
478 return (-1);
479
480 code = fin->fin_icode;
481 #ifdef USE_INET6
482 /* See NetBSD ip_fil_netbsd.c r1.4: */
483 if ((code < 0) || (code >= sizeof(icmptoicmp6unreach)/sizeof(int)))
484 return (-1);
485 #endif
486
487 if (ipf_checkl4sum(fin) == -1)
488 return (-1);
489 #ifdef MGETHDR
490 MGETHDR(m, M_NOWAIT, MT_HEADER);
491 #else
492 MGET(m, M_NOWAIT, MT_HEADER);
493 #endif
494 if (m == NULL)
495 return (-1);
496 avail = MHLEN;
497
498 xtra = 0;
499 hlen = 0;
500 ohlen = 0;
501 dst4.s_addr = 0;
502 ifp = fin->fin_ifp;
503 if (fin->fin_v == 4) {
504 if ((fin->fin_p == IPPROTO_ICMP) && !(fin->fin_flx & FI_SHORT))
505 switch (ntohs(fin->fin_data[0]) >> 8)
506 {
507 case ICMP_ECHO :
508 case ICMP_TSTAMP :
509 case ICMP_IREQ :
510 case ICMP_MASKREQ :
511 break;
512 default :
513 FREE_MB_T(m);
514 return (0);
515 }
516
517 if (dst == 0) {
518 if (ipf_ifpaddr(&V_ipfmain, 4, FRI_NORMAL, ifp,
519 &dst6, NULL) == -1) {
520 FREE_MB_T(m);
521 return (-1);
522 }
523 dst4 = dst6.in4;
524 } else
525 dst4.s_addr = fin->fin_daddr;
526
527 hlen = sizeof(ip_t);
528 ohlen = fin->fin_hlen;
529 iclen = hlen + offsetof(struct icmp, icmp_ip) + ohlen;
530 if (fin->fin_hlen < fin->fin_plen)
531 xtra = MIN(fin->fin_dlen, 8);
532 else
533 xtra = 0;
534 }
535
536 #ifdef USE_INET6
537 else if (fin->fin_v == 6) {
538 hlen = sizeof(ip6_t);
539 ohlen = sizeof(ip6_t);
540 iclen = hlen + offsetof(struct icmp, icmp_ip) + ohlen;
541 type = icmptoicmp6types[type];
542 if (type == ICMP6_DST_UNREACH)
543 code = icmptoicmp6unreach[code];
544
545 if (iclen + max_linkhdr + fin->fin_plen > avail) {
546 if (!(MCLGET(m, M_NOWAIT))) {
547 FREE_MB_T(m);
548 return (-1);
549 }
550 avail = MCLBYTES;
551 }
552 xtra = MIN(fin->fin_plen, avail - iclen - max_linkhdr);
553 xtra = MIN(xtra, IPV6_MMTU - iclen);
554 if (dst == 0) {
555 if (ipf_ifpaddr(&V_ipfmain, 6, FRI_NORMAL, ifp,
556 &dst6, NULL) == -1) {
557 FREE_MB_T(m);
558 return (-1);
559 }
560 } else
561 dst6 = fin->fin_dst6;
562 }
563 #endif
564 else {
565 FREE_MB_T(m);
566 return (-1);
567 }
568
569 avail -= (max_linkhdr + iclen);
570 if (avail < 0) {
571 FREE_MB_T(m);
572 return (-1);
573 }
574 if (xtra > avail)
575 xtra = avail;
576 iclen += xtra;
577 m->m_data += max_linkhdr;
578 m->m_pkthdr.rcvif = (struct ifnet *)0;
579 m->m_pkthdr.len = iclen;
580 m->m_len = iclen;
581 ip = mtod(m, ip_t *);
582 icmp = (struct icmp *)((char *)ip + hlen);
583 ip2 = (ip_t *)&icmp->icmp_ip;
584
585 icmp->icmp_type = type;
586 icmp->icmp_code = fin->fin_icode;
587 icmp->icmp_cksum = 0;
588 #ifdef icmp_nextmtu
589 if (type == ICMP_UNREACH && fin->fin_icode == ICMP_UNREACH_NEEDFRAG) {
590 if (fin->fin_mtu != 0) {
591 icmp->icmp_nextmtu = htons(fin->fin_mtu);
592
593 } else if (ifp != NULL) {
594 icmp->icmp_nextmtu = htons(GETIFMTU_4(ifp));
595
596 } else { /* make up a number... */
597 icmp->icmp_nextmtu = htons(fin->fin_plen - 20);
598 }
599 }
600 #endif
601
602 bcopy((char *)fin->fin_ip, (char *)ip2, ohlen);
603
604 #ifdef USE_INET6
605 ip6 = (ip6_t *)ip;
606 if (fin->fin_v == 6) {
607 ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow;
608 ip6->ip6_plen = htons(iclen - hlen);
609 ip6->ip6_nxt = IPPROTO_ICMPV6;
610 ip6->ip6_hlim = 0;
611 ip6->ip6_src = dst6.in6;
612 ip6->ip6_dst = fin->fin_src6.in6;
613 if (xtra > 0)
614 bcopy((char *)fin->fin_ip + ohlen,
615 (char *)&icmp->icmp_ip + ohlen, xtra);
616 icmp->icmp_cksum = in6_cksum(m, IPPROTO_ICMPV6,
617 sizeof(*ip6), iclen - hlen);
618 } else
619 #endif
620 {
621 ip->ip_p = IPPROTO_ICMP;
622 ip->ip_src.s_addr = dst4.s_addr;
623 ip->ip_dst.s_addr = fin->fin_saddr;
624
625 if (xtra > 0)
626 bcopy((char *)fin->fin_ip + ohlen,
627 (char *)&icmp->icmp_ip + ohlen, xtra);
628 icmp->icmp_cksum = ipf_cksum((u_short *)icmp,
629 sizeof(*icmp) + 8);
630 ip->ip_len = htons(iclen);
631 ip->ip_p = IPPROTO_ICMP;
632 }
633 err = ipf_send_ip(fin, m);
634 return (err);
635 }
636
637
638
639
640 /*
641 * m0 - pointer to mbuf where the IP packet starts
642 * mpp - pointer to the mbuf pointer that is the start of the mbuf chain
643 */
644 int
ipf_fastroute(mb_t * m0,mb_t ** mpp,fr_info_t * fin,frdest_t * fdp)645 ipf_fastroute(mb_t *m0, mb_t **mpp, fr_info_t *fin, frdest_t *fdp)
646 {
647 register struct ip *ip, *mhip;
648 register struct mbuf *m = *mpp;
649 int len, off, error = 0, hlen, code;
650 struct ifnet *ifp, *sifp;
651 struct route ro;
652 struct sockaddr_in *dst;
653 const struct sockaddr *gw;
654 struct nhop_object *nh;
655 u_long fibnum = 0;
656 u_short ip_off;
657 frdest_t node;
658 frentry_t *fr;
659
660 #ifdef M_WRITABLE
661 /*
662 * HOT FIX/KLUDGE:
663 *
664 * If the mbuf we're about to send is not writable (because of
665 * a cluster reference, for example) we'll need to make a copy
666 * of it since this routine modifies the contents.
667 *
668 * If you have non-crappy network hardware that can transmit data
669 * from the mbuf, rather than making a copy, this is gonna be a
670 * problem.
671 */
672 if (M_WRITABLE(m) == 0) {
673 m0 = m_dup(m, M_NOWAIT);
674 if (m0 != NULL) {
675 FREE_MB_T(m);
676 m = m0;
677 *mpp = m;
678 } else {
679 error = ENOBUFS;
680 FREE_MB_T(m);
681 goto done;
682 }
683 }
684 #endif
685
686 #ifdef USE_INET6
687 if (fin->fin_v == 6) {
688 /*
689 * currently "to <if>" and "to <if>:ip#" are not supported
690 * for IPv6
691 */
692 return (ip6_output(m, NULL, NULL, 0, NULL, NULL, NULL));
693 }
694 #endif
695
696 hlen = fin->fin_hlen;
697 ip = mtod(m0, struct ip *);
698 ifp = NULL;
699
700 /*
701 * Route packet.
702 */
703 bzero(&ro, sizeof (ro));
704 dst = (struct sockaddr_in *)&ro.ro_dst;
705 dst->sin_family = AF_INET;
706 dst->sin_addr = ip->ip_dst;
707 dst->sin_len = sizeof(dst);
708 gw = (const struct sockaddr *)dst;
709
710 fr = fin->fin_fr;
711 if ((fr != NULL) && !(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) &&
712 (fdp->fd_type == FRD_DSTLIST)) {
713 if (ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node) == 0)
714 fdp = &node;
715 }
716
717 if (fdp != NULL)
718 ifp = fdp->fd_ptr;
719 else
720 ifp = fin->fin_ifp;
721
722 if ((ifp == NULL) && ((fr == NULL) || !(fr->fr_flags & FR_FASTROUTE))) {
723 error = -2;
724 goto bad;
725 }
726
727 if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0))
728 dst->sin_addr = fdp->fd_ip;
729
730 fibnum = M_GETFIB(m0);
731 NET_EPOCH_ASSERT();
732 nh = fib4_lookup(fibnum, dst->sin_addr, 0, NHR_NONE, 0);
733 if (nh == NULL) {
734 if (in_localaddr(ip->ip_dst))
735 error = EHOSTUNREACH;
736 else
737 error = ENETUNREACH;
738 goto bad;
739 }
740
741 if (ifp == NULL)
742 ifp = nh->nh_ifp;
743 if (nh->nh_flags & NHF_GATEWAY) {
744 gw = &nh->gw_sa;
745 ro.ro_flags |= RT_HAS_GW;
746 }
747
748 /*
749 * For input packets which are being "fastrouted", they won't
750 * go back through output filtering and miss their chance to get
751 * NAT'd and counted. Duplicated packets aren't considered to be
752 * part of the normal packet stream, so do not NAT them or pass
753 * them through stateful checking, etc.
754 */
755 if ((fdp != &fr->fr_dif) && (fin->fin_out == 0)) {
756 sifp = fin->fin_ifp;
757 fin->fin_ifp = ifp;
758 fin->fin_out = 1;
759 (void) ipf_acctpkt(fin, NULL);
760 fin->fin_fr = NULL;
761 if (!fr || !(fr->fr_flags & FR_RETMASK)) {
762 u_32_t pass;
763
764 (void) ipf_state_check(fin, &pass);
765 }
766
767 switch (ipf_nat_checkout(fin, NULL))
768 {
769 case 0 :
770 break;
771 case 1 :
772 ip->ip_sum = 0;
773 break;
774 case -1 :
775 error = -1;
776 goto bad;
777 break;
778 }
779
780 fin->fin_ifp = sifp;
781 fin->fin_out = 0;
782 } else
783 ip->ip_sum = 0;
784 /*
785 * If small enough for interface, can just send directly.
786 */
787 if (ntohs(ip->ip_len) <= ifp->if_mtu) {
788 if (!ip->ip_sum)
789 ip->ip_sum = in_cksum(m, hlen);
790 error = (*ifp->if_output)(ifp, m, gw, &ro);
791 goto done;
792 }
793 /*
794 * Too large for interface; fragment if possible.
795 * Must be able to put at least 8 bytes per fragment.
796 */
797 ip_off = ntohs(ip->ip_off);
798 if (ip_off & IP_DF) {
799 error = EMSGSIZE;
800 goto bad;
801 }
802 len = (ifp->if_mtu - hlen) &~ 7;
803 if (len < 8) {
804 error = EMSGSIZE;
805 goto bad;
806 }
807
808 {
809 int mhlen, firstlen = len;
810 struct mbuf **mnext = &m->m_act;
811
812 /*
813 * Loop through length of segment after first fragment,
814 * make new header and copy data of each part and link onto chain.
815 */
816 m0 = m;
817 mhlen = sizeof (struct ip);
818 for (off = hlen + len; off < ntohs(ip->ip_len); off += len) {
819 #ifdef MGETHDR
820 MGETHDR(m, M_NOWAIT, MT_HEADER);
821 #else
822 MGET(m, M_NOWAIT, MT_HEADER);
823 #endif
824 if (m == NULL) {
825 m = m0;
826 error = ENOBUFS;
827 goto bad;
828 }
829 m->m_data += max_linkhdr;
830 mhip = mtod(m, struct ip *);
831 bcopy((char *)ip, (char *)mhip, sizeof(*ip));
832 if (hlen > sizeof (struct ip)) {
833 mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
834 IP_HL_A(mhip, mhlen >> 2);
835 }
836 m->m_len = mhlen;
837 mhip->ip_off = ((off - hlen) >> 3) + ip_off;
838 if (off + len >= ntohs(ip->ip_len))
839 len = ntohs(ip->ip_len) - off;
840 else
841 mhip->ip_off |= IP_MF;
842 mhip->ip_len = htons((u_short)(len + mhlen));
843 *mnext = m;
844 m->m_next = m_copym(m0, off, len, M_NOWAIT);
845 if (m->m_next == 0) {
846 error = ENOBUFS; /* ??? */
847 goto sendorfree;
848 }
849 m->m_pkthdr.len = mhlen + len;
850 m->m_pkthdr.rcvif = NULL;
851 mhip->ip_off = htons((u_short)mhip->ip_off);
852 mhip->ip_sum = 0;
853 mhip->ip_sum = in_cksum(m, mhlen);
854 mnext = &m->m_act;
855 }
856 /*
857 * Update first fragment by trimming what's been copied out
858 * and updating header, then send each fragment (in order).
859 */
860 m_adj(m0, hlen + firstlen - ip->ip_len);
861 ip->ip_len = htons((u_short)(hlen + firstlen));
862 ip->ip_off = htons((u_short)IP_MF);
863 ip->ip_sum = 0;
864 ip->ip_sum = in_cksum(m0, hlen);
865 sendorfree:
866 for (m = m0; m; m = m0) {
867 m0 = m->m_act;
868 m->m_act = 0;
869 if (error == 0)
870 error = (*ifp->if_output)(ifp, m, gw, &ro);
871 else
872 FREE_MB_T(m);
873 }
874 }
875 done:
876 if (!error)
877 V_ipfmain.ipf_frouteok[0]++;
878 else
879 V_ipfmain.ipf_frouteok[1]++;
880
881 return (0);
882 bad:
883 if (error == EMSGSIZE) {
884 sifp = fin->fin_ifp;
885 code = fin->fin_icode;
886 fin->fin_icode = ICMP_UNREACH_NEEDFRAG;
887 fin->fin_ifp = ifp;
888 (void) ipf_send_icmp_err(ICMP_UNREACH, fin, 1);
889 fin->fin_ifp = sifp;
890 fin->fin_icode = code;
891 }
892 FREE_MB_T(m);
893 goto done;
894 }
895
896
897 int
ipf_verifysrc(fr_info_t * fin)898 ipf_verifysrc(fr_info_t *fin)
899 {
900 struct nhop_object *nh;
901
902 NET_EPOCH_ASSERT();
903 nh = fib4_lookup(RT_DEFAULT_FIB, fin->fin_src, 0, NHR_NONE, 0);
904 if (nh == NULL)
905 return (0);
906 return (fin->fin_ifp == nh->nh_ifp);
907 }
908
909
910 /*
911 * return the first IP Address associated with an interface
912 */
913 int
ipf_ifpaddr(ipf_main_softc_t * softc,int v,int atype,void * ifptr,i6addr_t * inp,i6addr_t * inpmask)914 ipf_ifpaddr(ipf_main_softc_t *softc, int v, int atype, void *ifptr,
915 i6addr_t *inp, i6addr_t *inpmask)
916 {
917 #ifdef USE_INET6
918 struct in6_addr *ia6 = NULL;
919 #endif
920 struct sockaddr *sock, *mask;
921 struct sockaddr_in *sin;
922 struct ifaddr *ifa;
923 struct ifnet *ifp;
924
925 if ((ifptr == NULL) || (ifptr == (void *)-1))
926 return (-1);
927
928 sin = NULL;
929 ifp = ifptr;
930
931 if (v == 4)
932 inp->in4.s_addr = 0;
933 #ifdef USE_INET6
934 else if (v == 6)
935 bzero((char *)inp, sizeof(*inp));
936 #endif
937 ifa = CK_STAILQ_FIRST(&ifp->if_addrhead);
938
939 sock = ifa->ifa_addr;
940 while (sock != NULL && ifa != NULL) {
941 sin = (struct sockaddr_in *)sock;
942 if ((v == 4) && (sin->sin_family == AF_INET))
943 break;
944 #ifdef USE_INET6
945 if ((v == 6) && (sin->sin_family == AF_INET6)) {
946 ia6 = &((struct sockaddr_in6 *)sin)->sin6_addr;
947 if (!IN6_IS_ADDR_LINKLOCAL(ia6) &&
948 !IN6_IS_ADDR_LOOPBACK(ia6))
949 break;
950 }
951 #endif
952 ifa = CK_STAILQ_NEXT(ifa, ifa_link);
953 if (ifa != NULL)
954 sock = ifa->ifa_addr;
955 }
956
957 if (ifa == NULL || sin == NULL)
958 return (-1);
959
960 mask = ifa->ifa_netmask;
961 if (atype == FRI_BROADCAST)
962 sock = ifa->ifa_broadaddr;
963 else if (atype == FRI_PEERADDR)
964 sock = ifa->ifa_dstaddr;
965
966 if (sock == NULL)
967 return (-1);
968
969 #ifdef USE_INET6
970 if (v == 6) {
971 return (ipf_ifpfillv6addr(atype, (struct sockaddr_in6 *)sock,
972 (struct sockaddr_in6 *)mask,
973 inp, inpmask));
974 }
975 #endif
976 return (ipf_ifpfillv4addr(atype, (struct sockaddr_in *)sock,
977 (struct sockaddr_in *)mask,
978 &inp->in4, &inpmask->in4));
979 }
980
981
982 u_32_t
ipf_newisn(fr_info_t * fin)983 ipf_newisn(fr_info_t *fin)
984 {
985 u_32_t newiss;
986 newiss = arc4random();
987 return (newiss);
988 }
989
990
991 int
ipf_checkv4sum(fr_info_t * fin)992 ipf_checkv4sum(fr_info_t *fin)
993 {
994 #ifdef CSUM_DATA_VALID
995 int manual = 0;
996 u_short sum;
997 ip_t *ip;
998 mb_t *m;
999
1000 if ((fin->fin_flx & FI_NOCKSUM) != 0)
1001 return (0);
1002
1003 if ((fin->fin_flx & FI_SHORT) != 0)
1004 return (1);
1005
1006 if (fin->fin_cksum != FI_CK_NEEDED)
1007 return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1;
1008
1009 m = fin->fin_m;
1010 if (m == NULL) {
1011 manual = 1;
1012 goto skipauto;
1013 }
1014 ip = fin->fin_ip;
1015
1016 if ((m->m_pkthdr.csum_flags & (CSUM_IP_CHECKED|CSUM_IP_VALID)) ==
1017 CSUM_IP_CHECKED) {
1018 fin->fin_cksum = FI_CK_BAD;
1019 fin->fin_flx |= FI_BAD;
1020 DT2(ipf_fi_bad_checkv4sum_csum_ip_checked, fr_info_t *, fin, u_int, m->m_pkthdr.csum_flags & (CSUM_IP_CHECKED|CSUM_IP_VALID));
1021 return (-1);
1022 }
1023 if (m->m_pkthdr.csum_flags & CSUM_DATA_VALID) {
1024 /* Depending on the driver, UDP may have zero checksum */
1025 if (fin->fin_p == IPPROTO_UDP && (fin->fin_flx &
1026 (FI_FRAG|FI_SHORT|FI_BAD)) == 0) {
1027 udphdr_t *udp = fin->fin_dp;
1028 if (udp->uh_sum == 0) {
1029 /*
1030 * we're good no matter what the hardware
1031 * checksum flags and csum_data say (handling
1032 * of csum_data for zero UDP checksum is not
1033 * consistent across all drivers)
1034 */
1035 fin->fin_cksum = 1;
1036 return (0);
1037 }
1038 }
1039
1040 if (m->m_pkthdr.csum_flags & CSUM_PSEUDO_HDR)
1041 sum = m->m_pkthdr.csum_data;
1042 else
1043 sum = in_pseudo(ip->ip_src.s_addr, ip->ip_dst.s_addr,
1044 htonl(m->m_pkthdr.csum_data +
1045 fin->fin_dlen + fin->fin_p));
1046 sum ^= 0xffff;
1047 if (sum != 0) {
1048 fin->fin_cksum = FI_CK_BAD;
1049 fin->fin_flx |= FI_BAD;
1050 DT2(ipf_fi_bad_checkv4sum_sum, fr_info_t *, fin, u_int, sum);
1051 } else {
1052 fin->fin_cksum = FI_CK_SUMOK;
1053 return (0);
1054 }
1055 } else {
1056 if (m->m_pkthdr.csum_flags == CSUM_DELAY_DATA) {
1057 fin->fin_cksum = FI_CK_L4FULL;
1058 return (0);
1059 } else if (m->m_pkthdr.csum_flags == CSUM_TCP ||
1060 m->m_pkthdr.csum_flags == CSUM_UDP ||
1061 m->m_pkthdr.csum_flags == CSUM_IP) {
1062 fin->fin_cksum = FI_CK_L4PART;
1063 return (0);
1064 } else {
1065 manual = 1;
1066 }
1067 }
1068 skipauto:
1069 if (manual != 0) {
1070 if (ipf_checkl4sum(fin) == -1) {
1071 fin->fin_flx |= FI_BAD;
1072 DT2(ipf_fi_bad_checkv4sum_manual, fr_info_t *, fin, u_int, manual);
1073 return (-1);
1074 }
1075 }
1076 #else
1077 if (ipf_checkl4sum(fin) == -1) {
1078 fin->fin_flx |= FI_BAD;
1079 DT2(ipf_fi_bad_checkv4sum_checkl4sum, fr_info_t *, fin, u_int, -1);
1080 return (-1);
1081 }
1082 #endif
1083 return (0);
1084 }
1085
1086
1087 #ifdef USE_INET6
1088 int
ipf_checkv6sum(fr_info_t * fin)1089 ipf_checkv6sum(fr_info_t *fin)
1090 {
1091 if ((fin->fin_flx & FI_NOCKSUM) != 0) {
1092 DT(ipf_checkv6sum_fi_nocksum);
1093 return (0);
1094 }
1095
1096 if ((fin->fin_flx & FI_SHORT) != 0) {
1097 DT(ipf_checkv6sum_fi_short);
1098 return (1);
1099 }
1100
1101 if (fin->fin_cksum != FI_CK_NEEDED) {
1102 DT(ipf_checkv6sum_fi_ck_needed);
1103 return (fin->fin_cksum > FI_CK_NEEDED) ? 0 : -1;
1104 }
1105
1106 if (ipf_checkl4sum(fin) == -1) {
1107 fin->fin_flx |= FI_BAD;
1108 DT2(ipf_fi_bad_checkv6sum_checkl4sum, fr_info_t *, fin, u_int, -1);
1109 return (-1);
1110 }
1111 return (0);
1112 }
1113 #endif /* USE_INET6 */
1114
1115
1116 size_t
mbufchainlen(struct mbuf * m0)1117 mbufchainlen(struct mbuf *m0)
1118 {
1119 size_t len;
1120
1121 if ((m0->m_flags & M_PKTHDR) != 0) {
1122 len = m0->m_pkthdr.len;
1123 } else {
1124 struct mbuf *m;
1125
1126 for (m = m0, len = 0; m != NULL; m = m->m_next)
1127 len += m->m_len;
1128 }
1129 return (len);
1130 }
1131
1132
1133 /* ------------------------------------------------------------------------ */
1134 /* Function: ipf_pullup */
1135 /* Returns: NULL == pullup failed, else pointer to protocol header */
1136 /* Parameters: xmin(I)- pointer to buffer where data packet starts */
1137 /* fin(I) - pointer to packet information */
1138 /* len(I) - number of bytes to pullup */
1139 /* */
1140 /* Attempt to move at least len bytes (from the start of the buffer) into a */
1141 /* single buffer for ease of access. Operating system native functions are */
1142 /* used to manage buffers - if necessary. If the entire packet ends up in */
1143 /* a single buffer, set the FI_COALESCE flag even though ipf_coalesce() has */
1144 /* not been called. Both fin_ip and fin_dp are updated before exiting _IF_ */
1145 /* and ONLY if the pullup succeeds. */
1146 /* */
1147 /* We assume that 'xmin' is a pointer to a buffer that is part of the chain */
1148 /* of buffers that starts at *fin->fin_mp. */
1149 /* ------------------------------------------------------------------------ */
1150 ip_t *
ipf_pullup(mb_t * xmin,fr_info_t * fin,int len)1151 ipf_pullup(mb_t *xmin, fr_info_t *fin, int len)
1152 {
1153 int dpoff, ipoff;
1154 mb_t *m = xmin;
1155 ip_t *ip;
1156
1157 if (m == NULL)
1158 return (NULL);
1159
1160 ip = fin->fin_ip;
1161 if ((fin->fin_flx & FI_COALESCE) != 0)
1162 return (ip);
1163
1164 ipoff = fin->fin_ipoff;
1165 if (fin->fin_dp != NULL)
1166 dpoff = (char *)fin->fin_dp - (char *)ip;
1167 else
1168 dpoff = 0;
1169
1170 if (M_LEN(m) < len) {
1171 mb_t *n = *fin->fin_mp;
1172 /*
1173 * Assume that M_PKTHDR is set and just work with what is left
1174 * rather than check..
1175 * Should not make any real difference, anyway.
1176 */
1177 if (m != n) {
1178 /*
1179 * Record the mbuf that points to the mbuf that we're
1180 * about to go to work on so that we can update the
1181 * m_next appropriately later.
1182 */
1183 for (; n->m_next != m; n = n->m_next)
1184 ;
1185 } else {
1186 n = NULL;
1187 }
1188
1189 #ifdef MHLEN
1190 if (len > MHLEN)
1191 #else
1192 if (len > MLEN)
1193 #endif
1194 {
1195 #ifdef HAVE_M_PULLDOWN
1196 if (m_pulldown(m, 0, len, NULL) == NULL)
1197 m = NULL;
1198 #else
1199 FREE_MB_T(*fin->fin_mp);
1200 m = NULL;
1201 n = NULL;
1202 #endif
1203 } else
1204 {
1205
1206 m = m_pullup(m, len);
1207 }
1208 if (n != NULL)
1209 n->m_next = m;
1210 if (m == NULL) {
1211 /*
1212 * When n is non-NULL, it indicates that m pointed to
1213 * a sub-chain (tail) of the mbuf and that the head
1214 * of this chain has not yet been free'd.
1215 */
1216 if (n != NULL) {
1217 FREE_MB_T(*fin->fin_mp);
1218 }
1219
1220 *fin->fin_mp = NULL;
1221 fin->fin_m = NULL;
1222 return (NULL);
1223 }
1224
1225 if (n == NULL)
1226 *fin->fin_mp = m;
1227
1228 while (M_LEN(m) == 0) {
1229 m = m->m_next;
1230 }
1231 fin->fin_m = m;
1232 ip = MTOD(m, ip_t *) + ipoff;
1233
1234 fin->fin_ip = ip;
1235 if (fin->fin_dp != NULL)
1236 fin->fin_dp = (char *)fin->fin_ip + dpoff;
1237 if (fin->fin_fraghdr != NULL)
1238 fin->fin_fraghdr = (char *)ip +
1239 ((char *)fin->fin_fraghdr -
1240 (char *)fin->fin_ip);
1241 }
1242
1243 if (len == fin->fin_plen)
1244 fin->fin_flx |= FI_COALESCE;
1245 return (ip);
1246 }
1247
1248
1249 int
ipf_inject(fr_info_t * fin,mb_t * m)1250 ipf_inject(fr_info_t *fin, mb_t *m)
1251 {
1252 struct epoch_tracker et;
1253 int error = 0;
1254
1255 NET_EPOCH_ENTER(et);
1256 if (fin->fin_out == 0) {
1257 netisr_dispatch(NETISR_IP, m);
1258 } else {
1259 fin->fin_ip->ip_len = ntohs(fin->fin_ip->ip_len);
1260 fin->fin_ip->ip_off = ntohs(fin->fin_ip->ip_off);
1261 error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL, NULL);
1262 }
1263 NET_EPOCH_EXIT(et);
1264
1265 return (error);
1266 }
1267
1268 VNET_DEFINE_STATIC(pfil_hook_t, ipf_inet_hook);
1269 VNET_DEFINE_STATIC(pfil_hook_t, ipf_inet6_hook);
1270 #define V_ipf_inet_hook VNET(ipf_inet_hook)
1271 #define V_ipf_inet6_hook VNET(ipf_inet6_hook)
1272
ipf_pfil_unhook(void)1273 int ipf_pfil_unhook(void) {
1274
1275 pfil_remove_hook(V_ipf_inet_hook);
1276
1277 #ifdef USE_INET6
1278 pfil_remove_hook(V_ipf_inet6_hook);
1279 #endif
1280
1281 return (0);
1282 }
1283
ipf_pfil_hook(void)1284 int ipf_pfil_hook(void) {
1285 int error, error6;
1286
1287 struct pfil_hook_args pha = {
1288 .pa_version = PFIL_VERSION,
1289 .pa_flags = PFIL_IN | PFIL_OUT,
1290 .pa_modname = "ipfilter",
1291 .pa_rulname = "default-ip4",
1292 .pa_mbuf_chk = ipf_check_wrapper,
1293 .pa_type = PFIL_TYPE_IP4,
1294 };
1295 V_ipf_inet_hook = pfil_add_hook(&pha);
1296
1297 #ifdef USE_INET6
1298 pha.pa_rulname = "default-ip6";
1299 pha.pa_mbuf_chk = ipf_check_wrapper6;
1300 pha.pa_type = PFIL_TYPE_IP6;
1301 V_ipf_inet6_hook = pfil_add_hook(&pha);
1302 #endif
1303
1304 struct pfil_link_args pla = {
1305 .pa_version = PFIL_VERSION,
1306 .pa_flags = PFIL_IN | PFIL_OUT | PFIL_HEADPTR | PFIL_HOOKPTR,
1307 .pa_head = V_inet_pfil_head,
1308 .pa_hook = V_ipf_inet_hook,
1309 };
1310 error = pfil_link(&pla);
1311
1312 error6 = 0;
1313 #ifdef USE_INET6
1314 pla.pa_head = V_inet6_pfil_head;
1315 pla.pa_hook = V_ipf_inet6_hook;
1316 error6 = pfil_link(&pla);
1317 #endif
1318
1319 if (error || error6)
1320 error = ENODEV;
1321 else
1322 error = 0;
1323
1324 return (error);
1325 }
1326
1327 void
ipf_event_reg(void)1328 ipf_event_reg(void)
1329 {
1330 V_ipf_arrivetag = EVENTHANDLER_REGISTER(ifnet_arrival_event, \
1331 ipf_ifevent, NULL, \
1332 EVENTHANDLER_PRI_ANY);
1333 V_ipf_departtag = EVENTHANDLER_REGISTER(ifnet_departure_event, \
1334 ipf_ifevent, NULL, \
1335 EVENTHANDLER_PRI_ANY);
1336 }
1337
1338 void
ipf_event_dereg(void)1339 ipf_event_dereg(void)
1340 {
1341 if (V_ipf_arrivetag != NULL) {
1342 EVENTHANDLER_DEREGISTER(ifnet_arrival_event, V_ipf_arrivetag);
1343 }
1344 if (V_ipf_departtag != NULL) {
1345 EVENTHANDLER_DEREGISTER(ifnet_departure_event, V_ipf_departtag);
1346 }
1347 }
1348
1349
1350 u_32_t
ipf_random(void)1351 ipf_random(void)
1352 {
1353 return (arc4random());
1354 }
1355
1356
1357 u_int
ipf_pcksum(fr_info_t * fin,int hlen,u_int sum)1358 ipf_pcksum(fr_info_t *fin, int hlen, u_int sum)
1359 {
1360 struct mbuf *m;
1361 u_int sum2;
1362 int off;
1363
1364 m = fin->fin_m;
1365 off = (char *)fin->fin_dp - (char *)fin->fin_ip;
1366 m->m_data += hlen;
1367 m->m_len -= hlen;
1368 sum2 = in_cksum(fin->fin_m, fin->fin_plen - off);
1369 m->m_len += hlen;
1370 m->m_data -= hlen;
1371
1372 /*
1373 * Both sum and sum2 are partial sums, so combine them together.
1374 */
1375 sum += ~sum2 & 0xffff;
1376 while (sum > 0xffff)
1377 sum = (sum & 0xffff) + (sum >> 16);
1378 sum2 = ~sum & 0xffff;
1379 return (sum2);
1380 }
1381
1382 #ifdef USE_INET6
1383 u_int
ipf_pcksum6(struct mbuf * m,ip6_t * ip6,u_int32_t off,u_int32_t len)1384 ipf_pcksum6(struct mbuf *m, ip6_t *ip6, u_int32_t off, u_int32_t len)
1385 {
1386 #ifdef _KERNEL
1387 int sum;
1388
1389 if (m->m_len < sizeof(struct ip6_hdr)) {
1390 return (0xffff);
1391 }
1392
1393 sum = in6_cksum(m, ip6->ip6_nxt, off, len);
1394 return (sum);
1395 #else
1396 u_short *sp;
1397 u_int sum;
1398
1399 sp = (u_short *)&ip6->ip6_src;
1400 sum = *sp++; /* ip6_src */
1401 sum += *sp++;
1402 sum += *sp++;
1403 sum += *sp++;
1404 sum += *sp++;
1405 sum += *sp++;
1406 sum += *sp++;
1407 sum += *sp++;
1408 sum += *sp++; /* ip6_dst */
1409 sum += *sp++;
1410 sum += *sp++;
1411 sum += *sp++;
1412 sum += *sp++;
1413 sum += *sp++;
1414 sum += *sp++;
1415 sum += *sp++;
1416 return (ipf_pcksum(fin, off, sum));
1417 #endif
1418 }
1419 #endif
1420
1421 void
ipf_fbsd_kenv_get(ipf_main_softc_t * softc)1422 ipf_fbsd_kenv_get(ipf_main_softc_t *softc)
1423 {
1424 TUNABLE_INT_FETCH("net.inet.ipf.large_nat",
1425 &softc->ipf_large_nat);
1426 }
1427