/*
 * print_packet(af, packet)
 *
 * prints the contents of the packet structure for specified address family
 */
void
print_packet(int af, ipgpc_packet_t *pkt)
{
	char saddrbuf[INET6_ADDRSTRLEN];
	char daddrbuf[INET6_ADDRSTRLEN];

	if (af == AF_INET) {
		(void) inet_ntop(af, &V4_PART_OF_V6(pkt->saddr), saddrbuf,
		    sizeof (saddrbuf));
		(void) inet_ntop(af, &V4_PART_OF_V6(pkt->daddr), daddrbuf,
		    sizeof (daddrbuf));

		ipgpc4dbg(("print_packet: saddr = %s, daddr = %s, sport = %u" \
		    ", dport = %u, proto = %u, dsfield = %x, uid = %d," \
		    " if_index = %d, projid = %d, direction = %d", saddrbuf,
		    daddrbuf, ntohs(pkt->sport), ntohs(pkt->dport), pkt->proto,
		    pkt->dsfield, pkt->uid, pkt->if_index,
		    pkt->projid, pkt->direction));
	} else if (af == AF_INET6) {
		(void) inet_ntop(af, pkt->saddr.s6_addr32, saddrbuf,
		    sizeof (saddrbuf));
		(void) inet_ntop(af, pkt->daddr.s6_addr32, daddrbuf,
		    sizeof (daddrbuf));

		ipgpc4dbg(("print_packet: saddr = %s, daddr = %s, sport = %u" \
		    ", dport = %u, proto = %u, dsfield = %x, uid = %d," \
		    " if_index = %d, projid = %d, direction = %d", saddrbuf,
		    daddrbuf, ntohs(pkt->sport), ntohs(pkt->dport), pkt->proto,
		    pkt->dsfield, pkt->uid, pkt->if_index,
		    pkt->projid, pkt->direction));
	}
}
Example #2
0
/*
 * Print an IPv4 address and port number in a compact and easy to read format
 * The arguments are in network byte order
 */
static void
net_ipv4addrport_pr(const in6_addr_t *nipv6addr, in_port_t nport)
{
	uint32_t naddr = V4_PART_OF_V6((*nipv6addr));

	mdb_nhconvert(&nport, &nport, sizeof (nport));
	mdb_printf("%*I.%-5hu", ADDR_V4_WIDTH, naddr, nport);
}
/*
 * parse_packet(packet, mp)
 *
 * parses the given message block into a ipgpc_packet_t structure
 */
void
parse_packet(ipgpc_packet_t *packet, mblk_t *mp)
{
	ipha_t	*ipha;

	/* parse message block for IP header and ports */
	ipha = (ipha_t *)mp->b_rptr; /* get ip header */
	V4_PART_OF_V6(packet->saddr) = (int32_t)ipha->ipha_src;
	V4_PART_OF_V6(packet->daddr) = (int32_t)ipha->ipha_dst;
	packet->dsfield = ipha->ipha_type_of_service;
	packet->proto = ipha->ipha_protocol;
	packet->sport = 0;
	packet->dport = 0;
	find_ids(packet, mp);
	packet->len = msgdsize(mp);
	/* parse out TCP/UDP ports, if appropriate */
	if ((packet->proto == IPPROTO_TCP) || (packet->proto == IPPROTO_UDP) ||
	    (packet->proto == IPPROTO_SCTP)) {
		get_port_info(packet, ipha, AF_INET, mp);
	}
}
Example #4
0
dladm_status_t
do_check_ip_addr(char *addr_str, boolean_t local, flow_desc_t *fd)
{
	dladm_status_t	status;
	int		prefix_max, prefix_len = 0;
	char		*prefix_str, *endp = NULL;
	flow_mask_t	mask;
	in6_addr_t	*addr;
	uchar_t		*netmask;
	struct in_addr	v4addr;
	struct in6_addr	v6addr;
	int		family;

	if ((prefix_str = strchr(addr_str, '/')) != NULL) {
		*prefix_str++ = '\0';
		errno = 0;
		prefix_len = (int)strtol(prefix_str, &endp, 10);
		if (errno != 0 || prefix_len == 0 || *endp != '\0')
			return (DLADM_STATUS_INVALID_PREFIXLEN);
	}
	if (inet_pton(AF_INET, addr_str, &v4addr.s_addr) == 1) {
		family = AF_INET;
	} else if (inet_pton(AF_INET6, addr_str, v6addr.s6_addr) == 1) {
		family = AF_INET6;
	} else {
		return (DLADM_STATUS_INVALID_IP);
	}

	mask = FLOW_IP_VERSION;
	if (local) {
		mask |= FLOW_IP_LOCAL;
		addr = &fd->fd_local_addr;
		netmask = (uchar_t *)&fd->fd_local_netmask;
	} else {
		mask |= FLOW_IP_REMOTE;
		addr = &fd->fd_remote_addr;
		netmask = (uchar_t *)&fd->fd_remote_netmask;
	}

	if (family == AF_INET) {
		IN6_INADDR_TO_V4MAPPED(&v4addr, addr);
		prefix_max = IP_ABITS;
		fd->fd_ipversion = IPV4_VERSION;
		netmask = (uchar_t *)
		    &(V4_PART_OF_V6((*((in6_addr_t *)(void *)netmask))));
	} else {
		*addr = v6addr;
		prefix_max = IPV6_ABITS;
		fd->fd_ipversion = IPV6_VERSION;
	}

	if (prefix_len == 0)
		prefix_len = prefix_max;

	status = dladm_prefixlen2mask(prefix_len, prefix_max, netmask);

	if (status != DLADM_STATUS_OK) {
		return (DLADM_STATUS_INVALID_PREFIXLEN);
	}

	fd->fd_mask |= mask;
	return (DLADM_STATUS_OK);
}
/*
 * ipgpc_classify(af, packet)
 *
 * The function that drives the packet classification algorithm.  Given a
 * address family (either AF_INET or AF_INET6) the input packet structure
 * is matched against all the selector structures.  For each search of
 * a selector structure, all matched filters are collected.  Once all
 * selectors are searched, the best match of all matched filters is
 * determined.  Finally, the class associated with the best matching filter
 * is returned.  If no filters were matched, the default class is returned.
 * If a memory error occurred, NULL is returned.
 */
ipgpc_class_t *
ipgpc_classify(int af, ipgpc_packet_t *packet)
{
	int match_status;
	uint16_t slctrs_srchd;
	int class_id;
	ht_match_t fid_table[HASH_SIZE];
	ht_match_t *p, *q;
	int i;
	int rc;

	if (ipgpc_num_fltrs == 0) {
		/* zero filters are loaded, return default class */
		update_stats(ipgpc_def_class_id, packet->len);
		/*
		 * no need to free fid_table. Since zero selectors were
		 * searched and dynamic memory wasn't allocated.
		 */
		return (&ipgpc_cid_list[ipgpc_def_class_id].aclass);
	}

	match_status = 0;
	slctrs_srchd = ALL_MATCH_MASK;
	bzero(fid_table, sizeof (ht_match_t) * HASH_SIZE);

	/* first search all address family independent selectors */
	rc = common_classify(packet, fid_table, &slctrs_srchd);
	if (rc != NORMAL_MATCH) {
		/* free all dynamic allocated memory */
		FREE_FID_TABLE(fid_table, p, q, i);
		if (rc == NO_MATCHES) {
			update_stats(ipgpc_def_class_id, packet->len);
			return (&ipgpc_cid_list[ipgpc_def_class_id].aclass);
		} else {	/* memory error */
			return (NULL);
		}
	}

	switch (af) {		/* switch off of address family */
	case AF_INET:
		/* Find on IPv4 Source Address field */
		match_status = ipgpc_findfilters(IPGPC_TRIE_SADDRID,
		    V4_PART_OF_V6(packet->saddr), fid_table);
		if (CHECK_MATCH_STATUS(match_status, &slctrs_srchd,
		    ipgpc_trie_list[IPGPC_TRIE_SADDRID].info.mask)
		    != NORMAL_MATCH) {
			/* free all dynamic allocated memory */
			FREE_FID_TABLE(fid_table, p, q, i);
			if (match_status == NO_MATCHES) {
				update_stats(ipgpc_def_class_id, packet->len);
				return (&ipgpc_cid_list[ipgpc_def_class_id].
				    aclass);
			} else { /* memory error */
				return (NULL);
			}
		}
		/* Find on IPv4 Destination Address field */
		match_status = ipgpc_findfilters(IPGPC_TRIE_DADDRID,
		    V4_PART_OF_V6(packet->daddr), fid_table);
		if (CHECK_MATCH_STATUS(match_status, &slctrs_srchd,
		    ipgpc_trie_list[IPGPC_TRIE_DADDRID].info.mask)
		    != NORMAL_MATCH) {
			/* free all dynamic allocated memory */
			FREE_FID_TABLE(fid_table, p, q, i);
			if (match_status == NO_MATCHES) {
				update_stats(ipgpc_def_class_id, packet->len);
				return (&ipgpc_cid_list[ipgpc_def_class_id].
				    aclass);
			} else { /* memory error */
				return (NULL);
			}
		}
		break;
	case AF_INET6:
		/* Find on IPv6 Source Address field */
		match_status = ipgpc_findfilters6(IPGPC_TRIE_SADDRID6,
		    packet->saddr, fid_table);
		if (CHECK_MATCH_STATUS(match_status, &slctrs_srchd,
		    ipgpc_trie_list[IPGPC_TRIE_SADDRID6].info.mask)
		    != NORMAL_MATCH) {
			/* free all dynamic allocated memory */
			FREE_FID_TABLE(fid_table, p, q, i);
			if (match_status == NO_MATCHES) {
				update_stats(ipgpc_def_class_id, packet->len);
				return (&ipgpc_cid_list[ipgpc_def_class_id].
				    aclass);
			} else { /* memory error */
				return (NULL);
			}
		}
		/* Find on IPv6 Destination Address field */
		match_status = ipgpc_findfilters6(IPGPC_TRIE_DADDRID6,
		    packet->daddr, fid_table);
		if (CHECK_MATCH_STATUS(match_status, &slctrs_srchd,
		    ipgpc_trie_list[IPGPC_TRIE_DADDRID6].info.mask)
		    != NORMAL_MATCH) {
			/* free all dynamic allocated memory */
			FREE_FID_TABLE(fid_table, p, q, i);
			if (match_status == NO_MATCHES) {
				update_stats(ipgpc_def_class_id, packet->len);
				return (&ipgpc_cid_list[ipgpc_def_class_id].
				    aclass);
			} else {
				return (NULL);
			}
		}
		break;
	default:
		ipgpc0dbg(("ipgpc_classify(): Unknown Address Family"));
		/* free all dynamic allocated memory */
		FREE_FID_TABLE(fid_table, p, q, i);
		return (NULL);
	}

	/* zero selectors were searched, return default */
	if (slctrs_srchd == 0) {
		/*
		 * no need to free fid_table.  Since zero selectors were
		 * searched and dynamic memory wasn't allocated
		 */
		update_stats(ipgpc_def_class_id, packet->len);
		return (&ipgpc_cid_list[ipgpc_def_class_id].aclass);
	}

	/* Perform best match search */
	class_id = bestmatch(fid_table, slctrs_srchd);
	/* free all dynamic allocated memory */
	FREE_FID_TABLE(fid_table, p, q, i);

	update_stats(class_id, packet->len);
	return (&ipgpc_cid_list[class_id].aclass);
}