]>
git.ipfire.org Git - people/ms/dnsmasq.git/blob - src/dhcp.c
1 /* dnsmasq is Copyright (c) 2000-2006 Simon Kelley
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; version 2 dated June, 1991.
7 This program is distributed in the hope that it will be useful,
8 but WITHOUT ANY WARRANTY; without even the implied warranty of
9 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 GNU General Public License for more details.
16 struct in_addr relay
, primary
;
17 struct dhcp_context
*current
;
21 static int complete_context(struct daemon
*daemon
, struct in_addr local
, int if_index
,
22 struct in_addr netmask
, struct in_addr broadcast
, void *vparam
);
24 void dhcp_init(struct daemon
*daemon
)
26 int fd
= socket(PF_INET
, SOCK_DGRAM
, IPPROTO_UDP
);
27 struct sockaddr_in saddr
;
29 struct dhcp_config
*configs
, *cp
;
32 die (_("cannot create DHCP socket : %s"), NULL
);
35 #if defined(HAVE_LINUX_NETWORK)
36 setsockopt(fd
, SOL_IP
, IP_PKTINFO
, &oneopt
, sizeof(oneopt
)) == -1 ||
37 #elif defined(IP_RECVIF)
38 setsockopt(fd
, IPPROTO_IP
, IP_RECVIF
, &oneopt
, sizeof(oneopt
)) == -1 ||
40 setsockopt(fd
, SOL_SOCKET
, SO_BROADCAST
, &oneopt
, sizeof(oneopt
)) == -1)
41 die(_("failed to set options on DHCP socket: %s"), NULL
);
43 /* When bind-interfaces is set, there might be more than one dnmsasq
44 instance binding port 67. That's Ok if they serve different networks.
45 Need to set REUSEADDR to make this posible. */
46 if ((daemon
->options
& OPT_NOWILD
) &&
47 setsockopt(fd
, SOL_SOCKET
, SO_REUSEADDR
, &oneopt
, sizeof(oneopt
)) == -1)
48 die(_("failed to set SO_REUSEADDR on DHCP socket: %s"), NULL
);
50 memset(&saddr
, 0, sizeof(saddr
));
51 saddr
.sin_family
= AF_INET
;
52 saddr
.sin_port
= htons(DHCP_SERVER_PORT
);
53 saddr
.sin_addr
.s_addr
= INADDR_ANY
;
54 #ifdef HAVE_SOCKADDR_SA_LEN
55 saddr
.sin_len
= sizeof(struct sockaddr_in
);
58 if (bind(fd
, (struct sockaddr
*)&saddr
, sizeof(struct sockaddr_in
)))
59 die(_("failed to bind DHCP server socket: %s"), NULL
);
63 #ifndef HAVE_LINUX_NETWORK
64 /* When we're not using capabilities, we need to do this here before
65 we drop root. Also, set buffer size small, to avoid wasting
68 if (daemon
->options
& OPT_NO_PING
)
69 daemon
->dhcp_icmp_fd
= -1;
70 else if ((daemon
->dhcp_icmp_fd
= make_icmp_sock()) == -1 ||
71 setsockopt(daemon
->dhcp_icmp_fd
, SOL_SOCKET
, SO_RCVBUF
, &oneopt
, sizeof(oneopt
)) == -1 )
72 die(_("cannot create ICMP raw socket: %s."), NULL
);
74 /* Make BPF raw send socket */
78 /* If the same IP appears in more than one host config, then DISCOVER
79 for one of the hosts will get the address, but REQUEST will be NAKed,
80 since the address is reserved by the other one -> protocol loop. */
81 for (configs
= daemon
->dhcp_conf
; configs
; configs
= configs
->next
)
82 for (cp
= configs
->next
; cp
; cp
= cp
->next
)
83 if ((configs
->flags
& cp
->flags
& CONFIG_ADDR
) && configs
->addr
.s_addr
== cp
->addr
.s_addr
)
84 die(_("duplicate IP address %s in dhcp-config directive."), inet_ntoa(cp
->addr
));
86 daemon
->dhcp_packet
.iov_len
= sizeof(struct dhcp_packet
);
87 daemon
->dhcp_packet
.iov_base
= safe_malloc(daemon
->dhcp_packet
.iov_len
);
88 /* These two each hold a DHCP option max size 255
89 and get a terminating zero added */
90 daemon
->dhcp_buff
= safe_malloc(256);
91 daemon
->dhcp_buff2
= safe_malloc(256);
92 daemon
->ping_results
= NULL
;
95 void dhcp_packet(struct daemon
*daemon
, time_t now
)
97 struct dhcp_packet
*mess
;
98 struct dhcp_context
*context
;
102 struct sockaddr_in dest
;
103 struct cmsghdr
*cmptr
;
106 int iface_index
= 0, unicast_dest
= 0;
107 struct in_addr iface_addr
;
108 struct iface_param parm
;
111 struct cmsghdr align
; /* this ensures alignment */
112 #ifdef HAVE_LINUX_NETWORK
113 char control
[CMSG_SPACE(sizeof(struct in_pktinfo
))];
115 char control
[CMSG_SPACE(sizeof(struct sockaddr_dl
))];
119 msg
.msg_control
= control_u
.control
;
120 msg
.msg_controllen
= sizeof(control_u
);
123 msg
.msg_iov
= &daemon
->dhcp_packet
;
129 while ((sz
= recvmsg(daemon
->dhcpfd
, &msg
, MSG_PEEK
)) == -1 && errno
== EINTR
);
131 while (sz
!= -1 && (msg
.msg_flags
& MSG_TRUNC
) &&
132 expand_buf(&daemon
->dhcp_packet
, daemon
->dhcp_packet
.iov_len
+ 100));
134 /* expand_buf may have moved buffer */
135 mess
= daemon
->dhcp_packet
.iov_base
;
136 msg
.msg_controllen
= sizeof(control_u
);
138 msg
.msg_name
= &dest
;
139 msg
.msg_namelen
= sizeof(dest
);
141 while ((sz
= recvmsg(daemon
->dhcpfd
, &msg
, 0)) && errno
== EINTR
);
143 if ((msg
.msg_flags
& MSG_TRUNC
) ||
144 sz
< (ssize_t
)(sizeof(*mess
) - sizeof(mess
->options
)))
147 #if defined (HAVE_LINUX_NETWORK)
148 if (msg
.msg_controllen
< sizeof(struct cmsghdr
))
150 for (cmptr
= CMSG_FIRSTHDR(&msg
); cmptr
; cmptr
= CMSG_NXTHDR(&msg
, cmptr
))
151 if (cmptr
->cmsg_level
== SOL_IP
&& cmptr
->cmsg_type
== IP_PKTINFO
)
153 iface_index
= ((struct in_pktinfo
*)CMSG_DATA(cmptr
))->ipi_ifindex
;
154 if (((struct in_pktinfo
*)CMSG_DATA(cmptr
))->ipi_addr
.s_addr
!= INADDR_BROADCAST
)
158 if (!(ifr
.ifr_ifindex
= iface_index
) ||
159 ioctl(daemon
->dhcpfd
, SIOCGIFNAME
, &ifr
) == -1)
162 #elif defined(IP_RECVIF)
163 if (msg
.msg_controllen
< sizeof(struct cmsghdr
))
165 for (cmptr
= CMSG_FIRSTHDR(&msg
); cmptr
; cmptr
= CMSG_NXTHDR(&msg
, cmptr
))
166 if (cmptr
->cmsg_level
== IPPROTO_IP
&& cmptr
->cmsg_type
== IP_RECVIF
)
167 iface_index
= ((struct sockaddr_dl
*)CMSG_DATA(cmptr
))->sdl_index
;
169 if (!iface_index
|| !if_indextoname(iface_index
, ifr
.ifr_name
))
175 for (name
= daemon
->if_names
; name
->isloop
; name
= name
->next
);
176 strcpy(ifr
.ifr_name
, name
->name
);
177 iface_index
= if_nametoindex(name
->name
);
181 ifr
.ifr_addr
.sa_family
= AF_INET
;
182 if (ioctl(daemon
->dhcpfd
, SIOCGIFADDR
, &ifr
) < 0 )
184 iface_addr
= ((struct sockaddr_in
*) &ifr
.ifr_addr
)->sin_addr
;
186 for (tmp
= daemon
->dhcp_except
; tmp
; tmp
= tmp
->next
)
187 if (tmp
->name
&& (strcmp(tmp
->name
, ifr
.ifr_name
) == 0))
190 if (!iface_check(daemon
, AF_INET
, (struct all_addr
*)&iface_addr
, ifr
.ifr_name
))
193 /* unlinked contexts are marked by context->current == context */
194 for (context
= daemon
->dhcp
; context
; context
= context
->next
)
195 context
->current
= context
;
197 parm
.relay
= mess
->giaddr
;
198 parm
.primary
= iface_addr
;
200 parm
.ind
= iface_index
;
202 if (!iface_enumerate(daemon
, &parm
, complete_context
, NULL
))
204 lease_prune(NULL
, now
); /* lose any expired leases */
205 iov
.iov_len
= dhcp_reply(daemon
, parm
.current
, ifr
.ifr_name
, (size_t)sz
, now
, unicast_dest
);
206 lease_update_file(daemon
, now
);
207 lease_update_dns(daemon
);
208 lease_collect(daemon
);
210 if (iov
.iov_len
== 0)
213 msg
.msg_name
= &dest
;
214 msg
.msg_namelen
= sizeof(dest
);
215 msg
.msg_control
= NULL
;
216 msg
.msg_controllen
= 0;
218 iov
.iov_base
= daemon
->dhcp_packet
.iov_base
;
220 /* packet buffer may have moved */
221 mess
= daemon
->dhcp_packet
.iov_base
;
223 #ifdef HAVE_SOCKADDR_SA_LEN
224 dest
.sin_len
= sizeof(struct sockaddr_in
);
227 if (mess
->giaddr
.s_addr
)
229 /* Send to BOOTP relay */
230 dest
.sin_port
= htons(DHCP_SERVER_PORT
);
231 dest
.sin_addr
= mess
->giaddr
;
233 else if (mess
->ciaddr
.s_addr
)
235 /* If the client's idea of its own address tallys with
236 the source address in the request packet, we believe the
237 source port too, and send back to that. */
238 if (dest
.sin_addr
.s_addr
!= mess
->ciaddr
.s_addr
|| !dest
.sin_port
)
240 dest
.sin_port
= htons(DHCP_CLIENT_PORT
);
241 dest
.sin_addr
= mess
->ciaddr
;
244 #ifdef HAVE_LINUX_NETWORK
245 else if ((ntohs(mess
->flags
) & 0x8000) || mess
->hlen
== 0 ||
246 mess
->hlen
> sizeof(ifr
.ifr_addr
.sa_data
) || mess
->htype
== 0)
248 /* broadcast to 255.255.255.255 (or mac address invalid) */
249 struct in_pktinfo
*pkt
;
250 msg
.msg_control
= control_u
.control
;
251 msg
.msg_controllen
= sizeof(control_u
);
252 cmptr
= CMSG_FIRSTHDR(&msg
);
253 dest
.sin_addr
.s_addr
= INADDR_BROADCAST
;
254 dest
.sin_port
= htons(DHCP_CLIENT_PORT
);
255 pkt
= (struct in_pktinfo
*)CMSG_DATA(cmptr
);
256 pkt
->ipi_ifindex
= iface_index
;
257 pkt
->ipi_spec_dst
.s_addr
= 0;
258 msg
.msg_controllen
= cmptr
->cmsg_len
= CMSG_LEN(sizeof(struct in_pktinfo
));
259 cmptr
->cmsg_level
= SOL_IP
;
260 cmptr
->cmsg_type
= IP_PKTINFO
;
264 /* unicast to unconfigured client. Inject mac address direct into ARP cache.
265 struct sockaddr limits size to 14 bytes. */
267 dest
.sin_addr
= mess
->yiaddr
;
268 dest
.sin_port
= htons(DHCP_CLIENT_PORT
);
269 *((struct sockaddr_in
*)&req
.arp_pa
) = dest
;
270 req
.arp_ha
.sa_family
= mess
->htype
;
271 memcpy(req
.arp_ha
.sa_data
, mess
->chaddr
, mess
->hlen
);
272 strncpy(req
.arp_dev
, ifr
.ifr_name
, 16);
273 req
.arp_flags
= ATF_COM
;
274 ioctl(daemon
->dhcpfd
, SIOCSARP
, &req
);
279 send_via_bpf(daemon
, mess
, iov
.iov_len
, iface_addr
, &ifr
);
284 while(sendmsg(daemon
->dhcpfd
, &msg
, 0) == -1 && retry_send());
287 /* This is a complex routine: it gets called with each (address,netmask,broadcast) triple
288 of each interface (and any relay address) and does the following things:
290 1) Discards stuff for interfaces other than the one on which a DHCP packet just arrived.
291 2) Fills in any netmask and broadcast addresses which have not been explicitly configured.
292 3) Fills in local (this host) and router (this host or relay) addresses.
293 4) Links contexts which are valid for hosts directly connected to the arrival interface on ->current.
295 Note that the current chain may be superceded later for configured hosts or those coming via gateways. */
297 static int complete_context(struct daemon
*daemon
, struct in_addr local
, int if_index
,
298 struct in_addr netmask
, struct in_addr broadcast
, void *vparam
)
300 struct dhcp_context
*context
;
301 struct iface_param
*param
= vparam
;
303 if (if_index
!= param
->ind
)
304 return 1; /* no for us. */
306 for (context
= daemon
->dhcp
; context
; context
= context
->next
)
308 if (!(context
->flags
& CONTEXT_NETMASK
) &&
309 (is_same_net(local
, context
->start
, netmask
) ||
310 is_same_net(local
, context
->end
, netmask
)))
312 if (context
->netmask
.s_addr
!= netmask
.s_addr
&&
313 !(is_same_net(local
, context
->start
, netmask
) &&
314 is_same_net(local
, context
->end
, netmask
)))
316 strcpy(daemon
->dhcp_buff
, inet_ntoa(context
->start
));
317 strcpy(daemon
->dhcp_buff2
, inet_ntoa(context
->end
));
318 syslog(LOG_WARNING
, _("DHCP range %s -- %s is not consistent with netmask %s"),
319 daemon
->dhcp_buff
, daemon
->dhcp_buff2
, inet_ntoa(netmask
));
321 context
->netmask
= netmask
;
324 if (context
->netmask
.s_addr
)
326 if (is_same_net(local
, context
->start
, context
->netmask
) &&
327 is_same_net(local
, context
->end
, context
->netmask
))
329 /* link it onto the current chain if we've not seen it before */
330 if (context
->current
== context
)
332 context
->router
= local
;
333 context
->local
= local
;
334 context
->current
= param
->current
;
335 param
->current
= context
;
338 if (!(context
->flags
& CONTEXT_BRDCAST
))
340 if (is_same_net(broadcast
, context
->start
, context
->netmask
))
341 context
->broadcast
= broadcast
;
343 context
->broadcast
.s_addr
= context
->start
.s_addr
| ~context
->netmask
.s_addr
;
346 else if (param
->relay
.s_addr
&& is_same_net(param
->relay
, context
->start
, context
->netmask
))
348 context
->router
= param
->relay
;
349 context
->local
= param
->primary
;
350 /* fill in missing broadcast addresses for relayed ranges */
351 if (!(context
->flags
& CONTEXT_BRDCAST
))
352 context
->broadcast
.s_addr
= context
->start
.s_addr
| ~context
->netmask
.s_addr
;
361 struct dhcp_context
*address_available(struct dhcp_context
*context
, struct in_addr taddr
)
363 /* Check is an address is OK for this network, check all
364 possible ranges. Make sure that the address isn't in use
365 by the server itself. */
367 unsigned int start
, end
, addr
= ntohl(taddr
.s_addr
);
368 struct dhcp_context
*tmp
;
370 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
371 if (taddr
.s_addr
== context
->router
.s_addr
)
374 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
376 start
= ntohl(tmp
->start
.s_addr
);
377 end
= ntohl(tmp
->end
.s_addr
);
379 if (!(tmp
->flags
& CONTEXT_STATIC
) &&
388 struct dhcp_context
*narrow_context(struct dhcp_context
*context
, struct in_addr taddr
)
390 /* We start of with a set of possible contexts, all on the current physical interface.
391 These are chained on ->current.
392 Here we have an address, and return the actual context correponding to that
393 address. Note that none may fit, if the address came a dhcp-host and is outside
394 any dhcp-range. In that case we return a static range if possible, or failing that,
395 any context on the correct subnet. (If there's more than one, this is a dodgy
396 configuration: maybe there should be a warning.) */
398 struct dhcp_context
*tmp
;
400 if ((tmp
= address_available(context
, taddr
)))
403 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
404 if (is_same_net(taddr
, tmp
->start
, tmp
->netmask
) &&
405 (tmp
->flags
& CONTEXT_STATIC
))
408 for (tmp
= context
; tmp
; tmp
= tmp
->current
)
409 if (is_same_net(taddr
, tmp
->start
, tmp
->netmask
))
415 struct dhcp_config
*config_find_by_address(struct dhcp_config
*configs
, struct in_addr addr
)
417 struct dhcp_config
*config
;
419 for (config
= configs
; config
; config
= config
->next
)
420 if ((config
->flags
& CONFIG_ADDR
) && config
->addr
.s_addr
== addr
.s_addr
)
426 /* Is every member of check matched by a member of pool?
427 If negonly, match unless there's a negative tag which matches. */
428 int match_netid(struct dhcp_netid
*check
, struct dhcp_netid
*pool
, int negonly
)
430 struct dhcp_netid
*tmp1
;
432 if (!check
&& !negonly
)
435 for (; check
; check
= check
->next
)
437 if (check
->net
[0] != '#')
439 for (tmp1
= pool
; tmp1
; tmp1
= tmp1
->next
)
440 if (strcmp(check
->net
, tmp1
->net
) == 0)
442 if (!tmp1
|| negonly
)
446 for (tmp1
= pool
; tmp1
; tmp1
= tmp1
->next
)
447 if (strcmp((check
->net
)+1, tmp1
->net
) == 0)
453 int address_allocate(struct dhcp_context
*context
, struct daemon
*daemon
,
454 struct in_addr
*addrp
, unsigned char *hwaddr
, int hw_len
,
455 struct dhcp_netid
*netids
, time_t now
)
457 /* Find a free address: exclude anything in use and anything allocated to
458 a particular hwaddr/clientid/hostname in our configuration.
459 Try to return from contexts which match netids first. */
461 struct in_addr start
, addr
;
462 struct dhcp_context
*c
, *d
;
467 for (j
= 0, i
= 0; i
< hw_len
; i
++)
468 j
+= hwaddr
[i
] + (hwaddr
[i
] << 8) + (hwaddr
[i
] << 16);
470 for (pass
= 0; pass
<= 1; pass
++)
471 for (c
= context
; c
; c
= c
->current
)
472 if (c
->flags
& CONTEXT_STATIC
)
474 else if (!match_netid(c
->filter
, netids
, pass
))
478 /* pick a seed based on hwaddr then iterate until we find a free address. */
479 start
.s_addr
= addr
.s_addr
=
480 htonl(ntohl(c
->start
.s_addr
) +
481 ((j
+ c
->addr_epoch
) % (1 + ntohl(c
->end
.s_addr
) - ntohl(c
->start
.s_addr
))));
484 /* eliminate addresses in use by the server. */
485 for (d
= context
; d
; d
= d
->current
)
486 if (addr
.s_addr
== d
->router
.s_addr
)
490 !lease_find_by_addr(addr
) &&
491 !config_find_by_address(daemon
->dhcp_conf
, addr
))
493 struct ping_result
*r
, *victim
= NULL
;
494 int count
, max
= (int)(0.6 * (((float)PING_CACHE_TIME
)/
495 ((float)PING_WAIT
)));
499 if (daemon
->options
& OPT_NO_PING
)
502 /* check if we failed to ping addr sometime in the last
503 PING_CACHE_TIME seconds. If so, assume the same situation still exists.
504 This avoids problems when a stupid client bangs
505 on us repeatedly. As a final check, if we did more
506 than 60% of the possible ping checks in the last
507 PING_CACHE_TIME, we are in high-load mode, so don't do any more. */
508 for (count
= 0, r
= daemon
->ping_results
; r
; r
= r
->next
)
509 if (difftime(now
, r
->time
) > (float)PING_CACHE_TIME
)
510 victim
= r
; /* old record */
511 else if (++count
== max
|| r
->addr
.s_addr
== addr
.s_addr
)
514 if (icmp_ping(daemon
, addr
))
515 /* address in use: perturb address selection so that we are
516 less likely to try this address again. */
520 /* at this point victim may hold an expired record */
523 if ((victim
= malloc(sizeof(struct ping_result
))))
525 victim
->next
= daemon
->ping_results
;
526 daemon
->ping_results
= victim
;
530 /* record that this address is OK for 30s
531 without more ping checks */
541 addr
.s_addr
= htonl(ntohl(addr
.s_addr
) + 1);
543 if (addr
.s_addr
== htonl(ntohl(c
->end
.s_addr
) + 1))
546 } while (addr
.s_addr
!= start
.s_addr
);
551 static int is_addr_in_context(struct dhcp_context
*context
, struct dhcp_config
*config
)
553 if (!context
) /* called via find_config() from lease_update_from_configs() */
555 if (!(config
->flags
& CONFIG_ADDR
))
557 for (; context
; context
= context
->current
)
558 if (is_same_net(config
->addr
, context
->start
, context
->netmask
))
565 struct dhcp_config
*find_config(struct dhcp_config
*configs
,
566 struct dhcp_context
*context
,
567 unsigned char *clid
, int clid_len
,
568 unsigned char *hwaddr
, int hw_len
,
569 int hw_type
, char *hostname
)
571 struct dhcp_config
*config
;
574 for (config
= configs
; config
; config
= config
->next
)
575 if (config
->flags
& CONFIG_CLID
)
577 if (config
->clid_len
== clid_len
&&
578 memcmp(config
->clid
, clid
, clid_len
) == 0 &&
579 is_addr_in_context(context
, config
))
582 /* dhcpcd prefixes ASCII client IDs by zero which is wrong, but we try and
583 cope with that here */
584 if (*clid
== 0 && config
->clid_len
== clid_len
-1 &&
585 memcmp(config
->clid
, clid
+1, clid_len
-1) == 0 &&
586 is_addr_in_context(context
, config
))
591 for (config
= configs
; config
; config
= config
->next
)
592 if ((config
->flags
& CONFIG_HWADDR
) &&
593 config
->wildcard_mask
== 0 &&
594 config
->hwaddr_len
== hw_len
&&
595 (config
->hwaddr_type
== hw_type
|| config
->hwaddr_type
== 0) &&
596 memcmp(config
->hwaddr
, hwaddr
, hw_len
) == 0 &&
597 is_addr_in_context(context
, config
))
600 if (hostname
&& context
)
601 for (config
= configs
; config
; config
= config
->next
)
602 if ((config
->flags
& CONFIG_NAME
) &&
603 hostname_isequal(config
->hostname
, hostname
) &&
604 is_addr_in_context(context
, config
))
607 for (config
= configs
; config
; config
= config
->next
)
608 if ((config
->flags
& CONFIG_HWADDR
) &&
609 config
->wildcard_mask
!= 0 &&
610 config
->hwaddr_len
== hw_len
&&
611 (config
->hwaddr_type
== hw_type
|| config
->hwaddr_type
== 0) &&
612 is_addr_in_context(context
, config
) &&
613 memcmp_masked(config
->hwaddr
, hwaddr
, hw_len
, config
->wildcard_mask
))
619 void dhcp_read_ethers(struct daemon
*daemon
)
621 FILE *f
= fopen(ETHERSFILE
, "r");
623 char *buff
= daemon
->namebuff
;
626 unsigned char hwaddr
[ETHER_ADDR_LEN
];
627 struct dhcp_config
**up
, *tmp
;
628 struct dhcp_config
*config
, *configs
= daemon
->dhcp_conf
;
629 int count
= 0, lineno
= 0;
631 addr
.s_addr
= 0; /* eliminate warning */
635 syslog(LOG_ERR
, _("failed to read %s:%m"), ETHERSFILE
);
639 /* This can be called again on SIGHUP, so remove entries created last time round. */
640 for (up
= &daemon
->dhcp_conf
, config
= configs
; config
; config
= tmp
)
643 if (config
->flags
& CONFIG_FROM_ETHERS
)
646 /* cannot have a clid */
647 if (config
->flags
& CONFIG_NAME
)
648 free(config
->hostname
);
655 while (fgets(buff
, MAXDNAME
, f
))
659 while (strlen(buff
) > 0 && isspace(buff
[strlen(buff
)-1]))
660 buff
[strlen(buff
)-1] = 0;
662 if ((*buff
== '#') || (*buff
== '+'))
665 for (ip
= buff
; *ip
&& !isspace(*ip
); ip
++);
666 for(; *ip
&& isspace(*ip
); ip
++)
668 if (!*ip
|| parse_hex(buff
, hwaddr
, ETHER_ADDR_LEN
, NULL
, NULL
) != ETHER_ADDR_LEN
)
670 syslog(LOG_ERR
, _("bad line at %s line %d"), ETHERSFILE
, lineno
);
674 /* check for name or dotted-quad */
675 for (cp
= ip
; *cp
; cp
++)
676 if (!(*cp
== '.' || (*cp
>='0' && *cp
<= '9')))
681 if ((addr
.s_addr
= inet_addr(ip
)) == (in_addr_t
)-1)
683 syslog(LOG_ERR
, _("bad address at %s line %d"), ETHERSFILE
, lineno
);
689 for (config
= configs
; config
; config
= config
->next
)
690 if ((config
->flags
& CONFIG_ADDR
) && config
->addr
.s_addr
== addr
.s_addr
)
695 if (!canonicalise(ip
))
697 syslog(LOG_ERR
, _("bad name at %s line %d"), ETHERSFILE
, lineno
);
703 for (config
= configs
; config
; config
= config
->next
)
704 if ((config
->flags
& CONFIG_NAME
) && hostname_isequal(config
->hostname
, ip
))
710 for (config
= configs
; config
; config
= config
->next
)
711 if ((config
->flags
& CONFIG_HWADDR
) &&
712 config
->wildcard_mask
== 0 &&
713 config
->hwaddr_len
== ETHER_ADDR_LEN
&&
714 (config
->hwaddr_type
== ARPHRD_ETHER
|| config
->hwaddr_type
== 0) &&
715 memcmp(config
->hwaddr
, hwaddr
, ETHER_ADDR_LEN
) == 0)
720 if (!(config
= malloc(sizeof(struct dhcp_config
))))
722 config
->flags
= CONFIG_FROM_ETHERS
;
723 config
->wildcard_mask
= 0;
724 config
->next
= configs
;
728 config
->flags
|= flags
;
730 if (flags
& CONFIG_NAME
)
732 if ((config
->hostname
= malloc(strlen(ip
)+1)))
733 strcpy(config
->hostname
, ip
);
735 config
->flags
&= ~CONFIG_NAME
;
738 if (flags
& CONFIG_ADDR
)
742 config
->flags
|= CONFIG_HWADDR
| CONFIG_NOCLID
;
743 memcpy(config
->hwaddr
, hwaddr
, ETHER_ADDR_LEN
);
744 config
->hwaddr_len
= ETHER_ADDR_LEN
;
745 config
->hwaddr_type
= ARPHRD_ETHER
;
751 syslog(LOG_INFO
, _("read %s - %d addresses"), ETHERSFILE
, count
);
753 daemon
->dhcp_conf
= configs
;
756 void dhcp_update_configs(struct dhcp_config
*configs
)
758 /* Some people like to keep all static IP addresses in /etc/hosts.
759 This goes through /etc/hosts and sets static addresses for any DHCP config
760 records which don't have an address and whose name matches.
761 We take care to maintain the invariant that any IP address can appear
762 in at most one dhcp-host. Since /etc/hosts can be re-read by SIGHUP,
763 restore the status-quo ante first. */
765 struct dhcp_config
*config
;
768 for (config
= configs
; config
; config
= config
->next
)
769 if (config
->flags
& CONFIG_ADDR_HOSTS
)
770 config
->flags
&= ~(CONFIG_ADDR
| CONFIG_ADDR_HOSTS
);
772 for (config
= configs
; config
; config
= config
->next
)
773 if (!(config
->flags
& CONFIG_ADDR
) &&
774 (config
->flags
& CONFIG_NAME
) &&
775 (crec
= cache_find_by_name(NULL
, config
->hostname
, 0, F_IPV4
)) &&
776 (crec
->flags
& F_HOSTS
))
778 if (config_find_by_address(configs
, crec
->addr
.addr
.addr
.addr4
))
779 syslog(LOG_WARNING
, _("duplicate IP address %s (%s) in dhcp-config directive"),
780 inet_ntoa(crec
->addr
.addr
.addr
.addr4
), config
->hostname
);
783 config
->addr
= crec
->addr
.addr
.addr
.addr4
;
784 config
->flags
|= CONFIG_ADDR
| CONFIG_ADDR_HOSTS
;
789 /* If we've not found a hostname any other way, try and see if there's one in /etc/hosts
790 for this address. If it has a domain part, that must match the set domain and
792 char *host_from_dns(struct daemon
*daemon
, struct in_addr addr
)
794 struct crec
*lookup
= cache_find_by_addr(NULL
, (struct all_addr
*)&addr
, 0, F_IPV4
);
795 char *hostname
= NULL
;
797 if (lookup
&& (lookup
->flags
& F_HOSTS
))
799 hostname
= daemon
->dhcp_buff
;
800 strncpy(hostname
, cache_get_name(lookup
), 256);
802 hostname
= strip_hostname(daemon
, hostname
);
808 char *strip_hostname(struct daemon
*daemon
, char *hostname
)
810 char *dot
= strchr(hostname
, '.');
813 if (!daemon
->domain_suffix
|| !hostname_isequal(dot
+1, daemon
->domain_suffix
))
815 syslog(LOG_WARNING
, _("Ignoring DHCP host name %s because it has an illegal domain part"), hostname
);
820 *dot
= 0; /* truncate */
821 if (strlen(hostname
) == 0)
822 hostname
= NULL
; /* nothing left */