patch-2.4.4 linux/net/ipv4/udp.c
Next file: linux/net/ipv6/addrconf.c
Previous file: linux/net/ipv4/tcp_timer.c
Back to the patch index
Back to the overall index
- Lines: 201
- Date:
Thu Apr 12 12:11:39 2001
- Orig file:
v2.4.3/linux/net/ipv4/udp.c
- Orig date:
Fri Feb 9 11:34:13 2001
diff -u --recursive --new-file v2.4.3/linux/net/ipv4/udp.c linux/net/ipv4/udp.c
@@ -5,7 +5,7 @@
*
* The User Datagram Protocol (UDP).
*
- * Version: $Id: udp.c,v 1.91 2000/11/28 13:38:38 davem Exp $
+ * Version: $Id: udp.c,v 1.98 2001/03/06 21:15:10 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -291,22 +291,16 @@
* to find the appropriate port.
*/
-void udp_err(struct sk_buff *skb, unsigned char *dp, int len)
+void udp_err(struct sk_buff *skb, u32 info)
{
- struct iphdr *iph = (struct iphdr*)dp;
- struct udphdr *uh = (struct udphdr*)(dp+(iph->ihl<<2));
+ struct iphdr *iph = (struct iphdr*)skb->data;
+ struct udphdr *uh = (struct udphdr*)(skb->data+(iph->ihl<<2));
int type = skb->h.icmph->type;
int code = skb->h.icmph->code;
struct sock *sk;
int harderr;
- u32 info;
int err;
- if (len < (iph->ihl<<2)+sizeof(struct udphdr)) {
- ICMP_INC_STATS_BH(IcmpInErrors);
- return;
- }
-
sk = udp_v4_lookup(iph->daddr, uh->dest, iph->saddr, uh->source, skb->dev->ifindex);
if (sk == NULL) {
ICMP_INC_STATS_BH(IcmpInErrors);
@@ -314,7 +308,6 @@
}
err = 0;
- info = 0;
harderr = 0;
switch (type) {
@@ -326,14 +319,12 @@
goto out;
case ICMP_PARAMETERPROB:
err = EPROTO;
- info = ntohl(skb->h.icmph->un.gateway)>>24;
harderr = 1;
break;
case ICMP_DEST_UNREACH:
if (code == ICMP_FRAG_NEEDED) { /* Path MTU discovery */
if (sk->protinfo.af_inet.pmtudisc != IP_PMTUDISC_DONT) {
err = EMSGSIZE;
- info = ntohs(skb->h.icmph->un.frag.mtu);
harderr = 1;
break;
}
@@ -379,10 +370,7 @@
};
/*
- * Copy and checksum a UDP packet from user space into a buffer. We still have
- * to do the planning to get ip_build_xmit to spot direct transfer to network
- * card and provide an additional callback mode for direct user->board I/O
- * transfers. That one will be fun.
+ * Copy and checksum a UDP packet from user space into a buffer.
*/
static int udp_getfrag(const void *p, char * to, unsigned int offset, unsigned int fraglen)
@@ -409,10 +397,7 @@
}
/*
- * Unchecksummed UDP is sufficiently critical to stuff like ATM video conferencing
- * that we use two routines for this for speed. Probably we ought to have a
- * CONFIG_FAST_NET set for >10Mb/second boards to activate this sort of coding.
- * Timing needed to verify if this is a valid decision.
+ * Copy a UDP packet from user space into a buffer without checksumming.
*/
static int udp_getfrag_nosum(const void *p, char * to, unsigned int offset, unsigned int fraglen)
@@ -625,7 +610,7 @@
static __inline__ int __udp_checksum_complete(struct sk_buff *skb)
{
- return (unsigned short)csum_fold(csum_partial(skb->h.raw, skb->len, skb->csum));
+ return (unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum));
}
static __inline__ int udp_checksum_complete(struct sk_buff *skb)
@@ -655,11 +640,6 @@
if (flags & MSG_ERRQUEUE)
return ip_recv_error(sk, msg, len);
- /*
- * From here the generic datagram does a lot of the work. Come
- * the finished NET3, it will do _ALL_ the work!
- */
-
skb = skb_recv_datagram(sk, flags, noblock, &err);
if (!skb)
goto out;
@@ -679,9 +659,9 @@
err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov,
copied);
} else {
- err = copy_and_csum_toiovec(msg->msg_iov, skb, sizeof(struct udphdr));
+ err = skb_copy_and_csum_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov);
- if (err)
+ if (err == -EINVAL)
goto csum_copy_err;
}
@@ -758,6 +738,7 @@
sk->daddr = rt->rt_dst;
sk->dport = usin->sin_port;
sk->state = TCP_ESTABLISHED;
+ sk->protinfo.af_inet.id = jiffies;
sk_dst_set(sk, &rt->u.dst);
return(0);
@@ -872,10 +853,13 @@
if (uh->check == 0) {
skb->ip_summed = CHECKSUM_UNNECESSARY;
} else if (skb->ip_summed == CHECKSUM_HW) {
- if (udp_check(uh, ulen, saddr, daddr, skb->csum))
- return -1;
skb->ip_summed = CHECKSUM_UNNECESSARY;
- } else if (skb->ip_summed != CHECKSUM_UNNECESSARY)
+ if (!udp_check(uh, ulen, saddr, daddr, skb->csum))
+ return 0;
+ NETDEBUG(printk(KERN_DEBUG "udp v4 hw csum failure.\n"));
+ skb->ip_summed = CHECKSUM_NONE;
+ }
+ if (skb->ip_summed != CHECKSUM_UNNECESSARY)
skb->csum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0);
/* Probably, we should checksum udp header (it should be in cache
* in any case) and data in tiny packets (< rx copybreak).
@@ -887,7 +871,7 @@
* All we need to do is get the socket, and then do a checksum.
*/
-int udp_rcv(struct sk_buff *skb, unsigned short len)
+int udp_rcv(struct sk_buff *skb)
{
struct sock *sk;
struct udphdr *uh;
@@ -895,29 +879,22 @@
struct rtable *rt = (struct rtable*)skb->dst;
u32 saddr = skb->nh.iph->saddr;
u32 daddr = skb->nh.iph->daddr;
-
- /*
- * Get the header.
- */
-
- uh = skb->h.uh;
- __skb_pull(skb, skb->h.raw - skb->data);
+ int len = skb->len;
IP_INC_STATS_BH(IpInDelivers);
/*
* Validate the packet and the UDP length.
*/
-
- ulen = ntohs(uh->len);
+ ulen = ntohs(skb->h.uh->len);
- if (ulen > len || ulen < sizeof(*uh)) {
- NETDEBUG(printk(KERN_DEBUG "UDP: short packet: %d/%d\n", ulen, len));
- UDP_INC_STATS_BH(UdpInErrors);
- kfree_skb(skb);
- return(0);
- }
- skb_trim(skb, ulen);
+ if (ulen > len || ulen < sizeof(*uh))
+ goto short_packet;
+
+ if (pskb_trim(skb, ulen))
+ goto short_packet;
+
+ uh = skb->h.uh;
if (udp_checksum_init(skb, uh, ulen, saddr, daddr) < 0)
goto csum_error;
@@ -944,6 +921,12 @@
* Hmm. We got an UDP packet to a port to which we
* don't wanna listen. Ignore it.
*/
+ kfree_skb(skb);
+ return(0);
+
+short_packet:
+ NETDEBUG(printk(KERN_DEBUG "UDP: short packet: %d/%d\n", ulen, len));
+ UDP_INC_STATS_BH(UdpInErrors);
kfree_skb(skb);
return(0);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)