mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-11-03 20:38:59 +00:00 
			
		
		
		
	Merge "utils.c: Fix ast_set_default_eid for multiple platforms"
This commit is contained in:
		
							
								
								
									
										252
									
								
								main/utils.c
									
									
									
									
									
								
							
							
						
						
									
										252
									
								
								main/utils.c
									
									
									
									
									
								
							@@ -2508,73 +2508,227 @@ char *ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
 | 
			
		||||
	return os;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__Darwin__)
 | 
			
		||||
#include <ifaddrs.h>
 | 
			
		||||
#include <net/if_dl.h>
 | 
			
		||||
 | 
			
		||||
void ast_set_default_eid(struct ast_eid *eid)
 | 
			
		||||
{
 | 
			
		||||
#if defined(SIOCGIFHWADDR) && defined(HAVE_STRUCT_IFREQ_IFR_IFRU_IFRU_HWADDR)
 | 
			
		||||
	int s, x = 0;
 | 
			
		||||
	struct ifaddrs *ifap, *ifaphead;
 | 
			
		||||
	int rtnerr;
 | 
			
		||||
	const struct sockaddr_dl *sdl;
 | 
			
		||||
	int alen;
 | 
			
		||||
	caddr_t ap;
 | 
			
		||||
	char eid_str[20];
 | 
			
		||||
	struct ifreq ifr;
 | 
			
		||||
	static const unsigned int MAXIF = 10;
 | 
			
		||||
	unsigned char empty_mac[6] = {0, 0, 0, 0, 0, 0};
 | 
			
		||||
	unsigned char full_mac[6]  = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
 | 
			
		||||
 | 
			
		||||
	s = socket(AF_INET, SOCK_STREAM, 0);
 | 
			
		||||
	if (s < 0) {
 | 
			
		||||
	rtnerr = getifaddrs(&ifaphead);
 | 
			
		||||
	if (rtnerr) {
 | 
			
		||||
		ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
 | 
			
		||||
			"You will have to set it manually.\n");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	for (x = 0; x < MAXIF; x++) {
 | 
			
		||||
		static const char *prefixes[] = { "eth", "em", "eno", "ens" };
 | 
			
		||||
		unsigned int i;
 | 
			
		||||
 | 
			
		||||
		for (i = 0; i < ARRAY_LEN(prefixes); i++) {
 | 
			
		||||
			memset(&ifr, 0, sizeof(ifr));
 | 
			
		||||
			snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s%d", prefixes[i], x);
 | 
			
		||||
			if (!ioctl(s, SIOCGIFHWADDR, &ifr)) {
 | 
			
		||||
				break;
 | 
			
		||||
			}
 | 
			
		||||
	if (!ifaphead) {
 | 
			
		||||
		ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
 | 
			
		||||
			"You will have to set it manually.\n");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (ifap = ifaphead; ifap; ifap = ifap->ifa_next) {
 | 
			
		||||
		if (ifap->ifa_addr->sa_family != AF_LINK) {
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (i == ARRAY_LEN(prefixes)) {
 | 
			
		||||
			/* Try pciX#[1..N] */
 | 
			
		||||
			for (i = 0; i < MAXIF; i++) {
 | 
			
		||||
				memset(&ifr, 0, sizeof(ifr));
 | 
			
		||||
				snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "pci%d#%u", x, i);
 | 
			
		||||
				if (!ioctl(s, SIOCGIFHWADDR, &ifr)) {
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if (i == MAXIF) {
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
		sdl = (const struct sockaddr_dl *) ifap->ifa_addr;
 | 
			
		||||
		ap = ((caddr_t) ((sdl)->sdl_data + (sdl)->sdl_nlen));
 | 
			
		||||
		alen = sdl->sdl_alen;
 | 
			
		||||
		if (alen != 6 || !(memcmp(ap, &empty_mac, 6) && memcmp(ap, &full_mac, 6))) {
 | 
			
		||||
			continue;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		memcpy(eid, ((unsigned char *)&ifr.ifr_hwaddr) + 2, sizeof(*eid));
 | 
			
		||||
		ast_debug(1, "Seeding global EID '%s' from '%s' using 'siocgifhwaddr'\n", ast_eid_to_str(eid_str, sizeof(eid_str), eid), ifr.ifr_name);
 | 
			
		||||
		memcpy(eid, ap, sizeof(*eid));
 | 
			
		||||
		ast_debug(1, "Seeding global EID '%s'\n",
 | 
			
		||||
				ast_eid_to_str(eid_str, sizeof(eid_str), eid));
 | 
			
		||||
		freeifaddrs(ifaphead);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
 | 
			
		||||
		"You will have to set it manually.\n");
 | 
			
		||||
	freeifaddrs(ifaphead);
 | 
			
		||||
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#elif defined(SOLARIS)
 | 
			
		||||
#include <sys/sockio.h>
 | 
			
		||||
#include <net/if_arp.h>
 | 
			
		||||
 | 
			
		||||
void ast_set_default_eid(struct ast_eid *eid)
 | 
			
		||||
{
 | 
			
		||||
	int s;
 | 
			
		||||
	int x;
 | 
			
		||||
	int res = 0;
 | 
			
		||||
	struct lifreq *ifr = NULL;
 | 
			
		||||
	struct lifnum ifn;
 | 
			
		||||
	struct lifconf ifc;
 | 
			
		||||
	struct arpreq ar;
 | 
			
		||||
	struct sockaddr_in *sa, *sa2;
 | 
			
		||||
	char *buf = NULL;
 | 
			
		||||
	char eid_str[20];
 | 
			
		||||
	int bufsz;
 | 
			
		||||
	unsigned char empty_mac[6] = {0, 0, 0, 0, 0, 0};
 | 
			
		||||
	unsigned char full_mac[6]  = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
 | 
			
		||||
 | 
			
		||||
	s = socket(AF_INET, SOCK_STREAM, 0);
 | 
			
		||||
	if (s <= 0) {
 | 
			
		||||
		ast_log(LOG_WARNING, "Unable to open a socket for seeding global EID. "
 | 
			
		||||
			" You will have to set it manually.\n");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/* Get a count of interfaces on the machine */
 | 
			
		||||
	ifn.lifn_family = AF_UNSPEC;
 | 
			
		||||
	ifn.lifn_flags = 0;
 | 
			
		||||
	ifn.lifn_count = 0;
 | 
			
		||||
	if (ioctl(s, SIOCGLIFNUM, &ifn) < 0) {
 | 
			
		||||
		ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
 | 
			
		||||
			" You will have to set it manually.\n");
 | 
			
		||||
		close(s);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	close(s);
 | 
			
		||||
#else
 | 
			
		||||
#if defined(ifa_broadaddr) && !defined(SOLARIS)
 | 
			
		||||
	char eid_str[20];
 | 
			
		||||
	struct ifaddrs *ifap;
 | 
			
		||||
 | 
			
		||||
	if (getifaddrs(&ifap) == 0) {
 | 
			
		||||
		struct ifaddrs *p;
 | 
			
		||||
		for (p = ifap; p; p = p->ifa_next) {
 | 
			
		||||
			if ((p->ifa_addr->sa_family == AF_LINK) && !(p->ifa_flags & IFF_LOOPBACK) && (p->ifa_flags & IFF_RUNNING)) {
 | 
			
		||||
				struct sockaddr_dl* sdp = (struct sockaddr_dl*) p->ifa_addr;
 | 
			
		||||
				memcpy(&(eid->eid), sdp->sdl_data + sdp->sdl_nlen, 6);
 | 
			
		||||
				ast_debug(1, "Seeding global EID '%s' from '%s' using 'getifaddrs'\n", ast_eid_to_str(eid_str, sizeof(eid_str), eid), p->ifa_name);
 | 
			
		||||
				freeifaddrs(ifap);
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		freeifaddrs(ifap);
 | 
			
		||||
	bufsz = ifn.lifn_count * sizeof(struct lifreq);
 | 
			
		||||
	if (!(buf = ast_malloc(bufsz))) {
 | 
			
		||||
		ast_log(LOG_WARNING, "Unable to allocate memory for seeding global EID. "
 | 
			
		||||
			"You will have to set it manually.\n");
 | 
			
		||||
		close(s);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
#endif
 | 
			
		||||
#endif
 | 
			
		||||
	ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. You will have to set it manually.\n");
 | 
			
		||||
	memset(buf, 0, bufsz);
 | 
			
		||||
 | 
			
		||||
	/* Get a list of interfaces on the machine */
 | 
			
		||||
	ifc.lifc_len = bufsz;
 | 
			
		||||
	ifc.lifc_buf = buf;
 | 
			
		||||
	ifc.lifc_family = AF_UNSPEC;
 | 
			
		||||
	ifc.lifc_flags = 0;
 | 
			
		||||
	if (ioctl(s, SIOCGLIFCONF, &ifc) < 0) {
 | 
			
		||||
		ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
 | 
			
		||||
			"You will have to set it manually.\n");
 | 
			
		||||
		ast_free(buf);
 | 
			
		||||
		close(s);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for (ifr = (struct lifreq *)buf, x = 0; x < ifn.lifn_count; ifr++, x++) {
 | 
			
		||||
		unsigned char *p;
 | 
			
		||||
 | 
			
		||||
		sa = (struct sockaddr_in *)&(ifr->lifr_addr);
 | 
			
		||||
		sa2 = (struct sockaddr_in *)&(ar.arp_pa);
 | 
			
		||||
		*sa2 = *sa;
 | 
			
		||||
 | 
			
		||||
		if(ioctl(s, SIOCGARP, &ar) >= 0) {
 | 
			
		||||
			p = (unsigned char *)&(ar.arp_ha.sa_data);
 | 
			
		||||
			if (!(memcmp(p, &empty_mac, 6) && memcmp(p, &full_mac, 6))) {
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			memcpy(eid, p, sizeof(*eid));
 | 
			
		||||
			ast_debug(1, "Seeding global EID '%s'\n",
 | 
			
		||||
				ast_eid_to_str(eid_str, sizeof(eid_str), eid));
 | 
			
		||||
			ast_free(buf);
 | 
			
		||||
			close(s);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
 | 
			
		||||
		"You will have to set it manually.\n");
 | 
			
		||||
	ast_free(buf);
 | 
			
		||||
	close(s);
 | 
			
		||||
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#else
 | 
			
		||||
void ast_set_default_eid(struct ast_eid *eid)
 | 
			
		||||
{
 | 
			
		||||
	int s;
 | 
			
		||||
	int i;
 | 
			
		||||
	struct ifreq *ifr;
 | 
			
		||||
	struct ifreq *ifrp;
 | 
			
		||||
	struct ifconf ifc;
 | 
			
		||||
	char *buf = NULL;
 | 
			
		||||
	char eid_str[20];
 | 
			
		||||
	int bufsz, num_interfaces;
 | 
			
		||||
	unsigned char empty_mac[6] = {0, 0, 0, 0, 0, 0};
 | 
			
		||||
	unsigned char full_mac[6]  = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF};
 | 
			
		||||
 | 
			
		||||
	s = socket(AF_INET, SOCK_STREAM, 0);
 | 
			
		||||
	if (s <= 0) {
 | 
			
		||||
		ast_log(LOG_WARNING, "Unable to open socket for seeding global EID. "
 | 
			
		||||
			"You will have to set it manually.\n");
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ifc.ifc_len = 0;
 | 
			
		||||
	ifc.ifc_buf = NULL;
 | 
			
		||||
	if (ioctl(s, SIOCGIFCONF, &ifc) || ifc.ifc_len <= 0) {
 | 
			
		||||
		ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
 | 
			
		||||
			"You will have to set it manually.\n");
 | 
			
		||||
		close(s);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
	bufsz = ifc.ifc_len;
 | 
			
		||||
 | 
			
		||||
	if (!(buf = ast_malloc(bufsz))) {
 | 
			
		||||
		ast_log(LOG_WARNING, "Unable to allocate memory for seeding global EID. "
 | 
			
		||||
			"You will have to set it manually.\n");
 | 
			
		||||
		close(s);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ifc.ifc_buf = buf;
 | 
			
		||||
	if (ioctl(s, SIOCGIFCONF, &ifc) < 0) {
 | 
			
		||||
		ast_log(LOG_WARNING, "Unable to retrieve ethernet interfaces for seeding global EID. "
 | 
			
		||||
			"You will have to set it manually.\n");
 | 
			
		||||
		ast_free(buf);
 | 
			
		||||
		close(s);
 | 
			
		||||
		return;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ifrp = ifc.ifc_req;
 | 
			
		||||
	num_interfaces = ifc.ifc_len / sizeof(*ifr);
 | 
			
		||||
 | 
			
		||||
	for (i = 0; i < num_interfaces; i++) {
 | 
			
		||||
		ifr = &ifrp[i];
 | 
			
		||||
		if (!ioctl(s, SIOCGIFHWADDR, ifr)) {
 | 
			
		||||
			unsigned char *hwaddr = (unsigned char *) ifr->ifr_hwaddr.sa_data;
 | 
			
		||||
 | 
			
		||||
			if (!(memcmp(hwaddr, &empty_mac, 6) && memcmp(hwaddr, &full_mac, 6))) {
 | 
			
		||||
				continue;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			memcpy(eid, hwaddr, sizeof(*eid));
 | 
			
		||||
			ast_debug(1, "Seeding global EID '%s' from '%s' using 'siocgifhwaddr'\n",
 | 
			
		||||
				ast_eid_to_str(eid_str, sizeof(eid_str), eid), ifr->ifr_name);
 | 
			
		||||
			ast_free(buf);
 | 
			
		||||
			close(s);
 | 
			
		||||
			return;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. "
 | 
			
		||||
		"You will have to set it manually.\n");
 | 
			
		||||
	ast_free(buf);
 | 
			
		||||
	close(s);
 | 
			
		||||
 | 
			
		||||
	return;
 | 
			
		||||
}
 | 
			
		||||
#endif /* LINUX */
 | 
			
		||||
 | 
			
		||||
int ast_str_to_eid(struct ast_eid *eid, const char *s)
 | 
			
		||||
{
 | 
			
		||||
	unsigned int eid_int[6];
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user