forecast: Only reinject packets that are marked or from the configured interface
authorTobias Brunner <tobias@strongswan.org>
Tue, 5 Feb 2019 16:21:21 +0000 (17:21 +0100)
committerTobias Brunner <tobias@strongswan.org>
Thu, 14 Mar 2019 10:56:20 +0000 (11:56 +0100)
This seems to avoid broadcast loops (i.e. processing and reinjecting the
same broadcast packet over and over again) as the packets we send via
AF_PACKET socket are neither marked nor from that interface.

src/libcharon/plugins/forecast/forecast_forwarder.c

index ce39097..42b57b1 100644 (file)
@@ -317,9 +317,15 @@ static void join_groups(private_kernel_listener_t *this, struct sockaddr *addr)
 /**
  * Attach the socket filter to the socket
  */
-static bool attach_filter(int fd, uint32_t broadcast)
+static bool attach_filter(int fd, uint32_t broadcast, uint32_t ifindex)
 {
        struct sock_filter filter_code[] = {
+               /* handle any marked packets (from clients) */
+               BPF_STMT(BPF_LD+BPF_B+BPF_ABS, SKF_AD_OFF+SKF_AD_MARK),
+               BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 0, 2),
+               /* and those from the internal interface */
+               BPF_STMT(BPF_LD+BPF_B+BPF_ABS, SKF_AD_OFF+SKF_AD_IFINDEX),
+               BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ifindex, 0, 5),
                /* destination address: is ... */
                BPF_STMT(BPF_LD+BPF_W+BPF_ABS, offsetof(struct iphdr, daddr)),
                /* broadcast, as received from the local network */
@@ -390,7 +396,7 @@ static void setup_interface(private_kernel_listener_t *this)
                                DBG1(DBG_NET, "using forecast interface %s", current->ifa_name);
                                this->ifindex = get_ifindex(this, current->ifa_name);
                                in = (struct sockaddr_in*)current->ifa_broadaddr;
-                               attach_filter(this->pkt, in->sin_addr.s_addr);
+                               attach_filter(this->pkt, in->sin_addr.s_addr, this->ifindex);
                                join_groups(this, current->ifa_addr);
                                host = host_create_from_sockaddr(current->ifa_broadaddr);
                                if (host)