diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-20 16:43:21 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-05-20 16:43:21 -0400 |
commit | 06f4e926d256d902dd9a53dcb400fd74974ce087 (patch) | |
tree | 0b438b67f5f0eff6fd617bc497a9dace6164a488 /net/l2tp/l2tp_ip.c | |
parent | 8e7bfcbab3825d1b404d615cb1b54f44ff81f981 (diff) | |
parent | d93515611bbc70c2fe4db232e5feb448ed8e4cc9 (diff) |
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-next-2.6: (1446 commits)
macvlan: fix panic if lowerdev in a bond
tg3: Add braces around 5906 workaround.
tg3: Fix NETIF_F_LOOPBACK error
macvlan: remove one synchronize_rcu() call
networking: NET_CLS_ROUTE4 depends on INET
irda: Fix error propagation in ircomm_lmp_connect_response()
irda: Kill set but unused variable 'bytes' in irlan_check_command_param()
irda: Kill set but unused variable 'clen' in ircomm_connect_indication()
rxrpc: Fix set but unused variable 'usage' in rxrpc_get_transport()
be2net: Kill set but unused variable 'req' in lancer_fw_download()
irda: Kill set but unused vars 'saddr' and 'daddr' in irlan_provider_connect_indication()
atl1c: atl1c_resume() is only used when CONFIG_PM_SLEEP is defined.
rxrpc: Fix set but unused variable 'usage' in rxrpc_get_peer().
rxrpc: Kill set but unused variable 'local' in rxrpc_UDP_error_handler()
rxrpc: Kill set but unused variable 'sp' in rxrpc_process_connection()
rxrpc: Kill set but unused variable 'sp' in rxrpc_rotate_tx_window()
pkt_sched: Kill set but unused variable 'protocol' in tc_classify()
isdn: capi: Use pr_debug() instead of ifdefs.
tg3: Update version to 3.119
tg3: Apply rx_discards fix to 5719/5720
...
Fix up trivial conflicts in arch/x86/Kconfig and net/mac80211/agg-tx.c
as per Davem.
Diffstat (limited to 'net/l2tp/l2tp_ip.c')
-rw-r--r-- | net/l2tp/l2tp_ip.c | 52 |
1 files changed, 36 insertions, 16 deletions
diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c index 5c04f3e42704..b6466e71f5e1 100644 --- a/net/l2tp/l2tp_ip.c +++ b/net/l2tp/l2tp_ip.c | |||
@@ -296,12 +296,12 @@ out_in_use: | |||
296 | 296 | ||
297 | static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | 297 | static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) |
298 | { | 298 | { |
299 | int rc; | ||
300 | struct inet_sock *inet = inet_sk(sk); | ||
301 | struct sockaddr_l2tpip *lsa = (struct sockaddr_l2tpip *) uaddr; | 299 | struct sockaddr_l2tpip *lsa = (struct sockaddr_l2tpip *) uaddr; |
300 | struct inet_sock *inet = inet_sk(sk); | ||
301 | struct flowi4 *fl4; | ||
302 | struct rtable *rt; | 302 | struct rtable *rt; |
303 | __be32 saddr; | 303 | __be32 saddr; |
304 | int oif; | 304 | int oif, rc; |
305 | 305 | ||
306 | rc = -EINVAL; | 306 | rc = -EINVAL; |
307 | if (addr_len < sizeof(*lsa)) | 307 | if (addr_len < sizeof(*lsa)) |
@@ -311,6 +311,8 @@ static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len | |||
311 | if (lsa->l2tp_family != AF_INET) | 311 | if (lsa->l2tp_family != AF_INET) |
312 | goto out; | 312 | goto out; |
313 | 313 | ||
314 | lock_sock(sk); | ||
315 | |||
314 | sk_dst_reset(sk); | 316 | sk_dst_reset(sk); |
315 | 317 | ||
316 | oif = sk->sk_bound_dev_if; | 318 | oif = sk->sk_bound_dev_if; |
@@ -320,7 +322,8 @@ static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len | |||
320 | if (ipv4_is_multicast(lsa->l2tp_addr.s_addr)) | 322 | if (ipv4_is_multicast(lsa->l2tp_addr.s_addr)) |
321 | goto out; | 323 | goto out; |
322 | 324 | ||
323 | rt = ip_route_connect(lsa->l2tp_addr.s_addr, saddr, | 325 | fl4 = &inet->cork.fl.u.ip4; |
326 | rt = ip_route_connect(fl4, lsa->l2tp_addr.s_addr, saddr, | ||
324 | RT_CONN_FLAGS(sk), oif, | 327 | RT_CONN_FLAGS(sk), oif, |
325 | IPPROTO_L2TP, | 328 | IPPROTO_L2TP, |
326 | 0, 0, sk, true); | 329 | 0, 0, sk, true); |
@@ -340,10 +343,10 @@ static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len | |||
340 | l2tp_ip_sk(sk)->peer_conn_id = lsa->l2tp_conn_id; | 343 | l2tp_ip_sk(sk)->peer_conn_id = lsa->l2tp_conn_id; |
341 | 344 | ||
342 | if (!inet->inet_saddr) | 345 | if (!inet->inet_saddr) |
343 | inet->inet_saddr = rt->rt_src; | 346 | inet->inet_saddr = fl4->saddr; |
344 | if (!inet->inet_rcv_saddr) | 347 | if (!inet->inet_rcv_saddr) |
345 | inet->inet_rcv_saddr = rt->rt_src; | 348 | inet->inet_rcv_saddr = fl4->saddr; |
346 | inet->inet_daddr = rt->rt_dst; | 349 | inet->inet_daddr = fl4->daddr; |
347 | sk->sk_state = TCP_ESTABLISHED; | 350 | sk->sk_state = TCP_ESTABLISHED; |
348 | inet->inet_id = jiffies; | 351 | inet->inet_id = jiffies; |
349 | 352 | ||
@@ -356,6 +359,7 @@ static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len | |||
356 | 359 | ||
357 | rc = 0; | 360 | rc = 0; |
358 | out: | 361 | out: |
362 | release_sock(sk); | ||
359 | return rc; | 363 | return rc; |
360 | } | 364 | } |
361 | 365 | ||
@@ -416,23 +420,28 @@ static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m | |||
416 | int rc; | 420 | int rc; |
417 | struct l2tp_ip_sock *lsa = l2tp_ip_sk(sk); | 421 | struct l2tp_ip_sock *lsa = l2tp_ip_sk(sk); |
418 | struct inet_sock *inet = inet_sk(sk); | 422 | struct inet_sock *inet = inet_sk(sk); |
419 | struct ip_options *opt = inet->opt; | ||
420 | struct rtable *rt = NULL; | 423 | struct rtable *rt = NULL; |
424 | struct flowi4 *fl4; | ||
421 | int connected = 0; | 425 | int connected = 0; |
422 | __be32 daddr; | 426 | __be32 daddr; |
423 | 427 | ||
428 | lock_sock(sk); | ||
429 | |||
430 | rc = -ENOTCONN; | ||
424 | if (sock_flag(sk, SOCK_DEAD)) | 431 | if (sock_flag(sk, SOCK_DEAD)) |
425 | return -ENOTCONN; | 432 | goto out; |
426 | 433 | ||
427 | /* Get and verify the address. */ | 434 | /* Get and verify the address. */ |
428 | if (msg->msg_name) { | 435 | if (msg->msg_name) { |
429 | struct sockaddr_l2tpip *lip = (struct sockaddr_l2tpip *) msg->msg_name; | 436 | struct sockaddr_l2tpip *lip = (struct sockaddr_l2tpip *) msg->msg_name; |
437 | rc = -EINVAL; | ||
430 | if (msg->msg_namelen < sizeof(*lip)) | 438 | if (msg->msg_namelen < sizeof(*lip)) |
431 | return -EINVAL; | 439 | goto out; |
432 | 440 | ||
433 | if (lip->l2tp_family != AF_INET) { | 441 | if (lip->l2tp_family != AF_INET) { |
442 | rc = -EAFNOSUPPORT; | ||
434 | if (lip->l2tp_family != AF_UNSPEC) | 443 | if (lip->l2tp_family != AF_UNSPEC) |
435 | return -EAFNOSUPPORT; | 444 | goto out; |
436 | } | 445 | } |
437 | 446 | ||
438 | daddr = lip->l2tp_addr.s_addr; | 447 | daddr = lip->l2tp_addr.s_addr; |
@@ -467,19 +476,27 @@ static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m | |||
467 | goto error; | 476 | goto error; |
468 | } | 477 | } |
469 | 478 | ||
479 | fl4 = &inet->cork.fl.u.ip4; | ||
470 | if (connected) | 480 | if (connected) |
471 | rt = (struct rtable *) __sk_dst_check(sk, 0); | 481 | rt = (struct rtable *) __sk_dst_check(sk, 0); |
472 | 482 | ||
473 | if (rt == NULL) { | 483 | if (rt == NULL) { |
484 | struct ip_options_rcu *inet_opt; | ||
485 | |||
486 | rcu_read_lock(); | ||
487 | inet_opt = rcu_dereference(inet->inet_opt); | ||
488 | |||
474 | /* Use correct destination address if we have options. */ | 489 | /* Use correct destination address if we have options. */ |
475 | if (opt && opt->srr) | 490 | if (inet_opt && inet_opt->opt.srr) |
476 | daddr = opt->faddr; | 491 | daddr = inet_opt->opt.faddr; |
492 | |||
493 | rcu_read_unlock(); | ||
477 | 494 | ||
478 | /* If this fails, retransmit mechanism of transport layer will | 495 | /* If this fails, retransmit mechanism of transport layer will |
479 | * keep trying until route appears or the connection times | 496 | * keep trying until route appears or the connection times |
480 | * itself out. | 497 | * itself out. |
481 | */ | 498 | */ |
482 | rt = ip_route_output_ports(sock_net(sk), sk, | 499 | rt = ip_route_output_ports(sock_net(sk), fl4, sk, |
483 | daddr, inet->inet_saddr, | 500 | daddr, inet->inet_saddr, |
484 | inet->inet_dport, inet->inet_sport, | 501 | inet->inet_dport, inet->inet_sport, |
485 | sk->sk_protocol, RT_CONN_FLAGS(sk), | 502 | 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 | |||
491 | skb_dst_set(skb, dst_clone(&rt->dst)); | 508 | skb_dst_set(skb, dst_clone(&rt->dst)); |
492 | 509 | ||
493 | /* Queue the packet to IP for output */ | 510 | /* Queue the packet to IP for output */ |
494 | rc = ip_queue_xmit(skb); | 511 | rc = ip_queue_xmit(skb, &inet->cork.fl); |
495 | 512 | ||
496 | error: | 513 | error: |
497 | /* Update stats */ | 514 | /* Update stats */ |
@@ -503,12 +520,15 @@ error: | |||
503 | lsa->tx_errors++; | 520 | lsa->tx_errors++; |
504 | } | 521 | } |
505 | 522 | ||
523 | out: | ||
524 | release_sock(sk); | ||
506 | return rc; | 525 | return rc; |
507 | 526 | ||
508 | no_route: | 527 | no_route: |
509 | IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); | 528 | IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); |
510 | kfree_skb(skb); | 529 | kfree_skb(skb); |
511 | return -EHOSTUNREACH; | 530 | rc = -EHOSTUNREACH; |
531 | goto out; | ||
512 | } | 532 | } |
513 | 533 | ||
514 | static int l2tp_ip_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | 534 | static int l2tp_ip_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, |