diff options
-rw-r--r-- | include/net/sctp/structs.h | 14 | ||||
-rw-r--r-- | net/sctp/ipv6.c | 161 | ||||
-rw-r--r-- | net/sctp/protocol.c | 47 | ||||
-rw-r--r-- | net/sctp/socket.c | 2 | ||||
-rw-r--r-- | net/sctp/transport.c | 15 |
5 files changed, 112 insertions, 127 deletions
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h index 5c9bada51d2d..1d465d62f34f 100644 --- a/include/net/sctp/structs.h +++ b/include/net/sctp/structs.h | |||
@@ -566,17 +566,15 @@ struct sctp_af { | |||
566 | int __user *optlen); | 566 | int __user *optlen); |
567 | struct dst_entry *(*get_dst) (struct sctp_association *asoc, | 567 | struct dst_entry *(*get_dst) (struct sctp_association *asoc, |
568 | union sctp_addr *daddr, | 568 | union sctp_addr *daddr, |
569 | union sctp_addr *saddr); | 569 | union sctp_addr *saddr, |
570 | struct flowi *fl, | ||
571 | struct sock *sk); | ||
570 | void (*get_saddr) (struct sctp_sock *sk, | 572 | void (*get_saddr) (struct sctp_sock *sk, |
571 | struct sctp_association *asoc, | 573 | struct sctp_transport *t, |
572 | struct dst_entry *dst, | ||
573 | union sctp_addr *daddr, | 574 | union sctp_addr *daddr, |
574 | union sctp_addr *saddr); | 575 | struct flowi *fl); |
575 | void (*copy_addrlist) (struct list_head *, | 576 | void (*copy_addrlist) (struct list_head *, |
576 | struct net_device *); | 577 | struct net_device *); |
577 | void (*dst_saddr) (union sctp_addr *saddr, | ||
578 | struct dst_entry *dst, | ||
579 | __be16 port); | ||
580 | int (*cmp_addr) (const union sctp_addr *addr1, | 578 | int (*cmp_addr) (const union sctp_addr *addr1, |
581 | const union sctp_addr *addr2); | 579 | const union sctp_addr *addr2); |
582 | void (*addr_copy) (union sctp_addr *dst, | 580 | void (*addr_copy) (union sctp_addr *dst, |
@@ -1061,7 +1059,7 @@ void sctp_transport_set_owner(struct sctp_transport *, | |||
1061 | struct sctp_association *); | 1059 | struct sctp_association *); |
1062 | void sctp_transport_route(struct sctp_transport *, union sctp_addr *, | 1060 | void sctp_transport_route(struct sctp_transport *, union sctp_addr *, |
1063 | struct sctp_sock *); | 1061 | struct sctp_sock *); |
1064 | void sctp_transport_pmtu(struct sctp_transport *); | 1062 | void sctp_transport_pmtu(struct sctp_transport *, struct sock *sk); |
1065 | void sctp_transport_free(struct sctp_transport *); | 1063 | void sctp_transport_free(struct sctp_transport *); |
1066 | void sctp_transport_reset_timers(struct sctp_transport *); | 1064 | void sctp_transport_reset_timers(struct sctp_transport *); |
1067 | void sctp_transport_hold(struct sctp_transport *); | 1065 | void sctp_transport_hold(struct sctp_transport *); |
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 3a571d6614f9..51c048d256f5 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -82,6 +82,10 @@ | |||
82 | 82 | ||
83 | static inline int sctp_v6_addr_match_len(union sctp_addr *s1, | 83 | static inline int sctp_v6_addr_match_len(union sctp_addr *s1, |
84 | union sctp_addr *s2); | 84 | union sctp_addr *s2); |
85 | static void sctp_v6_to_addr(union sctp_addr *addr, struct in6_addr *saddr, | ||
86 | __be16 port); | ||
87 | static int sctp_v6_cmp_addr(const union sctp_addr *addr1, | ||
88 | const union sctp_addr *addr2); | ||
85 | 89 | ||
86 | /* Event handler for inet6 address addition/deletion events. | 90 | /* Event handler for inet6 address addition/deletion events. |
87 | * The sctp_local_addr_list needs to be protocted by a spin lock since | 91 | * The sctp_local_addr_list needs to be protocted by a spin lock since |
@@ -245,73 +249,99 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport) | |||
245 | */ | 249 | */ |
246 | static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc, | 250 | static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc, |
247 | union sctp_addr *daddr, | 251 | union sctp_addr *daddr, |
248 | union sctp_addr *saddr) | 252 | union sctp_addr *saddr, |
253 | struct flowi *fl, | ||
254 | struct sock *sk) | ||
249 | { | 255 | { |
250 | struct dst_entry *dst = NULL; | 256 | struct dst_entry *dst = NULL; |
251 | struct flowi6 fl6; | 257 | struct flowi6 *fl6 = &fl->u.ip6; |
252 | struct sctp_bind_addr *bp; | 258 | struct sctp_bind_addr *bp; |
253 | struct sctp_sockaddr_entry *laddr; | 259 | struct sctp_sockaddr_entry *laddr; |
254 | union sctp_addr *baddr = NULL; | 260 | union sctp_addr *baddr = NULL; |
261 | union sctp_addr dst_saddr; | ||
255 | __u8 matchlen = 0; | 262 | __u8 matchlen = 0; |
256 | __u8 bmatchlen; | 263 | __u8 bmatchlen; |
257 | sctp_scope_t scope; | 264 | sctp_scope_t scope; |
265 | int err = 0; | ||
258 | 266 | ||
259 | memset(&fl6, 0, sizeof(fl6)); | 267 | memset(fl6, 0, sizeof(struct flowi6)); |
260 | ipv6_addr_copy(&fl6.daddr, &daddr->v6.sin6_addr); | 268 | ipv6_addr_copy(&fl6->daddr, &daddr->v6.sin6_addr); |
261 | if (ipv6_addr_type(&daddr->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL) | 269 | if (ipv6_addr_type(&daddr->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL) |
262 | fl6.flowi6_oif = daddr->v6.sin6_scope_id; | 270 | fl6->flowi6_oif = daddr->v6.sin6_scope_id; |
263 | 271 | ||
264 | 272 | ||
265 | SCTP_DEBUG_PRINTK("%s: DST=%pI6 ", __func__, &fl6.daddr); | 273 | SCTP_DEBUG_PRINTK("%s: DST=%pI6 ", __func__, &fl6->daddr); |
266 | 274 | ||
267 | if (saddr) { | 275 | if (saddr) { |
268 | ipv6_addr_copy(&fl6.saddr, &saddr->v6.sin6_addr); | 276 | ipv6_addr_copy(&fl6->saddr, &saddr->v6.sin6_addr); |
269 | SCTP_DEBUG_PRINTK("SRC=%pI6 - ", &fl6.saddr); | 277 | SCTP_DEBUG_PRINTK("SRC=%pI6 - ", &fl6->saddr); |
270 | } | 278 | } |
271 | 279 | ||
272 | dst = ip6_route_output(&init_net, NULL, &fl6); | 280 | err = ip6_dst_lookup(sk, &dst, fl6); |
273 | if (!asoc || saddr) | 281 | if (!asoc || saddr) |
274 | goto out; | 282 | goto out; |
275 | 283 | ||
276 | if (dst->error) { | 284 | bp = &asoc->base.bind_addr; |
277 | dst_release(dst); | 285 | scope = sctp_scope(daddr); |
278 | dst = NULL; | 286 | /* ip6_dst_lookup has filled in the fl6->saddr for us. Check |
279 | bp = &asoc->base.bind_addr; | 287 | * to see if we can use it. |
280 | scope = sctp_scope(daddr); | 288 | */ |
281 | /* Walk through the bind address list and try to get a dst that | 289 | if (!err) { |
282 | * matches a bind address as the source address. | 290 | /* Walk through the bind address list and look for a bind |
291 | * address that matches the source address of the returned dst. | ||
283 | */ | 292 | */ |
293 | sctp_v6_to_addr(&dst_saddr, &fl6->saddr, htons(bp->port)); | ||
284 | rcu_read_lock(); | 294 | rcu_read_lock(); |
285 | list_for_each_entry_rcu(laddr, &bp->address_list, list) { | 295 | list_for_each_entry_rcu(laddr, &bp->address_list, list) { |
286 | if (!laddr->valid) | 296 | if (!laddr->valid || (laddr->state != SCTP_ADDR_SRC)) |
287 | continue; | 297 | continue; |
288 | if ((laddr->state == SCTP_ADDR_SRC) && | 298 | |
289 | (laddr->a.sa.sa_family == AF_INET6) && | 299 | /* Do not compare against v4 addrs */ |
290 | (scope <= sctp_scope(&laddr->a))) { | 300 | if ((laddr->a.sa.sa_family == AF_INET6) && |
291 | bmatchlen = sctp_v6_addr_match_len(daddr, | 301 | (sctp_v6_cmp_addr(&dst_saddr, &laddr->a))) { |
292 | &laddr->a); | 302 | rcu_read_unlock(); |
293 | if (!baddr || (matchlen < bmatchlen)) { | 303 | goto out; |
294 | baddr = &laddr->a; | ||
295 | matchlen = bmatchlen; | ||
296 | } | ||
297 | } | 304 | } |
298 | } | 305 | } |
299 | rcu_read_unlock(); | 306 | rcu_read_unlock(); |
300 | if (baddr) { | 307 | /* None of the bound addresses match the source address of the |
301 | ipv6_addr_copy(&fl6.saddr, &baddr->v6.sin6_addr); | 308 | * dst. So release it. |
302 | dst = ip6_route_output(&init_net, NULL, &fl6); | 309 | */ |
310 | dst_release(dst); | ||
311 | dst = NULL; | ||
312 | } | ||
313 | |||
314 | /* Walk through the bind address list and try to get the | ||
315 | * best source address for a given destination. | ||
316 | */ | ||
317 | rcu_read_lock(); | ||
318 | list_for_each_entry_rcu(laddr, &bp->address_list, list) { | ||
319 | if (!laddr->valid && laddr->state != SCTP_ADDR_SRC) | ||
320 | continue; | ||
321 | if ((laddr->a.sa.sa_family == AF_INET6) && | ||
322 | (scope <= sctp_scope(&laddr->a))) { | ||
323 | bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a); | ||
324 | if (!baddr || (matchlen < bmatchlen)) { | ||
325 | baddr = &laddr->a; | ||
326 | matchlen = bmatchlen; | ||
327 | } | ||
303 | } | 328 | } |
304 | } | 329 | } |
330 | rcu_read_unlock(); | ||
331 | if (baddr) { | ||
332 | ipv6_addr_copy(&fl6->saddr, &baddr->v6.sin6_addr); | ||
333 | err = ip6_dst_lookup(sk, &dst, fl6); | ||
334 | } | ||
335 | |||
305 | out: | 336 | out: |
306 | if (!dst->error) { | 337 | if (!err) { |
307 | struct rt6_info *rt; | 338 | struct rt6_info *rt; |
308 | rt = (struct rt6_info *)dst; | 339 | rt = (struct rt6_info *)dst; |
309 | SCTP_DEBUG_PRINTK("rt6_dst:%pI6 rt6_src:%pI6\n", | 340 | SCTP_DEBUG_PRINTK("rt6_dst:%pI6 rt6_src:%pI6\n", |
310 | &rt->rt6i_dst.addr, &rt->rt6i_src.addr); | 341 | &rt->rt6i_dst.addr, &fl6->saddr); |
311 | return dst; | 342 | return dst; |
312 | } | 343 | } |
313 | SCTP_DEBUG_PRINTK("NO ROUTE\n"); | 344 | SCTP_DEBUG_PRINTK("NO ROUTE\n"); |
314 | dst_release(dst); | ||
315 | return NULL; | 345 | return NULL; |
316 | } | 346 | } |
317 | 347 | ||
@@ -328,64 +358,21 @@ static inline int sctp_v6_addr_match_len(union sctp_addr *s1, | |||
328 | * and asoc's bind address list. | 358 | * and asoc's bind address list. |
329 | */ | 359 | */ |
330 | static void sctp_v6_get_saddr(struct sctp_sock *sk, | 360 | static void sctp_v6_get_saddr(struct sctp_sock *sk, |
331 | struct sctp_association *asoc, | 361 | struct sctp_transport *t, |
332 | struct dst_entry *dst, | ||
333 | union sctp_addr *daddr, | 362 | union sctp_addr *daddr, |
334 | union sctp_addr *saddr) | 363 | struct flowi *fl) |
335 | { | 364 | { |
336 | struct sctp_bind_addr *bp; | 365 | struct flowi6 *fl6 = &fl->u.ip6; |
337 | struct sctp_sockaddr_entry *laddr; | 366 | union sctp_addr *saddr = &t->saddr; |
338 | sctp_scope_t scope; | ||
339 | union sctp_addr *baddr = NULL; | ||
340 | __u8 matchlen = 0; | ||
341 | __u8 bmatchlen; | ||
342 | 367 | ||
343 | SCTP_DEBUG_PRINTK("%s: asoc:%p dst:%p daddr:%pI6 ", | 368 | SCTP_DEBUG_PRINTK("%s: asoc:%p dst:%p daddr:%pI6 ", |
344 | __func__, asoc, dst, &daddr->v6.sin6_addr); | 369 | __func__, t->asoc, t->dst, &daddr->v6.sin6_addr); |
345 | |||
346 | if (!asoc) { | ||
347 | ipv6_dev_get_saddr(sock_net(sctp_opt2sk(sk)), | ||
348 | dst ? ip6_dst_idev(dst)->dev : NULL, | ||
349 | &daddr->v6.sin6_addr, | ||
350 | inet6_sk(&sk->inet.sk)->srcprefs, | ||
351 | &saddr->v6.sin6_addr); | ||
352 | SCTP_DEBUG_PRINTK("saddr from ipv6_get_saddr: %pI6\n", | ||
353 | &saddr->v6.sin6_addr); | ||
354 | return; | ||
355 | } | ||
356 | |||
357 | scope = sctp_scope(daddr); | ||
358 | 370 | ||
359 | bp = &asoc->base.bind_addr; | ||
360 | |||
361 | /* Go through the bind address list and find the best source address | ||
362 | * that matches the scope of the destination address. | ||
363 | */ | ||
364 | rcu_read_lock(); | ||
365 | list_for_each_entry_rcu(laddr, &bp->address_list, list) { | ||
366 | if (!laddr->valid) | ||
367 | continue; | ||
368 | if ((laddr->state == SCTP_ADDR_SRC) && | ||
369 | (laddr->a.sa.sa_family == AF_INET6) && | ||
370 | (scope <= sctp_scope(&laddr->a))) { | ||
371 | bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a); | ||
372 | if (!baddr || (matchlen < bmatchlen)) { | ||
373 | baddr = &laddr->a; | ||
374 | matchlen = bmatchlen; | ||
375 | } | ||
376 | } | ||
377 | } | ||
378 | 371 | ||
379 | if (baddr) { | 372 | if (t->dst) { |
380 | memcpy(saddr, baddr, sizeof(union sctp_addr)); | 373 | saddr->v6.sin6_family = AF_INET6; |
381 | SCTP_DEBUG_PRINTK("saddr: %pI6\n", &saddr->v6.sin6_addr); | 374 | ipv6_addr_copy(&saddr->v6.sin6_addr, &fl6->saddr); |
382 | } else { | ||
383 | pr_err("%s: asoc:%p Could not find a valid source " | ||
384 | "address for the dest:%pI6\n", | ||
385 | __func__, asoc, &daddr->v6.sin6_addr); | ||
386 | } | 375 | } |
387 | |||
388 | rcu_read_unlock(); | ||
389 | } | 376 | } |
390 | 377 | ||
391 | /* Make a copy of all potential local addresses. */ | 378 | /* Make a copy of all potential local addresses. */ |
@@ -507,14 +494,13 @@ static int sctp_v6_to_addr_param(const union sctp_addr *addr, | |||
507 | return length; | 494 | return length; |
508 | } | 495 | } |
509 | 496 | ||
510 | /* Initialize a sctp_addr from a dst_entry. */ | 497 | /* Initialize a sctp_addr from struct in6_addr. */ |
511 | static void sctp_v6_dst_saddr(union sctp_addr *addr, struct dst_entry *dst, | 498 | static void sctp_v6_to_addr(union sctp_addr *addr, struct in6_addr *saddr, |
512 | __be16 port) | 499 | __be16 port) |
513 | { | 500 | { |
514 | struct rt6_info *rt = (struct rt6_info *)dst; | ||
515 | addr->sa.sa_family = AF_INET6; | 501 | addr->sa.sa_family = AF_INET6; |
516 | addr->v6.sin6_port = port; | 502 | addr->v6.sin6_port = port; |
517 | ipv6_addr_copy(&addr->v6.sin6_addr, &rt->rt6i_src.addr); | 503 | ipv6_addr_copy(&addr->v6.sin6_addr, saddr); |
518 | } | 504 | } |
519 | 505 | ||
520 | /* Compare addresses exactly. | 506 | /* Compare addresses exactly. |
@@ -1001,7 +987,6 @@ static struct sctp_af sctp_af_inet6 = { | |||
1001 | .to_sk_daddr = sctp_v6_to_sk_daddr, | 987 | .to_sk_daddr = sctp_v6_to_sk_daddr, |
1002 | .from_addr_param = sctp_v6_from_addr_param, | 988 | .from_addr_param = sctp_v6_from_addr_param, |
1003 | .to_addr_param = sctp_v6_to_addr_param, | 989 | .to_addr_param = sctp_v6_to_addr_param, |
1004 | .dst_saddr = sctp_v6_dst_saddr, | ||
1005 | .cmp_addr = sctp_v6_cmp_addr, | 990 | .cmp_addr = sctp_v6_cmp_addr, |
1006 | .scope = sctp_v6_scope, | 991 | .scope = sctp_v6_scope, |
1007 | .addr_valid = sctp_v6_addr_valid, | 992 | .addr_valid = sctp_v6_addr_valid, |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index d5bf91d04f63..34216458ded1 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -465,33 +465,35 @@ static sctp_scope_t sctp_v4_scope(union sctp_addr *addr) | |||
465 | */ | 465 | */ |
466 | static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, | 466 | static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, |
467 | union sctp_addr *daddr, | 467 | union sctp_addr *daddr, |
468 | union sctp_addr *saddr) | 468 | union sctp_addr *saddr, |
469 | struct flowi *fl, | ||
470 | struct sock *sk) | ||
469 | { | 471 | { |
470 | struct rtable *rt; | 472 | struct rtable *rt; |
471 | struct flowi4 fl4; | 473 | struct flowi4 *fl4 = &fl->u.ip4; |
472 | struct sctp_bind_addr *bp; | 474 | struct sctp_bind_addr *bp; |
473 | struct sctp_sockaddr_entry *laddr; | 475 | struct sctp_sockaddr_entry *laddr; |
474 | struct dst_entry *dst = NULL; | 476 | struct dst_entry *dst = NULL; |
475 | union sctp_addr dst_saddr; | 477 | union sctp_addr dst_saddr; |
476 | 478 | ||
477 | memset(&fl4, 0x0, sizeof(struct flowi4)); | 479 | memset(fl4, 0x0, sizeof(struct flowi4)); |
478 | fl4.daddr = daddr->v4.sin_addr.s_addr; | 480 | fl4->daddr = daddr->v4.sin_addr.s_addr; |
479 | fl4.fl4_dport = daddr->v4.sin_port; | 481 | fl4->fl4_dport = daddr->v4.sin_port; |
480 | fl4.flowi4_proto = IPPROTO_SCTP; | 482 | fl4->flowi4_proto = IPPROTO_SCTP; |
481 | if (asoc) { | 483 | if (asoc) { |
482 | fl4.flowi4_tos = RT_CONN_FLAGS(asoc->base.sk); | 484 | fl4->flowi4_tos = RT_CONN_FLAGS(asoc->base.sk); |
483 | fl4.flowi4_oif = asoc->base.sk->sk_bound_dev_if; | 485 | fl4->flowi4_oif = asoc->base.sk->sk_bound_dev_if; |
484 | fl4.fl4_sport = htons(asoc->base.bind_addr.port); | 486 | fl4->fl4_sport = htons(asoc->base.bind_addr.port); |
485 | } | 487 | } |
486 | if (saddr) { | 488 | if (saddr) { |
487 | fl4.saddr = saddr->v4.sin_addr.s_addr; | 489 | fl4->saddr = saddr->v4.sin_addr.s_addr; |
488 | fl4.fl4_sport = saddr->v4.sin_port; | 490 | fl4->fl4_sport = saddr->v4.sin_port; |
489 | } | 491 | } |
490 | 492 | ||
491 | SCTP_DEBUG_PRINTK("%s: DST:%pI4, SRC:%pI4 - ", | 493 | SCTP_DEBUG_PRINTK("%s: DST:%pI4, SRC:%pI4 - ", |
492 | __func__, &fl4.daddr, &fl4.saddr); | 494 | __func__, &fl4->daddr, &fl4->saddr); |
493 | 495 | ||
494 | rt = ip_route_output_key(&init_net, &fl4); | 496 | rt = ip_route_output_key(&init_net, fl4); |
495 | if (!IS_ERR(rt)) | 497 | if (!IS_ERR(rt)) |
496 | dst = &rt->dst; | 498 | dst = &rt->dst; |
497 | 499 | ||
@@ -533,9 +535,9 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, | |||
533 | continue; | 535 | continue; |
534 | if ((laddr->state == SCTP_ADDR_SRC) && | 536 | if ((laddr->state == SCTP_ADDR_SRC) && |
535 | (AF_INET == laddr->a.sa.sa_family)) { | 537 | (AF_INET == laddr->a.sa.sa_family)) { |
536 | fl4.saddr = laddr->a.v4.sin_addr.s_addr; | 538 | fl4->saddr = laddr->a.v4.sin_addr.s_addr; |
537 | fl4.fl4_sport = laddr->a.v4.sin_port; | 539 | fl4->fl4_sport = laddr->a.v4.sin_port; |
538 | rt = ip_route_output_key(&init_net, &fl4); | 540 | rt = ip_route_output_key(&init_net, fl4); |
539 | if (!IS_ERR(rt)) { | 541 | if (!IS_ERR(rt)) { |
540 | dst = &rt->dst; | 542 | dst = &rt->dst; |
541 | goto out_unlock; | 543 | goto out_unlock; |
@@ -559,19 +561,15 @@ out: | |||
559 | * to cache it separately and hence this is an empty routine. | 561 | * to cache it separately and hence this is an empty routine. |
560 | */ | 562 | */ |
561 | static void sctp_v4_get_saddr(struct sctp_sock *sk, | 563 | static void sctp_v4_get_saddr(struct sctp_sock *sk, |
562 | struct sctp_association *asoc, | 564 | struct sctp_transport *t, |
563 | struct dst_entry *dst, | ||
564 | union sctp_addr *daddr, | 565 | union sctp_addr *daddr, |
565 | union sctp_addr *saddr) | 566 | struct flowi *fl) |
566 | { | 567 | { |
567 | struct rtable *rt = (struct rtable *)dst; | 568 | union sctp_addr *saddr = &t->saddr; |
568 | 569 | struct rtable *rt = (struct rtable *)t->dst; | |
569 | if (!asoc) | ||
570 | return; | ||
571 | 570 | ||
572 | if (rt) { | 571 | if (rt) { |
573 | saddr->v4.sin_family = AF_INET; | 572 | saddr->v4.sin_family = AF_INET; |
574 | saddr->v4.sin_port = htons(asoc->base.bind_addr.port); | ||
575 | saddr->v4.sin_addr.s_addr = rt->rt_src; | 573 | saddr->v4.sin_addr.s_addr = rt->rt_src; |
576 | } | 574 | } |
577 | } | 575 | } |
@@ -950,7 +948,6 @@ static struct sctp_af sctp_af_inet = { | |||
950 | .to_sk_daddr = sctp_v4_to_sk_daddr, | 948 | .to_sk_daddr = sctp_v4_to_sk_daddr, |
951 | .from_addr_param = sctp_v4_from_addr_param, | 949 | .from_addr_param = sctp_v4_from_addr_param, |
952 | .to_addr_param = sctp_v4_to_addr_param, | 950 | .to_addr_param = sctp_v4_to_addr_param, |
953 | .dst_saddr = sctp_v4_dst_saddr, | ||
954 | .cmp_addr = sctp_v4_cmp_addr, | 951 | .cmp_addr = sctp_v4_cmp_addr, |
955 | .addr_valid = sctp_v4_addr_valid, | 952 | .addr_valid = sctp_v4_addr_valid, |
956 | .inaddr_any = sctp_v4_inaddr_any, | 953 | .inaddr_any = sctp_v4_inaddr_any, |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index f694ee116746..33d9ee629b4e 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -2287,7 +2287,7 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params, | |||
2287 | trans->param_flags = | 2287 | trans->param_flags = |
2288 | (trans->param_flags & ~SPP_PMTUD) | pmtud_change; | 2288 | (trans->param_flags & ~SPP_PMTUD) | pmtud_change; |
2289 | if (update) { | 2289 | if (update) { |
2290 | sctp_transport_pmtu(trans); | 2290 | sctp_transport_pmtu(trans, sctp_opt2sk(sp)); |
2291 | sctp_assoc_sync_pmtu(asoc); | 2291 | sctp_assoc_sync_pmtu(asoc); |
2292 | } | 2292 | } |
2293 | } else if (asoc) { | 2293 | } else if (asoc) { |
diff --git a/net/sctp/transport.c b/net/sctp/transport.c index d3ae493d234a..2544b9b21f86 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c | |||
@@ -211,11 +211,15 @@ void sctp_transport_set_owner(struct sctp_transport *transport, | |||
211 | } | 211 | } |
212 | 212 | ||
213 | /* Initialize the pmtu of a transport. */ | 213 | /* Initialize the pmtu of a transport. */ |
214 | void sctp_transport_pmtu(struct sctp_transport *transport) | 214 | void sctp_transport_pmtu(struct sctp_transport *transport, struct sock *sk) |
215 | { | 215 | { |
216 | struct dst_entry *dst; | 216 | struct dst_entry *dst; |
217 | struct flowi fl; | ||
217 | 218 | ||
218 | dst = transport->af_specific->get_dst(NULL, &transport->ipaddr, NULL); | 219 | dst = transport->af_specific->get_dst(transport->asoc, |
220 | &transport->ipaddr, | ||
221 | &transport->saddr, | ||
222 | &fl, sk); | ||
219 | 223 | ||
220 | if (dst) { | 224 | if (dst) { |
221 | transport->pathmtu = dst_mtu(dst); | 225 | transport->pathmtu = dst_mtu(dst); |
@@ -272,15 +276,16 @@ void sctp_transport_route(struct sctp_transport *transport, | |||
272 | struct sctp_af *af = transport->af_specific; | 276 | struct sctp_af *af = transport->af_specific; |
273 | union sctp_addr *daddr = &transport->ipaddr; | 277 | union sctp_addr *daddr = &transport->ipaddr; |
274 | struct dst_entry *dst; | 278 | struct dst_entry *dst; |
279 | struct flowi fl; | ||
275 | 280 | ||
276 | dst = af->get_dst(asoc, daddr, saddr); | 281 | dst = af->get_dst(asoc, daddr, saddr, &fl, sctp_opt2sk(opt)); |
282 | transport->dst = dst; | ||
277 | 283 | ||
278 | if (saddr) | 284 | if (saddr) |
279 | memcpy(&transport->saddr, saddr, sizeof(union sctp_addr)); | 285 | memcpy(&transport->saddr, saddr, sizeof(union sctp_addr)); |
280 | else | 286 | else |
281 | af->get_saddr(opt, asoc, dst, daddr, &transport->saddr); | 287 | af->get_saddr(opt, transport, daddr, &fl); |
282 | 288 | ||
283 | transport->dst = dst; | ||
284 | if ((transport->param_flags & SPP_PMTUD_DISABLE) && transport->pathmtu) { | 289 | if ((transport->param_flags & SPP_PMTUD_DISABLE) && transport->pathmtu) { |
285 | return; | 290 | return; |
286 | } | 291 | } |