libnwam_interface_type_t find_if_type(const char *name) { uint32_t media; libnwam_interface_type_t type; if (name == NULL) { dprintf("find_if_type: no ifname; returning IF_UNKNOWN"); return (IF_UNKNOWN); } type = IF_WIRED; if (dladm_name2info(dld_handle, name, NULL, NULL, NULL, &media) != DLADM_STATUS_OK) { if (strncmp(name, "ip.tun", 6) == 0 || strncmp(name, "ip6.tun", 7) == 0 || strncmp(name, "ip.6to4tun", 10) == 0) /* * We'll need to update our tunnel detection once * the clearview/tun project is integrated; tunnel * names won't necessarily be ip.tunN. */ type = IF_TUN; } else if (media == DL_WIFI) { type = IF_WIRELESS; } return (type); }
int delete_etherstub( char* name, int temporary ) { datalink_id_t linkid; dladm_status_t status; //indicates whether should be removed temporary or persistently uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; if( temporary != 0 ){ flags &= ~DLADM_OPT_PERSIST; } status = dladm_name2info(handle, name, &linkid, NULL, NULL, NULL); if (status != DLADM_STATUS_OK) return XBOW_STATUS_INVALID_NAME; status = dladm_vnic_delete(handle, linkid, flags); if (status != DLADM_STATUS_OK) return XBOW_STATUS_OPERATION_FAILURE; return XBOW_STATUS_OK; }
vlan_infos_t* get_vlan_infos() { char* links; int links_len = 0; dladm_walk_datalink_id( &count_links, handle, &links_len, DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST ); char* links_it = links = malloc( links_len * MAXLINKNAMELEN ); dladm_walk_datalink_id( &collect_link_names, handle, &links_it, DATALINK_CLASS_VLAN, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST ); vlan_infos_t* infos = malloc_vlan_infos( links_len ); infos->len = links_len; for ( int i = 0; i < links_len; ++i ) { char* name = links + i * MAXLINKNAMELEN; datalink_id_t vlanid = { 0 }; dladm_vlan_attr_t vinfo; char parent[ MAXLINKNAMELEN ] = { 0 }; strcpy( infos->vlan_infos[ i ]->name, name ); if ( DLADM_STATUS_OK != dladm_name2info( handle, name, &vlanid, NULL, NULL, NULL ) ) { } else { dladm_vlan_info( handle, vlanid, &vinfo, DLADM_OPT_ACTIVE ); if ( DLADM_STATUS_OK != dladm_datalink_id2info( handle, vinfo.dv_linkid, NULL, NULL, NULL, parent, sizeof( parent ) ) ) { } else { infos->vlan_infos[ i ]->tag = vinfo.dv_vid; strcpy( infos->vlan_infos[ i ]->link, parent ); } } } free( links ); return infos; }
int vlan_remove( char* name ) { datalink_id_t vlanid = { 0 }; dladm_status_t rc = { 0 }; if ( DLADM_STATUS_OK != dladm_name2info( handle, name, &vlanid, NULL, NULL, NULL ) ) { } else { rc = dladm_vlan_delete( handle, vlanid, DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST ); } return map_status( rc ); }
int vlan_create( vlan_info_t* info ) { dladm_status_t rc = { 0 }; dladm_arg_list_t* proplist = NULL; uint32_t flags = DLADM_OPT_ACTIVE | DLADM_OPT_PERSIST; datalink_id_t parentid, linkid; if ( DLADM_STATUS_OK != dladm_name2info( handle, info->link, &parentid, NULL, NULL, NULL ) ) { } else { rc = dladm_vlan_create( handle, info->name, parentid, ( uint16_t ) info->tag, proplist, flags, &linkid ); } return map_status( rc ); }
/* * ipmgmt_net_from_gz_init() initializes exclusive-IP stack non-global zones by * extracting configuration that has been saved in the kernel and applying * that information to the appropriate datalinks for the zone. If an ifname * argument is passed in, only the selected IP interface corresponding to * datalink will be initialized, otherwise all datalinks will be plumbed for IP * and IP address and route information will be configured. */ ipadm_status_t ipadm_init_net_from_gz(ipadm_handle_t iph, char *ifname, void (*persist_if)(char *, boolean_t, boolean_t)) { ngz_walk_data_t nwd; uint64_t flags; dladm_handle_t dlh = iph->iph_dlh; datalink_id_t linkid; if (iph->iph_zoneid == GLOBAL_ZONEID) return (IPADM_NOTSUP); if (ifname != NULL && i_ipadm_get_flags(iph, ifname, AF_INET, &flags) != IPADM_SUCCESS && i_ipadm_get_flags(iph, ifname, AF_INET6, &flags) != IPADM_SUCCESS) return (IPADM_ENXIO); if (ifname != NULL && !(flags & IFF_L3PROTECT)) return (IPADM_SUCCESS); /* nothing to initialize */ nwd.ngz_iph = iph; nwd.ngz_zoneid = iph->iph_zoneid; nwd.ngz_ifname = ifname; nwd.ngz_persist_if = persist_if; nwd.ngz_s10c = i_ipadm_zone_is_s10c(iph->iph_zoneid); nwd.ngz_ipstatus = IPADM_SUCCESS; if (ifname != NULL) { if (dladm_name2info(dlh, ifname, &linkid, NULL, NULL, NULL) != DLADM_STATUS_OK) { return (IPADM_ENXIO); } (void) i_ipadm_zone_network_attr(dlh, linkid, &nwd); } else { (void) dladm_walk_datalink_id(i_ipadm_zone_network_attr, dlh, &nwd, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, DLADM_OPT_PERSIST); } return (nwd.ngz_ipstatus); }
static void do_remove_flow(int argc, char *argv[]) { char option; char *flowname = NULL; char linkname[MAXLINKNAMELEN]; datalink_id_t linkid = DATALINK_ALL_LINKID; boolean_t l_arg = B_FALSE; remove_flow_state_t state; dladm_status_t status; bzero(&state, sizeof (state)); opterr = 0; while ((option = getopt_long(argc, argv, ":tR:l:", longopts, NULL)) != -1) { switch (option) { case 't': t_arg = B_TRUE; break; case 'R': altroot = optarg; break; case 'l': if (strlcpy(linkname, optarg, MAXLINKNAMELEN) >= MAXLINKNAMELEN) { die("link name too long"); } if (dladm_name2info(handle, linkname, &linkid, NULL, NULL, NULL) != DLADM_STATUS_OK) { die("invalid link '%s'", linkname); } l_arg = B_TRUE; break; default: die_opterr(optopt, option); break; } } /* when link not specified get flow name */ if (!l_arg) { if (optind != (argc-1)) { usage(); } else { if (strlen(argv[optind]) >= MAXFLOWNAMELEN) die("flow name too long"); flowname = argv[optind]; } status = dladm_flow_remove(handle, flowname, t_arg, altroot); } else { /* if link is specified then flow name should not be there */ if (optind == argc-1) usage(); /* walk the link to find flows and remove them */ state.fs_tempop = t_arg; state.fs_altroot = altroot; state.fs_status = DLADM_STATUS_OK; status = dladm_walk_flow(remove_flow, handle, linkid, &state, B_FALSE); /* * check if dladm_walk_flow terminated early and see if the * walker function as any status for us */ if (status == DLADM_STATUS_OK) status = state.fs_status; } if (status != DLADM_STATUS_OK) die_dlerr(status, "remove flow failed"); }
static void do_add_flow(int argc, char *argv[]) { char devname[MAXLINKNAMELEN]; char *name = NULL; uint_t index; datalink_id_t linkid; char option; boolean_t l_arg = B_FALSE; char propstr[DLADM_STRSIZE]; char attrstr[DLADM_STRSIZE]; dladm_arg_list_t *proplist = NULL; dladm_arg_list_t *attrlist = NULL; dladm_status_t status; bzero(propstr, DLADM_STRSIZE); bzero(attrstr, DLADM_STRSIZE); while ((option = getopt_long(argc, argv, "tR:l:a:p:", prop_longopts, NULL)) != -1) { switch (option) { case 't': t_arg = B_TRUE; break; case 'R': altroot = optarg; break; case 'l': if (strlcpy(devname, optarg, MAXLINKNAMELEN) >= MAXLINKNAMELEN) { die("link name too long"); } if (dladm_name2info(handle, devname, &linkid, NULL, NULL, NULL) != DLADM_STATUS_OK) die("invalid link '%s'", devname); l_arg = B_TRUE; break; case 'a': (void) strlcat(attrstr, optarg, DLADM_STRSIZE); if (strlcat(attrstr, ",", DLADM_STRSIZE) >= DLADM_STRSIZE) die("attribute list too long '%s'", attrstr); break; case 'p': (void) strlcat(propstr, optarg, DLADM_STRSIZE); if (strlcat(propstr, ",", DLADM_STRSIZE) >= DLADM_STRSIZE) die("property list too long '%s'", propstr); break; default: die_opterr(optopt, option); } } if (!l_arg) { die("link is required"); } opterr = 0; index = optind; if ((index != (argc - 1)) || match_attr(argv[index]) != NULL) { die("flow name is required"); } else { /* get flow name; required last argument */ if (strlen(argv[index]) >= MAXFLOWNAMELEN) die("flow name too long"); name = argv[index]; } if (dladm_parse_flow_attrs(attrstr, &attrlist, B_FALSE) != DLADM_STATUS_OK) die("invalid flow attribute specified"); if (dladm_parse_flow_props(propstr, &proplist, B_FALSE) != DLADM_STATUS_OK) die("invalid flow property specified"); status = dladm_flow_add(handle, linkid, attrlist, proplist, name, t_arg, altroot); if (status != DLADM_STATUS_OK) die_dlerr(status, "add flow failed"); dladm_free_attrs(attrlist); dladm_free_props(proplist); }
static void do_show_flowprop(int argc, char **argv) { int option; dladm_arg_list_t *proplist = NULL; show_flowprop_state_t state; char *fields_str = NULL; ofmt_handle_t ofmt; ofmt_status_t oferr; uint_t ofmtflags = 0; opterr = 0; state.fs_propvals = NULL; state.fs_line = NULL; state.fs_parsable = B_FALSE; state.fs_persist = B_FALSE; state.fs_header = B_TRUE; state.fs_retstatus = DLADM_STATUS_OK; state.fs_linkid = DATALINK_INVALID_LINKID; state.fs_flow = NULL; while ((option = getopt_long(argc, argv, ":p:cPl:o:", prop_longopts, NULL)) != -1) { switch (option) { case 'p': if (dladm_parse_flow_props(optarg, &proplist, B_TRUE) != DLADM_STATUS_OK) die("invalid flow properties specified"); break; case 'c': state.fs_parsable = B_TRUE; ofmtflags |= OFMT_PARSABLE; break; case 'P': state.fs_persist = B_TRUE; break; case 'l': if (dladm_name2info(handle, optarg, &state.fs_linkid, NULL, NULL, NULL) != DLADM_STATUS_OK) die("invalid link '%s'", optarg); break; case 'o': fields_str = optarg; break; default: die_opterr(optopt, option); break; } } if (optind == (argc - 1)) { if (strlen(argv[optind]) >= MAXFLOWNAMELEN) die("flow name too long"); state.fs_flow = argv[optind]; } else if (optind != argc) { usage(); } state.fs_proplist = proplist; state.fs_status = DLADM_STATUS_OK; oferr = ofmt_open(fields_str, flowprop_fields, ofmtflags, 0, &ofmt); flowadm_ofmt_check(oferr, state.fs_parsable, ofmt); state.fs_ofmt = ofmt; /* Show properties for one flow */ if (state.fs_flow != NULL) { show_flowprop_one_flow(&state, state.fs_flow); /* Show properties for all flows on one link */ } else if (state.fs_linkid != DATALINK_INVALID_LINKID) { (void) show_flowprop_onelink(handle, state.fs_linkid, &state); /* Show properties for all flows on all links */ } else { (void) dladm_walk_datalink_id(show_flowprop_onelink, handle, &state, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE); } dladm_free_props(proplist); ofmt_close(ofmt); }
static void do_show_flow(int argc, char *argv[]) { char flowname[MAXFLOWNAMELEN]; char linkname[MAXLINKNAMELEN]; datalink_id_t linkid = DATALINK_ALL_LINKID; int option; boolean_t s_arg = B_FALSE; boolean_t S_arg = B_FALSE; boolean_t i_arg = B_FALSE; boolean_t l_arg = B_FALSE; boolean_t o_arg = B_FALSE; uint32_t interval = 0; show_flow_state_t state; char *fields_str = NULL; ofmt_handle_t ofmt; ofmt_status_t oferr; uint_t ofmtflags = 0; bzero(&state, sizeof (state)); opterr = 0; while ((option = getopt_long(argc, argv, ":pPsSi:l:o:", longopts, NULL)) != -1) { switch (option) { case 'p': state.fs_parsable = B_TRUE; ofmtflags |= OFMT_PARSABLE; break; case 'P': state.fs_persist = B_TRUE; break; case 's': if (s_arg) die_optdup(option); s_arg = B_TRUE; break; case 'S': if (S_arg) die_optdup(option); S_arg = B_TRUE; break; case 'o': if (o_arg) die_optdup(option); o_arg = B_TRUE; fields_str = optarg; break; case 'i': if (i_arg) die_optdup(option); i_arg = B_TRUE; if (!dladm_str2interval(optarg, &interval)) die("invalid interval value '%s'", optarg); break; case 'l': if (strlcpy(linkname, optarg, MAXLINKNAMELEN) >= MAXLINKNAMELEN) die("link name too long\n"); if (dladm_name2info(handle, linkname, &linkid, NULL, NULL, NULL) != DLADM_STATUS_OK) die("invalid link '%s'", linkname); l_arg = B_TRUE; break; default: die_opterr(optopt, option); break; } } if (i_arg && !(s_arg || S_arg)) die("the -i option can be used only with -s or -S"); if (s_arg && S_arg) die("the -s option cannot be used with -S"); /* get flow name (optional last argument */ if (optind == (argc-1)) { if (strlcpy(flowname, argv[optind], MAXFLOWNAMELEN) >= MAXFLOWNAMELEN) die("flow name too long"); state.fs_flow = flowname; } if (S_arg) { dladm_continuous(handle, linkid, state.fs_flow, interval, FLOW_REPORT); return; } if (s_arg) { flow_stats(state.fs_flow, linkid, interval, fields_str, &state); return; } oferr = ofmt_open(fields_str, flow_fields, ofmtflags, 0, &ofmt); flowadm_ofmt_check(oferr, state.fs_parsable, ofmt); state.fs_ofmt = ofmt; /* Show attributes of one flow */ if (state.fs_flow != NULL) { show_one_flow(&state, state.fs_flow); /* Show attributes of flows on one link */ } else if (l_arg) { (void) show_flows_onelink(handle, linkid, &state); /* Show attributes of all flows on all links */ } else { (void) dladm_walk_datalink_id(show_flows_onelink, handle, &state, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE); } ofmt_close(ofmt); }
int main(int argc, char *argv[]) { struct wpa_supplicant wpa_s; char *link = NULL; char *key = NULL; dlpi_handle_t dh = NULL; datalink_id_t linkid; dladm_phys_attr_t dpa; int c; int exitcode; char door_file[WPA_STRSIZE]; for (;;) { c = getopt(argc, argv, "Dk:hi:v"); if (c < 0) break; switch (c) { case 'D': wpa_debug_level = MSG_DEBUG; break; case 'h': usage(); return (-1); case 'i': link = optarg; break; case 'k': key = optarg; break; case 'v': (void) printf("%s\n", wpa_supplicant_version); return (-1); default: usage(); return (-1); } } /* * key name is required to retrieve PSK value through libwdladm APIs. * key is saved by dladm command by keyname * see dladm. */ if ((link == NULL) || (key == NULL)) { wpa_printf(MSG_ERROR, "\nLink & key is required."); return (-1); } if ((strlen(key) >= sizeof (wpa_s.kname))) { wpa_printf(MSG_ERROR, "Too long key name '%s'.", key); return (-1); } if (daemon(0, 0)) return (-1); /* * Hold this link open to prevent a link renaming operation. */ if (dlpi_open(link, &dh, 0) != DLPI_SUCCESS) { wpa_printf(MSG_ERROR, "Failed to open link '%s'.", link); return (-1); } if (dladm_name2info(link, &linkid, NULL, NULL, NULL) != DLADM_STATUS_OK) { wpa_printf(MSG_ERROR, "Invalid link name '%s'.", link); dlpi_close(dh); return (-1); } /* * Get the device name of the link, which will be used as the door * file name used to communicate with the driver. Note that different * links use different doors. */ if (dladm_phys_info(linkid, &dpa, DLADM_OPT_ACTIVE) != DLADM_STATUS_OK) { wpa_printf(MSG_ERROR, "Failed to get device name of link '%s'.", link); dlpi_close(dh); return (-1); } (void) snprintf(door_file, WPA_STRSIZE, "%s_%s", WPA_DOOR, dpa.dp_dev); (void) memset(&wpa_s, 0, sizeof (wpa_s)); wpa_s.driver = &wpa_driver_wifi_ops; wpa_s.linkid = linkid; (void) strlcpy(wpa_s.kname, key, sizeof (wpa_s.kname)); eloop_init(&wpa_s); /* * Setup default WPA/WPA2 configuration * get ESSID and PSK value */ wpa_s.conf = wpa_config_read(&wpa_s); if (wpa_s.conf == NULL || wpa_s.conf->ssid == NULL) { wpa_printf(MSG_ERROR, "\nNo networks (SSID) configured.\n"); exitcode = -1; goto cleanup; } exitcode = 0; /* * Setup door file to communicate with driver */ if (wpa_supplicant_door_setup(&wpa_s, door_file) != 0) { wpa_printf(MSG_ERROR, "Failed to setup door(%s)", door_file); exitcode = -1; goto cleanup; } wpa_s.renew_snonce = 1; if (wpa_supplicant_driver_init(link, &wpa_s) < 0) { exitcode = -1; goto cleanup; } /* * This link is hold again in wpa_supplicant_driver_init(), so that * we release the first reference. */ dlpi_close(dh); dh = NULL; wpa_printf(MSG_DEBUG, "=> eloop_run"); (void) eloop_register_signal(SIGINT, wpa_supplicant_terminate, NULL); (void) eloop_register_signal(SIGTERM, wpa_supplicant_terminate, NULL); (void) eloop_register_signal(SIGKILL, wpa_supplicant_terminate, NULL); eloop_run(); wpa_printf(MSG_DEBUG, "<= eloop_run()"); wpa_supplicant_disassociate(&wpa_s, REASON_DEAUTH_LEAVING); if (wpa_s.driver->set_wpa(wpa_s.linkid, 0) < 0) { wpa_printf(MSG_ERROR, "Failed to disable WPA in the driver.\n"); } cleanup: wpa_supplicant_door_destroy(door_file); wpa_supplicant_cleanup(&wpa_s); eloop_destroy(); if (dh != NULL) dlpi_close(dh); return (exitcode); }
int main(int argc, char *argv[]) { int c; dladm_status_t status; const char *outfile = NULL; uint_t count = 0; dltran_progname = basename(argv[0]); while ((c = getopt(argc, argv, ":xvw:")) != -1) { switch (c) { case 'v': dltran_verbose = B_TRUE; break; case 'x': dltran_hex = B_TRUE; break; case 'w': dltran_write = B_TRUE; outfile = optarg; break; case ':': dltran_usage("option -%c requires an " "operand\n", optopt); return (2); case '?': default: dltran_usage("unknown option: -%c\n", optopt); return (2); } } argc -= optind; argv += optind; if (dltran_verbose) count++; if (dltran_hex) count++; if (dltran_write) count++; if (count > 1) { (void) fprintf(stderr, "only one of -v, -w, and -x may be " "specified\n"); return (2); } if (dltran_write) { if ((dltran_outfd = open(outfile, O_RDWR | O_TRUNC | O_CREAT, 0644)) < 0) { (void) fprintf(stderr, "failed to open output file " "%s: %s\n", outfile, strerror(errno)); return (1); } } if ((status = dladm_open(&dltran_hdl)) != DLADM_STATUS_OK) { (void) fprintf(stderr, "failed to open /dev/dld: %s\n", dladm_status2str(status, dltran_dlerrmsg)); return (1); } if (argc == 0) { (void) dladm_walk_datalink_id(dltran_dump_transceivers, dltran_hdl, NULL, DATALINK_CLASS_PHYS, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE); } else { int i; char *c; for (i = 0; i < argc; i++) { uint_t tran; uint_t *tranidp = NULL; datalink_id_t linkid; if ((c = strrchr(argv[i], '/')) != NULL) { unsigned long u; char *eptr; c++; errno = 0; u = strtoul(c, &eptr, 10); if (errno != 0 || *eptr != '\0' || u >= UINT_MAX) { (void) fprintf(stderr, "failed to " "parse link/transceiver: %s\n", argv[i]); return (1); } c--; *c = '\0'; tran = (uint_t)u; tranidp = &tran; } if ((status = dladm_name2info(dltran_hdl, argv[i], &linkid, NULL, NULL, NULL)) != DLADM_STATUS_OK) { (void) fprintf(stderr, "failed to get link " "id for link %s: %s\n", argv[i], dladm_status2str(status, dltran_dlerrmsg)); return (1); } (void) dltran_dump_transceivers(dltran_hdl, linkid, tranidp); } } return (dltran_errors != 0 ? 1 : 0); }
int main(int argc, char *argv[]) { dladm_status_t status; int option; boolean_t r_arg = B_FALSE; boolean_t t_arg = B_FALSE; boolean_t p_arg = B_FALSE; boolean_t i_arg = B_FALSE; boolean_t o_arg = B_FALSE; boolean_t u_arg = B_FALSE; boolean_t A_arg = B_FALSE; boolean_t S_arg = B_FALSE; boolean_t flow_arg = B_FALSE; datalink_id_t linkid = DATALINK_ALL_LINKID; char linkname[MAXLINKNAMELEN]; char flowname[MAXFLOWNAMELEN]; uint32_t interval = 0; char unit = '\0'; show_flow_state_t state; char *fields_str = NULL; char *o_fields_str = NULL; char *total_stat_fields = "flow,ipkts,rbytes,ierrs,opkts,obytes,oerrs"; char *rx_stat_fields = "flow,ipkts,rbytes,ierrs"; char *tx_stat_fields = "flow,opkts,obytes,oerrs"; ofmt_handle_t ofmt; ofmt_status_t oferr; uint_t ofmtflags = OFMT_RIGHTJUST; dladm_flow_attr_t attr; (void) setlocale(LC_ALL, ""); #if !defined(TEXT_DOMAIN) #define TEXT_DOMAIN "SYS_TEST" #endif (void) textdomain(TEXT_DOMAIN); progname = argv[0]; /* Open the libdladm handle */ if ((status = dladm_open(&handle)) != DLADM_STATUS_OK) die_dlerr(status, "could not open /dev/dld"); bzero(&state, sizeof (state)); opterr = 0; while ((option = getopt_long(argc, argv, ":rtApSi:o:u:l:h", NULL, NULL)) != -1) { switch (option) { case 'r': if (r_arg) die_optdup(option); r_arg = B_TRUE; break; case 't': if (t_arg) die_optdup(option); t_arg = B_TRUE; break; case 'A': if (A_arg) die_optdup(option); A_arg = B_TRUE; break; case 'p': if (p_arg) die_optdup(option); p_arg = B_TRUE; break; case 'S': if (S_arg) die_optdup(option); S_arg = B_TRUE; break; case 'i': if (i_arg) die_optdup(option); i_arg = B_TRUE; if (!dladm_str2interval(optarg, &interval)) die("invalid interval value '%s'", optarg); break; case 'o': o_arg = B_TRUE; o_fields_str = optarg; break; case 'u': if (u_arg) die_optdup(option); u_arg = B_TRUE; if (!flowstat_unit(optarg, &unit)) die("invalid unit value '%s'," "unit must be R|K|M|G|T|P", optarg); break; case 'l': if (strlcpy(linkname, optarg, MAXLINKNAMELEN) >= MAXLINKNAMELEN) die("link name too long\n"); if (dladm_name2info(handle, linkname, &linkid, NULL, NULL, NULL) != DLADM_STATUS_OK) die("invalid link '%s'", linkname); break; case 'h': if (r_arg || t_arg || p_arg || o_arg || u_arg || i_arg || S_arg || A_arg) { die("the option -h is not compatible with " "-r, -t, -p, -o, -u, -i, -S, -A"); } do_show_history(argc, argv); return (0); break; default: die_opterr(optopt, option, usage_ermsg); break; } } if (r_arg && t_arg) die("the option -t and -r are not compatible"); if (u_arg && p_arg) die("the option -u and -p are not compatible"); if (p_arg && !o_arg) die("-p requires -o"); if (p_arg && strcasecmp(o_fields_str, "all") == 0) die("\"-o all\" is invalid with -p"); if (S_arg && (r_arg || t_arg || p_arg || o_arg || u_arg)) die("the option -S is not compatible with " "-r, -t, -p, -o, -u"); if (A_arg && (r_arg || t_arg || p_arg || o_arg || u_arg || i_arg)) die("the option -A is not compatible with " "-r, -t, -p, -o, -u, -i"); /* get flow name (optional last argument) */ if (optind == (argc-1)) { if (strlcpy(flowname, argv[optind], MAXFLOWNAMELEN) >= MAXFLOWNAMELEN) die("flow name too long"); flow_arg = B_TRUE; } else if (optind != argc) { usage(); } if (S_arg) { dladm_continuous(handle, linkid, (flow_arg ? flowname : NULL), interval, FLOW_REPORT); return (0); } if (flow_arg && dladm_flow_info(handle, flowname, &attr) != DLADM_STATUS_OK) die("invalid flow %s", flowname); if (A_arg) { dump_all_flow_stats(&attr, &state, linkid, flow_arg); return (0); } state.fs_unit = unit; state.fs_parsable = p_arg; if (state.fs_parsable) ofmtflags |= OFMT_PARSABLE; if (r_arg) fields_str = rx_stat_fields; else if (t_arg) fields_str = tx_stat_fields; else fields_str = total_stat_fields; if (o_arg) { fields_str = (strcasecmp(o_fields_str, "all") == 0) ? fields_str : o_fields_str; } oferr = ofmt_open(fields_str, flow_s_fields, ofmtflags, 0, &ofmt); flowstat_ofmt_check(oferr, state.fs_parsable, ofmt); state.fs_ofmt = ofmt; for (;;) { /* Show stats for named flow */ if (flow_arg) { (void) query_flow_stats(handle, &attr, &state); /* Show stats for flows on one link */ } else if (linkid != DATALINK_INVALID_LINKID) { (void) dladm_walk_flow(query_flow_stats, handle, linkid, &state, B_FALSE); /* Show stats for all flows on all links */ } else { (void) dladm_walk_datalink_id(query_link_flow_stats, handle, &state, DATALINK_CLASS_ALL, DATALINK_ANY_MEDIATYPE, DLADM_OPT_ACTIVE); } if (interval == 0) break; (void) fflush(stdout); cleanup_removed_flows(&state); (void) sleep(interval); } ofmt_close(ofmt); dladm_close(handle); return (0); }