1f6074d74SHajimu UMEMOTO /* $KAME: getnameinfo.c,v 1.61 2002/06/27 09:25:47 itojun Exp $ */ 26cb94182SJun-ichiro itojun Hagino 38a16b7a1SPedro F. Giffuni /*- 48a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 58a16b7a1SPedro F. Giffuni * 67d56d374SYoshinobu Inoue * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. 767228c46SBruce M Simpson * Copyright (c) 2000 Ben Harris. 87d56d374SYoshinobu Inoue * All rights reserved. 97d56d374SYoshinobu Inoue * 107d56d374SYoshinobu Inoue * Redistribution and use in source and binary forms, with or without 117d56d374SYoshinobu Inoue * modification, are permitted provided that the following conditions 127d56d374SYoshinobu Inoue * are met: 137d56d374SYoshinobu Inoue * 1. Redistributions of source code must retain the above copyright 147d56d374SYoshinobu Inoue * notice, this list of conditions and the following disclaimer. 157d56d374SYoshinobu Inoue * 2. Redistributions in binary form must reproduce the above copyright 167d56d374SYoshinobu Inoue * notice, this list of conditions and the following disclaimer in the 177d56d374SYoshinobu Inoue * documentation and/or other materials provided with the distribution. 187d56d374SYoshinobu Inoue * 3. Neither the name of the project nor the names of its contributors 197d56d374SYoshinobu Inoue * may be used to endorse or promote products derived from this software 207d56d374SYoshinobu Inoue * without specific prior written permission. 217d56d374SYoshinobu Inoue * 227d56d374SYoshinobu Inoue * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 237d56d374SYoshinobu Inoue * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 247d56d374SYoshinobu Inoue * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 257d56d374SYoshinobu Inoue * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 267d56d374SYoshinobu Inoue * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 277d56d374SYoshinobu Inoue * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 287d56d374SYoshinobu Inoue * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 297d56d374SYoshinobu Inoue * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 307d56d374SYoshinobu Inoue * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 317d56d374SYoshinobu Inoue * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 327d56d374SYoshinobu Inoue * SUCH DAMAGE. 337d56d374SYoshinobu Inoue */ 347d56d374SYoshinobu Inoue 357d56d374SYoshinobu Inoue /* 367d56d374SYoshinobu Inoue * Issues to be discussed: 377d56d374SYoshinobu Inoue * - Thread safe-ness must be checked 386cb94182SJun-ichiro itojun Hagino * - RFC2553 says that we should raise error on short buffer. X/Open says 396cb94182SJun-ichiro itojun Hagino * we need to truncate the result. We obey RFC2553 (and X/Open should be 4045181a75SJun-ichiro itojun Hagino * modified). ipngwg rough consensus seems to follow RFC2553. 416cb94182SJun-ichiro itojun Hagino * - What is "local" in NI_FQDN? 426cb94182SJun-ichiro itojun Hagino * - NI_NAMEREQD and NI_NUMERICHOST conflict with each other. 4315e4dafcSHajimu UMEMOTO * - (KAME extension) always attach textual scopeid (fe80::1%lo0), if 4415e4dafcSHajimu UMEMOTO * sin6_scope_id is filled - standardization status? 4515e4dafcSHajimu UMEMOTO * XXX breaks backward compat for code that expects no scopeid. 4615e4dafcSHajimu UMEMOTO * beware on merge. 477d56d374SYoshinobu Inoue */ 487d56d374SYoshinobu Inoue 497d56d374SYoshinobu Inoue #include <sys/types.h> 507d56d374SYoshinobu Inoue #include <sys/socket.h> 51bb957021SHiroki Sato #include <sys/un.h> 527d56d374SYoshinobu Inoue #include <net/if.h> 5367228c46SBruce M Simpson #include <net/if_dl.h> 5467228c46SBruce M Simpson #include <net/if_types.h> 55823e5e0eSHajimu UMEMOTO #include <net/firewire.h> 567d56d374SYoshinobu Inoue #include <netinet/in.h> 577d56d374SYoshinobu Inoue #include <arpa/inet.h> 587d56d374SYoshinobu Inoue #include <arpa/nameser.h> 597d56d374SYoshinobu Inoue #include <netdb.h> 607d56d374SYoshinobu Inoue #include <resolv.h> 617d56d374SYoshinobu Inoue #include <string.h> 627d56d374SYoshinobu Inoue #include <stddef.h> 636cb94182SJun-ichiro itojun Hagino #include <errno.h> 647d56d374SYoshinobu Inoue 65bb957021SHiroki Sato static const struct afd *find_afd(int); 66bb957021SHiroki Sato static int getnameinfo_inet(const struct afd *, 67bb957021SHiroki Sato const struct sockaddr *, socklen_t, char *, 6867228c46SBruce M Simpson size_t, char *, size_t, int); 6967228c46SBruce M Simpson #ifdef INET6 7067228c46SBruce M Simpson static int ip6_parsenumeric(const struct sockaddr *, const char *, char *, 7167228c46SBruce M Simpson size_t, int); 7267228c46SBruce M Simpson static int ip6_sa2str(const struct sockaddr_in6 *, char *, size_t, int); 7367228c46SBruce M Simpson #endif 74bb957021SHiroki Sato static int getnameinfo_link(const struct afd *, 75bb957021SHiroki Sato const struct sockaddr *, socklen_t, char *, 7667228c46SBruce M Simpson size_t, char *, size_t, int); 7767228c46SBruce M Simpson static int hexname(const u_int8_t *, size_t, char *, size_t); 78bb957021SHiroki Sato static int getnameinfo_un(const struct afd *, 79bb957021SHiroki Sato const struct sockaddr *, socklen_t, char *, 80bb957021SHiroki Sato size_t, char *, size_t, int); 8167228c46SBruce M Simpson 82f6074d74SHajimu UMEMOTO static const struct afd { 837d56d374SYoshinobu Inoue int a_af; 841ccfa322SHajimu UMEMOTO size_t a_addrlen; 851ccfa322SHajimu UMEMOTO socklen_t a_socklen; 867d56d374SYoshinobu Inoue int a_off; 87bb957021SHiroki Sato int (*a_func)(const struct afd *, 88bb957021SHiroki Sato const struct sockaddr *, socklen_t, char *, 89bb957021SHiroki Sato size_t, char *, size_t, int); 907d56d374SYoshinobu Inoue } afdl [] = { 917d56d374SYoshinobu Inoue #ifdef INET6 927d56d374SYoshinobu Inoue {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6), 93bb957021SHiroki Sato offsetof(struct sockaddr_in6, sin6_addr), 94bb957021SHiroki Sato getnameinfo_inet}, 957d56d374SYoshinobu Inoue #endif 967d56d374SYoshinobu Inoue {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in), 97bb957021SHiroki Sato offsetof(struct sockaddr_in, sin_addr), 98bb957021SHiroki Sato getnameinfo_inet}, 99bb957021SHiroki Sato #define sizeofmember(type, member) (sizeof(((type *)0)->member)) 100bb957021SHiroki Sato {PF_LOCAL, sizeofmember(struct sockaddr_un, sun_path), 101bb957021SHiroki Sato sizeof(struct sockaddr_un), 102bb957021SHiroki Sato offsetof(struct sockaddr_un, sun_path), 103bb957021SHiroki Sato getnameinfo_un}, 104bb957021SHiroki Sato {PF_LINK, sizeofmember(struct sockaddr_dl, sdl_data), 105bb957021SHiroki Sato sizeof(struct sockaddr_dl), 106bb957021SHiroki Sato offsetof(struct sockaddr_dl, sdl_data), 107bb957021SHiroki Sato getnameinfo_link}, 1087d56d374SYoshinobu Inoue {0, 0, 0}, 1097d56d374SYoshinobu Inoue }; 1107d56d374SYoshinobu Inoue 111bb957021SHiroki Sato int 112bb957021SHiroki Sato getnameinfo(const struct sockaddr *sa, socklen_t salen, 11390d1d883SHajimu UMEMOTO char *host, size_t hostlen, char *serv, size_t servlen, 11490d1d883SHajimu UMEMOTO int flags) 1157d56d374SYoshinobu Inoue { 116f6074d74SHajimu UMEMOTO const struct afd *afd; 117bb957021SHiroki Sato 118bb957021SHiroki Sato if (sa == NULL) 119bb957021SHiroki Sato return (EAI_FAIL); 120bb957021SHiroki Sato 121bb957021SHiroki Sato afd = find_afd(sa->sa_family); 122bb957021SHiroki Sato if (afd == NULL) 123bb957021SHiroki Sato return (EAI_FAMILY); 12420d96999SHiroki Sato /* 12520d96999SHiroki Sato * getnameinfo() accepts an salen of sizeof(struct sockaddr_storage) 12620d96999SHiroki Sato * at maximum as shown in RFC 4038 Sec.6.2.3. 12720d96999SHiroki Sato */ 12820d96999SHiroki Sato if (salen > sizeof(struct sockaddr_storage)) 12920d96999SHiroki Sato return (EAI_FAMILY); 13020d96999SHiroki Sato 131c56e91b3SHiroki Sato switch (sa->sa_family) { 132c56e91b3SHiroki Sato case PF_LOCAL: 133bb957021SHiroki Sato /* 13420d96999SHiroki Sato * PF_LOCAL uses variable salen depending on the 135bb957021SHiroki Sato * content length of sun_path. Require 1 byte in 136bb957021SHiroki Sato * sun_path at least. 137bb957021SHiroki Sato */ 13820d96999SHiroki Sato if (salen <= afd->a_socklen - 139bb957021SHiroki Sato sizeofmember(struct sockaddr_un, sun_path)) 14020d96999SHiroki Sato return (EAI_FAMILY); 14120d96999SHiroki Sato else if (salen > afd->a_socklen) 14220d96999SHiroki Sato salen = afd->a_socklen; 143c56e91b3SHiroki Sato break; 144c56e91b3SHiroki Sato case PF_LINK: 145c56e91b3SHiroki Sato if (salen <= afd->a_socklen - 146c56e91b3SHiroki Sato sizeofmember(struct sockaddr_dl, sdl_data)) 14720d96999SHiroki Sato return (EAI_FAMILY); 148c56e91b3SHiroki Sato break; 149c56e91b3SHiroki Sato default: 15020d96999SHiroki Sato if (salen < afd->a_socklen) 15120d96999SHiroki Sato return (EAI_FAMILY); 15220d96999SHiroki Sato else 15320d96999SHiroki Sato salen = afd->a_socklen; 154c56e91b3SHiroki Sato break; 155c56e91b3SHiroki Sato } 156bb957021SHiroki Sato 157bb957021SHiroki Sato return ((*afd->a_func)(afd, sa, salen, host, hostlen, 158bb957021SHiroki Sato serv, servlen, flags)); 159bb957021SHiroki Sato } 160bb957021SHiroki Sato 161bb957021SHiroki Sato static const struct afd * 162bb957021SHiroki Sato find_afd(int af) 163bb957021SHiroki Sato { 164bb957021SHiroki Sato const struct afd *afd; 165bb957021SHiroki Sato 166bb957021SHiroki Sato if (af == PF_UNSPEC) 167bb957021SHiroki Sato return (NULL); 168bb957021SHiroki Sato for (afd = &afdl[0]; afd->a_af > 0; afd++) { 169bb957021SHiroki Sato if (afd->a_af == af) 170bb957021SHiroki Sato return (afd); 171bb957021SHiroki Sato } 172bb957021SHiroki Sato return (NULL); 173bb957021SHiroki Sato } 174bb957021SHiroki Sato 175bb957021SHiroki Sato static int 176bb957021SHiroki Sato getnameinfo_inet(const struct afd *afd, 177bb957021SHiroki Sato const struct sockaddr *sa, socklen_t salen, 178bb957021SHiroki Sato char *host, size_t hostlen, char *serv, size_t servlen, 179bb957021SHiroki Sato int flags) 180bb957021SHiroki Sato { 1817d56d374SYoshinobu Inoue struct servent *sp; 1827d56d374SYoshinobu Inoue struct hostent *hp; 1837d56d374SYoshinobu Inoue u_short port; 1846cb94182SJun-ichiro itojun Hagino const char *addr; 1856cb94182SJun-ichiro itojun Hagino u_int32_t v4a; 1867d56d374SYoshinobu Inoue int h_error; 1877d56d374SYoshinobu Inoue char numserv[512]; 1887d56d374SYoshinobu Inoue char numaddr[512]; 1897d56d374SYoshinobu Inoue 1906cb94182SJun-ichiro itojun Hagino /* network byte order */ 191bb957021SHiroki Sato port = ((const struct sockaddr_in *)sa)->sin_port; 1926cb94182SJun-ichiro itojun Hagino addr = (const char *)sa + afd->a_off; 1937d56d374SYoshinobu Inoue 1947d56d374SYoshinobu Inoue if (serv == NULL || servlen == 0) { 1956cb94182SJun-ichiro itojun Hagino /* 1966cb94182SJun-ichiro itojun Hagino * do nothing in this case. 1976cb94182SJun-ichiro itojun Hagino * in case you are wondering if "&&" is more correct than 198f6074d74SHajimu UMEMOTO * "||" here: rfc2553bis-03 says that serv == NULL OR 199f6074d74SHajimu UMEMOTO * servlen == 0 means that the caller does not want the result. 2006cb94182SJun-ichiro itojun Hagino */ 2017d56d374SYoshinobu Inoue } else { 2027d56d374SYoshinobu Inoue if (flags & NI_NUMERICSERV) 2037d56d374SYoshinobu Inoue sp = NULL; 2047d56d374SYoshinobu Inoue else { 2057d56d374SYoshinobu Inoue sp = getservbyport(port, 2067d56d374SYoshinobu Inoue (flags & NI_DGRAM) ? "udp" : "tcp"); 2077d56d374SYoshinobu Inoue } 2087d56d374SYoshinobu Inoue if (sp) { 20945181a75SJun-ichiro itojun Hagino if (strlen(sp->s_name) + 1 > servlen) 210f6074d74SHajimu UMEMOTO return EAI_MEMORY; 211d0509082SJacques Vidrine strlcpy(serv, sp->s_name, servlen); 2127d56d374SYoshinobu Inoue } else { 213f6074d74SHajimu UMEMOTO snprintf(numserv, sizeof(numserv), "%u", ntohs(port)); 21445181a75SJun-ichiro itojun Hagino if (strlen(numserv) + 1 > servlen) 215f6074d74SHajimu UMEMOTO return EAI_MEMORY; 216d0509082SJacques Vidrine strlcpy(serv, numserv, servlen); 2177d56d374SYoshinobu Inoue } 2187d56d374SYoshinobu Inoue } 2197d56d374SYoshinobu Inoue 2207d56d374SYoshinobu Inoue switch (sa->sa_family) { 2217d56d374SYoshinobu Inoue case AF_INET: 2226cb94182SJun-ichiro itojun Hagino v4a = (u_int32_t) 2236cb94182SJun-ichiro itojun Hagino ntohl(((const struct sockaddr_in *)sa)->sin_addr.s_addr); 2246c1c6ae5SRodney W. Grimes if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a) || 2256c1c6ae5SRodney W. Grimes IN_ZERONET(v4a)) 2267d56d374SYoshinobu Inoue flags |= NI_NUMERICHOST; 2277d56d374SYoshinobu Inoue break; 2287d56d374SYoshinobu Inoue #ifdef INET6 2297d56d374SYoshinobu Inoue case AF_INET6: 2307d56d374SYoshinobu Inoue { 2316cb94182SJun-ichiro itojun Hagino const struct sockaddr_in6 *sin6; 232*c179937bSBjoern A. Zeeb 2336cb94182SJun-ichiro itojun Hagino sin6 = (const struct sockaddr_in6 *)sa; 234*c179937bSBjoern A. Zeeb 235*c179937bSBjoern A. Zeeb /* 236*c179937bSBjoern A. Zeeb * https://pubs.opengroup.org/onlinepubs/9699919799/functions/getnameinfo.html 237*c179937bSBjoern A. Zeeb * "[IP6] [Option Start] If the socket address structure 238*c179937bSBjoern A. Zeeb * contains an IPv4-mapped IPv6 address or an IPv4-compatible 239*c179937bSBjoern A. Zeeb * IPv6 address, the implementation shall extract the embedded 240*c179937bSBjoern A. Zeeb * IPv4 address and lookup the node name for that IPv4 address. 241*c179937bSBjoern A. Zeeb * [Option End]" 242*c179937bSBjoern A. Zeeb * => getipnodebyaddr() handles this case for us. 243*c179937bSBjoern A. Zeeb * => in case of NI_NUMERICHOST being set, inet_ntop[6] will 244*c179937bSBjoern A. Zeeb * handle it too. 245*c179937bSBjoern A. Zeeb * 246*c179937bSBjoern A. Zeeb * "If the address is the IPv6 unspecified address ( "::" ), 247*c179937bSBjoern A. Zeeb * a lookup shall not be performed and the behavior shall be 248*c179937bSBjoern A. Zeeb * the same as when the node's name cannot be located." 249*c179937bSBjoern A. Zeeb * => getipnodebyaddr() handles this case for us. 250*c179937bSBjoern A. Zeeb * => in case of NI_NUMERICHOST being set, 251*c179937bSBjoern A. Zeeb * ip6_parsenumeric() -> inet_ntop[6] will handle it too. 252*c179937bSBjoern A. Zeeb */ 253*c179937bSBjoern A. Zeeb 254*c179937bSBjoern A. Zeeb /* 255*c179937bSBjoern A. Zeeb * We used to exclude link-local from lookups. 256*c179937bSBjoern A. Zeeb * Even though calles in the resolver chain may not (yet) 257*c179937bSBjoern A. Zeeb * properly deal with them, we no longer do as for link-local 258*c179937bSBjoern A. Zeeb * there is a path to resolve these. See: 259*c179937bSBjoern A. Zeeb * RFC 6303 4.5. IPv6 Link-Local Addresses 260*c179937bSBjoern A. Zeeb * RFC 6762 4. Reverse Address Mapping 261*c179937bSBjoern A. Zeeb * 262*c179937bSBjoern A. Zeeb * XXX For IPv6 MC the only reference found was 263*c179937bSBjoern A. Zeeb * https://www.ietf.org/archive/id/draft-michaelson-as112-ipv6-02.html 264*c179937bSBjoern A. Zeeb * but there are also no "empty zone"s for x.0.f.f.ip6.arpa 265*c179937bSBjoern A. Zeeb * in DNS servers. Keep catching it here for now and 266*c179937bSBjoern A. Zeeb * do not attempt name resolution but return the address string. 267*c179937bSBjoern A. Zeeb */ 268*c179937bSBjoern A. Zeeb if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) 2697d56d374SYoshinobu Inoue flags |= NI_NUMERICHOST; 2707d56d374SYoshinobu Inoue } 2717d56d374SYoshinobu Inoue break; 2727d56d374SYoshinobu Inoue #endif 2737d56d374SYoshinobu Inoue } 2747d56d374SYoshinobu Inoue if (host == NULL || hostlen == 0) { 2756cb94182SJun-ichiro itojun Hagino /* 2766cb94182SJun-ichiro itojun Hagino * do nothing in this case. 2776cb94182SJun-ichiro itojun Hagino * in case you are wondering if "&&" is more correct than 278f6074d74SHajimu UMEMOTO * "||" here: rfc2553bis-03 says that host == NULL or 279f6074d74SHajimu UMEMOTO * hostlen == 0 means that the caller does not want the result. 2806cb94182SJun-ichiro itojun Hagino */ 2817d56d374SYoshinobu Inoue } else if (flags & NI_NUMERICHOST) { 2821ccfa322SHajimu UMEMOTO size_t numaddrlen; 2836cb94182SJun-ichiro itojun Hagino 2847d56d374SYoshinobu Inoue /* NUMERICHOST and NAMEREQD conflicts with each other */ 2857d56d374SYoshinobu Inoue if (flags & NI_NAMEREQD) 286f6074d74SHajimu UMEMOTO return EAI_NONAME; 2876cb94182SJun-ichiro itojun Hagino 2886cb94182SJun-ichiro itojun Hagino switch(afd->a_af) { 2896cb94182SJun-ichiro itojun Hagino #ifdef INET6 2906cb94182SJun-ichiro itojun Hagino case AF_INET6: 2916cb94182SJun-ichiro itojun Hagino { 2926cb94182SJun-ichiro itojun Hagino int error; 2936cb94182SJun-ichiro itojun Hagino 2946cb94182SJun-ichiro itojun Hagino if ((error = ip6_parsenumeric(sa, addr, host, 2956cb94182SJun-ichiro itojun Hagino hostlen, flags)) != 0) 2966cb94182SJun-ichiro itojun Hagino return(error); 2976cb94182SJun-ichiro itojun Hagino break; 2986cb94182SJun-ichiro itojun Hagino } 2996cb94182SJun-ichiro itojun Hagino #endif 3006cb94182SJun-ichiro itojun Hagino default: 3017d56d374SYoshinobu Inoue if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr)) 3027d56d374SYoshinobu Inoue == NULL) 303f6074d74SHajimu UMEMOTO return EAI_SYSTEM; 3046cb94182SJun-ichiro itojun Hagino numaddrlen = strlen(numaddr); 3056cb94182SJun-ichiro itojun Hagino if (numaddrlen + 1 > hostlen) /* don't forget terminator */ 306f6074d74SHajimu UMEMOTO return EAI_MEMORY; 307d0509082SJacques Vidrine strlcpy(host, numaddr, hostlen); 3086cb94182SJun-ichiro itojun Hagino break; 3097d56d374SYoshinobu Inoue } 3107d56d374SYoshinobu Inoue } else { 3117d56d374SYoshinobu Inoue hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error); 3126cb94182SJun-ichiro itojun Hagino 3137d56d374SYoshinobu Inoue if (hp) { 3146cb94182SJun-ichiro itojun Hagino #if 0 3156cb94182SJun-ichiro itojun Hagino /* 3166cb94182SJun-ichiro itojun Hagino * commented out, since "for local host" is not 3176cb94182SJun-ichiro itojun Hagino * implemented here - see RFC2553 p30 3186cb94182SJun-ichiro itojun Hagino */ 3197d56d374SYoshinobu Inoue if (flags & NI_NOFQDN) { 3206cb94182SJun-ichiro itojun Hagino char *p; 3217d56d374SYoshinobu Inoue p = strchr(hp->h_name, '.'); 3226cb94182SJun-ichiro itojun Hagino if (p) 3236cb94182SJun-ichiro itojun Hagino *p = '\0'; 3247d56d374SYoshinobu Inoue } 3256cb94182SJun-ichiro itojun Hagino #endif 32645181a75SJun-ichiro itojun Hagino if (strlen(hp->h_name) + 1 > hostlen) { 3277d56d374SYoshinobu Inoue freehostent(hp); 328f6074d74SHajimu UMEMOTO return EAI_MEMORY; 3297d56d374SYoshinobu Inoue } 330d0509082SJacques Vidrine strlcpy(host, hp->h_name, hostlen); 3317d56d374SYoshinobu Inoue freehostent(hp); 3327d56d374SYoshinobu Inoue } else { 3337d56d374SYoshinobu Inoue if (flags & NI_NAMEREQD) 334f6074d74SHajimu UMEMOTO return EAI_NONAME; 3356cb94182SJun-ichiro itojun Hagino switch(afd->a_af) { 3366cb94182SJun-ichiro itojun Hagino #ifdef INET6 3376cb94182SJun-ichiro itojun Hagino case AF_INET6: 3386cb94182SJun-ichiro itojun Hagino { 3396cb94182SJun-ichiro itojun Hagino int error; 3406cb94182SJun-ichiro itojun Hagino 3416cb94182SJun-ichiro itojun Hagino if ((error = ip6_parsenumeric(sa, addr, host, 3426cb94182SJun-ichiro itojun Hagino hostlen, 3436cb94182SJun-ichiro itojun Hagino flags)) != 0) 3446cb94182SJun-ichiro itojun Hagino return(error); 3456cb94182SJun-ichiro itojun Hagino break; 3466cb94182SJun-ichiro itojun Hagino } 3476cb94182SJun-ichiro itojun Hagino #endif 3486cb94182SJun-ichiro itojun Hagino default: 3496cb94182SJun-ichiro itojun Hagino if (inet_ntop(afd->a_af, addr, host, 3506cb94182SJun-ichiro itojun Hagino hostlen) == NULL) 351f6074d74SHajimu UMEMOTO return EAI_SYSTEM; 3526cb94182SJun-ichiro itojun Hagino break; 3536cb94182SJun-ichiro itojun Hagino } 3547d56d374SYoshinobu Inoue } 3557d56d374SYoshinobu Inoue } 356f6074d74SHajimu UMEMOTO return(0); 3577d56d374SYoshinobu Inoue } 3586cb94182SJun-ichiro itojun Hagino 3596cb94182SJun-ichiro itojun Hagino #ifdef INET6 3606cb94182SJun-ichiro itojun Hagino static int 36190d1d883SHajimu UMEMOTO ip6_parsenumeric(const struct sockaddr *sa, const char *addr, 36290d1d883SHajimu UMEMOTO char *host, size_t hostlen, int flags) 3636cb94182SJun-ichiro itojun Hagino { 3641ccfa322SHajimu UMEMOTO size_t numaddrlen; 3656cb94182SJun-ichiro itojun Hagino char numaddr[512]; 3666cb94182SJun-ichiro itojun Hagino 367f6074d74SHajimu UMEMOTO if (inet_ntop(AF_INET6, addr, numaddr, sizeof(numaddr)) == NULL) 368f6074d74SHajimu UMEMOTO return EAI_SYSTEM; 3696cb94182SJun-ichiro itojun Hagino 3706cb94182SJun-ichiro itojun Hagino numaddrlen = strlen(numaddr); 3716cb94182SJun-ichiro itojun Hagino if (numaddrlen + 1 > hostlen) /* don't forget terminator */ 372734aa104SHajimu UMEMOTO return EAI_OVERFLOW; 373d0509082SJacques Vidrine strlcpy(host, numaddr, hostlen); 3746cb94182SJun-ichiro itojun Hagino 37515e4dafcSHajimu UMEMOTO if (((const struct sockaddr_in6 *)sa)->sin6_scope_id) { 37615e4dafcSHajimu UMEMOTO char zonebuf[MAXHOSTNAMELEN]; 37715e4dafcSHajimu UMEMOTO int zonelen; 3786cb94182SJun-ichiro itojun Hagino 37915e4dafcSHajimu UMEMOTO zonelen = ip6_sa2str( 38015e4dafcSHajimu UMEMOTO (const struct sockaddr_in6 *)(const void *)sa, 38115e4dafcSHajimu UMEMOTO zonebuf, sizeof(zonebuf), flags); 38215e4dafcSHajimu UMEMOTO if (zonelen < 0) 383734aa104SHajimu UMEMOTO return EAI_OVERFLOW; 38415e4dafcSHajimu UMEMOTO if (zonelen + 1 + numaddrlen + 1 > hostlen) 385734aa104SHajimu UMEMOTO return EAI_OVERFLOW; 386f6074d74SHajimu UMEMOTO 387f6074d74SHajimu UMEMOTO /* construct <numeric-addr><delim><zoneid> */ 38815e4dafcSHajimu UMEMOTO memcpy(host + numaddrlen + 1, zonebuf, 38915e4dafcSHajimu UMEMOTO (size_t)zonelen); 3906cb94182SJun-ichiro itojun Hagino host[numaddrlen] = SCOPE_DELIMITER; 39115e4dafcSHajimu UMEMOTO host[numaddrlen + 1 + zonelen] = '\0'; 3926cb94182SJun-ichiro itojun Hagino } 3936cb94182SJun-ichiro itojun Hagino 3946cb94182SJun-ichiro itojun Hagino return 0; 3956cb94182SJun-ichiro itojun Hagino } 3966cb94182SJun-ichiro itojun Hagino 3976cb94182SJun-ichiro itojun Hagino /* ARGSUSED */ 3986cb94182SJun-ichiro itojun Hagino static int 39990d1d883SHajimu UMEMOTO ip6_sa2str(const struct sockaddr_in6 *sa6, char *buf, size_t bufsiz, int flags) 4006cb94182SJun-ichiro itojun Hagino { 401f6074d74SHajimu UMEMOTO unsigned int ifindex; 402f6074d74SHajimu UMEMOTO const struct in6_addr *a6; 403f6074d74SHajimu UMEMOTO int n; 404f6074d74SHajimu UMEMOTO 405f6074d74SHajimu UMEMOTO ifindex = (unsigned int)sa6->sin6_scope_id; 406f6074d74SHajimu UMEMOTO a6 = &sa6->sin6_addr; 4076cb94182SJun-ichiro itojun Hagino 408f6074d74SHajimu UMEMOTO if ((flags & NI_NUMERICSCOPE) != 0) { 409f6074d74SHajimu UMEMOTO n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id); 410f6074d74SHajimu UMEMOTO if (n < 0 || n >= bufsiz) 411f6074d74SHajimu UMEMOTO return -1; 412f6074d74SHajimu UMEMOTO else 413f6074d74SHajimu UMEMOTO return n; 4146cb94182SJun-ichiro itojun Hagino } 4156cb94182SJun-ichiro itojun Hagino 4166cb94182SJun-ichiro itojun Hagino /* if_indextoname() does not take buffer size. not a good api... */ 417f6074d74SHajimu UMEMOTO if ((IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6) || 418f6074d74SHajimu UMEMOTO IN6_IS_ADDR_MC_NODELOCAL(a6)) && bufsiz >= IF_NAMESIZE) { 4196cb94182SJun-ichiro itojun Hagino char *p = if_indextoname(ifindex, buf); 4206cb94182SJun-ichiro itojun Hagino if (p) { 4216cb94182SJun-ichiro itojun Hagino return(strlen(p)); 4226cb94182SJun-ichiro itojun Hagino } 4236cb94182SJun-ichiro itojun Hagino } 4246cb94182SJun-ichiro itojun Hagino 4256cb94182SJun-ichiro itojun Hagino /* last resort */ 426f6074d74SHajimu UMEMOTO n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id); 4271ccfa322SHajimu UMEMOTO if (n < 0 || (size_t)n >= bufsiz) 428f6074d74SHajimu UMEMOTO return -1; 429f6074d74SHajimu UMEMOTO else 430f6074d74SHajimu UMEMOTO return n; 4316cb94182SJun-ichiro itojun Hagino } 4326cb94182SJun-ichiro itojun Hagino #endif /* INET6 */ 43367228c46SBruce M Simpson 43467228c46SBruce M Simpson /* 43567228c46SBruce M Simpson * getnameinfo_link(): 43667228c46SBruce M Simpson * Format a link-layer address into a printable format, paying attention to 43767228c46SBruce M Simpson * the interface type. 43867228c46SBruce M Simpson */ 43967228c46SBruce M Simpson /* ARGSUSED */ 44067228c46SBruce M Simpson static int 441bb957021SHiroki Sato getnameinfo_link(const struct afd *afd, 442bb957021SHiroki Sato const struct sockaddr *sa, socklen_t salen, 44367228c46SBruce M Simpson char *host, size_t hostlen, char *serv, size_t servlen, int flags) 44467228c46SBruce M Simpson { 44567228c46SBruce M Simpson const struct sockaddr_dl *sdl = 44667228c46SBruce M Simpson (const struct sockaddr_dl *)(const void *)sa; 447823e5e0eSHajimu UMEMOTO const struct fw_hwaddr *iha; 44867228c46SBruce M Simpson int n; 44967228c46SBruce M Simpson 45067228c46SBruce M Simpson if (serv != NULL && servlen > 0) 45167228c46SBruce M Simpson *serv = '\0'; 45267228c46SBruce M Simpson 45367228c46SBruce M Simpson if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 && sdl->sdl_slen == 0) { 45467228c46SBruce M Simpson n = snprintf(host, hostlen, "link#%d", sdl->sdl_index); 45534e38a56SHiroki Sato if (n >= hostlen) { 45667228c46SBruce M Simpson *host = '\0'; 45727a1ccfcSHiroki Sato return (EAI_MEMORY); 45867228c46SBruce M Simpson } 45927a1ccfcSHiroki Sato return (0); 46027a1ccfcSHiroki Sato } 46127a1ccfcSHiroki Sato 46234e38a56SHiroki Sato if (sdl->sdl_nlen > 0 && sdl->sdl_alen == 0) { 46334e38a56SHiroki Sato n = sdl->sdl_nlen; 46434e38a56SHiroki Sato if (n >= hostlen) { 46527a1ccfcSHiroki Sato *host = '\0'; 46627a1ccfcSHiroki Sato return (EAI_MEMORY); 46727a1ccfcSHiroki Sato } 46827a1ccfcSHiroki Sato memcpy(host, sdl->sdl_data, sdl->sdl_nlen); 46934e38a56SHiroki Sato host[n] = '\0'; 47034e38a56SHiroki Sato return (0); 47167228c46SBruce M Simpson } 47267228c46SBruce M Simpson 47367228c46SBruce M Simpson switch (sdl->sdl_type) { 474823e5e0eSHajimu UMEMOTO case IFT_IEEE1394: 475823e5e0eSHajimu UMEMOTO if (sdl->sdl_alen < sizeof(iha->sender_unique_ID_hi) + 476823e5e0eSHajimu UMEMOTO sizeof(iha->sender_unique_ID_lo)) 477823e5e0eSHajimu UMEMOTO return EAI_FAMILY; 478823e5e0eSHajimu UMEMOTO iha = (const struct fw_hwaddr *)(const void *)LLADDR(sdl); 479823e5e0eSHajimu UMEMOTO return hexname((const u_int8_t *)&iha->sender_unique_ID_hi, 480823e5e0eSHajimu UMEMOTO sizeof(iha->sender_unique_ID_hi) + 481823e5e0eSHajimu UMEMOTO sizeof(iha->sender_unique_ID_lo), 482823e5e0eSHajimu UMEMOTO host, hostlen); 48367228c46SBruce M Simpson /* 48467228c46SBruce M Simpson * The following have zero-length addresses. 48567228c46SBruce M Simpson * IFT_GIF (net/if_gif.c) 48667228c46SBruce M Simpson * IFT_LOOP (net/if_loop.c) 4876aae3517SGleb Smirnoff * IFT_PPP (net/if_tuntap.c) 48867228c46SBruce M Simpson * IFT_SLIP (net/if_sl.c, net/if_strip.c) 48967228c46SBruce M Simpson * IFT_STF (net/if_stf.c) 49067228c46SBruce M Simpson * IFT_L2VLAN (net/if_vlan.c) 49167228c46SBruce M Simpson * IFT_BRIDGE (net/if_bridge.h> 49267228c46SBruce M Simpson */ 49367228c46SBruce M Simpson /* 49467228c46SBruce M Simpson * The following use IPv4 addresses as link-layer addresses: 49567228c46SBruce M Simpson * IFT_OTHER (net/if_gre.c) 49667228c46SBruce M Simpson * IFT_OTHER (netinet/ip_ipip.c) 49767228c46SBruce M Simpson */ 49867228c46SBruce M Simpson /* default below is believed correct for all these. */ 49967228c46SBruce M Simpson case IFT_ETHER: 50067228c46SBruce M Simpson case IFT_FDDI: 50167228c46SBruce M Simpson case IFT_HIPPI: 50267228c46SBruce M Simpson case IFT_ISO88025: 50367228c46SBruce M Simpson default: 50467228c46SBruce M Simpson return hexname((u_int8_t *)LLADDR(sdl), (size_t)sdl->sdl_alen, 50567228c46SBruce M Simpson host, hostlen); 50667228c46SBruce M Simpson } 50767228c46SBruce M Simpson } 50867228c46SBruce M Simpson 50967228c46SBruce M Simpson static int 51027a1ccfcSHiroki Sato hexname(const u_int8_t *cp, size_t len, char *host, size_t hostlen) 51167228c46SBruce M Simpson { 51267228c46SBruce M Simpson int i, n; 51367228c46SBruce M Simpson char *outp = host; 51467228c46SBruce M Simpson 51567228c46SBruce M Simpson *outp = '\0'; 51667228c46SBruce M Simpson for (i = 0; i < len; i++) { 51767228c46SBruce M Simpson n = snprintf(outp, hostlen, "%s%02x", 51867228c46SBruce M Simpson i ? ":" : "", cp[i]); 51967228c46SBruce M Simpson if (n < 0 || n >= hostlen) { 52067228c46SBruce M Simpson *host = '\0'; 52167228c46SBruce M Simpson return EAI_MEMORY; 52267228c46SBruce M Simpson } 52367228c46SBruce M Simpson outp += n; 52467228c46SBruce M Simpson hostlen -= n; 52567228c46SBruce M Simpson } 52667228c46SBruce M Simpson return 0; 52767228c46SBruce M Simpson } 528bb957021SHiroki Sato 529bb957021SHiroki Sato /* 530bb957021SHiroki Sato * getnameinfo_un(): 531bb957021SHiroki Sato * Format a UNIX IPC domain address (pathname). 532bb957021SHiroki Sato */ 533bb957021SHiroki Sato /* ARGSUSED */ 534bb957021SHiroki Sato static int 535bb957021SHiroki Sato getnameinfo_un(const struct afd *afd, 536bb957021SHiroki Sato const struct sockaddr *sa, socklen_t salen, 537bb957021SHiroki Sato char *host, size_t hostlen, char *serv, size_t servlen, int flags) 538bb957021SHiroki Sato { 539bb957021SHiroki Sato size_t pathlen; 540bb957021SHiroki Sato 541bb957021SHiroki Sato if (serv != NULL && servlen > 0) 542bb957021SHiroki Sato *serv = '\0'; 543bb957021SHiroki Sato if (host != NULL && hostlen > 0) { 54420d96999SHiroki Sato pathlen = salen - afd->a_off; 545bb957021SHiroki Sato 546bb957021SHiroki Sato if (pathlen + 1 > hostlen) { 547bb957021SHiroki Sato *host = '\0'; 548bb957021SHiroki Sato return (EAI_MEMORY); 549bb957021SHiroki Sato } 550bb957021SHiroki Sato strlcpy(host, (const char *)sa + afd->a_off, pathlen + 1); 551bb957021SHiroki Sato } 552bb957021SHiroki Sato 553bb957021SHiroki Sato return (0); 554bb957021SHiroki Sato } 555