flowattr.c revision 801093905f15f0f1a50095474e8a3f0e5b0cb126
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * CDDL HEADER START
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * The contents of this file are subject to the terms of the
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Common Development and Distribution License (the "License").
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * You may not use this file except in compliance with the License.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * or http://www.opensolaris.org/os/licensing.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * See the License for the specific language governing permissions
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * and limitations under the License.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * When distributing Covered Code, include this CDDL HEADER in each
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * If applicable, add the following below this CDDL HEADER, with the
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * fields enclosed by brackets "[]" replaced with your own identifying
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * information: Portions Copyright [yyyy] [name of copyright owner]
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * CDDL HEADER END
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
801093905f15f0f1a50095474e8a3f0e5b0cb126Michael Lim * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <errno.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <stdlib.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <strings.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <sys/mac_flow.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <sys/types.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <sys/socket.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <netinet/in.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <arpa/inet.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <netdb.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <net/if_types.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <net/if_dl.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <inet/ip.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <inet/ip6.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <libdladm.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <libdlflow.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#include <libdlflow_impl.h>
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/* max port number for UDP, TCP & SCTP */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#define MAX_PORT 65535
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic fad_checkf_t do_check_local_ip;
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic fad_checkf_t do_check_remote_ip;
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic fad_checkf_t do_check_protocol;
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic fad_checkf_t do_check_local_port;
25ec3e3dd27cc1038c10efa18ed08f064eab5fbeEric Chengstatic fad_checkf_t do_check_remote_port;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic dladm_status_t do_check_port(char *, boolean_t, flow_desc_t *);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic fattr_desc_t attr_table[] = {
25ec3e3dd27cc1038c10efa18ed08f064eab5fbeEric Cheng { "local_ip", do_check_local_ip },
25ec3e3dd27cc1038c10efa18ed08f064eab5fbeEric Cheng { "remote_ip", do_check_remote_ip },
25ec3e3dd27cc1038c10efa18ed08f064eab5fbeEric Cheng { "transport", do_check_protocol },
25ec3e3dd27cc1038c10efa18ed08f064eab5fbeEric Cheng { "local_port", do_check_local_port },
25ec3e3dd27cc1038c10efa18ed08f064eab5fbeEric Cheng { "remote_port", do_check_remote_port },
25ec3e3dd27cc1038c10efa18ed08f064eab5fbeEric Cheng { "dsfield", do_check_dsfield },
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng};
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng#define DLADM_MAX_FLOWATTRS (sizeof (attr_table) / sizeof (fattr_desc_t))
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic dladm_status_t
da14cebe459d3275048785f25bd869cb09b5307fEric Chengdo_check_local_ip(char *attr_val, flow_desc_t *fdesc)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (do_check_ip_addr(attr_val, B_TRUE, fdesc));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic dladm_status_t
da14cebe459d3275048785f25bd869cb09b5307fEric Chengdo_check_remote_ip(char *attr_val, flow_desc_t *fdesc)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (do_check_ip_addr(attr_val, B_FALSE, fdesc));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengdladm_status_t
da14cebe459d3275048785f25bd869cb09b5307fEric Chengdo_check_ip_addr(char *addr_str, boolean_t local, flow_desc_t *fd)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng dladm_status_t status;
da0006029e69465355313f503741ac6ebe0d513bGirish Moodalbail int prefix_max, prefix_len = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng char *prefix_str, *endp = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng flow_mask_t mask;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng in6_addr_t *addr;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng uchar_t *netmask;
da0006029e69465355313f503741ac6ebe0d513bGirish Moodalbail struct in_addr v4addr;
da0006029e69465355313f503741ac6ebe0d513bGirish Moodalbail struct in6_addr v6addr;
da0006029e69465355313f503741ac6ebe0d513bGirish Moodalbail int family;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if ((prefix_str = strchr(addr_str, '/')) != NULL) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *prefix_str++ = '\0';
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng errno = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng prefix_len = (int)strtol(prefix_str, &endp, 10);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (errno != 0 || prefix_len == 0 || *endp != '\0')
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (DLADM_STATUS_INVALID_PREFIXLEN);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da0006029e69465355313f503741ac6ebe0d513bGirish Moodalbail if (inet_pton(AF_INET, addr_str, &v4addr.s_addr) == 1) {
da0006029e69465355313f503741ac6ebe0d513bGirish Moodalbail family = AF_INET;
da0006029e69465355313f503741ac6ebe0d513bGirish Moodalbail } else if (inet_pton(AF_INET6, addr_str, v6addr.s6_addr) == 1) {
da0006029e69465355313f503741ac6ebe0d513bGirish Moodalbail family = AF_INET6;
da0006029e69465355313f503741ac6ebe0d513bGirish Moodalbail } else {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (DLADM_STATUS_INVALID_IP);
da0006029e69465355313f503741ac6ebe0d513bGirish Moodalbail }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mask = FLOW_IP_VERSION;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (local) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mask |= FLOW_IP_LOCAL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng addr = &fd->fd_local_addr;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng netmask = (uchar_t *)&fd->fd_local_netmask;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng } else {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mask |= FLOW_IP_REMOTE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng addr = &fd->fd_remote_addr;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng netmask = (uchar_t *)&fd->fd_remote_netmask;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da0006029e69465355313f503741ac6ebe0d513bGirish Moodalbail if (family == AF_INET) {
da0006029e69465355313f503741ac6ebe0d513bGirish Moodalbail IN6_INADDR_TO_V4MAPPED(&v4addr, addr);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng prefix_max = IP_ABITS;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng fd->fd_ipversion = IPV4_VERSION;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng netmask = (uchar_t *)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng &(V4_PART_OF_V6((*((in6_addr_t *)(void *)netmask))));
da0006029e69465355313f503741ac6ebe0d513bGirish Moodalbail } else {
da0006029e69465355313f503741ac6ebe0d513bGirish Moodalbail *addr = v6addr;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng prefix_max = IPV6_ABITS;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng fd->fd_ipversion = IPV6_VERSION;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (prefix_len == 0)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng prefix_len = prefix_max;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng status = dladm_prefixlen2mask(prefix_len, prefix_max, netmask);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (status != DLADM_STATUS_OK) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (DLADM_STATUS_INVALID_PREFIXLEN);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng fd->fd_mask |= mask;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (DLADM_STATUS_OK);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengdladm_status_t
da14cebe459d3275048785f25bd869cb09b5307fEric Chengdo_check_protocol(char *attr_val, flow_desc_t *fdesc)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng uint8_t protocol;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng protocol = dladm_str2proto(attr_val);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (protocol != 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng fdesc->fd_mask |= FLOW_IP_PROTOCOL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng fdesc->fd_protocol = protocol;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (DLADM_STATUS_OK);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng } else {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (DLADM_STATUS_INVALID_PROTOCOL);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengdladm_status_t
da14cebe459d3275048785f25bd869cb09b5307fEric Chengdo_check_local_port(char *attr_val, flow_desc_t *fdesc)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (do_check_port(attr_val, B_TRUE, fdesc));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
25ec3e3dd27cc1038c10efa18ed08f064eab5fbeEric Chengdladm_status_t
25ec3e3dd27cc1038c10efa18ed08f064eab5fbeEric Chengdo_check_remote_port(char *attr_val, flow_desc_t *fdesc)
25ec3e3dd27cc1038c10efa18ed08f064eab5fbeEric Cheng{
25ec3e3dd27cc1038c10efa18ed08f064eab5fbeEric Cheng return (do_check_port(attr_val, B_FALSE, fdesc));
25ec3e3dd27cc1038c10efa18ed08f064eab5fbeEric Cheng}
25ec3e3dd27cc1038c10efa18ed08f064eab5fbeEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengdladm_status_t
da14cebe459d3275048785f25bd869cb09b5307fEric Chengdo_check_port(char *attr_val, boolean_t local, flow_desc_t *fdesc)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng char *endp = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng long val;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
25ec3e3dd27cc1038c10efa18ed08f064eab5fbeEric Cheng val = strtol(attr_val, &endp, 10);
25ec3e3dd27cc1038c10efa18ed08f064eab5fbeEric Cheng if (val < 1 || val > MAX_PORT || *endp != '\0')
25ec3e3dd27cc1038c10efa18ed08f064eab5fbeEric Cheng return (DLADM_STATUS_INVALID_PORT);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (local) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng fdesc->fd_mask |= FLOW_ULP_PORT_LOCAL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng fdesc->fd_local_port = htons((uint16_t)val);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng } else {
25ec3e3dd27cc1038c10efa18ed08f064eab5fbeEric Cheng fdesc->fd_mask |= FLOW_ULP_PORT_REMOTE;
25ec3e3dd27cc1038c10efa18ed08f064eab5fbeEric Cheng fdesc->fd_remote_port = htons((uint16_t)val);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (DLADM_STATUS_OK);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Check for invalid and/or duplicate attribute specification
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengstatic dladm_status_t
da14cebe459d3275048785f25bd869cb09b5307fEric Chengflow_attrlist_check(dladm_arg_list_t *attrlist)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng int i, j;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng boolean_t isset[DLADM_MAX_FLOWATTRS];
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng boolean_t matched;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng for (j = 0; j < DLADM_MAX_FLOWATTRS; j++)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng isset[j] = B_FALSE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng for (i = 0; i < attrlist->al_count; i++) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng matched = B_FALSE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng for (j = 0; j < DLADM_MAX_FLOWATTRS; j++) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (strcmp(attrlist->al_info[i].ai_name,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng attr_table[j].ad_name) == 0) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (isset[j])
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (DLADM_STATUS_FLOW_INCOMPATIBLE);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng else
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng isset[j] = B_TRUE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng matched = B_TRUE;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng /*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * if the attribute did not match any of the attribute in
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * attr_table, then it's an invalid attribute.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (!matched)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (DLADM_STATUS_BADARG);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (DLADM_STATUS_OK);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng/*
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * Convert an attribute list to a flow_desc_t using the attribute ad_check()
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng * functions.
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng */
da14cebe459d3275048785f25bd869cb09b5307fEric Chengdladm_status_t
da14cebe459d3275048785f25bd869cb09b5307fEric Chengdladm_flow_attrlist_extract(dladm_arg_list_t *attrlist, flow_desc_t *flowdesc)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng dladm_status_t status = DLADM_STATUS_BADARG;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng int i;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng for (i = 0; i < attrlist->al_count; i++) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng dladm_arg_info_t *aip = &attrlist->al_info[i];
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng int j;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng for (j = 0; j < DLADM_MAX_FLOWATTRS; j++) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng fattr_desc_t *adp = &attr_table[j];
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (strcasecmp(aip->ai_name, adp->ad_name) != 0)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng continue;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if ((aip->ai_val == NULL) || (*aip->ai_val == NULL))
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (DLADM_STATUS_BADARG);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (adp->ad_check != NULL)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng status = adp->ad_check(*aip->ai_val, flowdesc);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng else
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng status = DLADM_STATUS_BADARG;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (status != DLADM_STATUS_OK)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (status);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
801093905f15f0f1a50095474e8a3f0e5b0cb126Michael Lim
801093905f15f0f1a50095474e8a3f0e5b0cb126Michael Lim /*
801093905f15f0f1a50095474e8a3f0e5b0cb126Michael Lim * Make sure protocol is specified if either local or
801093905f15f0f1a50095474e8a3f0e5b0cb126Michael Lim * remote port is specified.
801093905f15f0f1a50095474e8a3f0e5b0cb126Michael Lim */
801093905f15f0f1a50095474e8a3f0e5b0cb126Michael Lim if ((flowdesc->fd_mask &
801093905f15f0f1a50095474e8a3f0e5b0cb126Michael Lim (FLOW_ULP_PORT_LOCAL | FLOW_ULP_PORT_REMOTE)) != 0 &&
801093905f15f0f1a50095474e8a3f0e5b0cb126Michael Lim (flowdesc->fd_mask & FLOW_IP_PROTOCOL) == 0)
801093905f15f0f1a50095474e8a3f0e5b0cb126Michael Lim return (DLADM_STATUS_PORT_NOPROTO);
801093905f15f0f1a50095474e8a3f0e5b0cb126Michael Lim
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (status);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvoid
da14cebe459d3275048785f25bd869cb09b5307fEric Chengdladm_free_attrs(dladm_arg_list_t *list)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng dladm_free_args(list);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengdladm_status_t
da14cebe459d3275048785f25bd869cb09b5307fEric Chengdladm_parse_flow_attrs(char *str, dladm_arg_list_t **listp, boolean_t novalues)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (dladm_parse_args(str, listp, novalues)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng != DLADM_STATUS_OK)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (DLADM_STATUS_ATTR_PARSE_ERR);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
63a6526d84bd7ea2c75b4b0d009fa5f51a67a22aMichael Lim if (*listp != NULL && flow_attrlist_check(*listp)
63a6526d84bd7ea2c75b4b0d009fa5f51a67a22aMichael Lim != DLADM_STATUS_OK) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng dladm_free_attrs(*listp);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (DLADM_STATUS_ATTR_PARSE_ERR);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (DLADM_STATUS_OK);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengdladm_status_t
da14cebe459d3275048785f25bd869cb09b5307fEric Chengdo_check_dsfield(char *str, flow_desc_t *fd)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng char *mask_str, *endp = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng uint_t mask = 0xff, value;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if ((mask_str = strchr(str, ':')) != NULL) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *mask_str++ = '\0';
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng errno = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng mask = strtoul(mask_str, &endp, 16);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (errno != 0 || mask == 0 || mask > 0xff ||
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng *endp != '\0')
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (DLADM_STATUS_INVALID_DSFMASK);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng errno = 0;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng endp = NULL;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng value = strtoul(str, &endp, 16);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (errno != 0 || value == 0 || value > 0xff || *endp != '\0')
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (DLADM_STATUS_INVALID_DSF);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng fd->fd_dsfield = (uint8_t)value;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng fd->fd_dsfield_mask = (uint8_t)mask;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng fd->fd_mask |= FLOW_IP_DSFIELD;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (DLADM_STATUS_OK);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengchar *
da14cebe459d3275048785f25bd869cb09b5307fEric Chengdladm_proto2str(uint8_t protocol)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (protocol == IPPROTO_TCP)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return ("tcp");
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (protocol == IPPROTO_UDP)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return ("udp");
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (protocol == IPPROTO_SCTP)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return ("sctp");
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (protocol == IPPROTO_ICMPV6)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return ("icmpv6");
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (protocol == IPPROTO_ICMP)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return ("icmp");
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng else
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return ("");
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chenguint8_t
da14cebe459d3275048785f25bd869cb09b5307fEric Chengdladm_str2proto(const char *protostr)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (strncasecmp(protostr, "tcp", 3) == 0)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (IPPROTO_TCP);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng else if (strncasecmp(protostr, "udp", 3) == 0)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (IPPROTO_UDP);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng else if (strncasecmp(protostr, "sctp", 4) == 0)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (IPPROTO_SCTP);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng else if (strncasecmp(protostr, "icmpv6", 6) == 0)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (IPPROTO_ICMPV6);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng else if (strncasecmp(protostr, "icmp", 4) == 0)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (IPPROTO_ICMP);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng return (0);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvoid
da14cebe459d3275048785f25bd869cb09b5307fEric Chengdladm_flow_attr_ip2str(dladm_flow_attr_t *attrp, char *buf, size_t buf_len)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng flow_desc_t fdesc = attrp->fa_flow_desc;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng struct in_addr ipaddr;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng int prefix_len, prefix_max;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng char *cp, abuf[INET6_ADDRSTRLEN];
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (fdesc.fd_mask & FLOW_IP_LOCAL) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (fdesc.fd_ipversion == IPV6_VERSION) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) inet_ntop(AF_INET6, &fdesc.fd_local_addr, abuf,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng INET6_ADDRSTRLEN);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cp = abuf;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng prefix_max = IPV6_ABITS;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng } else {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ipaddr.s_addr = fdesc.fd_local_addr._S6_un._S6_u32[3];
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cp = inet_ntoa(ipaddr);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng prefix_max = IP_ABITS;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) dladm_mask2prefixlen(&fdesc.fd_local_netmask,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng prefix_max, &prefix_len);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) snprintf(buf, buf_len, "LCL:%s/%d ", cp, prefix_len);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng } else if (fdesc.fd_mask & FLOW_IP_REMOTE) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (fdesc.fd_ipversion == IPV6_VERSION) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) inet_ntop(AF_INET6, &fdesc.fd_remote_addr, abuf,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng INET6_ADDRSTRLEN);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cp = abuf;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng prefix_max = IPV6_ABITS;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng } else {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ipaddr.s_addr = fdesc.fd_remote_addr._S6_un._S6_u32[3];
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng cp = inet_ntoa(ipaddr);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng prefix_max = IP_ABITS;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) dladm_mask2prefixlen(&fdesc.fd_remote_netmask,
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng prefix_max, &prefix_len);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) snprintf(buf, buf_len, "RMT:%s/%d ", cp, prefix_len);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng } else {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng buf[0] = '\0';
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvoid
da14cebe459d3275048785f25bd869cb09b5307fEric Chengdladm_flow_attr_proto2str(dladm_flow_attr_t *attrp, char *buf, size_t buf_len)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng flow_desc_t fdesc = attrp->fa_flow_desc;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) snprintf(buf, buf_len, "%s",
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng dladm_proto2str(fdesc.fd_protocol));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvoid
da14cebe459d3275048785f25bd869cb09b5307fEric Chengdladm_flow_attr_port2str(dladm_flow_attr_t *attrp, char *buf, size_t buf_len)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng flow_desc_t fdesc = attrp->fa_flow_desc;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (fdesc.fd_mask & FLOW_ULP_PORT_LOCAL) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) snprintf(buf, buf_len, "%d",
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng ntohs(fdesc.fd_local_port));
25ec3e3dd27cc1038c10efa18ed08f064eab5fbeEric Cheng } else if (fdesc.fd_mask & FLOW_ULP_PORT_REMOTE) {
25ec3e3dd27cc1038c10efa18ed08f064eab5fbeEric Cheng (void) snprintf(buf, buf_len, "%d",
25ec3e3dd27cc1038c10efa18ed08f064eab5fbeEric Cheng ntohs(fdesc.fd_remote_port));
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng } else {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng buf[0] = '\0';
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Chengvoid
da14cebe459d3275048785f25bd869cb09b5307fEric Chengdladm_flow_attr_dsfield2str(dladm_flow_attr_t *attrp, char *buf, size_t buf_len)
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng{
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng flow_desc_t fdesc = attrp->fa_flow_desc;
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng if (fdesc.fd_mask & FLOW_IP_DSFIELD) {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng (void) snprintf(buf, buf_len, "0x%x:0x%x",
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng fdesc.fd_dsfield, fdesc.fd_dsfield_mask);
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng } else {
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng buf[0] = '\0';
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng }
da14cebe459d3275048785f25bd869cb09b5307fEric Cheng}