Page MenuHomeFreeBSD

D21826.id.diff
No OneTemporary

D21826.id.diff

Index: usr.sbin/rwhod/rwhod.c
===================================================================
--- usr.sbin/rwhod/rwhod.c
+++ usr.sbin/rwhod/rwhod.c
@@ -88,17 +88,36 @@
#define MAX_MULTICAST_SCOPE 32 /* "site-wide", by convention */
+
+/*
+ * Note that 224.0.1.3(ipv4) and FF0X::103(ipv6) are reserved for
+ * rwhod. In case of ipv6, X defines the scope.
+ * We use X=5 because 5 is for site-local scope.
+ */
+
#define INADDR_WHOD_GROUP (u_long)0xe0000103 /* 224.0.1.3 */
/* (belongs in protocols/rwhod.h) */
+#define IN6ADDR_WHOD_GROUP_INIT \
+ {{{ 0xff, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03 }}} /* ff05::103 */
+
+const struct in6_addr in6addr_whod_group = IN6ADDR_WHOD_GROUP_INIT;
+
+int enable_v4 = 0;
+int enable_v6 = 0;
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_in6 multicast_addr6 =
+ { sizeof(multicast_addr6), AF_INET6, 0, 0, {{{0}}}, 0 };
+
/*
* Sleep interval. Don't forget to change the down time check in ruptime
* if this is changed.
@@ -120,9 +139,9 @@
int n_flags; /* should forward?, interface flags */
};
-struct neighbor *neighbors;
+struct neighbor *neighbors = NULL;
struct whod mywd;
-struct servent *sp;
+in_port_t whod_port;
int s;
int fdp;
pid_t pid_child_receiver;
@@ -178,9 +197,9 @@
int
main(int argc, char *argv[])
{
- int on;
- char *cp;
- struct sockaddr_in soin;
+ int on, err, ch;
+ char *cp, *endptr;
+ struct addrinfo hints, *res;
uid_t unpriv_uid;
gid_t unpriv_gid;
@@ -190,46 +209,77 @@
run_as(&unpriv_uid, &unpriv_gid);
- argv++;
- argc--;
- while (argc > 0 && *argv[0] == '-') {
- if (strcmp(*argv, "-m") == 0) {
- if (argc > 1 && isdigit(*(argv + 1)[0])) {
- argv++;
- argc--;
+ while ((ch = getopt(argc, argv, "46ilpm::")) != -1)
+ switch (ch) {
+ case '4':
+ enable_v4 = 1;
+ break;
+ case '6':
+ enable_v6 = 1;
+ break;
+ case 'i':
+ insecure_mode = 1;
+ break;
+ case 'l':
+ quiet_mode = 1;
+ break;
+ case 'p':
+ iff_flag = 0;
+ break;
+ case 'm':
+ if (optarg != NULL) {
multicast_mode = SCOPED_MULTICAST;
- multicast_scope = atoi(*argv);
- if (multicast_scope > MAX_MULTICAST_SCOPE) {
+ multicast_scope = (int)strtol(optarg, &endptr, 10);
+ if (*endptr != '\0') {
+ errx(1, "invalid ttl: %s", endptr);
+ } else if (multicast_scope > MAX_MULTICAST_SCOPE) {
errx(1, "ttl must not exceed %u",
MAX_MULTICAST_SCOPE);
}
} else {
multicast_mode = PER_INTERFACE_MULTICAST;
}
- } else if (strcmp(*argv, "-i") == 0) {
- insecure_mode = 1;
- } else if (strcmp(*argv, "-l") == 0) {
- quiet_mode = 1;
- } else if (strcmp(*argv, "-p") == 0) {
- iff_flag = 0;
- } else {
+ break;
+ case '?':
+ default:
usage();
}
- argv++;
- argc--;
- }
- if (argc > 0)
- usage();
+
+ argc -= optind;
+ argv += optind;
+
+ /* if neither -4 nor -6 was specified, enable both */
+ if (enable_v4 == 0 && enable_v6 == 0)
+ enable_v4 = enable_v6 = 1;
+
#ifndef DEBUG
daemon(1, 0);
#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_protocol = IPPROTO_UDP;
+ if (enable_v6 == 1)
+ hints.ai_family = AF_INET6;
+ else
+ hints.ai_family = AF_INET;
+ hints.ai_socktype = SOCK_DGRAM;
+
+ err = getaddrinfo(NULL, "who", &hints, &res);
+ if (err != 0) {
+ syslog(LOG_ERR, "who/udp: %s", gai_strerror(err));
exit(1);
}
+
+ if (res->ai_family == AF_INET6) {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)res->ai_addr;
+ whod_port = htons(sin6->sin6_port);
+ } else if (res->ai_family == AF_INET) {
+ struct sockaddr_in *sin = (struct sockaddr_in *)res->ai_addr;
+ whod_port = htons(sin->sin_port);
+ }
+
if (chdir(_PATH_RWHODIR) < 0) {
syslog(LOG_ERR, "%s: %m", _PATH_RWHODIR);
exit(1);
@@ -245,22 +295,29 @@
*cp = '\0';
strlcpy(mywd.wd_hostname, myname, sizeof(mywd.wd_hostname));
getboottime(0);
- if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+
+ if ((s = socket(res->ai_family, res->ai_socktype, 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);
- }
- 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) {
+
+ /*
+ * ipv6 doesn't support broadcast, but maybe
+ * multicast at FF02::1 can be used, 2 being scope for link-local
+ */
+ if (enable_v6 == 0)
+ if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) {
+ syslog(LOG_ERR, "setsockopt SO_BROADCAST: %m");
+ exit(1);
+ }
+
+ if (bind(s, res->ai_addr, res->ai_addrlen) < 0) {
syslog(LOG_ERR, "bind: %m");
exit(1);
}
+
+ freeaddrinfo(res);
+
if (setgid(unpriv_gid) != 0) {
syslog(LOG_ERR, "setgid: %m");
exit(1);
@@ -299,7 +356,7 @@
usage(void)
{
- fprintf(stderr, "usage: rwhod [-i] [-p] [-l] [-m [ttl]]\n");
+ fprintf(stderr, "usage: rwhod [-4] [-6] [-i] [-p] [-l] [-m [ttl]]\n");
exit(1);
}
@@ -351,7 +408,7 @@
void
receiver_process(void)
{
- struct sockaddr_in from;
+ struct sockaddr_storage from;
struct stat st;
cap_rights_t rights;
char path[64];
@@ -360,6 +417,7 @@
socklen_t len;
int cc, whod;
time_t t;
+ char ip[INET6_ADDRSTRLEN];
len = sizeof(from);
dirfd = open(".", O_RDONLY | O_DIRECTORY);
@@ -385,14 +443,26 @@
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));
- continue;
+ if (from.ss_family == AF_INET) {
+ struct sockaddr_in *sin = (struct sockaddr_in *)&from;
+ if (sin->sin_port != whod_port && !insecure_mode) {
+ syslog(LOG_WARNING, "%d: bad source port from %s",
+ ntohs(sin->sin_port),
+ inet_ntop(from.ss_family, &(sin->sin_addr), ip, sizeof(ip)));
+ continue;
+ }
+ } else if (from.ss_family == AF_INET6) {
+ struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&from;
+ if (sin6->sin6_port != whod_port && !insecure_mode) {
+ syslog(LOG_WARNING, "%d: bad source port from %s",
+ ntohs(sin6->sin6_port),
+ inet_ntop(from.ss_family, &(sin6->sin6_addr), ip, sizeof(ip)));
+ continue;
+ }
}
+
if (cc < WHDRSIZE) {
- syslog(LOG_WARNING, "short packet from %s",
- inet_ntoa(from.sin_addr));
+ syslog(LOG_WARNING, "short packet from %s", ip);
continue;
}
if (wd.wd_vers != WHODVERSION)
@@ -400,8 +470,7 @@
if (wd.wd_type != WHODTYPE_STATUS)
continue;
if (!verify(wd.wd_hostname, sizeof(wd.wd_hostname))) {
- syslog(LOG_WARNING, "malformed host name from %s",
- inet_ntoa(from.sin_addr));
+ syslog(LOG_WARNING, "malformed host name from %s", ip);
continue;
}
(void) snprintf(path, sizeof(path), "whod.%s", wd.wd_hostname);
@@ -600,30 +669,63 @@
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 (enable_v4 == 1) {
+ multicast_addr.sin_addr.s_addr = htonl(INADDR_WHOD_GROUP);
+ multicast_addr.sin_port = whod_port;
+ }
+ if (enable_v6 == 1) {
+ multicast_addr6.sin6_addr = in6addr_whod_group;
+ multicast_addr6.sin6_port = whod_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);
+
+ if (enable_v4 == 1) {
+ struct ip_mreq mreq;
+ uint8_t 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);
}
- 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);
+ if (enable_v6 == 1) {
+ struct ipv6_mreq mreq6;
+ uint8_t hops;
+
+ mreq6.ipv6mr_multiaddr = in6addr_whod_group;
+ mreq6.ipv6mr_interface = 0; /* choose default multicast interface, same as above in ipv4*/
+
+ if (setsockopt(so, IPPROTO_IPV6, IPV6_JOIN_GROUP,
+ &mreq6, sizeof(mreq6)) < 0) {
+ syslog(LOG_ERR,
+ "setsockopt IPV6_ADD_MEMBERSHIP: %m");
+ return (0);
+ }
+ hops = multicast_scope;
+ if (setsockopt(so, IPPROTO_IP, IPV6_MULTICAST_HOPS, &hops,
+ sizeof(hops)) < 0) {
+ syslog(LOG_ERR,
+ "setsockopt IPV6_MULTICAST_HOPS: %m");
+ return (0);
+ }
+ return (1);
}
- return (1);
+ //assert(enable_ipv4 == 1 || enable_ipv6 == 1);
}
mib[0] = CTL_NET;
@@ -668,7 +770,7 @@
#define PORT_SA(x) ((struct sockaddr_in *)(x))->sin_port
if (dstaddr == 0 || dstaddr->sa_family != AF_INET)
continue;
- PORT_SA(dstaddr) = sp->s_port;
+ PORT_SA(dstaddr) = whod_port;
for (np = neighbors; np != NULL; np = np->n_next) {
if (memcmp(sdl->sdl_data, np->n_name,
sdl->sdl_nlen) == 0 &&

File Metadata

Mime Type
text/plain
Expires
Tue, Apr 28, 11:47 PM (6 h, 20 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
32312684
Default Alt Text
D21826.id.diff (9 KB)

Event Timeline