1/*	$NetBSD: ip_fil.c,v 1.6 2023/06/24 05:31:51 msaitoh Exp $	*/
2
3/*
4 * Copyright (C) 2012 by Darren Reed.
5 *
6 * See the IPFILTER.LICENCE file for details on licencing.
7 *
8 * Id: ip_fil.c,v 1.1.1.2 2012/07/22 13:44:12 darrenr Exp
9 */
10#if !defined(lint)
11static __attribute__((__used__)) const char sccsid[] = "@(#)ip_fil.c	2.41 6/5/96 (C) 1993-2000 Darren Reed";
12static __attribute__((__used__)) const char rcsid[] = "@(#)Id: ip_fil.c,v 1.1.1.2 2012/07/22 13:44:12 darrenr Exp";
13#endif
14
15#include "ipf.h"
16#include "md5.h"
17#include "ipt.h"
18
19ipf_main_softc_t	ipfmain;
20
21static	struct	ifnet **ifneta = NULL;
22static	int	nifs = 0;
23
24struct	rtentry;
25
26static	void	ipf_setifpaddr __P((struct ifnet *, char *));
27void	init_ifp __P((void));
28#if defined(__sgi) && (IRIX < 60500)
29static int 	no_output __P((struct ifnet *, struct mbuf *,
30			       struct sockaddr *));
31static int	write_output __P((struct ifnet *, struct mbuf *,
32				  struct sockaddr *));
33#else
34# if TRU64 >= 1885
35static int 	no_output __P((struct ifnet *, struct mbuf *,
36			       struct sockaddr *, struct rtentry *, char *));
37static int	write_output __P((struct ifnet *, struct mbuf *,
38				  struct sockaddr *, struct rtentry *, char *));
39# else
40#if defined(__NetBSD_Version__) && (__NetBSD_Version__ >= 499001100)
41static int 	no_output(struct ifnet *, struct mbuf *,
42	    const struct sockaddr *, struct rtentry *);
43static int	write_output(struct ifnet *, struct mbuf *,
44	    const struct sockaddr *, struct rtentry *);
45#else
46static int 	no_output __P((struct ifnet *, struct mbuf *,
47			       struct sockaddr *, struct rtentry *));
48static int	write_output __P((struct ifnet *, struct mbuf *,
49				  struct sockaddr *, struct rtentry *));
50#endif
51# endif
52#endif
53
54
55int
56ipfattach(softc)
57	ipf_main_softc_t *softc;
58{
59	return 0;
60}
61
62
63int
64ipfdetach(softc)
65	ipf_main_softc_t *softc;
66{
67	return 0;
68}
69
70
71/*
72 * Filter ioctl interface.
73 */
74int
75ipfioctl(softc, dev, cmd, data, mode)
76	ipf_main_softc_t *softc;
77	int dev;
78	ioctlcmd_t cmd;
79	void *data;
80	int mode;
81{
82	int error = 0, unit = 0, uid;
83
84	uid = getuid();
85	unit = dev;
86
87	SPL_NET(s);
88
89	error = ipf_ioctlswitch(softc, unit, data, cmd, mode, uid, NULL);
90	if (error != -1) {
91		SPL_X(s);
92		return error;
93	}
94	SPL_X(s);
95	return error;
96}
97
98
99void
100ipf_forgetifp(softc, ifp)
101	ipf_main_softc_t *softc;
102	void *ifp;
103{
104	register frentry_t *f;
105
106	WRITE_ENTER(&softc->ipf_mutex);
107	for (f = softc->ipf_acct[0][softc->ipf_active]; (f != NULL);
108	     f = f->fr_next)
109		if (f->fr_ifa == ifp)
110			f->fr_ifa = (void *)-1;
111	for (f = softc->ipf_acct[1][softc->ipf_active]; (f != NULL);
112	     f = f->fr_next)
113		if (f->fr_ifa == ifp)
114			f->fr_ifa = (void *)-1;
115	for (f = softc->ipf_rules[0][softc->ipf_active]; (f != NULL);
116	     f = f->fr_next)
117		if (f->fr_ifa == ifp)
118			f->fr_ifa = (void *)-1;
119	for (f = softc->ipf_rules[1][softc->ipf_active]; (f != NULL);
120	     f = f->fr_next)
121		if (f->fr_ifa == ifp)
122			f->fr_ifa = (void *)-1;
123	RWLOCK_EXIT(&softc->ipf_mutex);
124	ipf_nat_sync(softc, ifp);
125	ipf_lookup_sync(softc, ifp);
126}
127
128
129static int
130#if defined(__sgi) && (IRIX < 60500)
131no_output(ifp, m, s)
132#else
133# if TRU64 >= 1885
134no_output (ifp, m, s, rt, cp)
135	char *cp;
136# else
137no_output(ifp, m, s, rt)
138# endif
139	struct rtentry *rt;
140#endif
141	struct ifnet *ifp;
142	struct mbuf *m;
143	const struct sockaddr *s;
144{
145	return 0;
146}
147
148
149static int
150#if defined(__sgi) && (IRIX < 60500)
151write_output(ifp, m, s)
152#else
153# if TRU64 >= 1885
154write_output (ifp, m, s, rt, cp)
155	char *cp;
156# else
157write_output(ifp, m, s, rt)
158# endif
159	struct rtentry *rt;
160#endif
161	struct ifnet *ifp;
162	struct mbuf *m;
163	const struct sockaddr *s;
164{
165	char fname[32];
166	mb_t *mb;
167	ip_t *ip;
168	int fd;
169
170	mb = (mb_t *)m;
171	ip = MTOD(mb, ip_t *);
172
173#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
174    (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
175    (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
176	sprintf(fname, "/tmp/%s", ifp->if_xname);
177#else
178	sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
179#endif
180	fd = open(fname, O_WRONLY|O_APPEND);
181	if (fd == -1) {
182		perror("open");
183		return -1;
184	}
185	write(fd, (char *)ip, ntohs(ip->ip_len));
186	close(fd);
187	return 0;
188}
189
190
191static void
192ipf_setifpaddr(ifp, addr)
193	struct ifnet *ifp;
194	char *addr;
195{
196#ifdef __sgi
197	struct in_ifaddr *ifa;
198#else
199	struct ifaddr *ifa;
200#endif
201
202#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
203	if (ifp->if_addrlist.tqh_first != NULL)
204#else
205# ifdef __sgi
206	if (ifp->in_ifaddr != NULL)
207# else
208	if (ifp->if_addrlist != NULL)
209# endif
210#endif
211		return;
212
213	ifa = (struct ifaddr *)calloc(1, sizeof(*ifa));
214#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
215	ifp->if_addrlist.tqh_first = ifa;
216#else
217# ifdef __sgi
218	ifp->in_ifaddr = ifa;
219# else
220	ifp->if_addrlist = ifa;
221# endif
222#endif
223
224	if (ifa != NULL) {
225		struct sockaddr_in *sin;
226
227#ifdef __sgi
228		sin = (struct sockaddr_in *)&ifa->ia_addr;
229#else
230		sin = (struct sockaddr_in *)&ifa->ifa_addr;
231#endif
232#ifdef USE_INET6
233		if (index(addr, ':') != NULL) {
234			struct sockaddr_in6 *sin6;
235
236			sin6 = (struct sockaddr_in6 *)&ifa->ifa_addr;
237			sin6->sin6_family = AF_INET6;
238			inet_pton(AF_INET6, addr, &sin6->sin6_addr);
239		} else
240#endif
241		{
242			sin->sin_family = AF_INET;
243			sin->sin_addr.s_addr = inet_addr(addr);
244			if (sin->sin_addr.s_addr == 0)
245				abort();
246		}
247	}
248}
249
250struct ifnet *
251get_unit(name, family)
252	char *name;
253	int family;
254{
255	struct ifnet *ifp, **ifpp, **old_ifneta;
256	char *addr;
257#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
258    (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
259    (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
260
261	if (!*name)
262		return NULL;
263
264	if (name == NULL)
265		name = "anon0";
266
267	addr = strchr(name, '=');
268	if (addr != NULL)
269		*addr++ = '\0';
270
271	for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
272		if (!strcmp(name, ifp->if_xname)) {
273			if (addr != NULL)
274				ipf_setifpaddr(ifp, addr);
275			return ifp;
276		}
277	}
278#else
279	char *s, ifname[LIFNAMSIZ+1];
280
281	if (name == NULL)
282		name = "anon0";
283
284	addr = strchr(name, '=');
285	if (addr != NULL)
286		*addr++ = '\0';
287
288	for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
289		COPYIFNAME(family, ifp, ifname);
290		if (!strcmp(name, ifname)) {
291			if (addr != NULL)
292				ipf_setifpaddr(ifp, addr);
293			return ifp;
294		}
295	}
296#endif
297
298	if (!ifneta) {
299		ifneta = (struct ifnet **)calloc(1, sizeof(ifp) * 2);
300		if (!ifneta)
301			return NULL;
302		ifneta[1] = NULL;
303		ifneta[0] = (struct ifnet *)calloc(1, sizeof(*ifp));
304		if (!ifneta[0]) {
305			free(ifneta);
306			return NULL;
307		}
308		nifs = 1;
309	} else {
310		old_ifneta = ifneta;
311		nifs++;
312		ifneta = (struct ifnet **)realloc(ifneta,
313						  (nifs + 1) * sizeof(ifp));
314		if (!ifneta) {
315			free(old_ifneta);
316			nifs = 0;
317			return NULL;
318		}
319		ifneta[nifs] = NULL;
320		ifneta[nifs - 1] = (struct ifnet *)calloc(1, sizeof(*ifp));
321		if (!ifneta[nifs - 1]) {
322			nifs--;
323			return NULL;
324		}
325	}
326	ifp = ifneta[nifs - 1];
327
328#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
329	TAILQ_INIT(&ifp->if_addrlist);
330#endif
331#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
332    (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
333    (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
334	(void) strncpy(ifp->if_xname, name, sizeof(ifp->if_xname));
335#else
336	s = name + strlen(name) - 1;
337	for (; s > name; s--) {
338		if (!ISDIGIT(*s)) {
339			s++;
340			break;
341		}
342	}
343
344	if ((s > name) && (*s != 0) && ISDIGIT(*s)) {
345		ifp->if_unit = atoi(s);
346		ifp->if_name = (char *)malloc(s - name + 1);
347		(void) strncpy(ifp->if_name, name, s - name);
348		ifp->if_name[s - name] = '\0';
349	} else {
350		ifp->if_name = strdup(name);
351		ifp->if_unit = -1;
352	}
353#endif
354	ifp->if_output = (void *)no_output;
355
356	if (addr != NULL) {
357		ipf_setifpaddr(ifp, addr);
358	}
359
360	return ifp;
361}
362
363
364char *
365get_ifname(ifp)
366	struct ifnet *ifp;
367{
368	static char ifname[LIFNAMSIZ];
369
370#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(linux) || \
371    (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
372	sprintf(ifname, "%s", ifp->if_xname);
373#else
374	if (ifp->if_unit != -1)
375		sprintf(ifname, "%s%d", ifp->if_name, ifp->if_unit);
376	else
377		strcpy(ifname, ifp->if_name);
378#endif
379	return ifname;
380}
381
382
383
384void
385init_ifp()
386{
387	struct ifnet *ifp, **ifpp;
388	char fname[32];
389	int fd;
390
391#if (defined(NetBSD) && (NetBSD <= 1991011) && (NetBSD >= 199606)) || \
392    (defined(OpenBSD) && (OpenBSD >= 199603)) || defined(linux) || \
393    (defined(__FreeBSD__) && (__FreeBSD_version >= 501113))
394	for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
395		ifp->if_output = (void *)write_output;
396		sprintf(fname, "/tmp/%s", ifp->if_xname);
397		fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
398		if (fd == -1)
399			perror("open");
400		else
401			close(fd);
402	}
403#else
404
405	for (ifpp = ifneta; ifpp && (ifp = *ifpp); ifpp++) {
406		ifp->if_output = (void *)write_output;
407		sprintf(fname, "/tmp/%s%d", ifp->if_name, ifp->if_unit);
408		fd = open(fname, O_WRONLY|O_CREAT|O_EXCL|O_TRUNC, 0600);
409		if (fd == -1)
410			perror("open");
411		else
412			close(fd);
413	}
414#endif
415}
416
417
418int
419ipf_fastroute(m, mpp, fin, fdp)
420	mb_t *m, **mpp;
421	fr_info_t *fin;
422	frdest_t *fdp;
423{
424	struct ifnet *ifp;
425	ip_t *ip = fin->fin_ip;
426	frdest_t node;
427	int error = 0;
428	frentry_t *fr;
429	void *sifp;
430	int sout;
431
432	sifp = fin->fin_ifp;
433	sout = fin->fin_out;
434	fr = fin->fin_fr;
435	ip->ip_sum = 0;
436
437	if (!(fr->fr_flags & FR_KEEPSTATE) && (fdp != NULL) &&
438	    (fdp->fd_type == FRD_DSTLIST)) {
439		bzero(&node, sizeof(node));
440		ipf_dstlist_select_node(fin, fdp->fd_ptr, NULL, &node);
441		fdp = &node;
442	}
443	ifp = fdp->fd_ptr;
444
445	if (ifp == NULL)
446		return 0;	/* no routing table out here */
447
448	if (fin->fin_out == 0) {
449		fin->fin_ifp = ifp;
450		fin->fin_out = 1;
451		(void) ipf_acctpkt(fin, NULL);
452		fin->fin_fr = NULL;
453		if (!fr || !(fr->fr_flags & FR_RETMASK)) {
454			u_32_t pass;
455
456			(void) ipf_state_check(fin, &pass);
457		}
458
459		switch (ipf_nat_checkout(fin, NULL))
460		{
461		case 0 :
462			break;
463		case 1 :
464			ip->ip_sum = 0;
465			break;
466		case -1 :
467			error = -1;
468			goto done;
469			break;
470		}
471
472	}
473
474	m->mb_ifp = ifp;
475	printpacket(fin->fin_out, m);
476
477#if defined(__sgi) && (IRIX < 60500)
478	(*ifp->if_output)(ifp, (void *)ip, NULL);
479# if TRU64 >= 1885
480	(*ifp->if_output)(ifp, (void *)m, NULL, 0, 0);
481# else
482	(*ifp->if_output)(ifp, (void *)m, NULL, 0);
483# endif
484#endif
485done:
486	fin->fin_ifp = sifp;
487	fin->fin_out = sout;
488	return error;
489}
490
491
492int
493ipf_send_reset(fin)
494	fr_info_t *fin;
495{
496	ipfkverbose("- TCP RST sent\n");
497	return 0;
498}
499
500
501int
502ipf_send_icmp_err(type, fin, dst)
503	int type;
504	fr_info_t *fin;
505	int dst;
506{
507	ipfkverbose("- ICMP unreachable sent\n");
508	return 0;
509}
510
511
512void
513m_freem(m)
514	mb_t *m;
515{
516	return;
517}
518
519
520void
521m_copydata(m, off, len, cp)
522	mb_t *m;
523	int off, len;
524	void * cp;
525{
526	bcopy((char *)m + off, cp, len);
527}
528
529
530int
531ipfuiomove(buf, len, rwflag, uio)
532	void *buf;
533	int len, rwflag;
534	struct uio *uio;
535{
536	int left, ioc, num, offset;
537	struct iovec *io;
538	char *start;
539
540	if (rwflag == UIO_READ) {
541		left = len;
542		ioc = 0;
543
544		offset = uio->uio_offset;
545
546		while ((left > 0) && (ioc < uio->uio_iovcnt)) {
547			io = uio->uio_iov + ioc;
548			num = io->iov_len;
549			if (num > left)
550				num = left;
551			start = (char *)io->iov_base + offset;
552			if (start > (char *)io->iov_base + io->iov_len) {
553				offset -= io->iov_len;
554				ioc++;
555				continue;
556			}
557			bcopy(buf, start, num);
558			uio->uio_resid -= num;
559			uio->uio_offset += num;
560			left -= num;
561			if (left > 0)
562				ioc++;
563		}
564		if (left > 0)
565			return EFAULT;
566	}
567	return 0;
568}
569
570
571u_32_t
572ipf_newisn(fin)
573	fr_info_t *fin;
574{
575	static int iss_seq_off = 0;
576	u_char hash[16];
577	u_32_t newiss;
578	MD5_CTX ctx;
579
580	/*
581	 * Compute the base value of the ISS.  It is a hash
582	 * of (saddr, sport, daddr, dport, secret).
583	 */
584	MD5Init(&ctx);
585
586	MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_src,
587		  sizeof(fin->fin_fi.fi_src));
588	MD5Update(&ctx, (u_char *) &fin->fin_fi.fi_dst,
589		  sizeof(fin->fin_fi.fi_dst));
590	MD5Update(&ctx, (u_char *) &fin->fin_dat, sizeof(fin->fin_dat));
591
592	/* MD5Update(&ctx, ipf_iss_secret, sizeof(ipf_iss_secret)); */
593
594	MD5Final(hash, &ctx);
595
596	memcpy(&newiss, hash, sizeof(newiss));
597
598	/*
599	 * Now increment our "timer", and add it in to
600	 * the computed value.
601	 *
602	 * XXX Use `addin'?
603	 * XXX TCP_ISSINCR too large to use?
604	 */
605	iss_seq_off += 0x00010000;
606	newiss += iss_seq_off;
607	return newiss;
608}
609
610
611/* ------------------------------------------------------------------------ */
612/* Function:    ipf_nextipid                                                */
613/* Returns:     int - 0 == success, -1 == error (packet should be dropped)  */
614/* Parameters:  fin(I) - pointer to packet information                      */
615/*                                                                          */
616/* Returns the next IPv4 ID to use for this packet.                         */
617/* ------------------------------------------------------------------------ */
618EXTERN_INLINE u_short
619ipf_nextipid(fin)
620	fr_info_t *fin;
621{
622	static u_short ipid = 0;
623	ipf_main_softc_t *softc = fin->fin_main_soft;
624	u_short id;
625
626	MUTEX_ENTER(&softc->ipf_rw);
627	if (fin->fin_pktnum != 0) {
628		/*
629		 * The -1 is for aligned test results.
630		 */
631		id = (fin->fin_pktnum - 1) & 0xffff;
632	} else {
633	}
634		id = ipid++;
635	MUTEX_EXIT(&softc->ipf_rw);
636
637	return id;
638}
639
640
641EXTERN_INLINE int
642ipf_checkv4sum(fin)
643	fr_info_t *fin;
644{
645
646	if (fin->fin_flx & FI_SHORT)
647		return 1;
648
649	if (ipf_checkl4sum(fin) == -1) {
650		fin->fin_flx |= FI_BAD;
651		return -1;
652	}
653	return 0;
654}
655
656
657#ifdef	USE_INET6
658EXTERN_INLINE int
659ipf_checkv6sum(fin)
660	fr_info_t *fin;
661{
662	if (fin->fin_flx & FI_SHORT)
663		return 1;
664
665	if (ipf_checkl4sum(fin) == -1) {
666		fin->fin_flx |= FI_BAD;
667		return -1;
668	}
669	return 0;
670}
671#endif
672
673
674#if 0
675/*
676 * See above for description, except that all addressing is in user space.
677 */
678int
679copyoutptr(softc, src, dst, size)
680	void *src, *dst;
681	size_t size;
682{
683	caddr_t ca;
684
685	bcopy(dst, (char *)&ca, sizeof(ca));
686	bcopy(src, ca, size);
687	return 0;
688}
689
690
691/*
692 * See above for description, except that all addressing is in user space.
693 */
694int
695copyinptr(src, dst, size)
696	void *src, *dst;
697	size_t size;
698{
699	caddr_t ca;
700
701	bcopy(src, (char *)&ca, sizeof(ca));
702	bcopy(ca, dst, size);
703	return 0;
704}
705#endif
706
707
708/*
709 * return the first IP Address associated with an interface
710 */
711int
712ipf_ifpaddr(softc, v, atype, ifptr, inp, inpmask)
713	ipf_main_softc_t *softc;
714	int v, atype;
715	void *ifptr;
716	i6addr_t *inp, *inpmask;
717{
718	struct ifnet *ifp = ifptr;
719#ifdef __sgi
720	struct in_ifaddr *ifa;
721#else
722	struct ifaddr *ifa;
723#endif
724
725#if defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__)
726	ifa = ifp->if_addrlist.tqh_first;
727#else
728# ifdef __sgi
729	ifa = (struct in_ifaddr *)ifp->in_ifaddr;
730# else
731	ifa = ifp->if_addrlist;
732# endif
733#endif
734	if (ifa != NULL) {
735		if (v == 4) {
736			struct sockaddr_in *sin, mask;
737
738			mask.sin_addr.s_addr = 0xffffffff;
739
740#ifdef __sgi
741			sin = (struct sockaddr_in *)&ifa->ia_addr;
742#else
743			sin = (struct sockaddr_in *)&ifa->ifa_addr;
744#endif
745
746			return ipf_ifpfillv4addr(atype, sin, &mask,
747						 &inp->in4, &inpmask->in4);
748		}
749#ifdef USE_INET6
750		if (v == 6) {
751			struct sockaddr_in6 *sin6, mask;
752
753			sin6 = (struct sockaddr_in6 *)&ifa->ifa_addr;
754			((i6addr_t *)&mask.sin6_addr)->i6[0] = 0xffffffff;
755			((i6addr_t *)&mask.sin6_addr)->i6[1] = 0xffffffff;
756			((i6addr_t *)&mask.sin6_addr)->i6[2] = 0xffffffff;
757			((i6addr_t *)&mask.sin6_addr)->i6[3] = 0xffffffff;
758			return ipf_ifpfillv6addr(atype, sin6, &mask,
759						 inp, inpmask);
760		}
761#endif
762	}
763	return 0;
764}
765
766
767/*
768 * This function is not meant to be random, rather just produce a
769 * sequence of numbers that isn't linear to show "randomness".
770 */
771u_32_t
772ipf_random()
773{
774	static unsigned int last = 0xa5a5a5a5;
775	static int calls = 0;
776	int number;
777
778	calls++;
779
780	/*
781	 * These are deliberately chosen to ensure that there is some
782	 * attempt to test whether the output covers the range in test n18.
783	 */
784	switch (calls)
785	{
786	case 1 :
787		number = 0;
788		break;
789	case 2 :
790		number = 4;
791		break;
792	case 3 :
793		number = 3999;
794		break;
795	case 4 :
796		number = 4000;
797		break;
798	case 5 :
799		number = 48999;
800		break;
801	case 6 :
802		number = 49000;
803		break;
804	default :
805		number = last;
806		last *= calls;
807		last++;
808		number ^= last;
809		break;
810	}
811	return number;
812}
813
814
815int
816ipf_verifysrc(fin)
817	fr_info_t *fin;
818{
819	return 1;
820}
821
822
823int
824ipf_inject(fin, m)
825	fr_info_t *fin;
826	mb_t *m;
827{
828	FREE_MB_T(m);
829
830	return 0;
831}
832
833
834u_int
835ipf_pcksum(fin, hlen, sum)
836	fr_info_t *fin;
837	int hlen;
838	u_int sum;
839{
840	u_short *sp;
841	u_int sum2;
842	int slen;
843
844	slen = fin->fin_plen - hlen;
845	sp = (u_short *)((u_char *)fin->fin_ip + hlen);
846
847	for (; slen > 1; slen -= 2)
848		sum += *sp++;
849	if (slen)
850		sum += ntohs(*(u_char *)sp << 8);
851	while (sum > 0xffff)
852		sum = (sum & 0xffff) + (sum >> 16);
853	sum2 = (u_short)(~sum & 0xffff);
854
855	return sum2;
856}
857
858
859void *
860ipf_pullup(m, fin, plen)
861	mb_t *m;
862	fr_info_t *fin;
863	int plen;
864{
865	if (M_LEN(m) >= plen)
866		return fin->fin_ip;
867
868	/*
869	 * Fake ipf_pullup failing
870	 */
871	fin->fin_reason = FRB_PULLUP;
872	*fin->fin_mp = NULL;
873	fin->fin_m = NULL;
874	fin->fin_ip = NULL;
875	return NULL;
876}
877