* If <pfx> is non-null, it is used as a string prefix before any path-based
* address (typically the path to a unix socket).
*/
-struct sockaddr_storage *str2sa_range(const char *str,
- int *port, int *low, int *high, int *fd,
- char **err, const char *pfx,
- char **fqdn, unsigned int opts);
+struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int *high, int *fd,
+ struct protocol **proto, char **err,
+ const char *pfx, char **fqdn, unsigned int opts);
/* converts <str> to a struct in_addr containing a network mask. It can be
* passed in dotted form (255.255.255.0) or in CIDR form (24). It returns 1
else if (warnifnotcap(curproxy, PR_CAP_BE, file, linenum, args[0], NULL))
err_code |= ERR_WARN;
- sk = str2sa_range(args[1], NULL, &port1, &port2, NULL,
+ sk = str2sa_range(args[1], NULL, &port1, &port2, NULL, &proto,
&errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_PORT_MAND | PA_O_STREAM | PA_O_XPRT);
if (!sk) {
ha_alert("parsing [%s:%d] : '%s' : %s\n", file, linenum, args[0], errmsg);
goto out;
}
- proto = protocol_by_family(sk->ss_family);
- if (!proto || !proto->connect) {
+ if (!proto->connect) {
ha_alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
file, linenum, args[0], args[1]);
err_code |= ERR_ALERT | ERR_FATAL;
curproxy->conn_src.iface_name = NULL;
curproxy->conn_src.iface_len = 0;
- sk = str2sa_range(args[1], NULL, &port1, &port2, NULL,
+ sk = str2sa_range(args[1], NULL, &port1, &port2, NULL, &proto,
&errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_STREAM);
if (!sk) {
ha_alert("parsing [%s:%d] : '%s %s' : %s\n",
goto out;
}
- proto = protocol_by_family(sk->ss_family);
- if (!proto || !proto->connect) {
+ if (!proto->connect) {
ha_alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
file, linenum, args[0], args[1]);
err_code |= ERR_ALERT | ERR_FATAL;
} else {
struct sockaddr_storage *sk;
- sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, NULL,
+ sk = str2sa_range(args[cur_arg + 1], NULL, &port1, &port2, NULL, &proto,
&errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_STREAM);
if (!sk) {
ha_alert("parsing [%s:%d] : '%s %s' : %s\n",
goto out;
}
- proto = protocol_by_family(sk->ss_family);
- if (!proto || !proto->connect) {
+ if (!proto->connect) {
ha_alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
file, linenum, args[cur_arg], args[cur_arg+1]);
err_code |= ERR_ALERT | ERR_FATAL;
*next++ = 0;
}
- ss2 = str2sa_range(str, NULL, &port, &end, &fd, err,
+ ss2 = str2sa_range(str, NULL, &port, &end, &fd, &proto, err,
curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_PORT_MAND | PA_O_PORT_RANGE |
PA_O_SOCKET_FD | PA_O_STREAM | PA_O_XPRT);
if (!ss2)
goto fail;
- proto = protocol_by_family(ss2->ss_family);
- if (!proto) {
- memprintf(err, "unsupported protocol family %d fr address '%s'", ss2->ss_family, str);
- goto fail;
- }
-
/* OK the address looks correct */
if (!create_listeners(bind_conf, ss2, port, end, fd, proto, err)) {
memprintf(err, "%s for address '%s'.\n", *err, str);
*next++ = 0;
}
- ss2 = str2sa_range(str, NULL, &port, &end, &fd, err,
+ ss2 = str2sa_range(str, NULL, &port, &end, &fd, &proto, err,
curproxy == global.stats_fe ? NULL : global.unix_bind.prefix,
NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_PORT_MAND | PA_O_PORT_RANGE |
PA_O_SOCKET_FD | PA_O_DGRAM | PA_O_XPRT);
if (!ss2)
goto fail;
- proto = protocol_by_family(ss2->ss_family);
- if (!proto) {
- memprintf(err, "unsupported protocol family %d fr address '%s'", ss2->ss_family, str);
- goto fail;
- }
-
/* OK the address looks correct */
if (!create_listeners(bind_conf, ss2, port, end, fd, proto, err)) {
memprintf(err, "%s for address '%s'.\n", *err, str);
}
}
newpeer->addr = l->rx.addr;
- newpeer->proto = protocol_by_family(newpeer->addr.ss_family);
+ newpeer->proto = l->rx.proto;
cur_arg++;
}
else if (strcmp(args[0], "nameserver") == 0) { /* nameserver definition */
struct sockaddr_storage *sk;
int port1, port2;
- struct protocol *proto;
if (!*args[2]) {
ha_alert("parsing [%s:%d] : '%s' expects <name> and <addr>[:<port>] as arguments.\n",
newnameserver->conf.line = linenum;
newnameserver->id = strdup(args[1]);
- sk = str2sa_range(args[2], NULL, &port1, &port2, NULL, &errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_PORT_MAND | PA_O_DGRAM);
+ sk = str2sa_range(args[2], NULL, &port1, &port2, NULL, NULL,
+ &errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_PORT_MAND | PA_O_DGRAM);
if (!sk) {
ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
- proto = protocol_by_family(sk->ss_family);
- if (!proto) {
- ha_alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
- file, linenum, args[0], args[1]);
- err_code |= ERR_ALERT | ERR_FATAL;
- goto out;
- }
-
newnameserver->addr = *sk;
}
else if (strcmp(args[0], "parse-resolv-conf") == 0) {
newmailer->id = strdup(args[1]);
- sk = str2sa_range(args[2], NULL, &port1, &port2, NULL, &errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_PORT_MAND | PA_O_STREAM | PA_O_XPRT);
+ sk = str2sa_range(args[2], NULL, &port1, &port2, NULL, &proto,
+ &errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_PORT_MAND | PA_O_STREAM | PA_O_XPRT);
if (!sk) {
ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
err_code |= ERR_ALERT | ERR_FATAL;
goto out;
}
- proto = protocol_by_family(sk->ss_family);
- if (!proto || !proto->connect || proto->sock_prot != IPPROTO_TCP) {
+ if (!proto->connect || proto->sock_prot != IPPROTO_TCP) {
ha_alert("parsing [%s:%d] : '%s %s' : TCP not supported for this address family.\n",
file, linenum, args[0], args[1]);
err_code |= ERR_ALERT | ERR_FATAL;
goto error;
}
- sk = str2sa_range(args[*cur_arg+1], NULL, &port1, &port2, NULL, errmsg, NULL, NULL,
+ sk = str2sa_range(args[*cur_arg+1], NULL, &port1, &port2, NULL, &proto, errmsg, NULL, NULL,
PA_O_RESOLVE | PA_O_PORT_OK | PA_O_STREAM);
if (!sk) {
memprintf(errmsg, "'%s' : %s", args[*cur_arg], *errmsg);
goto error;
}
- proto = protocol_by_family(sk->ss_family);
- if (!proto || !proto->connect) {
+ if (!proto->connect) {
memprintf(errmsg, "'%s %s' : connect() not supported for this address family.",
args[*cur_arg], args[*cur_arg+1]);
goto error;
newsrv->conf.line = 0;
memprintf(&msg, "sockpair@%d", child->ipc_fd[0]);
- if ((sk = str2sa_range(msg, &port, &port1, &port2, NULL,
+ if ((sk = str2sa_range(msg, &port, &port1, &port2, NULL, &proto,
&errmsg, NULL, NULL, PA_O_STREAM)) == 0) {
goto error;
}
free(msg);
msg = NULL;
- proto = protocol_by_family(sk->ss_family);
- if (!proto || !proto->connect) {
+ if (!proto->connect) {
goto error;
}
}
/* Parse ip address. */
- addr = str2sa_range(ip, NULL, &low, &high, NULL, NULL, NULL, NULL, PA_O_PORT_OK | PA_O_STREAM);
+ addr = str2sa_range(ip, NULL, &low, &high, NULL, NULL, NULL, NULL, NULL, PA_O_PORT_OK | PA_O_STREAM);
if (!addr) {
xref_unlock(&socket->xref, peer);
WILL_LJMP(luaL_error(L, "connect: cannot parse destination address '%s'", ip));
goto done;
}
- sk = str2sa_range(args[1], NULL, &port1, &port2, &fd,
+ sk = str2sa_range(args[1], NULL, &port1, &port2, &fd, NULL,
err, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_RAW_FD | PA_O_DGRAM);
if (!sk)
goto error;
}
/* 'sk' is statically allocated (no need to be freed). */
- sk = str2sa_range(args[*cur_arg + 1], NULL, &port_low, &port_high, NULL,
+ sk = str2sa_range(args[*cur_arg + 1], NULL, &port_low, &port_high, NULL, &proto,
&errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_PORT_RANGE | PA_O_STREAM);
if (!sk) {
memprintf(err, "'%s %s' : %s\n", args[*cur_arg], args[*cur_arg + 1], errmsg);
goto err;
}
- proto = protocol_by_family(sk->ss_family);
- if (!proto || !proto->connect) {
+ if (!proto->connect) {
ha_alert("'%s %s' : connect() not supported for this address family.\n",
args[*cur_arg], args[*cur_arg + 1]);
goto err;
int port1, port2;
/* 'sk' is statically allocated (no need to be freed). */
- sk = str2sa_range(args[*cur_arg + 1], NULL, &port1, &port2, NULL,
+ sk = str2sa_range(args[*cur_arg + 1], NULL, &port1, &port2, NULL, &proto,
&errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_STREAM);
if (!sk) {
ha_alert("'%s %s' : %s\n", args[*cur_arg], args[*cur_arg + 1], errmsg);
goto err;
}
- proto = protocol_by_family(sk->ss_family);
- if (!proto || !proto->connect) {
+ if (!proto->connect) {
ha_alert("'%s %s' : connect() not supported for this address family.\n",
args[*cur_arg], args[*cur_arg + 1]);
goto err;
}
/* 'sk' is statically allocated (no need to be freed). */
- sk = str2sa_range(args[*cur_arg + 1], NULL, &port_low, &port_high, NULL,
+ sk = str2sa_range(args[*cur_arg + 1], NULL, &port_low, &port_high, NULL, &proto,
&errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_PORT_MAND | PA_O_STREAM);
if (!sk) {
memprintf(err, "'%s %s' : %s\n", args[*cur_arg], args[*cur_arg + 1], errmsg);
goto err;
}
- proto = protocol_by_family(sk->ss_family);
- if (!proto || !proto->connect) {
+ if (!proto->connect) {
ha_alert("'%s %s' : connect() not supported for this address family.\n", args[*cur_arg], args[*cur_arg + 1]);
goto err;
}
if (!parse_addr)
goto skip_addr;
- sk = str2sa_range(args[cur_arg], &port, &port1, &port2, NULL,
+ sk = str2sa_range(args[cur_arg], &port, &port1, &port2, NULL, &proto,
&errmsg, NULL, &fqdn, (initial_resolve ? PA_O_RESOLVE : 0) | PA_O_PORT_OK | PA_O_PORT_OFS | PA_O_STREAM | PA_O_XPRT);
if (!sk) {
ha_alert("parsing [%s:%d] : '%s %s' : %s\n", file, linenum, args[0], args[1], errmsg);
goto out;
}
- proto = protocol_by_family(sk->ss_family);
- if (!fqdn && (!proto || !proto->connect)) {
+ if (!fqdn && !proto->connect) {
ha_alert("parsing [%s:%d] : '%s %s' : connect() not supported for this address family.\n",
file, linenum, args[0], args[1]);
err_code |= ERR_ALERT | ERR_FATAL;
goto error;
}
- sk = str2sa_range(args[cur_arg+1], NULL, &port1, &port2, NULL,
+ sk = str2sa_range(args[cur_arg+1], NULL, &port1, &port2, NULL, &proto,
errmsg, NULL, NULL, PA_O_RESOLVE | PA_O_PORT_OK | PA_O_STREAM);
if (!sk) {
memprintf(errmsg, "'%s' : %s.", args[cur_arg], *errmsg);
goto error;
}
- proto = protocol_by_family(sk->ss_family);
- if (!proto || !proto->connect) {
+ if (!proto->connect) {
memprintf(errmsg, "'%s' : connect() not supported for this address family.\n",
args[cur_arg]);
goto error;
#include <haproxy/hlua.h>
#include <haproxy/listener.h>
#include <haproxy/namespace.h>
+#include <haproxy/protocol.h>
#include <haproxy/ssl_sock.h>
#include <haproxy/stream_interface.h>
#include <haproxy/task.h>
* the address when cast to sockaddr_in and the address family is
* AF_CUST_EXISTING_FD.
*
+ * The matching protocol will be set into <proto> if non-null.
+ *
* Any known file descriptor is also assigned to <fd> if non-null, otherwise it
* is forced to -1.
*/
-struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int *high, int *fd, char **err, const char *pfx, char **fqdn, unsigned int opts)
+struct sockaddr_storage *str2sa_range(const char *str, int *port, int *low, int *high, int *fd,
+ struct protocol **proto, char **err,
+ const char *pfx, char **fqdn, unsigned int opts)
{
static THREAD_LOCAL struct sockaddr_storage ss;
struct sockaddr_storage *ret = NULL;
+ struct protocol *new_proto = NULL;
char *back, *str2;
char *port1, *port2;
int portl, porth, porta;
ss.ss_family = AF_CUST_UDP4;
}
+ if (proto) {
+ /* Note: if the caller asks for a proto, we must find one,
+ * except if we return with an fqdn that will resolve later,
+ * in which case the address is not known yet (this is only
+ * for servers actually).
+ */
+ new_proto = protocol_by_family(ss.ss_family);
+ if (!new_proto && (!fqdn || !*fqdn)) {
+ memprintf(err, "unsupported protocol family %d for address '%s'", ss.ss_family, str);
+ goto out;
+ }
+ }
+
ret = &ss;
out:
if (port)
*high = porth;
if (fd)
*fd = new_fd;
+ if (proto)
+ *proto = new_proto;
free(back);
return ret;
}