xref: /illumos-gate/usr/src/uts/common/inet/ipf/ip_frag.c (revision af5f29dd)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * Copyright (C) 1993-2003 by Darren Reed.
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * See the IPFILTER.LICENCE file for details on licencing.
5ab25eeb5Syz  *
672680cf5SDarren Reed  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
77c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
87c478bd9Sstevel@tonic-gate  */
97c478bd9Sstevel@tonic-gate 
107c478bd9Sstevel@tonic-gate #if defined(KERNEL) || defined(_KERNEL)
117c478bd9Sstevel@tonic-gate # undef KERNEL
127c478bd9Sstevel@tonic-gate # undef _KERNEL
137c478bd9Sstevel@tonic-gate # define        KERNEL	1
147c478bd9Sstevel@tonic-gate # define        _KERNEL	1
157c478bd9Sstevel@tonic-gate #endif
167c478bd9Sstevel@tonic-gate #include <sys/errno.h>
177c478bd9Sstevel@tonic-gate #include <sys/types.h>
187c478bd9Sstevel@tonic-gate #include <sys/param.h>
197c478bd9Sstevel@tonic-gate #include <sys/time.h>
207c478bd9Sstevel@tonic-gate #include <sys/file.h>
217c478bd9Sstevel@tonic-gate #ifdef __hpux
227c478bd9Sstevel@tonic-gate # include <sys/timeout.h>
237c478bd9Sstevel@tonic-gate #endif
247c478bd9Sstevel@tonic-gate #if !defined(_KERNEL)
257c478bd9Sstevel@tonic-gate # include <stdio.h>
267c478bd9Sstevel@tonic-gate # include <string.h>
277c478bd9Sstevel@tonic-gate # include <stdlib.h>
287c478bd9Sstevel@tonic-gate # define _KERNEL
297c478bd9Sstevel@tonic-gate # ifdef __OpenBSD__
307c478bd9Sstevel@tonic-gate struct file;
317c478bd9Sstevel@tonic-gate # endif
327c478bd9Sstevel@tonic-gate # include <sys/uio.h>
337c478bd9Sstevel@tonic-gate # undef _KERNEL
347c478bd9Sstevel@tonic-gate #endif
357c478bd9Sstevel@tonic-gate #if defined(_KERNEL) && (__FreeBSD_version >= 220000)
367c478bd9Sstevel@tonic-gate # include <sys/filio.h>
377c478bd9Sstevel@tonic-gate # include <sys/fcntl.h>
387c478bd9Sstevel@tonic-gate #else
397c478bd9Sstevel@tonic-gate # include <sys/ioctl.h>
407c478bd9Sstevel@tonic-gate #endif
41ab25eeb5Syz #if !defined(linux)
42ab25eeb5Syz # include <sys/protosw.h>
43ab25eeb5Syz #endif
447c478bd9Sstevel@tonic-gate #include <sys/socket.h>
457c478bd9Sstevel@tonic-gate #if defined(_KERNEL)
467c478bd9Sstevel@tonic-gate # include <sys/systm.h>
477c478bd9Sstevel@tonic-gate # if !defined(__SVR4) && !defined(__svr4__)
487c478bd9Sstevel@tonic-gate #  include <sys/mbuf.h>
497c478bd9Sstevel@tonic-gate # endif
507c478bd9Sstevel@tonic-gate #endif
517c478bd9Sstevel@tonic-gate #if !defined(__SVR4) && !defined(__svr4__)
52ab25eeb5Syz # if defined(_KERNEL) && !defined(__sgi) && !defined(AIX)
537c478bd9Sstevel@tonic-gate #  include <sys/kernel.h>
547c478bd9Sstevel@tonic-gate # endif
557c478bd9Sstevel@tonic-gate #else
567c478bd9Sstevel@tonic-gate # include <sys/byteorder.h>
577c478bd9Sstevel@tonic-gate # ifdef _KERNEL
587c478bd9Sstevel@tonic-gate #  include <sys/dditypes.h>
597c478bd9Sstevel@tonic-gate # endif
607c478bd9Sstevel@tonic-gate # include <sys/stream.h>
617c478bd9Sstevel@tonic-gate # include <sys/kmem.h>
627c478bd9Sstevel@tonic-gate #endif
637c478bd9Sstevel@tonic-gate #include <net/if.h>
647c478bd9Sstevel@tonic-gate #ifdef sun
657c478bd9Sstevel@tonic-gate # include <net/af.h>
667c478bd9Sstevel@tonic-gate #endif
677c478bd9Sstevel@tonic-gate #include <net/route.h>
687c478bd9Sstevel@tonic-gate #include <netinet/in.h>
697c478bd9Sstevel@tonic-gate #include <netinet/in_systm.h>
707c478bd9Sstevel@tonic-gate #include <netinet/ip.h>
71ab25eeb5Syz #if !defined(linux)
72ab25eeb5Syz # include <netinet/ip_var.h>
73ab25eeb5Syz #endif
747c478bd9Sstevel@tonic-gate #include <netinet/tcp.h>
757c478bd9Sstevel@tonic-gate #include <netinet/udp.h>
767c478bd9Sstevel@tonic-gate #include <netinet/ip_icmp.h>
777c478bd9Sstevel@tonic-gate #include "netinet/ip_compat.h"
78ab25eeb5Syz #include <netinet/tcpip.h>
797c478bd9Sstevel@tonic-gate #include "netinet/ip_fil.h"
807c478bd9Sstevel@tonic-gate #include "netinet/ip_nat.h"
817c478bd9Sstevel@tonic-gate #include "netinet/ip_frag.h"
827c478bd9Sstevel@tonic-gate #include "netinet/ip_state.h"
837c478bd9Sstevel@tonic-gate #include "netinet/ip_auth.h"
84f4b3ec61Sdh #include "netinet/ipf_stack.h"
857c478bd9Sstevel@tonic-gate #if (__FreeBSD_version >= 300000)
867c478bd9Sstevel@tonic-gate # include <sys/malloc.h>
877c478bd9Sstevel@tonic-gate # if defined(_KERNEL)
887c478bd9Sstevel@tonic-gate #  ifndef IPFILTER_LKM
897c478bd9Sstevel@tonic-gate #   include <sys/libkern.h>
907c478bd9Sstevel@tonic-gate #   include <sys/systm.h>
917c478bd9Sstevel@tonic-gate #  endif
927c478bd9Sstevel@tonic-gate extern struct callout_handle fr_slowtimer_ch;
937c478bd9Sstevel@tonic-gate # endif
947c478bd9Sstevel@tonic-gate #endif
957c478bd9Sstevel@tonic-gate #if defined(__NetBSD__) && (__NetBSD_Version__ >= 104230000)
967c478bd9Sstevel@tonic-gate # include <sys/callout.h>
977c478bd9Sstevel@tonic-gate extern struct callout fr_slowtimer_ch;
987c478bd9Sstevel@tonic-gate #endif
997c478bd9Sstevel@tonic-gate #if defined(__OpenBSD__)
1007c478bd9Sstevel@tonic-gate # include <sys/timeout.h>
1017c478bd9Sstevel@tonic-gate extern struct timeout fr_slowtimer_ch;
1027c478bd9Sstevel@tonic-gate #endif
103ab25eeb5Syz /* END OF INCLUDES */
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate #if !defined(lint)
1067c478bd9Sstevel@tonic-gate static const char sccsid[] = "@(#)ip_frag.c	1.11 3/24/96 (C) 1993-2000 Darren Reed";
107ab25eeb5Syz static const char rcsid[] = "@(#)$Id: ip_frag.c,v 2.77.2.5 2005/08/11 14:33:10 darrenr Exp $";
1087c478bd9Sstevel@tonic-gate #endif
1097c478bd9Sstevel@tonic-gate 
11072680cf5SDarren Reed static INLINE int ipfr_index __P((fr_info_t *, ipfr_t *));
1117c478bd9Sstevel@tonic-gate static ipfr_t *ipfr_newfrag __P((fr_info_t *, u_32_t, ipfr_t **));
1127c478bd9Sstevel@tonic-gate static ipfr_t *fr_fraglookup __P((fr_info_t *, ipfr_t **));
113f4b3ec61Sdh static void fr_fragdelete __P((ipfr_t *, ipfr_t ***, ipf_stack_t *));
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
1167c478bd9Sstevel@tonic-gate /* Function:    fr_fraginit                                                 */
1177c478bd9Sstevel@tonic-gate /* Returns:     int - 0 == success, -1 == error                             */
1187c478bd9Sstevel@tonic-gate /* Parameters:  Nil                                                         */
1197c478bd9Sstevel@tonic-gate /*                                                                          */
1207c478bd9Sstevel@tonic-gate /* Initialise the hash tables for the fragment cache lookups.               */
1217c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
fr_fraginit(ifs)122f4b3ec61Sdh int fr_fraginit(ifs)
123f4b3ec61Sdh ipf_stack_t *ifs;
1247c478bd9Sstevel@tonic-gate {
125f4b3ec61Sdh 	ifs->ifs_ipfr_tail = &ifs->ifs_ipfr_list;
126f4b3ec61Sdh 	ifs->ifs_ipfr_nattail = &ifs->ifs_ipfr_natlist;
127f4b3ec61Sdh 	ifs->ifs_ipfr_ipidtail = &ifs->ifs_ipfr_ipidlist;
1288128a42dSan 	/* the IP frag related variables are set in ipftuneable_setdefs() to
1298128a42dSan 	 * their default values
1308128a42dSan 	 */
131f4b3ec61Sdh 
132f4b3ec61Sdh 	KMALLOCS(ifs->ifs_ipfr_heads, ipfr_t **,
133f4b3ec61Sdh 	    ifs->ifs_ipfr_size * sizeof(ipfr_t *));
134f4b3ec61Sdh 	if (ifs->ifs_ipfr_heads == NULL)
1357c478bd9Sstevel@tonic-gate 		return -1;
136f4b3ec61Sdh 	bzero((char *)ifs->ifs_ipfr_heads,
137f4b3ec61Sdh 	    ifs->ifs_ipfr_size * sizeof(ipfr_t *));
1387c478bd9Sstevel@tonic-gate 
139f4b3ec61Sdh 	KMALLOCS(ifs->ifs_ipfr_nattab, ipfr_t **,
140f4b3ec61Sdh 	    ifs->ifs_ipfr_size * sizeof(ipfr_t *));
141f4b3ec61Sdh 	if (ifs->ifs_ipfr_nattab == NULL)
1427c478bd9Sstevel@tonic-gate 		return -1;
143f4b3ec61Sdh 	bzero((char *)ifs->ifs_ipfr_nattab,
144f4b3ec61Sdh 	    ifs->ifs_ipfr_size * sizeof(ipfr_t *));
1457c478bd9Sstevel@tonic-gate 
146f4b3ec61Sdh 	KMALLOCS(ifs->ifs_ipfr_ipidtab, ipfr_t **,
147f4b3ec61Sdh 	    ifs->ifs_ipfr_size * sizeof(ipfr_t *));
148f4b3ec61Sdh 	if (ifs->ifs_ipfr_ipidtab == NULL)
1497c478bd9Sstevel@tonic-gate 		return -1;
150f4b3ec61Sdh 	bzero((char *)ifs->ifs_ipfr_ipidtab,
151f4b3ec61Sdh 	    ifs->ifs_ipfr_size * sizeof(ipfr_t *));
1527c478bd9Sstevel@tonic-gate 
153f4b3ec61Sdh 	RWLOCK_INIT(&ifs->ifs_ipf_frag, "ipf fragment rwlock");
1547663b816Sml 
1557663b816Sml 	/* Initialise frblock with "block in all" */
156f4b3ec61Sdh 	bzero((char *)&ifs->ifs_frblock, sizeof(ifs->ifs_frblock));
157f4b3ec61Sdh 	ifs->ifs_frblock.fr_flags = FR_BLOCK|FR_INQUE;	/* block in */
158f4b3ec61Sdh 	ifs->ifs_frblock.fr_ref = 1;
1597663b816Sml 
160f4b3ec61Sdh 	ifs->ifs_fr_frag_init = 1;
1617c478bd9Sstevel@tonic-gate 
1627c478bd9Sstevel@tonic-gate 	return 0;
1637c478bd9Sstevel@tonic-gate }
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
1677c478bd9Sstevel@tonic-gate /* Function:    fr_fragunload                                               */
1687c478bd9Sstevel@tonic-gate /* Returns:     Nil                                                         */
1697c478bd9Sstevel@tonic-gate /* Parameters:  Nil                                                         */
1707c478bd9Sstevel@tonic-gate /*                                                                          */
1717c478bd9Sstevel@tonic-gate /* Free all memory allocated whilst running and from initialisation.        */
1727c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
fr_fragunload(ifs)173f4b3ec61Sdh void fr_fragunload(ifs)
174f4b3ec61Sdh ipf_stack_t *ifs;
1757c478bd9Sstevel@tonic-gate {
176f4b3ec61Sdh 	if (ifs->ifs_fr_frag_init == 1) {
177f4b3ec61Sdh 		fr_fragclear(ifs);
1787c478bd9Sstevel@tonic-gate 
179f4b3ec61Sdh 		RW_DESTROY(&ifs->ifs_ipf_frag);
180f4b3ec61Sdh 		ifs->ifs_fr_frag_init = 0;
1817c478bd9Sstevel@tonic-gate 	}
1827c478bd9Sstevel@tonic-gate 
183f4b3ec61Sdh 	if (ifs->ifs_ipfr_heads != NULL) {
184f4b3ec61Sdh 		KFREES(ifs->ifs_ipfr_heads,
185f4b3ec61Sdh 		    ifs->ifs_ipfr_size * sizeof(ipfr_t *));
186f4b3ec61Sdh 	}
187f4b3ec61Sdh 	ifs->ifs_ipfr_heads = NULL;
1887c478bd9Sstevel@tonic-gate 
189f4b3ec61Sdh 	if (ifs->ifs_ipfr_nattab != NULL) {
190f4b3ec61Sdh 		KFREES(ifs->ifs_ipfr_nattab,
191f4b3ec61Sdh 		    ifs->ifs_ipfr_size * sizeof(ipfr_t *));
192f4b3ec61Sdh 	}
193f4b3ec61Sdh 	ifs->ifs_ipfr_nattab = NULL;
1947c478bd9Sstevel@tonic-gate 
195f4b3ec61Sdh 	if (ifs->ifs_ipfr_ipidtab != NULL) {
196f4b3ec61Sdh 		KFREES(ifs->ifs_ipfr_ipidtab,
197f4b3ec61Sdh 		    ifs->ifs_ipfr_size * sizeof(ipfr_t *));
198f4b3ec61Sdh 	}
199f4b3ec61Sdh 	ifs->ifs_ipfr_ipidtab = NULL;
2007c478bd9Sstevel@tonic-gate }
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate 
2037c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
2047c478bd9Sstevel@tonic-gate /* Function:    fr_fragstats                                                */
205ab25eeb5Syz /* Returns:     ipfrstat_t* - pointer to struct with current frag stats     */
2067c478bd9Sstevel@tonic-gate /* Parameters:  Nil                                                         */
2077c478bd9Sstevel@tonic-gate /*                                                                          */
2087c478bd9Sstevel@tonic-gate /* Updates ipfr_stats with current information and returns a pointer to it  */
2097c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
fr_fragstats(ifs)210f4b3ec61Sdh ipfrstat_t *fr_fragstats(ifs)
211f4b3ec61Sdh ipf_stack_t *ifs;
2127c478bd9Sstevel@tonic-gate {
213f4b3ec61Sdh 	ifs->ifs_ipfr_stats.ifs_table = ifs->ifs_ipfr_heads;
214f4b3ec61Sdh 	ifs->ifs_ipfr_stats.ifs_nattab = ifs->ifs_ipfr_nattab;
215f4b3ec61Sdh 	ifs->ifs_ipfr_stats.ifs_inuse = ifs->ifs_ipfr_inuse;
216f4b3ec61Sdh 	return &ifs->ifs_ipfr_stats;
2177c478bd9Sstevel@tonic-gate }
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 
22072680cf5SDarren Reed /* ------------------------------------------------------------------------ */
22172680cf5SDarren Reed /* Function:    ipfr_index                                                  */
22272680cf5SDarren Reed /* Returns:     int     - index in fragment table for given packet          */
22372680cf5SDarren Reed /* Parameters:  fin(I)  - pointer to packet information                     */
22472680cf5SDarren Reed /*              frag(O) - pointer to ipfr_t structure to fill               */
22572680cf5SDarren Reed /*                                                                          */
22672680cf5SDarren Reed /* Compute the index in the fragment table while filling the per packet     */
22772680cf5SDarren Reed /* part of the fragment state.                                              */
22872680cf5SDarren Reed /* ------------------------------------------------------------------------ */
ipfr_index(fin,frag)22972680cf5SDarren Reed static INLINE int ipfr_index(fin, frag)
23072680cf5SDarren Reed fr_info_t *fin;
23172680cf5SDarren Reed ipfr_t *frag;
23272680cf5SDarren Reed {
23372680cf5SDarren Reed 	u_int idx;
23472680cf5SDarren Reed 
23572680cf5SDarren Reed 	/*
23672680cf5SDarren Reed 	 * For fragments, we record protocol, packet id, TOS and both IP#'s
23772680cf5SDarren Reed 	 * (these should all be the same for all fragments of a packet).
23872680cf5SDarren Reed 	 *
23972680cf5SDarren Reed 	 * build up a hash value to index the table with.
24072680cf5SDarren Reed 	 */
24172680cf5SDarren Reed 
24272680cf5SDarren Reed #ifdef	USE_INET6
24372680cf5SDarren Reed 	if (fin->fin_v == 6) {
24472680cf5SDarren Reed 		ip6_t *ip6 = (ip6_t *)fin->fin_ip;
24572680cf5SDarren Reed 
24672680cf5SDarren Reed 		frag->ipfr_p = fin->fin_fi.fi_p;
24772680cf5SDarren Reed 		frag->ipfr_id = fin->fin_id;
24872680cf5SDarren Reed 		frag->ipfr_tos = ip6->ip6_flow & IPV6_FLOWINFO_MASK;
24972680cf5SDarren Reed 		frag->ipfr_src.in6 = ip6->ip6_src;
25072680cf5SDarren Reed 		frag->ipfr_dst.in6 = ip6->ip6_dst;
25172680cf5SDarren Reed 	} else
25272680cf5SDarren Reed #endif
25372680cf5SDarren Reed 	{
25472680cf5SDarren Reed 		ip_t *ip = fin->fin_ip;
25572680cf5SDarren Reed 
25672680cf5SDarren Reed 		frag->ipfr_p = ip->ip_p;
25772680cf5SDarren Reed 		frag->ipfr_id = ip->ip_id;
25872680cf5SDarren Reed 		frag->ipfr_tos = ip->ip_tos;
25972680cf5SDarren Reed 		frag->ipfr_src.in4.s_addr = ip->ip_src.s_addr;
26072680cf5SDarren Reed 		frag->ipfr_src.i6[1] = 0;
26172680cf5SDarren Reed 		frag->ipfr_src.i6[2] = 0;
26272680cf5SDarren Reed 		frag->ipfr_src.i6[3] = 0;
26372680cf5SDarren Reed 		frag->ipfr_dst.in4.s_addr = ip->ip_dst.s_addr;
26472680cf5SDarren Reed 		frag->ipfr_dst.i6[1] = 0;
26572680cf5SDarren Reed 		frag->ipfr_dst.i6[2] = 0;
26672680cf5SDarren Reed 		frag->ipfr_dst.i6[3] = 0;
26772680cf5SDarren Reed 	}
26872680cf5SDarren Reed 	frag->ipfr_ifp = fin->fin_ifp;
26972680cf5SDarren Reed 	frag->ipfr_optmsk = fin->fin_fi.fi_optmsk & IPF_OPTCOPY;
27072680cf5SDarren Reed 	frag->ipfr_secmsk = fin->fin_fi.fi_secmsk;
27172680cf5SDarren Reed 	frag->ipfr_auth = fin->fin_fi.fi_auth;
27272680cf5SDarren Reed 
27372680cf5SDarren Reed 	idx = frag->ipfr_p;
27472680cf5SDarren Reed 	idx += frag->ipfr_id;
27572680cf5SDarren Reed 	idx += frag->ipfr_src.i6[0];
27672680cf5SDarren Reed 	idx += frag->ipfr_src.i6[1];
27772680cf5SDarren Reed 	idx += frag->ipfr_src.i6[2];
27872680cf5SDarren Reed 	idx += frag->ipfr_src.i6[3];
27972680cf5SDarren Reed 	idx += frag->ipfr_dst.i6[0];
28072680cf5SDarren Reed 	idx += frag->ipfr_dst.i6[1];
28172680cf5SDarren Reed 	idx += frag->ipfr_dst.i6[2];
28272680cf5SDarren Reed 	idx += frag->ipfr_dst.i6[3];
28372680cf5SDarren Reed 	idx *= 127;
28472680cf5SDarren Reed 	idx %= IPFT_SIZE;
28572680cf5SDarren Reed 
28672680cf5SDarren Reed 	return idx;
28772680cf5SDarren Reed }
28872680cf5SDarren Reed 
28972680cf5SDarren Reed 
2907c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
2917c478bd9Sstevel@tonic-gate /* Function:    ipfr_newfrag                                                */
2927c478bd9Sstevel@tonic-gate /* Returns:     ipfr_t * - pointer to fragment cache state info or NULL     */
2937c478bd9Sstevel@tonic-gate /* Parameters:  fin(I)   - pointer to packet information                    */
2947c478bd9Sstevel@tonic-gate /*              table(I) - pointer to frag table to add to                  */
2957c478bd9Sstevel@tonic-gate /*                                                                          */
2967c478bd9Sstevel@tonic-gate /* Add a new entry to the fragment cache, registering it as having come     */
2977c478bd9Sstevel@tonic-gate /* through this box, with the result of the filter operation.               */
2987c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
ipfr_newfrag(fin,pass,table)2997c478bd9Sstevel@tonic-gate static ipfr_t *ipfr_newfrag(fin, pass, table)
3007c478bd9Sstevel@tonic-gate fr_info_t *fin;
3017c478bd9Sstevel@tonic-gate u_32_t pass;
3027c478bd9Sstevel@tonic-gate ipfr_t *table[];
3037c478bd9Sstevel@tonic-gate {
3047c478bd9Sstevel@tonic-gate 	ipfr_t *fra, frag;
3057c478bd9Sstevel@tonic-gate 	u_int idx, off;
306f4b3ec61Sdh 	ipf_stack_t *ifs = fin->fin_ifs;
3077c478bd9Sstevel@tonic-gate 
308bd5ba10fSan 	if (ifs->ifs_ipfr_inuse >= ifs->ifs_ipfr_size)
3097c478bd9Sstevel@tonic-gate 		return NULL;
3107c478bd9Sstevel@tonic-gate 
3117c478bd9Sstevel@tonic-gate 	if ((fin->fin_flx & (FI_FRAG|FI_BAD)) != FI_FRAG)
3127c478bd9Sstevel@tonic-gate 		return NULL;
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 	if (pass & FR_FRSTRICT)
3157663b816Sml 		if (fin->fin_off != 0)
3167c478bd9Sstevel@tonic-gate 			return NULL;
3177c478bd9Sstevel@tonic-gate 
31872680cf5SDarren Reed 	idx = ipfr_index(fin, &frag);
3197c478bd9Sstevel@tonic-gate 
3207c478bd9Sstevel@tonic-gate 	/*
3217c478bd9Sstevel@tonic-gate 	 * first, make sure it isn't already there...
3227c478bd9Sstevel@tonic-gate 	 */
3237c478bd9Sstevel@tonic-gate 	for (fra = table[idx]; (fra != NULL); fra = fra->ipfr_hnext)
3247c478bd9Sstevel@tonic-gate 		if (!bcmp((char *)&frag.ipfr_ifp, (char *)&fra->ipfr_ifp,
3257c478bd9Sstevel@tonic-gate 			  IPFR_CMPSZ)) {
326f4b3ec61Sdh 			ifs->ifs_ipfr_stats.ifs_exists++;
3277c478bd9Sstevel@tonic-gate 			return NULL;
3287c478bd9Sstevel@tonic-gate 		}
3297c478bd9Sstevel@tonic-gate 
3307c478bd9Sstevel@tonic-gate 	/*
3317c478bd9Sstevel@tonic-gate 	 * allocate some memory, if possible, if not, just record that we
3327c478bd9Sstevel@tonic-gate 	 * failed to do so.
3337c478bd9Sstevel@tonic-gate 	 */
3347c478bd9Sstevel@tonic-gate 	KMALLOC(fra, ipfr_t *);
3357c478bd9Sstevel@tonic-gate 	if (fra == NULL) {
336f4b3ec61Sdh 		ifs->ifs_ipfr_stats.ifs_nomem++;
3377c478bd9Sstevel@tonic-gate 		return NULL;
3387c478bd9Sstevel@tonic-gate 	}
3397c478bd9Sstevel@tonic-gate 
340ab25eeb5Syz 	fra->ipfr_rule = fin->fin_fr;
341ab25eeb5Syz 	if (fra->ipfr_rule != NULL) {
342ab25eeb5Syz 
343ab25eeb5Syz 		frentry_t *fr;
344ab25eeb5Syz 
345ab25eeb5Syz 		fr = fin->fin_fr;
346ab25eeb5Syz 		MUTEX_ENTER(&fr->fr_lock);
347ab25eeb5Syz 		fr->fr_ref++;
348ab25eeb5Syz 		MUTEX_EXIT(&fr->fr_lock);
3497663b816Sml 	}
3507c478bd9Sstevel@tonic-gate 
3517c478bd9Sstevel@tonic-gate 	/*
3527c478bd9Sstevel@tonic-gate 	 * Insert the fragment into the fragment table, copy the struct used
3537c478bd9Sstevel@tonic-gate 	 * in the search using bcopy rather than reassign each field.
3547c478bd9Sstevel@tonic-gate 	 * Set the ttl to the default.
3557c478bd9Sstevel@tonic-gate 	 */
3567c478bd9Sstevel@tonic-gate 	if ((fra->ipfr_hnext = table[idx]) != NULL)
3577c478bd9Sstevel@tonic-gate 		table[idx]->ipfr_hprev = &fra->ipfr_hnext;
3587c478bd9Sstevel@tonic-gate 	fra->ipfr_hprev = table + idx;
3597c478bd9Sstevel@tonic-gate 	fra->ipfr_data = NULL;
3607c478bd9Sstevel@tonic-gate 	table[idx] = fra;
3617c478bd9Sstevel@tonic-gate 	bcopy((char *)&frag.ipfr_ifp, (char *)&fra->ipfr_ifp, IPFR_CMPSZ);
362f4b3ec61Sdh 	fra->ipfr_ttl = ifs->ifs_fr_ticks + ifs->ifs_fr_ipfrttl;
3637c478bd9Sstevel@tonic-gate 
3647c478bd9Sstevel@tonic-gate 	/*
3657c478bd9Sstevel@tonic-gate 	 * Compute the offset of the expected start of the next packet.
3667c478bd9Sstevel@tonic-gate 	 */
36772680cf5SDarren Reed 	off = fin->fin_off >> 3;
3687663b816Sml 	if (off == 0) {
3697c478bd9Sstevel@tonic-gate 		fra->ipfr_seen0 = 1;
3707663b816Sml 	} else {
3717663b816Sml 		fra->ipfr_seen0 = 0;
3727663b816Sml 	}
373ab25eeb5Syz 	fra->ipfr_off = off + fin->fin_dlen;
3747c478bd9Sstevel@tonic-gate 	fra->ipfr_pass = pass;
375f4b3ec61Sdh 	fra->ipfr_ref = 1;
376f4b3ec61Sdh 	ifs->ifs_ipfr_stats.ifs_new++;
377f4b3ec61Sdh 	ifs->ifs_ipfr_inuse++;
3787c478bd9Sstevel@tonic-gate 	return fra;
3797c478bd9Sstevel@tonic-gate }
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
3837c478bd9Sstevel@tonic-gate /* Function:    fr_newfrag                                                  */
3847c478bd9Sstevel@tonic-gate /* Returns:     int - 0 == success, -1 == error                             */
3857c478bd9Sstevel@tonic-gate /* Parameters:  fin(I)  - pointer to packet information                     */
3867c478bd9Sstevel@tonic-gate /*                                                                          */
3877c478bd9Sstevel@tonic-gate /* Add a new entry to the fragment cache table based on the current packet  */
3887c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
fr_newfrag(fin,pass)3897c478bd9Sstevel@tonic-gate int fr_newfrag(fin, pass)
3907c478bd9Sstevel@tonic-gate u_32_t pass;
3917c478bd9Sstevel@tonic-gate fr_info_t *fin;
3927c478bd9Sstevel@tonic-gate {
3937c478bd9Sstevel@tonic-gate 	ipfr_t	*fra;
394f4b3ec61Sdh 	ipf_stack_t *ifs = fin->fin_ifs;
3957c478bd9Sstevel@tonic-gate 
396f4b3ec61Sdh 	if (ifs->ifs_fr_frag_lock != 0)
397ab25eeb5Syz 		return -1;
3987c478bd9Sstevel@tonic-gate 
399f4b3ec61Sdh 	WRITE_ENTER(&ifs->ifs_ipf_frag);
400f4b3ec61Sdh 	fra = ipfr_newfrag(fin, pass, ifs->ifs_ipfr_heads);
4017c478bd9Sstevel@tonic-gate 	if (fra != NULL) {
402f4b3ec61Sdh 		*ifs->ifs_ipfr_tail = fra;
403f4b3ec61Sdh 		fra->ipfr_prev = ifs->ifs_ipfr_tail;
404f4b3ec61Sdh 		ifs->ifs_ipfr_tail = &fra->ipfr_next;
405f4b3ec61Sdh 		if (ifs->ifs_ipfr_list == NULL)
406f4b3ec61Sdh 			ifs->ifs_ipfr_list = fra;
4077c478bd9Sstevel@tonic-gate 		fra->ipfr_next = NULL;
4087c478bd9Sstevel@tonic-gate 	}
409f4b3ec61Sdh 	RWLOCK_EXIT(&ifs->ifs_ipf_frag);
4107c478bd9Sstevel@tonic-gate 	return fra ? 0 : -1;
4117c478bd9Sstevel@tonic-gate }
4127c478bd9Sstevel@tonic-gate 
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
4157c478bd9Sstevel@tonic-gate /* Function:    fr_nat_newfrag                                              */
4167c478bd9Sstevel@tonic-gate /* Returns:     int - 0 == success, -1 == error                             */
4177c478bd9Sstevel@tonic-gate /* Parameters:  fin(I)  - pointer to packet information                     */
4187c478bd9Sstevel@tonic-gate /*              nat(I)  - pointer to NAT structure                          */
4197c478bd9Sstevel@tonic-gate /*                                                                          */
4207c478bd9Sstevel@tonic-gate /* Create a new NAT fragment cache entry based on the current packet and    */
4217c478bd9Sstevel@tonic-gate /* the NAT structure for this "session".                                    */
4227c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
fr_nat_newfrag(fin,pass,nat)4237c478bd9Sstevel@tonic-gate int fr_nat_newfrag(fin, pass, nat)
4247c478bd9Sstevel@tonic-gate fr_info_t *fin;
4257c478bd9Sstevel@tonic-gate u_32_t pass;
4267c478bd9Sstevel@tonic-gate nat_t *nat;
4277c478bd9Sstevel@tonic-gate {
4287c478bd9Sstevel@tonic-gate 	ipfr_t	*fra;
429f4b3ec61Sdh 	ipf_stack_t *ifs = fin->fin_ifs;
4307c478bd9Sstevel@tonic-gate 
43172680cf5SDarren Reed 	if (ifs->ifs_fr_frag_lock != 0)
4327c478bd9Sstevel@tonic-gate 		return 0;
4337c478bd9Sstevel@tonic-gate 
434f4b3ec61Sdh 	WRITE_ENTER(&ifs->ifs_ipf_natfrag);
435f4b3ec61Sdh 	fra = ipfr_newfrag(fin, pass, ifs->ifs_ipfr_nattab);
4367c478bd9Sstevel@tonic-gate 	if (fra != NULL) {
4377c478bd9Sstevel@tonic-gate 		fra->ipfr_data = nat;
4387c478bd9Sstevel@tonic-gate 		nat->nat_data = fra;
439f4b3ec61Sdh 		*ifs->ifs_ipfr_nattail = fra;
440f4b3ec61Sdh 		fra->ipfr_prev = ifs->ifs_ipfr_nattail;
441f4b3ec61Sdh 		ifs->ifs_ipfr_nattail = &fra->ipfr_next;
4427c478bd9Sstevel@tonic-gate 		fra->ipfr_next = NULL;
4437c478bd9Sstevel@tonic-gate 	}
444f4b3ec61Sdh 	RWLOCK_EXIT(&ifs->ifs_ipf_natfrag);
4457c478bd9Sstevel@tonic-gate 	return fra ? 0 : -1;
4467c478bd9Sstevel@tonic-gate }
4477c478bd9Sstevel@tonic-gate 
4487c478bd9Sstevel@tonic-gate 
4497c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
4507c478bd9Sstevel@tonic-gate /* Function:    fr_ipid_newfrag                                             */
4517c478bd9Sstevel@tonic-gate /* Returns:     int - 0 == success, -1 == error                             */
4527c478bd9Sstevel@tonic-gate /* Parameters:  fin(I)  - pointer to packet information                     */
4537c478bd9Sstevel@tonic-gate /*              ipid(I) - new IP ID for this fragmented packet              */
4547c478bd9Sstevel@tonic-gate /*                                                                          */
4557c478bd9Sstevel@tonic-gate /* Create a new fragment cache entry for this packet and store, as a data   */
4567c478bd9Sstevel@tonic-gate /* pointer, the new IP ID value.                                            */
4577c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
fr_ipid_newfrag(fin,ipid)4587c478bd9Sstevel@tonic-gate int fr_ipid_newfrag(fin, ipid)
4597c478bd9Sstevel@tonic-gate fr_info_t *fin;
4607c478bd9Sstevel@tonic-gate u_32_t ipid;
4617c478bd9Sstevel@tonic-gate {
4627c478bd9Sstevel@tonic-gate 	ipfr_t	*fra;
463f4b3ec61Sdh 	ipf_stack_t *ifs = fin->fin_ifs;
4647c478bd9Sstevel@tonic-gate 
465f4b3ec61Sdh 	if (ifs->ifs_fr_frag_lock)
4667c478bd9Sstevel@tonic-gate 		return 0;
4677c478bd9Sstevel@tonic-gate 
468f4b3ec61Sdh 	WRITE_ENTER(&ifs->ifs_ipf_ipidfrag);
469f4b3ec61Sdh 	fra = ipfr_newfrag(fin, 0, ifs->ifs_ipfr_ipidtab);
4707c478bd9Sstevel@tonic-gate 	if (fra != NULL) {
4717c478bd9Sstevel@tonic-gate 		fra->ipfr_data = (void *)(uintptr_t)ipid;
472f4b3ec61Sdh 		*ifs->ifs_ipfr_ipidtail = fra;
473f4b3ec61Sdh 		fra->ipfr_prev = ifs->ifs_ipfr_ipidtail;
474f4b3ec61Sdh 		ifs->ifs_ipfr_ipidtail = &fra->ipfr_next;
4757c478bd9Sstevel@tonic-gate 		fra->ipfr_next = NULL;
4767c478bd9Sstevel@tonic-gate 	}
477f4b3ec61Sdh 	RWLOCK_EXIT(&ifs->ifs_ipf_ipidfrag);
4787c478bd9Sstevel@tonic-gate 	return fra ? 0 : -1;
4797c478bd9Sstevel@tonic-gate }
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 
4827c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
4837c478bd9Sstevel@tonic-gate /* Function:    fr_fraglookup                                               */
4847c478bd9Sstevel@tonic-gate /* Returns:     ipfr_t * - pointer to ipfr_t structure if there's a         */
4857c478bd9Sstevel@tonic-gate /*                         matching entry in the frag table, else NULL      */
4867c478bd9Sstevel@tonic-gate /* Parameters:  fin(I)   - pointer to packet information                    */
4877c478bd9Sstevel@tonic-gate /*              table(I) - pointer to fragment cache table to search        */
4887c478bd9Sstevel@tonic-gate /*                                                                          */
4897c478bd9Sstevel@tonic-gate /* Check the fragment cache to see if there is already a record of this     */
4907c478bd9Sstevel@tonic-gate /* packet with its filter result known.                                     */
4917c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
fr_fraglookup(fin,table)4927c478bd9Sstevel@tonic-gate static ipfr_t *fr_fraglookup(fin, table)
4937c478bd9Sstevel@tonic-gate fr_info_t *fin;
4947c478bd9Sstevel@tonic-gate ipfr_t *table[];
4957c478bd9Sstevel@tonic-gate {
4967c478bd9Sstevel@tonic-gate 	ipfr_t *f, frag;
4977c478bd9Sstevel@tonic-gate 	u_int idx;
498f4b3ec61Sdh 	ipf_stack_t *ifs = fin->fin_ifs;
4997c478bd9Sstevel@tonic-gate 
5007c478bd9Sstevel@tonic-gate 	if ((fin->fin_flx & (FI_FRAG|FI_BAD)) != FI_FRAG)
5017c478bd9Sstevel@tonic-gate 		return NULL;
5027c478bd9Sstevel@tonic-gate 
5037c478bd9Sstevel@tonic-gate 	/*
5047c478bd9Sstevel@tonic-gate 	 * For fragments, we record protocol, packet id, TOS and both IP#'s
5057c478bd9Sstevel@tonic-gate 	 * (these should all be the same for all fragments of a packet).
5067c478bd9Sstevel@tonic-gate 	 *
5077c478bd9Sstevel@tonic-gate 	 * build up a hash value to index the table with.
5087c478bd9Sstevel@tonic-gate 	 */
50972680cf5SDarren Reed 	idx = ipfr_index(fin, &frag);
5107c478bd9Sstevel@tonic-gate 
5117c478bd9Sstevel@tonic-gate 	/*
5127c478bd9Sstevel@tonic-gate 	 * check the table, careful to only compare the right amount of data
5137c478bd9Sstevel@tonic-gate 	 */
5147c478bd9Sstevel@tonic-gate 	for (f = table[idx]; f; f = f->ipfr_hnext)
5157c478bd9Sstevel@tonic-gate 		if (!bcmp((char *)&frag.ipfr_ifp, (char *)&f->ipfr_ifp,
5167c478bd9Sstevel@tonic-gate 			  IPFR_CMPSZ)) {
5177c478bd9Sstevel@tonic-gate 			u_short	off;
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 			/*
5207c478bd9Sstevel@tonic-gate 			 * We don't want to let short packets match because
5217c478bd9Sstevel@tonic-gate 			 * they could be compromising the security of other
5227c478bd9Sstevel@tonic-gate 			 * rules that want to match on layer 4 fields (and
5237c478bd9Sstevel@tonic-gate 			 * can't because they have been fragmented off.)
5247c478bd9Sstevel@tonic-gate 			 * Why do this check here?  The counter acts as an
5257c478bd9Sstevel@tonic-gate 			 * indicator of this kind of attack, whereas if it was
5267c478bd9Sstevel@tonic-gate 			 * elsewhere, it wouldn't know if other matching
5277c478bd9Sstevel@tonic-gate 			 * packets had been seen.
5287c478bd9Sstevel@tonic-gate 			 */
5297c478bd9Sstevel@tonic-gate 			if (fin->fin_flx & FI_SHORT) {
530f4b3ec61Sdh 				ATOMIC_INCL(ifs->ifs_ipfr_stats.ifs_short);
5317c478bd9Sstevel@tonic-gate 				continue;
5327c478bd9Sstevel@tonic-gate 			}
5337c478bd9Sstevel@tonic-gate 
5347c478bd9Sstevel@tonic-gate 			/*
5357c478bd9Sstevel@tonic-gate 			 * XXX - We really need to be guarding against the
5367c478bd9Sstevel@tonic-gate 			 * retransmission of (src,dst,id,offset-range) here
5377c478bd9Sstevel@tonic-gate 			 * because a fragmented packet is never resent with
5387c478bd9Sstevel@tonic-gate 			 * the same IP ID# (or shouldn't).
5397c478bd9Sstevel@tonic-gate 			 */
54072680cf5SDarren Reed 			off = fin->fin_off >> 3;
5417c478bd9Sstevel@tonic-gate 			if (f->ipfr_seen0) {
5427c478bd9Sstevel@tonic-gate 				if (off == 0) {
543f4b3ec61Sdh 					ATOMIC_INCL(ifs->ifs_ipfr_stats.ifs_retrans0);
5447c478bd9Sstevel@tonic-gate 					continue;
5457c478bd9Sstevel@tonic-gate 				}
5467663b816Sml 			} else if (off == 0) {
5477c478bd9Sstevel@tonic-gate 				f->ipfr_seen0 = 1;
5487663b816Sml 			}
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate 			if (f != table[idx]) {
5517c478bd9Sstevel@tonic-gate 				ipfr_t **fp;
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 				/*
5547c478bd9Sstevel@tonic-gate 				 * Move fragment info. to the top of the list
5557c478bd9Sstevel@tonic-gate 				 * to speed up searches.  First, delink...
5567c478bd9Sstevel@tonic-gate 				 */
5577c478bd9Sstevel@tonic-gate 				fp = f->ipfr_hprev;
5587c478bd9Sstevel@tonic-gate 				(*fp) = f->ipfr_hnext;
5597c478bd9Sstevel@tonic-gate 				if (f->ipfr_hnext != NULL)
5607c478bd9Sstevel@tonic-gate 					f->ipfr_hnext->ipfr_hprev = fp;
5617c478bd9Sstevel@tonic-gate 				/*
5627c478bd9Sstevel@tonic-gate 				 * Then put back at the top of the chain.
5637c478bd9Sstevel@tonic-gate 				 */
5647c478bd9Sstevel@tonic-gate 				f->ipfr_hnext = table[idx];
5657c478bd9Sstevel@tonic-gate 				table[idx]->ipfr_hprev = &f->ipfr_hnext;
5667c478bd9Sstevel@tonic-gate 				f->ipfr_hprev = table + idx;
5677c478bd9Sstevel@tonic-gate 				table[idx] = f;
5687c478bd9Sstevel@tonic-gate 			}
5697c478bd9Sstevel@tonic-gate 
5707c478bd9Sstevel@tonic-gate 			/*
5717c478bd9Sstevel@tonic-gate 			 * If we've follwed the fragments, and this is the
5727c478bd9Sstevel@tonic-gate 			 * last (in order), shrink expiration time.
5737c478bd9Sstevel@tonic-gate 			 */
5747c478bd9Sstevel@tonic-gate 			if (off == f->ipfr_off) {
57572680cf5SDarren Reed 				if (!(fin->fin_flx & FI_MOREFRAG))
576f4b3ec61Sdh 					f->ipfr_ttl = ifs->ifs_fr_ticks + 1;
577ab25eeb5Syz 				f->ipfr_off = fin->fin_dlen + off;
5787c478bd9Sstevel@tonic-gate 			} else if (f->ipfr_pass & FR_FRSTRICT)
5797c478bd9Sstevel@tonic-gate 				continue;
580f4b3ec61Sdh 			ATOMIC_INCL(ifs->ifs_ipfr_stats.ifs_hits);
5817c478bd9Sstevel@tonic-gate 			return f;
5827c478bd9Sstevel@tonic-gate 		}
5837c478bd9Sstevel@tonic-gate 	return NULL;
5847c478bd9Sstevel@tonic-gate }
5857c478bd9Sstevel@tonic-gate 
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
5887c478bd9Sstevel@tonic-gate /* Function:    fr_nat_knownfrag                                            */
5897c478bd9Sstevel@tonic-gate /* Returns:     nat_t* - pointer to 'parent' NAT structure if frag table    */
5907c478bd9Sstevel@tonic-gate /*                       match found, else NULL                             */
5917c478bd9Sstevel@tonic-gate /* Parameters:  fin(I)  - pointer to packet information                     */
5927c478bd9Sstevel@tonic-gate /*                                                                          */
5937c478bd9Sstevel@tonic-gate /* Functional interface for NAT lookups of the NAT fragment cache           */
5947c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
fr_nat_knownfrag(fin)5957c478bd9Sstevel@tonic-gate nat_t *fr_nat_knownfrag(fin)
5967c478bd9Sstevel@tonic-gate fr_info_t *fin;
5977c478bd9Sstevel@tonic-gate {
5987c478bd9Sstevel@tonic-gate 	nat_t	*nat;
5997c478bd9Sstevel@tonic-gate 	ipfr_t	*ipf;
600f4b3ec61Sdh 	ipf_stack_t *ifs = fin->fin_ifs;
6017c478bd9Sstevel@tonic-gate 
60272680cf5SDarren Reed 	if (ifs->ifs_fr_frag_lock || !ifs->ifs_ipfr_natlist)
6037c478bd9Sstevel@tonic-gate 		return NULL;
604f4b3ec61Sdh 	READ_ENTER(&ifs->ifs_ipf_natfrag);
605f4b3ec61Sdh 	ipf = fr_fraglookup(fin, ifs->ifs_ipfr_nattab);
6067c478bd9Sstevel@tonic-gate 	if (ipf != NULL) {
6077c478bd9Sstevel@tonic-gate 		nat = ipf->ipfr_data;
6087c478bd9Sstevel@tonic-gate 		/*
6097c478bd9Sstevel@tonic-gate 		 * This is the last fragment for this packet.
6107c478bd9Sstevel@tonic-gate 		 */
611f4b3ec61Sdh 		if ((ipf->ipfr_ttl == ifs->ifs_fr_ticks + 1) && (nat != NULL)) {
6127c478bd9Sstevel@tonic-gate 			nat->nat_data = NULL;
6137c478bd9Sstevel@tonic-gate 			ipf->ipfr_data = NULL;
6147c478bd9Sstevel@tonic-gate 		}
6157c478bd9Sstevel@tonic-gate 	} else
6167c478bd9Sstevel@tonic-gate 		nat = NULL;
617f4b3ec61Sdh 	RWLOCK_EXIT(&ifs->ifs_ipf_natfrag);
6187c478bd9Sstevel@tonic-gate 	return nat;
6197c478bd9Sstevel@tonic-gate }
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate 
6227c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
6237c478bd9Sstevel@tonic-gate /* Function:    fr_ipid_knownfrag                                           */
6247c478bd9Sstevel@tonic-gate /* Returns:     u_32_t - IPv4 ID for this packet if match found, else       */
6257c478bd9Sstevel@tonic-gate /*                       return 0xfffffff to indicate no match.             */
6267c478bd9Sstevel@tonic-gate /* Parameters:  fin(I) - pointer to packet information                      */
6277c478bd9Sstevel@tonic-gate /*                                                                          */
6287c478bd9Sstevel@tonic-gate /* Functional interface for IP ID lookups of the IP ID fragment cache       */
6297c478bd9Sstevel@tonic-gate /* ------------------------------------------------------------------------ */
fr_ipid_knownfrag(fin)6307c478bd9Sstevel@tonic-gate u_32_t fr_ipid_knownfrag(fin)
6317c478bd9Sstevel@tonic-gate fr_info_t *fin;
6327c478bd9Sstevel@tonic-gate {
6337c478bd9Sstevel@tonic-gate 	ipfr_t	*ipf;
6347c478bd9Sstevel@tonic-gate 	u_32_t	id;
635f4b3ec61Sdh 	ipf_stack_t *ifs = fin->fin_ifs;
6367c478bd9Sstevel@tonic-gate 
63772680cf5SDarren Reed 	if (ifs->ifs_fr_frag_lock || !ifs->ifs_ipfr_ipidlist)
6387c478bd9Sstevel@tonic-gate 		return 0xffffffff;
6397c478bd9Sstevel@tonic-gate 
640