[PATCH] Use libnl to get interface MAC and IP addresses

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



From: David L. Cantrell Jr <dcantrell@xxxxxxxxxx>

Reduce nl.c to enough to communicate with libnl.  We already have
libnl, so we might as well use it.  Plus, the latest version has
a reasonable API, so I'm totally against using it.

The _isys module and loader have been updated to call the new
functions:  nl_mac2str() and nl_ip2str() to get the MAC address or
IP address for the specified interface.

This patch also drops our need for glib for isys.  Yeah, I added the
dep and I'm removing it.
---
 isys/Makefile        |   13 +-
 isys/isys.c          |    6 +-
 isys/nl.c            |  699 +++++++++++---------------------------------------
 isys/nl.h            |   31 +--
 loader2/net.c        |    2 +-
 loader2/nfsinstall.c |    5 +-
 loader2/urlinstall.c |    5 +-
 7 files changed, 166 insertions(+), 595 deletions(-)

diff --git a/isys/Makefile b/isys/Makefile
index d5d0f09..7f2d304 100644
--- a/isys/Makefile
+++ b/isys/Makefile
@@ -35,9 +35,9 @@ endif
 PYMODULES = _isys.so
 SUBDIRS = 
 
-# glib
-LOADLIBES += $(shell pkg-config --libs glib-2.0)
-CFLAGS    += $(shell pkg-config --cflags glib-2.0)
+# libnl
+LOADLIBES += $(shell pkg-config --libs libnl-1)
+CFLAGS    += $(shell pkg-config --cflags libnl-1)
 
 # libdhcp
 LOADLIBES += $(shell pkg-config --libs libdhcp)
@@ -101,14 +101,9 @@ nfsmount.do: nfs_mountversion.h
 nfs_mountversion.h: /usr/include/linux/nfs_mount.h
 	grep NFS_MOUNT_VERSION $< | sed -e 's/NFS/KERNEL_NFS/' > $@
 
-nltest: str.o nl.c nl.h
-	$(CC) -c $(CFLAGS) -DTESTING nl.c -o nl.o
-	$(CC) -DTESTING nl.o -o nl $(LOADLIBES) str.o
-
 depend: nfs_mountversion.h
 	$(CPP) -M $(CFLAGS) $(SOURCES) > .depend
 
 ifeq (.depend,$(wildcard .depend))
 include .depend
-endif                                           
-
+endif
diff --git a/isys/isys.c b/isys/isys.c
index 1a37359..9395f0f 100644
--- a/isys/isys.c
+++ b/isys/isys.c
@@ -1041,7 +1041,7 @@ static PyObject * doGetMacAddress(PyObject * s, PyObject * args) {
     if (!PyArg_ParseTuple(args, "s", &dev))
         return NULL;
 
-    ret = netlink_interfaces_mac2str(dev);
+    ret = nl_mac2str(dev);
 
     return Py_BuildValue("s", ret);
 }
@@ -1063,9 +1063,9 @@ static PyObject * doGetIPAddress(PyObject * s, PyObject * args) {
     char *ret = NULL;
 
     if (!PyArg_ParseTuple(args, "s", &dev))
-	return NULL;
+        return NULL;
 
-    ret = netlink_interfaces_ip2str(dev);
+    ret = nl_ip2str(dev);
 
     return Py_BuildValue("s", ret);
 }
diff --git a/isys/nl.c b/isys/nl.c
index 84d7006..87178e5 100644
--- a/isys/nl.c
+++ b/isys/nl.c
@@ -21,612 +21,211 @@
 
 #include <stdio.h>
 #include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-#include <unistd.h>
-
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <linux/netlink.h>
-#include <linux/rtnetlink.h>
-#include <linux/if.h>
-#include <arpa/inet.h>
-#include <net/if_arp.h>
-
-#include <glib.h>
+#include <netinet/in.h>
+#include <netlink/netlink.h>
+#include <netlink/socket.h>
+#include <netlink/route/addr.h>
+#include <netlink/route/link.h>
 
 #include "nl.h"
 #include "str.h"
 
-/* A linked list of interface_info_t structures (see nl.h) */
-static GSList *interfaces = NULL;
-
-/**
- * Not really Netlink-specific, but handy nonetheless.  Takes a MAC address
- * and converts it to the familiar hexidecimal notation for easy reading.
- *
- * @param mac The unsigned char MAC address value.
- * @param buf The string to write the formatted address to.
- * @return Pointer to buf.
- */
-char *netlink_format_mac_addr(char *buf, unsigned char *mac) {
-    if (buf == NULL) {
-        if ((buf = malloc(20)) == NULL) {
-            perror("malloc in netlink_format_mac_addr");
-            return NULL;
-        }
-    }
-
-    sprintf(buf, "%02x:%02x:%02x:%02x:%02x:%02x",
-            mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
-
-    return str2upper(buf);
-}
-
-/**
- * Convert cylon-readable IP address to human-readable format (either v4
- * or v6).
- *
- * @param family The address family.
- * @param intf The interface_info_t structure with the IP address info.
- * @param buf The buffer to write the formatted IP address to.
- * @return A pointer to buf.
- */
-char *netlink_format_ip_addr(int family, interface_info_t *intf, char *buf) {
-    int iplen;
-
-    if (family == AF_INET6)
-        iplen = INET6_ADDRSTRLEN;
-    else
-        iplen = INET_ADDRSTRLEN;
-
-    if (buf == NULL) {
-        if ((buf = malloc(iplen)) == NULL) {
-            perror("malloc in netlink_format_ip_addr");
-            return NULL;
-        }
-
-        memset(buf, 0, iplen);
-    }
-
-    switch (family) {
-        case AF_INET:
-            inet_ntop(family, &(intf->ip_addr), buf, iplen);
-            break;
-        case AF_INET6:
-            inet_ntop(family, &(intf->ip6_addr), buf, iplen);
-            break;
-    }
-
-    return buf;
-}
-
-/**
- * Create a new PF_NETLINK socket for communication with the kernel Netlink
- * layer.  Open with NETLINK_ROUTE protocol since we want IPv4 and IPv6
- * interface, address, and routing information.
- *
- * @return Handle to new socket or -1 on error.
- */
-int netlink_create_socket(void) {
-    int sock;
-
-    sock = socket(PF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
-    if (sock < 0) {
-        perror("netlink socket");
-        return -1;
-    }
-
-    return sock;
-}
-
-/**
- * Send a dump request message for the specified information in the
- * specified family type.  Family may be AF_INET or AF_INET6, for
- * example.  The request type should be a GET type as specified in
- * /usr/include/linux/rtnetlink.h (for example, RTM_GETLINK).
- *
- * @param sock The Netlink socket to use.
- * @param type The Netlink request type.
- * @param family The address family.
- * @return The number of characters sent or -1 on error.
- */
-int netlink_send_dump_request(int sock, int type, int family) {
-    int ret;
-    char buf[BUFSZ];
-    struct sockaddr_nl snl;
-    struct nlmsghdr *nlh;
-    struct rtgenmsg *g;
-
-    memset(&snl, 0, sizeof(snl));
-    snl.nl_family = AF_NETLINK;
-
-    memset(buf, 0, sizeof(buf));
-    nlh = (struct nlmsghdr *)buf;
-    g = (struct rtgenmsg *)(buf + sizeof(struct nlmsghdr));
-
-    nlh->nlmsg_len = NLMSG_LENGTH(sizeof(struct rtgenmsg));
-    nlh->nlmsg_flags = NLM_F_REQUEST|NLM_F_DUMP;
-    nlh->nlmsg_type = type;
-    g->rtgen_family = family;
-
-    ret = sendto(sock, buf, nlh->nlmsg_len, 0, (struct sockaddr *)&snl,
-                 sizeof(snl));
-    if (ret < 0) {
-        perror("netlink_send_dump_request sendto");
-        return -1;
-    }
-
-    return ret;
-}
-
-/**
- * Look for an IP address for the given interface.
- *
- * @param index The interface index number.
- * @param family The address family (AF_INET or AF_INET6).
- * @param addr Pointer to where we should write the IP address.
- * @return -1 on error, 0 on success.
+/*
+ * Return an NETLINK_ROUTE cache.
  */
-int netlink_get_interface_ip(int index, int family, void *addr) {
-    int sock, ret, len, alen;
-    ssize_t bufsz, readsz;
-    char *buf = NULL;
-    struct nlmsghdr *nlh;
-    struct ifaddrmsg *ifa;
-    struct rtattr *rta;
-    struct rtattr *tb[IFLA_MAX+1];
-
-    /* get a socket */
-    if ((sock = netlink_create_socket()) == -1) {
-        perror("netlink_create_socket in netlink_get_interface_ip");
-        close(sock);
-        return -1;
-    }
-
-    /* send dump request */
-    ret = netlink_send_dump_request(sock, RTM_GETADDR, family);
-    if (ret <= 0) {
-        if (ret < 0)
-            perror("netlink_send_dump_request in netlink_get_interface_ip");
-        close(sock);
-        return ret < 0 ? -1 : 0;
-    }
+struct nl_cache *nl_get_link_cache(struct nl_handle **handle) {
+    struct nl_cache *cache = NULL;
 
-    /* MSG_TRUNC doesn't actually seem to /work/ with netlink on RHEL 5,
-     * so we do this lame growth game until we have a buffer big enough.
-     * When we're done (which is the first time if MSG_TRUNC does its job),
-     * bufsz is the size of the message. Then we allocate a real buffer and
-     * do recvfrom again without MSG_PEEK. */
-    len = 32;
-    do {
-        len <<= 1;
-        char tmpbuf[len];
-        bufsz = recvfrom(sock, tmpbuf, len, MSG_PEEK|MSG_TRUNC|MSG_WAITALL,
-            NULL, 0);
-        if (bufsz < 0 && errno == EAGAIN)
-                bufsz = len;
-    } while (bufsz == len);
-
-    if (bufsz <= 0) {
-        if (bufsz < 0)
-            perror("1st recvfrom in netlink_get_interface_ip");
-        close(sock);
-        return -1;
-    }
-
-    if ((buf = alloca(bufsz)) == NULL) {
-        perror("alloca on msg buf in netlink_get_interface_ip");
-        close(sock);
-        return -1;
+    if ((*handle = nl_handle_alloc()) == NULL) {
+        perror("nl_handle_alloc() failure in nl_get_link_cache()");
+        return NULL;
     }
-    memset(buf, '\0', bufsz);
 
-    while ((readsz = recvfrom(sock, buf, bufsz, MSG_WAITALL, NULL, 0)) <= 0) {
-        if (readsz < 0) {
-            if (errno == EAGAIN)
-                continue;
-            perror("2nd recvfrom in netlink_get_interface_ip");
-        }
-        close(sock);
-        return -1;
+    if (nl_connect(*handle, NETLINK_ROUTE)) {
+        perror("nl_connect() failure in nl_get_link_cache()");
+        nl_handle_destroy(*handle);
+        return NULL;
     }
 
-    nlh = (struct nlmsghdr *) buf;
-    while (NLMSG_OK(nlh, readsz)) {
-        switch (nlh->nlmsg_type) {
-            case NLMSG_DONE:
-                break;
-            case RTM_NEWADDR:
-                break;
-            default:
-                nlh = NLMSG_NEXT(nlh, readsz);
-                continue;
-        }
-
-        /* RTM_NEWADDR */
-        ifa = NLMSG_DATA(nlh);
-        rta = IFA_RTA(ifa);
-        len = IFA_PAYLOAD(nlh);
-
-        if (ifa->ifa_family != family) {
-            nlh = NLMSG_NEXT(nlh, readsz);
-            continue;
-        }
-
-        while (RTA_OK(rta, len)) {
-            if (rta->rta_type <= len)
-                tb[rta->rta_type] = rta;
-            rta = RTA_NEXT(rta, len);
-        }
-
-        alen = RTA_PAYLOAD(tb[IFA_ADDRESS]);
-
-        /* write the address */
-        if (tb[IFA_ADDRESS] && ifa->ifa_index == index) {
-            switch (family) {
-                case AF_INET:
-                    memset(addr, 0, sizeof(struct in_addr));
-                    memcpy(addr, (struct in_addr *)RTA_DATA(tb[IFA_ADDRESS]), alen);
-                    break;
-                case AF_INET6:
-                    memset(addr, 0, sizeof(struct in6_addr));
-                    memcpy(addr, (struct in6_addr *)RTA_DATA(tb[IFA_ADDRESS]), alen);
-                    break;
-            }
-
-            close(sock);
-            return 0;
-        }
-
-        /* next netlink msg */
-        nlh = NLMSG_NEXT(nlh, readsz);
+    if ((cache = rtnl_link_alloc_cache(*handle)) == NULL) {
+        perror("rtnl_link_alloc_cache() failure in nl_get_link_cache()");
+        nl_close(*handle);
+        nl_handle_destroy(*handle);
+        return NULL;
     }
 
-    close(sock);
-    return 0;
+    return cache;
 }
 
-/**
- * Initialize the interfaces linked list with the interface name, MAC
- * address, and IP addresses.  This function is only called once to
- * initialize the structure, but may be called again if the structure
- * should be reinitialized.
- *
- * @return 0 on succes, -1 on error.
+/*
+ * Given an interface name (e.g., eth0), return the IP address in human
+ * readable format (i.e., the output from inet_ntop()).  Return NULL for
+ * no match.  NOTE:  This function will check for IPv6 and IPv4
+ * addresses.  In the case where the interface has both, the IPv4 address
+ * is returned.  The only way you will get an IPv6 address from this function
+ * is if that's the only address configured for the interface.
  */
-int netlink_init_interfaces_list(void) {
-    int sock, len, alen, r, namelen;
-    ssize_t bufsz, readsz;
-    char *buf = NULL;
-    struct nlmsghdr *nlh;
-    struct ifinfomsg *ifi;
-    struct rtattr *rta;
-    struct rtattr *tb[IFLA_MAX+1];
-    interface_info_t *intfinfo;
-
-    /* if interfaces has stuff, free it now and read again */
-    if (interfaces != NULL)
-        netlink_interfaces_list_free();
-
-    /* get a socket */
-    if ((sock = netlink_create_socket()) == -1) {
-        perror("netlink_create_socket in netlink_init_interfaces_list");
-        close(sock);
-        return -1;
+char *nl_ip2str(char *ifname) {
+    int ifindex = -1, buflen = 0, family = 0;
+    char *buf = NULL, *bufv4 = NULL, *bufv6 = NULL, *pos = NULL;
+    struct nl_handle *handle = NULL;
+    struct nl_cache *cache = NULL;
+    struct nl_object *obj = NULL;
+    struct rtnl_addr *raddr = NULL;
+    struct nl_addr *addr = NULL;
+
+    if (ifname == NULL) {
+        perror("Missing ifname in nl_ip2str()");
+        return NULL;
     }
 
-    /* send dump request */
-    r = netlink_send_dump_request(sock, RTM_GETLINK, AF_NETLINK);
-    if (r <= 0) {
-        if (r < 0)
-            perror("netlink_send_dump_request in netlink_init_interfaces_list");
-        close(sock);
-        return r < 0 ? -1 : r;
+    if ((cache = nl_get_link_cache(&handle)) == NULL) {
+        perror("nl_get_link_cache() failure in nl_ip2str()");
+        return NULL;
     }
 
-    /* MSG_TRUNC doesn't actually seem to /work/ with netlink on RHEL 5,
-     * so we do this lame growth game until we have a buffer big enough.
-     * When we're done (which is the first time if MSG_TRUNC does its job),
-     * bufsz is the size of the message. Then we allocate a real buffer and
-     * do recvfrom again without MSG_PEEK. */
-    len = 32;
-    do {
-        len <<= 1;
-        char tmpbuf[len];
-        bufsz = recvfrom(sock, tmpbuf, len, MSG_PEEK|MSG_TRUNC|MSG_WAITALL,
-            NULL, 0);
-        if (bufsz < 0 && errno == EAGAIN)
-                bufsz = len;
-    } while (bufsz == len);
-
-    if (bufsz <= 0) {
-        if (bufsz < 0)
-            perror("1st recvfrom in netlink_get_interface_list");
-        close(sock);
-        return -1;
-    }
+    ifindex = rtnl_link_name2i(cache, ifname);
 
-    if ((buf = alloca(bufsz)) == NULL) {
-        perror("alloca on msg buf in netlink_get_interface_list");
-        close(sock);
-        return -1;
+    if ((cache = rtnl_addr_alloc_cache(handle)) == NULL) {
+        perror("rtnl_addr_alloc_cache() failure in nl_ip2str()");
+        goto ip2str_error;
     }
-    memset(buf, '\0', bufsz);
 
-    while ((readsz = recvfrom(sock, buf, bufsz, MSG_WAITALL, NULL, 0)) <= 0) {
-        if (readsz < 0) {
-            if (errno == EAGAIN)
-                continue;
-            perror("2nd recvfrom in netlink_get_interface_list");
-        }
-        close(sock);
-        return -1;
-    }
+    /* find the IPv4 and IPv6 addresses for this interface */
+    obj = nl_cache_get_first(cache);
+    while (obj) {
+        raddr = (struct rtnl_addr *) obj;
 
-    nlh = (struct nlmsghdr *) buf;
-    while (NLMSG_OK(nlh, readsz)) {
-        switch (nlh->nlmsg_type) {
-            case NLMSG_DONE:
-                break;
-            case RTM_NEWLINK:
-                break;
-            default:
-                nlh = NLMSG_NEXT(nlh, readsz);
-                continue;
-        }
-
-        /* RTM_NEWLINK */
-        memset(tb, 0, sizeof(tb));
-        memset(tb, 0, sizeof(struct rtattr *) * (IFLA_MAX + 1));
+        if (rtnl_addr_get_ifindex(raddr) == ifindex) {
+            family = rtnl_addr_get_family(raddr);
 
-        ifi = NLMSG_DATA(nlh);
-        rta = IFLA_RTA(ifi);
-        len = IFLA_PAYLOAD(nlh);
+            if (family == AF_INET || family == AF_INET6) {
+                /* skip if we have already saved an address */
+                /* FIXME: we should handle multiple addresses for the same
+                 * family per interface
+                 */
+                if (family == AF_INET && bufv4 != NULL) {
+                    continue;
+                }
 
-        /* we only do things with ethernet mac addrs, so ... */
-        if (ifi->ifi_type != ARPHRD_ETHER) {
-            nlh = NLMSG_NEXT(nlh, readsz);
-            continue;
-        }
+                if (family == AF_INET6 && bufv6 != NULL) {
+                    continue;
+                }
 
-        namelen = 0;
+                /* get the address */
+                addr = rtnl_addr_get_local(raddr);
 
-        while (RTA_OK(rta, len)) {
-            if (rta->rta_type <= len) {
-                if (rta->rta_type == IFLA_IFNAME) {
-                    namelen = rta->rta_len;
+                /* convert to human readable format */
+                if (family == AF_INET) {
+                    buflen = INET_ADDRSTRLEN;
+                } else if (family == AF_INET6) {
+                    buflen = INET6_ADDRSTRLEN;
                 }
 
-                tb[rta->rta_type] = rta;
-            }
-
-            rta = RTA_NEXT(rta, len);
-        }
+                buflen += 1;
 
-        if (tb[IFLA_ADDRESS] != NULL)
-            alen = RTA_PAYLOAD(tb[IFLA_ADDRESS]);
-        else
-            alen = 0;
-
-        /* we have an ethernet MAC addr if alen=6 */
-        if (alen == 6) {
-            /* make some room! */
-            intfinfo = malloc(sizeof(struct _interface_info_t));
-            if (intfinfo == NULL) {
-                perror("malloc in netlink_init_interfaces_list");
-                close(sock);
-                return -1;
-            }
+                if ((buf = malloc(buflen)) == NULL) {
+                    perror("malloc() failure on buf in nl_ip2str()");
+                    nl_addr_destroy(addr);
+                    goto ip2str_error;
+                }
 
-            /* copy the interface index */
-            intfinfo->i = ifi->ifi_index;
+                buf = nl_addr2str(addr, buf, buflen);
+                nl_addr_destroy(addr);
+
+                /* trim the prefix notation */
+                if ((pos = index(buf, '/')) != NULL) {
+                    *pos = '\0';
+                    if ((buf = realloc(buf, strlen(buf) + 1)) == NULL) {
+                        perror("realloc() failure on buf in nl_ip2str()");
+                        nl_addr_destroy(addr);
+                        goto ip2str_error;
+                    }
+                }
 
-            /* copy the interface name (eth0, eth1, ...) */
-            if (namelen > 0) {
-                intfinfo->name = strndup((char *) RTA_DATA(tb[IFLA_IFNAME]),
-                                         namelen);
-            } else {
-                intfinfo->name = NULL;
-            }
+                /* save the IP address in the right buffer */
+                if (family == AF_INET) {
+                    bufv4 = strdup(buf);
+                } else if (family == AF_INET6) {
+                    bufv6 = strdup(buf);
+                }
 
-            /* copy the MAC addr */
-            memcpy(&intfinfo->mac, RTA_DATA(tb[IFLA_ADDRESS]), alen);
-
-            if (ifi->ifi_flags & IFF_RUNNING) {
-                /* get the IPv4 address of this interface (if any) */
-                r = netlink_get_interface_ip(intfinfo->i, AF_INET, &intfinfo->ip_addr);
-                if (r < 0)
-                    memset(&intfinfo->ip_addr, 0, sizeof(struct in_addr));
-
-                /* get the IPv6 address of this interface (if any) */
-                r = netlink_get_interface_ip(intfinfo->i, AF_INET6, &intfinfo->ip6_addr);
-                if (r < 0)
-                    memset(&intfinfo->ip6_addr, 0, sizeof(struct in6_addr));
-            } else {
-                memset(&intfinfo->ip_addr, 0, sizeof(struct in_addr));
-                memset(&intfinfo->ip6_addr, 0, sizeof(struct in6_addr));
+                /* empty the main conversion buffer */
+                if (buf) {
+                    free(buf);
+                    buf = NULL;
+                }
             }
-
-            /* add this interface */
-            interfaces = g_slist_append(interfaces, intfinfo);
         }
 
-        /* next netlink msg */
-        nlh = NLMSG_NEXT(nlh, readsz);
+        obj = nl_cache_get_next(obj);
     }
 
-    close(sock);
-    return 0;
-}
-
-/**
- * Take the cylon-readable IP address for the specified device and format
- * it for human reading.  NOTE:  This function will check for IPv6 and IPv4
- * addresses.  In the case where the interface has both, the IPv4 address
- * is returned.  The only way you will get an IPv6 address from this function
- * is if that's the only address configured for the interface.
- *
- * @param ifname The interface name (e.g., eth0).
- * @return The human-readable IP address (either IPv4 or IPv6) or NULL on
- *         error/no match.
- */
-char *netlink_interfaces_ip2str(char *ifname) {
-    char *ret = NULL;
-    GSList *e;
-    interface_info_t *intf;
+ip2str_error:
+    nl_close(handle);
+    nl_handle_destroy(handle);
 
-    if (ifname == NULL)
-        return NULL;
-
-    /* init the interfaces list if it's empty or if nothing is found */
-    e = g_slist_find_custom(interfaces,ifname,&_netlink_interfaces_elem_find);
-    if (interfaces == NULL || e == NULL) {
-        int r = netlink_init_interfaces_list();
-
-        if (r < 0) {
-            perror("netlink_init_interfaces_list in netlink_interface_ip2str");
-            return NULL;
-        }
-    }
-
-    /* search */
-    e = g_slist_find_custom(interfaces,ifname,&_netlink_interfaces_elem_find);
-    if (e == NULL) {
-        return NULL;
+    /* return IPv4 address if we have both families
+     * return IPv6 address if we only have IPv6 family
+     * return NULL otherwise
+     */
+    if ((bufv4 && bufv6) || (bufv4 && !bufv6)) {
+        return bufv4;
+    } else if (!bufv4 && bufv6) {
+        return bufv6;
     } else {
-        intf = (interface_info_t *) e->data;
-
-        if (intf->ip_addr.s_addr == 0 && intf->ip6_addr.s6_addr[0] == 0)
-            /* neither IP set, return null */
-            ret = NULL;
-        else if (intf->ip_addr.s_addr == 0 && intf->ip6_addr.s6_addr[0] != 0)
-            /* only IPv6 addr, return that */
-            ret = netlink_format_ip_addr(AF_INET6, intf, ret);
-        else if (intf->ip_addr.s_addr != 0)
-            /* if IPv4 is set, return that (regardless of IPv6 value) */
-            ret = netlink_format_ip_addr(AF_INET, intf, ret);
-        else
-            /* we have no idea what happened, return NULL */
-            ret = NULL;
-
-        return ret;
+        return NULL;
     }
 }
 
 /**
- * Take the cylon-readable MAC address for the specified device and
- * format it for human reading.
- *
- * @param ifname The interface name (e.g., eth0).
- * @return The human-readable MAC address (e.g., 01:0A:3E:4B:91:12) or NULL
- *            on error.
+ * Given an interface name (e.g., eth0), return the MAC address in human
+ * readable format (e.g., 00:11:52:12:D9:A0).  Return NULL for no match.
  */
-char *netlink_interfaces_mac2str(char *ifname) {
-    char *ret = NULL;
-    GSList *e;
-    interface_info_t *intf;
-    int r;
+char *nl_mac2str(char *ifname) {
+    int buflen = 20;
+    char *buf = NULL;
+    struct nl_handle *handle = NULL;
+    struct nl_cache *cache = NULL;
+    struct rtnl_link *link = NULL;
+    struct nl_addr *addr = NULL;
 
-    if (ifname == NULL)
+    if (ifname == NULL) {
+        perror("Missing ifname in nl_mac2str()");
         return NULL;
-
-    /* init the interfaces list if it's empty */
-    if (interfaces == NULL) {
-        r = netlink_init_interfaces_list();
-
-        if (r < 0) {
-            perror("netlink_init_interfaces_list in netlink_interface_mac2str");
-            return NULL;
-        }
     }
 
-    e = g_slist_find_custom(interfaces,ifname,&_netlink_interfaces_elem_find);
-    if (e == NULL) {
+    if ((cache = nl_get_link_cache(&handle)) == NULL) {
+        perror("nl_get_link_cache() failure in nl_mac2str()");
         return NULL;
-    } else {
-        intf = (interface_info_t *) e->data;
-        ret = netlink_format_mac_addr(ret, intf->mac);
-        return ret;
     }
-}
-
-/**
- * Free memory for each element of the specified linked list.  Frees the
- * list after all elements have been freed (say 'free' some more).
- */
-void netlink_interfaces_list_free(void) {
-    g_slist_foreach(interfaces, &_netlink_interfaces_elem_free, NULL);
-    g_slist_free(interfaces);
-    interfaces = NULL;
-}
 
-/**
- * Callback function for netlink_interfaces_list_free.  Frees an individual
- * list element.
- *
- * @see netlink_interfaces_list_free
- */
-void _netlink_interfaces_elem_free(gpointer data, gpointer user_data) {
-    free(data);
-    return;
-}
+    if ((link = rtnl_link_get_by_name(cache, ifname)) == NULL) {
+        perror("rtnl_link_get_by_name() failure in nl_mac2str()");
+        goto mac2str_error2;
+    }
 
-/**
- * Compares one list element to the specified interface name.  Callback
- * function used to locate a list element by interface name.
- *
- * @see netlink_interfaces_mac2str
- * @see netlink_interfaces_ip2str
- */
-gint _netlink_interfaces_elem_find(gconstpointer a, gconstpointer b) {
-    char *ifname = (char *) b;
-    GSList *elemdata = (GSList *) a;
-    interface_info_t *intf;
-
-    intf = (interface_info_t *) elemdata;
-    if (intf->name == NULL)
-        return -1;
-    else
-        return strncmp(ifname, intf->name, strlen(ifname));
-}
+    if ((addr = rtnl_link_get_addr(link)) == NULL) {
+        perror("rtnl_link_get_addr() failure in nl_mac2str()");
+        goto mac2str_error3;
+    }
 
-#ifdef TESTING
-void print_interfaces(gpointer data, gpointer user_data) {
-    char *buf = NULL;
-    char *ipbuf = NULL;
-    interface_info_t *intf;
-
-    intf = (interface_info_t *) data;
-    printf("Interface %d\n", intf->i);
-    printf("    Name: %s\n", intf->name);
-    if (intf->ip_addr.s_addr != 0)
-        printf("    IPv4: %s\n", netlink_format_ip_addr(AF_INET, intf, ipbuf));
-    else
-        printf("    IPv4: not set\n");
-    if (intf->ip6_addr.s6_addr[0] != 0)
-        printf("    IPv6: %s\n", netlink_format_ip_addr(AF_INET6, intf, ipbuf));
-    else
-        printf("    IPv6: not set\n");
-    printf("     MAC: %s\n\n", netlink_format_mac_addr(buf, intf->mac));
-
-    printf("    mac2str test for %s: |%s|\n", intf->name, netlink_interfaces_mac2str(intf->name));
-    printf("     ip2str test for %s: |%s|\n", intf->name, netlink_interfaces_ip2str(intf->name));
-
-    printf("----------------------------------------------------------------\n");
-
-    return;
-}
+    if ((buf = malloc(buflen)) == NULL) {
+        perror("malloc() failure on buf in nl_mac2str()");
+        goto mac2str_error4;
+    }
 
-int main(void) {
-    if (netlink_init_interfaces_list() == -1) {
-        fprintf(stderr, "netlink_init_interfaces_list failure: %s\n", __func__);
-        fflush(stderr);
-        return EXIT_FAILURE;
+    if ((buf = nl_addr2str(addr, buf, buflen)) != NULL) {
+        buf = str2upper(buf);
     }
 
-    g_slist_foreach(interfaces, print_interfaces, NULL);
+mac2str_error4:
+    nl_addr_destroy(addr);
+mac2str_error3:
+    rtnl_link_put(link);
+mac2str_error2:
+    nl_close(handle);
+    nl_handle_destroy(handle);
 
-    return EXIT_SUCCESS;
+    return buf;
 }
-#endif
diff --git a/isys/nl.h b/isys/nl.h
index d182aa6..0a3b4f6 100644
--- a/isys/nl.h
+++ b/isys/nl.h
@@ -19,31 +19,10 @@
  * Author(s): David Cantrell <dcantrell@xxxxxxxxxx>
  */
 
-#include <netinet/in.h>
-#include <glib.h>
-
-#define BUFSZ 4096
-
-/* Information per interface */
-typedef struct _interface_info_t {
-   int i;                            /* interface index        */
-   char *name;                       /* name (eth0, eth1, ...) */
-   struct in_addr ip_addr;           /* IPv4 address (0=none)  */
-   struct in6_addr ip6_addr;         /* IPv6 address (0=none)  */
-   unsigned char mac[8];             /* MAC address            */
-} interface_info_t;
+#include <netlink/cache.h>
+#include <netlink/socket.h>
 
 /* Function prototypes */
-char *netlink_format_mac_addr(char *buf, unsigned char *mac);
-char *netlink_format_ip_addr(int family, interface_info_t *intf, char *buf);
-int netlink_create_socket(void);
-int netlink_send_dump_request(int sock, int type, int family);
-int netlink_get_interface_ip(int index, int family, void *addr);
-int netlink_init_interfaces_list(void);
-void netlink_interfaces_list_free(void);
-char *netlink_interfaces_mac2str(char *ifname);
-char *netlink_interfaces_ip2str(char *ifname);
-
-/* Private function prototypes -- used by the functions above */
-void _netlink_interfaces_elem_free(gpointer data, gpointer user_data);
-gint _netlink_interfaces_elem_find(gconstpointer a, gconstpointer b);
+struct nl_cache *nl_get_link_cache(struct nl_handle **handle);
+char *nl_mac2str(char *ifname);
+char *nl_ip2str(char *ifname);
diff --git a/loader2/net.c b/loader2/net.c
index ba500d9..31d3351 100644
--- a/loader2/net.c
+++ b/loader2/net.c
@@ -1795,7 +1795,7 @@ int chooseNetworkInterface(struct loaderData_s * loaderData) {
             } else if (ksMacAddr != NULL) {
                 /* maybe it's a mac address */
                 char *devmacaddr = NULL;
-                devmacaddr = netlink_interfaces_mac2str(devs[i]->device);
+                devmacaddr = nl_mac2str(devs[i]->device);
                 if ((devmacaddr != NULL) && !strcmp(ksMacAddr, devmacaddr)) {
                     foundDev = 1;
                     free(loaderData->netDev);
diff --git a/loader2/nfsinstall.c b/loader2/nfsinstall.c
index 18fb67e..d150370 100644
--- a/loader2/nfsinstall.c
+++ b/loader2/nfsinstall.c
@@ -360,9 +360,8 @@ int getFileFromNfs(char * url, char * dest, struct loaderData_s * loaderData) {
     }
 
     /* get the IP of the target system */
-    netlink_init_interfaces_list();
-    if ((ip = netlink_interfaces_ip2str(loaderData->netDev)) == NULL) {
-        logMessage(ERROR, "netlink_interfaces_ip2str returned NULL");
+    if ((ip = nl_ip2str(loaderData->netDev)) == NULL) {
+        logMessage(ERROR, "nl_ip2str returned NULL");
         return 1;
     }
 
diff --git a/loader2/urlinstall.c b/loader2/urlinstall.c
index 58cdc63..3fff562 100644
--- a/loader2/urlinstall.c
+++ b/loader2/urlinstall.c
@@ -310,8 +310,7 @@ int getFileFromUrl(char * url, char * dest,
     memset(&ui, 0, sizeof(ui));
     ui.protocol = proto;
 
-    netlink_init_interfaces_list();
-    if ((ip = netlink_interfaces_ip2str(loaderData->netDev)) == NULL) {
+    if ((ip = nl_ip2str(loaderData->netDev)) == NULL) {
         logMessage(ERROR, "getFileFromUrl: no client IP information");
         return 1;
     }
@@ -359,7 +358,7 @@ int getFileFromUrl(char * url, char * dest,
         devices = getDevices(DEVICE_NETWORK);
         for (i = 0; devices && devices[i]; i++) {
             dev = devices[i]->device;
-            mac = netlink_interfaces_mac2str(dev);
+            mac = nl_mac2str(dev);
 
             if (mac) {
                 q = asprintf(&tmpstr, "X-RHN-Provisioning-MAC-%d: %s %s\r\n",
-- 
1.5.3.8

_______________________________________________
Anaconda-devel-list mailing list
Anaconda-devel-list@xxxxxxxxxx
https://www.redhat.com/mailman/listinfo/anaconda-devel-list

[Index of Archives]     [Kickstart]     [Fedora Users]     [Fedora Legacy List]     [Fedora Maintainers]     [Fedora Desktop]     [Fedora SELinux]     [Big List of Linux Books]     [Yosemite News]     [Yosemite Photos]     [KDE Users]     [Fedora Tools]
  Powered by Linux