|
@@ -1921,6 +1921,7 @@ struct socket {
|
|
|
unsigned char is_ssl; /* Is port SSL-ed */
|
|
|
unsigned char ssl_redir; /* Is port supposed to redirect everything to SSL
|
|
|
* port */
|
|
|
+ unsigned char is_optional; /* Shouldn't cause us to exit if we can't bind to it */
|
|
|
unsigned char in_use; /* 0: invalid, 1: valid, 2: free */
|
|
|
};
|
|
|
|
|
@@ -15689,7 +15690,7 @@ parse_port_string(const struct vec *vec, struct socket *so, int *ip_version)
|
|
|
unsigned int a, b, c, d;
|
|
|
unsigned port;
|
|
|
unsigned long portUL;
|
|
|
- int ch, len;
|
|
|
+ int len;
|
|
|
const char *cb;
|
|
|
char *endptr;
|
|
|
#if defined(USE_IPV6)
|
|
@@ -15842,14 +15843,31 @@ parse_port_string(const struct vec *vec, struct socket *so, int *ip_version)
|
|
|
}
|
|
|
|
|
|
/* sscanf and the option splitting code ensure the following condition
|
|
|
- * Make sure the port is valid and vector ends with the port, 's' or 'r' */
|
|
|
- if ((len > 0) && is_valid_port(port)
|
|
|
- && (((size_t)len == vec->len) || (((size_t)len + 1) == vec->len))) {
|
|
|
- /* Next character after the port number */
|
|
|
- ch = ((size_t)len < vec->len) ? vec->ptr[len] : '\0';
|
|
|
- so->is_ssl = (ch == 's');
|
|
|
- so->ssl_redir = (ch == 'r');
|
|
|
- if ((ch == '\0') || (ch == 's') || (ch == 'r')) {
|
|
|
+ * Make sure the port is valid and vector ends with the port, 'o', 's', or 'r' */
|
|
|
+ if ((len > 0) && (is_valid_port(port))) {
|
|
|
+ int bad_suffix = 0;
|
|
|
+
|
|
|
+ /* Parse any suffix character(s) after the port number */
|
|
|
+ for (size_t i=len; i<vec->len; i++)
|
|
|
+ {
|
|
|
+ unsigned char * opt = NULL;
|
|
|
+ switch(vec->ptr[i])
|
|
|
+ {
|
|
|
+ case 'o': opt = &so->is_optional; break;
|
|
|
+ case 'r': opt = &so->ssl_redir; break;
|
|
|
+ case 's': opt = &so->is_ssl; break;
|
|
|
+ default: /* empty */ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((opt)&&(*opt == 0)) *opt = 1;
|
|
|
+ else
|
|
|
+ {
|
|
|
+ bad_suffix = 1;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if ((bad_suffix == 0)&&((so->is_ssl == 0)||(so->ssl_redir == 0))) {
|
|
|
return 1;
|
|
|
}
|
|
|
}
|
|
@@ -15904,8 +15922,11 @@ is_ssl_port_used(const char *ports)
|
|
|
char prevIsNumber = 0;
|
|
|
|
|
|
for (i = 0; i < portslen; i++) {
|
|
|
- if (prevIsNumber && (ports[i] == 's' || ports[i] == 'r')) {
|
|
|
- return 1;
|
|
|
+ if (prevIsNumber) {
|
|
|
+ int suffixCharIdx = (ports[i] == 'o') ? (i+1) : i; /* allow "os" and "or" suffixes */
|
|
|
+ if (ports[suffixCharIdx] == 's' || ports[suffixCharIdx] == 'r') {
|
|
|
+ return 1;
|
|
|
+ }
|
|
|
}
|
|
|
if (ports[i] >= '0' && ports[i] <= '9') {
|
|
|
prevIsNumber = 1;
|
|
@@ -16088,6 +16109,9 @@ set_ports_option(struct mg_context *phys_ctx)
|
|
|
strerror(errno));
|
|
|
closesocket(so.sock);
|
|
|
so.sock = INVALID_SOCKET;
|
|
|
+ if (so.is_optional) {
|
|
|
+ portsOk++; /* it's okay if we couldn't bind, this port is optional anyway */
|
|
|
+ }
|
|
|
continue;
|
|
|
}
|
|
|
}
|
|
@@ -16104,6 +16128,9 @@ set_ports_option(struct mg_context *phys_ctx)
|
|
|
strerror(errno));
|
|
|
closesocket(so.sock);
|
|
|
so.sock = INVALID_SOCKET;
|
|
|
+ if (so.is_optional) {
|
|
|
+ portsOk++; /* it's okay if we couldn't bind, this port is optional anyway */
|
|
|
+ }
|
|
|
continue;
|
|
|
}
|
|
|
}
|
|
@@ -16120,6 +16147,9 @@ set_ports_option(struct mg_context *phys_ctx)
|
|
|
strerror(errno));
|
|
|
closesocket(so.sock);
|
|
|
so.sock = INVALID_SOCKET;
|
|
|
+ if (so.is_optional) {
|
|
|
+ portsOk++; /* it's okay if we couldn't bind, this port is optional anyway */
|
|
|
+ }
|
|
|
continue;
|
|
|
}
|
|
|
}
|
|
@@ -20190,6 +20220,7 @@ accept_new_connection(const struct socket *listener, struct mg_context *ctx)
|
|
|
set_close_on_exec(so.sock, NULL, ctx);
|
|
|
so.is_ssl = listener->is_ssl;
|
|
|
so.ssl_redir = listener->ssl_redir;
|
|
|
+ so.is_optional = listener->is_optional;
|
|
|
if (getsockname(so.sock, &so.lsa.sa, &len) != 0) {
|
|
|
mg_cry_ctx_internal(ctx,
|
|
|
"%s: getsockname() failed: %s",
|