[Date Prev][Date Next] [Thread Prev][Thread Next]
[Thread Index]
[Date Index]
[Author Index]
[PATCH] Use libnl to get interface MAC and IP addresses
- From: David Cantrell <dcantrell redhat com>
- To: anaconda-devel-list redhat com
- Cc:
- Subject: [PATCH] Use libnl to get interface MAC and IP addresses
- Date: Mon, 21 Jan 2008 17:04:54 -1000
From: David L. Cantrell Jr <dcantrell redhat com>
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 redhat com>
*/
-#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
[Date Prev][Date Next] [Thread Prev][Thread Next]
[Thread Index]
[Date Index]
[Author Index]