mirror of
https://git.proxmox.com/git/mirror_frr
synced 2025-07-27 06:43:52 +00:00
Merge pull request #9074 from mobash-rasool/pim-fixes
pimd: IGMPv3 conformance fixes for invalid TTL and invalid TOS
This commit is contained in:
commit
b57d3daeea
@ -469,6 +469,45 @@ static int igmp_v1_recv_report(struct igmp_sock *igmp, struct in_addr from,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool pim_igmp_verify_header(struct ip *ip_hdr, size_t len, int igmp_msg_len,
|
||||||
|
int msg_type)
|
||||||
|
{
|
||||||
|
if (len < sizeof(*ip_hdr)) {
|
||||||
|
zlog_warn("IGMP packet size=%zu shorter than minimum=%zu", len,
|
||||||
|
sizeof(*ip_hdr));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (igmp_msg_len < PIM_IGMP_MIN_LEN) {
|
||||||
|
zlog_warn("IGMP message size=%d shorter than minimum=%d",
|
||||||
|
igmp_msg_len, PIM_IGMP_MIN_LEN);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((msg_type != PIM_IGMP_MTRACE_RESPONSE)
|
||||||
|
&& (msg_type != PIM_IGMP_MTRACE_QUERY_REQUEST)) {
|
||||||
|
if (ip_hdr->ip_ttl != 1) {
|
||||||
|
zlog_warn(
|
||||||
|
"Recv IGMP packet with invalid ttl=%u, discarding the packet",
|
||||||
|
ip_hdr->ip_ttl);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((msg_type == PIM_IGMP_V3_MEMBERSHIP_REPORT)
|
||||||
|
|| ((msg_type == PIM_IGMP_MEMBERSHIP_QUERY)
|
||||||
|
&& (igmp_msg_len >= IGMP_V3_SOURCES_OFFSET))) {
|
||||||
|
/* All IGMPv3 messages must be received with TOS set to 0xC0*/
|
||||||
|
if (ip_hdr->ip_tos != IPTOS_PREC_INTERNETCONTROL) {
|
||||||
|
zlog_warn("Received IGMP Packet with invalid TOS %u",
|
||||||
|
ip_hdr->ip_tos);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len)
|
int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len)
|
||||||
{
|
{
|
||||||
struct ip *ip_hdr;
|
struct ip *ip_hdr;
|
||||||
@ -479,17 +518,8 @@ int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len)
|
|||||||
char from_str[INET_ADDRSTRLEN];
|
char from_str[INET_ADDRSTRLEN];
|
||||||
char to_str[INET_ADDRSTRLEN];
|
char to_str[INET_ADDRSTRLEN];
|
||||||
|
|
||||||
if (len < sizeof(*ip_hdr)) {
|
|
||||||
zlog_warn("IGMP packet size=%zu shorter than minimum=%zu", len,
|
|
||||||
sizeof(*ip_hdr));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
ip_hdr = (struct ip *)buf;
|
ip_hdr = (struct ip *)buf;
|
||||||
|
|
||||||
pim_inet4_dump("<src?>", ip_hdr->ip_src, from_str, sizeof(from_str));
|
|
||||||
pim_inet4_dump("<dst?>", ip_hdr->ip_dst, to_str, sizeof(to_str));
|
|
||||||
|
|
||||||
ip_hlen = ip_hdr->ip_hl << 2; /* ip_hl gives length in 4-byte words */
|
ip_hlen = ip_hdr->ip_hl << 2; /* ip_hl gives length in 4-byte words */
|
||||||
|
|
||||||
if (ip_hlen > len) {
|
if (ip_hlen > len) {
|
||||||
@ -501,15 +531,11 @@ int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len)
|
|||||||
|
|
||||||
igmp_msg = buf + ip_hlen;
|
igmp_msg = buf + ip_hlen;
|
||||||
igmp_msg_len = len - ip_hlen;
|
igmp_msg_len = len - ip_hlen;
|
||||||
|
|
||||||
if (igmp_msg_len < PIM_IGMP_MIN_LEN) {
|
|
||||||
zlog_warn("IGMP message size=%d shorter than minimum=%d",
|
|
||||||
igmp_msg_len, PIM_IGMP_MIN_LEN);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
msg_type = *igmp_msg;
|
msg_type = *igmp_msg;
|
||||||
|
|
||||||
|
pim_inet4_dump("<src?>", ip_hdr->ip_src, from_str, sizeof(from_str));
|
||||||
|
pim_inet4_dump("<dst?>", ip_hdr->ip_dst, to_str, sizeof(to_str));
|
||||||
|
|
||||||
if (PIM_DEBUG_IGMP_PACKETS) {
|
if (PIM_DEBUG_IGMP_PACKETS) {
|
||||||
zlog_debug(
|
zlog_debug(
|
||||||
"Recv IGMP packet from %s to %s on %s: size=%zu ttl=%d msg_type=%d msg_size=%d",
|
"Recv IGMP packet from %s to %s on %s: size=%zu ttl=%d msg_type=%d msg_size=%d",
|
||||||
@ -517,6 +543,14 @@ int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len)
|
|||||||
msg_type, igmp_msg_len);
|
msg_type, igmp_msg_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!pim_igmp_verify_header(ip_hdr, len, igmp_msg_len, msg_type)) {
|
||||||
|
zlog_warn(
|
||||||
|
"Recv IGMP packet from %s to %s on %s: size=%zu ttl=%u msg_type=%d msg_size=%d",
|
||||||
|
from_str, to_str, igmp->interface->name, len,
|
||||||
|
ip_hdr->ip_ttl, msg_type, igmp_msg_len);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
switch (msg_type) {
|
switch (msg_type) {
|
||||||
case PIM_IGMP_MEMBERSHIP_QUERY: {
|
case PIM_IGMP_MEMBERSHIP_QUERY: {
|
||||||
int max_resp_code = igmp_msg[1];
|
int max_resp_code = igmp_msg[1];
|
||||||
|
@ -116,7 +116,8 @@ void igmp_sock_delete(struct igmp_sock *igmp);
|
|||||||
void igmp_sock_free(struct igmp_sock *igmp);
|
void igmp_sock_free(struct igmp_sock *igmp);
|
||||||
void igmp_sock_delete_all(struct interface *ifp);
|
void igmp_sock_delete_all(struct interface *ifp);
|
||||||
int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len);
|
int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len);
|
||||||
|
bool pim_igmp_verify_header(struct ip *ip_hdr, size_t len, int igmp_msg_len,
|
||||||
|
int msg_type);
|
||||||
void pim_igmp_general_query_on(struct igmp_sock *igmp);
|
void pim_igmp_general_query_on(struct igmp_sock *igmp);
|
||||||
void pim_igmp_general_query_off(struct igmp_sock *igmp);
|
void pim_igmp_general_query_off(struct igmp_sock *igmp);
|
||||||
void pim_igmp_other_querier_timer_on(struct igmp_sock *igmp);
|
void pim_igmp_other_querier_timer_on(struct igmp_sock *igmp);
|
||||||
|
Loading…
Reference in New Issue
Block a user