Index: net-snmp/agent/mibgroup/kernel_sunos5.h
===================================================================
--- net-snmp/agent/mibgroup/kernel_sunos5.h (revision 16735)
+++ net-snmp/agent/mibgroup/kernel_sunos5.h (revision 16736)
@@ -193,6 +193,8 @@
int getKstatString(const char *statname, const char *varname,
char *value, size_t value_len);
+ int solaris2_if_nametoindex(const char *, int);
+
#ifdef _STDC_COMPAT
#ifdef __cplusplus
}
Index: net-snmp/agent/mibgroup/if-mib/data_access/interface_solaris2.c
===================================================================
--- net-snmp/agent/mibgroup/if-mib/data_access/interface_solaris2.c (revision 16735)
+++ net-snmp/agent/mibgroup/if-mib/data_access/interface_solaris2.c (revision 16736)
@@ -14,6 +14,7 @@
#include <sys/ioctl.h>
#include <sys/sockio.h>
#include <strings.h>
+#include <string.h>
static int _set_ip_flags_v4(netsnmp_interface_entry *, mib2_ifEntry_t *);
static int _match_ifname_v4addr(void *ifname, void *ipaddr);
@@ -43,25 +44,7 @@
#if defined(HAVE_IF_NAMETOINDEX)
return if_nametoindex(name);
#else /* use GIFINDEX */
- int sd;
- struct ifreq ifr;
-
- if (name == 0) {
- return (0);
- }
-
- if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
- return (0);
- }
-
- strncpy(ifr.ifr_name, name, IFNAMSIZ);
- if (ioctl(sd, SIOCGIFINDEX, (char *) &ifr) < 0) {
- close(sd);
- return (0);
- }
-
- close(sd);
- return (ifr.ifr_index);
+ return solaris2_if_nametoindex(name, strlen(name));
#endif /* defined(HAVE_IF_NAMETOINDEX) */
}
Index: net-snmp/agent/mibgroup/mibII/interfaces.c
===================================================================
--- net-snmp/agent/mibgroup/mibII/interfaces.c (revision 16735)
+++ net-snmp/agent/mibgroup/mibII/interfaces.c (revision 16736)
@@ -2245,71 +2245,7 @@
int
Interface_Index_By_Name(char *Name, int Len)
{
- int i, sd, lastlen = 0, interfaces = 0;
- struct ifconf ifc;
- struct ifreq *ifrp = NULL;
- char *buf = NULL;
-
- if (Name == 0) {
- return 0;
- }
- if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
- return 0;
- }
-
- /*
- * Cope with lots of interfaces and brokenness of ioctl SIOCGIFCONF
- * on some platforms; see W. R. Stevens, ``Unix Network Programming
- * Volume I'', p.435.
- */
-
- for (i = 8;; i += 8) {
- buf = calloc(i, sizeof(struct ifreq));
- if (buf == NULL) {
- close(sd);
- return 0;
- }
- ifc.ifc_len = i * sizeof(struct ifreq);
- ifc.ifc_buf = (caddr_t) buf;
-
- if (ioctl(sd, SIOCGIFCONF, (char *) &ifc) < 0) {
- if (errno != EINVAL || lastlen != 0) {
- /*
- * Something has gone genuinely wrong.
- */
- free(buf);
- close(sd);
- return 0;
- }
- /*
- * Otherwise, it could just be that the buffer is too small.
- */
- } else {
- if (ifc.ifc_len == lastlen) {
- /*
- * The length is the same as the last time; we're done.
- */
- break;
- }
- lastlen = ifc.ifc_len;
- }
- free(buf);
- }
-
- ifrp = ifc.ifc_req;
- interfaces = (ifc.ifc_len / sizeof(struct ifreq)) + 1;
-
- for (i = 1; i < interfaces; i++, ifrp++) {
- if (strncmp(ifrp->ifr_name, Name, Len) == 0) {
- free(buf);
- close(sd);
- return i;
- }
- }
-
- free(buf);
- close(sd);
- return 0;
+ return (solaris2_if_nametoindex(Name, Len));
}
#endif /* solaris2 */
Index: net-snmp/agent/mibgroup/kernel_sunos5.c
===================================================================
--- net-snmp/agent/mibgroup/kernel_sunos5.c (revision 16735)
+++ net-snmp/agent/mibgroup/kernel_sunos5.c (revision 16736)
@@ -169,11 +169,14 @@
getif(mib2_ifEntry_t *ifbuf, size_t size, req_e req_type, mib2_ifEntry_t *resp,
size_t *length, int (*comp)(void *, void *), void *arg);
static void
-set_if_info(mib2_ifEntry_t *ifp, unsigned index, char *name, uint64_t flags,int mtu);
+set_if_info(mib2_ifEntry_t *ifp, unsigned index, char *name, uint64_t flags,
+ int mtu);
static int get_if_stats(mib2_ifEntry_t *ifp);
-static int get_phys_address(mib2_ifEntry_t *ifp);
-static int _dlpi_phys_address(int fd, char *paddr, int maxlen, int *paddrlen);
+static int _dlpi_open(const char *devname);
+static int _dlpi_get_phys_address(int fd, char *paddr, int maxlen,
+ int *paddrlen);
+static int _dlpi_get_iftype(int fd, unsigned int *iftype);
static int _dlpi_attach(int fd, int ppa);
static int _dlpi_parse_devname(char *devname, int *ppap);
@@ -1047,7 +1050,7 @@
mib2_ifEntry_t *resp, size_t *length, int (*comp)(void *, void *),
void *arg)
{
- int i, ret;
+ int fd, i, ret;
int ifsd, ifsd6 = -1;
struct lifreq lifreq, *lifrp;
mib2_ifEntry_t *ifp;
@@ -1109,6 +1112,15 @@
memset(ifp, 0, sizeof(mib2_ifEntry_t));
+ if ((fd = _dlpi_open(ifnp->if_name)) != -1) {
+ /* Could open DLPI... now try to grab some info */
+ (void) _dlpi_get_phys_address(fd, ifp->ifPhysAddress.o_bytes,
+ sizeof(ifp->ifPhysAddress.o_bytes),
+ &ifp->ifPhysAddress.o_length);
+ (void) _dlpi_get_iftype(fd, &ifp->ifType);
+ close(fd);
+ }
+
set_if_info(ifp, ifnp->if_index, ifnp->if_name, if_flags,
lifrp->lifr_metric);
@@ -1117,9 +1129,6 @@
continue;
}
- /* try to obtain the physical address */
- (void) get_phys_address(ifp);
-
/*
* Once we reach here we know that all went well, so move to
* the next ifEntry.
@@ -1294,8 +1303,11 @@
#endif /*defined(HAVE_IF_NAMEINDEX)&&defined(NETSNMP_INCLUDE_IFTABLE_REWRITES)*/
static void
-set_if_info(mib2_ifEntry_t *ifp, unsigned index, char *name, uint64_t flags, int mtu)
+set_if_info(mib2_ifEntry_t *ifp, unsigned index, char *name, uint64_t flags,
+ int mtu)
{
+ boolean_t havespeed = B_FALSE;
+
/*
* Set basic information
*/
@@ -1307,101 +1319,122 @@
ifp->ifLastChange = 0; /* Who knows ... */
ifp->flags = flags;
ifp->ifMtu = mtu;
+ ifp->ifSpeed = 0;
- /* make ifOperStatus depend on link status if available */
- if (ifp->ifAdminStatus == 1) {
- int i_tmp;
- /* only UPed interfaces get correct link status - if any */
- if (getKstatInt(NULL, name,"link_up",&i_tmp) == 0) {
- ifp->ifOperStatus = i_tmp ? 1 : 2;
- }
- }
-
/*
- * Set link Type and Speed
+ * Get link speed
*/
- ifp->ifType = 1;
- ifp->ifSpeed = 0;
-
- if ((getKstatInt(NULL, name, "ifspeed", &ifp->ifSpeed) == 0) &&
- (ifp->ifSpeed != 0)) {
+ if ((getKstatInt(NULL, name, "ifspeed", &ifp->ifSpeed) == 0)) {
/*
* check for SunOS patch with half implemented ifSpeed
*/
- if (ifp->ifSpeed < 10000) {
+ if (ifp->ifSpeed > 0 && ifp->ifSpeed < 10000) {
ifp->ifSpeed *= 1000000;
}
+ havespeed = B_TRUE;
} else if (getKstatInt(NULL, name, "ifSpeed", &ifp->ifSpeed) == 0) {
/*
* this is good
*/
+ havespeed = B_TRUE;
}
- switch (name[0]) {
- case 'a': /* ath (802.11) */
- if (name[1] == 't' && name[2] == 'h')
- ifp->ifType = 71;
- break;
- case 'l': /* le / lo / lane (ATM LAN Emulation) */
- if (name[1] == 'o') {
- if (!ifp->ifSpeed)
- ifp->ifSpeed = 127000000;
- ifp->ifType = 24;
- } else if (name[1] == 'e') {
- if (!ifp->ifSpeed)
- ifp->ifSpeed = 10000000;
- ifp->ifType = 6;
- } else if (name[1] == 'a') {
- if (!ifp->ifSpeed)
- ifp->ifSpeed = 155000000;
- ifp->ifType = 37;
- }
- break;
+ /* make ifOperStatus depend on link status if available */
+ if (ifp->ifAdminStatus == 1) {
+ int i_tmp;
+ /* only UPed interfaces get correct link status - if any */
+ if (getKstatInt(NULL, name,"link_up",&i_tmp) == 0) {
+ ifp->ifOperStatus = i_tmp ? 1 : 2;
+#ifdef IFF_FAILED
+ } else if (flags & IFF_FAILED) {
+ /*
+ * If IPMP is used, and if the daemon marks the interface
+ * as 'failed', then we know for sure something is amiss.
+ */
+ ifp->ifOperStatus = 2;
+#endif
+ } else if (havespeed == B_TRUE && ifp->ifSpeed == 0) {
+ /* Heuristic */
+ ifp->ifOperStatus = 2;
+ }
+ }
- case 'g': /* ge (gigabit ethernet card) */
- case 'c': /* ce (Cassini Gigabit-Ethernet (PCI) */
- if (!ifp->ifSpeed)
- ifp->ifSpeed = 1000000000;
- ifp->ifType = 6;
- break;
-
- case 'h': /* hme (SBus card) */
- case 'e': /* eri (PCI card) */
- case 'b': /* be */
- case 'd': /* dmfe -- found on netra X1 */
- if (!ifp->ifSpeed)
- ifp->ifSpeed = 100000000;
- ifp->ifType = 6;
- break;
-
- case 'f': /* fa (Fore ATM) */
- if (!ifp->ifSpeed)
- ifp->ifSpeed = 155000000;
- ifp->ifType = 37;
- break;
-
- case 'q': /* qe (QuadEther)/qa (Fore ATM)/qfe (QuadFastEther) */
- if (name[1] == 'a') {
- if (!ifp->ifSpeed)
- ifp->ifSpeed = 155000000;
- ifp->ifType = 37;
- } else if (name[1] == 'e') {
+ /*
+ * Set link Type and Speed (if it could not be determined from kstat)
+ */
+ if (ifp->ifType == 24) {
+ ifp->ifSpeed = 127000000;
+ } else if (ifp->ifType == 1 || ifp->ifType == 0) {
+ /*
+ * Could not get the type from DLPI, so lets fall back to the hardcoded
+ * values.
+ */
+ switch (name[0]) {
+ case 'a': /* ath (802.11) */
+ if (name[1] == 't' && name[2] == 'h')
+ ifp->ifType = 71;
+ break;
+ case 'l': /* le / lo / lane (ATM LAN Emulation) */
+ if (name[1] == 'o') {
if (!ifp->ifSpeed)
+ ifp->ifSpeed = 127000000;
+ ifp->ifType = 24;
+ } else if (name[1] == 'e') {
+ if (!ifp->ifSpeed)
ifp->ifSpeed = 10000000;
ifp->ifType = 6;
- } else if (name[1] == 'f') {
+ } else if (name[1] == 'a') {
if (!ifp->ifSpeed)
- ifp->ifSpeed = 100000000;
+ ifp->ifSpeed = 155000000;
+ ifp->ifType = 37;
+ }
+ break;
+
+ case 'g': /* ge (gigabit ethernet card) */
+ case 'c': /* ce (Cassini Gigabit-Ethernet (PCI) */
+ if (!ifp->ifSpeed)
+ ifp->ifSpeed = 1000000000;
ifp->ifType = 6;
+ break;
+
+ case 'h': /* hme (SBus card) */
+ case 'e': /* eri (PCI card) */
+ case 'b': /* be */
+ case 'd': /* dmfe -- found on netra X1 */
+ if (!ifp->ifSpeed)
+ ifp->ifSpeed = 100000000;
+ ifp->ifType = 6;
+ break;
+
+ case 'f': /* fa (Fore ATM) */
+ if (!ifp->ifSpeed)
+ ifp->ifSpeed = 155000000;
+ ifp->ifType = 37;
+ break;
+
+ case 'q': /* qe (QuadEther)/qa (Fore ATM)/qfe (QuadFastEther) */
+ if (name[1] == 'a') {
+ if (!ifp->ifSpeed)
+ ifp->ifSpeed = 155000000;
+ ifp->ifType = 37;
+ } else if (name[1] == 'e') {
+ if (!ifp->ifSpeed)
+ ifp->ifSpeed = 10000000;
+ ifp->ifType = 6;
+ } else if (name[1] == 'f') {
+ if (!ifp->ifSpeed)
+ ifp->ifSpeed = 100000000;
+ ifp->ifType = 6;
+ }
+ break;
+
+ case 'i': /* ibd (Infiniband)/ip.tun (IP tunnel) */
+ if (name[1] == 'b')
+ ifp->ifType = 199;
+ else if (name[1] == 'p')
+ ifp->ifType = 131;
+ break;
}
- break;
-
- case 'i': /* ibd (Infiniband)/ip.tun (IP tunnel) */
- if (name[1] == 'b')
- ifp->ifType = 199;
- else if (name[1] == 'p')
- ifp->ifType = 131;
- break;
}
}
@@ -1491,68 +1524,69 @@
}
/*
- * Obtain the physical address using DLPI. Pieces of this code is directly
- * taken from libdlpi, which unfortunately is not yet commonly available.
+ * Open a DLPI device.
+ *
+ * On success the file descriptor is returned.
+ * On error -1 is returned.
*/
-
-static int
-get_phys_address(mib2_ifEntry_t *ifp)
+static int
+_dlpi_open(const char *devname)
{
- char *devstr;
- int fd;
- int ppa = -1;
- int rc = -1;
+ char *devstr;
+ int fd = -1;
+ int ppa = -1;
- DEBUGMSGTL(("kernel_sunos5", "get_phys_address called\n"));
+ DEBUGMSGTL(("kernel_sunos5", "_dlpi_open called\n"));
- if ((devstr = malloc(5 + ifp->ifDescr.o_length + 1)) == NULL)
+ if (devname == NULL)
return (-1);
- (void) sprintf(devstr, "/dev/%s", ifp->ifDescr.o_bytes);
+
+ if ((devstr = malloc(5 + strlen(devname) + 1)) == NULL)
+ return (-1);
+ (void) sprintf(devstr, "/dev/%s", devname);
DEBUGMSGTL(("kernel_sunos5:dlpi", "devstr(%s)\n", devstr));
/*
* First try opening the device using style 1, if the device does not
* exist we try style 2. Modules will not be pushed, so something like
* ip tunnels will not work.
*/
- if ((fd = open(devstr, O_RDWR | O_NONBLOCK)) != -1) {
- DEBUGMSGTL(("kernel_sunos5:dlpi", "style1 open(%s)\n", devstr));
- rc = _dlpi_phys_address(fd, ifp->ifPhysAddress.o_bytes,
- sizeof(ifp->ifPhysAddress.o_bytes),
- &ifp->ifPhysAddress.o_length);
- } else if (_dlpi_parse_devname(devstr, &ppa) == 0) {
- DEBUGMSGTL(("kernel_sunos5:dlpi", "style2 parse: %s, %d\n",
- devstr, ppa));
- /* try style 2 */
- if ((fd = open(devstr, O_RDWR | O_NONBLOCK)) != -1) {
- DEBUGMSGTL(("kernel_sunos5:dlpi", "style2 open(%s)\n", devstr));
- if (_dlpi_attach(fd, ppa) == 0) {
- DEBUGMSGTL(("kernel_sunos5:dlpi", "attached\n"));
- rc = _dlpi_phys_address(fd, ifp->ifPhysAddress.o_bytes,
- sizeof(ifp->ifPhysAddress.o_bytes),
- &ifp->ifPhysAddress.o_length);
- }
- }
- }
+
+ DEBUGMSGTL(("kernel_sunos5:dlpi", "style1 open(%s)\n", devstr));
+ if ((fd = open(devstr, O_RDWR | O_NONBLOCK)) < 0) {
+ DEBUGMSGTL(("kernel_sunos5:dlpi", "style1 open failed\n"));
+ if (_dlpi_parse_devname(devstr, &ppa) == 0) {
+ DEBUGMSGTL(("kernel_sunos5:dlpi", "style2 parse: %s, %d\n",
+ devstr, ppa));
+ /* try style 2 */
+ DEBUGMSGTL(("kernel_sunos5:dlpi", "style2 open(%s)\n", devstr));
- free(devstr);
- if (fd != -1)
- close(fd);
+ if ((fd = open(devstr, O_RDWR | O_NONBLOCK)) != -1) {
+ if (_dlpi_attach(fd, ppa) == 0) {
+ DEBUGMSGTL(("kernel_sunos5:dlpi", "attached\n"));
+ } else {
+ DEBUGMSGTL(("kernel_sunos5:dlpi", "attached failed\n"));
+ close(fd);
+ fd = -1;
+ }
+ } else {
+ DEBUGMSGTL(("kernel_sunos5:dlpi", "style2 open failed\n"));
+ }
+ }
+ } else {
+ DEBUGMSGTL(("kernel_sunos5:dlpi", "style1 open succeeded\n"));
+ }
- if (rc == 0) {
- /* successful */
- DEBUGMSGTL(("kernel_sunos5:dlpi", "got phys addr using DLPI\n"));
- return (0);
- } else {
- DEBUGMSGTL(("kernel_sunos5:dlpi", "unable to get phys address\n"));
- return (-1);
- }
+ /* clean up */
+ free(devstr);
+
+ return (fd);
}
/*
- *
+ * Obtain the physical address of the interface using DLPI
*/
static int
-_dlpi_phys_address(int fd, char *addr, int maxlen, int *addrlen)
+_dlpi_get_phys_address(int fd, char *addr, int maxlen, int *addrlen)
{
dl_phys_addr_req_t paddr_req;
union DL_primitives *dlp;
@@ -1560,6 +1594,8 @@
char buf[MAX(DL_PHYS_ADDR_ACK_SIZE+64, DL_ERROR_ACK_SIZE)];
int flag = 0;
+ DEBUGMSGTL(("kernel_sunos5:dlpi", "_dlpi_get_phys_address\n"));
+
paddr_req.dl_primitive = DL_PHYS_ADDR_REQ;
paddr_req.dl_addr_type = DL_CURR_PHYS_ADDR;
ctlbuf.buf = (char *)&paddr_req;
@@ -1570,7 +1606,7 @@
ctlbuf.maxlen = sizeof(buf);
ctlbuf.len = 0;
ctlbuf.buf = buf;
- if (getmsg(fd, &ctlbuf, NULL, &flag) != 0)
+ if (getmsg(fd, &ctlbuf, NULL, &flag) < 0)
return (-1);
if (ctlbuf.len < sizeof(uint32_t))
@@ -1580,6 +1616,7 @@
case DL_PHYS_ADDR_ACK: {
dl_phys_addr_ack_t *phyp = (dl_phys_addr_ack_t *)buf;
+ DEBUGMSGTL(("kernel_sunos5:dlpi", "got ACK\n"));
if (ctlbuf.len < DL_PHYS_ADDR_ACK_SIZE || phyp->dl_addr_length > maxlen)
return (-1);
(void) memcpy(addr, buf+phyp->dl_addr_offset, phyp->dl_addr_length);
@@ -1589,16 +1626,137 @@
case DL_ERROR_ACK: {
dl_error_ack_t *errp = (dl_error_ack_t *)buf;
+ DEBUGMSGTL(("kernel_sunos5:dlpi", "got ERROR ACK\n"));
if (ctlbuf.len < DL_ERROR_ACK_SIZE)
return (-1);
return (errp->dl_errno);
}
default:
+ DEBUGMSGTL(("kernel_sunos5:dlpi", "got type: %x\n", dlp->dl_primitive));
return (-1);
}
}
+/*
+ * Query the interface about it's type.
+ */
static int
+_dlpi_get_iftype(int fd, unsigned int *iftype)
+{
+ dl_info_req_t info_req;
+ union DL_primitives *dlp;
+ struct strbuf ctlbuf;
+ char buf[MAX(DL_INFO_ACK_SIZE, DL_ERROR_ACK_SIZE)];
+ int flag = 0;
+
+ DEBUGMSGTL(("kernel_sunos5:dlpi", "_dlpi_get_iftype\n"));
+
+ info_req.dl_primitive = DL_INFO_REQ;
+ ctlbuf.buf = (char *)&info_req;
+ ctlbuf.len = DL_INFO_REQ_SIZE;
+ if (putmsg(fd, &ctlbuf, NULL, 0) < 0) {
+ DEBUGMSGTL(("kernel_sunos5:dlpi", "putmsg failed: %d\nn", errno));
+ return (-1);
+ }
+
+ ctlbuf.maxlen = sizeof(buf);
+ ctlbuf.len = 0;
+ ctlbuf.buf = buf;
+ if (getmsg(fd, &ctlbuf, NULL, &flag) < 0) {
+ DEBUGMSGTL(("kernel_sunos5:dlpi", "getmsg failed: %d\n", errno));
+ return (-1);
+ }
+
+ if (ctlbuf.len < sizeof(uint32_t))
+ return (-1);
+ dlp = (union DL_primitives *)buf;
+ switch (dlp->dl_primitive) {
+ case DL_INFO_ACK: {
+ dl_info_ack_t *info = (dl_info_ack_t *)buf;
+
+ if (ctlbuf.len < DL_INFO_ACK_SIZE)
+ return (-1);
+
+ DEBUGMSGTL(("kernel_sunos5:dlpi", "dl_mac_type: %x\n",
+ info->dl_mac_type));
+ switch (info->dl_mac_type) {
+ case DL_CSMACD:
+ case DL_ETHER:
+ case DL_ETH_CSMA:
+ *iftype = 6;
+ break;
+ case DL_TPB: /* Token Passing Bus */
+ *iftype = 8;
+ break;
+ case DL_TPR: /* Token Passing Ring */
+ *iftype = 9;
+ break;
+ case DL_HDLC:
+ *iftype = 118;
+ break;
+ case DL_FDDI:
+ *iftype = 15;
+ break;
+ case DL_FC: /* Fibre channel */
+ *iftype = 56;
+ break;
+ case DL_ATM:
+ *iftype = 37;
+ break;
+ case DL_X25:
+ case DL_ISDN:
+ *iftype = 63;
+ break;
+ case DL_HIPPI:
+ *iftype = 47;
+ break;
+#ifdef DL_IB
+ case DL_IB:
+ *iftype = 199;
+ break;
+#endif
+ case DL_FRAME: /* Frame Relay */
+ *iftype = 32;
+ break;
+ case DL_LOOP:
+ *iftype = 24;
+ break;
+#ifdef DL_WIFI
+ case DL_WIFI:
+ *iftype = 71;
+ break;
+#endif
+#ifdef DL_IPV4 /* then IPv6 is also defined */
+ case DL_IPV4: /* IPv4 Tunnel */
+ case DL_IPV6: /* IPv6 Tunnel */
+ *iftype = 131;
+ break;
+#endif
+ default:
+ *iftype = 1; /* Other */
+ break;
+ }
+
+ return (0);
+ }
+ case DL_ERROR_ACK: {
+ dl_error_ack_t *errp = (dl_error_ack_t *)buf;
+
+ DEBUGMSGTL(("kernel_sunos5:dlpi",
+ "got DL_ERROR_ACK: dlpi %d, error %d\n", errp->dl_errno,
+ errp->dl_unix_errno));
+
+ if (ctlbuf.len < DL_ERROR_ACK_SIZE)
+ return (-1);
+ return (errp->dl_errno);
+ }
+ default:
+ DEBUGMSGTL(("kernel_sunos5:dlpi", "got type %x\n", dlp->dl_primitive));
+ return (-1);
+ }
+}
+
+static int
_dlpi_attach(int fd, int ppa)
{
dl_attach_req_t attach_req;
@@ -1680,8 +1838,83 @@
} else {
return 1;
}
-}
+}
+/*
+ * Try to determine the index of a particular interface. If mfd-rewrites is
+ * specified, then this function would only be used when the system does not
+ * have if_nametoindex(3SOCKET).
+ */
+int
+solaris2_if_nametoindex(const char *Name, int Len)
+{
+ int i, sd, lastlen = 0, interfaces = 0;
+ struct ifconf ifc;
+ struct ifreq *ifrp = NULL;
+ char *buf = NULL;
+
+ if (Name == 0) {
+ return 0;
+ }
+ if ((sd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+ return 0;
+ }
+
+ /*
+ * Cope with lots of interfaces and brokenness of ioctl SIOCGIFCONF
+ * on some platforms; see W. R. Stevens, ``Unix Network Programming
+ * Volume I'', p.435.
+ */
+
+ for (i = 8;; i += 8) {
+ buf = calloc(i, sizeof(struct ifreq));
+ if (buf == NULL) {
+ close(sd);
+ return 0;
+ }
+ ifc.ifc_len = i * sizeof(struct ifreq);
+ ifc.ifc_buf = (caddr_t) buf;
+
+ if (ioctl(sd, SIOCGIFCONF, (char *) &ifc) < 0) {
+ if (errno != EINVAL || lastlen != 0) {
+ /*
+ * Something has gone genuinely wrong.
+ */
+ free(buf);
+ close(sd);
+ return 0;
+ }
+ /*
+ * Otherwise, it could just be that the buffer is too small.
+ */
+ } else {
+ if (ifc.ifc_len == lastlen) {
+ /*
+ * The length is the same as the last time; we're done.
+ */
+ break;
+ }
+ lastlen = ifc.ifc_len;
+ }
+ free(buf);
+ }
+
+ ifrp = ifc.ifc_req;
+ interfaces = (ifc.ifc_len / sizeof(struct ifreq)) + 1;
+
+ for (i = 1; i < interfaces; i++, ifrp++) {
+ if (strncmp(ifrp->ifr_name, Name, Len) == 0) {
+ free(buf);
+ close(sd);
+ return i;
+ }
+ }
+
+ free(buf);
+ close(sd);
+ return 0;
+}
+
#ifdef _STDC_COMPAT
#ifdef __cplusplus
}