44#if defined(sun) && defined(USE_V4_PKTINFO)
45#include <sys/sysmacros.h>
47#include <sys/sockio.h>
52#ifdef USE_SOCKET_FALLBACK
53# if !defined (USE_SOCKET_SEND)
54# define if_register_send if_register_fallback
55# define send_packet send_fallback
56# define if_reinitialize_send if_reinitialize_fallback
65static int no_global_v6_socket = 0;
66static unsigned int global_v6_socket_references = 0;
67static int global_v6_socket = -1;
68#if defined(RELAY_PORT)
69static unsigned int relay_port_v6_socket_references = 0;
70static int relay_port_v6_socket = -1;
81#if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO)
82static unsigned int global_v4_socket_references = 0;
83static int global_v4_socket = -1;
91#if !defined(SO_BINDTODEVICE) && !defined(USE_FALLBACK)
98#if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_FALLBACK)
103#ifndef USE_SOCKET_RECEIVE
112#ifdef USE_SOCKET_RECEIVE
124#if defined (USE_SOCKET_SEND) || \
125 defined (USE_SOCKET_RECEIVE) || \
126 defined (USE_SOCKET_FALLBACK)
130 int *do_multicast,
struct in6_addr *linklocal6)
132 struct sockaddr_storage name;
138 struct sockaddr_in6 *addr6;
140 struct sockaddr_in *addr;
144#if !defined(SO_BINDTODEVICE) && !defined(USE_FALLBACK)
147 log_fatal (
"The standard socket API can only support %s",
148 "hosts with a single network interface.");
157 memset(&name, 0,
sizeof(name));
161 addr6 = (
struct sockaddr_in6 *)&name;
162 addr6->sin6_family = AF_INET6;
164#if defined(RELAY_PORT)
171 memcpy(&addr6->sin6_addr,
173 sizeof(addr6->sin6_addr));
177 memcpy(&addr6->sin6_addr,
179 sizeof(addr6->sin6_addr));
181 if (IN6_IS_ADDR_LINKLOCAL(&addr6->sin6_addr)) {
182 addr6->sin6_scope_id = if_nametoindex(info->
name);
185 addr6->sin6_len =
sizeof(*addr6);
187 name_len =
sizeof(*addr6);
197 addr = (
struct sockaddr_in *)&name;
198 addr->sin_family = AF_INET;
200 memcpy(&addr->sin_addr,
202 sizeof(addr->sin_addr));
204 addr->sin_len =
sizeof(*addr);
206 name_len =
sizeof(*addr);
212 sock = socket(domain, SOCK_DGRAM, IPPROTO_UDP);
214 log_fatal(
"Can't create dhcp socket for %s: %m", info->
name);
220 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
221 (
char *)&flag,
sizeof(flag)) < 0) {
222 log_fatal(
"Can't set SO_REUSEADDR on dhcp socket for"
223 " %s: %m", info->
name);
230 (setsockopt(sock, SOL_SOCKET, SO_BROADCAST,
231 (
char *)&flag,
sizeof(flag)) < 0)) {
232 log_fatal(
"Can't set SO_BROADCAST on dhcp socket for"
233 " %s: %m", info->
name);
236#if defined(DHCPv6) && defined(SO_REUSEPORT)
248 if ((setsockopt(sock, SOL_SOCKET, SO_REUSEPORT,
249 (
char *)&flag,
sizeof(flag)) < 0) &&
250 (errno != ENOPROTOOPT)) {
251 log_fatal(
"Can't set SO_REUSEPORT on dhcp socket for"
252 " %s: %m", info->
name);
258 if (bind(sock, (
struct sockaddr *)&name, name_len) < 0) {
259 log_error(
"Can't bind to dhcp address: %m");
260 log_error(
"Please make sure there is no other dhcp server");
261 log_error(
"running and that there's no entry for dhcp or");
262 log_error(
"bootp in /etc/inetd.conf. Also make sure you");
263 log_error(
"are not running HP JetAdmin software, which");
267#if defined(SO_BINDTODEVICE)
270 setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE,
271 (
char *)(info -> ifp),
sizeof(*(info -> ifp))) < 0) {
272 log_fatal(
"Can't set SO_BINDTODEVICE on dhcp socket for"
273 " %s : %m", (
char *)(info->
ifp));
284#if defined(SCO) && defined(IP_BROADCAST_IF)
286 setsockopt(sock, IPPROTO_IP, IP_BROADCAST_IF, &info->
addresses[0],
288 log_fatal(
"Can't set IP_BROADCAST_IF on dhcp socket for"
289 " %s: %m", info->
name);
292#if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO)
297 if (family == AF_INET) {
299 if (setsockopt(sock, IPPROTO_IP, IP_RECVPKTINFO,
300 &on,
sizeof(on)) != 0) {
301 log_fatal(
"Can't set IP_RECVPTKINFO on dhcp socket for"
302 " %s: %m", info->
name);
313 if (family == AF_INET6) {
315#ifdef IPV6_RECVPKTINFO
317 if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO,
318 &on,
sizeof(on)) != 0) {
319 log_fatal(
"setsockopt: IPV6_RECVPKTINFO for %s: %m",
324 if (setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO,
325 &on,
sizeof(on)) != 0) {
326 log_fatal(
"setsockopt: IPV6_PKTINFO for %s: %m",
339 if (setsockopt(info->
wfdesc, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
340 &hop_limit,
sizeof(
int)) < 0) {
341 log_fatal(
"setsockopt: IPV6_MULTICAST_HOPS for %s: %m",
345 log_debug(
"Setting hop count limit to %d for interface %s",
346 hop_limit, info->
name);
353#if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_FALLBACK)
357#ifndef USE_SOCKET_RECEIVE
360 if (strcmp(info->
name,
"fallback") != 0)
362#if defined (USE_SOCKET_FALLBACK)
371 log_info (
"Sending on Socket/%s%s%s",
378#if defined (USE_SOCKET_SEND)
382#ifndef USE_SOCKET_RECEIVE
388 log_info (
"Disabling output on Socket/%s%s%s",
397#ifdef USE_SOCKET_RECEIVE
402#if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO)
403 if (global_v4_socket_references == 0) {
405 if (global_v4_socket < 0) {
410 log_fatal(
"Failed to create AF_INET socket %s:%d",
415 info->
rfdesc = global_v4_socket;
416 global_v4_socket_references++;
423 if (strcmp(info->
name,
"fallback") != 0)
427 log_info (
"Listening on Socket/%s%s%s",
437#if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO)
439 if ((info->
rfdesc == global_v4_socket) &&
440 (global_v4_socket_references > 0)) {
441 global_v4_socket_references--;
447 if (global_v4_socket_references == 0) {
448 close(global_v4_socket);
449 global_v4_socket = -1;
456 log_info (
"Disabling input on Socket/%s%s%s",
473 struct ipv6_mreq mreq;
476 &mreq.ipv6mr_multiaddr) <= 0) {
477 log_fatal(
"inet_pton: unable to convert '%s'",
480 mreq.ipv6mr_interface = if_nametoindex(info->
name);
481 if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
482 &mreq,
sizeof(mreq)) < 0) {
483 log_fatal(
"setsockopt: IPV6_JOIN_GROUP for %s: %m",
496 &mreq.ipv6mr_multiaddr) <= 0) {
497 log_fatal(
"inet_pton: unable to convert '%s'",
500 mreq.ipv6mr_interface = if_nametoindex(info->
name);
501 if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
502 &mreq,
sizeof(mreq)) < 0) {
503 log_fatal(
"setsockopt: IPV6_JOIN_GROUP for %s: %m",
512 int req_multi = do_multicast;
514 if (no_global_v6_socket) {
518#if defined(RELAY_PORT)
522 if (global_v6_socket_references == 0) {
525 if (global_v6_socket < 0) {
532 char addr6_str[INET6_ADDRSTRLEN];
534 if (inet_ntop(AF_INET6,
537 sizeof(addr6_str)) == NULL) {
538 log_fatal(
"inet_ntop: unable to convert "
549 info->
rfdesc = global_v6_socket;
550 info->
wfdesc = global_v6_socket;
551 global_v6_socket_references++;
553#if defined(RELAY_PORT)
560 if ((relay_port_v6_socket_references == 0) &&
564 if (relay_port_v6_socket < 0) {
567 log_info(
"Bound to relay port *:%d",
571 info->
rfdesc = relay_port_v6_socket;
572 info->
wfdesc = relay_port_v6_socket;
573 relay_port_v6_socket_references++;
578 if_register_multicast(info);
584 log_info(
"Listening on Socket/%d/%s/%s",
585 global_v6_socket, info->
name,
587 log_info(
"Sending on Socket/%d/%s/%s",
588 global_v6_socket, info->
name,
607 struct in6_addr *addr6 = NULL;
610 if (global_v6_socket >= 0) {
614 no_global_v6_socket = 1;
619 if (IN6_IS_ADDR_LINKLOCAL(addr6))
640 log_info(
"Listening on Socket/%d/%s/%s",
641 global_v6_socket, info->
name,
643 log_info(
"Sending on Socket/%d/%s/%s",
644 global_v6_socket, info->
name,
656 if (no_global_v6_socket) {
660 }
else if ((info->
rfdesc == global_v6_socket) &&
661 (info->
wfdesc == global_v6_socket) &&
662 (global_v6_socket_references > 0)) {
664 global_v6_socket_references--;
667#if defined(RELAY_PORT)
669 (info->
rfdesc == relay_port_v6_socket) &&
670 (info->
wfdesc == relay_port_v6_socket) &&
671 (relay_port_v6_socket_references > 0)) {
673 relay_port_v6_socket_references--;
685 log_info(
"Disabling output on Socket/%s/%s", info->
name,
693 if (!no_global_v6_socket) {
694 if (global_v6_socket_references == 0) {
695 close(global_v6_socket);
696 global_v6_socket = -1;
701#if defined(RELAY_PORT)
702 if (
relay_port && (relay_port_v6_socket_references == 0)) {
703 close(relay_port_v6_socket);
704 relay_port_v6_socket = -1;
706 log_info(
"Unbound from relay port *:%d",
714#if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_FALLBACK)
721 struct sockaddr_in *to;
725#ifdef IGNORE_HOSTUNREACH
729#if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO)
730 struct in_pktinfo pktinfo;
732 if (interface->
ifp != NULL) {
733 memset(&pktinfo, 0,
sizeof (pktinfo));
734 pktinfo.ipi_ifindex = interface->
ifp->ifr_index;
735 if (setsockopt(interface->
wfdesc, IPPROTO_IP,
736 IP_PKTINFO, (
char *)&pktinfo,
737 sizeof(pktinfo)) < 0)
738 log_fatal(
"setsockopt: IP_PKTINFO for %s: %m",
739 (
char*)(interface->
ifp));
742 result = sendto (interface -> wfdesc, (
char *)raw, len, 0,
743 (
struct sockaddr *)to,
sizeof *to);
744#ifdef IGNORE_HOSTUNREACH
745 }
while (to -> sin_addr.s_addr == htonl (INADDR_BROADCAST) &&
747 (errno == EHOSTUNREACH ||
748 errno == ECONNREFUSED) &&
753 if (errno == ENETUNREACH)
754 log_error (
"send_packet: please consult README file%s",
755 " regarding broadcast address.");
769static size_t CMSG_LEN(
size_t len) {
775 hdrlen = (size_t)CMSG_DATA(((
struct cmsghdr *)NULL));
781static size_t CMSG_SPACE(
size_t len) {
783 struct cmsghdr *cmsgp;
790 struct cmsghdr cmsg_sizer;
791 u_int8_t pktinfo_sizer[
sizeof(
struct cmsghdr) + 1024];
794 memset(&msg, 0,
sizeof(msg));
795 msg.msg_control = &dummybuf;
796 msg.msg_controllen =
sizeof(dummybuf);
798 cmsgp = (
struct cmsghdr *)&dummybuf;
799 cmsgp->cmsg_len = CMSG_LEN(len);
801 cmsgp = CMSG_NXTHDR(&msg, cmsgp);
803 return (
char *)cmsgp - (
char *)msg.msg_control;
812#if defined(DHCPv6) || \
813 (defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && \
814 defined(USE_V4_PKTINFO))
822static void *control_buf = NULL;
823static size_t control_buf_len = 0;
826allocate_cmsg_cbuf(
void) {
827 control_buf_len = CMSG_SPACE(
sizeof(
struct in6_pktinfo));
854 const unsigned char *raw,
size_t len,
855 struct sockaddr_in6 *to) {
858 struct sockaddr_in6 dst;
860 struct in6_pktinfo *pktinfo;
861 struct cmsghdr *cmsg;
862 unsigned int ifindex;
869 if (control_buf == NULL) {
870 allocate_cmsg_cbuf();
871 if (control_buf == NULL) {
872 log_error(
"send_packet6: unable to allocate cmsg header");
876 memset(control_buf, 0, control_buf_len);
881 memset(&m, 0,
sizeof(m));
887 memcpy(&dst, to,
sizeof(dst));
889 m.msg_namelen =
sizeof(dst);
890 ifindex = if_nametoindex(interface->
name);
896 if (no_global_v6_socket)
898 dst.sin6_scope_id = ifindex;
905 v.iov_base = (
char *)raw;
918 m.msg_control = control_buf;
919 m.msg_controllen = control_buf_len;
920 cmsg = CMSG_FIRSTHDR(&m);
921 INSIST(cmsg != NULL);
922 cmsg->cmsg_level = IPPROTO_IPV6;
923 cmsg->cmsg_type = IPV6_PKTINFO;
924 cmsg->cmsg_len = CMSG_LEN(
sizeof(*pktinfo));
925 pktinfo = (
struct in6_pktinfo *)CMSG_DATA(cmsg);
926 memset(pktinfo, 0,
sizeof(*pktinfo));
928 pktinfo->ipi6_ifindex = ifindex;
930 result = sendmsg(interface->
wfdesc, &m, 0);
938#ifdef USE_SOCKET_RECEIVE
943 struct sockaddr_in *from;
946#if !(defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO))
956 memset(hfrom, 0,
sizeof(*hfrom));
958#ifdef IGNORE_HOSTUNREACH
963#if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO)
966 struct cmsghdr *cmsg;
967 struct in_pktinfo *pktinfo;
968 unsigned int ifindex;
974 if (control_buf == NULL) {
975 allocate_cmsg_cbuf();
976 if (control_buf == NULL) {
977 log_error(
"receive_packet: unable to allocate cmsg "
982 memset(control_buf, 0, control_buf_len);
987 memset(&m, 0,
sizeof(m));
993 m.msg_namelen =
sizeof(*from);
1013 m.msg_control = control_buf;
1014 m.msg_controllen = control_buf_len;
1016 result = recvmsg(interface->
rfdesc, &m, 0);
1024 cmsg = CMSG_FIRSTHDR(&m);
1025 while (cmsg != NULL) {
1026 if ((cmsg->cmsg_level == IPPROTO_IP) &&
1027 (cmsg->cmsg_type == IP_PKTINFO)) {
1028 pktinfo = (
struct in_pktinfo *)CMSG_DATA(cmsg);
1029 ifindex = pktinfo->ipi_ifindex;
1036 memcpy(hfrom->
hbuf, &ifindex,
sizeof(ifindex));
1039 cmsg = CMSG_NXTHDR(&m, cmsg);
1050 result = recvfrom(interface -> rfdesc, (
char *)buf, len, 0,
1051 (
struct sockaddr *)from, &flen);
1053#ifdef IGNORE_HOSTUNREACH
1054 }
while (result < 0 &&
1055 (errno == EHOSTUNREACH ||
1056 errno == ECONNREFUSED) &&
1067 unsigned char *buf,
size_t len,
1068 struct sockaddr_in6 *from,
struct in6_addr *to_addr,
1069 unsigned int *if_idx)
1074 struct cmsghdr *cmsg;
1075 struct in6_pktinfo *pktinfo;
1081 if (control_buf == NULL) {
1082 allocate_cmsg_cbuf();
1083 if (control_buf == NULL) {
1084 log_error(
"receive_packet6: unable to allocate cmsg "
1089 memset(control_buf, 0, control_buf_len);
1094 memset(&m, 0,
sizeof(m));
1100 m.msg_namelen =
sizeof(*from);
1120 m.msg_control = control_buf;
1121 m.msg_controllen = control_buf_len;
1123 result = recvmsg(interface->
rfdesc, &m, 0);
1131 cmsg = CMSG_FIRSTHDR(&m);
1132 while (cmsg != NULL) {
1133 if ((cmsg->cmsg_level == IPPROTO_IPV6) &&
1134 (cmsg->cmsg_type == IPV6_PKTINFO)) {
1135 pktinfo = (
struct in6_pktinfo *)CMSG_DATA(cmsg);
1136 *to_addr = pktinfo->ipi6_addr;
1137 *if_idx = pktinfo->ipi6_ifindex;
1141 cmsg = CMSG_NXTHDR(&m, cmsg);
1156#if defined (USE_SOCKET_FALLBACK)
1163 struct sockaddr_in from;
1172 status = recvfrom (interface -> wfdesc, buf,
sizeof buf, 0,
1173 (
struct sockaddr *)&from, &flen);
1178 return ISC_R_UNEXPECTED;
1188#if defined (USE_SOCKET_SEND)
1198#if defined (SOCKET_CAN_RECEIVE_UNICAST_UNCONFIGURED)
1208#if defined(SO_BINDTODEVICE) || \
1209 (defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && \
1210 defined(USE_V4_PKTINFO))
1222#if defined (USE_SOCKET_FALLBACK)
1223 isc_result_t status;
1228 log_info (
"Sending on Socket/%s%s%s",
1238 log_fatal (
"Can't register I/O handle for %s: %s",
1239 fbi ->
name, isc_result_totext (status));
1240 interface_dereference (&fbi,
MDL);
1246#if defined(sun) && defined(USE_V4_PKTINFO)
1250 struct sockaddr_dl *dladdrp;
1254 memset(&lifr, 0,
sizeof (lifr));
1255 (void) strlcpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
1260 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ||
1269 if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) >= 0 &&
1276 log_fatal(
"Couldn't get interface flags for %s: %m", name);
1281 if (lifr.lifr_flags & (IFF_VIRTUAL|IFF_IPMP)) {
1283 srandom((
long)gethrtime());
1286 for (i = 1; i < hw->
hlen; ++i) {
1287 hw->
hbuf[i] = random() % 256;
1295 if (ioctl(sock, SIOCGLIFHWADDR, &lifr) < 0)
1296 log_fatal(
"Couldn't get interface hardware address for %s: %m",
1298 dladdrp = (
struct sockaddr_dl *)&lifr.lifr_addr;
1299 hw->
hlen = dladdrp->sdl_alen+1;
1300 switch (dladdrp->sdl_type) {
1315 log_fatal(
"%s: unsupported DLPI MAC type %lu", name,
1316 (
unsigned long)dladdrp->sdl_type);
1319 memcpy(hw->
hbuf+1, LLADDR(dladdrp), hw->
hlen-1);
#define All_DHCP_Relay_Agents_and_Servers
void if_reinitialize_receive(struct interface_info *)
void maybe_setup_fallback(void)
#define INTERFACE_UPSTREAM
#define INTERFACE_DOWNSTREAM
int supports_multiple_interfaces(struct interface_info *)
void if_deregister_send(struct interface_info *)
#define INTERFACE_STREAMS
void if_reinitialize_send(struct interface_info *)
isc_result_t fallback_discard(omapi_object_t *)
ssize_t send_packet(struct interface_info *, struct packet *, struct dhcp_packet *, size_t, struct in_addr, struct sockaddr_in *, struct hardware *)
void if_register_linklocal6(struct interface_info *info)
void if_deregister6(struct interface_info *info)
int can_receive_unicast_unconfigured(struct interface_info *)
ssize_t receive_packet(struct interface_info *, unsigned char *, size_t, struct sockaddr_in *, struct hardware *)
void get_hw_addr(struct interface_info *info)
struct in6_addr local_address6
void if_register_receive(struct interface_info *)
void if_register6(struct interface_info *info, int do_multicast)
int if_register_socket(struct interface_info *, int, int *, struct in6_addr *)
ssize_t send_packet6(struct interface_info *, const unsigned char *, size_t, struct sockaddr_in6 *)
void set_multicast_hop_limit(struct interface_info *info, int hop_limit)
int can_unicast_without_arp(struct interface_info *)
void if_deregister_receive(struct interface_info *)
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)
void if_register_send(struct interface_info *)
int setup_fallback(struct interface_info **fp, const char *file, int line)
int quiet_interface_discovery
struct in_addr local_address
omapi_object_type_t * dhcp_type_interface
int if_readsocket(omapi_object_t *h)
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 *))
struct __omapi_object omapi_object_t
void * dmalloc(size_t, const char *, int)
int log_error(const char *,...) __attribute__((__format__(__printf__
int int int log_debug(const char *,...) __attribute__((__format__(__printf__
void log_fatal(const char *,...) __attribute__((__format__(__printf__
int int log_info(const char *,...) __attribute__((__format__(__printf__
#define DHCP_R_INVALIDARG
u_int8_t hbuf[HARDWARE_ADDR_LEN+1]
struct in6_addr * v6addresses
struct shared_network * shared_network
struct in_addr * addresses