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