aboutsummaryrefslogtreecommitdiffstats
path: root/net/sctp
diff options
context:
space:
mode:
Diffstat (limited to 'net/sctp')
-rw-r--r--net/sctp/ipv6.c40
-rw-r--r--net/sctp/sm_make_chunk.c4
-rw-r--r--net/sctp/sm_sideeffect.c8
-rw-r--r--net/sctp/socket.c2
-rw-r--r--net/sctp/transport.c16
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,
416static void sctp_v6_from_skb(union sctp_addr *addr,struct sk_buff *skb, 416static 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, &param->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(&param->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 */
646void 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}