forked from Minki/linux
icmp: prepare rfc 4884 for ipv6
The RFC 4884 spec is largely the same between IPv4 and IPv6. Factor out the IPv4 specific parts in preparation for IPv6 support: - icmp types supported - icmp header size, and thus offset to original datagram start - datagram length field offset in icmp(6)hdr. - datagram length field word size: 4B for IPv4, 8B for IPv6. Signed-off-by: Willem de Bruijn <willemb@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
c4e9e09f55
commit
178c49d9f9
@ -37,6 +37,7 @@ static inline bool icmp_is_err(int type)
|
||||
}
|
||||
|
||||
void ip_icmp_error_rfc4884(const struct sk_buff *skb,
|
||||
struct sock_ee_data_rfc4884 *out);
|
||||
struct sock_ee_data_rfc4884 *out,
|
||||
int thlen, int off);
|
||||
|
||||
#endif /* _LINUX_ICMP_H */
|
||||
|
@ -1151,24 +1151,15 @@ static bool ip_icmp_error_rfc4884_validate(const struct sk_buff *skb, int off)
|
||||
}
|
||||
|
||||
void ip_icmp_error_rfc4884(const struct sk_buff *skb,
|
||||
struct sock_ee_data_rfc4884 *out)
|
||||
struct sock_ee_data_rfc4884 *out,
|
||||
int thlen, int off)
|
||||
{
|
||||
int hlen, off;
|
||||
|
||||
switch (icmp_hdr(skb)->type) {
|
||||
case ICMP_DEST_UNREACH:
|
||||
case ICMP_TIME_EXCEEDED:
|
||||
case ICMP_PARAMETERPROB:
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
int hlen;
|
||||
|
||||
/* original datagram headers: end of icmph to payload (skb->data) */
|
||||
hlen = -skb_transport_offset(skb) - sizeof(struct icmphdr);
|
||||
hlen = -skb_transport_offset(skb) - thlen;
|
||||
|
||||
/* per rfc 4884: minimal datagram length of 128 bytes */
|
||||
off = icmp_hdr(skb)->un.reserved[1] * sizeof(u32);
|
||||
if (off < 128 || off < hlen)
|
||||
return;
|
||||
|
||||
|
@ -390,6 +390,18 @@ int ip_ra_control(struct sock *sk, unsigned char on,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ipv4_icmp_error_rfc4884(const struct sk_buff *skb,
|
||||
struct sock_ee_data_rfc4884 *out)
|
||||
{
|
||||
switch (icmp_hdr(skb)->type) {
|
||||
case ICMP_DEST_UNREACH:
|
||||
case ICMP_TIME_EXCEEDED:
|
||||
case ICMP_PARAMETERPROB:
|
||||
ip_icmp_error_rfc4884(skb, out, sizeof(struct icmphdr),
|
||||
icmp_hdr(skb)->un.reserved[1] * 4);
|
||||
}
|
||||
}
|
||||
|
||||
void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err,
|
||||
__be16 port, u32 info, u8 *payload)
|
||||
{
|
||||
@ -413,7 +425,7 @@ void ip_icmp_error(struct sock *sk, struct sk_buff *skb, int err,
|
||||
|
||||
if (skb_pull(skb, payload - skb->data)) {
|
||||
if (inet_sk(sk)->recverr_rfc4884)
|
||||
ip_icmp_error_rfc4884(skb, &serr->ee.ee_rfc4884);
|
||||
ipv4_icmp_error_rfc4884(skb, &serr->ee.ee_rfc4884);
|
||||
|
||||
skb_reset_transport_header(skb);
|
||||
if (sock_queue_err_skb(sk, skb) == 0)
|
||||
|
Loading…
Reference in New Issue
Block a user