Expand PMF_FN_* macros.
[netbsd-mini2440.git] / external / bsd / dhcpcd / dist / bind.c
blob40fc09e774914a90be793f5e9f7c69e445e9a9cd
1 /*
2 * dhcpcd - DHCP client daemon
3 * Copyright (c) 2006-2009 Roy Marples <roy@marples.name>
4 * All rights reserved
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.
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.
28 #include <sys/param.h>
29 #include <sys/time.h>
31 #include <fcntl.h>
32 #ifdef BSD
33 # include <paths.h>
34 #endif
35 #include <signal.h>
36 #include <stdlib.h>
37 #include <syslog.h>
38 #include <unistd.h>
40 #include "arp.h"
41 #include "bind.h"
42 #include "common.h"
43 #include "configure.h"
44 #include "dhcpcd.h"
45 #include "eloop.h"
46 #include "if-options.h"
47 #include "net.h"
48 #include "signals.h"
50 #ifndef _PATH_DEVNULL
51 # define _PATH_DEVNULL "/dev/null"
52 #endif
54 /* We do things after aquiring the lease, so ensure we have enough time for them */
55 #define DHCP_MIN_LEASE 20
57 #ifndef THERE_IS_NO_FORK
58 pid_t
59 daemonise(void)
61 pid_t pid;
62 sigset_t full;
63 sigset_t old;
64 char buf = '\0';
65 int sidpipe[2], fd;
67 if (options & DHCPCD_DAEMONISED || !(options & DHCPCD_DAEMONISE))
68 return 0;
69 sigfillset(&full);
70 sigprocmask(SIG_SETMASK, &full, &old);
71 /* Setup a signal pipe so parent knows when to exit. */
72 if (pipe(sidpipe) == -1) {
73 syslog(LOG_ERR, "pipe: %m");
74 return -1;
76 syslog(LOG_INFO, "forking to background");
77 switch (pid = fork()) {
78 case -1:
79 syslog(LOG_ERR, "fork: %m");
80 exit(EXIT_FAILURE);
81 /* NOTREACHED */
82 case 0:
83 setsid();
84 /* Notify parent it's safe to exit as we've detached. */
85 close(sidpipe[0]);
86 if (write(sidpipe[1], &buf, 1) == -1)
87 syslog(LOG_ERR, "failed to notify parent: %m");
88 close(sidpipe[1]);
89 if ((fd = open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
90 dup2(fd, STDIN_FILENO);
91 dup2(fd, STDOUT_FILENO);
92 dup2(fd, STDERR_FILENO);
93 if (fd > STDERR_FILENO)
94 close(fd);
96 break;
97 default:
98 signal_reset();
99 /* Wait for child to detach */
100 close(sidpipe[1]);
101 if (read(sidpipe[0], &buf, 1) == -1)
102 syslog(LOG_ERR, "failed to read child: %m");
103 close(sidpipe[0]);
104 break;
106 /* Done with the fd now */
107 if (pid != 0) {
108 writepid(pidfd, pid);
109 close(pidfd);
110 pidfd = -1;
111 exit(EXIT_SUCCESS);
113 options |= DHCPCD_DAEMONISED;
114 sigprocmask(SIG_SETMASK, &old, NULL);
115 return pid;
117 #endif
119 void
120 bind_interface(void *arg)
122 struct interface *iface = arg;
123 struct if_state *state = iface->state;
124 struct if_options *ifo = state->options;
125 struct dhcp_lease *lease = &state->lease;
126 struct timeval tv;
128 /* We're binding an address now - ensure that sockets are closed */
129 close_sockets(iface);
130 state->reason = NULL;
131 delete_timeout(handle_exit_timeout, NULL);
132 if (clock_monotonic)
133 get_monotonic(&lease->boundtime);
134 state->xid = 0;
135 free(state->old);
136 state->old = state->new;
137 state->new = state->offer;
138 state->offer = NULL;
139 get_lease(lease, state->new);
140 if (ifo->options & DHCPCD_STATIC) {
141 syslog(LOG_INFO, "%s: using static address %s",
142 iface->name, inet_ntoa(lease->addr));
143 lease->leasetime = ~0U;
144 lease->net.s_addr = ifo->req_mask.s_addr;
145 state->reason = "STATIC";
146 } else if (IN_LINKLOCAL(htonl(state->new->yiaddr))) {
147 syslog(LOG_INFO, "%s: using IPv4LL address %s",
148 iface->name, inet_ntoa(lease->addr));
149 lease->leasetime = ~0U;
150 state->reason = "IPV4LL";
151 } else if (ifo->options & DHCPCD_INFORM) {
152 if (ifo->req_addr.s_addr != 0)
153 lease->addr.s_addr = ifo->req_addr.s_addr;
154 else
155 lease->addr.s_addr = iface->addr.s_addr;
156 syslog(LOG_INFO, "%s: received approval for %s", iface->name,
157 inet_ntoa(lease->addr));
158 lease->leasetime = ~0U;
159 state->reason = "INFORM";
160 } else {
161 if (gettimeofday(&tv, NULL) == 0)
162 lease->leasedfrom = tv.tv_sec;
163 else if (lease->frominfo)
164 state->reason = "TIMEOUT";
165 if (lease->leasetime == ~0U) {
166 lease->renewaltime =
167 lease->rebindtime =
168 lease->leasetime;
169 syslog(LOG_INFO, "%s: leased %s for infinity",
170 iface->name, inet_ntoa(lease->addr));
171 } else {
172 if (lease->leasetime < DHCP_MIN_LEASE) {
173 syslog(LOG_WARNING,
174 "%s: minimum lease is %d seconds",
175 iface->name, DHCP_MIN_LEASE);
176 lease->leasetime = DHCP_MIN_LEASE;
178 if (lease->rebindtime == 0)
179 lease->rebindtime = lease->leasetime * T2;
180 else if (lease->rebindtime >= lease->leasetime) {
181 lease->rebindtime = lease->leasetime * T2;
182 syslog(LOG_ERR,
183 "%s: rebind time greater than lease "
184 "time, forcing to %u seconds",
185 iface->name, lease->rebindtime);
187 if (lease->renewaltime == 0)
188 lease->renewaltime = lease->leasetime * T1;
189 else if (lease->renewaltime > lease->rebindtime) {
190 lease->renewaltime = lease->leasetime * T1;
191 syslog(LOG_ERR,
192 "%s: renewal time greater than rebind "
193 "time, forcing to %u seconds",
194 iface->name, lease->renewaltime);
196 syslog(LOG_INFO,
197 "%s: leased %s for %u seconds", iface->name,
198 inet_ntoa(lease->addr), lease->leasetime);
201 if (options & DHCPCD_TEST) {
202 state->reason = "TEST";
203 run_script(iface);
204 exit(EXIT_SUCCESS);
206 if (state->reason == NULL) {
207 if (state->old) {
208 if (state->old->yiaddr == state->new->yiaddr &&
209 lease->server.s_addr)
210 state->reason = "RENEW";
211 else
212 state->reason = "REBIND";
213 } else if (state->state == DHS_REBOOT)
214 state->reason = "REBOOT";
215 else
216 state->reason = "BOUND";
218 if (lease->leasetime == ~0U)
219 lease->renewaltime = lease->rebindtime = lease->leasetime;
220 else {
221 add_timeout_sec(lease->renewaltime, start_renew, iface);
222 add_timeout_sec(lease->rebindtime, start_rebind, iface);
223 add_timeout_sec(lease->leasetime, start_expire, iface);
225 ifo->options &= ~ DHCPCD_CSR_WARNED;
226 configure(iface);
227 daemonise();
228 state->state = DHS_BOUND;
229 if (ifo->options & DHCPCD_ARP) {
230 state->claims = 0;
231 send_arp_announce(iface);