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