]> git.ipfire.org Git - thirdparty/dhcpcd.git/blame - bind.c
Release dhcpcd-5.0.5
[thirdparty/dhcpcd.git] / bind.c
CommitLineData
fd05b7dc
RM
1/*
2 * dhcpcd - DHCP client daemon
601fb3d5 3 * Copyright (c) 2006-2009 Roy Marples <roy@marples.name>
fd05b7dc
RM
4 * All rights reserved
5
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
c93e8528
RM
28#include <sys/param.h>
29#include <fcntl.h>
30#ifdef BSD
31# include <paths.h>
32#endif
fd05b7dc
RM
33#include <signal.h>
34#include <stdlib.h>
765fbf7d 35#include <syslog.h>
fd05b7dc
RM
36#include <unistd.h>
37
38#include "arp.h"
39#include "bind.h"
40#include "common.h"
41#include "configure.h"
42#include "dhcpcd.h"
fd05b7dc
RM
43#include "eloop.h"
44#include "if-options.h"
fd05b7dc
RM
45#include "net.h"
46#include "signals.h"
47
c93e8528
RM
48#ifndef _PATH_DEVNULL
49# define _PATH_DEVNULL "/dev/null"
50#endif
51
6fcc7653
RM
52/* We do things after aquiring the lease, so ensure we have enough time for them */
53#define DHCP_MIN_LEASE 20
54
fd05b7dc
RM
55#ifndef THERE_IS_NO_FORK
56pid_t
57daemonise(void)
58{
59 pid_t pid;
60 sigset_t full;
61 sigset_t old;
62 char buf = '\0';
c93e8528 63 int sidpipe[2], fd;
fd05b7dc 64
da166178 65 if (options & DHCPCD_DAEMONISED || !(options & DHCPCD_DAEMONISE))
fd05b7dc
RM
66 return 0;
67 sigfillset(&full);
68 sigprocmask(SIG_SETMASK, &full, &old);
69 /* Setup a signal pipe so parent knows when to exit. */
70 if (pipe(sidpipe) == -1) {
765fbf7d 71 syslog(LOG_ERR, "pipe: %m");
fd05b7dc
RM
72 return -1;
73 }
765fbf7d 74 syslog(LOG_INFO, "forking to background");
fd05b7dc 75 switch (pid = fork()) {
eab2229c
RM
76 case -1:
77 syslog(LOG_ERR, "fork: %m");
78 exit(EXIT_FAILURE);
79 /* NOTREACHED */
80 case 0:
81 setsid();
82 /* Notify parent it's safe to exit as we've detached. */
83 close(sidpipe[0]);
84 if (write(sidpipe[1], &buf, 1) == -1)
85 syslog(LOG_ERR, "failed to notify parent: %m");
86 close(sidpipe[1]);
87 if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
88 dup2(fd, STDIN_FILENO);
89 dup2(fd, STDOUT_FILENO);
90 dup2(fd, STDERR_FILENO);
91 if (fd > STDERR_FILENO)
92 close(fd);
93 }
94 break;
95 default:
96 signal_reset();
97 /* Wait for child to detach */
98 close(sidpipe[1]);
99 if (read(sidpipe[0], &buf, 1) == -1)
100 syslog(LOG_ERR, "failed to read child: %m");
101 close(sidpipe[0]);
102 break;
fd05b7dc
RM
103 }
104 /* Done with the fd now */
105 if (pid != 0) {
106 writepid(pidfd, pid);
107 close(pidfd);
108 pidfd = -1;
109 exit(EXIT_SUCCESS);
110 }
da166178 111 options |= DHCPCD_DAEMONISED;
fd05b7dc
RM
112 sigprocmask(SIG_SETMASK, &old, NULL);
113 return pid;
114}
115#endif
116
f43e5853
RM
117void
118bind_interface(void *arg)
fd05b7dc 119{
f43e5853 120 struct interface *iface = arg;
fd05b7dc
RM
121 struct if_state *state = iface->state;
122 struct if_options *ifo = state->options;
123 struct dhcp_lease *lease = &state->lease;
124 struct timeval tv;
fd05b7dc 125
379a2b4b
RM
126 /* We're binding an address now - ensure that sockets are closed */
127 close_sockets(iface);
1ba42236 128 state->reason = NULL;
fd05b7dc
RM
129 delete_timeout(handle_exit_timeout, NULL);
130 if (clock_monotonic)
131 get_monotonic(&lease->boundtime);
fd05b7dc
RM
132 state->xid = 0;
133 free(state->old);
134 state->old = state->new;
135 state->new = state->offer;
136 state->offer = NULL;
137 get_lease(lease, state->new);
91a44b91
RM
138 if (ifo->options & DHCPCD_STATIC) {
139 syslog(LOG_INFO, "%s: using static address %s",
eab2229c 140 iface->name, inet_ntoa(lease->addr));
91a44b91 141 lease->leasetime = ~0U;
2f7cb97c 142 lease->net.s_addr = ifo->req_mask.s_addr;
1ba42236 143 state->reason = "STATIC";
91a44b91 144 } else if (IN_LINKLOCAL(htonl(state->new->yiaddr))) {
765fbf7d 145 syslog(LOG_INFO, "%s: using IPv4LL address %s",
eab2229c 146 iface->name, inet_ntoa(lease->addr));
fd05b7dc 147 lease->leasetime = ~0U;
1ba42236 148 state->reason = "IPV4LL";
fd05b7dc 149 } else if (ifo->options & DHCPCD_INFORM) {
2f7cb97c
RM
150 if (ifo->req_addr.s_addr != 0)
151 lease->addr.s_addr = ifo->req_addr.s_addr;
fd05b7dc
RM
152 else
153 lease->addr.s_addr = iface->addr.s_addr;
765fbf7d 154 syslog(LOG_INFO, "%s: received approval for %s", iface->name,
eab2229c 155 inet_ntoa(lease->addr));
fd05b7dc 156 lease->leasetime = ~0U;
1ba42236 157 state->reason = "INFORM";
fd05b7dc
RM
158 } else {
159 if (gettimeofday(&tv, NULL) == 0)
160 lease->leasedfrom = tv.tv_sec;
91a44b91 161 else if (lease->frominfo)
1ba42236 162 state->reason = "TIMEOUT";
fd05b7dc 163 if (lease->leasetime == ~0U) {
eab2229c
RM
164 lease->renewaltime =
165 lease->rebindtime =
166 lease->leasetime;
765fbf7d 167 syslog(LOG_INFO, "%s: leased %s for infinity",
eab2229c 168 iface->name, inet_ntoa(lease->addr));
fd05b7dc 169 } else {
6fcc7653
RM
170 if (lease->leasetime < DHCP_MIN_LEASE) {
171 syslog(LOG_WARNING,
172 "%s: minimum lease is %d seconds",
173 iface->name, DHCP_MIN_LEASE);
174 lease->leasetime = DHCP_MIN_LEASE;
175 }
40bc2d7f
RM
176 if (lease->rebindtime == 0)
177 lease->rebindtime = lease->leasetime * T2;
178 else if (lease->rebindtime >= lease->leasetime) {
fd05b7dc 179 lease->rebindtime = lease->leasetime * T2;
765fbf7d 180 syslog(LOG_ERR,
eab2229c
RM
181 "%s: rebind time greater than lease "
182 "time, forcing to %u seconds",
183 iface->name, lease->rebindtime);
fd05b7dc 184 }
40bc2d7f
RM
185 if (lease->renewaltime == 0)
186 lease->renewaltime = lease->leasetime * T1;
187 else if (lease->renewaltime > lease->rebindtime) {
fd05b7dc 188 lease->renewaltime = lease->leasetime * T1;
765fbf7d 189 syslog(LOG_ERR,
eab2229c
RM
190 "%s: renewal time greater than rebind "
191 "time, forcing to %u seconds",
192 iface->name, lease->renewaltime);
fd05b7dc 193 }
765fbf7d 194 syslog(LOG_INFO,
eab2229c
RM
195 "%s: leased %s for %u seconds", iface->name,
196 inet_ntoa(lease->addr), lease->leasetime);
fd05b7dc
RM
197 }
198 }
1ba42236
RM
199 if (options & DHCPCD_TEST) {
200 state->reason = "TEST";
201 run_script(iface);
202 exit(EXIT_SUCCESS);
203 }
204 if (state->reason == NULL) {
fd05b7dc
RM
205 if (state->old) {
206 if (state->old->yiaddr == state->new->yiaddr &&
207 lease->server.s_addr)
1ba42236 208 state->reason = "RENEW";
fd05b7dc 209 else
1ba42236 210 state->reason = "REBIND";
78c8e969 211 } else if (state->state == DHS_REBOOT)
1ba42236 212 state->reason = "REBOOT";
78c8e969 213 else
1ba42236 214 state->reason = "BOUND";
e7eeaf88 215 }
fd05b7dc
RM
216 if (lease->leasetime == ~0U)
217 lease->renewaltime = lease->rebindtime = lease->leasetime;
218 else {
219 add_timeout_sec(lease->renewaltime, start_renew, iface);
220 add_timeout_sec(lease->rebindtime, start_rebind, iface);
221 add_timeout_sec(lease->leasetime, start_expire, iface);
222 }
1ba42236 223 configure(iface);
fd05b7dc 224 daemonise();
78c8e969 225 state->state = DHS_BOUND;
fd05b7dc
RM
226 if (ifo->options & DHCPCD_ARP) {
227 state->claims = 0;
228 send_arp_announce(iface);
229 }
230}