diff options
Diffstat (limited to 'src/core/ngx_inet.c')
-rw-r--r-- | src/core/ngx_inet.c | 336 |
1 files changed, 335 insertions, 1 deletions
diff --git a/src/core/ngx_inet.c b/src/core/ngx_inet.c index a42df699b..f2b0cf78b 100644 --- a/src/core/ngx_inet.c +++ b/src/core/ngx_inet.c @@ -220,6 +220,339 @@ ngx_ptocidr(ngx_str_t *text, void *cidr) } +ngx_int_t +ngx_parse_url(ngx_conf_t *cf, ngx_url_t *u) +{ + u_char *p; + size_t len; + ngx_int_t port; + ngx_uint_t i; +#if (NGX_HAVE_UNIX_DOMAIN) + struct sockaddr_un *saun; +#endif + + len = u->url.len; + p = u->url.data; + + if (ngx_strncasecmp(p, "unix:", 5) == 0) { + +#if (NGX_HAVE_UNIX_DOMAIN) + + u->type = NGX_PARSE_URL_UNIX; + + p += 5; + len -= 5; + + if (u->uri_part) { + for (i = 0; i < len; i++) { + + if (p[i] == ':') { + len = i; + + u->uri.len -= len + 1; + u->uri.data += len + 1; + + break; + } + } + } + + if (len == 0) { + u->err = "no path in the unix domain socket"; + return NGX_ERROR; + } + + if (len + 1 > sizeof(saun->sun_path)) { + u->err = "too long path in the unix domain socket"; + return NGX_ERROR; + } + + u->peers = ngx_pcalloc(cf->pool, sizeof(ngx_peers_t)); + if (u->peers == NULL) { + return NGX_ERROR; + } + + saun = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_un)); + if (saun == NULL) { + return NGX_ERROR; + } + + u->peers->number = 1; + + saun->sun_family = AF_UNIX; + (void) ngx_cpystrn((u_char *) saun->sun_path, p, len + 1); + + u->peers->peer[0].sockaddr = (struct sockaddr *) saun; + u->peers->peer[0].socklen = sizeof(struct sockaddr_un); + u->peers->peer[0].name = u->url; + u->peers->peer[0].uri_separator = ":"; + + u->host_header.len = sizeof("localhost") - 1; + u->host_header.data = (u_char *) "localhost"; + + return NGX_OK; + +#else + u->err = "the unix domain sockets are not supported on this platform"; + + return NGX_ERROR; + +#endif + } + + if ((p[0] == ':' || p[0] == '/') && !u->listen) { + u->err = "invalid host"; + return NGX_ERROR; + } + + u->type = NGX_PARSE_URL_INET; + + u->host.data = p; + u->host_header.len = len; + u->host_header.data = p; + + for (i = 0; i < len; i++) { + + if (p[i] == ':') { + u->port.data = &p[i + 1]; + u->host.len = i; + + if (!u->uri_part) { + u->port.len = &p[len] - u->port.data; + break; + } + } + + if (p[i] == '/') { + u->uri.len = len - i; + u->uri.data = &p[i]; + u->host_header.len = i; + + if (u->host.len == 0) { + u->host.len = i; + } + + if (u->port.data == NULL) { + u->default_port = 1; + goto port; + } + + u->port.len = &p[i] - u->port.data; + + if (u->port.len == 0) { + u->err = "invalid port"; + return NGX_ERROR; + } + + break; + } + } + + if (u->port.data) { + + if (u->port.len == 0) { + u->port.len = &p[i] - u->port.data; + + if (u->port.len == 0) { + u->err = "invalid port"; + return NGX_ERROR; + } + } + + port = ngx_atoi(u->port.data, u->port.len); + + if (port == NGX_ERROR || port < 1 || port > 65536) { + u->err = "invalid port"; + return NGX_ERROR; + } + + } else { + port = ngx_atoi(p, len); + + if (port == NGX_ERROR) { + u->default_port = 1; + u->host.len = len; + + goto port; + } + + u->port.len = len; + u->port.data = p; + u->wildcard = 1; + } + + u->portn = (in_port_t) port; + +port: + + if (u->listen) { + return NGX_OK; + } + + if (u->default_port) { + + if (u->upstream) { + return NGX_OK; + } + + if (u->default_portn == 0) { + u->err = "no port"; + return NGX_ERROR; + } + + u->portn = u->default_portn; + + u->port.data = ngx_palloc(cf->pool, sizeof("65536") - 1); + if (u->port.data == NULL) { + return NGX_ERROR; + } + + u->port.len = ngx_sprintf(u->port.data, "%d", u->portn) - u->port.data; + + } else if (u->portn) { + if (u->portn == u->default_portn) { + u->default_port = 1; + } + + } else { + u->err = "no port"; + return NGX_ERROR; + } + + if (u->host.len == 0) { + u->err = "no host"; + return NGX_ERROR; + } + + u->peers = ngx_inet_resolve_peer(cf, &u->host, u->portn); + + if (u->peers == NULL) { + return NGX_ERROR; + } + + if (u->peers == NGX_CONF_ERROR) { + u->err = "host not found"; + return NGX_ERROR; + } + + return NGX_OK; +} + + +ngx_peers_t * +ngx_inet_resolve_peer(ngx_conf_t *cf, ngx_str_t *name, in_port_t port) +{ + u_char *host; + size_t len; + in_addr_t in_addr; + ngx_uint_t i; + ngx_peers_t *peers; + struct hostent *h; + struct sockaddr_in *sin; + + host = ngx_palloc(cf->temp_pool, name->len + 1); + if (host == NULL) { + return NULL; + } + + (void) ngx_cpystrn(host, name->data, name->len + 1); + + /* AF_INET only */ + + in_addr = inet_addr((char *) host); + + if (in_addr == INADDR_NONE) { + h = gethostbyname((char *) host); + + if (h == NULL || h->h_addr_list[0] == NULL) { + return NGX_CONF_ERROR; + } + + for (i = 0; h->h_addr_list[i] != NULL; i++) { /* void */ } + + /* MP: ngx_shared_palloc() */ + + peers = ngx_pcalloc(cf->pool, + sizeof(ngx_peers_t) + sizeof(ngx_peer_t) * (i - 1)); + if (peers == NULL) { + return NULL; + } + + peers->number = i; + peers->weight = 1; + + for (i = 0; h->h_addr_list[i] != NULL; i++) { + + sin = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_in)); + if (sin == NULL) { + return NULL; + } + + sin->sin_family = AF_INET; + sin->sin_port = htons(port); + sin->sin_addr.s_addr = *(in_addr_t *) (h->h_addr_list[i]); + + peers->peer[i].sockaddr = (struct sockaddr *) sin; + peers->peer[i].socklen = sizeof(struct sockaddr_in); + + len = INET_ADDRSTRLEN - 1 + 1 + sizeof(":65536") - 1; + + peers->peer[i].name.data = ngx_palloc(cf->pool, len); + if (peers->peer[i].name.data == NULL) { + return NULL; + } + + len = ngx_sock_ntop(AF_INET, (struct sockaddr *) sin, + peers->peer[i].name.data, len); + + peers->peer[i].name.len = + ngx_sprintf(&peers->peer[i].name.data[len], + ":%d", port) + - peers->peer[i].name.data; + + peers->peer[i].uri_separator = ""; + } + + } else { + + /* MP: ngx_shared_palloc() */ + + peers = ngx_pcalloc(cf->pool, sizeof(ngx_peers_t)); + if (peers == NULL) { + return NULL; + } + + sin = ngx_pcalloc(cf->pool, sizeof(struct sockaddr_in)); + if (sin == NULL) { + return NULL; + } + + peers->number = 1; + + sin->sin_family = AF_INET; + sin->sin_port = htons(port); + sin->sin_addr.s_addr = in_addr; + + peers->peer[0].sockaddr = (struct sockaddr *) sin; + peers->peer[0].socklen = sizeof(struct sockaddr_in); + + peers->peer[0].name.data = ngx_palloc(cf->pool, + name->len + sizeof(":65536") - 1); + if (peers->peer[0].name.data == NULL) { + return NULL; + } + + peers->peer[0].name.len = ngx_sprintf(peers->peer[0].name.data, "%V:%d", + name, port) + - peers->peer[0].name.data; + + peers->peer[0].uri_separator = ""; + } + + return peers; +} + + ngx_peers_t * ngx_inet_upstream_parse(ngx_conf_t *cf, ngx_inet_upstream_t *u) { @@ -241,6 +574,7 @@ ngx_inet_upstream_parse(ngx_conf_t *cf, ngx_inet_upstream_t *u) } if (u->default_port) { + if (u->default_port_value == 0) { ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, "no port in upstream \"%V\"", &u->name); @@ -277,7 +611,7 @@ ngx_inet_upstream_parse(ngx_conf_t *cf, ngx_inet_upstream_t *u) u->port = htons(u->port); - host = ngx_palloc(cf->pool, u->host.len + 1); + host = ngx_palloc(cf->temp_pool, u->host.len + 1); if (host == NULL) { return NULL; } |