Page MenuHomeFreeBSD

D45123.id.diff
No OneTemporary

D45123.id.diff

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
@@ -39,6 +39,7 @@
#include <sys/signal.h>
#include <sys/sysctl.h>
#include <sys/wait.h>
+#include <sys/_sockaddr_storage.h>
#include <net/if.h>
#include <net/if_dl.h>
@@ -73,16 +74,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 *sa;
/*
* Sleep interval. Don't forget to change the down time check in ruptime
@@ -107,7 +113,6 @@
struct neighbor *neighbors;
struct whod mywd;
-struct servent *sp;
int s;
int fdp;
pid_t pid_child_receiver;
@@ -163,9 +168,9 @@
int
main(int argc, char *argv[])
{
- int on;
+ int on, error, success = 0;
char *cp;
- struct sockaddr_in soin;
+ struct addrinfo hints, *servinfo, *p;
uid_t unpriv_uid;
gid_t unpriv_gid;
@@ -210,9 +215,14 @@
#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");
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_flags = AI_PASSIVE;
+ error = getaddrinfo(NULL, "who", &hints, &servinfo);
+ if (error) {
+ const char *error_message = gai_strerror(error);
+ syslog(LOG_ERR, "getaddrinfo: %s", error_message);
exit(1);
}
if (chdir(_PATH_RWHODIR) < 0) {
@@ -230,22 +240,51 @@
*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 = servinfo; 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, SOL_SOCKET, 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
+ };
+ if (bind(s, p->ai_addr, p->ai_addrlen) < 0) {
+ syslog(LOG_ERR, "bind: %m");
+ close(s);
+ continue;
+ }
+
+ sa = p->ai_addr; // Save as global variable
+ 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");
- exit(1);
+ if (!success) {
+ syslog(LOG_ERR, "No suitable address found for creating a socket");
+ exit(1); // Exit with an error status
}
+
if (setgid(unpriv_gid) != 0) {
syslog(LOG_ERR, "setgid: %m");
exit(1);
@@ -278,6 +317,7 @@
} else {
receiver_process();
}
+ freeaddrinfo(servinfo);
}
static void
@@ -336,14 +376,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,6 +402,12 @@
syslog(LOG_ERR, "cap_enter: %m");
exit(1);
}
+ error = getnameinfo(sa, sizeof(*sa), host, NI_MAXHOST, service, NI_MAXSERV, NI_NUMERICHOST | NI_NUMERICSERV); // Get address and port of us
+ if (error) {
+ const char *error_message = gai_strerror(error);
+ syslog(LOG_ERR, "getnameinfo: %s", error_message);
+ exit(1);
+ }
for (;;) {
cc = recvfrom(s, &wd, sizeof(wd), 0, (struct sockaddr *)&from,
&len);
@@ -370,14 +416,20 @@
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) {
+ const char *error_message = gai_strerror(error);
+ syslog(LOG_ERR, "getnameinfo: %s", error_message);
+ exit(1);
+ }
+ if (strcmp(service, service_from) && !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 +438,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);
@@ -497,13 +549,31 @@
* 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:
+ if (setsockopt(s, IPPROTO_IPV6,
+ IPV6_MULTICAST_IF,
+ &(((struct sockaddr_in6*)np->n_addr)->sin6_addr),
+ sizeof(struct in6_addr)) < 0) {
+ syslog(LOG_ERR,
+ "setsockopt IPV6_MULTICAST_IF: %m");
+ exit(1);
+ }
+ break;
+#endif
}
(void) sendto(s, (char *)&mywd, cc, 0,
(struct sockaddr *)&multicast_addr,
@@ -579,42 +649,82 @@
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;
-
- 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);
- }
- 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);
+ switch (sa->sa_family) {
+#ifdef INET
+ case AF_INET:
+ if (multicast_mode != NO_MULTICAST) {
+ struct sockaddr_in tmp;
+ tmp.sin_family = AF_INET;
+ tmp.sin_addr.s_addr = htonl(INADDR_WHOD_GROUP);
+ tmp.sin_port = ((struct sockaddr_in *)(sa))->sin_port;
+ struct sockaddr *tmp2 = (struct sockaddr *)&tmp;
+ memcpy(&multicast_addr, tmp2, sizeof(multicast_addr));
+ }
+ if (multicast_mode == SCOPED_MULTICAST) {
+ struct ip_mreq mreq;
+ 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);
+ }
+ 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);
+ }
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ if (multicast_mode != NO_MULTICAST) {
+ struct sockaddr_in6 tmp;
+ tmp.sin6_family = AF_INET6;
+ inet_pton(AF_INET6, IN6ADDR_WHOD_GROUP, &(tmp.sin6_addr));
+ tmp.sin6_port = ((struct sockaddr_in6 *)(sa))->sin6_port;
+ struct sockaddr *tmp2 = (struct sockaddr *)&tmp;
+ memcpy(&multicast_addr, tmp2, sizeof(multicast_addr));
+ }
+ if (multicast_mode == SCOPED_MULTICAST) {
+ struct ipv6_mreq mreq;
+ unsigned char ttl;
+ inet_pton(AF_INET6, IN6ADDR_WHOD_GROUP, &mreq.ipv6mr_multiaddr);
+ mreq.ipv6mr_interface = 0;
+ if (setsockopt(so, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq,
+ sizeof(mreq)) < 0) {
+ syslog(LOG_ERR,
+ "setsockopt IPV6_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] = sa->sa_family;
mib[4] = NET_RT_IFLIST;
mib[5] = 0;
if (sysctl(mib, nitems(mib), NULL, &needed, NULL, 0) < 0)
@@ -649,15 +759,38 @@
/* 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 != sa->sa_family)
continue;
- PORT_SA(dstaddr) = sp->s_port;
+ switch (dstaddr->sa_family) {
+#ifdef INET
+ case AF_INET:
+ PORT_SA(dstaddr) = PORT_SA(sa);
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ PORT_SA6(dstaddr) = PORT_SA6(sa);
+ break;
+#endif
+ }
+ error = getnameinfo(dstaddr, sizeof(*dstaddr), host_dst, NI_MAXHOST, NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV);
+ if (error) {
+ const char *error_message = gai_strerror(error);
+ syslog(LOG_ERR, "getnameinfo: %s", error_message);
+ exit(1);
+ }
for (np = neighbors; np != NULL; np = np->n_next) {
+ error = getnameinfo(np->n_addr, sizeof(*np->n_addr), host_np, NI_MAXHOST, NULL, 0, NI_NUMERICHOST | NI_NUMERICSERV);
+ if (error) {
+ const char *error_message = gai_strerror(error);
+ syslog(LOG_ERR, "getnameinfo: %s", error_message);
+ 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)) {
break;
}
}
@@ -677,23 +810,57 @@
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 (sa->sa_family) {
+#ifdef INET
+ case AF_INET: {
+ 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");
#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: {
+ struct ipv6_mreq mreq6;
+ memcpy((char *)np->n_addr, (char *)ifaddr,
+ np->n_addrlen);
+
+ inet_pton(AF_INET6, IN6ADDR_WHOD_GROUP,
+ &mreq6.ipv6mr_multiaddr);
+ mreq6.ipv6mr_interface = 0;
+ if (setsockopt(s, IPPROTO_IPV6, IPV6_JOIN_GROUP,
+ (const char *)&mreq6,
+ sizeof(mreq6)) < 0) {
+ syslog(LOG_ERR,
+ "setsockopt IPV6_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

Mime Type
text/plain
Expires
Sat, May 23, 3:39 PM (9 h, 11 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
33448997
Default Alt Text
D45123.id.diff (13 KB)

Event Timeline