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 <ctype.h> 7#include <stdlib.h> 8#include <string.h> 9#include <fcntl.h> 10#include <unistd.h> 11#include <pthread.h> 12#include <errno.h> 13#include "lookup.h" 14#include "stdio_impl.h" 15#include "syscall.h" 16 17static int is_valid_hostname(const char *host) 18{ 19 const unsigned char *s; 20 if (strnlen(host, 255)-1 >= 254 || mbstowcs(0, host, 0) == -1) return 0; 21 for (s=(void *)host; *s>=0x80 || *s=='.' || *s=='-' || isalnum(*s); s++); 22 return !*s; 23} 24 25static int name_from_null(struct address buf[static 2], const char *name, int family, int flags) 26{ 27 int cnt = 0; 28 if (name) return 0; 29 if (flags & AI_PASSIVE) { 30 if (family != AF_INET6) 31 buf[cnt++] = (struct address){ .family = AF_INET }; 32 if (family != AF_INET) 33 buf[cnt++] = (struct address){ .family = AF_INET6 }; 34 } else { 35 if (family != AF_INET6) 36 buf[cnt++] = (struct address){ .family = AF_INET, .addr = { 127,0,0,1 } }; 37 if (family != AF_INET) 38 buf[cnt++] = (struct address){ .family = AF_INET6, .addr = { [15] = 1 } }; 39 } 40 return cnt; 41} 42 43static int name_from_numeric(struct address buf[static 1], const char *name, int family) 44{ 45 return __lookup_ipliteral(buf, name, family); 46} 47 48static int name_from_hosts(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family) 49{ 50 char line[512]; 51 size_t l = strlen(name); 52 int cnt = 0, badfam = 0; 53 unsigned char _buf[1032]; 54 FILE _f, *f = __fopen_rb_ca("/etc/hosts", &_f, _buf, sizeof _buf); 55 if (!f) switch (errno) { 56 case ENOENT: 57 case ENOTDIR: 58 case EACCES: 59 return 0; 60 default: 61 return EAI_SYSTEM; 62 } 63 while (fgets(line, sizeof line, f) && cnt < MAXADDRS) { 64 char *p, *z; 65 66 if ((p=strchr(line, '#'))) *p++='\n', *p=0; 67 for(p=line+1; (p=strstr(p, name)) && 68 (!isspace(p[-1]) || !isspace(p[l])); p++); 69 if (!p) continue; 70 71 /* Isolate IP address to parse */ 72 for (p=line; *p && !isspace(*p); p++); 73 *p++ = 0; 74 switch (name_from_numeric(buf+cnt, line, family)) { 75 case 1: 76 cnt++; 77 break; 78 case 0: 79 continue; 80 default: 81 badfam = EAI_NONAME; 82 continue; 83 } 84 85 /* Extract first name as canonical name */ 86 for (; *p && isspace(*p); p++); 87 for (z=p; *z && !isspace(*z); z++); 88 *z = 0; 89 if (is_valid_hostname(p)) memcpy(canon, p, z-p+1); 90 } 91 __fclose_ca(f); 92 return cnt ? cnt : badfam; 93} 94 95struct dpc_ctx { 96 struct address *addrs; 97 char *canon; 98 int cnt; 99}; 100 101int __dns_parse(const unsigned char *, int, int (*)(void *, int, const void *, int, const void *), void *); 102int __dn_expand(const unsigned char *, const unsigned char *, const unsigned char *, char *, int); 103int __res_mkquery(int, const char *, int, int, const unsigned char *, int, const unsigned char*, unsigned char *, int); 104int __res_msend_rc(int, const unsigned char *const *, const int *, unsigned char *const *, int *, int, const struct resolvconf *); 105 106#define RR_A 1 107#define RR_CNAME 5 108#define RR_AAAA 28 109 110static int dns_parse_callback(void *c, int rr, const void *data, int len, const void *packet) 111{ 112 char tmp[256]; 113 struct dpc_ctx *ctx = c; 114 switch (rr) { 115 case RR_A: 116 if (len != 4) return -1; 117 ctx->addrs[ctx->cnt].family = AF_INET; 118 ctx->addrs[ctx->cnt].scopeid = 0; 119 memcpy(ctx->addrs[ctx->cnt++].addr, data, 4); 120 break; 121 case RR_AAAA: 122 if (len != 16) return -1; 123 ctx->addrs[ctx->cnt].family = AF_INET6; 124 ctx->addrs[ctx->cnt].scopeid = 0; 125 memcpy(ctx->addrs[ctx->cnt++].addr, data, 16); 126 break; 127 case RR_CNAME: 128 if (__dn_expand(packet, (const unsigned char *)packet + 512, 129 data, tmp, sizeof tmp) > 0 && is_valid_hostname(tmp)) 130 strcpy(ctx->canon, tmp); 131 break; 132 } 133 return 0; 134} 135 136static int name_from_dns(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family, const struct resolvconf *conf) 137{ 138 unsigned char qbuf[2][280], abuf[2][512]; 139 const unsigned char *qp[2] = { qbuf[0], qbuf[1] }; 140 unsigned char *ap[2] = { abuf[0], abuf[1] }; 141 int qlens[2], alens[2]; 142 int i, nq = 0; 143 struct dpc_ctx ctx = { .addrs = buf, .canon = canon }; 144 static const struct { int af; int rr; } afrr[2] = { 145 { .af = AF_INET6, .rr = RR_A }, 146 { .af = AF_INET, .rr = RR_AAAA }, 147 }; 148 149 for (i=0; i<2; i++) { 150 if (family != afrr[i].af) { 151 qlens[nq] = __res_mkquery(0, name, 1, afrr[i].rr, 152 0, 0, 0, qbuf[nq], sizeof *qbuf); 153 if (qlens[nq] == -1) 154 return EAI_NONAME; 155 nq++; 156 } 157 } 158 159 if (__res_msend_rc(nq, qp, qlens, ap, alens, sizeof *abuf, conf) < 0) 160 return EAI_SYSTEM; 161 162 for (i=0; i<nq; i++) 163 __dns_parse(abuf[i], alens[i], dns_parse_callback, &ctx); 164 165 if (ctx.cnt) return ctx.cnt; 166 if (alens[0] < 4 || (abuf[0][3] & 15) == 2) return EAI_AGAIN; 167 if ((abuf[0][3] & 15) == 0) return EAI_NONAME; 168 if ((abuf[0][3] & 15) == 3) return 0; 169 return EAI_FAIL; 170} 171 172static int name_from_dns_search(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family) 173{ 174 char search[256]; 175 struct resolvconf conf; 176 size_t l, dots; 177 char *p, *z; 178 179 if (__get_resolv_conf(&conf, search, sizeof search) < 0) return -1; 180 181 /* Count dots, suppress search when >=ndots or name ends in 182 * a dot, which is an explicit request for global scope. */ 183 for (dots=l=0; name[l]; l++) if (name[l]=='.') dots++; 184 if (dots >= conf.ndots || name[l-1]=='.') *search = 0; 185 186 /* This can never happen; the caller already checked length. */ 187 if (l >= 256) return EAI_NONAME; 188 189 /* Name with search domain appended is setup in canon[]. This both 190 * provides the desired default canonical name (if the requested 191 * name is not a CNAME record) and serves as a buffer for passing 192 * the full requested name to name_from_dns. */ 193 memcpy(canon, name, l); 194 canon[l] = '.'; 195 196 for (p=search; *p; p=z) { 197 for (; isspace(*p); p++); 198 for (z=p; *z && !isspace(*z); z++); 199 if (z==p) break; 200 if (z-p < 256 - l - 1) { 201 memcpy(canon+l+1, p, z-p); 202 canon[z-p+1+l] = 0; 203 int cnt = name_from_dns(buf, canon, canon, family, &conf); 204 if (cnt) return cnt; 205 } 206 } 207 208 canon[l] = 0; 209 return name_from_dns(buf, canon, name, family, &conf); 210} 211 212static const struct policy { 213 unsigned char addr[16]; 214 unsigned char len, mask; 215 unsigned char prec, label; 216} defpolicy[] = { 217 { "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1", 15, 0xff, 50, 0 }, 218 { "\0\0\0\0\0\0\0\0\0\0\xff\xff", 11, 0xff, 35, 4 }, 219 { "\x20\2", 1, 0xff, 30, 2 }, 220 { "\x20\1", 3, 0xff, 5, 5 }, 221 { "\xfc", 0, 0xfe, 3, 13 }, 222#if 0 223 /* These are deprecated and/or returned to the address 224 * pool, so despite the RFC, treating them as special 225 * is probably wrong. */ 226 { "", 11, 0xff, 1, 3 }, 227 { "\xfe\xc0", 1, 0xc0, 1, 11 }, 228 { "\x3f\xfe", 1, 0xff, 1, 12 }, 229#endif 230 /* Last rule must match all addresses to stop loop. */ 231 { "", 0, 0, 40, 1 }, 232}; 233 234static const struct policy *policyof(const struct in6_addr *a) 235{ 236 int i; 237 for (i=0; ; i++) { 238 if (memcmp(a->s6_addr, defpolicy[i].addr, defpolicy[i].len)) 239 continue; 240 if ((a->s6_addr[defpolicy[i].len] & defpolicy[i].mask) 241 != defpolicy[i].addr[defpolicy[i].len]) 242 continue; 243 return defpolicy+i; 244 } 245} 246 247static int labelof(const struct in6_addr *a) 248{ 249 return policyof(a)->label; 250} 251 252static int scopeof(const struct in6_addr *a) 253{ 254 if (IN6_IS_ADDR_MULTICAST(a)) return a->s6_addr[1] & 15; 255 if (IN6_IS_ADDR_LINKLOCAL(a)) return 2; 256 if (IN6_IS_ADDR_LOOPBACK(a)) return 2; 257 if (IN6_IS_ADDR_SITELOCAL(a)) return 5; 258 return 14; 259} 260 261static int prefixmatch(const struct in6_addr *s, const struct in6_addr *d) 262{ 263 /* FIXME: The common prefix length should be limited to no greater 264 * than the nominal length of the prefix portion of the source 265 * address. However the definition of the source prefix length is 266 * not clear and thus this limiting is not yet implemented. */ 267 unsigned i; 268 for (i=0; i<128 && !((s->s6_addr[i/8]^d->s6_addr[i/8])&(128>>(i%8))); i++); 269 return i; 270} 271 272#define DAS_USABLE 0x40000000 273#define DAS_MATCHINGSCOPE 0x20000000 274#define DAS_MATCHINGLABEL 0x10000000 275#define DAS_PREC_SHIFT 20 276#define DAS_SCOPE_SHIFT 16 277#define DAS_PREFIX_SHIFT 8 278#define DAS_ORDER_SHIFT 0 279 280static int addrcmp(const void *_a, const void *_b) 281{ 282 const struct address *a = _a, *b = _b; 283 return b->sortkey - a->sortkey; 284} 285 286int __lookup_name(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family, int flags) 287{ 288 int cnt = 0, i, j; 289 290 *canon = 0; 291 if (name) { 292 /* reject empty name and check len so it fits into temp bufs */ 293 size_t l = strnlen(name, 255); 294 if (l-1 >= 254) 295 return EAI_NONAME; 296 memcpy(canon, name, l+1); 297 } 298 299 /* Procedurally, a request for v6 addresses with the v4-mapped 300 * flag set is like a request for unspecified family, followed 301 * by filtering of the results. */ 302 if (flags & AI_V4MAPPED) { 303 if (family == AF_INET6) family = AF_UNSPEC; 304 else flags -= AI_V4MAPPED; 305 } 306 307 /* Try each backend until there's at least one result. */ 308 cnt = name_from_null(buf, name, family, flags); 309 if (!cnt) cnt = name_from_numeric(buf, name, family); 310 if (!cnt && !(flags & AI_NUMERICHOST)) { 311 cnt = name_from_hosts(buf, canon, name, family); 312 if (!cnt) cnt = name_from_dns_search(buf, canon, name, family); 313 } 314 if (cnt<=0) return cnt ? cnt : EAI_NONAME; 315 316 /* Filter/transform results for v4-mapped lookup, if requested. */ 317 if (flags & AI_V4MAPPED) { 318 if (!(flags & AI_ALL)) { 319 /* If any v6 results exist, remove v4 results. */ 320 for (i=0; i<cnt && buf[i].family != AF_INET6; i++); 321 if (i<cnt) { 322 for (j=0; i<cnt; i++) { 323 if (buf[i].family == AF_INET6) 324 buf[j++] = buf[i]; 325 } 326 cnt = i = j; 327 } 328 } 329 /* Translate any remaining v4 results to v6 */ 330 for (i=0; i<cnt; i++) { 331 if (buf[i].family != AF_INET) continue; 332 memcpy(buf[i].addr+12, buf[i].addr, 4); 333 memcpy(buf[i].addr, "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12); 334 buf[i].family = AF_INET6; 335 } 336 } 337 338 /* No further processing is needed if there are fewer than 2 339 * results or if there are only IPv4 results. */ 340 if (cnt<2 || family==AF_INET) return cnt; 341 for (i=0; buf[i].family == AF_INET; i++) 342 if (i==cnt) return cnt; 343 344 int cs; 345 pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs); 346 347 /* The following implements a subset of RFC 3484/6724 destination 348 * address selection by generating a single 31-bit sort key for 349 * each address. Rules 3, 4, and 7 are omitted for having 350 * excessive runtime and code size cost and dubious benefit. 351 * So far the label/precedence table cannot be customized. */ 352 for (i=0; i<cnt; i++) { 353 int key = 0; 354 struct sockaddr_in6 sa, da = { 355 .sin6_family = AF_INET6, 356 .sin6_scope_id = buf[i].scopeid, 357 .sin6_port = 65535 358 }; 359 if (buf[i].family == AF_INET6) { 360 memcpy(da.sin6_addr.s6_addr, buf[i].addr, 16); 361 } else { 362 memcpy(da.sin6_addr.s6_addr, 363 "\0\0\0\0\0\0\0\0\0\0\xff\xff", 12); 364 memcpy(da.sin6_addr.s6_addr+12, buf[i].addr, 4); 365 } 366 const struct policy *dpolicy = policyof(&da.sin6_addr); 367 int dscope = scopeof(&da.sin6_addr); 368 int dlabel = dpolicy->label; 369 int dprec = dpolicy->prec; 370 int prefixlen = 0; 371 int fd = socket(AF_INET6, SOCK_DGRAM|SOCK_CLOEXEC, IPPROTO_UDP); 372 if (fd >= 0) { 373 if (!connect(fd, (void *)&da, sizeof da)) { 374 key |= DAS_USABLE; 375 if (!getsockname(fd, (void *)&sa, 376 &(socklen_t){sizeof sa})) { 377 if (dscope == scopeof(&sa.sin6_addr)) 378 key |= DAS_MATCHINGSCOPE; 379 if (dlabel == labelof(&sa.sin6_addr)) 380 key |= DAS_MATCHINGLABEL; 381 prefixlen = prefixmatch(&sa.sin6_addr, 382 &da.sin6_addr); 383 } 384 } 385 close(fd); 386 } 387 key |= dprec << DAS_PREC_SHIFT; 388 key |= (15-dscope) << DAS_SCOPE_SHIFT; 389 key |= prefixlen << DAS_PREFIX_SHIFT; 390 key |= (MAXADDRS-i) << DAS_ORDER_SHIFT; 391 buf[i].sortkey = key; 392 } 393 qsort(buf, cnt, sizeof *buf, addrcmp); 394 395 pthread_setcancelstate(cs, 0); 396 397 return cnt; 398} 399