Exemplo n.º 1
0
/*
 * 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);
	}
}
Exemplo n.º 2
0
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);
}
Exemplo n.º 3
0
/*
 * We are only intested in DL_NOTE_LINK_UP events which we've registered for
 * in nwamd_dlpi_add_link().  But we have to keep calling dlpi_recv() to
 * force the notification callback to be executed.
 */
static void *
nwamd_dlpi_thread(void *arg)
{
	int rc;
	dlpi_handle_t *dh = arg;

	do {
		rc = dlpi_recv(*dh, NULL, NULL, NULL, NULL, -1, NULL);
	} while (rc == DLPI_SUCCESS);
	nlog(LOG_ERR, "dlpi_recv failed: %s", dlpi_strerror(rc));
	return (NULL);
}
Exemplo n.º 4
0
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;
}
Exemplo n.º 5
0
/*
 * Write error message to buffer.
 */
static void
pcap_libdlpi_err(const char *linkname, const char *func, int err, char *errbuf)
{
	snprintf(errbuf, PCAP_ERRBUF_SIZE, "libpcap: %s failed on %s: %s",
	    func, linkname, dlpi_strerror(err));
}
Exemplo n.º 6
0
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);
}
Exemplo n.º 7
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);
}
Exemplo n.º 8
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);
}