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