xref: /onnv-gate/usr/src/uts/common/ipp/ipgpc/classifier.c (revision 8485:633e5b5eb268)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51932Svi117747  * Common Development and Distribution License (the "License").
61932Svi117747  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
211932Svi117747 
220Sstevel@tonic-gate /*
23*8485SPeter.Memishian@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #include <sys/kmem.h>
280Sstevel@tonic-gate #include <sys/systm.h>
290Sstevel@tonic-gate #include <sys/socket.h>
300Sstevel@tonic-gate #include <sys/strsun.h>
310Sstevel@tonic-gate #include <netinet/in.h>
320Sstevel@tonic-gate #include <ipp/ipgpc/classifier.h>
330Sstevel@tonic-gate #include <inet/ip.h>
340Sstevel@tonic-gate #include <inet/ip6.h>
350Sstevel@tonic-gate #include <net/if.h>
360Sstevel@tonic-gate #include <inet/ipp_common.h>
370Sstevel@tonic-gate 
380Sstevel@tonic-gate /* Implementation file for classifier used in ipgpc module */
390Sstevel@tonic-gate 
400Sstevel@tonic-gate /*
410Sstevel@tonic-gate  * CHECK_MATCH_STATUS(match_status, slctrs_srchd, selector_mask)
420Sstevel@tonic-gate  *
430Sstevel@tonic-gate  * determines what the result of the selector search and what action needs to
440Sstevel@tonic-gate  * be taken next.
450Sstevel@tonic-gate  * if a NORMAL_MATCH occurs, business as usual NORMAL_MATCH
460Sstevel@tonic-gate  * if the selector was not searched because only DONTCARE keys are loaded,
470Sstevel@tonic-gate  * the selector is marked as not being searched
480Sstevel@tonic-gate  * otherwise, memory error occurred or no matches were found, classify()
490Sstevel@tonic-gate  * should return the error match status immediately
500Sstevel@tonic-gate  */
510Sstevel@tonic-gate #define	CHECK_MATCH_STATUS(match_status, slctrs_srchd, selector_mask)	\
520Sstevel@tonic-gate 	(((match_status) == NORMAL_MATCH) ?			\
530Sstevel@tonic-gate 	(NORMAL_MATCH) :					\
540Sstevel@tonic-gate 	(((match_status) == DONTCARE_ONLY_MATCH) ?		\
550Sstevel@tonic-gate 	(*(slctrs_srchd) ^= (selector_mask), NORMAL_MATCH) :	\
560Sstevel@tonic-gate 	(match_status)))
570Sstevel@tonic-gate 
580Sstevel@tonic-gate /* used to determine if an action instance already exists */
590Sstevel@tonic-gate boolean_t ipgpc_action_exist = B_FALSE;
600Sstevel@tonic-gate int ipgpc_debug = 0;		/* IPGPC debugging level */
610Sstevel@tonic-gate 
620Sstevel@tonic-gate /* Statics */
630Sstevel@tonic-gate static int common_classify(ipgpc_packet_t *, ht_match_t *, uint16_t *);
640Sstevel@tonic-gate static void update_stats(int, uint_t);
650Sstevel@tonic-gate static int bestmatch(ht_match_t *, uint16_t);
660Sstevel@tonic-gate static void get_port_info(ipgpc_packet_t *, void *, int, mblk_t *);
670Sstevel@tonic-gate 
680Sstevel@tonic-gate /*
690Sstevel@tonic-gate  * common_classify(packet, fid_table, slctrs_srchd)
700Sstevel@tonic-gate  *
710Sstevel@tonic-gate  * searches each of the common selectors
725331Samw  * - will return NORMAL_MATCH on success.  NO_MATCHES on error
730Sstevel@tonic-gate  */
740Sstevel@tonic-gate static int
750Sstevel@tonic-gate common_classify(ipgpc_packet_t *packet, ht_match_t *fid_table,
760Sstevel@tonic-gate     uint16_t *slctrs_srchd)
770Sstevel@tonic-gate {
780Sstevel@tonic-gate 	int match_status;
790Sstevel@tonic-gate 
800Sstevel@tonic-gate 	/* Find on packet direction */
810Sstevel@tonic-gate 	match_status =
820Sstevel@tonic-gate 	    ipgpc_findfilters(IPGPC_TABLE_DIR, packet->direction, fid_table);
830Sstevel@tonic-gate 	if (CHECK_MATCH_STATUS(match_status, slctrs_srchd,
840Sstevel@tonic-gate 	    ipgpc_table_list[DIR_IDX].info.mask) != NORMAL_MATCH) {
850Sstevel@tonic-gate 		return (match_status);
860Sstevel@tonic-gate 	}
870Sstevel@tonic-gate 
880Sstevel@tonic-gate 	/* Find on IF_INDEX of packet */
890Sstevel@tonic-gate 	match_status =
900Sstevel@tonic-gate 	    ipgpc_findfilters(IPGPC_TABLE_IF, packet->if_index, fid_table);
910Sstevel@tonic-gate 	if (CHECK_MATCH_STATUS(match_status, slctrs_srchd,
920Sstevel@tonic-gate 	    ipgpc_table_list[IF_IDX].info.mask) != NORMAL_MATCH) {
930Sstevel@tonic-gate 		return (match_status);
940Sstevel@tonic-gate 	}
950Sstevel@tonic-gate 
960Sstevel@tonic-gate 	/* Find on DS field */
970Sstevel@tonic-gate 	match_status =
980Sstevel@tonic-gate 	    ipgpc_findfilters(IPGPC_BA_DSID, packet->dsfield, fid_table);
990Sstevel@tonic-gate 	if (CHECK_MATCH_STATUS(match_status, slctrs_srchd,
1000Sstevel@tonic-gate 	    ipgpc_ds_table_id.info.mask) != NORMAL_MATCH) {
1010Sstevel@tonic-gate 		return (match_status);
1020Sstevel@tonic-gate 	}
1030Sstevel@tonic-gate 
1040Sstevel@tonic-gate 	/* Find on UID of packet */
1050Sstevel@tonic-gate 	match_status =
1060Sstevel@tonic-gate 	    ipgpc_findfilters(IPGPC_TABLE_UID, packet->uid, fid_table);
1070Sstevel@tonic-gate 	if (CHECK_MATCH_STATUS(match_status, slctrs_srchd,
1080Sstevel@tonic-gate 	    ipgpc_table_list[UID_IDX].info.mask) != NORMAL_MATCH) {
1090Sstevel@tonic-gate 		return (match_status);
1100Sstevel@tonic-gate 	}
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate 	/* Find on PROJID of packet */
1130Sstevel@tonic-gate 	match_status =
1140Sstevel@tonic-gate 	    ipgpc_findfilters(IPGPC_TABLE_PROJID, packet->projid, fid_table);
1150Sstevel@tonic-gate 	if (CHECK_MATCH_STATUS(match_status, slctrs_srchd,
1160Sstevel@tonic-gate 	    ipgpc_table_list[PROJID_IDX].info.mask) != NORMAL_MATCH) {
1170Sstevel@tonic-gate 		return (match_status);
1180Sstevel@tonic-gate 	}
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate 	/* Find on IP Protocol field */
1210Sstevel@tonic-gate 	if (packet->proto > 0) {
1220Sstevel@tonic-gate 		match_status = ipgpc_findfilters(IPGPC_TABLE_PROTOID,
1230Sstevel@tonic-gate 		    packet->proto, fid_table);
1240Sstevel@tonic-gate 		if (CHECK_MATCH_STATUS(match_status, slctrs_srchd,
1250Sstevel@tonic-gate 		    ipgpc_table_list[PROTOID_IDX].info.mask)
1260Sstevel@tonic-gate 		    != NORMAL_MATCH) {
1270Sstevel@tonic-gate 			return (match_status);
1280Sstevel@tonic-gate 		}
1290Sstevel@tonic-gate 	} else {
1300Sstevel@tonic-gate 		/* skip search */
1310Sstevel@tonic-gate 		*slctrs_srchd ^= ipgpc_table_list[PROTOID_IDX].info.mask;
1320Sstevel@tonic-gate 	}
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate 	/* Find on IP Source Port field */
1350Sstevel@tonic-gate 	if (packet->sport > 0) {
136*8485SPeter.Memishian@Sun.COM 		match_status = ipgpc_findfilters(IPGPC_TRIE_SPORTID,
137*8485SPeter.Memishian@Sun.COM 		    packet->sport, fid_table);
1380Sstevel@tonic-gate 		if (CHECK_MATCH_STATUS(match_status, slctrs_srchd,
1390Sstevel@tonic-gate 		    ipgpc_trie_list[IPGPC_TRIE_SPORTID].info.mask)
1400Sstevel@tonic-gate 		    != NORMAL_MATCH) {
1410Sstevel@tonic-gate 			return (match_status);
1420Sstevel@tonic-gate 		}
1430Sstevel@tonic-gate 	} else {
1440Sstevel@tonic-gate 		/* skip search */
1450Sstevel@tonic-gate 		*slctrs_srchd ^= ipgpc_trie_list[IPGPC_TRIE_SPORTID].info.mask;
1460Sstevel@tonic-gate 	}
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate 	/* Find on IP Destination Port field */
1490Sstevel@tonic-gate 	if (packet->dport > 0) {
150*8485SPeter.Memishian@Sun.COM 		match_status = ipgpc_findfilters(IPGPC_TRIE_DPORTID,
151*8485SPeter.Memishian@Sun.COM 		    packet->dport, fid_table);
1520Sstevel@tonic-gate 		if (CHECK_MATCH_STATUS(match_status, slctrs_srchd,
1530Sstevel@tonic-gate 		    ipgpc_trie_list[IPGPC_TRIE_DPORTID].info.mask)
1540Sstevel@tonic-gate 		    != NORMAL_MATCH) {
1550Sstevel@tonic-gate 			return (match_status);
1560Sstevel@tonic-gate 		}
1570Sstevel@tonic-gate 	} else {
1580Sstevel@tonic-gate 		/* skip search */
1590Sstevel@tonic-gate 		*slctrs_srchd ^= ipgpc_trie_list[IPGPC_TRIE_DPORTID].info.mask;
1600Sstevel@tonic-gate 	}
1610Sstevel@tonic-gate 	return (NORMAL_MATCH);
1620Sstevel@tonic-gate }
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate /*
1650Sstevel@tonic-gate  * update_stats(class_id, nbytes)
1660Sstevel@tonic-gate  *
1670Sstevel@tonic-gate  * if ipgpc_gather_stats == TRUE
1680Sstevel@tonic-gate  * updates the statistics for class pointed to be the input classid
1690Sstevel@tonic-gate  * and the global ipgpc kstats
1700Sstevel@tonic-gate  * updates the last time the class was matched with the current hrtime value,
1710Sstevel@tonic-gate  * number of packets and number of bytes with nbytes
1720Sstevel@tonic-gate  */
1730Sstevel@tonic-gate static void
1740Sstevel@tonic-gate update_stats(int class_id, uint_t nbytes)
1750Sstevel@tonic-gate {
1760Sstevel@tonic-gate 	if (ipgpc_gather_stats) {
1770Sstevel@tonic-gate 		/* update global stats */
1780Sstevel@tonic-gate 		BUMP_STATS(ipgpc_npackets);
1790Sstevel@tonic-gate 		UPDATE_STATS(ipgpc_nbytes, nbytes);
1800Sstevel@tonic-gate 		if (ipgpc_cid_list[class_id].aclass.gather_stats) {
1810Sstevel@tonic-gate 			/* update per class stats */
1820Sstevel@tonic-gate 			SET_STATS(ipgpc_cid_list[class_id].stats.last_match,
1830Sstevel@tonic-gate 			    gethrtime());
1840Sstevel@tonic-gate 			BUMP_STATS(ipgpc_cid_list[class_id].stats.npackets);
1850Sstevel@tonic-gate 			UPDATE_STATS(ipgpc_cid_list[class_id].stats.nbytes,
1860Sstevel@tonic-gate 			    nbytes);
1870Sstevel@tonic-gate 		}
1880Sstevel@tonic-gate 	}
1890Sstevel@tonic-gate }
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate /*
1920Sstevel@tonic-gate  * FREE_FID_TABLE(fid_table, p, q, i)
1930Sstevel@tonic-gate  *
1940Sstevel@tonic-gate  * searches fid_table for dynamically allocated memory and frees it
1950Sstevel@tonic-gate  * p, q, i are temps
1960Sstevel@tonic-gate  */
1970Sstevel@tonic-gate #define	FREE_FID_TABLE(fid_table, p, q, i)				\
1980Sstevel@tonic-gate 	/* free all allocated memory in fid_table */			\
1990Sstevel@tonic-gate 	for (i = 0; i < HASH_SIZE; ++i) {				\
2000Sstevel@tonic-gate 		if (fid_table[i].next != NULL) {			\
2010Sstevel@tonic-gate 			p = fid_table[i].next;				\
2020Sstevel@tonic-gate 			while (p != NULL) {				\
2030Sstevel@tonic-gate 				q = p;					\
2040Sstevel@tonic-gate 				p = p->next;				\
2050Sstevel@tonic-gate 				kmem_cache_free(ht_match_cache, q);	\
2060Sstevel@tonic-gate 			}						\
2070Sstevel@tonic-gate 		}							\
2081932Svi117747 	}
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate 
2110Sstevel@tonic-gate /*
2120Sstevel@tonic-gate  * ipgpc_classify(af, packet)
2130Sstevel@tonic-gate  *
2140Sstevel@tonic-gate  * The function that drives the packet classification algorithm.  Given a
2150Sstevel@tonic-gate  * address family (either AF_INET or AF_INET6) the input packet structure
2160Sstevel@tonic-gate  * is matched against all the selector structures.  For each search of
2170Sstevel@tonic-gate  * a selector structure, all matched filters are collected.  Once all
2180Sstevel@tonic-gate  * selectors are searched, the best match of all matched filters is
2190Sstevel@tonic-gate  * determined.  Finally, the class associated with the best matching filter
2200Sstevel@tonic-gate  * is returned.  If no filters were matched, the default class is returned.
2210Sstevel@tonic-gate  * If a memory error occurred, NULL is returned.
2220Sstevel@tonic-gate  */
2230Sstevel@tonic-gate ipgpc_class_t *
2240Sstevel@tonic-gate ipgpc_classify(int af, ipgpc_packet_t *packet)
2250Sstevel@tonic-gate {
2260Sstevel@tonic-gate 	int match_status;
2270Sstevel@tonic-gate 	uint16_t slctrs_srchd;
2280Sstevel@tonic-gate 	int class_id;
2290Sstevel@tonic-gate 	ht_match_t fid_table[HASH_SIZE];
2300Sstevel@tonic-gate 	ht_match_t *p, *q;
2310Sstevel@tonic-gate 	int i;
2320Sstevel@tonic-gate 	int rc;
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate 	if (ipgpc_num_fltrs == 0) {
2350Sstevel@tonic-gate 		/* zero filters are loaded, return default class */
2360Sstevel@tonic-gate 		update_stats(ipgpc_def_class_id, packet->len);
2370Sstevel@tonic-gate 		/*
2380Sstevel@tonic-gate 		 * no need to free fid_table. Since zero selectors were
2390Sstevel@tonic-gate 		 * searched and dynamic memory wasn't allocated.
2400Sstevel@tonic-gate 		 */
2410Sstevel@tonic-gate 		return (&ipgpc_cid_list[ipgpc_def_class_id].aclass);
2420Sstevel@tonic-gate 	}
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate 	match_status = 0;
2450Sstevel@tonic-gate 	slctrs_srchd = ALL_MATCH_MASK;
2460Sstevel@tonic-gate 	bzero(fid_table, sizeof (ht_match_t) * HASH_SIZE);
2470Sstevel@tonic-gate 
2480Sstevel@tonic-gate 	/* first search all address family independent selectors */
249*8485SPeter.Memishian@Sun.COM 	rc = common_classify(packet, fid_table, &slctrs_srchd);
250*8485SPeter.Memishian@Sun.COM 	if (rc != NORMAL_MATCH) {
2510Sstevel@tonic-gate 		/* free all dynamic allocated memory */
2520Sstevel@tonic-gate 		FREE_FID_TABLE(fid_table, p, q, i);
2530Sstevel@tonic-gate 		if (rc == NO_MATCHES) {
2540Sstevel@tonic-gate 			update_stats(ipgpc_def_class_id, packet->len);
2550Sstevel@tonic-gate 			return (&ipgpc_cid_list[ipgpc_def_class_id].aclass);
2560Sstevel@tonic-gate 		} else {	/* memory error */
2570Sstevel@tonic-gate 			return (NULL);
2580Sstevel@tonic-gate 		}
2590Sstevel@tonic-gate 	}
2600Sstevel@tonic-gate 
2610Sstevel@tonic-gate 	switch (af) {		/* switch off of address family */
2620Sstevel@tonic-gate 	case AF_INET:
2630Sstevel@tonic-gate 		/* Find on IPv4 Source Address field */
2640Sstevel@tonic-gate 		match_status = ipgpc_findfilters(IPGPC_TRIE_SADDRID,
2650Sstevel@tonic-gate 		    V4_PART_OF_V6(packet->saddr), fid_table);
2660Sstevel@tonic-gate 		if (CHECK_MATCH_STATUS(match_status, &slctrs_srchd,
2670Sstevel@tonic-gate 		    ipgpc_trie_list[IPGPC_TRIE_SADDRID].info.mask)
2680Sstevel@tonic-gate 		    != NORMAL_MATCH) {
2690Sstevel@tonic-gate 			/* free all dynamic allocated memory */
2700Sstevel@tonic-gate 			FREE_FID_TABLE(fid_table, p, q, i);
2710Sstevel@tonic-gate 			if (match_status == NO_MATCHES) {
2720Sstevel@tonic-gate 				update_stats(ipgpc_def_class_id, packet->len);
2730Sstevel@tonic-gate 				return (&ipgpc_cid_list[ipgpc_def_class_id].
2740Sstevel@tonic-gate 				    aclass);
2750Sstevel@tonic-gate 			} else { /* memory error */
2760Sstevel@tonic-gate 				return (NULL);
2770Sstevel@tonic-gate 			}
2780Sstevel@tonic-gate 		}
2790Sstevel@tonic-gate 		/* Find on IPv4 Destination Address field */
2800Sstevel@tonic-gate 		match_status = ipgpc_findfilters(IPGPC_TRIE_DADDRID,
2810Sstevel@tonic-gate 		    V4_PART_OF_V6(packet->daddr), fid_table);
2820Sstevel@tonic-gate 		if (CHECK_MATCH_STATUS(match_status, &slctrs_srchd,
2830Sstevel@tonic-gate 		    ipgpc_trie_list[IPGPC_TRIE_DADDRID].info.mask)
2840Sstevel@tonic-gate 		    != NORMAL_MATCH) {
2850Sstevel@tonic-gate 			/* free all dynamic allocated memory */
2860Sstevel@tonic-gate 			FREE_FID_TABLE(fid_table, p, q, i);
2870Sstevel@tonic-gate 			if (match_status == NO_MATCHES) {
2880Sstevel@tonic-gate 				update_stats(ipgpc_def_class_id, packet->len);
2890Sstevel@tonic-gate 				return (&ipgpc_cid_list[ipgpc_def_class_id].
2900Sstevel@tonic-gate 				    aclass);
2910Sstevel@tonic-gate 			} else { /* memory error */
2920Sstevel@tonic-gate 				return (NULL);
2930Sstevel@tonic-gate 			}
2940Sstevel@tonic-gate 		}
2950Sstevel@tonic-gate 		break;
2960Sstevel@tonic-gate 	case AF_INET6:
2970Sstevel@tonic-gate 		/* Find on IPv6 Source Address field */
2980Sstevel@tonic-gate 		match_status = ipgpc_findfilters6(IPGPC_TRIE_SADDRID6,
2990Sstevel@tonic-gate 		    packet->saddr, fid_table);
3000Sstevel@tonic-gate 		if (CHECK_MATCH_STATUS(match_status, &slctrs_srchd,
3010Sstevel@tonic-gate 		    ipgpc_trie_list[IPGPC_TRIE_SADDRID6].info.mask)
3020Sstevel@tonic-gate 		    != NORMAL_MATCH) {
3030Sstevel@tonic-gate 			/* free all dynamic allocated memory */
3040Sstevel@tonic-gate 			FREE_FID_TABLE(fid_table, p, q, i);
3050Sstevel@tonic-gate 			if (match_status == NO_MATCHES) {
3060Sstevel@tonic-gate 				update_stats(ipgpc_def_class_id, packet->len);
3070Sstevel@tonic-gate 				return (&ipgpc_cid_list[ipgpc_def_class_id].
3080Sstevel@tonic-gate 				    aclass);
3090Sstevel@tonic-gate 			} else { /* memory error */
3100Sstevel@tonic-gate 				return (NULL);
3110Sstevel@tonic-gate 			}
3120Sstevel@tonic-gate 		}
3130Sstevel@tonic-gate 		/* Find on IPv6 Destination Address field */
3140Sstevel@tonic-gate 		match_status = ipgpc_findfilters6(IPGPC_TRIE_DADDRID6,
3150Sstevel@tonic-gate 		    packet->daddr, fid_table);
3160Sstevel@tonic-gate 		if (CHECK_MATCH_STATUS(match_status, &slctrs_srchd,
3170Sstevel@tonic-gate 		    ipgpc_trie_list[IPGPC_TRIE_DADDRID6].info.mask)
3180Sstevel@tonic-gate 		    != NORMAL_MATCH) {
3190Sstevel@tonic-gate 			/* free all dynamic allocated memory */
3200Sstevel@tonic-gate 			FREE_FID_TABLE(fid_table, p, q, i);
3210Sstevel@tonic-gate 			if (match_status == NO_MATCHES) {
3220Sstevel@tonic-gate 				update_stats(ipgpc_def_class_id, packet->len);
3230Sstevel@tonic-gate 				return (&ipgpc_cid_list[ipgpc_def_class_id].
3240Sstevel@tonic-gate 				    aclass);
3250Sstevel@tonic-gate 			} else {
3260Sstevel@tonic-gate 				return (NULL);
3270Sstevel@tonic-gate 			}
3280Sstevel@tonic-gate 		}
3290Sstevel@tonic-gate 		break;
3300Sstevel@tonic-gate 	default:
3310Sstevel@tonic-gate 		ipgpc0dbg(("ipgpc_classify(): Unknown Address Family"));
3320Sstevel@tonic-gate 		/* free all dynamic allocated memory */
3330Sstevel@tonic-gate 		FREE_FID_TABLE(fid_table, p, q, i);
3340Sstevel@tonic-gate 		return (NULL);
3350Sstevel@tonic-gate 	}
3360Sstevel@tonic-gate 
3370Sstevel@tonic-gate 	/* zero selectors were searched, return default */
3380Sstevel@tonic-gate 	if (slctrs_srchd == 0) {
3390Sstevel@tonic-gate 		/*
3400Sstevel@tonic-gate 		 * no need to free fid_table.  Since zero selectors were
3410Sstevel@tonic-gate 		 * searched and dynamic memory wasn't allocated
3420Sstevel@tonic-gate 		 */
3430Sstevel@tonic-gate 		update_stats(ipgpc_def_class_id, packet->len);
3440Sstevel@tonic-gate 		return (&ipgpc_cid_list[ipgpc_def_class_id].aclass);
3450Sstevel@tonic-gate 	}
3460Sstevel@tonic-gate 
3470Sstevel@tonic-gate 	/* Perform best match search */
3480Sstevel@tonic-gate 	class_id = bestmatch(fid_table, slctrs_srchd);
3490Sstevel@tonic-gate 	/* free all dynamic allocated memory */
3500Sstevel@tonic-gate 	FREE_FID_TABLE(fid_table, p, q, i);
3510Sstevel@tonic-gate 
3520Sstevel@tonic-gate 	update_stats(class_id, packet->len);
3530Sstevel@tonic-gate 	return (&ipgpc_cid_list[class_id].aclass);
3540Sstevel@tonic-gate }
3550Sstevel@tonic-gate 
3560Sstevel@tonic-gate /*
3570Sstevel@tonic-gate  * bestmatch(fid_table, bestmask)
3580Sstevel@tonic-gate  *
3590Sstevel@tonic-gate  * determines the bestmatching filter in fid_table which matches the criteria
3600Sstevel@tonic-gate  * described below and returns the class id
3610Sstevel@tonic-gate  */
3620Sstevel@tonic-gate static int
3630Sstevel@tonic-gate bestmatch(ht_match_t *fid_table, uint16_t bestmask)
3640Sstevel@tonic-gate {
3650Sstevel@tonic-gate 	int i, key;
3660Sstevel@tonic-gate 	int bestmatch = -1;
3670Sstevel@tonic-gate 	int oldbm = -1;
3680Sstevel@tonic-gate 	uint32_t temp_prec;
3690Sstevel@tonic-gate 	uint32_t temp_prio;
3700Sstevel@tonic-gate 	uint64_t best_prio;
3710Sstevel@tonic-gate 	uint64_t real_prio;
3720Sstevel@tonic-gate 	ht_match_t *item;
3730Sstevel@tonic-gate 
3740Sstevel@tonic-gate 	for (i = 0; i < HASH_SIZE; ++i) {
3750Sstevel@tonic-gate 		if (fid_table[i].key == 0) {
3760Sstevel@tonic-gate 			continue;
3770Sstevel@tonic-gate 		}
3780Sstevel@tonic-gate 		for (item = &fid_table[i]; item != NULL; item = item->next) {
3790Sstevel@tonic-gate 			/*
3800Sstevel@tonic-gate 			 * BESTMATCH is:
3810Sstevel@tonic-gate 			 * 1. Matches in all selectors searched
3820Sstevel@tonic-gate 			 * 2. highest priority of filters that meet 1.
3830Sstevel@tonic-gate 			 * 3. best precedence of filters that meet 2
3840Sstevel@tonic-gate 			 *    with the same priority
3850Sstevel@tonic-gate 			 */
3860Sstevel@tonic-gate 			if ((key = item->key) == 0) {
3870Sstevel@tonic-gate 				continue;
3880Sstevel@tonic-gate 			}
3890Sstevel@tonic-gate 			if (ipgpc_fid_list[key].info <= 0) {
3900Sstevel@tonic-gate 				continue;
3910Sstevel@tonic-gate 			}
3920Sstevel@tonic-gate 
3930Sstevel@tonic-gate 			/*
3940Sstevel@tonic-gate 			 * check to see if fid has been inserted into a
3950Sstevel@tonic-gate 			 * selector structure we did not search
3960Sstevel@tonic-gate 			 * if so, then this filter is not a valid match
3970Sstevel@tonic-gate 			 * and bestmatch() should continue
3980Sstevel@tonic-gate 			 * this statement will == 0
3990Sstevel@tonic-gate 			 * - a selector has been searched and this filter
4000Sstevel@tonic-gate 			 *   either describes don't care or has inserted a
4010Sstevel@tonic-gate 			 *   value into this selector structure
4020Sstevel@tonic-gate 			 * - a selector has not been searched and this filter
4030Sstevel@tonic-gate 			 *   has described don't care for this selector
4040Sstevel@tonic-gate 			 */
4050Sstevel@tonic-gate 			if (((~bestmask) & ipgpc_fid_list[key].insert_map)
4060Sstevel@tonic-gate 			    != 0) {
4070Sstevel@tonic-gate 				continue;
4080Sstevel@tonic-gate 			}
4090Sstevel@tonic-gate 
4100Sstevel@tonic-gate 			/*
4110Sstevel@tonic-gate 			 * tests to see if the map of selectors that
4120Sstevel@tonic-gate 			 * were matched, equals the map of selectors
4130Sstevel@tonic-gate 			 * structures this filter inserts into
4140Sstevel@tonic-gate 			 */
4150Sstevel@tonic-gate 			if (item->match_map != ipgpc_fid_list[key].insert_map) {
4160Sstevel@tonic-gate 				continue;
4170Sstevel@tonic-gate 			}
4180Sstevel@tonic-gate 
4190Sstevel@tonic-gate 			if (bestmatch == -1) { /* first matching filter */
4200Sstevel@tonic-gate 				/* this filter becomes the bestmatch */
4210Sstevel@tonic-gate 				temp_prio =
4220Sstevel@tonic-gate 				    ipgpc_fid_list[key].filter.priority;
4230Sstevel@tonic-gate 				temp_prec =
4240Sstevel@tonic-gate 				    ipgpc_fid_list[key].filter.precedence;
4250Sstevel@tonic-gate 				best_prio = ((uint64_t)temp_prio << 32) |
4260Sstevel@tonic-gate 				    (uint64_t)~temp_prec;
4270Sstevel@tonic-gate 				bestmatch = key;
4280Sstevel@tonic-gate 				continue;
4290Sstevel@tonic-gate 			}
4300Sstevel@tonic-gate 
4310Sstevel@tonic-gate 			/*
4320Sstevel@tonic-gate 			 * calculate the real priority by combining priority
4330Sstevel@tonic-gate 			 * and precedence
4340Sstevel@tonic-gate 			 */
4350Sstevel@tonic-gate 			real_prio =
4360Sstevel@tonic-gate 			    ((uint64_t)ipgpc_fid_list[key].filter.priority
437*8485SPeter.Memishian@Sun.COM 			    << 32) |
4380Sstevel@tonic-gate 			    (uint64_t)~ipgpc_fid_list[key].filter.precedence;
4390Sstevel@tonic-gate 
4400Sstevel@tonic-gate 			/* check to see if this is the new bestmatch */
4410Sstevel@tonic-gate 			if (real_prio > best_prio) {
4420Sstevel@tonic-gate 				oldbm = bestmatch;
4430Sstevel@tonic-gate 				ipgpc3dbg(("bestmatch: filter %s " \
4440Sstevel@tonic-gate 				    "REJECTED because of better priority %d" \
4450Sstevel@tonic-gate 				    " and/or precedence %d",
4460Sstevel@tonic-gate 				    ipgpc_fid_list[oldbm].filter.filter_name,
4470Sstevel@tonic-gate 				    ipgpc_fid_list[oldbm].filter.priority,
4480Sstevel@tonic-gate 				    ipgpc_fid_list[oldbm].filter.precedence));
4490Sstevel@tonic-gate 				best_prio = real_prio;
4500Sstevel@tonic-gate 				bestmatch = key;
4510Sstevel@tonic-gate 			} else {
4520Sstevel@tonic-gate 				ipgpc3dbg(("bestmatch: filter %s " \
4530Sstevel@tonic-gate 				    "REJECTED because of beter priority %d" \
4540Sstevel@tonic-gate 				    " and/or precedence %d",
4550Sstevel@tonic-gate 				    ipgpc_fid_list[key].filter.filter_name,
4560Sstevel@tonic-gate 				    ipgpc_fid_list[key].filter.priority,
4570Sstevel@tonic-gate 				    ipgpc_fid_list[key].filter.precedence));
4580Sstevel@tonic-gate 			}
4590Sstevel@tonic-gate 		}
4600Sstevel@tonic-gate 	}
4610Sstevel@tonic-gate 	if (bestmatch == -1) {	/* no best matches were found */
4620Sstevel@tonic-gate 		ipgpc3dbg(("bestmatch: No filters ACCEPTED"));
4630Sstevel@tonic-gate 		return (ipgpc_def_class_id);
4640Sstevel@tonic-gate 	} else {
4650Sstevel@tonic-gate 		ipgpc3dbg(("bestmatch: filter %s ACCEPTED with priority %d " \
4660Sstevel@tonic-gate 		    "and precedence %d",
4670Sstevel@tonic-gate 		    ipgpc_fid_list[bestmatch].filter.filter_name,
4680Sstevel@tonic-gate 		    ipgpc_fid_list[bestmatch].filter.priority,
4690Sstevel@tonic-gate 		    ipgpc_fid_list[bestmatch].filter.precedence));
4700Sstevel@tonic-gate 		return (ipgpc_fid_list[bestmatch].class_id);
4710Sstevel@tonic-gate 	}
4720Sstevel@tonic-gate }
4730Sstevel@tonic-gate 
4740Sstevel@tonic-gate /*
4750Sstevel@tonic-gate  * get_port_info(packet, iph, af, mp)
4760Sstevel@tonic-gate  *
4770Sstevel@tonic-gate  * Gets the source and destination ports from the ULP header, if present.
4780Sstevel@tonic-gate  * If this is a fragment, don't try to get the port information even if this
4790Sstevel@tonic-gate  * is the first fragment. The reason being we won't have this information
4800Sstevel@tonic-gate  * in subsequent fragments and may end up classifying the first fragment
4810Sstevel@tonic-gate  * differently than others. This is not desired.
4820Sstevel@tonic-gate  * For IPv6 packets, step through the extension headers, if present, in
4830Sstevel@tonic-gate  * order to get to the ULP header.
4840Sstevel@tonic-gate  */
4850Sstevel@tonic-gate static void
4860Sstevel@tonic-gate get_port_info(ipgpc_packet_t *packet, void *iph, int af, mblk_t *mp)
4870Sstevel@tonic-gate {
4880Sstevel@tonic-gate 	uint16_t *up;
4890Sstevel@tonic-gate 
4900Sstevel@tonic-gate 	if (af == AF_INET) {
4910Sstevel@tonic-gate 		uint32_t u2, u1;
4920Sstevel@tonic-gate 		uint_t iplen;
4930Sstevel@tonic-gate 		ipha_t *ipha = (ipha_t *)iph;
4940Sstevel@tonic-gate 
4950Sstevel@tonic-gate 		u2 = ntohs(ipha->ipha_fragment_offset_and_flags);
4960Sstevel@tonic-gate 		u1 = u2 & (IPH_MF | IPH_OFFSET);
4970Sstevel@tonic-gate 		if (u1) {
4980Sstevel@tonic-gate 			return;
4990Sstevel@tonic-gate 		}
5000Sstevel@tonic-gate 		iplen = (ipha->ipha_version_and_hdr_length & 0xF) << 2;
5010Sstevel@tonic-gate 		up = (uint16_t *)(mp->b_rptr + iplen);
5020Sstevel@tonic-gate 		packet->sport = (uint16_t)*up++;
5030Sstevel@tonic-gate 		packet->dport = (uint16_t)*up;
5040Sstevel@tonic-gate 	} else {	/* AF_INET6 */
5050Sstevel@tonic-gate 		uint_t  length = IPV6_HDR_LEN;
5060Sstevel@tonic-gate 		ip6_t *ip6h = (ip6_t *)iph;
5070Sstevel@tonic-gate 		uint_t  ehdrlen;
5080Sstevel@tonic-gate 		uint8_t *nexthdrp, *whereptr, *endptr;
5090Sstevel@tonic-gate 		ip6_dest_t *desthdr;
5100Sstevel@tonic-gate 		ip6_rthdr_t *rthdr;
5110Sstevel@tonic-gate 		ip6_hbh_t *hbhhdr;
5120Sstevel@tonic-gate 
5130Sstevel@tonic-gate 		whereptr = ((uint8_t *)&ip6h[1]);
5140Sstevel@tonic-gate 		endptr = mp->b_wptr;
5150Sstevel@tonic-gate 		nexthdrp = &ip6h->ip6_nxt;
5160Sstevel@tonic-gate 		while (whereptr < endptr) {
5170Sstevel@tonic-gate 			switch (*nexthdrp) {
5180Sstevel@tonic-gate 			case IPPROTO_HOPOPTS:
5190Sstevel@tonic-gate 				hbhhdr = (ip6_hbh_t *)whereptr;
5200Sstevel@tonic-gate 				ehdrlen = 8 * (hbhhdr->ip6h_len + 1);
5210Sstevel@tonic-gate 				if ((uchar_t *)hbhhdr +  ehdrlen > endptr)
5220Sstevel@tonic-gate 					return;
5230Sstevel@tonic-gate 				nexthdrp = &hbhhdr->ip6h_nxt;
5240Sstevel@tonic-gate 				break;
5250Sstevel@tonic-gate 			case IPPROTO_DSTOPTS:
5260Sstevel@tonic-gate 				desthdr = (ip6_dest_t *)whereptr;
5270Sstevel@tonic-gate 				ehdrlen = 8 * (desthdr->ip6d_len + 1);
5280Sstevel@tonic-gate 				if ((uchar_t *)desthdr +  ehdrlen > endptr)
5290Sstevel@tonic-gate 					return;
5300Sstevel@tonic-gate 				nexthdrp = &desthdr->ip6d_nxt;
5310Sstevel@tonic-gate 				break;
5320Sstevel@tonic-gate 			case IPPROTO_ROUTING:
5330Sstevel@tonic-gate 				rthdr = (ip6_rthdr_t *)whereptr;
5340Sstevel@tonic-gate 				ehdrlen =  8 * (rthdr->ip6r_len + 1);
5350Sstevel@tonic-gate 				if ((uchar_t *)rthdr +  ehdrlen > endptr)
5360Sstevel@tonic-gate 					return;
5370Sstevel@tonic-gate 				nexthdrp = &rthdr->ip6r_nxt;
5380Sstevel@tonic-gate 				break;
5390Sstevel@tonic-gate 			case IPPROTO_FRAGMENT:
5400Sstevel@tonic-gate 				return;
5410Sstevel@tonic-gate 			case IPPROTO_TCP:
5420Sstevel@tonic-gate 			case IPPROTO_UDP:
5430Sstevel@tonic-gate 			case IPPROTO_SCTP:
5440Sstevel@tonic-gate 				/*
5450Sstevel@tonic-gate 				 * Verify we have at least ICMP_MIN_TP_HDR_LEN
5460Sstevel@tonic-gate 				 * bytes of the ULP's header to get the port
5470Sstevel@tonic-gate 				 * info.
5480Sstevel@tonic-gate 				 */
5490Sstevel@tonic-gate 				if (((uchar_t *)ip6h + length +
5500Sstevel@tonic-gate 				    ICMP_MIN_TP_HDR_LEN)  > endptr) {
5510Sstevel@tonic-gate 					return;
5520Sstevel@tonic-gate 				}
5530Sstevel@tonic-gate 				/* Get the protocol and the ports */
5540Sstevel@tonic-gate 				packet->proto = *nexthdrp;
5550Sstevel@tonic-gate 				up = (uint16_t *)((uchar_t *)ip6h + length);
5560Sstevel@tonic-gate 				packet->sport = (uint16_t)*up++;
5570Sstevel@tonic-gate 				packet->dport = (uint16_t)*up;
5580Sstevel@tonic-gate 				return;
5590Sstevel@tonic-gate 			case IPPROTO_ICMPV6:
5600Sstevel@tonic-gate 			case IPPROTO_ENCAP:
5610Sstevel@tonic-gate 			case IPPROTO_IPV6:
5620Sstevel@tonic-gate 			case IPPROTO_ESP:
5630Sstevel@tonic-gate 			case IPPROTO_AH:
5640Sstevel@tonic-gate 				packet->proto = *nexthdrp;
5650Sstevel@tonic-gate 				return;
5660Sstevel@tonic-gate 			case IPPROTO_NONE:
5670Sstevel@tonic-gate 			default:
5680Sstevel@tonic-gate 				return;
5690Sstevel@tonic-gate 			}
5700Sstevel@tonic-gate 			length += ehdrlen;
5710Sstevel@tonic-gate 			whereptr += ehdrlen;
5720Sstevel@tonic-gate 		}
5730Sstevel@tonic-gate 	}
5740Sstevel@tonic-gate }
5750Sstevel@tonic-gate 
5760Sstevel@tonic-gate /*
5770Sstevel@tonic-gate  * find_ids(packet, mp)
5780Sstevel@tonic-gate  *
5790Sstevel@tonic-gate  * attempt to discern the uid and projid of the originator of a packet by
5800Sstevel@tonic-gate  * looking at the dblks making up the packet - yeuch!
5810Sstevel@tonic-gate  *
5820Sstevel@tonic-gate  * We do it by skipping any fragments with a credp of NULL (originated in
5830Sstevel@tonic-gate  * kernel), taking the first value that isn't NULL to be the credp for the
5840Sstevel@tonic-gate  * whole packet. We also suck the projid from the same fragment.
5850Sstevel@tonic-gate  */
5860Sstevel@tonic-gate static void
5870Sstevel@tonic-gate find_ids(ipgpc_packet_t *packet, mblk_t *mp)
5880Sstevel@tonic-gate {
5890Sstevel@tonic-gate 	cred_t *cr;
5900Sstevel@tonic-gate 
5910Sstevel@tonic-gate 	while (DB_CRED(mp) == NULL && mp->b_cont != NULL)
5920Sstevel@tonic-gate 		mp = mp->b_cont;
5930Sstevel@tonic-gate 
5940Sstevel@tonic-gate 	if ((cr = DB_CRED(mp)) != NULL) {
5950Sstevel@tonic-gate 		packet->uid = crgetuid(cr);
5960Sstevel@tonic-gate 		packet->projid = crgetprojid(cr);
5970Sstevel@tonic-gate 	} else {
5984321Scasper 		packet->uid = (uid_t)-1;
5990Sstevel@tonic-gate 		packet->projid = -1;
6000Sstevel@tonic-gate 	}
6010Sstevel@tonic-gate }
6020Sstevel@tonic-gate 
6030Sstevel@tonic-gate /*
6040Sstevel@tonic-gate  * parse_packet(packet, mp)
6050Sstevel@tonic-gate  *
6060Sstevel@tonic-gate  * parses the given message block into a ipgpc_packet_t structure
6070Sstevel@tonic-gate  */
6080Sstevel@tonic-gate void
6090Sstevel@tonic-gate parse_packet(ipgpc_packet_t *packet, mblk_t *mp)
6100Sstevel@tonic-gate {
6110Sstevel@tonic-gate 	ipha_t	*ipha;
6120Sstevel@tonic-gate 
6130Sstevel@tonic-gate 	/* parse message block for IP header and ports */
6140Sstevel@tonic-gate 	ipha = (ipha_t *)mp->b_rptr; /* get ip header */
6150Sstevel@tonic-gate 	V4_PART_OF_V6(packet->saddr) = (int32_t)ipha->ipha_src;
6160Sstevel@tonic-gate 	V4_PART_OF_V6(packet->daddr) = (int32_t)ipha->ipha_dst;
6170Sstevel@tonic-gate 	packet->dsfield = ipha->ipha_type_of_service;
6180Sstevel@tonic-gate 	packet->proto = ipha->ipha_protocol;
6190Sstevel@tonic-gate 	packet->sport = 0;
6200Sstevel@tonic-gate 	packet->dport = 0;
6210Sstevel@tonic-gate 	find_ids(packet, mp);
6220Sstevel@tonic-gate 	packet->len = msgdsize(mp);
6230Sstevel@tonic-gate 	/* parse out TCP/UDP ports, if appropriate */
6240Sstevel@tonic-gate 	if ((packet->proto == IPPROTO_TCP) || (packet->proto == IPPROTO_UDP) ||
6250Sstevel@tonic-gate 	    (packet->proto == IPPROTO_SCTP)) {
6260Sstevel@tonic-gate 		get_port_info(packet, ipha, AF_INET, mp);
6270Sstevel@tonic-gate 	}
6280Sstevel@tonic-gate }
6290Sstevel@tonic-gate 
6300Sstevel@tonic-gate /*
6310Sstevel@tonic-gate  * parse_packet6(packet, mp)
6320Sstevel@tonic-gate  *
6330Sstevel@tonic-gate  * parses the message block into a ipgpc_packet_t structure for IPv6 traffic
6340Sstevel@tonic-gate  */
6350Sstevel@tonic-gate void
6360Sstevel@tonic-gate parse_packet6(ipgpc_packet_t *packet, mblk_t *mp)
6370Sstevel@tonic-gate {
6380Sstevel@tonic-gate 	ip6_t *ip6h = (ip6_t *)mp->b_rptr;
6390Sstevel@tonic-gate 
6400Sstevel@tonic-gate 	/* parse message block for IP header and ports */
6410Sstevel@tonic-gate 	bcopy(ip6h->ip6_src.s6_addr32, packet->saddr.s6_addr32,
6420Sstevel@tonic-gate 	    sizeof (ip6h->ip6_src.s6_addr32));
6430Sstevel@tonic-gate 	bcopy(ip6h->ip6_dst.s6_addr32, packet->daddr.s6_addr32,
6440Sstevel@tonic-gate 	    sizeof (ip6h->ip6_dst.s6_addr32));
6450Sstevel@tonic-gate 	/* Will be (re-)assigned in get_port_info */
6460Sstevel@tonic-gate 	packet->proto = ip6h->ip6_nxt;
6470Sstevel@tonic-gate 	packet->dsfield = __IPV6_TCLASS_FROM_FLOW(ip6h->ip6_vcf);
6480Sstevel@tonic-gate 	find_ids(packet, mp);
6490Sstevel@tonic-gate 	packet->len = msgdsize(mp);
6500Sstevel@tonic-gate 	packet->sport = 0;
6510Sstevel@tonic-gate 	packet->dport = 0;
6520Sstevel@tonic-gate 	/* Need to pullup everything. */
6530Sstevel@tonic-gate 	if (mp->b_cont != NULL) {
6540Sstevel@tonic-gate 		if (!pullupmsg(mp, -1)) {
6550Sstevel@tonic-gate 			ipgpc0dbg(("parse_packet6(): pullup error, can't " \
6560Sstevel@tonic-gate 			    "find ports"));
6570Sstevel@tonic-gate 			return;
6580Sstevel@tonic-gate 		}
6590Sstevel@tonic-gate 		ip6h = (ip6_t *)mp->b_rptr;
6600Sstevel@tonic-gate 	}
6610Sstevel@tonic-gate 	get_port_info(packet, ip6h, AF_INET6, mp);
6620Sstevel@tonic-gate }
6630Sstevel@tonic-gate 
6640Sstevel@tonic-gate #ifdef	IPGPC_DEBUG
6650Sstevel@tonic-gate /*
6660Sstevel@tonic-gate  * print_packet(af, packet)
6670Sstevel@tonic-gate  *
6680Sstevel@tonic-gate  * prints the contents of the packet structure for specified address family
6690Sstevel@tonic-gate  */
6700Sstevel@tonic-gate void
6710Sstevel@tonic-gate print_packet(int af, ipgpc_packet_t *pkt)
6720Sstevel@tonic-gate {
673*8485SPeter.Memishian@Sun.COM 	char saddrbuf[INET6_ADDRSTRLEN];
674*8485SPeter.Memishian@Sun.COM 	char daddrbuf[INET6_ADDRSTRLEN];
675*8485SPeter.Memishian@Sun.COM 
6760Sstevel@tonic-gate 	if (af == AF_INET) {
677*8485SPeter.Memishian@Sun.COM 		(void) inet_ntop(af, &V4_PART_OF_V6(pkt->saddr), saddrbuf,
678*8485SPeter.Memishian@Sun.COM 		    sizeof (saddrbuf));
679*8485SPeter.Memishian@Sun.COM 		(void) inet_ntop(af, &V4_PART_OF_V6(pkt->daddr), daddrbuf,
680*8485SPeter.Memishian@Sun.COM 		    sizeof (daddrbuf));
681*8485SPeter.Memishian@Sun.COM 
6820Sstevel@tonic-gate 		ipgpc4dbg(("print_packet: saddr = %s, daddr = %s, sport = %u" \
6830Sstevel@tonic-gate 		    ", dport = %u, proto = %u, dsfield = %x, uid = %d," \
684*8485SPeter.Memishian@Sun.COM 		    " if_index = %d, projid = %d, direction = %d", saddrbuf,
685*8485SPeter.Memishian@Sun.COM 		    daddrbuf, ntohs(pkt->sport), ntohs(pkt->dport), pkt->proto,
6860Sstevel@tonic-gate 		    pkt->dsfield, pkt->uid, pkt->if_index,
6870Sstevel@tonic-gate 		    pkt->projid, pkt->direction));
6880Sstevel@tonic-gate 	} else if (af == AF_INET6) {
689*8485SPeter.Memishian@Sun.COM 		(void) inet_ntop(af, pkt->saddr.s6_addr32, saddrbuf,
690*8485SPeter.Memishian@Sun.COM 		    sizeof (saddrbuf));
691*8485SPeter.Memishian@Sun.COM 		(void) inet_ntop(af, pkt->daddr.s6_addr32, daddrbuf,
692*8485SPeter.Memishian@Sun.COM 		    sizeof (daddrbuf));
693*8485SPeter.Memishian@Sun.COM 
6940Sstevel@tonic-gate 		ipgpc4dbg(("print_packet: saddr = %s, daddr = %s, sport = %u" \
6950Sstevel@tonic-gate 		    ", dport = %u, proto = %u, dsfield = %x, uid = %d," \
696*8485SPeter.Memishian@Sun.COM 		    " if_index = %d, projid = %d, direction = %d", saddrbuf,
697*8485SPeter.Memishian@Sun.COM 		    daddrbuf, ntohs(pkt->sport), ntohs(pkt->dport), pkt->proto,
6980Sstevel@tonic-gate 		    pkt->dsfield, pkt->uid, pkt->if_index,
6990Sstevel@tonic-gate 		    pkt->projid, pkt->direction));
7000Sstevel@tonic-gate 	}
7010Sstevel@tonic-gate }
7020Sstevel@tonic-gate #endif /* IPGPC_DEBUG */
703