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,
int addr_len, int flags);
extern int inet_accept(struct socket *sock,
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,
struct socket *sock,
struct msghdr *msg,
size_t size);
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 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 void inet_sock_release(struct sock *sk);
extern void inet_sock_destruct(struct sock *sk);
extern atomic_t inet_sock_nr;
......
......@@ -770,6 +770,19 @@ extern ssize_t sock_no_sendpage(struct socket *sock,
int offset, size_t size,
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
*/
......
......@@ -118,6 +118,7 @@
#include <net/protocol.h>
#include <linux/skbuff.h>
#include <net/sock.h>
#include <net/xfrm.h>
#include <linux/ipsec.h>
#include <linux/filter.h>
......@@ -1259,6 +1260,93 @@ void sock_disable_timestamp(struct sock *sk)
}
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(__release_sock);
EXPORT_SYMBOL(sk_alloc);
......
......@@ -166,79 +166,12 @@ void inet_sock_destruct(struct sock *sk)
#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
* socket object. Mostly it punts to the subprotocols of IP to do
* 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.
*/
......@@ -422,7 +355,7 @@ static int inet_create(struct socket *sock, int protocol)
if (sk->sk_prot->init) {
err = sk->sk_prot->init(sk);
if (err)
inet_sock_release(sk);
sk_common_release(sk);
}
out:
return err;
......@@ -729,22 +662,6 @@ int inet_getname(struct socket *sock, struct sockaddr *uaddr,
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,
size_t size)
{
......@@ -891,10 +808,10 @@ struct proto_ops inet_stream_ops = {
.ioctl = inet_ioctl,
.listen = inet_listen,
.shutdown = inet_shutdown,
.setsockopt = inet_setsockopt,
.getsockopt = inet_getsockopt,
.setsockopt = sock_common_setsockopt,
.getsockopt = sock_common_getsockopt,
.sendmsg = inet_sendmsg,
.recvmsg = inet_recvmsg,
.recvmsg = sock_common_recvmsg,
.mmap = sock_no_mmap,
.sendpage = tcp_sendpage
};
......@@ -906,16 +823,16 @@ struct proto_ops inet_dgram_ops = {
.bind = inet_bind,
.connect = inet_dgram_connect,
.socketpair = sock_no_socketpair,
.accept = sock_no_accept,
.accept = inet_accept,
.getname = inet_getname,
.poll = datagram_poll,
.ioctl = inet_ioctl,
.listen = sock_no_listen,
.shutdown = inet_shutdown,
.setsockopt = inet_setsockopt,
.getsockopt = inet_getsockopt,
.setsockopt = sock_common_setsockopt,
.getsockopt = sock_common_getsockopt,
.sendmsg = inet_sendmsg,
.recvmsg = inet_recvmsg,
.recvmsg = sock_common_recvmsg,
.mmap = sock_no_mmap,
.sendpage = inet_sendpage,
};
......@@ -1242,17 +1159,13 @@ EXPORT_SYMBOL(inet_dgram_connect);
EXPORT_SYMBOL(inet_dgram_ops);
EXPORT_SYMBOL(inet_family_ops);
EXPORT_SYMBOL(inet_getname);
EXPORT_SYMBOL(inet_getsockopt);
EXPORT_SYMBOL(inet_ioctl);
EXPORT_SYMBOL(inet_listen);
EXPORT_SYMBOL(inet_recvmsg);
EXPORT_SYMBOL(inet_register_protosw);
EXPORT_SYMBOL(inet_release);
EXPORT_SYMBOL(inet_sendmsg);
EXPORT_SYMBOL(inet_setsockopt);
EXPORT_SYMBOL(inet_shutdown);
EXPORT_SYMBOL(inet_sock_destruct);
EXPORT_SYMBOL(inet_sock_release);
EXPORT_SYMBOL(inet_stream_connect);
EXPORT_SYMBOL(inet_stream_ops);
EXPORT_SYMBOL(inet_unregister_protosw);
......
......@@ -94,8 +94,9 @@ int esp_output(struct sk_buff **pskb)
if (x->props.mode) {
top_iph = (struct iphdr*)skb_push(*pskb, x->props.header_len);
esph = (struct ip_esp_hdr*)(top_iph+1);
if (encap && encap->encap_type) {
if (encap) {
switch (encap->encap_type) {
default:
case UDP_ENCAP_ESPINUDP:
uh = (struct udphdr*) esph;
esph = (struct ip_esp_hdr*)(uh+1);
......@@ -106,15 +107,8 @@ int esp_output(struct sk_buff **pskb)
udpdata32 = (u32*)(uh+1);
udpdata32[0] = udpdata32[1] = 0;
esph = (struct ip_esp_hdr*)(udpdata32+2);
alen += 2;
top_iph->protocol = IPPROTO_UDP;
break;
default:
printk(KERN_INFO
"esp_output(): Unhandled encap: %u\n",
encap->encap_type);
top_iph->protocol = IPPROTO_ESP;
break;
}
} else
top_iph->protocol = IPPROTO_ESP;
......@@ -137,8 +131,9 @@ int esp_output(struct sk_buff **pskb)
esph = (struct ip_esp_hdr*)skb_push(*pskb, x->props.header_len);
top_iph = (struct iphdr*)skb_push(*pskb, iph->ihl*4);
memcpy(top_iph, &tmp_iph, iph->ihl*4);
if (encap && encap->encap_type) {
if (encap) {
switch (encap->encap_type) {
default:
case UDP_ENCAP_ESPINUDP:
uh = (struct udphdr*) esph;
esph = (struct ip_esp_hdr*)(uh+1);
......@@ -149,15 +144,8 @@ int esp_output(struct sk_buff **pskb)
udpdata32 = (u32*)(uh+1);
udpdata32[0] = udpdata32[1] = 0;
esph = (struct ip_esp_hdr*)(udpdata32+2);
alen += 2;
top_iph->protocol = IPPROTO_UDP;
break;
default:
printk(KERN_INFO
"esp_output(): Unhandled encap: %u\n",
encap->encap_type);
top_iph->protocol = IPPROTO_ESP;
break;
}
} else
top_iph->protocol = IPPROTO_ESP;
......@@ -313,28 +301,14 @@ int esp_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_bu
switch (decap->decap_type) {
case UDP_ENCAP_ESPINUDP:
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->saddr.a4 = iph->saddr;
encap_data->sport = uh->source;
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;
default:
printk(KERN_INFO
"esp_input(): processing unknown encap type: %u\n",
decap->decap_type);
break;
goto out;
}
}
......@@ -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)
return -EINVAL;
/* Next, if we don't have an encap type, then ignore it */
if (!encap->encap_type)
return 0;
switch (encap->encap_type) {
default:
case UDP_ENCAP_ESPINUDP:
case UDP_ENCAP_ESPINUDP_NON_IKE:
/*
......@@ -408,11 +379,6 @@ int esp_post_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct
skb->ip_summed = CHECKSUM_UNNECESSARY;
break;
default:
printk(KERN_INFO
"esp4_post_input(): Unhandled encap type: %u\n",
encap->encap_type);
break;
}
}
return 0;
......@@ -549,20 +515,14 @@ int esp_init_state(struct xfrm_state *x, void *args)
if (x->encap) {
struct xfrm_encap_tmpl *encap = x->encap;
if (encap->encap_type) {
switch (encap->encap_type) {
case UDP_ENCAP_ESPINUDP:
x->props.header_len += sizeof(struct udphdr);
break;
case UDP_ENCAP_ESPINUDP_NON_IKE:
x->props.header_len += sizeof(struct udphdr) + 2 * sizeof(u32);
break;
default:
printk (KERN_INFO
"esp_init_state(): Unhandled encap type: %u\n",
encap->encap_type);
break;
}
switch (encap->encap_type) {
default:
case UDP_ENCAP_ESPINUDP:
x->props.header_len += sizeof(struct udphdr);
break;
case UDP_ENCAP_ESPINUDP_NON_IKE:
x->props.header_len += sizeof(struct udphdr) + 2 * sizeof(u32);
break;
}
}
x->data = esp;
......
......@@ -480,7 +480,7 @@ static void raw_close(struct sock *sk, long timeout)
*/
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 */
......
......@@ -2094,7 +2094,7 @@ static int tcp_v4_init_sock(struct sock *sk)
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);
......@@ -2118,6 +2118,8 @@ static int tcp_v4_destroy_sock(struct sock *sk)
return 0;
}
EXPORT_SYMBOL(tcp_v4_destroy_sock);
#ifdef CONFIG_PROC_FS
/* Proc filesystem TCP sock list dumping. */
......
......@@ -931,7 +931,7 @@ int udp_disconnect(struct sock *sk, int flags)
static void udp_close(struct sock *sk, long timeout)
{
inet_sock_release(sk);
sk_common_release(sk);
}
/* return:
......@@ -964,6 +964,7 @@ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb)
len = skb->tail - udpdata;
switch (encap_type) {
default:
case UDP_ENCAP_ESPINUDP:
/* Check if this is a keepalive packet. If so, eat it. */
if (len == 1 && udpdata[0] == 0xff) {
......@@ -975,34 +976,6 @@ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb)
/* Must be an IKE packet.. pass it through */
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:
/* Check if this is a keepalive packet. If so, eat it. */
if (len == 1 && udpdata[0] == 0xff) {
......@@ -1012,17 +985,37 @@ static int udp_encap_rcv(struct sock * sk, struct sk_buff *skb)
/* ESP Packet with Non-IKE marker */
len = sizeof(struct udphdr) + 2 * sizeof(u32);
goto decaps;
} else
/* Must be an IKE packet.. pass it through */
return 1;
}
default:
if (net_ratelimit())
printk(KERN_INFO "udp_encap_rcv(): Unhandled UDP encap type: %u\n",
encap_type);
return 1;
/* 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;
#endif
}
......@@ -1297,7 +1290,16 @@ static int udp_setsockopt(struct sock *sk, int level, int optname,
break;
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;
default:
......
......@@ -250,7 +250,7 @@ static int inet6_create(struct socket *sock, int protocol)
if (sk->sk_prot->init) {
int err = sk->sk_prot->init(sk);
if (err != 0) {
inet_sock_release(sk);
sk_common_release(sk);
return err;
}
}
......@@ -510,10 +510,10 @@ struct proto_ops inet6_stream_ops = {
.ioctl = inet6_ioctl, /* must change */
.listen = inet_listen, /* ok */
.shutdown = inet_shutdown, /* ok */
.setsockopt = inet_setsockopt, /* ok */
.getsockopt = inet_getsockopt, /* ok */
.setsockopt = sock_common_setsockopt, /* ok */
.getsockopt = sock_common_getsockopt, /* ok */
.sendmsg = inet_sendmsg, /* ok */
.recvmsg = inet_recvmsg, /* ok */
.recvmsg = sock_common_recvmsg, /* ok */
.mmap = sock_no_mmap,
.sendpage = tcp_sendpage
};
......@@ -531,10 +531,10 @@ struct proto_ops inet6_dgram_ops = {
.ioctl = inet6_ioctl, /* must change */
.listen = sock_no_listen, /* ok */
.shutdown = inet_shutdown, /* ok */
.setsockopt = inet_setsockopt, /* ok */
.getsockopt = inet_getsockopt, /* ok */
.setsockopt = sock_common_setsockopt, /* ok */
.getsockopt = sock_common_getsockopt, /* ok */
.sendmsg = inet_sendmsg, /* ok */
.recvmsg = inet_recvmsg, /* ok */
.recvmsg = sock_common_recvmsg, /* ok */
.mmap = sock_no_mmap,
.sendpage = sock_no_sendpage,
};
......
......@@ -900,7 +900,7 @@ static void rawv6_close(struct sock *sk, long timeout)
if (inet_sk(sk)->num == IPPROTO_RAW)
ip6_ra_control(sk, -1, NULL);
inet_sock_release(sk);
sk_common_release(sk);
}
static int rawv6_init_sk(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)
{
struct tcp_opt *tp = tcp_sk(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);
extern int tcp_v4_destroy_sock(struct sock *sk);
tcp_v4_destroy_sock(sk);
return inet6_destroy_sock(sk);
}
......
......@@ -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)
{
inet_sock_release(sk);
sk_common_release(sk);
}
/*
......@@ -1044,7 +1044,14 @@ static int udpv6_setsockopt(struct sock *sk, int level, int optname,
break;
case UDP_ENCAP:
up->encap_type = val;
switch (val) {
case 0:
up->encap_type = val;
break;
default:
err = -ENOPROTOOPT;
break;
}
break;
default:
......
......@@ -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];
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]) {
struct sadb_x_nat_t_port* n_port =
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)
unsigned char *b;
struct nlmsghdr *nlh;
struct tcamsg *t;
struct netlink_callback dcb;
struct rtattr *x;
struct rtattr *tb[TCA_ACT_MAX+1];
struct rtattr *kind = NULL;
......@@ -646,7 +647,7 @@ int tca_action_flush(struct rtattr *rta, struct nlmsghdr *n, u32 pid)
x = (struct rtattr *) skb->tail;
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 ) {
goto rtattr_failure;
}
......
......@@ -641,7 +641,7 @@ struct sock *sctp_v6_create_accept_sk(struct sock *sk,
#endif
if (newsk->sk_prot->init(newsk)) {
inet_sock_release(newsk);
sk_common_release(newsk);
newsk = NULL;
}
......@@ -882,10 +882,10 @@ static struct proto_ops inet6_seqpacket_ops = {
.ioctl = inet6_ioctl,
.listen = sctp_inet_listen,
.shutdown = inet_shutdown,
.setsockopt = inet_setsockopt,
.getsockopt = inet_getsockopt,
.setsockopt = sock_common_setsockopt,
.getsockopt = sock_common_getsockopt,
.sendmsg = inet_sendmsg,
.recvmsg = inet_recvmsg,
.recvmsg = sock_common_recvmsg,
.mmap = sock_no_mmap,
};
......
......@@ -603,7 +603,7 @@ struct sock *sctp_v4_create_accept_sk(struct sock *sk,
#endif
if (newsk->sk_prot->init(newsk)) {
inet_sock_release(newsk);
sk_common_release(newsk);
newsk = NULL;
}
......@@ -846,10 +846,10 @@ struct proto_ops inet_seqpacket_ops = {
.ioctl = inet_ioctl,
.listen = sctp_inet_listen,
.shutdown = inet_shutdown, /* Looks harmless. */
.setsockopt = inet_setsockopt, /* IP_SOL IP_OPTION is a problem. */
.getsockopt = inet_getsockopt,
.setsockopt = sock_common_setsockopt, /* IP_SOL IP_OPTION is a problem. */
.getsockopt = sock_common_getsockopt,
.sendmsg = inet_sendmsg,
.recvmsg = inet_recvmsg,
.recvmsg = sock_common_recvmsg,
.mmap = sock_no_mmap,
.sendpage = sock_no_sendpage,
};
......
......@@ -945,11 +945,11 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout)
sctp_local_bh_disable();
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.
*/
sock_hold(sk);
inet_sock_release(sk);
sk_common_release(sk);
sctp_bh_unlock_sock(sk);
sctp_local_bh_enable();
......
......@@ -78,6 +78,15 @@ static int verify_encap_tmpl(struct rtattr **xfrma)
if ((rt->rta_len - sizeof(*rt)) < sizeof(*encap))
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;
}
......
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