Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F107753498
D45124.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
13 KB
Referenced Files
None
Subscribers
None
D45124.diff
View Options
diff --git a/usr.sbin/rwhod/Makefile b/usr.sbin/rwhod/Makefile
--- a/usr.sbin/rwhod/Makefile
+++ b/usr.sbin/rwhod/Makefile
@@ -1,3 +1,4 @@
+.include <src.opts.mk>
PROG= rwhod
MAN= rwhod.8
@@ -6,4 +7,11 @@
WARNS?= 3
+.if ${MK_INET_SUPPORT} != "no"
+CFLAGS+= -DINET
+.endif
+.if ${MK_INET6_SUPPORT} != "no"
+CFLAGS+= -DINET6
+.endif
+
.include <bsd.prog.mk>
diff --git a/usr.sbin/rwhod/rwhod.c b/usr.sbin/rwhod/rwhod.c
--- a/usr.sbin/rwhod/rwhod.c
+++ b/usr.sbin/rwhod/rwhod.c
@@ -73,16 +73,21 @@
#define MAX_MULTICAST_SCOPE 32 /* "site-wide", by convention */
+#ifdef INET
#define INADDR_WHOD_GROUP (u_long)0xe0000103 /* 224.0.1.3 */
/* (belongs in protocols/rwhod.h) */
+#endif
+#ifdef INET6
+#define IN6ADDR_WHOD_GROUP "ff02::103" /* link local address */
+#endif
int insecure_mode;
int quiet_mode;
int iff_flag = IFF_POINTOPOINT;
int multicast_mode = NO_MULTICAST;
int multicast_scope;
-struct sockaddr_in multicast_addr =
- { sizeof(multicast_addr), AF_INET, 0, { 0 }, { 0 } };
+struct sockaddr_storage multicast_addr;
+struct sockaddr *my_sa;
/*
* Sleep interval. Don't forget to change the down time check in ruptime
@@ -107,7 +112,6 @@
struct neighbor *neighbors;
struct whod mywd;
-struct servent *sp;
int s;
int fdp;
pid_t pid_child_receiver;
@@ -163,9 +167,9 @@
int
main(int argc, char *argv[])
{
- int on;
+ int on, error, success = 0;
char *cp;
- struct sockaddr_in soin;
+ struct addrinfo *res, *p;
uid_t unpriv_uid;
gid_t unpriv_gid;
@@ -210,11 +214,19 @@
#endif
(void) signal(SIGHUP, getboottime);
openlog("rwhod", LOG_PID | LOG_NDELAY, LOG_DAEMON);
- sp = getservbyname("who", "udp");
- if (sp == NULL) {
- syslog(LOG_ERR, "who/udp: unknown service");
+ error = getaddrinfo(NULL, "who", &(struct addrinfo){
+ .ai_family = AF_UNSPEC,
+ .ai_socktype = SOCK_DGRAM,
+ .ai_flags = AI_PASSIVE
+ }, &res);
+ if (error != 0) {
+ syslog(LOG_ERR, "getaddrinfo: %s", gai_strerror(error));
exit(1);
}
+ if (res->ai_next != NULL) {
+ syslog(LOG_INFO, "Multiple addresses were returned."
+ "Only the first address will be used.");
+ }
if (chdir(_PATH_RWHODIR) < 0) {
syslog(LOG_ERR, "%s: %m", _PATH_RWHODIR);
exit(1);
@@ -230,20 +242,49 @@
*cp = '\0';
strlcpy(mywd.wd_hostname, myname, sizeof(mywd.wd_hostname));
getboottime(0);
- if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
- syslog(LOG_ERR, "socket: %m");
- exit(1);
- }
- if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) {
- syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
- exit(1);
+ for (p = res; p != NULL; p = p->ai_next) {
+ if ((s = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) < 0) {
+ syslog(LOG_ERR, "socket: %m");
+ continue;
+ }
+ switch (p->ai_family) {
+#ifdef INET
+ case AF_INET:
+ if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) {
+ syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
+ close(s);
+ continue;
+ }
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, &on, sizeof(on)) < 0) {
+ syslog(LOG_ERR, "setsockopt IPV6_MULTICAST_IF: %m");
+ close(s);
+ continue;
+ }
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)) < 0) {
+ syslog(LOG_ERR, "setsockopt IPV6_V6ONLY: %m");
+ close(s);
+ continue;
+ }
+ break;
+#endif
+ default:
+ continue;
+ };
+ if (bind(s, p->ai_addr, p->ai_addrlen) < 0) {
+ syslog(LOG_ERR, "bind: %m");
+ close(s);
+ exit(1);
+ }
+ my_sa = p->ai_addr;
+ success = 1;
+ break;
}
- memset(&soin, 0, sizeof(soin));
- soin.sin_len = sizeof(soin);
- soin.sin_family = AF_INET;
- soin.sin_port = sp->s_port;
- if (bind(s, (struct sockaddr *)&soin, sizeof(soin)) < 0) {
- syslog(LOG_ERR, "bind: %m");
+ if (success == 0) {
+ syslog(LOG_ERR, "No suitable address found for creating a socket");
exit(1);
}
if (setgid(unpriv_gid) != 0) {
@@ -278,6 +319,7 @@
} else {
receiver_process();
}
+ freeaddrinfo(res);
}
static void
@@ -336,14 +378,14 @@
void
receiver_process(void)
{
- struct sockaddr_in from;
+ struct sockaddr from;
struct stat st;
cap_rights_t rights;
- char path[64];
+ char path[64], host[NI_MAXHOST], host_from[NI_MAXHOST], service[NI_MAXSERV], service_from[NI_MAXSERV];
int dirfd;
struct whod wd;
socklen_t len;
- int cc, whod;
+ int cc, whod, error;
time_t t;
len = sizeof(from);
@@ -362,22 +404,33 @@
syslog(LOG_ERR, "cap_enter: %m");
exit(1);
}
+ error = getnameinfo(my_sa, my_sa->sa_len, host, NI_MAXHOST, service, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV);
+ if (error != 0) {
+ syslog(LOG_ERR, "getnameinfo: %s", gai_strerror(error));
+ exit(1);
+ }
for (;;) {
- cc = recvfrom(s, &wd, sizeof(wd), 0, (struct sockaddr *)&from,
+ cc = recvfrom(s, &wd, sizeof(wd), 0, &from,
&len);
if (cc <= 0) {
if (cc < 0 && errno != EINTR)
syslog(LOG_WARNING, "recv: %m");
continue;
}
- if (from.sin_port != sp->s_port && !insecure_mode) {
- syslog(LOG_WARNING, "%d: bad source port from %s",
- ntohs(from.sin_port), inet_ntoa(from.sin_addr));
+ error = getnameinfo(&from, len, host_from, NI_MAXHOST, service_from,
+ NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV);
+ if (error != 0) {
+ syslog(LOG_ERR, "getnameinfo: %s", gai_strerror(error));
+ exit(1);
+ }
+ if (strcmp(service, service_from) != 0 && !insecure_mode) {
+ syslog(LOG_WARNING, "%s: bad source port from %s",
+ service_from, host_from);
continue;
}
if (cc < WHDRSIZE) {
syslog(LOG_WARNING, "short packet from %s",
- inet_ntoa(from.sin_addr));
+ host_from);
continue;
}
if (wd.wd_vers != WHODVERSION)
@@ -386,7 +439,7 @@
continue;
if (!verify(wd.wd_hostname, sizeof(wd.wd_hostname))) {
syslog(LOG_WARNING, "malformed host name from %s",
- inet_ntoa(from.sin_addr));
+ host_from);
continue;
}
(void) snprintf(path, sizeof(path), "whod.%s", wd.wd_hostname);
@@ -441,6 +494,7 @@
double avenrun[3];
time_t now;
int i, cc, status;
+ unsigned int ifindex;
struct utmpx *ut;
struct stat stb;
struct neighbor *np;
@@ -497,13 +551,32 @@
* Select the outgoing interface for the
* multicast.
*/
- if (setsockopt(s, IPPROTO_IP,
- IP_MULTICAST_IF,
- &(((struct sockaddr_in *)np->n_addr)->sin_addr),
- sizeof(struct in_addr)) < 0) {
- syslog(LOG_ERR,
- "setsockopt IP_MULTICAST_IF: %m");
- exit(1);
+ switch (np->n_addr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ if (setsockopt(s, IPPROTO_IP,
+ IP_MULTICAST_IF,
+ &(((struct sockaddr_in *)np->n_addr)->sin_addr),
+ sizeof(struct in_addr)) < 0) {
+ syslog(LOG_ERR,
+ "setsockopt IP_MULTICAST_IF: %m");
+ exit(1);
+ }
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ ifindex = if_nametoindex(np->n_name);
+ if (setsockopt(s, IPPROTO_IPV6,
+ IPV6_MULTICAST_IF,
+ &ifindex,
+ sizeof(ifindex)) < 0) {
+ syslog(LOG_ERR,
+ "setsockopt IPV6_MULTICAST_IF: %m");
+ exit(1);
+ }
+ break;
+#endif
}
(void) sendto(s, (char *)&mywd, cc, 0,
(struct sockaddr *)&multicast_addr,
@@ -574,47 +647,88 @@
int
configure(int so)
{
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ struct group_req greq;
struct neighbor *np;
struct if_msghdr *ifm;
struct ifa_msghdr *ifam;
struct sockaddr_dl *sdl;
size_t needed;
- int mib[6], flags, lflags, len;
- char *buf, *lim, *next;
+ int mib[6], flags, lflags, len, error;
+ char *buf, *lim, *next, host_dst[NI_MAXHOST], host_np[NI_MAXHOST];
struct rt_addrinfo info;
flags = 0;
- if (multicast_mode != NO_MULTICAST) {
- multicast_addr.sin_addr.s_addr = htonl(INADDR_WHOD_GROUP);
- multicast_addr.sin_port = sp->s_port;
- }
-
- if (multicast_mode == SCOPED_MULTICAST) {
- struct ip_mreq mreq;
- unsigned char ttl;
+ switch (my_sa->sa_family) {
+#ifdef INET
+ case AF_INET:
+ if (multicast_mode != NO_MULTICAST) {
+ sin.sin_len = sizeof(struct sockaddr_in);
+ sin.sin_family = AF_INET;
+ sin.sin_addr.s_addr = htonl(INADDR_WHOD_GROUP);
+ sin.sin_port = ((struct sockaddr_in *)(my_sa))->sin_port;
+ memcpy(&multicast_addr, (struct sockaddr *)&sin, sizeof(multicast_addr));
+ }
+ if (multicast_mode == SCOPED_MULTICAST) {
+ unsigned char ttl;
- mreq.imr_multiaddr.s_addr = htonl(INADDR_WHOD_GROUP);
- mreq.imr_interface.s_addr = htonl(INADDR_ANY);
- if (setsockopt(so, IPPROTO_IP, IP_ADD_MEMBERSHIP,
- &mreq, sizeof(mreq)) < 0) {
- syslog(LOG_ERR,
- "setsockopt IP_ADD_MEMBERSHIP: %m");
- return (0);
+ greq.gr_group = multicast_addr;
+ greq.gr_interface = 0;
+ if (setsockopt(so, IPPROTO_IP, MCAST_JOIN_GROUP, &greq,
+ sizeof(greq)) < 0) {
+ syslog(LOG_ERR,
+ "setsockopt MCAST_JOIN_GROUP: %m");
+ return (0);
+ }
+ ttl = multicast_scope;
+ if (setsockopt(so, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,
+ sizeof(ttl)) < 0) {
+ syslog(LOG_ERR,
+ "setsockopt IP_MULTICAST_TTL: %m");
+ return (0);
+ }
+ return (1);
}
- ttl = multicast_scope;
- if (setsockopt(so, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,
- sizeof(ttl)) < 0) {
- syslog(LOG_ERR,
- "setsockopt IP_MULTICAST_TTL: %m");
- return (0);
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ if (multicast_mode != NO_MULTICAST) {
+ sin6.sin6_len = sizeof(struct sockaddr_in6);
+ sin6.sin6_family = AF_INET6;
+ inet_pton(AF_INET6, IN6ADDR_WHOD_GROUP, &(sin6.sin6_addr));
+ sin6.sin6_port = ((struct sockaddr_in6 *)(my_sa))->sin6_port;
+ memcpy(&multicast_addr, (struct sockaddr *)&sin6, sizeof(multicast_addr));
}
- return (1);
+ if (multicast_mode == SCOPED_MULTICAST) {
+ int ttl;
+
+ greq.gr_group = multicast_addr;
+ greq.gr_interface = 0;
+ if (setsockopt(so, IPPROTO_IPV6, MCAST_JOIN_GROUP, &greq,
+ sizeof(greq)) < 0) {
+ syslog(LOG_ERR,
+ "setsockopt MCAST_JOIN_GROUP: %m");
+ return (0);
+ }
+ ttl = multicast_scope;
+ if (setsockopt(so, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
+ &ttl, sizeof(ttl)) < 0) {
+ syslog(LOG_ERR,
+ "setsockopt IPV6_MULTICAST_HOPS: %m");
+ return (0);
+ }
+ return (1);
+ }
+ break;
+#endif
}
mib[0] = CTL_NET;
mib[1] = PF_ROUTE;
mib[2] = 0;
- mib[3] = AF_INET;
+ mib[3] = my_sa->sa_family;
mib[4] = NET_RT_IFLIST;
mib[5] = 0;
if (sysctl(mib, nitems(mib), NULL, &needed, NULL, 0) < 0)
@@ -649,15 +763,37 @@
/* gag, wish we could get rid of Internet dependencies */
#define dstaddr info.rti_info[RTAX_BRD]
#define ifaddr info.rti_info[RTAX_IFA]
-#define IPADDR_SA(x) ((struct sockaddr_in *)(x))->sin_addr.s_addr
#define PORT_SA(x) ((struct sockaddr_in *)(x))->sin_port
- if (dstaddr == 0 || dstaddr->sa_family != AF_INET)
+#define PORT_SA6(x) ((struct sockaddr_in6 *)(x))->sin6_port
+ if (dstaddr == 0 || dstaddr->sa_family != my_sa->sa_family)
continue;
- PORT_SA(dstaddr) = sp->s_port;
+ switch (dstaddr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ PORT_SA(dstaddr) = PORT_SA(my_sa);
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ PORT_SA6(dstaddr) = PORT_SA6(my_sa);
+ break;
+#endif
+ }
+ error = getnameinfo(dstaddr, dstaddr->sa_len, host_dst, NI_MAXHOST, NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV);
+ if (error != 0) {
+ syslog(LOG_ERR, "getnameinfo: %s", gai_strerror(error));
+ exit(1);
+ }
for (np = neighbors; np != NULL; np = np->n_next) {
+ error = getnameinfo(np->n_addr, np->n_addr->sa_len, host_np, NI_MAXHOST,
+ NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV);
+ if (error != 0) {
+ syslog(LOG_ERR, "getnameinfo: %s", gai_strerror(error));
+ exit(1);
+ }
if (memcmp(sdl->sdl_data, np->n_name,
sdl->sdl_nlen) == 0 &&
- IPADDR_SA(np->n_addr) == IPADDR_SA(dstaddr)) {
+ strcmp(host_np, host_dst) == 0) {
break;
}
}
@@ -677,23 +813,48 @@
if (multicast_mode == PER_INTERFACE_MULTICAST &&
(flags & IFF_MULTICAST) != 0 &&
(flags & IFF_LOOPBACK) == 0) {
- struct ip_mreq mreq;
-
- memcpy((char *)np->n_addr, (char *)ifaddr,
- np->n_addrlen);
- mreq.imr_multiaddr.s_addr = htonl(INADDR_WHOD_GROUP);
- mreq.imr_interface.s_addr =
- ((struct sockaddr_in *)np->n_addr)->sin_addr.s_addr;
- if (setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP,
- &mreq, sizeof(mreq)) < 0) {
- syslog(LOG_ERR,
- "setsockopt IP_ADD_MEMBERSHIP: %m");
+ switch (my_sa->sa_family) {
+#ifdef INET
+ case AF_INET: {
+ memcpy((char *)np->n_addr, (char *)ifaddr,
+ np->n_addrlen);
+ greq.gr_group = multicast_addr;
+ greq.gr_interface= if_nametoindex(np->n_name);
+ if (setsockopt(s, IPPROTO_IP, MCAST_JOIN_GROUP,
+ &greq, sizeof(greq)) < 0) {
+ syslog(LOG_ERR,
+ "setsockopt MCAST_JOIN_GROUP: %m");
#if 0
/* Fall back to broadcast on this if. */
np->n_flags &= ~IFF_MULTICAST;
#else
- free(np);
- continue;
+ free(np);
+ continue;
+#endif
+ }
+ break;
+ }
+#endif
+#ifdef INET6
+ case AF_INET6: {
+ memcpy((char *)np->n_addr, (char *)ifaddr,
+ np->n_addrlen);
+ greq.gr_group = multicast_addr;
+ greq.gr_interface= if_nametoindex(np->n_name);
+ if (setsockopt(s, IPPROTO_IPV6, MCAST_JOIN_GROUP,
+ &greq, sizeof(greq)) < 0) {
+ syslog(LOG_ERR,
+ "setsockopt MCAST_JOIN_GROUP: %m");
+#if 0
+ /* Fall back to broadcast on this if. */
+ np->n_flags &= ~IFF_MULTICAST;
+#else
+ free(np);
+ continue;
+#endif
+ }
+ break;
+ }
#endif
}
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Jan 18, 11:36 PM (21 h, 55 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
15905023
Default Alt Text
D45124.diff (13 KB)
Attached To
Mode
D45124: rwhod: IPv6 clean
Attached
Detach File
Event Timeline
Log In to Comment