<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Mon, Mar 9, 2015 at 1:18 PM, Lennart Poettering <span dir="ltr"><<a href="mailto:lennart@poettering.net" target="_blank">lennart@poettering.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex"><span class="">On Mon, 09.03.15 13:09, Shawn Landden (<a href="mailto:shawn@churchofgit.com">shawn@churchofgit.com</a>) wrote:<br>
<br>
> +        if (UNIT_DEREF(s->accept_socket)) {<br>
> +                union sockaddr_union sa;<br>
> +                socklen_t salen = sizeof(sa);<br>
> +<br>
> +                r = getpeername(s->socket_fd, &<a href="http://sa.sa" target="_blank">sa.sa</a>, &salen);<br>
> +                if (r < 0) {<br>
> +                        r = -errno;<br>
> +                        goto fail;<br>
> +                }<br>
> +<br>
> +                if (sa.sa.sa_family == AF_INET ||<br>
> +                    sa.sa.sa_family == AF_INET6) {<br>
> +                        _cleanup_free_ char *addr = NULL;<br>
> +                        uint16_t port = (uint16_t)sockaddr_port(&sa);<br>
<br>
</span>We try to avoid invoking functions in the same lines as we declare<br>
variables.<br>
<br>
Also, even though this cannot fail in this case, I think it would be<br>
nicer, to make port an int, and check for < 0 and return an error in<br>
that case...<br>
<span class=""><br>
> +<br>
> +                        r = sockaddr_pretty(&<a href="http://sa.sa" target="_blank">sa.sa</a>, salen, true, false, &addr);<br>
> +                        if (r < 0)<br>
> +                                goto fail;<br>
> +<br>
> +                        if (!(our_env[n_env++] = strappend("REMOTE_ADDR=", addr))) {<br>
<br>
</span>In newer code we try to avoid making assignments and doing if checks<br>
in the same line.<br>
<span class=""><br>
><br>
> -int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_ipv6, char **ret) {<br>
> +int sockaddr_port(const union sockaddr_union *sa) {<br>
> +        assert_return(sa->sa.sa_family == AF_INET6 ||<br>
> +                      sa->sa.sa_family == AF_INET,<br>
> +                      -ENOTSUP);<br>
<br>
</span>assert_return() is a macro to use only for cases where there's a clear<br>
programming error of the caller. But I am pretty sure that this is not<br>
the case here. If it gets called on an non-AF_INET/AF_INET6 socket<br>
then this should fail without logging.<br>
<br>
Also I think an error code of EAFNOSUPPORT would be more appropriate.<br>
<br>
Hmm, and I think this should probably take an actual "struct<br>
sockaddr", rather than a union sockaddr_union...<br>
<div><div class="h5"><br>
> @@ -475,42 +485,40 @@ int sockaddr_pretty(const struct sockaddr *_sa, socklen_t salen, bool translate_<br>
><br>
>          switch (sa->sa.sa_family) {<br>
><br>
> -        case AF_INET: {<br>
> -                uint32_t a;<br>
> -<br>
> -                a = ntohl(sa->in.sin_addr.s_addr);<br>
> -<br>
> -                if (asprintf(&p,<br>
> -                             "%u.%u.%u.%u:%u",<br>
> -                             a >> 24, (a >> 16) & 0xFF, (a >> 8) & 0xFF, a & 0xFF,<br>
> -                             ntohs(sa->in.sin_port)) < 0)<br>
> -                        return -ENOMEM;<br>
> -<br>
> -                break;<br>
> -        }<br>
> -<br>
> +        case AF_INET:<br>
>          case AF_INET6: {<br>
> -                static const unsigned char ipv4_prefix[] = {<br>
> -                        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF<br>
> -                };<br>
> -<br>
> -                if (translate_ipv6 && memcmp(&sa->in6.sin6_addr, ipv4_prefix, sizeof(ipv4_prefix)) == 0) {<br>
> -                        const uint8_t *a = sa->in6.sin6_addr.s6_addr+12;<br>
> +                char a[MAX(INET6_ADDRSTRLEN, INET_ADDRSTRLEN)];<br>
> +                const char *addr;<br>
> +                bool ipv4_mapped = false;<br>
> +<br>
> +                if (inet_ntop(sa->sa.sa_family,<br>
> +                              /* this field of the API is kinda braindead,<br>
> +                               * should take head of struct so it can be passed the union...*/<br>
> +                              sa->sa.sa_family == AF_INET6 ?<br>
> +                                &sa->in6.sin6_addr :<br>
> +                                &sa->in.sin_addr,<br>
> +                              a, sizeof(a)) == NULL)<br>
> +                      return -ENOMEM;<br>
> +<br>
> +                /* glibc inet_ntop() presents v4-mapped addresses in ::ffff:a.b.c.d form */<br>
> +                if (translate_ipv6 && sa->sa.sa_family == AF_INET6 && strchr(a, '.')) {<br>
> +                        ipv4_mapped = true;<br>
> +                        addr = strempty(startswith(a, "::ffff:"));<br>
<br>
</div></div>I think it would be a lot nicer to check the raw IP prefix as before,<br>
and only then format things, then first formatting and then looking at<br>
the string again.<br>
<br>
We shouldn't bind us too closely to the precise formatting. I mean, if<br>
one day libc decides to format the thing as ipv6 again, or with<br>
uppercase hex chars, we shouldn't break.<br></blockquote><div><a href="https://tools.ietf.org/html/rfc5952#section-4.3">https://tools.ietf.org/html/rfc5952#section-4.3</a> says lowercase-only</div><div><a href="https://tools.ietf.org/html/rfc5952#section-5">https://tools.ietf.org/html/rfc5952#section-5</a> specifies formatting of ipv4-mapped addresses</div><div><br></div><div>and it is significantly longer that way, but sure, I can do it that way. </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left-width:1px;border-left-color:rgb(204,204,204);border-left-style:solid;padding-left:1ex">
<span class=""><br>
> +                } else<br>
> +                        addr = &a[0];<br>
> +<br>
> +                if (include_port) {<br>
> +                        uint16_t port = (uint16_t)sockaddr_port(sa);<br>
<br>
</span>No function calls in variable declarations, please. Same rule as above applies.<br>
<div class=""><div class="h5">Lennart<br>
<br>
--<br>
Lennart Poettering, Red Hat<br>
_______________________________________________<br>
systemd-devel mailing list<br>
<a href="mailto:systemd-devel@lists.freedesktop.org">systemd-devel@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/systemd-devel" target="_blank">http://lists.freedesktop.org/mailman/listinfo/systemd-devel</a><br>
</div></div></blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature">Shawn Landden</div>
</div></div>