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>