diff options
author | bms <bms@FreeBSD.org> | 2007-02-28 21:18:38 +0000 |
---|---|---|
committer | bms <bms@FreeBSD.org> | 2007-02-28 21:18:38 +0000 |
commit | 0738a9d791c7cf11ec35c5f1b495c0530c978447 (patch) | |
tree | 5795b2406f62ac8534a87ecbbb9b833c90045556 /lib/libc/net/getnameinfo.c | |
parent | 2010e1d527af4d5a25b9e8dd38e95b0b3d1a214c (diff) | |
download | FreeBSD-src-0738a9d791c7cf11ec35c5f1b495c0530c978447.zip FreeBSD-src-0738a9d791c7cf11ec35c5f1b495c0530c978447.tar.gz |
Nuke ascii2addr() and addr2ascii(). They have no consumers anywhere
in FreeBSD, and originated from INRIA IPv6.
Stub out netstat reference to addr2ascii() I mistakenly introduced.
Update misleading man page sections.
Merge NetBSD's getnameinfo() AF_LINK extensions for a portable way to
print link-layer addresses given a sockaddr_dl(), minus the IEEE 1394
bits which don't map directly to our code.
Obtained from: NetBSD (getnameinfo.c)
Discussed on: current (March 2006)
Diffstat (limited to 'lib/libc/net/getnameinfo.c')
-rw-r--r-- | lib/libc/net/getnameinfo.c | 124 |
1 files changed, 116 insertions, 8 deletions
diff --git a/lib/libc/net/getnameinfo.c b/lib/libc/net/getnameinfo.c index ed1e3af..0b59586 100644 --- a/lib/libc/net/getnameinfo.c +++ b/lib/libc/net/getnameinfo.c @@ -2,6 +2,7 @@ /* * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. + * Copyright (c) 2000 Ben Harris. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -49,6 +50,8 @@ __FBSDID("$FreeBSD$"); #include <sys/types.h> #include <sys/socket.h> #include <net/if.h> +#include <net/if_dl.h> +#include <net/if_types.h> #include <netinet/in.h> #include <arpa/inet.h> #include <arpa/nameser.h> @@ -58,6 +61,38 @@ __FBSDID("$FreeBSD$"); #include <stddef.h> #include <errno.h> +static int getnameinfo_inet(const struct sockaddr *, socklen_t, char *, + size_t, char *, size_t, int); +#ifdef INET6 +static int ip6_parsenumeric(const struct sockaddr *, const char *, char *, + size_t, int); +static int ip6_sa2str(const struct sockaddr_in6 *, char *, size_t, int); +#endif +static int getnameinfo_link(const struct sockaddr *, socklen_t, char *, + size_t, char *, size_t, int); +static int hexname(const u_int8_t *, size_t, char *, size_t); + +int +getnameinfo(const struct sockaddr *sa, socklen_t salen, + char *host, size_t hostlen, char *serv, size_t servlen, + int flags) +{ + + switch (sa->sa_family) { + case AF_INET: +#ifdef INET6 + case AF_INET6: +#endif + return getnameinfo_inet(sa, salen, host, hostlen, serv, + servlen, flags); + case AF_LINK: + return getnameinfo_link(sa, salen, host, hostlen, serv, + servlen, flags); + default: + return EAI_FAMILY; + } +} + static const struct afd { int a_af; size_t a_addrlen; @@ -79,14 +114,8 @@ struct sockinet { u_short si_port; }; -#ifdef INET6 -static int ip6_parsenumeric(const struct sockaddr *, const char *, char *, - size_t, int); -static int ip6_sa2str(const struct sockaddr_in6 *, char *, size_t, int); -#endif - -int -getnameinfo(const struct sockaddr *sa, socklen_t salen, +static int +getnameinfo_inet(const struct sockaddr *sa, socklen_t salen, char *host, size_t hostlen, char *serv, size_t servlen, int flags) { @@ -343,3 +372,82 @@ ip6_sa2str(const struct sockaddr_in6 *sa6, char *buf, size_t bufsiz, int flags) return n; } #endif /* INET6 */ + +/* + * getnameinfo_link(): + * Format a link-layer address into a printable format, paying attention to + * the interface type. + */ +/* ARGSUSED */ +static int +getnameinfo_link(const struct sockaddr *sa, socklen_t salen, + char *host, size_t hostlen, char *serv, size_t servlen, int flags) +{ + const struct sockaddr_dl *sdl = + (const struct sockaddr_dl *)(const void *)sa; + int n; + + if (serv != NULL && servlen > 0) + *serv = '\0'; + + if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 && sdl->sdl_slen == 0) { + n = snprintf(host, hostlen, "link#%d", sdl->sdl_index); + if (n > hostlen) { + *host = '\0'; + return EAI_MEMORY; + } + return 0; + } + + switch (sdl->sdl_type) { + /* + * The following have zero-length addresses. + * IFT_ATM (net/if_atmsubr.c) + * IFT_FAITH (net/if_faith.c) + * IFT_GIF (net/if_gif.c) + * IFT_LOOP (net/if_loop.c) + * IFT_PPP (net/if_ppp.c, net/if_spppsubr.c) + * IFT_SLIP (net/if_sl.c, net/if_strip.c) + * IFT_STF (net/if_stf.c) + * IFT_L2VLAN (net/if_vlan.c) + * IFT_BRIDGE (net/if_bridge.h> + */ + /* + * The following use IPv4 addresses as link-layer addresses: + * IFT_OTHER (net/if_gre.c) + * IFT_OTHER (netinet/ip_ipip.c) + */ + /* default below is believed correct for all these. */ + case IFT_ARCNET: + case IFT_ETHER: + case IFT_FDDI: + case IFT_HIPPI: + case IFT_ISO88025: + default: + return hexname((u_int8_t *)LLADDR(sdl), (size_t)sdl->sdl_alen, + host, hostlen); + } +} + +static int +hexname(cp, len, host, hostlen) + const u_int8_t *cp; + char *host; + size_t len, hostlen; +{ + int i, n; + char *outp = host; + + *outp = '\0'; + for (i = 0; i < len; i++) { + n = snprintf(outp, hostlen, "%s%02x", + i ? ":" : "", cp[i]); + if (n < 0 || n >= hostlen) { + *host = '\0'; + return EAI_MEMORY; + } + outp += n; + hostlen -= n; + } + return 0; +} |