aboutgitcodebugslistschat
path: root/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'util.c')
-rw-r--r--util.c48
1 files changed, 26 insertions, 22 deletions
diff --git a/util.c b/util.c
index dd2e57f..9a73fbb 100644
--- a/util.c
+++ b/util.c
@@ -35,7 +35,7 @@
/**
* sock_l4_sa() - Create and bind socket to socket address, add to epoll list
* @c: Execution context
- * @proto: Protocol number
+ * @type: epoll type
* @sa: Socket address to bind to
* @sl: Length of @sa
* @ifname: Interface for binding, NULL for any
@@ -44,34 +44,38 @@
*
* Return: newly created socket, negative error code on failure
*/
-static int sock_l4_sa(const struct ctx *c, uint8_t proto,
+static int sock_l4_sa(const struct ctx *c, enum epoll_type type,
const void *sa, socklen_t sl,
const char *ifname, bool v6only, uint32_t data)
{
sa_family_t af = ((const struct sockaddr *)sa)->sa_family;
- union epoll_ref ref = { .data = data };
+ union epoll_ref ref = { .type = type, .data = data };
struct epoll_event ev;
int fd, y = 1, ret;
+ uint8_t proto;
+ int socktype;
- switch (proto) {
- case IPPROTO_TCP:
- ref.type = EPOLL_TYPE_TCP_LISTEN;
+ switch (type) {
+ case EPOLL_TYPE_TCP_LISTEN:
+ proto = IPPROTO_TCP;
+ socktype = SOCK_STREAM | SOCK_NONBLOCK;
break;
- case IPPROTO_UDP:
- ref.type = EPOLL_TYPE_UDP;
+ case EPOLL_TYPE_UDP:
+ proto = IPPROTO_UDP;
+ socktype = SOCK_DGRAM | SOCK_NONBLOCK;
break;
- case IPPROTO_ICMP:
- case IPPROTO_ICMPV6:
- ref.type = EPOLL_TYPE_PING;
+ case EPOLL_TYPE_PING:
+ if (af == AF_INET)
+ proto = IPPROTO_ICMP;
+ else
+ proto = IPPROTO_ICMPV6;
+ socktype = SOCK_DGRAM | SOCK_NONBLOCK;
break;
default:
- return -EPFNOSUPPORT; /* Not implemented. */
+ ASSERT(0);
}
- if (proto == IPPROTO_TCP)
- fd = socket(af, SOCK_STREAM | SOCK_NONBLOCK, proto);
- else
- fd = socket(af, SOCK_DGRAM | SOCK_NONBLOCK, proto);
+ fd = socket(af, socktype, proto);
ret = -errno;
if (fd < 0) {
@@ -118,14 +122,14 @@ static int sock_l4_sa(const struct ctx *c, uint8_t proto,
* this is fine. This might also fail for ICMP because of a
* broken SELinux policy, see icmp_tap_handler().
*/
- if (proto != IPPROTO_ICMP && proto != IPPROTO_ICMPV6) {
+ if (type != EPOLL_TYPE_PING) {
ret = -errno;
close(fd);
return ret;
}
}
- if (proto == IPPROTO_TCP && listen(fd, 128) < 0) {
+ if (type == EPOLL_TYPE_TCP_LISTEN && listen(fd, 128) < 0) {
ret = -errno;
warn("TCP socket listen: %s", strerror(-ret));
close(fd);
@@ -146,7 +150,7 @@ static int sock_l4_sa(const struct ctx *c, uint8_t proto,
* sock_l4() - Create and bind socket for given L4, add to epoll list
* @c: Execution context
* @af: Address family, AF_INET or AF_INET6
- * @proto: Protocol number
+ * @type: epoll type
* @bind_addr: Address for binding, NULL for any
* @ifname: Interface for binding, NULL for any
* @port: Port, host order
@@ -154,7 +158,7 @@ static int sock_l4_sa(const struct ctx *c, uint8_t proto,
*
* Return: newly created socket, negative error code on failure
*/
-int sock_l4(const struct ctx *c, sa_family_t af, uint8_t proto,
+int sock_l4(const struct ctx *c, sa_family_t af, enum epoll_type type,
const void *bind_addr, const char *ifname, uint16_t port,
uint32_t data)
{
@@ -167,7 +171,7 @@ int sock_l4(const struct ctx *c, sa_family_t af, uint8_t proto,
};
if (bind_addr)
addr4.sin_addr = *(struct in_addr *)bind_addr;
- return sock_l4_sa(c, proto, &addr4, sizeof(addr4), ifname,
+ return sock_l4_sa(c, type, &addr4, sizeof(addr4), ifname,
false, data);
}
@@ -188,7 +192,7 @@ int sock_l4(const struct ctx *c, sa_family_t af, uint8_t proto,
sizeof(c->ip6.addr_ll)))
addr6.sin6_scope_id = c->ifi6;
}
- return sock_l4_sa(c, proto, &addr6, sizeof(addr6), ifname,
+ return sock_l4_sa(c, type, &addr6, sizeof(addr6), ifname,
af == AF_INET6, data);
}
default: