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;
68 #if defined(RELAY_PORT)
69 static unsigned int relay_port_v6_socket_references = 0;
70 static int relay_port_v6_socket = -1;
81 #if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO)
82 static unsigned int global_v4_socket_references = 0;
83 static 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
105 close (info -> wfdesc);
112 #ifdef USE_SOCKET_RECEIVE
118 close (info -> rfdesc);
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)
357 info->rfdesc = info->wfdesc;
360 info->wfdesc = info->rfdesc;
363 log_info (
"Sending on Socket/%s%s%s",
365 (info->shared_network ?
"/" :
""),
366 (info->shared_network ?
367 info->shared_network->name :
""));
370 #if defined (USE_SOCKET_SEND)
374 #ifndef USE_SOCKET_RECEIVE
375 close (info -> wfdesc);
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",
421 (info->shared_network ?
"/" :
""),
422 (info->shared_network ?
423 info->shared_network->name :
""));
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.");
758 static size_t CMSG_LEN(
size_t len) {
764 hdrlen = (size_t)CMSG_DATA(((
struct cmsghdr *)NULL));
770 static 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))
811 static void *control_buf = NULL;
812 static size_t control_buf_len = 0;
815 allocate_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);
880 if (no_global_v6_socket)
881 dst.sin6_scope_id = ifindex;
888 v.iov_base = (
char *)raw;
901 m.msg_control = control_buf;
902 m.msg_controllen = control_buf_len;
903 cmsg = CMSG_FIRSTHDR(&m);
904 INSIST(cmsg != NULL);
905 cmsg->cmsg_level = IPPROTO_IPV6;
906 cmsg->cmsg_type = IPV6_PKTINFO;
907 cmsg->cmsg_len = CMSG_LEN(
sizeof(*pktinfo));
908 pktinfo = (
struct in6_pktinfo *)CMSG_DATA(cmsg);
909 memset(pktinfo, 0,
sizeof(*pktinfo));
911 pktinfo->ipi6_ifindex = ifindex;
913 result = sendmsg(interface->
wfdesc, &m, 0);
921 #ifdef USE_SOCKET_RECEIVE
926 struct sockaddr_in *from;
929 #if !(defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO))
939 memset(hfrom, 0,
sizeof(*hfrom));
941 #ifdef IGNORE_HOSTUNREACH
946 #if defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && defined(USE_V4_PKTINFO)
949 struct cmsghdr *cmsg;
950 struct in_pktinfo *pktinfo;
951 unsigned int ifindex;
957 if (control_buf == NULL) {
958 allocate_cmsg_cbuf();
959 if (control_buf == NULL) {
960 log_error(
"receive_packet: unable to allocate cmsg "
965 memset(control_buf, 0, control_buf_len);
970 memset(&m, 0,
sizeof(m));
976 m.msg_namelen =
sizeof(*from);
996 m.msg_control = control_buf;
997 m.msg_controllen = control_buf_len;
999 result = recvmsg(interface->rfdesc, &m, 0);
1007 cmsg = CMSG_FIRSTHDR(&m);
1008 while (cmsg != NULL) {
1009 if ((cmsg->cmsg_level == IPPROTO_IP) &&
1010 (cmsg->cmsg_type == IP_PKTINFO)) {
1011 pktinfo = (
struct in_pktinfo *)CMSG_DATA(cmsg);
1012 ifindex = pktinfo->ipi_ifindex;
1019 memcpy(hfrom->
hbuf, &ifindex,
sizeof(ifindex));
1022 cmsg = CMSG_NXTHDR(&m, cmsg);
1033 result = recvfrom(interface -> rfdesc, (
char *)buf, len, 0,
1034 (
struct sockaddr *)from, &flen);
1036 #ifdef IGNORE_HOSTUNREACH
1037 }
while (result < 0 &&
1038 (errno == EHOSTUNREACH ||
1039 errno == ECONNREFUSED) &&
1050 unsigned char *buf,
size_t len,
1051 struct sockaddr_in6 *from,
struct in6_addr *to_addr,
1052 unsigned int *if_idx)
1057 struct cmsghdr *cmsg;
1058 struct in6_pktinfo *pktinfo;
1064 if (control_buf == NULL) {
1065 allocate_cmsg_cbuf();
1066 if (control_buf == NULL) {
1067 log_error(
"receive_packet6: unable to allocate cmsg "
1072 memset(control_buf, 0, control_buf_len);
1077 memset(&m, 0,
sizeof(m));
1083 m.msg_namelen =
sizeof(*from);
1103 m.msg_control = control_buf;
1104 m.msg_controllen = control_buf_len;
1106 result = recvmsg(interface->
rfdesc, &m, 0);
1114 cmsg = CMSG_FIRSTHDR(&m);
1115 while (cmsg != NULL) {
1116 if ((cmsg->cmsg_level == IPPROTO_IPV6) &&
1117 (cmsg->cmsg_type == IPV6_PKTINFO)) {
1118 pktinfo = (
struct in6_pktinfo *)CMSG_DATA(cmsg);
1119 *to_addr = pktinfo->ipi6_addr;
1120 *if_idx = pktinfo->ipi6_ifindex;
1124 cmsg = CMSG_NXTHDR(&m, cmsg);
1139 #if defined (USE_SOCKET_FALLBACK)
1146 struct sockaddr_in from;
1155 status = recvfrom (interface -> wfdesc, buf,
sizeof buf, 0,
1156 (
struct sockaddr *)&from, &flen);
1161 return ISC_R_UNEXPECTED;
1171 #if defined (USE_SOCKET_SEND)
1181 #if defined (SOCKET_CAN_RECEIVE_UNICAST_UNCONFIGURED)
1191 #if defined(SO_BINDTODEVICE) || \
1192 (defined(IP_PKTINFO) && defined(IP_RECVPKTINFO) && \
1193 defined(USE_V4_PKTINFO))
1205 #if defined (USE_SOCKET_FALLBACK)
1206 isc_result_t status;
1211 log_info (
"Sending on Socket/%s%s%s",
1221 log_fatal (
"Can't register I/O handle for %s: %s",
1222 fbi ->
name, isc_result_totext (status));
1223 interface_dereference (&fbi,
MDL);
1229 #if defined(sun) && defined(USE_V4_PKTINFO)
1233 struct sockaddr_dl *dladdrp;
1237 memset(&lifr, 0,
sizeof (lifr));
1238 (void) strlcpy(lifr.lifr_name, name, sizeof (lifr.lifr_name));
1243 if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ||
1252 if ((sock = socket(AF_INET6, SOCK_DGRAM, 0)) >= 0 &&
1259 log_fatal(
"Couldn't get interface flags for %s: %m", name);
1264 if (lifr.lifr_flags & (IFF_VIRTUAL|IFF_IPMP)) {
1266 srandom((
long)gethrtime());
1269 for (i = 1; i < hw->
hlen; ++i) {
1270 hw->
hbuf[i] = random() % 256;
1278 if (ioctl(sock, SIOCGLIFHWADDR, &lifr) < 0)
1279 log_fatal(
"Couldn't get interface hardware address for %s: %m",
1281 dladdrp = (
struct sockaddr_dl *)&lifr.lifr_addr;
1282 hw->
hlen = dladdrp->sdl_alen+1;
1283 switch (dladdrp->sdl_type) {
1298 log_fatal(
"%s: unsupported DLPI MAC type %lu", name,
1299 (
unsigned long)dladdrp->sdl_type);
1302 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
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 *)
log_fatal("no memory for uname information.")
void get_hw_addr(struct interface_info *info)
void maybe_setup_fallback(void)
void if_deregister_send(struct interface_info *)
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 *)
if(parse_ip_addr(cfile,&match->addr))
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 *)
#define INTERFACE_DOWNSTREAM
void if_reinitialize_receive(struct interface_info *)
int can_unicast_without_arp(struct interface_info *)
void if_register_receive(struct interface_info *)
struct in6_addr local_address6
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