?? mld6igmp_vif.cc
字號:
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 + -