patch-2.1.73 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: 251
- Date:
Wed Dec 10 09:45:16 1997
- Orig file:
v2.1.72/linux/net/ipv4/udp.c
- Orig date:
Mon Dec 1 12:04:17 1997
diff -u --recursive --new-file v2.1.72/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.44 1997/10/15 19:56:35 freitag Exp $
+ * Version: $Id: udp.c,v 1.45 1997/12/04 03:55:17 freitag Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -53,6 +53,8 @@
* Last socket cache retained as it
* does have a high hit rate.
* Olaf Kirch : Don't linearise iovec on sendmsg.
+ * Andi Kleen : Some cleanups, cache destination entry
+ * for connect.
*
*
* This program is free software; you can redistribute it and/or
@@ -69,7 +71,7 @@
MUST pass IP options from IP -> application (OK)
MUST allow application to specify IP options (OK)
4.1.3.3 (ICMP Messages)
- MUST pass ICMP error messages to application (OK)
+ MUST pass ICMP error messages to application (OK -- except when SO_BSDCOMPAT is set)
4.1.3.4 (UDP Checksums)
MUST provide facility for checksumming (OK)
MAY allow application to control checksumming (OK)
@@ -78,12 +80,10 @@
4.1.3.5 (UDP Multihoming)
MUST allow application to specify source address (OK)
SHOULD be able to communicate the chosen src addr up to application
- when application doesn't choose (NOT YET - doesn't seem to be in the BSD API)
- [Does opening a SOCK_PACKET and snooping your output count 8)]
+ when application doesn't choose (DOES - use recvmsg cmsgs)
4.1.3.6 (Invalid Addresses)
MUST discard invalid source addresses (OK -- done in the new routing code)
- MUST only send datagrams with one of our addresses (NOT YET - ought to be OK )
- 950728 -- MS
+ MUST only send datagrams with one of our addresses (OK)
*/
#include <asm/system.h>
@@ -459,8 +459,6 @@
return s;
}
-#define min(a,b) ((a)<(b)?(a):(b))
-
/*
* This routine is called by the ICMP module when it gets some
* sort of error condition. If err < 0 then the socket should
@@ -497,33 +495,27 @@
kfree_skb(skb2, FREE_READ);
}
- if (type == ICMP_SOURCE_QUENCH) {
-#if 0 /* FIXME: If you check the rest of the code, this is a NOP!
- * Someone figure out what we were trying to be doing
- * here. Besides, cong_window is a TCP thing and thus
- * I moved it out of normal sock and into tcp_opt.
- */
- /* Slow down! */
- if (sk->cong_window > 1)
- sk->cong_window = sk->cong_window/2;
-#endif
+ switch (type) {
+ case ICMP_SOURCE_QUENCH:
return;
- }
-
- if (type == ICMP_PARAMETERPROB)
- {
+ case ICMP_PARAMETERPROB:
sk->err = EPROTO;
sk->error_report(sk);
return;
- }
-
- if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED)
- {
- if (sk->ip_pmtudisc != IP_PMTUDISC_DONT) {
- sk->err = EMSGSIZE;
- sk->error_report(sk);
+ case ICMP_DEST_UNREACH:
+ if (code == ICMP_FRAG_NEEDED) { /* Path MTU discovery */
+ if (sk->ip_pmtudisc != IP_PMTUDISC_DONT) {
+ /*
+ * There should be really a way to pass the
+ * discovered MTU value back to the user (the
+ * ICMP layer did all the work for us)
+ */
+ sk->err = EMSGSIZE;
+ sk->error_report(sk);
+ }
+ return;
}
- return;
+ break;
}
/*
@@ -622,8 +614,8 @@
int ulen = len + sizeof(struct udphdr);
struct ipcm_cookie ipc;
struct udpfakehdr ufh;
- struct rtable *rt;
- int free = 0;
+ struct rtable *rt = NULL;
+ int free = 0, localroute = 0;
u32 daddr;
u8 tos;
int err;
@@ -635,12 +627,13 @@
* Check the flags.
*/
- if (msg->msg_flags&MSG_OOB) /* Mirror BSD error message compatibility */
+ if (msg->msg_flags&MSG_OOB) /* Mirror BSD error message compatibility */
return -EOPNOTSUPP;
if (msg->msg_flags&~(MSG_DONTROUTE|MSG_DONTWAIT))
return -EINVAL;
+
/*
* Get and verify the address.
*/
@@ -660,11 +653,13 @@
ufh.uh.dest = usin->sin_port;
if (ufh.uh.dest == 0)
return -EINVAL;
+ /* XXX: is a one-behind cache for the dst_entry worth it? */
} else {
if (sk->state != TCP_ESTABLISHED)
return -EINVAL;
ufh.daddr = sk->daddr;
ufh.uh.dest = sk->dummy_th.dest;
+ rt = (struct rtable *)sk->dst_cache;
}
ipc.addr = sk->saddr;
@@ -688,9 +683,13 @@
return -EINVAL;
daddr = ipc.opt->faddr;
}
- tos = RT_TOS(sk->ip_tos) | (sk->localroute || (msg->msg_flags&MSG_DONTROUTE) ||
- (ipc.opt && ipc.opt->is_strictroute));
-
+ tos = RT_TOS(sk->ip_tos);
+ if (sk->localroute || (msg->msg_flags&MSG_DONTROUTE) ||
+ (ipc.opt && ipc.opt->is_strictroute)) {
+ tos |= 1;
+ rt = NULL; /* sorry */
+ }
+
if (MULTICAST(daddr)) {
if (!ipc.oif)
ipc.oif = sk->ip_mc_index;
@@ -698,17 +697,15 @@
ufh.saddr = sk->ip_mc_addr;
}
- err = ip_route_output(&rt, daddr, ufh.saddr, tos, ipc.oif);
-
- if (err) {
- if (free) kfree(ipc.opt);
- return err;
- }
+ if (rt == NULL) {
+ err = ip_route_output(&rt, daddr, ufh.saddr, tos, ipc.oif);
+ if (err)
+ goto out;
+ localroute = 1;
- if (rt->rt_flags&RTCF_BROADCAST && !sk->broadcast) {
- if (free) kfree(ipc.opt);
- ip_rt_put(rt);
- return -EACCES;
+ err = -EACCES;
+ if (rt->rt_flags&RTCF_BROADCAST && !sk->broadcast)
+ goto out;
}
ufh.saddr = rt->rt_src;
@@ -727,15 +724,13 @@
/* violation above. -- MS */
lock_sock(sk);
- if (sk->no_check)
- err = ip_build_xmit(sk, udp_getfrag_nosum, &ufh, ulen,
- &ipc, rt, msg->msg_flags);
- else
- err = ip_build_xmit(sk, udp_getfrag, &ufh, ulen,
- &ipc, rt, msg->msg_flags);
- ip_rt_put(rt);
+ err = ip_build_xmit(sk,sk->no_check ? udp_getfrag_nosum : udp_getfrag,
+ &ufh, ulen, &ipc, rt, msg->msg_flags);
release_sock(sk);
+out:
+ if (localroute)
+ ip_rt_put(rt);
if (free)
kfree(ipc.opt);
if (!err) {
@@ -776,7 +771,7 @@
* of this packet since that is all
* that will be read.
*/
- amount = skb->len-sizeof(struct udphdr);
+ amount = skb->tail - skb->h.raw;
}
return put_user(amount, (int *)arg);
}
@@ -905,6 +900,9 @@
if (usin->sin_family && usin->sin_family != AF_INET)
return(-EAFNOSUPPORT);
+ dst_release(sk->dst_cache);
+ sk->dst_cache = NULL;
+
err = ip_route_connect(&rt, usin->sin_addr.s_addr, sk->saddr,
sk->ip_tos|sk->localroute, sk->bound_dev_if);
if (err)
@@ -920,9 +918,11 @@
sk->daddr = rt->rt_dst;
sk->dummy_th.dest = usin->sin_port;
sk->state = TCP_ESTABLISHED;
+
if(uh_cache_sk == sk)
uh_cache_sk = NULL;
- ip_rt_put(rt);
+
+ sk->dst_cache = &rt->u.dst;
return(0);
}
@@ -1073,13 +1073,6 @@
kfree_skb(skb, FREE_WRITE);
return(0);
}
-
- /* RFC1122 warning: According to 4.1.3.6, we MUST discard any */
- /* datagram which has an invalid source address, either here or */
- /* in IP. */
- /* Right now, IP isn't doing it, and neither is UDP. It's on the */
- /* FIXME list for IP, though, so I wouldn't worry about it. */
- /* (That's the Right Place to do it, IMHO.) -- MS */
if (uh->check &&
(((skb->ip_summed==CHECKSUM_HW)&&udp_check(uh,len,saddr,daddr,skb->csum)) ||
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov