Net-CDP

 view release on metacpan or  search on metacpan

libcdp/src/cdp.c  view on Meta::CPAN

#if HAVE_MULTICAST

static int
_cdp_multicast(const cdp_t *cdp, int add) {
	int result;
	
	struct ifreq ifr;
	struct packet_mreq mreq;
	
	if (!cdp->pcap)
		return -1;
	
	memset(&ifr, 0, sizeof(struct ifreq));
	strncpy(ifr.ifr_name, cdp->port, sizeof ifr.ifr_name - 1);
	ifr.ifr_name[sizeof ifr.ifr_name - 1] = '\0';
	result = ioctl(pcap_fileno(cdp->pcap), SIOCGIFINDEX, &ifr);
	
	if (result < 0)
		return result;
	
	mreq.mr_ifindex = ifr.ifr_ifindex;
	mreq.mr_type = PACKET_MR_MULTICAST;
	mreq.mr_alen = 6;
	memcpy(mreq.mr_address, cdp_multicast_mac, 6);
	mreq.mr_address[6] = mreq.mr_address[7] = '\0';
	return setsockopt(
		pcap_fileno(cdp->pcap),
		SOL_PACKET,
		add ? PACKET_ADD_MEMBERSHIP : PACKET_DROP_MEMBERSHIP,
		&mreq,
		sizeof(struct packet_mreq)
	);
}

#else /* HAVE_MULTICAST */

static int _cdp_multicast(const cdp_t *cdp, int add) { return 1; }

#endif /* ! HAVE_MULTICAST */

#if HAVE_LINUX_ETHTOOL_H

static void
_cdp_duplex(cdp_t *cdp) {
	int result, fd;
	struct ifreq ifr;
	struct ethtool_cmd ecmd;
	
	if (cdp->flags & CDP_DISABLE_SEND) {
		fd = socket(AF_INET, SOCK_DGRAM, 0);
		if (fd < 0)
			return;
	} else
		fd = libnet_getfd(cdp->libnet);
	
	memset(&ifr, 0, sizeof(struct ifreq));
	strncpy(ifr.ifr_name, cdp->port, sizeof ifr.ifr_name - 1);
	ifr.ifr_name[sizeof ifr.ifr_name - 1] = '\0';
	ifr.ifr_data = (caddr_t)&ecmd;
	ecmd.cmd = ETHTOOL_GSET;
	result = ioctl(fd, SIOCETHTOOL, &ifr);

	if (result >= 0)
		NEW(cdp->duplex, ecmd.duplex == DUPLEX_FULL ? 1 : 0, uint8_t);

	if (cdp->flags & CDP_DISABLE_SEND)
		close(fd);
}

#endif /* HAVE_LINUX_ETHTOOL_H */

cdp_llist_t *
cdp_get_ports(char *errors) {
	/* This code is lifted from Ethereal 0.9.13 */
	char *pcap_errors, *libnet_errors;
	int sock;
	int len, lastlen;
	struct ifconf ifc;
	struct ifreq ifrflags, *ifr, *last;
	char *buf;
	pcap_t *pcap;
	libnet_t *libnet;
	cdp_llist_t *normal, *loopback;

	if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
		snprintf(errors, (CDP_ERRBUF_SIZE - 1) * sizeof(char),
			"Error opening socket: %s", strerror(errno));
		errors[CDP_ERRBUF_SIZE - 1] = '\0';
		return NULL;
	}

	lastlen = 0;
	len = 100 * sizeof(struct ifreq);
	for ( ; ; ) {
		buf = MALLOC(len, char);
		ifc.ifc_len = len;
		ifc.ifc_buf = buf;
		memset(buf, 0, len);
		if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
			if (errno != EINVAL || lastlen != 0) {
				snprintf(errors, (CDP_ERRBUF_SIZE - 1) * sizeof(char),
					"Could not get list of interfaces: %s",
					strerror(errno));
				errors[CDP_ERRBUF_SIZE - 1] = '\0';
				FREE(buf);
				close(sock);
				return NULL;
			}
		} else {
			if ((unsigned) ifc.ifc_len < sizeof(struct ifreq)) {
				sprintf(errors,
					"SIOCGIFCONF ioctl returned an invalid buffer");
				FREE(buf);
				close(sock);
				return NULL;
			}
			if (ifc.ifc_len == lastlen)
				break;
			lastlen = ifc.ifc_len;
		}
		len += 10 * sizeof(struct ifreq);



( run in 1.278 second using v1.01-cache-2.11-cpan-e1769b4cff6 )