mirror of
https://github.com/openvswitch/ovs
synced 2025-08-30 22:05:19 +00:00
socket-util: Factor out new function inet_parse_active().
An upcoming commit needs to parse connection strings without connecting to them, so this change enables that.
This commit is contained in:
@@ -292,6 +292,55 @@ guess_netmask(uint32_t ip)
|
|||||||
: htonl(0)); /* ??? */
|
: htonl(0)); /* ??? */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Parses 'target', which should be a string in the format "<host>[:<port>]".
|
||||||
|
* <host> is required. If 'default_port' is nonzero then <port> is optional
|
||||||
|
* and defaults to 'default_port'.
|
||||||
|
*
|
||||||
|
* On success, returns true and stores the parsed remote address into '*sinp'.
|
||||||
|
* On failure, logs an error, stores zeros into '*sinp', and returns false. */
|
||||||
|
bool
|
||||||
|
inet_parse_active(const char *target_, uint16_t default_port,
|
||||||
|
struct sockaddr_in *sinp)
|
||||||
|
{
|
||||||
|
char *target = xstrdup(target_);
|
||||||
|
char *save_ptr = NULL;
|
||||||
|
const char *host_name;
|
||||||
|
const char *port_string;
|
||||||
|
bool ok = false;
|
||||||
|
|
||||||
|
/* Defaults. */
|
||||||
|
sinp->sin_family = AF_INET;
|
||||||
|
sinp->sin_port = htons(default_port);
|
||||||
|
|
||||||
|
/* Tokenize. */
|
||||||
|
host_name = strtok_r(target, ":", &save_ptr);
|
||||||
|
port_string = strtok_r(NULL, ":", &save_ptr);
|
||||||
|
if (!host_name) {
|
||||||
|
VLOG_ERR("%s: bad peer name format", target_);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Look up IP, port. */
|
||||||
|
if (lookup_ip(host_name, &sinp->sin_addr)) {
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (port_string && atoi(port_string)) {
|
||||||
|
sinp->sin_port = htons(atoi(port_string));
|
||||||
|
} else if (!default_port) {
|
||||||
|
VLOG_ERR("%s: port number must be specified", target_);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
ok = true;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (!ok) {
|
||||||
|
memset(sinp, 0, sizeof *sinp);
|
||||||
|
}
|
||||||
|
free(target);
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
/* Opens a non-blocking IPv4 socket of the specified 'style' and connects to
|
/* Opens a non-blocking IPv4 socket of the specified 'style' and connects to
|
||||||
* 'target', which should be a string in the format "<host>[:<port>]". <host>
|
* 'target', which should be a string in the format "<host>[:<port>]". <host>
|
||||||
* is required. If 'default_port' is nonzero then <port> is optional and
|
* is required. If 'default_port' is nonzero then <port> is optional and
|
||||||
@@ -307,40 +356,15 @@ guess_netmask(uint32_t ip)
|
|||||||
* If 'sinp' is non-null, then on success the target address is stored into
|
* If 'sinp' is non-null, then on success the target address is stored into
|
||||||
* '*sinp'. */
|
* '*sinp'. */
|
||||||
int
|
int
|
||||||
inet_open_active(int style, const char *target_, uint16_t default_port,
|
inet_open_active(int style, const char *target, uint16_t default_port,
|
||||||
struct sockaddr_in *sinp, int *fdp)
|
struct sockaddr_in *sinp, int *fdp)
|
||||||
{
|
{
|
||||||
char *target = xstrdup(target_);
|
|
||||||
char *save_ptr = NULL;
|
|
||||||
const char *host_name;
|
|
||||||
const char *port_string;
|
|
||||||
struct sockaddr_in sin;
|
struct sockaddr_in sin;
|
||||||
int fd = -1;
|
int fd = -1;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
/* Defaults. */
|
/* Parse. */
|
||||||
memset(&sin, 0, sizeof sin);
|
if (!inet_parse_active(target, default_port, &sin)) {
|
||||||
sin.sin_family = AF_INET;
|
|
||||||
sin.sin_port = htons(default_port);
|
|
||||||
|
|
||||||
/* Tokenize. */
|
|
||||||
host_name = strtok_r(target, ":", &save_ptr);
|
|
||||||
port_string = strtok_r(NULL, ":", &save_ptr);
|
|
||||||
if (!host_name) {
|
|
||||||
ovs_error(0, "%s: bad peer name format", target_);
|
|
||||||
error = EAFNOSUPPORT;
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Look up IP, port. */
|
|
||||||
error = lookup_ip(host_name, &sin.sin_addr);
|
|
||||||
if (error) {
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
if (port_string && atoi(port_string)) {
|
|
||||||
sin.sin_port = htons(atoi(port_string));
|
|
||||||
} else if (!default_port) {
|
|
||||||
VLOG_ERR("%s: port number must be specified", target_);
|
|
||||||
error = EAFNOSUPPORT;
|
error = EAFNOSUPPORT;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
@@ -348,7 +372,7 @@ inet_open_active(int style, const char *target_, uint16_t default_port,
|
|||||||
/* Create non-blocking socket. */
|
/* Create non-blocking socket. */
|
||||||
fd = socket(AF_INET, style, 0);
|
fd = socket(AF_INET, style, 0);
|
||||||
if (fd < 0) {
|
if (fd < 0) {
|
||||||
VLOG_ERR("%s: socket: %s", target_, strerror(errno));
|
VLOG_ERR("%s: socket: %s", target, strerror(errno));
|
||||||
error = errno;
|
error = errno;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
@@ -379,7 +403,6 @@ exit:
|
|||||||
} else {
|
} else {
|
||||||
*fdp = -1;
|
*fdp = -1;
|
||||||
}
|
}
|
||||||
free(target);
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -34,6 +34,8 @@ int get_unix_name_len(socklen_t sun_len);
|
|||||||
uint32_t guess_netmask(uint32_t ip);
|
uint32_t guess_netmask(uint32_t ip);
|
||||||
int get_null_fd(void);
|
int get_null_fd(void);
|
||||||
|
|
||||||
|
bool inet_parse_active(const char *target, uint16_t default_port,
|
||||||
|
struct sockaddr_in *sinp);
|
||||||
int inet_open_active(int style, const char *target, uint16_t default_port,
|
int inet_open_active(int style, const char *target, uint16_t default_port,
|
||||||
struct sockaddr_in *sinp, int *fdp);
|
struct sockaddr_in *sinp, int *fdp);
|
||||||
int inet_open_passive(int style, const char *target, int default_port,
|
int inet_open_passive(int style, const char *target, int default_port,
|
||||||
|
Reference in New Issue
Block a user