Under IPv4, when I send a UDP packet with invalid checksum, kernel used
udp_rcv() to up packet to UDP layer, application used udp_recvmsg to
receive message. So if one UDP packet with invalid checksum is arrived
to host, UDP_MIB_INDATAGRAMS will be increased 1, UDP_MIB_INERRORS
should be increased 1.
int udp_rcv(struct sk_buff *skb) {
...
udp_queue_rcv_skb();
...
}
static int udp_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) {
...
if (sk->sk_filter && skb->ip_summed != CHECKSUM_UNNECESSARY) {
if (__udp_checksum_complete(skb)) {
UDP_INC_STATS_BH(UDP_MIB_INERRORS);
kfree_skb(skb);
return -1;
}
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
....
UDP_INC_STATS_BH(UDP_MIB_INDATAGRAMS);
...
}
static int udp_recvmsg(...) {
...
csum_copy_err:
UDP_INC_STATS_BH(UDP_MIB_INERRORS);
...
}
In my test, I send a to a IPv4 UDP packet with invalid checksum to echo-
udp, I can find the following message in file /var/log/messages:
xinetd[4468]: service echo-dgram, recvfrom: Resource temporarily
unavailable (errno = 11)
and UDP_MIB_INDATAGRAMS increased 1, UDP_MIB_INERRORS increased 0.
xinetd used other fucntion to receive message, not udp_recvmsg()?
The other question is why discard the packet with invalid checksum only
when sk->sk_filter is set?
By the way, under IPv6, packet with invalid checksum be discard in
udpv6_rcv(), so So if one UDP packet with invalid checksum is arrived to
IPv6 host, UDP_MIB_INDATAGRAMS will be increased 0, UDP_MIB_INERRORS
should be increased 1.
static int udpv6_rcv(struct sk_buff **pskb, unsigned int *nhoffp) {
...
udpv6_queue_rcv_skb();
...
}
static inline int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff
*skb) {
...
if (skb->ip_summed != CHECKSUM_UNNECESSARY) {
if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len,
skb->csum))) {
UDP6_INC_STATS_BH(UDP_MIB_INERRORS);
kfree_skb(skb);
return 0;
}
skb->ip_summed = CHECKSUM_UNNECESSARY;
}
...
UDP6_INC_STATS_BH(UDP_MIB_INDATAGRAMS);
...
}
One packet with invalid checksum arrived to IPv4 and IPv6 host, the
count of UDP_MIB_INDATAGRAMS and UDP_MIB_INERRORS get different
increase. There definition of the two count are some difference between
IPv4 and IPv6?
> > IPv4 UDP does not discard the datagram with invalid checksum. UDP can
> > validate UDP checksums correctly only when socket filtering
> instructions
> > is set. If socket filtering instructions is not set, datagram with
> > invalid checksum will be passed to the application.
>
> We check the checksum later, in parallel with the copy of
> the packet data into userspace.
>
> See udp_recvmsg(), where we do this:
>
> if (skb->ip_summed==CHECKSUM_UNNECESSARY) {
> err = skb_copy_datagram_iovec(skb, sizeof(struct
> udphdr), msg->msg_iov,
> copied);
> } else if (msg->msg_flags&MSG_TRUNC) {
> if (__udp_checksum_complete(skb))
> goto csum_copy_err;
> err = skb_copy_datagram_iovec(skb, sizeof(struct
> udphdr), msg->msg_iov,
> copied);
> } else {
> err = skb_copy_and_csum_datagram_iovec(skb, sizeof
> (struct udphdr), msg->msg_iov);
>
> if (err == -EINVAL)
> goto csum_copy_err;
> }
-
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at http://vger.kernel.org/majordomo-info.html