Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 09 Dec 2015 23:35:15 +0900 (JST)
From:      Hiroki Sato <hrs@FreeBSD.org>
To:        ken@pcbsd.org
Cc:        freebsd-net@freebsd.org
Subject:   Re: IPv6 Address as text (C)
Message-ID:  <20151209.233515.1592617248580059512.hrs@allbsd.org>
In-Reply-To: <5668369F.9020309@pcbsd.org>
References:  <5668369F.9020309@pcbsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help
----Security_Multipart(Wed_Dec__9_23_35_15_2015_181)--
Content-Type: Text/Plain; charset=us-ascii
Content-Transfer-Encoding: 7bit

Ken Moore <ken@pcbsd.org> wrote
  in <5668369F.9020309@pcbsd.org>:

ke> Note: Please CC me on replies - I am not subscribed to this list.
ke>
ke> I am having a bit of trouble getting an accurate string representation
ke> of the current IPv6 address for a given device using the C system
ke> libraries and was wondering of somebody with more experience than me
ke> might be able to spot the error...
ke>
ke> Background:
ke> I have been working on a couple simple C/C++/Qt functions to return
ke> printable forms of the current ipv4 and ipv6 addresses assigned to a
ke> particular device, and while the ipv4 function works fine the ipv6
ke> address is consistently wrong and almost always the same string -
ke> making me think it is converting some internal error code to a string
ke> ("::XXe2:ffff:ff7f:0" where the "X"s are the only two characters which
ke> ever change).
ke>
ke> The two functions are nearly identical, and I think the error probably
ke> comes from needing to use inet_ntop() for the ipv6 address because
ke> there is no ipv6-compatible version of the inet_ntoa() function.
ke> Do you have any thoughts or ideas about where the error might be
ke> coming from or a better way to read off the ipv6 address as a string?
ke>
ke> Here are the two functions:
ke> Note: "name" is the QString of the device name (wlan0, re0, other...),
ke> and is an internal variable for the overall "NetDevice" class
ke> [code]
ke> //Fetch the IPv4 address and return it as a QString
ke> QString NetDevice::ipAsString(){
ke>    struct ifreq ifr;
ke>    memset(&ifr, 0, sizeof(struct ifreq));
ke>
ke>    strncpy(ifr.ifr_name, name.toLocal8Bit(), IFNAMSIZ);
ke>    int s = socket(PF_INET, SOCK_DGRAM, 0);
ke>
ke>    ioctl(s, SIOCGIFADDR, &ifr);
ke>    struct in_addr in = ((sockaddr_in *) &ifr.ifr_addr)->sin_addr;
ke>
ke>    return QString( inet_ntoa(in) );
ke> }
ke>
ke> //Fetch the IPv6 address and return it as a QString
ke> QString NetDevice::ipv6AsString(){
ke>    struct ifreq ifr;
ke>    memset(&ifr, 0, sizeof(struct ifreq));
ke>
ke>    strncpy(ifr.ifr_name, name.toLocal8Bit(), IFNAMSIZ);
ke>    int s = socket(PF_INET6, SOCK_DGRAM, 0);
ke>
ke>    ioctl(s, SIOCGIFADDR, &ifr);

 Should this be SIOCGIFADDR_IN6 here?  You should check the error
 code.

 Anyway, you should use getnameinfo() for IPv4 and IPv6 instead of
 inet_ntop() and inet_ntoa() for this purpose.  It is an address
 family independent API which accepts struct sockaddr directly like
 this:

----
  struct sockaddr *sa; /* input */
  char hbuf[NI_MAXHOST];
  int error;

  error = getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL,
      0, NI_NUMERICHOST);
  if (error) {
           errx(1, "getnameinfo: %s", gai_strerror(error));
           /* NOTREACHED */
  }
  printf("host=%s\n", hbuf);
----

 See getnameinfo(3) for more details.

-- Hiroki

----Security_Multipart(Wed_Dec__9_23_35_15_2015_181)--
Content-Type: application/pgp-signature
Content-Transfer-Encoding: 7bit

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1

iEYEABECAAYFAlZoPCMACgkQTyzT2CeTzy017QCgg0p18C2ZOOd5fyAbWJ0WKzOo
DwkAnAm4cZlrHuFM/V8IYm9zGtCazqrC
=04D0
-----END PGP SIGNATURE-----

----Security_Multipart(Wed_Dec__9_23_35_15_2015_181)----



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20151209.233515.1592617248580059512.hrs>