diff options
| author | David S. Miller <davem@davemloft.net> | 2011-05-12 23:01:55 -0400 |
|---|---|---|
| committer | David S. Miller <davem@davemloft.net> | 2011-05-12 23:01:55 -0400 |
| commit | 5c5095494fb545f53b80cbb7539679a10a3472a6 (patch) | |
| tree | d7c40cd66a58030ddef369bcb9acd8d95e2ac864 /net | |
| parent | 4d586b823acc46c55c889ae1798de236c9d403da (diff) | |
| parent | def57687e9579b7a797681990dff763c411f5347 (diff) | |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-next-2.6
Diffstat (limited to 'net')
| -rw-r--r-- | net/802/garp.c | 14 | ||||
| -rw-r--r-- | net/8021q/vlan_dev.c | 6 | ||||
| -rw-r--r-- | net/core/dev.c | 25 | ||||
| -rw-r--r-- | net/core/ethtool.c | 2 | ||||
| -rw-r--r-- | net/ipv4/ip_forward.c | 2 | ||||
| -rw-r--r-- | net/ipv4/ip_options.c | 4 | ||||
| -rw-r--r-- | net/irda/ircomm/ircomm_tty.c | 14 | ||||
| -rw-r--r-- | net/l2tp/l2tp_core.c | 10 | ||||
| -rw-r--r-- | net/netfilter/ipvs/ip_vs_core.c | 24 | ||||
| -rw-r--r-- | net/netfilter/ipvs/ip_vs_xmit.c | 97 | ||||
| -rw-r--r-- | net/sctp/socket.c | 13 |
11 files changed, 126 insertions, 85 deletions
diff --git a/net/802/garp.c b/net/802/garp.c index 5dbe8967bbd5..f8300a8b5fbc 100644 --- a/net/802/garp.c +++ b/net/802/garp.c | |||
| @@ -603,6 +603,11 @@ err1: | |||
| 603 | } | 603 | } |
| 604 | EXPORT_SYMBOL_GPL(garp_init_applicant); | 604 | EXPORT_SYMBOL_GPL(garp_init_applicant); |
| 605 | 605 | ||
| 606 | static void garp_app_kfree_rcu(struct rcu_head *head) | ||
| 607 | { | ||
| 608 | kfree(container_of(head, struct garp_applicant, rcu)); | ||
| 609 | } | ||
| 610 | |||
| 606 | void garp_uninit_applicant(struct net_device *dev, struct garp_application *appl) | 611 | void garp_uninit_applicant(struct net_device *dev, struct garp_application *appl) |
| 607 | { | 612 | { |
| 608 | struct garp_port *port = rtnl_dereference(dev->garp_port); | 613 | struct garp_port *port = rtnl_dereference(dev->garp_port); |
| @@ -611,7 +616,6 @@ void garp_uninit_applicant(struct net_device *dev, struct garp_application *appl | |||
| 611 | ASSERT_RTNL(); | 616 | ASSERT_RTNL(); |
| 612 | 617 | ||
| 613 | rcu_assign_pointer(port->applicants[appl->type], NULL); | 618 | rcu_assign_pointer(port->applicants[appl->type], NULL); |
| 614 | synchronize_rcu(); | ||
| 615 | 619 | ||
| 616 | /* Delete timer and generate a final TRANSMIT_PDU event to flush out | 620 | /* Delete timer and generate a final TRANSMIT_PDU event to flush out |
| 617 | * all pending messages before the applicant is gone. */ | 621 | * all pending messages before the applicant is gone. */ |
| @@ -621,7 +625,7 @@ void garp_uninit_applicant(struct net_device *dev, struct garp_application *appl | |||
| 621 | garp_queue_xmit(app); | 625 | garp_queue_xmit(app); |
| 622 | 626 | ||
| 623 | dev_mc_del(dev, appl->proto.group_address); | 627 | dev_mc_del(dev, appl->proto.group_address); |
| 624 | kfree(app); | 628 | call_rcu(&app->rcu, garp_app_kfree_rcu); |
| 625 | garp_release_port(dev); | 629 | garp_release_port(dev); |
| 626 | } | 630 | } |
| 627 | EXPORT_SYMBOL_GPL(garp_uninit_applicant); | 631 | EXPORT_SYMBOL_GPL(garp_uninit_applicant); |
| @@ -639,3 +643,9 @@ void garp_unregister_application(struct garp_application *appl) | |||
| 639 | stp_proto_unregister(&appl->proto); | 643 | stp_proto_unregister(&appl->proto); |
| 640 | } | 644 | } |
| 641 | EXPORT_SYMBOL_GPL(garp_unregister_application); | 645 | EXPORT_SYMBOL_GPL(garp_unregister_application); |
| 646 | |||
| 647 | static void __exit garp_cleanup_module(void) | ||
| 648 | { | ||
| 649 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ | ||
| 650 | } | ||
| 651 | module_exit(garp_cleanup_module); | ||
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 58f8010e1aef..f247f5bff88d 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
| @@ -528,7 +528,7 @@ static int vlan_dev_init(struct net_device *dev) | |||
| 528 | (1<<__LINK_STATE_DORMANT))) | | 528 | (1<<__LINK_STATE_DORMANT))) | |
| 529 | (1<<__LINK_STATE_PRESENT); | 529 | (1<<__LINK_STATE_PRESENT); |
| 530 | 530 | ||
| 531 | dev->hw_features = real_dev->vlan_features & NETIF_F_ALL_TX_OFFLOADS; | 531 | dev->hw_features = NETIF_F_ALL_TX_OFFLOADS; |
| 532 | dev->features |= real_dev->vlan_features | NETIF_F_LLTX; | 532 | dev->features |= real_dev->vlan_features | NETIF_F_LLTX; |
| 533 | dev->gso_max_size = real_dev->gso_max_size; | 533 | dev->gso_max_size = real_dev->gso_max_size; |
| 534 | 534 | ||
| @@ -587,9 +587,11 @@ static u32 vlan_dev_fix_features(struct net_device *dev, u32 features) | |||
| 587 | { | 587 | { |
| 588 | struct net_device *real_dev = vlan_dev_info(dev)->real_dev; | 588 | struct net_device *real_dev = vlan_dev_info(dev)->real_dev; |
| 589 | 589 | ||
| 590 | features &= (real_dev->features | NETIF_F_LLTX); | 590 | features &= real_dev->features; |
| 591 | features &= real_dev->vlan_features; | ||
| 591 | if (dev_ethtool_get_rx_csum(real_dev)) | 592 | if (dev_ethtool_get_rx_csum(real_dev)) |
| 592 | features |= NETIF_F_RXCSUM; | 593 | features |= NETIF_F_RXCSUM; |
| 594 | features |= NETIF_F_LLTX; | ||
| 593 | 595 | ||
| 594 | return features; | 596 | return features; |
| 595 | } | 597 | } |
diff --git a/net/core/dev.c b/net/core/dev.c index 75898a32c038..ea23353e6251 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -5289,6 +5289,14 @@ int __netdev_update_features(struct net_device *dev) | |||
| 5289 | return 1; | 5289 | return 1; |
| 5290 | } | 5290 | } |
| 5291 | 5291 | ||
| 5292 | /** | ||
| 5293 | * netdev_update_features - recalculate device features | ||
| 5294 | * @dev: the device to check | ||
| 5295 | * | ||
| 5296 | * Recalculate dev->features set and send notifications if it | ||
| 5297 | * has changed. Should be called after driver or hardware dependent | ||
| 5298 | * conditions might have changed that influence the features. | ||
| 5299 | */ | ||
| 5292 | void netdev_update_features(struct net_device *dev) | 5300 | void netdev_update_features(struct net_device *dev) |
| 5293 | { | 5301 | { |
| 5294 | if (__netdev_update_features(dev)) | 5302 | if (__netdev_update_features(dev)) |
| @@ -5297,6 +5305,23 @@ void netdev_update_features(struct net_device *dev) | |||
| 5297 | EXPORT_SYMBOL(netdev_update_features); | 5305 | EXPORT_SYMBOL(netdev_update_features); |
| 5298 | 5306 | ||
| 5299 | /** | 5307 | /** |
| 5308 | * netdev_change_features - recalculate device features | ||
| 5309 | * @dev: the device to check | ||
| 5310 | * | ||
| 5311 | * Recalculate dev->features set and send notifications even | ||
| 5312 | * if they have not changed. Should be called instead of | ||
| 5313 | * netdev_update_features() if also dev->vlan_features might | ||
| 5314 | * have changed to allow the changes to be propagated to stacked | ||
| 5315 | * VLAN devices. | ||
| 5316 | */ | ||
| 5317 | void netdev_change_features(struct net_device *dev) | ||
| 5318 | { | ||
| 5319 | __netdev_update_features(dev); | ||
| 5320 | netdev_features_change(dev); | ||
| 5321 | } | ||
| 5322 | EXPORT_SYMBOL(netdev_change_features); | ||
| 5323 | |||
| 5324 | /** | ||
| 5300 | * netif_stacked_transfer_operstate - transfer operstate | 5325 | * netif_stacked_transfer_operstate - transfer operstate |
| 5301 | * @rootdev: the root or lower level device to transfer state from | 5326 | * @rootdev: the root or lower level device to transfer state from |
| 5302 | * @dev: the device to transfer operstate to | 5327 | * @dev: the device to transfer operstate to |
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index b6f405888538..b8c2b10f397a 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
| @@ -361,7 +361,7 @@ static const char netdev_features_strings[ETHTOOL_DEV_FEATURE_WORDS * 32][ETH_GS | |||
| 361 | /* NETIF_F_NTUPLE */ "rx-ntuple-filter", | 361 | /* NETIF_F_NTUPLE */ "rx-ntuple-filter", |
| 362 | /* NETIF_F_RXHASH */ "rx-hashing", | 362 | /* NETIF_F_RXHASH */ "rx-hashing", |
| 363 | /* NETIF_F_RXCSUM */ "rx-checksum", | 363 | /* NETIF_F_RXCSUM */ "rx-checksum", |
| 364 | /* NETIF_F_NOCACHE_COPY */ "tx-nocache-copy" | 364 | /* NETIF_F_NOCACHE_COPY */ "tx-nocache-copy", |
| 365 | /* NETIF_F_LOOPBACK */ "loopback", | 365 | /* NETIF_F_LOOPBACK */ "loopback", |
| 366 | }; | 366 | }; |
| 367 | 367 | ||
diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index 99461f09320f..fcbc0c8f1261 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c | |||
| @@ -84,7 +84,7 @@ int ip_forward(struct sk_buff *skb) | |||
| 84 | 84 | ||
| 85 | rt = skb_rtable(skb); | 85 | rt = skb_rtable(skb); |
| 86 | 86 | ||
| 87 | if (opt->is_strictroute && rt->rt_dst != rt->rt_gateway) | 87 | if (opt->is_strictroute && iph->daddr != rt->rt_gateway) |
| 88 | goto sr_failed; | 88 | goto sr_failed; |
| 89 | 89 | ||
| 90 | if (unlikely(skb->len > dst_mtu(&rt->dst) && !skb_is_gso(skb) && | 90 | if (unlikely(skb->len > dst_mtu(&rt->dst) && !skb_is_gso(skb) && |
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index 01fc40965848..c5c26192b057 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c | |||
| @@ -601,7 +601,7 @@ int ip_options_rcv_srr(struct sk_buff *skb) | |||
| 601 | unsigned long orefdst; | 601 | unsigned long orefdst; |
| 602 | int err; | 602 | int err; |
| 603 | 603 | ||
| 604 | if (!opt->srr || !rt) | 604 | if (!rt) |
| 605 | return 0; | 605 | return 0; |
| 606 | 606 | ||
| 607 | if (skb->pkt_type != PACKET_HOST) | 607 | if (skb->pkt_type != PACKET_HOST) |
| @@ -635,7 +635,7 @@ int ip_options_rcv_srr(struct sk_buff *skb) | |||
| 635 | if (rt2->rt_type != RTN_LOCAL) | 635 | if (rt2->rt_type != RTN_LOCAL) |
| 636 | break; | 636 | break; |
| 637 | /* Superfast 8) loopback forward */ | 637 | /* Superfast 8) loopback forward */ |
| 638 | memcpy(&iph->daddr, &optptr[srrptr-1], 4); | 638 | iph->daddr = nexthop; |
| 639 | opt->is_changed = 1; | 639 | opt->is_changed = 1; |
| 640 | } | 640 | } |
| 641 | if (srrptr <= srrspace) { | 641 | if (srrptr <= srrspace) { |
diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c index a39cca8331df..b3cc8b3989a9 100644 --- a/net/irda/ircomm/ircomm_tty.c +++ b/net/irda/ircomm/ircomm_tty.c | |||
| @@ -38,6 +38,7 @@ | |||
| 38 | #include <linux/seq_file.h> | 38 | #include <linux/seq_file.h> |
| 39 | #include <linux/termios.h> | 39 | #include <linux/termios.h> |
| 40 | #include <linux/tty.h> | 40 | #include <linux/tty.h> |
| 41 | #include <linux/tty_flip.h> | ||
| 41 | #include <linux/interrupt.h> | 42 | #include <linux/interrupt.h> |
| 42 | #include <linux/device.h> /* for MODULE_ALIAS_CHARDEV_MAJOR */ | 43 | #include <linux/device.h> /* for MODULE_ALIAS_CHARDEV_MAJOR */ |
| 43 | 44 | ||
| @@ -1132,7 +1133,6 @@ static int ircomm_tty_data_indication(void *instance, void *sap, | |||
| 1132 | struct sk_buff *skb) | 1133 | struct sk_buff *skb) |
| 1133 | { | 1134 | { |
| 1134 | struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; | 1135 | struct ircomm_tty_cb *self = (struct ircomm_tty_cb *) instance; |
| 1135 | struct tty_ldisc *ld; | ||
| 1136 | 1136 | ||
| 1137 | IRDA_DEBUG(2, "%s()\n", __func__ ); | 1137 | IRDA_DEBUG(2, "%s()\n", __func__ ); |
| 1138 | 1138 | ||
| @@ -1161,15 +1161,11 @@ static int ircomm_tty_data_indication(void *instance, void *sap, | |||
| 1161 | } | 1161 | } |
| 1162 | 1162 | ||
| 1163 | /* | 1163 | /* |
| 1164 | * Just give it over to the line discipline. There is no need to | 1164 | * Use flip buffer functions since the code may be called from interrupt |
| 1165 | * involve the flip buffers, since we are not running in an interrupt | 1165 | * context |
| 1166 | * handler | ||
| 1167 | */ | 1166 | */ |
| 1168 | 1167 | tty_insert_flip_string(self->tty, skb->data, skb->len); | |
| 1169 | ld = tty_ldisc_ref(self->tty); | 1168 | tty_flip_buffer_push(self->tty); |
| 1170 | if (ld) | ||
| 1171 | ld->ops->receive_buf(self->tty, skb->data, NULL, skb->len); | ||
| 1172 | tty_ldisc_deref(ld); | ||
| 1173 | 1169 | ||
| 1174 | /* No need to kfree_skb - see ircomm_ttp_data_indication() */ | 1170 | /* No need to kfree_skb - see ircomm_ttp_data_indication() */ |
| 1175 | 1171 | ||
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 9be095e00450..ed8a2335442f 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c | |||
| @@ -1435,16 +1435,15 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 | |||
| 1435 | 1435 | ||
| 1436 | /* Add tunnel to our list */ | 1436 | /* Add tunnel to our list */ |
| 1437 | INIT_LIST_HEAD(&tunnel->list); | 1437 | INIT_LIST_HEAD(&tunnel->list); |
| 1438 | spin_lock_bh(&pn->l2tp_tunnel_list_lock); | ||
| 1439 | list_add_rcu(&tunnel->list, &pn->l2tp_tunnel_list); | ||
| 1440 | spin_unlock_bh(&pn->l2tp_tunnel_list_lock); | ||
| 1441 | synchronize_rcu(); | ||
| 1442 | atomic_inc(&l2tp_tunnel_count); | 1438 | atomic_inc(&l2tp_tunnel_count); |
| 1443 | 1439 | ||
| 1444 | /* Bump the reference count. The tunnel context is deleted | 1440 | /* Bump the reference count. The tunnel context is deleted |
| 1445 | * only when this drops to zero. | 1441 | * only when this drops to zero. Must be done before list insertion |
| 1446 | */ | 1442 | */ |
| 1447 | l2tp_tunnel_inc_refcount(tunnel); | 1443 | l2tp_tunnel_inc_refcount(tunnel); |
| 1444 | spin_lock_bh(&pn->l2tp_tunnel_list_lock); | ||
| 1445 | list_add_rcu(&tunnel->list, &pn->l2tp_tunnel_list); | ||
| 1446 | spin_unlock_bh(&pn->l2tp_tunnel_list_lock); | ||
| 1448 | 1447 | ||
| 1449 | err = 0; | 1448 | err = 0; |
| 1450 | err: | 1449 | err: |
| @@ -1636,7 +1635,6 @@ struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunn | |||
| 1636 | hlist_add_head_rcu(&session->global_hlist, | 1635 | hlist_add_head_rcu(&session->global_hlist, |
| 1637 | l2tp_session_id_hash_2(pn, session_id)); | 1636 | l2tp_session_id_hash_2(pn, session_id)); |
| 1638 | spin_unlock_bh(&pn->l2tp_session_hlist_lock); | 1637 | spin_unlock_bh(&pn->l2tp_session_hlist_lock); |
| 1639 | synchronize_rcu(); | ||
| 1640 | } | 1638 | } |
| 1641 | 1639 | ||
| 1642 | /* Ignore management session in session count value */ | 1640 | /* Ignore management session in session count value */ |
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index a74dae6c5dbc..bfa808f4da13 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c | |||
| @@ -1382,15 +1382,7 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) | |||
| 1382 | ip_vs_in_stats(cp, skb); | 1382 | ip_vs_in_stats(cp, skb); |
| 1383 | if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol) | 1383 | if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol) |
| 1384 | offset += 2 * sizeof(__u16); | 1384 | offset += 2 * sizeof(__u16); |
| 1385 | verdict = ip_vs_icmp_xmit(skb, cp, pp, offset); | 1385 | verdict = ip_vs_icmp_xmit(skb, cp, pp, offset, hooknum); |
| 1386 | /* LOCALNODE from FORWARD hook is not supported */ | ||
| 1387 | if (verdict == NF_ACCEPT && hooknum == NF_INET_FORWARD && | ||
| 1388 | skb_rtable(skb)->rt_flags & RTCF_LOCAL) { | ||
| 1389 | IP_VS_DBG(1, "%s(): " | ||
| 1390 | "local delivery to %pI4 but in FORWARD\n", | ||
| 1391 | __func__, &skb_rtable(skb)->rt_dst); | ||
| 1392 | verdict = NF_DROP; | ||
| 1393 | } | ||
| 1394 | 1386 | ||
| 1395 | out: | 1387 | out: |
| 1396 | __ip_vs_conn_put(cp); | 1388 | __ip_vs_conn_put(cp); |
| @@ -1412,7 +1404,6 @@ ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum) | |||
| 1412 | struct ip_vs_protocol *pp; | 1404 | struct ip_vs_protocol *pp; |
| 1413 | struct ip_vs_proto_data *pd; | 1405 | struct ip_vs_proto_data *pd; |
| 1414 | unsigned int offset, verdict; | 1406 | unsigned int offset, verdict; |
| 1415 | struct rt6_info *rt; | ||
| 1416 | 1407 | ||
| 1417 | *related = 1; | 1408 | *related = 1; |
| 1418 | 1409 | ||
| @@ -1474,23 +1465,12 @@ ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum) | |||
| 1474 | if (!cp) | 1465 | if (!cp) |
| 1475 | return NF_ACCEPT; | 1466 | return NF_ACCEPT; |
| 1476 | 1467 | ||
| 1477 | verdict = NF_DROP; | ||
| 1478 | |||
| 1479 | /* do the statistics and put it back */ | 1468 | /* do the statistics and put it back */ |
| 1480 | ip_vs_in_stats(cp, skb); | 1469 | ip_vs_in_stats(cp, skb); |
| 1481 | if (IPPROTO_TCP == cih->nexthdr || IPPROTO_UDP == cih->nexthdr || | 1470 | if (IPPROTO_TCP == cih->nexthdr || IPPROTO_UDP == cih->nexthdr || |
| 1482 | IPPROTO_SCTP == cih->nexthdr) | 1471 | IPPROTO_SCTP == cih->nexthdr) |
| 1483 | offset += 2 * sizeof(__u16); | 1472 | offset += 2 * sizeof(__u16); |
| 1484 | verdict = ip_vs_icmp_xmit_v6(skb, cp, pp, offset); | 1473 | verdict = ip_vs_icmp_xmit_v6(skb, cp, pp, offset, hooknum); |
| 1485 | /* LOCALNODE from FORWARD hook is not supported */ | ||
| 1486 | if (verdict == NF_ACCEPT && hooknum == NF_INET_FORWARD && | ||
| 1487 | (rt = (struct rt6_info *) skb_dst(skb)) && | ||
| 1488 | rt->rt6i_dev && rt->rt6i_dev->flags & IFF_LOOPBACK) { | ||
| 1489 | IP_VS_DBG(1, "%s(): " | ||
| 1490 | "local delivery to %pI6 but in FORWARD\n", | ||
| 1491 | __func__, &rt->rt6i_dst); | ||
| 1492 | verdict = NF_DROP; | ||
| 1493 | } | ||
| 1494 | 1474 | ||
| 1495 | __ip_vs_conn_put(cp); | 1475 | __ip_vs_conn_put(cp); |
| 1496 | 1476 | ||
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index 6132b213eddc..ee319a4338b0 100644 --- a/net/netfilter/ipvs/ip_vs_xmit.c +++ b/net/netfilter/ipvs/ip_vs_xmit.c | |||
| @@ -87,7 +87,7 @@ __ip_vs_dst_check(struct ip_vs_dest *dest, u32 rtos) | |||
| 87 | /* Get route to destination or remote server */ | 87 | /* Get route to destination or remote server */ |
| 88 | static struct rtable * | 88 | static struct rtable * |
| 89 | __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest, | 89 | __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest, |
| 90 | __be32 daddr, u32 rtos, int rt_mode) | 90 | __be32 daddr, u32 rtos, int rt_mode, __be32 *ret_saddr) |
| 91 | { | 91 | { |
| 92 | struct net *net = dev_net(skb_dst(skb)->dev); | 92 | struct net *net = dev_net(skb_dst(skb)->dev); |
| 93 | struct rtable *rt; /* Route to the other host */ | 93 | struct rtable *rt; /* Route to the other host */ |
| @@ -98,7 +98,12 @@ __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest, | |||
| 98 | spin_lock(&dest->dst_lock); | 98 | spin_lock(&dest->dst_lock); |
| 99 | if (!(rt = (struct rtable *) | 99 | if (!(rt = (struct rtable *) |
| 100 | __ip_vs_dst_check(dest, rtos))) { | 100 | __ip_vs_dst_check(dest, rtos))) { |
| 101 | rt = ip_route_output(net, dest->addr.ip, 0, rtos, 0); | 101 | struct flowi4 fl4; |
| 102 | |||
| 103 | memset(&fl4, 0, sizeof(fl4)); | ||
| 104 | fl4.daddr = dest->addr.ip; | ||
| 105 | fl4.flowi4_tos = rtos; | ||
| 106 | rt = ip_route_output_key(net, &fl4); | ||
| 102 | if (IS_ERR(rt)) { | 107 | if (IS_ERR(rt)) { |
| 103 | spin_unlock(&dest->dst_lock); | 108 | spin_unlock(&dest->dst_lock); |
| 104 | IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n", | 109 | IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n", |
| @@ -106,18 +111,30 @@ __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest, | |||
| 106 | return NULL; | 111 | return NULL; |
| 107 | } | 112 | } |
| 108 | __ip_vs_dst_set(dest, rtos, dst_clone(&rt->dst), 0); | 113 | __ip_vs_dst_set(dest, rtos, dst_clone(&rt->dst), 0); |
| 109 | IP_VS_DBG(10, "new dst %pI4, refcnt=%d, rtos=%X\n", | 114 | dest->dst_saddr.ip = fl4.saddr; |
| 110 | &dest->addr.ip, | 115 | IP_VS_DBG(10, "new dst %pI4, src %pI4, refcnt=%d, " |
| 116 | "rtos=%X\n", | ||
| 117 | &dest->addr.ip, &dest->dst_saddr.ip, | ||
| 111 | atomic_read(&rt->dst.__refcnt), rtos); | 118 | atomic_read(&rt->dst.__refcnt), rtos); |
| 112 | } | 119 | } |
| 120 | daddr = dest->addr.ip; | ||
| 121 | if (ret_saddr) | ||
| 122 | *ret_saddr = dest->dst_saddr.ip; | ||
| 113 | spin_unlock(&dest->dst_lock); | 123 | spin_unlock(&dest->dst_lock); |
| 114 | } else { | 124 | } else { |
| 115 | rt = ip_route_output(net, daddr, 0, rtos, 0); | 125 | struct flowi4 fl4; |
| 126 | |||
| 127 | memset(&fl4, 0, sizeof(fl4)); | ||
| 128 | fl4.daddr = daddr; | ||
| 129 | fl4.flowi4_tos = rtos; | ||
| 130 | rt = ip_route_output_key(net, &fl4); | ||
| 116 | if (IS_ERR(rt)) { | 131 | if (IS_ERR(rt)) { |
| 117 | IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n", | 132 | IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n", |
| 118 | &daddr); | 133 | &daddr); |
| 119 | return NULL; | 134 | return NULL; |
| 120 | } | 135 | } |
| 136 | if (ret_saddr) | ||
| 137 | *ret_saddr = fl4.saddr; | ||
| 121 | } | 138 | } |
| 122 | 139 | ||
| 123 | local = rt->rt_flags & RTCF_LOCAL; | 140 | local = rt->rt_flags & RTCF_LOCAL; |
| @@ -125,7 +142,7 @@ __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest, | |||
| 125 | rt_mode)) { | 142 | rt_mode)) { |
| 126 | IP_VS_DBG_RL("Stopping traffic to %s address, dest: %pI4\n", | 143 | IP_VS_DBG_RL("Stopping traffic to %s address, dest: %pI4\n", |
| 127 | (rt->rt_flags & RTCF_LOCAL) ? | 144 | (rt->rt_flags & RTCF_LOCAL) ? |
| 128 | "local":"non-local", &rt->rt_dst); | 145 | "local":"non-local", &daddr); |
| 129 | ip_rt_put(rt); | 146 | ip_rt_put(rt); |
| 130 | return NULL; | 147 | return NULL; |
| 131 | } | 148 | } |
| @@ -133,14 +150,14 @@ __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest, | |||
| 133 | !((ort = skb_rtable(skb)) && ort->rt_flags & RTCF_LOCAL)) { | 150 | !((ort = skb_rtable(skb)) && ort->rt_flags & RTCF_LOCAL)) { |
| 134 | IP_VS_DBG_RL("Redirect from non-local address %pI4 to local " | 151 | IP_VS_DBG_RL("Redirect from non-local address %pI4 to local " |
| 135 | "requires NAT method, dest: %pI4\n", | 152 | "requires NAT method, dest: %pI4\n", |
| 136 | &ip_hdr(skb)->daddr, &rt->rt_dst); | 153 | &ip_hdr(skb)->daddr, &daddr); |
| 137 | ip_rt_put(rt); | 154 | ip_rt_put(rt); |
| 138 | return NULL; | 155 | return NULL; |
| 139 | } | 156 | } |
| 140 | if (unlikely(!local && ipv4_is_loopback(ip_hdr(skb)->saddr))) { | 157 | if (unlikely(!local && ipv4_is_loopback(ip_hdr(skb)->saddr))) { |
| 141 | IP_VS_DBG_RL("Stopping traffic from loopback address %pI4 " | 158 | IP_VS_DBG_RL("Stopping traffic from loopback address %pI4 " |
| 142 | "to non-local address, dest: %pI4\n", | 159 | "to non-local address, dest: %pI4\n", |
| 143 | &ip_hdr(skb)->saddr, &rt->rt_dst); | 160 | &ip_hdr(skb)->saddr, &daddr); |
| 144 | ip_rt_put(rt); | 161 | ip_rt_put(rt); |
| 145 | return NULL; | 162 | return NULL; |
| 146 | } | 163 | } |
| @@ -229,8 +246,6 @@ out_err: | |||
| 229 | 246 | ||
| 230 | /* | 247 | /* |
| 231 | * Get route to destination or remote server | 248 | * Get route to destination or remote server |
| 232 | * rt_mode: flags, &1=Allow local dest, &2=Allow non-local dest, | ||
| 233 | * &4=Allow redirect from remote daddr to local | ||
| 234 | */ | 249 | */ |
| 235 | static struct rt6_info * | 250 | static struct rt6_info * |
| 236 | __ip_vs_get_out_rt_v6(struct sk_buff *skb, struct ip_vs_dest *dest, | 251 | __ip_vs_get_out_rt_v6(struct sk_buff *skb, struct ip_vs_dest *dest, |
| @@ -250,7 +265,7 @@ __ip_vs_get_out_rt_v6(struct sk_buff *skb, struct ip_vs_dest *dest, | |||
| 250 | u32 cookie; | 265 | u32 cookie; |
| 251 | 266 | ||
| 252 | dst = __ip_vs_route_output_v6(net, &dest->addr.in6, | 267 | dst = __ip_vs_route_output_v6(net, &dest->addr.in6, |
| 253 | &dest->dst_saddr, | 268 | &dest->dst_saddr.in6, |
| 254 | do_xfrm); | 269 | do_xfrm); |
| 255 | if (!dst) { | 270 | if (!dst) { |
| 256 | spin_unlock(&dest->dst_lock); | 271 | spin_unlock(&dest->dst_lock); |
| @@ -260,11 +275,11 @@ __ip_vs_get_out_rt_v6(struct sk_buff *skb, struct ip_vs_dest *dest, | |||
| 260 | cookie = rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0; | 275 | cookie = rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0; |
| 261 | __ip_vs_dst_set(dest, 0, dst_clone(&rt->dst), cookie); | 276 | __ip_vs_dst_set(dest, 0, dst_clone(&rt->dst), cookie); |
| 262 | IP_VS_DBG(10, "new dst %pI6, src %pI6, refcnt=%d\n", | 277 | IP_VS_DBG(10, "new dst %pI6, src %pI6, refcnt=%d\n", |
| 263 | &dest->addr.in6, &dest->dst_saddr, | 278 | &dest->addr.in6, &dest->dst_saddr.in6, |
| 264 | atomic_read(&rt->dst.__refcnt)); | 279 | atomic_read(&rt->dst.__refcnt)); |
| 265 | } | 280 | } |
| 266 | if (ret_saddr) | 281 | if (ret_saddr) |
| 267 | ipv6_addr_copy(ret_saddr, &dest->dst_saddr); | 282 | ipv6_addr_copy(ret_saddr, &dest->dst_saddr.in6); |
| 268 | spin_unlock(&dest->dst_lock); | 283 | spin_unlock(&dest->dst_lock); |
| 269 | } else { | 284 | } else { |
| 270 | dst = __ip_vs_route_output_v6(net, daddr, ret_saddr, do_xfrm); | 285 | dst = __ip_vs_route_output_v6(net, daddr, ret_saddr, do_xfrm); |
| @@ -274,13 +289,14 @@ __ip_vs_get_out_rt_v6(struct sk_buff *skb, struct ip_vs_dest *dest, | |||
| 274 | } | 289 | } |
| 275 | 290 | ||
| 276 | local = __ip_vs_is_local_route6(rt); | 291 | local = __ip_vs_is_local_route6(rt); |
| 277 | if (!((local ? 1 : 2) & rt_mode)) { | 292 | if (!((local ? IP_VS_RT_MODE_LOCAL : IP_VS_RT_MODE_NON_LOCAL) & |
| 293 | rt_mode)) { | ||
| 278 | IP_VS_DBG_RL("Stopping traffic to %s address, dest: %pI6\n", | 294 | IP_VS_DBG_RL("Stopping traffic to %s address, dest: %pI6\n", |
| 279 | local ? "local":"non-local", daddr); | 295 | local ? "local":"non-local", daddr); |
| 280 | dst_release(&rt->dst); | 296 | dst_release(&rt->dst); |
| 281 | return NULL; | 297 | return NULL; |
| 282 | } | 298 | } |
| 283 | if (local && !(rt_mode & 4) && | 299 | if (local && !(rt_mode & IP_VS_RT_MODE_RDR) && |
| 284 | !((ort = (struct rt6_info *) skb_dst(skb)) && | 300 | !((ort = (struct rt6_info *) skb_dst(skb)) && |
| 285 | __ip_vs_is_local_route6(ort))) { | 301 | __ip_vs_is_local_route6(ort))) { |
| 286 | IP_VS_DBG_RL("Redirect from non-local address %pI6 to local " | 302 | IP_VS_DBG_RL("Redirect from non-local address %pI6 to local " |
| @@ -386,7 +402,7 @@ ip_vs_bypass_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
| 386 | EnterFunction(10); | 402 | EnterFunction(10); |
| 387 | 403 | ||
| 388 | if (!(rt = __ip_vs_get_out_rt(skb, NULL, iph->daddr, RT_TOS(iph->tos), | 404 | if (!(rt = __ip_vs_get_out_rt(skb, NULL, iph->daddr, RT_TOS(iph->tos), |
| 389 | IP_VS_RT_MODE_NON_LOCAL))) | 405 | IP_VS_RT_MODE_NON_LOCAL, NULL))) |
| 390 | goto tx_error_icmp; | 406 | goto tx_error_icmp; |
| 391 | 407 | ||
| 392 | /* MTU checking */ | 408 | /* MTU checking */ |
| @@ -440,7 +456,8 @@ ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
| 440 | 456 | ||
| 441 | EnterFunction(10); | 457 | EnterFunction(10); |
| 442 | 458 | ||
| 443 | if (!(rt = __ip_vs_get_out_rt_v6(skb, NULL, &iph->daddr, NULL, 0, 2))) | 459 | if (!(rt = __ip_vs_get_out_rt_v6(skb, NULL, &iph->daddr, NULL, 0, |
| 460 | IP_VS_RT_MODE_NON_LOCAL))) | ||
| 444 | goto tx_error_icmp; | 461 | goto tx_error_icmp; |
| 445 | 462 | ||
| 446 | /* MTU checking */ | 463 | /* MTU checking */ |
| @@ -517,7 +534,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
| 517 | RT_TOS(iph->tos), | 534 | RT_TOS(iph->tos), |
| 518 | IP_VS_RT_MODE_LOCAL | | 535 | IP_VS_RT_MODE_LOCAL | |
| 519 | IP_VS_RT_MODE_NON_LOCAL | | 536 | IP_VS_RT_MODE_NON_LOCAL | |
| 520 | IP_VS_RT_MODE_RDR))) | 537 | IP_VS_RT_MODE_RDR, NULL))) |
| 521 | goto tx_error_icmp; | 538 | goto tx_error_icmp; |
| 522 | local = rt->rt_flags & RTCF_LOCAL; | 539 | local = rt->rt_flags & RTCF_LOCAL; |
| 523 | /* | 540 | /* |
| @@ -539,7 +556,7 @@ ip_vs_nat_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
| 539 | #endif | 556 | #endif |
| 540 | 557 | ||
| 541 | /* From world but DNAT to loopback address? */ | 558 | /* From world but DNAT to loopback address? */ |
| 542 | if (local && ipv4_is_loopback(rt->rt_dst) && | 559 | if (local && ipv4_is_loopback(cp->daddr.ip) && |
| 543 | rt_is_input_route(skb_rtable(skb))) { | 560 | rt_is_input_route(skb_rtable(skb))) { |
| 544 | IP_VS_DBG_RL_PKT(1, AF_INET, pp, skb, 0, "ip_vs_nat_xmit(): " | 561 | IP_VS_DBG_RL_PKT(1, AF_INET, pp, skb, 0, "ip_vs_nat_xmit(): " |
| 545 | "stopping DNAT to loopback address"); | 562 | "stopping DNAT to loopback address"); |
| @@ -632,7 +649,9 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
| 632 | } | 649 | } |
| 633 | 650 | ||
| 634 | if (!(rt = __ip_vs_get_out_rt_v6(skb, cp->dest, &cp->daddr.in6, NULL, | 651 | if (!(rt = __ip_vs_get_out_rt_v6(skb, cp->dest, &cp->daddr.in6, NULL, |
| 635 | 0, 1|2|4))) | 652 | 0, (IP_VS_RT_MODE_LOCAL | |
| 653 | IP_VS_RT_MODE_NON_LOCAL | | ||
| 654 | IP_VS_RT_MODE_RDR)))) | ||
| 636 | goto tx_error_icmp; | 655 | goto tx_error_icmp; |
| 637 | local = __ip_vs_is_local_route6(rt); | 656 | local = __ip_vs_is_local_route6(rt); |
| 638 | /* | 657 | /* |
| @@ -748,6 +767,7 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
| 748 | struct ip_vs_protocol *pp) | 767 | struct ip_vs_protocol *pp) |
| 749 | { | 768 | { |
| 750 | struct rtable *rt; /* Route to the other host */ | 769 | struct rtable *rt; /* Route to the other host */ |
| 770 | __be32 saddr; /* Source for tunnel */ | ||
| 751 | struct net_device *tdev; /* Device to other host */ | 771 | struct net_device *tdev; /* Device to other host */ |
| 752 | struct iphdr *old_iph = ip_hdr(skb); | 772 | struct iphdr *old_iph = ip_hdr(skb); |
| 753 | u8 tos = old_iph->tos; | 773 | u8 tos = old_iph->tos; |
| @@ -761,7 +781,8 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
| 761 | 781 | ||
| 762 | if (!(rt = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip, | 782 | if (!(rt = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip, |
| 763 | RT_TOS(tos), IP_VS_RT_MODE_LOCAL | | 783 | RT_TOS(tos), IP_VS_RT_MODE_LOCAL | |
| 764 | IP_VS_RT_MODE_NON_LOCAL))) | 784 | IP_VS_RT_MODE_NON_LOCAL, |
| 785 | &saddr))) | ||
| 765 | goto tx_error_icmp; | 786 | goto tx_error_icmp; |
| 766 | if (rt->rt_flags & RTCF_LOCAL) { | 787 | if (rt->rt_flags & RTCF_LOCAL) { |
| 767 | ip_rt_put(rt); | 788 | ip_rt_put(rt); |
| @@ -829,8 +850,8 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
| 829 | iph->frag_off = df; | 850 | iph->frag_off = df; |
| 830 | iph->protocol = IPPROTO_IPIP; | 851 | iph->protocol = IPPROTO_IPIP; |
| 831 | iph->tos = tos; | 852 | iph->tos = tos; |
| 832 | iph->daddr = rt->rt_dst; | 853 | iph->daddr = cp->daddr.ip; |
| 833 | iph->saddr = rt->rt_src; | 854 | iph->saddr = saddr; |
| 834 | iph->ttl = old_iph->ttl; | 855 | iph->ttl = old_iph->ttl; |
| 835 | ip_select_ident(iph, &rt->dst, NULL); | 856 | ip_select_ident(iph, &rt->dst, NULL); |
| 836 | 857 | ||
| @@ -875,7 +896,8 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
| 875 | EnterFunction(10); | 896 | EnterFunction(10); |
| 876 | 897 | ||
| 877 | if (!(rt = __ip_vs_get_out_rt_v6(skb, cp->dest, &cp->daddr.in6, | 898 | if (!(rt = __ip_vs_get_out_rt_v6(skb, cp->dest, &cp->daddr.in6, |
| 878 | &saddr, 1, 1|2))) | 899 | &saddr, 1, (IP_VS_RT_MODE_LOCAL | |
| 900 | IP_VS_RT_MODE_NON_LOCAL)))) | ||
| 879 | goto tx_error_icmp; | 901 | goto tx_error_icmp; |
| 880 | if (__ip_vs_is_local_route6(rt)) { | 902 | if (__ip_vs_is_local_route6(rt)) { |
| 881 | dst_release(&rt->dst); | 903 | dst_release(&rt->dst); |
| @@ -992,7 +1014,7 @@ ip_vs_dr_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
| 992 | if (!(rt = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip, | 1014 | if (!(rt = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip, |
| 993 | RT_TOS(iph->tos), | 1015 | RT_TOS(iph->tos), |
| 994 | IP_VS_RT_MODE_LOCAL | | 1016 | IP_VS_RT_MODE_LOCAL | |
| 995 | IP_VS_RT_MODE_NON_LOCAL))) | 1017 | IP_VS_RT_MODE_NON_LOCAL, NULL))) |
| 996 | goto tx_error_icmp; | 1018 | goto tx_error_icmp; |
| 997 | if (rt->rt_flags & RTCF_LOCAL) { | 1019 | if (rt->rt_flags & RTCF_LOCAL) { |
| 998 | ip_rt_put(rt); | 1020 | ip_rt_put(rt); |
| @@ -1050,7 +1072,8 @@ ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
| 1050 | EnterFunction(10); | 1072 | EnterFunction(10); |
| 1051 | 1073 | ||
| 1052 | if (!(rt = __ip_vs_get_out_rt_v6(skb, cp->dest, &cp->daddr.in6, NULL, | 1074 | if (!(rt = __ip_vs_get_out_rt_v6(skb, cp->dest, &cp->daddr.in6, NULL, |
| 1053 | 0, 1|2))) | 1075 | 0, (IP_VS_RT_MODE_LOCAL | |
| 1076 | IP_VS_RT_MODE_NON_LOCAL)))) | ||
| 1054 | goto tx_error_icmp; | 1077 | goto tx_error_icmp; |
| 1055 | if (__ip_vs_is_local_route6(rt)) { | 1078 | if (__ip_vs_is_local_route6(rt)) { |
| 1056 | dst_release(&rt->dst); | 1079 | dst_release(&rt->dst); |
| @@ -1109,12 +1132,13 @@ tx_error: | |||
| 1109 | */ | 1132 | */ |
| 1110 | int | 1133 | int |
| 1111 | ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | 1134 | ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, |
| 1112 | struct ip_vs_protocol *pp, int offset) | 1135 | struct ip_vs_protocol *pp, int offset, unsigned int hooknum) |
| 1113 | { | 1136 | { |
| 1114 | struct rtable *rt; /* Route to the other host */ | 1137 | struct rtable *rt; /* Route to the other host */ |
| 1115 | int mtu; | 1138 | int mtu; |
| 1116 | int rc; | 1139 | int rc; |
| 1117 | int local; | 1140 | int local; |
| 1141 | int rt_mode; | ||
| 1118 | 1142 | ||
| 1119 | EnterFunction(10); | 1143 | EnterFunction(10); |
| 1120 | 1144 | ||
| @@ -1135,11 +1159,13 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
| 1135 | * mangle and send the packet here (only for VS/NAT) | 1159 | * mangle and send the packet here (only for VS/NAT) |
| 1136 | */ | 1160 | */ |
| 1137 | 1161 | ||
| 1162 | /* LOCALNODE from FORWARD hook is not supported */ | ||
| 1163 | rt_mode = (hooknum != NF_INET_FORWARD) ? | ||
| 1164 | IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL | | ||
| 1165 | IP_VS_RT_MODE_RDR : IP_VS_RT_MODE_NON_LOCAL; | ||
| 1138 | if (!(rt = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip, | 1166 | if (!(rt = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip, |
| 1139 | RT_TOS(ip_hdr(skb)->tos), | 1167 | RT_TOS(ip_hdr(skb)->tos), |
| 1140 | IP_VS_RT_MODE_LOCAL | | 1168 | rt_mode, NULL))) |
| 1141 | IP_VS_RT_MODE_NON_LOCAL | | ||
| 1142 | IP_VS_RT_MODE_RDR))) | ||
| 1143 | goto tx_error_icmp; | 1169 | goto tx_error_icmp; |
| 1144 | local = rt->rt_flags & RTCF_LOCAL; | 1170 | local = rt->rt_flags & RTCF_LOCAL; |
| 1145 | 1171 | ||
| @@ -1162,7 +1188,7 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
| 1162 | #endif | 1188 | #endif |
| 1163 | 1189 | ||
| 1164 | /* From world but DNAT to loopback address? */ | 1190 | /* From world but DNAT to loopback address? */ |
| 1165 | if (local && ipv4_is_loopback(rt->rt_dst) && | 1191 | if (local && ipv4_is_loopback(cp->daddr.ip) && |
| 1166 | rt_is_input_route(skb_rtable(skb))) { | 1192 | rt_is_input_route(skb_rtable(skb))) { |
| 1167 | IP_VS_DBG(1, "%s(): " | 1193 | IP_VS_DBG(1, "%s(): " |
| 1168 | "stopping DNAT to loopback %pI4\n", | 1194 | "stopping DNAT to loopback %pI4\n", |
| @@ -1227,12 +1253,13 @@ ip_vs_icmp_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
| 1227 | #ifdef CONFIG_IP_VS_IPV6 | 1253 | #ifdef CONFIG_IP_VS_IPV6 |
| 1228 | int | 1254 | int |
| 1229 | ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, | 1255 | ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, |
| 1230 | struct ip_vs_protocol *pp, int offset) | 1256 | struct ip_vs_protocol *pp, int offset, unsigned int hooknum) |
| 1231 | { | 1257 | { |
| 1232 | struct rt6_info *rt; /* Route to the other host */ | 1258 | struct rt6_info *rt; /* Route to the other host */ |
| 1233 | int mtu; | 1259 | int mtu; |
| 1234 | int rc; | 1260 | int rc; |
| 1235 | int local; | 1261 | int local; |
| 1262 | int rt_mode; | ||
| 1236 | 1263 | ||
| 1237 | EnterFunction(10); | 1264 | EnterFunction(10); |
| 1238 | 1265 | ||
| @@ -1253,8 +1280,12 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
| 1253 | * mangle and send the packet here (only for VS/NAT) | 1280 | * mangle and send the packet here (only for VS/NAT) |
| 1254 | */ | 1281 | */ |
| 1255 | 1282 | ||
| 1283 | /* LOCALNODE from FORWARD hook is not supported */ | ||
| 1284 | rt_mode = (hooknum != NF_INET_FORWARD) ? | ||
| 1285 | IP_VS_RT_MODE_LOCAL | IP_VS_RT_MODE_NON_LOCAL | | ||
| 1286 | IP_VS_RT_MODE_RDR : IP_VS_RT_MODE_NON_LOCAL; | ||
| 1256 | if (!(rt = __ip_vs_get_out_rt_v6(skb, cp->dest, &cp->daddr.in6, NULL, | 1287 | if (!(rt = __ip_vs_get_out_rt_v6(skb, cp->dest, &cp->daddr.in6, NULL, |
| 1257 | 0, 1|2|4))) | 1288 | 0, rt_mode))) |
| 1258 | goto tx_error_icmp; | 1289 | goto tx_error_icmp; |
| 1259 | 1290 | ||
| 1260 | local = __ip_vs_is_local_route6(rt); | 1291 | local = __ip_vs_is_local_route6(rt); |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 33d9ee629b4e..6766913a53e6 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
| @@ -1496,7 +1496,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 1496 | struct sctp_chunk *chunk; | 1496 | struct sctp_chunk *chunk; |
| 1497 | union sctp_addr to; | 1497 | union sctp_addr to; |
| 1498 | struct sockaddr *msg_name = NULL; | 1498 | struct sockaddr *msg_name = NULL; |
| 1499 | struct sctp_sndrcvinfo default_sinfo = { 0 }; | 1499 | struct sctp_sndrcvinfo default_sinfo; |
| 1500 | struct sctp_sndrcvinfo *sinfo; | 1500 | struct sctp_sndrcvinfo *sinfo; |
| 1501 | struct sctp_initmsg *sinit; | 1501 | struct sctp_initmsg *sinit; |
| 1502 | sctp_assoc_t associd = 0; | 1502 | sctp_assoc_t associd = 0; |
| @@ -1760,6 +1760,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 1760 | /* If the user didn't specify SNDRCVINFO, make up one with | 1760 | /* If the user didn't specify SNDRCVINFO, make up one with |
| 1761 | * some defaults. | 1761 | * some defaults. |
| 1762 | */ | 1762 | */ |
| 1763 | memset(&default_sinfo, 0, sizeof(default_sinfo)); | ||
| 1763 | default_sinfo.sinfo_stream = asoc->default_stream; | 1764 | default_sinfo.sinfo_stream = asoc->default_stream; |
| 1764 | default_sinfo.sinfo_flags = asoc->default_flags; | 1765 | default_sinfo.sinfo_flags = asoc->default_flags; |
| 1765 | default_sinfo.sinfo_ppid = asoc->default_ppid; | 1766 | default_sinfo.sinfo_ppid = asoc->default_ppid; |
| @@ -1790,12 +1791,10 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 1790 | goto out_free; | 1791 | goto out_free; |
| 1791 | } | 1792 | } |
| 1792 | 1793 | ||
| 1793 | if (sinfo) { | 1794 | /* Check for invalid stream. */ |
| 1794 | /* Check for invalid stream. */ | 1795 | if (sinfo->sinfo_stream >= asoc->c.sinit_num_ostreams) { |
| 1795 | if (sinfo->sinfo_stream >= asoc->c.sinit_num_ostreams) { | 1796 | err = -EINVAL; |
| 1796 | err = -EINVAL; | 1797 | goto out_free; |
| 1797 | goto out_free; | ||
| 1798 | } | ||
| 1799 | } | 1798 | } |
| 1800 | 1799 | ||
| 1801 | timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); | 1800 | timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); |
