mirror of
				https://github.com/asterisk/asterisk.git
				synced 2025-10-31 02:37:10 +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