lookup_name.c raw

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