static int lw_nsnap_receive(struct lw_psr_port_priv *psr_ppriv) { struct lw_nsnap_port_priv *nsnap_ppriv = lw_nsnap_ppriv_get(psr_ppriv); struct na_packet nap; struct sockaddr_ll ll_from; int err; err = teamd_recvfrom(psr_ppriv->sock, &nap, sizeof(nap), 0, (struct sockaddr *) &ll_from, sizeof(ll_from)); if (err <= 0) return err; /* check IPV6 header */ if (nap.ip6h.ip6_vfc != 0x60 /* IPV6 */ || nap.ip6h.ip6_plen != htons(sizeof(nap) - sizeof(nap.ip6h)) || nap.ip6h.ip6_nxt != IPPROTO_ICMPV6 || nap.ip6h.ip6_hlim != 255 /* Do not route */ || memcmp(&nap.ip6h.ip6_src, &nsnap_ppriv->dst.sin6_addr, sizeof(struct in6_addr))) return 0; /* check ICMP6 header */ if (nap.nah.nd_na_type != ND_NEIGHBOR_ADVERT || nap.opt.nd_opt_type != ND_OPT_TARGET_LINKADDR || nap.opt.nd_opt_len != 1 /* 8 bytes */) return 0; psr_ppriv->reply_received = true; return 0; }
static int lw_ap_receive(struct lw_psr_port_priv *psr_ppriv) { struct lw_common_port_priv *common_ppriv = &psr_ppriv->common; struct lw_ap_port_priv *ap_ppriv = lw_ap_ppriv_get(psr_ppriv); int err; struct sockaddr_ll ll_my; struct sockaddr_ll ll_from; struct arp_packet ap; bool port_enabled; err = teamd_recvfrom(psr_ppriv->sock, &ap, sizeof(ap), 0, (struct sockaddr *) &ll_from, sizeof(ll_from)); if (err <= 0) return err; err = teamd_port_enabled(common_ppriv->ctx, common_ppriv->tdport, &port_enabled); if (err) return err; if ((port_enabled && ap_ppriv->validate_active) || (!port_enabled && ap_ppriv->validate_inactive)) { err = __get_port_curr_hwaddr(psr_ppriv, &ll_my, 0); if (err) return err; if (ap.ah.ar_hrd != htons(ll_my.sll_hatype) || ap.ah.ar_pro != htons(ETH_P_IP) || ap.ah.ar_hln != ll_my.sll_halen || ap.ah.ar_pln != 4) { return 0; } if ((ap_ppriv->src.s_addr != ap.target_ip.s_addr || ap_ppriv->dst.s_addr != ap.sender_ip.s_addr) && (ap_ppriv->dst.s_addr != ap.target_ip.s_addr || ap_ppriv->src.s_addr != ap.sender_ip.s_addr)) return 0; } psr_ppriv->reply_received = true; return 0; }