40 #include <sys/ioctl.h> 44 #if defined(sun) && defined(USE_V4_PKTINFO) 45 #include <sys/sysmacros.h> 47 #include <sys/sockio.h> 48 #include <net/if_dl.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 65 static int no_global_v6_socket = 0;
66 static unsigned int global_v6_socket_references = 0;
67 static int global_v6_socket = -1;
77 #if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO) 78 static unsigned int global_v4_socket_references = 0;
79 static int global_v4_socket = -1;
87 #if !defined(SO_BINDTODEVICE) && !defined(USE_FALLBACK) 94 #if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_FALLBACK) 99 #ifndef USE_SOCKET_RECEIVE 101 close (info -> wfdesc);
108 #ifdef USE_SOCKET_RECEIVE 114 close (info -> rfdesc);
120 #if defined (USE_SOCKET_SEND) || \ 121 defined (USE_SOCKET_RECEIVE) || \ 122 defined (USE_SOCKET_FALLBACK) 126 int *do_multicast,
struct in6_addr *linklocal6)
128 struct sockaddr_storage name;
134 struct sockaddr_in6 *addr6;
136 struct sockaddr_in *addr;
140 #if !defined(SO_BINDTODEVICE) && !defined(USE_FALLBACK) 143 log_fatal (
"The standard socket API can only support %s",
144 "hosts with a single network interface.");
153 memset(&name, 0,
sizeof(name));
157 addr6 = (
struct sockaddr_in6 *)&name;
158 addr6->sin6_family = AF_INET6;
161 memcpy(&addr6->sin6_addr,
163 sizeof(addr6->sin6_addr));
164 addr6->sin6_scope_id = if_nametoindex(info->
name);
167 addr6->sin6_len =
sizeof(*addr6);
169 name_len =
sizeof(*addr6);
179 addr = (
struct sockaddr_in *)&name;
180 addr->sin_family = AF_INET;
182 memcpy(&addr->sin_addr,
184 sizeof(addr->sin_addr));
186 addr->sin_len =
sizeof(*addr);
188 name_len =
sizeof(*addr);
194 sock = socket(domain, SOCK_DGRAM, IPPROTO_UDP);
196 log_fatal(
"Can't create dhcp socket: %m");
202 if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
203 (
char *)&flag,
sizeof(flag)) < 0) {
204 log_fatal(
"Can't set SO_REUSEADDR option on dhcp socket: %m");
211 (setsockopt(sock, SOL_SOCKET, SO_BROADCAST,
212 (
char *)&flag,
sizeof(flag)) < 0)) {
213 log_fatal(
"Can't set SO_BROADCAST option on dhcp socket: %m");
216 #if defined(DHCPv6) && defined(SO_REUSEPORT) 228 if ((setsockopt(sock, SOL_SOCKET, SO_REUSEPORT,
229 (
char *)&flag,
sizeof(flag)) < 0) &&
230 (errno != ENOPROTOOPT)) {
231 log_fatal(
"Can't set SO_REUSEPORT option on dhcp " 238 if (bind(sock, (
struct sockaddr *)&name, name_len) < 0) {
239 log_error(
"Can't bind to dhcp address: %m");
240 log_error(
"Please make sure there is no other dhcp server");
241 log_error(
"running and that there's no entry for dhcp or");
242 log_error(
"bootp in /etc/inetd.conf. Also make sure you");
243 log_error(
"are not running HP JetAdmin software, which");
247 #if defined(SO_BINDTODEVICE) 250 setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE,
251 (
char *)(info -> ifp),
sizeof(*(info -> ifp))) < 0) {
252 log_fatal(
"setsockopt: SO_BINDTODEVICE: %m");
263 #if defined(SCO) && defined(IP_BROADCAST_IF) 265 setsockopt(sock, IPPROTO_IP, IP_BROADCAST_IF, &info->
addresses[0],
267 log_fatal(
"Can't set IP_BROADCAST_IF on dhcp socket: %m");
270 #if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO) 275 if (family == AF_INET) {
277 if (setsockopt(sock, IPPROTO_IP, IP_RECVPKTINFO,
278 &on,
sizeof(on)) != 0) {
279 log_fatal(
"setsockopt: IPV_RECVPKTINFO: %m");
290 if (family == AF_INET6) {
292 #ifdef IPV6_RECVPKTINFO 294 if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO,
295 &on,
sizeof(on)) != 0) {
296 log_fatal(
"setsockopt: IPV6_RECVPKTINFO: %m");
300 if (setsockopt(sock, IPPROTO_IPV6, IPV6_PKTINFO,
301 &on,
sizeof(on)) != 0) {
302 log_fatal(
"setsockopt: IPV6_PKTINFO: %m");
314 if (setsockopt(info->
wfdesc, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
315 &hop_limit,
sizeof(
int)) < 0) {
316 log_fatal(
"setMulticaseHopLimit: IPV6_MULTICAST_HOPS: %m");
319 log_debug(
"Setting hop count limit to %d for interface %s",
320 hop_limit, info->
name);
327 #if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_FALLBACK) 331 #ifndef USE_SOCKET_RECEIVE 334 if (strcmp(info->name,
"fallback") != 0)
336 #if defined (USE_SOCKET_FALLBACK) 339 info->rfdesc = info->wfdesc;
342 info->wfdesc = info->rfdesc;
345 log_info (
"Sending on Socket/%s%s%s",
347 (info->shared_network ?
"/" :
""),
348 (info->shared_network ?
349 info->shared_network->name :
""));
352 #if defined (USE_SOCKET_SEND) 356 #ifndef USE_SOCKET_RECEIVE 357 close (info -> wfdesc);
362 log_info (
"Disabling output on Socket/%s%s%s",
371 #ifdef USE_SOCKET_RECEIVE 376 #if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO) 377 if (global_v4_socket_references == 0) {
379 if (global_v4_socket < 0) {
384 log_fatal(
"Failed to create AF_INET socket %s:%d",
389 info->rfdesc = global_v4_socket;
390 global_v4_socket_references++;
397 if (strcmp(info->name,
"fallback") != 0)
401 log_info (
"Listening on Socket/%s%s%s",
403 (info->shared_network ?
"/" :
""),
404 (info->shared_network ?
405 info->shared_network->name :
""));
411 #if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO) 413 if ((info->rfdesc == global_v4_socket) &&
414 (info->wfdesc == global_v4_socket) &&
415 (global_v4_socket_references > 0)) {
416 global_v4_socket_references--;
422 if (global_v4_socket_references == 0) {
423 close(global_v4_socket);
424 global_v4_socket = -1;
431 log_info (
"Disabling input on Socket/%s%s%s",
448 struct ipv6_mreq mreq;
451 &mreq.ipv6mr_multiaddr) <= 0) {
452 log_fatal(
"inet_pton: unable to convert '%s'",
455 mreq.ipv6mr_interface = if_nametoindex(info->
name);
456 if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
457 &mreq,
sizeof(mreq)) < 0) {
458 log_fatal(
"setsockopt: IPV6_JOIN_GROUP: %m");
470 &mreq.ipv6mr_multiaddr) <= 0) {
471 log_fatal(
"inet_pton: unable to convert '%s'",
474 mreq.ipv6mr_interface = if_nametoindex(info->
name);
475 if (setsockopt(sock, IPPROTO_IPV6, IPV6_JOIN_GROUP,
476 &mreq,
sizeof(mreq)) < 0) {
477 log_fatal(
"setsockopt: IPV6_JOIN_GROUP: %m");
485 int req_multi = do_multicast;
487 if (no_global_v6_socket) {
491 if (global_v6_socket_references == 0) {
494 if (global_v6_socket < 0) {
505 info->
rfdesc = global_v6_socket;
506 info->
wfdesc = global_v6_socket;
507 global_v6_socket_references++;
510 if_register_multicast(info);
516 log_info(
"Listening on Socket/%d/%s/%s",
517 global_v6_socket, info->
name,
519 log_info(
"Sending on Socket/%d/%s/%s",
520 global_v6_socket, info->
name,
539 struct in6_addr *addr6 = NULL;
542 if (global_v6_socket >= 0) {
546 no_global_v6_socket = 1;
551 if (IN6_IS_ADDR_LINKLOCAL(addr6))
572 log_info(
"Listening on Socket/%d/%s/%s",
573 global_v6_socket, info->
name,
575 log_info(
"Sending on Socket/%d/%s/%s",
576 global_v6_socket, info->
name,
588 if (no_global_v6_socket) {
592 }
else if ((info->
rfdesc == global_v6_socket) &&
593 (info->
wfdesc == global_v6_socket) &&
594 (global_v6_socket_references > 0)) {
596 global_v6_socket_references--;
607 log_info(
"Disabling output on Socket/%s/%s", info->
name,
615 if (!no_global_v6_socket &&
616 (global_v6_socket_references == 0)) {
617 close(global_v6_socket);
618 global_v6_socket = -1;
625 #if defined (USE_SOCKET_SEND) || defined (USE_SOCKET_FALLBACK) 632 struct sockaddr_in *to;
636 #ifdef IGNORE_HOSTUNREACH 640 #if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO) 641 struct in_pktinfo pktinfo;
643 if (interface->ifp != NULL) {
644 memset(&pktinfo, 0,
sizeof (pktinfo));
645 pktinfo.ipi_ifindex = interface->ifp->ifr_index;
646 if (setsockopt(interface->wfdesc, IPPROTO_IP,
647 IP_PKTINFO, (
char *)&pktinfo,
648 sizeof(pktinfo)) < 0)
652 result = sendto (interface -> wfdesc, (
char *)raw, len, 0,
653 (
struct sockaddr *)to,
sizeof *to);
654 #ifdef IGNORE_HOSTUNREACH 655 }
while (to -> sin_addr.s_addr == htonl (INADDR_BROADCAST) &&
657 (errno == EHOSTUNREACH ||
658 errno == ECONNREFUSED) &&
663 if (errno == ENETUNREACH)
664 log_error (
"send_packet: please consult README file%s",
665 " regarding broadcast address.");
679 static size_t CMSG_LEN(
size_t len) {
685 hdrlen = (size_t)CMSG_DATA(((
struct cmsghdr *)NULL));
691 static size_t CMSG_SPACE(
size_t len) {
693 struct cmsghdr *cmsgp;
700 struct cmsghdr cmsg_sizer;
701 u_int8_t pktinfo_sizer[
sizeof(
struct cmsghdr) + 1024];
704 memset(&msg, 0,
sizeof(msg));
705 msg.msg_control = &dummybuf;
706 msg.msg_controllen =
sizeof(dummybuf);
708 cmsgp = (
struct cmsghdr *)&dummybuf;
709 cmsgp->cmsg_len = CMSG_LEN(len);
711 cmsgp = CMSG_NXTHDR(&msg, cmsgp);
713 return (
char *)cmsgp - (
char *)msg.msg_control;
722 #if defined(DHCPv6) || \ 723 (defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && \ 724 defined(USE_V4_PKTINFO)) 732 static void *control_buf = NULL;
733 static size_t control_buf_len = 0;
736 allocate_cmsg_cbuf(
void) {
737 control_buf_len = CMSG_SPACE(
sizeof(
struct in6_pktinfo));
764 const unsigned char *raw,
size_t len,
765 struct sockaddr_in6 *to) {
768 struct sockaddr_in6 dst;
770 struct in6_pktinfo *pktinfo;
771 struct cmsghdr *cmsg;
772 unsigned int ifindex;
779 if (control_buf == NULL) {
780 allocate_cmsg_cbuf();
781 if (control_buf == NULL) {
782 log_error(
"send_packet6: unable to allocate cmsg header");
786 memset(control_buf, 0, control_buf_len);
791 memset(&m, 0,
sizeof(m));
797 memcpy(&dst, to,
sizeof(dst));
799 m.msg_namelen =
sizeof(dst);
800 ifindex = if_nametoindex(interface->
name);
801 if (no_global_v6_socket)
802 dst.sin6_scope_id = ifindex;
809 v.iov_base = (
char *)raw;
822 m.msg_control = control_buf;
823 m.msg_controllen = control_buf_len;
824 cmsg = CMSG_FIRSTHDR(&m);
825 INSIST(cmsg != NULL);
826 cmsg->cmsg_level = IPPROTO_IPV6;
827 cmsg->cmsg_type = IPV6_PKTINFO;
828 cmsg->cmsg_len = CMSG_LEN(
sizeof(*pktinfo));
829 pktinfo = (
struct in6_pktinfo *)CMSG_DATA(cmsg);
830 memset(pktinfo, 0,
sizeof(*pktinfo));
831 pktinfo->ipi6_ifindex = ifindex;
833 result = sendmsg(interface->
wfdesc, &m, 0);
841 #ifdef USE_SOCKET_RECEIVE 846 struct sockaddr_in *from;
849 #if !(defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO)) 859 memset(hfrom, 0,
sizeof(*hfrom));
861 #ifdef IGNORE_HOSTUNREACH 866 #if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO) 869 struct cmsghdr *cmsg;
870 struct in_pktinfo *pktinfo;
871 unsigned int ifindex;
877 if (control_buf == NULL) {
878 allocate_cmsg_cbuf();
879 if (control_buf == NULL) {
880 log_error(
"receive_packet: unable to allocate cmsg " 885 memset(control_buf, 0, control_buf_len);
890 memset(&m, 0,
sizeof(m));
896 m.msg_namelen =
sizeof(*from);
916 m.msg_control = control_buf;
917 m.msg_controllen = control_buf_len;
919 result = recvmsg(interface->rfdesc, &m, 0);
927 cmsg = CMSG_FIRSTHDR(&m);
928 while (cmsg != NULL) {
929 if ((cmsg->cmsg_level == IPPROTO_IP) &&
930 (cmsg->cmsg_type == IP_PKTINFO)) {
931 pktinfo = (
struct in_pktinfo *)CMSG_DATA(cmsg);
932 ifindex = pktinfo->ipi_ifindex;
939 memcpy(hfrom->
hbuf, &ifindex,
sizeof(ifindex));
942 cmsg = CMSG_NXTHDR(&m, cmsg);
953 result = recvfrom(interface -> rfdesc, (
char *)buf, len, 0,
954 (
struct sockaddr *)from, &flen);
956 #ifdef IGNORE_HOSTUNREACH 957 }
while (result < 0 &&
958 (errno == EHOSTUNREACH ||
959 errno == ECONNREFUSED) &&
970 unsigned char *buf,
size_t len,
971 struct sockaddr_in6 *from,
struct in6_addr *to_addr,
972 unsigned int *if_idx)
977 struct cmsghdr *cmsg;
978 struct in6_pktinfo *pktinfo;
984 if (control_buf == NULL) {
985 allocate_cmsg_cbuf();
986 if (control_buf == NULL) {
987 log_error(
"receive_packet6: unable to allocate cmsg " 992 memset(control_buf, 0, control_buf_len);
997 memset(&m, 0,
sizeof(m));
1003 m.msg_namelen =
sizeof(*from);
1023 m.msg_control = control_buf;
1024 m.msg_controllen = control_buf_len;
1026 result = recvmsg(interface->
rfdesc, &m, 0);
1034 cmsg = CMSG_FIRSTHDR(&m);
1035 while (cmsg != NULL) {
1036 if ((cmsg->cmsg_level == IPPROTO_IPV6) &&
1037 (cmsg->cmsg_type == IPV6_PKTINFO)) {
1038 pktinfo = (
struct in6_pktinfo *)CMSG_DATA(cmsg);
1039 *to_addr = pktinfo->ipi6_addr;
1040 *if_idx = pktinfo->ipi6_ifindex;
1044 cmsg = CMSG_NXTHDR(&m, cmsg);
1059 #if defined (USE_SOCKET_FALLBACK) 1066 struct sockaddr_in from;
1075 status = recvfrom (interface -> wfdesc, buf,
sizeof buf, 0,
1076 (
struct sockaddr *)&from, &flen);
1081 return ISC_R_UNEXPECTED;
1087 return ISC_R_SUCCESS;
1091 #if defined (USE_SOCKET_SEND) 1101 #if defined (SOCKET_CAN_RECEIVE_UNICAST_UNCONFIGURED) 1111 #if defined(SO_BINDTODEVICE) || \ 1112 (defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && \ 1113 defined(USE_V4_PKTINFO)) 1125 #if defined (USE_SOCKET_FALLBACK) 1126 isc_result_t status;
1131 log_info (
"Sending on Socket/%s%s%s",
1140 if (status != ISC_R_SUCCESS)
1141 log_fatal (
"Can't register I/O handle for %s: %s",
1142 fbi ->
name, isc_result_totext (status));
1143 interface_dereference (&fbi,
MDL);
1149 #if defined(sun) && defined(USE_V4_PKTINFO) 1153 struct sockaddr_dl *dladdrp;
1157 memset(&lifr, 0,
sizeof (lifr));
1158 (void) strlcpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
1163 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ||
1172 if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) >= 0 &&
1179 log_fatal(
"Couldn't get interface flags for %s: %m", name);
1184 if (lifr.lifr_flags & (IFF_VIRTUAL|IFF_IPMP)) {
1186 srandom((
long)gethrtime());
1189 for (i = 1; i < hw->
hlen; ++i) {
1190 hw->
hbuf[i] = random() % 256;
1198 if (ioctl(sock, SIOCGLIFHWADDR, &lifr) < 0)
1199 log_fatal(
"Couldn't get interface hardware address for %s: %m",
1201 dladdrp = (
struct sockaddr_dl *)&lifr.lifr_addr;
1202 hw->
hlen = dladdrp->sdl_alen+1;
1203 switch (dladdrp->sdl_type) {
1218 log_fatal(
"%s: unsupported DLPI MAC type %lu", name,
1219 (
unsigned long)dladdrp->sdl_type);
1222 memcpy(hw->
hbuf+1, LLADDR(dladdrp), hw->
hlen-1);
void if_register_send(struct interface_info *)
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 shared_network * shared_network
int if_readsocket(omapi_object_t *h)
void if_reinitialize_send(struct interface_info *)
#define All_DHCP_Relay_Agents_and_Servers
#define DHCP_R_INVALIDARG
int int int log_debug(const char *,...) __attribute__((__format__(__printf__
int can_receive_unicast_unconfigured(struct interface_info *)
struct in_addr * addresses
int setup_fallback(struct interface_info **fp, const char *file, int line)
int log_error(const char *,...) __attribute__((__format__(__printf__
void if_deregister_receive(struct interface_info *)
void get_hw_addr(struct interface_info *info)
void maybe_setup_fallback(void)
void if_deregister_send(struct interface_info *)
void log_fatal(const char *,...) __attribute__((__format__(__printf__
void if_deregister6(struct interface_info *info)
void if_register_linklocal6(struct interface_info *info)
ssize_t send_packet6(struct interface_info *, const unsigned char *, size_t, struct sockaddr_in6 *)
ssize_t send_packet(struct interface_info *, struct packet *, struct dhcp_packet *, size_t, struct in_addr, struct sockaddr_in *, struct hardware *)
omapi_object_type_t * dhcp_type_interface
int int log_info(const char *,...) __attribute__((__format__(__printf__
void * dmalloc(size_t, const char *, int)
void if_register6(struct interface_info *info, int do_multicast)
int quiet_interface_discovery
int supports_multiple_interfaces(struct interface_info *)
u_int8_t hbuf[HARDWARE_ADDR_LEN+1]
#define INTERFACE_UPSTREAM
void set_multicast_hop_limit(struct interface_info *info, int hop_limit)
struct in_addr local_address
ssize_t receive_packet(struct interface_info *, unsigned char *, size_t, struct sockaddr_in *, struct hardware *)
void if_reinitialize_receive(struct interface_info *)
int can_unicast_without_arp(struct interface_info *)
void if_register_receive(struct interface_info *)
isc_result_t fallback_discard(omapi_object_t *)
#define INTERFACE_STREAMS
int if_register_socket(struct interface_info *, int, int *, struct in6_addr *)
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 in6_addr * v6addresses