diff options
| author | itojun <> | 2000-04-26 14:46:47 +0000 |
|---|---|---|
| committer | itojun <> | 2000-04-26 14:46:47 +0000 |
| commit | 5e878c0e17bc8bd1f2a61d2702264ebad9534cad (patch) | |
| tree | c4690c8ad9437c3758eb0c1adac30fccefebfcba | |
| parent | 8738c88e88662a775664d029d71e0085093dcd9f (diff) | |
| download | openbsd-5e878c0e17bc8bd1f2a61d2702264ebad9534cad.tar.gz openbsd-5e878c0e17bc8bd1f2a61d2702264ebad9534cad.tar.bz2 openbsd-5e878c0e17bc8bd1f2a61d2702264ebad9534cad.zip | |
bring in latest KAME implementation.
conforms to draft-ietf-ipngwg-scopedaddr-format-01.txt.
behavior change: returns numeric scopeid if we can't convert to string
removed #if 0'ed portion which we will never revisit.
Diffstat (limited to '')
| -rw-r--r-- | src/lib/libc/net/getnameinfo.c | 185 |
1 files changed, 112 insertions, 73 deletions
diff --git a/src/lib/libc/net/getnameinfo.c b/src/lib/libc/net/getnameinfo.c index c174b8a7ea..33e628c623 100644 --- a/src/lib/libc/net/getnameinfo.c +++ b/src/lib/libc/net/getnameinfo.c | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* $OpenBSD: getnameinfo.c,v 1.12 2000/03/13 02:22:12 itojun Exp $ */ | 1 | /* $OpenBSD: getnameinfo.c,v 1.13 2000/04/26 14:46:47 itojun Exp $ */ |
| 2 | 2 | ||
| 3 | /* | 3 | /* |
| 4 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. | 4 | * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project. |
| @@ -37,9 +37,15 @@ | |||
| 37 | * - RFC2553 says that we should raise error on short buffer. X/Open says | 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 | 38 | * we need to truncate the result. We obey RFC2553 (and X/Open should be |
| 39 | * modified). | 39 | * modified). |
| 40 | * - What is "local" in NI_FQDN? | ||
| 41 | * - NI_NAMEREQD and NI_NUMERICHOST conflict with each other. | ||
| 42 | * - (KAME extension) NI_WITHSCOPEID when called with global address, | ||
| 43 | * and sin6_scope_id filled | ||
| 40 | */ | 44 | */ |
| 41 | 45 | ||
| 46 | #ifndef INET6 | ||
| 42 | #define INET6 | 47 | #define INET6 |
| 48 | #endif | ||
| 43 | 49 | ||
| 44 | #include <sys/types.h> | 50 | #include <sys/types.h> |
| 45 | #include <sys/socket.h> | 51 | #include <sys/socket.h> |
| @@ -79,7 +85,9 @@ struct sockinet { | |||
| 79 | }; | 85 | }; |
| 80 | 86 | ||
| 81 | #ifdef INET6 | 87 | #ifdef INET6 |
| 82 | static char *ip6_sa2str __P((struct sockaddr_in6 *, char *, int)); | 88 | static int ip6_parsenumeric __P((const struct sockaddr *, char *, char *, |
| 89 | int, int)); | ||
| 90 | static int ip6_sa2str __P((struct sockaddr_in6 *, char *, size_t, int)); | ||
| 83 | #endif | 91 | #endif |
| 84 | 92 | ||
| 85 | #define ENI_NOSOCKET 0 | 93 | #define ENI_NOSOCKET 0 |
| @@ -207,69 +215,40 @@ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) | |||
| 207 | /* NUMERICHOST and NAMEREQD conflicts with each other */ | 215 | /* NUMERICHOST and NAMEREQD conflicts with each other */ |
| 208 | if (flags & NI_NAMEREQD) | 216 | if (flags & NI_NAMEREQD) |
| 209 | return ENI_NOHOSTNAME; | 217 | return ENI_NOHOSTNAME; |
| 210 | if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr)) | ||
| 211 | == NULL) | ||
| 212 | return ENI_SYSTEM; | ||
| 213 | numaddrlen = strlen(numaddr); | ||
| 214 | if (numaddrlen + 1 > hostlen) /* don't forget terminator */ | ||
| 215 | return ENI_MEMORY; | ||
| 216 | strcpy(host, numaddr); | ||
| 217 | #if defined(INET6) && defined(NI_WITHSCOPEID) | ||
| 218 | if (afd->a_af == AF_INET6 && | ||
| 219 | (IN6_IS_ADDR_LINKLOCAL((struct in6_addr *)addr) || | ||
| 220 | IN6_IS_ADDR_MULTICAST((struct in6_addr *)addr)) && | ||
| 221 | ((struct sockaddr_in6 *)sa)->sin6_scope_id) { | ||
| 222 | #ifndef ALWAYS_WITHSCOPE | ||
| 223 | if (flags & NI_WITHSCOPEID) | ||
| 224 | #endif /* !ALWAYS_WITHSCOPE */ | ||
| 225 | { | ||
| 226 | char scopebuf[MAXHOSTNAMELEN], *s; | ||
| 227 | int scopelen; | ||
| 228 | |||
| 229 | if ((s = ip6_sa2str((struct sockaddr_in6 *)sa, | ||
| 230 | scopebuf, 0)) == NULL) | ||
| 231 | /* XXX what should we do? */ | ||
| 232 | strcpy(scopebuf, "0"); | ||
| 233 | 218 | ||
| 234 | scopelen = strlen(scopebuf); | 219 | switch(afd->a_af) { |
| 235 | if (scopelen + 1 + numaddrlen + 1 > hostlen) | 220 | #ifdef INET6 |
| 236 | return ENI_MEMORY; | 221 | case AF_INET6: |
| 222 | { | ||
| 223 | int error; | ||
| 237 | 224 | ||
| 238 | #if 0 | 225 | if ((error = ip6_parsenumeric(sa, addr, host, |
| 239 | /* | 226 | hostlen, flags)) != 0) |
| 240 | * construct <scopeid><delim><numeric-addr> | 227 | return(error); |
| 241 | */ | 228 | break; |
| 242 | /* | 229 | } |
| 243 | * Shift the host string to allocate | ||
| 244 | * space for the scope ID part. | ||
| 245 | */ | ||
| 246 | memmove(host + scopelen + 1, host, | ||
| 247 | numaddrlen); | ||
| 248 | /* copy the scope ID and the delimiter */ | ||
| 249 | memcpy(host, scopebuf, scopelen); | ||
| 250 | host[scopelen] = SCOPE_DELIMITER; | ||
| 251 | host[scopelen + 1 + numaddrlen] = '\0'; | ||
| 252 | #else | ||
| 253 | /* | ||
| 254 | * construct <numeric-addr><delim><scopeid> | ||
| 255 | */ | ||
| 256 | memcpy(host + numaddrlen + 1, scopebuf, | ||
| 257 | scopelen); | ||
| 258 | host[numaddrlen] = SCOPE_DELIMITER; | ||
| 259 | host[numaddrlen + 1 + scopelen] = '\0'; | ||
| 260 | #endif | 230 | #endif |
| 261 | } | 231 | default: |
| 232 | if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr)) | ||
| 233 | == NULL) | ||
| 234 | return ENI_SYSTEM; | ||
| 235 | numaddrlen = strlen(numaddr); | ||
| 236 | if (numaddrlen + 1 > hostlen) /* don't forget terminator */ | ||
| 237 | return ENI_MEMORY; | ||
| 238 | strcpy(host, numaddr); | ||
| 239 | break; | ||
| 262 | } | 240 | } |
| 263 | #endif /* INET6 */ | ||
| 264 | } else { | 241 | } else { |
| 265 | hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af); | 242 | hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af); |
| 266 | h_error = h_errno; | 243 | h_error = h_errno; |
| 267 | 244 | ||
| 268 | if (hp) { | 245 | if (hp) { |
| 269 | #if 0 | 246 | #if 0 |
| 247 | /* | ||
| 248 | * commented out, since "for local host" is not | ||
| 249 | * implemented here - see RFC2553 p30 | ||
| 250 | */ | ||
| 270 | if (flags & NI_NOFQDN) { | 251 | if (flags & NI_NOFQDN) { |
| 271 | char *p; | ||
| 272 | |||
| 273 | p = strchr(hp->h_name, '.'); | 252 | p = strchr(hp->h_name, '.'); |
| 274 | if (p) | 253 | if (p) |
| 275 | *p = '\0'; | 254 | *p = '\0'; |
| @@ -282,23 +261,82 @@ getnameinfo(sa, salen, host, hostlen, serv, servlen, flags) | |||
| 282 | } else { | 261 | } else { |
| 283 | if (flags & NI_NAMEREQD) | 262 | if (flags & NI_NAMEREQD) |
| 284 | return ENI_NOHOSTNAME; | 263 | return ENI_NOHOSTNAME; |
| 285 | if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr)) | 264 | switch(afd->a_af) { |
| 286 | == NULL) | 265 | #ifdef INET6 |
| 287 | return ENI_NOHOSTNAME; | 266 | case AF_INET6: |
| 288 | if (strlen(numaddr) > hostlen) | 267 | { |
| 289 | return ENI_MEMORY; | 268 | int error; |
| 290 | strcpy(host, numaddr); | 269 | |
| 270 | if ((error = ip6_parsenumeric(sa, addr, host, | ||
| 271 | hostlen, | ||
| 272 | flags)) != 0) | ||
| 273 | return(error); | ||
| 274 | break; | ||
| 275 | } | ||
| 276 | #endif | ||
| 277 | default: | ||
| 278 | if (inet_ntop(afd->a_af, addr, host, | ||
| 279 | hostlen) == NULL) | ||
| 280 | return ENI_SYSTEM; | ||
| 281 | break; | ||
| 282 | } | ||
| 291 | } | 283 | } |
| 292 | } | 284 | } |
| 293 | return SUCCESS; | 285 | return SUCCESS; |
| 294 | } | 286 | } |
| 295 | 287 | ||
| 296 | #ifdef INET6 | 288 | #ifdef INET6 |
| 289 | static int | ||
| 290 | ip6_parsenumeric(sa, addr, host, hostlen, flags) | ||
| 291 | const struct sockaddr *sa; | ||
| 292 | char *addr, *host; | ||
| 293 | int flags, hostlen; | ||
| 294 | { | ||
| 295 | int numaddrlen; | ||
| 296 | char numaddr[512]; | ||
| 297 | |||
| 298 | if (inet_ntop(AF_INET6, addr, numaddr, sizeof(numaddr)) | ||
| 299 | == NULL) | ||
| 300 | return ENI_SYSTEM; | ||
| 301 | |||
| 302 | numaddrlen = strlen(numaddr); | ||
| 303 | if (numaddrlen + 1 > hostlen) /* don't forget terminator */ | ||
| 304 | return ENI_MEMORY; | ||
| 305 | strcpy(host, numaddr); | ||
| 306 | |||
| 307 | #ifdef NI_WITHSCOPEID | ||
| 308 | if (((struct sockaddr_in6 *)sa)->sin6_scope_id) { | ||
| 309 | if (flags & NI_WITHSCOPEID) | ||
| 310 | { | ||
| 311 | char scopebuf[MAXHOSTNAMELEN]; | ||
| 312 | int scopelen; | ||
| 313 | |||
| 314 | /* ip6_sa2str never fails */ | ||
| 315 | scopelen = ip6_sa2str((struct sockaddr_in6 *)sa, | ||
| 316 | scopebuf, sizeof(scopebuf), | ||
| 317 | 0); | ||
| 318 | if (scopelen + 1 + numaddrlen + 1 > hostlen) | ||
| 319 | return ENI_MEMORY; | ||
| 320 | /* | ||
| 321 | * construct <numeric-addr><delim><scopeid> | ||
| 322 | */ | ||
| 323 | memcpy(host + numaddrlen + 1, scopebuf, | ||
| 324 | scopelen); | ||
| 325 | host[numaddrlen] = SCOPE_DELIMITER; | ||
| 326 | host[numaddrlen + 1 + scopelen] = '\0'; | ||
| 327 | } | ||
| 328 | } | ||
| 329 | #endif /* NI_WITHSCOPEID */ | ||
| 330 | |||
| 331 | return 0; | ||
| 332 | } | ||
| 333 | |||
| 297 | /* ARGSUSED */ | 334 | /* ARGSUSED */ |
| 298 | static char * | 335 | static int |
| 299 | ip6_sa2str(sa6, buf, flags) | 336 | ip6_sa2str(sa6, buf, bufsiz, flags) |
| 300 | struct sockaddr_in6 *sa6; | 337 | struct sockaddr_in6 *sa6; |
| 301 | char *buf; | 338 | char *buf; |
| 339 | size_t bufsiz; | ||
| 302 | int flags; | 340 | int flags; |
| 303 | { | 341 | { |
| 304 | unsigned int ifindex = (unsigned int)sa6->sin6_scope_id; | 342 | unsigned int ifindex = (unsigned int)sa6->sin6_scope_id; |
| @@ -306,19 +344,20 @@ ip6_sa2str(sa6, buf, flags) | |||
| 306 | 344 | ||
| 307 | #ifdef notyet | 345 | #ifdef notyet |
| 308 | if (flags & NI_NUMERICSCOPE) { | 346 | if (flags & NI_NUMERICSCOPE) { |
| 309 | sprintf(buf, "%d", sa6->sin6_scope_id); | 347 | return(snprintf(buf, bufsiz, "%d", sa6->sin6_scope_id)); |
| 310 | return(buf); | ||
| 311 | } | 348 | } |
| 312 | #endif | 349 | #endif |
| 313 | 350 | ||
| 314 | if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) | 351 | /* if_indextoname() does not take buffer size. not a good api... */ |
| 315 | return(if_indextoname(ifindex, buf)); | 352 | if ((IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6)) && |
| 316 | 353 | bufsiz >= IF_NAMESIZE) { | |
| 317 | if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6)) | 354 | char *p = if_indextoname(ifindex, buf); |
| 318 | return(NULL); /* XXX */ | 355 | if (p) { |
| 319 | if (IN6_IS_ADDR_MC_ORGLOCAL(a6)) | 356 | return(strlen(p)); |
| 320 | return(NULL); /* XXX */ | 357 | } |
| 358 | } | ||
| 321 | 359 | ||
| 322 | return(NULL); /* XXX */ | 360 | /* last resort */ |
| 361 | return(snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id)); | ||
| 323 | } | 362 | } |
| 324 | #endif | 363 | #endif /* INET6 */ |
