]> git.ipfire.org Git - thirdparty/dhcpcd.git/commitdiff
Add 4 and 6 arguments to the waitip command so that you can specify
authorRoy Marples <roy@marples.name>
Sat, 31 Aug 2013 16:48:39 +0000 (16:48 +0000)
committerRoy Marples <roy@marples.name>
Sat, 31 Aug 2013 16:48:39 +0000 (16:48 +0000)
which protocols to wait for.

dhcp6.c
dhcpcd.8.in
dhcpcd.c
dhcpcd.conf.5.in
if-options.c
if-options.h
ipv4.c
ipv4.h
ipv6nd.c

diff --git a/dhcp6.c b/dhcp6.c
index 54978446f006bf94e0faccf25deba6f060c2d66f..16eca1c11b5840e2eeb4d4c17cc5130d188e281a 100644 (file)
--- a/dhcp6.c
+++ b/dhcp6.c
@@ -1211,7 +1211,7 @@ dhcp6_checkstatusok(const struct interface *ifp,
 }
 
 static struct ipv6_addr *
-dhcp6_findaddr(const struct in6_addr *a, struct interface *ifp)
+dhcp6_findaddr(struct interface *ifp, const struct in6_addr *addr)
 {
        const struct dhcp6_state *state;
        struct ipv6_addr *ap;
@@ -1219,7 +1219,12 @@ dhcp6_findaddr(const struct in6_addr *a, struct interface *ifp)
        state = D6_CSTATE(ifp);
        if (state) {
                TAILQ_FOREACH(ap, &state->addrs, next) {
-                       if (IN6_ARE_ADDR_EQUAL(&ap->addr, a))
+                       if (addr == NULL) {
+                               if ((ap->flags &
+                                   (IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED)) ==
+                                   (IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED))
+                                       return ap;
+                       } else if (IN6_ARE_ADDR_EQUAL(&ap->addr, addr))
                                return ap;
                }
        }
@@ -1227,12 +1232,12 @@ dhcp6_findaddr(const struct in6_addr *a, struct interface *ifp)
 }
 
 int
-dhcp6_addrexists(const struct ipv6_addr *a)
+dhcp6_addrexists(const struct ipv6_addr *addr)
 {
        struct interface *ifp;
 
        TAILQ_FOREACH(ifp, ifaces, next) {
-               if (dhcp6_findaddr(&a->addr, ifp))
+               if (dhcp6_findaddr(ifp, addr == NULL ? NULL : &addr->addr))
                        return 1;
        }
        return 0;
@@ -1313,7 +1318,7 @@ dhcp6_findna(struct interface *ifp, const uint8_t *iaid,
                p = D6_COPTION_DATA(o);
                memcpy(&in6.s6_addr, p, sizeof(in6.s6_addr));
                p += sizeof(in6.s6_addr);
-               a = dhcp6_findaddr(&in6, ifp);
+               a = dhcp6_findaddr(ifp, &in6);
                if (a == NULL) {
                        a = calloc(1, sizeof(*a));
                        if (a == NULL) {
index ff2f704a0a014e143c1909cb2be1da0ad994a44a..618f8cccee43190ba38c9f0f1a00eaed3c1127f8 100644 (file)
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd August 26, 2013
+.Dd August 31, 2013
 .Dt DHCPCD 8
 .Os
 .Sh NAME
@@ -30,7 +30,7 @@
 .Nd a DHCP client
 .Sh SYNOPSIS
 .Nm
-.Op Fl 46ABbDdEGgHJKLpqTVw
+.Op Fl 46ABbDdEGgHJKLpqTV
 .Op Fl C , Fl Fl nohook Ar hook
 .Op Fl c , Fl Fl script Ar script
 .Op Fl e , Fl Fl env Ar value
@@ -51,6 +51,7 @@
 .Op Fl u , Fl Fl userclass Ar class
 .Op Fl v , Fl Fl vendor Ar code , Ar value
 .Op Fl W , Fl Fl whitelist Ar address Ns Op Ar /cidr
+.Op Fl w , Fl Fl waitip Op 4 | 6
 .Op Fl y , Fl Fl reboot Ar seconds
 .Op Fl X , Fl Fl blacklist Ar address Ns Op Ar /cidr
 .Op Fl Z , Fl Fl denyinterfaces Ar pattern
@@ -417,8 +418,10 @@ Set un-encapsulated vendor option to hello world.
 Display both program version and copyright information.
 .Nm
 then exits before doing any configuration.
-.It Fl w , Fl Fl waitip
+.It Fl w , Fl Fl waitip Op 4 | 6
 Wait for an address to be assigned before forking to the background.
+4 means wait for an IPv4 address to be assigned.
+6 means wait for an IPv6 address to be assigned.
 .It Fl x , Fl Fl exit Op Ar interface
 This will signal an existing
 .Nm
index d410c4a06b5b093d058a70ba19393749ca3d28ee..ba5c51803f1322060a03bfc3bd1301d3637d18fd 100644 (file)
--- a/dhcpcd.c
+++ b/dhcpcd.c
@@ -206,6 +206,23 @@ daemonise(void)
        char buf = '\0';
        int sidpipe[2], fd;
 
+       if (options & DHCPCD_DAEMONISE && !(options & DHCPCD_DAEMONISED)) {
+               if (options & DHCPCD_WAITIP4 &&
+                   !ipv4_addrexists(NULL))
+                       return -1;
+               if (options & DHCPCD_WAITIP6 &&
+                   !ipv6nd_addrexists(NULL) &&
+                   !dhcp6_addrexists(NULL))
+                       return -1;
+               if ((options &
+                   (DHCPCD_WAITIP | DHCPCD_WAITIP4 | DHCPCD_WAITIP6)) ==
+                   DHCPCD_WAITIP &&
+                   !ipv4_addrexists(NULL) &&
+                   !ipv6nd_addrexists(NULL) &&
+                   !dhcp6_addrexists(NULL))
+                       return -1;
+       }
+
        eloop_timeout_delete(handle_exit_timeout, NULL);
        if (options & DHCPCD_DAEMONISED || !(options & DHCPCD_DAEMONISE))
                return 0;
index a24d1af3ad45387ca9a5c651b732c9e1a637bd63..e49948b24f0b41f9ea581dbaa1ebc65fb5011bfd 100644 (file)
@@ -22,7 +22,7 @@
 .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 .\" SUCH DAMAGE.
 .\"
-.Dd August 26, 2013
+.Dd August 31, 2013
 .Dt DHCPCD.CONF 5 SMM
 .Os
 .Sh NAME
@@ -410,8 +410,10 @@ For example
 If not set then none is sent.
 Some badly configured DHCP servers reject unknown vendorclassids.
 To work around it, try and impersonate Windows by using the MSFT vendorclassid.
-.It Ic waitip
+.It Ic waitip Op 4 | 6
 Wait for an address to be assigned before forking to the background.
+4 means wait for an IPv4 address to be assigned.
+6 means wait for an IPv6 address to be assigned.
 .It Ic xidhwaddr
 Use the last four bytes of the hardware address as the DHCP xid instead
 of a randomly generated number.
index 3ed2cf42913e5b83b1c7a8ba611aaac79189138c..11c4f70c8bc24872069472bd53636d6f234f3b23 100644 (file)
@@ -90,7 +90,7 @@ const struct option cf_options[] = {
        {"timeout",         required_argument, NULL, 't'},
        {"userclass",       required_argument, NULL, 'u'},
        {"vendor",          required_argument, NULL, 'v'},
-       {"waitip",          no_argument,       NULL, 'w'},
+       {"waitip",          optional_argument, NULL, 'w'},
        {"exit",            no_argument,       NULL, 'x'},
        {"allowinterfaces", required_argument, NULL, 'z'},
        {"reboot",          required_argument, NULL, 'y'},
@@ -640,6 +640,12 @@ parse_option(struct if_options *ifo, int opt, const char *arg)
                break;
        case 'w':
                ifo->options |= DHCPCD_WAITIP;
+               if (arg != NULL && arg[0] != '\0') {
+                       if (arg[0] == '4' || arg[1] == '4')
+                               ifo->options |= DHCPCD_WAITIP4;
+                       if (arg[0] == '6' || arg[1] == '6')
+                               ifo->options |= DHCPCD_WAITIP6;
+               }
                break;
        case 'y':
                ifo->reboot = atoint(arg);
index 9eb768cae5f76b514fd60313c4cf06caba3f0da3..a3ef051423624537c154f5504e923492598bd78b 100644 (file)
@@ -96,6 +96,8 @@
 #define DHCPCD_DEPARTED                        (1ULL << 42)
 #define DHCPCD_HOSTNAME_SHORT          (1ULL << 43)
 #define DHCPCD_EXITING                 (1ULL << 44)
+#define DHCPCD_WAITIP4                 (1ULL << 45)
+#define DHCPCD_WAITIP6                 (1ULL << 46)
 
 extern const struct option cf_options[];
 
diff --git a/ipv4.c b/ipv4.c
index 4d497fb28e24f5c9278a7830523eee917cd46b29..bd33ad6b82cb10507ab2607834e376892fdc576f 100644 (file)
--- a/ipv4.c
+++ b/ipv4.c
@@ -109,6 +109,27 @@ ipv4_getnetmask(uint32_t addr)
        return 0;
 }
 
+int
+ipv4_addrexists(const struct in_addr *addr)
+{
+       const struct interface *ifp;
+       const struct dhcp_state *state;
+
+       TAILQ_FOREACH(ifp, ifaces, next) {
+               state = D_CSTATE(ifp);
+               if (state) {
+                       if (addr == NULL) {
+                               if (state->addr.s_addr)
+                                       return 1;
+                       } else if (memcmp(&addr->s_addr,
+                           &state->addr.s_addr,
+                           sizeof(state->addr.s_addr)) == 0)
+                               return 1;
+               }
+       }
+       return 0;
+}
+
 int
 ipv4_doaddress(const char *ifname,
     struct in_addr *addr, struct in_addr *net, struct in_addr *dst, int act)
diff --git a/ipv4.h b/ipv4.h
index ae9d6fcf8e819c00df97f7ce0bf712e4b3a9352e..eec0000ac21b434671609d1fc315eebbbfd3cb0a 100644 (file)
--- a/ipv4.h
+++ b/ipv4.h
@@ -46,6 +46,7 @@ int ipv4_init(void);
 int inet_ntocidr(struct in_addr);
 int inet_cidrtoaddr(int, struct in_addr *);
 uint32_t ipv4_getnetmask(uint32_t);
+int ipv4_addrexists(const struct in_addr *);
 
 void ipv4_buildroutes(void);
 void ipv4_applyaddr(void *);
index 8f372b0db5ecc66272ba58f20175bc17531e713e..7cf3367953fa6540499849f4bbed548d24dba405 100644 (file)
--- a/ipv6nd.c
+++ b/ipv6nd.c
@@ -382,14 +382,19 @@ ipv6nd_free_opts(struct ra *rap)
 }
 
 int
-ipv6nd_addrexists(const struct ipv6_addr *a)
+ipv6nd_addrexists(const struct ipv6_addr *addr)
 {
        struct ra *rap;
        struct ipv6_addr *ap;
 
        TAILQ_FOREACH(rap, &ipv6_routers, next) {
                TAILQ_FOREACH(ap, &rap->addrs, next) {
-                       if (memcmp(&ap->addr, &a->addr, sizeof(a->addr)) == 0)
+                       if (addr == NULL) {
+                               if ((ap->flags &
+                                   (IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED)) ==
+                                   (IPV6_AF_ADDED | IPV6_AF_DADCOMPLETED))
+                                       return 1;
+                       } else if (IN6_ARE_ADDR_EQUAL(&ap->addr, addr))
                                return 1;
                }
        }