From: Roy Marples Date: Sat, 31 Aug 2013 16:48:39 +0000 (+0000) Subject: Add 4 and 6 arguments to the waitip command so that you can specify X-Git-Tag: v6.1.0~34 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=7013b07382b7a2aa63115d75fc6724bedf199a9c;p=thirdparty%2Fdhcpcd.git Add 4 and 6 arguments to the waitip command so that you can specify which protocols to wait for. --- diff --git a/dhcp6.c b/dhcp6.c index 54978446..16eca1c1 100644 --- 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) { diff --git a/dhcpcd.8.in b/dhcpcd.8.in index ff2f704a..618f8ccc 100644 --- a/dhcpcd.8.in +++ b/dhcpcd.8.in @@ -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 diff --git a/dhcpcd.c b/dhcpcd.c index d410c4a0..ba5c5180 100644 --- 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; diff --git a/dhcpcd.conf.5.in b/dhcpcd.conf.5.in index a24d1af3..e49948b2 100644 --- a/dhcpcd.conf.5.in +++ b/dhcpcd.conf.5.in @@ -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. diff --git a/if-options.c b/if-options.c index 3ed2cf42..11c4f70c 100644 --- a/if-options.c +++ b/if-options.c @@ -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); diff --git a/if-options.h b/if-options.h index 9eb768ca..a3ef0514 100644 --- a/if-options.h +++ b/if-options.h @@ -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 4d497fb2..bd33ad6b 100644 --- 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 ae9d6fcf..eec0000a 100644 --- 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 *); diff --git a/ipv6nd.c b/ipv6nd.c index 8f372b0d..7cf33679 100644 --- 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; } }