blob: 16ff0cb7b7c61040f0434222975cbdfeb8a81e41 [file] [log] [blame]
The Android Open Source Project1dc9e472009-03-03 19:28:35 -08001/* $NetBSD: getnameinfo.c,v 1.43 2006/02/17 15:58:26 ginsbach Exp $ */
2/* $KAME: getnameinfo.c,v 1.45 2000/09/25 22:43:56 itojun Exp $ */
3
4/*
5 * Copyright (c) 2000 Ben Harris.
6 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of the project nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34/*
35 * Issues to be discussed:
36 * - Thread safe-ness must be checked
37 * - RFC2553 says that we should raise error on short buffer. X/Open says
38 * we need to truncate the result. We obey RFC2553 (and X/Open should be
39 * modified). ipngwg rough consensus seems to follow RFC2553.
40 * - What is "local" in NI_FQDN?
41 * - NI_NAMEREQD and NI_NUMERICHOST conflict with each other.
42 * - (KAME extension) always attach textual scopeid (fe80::1%lo0), if
43 * sin6_scope_id is filled - standardization status?
44 * XXX breaks backward compat for code that expects no scopeid.
45 * beware on merge.
46 */
47
48#include <sys/cdefs.h>
49#if defined(LIBC_SCCS) && !defined(lint)
50__RCSID("$NetBSD: getnameinfo.c,v 1.43 2006/02/17 15:58:26 ginsbach Exp $");
51#endif /* LIBC_SCCS and not lint */
52
53#include <sys/types.h>
54#include <sys/socket.h>
55#include <net/if.h>
Elliott Hughes5056f1f2012-06-11 15:01:10 -070056#if defined(ANDROID_CHANGES) && defined(AF_LINK)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080057#include <net/if_dl.h>
Elliott Hughes5056f1f2012-06-11 15:01:10 -070058#endif
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080059#include <net/if_ieee1394.h>
60#include <net/if_types.h>
61#include <netinet/in.h>
62#include <arpa/inet.h>
63#include "arpa_nameser.h"
64#include <assert.h>
65#include <limits.h>
66#include <netdb.h>
67#ifdef ANDROID_CHANGES
68#include "resolv_private.h"
Mattias Falk149f7df2011-02-15 08:45:26 +010069#include <sys/system_properties.h>
70#include <stdlib.h>
71#include <unistd.h>
72#include <sys/un.h>
73#include <errno.h>
The Android Open Source Project1dc9e472009-03-03 19:28:35 -080074#else
75#include <resolv.h>
76#endif
77#include <stddef.h>
78#include <string.h>
79
80static const struct afd {
81 int a_af;
82 socklen_t a_addrlen;
83 socklen_t a_socklen;
84 int a_off;
85} afdl [] = {
86#ifdef INET6
87 {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
88 offsetof(struct sockaddr_in6, sin6_addr)},
89#endif
90 {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
91 offsetof(struct sockaddr_in, sin_addr)},
92 {0, 0, 0, 0},
93};
94
95struct sockinet {
96 u_char si_len;
97 u_char si_family;
98 u_short si_port;
99};
100
Mattias Falkc63e5902011-08-23 14:34:14 +0200101#if defined(ANDROID_CHANGES)
102static int getnameinfo_inet __P((const struct sockaddr *, socklen_t, char *,
103 socklen_t, char *, socklen_t, int, const char*));
104#else
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800105static int getnameinfo_inet __P((const struct sockaddr *, socklen_t, char *,
Robert Greenwaltb002a2f2013-01-19 00:40:24 +0000106 socklen_t, char *, socklen_t, int));
Mattias Falkc63e5902011-08-23 14:34:14 +0200107#endif
108
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800109#ifdef INET6
110static int ip6_parsenumeric __P((const struct sockaddr *, const char *, char *,
111 socklen_t, int));
112static int ip6_sa2str __P((const struct sockaddr_in6 *, char *, size_t,
113 int));
114#endif
Elliott Hughes5056f1f2012-06-11 15:01:10 -0700115#if defined(ANDROID_CHANGES) && defined(AF_LINK)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800116static int getnameinfo_link __P((const struct sockaddr *, socklen_t, char *,
117 socklen_t, char *, socklen_t, int));
Elliott Hughes5056f1f2012-06-11 15:01:10 -0700118#endif
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800119static int hexname __P((const u_int8_t *, size_t, char *, socklen_t));
120
Selim Gurun06e18312012-02-27 15:58:54 -0800121// This should be synchronized to ResponseCode.h
122static const int DnsProxyQueryResult = 222;
123
124
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800125/*
126 * Top-level getnameinfo() code. Look at the address family, and pick an
127 * appropriate function to call.
128 */
129int getnameinfo(const struct sockaddr* sa, socklen_t salen, char* host, size_t hostlen, char* serv, size_t servlen, int flags)
130{
Mattias Falkc63e5902011-08-23 14:34:14 +0200131#ifdef ANDROID_CHANGES
132 return android_getnameinfoforiface(sa, salen, host, hostlen, serv, servlen, flags, NULL);
133}
134
135int android_getnameinfoforiface(const struct sockaddr* sa, socklen_t salen, char* host, size_t hostlen, char* serv, size_t servlen, int flags, const char* iface)
136{
137#endif /* ANDROID_CHANGES */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800138 switch (sa->sa_family) {
139 case AF_INET:
140 case AF_INET6:
141 return getnameinfo_inet(sa, salen, host, hostlen,
Mattias Falkc63e5902011-08-23 14:34:14 +0200142#ifdef ANDROID_CHANGES
143 serv, servlen, flags, iface);
144#else
Robert Greenwaltb002a2f2013-01-19 00:40:24 +0000145 serv, servlen, flags);
Mattias Falkc63e5902011-08-23 14:34:14 +0200146#endif
Elliott Hughes5056f1f2012-06-11 15:01:10 -0700147#if defined(ANDROID_CHANGES) && defined(AF_LINK)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800148 case AF_LINK:
149 return getnameinfo_link(sa, salen, host, hostlen,
Mattias Falkc63e5902011-08-23 14:34:14 +0200150 serv, servlen, flags);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800151#endif
152 default:
153 return EAI_FAMILY;
154 }
155}
Robert Greenwaltb002a2f2013-01-19 00:40:24 +0000156
Mattias Falk149f7df2011-02-15 08:45:26 +0100157#ifdef ANDROID_CHANGES
158/* On success length of the host name is returned. A return
159 * value of 0 means there's no host name associated with
160 * the address. On failure -1 is returned in which case
161 * normal execution flow shall continue. */
162static int
Mattias Falkc63e5902011-08-23 14:34:14 +0200163android_gethostbyaddr_proxy(char* nameBuf, size_t nameBufLen, const void *addr, socklen_t addrLen, int addrFamily, const char* iface)
164{
165 struct hostent *hostResult =
166 android_gethostbyaddrforiface_proxy(addr, addrLen, addrFamily, iface);
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800167
Mattias Falkc63e5902011-08-23 14:34:14 +0200168 if (hostResult == NULL) return 0;
Mattias Falk149f7df2011-02-15 08:45:26 +0100169
Mattias Falkc63e5902011-08-23 14:34:14 +0200170 int lengthResult = strlen(hostResult->h_name);
Mattias Falk149f7df2011-02-15 08:45:26 +0100171
Mattias Falkc63e5902011-08-23 14:34:14 +0200172 if (nameBuf) strncpy(nameBuf, hostResult->h_name, nameBufLen);
173 return lengthResult;
Mattias Falk149f7df2011-02-15 08:45:26 +0100174}
175#endif
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800176/*
177 * getnameinfo_inet():
178 * Format an IPv4 or IPv6 sockaddr into a printable string.
179 */
Mattias Falkc63e5902011-08-23 14:34:14 +0200180#ifdef ANDROID_CHANGES
181static int
182getnameinfo_inet(sa, salen, host, hostlen, serv, servlen, flags, iface)
183 const struct sockaddr *sa;
184 socklen_t salen;
185 char *host;
186 socklen_t hostlen;
187 char *serv;
188 socklen_t servlen;
189 int flags;
190 const char* iface;
191#else
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800192static int
Robert Greenwaltb002a2f2013-01-19 00:40:24 +0000193getnameinfo_inet(sa, salen, host, hostlen, serv, servlen, flags)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800194 const struct sockaddr *sa;
195 socklen_t salen;
196 char *host;
197 socklen_t hostlen;
198 char *serv;
199 socklen_t servlen;
200 int flags;
Mattias Falkc63e5902011-08-23 14:34:14 +0200201#endif
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800202{
203 const struct afd *afd;
204 struct servent *sp;
205 struct hostent *hp;
206 u_short port;
207 int family, i;
208 const char *addr;
209 u_int32_t v4a;
210 char numserv[512];
211 char numaddr[512];
212
213 /* sa is checked below */
214 /* host may be NULL */
215 /* serv may be NULL */
216
217 if (sa == NULL)
218 return EAI_FAIL;
219
220#ifdef BSD4_4
221 if (sa->sa_len != salen)
222 return EAI_FAIL;
223#endif
224
225 family = sa->sa_family;
226 for (i = 0; afdl[i].a_af; i++)
227 if (afdl[i].a_af == family) {
228 afd = &afdl[i];
229 goto found;
230 }
231 return EAI_FAMILY;
232
233 found:
234 if (salen != afd->a_socklen)
235 return EAI_FAIL;
236
237 /* network byte order */
238 port = ((const struct sockinet *)(const void *)sa)->si_port;
239 addr = (const char *)(const void *)sa + afd->a_off;
240
241 if (serv == NULL || servlen == 0) {
242 /*
243 * do nothing in this case.
244 * in case you are wondering if "&&" is more correct than
245 * "||" here: rfc2553bis-03 says that serv == NULL OR
246 * servlen == 0 means that the caller does not want the result.
247 */
248 } else {
249 if (flags & NI_NUMERICSERV)
250 sp = NULL;
251 else {
252 sp = getservbyport(port,
253 (flags & NI_DGRAM) ? "udp" : "tcp");
254 }
255 if (sp) {
256 if (strlen(sp->s_name) + 1 > (size_t)servlen)
257 return EAI_MEMORY;
258 strlcpy(serv, sp->s_name, servlen);
259 } else {
260 snprintf(numserv, sizeof(numserv), "%u", ntohs(port));
261 if (strlen(numserv) + 1 > (size_t)servlen)
262 return EAI_MEMORY;
263 strlcpy(serv, numserv, servlen);
264 }
265 }
266
267 switch (sa->sa_family) {
268 case AF_INET:
269 v4a = (u_int32_t)
270 ntohl(((const struct sockaddr_in *)
271 (const void *)sa)->sin_addr.s_addr);
272 if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
273 flags |= NI_NUMERICHOST;
274 v4a >>= IN_CLASSA_NSHIFT;
275 if (v4a == 0)
276 flags |= NI_NUMERICHOST;
277 break;
278#ifdef INET6
279 case AF_INET6:
280 {
281 const struct sockaddr_in6 *sin6;
282 sin6 = (const struct sockaddr_in6 *)(const void *)sa;
283 switch (sin6->sin6_addr.s6_addr[0]) {
284 case 0x00:
285 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
286 ;
287 else if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
288 ;
289 else
290 flags |= NI_NUMERICHOST;
291 break;
292 default:
293 if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
294 flags |= NI_NUMERICHOST;
295 }
296 else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
297 flags |= NI_NUMERICHOST;
298 break;
299 }
300 }
301 break;
302#endif
303 }
304 if (host == NULL || hostlen == 0) {
305 /*
306 * do nothing in this case.
307 * in case you are wondering if "&&" is more correct than
308 * "||" here: rfc2553bis-03 says that host == NULL or
309 * hostlen == 0 means that the caller does not want the result.
310 */
311 } else if (flags & NI_NUMERICHOST) {
312 size_t numaddrlen;
313
314 /* NUMERICHOST and NAMEREQD conflicts with each other */
315 if (flags & NI_NAMEREQD)
316 return EAI_NONAME;
317
318 switch(afd->a_af) {
319#ifdef INET6
320 case AF_INET6:
321 {
322 int error;
323
324 if ((error = ip6_parsenumeric(sa, addr, host,
325 hostlen, flags)) != 0)
326 return(error);
327 break;
328 }
329#endif
330 default:
331 if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
332 == NULL)
333 return EAI_SYSTEM;
334 numaddrlen = strlen(numaddr);
335 if (numaddrlen + 1 > (size_t)hostlen) /* don't forget terminator */
336 return EAI_MEMORY;
337 strlcpy(host, numaddr, hostlen);
338 break;
339 }
340 } else {
Mattias Falk149f7df2011-02-15 08:45:26 +0100341#ifdef ANDROID_CHANGES
342 struct hostent android_proxy_hostent;
343 char android_proxy_buf[MAXDNAME];
Mattias Falk149f7df2011-02-15 08:45:26 +0100344
Selim Gurun06e18312012-02-27 15:58:54 -0800345 int hostnamelen = android_gethostbyaddr_proxy(android_proxy_buf,
Mattias Falkc63e5902011-08-23 14:34:14 +0200346 MAXDNAME, addr, afd->a_addrlen, afd->a_af, iface);
Selim Gurun06e18312012-02-27 15:58:54 -0800347 if (hostnamelen > 0) {
348 hp = &android_proxy_hostent;
349 hp->h_name = android_proxy_buf;
350 } else if (!hostnamelen) {
351 hp = NULL;
Mattias Falk149f7df2011-02-15 08:45:26 +0100352 } else {
Mattias Falkc63e5902011-08-23 14:34:14 +0200353 hp = android_gethostbyaddrforiface(addr, afd->a_addrlen, afd->a_af, iface);
Mattias Falk149f7df2011-02-15 08:45:26 +0100354 }
355#else
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800356 hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
Mattias Falk149f7df2011-02-15 08:45:26 +0100357#endif
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800358
359 if (hp) {
Elliott Hughes5056f1f2012-06-11 15:01:10 -0700360#if defined(ANDROID_CHANGES) && defined(AF_LINK)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800361 /*
362 * commented out, since "for local host" is not
363 * implemented here - see RFC2553 p30
364 */
365 if (flags & NI_NOFQDN) {
366 char *p;
367 p = strchr(hp->h_name, '.');
368 if (p)
369 *p = '\0';
370 }
371#endif
372 if (strlen(hp->h_name) + 1 > (size_t)hostlen) {
373 return EAI_MEMORY;
374 }
375 strlcpy(host, hp->h_name, hostlen);
376 } else {
377 if (flags & NI_NAMEREQD)
378 return EAI_NONAME;
379 switch(afd->a_af) {
380#ifdef INET6
381 case AF_INET6:
382 {
383 int error;
384
385 if ((error = ip6_parsenumeric(sa, addr, host,
386 hostlen,
387 flags)) != 0)
388 return(error);
389 break;
390 }
391#endif
392 default:
393 if (inet_ntop(afd->a_af, addr, host,
394 hostlen) == NULL)
395 return EAI_SYSTEM;
396 break;
397 }
398 }
399 }
400 return(0);
401}
402
403#ifdef INET6
404static int
405ip6_parsenumeric(sa, addr, host, hostlen, flags)
406 const struct sockaddr *sa;
407 const char *addr;
408 char *host;
409 socklen_t hostlen;
410 int flags;
411{
412 size_t numaddrlen;
413 char numaddr[512];
414
415 assert(sa != NULL);
416 assert(addr != NULL);
417 assert(host != NULL);
418
David 'Digit' Turner50ace4f2010-06-16 16:36:41 -0700419 if (hostlen < 0)
420 return EAI_OVERFLOW;
421
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800422 if (inet_ntop(AF_INET6, addr, numaddr, sizeof(numaddr)) == NULL)
423 return EAI_SYSTEM;
424
425 numaddrlen = strlen(numaddr);
David 'Digit' Turner50ace4f2010-06-16 16:36:41 -0700426 if (numaddrlen + 1 > (size_t)hostlen) /* don't forget terminator */
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800427 return EAI_OVERFLOW;
428 strlcpy(host, numaddr, hostlen);
429
430 if (((const struct sockaddr_in6 *)(const void *)sa)->sin6_scope_id) {
431 char zonebuf[MAXHOSTNAMELEN];
432 int zonelen;
433
434 zonelen = ip6_sa2str(
435 (const struct sockaddr_in6 *)(const void *)sa,
436 zonebuf, sizeof(zonebuf), flags);
437 if (zonelen < 0)
438 return EAI_OVERFLOW;
David 'Digit' Turner50ace4f2010-06-16 16:36:41 -0700439 if ((size_t) zonelen + 1 + numaddrlen + 1 > (size_t)hostlen)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800440 return EAI_OVERFLOW;
441 /* construct <numeric-addr><delim><zoneid> */
442 memcpy(host + numaddrlen + 1, zonebuf,
443 (size_t)zonelen);
444 host[numaddrlen] = SCOPE_DELIMITER;
445 host[numaddrlen + 1 + zonelen] = '\0';
446 }
447
448 return 0;
449}
450
451/* ARGSUSED */
452static int
453ip6_sa2str(sa6, buf, bufsiz, flags)
454 const struct sockaddr_in6 *sa6;
455 char *buf;
456 size_t bufsiz;
457 int flags;
458{
459 unsigned int ifindex;
460 const struct in6_addr *a6;
461 int n;
462
463 assert(sa6 != NULL);
464 assert(buf != NULL);
465
466 ifindex = (unsigned int)sa6->sin6_scope_id;
467 a6 = &sa6->sin6_addr;
468
469#ifdef NI_NUMERICSCOPE
470 if ((flags & NI_NUMERICSCOPE) != 0) {
471 n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id);
472 if (n < 0 || n >= bufsiz)
473 return -1;
474 else
475 return n;
476 }
477#endif
478
479 /* if_indextoname() does not take buffer size. not a good api... */
480 if ((IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) &&
481 bufsiz >= IF_NAMESIZE) {
482 char *p = if_indextoname(ifindex, buf);
483 if (p) {
484 return(strlen(p));
485 }
486 }
487
488 /* last resort */
489 n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id);
490 if (n < 0 || (size_t) n >= bufsiz)
491 return -1;
492 else
493 return n;
494}
495#endif /* INET6 */
496
497
Elliott Hughes5056f1f2012-06-11 15:01:10 -0700498#if defined(ANDROID_CHANGES) && defined(AF_LINK)
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800499/*
500 * getnameinfo_link():
501 * Format a link-layer address into a printable format, paying attention to
502 * the interface type.
503 */
504/* ARGSUSED */
505static int
506getnameinfo_link(const struct sockaddr *sa, socklen_t salen,
507 char *host, socklen_t hostlen, char *serv, socklen_t servlen,
508 int flags)
509{
510 const struct sockaddr_dl *sdl =
511 (const struct sockaddr_dl *)(const void *)sa;
512 const struct ieee1394_hwaddr *iha;
513 int n;
514
515 if (serv != NULL && servlen > 0)
516 *serv = '\0';
517
518 if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 && sdl->sdl_slen == 0) {
519 n = snprintf(host, hostlen, "link#%u", sdl->sdl_index);
520 if (n < 0 || (socklen_t) n > hostlen) {
521 *host = '\0';
522 return EAI_MEMORY;
523 }
524 return 0;
525 }
526
527 switch (sdl->sdl_type) {
528#ifdef IFT_ECONET
529 case IFT_ECONET:
530 if (sdl->sdl_alen < 2)
531 return EAI_FAMILY;
532 if (CLLADDR(sdl)[1] == 0)
533 n = snprintf(host, hostlen, "%u", CLLADDR(sdl)[0]);
534 else
535 n = snprintf(host, hostlen, "%u.%u",
536 CLLADDR(sdl)[1], CLLADDR(sdl)[0]);
537 if (n < 0 || (socklen_t) n >= hostlen) {
538 *host = '\0';
539 return EAI_MEMORY;
540 } else
541 return 0;
542#endif
543 case IFT_IEEE1394:
544 if (sdl->sdl_alen < sizeof(iha->iha_uid))
545 return EAI_FAMILY;
546 iha =
547 (const struct ieee1394_hwaddr *)(const void *)CLLADDR(sdl);
548 return hexname(iha->iha_uid, sizeof(iha->iha_uid),
549 host, hostlen);
550 /*
551 * The following have zero-length addresses.
552 * IFT_ATM (net/if_atmsubr.c)
553 * IFT_FAITH (net/if_faith.c)
554 * IFT_GIF (net/if_gif.c)
555 * IFT_LOOP (net/if_loop.c)
556 * IFT_PPP (net/if_ppp.c, net/if_spppsubr.c)
557 * IFT_SLIP (net/if_sl.c, net/if_strip.c)
558 * IFT_STF (net/if_stf.c)
559 * IFT_L2VLAN (net/if_vlan.c)
560 * IFT_PROPVIRTUAL (net/if_bridge.h>
561 */
562 /*
563 * The following use IPv4 addresses as link-layer addresses:
564 * IFT_OTHER (net/if_gre.c)
565 */
566 case IFT_ARCNET: /* default below is believed correct for all these. */
567 case IFT_ETHER:
568 case IFT_FDDI:
569 case IFT_HIPPI:
570 case IFT_ISO88025:
571 default:
572 return hexname((const u_int8_t *)CLLADDR(sdl),
573 (size_t)sdl->sdl_alen, host, hostlen);
574 }
575}
Elliott Hughes5056f1f2012-06-11 15:01:10 -0700576#endif
The Android Open Source Project1dc9e472009-03-03 19:28:35 -0800577
578static int
579hexname(cp, len, host, hostlen)
580 const u_int8_t *cp;
581 char *host;
582 size_t len;
583 socklen_t hostlen;
584{
585 int n;
586 size_t i;
587 char *outp = host;
588
589 *outp = '\0';
590 for (i = 0; i < len; i++) {
591 n = snprintf(outp, hostlen, "%s%02x",
592 i ? ":" : "", cp[i]);
593 if (n < 0 || (socklen_t) n >= hostlen) {
594 *host = '\0';
595 return EAI_MEMORY;
596 }
597 outp += n;
598 hostlen -= n;
599 }
600 return 0;
601}