diff --git a/pimd/pim_igmp.c b/pimd/pim_igmp.c index 3325b6ee34..426112d4d6 100644 --- a/pimd/pim_igmp.c +++ b/pimd/pim_igmp.c @@ -473,15 +473,33 @@ static int igmp_v1_recv_report(struct igmp_sock *igmp, struct in_addr from, return 0; } -bool pim_igmp_verify_header(struct ip *ip_hdr, size_t len, int igmp_msg_len, - int msg_type) +bool pim_igmp_verify_header(struct ip *ip_hdr, size_t len, size_t *hlen) { + char *igmp_msg; + int igmp_msg_len; + int msg_type; + size_t ip_hlen; /* ip header length in bytes */ + if (len < sizeof(*ip_hdr)) { zlog_warn("IGMP packet size=%zu shorter than minimum=%zu", len, sizeof(*ip_hdr)); return false; } + ip_hlen = ip_hdr->ip_hl << 2; /* ip_hl gives length in 4-byte words */ + *hlen = ip_hlen; + + if (ip_hlen > len) { + zlog_warn( + "IGMP packet header claims size %zu, but we only have %zu bytes", + ip_hlen, len); + return false; + } + + igmp_msg = (char *)ip_hdr + ip_hlen; + igmp_msg_len = len - ip_hlen; + msg_type = *igmp_msg; + 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); @@ -514,7 +532,7 @@ bool pim_igmp_verify_header(struct ip *ip_hdr, size_t len, int igmp_msg_len, int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len) { - struct ip *ip_hdr; + struct ip *ip_hdr = (struct ip *)buf; size_t ip_hlen; /* ip header length in bytes */ char *igmp_msg; int igmp_msg_len; @@ -522,16 +540,8 @@ int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t len) char from_str[INET_ADDRSTRLEN]; char to_str[INET_ADDRSTRLEN]; - ip_hdr = (struct ip *)buf; - - ip_hlen = ip_hdr->ip_hl << 2; /* ip_hl gives length in 4-byte words */ - - if (ip_hlen > len) { - zlog_warn( - "IGMP packet header claims size %zu, but we only have %zu bytes", - ip_hlen, len); + if (!pim_igmp_verify_header(ip_hdr, len, &ip_hlen)) return -1; - } igmp_msg = buf + ip_hlen; igmp_msg_len = len - ip_hlen; @@ -547,14 +557,6 @@ int pim_igmp_packet(struct igmp_sock *igmp, char *buf, size_t 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) { case PIM_IGMP_MEMBERSHIP_QUERY: { int max_resp_code = igmp_msg[1]; diff --git a/pimd/pim_igmp.h b/pimd/pim_igmp.h index 01bf02da9f..abb8af836b 100644 --- a/pimd/pim_igmp.h +++ b/pimd/pim_igmp.h @@ -116,8 +116,7 @@ void igmp_sock_delete(struct igmp_sock *igmp); void igmp_sock_free(struct igmp_sock *igmp); void igmp_sock_delete_all(struct interface *ifp); 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); +bool pim_igmp_verify_header(struct ip *ip_hdr, size_t len, size_t *ip_hlen); void pim_igmp_general_query_on(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);