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)) { 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->eth_addr, eth->source, sizeof(dest->eth_addr)); } if (dest) { dest->type = MR_ADDR_ETHER; dest->netbits = 0; dest->len = 6; memcpy(dest->eth_addr, eth->dest, sizeof(dest->eth_addr)); /* 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))) { switch (ntohs(eth->proto)) { case OPENVPN_ETH_P_IPV4: ret |= (mroute_extract_addr_ip(esrc, edest, &b) << MROUTE_SEC_SHIFT); break; case OPENVPN_ETH_P_ARP: ret |= (mroute_extract_addr_arp(esrc, edest, &b) << MROUTE_SEC_SHIFT); break; } } } #endif } return ret; }
static inline bool is_mac_mcast_maddr (const struct mroute_addr *addr) { return (addr->type & MR_ADDR_MASK) == MR_ADDR_ETHER && is_mac_mcast_addr (addr->addr); }