patch-2.1.30 linux/net/ipv6/udp.c
Next file: linux/net/ipx/af_ipx.c
Previous file: linux/net/ipv6/tcp_ipv6.c
Back to the patch index
Back to the overall index
- Lines: 441
- Date:
Thu Mar 20 18:17:15 1997
- Orig file:
v2.1.29/linux/net/ipv6/udp.c
- Orig date:
Mon Mar 17 14:54:36 1997
diff -u --recursive --new-file v2.1.29/linux/net/ipv6/udp.c linux/net/ipv6/udp.c
@@ -7,7 +7,7 @@
*
* Based on linux/ipv4/udp.c
*
- * $Id: udp.c,v 1.9 1997/03/04 10:41:59 davem Exp $
+ * $Id: udp.c,v 1.12 1997/03/18 18:24:59 davem Exp $
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -34,7 +34,7 @@
#include <net/ndisc.h>
#include <net/protocol.h>
#include <net/transp_v6.h>
-#include <net/ipv6_route.h>
+#include <net/ip6_route.h>
#include <net/addrconf.h>
#include <net/ip.h>
#include <net/udp.h>
@@ -60,7 +60,7 @@
if(addr_type == IPV6_ADDR_ANY || (!sk2->rcv_saddr)) {
if((!sk2_reuse) ||
(!sk_reuse) ||
- (state != TCP_LISTEN)) {
+ (state == TCP_LISTEN)) {
retval = 1;
break;
}
@@ -184,9 +184,10 @@
{
struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr;
struct in6_addr *daddr;
- struct dest_entry *dest;
+ struct dst_entry *dst;
struct ipv6_pinfo *np;
struct inet6_ifaddr *ifa;
+ struct flowi fl;
int addr_type;
if (addr_len < sizeof(*usin))
@@ -198,8 +199,7 @@
addr_type = ipv6_addr_type(&usin->sin6_addr);
np = &sk->net_pinfo.af_inet6;
- if (addr_type == IPV6_ADDR_ANY)
- {
+ if (addr_type == IPV6_ADDR_ANY) {
/*
* connect to self
*/
@@ -208,8 +208,7 @@
daddr = &usin->sin6_addr;
- if (addr_type == IPV6_ADDR_MAPPED)
- {
+ if (addr_type == IPV6_ADDR_MAPPED) {
struct sockaddr_in sin;
int err;
@@ -219,22 +218,18 @@
err = udp_connect(sk, (struct sockaddr*) &sin, sizeof(sin));
if (err < 0)
- {
return err;
- }
ipv6_addr_copy(&np->daddr, daddr);
- if(ipv6_addr_any(&np->saddr))
- {
+ if(ipv6_addr_any(&np->saddr)) {
ipv6_addr_set(&np->saddr, 0, 0,
__constant_htonl(0x0000ffff),
sk->saddr);
}
- if(ipv6_addr_any(&np->rcv_saddr))
- {
+ if(ipv6_addr_any(&np->rcv_saddr)) {
ipv6_addr_set(&np->rcv_saddr, 0, 0,
__constant_htonl(0x0000ffff),
sk->rcv_saddr);
@@ -244,35 +239,41 @@
ipv6_addr_copy(&np->daddr, daddr);
+ sk->dummy_th.dest = usin->sin6_port;
+
/*
* Check for a route to destination an obtain the
* destination cache for it.
*/
- dest = ipv6_dst_route(daddr, NULL, sk->localroute ? RTI_GATEWAY : 0);
-
- np->dest = dest;
+ fl.proto = IPPROTO_UDP;
+ fl.nl_u.ip6_u.daddr = daddr;
+ fl.nl_u.ip6_u.saddr = NULL;
+ fl.dev = NULL;
+ fl.uli_u.ports.dport = sk->dummy_th.dest;
+ fl.uli_u.ports.sport = sk->dummy_th.source;
+
+ dst = ip6_route_output(sk, &fl);
+
+ if (dst->error) {
+ dst_release(dst);
+ return dst->error;
+ }
- if (dest == NULL)
- return -ENETUNREACH;
+ ip6_dst_store(sk, dst);
/* get the source adddress used in the apropriate device */
- ifa = ipv6_get_saddr((struct rt6_info *) dest, daddr);
+ ifa = ipv6_get_saddr(dst, daddr);
if(ipv6_addr_any(&np->saddr))
- {
ipv6_addr_copy(&np->saddr, &ifa->addr);
- }
- if(ipv6_addr_any(&np->rcv_saddr))
- {
+ if(ipv6_addr_any(&np->rcv_saddr)) {
ipv6_addr_copy(&np->rcv_saddr, &ifa->addr);
sk->rcv_saddr = 0xffffffff;
}
- sk->dummy_th.dest = usin->sin6_port;
-
sk->state = TCP_ESTABLISHED;
return(0);
@@ -285,10 +286,10 @@
lock_sock(sk);
sk->state = TCP_CLOSE;
- if (np->dest)
- {
- ipv6_dst_unlock(np->dest);
- }
+ if (np->dst)
+ dst_release(np->dst);
+
+ ipv6_sock_mc_close(sk);
release_sock(sk);
destroy_sock(sk);
@@ -306,7 +307,6 @@
int truesize;
struct sk_buff *skb;
int err;
-
/*
* Check any passed addresses
@@ -328,8 +328,7 @@
copied=truesize;
- if(copied>len)
- {
+ if(copied>len) {
copied=len;
msg->msg_flags|=MSG_TRUNC;
}
@@ -346,8 +345,7 @@
sk->stamp=skb->stamp;
/* Copy the address. */
- if (msg->msg_name)
- {
+ if (msg->msg_name) {
struct sockaddr_in6 *sin6;
sin6 = (struct sockaddr_in6 *) msg->msg_name;
@@ -355,13 +353,10 @@
sin6->sin6_family = AF_INET6;
sin6->sin6_port = skb->h.uh->source;
- if (skb->protocol == __constant_htons(ETH_P_IP))
- {
+ if (skb->protocol == __constant_htons(ETH_P_IP)) {
ipv6_addr_set(&sin6->sin6_addr, 0, 0,
__constant_htonl(0xffff), skb->nh.iph->saddr);
- }
- else
- {
+ } else {
memcpy(&sin6->sin6_addr, &skb->nh.ipv6h->saddr,
sizeof(struct in6_addr));
@@ -386,22 +381,20 @@
sk = udp_v6_lookup(saddr, uh->source, daddr, uh->dest);
- if (sk == NULL)
- {
+ if (sk == NULL) {
printk(KERN_DEBUG "icmp for unkown sock\n");
return;
}
- if (icmpv6_err_convert(type, code, &err))
- {
+ if (icmpv6_err_convert(type, code, &err)) {
if(sk->bsdism && sk->state!=TCP_ESTABLISHED)
return;
sk->err = err;
sk->error_report(sk);
- }
- else
+ } else {
sk->err_soft = err;
+ }
}
static inline int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb)
@@ -507,16 +500,14 @@
ulen = ntohs(uh->len);
- if (ulen > len || len < sizeof(*uh))
- {
+ if (ulen > len || len < sizeof(*uh)) {
printk(KERN_DEBUG "UDP: short packet: %d/%d\n", ulen, len);
udp_stats_in6.UdpInErrors++;
kfree_skb(skb, FREE_READ);
return(0);
}
- if (uh->check == 0)
- {
+ if (uh->check == 0) {
printk(KERN_DEBUG "IPv6: udp checksum is 0\n");
goto discard;
}
@@ -525,12 +516,11 @@
case CHECKSUM_NONE:
skb->csum = csum_partial((char*)uh, len, 0);
case CHECKSUM_HW:
- if (csum_ipv6_magic(saddr, daddr, len, IPPROTO_UDP, skb->csum))
- {
+ if (csum_ipv6_magic(saddr, daddr, len, IPPROTO_UDP, skb->csum)) {
printk(KERN_DEBUG "IPv6: udp checksum error\n");
goto discard;
}
- }
+ };
len = ulen;
@@ -551,12 +541,10 @@
sk = udp_v6_lookup(saddr, uh->source, daddr, uh->dest);
- if (sk == NULL)
- {
+ if (sk == NULL) {
udp_stats_in6.UdpNoPorts++;
- icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH,
- 0, dev);
+ icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0, dev);
kfree_skb(skb, FREE_READ);
return(0);
@@ -564,18 +552,14 @@
/* deliver */
- if (sk->users)
- {
+ if (sk->sock_readers)
__skb_queue_tail(&sk->back_log, skb);
- }
else
- {
udpv6_queue_rcv_skb(sk, skb);
- }
return(0);
- discard:
+discard:
udp_stats_in6.UdpInErrors++;
kfree_skb(skb, FREE_READ);
return(0);
@@ -608,12 +592,9 @@
dst = buff;
- if (offset)
- {
+ if (offset) {
offset -= sizeof(struct udphdr);
- }
- else
- {
+ } else {
dst += sizeof(struct udphdr);
final = 1;
clen -= sizeof(struct udphdr);
@@ -622,19 +603,15 @@
udh->wcheck = csum_partial_copy_fromiovecend(dst, udh->iov, offset,
clen, udh->wcheck);
- if (final)
- {
+ if (final) {
struct in6_addr *daddr;
udh->wcheck = csum_partial((char *)udh, sizeof(struct udphdr),
udh->wcheck);
- if (udh->daddr)
- {
+ if (udh->daddr) {
daddr = udh->daddr;
- }
- else
- {
+ } else {
/*
* use packet destination address
* this should improve cache locality
@@ -654,27 +631,26 @@
static int udpv6_sendmsg(struct sock *sk, struct msghdr *msg, int ulen)
{
-
struct ipv6_options opt_space;
struct udpv6fakehdr udh;
struct ipv6_pinfo *np = &sk->net_pinfo.af_inet6;
struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *) msg->msg_name;
struct ipv6_options *opt = NULL;
struct device *dev = NULL;
+ struct flowi fl;
int addr_len = msg->msg_namelen;
struct in6_addr *daddr;
struct in6_addr *saddr = NULL;
int len = ulen + sizeof(struct udphdr);
int addr_type;
- int hlimit = 0;
- int err;
+ int hlimit = -1;
+ int err;
if (msg->msg_flags & ~(MSG_DONTROUTE|MSG_DONTWAIT))
return(-EINVAL);
- if (sin6)
- {
+ if (sin6) {
if (addr_len < sizeof(*sin6))
return(-EINVAL);
@@ -687,14 +663,11 @@
udh.uh.dest = sin6->sin6_port;
daddr = &sin6->sin6_addr;
- if (np->dest && ipv6_addr_cmp(daddr, &np->daddr))
- {
- ipv6_dst_unlock(np->dest);
- np->dest = NULL;
+ if (np->dst && ipv6_addr_cmp(daddr, &np->daddr)) {
+ dst_release(np->dst);
+ np->dst = NULL;
}
- }
- else
- {
+ } else {
if (sk->state != TCP_ESTABLISHED)
return(-EINVAL);
@@ -704,8 +677,7 @@
addr_type = ipv6_addr_type(daddr);
- if (addr_type == IPV6_ADDR_MAPPED)
- {
+ if (addr_type == IPV6_ADDR_MAPPED) {
struct sockaddr_in sin;
sin.sin_family = AF_INET;
@@ -716,22 +688,18 @@
udh.daddr = NULL;
- if (msg->msg_controllen)
- {
+ if (msg->msg_controllen) {
opt = &opt_space;
memset(opt, 0, sizeof(struct ipv6_options));
err = datagram_send_ctl(msg, &dev, &saddr, opt, &hlimit);
- if (err < 0)
- {
+ if (err < 0) {
printk(KERN_DEBUG "invalid msg_control\n");
return err;
}
if (opt->srcrt)
- {
udh.daddr = daddr;
- }
}
udh.uh.source = sk->dummy_th.source;
@@ -740,11 +708,17 @@
udh.iov = msg->msg_iov;
udh.wcheck = 0;
udh.pl_len = len;
-
- err = ipv6_build_xmit(sk, udpv6_getfrag, &udh, daddr, len,
- saddr, dev, opt, IPPROTO_UDP, hlimit,
- msg->msg_flags&MSG_DONTWAIT);
-
+
+ fl.proto = IPPROTO_UDP;
+ fl.nl_u.ip6_u.daddr = daddr;
+ fl.nl_u.ip6_u.saddr = saddr;
+ fl.dev = dev;
+ fl.uli_u.ports.dport = udh.uh.dest;
+ fl.uli_u.ports.sport = udh.uh.source;
+
+ err = ip6_build_xmit(sk, udpv6_getfrag, &udh, &fl, len, opt, hlimit,
+ msg->msg_flags);
+
if (err < 0)
return err;
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov