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 )