~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Nginx/core/ngx_inet.c

Version: ~ [ nginx-0.6.26 ] ~ [ nginx-0.5.35 ] ~ [ nginx-0.5.20 ] ~ [ nginx-0.5.19 ] ~

  1 
  2 /*
  3  * Copyright (C) Igor Sysoev
  4  */
  5 
  6 
  7 #include <ngx_config.h>
  8 #include <ngx_core.h>
  9 
 10 
 11 static size_t ngx_sprint_uchar(u_char *text, u_char c, size_t len);
 12 
 13 
 14 /* AF_INET only */
 15 
 16 in_addr_t
 17 ngx_inet_addr(u_char *text, size_t len)
 18 {
 19     u_char      *p, c;
 20     in_addr_t    addr;
 21     ngx_uint_t   octet, n;
 22 
 23     addr = 0;
 24     octet = 0;
 25     n = 0;
 26 
 27     for (p = text; p < text + len; p++) {
 28 
 29         c = *p;
 30 
 31         if (c >= '' && c <= '9') {
 32             octet = octet * 10 + (c - '');
 33             continue;
 34         }
 35 
 36         if (c == '.' && octet < 256) {
 37             addr = (addr << 8) + octet;
 38             octet = 0;
 39             n++;
 40             continue;
 41         }
 42 
 43         return INADDR_NONE;
 44     }
 45 
 46     if (n != 3) {
 47         return INADDR_NONE;
 48     }
 49 
 50     if (octet < 256) {
 51         addr = (addr << 8) + octet;
 52         return htonl(addr);
 53     }
 54 
 55     return INADDR_NONE;
 56 }
 57 
 58 
 59 /*
 60  * ngx_sock_ntop() and ngx_inet_ntop() may be implemented as
 61  * "ngx_sprintf(text, "%ud.%ud.%ud.%ud", p[0], p[1], p[2], p[3])", however,
 62  * they had been implemented long before the ngx_sprintf() had appeared
 63  * and they are faster by 1.5-2.5 times, so it is worth to keep them.
 64  *
 65  * By the way, the implementation using ngx_sprintf() is faster by 2.5-3 times
 66  * than using FreeBSD libc's snprintf().
 67  */
 68 
 69 /* AF_INET only */
 70 
 71 size_t
 72 ngx_sock_ntop(int family, struct sockaddr *sa, u_char *text, size_t len)
 73 {
 74     u_char              *p;
 75     size_t               n;
 76     ngx_uint_t           i;
 77     struct sockaddr_in  *sin;
 78 
 79     if (len == 0) {
 80         return 0;
 81     }
 82 
 83     if (family != AF_INET) {
 84         return 0;
 85     }
 86 
 87     sin = (struct sockaddr_in *) sa;
 88     p = (u_char *) &sin->sin_addr;
 89 
 90     if (len > INET_ADDRSTRLEN) {
 91         len = INET_ADDRSTRLEN;
 92     }
 93 
 94     n = ngx_sprint_uchar(text, p[0], len);
 95 
 96     i = 1;
 97 
 98     do {
 99         if (len == n) {
100             text[n - 1] = '\0';
101             return n;
102         }
103 
104         text[n++] = '.';
105 
106         if (len == n) {
107             text[n - 1] = '\0';
108             return n;
109         }
110 
111         n += ngx_sprint_uchar(&text[n], p[i++], len - n);
112 
113     } while (i < 4);
114 
115     if (len == n) {
116         text[n] = '\0';
117         return n;
118     }
119 
120     text[n] = '\0';
121 
122     return n;
123 }
124 
125 
126 size_t
127 ngx_inet_ntop(int family, void *addr, u_char *text, size_t len)
128 {
129     u_char      *p;
130     size_t       n;
131     ngx_uint_t   i;
132 
133     if (len == 0) {
134         return 0;
135     }
136 
137     if (family != AF_INET) {
138         return 0;
139     }
140 
141     p = (u_char *) addr;
142 
143     if (len > INET_ADDRSTRLEN) {
144         len = INET_ADDRSTRLEN;
145     }
146 
147     n = ngx_sprint_uchar(text, p[0], len);
148 
149     i = 1;
150 
151     do {
152         if (len == n) {
153             text[n - 1] = '\0';
154             return n;
155         }
156 
157         text[n++] = '.';
158 
159         if (len == n) {
160             text[n - 1] = '\0';
161             return n;
162         }
163 
164         n += ngx_sprint_uchar(&text[n], p[i++], len - n);
165 
166     } while (i < 4);
167 
168     if (len == n) {
169         text[n] = '\0';
170         return n;
171     }
172 
173     text[n] = '\0';
174 
175     return n;
176 }
177 
178 
179 static size_t
180 ngx_sprint_uchar(u_char *text, u_char c, size_t len)
181 {
182     size_t      n;
183     ngx_uint_t  c1, c2;
184 
185     n = 0;
186 
187     if (len == n) {
188         return n;
189     }
190 
191     c1 = c / 100;
192 
193     if (c1) {
194         *text++ = (u_char) (c1 + '');
195         n++;
196 
197         if (len == n) {
198             return n;
199         }
200     }
201 
202     c2 = (c % 100) / 10;
203 
204     if (c1 || c2) {
205         *text++ = (u_char) (c2 + '');
206         n++;
207 
208         if (len == n) {
209             return n;
210         }
211     }
212 
213     c2 = c % 10;
214 
215     *text = (u_char) (c2 + '');
216     n++;
217 
218     return n;
219 }
220 
221 
222 /* AF_INET only */
223 
224 ngx_int_t
225 ngx_ptocidr(ngx_str_t *text, void *cidr)
226 {
227     ngx_int_t         m;
228     ngx_uint_t        i;
229     ngx_inet_cidr_t  *in_cidr;
230 
231     in_cidr = cidr;
232 
233     for (i = 0; i < text->len; i++) {
234         if (text->data[i] == '/') {
235             break;
236         }
237     }
238 
239     if (i == text->len) {
240         return NGX_ERROR;
241     }
242 
243     text->data[i] = '\0';
244     in_cidr->addr = inet_addr((char *) text->data);
245     text->data[i] = '/';
246     if (in_cidr->addr == INADDR_NONE) {
247         return NGX_ERROR;
248     }
249 
250     m = ngx_atoi(&text->data[i + 1], text->len - (i + 1));
251     if (m == NGX_ERROR) {
252         return NGX_ERROR;
253     }
254 
255     if (m == 0) {
256 
257         /* the x86 compilers use the shl instruction that shifts by modulo 32 */
258 
259         in_cidr->mask = 0;
260         return NGX_OK;
261     }
262 
263     in_cidr->mask = htonl((ngx_uint_t) (0 - (1 << (32 - m))));
264 
265     if (in_cidr->addr == (in_cidr->addr & in_cidr->mask)) {
266         return NGX_OK;
267     }
268 
269     in_cidr->addr &= in_cidr->mask;
270 
271     return NGX_DONE;
272 }
273 
274 
275 ngx_int_t
276 ngx_parse_url(ngx_pool_t *pool, ngx_url_t *u)
277 {
278     u_char              *p, *host, *port_start;
279     size_t               len, port_len;
280     ngx_int_t            port;
281     ngx_uint_t           i;
282     struct hostent      *h;
283 #if (NGX_HAVE_UNIX_DOMAIN)
284     struct sockaddr_un  *saun;
285 #endif
286 
287     len = u->url.len;
288     p = u->url.data;
289 
290     if (ngx_strncasecmp(p, (u_char *) "unix:", 5) == 0) {
291 
292 #if (NGX_HAVE_UNIX_DOMAIN)
293 
294         p += 5;
295         len -= 5;
296 
297         u->uri.len = len;
298         u->uri.data = p;
299 
300         if (u->uri_part) {
301             for (i = 0; i < len; i++) {
302 
303                 if (p[i] == ':') {
304                     len = i;
305 
306                     u->uri.len -= len + 1;
307                     u->uri.data += len + 1;
308 
309                     break;
310                 }
311             }
312         }
313 
314         if (len == 0) {
315             u->err = "no path in the unix domain socket";
316             return NGX_ERROR;
317         }
318 
319         if (len + 1 > sizeof(saun->sun_path)) {
320             u->err = "too long path in the unix domain socket";
321             return NGX_ERROR;
322         }
323 
324         u->addrs = ngx_pcalloc(pool, sizeof(ngx_peer_addr_t));
325         if (u->addrs == NULL) {
326             return NGX_ERROR;
327         }
328 
329         saun = ngx_pcalloc(pool, sizeof(struct sockaddr_un));
330         if (saun == NULL) {
331             return NGX_ERROR;
332         }
333 
334         u->naddrs = 1;
335 
336         saun->sun_family = AF_UNIX;
337         (void) ngx_cpystrn((u_char *) saun->sun_path, p, len + 1);
338 
339         u->addrs[0].sockaddr = (struct sockaddr *) saun;
340         u->addrs[0].socklen = sizeof(struct sockaddr_un);
341         u->addrs[0].name.len = len + 5;
342         u->addrs[0].name.data = u->url.data;
343 
344         u->host.len = len;
345         u->host.data = p;
346 
347         u->unix_socket = 1;
348 
349         return NGX_OK;
350 
351 #else
352         u->err = "the unix domain sockets are not supported on this platform";
353 
354         return NGX_ERROR;
355 
356 #endif
357     }
358 
359     if ((p[0] == ':' || p[0] == '/') && !u->listen) {
360         u->err = "invalid host";
361         return NGX_ERROR;
362     }
363 
364     u->host.data = p;
365 
366     port_start = NULL;
367     port_len = 0;
368 
369     for (i = 0; i < len; i++) {
370 
371         if (p[i] == ':') {
372             port_start = &p[i + 1];
373             u->host.len = i;
374 
375             if (!u->uri_part) {
376                 port_len = len - (i + 1);
377                 break;
378             }
379         }
380 
381         if (p[i] == '/') {
382             u->uri.len = len - i;
383             u->uri.data = &p[i];
384 
385             if (u->host.len == 0) {
386                 u->host.len = i;
387             }
388 
389             if (port_start == NULL) {
390                 u->no_port = 1;
391                 goto no_port;
392             }
393 
394             port_len = &p[i] - port_start;
395 
396             if (port_len == 0) {
397                 u->err = "invalid port";
398                 return NGX_ERROR;
399             }
400 
401             break;
402         }
403     }
404 
405     if (port_start) {
406 
407         if (port_len == 0) {
408             port_len = &p[i] - port_start;
409 
410             if (port_len == 0) {
411                 u->err = "invalid port";
412                 return NGX_ERROR;
413             }
414         }
415 
416         port = ngx_atoi(port_start, port_len);
417 
418         if (port == NGX_ERROR || port < 1 || port > 65536) {
419             u->err = "invalid port";
420             return NGX_ERROR;
421         }
422 
423         u->port_text.len = port_len;
424         u->port_text.data = port_start;
425 
426     } else {
427         port = ngx_atoi(p, len);
428 
429         if (port == NGX_ERROR) {
430             u->host.len = len;
431             u->no_port = 1;
432 
433             goto no_port;
434         }
435 
436         u->wildcard = 1;
437     }
438 
439     u->port = (in_port_t) port;
440 
441 no_port:
442 
443     if (u->listen) {
444 
445         if (u->port == 0) {
446             if (u->default_port == 0) {
447                 u->err = "no port";
448                 return NGX_ERROR;
449             }
450 
451             u->port = u->default_port;
452         }
453 
454         if (u->host.len == 1 && u->host.data[0] == '*') {
455             u->host.len = 0;
456         }
457 
458         /* AF_INET only */
459 
460         if (u->host.len) {
461 
462             host = ngx_alloc(u->host.len + 1, pool->log);
463             if (host == NULL) {
464                 return NGX_ERROR;
465             }
466 
467             (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);
468 
469             u->addr.in_addr = inet_addr((const char *) host);
470 
471             if (u->addr.in_addr == INADDR_NONE) {
472                 h = gethostbyname((const char *) host);
473 
474                 if (h == NULL || h->h_addr_list[0] == NULL) {
475                     ngx_free(host);
476                     u->err = "host not found";
477                     return NGX_ERROR;
478                 }
479 
480                 u->addr.in_addr = *(in_addr_t *) (h->h_addr_list[0]);
481             }
482 
483             ngx_free(host);
484 
485         } else {
486             u->addr.in_addr = INADDR_ANY;
487         }
488 
489         return NGX_OK;
490     }
491 
492     if (u->host.len == 0) {
493         u->err = "no host";
494         return NGX_ERROR;
495     }
496 
497     if (u->no_resolve) {
498         return NGX_OK;
499     }
500 
501     if (u->no_port) {
502         u->port = u->default_port;
503     }
504 
505     if (u->port == 0) {
506         u->err = "no port";
507         return NGX_ERROR;
508     }
509 
510     if (ngx_inet_resolve_host(pool, u) != NGX_OK) {
511         return NGX_ERROR;
512     }
513 
514     return NGX_OK;
515 }
516 
517 
518 ngx_int_t
519 ngx_inet_resolve_host(ngx_pool_t *pool, ngx_url_t *u)
520 {
521     u_char              *p, *host;
522     size_t               len;
523     in_addr_t            in_addr;
524     ngx_uint_t           i;
525     struct hostent      *h;
526     struct sockaddr_in  *sin;
527 
528     host = ngx_alloc(u->host.len + 1, pool->log);
529     if (host == NULL) {
530         return NGX_ERROR;
531     }
532 
533     (void) ngx_cpystrn(host, u->host.data, u->host.len + 1);
534 
535     /* AF_INET only */
536 
537     in_addr = inet_addr((char *) host);
538 
539     if (in_addr == INADDR_NONE) {
540         h = gethostbyname((char *) host);
541 
542         ngx_free(host);
543 
544         if (h == NULL || h->h_addr_list[0] == NULL) {
545             u->err = "host not found";
546             return NGX_ERROR;
547         }
548 
549         if (u->one_addr == 0) {
550             for (i = 0; h->h_addr_list[i] != NULL; i++) { /* void */ }
551 
552         } else {
553             i = 1;
554         }
555 
556         /* MP: ngx_shared_palloc() */
557 
558         u->addrs = ngx_pcalloc(pool, i * sizeof(ngx_peer_addr_t));
559         if (u->addrs == NULL) {
560             return NGX_ERROR;
561         }
562 
563         u->naddrs = i;
564 
565         for (i = 0; h->h_addr_list[i] != NULL; i++) {
566 
567             sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
568             if (sin == NULL) {
569                 return NGX_ERROR;
570             }
571 
572             sin->sin_family = AF_INET;
573             sin->sin_port = htons(u->port);
574             sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]);
575 
576             u->addrs[i].sockaddr = (struct sockaddr *) sin;
577             u->addrs[i].socklen = sizeof(struct sockaddr_in);
578 
579             len = INET_ADDRSTRLEN - 1 + 1 + sizeof(":65536") - 1;
580 
581             p = ngx_palloc(pool, len);
582             if (p == NULL) {
583                 return NGX_ERROR;
584             }
585 
586             len = ngx_sock_ntop(AF_INET, (struct sockaddr *) sin, p, len);
587 
588             u->addrs[i].name.len = ngx_sprintf(&p[len], ":%d", u->port) - p;
589             u->addrs[i].name.data = p;
590         }
591 
592     } else {
593 
594         ngx_free(host);
595 
596         /* MP: ngx_shared_palloc() */
597 
598         u->addrs = ngx_pcalloc(pool, sizeof(ngx_peer_addr_t));
599         if (u->addrs == NULL) {
600             return NGX_ERROR;
601         }
602 
603         sin = ngx_pcalloc(pool, sizeof(struct sockaddr_in));
604         if (sin == NULL) {
605             return NGX_ERROR;
606         }
607 
608         u->naddrs = 1;
609 
610         sin->sin_family = AF_INET;
611         sin->sin_port = htons(u->port);
612         sin->sin_addr.s_addr = in_addr;
613 
614         u->addrs[0].sockaddr = (struct sockaddr *) sin;
615         u->addrs[0].socklen = sizeof(struct sockaddr_in);
616 
617         p = ngx_palloc(pool, u->host.len + sizeof(":65536") - 1);
618         if (p == NULL) {
619             return NGX_ERROR;
620         }
621 
622         u->addrs[0].name.len = ngx_sprintf(p, "%V:%d", &u->host, u->port) - p;
623         u->addrs[0].name.data = p;
624     }
625 
626     return NGX_OK;
627 }
628 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.