1#include <sys/socket.h> 2#include <netinet/in.h> 3#include <netdb.h> 4#include <net/if.h> 5#include <arpa/inet.h> 6#include <limits.h> 7#include <stdlib.h> 8#include <string.h> 9#include <ctype.h> 10#include "lookup.h" 11 12int __inet_aton(const char *, struct in_addr *); 13 14int __lookup_ipliteral(struct address buf[static 1], const char *name, int family) 15{ 16 struct in_addr a4; 17 struct in6_addr a6; 18 if (__inet_aton(name, &a4) > 0) { 19 if (family == AF_INET6) /* wrong family */ 20 return EAI_NONAME; 21 memcpy(&buf[0].addr, &a4, sizeof a4); 22 buf[0].family = AF_INET; 23 buf[0].scopeid = 0; 24 return 1; 25 } 26 27 char tmp[64]; 28 char *p = strchr(name, '%'), *z; 29 unsigned long long scopeid = 0; 30 if (p && p-name < 64) { 31 memcpy(tmp, name, p-name); 32 tmp[p-name] = 0; 33 name = tmp; 34 } 35 36 if (inet_pton(AF_INET6, name, &a6) <= 0) 37 return 0; 38 if (family == AF_INET) /* wrong family */ 39 return EAI_NONAME; 40 41 memcpy(&buf[0].addr, &a6, sizeof a6); 42 buf[0].family = AF_INET6; 43 if (p) { 44 if (isdigit(*++p)) scopeid = strtoull(p, &z, 10); 45 else z = p-1; 46 if (*z) { 47 if (!IN6_IS_ADDR_LINKLOCAL(&a6) && 48 !IN6_IS_ADDR_MC_LINKLOCAL(&a6)) 49 return EAI_NONAME; 50 scopeid = if_nametoindex(p); 51 if (!scopeid) return EAI_NONAME; 52 } 53 if (scopeid > UINT_MAX) return EAI_NONAME; 54 } 55 buf[0].scopeid = scopeid; 56 return 1; 57} 58