aboutsummaryrefslogtreecommitdiffstats
path: root/net/dccp/ipv4.c
diff options
context:
space:
mode:
authorGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
committerGlenn Elliott <gelliott@cs.unc.edu>2012-03-04 19:47:13 -0500
commitc71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch)
treeecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /net/dccp/ipv4.c
parentea53c912f8a86a8567697115b6a0d8152beee5c8 (diff)
parent6a00f206debf8a5c8899055726ad127dbeeed098 (diff)
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts: litmus/sched_cedf.c
Diffstat (limited to 'net/dccp/ipv4.c')
-rw-r--r--net/dccp/ipv4.c102
1 files changed, 58 insertions, 44 deletions
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c
index d4a166f0f391..8c36adfd1919 100644
--- a/net/dccp/ipv4.c
+++ b/net/dccp/ipv4.c
@@ -40,13 +40,15 @@
40 40
41int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) 41int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
42{ 42{
43 const struct sockaddr_in *usin = (struct sockaddr_in *)uaddr;
43 struct inet_sock *inet = inet_sk(sk); 44 struct inet_sock *inet = inet_sk(sk);
44 struct dccp_sock *dp = dccp_sk(sk); 45 struct dccp_sock *dp = dccp_sk(sk);
45 const struct sockaddr_in *usin = (struct sockaddr_in *)uaddr; 46 __be16 orig_sport, orig_dport;
46 struct rtable *rt;
47 __be32 daddr, nexthop; 47 __be32 daddr, nexthop;
48 int tmp; 48 struct flowi4 *fl4;
49 struct rtable *rt;
49 int err; 50 int err;
51 struct ip_options_rcu *inet_opt;
50 52
51 dp->dccps_role = DCCP_ROLE_CLIENT; 53 dp->dccps_role = DCCP_ROLE_CLIENT;
52 54
@@ -57,37 +59,43 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
57 return -EAFNOSUPPORT; 59 return -EAFNOSUPPORT;
58 60
59 nexthop = daddr = usin->sin_addr.s_addr; 61 nexthop = daddr = usin->sin_addr.s_addr;
60 if (inet->opt != NULL && inet->opt->srr) { 62
63 inet_opt = rcu_dereference_protected(inet->inet_opt,
64 sock_owned_by_user(sk));
65 if (inet_opt != NULL && inet_opt->opt.srr) {
61 if (daddr == 0) 66 if (daddr == 0)
62 return -EINVAL; 67 return -EINVAL;
63 nexthop = inet->opt->faddr; 68 nexthop = inet_opt->opt.faddr;
64 } 69 }
65 70
66 tmp = ip_route_connect(&rt, nexthop, inet->inet_saddr, 71 orig_sport = inet->inet_sport;
67 RT_CONN_FLAGS(sk), sk->sk_bound_dev_if, 72 orig_dport = usin->sin_port;
68 IPPROTO_DCCP, 73 fl4 = &inet->cork.fl.u.ip4;
69 inet->inet_sport, usin->sin_port, sk, 1); 74 rt = ip_route_connect(fl4, nexthop, inet->inet_saddr,
70 if (tmp < 0) 75 RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
71 return tmp; 76 IPPROTO_DCCP,
77 orig_sport, orig_dport, sk, true);
78 if (IS_ERR(rt))
79 return PTR_ERR(rt);
72 80
73 if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) { 81 if (rt->rt_flags & (RTCF_MULTICAST | RTCF_BROADCAST)) {
74 ip_rt_put(rt); 82 ip_rt_put(rt);
75 return -ENETUNREACH; 83 return -ENETUNREACH;
76 } 84 }
77 85
78 if (inet->opt == NULL || !inet->opt->srr) 86 if (inet_opt == NULL || !inet_opt->opt.srr)
79 daddr = rt->rt_dst; 87 daddr = fl4->daddr;
80 88
81 if (inet->inet_saddr == 0) 89 if (inet->inet_saddr == 0)
82 inet->inet_saddr = rt->rt_src; 90 inet->inet_saddr = fl4->saddr;
83 inet->inet_rcv_saddr = inet->inet_saddr; 91 inet->inet_rcv_saddr = inet->inet_saddr;
84 92
85 inet->inet_dport = usin->sin_port; 93 inet->inet_dport = usin->sin_port;
86 inet->inet_daddr = daddr; 94 inet->inet_daddr = daddr;
87 95
88 inet_csk(sk)->icsk_ext_hdr_len = 0; 96 inet_csk(sk)->icsk_ext_hdr_len = 0;
89 if (inet->opt != NULL) 97 if (inet_opt)
90 inet_csk(sk)->icsk_ext_hdr_len = inet->opt->optlen; 98 inet_csk(sk)->icsk_ext_hdr_len = inet_opt->opt.optlen;
91 /* 99 /*
92 * Socket identity is still unknown (sport may be zero). 100 * Socket identity is still unknown (sport may be zero).
93 * However we set state to DCCP_REQUESTING and not releasing socket 101 * However we set state to DCCP_REQUESTING and not releasing socket
@@ -99,11 +107,12 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
99 if (err != 0) 107 if (err != 0)
100 goto failure; 108 goto failure;
101 109
102 err = ip_route_newports(&rt, IPPROTO_DCCP, inet->inet_sport, 110 rt = ip_route_newports(fl4, rt, orig_sport, orig_dport,
103 inet->inet_dport, sk); 111 inet->inet_sport, inet->inet_dport, sk);
104 if (err != 0) 112 if (IS_ERR(rt)) {
113 rt = NULL;
105 goto failure; 114 goto failure;
106 115 }
107 /* OK, now commit destination to socket. */ 116 /* OK, now commit destination to socket. */
108 sk_setup_caps(sk, &rt->dst); 117 sk_setup_caps(sk, &rt->dst);
109 118
@@ -387,39 +396,44 @@ struct sock *dccp_v4_request_recv_sock(struct sock *sk, struct sk_buff *skb,
387 if (sk_acceptq_is_full(sk)) 396 if (sk_acceptq_is_full(sk))
388 goto exit_overflow; 397 goto exit_overflow;
389 398
390 if (dst == NULL && (dst = inet_csk_route_req(sk, req)) == NULL)
391 goto exit;
392
393 newsk = dccp_create_openreq_child(sk, req, skb); 399 newsk = dccp_create_openreq_child(sk, req, skb);
394 if (newsk == NULL) 400 if (newsk == NULL)
395 goto exit; 401 goto exit_nonewsk;
396
397 sk_setup_caps(newsk, dst);
398 402
399 newinet = inet_sk(newsk); 403 newinet = inet_sk(newsk);
400 ireq = inet_rsk(req); 404 ireq = inet_rsk(req);
401 newinet->inet_daddr = ireq->rmt_addr; 405 newinet->inet_daddr = ireq->rmt_addr;
402 newinet->inet_rcv_saddr = ireq->loc_addr; 406 newinet->inet_rcv_saddr = ireq->loc_addr;
403 newinet->inet_saddr = ireq->loc_addr; 407 newinet->inet_saddr = ireq->loc_addr;
404 newinet->opt = ireq->opt; 408 newinet->inet_opt = ireq->opt;
405 ireq->opt = NULL; 409 ireq->opt = NULL;
406 newinet->mc_index = inet_iif(skb); 410 newinet->mc_index = inet_iif(skb);
407 newinet->mc_ttl = ip_hdr(skb)->ttl; 411 newinet->mc_ttl = ip_hdr(skb)->ttl;
408 newinet->inet_id = jiffies; 412 newinet->inet_id = jiffies;
409 413
414 if (dst == NULL && (dst = inet_csk_route_child_sock(sk, newsk, req)) == NULL)
415 goto put_and_exit;
416
417 sk_setup_caps(newsk, dst);
418
410 dccp_sync_mss(newsk, dst_mtu(dst)); 419 dccp_sync_mss(newsk, dst_mtu(dst));
411 420
421 if (__inet_inherit_port(sk, newsk) < 0)
422 goto put_and_exit;
412 __inet_hash_nolisten(newsk, NULL); 423 __inet_hash_nolisten(newsk, NULL);
413 __inet_inherit_port(sk, newsk);
414 424
415 return newsk; 425 return newsk;
416 426
417exit_overflow: 427exit_overflow:
418 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS); 428 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS);
429exit_nonewsk:
430 dst_release(dst);
419exit: 431exit:
420 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); 432 NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS);
421 dst_release(dst);
422 return NULL; 433 return NULL;
434put_and_exit:
435 sock_put(newsk);
436 goto exit;
423} 437}
424 438
425EXPORT_SYMBOL_GPL(dccp_v4_request_recv_sock); 439EXPORT_SYMBOL_GPL(dccp_v4_request_recv_sock);
@@ -457,20 +471,19 @@ static struct dst_entry* dccp_v4_route_skb(struct net *net, struct sock *sk,
457 struct sk_buff *skb) 471 struct sk_buff *skb)
458{ 472{
459 struct rtable *rt; 473 struct rtable *rt;
460 struct flowi fl = { .oif = skb_rtable(skb)->rt_iif, 474 struct flowi4 fl4 = {
461 .nl_u = { .ip4_u = 475 .flowi4_oif = skb_rtable(skb)->rt_iif,
462 { .daddr = ip_hdr(skb)->saddr, 476 .daddr = ip_hdr(skb)->saddr,
463 .saddr = ip_hdr(skb)->daddr, 477 .saddr = ip_hdr(skb)->daddr,
464 .tos = RT_CONN_FLAGS(sk) } }, 478 .flowi4_tos = RT_CONN_FLAGS(sk),
465 .proto = sk->sk_protocol, 479 .flowi4_proto = sk->sk_protocol,
466 .uli_u = { .ports = 480 .fl4_sport = dccp_hdr(skb)->dccph_dport,
467 { .sport = dccp_hdr(skb)->dccph_dport, 481 .fl4_dport = dccp_hdr(skb)->dccph_sport,
468 .dport = dccp_hdr(skb)->dccph_sport } 482 };
469 } 483
470 }; 484 security_skb_classify_flow(skb, flowi4_to_flowi(&fl4));
471 485 rt = ip_route_output_flow(net, &fl4, sk);
472 security_skb_classify_flow(skb, &fl); 486 if (IS_ERR(rt)) {
473 if (ip_route_output_flow(net, &rt, &fl, sk, 0)) {
474 IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES); 487 IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES);
475 return NULL; 488 return NULL;
476 } 489 }
@@ -484,8 +497,9 @@ static int dccp_v4_send_response(struct sock *sk, struct request_sock *req,
484 int err = -1; 497 int err = -1;
485 struct sk_buff *skb; 498 struct sk_buff *skb;
486 struct dst_entry *dst; 499 struct dst_entry *dst;
500 struct flowi4 fl4;
487 501
488 dst = inet_csk_route_req(sk, req); 502 dst = inet_csk_route_req(sk, &fl4, req);
489 if (dst == NULL) 503 if (dst == NULL)
490 goto out; 504 goto out;
491 505