bpf netd: block local network calls on egress

Add method that will perform lookup in trie map and identify
if destination for packet is local network.

If the packet is for local network, we will drop it.
This logic will be paired with permission in future.

Test: Locally tested by adding values from userspace and
sending packets to same address.

Bug: 373608607
Change-Id: If58edf2be717931f160ccbbd86cea35e4463aff4
diff --git a/bpf/progs/netd.c b/bpf/progs/netd.c
index 41ea82d..88aa490 100644
--- a/bpf/progs/netd.c
+++ b/bpf/progs/netd.c
@@ -252,6 +252,42 @@
     return v ? *v : true;
 }
 
+static __always_inline inline bool should_block_local_network_packets(struct __sk_buff *skb,
+                                   const struct kver_uint kver) {
+    struct in6_addr remote_ip6;
+    uint8_t ip_proto;
+    uint8_t L4_off;
+    if (skb->protocol == htons(ETH_P_IP)) {
+        remote_ip6.s6_addr32[0] = 0;
+        remote_ip6.s6_addr32[1] = 0;
+        remote_ip6.s6_addr32[2] = htonl(0xFFFF);
+        (void)bpf_skb_load_bytes_net(skb, IP4_OFFSET(daddr), &remote_ip6.s6_addr32[3], 4, kver);
+        (void)bpf_skb_load_bytes_net(skb, IP4_OFFSET(protocol), &ip_proto, sizeof(ip_proto), kver);
+        uint8_t ihl;
+        (void)bpf_skb_load_bytes_net(skb, IPPROTO_IHL_OFF, &ihl, sizeof(ihl), kver);
+        L4_off = (ihl & 0x0F) * 4;  // IHL calculation.
+    } else if (skb->protocol == htons(ETH_P_IPV6)) {
+        (void)bpf_skb_load_bytes_net(skb, IP6_OFFSET(daddr), &remote_ip6, sizeof(remote_ip6), kver);
+        (void)bpf_skb_load_bytes_net(skb, IP6_OFFSET(nexthdr), &ip_proto, sizeof(ip_proto), kver);
+        L4_off = sizeof(struct ipv6hdr);
+    } else {
+        return false;
+    }
+
+    __be16 port = 0;
+    switch (ip_proto) {
+      case IPPROTO_TCP:
+      case IPPROTO_DCCP:
+      case IPPROTO_UDP:
+      case IPPROTO_UDPLITE:
+      case IPPROTO_SCTP:
+        (void)bpf_skb_load_bytes_net(skb, L4_off + 2, &port, sizeof(port), kver);
+        break;
+    }
+
+    return !is_local_net_access_allowed(skb->ifindex, &remote_ip6, ip_proto, port);
+}
+
 static __always_inline inline void do_packet_tracing(
         const struct __sk_buff* const skb, const struct egress_bool egress, const uint32_t uid,
         const uint32_t tag, const struct kver_uint kver) {
@@ -510,7 +546,7 @@
     }
 
     if (SDK_LEVEL_IS_AT_LEAST(lvl, 25Q2) && (match != DROP)) {
-        // TODO: implement local network blocking
+        if (egress.egress && should_block_local_network_packets(skb, kver)) match = DROP;
     }
 
     // If an outbound packet is going to be dropped, we do not count that traffic.