#include <netinet/in.h>
#include <errno.h>
+#include <fnmatch.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <syslog.h>
#include <unistd.h>
#include "config.h"
#include "common.h"
#include "dhcp.h"
+#include "if-options.h"
#include "net.h"
/* Darwin doesn't define this for some very odd reason */
}
}
+static void
+discover_link(struct interface **ifs, int argc, char * const *argv,
+ struct ifreq *ifr)
+{
+ struct interface *ifp, *ifl = NULL;
+ struct sockaddr_dl *sdl;
+ int n;
+
+ if (ifr->ifr_addr.sa_family != AF_LINK)
+ return;
+ for (ifp = *ifs; ifp; ifp = ifp->next) {
+ if (strcmp(ifp->name, ifr->ifr_name) == 0)
+ return;
+ ifl = ifp;
+ }
+ if (argc > 0) {
+ for (n = 0; n < argc; n++)
+ if (strcmp(ifr->ifr_name, argv[n]) == 0)
+ return;
+ } else {
+ for (n = 0; n < ifdc; n++)
+ if (fnmatch(ifdv[n], ifr->ifr_name, 0) == 0)
+ return;
+ for (n = 0; n < ifac; n++)
+ if (fnmatch(ifav[n], ifr->ifr_name, 0) == 0)
+ break;
+ if (ifac && n == ifac)
+ return;
+ }
+ if (!(ifp = init_interface(ifr->ifr_name)))
+ return;
+ sdl = xmalloc(ifr->ifr_addr.sa_len);
+ memcpy(sdl, &ifr->ifr_addr, ifr->ifr_addr.sa_len);
+ switch(sdl->sdl_type) {
+ case IFT_ETHER:
+ ifp->family = ARPHRD_ETHER;
+ ifp->hwlen = sdl->sdl_alen;
+ memcpy(ifp->hwaddr, LLADDR(sdl), sdl->sdl_alen);
+ break;
+ default:
+ /* Don't needlessly spam console on startup */
+ if (!(options & DHCPCD_MASTER &&
+ !(options & DHCPCD_DAEMONISED) &&
+ options & DHCPCD_QUIET))
+ syslog(LOG_ERR, "%s: unsupported interface type",
+ ifr->ifr_name);
+ free(ifp);
+ ifp = NULL;
+ break;
+ }
+ free(sdl);
+ if (ifp && ifl)
+ ifl->next = ifp;
+ else
+ *ifs = ifp;
+}
+
struct interface *
discover_interfaces(int argc, char * const *argv)
{
struct interface *ifs = NULL;
- do_interface(NULL, &ifs, argc, argv, NULL, NULL, 2);
+ do_interface(NULL, discover_link, &ifs, argc, argv, NULL, NULL, 2);
return ifs;
}
# include <net/if_media.h>
#endif
#ifdef BSD
+# include <net/if_types.h>
# include <net80211/ieee80211_ioctl.h>
#endif
#ifdef __linux__
#include <ctype.h>
#include <errno.h>
-#include <fnmatch.h>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
char *p = hwaddr_buffer;
size_t i;
- for (i = 0; i < hwlen && i < sizeof(hwaddr_buffer) / 3; i++) {
+ for (i = 0; i < hwlen && i < HWADDR_LEN; i++) {
if (i > 0)
*p ++= ':';
p += snprintf(p, 3, "%.2x", hwaddr[i]);
}
memcpy(iface->hwaddr, ifr.ifr_hwaddr.sa_data, iface->hwlen);
iface->family = ifr.ifr_hwaddr.sa_family;
-
-#else
- iface->family = ARPHRD_ETHER;
#endif
if (ioctl(s, SIOCGIFMTU, &ifr) == -1)
int
do_interface(const char *ifname,
- _unused struct interface **ifs,
- _unused int argc, _unused char * const *argv,
+ void (*do_link)(struct interface **, int, char * const *, struct ifreq *),
+ struct interface **ifs, int argc, char * const *argv,
struct in_addr *addr, struct in_addr *net, int act)
{
int s;
struct sockaddr_in address;
struct ifreq *ifr;
struct sockaddr_in netmask;
-#ifdef AF_LINK
- int n;
- struct sockaddr_dl *sdl;
- struct interface *ifp, *ifl = NULL, *ifn = NULL;
-#endif
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
return -1;
found = 1;
-#ifdef AF_LINK
/* Interface discovery for BSD's */
- if (act == 2 && ifr->ifr_addr.sa_family == AF_LINK) {
- for (ifp = *ifs; ifp; ifp = ifp->next) {
- ifl = ifp;
- if (strcmp(ifp->name, ifr->ifr_name) == 0)
- break;
- }
- if (ifp)
- continue;
- if (argc > 0) {
- for (n = 0; n < argc; n++)
- if (strcmp(ifr->ifr_name, argv[n]) == 0)
- break;
- if (n == argc)
- continue;
- } else {
- for (n = 0; n < ifdc; n++)
- if (!fnmatch(ifdv[n], ifr->ifr_name, 0))
- break;
- if (n < ifdc)
- continue;
- for (n = 0; n < ifac; n++)
- if (!fnmatch(ifav[n], ifr->ifr_name, 0))
- break;
- if (ifac && n == ifac)
- continue;
- }
- ifn = init_interface(ifr->ifr_name);
- if (!ifn)
- continue;
- if (ifl)
- ifp = ifl->next = ifn;
- else
- ifp = *ifs = ifn;
- sdl = xmalloc(ifr->ifr_addr.sa_len);
- memcpy(sdl, &ifr->ifr_addr, ifr->ifr_addr.sa_len);
- ifp->hwlen = sdl->sdl_alen;
- memcpy(ifp->hwaddr, LLADDR(sdl), sdl->sdl_alen);
- free(sdl);
+ if (act == 2 && do_link) {
+ do_link(ifs, argc, argv, ifr);
+ continue;
}
-#endif
if (ifr->ifr_addr.sa_family == AF_INET && addr) {
memcpy(&address, &ifr->ifr_addr, sizeof(address));
int inet_cidrtoaddr(int, struct in_addr *);
int up_interface(const char *);
-int do_interface(const char *, struct interface **,
- int argc, char * const *argv,
+int do_interface(const char *, void (*)(struct interface **, int, char * const *, struct ifreq *),
+ struct interface **, int, char * const *,
struct in_addr *, struct in_addr *, int);
int if_address(const struct interface *,
const struct in_addr *, const struct in_addr *,