summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--main/utils.c244
1 files changed, 199 insertions, 45 deletions
diff --git a/main/utils.c b/main/utils.c
index fc7aa30d7..fd1edf490 100644
--- a/main/utils.c
+++ b/main/utils.c
@@ -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)
{