/* * 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)); } }
/* * 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); } }
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); }