which protocols to wait for.
}
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;
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;
}
}
}
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;
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) {
.\" 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
.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
.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
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
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;
.\" 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
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.
{"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'},
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);
#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[];
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)
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 *);
}
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;
}
}