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: %m");
220 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
221 (
char *)&flag,
sizeof(flag)) < 0) {
222 log_fatal(
"Can't set SO_REUSEADDR option on dhcp socket: %m");
229 (setsockopt(sock, SOL_SOCKET, SO_BROADCAST,
230 (
char *)&flag,
sizeof(flag)) < 0)) {
231 log_fatal(
"Can't set SO_BROADCAST option on dhcp socket: %m");
234#if defined(DHCPv6) && defined(SO_REUSEPORT)
246 if ((setsockopt(sock, SOL_SOCKET, SO_REUSEPORT,
247 (
char *)&flag,
sizeof(flag)) < 0) &&
248 (errno != ENOPROTOOPT)) {
249 log_fatal(
"Can't set SO_REUSEPORT option on dhcp "
256 if (bind(sock, (
struct sockaddr *)&name, name_len) < 0) {
257 log_error(
"Can't bind to dhcp address: %m");
258 log_error(
"Please make sure there is no other dhcp server");
259 log_error(
"running and that there's no entry for dhcp or");
260 log_error(
"bootp in /etc/inetd.conf. Also make sure you");
261 log_error(
"are not running HP JetAdmin software, which");
265#if defined(SO_BINDTODEVICE)
268 setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE,
269 (
char *)(info -> ifp),
sizeof(*(info -> ifp))) < 0) {
270 log_fatal(
"setsockopt: SO_BINDTODEVICE: %m");
281#if defined(SCO) && defined(IP_BROADCAST_IF)
283 setsockopt(sock, IPPROTO_IP, IP_BROADCAST_IF, &info->
addresses[0],
285 log_fatal(
"Can't set IP_BROADCAST_IF on dhcp socket: %m");
288#if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO)
293 if (family == AF_INET) {
295 if (setsockopt(sock, IPPROTO_IP, IP_RECVPKTINFO,
296 &on,
sizeof(on)) != 0) {
297 log_fatal(
"setsockopt: IPV_RECVPKTINFO: %m");
308 if (family == AF_INET6) {
310#ifdef IPV6_RECVPKTINFO
312 if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO,
313 &on,
sizeof(on)) != 0) {
314 log_fatal(
"setsockopt: IPV6_RECVPKTINFO: %m");
318 if (setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO,
319 &on,
sizeof(on)) != 0) {
320 log_fatal(
"setsockopt: IPV6_PKTINFO: %m");
332 if (setsockopt(info->
wfdesc, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
333 &hop_limit,
sizeof(
int)) < 0) {
334 log_fatal(
"setMulticaseHopLimit: IPV6_MULTICAST_HOPS: %m");
337 log_debug(
"Setting hop count limit to %d for interface %s",
338 hop_limit, info->
name);
345#if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_FALLBACK)
349#ifndef USE_SOCKET_RECEIVE
352 if (strcmp(info->
name,
"fallback") != 0)
354#if defined (USE_SOCKET_FALLBACK)
363 log_info (
"Sending on Socket/%s%s%s",
370#if defined (USE_SOCKET_SEND)
374#ifndef USE_SOCKET_RECEIVE
380 log_info (
"Disabling output on Socket/%s%s%s",
389#ifdef USE_SOCKET_RECEIVE
394#if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO)
395 if (global_v4_socket_references == 0) {
397 if (global_v4_socket < 0) {
402 log_fatal(
"Failed to create AF_INET socket %s:%d",
407 info->
rfdesc = global_v4_socket;
408 global_v4_socket_references++;
415 if (strcmp(info->
name,
"fallback") != 0)
419 log_info (
"Listening on Socket/%s%s%s",
429#if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO)
431 if ((info->
rfdesc == global_v4_socket) &&
432 (global_v4_socket_references > 0)) {
433 global_v4_socket_references--;
439 if (global_v4_socket_references == 0) {
440 close(global_v4_socket);
441 global_v4_socket = -1;
448 log_info (
"Disabling input on Socket/%s%s%s",
465 struct ipv6_mreq mreq;
468 &mreq.ipv6mr_multiaddr) <= 0) {
469 log_fatal(
"inet_pton: unable to convert '%s'",
472 mreq.ipv6mr_interface = if_nametoindex(info->
name);
473 if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
474 &mreq,
sizeof(mreq)) < 0) {
475 log_fatal(
"setsockopt: IPV6_JOIN_GROUP: %m");
487 &mreq.ipv6mr_multiaddr) <= 0) {
488 log_fatal(
"inet_pton: unable to convert '%s'",
491 mreq.ipv6mr_interface = if_nametoindex(info->
name);
492 if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
493 &mreq,
sizeof(mreq)) < 0) {
494 log_fatal(
"setsockopt: IPV6_JOIN_GROUP: %m");
502 int req_multi = do_multicast;
504 if (no_global_v6_socket) {
508#if defined(RELAY_PORT)
512 if (global_v6_socket_references == 0) {
515 if (global_v6_socket < 0) {
522 char addr6_str[INET6_ADDRSTRLEN];
524 if (inet_ntop(AF_INET6,
527 sizeof(addr6_str)) == NULL) {
528 log_fatal(
"inet_ntop: unable to convert "
539 info->
rfdesc = global_v6_socket;
540 info->
wfdesc = global_v6_socket;
541 global_v6_socket_references++;
543#if defined(RELAY_PORT)
550 if ((relay_port_v6_socket_references == 0) &&
554 if (relay_port_v6_socket < 0) {
557 log_info(
"Bound to relay port *:%d",
561 info->
rfdesc = relay_port_v6_socket;
562 info->
wfdesc = relay_port_v6_socket;
563 relay_port_v6_socket_references++;
568 if_register_multicast(info);
574 log_info(
"Listening on Socket/%d/%s/%s",
575 global_v6_socket, info->
name,
577 log_info(
"Sending on Socket/%d/%s/%s",
578 global_v6_socket, info->
name,
597 struct in6_addr *addr6 = NULL;
600 if (global_v6_socket >= 0) {
604 no_global_v6_socket = 1;
609 if (IN6_IS_ADDR_LINKLOCAL(addr6))
630 log_info(
"Listening on Socket/%d/%s/%s",
631 global_v6_socket, info->
name,
633 log_info(
"Sending on Socket/%d/%s/%s",
634 global_v6_socket, info->
name,
646 if (no_global_v6_socket) {
650 }
else if ((info->
rfdesc == global_v6_socket) &&
651 (info->
wfdesc == global_v6_socket) &&
652 (global_v6_socket_references > 0)) {
654 global_v6_socket_references--;
657#if defined(RELAY_PORT)
659 (info->
rfdesc == relay_port_v6_socket) &&
660 (info->
wfdesc == relay_port_v6_socket) &&
661 (relay_port_v6_socket_references > 0)) {
663 relay_port_v6_socket_references--;
675 log_info(
"Disabling output on Socket/%s/%s", info->
name,
683 if (!no_global_v6_socket) {
684 if (global_v6_socket_references == 0) {
685 close(global_v6_socket);
686 global_v6_socket = -1;
691#if defined(RELAY_PORT)
692 if (
relay_port && (relay_port_v6_socket_references == 0)) {
693 close(relay_port_v6_socket);
694 relay_port_v6_socket = -1;
696 log_info(
"Unbound from relay port *:%d",
704#if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_FALLBACK)
711 struct sockaddr_in *to;
715#ifdef IGNORE_HOSTUNREACH
719#if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO)
720 struct in_pktinfo pktinfo;
722 if (interface->
ifp != NULL) {
723 memset(&pktinfo, 0,
sizeof (pktinfo));
724 pktinfo.ipi_ifindex = interface->
ifp->ifr_index;
725 if (setsockopt(interface->
wfdesc, IPPROTO_IP,
726 IP_PKTINFO, (
char *)&pktinfo,
727 sizeof(pktinfo)) < 0)
731 result = sendto (interface -> wfdesc, (
char *)raw, len, 0,
732 (
struct sockaddr *)to,
sizeof *to);
733#ifdef IGNORE_HOSTUNREACH
734 }
while (to -> sin_addr.s_addr == htonl (INADDR_BROADCAST) &&
736 (errno == EHOSTUNREACH ||
737 errno == ECONNREFUSED) &&
742 if (errno == ENETUNREACH)
743 log_error (
"send_packet: please consult README file%s",
744 " regarding broadcast address.");
758static size_t CMSG_LEN(
size_t len) {
764 hdrlen = (size_t)CMSG_DATA(((
struct cmsghdr *)NULL));
770static size_t CMSG_SPACE(
size_t len) {
772 struct cmsghdr *cmsgp;
779 struct cmsghdr cmsg_sizer;
780 u_int8_t pktinfo_sizer[
sizeof(
struct cmsghdr) + 1024];
783 memset(&msg, 0,
sizeof(msg));
784 msg.msg_control = &dummybuf;
785 msg.msg_controllen =
sizeof(dummybuf);
787 cmsgp = (
struct cmsghdr *)&dummybuf;
788 cmsgp->cmsg_len = CMSG_LEN(len);
790 cmsgp = CMSG_NXTHDR(&msg, cmsgp);
792 return (
char *)cmsgp - (
char *)msg.msg_control;
801#if defined(DHCPv6) || \
802 (defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && \
803 defined(USE_V4_PKTINFO))
811static void *control_buf = NULL;
812static size_t control_buf_len = 0;
815allocate_cmsg_cbuf(
void) {
816 control_buf_len = CMSG_SPACE(
sizeof(
struct in6_pktinfo));
843 const unsigned char *raw,
size_t len,
844 struct sockaddr_in6 *to) {
847 struct sockaddr_in6 dst;
849 struct in6_pktinfo *pktinfo;
850 struct cmsghdr *cmsg;
851 unsigned int ifindex;
858 if (control_buf == NULL) {
859 allocate_cmsg_cbuf();
860 if (control_buf == NULL) {
861 log_error(
"send_packet6: unable to allocate cmsg header");
865 memset(control_buf, 0, control_buf_len);
870 memset(&m, 0,
sizeof(m));
876 memcpy(&dst, to,
sizeof(dst));
878 m.msg_namelen =
sizeof(dst);
879 ifindex = if_nametoindex(interface->
name);
885 if (no_global_v6_socket)
887 dst.sin6_scope_id = ifindex;
894 v.iov_base = (
char *)raw;
907 m.msg_control = control_buf;
908 m.msg_controllen = control_buf_len;
909 cmsg = CMSG_FIRSTHDR(&m);
910 INSIST(cmsg != NULL);
911 cmsg->cmsg_level = IPPROTO_IPV6;
912 cmsg->cmsg_type = IPV6_PKTINFO;
913 cmsg->cmsg_len = CMSG_LEN(
sizeof(*pktinfo));
914 pktinfo = (
struct in6_pktinfo *)CMSG_DATA(cmsg);
915 memset(pktinfo, 0,
sizeof(*pktinfo));
917 pktinfo->ipi6_ifindex = ifindex;
919 result = sendmsg(interface->
wfdesc, &m, 0);
927#ifdef USE_SOCKET_RECEIVE
932 struct sockaddr_in *from;
935#if !(defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO))
945 memset(hfrom, 0,
sizeof(*hfrom));
947#ifdef IGNORE_HOSTUNREACH
952#if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO)
955 struct cmsghdr *cmsg;
956 struct in_pktinfo *pktinfo;
957 unsigned int ifindex;
963 if (control_buf == NULL) {
964 allocate_cmsg_cbuf();
965 if (control_buf == NULL) {
966 log_error(
"receive_packet: unable to allocate cmsg "
971 memset(control_buf, 0, control_buf_len);
976 memset(&m, 0,
sizeof(m));
982 m.msg_namelen =
sizeof(*from);
1002 m.msg_control = control_buf;
1003 m.msg_controllen = control_buf_len;
1005 result = recvmsg(interface->
rfdesc, &m, 0);
1013 cmsg = CMSG_FIRSTHDR(&m);
1014 while (cmsg != NULL) {
1015 if ((cmsg->cmsg_level == IPPROTO_IP) &&
1016 (cmsg->cmsg_type == IP_PKTINFO)) {
1017 pktinfo = (
struct in_pktinfo *)CMSG_DATA(cmsg);
1018 ifindex = pktinfo->ipi_ifindex;
1025 memcpy(hfrom->
hbuf, &ifindex,
sizeof(ifindex));
1028 cmsg = CMSG_NXTHDR(&m, cmsg);
1039 result = recvfrom(interface -> rfdesc, (
char *)buf, len, 0,
1040 (
struct sockaddr *)from, &flen);
1042#ifdef IGNORE_HOSTUNREACH
1043 }
while (result < 0 &&
1044 (errno == EHOSTUNREACH ||
1045 errno == ECONNREFUSED) &&
1056 unsigned char *buf,
size_t len,
1057 struct sockaddr_in6 *from,
struct in6_addr *to_addr,
1058 unsigned int *if_idx)
1063 struct cmsghdr *cmsg;
1064 struct in6_pktinfo *pktinfo;
1070 if (control_buf == NULL) {
1071 allocate_cmsg_cbuf();
1072 if (control_buf == NULL) {
1073 log_error(
"receive_packet6: unable to allocate cmsg "
1078 memset(control_buf, 0, control_buf_len);
1083 memset(&m, 0,
sizeof(m));
1089 m.msg_namelen =
sizeof(*from);
1109 m.msg_control = control_buf;
1110 m.msg_controllen = control_buf_len;
1112 result = recvmsg(interface->
rfdesc, &m, 0);
1120 cmsg = CMSG_FIRSTHDR(&m);
1121 while (cmsg != NULL) {
1122 if ((cmsg->cmsg_level == IPPROTO_IPV6) &&
1123 (cmsg->cmsg_type == IPV6_PKTINFO)) {
1124 pktinfo = (
struct in6_pktinfo *)CMSG_DATA(cmsg);
1125 *to_addr = pktinfo->ipi6_addr;
1126 *if_idx = pktinfo->ipi6_ifindex;
1130 cmsg = CMSG_NXTHDR(&m, cmsg);
1145#if defined (USE_SOCKET_FALLBACK)
1152 struct sockaddr_in from;
1161 status = recvfrom (interface -> wfdesc, buf,
sizeof buf, 0,
1162 (
struct sockaddr *)&from, &flen);
1167 return ISC_R_UNEXPECTED;
1177#if defined (USE_SOCKET_SEND)
1187#if defined (SOCKET_CAN_RECEIVE_UNICAST_UNCONFIGURED)
1197#if defined(SO_BINDTODEVICE) || \
1198 (defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && \
1199 defined(USE_V4_PKTINFO))
1211#if defined (USE_SOCKET_FALLBACK)
1212 isc_result_t status;
1217 log_info (
"Sending on Socket/%s%s%s",
1227 log_fatal (
"Can't register I/O handle for %s: %s",
1228 fbi ->
name, isc_result_totext (status));
1229 interface_dereference (&fbi,
MDL);
1235#if defined(sun) && defined(USE_V4_PKTINFO)
1239 struct sockaddr_dl *dladdrp;
1243 memset(&lifr, 0,
sizeof (lifr));
1244 (void) strlcpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
1249 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ||
1258 if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) >= 0 &&
1265 log_fatal(
"Couldn't get interface flags for %s: %m", name);
1270 if (lifr.lifr_flags & (IFF_VIRTUAL|IFF_IPMP)) {
1272 srandom((
long)gethrtime());
1275 for (i = 1; i < hw->
hlen; ++i) {
1276 hw->
hbuf[i] = random() % 256;
1284 if (ioctl(sock, SIOCGLIFHWADDR, &lifr) < 0)
1285 log_fatal(
"Couldn't get interface hardware address for %s: %m",
1287 dladdrp = (
struct sockaddr_dl *)&lifr.lifr_addr;
1288 hw->
hlen = dladdrp->sdl_alen+1;
1289 switch (dladdrp->sdl_type) {
1304 log_fatal(
"%s: unsupported DLPI MAC type %lu", name,
1305 (
unsigned long)dladdrp->sdl_type);
1308 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 *))
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