patch-2.1.124 linux/net/ipv4/udp.c
Next file: linux/net/ipv6/af_inet6.c
Previous file: linux/net/ipv4/tcp_output.c
Back to the patch index
Back to the overall index
- Lines: 170
- Date:
Sun Oct 4 10:19:40 1998
- Orig file:
v2.1.123/linux/net/ipv4/udp.c
- Orig date:
Thu Sep 17 17:53:40 1998
diff -u --recursive --new-file v2.1.123/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.62 1998/09/15 02:11:32 davem Exp $
+ * Version: $Id: udp.c,v 1.63 1998/10/03 09:38:16 davem Exp $
*
* Authors: Ross Biro, <bir7@leland.Stanford.Edu>
* Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
@@ -481,6 +481,9 @@
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_statistics.IcmpInErrors++;
@@ -493,36 +496,40 @@
return; /* No socket for error */
}
- if (sk->ip_recverr && !atomic_read(&sk->sock_readers)) {
- struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
- if (skb2 && sock_queue_err_skb(sk, skb2))
- kfree_skb(skb2);
- }
-
+ err = 0;
+ info = 0;
+ harderr = 0;
+
switch (type) {
+ default:
case ICMP_TIME_EXCEEDED:
+ err = EHOSTUNREACH;
+ break;
case ICMP_SOURCE_QUENCH:
return;
case ICMP_PARAMETERPROB:
- sk->err = EPROTO;
- sk->error_report(sk);
- return;
+ 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->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);
+ err = EMSGSIZE;
+ info = ntohs(skb->h.icmph->un.frag.mtu);
+ harderr = 1;
+ break;
}
return;
}
+ err = EHOSTUNREACH;
+ if (code <= NR_ICMP_UNREACH) {
+ harderr = icmp_err_convert[code].fatal;
+ err = icmp_err_convert[code].errno;
+ }
break;
}
-
+
/*
* Various people wanted BSD UDP semantics. Well they've come
* back out because they slow down response to stuff like dead
@@ -531,21 +538,25 @@
* 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. */
+ /*
+ * RFC1122: OK. Passes ICMP errors back to application, as per
+ * 4.1.3.3. After the comment above, that should be no surprise.
+ */
- if (code < NR_ICMP_UNREACH && icmp_err_convert[code].fatal)
- {
- /*
- * 4.x BSD compatibility item. Break RFC1122 to
- * get BSD socket semantics.
- */
- if(sk->bsdism && sk->state!=TCP_ESTABLISHED)
- return;
- sk->err = icmp_err_convert[code].errno;
- sk->error_report(sk);
- }
+ if (!harderr && !sk->ip_recverr)
+ return;
+
+ /*
+ * 4.x BSD compatibility item. Break RFC1122 to
+ * get BSD socket semantics.
+ */
+ if(sk->bsdism && sk->state!=TCP_ESTABLISHED)
+ return;
+
+ if (sk->ip_recverr)
+ ip_icmp_error(sk, skb, err, uh->dest, info, (u8*)(uh+1));
+ sk->err = err;
+ sk->error_report(sk);
}
@@ -854,24 +865,17 @@
/*
* Check any passed addresses
*/
-
if (addr_len)
*addr_len=sizeof(*sin);
- if (sk->ip_recverr && (skb = skb_dequeue(&sk->error_queue)) != NULL) {
- err = sock_error(sk);
- if (msg->msg_controllen != 0) {
- put_cmsg(msg, SOL_IP, IP_RECVERR, skb->len, skb->data);
- err = 0;
- }
- goto out_free;
- }
-
+ 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;
@@ -1026,7 +1030,7 @@
* Charge it to the socket, dropping if the queue is full.
*/
- if (__sock_queue_rcv_skb(sk,skb)<0) {
+ if (sock_queue_rcv_skb(sk,skb)<0) {
udp_statistics.UdpInErrors++;
ip_statistics.IpInDiscards++;
ip_statistics.IpInDelivers--;
@@ -1196,9 +1200,11 @@
* RFC1122: OK. Discards the bad packet silently (as far as
* the network is concerned, anyway) as per 4.1.3.4 (MUST).
*/
- NETDEBUG(printk(KERN_DEBUG "UDP: bad checksum. From %08lX:%d to %08lX:%d ulen %d\n",
- ntohl(saddr),ntohs(uh->source),
- ntohl(daddr),ntohs(uh->dest),
+ NETDEBUG(printk(KERN_DEBUG "UDP: bad checksum. From %d.%d.%d.%d:%d to %d.%d.%d.%d:%d ulen %d\n",
+ NIPQUAD(saddr),
+ ntohs(uh->source),
+ NIPQUAD(daddr),
+ ntohs(uh->dest),
ulen));
udp_statistics.UdpInErrors++;
kfree_skb(skb);
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov