Merge "utils.c: Fix ast_set_default_eid for multiple platforms"

changes/61/4161/1
zuul 9 years ago committed by Gerrit Code Review
commit 7c00b34372

@ -2508,72 +2508,226 @@ 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;
}
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;
}
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
#if defined(ifa_broadaddr) && !defined(SOLARIS)
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];
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;
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;
}
freeifaddrs(ifap);
}
#endif
#endif
ast_log(LOG_WARNING, "No ethernet interface found for seeding global EID. You will have to set it manually.\n");
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)
{

Loading…
Cancel
Save