diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /net/dccp/ipv4.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (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.c | 102 |
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 | ||
41 | int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | 41 | int 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 | ||
417 | exit_overflow: | 427 | exit_overflow: |
418 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS); | 428 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS); |
429 | exit_nonewsk: | ||
430 | dst_release(dst); | ||
419 | exit: | 431 | exit: |
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; |
434 | put_and_exit: | ||
435 | sock_put(newsk); | ||
436 | goto exit; | ||
423 | } | 437 | } |
424 | 438 | ||
425 | EXPORT_SYMBOL_GPL(dccp_v4_request_recv_sock); | 439 | EXPORT_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 | ||