int readMacAddress(char *devName, u_char *buf, int bufLen) { // we can only call dlpi_open() with root privileges. So only try to get // the MAC address if we are still root. We could cache the dlpi handle // for each interface as another field in the adaptorNIO structure, but in // practice it seems unlikely that the MAC address will change without // a reboot of the host, so it's OK to only read it at the start. If a // new interface somehow appears then it will just be instantiated without // a MAC. if(getuid() != 0) { return NO; } int macaddrlen = DLPI_PHYSADDR_MAX; int copied = 0; char macaddr[DLPI_PHYSADDR_MAX]; dlpi_handle_t dh; if (DLPI_SUCCESS != dlpi_open(devName, &dh, 0)) { myLog(LOG_ERR, "device %s dlpi_open failed : %s", devName, strerror(errno)); return 0; } // opened OK if (DLPI_SUCCESS != dlpi_get_physaddr(dh, DL_CURR_PHYS_ADDR, macaddr, &macaddrlen)) { myLog(LOG_ERR, "device %s dlpi_get_physaddr failed :%s", devName, strerror(errno)); } if(macaddrlen <= bufLen) { memcpy(buf, macaddr, macaddrlen); copied = macaddrlen; } dlpi_close(dh); return copied; }
/* * This is called when we want to start receiving notifications from state * changes on a link. */ void nwamd_dlpi_add_link(nwamd_object_t obj) { nwamd_ncu_t *ncu = obj->nwamd_object_data; nwamd_link_t *link; dlpi_notifyid_t id; int rc; nlog(LOG_DEBUG, "nwamd_dlpi_add_link: ncu %p (%s) type %d", ncu, obj->nwamd_object_name, ncu != NULL ? ncu->ncu_type : -1); assert(ncu != NULL && ncu->ncu_type == NWAM_NCU_TYPE_LINK); link = &ncu->ncu_link; /* Already running? */ if (link->nwamd_link_dlpi_thread != 0) { nlog(LOG_DEBUG, "nwamd_dlpi_add_link(%s) already running", obj->nwamd_object_name); return; } rc = dlpi_open(ncu->ncu_name, &link->nwamd_link_dhp, 0); if (rc != DLPI_SUCCESS) { nlog(LOG_ERR, "nwamd_dlpi_add_link: dlpi_open(%s) = %s", ncu->ncu_name, dlpi_strerror(rc)); return; } /* Wifi links do not support setting/unsetting these properties */ if (dladm_wlan_validate(dld_handle, ncu->ncu_link.nwamd_link_id, NULL, NULL) == DLADM_STATUS_OK) { nlog(LOG_DEBUG, "nwamd_dlpi_add_link(%s): skipping " "wifi link properties initialization", ncu->ncu_name); } else nwamd_set_unset_link_properties(ncu, B_TRUE); rc = dlpi_enabnotify(link->nwamd_link_dhp, DL_NOTE_LINK_UP | DL_NOTE_LINK_DOWN, nwamd_dlpi_notify, ncu->ncu_name, &id); if (rc != DLPI_SUCCESS) { nlog(LOG_ERR, "nwamd_dlpi_add_link: dlpi_enabnotify(%s) = %s", obj->nwamd_object_name, dlpi_strerror(rc)); dlpi_close(link->nwamd_link_dhp); return; } rc = pthread_create(&link->nwamd_link_dlpi_thread, NULL, nwamd_dlpi_thread, &link->nwamd_link_dhp); if (rc != 0) { nlog(LOG_ERR, "nwamd_dlpi_add_link: couldn't create " "dlpi thread for %s: %s", obj->nwamd_object_name, strerror(rc)); dlpi_close(link->nwamd_link_dhp); } }
static boolean_t dlpi_walk_cb(const char *name, void *arg) { NOTE(ARGUNUSED(arg)) dlpi_handle_t dlh; link_t *link; int rc; dlpi_info_t info; boolean_t keep; size_t len; rc = dlpi_open(name, &dlh, DLPI_PASSIVE|DLPI_NATIVE); if (rc != DLPI_SUCCESS) { DMSG(D_NET, "dlpi_open(%s) failed: %s; skipping.", name, dlpi_strerror(rc)); return (B_TRUE); } rc = dlpi_info(dlh, &info, 0); if (rc != DLPI_SUCCESS) { DMSG(D_NET, "dlpi_info(%s) failed: %s; skipping.", name, dlpi_strerror(rc)); dlpi_close(dlh); return (B_TRUE); } keep = !!(info.di_mactype == DL_ETHER); DMSG(D_NET, "found link %s, mactype = %s (%d)%s.", name, dlpi_mactype(info.di_mactype), info.di_mactype, (keep) ? "" : "; discarding"); dlpi_close(dlh); if (!keep) return (B_TRUE); VERIFY((link = link_alloc(name)) != NULL); list_insert_tail(&links, (void *)link); num_links++; if ((len = strlen(name)) > link_max_len) link_max_len = len; return (B_TRUE); }
static void hwaddr_libdlpi_lookup(sigar_t *sigar, sigar_net_interface_config_t *ifconfig) { dlpi_handle_t handle; dlpi_info_t linkinfo; uchar_t addr[DLPI_PHYSADDR_MAX]; uint_t alen = sizeof(addr); if (dlpi_open(ifconfig->name, &handle, 0) != DLPI_SUCCESS) { return; } if (dlpi_get_physaddr(handle, DL_CURR_PHYS_ADDR, addr, &alen) == DLPI_SUCCESS && dlpi_info(handle, &linkinfo, 0) == DLPI_SUCCESS) { if (alen < sizeof(ifconfig->hwaddr.addr.mac)) { sigar_net_address_mac_set(ifconfig->hwaddr, addr, alen); SIGAR_SSTRCPY(ifconfig->type, dlpi_mactype(linkinfo.di_mactype)); } } dlpi_close(handle); }
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); }
static int eth_get(const char *device, u8 ea[ETH_ALEN]) { #ifdef __sun__ dlpi_handle_t dh; u32 physaddrlen = DLPI_PHYSADDR_MAX; u8 physaddr[DLPI_PHYSADDR_MAX]; int retval; retval = dlpi_open(device, &dh, 0); if (retval != DLPI_SUCCESS) { wpa_printf(MSG_ERROR, "dlpi_open error: %s", dlpi_strerror(retval)); return -1; } retval = dlpi_get_physaddr(dh, DL_CURR_PHYS_ADDR, physaddr, &physaddrlen); if (retval != DLPI_SUCCESS) { wpa_printf(MSG_ERROR, "dlpi_get_physaddr error: %s", dlpi_strerror(retval)); dlpi_close(dh); return -1; } os_memcpy(ea, physaddr, ETH_ALEN); dlpi_close(dh); #else /* __sun__ */ struct if_msghdr *ifm; struct sockaddr_dl *sdl; u_char *p, *buf; size_t len; int mib[] = { CTL_NET, AF_ROUTE, 0, AF_LINK, NET_RT_IFLIST, 0 }; if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) return -1; if ((buf = os_malloc(len)) == NULL) return -1; if (sysctl(mib, 6, buf, &len, NULL, 0) < 0) { os_free(buf); return -1; } for (p = buf; p < buf + len; p += ifm->ifm_msglen) { ifm = (struct if_msghdr *)p; sdl = (struct sockaddr_dl *)(ifm + 1); if (ifm->ifm_type != RTM_IFINFO || (ifm->ifm_addrs & RTA_IFP) == 0) continue; if (sdl->sdl_family != AF_LINK || sdl->sdl_nlen == 0 || os_memcmp(sdl->sdl_data, device, sdl->sdl_nlen) != 0) continue; os_memcpy(ea, LLADDR(sdl), sdl->sdl_alen); break; } os_free(buf); if (p >= buf + len) { errno = ESRCH; return -1; } #endif /* __sun__ */ return 0; }
static int pcap_activate_libdlpi(pcap_t *p) { struct pcap_dlpi *pd = p->priv; int retv; dlpi_handle_t dh; dlpi_info_t dlinfo; int err = PCAP_ERROR; /* * Enable Solaris raw and passive DLPI extensions; * dlpi_open() will not fail if the underlying link does not support * passive mode. See dlpi(7P) for details. */ retv = dlpi_open(p->opt.source, &dh, DLPI_RAW|DLPI_PASSIVE); if (retv != DLPI_SUCCESS) { if (retv == DLPI_ELINKNAMEINVAL || retv == DLPI_ENOLINK) err = PCAP_ERROR_NO_SUCH_DEVICE; else if (retv == DL_SYSERR && (errno == EPERM || errno == EACCES)) err = PCAP_ERROR_PERM_DENIED; pcap_libdlpi_err(p->opt.source, "dlpi_open", retv, p->errbuf); return (err); } pd->dlpi_hd = dh; if (p->opt.rfmon) { /* * This device exists, but we don't support monitor mode * any platforms that support DLPI. */ err = PCAP_ERROR_RFMON_NOTSUP; goto bad; } /* Bind with DLPI_ANY_SAP. */ if ((retv = dlpi_bind(pd->dlpi_hd, DLPI_ANY_SAP, 0)) != DLPI_SUCCESS) { pcap_libdlpi_err(p->opt.source, "dlpi_bind", retv, p->errbuf); goto bad; } /* Enable promiscuous mode. */ if (p->opt.promisc) { err = dlpromiscon(p, DL_PROMISC_PHYS); if (err < 0) { /* * "You don't have permission to capture on * this device" and "you don't have permission * to capture in promiscuous mode on this * device" are different; let the user know, * so if they can't get permission to * capture in promiscuous mode, they can at * least try to capture in non-promiscuous * mode. * * XXX - you might have to capture in * promiscuous mode to see outgoing packets. */ if (err == PCAP_ERROR_PERM_DENIED) err = PCAP_ERROR_PROMISC_PERM_DENIED; goto bad; } } else { /* Try to enable multicast. */ err = dlpromiscon(p, DL_PROMISC_MULTI); if (err < 0) goto bad; } /* Try to enable SAP promiscuity. */ err = dlpromiscon(p, DL_PROMISC_SAP); if (err < 0) { /* * Not fatal, since the DL_PROMISC_PHYS mode worked. * Report it as a warning, however. */ if (p->opt.promisc) err = PCAP_WARNING; else goto bad; } /* Determine link type. */ if ((retv = dlpi_info(pd->dlpi_hd, &dlinfo, 0)) != DLPI_SUCCESS) { pcap_libdlpi_err(p->opt.source, "dlpi_info", retv, p->errbuf); goto bad; } if (pcap_process_mactype(p, dlinfo.di_mactype) != 0) goto bad; p->fd = dlpi_fd(pd->dlpi_hd); /* Push and configure bufmod. */ if (pcap_conf_bufmod(p, p->snapshot) != 0) goto bad; /* * Flush the read side. */ if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s", pcap_strerror(errno)); goto bad; } /* Allocate data buffer. */ if (pcap_alloc_databuf(p) != 0) goto bad; /* * "p->fd" is a FD for a STREAMS device, so "select()" and * "poll()" should work on it. */ p->selectable_fd = p->fd; p->read_op = pcap_read_libdlpi; p->inject_op = pcap_inject_libdlpi; p->setfilter_op = install_bpf_program; /* No kernel filtering */ p->setdirection_op = NULL; /* Not implemented */ p->set_datalink_op = NULL; /* Can't change data link type */ p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; p->stats_op = pcap_stats_dlpi; p->cleanup_op = pcap_cleanup_libdlpi; return (0); bad: pcap_cleanup_libdlpi(p); return (err); }
int main(int argc, char *argv[]) { int c, ret; char *eptr; unsigned long sap; uint_t bind_sap; dlpi_handle_t dh; dlrecv_prog = basename(argv[0]); while ((c = getopt(argc, argv, ":s:")) != -1) { switch (c) { case 's': errno = 0; sap = strtoul(optarg, &eptr, 10); if (errno != 0 || sap == 0 || sap >= UINT16_MAX || *eptr != '\0') { dlrecv_usage("Invalid value for sap (-s): %s\n", optarg); return (2); } dlrecv_sap = sap; break; case ':': dlrecv_usage("Option -%c requires an operand\n", optopt); return (2); case '?': dlrecv_usage("Unknown option: -%c\n", optopt); return (2); } } argc -= optind; argv += optind; if (argc != 1) { dlrecv_usage("missing required operands\n"); return (2); } if ((ret = dlpi_open(argv[0], &dh, 0)) != DLPI_SUCCESS) { warnx("failed to open %s: %s\n", argv[0], dlpi_strerror(ret)); exit(1); } if ((ret = dlpi_bind(dh, dlrecv_sap, &bind_sap)) != DLPI_SUCCESS) { warnx("failed to bind to sap 0x%x: %s\n", dlrecv_sap, dlpi_strerror(ret)); exit(1); } if (bind_sap != dlrecv_sap) { warnx("failed to bind to requested sap 0x%x, bound to " "0x%x\n", dlrecv_sap, bind_sap); exit(1); } for (;;) { dlpi_recvinfo_t rinfo; dlsend_msg_t msg; size_t msglen; boolean_t invalid = B_FALSE; msglen = sizeof (msg); ret = dlpi_recv(dh, NULL, NULL, &msg, &msglen, -1, &rinfo); if (ret != DLPI_SUCCESS) { warnx("failed to receive data: %s\n", dlpi_strerror(ret)); continue; } if (msglen != rinfo.dri_totmsglen) { warnx("message truncated: expected %ld bytes, " "got %ld\n", sizeof (dlsend_msg_t), rinfo.dri_totmsglen); invalid = B_TRUE; } if (msglen != sizeof (msg)) { warnx("message too short: expected %ld bytes, " "got %ld\n", sizeof (dlsend_msg_t), msglen); invalid = B_TRUE; } if (!invalid) { invalid = !dlrecv_isvalid(&msg); } dlrecv_print(&msg, &rinfo, invalid); } /* LINTED: E_STMT_NOT_REACHED */ return (0); }
int main(int argc, char **argv) { char cnambuf[DLPI_LINKNAME_MAX], device[DLPI_LINKNAME_MAX]; struct scc_mode sm; struct strioctl sioc; int fd, speed; int retval; char *arg, *cp; char loopchange = 0; char echochange = 0; char clockchange = 0; uint_t ppa; dlpi_handle_t dh; if (argc == 1) { usage(); exit(1); } argc--; argv++; if (strlcpy(cnambuf, argv[0], sizeof (cnambuf)) >= sizeof (cnambuf)) { (void) fprintf(stderr, "syncinit: invalid device name (too long) %s\n", argv[0]); exit(1); } cp = cnambuf; while (*cp) /* find the end of the name */ cp++; cp--; if (!isdigit(*cp)) { (void) fprintf(stderr, "syncinit: %s missing minor device number\n", cnambuf); exit(1); } retval = dlpi_open(cnambuf, &dh, DLPI_EXCL|DLPI_SERIAL); if (retval != DLPI_SUCCESS) { (void) fprintf(stderr, "syncinit: dlpi_open %s: %s\n", cnambuf, dlpi_strerror(retval)); exit(1); } (void) dlpi_parselink(cnambuf, device, &ppa); (void) printf("device: %s ppa: %u\n", device, ppa); fd = dlpi_fd(dh); argc--; argv++; if (argc) { /* setting things */ sioc.ic_cmd = S_IOCGETMODE; sioc.ic_timout = -1; sioc.ic_len = sizeof (struct scc_mode); sioc.ic_dp = (char *)&sm; if (ioctl(fd, I_STR, &sioc) < 0) { perror("S_IOCGETMODE"); (void) fprintf(stderr, "syncinit: can't get sync mode info for %s\n", cnambuf); exit(1); } while (argc-- > 0) { arg = *argv++; if (sscanf(arg, "%d", &speed) == 1) sm.sm_baudrate = speed; else if (strchr(arg, '=')) { if (prefix(arg, "loop")) { if (lookup(yesno, arg)) sm.sm_config |= CONN_LPBK; else sm.sm_config &= ~CONN_LPBK; loopchange++; } else if (prefix(arg, "echo")) { if (lookup(yesno, arg)) sm.sm_config |= CONN_ECHO; else sm.sm_config &= ~CONN_ECHO; echochange++; } else if (prefix(arg, "nrzi")) { if (lookup(yesno, arg)) sm.sm_config |= CONN_NRZI; else sm.sm_config &= ~CONN_NRZI; } else if (prefix(arg, "txc")) { sm.sm_txclock = lookup(txnames, arg); clockchange++; } else if (prefix(arg, "rxc")) { sm.sm_rxclock = lookup(rxnames, arg); clockchange++; } else if (prefix(arg, "speed")) { arg = strchr(arg, '=') + 1; if (sscanf(arg, "%d", &speed) == 1) { sm.sm_baudrate = speed; } else (void) fprintf(stderr, "syncinit: %s %s\n", "bad speed:", arg); } } else if (equal(arg, "external")) { sm.sm_txclock = TXC_IS_TXC; sm.sm_rxclock = RXC_IS_RXC; sm.sm_config &= ~CONN_LPBK; } else if (equal(arg, "sender")) { sm.sm_txclock = TXC_IS_BAUD; sm.sm_rxclock = RXC_IS_RXC; sm.sm_config &= ~CONN_LPBK; } else if (equal(arg, "internal")) { sm.sm_txclock = TXC_IS_PLL; sm.sm_rxclock = RXC_IS_PLL; sm.sm_config &= ~CONN_LPBK; } else if (equal(arg, "stop")) { sm.sm_baudrate = 0; } else (void) fprintf(stderr, "Bad arg: %s\n", arg); } /* * If we're going to change the state of loopback, and we * don't have our own plans for clock sources, use defaults. */ if (loopchange && !clockchange) { if (sm.sm_config & CONN_LPBK) { sm.sm_txclock = TXC_IS_BAUD; sm.sm_rxclock = RXC_IS_BAUD; } else { sm.sm_txclock = TXC_IS_TXC; sm.sm_rxclock = RXC_IS_RXC; } } sioc.ic_cmd = S_IOCSETMODE; sioc.ic_timout = -1; sioc.ic_len = sizeof (struct scc_mode); sioc.ic_dp = (char *)&sm; if (ioctl(fd, I_STR, &sioc) < 0) { perror("S_IOCSETMODE"); (void) ioctl(fd, S_IOCGETMODE, &sm); (void) fprintf(stderr, "syncinit: ioctl failure code = %x\n", sm.sm_retval); exit(1); } } /* Report State */ sioc.ic_cmd = S_IOCGETMODE; sioc.ic_timout = -1; sioc.ic_len = sizeof (struct scc_mode); sioc.ic_dp = (char *)&sm; if (ioctl(fd, I_STR, &sioc) < 0) { perror("S_IOCGETMODE"); (void) fprintf(stderr, "syncinit: can't get sync mode info for %s\n", cnambuf); exit(1); } (void) printf( "speed=%d, loopback=%s, echo=%s, nrzi=%s, txc=%s, rxc=%s\n", sm.sm_baudrate, yesno[((int)(sm.sm_config & CONN_LPBK) > 0)], yesno[((int)(sm.sm_config & CONN_ECHO) > 0)], yesno[((int)(sm.sm_config & CONN_NRZI) > 0)], txnames[sm.sm_txclock], rxnames[sm.sm_rxclock]); return (0); }
static int pcap_activate_libdlpi(pcap_t *p) { int retv; dlpi_handle_t dh; dlpi_info_t dlinfo; int err = PCAP_ERROR; /* * Enable Solaris raw and passive DLPI extensions; * dlpi_open() will not fail if the underlying link does not support * passive mode. See dlpi(7P) for details. */ retv = dlpi_open(p->opt.source, &dh, DLPI_RAW|DLPI_PASSIVE); if (retv != DLPI_SUCCESS) { if (retv == DLPI_ELINKNAMEINVAL || retv == DLPI_ENOLINK) err = PCAP_ERROR_NO_SUCH_DEVICE; else if (retv == DL_SYSERR && errno == EACCES) err = PCAP_ERROR_PERM_DENIED; pcap_libdlpi_err(p->opt.source, "dlpi_open", retv, p->errbuf); return (err); } p->dlpi_hd = dh; if (p->opt.rfmon) { /* * This device exists, but we don't support monitor mode * any platforms that support DLPI. */ err = PCAP_ERROR_RFMON_NOTSUP; goto bad; } /* Bind with DLPI_ANY_SAP. */ if ((retv = dlpi_bind(p->dlpi_hd, DLPI_ANY_SAP, 0)) != DLPI_SUCCESS) { pcap_libdlpi_err(p->opt.source, "dlpi_bind", retv, p->errbuf); goto bad; } /* Enable promiscuous mode. */ if (p->opt.promisc) { retv = dlpi_promiscon(p->dlpi_hd, DL_PROMISC_PHYS); if (retv != DLPI_SUCCESS) { pcap_libdlpi_err(p->opt.source, "dlpi_promisc(PHYSICAL)", retv, p->errbuf); goto bad; } } else { /* Try to enable multicast. */ retv = dlpi_promiscon(p->dlpi_hd, DL_PROMISC_MULTI); if (retv != DLPI_SUCCESS) { pcap_libdlpi_err(p->opt.source, "dlpi_promisc(MULTI)", retv, p->errbuf); goto bad; } } /* Try to enable SAP promiscuity. */ retv = dlpi_promiscon(p->dlpi_hd, DL_PROMISC_SAP); if (retv != DLPI_SUCCESS) { if (p->opt.promisc) { pcap_libdlpi_err(p->opt.source, "dlpi_promisc(SAP)", retv, p->errbuf); goto bad; } /* Not fatal, since the DL_PROMISC_PHYS mode worked. */ fprintf(stderr, "WARNING: dlpi_promisc(SAP) failed on" " %s:(%s)\n", p->opt.source, dlpi_strerror(retv)); } /* Determine link type. */ if ((retv = dlpi_info(p->dlpi_hd, &dlinfo, 0)) != DLPI_SUCCESS) { pcap_libdlpi_err(p->opt.source, "dlpi_info", retv, p->errbuf); goto bad; } if (pcap_process_mactype(p, dlinfo.di_mactype) != 0) goto bad; p->fd = dlpi_fd(p->dlpi_hd); /* Push and configure bufmod. */ if (pcap_conf_bufmod(p, p->snapshot, p->md.timeout) != 0) goto bad; /* * Flush the read side. */ if (ioctl(p->fd, I_FLUSH, FLUSHR) != 0) { snprintf(p->errbuf, PCAP_ERRBUF_SIZE, "FLUSHR: %s", pcap_strerror(errno)); goto bad; } /* Allocate data buffer. */ if (pcap_alloc_databuf(p) != 0) goto bad; /* * "p->fd" is a FD for a STREAMS device, so "select()" and * "poll()" should work on it. */ p->selectable_fd = p->fd; p->read_op = pcap_read_libdlpi; p->inject_op = pcap_inject_libdlpi; p->setfilter_op = install_bpf_program; /* No kernel filtering */ p->setdirection_op = NULL; /* Not implemented */ p->set_datalink_op = NULL; /* Can't change data link type */ p->getnonblock_op = pcap_getnonblock_fd; p->setnonblock_op = pcap_setnonblock_fd; p->stats_op = pcap_stats_dlpi; p->cleanup_op = pcap_cleanup_libdlpi; return (0); bad: pcap_cleanup_libdlpi(p); return (err); }
boolean_t port_dlpi_open(const char *portname, struct portdata *port, datalink_class_t class) { uchar_t addrbuf[DLPI_PHYSADDR_MAX]; size_t alen = DLPI_PHYSADDR_MAX; int rc; char addrstr[ETHERADDRL * 3]; /* * We use DLPI 'raw' mode so that we get access to the received * Ethernet 802 length field. libdlpi otherwise eats this value. Note * that 'raw' mode support is required in order to use snoop, so it's * expected to be common, even if it's not documented. */ rc = dlpi_open(portname, &port->dlpi, DLPI_RAW); if (rc != DLPI_SUCCESS) { syslog(LOG_ERR, "can't open %s: %s", portname, dlpi_strerror(rc)); return (B_FALSE); } port->phys_status = B_TRUE; port->sdu_failed = B_FALSE; port->bpdu_protect = B_FALSE; /* * Now that the driver is open, we can get at least the initial value * of the interface speed. We need to do this before establishing the * notify callback, so that it can update us later. */