 |
ISC DHCP
4.4.2b1
A reference DHCPv4 and DHCPv6 implementation
|
|
Go to the documentation of this file.
32 #define IF_LINE_LENGTH 1024
35 #include <sys/ioctl.h>
109 log_fatal (
"Can't register interface object type: %s",
110 isc_result_totext (status));
115 #if defined (TRACING)
159 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFNUM) && defined(SIOCGLIFFLAGS)
164 #ifdef ISC_PLATFORM_HAVEIF_LADDRCONF
165 # define lifc_len iflc_len
166 # define lifc_buf iflc_buf
167 # define lifc_req iflc_req
168 # define LIFCONF if_laddrconf
170 # define ISC_HAVE_LIFC_FAMILY 1
171 # define ISC_HAVE_LIFC_FLAGS 1
172 # define LIFCONF lifconf
175 #ifdef ISC_PLATFORM_HAVEIF_LADDRREQ
176 # define lifr_addr iflr_addr
177 # define lifr_name iflr_name
178 # define lifr_dstaddr iflr_dstaddr
179 # define lifr_flags iflr_flags
180 # define sockaddr_storage sockaddr_ext
181 # define ss_family sa_family
182 # define LIFREQ if_laddrreq
184 # define LIFREQ lifreq
188 # if defined(LIFNAMSIZ)
189 # define IF_NAMESIZE LIFNAMSIZ
190 # elif defined(IFNAMSIZ)
191 # define IF_NAMESIZE IFNAMSIZ
193 # define IF_NAMESIZE 16
196 #elif !defined(__linux) && !defined(HAVE_IFADDRS_H)
197 # define SIOCGLIFCONF SIOCGIFCONF
198 # define SIOCGLIFFLAGS SIOCGIFFLAGS
199 # define LIFREQ ifreq
200 # define LIFCONF ifconf
201 # define lifr_name ifr_name
202 # define lifr_addr ifr_addr
203 # define lifr_flags ifr_flags
204 # define lifc_len ifc_len
205 # define lifc_buf ifc_buf
206 # define lifc_req ifc_req
208 # define ss_family __ss_family
212 #if defined(SIOCGLIFCONF) && defined(SIOCGLIFFLAGS)
249 #ifdef ISC_PLATFORM_HAVELIFNUM
250 struct lifnum lifnum;
256 if (ifaces->
sock < 0) {
257 log_error(
"Error creating socket to list interfaces; %m");
261 memset(&lifnum, 0,
sizeof(lifnum));
262 #ifdef ISC_PLATFORM_HAVELIFNUM
263 lifnum.lifn_family = AF_UNSPEC;
266 if (ioctl(ifaces->
sock, SIOCGLIFNUM, &lifnum) < 0) {
267 log_error(
"Error finding total number of interfaces; %m");
273 #ifdef ISC_PLATFORM_HAVELIFNUM
274 ifaces->
num = lifnum.lifn_count;
276 ifaces->
num = lifnum;
282 memset(&ifaces->
conf, 0,
sizeof(ifaces->
conf));
283 #ifdef ISC_HAVE_LIFC_FAMILY
284 ifaces->
conf.lifc_family = AF_UNSPEC;
288 if (ifaces->
conf.lifc_buf == NULL) {
289 log_fatal(
"Out of memory getting interface list.");
293 log_error(
"Error getting interfaces configuration list; %m");
316 #if defined(sun) || defined(__linux)
324 if (ifaces->
next >= ifaces->
num) {
329 p = ifaces->
conf.lifc_req;
332 if (strlen(p->lifr_name) >=
sizeof(info->
name)) {
334 log_error(
"Interface name '%s' too long", p->lifr_name);
345 strncpy(info->
name, p->lifr_name,
sizeof(info->
name) - 1);
346 memcpy(&info->
addr, &p->lifr_addr,
sizeof(p->lifr_addr));
348 #if defined(sun) || defined(__linux)
350 s = strchr(info->
name,
':');
358 (strncmp(info->
name,
"dummy", 5) == 0));
360 memset(&tmp, 0,
sizeof(tmp));
361 strncpy(tmp.lifr_name, info->
name,
sizeof(tmp.lifr_name) - 1);
363 log_error(
"Error getting interface flags for '%s'; %m",
368 info->
flags = tmp.lifr_flags;
403 struct ifaddrs *head;
404 struct ifaddrs *
next;
412 struct sockaddr_storage
addr;
423 if (getifaddrs(&ifaces->head) != 0) {
424 log_error(
"Error getting interfaces; %m");
427 ifaces->
next = ifaces->head;
441 if (ifaces->
next == NULL) {
445 if (strlen(ifaces->
next->ifa_name) >=
sizeof(info->
name)) {
446 log_error(
"Interface name '%s' too long",
447 ifaces->
next->ifa_name);
452 strncpy(info->
name, ifaces->
next->ifa_name,
sizeof(info->
name) - 1);
453 memset(&info->
addr, 0 ,
sizeof(info->
addr));
458 if (ifaces->
next->ifa_addr != NULL) {
461 if (ifaces->
next->ifa_addr->sa_family == AF_INET)
462 sa_len =
sizeof(
struct sockaddr_in);
463 else if (ifaces->
next->ifa_addr->sa_family == AF_INET6)
464 sa_len =
sizeof(
struct sockaddr_in6);
466 sa_len = ifaces->
next->ifa_addr->sa_len;
468 memcpy(&info->
addr, ifaces->
next->ifa_addr, sa_len);
471 ifaces->
next = ifaces->
next->ifa_next;
481 freeifaddrs(ifaces->head);
490 const struct in_addr *addr) {
498 log_fatal(
"Out of memory saving IPv4 address "
508 tmp =
dmalloc(new_max *
sizeof(
struct in_addr),
MDL);
510 log_fatal(
"Out of memory saving IPv4 address "
527 const struct in6_addr *addr) {
536 log_fatal(
"Out of memory saving IPv6 address "
542 struct in6_addr *tmp;
546 tmp =
dmalloc(new_max *
sizeof(
struct in6_addr),
MDL);
548 log_fatal(
"Out of memory saving IPv6 address "
577 char abuf[
sizeof(
"ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")];
593 log_fatal(
"Can't get list of interfaces.");
627 !(info.
flags & IFF_BROADCAST)) ||
630 !(info.
flags & IFF_MULTICAST)) ||
632 info.
flags & IFF_LOOPBACK ||
633 info.
flags & IFF_POINTOPOINT) && !tmp) ||
634 (!(info.
flags & IFF_UP) &&
641 status = interface_allocate(&tmp,
MDL);
643 log_fatal(
"Error allocating interface %s: %s",
644 info.
name, isc_result_totext(status));
650 interface_dereference(&tmp,
MDL);
657 (*dhcp_interface_discovery_hook)(tmp);
660 if ((info.
addr.ss_family == AF_INET) &&
662 struct sockaddr_in *a = (
struct sockaddr_in*)&info.
addr;
666 if (a->sin_addr.s_addr == htonl(INADDR_LOOPBACK) &&
674 if (a->sin_addr.s_addr != htonl(INADDR_ANY))
681 memcpy(addr.iabuf, &a->sin_addr.s_addr, addr.len);
683 (*dhcp_interface_setup_hook)(tmp, &addr);
687 else if ((info.
addr.ss_family == AF_INET6) &&
689 struct sockaddr_in6 *a =
690 (
struct sockaddr_in6*)&info.
addr;
694 if (IN6_IS_ADDR_LOOPBACK(&a->sin6_addr) &&
702 if (IN6_IS_ADDR_UNSPECIFIED(&a->sin6_addr))
705 add_ipv6_addr_to_interface(tmp, &a->sin6_addr);
709 memcpy(addr.iabuf, &a->sin6_addr, addr.len);
711 (*dhcp_interface_setup_hook)(tmp, &addr);
718 log_fatal(
"Error getting interface information.");
729 if (tmp->
ifp == NULL) {
732 tif = (
struct ifreq *)
dmalloc(
sizeof(
struct ifreq),
736 strcpy(tif->ifr_name, tmp->
name);
749 tmp = last = next = NULL;
754 interface_dereference (&next,
MDL);
756 interface_reference (&next, tmp -> next,
MDL);
759 interface_dereference(&tmp,
MDL);
761 interface_reference(&tmp, next,
MDL);
775 log_fatal (
"%s: not found", tmp -> name);
783 interface_dereference (&last -> next,
MDL);
785 interface_reference (&last -> next,
789 interface_dereference (&tmp -> next,
MDL);
794 interface_reference (&tmp -> next,
799 interface_dereference (&tmp,
MDL);
801 interface_reference (&tmp, next,
MDL);
810 log_info(
"No subnet declaration for %s (%s).",
813 "no IPv4 addresses" :
823 strcpy(abuf,
"no IPv6 addresses");
825 log_info(
"No subnet6 declaration for %s (%s).",
831 log_info (
"** Ignoring requests on %s. %s",
832 tmp -> name,
"If this is not what");
833 log_info (
" you want, please write %s",
836 "a subnet6 declaration" :
838 "a subnet declaration");
839 log_info (
" in your dhcpd.conf file %s",
840 "for the network segment");
843 tmp -> name,
"is attached. **");
850 "subnet6 declaration for this" :
852 "subnet declaration for this");
853 log_error (
"subnet. You cannot prevent %s",
855 log_error (
"from listening on this subnet %s",
857 log_fatal (
"operating system does not %s.",
858 "support this capability");
883 "address", tmp->
name);
924 #if defined (F_SETFD)
927 if ((tmp -> rfdesc >= 0) &&
928 (fcntl (tmp -> rfdesc, F_SETFD, 1) < 0))
929 log_error (
"Can't set close-on-exec on %s: %m",
931 if ((tmp -> wfdesc != tmp -> rfdesc) &&
932 (tmp -> wfdesc >= 0) &&
933 (fcntl (tmp -> wfdesc, F_SETFD, 1) < 0))
934 log_error (
"Can't set close-on-exec on %s: %m",
938 interface_dereference (&tmp,
MDL);
940 interface_reference (&tmp, next,
MDL);
949 for (tmp =
interfaces; tmp; tmp = tmp -> next) {
953 if (tmp -> rfdesc == -1)
959 #define UPSTREAM(ifp) \
960 ((ifp->flags & INTERFACE_STREAMS) == INTERFACE_UPSTREAM)
961 #define DOWNSTREAM(ifp) \
962 ((ifp->flags & INTERFACE_STREAMS) == INTERFACE_DOWNSTREAM)
976 if (updone && UPSTREAM(tmp))
978 if (downdone && DOWNSTREAM(tmp))
1002 log_fatal (
"Can't register I/O handle for %s: %s",
1003 tmp -> name, isc_result_totext (status));
1014 #
if defined(RELAY_PORT)
1015 && ((
relay_port == 0) || (updone && downdone))
1024 log_fatal (
"Not configured to listen on any interfaces!");
1033 #if defined (F_SETFD)
1036 log_error (
"Can't set close-on-exec on fallback: %m");
1039 log_error (
"Can't set close-on-exec on fallback: %m");
1058 isc_result_t status;
1062 log_fatal (
"Error allocating fallback interface: %s",
1063 isc_result_totext (status));
1093 struct sockaddr_in from;
1098 unsigned char packbuf [4095];
1113 return ISC_R_UNEXPECTED;
1116 return ISC_R_UNEXPECTED;
1128 return ISC_R_UNEXPECTED;
1130 #if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO)
1133 unsigned int ifindex;
1135 memcpy(&ifindex, hfrom.
hbuf, sizeof (ifindex));
1142 while ((
ip != NULL) && (if_nametoindex(
ip->name) != ifindex))
1145 return ISC_R_NOTFOUND;
1151 memcpy (ifrom.
iabuf, &from.sin_addr, ifrom.
len);
1153 (*bootp_packet_handler) (
ip, &u.packet, (unsigned)result,
1154 from.sin_port, ifrom, &hfrom);
1167 struct sockaddr_in6 from;
1174 unsigned int if_idx = 0;
1182 &from, &to, &if_idx);
1184 log_error(
"receive_packet6() failed on %s: %m",
ip->name);
1185 return ISC_R_UNEXPECTED;
1190 return ISC_R_NOTFOUND;
1196 if (IN6_IS_ADDR_MULTICAST(&to)) {
1203 memcpy(ifrom.iabuf, &from.sin6_addr, ifrom.len);
1207 while ((
ip != NULL) && (if_nametoindex(
ip->name) != if_idx))
1211 return ISC_R_NOTFOUND;
1213 (*dhcpv6_packet_handler)(
ip, buf,
1214 result, from.sin6_port,
1215 &ifrom, is_unicast);
1228 isc_result_t status;
1237 value -> u.buffer.len <
sizeof interface -> name) {
1238 memcpy (interface -> name,
1239 value -> u.buffer.value,
1240 value -> u.buffer.len);
1248 if (h -> inner && h -> inner -> type -> set_value) {
1249 status = ((*(h -> inner -> type -> set_value))
1250 (h -> inner, id, name,
value));
1255 return ISC_R_NOTFOUND;
1276 if (interface -> ifp) {
1278 interface -> ifp = 0;
1280 if (interface -> next)
1281 interface_dereference (&interface -> next,
file,
line);
1282 if (interface -> rbuf) {
1284 interface -> rbuf = (
unsigned char *)0;
1286 if (interface -> client)
1297 const char *
name, va_list ap)
1300 isc_result_t status;
1308 if (!strcmp (name,
"update")) {
1310 if (
ip == interface)
1316 if (
ip == interface)
1323 if (h -> inner && h -> inner -> type -> signal_handler) {
1324 status = ((*(h -> inner -> type -> signal_handler))
1325 (h -> inner, name, ap));
1329 return ISC_R_NOTFOUND;
1337 isc_result_t status;
1356 if (h -> inner && h -> inner -> type -> stuff_values) {
1357 status = ((*(h -> inner -> type -> stuff_values))
1358 (c, id, h -> inner));
1371 isc_result_t status;
1399 interface = interface -> next) {
1400 s = memchr (interface -> name, 0, IFNAMSIZ);
1402 len = s - &
interface -> name [0];
1405 if ((tv ->
value -> u.buffer.len == len &&
1406 !memcmp (interface -> name,
1407 (
char *)tv ->
value -> u.buffer.value,
1413 interface;
interface = interface -> next) {
1414 s = memchr (interface -> name, 0, IFNAMSIZ);
1416 len = s - &
interface -> name [0];
1419 if ((tv ->
value -> u.buffer.len == len &&
1420 !memcmp (interface -> name,
1422 tv ->
value -> u.buffer.value,
1432 }
else if (!interface) {
1435 return ISC_R_NOTFOUND;
1454 isc_result_t status;
1457 status = interface_allocate (&hp,
MDL);
1462 interface_dereference (&hp,
MDL);
1476 if (
ip == interface) {
1478 interface_dereference (&last -> next,
MDL);
1480 interface_reference (&last -> next,
1489 interface_dereference (&
ip -> next,
MDL);
1495 return ISC_R_NOTFOUND;
1499 interface_reference (&interface -> next,
1507 (*dhcp_interface_shutdown_hook) (interface);
1534 if (tptr ->
index == -1) {
1541 if (interface_max <= tptr ->
index) {
1546 log_error (
"interface_stash: allocation failed ");
1566 #if defined (TRACING)
1579 interface_reference (&tmp ->
next,
struct interface_info * interfaces
#define OMAPI_OBJECT_ALLOC(name, stype, type)
isc_result_t omapi_object_reference(omapi_object_t **, omapi_object_t *, const char *, int)
struct in_addr local_address
void interface_stash(struct interface_info *tptr)
void trace_outpacket_stop(trace_type_t *)
void log_fatal(const char *,...) __attribute__((__format__(__printf__
omapi_object_type_t * dhcp_type_interface
struct in6_addr local_address6
int interfaces_invalidated
void if_register_receive(struct interface_info *)
void trace_interface_register(trace_type_t *, struct interface_info *)
isc_result_t(* dhcp_interface_startup_hook)(struct interface_info *)
struct in_addr limited_broadcast
isc_result_t omapi_connection_put_name(omapi_object_t *, const char *)
isc_result_t dhcp_interface_lookup(omapi_object_t **ip, omapi_object_t *id, omapi_object_t *ref)
void if_deregister6(struct interface_info *info)
trace_type_t * outpacket_trace
trace_type_t * trace_type_register(const char *, void *, void(*)(trace_type_t *, unsigned, char *), void(*)(trace_type_t *), const char *, int)
isc_result_t omapi_register_io_object(omapi_object_t *, int(*)(omapi_object_t *), int(*)(omapi_object_t *), isc_result_t(*)(omapi_object_t *), isc_result_t(*)(omapi_object_t *), isc_result_t(*)(omapi_object_t *))
void trace_interface_stop(trace_type_t *)
int(* dhcp_interface_setup_hook)(struct interface_info *, struct iaddr *)
#define DISCOVER_UNCONFIGURED
void trace_outpacket_input(trace_type_t *, unsigned, char *)
isc_result_t dhcp_interface_destroy(omapi_object_t *h, const char *file, int line)
trace_type_t * interface_trace
int if_readsocket(omapi_object_t *h)
isc_result_t interface_initialize(omapi_object_t *ipo, const char *file, int line)
void if_register_linklocal6(struct interface_info *info)
#define DHCP_FIXED_NON_UDP
void if_register_send(struct interface_info *)
void trace_inpacket_stop(trace_type_t *)
#define DISCOVER_SERVER46
int supports_multiple_interfaces(struct interface_info *)
int(* dhcp_interface_discovery_hook)(struct interface_info *)
void reinitialize_interfaces()
void if_deregister_receive(struct interface_info *)
int(* dhcp_interface_shutdown_hook)(struct interface_info *)
isc_result_t dhcp_interface_set_value(omapi_object_t *h, omapi_object_t *id, omapi_data_string_t *name, omapi_typed_data_t *value)
void if_reinitialize_receive(struct interface_info *)
void add_ipv4_addr_to_interface(struct interface_info *iface, const struct in_addr *addr)
#define INTERFACE_REQUESTED
int int log_info(const char *,...) __attribute__((__format__(__printf__
void discover_interfaces(int state)
#define INTERFACE_STREAMS
void interface_snorf(struct interface_info *tmp, int ir)
isc_result_t omapi_object_dereference(omapi_object_t **, const char *, int)
ssize_t receive_packet6(struct interface_info *interface, unsigned char *buf, size_t len, struct sockaddr_in6 *from, struct in6_addr *to_addr, unsigned int *if_index)
struct interface_info * next
void dfree(void *, const char *, int)
isc_result_t dhcp_interface_get_value(omapi_object_t *h, omapi_object_t *id, omapi_data_string_t *name, omapi_value_t **value)
#define INTERFACE_AUTOMATIC
ssize_t receive_packet(struct interface_info *, unsigned char *, size_t, struct sockaddr_in *, struct hardware *)
#define INTERFACE_RUNNING
int next_iface(struct iface_info *info, int *err, struct iface_conf_list *ifaces)
int log_error(const char *,...) __attribute__((__format__(__printf__
void if_register6(struct interface_info *info, int do_multicast)
int omapi_ds_strcmp(omapi_data_string_t *, const char *)
void interface_trace_setup(void)
isc_result_t omapi_value_dereference(omapi_value_t **, const char *, int)
void end_iface_scan(struct iface_conf_list *ifaces)
isc_result_t omapi_object_type_register(omapi_object_type_t **, const char *, isc_result_t(*)(omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *), isc_result_t(*)(omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **), isc_result_t(*)(omapi_object_t *, const char *, int), isc_result_t(*)(omapi_object_t *, const char *, va_list), isc_result_t(*)(omapi_object_t *, omapi_object_t *, omapi_object_t *), isc_result_t(*)(omapi_object_t **, omapi_object_t *, omapi_object_t *), isc_result_t(*)(omapi_object_t **, omapi_object_t *), isc_result_t(*)(omapi_object_t *, omapi_object_t *), isc_result_t(*)(omapi_object_t *, const char *, int), isc_result_t(*)(omapi_object_t **, const char *, int), isc_result_t(*)(size_t), size_t, isc_result_t(*)(omapi_object_t *, const char *, int), int)
void trace_interface_input(trace_type_t *, unsigned, char *)
#define DISCOVER_REQUESTED
void(* bootp_packet_handler)(struct interface_info *, struct dhcp_packet *, unsigned, unsigned int, struct iaddr, struct hardware *)
int setup_fallback(struct interface_info **fp, const char *file, int line)
void maybe_setup_fallback(void)
void(* dhcpv6_packet_handler)(struct interface_info *, const char *, int, int, const struct iaddr *, isc_boolean_t)
isc_result_t omapi_connection_put_string(omapi_object_t *, const char *)
isc_result_t dhcp_interface_remove(omapi_object_t *lp, omapi_object_t *id)
trace_type_t * inpacket_trace
struct interface_info ** interface_vector
u_int8_t hbuf[HARDWARE_ADDR_LEN+1]
void trace_inpacket_input(trace_type_t *, unsigned, char *)
void get_hw_addr(struct interface_info *info)
struct in6_addr * v6addresses
struct interface_info * interface
int begin_iface_scan(struct iface_conf_list *ifaces)
void * dmalloc(size_t, const char *, int)
struct sockaddr_storage addr
struct shared_network * shared_network
int quiet_interface_discovery
#define ISC_R_NOTIMPLEMENTED
isc_result_t omapi_get_value_str(omapi_object_t *, omapi_object_t *, const char *, omapi_value_t **)
void if_reinitialize_send(struct interface_info *)
struct iaddr interface_address
isc_result_t got_one_v6(omapi_object_t *)
isc_result_t omapi_handle_td_lookup(omapi_object_t **, omapi_typed_data_t *)
isc_result_t dhcp_interface_signal_handler(omapi_object_t *h, const char *name, va_list ap)
void try_hw_addr(struct interface_info *info)
#define DHCP_R_INVALIDARG
void if_deregister_send(struct interface_info *)
struct interface_info * dummy_interfaces
isc_result_t dhcp_interface_create(omapi_object_t **lp, omapi_object_t *id)
isc_result_t interface_setup()
isc_result_t got_one(omapi_object_t *h)
#define DHCP_R_KEYCONFLICT
struct interface_info * fallback_interface
isc_result_t omapi_unregister_io_object(omapi_object_t *)
struct in_addr * addresses
isc_result_t dhcp_interface_stuff_values(omapi_object_t *c, omapi_object_t *id, omapi_object_t *h)