diff options
Diffstat (limited to 'net/sctp')
-rw-r--r-- | net/sctp/ipv6.c | 40 | ||||
-rw-r--r-- | net/sctp/sm_make_chunk.c | 4 | ||||
-rw-r--r-- | net/sctp/sm_sideeffect.c | 8 | ||||
-rw-r--r-- | net/sctp/socket.c | 2 | ||||
-rw-r--r-- | net/sctp/transport.c | 16 |
5 files changed, 46 insertions, 24 deletions
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 810427833bcd..91f479121c55 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -107,7 +107,7 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev, | |||
107 | if (addr) { | 107 | if (addr) { |
108 | addr->a.v6.sin6_family = AF_INET6; | 108 | addr->a.v6.sin6_family = AF_INET6; |
109 | addr->a.v6.sin6_port = 0; | 109 | addr->a.v6.sin6_port = 0; |
110 | ipv6_addr_copy(&addr->a.v6.sin6_addr, &ifa->addr); | 110 | addr->a.v6.sin6_addr = ifa->addr; |
111 | addr->a.v6.sin6_scope_id = ifa->idev->dev->ifindex; | 111 | addr->a.v6.sin6_scope_id = ifa->idev->dev->ifindex; |
112 | addr->valid = 1; | 112 | addr->valid = 1; |
113 | spin_lock_bh(&sctp_local_addr_lock); | 113 | spin_lock_bh(&sctp_local_addr_lock); |
@@ -219,8 +219,8 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport) | |||
219 | /* Fill in the dest address from the route entry passed with the skb | 219 | /* Fill in the dest address from the route entry passed with the skb |
220 | * and the source address from the transport. | 220 | * and the source address from the transport. |
221 | */ | 221 | */ |
222 | ipv6_addr_copy(&fl6.daddr, &transport->ipaddr.v6.sin6_addr); | 222 | fl6.daddr = transport->ipaddr.v6.sin6_addr; |
223 | ipv6_addr_copy(&fl6.saddr, &transport->saddr.v6.sin6_addr); | 223 | fl6.saddr = transport->saddr.v6.sin6_addr; |
224 | 224 | ||
225 | fl6.flowlabel = np->flow_label; | 225 | fl6.flowlabel = np->flow_label; |
226 | IP6_ECN_flow_xmit(sk, fl6.flowlabel); | 226 | IP6_ECN_flow_xmit(sk, fl6.flowlabel); |
@@ -231,7 +231,7 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport) | |||
231 | 231 | ||
232 | if (np->opt && np->opt->srcrt) { | 232 | if (np->opt && np->opt->srcrt) { |
233 | struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; | 233 | struct rt0_hdr *rt0 = (struct rt0_hdr *) np->opt->srcrt; |
234 | ipv6_addr_copy(&fl6.daddr, rt0->addr); | 234 | fl6.daddr = *rt0->addr; |
235 | } | 235 | } |
236 | 236 | ||
237 | SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, src:%pI6 dst:%pI6\n", | 237 | SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, src:%pI6 dst:%pI6\n", |
@@ -265,7 +265,7 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, | |||
265 | sctp_scope_t scope; | 265 | sctp_scope_t scope; |
266 | 266 | ||
267 | memset(fl6, 0, sizeof(struct flowi6)); | 267 | memset(fl6, 0, sizeof(struct flowi6)); |
268 | ipv6_addr_copy(&fl6->daddr, &daddr->v6.sin6_addr); | 268 | fl6->daddr = daddr->v6.sin6_addr; |
269 | fl6->fl6_dport = daddr->v6.sin6_port; | 269 | fl6->fl6_dport = daddr->v6.sin6_port; |
270 | fl6->flowi6_proto = IPPROTO_SCTP; | 270 | fl6->flowi6_proto = IPPROTO_SCTP; |
271 | if (ipv6_addr_type(&daddr->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL) | 271 | if (ipv6_addr_type(&daddr->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL) |
@@ -277,7 +277,7 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, | |||
277 | fl6->fl6_sport = htons(asoc->base.bind_addr.port); | 277 | fl6->fl6_sport = htons(asoc->base.bind_addr.port); |
278 | 278 | ||
279 | if (saddr) { | 279 | if (saddr) { |
280 | ipv6_addr_copy(&fl6->saddr, &saddr->v6.sin6_addr); | 280 | fl6->saddr = saddr->v6.sin6_addr; |
281 | fl6->fl6_sport = saddr->v6.sin6_port; | 281 | fl6->fl6_sport = saddr->v6.sin6_port; |
282 | SCTP_DEBUG_PRINTK("SRC=%pI6 - ", &fl6->saddr); | 282 | SCTP_DEBUG_PRINTK("SRC=%pI6 - ", &fl6->saddr); |
283 | } | 283 | } |
@@ -334,7 +334,7 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, | |||
334 | } | 334 | } |
335 | rcu_read_unlock(); | 335 | rcu_read_unlock(); |
336 | if (baddr) { | 336 | if (baddr) { |
337 | ipv6_addr_copy(&fl6->saddr, &baddr->v6.sin6_addr); | 337 | fl6->saddr = baddr->v6.sin6_addr; |
338 | fl6->fl6_sport = baddr->v6.sin6_port; | 338 | fl6->fl6_sport = baddr->v6.sin6_port; |
339 | dst = ip6_dst_lookup_flow(sk, fl6, NULL, false); | 339 | dst = ip6_dst_lookup_flow(sk, fl6, NULL, false); |
340 | } | 340 | } |
@@ -375,7 +375,7 @@ static void sctp_v6_get_saddr(struct sctp_sock *sk, | |||
375 | 375 | ||
376 | if (t->dst) { | 376 | if (t->dst) { |
377 | saddr->v6.sin6_family = AF_INET6; | 377 | saddr->v6.sin6_family = AF_INET6; |
378 | ipv6_addr_copy(&saddr->v6.sin6_addr, &fl6->saddr); | 378 | saddr->v6.sin6_addr = fl6->saddr; |
379 | } | 379 | } |
380 | } | 380 | } |
381 | 381 | ||
@@ -400,7 +400,7 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist, | |||
400 | if (addr) { | 400 | if (addr) { |
401 | addr->a.v6.sin6_family = AF_INET6; | 401 | addr->a.v6.sin6_family = AF_INET6; |
402 | addr->a.v6.sin6_port = 0; | 402 | addr->a.v6.sin6_port = 0; |
403 | ipv6_addr_copy(&addr->a.v6.sin6_addr, &ifp->addr); | 403 | addr->a.v6.sin6_addr = ifp->addr; |
404 | addr->a.v6.sin6_scope_id = dev->ifindex; | 404 | addr->a.v6.sin6_scope_id = dev->ifindex; |
405 | addr->valid = 1; | 405 | addr->valid = 1; |
406 | INIT_LIST_HEAD(&addr->list); | 406 | INIT_LIST_HEAD(&addr->list); |
@@ -416,7 +416,6 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist, | |||
416 | static void sctp_v6_from_skb(union sctp_addr *addr,struct sk_buff *skb, | 416 | static void sctp_v6_from_skb(union sctp_addr *addr,struct sk_buff *skb, |
417 | int is_saddr) | 417 | int is_saddr) |
418 | { | 418 | { |
419 | void *from; | ||
420 | __be16 *port; | 419 | __be16 *port; |
421 | struct sctphdr *sh; | 420 | struct sctphdr *sh; |
422 | 421 | ||
@@ -428,12 +427,11 @@ static void sctp_v6_from_skb(union sctp_addr *addr,struct sk_buff *skb, | |||
428 | sh = sctp_hdr(skb); | 427 | sh = sctp_hdr(skb); |
429 | if (is_saddr) { | 428 | if (is_saddr) { |
430 | *port = sh->source; | 429 | *port = sh->source; |
431 | from = &ipv6_hdr(skb)->saddr; | 430 | addr->v6.sin6_addr = ipv6_hdr(skb)->saddr; |
432 | } else { | 431 | } else { |
433 | *port = sh->dest; | 432 | *port = sh->dest; |
434 | from = &ipv6_hdr(skb)->daddr; | 433 | addr->v6.sin6_addr = ipv6_hdr(skb)->daddr; |
435 | } | 434 | } |
436 | ipv6_addr_copy(&addr->v6.sin6_addr, from); | ||
437 | } | 435 | } |
438 | 436 | ||
439 | /* Initialize an sctp_addr from a socket. */ | 437 | /* Initialize an sctp_addr from a socket. */ |
@@ -441,7 +439,7 @@ static void sctp_v6_from_sk(union sctp_addr *addr, struct sock *sk) | |||
441 | { | 439 | { |
442 | addr->v6.sin6_family = AF_INET6; | 440 | addr->v6.sin6_family = AF_INET6; |
443 | addr->v6.sin6_port = 0; | 441 | addr->v6.sin6_port = 0; |
444 | ipv6_addr_copy(&addr->v6.sin6_addr, &inet6_sk(sk)->rcv_saddr); | 442 | addr->v6.sin6_addr = inet6_sk(sk)->rcv_saddr; |
445 | } | 443 | } |
446 | 444 | ||
447 | /* Initialize sk->sk_rcv_saddr from sctp_addr. */ | 445 | /* Initialize sk->sk_rcv_saddr from sctp_addr. */ |
@@ -454,7 +452,7 @@ static void sctp_v6_to_sk_saddr(union sctp_addr *addr, struct sock *sk) | |||
454 | inet6_sk(sk)->rcv_saddr.s6_addr32[3] = | 452 | inet6_sk(sk)->rcv_saddr.s6_addr32[3] = |
455 | addr->v4.sin_addr.s_addr; | 453 | addr->v4.sin_addr.s_addr; |
456 | } else { | 454 | } else { |
457 | ipv6_addr_copy(&inet6_sk(sk)->rcv_saddr, &addr->v6.sin6_addr); | 455 | inet6_sk(sk)->rcv_saddr = addr->v6.sin6_addr; |
458 | } | 456 | } |
459 | } | 457 | } |
460 | 458 | ||
@@ -467,7 +465,7 @@ static void sctp_v6_to_sk_daddr(union sctp_addr *addr, struct sock *sk) | |||
467 | inet6_sk(sk)->daddr.s6_addr32[2] = htonl(0x0000ffff); | 465 | inet6_sk(sk)->daddr.s6_addr32[2] = htonl(0x0000ffff); |
468 | inet6_sk(sk)->daddr.s6_addr32[3] = addr->v4.sin_addr.s_addr; | 466 | inet6_sk(sk)->daddr.s6_addr32[3] = addr->v4.sin_addr.s_addr; |
469 | } else { | 467 | } else { |
470 | ipv6_addr_copy(&inet6_sk(sk)->daddr, &addr->v6.sin6_addr); | 468 | inet6_sk(sk)->daddr = addr->v6.sin6_addr; |
471 | } | 469 | } |
472 | } | 470 | } |
473 | 471 | ||
@@ -479,7 +477,7 @@ static void sctp_v6_from_addr_param(union sctp_addr *addr, | |||
479 | addr->v6.sin6_family = AF_INET6; | 477 | addr->v6.sin6_family = AF_INET6; |
480 | addr->v6.sin6_port = port; | 478 | addr->v6.sin6_port = port; |
481 | addr->v6.sin6_flowinfo = 0; /* BUG */ | 479 | addr->v6.sin6_flowinfo = 0; /* BUG */ |
482 | ipv6_addr_copy(&addr->v6.sin6_addr, ¶m->v6.addr); | 480 | addr->v6.sin6_addr = param->v6.addr; |
483 | addr->v6.sin6_scope_id = iif; | 481 | addr->v6.sin6_scope_id = iif; |
484 | } | 482 | } |
485 | 483 | ||
@@ -493,7 +491,7 @@ static int sctp_v6_to_addr_param(const union sctp_addr *addr, | |||
493 | 491 | ||
494 | param->v6.param_hdr.type = SCTP_PARAM_IPV6_ADDRESS; | 492 | param->v6.param_hdr.type = SCTP_PARAM_IPV6_ADDRESS; |
495 | param->v6.param_hdr.length = htons(length); | 493 | param->v6.param_hdr.length = htons(length); |
496 | ipv6_addr_copy(¶m->v6.addr, &addr->v6.sin6_addr); | 494 | param->v6.addr = addr->v6.sin6_addr; |
497 | 495 | ||
498 | return length; | 496 | return length; |
499 | } | 497 | } |
@@ -504,7 +502,7 @@ static void sctp_v6_to_addr(union sctp_addr *addr, struct in6_addr *saddr, | |||
504 | { | 502 | { |
505 | addr->sa.sa_family = AF_INET6; | 503 | addr->sa.sa_family = AF_INET6; |
506 | addr->v6.sin6_port = port; | 504 | addr->v6.sin6_port = port; |
507 | ipv6_addr_copy(&addr->v6.sin6_addr, saddr); | 505 | addr->v6.sin6_addr = *saddr; |
508 | } | 506 | } |
509 | 507 | ||
510 | /* Compare addresses exactly. | 508 | /* Compare addresses exactly. |
@@ -759,7 +757,7 @@ static void sctp_inet6_event_msgname(struct sctp_ulpevent *event, | |||
759 | } | 757 | } |
760 | 758 | ||
761 | sin6from = &asoc->peer.primary_addr.v6; | 759 | sin6from = &asoc->peer.primary_addr.v6; |
762 | ipv6_addr_copy(&sin6->sin6_addr, &sin6from->sin6_addr); | 760 | sin6->sin6_addr = sin6from->sin6_addr; |
763 | if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) | 761 | if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) |
764 | sin6->sin6_scope_id = sin6from->sin6_scope_id; | 762 | sin6->sin6_scope_id = sin6from->sin6_scope_id; |
765 | } | 763 | } |
@@ -787,7 +785,7 @@ static void sctp_inet6_skb_msgname(struct sk_buff *skb, char *msgname, | |||
787 | } | 785 | } |
788 | 786 | ||
789 | /* Otherwise, just copy the v6 address. */ | 787 | /* Otherwise, just copy the v6 address. */ |
790 | ipv6_addr_copy(&sin6->sin6_addr, &ipv6_hdr(skb)->saddr); | 788 | sin6->sin6_addr = ipv6_hdr(skb)->saddr; |
791 | if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) { | 789 | if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) { |
792 | struct sctp_ulpevent *ev = sctp_skb2event(skb); | 790 | struct sctp_ulpevent *ev = sctp_skb2event(skb); |
793 | sin6->sin6_scope_id = ev->iif; | 791 | sin6->sin6_scope_id = ev->iif; |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 0121e0ab0351..a85eeeb55dd0 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -3400,8 +3400,10 @@ int sctp_process_asconf_ack(struct sctp_association *asoc, | |||
3400 | asconf_len -= length; | 3400 | asconf_len -= length; |
3401 | } | 3401 | } |
3402 | 3402 | ||
3403 | if (no_err && asoc->src_out_of_asoc_ok) | 3403 | if (no_err && asoc->src_out_of_asoc_ok) { |
3404 | asoc->src_out_of_asoc_ok = 0; | 3404 | asoc->src_out_of_asoc_ok = 0; |
3405 | sctp_transport_immediate_rtx(asoc->peer.primary_path); | ||
3406 | } | ||
3405 | 3407 | ||
3406 | /* Free the cached last sent asconf chunk. */ | 3408 | /* Free the cached last sent asconf chunk. */ |
3407 | list_del_init(&asconf->transmitted_list); | 3409 | list_del_init(&asconf->transmitted_list); |
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index 76388b083f28..1ff51c9d18d5 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -666,6 +666,7 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds, | |||
666 | struct sctp_chunk *chunk) | 666 | struct sctp_chunk *chunk) |
667 | { | 667 | { |
668 | sctp_sender_hb_info_t *hbinfo; | 668 | sctp_sender_hb_info_t *hbinfo; |
669 | int was_unconfirmed = 0; | ||
669 | 670 | ||
670 | /* 8.3 Upon the receipt of the HEARTBEAT ACK, the sender of the | 671 | /* 8.3 Upon the receipt of the HEARTBEAT ACK, the sender of the |
671 | * HEARTBEAT should clear the error counter of the destination | 672 | * HEARTBEAT should clear the error counter of the destination |
@@ -692,9 +693,11 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds, | |||
692 | /* Mark the destination transport address as active if it is not so | 693 | /* Mark the destination transport address as active if it is not so |
693 | * marked. | 694 | * marked. |
694 | */ | 695 | */ |
695 | if ((t->state == SCTP_INACTIVE) || (t->state == SCTP_UNCONFIRMED)) | 696 | if ((t->state == SCTP_INACTIVE) || (t->state == SCTP_UNCONFIRMED)) { |
697 | was_unconfirmed = 1; | ||
696 | sctp_assoc_control_transport(asoc, t, SCTP_TRANSPORT_UP, | 698 | sctp_assoc_control_transport(asoc, t, SCTP_TRANSPORT_UP, |
697 | SCTP_HEARTBEAT_SUCCESS); | 699 | SCTP_HEARTBEAT_SUCCESS); |
700 | } | ||
698 | 701 | ||
699 | /* The receiver of the HEARTBEAT ACK should also perform an | 702 | /* The receiver of the HEARTBEAT ACK should also perform an |
700 | * RTT measurement for that destination transport address | 703 | * RTT measurement for that destination transport address |
@@ -712,6 +715,9 @@ static void sctp_cmd_transport_on(sctp_cmd_seq_t *cmds, | |||
712 | /* Update the heartbeat timer. */ | 715 | /* Update the heartbeat timer. */ |
713 | if (!mod_timer(&t->hb_timer, sctp_transport_timeout(t))) | 716 | if (!mod_timer(&t->hb_timer, sctp_transport_timeout(t))) |
714 | sctp_transport_hold(t); | 717 | sctp_transport_hold(t); |
718 | |||
719 | if (was_unconfirmed && asoc->peer.transport_count == 1) | ||
720 | sctp_transport_immediate_rtx(t); | ||
715 | } | 721 | } |
716 | 722 | ||
717 | 723 | ||
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 13bf5fcdbff1..d56c07a3d435 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -804,7 +804,7 @@ static int sctp_send_asconf_del_ip(struct sock *sk, | |||
804 | struct sockaddr_in6 *sin6; | 804 | struct sockaddr_in6 *sin6; |
805 | 805 | ||
806 | sin6 = (struct sockaddr_in6 *)addrs; | 806 | sin6 = (struct sockaddr_in6 *)addrs; |
807 | ipv6_addr_copy(&asoc->asconf_addr_del_pending->v6.sin6_addr, &sin6->sin6_addr); | 807 | asoc->asconf_addr_del_pending->v6.sin6_addr = sin6->sin6_addr; |
808 | } | 808 | } |
809 | SCTP_DEBUG_PRINTK_IPADDR("send_asconf_del_ip: keep the last address asoc: %p ", | 809 | SCTP_DEBUG_PRINTK_IPADDR("send_asconf_del_ip: keep the last address asoc: %p ", |
810 | " at %p\n", asoc, asoc->asconf_addr_del_pending, | 810 | " at %p\n", asoc, asoc->asconf_addr_del_pending, |
diff --git a/net/sctp/transport.c b/net/sctp/transport.c index 394c57ca2f54..3889330b7b04 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c | |||
@@ -641,3 +641,19 @@ void sctp_transport_reset(struct sctp_transport *t) | |||
641 | t->cacc.next_tsn_at_change = 0; | 641 | t->cacc.next_tsn_at_change = 0; |
642 | t->cacc.cacc_saw_newack = 0; | 642 | t->cacc.cacc_saw_newack = 0; |
643 | } | 643 | } |
644 | |||
645 | /* Schedule retransmission on the given transport */ | ||
646 | void sctp_transport_immediate_rtx(struct sctp_transport *t) | ||
647 | { | ||
648 | /* Stop pending T3_rtx_timer */ | ||
649 | if (timer_pending(&t->T3_rtx_timer)) { | ||
650 | (void)del_timer(&t->T3_rtx_timer); | ||
651 | sctp_transport_put(t); | ||
652 | } | ||
653 | sctp_retransmit(&t->asoc->outqueue, t, SCTP_RTXR_T3_RTX); | ||
654 | if (!timer_pending(&t->T3_rtx_timer)) { | ||
655 | if (!mod_timer(&t->T3_rtx_timer, jiffies + t->rto)) | ||
656 | sctp_transport_hold(t); | ||
657 | } | ||
658 | return; | ||
659 | } | ||