aboutsummaryrefslogtreecommitdiff
path: root/mroute.c
diff options
context:
space:
mode:
Diffstat (limited to 'mroute.c')
-rw-r--r--mroute.c213
1 files changed, 144 insertions, 69 deletions
diff --git a/mroute.c b/mroute.c
index 5922b8a..5b383a9 100644
--- a/mroute.c
+++ b/mroute.c
@@ -76,87 +76,144 @@ mroute_learnable_address (const struct mroute_addr *addr)
return not_all_zeros && not_all_ones && !is_mac_mcast_maddr (addr);
}
-/*
- * Given a raw packet in buf, return the src and dest
- * addresses of the packet.
- */
+static inline void
+mroute_get_in_addr_t (struct mroute_addr *ma, const in_addr_t src, unsigned int mask)
+{
+ if (ma)
+ {
+ ma->type = MR_ADDR_IPV4 | mask;
+ ma->netbits = 0;
+ ma->len = 4;
+ *(in_addr_t*)ma->addr = src;
+ }
+}
+
+static inline bool
+mroute_is_mcast (const in_addr_t addr)
+{
+ return ((addr & htonl(IP_MCAST_SUBNET_MASK)) == htonl(IP_MCAST_NETWORK));
+}
+
+#ifdef ENABLE_PF
+
+static unsigned int
+mroute_extract_addr_arp (struct mroute_addr *src,
+ struct mroute_addr *dest,
+ const struct buffer *buf)
+{
+ unsigned int ret = 0;
+ if (BLEN (buf) >= (int) sizeof (struct openvpn_arp))
+ {
+ const struct openvpn_arp *arp = (const struct openvpn_arp *) BPTR (buf);
+ if (arp->mac_addr_type == htons(0x0001)
+ && arp->proto_addr_type == htons(0x0800)
+ && arp->mac_addr_size == 0x06
+ && arp->proto_addr_size == 0x04)
+ {
+ mroute_get_in_addr_t (src, arp->ip_src, MR_ARP);
+ mroute_get_in_addr_t (dest, arp->ip_dest, MR_ARP);
+
+ /* multicast packet? */
+ if (mroute_is_mcast (arp->ip_dest))
+ ret |= MROUTE_EXTRACT_MCAST;
+
+ ret |= MROUTE_EXTRACT_SUCCEEDED;
+ }
+ }
+ return ret;
+}
+
+#endif
+
unsigned int
-mroute_extract_addr_from_packet (struct mroute_addr *src,
- struct mroute_addr *dest,
- struct buffer *buf,
- int tunnel_type)
+mroute_extract_addr_ipv4 (struct mroute_addr *src,
+ struct mroute_addr *dest,
+ const struct buffer *buf)
{
unsigned int ret = 0;
- verify_align_4 (buf);
- if (tunnel_type == DEV_TYPE_TUN)
+ if (BLEN (buf) >= 1)
{
- if (BLEN (buf) >= 1)
+ switch (OPENVPN_IPH_GET_VER (*BPTR(buf)))
{
- switch (OPENVPN_IPH_GET_VER (*BPTR(buf)))
+ case 4:
+ if (BLEN (buf) >= (int) sizeof (struct openvpn_iphdr))
{
- case 4:
- if (BLEN (buf) >= (int) sizeof (struct openvpn_iphdr))
- {
- const struct openvpn_iphdr *ip = (const struct openvpn_iphdr *) BPTR (buf);
- if (src)
- {
- src->type = MR_ADDR_IPV4;
- src->netbits = 0;
- src->len = 4;
- memcpy (src->addr, &ip->saddr, 4);
- }
- if (dest)
- {
- dest->type = MR_ADDR_IPV4;
- dest->netbits = 0;
- dest->len = 4;
- memcpy (dest->addr, &ip->daddr, 4);
-
- /* mcast address? */
- if ((ip->daddr & htonl(IP_MCAST_SUBNET_MASK)) == htonl(IP_MCAST_NETWORK))
- ret |= MROUTE_EXTRACT_MCAST;
-
- /* IGMP message? */
- if (ip->protocol == OPENVPN_IPPROTO_IGMP)
- ret |= MROUTE_EXTRACT_IGMP;
- }
- ret |= MROUTE_EXTRACT_SUCCEEDED;
- }
- break;
- case 6:
- {
- msg (M_WARN, "Need IPv6 code in mroute_extract_addr_from_packet");
- break;
- }
+ const struct openvpn_iphdr *ip = (const struct openvpn_iphdr *) BPTR (buf);
+
+ mroute_get_in_addr_t (src, ip->saddr, 0);
+ mroute_get_in_addr_t (dest, ip->daddr, 0);
+
+ /* multicast packet? */
+ if (mroute_is_mcast (ip->daddr))
+ ret |= MROUTE_EXTRACT_MCAST;
+
+ /* IGMP message? */
+ if (ip->protocol == OPENVPN_IPPROTO_IGMP)
+ ret |= MROUTE_EXTRACT_IGMP;
+
+ ret |= MROUTE_EXTRACT_SUCCEEDED;
}
+ break;
+ case 6:
+ {
+ msg (M_WARN, "Need IPv6 code in mroute_extract_addr_from_packet");
+ break;
+ }
}
}
- else if (tunnel_type == DEV_TYPE_TAP)
+ return ret;
+}
+
+unsigned int
+mroute_extract_addr_ether (struct mroute_addr *src,
+ struct mroute_addr *dest,
+ struct mroute_addr *esrc,
+ struct mroute_addr *edest,
+ const struct buffer *buf)
+{
+ unsigned int ret = 0;
+ if (BLEN (buf) >= (int) sizeof (struct openvpn_ethhdr))
{
- if (BLEN (buf) >= (int) sizeof (struct openvpn_ethhdr))
+ const struct openvpn_ethhdr *eth = (const struct openvpn_ethhdr *) BPTR (buf);
+ if (src)
{
- const struct openvpn_ethhdr *eth = (const struct openvpn_ethhdr *) BPTR (buf);
- if (src)
- {
- src->type = MR_ADDR_ETHER;
- src->netbits = 0;
- src->len = 6;
- memcpy (src->addr, eth->source, 6);
- }
- if (dest)
+ src->type = MR_ADDR_ETHER;
+ src->netbits = 0;
+ src->len = 6;
+ memcpy (src->addr, eth->source, 6);
+ }
+ if (dest)
+ {
+ dest->type = MR_ADDR_ETHER;
+ dest->netbits = 0;
+ dest->len = 6;
+ memcpy (dest->addr, eth->dest, 6);
+
+ /* ethernet broadcast/multicast packet? */
+ if (is_mac_mcast_addr (eth->dest))
+ ret |= MROUTE_EXTRACT_BCAST;
+ }
+
+ ret |= MROUTE_EXTRACT_SUCCEEDED;
+
+#ifdef ENABLE_PF
+ if (esrc || edest)
+ {
+ struct buffer b = *buf;
+ if (buf_advance (&b, sizeof (struct openvpn_ethhdr)))
{
- dest->type = MR_ADDR_ETHER;
- dest->netbits = 0;
- dest->len = 6;
- memcpy (dest->addr, eth->dest, 6);
-
- /* ethernet broadcast/multicast packet? */
- if (is_mac_mcast_addr (eth->dest))
- ret |= MROUTE_EXTRACT_BCAST;
+ switch (ntohs (eth->proto))
+ {
+ case OPENVPN_ETH_P_IPV4:
+ ret |= (mroute_extract_addr_ipv4 (esrc, edest, &b) << MROUTE_SEC_SHIFT);
+ break;
+ case OPENVPN_ETH_P_ARP:
+ ret |= (mroute_extract_addr_arp (esrc, edest, &b) << MROUTE_SEC_SHIFT);
+ break;
+ }
}
-
- ret |= MROUTE_EXTRACT_SUCCEEDED;
}
+#endif
}
return ret;
}
@@ -229,6 +286,14 @@ const char *
mroute_addr_print (const struct mroute_addr *ma,
struct gc_arena *gc)
{
+ return mroute_addr_print_ex (ma, MAPF_IA_EMPTY_IF_UNDEF, gc);
+}
+
+const char *
+mroute_addr_print_ex (const struct mroute_addr *ma,
+ const unsigned int flags,
+ struct gc_arena *gc)
+{
struct buffer out = alloc_buf_gc (64, gc);
if (ma)
{
@@ -249,9 +314,19 @@ mroute_addr_print (const struct mroute_addr *ma,
addr = buf_read_u32 (&buf, &status);
if (status)
{
- buf_printf (&out, "%s", print_in_addr_t (addr, IA_EMPTY_IF_UNDEF, gc));
+ if ((flags & MAPF_SHOW_ARP) && (maddr.type & MR_ARP))
+ buf_printf (&out, "ARP/");
+ buf_printf (&out, "%s", print_in_addr_t (addr, (flags & MAPF_IA_EMPTY_IF_UNDEF) ? IA_EMPTY_IF_UNDEF : 0, gc));
if (maddr.type & MR_WITH_NETBITS)
- buf_printf (&out, "/%d", maddr.netbits);
+ {
+ if (flags & MAPF_SUBNET)
+ {
+ const in_addr_t netmask = netbits_to_netmask (maddr.netbits);
+ buf_printf (&out, "/%s", print_in_addr_t (netmask, 0, gc));
+ }
+ else
+ buf_printf (&out, "/%d", maddr.netbits);
+ }
}
if (maddr.type & MR_WITH_PORT)
{