* Process a received IGMPv1 query. * Return non-zero if the message should be dropped. * * VIMAGE: The curvnet pointer is derived from the input ifp. */
| 753 | * VIMAGE: The curvnet pointer is derived from the input ifp. |
| 754 | */ |
| 755 | static int |
| 756 | igmp_input_v1_query(struct ifnet *ifp, const struct ip *ip, |
| 757 | const struct igmp *igmp) |
| 758 | { |
| 759 | struct ifmultiaddr *ifma; |
| 760 | struct igmp_ifsoftc *igi; |
| 761 | struct in_multi *inm; |
| 762 | |
| 763 | NET_EPOCH_ASSERT(); |
| 764 | |
| 765 | /* |
| 766 | * IGMPv1 Host Mmembership Queries SHOULD always be addressed to |
| 767 | * 224.0.0.1. They are always treated as General Queries. |
| 768 | * igmp_group is always ignored. Do not drop it as a userland |
| 769 | * daemon may wish to see it. |
| 770 | * XXX SMPng: unlocked increments in igmpstat assumed atomic. |
| 771 | */ |
| 772 | if (!in_allhosts(ip->ip_dst) || !in_nullhost(igmp->igmp_group)) { |
| 773 | IGMPSTAT_INC(igps_rcv_badqueries); |
| 774 | return (0); |
| 775 | } |
| 776 | IGMPSTAT_INC(igps_rcv_gen_queries); |
| 777 | |
| 778 | IN_MULTI_LIST_LOCK(); |
| 779 | IGMP_LOCK(); |
| 780 | |
| 781 | igi = ((struct in_ifinfo *)ifp->if_afdata[AF_INET])->ii_igmp; |
| 782 | KASSERT(igi != NULL, ("%s: no igmp_ifsoftc for ifp %p", __func__, ifp)); |
| 783 | |
| 784 | if (igi->igi_flags & IGIF_LOOPBACK) { |
| 785 | CTR2(KTR_IGMPV3, "ignore v1 query on IGIF_LOOPBACK ifp %p(%s)", |
| 786 | ifp, ifp->if_xname); |
| 787 | goto out_locked; |
| 788 | } |
| 789 | |
| 790 | /* |
| 791 | * Switch to IGMPv1 host compatibility mode. |
| 792 | */ |
| 793 | igmp_set_version(igi, IGMP_VERSION_1); |
| 794 | |
| 795 | CTR2(KTR_IGMPV3, "process v1 query on ifp %p(%s)", ifp, ifp->if_xname); |
| 796 | |
| 797 | /* |
| 798 | * Start the timers in all of our group records |
| 799 | * for the interface on which the query arrived, |
| 800 | * except those which are already running. |
| 801 | */ |
| 802 | CK_STAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { |
| 803 | if (ifma->ifma_addr->sa_family != AF_INET || |
| 804 | ifma->ifma_protospec == NULL) |
| 805 | continue; |
| 806 | inm = (struct in_multi *)ifma->ifma_protospec; |
| 807 | if (inm->inm_timer != 0) |
| 808 | continue; |
| 809 | switch (inm->inm_state) { |
| 810 | case IGMP_NOT_MEMBER: |
| 811 | case IGMP_SILENT_MEMBER: |
| 812 | break; |
no test coverage detected