diff --git a/ChangeLog.md b/ChangeLog.md index 4b3fca6..e074af8 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -4,6 +4,18 @@ ChangeLog All notable changes to the project are documented in this file. +[v1.5][] - 2021-09-09 +--------------------- + +### Changes +- Add support for handling IPv4 addresses mapped on IPv6 +- Pass through SOCK_STREAM in `recv()`, `recvfrom()` and `recvmsg()` + +### Fixes +- Restore IP_PKTINFO option on socket after interface inspection +- Fix uninitialized variable + + [v1.4][] - 2021-09-06 --------------------- @@ -58,6 +70,7 @@ First public release. Basic `accept()` wrapper which reads allowed interface:port tuples from an `ACL=iface:port;iface2:port` environment variable. +[v1.5]: https://github.com/westermo/accept-guard/compare/v1.4...v1.5 [v1.4]: https://github.com/westermo/accept-guard/compare/v1.3...v1.4 [v1.3]: https://github.com/westermo/accept-guard/compare/v1.2...v1.3 [v1.2]: https://github.com/westermo/accept-guard/compare/v1.1...v1.2 diff --git a/Makefile b/Makefile index e6c14e9..bb6b5d4 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -VERSION = 1.4 +VERSION = 1.5 NAME = accept-guard PKG = $(NAME)-$(VERSION) ARCHIVE = $(PKG).tar.gz diff --git a/accept-guard.c b/accept-guard.c index abeb80e..b0d8f46 100644 --- a/accept-guard.c +++ b/accept-guard.c @@ -125,9 +125,9 @@ static int identify_inbound(int sd, int ifindex, char *ifname, size_t len, int * { struct ifaddrs *ifaddr, *ifa; #ifdef AF_INET6 - struct sockaddr_storage ss; + struct sockaddr_storage ss = { 0 }; #else - struct sockaddr_in ss; + struct sockaddr_in ss = { 0 }; #endif socklen_t slen = sizeof(ss); @@ -261,6 +261,21 @@ static int is_inet_domain(int sd) return 0; /* Possibly AF_UNIX socket, allow */ } +static int is_sock_stream(int sd) +{ + socklen_t len; + int val; + + len = sizeof(val); + if (getsockopt(sd, SOL_SOCKET, SO_TYPE, &val, &len) == -1) + return 1; /* Fall back to allow syscall on error */ + + if (val == SOCK_STREAM) + return 1; + + return 0; +} + int accept(int socket, struct sockaddr *addr, socklen_t *addrlen) { int rc; @@ -292,9 +307,15 @@ static int peek_ifindex(int sd) struct sockaddr_in sin; struct cmsghdr *cmsg; struct msghdr msgh; + socklen_t orig_len; + int orig_on = 0; int on = 1; - setsockopt(sd, SOL_IP, IP_PKTINFO, &on, sizeof(on)); + orig_len = sizeof(orig_on); + if (getsockopt(sd, SOL_IP, IP_PKTINFO, &orig_on, &orig_len) == -1) + return 0; /* Fall back to allow syscall on error */ + if (setsockopt(sd, SOL_IP, IP_PKTINFO, &on, sizeof(on)) == -1) + return 0; /* Fall back to allow syscall on error */ memset(&msgh, 0, sizeof(msgh)); msgh.msg_name = &sin; @@ -302,9 +323,13 @@ static int peek_ifindex(int sd) msgh.msg_control = cmbuf; msgh.msg_controllen = sizeof(cmbuf); - if (org_recvmsg(sd, &msgh, MSG_PEEK) == -1) + + if (org_recvmsg(sd, &msgh, MSG_PEEK) == -1) { + (void)setsockopt(sd, SOL_IP, IP_PKTINFO, &orig_on, sizeof(orig_on)); return 0; + } + (void)setsockopt(sd, SOL_IP, IP_PKTINFO, &orig_on, sizeof(orig_on)); for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg; cmsg = CMSG_NXTHDR(&msgh, cmsg)) { struct in_pktinfo *ipi = (struct in_pktinfo *)CMSG_DATA(cmsg); @@ -319,7 +344,7 @@ static int peek_ifindex(int sd) static ssize_t do_recv(int sd, int rc, int flags, int ifindex) { - if (rc == -1 || (flags & MSG_PEEK) || ifindex == 0 || !is_inet_domain(sd)) + if (rc == -1 || (flags & MSG_PEEK) || ifindex == 0 || !is_inet_domain(sd) || is_sock_stream(sd)) goto done; parse_acl(); diff --git a/test/Makefile b/test/Makefile index a4797ce..d0bc536 100644 --- a/test/Makefile +++ b/test/Makefile @@ -1,6 +1,6 @@ EXEC := client server CFLAGS := -W -Wall -Wextra -std=gnu99 -g -O2 -TESTS := accept.sh accept6.sh recvfrom.sh recvmsg.sh +TESTS := accept.sh accept6.sh accept6-ipv4-mapped.sh recvfrom.sh recvmsg.sh all: $(EXEC) diff --git a/test/accept6-ipv4-mapped.sh b/test/accept6-ipv4-mapped.sh new file mode 100755 index 0000000..eba845f --- /dev/null +++ b/test/accept6-ipv4-mapped.sh @@ -0,0 +1,19 @@ +#!/bin/sh +#set -x + +# shellcheck source=/dev/null +. "$(dirname "$0")/lib.sh" + +topology +server -6 -t + +print "Verifying loopback connectivity ..." +./client -t -p 8080 127.0.0.1 || FAIL + +print "Verifying no connection via a1 ..." +./client -t -p 8080 10.0.0.1 && FAIL + +print "Verifying connection via a2 ..." +./client -t -p 8080 20.0.0.1 || FAIL + +OK