From: Roy Marples Date: Sun, 3 Dec 2006 10:28:57 +0000 (+0000) Subject: Linux systems without glibc-2.3 don't have getifaddrs, so we define our own. X-Git-Tag: v3.2.3~365 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=ef95a74bcd39bccd11ff5fe49bceb2e33caf865f;p=thirdparty%2Fdhcpcd.git Linux systems without glibc-2.3 don't have getifaddrs, so we define our own. --- diff --git a/ChangeLog b/ChangeLog index 2704d680..77f5750a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,8 +1,10 @@ +dhcpcd-3.0.2 +Linux systems without glibc-2.3 don't have getifaddrs, so we define our own. Changed the default timeout to 20 seconds, allowing hme Sparc drivers to work. Set the rfds correctly so we can get a reply after re-sending a request. Set the seconds elasped and maximum message size correctly in DHCP messages. Now compiles on Linux 2.4 kernels. -xmalloc dhcp objects so we can swap pointer around easily. +xmalloc dhcp objects so we can swap the pointers around easily. dhcpcd-3.0.1 Quote all vars in the info file. diff --git a/Makefile b/Makefile index 1c1992c9..4dd51dcf 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ # Should work for both GNU make and BSD mke -VERSION = 3.0.2_pre1 +VERSION = 3.0.2 INSTALL ?= install CFLAGS ?= -Wall -O2 -pedantic -std=gnu99 diff --git a/interface.c b/interface.c index 7631fafb..c678e66d 100644 --- a/interface.c +++ b/interface.c @@ -29,19 +29,26 @@ /* Netlink suff */ #ifdef __linux__ #include /* Needed for 2.4 kernels */ +#include #include #include #include #include +/* Only glibc-2.3 ships with ifaddrs.h */ +#if defined (__GLIBC__) && defined (__GLIBC_PREREQ) && __GLIBC_PREREQ (2,3) +#define HAVE_IFADDRS_H +#include +#endif #else #include #include #include #include -#endif /* __linux__ */ +#define HAVE_IFADDRS_H +#include +#endif #include -#include #include #include #include @@ -84,6 +91,8 @@ void free_route (route_t *routes) } } + + interface_t *read_interface (const char *ifname, int metric) { if (! ifname) @@ -94,6 +103,7 @@ interface_t *read_interface (const char *ifname, int metric) interface_t *iface; unsigned char hwaddr[ETHER_ADDR_LEN]; +#ifndef __linux__ struct ifaddrs *ifap; struct ifaddrs *p; @@ -104,25 +114,16 @@ interface_t *read_interface (const char *ifname, int metric) { if (strcmp (p->ifa_name, ifname) != 0) continue; -#ifdef __linux__ - struct sockaddr_ll *sll = (struct sockaddr_ll*) p->ifa_addr; - if (p->ifa_addr->sa_family != AF_PACKET - || sll->sll_hatype != ARPHRD_ETHER) -#else - struct sockaddr_dl *sdl = (struct sockaddr_dl *) p->ifa_addr; + + struct sockaddr_dl *sdl = (struct sockaddr_dl *) p->ifa_addr; if (p->ifa_addr->sa_family != AF_LINK || sdl->sdl_type != IFT_ETHER) -#endif { logger (LOG_ERR, "not Ethernet"); freeifaddrs (ifap); return NULL; } -#ifdef __linux__ - memcpy (hwaddr, sll->sll_addr, ETHER_ADDR_LEN); -#else memcpy (hwaddr, sdl->sdl_data + sdl->sdl_nlen, ETHER_ADDR_LEN); -#endif break; } freeifaddrs (ifap); @@ -132,18 +133,33 @@ interface_t *read_interface (const char *ifname, int metric) logger (LOG_ERR, "could not find interface %s", ifname); return NULL; } +#endif memset (&ifr, 0, sizeof (struct ifreq)); strncpy (ifr.ifr_name, ifname, sizeof (ifr.ifr_name)); - if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) + if ((s = socket (AF_INET, SOCK_DGRAM, 0)) < 0) { logger (LOG_ERR, "socket: %s", strerror (errno)); return NULL; } -#ifndef __linux__ +#ifdef __linux__ + if (ioctl (s, SIOCGIFHWADDR, &ifr) <0) + { + logger (LOG_ERR, "ioctl SIOCGIFHWADDR: %s", strerror(errno)); + close (s); + return NULL; + } + if (ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER) + { + logger (LOG_ERR, "interface is not Ethernet"); + close (s); + return NULL; + } + memcpy (&hwaddr, &ifr.ifr_hwaddr.sa_data, ETHER_ADDR_LEN); +#else ifr.ifr_metric = metric; - if (ioctl(s, SIOCSIFMETRIC, &ifr) < 0) + if (ioctl (s, SIOCSIFMETRIC, &ifr) < 0) { logger (LOG_ERR, "ioctl SIOCSIFMETRIC: %s", strerror (errno)); close (s); @@ -637,7 +653,25 @@ int del_address (const char *ifname, struct in_addr address) return (do_address (ifname, address, t, t, 1)); } -/* This should work on all platforms */ +int add_route (const char *ifname, struct in_addr destination, + struct in_addr netmask, struct in_addr gateway, int metric) +{ + return (do_route (ifname, destination, netmask, gateway, metric, 0, 0)); +} + +int change_route (const char *ifname, struct in_addr destination, + struct in_addr netmask, struct in_addr gateway, int metric) +{ + return (do_route (ifname, destination, netmask, gateway, metric, 1, 0)); +} + +int del_route (const char *ifname, struct in_addr destination, + struct in_addr netmask, struct in_addr gateway, int metric) +{ + return (do_route (ifname, destination, netmask, gateway, metric, 0, 1)); +} + +#ifdef HAVE_IFADDRS_H int flush_addresses (const char *ifname) { if (! ifname) @@ -649,6 +683,7 @@ int flush_addresses (const char *ifname) if (getifaddrs (&ifap) != 0) return -1; + int retval = 0; for (p = ifap; p; p = p->ifa_next) { if (strcmp (p->ifa_name, ifname) != 0) @@ -656,28 +691,61 @@ int flush_addresses (const char *ifname) struct sockaddr_in *sin = (struct sockaddr_in*) p->ifa_addr; if (sin->sin_family == AF_INET) - del_address (ifname, sin->sin_addr); + if (del_address (ifname, sin->sin_addr) < 0) + retval = -1; } freeifaddrs (ifap); - return 0; + return retval; } - -int add_route (const char *ifname, struct in_addr destination, - struct in_addr netmask, struct in_addr gateway, int metric) +#else +int flush_addresses (const char *ifname) { - return (do_route (ifname, destination, netmask, gateway, metric, 0, 0)); -} + int s; + if ((s = socket (AF_INET, SOCK_DGRAM, 0)) < 0) + { + logger (LOG_ERR, "socket: %s", strerror (errno)); + return -1; + } -int change_route (const char *ifname, struct in_addr destination, - struct in_addr netmask, struct in_addr gateway, int metric) -{ - return (do_route (ifname, destination, netmask, gateway, metric, 1, 0)); -} + struct ifconf ifc; + memset (&ifc, 0, sizeof (struct ifconf)); + ifc.ifc_buf = NULL; + if (ioctl (s, SIOCGIFCONF, &ifc) < 0) + { + logger (LOG_ERR, "ioctl SIOCGIFCONF: %s", strerror (errno)); + close (s); + } -int del_route (const char *ifname, struct in_addr destination, - struct in_addr netmask, struct in_addr gateway, int metric) -{ - return (do_route (ifname, destination, netmask, gateway, metric, 0, 1)); -} + void *ifrs = xmalloc (ifc.ifc_len); + ifc.ifc_buf = ifrs; + if (ioctl (s, SIOCGIFCONF, &ifc) < 0) + { + logger (LOG_ERR, "ioctl SIOCGIFCONF: %s", strerror (errno)); + close (s); + free (ifrs); + return -1; + } + + close (s); + + int nifs = ifc.ifc_len / sizeof (struct ifreq); + struct ifreq *ifr = ifrs; + int retval = 0; + int i; + for (i = 0; i < nifs; i++) + { + if (ifr->ifr_addr.sa_family != AF_INET + || strcmp (ifname, ifr->ifr_name) != 0) + continue; + + struct sockaddr_in *in = (struct sockaddr_in *) &ifr->ifr_addr; + if (del_address (ifname, in->sin_addr) < 0) + retval = -1; + ifr++; + } + free (ifrs); + return retval; +} +#endif