ip_fil_netbsd.c revision 1.1 1 /* $NetBSD: ip_fil_netbsd.c,v 1.1 2012/03/23 20:36:55 christos Exp $ */
2
3 /*
4 * Copyright (C) 2012 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";
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 #include <sys/param.h>
20 #if (NetBSD >= 199905) && !defined(IPFILTER_LKM)
21 # include "opt_pfil_hooks.h"
22 # include "opt_ipsec.h"
23 #endif
24 #include <sys/errno.h>
25 #include <sys/types.h>
26 #include <sys/file.h>
27 #include <sys/ioctl.h>
28 #include <sys/time.h>
29 #include <sys/systm.h>
30 #include <sys/select.h>
31 #if (NetBSD > 199609)
32 # include <sys/dirent.h>
33 #else
34 # include <sys/dir.h>
35 #endif
36 #if (__NetBSD_Version__ >= 599005900)
37 # include <sys/cprng.h>
38 #endif
39 #include <sys/mbuf.h>
40 #include <sys/protosw.h>
41 #include <sys/socket.h>
42 #include <sys/poll.h>
43 #if (__NetBSD_Version__ >= 399002000)
44 # include <sys/kauth.h>
45 #endif
46
47 #include <net/if.h>
48 #include <net/route.h>
49 #include <netinet/in.h>
50 #include <netinet/in_var.h>
51 #include <netinet/in_systm.h>
52 #include <netinet/ip.h>
53 #include <netinet/ip_var.h>
54 #include <netinet/tcp.h>
55 #if __NetBSD_Version__ >= 105190000 /* 1.5T */
56 # include <netinet/tcp_timer.h>
57 # include <netinet/tcp_var.h>
58 #endif
59 #include <netinet/udp.h>
60 #include <netinet/tcpip.h>
61 #include <netinet/ip_icmp.h>
62 #include "netinet/ip_compat.h"
63 #ifdef USE_INET6
64 # include <netinet/icmp6.h>
65 # if (__NetBSD_Version__ >= 106000000)
66 # include <netinet6/nd6.h>
67 # endif
68 #endif
69 #include "netinet/ip_fil.h"
70 #include "netinet/ip_nat.h"
71 #include "netinet/ip_frag.h"
72 #include "netinet/ip_state.h"
73 #include "netinet/ip_proxy.h"
74 #include "netinet/ip_auth.h"
75 #include "netinet/ip_sync.h"
76 #include "netinet/ip_lookup.h"
77 #include "netinet/ip_dstlist.h"
78 #ifdef IPFILTER_SCAN
79 #include "netinet/ip_scan.h"
80 #endif
81 #include <sys/md5.h>
82 #include <sys/kernel.h>
83 #include <sys/conf.h>
84 #ifdef INET
85 extern int ip_optcopy __P((struct ip *, struct ip *));
86 #endif
87
88 #ifdef IPFILTER_M_IPFILTER
89 MALLOC_DEFINE(M_IPFILTER, "IP Filter", "IP Filter packet filter data structures");
90 #endif
91
92 #if __NetBSD_Version__ >= 105009999
93 # define csuminfo csum_flags
94 #endif
95
96 #if __NetBSD_Version__ < 200000000
97 extern struct protosw inetsw[];
98 #endif
99 #if (NetBSD >= 199511)
100 static int ipfopen(dev_t dev, int flags, int devtype, PROC_T *p);
101 static int ipfclose(dev_t dev, int flags, int devtype, PROC_T *p);
102 #else
103 # if (__NetBSD_Version__ >= 399001400)
104 static int ipfopen(dev_t dev, int flags, struct lwp *);
105 static int ipfclose(dev_t dev, int flags, struct lwp *);
106 # else
107 static int ipfopen(dev_t dev, int flags);
108 static int ipfclose(dev_t dev, int flags);
109 # endif /* __NetBSD_Version__ >= 399001400 */
110 #endif
111 static int ipfread(dev_t, struct uio *, int ioflag);
112 static int ipfwrite(dev_t, struct uio *, int ioflag);
113 static int ipfpoll(dev_t, int events, PROC_T *);
114 static void ipf_timer_func __P((void *ptr));
115
116 const struct cdevsw ipl_cdevsw = {
117 ipfopen, ipfclose, ipfread, ipfwrite, ipfioctl,
118 nostop, notty, ipfpoll, nommap,
119 #if (__NetBSD_Version__ >= 200000000)
120 nokqfilter,
121 #endif
122 #ifdef D_OTHER
123 D_OTHER,
124 #endif
125 };
126
127 ipf_main_softc_t ipfmain;
128
129 static u_short ipid = 0;
130 static int (*ipf_savep) __P((void *, ip_t *, int, void *, int, struct mbuf **));
131 static int ipf_send_ip __P((fr_info_t *, mb_t *));
132 #ifdef USE_INET6
133 static int ipf_fastroute6 __P((struct mbuf *, struct mbuf **,
134 fr_info_t *, frdest_t *));
135 #endif
136
137 #if defined(NETBSD_PF)
138 # include <net/pfil.h>
139 /*
140 * We provide the ipf_checkp name just to minimize changes later.
141 */
142 int (*ipf_checkp) __P((void *, ip_t *ip, int hlen, void *ifp, int out, mb_t **mp));
143 #endif /* NETBSD_PF */
144
145 #if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105110000)
146 # include <net/pfil.h>
147
148 static int ipf_check_wrapper(void *, struct mbuf **, struct ifnet *, int );
149
150 static int
151 ipf_check_wrapper(arg, mp, ifp, dir)
152 void *arg;
153 struct mbuf **mp;
154 struct ifnet *ifp;
155 int dir;
156 {
157 struct ip *ip;
158 int rv, hlen;
159
160 #if __NetBSD_Version__ >= 200080000
161 /*
162 * ensure that mbufs are writable beforehand
163 * as it's assumed by ipf code.
164 * XXX inefficient
165 */
166 int error = m_makewritable(mp, 0, M_COPYALL, M_DONTWAIT);
167
168 if (error) {
169 m_freem(*mp);
170 *mp = NULL;
171 return error;
172 }
173 #endif
174 ip = mtod(*mp, struct ip *);
175 hlen = ip->ip_hl << 2;
176
177 #ifdef INET
178 #if defined(M_CSUM_TCPv4)
179 /*
180 * If the packet is out-bound, we can't delay checksums
181 * here. For in-bound, the checksum has already been
182 * validated.
183 */
184 if (dir == PFIL_OUT) {
185 if ((*mp)->m_pkthdr.csum_flags & (M_CSUM_TCPv4|M_CSUM_UDPv4)) {
186 in_delayed_cksum(*mp);
187 (*mp)->m_pkthdr.csum_flags &=
188 ~(M_CSUM_TCPv4|M_CSUM_UDPv4);
189 }
190 }
191 #endif /* M_CSUM_TCPv4 */
192 #endif /* INET */
193
194 /*
195 * Note, we don't need to update the checksum, because
196 * it has already been verified.
197 */
198 rv = ipf_check(&ipfmain, ip, hlen, ifp, (dir == PFIL_OUT), mp);
199
200 return (rv);
201 }
202
203 # ifdef USE_INET6
204 # include <netinet/ip6.h>
205
206 static int ipf_check_wrapper6(void *, struct mbuf **, struct ifnet *, int );
207
208 static int
209 ipf_check_wrapper6(arg, mp, ifp, dir)
210 void *arg;
211 struct mbuf **mp;
212 struct ifnet *ifp;
213 int dir;
214 {
215 # if defined(M_CSUM_TCPv6) && (__NetBSD_Version__ > 200000000)
216 /*
217 * If the packet is out-bound, we can't delay checksums
218 * here. For in-bound, the checksum has already been
219 * validated.
220 */
221 if (dir == PFIL_OUT) {
222 if ((*mp)->m_pkthdr.csum_flags & (M_CSUM_TCPv6|M_CSUM_UDPv6)) {
223 # if (__NetBSD_Version__ > 399000600)
224 in6_delayed_cksum(*mp);
225 # endif
226 (*mp)->m_pkthdr.csum_flags &= ~(M_CSUM_TCPv6|
227 M_CSUM_UDPv6);
228 }
229 }
230 # endif
231
232 return (ipf_check(&ipfmain, mtod(*mp, struct ip *), sizeof(struct ip6_hdr),
233 ifp, (dir == PFIL_OUT), mp));
234 }
235 # endif
236
237
238 # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET)
239 static int ipf_pfilsync(void *, struct mbuf **, struct ifnet *, int);
240
241 static int
242 ipf_pfilsync(hdr, mp, ifp, dir)
243 void *hdr;
244 struct mbuf **mp;
245 struct ifnet *ifp;
246 int dir;
247 {
248 /*
249 * The interface pointer is useless for create (we have nothing to
250 * compare it to) and at detach, the interface name is still in the
251 * list of active NICs (albeit, down, but that's not any real
252 * indicator) and doing ifunit() on the name will still return the
253 * pointer, so it's not much use then, either.
254 */
255 ipf_sync(&ipfmain, NULL);
256 return 0;
257 }
258 # endif
259
260 #endif /* __NetBSD_Version__ >= 105110000 */
261
262
263 #if defined(IPFILTER_LKM)
264 int
265 ipf_identify(s)
266 char *s;
267 {
268 if (strcmp(s, "ipl") == 0)
269 return 1;
270 return 0;
271 }
272 #endif /* IPFILTER_LKM */
273
274
275 /*
276 * Try to detect the case when compiling for NetBSD with pseudo-device
277 */
278 void
279 ipfilterattach(count)
280 int count;
281 {
282 if (ipf_load_all() == 0)
283 (void) ipf_create_all(&ipfmain);
284 }
285
286
287 int
288 ipfattach(softc)
289 ipf_main_softc_t *softc;
290 {
291 SPL_INT(s);
292 #if (__NetBSD_Version__ >= 499005500)
293 int i;
294 #endif
295 #if defined(NETBSD_PF) && (__NetBSD_Version__ >= 104200000)
296 int error = 0;
297 # if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 105110000)
298 struct pfil_head *ph_inet;
299 # ifdef USE_INET6
300 struct pfil_head *ph_inet6;
301 # endif
302 # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET)
303 struct pfil_head *ph_ifsync;
304 # endif
305 # endif
306 #endif
307
308 SPL_NET(s);
309 if ((softc->ipf_running > 0) || (ipf_checkp == ipf_check)) {
310 printf("IP Filter: already initialized\n");
311 SPL_X(s);
312 IPFERROR(130017);
313 return EBUSY;
314 }
315
316 if (ipf_init_all(softc) < 0) {
317 SPL_X(s);
318 IPFERROR(130015);
319 return EIO;
320 }
321
322 #ifdef NETBSD_PF
323 # if (__NetBSD_Version__ >= 104200000)
324 # if __NetBSD_Version__ >= 105110000
325 ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
326 # ifdef USE_INET6
327 ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
328 # endif
329 # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET)
330 ph_ifsync = pfil_head_get(PFIL_TYPE_IFNET, 0);
331 # endif
332
333 if (ph_inet == NULL
334 # ifdef USE_INET6
335 && ph_inet6 == NULL
336 # endif
337 # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET)
338 && ph_ifsync == NULL
339 # endif
340 ) {
341 SPL_X(s);
342 IPFERROR(130016);
343 return ENODEV;
344 }
345
346 if (ph_inet != NULL)
347 error = pfil_add_hook((void *)ipf_check_wrapper, NULL,
348 PFIL_IN|PFIL_OUT, ph_inet);
349 else
350 error = 0;
351 # else
352 error = pfil_add_hook((void *)ipf_check, PFIL_IN|PFIL_OUT,
353 &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
354 # endif
355 if (error) {
356 IPFERROR(130013);
357 goto pfil_error;
358 }
359 # else
360 pfil_add_hook((void *)ipf_check, PFIL_IN|PFIL_OUT);
361 # endif
362
363 # ifdef USE_INET6
364 # if __NetBSD_Version__ >= 105110000
365 if (ph_inet6 != NULL)
366 error = pfil_add_hook((void *)ipf_check_wrapper6, NULL,
367 PFIL_IN|PFIL_OUT, ph_inet6);
368 else
369 error = 0;
370 if (error) {
371 pfil_remove_hook((void *)ipf_check_wrapper6, NULL,
372 PFIL_IN|PFIL_OUT, ph_inet6);
373 ipfmain.ipf_interror = 130014;
374 goto pfil_error;
375 }
376 # else
377 error = pfil_add_hook((void *)ipf_check, PFIL_IN|PFIL_OUT,
378 &inetsw[ip_protox[IPPROTO_IPV6]].pr_pfh);
379 if (error) {
380 pfil_remove_hook((void *)ipf_check, PFIL_IN|PFIL_OUT,
381 &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
382 IPFERROR(130014);
383 goto pfil_error;
384 }
385 # endif
386 # endif
387
388 # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET)
389 if (ph_ifsync != NULL)
390 (void) pfil_add_hook((void *)ipf_pfilsync, NULL,
391 PFIL_IFNET, ph_ifsync);
392 # endif
393 #endif
394
395 #if (__NetBSD_Version__ >= 499005500)
396 for (i = 0; i < IPL_LOGSIZE; i++)
397 selinit(&ipfmain.ipf_selwait[i]);
398 #else
399 bzero((char *)ipfmain.ipf_selwait, sizeof(ipfmain.ipf_selwait));
400 #endif
401 ipf_savep = ipf_checkp;
402 ipf_checkp = ipf_check;
403
404 #ifdef INET
405 if (softc->ipf_control_forwarding & 1)
406 ipforwarding = 1;
407 #endif
408
409 ipid = 0;
410
411 SPL_X(s);
412
413 #if (__NetBSD_Version__ >= 104010000)
414 # if (__NetBSD_Version__ >= 499002000)
415 callout_init(&softc->ipf_slow_ch, 0);
416 # else
417 callout_init(&softc->ipf_slow_ch);
418 # endif
419 callout_reset(&softc->ipf_slow_ch, (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT,
420 ipf_timer_func, softc);
421 #else
422 timeout(ipf_timer_func, softc, (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT);
423 #endif
424 return 0;
425
426 #if __NetBSD_Version__ >= 105110000
427 pfil_error:
428 SPL_X(s);
429 ipf_fini_all(softc);
430 return error;
431 #endif
432 }
433
434 static void
435 ipf_timer_func(ptr)
436 void *ptr;
437 {
438 ipf_main_softc_t *softc = ptr;
439 SPL_INT(s);
440
441 SPL_NET(s);
442 READ_ENTER(&softc->ipf_global);
443
444 if (softc->ipf_running > 0)
445 ipf_slowtimer(softc);
446
447 if (softc->ipf_running == -1 || softc->ipf_running == 1) {
448 #if NETBSD_GE_REV(104240000)
449 callout_reset(&softc->ipf_slow_ch, hz / 2,
450 ipf_timer_func, softc);
451 #else
452 timeout(ipf_timer_func, softc,
453 (hz / IPF_HZ_DIVIDE) * IPF_HZ_MULT);
454 #endif
455 }
456 RWLOCK_EXIT(&softc->ipf_global);
457 SPL_X(s);
458 }
459
460
461 /*
462 * Disable the filter by removing the hooks from the IP input/output
463 * stream.
464 */
465 int
466 ipfdetach(softc)
467 ipf_main_softc_t *softc;
468 {
469 SPL_INT(s);
470 #if (__NetBSD_Version__ >= 499005500)
471 int i;
472 #endif
473 #if defined(NETBSD_PF) && (__NetBSD_Version__ >= 104200000)
474 int error = 0;
475 # if __NetBSD_Version__ >= 105150000
476 struct pfil_head *ph_inet = pfil_head_get(PFIL_TYPE_AF, AF_INET);
477 # ifdef USE_INET6
478 struct pfil_head *ph_inet6 = pfil_head_get(PFIL_TYPE_AF, AF_INET6);
479 # endif
480 # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET)
481 struct pfil_head *ph_ifsync = pfil_head_get(PFIL_TYPE_IFNET, 0);
482 # endif
483 # endif
484 #endif
485
486 SPL_NET(s);
487
488 #if (__NetBSD_Version__ >= 104010000)
489 if (softc->ipf_running > 0)
490 callout_stop(&softc->ipf_slow_ch);
491 #else
492 untimeout(ipf_slowtimer, NULL);
493 #endif /* NetBSD */
494
495 ipf_checkp = ipf_savep;
496 (void) ipf_flush(softc, IPL_LOGIPF, FR_INQUE|FR_OUTQUE|FR_INACTIVE);
497 (void) ipf_flush(softc, IPL_LOGIPF, FR_INQUE|FR_OUTQUE);
498
499 #ifdef INET
500 if (softc->ipf_control_forwarding & 2)
501 ipforwarding = 0;
502 #endif
503
504 #ifdef NETBSD_PF
505 # if (__NetBSD_Version__ >= 104200000)
506 # if __NetBSD_Version__ >= 105110000
507 # if defined(PFIL_TYPE_IFNET) && defined(PFIL_IFNET)
508 (void) pfil_remove_hook((void *)ipf_pfilsync, NULL,
509 PFIL_IFNET, ph_ifsync);
510 # endif
511
512 if (ph_inet != NULL)
513 error = pfil_remove_hook((void *)ipf_check_wrapper, NULL,
514 PFIL_IN|PFIL_OUT, ph_inet);
515 else
516 error = 0;
517 # else
518 error = pfil_remove_hook((void *)ipf_check, PFIL_IN|PFIL_OUT,
519 &inetsw[ip_protox[IPPROTO_IP]].pr_pfh);
520 # endif
521 if (error) {
522 SPL_X(s);
523 IPFERROR(130011);
524 return error;
525 }
526 # else
527 pfil_remove_hook((void *)ipf_check, PFIL_IN|PFIL_OUT);
528 # endif
529 # ifdef USE_INET6
530 # if __NetBSD_Version__ >= 105110000
531 if (ph_inet6 != NULL)
532 error = pfil_remove_hook((void *)ipf_check_wrapper6, NULL,
533 PFIL_IN|PFIL_OUT, ph_inet6);
534 else
535 error = 0;
536 # else
537 error = pfil_remove_hook((void *)ipf_check, PFIL_IN|PFIL_OUT,
538 &inetsw[ip_protox[IPPROTO_IPV6]].pr_pfh);
539 # endif
540 if (error) {
541 SPL_X(s);
542 IPFERROR(130012);
543 return error;
544 }
545 # endif
546 #endif
547 SPL_X(s);
548
549 #if (__NetBSD_Version__ >= 499005500)
550 for (i = 0; i < IPL_LOGSIZE; i++)
551 seldestroy(&ipfmain.ipf_selwait[i]);
552 #endif
553
554 ipf_fini_all(softc);
555
556 return 0;
557 }
558
559
560 /*
561 * Filter ioctl interface.
562 */
563 int
564 ipfioctl(dev, cmd, data, mode
565 #if (NetBSD >= 199511)
566 , p)
567 # if (__NetBSD_Version__ >= 399001400)
568 struct lwp *p;
569 # if (__NetBSD_Version__ >= 399002000)
570 # define UID(l) kauth_cred_getuid((l)->l_cred)
571 # else
572 # define UID(l) ((l)->l_proc->p_cred->p_ruid)
573 # endif
574 # else
575 struct proc *p;
576 # define UID(p) ((p)->p_cred->p_ruid)
577 # endif
578 #else
579 )
580 #endif
581 dev_t dev;
582 u_long cmd;
583 #if (__NetBSD_Version__ >= 499001000)
584 void *data;
585 #else
586 caddr_t data;
587 #endif
588 int mode;
589 {
590 int error = 0, unit = 0;
591 SPL_INT(s);
592
593 #if (__NetBSD_Version__ >= 399002000)
594 if ((mode & FWRITE) &&
595 kauth_authorize_network(p->l_cred, KAUTH_NETWORK_FIREWALL,
596 KAUTH_REQ_NETWORK_FIREWALL_FW, NULL,
597 NULL, NULL)) {
598 ipfmain.ipf_interror = 130005;
599 return EPERM;
600 }
601 #else
602 if ((securelevel >= 2) && (mode & FWRITE)) {
603 ipfmain.ipf_interror = 130001;
604 return EPERM;
605 }
606 #endif
607
608 unit = GET_MINOR(dev);
609 if ((IPL_LOGMAX < unit) || (unit < 0)) {
610 ipfmain.ipf_interror = 130002;
611 return ENXIO;
612 }
613
614 if (ipfmain.ipf_running <= 0) {
615 if (unit != IPL_LOGIPF) {
616 ipfmain.ipf_interror = 130003;
617 return EIO;
618 }
619 if (cmd != SIOCIPFGETNEXT && cmd != SIOCIPFGET &&
620 cmd != SIOCIPFSET && cmd != SIOCFRENB &&
621 cmd != SIOCGETFS && cmd != SIOCGETFF &&
622 cmd != SIOCIPFINTERROR) {
623 ipfmain.ipf_interror = 130004;
624 return EIO;
625 }
626 }
627
628 SPL_NET(s);
629
630 error = ipf_ioctlswitch(&ipfmain, unit, data, cmd, mode, UID(p), p);
631 if (error != -1) {
632 SPL_X(s);
633 return error;
634 }
635
636 SPL_X(s);
637 return error;
638 }
639
640
641 /*
642 * ipf_send_reset - this could conceivably be a call to tcp_respond(), but that
643 * requires a large amount of setting up and isn't any more efficient.
644 */
645 int
646 ipf_send_reset(fin)
647 fr_info_t *fin;
648 {
649 struct tcphdr *tcp, *tcp2;
650 int tlen = 0, hlen;
651 struct mbuf *m;
652 #ifdef USE_INET6
653 ip6_t *ip6;
654 #endif
655 ip_t *ip;
656
657 tcp = fin->fin_dp;
658 if (tcp->th_flags & TH_RST)
659 return -1; /* feedback loop */
660
661 if (ipf_checkl4sum(fin) == -1)
662 return -1;
663
664 tlen = fin->fin_dlen - (TCP_OFF(tcp) << 2) +
665 ((tcp->th_flags & TH_SYN) ? 1 : 0) +
666 ((tcp->th_flags & TH_FIN) ? 1 : 0);
667
668 #ifdef USE_INET6
669 hlen = (fin->fin_v == 6) ? sizeof(ip6_t) : sizeof(ip_t);
670 #else
671 hlen = sizeof(ip_t);
672 #endif
673 #ifdef MGETHDR
674 MGETHDR(m, M_DONTWAIT, MT_HEADER);
675 #else
676 MGET(m, M_DONTWAIT, MT_HEADER);
677 #endif
678 if (m == NULL)
679 return -1;
680 if (sizeof(*tcp2) + hlen > MHLEN) {
681 MCLGET(m, M_DONTWAIT);
682 if (m == NULL)
683 return -1;
684 if ((m->m_flags & M_EXT) == 0) {
685 FREE_MB_T(m);
686 return -1;
687 }
688 }
689
690 m->m_len = sizeof(*tcp2) + hlen;
691 m->m_data += max_linkhdr;
692 m->m_pkthdr.len = m->m_len;
693 m->m_pkthdr.rcvif = (struct ifnet *)0;
694 ip = mtod(m, struct ip *);
695 bzero((char *)ip, hlen);
696 #ifdef USE_INET6
697 ip6 = (ip6_t *)ip;
698 #endif
699 bzero((char *)ip, sizeof(*tcp2) + hlen);
700 tcp2 = (struct tcphdr *)((char *)ip + hlen);
701 tcp2->th_sport = tcp->th_dport;
702 tcp2->th_dport = tcp->th_sport;
703
704 if (tcp->th_flags & TH_ACK) {
705 tcp2->th_seq = tcp->th_ack;
706 tcp2->th_flags = TH_RST;
707 tcp2->th_ack = 0;
708 } else {
709 tcp2->th_seq = 0;
710 tcp2->th_ack = ntohl(tcp->th_seq);
711 tcp2->th_ack += tlen;
712 tcp2->th_ack = htonl(tcp2->th_ack);
713 tcp2->th_flags = TH_RST|TH_ACK;
714 }
715 tcp2->th_x2 = 0;
716 TCP_OFF_A(tcp2, sizeof(*tcp2) >> 2);
717 tcp2->th_win = tcp->th_win;
718 tcp2->th_sum = 0;
719 tcp2->th_urp = 0;
720
721 #ifdef USE_INET6
722 if (fin->fin_v == 6) {
723 ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow;
724 ip6->ip6_plen = htons(sizeof(struct tcphdr));
725 ip6->ip6_nxt = IPPROTO_TCP;
726 ip6->ip6_hlim = 0;
727 ip6->ip6_src = fin->fin_dst6.in6;
728 ip6->ip6_dst = fin->fin_src6.in6;
729 tcp2->th_sum = in6_cksum(m, IPPROTO_TCP,
730 sizeof(*ip6), sizeof(*tcp2));
731 return ipf_send_ip(fin, m);
732 }
733 #endif
734 #ifdef INET
735 ip->ip_p = IPPROTO_TCP;
736 ip->ip_len = htons(sizeof(struct tcphdr));
737 ip->ip_src.s_addr = fin->fin_daddr;
738 ip->ip_dst.s_addr = fin->fin_saddr;
739 tcp2->th_sum = in_cksum(m, hlen + sizeof(*tcp2));
740 ip->ip_len = hlen + sizeof(*tcp2);
741 return ipf_send_ip(fin, m);
742 #else
743 return 0;
744 #endif
745 }
746
747
748 /*
749 * Expects ip_len to be in host byte order when called.
750 */
751 static int
752 ipf_send_ip(fin, m)
753 fr_info_t *fin;
754 mb_t *m;
755 {
756 fr_info_t fnew;
757 #ifdef INET
758 ip_t *oip;
759 #endif
760 ip_t *ip;
761 int hlen;
762
763 ip = mtod(m, ip_t *);
764 bzero((char *)&fnew, sizeof(fnew));
765 fnew.fin_main_soft = fin->fin_main_soft;
766
767 IP_V_A(ip, fin->fin_v);
768 switch (fin->fin_v)
769 {
770 #ifdef INET
771 case 4 :
772 oip = fin->fin_ip;
773 hlen = sizeof(*oip);
774 fnew.fin_v = 4;
775 fnew.fin_p = ip->ip_p;
776 fnew.fin_plen = ntohs(ip->ip_len);
777 HTONS(ip->ip_len);
778 IP_HL_A(ip, sizeof(*oip) >> 2);
779 ip->ip_tos = oip->ip_tos;
780 ip->ip_id = ipf_nextipid(fin);
781 ip->ip_off = htons(ip_mtudisc ? IP_DF : 0);
782 ip->ip_ttl = ip_defttl;
783 ip->ip_sum = 0;
784 break;
785 #endif
786 #ifdef USE_INET6
787 case 6 :
788 {
789 ip6_t *ip6 = (ip6_t *)ip;
790
791 ip6->ip6_vfc = 0x60;
792 ip6->ip6_hlim = IPDEFTTL;
793
794 hlen = sizeof(*ip6);
795 fnew.fin_p = ip6->ip6_nxt;
796 fnew.fin_v = 6;
797 fnew.fin_plen = ntohs(ip6->ip6_plen) + hlen;
798 break;
799 }
800 #endif
801 default :
802 return EINVAL;
803 }
804 #ifdef IPSEC
805 m->m_pkthdr.rcvif = NULL;
806 #endif
807
808 fnew.fin_ifp = fin->fin_ifp;
809 fnew.fin_flx = FI_NOCKSUM;
810 fnew.fin_m = m;
811 fnew.fin_ip = ip;
812 fnew.fin_mp = &m;
813 fnew.fin_hlen = hlen;
814 fnew.fin_dp = (char *)ip + hlen;
815 (void) ipf_makefrip(hlen, ip, &fnew);
816
817 return ipf_fastroute(m, &m, &fnew, NULL);
818 }
819
820
821 int
822 ipf_send_icmp_err(type, fin, dst)
823 int type;
824 fr_info_t *fin;
825 int dst;
826 {
827 int err, hlen, xtra, iclen, ohlen, avail, code;
828 struct in_addr dst4;
829 struct icmp *icmp;
830 struct mbuf *m;
831 i6addr_t dst6;
832 void *ifp;
833 #ifdef USE_INET6
834 ip6_t *ip6;
835 #endif
836 ip_t *ip, *ip2;
837
838 if ((type < 0) || (type > ICMP_MAXTYPE))
839 return -1;
840
841 code = fin->fin_icode;
842 #ifdef USE_INET6
843 if ((code < 0) || (code > sizeof(icmptoicmp6unreach)/sizeof(int)))
844 return -1;
845 #endif
846
847 if (ipf_checkl4sum(fin) == -1)
848 return -1;
849 #ifdef MGETHDR
850 MGETHDR(m, M_DONTWAIT, MT_HEADER);
851 #else
852 MGET(m, M_DONTWAIT, MT_HEADER);
853 #endif
854 if (m == NULL)
855 return -1;
856 avail = MHLEN;
857
858 xtra = 0;
859 hlen = 0;
860 ohlen = 0;
861 dst4.s_addr = 0;
862 ifp = fin->fin_ifp;
863 if (fin->fin_v == 4) {
864 if ((fin->fin_p == IPPROTO_ICMP) && !(fin->fin_flx & FI_SHORT))
865 switch (ntohs(fin->fin_data[0]) >> 8)
866 {
867 case ICMP_ECHO :
868 case ICMP_TSTAMP :
869 case ICMP_IREQ :
870 case ICMP_MASKREQ :
871 break;
872 default :
873 FREE_MB_T(m);
874 return 0;
875 }
876
877 if (dst == 0) {
878 if (ipf_ifpaddr(&ipfmain, 4, FRI_NORMAL, ifp,
879 &dst6, NULL) == -1) {
880 FREE_MB_T(m);
881 return -1;
882 }
883 dst4 = dst6.in4;
884 } else
885 dst4.s_addr = fin->fin_daddr;
886
887 hlen = sizeof(ip_t);
888 ohlen = fin->fin_hlen;
889 iclen = hlen + offsetof(struct icmp, icmp_ip) + ohlen;
890 if (fin->fin_hlen < fin->fin_plen)
891 xtra = MIN(fin->fin_dlen, 8);
892 else
893 xtra = 0;
894 }
895
896 #ifdef USE_INET6
897 else if (fin->fin_v == 6) {
898 hlen = sizeof(ip6_t);
899 ohlen = sizeof(ip6_t);
900 iclen = hlen + offsetof(struct icmp, icmp_ip) + ohlen;
901 type = icmptoicmp6types[type];
902 if (type == ICMP6_DST_UNREACH)
903 code = icmptoicmp6unreach[code];
904
905 if (iclen + max_linkhdr + fin->fin_plen > avail) {
906 MCLGET(m, M_DONTWAIT);
907 if (m == NULL)
908 return -1;
909 if ((m->m_flags & M_EXT) == 0) {
910 FREE_MB_T(m);
911 return -1;
912 }
913 avail = MCLBYTES;
914 }
915 xtra = MIN(fin->fin_plen, avail - iclen - max_linkhdr);
916 xtra = MIN(xtra, IPV6_MMTU - iclen);
917 if (dst == 0) {
918 if (ipf_ifpaddr(&ipfmain, 6, FRI_NORMAL, ifp,
919 &dst6, NULL) == -1) {
920 FREE_MB_T(m);
921 return -1;
922 }
923 } else
924 dst6 = fin->fin_dst6;
925 }
926 #endif
927 else {
928 FREE_MB_T(m);
929 return -1;
930 }
931
932 avail -= (max_linkhdr + iclen);
933 if (avail < 0) {
934 FREE_MB_T(m);
935 return -1;
936 }
937 if (xtra > avail)
938 xtra = avail;
939 iclen += xtra;
940 m->m_data += max_linkhdr;
941 m->m_pkthdr.rcvif = (struct ifnet *)0;
942 m->m_pkthdr.len = iclen;
943 m->m_len = iclen;
944 ip = mtod(m, ip_t *);
945 icmp = (struct icmp *)((char *)ip + hlen);
946 ip2 = (ip_t *)&icmp->icmp_ip;
947
948 icmp->icmp_type = type;
949 icmp->icmp_code = fin->fin_icode;
950 icmp->icmp_cksum = 0;
951 #ifdef icmp_nextmtu
952 if (type == ICMP_UNREACH && fin->fin_icode == ICMP_UNREACH_NEEDFRAG) {
953 if (fin->fin_mtu != 0) {
954 icmp->icmp_nextmtu = htons(fin->fin_mtu);
955
956 } else if (ifp != NULL) {
957 icmp->icmp_nextmtu = htons(GETIFMTU_4(ifp));
958
959 } else { /* make up a number... */
960 icmp->icmp_nextmtu = htons(fin->fin_plen - 20);
961 }
962 }
963 #endif
964
965 bcopy((char *)fin->fin_ip, (char *)ip2, ohlen);
966
967 #if defined(M_CSUM_IPv4)
968 /*
969 * Clear any in-bound checksum flags for this packet.
970 */
971 m->m_pkthdr.csuminfo = 0;
972 #endif /* __NetBSD__ && M_CSUM_IPv4 */
973
974 #ifdef USE_INET6
975 ip6 = (ip6_t *)ip;
976 if (fin->fin_v == 6) {
977 ip6->ip6_flow = ((ip6_t *)fin->fin_ip)->ip6_flow;
978 ip6->ip6_plen = htons(iclen - hlen);
979 ip6->ip6_nxt = IPPROTO_ICMPV6;
980 ip6->ip6_hlim = 0;
981 ip6->ip6_src = dst6.in6;
982 ip6->ip6_dst = fin->fin_src6.in6;
983 if (xtra > 0)
984 bcopy((char *)fin->fin_ip + ohlen,
985 (char *)&icmp->icmp_ip + ohlen, xtra);
986 icmp->icmp_cksum = in6_cksum(m, IPPROTO_ICMPV6,
987 sizeof(*ip6), iclen - hlen);
988 } else
989 #endif
990 {
991 ip->ip_p = IPPROTO_ICMP;
992 ip->ip_src.s_addr = dst4.s_addr;
993 ip->ip_dst.s_addr = fin->fin_saddr;
994
995 if (xtra > 0)
996 bcopy((char *)fin->fin_ip + ohlen,
997 (char *)&icmp->icmp_ip + ohlen, xtra);
998 icmp->icmp_cksum = ipf_cksum((u_short *)icmp,
999 sizeof(*icmp) + 8);
1000 ip->ip_len = iclen;
1001 ip->ip_p = IPPROTO_ICMP;
1002 }
1003 err = ipf_send_ip(fin, m);
1004 return err;
1005 }
1006
1007
1008 /*
1009 * m0 - pointer to mbuf where the IP packet starts
1010 * mpp - pointer to the mbuf pointer that is the start of the mbuf chain
1011 */
1012 int
1013 ipf_fastroute(m0, mpp, fin, fdp)
1014 mb_t *m0, **mpp;
1015 fr_info_t *fin;
1016 frdest_t *fdp;
1017 {
1018 register struct ip *ip, *mhip;
1019 register struct mbuf *m = *mpp;
1020 register struct route *ro;
1021 int len, off, error = 0, hlen, code;
1022 struct ifnet *ifp, *sifp;
1023 ipf_main_softc_t *softc;
1024 #if __NetBSD_Version__ >= 499001100
1025 union {
1026 struct sockaddr dst;
1027 struct sockaddr_in dst4;
1028 } u;
1029 #else
1030 struct sockaddr_in *dst4;
1031 #endif
1032 struct sockaddr *dst;
1033 u_short ip_off, ip_len;
1034 struct route iproute;
1035 struct rtentry *rt;
1036 frdest_t node;
1037 frentry_t *fr;
1038
1039 if (fin->fin_v == 6) {
1040 #ifdef USE_INET6
1041 error = ipf_fastroute6(m0, mpp, fin, fdp);
1042 #else
1043 error = EPROTONOSUPPORT;
1044 #endif
1045 if ((error != 0) && (*mpp != NULL))
1046 FREE_MB_T(*mpp);
1047 return error;
1048 }
1049 #ifndef INET
1050 FREE_MB_T(*mpp);
1051 return EPROTONOSUPPORT;
1052 #else
1053
1054 hlen = fin->fin_hlen;
1055 ip = mtod(m0, struct ip *);
1056 softc = fin->fin_main_soft;
1057 rt = NULL;
1058 ifp = NULL;
1059
1060 # if defined(M_CSUM_IPv4)
1061 /*
1062 * Clear any in-bound checksum flags for this packet.
1063 */
1064 m0->m_pkthdr.csuminfo = 0;
1065 # endif /* __NetBSD__ && M_CSUM_IPv4 */
1066
1067 /*
1068 * Route packet.
1069 */
1070 ro = &iproute;
1071 bzero(ro, sizeof (*ro));
1072 fr = fin->fin_fr;
1073
1074 if ((fr != NULL) && !(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) &&
1075 (fdp->fd_type == FRD_DSTLIST)) {
1076 if (ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node) == 0)
1077 fdp = &node;
1078 }
1079 if (fdp != NULL)
1080 ifp = fdp->fd_ptr;
1081 else
1082 ifp = fin->fin_ifp;
1083
1084 if ((ifp == NULL) && ((fr == NULL) || !(fr->fr_flags & FR_FASTROUTE))) {
1085 error = -2;
1086 goto bad;
1087 }
1088
1089 # if __NetBSD_Version__ >= 499001100
1090 if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0))
1091 sockaddr_in_init(&u.dst4, &fdp->fd_ip, 0);
1092 else
1093 sockaddr_in_init(&u.dst4, &ip->ip_dst, 0);
1094 dst = &u.dst;
1095 rtcache_setdst(ro, dst);
1096 rt = rtcache_init(ro);
1097 # else
1098 dst4 = (struct sockaddr_in *)&ro->ro_dst;
1099 dst = (struct sockaddr *)dst4;
1100 dst4->sin_family = AF_INET;
1101 dst4->sin_addr = ip->ip_dst;
1102
1103 if ((fdp != NULL) && (fdp->fd_ip.s_addr != 0))
1104 dst4->sin_addr = fdp->fd_ip;
1105
1106 dst4->sin_len = sizeof(*dst);
1107 rtalloc(ro);
1108 rt = ro->ro_rt;
1109 # endif
1110 if ((ifp == NULL) && (rt != NULL))
1111 ifp = rt->rt_ifp;
1112 if ((rt == NULL) || (ifp == NULL)) {
1113 if (in_localaddr(ip->ip_dst))
1114 error = EHOSTUNREACH;
1115 else
1116 error = ENETUNREACH;
1117 goto bad;
1118 }
1119
1120
1121 if (rt->rt_flags & RTF_GATEWAY)
1122 dst = rt->rt_gateway;
1123
1124 rt->rt_use++;
1125
1126 /*
1127 * For input packets which are being "fastrouted", they won't
1128 * go back through output filtering and miss their chance to get
1129 * NAT'd and counted. Duplicated packets aren't considered to be
1130 * part of the normal packet stream, so do not NAT them or pass
1131 * them through stateful checking, etc.
1132 */
1133 if ((fdp != &fr->fr_dif) && (fin->fin_out == 0)) {
1134 sifp = fin->fin_ifp;
1135 fin->fin_ifp = ifp;
1136 fin->fin_out = 1;
1137 (void) ipf_acctpkt(fin, NULL);
1138 fin->fin_fr = NULL;
1139 if (!fr || !(fr->fr_flags & FR_RETMASK)) {
1140 u_32_t pass;
1141
1142 (void) ipf_state_check(fin, &pass);
1143 }
1144
1145 switch (ipf_nat_checkout(fin, NULL))
1146 {
1147 case 0 :
1148 break;
1149 case 1 :
1150 ip->ip_sum = 0;
1151 break;
1152 case -1 :
1153 error = -1;
1154 goto bad;
1155 break;
1156 }
1157
1158 fin->fin_ifp = sifp;
1159 fin->fin_out = 0;
1160 } else
1161 ip->ip_sum = 0;
1162 /*
1163 * If small enough for interface, can just send directly.
1164 */
1165 m->m_pkthdr.rcvif = ifp;
1166
1167 ip_len = ntohs(ip->ip_len);
1168 if (ip_len <= ifp->if_mtu) {
1169 # if defined(M_CSUM_IPv4)
1170 # if (__NetBSD_Version__ >= 105009999)
1171 if (ifp->if_csum_flags_tx & M_CSUM_IPv4)
1172 m->m_pkthdr.csuminfo |= M_CSUM_IPv4;
1173 # else
1174 if (ifp->if_capabilities & IFCAP_CSUM_IPv4)
1175 m->m_pkthdr.csuminfo |= M_CSUM_IPv4;
1176 # endif /* (__NetBSD_Version__ >= 105009999) */
1177 else if (ip->ip_sum == 0)
1178 ip->ip_sum = in_cksum(m, hlen);
1179 # else
1180 if (!ip->ip_sum)
1181 ip->ip_sum = in_cksum(m, hlen);
1182 # endif /* M_CSUM_IPv4 */
1183
1184 error = (*ifp->if_output)(ifp, m, dst, rt);
1185 goto done;
1186 }
1187
1188 /*
1189 * Too large for interface; fragment if possible.
1190 * Must be able to put at least 8 bytes per fragment.
1191 */
1192 ip_off = ntohs(ip->ip_off);
1193 if (ip_off & IP_DF) {
1194 error = EMSGSIZE;
1195 goto bad;
1196 }
1197 len = (ifp->if_mtu - hlen) &~ 7;
1198 if (len < 8) {
1199 error = EMSGSIZE;
1200 goto bad;
1201 }
1202
1203 {
1204 int mhlen, firstlen = len;
1205 struct mbuf **mnext = &m->m_act;
1206
1207 /*
1208 * Loop through length of segment after first fragment,
1209 * make new header and copy data of each part and link onto chain.
1210 */
1211 m0 = m;
1212 mhlen = sizeof (struct ip);
1213 for (off = hlen + len; off < ip_len; off += len) {
1214 # ifdef MGETHDR
1215 MGETHDR(m, M_DONTWAIT, MT_HEADER);
1216 # else
1217 MGET(m, M_DONTWAIT, MT_HEADER);
1218 # endif
1219 if (m == 0) {
1220 m = m0;
1221 error = ENOBUFS;
1222 goto bad;
1223 }
1224 m->m_data += max_linkhdr;
1225 mhip = mtod(m, struct ip *);
1226 bcopy((char *)ip, (char *)mhip, sizeof(*ip));
1227 if (hlen > sizeof (struct ip)) {
1228 mhlen = ip_optcopy(ip, mhip) + sizeof (struct ip);
1229 IP_HL_A(mhip, mhlen >> 2);
1230 }
1231 m->m_len = mhlen;
1232 mhip->ip_off = ((off - hlen) >> 3) + ip_off;
1233 if (off + len >= ip_len)
1234 len = ip_len - off;
1235 else
1236 mhip->ip_off |= IP_MF;
1237 mhip->ip_len = htons((u_short)(len + mhlen));
1238 m->m_next = m_copy(m0, off, len);
1239 if (m->m_next == 0) {
1240 error = ENOBUFS; /* ??? */
1241 goto sendorfree;
1242 }
1243 m->m_pkthdr.len = mhlen + len;
1244 m->m_pkthdr.rcvif = NULL;
1245 mhip->ip_off = htons((u_short)mhip->ip_off);
1246 mhip->ip_sum = 0;
1247 mhip->ip_sum = in_cksum(m, mhlen);
1248 *mnext = m;
1249 mnext = &m->m_act;
1250 }
1251 /*
1252 * Update first fragment by trimming what's been copied out
1253 * and updating header, then send each fragment (in order).
1254 */
1255 m_adj(m0, hlen + firstlen - ip_len);
1256 ip->ip_len = htons((u_short)(hlen + firstlen));
1257 ip->ip_off = htons((u_short)IP_MF);
1258 ip->ip_sum = 0;
1259 ip->ip_sum = in_cksum(m0, hlen);
1260 sendorfree:
1261 for (m = m0; m; m = m0) {
1262 m0 = m->m_act;
1263 m->m_act = 0;
1264 if (error == 0) {
1265 error = (*ifp->if_output)(ifp, m, dst, rt);
1266 } else {
1267 FREE_MB_T(m);
1268 }
1269 }
1270 }
1271 done:
1272 if (!error)
1273 softc->ipf_frouteok[0]++;
1274 else
1275 softc->ipf_frouteok[1]++;
1276
1277 # if __NetBSD_Version__ >= 499001100
1278 rtcache_free(ro);
1279 # else
1280 if (rt) {
1281 RTFREE(rt);
1282 }
1283 # endif
1284 return error;
1285 bad:
1286 if (error == EMSGSIZE) {
1287 sifp = fin->fin_ifp;
1288 code = fin->fin_icode;
1289 fin->fin_icode = ICMP_UNREACH_NEEDFRAG;
1290 fin->fin_ifp = ifp;
1291 (void) ipf_send_icmp_err(ICMP_UNREACH, fin, 1);
1292 fin->fin_ifp = sifp;
1293 fin->fin_icode = code;
1294 }
1295 FREE_MB_T(m);
1296 goto done;
1297 #endif /* INET */
1298 }
1299
1300
1301 #if defined(USE_INET6)
1302 /*
1303 * This is the IPv6 specific fastroute code. It doesn't clean up the mbuf's
1304 * or ensure that it is an IPv6 packet that is being forwarded, those are
1305 * expected to be done by the called (ipf_fastroute).
1306 */
1307 static int
1308 ipf_fastroute6(m0, mpp, fin, fdp)
1309 struct mbuf *m0, **mpp;
1310 fr_info_t *fin;
1311 frdest_t *fdp;
1312 {
1313 # if __NetBSD_Version__ >= 499001100
1314 struct route ip6route;
1315 const struct sockaddr *dst;
1316 union {
1317 struct sockaddr dst;
1318 struct sockaddr_in6 dst6;
1319 } u;
1320 struct route *ro;
1321 # else
1322 struct route_in6 ip6route;
1323 struct sockaddr_in6 *dst6;
1324 struct route_in6 *ro;
1325 # endif
1326 struct rtentry *rt;
1327 struct ifnet *ifp;
1328 frentry_t *fr;
1329 u_long mtu;
1330 int error;
1331
1332 error = 0;
1333 ro = &ip6route;
1334 fr = fin->fin_fr;
1335
1336 if (fdp != NULL)
1337 ifp = fdp->fd_ptr;
1338 else
1339 ifp = fin->fin_ifp;
1340 bzero(ro, sizeof(*ro));
1341 # if __NetBSD_Version__ >= 499001100
1342 if (fdp != NULL && IP6_NOTZERO(&fdp->fd_ip6))
1343 sockaddr_in6_init(&u.dst6, &fdp->fd_ip6.in6, 0, 0, 0);
1344 else
1345 sockaddr_in6_init(&u.dst6, &fin->fin_fi.fi_dst.in6, 0, 0, 0);
1346 dst = &u.dst;
1347 rtcache_setdst(ro, dst);
1348
1349 rt = rtcache_init(ro);
1350 if ((ifp == NULL) && (rt != NULL))
1351 ifp = rt->rt_ifp;
1352 # else
1353 dst6 = (struct sockaddr_in6 *)&ro->ro_dst;
1354 dst6->sin6_family = AF_INET6;
1355 dst6->sin6_len = sizeof(struct sockaddr_in6);
1356 dst6->sin6_addr = fin->fin_fi.fi_dst.in6;
1357
1358 if (fdp != NULL) {
1359 if (IP6_NOTZERO(&fdp->fd_ip6))
1360 dst6->sin6_addr = fdp->fd_ip6.in6;
1361 }
1362
1363 rtalloc((struct route *)ro);
1364
1365 if ((ifp == NULL) && (ro->ro_rt != NULL))
1366 ifp = ro->ro_rt->rt_ifp;
1367 rt = ro->ro_rt;
1368 # endif
1369 if ((rt == NULL) || (ifp == NULL)) {
1370
1371 error = EHOSTUNREACH;
1372 goto bad;
1373 }
1374
1375 /* KAME */
1376 # if __NetBSD_Version__ >= 499001100
1377 if (IN6_IS_ADDR_LINKLOCAL(&u.dst6.sin6_addr))
1378 u.dst6.sin6_addr.s6_addr16[1] = htons(ifp->if_index);
1379 # else
1380 if (IN6_IS_ADDR_LINKLOCAL(&dst6->sin6_addr))
1381 dst6->sin6_addr.s6_addr16[1] = htons(ifp->if_index);
1382 # endif
1383
1384 {
1385 # if (__NetBSD_Version__ >= 106010000)
1386 struct in6_ifextra *ife;
1387 # endif
1388 if (rt->rt_flags & RTF_GATEWAY)
1389 # if __NetBSD_Version__ >= 499001100
1390 dst = rt->rt_gateway;
1391 # else
1392 dst6 = (struct sockaddr_in6 *)rt->rt_gateway;
1393 # endif
1394 rt->rt_use++;
1395
1396 /* Determine path MTU. */
1397 # if (__NetBSD_Version__ <= 106009999)
1398 mtu = nd_ifinfo[ifp->if_index].linkmtu;
1399 # else
1400 ife = (struct in6_ifextra *)(ifp)->if_afdata[AF_INET6];
1401 # ifdef IN6_LINKMTU
1402 mtu = IN6_LINKMTU(ifp);
1403 # else
1404 mtu = ife->nd_ifinfo[ifp->if_index].linkmtu;
1405 # endif
1406 # endif
1407 if ((error == 0) && (m0->m_pkthdr.len <= mtu)) {
1408 # if __NetBSD_Version__ >= 499001100
1409 error = nd6_output(ifp, ifp, *mpp, satocsin6(dst), rt);
1410 # else
1411 error = nd6_output(ifp, ifp, *mpp, dst6, rt);
1412 # endif
1413 } else {
1414 error = EMSGSIZE;
1415 }
1416 }
1417 bad:
1418 # if __NetBSD_Version__ >= 499001100
1419 rtcache_free(ro);
1420 # else
1421 if (ro->ro_rt != NULL) {
1422 RTFREE(((struct route *)ro)->ro_rt);
1423 }
1424 # endif
1425 return error;
1426 }
1427 #endif /* INET6 */
1428
1429
1430 int
1431 ipf_verifysrc(fin)
1432 fr_info_t *fin;
1433 {
1434 #if __NetBSD_Version__ >= 499001100
1435 union {
1436 struct sockaddr dst;
1437 struct sockaddr_in dst4;
1438 } u;
1439 struct rtentry *rt;
1440 #else
1441 struct sockaddr_in *dst;
1442 #endif
1443 struct route iproute;
1444 int rc;
1445
1446 #if __NetBSD_Version__ >= 499001100
1447 sockaddr_in_init(&u.dst4, &fin->fin_src, 0);
1448 rtcache_setdst(&iproute, &u.dst);
1449 rt = rtcache_init(&iproute);
1450 if (rt == NULL)
1451 rc = 0;
1452 else
1453 rc = (fin->fin_ifp == rt->rt_ifp);
1454 rtcache_free(&iproute);
1455 #else
1456 dst = (struct sockaddr_in *)&iproute.ro_dst;
1457 dst->sin_len = sizeof(*dst);
1458 dst->sin_family = AF_INET;
1459 dst->sin_addr = fin->fin_src;
1460 rtalloc(&iproute);
1461 if (iproute.ro_rt == NULL)
1462 return 0;
1463 rc = (fin->fin_ifp == iproute.ro_rt->rt_ifp);
1464 RTFREE(iproute.ro_rt);
1465 #endif
1466 return rc;
1467 }
1468
1469
1470 /*
1471 * return the first IP Address associated with an interface
1472 */
1473 int
1474 ipf_ifpaddr(softc, v, atype, ifptr, inp, inpmask)
1475 ipf_main_softc_t *softc;
1476 int v, atype;
1477 void *ifptr;
1478 i6addr_t *inp, *inpmask;
1479 {
1480 #ifdef USE_INET6
1481 struct in6_addr *inp6 = NULL;
1482 #endif
1483 struct sockaddr *sock, *mask;
1484 struct sockaddr_in *sin;
1485 struct ifaddr *ifa;
1486 struct ifnet *ifp;
1487
1488 if ((ifptr == NULL) || (ifptr == (void *)-1))
1489 return -1;
1490
1491 ifp = ifptr;
1492 mask = NULL;
1493
1494 if (v == 4)
1495 inp->in4.s_addr = 0;
1496 #ifdef USE_INET6
1497 else if (v == 6)
1498 bzero((char *)inp, sizeof(*inp));
1499 #endif
1500
1501 ifa = ifp->if_addrlist.tqh_first;
1502 sock = ifa->ifa_addr;
1503 while (sock != NULL && ifa != NULL) {
1504 sin = (struct sockaddr_in *)sock;
1505 if ((v == 4) && (sin->sin_family == AF_INET))
1506 break;
1507 #ifdef USE_INET6
1508 if ((v == 6) && (sin->sin_family == AF_INET6)) {
1509 inp6 = &((struct sockaddr_in6 *)sin)->sin6_addr;
1510 if (!IN6_IS_ADDR_LINKLOCAL(inp6) &&
1511 !IN6_IS_ADDR_LOOPBACK(inp6))
1512 break;
1513 }
1514 #endif
1515 ifa = ifa->ifa_list.tqe_next;
1516 if (ifa != NULL)
1517 sock = ifa->ifa_addr;
1518 }
1519 if (ifa == NULL || sock == NULL)
1520 return -1;
1521
1522 mask = ifa->ifa_netmask;
1523 if (atype == FRI_BROADCAST)
1524 sock = ifa->ifa_broadaddr;
1525 else if (atype == FRI_PEERADDR)
1526 sock = ifa->ifa_dstaddr;
1527
1528 #ifdef USE_INET6
1529 if (v == 6)
1530 return ipf_ifpfillv6addr(atype, (struct sockaddr_in6 *)sock,
1531 (struct sockaddr_in6 *)mask,
1532 inp, inpmask);
1533 #endif
1534 return ipf_ifpfillv4addr(atype, (struct sockaddr_in *)sock,
1535 (struct sockaddr_in *)mask,
1536 &inp->in4, &inpmask->in4);
1537 }
1538
1539
1540 u_32_t
1541 ipf_newisn(fin)
1542 fr_info_t *fin;
1543 {
1544 #if __NetBSD_Version__ >= 105190000 /* 1.5T */
1545 size_t asz;
1546
1547 if (fin->fin_v == 4)
1548 asz = sizeof(struct in_addr);
1549 else if (fin->fin_v == 6)
1550 asz = sizeof(fin->fin_src);
1551 else /* XXX: no way to return error */
1552 return 0;
1553 return tcp_new_iss1((void *)&fin->fin_src, (void *)&fin->fin_dst,
1554 fin->fin_sport, fin->fin_dport, asz, 0);
1555 #else
1556 static int iss_seq_off = 0;
1557 u_char hash[16];
1558 u_32_t newiss;
1559 MD5_CTX ctx;
1560
1561 /*
1562 * Compute the base value of the ISS. It is a hash
1563 * of (saddr, sport, daddr, dport, secret).
1564 */
1565 MD5Init(&ctx);
1566
1567 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src,
1568 sizeof(fin->fin_fi.fi_src));
1569 MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst,
1570 sizeof(fin->fin_fi.fi_dst));
1571 MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat));
1572
1573 MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret));
1574
1575 MD5Final(hash, &ctx);
1576
1577 memcpy(&newiss, hash, sizeof(newiss));
1578
1579 /*
1580 * Now increment our "timer", and add it in to
1581 * the computed value.
1582 *
1583 * XXX Use `addin'?
1584 * XXX TCP_ISSINCR too large to use?
1585 */
1586 iss_seq_off += 0x00010000;
1587 newiss += iss_seq_off;
1588 return newiss;
1589 #endif
1590 }
1591
1592
1593 /* ------------------------------------------------------------------------ */
1594 /* Function: ipf_nextipid */
1595 /* Returns: int - 0 == success, -1 == error (packet should be droppped) */
1596 /* Parameters: fin(I) - pointer to packet information */
1597 /* */
1598 /* Returns the next IPv4 ID to use for this packet. */
1599 /* ------------------------------------------------------------------------ */
1600 u_short
1601 ipf_nextipid(fin)
1602 fr_info_t *fin;
1603 {
1604 #ifdef USE_MUTEXES
1605 ipf_main_softc_t *softc = fin->fin_main_soft;
1606 #endif
1607 u_short id;
1608
1609 MUTEX_ENTER(&softc->ipf_rw);
1610 id = ipid++;
1611 MUTEX_EXIT(&softc->ipf_rw);
1612
1613 return id;
1614 }
1615
1616
1617 INLINE int
1618 ipf_checkv4sum(fin)
1619 fr_info_t *fin;
1620 {
1621 #ifdef M_CSUM_TCP_UDP_BAD
1622 int manual, pflag, cflags, active;
1623 mb_t *m;
1624
1625 if ((fin->fin_flx & FI_NOCKSUM) != 0)
1626 return 0;
1627
1628 if ((fin->fin_flx & FI_SHORT) != 0)
1629 return 1;
1630
1631 if (fin->fin_cksum != 0)
1632 return (fin->fin_cksum == 1) ? 0 : -1;
1633
1634 manual = 0;
1635 m = fin->fin_m;
1636 if (m == NULL) {
1637 manual = 1;
1638 goto skipauto;
1639 }
1640
1641 switch (fin->fin_p)
1642 {
1643 case IPPROTO_UDP :
1644 pflag = M_CSUM_UDPv4;
1645 break;
1646 case IPPROTO_TCP :
1647 pflag = M_CSUM_TCPv4;
1648 break;
1649 default :
1650 pflag = 0;
1651 manual = 1;
1652 break;
1653 }
1654
1655 active = ((struct ifnet *)fin->fin_ifp)->if_csum_flags_rx & pflag;
1656 active |= M_CSUM_TCP_UDP_BAD | M_CSUM_DATA;
1657 cflags = m->m_pkthdr.csum_flags & active;
1658
1659 if (pflag != 0) {
1660 if (cflags == (pflag | M_CSUM_TCP_UDP_BAD)) {
1661 fin->fin_flx |= FI_BAD;
1662 fin->fin_cksum = -1;
1663 } else if (cflags == (pflag | M_CSUM_DATA)) {
1664 if ((m->m_pkthdr.csum_data ^ 0xffff) != 0) {
1665 fin->fin_flx |= FI_BAD;
1666 fin->fin_cksum = -1;
1667 } else {
1668 fin->fin_cksum = 1;
1669 }
1670 } else if (cflags == pflag) {
1671 fin->fin_cksum = 1;
1672 } else {
1673 manual = 1;
1674 }
1675 }
1676 skipauto:
1677 if (manual != 0) {
1678 if (ipf_checkl4sum(fin) == -1) {
1679 fin->fin_flx |= FI_BAD;
1680 return -1;
1681 }
1682 }
1683 #else
1684 if (ipf_checkl4sum(fin) == -1) {
1685 fin->fin_flx |= FI_BAD;
1686 return -1;
1687 }
1688 #endif
1689 return 0;
1690 }
1691
1692
1693 #ifdef USE_INET6
1694 INLINE int
1695 ipf_checkv6sum(fin)
1696 fr_info_t *fin;
1697 {
1698 # ifdef M_CSUM_TCP_UDP_BAD
1699 int manual, pflag, cflags, active;
1700 mb_t *m;
1701
1702 if ((fin->fin_flx & FI_NOCKSUM) != 0)
1703 return 0;
1704
1705 if ((fin->fin_flx & FI_SHORT) != 0)
1706 return 1;
1707
1708 if (fin->fin_cksum != 0)
1709 return (fin->fin_cksum == 1) ? 0 : -1;
1710
1711
1712 manual = 0;
1713 m = fin->fin_m;
1714
1715 switch (fin->fin_p)
1716 {
1717 case IPPROTO_UDP :
1718 pflag = M_CSUM_UDPv6;
1719 break;
1720 case IPPROTO_TCP :
1721 pflag = M_CSUM_TCPv6;
1722 break;
1723 default :
1724 pflag = 0;
1725 manual = 1;
1726 break;
1727 }
1728
1729 active = ((struct ifnet *)fin->fin_ifp)->if_csum_flags_rx & pflag;
1730 active |= M_CSUM_TCP_UDP_BAD | M_CSUM_DATA;
1731 cflags = m->m_pkthdr.csum_flags & active;
1732
1733 if (pflag != 0) {
1734 if (cflags == (pflag | M_CSUM_TCP_UDP_BAD)) {
1735 fin->fin_flx |= FI_BAD;
1736 } else if (cflags == (pflag | M_CSUM_DATA)) {
1737 if ((m->m_pkthdr.csum_data ^ 0xffff) != 0)
1738 fin->fin_flx |= FI_BAD;
1739 } else if (cflags == pflag) {
1740 ;
1741 } else {
1742 manual = 1;
1743 }
1744 }
1745 if (manual != 0) {
1746 if (ipf_checkl4sum(fin) == -1) {
1747 fin->fin_flx |= FI_BAD;
1748 return -1;
1749 }
1750 }
1751 # else
1752 if (ipf_checkl4sum(fin) == -1) {
1753 fin->fin_flx |= FI_BAD;
1754 return -1;
1755 }
1756 # endif
1757 return 0;
1758 }
1759 #endif /* USE_INET6 */
1760
1761
1762 size_t
1763 mbufchainlen(m0)
1764 struct mbuf *m0;
1765 {
1766 size_t len;
1767
1768 if ((m0->m_flags & M_PKTHDR) != 0) {
1769 len = m0->m_pkthdr.len;
1770 } else {
1771 struct mbuf *m;
1772
1773 for (m = m0, len = 0; m != NULL; m = m->m_next)
1774 len += m->m_len;
1775 }
1776 return len;
1777 }
1778
1779
1780 /* ------------------------------------------------------------------------ */
1781 /* Function: ipf_pullup */
1782 /* Returns: NULL == pullup failed, else pointer to protocol header */
1783 /* Parameters: xmin(I)- pointer to buffer where data packet starts */
1784 /* fin(I) - pointer to packet information */
1785 /* len(I) - number of bytes to pullup */
1786 /* */
1787 /* Attempt to move at least len bytes (from the start of the buffer) into a */
1788 /* single buffer for ease of access. Operating system native functions are */
1789 /* used to manage buffers - if necessary. If the entire packet ends up in */
1790 /* a single buffer, set the FI_COALESCE flag even though ipf_coalesce() has */
1791 /* not been called. Both fin_ip and fin_dp are updated before exiting _IF_ */
1792 /* and ONLY if the pullup succeeds. */
1793 /* */
1794 /* We assume that 'xmin' is a pointer to a buffer that is part of the chain */
1795 /* of buffers that starts at *fin->fin_mp. */
1796 /* ------------------------------------------------------------------------ */
1797 void *
1798 ipf_pullup(xmin, fin, len)
1799 mb_t *xmin;
1800 fr_info_t *fin;
1801 int len;
1802 {
1803 int dpoff, ipoff;
1804 mb_t *m = xmin;
1805 char *ip;
1806
1807 if (m == NULL)
1808 return NULL;
1809
1810 ip = (char *)fin->fin_ip;
1811 if ((fin->fin_flx & FI_COALESCE) != 0)
1812 return ip;
1813
1814 ipoff = fin->fin_ipoff;
1815 if (fin->fin_dp != NULL)
1816 dpoff = (char *)fin->fin_dp - (char *)ip;
1817 else
1818 dpoff = 0;
1819
1820 if (M_LEN(m) < len) {
1821 mb_t *n = *fin->fin_mp;
1822 /*
1823 * Assume that M_PKTHDR is set and just work with what is left
1824 * rather than check..
1825 * Should not make any real difference, anyway.
1826 */
1827 if (m != n) {
1828 /*
1829 * Record the mbuf that points to the mbuf that we're
1830 * about to go to work on so that we can update the
1831 * m_next appropriately later.
1832 */
1833 for (; n->m_next != m; n = n->m_next)
1834 ;
1835 } else {
1836 n = NULL;
1837 }
1838
1839 #ifdef MHLEN
1840 if (len > MHLEN)
1841 #else
1842 if (len > MLEN)
1843 #endif
1844 {
1845 #ifdef HAVE_M_PULLDOWN
1846 if (m_pulldown(m, 0, len, NULL) == NULL)
1847 m = NULL;
1848 #else
1849 FREE_MB_T(*fin->fin_mp);
1850 m = NULL;
1851 n = NULL;
1852 #endif
1853 } else
1854 {
1855 m = m_pullup(m, len);
1856 }
1857 if (n != NULL)
1858 n->m_next = m;
1859 if (m == NULL) {
1860 /*
1861 * When n is non-NULL, it indicates that m pointed to
1862 * a sub-chain (tail) of the mbuf and that the head
1863 * of this chain has not yet been free'd.
1864 */
1865 if (n != NULL) {
1866 FREE_MB_T(*fin->fin_mp);
1867 }
1868
1869 *fin->fin_mp = NULL;
1870 fin->fin_m = NULL;
1871 return NULL;
1872 }
1873
1874 if (n == NULL)
1875 *fin->fin_mp = m;
1876
1877 while (M_LEN(m) == 0) {
1878 m = m->m_next;
1879 }
1880 fin->fin_m = m;
1881 ip = MTOD(m, char *) + ipoff;
1882
1883 fin->fin_ip = (ip_t *)ip;
1884 if (fin->fin_dp != NULL)
1885 fin->fin_dp = (char *)fin->fin_ip + dpoff;
1886 }
1887
1888 if (len == fin->fin_plen)
1889 fin->fin_flx |= FI_COALESCE;
1890 return ip;
1891 }
1892
1893
1894 int
1895 ipf_inject(fin, m)
1896 fr_info_t *fin;
1897 mb_t *m;
1898 {
1899 int error;
1900
1901 if (fin->fin_out == 0) {
1902 struct ifqueue *ifq;
1903
1904 ifq = &ipintrq;
1905
1906 if (IF_QFULL(ifq)) {
1907 IF_DROP(ifq);
1908 FREE_MB_T(m);
1909 error = ENOBUFS;
1910 } else {
1911 IF_ENQUEUE(ifq, m);
1912 error = 0;
1913 }
1914 } else {
1915 error = ip_output(m, NULL, NULL, IP_FORWARDING, NULL);
1916 }
1917
1918 return error;
1919 }
1920
1921
1922 u_32_t
1923 ipf_random()
1924 {
1925 int number;
1926
1927 #ifdef _CPRNG_H
1928 number = cprng_fast32();
1929 #else
1930 number = arc4random();
1931 #endif
1932 return number;
1933 }
1934
1935
1936 /*
1937 * routines below for saving IP headers to buffer
1938 */
1939 static int ipfopen(dev, flags
1940 #if (NetBSD >= 199511)
1941 , devtype, p)
1942 int devtype;
1943 PROC_T *p;
1944 #else
1945 )
1946 #endif
1947 dev_t dev;
1948 int flags;
1949 {
1950 u_int unit = GET_MINOR(dev);
1951 int error;
1952
1953 if (IPL_LOGMAX < unit) {
1954 error = ENXIO;
1955 } else {
1956 switch (unit)
1957 {
1958 case IPL_LOGIPF :
1959 case IPL_LOGNAT :
1960 case IPL_LOGSTATE :
1961 case IPL_LOGAUTH :
1962 case IPL_LOGLOOKUP :
1963 case IPL_LOGSYNC :
1964 #ifdef IPFILTER_SCAN
1965 case IPL_LOGSCAN :
1966 #endif
1967 error = 0;
1968 break;
1969 default :
1970 error = ENXIO;
1971 break;
1972 }
1973 }
1974 return error;
1975 }
1976
1977
1978 static int ipfclose(dev, flags
1979 #if (NetBSD >= 199511)
1980 , devtype, p)
1981 int devtype;
1982 PROC_T *p;
1983 #else
1984 )
1985 #endif
1986 dev_t dev;
1987 int flags;
1988 {
1989 u_int unit = GET_MINOR(dev);
1990
1991 if (IPL_LOGMAX < unit)
1992 unit = ENXIO;
1993 else
1994 unit = 0;
1995 return unit;
1996 }
1997
1998 /*
1999 * ipfread/ipflog
2000 * both of these must operate with at least splnet() lest they be
2001 * called during packet processing and cause an inconsistancy to appear in
2002 * the filter lists.
2003 */
2004 static int ipfread(dev, uio, ioflag)
2005 int ioflag;
2006 dev_t dev;
2007 register struct uio *uio;
2008 {
2009
2010 if (ipfmain.ipf_running < 1) {
2011 ipfmain.ipf_interror = 130006;
2012 return EIO;
2013 }
2014
2015 if (GET_MINOR(dev) == IPL_LOGSYNC)
2016 return ipf_sync_read(&ipfmain, uio);
2017
2018 #ifdef IPFILTER_LOG
2019 return ipf_log_read(&ipfmain, GET_MINOR(dev), uio);
2020 #else
2021 ipfmain.ipf_interror = 130007;
2022 return ENXIO;
2023 #endif
2024 }
2025
2026
2027 /*
2028 * ipfwrite
2029 * both of these must operate with at least splnet() lest they be
2030 * called during packet processing and cause an inconsistancy to appear in
2031 * the filter lists.
2032 */
2033 static int ipfwrite(dev, uio, ioflag)
2034 int ioflag;
2035 dev_t dev;
2036 register struct uio *uio;
2037 {
2038
2039 if (ipfmain.ipf_running < 1) {
2040 ipfmain.ipf_interror = 130008;
2041 return EIO;
2042 }
2043
2044 if (GET_MINOR(dev) == IPL_LOGSYNC)
2045 return ipf_sync_write(&ipfmain, uio);
2046 ipfmain.ipf_interror = 130009;
2047 return ENXIO;
2048 }
2049
2050
2051 static int ipfpoll(dev, events, p)
2052 dev_t dev;
2053 int events;
2054 PROC_T *p;
2055 {
2056 u_int unit = GET_MINOR(dev);
2057 int revents = 0;
2058
2059 if (IPL_LOGMAX < unit) {
2060 ipfmain.ipf_interror = 130010;
2061 return ENXIO;
2062 }
2063
2064 switch (unit)
2065 {
2066 case IPL_LOGIPF :
2067 case IPL_LOGNAT :
2068 case IPL_LOGSTATE :
2069 #ifdef IPFILTER_LOG
2070 if ((events & (POLLIN | POLLRDNORM)) &&
2071 ipf_log_canread(&ipfmain, unit))
2072 revents |= events & (POLLIN | POLLRDNORM);
2073 #endif
2074 break;
2075 case IPL_LOGAUTH :
2076 if ((events & (POLLIN | POLLRDNORM)) &&
2077 ipf_auth_waiting(&ipfmain))
2078 revents |= events & (POLLIN | POLLRDNORM);
2079 break;
2080 case IPL_LOGSYNC :
2081 if ((events & (POLLIN | POLLRDNORM)) &&
2082 ipf_sync_canread(&ipfmain))
2083 revents |= events & (POLLIN | POLLRDNORM);
2084 if ((events & (POLLOUT | POLLWRNORM)) &&
2085 ipf_sync_canwrite(&ipfmain))
2086 revents |= events & (POLLOUT | POLLWRNORM);
2087 break;
2088 case IPL_LOGSCAN :
2089 case IPL_LOGLOOKUP :
2090 default :
2091 break;
2092 }
2093
2094 if ((revents == 0) && (((events & (POLLIN|POLLRDNORM)) != 0)))
2095 selrecord(p, &ipfmain.ipf_selwait[unit]);
2096 return revents;
2097 }
2098
2099 u_int
2100 ipf_pcksum(fin, hlen, sum)
2101 fr_info_t *fin;
2102 int hlen;
2103 u_int sum;
2104 {
2105 struct mbuf *m;
2106 u_int sum2;
2107 int off;
2108
2109 m = fin->fin_m;
2110 off = (char *)fin->fin_dp - (char *)fin->fin_ip;
2111 m->m_data += hlen;
2112 m->m_len -= hlen;
2113 sum2 = in_cksum(fin->fin_m, fin->fin_plen - off);
2114 m->m_len += hlen;
2115 m->m_data -= hlen;
2116
2117 /*
2118 * Both sum and sum2 are partial sums, so combine them together.
2119 */
2120 sum += ~sum2 & 0xffff;
2121 while (sum > 0xffff)
2122 sum = (sum & 0xffff) + (sum >> 16);
2123 sum2 = ~sum & 0xffff;
2124 return sum2;
2125 }
2126