]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
You can now add a configure block per ssid if the interface is wireless.
authorRoy Marples <roy@marples.name>
Thu, 1 Jan 2009 20:51:04 +0000 (20:51 +0000)
committerRoy Marples <roy@marples.name>
Thu, 1 Jan 2009 20:51:04 +0000 (20:51 +0000)
dhcpcd.c
dhcpcd.conf.5.in
dhcpcd.h
if-bsd.c
if-linux.c
if-options.c
if-options.h
net.c
net.h

index 033f1368bec60cfcf970d0381349da64b5e88add..aa2a6020359bdf2dd7e11336f8c048a199c8ef5a 100644 (file)
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -73,6 +73,8 @@ char **ifav = NULL;
 int ifdc = 0;
 char **ifdv = NULL;
 
+static char **margv;
+static int margc;
 static char **ifv;
 static int ifc;
 static int linkfd = -1;
@@ -642,10 +644,67 @@ send_release(struct interface *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, 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)
@@ -669,6 +728,12 @@ handle_carrier(const char *ifname)
                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;
@@ -889,62 +954,6 @@ start_interface(void *arg)
                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)
 {
@@ -1217,7 +1226,9 @@ main(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)
index f136a944d3f596d03d00bdedc9d8d73c55c61178..56090c483a629c50a8c2c8cda0f5f7d7d90cdb6f 100644 (file)
@@ -175,6 +175,9 @@ Use
 .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 .
index 07d69c24ee783f37b26a1fd62d4d2463961aedcb..0bcb280da9df39b1fc24fcd45ae68431086d6764 100644 (file)
--- a/dhcpcd.h
+++ b/dhcpcd.h
@@ -1,6 +1,6 @@
 /* 
  * 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
@@ -37,6 +37,7 @@
 #include "if-options.h"
 
 #define HWADDR_LEN 20
+#define IF_SSIDSIZE 33
 
 enum DHS {
        DHS_INIT,
@@ -85,6 +86,7 @@ struct interface
        int metric;
        int carrier;
        int arpable;
+       char ssid[IF_SSIDSIZE];
 
        int raw_fd;
        int udp_fd;
index 9bf8a4edab44165ccd8ae3489eb5cfeee58b431b..82bce1886dd030520ef89d606bc26b81c3b45b59 100644 (file)
--- a/if-bsd.c
+++ b/if-bsd.c
@@ -1,6 +1,6 @@
 /* 
  * 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
@@ -64,7 +64,7 @@
 #endif
 
 int
-if_wireless(const char *ifname)
+getifssid(const char *ifname, char *ssid)
 {
        int s, retval = -1;
 #if defined(SIOCG80211NWID)
@@ -72,6 +72,7 @@ if_wireless(const char *ifname)
        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)
@@ -81,14 +82,22 @@ if_wireless(const char *ifname)
        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;
index c9cba9ef133918d7076fce17d43f8f155094340f..937b4ad0cd733f37e6e98452d46cda08c2babd1a 100644 (file)
@@ -1,6 +1,6 @@
 /* 
  * 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
@@ -36,6 +36,7 @@
 #include <arpa/inet.h>
 #include <linux/netlink.h>
 #include <linux/rtnetlink.h>
+#include <linux/wireless.h>
 #include <netinet/ether.h>
 #include <netpacket/packet.h>
 
@@ -73,17 +74,22 @@ static void (*nl_add)(const char *);
 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;
 }
index abbb92ccfb3f153ba48c558c6d59b2e2057621e3..4e8ddbfecf507f921f7fe3e46bdde74f8ae72d6e 100644 (file)
@@ -662,7 +662,7 @@ parse_config_line(struct if_options *ifo, const char *opt, char *line)
 }
 
 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;
@@ -709,6 +709,14 @@ read_config(const char *file, const char *ifname)
                                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) {
index 545e74791b623599582b69640d96f86bd610cd61..95e83dc6547bad774ee81d9c76da5c01954a535f 100644 (file)
@@ -100,7 +100,7 @@ struct if_options {
        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 *);
 
diff --git a/net.c b/net.c
index 45dab802acc829c783318a1f6bf13cd8d7ad3254..ed580cc55beb9b2ac8cf7f6a2a7a1c2ea16dde8d 100644 (file)
--- a/net.c
+++ b/net.c
@@ -1,6 +1,6 @@
 /* 
  * 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
@@ -196,7 +196,7 @@ init_interface(const char *ifname)
        /* 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
diff --git a/net.h b/net.h
index 29e7df36c507de20eb522462584b1c59236f1614..b65dc7ee10cd3757a26e9c82ff30bb4cdb010784 100644 (file)
--- a/net.h
+++ b/net.h
@@ -1,6 +1,6 @@
 /* 
  * 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
@@ -91,7 +91,7 @@ uint32_t get_netmask(uint32_t);
 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 *);