projects
/
platform
/
kernel
/
linux-starfive.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
[platform/kernel/linux-starfive.git]
/
net
/
l2tp
/
l2tp_ip.c
diff --git
a/net/l2tp/l2tp_ip.c
b/net/l2tp/l2tp_ip.c
index
5c04f3e
..
b6466e7
100644
(file)
--- a/
net/l2tp/l2tp_ip.c
+++ b/
net/l2tp/l2tp_ip.c
@@
-296,12
+296,12
@@
out_in_use:
static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
{
static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
{
- int rc;
- struct inet_sock *inet = inet_sk(sk);
struct sockaddr_l2tpip *lsa = (struct sockaddr_l2tpip *) uaddr;
struct sockaddr_l2tpip *lsa = (struct sockaddr_l2tpip *) uaddr;
+ struct inet_sock *inet = inet_sk(sk);
+ struct flowi4 *fl4;
struct rtable *rt;
__be32 saddr;
struct rtable *rt;
__be32 saddr;
- int oif;
+ int oif
, rc
;
rc = -EINVAL;
if (addr_len < sizeof(*lsa))
rc = -EINVAL;
if (addr_len < sizeof(*lsa))
@@
-311,6
+311,8
@@
static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len
if (lsa->l2tp_family != AF_INET)
goto out;
if (lsa->l2tp_family != AF_INET)
goto out;
+ lock_sock(sk);
+
sk_dst_reset(sk);
oif = sk->sk_bound_dev_if;
sk_dst_reset(sk);
oif = sk->sk_bound_dev_if;
@@
-320,7
+322,8
@@
static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len
if (ipv4_is_multicast(lsa->l2tp_addr.s_addr))
goto out;
if (ipv4_is_multicast(lsa->l2tp_addr.s_addr))
goto out;
- rt = ip_route_connect(lsa->l2tp_addr.s_addr, saddr,
+ fl4 = &inet->cork.fl.u.ip4;
+ rt = ip_route_connect(fl4, lsa->l2tp_addr.s_addr, saddr,
RT_CONN_FLAGS(sk), oif,
IPPROTO_L2TP,
0, 0, sk, true);
RT_CONN_FLAGS(sk), oif,
IPPROTO_L2TP,
0, 0, sk, true);
@@
-340,10
+343,10
@@
static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len
l2tp_ip_sk(sk)->peer_conn_id = lsa->l2tp_conn_id;
if (!inet->inet_saddr)
l2tp_ip_sk(sk)->peer_conn_id = lsa->l2tp_conn_id;
if (!inet->inet_saddr)
- inet->inet_saddr =
rt->rt_src
;
+ inet->inet_saddr =
fl4->saddr
;
if (!inet->inet_rcv_saddr)
if (!inet->inet_rcv_saddr)
- inet->inet_rcv_saddr =
rt->rt_src
;
- inet->inet_daddr =
rt->rt_dst
;
+ inet->inet_rcv_saddr =
fl4->saddr
;
+ inet->inet_daddr =
fl4->daddr
;
sk->sk_state = TCP_ESTABLISHED;
inet->inet_id = jiffies;
sk->sk_state = TCP_ESTABLISHED;
inet->inet_id = jiffies;
@@
-356,6
+359,7
@@
static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len
rc = 0;
out:
rc = 0;
out:
+ release_sock(sk);
return rc;
}
return rc;
}
@@
-416,23
+420,28
@@
static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m
int rc;
struct l2tp_ip_sock *lsa = l2tp_ip_sk(sk);
struct inet_sock *inet = inet_sk(sk);
int rc;
struct l2tp_ip_sock *lsa = l2tp_ip_sk(sk);
struct inet_sock *inet = inet_sk(sk);
- struct ip_options *opt = inet->opt;
struct rtable *rt = NULL;
struct rtable *rt = NULL;
+ struct flowi4 *fl4;
int connected = 0;
__be32 daddr;
int connected = 0;
__be32 daddr;
+ lock_sock(sk);
+
+ rc = -ENOTCONN;
if (sock_flag(sk, SOCK_DEAD))
if (sock_flag(sk, SOCK_DEAD))
-
return -ENOTCONN
;
+
goto out
;
/* Get and verify the address. */
if (msg->msg_name) {
struct sockaddr_l2tpip *lip = (struct sockaddr_l2tpip *) msg->msg_name;
/* Get and verify the address. */
if (msg->msg_name) {
struct sockaddr_l2tpip *lip = (struct sockaddr_l2tpip *) msg->msg_name;
+ rc = -EINVAL;
if (msg->msg_namelen < sizeof(*lip))
if (msg->msg_namelen < sizeof(*lip))
-
return -EINVAL
;
+
goto out
;
if (lip->l2tp_family != AF_INET) {
if (lip->l2tp_family != AF_INET) {
+ rc = -EAFNOSUPPORT;
if (lip->l2tp_family != AF_UNSPEC)
if (lip->l2tp_family != AF_UNSPEC)
-
return -EAFNOSUPPORT
;
+
goto out
;
}
daddr = lip->l2tp_addr.s_addr;
}
daddr = lip->l2tp_addr.s_addr;
@@
-467,19
+476,27
@@
static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m
goto error;
}
goto error;
}
+ fl4 = &inet->cork.fl.u.ip4;
if (connected)
rt = (struct rtable *) __sk_dst_check(sk, 0);
if (rt == NULL) {
if (connected)
rt = (struct rtable *) __sk_dst_check(sk, 0);
if (rt == NULL) {
+ struct ip_options_rcu *inet_opt;
+
+ rcu_read_lock();
+ inet_opt = rcu_dereference(inet->inet_opt);
+
/* Use correct destination address if we have options. */
/* Use correct destination address if we have options. */
- if (opt && opt->srr)
- daddr = opt->faddr;
+ if (inet_opt && inet_opt->opt.srr)
+ daddr = inet_opt->opt.faddr;
+
+ rcu_read_unlock();
/* If this fails, retransmit mechanism of transport layer will
* keep trying until route appears or the connection times
* itself out.
*/
/* If this fails, retransmit mechanism of transport layer will
* keep trying until route appears or the connection times
* itself out.
*/
- rt = ip_route_output_ports(sock_net(sk), sk,
+ rt = ip_route_output_ports(sock_net(sk),
fl4,
sk,
daddr, inet->inet_saddr,
inet->inet_dport, inet->inet_sport,
sk->sk_protocol, RT_CONN_FLAGS(sk),
daddr, inet->inet_saddr,
inet->inet_dport, inet->inet_sport,
sk->sk_protocol, RT_CONN_FLAGS(sk),
@@
-491,7
+508,7
@@
static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m
skb_dst_set(skb, dst_clone(&rt->dst));
/* Queue the packet to IP for output */
skb_dst_set(skb, dst_clone(&rt->dst));
/* Queue the packet to IP for output */
- rc = ip_queue_xmit(skb);
+ rc = ip_queue_xmit(skb
, &inet->cork.fl
);
error:
/* Update stats */
error:
/* Update stats */
@@
-503,12
+520,15
@@
error:
lsa->tx_errors++;
}
lsa->tx_errors++;
}
+out:
+ release_sock(sk);
return rc;
no_route:
IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
kfree_skb(skb);
return rc;
no_route:
IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES);
kfree_skb(skb);
- return -EHOSTUNREACH;
+ rc = -EHOSTUNREACH;
+ goto out;
}
static int l2tp_ip_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
}
static int l2tp_ip_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,