nnrpd -D and IPv6 (was Re: Joint is better than Panzerfaust)
Jeffrey M. Vinocur
jeff at puck.litech.org
Sun Sep 15 05:11:49 UTC 2002
The below patch was hiding in news.software.nntp (I almost missed
it, as there was a bunch of non-INN-related stuff at the top of
the article). I ran this by Nathan (who did some of the IPv6
stuff in CURRENT), and he says if it does actually make something
work that was broken, might as well.
But I don't use nnrpd -D, and so have no way to test this, and
don't know the IPv6 code well enough to do it by inspection. So
I figured I'd at least make sure it got full light of day and
hope somebody else would run with it.
In article <000OOOOOO0 at news.radio.cz> Barry wrote:
>
>[...]
>
>Methinks this discussion is best at home in alt.binaries.news-swerver-
>consumption, but I hesitate to attempt a followup there in case the
>mail2news gateway rejects this for policy reasons against potential
>abuse. So, to try and be marginally on-topic in the other froup too,
>here's a quick and ugly (and not comprehensive) patch I've come up with --
>it can fail misleadingly for invalid IPv6 addresses, for example, and
>was intended purely to get daemon mode to work without taking the
>time to do it right, since I have no clue whatsoever what I'm doing:
>
>
>--- nnrpd.c-DIST Fri Aug 2 17:37:52 2002
>+++ nnrpd.c Wed Sep 11 08:43:48 2002
>@@ -842,11 +842,13 @@
> socklen_t clen;
> #ifdef HAVE_INET6
> struct sockaddr_storage ssa, csa;
>- struct sockaddr_in6 *ssa6 = (struct sockaddr_in6 *) &ssa;
>+ /* `ssa' is no longer used itself, but I'm too lazy to remove it */
>+ struct sockaddr_in6 ssa6;
> #else
> struct sockaddr_in ssa, csa;
> #endif
>- struct sockaddr_in *ssa4 = (struct sockaddr_in *) &ssa;
>+ /* ditto about ssa */
>+ struct sockaddr_in ssa4;
> struct stat Sb;
> pid_t pid = -1;
> gid_t NewsGID;
>@@ -986,23 +988,32 @@
> if (DaemonMode) {
>
> #ifdef HAVE_INET6
>- memset(&ssa, '\0', sizeof(struct sockaddr_in6));
>- ssa6->sin6_family = AF_INET6;
>- ssa6->sin6_port = htons(ListenPort);
>- if (inet_pton(AF_INET6, ListenAddr, ssa6->sin6_addr.s6_addr) > 0) {
>- if ( (lfd = socket(AF_INET6, SOCK_STREAM, 0)) < 0) {
>+ /* memset ssa6 separately instead */
>+ memset(&ssa6, 0, sizeof ssa6);
>+ ssa6.sin6_family = AF_INET6;
>+ ssa6.sin6_port = htons(ListenPort);
>+#ifdef HAVE_SOCKADDR_LEN
>+ ssa6.sin6_len = sizeof ssa6;
>+#endif
>+ if (inet_pton(AF_INET6, ListenAddr, &ssa6.sin6_addr) > 0) {
>+ /* gratuitous changes to match inndstart */
>+ if ( (lfd = socket(PF_INET6, SOCK_STREAM, 0)) < 0) {
> syslog(L_FATAL, "can't open socket (%m)");
> exit(1);
> }
> }
> else {
> #endif
>- memset(&ssa, '\0', sizeof(struct sockaddr_in));
>- ssa4->sin_family = AF_INET;
>- ssa4->sin_port = htons(ListenPort);
>- if (inet_aton(ListenAddr, &ssa4->sin_addr) <= 0 )
>- ssa4->sin_addr.s_addr = htonl(INADDR_ANY);
>- if ( (lfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
>+ /* see comment above, here we whack ssa4 */
>+ memset(&ssa4, 0, sizeof(struct sockaddr_in));
>+ ssa4.sin_family = AF_INET;
>+ ssa4.sin_port = htons(ListenPort);
>+#ifdef HAVE_SOCKADDR_LEN
>+ ssa4.sin_len = sizeof ssa4;
>+#endif
>+ if (inet_aton(ListenAddr, &ssa4.sin_addr) <= 0 )
>+ ssa4.sin_addr.s_addr = htonl(INADDR_ANY);
>+ if ( (lfd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
> syslog(L_FATAL, "can't open socket (%m)");
> exit(1);
> }
>@@ -1016,11 +1027,21 @@
> exit(1);
> }
>
>- if (bind(lfd, (struct sockaddr *) &ssa, sizeof(ssa)) < 0) {
>+ /* Ugly. Try to bind ssa6 whether or not ListenAddr really is IPv6 */
>+#ifdef HAVE_INET6
>+ if (bind(lfd, (struct sockaddr *) &ssa6, sizeof(ssa6)) < 0) {
>+ /* If this fails for *any* reason, not just if it's IPv4, then
>+ try that, possibly concealing the real failure... */
>+#endif
>+ if (bind(lfd, (struct sockaddr *) &ssa4, sizeof(ssa4)) < 0) {
> fprintf(stderr, "%s: can't bind (%s)\n", argv[0], strerror(errno));
> syslog(L_FATAL, "can't bind local address (%m)");
> exit(1);
>+ }
>+#ifdef HAVE_INET6
>+ /* But hey, if HAVE_INET6 was defined, things had been t0taL B0rkeD */
> }
>+#endif
>
> /* If started as root, switch to news uid */
> if (getuid() == 0) {
>
>
>I mean, it just didn't work at all before, but now it does, though
>not perfectly. What more could I ask for? Okay, yes, that too.
--
Jeffrey M. Vinocur
jeff at litech.org
More information about the inn-workers
mailing list