Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(205)

Side by Side Diff: fusl/src/network/lookup_name.c

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

Powered by Google App Engine
This is Rietveld 408576698