[systemd-devel] [PATCH 4/6] make in_addr_from_string() accept ipv4 addresses even when using AF_INET6

Shawn Landden shawn at churchofgit.com
Sun Mar 15 13:43:51 PDT 2015


On Sun, Mar 15, 2015 at 1:36 PM, Zbigniew Jędrzejewski-Szmek <
zbyszek at in.waw.pl> wrote:

> On Sun, Mar 15, 2015 at 01:28:05PM -0700, Shawn Landden wrote:
> > On Sun, Mar 15, 2015 at 1:07 PM, Zbigniew Jędrzejewski-Szmek <
> > zbyszek at in.waw.pl> wrote:
> >
> > > On Wed, Mar 11, 2015 at 08:13:47AM -0700, Shawn Landden wrote:
> > > > if we are going to have a function to fix up the deficiencies of
> > > > inet_pton(), better go all the way.
> > > > ---
> > > >  src/shared/in-addr-util.c | 17 +++++++++++++++++
> > > >  src/shared/in-addr-util.h |  1 +
> > > >  2 files changed, 18 insertions(+)
> > > >
> > > > diff --git a/src/shared/in-addr-util.c b/src/shared/in-addr-util.c
> > > > index ade4012..b7532a6 100644
> > > > --- a/src/shared/in-addr-util.c
> > > > +++ b/src/shared/in-addr-util.c
> > > > @@ -206,7 +206,18 @@ int in_addr_to_string(int family, const union
> > > in_addr_union *u, char **ret) {
> > > >          return 0;
> > > >  }
> > > >
> > > > +struct in6_addr in_addr_to_in6_addr(struct in_addr ipv4) {
> > > > +        struct in6_addr r = { { {
> > > > +                0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF, 0, 0, 0, 0
> > > > +        } } };
> > > > +
> > > > +        r.s6_addr32[3] = ipv4.s_addr;
> > > > +
> > > > +        return r;
> > > > +}
> > > > +
> > > >  int in_addr_from_string(int family, const char *s, void *ret) {
> > > > +        struct in_addr v4mapped;
> > > >
> > > >          assert(s);
> > > >          assert(ret);
> > > > @@ -214,6 +225,12 @@ int in_addr_from_string(int family, const char
> *s,
> > > void *ret) {
> > > >          if (!IN_SET(family, AF_INET, AF_INET6))
> > > >                  return -EAFNOSUPPORT;
> > > >
> > > > +        if (family == AF_INET6)
> > > > +                if (inet_pton(AF_INET, s, &v4mapped) == 1) {
> > > > +                        *((struct in6_addr *)ret) =
> > > in_addr_to_in6_addr(v4mapped);
> > > > +                        return 0;
> > > > +                }
> > > > +
> > > Hm, IIUC, an ipv6 address was specified, but the user gave an ipv4
> address.
> > > Automatically converting seems like a way to entice confusion...
> > >
> > > Except that the linux kernel supports binding to ipv4 this way, (see
> > ipv6(7)).
> >
> > In the inet_pton man page:
> >
> > BUGS
> >        AF_INET6 does not recognize IPv4 addresses.  An explicit
> IPv4-mapped
> > IPv6 address must be supplied in src instead.
> Right, but looking at how in_addr_from_string is used, we usually call it
> with an explicit family, and if it parses as ipv4, assume the family is
> ipv4,
> otherwise parse it as ipv6. So your change would either be a noop (if
> the check for ipv4 syntax was already done before), or would mess up this
> detection.
>
> What scenario are you trying to solve?
>
> nothing is particular, I was just trying to give myself a reason not to
refactor these to just call inet_pton() directly as without this change the
wrapper function does nothing except check for NULL.

> Zbyszek
>
> >
> >
> > Zbyszek
> > >
> > > >          errno = 0;
> > > >          if (inet_pton(family, s, ret) <= 0)
> > > >                  return errno ? -errno : -EINVAL;
> > > > diff --git a/src/shared/in-addr-util.h b/src/shared/in-addr-util.h
> > > > index 8b3a07c..f140ec9 100644
> > > > --- a/src/shared/in-addr-util.h
> > > > +++ b/src/shared/in-addr-util.h
> > > > @@ -37,6 +37,7 @@ int in_addr_equal(int family, const union
> > > in_addr_union *a, const union in_addr_
> > > >  int in_addr_prefix_intersect(int family, const union in_addr_union
> *a,
> > > unsigned aprefixlen, const union in_addr_union *b, unsigned
> bprefixlen);
> > > >  int in_addr_prefix_next(int family, union in_addr_union *u, unsigned
> > > prefixlen);
> > > >  int in_addr_to_string(int family, const union in_addr_union *u, char
> > > **ret);
> > > > +struct in6_addr in_addr_to_in6_addr(struct in_addr ipv4) _const_;
> > > >  int in_addr_from_string(int family, const char *s, void *ret);
> > > >  int in_addr_from_string_auto(const char *s, int *family, union
> > > in_addr_union *ret);
> > > >  unsigned char in_addr_netmask_to_prefixlen(const struct in_addr
> *addr);
> > > > --
> > > > 2.2.1.209.g41e5f3a
> > > >
> > > > _______________________________________________
> > > > systemd-devel mailing list
> > > > systemd-devel at lists.freedesktop.org
> > > > http://lists.freedesktop.org/mailman/listinfo/systemd-devel
> > > _______________________________________________
> > > systemd-devel mailing list
> > > systemd-devel at lists.freedesktop.org
> > > http://lists.freedesktop.org/mailman/listinfo/systemd-devel
> > >
> >
> >
> >
> > --
> > Shawn Landden
> _______________________________________________
> systemd-devel mailing list
> systemd-devel at lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/systemd-devel
>



-- 
Shawn Landden
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.freedesktop.org/archives/systemd-devel/attachments/20150315/19ddd1d4/attachment-0001.html>


More information about the systemd-devel mailing list