int dlpi_enabnotify(dlpi_handle_t dh, uint_t notes, dlpi_notifyfunc_t *funcp, void *arg, dlpi_notifyid_t *id) { int retval; dlpi_msg_t req, ack; dl_notify_req_t *notifyreqp; dlpi_impl_t *dip = (dlpi_impl_t *)dh; dlpi_notifyent_t *newnotifp; dlpi_info_t dlinfo; if (dip == NULL) return (DLPI_EINHANDLE); retval = dlpi_info((dlpi_handle_t)dip, &dlinfo, 0); if (retval != DLPI_SUCCESS) return (retval); if (dip->dli_note_processing) return (DLPI_FAILURE); if (funcp == NULL || id == NULL) return (DLPI_EINVAL); if ((~DLPI_NOTIFICATION_TYPES & notes) || !(notes & DLPI_NOTIFICATION_TYPES)) return (DLPI_ENOTEINVAL); DLPI_MSG_CREATE(req, DL_NOTIFY_REQ); DLPI_MSG_CREATE(ack, DL_NOTIFY_ACK); notifyreqp = &(req.dlm_msg->notify_req); notifyreqp->dl_notifications = notes; notifyreqp->dl_timelimit = 0; retval = i_dlpi_msg_common(dip, &req, &ack, DL_NOTIFY_ACK_SIZE, 0); if (retval == DL_NOTSUPPORTED) return (DLPI_ENOTENOTSUP); if (retval != DLPI_SUCCESS) return (retval); if ((newnotifp = calloc(1, sizeof (dlpi_notifyent_t))) == NULL) return (DL_SYSERR); /* Register notification information. */ newnotifp->dln_fnp = funcp; newnotifp->dln_notes = notes; newnotifp->arg = arg; newnotifp->dln_rm = B_FALSE; /* Insert notification node at head */ newnotifp->dln_next = dip->dli_notifylistp; dip->dli_notifylistp = newnotifp; *id = (dlpi_notifyid_t)newnotifp; return (DLPI_SUCCESS); }
/* * Verify with DLPI that the link is the expected DLPI 'style' device, * dlpi_info sets the DLPI style in the DLPI handle. */ static int i_dlpi_checkstyle(dlpi_impl_t *dip, t_uscalar_t style) { int retval; dlpi_info_t dlinfo; retval = dlpi_info((dlpi_handle_t)dip, &dlinfo, 0); if (retval == DLPI_SUCCESS && dip->dli_style != style) retval = DLPI_EBADLINK; return (retval); }
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); }
static int get_if_info(const char *name, dladm_attr_t *dlattrp, boolean_t *legacy) { int err; if ((err = dladm_info(name, dlattrp)) == 0) { *legacy = B_FALSE; } else if (err < 0 && errno == ENODEV) { int fd; dlpi_if_attr_t dia; dl_info_ack_t dlia; /* * A return value of ENODEV means that the specified * device is not gldv3. */ if ((fd = dlpi_if_open(name, &dia, B_FALSE)) != -1 && dlpi_info(fd, -1, &dlia, NULL, NULL, NULL, NULL, NULL, NULL) != -1) { (void) dlpi_close(fd); *legacy = B_TRUE; bzero(dlattrp, sizeof (*dlattrp)); dlattrp->da_max_sdu = (uint_t)dlia.dl_max_sdu; } else { errno = ENOENT; return (-1); } } else { /* * If the return value is not ENODEV, this means that * user is either passing in a bogus interface name * or a vlan interface name that doesn't exist yet. */ errno = ENOENT; return (-1); } 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); }
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); }