⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 mld6igmp_vif.cc

📁 MLDv2 support igmpv3 lite
💻 CC
📖 第 1 页 / 共 4 页
字号:
    bool check_src_linklocal_unicast = false;    bool allow_src_zero_address = false;    bool check_dst_multicast = false;    bool check_group_interfacelocal_multicast = false;    bool decode_extra_fields = false;        //    // Message length check.    //    if (BUFFER_DATA_SIZE(buffer) < mld6igmp_constant_minlen()) {	error_msg = c_format("RX packet from %s to %s on vif %s: "			     "too short data field (%u octets)",			     cstring(src), cstring(dst),			     name().c_str(),			     XORP_UINT_CAST(BUFFER_DATA_SIZE(buffer)));	XLOG_WARNING("%s", error_msg.c_str());	return (XORP_ERROR);    }        //    // Checksum verification.    //    cksum = inet_checksum(BUFFER_DATA_HEAD(buffer), BUFFER_DATA_SIZE(buffer));#ifdef HAVE_IPV6    // Add the checksum for the IPv6 pseudo-header    if (proto_is_mld6()) {	uint16_t cksum2;	size_t ph_len = BUFFER_DATA_SIZE(buffer);	cksum2 = calculate_ipv6_pseudo_header_checksum(src, dst, ph_len,						       IPPROTO_ICMPV6);	cksum = inet_checksum_add(cksum, cksum2);    }#endif // HAVE_IPV6    if (cksum) {	error_msg = c_format("RX packet from %s to %s on vif %s: "			     "checksum error",			     cstring(src), cstring(dst),			     name().c_str());	XLOG_WARNING("%s", error_msg.c_str());	return (XORP_ERROR);    }        //    // Protocol version check.    //    // XXX: MLD and IGMP messages do not have an explicit field for protocol    // version. Protocol version check is performed later, per (some) message    // type.    //        //    // Get the message type and the max. resp. time (in case of IGMP).    //    // Note that in case of IGMP the max. resp. time is the `igmp_code' field    // in `struct igmp'.    //    if (proto_is_igmp()) {	BUFFER_GET_OCTET(message_type, buffer);	BUFFER_GET_OCTET(max_resp_code, buffer);	BUFFER_GET_SKIP(2, buffer);		// The checksum    }    if (proto_is_mld6()) {	BUFFER_GET_OCTET(message_type, buffer);	BUFFER_GET_SKIP(1, buffer);		// The `Code' field: unused	BUFFER_GET_SKIP(2, buffer);		// The `Checksum' field    }    XLOG_TRACE(mld6igmp_node().is_log_trace(),	       "RX %s from %s to %s on vif %s",	       proto_message_type2ascii(message_type),	       cstring(src), cstring(dst),	       name().c_str());    //    // Ignore messages that are not recognized by older protocol version.    //    // XXX: Unrecognized message types MUST be silently ignored.    //    if (proto_is_igmp()) {	switch (message_type) {	case IGMP_MEMBERSHIP_QUERY:	    // Recognized by IGMPv1, IGMPv2, IGMPv3	    break;	case IGMP_V1_MEMBERSHIP_REPORT:	    // Recognized by IGMPv1, IGMPv2, IGMPv3	    break;	case IGMP_V2_MEMBERSHIP_REPORT:	    // Recognized by IGMPv2, IGMPv3	    if (is_igmpv1_mode())		return (XORP_ERROR);	    break;	case IGMP_V2_LEAVE_GROUP:	    // Recognized by IGMPv2, IGMPv3	    if (is_igmpv1_mode())		return (XORP_ERROR);	    break;	case IGMP_V3_MEMBERSHIP_REPORT:	    // Recognized by IGMPv3	    if (is_igmpv1_mode() || is_igmpv2_mode())		return (XORP_ERROR);	    break;	case IGMP_DVMRP:	case IGMP_MTRACE:	    break;	default:	    // Unrecognized message	    return (XORP_ERROR);	}    }    if (proto_is_mld6()) {	switch (message_type) {	case MLD_LISTENER_QUERY:	    // Recognized by MLDv1, MLDv2	    break;	case MLD_LISTENER_REPORT:	    // Recognized by MLDv1, MLDv2	    break;	case MLD_LISTENER_DONE:	    // Recognized by MLDv1, MLDv2	    break;	case MLDV2_LISTENER_REPORT:	    // Recognized by MLDv2	    if (is_mldv1_mode())		return (XORP_ERROR);	    break;	case MLD_MTRACE:	    break;	default:	    // Unrecognized message	    return (XORP_ERROR);	}    }    //    // Assign various flags what needs to be checked, based on the    // message type:    //  - check_router_alert_option    //  - check_src_linklocal_unicast    //  - allow_src_zero_address    //  - check_dst_multicast    //  - check_group_interfacelocal_multicast    //  - decode_extra_fields    //    if (proto_is_igmp()) {	switch (message_type) {	case IGMP_MEMBERSHIP_QUERY:	case IGMP_V1_MEMBERSHIP_REPORT:	case IGMP_V2_MEMBERSHIP_REPORT:	case IGMP_V2_LEAVE_GROUP:	case IGMP_V3_MEMBERSHIP_REPORT:	    if (_ip_router_alert_option_check.get())		check_router_alert_option = true;	    check_src_linklocal_unicast = false;	// Not needed for IPv4	    if (is_igmpv3_mode()) {		if ((message_type == IGMP_V1_MEMBERSHIP_REPORT)		    || (message_type == IGMP_V2_MEMBERSHIP_REPORT)		    || (message_type == IGMP_V3_MEMBERSHIP_REPORT)) {		    allow_src_zero_address = true;	// True only for IGMPv3		}	    }	    check_dst_multicast = true;	    if (is_igmpv3_mode())		check_dst_multicast = false;		// XXX: disable	    check_group_interfacelocal_multicast = false;// Not needed for IPv4	    decode_extra_fields = true;	    if (message_type == IGMP_V3_MEMBERSHIP_REPORT)		decode_extra_fields = false;	    break;	case IGMP_DVMRP:	case IGMP_MTRACE:	    // TODO: Assign the flags as appropriate	    break;	default:	    break;	}    }    if (proto_is_mld6()) {	switch (message_type) {	case MLD_LISTENER_QUERY:	case MLD_LISTENER_REPORT:	case MLD_LISTENER_DONE:	case MLDV2_LISTENER_REPORT:	    check_router_alert_option = true;	    check_src_linklocal_unicast = true;	    allow_src_zero_address = false;		// Always false for MLD	    check_dst_multicast = true;	    if (is_mldv2_mode())		check_dst_multicast = false;		// XXX: disable	    check_group_interfacelocal_multicast = true;	    decode_extra_fields = true;	    if (message_type == MLDV2_LISTENER_REPORT)		decode_extra_fields = false;	    break;	case MLD_MTRACE:	    // TODO: Assign the flags as appropriate	    break;	default:	    break;	}    }    //    // Decode the extra fields: the max. resp. time (in case of MLD),    // and the group address.    //    if (decode_extra_fields) {	if (proto_is_igmp()) {	    BUFFER_GET_IPVX(family(), group_address, buffer);	}	if (proto_is_mld6()) {	    BUFFER_GET_HOST_16(max_resp_code, buffer);	    BUFFER_GET_SKIP(2, buffer);		// The `Reserved' field	    BUFFER_GET_IPVX(family(), group_address, buffer);	}    }    //    // IP Router Alert option check.    //    if (check_router_alert_option && (! ip_router_alert)) {	error_msg = c_format("RX %s from %s to %s on vif %s: "			     "missing IP Router Alert option",			     proto_message_type2ascii(message_type),			     cstring(src), cstring(dst),			     name().c_str());	XLOG_WARNING("%s", error_msg.c_str());	return (XORP_ERROR);    }    //    // TODO: check the TTL, TOS and ip_internet_control flag if we are    // running in secure mode.    //    UNUSED(ip_ttl);    UNUSED(ip_tos);    UNUSED(ip_internet_control);#if 0    if (ip_ttl != MINTTL) {	error_msg = c_format("RX %s from %s to %s on vif %s: "			     "ip_ttl = %d instead of %d",			     proto_message_type2ascii(message_type),			     cstring(src), cstring(dst),			     name().c_str(),			     ip_ttl, MINTTL);	XLOG_WARNING("%s", error_msg.c_str());	return (XORP_ERROR);    }#endif // 0        //    // Source address check.    //    if (! src.is_unicast()) {	//	// Source address must always be unicast.	// The kernel should have checked that, but just in case...	//	error_msg = c_format("RX %s from %s to %s on vif %s: "			     "source must be unicast",			     proto_message_type2ascii(message_type),			     cstring(src), cstring(dst),			     name().c_str());	XLOG_WARNING("%s", error_msg.c_str());	return (XORP_ERROR);    }    if (src.af() != family()) {	// Invalid source address family	XLOG_WARNING("RX %s from %s to %s on vif %s: "		     "invalid source address family "		     "(received %d expected %d)",		     proto_message_type2ascii(message_type),		     cstring(src), cstring(dst),		     name().c_str(),		     src.af(), family());    }    // Source address must be directly connected    if (! mld6igmp_node().is_directly_connected(*this, src)) {	error_msg = c_format("RX %s from %s to %s on vif %s: "			     "source must be directly connected",			     proto_message_type2ascii(message_type),			     cstring(src), cstring(dst),			     name().c_str());	XLOG_WARNING("%s", error_msg.c_str());	return (XORP_ERROR);    }    if (check_src_linklocal_unicast) {	if (src.is_linklocal_unicast()	    || (allow_src_zero_address && src.is_zero())) {	    // The source address is link-local or (allowed) zero address	} else {	    // The source address is not link-local	    error_msg = c_format("RX %s from %s to %s on vif %s: "				 "source is not a link-local address",				 proto_message_type2ascii(message_type),				 cstring(src), cstring(dst),				 name().c_str());	    XLOG_WARNING("%s", error_msg.c_str());	    return (XORP_ERROR);	}    }    //    // Destination address check.    //    if (dst.af() != family()) {	// Invalid destination address family	XLOG_WARNING("RX %s from %s to %s on vif %s: "		     "invalid destination address family "		     "(received %d expected %d)",		     proto_message_type2ascii(message_type),		     cstring(src), cstring(dst),		     name().c_str(),		     dst.af(), family());    }    if (check_dst_multicast && (! dst.is_multicast())) {	// The destination address is not multicast	error_msg = c_format("RX %s from %s to %s on vif %s: "			     "destination must be multicast. "			     "Packet ignored.",			     proto_message_type2ascii(message_type),			     cstring(src), cstring(dst),			     name().c_str());	XLOG_WARNING("%s", error_msg.c_str());	return (XORP_ERROR);    }    //    // Inner multicast address scope check.    //    if (check_group_interfacelocal_multicast	&& group_address.is_interfacelocal_multicast()) {	error_msg = c_format("RX %s from %s to %s on vif %s: "			     "invalid interface-local scope of inner "			     "multicast address: %s",			     proto_message_type2ascii(message_type),			     cstring(src), cstring(dst),			     name().c_str(),			     cstring(group_address));	XLOG_WARNING("%s", error_msg.c_str());	return (XORP_ERROR);    }    //    // Origin router neighbor check.    //    // XXX: in IGMP and MLD we don't need such check        //    // Process each message, based on its type.    //    if (proto_is_igmp()) {	switch (message_type) {	case IGMP_MEMBERSHIP_QUERY:	    mld6igmp_membership_query_recv(src, dst,					   message_type, max_resp_code,					   group_address, buffer);	    break;	case IGMP_V1_MEMBERSHIP_REPORT:	case IGMP_V2_MEMBERSHIP_REPORT:	    mld6igmp_membership_report_recv(src, dst,					    message_type, max_resp_code,					    group_address, buffer);	    break;	case IGMP_V2_LEAVE_GROUP:	    mld6igmp_leave_group_recv(src, dst,				      message_type, max_resp_code,				      group_address, buffer);	    break;	case IGMP_V3_MEMBERSHIP_REPORT:	    mld6igmp_ssm_membership_report_recv(src, dst, message_type,						buffer);	    break;	case IGMP_DVMRP:	{	    //	    // XXX: We care only about the DVMRP messages that are used	    // by mrinfo.	    //	    // XXX: the older purpose of the 'igmp_code' field	    uint16_t igmp_code = max_resp_code;	    switch (igmp_code) {	    case DVMRP_ASK_NEIGHBORS:		// Some old DVMRP messages from mrinfo(?).		// TODO: not implemented yet.		// TODO: do we really need this message implemented?		break;	    case DVMRP_ASK_NEIGHBORS2:		// Used for mrinfo support.		// XXX: not implemented yet.		break;	    case DVMRP_INFO_REQUEST:		// Information request (TODO: used by mrinfo?)		// TODO: not implemented yet.		break;	    default:		// XXX: We don't care about the rest of the DVMRP_* messages		break;	    }	}	case IGMP_MTRACE:	    // TODO: is this the new message sent by 'mtrace'?	    // TODO: not implemented yet.	    break;	default:	    // XXX: Unrecognized message types MUST be silently ignored.	    break;	}    }    if (proto_is_mld6()) {	switch (message_type) {	case MLD_LISTENER_QUERY:	    mld6igmp_membership_query_recv(src, dst,					   message_type, max_resp_code,					   group_address, buffer);	    break;	case MLD_LISTENER_REPORT:	    mld6igmp_membership_report_recv(src, dst,					    message_type, max_resp_code,					    group_address, buffer);	    break;	case MLD_LISTENER_DONE:	    mld6igmp_leave_group_recv(src, dst,				      message_type, max_resp_code,				      group_address, buffer);	    break;	case MLDV2_LISTENER_REPORT:	    mld6igmp_ssm_membership_report_recv(src, dst, message_type,						buffer);	    break;	case MLD_MTRACE:	    // TODO: is this the new message sent by 'mtrace'?	    // TODO: not implemented yet.	    break;	default:	    // XXX: Unrecognized message types MUST be silently ignored.	    break;	}    }    return (XORP_OK); rcvlen_error:    XLOG_UNREACHABLE();    error_msg = c_format("RX packet from %s to %s on vif %s: "			 "some fields are too short",			 cstring(src), cstring(dst),			 name().c_str());    XLOG_WARNING("%s", error_msg.c_str());    return (XORP_ERROR);}/** * Mld6igmpVif::update_primary_address: * @error_msg: The error message (if error). *  * Update the primary address. *  * The primary address should be a link-local unicast address, and * is used for transmitting the multicast control packets on the LAN. *  * Return value: %XORP_OK on success, otherwise %XORP_ERROR. **/intMld6igmpVif::update_primary_address(string& error_msg){    bool i_was_querier = false;    IPvX primary_a(IPvX::ZERO(family()));    IPvX domain_wide_a(IPvX::ZERO(family()));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -