Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/nginx/nginx.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/ngx_inet.c')
-rw-r--r--src/core/ngx_inet.c336
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;
}