Commit 65d17d59 authored by Linus Torvalds's avatar Linus Torvalds

Merge master.kernel.org:/home/davem/BK/net-2.6

into ppc970.osdl.org:/home/torvalds/v2.6/linux
parents b19738ae 4bddee2c
...@@ -20,27 +20,14 @@ extern int inet_dgram_connect(struct socket *sock, ...@@ -20,27 +20,14 @@ extern int inet_dgram_connect(struct socket *sock,
int addr_len, int flags); int addr_len, int flags);
extern int inet_accept(struct socket *sock, extern int inet_accept(struct socket *sock,
struct socket *newsock, int flags); struct socket *newsock, int flags);
extern int inet_recvmsg(struct kiocb *iocb,
struct socket *sock,
struct msghdr *ubuf,
size_t size, int flags);
extern int inet_sendmsg(struct kiocb *iocb, extern int inet_sendmsg(struct kiocb *iocb,
struct socket *sock, struct socket *sock,
struct msghdr *msg, struct msghdr *msg,
size_t size); size_t size);
extern int inet_shutdown(struct socket *sock, int how); extern int inet_shutdown(struct socket *sock, int how);
extern unsigned int inet_poll(struct file * file, struct socket *sock, struct poll_table_struct *wait); extern unsigned int inet_poll(struct file * file, struct socket *sock, struct poll_table_struct *wait);
extern int inet_setsockopt(struct socket *sock, int level,
int optname,
char __user *optval,
int optlen);
extern int inet_getsockopt(struct socket *sock, int level,
int optname,
char __user *optval,
int __user *optlen);
extern int inet_listen(struct socket *sock, int backlog); extern int inet_listen(struct socket *sock, int backlog);
extern void inet_sock_release(struct sock *sk);
extern void inet_sock_destruct(struct sock *sk); extern void inet_sock_destruct(struct sock *sk);
extern atomic_t inet_sock_nr; extern atomic_t inet_sock_nr;
......
...@@ -770,6 +770,19 @@ extern ssize_t sock_no_sendpage(struct socket *sock, ...@@ -770,6 +770,19 @@ extern ssize_t sock_no_sendpage(struct socket *sock,
int offset, size_t size, int offset, size_t size,
int flags); int flags);
/*
* Functions to fill in entries in struct proto_ops when a protocol
* uses the inet style.
*/
extern int sock_common_getsockopt(struct socket *sock, int level, int optname,
char __user *optval, int __user *optlen);
extern int sock_common_recvmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t size, int flags);
extern int sock_common_setsockopt(struct socket *sock, int level, int optname,
char __user *optval, int optlen);
extern void sk_common_release(struct sock *sk);
/* /*
* Default socket callbacks and setup code * Default socket callbacks and setup code
*/ */
......
...@@ -118,6 +118,7 @@ ...@@ -118,6 +118,7 @@
#include <net/protocol.h> #include <net/protocol.h>
#include <linux/skbuff.h> #include <linux/skbuff.h>
#include <net/sock.h> #include <net/sock.h>
#include <net/xfrm.h>
#include <linux/ipsec.h> #include <linux/ipsec.h>
#include <linux/filter.h> #include <linux/filter.h>
...@@ -1259,6 +1260,93 @@ void sock_disable_timestamp(struct sock *sk) ...@@ -1259,6 +1260,93 @@ void sock_disable_timestamp(struct sock *sk)
} }
EXPORT_SYMBOL(sock_disable_timestamp); EXPORT_SYMBOL(sock_disable_timestamp);
/*
* Get a socket option on an socket.
*
* FIX: POSIX 1003.1g is very ambiguous here. It states that
* asynchronous errors should be reported by getsockopt. We assume
* this means if you specify SO_ERROR (otherwise whats the point of it).
*/
int sock_common_getsockopt(struct socket *sock, int level, int optname,
char __user *optval, int __user *optlen)
{
struct sock *sk = sock->sk;
return sk->sk_prot->getsockopt(sk, level, optname, optval, optlen);
}
EXPORT_SYMBOL(sock_common_getsockopt);
int sock_common_recvmsg(struct kiocb *iocb, struct socket *sock,
struct msghdr *msg, size_t size, int flags)
{
struct sock *sk = sock->sk;
int addr_len = 0;
int err;
err = sk->sk_prot->recvmsg(iocb, sk, msg, size, flags & MSG_DONTWAIT,
flags & ~MSG_DONTWAIT, &addr_len);
if (err >= 0)
msg->msg_namelen = addr_len;
return err;
}
EXPORT_SYMBOL(sock_common_recvmsg);
/*
* Set socket options on an inet socket.
*/
int sock_common_setsockopt(struct socket *sock, int level, int optname,
char __user *optval, int optlen)
{
struct sock *sk = sock->sk;
return sk->sk_prot->setsockopt(sk, level, optname, optval, optlen);
}
EXPORT_SYMBOL(sock_common_setsockopt);
void sk_common_release(struct sock *sk)
{
if (sk->sk_prot->destroy)
sk->sk_prot->destroy(sk);
/*
* Observation: when sock_common_release is called, processes have
* no access to socket. But net still has.
* Step one, detach it from networking:
*
* A. Remove from hash tables.
*/
sk->sk_prot->unhash(sk);
/*
* In this point socket cannot receive new packets, but it is possible
* that some packets are in flight because some CPU runs receiver and
* did hash table lookup before we unhashed socket. They will achieve
* receive queue and will be purged by socket destructor.
*
* Also we still have packets pending on receive queue and probably,
* our own packets waiting in device queues. sock_destroy will drain
* receive queue, but transmitted packets will delay socket destruction
* until the last reference will be released.
*/
sock_orphan(sk);
xfrm_sk_free_policy(sk);
#ifdef INET_REFCNT_DEBUG
if (atomic_read(&sk->sk_refcnt) != 1)
printk(KERN_DEBUG "Destruction of the socket %p delayed, c=%d\n",
sk, atomic_read(&sk->sk_refcnt));
#endif
sock_put(sk);
}
EXPORT_SYMBOL(sk_common_release);
EXPORT_SYMBOL(__lock_sock); EXPORT_SYMBOL(__lock_sock);
EXPORT_SYMBOL(__release_sock); EXPORT_SYMBOL(__release_sock);
EXPORT_SYMBOL(sk_alloc); EXPORT_SYMBOL(sk_alloc);
......
...@@ -166,79 +166,12 @@ void inet_sock_destruct(struct sock *sk) ...@@ -166,79 +166,12 @@ void inet_sock_destruct(struct sock *sk)
#endif #endif
} }
void inet_sock_release(struct sock *sk)
{
if (sk->sk_prot->destroy)
sk->sk_prot->destroy(sk);
/* Observation: when inet_sock_release is called, processes have
* no access to socket. But net still has.
* Step one, detach it from networking:
*
* A. Remove from hash tables.
*/
sk->sk_prot->unhash(sk);
/* In this point socket cannot receive new packets,
* but it is possible that some packets are in flight
* because some CPU runs receiver and did hash table lookup
* before we unhashed socket. They will achieve receive queue
* and will be purged by socket destructor.
*
* Also we still have packets pending on receive
* queue and probably, our own packets waiting in device queues.
* sock_destroy will drain receive queue, but transmitted
* packets will delay socket destruction until the last reference
* will be released.
*/
sock_orphan(sk);
xfrm_sk_free_policy(sk);
#ifdef INET_REFCNT_DEBUG
if (atomic_read(&sk->sk_refcnt) != 1)
printk(KERN_DEBUG "Destruction inet %p delayed, c=%d\n",
sk, atomic_read(&sk->sk_refcnt));
#endif
sock_put(sk);
}
/* /*
* The routines beyond this point handle the behaviour of an AF_INET * The routines beyond this point handle the behaviour of an AF_INET
* socket object. Mostly it punts to the subprotocols of IP to do * socket object. Mostly it punts to the subprotocols of IP to do
* the work. * the work.
*/ */
/*
* Set socket options on an inet socket.
*/
int inet_setsockopt(struct socket *sock, int level, int optname,
char __user *optval, int optlen)
{
struct sock *sk = sock->sk;
return sk->sk_prot->setsockopt(sk, level, optname, optval, optlen);
}
/*
* Get a socket option on an AF_INET socket.
*
* FIX: POSIX 1003.1g is very ambiguous here. It states that
* asynchronous errors should be reported by getsockopt. We assume
* this means if you specify SO_ERROR (otherwise whats the point of it).
*/
int inet_getsockopt(struct socket *sock, int level, int optname,
char __user *optval, int __user *optlen)
{
struct sock *sk = sock->sk;
return sk->sk_prot->getsockopt(sk, level, optname, optval, optlen);
}
/* /*
* Automatically bind an unbound socket. * Automatically bind an unbound socket.
*/ */
...@@ -422,7 +355,7 @@ static int inet_create(struct socket *sock, int protocol) ...@@ -422,7 +355,7 @@ static int inet_create(struct socket *sock, int protocol)
if (sk->sk_prot->init) { if (sk->sk_prot->init) {
err = sk->sk_prot->init(sk); err = sk->sk_prot->init(sk);
if (err) if (err)
inet_sock_release(sk); sk_common_release(sk);
} }
out: out:
return err; return err;
...@@ -729,22 +662,6 @@ int inet_getname(struct socket *sock, struct sockaddr *uaddr, ...@@ -729,22 +662,6 @@ int inet_getname(struct socket *sock, struct sockaddr *uaddr,
return 0; return 0;
} }
int inet_recvmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
size_t size, int flags)
{
struct sock *sk = sock->sk;
int addr_len = 0;
int err;
err = sk->sk_prot->recvmsg(iocb, sk, msg, size, flags & MSG_DONTWAIT,
flags & ~MSG_DONTWAIT, &addr_len);
if (err >= 0)
msg->msg_namelen = addr_len;
return err;
}
int inet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg, int inet_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr *msg,
size_t size) size_t size)
{ {
...@@ -891,10 +808,10 @@ struct proto_ops inet_stream_ops = { ...@@ -891,10 +808,10 @@ struct proto_ops inet_stream_ops = {
.ioctl = inet_ioctl, .ioctl = inet_ioctl,
.listen = inet_listen, .listen = inet_listen,
.shutdown = inet_shutdown, .shutdown = inet_shutdown,
.setsockopt = inet_setsockopt, .setsockopt = sock_common_setsockopt,
.getsockopt = inet_getsockopt, .getsockopt = sock_common_getsockopt,
.sendmsg = inet_sendmsg, .sendmsg = inet_sendmsg,
.recvmsg = inet_recvmsg, .recvmsg = sock_common_recvmsg,
.mmap = sock_no_mmap, .mmap = sock_no_mmap,
.sendpage = tcp_sendpage .sendpage = tcp_sendpage
}; };
...@@ -906,16 +823,16 @@ struct proto_ops inet_dgram_ops = { ...@@ -906,16 +823,16 @@ struct proto_ops inet_dgram_ops = {
.bind = inet_bind, .bind = inet_bind,
.connect = inet_dgram_connect, .connect = inet_dgram_connect,
.socketpair = sock_no_socketpair, .socketpair = sock_no_socketpair,
.accept = sock_no_accept, .accept = inet_accept,
.getname = inet_getname, .getname = inet_getname,
.poll = datagram_poll, .poll = datagram_poll,
.ioctl = inet_ioctl, .ioctl = inet_ioctl,
.listen = sock_no_listen, .listen = sock_no_listen,
.shutdown = inet_shutdown, .shutdown = inet_shutdown,
.setsockopt = inet_setsockopt, .setsockopt = sock_common_setsockopt,
.getsockopt = inet_getsockopt, .getsockopt = sock_common_getsockopt,
.sendmsg = inet_sendmsg, .sendmsg = inet_sendmsg,
.recvmsg = inet_recvmsg, .recvmsg = sock_common_recvmsg,
.mmap = sock_no_mmap, .mmap = sock_no_mmap,
.sendpage = inet_sendpage, .sendpage = inet_sendpage,
}; };
...@@ -1242,17 +1159,13 @@ EXPORT_SYMBOL(inet_dgram_connect); ...@@ -1242,17 +1159,13 @@ EXPORT_SYMBOL(inet_dgram_connect);
EXPORT_SYMBOL(inet_dgram_ops); EXPORT_SYMBOL(inet_dgram_ops);
EXPORT_SYMBOL(inet_family_ops); EXPORT_SYMBOL(inet_family_ops);
EXPORT_SYMBOL(inet_getname); EXPORT_SYMBOL(inet_getname);
EXPORT_SYMBOL(inet_getsockopt);
EXPORT_SYMBOL(inet_ioctl); EXPORT_SYMBOL(inet_ioctl);
EXPORT_SYMBOL(inet_listen); EXPORT_SYMBOL(inet_listen);
EXPORT_SYMBOL(inet_recvmsg);
EXPORT_SYMBOL(inet_register_protosw); EXPORT_SYMBOL(inet_register_protosw);
EXPORT_SYMBOL(inet_release); EXPORT_SYMBOL(inet_release);
EXPORT_SYMBOL(inet_sendmsg); EXPORT_SYMBOL(inet_sendmsg);
EXPORT_SYMBOL(inet_setsockopt);
EXPORT_SYMBOL(inet_shutdown); EXPORT_SYMBOL(inet_shutdown);
EXPORT_SYMBOL(inet_sock_destruct); EXPORT_SYMBOL(inet_sock_destruct);
EXPORT_SYMBOL(inet_sock_release);
EXPORT_SYMBOL(inet_stream_connect); EXPORT_SYMBOL(inet_stream_connect);
EXPORT_SYMBOL(inet_stream_ops); EXPORT_SYMBOL(inet_stream_ops);
EXPORT_SYMBOL(inet_unregister_protosw); EXPORT_SYMBOL(inet_unregister_protosw);
......
...@@ -94,8 +94,9 @@ int esp_output(struct sk_buff **pskb) ...@@ -94,8 +94,9 @@ int esp_output(struct sk_buff **pskb)
if (x->props.mode) { if (x->props.mode) {
top_iph = (struct iphdr*)skb_push(*pskb, x->props.header_len); top_iph = (struct iphdr*)skb_push(*pskb, x->props.header_len);
esph = (struct ip_esp_hdr*)(top_iph+1); esph = (struct ip_esp_hdr*)(top_iph+1);
if (encap && encap->encap_type) { if (encap) {
switch (encap->encap_type) { switch (encap->encap_type) {
default:
case UDP_ENCAP_ESPINUDP: case UDP_ENCAP_ESPINUDP:
uh = (struct udphdr*) esph; uh = (struct udphdr*) esph;
esph = (struct ip_esp_hdr*)(uh+1); esph = (struct ip_esp_hdr*)(uh+1);
...@@ -106,15 +107,8 @@ int esp_output(struct sk_buff **pskb) ...@@ -106,15 +107,8 @@ int esp_output(struct sk_buff **pskb)
udpdata32 = (u32*)(uh+1); udpdata32 = (u32*)(uh+1);
udpdata32[0] = udpdata32[1] = 0; udpdata32[0] = udpdata32[1] = 0;
esph = (struct ip_esp_hdr*)(udpdata32+2); esph = (struct ip_esp_hdr*)(udpdata32+2);
alen += 2;
top_iph->protocol = IPPROTO_UDP; top_iph->protocol = IPPROTO_UDP;
break; break;
default:
printk(KERN_INFO
"esp_output(): Unhandled encap: %u\n",
encap->encap_type);
top_iph->protocol = IPPROTO_ESP;
break;
} }
} else } else
top_iph->protocol = IPPROTO_ESP; top_iph->protocol = IPPROTO_ESP;
...@@ -137,8 +131,9 @@ int esp_output(struct sk_buff **pskb) ...@@ -137,8 +131,9 @@ int esp_output(struct sk_buff **pskb)
esph = (struct ip_esp_hdr*)skb_push(*pskb, x->props.header_len); esph = (struct ip_esp_hdr*)skb_push(*pskb, x->props.header_len);
top_iph = (struct iphdr*)skb_push(*pskb, iph->ihl*4); top_iph = (struct iphdr*)skb_push(*pskb, iph->ihl*4);
memcpy(top_iph, &tmp_iph, iph->ihl*4); memcpy(top_iph, &tmp_iph, iph->ihl*4);
if (encap && encap->encap_type) { if (encap) {
switch (encap->encap_type) { switch (encap->encap_type) {
default:
case UDP_ENCAP_ESPINUDP: case UDP_ENCAP_ESPINUDP:
uh = (struct udphdr*) esph; uh = (struct udphdr*) esph;
esph = (struct ip_esp_hdr*)(uh+1); esph = (struct ip_esp_hdr*)(uh+1);
...@@ -149,15 +144,8 @@ int esp_output(struct sk_buff **pskb) ...@@ -149,15 +144,8 @@ int esp_output(struct sk_buff **pskb)
udpdata32 = (u32*)(uh+1); udpdata32 = (u32*)(uh+1);
udpdata32[0] = udpdata32[1] = 0; udpdata32[0] = udpdata32[1] = 0;
esph = (struct ip_esp_hdr*)(udpdata32+2); esph = (struct ip_esp_hdr*)(udpdata32+2);
alen += 2;
top_iph->protocol = IPPROTO_UDP; top_iph->protocol = IPPROTO_UDP;
break; break;
default:
printk(KERN_INFO
"esp_output(): Unhandled encap: %u\n",
encap->encap_type);
top_iph->protocol = IPPROTO_ESP;
break;
} }
} else } else
top_iph->protocol = IPPROTO_ESP; top_iph->protocol = IPPROTO_ESP;
...@@ -313,28 +301,14 @@ int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_bu ...@@ -313,28 +301,14 @@ int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_bu
switch (decap->decap_type) { switch (decap->decap_type) {
case UDP_ENCAP_ESPINUDP: case UDP_ENCAP_ESPINUDP:
case UDP_ENCAP_ESPINUDP_NON_IKE: case UDP_ENCAP_ESPINUDP_NON_IKE:
if ((void*)uh == (void*)esph) {
printk(KERN_DEBUG
"esp_input(): Got ESP; expecting ESPinUDP\n");
break;
}
encap_data->proto = AF_INET; encap_data->proto = AF_INET;
encap_data->saddr.a4 = iph->saddr; encap_data->saddr.a4 = iph->saddr;
encap_data->sport = uh->source; encap_data->sport = uh->source;
encap_len = (void*)esph - (void*)uh; encap_len = (void*)esph - (void*)uh;
if (encap_len != sizeof(*uh))
printk(KERN_DEBUG
"esp_input(): UDP -> ESP: too much room: %d\n",
encap_len);
break; break;
default: default:
printk(KERN_INFO goto out;
"esp_input(): processing unknown encap type: %u\n",
decap->decap_type);
break;
} }
} }
...@@ -367,11 +341,8 @@ int esp_post_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct ...@@ -367,11 +341,8 @@ int esp_post_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct
if (encap->encap_type != decap->decap_type) if (encap->encap_type != decap->decap_type)
return -EINVAL; return -EINVAL;
/* Next, if we don't have an encap type, then ignore it */
if (!encap->encap_type)
return 0;
switch (encap->encap_type) { switch (encap->encap_type) {
default:
case UDP_ENCAP_ESPINUDP: case UDP_ENCAP_ESPINUDP:
case UDP_ENCAP_ESPINUDP_NON_IKE: case UDP_ENCAP_ESPINUDP_NON_IKE:
/* /*
...@@ -408,11 +379,6 @@ int esp_post_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct ...@@ -408,11 +379,6 @@ int esp_post_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct
skb->ip_summed = CHECKSUM_UNNECESSARY; skb->ip_summed = CHECKSUM_UNNECESSARY;
break; break;
default:
printk(KERN_INFO
"esp4_post_input(): Unhandled encap type: %u\n",
encap->encap_type);
break;
} }
} }
return 0; return 0;
...@@ -549,20 +515,14 @@ int esp_init_state(struct xfrm_state *x, void *args) ...@@ -549,20 +515,14 @@ int esp_init_state(struct xfrm_state *x, void *args)
if (x->encap) { if (x->encap) {
struct xfrm_encap_tmpl *encap = x->encap; struct xfrm_encap_tmpl *encap = x->encap;
if (encap->encap_type) { switch (encap->encap_type) {
switch (encap->encap_type) { default:
case UDP_ENCAP_ESPINUDP: case UDP_ENCAP_ESPINUDP:
x->props.header_len += sizeof(struct udphdr); x->props.header_len += sizeof(struct udphdr);
break; break;
case UDP_ENCAP_ESPINUDP_NON_IKE: case UDP_ENCAP_ESPINUDP_NON_IKE:
x->props.header_len += sizeof(struct udphdr) + 2 * sizeof(u32); x->props.header_len += sizeof(struct udphdr) + 2 * sizeof(u32);
break; break;
default:
printk (KERN_INFO
"esp_init_state(): Unhandled encap type: %u\n",
encap->encap_type);
break;
}
} }
} }
x->data = esp; x->data = esp;
......
...@@ -480,7 +480,7 @@ static void raw_close(struct sock *sk, long timeout) ...@@ -480,7 +480,7 @@ static void raw_close(struct sock *sk, long timeout)
*/ */
ip_ra_control(sk, 0, NULL); ip_ra_control(sk, 0, NULL);
inet_sock_release(sk); sk_common_release(sk);
} }
/* This gets rid of all the nasties in af_inet. -DaveM */ /* This gets rid of all the nasties in af_inet. -DaveM */
......
...@@ -2094,7 +2094,7 @@ static int tcp_v4_init_sock(struct sock *sk) ...@@ -2094,7 +2094,7 @@ static int tcp_v4_init_sock(struct sock *sk)
return 0; return 0;
} }
static int tcp_v4_destroy_sock(struct sock *sk) int tcp_v4_destroy_sock(struct sock *sk)
{ {
struct tcp_opt *tp = tcp_sk(sk); struct tcp_opt *tp = tcp_sk(sk);
...@@ -2118,6 +2118,8 @@ static int tcp_v4_destroy_sock(struct sock *sk) ...@@ -2118,6 +2118,8 @@ static int tcp_v4_destroy_sock(struct sock *sk)
return 0; return 0;
} }
EXPORT_SYMBOL(tcp_v4_destroy_sock);
#ifdef CONFIG_PROC_FS #ifdef CONFIG_PROC_FS
/* Proc filesystem TCP sock list dumping. */ /* Proc filesystem TCP sock list dumping. */
......
...@@ -931,7 +931,7 @@ int udp_disconnect(struct sock *sk, int flags) ...@@ -931,7 +931,7 @@ int udp_disconnect(struct sock *sk, int flags)
static void udp_close(struct sock *sk, long timeout) static void udp_close(struct sock *sk, long timeout)
{ {
inet_sock_release(sk); sk_common_release(sk);
} }
/* return: /* return:
...@@ -964,6 +964,7 @@ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb) ...@@ -964,6 +964,7 @@ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb)
len = skb->tail - udpdata; len = skb->tail - udpdata;
switch (encap_type) { switch (encap_type) {
default:
case UDP_ENCAP_ESPINUDP: case UDP_ENCAP_ESPINUDP:
/* Check if this is a keepalive packet. If so, eat it. */ /* Check if this is a keepalive packet. If so, eat it. */
if (len == 1 && udpdata[0] == 0xff) { if (len == 1 && udpdata[0] == 0xff) {
...@@ -975,34 +976,6 @@ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb) ...@@ -975,34 +976,6 @@ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb)
/* Must be an IKE packet.. pass it through */ /* Must be an IKE packet.. pass it through */
return 1; return 1;
decaps:
/* At this point we are sure that this is an ESPinUDP packet,
* so we need to remove 'len' bytes from the packet (the UDP
* header and optional ESP marker bytes) and then modify the
* protocol to ESP, and then call into the transform receiver.
*/
/* Now we can update and verify the packet length... */
iph = skb->nh.iph;
iphlen = iph->ihl << 2;
iph->tot_len = htons(ntohs(iph->tot_len) - len);
if (skb->len < iphlen + len) {
/* packet is too small!?! */
return 0;
}
/* pull the data buffer up to the ESP header and set the
* transport header to point to ESP. Keep UDP on the stack
* for later.
*/
skb->h.raw = skb_pull(skb, len);
/* modify the protocol (it's ESP!) */
iph->protocol = IPPROTO_ESP;
/* and let the caller know to send this into the ESP processor... */
return -1;
case UDP_ENCAP_ESPINUDP_NON_IKE: case UDP_ENCAP_ESPINUDP_NON_IKE:
/* Check if this is a keepalive packet. If so, eat it. */ /* Check if this is a keepalive packet. If so, eat it. */
if (len == 1 && udpdata[0] == 0xff) { if (len == 1 && udpdata[0] == 0xff) {
...@@ -1012,17 +985,37 @@ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb) ...@@ -1012,17 +985,37 @@ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb)
/* ESP Packet with Non-IKE marker */ /* ESP Packet with Non-IKE marker */
len = sizeof(struct udphdr) + 2 * sizeof(u32); len = sizeof(struct udphdr) + 2 * sizeof(u32);
goto decaps;
} else } else
/* Must be an IKE packet.. pass it through */ /* Must be an IKE packet.. pass it through */
return 1; return 1;
}
default: /* At this point we are sure that this is an ESPinUDP packet,
if (net_ratelimit()) * so we need to remove 'len' bytes from the packet (the UDP
printk(KERN_INFO "udp_encap_rcv(): Unhandled UDP encap type: %u\n", * header and optional ESP marker bytes) and then modify the
encap_type); * protocol to ESP, and then call into the transform receiver.
return 1; */
/* Now we can update and verify the packet length... */
iph = skb->nh.iph;
iphlen = iph->ihl << 2;
iph->tot_len = htons(ntohs(iph->tot_len) - len);
if (skb->len < iphlen + len) {
/* packet is too small!?! */
return 0;
} }
/* pull the data buffer up to the ESP header and set the
* transport header to point to ESP. Keep UDP on the stack
* for later.
*/
skb->h.raw = skb_pull(skb, len);
/* modify the protocol (it's ESP!) */
iph->protocol = IPPROTO_ESP;
/* and let the caller know to send this into the ESP processor... */
return -1;
#endif #endif
} }
...@@ -1297,7 +1290,16 @@ static int udp_setsockopt(struct sock *sk, int level, int optname, ...@@ -1297,7 +1290,16 @@ static int udp_setsockopt(struct sock *sk, int level, int optname,
break; break;
case UDP_ENCAP: case UDP_ENCAP:
up->encap_type = val; switch (val) {
case 0:
case UDP_ENCAP_ESPINUDP:
case UDP_ENCAP_ESPINUDP_NON_IKE:
up->encap_type = val;
break;
default:
err = -ENOPROTOOPT;
break;
}
break; break;
default: default:
......
...@@ -250,7 +250,7 @@ static int inet6_create(struct socket *sock, int protocol) ...@@ -250,7 +250,7 @@ static int inet6_create(struct socket *sock, int protocol)
if (sk->sk_prot->init) { if (sk->sk_prot->init) {
int err = sk->sk_prot->init(sk); int err = sk->sk_prot->init(sk);
if (err != 0) { if (err != 0) {
inet_sock_release(sk); sk_common_release(sk);
return err; return err;
} }
} }
...@@ -510,10 +510,10 @@ struct proto_ops inet6_stream_ops = { ...@@ -510,10 +510,10 @@ struct proto_ops inet6_stream_ops = {
.ioctl = inet6_ioctl, /* must change */ .ioctl = inet6_ioctl, /* must change */
.listen = inet_listen, /* ok */ .listen = inet_listen, /* ok */
.shutdown = inet_shutdown, /* ok */ .shutdown = inet_shutdown, /* ok */
.setsockopt = inet_setsockopt, /* ok */ .setsockopt = sock_common_setsockopt, /* ok */
.getsockopt = inet_getsockopt, /* ok */ .getsockopt = sock_common_getsockopt, /* ok */
.sendmsg = inet_sendmsg, /* ok */ .sendmsg = inet_sendmsg, /* ok */
.recvmsg = inet_recvmsg, /* ok */ .recvmsg = sock_common_recvmsg, /* ok */
.mmap = sock_no_mmap, .mmap = sock_no_mmap,
.sendpage = tcp_sendpage .sendpage = tcp_sendpage
}; };
...@@ -531,10 +531,10 @@ struct proto_ops inet6_dgram_ops = { ...@@ -531,10 +531,10 @@ struct proto_ops inet6_dgram_ops = {
.ioctl = inet6_ioctl, /* must change */ .ioctl = inet6_ioctl, /* must change */
.listen = sock_no_listen, /* ok */ .listen = sock_no_listen, /* ok */
.shutdown = inet_shutdown, /* ok */ .shutdown = inet_shutdown, /* ok */
.setsockopt = inet_setsockopt, /* ok */ .setsockopt = sock_common_setsockopt, /* ok */
.getsockopt = inet_getsockopt, /* ok */ .getsockopt = sock_common_getsockopt, /* ok */
.sendmsg = inet_sendmsg, /* ok */ .sendmsg = inet_sendmsg, /* ok */
.recvmsg = inet_recvmsg, /* ok */ .recvmsg = sock_common_recvmsg, /* ok */
.mmap = sock_no_mmap, .mmap = sock_no_mmap,
.sendpage = sock_no_sendpage, .sendpage = sock_no_sendpage,
}; };
......
...@@ -900,7 +900,7 @@ static void rawv6_close(struct sock *sk, long timeout) ...@@ -900,7 +900,7 @@ static void rawv6_close(struct sock *sk, long timeout)
if (inet_sk(sk)->num == IPPROTO_RAW) if (inet_sk(sk)->num == IPPROTO_RAW)
ip6_ra_control(sk, -1, NULL); ip6_ra_control(sk, -1, NULL);
inet_sock_release(sk); sk_common_release(sk);
} }
static int rawv6_init_sk(struct sock *sk) static int rawv6_init_sk(struct sock *sk)
......
...@@ -1892,25 +1892,9 @@ static int tcp_v6_init_sock(struct sock *sk) ...@@ -1892,25 +1892,9 @@ static int tcp_v6_init_sock(struct sock *sk)
static int tcp_v6_destroy_sock(struct sock *sk) static int tcp_v6_destroy_sock(struct sock *sk)
{ {
struct tcp_opt *tp = tcp_sk(sk); extern int tcp_v4_destroy_sock(struct sock *sk);
tcp_clear_xmit_timers(sk);
/* Cleanup up the write buffer. */
sk_stream_writequeue_purge(sk);
/* Cleans up our, hopefully empty, out_of_order_queue. */
__skb_queue_purge(&tp->out_of_order_queue);
/* Clean prequeue, it must be empty really */
__skb_queue_purge(&tp->ucopy.prequeue);
/* Clean up a referenced TCP bind bucket. */
if (tcp_sk(sk)->bind_hash)
tcp_put_port(sk);
atomic_dec(&tcp_sockets_allocated);
tcp_v4_destroy_sock(sk);
return inet6_destroy_sock(sk); return inet6_destroy_sock(sk);
} }
......
...@@ -358,7 +358,7 @@ int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) ...@@ -358,7 +358,7 @@ int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
static void udpv6_close(struct sock *sk, long timeout) static void udpv6_close(struct sock *sk, long timeout)
{ {
inet_sock_release(sk); sk_common_release(sk);
} }
/* /*
...@@ -1044,7 +1044,14 @@ static int udpv6_setsockopt(struct sock *sk, int level, int optname, ...@@ -1044,7 +1044,14 @@ static int udpv6_setsockopt(struct sock *sk, int level, int optname,
break; break;
case UDP_ENCAP: case UDP_ENCAP:
up->encap_type = val; switch (val) {
case 0:
up->encap_type = val;
break;
default:
err = -ENOPROTOOPT;
break;
}
break; break;
default: default:
......
...@@ -1075,6 +1075,15 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr, ...@@ -1075,6 +1075,15 @@ static struct xfrm_state * pfkey_msg2xfrm_state(struct sadb_msg *hdr,
n_type = ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1]; n_type = ext_hdrs[SADB_X_EXT_NAT_T_TYPE-1];
natt->encap_type = n_type->sadb_x_nat_t_type_type; natt->encap_type = n_type->sadb_x_nat_t_type_type;
switch (natt->encap_type) {
case UDP_ENCAP_ESPINUDP:
case UDP_ENCAP_ESPINUDP_NON_IKE:
break;
default:
err = -ENOPROTOOPT;
goto out;
}
if (ext_hdrs[SADB_X_EXT_NAT_T_SPORT-1]) { if (ext_hdrs[SADB_X_EXT_NAT_T_SPORT-1]) {
struct sadb_x_nat_t_port* n_port = struct sadb_x_nat_t_port* n_port =
ext_hdrs[SADB_X_EXT_NAT_T_SPORT-1]; ext_hdrs[SADB_X_EXT_NAT_T_SPORT-1];
......
...@@ -610,6 +610,7 @@ int tca_action_flush(struct rtattr *rta, struct nlmsghdr *n, u32 pid) ...@@ -610,6 +610,7 @@ int tca_action_flush(struct rtattr *rta, struct nlmsghdr *n, u32 pid)
unsigned char *b; unsigned char *b;
struct nlmsghdr *nlh; struct nlmsghdr *nlh;
struct tcamsg *t; struct tcamsg *t;
struct netlink_callback dcb;
struct rtattr *x; struct rtattr *x;
struct rtattr *tb[TCA_ACT_MAX+1]; struct rtattr *tb[TCA_ACT_MAX+1];
struct rtattr *kind = NULL; struct rtattr *kind = NULL;
...@@ -646,7 +647,7 @@ int tca_action_flush(struct rtattr *rta, struct nlmsghdr *n, u32 pid) ...@@ -646,7 +647,7 @@ int tca_action_flush(struct rtattr *rta, struct nlmsghdr *n, u32 pid)
x = (struct rtattr *) skb->tail; x = (struct rtattr *) skb->tail;
RTA_PUT(skb, TCA_ACT_TAB, 0, NULL); RTA_PUT(skb, TCA_ACT_TAB, 0, NULL);
err = a->ops->walk(skb, NULL, RTM_DELACTION, a); err = a->ops->walk(skb, &dcb, RTM_DELACTION, a);
if (0 > err ) { if (0 > err ) {
goto rtattr_failure; goto rtattr_failure;
} }
......
...@@ -641,7 +641,7 @@ struct sock *sctp_v6_create_accept_sk(struct sock *sk, ...@@ -641,7 +641,7 @@ struct sock *sctp_v6_create_accept_sk(struct sock *sk,
#endif #endif
if (newsk->sk_prot->init(newsk)) { if (newsk->sk_prot->init(newsk)) {
inet_sock_release(newsk); sk_common_release(newsk);
newsk = NULL; newsk = NULL;
} }
...@@ -882,10 +882,10 @@ static struct proto_ops inet6_seqpacket_ops = { ...@@ -882,10 +882,10 @@ static struct proto_ops inet6_seqpacket_ops = {
.ioctl = inet6_ioctl, .ioctl = inet6_ioctl,
.listen = sctp_inet_listen, .listen = sctp_inet_listen,
.shutdown = inet_shutdown, .shutdown = inet_shutdown,
.setsockopt = inet_setsockopt, .setsockopt = sock_common_setsockopt,
.getsockopt = inet_getsockopt, .getsockopt = sock_common_getsockopt,
.sendmsg = inet_sendmsg, .sendmsg = inet_sendmsg,
.recvmsg = inet_recvmsg, .recvmsg = sock_common_recvmsg,
.mmap = sock_no_mmap, .mmap = sock_no_mmap,
}; };
......
...@@ -603,7 +603,7 @@ struct sock *sctp_v4_create_accept_sk(struct sock *sk, ...@@ -603,7 +603,7 @@ struct sock *sctp_v4_create_accept_sk(struct sock *sk,
#endif #endif
if (newsk->sk_prot->init(newsk)) { if (newsk->sk_prot->init(newsk)) {
inet_sock_release(newsk); sk_common_release(newsk);
newsk = NULL; newsk = NULL;
} }
...@@ -846,10 +846,10 @@ struct proto_ops inet_seqpacket_ops = { ...@@ -846,10 +846,10 @@ struct proto_ops inet_seqpacket_ops = {
.ioctl = inet_ioctl, .ioctl = inet_ioctl,
.listen = sctp_inet_listen, .listen = sctp_inet_listen,
.shutdown = inet_shutdown, /* Looks harmless. */ .shutdown = inet_shutdown, /* Looks harmless. */
.setsockopt = inet_setsockopt, /* IP_SOL IP_OPTION is a problem. */ .setsockopt = sock_common_setsockopt, /* IP_SOL IP_OPTION is a problem. */
.getsockopt = inet_getsockopt, .getsockopt = sock_common_getsockopt,
.sendmsg = inet_sendmsg, .sendmsg = inet_sendmsg,
.recvmsg = inet_recvmsg, .recvmsg = sock_common_recvmsg,
.mmap = sock_no_mmap, .mmap = sock_no_mmap,
.sendpage = sock_no_sendpage, .sendpage = sock_no_sendpage,
}; };
......
...@@ -945,11 +945,11 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout) ...@@ -945,11 +945,11 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout)
sctp_local_bh_disable(); sctp_local_bh_disable();
sctp_bh_lock_sock(sk); sctp_bh_lock_sock(sk);
/* Hold the sock, since inet_sock_release() will put sock_put() /* Hold the sock, since sk_common_release() will put sock_put()
* and we have just a little more cleanup. * and we have just a little more cleanup.
*/ */
sock_hold(sk); sock_hold(sk);
inet_sock_release(sk); sk_common_release(sk);
sctp_bh_unlock_sock(sk); sctp_bh_unlock_sock(sk);
sctp_local_bh_enable(); sctp_local_bh_enable();
......
...@@ -78,6 +78,15 @@ static int verify_encap_tmpl(struct rtattr **xfrma) ...@@ -78,6 +78,15 @@ static int verify_encap_tmpl(struct rtattr **xfrma)
if ((rt->rta_len - sizeof(*rt)) < sizeof(*encap)) if ((rt->rta_len - sizeof(*rt)) < sizeof(*encap))
return -EINVAL; return -EINVAL;
encap = RTA_DATA(rt);
switch (encap->encap_type) {
case UDP_ENCAP_ESPINUDP:
case UDP_ENCAP_ESPINUDP_NON_IKE:
break;
default:
return -ENOPROTOOPT;
}
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment