summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2016-12-15 20:47:10 -0500
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2016-12-15 21:15:51 -0500
commitbc691d8e293a593fbd14ad1d592d06f4f490ed29 (patch)
tree92967822d8d4e80d6262d12cb7d90336bda57b35
parent4a3cee1ad33d35bb14b845a4d5cfcebe98c99260 (diff)
downloadpython-systemd-bc691d8e293a593fbd14ad1d592d06f4f490ed29.tar.gz
Fix handling of addresses without port and add tests
-rw-r--r--systemd/test/test_daemon.py19
-rw-r--r--systemd/util.c90
2 files changed, 62 insertions, 47 deletions
diff --git a/systemd/test/test_daemon.py b/systemd/test/test_daemon.py
index 272c46f..5e9f5b8 100644
--- a/systemd/test/test_daemon.py
+++ b/systemd/test/test_daemon.py
@@ -158,27 +158,28 @@ def test_is_socket_sockaddr():
with contextlib.closing(socket.socket(socket.AF_INET)) as sock:
sock.bind(('127.0.0.1', 0))
addr, port = sock.getsockname()
+ port = ':{}'.format(port)
for listening in (0, 1):
for arg in (sock, sock.fileno()):
- # assert is_socket_sockaddr(arg, '127.0.0.1', socket.SOCK_STREAM)
- assert is_socket_sockaddr(arg, '127.0.0.1:{}'.format(port), socket.SOCK_STREAM)
+ assert is_socket_sockaddr(arg, '127.0.0.1', socket.SOCK_STREAM)
+ assert is_socket_sockaddr(arg, '127.0.0.1' + port, socket.SOCK_STREAM)
- assert is_socket_sockaddr(arg, '127.0.0.1:{}'.format(port), listening=listening)
- assert is_socket_sockaddr(arg, '127.0.0.1:{}'.format(port), listening=-1)
- assert not is_socket_sockaddr(arg, '127.0.0.1:{}'.format(port), listening=not listening)
+ assert is_socket_sockaddr(arg, '127.0.0.1' + port, listening=listening)
+ assert is_socket_sockaddr(arg, '127.0.0.1' + port, listening=-1)
+ assert not is_socket_sockaddr(arg, '127.0.0.1' + port, listening=not listening)
with pytest.raises(ValueError):
is_socket_sockaddr(arg, '127.0.0.1', flowinfo=123456)
- assert not is_socket_sockaddr(arg, '129.168.11.11:23'.format(port), socket.SOCK_STREAM)
- #assert not is_socket_sockaddr(arg, '127.0.0.1', socket.SOCK_DGRAM)
+ assert not is_socket_sockaddr(arg, '129.168.11.11:23', socket.SOCK_STREAM)
+ assert not is_socket_sockaddr(arg, '127.0.0.1', socket.SOCK_DGRAM)
with pytest.raises(ValueError):
_is_socket_sockaddr(arg, '127.0.0.1', 0, 123456)
- assert not _is_socket_sockaddr(arg, '129.168.11.11:23'.format(port), socket.SOCK_STREAM)
- #assert not _is_socket_sockaddr(arg, '127.0.0.1', socket.SOCK_DGRAM)
+ assert not _is_socket_sockaddr(arg, '129.168.11.11:23', socket.SOCK_STREAM)
+ assert not _is_socket_sockaddr(arg, '127.0.0.1', socket.SOCK_DGRAM)
sock.listen(11)
diff --git a/systemd/util.c b/systemd/util.c
index f4551c3..e02c825 100644
--- a/systemd/util.c
+++ b/systemd/util.c
@@ -71,6 +71,43 @@ static bool socket_ipv6_is_supported(void) {
return true;
}
+static int assign_address(const char *s,
+ uint16_t port,
+ union sockaddr_union *addr, unsigned *addr_len) {
+ int r;
+
+ /* IPv4 in w.x.y.z:p notation? */
+ r = inet_pton(AF_INET, s, &addr->in.sin_addr);
+ if (r < 0)
+ return -errno;
+
+ if (r > 0) {
+ /* Gotcha, it's a traditional IPv4 address */
+ addr->in.sin_family = AF_INET;
+ addr->in.sin_port = htobe16(port);
+ *addr_len = sizeof(struct sockaddr_in);
+ } else {
+ unsigned idx;
+
+ if (strlen(s) > IF_NAMESIZE-1)
+ return -EINVAL;
+
+ /* Uh, our last resort, an interface name */
+ idx = if_nametoindex(s);
+ if (idx == 0)
+ return -EINVAL;
+
+ addr->in6.sin6_family = AF_INET6;
+ addr->in6.sin6_port = htobe16(port);
+ addr->in6.sin6_scope_id = idx;
+ addr->in6.sin6_addr = in6addr_any;
+ *addr_len = sizeof(struct sockaddr_in6);
+ }
+
+ return 0;
+}
+
+
int parse_sockaddr(const char *s,
union sockaddr_union *addr, unsigned *addr_len) {
@@ -92,19 +129,22 @@ int parse_sockaddr(const char *s,
return errno > 0 ? -errno : -EINVAL;
e++;
- if (*e != ':')
- return -EINVAL;
+ if (*e) {
+ if (*e != ':')
+ return -EINVAL;
- e++;
- r = safe_atou(e, &u);
- if (r < 0)
- return r;
+ e++;
+ r = safe_atou(e, &u);
+ if (r < 0)
+ return r;
- if (u <= 0 || u > 0xFFFF)
- return -EINVAL;
+ if (u <= 0 || u > 0xFFFF)
+ return -EINVAL;
+
+ addr->in6.sin6_port = htobe16((uint16_t)u);
+ }
addr->in6.sin6_family = AF_INET6;
- addr->in6.sin6_port = htobe16((uint16_t)u);
*addr_len = sizeof(struct sockaddr_in6);
} else {
@@ -118,40 +158,14 @@ int parse_sockaddr(const char *s,
return -EINVAL;
n = strndupa(s, e-s);
+ return assign_address(n, u, addr, addr_len);
- /* IPv4 in w.x.y.z:p notation? */
- r = inet_pton(AF_INET, n, &addr->in.sin_addr);
- if (r < 0)
- return -errno;
-
- if (r > 0) {
- /* Gotcha, it's a traditional IPv4 address */
- addr->in.sin_family = AF_INET;
- addr->in.sin_port = htobe16((uint16_t)u);
- *addr_len = sizeof(struct sockaddr_in);
- } else {
- unsigned idx;
-
- if (strlen(n) > IF_NAMESIZE-1)
- return -EINVAL;
-
- /* Uh, our last resort, an interface name */
- idx = if_nametoindex(n);
- if (idx == 0)
- return -EINVAL;
-
- addr->in6.sin6_family = AF_INET6;
- addr->in6.sin6_port = htobe16((uint16_t)u);
- addr->in6.sin6_scope_id = idx;
- addr->in6.sin6_addr = in6addr_any;
- *addr_len = sizeof(struct sockaddr_in6);
- }
} else {
- /* Just a port */
r = safe_atou(s, &u);
if (r < 0)
- return r;
+ return assign_address(s, 0, addr, addr_len);
+ /* Just a port */
if (u <= 0 || u > 0xFFFF)
return -EINVAL;