Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F154343815
D21826.id.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D21826.id.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D21826: Proceeding to make rwhod ipv6 clean.
Attached
Detach File
Event Timeline
Log In to Comment