patch-2.3.41 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: 309
- Date:
Sat Jan 22 11:54:57 2000
- Orig file:
v2.3.40/linux/net/ipv4/udp.c
- Orig date:
Tue Jan 11 22:31:46 2000
diff -u --recursive --new-file v2.3.40/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.77 2000/01/09 02:19:44 davem Exp $
+ * Version: $Id: udp.c,v 1.79 2000/01/18 08:24:20 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -369,30 +369,15 @@
}
/*
- * Various people wanted BSD UDP semantics. Well they've come
- * back out because they slow down response to stuff like dead
- * or unreachable name servers and they screw term users something
- * chronic. Oh and it violates RFC1122. So basically fix your
- * client code people.
- */
-
- /*
* RFC1122: OK. Passes ICMP errors back to application, as per
- * 4.1.3.3. After the comment above, that should be no surprise.
- */
-
- if (!harderr && !sk->protinfo.af_inet.recverr)
- goto out;
-
- /*
- * 4.x BSD compatibility item. Break RFC1122 to
- * get BSD socket semantics.
+ * 4.1.3.3.
*/
- if(sk->bsdism && sk->state!=TCP_ESTABLISHED && !sk->protinfo.af_inet.recverr)
- goto out;
-
- if (sk->protinfo.af_inet.recverr)
+ if (!sk->protinfo.af_inet.recverr) {
+ if (!harderr || sk->state != TCP_ESTABLISHED)
+ goto out;
+ } else {
ip_icmp_error(sk, skb, err, uh->dest, info, (u8*)(uh+1));
+ }
sk->err = err;
sk->error_report(sk);
out:
@@ -629,15 +614,13 @@
{
switch(cmd)
{
- case TIOCOUTQ:
+ case SIOCOUTQ:
{
- unsigned long amount;
-
- amount = sock_wspace(sk);
+ int amount = atomic_read(&sk->wmem_alloc);
return put_user(amount, (int *)arg);
}
- case TIOCINQ:
+ case SIOCINQ:
{
struct sk_buff *skb;
unsigned long amount;
@@ -663,6 +646,17 @@
return(0);
}
+static __inline__ int __udp_checksum_complete(struct sk_buff *skb)
+{
+ return (unsigned short)csum_fold(csum_partial(skb->h.raw, skb->len, skb->csum));
+}
+
+static __inline__ int udp_checksum_complete(struct sk_buff *skb)
+{
+ return skb->ip_summed != CHECKSUM_UNNECESSARY &&
+ __udp_checksum_complete(skb);
+}
+
/*
* This should be easy, if there is something there we
* return it, otherwise we block.
@@ -699,31 +693,21 @@
msg->msg_flags |= MSG_TRUNC;
}
-#ifndef CONFIG_UDP_DELAY_CSUM
- err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov,
- copied);
-#else
if (skb->ip_summed==CHECKSUM_UNNECESSARY) {
err = skb_copy_datagram_iovec(skb, sizeof(struct udphdr), msg->msg_iov,
copied);
- } else if (copied > msg->msg_iov[0].iov_len || (msg->msg_flags&MSG_TRUNC)) {
- if ((unsigned short)csum_fold(csum_partial(skb->h.raw, skb->len, skb->csum)))
+ } 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 {
- unsigned int csum;
+ err = copy_and_csum_toiovec(msg->msg_iov, skb, sizeof(struct udphdr));
- err = 0;
- csum = csum_partial(skb->h.raw, sizeof(struct udphdr), skb->csum);
- csum = csum_and_copy_to_user((char*)&skb->h.uh[1], msg->msg_iov[0].iov_base,
- copied, csum, &err);
if (err)
- goto out_free;
- if ((unsigned short)csum_fold(csum))
goto csum_copy_err;
}
-#endif
+
if (err)
goto out_free;
sk->stamp=skb->stamp;
@@ -744,7 +728,6 @@
out:
return err;
-#ifdef CONFIG_UDP_DELAY_CSUM
csum_copy_err:
UDP_INC_STATS_BH(UdpInErrors);
@@ -768,7 +751,6 @@
* as some normal condition.
*/
return (flags&MSG_DONTWAIT) ? -EAGAIN : -EHOSTUNREACH;
-#endif
}
int udp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
@@ -831,9 +813,9 @@
* Charge it to the socket, dropping if the queue is full.
*/
-#if defined(CONFIG_FILTER) && defined(CONFIG_UDP_DELAY_CSUM)
+#if defined(CONFIG_FILTER)
if (sk->filter && skb->ip_summed != CHECKSUM_UNNECESSARY) {
- if ((unsigned short)csum_fold(csum_partial(skb->h.raw, skb->len, skb->csum))) {
+ if (__udp_checksum_complete(skb)) {
UDP_INC_STATS_BH(UdpInErrors);
IP_INC_STATS_BH(IpInDiscards);
ip_statistics[smp_processor_id()*2].IpInDelivers--;
@@ -855,12 +837,6 @@
return 0;
}
-
-static inline void udp_deliver(struct sock *sk, struct sk_buff *skb)
-{
- udp_queue_rcv_skb(sk, skb);
-}
-
/*
* Multicasts and broadcasts go to each listener.
*
@@ -889,7 +865,7 @@
skb1 = skb_clone(skb, GFP_ATOMIC);
if(skb1)
- udp_deliver(sk, skb1);
+ udp_queue_rcv_skb(sk, skb1);
sk = sknext;
} while(sknext);
} else
@@ -898,30 +874,25 @@
return 0;
}
-static int udp_checksum_verify(struct sk_buff *skb, struct udphdr *uh,
- unsigned short ulen, u32 saddr, u32 daddr,
- int full_csum_deferred)
-{
- if (!full_csum_deferred) {
- if (uh->check) {
- if (skb->ip_summed == CHECKSUM_HW &&
- udp_check(uh, ulen, saddr, daddr, skb->csum))
- return -1;
- if (skb->ip_summed == CHECKSUM_NONE &&
- udp_check(uh, ulen, saddr, daddr,
- csum_partial((char *)uh, ulen, 0)))
- return -1;
- }
- } else {
- 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)
- skb->csum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0);
- }
+/* Initialize UDP checksum. If exited with zero value (success),
+ * CHECKSUM_UNNECESSARY means, that no more checks are required.
+ * Otherwise, csum completion requires chacksumming packet body,
+ * including udp header and folding it to skb->csum.
+ */
+static int udp_checksum_init(struct sk_buff *skb, struct udphdr *uh,
+ unsigned short ulen, u32 saddr, u32 daddr)
+{
+ 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)
+ 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).
+ */
return 0;
}
@@ -961,50 +932,33 @@
}
skb_trim(skb, ulen);
- if(rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST)) {
- int defer;
+ if (udp_checksum_init(skb, uh, ulen, saddr, daddr) < 0)
+ goto csum_error;
-#ifdef CONFIG_UDP_DELAY_CSUM
- defer = 1;
-#else
- defer = 0;
-#endif
- if (udp_checksum_verify(skb, uh, ulen, saddr, daddr, defer))
- goto csum_error;
+ if(rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))
return udp_v4_mcast_deliver(skb, uh, saddr, daddr);
- }
sk = udp_v4_lookup(saddr, uh->source, daddr, uh->dest, skb->dev->ifindex);
-
- if (sk == NULL) {
- /* No socket. Drop packet silently, if checksum is wrong */
- if (udp_checksum_verify(skb, uh, ulen, saddr, daddr, 0))
- goto csum_error;
-
- UDP_INC_STATS_BH(UdpNoPorts);
- icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
-
- /*
- * Hmm. We got an UDP packet to a port to which we
- * don't wanna listen. Ignore it.
- */
- kfree_skb(skb);
- return(0);
- }
- if (udp_checksum_verify(skb, uh, ulen, saddr, daddr,
-#ifdef CONFIG_UDP_DELAY_CSUM
- 1
-#else
- (sk->no_check & UDP_CSUM_NORCV) != 0
-#endif
- )) {
+
+ if (sk != NULL) {
+ udp_queue_rcv_skb(sk, skb);
sock_put(sk);
- goto csum_error;
+ return 0;
}
- udp_deliver(sk, skb);
- __sock_put(sk);
- return 0;
+ /* No socket. Drop packet silently, if checksum is wrong */
+ if (udp_checksum_complete(skb))
+ goto csum_error;
+
+ UDP_INC_STATS_BH(UdpNoPorts);
+ icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0);
+
+ /*
+ * Hmm. We got an UDP packet to a port to which we
+ * don't wanna listen. Ignore it.
+ */
+ kfree_skb(skb);
+ return(0);
csum_error:
/*
@@ -1090,10 +1044,6 @@
udp_connect, /* connect */
udp_disconnect, /* disconnect */
NULL, /* accept */
- NULL, /* retransmit */
- NULL, /* write_wakeup */
- NULL, /* read_wakeup */
- datagram_poll, /* poll */
udp_ioctl, /* ioctl */
NULL, /* init */
NULL, /* destroy */
@@ -1107,7 +1057,5 @@
udp_v4_hash, /* hash */
udp_v4_unhash, /* unhash */
udp_v4_get_port, /* good_socknum */
- 128, /* max_header */
- 0, /* retransmits */
"UDP", /* name */
};
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)