⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cdp.c

📁 Net-CDP-0.09 cdp相关源包
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * $Id: cdp.c,v 1.5 2005/07/21 10:57:05 mchapman Exp $ */#include <system.h>#include <encoding.h>#if HAVE_SYS_TIME_H# include <sys/time.h>#endif /* HAVE_SYS_TIME_H */#if HAVE_SYS_SOCKET_H# include <sys/socket.h>#endif /* HAVE_SYS_SOCKET_H */#if HAVE_NET_IF_H# include <net/if.h>#endif /* HAVE_NET_IF_H */#if HAVE_SYS_IOCTL_H# include <sys/ioctl.h>#endif /* HAVE_SYS_IOCTL_H */#if HAVE_LINUX_ETHTOOL_H# include <linux/ethtool.h>#endif /* HAVE_LINUX_ETHTOOL_H */#if HAVE_LINUX_SOCKIOS_H# include <linux/sockios.h>#endif /* HAVE_LINUX_ETHTOOL_H */#if HAVE_NETINET_IF_ETHER_H# include <netinet/if_ether.h>#endif /* HAVE_NETINET_IF_ETHER_H */#if HAVE_FCNTL_H# include <fcntl.h>#endif /* HAVE_FCNTL_H */#if HAVE_MULTICAST# if HAVE_NETPACKET_PACKET_H#  include <netpacket/packet.h># endif /* HAVE_NETPACKET_PACKET_H */#endif /* HAVE_MULTICAST */#define BPF_FILTER "ether host 01:00:0c:cc:cc:cc and ether[20:2] = 0x2000"static const uint8_t cdp_multicast_mac[] =	{ 0x01, 0x00, 0x0c, 0xcc, 0xcc, 0xcc };static void_cdp_callback(cdp_t *cdp, const struct pcap_pkthdr *header, const void *data) {	/*	 * Grab the header and data and save it in the supplied cdp object.	 * cdp_recv will pick it up when pcap_dispatch returns.	 */	cdp->header = header;	cdp->data = data;}#if HAVE_MULTICASTstatic 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_Hstatic 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);		FREE(buf);	}	normal = cdp_llist_new((cdp_dup_fn_t)strdup, (cdp_free_fn_t)free);	loopback = cdp_llist_new((cdp_dup_fn_t)strdup, (cdp_free_fn_t)free);	pcap_errors = SALLOC(PCAP_ERRBUF_SIZE);	libnet_errors = SALLOC(LIBNET_ERRBUF_SIZE);	ifr = (struct ifreq *)ifc.ifc_req;	last = (struct ifreq *)VOIDP_OFFSET(ifr, ifc.ifc_len);	for ( ; ifr < last; ifr++) {		cdp_llist_iter_t found;		/*		 * Skip addresses that begin with "dummy", or that include		 * a ":" (the latter are Solaris virtuals).		 */		if (strncmp(ifr->ifr_name, "dummy", 5) == 0 ||			strchr(ifr->ifr_name, ':') != NULL)			continue;		/*		 * If we already have this interface name on the list,		 * don't add it (SIOCGIFCONF returns, at least on		 * BSD-flavored systems, one entry per interface *address*;		 * if an interface has multiple addresses, we get multiple		 * entries for it).		 */		for (			found = cdp_llist_iter(normal);			found && strcmp(				(char *)cdp_llist_get(found), ifr->ifr_name			);			found = cdp_llist_next(found)		)			;		if (found)			continue;		for (			found = cdp_llist_iter(loopback);			found && strcmp(				(char *)cdp_llist_get(found), ifr->ifr_name			);			found = cdp_llist_next(found)		)			;		if (found)			continue;		/*		 * Get the interface flags.		 */		memset(&ifrflags, 0, sizeof ifrflags);		strncpy(ifrflags.ifr_name, ifr->ifr_name,			sizeof ifrflags.ifr_name);		if (ioctl(sock, SIOCGIFFLAGS, (char *)&ifrflags) < 0) {			if (errno == ENXIO)				continue;			snprintf(errors, (CDP_ERRBUF_SIZE - 1) * sizeof(char),				"Could not get flags for interface %s: %s",				ifr->ifr_name, strerror(errno));			errors[CDP_ERRBUF_SIZE - 1] = '\0';			FREE(buf);			close(sock);			FREE(pcap_errors);			FREE(libnet_errors);			cdp_llist_free(normal);			cdp_llist_free(loopback);			return NULL;		}		/*		 * Skip interfaces that aren't up.		 */		if (!(ifrflags.ifr_flags & IFF_UP))			continue;		/*		 * Skip interfaces that we can't open with "libpcap".		 * Open with the minimum packet size - it appears that the		 * IRIX SIOCSNOOPLEN "ioctl" may fail if the capture length		 * supplied is too large, rather than just truncating it.		 * Also grab the data link type here.		 */		if (!(pcap = pcap_open_live(ifr->ifr_name, 68, 0, 0, pcap_errors)))			continue;		{			int linktype = pcap_datalink(pcap);			pcap_close(pcap);			/*			 * Skip interfaces where we can't use ethernet addresses.			 */			if (!(linktype == DLT_EN10MB || linktype == DLT_FDDI || linktype == DLT_IEEE802))				continue;		}		/*		 * Also skip interfaces that we can't be open with "libnet".		 * Some versions of libnet don't work with loopback interfaces.		 */		if (!(libnet = libnet_init(LIBNET_LINK, ifr->ifr_name, libnet_errors)))			continue;		libnet_destroy(libnet);		/*		 * If it's a loopback interface, add it to the loopback list,		 * otherwise add it after the normal list.		 */		{			char *port = strdup(ifr->ifr_name);			if ((ifrflags.ifr_flags & IFF_LOOPBACK) ||				strncmp(ifr->ifr_name, "lo", 2) == 0)				cdp_llist_append(loopback, port);			else				cdp_llist_append(normal, port);		}	}	FREE(buf);	close(sock);	FREE(pcap_errors);	FREE(libnet_errors);	cdp_llist_transfer(normal, loopback);	cdp_llist_free(loopback);	return normal;}cdp_t *cdp_new(const char *port, int flags, char *errors) {	cdp_t *cdp;	char *pcap_errors;	char *libnet_errors;		bpf_u_int32 mask;	bpf_u_int32 net;	struct bpf_program filter;	struct libnet_ether_addr *hwaddr;		pcap_errors = SALLOC(PCAP_ERRBUF_SIZE);	libnet_errors = SALLOC(LIBNET_ERRBUF_SIZE);	errors[0] = '\0';		cdp = CALLOC(1, cdp_t);	cdp->flags = flags;		{		int sock;		struct ifreq ifrflags;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -