int ifdc = 0;
char **ifdv = NULL;
+static char **margv;
+static int margc;
static char **ifv;
static int ifc;
static int linkfd = -1;
}
}
+static void
+configure_interface(struct interface *iface, int argc, char **argv)
+{
+ struct if_state *ifs = iface->state;
+ struct if_options *ifo;
+ uint8_t *duid;
+ size_t len = 0, ifl;
+
+ free_options(ifs->options);
+ ifo = ifs->options = read_config(cffile, iface->name, iface->ssid);
+ add_options(ifo, argc, argv);
+
+ if (ifo->metric != -1)
+ iface->metric = ifo->metric;
+
+ /* If we haven't specified a ClientID and our hardware address
+ * length is greater than DHCP_CHADDR_LEN then we enforce a ClientID
+ * of the hardware address family and the hardware address. */
+ if (iface->hwlen > DHCP_CHADDR_LEN)
+ ifo->options |= DHCPCD_CLIENTID;
+
+ free(iface->clientid);
+ if (*ifo->clientid) {
+ iface->clientid = xmalloc(ifo->clientid[0] + 1);
+ memcpy(iface->clientid, ifo->clientid, ifo->clientid[0] + 1);
+ } else if (ifo->options & DHCPCD_CLIENTID) {
+ if (ifo->options & DHCPCD_DUID) {
+ duid = xmalloc(DUID_LEN);
+ if ((len = get_duid(duid, iface)) == 0)
+ syslog(LOG_ERR, "get_duid: %m");
+ }
+ if (len > 0) {
+ iface->clientid = xmalloc(len + 6);
+ iface->clientid[0] = len + 5;
+ iface->clientid[1] = 255; /* RFC 4361 */
+ ifl = strlen(iface->name);
+ if (ifl < 5) {
+ memcpy(iface->clientid + 2, iface->name, ifl);
+ if (ifl < 4)
+ memset(iface->clientid + 2 + ifl,
+ 0, 4 - ifl);
+ } else {
+ ifl = htonl(if_nametoindex(iface->name));
+ memcpy(iface->clientid + 2, &ifl, 4);
+ }
+ } else if (len == 0) {
+ len = iface->hwlen + 1;
+ iface->clientid = xmalloc(len + 1);
+ iface->clientid[0] = len;
+ iface->clientid[1] = iface->family;
+ memcpy(iface->clientid + 2, iface->hwaddr,
+ iface->hwlen);
+ }
+ }
+}
+
static void
handle_carrier(const char *ifname)
{
struct interface *iface;
+ char ssid[IF_SSIDSIZE];
for (iface = ifaces; iface; iface = iface->next)
if (strcmp(iface->name, ifname) == 0)
if (iface->carrier != LINK_UP) {
iface->carrier = LINK_UP;
syslog(LOG_INFO, "%s: carrier acquired", iface->name);
+ /* We need to reconfigre for if ssid changed */
+ getifssid(iface->name, ssid);
+ if (strcmp(iface->ssid, ssid) != 0) {
+ strlcpy(ssid, iface->ssid, sizeof(iface->ssid));
+ configure_interface(iface, margc, margv);
+ }
start_interface(iface);
}
break;
start_reboot(iface);
}
-static void
-configure_interface(struct interface *iface, int argc, char **argv)
-{
- struct if_state *ifs = iface->state;
- struct if_options *ifo;
- uint8_t *duid;
- size_t len = 0, ifl;
-
- free_options(ifs->options);
- ifo = ifs->options = read_config(cffile, iface->name);
- add_options(ifo, argc, argv);
-
- if (ifo->metric != -1)
- iface->metric = ifo->metric;
-
- /* If we haven't specified a ClientID and our hardware address
- * length is greater than DHCP_CHADDR_LEN then we enforce a ClientID
- * of the hardware address family and the hardware address. */
- if (iface->hwlen > DHCP_CHADDR_LEN)
- ifo->options |= DHCPCD_CLIENTID;
-
- free(iface->clientid);
- if (*ifo->clientid) {
- iface->clientid = xmalloc(ifo->clientid[0] + 1);
- memcpy(iface->clientid, ifo->clientid, ifo->clientid[0] + 1);
- } else if (ifo->options & DHCPCD_CLIENTID) {
- if (ifo->options & DHCPCD_DUID) {
- duid = xmalloc(DUID_LEN);
- if ((len = get_duid(duid, iface)) == 0)
- syslog(LOG_ERR, "get_duid: %m");
- }
- if (len > 0) {
- iface->clientid = xmalloc(len + 6);
- iface->clientid[0] = len + 5;
- iface->clientid[1] = 255; /* RFC 4361 */
- ifl = strlen(iface->name);
- if (ifl < 5) {
- memcpy(iface->clientid + 2, iface->name, ifl);
- if (ifl < 4)
- memset(iface->clientid + 2 + ifl,
- 0, 4 - ifl);
- } else {
- ifl = htonl(if_nametoindex(iface->name));
- memcpy(iface->clientid + 2, &ifl, 4);
- }
- } else if (len == 0) {
- len = iface->hwlen + 1;
- iface->clientid = xmalloc(len + 1);
- iface->clientid[0] = len;
- iface->clientid[1] = iface->family;
- memcpy(iface->clientid + 2, iface->hwaddr,
- iface->hwlen);
- }
- }
-}
-
static void
init_state(struct interface *iface, int argc, char **argv)
{
}
}
- ifo = read_config(cffile, NULL);
+ margv = argv;
+ margc = argc;
+ ifo = read_config(cffile, NULL, NULL);
opt = add_options(ifo, argc, argv);
if (opt != 1) {
if (opt == 0)
.Ar script
instead of the default
.Pa @SCRIPT@ .
+.It Ic ssid Ar ssid
+Subsequent options are only parsed for this wireless
+.Ar ssid .
.It Ic static Ar value
Configures a static
.Ar value .
/*
* dhcpcd - DHCP client daemon
- * Copyright 2006-2008 Roy Marples <roy@marples.name>
+ * Copyright 2006-2009 Roy Marples <roy@marples.name>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
#include "if-options.h"
#define HWADDR_LEN 20
+#define IF_SSIDSIZE 33
enum DHS {
DHS_INIT,
int metric;
int carrier;
int arpable;
+ char ssid[IF_SSIDSIZE];
int raw_fd;
int udp_fd;
/*
* dhcpcd - DHCP client daemon
- * Copyright 2006-2008 Roy Marples <roy@marples.name>
+ * Copyright 2006-2009 Roy Marples <roy@marples.name>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
#endif
int
-if_wireless(const char *ifname)
+getifssid(const char *ifname, char *ssid)
{
int s, retval = -1;
#if defined(SIOCG80211NWID)
struct ieee80211_nwid nwid;
#elif defined(IEEE80211_IOC_SSID)
struct ieee80211req ireq;
+ char nwid[IEEE80211_NWID_LEN + 1];
#endif
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
memset(&nwid, 0, sizeof(nwid));
ifr.ifr_data = (void *)&nwid;
- if (ioctl(s, SIOCG80211NWID, &ifr) == 0)
- retval = 0;
+ if (ioctl(s, SIOCG80211NWID, &ifr) == 0) {
+ retval = nwid.i_len;
+ memcpy(nwid.i_nwid, ssid, nwid.i_len);
+ ssid[nwid.i_len] = '\0';
+ }
#elif defined(IEEE80211_IOC_SSID) /* FreeBSD */
memset(&ireq, 0, sizeof(ireq));
strlcpy(ireq.i_name, ifname, sizeof(ireq.i_name));
- ireq.i_type = IEEE80211_IOC_NUMSSIDS;
- if (ioctl(s, SIOCG80211, &ireq) == 0)
- retval = 0;
+ ireq.i_type = IEEE80211_IOC_SSID;
+ ireq.i_val = -1;
+ ireq.i_data = &nwid;
+ if (ioctl(s, SIOCG80211, &ireq) == 0) {
+ retval = ireq.i_len;
+ memcpy(nwid, ssid, ireq.i_len);
+ ssid[ireq.i_len] = '\0';
+ }
#endif
close(s);
return retval;
/*
* dhcpcd - DHCP client daemon
- * Copyright 2006-2008 Roy Marples <roy@marples.name>
+ * Copyright 2006-2009 Roy Marples <roy@marples.name>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
#include <arpa/inet.h>
#include <linux/netlink.h>
#include <linux/rtnetlink.h>
+#include <linux/wireless.h>
#include <netinet/ether.h>
#include <netpacket/packet.h>
static void (*nl_remove)(const char *);
int
-if_wireless(const char *ifname)
+getifssid(const char *ifname, char *ssid)
{
- int s, retval = -1;
- struct ifreq ifr;
+ int s, retval;
+ struct iwreq iwr;
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
- return retval;
- memset(&ifr, 0, sizeof(ifr));
- strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
- if (ioctl(s, SIOCGIWNAME, &ifr) == 0)
- retval = 0;
+ return -1;
+ memset(&iwr, 0, sizeof(iwr));
+ strlcpy(iwr.ifr_name, ifname, sizeof(iwr.ifr_name));
+ iwr.u.essid.pointer = ssid;
+ iwr.u.essid.length = IF_SSIDSIZE - 1;
+
+ if (ioctl(s, SIOCGIWESSID, &iwr) == 0)
+ retval = iwr.u.essid.length;
+ else
+ retval = -1;
close(s);
return retval;
}
}
struct if_options *
-read_config(const char *file, const char *ifname)
+read_config(const char *file, const char *ifname, const char *ssid)
{
struct if_options *ifo;
FILE *f;
skip = 1;
continue;
}
+ /* Start of an ssid block, skip if not ours */
+ if (strcmp(option, "ssid") == 0) {
+ if (ssid && line && strcmp(line, ssid) == 0)
+ skip = 0;
+ else
+ skip = 1;
+ continue;
+ }
if (skip)
continue;
if (parse_config_line(ifo, option, line) != 1) {
in_addr_t *blacklist;
};
-struct if_options *read_config(const char *, const char *);
+struct if_options *read_config(const char *, const char *, const char *);
int add_options(struct if_options *, int, char **);
void free_options(struct if_options *);
/*
* dhcpcd - DHCP client daemon
- * Copyright 2006-2008 Roy Marples <roy@marples.name>
+ * Copyright 2006-2009 Roy Marples <roy@marples.name>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
/* We reserve the 100 range for virtual interfaces, if and when
* we can work them out. */
iface->metric = 200 + if_nametoindex(iface->name);
- if (if_wireless(ifname) == 0)
+ if (getifssid(ifname, iface->ssid) != -1)
iface->metric += 100;
#ifdef SIOCGIFHWADDR
/*
* dhcpcd - DHCP client daemon
- * Copyright 2006-2008 Roy Marples <roy@marples.name>
+ * Copyright 2006-2009 Roy Marples <roy@marples.name>
* All rights reserved
* Redistribution and use in source and binary forms, with or without
char *hwaddr_ntoa(const unsigned char *, size_t);
size_t hwaddr_aton(unsigned char *, const char *);
-int if_wireless(const char *);
+int getifssid(const char *, char *);
struct interface *init_interface(const char *);
struct interface *discover_interfaces(int, char * const *);
void free_interface(struct interface *);