diff options
Diffstat (limited to 'net')
329 files changed, 9119 insertions, 5466 deletions
diff --git a/net/802/garp.c b/net/802/garp.c index c1df2dad8c6b..f8300a8b5fbc 100644 --- a/net/802/garp.c +++ b/net/802/garp.c | |||
@@ -544,6 +544,11 @@ static int garp_init_port(struct net_device *dev) | |||
544 | return 0; | 544 | return 0; |
545 | } | 545 | } |
546 | 546 | ||
547 | static void garp_kfree_rcu(struct rcu_head *head) | ||
548 | { | ||
549 | kfree(container_of(head, struct garp_port, rcu)); | ||
550 | } | ||
551 | |||
547 | static void garp_release_port(struct net_device *dev) | 552 | static void garp_release_port(struct net_device *dev) |
548 | { | 553 | { |
549 | struct garp_port *port = rtnl_dereference(dev->garp_port); | 554 | struct garp_port *port = rtnl_dereference(dev->garp_port); |
@@ -554,8 +559,7 @@ static void garp_release_port(struct net_device *dev) | |||
554 | return; | 559 | return; |
555 | } | 560 | } |
556 | rcu_assign_pointer(dev->garp_port, NULL); | 561 | rcu_assign_pointer(dev->garp_port, NULL); |
557 | synchronize_rcu(); | 562 | call_rcu(&port->rcu, garp_kfree_rcu); |
558 | kfree(port); | ||
559 | } | 563 | } |
560 | 564 | ||
561 | int garp_init_applicant(struct net_device *dev, struct garp_application *appl) | 565 | int garp_init_applicant(struct net_device *dev, struct garp_application *appl) |
@@ -599,6 +603,11 @@ err1: | |||
599 | } | 603 | } |
600 | EXPORT_SYMBOL_GPL(garp_init_applicant); | 604 | EXPORT_SYMBOL_GPL(garp_init_applicant); |
601 | 605 | ||
606 | static void garp_app_kfree_rcu(struct rcu_head *head) | ||
607 | { | ||
608 | kfree(container_of(head, struct garp_applicant, rcu)); | ||
609 | } | ||
610 | |||
602 | 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) |
603 | { | 612 | { |
604 | struct garp_port *port = rtnl_dereference(dev->garp_port); | 613 | struct garp_port *port = rtnl_dereference(dev->garp_port); |
@@ -607,7 +616,6 @@ void garp_uninit_applicant(struct net_device *dev, struct garp_application *appl | |||
607 | ASSERT_RTNL(); | 616 | ASSERT_RTNL(); |
608 | 617 | ||
609 | rcu_assign_pointer(port->applicants[appl->type], NULL); | 618 | rcu_assign_pointer(port->applicants[appl->type], NULL); |
610 | synchronize_rcu(); | ||
611 | 619 | ||
612 | /* 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 |
613 | * all pending messages before the applicant is gone. */ | 621 | * all pending messages before the applicant is gone. */ |
@@ -617,7 +625,7 @@ void garp_uninit_applicant(struct net_device *dev, struct garp_application *appl | |||
617 | garp_queue_xmit(app); | 625 | garp_queue_xmit(app); |
618 | 626 | ||
619 | dev_mc_del(dev, appl->proto.group_address); | 627 | dev_mc_del(dev, appl->proto.group_address); |
620 | kfree(app); | 628 | call_rcu(&app->rcu, garp_app_kfree_rcu); |
621 | garp_release_port(dev); | 629 | garp_release_port(dev); |
622 | } | 630 | } |
623 | EXPORT_SYMBOL_GPL(garp_uninit_applicant); | 631 | EXPORT_SYMBOL_GPL(garp_uninit_applicant); |
@@ -635,3 +643,9 @@ void garp_unregister_application(struct garp_application *appl) | |||
635 | stp_proto_unregister(&appl->proto); | 643 | stp_proto_unregister(&appl->proto); |
636 | } | 644 | } |
637 | 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.c b/net/8021q/vlan.c index 7850412f52b7..b2274d1fd605 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c | |||
@@ -49,11 +49,6 @@ const char vlan_version[] = DRV_VERSION; | |||
49 | static const char vlan_copyright[] = "Ben Greear <greearb@candelatech.com>"; | 49 | static const char vlan_copyright[] = "Ben Greear <greearb@candelatech.com>"; |
50 | static const char vlan_buggyright[] = "David S. Miller <davem@redhat.com>"; | 50 | static const char vlan_buggyright[] = "David S. Miller <davem@redhat.com>"; |
51 | 51 | ||
52 | static struct packet_type vlan_packet_type __read_mostly = { | ||
53 | .type = cpu_to_be16(ETH_P_8021Q), | ||
54 | .func = vlan_skb_recv, /* VLAN receive method */ | ||
55 | }; | ||
56 | |||
57 | /* End of global variables definitions. */ | 52 | /* End of global variables definitions. */ |
58 | 53 | ||
59 | static void vlan_group_free(struct vlan_group *grp) | 54 | static void vlan_group_free(struct vlan_group *grp) |
@@ -124,10 +119,14 @@ void unregister_vlan_dev(struct net_device *dev, struct list_head *head) | |||
124 | 119 | ||
125 | grp->nr_vlans--; | 120 | grp->nr_vlans--; |
126 | 121 | ||
127 | vlan_group_set_device(grp, vlan_id, NULL); | 122 | if (vlan->flags & VLAN_FLAG_GVRP) |
128 | if (!grp->killall) | 123 | vlan_gvrp_request_leave(dev); |
129 | synchronize_net(); | ||
130 | 124 | ||
125 | vlan_group_set_device(grp, vlan_id, NULL); | ||
126 | /* Because unregister_netdevice_queue() makes sure at least one rcu | ||
127 | * grace period is respected before device freeing, | ||
128 | * we dont need to call synchronize_net() here. | ||
129 | */ | ||
131 | unregister_netdevice_queue(dev, head); | 130 | unregister_netdevice_queue(dev, head); |
132 | 131 | ||
133 | /* If the group is now empty, kill off the group. */ | 132 | /* If the group is now empty, kill off the group. */ |
@@ -327,10 +326,6 @@ static void vlan_sync_address(struct net_device *dev, | |||
327 | static void vlan_transfer_features(struct net_device *dev, | 326 | static void vlan_transfer_features(struct net_device *dev, |
328 | struct net_device *vlandev) | 327 | struct net_device *vlandev) |
329 | { | 328 | { |
330 | u32 old_features = vlandev->features; | ||
331 | |||
332 | vlandev->features &= ~dev->vlan_features; | ||
333 | vlandev->features |= dev->features & dev->vlan_features; | ||
334 | vlandev->gso_max_size = dev->gso_max_size; | 329 | vlandev->gso_max_size = dev->gso_max_size; |
335 | 330 | ||
336 | if (dev->features & NETIF_F_HW_VLAN_TX) | 331 | if (dev->features & NETIF_F_HW_VLAN_TX) |
@@ -341,8 +336,8 @@ static void vlan_transfer_features(struct net_device *dev, | |||
341 | #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) | 336 | #if defined(CONFIG_FCOE) || defined(CONFIG_FCOE_MODULE) |
342 | vlandev->fcoe_ddp_xid = dev->fcoe_ddp_xid; | 337 | vlandev->fcoe_ddp_xid = dev->fcoe_ddp_xid; |
343 | #endif | 338 | #endif |
344 | if (old_features != vlandev->features) | 339 | |
345 | netdev_features_change(vlandev); | 340 | netdev_update_features(vlandev); |
346 | } | 341 | } |
347 | 342 | ||
348 | static void __vlan_device_event(struct net_device *dev, unsigned long event) | 343 | static void __vlan_device_event(struct net_device *dev, unsigned long event) |
@@ -487,9 +482,6 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
487 | if (dev->reg_state != NETREG_UNREGISTERING) | 482 | if (dev->reg_state != NETREG_UNREGISTERING) |
488 | break; | 483 | break; |
489 | 484 | ||
490 | /* Delete all VLANs for this dev. */ | ||
491 | grp->killall = 1; | ||
492 | |||
493 | for (i = 0; i < VLAN_N_VID; i++) { | 485 | for (i = 0; i < VLAN_N_VID; i++) { |
494 | vlandev = vlan_group_get_device(grp, i); | 486 | vlandev = vlan_group_get_device(grp, i); |
495 | if (!vlandev) | 487 | if (!vlandev) |
@@ -508,6 +500,18 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
508 | case NETDEV_PRE_TYPE_CHANGE: | 500 | case NETDEV_PRE_TYPE_CHANGE: |
509 | /* Forbid underlaying device to change its type. */ | 501 | /* Forbid underlaying device to change its type. */ |
510 | return NOTIFY_BAD; | 502 | return NOTIFY_BAD; |
503 | |||
504 | case NETDEV_NOTIFY_PEERS: | ||
505 | case NETDEV_BONDING_FAILOVER: | ||
506 | /* Propagate to vlan devices */ | ||
507 | for (i = 0; i < VLAN_N_VID; i++) { | ||
508 | vlandev = vlan_group_get_device(grp, i); | ||
509 | if (!vlandev) | ||
510 | continue; | ||
511 | |||
512 | call_netdevice_notifiers(event, vlandev); | ||
513 | } | ||
514 | break; | ||
511 | } | 515 | } |
512 | 516 | ||
513 | out: | 517 | out: |
@@ -688,7 +692,6 @@ static int __init vlan_proto_init(void) | |||
688 | if (err < 0) | 692 | if (err < 0) |
689 | goto err4; | 693 | goto err4; |
690 | 694 | ||
691 | dev_add_pack(&vlan_packet_type); | ||
692 | vlan_ioctl_set(vlan_ioctl_handler); | 695 | vlan_ioctl_set(vlan_ioctl_handler); |
693 | return 0; | 696 | return 0; |
694 | 697 | ||
@@ -709,8 +712,6 @@ static void __exit vlan_cleanup_module(void) | |||
709 | 712 | ||
710 | unregister_netdevice_notifier(&vlan_notifier_block); | 713 | unregister_netdevice_notifier(&vlan_notifier_block); |
711 | 714 | ||
712 | dev_remove_pack(&vlan_packet_type); | ||
713 | |||
714 | unregister_pernet_subsys(&vlan_net_ops); | 715 | unregister_pernet_subsys(&vlan_net_ops); |
715 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ | 716 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ |
716 | 717 | ||
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h index 5687c9b95f33..c3408def8a19 100644 --- a/net/8021q/vlan.h +++ b/net/8021q/vlan.h | |||
@@ -75,8 +75,6 @@ static inline struct vlan_dev_info *vlan_dev_info(const struct net_device *dev) | |||
75 | } | 75 | } |
76 | 76 | ||
77 | /* found in vlan_dev.c */ | 77 | /* found in vlan_dev.c */ |
78 | int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, | ||
79 | struct packet_type *ptype, struct net_device *orig_dev); | ||
80 | void vlan_dev_set_ingress_priority(const struct net_device *dev, | 78 | void vlan_dev_set_ingress_priority(const struct net_device *dev, |
81 | u32 skb_prio, u16 vlan_prio); | 79 | u32 skb_prio, u16 vlan_prio); |
82 | int vlan_dev_set_egress_priority(const struct net_device *dev, | 80 | int vlan_dev_set_egress_priority(const struct net_device *dev, |
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index ce8e3ab3e7a5..41495dc2a4c9 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c | |||
@@ -4,7 +4,7 @@ | |||
4 | #include <linux/netpoll.h> | 4 | #include <linux/netpoll.h> |
5 | #include "vlan.h" | 5 | #include "vlan.h" |
6 | 6 | ||
7 | bool vlan_hwaccel_do_receive(struct sk_buff **skbp) | 7 | bool vlan_do_receive(struct sk_buff **skbp) |
8 | { | 8 | { |
9 | struct sk_buff *skb = *skbp; | 9 | struct sk_buff *skb = *skbp; |
10 | u16 vlan_id = skb->vlan_tci & VLAN_VID_MASK; | 10 | u16 vlan_id = skb->vlan_tci & VLAN_VID_MASK; |
@@ -88,3 +88,86 @@ gro_result_t vlan_gro_frags(struct napi_struct *napi, struct vlan_group *grp, | |||
88 | return napi_gro_frags(napi); | 88 | return napi_gro_frags(napi); |
89 | } | 89 | } |
90 | EXPORT_SYMBOL(vlan_gro_frags); | 90 | EXPORT_SYMBOL(vlan_gro_frags); |
91 | |||
92 | static struct sk_buff *vlan_check_reorder_header(struct sk_buff *skb) | ||
93 | { | ||
94 | if (vlan_dev_info(skb->dev)->flags & VLAN_FLAG_REORDER_HDR) { | ||
95 | if (skb_cow(skb, skb_headroom(skb)) < 0) | ||
96 | skb = NULL; | ||
97 | if (skb) { | ||
98 | /* Lifted from Gleb's VLAN code... */ | ||
99 | memmove(skb->data - ETH_HLEN, | ||
100 | skb->data - VLAN_ETH_HLEN, 12); | ||
101 | skb->mac_header += VLAN_HLEN; | ||
102 | } | ||
103 | } | ||
104 | return skb; | ||
105 | } | ||
106 | |||
107 | static void vlan_set_encap_proto(struct sk_buff *skb, struct vlan_hdr *vhdr) | ||
108 | { | ||
109 | __be16 proto; | ||
110 | unsigned char *rawp; | ||
111 | |||
112 | /* | ||
113 | * Was a VLAN packet, grab the encapsulated protocol, which the layer | ||
114 | * three protocols care about. | ||
115 | */ | ||
116 | |||
117 | proto = vhdr->h_vlan_encapsulated_proto; | ||
118 | if (ntohs(proto) >= 1536) { | ||
119 | skb->protocol = proto; | ||
120 | return; | ||
121 | } | ||
122 | |||
123 | rawp = skb->data; | ||
124 | if (*(unsigned short *) rawp == 0xFFFF) | ||
125 | /* | ||
126 | * This is a magic hack to spot IPX packets. Older Novell | ||
127 | * breaks the protocol design and runs IPX over 802.3 without | ||
128 | * an 802.2 LLC layer. We look for FFFF which isn't a used | ||
129 | * 802.2 SSAP/DSAP. This won't work for fault tolerant netware | ||
130 | * but does for the rest. | ||
131 | */ | ||
132 | skb->protocol = htons(ETH_P_802_3); | ||
133 | else | ||
134 | /* | ||
135 | * Real 802.2 LLC | ||
136 | */ | ||
137 | skb->protocol = htons(ETH_P_802_2); | ||
138 | } | ||
139 | |||
140 | struct sk_buff *vlan_untag(struct sk_buff *skb) | ||
141 | { | ||
142 | struct vlan_hdr *vhdr; | ||
143 | u16 vlan_tci; | ||
144 | |||
145 | if (unlikely(vlan_tx_tag_present(skb))) { | ||
146 | /* vlan_tci is already set-up so leave this for another time */ | ||
147 | return skb; | ||
148 | } | ||
149 | |||
150 | skb = skb_share_check(skb, GFP_ATOMIC); | ||
151 | if (unlikely(!skb)) | ||
152 | goto err_free; | ||
153 | |||
154 | if (unlikely(!pskb_may_pull(skb, VLAN_HLEN))) | ||
155 | goto err_free; | ||
156 | |||
157 | vhdr = (struct vlan_hdr *) skb->data; | ||
158 | vlan_tci = ntohs(vhdr->h_vlan_TCI); | ||
159 | __vlan_hwaccel_put_tag(skb, vlan_tci); | ||
160 | |||
161 | skb_pull_rcsum(skb, VLAN_HLEN); | ||
162 | vlan_set_encap_proto(skb, vhdr); | ||
163 | |||
164 | skb = vlan_check_reorder_header(skb); | ||
165 | if (unlikely(!skb)) | ||
166 | goto err_free; | ||
167 | |||
168 | return skb; | ||
169 | |||
170 | err_free: | ||
171 | kfree_skb(skb); | ||
172 | return NULL; | ||
173 | } | ||
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index e34ea9e5e28b..f247f5bff88d 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
@@ -65,179 +65,6 @@ static int vlan_dev_rebuild_header(struct sk_buff *skb) | |||
65 | return 0; | 65 | return 0; |
66 | } | 66 | } |
67 | 67 | ||
68 | static inline struct sk_buff *vlan_check_reorder_header(struct sk_buff *skb) | ||
69 | { | ||
70 | if (vlan_dev_info(skb->dev)->flags & VLAN_FLAG_REORDER_HDR) { | ||
71 | if (skb_cow(skb, skb_headroom(skb)) < 0) | ||
72 | skb = NULL; | ||
73 | if (skb) { | ||
74 | /* Lifted from Gleb's VLAN code... */ | ||
75 | memmove(skb->data - ETH_HLEN, | ||
76 | skb->data - VLAN_ETH_HLEN, 12); | ||
77 | skb->mac_header += VLAN_HLEN; | ||
78 | } | ||
79 | } | ||
80 | |||
81 | return skb; | ||
82 | } | ||
83 | |||
84 | static inline void vlan_set_encap_proto(struct sk_buff *skb, | ||
85 | struct vlan_hdr *vhdr) | ||
86 | { | ||
87 | __be16 proto; | ||
88 | unsigned char *rawp; | ||
89 | |||
90 | /* | ||
91 | * Was a VLAN packet, grab the encapsulated protocol, which the layer | ||
92 | * three protocols care about. | ||
93 | */ | ||
94 | |||
95 | proto = vhdr->h_vlan_encapsulated_proto; | ||
96 | if (ntohs(proto) >= 1536) { | ||
97 | skb->protocol = proto; | ||
98 | return; | ||
99 | } | ||
100 | |||
101 | rawp = skb->data; | ||
102 | if (*(unsigned short *)rawp == 0xFFFF) | ||
103 | /* | ||
104 | * This is a magic hack to spot IPX packets. Older Novell | ||
105 | * breaks the protocol design and runs IPX over 802.3 without | ||
106 | * an 802.2 LLC layer. We look for FFFF which isn't a used | ||
107 | * 802.2 SSAP/DSAP. This won't work for fault tolerant netware | ||
108 | * but does for the rest. | ||
109 | */ | ||
110 | skb->protocol = htons(ETH_P_802_3); | ||
111 | else | ||
112 | /* | ||
113 | * Real 802.2 LLC | ||
114 | */ | ||
115 | skb->protocol = htons(ETH_P_802_2); | ||
116 | } | ||
117 | |||
118 | /* | ||
119 | * Determine the packet's protocol ID. The rule here is that we | ||
120 | * assume 802.3 if the type field is short enough to be a length. | ||
121 | * This is normal practice and works for any 'now in use' protocol. | ||
122 | * | ||
123 | * Also, at this point we assume that we ARE dealing exclusively with | ||
124 | * VLAN packets, or packets that should be made into VLAN packets based | ||
125 | * on a default VLAN ID. | ||
126 | * | ||
127 | * NOTE: Should be similar to ethernet/eth.c. | ||
128 | * | ||
129 | * SANITY NOTE: This method is called when a packet is moving up the stack | ||
130 | * towards userland. To get here, it would have already passed | ||
131 | * through the ethernet/eth.c eth_type_trans() method. | ||
132 | * SANITY NOTE 2: We are referencing to the VLAN_HDR frields, which MAY be | ||
133 | * stored UNALIGNED in the memory. RISC systems don't like | ||
134 | * such cases very much... | ||
135 | * SANITY NOTE 2a: According to Dave Miller & Alexey, it will always be | ||
136 | * aligned, so there doesn't need to be any of the unaligned | ||
137 | * stuff. It has been commented out now... --Ben | ||
138 | * | ||
139 | */ | ||
140 | int vlan_skb_recv(struct sk_buff *skb, struct net_device *dev, | ||
141 | struct packet_type *ptype, struct net_device *orig_dev) | ||
142 | { | ||
143 | struct vlan_hdr *vhdr; | ||
144 | struct vlan_pcpu_stats *rx_stats; | ||
145 | struct net_device *vlan_dev; | ||
146 | u16 vlan_id; | ||
147 | u16 vlan_tci; | ||
148 | |||
149 | skb = skb_share_check(skb, GFP_ATOMIC); | ||
150 | if (skb == NULL) | ||
151 | goto err_free; | ||
152 | |||
153 | if (unlikely(!pskb_may_pull(skb, VLAN_HLEN))) | ||
154 | goto err_free; | ||
155 | |||
156 | vhdr = (struct vlan_hdr *)skb->data; | ||
157 | vlan_tci = ntohs(vhdr->h_vlan_TCI); | ||
158 | vlan_id = vlan_tci & VLAN_VID_MASK; | ||
159 | |||
160 | rcu_read_lock(); | ||
161 | vlan_dev = vlan_find_dev(dev, vlan_id); | ||
162 | |||
163 | /* If the VLAN device is defined, we use it. | ||
164 | * If not, and the VID is 0, it is a 802.1p packet (not | ||
165 | * really a VLAN), so we will just netif_rx it later to the | ||
166 | * original interface, but with the skb->proto set to the | ||
167 | * wrapped proto: we do nothing here. | ||
168 | */ | ||
169 | |||
170 | if (!vlan_dev) { | ||
171 | if (vlan_id) { | ||
172 | pr_debug("%s: ERROR: No net_device for VID: %u on dev: %s\n", | ||
173 | __func__, vlan_id, dev->name); | ||
174 | goto err_unlock; | ||
175 | } | ||
176 | rx_stats = NULL; | ||
177 | } else { | ||
178 | skb->dev = vlan_dev; | ||
179 | |||
180 | rx_stats = this_cpu_ptr(vlan_dev_info(skb->dev)->vlan_pcpu_stats); | ||
181 | |||
182 | u64_stats_update_begin(&rx_stats->syncp); | ||
183 | rx_stats->rx_packets++; | ||
184 | rx_stats->rx_bytes += skb->len; | ||
185 | |||
186 | skb->priority = vlan_get_ingress_priority(skb->dev, vlan_tci); | ||
187 | |||
188 | pr_debug("%s: priority: %u for TCI: %hu\n", | ||
189 | __func__, skb->priority, vlan_tci); | ||
190 | |||
191 | switch (skb->pkt_type) { | ||
192 | case PACKET_BROADCAST: | ||
193 | /* Yeah, stats collect these together.. */ | ||
194 | /* stats->broadcast ++; // no such counter :-( */ | ||
195 | break; | ||
196 | |||
197 | case PACKET_MULTICAST: | ||
198 | rx_stats->rx_multicast++; | ||
199 | break; | ||
200 | |||
201 | case PACKET_OTHERHOST: | ||
202 | /* Our lower layer thinks this is not local, let's make | ||
203 | * sure. | ||
204 | * This allows the VLAN to have a different MAC than the | ||
205 | * underlying device, and still route correctly. | ||
206 | */ | ||
207 | if (!compare_ether_addr(eth_hdr(skb)->h_dest, | ||
208 | skb->dev->dev_addr)) | ||
209 | skb->pkt_type = PACKET_HOST; | ||
210 | break; | ||
211 | default: | ||
212 | break; | ||
213 | } | ||
214 | u64_stats_update_end(&rx_stats->syncp); | ||
215 | } | ||
216 | |||
217 | skb_pull_rcsum(skb, VLAN_HLEN); | ||
218 | vlan_set_encap_proto(skb, vhdr); | ||
219 | |||
220 | if (vlan_dev) { | ||
221 | skb = vlan_check_reorder_header(skb); | ||
222 | if (!skb) { | ||
223 | rx_stats->rx_errors++; | ||
224 | goto err_unlock; | ||
225 | } | ||
226 | } | ||
227 | |||
228 | netif_rx(skb); | ||
229 | |||
230 | rcu_read_unlock(); | ||
231 | return NET_RX_SUCCESS; | ||
232 | |||
233 | err_unlock: | ||
234 | rcu_read_unlock(); | ||
235 | err_free: | ||
236 | atomic_long_inc(&dev->rx_dropped); | ||
237 | kfree_skb(skb); | ||
238 | return NET_RX_DROP; | ||
239 | } | ||
240 | |||
241 | static inline u16 | 68 | static inline u16 |
242 | vlan_dev_get_egress_qos_mask(struct net_device *dev, struct sk_buff *skb) | 69 | vlan_dev_get_egress_qos_mask(struct net_device *dev, struct sk_buff *skb) |
243 | { | 70 | { |
@@ -487,9 +314,6 @@ static int vlan_dev_stop(struct net_device *dev) | |||
487 | struct vlan_dev_info *vlan = vlan_dev_info(dev); | 314 | struct vlan_dev_info *vlan = vlan_dev_info(dev); |
488 | struct net_device *real_dev = vlan->real_dev; | 315 | struct net_device *real_dev = vlan->real_dev; |
489 | 316 | ||
490 | if (vlan->flags & VLAN_FLAG_GVRP) | ||
491 | vlan_gvrp_request_leave(dev); | ||
492 | |||
493 | dev_mc_unsync(real_dev, dev); | 317 | dev_mc_unsync(real_dev, dev); |
494 | dev_uc_unsync(real_dev, dev); | 318 | dev_uc_unsync(real_dev, dev); |
495 | if (dev->flags & IFF_ALLMULTI) | 319 | if (dev->flags & IFF_ALLMULTI) |
@@ -704,8 +528,8 @@ static int vlan_dev_init(struct net_device *dev) | |||
704 | (1<<__LINK_STATE_DORMANT))) | | 528 | (1<<__LINK_STATE_DORMANT))) | |
705 | (1<<__LINK_STATE_PRESENT); | 529 | (1<<__LINK_STATE_PRESENT); |
706 | 530 | ||
707 | dev->features |= real_dev->features & real_dev->vlan_features; | 531 | dev->hw_features = NETIF_F_ALL_TX_OFFLOADS; |
708 | dev->features |= NETIF_F_LLTX; | 532 | dev->features |= real_dev->vlan_features | NETIF_F_LLTX; |
709 | dev->gso_max_size = real_dev->gso_max_size; | 533 | dev->gso_max_size = real_dev->gso_max_size; |
710 | 534 | ||
711 | /* ipv6 shared card related stuff */ | 535 | /* ipv6 shared card related stuff */ |
@@ -759,6 +583,19 @@ static void vlan_dev_uninit(struct net_device *dev) | |||
759 | } | 583 | } |
760 | } | 584 | } |
761 | 585 | ||
586 | static u32 vlan_dev_fix_features(struct net_device *dev, u32 features) | ||
587 | { | ||
588 | struct net_device *real_dev = vlan_dev_info(dev)->real_dev; | ||
589 | |||
590 | features &= real_dev->features; | ||
591 | features &= real_dev->vlan_features; | ||
592 | if (dev_ethtool_get_rx_csum(real_dev)) | ||
593 | features |= NETIF_F_RXCSUM; | ||
594 | features |= NETIF_F_LLTX; | ||
595 | |||
596 | return features; | ||
597 | } | ||
598 | |||
762 | static int vlan_ethtool_get_settings(struct net_device *dev, | 599 | static int vlan_ethtool_get_settings(struct net_device *dev, |
763 | struct ethtool_cmd *cmd) | 600 | struct ethtool_cmd *cmd) |
764 | { | 601 | { |
@@ -774,18 +611,6 @@ static void vlan_ethtool_get_drvinfo(struct net_device *dev, | |||
774 | strcpy(info->fw_version, "N/A"); | 611 | strcpy(info->fw_version, "N/A"); |
775 | } | 612 | } |
776 | 613 | ||
777 | static u32 vlan_ethtool_get_rx_csum(struct net_device *dev) | ||
778 | { | ||
779 | const struct vlan_dev_info *vlan = vlan_dev_info(dev); | ||
780 | return dev_ethtool_get_rx_csum(vlan->real_dev); | ||
781 | } | ||
782 | |||
783 | static u32 vlan_ethtool_get_flags(struct net_device *dev) | ||
784 | { | ||
785 | const struct vlan_dev_info *vlan = vlan_dev_info(dev); | ||
786 | return dev_ethtool_get_flags(vlan->real_dev); | ||
787 | } | ||
788 | |||
789 | static struct rtnl_link_stats64 *vlan_dev_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) | 614 | static struct rtnl_link_stats64 *vlan_dev_get_stats64(struct net_device *dev, struct rtnl_link_stats64 *stats) |
790 | { | 615 | { |
791 | 616 | ||
@@ -823,32 +648,10 @@ static struct rtnl_link_stats64 *vlan_dev_get_stats64(struct net_device *dev, st | |||
823 | return stats; | 648 | return stats; |
824 | } | 649 | } |
825 | 650 | ||
826 | static int vlan_ethtool_set_tso(struct net_device *dev, u32 data) | ||
827 | { | ||
828 | if (data) { | ||
829 | struct net_device *real_dev = vlan_dev_info(dev)->real_dev; | ||
830 | |||
831 | /* Underlying device must support TSO for VLAN-tagged packets | ||
832 | * and must have TSO enabled now. | ||
833 | */ | ||
834 | if (!(real_dev->vlan_features & NETIF_F_TSO)) | ||
835 | return -EOPNOTSUPP; | ||
836 | if (!(real_dev->features & NETIF_F_TSO)) | ||
837 | return -EINVAL; | ||
838 | dev->features |= NETIF_F_TSO; | ||
839 | } else { | ||
840 | dev->features &= ~NETIF_F_TSO; | ||
841 | } | ||
842 | return 0; | ||
843 | } | ||
844 | |||
845 | static const struct ethtool_ops vlan_ethtool_ops = { | 651 | static const struct ethtool_ops vlan_ethtool_ops = { |
846 | .get_settings = vlan_ethtool_get_settings, | 652 | .get_settings = vlan_ethtool_get_settings, |
847 | .get_drvinfo = vlan_ethtool_get_drvinfo, | 653 | .get_drvinfo = vlan_ethtool_get_drvinfo, |
848 | .get_link = ethtool_op_get_link, | 654 | .get_link = ethtool_op_get_link, |
849 | .get_rx_csum = vlan_ethtool_get_rx_csum, | ||
850 | .get_flags = vlan_ethtool_get_flags, | ||
851 | .set_tso = vlan_ethtool_set_tso, | ||
852 | }; | 655 | }; |
853 | 656 | ||
854 | static const struct net_device_ops vlan_netdev_ops = { | 657 | static const struct net_device_ops vlan_netdev_ops = { |
@@ -874,6 +677,7 @@ static const struct net_device_ops vlan_netdev_ops = { | |||
874 | .ndo_fcoe_get_wwn = vlan_dev_fcoe_get_wwn, | 677 | .ndo_fcoe_get_wwn = vlan_dev_fcoe_get_wwn, |
875 | .ndo_fcoe_ddp_target = vlan_dev_fcoe_ddp_target, | 678 | .ndo_fcoe_ddp_target = vlan_dev_fcoe_ddp_target, |
876 | #endif | 679 | #endif |
680 | .ndo_fix_features = vlan_dev_fix_features, | ||
877 | }; | 681 | }; |
878 | 682 | ||
879 | void vlan_setup(struct net_device *dev) | 683 | void vlan_setup(struct net_device *dev) |
diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c index d1314cf18adf..d940c49d168a 100644 --- a/net/8021q/vlanproc.c +++ b/net/8021q/vlanproc.c | |||
@@ -54,7 +54,7 @@ static const char name_conf[] = "config"; | |||
54 | 54 | ||
55 | /* | 55 | /* |
56 | * Structures for interfacing with the /proc filesystem. | 56 | * Structures for interfacing with the /proc filesystem. |
57 | * VLAN creates its own directory /proc/net/vlan with the folowing | 57 | * VLAN creates its own directory /proc/net/vlan with the following |
58 | * entries: | 58 | * entries: |
59 | * config device status/configuration | 59 | * config device status/configuration |
60 | * <device> entry for each device | 60 | * <device> entry for each device |
diff --git a/net/9p/client.c b/net/9p/client.c index 2ccbf04d37df..0ce959218607 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
@@ -178,7 +178,7 @@ free_and_return: | |||
178 | * @tag: numeric id for transaction | 178 | * @tag: numeric id for transaction |
179 | * | 179 | * |
180 | * this is a simple array lookup, but will grow the | 180 | * this is a simple array lookup, but will grow the |
181 | * request_slots as necessary to accomodate transaction | 181 | * request_slots as necessary to accommodate transaction |
182 | * ids which did not previously have a slot. | 182 | * ids which did not previously have a slot. |
183 | * | 183 | * |
184 | * this code relies on the client spinlock to manage locks, its | 184 | * this code relies on the client spinlock to manage locks, its |
@@ -1302,7 +1302,7 @@ int | |||
1302 | p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset, | 1302 | p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset, |
1303 | u32 count) | 1303 | u32 count) |
1304 | { | 1304 | { |
1305 | int err, rsize, total; | 1305 | int err, rsize; |
1306 | struct p9_client *clnt; | 1306 | struct p9_client *clnt; |
1307 | struct p9_req_t *req; | 1307 | struct p9_req_t *req; |
1308 | char *dataptr; | 1308 | char *dataptr; |
@@ -1311,7 +1311,6 @@ p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset, | |||
1311 | (long long unsigned) offset, count); | 1311 | (long long unsigned) offset, count); |
1312 | err = 0; | 1312 | err = 0; |
1313 | clnt = fid->clnt; | 1313 | clnt = fid->clnt; |
1314 | total = 0; | ||
1315 | 1314 | ||
1316 | rsize = fid->iounit; | 1315 | rsize = fid->iounit; |
1317 | if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) | 1316 | if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) |
@@ -1367,7 +1366,7 @@ int | |||
1367 | p9_client_write(struct p9_fid *fid, char *data, const char __user *udata, | 1366 | p9_client_write(struct p9_fid *fid, char *data, const char __user *udata, |
1368 | u64 offset, u32 count) | 1367 | u64 offset, u32 count) |
1369 | { | 1368 | { |
1370 | int err, rsize, total; | 1369 | int err, rsize; |
1371 | struct p9_client *clnt; | 1370 | struct p9_client *clnt; |
1372 | struct p9_req_t *req; | 1371 | struct p9_req_t *req; |
1373 | 1372 | ||
@@ -1375,7 +1374,6 @@ p9_client_write(struct p9_fid *fid, char *data, const char __user *udata, | |||
1375 | fid->fid, (long long unsigned) offset, count); | 1374 | fid->fid, (long long unsigned) offset, count); |
1376 | err = 0; | 1375 | err = 0; |
1377 | clnt = fid->clnt; | 1376 | clnt = fid->clnt; |
1378 | total = 0; | ||
1379 | 1377 | ||
1380 | rsize = fid->iounit; | 1378 | rsize = fid->iounit; |
1381 | if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) | 1379 | if (!rsize || rsize > clnt->msize-P9_IOHDRSZ) |
@@ -1766,7 +1764,7 @@ EXPORT_SYMBOL_GPL(p9_client_xattrcreate); | |||
1766 | 1764 | ||
1767 | int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset) | 1765 | int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset) |
1768 | { | 1766 | { |
1769 | int err, rsize, total; | 1767 | int err, rsize; |
1770 | struct p9_client *clnt; | 1768 | struct p9_client *clnt; |
1771 | struct p9_req_t *req; | 1769 | struct p9_req_t *req; |
1772 | char *dataptr; | 1770 | char *dataptr; |
@@ -1776,7 +1774,6 @@ int p9_client_readdir(struct p9_fid *fid, char *data, u32 count, u64 offset) | |||
1776 | 1774 | ||
1777 | err = 0; | 1775 | err = 0; |
1778 | clnt = fid->clnt; | 1776 | clnt = fid->clnt; |
1779 | total = 0; | ||
1780 | 1777 | ||
1781 | rsize = fid->iounit; | 1778 | rsize = fid->iounit; |
1782 | if (!rsize || rsize > clnt->msize-P9_READDIRHDRSZ) | 1779 | if (!rsize || rsize > clnt->msize-P9_READDIRHDRSZ) |
diff --git a/net/9p/trans_common.c b/net/9p/trans_common.c index 9172ab78fcb0..d47880e971dd 100644 --- a/net/9p/trans_common.c +++ b/net/9p/trans_common.c | |||
@@ -36,7 +36,7 @@ p9_release_req_pages(struct trans_rpage_info *rpinfo) | |||
36 | EXPORT_SYMBOL(p9_release_req_pages); | 36 | EXPORT_SYMBOL(p9_release_req_pages); |
37 | 37 | ||
38 | /** | 38 | /** |
39 | * p9_nr_pages - Return number of pages needed to accomodate the payload. | 39 | * p9_nr_pages - Return number of pages needed to accommodate the payload. |
40 | */ | 40 | */ |
41 | int | 41 | int |
42 | p9_nr_pages(struct p9_req_t *req) | 42 | p9_nr_pages(struct p9_req_t *req) |
@@ -55,7 +55,7 @@ EXPORT_SYMBOL(p9_nr_pages); | |||
55 | * @req: Request to be sent to server. | 55 | * @req: Request to be sent to server. |
56 | * @pdata_off: data offset into the first page after translation (gup). | 56 | * @pdata_off: data offset into the first page after translation (gup). |
57 | * @pdata_len: Total length of the IO. gup may not return requested # of pages. | 57 | * @pdata_len: Total length of the IO. gup may not return requested # of pages. |
58 | * @nr_pages: number of pages to accomodate the payload | 58 | * @nr_pages: number of pages to accommodate the payload |
59 | * @rw: Indicates if the pages are for read or write. | 59 | * @rw: Indicates if the pages are for read or write. |
60 | */ | 60 | */ |
61 | int | 61 | int |
diff --git a/net/9p/util.c b/net/9p/util.c index b84619b5ba22..da6af81e59d9 100644 --- a/net/9p/util.c +++ b/net/9p/util.c | |||
@@ -67,7 +67,7 @@ EXPORT_SYMBOL(p9_idpool_create); | |||
67 | 67 | ||
68 | /** | 68 | /** |
69 | * p9_idpool_destroy - create a new per-connection id pool | 69 | * p9_idpool_destroy - create a new per-connection id pool |
70 | * @p: idpool to destory | 70 | * @p: idpool to destroy |
71 | */ | 71 | */ |
72 | 72 | ||
73 | void p9_idpool_destroy(struct p9_idpool *p) | 73 | void p9_idpool_destroy(struct p9_idpool *p) |
diff --git a/net/Kconfig b/net/Kconfig index 79cabf1ee68b..878151c772c9 100644 --- a/net/Kconfig +++ b/net/Kconfig | |||
@@ -232,6 +232,20 @@ config XPS | |||
232 | depends on SMP && SYSFS && USE_GENERIC_SMP_HELPERS | 232 | depends on SMP && SYSFS && USE_GENERIC_SMP_HELPERS |
233 | default y | 233 | default y |
234 | 234 | ||
235 | config HAVE_BPF_JIT | ||
236 | bool | ||
237 | |||
238 | config BPF_JIT | ||
239 | bool "enable BPF Just In Time compiler" | ||
240 | depends on HAVE_BPF_JIT | ||
241 | depends on MODULES | ||
242 | ---help--- | ||
243 | Berkeley Packet Filter filtering capabilities are normally handled | ||
244 | by an interpreter. This option allows kernel to generate a native | ||
245 | code when filter is loaded in memory. This should speedup | ||
246 | packet sniffing (libpcap/tcpdump). Note : Admin should enable | ||
247 | this feature changing /proc/sys/net/core/bpf_jit_enable | ||
248 | |||
235 | menu "Network testing" | 249 | menu "Network testing" |
236 | 250 | ||
237 | config NET_PKTGEN | 251 | config NET_PKTGEN |
diff --git a/net/atm/br2684.c b/net/atm/br2684.c index fce2eae8d476..2252c2085dac 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c | |||
@@ -509,7 +509,7 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg) | |||
509 | write_lock_irq(&devs_lock); | 509 | write_lock_irq(&devs_lock); |
510 | net_dev = br2684_find_dev(&be.ifspec); | 510 | net_dev = br2684_find_dev(&be.ifspec); |
511 | if (net_dev == NULL) { | 511 | if (net_dev == NULL) { |
512 | pr_err("tried to attach to non-existant device\n"); | 512 | pr_err("tried to attach to non-existent device\n"); |
513 | err = -ENXIO; | 513 | err = -ENXIO; |
514 | goto error; | 514 | goto error; |
515 | } | 515 | } |
diff --git a/net/atm/lec.c b/net/atm/lec.c index 38754fdb88ba..25073b6ef474 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c | |||
@@ -129,7 +129,6 @@ static struct net_device *dev_lec[MAX_LEC_ITF]; | |||
129 | #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) | 129 | #if defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) |
130 | static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev) | 130 | static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev) |
131 | { | 131 | { |
132 | struct ethhdr *eth; | ||
133 | char *buff; | 132 | char *buff; |
134 | struct lec_priv *priv; | 133 | struct lec_priv *priv; |
135 | 134 | ||
@@ -138,7 +137,6 @@ static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev) | |||
138 | * LE_TOPOLOGY_REQUEST with the same value of Topology Change bit | 137 | * LE_TOPOLOGY_REQUEST with the same value of Topology Change bit |
139 | * as the Config BPDU has | 138 | * as the Config BPDU has |
140 | */ | 139 | */ |
141 | eth = (struct ethhdr *)skb->data; | ||
142 | buff = skb->data + skb->dev->hard_header_len; | 140 | buff = skb->data + skb->dev->hard_header_len; |
143 | if (*buff++ == 0x42 && *buff++ == 0x42 && *buff++ == 0x03) { | 141 | if (*buff++ == 0x42 && *buff++ == 0x42 && *buff++ == 0x03) { |
144 | struct sock *sk; | 142 | struct sock *sk; |
@@ -1180,7 +1178,6 @@ static int __init lane_module_init(void) | |||
1180 | static void __exit lane_module_cleanup(void) | 1178 | static void __exit lane_module_cleanup(void) |
1181 | { | 1179 | { |
1182 | int i; | 1180 | int i; |
1183 | struct lec_priv *priv; | ||
1184 | 1181 | ||
1185 | remove_proc_entry("lec", atm_proc_root); | 1182 | remove_proc_entry("lec", atm_proc_root); |
1186 | 1183 | ||
@@ -1188,7 +1185,6 @@ static void __exit lane_module_cleanup(void) | |||
1188 | 1185 | ||
1189 | for (i = 0; i < MAX_LEC_ITF; i++) { | 1186 | for (i = 0; i < MAX_LEC_ITF; i++) { |
1190 | if (dev_lec[i] != NULL) { | 1187 | if (dev_lec[i] != NULL) { |
1191 | priv = netdev_priv(dev_lec[i]); | ||
1192 | unregister_netdev(dev_lec[i]); | 1188 | unregister_netdev(dev_lec[i]); |
1193 | free_netdev(dev_lec[i]); | 1189 | free_netdev(dev_lec[i]); |
1194 | dev_lec[i] = NULL; | 1190 | dev_lec[i] = NULL; |
diff --git a/net/atm/lec.h b/net/atm/lec.h index 9d14d196cc1d..dfc071966463 100644 --- a/net/atm/lec.h +++ b/net/atm/lec.h | |||
@@ -35,7 +35,7 @@ struct lecdatahdr_8025 { | |||
35 | * Operations that LANE2 capable device can do. Two first functions | 35 | * Operations that LANE2 capable device can do. Two first functions |
36 | * are used to make the device do things. See spec 3.1.3 and 3.1.4. | 36 | * are used to make the device do things. See spec 3.1.3 and 3.1.4. |
37 | * | 37 | * |
38 | * The third function is intented for the MPOA component sitting on | 38 | * The third function is intended for the MPOA component sitting on |
39 | * top of the LANE device. The MPOA component assigns it's own function | 39 | * top of the LANE device. The MPOA component assigns it's own function |
40 | * to (*associate_indicator)() and the LANE device will use that | 40 | * to (*associate_indicator)() and the LANE device will use that |
41 | * function to tell about TLVs it sees floating through. | 41 | * function to tell about TLVs it sees floating through. |
diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index 6da5daeebab7..e7c69f4619ec 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c | |||
@@ -1538,8 +1538,6 @@ static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1538 | } | 1538 | } |
1539 | 1539 | ||
1540 | /* Build a packet */ | 1540 | /* Build a packet */ |
1541 | SOCK_DEBUG(sk, "AX.25: sendto: Addresses built. Building packet.\n"); | ||
1542 | |||
1543 | /* Assume the worst case */ | 1541 | /* Assume the worst case */ |
1544 | size = len + ax25->ax25_dev->dev->hard_header_len; | 1542 | size = len + ax25->ax25_dev->dev->hard_header_len; |
1545 | 1543 | ||
@@ -1549,8 +1547,6 @@ static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1549 | 1547 | ||
1550 | skb_reserve(skb, size - len); | 1548 | skb_reserve(skb, size - len); |
1551 | 1549 | ||
1552 | SOCK_DEBUG(sk, "AX.25: Appending user data\n"); | ||
1553 | |||
1554 | /* User data follows immediately after the AX.25 data */ | 1550 | /* User data follows immediately after the AX.25 data */ |
1555 | if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { | 1551 | if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { |
1556 | err = -EFAULT; | 1552 | err = -EFAULT; |
@@ -1564,8 +1560,6 @@ static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1564 | if (!ax25->pidincl) | 1560 | if (!ax25->pidincl) |
1565 | *skb_push(skb, 1) = sk->sk_protocol; | 1561 | *skb_push(skb, 1) = sk->sk_protocol; |
1566 | 1562 | ||
1567 | SOCK_DEBUG(sk, "AX.25: Transmitting buffer\n"); | ||
1568 | |||
1569 | if (sk->sk_type == SOCK_SEQPACKET) { | 1563 | if (sk->sk_type == SOCK_SEQPACKET) { |
1570 | /* Connected mode sockets go via the LAPB machine */ | 1564 | /* Connected mode sockets go via the LAPB machine */ |
1571 | if (sk->sk_state != TCP_ESTABLISHED) { | 1565 | if (sk->sk_state != TCP_ESTABLISHED) { |
@@ -1583,22 +1577,14 @@ static int ax25_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1583 | 1577 | ||
1584 | skb_push(skb, 1 + ax25_addr_size(dp)); | 1578 | skb_push(skb, 1 + ax25_addr_size(dp)); |
1585 | 1579 | ||
1586 | SOCK_DEBUG(sk, "Building AX.25 Header (dp=%p).\n", dp); | 1580 | /* Building AX.25 Header */ |
1587 | |||
1588 | if (dp != NULL) | ||
1589 | SOCK_DEBUG(sk, "Num digipeaters=%d\n", dp->ndigi); | ||
1590 | 1581 | ||
1591 | /* Build an AX.25 header */ | 1582 | /* Build an AX.25 header */ |
1592 | lv = ax25_addr_build(skb->data, &ax25->source_addr, &sax.sax25_call, | 1583 | lv = ax25_addr_build(skb->data, &ax25->source_addr, &sax.sax25_call, |
1593 | dp, AX25_COMMAND, AX25_MODULUS); | 1584 | dp, AX25_COMMAND, AX25_MODULUS); |
1594 | 1585 | ||
1595 | SOCK_DEBUG(sk, "Built header (%d bytes)\n",lv); | ||
1596 | |||
1597 | skb_set_transport_header(skb, lv); | 1586 | skb_set_transport_header(skb, lv); |
1598 | 1587 | ||
1599 | SOCK_DEBUG(sk, "base=%p pos=%p\n", | ||
1600 | skb->data, skb_transport_header(skb)); | ||
1601 | |||
1602 | *skb_transport_header(skb) = AX25_UI; | 1588 | *skb_transport_header(skb) = AX25_UI; |
1603 | 1589 | ||
1604 | /* Datagram frames go straight out of the door as UI */ | 1590 | /* Datagram frames go straight out of the door as UI */ |
diff --git a/net/ax25/ax25_iface.c b/net/ax25/ax25_iface.c index 5a0dda8df492..60b545e2822a 100644 --- a/net/ax25/ax25_iface.c +++ b/net/ax25/ax25_iface.c | |||
@@ -58,7 +58,7 @@ EXPORT_SYMBOL_GPL(ax25_register_pid); | |||
58 | 58 | ||
59 | void ax25_protocol_release(unsigned int pid) | 59 | void ax25_protocol_release(unsigned int pid) |
60 | { | 60 | { |
61 | struct ax25_protocol *s, *protocol; | 61 | struct ax25_protocol *protocol; |
62 | 62 | ||
63 | write_lock_bh(&protocol_list_lock); | 63 | write_lock_bh(&protocol_list_lock); |
64 | protocol = protocol_list; | 64 | protocol = protocol_list; |
@@ -72,7 +72,6 @@ void ax25_protocol_release(unsigned int pid) | |||
72 | 72 | ||
73 | while (protocol != NULL && protocol->next != NULL) { | 73 | while (protocol != NULL && protocol->next != NULL) { |
74 | if (protocol->next->pid == pid) { | 74 | if (protocol->next->pid == pid) { |
75 | s = protocol->next; | ||
76 | protocol->next = protocol->next->next; | 75 | protocol->next = protocol->next->next; |
77 | goto out; | 76 | goto out; |
78 | } | 77 | } |
diff --git a/net/batman-adv/aggregation.c b/net/batman-adv/aggregation.c index af45d6b2031f..a8c32030527c 100644 --- a/net/batman-adv/aggregation.c +++ b/net/batman-adv/aggregation.c | |||
@@ -23,11 +23,12 @@ | |||
23 | #include "aggregation.h" | 23 | #include "aggregation.h" |
24 | #include "send.h" | 24 | #include "send.h" |
25 | #include "routing.h" | 25 | #include "routing.h" |
26 | #include "hard-interface.h" | ||
26 | 27 | ||
27 | /* calculate the size of the hna information for a given packet */ | 28 | /* calculate the size of the tt information for a given packet */ |
28 | static int hna_len(struct batman_packet *batman_packet) | 29 | static int tt_len(struct batman_packet *batman_packet) |
29 | { | 30 | { |
30 | return batman_packet->num_hna * ETH_ALEN; | 31 | return batman_packet->num_tt * ETH_ALEN; |
31 | } | 32 | } |
32 | 33 | ||
33 | /* return true if new_packet can be aggregated with forw_packet */ | 34 | /* return true if new_packet can be aggregated with forw_packet */ |
@@ -95,7 +96,6 @@ static bool can_aggregate_with(struct batman_packet *new_batman_packet, | |||
95 | return false; | 96 | return false; |
96 | } | 97 | } |
97 | 98 | ||
98 | #define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0) | ||
99 | /* create a new aggregated packet and add this packet to it */ | 99 | /* create a new aggregated packet and add this packet to it */ |
100 | static void new_aggregated_packet(unsigned char *packet_buff, int packet_len, | 100 | static void new_aggregated_packet(unsigned char *packet_buff, int packet_len, |
101 | unsigned long send_time, bool direct_link, | 101 | unsigned long send_time, bool direct_link, |
@@ -106,12 +106,15 @@ static void new_aggregated_packet(unsigned char *packet_buff, int packet_len, | |||
106 | struct forw_packet *forw_packet_aggr; | 106 | struct forw_packet *forw_packet_aggr; |
107 | unsigned char *skb_buff; | 107 | unsigned char *skb_buff; |
108 | 108 | ||
109 | if (!atomic_inc_not_zero(&if_incoming->refcount)) | ||
110 | return; | ||
111 | |||
109 | /* own packet should always be scheduled */ | 112 | /* own packet should always be scheduled */ |
110 | if (!own_packet) { | 113 | if (!own_packet) { |
111 | if (!atomic_dec_not_zero(&bat_priv->batman_queue_left)) { | 114 | if (!atomic_dec_not_zero(&bat_priv->batman_queue_left)) { |
112 | bat_dbg(DBG_BATMAN, bat_priv, | 115 | bat_dbg(DBG_BATMAN, bat_priv, |
113 | "batman packet queue full\n"); | 116 | "batman packet queue full\n"); |
114 | return; | 117 | goto out; |
115 | } | 118 | } |
116 | } | 119 | } |
117 | 120 | ||
@@ -119,7 +122,7 @@ static void new_aggregated_packet(unsigned char *packet_buff, int packet_len, | |||
119 | if (!forw_packet_aggr) { | 122 | if (!forw_packet_aggr) { |
120 | if (!own_packet) | 123 | if (!own_packet) |
121 | atomic_inc(&bat_priv->batman_queue_left); | 124 | atomic_inc(&bat_priv->batman_queue_left); |
122 | return; | 125 | goto out; |
123 | } | 126 | } |
124 | 127 | ||
125 | if ((atomic_read(&bat_priv->aggregated_ogms)) && | 128 | if ((atomic_read(&bat_priv->aggregated_ogms)) && |
@@ -134,7 +137,7 @@ static void new_aggregated_packet(unsigned char *packet_buff, int packet_len, | |||
134 | if (!own_packet) | 137 | if (!own_packet) |
135 | atomic_inc(&bat_priv->batman_queue_left); | 138 | atomic_inc(&bat_priv->batman_queue_left); |
136 | kfree(forw_packet_aggr); | 139 | kfree(forw_packet_aggr); |
137 | return; | 140 | goto out; |
138 | } | 141 | } |
139 | skb_reserve(forw_packet_aggr->skb, sizeof(struct ethhdr)); | 142 | skb_reserve(forw_packet_aggr->skb, sizeof(struct ethhdr)); |
140 | 143 | ||
@@ -165,6 +168,10 @@ static void new_aggregated_packet(unsigned char *packet_buff, int packet_len, | |||
165 | queue_delayed_work(bat_event_workqueue, | 168 | queue_delayed_work(bat_event_workqueue, |
166 | &forw_packet_aggr->delayed_work, | 169 | &forw_packet_aggr->delayed_work, |
167 | send_time - jiffies); | 170 | send_time - jiffies); |
171 | |||
172 | return; | ||
173 | out: | ||
174 | hardif_free_ref(if_incoming); | ||
168 | } | 175 | } |
169 | 176 | ||
170 | /* aggregate a new packet into the existing aggregation */ | 177 | /* aggregate a new packet into the existing aggregation */ |
@@ -251,7 +258,7 @@ void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff, | |||
251 | { | 258 | { |
252 | struct batman_packet *batman_packet; | 259 | struct batman_packet *batman_packet; |
253 | int buff_pos = 0; | 260 | int buff_pos = 0; |
254 | unsigned char *hna_buff; | 261 | unsigned char *tt_buff; |
255 | 262 | ||
256 | batman_packet = (struct batman_packet *)packet_buff; | 263 | batman_packet = (struct batman_packet *)packet_buff; |
257 | 264 | ||
@@ -260,14 +267,14 @@ void receive_aggr_bat_packet(struct ethhdr *ethhdr, unsigned char *packet_buff, | |||
260 | orig_interval. */ | 267 | orig_interval. */ |
261 | batman_packet->seqno = ntohl(batman_packet->seqno); | 268 | batman_packet->seqno = ntohl(batman_packet->seqno); |
262 | 269 | ||
263 | hna_buff = packet_buff + buff_pos + BAT_PACKET_LEN; | 270 | tt_buff = packet_buff + buff_pos + BAT_PACKET_LEN; |
264 | receive_bat_packet(ethhdr, batman_packet, | 271 | receive_bat_packet(ethhdr, batman_packet, |
265 | hna_buff, hna_len(batman_packet), | 272 | tt_buff, tt_len(batman_packet), |
266 | if_incoming); | 273 | if_incoming); |
267 | 274 | ||
268 | buff_pos += BAT_PACKET_LEN + hna_len(batman_packet); | 275 | buff_pos += BAT_PACKET_LEN + tt_len(batman_packet); |
269 | batman_packet = (struct batman_packet *) | 276 | batman_packet = (struct batman_packet *) |
270 | (packet_buff + buff_pos); | 277 | (packet_buff + buff_pos); |
271 | } while (aggregated_packet(buff_pos, packet_len, | 278 | } while (aggregated_packet(buff_pos, packet_len, |
272 | batman_packet->num_hna)); | 279 | batman_packet->num_tt)); |
273 | } | 280 | } |
diff --git a/net/batman-adv/aggregation.h b/net/batman-adv/aggregation.h index 062204289d1f..7e6d72fbf540 100644 --- a/net/batman-adv/aggregation.h +++ b/net/batman-adv/aggregation.h | |||
@@ -25,9 +25,9 @@ | |||
25 | #include "main.h" | 25 | #include "main.h" |
26 | 26 | ||
27 | /* is there another aggregated packet here? */ | 27 | /* is there another aggregated packet here? */ |
28 | static inline int aggregated_packet(int buff_pos, int packet_len, int num_hna) | 28 | static inline int aggregated_packet(int buff_pos, int packet_len, int num_tt) |
29 | { | 29 | { |
30 | int next_buff_pos = buff_pos + BAT_PACKET_LEN + (num_hna * ETH_ALEN); | 30 | int next_buff_pos = buff_pos + BAT_PACKET_LEN + (num_tt * ETH_ALEN); |
31 | 31 | ||
32 | return (next_buff_pos <= packet_len) && | 32 | return (next_buff_pos <= packet_len) && |
33 | (next_buff_pos <= MAX_AGGREGATION_BYTES); | 33 | (next_buff_pos <= MAX_AGGREGATION_BYTES); |
diff --git a/net/batman-adv/bat_debugfs.c b/net/batman-adv/bat_debugfs.c index 0e9d43509935..abaeec5f6247 100644 --- a/net/batman-adv/bat_debugfs.c +++ b/net/batman-adv/bat_debugfs.c | |||
@@ -241,13 +241,13 @@ static int softif_neigh_open(struct inode *inode, struct file *file) | |||
241 | static int transtable_global_open(struct inode *inode, struct file *file) | 241 | static int transtable_global_open(struct inode *inode, struct file *file) |
242 | { | 242 | { |
243 | struct net_device *net_dev = (struct net_device *)inode->i_private; | 243 | struct net_device *net_dev = (struct net_device *)inode->i_private; |
244 | return single_open(file, hna_global_seq_print_text, net_dev); | 244 | return single_open(file, tt_global_seq_print_text, net_dev); |
245 | } | 245 | } |
246 | 246 | ||
247 | static int transtable_local_open(struct inode *inode, struct file *file) | 247 | static int transtable_local_open(struct inode *inode, struct file *file) |
248 | { | 248 | { |
249 | struct net_device *net_dev = (struct net_device *)inode->i_private; | 249 | struct net_device *net_dev = (struct net_device *)inode->i_private; |
250 | return single_open(file, hna_local_seq_print_text, net_dev); | 250 | return single_open(file, tt_local_seq_print_text, net_dev); |
251 | } | 251 | } |
252 | 252 | ||
253 | static int vis_data_open(struct inode *inode, struct file *file) | 253 | static int vis_data_open(struct inode *inode, struct file *file) |
diff --git a/net/batman-adv/bat_sysfs.c b/net/batman-adv/bat_sysfs.c index e449bf6353e0..497a0700cc3c 100644 --- a/net/batman-adv/bat_sysfs.c +++ b/net/batman-adv/bat_sysfs.c | |||
@@ -488,22 +488,24 @@ static ssize_t store_mesh_iface(struct kobject *kobj, struct attribute *attr, | |||
488 | (strncmp(hard_iface->soft_iface->name, buff, IFNAMSIZ) == 0)) | 488 | (strncmp(hard_iface->soft_iface->name, buff, IFNAMSIZ) == 0)) |
489 | goto out; | 489 | goto out; |
490 | 490 | ||
491 | if (!rtnl_trylock()) { | ||
492 | ret = -ERESTARTSYS; | ||
493 | goto out; | ||
494 | } | ||
495 | |||
491 | if (status_tmp == IF_NOT_IN_USE) { | 496 | if (status_tmp == IF_NOT_IN_USE) { |
492 | rtnl_lock(); | ||
493 | hardif_disable_interface(hard_iface); | 497 | hardif_disable_interface(hard_iface); |
494 | rtnl_unlock(); | 498 | goto unlock; |
495 | goto out; | ||
496 | } | 499 | } |
497 | 500 | ||
498 | /* if the interface already is in use */ | 501 | /* if the interface already is in use */ |
499 | if (hard_iface->if_status != IF_NOT_IN_USE) { | 502 | if (hard_iface->if_status != IF_NOT_IN_USE) |
500 | rtnl_lock(); | ||
501 | hardif_disable_interface(hard_iface); | 503 | hardif_disable_interface(hard_iface); |
502 | rtnl_unlock(); | ||
503 | } | ||
504 | 504 | ||
505 | ret = hardif_enable_interface(hard_iface, buff); | 505 | ret = hardif_enable_interface(hard_iface, buff); |
506 | 506 | ||
507 | unlock: | ||
508 | rtnl_unlock(); | ||
507 | out: | 509 | out: |
508 | hardif_free_ref(hard_iface); | 510 | hardif_free_ref(hard_iface); |
509 | return ret; | 511 | return ret; |
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 3cc43558cf9c..65f39530799d 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include "gateway_client.h" | 23 | #include "gateway_client.h" |
24 | #include "gateway_common.h" | 24 | #include "gateway_common.h" |
25 | #include "hard-interface.h" | 25 | #include "hard-interface.h" |
26 | #include "originator.h" | ||
26 | #include <linux/ip.h> | 27 | #include <linux/ip.h> |
27 | #include <linux/ipv6.h> | 28 | #include <linux/ipv6.h> |
28 | #include <linux/udp.h> | 29 | #include <linux/udp.h> |
@@ -42,61 +43,76 @@ static void gw_node_free_ref(struct gw_node *gw_node) | |||
42 | call_rcu(&gw_node->rcu, gw_node_free_rcu); | 43 | call_rcu(&gw_node->rcu, gw_node_free_rcu); |
43 | } | 44 | } |
44 | 45 | ||
45 | void *gw_get_selected(struct bat_priv *bat_priv) | 46 | static struct gw_node *gw_get_selected_gw_node(struct bat_priv *bat_priv) |
46 | { | 47 | { |
47 | struct gw_node *curr_gateway_tmp; | 48 | struct gw_node *gw_node; |
48 | struct orig_node *orig_node = NULL; | ||
49 | 49 | ||
50 | rcu_read_lock(); | 50 | rcu_read_lock(); |
51 | curr_gateway_tmp = rcu_dereference(bat_priv->curr_gw); | 51 | gw_node = rcu_dereference(bat_priv->curr_gw); |
52 | if (!curr_gateway_tmp) | 52 | if (!gw_node) |
53 | goto out; | ||
54 | |||
55 | orig_node = curr_gateway_tmp->orig_node; | ||
56 | if (!orig_node) | ||
57 | goto out; | 53 | goto out; |
58 | 54 | ||
59 | if (!atomic_inc_not_zero(&orig_node->refcount)) | 55 | if (!atomic_inc_not_zero(&gw_node->refcount)) |
60 | orig_node = NULL; | 56 | gw_node = NULL; |
61 | 57 | ||
62 | out: | 58 | out: |
63 | rcu_read_unlock(); | 59 | rcu_read_unlock(); |
64 | return orig_node; | 60 | return gw_node; |
65 | } | 61 | } |
66 | 62 | ||
67 | void gw_deselect(struct bat_priv *bat_priv) | 63 | struct orig_node *gw_get_selected_orig(struct bat_priv *bat_priv) |
68 | { | 64 | { |
69 | struct gw_node *gw_node; | 65 | struct gw_node *gw_node; |
66 | struct orig_node *orig_node = NULL; | ||
70 | 67 | ||
71 | spin_lock_bh(&bat_priv->gw_list_lock); | 68 | gw_node = gw_get_selected_gw_node(bat_priv); |
72 | gw_node = rcu_dereference(bat_priv->curr_gw); | 69 | if (!gw_node) |
73 | rcu_assign_pointer(bat_priv->curr_gw, NULL); | 70 | goto out; |
74 | spin_unlock_bh(&bat_priv->gw_list_lock); | 71 | |
72 | rcu_read_lock(); | ||
73 | orig_node = gw_node->orig_node; | ||
74 | if (!orig_node) | ||
75 | goto unlock; | ||
76 | |||
77 | if (!atomic_inc_not_zero(&orig_node->refcount)) | ||
78 | orig_node = NULL; | ||
75 | 79 | ||
80 | unlock: | ||
81 | rcu_read_unlock(); | ||
82 | out: | ||
76 | if (gw_node) | 83 | if (gw_node) |
77 | gw_node_free_ref(gw_node); | 84 | gw_node_free_ref(gw_node); |
85 | return orig_node; | ||
78 | } | 86 | } |
79 | 87 | ||
80 | static void gw_select(struct bat_priv *bat_priv, struct gw_node *new_gw_node) | 88 | static void gw_select(struct bat_priv *bat_priv, struct gw_node *new_gw_node) |
81 | { | 89 | { |
82 | struct gw_node *curr_gw_node; | 90 | struct gw_node *curr_gw_node; |
83 | 91 | ||
92 | spin_lock_bh(&bat_priv->gw_list_lock); | ||
93 | |||
84 | if (new_gw_node && !atomic_inc_not_zero(&new_gw_node->refcount)) | 94 | if (new_gw_node && !atomic_inc_not_zero(&new_gw_node->refcount)) |
85 | new_gw_node = NULL; | 95 | new_gw_node = NULL; |
86 | 96 | ||
87 | spin_lock_bh(&bat_priv->gw_list_lock); | 97 | curr_gw_node = bat_priv->curr_gw; |
88 | curr_gw_node = rcu_dereference(bat_priv->curr_gw); | ||
89 | rcu_assign_pointer(bat_priv->curr_gw, new_gw_node); | 98 | rcu_assign_pointer(bat_priv->curr_gw, new_gw_node); |
90 | spin_unlock_bh(&bat_priv->gw_list_lock); | ||
91 | 99 | ||
92 | if (curr_gw_node) | 100 | if (curr_gw_node) |
93 | gw_node_free_ref(curr_gw_node); | 101 | gw_node_free_ref(curr_gw_node); |
102 | |||
103 | spin_unlock_bh(&bat_priv->gw_list_lock); | ||
104 | } | ||
105 | |||
106 | void gw_deselect(struct bat_priv *bat_priv) | ||
107 | { | ||
108 | gw_select(bat_priv, NULL); | ||
94 | } | 109 | } |
95 | 110 | ||
96 | void gw_election(struct bat_priv *bat_priv) | 111 | void gw_election(struct bat_priv *bat_priv) |
97 | { | 112 | { |
98 | struct hlist_node *node; | 113 | struct hlist_node *node; |
99 | struct gw_node *gw_node, *curr_gw, *curr_gw_tmp = NULL; | 114 | struct gw_node *gw_node, *curr_gw = NULL, *curr_gw_tmp = NULL; |
115 | struct neigh_node *router; | ||
100 | uint8_t max_tq = 0; | 116 | uint8_t max_tq = 0; |
101 | uint32_t max_gw_factor = 0, tmp_gw_factor = 0; | 117 | uint32_t max_gw_factor = 0, tmp_gw_factor = 0; |
102 | int down, up; | 118 | int down, up; |
@@ -110,32 +126,25 @@ void gw_election(struct bat_priv *bat_priv) | |||
110 | if (atomic_read(&bat_priv->gw_mode) != GW_MODE_CLIENT) | 126 | if (atomic_read(&bat_priv->gw_mode) != GW_MODE_CLIENT) |
111 | return; | 127 | return; |
112 | 128 | ||
113 | rcu_read_lock(); | 129 | curr_gw = gw_get_selected_gw_node(bat_priv); |
114 | curr_gw = rcu_dereference(bat_priv->curr_gw); | 130 | if (curr_gw) |
115 | if (curr_gw) { | 131 | goto out; |
116 | rcu_read_unlock(); | ||
117 | return; | ||
118 | } | ||
119 | 132 | ||
133 | rcu_read_lock(); | ||
120 | if (hlist_empty(&bat_priv->gw_list)) { | 134 | if (hlist_empty(&bat_priv->gw_list)) { |
121 | 135 | bat_dbg(DBG_BATMAN, bat_priv, | |
122 | if (curr_gw) { | 136 | "Removing selected gateway - " |
123 | rcu_read_unlock(); | 137 | "no gateway in range\n"); |
124 | bat_dbg(DBG_BATMAN, bat_priv, | 138 | gw_deselect(bat_priv); |
125 | "Removing selected gateway - " | 139 | goto unlock; |
126 | "no gateway in range\n"); | ||
127 | gw_deselect(bat_priv); | ||
128 | } else | ||
129 | rcu_read_unlock(); | ||
130 | |||
131 | return; | ||
132 | } | 140 | } |
133 | 141 | ||
134 | hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { | 142 | hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { |
135 | if (!gw_node->orig_node->router) | 143 | if (gw_node->deleted) |
136 | continue; | 144 | continue; |
137 | 145 | ||
138 | if (gw_node->deleted) | 146 | router = orig_node_get_router(gw_node->orig_node); |
147 | if (!router) | ||
139 | continue; | 148 | continue; |
140 | 149 | ||
141 | switch (atomic_read(&bat_priv->gw_sel_class)) { | 150 | switch (atomic_read(&bat_priv->gw_sel_class)) { |
@@ -143,15 +152,14 @@ void gw_election(struct bat_priv *bat_priv) | |||
143 | gw_bandwidth_to_kbit(gw_node->orig_node->gw_flags, | 152 | gw_bandwidth_to_kbit(gw_node->orig_node->gw_flags, |
144 | &down, &up); | 153 | &down, &up); |
145 | 154 | ||
146 | tmp_gw_factor = (gw_node->orig_node->router->tq_avg * | 155 | tmp_gw_factor = (router->tq_avg * router->tq_avg * |
147 | gw_node->orig_node->router->tq_avg * | ||
148 | down * 100 * 100) / | 156 | down * 100 * 100) / |
149 | (TQ_LOCAL_WINDOW_SIZE * | 157 | (TQ_LOCAL_WINDOW_SIZE * |
150 | TQ_LOCAL_WINDOW_SIZE * 64); | 158 | TQ_LOCAL_WINDOW_SIZE * 64); |
151 | 159 | ||
152 | if ((tmp_gw_factor > max_gw_factor) || | 160 | if ((tmp_gw_factor > max_gw_factor) || |
153 | ((tmp_gw_factor == max_gw_factor) && | 161 | ((tmp_gw_factor == max_gw_factor) && |
154 | (gw_node->orig_node->router->tq_avg > max_tq))) | 162 | (router->tq_avg > max_tq))) |
155 | curr_gw_tmp = gw_node; | 163 | curr_gw_tmp = gw_node; |
156 | break; | 164 | break; |
157 | 165 | ||
@@ -163,19 +171,25 @@ void gw_election(struct bat_priv *bat_priv) | |||
163 | * soon as a better gateway appears which has | 171 | * soon as a better gateway appears which has |
164 | * $routing_class more tq points) | 172 | * $routing_class more tq points) |
165 | **/ | 173 | **/ |
166 | if (gw_node->orig_node->router->tq_avg > max_tq) | 174 | if (router->tq_avg > max_tq) |
167 | curr_gw_tmp = gw_node; | 175 | curr_gw_tmp = gw_node; |
168 | break; | 176 | break; |
169 | } | 177 | } |
170 | 178 | ||
171 | if (gw_node->orig_node->router->tq_avg > max_tq) | 179 | if (router->tq_avg > max_tq) |
172 | max_tq = gw_node->orig_node->router->tq_avg; | 180 | max_tq = router->tq_avg; |
173 | 181 | ||
174 | if (tmp_gw_factor > max_gw_factor) | 182 | if (tmp_gw_factor > max_gw_factor) |
175 | max_gw_factor = tmp_gw_factor; | 183 | max_gw_factor = tmp_gw_factor; |
184 | |||
185 | neigh_node_free_ref(router); | ||
176 | } | 186 | } |
177 | 187 | ||
178 | if (curr_gw != curr_gw_tmp) { | 188 | if (curr_gw != curr_gw_tmp) { |
189 | router = orig_node_get_router(curr_gw_tmp->orig_node); | ||
190 | if (!router) | ||
191 | goto unlock; | ||
192 | |||
179 | if ((curr_gw) && (!curr_gw_tmp)) | 193 | if ((curr_gw) && (!curr_gw_tmp)) |
180 | bat_dbg(DBG_BATMAN, bat_priv, | 194 | bat_dbg(DBG_BATMAN, bat_priv, |
181 | "Removing selected gateway - " | 195 | "Removing selected gateway - " |
@@ -186,48 +200,50 @@ void gw_election(struct bat_priv *bat_priv) | |||
186 | "(gw_flags: %i, tq: %i)\n", | 200 | "(gw_flags: %i, tq: %i)\n", |
187 | curr_gw_tmp->orig_node->orig, | 201 | curr_gw_tmp->orig_node->orig, |
188 | curr_gw_tmp->orig_node->gw_flags, | 202 | curr_gw_tmp->orig_node->gw_flags, |
189 | curr_gw_tmp->orig_node->router->tq_avg); | 203 | router->tq_avg); |
190 | else | 204 | else |
191 | bat_dbg(DBG_BATMAN, bat_priv, | 205 | bat_dbg(DBG_BATMAN, bat_priv, |
192 | "Changing route to gateway %pM " | 206 | "Changing route to gateway %pM " |
193 | "(gw_flags: %i, tq: %i)\n", | 207 | "(gw_flags: %i, tq: %i)\n", |
194 | curr_gw_tmp->orig_node->orig, | 208 | curr_gw_tmp->orig_node->orig, |
195 | curr_gw_tmp->orig_node->gw_flags, | 209 | curr_gw_tmp->orig_node->gw_flags, |
196 | curr_gw_tmp->orig_node->router->tq_avg); | 210 | router->tq_avg); |
197 | 211 | ||
212 | neigh_node_free_ref(router); | ||
198 | gw_select(bat_priv, curr_gw_tmp); | 213 | gw_select(bat_priv, curr_gw_tmp); |
199 | } | 214 | } |
200 | 215 | ||
216 | unlock: | ||
201 | rcu_read_unlock(); | 217 | rcu_read_unlock(); |
218 | out: | ||
219 | if (curr_gw) | ||
220 | gw_node_free_ref(curr_gw); | ||
202 | } | 221 | } |
203 | 222 | ||
204 | void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node) | 223 | void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node) |
205 | { | 224 | { |
206 | struct gw_node *curr_gateway_tmp; | 225 | struct orig_node *curr_gw_orig; |
226 | struct neigh_node *router_gw = NULL, *router_orig = NULL; | ||
207 | uint8_t gw_tq_avg, orig_tq_avg; | 227 | uint8_t gw_tq_avg, orig_tq_avg; |
208 | 228 | ||
209 | rcu_read_lock(); | 229 | curr_gw_orig = gw_get_selected_orig(bat_priv); |
210 | curr_gateway_tmp = rcu_dereference(bat_priv->curr_gw); | 230 | if (!curr_gw_orig) |
211 | if (!curr_gateway_tmp) | 231 | goto deselect; |
212 | goto out_rcu; | ||
213 | |||
214 | if (!curr_gateway_tmp->orig_node) | ||
215 | goto deselect_rcu; | ||
216 | 232 | ||
217 | if (!curr_gateway_tmp->orig_node->router) | 233 | router_gw = orig_node_get_router(curr_gw_orig); |
218 | goto deselect_rcu; | 234 | if (!router_gw) |
235 | goto deselect; | ||
219 | 236 | ||
220 | /* this node already is the gateway */ | 237 | /* this node already is the gateway */ |
221 | if (curr_gateway_tmp->orig_node == orig_node) | 238 | if (curr_gw_orig == orig_node) |
222 | goto out_rcu; | 239 | goto out; |
223 | |||
224 | if (!orig_node->router) | ||
225 | goto out_rcu; | ||
226 | 240 | ||
227 | gw_tq_avg = curr_gateway_tmp->orig_node->router->tq_avg; | 241 | router_orig = orig_node_get_router(orig_node); |
228 | rcu_read_unlock(); | 242 | if (!router_orig) |
243 | goto out; | ||
229 | 244 | ||
230 | orig_tq_avg = orig_node->router->tq_avg; | 245 | gw_tq_avg = router_gw->tq_avg; |
246 | orig_tq_avg = router_orig->tq_avg; | ||
231 | 247 | ||
232 | /* the TQ value has to be better */ | 248 | /* the TQ value has to be better */ |
233 | if (orig_tq_avg < gw_tq_avg) | 249 | if (orig_tq_avg < gw_tq_avg) |
@@ -245,16 +261,17 @@ void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node) | |||
245 | "Restarting gateway selection: better gateway found (tq curr: " | 261 | "Restarting gateway selection: better gateway found (tq curr: " |
246 | "%i, tq new: %i)\n", | 262 | "%i, tq new: %i)\n", |
247 | gw_tq_avg, orig_tq_avg); | 263 | gw_tq_avg, orig_tq_avg); |
248 | goto deselect; | ||
249 | 264 | ||
250 | out_rcu: | ||
251 | rcu_read_unlock(); | ||
252 | goto out; | ||
253 | deselect_rcu: | ||
254 | rcu_read_unlock(); | ||
255 | deselect: | 265 | deselect: |
256 | gw_deselect(bat_priv); | 266 | gw_deselect(bat_priv); |
257 | out: | 267 | out: |
268 | if (curr_gw_orig) | ||
269 | orig_node_free_ref(curr_gw_orig); | ||
270 | if (router_gw) | ||
271 | neigh_node_free_ref(router_gw); | ||
272 | if (router_orig) | ||
273 | neigh_node_free_ref(router_orig); | ||
274 | |||
258 | return; | 275 | return; |
259 | } | 276 | } |
260 | 277 | ||
@@ -291,7 +308,15 @@ void gw_node_update(struct bat_priv *bat_priv, | |||
291 | struct orig_node *orig_node, uint8_t new_gwflags) | 308 | struct orig_node *orig_node, uint8_t new_gwflags) |
292 | { | 309 | { |
293 | struct hlist_node *node; | 310 | struct hlist_node *node; |
294 | struct gw_node *gw_node; | 311 | struct gw_node *gw_node, *curr_gw; |
312 | |||
313 | /** | ||
314 | * Note: We don't need a NULL check here, since curr_gw never gets | ||
315 | * dereferenced. If curr_gw is NULL we also should not exit as we may | ||
316 | * have this gateway in our list (duplication check!) even though we | ||
317 | * have no currently selected gateway. | ||
318 | */ | ||
319 | curr_gw = gw_get_selected_gw_node(bat_priv); | ||
295 | 320 | ||
296 | rcu_read_lock(); | 321 | rcu_read_lock(); |
297 | hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { | 322 | hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { |
@@ -312,22 +337,26 @@ void gw_node_update(struct bat_priv *bat_priv, | |||
312 | "Gateway %pM removed from gateway list\n", | 337 | "Gateway %pM removed from gateway list\n", |
313 | orig_node->orig); | 338 | orig_node->orig); |
314 | 339 | ||
315 | if (gw_node == rcu_dereference(bat_priv->curr_gw)) { | 340 | if (gw_node == curr_gw) |
316 | rcu_read_unlock(); | 341 | goto deselect; |
317 | gw_deselect(bat_priv); | ||
318 | return; | ||
319 | } | ||
320 | } | 342 | } |
321 | 343 | ||
322 | rcu_read_unlock(); | 344 | goto unlock; |
323 | return; | ||
324 | } | 345 | } |
325 | rcu_read_unlock(); | ||
326 | 346 | ||
327 | if (new_gwflags == 0) | 347 | if (new_gwflags == 0) |
328 | return; | 348 | goto unlock; |
329 | 349 | ||
330 | gw_node_add(bat_priv, orig_node, new_gwflags); | 350 | gw_node_add(bat_priv, orig_node, new_gwflags); |
351 | goto unlock; | ||
352 | |||
353 | deselect: | ||
354 | gw_deselect(bat_priv); | ||
355 | unlock: | ||
356 | rcu_read_unlock(); | ||
357 | |||
358 | if (curr_gw) | ||
359 | gw_node_free_ref(curr_gw); | ||
331 | } | 360 | } |
332 | 361 | ||
333 | void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node) | 362 | void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node) |
@@ -337,9 +366,12 @@ void gw_node_delete(struct bat_priv *bat_priv, struct orig_node *orig_node) | |||
337 | 366 | ||
338 | void gw_node_purge(struct bat_priv *bat_priv) | 367 | void gw_node_purge(struct bat_priv *bat_priv) |
339 | { | 368 | { |
340 | struct gw_node *gw_node; | 369 | struct gw_node *gw_node, *curr_gw; |
341 | struct hlist_node *node, *node_tmp; | 370 | struct hlist_node *node, *node_tmp; |
342 | unsigned long timeout = 2 * PURGE_TIMEOUT * HZ; | 371 | unsigned long timeout = 2 * PURGE_TIMEOUT * HZ; |
372 | char do_deselect = 0; | ||
373 | |||
374 | curr_gw = gw_get_selected_gw_node(bat_priv); | ||
343 | 375 | ||
344 | spin_lock_bh(&bat_priv->gw_list_lock); | 376 | spin_lock_bh(&bat_priv->gw_list_lock); |
345 | 377 | ||
@@ -350,41 +382,56 @@ void gw_node_purge(struct bat_priv *bat_priv) | |||
350 | atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) | 382 | atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) |
351 | continue; | 383 | continue; |
352 | 384 | ||
353 | if (rcu_dereference(bat_priv->curr_gw) == gw_node) | 385 | if (curr_gw == gw_node) |
354 | gw_deselect(bat_priv); | 386 | do_deselect = 1; |
355 | 387 | ||
356 | hlist_del_rcu(&gw_node->list); | 388 | hlist_del_rcu(&gw_node->list); |
357 | gw_node_free_ref(gw_node); | 389 | gw_node_free_ref(gw_node); |
358 | } | 390 | } |
359 | 391 | ||
360 | |||
361 | spin_unlock_bh(&bat_priv->gw_list_lock); | 392 | spin_unlock_bh(&bat_priv->gw_list_lock); |
393 | |||
394 | /* gw_deselect() needs to acquire the gw_list_lock */ | ||
395 | if (do_deselect) | ||
396 | gw_deselect(bat_priv); | ||
397 | |||
398 | if (curr_gw) | ||
399 | gw_node_free_ref(curr_gw); | ||
362 | } | 400 | } |
363 | 401 | ||
402 | /** | ||
403 | * fails if orig_node has no router | ||
404 | */ | ||
364 | static int _write_buffer_text(struct bat_priv *bat_priv, | 405 | static int _write_buffer_text(struct bat_priv *bat_priv, |
365 | struct seq_file *seq, struct gw_node *gw_node) | 406 | struct seq_file *seq, struct gw_node *gw_node) |
366 | { | 407 | { |
367 | struct gw_node *curr_gw; | 408 | struct gw_node *curr_gw; |
368 | int down, up, ret; | 409 | struct neigh_node *router; |
410 | int down, up, ret = -1; | ||
369 | 411 | ||
370 | gw_bandwidth_to_kbit(gw_node->orig_node->gw_flags, &down, &up); | 412 | gw_bandwidth_to_kbit(gw_node->orig_node->gw_flags, &down, &up); |
371 | 413 | ||
372 | rcu_read_lock(); | 414 | router = orig_node_get_router(gw_node->orig_node); |
373 | curr_gw = rcu_dereference(bat_priv->curr_gw); | 415 | if (!router) |
416 | goto out; | ||
374 | 417 | ||
375 | ret = seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %3i - %i%s/%i%s\n", | 418 | curr_gw = gw_get_selected_gw_node(bat_priv); |
376 | (curr_gw == gw_node ? "=>" : " "), | ||
377 | gw_node->orig_node->orig, | ||
378 | gw_node->orig_node->router->tq_avg, | ||
379 | gw_node->orig_node->router->addr, | ||
380 | gw_node->orig_node->router->if_incoming->net_dev->name, | ||
381 | gw_node->orig_node->gw_flags, | ||
382 | (down > 2048 ? down / 1024 : down), | ||
383 | (down > 2048 ? "MBit" : "KBit"), | ||
384 | (up > 2048 ? up / 1024 : up), | ||
385 | (up > 2048 ? "MBit" : "KBit")); | ||
386 | 419 | ||
387 | rcu_read_unlock(); | 420 | ret = seq_printf(seq, "%s %pM (%3i) %pM [%10s]: %3i - %i%s/%i%s\n", |
421 | (curr_gw == gw_node ? "=>" : " "), | ||
422 | gw_node->orig_node->orig, | ||
423 | router->tq_avg, router->addr, | ||
424 | router->if_incoming->net_dev->name, | ||
425 | gw_node->orig_node->gw_flags, | ||
426 | (down > 2048 ? down / 1024 : down), | ||
427 | (down > 2048 ? "MBit" : "KBit"), | ||
428 | (up > 2048 ? up / 1024 : up), | ||
429 | (up > 2048 ? "MBit" : "KBit")); | ||
430 | |||
431 | neigh_node_free_ref(router); | ||
432 | if (curr_gw) | ||
433 | gw_node_free_ref(curr_gw); | ||
434 | out: | ||
388 | return ret; | 435 | return ret; |
389 | } | 436 | } |
390 | 437 | ||
@@ -392,40 +439,42 @@ int gw_client_seq_print_text(struct seq_file *seq, void *offset) | |||
392 | { | 439 | { |
393 | struct net_device *net_dev = (struct net_device *)seq->private; | 440 | struct net_device *net_dev = (struct net_device *)seq->private; |
394 | struct bat_priv *bat_priv = netdev_priv(net_dev); | 441 | struct bat_priv *bat_priv = netdev_priv(net_dev); |
442 | struct hard_iface *primary_if; | ||
395 | struct gw_node *gw_node; | 443 | struct gw_node *gw_node; |
396 | struct hlist_node *node; | 444 | struct hlist_node *node; |
397 | int gw_count = 0; | 445 | int gw_count = 0, ret = 0; |
398 | |||
399 | if (!bat_priv->primary_if) { | ||
400 | 446 | ||
401 | return seq_printf(seq, "BATMAN mesh %s disabled - please " | 447 | primary_if = primary_if_get_selected(bat_priv); |
402 | "specify interfaces to enable it\n", | 448 | if (!primary_if) { |
403 | net_dev->name); | 449 | ret = seq_printf(seq, "BATMAN mesh %s disabled - please " |
450 | "specify interfaces to enable it\n", | ||
451 | net_dev->name); | ||
452 | goto out; | ||
404 | } | 453 | } |
405 | 454 | ||
406 | if (bat_priv->primary_if->if_status != IF_ACTIVE) { | 455 | if (primary_if->if_status != IF_ACTIVE) { |
407 | 456 | ret = seq_printf(seq, "BATMAN mesh %s disabled - " | |
408 | return seq_printf(seq, "BATMAN mesh %s disabled - " | 457 | "primary interface not active\n", |
409 | "primary interface not active\n", | 458 | net_dev->name); |
410 | net_dev->name); | 459 | goto out; |
411 | } | 460 | } |
412 | 461 | ||
413 | seq_printf(seq, " %-12s (%s/%i) %17s [%10s]: gw_class ... " | 462 | seq_printf(seq, " %-12s (%s/%i) %17s [%10s]: gw_class ... " |
414 | "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n", | 463 | "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n", |
415 | "Gateway", "#", TQ_MAX_VALUE, "Nexthop", | 464 | "Gateway", "#", TQ_MAX_VALUE, "Nexthop", |
416 | "outgoingIF", SOURCE_VERSION, REVISION_VERSION_STR, | 465 | "outgoingIF", SOURCE_VERSION, REVISION_VERSION_STR, |
417 | bat_priv->primary_if->net_dev->name, | 466 | primary_if->net_dev->name, |
418 | bat_priv->primary_if->net_dev->dev_addr, net_dev->name); | 467 | primary_if->net_dev->dev_addr, net_dev->name); |
419 | 468 | ||
420 | rcu_read_lock(); | 469 | rcu_read_lock(); |
421 | hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { | 470 | hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { |
422 | if (gw_node->deleted) | 471 | if (gw_node->deleted) |
423 | continue; | 472 | continue; |
424 | 473 | ||
425 | if (!gw_node->orig_node->router) | 474 | /* fails if orig_node has no router */ |
475 | if (_write_buffer_text(bat_priv, seq, gw_node) < 0) | ||
426 | continue; | 476 | continue; |
427 | 477 | ||
428 | _write_buffer_text(bat_priv, seq, gw_node); | ||
429 | gw_count++; | 478 | gw_count++; |
430 | } | 479 | } |
431 | rcu_read_unlock(); | 480 | rcu_read_unlock(); |
@@ -433,7 +482,10 @@ int gw_client_seq_print_text(struct seq_file *seq, void *offset) | |||
433 | if (gw_count == 0) | 482 | if (gw_count == 0) |
434 | seq_printf(seq, "No gateways in range ...\n"); | 483 | seq_printf(seq, "No gateways in range ...\n"); |
435 | 484 | ||
436 | return 0; | 485 | out: |
486 | if (primary_if) | ||
487 | hardif_free_ref(primary_if); | ||
488 | return ret; | ||
437 | } | 489 | } |
438 | 490 | ||
439 | int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb) | 491 | int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb) |
@@ -442,6 +494,7 @@ int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb) | |||
442 | struct iphdr *iphdr; | 494 | struct iphdr *iphdr; |
443 | struct ipv6hdr *ipv6hdr; | 495 | struct ipv6hdr *ipv6hdr; |
444 | struct udphdr *udphdr; | 496 | struct udphdr *udphdr; |
497 | struct gw_node *curr_gw; | ||
445 | unsigned int header_len = 0; | 498 | unsigned int header_len = 0; |
446 | 499 | ||
447 | if (atomic_read(&bat_priv->gw_mode) == GW_MODE_OFF) | 500 | if (atomic_read(&bat_priv->gw_mode) == GW_MODE_OFF) |
@@ -506,12 +559,11 @@ int gw_is_target(struct bat_priv *bat_priv, struct sk_buff *skb) | |||
506 | if (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER) | 559 | if (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER) |
507 | return -1; | 560 | return -1; |
508 | 561 | ||
509 | rcu_read_lock(); | 562 | curr_gw = gw_get_selected_gw_node(bat_priv); |
510 | if (!rcu_dereference(bat_priv->curr_gw)) { | 563 | if (!curr_gw) |
511 | rcu_read_unlock(); | ||
512 | return 0; | 564 | return 0; |
513 | } | ||
514 | rcu_read_unlock(); | ||
515 | 565 | ||
566 | if (curr_gw) | ||
567 | gw_node_free_ref(curr_gw); | ||
516 | return 1; | 568 | return 1; |
517 | } | 569 | } |
diff --git a/net/batman-adv/gateway_client.h b/net/batman-adv/gateway_client.h index 2aa439124ee3..1ce8c6066da1 100644 --- a/net/batman-adv/gateway_client.h +++ b/net/batman-adv/gateway_client.h | |||
@@ -24,7 +24,7 @@ | |||
24 | 24 | ||
25 | void gw_deselect(struct bat_priv *bat_priv); | 25 | void gw_deselect(struct bat_priv *bat_priv); |
26 | void gw_election(struct bat_priv *bat_priv); | 26 | void gw_election(struct bat_priv *bat_priv); |
27 | void *gw_get_selected(struct bat_priv *bat_priv); | 27 | struct orig_node *gw_get_selected_orig(struct bat_priv *bat_priv); |
28 | void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node); | 28 | void gw_check_election(struct bat_priv *bat_priv, struct orig_node *orig_node); |
29 | void gw_node_update(struct bat_priv *bat_priv, | 29 | void gw_node_update(struct bat_priv *bat_priv, |
30 | struct orig_node *orig_node, uint8_t new_gwflags); | 30 | struct orig_node *orig_node, uint8_t new_gwflags); |
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index b3058e46ee6b..dfbfccc9fe40 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c | |||
@@ -31,9 +31,6 @@ | |||
31 | 31 | ||
32 | #include <linux/if_arp.h> | 32 | #include <linux/if_arp.h> |
33 | 33 | ||
34 | /* protect update critical side of hardif_list - but not the content */ | ||
35 | static DEFINE_SPINLOCK(hardif_list_lock); | ||
36 | |||
37 | 34 | ||
38 | static int batman_skb_recv(struct sk_buff *skb, | 35 | static int batman_skb_recv(struct sk_buff *skb, |
39 | struct net_device *dev, | 36 | struct net_device *dev, |
@@ -110,47 +107,57 @@ out: | |||
110 | return hard_iface; | 107 | return hard_iface; |
111 | } | 108 | } |
112 | 109 | ||
113 | static void update_primary_addr(struct bat_priv *bat_priv) | 110 | static void primary_if_update_addr(struct bat_priv *bat_priv) |
114 | { | 111 | { |
115 | struct vis_packet *vis_packet; | 112 | struct vis_packet *vis_packet; |
113 | struct hard_iface *primary_if; | ||
114 | |||
115 | primary_if = primary_if_get_selected(bat_priv); | ||
116 | if (!primary_if) | ||
117 | goto out; | ||
116 | 118 | ||
117 | vis_packet = (struct vis_packet *) | 119 | vis_packet = (struct vis_packet *) |
118 | bat_priv->my_vis_info->skb_packet->data; | 120 | bat_priv->my_vis_info->skb_packet->data; |
119 | memcpy(vis_packet->vis_orig, | 121 | memcpy(vis_packet->vis_orig, primary_if->net_dev->dev_addr, ETH_ALEN); |
120 | bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); | ||
121 | memcpy(vis_packet->sender_orig, | 122 | memcpy(vis_packet->sender_orig, |
122 | bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); | 123 | primary_if->net_dev->dev_addr, ETH_ALEN); |
124 | |||
125 | out: | ||
126 | if (primary_if) | ||
127 | hardif_free_ref(primary_if); | ||
123 | } | 128 | } |
124 | 129 | ||
125 | static void set_primary_if(struct bat_priv *bat_priv, | 130 | static void primary_if_select(struct bat_priv *bat_priv, |
126 | struct hard_iface *hard_iface) | 131 | struct hard_iface *new_hard_iface) |
127 | { | 132 | { |
133 | struct hard_iface *curr_hard_iface; | ||
128 | struct batman_packet *batman_packet; | 134 | struct batman_packet *batman_packet; |
129 | struct hard_iface *old_if; | ||
130 | 135 | ||
131 | if (hard_iface && !atomic_inc_not_zero(&hard_iface->refcount)) | 136 | ASSERT_RTNL(); |
132 | hard_iface = NULL; | 137 | |
138 | if (new_hard_iface && !atomic_inc_not_zero(&new_hard_iface->refcount)) | ||
139 | new_hard_iface = NULL; | ||
133 | 140 | ||
134 | old_if = bat_priv->primary_if; | 141 | curr_hard_iface = bat_priv->primary_if; |
135 | bat_priv->primary_if = hard_iface; | 142 | rcu_assign_pointer(bat_priv->primary_if, new_hard_iface); |
136 | 143 | ||
137 | if (old_if) | 144 | if (curr_hard_iface) |
138 | hardif_free_ref(old_if); | 145 | hardif_free_ref(curr_hard_iface); |
139 | 146 | ||
140 | if (!bat_priv->primary_if) | 147 | if (!new_hard_iface) |
141 | return; | 148 | return; |
142 | 149 | ||
143 | batman_packet = (struct batman_packet *)(hard_iface->packet_buff); | 150 | batman_packet = (struct batman_packet *)(new_hard_iface->packet_buff); |
144 | batman_packet->flags = PRIMARIES_FIRST_HOP; | 151 | batman_packet->flags = PRIMARIES_FIRST_HOP; |
145 | batman_packet->ttl = TTL; | 152 | batman_packet->ttl = TTL; |
146 | 153 | ||
147 | update_primary_addr(bat_priv); | 154 | primary_if_update_addr(bat_priv); |
148 | 155 | ||
149 | /*** | 156 | /*** |
150 | * hacky trick to make sure that we send the HNA information via | 157 | * hacky trick to make sure that we send the TT information via |
151 | * our new primary interface | 158 | * our new primary interface |
152 | */ | 159 | */ |
153 | atomic_set(&bat_priv->hna_local_changed, 1); | 160 | atomic_set(&bat_priv->tt_local_changed, 1); |
154 | } | 161 | } |
155 | 162 | ||
156 | static bool hardif_is_iface_up(struct hard_iface *hard_iface) | 163 | static bool hardif_is_iface_up(struct hard_iface *hard_iface) |
@@ -236,9 +243,10 @@ void update_min_mtu(struct net_device *soft_iface) | |||
236 | static void hardif_activate_interface(struct hard_iface *hard_iface) | 243 | static void hardif_activate_interface(struct hard_iface *hard_iface) |
237 | { | 244 | { |
238 | struct bat_priv *bat_priv; | 245 | struct bat_priv *bat_priv; |
246 | struct hard_iface *primary_if = NULL; | ||
239 | 247 | ||
240 | if (hard_iface->if_status != IF_INACTIVE) | 248 | if (hard_iface->if_status != IF_INACTIVE) |
241 | return; | 249 | goto out; |
242 | 250 | ||
243 | bat_priv = netdev_priv(hard_iface->soft_iface); | 251 | bat_priv = netdev_priv(hard_iface->soft_iface); |
244 | 252 | ||
@@ -249,14 +257,18 @@ static void hardif_activate_interface(struct hard_iface *hard_iface) | |||
249 | * the first active interface becomes our primary interface or | 257 | * the first active interface becomes our primary interface or |
250 | * the next active interface after the old primay interface was removed | 258 | * the next active interface after the old primay interface was removed |
251 | */ | 259 | */ |
252 | if (!bat_priv->primary_if) | 260 | primary_if = primary_if_get_selected(bat_priv); |
253 | set_primary_if(bat_priv, hard_iface); | 261 | if (!primary_if) |
262 | primary_if_select(bat_priv, hard_iface); | ||
254 | 263 | ||
255 | bat_info(hard_iface->soft_iface, "Interface activated: %s\n", | 264 | bat_info(hard_iface->soft_iface, "Interface activated: %s\n", |
256 | hard_iface->net_dev->name); | 265 | hard_iface->net_dev->name); |
257 | 266 | ||
258 | update_min_mtu(hard_iface->soft_iface); | 267 | update_min_mtu(hard_iface->soft_iface); |
259 | return; | 268 | |
269 | out: | ||
270 | if (primary_if) | ||
271 | hardif_free_ref(primary_if); | ||
260 | } | 272 | } |
261 | 273 | ||
262 | static void hardif_deactivate_interface(struct hard_iface *hard_iface) | 274 | static void hardif_deactivate_interface(struct hard_iface *hard_iface) |
@@ -327,7 +339,7 @@ int hardif_enable_interface(struct hard_iface *hard_iface, char *iface_name) | |||
327 | batman_packet->flags = 0; | 339 | batman_packet->flags = 0; |
328 | batman_packet->ttl = 2; | 340 | batman_packet->ttl = 2; |
329 | batman_packet->tq = TQ_MAX_VALUE; | 341 | batman_packet->tq = TQ_MAX_VALUE; |
330 | batman_packet->num_hna = 0; | 342 | batman_packet->num_tt = 0; |
331 | 343 | ||
332 | hard_iface->if_num = bat_priv->num_ifaces; | 344 | hard_iface->if_num = bat_priv->num_ifaces; |
333 | bat_priv->num_ifaces++; | 345 | bat_priv->num_ifaces++; |
@@ -386,12 +398,13 @@ err: | |||
386 | void hardif_disable_interface(struct hard_iface *hard_iface) | 398 | void hardif_disable_interface(struct hard_iface *hard_iface) |
387 | { | 399 | { |
388 | struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface); | 400 | struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface); |
401 | struct hard_iface *primary_if = NULL; | ||
389 | 402 | ||
390 | if (hard_iface->if_status == IF_ACTIVE) | 403 | if (hard_iface->if_status == IF_ACTIVE) |
391 | hardif_deactivate_interface(hard_iface); | 404 | hardif_deactivate_interface(hard_iface); |
392 | 405 | ||
393 | if (hard_iface->if_status != IF_INACTIVE) | 406 | if (hard_iface->if_status != IF_INACTIVE) |
394 | return; | 407 | goto out; |
395 | 408 | ||
396 | bat_info(hard_iface->soft_iface, "Removing interface: %s\n", | 409 | bat_info(hard_iface->soft_iface, "Removing interface: %s\n", |
397 | hard_iface->net_dev->name); | 410 | hard_iface->net_dev->name); |
@@ -400,11 +413,12 @@ void hardif_disable_interface(struct hard_iface *hard_iface) | |||
400 | bat_priv->num_ifaces--; | 413 | bat_priv->num_ifaces--; |
401 | orig_hash_del_if(hard_iface, bat_priv->num_ifaces); | 414 | orig_hash_del_if(hard_iface, bat_priv->num_ifaces); |
402 | 415 | ||
403 | if (hard_iface == bat_priv->primary_if) { | 416 | primary_if = primary_if_get_selected(bat_priv); |
417 | if (hard_iface == primary_if) { | ||
404 | struct hard_iface *new_if; | 418 | struct hard_iface *new_if; |
405 | 419 | ||
406 | new_if = hardif_get_active(hard_iface->soft_iface); | 420 | new_if = hardif_get_active(hard_iface->soft_iface); |
407 | set_primary_if(bat_priv, new_if); | 421 | primary_if_select(bat_priv, new_if); |
408 | 422 | ||
409 | if (new_if) | 423 | if (new_if) |
410 | hardif_free_ref(new_if); | 424 | hardif_free_ref(new_if); |
@@ -425,6 +439,10 @@ void hardif_disable_interface(struct hard_iface *hard_iface) | |||
425 | 439 | ||
426 | hard_iface->soft_iface = NULL; | 440 | hard_iface->soft_iface = NULL; |
427 | hardif_free_ref(hard_iface); | 441 | hardif_free_ref(hard_iface); |
442 | |||
443 | out: | ||
444 | if (primary_if) | ||
445 | hardif_free_ref(primary_if); | ||
428 | } | 446 | } |
429 | 447 | ||
430 | static struct hard_iface *hardif_add_interface(struct net_device *net_dev) | 448 | static struct hard_iface *hardif_add_interface(struct net_device *net_dev) |
@@ -432,6 +450,8 @@ static struct hard_iface *hardif_add_interface(struct net_device *net_dev) | |||
432 | struct hard_iface *hard_iface; | 450 | struct hard_iface *hard_iface; |
433 | int ret; | 451 | int ret; |
434 | 452 | ||
453 | ASSERT_RTNL(); | ||
454 | |||
435 | ret = is_valid_iface(net_dev); | 455 | ret = is_valid_iface(net_dev); |
436 | if (ret != 1) | 456 | if (ret != 1) |
437 | goto out; | 457 | goto out; |
@@ -458,10 +478,7 @@ static struct hard_iface *hardif_add_interface(struct net_device *net_dev) | |||
458 | atomic_set(&hard_iface->refcount, 2); | 478 | atomic_set(&hard_iface->refcount, 2); |
459 | 479 | ||
460 | check_known_mac_addr(hard_iface->net_dev); | 480 | check_known_mac_addr(hard_iface->net_dev); |
461 | |||
462 | spin_lock(&hardif_list_lock); | ||
463 | list_add_tail_rcu(&hard_iface->list, &hardif_list); | 481 | list_add_tail_rcu(&hard_iface->list, &hardif_list); |
464 | spin_unlock(&hardif_list_lock); | ||
465 | 482 | ||
466 | return hard_iface; | 483 | return hard_iface; |
467 | 484 | ||
@@ -475,6 +492,8 @@ out: | |||
475 | 492 | ||
476 | static void hardif_remove_interface(struct hard_iface *hard_iface) | 493 | static void hardif_remove_interface(struct hard_iface *hard_iface) |
477 | { | 494 | { |
495 | ASSERT_RTNL(); | ||
496 | |||
478 | /* first deactivate interface */ | 497 | /* first deactivate interface */ |
479 | if (hard_iface->if_status != IF_NOT_IN_USE) | 498 | if (hard_iface->if_status != IF_NOT_IN_USE) |
480 | hardif_disable_interface(hard_iface); | 499 | hardif_disable_interface(hard_iface); |
@@ -490,20 +509,11 @@ static void hardif_remove_interface(struct hard_iface *hard_iface) | |||
490 | void hardif_remove_interfaces(void) | 509 | void hardif_remove_interfaces(void) |
491 | { | 510 | { |
492 | struct hard_iface *hard_iface, *hard_iface_tmp; | 511 | struct hard_iface *hard_iface, *hard_iface_tmp; |
493 | struct list_head if_queue; | ||
494 | |||
495 | INIT_LIST_HEAD(&if_queue); | ||
496 | 512 | ||
497 | spin_lock(&hardif_list_lock); | 513 | rtnl_lock(); |
498 | list_for_each_entry_safe(hard_iface, hard_iface_tmp, | 514 | list_for_each_entry_safe(hard_iface, hard_iface_tmp, |
499 | &hardif_list, list) { | 515 | &hardif_list, list) { |
500 | list_del_rcu(&hard_iface->list); | 516 | list_del_rcu(&hard_iface->list); |
501 | list_add_tail(&hard_iface->list, &if_queue); | ||
502 | } | ||
503 | spin_unlock(&hardif_list_lock); | ||
504 | |||
505 | rtnl_lock(); | ||
506 | list_for_each_entry_safe(hard_iface, hard_iface_tmp, &if_queue, list) { | ||
507 | hardif_remove_interface(hard_iface); | 517 | hardif_remove_interface(hard_iface); |
508 | } | 518 | } |
509 | rtnl_unlock(); | 519 | rtnl_unlock(); |
@@ -514,6 +524,7 @@ static int hard_if_event(struct notifier_block *this, | |||
514 | { | 524 | { |
515 | struct net_device *net_dev = (struct net_device *)ptr; | 525 | struct net_device *net_dev = (struct net_device *)ptr; |
516 | struct hard_iface *hard_iface = hardif_get_by_netdev(net_dev); | 526 | struct hard_iface *hard_iface = hardif_get_by_netdev(net_dev); |
527 | struct hard_iface *primary_if = NULL; | ||
517 | struct bat_priv *bat_priv; | 528 | struct bat_priv *bat_priv; |
518 | 529 | ||
519 | if (!hard_iface && event == NETDEV_REGISTER) | 530 | if (!hard_iface && event == NETDEV_REGISTER) |
@@ -531,9 +542,7 @@ static int hard_if_event(struct notifier_block *this, | |||
531 | hardif_deactivate_interface(hard_iface); | 542 | hardif_deactivate_interface(hard_iface); |
532 | break; | 543 | break; |
533 | case NETDEV_UNREGISTER: | 544 | case NETDEV_UNREGISTER: |
534 | spin_lock(&hardif_list_lock); | ||
535 | list_del_rcu(&hard_iface->list); | 545 | list_del_rcu(&hard_iface->list); |
536 | spin_unlock(&hardif_list_lock); | ||
537 | 546 | ||
538 | hardif_remove_interface(hard_iface); | 547 | hardif_remove_interface(hard_iface); |
539 | break; | 548 | break; |
@@ -549,8 +558,12 @@ static int hard_if_event(struct notifier_block *this, | |||
549 | update_mac_addresses(hard_iface); | 558 | update_mac_addresses(hard_iface); |
550 | 559 | ||
551 | bat_priv = netdev_priv(hard_iface->soft_iface); | 560 | bat_priv = netdev_priv(hard_iface->soft_iface); |
552 | if (hard_iface == bat_priv->primary_if) | 561 | primary_if = primary_if_get_selected(bat_priv); |
553 | update_primary_addr(bat_priv); | 562 | if (!primary_if) |
563 | goto hardif_put; | ||
564 | |||
565 | if (hard_iface == primary_if) | ||
566 | primary_if_update_addr(bat_priv); | ||
554 | break; | 567 | break; |
555 | default: | 568 | default: |
556 | break; | 569 | break; |
@@ -559,6 +572,8 @@ static int hard_if_event(struct notifier_block *this, | |||
559 | hardif_put: | 572 | hardif_put: |
560 | hardif_free_ref(hard_iface); | 573 | hardif_free_ref(hard_iface); |
561 | out: | 574 | out: |
575 | if (primary_if) | ||
576 | hardif_free_ref(primary_if); | ||
562 | return NOTIFY_DONE; | 577 | return NOTIFY_DONE; |
563 | } | 578 | } |
564 | 579 | ||
diff --git a/net/batman-adv/hard-interface.h b/net/batman-adv/hard-interface.h index a9ddf36e51c8..64265991460b 100644 --- a/net/batman-adv/hard-interface.h +++ b/net/batman-adv/hard-interface.h | |||
@@ -45,4 +45,22 @@ static inline void hardif_free_ref(struct hard_iface *hard_iface) | |||
45 | call_rcu(&hard_iface->rcu, hardif_free_rcu); | 45 | call_rcu(&hard_iface->rcu, hardif_free_rcu); |
46 | } | 46 | } |
47 | 47 | ||
48 | static inline struct hard_iface *primary_if_get_selected( | ||
49 | struct bat_priv *bat_priv) | ||
50 | { | ||
51 | struct hard_iface *hard_iface; | ||
52 | |||
53 | rcu_read_lock(); | ||
54 | hard_iface = rcu_dereference(bat_priv->primary_if); | ||
55 | if (!hard_iface) | ||
56 | goto out; | ||
57 | |||
58 | if (!atomic_inc_not_zero(&hard_iface->refcount)) | ||
59 | hard_iface = NULL; | ||
60 | |||
61 | out: | ||
62 | rcu_read_unlock(); | ||
63 | return hard_iface; | ||
64 | } | ||
65 | |||
48 | #endif /* _NET_BATMAN_ADV_HARD_INTERFACE_H_ */ | 66 | #endif /* _NET_BATMAN_ADV_HARD_INTERFACE_H_ */ |
diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c index 34ce56c358e5..fa22ba2bb832 100644 --- a/net/batman-adv/icmp_socket.c +++ b/net/batman-adv/icmp_socket.c | |||
@@ -153,6 +153,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, | |||
153 | { | 153 | { |
154 | struct socket_client *socket_client = file->private_data; | 154 | struct socket_client *socket_client = file->private_data; |
155 | struct bat_priv *bat_priv = socket_client->bat_priv; | 155 | struct bat_priv *bat_priv = socket_client->bat_priv; |
156 | struct hard_iface *primary_if = NULL; | ||
156 | struct sk_buff *skb; | 157 | struct sk_buff *skb; |
157 | struct icmp_packet_rr *icmp_packet; | 158 | struct icmp_packet_rr *icmp_packet; |
158 | 159 | ||
@@ -167,15 +168,21 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, | |||
167 | return -EINVAL; | 168 | return -EINVAL; |
168 | } | 169 | } |
169 | 170 | ||
170 | if (!bat_priv->primary_if) | 171 | primary_if = primary_if_get_selected(bat_priv); |
171 | return -EFAULT; | 172 | |
173 | if (!primary_if) { | ||
174 | len = -EFAULT; | ||
175 | goto out; | ||
176 | } | ||
172 | 177 | ||
173 | if (len >= sizeof(struct icmp_packet_rr)) | 178 | if (len >= sizeof(struct icmp_packet_rr)) |
174 | packet_len = sizeof(struct icmp_packet_rr); | 179 | packet_len = sizeof(struct icmp_packet_rr); |
175 | 180 | ||
176 | skb = dev_alloc_skb(packet_len + sizeof(struct ethhdr)); | 181 | skb = dev_alloc_skb(packet_len + sizeof(struct ethhdr)); |
177 | if (!skb) | 182 | if (!skb) { |
178 | return -ENOMEM; | 183 | len = -ENOMEM; |
184 | goto out; | ||
185 | } | ||
179 | 186 | ||
180 | skb_reserve(skb, sizeof(struct ethhdr)); | 187 | skb_reserve(skb, sizeof(struct ethhdr)); |
181 | icmp_packet = (struct icmp_packet_rr *)skb_put(skb, packet_len); | 188 | icmp_packet = (struct icmp_packet_rr *)skb_put(skb, packet_len); |
@@ -218,23 +225,13 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, | |||
218 | if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE) | 225 | if (atomic_read(&bat_priv->mesh_state) != MESH_ACTIVE) |
219 | goto dst_unreach; | 226 | goto dst_unreach; |
220 | 227 | ||
221 | rcu_read_lock(); | ||
222 | orig_node = orig_hash_find(bat_priv, icmp_packet->dst); | 228 | orig_node = orig_hash_find(bat_priv, icmp_packet->dst); |
223 | |||
224 | if (!orig_node) | 229 | if (!orig_node) |
225 | goto unlock; | 230 | goto dst_unreach; |
226 | |||
227 | neigh_node = orig_node->router; | ||
228 | 231 | ||
232 | neigh_node = orig_node_get_router(orig_node); | ||
229 | if (!neigh_node) | 233 | if (!neigh_node) |
230 | goto unlock; | 234 | goto dst_unreach; |
231 | |||
232 | if (!atomic_inc_not_zero(&neigh_node->refcount)) { | ||
233 | neigh_node = NULL; | ||
234 | goto unlock; | ||
235 | } | ||
236 | |||
237 | rcu_read_unlock(); | ||
238 | 235 | ||
239 | if (!neigh_node->if_incoming) | 236 | if (!neigh_node->if_incoming) |
240 | goto dst_unreach; | 237 | goto dst_unreach; |
@@ -243,7 +240,7 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, | |||
243 | goto dst_unreach; | 240 | goto dst_unreach; |
244 | 241 | ||
245 | memcpy(icmp_packet->orig, | 242 | memcpy(icmp_packet->orig, |
246 | bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); | 243 | primary_if->net_dev->dev_addr, ETH_ALEN); |
247 | 244 | ||
248 | if (packet_len == sizeof(struct icmp_packet_rr)) | 245 | if (packet_len == sizeof(struct icmp_packet_rr)) |
249 | memcpy(icmp_packet->rr, | 246 | memcpy(icmp_packet->rr, |
@@ -252,14 +249,14 @@ static ssize_t bat_socket_write(struct file *file, const char __user *buff, | |||
252 | send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); | 249 | send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); |
253 | goto out; | 250 | goto out; |
254 | 251 | ||
255 | unlock: | ||
256 | rcu_read_unlock(); | ||
257 | dst_unreach: | 252 | dst_unreach: |
258 | icmp_packet->msg_type = DESTINATION_UNREACHABLE; | 253 | icmp_packet->msg_type = DESTINATION_UNREACHABLE; |
259 | bat_socket_add_packet(socket_client, icmp_packet, packet_len); | 254 | bat_socket_add_packet(socket_client, icmp_packet, packet_len); |
260 | free_skb: | 255 | free_skb: |
261 | kfree_skb(skb); | 256 | kfree_skb(skb); |
262 | out: | 257 | out: |
258 | if (primary_if) | ||
259 | hardif_free_ref(primary_if); | ||
263 | if (neigh_node) | 260 | if (neigh_node) |
264 | neigh_node_free_ref(neigh_node); | 261 | neigh_node_free_ref(neigh_node); |
265 | if (orig_node) | 262 | if (orig_node) |
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 709b33bbdf43..0a7cee0076f4 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c | |||
@@ -33,6 +33,9 @@ | |||
33 | #include "vis.h" | 33 | #include "vis.h" |
34 | #include "hash.h" | 34 | #include "hash.h" |
35 | 35 | ||
36 | |||
37 | /* List manipulations on hardif_list have to be rtnl_lock()'ed, | ||
38 | * list traversals just rcu-locked */ | ||
36 | struct list_head hardif_list; | 39 | struct list_head hardif_list; |
37 | 40 | ||
38 | unsigned char broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; | 41 | unsigned char broadcast_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; |
@@ -81,28 +84,29 @@ int mesh_init(struct net_device *soft_iface) | |||
81 | 84 | ||
82 | spin_lock_init(&bat_priv->forw_bat_list_lock); | 85 | spin_lock_init(&bat_priv->forw_bat_list_lock); |
83 | spin_lock_init(&bat_priv->forw_bcast_list_lock); | 86 | spin_lock_init(&bat_priv->forw_bcast_list_lock); |
84 | spin_lock_init(&bat_priv->hna_lhash_lock); | 87 | spin_lock_init(&bat_priv->tt_lhash_lock); |
85 | spin_lock_init(&bat_priv->hna_ghash_lock); | 88 | spin_lock_init(&bat_priv->tt_ghash_lock); |
86 | spin_lock_init(&bat_priv->gw_list_lock); | 89 | spin_lock_init(&bat_priv->gw_list_lock); |
87 | spin_lock_init(&bat_priv->vis_hash_lock); | 90 | spin_lock_init(&bat_priv->vis_hash_lock); |
88 | spin_lock_init(&bat_priv->vis_list_lock); | 91 | spin_lock_init(&bat_priv->vis_list_lock); |
89 | spin_lock_init(&bat_priv->softif_neigh_lock); | 92 | spin_lock_init(&bat_priv->softif_neigh_lock); |
93 | spin_lock_init(&bat_priv->softif_neigh_vid_lock); | ||
90 | 94 | ||
91 | INIT_HLIST_HEAD(&bat_priv->forw_bat_list); | 95 | INIT_HLIST_HEAD(&bat_priv->forw_bat_list); |
92 | INIT_HLIST_HEAD(&bat_priv->forw_bcast_list); | 96 | INIT_HLIST_HEAD(&bat_priv->forw_bcast_list); |
93 | INIT_HLIST_HEAD(&bat_priv->gw_list); | 97 | INIT_HLIST_HEAD(&bat_priv->gw_list); |
94 | INIT_HLIST_HEAD(&bat_priv->softif_neigh_list); | 98 | INIT_HLIST_HEAD(&bat_priv->softif_neigh_vids); |
95 | 99 | ||
96 | if (originator_init(bat_priv) < 1) | 100 | if (originator_init(bat_priv) < 1) |
97 | goto err; | 101 | goto err; |
98 | 102 | ||
99 | if (hna_local_init(bat_priv) < 1) | 103 | if (tt_local_init(bat_priv) < 1) |
100 | goto err; | 104 | goto err; |
101 | 105 | ||
102 | if (hna_global_init(bat_priv) < 1) | 106 | if (tt_global_init(bat_priv) < 1) |
103 | goto err; | 107 | goto err; |
104 | 108 | ||
105 | hna_local_add(soft_iface, soft_iface->dev_addr); | 109 | tt_local_add(soft_iface, soft_iface->dev_addr); |
106 | 110 | ||
107 | if (vis_init(bat_priv) < 1) | 111 | if (vis_init(bat_priv) < 1) |
108 | goto err; | 112 | goto err; |
@@ -133,8 +137,8 @@ void mesh_free(struct net_device *soft_iface) | |||
133 | gw_node_purge(bat_priv); | 137 | gw_node_purge(bat_priv); |
134 | originator_free(bat_priv); | 138 | originator_free(bat_priv); |
135 | 139 | ||
136 | hna_local_free(bat_priv); | 140 | tt_local_free(bat_priv); |
137 | hna_global_free(bat_priv); | 141 | tt_global_free(bat_priv); |
138 | 142 | ||
139 | softif_neigh_purge(bat_priv); | 143 | softif_neigh_purge(bat_priv); |
140 | 144 | ||
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index dc248697de71..148b49e02642 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h | |||
@@ -34,16 +34,18 @@ | |||
34 | 34 | ||
35 | #define TQ_MAX_VALUE 255 | 35 | #define TQ_MAX_VALUE 255 |
36 | #define JITTER 20 | 36 | #define JITTER 20 |
37 | #define TTL 50 /* Time To Live of broadcast messages */ | ||
38 | 37 | ||
39 | #define PURGE_TIMEOUT 200 /* purge originators after time in seconds if no | 38 | /* Time To Live of broadcast messages */ |
40 | * valid packet comes in -> TODO: check | 39 | #define TTL 50 |
41 | * influence on TQ_LOCAL_WINDOW_SIZE */ | ||
42 | #define LOCAL_HNA_TIMEOUT 3600 /* in seconds */ | ||
43 | 40 | ||
44 | #define TQ_LOCAL_WINDOW_SIZE 64 /* sliding packet range of received originator | 41 | /* purge originators after time in seconds if no valid packet comes in |
45 | * messages in squence numbers (should be a | 42 | * -> TODO: check influence on TQ_LOCAL_WINDOW_SIZE */ |
46 | * multiple of our word size) */ | 43 | #define PURGE_TIMEOUT 200 |
44 | #define TT_LOCAL_TIMEOUT 3600 /* in seconds */ | ||
45 | |||
46 | /* sliding packet range of received originator messages in squence numbers | ||
47 | * (should be a multiple of our word size) */ | ||
48 | #define TQ_LOCAL_WINDOW_SIZE 64 | ||
47 | #define TQ_GLOBAL_WINDOW_SIZE 5 | 49 | #define TQ_GLOBAL_WINDOW_SIZE 5 |
48 | #define TQ_LOCAL_BIDRECT_SEND_MINIMUM 1 | 50 | #define TQ_LOCAL_BIDRECT_SEND_MINIMUM 1 |
49 | #define TQ_LOCAL_BIDRECT_RECV_MINIMUM 1 | 51 | #define TQ_LOCAL_BIDRECT_RECV_MINIMUM 1 |
@@ -55,21 +57,20 @@ | |||
55 | 57 | ||
56 | #define VIS_INTERVAL 5000 /* 5 seconds */ | 58 | #define VIS_INTERVAL 5000 /* 5 seconds */ |
57 | 59 | ||
58 | /* how much worse secondary interfaces may be to | 60 | /* how much worse secondary interfaces may be to be considered as bonding |
59 | * to be considered as bonding candidates */ | 61 | * candidates */ |
60 | |||
61 | #define BONDING_TQ_THRESHOLD 50 | 62 | #define BONDING_TQ_THRESHOLD 50 |
62 | 63 | ||
63 | #define MAX_AGGREGATION_BYTES 512 /* should not be bigger than 512 bytes or | 64 | /* should not be bigger than 512 bytes or change the size of |
64 | * change the size of | 65 | * forw_packet->direct_link_flags */ |
65 | * forw_packet->direct_link_flags */ | 66 | #define MAX_AGGREGATION_BYTES 512 |
66 | #define MAX_AGGREGATION_MS 100 | 67 | #define MAX_AGGREGATION_MS 100 |
67 | 68 | ||
68 | #define SOFTIF_NEIGH_TIMEOUT 180000 /* 3 minutes */ | 69 | #define SOFTIF_NEIGH_TIMEOUT 180000 /* 3 minutes */ |
69 | 70 | ||
71 | /* don't reset again within 30 seconds */ | ||
70 | #define RESET_PROTECTION_MS 30000 | 72 | #define RESET_PROTECTION_MS 30000 |
71 | #define EXPECTED_SEQNO_RANGE 65536 | 73 | #define EXPECTED_SEQNO_RANGE 65536 |
72 | /* don't reset again within 30 seconds */ | ||
73 | 74 | ||
74 | #define MESH_INACTIVE 0 | 75 | #define MESH_INACTIVE 0 |
75 | #define MESH_ACTIVE 1 | 76 | #define MESH_ACTIVE 1 |
@@ -84,12 +85,13 @@ | |||
84 | #ifdef pr_fmt | 85 | #ifdef pr_fmt |
85 | #undef pr_fmt | 86 | #undef pr_fmt |
86 | #endif | 87 | #endif |
87 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt /* Append 'batman-adv: ' before | 88 | /* Append 'batman-adv: ' before kernel messages */ |
88 | * kernel messages */ | 89 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
89 | 90 | ||
90 | #define DBG_BATMAN 1 /* all messages related to routing / flooding / | 91 | /* all messages related to routing / flooding / broadcasting / etc */ |
91 | * broadcasting / etc */ | 92 | #define DBG_BATMAN 1 |
92 | #define DBG_ROUTES 2 /* route or hna added / changed / deleted */ | 93 | /* route or tt entry added / changed / deleted */ |
94 | #define DBG_ROUTES 2 | ||
93 | #define DBG_ALL 3 | 95 | #define DBG_ALL 3 |
94 | 96 | ||
95 | 97 | ||
@@ -175,4 +177,6 @@ static inline int compare_eth(void *data1, void *data2) | |||
175 | return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); | 177 | return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); |
176 | } | 178 | } |
177 | 179 | ||
180 | #define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0) | ||
181 | |||
178 | #endif /* _NET_BATMAN_ADV_MAIN_H_ */ | 182 | #endif /* _NET_BATMAN_ADV_MAIN_H_ */ |
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 0b9133022d2d..080ec88330a3 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c | |||
@@ -19,8 +19,6 @@ | |||
19 | * | 19 | * |
20 | */ | 20 | */ |
21 | 21 | ||
22 | /* increase the reference counter for this originator */ | ||
23 | |||
24 | #include "main.h" | 22 | #include "main.h" |
25 | #include "originator.h" | 23 | #include "originator.h" |
26 | #include "hash.h" | 24 | #include "hash.h" |
@@ -70,6 +68,21 @@ void neigh_node_free_ref(struct neigh_node *neigh_node) | |||
70 | call_rcu(&neigh_node->rcu, neigh_node_free_rcu); | 68 | call_rcu(&neigh_node->rcu, neigh_node_free_rcu); |
71 | } | 69 | } |
72 | 70 | ||
71 | /* increases the refcounter of a found router */ | ||
72 | struct neigh_node *orig_node_get_router(struct orig_node *orig_node) | ||
73 | { | ||
74 | struct neigh_node *router; | ||
75 | |||
76 | rcu_read_lock(); | ||
77 | router = rcu_dereference(orig_node->router); | ||
78 | |||
79 | if (router && !atomic_inc_not_zero(&router->refcount)) | ||
80 | router = NULL; | ||
81 | |||
82 | rcu_read_unlock(); | ||
83 | return router; | ||
84 | } | ||
85 | |||
73 | struct neigh_node *create_neighbor(struct orig_node *orig_node, | 86 | struct neigh_node *create_neighbor(struct orig_node *orig_node, |
74 | struct orig_node *orig_neigh_node, | 87 | struct orig_node *orig_neigh_node, |
75 | uint8_t *neigh, | 88 | uint8_t *neigh, |
@@ -87,6 +100,7 @@ struct neigh_node *create_neighbor(struct orig_node *orig_node, | |||
87 | 100 | ||
88 | INIT_HLIST_NODE(&neigh_node->list); | 101 | INIT_HLIST_NODE(&neigh_node->list); |
89 | INIT_LIST_HEAD(&neigh_node->bonding_list); | 102 | INIT_LIST_HEAD(&neigh_node->bonding_list); |
103 | spin_lock_init(&neigh_node->tq_lock); | ||
90 | 104 | ||
91 | memcpy(neigh_node->addr, neigh, ETH_ALEN); | 105 | memcpy(neigh_node->addr, neigh, ETH_ALEN); |
92 | neigh_node->orig_node = orig_neigh_node; | 106 | neigh_node->orig_node = orig_neigh_node; |
@@ -128,7 +142,7 @@ static void orig_node_free_rcu(struct rcu_head *rcu) | |||
128 | spin_unlock_bh(&orig_node->neigh_list_lock); | 142 | spin_unlock_bh(&orig_node->neigh_list_lock); |
129 | 143 | ||
130 | frag_list_free(&orig_node->frag_list); | 144 | frag_list_free(&orig_node->frag_list); |
131 | hna_global_del_orig(orig_node->bat_priv, orig_node, | 145 | tt_global_del_orig(orig_node->bat_priv, orig_node, |
132 | "originator timed out"); | 146 | "originator timed out"); |
133 | 147 | ||
134 | kfree(orig_node->bcast_own); | 148 | kfree(orig_node->bcast_own); |
@@ -206,7 +220,7 @@ struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr) | |||
206 | orig_node->bat_priv = bat_priv; | 220 | orig_node->bat_priv = bat_priv; |
207 | memcpy(orig_node->orig, addr, ETH_ALEN); | 221 | memcpy(orig_node->orig, addr, ETH_ALEN); |
208 | orig_node->router = NULL; | 222 | orig_node->router = NULL; |
209 | orig_node->hna_buff = NULL; | 223 | orig_node->tt_buff = NULL; |
210 | orig_node->bcast_seqno_reset = jiffies - 1 | 224 | orig_node->bcast_seqno_reset = jiffies - 1 |
211 | - msecs_to_jiffies(RESET_PROTECTION_MS); | 225 | - msecs_to_jiffies(RESET_PROTECTION_MS); |
212 | orig_node->batman_seqno_reset = jiffies - 1 | 226 | orig_node->batman_seqno_reset = jiffies - 1 |
@@ -317,8 +331,8 @@ static bool purge_orig_node(struct bat_priv *bat_priv, | |||
317 | &best_neigh_node)) { | 331 | &best_neigh_node)) { |
318 | update_routes(bat_priv, orig_node, | 332 | update_routes(bat_priv, orig_node, |
319 | best_neigh_node, | 333 | best_neigh_node, |
320 | orig_node->hna_buff, | 334 | orig_node->tt_buff, |
321 | orig_node->hna_buff_len); | 335 | orig_node->tt_buff_len); |
322 | } | 336 | } |
323 | } | 337 | } |
324 | 338 | ||
@@ -389,29 +403,34 @@ int orig_seq_print_text(struct seq_file *seq, void *offset) | |||
389 | struct hashtable_t *hash = bat_priv->orig_hash; | 403 | struct hashtable_t *hash = bat_priv->orig_hash; |
390 | struct hlist_node *node, *node_tmp; | 404 | struct hlist_node *node, *node_tmp; |
391 | struct hlist_head *head; | 405 | struct hlist_head *head; |
406 | struct hard_iface *primary_if; | ||
392 | struct orig_node *orig_node; | 407 | struct orig_node *orig_node; |
393 | struct neigh_node *neigh_node; | 408 | struct neigh_node *neigh_node, *neigh_node_tmp; |
394 | int batman_count = 0; | 409 | int batman_count = 0; |
395 | int last_seen_secs; | 410 | int last_seen_secs; |
396 | int last_seen_msecs; | 411 | int last_seen_msecs; |
397 | int i; | 412 | int i, ret = 0; |
398 | 413 | ||
399 | if ((!bat_priv->primary_if) || | 414 | primary_if = primary_if_get_selected(bat_priv); |
400 | (bat_priv->primary_if->if_status != IF_ACTIVE)) { | 415 | |
401 | if (!bat_priv->primary_if) | 416 | if (!primary_if) { |
402 | return seq_printf(seq, "BATMAN mesh %s disabled - " | 417 | ret = seq_printf(seq, "BATMAN mesh %s disabled - " |
403 | "please specify interfaces to enable it\n", | 418 | "please specify interfaces to enable it\n", |
404 | net_dev->name); | 419 | net_dev->name); |
420 | goto out; | ||
421 | } | ||
405 | 422 | ||
406 | return seq_printf(seq, "BATMAN mesh %s " | 423 | if (primary_if->if_status != IF_ACTIVE) { |
407 | "disabled - primary interface not active\n", | 424 | ret = seq_printf(seq, "BATMAN mesh %s " |
408 | net_dev->name); | 425 | "disabled - primary interface not active\n", |
426 | net_dev->name); | ||
427 | goto out; | ||
409 | } | 428 | } |
410 | 429 | ||
411 | seq_printf(seq, "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n", | 430 | seq_printf(seq, "[B.A.T.M.A.N. adv %s%s, MainIF/MAC: %s/%pM (%s)]\n", |
412 | SOURCE_VERSION, REVISION_VERSION_STR, | 431 | SOURCE_VERSION, REVISION_VERSION_STR, |
413 | bat_priv->primary_if->net_dev->name, | 432 | primary_if->net_dev->name, |
414 | bat_priv->primary_if->net_dev->dev_addr, net_dev->name); | 433 | primary_if->net_dev->dev_addr, net_dev->name); |
415 | seq_printf(seq, " %-15s %s (%s/%i) %17s [%10s]: %20s ...\n", | 434 | seq_printf(seq, " %-15s %s (%s/%i) %17s [%10s]: %20s ...\n", |
416 | "Originator", "last-seen", "#", TQ_MAX_VALUE, "Nexthop", | 435 | "Originator", "last-seen", "#", TQ_MAX_VALUE, "Nexthop", |
417 | "outgoingIF", "Potential nexthops"); | 436 | "outgoingIF", "Potential nexthops"); |
@@ -421,40 +440,47 @@ int orig_seq_print_text(struct seq_file *seq, void *offset) | |||
421 | 440 | ||
422 | rcu_read_lock(); | 441 | rcu_read_lock(); |
423 | hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { | 442 | hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { |
424 | if (!orig_node->router) | 443 | neigh_node = orig_node_get_router(orig_node); |
444 | if (!neigh_node) | ||
425 | continue; | 445 | continue; |
426 | 446 | ||
427 | if (orig_node->router->tq_avg == 0) | 447 | if (neigh_node->tq_avg == 0) |
428 | continue; | 448 | goto next; |
429 | 449 | ||
430 | last_seen_secs = jiffies_to_msecs(jiffies - | 450 | last_seen_secs = jiffies_to_msecs(jiffies - |
431 | orig_node->last_valid) / 1000; | 451 | orig_node->last_valid) / 1000; |
432 | last_seen_msecs = jiffies_to_msecs(jiffies - | 452 | last_seen_msecs = jiffies_to_msecs(jiffies - |
433 | orig_node->last_valid) % 1000; | 453 | orig_node->last_valid) % 1000; |
434 | 454 | ||
435 | neigh_node = orig_node->router; | ||
436 | seq_printf(seq, "%pM %4i.%03is (%3i) %pM [%10s]:", | 455 | seq_printf(seq, "%pM %4i.%03is (%3i) %pM [%10s]:", |
437 | orig_node->orig, last_seen_secs, | 456 | orig_node->orig, last_seen_secs, |
438 | last_seen_msecs, neigh_node->tq_avg, | 457 | last_seen_msecs, neigh_node->tq_avg, |
439 | neigh_node->addr, | 458 | neigh_node->addr, |
440 | neigh_node->if_incoming->net_dev->name); | 459 | neigh_node->if_incoming->net_dev->name); |
441 | 460 | ||
442 | hlist_for_each_entry_rcu(neigh_node, node_tmp, | 461 | hlist_for_each_entry_rcu(neigh_node_tmp, node_tmp, |
443 | &orig_node->neigh_list, list) { | 462 | &orig_node->neigh_list, list) { |
444 | seq_printf(seq, " %pM (%3i)", neigh_node->addr, | 463 | seq_printf(seq, " %pM (%3i)", |
445 | neigh_node->tq_avg); | 464 | neigh_node_tmp->addr, |
465 | neigh_node_tmp->tq_avg); | ||
446 | } | 466 | } |
447 | 467 | ||
448 | seq_printf(seq, "\n"); | 468 | seq_printf(seq, "\n"); |
449 | batman_count++; | 469 | batman_count++; |
470 | |||
471 | next: | ||
472 | neigh_node_free_ref(neigh_node); | ||
450 | } | 473 | } |
451 | rcu_read_unlock(); | 474 | rcu_read_unlock(); |
452 | } | 475 | } |
453 | 476 | ||
454 | if ((batman_count == 0)) | 477 | if (batman_count == 0) |
455 | seq_printf(seq, "No batman nodes in range ...\n"); | 478 | seq_printf(seq, "No batman nodes in range ...\n"); |
456 | 479 | ||
457 | return 0; | 480 | out: |
481 | if (primary_if) | ||
482 | hardif_free_ref(primary_if); | ||
483 | return ret; | ||
458 | } | 484 | } |
459 | 485 | ||
460 | static int orig_node_add_if(struct orig_node *orig_node, int max_if_num) | 486 | static int orig_node_add_if(struct orig_node *orig_node, int max_if_num) |
diff --git a/net/batman-adv/originator.h b/net/batman-adv/originator.h index 5cc011057da1..e1d641f27aa9 100644 --- a/net/batman-adv/originator.h +++ b/net/batman-adv/originator.h | |||
@@ -34,6 +34,7 @@ struct neigh_node *create_neighbor(struct orig_node *orig_node, | |||
34 | uint8_t *neigh, | 34 | uint8_t *neigh, |
35 | struct hard_iface *if_incoming); | 35 | struct hard_iface *if_incoming); |
36 | void neigh_node_free_ref(struct neigh_node *neigh_node); | 36 | void neigh_node_free_ref(struct neigh_node *neigh_node); |
37 | struct neigh_node *orig_node_get_router(struct orig_node *orig_node); | ||
37 | int orig_seq_print_text(struct seq_file *seq, void *offset); | 38 | int orig_seq_print_text(struct seq_file *seq, void *offset); |
38 | int orig_hash_add_if(struct hard_iface *hard_iface, int max_if_num); | 39 | int orig_hash_add_if(struct hard_iface *hard_iface, int max_if_num); |
39 | int orig_hash_del_if(struct hard_iface *hard_iface, int max_if_num); | 40 | int orig_hash_del_if(struct hard_iface *hard_iface, int max_if_num); |
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h index e7571879af3f..eda99650e9f8 100644 --- a/net/batman-adv/packet.h +++ b/net/batman-adv/packet.h | |||
@@ -61,7 +61,7 @@ struct batman_packet { | |||
61 | uint8_t orig[6]; | 61 | uint8_t orig[6]; |
62 | uint8_t prev_sender[6]; | 62 | uint8_t prev_sender[6]; |
63 | uint8_t ttl; | 63 | uint8_t ttl; |
64 | uint8_t num_hna; | 64 | uint8_t num_tt; |
65 | uint8_t gw_flags; /* flags related to gateway class */ | 65 | uint8_t gw_flags; /* flags related to gateway class */ |
66 | uint8_t align; | 66 | uint8_t align; |
67 | } __packed; | 67 | } __packed; |
@@ -128,8 +128,7 @@ struct vis_packet { | |||
128 | uint8_t entries; /* number of entries behind this struct */ | 128 | uint8_t entries; /* number of entries behind this struct */ |
129 | uint32_t seqno; /* sequence number */ | 129 | uint32_t seqno; /* sequence number */ |
130 | uint8_t ttl; /* TTL */ | 130 | uint8_t ttl; /* TTL */ |
131 | uint8_t vis_orig[6]; /* originator that informs about its | 131 | uint8_t vis_orig[6]; /* originator that announces its neighbors */ |
132 | * neighbors */ | ||
133 | uint8_t target_orig[6]; /* who should receive this packet */ | 132 | uint8_t target_orig[6]; /* who should receive this packet */ |
134 | uint8_t sender_orig[6]; /* who sent or rebroadcasted this packet */ | 133 | uint8_t sender_orig[6]; /* who sent or rebroadcasted this packet */ |
135 | } __packed; | 134 | } __packed; |
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index c172f5d0e05a..bb1c3ec7e3ff 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c | |||
@@ -64,80 +64,97 @@ void slide_own_bcast_window(struct hard_iface *hard_iface) | |||
64 | } | 64 | } |
65 | } | 65 | } |
66 | 66 | ||
67 | static void update_HNA(struct bat_priv *bat_priv, struct orig_node *orig_node, | 67 | static void update_TT(struct bat_priv *bat_priv, struct orig_node *orig_node, |
68 | unsigned char *hna_buff, int hna_buff_len) | 68 | unsigned char *tt_buff, int tt_buff_len) |
69 | { | 69 | { |
70 | if ((hna_buff_len != orig_node->hna_buff_len) || | 70 | if ((tt_buff_len != orig_node->tt_buff_len) || |
71 | ((hna_buff_len > 0) && | 71 | ((tt_buff_len > 0) && |
72 | (orig_node->hna_buff_len > 0) && | 72 | (orig_node->tt_buff_len > 0) && |
73 | (memcmp(orig_node->hna_buff, hna_buff, hna_buff_len) != 0))) { | 73 | (memcmp(orig_node->tt_buff, tt_buff, tt_buff_len) != 0))) { |
74 | 74 | ||
75 | if (orig_node->hna_buff_len > 0) | 75 | if (orig_node->tt_buff_len > 0) |
76 | hna_global_del_orig(bat_priv, orig_node, | 76 | tt_global_del_orig(bat_priv, orig_node, |
77 | "originator changed hna"); | 77 | "originator changed tt"); |
78 | 78 | ||
79 | if ((hna_buff_len > 0) && (hna_buff)) | 79 | if ((tt_buff_len > 0) && (tt_buff)) |
80 | hna_global_add_orig(bat_priv, orig_node, | 80 | tt_global_add_orig(bat_priv, orig_node, |
81 | hna_buff, hna_buff_len); | 81 | tt_buff, tt_buff_len); |
82 | } | 82 | } |
83 | } | 83 | } |
84 | 84 | ||
85 | static void update_route(struct bat_priv *bat_priv, | 85 | static void update_route(struct bat_priv *bat_priv, |
86 | struct orig_node *orig_node, | 86 | struct orig_node *orig_node, |
87 | struct neigh_node *neigh_node, | 87 | struct neigh_node *neigh_node, |
88 | unsigned char *hna_buff, int hna_buff_len) | 88 | unsigned char *tt_buff, int tt_buff_len) |
89 | { | 89 | { |
90 | struct neigh_node *neigh_node_tmp; | 90 | struct neigh_node *curr_router; |
91 | |||
92 | curr_router = orig_node_get_router(orig_node); | ||
91 | 93 | ||
92 | /* route deleted */ | 94 | /* route deleted */ |
93 | if ((orig_node->router) && (!neigh_node)) { | 95 | if ((curr_router) && (!neigh_node)) { |
94 | 96 | ||
95 | bat_dbg(DBG_ROUTES, bat_priv, "Deleting route towards: %pM\n", | 97 | bat_dbg(DBG_ROUTES, bat_priv, "Deleting route towards: %pM\n", |
96 | orig_node->orig); | 98 | orig_node->orig); |
97 | hna_global_del_orig(bat_priv, orig_node, | 99 | tt_global_del_orig(bat_priv, orig_node, |
98 | "originator timed out"); | 100 | "originator timed out"); |
99 | 101 | ||
100 | /* route added */ | 102 | /* route added */ |
101 | } else if ((!orig_node->router) && (neigh_node)) { | 103 | } else if ((!curr_router) && (neigh_node)) { |
102 | 104 | ||
103 | bat_dbg(DBG_ROUTES, bat_priv, | 105 | bat_dbg(DBG_ROUTES, bat_priv, |
104 | "Adding route towards: %pM (via %pM)\n", | 106 | "Adding route towards: %pM (via %pM)\n", |
105 | orig_node->orig, neigh_node->addr); | 107 | orig_node->orig, neigh_node->addr); |
106 | hna_global_add_orig(bat_priv, orig_node, | 108 | tt_global_add_orig(bat_priv, orig_node, |
107 | hna_buff, hna_buff_len); | 109 | tt_buff, tt_buff_len); |
108 | 110 | ||
109 | /* route changed */ | 111 | /* route changed */ |
110 | } else { | 112 | } else { |
111 | bat_dbg(DBG_ROUTES, bat_priv, | 113 | bat_dbg(DBG_ROUTES, bat_priv, |
112 | "Changing route towards: %pM " | 114 | "Changing route towards: %pM " |
113 | "(now via %pM - was via %pM)\n", | 115 | "(now via %pM - was via %pM)\n", |
114 | orig_node->orig, neigh_node->addr, | 116 | orig_node->orig, neigh_node->addr, |
115 | orig_node->router->addr); | 117 | curr_router->addr); |
116 | } | 118 | } |
117 | 119 | ||
120 | if (curr_router) | ||
121 | neigh_node_free_ref(curr_router); | ||
122 | |||
123 | /* increase refcount of new best neighbor */ | ||
118 | if (neigh_node && !atomic_inc_not_zero(&neigh_node->refcount)) | 124 | if (neigh_node && !atomic_inc_not_zero(&neigh_node->refcount)) |
119 | neigh_node = NULL; | 125 | neigh_node = NULL; |
120 | neigh_node_tmp = orig_node->router; | 126 | |
121 | orig_node->router = neigh_node; | 127 | spin_lock_bh(&orig_node->neigh_list_lock); |
122 | if (neigh_node_tmp) | 128 | rcu_assign_pointer(orig_node->router, neigh_node); |
123 | neigh_node_free_ref(neigh_node_tmp); | 129 | spin_unlock_bh(&orig_node->neigh_list_lock); |
130 | |||
131 | /* decrease refcount of previous best neighbor */ | ||
132 | if (curr_router) | ||
133 | neigh_node_free_ref(curr_router); | ||
124 | } | 134 | } |
125 | 135 | ||
126 | 136 | ||
127 | void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, | 137 | void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, |
128 | struct neigh_node *neigh_node, unsigned char *hna_buff, | 138 | struct neigh_node *neigh_node, unsigned char *tt_buff, |
129 | int hna_buff_len) | 139 | int tt_buff_len) |
130 | { | 140 | { |
141 | struct neigh_node *router = NULL; | ||
131 | 142 | ||
132 | if (!orig_node) | 143 | if (!orig_node) |
133 | return; | 144 | goto out; |
145 | |||
146 | router = orig_node_get_router(orig_node); | ||
134 | 147 | ||
135 | if (orig_node->router != neigh_node) | 148 | if (router != neigh_node) |
136 | update_route(bat_priv, orig_node, neigh_node, | 149 | update_route(bat_priv, orig_node, neigh_node, |
137 | hna_buff, hna_buff_len); | 150 | tt_buff, tt_buff_len); |
138 | /* may be just HNA changed */ | 151 | /* may be just TT changed */ |
139 | else | 152 | else |
140 | update_HNA(bat_priv, orig_node, hna_buff, hna_buff_len); | 153 | update_TT(bat_priv, orig_node, tt_buff, tt_buff_len); |
154 | |||
155 | out: | ||
156 | if (router) | ||
157 | neigh_node_free_ref(router); | ||
141 | } | 158 | } |
142 | 159 | ||
143 | static int is_bidirectional_neigh(struct orig_node *orig_node, | 160 | static int is_bidirectional_neigh(struct orig_node *orig_node, |
@@ -152,65 +169,41 @@ static int is_bidirectional_neigh(struct orig_node *orig_node, | |||
152 | uint8_t orig_eq_count, neigh_rq_count, tq_own; | 169 | uint8_t orig_eq_count, neigh_rq_count, tq_own; |
153 | int tq_asym_penalty, ret = 0; | 170 | int tq_asym_penalty, ret = 0; |
154 | 171 | ||
155 | if (orig_node == orig_neigh_node) { | 172 | /* find corresponding one hop neighbor */ |
156 | rcu_read_lock(); | 173 | rcu_read_lock(); |
157 | hlist_for_each_entry_rcu(tmp_neigh_node, node, | 174 | hlist_for_each_entry_rcu(tmp_neigh_node, node, |
158 | &orig_node->neigh_list, list) { | 175 | &orig_neigh_node->neigh_list, list) { |
159 | |||
160 | if (!compare_eth(tmp_neigh_node->addr, | ||
161 | orig_neigh_node->orig)) | ||
162 | continue; | ||
163 | |||
164 | if (tmp_neigh_node->if_incoming != if_incoming) | ||
165 | continue; | ||
166 | |||
167 | if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) | ||
168 | continue; | ||
169 | |||
170 | neigh_node = tmp_neigh_node; | ||
171 | } | ||
172 | rcu_read_unlock(); | ||
173 | 176 | ||
174 | if (!neigh_node) | 177 | if (!compare_eth(tmp_neigh_node->addr, orig_neigh_node->orig)) |
175 | neigh_node = create_neighbor(orig_node, | 178 | continue; |
176 | orig_neigh_node, | ||
177 | orig_neigh_node->orig, | ||
178 | if_incoming); | ||
179 | if (!neigh_node) | ||
180 | goto out; | ||
181 | 179 | ||
182 | neigh_node->last_valid = jiffies; | 180 | if (tmp_neigh_node->if_incoming != if_incoming) |
183 | } else { | 181 | continue; |
184 | /* find packet count of corresponding one hop neighbor */ | ||
185 | rcu_read_lock(); | ||
186 | hlist_for_each_entry_rcu(tmp_neigh_node, node, | ||
187 | &orig_neigh_node->neigh_list, list) { | ||
188 | 182 | ||
189 | if (!compare_eth(tmp_neigh_node->addr, | 183 | if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) |
190 | orig_neigh_node->orig)) | 184 | continue; |
191 | continue; | ||
192 | 185 | ||
193 | if (tmp_neigh_node->if_incoming != if_incoming) | 186 | neigh_node = tmp_neigh_node; |
194 | continue; | 187 | break; |
188 | } | ||
189 | rcu_read_unlock(); | ||
195 | 190 | ||
196 | if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) | 191 | if (!neigh_node) |
197 | continue; | 192 | neigh_node = create_neighbor(orig_neigh_node, |
193 | orig_neigh_node, | ||
194 | orig_neigh_node->orig, | ||
195 | if_incoming); | ||
198 | 196 | ||
199 | neigh_node = tmp_neigh_node; | 197 | if (!neigh_node) |
200 | } | 198 | goto out; |
201 | rcu_read_unlock(); | ||
202 | 199 | ||
203 | if (!neigh_node) | 200 | /* if orig_node is direct neighbour update neigh_node last_valid */ |
204 | neigh_node = create_neighbor(orig_neigh_node, | 201 | if (orig_node == orig_neigh_node) |
205 | orig_neigh_node, | 202 | neigh_node->last_valid = jiffies; |
206 | orig_neigh_node->orig, | ||
207 | if_incoming); | ||
208 | if (!neigh_node) | ||
209 | goto out; | ||
210 | } | ||
211 | 203 | ||
212 | orig_node->last_valid = jiffies; | 204 | orig_node->last_valid = jiffies; |
213 | 205 | ||
206 | /* find packet count of corresponding one hop neighbor */ | ||
214 | spin_lock_bh(&orig_node->ogm_cnt_lock); | 207 | spin_lock_bh(&orig_node->ogm_cnt_lock); |
215 | orig_eq_count = orig_neigh_node->bcast_own_sum[if_incoming->if_num]; | 208 | orig_eq_count = orig_neigh_node->bcast_own_sum[if_incoming->if_num]; |
216 | neigh_rq_count = neigh_node->real_packet_count; | 209 | neigh_rq_count = neigh_node->real_packet_count; |
@@ -288,8 +281,8 @@ static void bonding_candidate_add(struct orig_node *orig_node, | |||
288 | struct neigh_node *neigh_node) | 281 | struct neigh_node *neigh_node) |
289 | { | 282 | { |
290 | struct hlist_node *node; | 283 | struct hlist_node *node; |
291 | struct neigh_node *tmp_neigh_node; | 284 | struct neigh_node *tmp_neigh_node, *router = NULL; |
292 | uint8_t best_tq, interference_candidate = 0; | 285 | uint8_t interference_candidate = 0; |
293 | 286 | ||
294 | spin_lock_bh(&orig_node->neigh_list_lock); | 287 | spin_lock_bh(&orig_node->neigh_list_lock); |
295 | 288 | ||
@@ -298,13 +291,12 @@ static void bonding_candidate_add(struct orig_node *orig_node, | |||
298 | neigh_node->orig_node->primary_addr)) | 291 | neigh_node->orig_node->primary_addr)) |
299 | goto candidate_del; | 292 | goto candidate_del; |
300 | 293 | ||
301 | if (!orig_node->router) | 294 | router = orig_node_get_router(orig_node); |
295 | if (!router) | ||
302 | goto candidate_del; | 296 | goto candidate_del; |
303 | 297 | ||
304 | best_tq = orig_node->router->tq_avg; | ||
305 | |||
306 | /* ... and is good enough to be considered */ | 298 | /* ... and is good enough to be considered */ |
307 | if (neigh_node->tq_avg < best_tq - BONDING_TQ_THRESHOLD) | 299 | if (neigh_node->tq_avg < router->tq_avg - BONDING_TQ_THRESHOLD) |
308 | goto candidate_del; | 300 | goto candidate_del; |
309 | 301 | ||
310 | /** | 302 | /** |
@@ -350,7 +342,9 @@ candidate_del: | |||
350 | 342 | ||
351 | out: | 343 | out: |
352 | spin_unlock_bh(&orig_node->neigh_list_lock); | 344 | spin_unlock_bh(&orig_node->neigh_list_lock); |
353 | return; | 345 | |
346 | if (router) | ||
347 | neigh_node_free_ref(router); | ||
354 | } | 348 | } |
355 | 349 | ||
356 | /* copy primary address for bonding */ | 350 | /* copy primary address for bonding */ |
@@ -369,13 +363,14 @@ static void update_orig(struct bat_priv *bat_priv, | |||
369 | struct ethhdr *ethhdr, | 363 | struct ethhdr *ethhdr, |
370 | struct batman_packet *batman_packet, | 364 | struct batman_packet *batman_packet, |
371 | struct hard_iface *if_incoming, | 365 | struct hard_iface *if_incoming, |
372 | unsigned char *hna_buff, int hna_buff_len, | 366 | unsigned char *tt_buff, int tt_buff_len, |
373 | char is_duplicate) | 367 | char is_duplicate) |
374 | { | 368 | { |
375 | struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; | 369 | struct neigh_node *neigh_node = NULL, *tmp_neigh_node = NULL; |
370 | struct neigh_node *router = NULL; | ||
376 | struct orig_node *orig_node_tmp; | 371 | struct orig_node *orig_node_tmp; |
377 | struct hlist_node *node; | 372 | struct hlist_node *node; |
378 | int tmp_hna_buff_len; | 373 | int tmp_tt_buff_len; |
379 | uint8_t bcast_own_sum_orig, bcast_own_sum_neigh; | 374 | uint8_t bcast_own_sum_orig, bcast_own_sum_neigh; |
380 | 375 | ||
381 | bat_dbg(DBG_BATMAN, bat_priv, "update_originator(): " | 376 | bat_dbg(DBG_BATMAN, bat_priv, "update_originator(): " |
@@ -396,10 +391,12 @@ static void update_orig(struct bat_priv *bat_priv, | |||
396 | if (is_duplicate) | 391 | if (is_duplicate) |
397 | continue; | 392 | continue; |
398 | 393 | ||
394 | spin_lock_bh(&tmp_neigh_node->tq_lock); | ||
399 | ring_buffer_set(tmp_neigh_node->tq_recv, | 395 | ring_buffer_set(tmp_neigh_node->tq_recv, |
400 | &tmp_neigh_node->tq_index, 0); | 396 | &tmp_neigh_node->tq_index, 0); |
401 | tmp_neigh_node->tq_avg = | 397 | tmp_neigh_node->tq_avg = |
402 | ring_buffer_avg(tmp_neigh_node->tq_recv); | 398 | ring_buffer_avg(tmp_neigh_node->tq_recv); |
399 | spin_unlock_bh(&tmp_neigh_node->tq_lock); | ||
403 | } | 400 | } |
404 | 401 | ||
405 | if (!neigh_node) { | 402 | if (!neigh_node) { |
@@ -424,10 +421,12 @@ static void update_orig(struct bat_priv *bat_priv, | |||
424 | orig_node->flags = batman_packet->flags; | 421 | orig_node->flags = batman_packet->flags; |
425 | neigh_node->last_valid = jiffies; | 422 | neigh_node->last_valid = jiffies; |
426 | 423 | ||
424 | spin_lock_bh(&neigh_node->tq_lock); | ||
427 | ring_buffer_set(neigh_node->tq_recv, | 425 | ring_buffer_set(neigh_node->tq_recv, |
428 | &neigh_node->tq_index, | 426 | &neigh_node->tq_index, |
429 | batman_packet->tq); | 427 | batman_packet->tq); |
430 | neigh_node->tq_avg = ring_buffer_avg(neigh_node->tq_recv); | 428 | neigh_node->tq_avg = ring_buffer_avg(neigh_node->tq_recv); |
429 | spin_unlock_bh(&neigh_node->tq_lock); | ||
431 | 430 | ||
432 | if (!is_duplicate) { | 431 | if (!is_duplicate) { |
433 | orig_node->last_ttl = batman_packet->ttl; | 432 | orig_node->last_ttl = batman_packet->ttl; |
@@ -436,24 +435,23 @@ static void update_orig(struct bat_priv *bat_priv, | |||
436 | 435 | ||
437 | bonding_candidate_add(orig_node, neigh_node); | 436 | bonding_candidate_add(orig_node, neigh_node); |
438 | 437 | ||
439 | tmp_hna_buff_len = (hna_buff_len > batman_packet->num_hna * ETH_ALEN ? | 438 | tmp_tt_buff_len = (tt_buff_len > batman_packet->num_tt * ETH_ALEN ? |
440 | batman_packet->num_hna * ETH_ALEN : hna_buff_len); | 439 | batman_packet->num_tt * ETH_ALEN : tt_buff_len); |
441 | 440 | ||
442 | /* if this neighbor already is our next hop there is nothing | 441 | /* if this neighbor already is our next hop there is nothing |
443 | * to change */ | 442 | * to change */ |
444 | if (orig_node->router == neigh_node) | 443 | router = orig_node_get_router(orig_node); |
445 | goto update_hna; | 444 | if (router == neigh_node) |
445 | goto update_tt; | ||
446 | 446 | ||
447 | /* if this neighbor does not offer a better TQ we won't consider it */ | 447 | /* if this neighbor does not offer a better TQ we won't consider it */ |
448 | if ((orig_node->router) && | 448 | if (router && (router->tq_avg > neigh_node->tq_avg)) |
449 | (orig_node->router->tq_avg > neigh_node->tq_avg)) | 449 | goto update_tt; |
450 | goto update_hna; | ||
451 | 450 | ||
452 | /* if the TQ is the same and the link not more symetric we | 451 | /* if the TQ is the same and the link not more symetric we |
453 | * won't consider it either */ | 452 | * won't consider it either */ |
454 | if ((orig_node->router) && | 453 | if (router && (neigh_node->tq_avg == router->tq_avg)) { |
455 | (neigh_node->tq_avg == orig_node->router->tq_avg)) { | 454 | orig_node_tmp = router->orig_node; |
456 | orig_node_tmp = orig_node->router->orig_node; | ||
457 | spin_lock_bh(&orig_node_tmp->ogm_cnt_lock); | 455 | spin_lock_bh(&orig_node_tmp->ogm_cnt_lock); |
458 | bcast_own_sum_orig = | 456 | bcast_own_sum_orig = |
459 | orig_node_tmp->bcast_own_sum[if_incoming->if_num]; | 457 | orig_node_tmp->bcast_own_sum[if_incoming->if_num]; |
@@ -466,16 +464,16 @@ static void update_orig(struct bat_priv *bat_priv, | |||
466 | spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock); | 464 | spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock); |
467 | 465 | ||
468 | if (bcast_own_sum_orig >= bcast_own_sum_neigh) | 466 | if (bcast_own_sum_orig >= bcast_own_sum_neigh) |
469 | goto update_hna; | 467 | goto update_tt; |
470 | } | 468 | } |
471 | 469 | ||
472 | update_routes(bat_priv, orig_node, neigh_node, | 470 | update_routes(bat_priv, orig_node, neigh_node, |
473 | hna_buff, tmp_hna_buff_len); | 471 | tt_buff, tmp_tt_buff_len); |
474 | goto update_gw; | 472 | goto update_gw; |
475 | 473 | ||
476 | update_hna: | 474 | update_tt: |
477 | update_routes(bat_priv, orig_node, orig_node->router, | 475 | update_routes(bat_priv, orig_node, router, |
478 | hna_buff, tmp_hna_buff_len); | 476 | tt_buff, tmp_tt_buff_len); |
479 | 477 | ||
480 | update_gw: | 478 | update_gw: |
481 | if (orig_node->gw_flags != batman_packet->gw_flags) | 479 | if (orig_node->gw_flags != batman_packet->gw_flags) |
@@ -496,6 +494,8 @@ unlock: | |||
496 | out: | 494 | out: |
497 | if (neigh_node) | 495 | if (neigh_node) |
498 | neigh_node_free_ref(neigh_node); | 496 | neigh_node_free_ref(neigh_node); |
497 | if (router) | ||
498 | neigh_node_free_ref(router); | ||
499 | } | 499 | } |
500 | 500 | ||
501 | /* checks whether the host restarted and is in the protection time. | 501 | /* checks whether the host restarted and is in the protection time. |
@@ -597,12 +597,14 @@ out: | |||
597 | 597 | ||
598 | void receive_bat_packet(struct ethhdr *ethhdr, | 598 | void receive_bat_packet(struct ethhdr *ethhdr, |
599 | struct batman_packet *batman_packet, | 599 | struct batman_packet *batman_packet, |
600 | unsigned char *hna_buff, int hna_buff_len, | 600 | unsigned char *tt_buff, int tt_buff_len, |
601 | struct hard_iface *if_incoming) | 601 | struct hard_iface *if_incoming) |
602 | { | 602 | { |
603 | struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); | 603 | struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); |
604 | struct hard_iface *hard_iface; | 604 | struct hard_iface *hard_iface; |
605 | struct orig_node *orig_neigh_node, *orig_node; | 605 | struct orig_node *orig_neigh_node, *orig_node; |
606 | struct neigh_node *router = NULL, *router_router = NULL; | ||
607 | struct neigh_node *orig_neigh_router = NULL; | ||
606 | char has_directlink_flag; | 608 | char has_directlink_flag; |
607 | char is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0; | 609 | char is_my_addr = 0, is_my_orig = 0, is_my_oldorig = 0; |
608 | char is_broadcast = 0, is_bidirectional, is_single_hop_neigh; | 610 | char is_broadcast = 0, is_bidirectional, is_single_hop_neigh; |
@@ -747,14 +749,15 @@ void receive_bat_packet(struct ethhdr *ethhdr, | |||
747 | goto out; | 749 | goto out; |
748 | } | 750 | } |
749 | 751 | ||
752 | router = orig_node_get_router(orig_node); | ||
753 | if (router) | ||
754 | router_router = orig_node_get_router(router->orig_node); | ||
755 | |||
750 | /* avoid temporary routing loops */ | 756 | /* avoid temporary routing loops */ |
751 | if ((orig_node->router) && | 757 | if (router && router_router && |
752 | (orig_node->router->orig_node->router) && | 758 | (compare_eth(router->addr, batman_packet->prev_sender)) && |
753 | (compare_eth(orig_node->router->addr, | ||
754 | batman_packet->prev_sender)) && | ||
755 | !(compare_eth(batman_packet->orig, batman_packet->prev_sender)) && | 759 | !(compare_eth(batman_packet->orig, batman_packet->prev_sender)) && |
756 | (compare_eth(orig_node->router->addr, | 760 | (compare_eth(router->addr, router_router->addr))) { |
757 | orig_node->router->orig_node->router->addr))) { | ||
758 | bat_dbg(DBG_BATMAN, bat_priv, | 761 | bat_dbg(DBG_BATMAN, bat_priv, |
759 | "Drop packet: ignoring all rebroadcast packets that " | 762 | "Drop packet: ignoring all rebroadcast packets that " |
760 | "may make me loop (sender: %pM)\n", ethhdr->h_source); | 763 | "may make me loop (sender: %pM)\n", ethhdr->h_source); |
@@ -769,9 +772,11 @@ void receive_bat_packet(struct ethhdr *ethhdr, | |||
769 | if (!orig_neigh_node) | 772 | if (!orig_neigh_node) |
770 | goto out; | 773 | goto out; |
771 | 774 | ||
775 | orig_neigh_router = orig_node_get_router(orig_neigh_node); | ||
776 | |||
772 | /* drop packet if sender is not a direct neighbor and if we | 777 | /* drop packet if sender is not a direct neighbor and if we |
773 | * don't route towards it */ | 778 | * don't route towards it */ |
774 | if (!is_single_hop_neigh && (!orig_neigh_node->router)) { | 779 | if (!is_single_hop_neigh && (!orig_neigh_router)) { |
775 | bat_dbg(DBG_BATMAN, bat_priv, | 780 | bat_dbg(DBG_BATMAN, bat_priv, |
776 | "Drop packet: OGM via unknown neighbor!\n"); | 781 | "Drop packet: OGM via unknown neighbor!\n"); |
777 | goto out_neigh; | 782 | goto out_neigh; |
@@ -789,14 +794,14 @@ void receive_bat_packet(struct ethhdr *ethhdr, | |||
789 | ((orig_node->last_real_seqno == batman_packet->seqno) && | 794 | ((orig_node->last_real_seqno == batman_packet->seqno) && |
790 | (orig_node->last_ttl - 3 <= batman_packet->ttl)))) | 795 | (orig_node->last_ttl - 3 <= batman_packet->ttl)))) |
791 | update_orig(bat_priv, orig_node, ethhdr, batman_packet, | 796 | update_orig(bat_priv, orig_node, ethhdr, batman_packet, |
792 | if_incoming, hna_buff, hna_buff_len, is_duplicate); | 797 | if_incoming, tt_buff, tt_buff_len, is_duplicate); |
793 | 798 | ||
794 | /* is single hop (direct) neighbor */ | 799 | /* is single hop (direct) neighbor */ |
795 | if (is_single_hop_neigh) { | 800 | if (is_single_hop_neigh) { |
796 | 801 | ||
797 | /* mark direct link on incoming interface */ | 802 | /* mark direct link on incoming interface */ |
798 | schedule_forward_packet(orig_node, ethhdr, batman_packet, | 803 | schedule_forward_packet(orig_node, ethhdr, batman_packet, |
799 | 1, hna_buff_len, if_incoming); | 804 | 1, tt_buff_len, if_incoming); |
800 | 805 | ||
801 | bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: " | 806 | bat_dbg(DBG_BATMAN, bat_priv, "Forwarding packet: " |
802 | "rebroadcast neighbor packet with direct link flag\n"); | 807 | "rebroadcast neighbor packet with direct link flag\n"); |
@@ -819,12 +824,19 @@ void receive_bat_packet(struct ethhdr *ethhdr, | |||
819 | bat_dbg(DBG_BATMAN, bat_priv, | 824 | bat_dbg(DBG_BATMAN, bat_priv, |
820 | "Forwarding packet: rebroadcast originator packet\n"); | 825 | "Forwarding packet: rebroadcast originator packet\n"); |
821 | schedule_forward_packet(orig_node, ethhdr, batman_packet, | 826 | schedule_forward_packet(orig_node, ethhdr, batman_packet, |
822 | 0, hna_buff_len, if_incoming); | 827 | 0, tt_buff_len, if_incoming); |
823 | 828 | ||
824 | out_neigh: | 829 | out_neigh: |
825 | if ((orig_neigh_node) && (!is_single_hop_neigh)) | 830 | if ((orig_neigh_node) && (!is_single_hop_neigh)) |
826 | orig_node_free_ref(orig_neigh_node); | 831 | orig_node_free_ref(orig_neigh_node); |
827 | out: | 832 | out: |
833 | if (router) | ||
834 | neigh_node_free_ref(router); | ||
835 | if (router_router) | ||
836 | neigh_node_free_ref(router_router); | ||
837 | if (orig_neigh_router) | ||
838 | neigh_node_free_ref(orig_neigh_router); | ||
839 | |||
828 | orig_node_free_ref(orig_node); | 840 | orig_node_free_ref(orig_node); |
829 | } | 841 | } |
830 | 842 | ||
@@ -868,8 +880,9 @@ int recv_bat_packet(struct sk_buff *skb, struct hard_iface *hard_iface) | |||
868 | static int recv_my_icmp_packet(struct bat_priv *bat_priv, | 880 | static int recv_my_icmp_packet(struct bat_priv *bat_priv, |
869 | struct sk_buff *skb, size_t icmp_len) | 881 | struct sk_buff *skb, size_t icmp_len) |
870 | { | 882 | { |
883 | struct hard_iface *primary_if = NULL; | ||
871 | struct orig_node *orig_node = NULL; | 884 | struct orig_node *orig_node = NULL; |
872 | struct neigh_node *neigh_node = NULL; | 885 | struct neigh_node *router = NULL; |
873 | struct icmp_packet_rr *icmp_packet; | 886 | struct icmp_packet_rr *icmp_packet; |
874 | int ret = NET_RX_DROP; | 887 | int ret = NET_RX_DROP; |
875 | 888 | ||
@@ -881,28 +894,19 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv, | |||
881 | goto out; | 894 | goto out; |
882 | } | 895 | } |
883 | 896 | ||
884 | if (!bat_priv->primary_if) | 897 | primary_if = primary_if_get_selected(bat_priv); |
898 | if (!primary_if) | ||
885 | goto out; | 899 | goto out; |
886 | 900 | ||
887 | /* answer echo request (ping) */ | 901 | /* answer echo request (ping) */ |
888 | /* get routing information */ | 902 | /* get routing information */ |
889 | rcu_read_lock(); | ||
890 | orig_node = orig_hash_find(bat_priv, icmp_packet->orig); | 903 | orig_node = orig_hash_find(bat_priv, icmp_packet->orig); |
891 | |||
892 | if (!orig_node) | 904 | if (!orig_node) |
893 | goto unlock; | 905 | goto out; |
894 | |||
895 | neigh_node = orig_node->router; | ||
896 | |||
897 | if (!neigh_node) | ||
898 | goto unlock; | ||
899 | |||
900 | if (!atomic_inc_not_zero(&neigh_node->refcount)) { | ||
901 | neigh_node = NULL; | ||
902 | goto unlock; | ||
903 | } | ||
904 | 906 | ||
905 | rcu_read_unlock(); | 907 | router = orig_node_get_router(orig_node); |
908 | if (!router) | ||
909 | goto out; | ||
906 | 910 | ||
907 | /* create a copy of the skb, if needed, to modify it. */ | 911 | /* create a copy of the skb, if needed, to modify it. */ |
908 | if (skb_cow(skb, sizeof(struct ethhdr)) < 0) | 912 | if (skb_cow(skb, sizeof(struct ethhdr)) < 0) |
@@ -911,20 +915,18 @@ static int recv_my_icmp_packet(struct bat_priv *bat_priv, | |||
911 | icmp_packet = (struct icmp_packet_rr *)skb->data; | 915 | icmp_packet = (struct icmp_packet_rr *)skb->data; |
912 | 916 | ||
913 | memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); | 917 | memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); |
914 | memcpy(icmp_packet->orig, | 918 | memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, ETH_ALEN); |
915 | bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); | ||
916 | icmp_packet->msg_type = ECHO_REPLY; | 919 | icmp_packet->msg_type = ECHO_REPLY; |
917 | icmp_packet->ttl = TTL; | 920 | icmp_packet->ttl = TTL; |
918 | 921 | ||
919 | send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); | 922 | send_skb_packet(skb, router->if_incoming, router->addr); |
920 | ret = NET_RX_SUCCESS; | 923 | ret = NET_RX_SUCCESS; |
921 | goto out; | ||
922 | 924 | ||
923 | unlock: | ||
924 | rcu_read_unlock(); | ||
925 | out: | 925 | out: |
926 | if (neigh_node) | 926 | if (primary_if) |
927 | neigh_node_free_ref(neigh_node); | 927 | hardif_free_ref(primary_if); |
928 | if (router) | ||
929 | neigh_node_free_ref(router); | ||
928 | if (orig_node) | 930 | if (orig_node) |
929 | orig_node_free_ref(orig_node); | 931 | orig_node_free_ref(orig_node); |
930 | return ret; | 932 | return ret; |
@@ -933,8 +935,9 @@ out: | |||
933 | static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, | 935 | static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, |
934 | struct sk_buff *skb) | 936 | struct sk_buff *skb) |
935 | { | 937 | { |
938 | struct hard_iface *primary_if = NULL; | ||
936 | struct orig_node *orig_node = NULL; | 939 | struct orig_node *orig_node = NULL; |
937 | struct neigh_node *neigh_node = NULL; | 940 | struct neigh_node *router = NULL; |
938 | struct icmp_packet *icmp_packet; | 941 | struct icmp_packet *icmp_packet; |
939 | int ret = NET_RX_DROP; | 942 | int ret = NET_RX_DROP; |
940 | 943 | ||
@@ -948,27 +951,18 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, | |||
948 | goto out; | 951 | goto out; |
949 | } | 952 | } |
950 | 953 | ||
951 | if (!bat_priv->primary_if) | 954 | primary_if = primary_if_get_selected(bat_priv); |
955 | if (!primary_if) | ||
952 | goto out; | 956 | goto out; |
953 | 957 | ||
954 | /* get routing information */ | 958 | /* get routing information */ |
955 | rcu_read_lock(); | ||
956 | orig_node = orig_hash_find(bat_priv, icmp_packet->orig); | 959 | orig_node = orig_hash_find(bat_priv, icmp_packet->orig); |
957 | |||
958 | if (!orig_node) | 960 | if (!orig_node) |
959 | goto unlock; | 961 | goto out; |
960 | |||
961 | neigh_node = orig_node->router; | ||
962 | |||
963 | if (!neigh_node) | ||
964 | goto unlock; | ||
965 | |||
966 | if (!atomic_inc_not_zero(&neigh_node->refcount)) { | ||
967 | neigh_node = NULL; | ||
968 | goto unlock; | ||
969 | } | ||
970 | 962 | ||
971 | rcu_read_unlock(); | 963 | router = orig_node_get_router(orig_node); |
964 | if (!router) | ||
965 | goto out; | ||
972 | 966 | ||
973 | /* create a copy of the skb, if needed, to modify it. */ | 967 | /* create a copy of the skb, if needed, to modify it. */ |
974 | if (skb_cow(skb, sizeof(struct ethhdr)) < 0) | 968 | if (skb_cow(skb, sizeof(struct ethhdr)) < 0) |
@@ -977,20 +971,18 @@ static int recv_icmp_ttl_exceeded(struct bat_priv *bat_priv, | |||
977 | icmp_packet = (struct icmp_packet *)skb->data; | 971 | icmp_packet = (struct icmp_packet *)skb->data; |
978 | 972 | ||
979 | memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); | 973 | memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); |
980 | memcpy(icmp_packet->orig, | 974 | memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, ETH_ALEN); |
981 | bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); | ||
982 | icmp_packet->msg_type = TTL_EXCEEDED; | 975 | icmp_packet->msg_type = TTL_EXCEEDED; |
983 | icmp_packet->ttl = TTL; | 976 | icmp_packet->ttl = TTL; |
984 | 977 | ||
985 | send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); | 978 | send_skb_packet(skb, router->if_incoming, router->addr); |
986 | ret = NET_RX_SUCCESS; | 979 | ret = NET_RX_SUCCESS; |
987 | goto out; | ||
988 | 980 | ||
989 | unlock: | ||
990 | rcu_read_unlock(); | ||
991 | out: | 981 | out: |
992 | if (neigh_node) | 982 | if (primary_if) |
993 | neigh_node_free_ref(neigh_node); | 983 | hardif_free_ref(primary_if); |
984 | if (router) | ||
985 | neigh_node_free_ref(router); | ||
994 | if (orig_node) | 986 | if (orig_node) |
995 | orig_node_free_ref(orig_node); | 987 | orig_node_free_ref(orig_node); |
996 | return ret; | 988 | return ret; |
@@ -1003,7 +995,7 @@ int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if) | |||
1003 | struct icmp_packet_rr *icmp_packet; | 995 | struct icmp_packet_rr *icmp_packet; |
1004 | struct ethhdr *ethhdr; | 996 | struct ethhdr *ethhdr; |
1005 | struct orig_node *orig_node = NULL; | 997 | struct orig_node *orig_node = NULL; |
1006 | struct neigh_node *neigh_node = NULL; | 998 | struct neigh_node *router = NULL; |
1007 | int hdr_size = sizeof(struct icmp_packet); | 999 | int hdr_size = sizeof(struct icmp_packet); |
1008 | int ret = NET_RX_DROP; | 1000 | int ret = NET_RX_DROP; |
1009 | 1001 | ||
@@ -1050,23 +1042,13 @@ int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if) | |||
1050 | return recv_icmp_ttl_exceeded(bat_priv, skb); | 1042 | return recv_icmp_ttl_exceeded(bat_priv, skb); |
1051 | 1043 | ||
1052 | /* get routing information */ | 1044 | /* get routing information */ |
1053 | rcu_read_lock(); | ||
1054 | orig_node = orig_hash_find(bat_priv, icmp_packet->dst); | 1045 | orig_node = orig_hash_find(bat_priv, icmp_packet->dst); |
1055 | |||
1056 | if (!orig_node) | 1046 | if (!orig_node) |
1057 | goto unlock; | 1047 | goto out; |
1058 | |||
1059 | neigh_node = orig_node->router; | ||
1060 | |||
1061 | if (!neigh_node) | ||
1062 | goto unlock; | ||
1063 | |||
1064 | if (!atomic_inc_not_zero(&neigh_node->refcount)) { | ||
1065 | neigh_node = NULL; | ||
1066 | goto unlock; | ||
1067 | } | ||
1068 | 1048 | ||
1069 | rcu_read_unlock(); | 1049 | router = orig_node_get_router(orig_node); |
1050 | if (!router) | ||
1051 | goto out; | ||
1070 | 1052 | ||
1071 | /* create a copy of the skb, if needed, to modify it. */ | 1053 | /* create a copy of the skb, if needed, to modify it. */ |
1072 | if (skb_cow(skb, sizeof(struct ethhdr)) < 0) | 1054 | if (skb_cow(skb, sizeof(struct ethhdr)) < 0) |
@@ -1078,20 +1060,117 @@ int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if) | |||
1078 | icmp_packet->ttl--; | 1060 | icmp_packet->ttl--; |
1079 | 1061 | ||
1080 | /* route it */ | 1062 | /* route it */ |
1081 | send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); | 1063 | send_skb_packet(skb, router->if_incoming, router->addr); |
1082 | ret = NET_RX_SUCCESS; | 1064 | ret = NET_RX_SUCCESS; |
1083 | goto out; | ||
1084 | 1065 | ||
1085 | unlock: | ||
1086 | rcu_read_unlock(); | ||
1087 | out: | 1066 | out: |
1088 | if (neigh_node) | 1067 | if (router) |
1089 | neigh_node_free_ref(neigh_node); | 1068 | neigh_node_free_ref(router); |
1090 | if (orig_node) | 1069 | if (orig_node) |
1091 | orig_node_free_ref(orig_node); | 1070 | orig_node_free_ref(orig_node); |
1092 | return ret; | 1071 | return ret; |
1093 | } | 1072 | } |
1094 | 1073 | ||
1074 | /* In the bonding case, send the packets in a round | ||
1075 | * robin fashion over the remaining interfaces. | ||
1076 | * | ||
1077 | * This method rotates the bonding list and increases the | ||
1078 | * returned router's refcount. */ | ||
1079 | static struct neigh_node *find_bond_router(struct orig_node *primary_orig, | ||
1080 | struct hard_iface *recv_if) | ||
1081 | { | ||
1082 | struct neigh_node *tmp_neigh_node; | ||
1083 | struct neigh_node *router = NULL, *first_candidate = NULL; | ||
1084 | |||
1085 | rcu_read_lock(); | ||
1086 | list_for_each_entry_rcu(tmp_neigh_node, &primary_orig->bond_list, | ||
1087 | bonding_list) { | ||
1088 | if (!first_candidate) | ||
1089 | first_candidate = tmp_neigh_node; | ||
1090 | |||
1091 | /* recv_if == NULL on the first node. */ | ||
1092 | if (tmp_neigh_node->if_incoming == recv_if) | ||
1093 | continue; | ||
1094 | |||
1095 | if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) | ||
1096 | continue; | ||
1097 | |||
1098 | router = tmp_neigh_node; | ||
1099 | break; | ||
1100 | } | ||
1101 | |||
1102 | /* use the first candidate if nothing was found. */ | ||
1103 | if (!router && first_candidate && | ||
1104 | atomic_inc_not_zero(&first_candidate->refcount)) | ||
1105 | router = first_candidate; | ||
1106 | |||
1107 | if (!router) | ||
1108 | goto out; | ||
1109 | |||
1110 | /* selected should point to the next element | ||
1111 | * after the current router */ | ||
1112 | spin_lock_bh(&primary_orig->neigh_list_lock); | ||
1113 | /* this is a list_move(), which unfortunately | ||
1114 | * does not exist as rcu version */ | ||
1115 | list_del_rcu(&primary_orig->bond_list); | ||
1116 | list_add_rcu(&primary_orig->bond_list, | ||
1117 | &router->bonding_list); | ||
1118 | spin_unlock_bh(&primary_orig->neigh_list_lock); | ||
1119 | |||
1120 | out: | ||
1121 | rcu_read_unlock(); | ||
1122 | return router; | ||
1123 | } | ||
1124 | |||
1125 | /* Interface Alternating: Use the best of the | ||
1126 | * remaining candidates which are not using | ||
1127 | * this interface. | ||
1128 | * | ||
1129 | * Increases the returned router's refcount */ | ||
1130 | static struct neigh_node *find_ifalter_router(struct orig_node *primary_orig, | ||
1131 | struct hard_iface *recv_if) | ||
1132 | { | ||
1133 | struct neigh_node *tmp_neigh_node; | ||
1134 | struct neigh_node *router = NULL, *first_candidate = NULL; | ||
1135 | |||
1136 | rcu_read_lock(); | ||
1137 | list_for_each_entry_rcu(tmp_neigh_node, &primary_orig->bond_list, | ||
1138 | bonding_list) { | ||
1139 | if (!first_candidate) | ||
1140 | first_candidate = tmp_neigh_node; | ||
1141 | |||
1142 | /* recv_if == NULL on the first node. */ | ||
1143 | if (tmp_neigh_node->if_incoming == recv_if) | ||
1144 | continue; | ||
1145 | |||
1146 | if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) | ||
1147 | continue; | ||
1148 | |||
1149 | /* if we don't have a router yet | ||
1150 | * or this one is better, choose it. */ | ||
1151 | if ((!router) || | ||
1152 | (tmp_neigh_node->tq_avg > router->tq_avg)) { | ||
1153 | /* decrement refcount of | ||
1154 | * previously selected router */ | ||
1155 | if (router) | ||
1156 | neigh_node_free_ref(router); | ||
1157 | |||
1158 | router = tmp_neigh_node; | ||
1159 | atomic_inc_not_zero(&router->refcount); | ||
1160 | } | ||
1161 | |||
1162 | neigh_node_free_ref(tmp_neigh_node); | ||
1163 | } | ||
1164 | |||
1165 | /* use the first candidate if nothing was found. */ | ||
1166 | if (!router && first_candidate && | ||
1167 | atomic_inc_not_zero(&first_candidate->refcount)) | ||
1168 | router = first_candidate; | ||
1169 | |||
1170 | rcu_read_unlock(); | ||
1171 | return router; | ||
1172 | } | ||
1173 | |||
1095 | /* find a suitable router for this originator, and use | 1174 | /* find a suitable router for this originator, and use |
1096 | * bonding if possible. increases the found neighbors | 1175 | * bonding if possible. increases the found neighbors |
1097 | * refcount.*/ | 1176 | * refcount.*/ |
@@ -1101,15 +1180,16 @@ struct neigh_node *find_router(struct bat_priv *bat_priv, | |||
1101 | { | 1180 | { |
1102 | struct orig_node *primary_orig_node; | 1181 | struct orig_node *primary_orig_node; |
1103 | struct orig_node *router_orig; | 1182 | struct orig_node *router_orig; |
1104 | struct neigh_node *router, *first_candidate, *tmp_neigh_node; | 1183 | struct neigh_node *router; |
1105 | static uint8_t zero_mac[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; | 1184 | static uint8_t zero_mac[ETH_ALEN] = {0, 0, 0, 0, 0, 0}; |
1106 | int bonding_enabled; | 1185 | int bonding_enabled; |
1107 | 1186 | ||
1108 | if (!orig_node) | 1187 | if (!orig_node) |
1109 | return NULL; | 1188 | return NULL; |
1110 | 1189 | ||
1111 | if (!orig_node->router) | 1190 | router = orig_node_get_router(orig_node); |
1112 | return NULL; | 1191 | if (!router) |
1192 | goto err; | ||
1113 | 1193 | ||
1114 | /* without bonding, the first node should | 1194 | /* without bonding, the first node should |
1115 | * always choose the default router. */ | 1195 | * always choose the default router. */ |
@@ -1117,12 +1197,9 @@ struct neigh_node *find_router(struct bat_priv *bat_priv, | |||
1117 | 1197 | ||
1118 | rcu_read_lock(); | 1198 | rcu_read_lock(); |
1119 | /* select default router to output */ | 1199 | /* select default router to output */ |
1120 | router = orig_node->router; | 1200 | router_orig = router->orig_node; |
1121 | router_orig = orig_node->router->orig_node; | 1201 | if (!router_orig) |
1122 | if (!router_orig || !atomic_inc_not_zero(&router->refcount)) { | 1202 | goto err_unlock; |
1123 | rcu_read_unlock(); | ||
1124 | return NULL; | ||
1125 | } | ||
1126 | 1203 | ||
1127 | if ((!recv_if) && (!bonding_enabled)) | 1204 | if ((!recv_if) && (!bonding_enabled)) |
1128 | goto return_router; | 1205 | goto return_router; |
@@ -1151,91 +1228,26 @@ struct neigh_node *find_router(struct bat_priv *bat_priv, | |||
1151 | if (atomic_read(&primary_orig_node->bond_candidates) < 2) | 1228 | if (atomic_read(&primary_orig_node->bond_candidates) < 2) |
1152 | goto return_router; | 1229 | goto return_router; |
1153 | 1230 | ||
1154 | |||
1155 | /* all nodes between should choose a candidate which | 1231 | /* all nodes between should choose a candidate which |
1156 | * is is not on the interface where the packet came | 1232 | * is is not on the interface where the packet came |
1157 | * in. */ | 1233 | * in. */ |
1158 | 1234 | ||
1159 | neigh_node_free_ref(router); | 1235 | neigh_node_free_ref(router); |
1160 | first_candidate = NULL; | ||
1161 | router = NULL; | ||
1162 | |||
1163 | if (bonding_enabled) { | ||
1164 | /* in the bonding case, send the packets in a round | ||
1165 | * robin fashion over the remaining interfaces. */ | ||
1166 | |||
1167 | list_for_each_entry_rcu(tmp_neigh_node, | ||
1168 | &primary_orig_node->bond_list, bonding_list) { | ||
1169 | if (!first_candidate) | ||
1170 | first_candidate = tmp_neigh_node; | ||
1171 | /* recv_if == NULL on the first node. */ | ||
1172 | if (tmp_neigh_node->if_incoming != recv_if && | ||
1173 | atomic_inc_not_zero(&tmp_neigh_node->refcount)) { | ||
1174 | router = tmp_neigh_node; | ||
1175 | break; | ||
1176 | } | ||
1177 | } | ||
1178 | |||
1179 | /* use the first candidate if nothing was found. */ | ||
1180 | if (!router && first_candidate && | ||
1181 | atomic_inc_not_zero(&first_candidate->refcount)) | ||
1182 | router = first_candidate; | ||
1183 | 1236 | ||
1184 | if (!router) { | 1237 | if (bonding_enabled) |
1185 | rcu_read_unlock(); | 1238 | router = find_bond_router(primary_orig_node, recv_if); |
1186 | return NULL; | 1239 | else |
1187 | } | 1240 | router = find_ifalter_router(primary_orig_node, recv_if); |
1188 | |||
1189 | /* selected should point to the next element | ||
1190 | * after the current router */ | ||
1191 | spin_lock_bh(&primary_orig_node->neigh_list_lock); | ||
1192 | /* this is a list_move(), which unfortunately | ||
1193 | * does not exist as rcu version */ | ||
1194 | list_del_rcu(&primary_orig_node->bond_list); | ||
1195 | list_add_rcu(&primary_orig_node->bond_list, | ||
1196 | &router->bonding_list); | ||
1197 | spin_unlock_bh(&primary_orig_node->neigh_list_lock); | ||
1198 | |||
1199 | } else { | ||
1200 | /* if bonding is disabled, use the best of the | ||
1201 | * remaining candidates which are not using | ||
1202 | * this interface. */ | ||
1203 | list_for_each_entry_rcu(tmp_neigh_node, | ||
1204 | &primary_orig_node->bond_list, bonding_list) { | ||
1205 | if (!first_candidate) | ||
1206 | first_candidate = tmp_neigh_node; | ||
1207 | |||
1208 | /* recv_if == NULL on the first node. */ | ||
1209 | if (tmp_neigh_node->if_incoming == recv_if) | ||
1210 | continue; | ||
1211 | |||
1212 | if (!atomic_inc_not_zero(&tmp_neigh_node->refcount)) | ||
1213 | continue; | ||
1214 | |||
1215 | /* if we don't have a router yet | ||
1216 | * or this one is better, choose it. */ | ||
1217 | if ((!router) || | ||
1218 | (tmp_neigh_node->tq_avg > router->tq_avg)) { | ||
1219 | /* decrement refcount of | ||
1220 | * previously selected router */ | ||
1221 | if (router) | ||
1222 | neigh_node_free_ref(router); | ||
1223 | |||
1224 | router = tmp_neigh_node; | ||
1225 | atomic_inc_not_zero(&router->refcount); | ||
1226 | } | ||
1227 | |||
1228 | neigh_node_free_ref(tmp_neigh_node); | ||
1229 | } | ||
1230 | 1241 | ||
1231 | /* use the first candidate if nothing was found. */ | ||
1232 | if (!router && first_candidate && | ||
1233 | atomic_inc_not_zero(&first_candidate->refcount)) | ||
1234 | router = first_candidate; | ||
1235 | } | ||
1236 | return_router: | 1242 | return_router: |
1237 | rcu_read_unlock(); | 1243 | rcu_read_unlock(); |
1238 | return router; | 1244 | return router; |
1245 | err_unlock: | ||
1246 | rcu_read_unlock(); | ||
1247 | err: | ||
1248 | if (router) | ||
1249 | neigh_node_free_ref(router); | ||
1250 | return NULL; | ||
1239 | } | 1251 | } |
1240 | 1252 | ||
1241 | static int check_unicast_packet(struct sk_buff *skb, int hdr_size) | 1253 | static int check_unicast_packet(struct sk_buff *skb, int hdr_size) |
@@ -1284,13 +1296,10 @@ int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if) | |||
1284 | } | 1296 | } |
1285 | 1297 | ||
1286 | /* get routing information */ | 1298 | /* get routing information */ |
1287 | rcu_read_lock(); | ||
1288 | orig_node = orig_hash_find(bat_priv, unicast_packet->dest); | 1299 | orig_node = orig_hash_find(bat_priv, unicast_packet->dest); |
1289 | 1300 | ||
1290 | if (!orig_node) | 1301 | if (!orig_node) |
1291 | goto unlock; | 1302 | goto out; |
1292 | |||
1293 | rcu_read_unlock(); | ||
1294 | 1303 | ||
1295 | /* find_router() increases neigh_nodes refcount if found. */ | 1304 | /* find_router() increases neigh_nodes refcount if found. */ |
1296 | neigh_node = find_router(bat_priv, orig_node, recv_if); | 1305 | neigh_node = find_router(bat_priv, orig_node, recv_if); |
@@ -1336,10 +1345,7 @@ int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if) | |||
1336 | /* route it */ | 1345 | /* route it */ |
1337 | send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); | 1346 | send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); |
1338 | ret = NET_RX_SUCCESS; | 1347 | ret = NET_RX_SUCCESS; |
1339 | goto out; | ||
1340 | 1348 | ||
1341 | unlock: | ||
1342 | rcu_read_unlock(); | ||
1343 | out: | 1349 | out: |
1344 | if (neigh_node) | 1350 | if (neigh_node) |
1345 | neigh_node_free_ref(neigh_node); | 1351 | neigh_node_free_ref(neigh_node); |
@@ -1438,13 +1444,10 @@ int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if) | |||
1438 | if (bcast_packet->ttl < 2) | 1444 | if (bcast_packet->ttl < 2) |
1439 | goto out; | 1445 | goto out; |
1440 | 1446 | ||
1441 | rcu_read_lock(); | ||
1442 | orig_node = orig_hash_find(bat_priv, bcast_packet->orig); | 1447 | orig_node = orig_hash_find(bat_priv, bcast_packet->orig); |
1443 | 1448 | ||
1444 | if (!orig_node) | 1449 | if (!orig_node) |
1445 | goto rcu_unlock; | 1450 | goto out; |
1446 | |||
1447 | rcu_read_unlock(); | ||
1448 | 1451 | ||
1449 | spin_lock_bh(&orig_node->bcast_seqno_lock); | 1452 | spin_lock_bh(&orig_node->bcast_seqno_lock); |
1450 | 1453 | ||
@@ -1475,9 +1478,6 @@ int recv_bcast_packet(struct sk_buff *skb, struct hard_iface *recv_if) | |||
1475 | ret = NET_RX_SUCCESS; | 1478 | ret = NET_RX_SUCCESS; |
1476 | goto out; | 1479 | goto out; |
1477 | 1480 | ||
1478 | rcu_unlock: | ||
1479 | rcu_read_unlock(); | ||
1480 | goto out; | ||
1481 | spin_unlock: | 1481 | spin_unlock: |
1482 | spin_unlock_bh(&orig_node->bcast_seqno_lock); | 1482 | spin_unlock_bh(&orig_node->bcast_seqno_lock); |
1483 | out: | 1483 | out: |
diff --git a/net/batman-adv/routing.h b/net/batman-adv/routing.h index b5a064c88a4f..870f29842b28 100644 --- a/net/batman-adv/routing.h +++ b/net/batman-adv/routing.h | |||
@@ -25,11 +25,11 @@ | |||
25 | void slide_own_bcast_window(struct hard_iface *hard_iface); | 25 | void slide_own_bcast_window(struct hard_iface *hard_iface); |
26 | void receive_bat_packet(struct ethhdr *ethhdr, | 26 | void receive_bat_packet(struct ethhdr *ethhdr, |
27 | struct batman_packet *batman_packet, | 27 | struct batman_packet *batman_packet, |
28 | unsigned char *hna_buff, int hna_buff_len, | 28 | unsigned char *tt_buff, int tt_buff_len, |
29 | struct hard_iface *if_incoming); | 29 | struct hard_iface *if_incoming); |
30 | void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, | 30 | void update_routes(struct bat_priv *bat_priv, struct orig_node *orig_node, |
31 | struct neigh_node *neigh_node, unsigned char *hna_buff, | 31 | struct neigh_node *neigh_node, unsigned char *tt_buff, |
32 | int hna_buff_len); | 32 | int tt_buff_len); |
33 | int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if); | 33 | int route_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if); |
34 | int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if); | 34 | int recv_icmp_packet(struct sk_buff *skb, struct hard_iface *recv_if); |
35 | int recv_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if); | 35 | int recv_unicast_packet(struct sk_buff *skb, struct hard_iface *recv_if); |
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index d49e54d932af..33779278f1b2 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c | |||
@@ -121,7 +121,7 @@ static void send_packet_to_if(struct forw_packet *forw_packet, | |||
121 | /* adjust all flags and log packets */ | 121 | /* adjust all flags and log packets */ |
122 | while (aggregated_packet(buff_pos, | 122 | while (aggregated_packet(buff_pos, |
123 | forw_packet->packet_len, | 123 | forw_packet->packet_len, |
124 | batman_packet->num_hna)) { | 124 | batman_packet->num_tt)) { |
125 | 125 | ||
126 | /* we might have aggregated direct link packets with an | 126 | /* we might have aggregated direct link packets with an |
127 | * ordinary base packet */ | 127 | * ordinary base packet */ |
@@ -146,7 +146,7 @@ static void send_packet_to_if(struct forw_packet *forw_packet, | |||
146 | hard_iface->net_dev->dev_addr); | 146 | hard_iface->net_dev->dev_addr); |
147 | 147 | ||
148 | buff_pos += sizeof(struct batman_packet) + | 148 | buff_pos += sizeof(struct batman_packet) + |
149 | (batman_packet->num_hna * ETH_ALEN); | 149 | (batman_packet->num_tt * ETH_ALEN); |
150 | packet_num++; | 150 | packet_num++; |
151 | batman_packet = (struct batman_packet *) | 151 | batman_packet = (struct batman_packet *) |
152 | (forw_packet->skb->data + buff_pos); | 152 | (forw_packet->skb->data + buff_pos); |
@@ -222,7 +222,7 @@ static void rebuild_batman_packet(struct bat_priv *bat_priv, | |||
222 | struct batman_packet *batman_packet; | 222 | struct batman_packet *batman_packet; |
223 | 223 | ||
224 | new_len = sizeof(struct batman_packet) + | 224 | new_len = sizeof(struct batman_packet) + |
225 | (bat_priv->num_local_hna * ETH_ALEN); | 225 | (bat_priv->num_local_tt * ETH_ALEN); |
226 | new_buff = kmalloc(new_len, GFP_ATOMIC); | 226 | new_buff = kmalloc(new_len, GFP_ATOMIC); |
227 | 227 | ||
228 | /* keep old buffer if kmalloc should fail */ | 228 | /* keep old buffer if kmalloc should fail */ |
@@ -231,7 +231,7 @@ static void rebuild_batman_packet(struct bat_priv *bat_priv, | |||
231 | sizeof(struct batman_packet)); | 231 | sizeof(struct batman_packet)); |
232 | batman_packet = (struct batman_packet *)new_buff; | 232 | batman_packet = (struct batman_packet *)new_buff; |
233 | 233 | ||
234 | batman_packet->num_hna = hna_local_fill_buffer(bat_priv, | 234 | batman_packet->num_tt = tt_local_fill_buffer(bat_priv, |
235 | new_buff + sizeof(struct batman_packet), | 235 | new_buff + sizeof(struct batman_packet), |
236 | new_len - sizeof(struct batman_packet)); | 236 | new_len - sizeof(struct batman_packet)); |
237 | 237 | ||
@@ -244,6 +244,7 @@ static void rebuild_batman_packet(struct bat_priv *bat_priv, | |||
244 | void schedule_own_packet(struct hard_iface *hard_iface) | 244 | void schedule_own_packet(struct hard_iface *hard_iface) |
245 | { | 245 | { |
246 | struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface); | 246 | struct bat_priv *bat_priv = netdev_priv(hard_iface->soft_iface); |
247 | struct hard_iface *primary_if; | ||
247 | unsigned long send_time; | 248 | unsigned long send_time; |
248 | struct batman_packet *batman_packet; | 249 | struct batman_packet *batman_packet; |
249 | int vis_server; | 250 | int vis_server; |
@@ -253,6 +254,7 @@ void schedule_own_packet(struct hard_iface *hard_iface) | |||
253 | return; | 254 | return; |
254 | 255 | ||
255 | vis_server = atomic_read(&bat_priv->vis_mode); | 256 | vis_server = atomic_read(&bat_priv->vis_mode); |
257 | primary_if = primary_if_get_selected(bat_priv); | ||
256 | 258 | ||
257 | /** | 259 | /** |
258 | * the interface gets activated here to avoid race conditions between | 260 | * the interface gets activated here to avoid race conditions between |
@@ -264,9 +266,9 @@ void schedule_own_packet(struct hard_iface *hard_iface) | |||
264 | if (hard_iface->if_status == IF_TO_BE_ACTIVATED) | 266 | if (hard_iface->if_status == IF_TO_BE_ACTIVATED) |
265 | hard_iface->if_status = IF_ACTIVE; | 267 | hard_iface->if_status = IF_ACTIVE; |
266 | 268 | ||
267 | /* if local hna has changed and interface is a primary interface */ | 269 | /* if local tt has changed and interface is a primary interface */ |
268 | if ((atomic_read(&bat_priv->hna_local_changed)) && | 270 | if ((atomic_read(&bat_priv->tt_local_changed)) && |
269 | (hard_iface == bat_priv->primary_if)) | 271 | (hard_iface == primary_if)) |
270 | rebuild_batman_packet(bat_priv, hard_iface); | 272 | rebuild_batman_packet(bat_priv, hard_iface); |
271 | 273 | ||
272 | /** | 274 | /** |
@@ -284,7 +286,7 @@ void schedule_own_packet(struct hard_iface *hard_iface) | |||
284 | else | 286 | else |
285 | batman_packet->flags &= ~VIS_SERVER; | 287 | batman_packet->flags &= ~VIS_SERVER; |
286 | 288 | ||
287 | if ((hard_iface == bat_priv->primary_if) && | 289 | if ((hard_iface == primary_if) && |
288 | (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER)) | 290 | (atomic_read(&bat_priv->gw_mode) == GW_MODE_SERVER)) |
289 | batman_packet->gw_flags = | 291 | batman_packet->gw_flags = |
290 | (uint8_t)atomic_read(&bat_priv->gw_bandwidth); | 292 | (uint8_t)atomic_read(&bat_priv->gw_bandwidth); |
@@ -299,15 +301,19 @@ void schedule_own_packet(struct hard_iface *hard_iface) | |||
299 | hard_iface->packet_buff, | 301 | hard_iface->packet_buff, |
300 | hard_iface->packet_len, | 302 | hard_iface->packet_len, |
301 | hard_iface, 1, send_time); | 303 | hard_iface, 1, send_time); |
304 | |||
305 | if (primary_if) | ||
306 | hardif_free_ref(primary_if); | ||
302 | } | 307 | } |
303 | 308 | ||
304 | void schedule_forward_packet(struct orig_node *orig_node, | 309 | void schedule_forward_packet(struct orig_node *orig_node, |
305 | struct ethhdr *ethhdr, | 310 | struct ethhdr *ethhdr, |
306 | struct batman_packet *batman_packet, | 311 | struct batman_packet *batman_packet, |
307 | uint8_t directlink, int hna_buff_len, | 312 | uint8_t directlink, int tt_buff_len, |
308 | struct hard_iface *if_incoming) | 313 | struct hard_iface *if_incoming) |
309 | { | 314 | { |
310 | struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); | 315 | struct bat_priv *bat_priv = netdev_priv(if_incoming->soft_iface); |
316 | struct neigh_node *router; | ||
311 | unsigned char in_tq, in_ttl, tq_avg = 0; | 317 | unsigned char in_tq, in_ttl, tq_avg = 0; |
312 | unsigned long send_time; | 318 | unsigned long send_time; |
313 | 319 | ||
@@ -316,6 +322,8 @@ void schedule_forward_packet(struct orig_node *orig_node, | |||
316 | return; | 322 | return; |
317 | } | 323 | } |
318 | 324 | ||
325 | router = orig_node_get_router(orig_node); | ||
326 | |||
319 | in_tq = batman_packet->tq; | 327 | in_tq = batman_packet->tq; |
320 | in_ttl = batman_packet->ttl; | 328 | in_ttl = batman_packet->ttl; |
321 | 329 | ||
@@ -324,20 +332,22 @@ void schedule_forward_packet(struct orig_node *orig_node, | |||
324 | 332 | ||
325 | /* rebroadcast tq of our best ranking neighbor to ensure the rebroadcast | 333 | /* rebroadcast tq of our best ranking neighbor to ensure the rebroadcast |
326 | * of our best tq value */ | 334 | * of our best tq value */ |
327 | if ((orig_node->router) && (orig_node->router->tq_avg != 0)) { | 335 | if (router && router->tq_avg != 0) { |
328 | 336 | ||
329 | /* rebroadcast ogm of best ranking neighbor as is */ | 337 | /* rebroadcast ogm of best ranking neighbor as is */ |
330 | if (!compare_eth(orig_node->router->addr, ethhdr->h_source)) { | 338 | if (!compare_eth(router->addr, ethhdr->h_source)) { |
331 | batman_packet->tq = orig_node->router->tq_avg; | 339 | batman_packet->tq = router->tq_avg; |
332 | 340 | ||
333 | if (orig_node->router->last_ttl) | 341 | if (router->last_ttl) |
334 | batman_packet->ttl = orig_node->router->last_ttl | 342 | batman_packet->ttl = router->last_ttl - 1; |
335 | - 1; | ||
336 | } | 343 | } |
337 | 344 | ||
338 | tq_avg = orig_node->router->tq_avg; | 345 | tq_avg = router->tq_avg; |
339 | } | 346 | } |
340 | 347 | ||
348 | if (router) | ||
349 | neigh_node_free_ref(router); | ||
350 | |||
341 | /* apply hop penalty */ | 351 | /* apply hop penalty */ |
342 | batman_packet->tq = hop_penalty(batman_packet->tq, bat_priv); | 352 | batman_packet->tq = hop_penalty(batman_packet->tq, bat_priv); |
343 | 353 | ||
@@ -359,7 +369,7 @@ void schedule_forward_packet(struct orig_node *orig_node, | |||
359 | send_time = forward_send_time(); | 369 | send_time = forward_send_time(); |
360 | add_bat_packet_to_list(bat_priv, | 370 | add_bat_packet_to_list(bat_priv, |
361 | (unsigned char *)batman_packet, | 371 | (unsigned char *)batman_packet, |
362 | sizeof(struct batman_packet) + hna_buff_len, | 372 | sizeof(struct batman_packet) + tt_buff_len, |
363 | if_incoming, 0, send_time); | 373 | if_incoming, 0, send_time); |
364 | } | 374 | } |
365 | 375 | ||
@@ -367,6 +377,8 @@ static void forw_packet_free(struct forw_packet *forw_packet) | |||
367 | { | 377 | { |
368 | if (forw_packet->skb) | 378 | if (forw_packet->skb) |
369 | kfree_skb(forw_packet->skb); | 379 | kfree_skb(forw_packet->skb); |
380 | if (forw_packet->if_incoming) | ||
381 | hardif_free_ref(forw_packet->if_incoming); | ||
370 | kfree(forw_packet); | 382 | kfree(forw_packet); |
371 | } | 383 | } |
372 | 384 | ||
@@ -388,7 +400,6 @@ static void _add_bcast_packet_to_list(struct bat_priv *bat_priv, | |||
388 | send_time); | 400 | send_time); |
389 | } | 401 | } |
390 | 402 | ||
391 | #define atomic_dec_not_zero(v) atomic_add_unless((v), -1, 0) | ||
392 | /* add a broadcast packet to the queue and setup timers. broadcast packets | 403 | /* add a broadcast packet to the queue and setup timers. broadcast packets |
393 | * are sent multiple times to increase probability for beeing received. | 404 | * are sent multiple times to increase probability for beeing received. |
394 | * | 405 | * |
@@ -399,6 +410,7 @@ static void _add_bcast_packet_to_list(struct bat_priv *bat_priv, | |||
399 | * skb is freed. */ | 410 | * skb is freed. */ |
400 | int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb) | 411 | int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb) |
401 | { | 412 | { |
413 | struct hard_iface *primary_if = NULL; | ||
402 | struct forw_packet *forw_packet; | 414 | struct forw_packet *forw_packet; |
403 | struct bcast_packet *bcast_packet; | 415 | struct bcast_packet *bcast_packet; |
404 | 416 | ||
@@ -407,8 +419,9 @@ int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb) | |||
407 | goto out; | 419 | goto out; |
408 | } | 420 | } |
409 | 421 | ||
410 | if (!bat_priv->primary_if) | 422 | primary_if = primary_if_get_selected(bat_priv); |
411 | goto out; | 423 | if (!primary_if) |
424 | goto out_and_inc; | ||
412 | 425 | ||
413 | forw_packet = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC); | 426 | forw_packet = kmalloc(sizeof(struct forw_packet), GFP_ATOMIC); |
414 | 427 | ||
@@ -426,7 +439,7 @@ int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb) | |||
426 | skb_reset_mac_header(skb); | 439 | skb_reset_mac_header(skb); |
427 | 440 | ||
428 | forw_packet->skb = skb; | 441 | forw_packet->skb = skb; |
429 | forw_packet->if_incoming = bat_priv->primary_if; | 442 | forw_packet->if_incoming = primary_if; |
430 | 443 | ||
431 | /* how often did we send the bcast packet ? */ | 444 | /* how often did we send the bcast packet ? */ |
432 | forw_packet->num_packets = 0; | 445 | forw_packet->num_packets = 0; |
@@ -439,6 +452,8 @@ packet_free: | |||
439 | out_and_inc: | 452 | out_and_inc: |
440 | atomic_inc(&bat_priv->bcast_queue_left); | 453 | atomic_inc(&bat_priv->bcast_queue_left); |
441 | out: | 454 | out: |
455 | if (primary_if) | ||
456 | hardif_free_ref(primary_if); | ||
442 | return NETDEV_TX_BUSY; | 457 | return NETDEV_TX_BUSY; |
443 | } | 458 | } |
444 | 459 | ||
@@ -526,6 +541,7 @@ void purge_outstanding_packets(struct bat_priv *bat_priv, | |||
526 | { | 541 | { |
527 | struct forw_packet *forw_packet; | 542 | struct forw_packet *forw_packet; |
528 | struct hlist_node *tmp_node, *safe_tmp_node; | 543 | struct hlist_node *tmp_node, *safe_tmp_node; |
544 | bool pending; | ||
529 | 545 | ||
530 | if (hard_iface) | 546 | if (hard_iface) |
531 | bat_dbg(DBG_BATMAN, bat_priv, | 547 | bat_dbg(DBG_BATMAN, bat_priv, |
@@ -554,8 +570,13 @@ void purge_outstanding_packets(struct bat_priv *bat_priv, | |||
554 | * send_outstanding_bcast_packet() will lock the list to | 570 | * send_outstanding_bcast_packet() will lock the list to |
555 | * delete the item from the list | 571 | * delete the item from the list |
556 | */ | 572 | */ |
557 | cancel_delayed_work_sync(&forw_packet->delayed_work); | 573 | pending = cancel_delayed_work_sync(&forw_packet->delayed_work); |
558 | spin_lock_bh(&bat_priv->forw_bcast_list_lock); | 574 | spin_lock_bh(&bat_priv->forw_bcast_list_lock); |
575 | |||
576 | if (pending) { | ||
577 | hlist_del(&forw_packet->list); | ||
578 | forw_packet_free(forw_packet); | ||
579 | } | ||
559 | } | 580 | } |
560 | spin_unlock_bh(&bat_priv->forw_bcast_list_lock); | 581 | spin_unlock_bh(&bat_priv->forw_bcast_list_lock); |
561 | 582 | ||
@@ -578,8 +599,13 @@ void purge_outstanding_packets(struct bat_priv *bat_priv, | |||
578 | * send_outstanding_bat_packet() will lock the list to | 599 | * send_outstanding_bat_packet() will lock the list to |
579 | * delete the item from the list | 600 | * delete the item from the list |
580 | */ | 601 | */ |
581 | cancel_delayed_work_sync(&forw_packet->delayed_work); | 602 | pending = cancel_delayed_work_sync(&forw_packet->delayed_work); |
582 | spin_lock_bh(&bat_priv->forw_bat_list_lock); | 603 | spin_lock_bh(&bat_priv->forw_bat_list_lock); |
604 | |||
605 | if (pending) { | ||
606 | hlist_del(&forw_packet->list); | ||
607 | forw_packet_free(forw_packet); | ||
608 | } | ||
583 | } | 609 | } |
584 | spin_unlock_bh(&bat_priv->forw_bat_list_lock); | 610 | spin_unlock_bh(&bat_priv->forw_bat_list_lock); |
585 | } | 611 | } |
diff --git a/net/batman-adv/send.h b/net/batman-adv/send.h index 7b2ff19c05e7..247172d71e4b 100644 --- a/net/batman-adv/send.h +++ b/net/batman-adv/send.h | |||
@@ -29,7 +29,7 @@ void schedule_own_packet(struct hard_iface *hard_iface); | |||
29 | void schedule_forward_packet(struct orig_node *orig_node, | 29 | void schedule_forward_packet(struct orig_node *orig_node, |
30 | struct ethhdr *ethhdr, | 30 | struct ethhdr *ethhdr, |
31 | struct batman_packet *batman_packet, | 31 | struct batman_packet *batman_packet, |
32 | uint8_t directlink, int hna_buff_len, | 32 | uint8_t directlink, int tt_buff_len, |
33 | struct hard_iface *if_outgoing); | 33 | struct hard_iface *if_outgoing); |
34 | int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb); | 34 | int add_bcast_packet_to_list(struct bat_priv *bat_priv, struct sk_buff *skb); |
35 | void send_outstanding_bat_packet(struct work_struct *work); | 35 | void send_outstanding_bat_packet(struct work_struct *work); |
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 9ed26140a269..c76a33eeb3f1 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c | |||
@@ -43,8 +43,6 @@ static void bat_get_drvinfo(struct net_device *dev, | |||
43 | static u32 bat_get_msglevel(struct net_device *dev); | 43 | static u32 bat_get_msglevel(struct net_device *dev); |
44 | static void bat_set_msglevel(struct net_device *dev, u32 value); | 44 | static void bat_set_msglevel(struct net_device *dev, u32 value); |
45 | static u32 bat_get_link(struct net_device *dev); | 45 | static u32 bat_get_link(struct net_device *dev); |
46 | static u32 bat_get_rx_csum(struct net_device *dev); | ||
47 | static int bat_set_rx_csum(struct net_device *dev, u32 data); | ||
48 | 46 | ||
49 | static const struct ethtool_ops bat_ethtool_ops = { | 47 | static const struct ethtool_ops bat_ethtool_ops = { |
50 | .get_settings = bat_get_settings, | 48 | .get_settings = bat_get_settings, |
@@ -52,8 +50,6 @@ static const struct ethtool_ops bat_ethtool_ops = { | |||
52 | .get_msglevel = bat_get_msglevel, | 50 | .get_msglevel = bat_get_msglevel, |
53 | .set_msglevel = bat_set_msglevel, | 51 | .set_msglevel = bat_set_msglevel, |
54 | .get_link = bat_get_link, | 52 | .get_link = bat_get_link, |
55 | .get_rx_csum = bat_get_rx_csum, | ||
56 | .set_rx_csum = bat_set_rx_csum | ||
57 | }; | 53 | }; |
58 | 54 | ||
59 | int my_skb_head_push(struct sk_buff *skb, unsigned int len) | 55 | int my_skb_head_push(struct sk_buff *skb, unsigned int len) |
@@ -90,106 +86,365 @@ static void softif_neigh_free_ref(struct softif_neigh *softif_neigh) | |||
90 | call_rcu(&softif_neigh->rcu, softif_neigh_free_rcu); | 86 | call_rcu(&softif_neigh->rcu, softif_neigh_free_rcu); |
91 | } | 87 | } |
92 | 88 | ||
93 | void softif_neigh_purge(struct bat_priv *bat_priv) | 89 | static void softif_neigh_vid_free_rcu(struct rcu_head *rcu) |
94 | { | 90 | { |
95 | struct softif_neigh *softif_neigh, *softif_neigh_tmp; | 91 | struct softif_neigh_vid *softif_neigh_vid; |
92 | struct softif_neigh *softif_neigh; | ||
96 | struct hlist_node *node, *node_tmp; | 93 | struct hlist_node *node, *node_tmp; |
94 | struct bat_priv *bat_priv; | ||
97 | 95 | ||
98 | spin_lock_bh(&bat_priv->softif_neigh_lock); | 96 | softif_neigh_vid = container_of(rcu, struct softif_neigh_vid, rcu); |
97 | bat_priv = softif_neigh_vid->bat_priv; | ||
99 | 98 | ||
99 | spin_lock_bh(&bat_priv->softif_neigh_lock); | ||
100 | hlist_for_each_entry_safe(softif_neigh, node, node_tmp, | 100 | hlist_for_each_entry_safe(softif_neigh, node, node_tmp, |
101 | &bat_priv->softif_neigh_list, list) { | 101 | &softif_neigh_vid->softif_neigh_list, list) { |
102 | hlist_del_rcu(&softif_neigh->list); | ||
103 | softif_neigh_free_ref(softif_neigh); | ||
104 | } | ||
105 | spin_unlock_bh(&bat_priv->softif_neigh_lock); | ||
102 | 106 | ||
103 | if ((!time_after(jiffies, softif_neigh->last_seen + | 107 | kfree(softif_neigh_vid); |
104 | msecs_to_jiffies(SOFTIF_NEIGH_TIMEOUT))) && | 108 | } |
105 | (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE)) | ||
106 | continue; | ||
107 | 109 | ||
108 | hlist_del_rcu(&softif_neigh->list); | 110 | static void softif_neigh_vid_free_ref(struct softif_neigh_vid *softif_neigh_vid) |
111 | { | ||
112 | if (atomic_dec_and_test(&softif_neigh_vid->refcount)) | ||
113 | call_rcu(&softif_neigh_vid->rcu, softif_neigh_vid_free_rcu); | ||
114 | } | ||
109 | 115 | ||
110 | if (bat_priv->softif_neigh == softif_neigh) { | 116 | static struct softif_neigh_vid *softif_neigh_vid_get(struct bat_priv *bat_priv, |
111 | bat_dbg(DBG_ROUTES, bat_priv, | 117 | short vid) |
112 | "Current mesh exit point '%pM' vanished " | 118 | { |
113 | "(vid: %d).\n", | 119 | struct softif_neigh_vid *softif_neigh_vid; |
114 | softif_neigh->addr, softif_neigh->vid); | 120 | struct hlist_node *node; |
115 | softif_neigh_tmp = bat_priv->softif_neigh; | ||
116 | bat_priv->softif_neigh = NULL; | ||
117 | softif_neigh_free_ref(softif_neigh_tmp); | ||
118 | } | ||
119 | 121 | ||
120 | softif_neigh_free_ref(softif_neigh); | 122 | rcu_read_lock(); |
123 | hlist_for_each_entry_rcu(softif_neigh_vid, node, | ||
124 | &bat_priv->softif_neigh_vids, list) { | ||
125 | if (softif_neigh_vid->vid != vid) | ||
126 | continue; | ||
127 | |||
128 | if (!atomic_inc_not_zero(&softif_neigh_vid->refcount)) | ||
129 | continue; | ||
130 | |||
131 | goto out; | ||
121 | } | 132 | } |
122 | 133 | ||
123 | spin_unlock_bh(&bat_priv->softif_neigh_lock); | 134 | softif_neigh_vid = kzalloc(sizeof(struct softif_neigh_vid), |
135 | GFP_ATOMIC); | ||
136 | if (!softif_neigh_vid) | ||
137 | goto out; | ||
138 | |||
139 | softif_neigh_vid->vid = vid; | ||
140 | softif_neigh_vid->bat_priv = bat_priv; | ||
141 | |||
142 | /* initialize with 2 - caller decrements counter by one */ | ||
143 | atomic_set(&softif_neigh_vid->refcount, 2); | ||
144 | INIT_HLIST_HEAD(&softif_neigh_vid->softif_neigh_list); | ||
145 | INIT_HLIST_NODE(&softif_neigh_vid->list); | ||
146 | spin_lock_bh(&bat_priv->softif_neigh_vid_lock); | ||
147 | hlist_add_head_rcu(&softif_neigh_vid->list, | ||
148 | &bat_priv->softif_neigh_vids); | ||
149 | spin_unlock_bh(&bat_priv->softif_neigh_vid_lock); | ||
150 | |||
151 | out: | ||
152 | rcu_read_unlock(); | ||
153 | return softif_neigh_vid; | ||
124 | } | 154 | } |
125 | 155 | ||
126 | static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv, | 156 | static struct softif_neigh *softif_neigh_get(struct bat_priv *bat_priv, |
127 | uint8_t *addr, short vid) | 157 | uint8_t *addr, short vid) |
128 | { | 158 | { |
129 | struct softif_neigh *softif_neigh; | 159 | struct softif_neigh_vid *softif_neigh_vid; |
160 | struct softif_neigh *softif_neigh = NULL; | ||
130 | struct hlist_node *node; | 161 | struct hlist_node *node; |
131 | 162 | ||
163 | softif_neigh_vid = softif_neigh_vid_get(bat_priv, vid); | ||
164 | if (!softif_neigh_vid) | ||
165 | goto out; | ||
166 | |||
132 | rcu_read_lock(); | 167 | rcu_read_lock(); |
133 | hlist_for_each_entry_rcu(softif_neigh, node, | 168 | hlist_for_each_entry_rcu(softif_neigh, node, |
134 | &bat_priv->softif_neigh_list, list) { | 169 | &softif_neigh_vid->softif_neigh_list, |
170 | list) { | ||
135 | if (!compare_eth(softif_neigh->addr, addr)) | 171 | if (!compare_eth(softif_neigh->addr, addr)) |
136 | continue; | 172 | continue; |
137 | 173 | ||
138 | if (softif_neigh->vid != vid) | ||
139 | continue; | ||
140 | |||
141 | if (!atomic_inc_not_zero(&softif_neigh->refcount)) | 174 | if (!atomic_inc_not_zero(&softif_neigh->refcount)) |
142 | continue; | 175 | continue; |
143 | 176 | ||
144 | softif_neigh->last_seen = jiffies; | 177 | softif_neigh->last_seen = jiffies; |
145 | goto out; | 178 | goto unlock; |
146 | } | 179 | } |
147 | 180 | ||
148 | softif_neigh = kzalloc(sizeof(struct softif_neigh), GFP_ATOMIC); | 181 | softif_neigh = kzalloc(sizeof(struct softif_neigh), GFP_ATOMIC); |
149 | if (!softif_neigh) | 182 | if (!softif_neigh) |
150 | goto out; | 183 | goto unlock; |
151 | 184 | ||
152 | memcpy(softif_neigh->addr, addr, ETH_ALEN); | 185 | memcpy(softif_neigh->addr, addr, ETH_ALEN); |
153 | softif_neigh->vid = vid; | ||
154 | softif_neigh->last_seen = jiffies; | 186 | softif_neigh->last_seen = jiffies; |
155 | /* initialize with 2 - caller decrements counter by one */ | 187 | /* initialize with 2 - caller decrements counter by one */ |
156 | atomic_set(&softif_neigh->refcount, 2); | 188 | atomic_set(&softif_neigh->refcount, 2); |
157 | 189 | ||
158 | INIT_HLIST_NODE(&softif_neigh->list); | 190 | INIT_HLIST_NODE(&softif_neigh->list); |
159 | spin_lock_bh(&bat_priv->softif_neigh_lock); | 191 | spin_lock_bh(&bat_priv->softif_neigh_lock); |
160 | hlist_add_head_rcu(&softif_neigh->list, &bat_priv->softif_neigh_list); | 192 | hlist_add_head_rcu(&softif_neigh->list, |
193 | &softif_neigh_vid->softif_neigh_list); | ||
161 | spin_unlock_bh(&bat_priv->softif_neigh_lock); | 194 | spin_unlock_bh(&bat_priv->softif_neigh_lock); |
162 | 195 | ||
196 | unlock: | ||
197 | rcu_read_unlock(); | ||
163 | out: | 198 | out: |
199 | if (softif_neigh_vid) | ||
200 | softif_neigh_vid_free_ref(softif_neigh_vid); | ||
201 | return softif_neigh; | ||
202 | } | ||
203 | |||
204 | static struct softif_neigh *softif_neigh_get_selected( | ||
205 | struct softif_neigh_vid *softif_neigh_vid) | ||
206 | { | ||
207 | struct softif_neigh *softif_neigh; | ||
208 | |||
209 | rcu_read_lock(); | ||
210 | softif_neigh = rcu_dereference(softif_neigh_vid->softif_neigh); | ||
211 | |||
212 | if (softif_neigh && !atomic_inc_not_zero(&softif_neigh->refcount)) | ||
213 | softif_neigh = NULL; | ||
214 | |||
164 | rcu_read_unlock(); | 215 | rcu_read_unlock(); |
165 | return softif_neigh; | 216 | return softif_neigh; |
166 | } | 217 | } |
167 | 218 | ||
219 | static struct softif_neigh *softif_neigh_vid_get_selected( | ||
220 | struct bat_priv *bat_priv, | ||
221 | short vid) | ||
222 | { | ||
223 | struct softif_neigh_vid *softif_neigh_vid; | ||
224 | struct softif_neigh *softif_neigh = NULL; | ||
225 | |||
226 | softif_neigh_vid = softif_neigh_vid_get(bat_priv, vid); | ||
227 | if (!softif_neigh_vid) | ||
228 | goto out; | ||
229 | |||
230 | softif_neigh = softif_neigh_get_selected(softif_neigh_vid); | ||
231 | out: | ||
232 | if (softif_neigh_vid) | ||
233 | softif_neigh_vid_free_ref(softif_neigh_vid); | ||
234 | return softif_neigh; | ||
235 | } | ||
236 | |||
237 | static void softif_neigh_vid_select(struct bat_priv *bat_priv, | ||
238 | struct softif_neigh *new_neigh, | ||
239 | short vid) | ||
240 | { | ||
241 | struct softif_neigh_vid *softif_neigh_vid; | ||
242 | struct softif_neigh *curr_neigh; | ||
243 | |||
244 | softif_neigh_vid = softif_neigh_vid_get(bat_priv, vid); | ||
245 | if (!softif_neigh_vid) | ||
246 | goto out; | ||
247 | |||
248 | spin_lock_bh(&bat_priv->softif_neigh_lock); | ||
249 | |||
250 | if (new_neigh && !atomic_inc_not_zero(&new_neigh->refcount)) | ||
251 | new_neigh = NULL; | ||
252 | |||
253 | curr_neigh = softif_neigh_vid->softif_neigh; | ||
254 | rcu_assign_pointer(softif_neigh_vid->softif_neigh, new_neigh); | ||
255 | |||
256 | if ((curr_neigh) && (!new_neigh)) | ||
257 | bat_dbg(DBG_ROUTES, bat_priv, | ||
258 | "Removing mesh exit point on vid: %d (prev: %pM).\n", | ||
259 | vid, curr_neigh->addr); | ||
260 | else if ((curr_neigh) && (new_neigh)) | ||
261 | bat_dbg(DBG_ROUTES, bat_priv, | ||
262 | "Changing mesh exit point on vid: %d from %pM " | ||
263 | "to %pM.\n", vid, curr_neigh->addr, new_neigh->addr); | ||
264 | else if ((!curr_neigh) && (new_neigh)) | ||
265 | bat_dbg(DBG_ROUTES, bat_priv, | ||
266 | "Setting mesh exit point on vid: %d to %pM.\n", | ||
267 | vid, new_neigh->addr); | ||
268 | |||
269 | if (curr_neigh) | ||
270 | softif_neigh_free_ref(curr_neigh); | ||
271 | |||
272 | spin_unlock_bh(&bat_priv->softif_neigh_lock); | ||
273 | |||
274 | out: | ||
275 | if (softif_neigh_vid) | ||
276 | softif_neigh_vid_free_ref(softif_neigh_vid); | ||
277 | } | ||
278 | |||
279 | static void softif_neigh_vid_deselect(struct bat_priv *bat_priv, | ||
280 | struct softif_neigh_vid *softif_neigh_vid) | ||
281 | { | ||
282 | struct softif_neigh *curr_neigh; | ||
283 | struct softif_neigh *softif_neigh = NULL, *softif_neigh_tmp; | ||
284 | struct hard_iface *primary_if = NULL; | ||
285 | struct hlist_node *node; | ||
286 | |||
287 | primary_if = primary_if_get_selected(bat_priv); | ||
288 | if (!primary_if) | ||
289 | goto out; | ||
290 | |||
291 | /* find new softif_neigh immediately to avoid temporary loops */ | ||
292 | rcu_read_lock(); | ||
293 | curr_neigh = rcu_dereference(softif_neigh_vid->softif_neigh); | ||
294 | |||
295 | hlist_for_each_entry_rcu(softif_neigh_tmp, node, | ||
296 | &softif_neigh_vid->softif_neigh_list, | ||
297 | list) { | ||
298 | if (softif_neigh_tmp == curr_neigh) | ||
299 | continue; | ||
300 | |||
301 | /* we got a neighbor but its mac is 'bigger' than ours */ | ||
302 | if (memcmp(primary_if->net_dev->dev_addr, | ||
303 | softif_neigh_tmp->addr, ETH_ALEN) < 0) | ||
304 | continue; | ||
305 | |||
306 | if (!atomic_inc_not_zero(&softif_neigh_tmp->refcount)) | ||
307 | continue; | ||
308 | |||
309 | softif_neigh = softif_neigh_tmp; | ||
310 | goto unlock; | ||
311 | } | ||
312 | |||
313 | unlock: | ||
314 | rcu_read_unlock(); | ||
315 | out: | ||
316 | softif_neigh_vid_select(bat_priv, softif_neigh, softif_neigh_vid->vid); | ||
317 | |||
318 | if (primary_if) | ||
319 | hardif_free_ref(primary_if); | ||
320 | if (softif_neigh) | ||
321 | softif_neigh_free_ref(softif_neigh); | ||
322 | } | ||
323 | |||
168 | int softif_neigh_seq_print_text(struct seq_file *seq, void *offset) | 324 | int softif_neigh_seq_print_text(struct seq_file *seq, void *offset) |
169 | { | 325 | { |
170 | struct net_device *net_dev = (struct net_device *)seq->private; | 326 | struct net_device *net_dev = (struct net_device *)seq->private; |
171 | struct bat_priv *bat_priv = netdev_priv(net_dev); | 327 | struct bat_priv *bat_priv = netdev_priv(net_dev); |
328 | struct softif_neigh_vid *softif_neigh_vid; | ||
172 | struct softif_neigh *softif_neigh; | 329 | struct softif_neigh *softif_neigh; |
173 | struct hlist_node *node; | 330 | struct hard_iface *primary_if; |
331 | struct hlist_node *node, *node_tmp; | ||
332 | struct softif_neigh *curr_softif_neigh; | ||
333 | int ret = 0, last_seen_secs, last_seen_msecs; | ||
334 | |||
335 | primary_if = primary_if_get_selected(bat_priv); | ||
336 | if (!primary_if) { | ||
337 | ret = seq_printf(seq, "BATMAN mesh %s disabled - " | ||
338 | "please specify interfaces to enable it\n", | ||
339 | net_dev->name); | ||
340 | goto out; | ||
341 | } | ||
174 | 342 | ||
175 | if (!bat_priv->primary_if) { | 343 | if (primary_if->if_status != IF_ACTIVE) { |
176 | return seq_printf(seq, "BATMAN mesh %s disabled - " | 344 | ret = seq_printf(seq, "BATMAN mesh %s " |
177 | "please specify interfaces to enable it\n", | 345 | "disabled - primary interface not active\n", |
178 | net_dev->name); | 346 | net_dev->name); |
347 | goto out; | ||
179 | } | 348 | } |
180 | 349 | ||
181 | seq_printf(seq, "Softif neighbor list (%s)\n", net_dev->name); | 350 | seq_printf(seq, "Softif neighbor list (%s)\n", net_dev->name); |
182 | 351 | ||
183 | rcu_read_lock(); | 352 | rcu_read_lock(); |
184 | hlist_for_each_entry_rcu(softif_neigh, node, | 353 | hlist_for_each_entry_rcu(softif_neigh_vid, node, |
185 | &bat_priv->softif_neigh_list, list) | 354 | &bat_priv->softif_neigh_vids, list) { |
186 | seq_printf(seq, "%s %pM (vid: %d)\n", | 355 | seq_printf(seq, " %-15s %s on vid: %d\n", |
187 | bat_priv->softif_neigh == softif_neigh | 356 | "Originator", "last-seen", softif_neigh_vid->vid); |
188 | ? "=>" : " ", softif_neigh->addr, | 357 | |
189 | softif_neigh->vid); | 358 | curr_softif_neigh = softif_neigh_get_selected(softif_neigh_vid); |
359 | |||
360 | hlist_for_each_entry_rcu(softif_neigh, node_tmp, | ||
361 | &softif_neigh_vid->softif_neigh_list, | ||
362 | list) { | ||
363 | last_seen_secs = jiffies_to_msecs(jiffies - | ||
364 | softif_neigh->last_seen) / 1000; | ||
365 | last_seen_msecs = jiffies_to_msecs(jiffies - | ||
366 | softif_neigh->last_seen) % 1000; | ||
367 | seq_printf(seq, "%s %pM %3i.%03is\n", | ||
368 | curr_softif_neigh == softif_neigh | ||
369 | ? "=>" : " ", softif_neigh->addr, | ||
370 | last_seen_secs, last_seen_msecs); | ||
371 | } | ||
372 | |||
373 | if (curr_softif_neigh) | ||
374 | softif_neigh_free_ref(curr_softif_neigh); | ||
375 | |||
376 | seq_printf(seq, "\n"); | ||
377 | } | ||
190 | rcu_read_unlock(); | 378 | rcu_read_unlock(); |
191 | 379 | ||
192 | return 0; | 380 | out: |
381 | if (primary_if) | ||
382 | hardif_free_ref(primary_if); | ||
383 | return ret; | ||
384 | } | ||
385 | |||
386 | void softif_neigh_purge(struct bat_priv *bat_priv) | ||
387 | { | ||
388 | struct softif_neigh *softif_neigh, *curr_softif_neigh; | ||
389 | struct softif_neigh_vid *softif_neigh_vid; | ||
390 | struct hlist_node *node, *node_tmp, *node_tmp2; | ||
391 | char do_deselect; | ||
392 | |||
393 | rcu_read_lock(); | ||
394 | hlist_for_each_entry_rcu(softif_neigh_vid, node, | ||
395 | &bat_priv->softif_neigh_vids, list) { | ||
396 | if (!atomic_inc_not_zero(&softif_neigh_vid->refcount)) | ||
397 | continue; | ||
398 | |||
399 | curr_softif_neigh = softif_neigh_get_selected(softif_neigh_vid); | ||
400 | do_deselect = 0; | ||
401 | |||
402 | spin_lock_bh(&bat_priv->softif_neigh_lock); | ||
403 | hlist_for_each_entry_safe(softif_neigh, node_tmp, node_tmp2, | ||
404 | &softif_neigh_vid->softif_neigh_list, | ||
405 | list) { | ||
406 | if ((!time_after(jiffies, softif_neigh->last_seen + | ||
407 | msecs_to_jiffies(SOFTIF_NEIGH_TIMEOUT))) && | ||
408 | (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE)) | ||
409 | continue; | ||
410 | |||
411 | if (curr_softif_neigh == softif_neigh) { | ||
412 | bat_dbg(DBG_ROUTES, bat_priv, | ||
413 | "Current mesh exit point on vid: %d " | ||
414 | "'%pM' vanished.\n", | ||
415 | softif_neigh_vid->vid, | ||
416 | softif_neigh->addr); | ||
417 | do_deselect = 1; | ||
418 | } | ||
419 | |||
420 | hlist_del_rcu(&softif_neigh->list); | ||
421 | softif_neigh_free_ref(softif_neigh); | ||
422 | } | ||
423 | spin_unlock_bh(&bat_priv->softif_neigh_lock); | ||
424 | |||
425 | /* soft_neigh_vid_deselect() needs to acquire the | ||
426 | * softif_neigh_lock */ | ||
427 | if (do_deselect) | ||
428 | softif_neigh_vid_deselect(bat_priv, softif_neigh_vid); | ||
429 | |||
430 | if (curr_softif_neigh) | ||
431 | softif_neigh_free_ref(curr_softif_neigh); | ||
432 | |||
433 | softif_neigh_vid_free_ref(softif_neigh_vid); | ||
434 | } | ||
435 | rcu_read_unlock(); | ||
436 | |||
437 | spin_lock_bh(&bat_priv->softif_neigh_vid_lock); | ||
438 | hlist_for_each_entry_safe(softif_neigh_vid, node, node_tmp, | ||
439 | &bat_priv->softif_neigh_vids, list) { | ||
440 | if (!hlist_empty(&softif_neigh_vid->softif_neigh_list)) | ||
441 | continue; | ||
442 | |||
443 | hlist_del_rcu(&softif_neigh_vid->list); | ||
444 | softif_neigh_vid_free_ref(softif_neigh_vid); | ||
445 | } | ||
446 | spin_unlock_bh(&bat_priv->softif_neigh_vid_lock); | ||
447 | |||
193 | } | 448 | } |
194 | 449 | ||
195 | static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, | 450 | static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, |
@@ -198,7 +453,9 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, | |||
198 | struct bat_priv *bat_priv = netdev_priv(dev); | 453 | struct bat_priv *bat_priv = netdev_priv(dev); |
199 | struct ethhdr *ethhdr = (struct ethhdr *)skb->data; | 454 | struct ethhdr *ethhdr = (struct ethhdr *)skb->data; |
200 | struct batman_packet *batman_packet; | 455 | struct batman_packet *batman_packet; |
201 | struct softif_neigh *softif_neigh, *softif_neigh_tmp; | 456 | struct softif_neigh *softif_neigh = NULL; |
457 | struct hard_iface *primary_if = NULL; | ||
458 | struct softif_neigh *curr_softif_neigh = NULL; | ||
202 | 459 | ||
203 | if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) | 460 | if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) |
204 | batman_packet = (struct batman_packet *) | 461 | batman_packet = (struct batman_packet *) |
@@ -207,63 +464,52 @@ static void softif_batman_recv(struct sk_buff *skb, struct net_device *dev, | |||
207 | batman_packet = (struct batman_packet *)(skb->data + ETH_HLEN); | 464 | batman_packet = (struct batman_packet *)(skb->data + ETH_HLEN); |
208 | 465 | ||
209 | if (batman_packet->version != COMPAT_VERSION) | 466 | if (batman_packet->version != COMPAT_VERSION) |
210 | goto err; | 467 | goto out; |
211 | 468 | ||
212 | if (batman_packet->packet_type != BAT_PACKET) | 469 | if (batman_packet->packet_type != BAT_PACKET) |
213 | goto err; | 470 | goto out; |
214 | 471 | ||
215 | if (!(batman_packet->flags & PRIMARIES_FIRST_HOP)) | 472 | if (!(batman_packet->flags & PRIMARIES_FIRST_HOP)) |
216 | goto err; | 473 | goto out; |
217 | 474 | ||
218 | if (is_my_mac(batman_packet->orig)) | 475 | if (is_my_mac(batman_packet->orig)) |
219 | goto err; | 476 | goto out; |
220 | 477 | ||
221 | softif_neigh = softif_neigh_get(bat_priv, batman_packet->orig, vid); | 478 | softif_neigh = softif_neigh_get(bat_priv, batman_packet->orig, vid); |
222 | |||
223 | if (!softif_neigh) | 479 | if (!softif_neigh) |
224 | goto err; | 480 | goto out; |
225 | 481 | ||
226 | if (bat_priv->softif_neigh == softif_neigh) | 482 | curr_softif_neigh = softif_neigh_vid_get_selected(bat_priv, vid); |
483 | if (curr_softif_neigh == softif_neigh) | ||
484 | goto out; | ||
485 | |||
486 | primary_if = primary_if_get_selected(bat_priv); | ||
487 | if (!primary_if) | ||
227 | goto out; | 488 | goto out; |
228 | 489 | ||
229 | /* we got a neighbor but its mac is 'bigger' than ours */ | 490 | /* we got a neighbor but its mac is 'bigger' than ours */ |
230 | if (memcmp(bat_priv->primary_if->net_dev->dev_addr, | 491 | if (memcmp(primary_if->net_dev->dev_addr, |
231 | softif_neigh->addr, ETH_ALEN) < 0) | 492 | softif_neigh->addr, ETH_ALEN) < 0) |
232 | goto out; | 493 | goto out; |
233 | 494 | ||
234 | /* switch to new 'smallest neighbor' */ | ||
235 | if ((bat_priv->softif_neigh) && | ||
236 | (memcmp(softif_neigh->addr, bat_priv->softif_neigh->addr, | ||
237 | ETH_ALEN) < 0)) { | ||
238 | bat_dbg(DBG_ROUTES, bat_priv, | ||
239 | "Changing mesh exit point from %pM (vid: %d) " | ||
240 | "to %pM (vid: %d).\n", | ||
241 | bat_priv->softif_neigh->addr, | ||
242 | bat_priv->softif_neigh->vid, | ||
243 | softif_neigh->addr, softif_neigh->vid); | ||
244 | softif_neigh_tmp = bat_priv->softif_neigh; | ||
245 | bat_priv->softif_neigh = softif_neigh; | ||
246 | softif_neigh_free_ref(softif_neigh_tmp); | ||
247 | /* we need to hold the additional reference */ | ||
248 | goto err; | ||
249 | } | ||
250 | |||
251 | /* close own batX device and use softif_neigh as exit node */ | 495 | /* close own batX device and use softif_neigh as exit node */ |
252 | if ((!bat_priv->softif_neigh) && | 496 | if (!curr_softif_neigh) { |
253 | (memcmp(softif_neigh->addr, | 497 | softif_neigh_vid_select(bat_priv, softif_neigh, vid); |
254 | bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN) < 0)) { | 498 | goto out; |
255 | bat_dbg(DBG_ROUTES, bat_priv, | ||
256 | "Setting mesh exit point to %pM (vid: %d).\n", | ||
257 | softif_neigh->addr, softif_neigh->vid); | ||
258 | bat_priv->softif_neigh = softif_neigh; | ||
259 | /* we need to hold the additional reference */ | ||
260 | goto err; | ||
261 | } | 499 | } |
262 | 500 | ||
501 | /* switch to new 'smallest neighbor' */ | ||
502 | if (memcmp(softif_neigh->addr, curr_softif_neigh->addr, ETH_ALEN) < 0) | ||
503 | softif_neigh_vid_select(bat_priv, softif_neigh, vid); | ||
504 | |||
263 | out: | 505 | out: |
264 | softif_neigh_free_ref(softif_neigh); | ||
265 | err: | ||
266 | kfree_skb(skb); | 506 | kfree_skb(skb); |
507 | if (softif_neigh) | ||
508 | softif_neigh_free_ref(softif_neigh); | ||
509 | if (curr_softif_neigh) | ||
510 | softif_neigh_free_ref(curr_softif_neigh); | ||
511 | if (primary_if) | ||
512 | hardif_free_ref(primary_if); | ||
267 | return; | 513 | return; |
268 | } | 514 | } |
269 | 515 | ||
@@ -293,11 +539,11 @@ static int interface_set_mac_addr(struct net_device *dev, void *p) | |||
293 | if (!is_valid_ether_addr(addr->sa_data)) | 539 | if (!is_valid_ether_addr(addr->sa_data)) |
294 | return -EADDRNOTAVAIL; | 540 | return -EADDRNOTAVAIL; |
295 | 541 | ||
296 | /* only modify hna-table if it has been initialised before */ | 542 | /* only modify transtable if it has been initialised before */ |
297 | if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) { | 543 | if (atomic_read(&bat_priv->mesh_state) == MESH_ACTIVE) { |
298 | hna_local_remove(bat_priv, dev->dev_addr, | 544 | tt_local_remove(bat_priv, dev->dev_addr, |
299 | "mac address changed"); | 545 | "mac address changed"); |
300 | hna_local_add(dev, addr->sa_data); | 546 | tt_local_add(dev, addr->sa_data); |
301 | } | 547 | } |
302 | 548 | ||
303 | memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); | 549 | memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); |
@@ -319,8 +565,10 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) | |||
319 | { | 565 | { |
320 | struct ethhdr *ethhdr = (struct ethhdr *)skb->data; | 566 | struct ethhdr *ethhdr = (struct ethhdr *)skb->data; |
321 | struct bat_priv *bat_priv = netdev_priv(soft_iface); | 567 | struct bat_priv *bat_priv = netdev_priv(soft_iface); |
568 | struct hard_iface *primary_if = NULL; | ||
322 | struct bcast_packet *bcast_packet; | 569 | struct bcast_packet *bcast_packet; |
323 | struct vlan_ethhdr *vhdr; | 570 | struct vlan_ethhdr *vhdr; |
571 | struct softif_neigh *curr_softif_neigh = NULL; | ||
324 | int data_len = skb->len, ret; | 572 | int data_len = skb->len, ret; |
325 | short vid = -1; | 573 | short vid = -1; |
326 | bool do_bcast = false; | 574 | bool do_bcast = false; |
@@ -348,11 +596,12 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) | |||
348 | * if we have a another chosen mesh exit node in range | 596 | * if we have a another chosen mesh exit node in range |
349 | * it will transport the packets to the mesh | 597 | * it will transport the packets to the mesh |
350 | */ | 598 | */ |
351 | if ((bat_priv->softif_neigh) && (bat_priv->softif_neigh->vid == vid)) | 599 | curr_softif_neigh = softif_neigh_vid_get_selected(bat_priv, vid); |
600 | if (curr_softif_neigh) | ||
352 | goto dropped; | 601 | goto dropped; |
353 | 602 | ||
354 | /* TODO: check this for locks */ | 603 | /* TODO: check this for locks */ |
355 | hna_local_add(soft_iface, ethhdr->h_source); | 604 | tt_local_add(soft_iface, ethhdr->h_source); |
356 | 605 | ||
357 | if (is_multicast_ether_addr(ethhdr->h_dest)) { | 606 | if (is_multicast_ether_addr(ethhdr->h_dest)) { |
358 | ret = gw_is_target(bat_priv, skb); | 607 | ret = gw_is_target(bat_priv, skb); |
@@ -366,7 +615,8 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) | |||
366 | 615 | ||
367 | /* ethernet packet should be broadcasted */ | 616 | /* ethernet packet should be broadcasted */ |
368 | if (do_bcast) { | 617 | if (do_bcast) { |
369 | if (!bat_priv->primary_if) | 618 | primary_if = primary_if_get_selected(bat_priv); |
619 | if (!primary_if) | ||
370 | goto dropped; | 620 | goto dropped; |
371 | 621 | ||
372 | if (my_skb_head_push(skb, sizeof(struct bcast_packet)) < 0) | 622 | if (my_skb_head_push(skb, sizeof(struct bcast_packet)) < 0) |
@@ -382,7 +632,7 @@ int interface_tx(struct sk_buff *skb, struct net_device *soft_iface) | |||
382 | /* hw address of first interface is the orig mac because only | 632 | /* hw address of first interface is the orig mac because only |
383 | * this mac is known throughout the mesh */ | 633 | * this mac is known throughout the mesh */ |
384 | memcpy(bcast_packet->orig, | 634 | memcpy(bcast_packet->orig, |
385 | bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); | 635 | primary_if->net_dev->dev_addr, ETH_ALEN); |
386 | 636 | ||
387 | /* set broadcast sequence number */ | 637 | /* set broadcast sequence number */ |
388 | bcast_packet->seqno = | 638 | bcast_packet->seqno = |
@@ -410,6 +660,10 @@ dropped: | |||
410 | dropped_freed: | 660 | dropped_freed: |
411 | bat_priv->stats.tx_dropped++; | 661 | bat_priv->stats.tx_dropped++; |
412 | end: | 662 | end: |
663 | if (curr_softif_neigh) | ||
664 | softif_neigh_free_ref(curr_softif_neigh); | ||
665 | if (primary_if) | ||
666 | hardif_free_ref(primary_if); | ||
413 | return NETDEV_TX_OK; | 667 | return NETDEV_TX_OK; |
414 | } | 668 | } |
415 | 669 | ||
@@ -421,6 +675,7 @@ void interface_rx(struct net_device *soft_iface, | |||
421 | struct unicast_packet *unicast_packet; | 675 | struct unicast_packet *unicast_packet; |
422 | struct ethhdr *ethhdr; | 676 | struct ethhdr *ethhdr; |
423 | struct vlan_ethhdr *vhdr; | 677 | struct vlan_ethhdr *vhdr; |
678 | struct softif_neigh *curr_softif_neigh = NULL; | ||
424 | short vid = -1; | 679 | short vid = -1; |
425 | int ret; | 680 | int ret; |
426 | 681 | ||
@@ -450,7 +705,8 @@ void interface_rx(struct net_device *soft_iface, | |||
450 | * if we have a another chosen mesh exit node in range | 705 | * if we have a another chosen mesh exit node in range |
451 | * it will transport the packets to the non-mesh network | 706 | * it will transport the packets to the non-mesh network |
452 | */ | 707 | */ |
453 | if ((bat_priv->softif_neigh) && (bat_priv->softif_neigh->vid == vid)) { | 708 | curr_softif_neigh = softif_neigh_vid_get_selected(bat_priv, vid); |
709 | if (curr_softif_neigh) { | ||
454 | skb_push(skb, hdr_size); | 710 | skb_push(skb, hdr_size); |
455 | unicast_packet = (struct unicast_packet *)skb->data; | 711 | unicast_packet = (struct unicast_packet *)skb->data; |
456 | 712 | ||
@@ -461,7 +717,7 @@ void interface_rx(struct net_device *soft_iface, | |||
461 | skb_reset_mac_header(skb); | 717 | skb_reset_mac_header(skb); |
462 | 718 | ||
463 | memcpy(unicast_packet->dest, | 719 | memcpy(unicast_packet->dest, |
464 | bat_priv->softif_neigh->addr, ETH_ALEN); | 720 | curr_softif_neigh->addr, ETH_ALEN); |
465 | ret = route_unicast_packet(skb, recv_if); | 721 | ret = route_unicast_packet(skb, recv_if); |
466 | if (ret == NET_RX_DROP) | 722 | if (ret == NET_RX_DROP) |
467 | goto dropped; | 723 | goto dropped; |
@@ -474,7 +730,7 @@ void interface_rx(struct net_device *soft_iface, | |||
474 | goto dropped; | 730 | goto dropped; |
475 | skb->protocol = eth_type_trans(skb, soft_iface); | 731 | skb->protocol = eth_type_trans(skb, soft_iface); |
476 | 732 | ||
477 | /* should not be neccesary anymore as we use skb_pull_rcsum() | 733 | /* should not be necessary anymore as we use skb_pull_rcsum() |
478 | * TODO: please verify this and remove this TODO | 734 | * TODO: please verify this and remove this TODO |
479 | * -- Dec 21st 2009, Simon Wunderlich */ | 735 | * -- Dec 21st 2009, Simon Wunderlich */ |
480 | 736 | ||
@@ -486,11 +742,13 @@ void interface_rx(struct net_device *soft_iface, | |||
486 | soft_iface->last_rx = jiffies; | 742 | soft_iface->last_rx = jiffies; |
487 | 743 | ||
488 | netif_rx(skb); | 744 | netif_rx(skb); |
489 | return; | 745 | goto out; |
490 | 746 | ||
491 | dropped: | 747 | dropped: |
492 | kfree_skb(skb); | 748 | kfree_skb(skb); |
493 | out: | 749 | out: |
750 | if (curr_softif_neigh) | ||
751 | softif_neigh_free_ref(curr_softif_neigh); | ||
494 | return; | 752 | return; |
495 | } | 753 | } |
496 | 754 | ||
@@ -524,14 +782,15 @@ static void interface_setup(struct net_device *dev) | |||
524 | dev->hard_start_xmit = interface_tx; | 782 | dev->hard_start_xmit = interface_tx; |
525 | #endif | 783 | #endif |
526 | dev->destructor = free_netdev; | 784 | dev->destructor = free_netdev; |
785 | dev->tx_queue_len = 0; | ||
527 | 786 | ||
528 | /** | 787 | /** |
529 | * can't call min_mtu, because the needed variables | 788 | * can't call min_mtu, because the needed variables |
530 | * have not been initialized yet | 789 | * have not been initialized yet |
531 | */ | 790 | */ |
532 | dev->mtu = ETH_DATA_LEN; | 791 | dev->mtu = ETH_DATA_LEN; |
533 | dev->hard_header_len = BAT_HEADER_LEN; /* reserve more space in the | 792 | /* reserve more space in the skbuff for our header */ |
534 | * skbuff for our header */ | 793 | dev->hard_header_len = BAT_HEADER_LEN; |
535 | 794 | ||
536 | /* generate random address */ | 795 | /* generate random address */ |
537 | random_ether_addr(dev_addr); | 796 | random_ether_addr(dev_addr); |
@@ -556,7 +815,7 @@ struct net_device *softif_create(char *name) | |||
556 | goto out; | 815 | goto out; |
557 | } | 816 | } |
558 | 817 | ||
559 | ret = register_netdev(soft_iface); | 818 | ret = register_netdevice(soft_iface); |
560 | if (ret < 0) { | 819 | if (ret < 0) { |
561 | pr_err("Unable to register the batman interface '%s': %i\n", | 820 | pr_err("Unable to register the batman interface '%s': %i\n", |
562 | name, ret); | 821 | name, ret); |
@@ -580,11 +839,10 @@ struct net_device *softif_create(char *name) | |||
580 | 839 | ||
581 | atomic_set(&bat_priv->mesh_state, MESH_INACTIVE); | 840 | atomic_set(&bat_priv->mesh_state, MESH_INACTIVE); |
582 | atomic_set(&bat_priv->bcast_seqno, 1); | 841 | atomic_set(&bat_priv->bcast_seqno, 1); |
583 | atomic_set(&bat_priv->hna_local_changed, 0); | 842 | atomic_set(&bat_priv->tt_local_changed, 0); |
584 | 843 | ||
585 | bat_priv->primary_if = NULL; | 844 | bat_priv->primary_if = NULL; |
586 | bat_priv->num_ifaces = 0; | 845 | bat_priv->num_ifaces = 0; |
587 | bat_priv->softif_neigh = NULL; | ||
588 | 846 | ||
589 | ret = sysfs_add_meshif(soft_iface); | 847 | ret = sysfs_add_meshif(soft_iface); |
590 | if (ret < 0) | 848 | if (ret < 0) |
@@ -640,7 +898,7 @@ static int bat_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
640 | { | 898 | { |
641 | cmd->supported = 0; | 899 | cmd->supported = 0; |
642 | cmd->advertising = 0; | 900 | cmd->advertising = 0; |
643 | cmd->speed = SPEED_10; | 901 | ethtool_cmd_speed_set(cmd, SPEED_10); |
644 | cmd->duplex = DUPLEX_FULL; | 902 | cmd->duplex = DUPLEX_FULL; |
645 | cmd->port = PORT_TP; | 903 | cmd->port = PORT_TP; |
646 | cmd->phy_address = 0; | 904 | cmd->phy_address = 0; |
@@ -675,12 +933,3 @@ static u32 bat_get_link(struct net_device *dev) | |||
675 | return 1; | 933 | return 1; |
676 | } | 934 | } |
677 | 935 | ||
678 | static u32 bat_get_rx_csum(struct net_device *dev) | ||
679 | { | ||
680 | return 0; | ||
681 | } | ||
682 | |||
683 | static int bat_set_rx_csum(struct net_device *dev, u32 data) | ||
684 | { | ||
685 | return -EOPNOTSUPP; | ||
686 | } | ||
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 8d15b48d1692..7b729660cbfd 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c | |||
@@ -22,43 +22,44 @@ | |||
22 | #include "main.h" | 22 | #include "main.h" |
23 | #include "translation-table.h" | 23 | #include "translation-table.h" |
24 | #include "soft-interface.h" | 24 | #include "soft-interface.h" |
25 | #include "hard-interface.h" | ||
25 | #include "hash.h" | 26 | #include "hash.h" |
26 | #include "originator.h" | 27 | #include "originator.h" |
27 | 28 | ||
28 | static void hna_local_purge(struct work_struct *work); | 29 | static void tt_local_purge(struct work_struct *work); |
29 | static void _hna_global_del_orig(struct bat_priv *bat_priv, | 30 | static void _tt_global_del_orig(struct bat_priv *bat_priv, |
30 | struct hna_global_entry *hna_global_entry, | 31 | struct tt_global_entry *tt_global_entry, |
31 | char *message); | 32 | char *message); |
32 | 33 | ||
33 | /* returns 1 if they are the same mac addr */ | 34 | /* returns 1 if they are the same mac addr */ |
34 | static int compare_lhna(struct hlist_node *node, void *data2) | 35 | static int compare_ltt(struct hlist_node *node, void *data2) |
35 | { | 36 | { |
36 | void *data1 = container_of(node, struct hna_local_entry, hash_entry); | 37 | void *data1 = container_of(node, struct tt_local_entry, hash_entry); |
37 | 38 | ||
38 | return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); | 39 | return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); |
39 | } | 40 | } |
40 | 41 | ||
41 | /* returns 1 if they are the same mac addr */ | 42 | /* returns 1 if they are the same mac addr */ |
42 | static int compare_ghna(struct hlist_node *node, void *data2) | 43 | static int compare_gtt(struct hlist_node *node, void *data2) |
43 | { | 44 | { |
44 | void *data1 = container_of(node, struct hna_global_entry, hash_entry); | 45 | void *data1 = container_of(node, struct tt_global_entry, hash_entry); |
45 | 46 | ||
46 | return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); | 47 | return (memcmp(data1, data2, ETH_ALEN) == 0 ? 1 : 0); |
47 | } | 48 | } |
48 | 49 | ||
49 | static void hna_local_start_timer(struct bat_priv *bat_priv) | 50 | static void tt_local_start_timer(struct bat_priv *bat_priv) |
50 | { | 51 | { |
51 | INIT_DELAYED_WORK(&bat_priv->hna_work, hna_local_purge); | 52 | INIT_DELAYED_WORK(&bat_priv->tt_work, tt_local_purge); |
52 | queue_delayed_work(bat_event_workqueue, &bat_priv->hna_work, 10 * HZ); | 53 | queue_delayed_work(bat_event_workqueue, &bat_priv->tt_work, 10 * HZ); |
53 | } | 54 | } |
54 | 55 | ||
55 | static struct hna_local_entry *hna_local_hash_find(struct bat_priv *bat_priv, | 56 | static struct tt_local_entry *tt_local_hash_find(struct bat_priv *bat_priv, |
56 | void *data) | 57 | void *data) |
57 | { | 58 | { |
58 | struct hashtable_t *hash = bat_priv->hna_local_hash; | 59 | struct hashtable_t *hash = bat_priv->tt_local_hash; |
59 | struct hlist_head *head; | 60 | struct hlist_head *head; |
60 | struct hlist_node *node; | 61 | struct hlist_node *node; |
61 | struct hna_local_entry *hna_local_entry, *hna_local_entry_tmp = NULL; | 62 | struct tt_local_entry *tt_local_entry, *tt_local_entry_tmp = NULL; |
62 | int index; | 63 | int index; |
63 | 64 | ||
64 | if (!hash) | 65 | if (!hash) |
@@ -68,26 +69,26 @@ static struct hna_local_entry *hna_local_hash_find(struct bat_priv *bat_priv, | |||
68 | head = &hash->table[index]; | 69 | head = &hash->table[index]; |
69 | 70 | ||
70 | rcu_read_lock(); | 71 | rcu_read_lock(); |
71 | hlist_for_each_entry_rcu(hna_local_entry, node, head, hash_entry) { | 72 | hlist_for_each_entry_rcu(tt_local_entry, node, head, hash_entry) { |
72 | if (!compare_eth(hna_local_entry, data)) | 73 | if (!compare_eth(tt_local_entry, data)) |
73 | continue; | 74 | continue; |
74 | 75 | ||
75 | hna_local_entry_tmp = hna_local_entry; | 76 | tt_local_entry_tmp = tt_local_entry; |
76 | break; | 77 | break; |
77 | } | 78 | } |
78 | rcu_read_unlock(); | 79 | rcu_read_unlock(); |
79 | 80 | ||
80 | return hna_local_entry_tmp; | 81 | return tt_local_entry_tmp; |
81 | } | 82 | } |
82 | 83 | ||
83 | static struct hna_global_entry *hna_global_hash_find(struct bat_priv *bat_priv, | 84 | static struct tt_global_entry *tt_global_hash_find(struct bat_priv *bat_priv, |
84 | void *data) | 85 | void *data) |
85 | { | 86 | { |
86 | struct hashtable_t *hash = bat_priv->hna_global_hash; | 87 | struct hashtable_t *hash = bat_priv->tt_global_hash; |
87 | struct hlist_head *head; | 88 | struct hlist_head *head; |
88 | struct hlist_node *node; | 89 | struct hlist_node *node; |
89 | struct hna_global_entry *hna_global_entry; | 90 | struct tt_global_entry *tt_global_entry; |
90 | struct hna_global_entry *hna_global_entry_tmp = NULL; | 91 | struct tt_global_entry *tt_global_entry_tmp = NULL; |
91 | int index; | 92 | int index; |
92 | 93 | ||
93 | if (!hash) | 94 | if (!hash) |
@@ -97,125 +98,125 @@ static struct hna_global_entry *hna_global_hash_find(struct bat_priv *bat_priv, | |||
97 | head = &hash->table[index]; | 98 | head = &hash->table[index]; |
98 | 99 | ||
99 | rcu_read_lock(); | 100 | rcu_read_lock(); |
100 | hlist_for_each_entry_rcu(hna_global_entry, node, head, hash_entry) { | 101 | hlist_for_each_entry_rcu(tt_global_entry, node, head, hash_entry) { |
101 | if (!compare_eth(hna_global_entry, data)) | 102 | if (!compare_eth(tt_global_entry, data)) |
102 | continue; | 103 | continue; |
103 | 104 | ||
104 | hna_global_entry_tmp = hna_global_entry; | 105 | tt_global_entry_tmp = tt_global_entry; |
105 | break; | 106 | break; |
106 | } | 107 | } |
107 | rcu_read_unlock(); | 108 | rcu_read_unlock(); |
108 | 109 | ||
109 | return hna_global_entry_tmp; | 110 | return tt_global_entry_tmp; |
110 | } | 111 | } |
111 | 112 | ||
112 | int hna_local_init(struct bat_priv *bat_priv) | 113 | int tt_local_init(struct bat_priv *bat_priv) |
113 | { | 114 | { |
114 | if (bat_priv->hna_local_hash) | 115 | if (bat_priv->tt_local_hash) |
115 | return 1; | 116 | return 1; |
116 | 117 | ||
117 | bat_priv->hna_local_hash = hash_new(1024); | 118 | bat_priv->tt_local_hash = hash_new(1024); |
118 | 119 | ||
119 | if (!bat_priv->hna_local_hash) | 120 | if (!bat_priv->tt_local_hash) |
120 | return 0; | 121 | return 0; |
121 | 122 | ||
122 | atomic_set(&bat_priv->hna_local_changed, 0); | 123 | atomic_set(&bat_priv->tt_local_changed, 0); |
123 | hna_local_start_timer(bat_priv); | 124 | tt_local_start_timer(bat_priv); |
124 | 125 | ||
125 | return 1; | 126 | return 1; |
126 | } | 127 | } |
127 | 128 | ||
128 | void hna_local_add(struct net_device *soft_iface, uint8_t *addr) | 129 | void tt_local_add(struct net_device *soft_iface, uint8_t *addr) |
129 | { | 130 | { |
130 | struct bat_priv *bat_priv = netdev_priv(soft_iface); | 131 | struct bat_priv *bat_priv = netdev_priv(soft_iface); |
131 | struct hna_local_entry *hna_local_entry; | 132 | struct tt_local_entry *tt_local_entry; |
132 | struct hna_global_entry *hna_global_entry; | 133 | struct tt_global_entry *tt_global_entry; |
133 | int required_bytes; | 134 | int required_bytes; |
134 | 135 | ||
135 | spin_lock_bh(&bat_priv->hna_lhash_lock); | 136 | spin_lock_bh(&bat_priv->tt_lhash_lock); |
136 | hna_local_entry = hna_local_hash_find(bat_priv, addr); | 137 | tt_local_entry = tt_local_hash_find(bat_priv, addr); |
137 | spin_unlock_bh(&bat_priv->hna_lhash_lock); | 138 | spin_unlock_bh(&bat_priv->tt_lhash_lock); |
138 | 139 | ||
139 | if (hna_local_entry) { | 140 | if (tt_local_entry) { |
140 | hna_local_entry->last_seen = jiffies; | 141 | tt_local_entry->last_seen = jiffies; |
141 | return; | 142 | return; |
142 | } | 143 | } |
143 | 144 | ||
144 | /* only announce as many hosts as possible in the batman-packet and | 145 | /* only announce as many hosts as possible in the batman-packet and |
145 | space in batman_packet->num_hna That also should give a limit to | 146 | space in batman_packet->num_tt That also should give a limit to |
146 | MAC-flooding. */ | 147 | MAC-flooding. */ |
147 | required_bytes = (bat_priv->num_local_hna + 1) * ETH_ALEN; | 148 | required_bytes = (bat_priv->num_local_tt + 1) * ETH_ALEN; |
148 | required_bytes += BAT_PACKET_LEN; | 149 | required_bytes += BAT_PACKET_LEN; |
149 | 150 | ||
150 | if ((required_bytes > ETH_DATA_LEN) || | 151 | if ((required_bytes > ETH_DATA_LEN) || |
151 | (atomic_read(&bat_priv->aggregated_ogms) && | 152 | (atomic_read(&bat_priv->aggregated_ogms) && |
152 | required_bytes > MAX_AGGREGATION_BYTES) || | 153 | required_bytes > MAX_AGGREGATION_BYTES) || |
153 | (bat_priv->num_local_hna + 1 > 255)) { | 154 | (bat_priv->num_local_tt + 1 > 255)) { |
154 | bat_dbg(DBG_ROUTES, bat_priv, | 155 | bat_dbg(DBG_ROUTES, bat_priv, |
155 | "Can't add new local hna entry (%pM): " | 156 | "Can't add new local tt entry (%pM): " |
156 | "number of local hna entries exceeds packet size\n", | 157 | "number of local tt entries exceeds packet size\n", |
157 | addr); | 158 | addr); |
158 | return; | 159 | return; |
159 | } | 160 | } |
160 | 161 | ||
161 | bat_dbg(DBG_ROUTES, bat_priv, | 162 | bat_dbg(DBG_ROUTES, bat_priv, |
162 | "Creating new local hna entry: %pM\n", addr); | 163 | "Creating new local tt entry: %pM\n", addr); |
163 | 164 | ||
164 | hna_local_entry = kmalloc(sizeof(struct hna_local_entry), GFP_ATOMIC); | 165 | tt_local_entry = kmalloc(sizeof(struct tt_local_entry), GFP_ATOMIC); |
165 | if (!hna_local_entry) | 166 | if (!tt_local_entry) |
166 | return; | 167 | return; |
167 | 168 | ||
168 | memcpy(hna_local_entry->addr, addr, ETH_ALEN); | 169 | memcpy(tt_local_entry->addr, addr, ETH_ALEN); |
169 | hna_local_entry->last_seen = jiffies; | 170 | tt_local_entry->last_seen = jiffies; |
170 | 171 | ||
171 | /* the batman interface mac address should never be purged */ | 172 | /* the batman interface mac address should never be purged */ |
172 | if (compare_eth(addr, soft_iface->dev_addr)) | 173 | if (compare_eth(addr, soft_iface->dev_addr)) |
173 | hna_local_entry->never_purge = 1; | 174 | tt_local_entry->never_purge = 1; |
174 | else | 175 | else |
175 | hna_local_entry->never_purge = 0; | 176 | tt_local_entry->never_purge = 0; |
176 | 177 | ||
177 | spin_lock_bh(&bat_priv->hna_lhash_lock); | 178 | spin_lock_bh(&bat_priv->tt_lhash_lock); |
178 | 179 | ||
179 | hash_add(bat_priv->hna_local_hash, compare_lhna, choose_orig, | 180 | hash_add(bat_priv->tt_local_hash, compare_ltt, choose_orig, |
180 | hna_local_entry, &hna_local_entry->hash_entry); | 181 | tt_local_entry, &tt_local_entry->hash_entry); |
181 | bat_priv->num_local_hna++; | 182 | bat_priv->num_local_tt++; |
182 | atomic_set(&bat_priv->hna_local_changed, 1); | 183 | atomic_set(&bat_priv->tt_local_changed, 1); |
183 | 184 | ||
184 | spin_unlock_bh(&bat_priv->hna_lhash_lock); | 185 | spin_unlock_bh(&bat_priv->tt_lhash_lock); |
185 | 186 | ||
186 | /* remove address from global hash if present */ | 187 | /* remove address from global hash if present */ |
187 | spin_lock_bh(&bat_priv->hna_ghash_lock); | 188 | spin_lock_bh(&bat_priv->tt_ghash_lock); |
188 | 189 | ||
189 | hna_global_entry = hna_global_hash_find(bat_priv, addr); | 190 | tt_global_entry = tt_global_hash_find(bat_priv, addr); |
190 | 191 | ||
191 | if (hna_global_entry) | 192 | if (tt_global_entry) |
192 | _hna_global_del_orig(bat_priv, hna_global_entry, | 193 | _tt_global_del_orig(bat_priv, tt_global_entry, |
193 | "local hna received"); | 194 | "local tt received"); |
194 | 195 | ||
195 | spin_unlock_bh(&bat_priv->hna_ghash_lock); | 196 | spin_unlock_bh(&bat_priv->tt_ghash_lock); |
196 | } | 197 | } |
197 | 198 | ||
198 | int hna_local_fill_buffer(struct bat_priv *bat_priv, | 199 | int tt_local_fill_buffer(struct bat_priv *bat_priv, |
199 | unsigned char *buff, int buff_len) | 200 | unsigned char *buff, int buff_len) |
200 | { | 201 | { |
201 | struct hashtable_t *hash = bat_priv->hna_local_hash; | 202 | struct hashtable_t *hash = bat_priv->tt_local_hash; |
202 | struct hna_local_entry *hna_local_entry; | 203 | struct tt_local_entry *tt_local_entry; |
203 | struct hlist_node *node; | 204 | struct hlist_node *node; |
204 | struct hlist_head *head; | 205 | struct hlist_head *head; |
205 | int i, count = 0; | 206 | int i, count = 0; |
206 | 207 | ||
207 | spin_lock_bh(&bat_priv->hna_lhash_lock); | 208 | spin_lock_bh(&bat_priv->tt_lhash_lock); |
208 | 209 | ||
209 | for (i = 0; i < hash->size; i++) { | 210 | for (i = 0; i < hash->size; i++) { |
210 | head = &hash->table[i]; | 211 | head = &hash->table[i]; |
211 | 212 | ||
212 | rcu_read_lock(); | 213 | rcu_read_lock(); |
213 | hlist_for_each_entry_rcu(hna_local_entry, node, | 214 | hlist_for_each_entry_rcu(tt_local_entry, node, |
214 | head, hash_entry) { | 215 | head, hash_entry) { |
215 | if (buff_len < (count + 1) * ETH_ALEN) | 216 | if (buff_len < (count + 1) * ETH_ALEN) |
216 | break; | 217 | break; |
217 | 218 | ||
218 | memcpy(buff + (count * ETH_ALEN), hna_local_entry->addr, | 219 | memcpy(buff + (count * ETH_ALEN), tt_local_entry->addr, |
219 | ETH_ALEN); | 220 | ETH_ALEN); |
220 | 221 | ||
221 | count++; | 222 | count++; |
@@ -223,37 +224,47 @@ int hna_local_fill_buffer(struct bat_priv *bat_priv, | |||
223 | rcu_read_unlock(); | 224 | rcu_read_unlock(); |
224 | } | 225 | } |
225 | 226 | ||
226 | /* if we did not get all new local hnas see you next time ;-) */ | 227 | /* if we did not get all new local tts see you next time ;-) */ |
227 | if (count == bat_priv->num_local_hna) | 228 | if (count == bat_priv->num_local_tt) |
228 | atomic_set(&bat_priv->hna_local_changed, 0); | 229 | atomic_set(&bat_priv->tt_local_changed, 0); |
229 | 230 | ||
230 | spin_unlock_bh(&bat_priv->hna_lhash_lock); | 231 | spin_unlock_bh(&bat_priv->tt_lhash_lock); |
231 | return count; | 232 | return count; |
232 | } | 233 | } |
233 | 234 | ||
234 | int hna_local_seq_print_text(struct seq_file *seq, void *offset) | 235 | int tt_local_seq_print_text(struct seq_file *seq, void *offset) |
235 | { | 236 | { |
236 | struct net_device *net_dev = (struct net_device *)seq->private; | 237 | struct net_device *net_dev = (struct net_device *)seq->private; |
237 | struct bat_priv *bat_priv = netdev_priv(net_dev); | 238 | struct bat_priv *bat_priv = netdev_priv(net_dev); |
238 | struct hashtable_t *hash = bat_priv->hna_local_hash; | 239 | struct hashtable_t *hash = bat_priv->tt_local_hash; |
239 | struct hna_local_entry *hna_local_entry; | 240 | struct tt_local_entry *tt_local_entry; |
241 | struct hard_iface *primary_if; | ||
240 | struct hlist_node *node; | 242 | struct hlist_node *node; |
241 | struct hlist_head *head; | 243 | struct hlist_head *head; |
242 | size_t buf_size, pos; | 244 | size_t buf_size, pos; |
243 | char *buff; | 245 | char *buff; |
244 | int i; | 246 | int i, ret = 0; |
245 | 247 | ||
246 | if (!bat_priv->primary_if) { | 248 | primary_if = primary_if_get_selected(bat_priv); |
247 | return seq_printf(seq, "BATMAN mesh %s disabled - " | 249 | if (!primary_if) { |
248 | "please specify interfaces to enable it\n", | 250 | ret = seq_printf(seq, "BATMAN mesh %s disabled - " |
249 | net_dev->name); | 251 | "please specify interfaces to enable it\n", |
252 | net_dev->name); | ||
253 | goto out; | ||
254 | } | ||
255 | |||
256 | if (primary_if->if_status != IF_ACTIVE) { | ||
257 | ret = seq_printf(seq, "BATMAN mesh %s disabled - " | ||
258 | "primary interface not active\n", | ||
259 | net_dev->name); | ||
260 | goto out; | ||
250 | } | 261 | } |
251 | 262 | ||
252 | seq_printf(seq, "Locally retrieved addresses (from %s) " | 263 | seq_printf(seq, "Locally retrieved addresses (from %s) " |
253 | "announced via HNA:\n", | 264 | "announced via TT:\n", |
254 | net_dev->name); | 265 | net_dev->name); |
255 | 266 | ||
256 | spin_lock_bh(&bat_priv->hna_lhash_lock); | 267 | spin_lock_bh(&bat_priv->tt_lhash_lock); |
257 | 268 | ||
258 | buf_size = 1; | 269 | buf_size = 1; |
259 | /* Estimate length for: " * xx:xx:xx:xx:xx:xx\n" */ | 270 | /* Estimate length for: " * xx:xx:xx:xx:xx:xx\n" */ |
@@ -268,8 +279,9 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset) | |||
268 | 279 | ||
269 | buff = kmalloc(buf_size, GFP_ATOMIC); | 280 | buff = kmalloc(buf_size, GFP_ATOMIC); |
270 | if (!buff) { | 281 | if (!buff) { |
271 | spin_unlock_bh(&bat_priv->hna_lhash_lock); | 282 | spin_unlock_bh(&bat_priv->tt_lhash_lock); |
272 | return -ENOMEM; | 283 | ret = -ENOMEM; |
284 | goto out; | ||
273 | } | 285 | } |
274 | 286 | ||
275 | buff[0] = '\0'; | 287 | buff[0] = '\0'; |
@@ -279,211 +291,225 @@ int hna_local_seq_print_text(struct seq_file *seq, void *offset) | |||
279 | head = &hash->table[i]; | 291 | head = &hash->table[i]; |
280 | 292 | ||
281 | rcu_read_lock(); | 293 | rcu_read_lock(); |
282 | hlist_for_each_entry_rcu(hna_local_entry, node, | 294 | hlist_for_each_entry_rcu(tt_local_entry, node, |
283 | head, hash_entry) { | 295 | head, hash_entry) { |
284 | pos += snprintf(buff + pos, 22, " * %pM\n", | 296 | pos += snprintf(buff + pos, 22, " * %pM\n", |
285 | hna_local_entry->addr); | 297 | tt_local_entry->addr); |
286 | } | 298 | } |
287 | rcu_read_unlock(); | 299 | rcu_read_unlock(); |
288 | } | 300 | } |
289 | 301 | ||
290 | spin_unlock_bh(&bat_priv->hna_lhash_lock); | 302 | spin_unlock_bh(&bat_priv->tt_lhash_lock); |
291 | 303 | ||
292 | seq_printf(seq, "%s", buff); | 304 | seq_printf(seq, "%s", buff); |
293 | kfree(buff); | 305 | kfree(buff); |
294 | return 0; | 306 | out: |
307 | if (primary_if) | ||
308 | hardif_free_ref(primary_if); | ||
309 | return ret; | ||
295 | } | 310 | } |
296 | 311 | ||
297 | static void _hna_local_del(struct hlist_node *node, void *arg) | 312 | static void _tt_local_del(struct hlist_node *node, void *arg) |
298 | { | 313 | { |
299 | struct bat_priv *bat_priv = (struct bat_priv *)arg; | 314 | struct bat_priv *bat_priv = (struct bat_priv *)arg; |
300 | void *data = container_of(node, struct hna_local_entry, hash_entry); | 315 | void *data = container_of(node, struct tt_local_entry, hash_entry); |
301 | 316 | ||
302 | kfree(data); | 317 | kfree(data); |
303 | bat_priv->num_local_hna--; | 318 | bat_priv->num_local_tt--; |
304 | atomic_set(&bat_priv->hna_local_changed, 1); | 319 | atomic_set(&bat_priv->tt_local_changed, 1); |
305 | } | 320 | } |
306 | 321 | ||
307 | static void hna_local_del(struct bat_priv *bat_priv, | 322 | static void tt_local_del(struct bat_priv *bat_priv, |
308 | struct hna_local_entry *hna_local_entry, | 323 | struct tt_local_entry *tt_local_entry, |
309 | char *message) | 324 | char *message) |
310 | { | 325 | { |
311 | bat_dbg(DBG_ROUTES, bat_priv, "Deleting local hna entry (%pM): %s\n", | 326 | bat_dbg(DBG_ROUTES, bat_priv, "Deleting local tt entry (%pM): %s\n", |
312 | hna_local_entry->addr, message); | 327 | tt_local_entry->addr, message); |
313 | 328 | ||
314 | hash_remove(bat_priv->hna_local_hash, compare_lhna, choose_orig, | 329 | hash_remove(bat_priv->tt_local_hash, compare_ltt, choose_orig, |
315 | hna_local_entry->addr); | 330 | tt_local_entry->addr); |
316 | _hna_local_del(&hna_local_entry->hash_entry, bat_priv); | 331 | _tt_local_del(&tt_local_entry->hash_entry, bat_priv); |
317 | } | 332 | } |
318 | 333 | ||
319 | void hna_local_remove(struct bat_priv *bat_priv, | 334 | void tt_local_remove(struct bat_priv *bat_priv, |
320 | uint8_t *addr, char *message) | 335 | uint8_t *addr, char *message) |
321 | { | 336 | { |
322 | struct hna_local_entry *hna_local_entry; | 337 | struct tt_local_entry *tt_local_entry; |
323 | 338 | ||
324 | spin_lock_bh(&bat_priv->hna_lhash_lock); | 339 | spin_lock_bh(&bat_priv->tt_lhash_lock); |
325 | 340 | ||
326 | hna_local_entry = hna_local_hash_find(bat_priv, addr); | 341 | tt_local_entry = tt_local_hash_find(bat_priv, addr); |
327 | 342 | ||
328 | if (hna_local_entry) | 343 | if (tt_local_entry) |
329 | hna_local_del(bat_priv, hna_local_entry, message); | 344 | tt_local_del(bat_priv, tt_local_entry, message); |
330 | 345 | ||
331 | spin_unlock_bh(&bat_priv->hna_lhash_lock); | 346 | spin_unlock_bh(&bat_priv->tt_lhash_lock); |
332 | } | 347 | } |
333 | 348 | ||
334 | static void hna_local_purge(struct work_struct *work) | 349 | static void tt_local_purge(struct work_struct *work) |
335 | { | 350 | { |
336 | struct delayed_work *delayed_work = | 351 | struct delayed_work *delayed_work = |
337 | container_of(work, struct delayed_work, work); | 352 | container_of(work, struct delayed_work, work); |
338 | struct bat_priv *bat_priv = | 353 | struct bat_priv *bat_priv = |
339 | container_of(delayed_work, struct bat_priv, hna_work); | 354 | container_of(delayed_work, struct bat_priv, tt_work); |
340 | struct hashtable_t *hash = bat_priv->hna_local_hash; | 355 | struct hashtable_t *hash = bat_priv->tt_local_hash; |
341 | struct hna_local_entry *hna_local_entry; | 356 | struct tt_local_entry *tt_local_entry; |
342 | struct hlist_node *node, *node_tmp; | 357 | struct hlist_node *node, *node_tmp; |
343 | struct hlist_head *head; | 358 | struct hlist_head *head; |
344 | unsigned long timeout; | 359 | unsigned long timeout; |
345 | int i; | 360 | int i; |
346 | 361 | ||
347 | spin_lock_bh(&bat_priv->hna_lhash_lock); | 362 | spin_lock_bh(&bat_priv->tt_lhash_lock); |
348 | 363 | ||
349 | for (i = 0; i < hash->size; i++) { | 364 | for (i = 0; i < hash->size; i++) { |
350 | head = &hash->table[i]; | 365 | head = &hash->table[i]; |
351 | 366 | ||
352 | hlist_for_each_entry_safe(hna_local_entry, node, node_tmp, | 367 | hlist_for_each_entry_safe(tt_local_entry, node, node_tmp, |
353 | head, hash_entry) { | 368 | head, hash_entry) { |
354 | if (hna_local_entry->never_purge) | 369 | if (tt_local_entry->never_purge) |
355 | continue; | 370 | continue; |
356 | 371 | ||
357 | timeout = hna_local_entry->last_seen; | 372 | timeout = tt_local_entry->last_seen; |
358 | timeout += LOCAL_HNA_TIMEOUT * HZ; | 373 | timeout += TT_LOCAL_TIMEOUT * HZ; |
359 | 374 | ||
360 | if (time_before(jiffies, timeout)) | 375 | if (time_before(jiffies, timeout)) |
361 | continue; | 376 | continue; |
362 | 377 | ||
363 | hna_local_del(bat_priv, hna_local_entry, | 378 | tt_local_del(bat_priv, tt_local_entry, |
364 | "address timed out"); | 379 | "address timed out"); |
365 | } | 380 | } |
366 | } | 381 | } |
367 | 382 | ||
368 | spin_unlock_bh(&bat_priv->hna_lhash_lock); | 383 | spin_unlock_bh(&bat_priv->tt_lhash_lock); |
369 | hna_local_start_timer(bat_priv); | 384 | tt_local_start_timer(bat_priv); |
370 | } | 385 | } |
371 | 386 | ||
372 | void hna_local_free(struct bat_priv *bat_priv) | 387 | void tt_local_free(struct bat_priv *bat_priv) |
373 | { | 388 | { |
374 | if (!bat_priv->hna_local_hash) | 389 | if (!bat_priv->tt_local_hash) |
375 | return; | 390 | return; |
376 | 391 | ||
377 | cancel_delayed_work_sync(&bat_priv->hna_work); | 392 | cancel_delayed_work_sync(&bat_priv->tt_work); |
378 | hash_delete(bat_priv->hna_local_hash, _hna_local_del, bat_priv); | 393 | hash_delete(bat_priv->tt_local_hash, _tt_local_del, bat_priv); |
379 | bat_priv->hna_local_hash = NULL; | 394 | bat_priv->tt_local_hash = NULL; |
380 | } | 395 | } |
381 | 396 | ||
382 | int hna_global_init(struct bat_priv *bat_priv) | 397 | int tt_global_init(struct bat_priv *bat_priv) |
383 | { | 398 | { |
384 | if (bat_priv->hna_global_hash) | 399 | if (bat_priv->tt_global_hash) |
385 | return 1; | 400 | return 1; |
386 | 401 | ||
387 | bat_priv->hna_global_hash = hash_new(1024); | 402 | bat_priv->tt_global_hash = hash_new(1024); |
388 | 403 | ||
389 | if (!bat_priv->hna_global_hash) | 404 | if (!bat_priv->tt_global_hash) |
390 | return 0; | 405 | return 0; |
391 | 406 | ||
392 | return 1; | 407 | return 1; |
393 | } | 408 | } |
394 | 409 | ||
395 | void hna_global_add_orig(struct bat_priv *bat_priv, | 410 | void tt_global_add_orig(struct bat_priv *bat_priv, |
396 | struct orig_node *orig_node, | 411 | struct orig_node *orig_node, |
397 | unsigned char *hna_buff, int hna_buff_len) | 412 | unsigned char *tt_buff, int tt_buff_len) |
398 | { | 413 | { |
399 | struct hna_global_entry *hna_global_entry; | 414 | struct tt_global_entry *tt_global_entry; |
400 | struct hna_local_entry *hna_local_entry; | 415 | struct tt_local_entry *tt_local_entry; |
401 | int hna_buff_count = 0; | 416 | int tt_buff_count = 0; |
402 | unsigned char *hna_ptr; | 417 | unsigned char *tt_ptr; |
403 | 418 | ||
404 | while ((hna_buff_count + 1) * ETH_ALEN <= hna_buff_len) { | 419 | while ((tt_buff_count + 1) * ETH_ALEN <= tt_buff_len) { |
405 | spin_lock_bh(&bat_priv->hna_ghash_lock); | 420 | spin_lock_bh(&bat_priv->tt_ghash_lock); |
406 | 421 | ||
407 | hna_ptr = hna_buff + (hna_buff_count * ETH_ALEN); | 422 | tt_ptr = tt_buff + (tt_buff_count * ETH_ALEN); |
408 | hna_global_entry = hna_global_hash_find(bat_priv, hna_ptr); | 423 | tt_global_entry = tt_global_hash_find(bat_priv, tt_ptr); |
409 | 424 | ||
410 | if (!hna_global_entry) { | 425 | if (!tt_global_entry) { |
411 | spin_unlock_bh(&bat_priv->hna_ghash_lock); | 426 | spin_unlock_bh(&bat_priv->tt_ghash_lock); |
412 | 427 | ||
413 | hna_global_entry = | 428 | tt_global_entry = |
414 | kmalloc(sizeof(struct hna_global_entry), | 429 | kmalloc(sizeof(struct tt_global_entry), |
415 | GFP_ATOMIC); | 430 | GFP_ATOMIC); |
416 | 431 | ||
417 | if (!hna_global_entry) | 432 | if (!tt_global_entry) |
418 | break; | 433 | break; |
419 | 434 | ||
420 | memcpy(hna_global_entry->addr, hna_ptr, ETH_ALEN); | 435 | memcpy(tt_global_entry->addr, tt_ptr, ETH_ALEN); |
421 | 436 | ||
422 | bat_dbg(DBG_ROUTES, bat_priv, | 437 | bat_dbg(DBG_ROUTES, bat_priv, |
423 | "Creating new global hna entry: " | 438 | "Creating new global tt entry: " |
424 | "%pM (via %pM)\n", | 439 | "%pM (via %pM)\n", |
425 | hna_global_entry->addr, orig_node->orig); | 440 | tt_global_entry->addr, orig_node->orig); |
426 | 441 | ||
427 | spin_lock_bh(&bat_priv->hna_ghash_lock); | 442 | spin_lock_bh(&bat_priv->tt_ghash_lock); |
428 | hash_add(bat_priv->hna_global_hash, compare_ghna, | 443 | hash_add(bat_priv->tt_global_hash, compare_gtt, |
429 | choose_orig, hna_global_entry, | 444 | choose_orig, tt_global_entry, |
430 | &hna_global_entry->hash_entry); | 445 | &tt_global_entry->hash_entry); |
431 | 446 | ||
432 | } | 447 | } |
433 | 448 | ||
434 | hna_global_entry->orig_node = orig_node; | 449 | tt_global_entry->orig_node = orig_node; |
435 | spin_unlock_bh(&bat_priv->hna_ghash_lock); | 450 | spin_unlock_bh(&bat_priv->tt_ghash_lock); |
436 | 451 | ||
437 | /* remove address from local hash if present */ | 452 | /* remove address from local hash if present */ |
438 | spin_lock_bh(&bat_priv->hna_lhash_lock); | 453 | spin_lock_bh(&bat_priv->tt_lhash_lock); |
439 | 454 | ||
440 | hna_ptr = hna_buff + (hna_buff_count * ETH_ALEN); | 455 | tt_ptr = tt_buff + (tt_buff_count * ETH_ALEN); |
441 | hna_local_entry = hna_local_hash_find(bat_priv, hna_ptr); | 456 | tt_local_entry = tt_local_hash_find(bat_priv, tt_ptr); |
442 | 457 | ||
443 | if (hna_local_entry) | 458 | if (tt_local_entry) |
444 | hna_local_del(bat_priv, hna_local_entry, | 459 | tt_local_del(bat_priv, tt_local_entry, |
445 | "global hna received"); | 460 | "global tt received"); |
446 | 461 | ||
447 | spin_unlock_bh(&bat_priv->hna_lhash_lock); | 462 | spin_unlock_bh(&bat_priv->tt_lhash_lock); |
448 | 463 | ||
449 | hna_buff_count++; | 464 | tt_buff_count++; |
450 | } | 465 | } |
451 | 466 | ||
452 | /* initialize, and overwrite if malloc succeeds */ | 467 | /* initialize, and overwrite if malloc succeeds */ |
453 | orig_node->hna_buff = NULL; | 468 | orig_node->tt_buff = NULL; |
454 | orig_node->hna_buff_len = 0; | 469 | orig_node->tt_buff_len = 0; |
455 | 470 | ||
456 | if (hna_buff_len > 0) { | 471 | if (tt_buff_len > 0) { |
457 | orig_node->hna_buff = kmalloc(hna_buff_len, GFP_ATOMIC); | 472 | orig_node->tt_buff = kmalloc(tt_buff_len, GFP_ATOMIC); |
458 | if (orig_node->hna_buff) { | 473 | if (orig_node->tt_buff) { |
459 | memcpy(orig_node->hna_buff, hna_buff, hna_buff_len); | 474 | memcpy(orig_node->tt_buff, tt_buff, tt_buff_len); |
460 | orig_node->hna_buff_len = hna_buff_len; | 475 | orig_node->tt_buff_len = tt_buff_len; |
461 | } | 476 | } |
462 | } | 477 | } |
463 | } | 478 | } |
464 | 479 | ||
465 | int hna_global_seq_print_text(struct seq_file *seq, void *offset) | 480 | int tt_global_seq_print_text(struct seq_file *seq, void *offset) |
466 | { | 481 | { |
467 | struct net_device *net_dev = (struct net_device *)seq->private; | 482 | struct net_device *net_dev = (struct net_device *)seq->private; |
468 | struct bat_priv *bat_priv = netdev_priv(net_dev); | 483 | struct bat_priv *bat_priv = netdev_priv(net_dev); |
469 | struct hashtable_t *hash = bat_priv->hna_global_hash; | 484 | struct hashtable_t *hash = bat_priv->tt_global_hash; |
470 | struct hna_global_entry *hna_global_entry; | 485 | struct tt_global_entry *tt_global_entry; |
486 | struct hard_iface *primary_if; | ||
471 | struct hlist_node *node; | 487 | struct hlist_node *node; |
472 | struct hlist_head *head; | 488 | struct hlist_head *head; |
473 | size_t buf_size, pos; | 489 | size_t buf_size, pos; |
474 | char *buff; | 490 | char *buff; |
475 | int i; | 491 | int i, ret = 0; |
476 | 492 | ||
477 | if (!bat_priv->primary_if) { | 493 | primary_if = primary_if_get_selected(bat_priv); |
478 | return seq_printf(seq, "BATMAN mesh %s disabled - " | 494 | if (!primary_if) { |
479 | "please specify interfaces to enable it\n", | 495 | ret = seq_printf(seq, "BATMAN mesh %s disabled - please " |
480 | net_dev->name); | 496 | "specify interfaces to enable it\n", |
497 | net_dev->name); | ||
498 | goto out; | ||
481 | } | 499 | } |
482 | 500 | ||
483 | seq_printf(seq, "Globally announced HNAs received via the mesh %s\n", | 501 | if (primary_if->if_status != IF_ACTIVE) { |
502 | ret = seq_printf(seq, "BATMAN mesh %s disabled - " | ||
503 | "primary interface not active\n", | ||
504 | net_dev->name); | ||
505 | goto out; | ||
506 | } | ||
507 | |||
508 | seq_printf(seq, | ||
509 | "Globally announced TT entries received via the mesh %s\n", | ||
484 | net_dev->name); | 510 | net_dev->name); |
485 | 511 | ||
486 | spin_lock_bh(&bat_priv->hna_ghash_lock); | 512 | spin_lock_bh(&bat_priv->tt_ghash_lock); |
487 | 513 | ||
488 | buf_size = 1; | 514 | buf_size = 1; |
489 | /* Estimate length for: " * xx:xx:xx:xx:xx:xx via xx:xx:xx:xx:xx:xx\n"*/ | 515 | /* Estimate length for: " * xx:xx:xx:xx:xx:xx via xx:xx:xx:xx:xx:xx\n"*/ |
@@ -498,8 +524,9 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset) | |||
498 | 524 | ||
499 | buff = kmalloc(buf_size, GFP_ATOMIC); | 525 | buff = kmalloc(buf_size, GFP_ATOMIC); |
500 | if (!buff) { | 526 | if (!buff) { |
501 | spin_unlock_bh(&bat_priv->hna_ghash_lock); | 527 | spin_unlock_bh(&bat_priv->tt_ghash_lock); |
502 | return -ENOMEM; | 528 | ret = -ENOMEM; |
529 | goto out; | ||
503 | } | 530 | } |
504 | buff[0] = '\0'; | 531 | buff[0] = '\0'; |
505 | pos = 0; | 532 | pos = 0; |
@@ -508,101 +535,104 @@ int hna_global_seq_print_text(struct seq_file *seq, void *offset) | |||
508 | head = &hash->table[i]; | 535 | head = &hash->table[i]; |
509 | 536 | ||
510 | rcu_read_lock(); | 537 | rcu_read_lock(); |
511 | hlist_for_each_entry_rcu(hna_global_entry, node, | 538 | hlist_for_each_entry_rcu(tt_global_entry, node, |
512 | head, hash_entry) { | 539 | head, hash_entry) { |
513 | pos += snprintf(buff + pos, 44, | 540 | pos += snprintf(buff + pos, 44, |
514 | " * %pM via %pM\n", | 541 | " * %pM via %pM\n", |
515 | hna_global_entry->addr, | 542 | tt_global_entry->addr, |
516 | hna_global_entry->orig_node->orig); | 543 | tt_global_entry->orig_node->orig); |
517 | } | 544 | } |
518 | rcu_read_unlock(); | 545 | rcu_read_unlock(); |
519 | } | 546 | } |
520 | 547 | ||
521 | spin_unlock_bh(&bat_priv->hna_ghash_lock); | 548 | spin_unlock_bh(&bat_priv->tt_ghash_lock); |
522 | 549 | ||
523 | seq_printf(seq, "%s", buff); | 550 | seq_printf(seq, "%s", buff); |
524 | kfree(buff); | 551 | kfree(buff); |
525 | return 0; | 552 | out: |
553 | if (primary_if) | ||
554 | hardif_free_ref(primary_if); | ||
555 | return ret; | ||
526 | } | 556 | } |
527 | 557 | ||
528 | static void _hna_global_del_orig(struct bat_priv *bat_priv, | 558 | static void _tt_global_del_orig(struct bat_priv *bat_priv, |
529 | struct hna_global_entry *hna_global_entry, | 559 | struct tt_global_entry *tt_global_entry, |
530 | char *message) | 560 | char *message) |
531 | { | 561 | { |
532 | bat_dbg(DBG_ROUTES, bat_priv, | 562 | bat_dbg(DBG_ROUTES, bat_priv, |
533 | "Deleting global hna entry %pM (via %pM): %s\n", | 563 | "Deleting global tt entry %pM (via %pM): %s\n", |
534 | hna_global_entry->addr, hna_global_entry->orig_node->orig, | 564 | tt_global_entry->addr, tt_global_entry->orig_node->orig, |
535 | message); | 565 | message); |
536 | 566 | ||
537 | hash_remove(bat_priv->hna_global_hash, compare_ghna, choose_orig, | 567 | hash_remove(bat_priv->tt_global_hash, compare_gtt, choose_orig, |
538 | hna_global_entry->addr); | 568 | tt_global_entry->addr); |
539 | kfree(hna_global_entry); | 569 | kfree(tt_global_entry); |
540 | } | 570 | } |
541 | 571 | ||
542 | void hna_global_del_orig(struct bat_priv *bat_priv, | 572 | void tt_global_del_orig(struct bat_priv *bat_priv, |
543 | struct orig_node *orig_node, char *message) | 573 | struct orig_node *orig_node, char *message) |
544 | { | 574 | { |
545 | struct hna_global_entry *hna_global_entry; | 575 | struct tt_global_entry *tt_global_entry; |
546 | int hna_buff_count = 0; | 576 | int tt_buff_count = 0; |
547 | unsigned char *hna_ptr; | 577 | unsigned char *tt_ptr; |
548 | 578 | ||
549 | if (orig_node->hna_buff_len == 0) | 579 | if (orig_node->tt_buff_len == 0) |
550 | return; | 580 | return; |
551 | 581 | ||
552 | spin_lock_bh(&bat_priv->hna_ghash_lock); | 582 | spin_lock_bh(&bat_priv->tt_ghash_lock); |
553 | 583 | ||
554 | while ((hna_buff_count + 1) * ETH_ALEN <= orig_node->hna_buff_len) { | 584 | while ((tt_buff_count + 1) * ETH_ALEN <= orig_node->tt_buff_len) { |
555 | hna_ptr = orig_node->hna_buff + (hna_buff_count * ETH_ALEN); | 585 | tt_ptr = orig_node->tt_buff + (tt_buff_count * ETH_ALEN); |
556 | hna_global_entry = hna_global_hash_find(bat_priv, hna_ptr); | 586 | tt_global_entry = tt_global_hash_find(bat_priv, tt_ptr); |
557 | 587 | ||
558 | if ((hna_global_entry) && | 588 | if ((tt_global_entry) && |
559 | (hna_global_entry->orig_node == orig_node)) | 589 | (tt_global_entry->orig_node == orig_node)) |
560 | _hna_global_del_orig(bat_priv, hna_global_entry, | 590 | _tt_global_del_orig(bat_priv, tt_global_entry, |
561 | message); | 591 | message); |
562 | 592 | ||
563 | hna_buff_count++; | 593 | tt_buff_count++; |
564 | } | 594 | } |
565 | 595 | ||
566 | spin_unlock_bh(&bat_priv->hna_ghash_lock); | 596 | spin_unlock_bh(&bat_priv->tt_ghash_lock); |
567 | 597 | ||
568 | orig_node->hna_buff_len = 0; | 598 | orig_node->tt_buff_len = 0; |
569 | kfree(orig_node->hna_buff); | 599 | kfree(orig_node->tt_buff); |
570 | orig_node->hna_buff = NULL; | 600 | orig_node->tt_buff = NULL; |
571 | } | 601 | } |
572 | 602 | ||
573 | static void hna_global_del(struct hlist_node *node, void *arg) | 603 | static void tt_global_del(struct hlist_node *node, void *arg) |
574 | { | 604 | { |
575 | void *data = container_of(node, struct hna_global_entry, hash_entry); | 605 | void *data = container_of(node, struct tt_global_entry, hash_entry); |
576 | 606 | ||
577 | kfree(data); | 607 | kfree(data); |
578 | } | 608 | } |
579 | 609 | ||
580 | void hna_global_free(struct bat_priv *bat_priv) | 610 | void tt_global_free(struct bat_priv *bat_priv) |
581 | { | 611 | { |
582 | if (!bat_priv->hna_global_hash) | 612 | if (!bat_priv->tt_global_hash) |
583 | return; | 613 | return; |
584 | 614 | ||
585 | hash_delete(bat_priv->hna_global_hash, hna_global_del, NULL); | 615 | hash_delete(bat_priv->tt_global_hash, tt_global_del, NULL); |
586 | bat_priv->hna_global_hash = NULL; | 616 | bat_priv->tt_global_hash = NULL; |
587 | } | 617 | } |
588 | 618 | ||
589 | struct orig_node *transtable_search(struct bat_priv *bat_priv, uint8_t *addr) | 619 | struct orig_node *transtable_search(struct bat_priv *bat_priv, uint8_t *addr) |
590 | { | 620 | { |
591 | struct hna_global_entry *hna_global_entry; | 621 | struct tt_global_entry *tt_global_entry; |
592 | struct orig_node *orig_node = NULL; | 622 | struct orig_node *orig_node = NULL; |
593 | 623 | ||
594 | spin_lock_bh(&bat_priv->hna_ghash_lock); | 624 | spin_lock_bh(&bat_priv->tt_ghash_lock); |
595 | hna_global_entry = hna_global_hash_find(bat_priv, addr); | 625 | tt_global_entry = tt_global_hash_find(bat_priv, addr); |
596 | 626 | ||
597 | if (!hna_global_entry) | 627 | if (!tt_global_entry) |
598 | goto out; | 628 | goto out; |
599 | 629 | ||
600 | if (!atomic_inc_not_zero(&hna_global_entry->orig_node->refcount)) | 630 | if (!atomic_inc_not_zero(&tt_global_entry->orig_node->refcount)) |
601 | goto out; | 631 | goto out; |
602 | 632 | ||
603 | orig_node = hna_global_entry->orig_node; | 633 | orig_node = tt_global_entry->orig_node; |
604 | 634 | ||
605 | out: | 635 | out: |
606 | spin_unlock_bh(&bat_priv->hna_ghash_lock); | 636 | spin_unlock_bh(&bat_priv->tt_ghash_lock); |
607 | return orig_node; | 637 | return orig_node; |
608 | } | 638 | } |
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h index f19931ca1457..46152c38cc95 100644 --- a/net/batman-adv/translation-table.h +++ b/net/batman-adv/translation-table.h | |||
@@ -22,22 +22,22 @@ | |||
22 | #ifndef _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ | 22 | #ifndef _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ |
23 | #define _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ | 23 | #define _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ |
24 | 24 | ||
25 | int hna_local_init(struct bat_priv *bat_priv); | 25 | int tt_local_init(struct bat_priv *bat_priv); |
26 | void hna_local_add(struct net_device *soft_iface, uint8_t *addr); | 26 | void tt_local_add(struct net_device *soft_iface, uint8_t *addr); |
27 | void hna_local_remove(struct bat_priv *bat_priv, | 27 | void tt_local_remove(struct bat_priv *bat_priv, |
28 | uint8_t *addr, char *message); | 28 | uint8_t *addr, char *message); |
29 | int hna_local_fill_buffer(struct bat_priv *bat_priv, | 29 | int tt_local_fill_buffer(struct bat_priv *bat_priv, |
30 | unsigned char *buff, int buff_len); | 30 | unsigned char *buff, int buff_len); |
31 | int hna_local_seq_print_text(struct seq_file *seq, void *offset); | 31 | int tt_local_seq_print_text(struct seq_file *seq, void *offset); |
32 | void hna_local_free(struct bat_priv *bat_priv); | 32 | void tt_local_free(struct bat_priv *bat_priv); |
33 | int hna_global_init(struct bat_priv *bat_priv); | 33 | int tt_global_init(struct bat_priv *bat_priv); |
34 | void hna_global_add_orig(struct bat_priv *bat_priv, | 34 | void tt_global_add_orig(struct bat_priv *bat_priv, |
35 | struct orig_node *orig_node, | 35 | struct orig_node *orig_node, |
36 | unsigned char *hna_buff, int hna_buff_len); | 36 | unsigned char *tt_buff, int tt_buff_len); |
37 | int hna_global_seq_print_text(struct seq_file *seq, void *offset); | 37 | int tt_global_seq_print_text(struct seq_file *seq, void *offset); |
38 | void hna_global_del_orig(struct bat_priv *bat_priv, | 38 | void tt_global_del_orig(struct bat_priv *bat_priv, |
39 | struct orig_node *orig_node, char *message); | 39 | struct orig_node *orig_node, char *message); |
40 | void hna_global_free(struct bat_priv *bat_priv); | 40 | void tt_global_free(struct bat_priv *bat_priv); |
41 | struct orig_node *transtable_search(struct bat_priv *bat_priv, uint8_t *addr); | 41 | struct orig_node *transtable_search(struct bat_priv *bat_priv, uint8_t *addr); |
42 | 42 | ||
43 | #endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */ | 43 | #endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */ |
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 83445cf0cc9f..fab70e8b16ee 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h | |||
@@ -67,7 +67,7 @@ struct hard_iface { | |||
67 | struct orig_node { | 67 | struct orig_node { |
68 | uint8_t orig[ETH_ALEN]; | 68 | uint8_t orig[ETH_ALEN]; |
69 | uint8_t primary_addr[ETH_ALEN]; | 69 | uint8_t primary_addr[ETH_ALEN]; |
70 | struct neigh_node *router; | 70 | struct neigh_node __rcu *router; /* rcu protected pointer */ |
71 | unsigned long *bcast_own; | 71 | unsigned long *bcast_own; |
72 | uint8_t *bcast_own_sum; | 72 | uint8_t *bcast_own_sum; |
73 | unsigned long last_valid; | 73 | unsigned long last_valid; |
@@ -75,25 +75,25 @@ struct orig_node { | |||
75 | unsigned long batman_seqno_reset; | 75 | unsigned long batman_seqno_reset; |
76 | uint8_t gw_flags; | 76 | uint8_t gw_flags; |
77 | uint8_t flags; | 77 | uint8_t flags; |
78 | unsigned char *hna_buff; | 78 | unsigned char *tt_buff; |
79 | int16_t hna_buff_len; | 79 | int16_t tt_buff_len; |
80 | uint32_t last_real_seqno; | 80 | uint32_t last_real_seqno; |
81 | uint8_t last_ttl; | 81 | uint8_t last_ttl; |
82 | unsigned long bcast_bits[NUM_WORDS]; | 82 | unsigned long bcast_bits[NUM_WORDS]; |
83 | uint32_t last_bcast_seqno; | 83 | uint32_t last_bcast_seqno; |
84 | struct hlist_head neigh_list; | 84 | struct hlist_head neigh_list; |
85 | struct list_head frag_list; | 85 | struct list_head frag_list; |
86 | spinlock_t neigh_list_lock; /* protects neighbor list */ | 86 | spinlock_t neigh_list_lock; /* protects neigh_list and router */ |
87 | atomic_t refcount; | 87 | atomic_t refcount; |
88 | struct rcu_head rcu; | 88 | struct rcu_head rcu; |
89 | struct hlist_node hash_entry; | 89 | struct hlist_node hash_entry; |
90 | struct bat_priv *bat_priv; | 90 | struct bat_priv *bat_priv; |
91 | unsigned long last_frag_packet; | 91 | unsigned long last_frag_packet; |
92 | spinlock_t ogm_cnt_lock; /* protects: bcast_own, bcast_own_sum, | 92 | /* ogm_cnt_lock protects: bcast_own, bcast_own_sum, |
93 | * neigh_node->real_bits, | 93 | * neigh_node->real_bits, neigh_node->real_packet_count */ |
94 | * neigh_node->real_packet_count */ | 94 | spinlock_t ogm_cnt_lock; |
95 | spinlock_t bcast_seqno_lock; /* protects bcast_bits, | 95 | /* bcast_seqno_lock protects bcast_bits, last_bcast_seqno */ |
96 | * last_bcast_seqno */ | 96 | spinlock_t bcast_seqno_lock; |
97 | atomic_t bond_candidates; | 97 | atomic_t bond_candidates; |
98 | struct list_head bond_list; | 98 | struct list_head bond_list; |
99 | }; | 99 | }; |
@@ -125,6 +125,7 @@ struct neigh_node { | |||
125 | struct rcu_head rcu; | 125 | struct rcu_head rcu; |
126 | struct orig_node *orig_node; | 126 | struct orig_node *orig_node; |
127 | struct hard_iface *if_incoming; | 127 | struct hard_iface *if_incoming; |
128 | spinlock_t tq_lock; /* protects: tq_recv, tq_index */ | ||
128 | }; | 129 | }; |
129 | 130 | ||
130 | 131 | ||
@@ -145,34 +146,34 @@ struct bat_priv { | |||
145 | atomic_t bcast_queue_left; | 146 | atomic_t bcast_queue_left; |
146 | atomic_t batman_queue_left; | 147 | atomic_t batman_queue_left; |
147 | char num_ifaces; | 148 | char num_ifaces; |
148 | struct hlist_head softif_neigh_list; | ||
149 | struct softif_neigh *softif_neigh; | ||
150 | struct debug_log *debug_log; | 149 | struct debug_log *debug_log; |
151 | struct hard_iface *primary_if; | ||
152 | struct kobject *mesh_obj; | 150 | struct kobject *mesh_obj; |
153 | struct dentry *debug_dir; | 151 | struct dentry *debug_dir; |
154 | struct hlist_head forw_bat_list; | 152 | struct hlist_head forw_bat_list; |
155 | struct hlist_head forw_bcast_list; | 153 | struct hlist_head forw_bcast_list; |
156 | struct hlist_head gw_list; | 154 | struct hlist_head gw_list; |
155 | struct hlist_head softif_neigh_vids; | ||
157 | struct list_head vis_send_list; | 156 | struct list_head vis_send_list; |
158 | struct hashtable_t *orig_hash; | 157 | struct hashtable_t *orig_hash; |
159 | struct hashtable_t *hna_local_hash; | 158 | struct hashtable_t *tt_local_hash; |
160 | struct hashtable_t *hna_global_hash; | 159 | struct hashtable_t *tt_global_hash; |
161 | struct hashtable_t *vis_hash; | 160 | struct hashtable_t *vis_hash; |
162 | spinlock_t forw_bat_list_lock; /* protects forw_bat_list */ | 161 | spinlock_t forw_bat_list_lock; /* protects forw_bat_list */ |
163 | spinlock_t forw_bcast_list_lock; /* protects */ | 162 | spinlock_t forw_bcast_list_lock; /* protects */ |
164 | spinlock_t hna_lhash_lock; /* protects hna_local_hash */ | 163 | spinlock_t tt_lhash_lock; /* protects tt_local_hash */ |
165 | spinlock_t hna_ghash_lock; /* protects hna_global_hash */ | 164 | spinlock_t tt_ghash_lock; /* protects tt_global_hash */ |
166 | spinlock_t gw_list_lock; /* protects gw_list and curr_gw */ | 165 | spinlock_t gw_list_lock; /* protects gw_list and curr_gw */ |
167 | spinlock_t vis_hash_lock; /* protects vis_hash */ | 166 | spinlock_t vis_hash_lock; /* protects vis_hash */ |
168 | spinlock_t vis_list_lock; /* protects vis_info::recv_list */ | 167 | spinlock_t vis_list_lock; /* protects vis_info::recv_list */ |
169 | spinlock_t softif_neigh_lock; /* protects soft-interface neigh list */ | 168 | spinlock_t softif_neigh_lock; /* protects soft-interface neigh list */ |
170 | int16_t num_local_hna; | 169 | spinlock_t softif_neigh_vid_lock; /* protects soft-interface vid list */ |
171 | atomic_t hna_local_changed; | 170 | int16_t num_local_tt; |
172 | struct delayed_work hna_work; | 171 | atomic_t tt_local_changed; |
172 | struct delayed_work tt_work; | ||
173 | struct delayed_work orig_work; | 173 | struct delayed_work orig_work; |
174 | struct delayed_work vis_work; | 174 | struct delayed_work vis_work; |
175 | struct gw_node __rcu *curr_gw; /* rcu protected pointer */ | 175 | struct gw_node __rcu *curr_gw; /* rcu protected pointer */ |
176 | struct hard_iface __rcu *primary_if; /* rcu protected pointer */ | ||
176 | struct vis_info *my_vis_info; | 177 | struct vis_info *my_vis_info; |
177 | }; | 178 | }; |
178 | 179 | ||
@@ -191,14 +192,14 @@ struct socket_packet { | |||
191 | struct icmp_packet_rr icmp_packet; | 192 | struct icmp_packet_rr icmp_packet; |
192 | }; | 193 | }; |
193 | 194 | ||
194 | struct hna_local_entry { | 195 | struct tt_local_entry { |
195 | uint8_t addr[ETH_ALEN]; | 196 | uint8_t addr[ETH_ALEN]; |
196 | unsigned long last_seen; | 197 | unsigned long last_seen; |
197 | char never_purge; | 198 | char never_purge; |
198 | struct hlist_node hash_entry; | 199 | struct hlist_node hash_entry; |
199 | }; | 200 | }; |
200 | 201 | ||
201 | struct hna_global_entry { | 202 | struct tt_global_entry { |
202 | uint8_t addr[ETH_ALEN]; | 203 | uint8_t addr[ETH_ALEN]; |
203 | struct orig_node *orig_node; | 204 | struct orig_node *orig_node; |
204 | struct hlist_node hash_entry; | 205 | struct hlist_node hash_entry; |
@@ -261,7 +262,7 @@ struct vis_info { | |||
261 | struct vis_info_entry { | 262 | struct vis_info_entry { |
262 | uint8_t src[ETH_ALEN]; | 263 | uint8_t src[ETH_ALEN]; |
263 | uint8_t dest[ETH_ALEN]; | 264 | uint8_t dest[ETH_ALEN]; |
264 | uint8_t quality; /* quality = 0 means HNA */ | 265 | uint8_t quality; /* quality = 0 client */ |
265 | } __packed; | 266 | } __packed; |
266 | 267 | ||
267 | struct recvlist_node { | 268 | struct recvlist_node { |
@@ -269,11 +270,20 @@ struct recvlist_node { | |||
269 | uint8_t mac[ETH_ALEN]; | 270 | uint8_t mac[ETH_ALEN]; |
270 | }; | 271 | }; |
271 | 272 | ||
273 | struct softif_neigh_vid { | ||
274 | struct hlist_node list; | ||
275 | struct bat_priv *bat_priv; | ||
276 | short vid; | ||
277 | atomic_t refcount; | ||
278 | struct softif_neigh __rcu *softif_neigh; | ||
279 | struct rcu_head rcu; | ||
280 | struct hlist_head softif_neigh_list; | ||
281 | }; | ||
282 | |||
272 | struct softif_neigh { | 283 | struct softif_neigh { |
273 | struct hlist_node list; | 284 | struct hlist_node list; |
274 | uint8_t addr[ETH_ALEN]; | 285 | uint8_t addr[ETH_ALEN]; |
275 | unsigned long last_seen; | 286 | unsigned long last_seen; |
276 | short vid; | ||
277 | atomic_t refcount; | 287 | atomic_t refcount; |
278 | struct rcu_head rcu; | 288 | struct rcu_head rcu; |
279 | }; | 289 | }; |
diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c index 19f84bd443af..19c3daf34ac6 100644 --- a/net/batman-adv/unicast.c +++ b/net/batman-adv/unicast.c | |||
@@ -221,15 +221,17 @@ int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv, | |||
221 | struct hard_iface *hard_iface, uint8_t dstaddr[]) | 221 | struct hard_iface *hard_iface, uint8_t dstaddr[]) |
222 | { | 222 | { |
223 | struct unicast_packet tmp_uc, *unicast_packet; | 223 | struct unicast_packet tmp_uc, *unicast_packet; |
224 | struct hard_iface *primary_if; | ||
224 | struct sk_buff *frag_skb; | 225 | struct sk_buff *frag_skb; |
225 | struct unicast_frag_packet *frag1, *frag2; | 226 | struct unicast_frag_packet *frag1, *frag2; |
226 | int uc_hdr_len = sizeof(struct unicast_packet); | 227 | int uc_hdr_len = sizeof(struct unicast_packet); |
227 | int ucf_hdr_len = sizeof(struct unicast_frag_packet); | 228 | int ucf_hdr_len = sizeof(struct unicast_frag_packet); |
228 | int data_len = skb->len - uc_hdr_len; | 229 | int data_len = skb->len - uc_hdr_len; |
229 | int large_tail = 0; | 230 | int large_tail = 0, ret = NET_RX_DROP; |
230 | uint16_t seqno; | 231 | uint16_t seqno; |
231 | 232 | ||
232 | if (!bat_priv->primary_if) | 233 | primary_if = primary_if_get_selected(bat_priv); |
234 | if (!primary_if) | ||
233 | goto dropped; | 235 | goto dropped; |
234 | 236 | ||
235 | frag_skb = dev_alloc_skb(data_len - (data_len / 2) + ucf_hdr_len); | 237 | frag_skb = dev_alloc_skb(data_len - (data_len / 2) + ucf_hdr_len); |
@@ -254,7 +256,7 @@ int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv, | |||
254 | frag1->version = COMPAT_VERSION; | 256 | frag1->version = COMPAT_VERSION; |
255 | frag1->packet_type = BAT_UNICAST_FRAG; | 257 | frag1->packet_type = BAT_UNICAST_FRAG; |
256 | 258 | ||
257 | memcpy(frag1->orig, bat_priv->primary_if->net_dev->dev_addr, ETH_ALEN); | 259 | memcpy(frag1->orig, primary_if->net_dev->dev_addr, ETH_ALEN); |
258 | memcpy(frag2, frag1, sizeof(struct unicast_frag_packet)); | 260 | memcpy(frag2, frag1, sizeof(struct unicast_frag_packet)); |
259 | 261 | ||
260 | if (data_len & 1) | 262 | if (data_len & 1) |
@@ -269,13 +271,17 @@ int frag_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv, | |||
269 | 271 | ||
270 | send_skb_packet(skb, hard_iface, dstaddr); | 272 | send_skb_packet(skb, hard_iface, dstaddr); |
271 | send_skb_packet(frag_skb, hard_iface, dstaddr); | 273 | send_skb_packet(frag_skb, hard_iface, dstaddr); |
272 | return NET_RX_SUCCESS; | 274 | ret = NET_RX_SUCCESS; |
275 | goto out; | ||
273 | 276 | ||
274 | drop_frag: | 277 | drop_frag: |
275 | kfree_skb(frag_skb); | 278 | kfree_skb(frag_skb); |
276 | dropped: | 279 | dropped: |
277 | kfree_skb(skb); | 280 | kfree_skb(skb); |
278 | return NET_RX_DROP; | 281 | out: |
282 | if (primary_if) | ||
283 | hardif_free_ref(primary_if); | ||
284 | return ret; | ||
279 | } | 285 | } |
280 | 286 | ||
281 | int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) | 287 | int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) |
@@ -289,12 +295,12 @@ int unicast_send_skb(struct sk_buff *skb, struct bat_priv *bat_priv) | |||
289 | 295 | ||
290 | /* get routing information */ | 296 | /* get routing information */ |
291 | if (is_multicast_ether_addr(ethhdr->h_dest)) { | 297 | if (is_multicast_ether_addr(ethhdr->h_dest)) { |
292 | orig_node = (struct orig_node *)gw_get_selected(bat_priv); | 298 | orig_node = (struct orig_node *)gw_get_selected_orig(bat_priv); |
293 | if (orig_node) | 299 | if (orig_node) |
294 | goto find_router; | 300 | goto find_router; |
295 | } | 301 | } |
296 | 302 | ||
297 | /* check for hna host - increases orig_node refcount */ | 303 | /* check for tt host - increases orig_node refcount */ |
298 | orig_node = transtable_search(bat_priv, ethhdr->h_dest); | 304 | orig_node = transtable_search(bat_priv, ethhdr->h_dest); |
299 | 305 | ||
300 | find_router: | 306 | find_router: |
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c index f90212f42082..c39f20cc1ba6 100644 --- a/net/batman-adv/vis.c +++ b/net/batman-adv/vis.c | |||
@@ -194,7 +194,7 @@ static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry, | |||
194 | { | 194 | { |
195 | /* maximal length: max(4+17+2, 3+17+1+3+2) == 26 */ | 195 | /* maximal length: max(4+17+2, 3+17+1+3+2) == 26 */ |
196 | if (primary && entry->quality == 0) | 196 | if (primary && entry->quality == 0) |
197 | return sprintf(buff, "HNA %pM, ", entry->dest); | 197 | return sprintf(buff, "TT %pM, ", entry->dest); |
198 | else if (compare_eth(entry->src, src)) | 198 | else if (compare_eth(entry->src, src)) |
199 | return sprintf(buff, "TQ %pM %d, ", entry->dest, | 199 | return sprintf(buff, "TQ %pM %d, ", entry->dest, |
200 | entry->quality); | 200 | entry->quality); |
@@ -204,6 +204,7 @@ static ssize_t vis_data_read_entry(char *buff, struct vis_info_entry *entry, | |||
204 | 204 | ||
205 | int vis_seq_print_text(struct seq_file *seq, void *offset) | 205 | int vis_seq_print_text(struct seq_file *seq, void *offset) |
206 | { | 206 | { |
207 | struct hard_iface *primary_if; | ||
207 | struct hlist_node *node; | 208 | struct hlist_node *node; |
208 | struct hlist_head *head; | 209 | struct hlist_head *head; |
209 | struct vis_info *info; | 210 | struct vis_info *info; |
@@ -215,15 +216,18 @@ int vis_seq_print_text(struct seq_file *seq, void *offset) | |||
215 | HLIST_HEAD(vis_if_list); | 216 | HLIST_HEAD(vis_if_list); |
216 | struct if_list_entry *entry; | 217 | struct if_list_entry *entry; |
217 | struct hlist_node *pos, *n; | 218 | struct hlist_node *pos, *n; |
218 | int i, j; | 219 | int i, j, ret = 0; |
219 | int vis_server = atomic_read(&bat_priv->vis_mode); | 220 | int vis_server = atomic_read(&bat_priv->vis_mode); |
220 | size_t buff_pos, buf_size; | 221 | size_t buff_pos, buf_size; |
221 | char *buff; | 222 | char *buff; |
222 | int compare; | 223 | int compare; |
223 | 224 | ||
224 | if ((!bat_priv->primary_if) || | 225 | primary_if = primary_if_get_selected(bat_priv); |
225 | (vis_server == VIS_TYPE_CLIENT_UPDATE)) | 226 | if (!primary_if) |
226 | return 0; | 227 | goto out; |
228 | |||
229 | if (vis_server == VIS_TYPE_CLIENT_UPDATE) | ||
230 | goto out; | ||
227 | 231 | ||
228 | buf_size = 1; | 232 | buf_size = 1; |
229 | /* Estimate length */ | 233 | /* Estimate length */ |
@@ -270,7 +274,8 @@ int vis_seq_print_text(struct seq_file *seq, void *offset) | |||
270 | buff = kmalloc(buf_size, GFP_ATOMIC); | 274 | buff = kmalloc(buf_size, GFP_ATOMIC); |
271 | if (!buff) { | 275 | if (!buff) { |
272 | spin_unlock_bh(&bat_priv->vis_hash_lock); | 276 | spin_unlock_bh(&bat_priv->vis_hash_lock); |
273 | return -ENOMEM; | 277 | ret = -ENOMEM; |
278 | goto out; | ||
274 | } | 279 | } |
275 | buff[0] = '\0'; | 280 | buff[0] = '\0'; |
276 | buff_pos = 0; | 281 | buff_pos = 0; |
@@ -328,7 +333,10 @@ int vis_seq_print_text(struct seq_file *seq, void *offset) | |||
328 | seq_printf(seq, "%s", buff); | 333 | seq_printf(seq, "%s", buff); |
329 | kfree(buff); | 334 | kfree(buff); |
330 | 335 | ||
331 | return 0; | 336 | out: |
337 | if (primary_if) | ||
338 | hardif_free_ref(primary_if); | ||
339 | return ret; | ||
332 | } | 340 | } |
333 | 341 | ||
334 | /* add the info packet to the send list, if it was not | 342 | /* add the info packet to the send list, if it was not |
@@ -558,6 +566,7 @@ static int find_best_vis_server(struct bat_priv *bat_priv, | |||
558 | struct vis_info *info) | 566 | struct vis_info *info) |
559 | { | 567 | { |
560 | struct hashtable_t *hash = bat_priv->orig_hash; | 568 | struct hashtable_t *hash = bat_priv->orig_hash; |
569 | struct neigh_node *router; | ||
561 | struct hlist_node *node; | 570 | struct hlist_node *node; |
562 | struct hlist_head *head; | 571 | struct hlist_head *head; |
563 | struct orig_node *orig_node; | 572 | struct orig_node *orig_node; |
@@ -571,13 +580,17 @@ static int find_best_vis_server(struct bat_priv *bat_priv, | |||
571 | 580 | ||
572 | rcu_read_lock(); | 581 | rcu_read_lock(); |
573 | hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { | 582 | hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { |
574 | if ((orig_node) && (orig_node->router) && | 583 | router = orig_node_get_router(orig_node); |
575 | (orig_node->flags & VIS_SERVER) && | 584 | if (!router) |
576 | (orig_node->router->tq_avg > best_tq)) { | 585 | continue; |
577 | best_tq = orig_node->router->tq_avg; | 586 | |
587 | if ((orig_node->flags & VIS_SERVER) && | ||
588 | (router->tq_avg > best_tq)) { | ||
589 | best_tq = router->tq_avg; | ||
578 | memcpy(packet->target_orig, orig_node->orig, | 590 | memcpy(packet->target_orig, orig_node->orig, |
579 | ETH_ALEN); | 591 | ETH_ALEN); |
580 | } | 592 | } |
593 | neigh_node_free_ref(router); | ||
581 | } | 594 | } |
582 | rcu_read_unlock(); | 595 | rcu_read_unlock(); |
583 | } | 596 | } |
@@ -605,11 +618,11 @@ static int generate_vis_packet(struct bat_priv *bat_priv) | |||
605 | struct hlist_node *node; | 618 | struct hlist_node *node; |
606 | struct hlist_head *head; | 619 | struct hlist_head *head; |
607 | struct orig_node *orig_node; | 620 | struct orig_node *orig_node; |
608 | struct neigh_node *neigh_node; | 621 | struct neigh_node *router; |
609 | struct vis_info *info = (struct vis_info *)bat_priv->my_vis_info; | 622 | struct vis_info *info = (struct vis_info *)bat_priv->my_vis_info; |
610 | struct vis_packet *packet = (struct vis_packet *)info->skb_packet->data; | 623 | struct vis_packet *packet = (struct vis_packet *)info->skb_packet->data; |
611 | struct vis_info_entry *entry; | 624 | struct vis_info_entry *entry; |
612 | struct hna_local_entry *hna_local_entry; | 625 | struct tt_local_entry *tt_local_entry; |
613 | int best_tq = -1, i; | 626 | int best_tq = -1, i; |
614 | 627 | ||
615 | info->first_seen = jiffies; | 628 | info->first_seen = jiffies; |
@@ -633,59 +646,61 @@ static int generate_vis_packet(struct bat_priv *bat_priv) | |||
633 | 646 | ||
634 | rcu_read_lock(); | 647 | rcu_read_lock(); |
635 | hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { | 648 | hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { |
636 | neigh_node = orig_node->router; | 649 | router = orig_node_get_router(orig_node); |
637 | 650 | if (!router) | |
638 | if (!neigh_node) | ||
639 | continue; | 651 | continue; |
640 | 652 | ||
641 | if (!compare_eth(neigh_node->addr, orig_node->orig)) | 653 | if (!compare_eth(router->addr, orig_node->orig)) |
642 | continue; | 654 | goto next; |
643 | 655 | ||
644 | if (neigh_node->if_incoming->if_status != IF_ACTIVE) | 656 | if (router->if_incoming->if_status != IF_ACTIVE) |
645 | continue; | 657 | goto next; |
646 | 658 | ||
647 | if (neigh_node->tq_avg < 1) | 659 | if (router->tq_avg < 1) |
648 | continue; | 660 | goto next; |
649 | 661 | ||
650 | /* fill one entry into buffer. */ | 662 | /* fill one entry into buffer. */ |
651 | entry = (struct vis_info_entry *) | 663 | entry = (struct vis_info_entry *) |
652 | skb_put(info->skb_packet, sizeof(*entry)); | 664 | skb_put(info->skb_packet, sizeof(*entry)); |
653 | memcpy(entry->src, | 665 | memcpy(entry->src, |
654 | neigh_node->if_incoming->net_dev->dev_addr, | 666 | router->if_incoming->net_dev->dev_addr, |
655 | ETH_ALEN); | 667 | ETH_ALEN); |
656 | memcpy(entry->dest, orig_node->orig, ETH_ALEN); | 668 | memcpy(entry->dest, orig_node->orig, ETH_ALEN); |
657 | entry->quality = neigh_node->tq_avg; | 669 | entry->quality = router->tq_avg; |
658 | packet->entries++; | 670 | packet->entries++; |
659 | 671 | ||
672 | next: | ||
673 | neigh_node_free_ref(router); | ||
674 | |||
660 | if (vis_packet_full(info)) | 675 | if (vis_packet_full(info)) |
661 | goto unlock; | 676 | goto unlock; |
662 | } | 677 | } |
663 | rcu_read_unlock(); | 678 | rcu_read_unlock(); |
664 | } | 679 | } |
665 | 680 | ||
666 | hash = bat_priv->hna_local_hash; | 681 | hash = bat_priv->tt_local_hash; |
667 | 682 | ||
668 | spin_lock_bh(&bat_priv->hna_lhash_lock); | 683 | spin_lock_bh(&bat_priv->tt_lhash_lock); |
669 | for (i = 0; i < hash->size; i++) { | 684 | for (i = 0; i < hash->size; i++) { |
670 | head = &hash->table[i]; | 685 | head = &hash->table[i]; |
671 | 686 | ||
672 | hlist_for_each_entry(hna_local_entry, node, head, hash_entry) { | 687 | hlist_for_each_entry(tt_local_entry, node, head, hash_entry) { |
673 | entry = (struct vis_info_entry *) | 688 | entry = (struct vis_info_entry *) |
674 | skb_put(info->skb_packet, | 689 | skb_put(info->skb_packet, |
675 | sizeof(*entry)); | 690 | sizeof(*entry)); |
676 | memset(entry->src, 0, ETH_ALEN); | 691 | memset(entry->src, 0, ETH_ALEN); |
677 | memcpy(entry->dest, hna_local_entry->addr, ETH_ALEN); | 692 | memcpy(entry->dest, tt_local_entry->addr, ETH_ALEN); |
678 | entry->quality = 0; /* 0 means HNA */ | 693 | entry->quality = 0; /* 0 means TT */ |
679 | packet->entries++; | 694 | packet->entries++; |
680 | 695 | ||
681 | if (vis_packet_full(info)) { | 696 | if (vis_packet_full(info)) { |
682 | spin_unlock_bh(&bat_priv->hna_lhash_lock); | 697 | spin_unlock_bh(&bat_priv->tt_lhash_lock); |
683 | return 0; | 698 | return 0; |
684 | } | 699 | } |
685 | } | 700 | } |
686 | } | 701 | } |
687 | 702 | ||
688 | spin_unlock_bh(&bat_priv->hna_lhash_lock); | 703 | spin_unlock_bh(&bat_priv->tt_lhash_lock); |
689 | return 0; | 704 | return 0; |
690 | 705 | ||
691 | unlock: | 706 | unlock: |
@@ -725,6 +740,7 @@ static void purge_vis_packets(struct bat_priv *bat_priv) | |||
725 | static void broadcast_vis_packet(struct bat_priv *bat_priv, | 740 | static void broadcast_vis_packet(struct bat_priv *bat_priv, |
726 | struct vis_info *info) | 741 | struct vis_info *info) |
727 | { | 742 | { |
743 | struct neigh_node *router; | ||
728 | struct hashtable_t *hash = bat_priv->orig_hash; | 744 | struct hashtable_t *hash = bat_priv->orig_hash; |
729 | struct hlist_node *node; | 745 | struct hlist_node *node; |
730 | struct hlist_head *head; | 746 | struct hlist_head *head; |
@@ -745,19 +761,26 @@ static void broadcast_vis_packet(struct bat_priv *bat_priv, | |||
745 | rcu_read_lock(); | 761 | rcu_read_lock(); |
746 | hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { | 762 | hlist_for_each_entry_rcu(orig_node, node, head, hash_entry) { |
747 | /* if it's a vis server and reachable, send it. */ | 763 | /* if it's a vis server and reachable, send it. */ |
748 | if ((!orig_node) || (!orig_node->router)) | ||
749 | continue; | ||
750 | if (!(orig_node->flags & VIS_SERVER)) | 764 | if (!(orig_node->flags & VIS_SERVER)) |
751 | continue; | 765 | continue; |
766 | |||
767 | router = orig_node_get_router(orig_node); | ||
768 | if (!router) | ||
769 | continue; | ||
770 | |||
752 | /* don't send it if we already received the packet from | 771 | /* don't send it if we already received the packet from |
753 | * this node. */ | 772 | * this node. */ |
754 | if (recv_list_is_in(bat_priv, &info->recv_list, | 773 | if (recv_list_is_in(bat_priv, &info->recv_list, |
755 | orig_node->orig)) | 774 | orig_node->orig)) { |
775 | neigh_node_free_ref(router); | ||
756 | continue; | 776 | continue; |
777 | } | ||
757 | 778 | ||
758 | memcpy(packet->target_orig, orig_node->orig, ETH_ALEN); | 779 | memcpy(packet->target_orig, orig_node->orig, ETH_ALEN); |
759 | hard_iface = orig_node->router->if_incoming; | 780 | hard_iface = router->if_incoming; |
760 | memcpy(dstaddr, orig_node->router->addr, ETH_ALEN); | 781 | memcpy(dstaddr, router->addr, ETH_ALEN); |
782 | |||
783 | neigh_node_free_ref(router); | ||
761 | 784 | ||
762 | skb = skb_clone(info->skb_packet, GFP_ATOMIC); | 785 | skb = skb_clone(info->skb_packet, GFP_ATOMIC); |
763 | if (skb) | 786 | if (skb) |
@@ -772,60 +795,48 @@ static void unicast_vis_packet(struct bat_priv *bat_priv, | |||
772 | struct vis_info *info) | 795 | struct vis_info *info) |
773 | { | 796 | { |
774 | struct orig_node *orig_node; | 797 | struct orig_node *orig_node; |
775 | struct neigh_node *neigh_node = NULL; | 798 | struct neigh_node *router = NULL; |
776 | struct sk_buff *skb; | 799 | struct sk_buff *skb; |
777 | struct vis_packet *packet; | 800 | struct vis_packet *packet; |
778 | 801 | ||
779 | packet = (struct vis_packet *)info->skb_packet->data; | 802 | packet = (struct vis_packet *)info->skb_packet->data; |
780 | 803 | ||
781 | rcu_read_lock(); | ||
782 | orig_node = orig_hash_find(bat_priv, packet->target_orig); | 804 | orig_node = orig_hash_find(bat_priv, packet->target_orig); |
783 | |||
784 | if (!orig_node) | 805 | if (!orig_node) |
785 | goto unlock; | 806 | goto out; |
786 | |||
787 | neigh_node = orig_node->router; | ||
788 | 807 | ||
789 | if (!neigh_node) | 808 | router = orig_node_get_router(orig_node); |
790 | goto unlock; | 809 | if (!router) |
791 | 810 | goto out; | |
792 | if (!atomic_inc_not_zero(&neigh_node->refcount)) { | ||
793 | neigh_node = NULL; | ||
794 | goto unlock; | ||
795 | } | ||
796 | |||
797 | rcu_read_unlock(); | ||
798 | 811 | ||
799 | skb = skb_clone(info->skb_packet, GFP_ATOMIC); | 812 | skb = skb_clone(info->skb_packet, GFP_ATOMIC); |
800 | if (skb) | 813 | if (skb) |
801 | send_skb_packet(skb, neigh_node->if_incoming, | 814 | send_skb_packet(skb, router->if_incoming, router->addr); |
802 | neigh_node->addr); | ||
803 | 815 | ||
804 | goto out; | ||
805 | |||
806 | unlock: | ||
807 | rcu_read_unlock(); | ||
808 | out: | 816 | out: |
809 | if (neigh_node) | 817 | if (router) |
810 | neigh_node_free_ref(neigh_node); | 818 | neigh_node_free_ref(router); |
811 | if (orig_node) | 819 | if (orig_node) |
812 | orig_node_free_ref(orig_node); | 820 | orig_node_free_ref(orig_node); |
813 | return; | ||
814 | } | 821 | } |
815 | 822 | ||
816 | /* only send one vis packet. called from send_vis_packets() */ | 823 | /* only send one vis packet. called from send_vis_packets() */ |
817 | static void send_vis_packet(struct bat_priv *bat_priv, struct vis_info *info) | 824 | static void send_vis_packet(struct bat_priv *bat_priv, struct vis_info *info) |
818 | { | 825 | { |
826 | struct hard_iface *primary_if; | ||
819 | struct vis_packet *packet; | 827 | struct vis_packet *packet; |
820 | 828 | ||
829 | primary_if = primary_if_get_selected(bat_priv); | ||
830 | if (!primary_if) | ||
831 | goto out; | ||
832 | |||
821 | packet = (struct vis_packet *)info->skb_packet->data; | 833 | packet = (struct vis_packet *)info->skb_packet->data; |
822 | if (packet->ttl < 2) { | 834 | if (packet->ttl < 2) { |
823 | pr_debug("Error - can't send vis packet: ttl exceeded\n"); | 835 | pr_debug("Error - can't send vis packet: ttl exceeded\n"); |
824 | return; | 836 | goto out; |
825 | } | 837 | } |
826 | 838 | ||
827 | memcpy(packet->sender_orig, bat_priv->primary_if->net_dev->dev_addr, | 839 | memcpy(packet->sender_orig, primary_if->net_dev->dev_addr, ETH_ALEN); |
828 | ETH_ALEN); | ||
829 | packet->ttl--; | 840 | packet->ttl--; |
830 | 841 | ||
831 | if (is_broadcast_ether_addr(packet->target_orig)) | 842 | if (is_broadcast_ether_addr(packet->target_orig)) |
@@ -833,6 +844,10 @@ static void send_vis_packet(struct bat_priv *bat_priv, struct vis_info *info) | |||
833 | else | 844 | else |
834 | unicast_vis_packet(bat_priv, info); | 845 | unicast_vis_packet(bat_priv, info); |
835 | packet->ttl++; /* restore TTL */ | 846 | packet->ttl++; /* restore TTL */ |
847 | |||
848 | out: | ||
849 | if (primary_if) | ||
850 | hardif_free_ref(primary_if); | ||
836 | } | 851 | } |
837 | 852 | ||
838 | /* called from timer; send (and maybe generate) vis packet. */ | 853 | /* called from timer; send (and maybe generate) vis packet. */ |
@@ -859,8 +874,7 @@ static void send_vis_packets(struct work_struct *work) | |||
859 | kref_get(&info->refcount); | 874 | kref_get(&info->refcount); |
860 | spin_unlock_bh(&bat_priv->vis_hash_lock); | 875 | spin_unlock_bh(&bat_priv->vis_hash_lock); |
861 | 876 | ||
862 | if (bat_priv->primary_if) | 877 | send_vis_packet(bat_priv, info); |
863 | send_vis_packet(bat_priv, info); | ||
864 | 878 | ||
865 | spin_lock_bh(&bat_priv->vis_hash_lock); | 879 | spin_lock_bh(&bat_priv->vis_hash_lock); |
866 | send_list_del(info); | 880 | send_list_del(info); |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 4487bbd0d72e..815269b07f20 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -2004,7 +2004,7 @@ static void hci_tx_task(unsigned long arg) | |||
2004 | read_unlock(&hci_task_lock); | 2004 | read_unlock(&hci_task_lock); |
2005 | } | 2005 | } |
2006 | 2006 | ||
2007 | /* ----- HCI RX task (incoming data proccessing) ----- */ | 2007 | /* ----- HCI RX task (incoming data processing) ----- */ |
2008 | 2008 | ||
2009 | /* ACL data packet */ | 2009 | /* ACL data packet */ |
2010 | static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb) | 2010 | static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb) |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index a5ab4a29ae31..4f3bc741183c 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -3666,7 +3666,7 @@ drop: | |||
3666 | static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb) | 3666 | static inline int l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb) |
3667 | { | 3667 | { |
3668 | struct l2cap_chan *chan; | 3668 | struct l2cap_chan *chan; |
3669 | struct sock *sk; | 3669 | struct sock *sk = NULL; |
3670 | struct l2cap_pinfo *pi; | 3670 | struct l2cap_pinfo *pi; |
3671 | u16 control; | 3671 | u16 control; |
3672 | u8 tx_seq; | 3672 | u8 tx_seq; |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index c98360d40b84..18dc9888d8c2 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -649,7 +649,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch | |||
649 | 649 | ||
650 | if (opt == BT_FLUSHABLE_OFF) { | 650 | if (opt == BT_FLUSHABLE_OFF) { |
651 | struct l2cap_conn *conn = chan->conn; | 651 | struct l2cap_conn *conn = chan->conn; |
652 | /* proceed futher only when we have l2cap_conn and | 652 | /* proceed further only when we have l2cap_conn and |
653 | No Flush support in the LM */ | 653 | No Flush support in the LM */ |
654 | if (!conn || !lmp_no_flush_capable(conn->hcon->hdev)) { | 654 | if (!conn || !lmp_no_flush_capable(conn->hcon->hdev)) { |
655 | err = -EINVAL; | 655 | err = -EINVAL; |
diff --git a/net/bridge/br.c b/net/bridge/br.c index 84bbb82599b2..f20c4fd915a8 100644 --- a/net/bridge/br.c +++ b/net/bridge/br.c | |||
@@ -104,3 +104,4 @@ module_init(br_init) | |||
104 | module_exit(br_deinit) | 104 | module_exit(br_deinit) |
105 | MODULE_LICENSE("GPL"); | 105 | MODULE_LICENSE("GPL"); |
106 | MODULE_VERSION(BR_VERSION); | 106 | MODULE_VERSION(BR_VERSION); |
107 | MODULE_ALIAS_RTNL_LINK("bridge"); | ||
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 21e5901186ea..a6b2f86378c7 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c | |||
@@ -74,13 +74,23 @@ out: | |||
74 | return NETDEV_TX_OK; | 74 | return NETDEV_TX_OK; |
75 | } | 75 | } |
76 | 76 | ||
77 | static int br_dev_init(struct net_device *dev) | ||
78 | { | ||
79 | struct net_bridge *br = netdev_priv(dev); | ||
80 | |||
81 | br->stats = alloc_percpu(struct br_cpu_netstats); | ||
82 | if (!br->stats) | ||
83 | return -ENOMEM; | ||
84 | |||
85 | return 0; | ||
86 | } | ||
87 | |||
77 | static int br_dev_open(struct net_device *dev) | 88 | static int br_dev_open(struct net_device *dev) |
78 | { | 89 | { |
79 | struct net_bridge *br = netdev_priv(dev); | 90 | struct net_bridge *br = netdev_priv(dev); |
80 | 91 | ||
81 | netif_carrier_off(dev); | 92 | netif_carrier_off(dev); |
82 | 93 | netdev_update_features(dev); | |
83 | br_features_recompute(br); | ||
84 | netif_start_queue(dev); | 94 | netif_start_queue(dev); |
85 | br_stp_enable_bridge(br); | 95 | br_stp_enable_bridge(br); |
86 | br_multicast_open(br); | 96 | br_multicast_open(br); |
@@ -177,48 +187,11 @@ static void br_getinfo(struct net_device *dev, struct ethtool_drvinfo *info) | |||
177 | strcpy(info->bus_info, "N/A"); | 187 | strcpy(info->bus_info, "N/A"); |
178 | } | 188 | } |
179 | 189 | ||
180 | static int br_set_sg(struct net_device *dev, u32 data) | 190 | static u32 br_fix_features(struct net_device *dev, u32 features) |
181 | { | ||
182 | struct net_bridge *br = netdev_priv(dev); | ||
183 | |||
184 | if (data) | ||
185 | br->feature_mask |= NETIF_F_SG; | ||
186 | else | ||
187 | br->feature_mask &= ~NETIF_F_SG; | ||
188 | |||
189 | br_features_recompute(br); | ||
190 | return 0; | ||
191 | } | ||
192 | |||
193 | static int br_set_tso(struct net_device *dev, u32 data) | ||
194 | { | ||
195 | struct net_bridge *br = netdev_priv(dev); | ||
196 | |||
197 | if (data) | ||
198 | br->feature_mask |= NETIF_F_TSO; | ||
199 | else | ||
200 | br->feature_mask &= ~NETIF_F_TSO; | ||
201 | |||
202 | br_features_recompute(br); | ||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | static int br_set_tx_csum(struct net_device *dev, u32 data) | ||
207 | { | 191 | { |
208 | struct net_bridge *br = netdev_priv(dev); | 192 | struct net_bridge *br = netdev_priv(dev); |
209 | 193 | ||
210 | if (data) | 194 | return br_features_recompute(br, features); |
211 | br->feature_mask |= NETIF_F_NO_CSUM; | ||
212 | else | ||
213 | br->feature_mask &= ~NETIF_F_ALL_CSUM; | ||
214 | |||
215 | br_features_recompute(br); | ||
216 | return 0; | ||
217 | } | ||
218 | |||
219 | static int br_set_flags(struct net_device *netdev, u32 data) | ||
220 | { | ||
221 | return ethtool_op_set_flags(netdev, data, ETH_FLAG_TXVLAN); | ||
222 | } | 195 | } |
223 | 196 | ||
224 | #ifdef CONFIG_NET_POLL_CONTROLLER | 197 | #ifdef CONFIG_NET_POLL_CONTROLLER |
@@ -319,21 +292,12 @@ static int br_del_slave(struct net_device *dev, struct net_device *slave_dev) | |||
319 | static const struct ethtool_ops br_ethtool_ops = { | 292 | static const struct ethtool_ops br_ethtool_ops = { |
320 | .get_drvinfo = br_getinfo, | 293 | .get_drvinfo = br_getinfo, |
321 | .get_link = ethtool_op_get_link, | 294 | .get_link = ethtool_op_get_link, |
322 | .get_tx_csum = ethtool_op_get_tx_csum, | ||
323 | .set_tx_csum = br_set_tx_csum, | ||
324 | .get_sg = ethtool_op_get_sg, | ||
325 | .set_sg = br_set_sg, | ||
326 | .get_tso = ethtool_op_get_tso, | ||
327 | .set_tso = br_set_tso, | ||
328 | .get_ufo = ethtool_op_get_ufo, | ||
329 | .set_ufo = ethtool_op_set_ufo, | ||
330 | .get_flags = ethtool_op_get_flags, | ||
331 | .set_flags = br_set_flags, | ||
332 | }; | 295 | }; |
333 | 296 | ||
334 | static const struct net_device_ops br_netdev_ops = { | 297 | static const struct net_device_ops br_netdev_ops = { |
335 | .ndo_open = br_dev_open, | 298 | .ndo_open = br_dev_open, |
336 | .ndo_stop = br_dev_stop, | 299 | .ndo_stop = br_dev_stop, |
300 | .ndo_init = br_dev_init, | ||
337 | .ndo_start_xmit = br_dev_xmit, | 301 | .ndo_start_xmit = br_dev_xmit, |
338 | .ndo_get_stats64 = br_get_stats64, | 302 | .ndo_get_stats64 = br_get_stats64, |
339 | .ndo_set_mac_address = br_set_mac_address, | 303 | .ndo_set_mac_address = br_set_mac_address, |
@@ -347,6 +311,7 @@ static const struct net_device_ops br_netdev_ops = { | |||
347 | #endif | 311 | #endif |
348 | .ndo_add_slave = br_add_slave, | 312 | .ndo_add_slave = br_add_slave, |
349 | .ndo_del_slave = br_del_slave, | 313 | .ndo_del_slave = br_del_slave, |
314 | .ndo_fix_features = br_fix_features, | ||
350 | }; | 315 | }; |
351 | 316 | ||
352 | static void br_dev_free(struct net_device *dev) | 317 | static void br_dev_free(struct net_device *dev) |
@@ -357,18 +322,49 @@ static void br_dev_free(struct net_device *dev) | |||
357 | free_netdev(dev); | 322 | free_netdev(dev); |
358 | } | 323 | } |
359 | 324 | ||
325 | static struct device_type br_type = { | ||
326 | .name = "bridge", | ||
327 | }; | ||
328 | |||
360 | void br_dev_setup(struct net_device *dev) | 329 | void br_dev_setup(struct net_device *dev) |
361 | { | 330 | { |
331 | struct net_bridge *br = netdev_priv(dev); | ||
332 | |||
362 | random_ether_addr(dev->dev_addr); | 333 | random_ether_addr(dev->dev_addr); |
363 | ether_setup(dev); | 334 | ether_setup(dev); |
364 | 335 | ||
365 | dev->netdev_ops = &br_netdev_ops; | 336 | dev->netdev_ops = &br_netdev_ops; |
366 | dev->destructor = br_dev_free; | 337 | dev->destructor = br_dev_free; |
367 | SET_ETHTOOL_OPS(dev, &br_ethtool_ops); | 338 | SET_ETHTOOL_OPS(dev, &br_ethtool_ops); |
339 | SET_NETDEV_DEVTYPE(dev, &br_type); | ||
368 | dev->tx_queue_len = 0; | 340 | dev->tx_queue_len = 0; |
369 | dev->priv_flags = IFF_EBRIDGE; | 341 | dev->priv_flags = IFF_EBRIDGE; |
370 | 342 | ||
371 | dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | | 343 | dev->features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | |
372 | NETIF_F_GSO_MASK | NETIF_F_NO_CSUM | NETIF_F_LLTX | | 344 | NETIF_F_GSO_MASK | NETIF_F_NO_CSUM | NETIF_F_LLTX | |
373 | NETIF_F_NETNS_LOCAL | NETIF_F_GSO | NETIF_F_HW_VLAN_TX; | 345 | NETIF_F_NETNS_LOCAL | NETIF_F_HW_VLAN_TX; |
346 | dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | | ||
347 | NETIF_F_GSO_MASK | NETIF_F_NO_CSUM | | ||
348 | NETIF_F_HW_VLAN_TX; | ||
349 | |||
350 | br->dev = dev; | ||
351 | spin_lock_init(&br->lock); | ||
352 | INIT_LIST_HEAD(&br->port_list); | ||
353 | spin_lock_init(&br->hash_lock); | ||
354 | |||
355 | br->bridge_id.prio[0] = 0x80; | ||
356 | br->bridge_id.prio[1] = 0x00; | ||
357 | |||
358 | memcpy(br->group_addr, br_group_address, ETH_ALEN); | ||
359 | |||
360 | br->stp_enabled = BR_NO_STP; | ||
361 | br->designated_root = br->bridge_id; | ||
362 | br->bridge_max_age = br->max_age = 20 * HZ; | ||
363 | br->bridge_hello_time = br->hello_time = 2 * HZ; | ||
364 | br->bridge_forward_delay = br->forward_delay = 15 * HZ; | ||
365 | br->ageing_time = 300 * HZ; | ||
366 | |||
367 | br_netfilter_rtable_init(br); | ||
368 | br_stp_timer_init(br); | ||
369 | br_multicast_init(br); | ||
374 | } | 370 | } |
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index 88485cc74dc3..e0dfbc151dd7 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c | |||
@@ -28,6 +28,7 @@ | |||
28 | static struct kmem_cache *br_fdb_cache __read_mostly; | 28 | static struct kmem_cache *br_fdb_cache __read_mostly; |
29 | static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source, | 29 | static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source, |
30 | const unsigned char *addr); | 30 | const unsigned char *addr); |
31 | static void fdb_notify(const struct net_bridge_fdb_entry *, int); | ||
31 | 32 | ||
32 | static u32 fdb_salt __read_mostly; | 33 | static u32 fdb_salt __read_mostly; |
33 | 34 | ||
@@ -62,7 +63,7 @@ static inline int has_expired(const struct net_bridge *br, | |||
62 | const struct net_bridge_fdb_entry *fdb) | 63 | const struct net_bridge_fdb_entry *fdb) |
63 | { | 64 | { |
64 | return !fdb->is_static && | 65 | return !fdb->is_static && |
65 | time_before_eq(fdb->ageing_timer + hold_time(br), jiffies); | 66 | time_before_eq(fdb->updated + hold_time(br), jiffies); |
66 | } | 67 | } |
67 | 68 | ||
68 | static inline int br_mac_hash(const unsigned char *mac) | 69 | static inline int br_mac_hash(const unsigned char *mac) |
@@ -81,6 +82,7 @@ static void fdb_rcu_free(struct rcu_head *head) | |||
81 | 82 | ||
82 | static inline void fdb_delete(struct net_bridge_fdb_entry *f) | 83 | static inline void fdb_delete(struct net_bridge_fdb_entry *f) |
83 | { | 84 | { |
85 | fdb_notify(f, RTM_DELNEIGH); | ||
84 | hlist_del_rcu(&f->hlist); | 86 | hlist_del_rcu(&f->hlist); |
85 | call_rcu(&f->rcu, fdb_rcu_free); | 87 | call_rcu(&f->rcu, fdb_rcu_free); |
86 | } | 88 | } |
@@ -140,7 +142,7 @@ void br_fdb_cleanup(unsigned long _data) | |||
140 | unsigned long this_timer; | 142 | unsigned long this_timer; |
141 | if (f->is_static) | 143 | if (f->is_static) |
142 | continue; | 144 | continue; |
143 | this_timer = f->ageing_timer + delay; | 145 | this_timer = f->updated + delay; |
144 | if (time_before_eq(this_timer, jiffies)) | 146 | if (time_before_eq(this_timer, jiffies)) |
145 | fdb_delete(f); | 147 | fdb_delete(f); |
146 | else if (time_before(this_timer, next_timer)) | 148 | else if (time_before(this_timer, next_timer)) |
@@ -169,7 +171,7 @@ void br_fdb_flush(struct net_bridge *br) | |||
169 | spin_unlock_bh(&br->hash_lock); | 171 | spin_unlock_bh(&br->hash_lock); |
170 | } | 172 | } |
171 | 173 | ||
172 | /* Flush all entries refering to a specific port. | 174 | /* Flush all entries referring to a specific port. |
173 | * if do_all is set also flush static entries | 175 | * if do_all is set also flush static entries |
174 | */ | 176 | */ |
175 | void br_fdb_delete_by_port(struct net_bridge *br, | 177 | void br_fdb_delete_by_port(struct net_bridge *br, |
@@ -293,7 +295,7 @@ int br_fdb_fillbuf(struct net_bridge *br, void *buf, | |||
293 | 295 | ||
294 | fe->is_local = f->is_local; | 296 | fe->is_local = f->is_local; |
295 | if (!f->is_static) | 297 | if (!f->is_static) |
296 | fe->ageing_timer_value = jiffies_to_clock_t(jiffies - f->ageing_timer); | 298 | fe->ageing_timer_value = jiffies_to_clock_t(jiffies - f->updated); |
297 | ++fe; | 299 | ++fe; |
298 | ++num; | 300 | ++num; |
299 | } | 301 | } |
@@ -305,8 +307,21 @@ int br_fdb_fillbuf(struct net_bridge *br, void *buf, | |||
305 | return num; | 307 | return num; |
306 | } | 308 | } |
307 | 309 | ||
308 | static inline struct net_bridge_fdb_entry *fdb_find(struct hlist_head *head, | 310 | static struct net_bridge_fdb_entry *fdb_find(struct hlist_head *head, |
309 | const unsigned char *addr) | 311 | const unsigned char *addr) |
312 | { | ||
313 | struct hlist_node *h; | ||
314 | struct net_bridge_fdb_entry *fdb; | ||
315 | |||
316 | hlist_for_each_entry(fdb, h, head, hlist) { | ||
317 | if (!compare_ether_addr(fdb->addr.addr, addr)) | ||
318 | return fdb; | ||
319 | } | ||
320 | return NULL; | ||
321 | } | ||
322 | |||
323 | static struct net_bridge_fdb_entry *fdb_find_rcu(struct hlist_head *head, | ||
324 | const unsigned char *addr) | ||
310 | { | 325 | { |
311 | struct hlist_node *h; | 326 | struct hlist_node *h; |
312 | struct net_bridge_fdb_entry *fdb; | 327 | struct net_bridge_fdb_entry *fdb; |
@@ -320,8 +335,7 @@ static inline struct net_bridge_fdb_entry *fdb_find(struct hlist_head *head, | |||
320 | 335 | ||
321 | static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head, | 336 | static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head, |
322 | struct net_bridge_port *source, | 337 | struct net_bridge_port *source, |
323 | const unsigned char *addr, | 338 | const unsigned char *addr) |
324 | int is_local) | ||
325 | { | 339 | { |
326 | struct net_bridge_fdb_entry *fdb; | 340 | struct net_bridge_fdb_entry *fdb; |
327 | 341 | ||
@@ -329,11 +343,11 @@ static struct net_bridge_fdb_entry *fdb_create(struct hlist_head *head, | |||
329 | if (fdb) { | 343 | if (fdb) { |
330 | memcpy(fdb->addr.addr, addr, ETH_ALEN); | 344 | memcpy(fdb->addr.addr, addr, ETH_ALEN); |
331 | fdb->dst = source; | 345 | fdb->dst = source; |
332 | fdb->is_local = is_local; | 346 | fdb->is_local = 0; |
333 | fdb->is_static = is_local; | 347 | fdb->is_static = 0; |
334 | fdb->ageing_timer = jiffies; | 348 | fdb->updated = fdb->used = jiffies; |
335 | |||
336 | hlist_add_head_rcu(&fdb->hlist, head); | 349 | hlist_add_head_rcu(&fdb->hlist, head); |
350 | fdb_notify(fdb, RTM_NEWNEIGH); | ||
337 | } | 351 | } |
338 | return fdb; | 352 | return fdb; |
339 | } | 353 | } |
@@ -360,12 +374,15 @@ static int fdb_insert(struct net_bridge *br, struct net_bridge_port *source, | |||
360 | fdb_delete(fdb); | 374 | fdb_delete(fdb); |
361 | } | 375 | } |
362 | 376 | ||
363 | if (!fdb_create(head, source, addr, 1)) | 377 | fdb = fdb_create(head, source, addr); |
378 | if (!fdb) | ||
364 | return -ENOMEM; | 379 | return -ENOMEM; |
365 | 380 | ||
381 | fdb->is_local = fdb->is_static = 1; | ||
366 | return 0; | 382 | return 0; |
367 | } | 383 | } |
368 | 384 | ||
385 | /* Add entry for local address of interface */ | ||
369 | int br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source, | 386 | int br_fdb_insert(struct net_bridge *br, struct net_bridge_port *source, |
370 | const unsigned char *addr) | 387 | const unsigned char *addr) |
371 | { | 388 | { |
@@ -392,7 +409,7 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, | |||
392 | source->state == BR_STATE_FORWARDING)) | 409 | source->state == BR_STATE_FORWARDING)) |
393 | return; | 410 | return; |
394 | 411 | ||
395 | fdb = fdb_find(head, addr); | 412 | fdb = fdb_find_rcu(head, addr); |
396 | if (likely(fdb)) { | 413 | if (likely(fdb)) { |
397 | /* attempt to update an entry for a local interface */ | 414 | /* attempt to update an entry for a local interface */ |
398 | if (unlikely(fdb->is_local)) { | 415 | if (unlikely(fdb->is_local)) { |
@@ -403,15 +420,277 @@ void br_fdb_update(struct net_bridge *br, struct net_bridge_port *source, | |||
403 | } else { | 420 | } else { |
404 | /* fastpath: update of existing entry */ | 421 | /* fastpath: update of existing entry */ |
405 | fdb->dst = source; | 422 | fdb->dst = source; |
406 | fdb->ageing_timer = jiffies; | 423 | fdb->updated = jiffies; |
407 | } | 424 | } |
408 | } else { | 425 | } else { |
409 | spin_lock(&br->hash_lock); | 426 | spin_lock(&br->hash_lock); |
410 | if (!fdb_find(head, addr)) | 427 | if (likely(!fdb_find(head, addr))) |
411 | fdb_create(head, source, addr, 0); | 428 | fdb_create(head, source, addr); |
429 | |||
412 | /* else we lose race and someone else inserts | 430 | /* else we lose race and someone else inserts |
413 | * it first, don't bother updating | 431 | * it first, don't bother updating |
414 | */ | 432 | */ |
415 | spin_unlock(&br->hash_lock); | 433 | spin_unlock(&br->hash_lock); |
416 | } | 434 | } |
417 | } | 435 | } |
436 | |||
437 | static int fdb_to_nud(const struct net_bridge_fdb_entry *fdb) | ||
438 | { | ||
439 | if (fdb->is_local) | ||
440 | return NUD_PERMANENT; | ||
441 | else if (fdb->is_static) | ||
442 | return NUD_NOARP; | ||
443 | else if (has_expired(fdb->dst->br, fdb)) | ||
444 | return NUD_STALE; | ||
445 | else | ||
446 | return NUD_REACHABLE; | ||
447 | } | ||
448 | |||
449 | static int fdb_fill_info(struct sk_buff *skb, | ||
450 | const struct net_bridge_fdb_entry *fdb, | ||
451 | u32 pid, u32 seq, int type, unsigned int flags) | ||
452 | { | ||
453 | unsigned long now = jiffies; | ||
454 | struct nda_cacheinfo ci; | ||
455 | struct nlmsghdr *nlh; | ||
456 | struct ndmsg *ndm; | ||
457 | |||
458 | nlh = nlmsg_put(skb, pid, seq, type, sizeof(*ndm), flags); | ||
459 | if (nlh == NULL) | ||
460 | return -EMSGSIZE; | ||
461 | |||
462 | |||
463 | ndm = nlmsg_data(nlh); | ||
464 | ndm->ndm_family = AF_BRIDGE; | ||
465 | ndm->ndm_pad1 = 0; | ||
466 | ndm->ndm_pad2 = 0; | ||
467 | ndm->ndm_flags = 0; | ||
468 | ndm->ndm_type = 0; | ||
469 | ndm->ndm_ifindex = fdb->dst->dev->ifindex; | ||
470 | ndm->ndm_state = fdb_to_nud(fdb); | ||
471 | |||
472 | NLA_PUT(skb, NDA_LLADDR, ETH_ALEN, &fdb->addr); | ||
473 | |||
474 | ci.ndm_used = jiffies_to_clock_t(now - fdb->used); | ||
475 | ci.ndm_confirmed = 0; | ||
476 | ci.ndm_updated = jiffies_to_clock_t(now - fdb->updated); | ||
477 | ci.ndm_refcnt = 0; | ||
478 | NLA_PUT(skb, NDA_CACHEINFO, sizeof(ci), &ci); | ||
479 | |||
480 | return nlmsg_end(skb, nlh); | ||
481 | |||
482 | nla_put_failure: | ||
483 | nlmsg_cancel(skb, nlh); | ||
484 | return -EMSGSIZE; | ||
485 | } | ||
486 | |||
487 | static inline size_t fdb_nlmsg_size(void) | ||
488 | { | ||
489 | return NLMSG_ALIGN(sizeof(struct ndmsg)) | ||
490 | + nla_total_size(ETH_ALEN) /* NDA_LLADDR */ | ||
491 | + nla_total_size(sizeof(struct nda_cacheinfo)); | ||
492 | } | ||
493 | |||
494 | static void fdb_notify(const struct net_bridge_fdb_entry *fdb, int type) | ||
495 | { | ||
496 | struct net *net = dev_net(fdb->dst->dev); | ||
497 | struct sk_buff *skb; | ||
498 | int err = -ENOBUFS; | ||
499 | |||
500 | skb = nlmsg_new(fdb_nlmsg_size(), GFP_ATOMIC); | ||
501 | if (skb == NULL) | ||
502 | goto errout; | ||
503 | |||
504 | err = fdb_fill_info(skb, fdb, 0, 0, type, 0); | ||
505 | if (err < 0) { | ||
506 | /* -EMSGSIZE implies BUG in fdb_nlmsg_size() */ | ||
507 | WARN_ON(err == -EMSGSIZE); | ||
508 | kfree_skb(skb); | ||
509 | goto errout; | ||
510 | } | ||
511 | rtnl_notify(skb, net, 0, RTNLGRP_NEIGH, NULL, GFP_ATOMIC); | ||
512 | return; | ||
513 | errout: | ||
514 | if (err < 0) | ||
515 | rtnl_set_sk_err(net, RTNLGRP_NEIGH, err); | ||
516 | } | ||
517 | |||
518 | /* Dump information about entries, in response to GETNEIGH */ | ||
519 | int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb) | ||
520 | { | ||
521 | struct net *net = sock_net(skb->sk); | ||
522 | struct net_device *dev; | ||
523 | int idx = 0; | ||
524 | |||
525 | rcu_read_lock(); | ||
526 | for_each_netdev_rcu(net, dev) { | ||
527 | struct net_bridge *br = netdev_priv(dev); | ||
528 | int i; | ||
529 | |||
530 | if (!(dev->priv_flags & IFF_EBRIDGE)) | ||
531 | continue; | ||
532 | |||
533 | for (i = 0; i < BR_HASH_SIZE; i++) { | ||
534 | struct hlist_node *h; | ||
535 | struct net_bridge_fdb_entry *f; | ||
536 | |||
537 | hlist_for_each_entry_rcu(f, h, &br->hash[i], hlist) { | ||
538 | if (idx < cb->args[0]) | ||
539 | goto skip; | ||
540 | |||
541 | if (fdb_fill_info(skb, f, | ||
542 | NETLINK_CB(cb->skb).pid, | ||
543 | cb->nlh->nlmsg_seq, | ||
544 | RTM_NEWNEIGH, | ||
545 | NLM_F_MULTI) < 0) | ||
546 | break; | ||
547 | skip: | ||
548 | ++idx; | ||
549 | } | ||
550 | } | ||
551 | } | ||
552 | rcu_read_unlock(); | ||
553 | |||
554 | cb->args[0] = idx; | ||
555 | |||
556 | return skb->len; | ||
557 | } | ||
558 | |||
559 | /* Create new static fdb entry */ | ||
560 | static int fdb_add_entry(struct net_bridge_port *source, const __u8 *addr, | ||
561 | __u16 state) | ||
562 | { | ||
563 | struct net_bridge *br = source->br; | ||
564 | struct hlist_head *head = &br->hash[br_mac_hash(addr)]; | ||
565 | struct net_bridge_fdb_entry *fdb; | ||
566 | |||
567 | fdb = fdb_find(head, addr); | ||
568 | if (fdb) | ||
569 | return -EEXIST; | ||
570 | |||
571 | fdb = fdb_create(head, source, addr); | ||
572 | if (!fdb) | ||
573 | return -ENOMEM; | ||
574 | |||
575 | if (state & NUD_PERMANENT) | ||
576 | fdb->is_local = fdb->is_static = 1; | ||
577 | else if (state & NUD_NOARP) | ||
578 | fdb->is_static = 1; | ||
579 | return 0; | ||
580 | } | ||
581 | |||
582 | /* Add new permanent fdb entry with RTM_NEWNEIGH */ | ||
583 | int br_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | ||
584 | { | ||
585 | struct net *net = sock_net(skb->sk); | ||
586 | struct ndmsg *ndm; | ||
587 | struct nlattr *tb[NDA_MAX+1]; | ||
588 | struct net_device *dev; | ||
589 | struct net_bridge_port *p; | ||
590 | const __u8 *addr; | ||
591 | int err; | ||
592 | |||
593 | ASSERT_RTNL(); | ||
594 | err = nlmsg_parse(nlh, sizeof(*ndm), tb, NDA_MAX, NULL); | ||
595 | if (err < 0) | ||
596 | return err; | ||
597 | |||
598 | ndm = nlmsg_data(nlh); | ||
599 | if (ndm->ndm_ifindex == 0) { | ||
600 | pr_info("bridge: RTM_NEWNEIGH with invalid ifindex\n"); | ||
601 | return -EINVAL; | ||
602 | } | ||
603 | |||
604 | dev = __dev_get_by_index(net, ndm->ndm_ifindex); | ||
605 | if (dev == NULL) { | ||
606 | pr_info("bridge: RTM_NEWNEIGH with unknown ifindex\n"); | ||
607 | return -ENODEV; | ||
608 | } | ||
609 | |||
610 | if (!tb[NDA_LLADDR] || nla_len(tb[NDA_LLADDR]) != ETH_ALEN) { | ||
611 | pr_info("bridge: RTM_NEWNEIGH with invalid address\n"); | ||
612 | return -EINVAL; | ||
613 | } | ||
614 | |||
615 | addr = nla_data(tb[NDA_LLADDR]); | ||
616 | if (!is_valid_ether_addr(addr)) { | ||
617 | pr_info("bridge: RTM_NEWNEIGH with invalid ether address\n"); | ||
618 | return -EINVAL; | ||
619 | } | ||
620 | |||
621 | p = br_port_get_rtnl(dev); | ||
622 | if (p == NULL) { | ||
623 | pr_info("bridge: RTM_NEWNEIGH %s not a bridge port\n", | ||
624 | dev->name); | ||
625 | return -EINVAL; | ||
626 | } | ||
627 | |||
628 | spin_lock_bh(&p->br->hash_lock); | ||
629 | err = fdb_add_entry(p, addr, ndm->ndm_state); | ||
630 | spin_unlock_bh(&p->br->hash_lock); | ||
631 | |||
632 | return err; | ||
633 | } | ||
634 | |||
635 | static int fdb_delete_by_addr(struct net_bridge_port *p, const u8 *addr) | ||
636 | { | ||
637 | struct net_bridge *br = p->br; | ||
638 | struct hlist_head *head = &br->hash[br_mac_hash(addr)]; | ||
639 | struct net_bridge_fdb_entry *fdb; | ||
640 | |||
641 | fdb = fdb_find(head, addr); | ||
642 | if (!fdb) | ||
643 | return -ENOENT; | ||
644 | |||
645 | fdb_delete(fdb); | ||
646 | return 0; | ||
647 | } | ||
648 | |||
649 | /* Remove neighbor entry with RTM_DELNEIGH */ | ||
650 | int br_fdb_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | ||
651 | { | ||
652 | struct net *net = sock_net(skb->sk); | ||
653 | struct ndmsg *ndm; | ||
654 | struct net_bridge_port *p; | ||
655 | struct nlattr *llattr; | ||
656 | const __u8 *addr; | ||
657 | struct net_device *dev; | ||
658 | int err; | ||
659 | |||
660 | ASSERT_RTNL(); | ||
661 | if (nlmsg_len(nlh) < sizeof(*ndm)) | ||
662 | return -EINVAL; | ||
663 | |||
664 | ndm = nlmsg_data(nlh); | ||
665 | if (ndm->ndm_ifindex == 0) { | ||
666 | pr_info("bridge: RTM_DELNEIGH with invalid ifindex\n"); | ||
667 | return -EINVAL; | ||
668 | } | ||
669 | |||
670 | dev = __dev_get_by_index(net, ndm->ndm_ifindex); | ||
671 | if (dev == NULL) { | ||
672 | pr_info("bridge: RTM_DELNEIGH with unknown ifindex\n"); | ||
673 | return -ENODEV; | ||
674 | } | ||
675 | |||
676 | llattr = nlmsg_find_attr(nlh, sizeof(*ndm), NDA_LLADDR); | ||
677 | if (llattr == NULL || nla_len(llattr) != ETH_ALEN) { | ||
678 | pr_info("bridge: RTM_DELNEIGH with invalid address\n"); | ||
679 | return -EINVAL; | ||
680 | } | ||
681 | |||
682 | addr = nla_data(llattr); | ||
683 | |||
684 | p = br_port_get_rtnl(dev); | ||
685 | if (p == NULL) { | ||
686 | pr_info("bridge: RTM_DELNEIGH %s not a bridge port\n", | ||
687 | dev->name); | ||
688 | return -EINVAL; | ||
689 | } | ||
690 | |||
691 | spin_lock_bh(&p->br->hash_lock); | ||
692 | err = fdb_delete_by_addr(p, addr); | ||
693 | spin_unlock_bh(&p->br->hash_lock); | ||
694 | |||
695 | return err; | ||
696 | } | ||
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 718b60366dfe..5dbdfdfc3a34 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
@@ -36,8 +36,8 @@ static int port_cost(struct net_device *dev) | |||
36 | if (dev->ethtool_ops && dev->ethtool_ops->get_settings) { | 36 | if (dev->ethtool_ops && dev->ethtool_ops->get_settings) { |
37 | struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET, }; | 37 | struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET, }; |
38 | 38 | ||
39 | if (!dev->ethtool_ops->get_settings(dev, &ecmd)) { | 39 | if (!dev_ethtool_get_settings(dev, &ecmd)) { |
40 | switch(ecmd.speed) { | 40 | switch (ethtool_cmd_speed(&ecmd)) { |
41 | case SPEED_10000: | 41 | case SPEED_10000: |
42 | return 2; | 42 | return 2; |
43 | case SPEED_1000: | 43 | case SPEED_1000: |
@@ -175,56 +175,6 @@ static void del_br(struct net_bridge *br, struct list_head *head) | |||
175 | unregister_netdevice_queue(br->dev, head); | 175 | unregister_netdevice_queue(br->dev, head); |
176 | } | 176 | } |
177 | 177 | ||
178 | static struct net_device *new_bridge_dev(struct net *net, const char *name) | ||
179 | { | ||
180 | struct net_bridge *br; | ||
181 | struct net_device *dev; | ||
182 | |||
183 | dev = alloc_netdev(sizeof(struct net_bridge), name, | ||
184 | br_dev_setup); | ||
185 | |||
186 | if (!dev) | ||
187 | return NULL; | ||
188 | dev_net_set(dev, net); | ||
189 | |||
190 | br = netdev_priv(dev); | ||
191 | br->dev = dev; | ||
192 | |||
193 | br->stats = alloc_percpu(struct br_cpu_netstats); | ||
194 | if (!br->stats) { | ||
195 | free_netdev(dev); | ||
196 | return NULL; | ||
197 | } | ||
198 | |||
199 | spin_lock_init(&br->lock); | ||
200 | INIT_LIST_HEAD(&br->port_list); | ||
201 | spin_lock_init(&br->hash_lock); | ||
202 | |||
203 | br->bridge_id.prio[0] = 0x80; | ||
204 | br->bridge_id.prio[1] = 0x00; | ||
205 | |||
206 | memcpy(br->group_addr, br_group_address, ETH_ALEN); | ||
207 | |||
208 | br->feature_mask = dev->features; | ||
209 | br->stp_enabled = BR_NO_STP; | ||
210 | br->designated_root = br->bridge_id; | ||
211 | br->root_path_cost = 0; | ||
212 | br->root_port = 0; | ||
213 | br->bridge_max_age = br->max_age = 20 * HZ; | ||
214 | br->bridge_hello_time = br->hello_time = 2 * HZ; | ||
215 | br->bridge_forward_delay = br->forward_delay = 15 * HZ; | ||
216 | br->topology_change = 0; | ||
217 | br->topology_change_detected = 0; | ||
218 | br->ageing_time = 300 * HZ; | ||
219 | |||
220 | br_netfilter_rtable_init(br); | ||
221 | |||
222 | br_stp_timer_init(br); | ||
223 | br_multicast_init(br); | ||
224 | |||
225 | return dev; | ||
226 | } | ||
227 | |||
228 | /* find an available port number */ | 178 | /* find an available port number */ |
229 | static int find_portno(struct net_bridge *br) | 179 | static int find_portno(struct net_bridge *br) |
230 | { | 180 | { |
@@ -277,42 +227,19 @@ static struct net_bridge_port *new_nbp(struct net_bridge *br, | |||
277 | return p; | 227 | return p; |
278 | } | 228 | } |
279 | 229 | ||
280 | static struct device_type br_type = { | ||
281 | .name = "bridge", | ||
282 | }; | ||
283 | |||
284 | int br_add_bridge(struct net *net, const char *name) | 230 | int br_add_bridge(struct net *net, const char *name) |
285 | { | 231 | { |
286 | struct net_device *dev; | 232 | struct net_device *dev; |
287 | int ret; | ||
288 | 233 | ||
289 | dev = new_bridge_dev(net, name); | 234 | dev = alloc_netdev(sizeof(struct net_bridge), name, |
235 | br_dev_setup); | ||
236 | |||
290 | if (!dev) | 237 | if (!dev) |
291 | return -ENOMEM; | 238 | return -ENOMEM; |
292 | 239 | ||
293 | rtnl_lock(); | 240 | dev_net_set(dev, net); |
294 | if (strchr(dev->name, '%')) { | ||
295 | ret = dev_alloc_name(dev, dev->name); | ||
296 | if (ret < 0) | ||
297 | goto out_free; | ||
298 | } | ||
299 | |||
300 | SET_NETDEV_DEVTYPE(dev, &br_type); | ||
301 | |||
302 | ret = register_netdevice(dev); | ||
303 | if (ret) | ||
304 | goto out_free; | ||
305 | |||
306 | ret = br_sysfs_addbr(dev); | ||
307 | if (ret) | ||
308 | unregister_netdevice(dev); | ||
309 | out: | ||
310 | rtnl_unlock(); | ||
311 | return ret; | ||
312 | 241 | ||
313 | out_free: | 242 | return register_netdev(dev); |
314 | free_netdev(dev); | ||
315 | goto out; | ||
316 | } | 243 | } |
317 | 244 | ||
318 | int br_del_bridge(struct net *net, const char *name) | 245 | int br_del_bridge(struct net *net, const char *name) |
@@ -364,15 +291,15 @@ int br_min_mtu(const struct net_bridge *br) | |||
364 | /* | 291 | /* |
365 | * Recomputes features using slave's features | 292 | * Recomputes features using slave's features |
366 | */ | 293 | */ |
367 | void br_features_recompute(struct net_bridge *br) | 294 | u32 br_features_recompute(struct net_bridge *br, u32 features) |
368 | { | 295 | { |
369 | struct net_bridge_port *p; | 296 | struct net_bridge_port *p; |
370 | u32 features, mask; | 297 | u32 mask; |
371 | 298 | ||
372 | features = mask = br->feature_mask; | ||
373 | if (list_empty(&br->port_list)) | 299 | if (list_empty(&br->port_list)) |
374 | goto done; | 300 | return features; |
375 | 301 | ||
302 | mask = features; | ||
376 | features &= ~NETIF_F_ONE_FOR_ALL; | 303 | features &= ~NETIF_F_ONE_FOR_ALL; |
377 | 304 | ||
378 | list_for_each_entry(p, &br->port_list, list) { | 305 | list_for_each_entry(p, &br->port_list, list) { |
@@ -380,8 +307,7 @@ void br_features_recompute(struct net_bridge *br) | |||
380 | p->dev->features, mask); | 307 | p->dev->features, mask); |
381 | } | 308 | } |
382 | 309 | ||
383 | done: | 310 | return features; |
384 | br->dev->features = netdev_fix_features(br->dev, features); | ||
385 | } | 311 | } |
386 | 312 | ||
387 | /* called with RTNL */ | 313 | /* called with RTNL */ |
@@ -446,9 +372,10 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
446 | 372 | ||
447 | list_add_rcu(&p->list, &br->port_list); | 373 | list_add_rcu(&p->list, &br->port_list); |
448 | 374 | ||
375 | netdev_update_features(br->dev); | ||
376 | |||
449 | spin_lock_bh(&br->lock); | 377 | spin_lock_bh(&br->lock); |
450 | changed_addr = br_stp_recalculate_bridge_id(br); | 378 | changed_addr = br_stp_recalculate_bridge_id(br); |
451 | br_features_recompute(br); | ||
452 | 379 | ||
453 | if ((dev->flags & IFF_UP) && netif_carrier_ok(dev) && | 380 | if ((dev->flags & IFF_UP) && netif_carrier_ok(dev) && |
454 | (br->dev->flags & IFF_UP)) | 381 | (br->dev->flags & IFF_UP)) |
@@ -496,9 +423,10 @@ int br_del_if(struct net_bridge *br, struct net_device *dev) | |||
496 | 423 | ||
497 | spin_lock_bh(&br->lock); | 424 | spin_lock_bh(&br->lock); |
498 | br_stp_recalculate_bridge_id(br); | 425 | br_stp_recalculate_bridge_id(br); |
499 | br_features_recompute(br); | ||
500 | spin_unlock_bh(&br->lock); | 426 | spin_unlock_bh(&br->lock); |
501 | 427 | ||
428 | netdev_update_features(br->dev); | ||
429 | |||
502 | return 0; | 430 | return 0; |
503 | } | 431 | } |
504 | 432 | ||
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index e2160792e1bc..f3ac1e858ee1 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c | |||
@@ -98,9 +98,10 @@ int br_handle_frame_finish(struct sk_buff *skb) | |||
98 | } | 98 | } |
99 | 99 | ||
100 | if (skb) { | 100 | if (skb) { |
101 | if (dst) | 101 | if (dst) { |
102 | dst->used = jiffies; | ||
102 | br_forward(dst->dst, skb, skb2); | 103 | br_forward(dst->dst, skb, skb2); |
103 | else | 104 | } else |
104 | br_flood_forward(br, skb, skb2); | 105 | br_flood_forward(br, skb, skb2); |
105 | } | 106 | } |
106 | 107 | ||
@@ -164,7 +165,7 @@ rx_handler_result_t br_handle_frame(struct sk_buff **pskb) | |||
164 | goto drop; | 165 | goto drop; |
165 | 166 | ||
166 | /* If STP is turned off, then forward */ | 167 | /* If STP is turned off, then forward */ |
167 | if (p->br->stp_enabled == BR_NO_STP) | 168 | if (p->br->stp_enabled == BR_NO_STP && dest[5] == 0) |
168 | goto forward; | 169 | goto forward; |
169 | 170 | ||
170 | if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, | 171 | if (NF_HOOK(NFPROTO_BRIDGE, NF_BR_LOCAL_IN, skb, skb->dev, |
diff --git a/net/bridge/br_ioctl.c b/net/bridge/br_ioctl.c index cb43312b846e..7222fe1d5460 100644 --- a/net/bridge/br_ioctl.c +++ b/net/bridge/br_ioctl.c | |||
@@ -106,7 +106,7 @@ static int add_del_if(struct net_bridge *br, int ifindex, int isadd) | |||
106 | /* | 106 | /* |
107 | * Legacy ioctl's through SIOCDEVPRIVATE | 107 | * Legacy ioctl's through SIOCDEVPRIVATE |
108 | * This interface is deprecated because it was too difficult to | 108 | * This interface is deprecated because it was too difficult to |
109 | * to do the translation for 32/64bit ioctl compatability. | 109 | * to do the translation for 32/64bit ioctl compatibility. |
110 | */ | 110 | */ |
111 | static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | 111 | static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) |
112 | { | 112 | { |
@@ -181,40 +181,19 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | |||
181 | if (!capable(CAP_NET_ADMIN)) | 181 | if (!capable(CAP_NET_ADMIN)) |
182 | return -EPERM; | 182 | return -EPERM; |
183 | 183 | ||
184 | spin_lock_bh(&br->lock); | 184 | return br_set_forward_delay(br, args[1]); |
185 | br->bridge_forward_delay = clock_t_to_jiffies(args[1]); | ||
186 | if (br_is_root_bridge(br)) | ||
187 | br->forward_delay = br->bridge_forward_delay; | ||
188 | spin_unlock_bh(&br->lock); | ||
189 | return 0; | ||
190 | 185 | ||
191 | case BRCTL_SET_BRIDGE_HELLO_TIME: | 186 | case BRCTL_SET_BRIDGE_HELLO_TIME: |
192 | { | ||
193 | unsigned long t = clock_t_to_jiffies(args[1]); | ||
194 | if (!capable(CAP_NET_ADMIN)) | 187 | if (!capable(CAP_NET_ADMIN)) |
195 | return -EPERM; | 188 | return -EPERM; |
196 | 189 | ||
197 | if (t < HZ) | 190 | return br_set_hello_time(br, args[1]); |
198 | return -EINVAL; | ||
199 | |||
200 | spin_lock_bh(&br->lock); | ||
201 | br->bridge_hello_time = t; | ||
202 | if (br_is_root_bridge(br)) | ||
203 | br->hello_time = br->bridge_hello_time; | ||
204 | spin_unlock_bh(&br->lock); | ||
205 | return 0; | ||
206 | } | ||
207 | 191 | ||
208 | case BRCTL_SET_BRIDGE_MAX_AGE: | 192 | case BRCTL_SET_BRIDGE_MAX_AGE: |
209 | if (!capable(CAP_NET_ADMIN)) | 193 | if (!capable(CAP_NET_ADMIN)) |
210 | return -EPERM; | 194 | return -EPERM; |
211 | 195 | ||
212 | spin_lock_bh(&br->lock); | 196 | return br_set_max_age(br, args[1]); |
213 | br->bridge_max_age = clock_t_to_jiffies(args[1]); | ||
214 | if (br_is_root_bridge(br)) | ||
215 | br->max_age = br->bridge_max_age; | ||
216 | spin_unlock_bh(&br->lock); | ||
217 | return 0; | ||
218 | 197 | ||
219 | case BRCTL_SET_AGEING_TIME: | 198 | case BRCTL_SET_AGEING_TIME: |
220 | if (!capable(CAP_NET_ADMIN)) | 199 | if (!capable(CAP_NET_ADMIN)) |
@@ -275,19 +254,16 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | |||
275 | case BRCTL_SET_PORT_PRIORITY: | 254 | case BRCTL_SET_PORT_PRIORITY: |
276 | { | 255 | { |
277 | struct net_bridge_port *p; | 256 | struct net_bridge_port *p; |
278 | int ret = 0; | 257 | int ret; |
279 | 258 | ||
280 | if (!capable(CAP_NET_ADMIN)) | 259 | if (!capable(CAP_NET_ADMIN)) |
281 | return -EPERM; | 260 | return -EPERM; |
282 | 261 | ||
283 | if (args[2] >= (1<<(16-BR_PORT_BITS))) | ||
284 | return -ERANGE; | ||
285 | |||
286 | spin_lock_bh(&br->lock); | 262 | spin_lock_bh(&br->lock); |
287 | if ((p = br_get_port(br, args[1])) == NULL) | 263 | if ((p = br_get_port(br, args[1])) == NULL) |
288 | ret = -EINVAL; | 264 | ret = -EINVAL; |
289 | else | 265 | else |
290 | br_stp_set_port_priority(p, args[2]); | 266 | ret = br_stp_set_port_priority(p, args[2]); |
291 | spin_unlock_bh(&br->lock); | 267 | spin_unlock_bh(&br->lock); |
292 | return ret; | 268 | return ret; |
293 | } | 269 | } |
@@ -295,15 +271,17 @@ static int old_dev_ioctl(struct net_device *dev, struct ifreq *rq, int cmd) | |||
295 | case BRCTL_SET_PATH_COST: | 271 | case BRCTL_SET_PATH_COST: |
296 | { | 272 | { |
297 | struct net_bridge_port *p; | 273 | struct net_bridge_port *p; |
298 | int ret = 0; | 274 | int ret; |
299 | 275 | ||
300 | if (!capable(CAP_NET_ADMIN)) | 276 | if (!capable(CAP_NET_ADMIN)) |
301 | return -EPERM; | 277 | return -EPERM; |
302 | 278 | ||
279 | spin_lock_bh(&br->lock); | ||
303 | if ((p = br_get_port(br, args[1])) == NULL) | 280 | if ((p = br_get_port(br, args[1])) == NULL) |
304 | ret = -EINVAL; | 281 | ret = -EINVAL; |
305 | else | 282 | else |
306 | br_stp_set_path_cost(p, args[2]); | 283 | ret = br_stp_set_path_cost(p, args[2]); |
284 | spin_unlock_bh(&br->lock); | ||
307 | 285 | ||
308 | return ret; | 286 | return ret; |
309 | } | 287 | } |
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 59660c909a7c..2f14eafdeeab 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
@@ -413,7 +413,7 @@ out: | |||
413 | 413 | ||
414 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 414 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
415 | static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br, | 415 | static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br, |
416 | struct in6_addr *group) | 416 | const struct in6_addr *group) |
417 | { | 417 | { |
418 | struct sk_buff *skb; | 418 | struct sk_buff *skb; |
419 | struct ipv6hdr *ip6h; | 419 | struct ipv6hdr *ip6h; |
@@ -1115,7 +1115,7 @@ static int br_ip4_multicast_query(struct net_bridge *br, | |||
1115 | struct net_bridge_port *port, | 1115 | struct net_bridge_port *port, |
1116 | struct sk_buff *skb) | 1116 | struct sk_buff *skb) |
1117 | { | 1117 | { |
1118 | struct iphdr *iph = ip_hdr(skb); | 1118 | const struct iphdr *iph = ip_hdr(skb); |
1119 | struct igmphdr *ih = igmp_hdr(skb); | 1119 | struct igmphdr *ih = igmp_hdr(skb); |
1120 | struct net_bridge_mdb_entry *mp; | 1120 | struct net_bridge_mdb_entry *mp; |
1121 | struct igmpv3_query *ih3; | 1121 | struct igmpv3_query *ih3; |
@@ -1190,7 +1190,7 @@ static int br_ip6_multicast_query(struct net_bridge *br, | |||
1190 | struct net_bridge_port *port, | 1190 | struct net_bridge_port *port, |
1191 | struct sk_buff *skb) | 1191 | struct sk_buff *skb) |
1192 | { | 1192 | { |
1193 | struct ipv6hdr *ip6h = ipv6_hdr(skb); | 1193 | const struct ipv6hdr *ip6h = ipv6_hdr(skb); |
1194 | struct mld_msg *mld = (struct mld_msg *) icmp6_hdr(skb); | 1194 | struct mld_msg *mld = (struct mld_msg *) icmp6_hdr(skb); |
1195 | struct net_bridge_mdb_entry *mp; | 1195 | struct net_bridge_mdb_entry *mp; |
1196 | struct mld2_query *mld2q; | 1196 | struct mld2_query *mld2q; |
@@ -1198,7 +1198,7 @@ static int br_ip6_multicast_query(struct net_bridge *br, | |||
1198 | struct net_bridge_port_group __rcu **pp; | 1198 | struct net_bridge_port_group __rcu **pp; |
1199 | unsigned long max_delay; | 1199 | unsigned long max_delay; |
1200 | unsigned long now = jiffies; | 1200 | unsigned long now = jiffies; |
1201 | struct in6_addr *group = NULL; | 1201 | const struct in6_addr *group = NULL; |
1202 | int err = 0; | 1202 | int err = 0; |
1203 | 1203 | ||
1204 | spin_lock(&br->multicast_lock); | 1204 | spin_lock(&br->multicast_lock); |
@@ -1356,7 +1356,7 @@ static int br_multicast_ipv4_rcv(struct net_bridge *br, | |||
1356 | struct sk_buff *skb) | 1356 | struct sk_buff *skb) |
1357 | { | 1357 | { |
1358 | struct sk_buff *skb2 = skb; | 1358 | struct sk_buff *skb2 = skb; |
1359 | struct iphdr *iph; | 1359 | const struct iphdr *iph; |
1360 | struct igmphdr *ih; | 1360 | struct igmphdr *ih; |
1361 | unsigned len; | 1361 | unsigned len; |
1362 | unsigned offset; | 1362 | unsigned offset; |
@@ -1452,7 +1452,7 @@ static int br_multicast_ipv6_rcv(struct net_bridge *br, | |||
1452 | struct sk_buff *skb) | 1452 | struct sk_buff *skb) |
1453 | { | 1453 | { |
1454 | struct sk_buff *skb2; | 1454 | struct sk_buff *skb2; |
1455 | struct ipv6hdr *ip6h; | 1455 | const struct ipv6hdr *ip6h; |
1456 | struct icmp6hdr *icmp6h; | 1456 | struct icmp6hdr *icmp6h; |
1457 | u8 nexthdr; | 1457 | u8 nexthdr; |
1458 | unsigned len; | 1458 | unsigned len; |
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 008ff6c4eecf..5614907525e1 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
@@ -219,7 +219,7 @@ static inline void nf_bridge_update_protocol(struct sk_buff *skb) | |||
219 | static int br_parse_ip_options(struct sk_buff *skb) | 219 | static int br_parse_ip_options(struct sk_buff *skb) |
220 | { | 220 | { |
221 | struct ip_options *opt; | 221 | struct ip_options *opt; |
222 | struct iphdr *iph; | 222 | const struct iphdr *iph; |
223 | struct net_device *dev = skb->dev; | 223 | struct net_device *dev = skb->dev; |
224 | u32 len; | 224 | u32 len; |
225 | 225 | ||
@@ -249,11 +249,9 @@ static int br_parse_ip_options(struct sk_buff *skb) | |||
249 | goto drop; | 249 | goto drop; |
250 | } | 250 | } |
251 | 251 | ||
252 | /* Zero out the CB buffer if no options present */ | 252 | memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); |
253 | if (iph->ihl == 5) { | 253 | if (iph->ihl == 5) |
254 | memset(IPCB(skb), 0, sizeof(struct inet_skb_parm)); | ||
255 | return 0; | 254 | return 0; |
256 | } | ||
257 | 255 | ||
258 | opt->optlen = iph->ihl*4 - sizeof(struct iphdr); | 256 | opt->optlen = iph->ihl*4 - sizeof(struct iphdr); |
259 | if (ip_options_compile(dev_net(dev), opt, skb)) | 257 | if (ip_options_compile(dev_net(dev), opt, skb)) |
@@ -556,7 +554,7 @@ static unsigned int br_nf_pre_routing_ipv6(unsigned int hook, | |||
556 | const struct net_device *out, | 554 | const struct net_device *out, |
557 | int (*okfn)(struct sk_buff *)) | 555 | int (*okfn)(struct sk_buff *)) |
558 | { | 556 | { |
559 | struct ipv6hdr *hdr; | 557 | const struct ipv6hdr *hdr; |
560 | u32 pkt_len; | 558 | u32 pkt_len; |
561 | 559 | ||
562 | if (skb->len < sizeof(struct ipv6hdr)) | 560 | if (skb->len < sizeof(struct ipv6hdr)) |
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index f8bf4c7f842c..ffb0dc4cc0e8 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c | |||
@@ -12,9 +12,11 @@ | |||
12 | 12 | ||
13 | #include <linux/kernel.h> | 13 | #include <linux/kernel.h> |
14 | #include <linux/slab.h> | 14 | #include <linux/slab.h> |
15 | #include <linux/etherdevice.h> | ||
15 | #include <net/rtnetlink.h> | 16 | #include <net/rtnetlink.h> |
16 | #include <net/net_namespace.h> | 17 | #include <net/net_namespace.h> |
17 | #include <net/sock.h> | 18 | #include <net/sock.h> |
19 | |||
18 | #include "br_private.h" | 20 | #include "br_private.h" |
19 | 21 | ||
20 | static inline size_t br_nlmsg_size(void) | 22 | static inline size_t br_nlmsg_size(void) |
@@ -118,8 +120,9 @@ static int br_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | |||
118 | int idx; | 120 | int idx; |
119 | 121 | ||
120 | idx = 0; | 122 | idx = 0; |
121 | for_each_netdev(net, dev) { | 123 | rcu_read_lock(); |
122 | struct net_bridge_port *port = br_port_get_rtnl(dev); | 124 | for_each_netdev_rcu(net, dev) { |
125 | struct net_bridge_port *port = br_port_get_rcu(dev); | ||
123 | 126 | ||
124 | /* not a bridge port */ | 127 | /* not a bridge port */ |
125 | if (!port || idx < cb->args[0]) | 128 | if (!port || idx < cb->args[0]) |
@@ -133,7 +136,7 @@ static int br_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | |||
133 | skip: | 136 | skip: |
134 | ++idx; | 137 | ++idx; |
135 | } | 138 | } |
136 | 139 | rcu_read_unlock(); | |
137 | cb->args[0] = idx; | 140 | cb->args[0] = idx; |
138 | 141 | ||
139 | return skb->len; | 142 | return skb->len; |
@@ -188,20 +191,61 @@ static int br_rtm_setlink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
188 | return 0; | 191 | return 0; |
189 | } | 192 | } |
190 | 193 | ||
194 | static int br_validate(struct nlattr *tb[], struct nlattr *data[]) | ||
195 | { | ||
196 | if (tb[IFLA_ADDRESS]) { | ||
197 | if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) | ||
198 | return -EINVAL; | ||
199 | if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) | ||
200 | return -EADDRNOTAVAIL; | ||
201 | } | ||
202 | |||
203 | return 0; | ||
204 | } | ||
205 | |||
206 | static struct rtnl_link_ops br_link_ops __read_mostly = { | ||
207 | .kind = "bridge", | ||
208 | .priv_size = sizeof(struct net_bridge), | ||
209 | .setup = br_dev_setup, | ||
210 | .validate = br_validate, | ||
211 | }; | ||
191 | 212 | ||
192 | int __init br_netlink_init(void) | 213 | int __init br_netlink_init(void) |
193 | { | 214 | { |
194 | if (__rtnl_register(PF_BRIDGE, RTM_GETLINK, NULL, br_dump_ifinfo)) | 215 | int err; |
195 | return -ENOBUFS; | ||
196 | 216 | ||
197 | /* Only the first call to __rtnl_register can fail */ | 217 | err = rtnl_link_register(&br_link_ops); |
198 | __rtnl_register(PF_BRIDGE, RTM_SETLINK, br_rtm_setlink, NULL); | 218 | if (err < 0) |
219 | goto err1; | ||
220 | |||
221 | err = __rtnl_register(PF_BRIDGE, RTM_GETLINK, NULL, br_dump_ifinfo); | ||
222 | if (err) | ||
223 | goto err2; | ||
224 | err = __rtnl_register(PF_BRIDGE, RTM_SETLINK, br_rtm_setlink, NULL); | ||
225 | if (err) | ||
226 | goto err3; | ||
227 | err = __rtnl_register(PF_BRIDGE, RTM_NEWNEIGH, br_fdb_add, NULL); | ||
228 | if (err) | ||
229 | goto err3; | ||
230 | err = __rtnl_register(PF_BRIDGE, RTM_DELNEIGH, br_fdb_delete, NULL); | ||
231 | if (err) | ||
232 | goto err3; | ||
233 | err = __rtnl_register(PF_BRIDGE, RTM_GETNEIGH, NULL, br_fdb_dump); | ||
234 | if (err) | ||
235 | goto err3; | ||
199 | 236 | ||
200 | return 0; | 237 | return 0; |
238 | |||
239 | err3: | ||
240 | rtnl_unregister_all(PF_BRIDGE); | ||
241 | err2: | ||
242 | rtnl_link_unregister(&br_link_ops); | ||
243 | err1: | ||
244 | return err; | ||
201 | } | 245 | } |
202 | 246 | ||
203 | void __exit br_netlink_fini(void) | 247 | void __exit br_netlink_fini(void) |
204 | { | 248 | { |
249 | rtnl_link_unregister(&br_link_ops); | ||
205 | rtnl_unregister_all(PF_BRIDGE); | 250 | rtnl_unregister_all(PF_BRIDGE); |
206 | } | 251 | } |
207 | |||
diff --git a/net/bridge/br_notify.c b/net/bridge/br_notify.c index 7d337c9b6082..6545ee9591d1 100644 --- a/net/bridge/br_notify.c +++ b/net/bridge/br_notify.c | |||
@@ -36,6 +36,12 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v | |||
36 | struct net_bridge *br; | 36 | struct net_bridge *br; |
37 | int err; | 37 | int err; |
38 | 38 | ||
39 | /* register of bridge completed, add sysfs entries */ | ||
40 | if ((dev->priv_flags & IFF_EBRIDGE) && event == NETDEV_REGISTER) { | ||
41 | br_sysfs_addbr(dev); | ||
42 | return NOTIFY_DONE; | ||
43 | } | ||
44 | |||
39 | /* not a port of a bridge */ | 45 | /* not a port of a bridge */ |
40 | p = br_port_get_rtnl(dev); | 46 | p = br_port_get_rtnl(dev); |
41 | if (!p) | 47 | if (!p) |
@@ -60,10 +66,7 @@ static int br_device_event(struct notifier_block *unused, unsigned long event, v | |||
60 | break; | 66 | break; |
61 | 67 | ||
62 | case NETDEV_FEAT_CHANGE: | 68 | case NETDEV_FEAT_CHANGE: |
63 | spin_lock_bh(&br->lock); | 69 | netdev_update_features(br->dev); |
64 | if (netif_running(br->dev)) | ||
65 | br_features_recompute(br); | ||
66 | spin_unlock_bh(&br->lock); | ||
67 | break; | 70 | break; |
68 | 71 | ||
69 | case NETDEV_DOWN: | 72 | case NETDEV_DOWN: |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 387013d33745..54578f274d85 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
@@ -64,7 +64,8 @@ struct net_bridge_fdb_entry | |||
64 | struct net_bridge_port *dst; | 64 | struct net_bridge_port *dst; |
65 | 65 | ||
66 | struct rcu_head rcu; | 66 | struct rcu_head rcu; |
67 | unsigned long ageing_timer; | 67 | unsigned long updated; |
68 | unsigned long used; | ||
68 | mac_addr addr; | 69 | mac_addr addr; |
69 | unsigned char is_local; | 70 | unsigned char is_local; |
70 | unsigned char is_static; | 71 | unsigned char is_static; |
@@ -182,7 +183,6 @@ struct net_bridge | |||
182 | struct br_cpu_netstats __percpu *stats; | 183 | struct br_cpu_netstats __percpu *stats; |
183 | spinlock_t hash_lock; | 184 | spinlock_t hash_lock; |
184 | struct hlist_head hash[BR_HASH_SIZE]; | 185 | struct hlist_head hash[BR_HASH_SIZE]; |
185 | u32 feature_mask; | ||
186 | #ifdef CONFIG_BRIDGE_NETFILTER | 186 | #ifdef CONFIG_BRIDGE_NETFILTER |
187 | struct rtable fake_rtable; | 187 | struct rtable fake_rtable; |
188 | bool nf_call_iptables; | 188 | bool nf_call_iptables; |
@@ -353,6 +353,9 @@ extern int br_fdb_insert(struct net_bridge *br, | |||
353 | extern void br_fdb_update(struct net_bridge *br, | 353 | extern void br_fdb_update(struct net_bridge *br, |
354 | struct net_bridge_port *source, | 354 | struct net_bridge_port *source, |
355 | const unsigned char *addr); | 355 | const unsigned char *addr); |
356 | extern int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb); | ||
357 | extern int br_fdb_add(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg); | ||
358 | extern int br_fdb_delete(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg); | ||
356 | 359 | ||
357 | /* br_forward.c */ | 360 | /* br_forward.c */ |
358 | extern void br_deliver(const struct net_bridge_port *to, | 361 | extern void br_deliver(const struct net_bridge_port *to, |
@@ -375,7 +378,7 @@ extern int br_add_if(struct net_bridge *br, | |||
375 | extern int br_del_if(struct net_bridge *br, | 378 | extern int br_del_if(struct net_bridge *br, |
376 | struct net_device *dev); | 379 | struct net_device *dev); |
377 | extern int br_min_mtu(const struct net_bridge *br); | 380 | extern int br_min_mtu(const struct net_bridge *br); |
378 | extern void br_features_recompute(struct net_bridge *br); | 381 | extern u32 br_features_recompute(struct net_bridge *br, u32 features); |
379 | 382 | ||
380 | /* br_input.c */ | 383 | /* br_input.c */ |
381 | extern int br_handle_frame_finish(struct sk_buff *skb); | 384 | extern int br_handle_frame_finish(struct sk_buff *skb); |
@@ -491,6 +494,11 @@ extern struct net_bridge_port *br_get_port(struct net_bridge *br, | |||
491 | extern void br_init_port(struct net_bridge_port *p); | 494 | extern void br_init_port(struct net_bridge_port *p); |
492 | extern void br_become_designated_port(struct net_bridge_port *p); | 495 | extern void br_become_designated_port(struct net_bridge_port *p); |
493 | 496 | ||
497 | extern int br_set_forward_delay(struct net_bridge *br, unsigned long x); | ||
498 | extern int br_set_hello_time(struct net_bridge *br, unsigned long x); | ||
499 | extern int br_set_max_age(struct net_bridge *br, unsigned long x); | ||
500 | |||
501 | |||
494 | /* br_stp_if.c */ | 502 | /* br_stp_if.c */ |
495 | extern void br_stp_enable_bridge(struct net_bridge *br); | 503 | extern void br_stp_enable_bridge(struct net_bridge *br); |
496 | extern void br_stp_disable_bridge(struct net_bridge *br); | 504 | extern void br_stp_disable_bridge(struct net_bridge *br); |
@@ -501,10 +509,10 @@ extern bool br_stp_recalculate_bridge_id(struct net_bridge *br); | |||
501 | extern void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *a); | 509 | extern void br_stp_change_bridge_id(struct net_bridge *br, const unsigned char *a); |
502 | extern void br_stp_set_bridge_priority(struct net_bridge *br, | 510 | extern void br_stp_set_bridge_priority(struct net_bridge *br, |
503 | u16 newprio); | 511 | u16 newprio); |
504 | extern void br_stp_set_port_priority(struct net_bridge_port *p, | 512 | extern int br_stp_set_port_priority(struct net_bridge_port *p, |
505 | u8 newprio); | 513 | unsigned long newprio); |
506 | extern void br_stp_set_path_cost(struct net_bridge_port *p, | 514 | extern int br_stp_set_path_cost(struct net_bridge_port *p, |
507 | u32 path_cost); | 515 | unsigned long path_cost); |
508 | extern ssize_t br_show_bridge_id(char *buf, const struct bridge_id *id); | 516 | extern ssize_t br_show_bridge_id(char *buf, const struct bridge_id *id); |
509 | 517 | ||
510 | /* br_stp_bpdu.c */ | 518 | /* br_stp_bpdu.c */ |
diff --git a/net/bridge/br_private_stp.h b/net/bridge/br_private_stp.h index 8b650f7fbfa0..642ef47a867e 100644 --- a/net/bridge/br_private_stp.h +++ b/net/bridge/br_private_stp.h | |||
@@ -16,6 +16,19 @@ | |||
16 | #define BPDU_TYPE_CONFIG 0 | 16 | #define BPDU_TYPE_CONFIG 0 |
17 | #define BPDU_TYPE_TCN 0x80 | 17 | #define BPDU_TYPE_TCN 0x80 |
18 | 18 | ||
19 | /* IEEE 802.1D-1998 timer values */ | ||
20 | #define BR_MIN_HELLO_TIME (1*HZ) | ||
21 | #define BR_MAX_HELLO_TIME (10*HZ) | ||
22 | |||
23 | #define BR_MIN_FORWARD_DELAY (2*HZ) | ||
24 | #define BR_MAX_FORWARD_DELAY (30*HZ) | ||
25 | |||
26 | #define BR_MIN_MAX_AGE (6*HZ) | ||
27 | #define BR_MAX_MAX_AGE (40*HZ) | ||
28 | |||
29 | #define BR_MIN_PATH_COST 1 | ||
30 | #define BR_MAX_PATH_COST 65535 | ||
31 | |||
19 | struct br_config_bpdu | 32 | struct br_config_bpdu |
20 | { | 33 | { |
21 | unsigned topology_change:1; | 34 | unsigned topology_change:1; |
diff --git a/net/bridge/br_stp.c b/net/bridge/br_stp.c index 7370d14f634d..bb4383e84de9 100644 --- a/net/bridge/br_stp.c +++ b/net/bridge/br_stp.c | |||
@@ -484,3 +484,51 @@ void br_received_tcn_bpdu(struct net_bridge_port *p) | |||
484 | br_topology_change_acknowledge(p); | 484 | br_topology_change_acknowledge(p); |
485 | } | 485 | } |
486 | } | 486 | } |
487 | |||
488 | /* Change bridge STP parameter */ | ||
489 | int br_set_hello_time(struct net_bridge *br, unsigned long val) | ||
490 | { | ||
491 | unsigned long t = clock_t_to_jiffies(val); | ||
492 | |||
493 | if (t < BR_MIN_HELLO_TIME || t > BR_MAX_HELLO_TIME) | ||
494 | return -ERANGE; | ||
495 | |||
496 | spin_lock_bh(&br->lock); | ||
497 | br->bridge_hello_time = t; | ||
498 | if (br_is_root_bridge(br)) | ||
499 | br->hello_time = br->bridge_hello_time; | ||
500 | spin_unlock_bh(&br->lock); | ||
501 | return 0; | ||
502 | } | ||
503 | |||
504 | int br_set_max_age(struct net_bridge *br, unsigned long val) | ||
505 | { | ||
506 | unsigned long t = clock_t_to_jiffies(val); | ||
507 | |||
508 | if (t < BR_MIN_MAX_AGE || t > BR_MAX_MAX_AGE) | ||
509 | return -ERANGE; | ||
510 | |||
511 | spin_lock_bh(&br->lock); | ||
512 | br->bridge_max_age = t; | ||
513 | if (br_is_root_bridge(br)) | ||
514 | br->max_age = br->bridge_max_age; | ||
515 | spin_unlock_bh(&br->lock); | ||
516 | return 0; | ||
517 | |||
518 | } | ||
519 | |||
520 | int br_set_forward_delay(struct net_bridge *br, unsigned long val) | ||
521 | { | ||
522 | unsigned long t = clock_t_to_jiffies(val); | ||
523 | |||
524 | if (br->stp_enabled != BR_NO_STP && | ||
525 | (t < BR_MIN_FORWARD_DELAY || t > BR_MAX_FORWARD_DELAY)) | ||
526 | return -ERANGE; | ||
527 | |||
528 | spin_lock_bh(&br->lock); | ||
529 | br->bridge_forward_delay = t; | ||
530 | if (br_is_root_bridge(br)) | ||
531 | br->forward_delay = br->bridge_forward_delay; | ||
532 | spin_unlock_bh(&br->lock); | ||
533 | return 0; | ||
534 | } | ||
diff --git a/net/bridge/br_stp_if.c b/net/bridge/br_stp_if.c index 9b61d09de9b9..6f615b8192f4 100644 --- a/net/bridge/br_stp_if.c +++ b/net/bridge/br_stp_if.c | |||
@@ -20,7 +20,7 @@ | |||
20 | 20 | ||
21 | 21 | ||
22 | /* Port id is composed of priority and port number. | 22 | /* Port id is composed of priority and port number. |
23 | * NB: least significant bits of priority are dropped to | 23 | * NB: some bits of priority are dropped to |
24 | * make room for more ports. | 24 | * make room for more ports. |
25 | */ | 25 | */ |
26 | static inline port_id br_make_port_id(__u8 priority, __u16 port_no) | 26 | static inline port_id br_make_port_id(__u8 priority, __u16 port_no) |
@@ -29,6 +29,8 @@ static inline port_id br_make_port_id(__u8 priority, __u16 port_no) | |||
29 | | (port_no & ((1<<BR_PORT_BITS)-1)); | 29 | | (port_no & ((1<<BR_PORT_BITS)-1)); |
30 | } | 30 | } |
31 | 31 | ||
32 | #define BR_MAX_PORT_PRIORITY ((u16)~0 >> BR_PORT_BITS) | ||
33 | |||
32 | /* called under bridge lock */ | 34 | /* called under bridge lock */ |
33 | void br_init_port(struct net_bridge_port *p) | 35 | void br_init_port(struct net_bridge_port *p) |
34 | { | 36 | { |
@@ -255,10 +257,14 @@ void br_stp_set_bridge_priority(struct net_bridge *br, u16 newprio) | |||
255 | } | 257 | } |
256 | 258 | ||
257 | /* called under bridge lock */ | 259 | /* called under bridge lock */ |
258 | void br_stp_set_port_priority(struct net_bridge_port *p, u8 newprio) | 260 | int br_stp_set_port_priority(struct net_bridge_port *p, unsigned long newprio) |
259 | { | 261 | { |
260 | port_id new_port_id = br_make_port_id(newprio, p->port_no); | 262 | port_id new_port_id; |
263 | |||
264 | if (newprio > BR_MAX_PORT_PRIORITY) | ||
265 | return -ERANGE; | ||
261 | 266 | ||
267 | new_port_id = br_make_port_id(newprio, p->port_no); | ||
262 | if (br_is_designated_port(p)) | 268 | if (br_is_designated_port(p)) |
263 | p->designated_port = new_port_id; | 269 | p->designated_port = new_port_id; |
264 | 270 | ||
@@ -269,14 +275,21 @@ void br_stp_set_port_priority(struct net_bridge_port *p, u8 newprio) | |||
269 | br_become_designated_port(p); | 275 | br_become_designated_port(p); |
270 | br_port_state_selection(p->br); | 276 | br_port_state_selection(p->br); |
271 | } | 277 | } |
278 | |||
279 | return 0; | ||
272 | } | 280 | } |
273 | 281 | ||
274 | /* called under bridge lock */ | 282 | /* called under bridge lock */ |
275 | void br_stp_set_path_cost(struct net_bridge_port *p, u32 path_cost) | 283 | int br_stp_set_path_cost(struct net_bridge_port *p, unsigned long path_cost) |
276 | { | 284 | { |
285 | if (path_cost < BR_MIN_PATH_COST || | ||
286 | path_cost > BR_MAX_PATH_COST) | ||
287 | return -ERANGE; | ||
288 | |||
277 | p->path_cost = path_cost; | 289 | p->path_cost = path_cost; |
278 | br_configuration_update(p->br); | 290 | br_configuration_update(p->br); |
279 | br_port_state_selection(p->br); | 291 | br_port_state_selection(p->br); |
292 | return 0; | ||
280 | } | 293 | } |
281 | 294 | ||
282 | ssize_t br_show_bridge_id(char *buf, const struct bridge_id *id) | 295 | ssize_t br_show_bridge_id(char *buf, const struct bridge_id *id) |
diff --git a/net/bridge/br_sysfs_br.c b/net/bridge/br_sysfs_br.c index 5c1e5559ebba..68b893ea8c3a 100644 --- a/net/bridge/br_sysfs_br.c +++ b/net/bridge/br_sysfs_br.c | |||
@@ -43,9 +43,7 @@ static ssize_t store_bridge_parm(struct device *d, | |||
43 | if (endp == buf) | 43 | if (endp == buf) |
44 | return -EINVAL; | 44 | return -EINVAL; |
45 | 45 | ||
46 | spin_lock_bh(&br->lock); | ||
47 | err = (*set)(br, val); | 46 | err = (*set)(br, val); |
48 | spin_unlock_bh(&br->lock); | ||
49 | return err ? err : len; | 47 | return err ? err : len; |
50 | } | 48 | } |
51 | 49 | ||
@@ -57,20 +55,11 @@ static ssize_t show_forward_delay(struct device *d, | |||
57 | return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->forward_delay)); | 55 | return sprintf(buf, "%lu\n", jiffies_to_clock_t(br->forward_delay)); |
58 | } | 56 | } |
59 | 57 | ||
60 | static int set_forward_delay(struct net_bridge *br, unsigned long val) | ||
61 | { | ||
62 | unsigned long delay = clock_t_to_jiffies(val); | ||
63 | br->forward_delay = delay; | ||
64 | if (br_is_root_bridge(br)) | ||
65 | br->bridge_forward_delay = delay; | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | static ssize_t store_forward_delay(struct device *d, | 58 | static ssize_t store_forward_delay(struct device *d, |
70 | struct device_attribute *attr, | 59 | struct device_attribute *attr, |
71 | const char *buf, size_t len) | 60 | const char *buf, size_t len) |
72 | { | 61 | { |
73 | return store_bridge_parm(d, buf, len, set_forward_delay); | 62 | return store_bridge_parm(d, buf, len, br_set_forward_delay); |
74 | } | 63 | } |
75 | static DEVICE_ATTR(forward_delay, S_IRUGO | S_IWUSR, | 64 | static DEVICE_ATTR(forward_delay, S_IRUGO | S_IWUSR, |
76 | show_forward_delay, store_forward_delay); | 65 | show_forward_delay, store_forward_delay); |
@@ -82,24 +71,11 @@ static ssize_t show_hello_time(struct device *d, struct device_attribute *attr, | |||
82 | jiffies_to_clock_t(to_bridge(d)->hello_time)); | 71 | jiffies_to_clock_t(to_bridge(d)->hello_time)); |
83 | } | 72 | } |
84 | 73 | ||
85 | static int set_hello_time(struct net_bridge *br, unsigned long val) | ||
86 | { | ||
87 | unsigned long t = clock_t_to_jiffies(val); | ||
88 | |||
89 | if (t < HZ) | ||
90 | return -EINVAL; | ||
91 | |||
92 | br->hello_time = t; | ||
93 | if (br_is_root_bridge(br)) | ||
94 | br->bridge_hello_time = t; | ||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | static ssize_t store_hello_time(struct device *d, | 74 | static ssize_t store_hello_time(struct device *d, |
99 | struct device_attribute *attr, const char *buf, | 75 | struct device_attribute *attr, const char *buf, |
100 | size_t len) | 76 | size_t len) |
101 | { | 77 | { |
102 | return store_bridge_parm(d, buf, len, set_hello_time); | 78 | return store_bridge_parm(d, buf, len, br_set_hello_time); |
103 | } | 79 | } |
104 | static DEVICE_ATTR(hello_time, S_IRUGO | S_IWUSR, show_hello_time, | 80 | static DEVICE_ATTR(hello_time, S_IRUGO | S_IWUSR, show_hello_time, |
105 | store_hello_time); | 81 | store_hello_time); |
@@ -111,19 +87,10 @@ static ssize_t show_max_age(struct device *d, struct device_attribute *attr, | |||
111 | jiffies_to_clock_t(to_bridge(d)->max_age)); | 87 | jiffies_to_clock_t(to_bridge(d)->max_age)); |
112 | } | 88 | } |
113 | 89 | ||
114 | static int set_max_age(struct net_bridge *br, unsigned long val) | ||
115 | { | ||
116 | unsigned long t = clock_t_to_jiffies(val); | ||
117 | br->max_age = t; | ||
118 | if (br_is_root_bridge(br)) | ||
119 | br->bridge_max_age = t; | ||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | static ssize_t store_max_age(struct device *d, struct device_attribute *attr, | 90 | static ssize_t store_max_age(struct device *d, struct device_attribute *attr, |
124 | const char *buf, size_t len) | 91 | const char *buf, size_t len) |
125 | { | 92 | { |
126 | return store_bridge_parm(d, buf, len, set_max_age); | 93 | return store_bridge_parm(d, buf, len, br_set_max_age); |
127 | } | 94 | } |
128 | static DEVICE_ATTR(max_age, S_IRUGO | S_IWUSR, show_max_age, store_max_age); | 95 | static DEVICE_ATTR(max_age, S_IRUGO | S_IWUSR, show_max_age, store_max_age); |
129 | 96 | ||
diff --git a/net/bridge/br_sysfs_if.c b/net/bridge/br_sysfs_if.c index fd5799c9bc8d..6229b62749e8 100644 --- a/net/bridge/br_sysfs_if.c +++ b/net/bridge/br_sysfs_if.c | |||
@@ -23,7 +23,7 @@ | |||
23 | struct brport_attribute { | 23 | struct brport_attribute { |
24 | struct attribute attr; | 24 | struct attribute attr; |
25 | ssize_t (*show)(struct net_bridge_port *, char *); | 25 | ssize_t (*show)(struct net_bridge_port *, char *); |
26 | ssize_t (*store)(struct net_bridge_port *, unsigned long); | 26 | int (*store)(struct net_bridge_port *, unsigned long); |
27 | }; | 27 | }; |
28 | 28 | ||
29 | #define BRPORT_ATTR(_name,_mode,_show,_store) \ | 29 | #define BRPORT_ATTR(_name,_mode,_show,_store) \ |
@@ -38,27 +38,17 @@ static ssize_t show_path_cost(struct net_bridge_port *p, char *buf) | |||
38 | { | 38 | { |
39 | return sprintf(buf, "%d\n", p->path_cost); | 39 | return sprintf(buf, "%d\n", p->path_cost); |
40 | } | 40 | } |
41 | static ssize_t store_path_cost(struct net_bridge_port *p, unsigned long v) | 41 | |
42 | { | ||
43 | br_stp_set_path_cost(p, v); | ||
44 | return 0; | ||
45 | } | ||
46 | static BRPORT_ATTR(path_cost, S_IRUGO | S_IWUSR, | 42 | static BRPORT_ATTR(path_cost, S_IRUGO | S_IWUSR, |
47 | show_path_cost, store_path_cost); | 43 | show_path_cost, br_stp_set_path_cost); |
48 | 44 | ||
49 | static ssize_t show_priority(struct net_bridge_port *p, char *buf) | 45 | static ssize_t show_priority(struct net_bridge_port *p, char *buf) |
50 | { | 46 | { |
51 | return sprintf(buf, "%d\n", p->priority); | 47 | return sprintf(buf, "%d\n", p->priority); |
52 | } | 48 | } |
53 | static ssize_t store_priority(struct net_bridge_port *p, unsigned long v) | 49 | |
54 | { | ||
55 | if (v >= (1<<(16-BR_PORT_BITS))) | ||
56 | return -ERANGE; | ||
57 | br_stp_set_port_priority(p, v); | ||
58 | return 0; | ||
59 | } | ||
60 | static BRPORT_ATTR(priority, S_IRUGO | S_IWUSR, | 50 | static BRPORT_ATTR(priority, S_IRUGO | S_IWUSR, |
61 | show_priority, store_priority); | 51 | show_priority, br_stp_set_port_priority); |
62 | 52 | ||
63 | static ssize_t show_designated_root(struct net_bridge_port *p, char *buf) | 53 | static ssize_t show_designated_root(struct net_bridge_port *p, char *buf) |
64 | { | 54 | { |
@@ -136,7 +126,7 @@ static ssize_t show_hold_timer(struct net_bridge_port *p, | |||
136 | } | 126 | } |
137 | static BRPORT_ATTR(hold_timer, S_IRUGO, show_hold_timer, NULL); | 127 | static BRPORT_ATTR(hold_timer, S_IRUGO, show_hold_timer, NULL); |
138 | 128 | ||
139 | static ssize_t store_flush(struct net_bridge_port *p, unsigned long v) | 129 | static int store_flush(struct net_bridge_port *p, unsigned long v) |
140 | { | 130 | { |
141 | br_fdb_delete_by_port(p->br, p, 0); // Don't delete local entry | 131 | br_fdb_delete_by_port(p->br, p, 0); // Don't delete local entry |
142 | return 0; | 132 | return 0; |
@@ -148,7 +138,7 @@ static ssize_t show_hairpin_mode(struct net_bridge_port *p, char *buf) | |||
148 | int hairpin_mode = (p->flags & BR_HAIRPIN_MODE) ? 1 : 0; | 138 | int hairpin_mode = (p->flags & BR_HAIRPIN_MODE) ? 1 : 0; |
149 | return sprintf(buf, "%d\n", hairpin_mode); | 139 | return sprintf(buf, "%d\n", hairpin_mode); |
150 | } | 140 | } |
151 | static ssize_t store_hairpin_mode(struct net_bridge_port *p, unsigned long v) | 141 | static int store_hairpin_mode(struct net_bridge_port *p, unsigned long v) |
152 | { | 142 | { |
153 | if (v) | 143 | if (v) |
154 | p->flags |= BR_HAIRPIN_MODE; | 144 | p->flags |= BR_HAIRPIN_MODE; |
@@ -165,7 +155,7 @@ static ssize_t show_multicast_router(struct net_bridge_port *p, char *buf) | |||
165 | return sprintf(buf, "%d\n", p->multicast_router); | 155 | return sprintf(buf, "%d\n", p->multicast_router); |
166 | } | 156 | } |
167 | 157 | ||
168 | static ssize_t store_multicast_router(struct net_bridge_port *p, | 158 | static int store_multicast_router(struct net_bridge_port *p, |
169 | unsigned long v) | 159 | unsigned long v) |
170 | { | 160 | { |
171 | return br_multicast_set_port_router(p, v); | 161 | return br_multicast_set_port_router(p, v); |
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 893669caa8de..1a92b369c820 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c | |||
@@ -1766,7 +1766,7 @@ static int compat_table_info(const struct ebt_table_info *info, | |||
1766 | 1766 | ||
1767 | newinfo->entries_size = size; | 1767 | newinfo->entries_size = size; |
1768 | 1768 | ||
1769 | xt_compat_init_offsets(AF_INET, info->nentries); | 1769 | xt_compat_init_offsets(NFPROTO_BRIDGE, info->nentries); |
1770 | return EBT_ENTRY_ITERATE(entries, size, compat_calc_entry, info, | 1770 | return EBT_ENTRY_ITERATE(entries, size, compat_calc_entry, info, |
1771 | entries, newinfo); | 1771 | entries, newinfo); |
1772 | } | 1772 | } |
@@ -1882,7 +1882,7 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt, | |||
1882 | struct xt_match *match; | 1882 | struct xt_match *match; |
1883 | struct xt_target *wt; | 1883 | struct xt_target *wt; |
1884 | void *dst = NULL; | 1884 | void *dst = NULL; |
1885 | int off, pad = 0, ret = 0; | 1885 | int off, pad = 0; |
1886 | unsigned int size_kern, entry_offset, match_size = mwt->match_size; | 1886 | unsigned int size_kern, entry_offset, match_size = mwt->match_size; |
1887 | 1887 | ||
1888 | strlcpy(name, mwt->u.name, sizeof(name)); | 1888 | strlcpy(name, mwt->u.name, sizeof(name)); |
@@ -1935,13 +1935,6 @@ static int compat_mtw_from_user(struct compat_ebt_entry_mwt *mwt, | |||
1935 | break; | 1935 | break; |
1936 | } | 1936 | } |
1937 | 1937 | ||
1938 | if (!dst) { | ||
1939 | ret = xt_compat_add_offset(NFPROTO_BRIDGE, entry_offset, | ||
1940 | off + ebt_compat_entry_padsize()); | ||
1941 | if (ret < 0) | ||
1942 | return ret; | ||
1943 | } | ||
1944 | |||
1945 | state->buf_kern_offset += match_size + off; | 1938 | state->buf_kern_offset += match_size + off; |
1946 | state->buf_user_offset += match_size; | 1939 | state->buf_user_offset += match_size; |
1947 | pad = XT_ALIGN(size_kern) - size_kern; | 1940 | pad = XT_ALIGN(size_kern) - size_kern; |
@@ -2016,50 +2009,6 @@ static int ebt_size_mwt(struct compat_ebt_entry_mwt *match32, | |||
2016 | return growth; | 2009 | return growth; |
2017 | } | 2010 | } |
2018 | 2011 | ||
2019 | #define EBT_COMPAT_WATCHER_ITERATE(e, fn, args...) \ | ||
2020 | ({ \ | ||
2021 | unsigned int __i; \ | ||
2022 | int __ret = 0; \ | ||
2023 | struct compat_ebt_entry_mwt *__watcher; \ | ||
2024 | \ | ||
2025 | for (__i = e->watchers_offset; \ | ||
2026 | __i < (e)->target_offset; \ | ||
2027 | __i += __watcher->watcher_size + \ | ||
2028 | sizeof(struct compat_ebt_entry_mwt)) { \ | ||
2029 | __watcher = (void *)(e) + __i; \ | ||
2030 | __ret = fn(__watcher , ## args); \ | ||
2031 | if (__ret != 0) \ | ||
2032 | break; \ | ||
2033 | } \ | ||
2034 | if (__ret == 0) { \ | ||
2035 | if (__i != (e)->target_offset) \ | ||
2036 | __ret = -EINVAL; \ | ||
2037 | } \ | ||
2038 | __ret; \ | ||
2039 | }) | ||
2040 | |||
2041 | #define EBT_COMPAT_MATCH_ITERATE(e, fn, args...) \ | ||
2042 | ({ \ | ||
2043 | unsigned int __i; \ | ||
2044 | int __ret = 0; \ | ||
2045 | struct compat_ebt_entry_mwt *__match; \ | ||
2046 | \ | ||
2047 | for (__i = sizeof(struct ebt_entry); \ | ||
2048 | __i < (e)->watchers_offset; \ | ||
2049 | __i += __match->match_size + \ | ||
2050 | sizeof(struct compat_ebt_entry_mwt)) { \ | ||
2051 | __match = (void *)(e) + __i; \ | ||
2052 | __ret = fn(__match , ## args); \ | ||
2053 | if (__ret != 0) \ | ||
2054 | break; \ | ||
2055 | } \ | ||
2056 | if (__ret == 0) { \ | ||
2057 | if (__i != (e)->watchers_offset) \ | ||
2058 | __ret = -EINVAL; \ | ||
2059 | } \ | ||
2060 | __ret; \ | ||
2061 | }) | ||
2062 | |||
2063 | /* called for all ebt_entry structures. */ | 2012 | /* called for all ebt_entry structures. */ |
2064 | static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base, | 2013 | static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base, |
2065 | unsigned int *total, | 2014 | unsigned int *total, |
@@ -2132,6 +2081,14 @@ static int size_entry_mwt(struct ebt_entry *entry, const unsigned char *base, | |||
2132 | } | 2081 | } |
2133 | } | 2082 | } |
2134 | 2083 | ||
2084 | if (state->buf_kern_start == NULL) { | ||
2085 | unsigned int offset = buf_start - (char *) base; | ||
2086 | |||
2087 | ret = xt_compat_add_offset(NFPROTO_BRIDGE, offset, new_offset); | ||
2088 | if (ret < 0) | ||
2089 | return ret; | ||
2090 | } | ||
2091 | |||
2135 | startoff = state->buf_user_offset - startoff; | 2092 | startoff = state->buf_user_offset - startoff; |
2136 | 2093 | ||
2137 | BUG_ON(*total < startoff); | 2094 | BUG_ON(*total < startoff); |
@@ -2240,6 +2197,7 @@ static int compat_do_replace(struct net *net, void __user *user, | |||
2240 | 2197 | ||
2241 | xt_compat_lock(NFPROTO_BRIDGE); | 2198 | xt_compat_lock(NFPROTO_BRIDGE); |
2242 | 2199 | ||
2200 | xt_compat_init_offsets(NFPROTO_BRIDGE, tmp.nentries); | ||
2243 | ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state); | 2201 | ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state); |
2244 | if (ret < 0) | 2202 | if (ret < 0) |
2245 | goto out_unlock; | 2203 | goto out_unlock; |
diff --git a/net/caif/Makefile b/net/caif/Makefile index 9d38e406e4a4..ebcd4e7e6f47 100644 --- a/net/caif/Makefile +++ b/net/caif/Makefile | |||
@@ -5,7 +5,7 @@ caif-y := caif_dev.o \ | |||
5 | cffrml.o cfveil.o cfdbgl.o\ | 5 | cffrml.o cfveil.o cfdbgl.o\ |
6 | cfserl.o cfdgml.o \ | 6 | cfserl.o cfdgml.o \ |
7 | cfrfml.o cfvidl.o cfutill.o \ | 7 | cfrfml.o cfvidl.o cfutill.o \ |
8 | cfsrvl.o cfpkt_skbuff.o caif_config_util.o | 8 | cfsrvl.o cfpkt_skbuff.o |
9 | 9 | ||
10 | obj-$(CONFIG_CAIF) += caif.o | 10 | obj-$(CONFIG_CAIF) += caif.o |
11 | obj-$(CONFIG_CAIF_NETDEV) += chnl_net.o | 11 | obj-$(CONFIG_CAIF_NETDEV) += chnl_net.o |
diff --git a/net/caif/caif_config_util.c b/net/caif/caif_config_util.c deleted file mode 100644 index d522d8c1703e..000000000000 --- a/net/caif/caif_config_util.c +++ /dev/null | |||
@@ -1,99 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) ST-Ericsson AB 2010 | ||
3 | * Author: Sjur Brendeland sjur.brandeland@stericsson.com | ||
4 | * License terms: GNU General Public License (GPL) version 2 | ||
5 | */ | ||
6 | |||
7 | #include <linux/module.h> | ||
8 | #include <linux/spinlock.h> | ||
9 | #include <net/caif/cfctrl.h> | ||
10 | #include <net/caif/cfcnfg.h> | ||
11 | #include <net/caif/caif_dev.h> | ||
12 | |||
13 | int connect_req_to_link_param(struct cfcnfg *cnfg, | ||
14 | struct caif_connect_request *s, | ||
15 | struct cfctrl_link_param *l) | ||
16 | { | ||
17 | struct dev_info *dev_info; | ||
18 | enum cfcnfg_phy_preference pref; | ||
19 | int res; | ||
20 | |||
21 | memset(l, 0, sizeof(*l)); | ||
22 | /* In caif protocol low value is high priority */ | ||
23 | l->priority = CAIF_PRIO_MAX - s->priority + 1; | ||
24 | |||
25 | if (s->ifindex != 0){ | ||
26 | res = cfcnfg_get_id_from_ifi(cnfg, s->ifindex); | ||
27 | if (res < 0) | ||
28 | return res; | ||
29 | l->phyid = res; | ||
30 | } | ||
31 | else { | ||
32 | switch (s->link_selector) { | ||
33 | case CAIF_LINK_HIGH_BANDW: | ||
34 | pref = CFPHYPREF_HIGH_BW; | ||
35 | break; | ||
36 | case CAIF_LINK_LOW_LATENCY: | ||
37 | pref = CFPHYPREF_LOW_LAT; | ||
38 | break; | ||
39 | default: | ||
40 | return -EINVAL; | ||
41 | } | ||
42 | dev_info = cfcnfg_get_phyid(cnfg, pref); | ||
43 | if (dev_info == NULL) | ||
44 | return -ENODEV; | ||
45 | l->phyid = dev_info->id; | ||
46 | } | ||
47 | switch (s->protocol) { | ||
48 | case CAIFPROTO_AT: | ||
49 | l->linktype = CFCTRL_SRV_VEI; | ||
50 | if (s->sockaddr.u.at.type == CAIF_ATTYPE_PLAIN) | ||
51 | l->chtype = 0x02; | ||
52 | else | ||
53 | l->chtype = s->sockaddr.u.at.type; | ||
54 | l->endpoint = 0x00; | ||
55 | break; | ||
56 | case CAIFPROTO_DATAGRAM: | ||
57 | l->linktype = CFCTRL_SRV_DATAGRAM; | ||
58 | l->chtype = 0x00; | ||
59 | l->u.datagram.connid = s->sockaddr.u.dgm.connection_id; | ||
60 | break; | ||
61 | case CAIFPROTO_DATAGRAM_LOOP: | ||
62 | l->linktype = CFCTRL_SRV_DATAGRAM; | ||
63 | l->chtype = 0x03; | ||
64 | l->endpoint = 0x00; | ||
65 | l->u.datagram.connid = s->sockaddr.u.dgm.connection_id; | ||
66 | break; | ||
67 | case CAIFPROTO_RFM: | ||
68 | l->linktype = CFCTRL_SRV_RFM; | ||
69 | l->u.datagram.connid = s->sockaddr.u.rfm.connection_id; | ||
70 | strncpy(l->u.rfm.volume, s->sockaddr.u.rfm.volume, | ||
71 | sizeof(l->u.rfm.volume)-1); | ||
72 | l->u.rfm.volume[sizeof(l->u.rfm.volume)-1] = 0; | ||
73 | break; | ||
74 | case CAIFPROTO_UTIL: | ||
75 | l->linktype = CFCTRL_SRV_UTIL; | ||
76 | l->endpoint = 0x00; | ||
77 | l->chtype = 0x00; | ||
78 | strncpy(l->u.utility.name, s->sockaddr.u.util.service, | ||
79 | sizeof(l->u.utility.name)-1); | ||
80 | l->u.utility.name[sizeof(l->u.utility.name)-1] = 0; | ||
81 | caif_assert(sizeof(l->u.utility.name) > 10); | ||
82 | l->u.utility.paramlen = s->param.size; | ||
83 | if (l->u.utility.paramlen > sizeof(l->u.utility.params)) | ||
84 | l->u.utility.paramlen = sizeof(l->u.utility.params); | ||
85 | |||
86 | memcpy(l->u.utility.params, s->param.data, | ||
87 | l->u.utility.paramlen); | ||
88 | |||
89 | break; | ||
90 | case CAIFPROTO_DEBUG: | ||
91 | l->linktype = CFCTRL_SRV_DBG; | ||
92 | l->endpoint = s->sockaddr.u.dbg.service; | ||
93 | l->chtype = s->sockaddr.u.dbg.type; | ||
94 | break; | ||
95 | default: | ||
96 | return -EINVAL; | ||
97 | } | ||
98 | return 0; | ||
99 | } | ||
diff --git a/net/caif/caif_dev.c b/net/caif/caif_dev.c index a42a408306e4..366ca0fb7a29 100644 --- a/net/caif/caif_dev.c +++ b/net/caif/caif_dev.c | |||
@@ -12,49 +12,51 @@ | |||
12 | #define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__ | 12 | #define pr_fmt(fmt) KBUILD_MODNAME ":%s(): " fmt, __func__ |
13 | 13 | ||
14 | #include <linux/version.h> | 14 | #include <linux/version.h> |
15 | #include <linux/module.h> | ||
16 | #include <linux/kernel.h> | 15 | #include <linux/kernel.h> |
17 | #include <linux/if_arp.h> | 16 | #include <linux/if_arp.h> |
18 | #include <linux/net.h> | 17 | #include <linux/net.h> |
19 | #include <linux/netdevice.h> | 18 | #include <linux/netdevice.h> |
20 | #include <linux/skbuff.h> | 19 | #include <linux/mutex.h> |
21 | #include <linux/sched.h> | ||
22 | #include <linux/wait.h> | ||
23 | #include <net/netns/generic.h> | 20 | #include <net/netns/generic.h> |
24 | #include <net/net_namespace.h> | 21 | #include <net/net_namespace.h> |
25 | #include <net/pkt_sched.h> | 22 | #include <net/pkt_sched.h> |
26 | #include <net/caif/caif_device.h> | 23 | #include <net/caif/caif_device.h> |
27 | #include <net/caif/caif_dev.h> | ||
28 | #include <net/caif/caif_layer.h> | 24 | #include <net/caif/caif_layer.h> |
29 | #include <net/caif/cfpkt.h> | 25 | #include <net/caif/cfpkt.h> |
30 | #include <net/caif/cfcnfg.h> | 26 | #include <net/caif/cfcnfg.h> |
31 | 27 | ||
32 | MODULE_LICENSE("GPL"); | 28 | MODULE_LICENSE("GPL"); |
33 | #define TIMEOUT (HZ*5) | ||
34 | 29 | ||
35 | /* Used for local tracking of the CAIF net devices */ | 30 | /* Used for local tracking of the CAIF net devices */ |
36 | struct caif_device_entry { | 31 | struct caif_device_entry { |
37 | struct cflayer layer; | 32 | struct cflayer layer; |
38 | struct list_head list; | 33 | struct list_head list; |
39 | atomic_t in_use; | ||
40 | atomic_t state; | ||
41 | u16 phyid; | ||
42 | struct net_device *netdev; | 34 | struct net_device *netdev; |
43 | wait_queue_head_t event; | 35 | int __percpu *pcpu_refcnt; |
44 | }; | 36 | }; |
45 | 37 | ||
46 | struct caif_device_entry_list { | 38 | struct caif_device_entry_list { |
47 | struct list_head list; | 39 | struct list_head list; |
48 | /* Protects simulanous deletes in list */ | 40 | /* Protects simulanous deletes in list */ |
49 | spinlock_t lock; | 41 | struct mutex lock; |
50 | }; | 42 | }; |
51 | 43 | ||
52 | struct caif_net { | 44 | struct caif_net { |
45 | struct cfcnfg *cfg; | ||
53 | struct caif_device_entry_list caifdevs; | 46 | struct caif_device_entry_list caifdevs; |
54 | }; | 47 | }; |
55 | 48 | ||
56 | static int caif_net_id; | 49 | static int caif_net_id; |
57 | static struct cfcnfg *cfg; | 50 | |
51 | struct cfcnfg *get_cfcnfg(struct net *net) | ||
52 | { | ||
53 | struct caif_net *caifn; | ||
54 | BUG_ON(!net); | ||
55 | caifn = net_generic(net, caif_net_id); | ||
56 | BUG_ON(!caifn); | ||
57 | return caifn->cfg; | ||
58 | } | ||
59 | EXPORT_SYMBOL(get_cfcnfg); | ||
58 | 60 | ||
59 | static struct caif_device_entry_list *caif_device_list(struct net *net) | 61 | static struct caif_device_entry_list *caif_device_list(struct net *net) |
60 | { | 62 | { |
@@ -65,19 +67,39 @@ static struct caif_device_entry_list *caif_device_list(struct net *net) | |||
65 | return &caifn->caifdevs; | 67 | return &caifn->caifdevs; |
66 | } | 68 | } |
67 | 69 | ||
70 | static void caifd_put(struct caif_device_entry *e) | ||
71 | { | ||
72 | irqsafe_cpu_dec(*e->pcpu_refcnt); | ||
73 | } | ||
74 | |||
75 | static void caifd_hold(struct caif_device_entry *e) | ||
76 | { | ||
77 | irqsafe_cpu_inc(*e->pcpu_refcnt); | ||
78 | } | ||
79 | |||
80 | static int caifd_refcnt_read(struct caif_device_entry *e) | ||
81 | { | ||
82 | int i, refcnt = 0; | ||
83 | for_each_possible_cpu(i) | ||
84 | refcnt += *per_cpu_ptr(e->pcpu_refcnt, i); | ||
85 | return refcnt; | ||
86 | } | ||
87 | |||
68 | /* Allocate new CAIF device. */ | 88 | /* Allocate new CAIF device. */ |
69 | static struct caif_device_entry *caif_device_alloc(struct net_device *dev) | 89 | static struct caif_device_entry *caif_device_alloc(struct net_device *dev) |
70 | { | 90 | { |
71 | struct caif_device_entry_list *caifdevs; | 91 | struct caif_device_entry_list *caifdevs; |
72 | struct caif_device_entry *caifd; | 92 | struct caif_device_entry *caifd; |
93 | |||
73 | caifdevs = caif_device_list(dev_net(dev)); | 94 | caifdevs = caif_device_list(dev_net(dev)); |
74 | BUG_ON(!caifdevs); | 95 | BUG_ON(!caifdevs); |
96 | |||
75 | caifd = kzalloc(sizeof(*caifd), GFP_ATOMIC); | 97 | caifd = kzalloc(sizeof(*caifd), GFP_ATOMIC); |
76 | if (!caifd) | 98 | if (!caifd) |
77 | return NULL; | 99 | return NULL; |
100 | caifd->pcpu_refcnt = alloc_percpu(int); | ||
78 | caifd->netdev = dev; | 101 | caifd->netdev = dev; |
79 | list_add(&caifd->list, &caifdevs->list); | 102 | dev_hold(dev); |
80 | init_waitqueue_head(&caifd->event); | ||
81 | return caifd; | 103 | return caifd; |
82 | } | 104 | } |
83 | 105 | ||
@@ -87,98 +109,60 @@ static struct caif_device_entry *caif_get(struct net_device *dev) | |||
87 | caif_device_list(dev_net(dev)); | 109 | caif_device_list(dev_net(dev)); |
88 | struct caif_device_entry *caifd; | 110 | struct caif_device_entry *caifd; |
89 | BUG_ON(!caifdevs); | 111 | BUG_ON(!caifdevs); |
90 | list_for_each_entry(caifd, &caifdevs->list, list) { | 112 | list_for_each_entry_rcu(caifd, &caifdevs->list, list) { |
91 | if (caifd->netdev == dev) | 113 | if (caifd->netdev == dev) |
92 | return caifd; | 114 | return caifd; |
93 | } | 115 | } |
94 | return NULL; | 116 | return NULL; |
95 | } | 117 | } |
96 | 118 | ||
97 | static void caif_device_destroy(struct net_device *dev) | ||
98 | { | ||
99 | struct caif_device_entry_list *caifdevs = | ||
100 | caif_device_list(dev_net(dev)); | ||
101 | struct caif_device_entry *caifd; | ||
102 | ASSERT_RTNL(); | ||
103 | if (dev->type != ARPHRD_CAIF) | ||
104 | return; | ||
105 | |||
106 | spin_lock_bh(&caifdevs->lock); | ||
107 | caifd = caif_get(dev); | ||
108 | if (caifd == NULL) { | ||
109 | spin_unlock_bh(&caifdevs->lock); | ||
110 | return; | ||
111 | } | ||
112 | |||
113 | list_del(&caifd->list); | ||
114 | spin_unlock_bh(&caifdevs->lock); | ||
115 | |||
116 | kfree(caifd); | ||
117 | } | ||
118 | |||
119 | static int transmit(struct cflayer *layer, struct cfpkt *pkt) | 119 | static int transmit(struct cflayer *layer, struct cfpkt *pkt) |
120 | { | 120 | { |
121 | int err; | ||
121 | struct caif_device_entry *caifd = | 122 | struct caif_device_entry *caifd = |
122 | container_of(layer, struct caif_device_entry, layer); | 123 | container_of(layer, struct caif_device_entry, layer); |
123 | struct sk_buff *skb, *skb2; | 124 | struct sk_buff *skb; |
124 | int ret = -EINVAL; | 125 | |
125 | skb = cfpkt_tonative(pkt); | 126 | skb = cfpkt_tonative(pkt); |
126 | skb->dev = caifd->netdev; | 127 | skb->dev = caifd->netdev; |
127 | /* | ||
128 | * Don't allow SKB to be destroyed upon error, but signal resend | ||
129 | * notification to clients. We can't rely on the return value as | ||
130 | * congestion (NET_XMIT_CN) sometimes drops the packet, sometimes don't. | ||
131 | */ | ||
132 | if (netif_queue_stopped(caifd->netdev)) | ||
133 | return -EAGAIN; | ||
134 | skb2 = skb_get(skb); | ||
135 | |||
136 | ret = dev_queue_xmit(skb2); | ||
137 | |||
138 | if (!ret) | ||
139 | kfree_skb(skb); | ||
140 | else | ||
141 | return -EAGAIN; | ||
142 | 128 | ||
143 | return 0; | 129 | err = dev_queue_xmit(skb); |
144 | } | 130 | if (err > 0) |
131 | err = -EIO; | ||
145 | 132 | ||
146 | static int modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl) | 133 | return err; |
147 | { | ||
148 | struct caif_device_entry *caifd; | ||
149 | struct caif_dev_common *caifdev; | ||
150 | caifd = container_of(layr, struct caif_device_entry, layer); | ||
151 | caifdev = netdev_priv(caifd->netdev); | ||
152 | if (ctrl == _CAIF_MODEMCMD_PHYIF_USEFULL) { | ||
153 | atomic_set(&caifd->in_use, 1); | ||
154 | wake_up_interruptible(&caifd->event); | ||
155 | |||
156 | } else if (ctrl == _CAIF_MODEMCMD_PHYIF_USELESS) { | ||
157 | atomic_set(&caifd->in_use, 0); | ||
158 | wake_up_interruptible(&caifd->event); | ||
159 | } | ||
160 | return 0; | ||
161 | } | 134 | } |
162 | 135 | ||
163 | /* | 136 | /* |
164 | * Stuff received packets to associated sockets. | 137 | * Stuff received packets into the CAIF stack. |
165 | * On error, returns non-zero and releases the skb. | 138 | * On error, returns non-zero and releases the skb. |
166 | */ | 139 | */ |
167 | static int receive(struct sk_buff *skb, struct net_device *dev, | 140 | static int receive(struct sk_buff *skb, struct net_device *dev, |
168 | struct packet_type *pkttype, struct net_device *orig_dev) | 141 | struct packet_type *pkttype, struct net_device *orig_dev) |
169 | { | 142 | { |
170 | struct net *net; | ||
171 | struct cfpkt *pkt; | 143 | struct cfpkt *pkt; |
172 | struct caif_device_entry *caifd; | 144 | struct caif_device_entry *caifd; |
173 | net = dev_net(dev); | 145 | |
174 | pkt = cfpkt_fromnative(CAIF_DIR_IN, skb); | 146 | pkt = cfpkt_fromnative(CAIF_DIR_IN, skb); |
147 | |||
148 | rcu_read_lock(); | ||
175 | caifd = caif_get(dev); | 149 | caifd = caif_get(dev); |
176 | if (!caifd || !caifd->layer.up || !caifd->layer.up->receive) | ||
177 | return NET_RX_DROP; | ||
178 | 150 | ||
179 | if (caifd->layer.up->receive(caifd->layer.up, pkt)) | 151 | if (!caifd || !caifd->layer.up || !caifd->layer.up->receive || |
152 | !netif_oper_up(caifd->netdev)) { | ||
153 | rcu_read_unlock(); | ||
154 | kfree_skb(skb); | ||
180 | return NET_RX_DROP; | 155 | return NET_RX_DROP; |
156 | } | ||
157 | |||
158 | /* Hold reference to netdevice while using CAIF stack */ | ||
159 | caifd_hold(caifd); | ||
160 | rcu_read_unlock(); | ||
161 | |||
162 | caifd->layer.up->receive(caifd->layer.up, pkt); | ||
181 | 163 | ||
164 | /* Release reference to stack upwards */ | ||
165 | caifd_put(caifd); | ||
182 | return 0; | 166 | return 0; |
183 | } | 167 | } |
184 | 168 | ||
@@ -189,15 +173,25 @@ static struct packet_type caif_packet_type __read_mostly = { | |||
189 | 173 | ||
190 | static void dev_flowctrl(struct net_device *dev, int on) | 174 | static void dev_flowctrl(struct net_device *dev, int on) |
191 | { | 175 | { |
192 | struct caif_device_entry *caifd = caif_get(dev); | 176 | struct caif_device_entry *caifd; |
193 | if (!caifd || !caifd->layer.up || !caifd->layer.up->ctrlcmd) | 177 | |
178 | rcu_read_lock(); | ||
179 | |||
180 | caifd = caif_get(dev); | ||
181 | if (!caifd || !caifd->layer.up || !caifd->layer.up->ctrlcmd) { | ||
182 | rcu_read_unlock(); | ||
194 | return; | 183 | return; |
184 | } | ||
185 | |||
186 | caifd_hold(caifd); | ||
187 | rcu_read_unlock(); | ||
195 | 188 | ||
196 | caifd->layer.up->ctrlcmd(caifd->layer.up, | 189 | caifd->layer.up->ctrlcmd(caifd->layer.up, |
197 | on ? | 190 | on ? |
198 | _CAIF_CTRLCMD_PHYIF_FLOW_ON_IND : | 191 | _CAIF_CTRLCMD_PHYIF_FLOW_ON_IND : |
199 | _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND, | 192 | _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND, |
200 | caifd->layer.id); | 193 | caifd->layer.id); |
194 | caifd_put(caifd); | ||
201 | } | 195 | } |
202 | 196 | ||
203 | /* notify Caif of device events */ | 197 | /* notify Caif of device events */ |
@@ -208,37 +202,28 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what, | |||
208 | struct caif_device_entry *caifd = NULL; | 202 | struct caif_device_entry *caifd = NULL; |
209 | struct caif_dev_common *caifdev; | 203 | struct caif_dev_common *caifdev; |
210 | enum cfcnfg_phy_preference pref; | 204 | enum cfcnfg_phy_preference pref; |
211 | int res = -EINVAL; | ||
212 | enum cfcnfg_phy_type phy_type; | 205 | enum cfcnfg_phy_type phy_type; |
206 | struct cfcnfg *cfg; | ||
207 | struct caif_device_entry_list *caifdevs = | ||
208 | caif_device_list(dev_net(dev)); | ||
213 | 209 | ||
214 | if (dev->type != ARPHRD_CAIF) | 210 | if (dev->type != ARPHRD_CAIF) |
215 | return 0; | 211 | return 0; |
216 | 212 | ||
213 | cfg = get_cfcnfg(dev_net(dev)); | ||
214 | if (cfg == NULL) | ||
215 | return 0; | ||
216 | |||
217 | switch (what) { | 217 | switch (what) { |
218 | case NETDEV_REGISTER: | 218 | case NETDEV_REGISTER: |
219 | netdev_info(dev, "register\n"); | ||
220 | caifd = caif_device_alloc(dev); | 219 | caifd = caif_device_alloc(dev); |
221 | if (caifd == NULL) | 220 | if (!caifd) |
222 | break; | 221 | return 0; |
222 | |||
223 | caifdev = netdev_priv(dev); | 223 | caifdev = netdev_priv(dev); |
224 | caifdev->flowctrl = dev_flowctrl; | 224 | caifdev->flowctrl = dev_flowctrl; |
225 | atomic_set(&caifd->state, what); | ||
226 | res = 0; | ||
227 | break; | ||
228 | 225 | ||
229 | case NETDEV_UP: | ||
230 | netdev_info(dev, "up\n"); | ||
231 | caifd = caif_get(dev); | ||
232 | if (caifd == NULL) | ||
233 | break; | ||
234 | caifdev = netdev_priv(dev); | ||
235 | if (atomic_read(&caifd->state) == NETDEV_UP) { | ||
236 | netdev_info(dev, "already up\n"); | ||
237 | break; | ||
238 | } | ||
239 | atomic_set(&caifd->state, what); | ||
240 | caifd->layer.transmit = transmit; | 226 | caifd->layer.transmit = transmit; |
241 | caifd->layer.modemcmd = modemcmd; | ||
242 | 227 | ||
243 | if (caifdev->use_frag) | 228 | if (caifdev->use_frag) |
244 | phy_type = CFPHYTYPE_FRAG; | 229 | phy_type = CFPHYTYPE_FRAG; |
@@ -256,62 +241,94 @@ static int caif_device_notify(struct notifier_block *me, unsigned long what, | |||
256 | pref = CFPHYPREF_HIGH_BW; | 241 | pref = CFPHYPREF_HIGH_BW; |
257 | break; | 242 | break; |
258 | } | 243 | } |
259 | dev_hold(dev); | 244 | strncpy(caifd->layer.name, dev->name, |
260 | cfcnfg_add_phy_layer(get_caif_conf(), | 245 | sizeof(caifd->layer.name) - 1); |
246 | caifd->layer.name[sizeof(caifd->layer.name) - 1] = 0; | ||
247 | |||
248 | mutex_lock(&caifdevs->lock); | ||
249 | list_add_rcu(&caifd->list, &caifdevs->list); | ||
250 | |||
251 | cfcnfg_add_phy_layer(cfg, | ||
261 | phy_type, | 252 | phy_type, |
262 | dev, | 253 | dev, |
263 | &caifd->layer, | 254 | &caifd->layer, |
264 | &caifd->phyid, | ||
265 | pref, | 255 | pref, |
266 | caifdev->use_fcs, | 256 | caifdev->use_fcs, |
267 | caifdev->use_stx); | 257 | caifdev->use_stx); |
268 | strncpy(caifd->layer.name, dev->name, | 258 | mutex_unlock(&caifdevs->lock); |
269 | sizeof(caifd->layer.name) - 1); | ||
270 | caifd->layer.name[sizeof(caifd->layer.name) - 1] = 0; | ||
271 | break; | 259 | break; |
272 | 260 | ||
273 | case NETDEV_GOING_DOWN: | 261 | case NETDEV_UP: |
262 | rcu_read_lock(); | ||
263 | |||
274 | caifd = caif_get(dev); | 264 | caifd = caif_get(dev); |
275 | if (caifd == NULL) | 265 | if (caifd == NULL) { |
266 | rcu_read_unlock(); | ||
276 | break; | 267 | break; |
277 | netdev_info(dev, "going down\n"); | 268 | } |
278 | 269 | ||
279 | if (atomic_read(&caifd->state) == NETDEV_GOING_DOWN || | 270 | cfcnfg_set_phy_state(cfg, &caifd->layer, true); |
280 | atomic_read(&caifd->state) == NETDEV_DOWN) | 271 | rcu_read_unlock(); |
281 | break; | ||
282 | 272 | ||
283 | atomic_set(&caifd->state, what); | ||
284 | if (!caifd || !caifd->layer.up || !caifd->layer.up->ctrlcmd) | ||
285 | return -EINVAL; | ||
286 | caifd->layer.up->ctrlcmd(caifd->layer.up, | ||
287 | _CAIF_CTRLCMD_PHYIF_DOWN_IND, | ||
288 | caifd->layer.id); | ||
289 | might_sleep(); | ||
290 | res = wait_event_interruptible_timeout(caifd->event, | ||
291 | atomic_read(&caifd->in_use) == 0, | ||
292 | TIMEOUT); | ||
293 | break; | 273 | break; |
294 | 274 | ||
295 | case NETDEV_DOWN: | 275 | case NETDEV_DOWN: |
276 | rcu_read_lock(); | ||
277 | |||
296 | caifd = caif_get(dev); | 278 | caifd = caif_get(dev); |
297 | if (caifd == NULL) | 279 | if (!caifd || !caifd->layer.up || !caifd->layer.up->ctrlcmd) { |
298 | break; | 280 | rcu_read_unlock(); |
299 | netdev_info(dev, "down\n"); | 281 | return -EINVAL; |
300 | if (atomic_read(&caifd->in_use)) | 282 | } |
301 | netdev_warn(dev, | 283 | |
302 | "Unregistering an active CAIF device\n"); | 284 | cfcnfg_set_phy_state(cfg, &caifd->layer, false); |
303 | cfcnfg_del_phy_layer(get_caif_conf(), &caifd->layer); | 285 | caifd_hold(caifd); |
304 | dev_put(dev); | 286 | rcu_read_unlock(); |
305 | atomic_set(&caifd->state, what); | 287 | |
288 | caifd->layer.up->ctrlcmd(caifd->layer.up, | ||
289 | _CAIF_CTRLCMD_PHYIF_DOWN_IND, | ||
290 | caifd->layer.id); | ||
291 | caifd_put(caifd); | ||
306 | break; | 292 | break; |
307 | 293 | ||
308 | case NETDEV_UNREGISTER: | 294 | case NETDEV_UNREGISTER: |
295 | mutex_lock(&caifdevs->lock); | ||
296 | |||
309 | caifd = caif_get(dev); | 297 | caifd = caif_get(dev); |
310 | if (caifd == NULL) | 298 | if (caifd == NULL) { |
299 | mutex_unlock(&caifdevs->lock); | ||
300 | break; | ||
301 | } | ||
302 | list_del_rcu(&caifd->list); | ||
303 | |||
304 | /* | ||
305 | * NETDEV_UNREGISTER is called repeatedly until all reference | ||
306 | * counts for the net-device are released. If references to | ||
307 | * caifd is taken, simply ignore NETDEV_UNREGISTER and wait for | ||
308 | * the next call to NETDEV_UNREGISTER. | ||
309 | * | ||
310 | * If any packets are in flight down the CAIF Stack, | ||
311 | * cfcnfg_del_phy_layer will return nonzero. | ||
312 | * If no packets are in flight, the CAIF Stack associated | ||
313 | * with the net-device un-registering is freed. | ||
314 | */ | ||
315 | |||
316 | if (caifd_refcnt_read(caifd) != 0 || | ||
317 | cfcnfg_del_phy_layer(cfg, &caifd->layer) != 0) { | ||
318 | |||
319 | pr_info("Wait for device inuse\n"); | ||
320 | /* Enrole device if CAIF Stack is still in use */ | ||
321 | list_add_rcu(&caifd->list, &caifdevs->list); | ||
322 | mutex_unlock(&caifdevs->lock); | ||
311 | break; | 323 | break; |
312 | netdev_info(dev, "unregister\n"); | 324 | } |
313 | atomic_set(&caifd->state, what); | 325 | |
314 | caif_device_destroy(dev); | 326 | synchronize_rcu(); |
327 | dev_put(caifd->netdev); | ||
328 | free_percpu(caifd->pcpu_refcnt); | ||
329 | kfree(caifd); | ||
330 | |||
331 | mutex_unlock(&caifdevs->lock); | ||
315 | break; | 332 | break; |
316 | } | 333 | } |
317 | return 0; | 334 | return 0; |
@@ -322,61 +339,60 @@ static struct notifier_block caif_device_notifier = { | |||
322 | .priority = 0, | 339 | .priority = 0, |
323 | }; | 340 | }; |
324 | 341 | ||
325 | |||
326 | struct cfcnfg *get_caif_conf(void) | ||
327 | { | ||
328 | return cfg; | ||
329 | } | ||
330 | EXPORT_SYMBOL(get_caif_conf); | ||
331 | |||
332 | int caif_connect_client(struct caif_connect_request *conn_req, | ||
333 | struct cflayer *client_layer, int *ifindex, | ||
334 | int *headroom, int *tailroom) | ||
335 | { | ||
336 | struct cfctrl_link_param param; | ||
337 | int ret; | ||
338 | ret = connect_req_to_link_param(get_caif_conf(), conn_req, ¶m); | ||
339 | if (ret) | ||
340 | return ret; | ||
341 | /* Hook up the adaptation layer. */ | ||
342 | return cfcnfg_add_adaptation_layer(get_caif_conf(), ¶m, | ||
343 | client_layer, ifindex, | ||
344 | headroom, tailroom); | ||
345 | } | ||
346 | EXPORT_SYMBOL(caif_connect_client); | ||
347 | |||
348 | int caif_disconnect_client(struct cflayer *adap_layer) | ||
349 | { | ||
350 | return cfcnfg_disconn_adapt_layer(get_caif_conf(), adap_layer); | ||
351 | } | ||
352 | EXPORT_SYMBOL(caif_disconnect_client); | ||
353 | |||
354 | void caif_release_client(struct cflayer *adap_layer) | ||
355 | { | ||
356 | cfcnfg_release_adap_layer(adap_layer); | ||
357 | } | ||
358 | EXPORT_SYMBOL(caif_release_client); | ||
359 | |||
360 | /* Per-namespace Caif devices handling */ | 342 | /* Per-namespace Caif devices handling */ |
361 | static int caif_init_net(struct net *net) | 343 | static int caif_init_net(struct net *net) |
362 | { | 344 | { |
363 | struct caif_net *caifn = net_generic(net, caif_net_id); | 345 | struct caif_net *caifn = net_generic(net, caif_net_id); |
346 | BUG_ON(!caifn); | ||
364 | INIT_LIST_HEAD(&caifn->caifdevs.list); | 347 | INIT_LIST_HEAD(&caifn->caifdevs.list); |
365 | spin_lock_init(&caifn->caifdevs.lock); | 348 | mutex_init(&caifn->caifdevs.lock); |
349 | |||
350 | caifn->cfg = cfcnfg_create(); | ||
351 | if (!caifn->cfg) { | ||
352 | pr_warn("can't create cfcnfg\n"); | ||
353 | return -ENOMEM; | ||
354 | } | ||
355 | |||
366 | return 0; | 356 | return 0; |
367 | } | 357 | } |
368 | 358 | ||
369 | static void caif_exit_net(struct net *net) | 359 | static void caif_exit_net(struct net *net) |
370 | { | 360 | { |
371 | struct net_device *dev; | 361 | struct caif_device_entry *caifd, *tmp; |
372 | int res; | 362 | struct caif_device_entry_list *caifdevs = |
363 | caif_device_list(net); | ||
364 | struct cfcnfg *cfg; | ||
365 | |||
373 | rtnl_lock(); | 366 | rtnl_lock(); |
374 | for_each_netdev(net, dev) { | 367 | mutex_lock(&caifdevs->lock); |
375 | if (dev->type != ARPHRD_CAIF) | 368 | |
376 | continue; | 369 | cfg = get_cfcnfg(net); |
377 | res = dev_close(dev); | 370 | if (cfg == NULL) { |
378 | caif_device_destroy(dev); | 371 | mutex_unlock(&caifdevs->lock); |
372 | return; | ||
379 | } | 373 | } |
374 | |||
375 | list_for_each_entry_safe(caifd, tmp, &caifdevs->list, list) { | ||
376 | int i = 0; | ||
377 | list_del_rcu(&caifd->list); | ||
378 | cfcnfg_set_phy_state(cfg, &caifd->layer, false); | ||
379 | |||
380 | while (i < 10 && | ||
381 | (caifd_refcnt_read(caifd) != 0 || | ||
382 | cfcnfg_del_phy_layer(cfg, &caifd->layer) != 0)) { | ||
383 | |||
384 | pr_info("Wait for device inuse\n"); | ||
385 | msleep(250); | ||
386 | i++; | ||
387 | } | ||
388 | synchronize_rcu(); | ||
389 | dev_put(caifd->netdev); | ||
390 | free_percpu(caifd->pcpu_refcnt); | ||
391 | kfree(caifd); | ||
392 | } | ||
393 | cfcnfg_remove(cfg); | ||
394 | |||
395 | mutex_unlock(&caifdevs->lock); | ||
380 | rtnl_unlock(); | 396 | rtnl_unlock(); |
381 | } | 397 | } |
382 | 398 | ||
@@ -391,32 +407,23 @@ static struct pernet_operations caif_net_ops = { | |||
391 | static int __init caif_device_init(void) | 407 | static int __init caif_device_init(void) |
392 | { | 408 | { |
393 | int result; | 409 | int result; |
394 | cfg = cfcnfg_create(); | 410 | |
395 | if (!cfg) { | ||
396 | pr_warn("can't create cfcnfg\n"); | ||
397 | goto err_cfcnfg_create_failed; | ||
398 | } | ||
399 | result = register_pernet_device(&caif_net_ops); | 411 | result = register_pernet_device(&caif_net_ops); |
400 | 412 | ||
401 | if (result) { | 413 | if (result) |
402 | kfree(cfg); | ||
403 | cfg = NULL; | ||
404 | return result; | 414 | return result; |
405 | } | 415 | |
406 | dev_add_pack(&caif_packet_type); | ||
407 | register_netdevice_notifier(&caif_device_notifier); | 416 | register_netdevice_notifier(&caif_device_notifier); |
417 | dev_add_pack(&caif_packet_type); | ||
408 | 418 | ||
409 | return result; | 419 | return result; |
410 | err_cfcnfg_create_failed: | ||
411 | return -ENODEV; | ||
412 | } | 420 | } |
413 | 421 | ||
414 | static void __exit caif_device_exit(void) | 422 | static void __exit caif_device_exit(void) |
415 | { | 423 | { |
416 | dev_remove_pack(&caif_packet_type); | ||
417 | unregister_pernet_device(&caif_net_ops); | 424 | unregister_pernet_device(&caif_net_ops); |
418 | unregister_netdevice_notifier(&caif_device_notifier); | 425 | unregister_netdevice_notifier(&caif_device_notifier); |
419 | cfcnfg_remove(cfg); | 426 | dev_remove_pack(&caif_packet_type); |
420 | } | 427 | } |
421 | 428 | ||
422 | module_init(caif_device_init); | 429 | module_init(caif_device_init); |
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index 8184c031d028..b840395ced1d 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c | |||
@@ -48,6 +48,7 @@ static struct dentry *debugfsdir; | |||
48 | #ifdef CONFIG_DEBUG_FS | 48 | #ifdef CONFIG_DEBUG_FS |
49 | struct debug_fs_counter { | 49 | struct debug_fs_counter { |
50 | atomic_t caif_nr_socks; | 50 | atomic_t caif_nr_socks; |
51 | atomic_t caif_sock_create; | ||
51 | atomic_t num_connect_req; | 52 | atomic_t num_connect_req; |
52 | atomic_t num_connect_resp; | 53 | atomic_t num_connect_resp; |
53 | atomic_t num_connect_fail_resp; | 54 | atomic_t num_connect_fail_resp; |
@@ -59,11 +60,11 @@ struct debug_fs_counter { | |||
59 | atomic_t num_rx_flow_on; | 60 | atomic_t num_rx_flow_on; |
60 | }; | 61 | }; |
61 | static struct debug_fs_counter cnt; | 62 | static struct debug_fs_counter cnt; |
62 | #define dbfs_atomic_inc(v) atomic_inc(v) | 63 | #define dbfs_atomic_inc(v) atomic_inc_return(v) |
63 | #define dbfs_atomic_dec(v) atomic_dec(v) | 64 | #define dbfs_atomic_dec(v) atomic_dec_return(v) |
64 | #else | 65 | #else |
65 | #define dbfs_atomic_inc(v) | 66 | #define dbfs_atomic_inc(v) 0 |
66 | #define dbfs_atomic_dec(v) | 67 | #define dbfs_atomic_dec(v) 0 |
67 | #endif | 68 | #endif |
68 | 69 | ||
69 | struct caifsock { | 70 | struct caifsock { |
@@ -155,9 +156,10 @@ static int caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
155 | 156 | ||
156 | if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= | 157 | if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= |
157 | (unsigned)sk->sk_rcvbuf && rx_flow_is_on(cf_sk)) { | 158 | (unsigned)sk->sk_rcvbuf && rx_flow_is_on(cf_sk)) { |
158 | pr_debug("sending flow OFF (queue len = %d %d)\n", | 159 | if (net_ratelimit()) |
159 | atomic_read(&cf_sk->sk.sk_rmem_alloc), | 160 | pr_debug("sending flow OFF (queue len = %d %d)\n", |
160 | sk_rcvbuf_lowwater(cf_sk)); | 161 | atomic_read(&cf_sk->sk.sk_rmem_alloc), |
162 | sk_rcvbuf_lowwater(cf_sk)); | ||
161 | set_rx_flow_off(cf_sk); | 163 | set_rx_flow_off(cf_sk); |
162 | dbfs_atomic_inc(&cnt.num_rx_flow_off); | 164 | dbfs_atomic_inc(&cnt.num_rx_flow_off); |
163 | caif_flow_ctrl(sk, CAIF_MODEMCMD_FLOW_OFF_REQ); | 165 | caif_flow_ctrl(sk, CAIF_MODEMCMD_FLOW_OFF_REQ); |
@@ -168,7 +170,8 @@ static int caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
168 | return err; | 170 | return err; |
169 | if (!sk_rmem_schedule(sk, skb->truesize) && rx_flow_is_on(cf_sk)) { | 171 | if (!sk_rmem_schedule(sk, skb->truesize) && rx_flow_is_on(cf_sk)) { |
170 | set_rx_flow_off(cf_sk); | 172 | set_rx_flow_off(cf_sk); |
171 | pr_debug("sending flow OFF due to rmem_schedule\n"); | 173 | if (net_ratelimit()) |
174 | pr_debug("sending flow OFF due to rmem_schedule\n"); | ||
172 | dbfs_atomic_inc(&cnt.num_rx_flow_off); | 175 | dbfs_atomic_inc(&cnt.num_rx_flow_off); |
173 | caif_flow_ctrl(sk, CAIF_MODEMCMD_FLOW_OFF_REQ); | 176 | caif_flow_ctrl(sk, CAIF_MODEMCMD_FLOW_OFF_REQ); |
174 | } | 177 | } |
@@ -202,13 +205,25 @@ static int caif_sktrecv_cb(struct cflayer *layr, struct cfpkt *pkt) | |||
202 | skb = cfpkt_tonative(pkt); | 205 | skb = cfpkt_tonative(pkt); |
203 | 206 | ||
204 | if (unlikely(cf_sk->sk.sk_state != CAIF_CONNECTED)) { | 207 | if (unlikely(cf_sk->sk.sk_state != CAIF_CONNECTED)) { |
205 | cfpkt_destroy(pkt); | 208 | kfree_skb(skb); |
206 | return 0; | 209 | return 0; |
207 | } | 210 | } |
208 | caif_queue_rcv_skb(&cf_sk->sk, skb); | 211 | caif_queue_rcv_skb(&cf_sk->sk, skb); |
209 | return 0; | 212 | return 0; |
210 | } | 213 | } |
211 | 214 | ||
215 | static void cfsk_hold(struct cflayer *layr) | ||
216 | { | ||
217 | struct caifsock *cf_sk = container_of(layr, struct caifsock, layer); | ||
218 | sock_hold(&cf_sk->sk); | ||
219 | } | ||
220 | |||
221 | static void cfsk_put(struct cflayer *layr) | ||
222 | { | ||
223 | struct caifsock *cf_sk = container_of(layr, struct caifsock, layer); | ||
224 | sock_put(&cf_sk->sk); | ||
225 | } | ||
226 | |||
212 | /* Packet Control Callback function called from CAIF */ | 227 | /* Packet Control Callback function called from CAIF */ |
213 | static void caif_ctrl_cb(struct cflayer *layr, | 228 | static void caif_ctrl_cb(struct cflayer *layr, |
214 | enum caif_ctrlcmd flow, | 229 | enum caif_ctrlcmd flow, |
@@ -232,6 +247,8 @@ static void caif_ctrl_cb(struct cflayer *layr, | |||
232 | 247 | ||
233 | case CAIF_CTRLCMD_INIT_RSP: | 248 | case CAIF_CTRLCMD_INIT_RSP: |
234 | /* We're now connected */ | 249 | /* We're now connected */ |
250 | caif_client_register_refcnt(&cf_sk->layer, | ||
251 | cfsk_hold, cfsk_put); | ||
235 | dbfs_atomic_inc(&cnt.num_connect_resp); | 252 | dbfs_atomic_inc(&cnt.num_connect_resp); |
236 | cf_sk->sk.sk_state = CAIF_CONNECTED; | 253 | cf_sk->sk.sk_state = CAIF_CONNECTED; |
237 | set_tx_flow_on(cf_sk); | 254 | set_tx_flow_on(cf_sk); |
@@ -242,7 +259,6 @@ static void caif_ctrl_cb(struct cflayer *layr, | |||
242 | /* We're now disconnected */ | 259 | /* We're now disconnected */ |
243 | cf_sk->sk.sk_state = CAIF_DISCONNECTED; | 260 | cf_sk->sk.sk_state = CAIF_DISCONNECTED; |
244 | cf_sk->sk.sk_state_change(&cf_sk->sk); | 261 | cf_sk->sk.sk_state_change(&cf_sk->sk); |
245 | cfcnfg_release_adap_layer(&cf_sk->layer); | ||
246 | break; | 262 | break; |
247 | 263 | ||
248 | case CAIF_CTRLCMD_INIT_FAIL_RSP: | 264 | case CAIF_CTRLCMD_INIT_FAIL_RSP: |
@@ -519,43 +535,14 @@ static int transmit_skb(struct sk_buff *skb, struct caifsock *cf_sk, | |||
519 | int noblock, long timeo) | 535 | int noblock, long timeo) |
520 | { | 536 | { |
521 | struct cfpkt *pkt; | 537 | struct cfpkt *pkt; |
522 | int ret, loopcnt = 0; | ||
523 | 538 | ||
524 | pkt = cfpkt_fromnative(CAIF_DIR_OUT, skb); | 539 | pkt = cfpkt_fromnative(CAIF_DIR_OUT, skb); |
525 | memset(cfpkt_info(pkt), 0, sizeof(struct caif_payload_info)); | 540 | memset(skb->cb, 0, sizeof(struct caif_payload_info)); |
526 | do { | ||
527 | 541 | ||
528 | ret = -ETIMEDOUT; | 542 | if (cf_sk->layer.dn == NULL) |
543 | return -EINVAL; | ||
529 | 544 | ||
530 | /* Slight paranoia, probably not needed. */ | 545 | return cf_sk->layer.dn->transmit(cf_sk->layer.dn, pkt); |
531 | if (unlikely(loopcnt++ > 1000)) { | ||
532 | pr_warn("transmit retries failed, error = %d\n", ret); | ||
533 | break; | ||
534 | } | ||
535 | |||
536 | if (cf_sk->layer.dn != NULL) | ||
537 | ret = cf_sk->layer.dn->transmit(cf_sk->layer.dn, pkt); | ||
538 | if (likely(ret >= 0)) | ||
539 | break; | ||
540 | /* if transmit return -EAGAIN, then retry */ | ||
541 | if (noblock && ret == -EAGAIN) | ||
542 | break; | ||
543 | timeo = caif_wait_for_flow_on(cf_sk, 0, timeo, &ret); | ||
544 | if (signal_pending(current)) { | ||
545 | ret = sock_intr_errno(timeo); | ||
546 | break; | ||
547 | } | ||
548 | if (ret) | ||
549 | break; | ||
550 | if (cf_sk->sk.sk_state != CAIF_CONNECTED || | ||
551 | sock_flag(&cf_sk->sk, SOCK_DEAD) || | ||
552 | (cf_sk->sk.sk_shutdown & RCV_SHUTDOWN)) { | ||
553 | ret = -EPIPE; | ||
554 | cf_sk->sk.sk_err = EPIPE; | ||
555 | break; | ||
556 | } | ||
557 | } while (ret == -EAGAIN); | ||
558 | return ret; | ||
559 | } | 546 | } |
560 | 547 | ||
561 | /* Copied from af_unix:unix_dgram_sendmsg, and adapted to CAIF */ | 548 | /* Copied from af_unix:unix_dgram_sendmsg, and adapted to CAIF */ |
@@ -620,7 +607,9 @@ static int caif_seqpkt_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
620 | goto err; | 607 | goto err; |
621 | ret = transmit_skb(skb, cf_sk, noblock, timeo); | 608 | ret = transmit_skb(skb, cf_sk, noblock, timeo); |
622 | if (ret < 0) | 609 | if (ret < 0) |
623 | goto err; | 610 | /* skb is already freed */ |
611 | return ret; | ||
612 | |||
624 | return len; | 613 | return len; |
625 | err: | 614 | err: |
626 | kfree_skb(skb); | 615 | kfree_skb(skb); |
@@ -826,7 +815,7 @@ static int caif_connect(struct socket *sock, struct sockaddr *uaddr, | |||
826 | sk->sk_state == CAIF_DISCONNECTED); | 815 | sk->sk_state == CAIF_DISCONNECTED); |
827 | if (sk->sk_shutdown & SHUTDOWN_MASK) { | 816 | if (sk->sk_shutdown & SHUTDOWN_MASK) { |
828 | /* Allow re-connect after SHUTDOWN_IND */ | 817 | /* Allow re-connect after SHUTDOWN_IND */ |
829 | caif_disconnect_client(&cf_sk->layer); | 818 | caif_disconnect_client(sock_net(sk), &cf_sk->layer); |
830 | break; | 819 | break; |
831 | } | 820 | } |
832 | /* No reconnect on a seqpacket socket */ | 821 | /* No reconnect on a seqpacket socket */ |
@@ -866,8 +855,10 @@ static int caif_connect(struct socket *sock, struct sockaddr *uaddr, | |||
866 | 855 | ||
867 | dbfs_atomic_inc(&cnt.num_connect_req); | 856 | dbfs_atomic_inc(&cnt.num_connect_req); |
868 | cf_sk->layer.receive = caif_sktrecv_cb; | 857 | cf_sk->layer.receive = caif_sktrecv_cb; |
869 | err = caif_connect_client(&cf_sk->conn_req, | 858 | |
859 | err = caif_connect_client(sock_net(sk), &cf_sk->conn_req, | ||
870 | &cf_sk->layer, &ifindex, &headroom, &tailroom); | 860 | &cf_sk->layer, &ifindex, &headroom, &tailroom); |
861 | |||
871 | if (err < 0) { | 862 | if (err < 0) { |
872 | cf_sk->sk.sk_socket->state = SS_UNCONNECTED; | 863 | cf_sk->sk.sk_socket->state = SS_UNCONNECTED; |
873 | cf_sk->sk.sk_state = CAIF_DISCONNECTED; | 864 | cf_sk->sk.sk_state = CAIF_DISCONNECTED; |
@@ -947,13 +938,14 @@ static int caif_release(struct socket *sock) | |||
947 | * caif_queue_rcv_skb checks SOCK_DEAD holding the queue lock, | 938 | * caif_queue_rcv_skb checks SOCK_DEAD holding the queue lock, |
948 | * this ensures no packets when sock is dead. | 939 | * this ensures no packets when sock is dead. |
949 | */ | 940 | */ |
950 | spin_lock(&sk->sk_receive_queue.lock); | 941 | spin_lock_bh(&sk->sk_receive_queue.lock); |
951 | sock_set_flag(sk, SOCK_DEAD); | 942 | sock_set_flag(sk, SOCK_DEAD); |
952 | spin_unlock(&sk->sk_receive_queue.lock); | 943 | spin_unlock_bh(&sk->sk_receive_queue.lock); |
953 | sock->sk = NULL; | 944 | sock->sk = NULL; |
954 | 945 | ||
955 | dbfs_atomic_inc(&cnt.num_disconnect); | 946 | dbfs_atomic_inc(&cnt.num_disconnect); |
956 | 947 | ||
948 | WARN_ON(IS_ERR(cf_sk->debugfs_socket_dir)); | ||
957 | if (cf_sk->debugfs_socket_dir != NULL) | 949 | if (cf_sk->debugfs_socket_dir != NULL) |
958 | debugfs_remove_recursive(cf_sk->debugfs_socket_dir); | 950 | debugfs_remove_recursive(cf_sk->debugfs_socket_dir); |
959 | 951 | ||
@@ -963,13 +955,12 @@ static int caif_release(struct socket *sock) | |||
963 | 955 | ||
964 | if (cf_sk->sk.sk_socket->state == SS_CONNECTED || | 956 | if (cf_sk->sk.sk_socket->state == SS_CONNECTED || |
965 | cf_sk->sk.sk_socket->state == SS_CONNECTING) | 957 | cf_sk->sk.sk_socket->state == SS_CONNECTING) |
966 | res = caif_disconnect_client(&cf_sk->layer); | 958 | res = caif_disconnect_client(sock_net(sk), &cf_sk->layer); |
967 | 959 | ||
968 | cf_sk->sk.sk_socket->state = SS_DISCONNECTING; | 960 | cf_sk->sk.sk_socket->state = SS_DISCONNECTING; |
969 | wake_up_interruptible_poll(sk_sleep(sk), POLLERR|POLLHUP); | 961 | wake_up_interruptible_poll(sk_sleep(sk), POLLERR|POLLHUP); |
970 | 962 | ||
971 | sock_orphan(sk); | 963 | sock_orphan(sk); |
972 | cf_sk->layer.dn = NULL; | ||
973 | sk_stream_kill_queues(&cf_sk->sk); | 964 | sk_stream_kill_queues(&cf_sk->sk); |
974 | release_sock(sk); | 965 | release_sock(sk); |
975 | sock_put(sk); | 966 | sock_put(sk); |
@@ -1060,16 +1051,18 @@ static void caif_sock_destructor(struct sock *sk) | |||
1060 | caif_assert(sk_unhashed(sk)); | 1051 | caif_assert(sk_unhashed(sk)); |
1061 | caif_assert(!sk->sk_socket); | 1052 | caif_assert(!sk->sk_socket); |
1062 | if (!sock_flag(sk, SOCK_DEAD)) { | 1053 | if (!sock_flag(sk, SOCK_DEAD)) { |
1063 | pr_info("Attempt to release alive CAIF socket: %p\n", sk); | 1054 | pr_debug("Attempt to release alive CAIF socket: %p\n", sk); |
1064 | return; | 1055 | return; |
1065 | } | 1056 | } |
1066 | sk_stream_kill_queues(&cf_sk->sk); | 1057 | sk_stream_kill_queues(&cf_sk->sk); |
1067 | dbfs_atomic_dec(&cnt.caif_nr_socks); | 1058 | dbfs_atomic_dec(&cnt.caif_nr_socks); |
1059 | caif_free_client(&cf_sk->layer); | ||
1068 | } | 1060 | } |
1069 | 1061 | ||
1070 | static int caif_create(struct net *net, struct socket *sock, int protocol, | 1062 | static int caif_create(struct net *net, struct socket *sock, int protocol, |
1071 | int kern) | 1063 | int kern) |
1072 | { | 1064 | { |
1065 | int num; | ||
1073 | struct sock *sk = NULL; | 1066 | struct sock *sk = NULL; |
1074 | struct caifsock *cf_sk = NULL; | 1067 | struct caifsock *cf_sk = NULL; |
1075 | static struct proto prot = {.name = "PF_CAIF", | 1068 | static struct proto prot = {.name = "PF_CAIF", |
@@ -1132,14 +1125,16 @@ static int caif_create(struct net *net, struct socket *sock, int protocol, | |||
1132 | cf_sk->conn_req.protocol = protocol; | 1125 | cf_sk->conn_req.protocol = protocol; |
1133 | /* Increase the number of sockets created. */ | 1126 | /* Increase the number of sockets created. */ |
1134 | dbfs_atomic_inc(&cnt.caif_nr_socks); | 1127 | dbfs_atomic_inc(&cnt.caif_nr_socks); |
1128 | num = dbfs_atomic_inc(&cnt.caif_sock_create); | ||
1135 | #ifdef CONFIG_DEBUG_FS | 1129 | #ifdef CONFIG_DEBUG_FS |
1136 | if (!IS_ERR(debugfsdir)) { | 1130 | if (!IS_ERR(debugfsdir)) { |
1131 | |||
1137 | /* Fill in some information concerning the misc socket. */ | 1132 | /* Fill in some information concerning the misc socket. */ |
1138 | snprintf(cf_sk->name, sizeof(cf_sk->name), "cfsk%d", | 1133 | snprintf(cf_sk->name, sizeof(cf_sk->name), "cfsk%d", num); |
1139 | atomic_read(&cnt.caif_nr_socks)); | ||
1140 | 1134 | ||
1141 | cf_sk->debugfs_socket_dir = | 1135 | cf_sk->debugfs_socket_dir = |
1142 | debugfs_create_dir(cf_sk->name, debugfsdir); | 1136 | debugfs_create_dir(cf_sk->name, debugfsdir); |
1137 | |||
1143 | debugfs_create_u32("sk_state", S_IRUSR | S_IWUSR, | 1138 | debugfs_create_u32("sk_state", S_IRUSR | S_IWUSR, |
1144 | cf_sk->debugfs_socket_dir, | 1139 | cf_sk->debugfs_socket_dir, |
1145 | (u32 *) &cf_sk->sk.sk_state); | 1140 | (u32 *) &cf_sk->sk.sk_state); |
@@ -1183,6 +1178,9 @@ static int __init caif_sktinit_module(void) | |||
1183 | debugfs_create_u32("num_sockets", S_IRUSR | S_IWUSR, | 1178 | debugfs_create_u32("num_sockets", S_IRUSR | S_IWUSR, |
1184 | debugfsdir, | 1179 | debugfsdir, |
1185 | (u32 *) &cnt.caif_nr_socks); | 1180 | (u32 *) &cnt.caif_nr_socks); |
1181 | debugfs_create_u32("num_create", S_IRUSR | S_IWUSR, | ||
1182 | debugfsdir, | ||
1183 | (u32 *) &cnt.caif_sock_create); | ||
1186 | debugfs_create_u32("num_connect_req", S_IRUSR | S_IWUSR, | 1184 | debugfs_create_u32("num_connect_req", S_IRUSR | S_IWUSR, |
1187 | debugfsdir, | 1185 | debugfsdir, |
1188 | (u32 *) &cnt.num_connect_req); | 1186 | (u32 *) &cnt.num_connect_req); |
diff --git a/net/caif/cfcnfg.c b/net/caif/cfcnfg.c index f1f98d967d8a..351c2ca7e7b9 100644 --- a/net/caif/cfcnfg.c +++ b/net/caif/cfcnfg.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/stddef.h> | 10 | #include <linux/stddef.h> |
11 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
12 | #include <linux/netdevice.h> | 12 | #include <linux/netdevice.h> |
13 | #include <linux/module.h> | ||
13 | #include <net/caif/caif_layer.h> | 14 | #include <net/caif/caif_layer.h> |
14 | #include <net/caif/cfpkt.h> | 15 | #include <net/caif/cfpkt.h> |
15 | #include <net/caif/cfcnfg.h> | 16 | #include <net/caif/cfcnfg.h> |
@@ -18,11 +19,7 @@ | |||
18 | #include <net/caif/cffrml.h> | 19 | #include <net/caif/cffrml.h> |
19 | #include <net/caif/cfserl.h> | 20 | #include <net/caif/cfserl.h> |
20 | #include <net/caif/cfsrvl.h> | 21 | #include <net/caif/cfsrvl.h> |
21 | 22 | #include <net/caif/caif_dev.h> | |
22 | #include <linux/module.h> | ||
23 | #include <asm/atomic.h> | ||
24 | |||
25 | #define MAX_PHY_LAYERS 7 | ||
26 | 23 | ||
27 | #define container_obj(layr) container_of(layr, struct cfcnfg, layer) | 24 | #define container_obj(layr) container_of(layr, struct cfcnfg, layer) |
28 | 25 | ||
@@ -30,6 +27,9 @@ | |||
30 | * to manage physical interfaces | 27 | * to manage physical interfaces |
31 | */ | 28 | */ |
32 | struct cfcnfg_phyinfo { | 29 | struct cfcnfg_phyinfo { |
30 | struct list_head node; | ||
31 | bool up; | ||
32 | |||
33 | /* Pointer to the layer below the MUX (framing layer) */ | 33 | /* Pointer to the layer below the MUX (framing layer) */ |
34 | struct cflayer *frm_layer; | 34 | struct cflayer *frm_layer; |
35 | /* Pointer to the lowest actual physical layer */ | 35 | /* Pointer to the lowest actual physical layer */ |
@@ -39,9 +39,6 @@ struct cfcnfg_phyinfo { | |||
39 | /* Preference of the physical in interface */ | 39 | /* Preference of the physical in interface */ |
40 | enum cfcnfg_phy_preference pref; | 40 | enum cfcnfg_phy_preference pref; |
41 | 41 | ||
42 | /* Reference count, number of channels using the device */ | ||
43 | int phy_ref_count; | ||
44 | |||
45 | /* Information about the physical device */ | 42 | /* Information about the physical device */ |
46 | struct dev_info dev_info; | 43 | struct dev_info dev_info; |
47 | 44 | ||
@@ -59,8 +56,8 @@ struct cfcnfg { | |||
59 | struct cflayer layer; | 56 | struct cflayer layer; |
60 | struct cflayer *ctrl; | 57 | struct cflayer *ctrl; |
61 | struct cflayer *mux; | 58 | struct cflayer *mux; |
62 | u8 last_phyid; | 59 | struct list_head phys; |
63 | struct cfcnfg_phyinfo phy_layers[MAX_PHY_LAYERS]; | 60 | struct mutex lock; |
64 | }; | 61 | }; |
65 | 62 | ||
66 | static void cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, | 63 | static void cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, |
@@ -76,6 +73,9 @@ struct cfcnfg *cfcnfg_create(void) | |||
76 | { | 73 | { |
77 | struct cfcnfg *this; | 74 | struct cfcnfg *this; |
78 | struct cfctrl_rsp *resp; | 75 | struct cfctrl_rsp *resp; |
76 | |||
77 | might_sleep(); | ||
78 | |||
79 | /* Initiate this layer */ | 79 | /* Initiate this layer */ |
80 | this = kzalloc(sizeof(struct cfcnfg), GFP_ATOMIC); | 80 | this = kzalloc(sizeof(struct cfcnfg), GFP_ATOMIC); |
81 | if (!this) { | 81 | if (!this) { |
@@ -99,27 +99,33 @@ struct cfcnfg *cfcnfg_create(void) | |||
99 | resp->radioset_rsp = cfctrl_resp_func; | 99 | resp->radioset_rsp = cfctrl_resp_func; |
100 | resp->linksetup_rsp = cfcnfg_linkup_rsp; | 100 | resp->linksetup_rsp = cfcnfg_linkup_rsp; |
101 | resp->reject_rsp = cfcnfg_reject_rsp; | 101 | resp->reject_rsp = cfcnfg_reject_rsp; |
102 | 102 | INIT_LIST_HEAD(&this->phys); | |
103 | this->last_phyid = 1; | ||
104 | 103 | ||
105 | cfmuxl_set_uplayer(this->mux, this->ctrl, 0); | 104 | cfmuxl_set_uplayer(this->mux, this->ctrl, 0); |
106 | layer_set_dn(this->ctrl, this->mux); | 105 | layer_set_dn(this->ctrl, this->mux); |
107 | layer_set_up(this->ctrl, this); | 106 | layer_set_up(this->ctrl, this); |
107 | mutex_init(&this->lock); | ||
108 | |||
108 | return this; | 109 | return this; |
109 | out_of_mem: | 110 | out_of_mem: |
110 | pr_warn("Out of memory\n"); | 111 | pr_warn("Out of memory\n"); |
112 | |||
113 | synchronize_rcu(); | ||
114 | |||
111 | kfree(this->mux); | 115 | kfree(this->mux); |
112 | kfree(this->ctrl); | 116 | kfree(this->ctrl); |
113 | kfree(this); | 117 | kfree(this); |
114 | return NULL; | 118 | return NULL; |
115 | } | 119 | } |
116 | EXPORT_SYMBOL(cfcnfg_create); | ||
117 | 120 | ||
118 | void cfcnfg_remove(struct cfcnfg *cfg) | 121 | void cfcnfg_remove(struct cfcnfg *cfg) |
119 | { | 122 | { |
123 | might_sleep(); | ||
120 | if (cfg) { | 124 | if (cfg) { |
125 | synchronize_rcu(); | ||
126 | |||
121 | kfree(cfg->mux); | 127 | kfree(cfg->mux); |
122 | kfree(cfg->ctrl); | 128 | cfctrl_remove(cfg->ctrl); |
123 | kfree(cfg); | 129 | kfree(cfg); |
124 | } | 130 | } |
125 | } | 131 | } |
@@ -128,132 +134,96 @@ static void cfctrl_resp_func(void) | |||
128 | { | 134 | { |
129 | } | 135 | } |
130 | 136 | ||
137 | static struct cfcnfg_phyinfo *cfcnfg_get_phyinfo_rcu(struct cfcnfg *cnfg, | ||
138 | u8 phyid) | ||
139 | { | ||
140 | struct cfcnfg_phyinfo *phy; | ||
141 | |||
142 | list_for_each_entry_rcu(phy, &cnfg->phys, node) | ||
143 | if (phy->id == phyid) | ||
144 | return phy; | ||
145 | return NULL; | ||
146 | } | ||
147 | |||
131 | static void cfctrl_enum_resp(void) | 148 | static void cfctrl_enum_resp(void) |
132 | { | 149 | { |
133 | } | 150 | } |
134 | 151 | ||
135 | struct dev_info *cfcnfg_get_phyid(struct cfcnfg *cnfg, | 152 | static struct dev_info *cfcnfg_get_phyid(struct cfcnfg *cnfg, |
136 | enum cfcnfg_phy_preference phy_pref) | 153 | enum cfcnfg_phy_preference phy_pref) |
137 | { | 154 | { |
138 | u16 i; | ||
139 | |||
140 | /* Try to match with specified preference */ | 155 | /* Try to match with specified preference */ |
141 | for (i = 1; i < MAX_PHY_LAYERS; i++) { | 156 | struct cfcnfg_phyinfo *phy; |
142 | if (cnfg->phy_layers[i].id == i && | 157 | |
143 | cnfg->phy_layers[i].pref == phy_pref && | 158 | list_for_each_entry_rcu(phy, &cnfg->phys, node) { |
144 | cnfg->phy_layers[i].frm_layer != NULL) { | 159 | if (phy->up && phy->pref == phy_pref && |
145 | caif_assert(cnfg->phy_layers != NULL); | 160 | phy->frm_layer != NULL) |
146 | caif_assert(cnfg->phy_layers[i].id == i); | 161 | |
147 | return &cnfg->phy_layers[i].dev_info; | 162 | return &phy->dev_info; |
148 | } | ||
149 | } | 163 | } |
164 | |||
150 | /* Otherwise just return something */ | 165 | /* Otherwise just return something */ |
151 | for (i = 1; i < MAX_PHY_LAYERS; i++) { | 166 | list_for_each_entry_rcu(phy, &cnfg->phys, node) |
152 | if (cnfg->phy_layers[i].id == i) { | 167 | if (phy->up) |
153 | caif_assert(cnfg->phy_layers != NULL); | 168 | return &phy->dev_info; |
154 | caif_assert(cnfg->phy_layers[i].id == i); | ||
155 | return &cnfg->phy_layers[i].dev_info; | ||
156 | } | ||
157 | } | ||
158 | 169 | ||
159 | return NULL; | 170 | return NULL; |
160 | } | 171 | } |
161 | 172 | ||
162 | static struct cfcnfg_phyinfo *cfcnfg_get_phyinfo(struct cfcnfg *cnfg, | 173 | static int cfcnfg_get_id_from_ifi(struct cfcnfg *cnfg, int ifi) |
163 | u8 phyid) | ||
164 | { | 174 | { |
165 | int i; | 175 | struct cfcnfg_phyinfo *phy; |
166 | /* Try to match with specified preference */ | ||
167 | for (i = 0; i < MAX_PHY_LAYERS; i++) | ||
168 | if (cnfg->phy_layers[i].frm_layer != NULL && | ||
169 | cnfg->phy_layers[i].id == phyid) | ||
170 | return &cnfg->phy_layers[i]; | ||
171 | return NULL; | ||
172 | } | ||
173 | |||
174 | 176 | ||
175 | int cfcnfg_get_id_from_ifi(struct cfcnfg *cnfg, int ifi) | 177 | list_for_each_entry_rcu(phy, &cnfg->phys, node) |
176 | { | 178 | if (phy->ifindex == ifi && phy->up) |
177 | int i; | 179 | return phy->id; |
178 | for (i = 0; i < MAX_PHY_LAYERS; i++) | ||
179 | if (cnfg->phy_layers[i].frm_layer != NULL && | ||
180 | cnfg->phy_layers[i].ifindex == ifi) | ||
181 | return i; | ||
182 | return -ENODEV; | 180 | return -ENODEV; |
183 | } | 181 | } |
184 | 182 | ||
185 | int cfcnfg_disconn_adapt_layer(struct cfcnfg *cnfg, struct cflayer *adap_layer) | 183 | int caif_disconnect_client(struct net *net, struct cflayer *adap_layer) |
186 | { | 184 | { |
187 | u8 channel_id = 0; | 185 | u8 channel_id = 0; |
188 | int ret = 0; | 186 | int ret = 0; |
189 | struct cflayer *servl = NULL; | 187 | struct cflayer *servl = NULL; |
190 | struct cfcnfg_phyinfo *phyinfo = NULL; | 188 | struct cfcnfg *cfg = get_cfcnfg(net); |
191 | u8 phyid = 0; | ||
192 | 189 | ||
193 | caif_assert(adap_layer != NULL); | 190 | caif_assert(adap_layer != NULL); |
191 | |||
194 | channel_id = adap_layer->id; | 192 | channel_id = adap_layer->id; |
195 | if (adap_layer->dn == NULL || channel_id == 0) { | 193 | if (adap_layer->dn == NULL || channel_id == 0) { |
196 | pr_err("adap_layer->dn == NULL or adap_layer->id is 0\n"); | 194 | pr_err("adap_layer->dn == NULL or adap_layer->id is 0\n"); |
197 | ret = -ENOTCONN; | 195 | ret = -ENOTCONN; |
198 | goto end; | 196 | goto end; |
199 | } | 197 | } |
200 | servl = cfmuxl_remove_uplayer(cnfg->mux, channel_id); | 198 | |
199 | servl = cfmuxl_remove_uplayer(cfg->mux, channel_id); | ||
201 | if (servl == NULL) { | 200 | if (servl == NULL) { |
202 | pr_err("PROTOCOL ERROR - Error removing service_layer Channel_Id(%d)", | 201 | pr_err("PROTOCOL ERROR - " |
203 | channel_id); | 202 | "Error removing service_layer Channel_Id(%d)", |
203 | channel_id); | ||
204 | ret = -EINVAL; | 204 | ret = -EINVAL; |
205 | goto end; | 205 | goto end; |
206 | } | 206 | } |
207 | layer_set_up(servl, NULL); | 207 | |
208 | ret = cfctrl_linkdown_req(cnfg->ctrl, channel_id, adap_layer); | 208 | ret = cfctrl_linkdown_req(cfg->ctrl, channel_id, adap_layer); |
209 | if (ret) | 209 | |
210 | goto end; | ||
211 | caif_assert(channel_id == servl->id); | ||
212 | if (adap_layer->dn != NULL) { | ||
213 | phyid = cfsrvl_getphyid(adap_layer->dn); | ||
214 | |||
215 | phyinfo = cfcnfg_get_phyinfo(cnfg, phyid); | ||
216 | if (phyinfo == NULL) { | ||
217 | pr_warn("No interface to send disconnect to\n"); | ||
218 | ret = -ENODEV; | ||
219 | goto end; | ||
220 | } | ||
221 | if (phyinfo->id != phyid || | ||
222 | phyinfo->phy_layer->id != phyid || | ||
223 | phyinfo->frm_layer->id != phyid) { | ||
224 | pr_err("Inconsistency in phy registration\n"); | ||
225 | ret = -EINVAL; | ||
226 | goto end; | ||
227 | } | ||
228 | } | ||
229 | if (phyinfo != NULL && --phyinfo->phy_ref_count == 0 && | ||
230 | phyinfo->phy_layer != NULL && | ||
231 | phyinfo->phy_layer->modemcmd != NULL) { | ||
232 | phyinfo->phy_layer->modemcmd(phyinfo->phy_layer, | ||
233 | _CAIF_MODEMCMD_PHYIF_USELESS); | ||
234 | } | ||
235 | end: | 210 | end: |
236 | cfsrvl_put(servl); | 211 | cfctrl_cancel_req(cfg->ctrl, adap_layer); |
237 | cfctrl_cancel_req(cnfg->ctrl, adap_layer); | 212 | |
213 | /* Do RCU sync before initiating cleanup */ | ||
214 | synchronize_rcu(); | ||
238 | if (adap_layer->ctrlcmd != NULL) | 215 | if (adap_layer->ctrlcmd != NULL) |
239 | adap_layer->ctrlcmd(adap_layer, CAIF_CTRLCMD_DEINIT_RSP, 0); | 216 | adap_layer->ctrlcmd(adap_layer, CAIF_CTRLCMD_DEINIT_RSP, 0); |
240 | return ret; | 217 | return ret; |
241 | 218 | ||
242 | } | 219 | } |
243 | EXPORT_SYMBOL(cfcnfg_disconn_adapt_layer); | 220 | EXPORT_SYMBOL(caif_disconnect_client); |
244 | |||
245 | void cfcnfg_release_adap_layer(struct cflayer *adap_layer) | ||
246 | { | ||
247 | if (adap_layer->dn) | ||
248 | cfsrvl_put(adap_layer->dn); | ||
249 | } | ||
250 | EXPORT_SYMBOL(cfcnfg_release_adap_layer); | ||
251 | 221 | ||
252 | static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id) | 222 | static void cfcnfg_linkdestroy_rsp(struct cflayer *layer, u8 channel_id) |
253 | { | 223 | { |
254 | } | 224 | } |
255 | 225 | ||
256 | int protohead[CFCTRL_SRV_MASK] = { | 226 | static const int protohead[CFCTRL_SRV_MASK] = { |
257 | [CFCTRL_SRV_VEI] = 4, | 227 | [CFCTRL_SRV_VEI] = 4, |
258 | [CFCTRL_SRV_DATAGRAM] = 7, | 228 | [CFCTRL_SRV_DATAGRAM] = 7, |
259 | [CFCTRL_SRV_UTIL] = 4, | 229 | [CFCTRL_SRV_UTIL] = 4, |
@@ -261,49 +231,157 @@ int protohead[CFCTRL_SRV_MASK] = { | |||
261 | [CFCTRL_SRV_DBG] = 3, | 231 | [CFCTRL_SRV_DBG] = 3, |
262 | }; | 232 | }; |
263 | 233 | ||
264 | int cfcnfg_add_adaptation_layer(struct cfcnfg *cnfg, | 234 | |
265 | struct cfctrl_link_param *param, | 235 | static int caif_connect_req_to_link_param(struct cfcnfg *cnfg, |
266 | struct cflayer *adap_layer, | 236 | struct caif_connect_request *s, |
267 | int *ifindex, | 237 | struct cfctrl_link_param *l) |
238 | { | ||
239 | struct dev_info *dev_info; | ||
240 | enum cfcnfg_phy_preference pref; | ||
241 | int res; | ||
242 | |||
243 | memset(l, 0, sizeof(*l)); | ||
244 | /* In caif protocol low value is high priority */ | ||
245 | l->priority = CAIF_PRIO_MAX - s->priority + 1; | ||
246 | |||
247 | if (s->ifindex != 0) { | ||
248 | res = cfcnfg_get_id_from_ifi(cnfg, s->ifindex); | ||
249 | if (res < 0) | ||
250 | return res; | ||
251 | l->phyid = res; | ||
252 | } else { | ||
253 | switch (s->link_selector) { | ||
254 | case CAIF_LINK_HIGH_BANDW: | ||
255 | pref = CFPHYPREF_HIGH_BW; | ||
256 | break; | ||
257 | case CAIF_LINK_LOW_LATENCY: | ||
258 | pref = CFPHYPREF_LOW_LAT; | ||
259 | break; | ||
260 | default: | ||
261 | return -EINVAL; | ||
262 | } | ||
263 | dev_info = cfcnfg_get_phyid(cnfg, pref); | ||
264 | if (dev_info == NULL) | ||
265 | return -ENODEV; | ||
266 | l->phyid = dev_info->id; | ||
267 | } | ||
268 | switch (s->protocol) { | ||
269 | case CAIFPROTO_AT: | ||
270 | l->linktype = CFCTRL_SRV_VEI; | ||
271 | l->endpoint = (s->sockaddr.u.at.type >> 2) & 0x3; | ||
272 | l->chtype = s->sockaddr.u.at.type & 0x3; | ||
273 | break; | ||
274 | case CAIFPROTO_DATAGRAM: | ||
275 | l->linktype = CFCTRL_SRV_DATAGRAM; | ||
276 | l->chtype = 0x00; | ||
277 | l->u.datagram.connid = s->sockaddr.u.dgm.connection_id; | ||
278 | break; | ||
279 | case CAIFPROTO_DATAGRAM_LOOP: | ||
280 | l->linktype = CFCTRL_SRV_DATAGRAM; | ||
281 | l->chtype = 0x03; | ||
282 | l->endpoint = 0x00; | ||
283 | l->u.datagram.connid = s->sockaddr.u.dgm.connection_id; | ||
284 | break; | ||
285 | case CAIFPROTO_RFM: | ||
286 | l->linktype = CFCTRL_SRV_RFM; | ||
287 | l->u.datagram.connid = s->sockaddr.u.rfm.connection_id; | ||
288 | strncpy(l->u.rfm.volume, s->sockaddr.u.rfm.volume, | ||
289 | sizeof(l->u.rfm.volume)-1); | ||
290 | l->u.rfm.volume[sizeof(l->u.rfm.volume)-1] = 0; | ||
291 | break; | ||
292 | case CAIFPROTO_UTIL: | ||
293 | l->linktype = CFCTRL_SRV_UTIL; | ||
294 | l->endpoint = 0x00; | ||
295 | l->chtype = 0x00; | ||
296 | strncpy(l->u.utility.name, s->sockaddr.u.util.service, | ||
297 | sizeof(l->u.utility.name)-1); | ||
298 | l->u.utility.name[sizeof(l->u.utility.name)-1] = 0; | ||
299 | caif_assert(sizeof(l->u.utility.name) > 10); | ||
300 | l->u.utility.paramlen = s->param.size; | ||
301 | if (l->u.utility.paramlen > sizeof(l->u.utility.params)) | ||
302 | l->u.utility.paramlen = sizeof(l->u.utility.params); | ||
303 | |||
304 | memcpy(l->u.utility.params, s->param.data, | ||
305 | l->u.utility.paramlen); | ||
306 | |||
307 | break; | ||
308 | case CAIFPROTO_DEBUG: | ||
309 | l->linktype = CFCTRL_SRV_DBG; | ||
310 | l->endpoint = s->sockaddr.u.dbg.service; | ||
311 | l->chtype = s->sockaddr.u.dbg.type; | ||
312 | break; | ||
313 | default: | ||
314 | return -EINVAL; | ||
315 | } | ||
316 | return 0; | ||
317 | } | ||
318 | |||
319 | int caif_connect_client(struct net *net, struct caif_connect_request *conn_req, | ||
320 | struct cflayer *adap_layer, int *ifindex, | ||
268 | int *proto_head, | 321 | int *proto_head, |
269 | int *proto_tail) | 322 | int *proto_tail) |
270 | { | 323 | { |
271 | struct cflayer *frml; | 324 | struct cflayer *frml; |
325 | struct cfcnfg_phyinfo *phy; | ||
326 | int err; | ||
327 | struct cfctrl_link_param param; | ||
328 | struct cfcnfg *cfg = get_cfcnfg(net); | ||
329 | caif_assert(cfg != NULL); | ||
330 | |||
331 | rcu_read_lock(); | ||
332 | err = caif_connect_req_to_link_param(cfg, conn_req, ¶m); | ||
333 | if (err) | ||
334 | goto unlock; | ||
335 | |||
336 | phy = cfcnfg_get_phyinfo_rcu(cfg, param.phyid); | ||
337 | if (!phy) { | ||
338 | err = -ENODEV; | ||
339 | goto unlock; | ||
340 | } | ||
341 | err = -EINVAL; | ||
342 | |||
272 | if (adap_layer == NULL) { | 343 | if (adap_layer == NULL) { |
273 | pr_err("adap_layer is zero\n"); | 344 | pr_err("adap_layer is zero\n"); |
274 | return -EINVAL; | 345 | goto unlock; |
275 | } | 346 | } |
276 | if (adap_layer->receive == NULL) { | 347 | if (adap_layer->receive == NULL) { |
277 | pr_err("adap_layer->receive is NULL\n"); | 348 | pr_err("adap_layer->receive is NULL\n"); |
278 | return -EINVAL; | 349 | goto unlock; |
279 | } | 350 | } |
280 | if (adap_layer->ctrlcmd == NULL) { | 351 | if (adap_layer->ctrlcmd == NULL) { |
281 | pr_err("adap_layer->ctrlcmd == NULL\n"); | 352 | pr_err("adap_layer->ctrlcmd == NULL\n"); |
282 | return -EINVAL; | 353 | goto unlock; |
283 | } | 354 | } |
284 | frml = cnfg->phy_layers[param->phyid].frm_layer; | 355 | |
356 | err = -ENODEV; | ||
357 | frml = phy->frm_layer; | ||
285 | if (frml == NULL) { | 358 | if (frml == NULL) { |
286 | pr_err("Specified PHY type does not exist!\n"); | 359 | pr_err("Specified PHY type does not exist!\n"); |
287 | return -ENODEV; | 360 | goto unlock; |
288 | } | 361 | } |
289 | caif_assert(param->phyid == cnfg->phy_layers[param->phyid].id); | 362 | caif_assert(param.phyid == phy->id); |
290 | caif_assert(cnfg->phy_layers[param->phyid].frm_layer->id == | 363 | caif_assert(phy->frm_layer->id == |
291 | param->phyid); | 364 | param.phyid); |
292 | caif_assert(cnfg->phy_layers[param->phyid].phy_layer->id == | 365 | caif_assert(phy->phy_layer->id == |
293 | param->phyid); | 366 | param.phyid); |
294 | 367 | ||
295 | *ifindex = cnfg->phy_layers[param->phyid].ifindex; | 368 | *ifindex = phy->ifindex; |
369 | *proto_tail = 2; | ||
296 | *proto_head = | 370 | *proto_head = |
297 | protohead[param->linktype]+ | ||
298 | (cnfg->phy_layers[param->phyid].use_stx ? 1 : 0); | ||
299 | 371 | ||
300 | *proto_tail = 2; | 372 | protohead[param.linktype] + (phy->use_stx ? 1 : 0); |
373 | |||
374 | rcu_read_unlock(); | ||
301 | 375 | ||
302 | /* FIXME: ENUMERATE INITIALLY WHEN ACTIVATING PHYSICAL INTERFACE */ | 376 | /* FIXME: ENUMERATE INITIALLY WHEN ACTIVATING PHYSICAL INTERFACE */ |
303 | cfctrl_enum_req(cnfg->ctrl, param->phyid); | 377 | cfctrl_enum_req(cfg->ctrl, param.phyid); |
304 | return cfctrl_linkup_request(cnfg->ctrl, param, adap_layer); | 378 | return cfctrl_linkup_request(cfg->ctrl, ¶m, adap_layer); |
379 | |||
380 | unlock: | ||
381 | rcu_read_unlock(); | ||
382 | return err; | ||
305 | } | 383 | } |
306 | EXPORT_SYMBOL(cfcnfg_add_adaptation_layer); | 384 | EXPORT_SYMBOL(caif_connect_client); |
307 | 385 | ||
308 | static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id, | 386 | static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id, |
309 | struct cflayer *adapt_layer) | 387 | struct cflayer *adapt_layer) |
@@ -315,32 +393,37 @@ static void cfcnfg_reject_rsp(struct cflayer *layer, u8 channel_id, | |||
315 | 393 | ||
316 | static void | 394 | static void |
317 | cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv, | 395 | cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv, |
318 | u8 phyid, struct cflayer *adapt_layer) | 396 | u8 phyid, struct cflayer *adapt_layer) |
319 | { | 397 | { |
320 | struct cfcnfg *cnfg = container_obj(layer); | 398 | struct cfcnfg *cnfg = container_obj(layer); |
321 | struct cflayer *servicel = NULL; | 399 | struct cflayer *servicel = NULL; |
322 | struct cfcnfg_phyinfo *phyinfo; | 400 | struct cfcnfg_phyinfo *phyinfo; |
323 | struct net_device *netdev; | 401 | struct net_device *netdev; |
324 | 402 | ||
403 | rcu_read_lock(); | ||
404 | |||
325 | if (adapt_layer == NULL) { | 405 | if (adapt_layer == NULL) { |
326 | pr_debug("link setup response but no client exist, send linkdown back\n"); | 406 | pr_debug("link setup response but no client exist," |
407 | "send linkdown back\n"); | ||
327 | cfctrl_linkdown_req(cnfg->ctrl, channel_id, NULL); | 408 | cfctrl_linkdown_req(cnfg->ctrl, channel_id, NULL); |
328 | return; | 409 | goto unlock; |
329 | } | 410 | } |
330 | 411 | ||
331 | caif_assert(cnfg != NULL); | 412 | caif_assert(cnfg != NULL); |
332 | caif_assert(phyid != 0); | 413 | caif_assert(phyid != 0); |
333 | phyinfo = &cnfg->phy_layers[phyid]; | 414 | |
415 | phyinfo = cfcnfg_get_phyinfo_rcu(cnfg, phyid); | ||
416 | if (phyinfo == NULL) { | ||
417 | pr_err("ERROR: Link Layer Device dissapeared" | ||
418 | "while connecting\n"); | ||
419 | goto unlock; | ||
420 | } | ||
421 | |||
422 | caif_assert(phyinfo != NULL); | ||
334 | caif_assert(phyinfo->id == phyid); | 423 | caif_assert(phyinfo->id == phyid); |
335 | caif_assert(phyinfo->phy_layer != NULL); | 424 | caif_assert(phyinfo->phy_layer != NULL); |
336 | caif_assert(phyinfo->phy_layer->id == phyid); | 425 | caif_assert(phyinfo->phy_layer->id == phyid); |
337 | 426 | ||
338 | phyinfo->phy_ref_count++; | ||
339 | if (phyinfo->phy_ref_count == 1 && | ||
340 | phyinfo->phy_layer->modemcmd != NULL) { | ||
341 | phyinfo->phy_layer->modemcmd(phyinfo->phy_layer, | ||
342 | _CAIF_MODEMCMD_PHYIF_USEFULL); | ||
343 | } | ||
344 | adapt_layer->id = channel_id; | 427 | adapt_layer->id = channel_id; |
345 | 428 | ||
346 | switch (serv) { | 429 | switch (serv) { |
@@ -348,7 +431,8 @@ cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv, | |||
348 | servicel = cfvei_create(channel_id, &phyinfo->dev_info); | 431 | servicel = cfvei_create(channel_id, &phyinfo->dev_info); |
349 | break; | 432 | break; |
350 | case CFCTRL_SRV_DATAGRAM: | 433 | case CFCTRL_SRV_DATAGRAM: |
351 | servicel = cfdgml_create(channel_id, &phyinfo->dev_info); | 434 | servicel = cfdgml_create(channel_id, |
435 | &phyinfo->dev_info); | ||
352 | break; | 436 | break; |
353 | case CFCTRL_SRV_RFM: | 437 | case CFCTRL_SRV_RFM: |
354 | netdev = phyinfo->dev_info.dev; | 438 | netdev = phyinfo->dev_info.dev; |
@@ -365,94 +449,93 @@ cfcnfg_linkup_rsp(struct cflayer *layer, u8 channel_id, enum cfctrl_srv serv, | |||
365 | servicel = cfdbgl_create(channel_id, &phyinfo->dev_info); | 449 | servicel = cfdbgl_create(channel_id, &phyinfo->dev_info); |
366 | break; | 450 | break; |
367 | default: | 451 | default: |
368 | pr_err("Protocol error. Link setup response - unknown channel type\n"); | 452 | pr_err("Protocol error. Link setup response " |
369 | return; | 453 | "- unknown channel type\n"); |
454 | goto unlock; | ||
370 | } | 455 | } |
371 | if (!servicel) { | 456 | if (!servicel) { |
372 | pr_warn("Out of memory\n"); | 457 | pr_warn("Out of memory\n"); |
373 | return; | 458 | goto unlock; |
374 | } | 459 | } |
375 | layer_set_dn(servicel, cnfg->mux); | 460 | layer_set_dn(servicel, cnfg->mux); |
376 | cfmuxl_set_uplayer(cnfg->mux, servicel, channel_id); | 461 | cfmuxl_set_uplayer(cnfg->mux, servicel, channel_id); |
377 | layer_set_up(servicel, adapt_layer); | 462 | layer_set_up(servicel, adapt_layer); |
378 | layer_set_dn(adapt_layer, servicel); | 463 | layer_set_dn(adapt_layer, servicel); |
379 | cfsrvl_get(servicel); | 464 | |
465 | rcu_read_unlock(); | ||
466 | |||
380 | servicel->ctrlcmd(servicel, CAIF_CTRLCMD_INIT_RSP, 0); | 467 | servicel->ctrlcmd(servicel, CAIF_CTRLCMD_INIT_RSP, 0); |
468 | return; | ||
469 | unlock: | ||
470 | rcu_read_unlock(); | ||
381 | } | 471 | } |
382 | 472 | ||
383 | void | 473 | void |
384 | cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type, | 474 | cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type, |
385 | struct net_device *dev, struct cflayer *phy_layer, | 475 | struct net_device *dev, struct cflayer *phy_layer, |
386 | u16 *phyid, enum cfcnfg_phy_preference pref, | 476 | enum cfcnfg_phy_preference pref, |
387 | bool fcs, bool stx) | 477 | bool fcs, bool stx) |
388 | { | 478 | { |
389 | struct cflayer *frml; | 479 | struct cflayer *frml; |
390 | struct cflayer *phy_driver = NULL; | 480 | struct cflayer *phy_driver = NULL; |
481 | struct cfcnfg_phyinfo *phyinfo; | ||
391 | int i; | 482 | int i; |
483 | u8 phyid; | ||
392 | 484 | ||
485 | mutex_lock(&cnfg->lock); | ||
393 | 486 | ||
394 | if (cnfg->phy_layers[cnfg->last_phyid].frm_layer == NULL) { | 487 | /* CAIF protocol allow maximum 6 link-layers */ |
395 | *phyid = cnfg->last_phyid; | 488 | for (i = 0; i < 7; i++) { |
396 | 489 | phyid = (dev->ifindex + i) & 0x7; | |
397 | /* range: * 1..(MAX_PHY_LAYERS-1) */ | 490 | if (phyid == 0) |
398 | cnfg->last_phyid = | 491 | continue; |
399 | (cnfg->last_phyid % (MAX_PHY_LAYERS - 1)) + 1; | 492 | if (cfcnfg_get_phyinfo_rcu(cnfg, phyid) == NULL) |
400 | } else { | 493 | goto got_phyid; |
401 | *phyid = 0; | ||
402 | for (i = 1; i < MAX_PHY_LAYERS; i++) { | ||
403 | if (cnfg->phy_layers[i].frm_layer == NULL) { | ||
404 | *phyid = i; | ||
405 | break; | ||
406 | } | ||
407 | } | ||
408 | } | ||
409 | if (*phyid == 0) { | ||
410 | pr_err("No Available PHY ID\n"); | ||
411 | return; | ||
412 | } | 494 | } |
495 | pr_warn("Too many CAIF Link Layers (max 6)\n"); | ||
496 | goto out; | ||
497 | |||
498 | got_phyid: | ||
499 | phyinfo = kzalloc(sizeof(struct cfcnfg_phyinfo), GFP_ATOMIC); | ||
413 | 500 | ||
414 | switch (phy_type) { | 501 | switch (phy_type) { |
415 | case CFPHYTYPE_FRAG: | 502 | case CFPHYTYPE_FRAG: |
416 | phy_driver = | 503 | phy_driver = |
417 | cfserl_create(CFPHYTYPE_FRAG, *phyid, stx); | 504 | cfserl_create(CFPHYTYPE_FRAG, phyid, stx); |
418 | if (!phy_driver) { | 505 | if (!phy_driver) { |
419 | pr_warn("Out of memory\n"); | 506 | pr_warn("Out of memory\n"); |
420 | return; | 507 | goto out; |
421 | } | 508 | } |
422 | |||
423 | break; | 509 | break; |
424 | case CFPHYTYPE_CAIF: | 510 | case CFPHYTYPE_CAIF: |
425 | phy_driver = NULL; | 511 | phy_driver = NULL; |
426 | break; | 512 | break; |
427 | default: | 513 | default: |
428 | pr_err("%d\n", phy_type); | 514 | goto out; |
429 | return; | ||
430 | break; | ||
431 | } | 515 | } |
432 | 516 | phy_layer->id = phyid; | |
433 | phy_layer->id = *phyid; | 517 | phyinfo->pref = pref; |
434 | cnfg->phy_layers[*phyid].pref = pref; | 518 | phyinfo->id = phyid; |
435 | cnfg->phy_layers[*phyid].id = *phyid; | 519 | phyinfo->dev_info.id = phyid; |
436 | cnfg->phy_layers[*phyid].dev_info.id = *phyid; | 520 | phyinfo->dev_info.dev = dev; |
437 | cnfg->phy_layers[*phyid].dev_info.dev = dev; | 521 | phyinfo->phy_layer = phy_layer; |
438 | cnfg->phy_layers[*phyid].phy_layer = phy_layer; | 522 | phyinfo->ifindex = dev->ifindex; |
439 | cnfg->phy_layers[*phyid].phy_ref_count = 0; | 523 | phyinfo->use_stx = stx; |
440 | cnfg->phy_layers[*phyid].ifindex = dev->ifindex; | 524 | phyinfo->use_fcs = fcs; |
441 | cnfg->phy_layers[*phyid].use_stx = stx; | ||
442 | cnfg->phy_layers[*phyid].use_fcs = fcs; | ||
443 | 525 | ||
444 | phy_layer->type = phy_type; | 526 | phy_layer->type = phy_type; |
445 | frml = cffrml_create(*phyid, fcs); | 527 | frml = cffrml_create(phyid, fcs); |
528 | |||
446 | if (!frml) { | 529 | if (!frml) { |
447 | pr_warn("Out of memory\n"); | 530 | pr_warn("Out of memory\n"); |
448 | return; | 531 | kfree(phyinfo); |
532 | goto out; | ||
449 | } | 533 | } |
450 | cnfg->phy_layers[*phyid].frm_layer = frml; | 534 | phyinfo->frm_layer = frml; |
451 | cfmuxl_set_dnlayer(cnfg->mux, frml, *phyid); | ||
452 | layer_set_up(frml, cnfg->mux); | 535 | layer_set_up(frml, cnfg->mux); |
453 | 536 | ||
454 | if (phy_driver != NULL) { | 537 | if (phy_driver != NULL) { |
455 | phy_driver->id = *phyid; | 538 | phy_driver->id = phyid; |
456 | layer_set_dn(frml, phy_driver); | 539 | layer_set_dn(frml, phy_driver); |
457 | layer_set_up(phy_driver, frml); | 540 | layer_set_up(phy_driver, frml); |
458 | layer_set_dn(phy_driver, phy_layer); | 541 | layer_set_dn(phy_driver, phy_layer); |
@@ -461,33 +544,95 @@ cfcnfg_add_phy_layer(struct cfcnfg *cnfg, enum cfcnfg_phy_type phy_type, | |||
461 | layer_set_dn(frml, phy_layer); | 544 | layer_set_dn(frml, phy_layer); |
462 | layer_set_up(phy_layer, frml); | 545 | layer_set_up(phy_layer, frml); |
463 | } | 546 | } |
547 | |||
548 | list_add_rcu(&phyinfo->node, &cnfg->phys); | ||
549 | out: | ||
550 | mutex_unlock(&cnfg->lock); | ||
464 | } | 551 | } |
465 | EXPORT_SYMBOL(cfcnfg_add_phy_layer); | 552 | EXPORT_SYMBOL(cfcnfg_add_phy_layer); |
466 | 553 | ||
554 | int cfcnfg_set_phy_state(struct cfcnfg *cnfg, struct cflayer *phy_layer, | ||
555 | bool up) | ||
556 | { | ||
557 | struct cfcnfg_phyinfo *phyinfo; | ||
558 | |||
559 | rcu_read_lock(); | ||
560 | phyinfo = cfcnfg_get_phyinfo_rcu(cnfg, phy_layer->id); | ||
561 | if (phyinfo == NULL) { | ||
562 | rcu_read_unlock(); | ||
563 | return -ENODEV; | ||
564 | } | ||
565 | |||
566 | if (phyinfo->up == up) { | ||
567 | rcu_read_unlock(); | ||
568 | return 0; | ||
569 | } | ||
570 | phyinfo->up = up; | ||
571 | |||
572 | if (up) { | ||
573 | cffrml_hold(phyinfo->frm_layer); | ||
574 | cfmuxl_set_dnlayer(cnfg->mux, phyinfo->frm_layer, | ||
575 | phy_layer->id); | ||
576 | } else { | ||
577 | cfmuxl_remove_dnlayer(cnfg->mux, phy_layer->id); | ||
578 | cffrml_put(phyinfo->frm_layer); | ||
579 | } | ||
580 | |||
581 | rcu_read_unlock(); | ||
582 | return 0; | ||
583 | } | ||
584 | EXPORT_SYMBOL(cfcnfg_set_phy_state); | ||
585 | |||
467 | int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer) | 586 | int cfcnfg_del_phy_layer(struct cfcnfg *cnfg, struct cflayer *phy_layer) |
468 | { | 587 | { |
469 | struct cflayer *frml, *frml_dn; | 588 | struct cflayer *frml, *frml_dn; |
470 | u16 phyid; | 589 | u16 phyid; |
590 | struct cfcnfg_phyinfo *phyinfo; | ||
591 | |||
592 | might_sleep(); | ||
593 | |||
594 | mutex_lock(&cnfg->lock); | ||
595 | |||
471 | phyid = phy_layer->id; | 596 | phyid = phy_layer->id; |
472 | caif_assert(phyid == cnfg->phy_layers[phyid].id); | 597 | phyinfo = cfcnfg_get_phyinfo_rcu(cnfg, phyid); |
473 | caif_assert(phy_layer == cnfg->phy_layers[phyid].phy_layer); | 598 | |
599 | if (phyinfo == NULL) { | ||
600 | mutex_unlock(&cnfg->lock); | ||
601 | return 0; | ||
602 | } | ||
603 | caif_assert(phyid == phyinfo->id); | ||
604 | caif_assert(phy_layer == phyinfo->phy_layer); | ||
474 | caif_assert(phy_layer->id == phyid); | 605 | caif_assert(phy_layer->id == phyid); |
475 | caif_assert(cnfg->phy_layers[phyid].frm_layer->id == phyid); | 606 | caif_assert(phyinfo->frm_layer->id == phyid); |
476 | 607 | ||
477 | memset(&cnfg->phy_layers[phy_layer->id], 0, | 608 | list_del_rcu(&phyinfo->node); |
478 | sizeof(struct cfcnfg_phyinfo)); | 609 | synchronize_rcu(); |
479 | frml = cfmuxl_remove_dnlayer(cnfg->mux, phy_layer->id); | 610 | |
611 | /* Fail if reference count is not zero */ | ||
612 | if (cffrml_refcnt_read(phyinfo->frm_layer) != 0) { | ||
613 | pr_info("Wait for device inuse\n"); | ||
614 | list_add_rcu(&phyinfo->node, &cnfg->phys); | ||
615 | mutex_unlock(&cnfg->lock); | ||
616 | return -EAGAIN; | ||
617 | } | ||
618 | |||
619 | frml = phyinfo->frm_layer; | ||
480 | frml_dn = frml->dn; | 620 | frml_dn = frml->dn; |
481 | cffrml_set_uplayer(frml, NULL); | 621 | cffrml_set_uplayer(frml, NULL); |
482 | cffrml_set_dnlayer(frml, NULL); | 622 | cffrml_set_dnlayer(frml, NULL); |
483 | kfree(frml); | ||
484 | |||
485 | if (phy_layer != frml_dn) { | 623 | if (phy_layer != frml_dn) { |
486 | layer_set_up(frml_dn, NULL); | 624 | layer_set_up(frml_dn, NULL); |
487 | layer_set_dn(frml_dn, NULL); | 625 | layer_set_dn(frml_dn, NULL); |
488 | kfree(frml_dn); | ||
489 | } | 626 | } |
490 | layer_set_up(phy_layer, NULL); | 627 | layer_set_up(phy_layer, NULL); |
628 | |||
629 | if (phyinfo->phy_layer != frml_dn) | ||
630 | kfree(frml_dn); | ||
631 | |||
632 | cffrml_free(frml); | ||
633 | kfree(phyinfo); | ||
634 | mutex_unlock(&cnfg->lock); | ||
635 | |||
491 | return 0; | 636 | return 0; |
492 | } | 637 | } |
493 | EXPORT_SYMBOL(cfcnfg_del_phy_layer); | 638 | EXPORT_SYMBOL(cfcnfg_del_phy_layer); |
diff --git a/net/caif/cfctrl.c b/net/caif/cfctrl.c index 3cd8f978e309..0c00a6015dda 100644 --- a/net/caif/cfctrl.c +++ b/net/caif/cfctrl.c | |||
@@ -17,7 +17,6 @@ | |||
17 | #define UTILITY_NAME_LENGTH 16 | 17 | #define UTILITY_NAME_LENGTH 16 |
18 | #define CFPKT_CTRL_PKT_LEN 20 | 18 | #define CFPKT_CTRL_PKT_LEN 20 |
19 | 19 | ||
20 | |||
21 | #ifdef CAIF_NO_LOOP | 20 | #ifdef CAIF_NO_LOOP |
22 | static int handle_loop(struct cfctrl *ctrl, | 21 | static int handle_loop(struct cfctrl *ctrl, |
23 | int cmd, struct cfpkt *pkt){ | 22 | int cmd, struct cfpkt *pkt){ |
@@ -51,14 +50,31 @@ struct cflayer *cfctrl_create(void) | |||
51 | this->serv.layer.receive = cfctrl_recv; | 50 | this->serv.layer.receive = cfctrl_recv; |
52 | sprintf(this->serv.layer.name, "ctrl"); | 51 | sprintf(this->serv.layer.name, "ctrl"); |
53 | this->serv.layer.ctrlcmd = cfctrl_ctrlcmd; | 52 | this->serv.layer.ctrlcmd = cfctrl_ctrlcmd; |
53 | #ifndef CAIF_NO_LOOP | ||
54 | spin_lock_init(&this->loop_linkid_lock); | 54 | spin_lock_init(&this->loop_linkid_lock); |
55 | this->loop_linkid = 1; | ||
56 | #endif | ||
55 | spin_lock_init(&this->info_list_lock); | 57 | spin_lock_init(&this->info_list_lock); |
56 | INIT_LIST_HEAD(&this->list); | 58 | INIT_LIST_HEAD(&this->list); |
57 | this->loop_linkid = 1; | ||
58 | return &this->serv.layer; | 59 | return &this->serv.layer; |
59 | } | 60 | } |
60 | 61 | ||
61 | static bool param_eq(struct cfctrl_link_param *p1, struct cfctrl_link_param *p2) | 62 | void cfctrl_remove(struct cflayer *layer) |
63 | { | ||
64 | struct cfctrl_request_info *p, *tmp; | ||
65 | struct cfctrl *ctrl = container_obj(layer); | ||
66 | |||
67 | spin_lock_bh(&ctrl->info_list_lock); | ||
68 | list_for_each_entry_safe(p, tmp, &ctrl->list, list) { | ||
69 | list_del(&p->list); | ||
70 | kfree(p); | ||
71 | } | ||
72 | spin_unlock_bh(&ctrl->info_list_lock); | ||
73 | kfree(layer); | ||
74 | } | ||
75 | |||
76 | static bool param_eq(const struct cfctrl_link_param *p1, | ||
77 | const struct cfctrl_link_param *p2) | ||
62 | { | 78 | { |
63 | bool eq = | 79 | bool eq = |
64 | p1->linktype == p2->linktype && | 80 | p1->linktype == p2->linktype && |
@@ -100,8 +116,8 @@ static bool param_eq(struct cfctrl_link_param *p1, struct cfctrl_link_param *p2) | |||
100 | return false; | 116 | return false; |
101 | } | 117 | } |
102 | 118 | ||
103 | bool cfctrl_req_eq(struct cfctrl_request_info *r1, | 119 | static bool cfctrl_req_eq(const struct cfctrl_request_info *r1, |
104 | struct cfctrl_request_info *r2) | 120 | const struct cfctrl_request_info *r2) |
105 | { | 121 | { |
106 | if (r1->cmd != r2->cmd) | 122 | if (r1->cmd != r2->cmd) |
107 | return false; | 123 | return false; |
@@ -112,23 +128,22 @@ bool cfctrl_req_eq(struct cfctrl_request_info *r1, | |||
112 | } | 128 | } |
113 | 129 | ||
114 | /* Insert request at the end */ | 130 | /* Insert request at the end */ |
115 | void cfctrl_insert_req(struct cfctrl *ctrl, | 131 | static void cfctrl_insert_req(struct cfctrl *ctrl, |
116 | struct cfctrl_request_info *req) | 132 | struct cfctrl_request_info *req) |
117 | { | 133 | { |
118 | spin_lock(&ctrl->info_list_lock); | 134 | spin_lock_bh(&ctrl->info_list_lock); |
119 | atomic_inc(&ctrl->req_seq_no); | 135 | atomic_inc(&ctrl->req_seq_no); |
120 | req->sequence_no = atomic_read(&ctrl->req_seq_no); | 136 | req->sequence_no = atomic_read(&ctrl->req_seq_no); |
121 | list_add_tail(&req->list, &ctrl->list); | 137 | list_add_tail(&req->list, &ctrl->list); |
122 | spin_unlock(&ctrl->info_list_lock); | 138 | spin_unlock_bh(&ctrl->info_list_lock); |
123 | } | 139 | } |
124 | 140 | ||
125 | /* Compare and remove request */ | 141 | /* Compare and remove request */ |
126 | struct cfctrl_request_info *cfctrl_remove_req(struct cfctrl *ctrl, | 142 | static struct cfctrl_request_info *cfctrl_remove_req(struct cfctrl *ctrl, |
127 | struct cfctrl_request_info *req) | 143 | struct cfctrl_request_info *req) |
128 | { | 144 | { |
129 | struct cfctrl_request_info *p, *tmp, *first; | 145 | struct cfctrl_request_info *p, *tmp, *first; |
130 | 146 | ||
131 | spin_lock(&ctrl->info_list_lock); | ||
132 | first = list_first_entry(&ctrl->list, struct cfctrl_request_info, list); | 147 | first = list_first_entry(&ctrl->list, struct cfctrl_request_info, list); |
133 | 148 | ||
134 | list_for_each_entry_safe(p, tmp, &ctrl->list, list) { | 149 | list_for_each_entry_safe(p, tmp, &ctrl->list, list) { |
@@ -144,7 +159,6 @@ struct cfctrl_request_info *cfctrl_remove_req(struct cfctrl *ctrl, | |||
144 | } | 159 | } |
145 | p = NULL; | 160 | p = NULL; |
146 | out: | 161 | out: |
147 | spin_unlock(&ctrl->info_list_lock); | ||
148 | return p; | 162 | return p; |
149 | } | 163 | } |
150 | 164 | ||
@@ -154,16 +168,6 @@ struct cfctrl_rsp *cfctrl_get_respfuncs(struct cflayer *layer) | |||
154 | return &this->res; | 168 | return &this->res; |
155 | } | 169 | } |
156 | 170 | ||
157 | void cfctrl_set_dnlayer(struct cflayer *this, struct cflayer *dn) | ||
158 | { | ||
159 | this->dn = dn; | ||
160 | } | ||
161 | |||
162 | void cfctrl_set_uplayer(struct cflayer *this, struct cflayer *up) | ||
163 | { | ||
164 | this->up = up; | ||
165 | } | ||
166 | |||
167 | static void init_info(struct caif_payload_info *info, struct cfctrl *cfctrl) | 171 | static void init_info(struct caif_payload_info *info, struct cfctrl *cfctrl) |
168 | { | 172 | { |
169 | info->hdr_len = 0; | 173 | info->hdr_len = 0; |
@@ -188,10 +192,6 @@ void cfctrl_enum_req(struct cflayer *layer, u8 physlinkid) | |||
188 | cfpkt_addbdy(pkt, physlinkid); | 192 | cfpkt_addbdy(pkt, physlinkid); |
189 | ret = | 193 | ret = |
190 | cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); | 194 | cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); |
191 | if (ret < 0) { | ||
192 | pr_err("Could not transmit enum message\n"); | ||
193 | cfpkt_destroy(pkt); | ||
194 | } | ||
195 | } | 195 | } |
196 | 196 | ||
197 | int cfctrl_linkup_request(struct cflayer *layer, | 197 | int cfctrl_linkup_request(struct cflayer *layer, |
@@ -205,14 +205,23 @@ int cfctrl_linkup_request(struct cflayer *layer, | |||
205 | struct cfctrl_request_info *req; | 205 | struct cfctrl_request_info *req; |
206 | int ret; | 206 | int ret; |
207 | char utility_name[16]; | 207 | char utility_name[16]; |
208 | struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN); | 208 | struct cfpkt *pkt; |
209 | |||
210 | if (cfctrl_cancel_req(layer, user_layer) > 0) { | ||
211 | /* Slight Paranoia, check if already connecting */ | ||
212 | pr_err("Duplicate connect request for same client\n"); | ||
213 | WARN_ON(1); | ||
214 | return -EALREADY; | ||
215 | } | ||
216 | |||
217 | pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN); | ||
209 | if (!pkt) { | 218 | if (!pkt) { |
210 | pr_warn("Out of memory\n"); | 219 | pr_warn("Out of memory\n"); |
211 | return -ENOMEM; | 220 | return -ENOMEM; |
212 | } | 221 | } |
213 | cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_SETUP); | 222 | cfpkt_addbdy(pkt, CFCTRL_CMD_LINK_SETUP); |
214 | cfpkt_addbdy(pkt, (param->chtype << 4) + param->linktype); | 223 | cfpkt_addbdy(pkt, (param->chtype << 4) | param->linktype); |
215 | cfpkt_addbdy(pkt, (param->priority << 3) + param->phyid); | 224 | cfpkt_addbdy(pkt, (param->priority << 3) | param->phyid); |
216 | cfpkt_addbdy(pkt, param->endpoint & 0x03); | 225 | cfpkt_addbdy(pkt, param->endpoint & 0x03); |
217 | 226 | ||
218 | switch (param->linktype) { | 227 | switch (param->linktype) { |
@@ -275,9 +284,13 @@ int cfctrl_linkup_request(struct cflayer *layer, | |||
275 | ret = | 284 | ret = |
276 | cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); | 285 | cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); |
277 | if (ret < 0) { | 286 | if (ret < 0) { |
278 | pr_err("Could not transmit linksetup request\n"); | 287 | int count; |
279 | cfpkt_destroy(pkt); | 288 | |
280 | return -ENODEV; | 289 | count = cfctrl_cancel_req(&cfctrl->serv.layer, |
290 | user_layer); | ||
291 | if (count != 1) | ||
292 | pr_err("Could not remove request (%d)", count); | ||
293 | return -ENODEV; | ||
281 | } | 294 | } |
282 | return 0; | 295 | return 0; |
283 | } | 296 | } |
@@ -297,80 +310,29 @@ int cfctrl_linkdown_req(struct cflayer *layer, u8 channelid, | |||
297 | init_info(cfpkt_info(pkt), cfctrl); | 310 | init_info(cfpkt_info(pkt), cfctrl); |
298 | ret = | 311 | ret = |
299 | cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); | 312 | cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); |
300 | if (ret < 0) { | 313 | #ifndef CAIF_NO_LOOP |
301 | pr_err("Could not transmit link-down request\n"); | 314 | cfctrl->loop_linkused[channelid] = 0; |
302 | cfpkt_destroy(pkt); | 315 | #endif |
303 | } | ||
304 | return ret; | 316 | return ret; |
305 | } | 317 | } |
306 | 318 | ||
307 | void cfctrl_sleep_req(struct cflayer *layer) | 319 | int cfctrl_cancel_req(struct cflayer *layr, struct cflayer *adap_layer) |
308 | { | ||
309 | int ret; | ||
310 | struct cfctrl *cfctrl = container_obj(layer); | ||
311 | struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN); | ||
312 | if (!pkt) { | ||
313 | pr_warn("Out of memory\n"); | ||
314 | return; | ||
315 | } | ||
316 | cfpkt_addbdy(pkt, CFCTRL_CMD_SLEEP); | ||
317 | init_info(cfpkt_info(pkt), cfctrl); | ||
318 | ret = | ||
319 | cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); | ||
320 | if (ret < 0) | ||
321 | cfpkt_destroy(pkt); | ||
322 | } | ||
323 | |||
324 | void cfctrl_wake_req(struct cflayer *layer) | ||
325 | { | ||
326 | int ret; | ||
327 | struct cfctrl *cfctrl = container_obj(layer); | ||
328 | struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN); | ||
329 | if (!pkt) { | ||
330 | pr_warn("Out of memory\n"); | ||
331 | return; | ||
332 | } | ||
333 | cfpkt_addbdy(pkt, CFCTRL_CMD_WAKE); | ||
334 | init_info(cfpkt_info(pkt), cfctrl); | ||
335 | ret = | ||
336 | cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); | ||
337 | if (ret < 0) | ||
338 | cfpkt_destroy(pkt); | ||
339 | } | ||
340 | |||
341 | void cfctrl_getstartreason_req(struct cflayer *layer) | ||
342 | { | ||
343 | int ret; | ||
344 | struct cfctrl *cfctrl = container_obj(layer); | ||
345 | struct cfpkt *pkt = cfpkt_create(CFPKT_CTRL_PKT_LEN); | ||
346 | if (!pkt) { | ||
347 | pr_warn("Out of memory\n"); | ||
348 | return; | ||
349 | } | ||
350 | cfpkt_addbdy(pkt, CFCTRL_CMD_START_REASON); | ||
351 | init_info(cfpkt_info(pkt), cfctrl); | ||
352 | ret = | ||
353 | cfctrl->serv.layer.dn->transmit(cfctrl->serv.layer.dn, pkt); | ||
354 | if (ret < 0) | ||
355 | cfpkt_destroy(pkt); | ||
356 | } | ||
357 | |||
358 | |||
359 | void cfctrl_cancel_req(struct cflayer *layr, struct cflayer *adap_layer) | ||
360 | { | 320 | { |
361 | struct cfctrl_request_info *p, *tmp; | 321 | struct cfctrl_request_info *p, *tmp; |
362 | struct cfctrl *ctrl = container_obj(layr); | 322 | struct cfctrl *ctrl = container_obj(layr); |
363 | spin_lock(&ctrl->info_list_lock); | 323 | int found = 0; |
324 | spin_lock_bh(&ctrl->info_list_lock); | ||
364 | 325 | ||
365 | list_for_each_entry_safe(p, tmp, &ctrl->list, list) { | 326 | list_for_each_entry_safe(p, tmp, &ctrl->list, list) { |
366 | if (p->client_layer == adap_layer) { | 327 | if (p->client_layer == adap_layer) { |
367 | pr_debug("cancel req :%d\n", p->sequence_no); | ||
368 | list_del(&p->list); | 328 | list_del(&p->list); |
369 | kfree(p); | 329 | kfree(p); |
330 | found++; | ||
370 | } | 331 | } |
371 | } | 332 | } |
372 | 333 | ||
373 | spin_unlock(&ctrl->info_list_lock); | 334 | spin_unlock_bh(&ctrl->info_list_lock); |
335 | return found; | ||
374 | } | 336 | } |
375 | 337 | ||
376 | static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) | 338 | static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) |
@@ -522,6 +484,7 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) | |||
522 | 484 | ||
523 | rsp.cmd = cmd; | 485 | rsp.cmd = cmd; |
524 | rsp.param = linkparam; | 486 | rsp.param = linkparam; |
487 | spin_lock_bh(&cfctrl->info_list_lock); | ||
525 | req = cfctrl_remove_req(cfctrl, &rsp); | 488 | req = cfctrl_remove_req(cfctrl, &rsp); |
526 | 489 | ||
527 | if (CFCTRL_ERR_BIT == (CFCTRL_ERR_BIT & cmdrsp) || | 490 | if (CFCTRL_ERR_BIT == (CFCTRL_ERR_BIT & cmdrsp) || |
@@ -541,6 +504,8 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) | |||
541 | 504 | ||
542 | if (req != NULL) | 505 | if (req != NULL) |
543 | kfree(req); | 506 | kfree(req); |
507 | |||
508 | spin_unlock_bh(&cfctrl->info_list_lock); | ||
544 | } | 509 | } |
545 | break; | 510 | break; |
546 | case CFCTRL_CMD_LINK_DESTROY: | 511 | case CFCTRL_CMD_LINK_DESTROY: |
@@ -584,12 +549,29 @@ static void cfctrl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, | |||
584 | switch (ctrl) { | 549 | switch (ctrl) { |
585 | case _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND: | 550 | case _CAIF_CTRLCMD_PHYIF_FLOW_OFF_IND: |
586 | case CAIF_CTRLCMD_FLOW_OFF_IND: | 551 | case CAIF_CTRLCMD_FLOW_OFF_IND: |
587 | spin_lock(&this->info_list_lock); | 552 | spin_lock_bh(&this->info_list_lock); |
588 | if (!list_empty(&this->list)) { | 553 | if (!list_empty(&this->list)) { |
589 | pr_debug("Received flow off in control layer\n"); | 554 | pr_debug("Received flow off in control layer\n"); |
590 | } | 555 | } |
591 | spin_unlock(&this->info_list_lock); | 556 | spin_unlock_bh(&this->info_list_lock); |
592 | break; | 557 | break; |
558 | case _CAIF_CTRLCMD_PHYIF_DOWN_IND: { | ||
559 | struct cfctrl_request_info *p, *tmp; | ||
560 | |||
561 | /* Find all connect request and report failure */ | ||
562 | spin_lock_bh(&this->info_list_lock); | ||
563 | list_for_each_entry_safe(p, tmp, &this->list, list) { | ||
564 | if (p->param.phyid == phyid) { | ||
565 | list_del(&p->list); | ||
566 | p->client_layer->ctrlcmd(p->client_layer, | ||
567 | CAIF_CTRLCMD_INIT_FAIL_RSP, | ||
568 | phyid); | ||
569 | kfree(p); | ||
570 | } | ||
571 | } | ||
572 | spin_unlock_bh(&this->info_list_lock); | ||
573 | break; | ||
574 | } | ||
593 | default: | 575 | default: |
594 | break; | 576 | break; |
595 | } | 577 | } |
@@ -599,27 +581,33 @@ static void cfctrl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, | |||
599 | static int handle_loop(struct cfctrl *ctrl, int cmd, struct cfpkt *pkt) | 581 | static int handle_loop(struct cfctrl *ctrl, int cmd, struct cfpkt *pkt) |
600 | { | 582 | { |
601 | static int last_linkid; | 583 | static int last_linkid; |
584 | static int dec; | ||
602 | u8 linkid, linktype, tmp; | 585 | u8 linkid, linktype, tmp; |
603 | switch (cmd) { | 586 | switch (cmd) { |
604 | case CFCTRL_CMD_LINK_SETUP: | 587 | case CFCTRL_CMD_LINK_SETUP: |
605 | spin_lock(&ctrl->loop_linkid_lock); | 588 | spin_lock_bh(&ctrl->loop_linkid_lock); |
606 | for (linkid = last_linkid + 1; linkid < 255; linkid++) | 589 | if (!dec) { |
607 | if (!ctrl->loop_linkused[linkid]) | 590 | for (linkid = last_linkid + 1; linkid < 255; linkid++) |
608 | goto found; | 591 | if (!ctrl->loop_linkused[linkid]) |
592 | goto found; | ||
593 | } | ||
594 | dec = 1; | ||
609 | for (linkid = last_linkid - 1; linkid > 0; linkid--) | 595 | for (linkid = last_linkid - 1; linkid > 0; linkid--) |
610 | if (!ctrl->loop_linkused[linkid]) | 596 | if (!ctrl->loop_linkused[linkid]) |
611 | goto found; | 597 | goto found; |
612 | spin_unlock(&ctrl->loop_linkid_lock); | 598 | spin_unlock_bh(&ctrl->loop_linkid_lock); |
613 | pr_err("Out of link-ids\n"); | 599 | |
614 | return -EINVAL; | ||
615 | found: | 600 | found: |
601 | if (linkid < 10) | ||
602 | dec = 0; | ||
603 | |||
616 | if (!ctrl->loop_linkused[linkid]) | 604 | if (!ctrl->loop_linkused[linkid]) |
617 | ctrl->loop_linkused[linkid] = 1; | 605 | ctrl->loop_linkused[linkid] = 1; |
618 | 606 | ||
619 | last_linkid = linkid; | 607 | last_linkid = linkid; |
620 | 608 | ||
621 | cfpkt_add_trail(pkt, &linkid, 1); | 609 | cfpkt_add_trail(pkt, &linkid, 1); |
622 | spin_unlock(&ctrl->loop_linkid_lock); | 610 | spin_unlock_bh(&ctrl->loop_linkid_lock); |
623 | cfpkt_peek_head(pkt, &linktype, 1); | 611 | cfpkt_peek_head(pkt, &linktype, 1); |
624 | if (linktype == CFCTRL_SRV_UTIL) { | 612 | if (linktype == CFCTRL_SRV_UTIL) { |
625 | tmp = 0x01; | 613 | tmp = 0x01; |
@@ -629,10 +617,10 @@ found: | |||
629 | break; | 617 | break; |
630 | 618 | ||
631 | case CFCTRL_CMD_LINK_DESTROY: | 619 | case CFCTRL_CMD_LINK_DESTROY: |
632 | spin_lock(&ctrl->loop_linkid_lock); | 620 | spin_lock_bh(&ctrl->loop_linkid_lock); |
633 | cfpkt_peek_head(pkt, &linkid, 1); | 621 | cfpkt_peek_head(pkt, &linkid, 1); |
634 | ctrl->loop_linkused[linkid] = 0; | 622 | ctrl->loop_linkused[linkid] = 0; |
635 | spin_unlock(&ctrl->loop_linkid_lock); | 623 | spin_unlock_bh(&ctrl->loop_linkid_lock); |
636 | break; | 624 | break; |
637 | default: | 625 | default: |
638 | break; | 626 | break; |
diff --git a/net/caif/cfdgml.c b/net/caif/cfdgml.c index 27dab26ad3b8..0382dec84fdc 100644 --- a/net/caif/cfdgml.c +++ b/net/caif/cfdgml.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <net/caif/cfsrvl.h> | 13 | #include <net/caif/cfsrvl.h> |
14 | #include <net/caif/cfpkt.h> | 14 | #include <net/caif/cfpkt.h> |
15 | 15 | ||
16 | |||
16 | #define container_obj(layr) ((struct cfsrvl *) layr) | 17 | #define container_obj(layr) ((struct cfsrvl *) layr) |
17 | 18 | ||
18 | #define DGM_CMD_BIT 0x80 | 19 | #define DGM_CMD_BIT 0x80 |
@@ -83,6 +84,7 @@ static int cfdgml_receive(struct cflayer *layr, struct cfpkt *pkt) | |||
83 | 84 | ||
84 | static int cfdgml_transmit(struct cflayer *layr, struct cfpkt *pkt) | 85 | static int cfdgml_transmit(struct cflayer *layr, struct cfpkt *pkt) |
85 | { | 86 | { |
87 | u8 packet_type; | ||
86 | u32 zero = 0; | 88 | u32 zero = 0; |
87 | struct caif_payload_info *info; | 89 | struct caif_payload_info *info; |
88 | struct cfsrvl *service = container_obj(layr); | 90 | struct cfsrvl *service = container_obj(layr); |
@@ -94,7 +96,9 @@ static int cfdgml_transmit(struct cflayer *layr, struct cfpkt *pkt) | |||
94 | if (cfpkt_getlen(pkt) > DGM_MTU) | 96 | if (cfpkt_getlen(pkt) > DGM_MTU) |
95 | return -EMSGSIZE; | 97 | return -EMSGSIZE; |
96 | 98 | ||
97 | cfpkt_add_head(pkt, &zero, 4); | 99 | cfpkt_add_head(pkt, &zero, 3); |
100 | packet_type = 0x08; /* B9 set - UNCLASSIFIED */ | ||
101 | cfpkt_add_head(pkt, &packet_type, 1); | ||
98 | 102 | ||
99 | /* Add info for MUX-layer to route the packet out. */ | 103 | /* Add info for MUX-layer to route the packet out. */ |
100 | info = cfpkt_info(pkt); | 104 | info = cfpkt_info(pkt); |
@@ -104,10 +108,5 @@ static int cfdgml_transmit(struct cflayer *layr, struct cfpkt *pkt) | |||
104 | */ | 108 | */ |
105 | info->hdr_len = 4; | 109 | info->hdr_len = 4; |
106 | info->dev_info = &service->dev_info; | 110 | info->dev_info = &service->dev_info; |
107 | ret = layr->dn->transmit(layr->dn, pkt); | 111 | return layr->dn->transmit(layr->dn, pkt); |
108 | if (ret < 0) { | ||
109 | u32 tmp32; | ||
110 | cfpkt_extr_head(pkt, &tmp32, 4); | ||
111 | } | ||
112 | return ret; | ||
113 | } | 112 | } |
diff --git a/net/caif/cffrml.c b/net/caif/cffrml.c index a445043931ae..04204b202718 100644 --- a/net/caif/cffrml.c +++ b/net/caif/cffrml.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/spinlock.h> | 12 | #include <linux/spinlock.h> |
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | #include <linux/crc-ccitt.h> | 14 | #include <linux/crc-ccitt.h> |
15 | #include <linux/netdevice.h> | ||
15 | #include <net/caif/caif_layer.h> | 16 | #include <net/caif/caif_layer.h> |
16 | #include <net/caif/cfpkt.h> | 17 | #include <net/caif/cfpkt.h> |
17 | #include <net/caif/cffrml.h> | 18 | #include <net/caif/cffrml.h> |
@@ -21,6 +22,7 @@ | |||
21 | struct cffrml { | 22 | struct cffrml { |
22 | struct cflayer layer; | 23 | struct cflayer layer; |
23 | bool dofcs; /* !< FCS active */ | 24 | bool dofcs; /* !< FCS active */ |
25 | int __percpu *pcpu_refcnt; | ||
24 | }; | 26 | }; |
25 | 27 | ||
26 | static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt); | 28 | static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt); |
@@ -37,6 +39,12 @@ struct cflayer *cffrml_create(u16 phyid, bool use_fcs) | |||
37 | pr_warn("Out of memory\n"); | 39 | pr_warn("Out of memory\n"); |
38 | return NULL; | 40 | return NULL; |
39 | } | 41 | } |
42 | this->pcpu_refcnt = alloc_percpu(int); | ||
43 | if (this->pcpu_refcnt == NULL) { | ||
44 | kfree(this); | ||
45 | return NULL; | ||
46 | } | ||
47 | |||
40 | caif_assert(offsetof(struct cffrml, layer) == 0); | 48 | caif_assert(offsetof(struct cffrml, layer) == 0); |
41 | 49 | ||
42 | memset(this, 0, sizeof(struct cflayer)); | 50 | memset(this, 0, sizeof(struct cflayer)); |
@@ -49,6 +57,13 @@ struct cflayer *cffrml_create(u16 phyid, bool use_fcs) | |||
49 | return (struct cflayer *) this; | 57 | return (struct cflayer *) this; |
50 | } | 58 | } |
51 | 59 | ||
60 | void cffrml_free(struct cflayer *layer) | ||
61 | { | ||
62 | struct cffrml *this = container_obj(layer); | ||
63 | free_percpu(this->pcpu_refcnt); | ||
64 | kfree(layer); | ||
65 | } | ||
66 | |||
52 | void cffrml_set_uplayer(struct cflayer *this, struct cflayer *up) | 67 | void cffrml_set_uplayer(struct cflayer *this, struct cflayer *up) |
53 | { | 68 | { |
54 | this->up = up; | 69 | this->up = up; |
@@ -112,6 +127,13 @@ static int cffrml_receive(struct cflayer *layr, struct cfpkt *pkt) | |||
112 | cfpkt_destroy(pkt); | 127 | cfpkt_destroy(pkt); |
113 | return -EPROTO; | 128 | return -EPROTO; |
114 | } | 129 | } |
130 | |||
131 | if (layr->up == NULL) { | ||
132 | pr_err("Layr up is missing!\n"); | ||
133 | cfpkt_destroy(pkt); | ||
134 | return -EINVAL; | ||
135 | } | ||
136 | |||
115 | return layr->up->receive(layr->up, pkt); | 137 | return layr->up->receive(layr->up, pkt); |
116 | } | 138 | } |
117 | 139 | ||
@@ -120,7 +142,6 @@ static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt) | |||
120 | int tmp; | 142 | int tmp; |
121 | u16 chks; | 143 | u16 chks; |
122 | u16 len; | 144 | u16 len; |
123 | int ret; | ||
124 | struct cffrml *this = container_obj(layr); | 145 | struct cffrml *this = container_obj(layr); |
125 | if (this->dofcs) { | 146 | if (this->dofcs) { |
126 | chks = cfpkt_iterate(pkt, cffrml_checksum, 0xffff); | 147 | chks = cfpkt_iterate(pkt, cffrml_checksum, 0xffff); |
@@ -135,19 +156,44 @@ static int cffrml_transmit(struct cflayer *layr, struct cfpkt *pkt) | |||
135 | cfpkt_info(pkt)->hdr_len += 2; | 156 | cfpkt_info(pkt)->hdr_len += 2; |
136 | if (cfpkt_erroneous(pkt)) { | 157 | if (cfpkt_erroneous(pkt)) { |
137 | pr_err("Packet is erroneous!\n"); | 158 | pr_err("Packet is erroneous!\n"); |
159 | cfpkt_destroy(pkt); | ||
138 | return -EPROTO; | 160 | return -EPROTO; |
139 | } | 161 | } |
140 | ret = layr->dn->transmit(layr->dn, pkt); | 162 | |
141 | if (ret < 0) { | 163 | if (layr->dn == NULL) { |
142 | /* Remove header on faulty packet. */ | 164 | cfpkt_destroy(pkt); |
143 | cfpkt_extr_head(pkt, &tmp, 2); | 165 | return -ENODEV; |
166 | |||
144 | } | 167 | } |
145 | return ret; | 168 | return layr->dn->transmit(layr->dn, pkt); |
146 | } | 169 | } |
147 | 170 | ||
148 | static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, | 171 | static void cffrml_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, |
149 | int phyid) | 172 | int phyid) |
150 | { | 173 | { |
151 | if (layr->up->ctrlcmd) | 174 | if (layr->up && layr->up->ctrlcmd) |
152 | layr->up->ctrlcmd(layr->up, ctrl, layr->id); | 175 | layr->up->ctrlcmd(layr->up, ctrl, layr->id); |
153 | } | 176 | } |
177 | |||
178 | void cffrml_put(struct cflayer *layr) | ||
179 | { | ||
180 | struct cffrml *this = container_obj(layr); | ||
181 | if (layr != NULL && this->pcpu_refcnt != NULL) | ||
182 | irqsafe_cpu_dec(*this->pcpu_refcnt); | ||
183 | } | ||
184 | |||
185 | void cffrml_hold(struct cflayer *layr) | ||
186 | { | ||
187 | struct cffrml *this = container_obj(layr); | ||
188 | if (layr != NULL && this->pcpu_refcnt != NULL) | ||
189 | irqsafe_cpu_inc(*this->pcpu_refcnt); | ||
190 | } | ||
191 | |||
192 | int cffrml_refcnt_read(struct cflayer *layr) | ||
193 | { | ||
194 | int i, refcnt = 0; | ||
195 | struct cffrml *this = container_obj(layr); | ||
196 | for_each_possible_cpu(i) | ||
197 | refcnt += *per_cpu_ptr(this->pcpu_refcnt, i); | ||
198 | return refcnt; | ||
199 | } | ||
diff --git a/net/caif/cfmuxl.c b/net/caif/cfmuxl.c index 46f34b2e0478..2a56df7e0a4b 100644 --- a/net/caif/cfmuxl.c +++ b/net/caif/cfmuxl.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/stddef.h> | 9 | #include <linux/stddef.h> |
10 | #include <linux/spinlock.h> | 10 | #include <linux/spinlock.h> |
11 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
12 | #include <linux/rculist.h> | ||
12 | #include <net/caif/cfpkt.h> | 13 | #include <net/caif/cfpkt.h> |
13 | #include <net/caif/cfmuxl.h> | 14 | #include <net/caif/cfmuxl.h> |
14 | #include <net/caif/cfsrvl.h> | 15 | #include <net/caif/cfsrvl.h> |
@@ -64,66 +65,31 @@ struct cflayer *cfmuxl_create(void) | |||
64 | int cfmuxl_set_uplayer(struct cflayer *layr, struct cflayer *up, u8 linkid) | 65 | int cfmuxl_set_uplayer(struct cflayer *layr, struct cflayer *up, u8 linkid) |
65 | { | 66 | { |
66 | struct cfmuxl *muxl = container_obj(layr); | 67 | struct cfmuxl *muxl = container_obj(layr); |
67 | spin_lock(&muxl->receive_lock); | ||
68 | cfsrvl_get(up); | ||
69 | list_add(&up->node, &muxl->srvl_list); | ||
70 | spin_unlock(&muxl->receive_lock); | ||
71 | return 0; | ||
72 | } | ||
73 | |||
74 | bool cfmuxl_is_phy_inuse(struct cflayer *layr, u8 phyid) | ||
75 | { | ||
76 | struct list_head *node; | ||
77 | struct cflayer *layer; | ||
78 | struct cfmuxl *muxl = container_obj(layr); | ||
79 | bool match = false; | ||
80 | spin_lock(&muxl->receive_lock); | ||
81 | |||
82 | list_for_each(node, &muxl->srvl_list) { | ||
83 | layer = list_entry(node, struct cflayer, node); | ||
84 | if (cfsrvl_phyid_match(layer, phyid)) { | ||
85 | match = true; | ||
86 | break; | ||
87 | } | ||
88 | |||
89 | } | ||
90 | spin_unlock(&muxl->receive_lock); | ||
91 | return match; | ||
92 | } | ||
93 | 68 | ||
94 | u8 cfmuxl_get_phyid(struct cflayer *layr, u8 channel_id) | 69 | spin_lock_bh(&muxl->receive_lock); |
95 | { | 70 | list_add_rcu(&up->node, &muxl->srvl_list); |
96 | struct cflayer *up; | 71 | spin_unlock_bh(&muxl->receive_lock); |
97 | int phyid; | 72 | return 0; |
98 | struct cfmuxl *muxl = container_obj(layr); | ||
99 | spin_lock(&muxl->receive_lock); | ||
100 | up = get_up(muxl, channel_id); | ||
101 | if (up != NULL) | ||
102 | phyid = cfsrvl_getphyid(up); | ||
103 | else | ||
104 | phyid = 0; | ||
105 | spin_unlock(&muxl->receive_lock); | ||
106 | return phyid; | ||
107 | } | 73 | } |
108 | 74 | ||
109 | int cfmuxl_set_dnlayer(struct cflayer *layr, struct cflayer *dn, u8 phyid) | 75 | int cfmuxl_set_dnlayer(struct cflayer *layr, struct cflayer *dn, u8 phyid) |
110 | { | 76 | { |
111 | struct cfmuxl *muxl = (struct cfmuxl *) layr; | 77 | struct cfmuxl *muxl = (struct cfmuxl *) layr; |
112 | spin_lock(&muxl->transmit_lock); | 78 | |
113 | list_add(&dn->node, &muxl->frml_list); | 79 | spin_lock_bh(&muxl->transmit_lock); |
114 | spin_unlock(&muxl->transmit_lock); | 80 | list_add_rcu(&dn->node, &muxl->frml_list); |
81 | spin_unlock_bh(&muxl->transmit_lock); | ||
115 | return 0; | 82 | return 0; |
116 | } | 83 | } |
117 | 84 | ||
118 | static struct cflayer *get_from_id(struct list_head *list, u16 id) | 85 | static struct cflayer *get_from_id(struct list_head *list, u16 id) |
119 | { | 86 | { |
120 | struct list_head *node; | 87 | struct cflayer *lyr; |
121 | struct cflayer *layer; | 88 | list_for_each_entry_rcu(lyr, list, node) { |
122 | list_for_each(node, list) { | 89 | if (lyr->id == id) |
123 | layer = list_entry(node, struct cflayer, node); | 90 | return lyr; |
124 | if (layer->id == id) | ||
125 | return layer; | ||
126 | } | 91 | } |
92 | |||
127 | return NULL; | 93 | return NULL; |
128 | } | 94 | } |
129 | 95 | ||
@@ -131,41 +97,45 @@ struct cflayer *cfmuxl_remove_dnlayer(struct cflayer *layr, u8 phyid) | |||
131 | { | 97 | { |
132 | struct cfmuxl *muxl = container_obj(layr); | 98 | struct cfmuxl *muxl = container_obj(layr); |
133 | struct cflayer *dn; | 99 | struct cflayer *dn; |
134 | spin_lock(&muxl->transmit_lock); | 100 | int idx = phyid % DN_CACHE_SIZE; |
135 | memset(muxl->dn_cache, 0, sizeof(muxl->dn_cache)); | 101 | |
102 | spin_lock_bh(&muxl->transmit_lock); | ||
103 | rcu_assign_pointer(muxl->dn_cache[idx], NULL); | ||
136 | dn = get_from_id(&muxl->frml_list, phyid); | 104 | dn = get_from_id(&muxl->frml_list, phyid); |
137 | if (dn == NULL) { | 105 | if (dn == NULL) |
138 | spin_unlock(&muxl->transmit_lock); | 106 | goto out; |
139 | return NULL; | 107 | |
140 | } | 108 | list_del_rcu(&dn->node); |
141 | list_del(&dn->node); | ||
142 | caif_assert(dn != NULL); | 109 | caif_assert(dn != NULL); |
143 | spin_unlock(&muxl->transmit_lock); | 110 | out: |
111 | spin_unlock_bh(&muxl->transmit_lock); | ||
144 | return dn; | 112 | return dn; |
145 | } | 113 | } |
146 | 114 | ||
147 | /* Invariant: lock is taken */ | ||
148 | static struct cflayer *get_up(struct cfmuxl *muxl, u16 id) | 115 | static struct cflayer *get_up(struct cfmuxl *muxl, u16 id) |
149 | { | 116 | { |
150 | struct cflayer *up; | 117 | struct cflayer *up; |
151 | int idx = id % UP_CACHE_SIZE; | 118 | int idx = id % UP_CACHE_SIZE; |
152 | up = muxl->up_cache[idx]; | 119 | up = rcu_dereference(muxl->up_cache[idx]); |
153 | if (up == NULL || up->id != id) { | 120 | if (up == NULL || up->id != id) { |
121 | spin_lock_bh(&muxl->receive_lock); | ||
154 | up = get_from_id(&muxl->srvl_list, id); | 122 | up = get_from_id(&muxl->srvl_list, id); |
155 | muxl->up_cache[idx] = up; | 123 | rcu_assign_pointer(muxl->up_cache[idx], up); |
124 | spin_unlock_bh(&muxl->receive_lock); | ||
156 | } | 125 | } |
157 | return up; | 126 | return up; |
158 | } | 127 | } |
159 | 128 | ||
160 | /* Invariant: lock is taken */ | ||
161 | static struct cflayer *get_dn(struct cfmuxl *muxl, struct dev_info *dev_info) | 129 | static struct cflayer *get_dn(struct cfmuxl *muxl, struct dev_info *dev_info) |
162 | { | 130 | { |
163 | struct cflayer *dn; | 131 | struct cflayer *dn; |
164 | int idx = dev_info->id % DN_CACHE_SIZE; | 132 | int idx = dev_info->id % DN_CACHE_SIZE; |
165 | dn = muxl->dn_cache[idx]; | 133 | dn = rcu_dereference(muxl->dn_cache[idx]); |
166 | if (dn == NULL || dn->id != dev_info->id) { | 134 | if (dn == NULL || dn->id != dev_info->id) { |
135 | spin_lock_bh(&muxl->transmit_lock); | ||
167 | dn = get_from_id(&muxl->frml_list, dev_info->id); | 136 | dn = get_from_id(&muxl->frml_list, dev_info->id); |
168 | muxl->dn_cache[idx] = dn; | 137 | rcu_assign_pointer(muxl->dn_cache[idx], dn); |
138 | spin_unlock_bh(&muxl->transmit_lock); | ||
169 | } | 139 | } |
170 | return dn; | 140 | return dn; |
171 | } | 141 | } |
@@ -174,15 +144,17 @@ struct cflayer *cfmuxl_remove_uplayer(struct cflayer *layr, u8 id) | |||
174 | { | 144 | { |
175 | struct cflayer *up; | 145 | struct cflayer *up; |
176 | struct cfmuxl *muxl = container_obj(layr); | 146 | struct cfmuxl *muxl = container_obj(layr); |
177 | spin_lock(&muxl->receive_lock); | 147 | int idx = id % UP_CACHE_SIZE; |
178 | up = get_up(muxl, id); | 148 | |
149 | spin_lock_bh(&muxl->receive_lock); | ||
150 | up = get_from_id(&muxl->srvl_list, id); | ||
179 | if (up == NULL) | 151 | if (up == NULL) |
180 | goto out; | 152 | goto out; |
181 | memset(muxl->up_cache, 0, sizeof(muxl->up_cache)); | 153 | |
182 | list_del(&up->node); | 154 | rcu_assign_pointer(muxl->up_cache[idx], NULL); |
183 | cfsrvl_put(up); | 155 | list_del_rcu(&up->node); |
184 | out: | 156 | out: |
185 | spin_unlock(&muxl->receive_lock); | 157 | spin_unlock_bh(&muxl->receive_lock); |
186 | return up; | 158 | return up; |
187 | } | 159 | } |
188 | 160 | ||
@@ -197,58 +169,78 @@ static int cfmuxl_receive(struct cflayer *layr, struct cfpkt *pkt) | |||
197 | cfpkt_destroy(pkt); | 169 | cfpkt_destroy(pkt); |
198 | return -EPROTO; | 170 | return -EPROTO; |
199 | } | 171 | } |
200 | 172 | rcu_read_lock(); | |
201 | spin_lock(&muxl->receive_lock); | ||
202 | up = get_up(muxl, id); | 173 | up = get_up(muxl, id); |
203 | spin_unlock(&muxl->receive_lock); | 174 | |
204 | if (up == NULL) { | 175 | if (up == NULL) { |
205 | pr_info("Received data on unknown link ID = %d (0x%x) up == NULL", | 176 | pr_debug("Received data on unknown link ID = %d (0x%x)" |
206 | id, id); | 177 | " up == NULL", id, id); |
207 | cfpkt_destroy(pkt); | 178 | cfpkt_destroy(pkt); |
208 | /* | 179 | /* |
209 | * Don't return ERROR, since modem misbehaves and sends out | 180 | * Don't return ERROR, since modem misbehaves and sends out |
210 | * flow on before linksetup response. | 181 | * flow on before linksetup response. |
211 | */ | 182 | */ |
183 | |||
184 | rcu_read_unlock(); | ||
212 | return /* CFGLU_EPROT; */ 0; | 185 | return /* CFGLU_EPROT; */ 0; |
213 | } | 186 | } |
187 | |||
188 | /* We can't hold rcu_lock during receive, so take a ref count instead */ | ||
214 | cfsrvl_get(up); | 189 | cfsrvl_get(up); |
190 | rcu_read_unlock(); | ||
191 | |||
215 | ret = up->receive(up, pkt); | 192 | ret = up->receive(up, pkt); |
193 | |||
216 | cfsrvl_put(up); | 194 | cfsrvl_put(up); |
217 | return ret; | 195 | return ret; |
218 | } | 196 | } |
219 | 197 | ||
220 | static int cfmuxl_transmit(struct cflayer *layr, struct cfpkt *pkt) | 198 | static int cfmuxl_transmit(struct cflayer *layr, struct cfpkt *pkt) |
221 | { | 199 | { |
222 | int ret; | ||
223 | struct cfmuxl *muxl = container_obj(layr); | 200 | struct cfmuxl *muxl = container_obj(layr); |
201 | int err; | ||
224 | u8 linkid; | 202 | u8 linkid; |
225 | struct cflayer *dn; | 203 | struct cflayer *dn; |
226 | struct caif_payload_info *info = cfpkt_info(pkt); | 204 | struct caif_payload_info *info = cfpkt_info(pkt); |
227 | dn = get_dn(muxl, cfpkt_info(pkt)->dev_info); | 205 | BUG_ON(!info); |
206 | |||
207 | rcu_read_lock(); | ||
208 | |||
209 | dn = get_dn(muxl, info->dev_info); | ||
228 | if (dn == NULL) { | 210 | if (dn == NULL) { |
229 | pr_warn("Send data on unknown phy ID = %d (0x%x)\n", | 211 | pr_debug("Send data on unknown phy ID = %d (0x%x)\n", |
230 | info->dev_info->id, info->dev_info->id); | 212 | info->dev_info->id, info->dev_info->id); |
213 | rcu_read_unlock(); | ||
214 | cfpkt_destroy(pkt); | ||
231 | return -ENOTCONN; | 215 | return -ENOTCONN; |
232 | } | 216 | } |
217 | |||
233 | info->hdr_len += 1; | 218 | info->hdr_len += 1; |
234 | linkid = info->channel_id; | 219 | linkid = info->channel_id; |
235 | cfpkt_add_head(pkt, &linkid, 1); | 220 | cfpkt_add_head(pkt, &linkid, 1); |
236 | ret = dn->transmit(dn, pkt); | 221 | |
237 | /* Remove MUX protocol header upon error. */ | 222 | /* We can't hold rcu_lock during receive, so take a ref count instead */ |
238 | if (ret < 0) | 223 | cffrml_hold(dn); |
239 | cfpkt_extr_head(pkt, &linkid, 1); | 224 | |
240 | return ret; | 225 | rcu_read_unlock(); |
226 | |||
227 | err = dn->transmit(dn, pkt); | ||
228 | |||
229 | cffrml_put(dn); | ||
230 | return err; | ||
241 | } | 231 | } |
242 | 232 | ||
243 | static void cfmuxl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, | 233 | static void cfmuxl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, |
244 | int phyid) | 234 | int phyid) |
245 | { | 235 | { |
246 | struct cfmuxl *muxl = container_obj(layr); | 236 | struct cfmuxl *muxl = container_obj(layr); |
247 | struct list_head *node; | ||
248 | struct cflayer *layer; | 237 | struct cflayer *layer; |
249 | list_for_each(node, &muxl->srvl_list) { | 238 | |
250 | layer = list_entry(node, struct cflayer, node); | 239 | rcu_read_lock(); |
251 | if (cfsrvl_phyid_match(layer, phyid)) | 240 | list_for_each_entry_rcu(layer, &muxl->srvl_list, node) { |
241 | if (cfsrvl_phyid_match(layer, phyid) && layer->ctrlcmd) | ||
242 | /* NOTE: ctrlcmd is not allowed to block */ | ||
252 | layer->ctrlcmd(layer, ctrl, phyid); | 243 | layer->ctrlcmd(layer, ctrl, phyid); |
253 | } | 244 | } |
245 | rcu_read_unlock(); | ||
254 | } | 246 | } |
diff --git a/net/caif/cfpkt_skbuff.c b/net/caif/cfpkt_skbuff.c index d7e865e2ff65..75d4bfae1a78 100644 --- a/net/caif/cfpkt_skbuff.c +++ b/net/caif/cfpkt_skbuff.c | |||
@@ -42,22 +42,22 @@ struct cfpkt_priv_data { | |||
42 | bool erronous; | 42 | bool erronous; |
43 | }; | 43 | }; |
44 | 44 | ||
45 | inline struct cfpkt_priv_data *cfpkt_priv(struct cfpkt *pkt) | 45 | static inline struct cfpkt_priv_data *cfpkt_priv(struct cfpkt *pkt) |
46 | { | 46 | { |
47 | return (struct cfpkt_priv_data *) pkt->skb.cb; | 47 | return (struct cfpkt_priv_data *) pkt->skb.cb; |
48 | } | 48 | } |
49 | 49 | ||
50 | inline bool is_erronous(struct cfpkt *pkt) | 50 | static inline bool is_erronous(struct cfpkt *pkt) |
51 | { | 51 | { |
52 | return cfpkt_priv(pkt)->erronous; | 52 | return cfpkt_priv(pkt)->erronous; |
53 | } | 53 | } |
54 | 54 | ||
55 | inline struct sk_buff *pkt_to_skb(struct cfpkt *pkt) | 55 | static inline struct sk_buff *pkt_to_skb(struct cfpkt *pkt) |
56 | { | 56 | { |
57 | return &pkt->skb; | 57 | return &pkt->skb; |
58 | } | 58 | } |
59 | 59 | ||
60 | inline struct cfpkt *skb_to_pkt(struct sk_buff *skb) | 60 | static inline struct cfpkt *skb_to_pkt(struct sk_buff *skb) |
61 | { | 61 | { |
62 | return (struct cfpkt *) skb; | 62 | return (struct cfpkt *) skb; |
63 | } | 63 | } |
@@ -97,21 +97,20 @@ inline struct cfpkt *cfpkt_create(u16 len) | |||
97 | { | 97 | { |
98 | return cfpkt_create_pfx(len + PKT_POSTFIX, PKT_PREFIX); | 98 | return cfpkt_create_pfx(len + PKT_POSTFIX, PKT_PREFIX); |
99 | } | 99 | } |
100 | EXPORT_SYMBOL(cfpkt_create); | ||
101 | 100 | ||
102 | void cfpkt_destroy(struct cfpkt *pkt) | 101 | void cfpkt_destroy(struct cfpkt *pkt) |
103 | { | 102 | { |
104 | struct sk_buff *skb = pkt_to_skb(pkt); | 103 | struct sk_buff *skb = pkt_to_skb(pkt); |
105 | kfree_skb(skb); | 104 | kfree_skb(skb); |
106 | } | 105 | } |
107 | EXPORT_SYMBOL(cfpkt_destroy); | 106 | |
108 | 107 | ||
109 | inline bool cfpkt_more(struct cfpkt *pkt) | 108 | inline bool cfpkt_more(struct cfpkt *pkt) |
110 | { | 109 | { |
111 | struct sk_buff *skb = pkt_to_skb(pkt); | 110 | struct sk_buff *skb = pkt_to_skb(pkt); |
112 | return skb->len > 0; | 111 | return skb->len > 0; |
113 | } | 112 | } |
114 | EXPORT_SYMBOL(cfpkt_more); | 113 | |
115 | 114 | ||
116 | int cfpkt_peek_head(struct cfpkt *pkt, void *data, u16 len) | 115 | int cfpkt_peek_head(struct cfpkt *pkt, void *data, u16 len) |
117 | { | 116 | { |
@@ -123,7 +122,6 @@ int cfpkt_peek_head(struct cfpkt *pkt, void *data, u16 len) | |||
123 | return !cfpkt_extr_head(pkt, data, len) && | 122 | return !cfpkt_extr_head(pkt, data, len) && |
124 | !cfpkt_add_head(pkt, data, len); | 123 | !cfpkt_add_head(pkt, data, len); |
125 | } | 124 | } |
126 | EXPORT_SYMBOL(cfpkt_peek_head); | ||
127 | 125 | ||
128 | int cfpkt_extr_head(struct cfpkt *pkt, void *data, u16 len) | 126 | int cfpkt_extr_head(struct cfpkt *pkt, void *data, u16 len) |
129 | { | 127 | { |
@@ -148,7 +146,6 @@ int cfpkt_extr_head(struct cfpkt *pkt, void *data, u16 len) | |||
148 | memcpy(data, from, len); | 146 | memcpy(data, from, len); |
149 | return 0; | 147 | return 0; |
150 | } | 148 | } |
151 | EXPORT_SYMBOL(cfpkt_extr_head); | ||
152 | 149 | ||
153 | int cfpkt_extr_trail(struct cfpkt *pkt, void *dta, u16 len) | 150 | int cfpkt_extr_trail(struct cfpkt *pkt, void *dta, u16 len) |
154 | { | 151 | { |
@@ -171,13 +168,13 @@ int cfpkt_extr_trail(struct cfpkt *pkt, void *dta, u16 len) | |||
171 | memcpy(data, from, len); | 168 | memcpy(data, from, len); |
172 | return 0; | 169 | return 0; |
173 | } | 170 | } |
174 | EXPORT_SYMBOL(cfpkt_extr_trail); | 171 | |
175 | 172 | ||
176 | int cfpkt_pad_trail(struct cfpkt *pkt, u16 len) | 173 | int cfpkt_pad_trail(struct cfpkt *pkt, u16 len) |
177 | { | 174 | { |
178 | return cfpkt_add_body(pkt, NULL, len); | 175 | return cfpkt_add_body(pkt, NULL, len); |
179 | } | 176 | } |
180 | EXPORT_SYMBOL(cfpkt_pad_trail); | 177 | |
181 | 178 | ||
182 | int cfpkt_add_body(struct cfpkt *pkt, const void *data, u16 len) | 179 | int cfpkt_add_body(struct cfpkt *pkt, const void *data, u16 len) |
183 | { | 180 | { |
@@ -226,13 +223,11 @@ int cfpkt_add_body(struct cfpkt *pkt, const void *data, u16 len) | |||
226 | memcpy(to, data, len); | 223 | memcpy(to, data, len); |
227 | return 0; | 224 | return 0; |
228 | } | 225 | } |
229 | EXPORT_SYMBOL(cfpkt_add_body); | ||
230 | 226 | ||
231 | inline int cfpkt_addbdy(struct cfpkt *pkt, u8 data) | 227 | inline int cfpkt_addbdy(struct cfpkt *pkt, u8 data) |
232 | { | 228 | { |
233 | return cfpkt_add_body(pkt, &data, 1); | 229 | return cfpkt_add_body(pkt, &data, 1); |
234 | } | 230 | } |
235 | EXPORT_SYMBOL(cfpkt_addbdy); | ||
236 | 231 | ||
237 | int cfpkt_add_head(struct cfpkt *pkt, const void *data2, u16 len) | 232 | int cfpkt_add_head(struct cfpkt *pkt, const void *data2, u16 len) |
238 | { | 233 | { |
@@ -259,20 +254,20 @@ int cfpkt_add_head(struct cfpkt *pkt, const void *data2, u16 len) | |||
259 | memcpy(to, data, len); | 254 | memcpy(to, data, len); |
260 | return 0; | 255 | return 0; |
261 | } | 256 | } |
262 | EXPORT_SYMBOL(cfpkt_add_head); | 257 | |
263 | 258 | ||
264 | inline int cfpkt_add_trail(struct cfpkt *pkt, const void *data, u16 len) | 259 | inline int cfpkt_add_trail(struct cfpkt *pkt, const void *data, u16 len) |
265 | { | 260 | { |
266 | return cfpkt_add_body(pkt, data, len); | 261 | return cfpkt_add_body(pkt, data, len); |
267 | } | 262 | } |
268 | EXPORT_SYMBOL(cfpkt_add_trail); | 263 | |
269 | 264 | ||
270 | inline u16 cfpkt_getlen(struct cfpkt *pkt) | 265 | inline u16 cfpkt_getlen(struct cfpkt *pkt) |
271 | { | 266 | { |
272 | struct sk_buff *skb = pkt_to_skb(pkt); | 267 | struct sk_buff *skb = pkt_to_skb(pkt); |
273 | return skb->len; | 268 | return skb->len; |
274 | } | 269 | } |
275 | EXPORT_SYMBOL(cfpkt_getlen); | 270 | |
276 | 271 | ||
277 | inline u16 cfpkt_iterate(struct cfpkt *pkt, | 272 | inline u16 cfpkt_iterate(struct cfpkt *pkt, |
278 | u16 (*iter_func)(u16, void *, u16), | 273 | u16 (*iter_func)(u16, void *, u16), |
@@ -290,7 +285,7 @@ inline u16 cfpkt_iterate(struct cfpkt *pkt, | |||
290 | } | 285 | } |
291 | return iter_func(data, pkt->skb.data, cfpkt_getlen(pkt)); | 286 | return iter_func(data, pkt->skb.data, cfpkt_getlen(pkt)); |
292 | } | 287 | } |
293 | EXPORT_SYMBOL(cfpkt_iterate); | 288 | |
294 | 289 | ||
295 | int cfpkt_setlen(struct cfpkt *pkt, u16 len) | 290 | int cfpkt_setlen(struct cfpkt *pkt, u16 len) |
296 | { | 291 | { |
@@ -315,18 +310,6 @@ int cfpkt_setlen(struct cfpkt *pkt, u16 len) | |||
315 | 310 | ||
316 | return cfpkt_getlen(pkt); | 311 | return cfpkt_getlen(pkt); |
317 | } | 312 | } |
318 | EXPORT_SYMBOL(cfpkt_setlen); | ||
319 | |||
320 | struct cfpkt *cfpkt_create_uplink(const unsigned char *data, unsigned int len) | ||
321 | { | ||
322 | struct cfpkt *pkt = cfpkt_create_pfx(len + PKT_POSTFIX, PKT_PREFIX); | ||
323 | if (!pkt) | ||
324 | return NULL; | ||
325 | if (unlikely(data != NULL)) | ||
326 | cfpkt_add_body(pkt, data, len); | ||
327 | return pkt; | ||
328 | } | ||
329 | EXPORT_SYMBOL(cfpkt_create_uplink); | ||
330 | 313 | ||
331 | struct cfpkt *cfpkt_append(struct cfpkt *dstpkt, | 314 | struct cfpkt *cfpkt_append(struct cfpkt *dstpkt, |
332 | struct cfpkt *addpkt, | 315 | struct cfpkt *addpkt, |
@@ -368,7 +351,6 @@ struct cfpkt *cfpkt_append(struct cfpkt *dstpkt, | |||
368 | dst->len += addlen; | 351 | dst->len += addlen; |
369 | return skb_to_pkt(dst); | 352 | return skb_to_pkt(dst); |
370 | } | 353 | } |
371 | EXPORT_SYMBOL(cfpkt_append); | ||
372 | 354 | ||
373 | struct cfpkt *cfpkt_split(struct cfpkt *pkt, u16 pos) | 355 | struct cfpkt *cfpkt_split(struct cfpkt *pkt, u16 pos) |
374 | { | 356 | { |
@@ -406,174 +388,13 @@ struct cfpkt *cfpkt_split(struct cfpkt *pkt, u16 pos) | |||
406 | skb2->len += len2nd; | 388 | skb2->len += len2nd; |
407 | return skb_to_pkt(skb2); | 389 | return skb_to_pkt(skb2); |
408 | } | 390 | } |
409 | EXPORT_SYMBOL(cfpkt_split); | ||
410 | |||
411 | char *cfpkt_log_pkt(struct cfpkt *pkt, char *buf, int buflen) | ||
412 | { | ||
413 | struct sk_buff *skb = pkt_to_skb(pkt); | ||
414 | char *p = buf; | ||
415 | int i; | ||
416 | |||
417 | /* | ||
418 | * Sanity check buffer length, it needs to be at least as large as | ||
419 | * the header info: ~=50+ bytes | ||
420 | */ | ||
421 | if (buflen < 50) | ||
422 | return NULL; | ||
423 | |||
424 | snprintf(buf, buflen, "%s: pkt:%p len:%ld(%ld+%ld) {%ld,%ld} data: [", | ||
425 | is_erronous(pkt) ? "ERRONOUS-SKB" : | ||
426 | (skb->data_len != 0 ? "COMPLEX-SKB" : "SKB"), | ||
427 | skb, | ||
428 | (long) skb->len, | ||
429 | (long) (skb_tail_pointer(skb) - skb->data), | ||
430 | (long) skb->data_len, | ||
431 | (long) (skb->data - skb->head), | ||
432 | (long) (skb_tail_pointer(skb) - skb->head)); | ||
433 | p = buf + strlen(buf); | ||
434 | |||
435 | for (i = 0; i < skb_tail_pointer(skb) - skb->data && i < 300; i++) { | ||
436 | if (p > buf + buflen - 10) { | ||
437 | sprintf(p, "..."); | ||
438 | p = buf + strlen(buf); | ||
439 | break; | ||
440 | } | ||
441 | sprintf(p, "%02x,", skb->data[i]); | ||
442 | p = buf + strlen(buf); | ||
443 | } | ||
444 | sprintf(p, "]\n"); | ||
445 | return buf; | ||
446 | } | ||
447 | EXPORT_SYMBOL(cfpkt_log_pkt); | ||
448 | |||
449 | int cfpkt_raw_append(struct cfpkt *pkt, void **buf, unsigned int buflen) | ||
450 | { | ||
451 | struct sk_buff *skb = pkt_to_skb(pkt); | ||
452 | struct sk_buff *lastskb; | ||
453 | |||
454 | caif_assert(buf != NULL); | ||
455 | if (unlikely(is_erronous(pkt))) | ||
456 | return -EPROTO; | ||
457 | /* Make sure SKB is writable */ | ||
458 | if (unlikely(skb_cow_data(skb, 0, &lastskb) < 0)) { | ||
459 | PKT_ERROR(pkt, "skb_cow_data failed\n"); | ||
460 | return -EPROTO; | ||
461 | } | ||
462 | |||
463 | if (unlikely(skb_linearize(skb) != 0)) { | ||
464 | PKT_ERROR(pkt, "linearize failed\n"); | ||
465 | return -EPROTO; | ||
466 | } | ||
467 | |||
468 | if (unlikely(skb_tailroom(skb) < buflen)) { | ||
469 | PKT_ERROR(pkt, "buffer too short - failed\n"); | ||
470 | return -EPROTO; | ||
471 | } | ||
472 | |||
473 | *buf = skb_put(skb, buflen); | ||
474 | return 1; | ||
475 | } | ||
476 | EXPORT_SYMBOL(cfpkt_raw_append); | ||
477 | 391 | ||
478 | int cfpkt_raw_extract(struct cfpkt *pkt, void **buf, unsigned int buflen) | 392 | bool cfpkt_erroneous(struct cfpkt *pkt) |
479 | { | ||
480 | struct sk_buff *skb = pkt_to_skb(pkt); | ||
481 | |||
482 | caif_assert(buf != NULL); | ||
483 | if (unlikely(is_erronous(pkt))) | ||
484 | return -EPROTO; | ||
485 | |||
486 | if (unlikely(buflen > skb->len)) { | ||
487 | PKT_ERROR(pkt, "buflen too large - failed\n"); | ||
488 | return -EPROTO; | ||
489 | } | ||
490 | |||
491 | if (unlikely(buflen > skb_headlen(skb))) { | ||
492 | if (unlikely(skb_linearize(skb) != 0)) { | ||
493 | PKT_ERROR(pkt, "linearize failed\n"); | ||
494 | return -EPROTO; | ||
495 | } | ||
496 | } | ||
497 | |||
498 | *buf = skb->data; | ||
499 | skb_pull(skb, buflen); | ||
500 | |||
501 | return 1; | ||
502 | } | ||
503 | EXPORT_SYMBOL(cfpkt_raw_extract); | ||
504 | |||
505 | inline bool cfpkt_erroneous(struct cfpkt *pkt) | ||
506 | { | 393 | { |
507 | return cfpkt_priv(pkt)->erronous; | 394 | return cfpkt_priv(pkt)->erronous; |
508 | } | 395 | } |
509 | EXPORT_SYMBOL(cfpkt_erroneous); | ||
510 | |||
511 | struct cfpktq *cfpktq_create(void) | ||
512 | { | ||
513 | struct cfpktq *q = kmalloc(sizeof(struct cfpktq), GFP_ATOMIC); | ||
514 | if (!q) | ||
515 | return NULL; | ||
516 | skb_queue_head_init(&q->head); | ||
517 | atomic_set(&q->count, 0); | ||
518 | spin_lock_init(&q->lock); | ||
519 | return q; | ||
520 | } | ||
521 | EXPORT_SYMBOL(cfpktq_create); | ||
522 | |||
523 | void cfpkt_queue(struct cfpktq *pktq, struct cfpkt *pkt, unsigned short prio) | ||
524 | { | ||
525 | atomic_inc(&pktq->count); | ||
526 | spin_lock(&pktq->lock); | ||
527 | skb_queue_tail(&pktq->head, pkt_to_skb(pkt)); | ||
528 | spin_unlock(&pktq->lock); | ||
529 | |||
530 | } | ||
531 | EXPORT_SYMBOL(cfpkt_queue); | ||
532 | |||
533 | struct cfpkt *cfpkt_qpeek(struct cfpktq *pktq) | ||
534 | { | ||
535 | struct cfpkt *tmp; | ||
536 | spin_lock(&pktq->lock); | ||
537 | tmp = skb_to_pkt(skb_peek(&pktq->head)); | ||
538 | spin_unlock(&pktq->lock); | ||
539 | return tmp; | ||
540 | } | ||
541 | EXPORT_SYMBOL(cfpkt_qpeek); | ||
542 | |||
543 | struct cfpkt *cfpkt_dequeue(struct cfpktq *pktq) | ||
544 | { | ||
545 | struct cfpkt *pkt; | ||
546 | spin_lock(&pktq->lock); | ||
547 | pkt = skb_to_pkt(skb_dequeue(&pktq->head)); | ||
548 | if (pkt) { | ||
549 | atomic_dec(&pktq->count); | ||
550 | caif_assert(atomic_read(&pktq->count) >= 0); | ||
551 | } | ||
552 | spin_unlock(&pktq->lock); | ||
553 | return pkt; | ||
554 | } | ||
555 | EXPORT_SYMBOL(cfpkt_dequeue); | ||
556 | |||
557 | int cfpkt_qcount(struct cfpktq *pktq) | ||
558 | { | ||
559 | return atomic_read(&pktq->count); | ||
560 | } | ||
561 | EXPORT_SYMBOL(cfpkt_qcount); | ||
562 | |||
563 | struct cfpkt *cfpkt_clone_release(struct cfpkt *pkt) | ||
564 | { | ||
565 | struct cfpkt *clone; | ||
566 | clone = skb_to_pkt(skb_clone(pkt_to_skb(pkt), GFP_ATOMIC)); | ||
567 | /* Free original packet. */ | ||
568 | cfpkt_destroy(pkt); | ||
569 | if (!clone) | ||
570 | return NULL; | ||
571 | return clone; | ||
572 | } | ||
573 | EXPORT_SYMBOL(cfpkt_clone_release); | ||
574 | 396 | ||
575 | struct caif_payload_info *cfpkt_info(struct cfpkt *pkt) | 397 | struct caif_payload_info *cfpkt_info(struct cfpkt *pkt) |
576 | { | 398 | { |
577 | return (struct caif_payload_info *)&pkt_to_skb(pkt)->cb; | 399 | return (struct caif_payload_info *)&pkt_to_skb(pkt)->cb; |
578 | } | 400 | } |
579 | EXPORT_SYMBOL(cfpkt_info); | ||
diff --git a/net/caif/cfrfml.c b/net/caif/cfrfml.c index e2fb5fa75795..0deabb440051 100644 --- a/net/caif/cfrfml.c +++ b/net/caif/cfrfml.c | |||
@@ -31,9 +31,9 @@ struct cfrfml { | |||
31 | spinlock_t sync; | 31 | spinlock_t sync; |
32 | }; | 32 | }; |
33 | 33 | ||
34 | static void cfrfml_release(struct kref *kref) | 34 | static void cfrfml_release(struct cflayer *layer) |
35 | { | 35 | { |
36 | struct cfsrvl *srvl = container_of(kref, struct cfsrvl, ref); | 36 | struct cfsrvl *srvl = container_of(layer, struct cfsrvl, layer); |
37 | struct cfrfml *rfml = container_obj(&srvl->layer); | 37 | struct cfrfml *rfml = container_obj(&srvl->layer); |
38 | 38 | ||
39 | if (rfml->incomplete_frm) | 39 | if (rfml->incomplete_frm) |
diff --git a/net/caif/cfserl.c b/net/caif/cfserl.c index 8303fe3ebf89..2715c84cfa87 100644 --- a/net/caif/cfserl.c +++ b/net/caif/cfserl.c | |||
@@ -179,15 +179,10 @@ static int cfserl_receive(struct cflayer *l, struct cfpkt *newpkt) | |||
179 | static int cfserl_transmit(struct cflayer *layer, struct cfpkt *newpkt) | 179 | static int cfserl_transmit(struct cflayer *layer, struct cfpkt *newpkt) |
180 | { | 180 | { |
181 | struct cfserl *layr = container_obj(layer); | 181 | struct cfserl *layr = container_obj(layer); |
182 | int ret; | ||
183 | u8 tmp8 = CFSERL_STX; | 182 | u8 tmp8 = CFSERL_STX; |
184 | if (layr->usestx) | 183 | if (layr->usestx) |
185 | cfpkt_add_head(newpkt, &tmp8, 1); | 184 | cfpkt_add_head(newpkt, &tmp8, 1); |
186 | ret = layer->dn->transmit(layer->dn, newpkt); | 185 | return layer->dn->transmit(layer->dn, newpkt); |
187 | if (ret < 0) | ||
188 | cfpkt_extr_head(newpkt, &tmp8, 1); | ||
189 | |||
190 | return ret; | ||
191 | } | 186 | } |
192 | 187 | ||
193 | static void cfserl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, | 188 | static void cfserl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, |
diff --git a/net/caif/cfsrvl.c b/net/caif/cfsrvl.c index ab5e542526bf..535a1e72b366 100644 --- a/net/caif/cfsrvl.c +++ b/net/caif/cfsrvl.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/types.h> | 10 | #include <linux/types.h> |
11 | #include <linux/errno.h> | 11 | #include <linux/errno.h> |
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | #include <linux/module.h> | ||
13 | #include <net/caif/caif_layer.h> | 14 | #include <net/caif/caif_layer.h> |
14 | #include <net/caif/cfsrvl.h> | 15 | #include <net/caif/cfsrvl.h> |
15 | #include <net/caif/cfpkt.h> | 16 | #include <net/caif/cfpkt.h> |
@@ -27,8 +28,8 @@ static void cfservl_ctrlcmd(struct cflayer *layr, enum caif_ctrlcmd ctrl, | |||
27 | { | 28 | { |
28 | struct cfsrvl *service = container_obj(layr); | 29 | struct cfsrvl *service = container_obj(layr); |
29 | 30 | ||
30 | caif_assert(layr->up != NULL); | 31 | if (layr->up == NULL || layr->up->ctrlcmd == NULL) |
31 | caif_assert(layr->up->ctrlcmd != NULL); | 32 | return; |
32 | 33 | ||
33 | switch (ctrl) { | 34 | switch (ctrl) { |
34 | case CAIF_CTRLCMD_INIT_RSP: | 35 | case CAIF_CTRLCMD_INIT_RSP: |
@@ -151,14 +152,9 @@ static int cfservl_modemcmd(struct cflayer *layr, enum caif_modemcmd ctrl) | |||
151 | return -EINVAL; | 152 | return -EINVAL; |
152 | } | 153 | } |
153 | 154 | ||
154 | void cfservl_destroy(struct cflayer *layer) | 155 | static void cfsrvl_release(struct cflayer *layer) |
155 | { | 156 | { |
156 | kfree(layer); | 157 | struct cfsrvl *service = container_of(layer, struct cfsrvl, layer); |
157 | } | ||
158 | |||
159 | void cfsrvl_release(struct kref *kref) | ||
160 | { | ||
161 | struct cfsrvl *service = container_of(kref, struct cfsrvl, ref); | ||
162 | kfree(service); | 158 | kfree(service); |
163 | } | 159 | } |
164 | 160 | ||
@@ -178,10 +174,8 @@ void cfsrvl_init(struct cfsrvl *service, | |||
178 | service->dev_info = *dev_info; | 174 | service->dev_info = *dev_info; |
179 | service->supports_flowctrl = supports_flowctrl; | 175 | service->supports_flowctrl = supports_flowctrl; |
180 | service->release = cfsrvl_release; | 176 | service->release = cfsrvl_release; |
181 | kref_init(&service->ref); | ||
182 | } | 177 | } |
183 | 178 | ||
184 | |||
185 | bool cfsrvl_ready(struct cfsrvl *service, int *err) | 179 | bool cfsrvl_ready(struct cfsrvl *service, int *err) |
186 | { | 180 | { |
187 | if (service->open && service->modem_flow_on && service->phy_flow_on) | 181 | if (service->open && service->modem_flow_on && service->phy_flow_on) |
@@ -194,6 +188,7 @@ bool cfsrvl_ready(struct cfsrvl *service, int *err) | |||
194 | *err = -EAGAIN; | 188 | *err = -EAGAIN; |
195 | return false; | 189 | return false; |
196 | } | 190 | } |
191 | |||
197 | u8 cfsrvl_getphyid(struct cflayer *layer) | 192 | u8 cfsrvl_getphyid(struct cflayer *layer) |
198 | { | 193 | { |
199 | struct cfsrvl *servl = container_obj(layer); | 194 | struct cfsrvl *servl = container_obj(layer); |
@@ -205,3 +200,26 @@ bool cfsrvl_phyid_match(struct cflayer *layer, int phyid) | |||
205 | struct cfsrvl *servl = container_obj(layer); | 200 | struct cfsrvl *servl = container_obj(layer); |
206 | return servl->dev_info.id == phyid; | 201 | return servl->dev_info.id == phyid; |
207 | } | 202 | } |
203 | |||
204 | void caif_free_client(struct cflayer *adap_layer) | ||
205 | { | ||
206 | struct cfsrvl *servl; | ||
207 | if (adap_layer == NULL || adap_layer->dn == NULL) | ||
208 | return; | ||
209 | servl = container_obj(adap_layer->dn); | ||
210 | servl->release(&servl->layer); | ||
211 | } | ||
212 | EXPORT_SYMBOL(caif_free_client); | ||
213 | |||
214 | void caif_client_register_refcnt(struct cflayer *adapt_layer, | ||
215 | void (*hold)(struct cflayer *lyr), | ||
216 | void (*put)(struct cflayer *lyr)) | ||
217 | { | ||
218 | struct cfsrvl *service; | ||
219 | service = container_of(adapt_layer->dn, struct cfsrvl, layer); | ||
220 | |||
221 | WARN_ON(adapt_layer == NULL || adapt_layer->dn == NULL); | ||
222 | service->hold = hold; | ||
223 | service->put = put; | ||
224 | } | ||
225 | EXPORT_SYMBOL(caif_client_register_refcnt); | ||
diff --git a/net/caif/cfutill.c b/net/caif/cfutill.c index 315c0d601368..98e027db18ed 100644 --- a/net/caif/cfutill.c +++ b/net/caif/cfutill.c | |||
@@ -100,10 +100,5 @@ static int cfutill_transmit(struct cflayer *layr, struct cfpkt *pkt) | |||
100 | */ | 100 | */ |
101 | info->hdr_len = 1; | 101 | info->hdr_len = 1; |
102 | info->dev_info = &service->dev_info; | 102 | info->dev_info = &service->dev_info; |
103 | ret = layr->dn->transmit(layr->dn, pkt); | 103 | return layr->dn->transmit(layr->dn, pkt); |
104 | if (ret < 0) { | ||
105 | u32 tmp32; | ||
106 | cfpkt_extr_head(pkt, &tmp32, 4); | ||
107 | } | ||
108 | return ret; | ||
109 | } | 104 | } |
diff --git a/net/caif/cfveil.c b/net/caif/cfveil.c index c3b1dec4acf6..3ec83fbc2887 100644 --- a/net/caif/cfveil.c +++ b/net/caif/cfveil.c | |||
@@ -82,13 +82,14 @@ static int cfvei_transmit(struct cflayer *layr, struct cfpkt *pkt) | |||
82 | int ret; | 82 | int ret; |
83 | struct cfsrvl *service = container_obj(layr); | 83 | struct cfsrvl *service = container_obj(layr); |
84 | if (!cfsrvl_ready(service, &ret)) | 84 | if (!cfsrvl_ready(service, &ret)) |
85 | return ret; | 85 | goto err; |
86 | caif_assert(layr->dn != NULL); | 86 | caif_assert(layr->dn != NULL); |
87 | caif_assert(layr->dn->transmit != NULL); | 87 | caif_assert(layr->dn->transmit != NULL); |
88 | 88 | ||
89 | if (cfpkt_add_head(pkt, &tmp, 1) < 0) { | 89 | if (cfpkt_add_head(pkt, &tmp, 1) < 0) { |
90 | pr_err("Packet is erroneous!\n"); | 90 | pr_err("Packet is erroneous!\n"); |
91 | return -EPROTO; | 91 | ret = -EPROTO; |
92 | goto err; | ||
92 | } | 93 | } |
93 | 94 | ||
94 | /* Add info-> for MUX-layer to route the packet out. */ | 95 | /* Add info-> for MUX-layer to route the packet out. */ |
@@ -96,8 +97,8 @@ static int cfvei_transmit(struct cflayer *layr, struct cfpkt *pkt) | |||
96 | info->channel_id = service->layer.id; | 97 | info->channel_id = service->layer.id; |
97 | info->hdr_len = 1; | 98 | info->hdr_len = 1; |
98 | info->dev_info = &service->dev_info; | 99 | info->dev_info = &service->dev_info; |
99 | ret = layr->dn->transmit(layr->dn, pkt); | 100 | return layr->dn->transmit(layr->dn, pkt); |
100 | if (ret < 0) | 101 | err: |
101 | cfpkt_extr_head(pkt, &tmp, 1); | 102 | cfpkt_destroy(pkt); |
102 | return ret; | 103 | return ret; |
103 | } | 104 | } |
diff --git a/net/caif/cfvidl.c b/net/caif/cfvidl.c index bf6fef2a0eff..b2f5989ad455 100644 --- a/net/caif/cfvidl.c +++ b/net/caif/cfvidl.c | |||
@@ -60,8 +60,5 @@ static int cfvidl_transmit(struct cflayer *layr, struct cfpkt *pkt) | |||
60 | info = cfpkt_info(pkt); | 60 | info = cfpkt_info(pkt); |
61 | info->channel_id = service->layer.id; | 61 | info->channel_id = service->layer.id; |
62 | info->dev_info = &service->dev_info; | 62 | info->dev_info = &service->dev_info; |
63 | ret = layr->dn->transmit(layr->dn, pkt); | 63 | return layr->dn->transmit(layr->dn, pkt); |
64 | if (ret < 0) | ||
65 | cfpkt_extr_head(pkt, &videoheader, 4); | ||
66 | return ret; | ||
67 | } | 64 | } |
diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c index 6008d6dc18a0..649ebacaf6bc 100644 --- a/net/caif/chnl_net.c +++ b/net/caif/chnl_net.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include <linux/caif/if_caif.h> | 20 | #include <linux/caif/if_caif.h> |
21 | #include <net/rtnetlink.h> | 21 | #include <net/rtnetlink.h> |
22 | #include <net/caif/caif_layer.h> | 22 | #include <net/caif/caif_layer.h> |
23 | #include <net/caif/cfcnfg.h> | ||
24 | #include <net/caif/cfpkt.h> | 23 | #include <net/caif/cfpkt.h> |
25 | #include <net/caif/caif_dev.h> | 24 | #include <net/caif/caif_dev.h> |
26 | 25 | ||
@@ -84,10 +83,11 @@ static int chnl_recv_cb(struct cflayer *layr, struct cfpkt *pkt) | |||
84 | if (!priv) | 83 | if (!priv) |
85 | return -EINVAL; | 84 | return -EINVAL; |
86 | 85 | ||
86 | skb = (struct sk_buff *) cfpkt_tonative(pkt); | ||
87 | |||
87 | /* Get length of CAIF packet. */ | 88 | /* Get length of CAIF packet. */ |
88 | pktlen = cfpkt_getlen(pkt); | 89 | pktlen = skb->len; |
89 | 90 | ||
90 | skb = (struct sk_buff *) cfpkt_tonative(pkt); | ||
91 | /* Pass some minimum information and | 91 | /* Pass some minimum information and |
92 | * send the packet to the net stack. | 92 | * send the packet to the net stack. |
93 | */ | 93 | */ |
@@ -153,6 +153,18 @@ static void close_work(struct work_struct *work) | |||
153 | } | 153 | } |
154 | static DECLARE_WORK(close_worker, close_work); | 154 | static DECLARE_WORK(close_worker, close_work); |
155 | 155 | ||
156 | static void chnl_hold(struct cflayer *lyr) | ||
157 | { | ||
158 | struct chnl_net *priv = container_of(lyr, struct chnl_net, chnl); | ||
159 | dev_hold(priv->netdev); | ||
160 | } | ||
161 | |||
162 | static void chnl_put(struct cflayer *lyr) | ||
163 | { | ||
164 | struct chnl_net *priv = container_of(lyr, struct chnl_net, chnl); | ||
165 | dev_put(priv->netdev); | ||
166 | } | ||
167 | |||
156 | static void chnl_flowctrl_cb(struct cflayer *layr, enum caif_ctrlcmd flow, | 168 | static void chnl_flowctrl_cb(struct cflayer *layr, enum caif_ctrlcmd flow, |
157 | int phyid) | 169 | int phyid) |
158 | { | 170 | { |
@@ -190,6 +202,7 @@ static void chnl_flowctrl_cb(struct cflayer *layr, enum caif_ctrlcmd flow, | |||
190 | netif_wake_queue(priv->netdev); | 202 | netif_wake_queue(priv->netdev); |
191 | break; | 203 | break; |
192 | case CAIF_CTRLCMD_INIT_RSP: | 204 | case CAIF_CTRLCMD_INIT_RSP: |
205 | caif_client_register_refcnt(&priv->chnl, chnl_hold, chnl_put); | ||
193 | priv->state = CAIF_CONNECTED; | 206 | priv->state = CAIF_CONNECTED; |
194 | priv->flowenabled = true; | 207 | priv->flowenabled = true; |
195 | netif_wake_queue(priv->netdev); | 208 | netif_wake_queue(priv->netdev); |
@@ -257,8 +270,9 @@ static int chnl_net_open(struct net_device *dev) | |||
257 | 270 | ||
258 | if (priv->state != CAIF_CONNECTING) { | 271 | if (priv->state != CAIF_CONNECTING) { |
259 | priv->state = CAIF_CONNECTING; | 272 | priv->state = CAIF_CONNECTING; |
260 | result = caif_connect_client(&priv->conn_req, &priv->chnl, | 273 | result = caif_connect_client(dev_net(dev), &priv->conn_req, |
261 | &llifindex, &headroom, &tailroom); | 274 | &priv->chnl, &llifindex, |
275 | &headroom, &tailroom); | ||
262 | if (result != 0) { | 276 | if (result != 0) { |
263 | pr_debug("err: " | 277 | pr_debug("err: " |
264 | "Unable to register and open device," | 278 | "Unable to register and open device," |
@@ -314,7 +328,7 @@ static int chnl_net_open(struct net_device *dev) | |||
314 | 328 | ||
315 | if (result == 0) { | 329 | if (result == 0) { |
316 | pr_debug("connect timeout\n"); | 330 | pr_debug("connect timeout\n"); |
317 | caif_disconnect_client(&priv->chnl); | 331 | caif_disconnect_client(dev_net(dev), &priv->chnl); |
318 | priv->state = CAIF_DISCONNECTED; | 332 | priv->state = CAIF_DISCONNECTED; |
319 | pr_debug("state disconnected\n"); | 333 | pr_debug("state disconnected\n"); |
320 | result = -ETIMEDOUT; | 334 | result = -ETIMEDOUT; |
@@ -330,7 +344,7 @@ static int chnl_net_open(struct net_device *dev) | |||
330 | return 0; | 344 | return 0; |
331 | 345 | ||
332 | error: | 346 | error: |
333 | caif_disconnect_client(&priv->chnl); | 347 | caif_disconnect_client(dev_net(dev), &priv->chnl); |
334 | priv->state = CAIF_DISCONNECTED; | 348 | priv->state = CAIF_DISCONNECTED; |
335 | pr_debug("state disconnected\n"); | 349 | pr_debug("state disconnected\n"); |
336 | return result; | 350 | return result; |
@@ -344,7 +358,7 @@ static int chnl_net_stop(struct net_device *dev) | |||
344 | ASSERT_RTNL(); | 358 | ASSERT_RTNL(); |
345 | priv = netdev_priv(dev); | 359 | priv = netdev_priv(dev); |
346 | priv->state = CAIF_DISCONNECTED; | 360 | priv->state = CAIF_DISCONNECTED; |
347 | caif_disconnect_client(&priv->chnl); | 361 | caif_disconnect_client(dev_net(dev), &priv->chnl); |
348 | return 0; | 362 | return 0; |
349 | } | 363 | } |
350 | 364 | ||
@@ -373,11 +387,18 @@ static const struct net_device_ops netdev_ops = { | |||
373 | .ndo_start_xmit = chnl_net_start_xmit, | 387 | .ndo_start_xmit = chnl_net_start_xmit, |
374 | }; | 388 | }; |
375 | 389 | ||
390 | static void chnl_net_destructor(struct net_device *dev) | ||
391 | { | ||
392 | struct chnl_net *priv = netdev_priv(dev); | ||
393 | caif_free_client(&priv->chnl); | ||
394 | free_netdev(dev); | ||
395 | } | ||
396 | |||
376 | static void ipcaif_net_setup(struct net_device *dev) | 397 | static void ipcaif_net_setup(struct net_device *dev) |
377 | { | 398 | { |
378 | struct chnl_net *priv; | 399 | struct chnl_net *priv; |
379 | dev->netdev_ops = &netdev_ops; | 400 | dev->netdev_ops = &netdev_ops; |
380 | dev->destructor = free_netdev; | 401 | dev->destructor = chnl_net_destructor; |
381 | dev->flags |= IFF_NOARP; | 402 | dev->flags |= IFF_NOARP; |
382 | dev->flags |= IFF_POINTOPOINT; | 403 | dev->flags |= IFF_POINTOPOINT; |
383 | dev->mtu = GPRS_PDP_MTU; | 404 | dev->mtu = GPRS_PDP_MTU; |
@@ -391,7 +412,7 @@ static void ipcaif_net_setup(struct net_device *dev) | |||
391 | priv->conn_req.link_selector = CAIF_LINK_HIGH_BANDW; | 412 | priv->conn_req.link_selector = CAIF_LINK_HIGH_BANDW; |
392 | priv->conn_req.priority = CAIF_PRIO_LOW; | 413 | priv->conn_req.priority = CAIF_PRIO_LOW; |
393 | /* Insert illegal value */ | 414 | /* Insert illegal value */ |
394 | priv->conn_req.sockaddr.u.dgm.connection_id = -1; | 415 | priv->conn_req.sockaddr.u.dgm.connection_id = 0; |
395 | priv->flowenabled = false; | 416 | priv->flowenabled = false; |
396 | 417 | ||
397 | init_waitqueue_head(&priv->netmgmt_wq); | 418 | init_waitqueue_head(&priv->netmgmt_wq); |
@@ -453,6 +474,10 @@ static int ipcaif_newlink(struct net *src_net, struct net_device *dev, | |||
453 | pr_warn("device rtml registration failed\n"); | 474 | pr_warn("device rtml registration failed\n"); |
454 | else | 475 | else |
455 | list_add(&caifdev->list_field, &chnl_net_list); | 476 | list_add(&caifdev->list_field, &chnl_net_list); |
477 | |||
478 | /* Take ifindex as connection-id if null */ | ||
479 | if (caifdev->conn_req.sockaddr.u.dgm.connection_id == 0) | ||
480 | caifdev->conn_req.sockaddr.u.dgm.connection_id = dev->ifindex; | ||
456 | return ret; | 481 | return ret; |
457 | } | 482 | } |
458 | 483 | ||
diff --git a/net/can/af_can.c b/net/can/af_can.c index 733d66f1b05a..094fc5332d42 100644 --- a/net/can/af_can.c +++ b/net/can/af_can.c | |||
@@ -84,8 +84,8 @@ static DEFINE_SPINLOCK(can_rcvlists_lock); | |||
84 | static struct kmem_cache *rcv_cache __read_mostly; | 84 | static struct kmem_cache *rcv_cache __read_mostly; |
85 | 85 | ||
86 | /* table of registered CAN protocols */ | 86 | /* table of registered CAN protocols */ |
87 | static struct can_proto *proto_tab[CAN_NPROTO] __read_mostly; | 87 | static const struct can_proto *proto_tab[CAN_NPROTO] __read_mostly; |
88 | static DEFINE_SPINLOCK(proto_tab_lock); | 88 | static DEFINE_MUTEX(proto_tab_lock); |
89 | 89 | ||
90 | struct timer_list can_stattimer; /* timer for statistics update */ | 90 | struct timer_list can_stattimer; /* timer for statistics update */ |
91 | struct s_stats can_stats; /* packet statistics */ | 91 | struct s_stats can_stats; /* packet statistics */ |
@@ -115,11 +115,29 @@ static void can_sock_destruct(struct sock *sk) | |||
115 | skb_queue_purge(&sk->sk_receive_queue); | 115 | skb_queue_purge(&sk->sk_receive_queue); |
116 | } | 116 | } |
117 | 117 | ||
118 | static const struct can_proto *can_get_proto(int protocol) | ||
119 | { | ||
120 | const struct can_proto *cp; | ||
121 | |||
122 | rcu_read_lock(); | ||
123 | cp = rcu_dereference(proto_tab[protocol]); | ||
124 | if (cp && !try_module_get(cp->prot->owner)) | ||
125 | cp = NULL; | ||
126 | rcu_read_unlock(); | ||
127 | |||
128 | return cp; | ||
129 | } | ||
130 | |||
131 | static inline void can_put_proto(const struct can_proto *cp) | ||
132 | { | ||
133 | module_put(cp->prot->owner); | ||
134 | } | ||
135 | |||
118 | static int can_create(struct net *net, struct socket *sock, int protocol, | 136 | static int can_create(struct net *net, struct socket *sock, int protocol, |
119 | int kern) | 137 | int kern) |
120 | { | 138 | { |
121 | struct sock *sk; | 139 | struct sock *sk; |
122 | struct can_proto *cp; | 140 | const struct can_proto *cp; |
123 | int err = 0; | 141 | int err = 0; |
124 | 142 | ||
125 | sock->state = SS_UNCONNECTED; | 143 | sock->state = SS_UNCONNECTED; |
@@ -130,9 +148,12 @@ static int can_create(struct net *net, struct socket *sock, int protocol, | |||
130 | if (!net_eq(net, &init_net)) | 148 | if (!net_eq(net, &init_net)) |
131 | return -EAFNOSUPPORT; | 149 | return -EAFNOSUPPORT; |
132 | 150 | ||
151 | cp = can_get_proto(protocol); | ||
152 | |||
133 | #ifdef CONFIG_MODULES | 153 | #ifdef CONFIG_MODULES |
134 | /* try to load protocol module kernel is modular */ | 154 | if (!cp) { |
135 | if (!proto_tab[protocol]) { | 155 | /* try to load protocol module if kernel is modular */ |
156 | |||
136 | err = request_module("can-proto-%d", protocol); | 157 | err = request_module("can-proto-%d", protocol); |
137 | 158 | ||
138 | /* | 159 | /* |
@@ -143,22 +164,18 @@ static int can_create(struct net *net, struct socket *sock, int protocol, | |||
143 | if (err && printk_ratelimit()) | 164 | if (err && printk_ratelimit()) |
144 | printk(KERN_ERR "can: request_module " | 165 | printk(KERN_ERR "can: request_module " |
145 | "(can-proto-%d) failed.\n", protocol); | 166 | "(can-proto-%d) failed.\n", protocol); |
167 | |||
168 | cp = can_get_proto(protocol); | ||
146 | } | 169 | } |
147 | #endif | 170 | #endif |
148 | 171 | ||
149 | spin_lock(&proto_tab_lock); | ||
150 | cp = proto_tab[protocol]; | ||
151 | if (cp && !try_module_get(cp->prot->owner)) | ||
152 | cp = NULL; | ||
153 | spin_unlock(&proto_tab_lock); | ||
154 | |||
155 | /* check for available protocol and correct usage */ | 172 | /* check for available protocol and correct usage */ |
156 | 173 | ||
157 | if (!cp) | 174 | if (!cp) |
158 | return -EPROTONOSUPPORT; | 175 | return -EPROTONOSUPPORT; |
159 | 176 | ||
160 | if (cp->type != sock->type) { | 177 | if (cp->type != sock->type) { |
161 | err = -EPROTONOSUPPORT; | 178 | err = -EPROTOTYPE; |
162 | goto errout; | 179 | goto errout; |
163 | } | 180 | } |
164 | 181 | ||
@@ -183,7 +200,7 @@ static int can_create(struct net *net, struct socket *sock, int protocol, | |||
183 | } | 200 | } |
184 | 201 | ||
185 | errout: | 202 | errout: |
186 | module_put(cp->prot->owner); | 203 | can_put_proto(cp); |
187 | return err; | 204 | return err; |
188 | } | 205 | } |
189 | 206 | ||
@@ -679,7 +696,7 @@ drop: | |||
679 | * -EBUSY protocol already in use | 696 | * -EBUSY protocol already in use |
680 | * -ENOBUF if proto_register() fails | 697 | * -ENOBUF if proto_register() fails |
681 | */ | 698 | */ |
682 | int can_proto_register(struct can_proto *cp) | 699 | int can_proto_register(const struct can_proto *cp) |
683 | { | 700 | { |
684 | int proto = cp->protocol; | 701 | int proto = cp->protocol; |
685 | int err = 0; | 702 | int err = 0; |
@@ -694,15 +711,16 @@ int can_proto_register(struct can_proto *cp) | |||
694 | if (err < 0) | 711 | if (err < 0) |
695 | return err; | 712 | return err; |
696 | 713 | ||
697 | spin_lock(&proto_tab_lock); | 714 | mutex_lock(&proto_tab_lock); |
715 | |||
698 | if (proto_tab[proto]) { | 716 | if (proto_tab[proto]) { |
699 | printk(KERN_ERR "can: protocol %d already registered\n", | 717 | printk(KERN_ERR "can: protocol %d already registered\n", |
700 | proto); | 718 | proto); |
701 | err = -EBUSY; | 719 | err = -EBUSY; |
702 | } else | 720 | } else |
703 | proto_tab[proto] = cp; | 721 | rcu_assign_pointer(proto_tab[proto], cp); |
704 | 722 | ||
705 | spin_unlock(&proto_tab_lock); | 723 | mutex_unlock(&proto_tab_lock); |
706 | 724 | ||
707 | if (err < 0) | 725 | if (err < 0) |
708 | proto_unregister(cp->prot); | 726 | proto_unregister(cp->prot); |
@@ -715,17 +733,16 @@ EXPORT_SYMBOL(can_proto_register); | |||
715 | * can_proto_unregister - unregister CAN transport protocol | 733 | * can_proto_unregister - unregister CAN transport protocol |
716 | * @cp: pointer to CAN protocol structure | 734 | * @cp: pointer to CAN protocol structure |
717 | */ | 735 | */ |
718 | void can_proto_unregister(struct can_proto *cp) | 736 | void can_proto_unregister(const struct can_proto *cp) |
719 | { | 737 | { |
720 | int proto = cp->protocol; | 738 | int proto = cp->protocol; |
721 | 739 | ||
722 | spin_lock(&proto_tab_lock); | 740 | mutex_lock(&proto_tab_lock); |
723 | if (!proto_tab[proto]) { | 741 | BUG_ON(proto_tab[proto] != cp); |
724 | printk(KERN_ERR "BUG: can: protocol %d is not registered\n", | 742 | rcu_assign_pointer(proto_tab[proto], NULL); |
725 | proto); | 743 | mutex_unlock(&proto_tab_lock); |
726 | } | 744 | |
727 | proto_tab[proto] = NULL; | 745 | synchronize_rcu(); |
728 | spin_unlock(&proto_tab_lock); | ||
729 | 746 | ||
730 | proto_unregister(cp->prot); | 747 | proto_unregister(cp->prot); |
731 | } | 748 | } |
diff --git a/net/can/bcm.c b/net/can/bcm.c index 871a0ad51025..cced806098a9 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c | |||
@@ -387,7 +387,7 @@ static void bcm_tx_timeout_tsklet(unsigned long data) | |||
387 | } | 387 | } |
388 | 388 | ||
389 | /* | 389 | /* |
390 | * bcm_tx_timeout_handler - performes cyclic CAN frame transmissions | 390 | * bcm_tx_timeout_handler - performs cyclic CAN frame transmissions |
391 | */ | 391 | */ |
392 | static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer) | 392 | static enum hrtimer_restart bcm_tx_timeout_handler(struct hrtimer *hrtimer) |
393 | { | 393 | { |
@@ -1427,9 +1427,14 @@ static int bcm_init(struct sock *sk) | |||
1427 | static int bcm_release(struct socket *sock) | 1427 | static int bcm_release(struct socket *sock) |
1428 | { | 1428 | { |
1429 | struct sock *sk = sock->sk; | 1429 | struct sock *sk = sock->sk; |
1430 | struct bcm_sock *bo = bcm_sk(sk); | 1430 | struct bcm_sock *bo; |
1431 | struct bcm_op *op, *next; | 1431 | struct bcm_op *op, *next; |
1432 | 1432 | ||
1433 | if (sk == NULL) | ||
1434 | return 0; | ||
1435 | |||
1436 | bo = bcm_sk(sk); | ||
1437 | |||
1433 | /* remove bcm_ops, timer, rx_unregister(), etc. */ | 1438 | /* remove bcm_ops, timer, rx_unregister(), etc. */ |
1434 | 1439 | ||
1435 | unregister_netdevice_notifier(&bo->notifier); | 1440 | unregister_netdevice_notifier(&bo->notifier); |
@@ -1596,7 +1601,7 @@ static struct proto bcm_proto __read_mostly = { | |||
1596 | .init = bcm_init, | 1601 | .init = bcm_init, |
1597 | }; | 1602 | }; |
1598 | 1603 | ||
1599 | static struct can_proto bcm_can_proto __read_mostly = { | 1604 | static const struct can_proto bcm_can_proto = { |
1600 | .type = SOCK_DGRAM, | 1605 | .type = SOCK_DGRAM, |
1601 | .protocol = CAN_BCM, | 1606 | .protocol = CAN_BCM, |
1602 | .ops = &bcm_ops, | 1607 | .ops = &bcm_ops, |
diff --git a/net/can/raw.c b/net/can/raw.c index 649acfa7c70a..dea99a6e596c 100644 --- a/net/can/raw.c +++ b/net/can/raw.c | |||
@@ -305,7 +305,12 @@ static int raw_init(struct sock *sk) | |||
305 | static int raw_release(struct socket *sock) | 305 | static int raw_release(struct socket *sock) |
306 | { | 306 | { |
307 | struct sock *sk = sock->sk; | 307 | struct sock *sk = sock->sk; |
308 | struct raw_sock *ro = raw_sk(sk); | 308 | struct raw_sock *ro; |
309 | |||
310 | if (!sk) | ||
311 | return 0; | ||
312 | |||
313 | ro = raw_sk(sk); | ||
309 | 314 | ||
310 | unregister_netdevice_notifier(&ro->notifier); | 315 | unregister_netdevice_notifier(&ro->notifier); |
311 | 316 | ||
@@ -769,7 +774,7 @@ static struct proto raw_proto __read_mostly = { | |||
769 | .init = raw_init, | 774 | .init = raw_init, |
770 | }; | 775 | }; |
771 | 776 | ||
772 | static struct can_proto raw_can_proto __read_mostly = { | 777 | static const struct can_proto raw_can_proto = { |
773 | .type = SOCK_RAW, | 778 | .type = SOCK_RAW, |
774 | .protocol = CAN_RAW, | 779 | .protocol = CAN_RAW, |
775 | .ops = &raw_ops, | 780 | .ops = &raw_ops, |
diff --git a/net/ceph/Kconfig b/net/ceph/Kconfig index ad424049b0cf..be683f2d401f 100644 --- a/net/ceph/Kconfig +++ b/net/ceph/Kconfig | |||
@@ -4,6 +4,7 @@ config CEPH_LIB | |||
4 | select LIBCRC32C | 4 | select LIBCRC32C |
5 | select CRYPTO_AES | 5 | select CRYPTO_AES |
6 | select CRYPTO | 6 | select CRYPTO |
7 | select KEYS | ||
7 | default n | 8 | default n |
8 | help | 9 | help |
9 | Choose Y or M here to include cephlib, which provides the | 10 | Choose Y or M here to include cephlib, which provides the |
diff --git a/net/ceph/auth.c b/net/ceph/auth.c index 549c1f43e1d5..b4bf4ac090f1 100644 --- a/net/ceph/auth.c +++ b/net/ceph/auth.c | |||
@@ -35,12 +35,12 @@ static int ceph_auth_init_protocol(struct ceph_auth_client *ac, int protocol) | |||
35 | /* | 35 | /* |
36 | * setup, teardown. | 36 | * setup, teardown. |
37 | */ | 37 | */ |
38 | struct ceph_auth_client *ceph_auth_init(const char *name, const char *secret) | 38 | struct ceph_auth_client *ceph_auth_init(const char *name, const struct ceph_crypto_key *key) |
39 | { | 39 | { |
40 | struct ceph_auth_client *ac; | 40 | struct ceph_auth_client *ac; |
41 | int ret; | 41 | int ret; |
42 | 42 | ||
43 | dout("auth_init name '%s' secret '%s'\n", name, secret); | 43 | dout("auth_init name '%s'\n", name); |
44 | 44 | ||
45 | ret = -ENOMEM; | 45 | ret = -ENOMEM; |
46 | ac = kzalloc(sizeof(*ac), GFP_NOFS); | 46 | ac = kzalloc(sizeof(*ac), GFP_NOFS); |
@@ -52,8 +52,8 @@ struct ceph_auth_client *ceph_auth_init(const char *name, const char *secret) | |||
52 | ac->name = name; | 52 | ac->name = name; |
53 | else | 53 | else |
54 | ac->name = CEPH_AUTH_NAME_DEFAULT; | 54 | ac->name = CEPH_AUTH_NAME_DEFAULT; |
55 | dout("auth_init name %s secret %s\n", ac->name, secret); | 55 | dout("auth_init name %s\n", ac->name); |
56 | ac->secret = secret; | 56 | ac->key = key; |
57 | return ac; | 57 | return ac; |
58 | 58 | ||
59 | out: | 59 | out: |
diff --git a/net/ceph/auth_x.c b/net/ceph/auth_x.c index 7fd5dfcf6e18..1587dc6010c6 100644 --- a/net/ceph/auth_x.c +++ b/net/ceph/auth_x.c | |||
@@ -662,14 +662,16 @@ int ceph_x_init(struct ceph_auth_client *ac) | |||
662 | goto out; | 662 | goto out; |
663 | 663 | ||
664 | ret = -EINVAL; | 664 | ret = -EINVAL; |
665 | if (!ac->secret) { | 665 | if (!ac->key) { |
666 | pr_err("no secret set (for auth_x protocol)\n"); | 666 | pr_err("no secret set (for auth_x protocol)\n"); |
667 | goto out_nomem; | 667 | goto out_nomem; |
668 | } | 668 | } |
669 | 669 | ||
670 | ret = ceph_crypto_key_unarmor(&xi->secret, ac->secret); | 670 | ret = ceph_crypto_key_clone(&xi->secret, ac->key); |
671 | if (ret) | 671 | if (ret < 0) { |
672 | pr_err("cannot clone key: %d\n", ret); | ||
672 | goto out_nomem; | 673 | goto out_nomem; |
674 | } | ||
673 | 675 | ||
674 | xi->starting = true; | 676 | xi->starting = true; |
675 | xi->ticket_handlers = RB_ROOT; | 677 | xi->ticket_handlers = RB_ROOT; |
diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index 95f96ab94bba..132963abc266 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c | |||
@@ -5,6 +5,8 @@ | |||
5 | #include <linux/fs.h> | 5 | #include <linux/fs.h> |
6 | #include <linux/inet.h> | 6 | #include <linux/inet.h> |
7 | #include <linux/in6.h> | 7 | #include <linux/in6.h> |
8 | #include <linux/key.h> | ||
9 | #include <keys/ceph-type.h> | ||
8 | #include <linux/module.h> | 10 | #include <linux/module.h> |
9 | #include <linux/mount.h> | 11 | #include <linux/mount.h> |
10 | #include <linux/parser.h> | 12 | #include <linux/parser.h> |
@@ -20,6 +22,7 @@ | |||
20 | #include <linux/ceph/decode.h> | 22 | #include <linux/ceph/decode.h> |
21 | #include <linux/ceph/mon_client.h> | 23 | #include <linux/ceph/mon_client.h> |
22 | #include <linux/ceph/auth.h> | 24 | #include <linux/ceph/auth.h> |
25 | #include "crypto.h" | ||
23 | 26 | ||
24 | 27 | ||
25 | 28 | ||
@@ -117,9 +120,29 @@ int ceph_compare_options(struct ceph_options *new_opt, | |||
117 | if (ret) | 120 | if (ret) |
118 | return ret; | 121 | return ret; |
119 | 122 | ||
120 | ret = strcmp_null(opt1->secret, opt2->secret); | 123 | if (opt1->key && !opt2->key) |
121 | if (ret) | 124 | return -1; |
122 | return ret; | 125 | if (!opt1->key && opt2->key) |
126 | return 1; | ||
127 | if (opt1->key && opt2->key) { | ||
128 | if (opt1->key->type != opt2->key->type) | ||
129 | return -1; | ||
130 | if (opt1->key->created.tv_sec != opt2->key->created.tv_sec) | ||
131 | return -1; | ||
132 | if (opt1->key->created.tv_nsec != opt2->key->created.tv_nsec) | ||
133 | return -1; | ||
134 | if (opt1->key->len != opt2->key->len) | ||
135 | return -1; | ||
136 | if (opt1->key->key && !opt2->key->key) | ||
137 | return -1; | ||
138 | if (!opt1->key->key && opt2->key->key) | ||
139 | return 1; | ||
140 | if (opt1->key->key && opt2->key->key) { | ||
141 | ret = memcmp(opt1->key->key, opt2->key->key, opt1->key->len); | ||
142 | if (ret) | ||
143 | return ret; | ||
144 | } | ||
145 | } | ||
123 | 146 | ||
124 | /* any matching mon ip implies a match */ | 147 | /* any matching mon ip implies a match */ |
125 | for (i = 0; i < opt1->num_mon; i++) { | 148 | for (i = 0; i < opt1->num_mon; i++) { |
@@ -176,6 +199,7 @@ enum { | |||
176 | Opt_fsid, | 199 | Opt_fsid, |
177 | Opt_name, | 200 | Opt_name, |
178 | Opt_secret, | 201 | Opt_secret, |
202 | Opt_key, | ||
179 | Opt_ip, | 203 | Opt_ip, |
180 | Opt_last_string, | 204 | Opt_last_string, |
181 | /* string args above */ | 205 | /* string args above */ |
@@ -192,6 +216,7 @@ static match_table_t opt_tokens = { | |||
192 | {Opt_fsid, "fsid=%s"}, | 216 | {Opt_fsid, "fsid=%s"}, |
193 | {Opt_name, "name=%s"}, | 217 | {Opt_name, "name=%s"}, |
194 | {Opt_secret, "secret=%s"}, | 218 | {Opt_secret, "secret=%s"}, |
219 | {Opt_key, "key=%s"}, | ||
195 | {Opt_ip, "ip=%s"}, | 220 | {Opt_ip, "ip=%s"}, |
196 | /* string args above */ | 221 | /* string args above */ |
197 | {Opt_noshare, "noshare"}, | 222 | {Opt_noshare, "noshare"}, |
@@ -203,11 +228,56 @@ void ceph_destroy_options(struct ceph_options *opt) | |||
203 | { | 228 | { |
204 | dout("destroy_options %p\n", opt); | 229 | dout("destroy_options %p\n", opt); |
205 | kfree(opt->name); | 230 | kfree(opt->name); |
206 | kfree(opt->secret); | 231 | if (opt->key) { |
232 | ceph_crypto_key_destroy(opt->key); | ||
233 | kfree(opt->key); | ||
234 | } | ||
207 | kfree(opt); | 235 | kfree(opt); |
208 | } | 236 | } |
209 | EXPORT_SYMBOL(ceph_destroy_options); | 237 | EXPORT_SYMBOL(ceph_destroy_options); |
210 | 238 | ||
239 | /* get secret from key store */ | ||
240 | static int get_secret(struct ceph_crypto_key *dst, const char *name) { | ||
241 | struct key *ukey; | ||
242 | int key_err; | ||
243 | int err = 0; | ||
244 | struct ceph_crypto_key *ckey; | ||
245 | |||
246 | ukey = request_key(&key_type_ceph, name, NULL); | ||
247 | if (!ukey || IS_ERR(ukey)) { | ||
248 | /* request_key errors don't map nicely to mount(2) | ||
249 | errors; don't even try, but still printk */ | ||
250 | key_err = PTR_ERR(ukey); | ||
251 | switch (key_err) { | ||
252 | case -ENOKEY: | ||
253 | pr_warning("ceph: Mount failed due to key not found: %s\n", name); | ||
254 | break; | ||
255 | case -EKEYEXPIRED: | ||
256 | pr_warning("ceph: Mount failed due to expired key: %s\n", name); | ||
257 | break; | ||
258 | case -EKEYREVOKED: | ||
259 | pr_warning("ceph: Mount failed due to revoked key: %s\n", name); | ||
260 | break; | ||
261 | default: | ||
262 | pr_warning("ceph: Mount failed due to unknown key error" | ||
263 | " %d: %s\n", key_err, name); | ||
264 | } | ||
265 | err = -EPERM; | ||
266 | goto out; | ||
267 | } | ||
268 | |||
269 | ckey = ukey->payload.data; | ||
270 | err = ceph_crypto_key_clone(dst, ckey); | ||
271 | if (err) | ||
272 | goto out_key; | ||
273 | /* pass through, err is 0 */ | ||
274 | |||
275 | out_key: | ||
276 | key_put(ukey); | ||
277 | out: | ||
278 | return err; | ||
279 | } | ||
280 | |||
211 | int ceph_parse_options(struct ceph_options **popt, char *options, | 281 | int ceph_parse_options(struct ceph_options **popt, char *options, |
212 | const char *dev_name, const char *dev_name_end, | 282 | const char *dev_name, const char *dev_name_end, |
213 | int (*parse_extra_token)(char *c, void *private), | 283 | int (*parse_extra_token)(char *c, void *private), |
@@ -295,9 +365,24 @@ int ceph_parse_options(struct ceph_options **popt, char *options, | |||
295 | GFP_KERNEL); | 365 | GFP_KERNEL); |
296 | break; | 366 | break; |
297 | case Opt_secret: | 367 | case Opt_secret: |
298 | opt->secret = kstrndup(argstr[0].from, | 368 | opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL); |
299 | argstr[0].to-argstr[0].from, | 369 | if (!opt->key) { |
300 | GFP_KERNEL); | 370 | err = -ENOMEM; |
371 | goto out; | ||
372 | } | ||
373 | err = ceph_crypto_key_unarmor(opt->key, argstr[0].from); | ||
374 | if (err < 0) | ||
375 | goto out; | ||
376 | break; | ||
377 | case Opt_key: | ||
378 | opt->key = kzalloc(sizeof(*opt->key), GFP_KERNEL); | ||
379 | if (!opt->key) { | ||
380 | err = -ENOMEM; | ||
381 | goto out; | ||
382 | } | ||
383 | err = get_secret(opt->key, argstr[0].from); | ||
384 | if (err < 0) | ||
385 | goto out; | ||
301 | break; | 386 | break; |
302 | 387 | ||
303 | /* misc */ | 388 | /* misc */ |
@@ -394,8 +479,8 @@ void ceph_destroy_client(struct ceph_client *client) | |||
394 | ceph_osdc_stop(&client->osdc); | 479 | ceph_osdc_stop(&client->osdc); |
395 | 480 | ||
396 | /* | 481 | /* |
397 | * make sure mds and osd connections close out before destroying | 482 | * make sure osd connections close out before destroying the |
398 | * the auth module, which is needed to free those connections' | 483 | * auth module, which is needed to free those connections' |
399 | * ceph_authorizers. | 484 | * ceph_authorizers. |
400 | */ | 485 | */ |
401 | ceph_msgr_flush(); | 486 | ceph_msgr_flush(); |
@@ -496,10 +581,14 @@ static int __init init_ceph_lib(void) | |||
496 | if (ret < 0) | 581 | if (ret < 0) |
497 | goto out; | 582 | goto out; |
498 | 583 | ||
499 | ret = ceph_msgr_init(); | 584 | ret = ceph_crypto_init(); |
500 | if (ret < 0) | 585 | if (ret < 0) |
501 | goto out_debugfs; | 586 | goto out_debugfs; |
502 | 587 | ||
588 | ret = ceph_msgr_init(); | ||
589 | if (ret < 0) | ||
590 | goto out_crypto; | ||
591 | |||
503 | pr_info("loaded (mon/osd proto %d/%d, osdmap %d/%d %d/%d)\n", | 592 | pr_info("loaded (mon/osd proto %d/%d, osdmap %d/%d %d/%d)\n", |
504 | CEPH_MONC_PROTOCOL, CEPH_OSDC_PROTOCOL, | 593 | CEPH_MONC_PROTOCOL, CEPH_OSDC_PROTOCOL, |
505 | CEPH_OSDMAP_VERSION, CEPH_OSDMAP_VERSION_EXT, | 594 | CEPH_OSDMAP_VERSION, CEPH_OSDMAP_VERSION_EXT, |
@@ -507,6 +596,8 @@ static int __init init_ceph_lib(void) | |||
507 | 596 | ||
508 | return 0; | 597 | return 0; |
509 | 598 | ||
599 | out_crypto: | ||
600 | ceph_crypto_shutdown(); | ||
510 | out_debugfs: | 601 | out_debugfs: |
511 | ceph_debugfs_cleanup(); | 602 | ceph_debugfs_cleanup(); |
512 | out: | 603 | out: |
@@ -517,6 +608,7 @@ static void __exit exit_ceph_lib(void) | |||
517 | { | 608 | { |
518 | dout("exit_ceph_lib\n"); | 609 | dout("exit_ceph_lib\n"); |
519 | ceph_msgr_exit(); | 610 | ceph_msgr_exit(); |
611 | ceph_crypto_shutdown(); | ||
520 | ceph_debugfs_cleanup(); | 612 | ceph_debugfs_cleanup(); |
521 | } | 613 | } |
522 | 614 | ||
diff --git a/net/ceph/crypto.c b/net/ceph/crypto.c index 7b505b0c983f..5a8009c9e0cd 100644 --- a/net/ceph/crypto.c +++ b/net/ceph/crypto.c | |||
@@ -5,10 +5,23 @@ | |||
5 | #include <linux/scatterlist.h> | 5 | #include <linux/scatterlist.h> |
6 | #include <linux/slab.h> | 6 | #include <linux/slab.h> |
7 | #include <crypto/hash.h> | 7 | #include <crypto/hash.h> |
8 | #include <linux/key-type.h> | ||
8 | 9 | ||
10 | #include <keys/ceph-type.h> | ||
9 | #include <linux/ceph/decode.h> | 11 | #include <linux/ceph/decode.h> |
10 | #include "crypto.h" | 12 | #include "crypto.h" |
11 | 13 | ||
14 | int ceph_crypto_key_clone(struct ceph_crypto_key *dst, | ||
15 | const struct ceph_crypto_key *src) | ||
16 | { | ||
17 | memcpy(dst, src, sizeof(struct ceph_crypto_key)); | ||
18 | dst->key = kmalloc(src->len, GFP_NOFS); | ||
19 | if (!dst->key) | ||
20 | return -ENOMEM; | ||
21 | memcpy(dst->key, src->key, src->len); | ||
22 | return 0; | ||
23 | } | ||
24 | |||
12 | int ceph_crypto_key_encode(struct ceph_crypto_key *key, void **p, void *end) | 25 | int ceph_crypto_key_encode(struct ceph_crypto_key *key, void **p, void *end) |
13 | { | 26 | { |
14 | if (*p + sizeof(u16) + sizeof(key->created) + | 27 | if (*p + sizeof(u16) + sizeof(key->created) + |
@@ -410,3 +423,63 @@ int ceph_encrypt2(struct ceph_crypto_key *secret, void *dst, size_t *dst_len, | |||
410 | return -EINVAL; | 423 | return -EINVAL; |
411 | } | 424 | } |
412 | } | 425 | } |
426 | |||
427 | int ceph_key_instantiate(struct key *key, const void *data, size_t datalen) | ||
428 | { | ||
429 | struct ceph_crypto_key *ckey; | ||
430 | int ret; | ||
431 | void *p; | ||
432 | |||
433 | ret = -EINVAL; | ||
434 | if (datalen <= 0 || datalen > 32767 || !data) | ||
435 | goto err; | ||
436 | |||
437 | ret = key_payload_reserve(key, datalen); | ||
438 | if (ret < 0) | ||
439 | goto err; | ||
440 | |||
441 | ret = -ENOMEM; | ||
442 | ckey = kmalloc(sizeof(*ckey), GFP_KERNEL); | ||
443 | if (!ckey) | ||
444 | goto err; | ||
445 | |||
446 | /* TODO ceph_crypto_key_decode should really take const input */ | ||
447 | p = (void*)data; | ||
448 | ret = ceph_crypto_key_decode(ckey, &p, (char*)data+datalen); | ||
449 | if (ret < 0) | ||
450 | goto err_ckey; | ||
451 | |||
452 | key->payload.data = ckey; | ||
453 | return 0; | ||
454 | |||
455 | err_ckey: | ||
456 | kfree(ckey); | ||
457 | err: | ||
458 | return ret; | ||
459 | } | ||
460 | |||
461 | int ceph_key_match(const struct key *key, const void *description) | ||
462 | { | ||
463 | return strcmp(key->description, description) == 0; | ||
464 | } | ||
465 | |||
466 | void ceph_key_destroy(struct key *key) { | ||
467 | struct ceph_crypto_key *ckey = key->payload.data; | ||
468 | |||
469 | ceph_crypto_key_destroy(ckey); | ||
470 | } | ||
471 | |||
472 | struct key_type key_type_ceph = { | ||
473 | .name = "ceph", | ||
474 | .instantiate = ceph_key_instantiate, | ||
475 | .match = ceph_key_match, | ||
476 | .destroy = ceph_key_destroy, | ||
477 | }; | ||
478 | |||
479 | int ceph_crypto_init(void) { | ||
480 | return register_key_type(&key_type_ceph); | ||
481 | } | ||
482 | |||
483 | void ceph_crypto_shutdown(void) { | ||
484 | unregister_key_type(&key_type_ceph); | ||
485 | } | ||
diff --git a/net/ceph/crypto.h b/net/ceph/crypto.h index f9eccace592b..1919d1550d75 100644 --- a/net/ceph/crypto.h +++ b/net/ceph/crypto.h | |||
@@ -19,6 +19,8 @@ static inline void ceph_crypto_key_destroy(struct ceph_crypto_key *key) | |||
19 | kfree(key->key); | 19 | kfree(key->key); |
20 | } | 20 | } |
21 | 21 | ||
22 | extern int ceph_crypto_key_clone(struct ceph_crypto_key *dst, | ||
23 | const struct ceph_crypto_key *src); | ||
22 | extern int ceph_crypto_key_encode(struct ceph_crypto_key *key, | 24 | extern int ceph_crypto_key_encode(struct ceph_crypto_key *key, |
23 | void **p, void *end); | 25 | void **p, void *end); |
24 | extern int ceph_crypto_key_decode(struct ceph_crypto_key *key, | 26 | extern int ceph_crypto_key_decode(struct ceph_crypto_key *key, |
@@ -40,6 +42,8 @@ extern int ceph_encrypt2(struct ceph_crypto_key *secret, | |||
40 | void *dst, size_t *dst_len, | 42 | void *dst, size_t *dst_len, |
41 | const void *src1, size_t src1_len, | 43 | const void *src1, size_t src1_len, |
42 | const void *src2, size_t src2_len); | 44 | const void *src2, size_t src2_len); |
45 | extern int ceph_crypto_init(void); | ||
46 | extern void ceph_crypto_shutdown(void); | ||
43 | 47 | ||
44 | /* armor.c */ | 48 | /* armor.c */ |
45 | extern int ceph_armor(char *dst, const char *src, const char *end); | 49 | extern int ceph_armor(char *dst, const char *src, const char *end); |
diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 8a079399174a..cbe31fa45508 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c | |||
@@ -759,7 +759,7 @@ int ceph_monc_init(struct ceph_mon_client *monc, struct ceph_client *cl) | |||
759 | 759 | ||
760 | /* authentication */ | 760 | /* authentication */ |
761 | monc->auth = ceph_auth_init(cl->options->name, | 761 | monc->auth = ceph_auth_init(cl->options->name, |
762 | cl->options->secret); | 762 | cl->options->key); |
763 | if (IS_ERR(monc->auth)) | 763 | if (IS_ERR(monc->auth)) |
764 | return PTR_ERR(monc->auth); | 764 | return PTR_ERR(monc->auth); |
765 | monc->auth->want_keys = | 765 | monc->auth->want_keys = |
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 02212ed50852..50af02737a3d 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c | |||
@@ -837,8 +837,7 @@ static void __unregister_request(struct ceph_osd_client *osdc, | |||
837 | dout("moving osd to %p lru\n", req->r_osd); | 837 | dout("moving osd to %p lru\n", req->r_osd); |
838 | __move_osd_to_lru(osdc, req->r_osd); | 838 | __move_osd_to_lru(osdc, req->r_osd); |
839 | } | 839 | } |
840 | if (list_empty(&req->r_osd_item) && | 840 | if (list_empty(&req->r_linger_item)) |
841 | list_empty(&req->r_linger_item)) | ||
842 | req->r_osd = NULL; | 841 | req->r_osd = NULL; |
843 | } | 842 | } |
844 | 843 | ||
@@ -883,7 +882,8 @@ static void __unregister_linger_request(struct ceph_osd_client *osdc, | |||
883 | dout("moving osd to %p lru\n", req->r_osd); | 882 | dout("moving osd to %p lru\n", req->r_osd); |
884 | __move_osd_to_lru(osdc, req->r_osd); | 883 | __move_osd_to_lru(osdc, req->r_osd); |
885 | } | 884 | } |
886 | req->r_osd = NULL; | 885 | if (list_empty(&req->r_osd_item)) |
886 | req->r_osd = NULL; | ||
887 | } | 887 | } |
888 | } | 888 | } |
889 | 889 | ||
@@ -917,7 +917,7 @@ EXPORT_SYMBOL(ceph_osdc_set_request_linger); | |||
917 | /* | 917 | /* |
918 | * Pick an osd (the first 'up' osd in the pg), allocate the osd struct | 918 | * Pick an osd (the first 'up' osd in the pg), allocate the osd struct |
919 | * (as needed), and set the request r_osd appropriately. If there is | 919 | * (as needed), and set the request r_osd appropriately. If there is |
920 | * no up osd, set r_osd to NULL. Move the request to the appropiate list | 920 | * no up osd, set r_osd to NULL. Move the request to the appropriate list |
921 | * (unsent, homeless) or leave on in-flight lru. | 921 | * (unsent, homeless) or leave on in-flight lru. |
922 | * | 922 | * |
923 | * Return 0 if unchanged, 1 if changed, or negative on error. | 923 | * Return 0 if unchanged, 1 if changed, or negative on error. |
@@ -1602,11 +1602,11 @@ void handle_watch_notify(struct ceph_osd_client *osdc, struct ceph_msg *msg) | |||
1602 | cookie, ver, event); | 1602 | cookie, ver, event); |
1603 | if (event) { | 1603 | if (event) { |
1604 | event_work = kmalloc(sizeof(*event_work), GFP_NOIO); | 1604 | event_work = kmalloc(sizeof(*event_work), GFP_NOIO); |
1605 | INIT_WORK(&event_work->work, do_event_work); | ||
1606 | if (!event_work) { | 1605 | if (!event_work) { |
1607 | dout("ERROR: could not allocate event_work\n"); | 1606 | dout("ERROR: could not allocate event_work\n"); |
1608 | goto done_err; | 1607 | goto done_err; |
1609 | } | 1608 | } |
1609 | INIT_WORK(&event_work->work, do_event_work); | ||
1610 | event_work->event = event; | 1610 | event_work->event = event; |
1611 | event_work->ver = ver; | 1611 | event_work->ver = ver; |
1612 | event_work->notify_id = notify_id; | 1612 | event_work->notify_id = notify_id; |
@@ -1672,7 +1672,7 @@ int ceph_osdc_start_request(struct ceph_osd_client *osdc, | |||
1672 | if (req->r_sent == 0) { | 1672 | if (req->r_sent == 0) { |
1673 | rc = __map_request(osdc, req); | 1673 | rc = __map_request(osdc, req); |
1674 | if (rc < 0) | 1674 | if (rc < 0) |
1675 | return rc; | 1675 | goto out_unlock; |
1676 | if (req->r_osd == NULL) { | 1676 | if (req->r_osd == NULL) { |
1677 | dout("send_request %p no up osds in pg\n", req); | 1677 | dout("send_request %p no up osds in pg\n", req); |
1678 | ceph_monc_request_next_osdmap(&osdc->client->monc); | 1678 | ceph_monc_request_next_osdmap(&osdc->client->monc); |
@@ -1689,6 +1689,8 @@ int ceph_osdc_start_request(struct ceph_osd_client *osdc, | |||
1689 | } | 1689 | } |
1690 | } | 1690 | } |
1691 | } | 1691 | } |
1692 | |||
1693 | out_unlock: | ||
1692 | mutex_unlock(&osdc->request_mutex); | 1694 | mutex_unlock(&osdc->request_mutex); |
1693 | up_read(&osdc->map_sem); | 1695 | up_read(&osdc->map_sem); |
1694 | return rc; | 1696 | return rc; |
diff --git a/net/compat.c b/net/compat.c index 3649d5895361..c578d9382e19 100644 --- a/net/compat.c +++ b/net/compat.c | |||
@@ -722,11 +722,11 @@ EXPORT_SYMBOL(compat_mc_getsockopt); | |||
722 | 722 | ||
723 | /* Argument list sizes for compat_sys_socketcall */ | 723 | /* Argument list sizes for compat_sys_socketcall */ |
724 | #define AL(x) ((x) * sizeof(u32)) | 724 | #define AL(x) ((x) * sizeof(u32)) |
725 | static unsigned char nas[20] = { | 725 | static unsigned char nas[21] = { |
726 | AL(0), AL(3), AL(3), AL(3), AL(2), AL(3), | 726 | AL(0), AL(3), AL(3), AL(3), AL(2), AL(3), |
727 | AL(3), AL(3), AL(4), AL(4), AL(4), AL(6), | 727 | AL(3), AL(3), AL(4), AL(4), AL(4), AL(6), |
728 | AL(6), AL(2), AL(5), AL(5), AL(3), AL(3), | 728 | AL(6), AL(2), AL(5), AL(5), AL(3), AL(3), |
729 | AL(4), AL(5) | 729 | AL(4), AL(5), AL(4) |
730 | }; | 730 | }; |
731 | #undef AL | 731 | #undef AL |
732 | 732 | ||
@@ -735,6 +735,13 @@ asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, uns | |||
735 | return sys_sendmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); | 735 | return sys_sendmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); |
736 | } | 736 | } |
737 | 737 | ||
738 | asmlinkage long compat_sys_sendmmsg(int fd, struct compat_mmsghdr __user *mmsg, | ||
739 | unsigned vlen, unsigned int flags) | ||
740 | { | ||
741 | return __sys_sendmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, | ||
742 | flags | MSG_CMSG_COMPAT); | ||
743 | } | ||
744 | |||
738 | asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags) | 745 | asmlinkage long compat_sys_recvmsg(int fd, struct compat_msghdr __user *msg, unsigned int flags) |
739 | { | 746 | { |
740 | return sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); | 747 | return sys_recvmsg(fd, (struct msghdr __user *)msg, flags | MSG_CMSG_COMPAT); |
@@ -780,7 +787,7 @@ asmlinkage long compat_sys_socketcall(int call, u32 __user *args) | |||
780 | u32 a[6]; | 787 | u32 a[6]; |
781 | u32 a0, a1; | 788 | u32 a0, a1; |
782 | 789 | ||
783 | if (call < SYS_SOCKET || call > SYS_RECVMMSG) | 790 | if (call < SYS_SOCKET || call > SYS_SENDMMSG) |
784 | return -EINVAL; | 791 | return -EINVAL; |
785 | if (copy_from_user(a, args, nas[call])) | 792 | if (copy_from_user(a, args, nas[call])) |
786 | return -EFAULT; | 793 | return -EFAULT; |
@@ -839,6 +846,9 @@ asmlinkage long compat_sys_socketcall(int call, u32 __user *args) | |||
839 | case SYS_SENDMSG: | 846 | case SYS_SENDMSG: |
840 | ret = compat_sys_sendmsg(a0, compat_ptr(a1), a[2]); | 847 | ret = compat_sys_sendmsg(a0, compat_ptr(a1), a[2]); |
841 | break; | 848 | break; |
849 | case SYS_SENDMMSG: | ||
850 | ret = compat_sys_sendmmsg(a0, compat_ptr(a1), a[2], a[3]); | ||
851 | break; | ||
842 | case SYS_RECVMSG: | 852 | case SYS_RECVMSG: |
843 | ret = compat_sys_recvmsg(a0, compat_ptr(a1), a[2]); | 853 | ret = compat_sys_recvmsg(a0, compat_ptr(a1), a[2]); |
844 | break; | 854 | break; |
diff --git a/net/core/dev.c b/net/core/dev.c index 3da9fb06d47a..3ed09f8ecbf8 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -948,7 +948,7 @@ int dev_alloc_name(struct net_device *dev, const char *name) | |||
948 | } | 948 | } |
949 | EXPORT_SYMBOL(dev_alloc_name); | 949 | EXPORT_SYMBOL(dev_alloc_name); |
950 | 950 | ||
951 | static int dev_get_valid_name(struct net_device *dev, const char *name, bool fmt) | 951 | static int dev_get_valid_name(struct net_device *dev, const char *name) |
952 | { | 952 | { |
953 | struct net *net; | 953 | struct net *net; |
954 | 954 | ||
@@ -958,7 +958,7 @@ static int dev_get_valid_name(struct net_device *dev, const char *name, bool fmt | |||
958 | if (!dev_valid_name(name)) | 958 | if (!dev_valid_name(name)) |
959 | return -EINVAL; | 959 | return -EINVAL; |
960 | 960 | ||
961 | if (fmt && strchr(name, '%')) | 961 | if (strchr(name, '%')) |
962 | return dev_alloc_name(dev, name); | 962 | return dev_alloc_name(dev, name); |
963 | else if (__dev_get_by_name(net, name)) | 963 | else if (__dev_get_by_name(net, name)) |
964 | return -EEXIST; | 964 | return -EEXIST; |
@@ -995,7 +995,7 @@ int dev_change_name(struct net_device *dev, const char *newname) | |||
995 | 995 | ||
996 | memcpy(oldname, dev->name, IFNAMSIZ); | 996 | memcpy(oldname, dev->name, IFNAMSIZ); |
997 | 997 | ||
998 | err = dev_get_valid_name(dev, newname, 1); | 998 | err = dev_get_valid_name(dev, newname); |
999 | if (err < 0) | 999 | if (err < 0) |
1000 | return err; | 1000 | return err; |
1001 | 1001 | ||
@@ -1284,11 +1284,13 @@ static int dev_close_many(struct list_head *head) | |||
1284 | */ | 1284 | */ |
1285 | int dev_close(struct net_device *dev) | 1285 | int dev_close(struct net_device *dev) |
1286 | { | 1286 | { |
1287 | LIST_HEAD(single); | 1287 | if (dev->flags & IFF_UP) { |
1288 | LIST_HEAD(single); | ||
1288 | 1289 | ||
1289 | list_add(&dev->unreg_list, &single); | 1290 | list_add(&dev->unreg_list, &single); |
1290 | dev_close_many(&single); | 1291 | dev_close_many(&single); |
1291 | list_del(&single); | 1292 | list_del(&single); |
1293 | } | ||
1292 | return 0; | 1294 | return 0; |
1293 | } | 1295 | } |
1294 | EXPORT_SYMBOL(dev_close); | 1296 | EXPORT_SYMBOL(dev_close); |
@@ -1315,7 +1317,8 @@ void dev_disable_lro(struct net_device *dev) | |||
1315 | return; | 1317 | return; |
1316 | 1318 | ||
1317 | __ethtool_set_flags(dev, flags & ~ETH_FLAG_LRO); | 1319 | __ethtool_set_flags(dev, flags & ~ETH_FLAG_LRO); |
1318 | WARN_ON(dev->features & NETIF_F_LRO); | 1320 | if (unlikely(dev->features & NETIF_F_LRO)) |
1321 | netdev_WARN(dev, "failed to disable LRO!\n"); | ||
1319 | } | 1322 | } |
1320 | EXPORT_SYMBOL(dev_disable_lro); | 1323 | EXPORT_SYMBOL(dev_disable_lro); |
1321 | 1324 | ||
@@ -2091,7 +2094,7 @@ int dev_hard_start_xmit(struct sk_buff *skb, struct net_device *dev, | |||
2091 | u32 features; | 2094 | u32 features; |
2092 | 2095 | ||
2093 | /* | 2096 | /* |
2094 | * If device doesnt need skb->dst, release it right now while | 2097 | * If device doesn't need skb->dst, release it right now while |
2095 | * its hot in this cpu cache | 2098 | * its hot in this cpu cache |
2096 | */ | 2099 | */ |
2097 | if (dev->priv_flags & IFF_XMIT_DST_RELEASE) | 2100 | if (dev->priv_flags & IFF_XMIT_DST_RELEASE) |
@@ -2151,7 +2154,7 @@ gso: | |||
2151 | nskb->next = NULL; | 2154 | nskb->next = NULL; |
2152 | 2155 | ||
2153 | /* | 2156 | /* |
2154 | * If device doesnt need nskb->dst, release it right now while | 2157 | * If device doesn't need nskb->dst, release it right now while |
2155 | * its hot in this cpu cache | 2158 | * its hot in this cpu cache |
2156 | */ | 2159 | */ |
2157 | if (dev->priv_flags & IFF_XMIT_DST_RELEASE) | 2160 | if (dev->priv_flags & IFF_XMIT_DST_RELEASE) |
@@ -2502,8 +2505,8 @@ static inline void ____napi_schedule(struct softnet_data *sd, | |||
2502 | __u32 __skb_get_rxhash(struct sk_buff *skb) | 2505 | __u32 __skb_get_rxhash(struct sk_buff *skb) |
2503 | { | 2506 | { |
2504 | int nhoff, hash = 0, poff; | 2507 | int nhoff, hash = 0, poff; |
2505 | struct ipv6hdr *ip6; | 2508 | const struct ipv6hdr *ip6; |
2506 | struct iphdr *ip; | 2509 | const struct iphdr *ip; |
2507 | u8 ip_proto; | 2510 | u8 ip_proto; |
2508 | u32 addr1, addr2, ihl; | 2511 | u32 addr1, addr2, ihl; |
2509 | union { | 2512 | union { |
@@ -2518,7 +2521,7 @@ __u32 __skb_get_rxhash(struct sk_buff *skb) | |||
2518 | if (!pskb_may_pull(skb, sizeof(*ip) + nhoff)) | 2521 | if (!pskb_may_pull(skb, sizeof(*ip) + nhoff)) |
2519 | goto done; | 2522 | goto done; |
2520 | 2523 | ||
2521 | ip = (struct iphdr *) (skb->data + nhoff); | 2524 | ip = (const struct iphdr *) (skb->data + nhoff); |
2522 | if (ip->frag_off & htons(IP_MF | IP_OFFSET)) | 2525 | if (ip->frag_off & htons(IP_MF | IP_OFFSET)) |
2523 | ip_proto = 0; | 2526 | ip_proto = 0; |
2524 | else | 2527 | else |
@@ -2531,7 +2534,7 @@ __u32 __skb_get_rxhash(struct sk_buff *skb) | |||
2531 | if (!pskb_may_pull(skb, sizeof(*ip6) + nhoff)) | 2534 | if (!pskb_may_pull(skb, sizeof(*ip6) + nhoff)) |
2532 | goto done; | 2535 | goto done; |
2533 | 2536 | ||
2534 | ip6 = (struct ipv6hdr *) (skb->data + nhoff); | 2537 | ip6 = (const struct ipv6hdr *) (skb->data + nhoff); |
2535 | ip_proto = ip6->nexthdr; | 2538 | ip_proto = ip6->nexthdr; |
2536 | addr1 = (__force u32) ip6->saddr.s6_addr32[3]; | 2539 | addr1 = (__force u32) ip6->saddr.s6_addr32[3]; |
2537 | addr2 = (__force u32) ip6->daddr.s6_addr32[3]; | 2540 | addr2 = (__force u32) ip6->daddr.s6_addr32[3]; |
@@ -2970,8 +2973,8 @@ EXPORT_SYMBOL_GPL(br_fdb_test_addr_hook); | |||
2970 | * when CONFIG_NET_CLS_ACT is? otherwise some useless instructions | 2973 | * when CONFIG_NET_CLS_ACT is? otherwise some useless instructions |
2971 | * a compare and 2 stores extra right now if we dont have it on | 2974 | * a compare and 2 stores extra right now if we dont have it on |
2972 | * but have CONFIG_NET_CLS_ACT | 2975 | * but have CONFIG_NET_CLS_ACT |
2973 | * NOTE: This doesnt stop any functionality; if you dont have | 2976 | * NOTE: This doesn't stop any functionality; if you dont have |
2974 | * the ingress scheduler, you just cant add policies on ingress. | 2977 | * the ingress scheduler, you just can't add policies on ingress. |
2975 | * | 2978 | * |
2976 | */ | 2979 | */ |
2977 | static int ing_filter(struct sk_buff *skb, struct netdev_queue *rxq) | 2980 | static int ing_filter(struct sk_buff *skb, struct netdev_queue *rxq) |
@@ -3076,25 +3079,6 @@ void netdev_rx_handler_unregister(struct net_device *dev) | |||
3076 | } | 3079 | } |
3077 | EXPORT_SYMBOL_GPL(netdev_rx_handler_unregister); | 3080 | EXPORT_SYMBOL_GPL(netdev_rx_handler_unregister); |
3078 | 3081 | ||
3079 | static void vlan_on_bond_hook(struct sk_buff *skb) | ||
3080 | { | ||
3081 | /* | ||
3082 | * Make sure ARP frames received on VLAN interfaces stacked on | ||
3083 | * bonding interfaces still make their way to any base bonding | ||
3084 | * device that may have registered for a specific ptype. | ||
3085 | */ | ||
3086 | if (skb->dev->priv_flags & IFF_802_1Q_VLAN && | ||
3087 | vlan_dev_real_dev(skb->dev)->priv_flags & IFF_BONDING && | ||
3088 | skb->protocol == htons(ETH_P_ARP)) { | ||
3089 | struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC); | ||
3090 | |||
3091 | if (!skb2) | ||
3092 | return; | ||
3093 | skb2->dev = vlan_dev_real_dev(skb->dev); | ||
3094 | netif_rx(skb2); | ||
3095 | } | ||
3096 | } | ||
3097 | |||
3098 | static int __netif_receive_skb(struct sk_buff *skb) | 3082 | static int __netif_receive_skb(struct sk_buff *skb) |
3099 | { | 3083 | { |
3100 | struct packet_type *ptype, *pt_prev; | 3084 | struct packet_type *ptype, *pt_prev; |
@@ -3130,6 +3114,12 @@ another_round: | |||
3130 | 3114 | ||
3131 | __this_cpu_inc(softnet_data.processed); | 3115 | __this_cpu_inc(softnet_data.processed); |
3132 | 3116 | ||
3117 | if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) { | ||
3118 | skb = vlan_untag(skb); | ||
3119 | if (unlikely(!skb)) | ||
3120 | goto out; | ||
3121 | } | ||
3122 | |||
3133 | #ifdef CONFIG_NET_CLS_ACT | 3123 | #ifdef CONFIG_NET_CLS_ACT |
3134 | if (skb->tc_verd & TC_NCLS) { | 3124 | if (skb->tc_verd & TC_NCLS) { |
3135 | skb->tc_verd = CLR_TC_NCLS(skb->tc_verd); | 3125 | skb->tc_verd = CLR_TC_NCLS(skb->tc_verd); |
@@ -3177,15 +3167,13 @@ ncls: | |||
3177 | ret = deliver_skb(skb, pt_prev, orig_dev); | 3167 | ret = deliver_skb(skb, pt_prev, orig_dev); |
3178 | pt_prev = NULL; | 3168 | pt_prev = NULL; |
3179 | } | 3169 | } |
3180 | if (vlan_hwaccel_do_receive(&skb)) { | 3170 | if (vlan_do_receive(&skb)) { |
3181 | ret = __netif_receive_skb(skb); | 3171 | ret = __netif_receive_skb(skb); |
3182 | goto out; | 3172 | goto out; |
3183 | } else if (unlikely(!skb)) | 3173 | } else if (unlikely(!skb)) |
3184 | goto out; | 3174 | goto out; |
3185 | } | 3175 | } |
3186 | 3176 | ||
3187 | vlan_on_bond_hook(skb); | ||
3188 | |||
3189 | /* deliver only exact match when indicated */ | 3177 | /* deliver only exact match when indicated */ |
3190 | null_or_dev = deliver_exact ? skb->dev : NULL; | 3178 | null_or_dev = deliver_exact ? skb->dev : NULL; |
3191 | 3179 | ||
@@ -3800,7 +3788,7 @@ static void net_rx_action(struct softirq_action *h) | |||
3800 | * with netpoll's poll_napi(). Only the entity which | 3788 | * with netpoll's poll_napi(). Only the entity which |
3801 | * obtains the lock and sees NAPI_STATE_SCHED set will | 3789 | * obtains the lock and sees NAPI_STATE_SCHED set will |
3802 | * actually make the ->poll() call. Therefore we avoid | 3790 | * actually make the ->poll() call. Therefore we avoid |
3803 | * accidently calling ->poll() when NAPI is not scheduled. | 3791 | * accidentally calling ->poll() when NAPI is not scheduled. |
3804 | */ | 3792 | */ |
3805 | work = 0; | 3793 | work = 0; |
3806 | if (test_bit(NAPI_STATE_SCHED, &n->state)) { | 3794 | if (test_bit(NAPI_STATE_SCHED, &n->state)) { |
@@ -4510,6 +4498,30 @@ void dev_set_rx_mode(struct net_device *dev) | |||
4510 | } | 4498 | } |
4511 | 4499 | ||
4512 | /** | 4500 | /** |
4501 | * dev_ethtool_get_settings - call device's ethtool_ops::get_settings() | ||
4502 | * @dev: device | ||
4503 | * @cmd: memory area for ethtool_ops::get_settings() result | ||
4504 | * | ||
4505 | * The cmd arg is initialized properly (cleared and | ||
4506 | * ethtool_cmd::cmd field set to ETHTOOL_GSET). | ||
4507 | * | ||
4508 | * Return device's ethtool_ops::get_settings() result value or | ||
4509 | * -EOPNOTSUPP when device doesn't expose | ||
4510 | * ethtool_ops::get_settings() operation. | ||
4511 | */ | ||
4512 | int dev_ethtool_get_settings(struct net_device *dev, | ||
4513 | struct ethtool_cmd *cmd) | ||
4514 | { | ||
4515 | if (!dev->ethtool_ops || !dev->ethtool_ops->get_settings) | ||
4516 | return -EOPNOTSUPP; | ||
4517 | |||
4518 | memset(cmd, 0, sizeof(struct ethtool_cmd)); | ||
4519 | cmd->cmd = ETHTOOL_GSET; | ||
4520 | return dev->ethtool_ops->get_settings(dev, cmd); | ||
4521 | } | ||
4522 | EXPORT_SYMBOL(dev_ethtool_get_settings); | ||
4523 | |||
4524 | /** | ||
4513 | * dev_get_flags - get flags reported to userspace | 4525 | * dev_get_flags - get flags reported to userspace |
4514 | * @dev: device | 4526 | * @dev: device |
4515 | * | 4527 | * |
@@ -4773,7 +4785,7 @@ static int dev_ifsioc_locked(struct net *net, struct ifreq *ifr, unsigned int cm | |||
4773 | * is never reached | 4785 | * is never reached |
4774 | */ | 4786 | */ |
4775 | WARN_ON(1); | 4787 | WARN_ON(1); |
4776 | err = -EINVAL; | 4788 | err = -ENOTTY; |
4777 | break; | 4789 | break; |
4778 | 4790 | ||
4779 | } | 4791 | } |
@@ -5041,7 +5053,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg) | |||
5041 | /* Set the per device memory buffer space. | 5053 | /* Set the per device memory buffer space. |
5042 | * Not applicable in our case */ | 5054 | * Not applicable in our case */ |
5043 | case SIOCSIFLINK: | 5055 | case SIOCSIFLINK: |
5044 | return -EINVAL; | 5056 | return -ENOTTY; |
5045 | 5057 | ||
5046 | /* | 5058 | /* |
5047 | * Unknown or private ioctl. | 5059 | * Unknown or private ioctl. |
@@ -5062,7 +5074,7 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg) | |||
5062 | /* Take care of Wireless Extensions */ | 5074 | /* Take care of Wireless Extensions */ |
5063 | if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) | 5075 | if (cmd >= SIOCIWFIRST && cmd <= SIOCIWLAST) |
5064 | return wext_handle_ioctl(net, &ifr, cmd, arg); | 5076 | return wext_handle_ioctl(net, &ifr, cmd, arg); |
5065 | return -EINVAL; | 5077 | return -ENOTTY; |
5066 | } | 5078 | } |
5067 | } | 5079 | } |
5068 | 5080 | ||
@@ -5203,11 +5215,15 @@ u32 netdev_fix_features(struct net_device *dev, u32 features) | |||
5203 | } | 5215 | } |
5204 | 5216 | ||
5205 | /* TSO requires that SG is present as well. */ | 5217 | /* TSO requires that SG is present as well. */ |
5206 | if ((features & NETIF_F_TSO) && !(features & NETIF_F_SG)) { | 5218 | if ((features & NETIF_F_ALL_TSO) && !(features & NETIF_F_SG)) { |
5207 | netdev_info(dev, "Dropping NETIF_F_TSO since no SG feature.\n"); | 5219 | netdev_info(dev, "Dropping TSO features since no SG feature.\n"); |
5208 | features &= ~NETIF_F_TSO; | 5220 | features &= ~NETIF_F_ALL_TSO; |
5209 | } | 5221 | } |
5210 | 5222 | ||
5223 | /* TSO ECN requires that TSO is present as well. */ | ||
5224 | if ((features & NETIF_F_ALL_TSO) == NETIF_F_TSO_ECN) | ||
5225 | features &= ~NETIF_F_TSO_ECN; | ||
5226 | |||
5211 | /* Software GSO depends on SG. */ | 5227 | /* Software GSO depends on SG. */ |
5212 | if ((features & NETIF_F_GSO) && !(features & NETIF_F_SG)) { | 5228 | if ((features & NETIF_F_GSO) && !(features & NETIF_F_SG)) { |
5213 | netdev_info(dev, "Dropping NETIF_F_GSO since no SG feature.\n"); | 5229 | netdev_info(dev, "Dropping NETIF_F_GSO since no SG feature.\n"); |
@@ -5236,11 +5252,13 @@ u32 netdev_fix_features(struct net_device *dev, u32 features) | |||
5236 | } | 5252 | } |
5237 | EXPORT_SYMBOL(netdev_fix_features); | 5253 | EXPORT_SYMBOL(netdev_fix_features); |
5238 | 5254 | ||
5239 | void netdev_update_features(struct net_device *dev) | 5255 | int __netdev_update_features(struct net_device *dev) |
5240 | { | 5256 | { |
5241 | u32 features; | 5257 | u32 features; |
5242 | int err = 0; | 5258 | int err = 0; |
5243 | 5259 | ||
5260 | ASSERT_RTNL(); | ||
5261 | |||
5244 | features = netdev_get_wanted_features(dev); | 5262 | features = netdev_get_wanted_features(dev); |
5245 | 5263 | ||
5246 | if (dev->netdev_ops->ndo_fix_features) | 5264 | if (dev->netdev_ops->ndo_fix_features) |
@@ -5250,7 +5268,7 @@ void netdev_update_features(struct net_device *dev) | |||
5250 | features = netdev_fix_features(dev, features); | 5268 | features = netdev_fix_features(dev, features); |
5251 | 5269 | ||
5252 | if (dev->features == features) | 5270 | if (dev->features == features) |
5253 | return; | 5271 | return 0; |
5254 | 5272 | ||
5255 | netdev_info(dev, "Features changed: 0x%08x -> 0x%08x\n", | 5273 | netdev_info(dev, "Features changed: 0x%08x -> 0x%08x\n", |
5256 | dev->features, features); | 5274 | dev->features, features); |
@@ -5258,16 +5276,52 @@ void netdev_update_features(struct net_device *dev) | |||
5258 | if (dev->netdev_ops->ndo_set_features) | 5276 | if (dev->netdev_ops->ndo_set_features) |
5259 | err = dev->netdev_ops->ndo_set_features(dev, features); | 5277 | err = dev->netdev_ops->ndo_set_features(dev, features); |
5260 | 5278 | ||
5261 | if (!err) | 5279 | if (unlikely(err < 0)) { |
5262 | dev->features = features; | ||
5263 | else if (err < 0) | ||
5264 | netdev_err(dev, | 5280 | netdev_err(dev, |
5265 | "set_features() failed (%d); wanted 0x%08x, left 0x%08x\n", | 5281 | "set_features() failed (%d); wanted 0x%08x, left 0x%08x\n", |
5266 | err, features, dev->features); | 5282 | err, features, dev->features); |
5283 | return -1; | ||
5284 | } | ||
5285 | |||
5286 | if (!err) | ||
5287 | dev->features = features; | ||
5288 | |||
5289 | return 1; | ||
5290 | } | ||
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 | */ | ||
5300 | void netdev_update_features(struct net_device *dev) | ||
5301 | { | ||
5302 | if (__netdev_update_features(dev)) | ||
5303 | netdev_features_change(dev); | ||
5267 | } | 5304 | } |
5268 | EXPORT_SYMBOL(netdev_update_features); | 5305 | EXPORT_SYMBOL(netdev_update_features); |
5269 | 5306 | ||
5270 | /** | 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 | /** | ||
5271 | * netif_stacked_transfer_operstate - transfer operstate | 5325 | * netif_stacked_transfer_operstate - transfer operstate |
5272 | * @rootdev: the root or lower level device to transfer state from | 5326 | * @rootdev: the root or lower level device to transfer state from |
5273 | * @dev: the device to transfer operstate to | 5327 | * @dev: the device to transfer operstate to |
@@ -5383,6 +5437,10 @@ int register_netdevice(struct net_device *dev) | |||
5383 | 5437 | ||
5384 | dev->iflink = -1; | 5438 | dev->iflink = -1; |
5385 | 5439 | ||
5440 | ret = dev_get_valid_name(dev, dev->name); | ||
5441 | if (ret < 0) | ||
5442 | goto out; | ||
5443 | |||
5386 | /* Init, if this function is available */ | 5444 | /* Init, if this function is available */ |
5387 | if (dev->netdev_ops->ndo_init) { | 5445 | if (dev->netdev_ops->ndo_init) { |
5388 | ret = dev->netdev_ops->ndo_init(dev); | 5446 | ret = dev->netdev_ops->ndo_init(dev); |
@@ -5393,10 +5451,6 @@ int register_netdevice(struct net_device *dev) | |||
5393 | } | 5451 | } |
5394 | } | 5452 | } |
5395 | 5453 | ||
5396 | ret = dev_get_valid_name(dev, dev->name, 0); | ||
5397 | if (ret) | ||
5398 | goto err_uninit; | ||
5399 | |||
5400 | dev->ifindex = dev_new_index(net); | 5454 | dev->ifindex = dev_new_index(net); |
5401 | if (dev->iflink == -1) | 5455 | if (dev->iflink == -1) |
5402 | dev->iflink = dev->ifindex; | 5456 | dev->iflink = dev->ifindex; |
@@ -5414,6 +5468,14 @@ int register_netdevice(struct net_device *dev) | |||
5414 | dev->features &= ~NETIF_F_GSO; | 5468 | dev->features &= ~NETIF_F_GSO; |
5415 | } | 5469 | } |
5416 | 5470 | ||
5471 | /* Turn on no cache copy if HW is doing checksum */ | ||
5472 | dev->hw_features |= NETIF_F_NOCACHE_COPY; | ||
5473 | if ((dev->features & NETIF_F_ALL_CSUM) && | ||
5474 | !(dev->features & NETIF_F_NO_CSUM)) { | ||
5475 | dev->wanted_features |= NETIF_F_NOCACHE_COPY; | ||
5476 | dev->features |= NETIF_F_NOCACHE_COPY; | ||
5477 | } | ||
5478 | |||
5417 | /* Enable GRO and NETIF_F_HIGHDMA for vlans by default, | 5479 | /* Enable GRO and NETIF_F_HIGHDMA for vlans by default, |
5418 | * vlan_dev_init() will do the dev->features check, so these features | 5480 | * vlan_dev_init() will do the dev->features check, so these features |
5419 | * are enabled only if supported by underlying device. | 5481 | * are enabled only if supported by underlying device. |
@@ -5430,7 +5492,7 @@ int register_netdevice(struct net_device *dev) | |||
5430 | goto err_uninit; | 5492 | goto err_uninit; |
5431 | dev->reg_state = NETREG_REGISTERED; | 5493 | dev->reg_state = NETREG_REGISTERED; |
5432 | 5494 | ||
5433 | netdev_update_features(dev); | 5495 | __netdev_update_features(dev); |
5434 | 5496 | ||
5435 | /* | 5497 | /* |
5436 | * Default initial state at registry is that the | 5498 | * Default initial state at registry is that the |
@@ -5527,19 +5589,7 @@ int register_netdev(struct net_device *dev) | |||
5527 | int err; | 5589 | int err; |
5528 | 5590 | ||
5529 | rtnl_lock(); | 5591 | rtnl_lock(); |
5530 | |||
5531 | /* | ||
5532 | * If the name is a format string the caller wants us to do a | ||
5533 | * name allocation. | ||
5534 | */ | ||
5535 | if (strchr(dev->name, '%')) { | ||
5536 | err = dev_alloc_name(dev, dev->name); | ||
5537 | if (err < 0) | ||
5538 | goto out; | ||
5539 | } | ||
5540 | |||
5541 | err = register_netdevice(dev); | 5592 | err = register_netdevice(dev); |
5542 | out: | ||
5543 | rtnl_unlock(); | 5593 | rtnl_unlock(); |
5544 | return err; | 5594 | return err; |
5545 | } | 5595 | } |
@@ -6021,7 +6071,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char | |||
6021 | /* We get here if we can't use the current device name */ | 6071 | /* We get here if we can't use the current device name */ |
6022 | if (!pat) | 6072 | if (!pat) |
6023 | goto out; | 6073 | goto out; |
6024 | if (dev_get_valid_name(dev, pat, 1)) | 6074 | if (dev_get_valid_name(dev, pat) < 0) |
6025 | goto out; | 6075 | goto out; |
6026 | } | 6076 | } |
6027 | 6077 | ||
@@ -6153,29 +6203,20 @@ static int dev_cpu_callback(struct notifier_block *nfb, | |||
6153 | */ | 6203 | */ |
6154 | u32 netdev_increment_features(u32 all, u32 one, u32 mask) | 6204 | u32 netdev_increment_features(u32 all, u32 one, u32 mask) |
6155 | { | 6205 | { |
6156 | /* If device needs checksumming, downgrade to it. */ | 6206 | if (mask & NETIF_F_GEN_CSUM) |
6157 | if (all & NETIF_F_NO_CSUM && !(one & NETIF_F_NO_CSUM)) | 6207 | mask |= NETIF_F_ALL_CSUM; |
6158 | all ^= NETIF_F_NO_CSUM | (one & NETIF_F_ALL_CSUM); | 6208 | mask |= NETIF_F_VLAN_CHALLENGED; |
6159 | else if (mask & NETIF_F_ALL_CSUM) { | ||
6160 | /* If one device supports v4/v6 checksumming, set for all. */ | ||
6161 | if (one & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM) && | ||
6162 | !(all & NETIF_F_GEN_CSUM)) { | ||
6163 | all &= ~NETIF_F_ALL_CSUM; | ||
6164 | all |= one & (NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM); | ||
6165 | } | ||
6166 | 6209 | ||
6167 | /* If one device supports hw checksumming, set for all. */ | 6210 | all |= one & (NETIF_F_ONE_FOR_ALL|NETIF_F_ALL_CSUM) & mask; |
6168 | if (one & NETIF_F_GEN_CSUM && !(all & NETIF_F_GEN_CSUM)) { | 6211 | all &= one | ~NETIF_F_ALL_FOR_ALL; |
6169 | all &= ~NETIF_F_ALL_CSUM; | ||
6170 | all |= NETIF_F_HW_CSUM; | ||
6171 | } | ||
6172 | } | ||
6173 | 6212 | ||
6174 | one |= NETIF_F_ALL_CSUM; | 6213 | /* If device needs checksumming, downgrade to it. */ |
6214 | if (all & (NETIF_F_ALL_CSUM & ~NETIF_F_NO_CSUM)) | ||
6215 | all &= ~NETIF_F_NO_CSUM; | ||
6175 | 6216 | ||
6176 | one |= all & NETIF_F_ONE_FOR_ALL; | 6217 | /* If one device supports hw checksumming, set for all. */ |
6177 | all &= one | NETIF_F_LLTX | NETIF_F_GSO | NETIF_F_UFO; | 6218 | if (all & NETIF_F_GEN_CSUM) |
6178 | all |= one & mask & NETIF_F_ONE_FOR_ALL; | 6219 | all &= ~(NETIF_F_ALL_CSUM & ~NETIF_F_GEN_CSUM); |
6179 | 6220 | ||
6180 | return all; | 6221 | return all; |
6181 | } | 6222 | } |
@@ -6336,7 +6377,7 @@ static void __net_exit default_device_exit(struct net *net) | |||
6336 | if (dev->rtnl_link_ops) | 6377 | if (dev->rtnl_link_ops) |
6337 | continue; | 6378 | continue; |
6338 | 6379 | ||
6339 | /* Push remaing network devices to init_net */ | 6380 | /* Push remaining network devices to init_net */ |
6340 | snprintf(fb_name, IFNAMSIZ, "dev%d", dev->ifindex); | 6381 | snprintf(fb_name, IFNAMSIZ, "dev%d", dev->ifindex); |
6341 | err = dev_change_net_namespace(dev, &init_net, fb_name); | 6382 | err = dev_change_net_namespace(dev, &init_net, fb_name); |
6342 | if (err) { | 6383 | if (err) { |
diff --git a/net/core/dst.c b/net/core/dst.c index 91104d35de7d..30f009327b62 100644 --- a/net/core/dst.c +++ b/net/core/dst.c | |||
@@ -166,7 +166,8 @@ EXPORT_SYMBOL(dst_discard); | |||
166 | 166 | ||
167 | const u32 dst_default_metrics[RTAX_MAX]; | 167 | const u32 dst_default_metrics[RTAX_MAX]; |
168 | 168 | ||
169 | void *dst_alloc(struct dst_ops *ops, int initial_ref) | 169 | void *dst_alloc(struct dst_ops *ops, struct net_device *dev, |
170 | int initial_ref, int initial_obsolete, int flags) | ||
170 | { | 171 | { |
171 | struct dst_entry *dst; | 172 | struct dst_entry *dst; |
172 | 173 | ||
@@ -174,15 +175,36 @@ void *dst_alloc(struct dst_ops *ops, int initial_ref) | |||
174 | if (ops->gc(ops)) | 175 | if (ops->gc(ops)) |
175 | return NULL; | 176 | return NULL; |
176 | } | 177 | } |
177 | dst = kmem_cache_zalloc(ops->kmem_cachep, GFP_ATOMIC); | 178 | dst = kmem_cache_alloc(ops->kmem_cachep, GFP_ATOMIC); |
178 | if (!dst) | 179 | if (!dst) |
179 | return NULL; | 180 | return NULL; |
180 | atomic_set(&dst->__refcnt, initial_ref); | 181 | dst->child = NULL; |
182 | dst->dev = dev; | ||
183 | if (dev) | ||
184 | dev_hold(dev); | ||
181 | dst->ops = ops; | 185 | dst->ops = ops; |
182 | dst->lastuse = jiffies; | ||
183 | dst->path = dst; | ||
184 | dst->input = dst->output = dst_discard; | ||
185 | dst_init_metrics(dst, dst_default_metrics, true); | 186 | dst_init_metrics(dst, dst_default_metrics, true); |
187 | dst->expires = 0UL; | ||
188 | dst->path = dst; | ||
189 | dst->neighbour = NULL; | ||
190 | dst->hh = NULL; | ||
191 | #ifdef CONFIG_XFRM | ||
192 | dst->xfrm = NULL; | ||
193 | #endif | ||
194 | dst->input = dst_discard; | ||
195 | dst->output = dst_discard; | ||
196 | dst->error = 0; | ||
197 | dst->obsolete = initial_obsolete; | ||
198 | dst->header_len = 0; | ||
199 | dst->trailer_len = 0; | ||
200 | #ifdef CONFIG_IP_ROUTE_CLASSID | ||
201 | dst->tclassid = 0; | ||
202 | #endif | ||
203 | atomic_set(&dst->__refcnt, initial_ref); | ||
204 | dst->__use = 0; | ||
205 | dst->lastuse = jiffies; | ||
206 | dst->flags = flags; | ||
207 | dst->next = NULL; | ||
186 | #if RT_CACHE_DEBUG >= 2 | 208 | #if RT_CACHE_DEBUG >= 2 |
187 | atomic_inc(&dst_total); | 209 | atomic_inc(&dst_total); |
188 | #endif | 210 | #endif |
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 74ead9eca126..b8c2bcfee6af 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
@@ -21,6 +21,8 @@ | |||
21 | #include <linux/uaccess.h> | 21 | #include <linux/uaccess.h> |
22 | #include <linux/vmalloc.h> | 22 | #include <linux/vmalloc.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/rtnetlink.h> | ||
25 | #include <linux/sched.h> | ||
24 | 26 | ||
25 | /* | 27 | /* |
26 | * Some useful ethtool_ops methods that're device independent. | 28 | * Some useful ethtool_ops methods that're device independent. |
@@ -317,7 +319,7 @@ static int ethtool_set_features(struct net_device *dev, void __user *useraddr) | |||
317 | 319 | ||
318 | dev->wanted_features &= ~features[0].valid; | 320 | dev->wanted_features &= ~features[0].valid; |
319 | dev->wanted_features |= features[0].valid & features[0].requested; | 321 | dev->wanted_features |= features[0].valid & features[0].requested; |
320 | netdev_update_features(dev); | 322 | __netdev_update_features(dev); |
321 | 323 | ||
322 | if ((dev->wanted_features ^ dev->features) & features[0].valid) | 324 | if ((dev->wanted_features ^ dev->features) & features[0].valid) |
323 | ret |= ETHTOOL_F_WISH; | 325 | ret |= ETHTOOL_F_WISH; |
@@ -359,8 +361,8 @@ static const char netdev_features_strings[ETHTOOL_DEV_FEATURE_WORDS * 32][ETH_GS | |||
359 | /* NETIF_F_NTUPLE */ "rx-ntuple-filter", | 361 | /* NETIF_F_NTUPLE */ "rx-ntuple-filter", |
360 | /* NETIF_F_RXHASH */ "rx-hashing", | 362 | /* NETIF_F_RXHASH */ "rx-hashing", |
361 | /* NETIF_F_RXCSUM */ "rx-checksum", | 363 | /* NETIF_F_RXCSUM */ "rx-checksum", |
362 | "", | 364 | /* NETIF_F_NOCACHE_COPY */ "tx-nocache-copy", |
363 | "", | 365 | /* NETIF_F_LOOPBACK */ "loopback", |
364 | }; | 366 | }; |
365 | 367 | ||
366 | static int __ethtool_get_sset_count(struct net_device *dev, int sset) | 368 | static int __ethtool_get_sset_count(struct net_device *dev, int sset) |
@@ -499,7 +501,7 @@ static int ethtool_set_one_feature(struct net_device *dev, | |||
499 | else | 501 | else |
500 | dev->wanted_features &= ~mask; | 502 | dev->wanted_features &= ~mask; |
501 | 503 | ||
502 | netdev_update_features(dev); | 504 | __netdev_update_features(dev); |
503 | return 0; | 505 | return 0; |
504 | } | 506 | } |
505 | 507 | ||
@@ -544,14 +546,14 @@ int __ethtool_set_flags(struct net_device *dev, u32 data) | |||
544 | } | 546 | } |
545 | 547 | ||
546 | /* allow changing only bits set in hw_features */ | 548 | /* allow changing only bits set in hw_features */ |
547 | changed = (data ^ dev->wanted_features) & flags_dup_features; | 549 | changed = (data ^ dev->features) & flags_dup_features; |
548 | if (changed & ~dev->hw_features) | 550 | if (changed & ~dev->hw_features) |
549 | return (changed & dev->hw_features) ? -EINVAL : -EOPNOTSUPP; | 551 | return (changed & dev->hw_features) ? -EINVAL : -EOPNOTSUPP; |
550 | 552 | ||
551 | dev->wanted_features = | 553 | dev->wanted_features = |
552 | (dev->wanted_features & ~changed) | data; | 554 | (dev->wanted_features & ~changed) | (data & dev->hw_features); |
553 | 555 | ||
554 | netdev_update_features(dev); | 556 | __netdev_update_features(dev); |
555 | 557 | ||
556 | return 0; | 558 | return 0; |
557 | } | 559 | } |
@@ -908,6 +910,9 @@ static noinline_for_stack int ethtool_set_rx_ntuple(struct net_device *dev, | |||
908 | struct ethtool_rx_ntuple_flow_spec_container *fsc = NULL; | 910 | struct ethtool_rx_ntuple_flow_spec_container *fsc = NULL; |
909 | int ret; | 911 | int ret; |
910 | 912 | ||
913 | if (!ops->set_rx_ntuple) | ||
914 | return -EOPNOTSUPP; | ||
915 | |||
911 | if (!(dev->features & NETIF_F_NTUPLE)) | 916 | if (!(dev->features & NETIF_F_NTUPLE)) |
912 | return -EINVAL; | 917 | return -EINVAL; |
913 | 918 | ||
@@ -1441,6 +1446,35 @@ static int ethtool_set_ringparam(struct net_device *dev, void __user *useraddr) | |||
1441 | return dev->ethtool_ops->set_ringparam(dev, &ringparam); | 1446 | return dev->ethtool_ops->set_ringparam(dev, &ringparam); |
1442 | } | 1447 | } |
1443 | 1448 | ||
1449 | static noinline_for_stack int ethtool_get_channels(struct net_device *dev, | ||
1450 | void __user *useraddr) | ||
1451 | { | ||
1452 | struct ethtool_channels channels = { .cmd = ETHTOOL_GCHANNELS }; | ||
1453 | |||
1454 | if (!dev->ethtool_ops->get_channels) | ||
1455 | return -EOPNOTSUPP; | ||
1456 | |||
1457 | dev->ethtool_ops->get_channels(dev, &channels); | ||
1458 | |||
1459 | if (copy_to_user(useraddr, &channels, sizeof(channels))) | ||
1460 | return -EFAULT; | ||
1461 | return 0; | ||
1462 | } | ||
1463 | |||
1464 | static noinline_for_stack int ethtool_set_channels(struct net_device *dev, | ||
1465 | void __user *useraddr) | ||
1466 | { | ||
1467 | struct ethtool_channels channels; | ||
1468 | |||
1469 | if (!dev->ethtool_ops->set_channels) | ||
1470 | return -EOPNOTSUPP; | ||
1471 | |||
1472 | if (copy_from_user(&channels, useraddr, sizeof(channels))) | ||
1473 | return -EFAULT; | ||
1474 | |||
1475 | return dev->ethtool_ops->set_channels(dev, &channels); | ||
1476 | } | ||
1477 | |||
1444 | static int ethtool_get_pauseparam(struct net_device *dev, void __user *useraddr) | 1478 | static int ethtool_get_pauseparam(struct net_device *dev, void __user *useraddr) |
1445 | { | 1479 | { |
1446 | struct ethtool_pauseparam pauseparam = { ETHTOOL_GPAUSEPARAM }; | 1480 | struct ethtool_pauseparam pauseparam = { ETHTOOL_GPAUSEPARAM }; |
@@ -1618,14 +1652,60 @@ out: | |||
1618 | static int ethtool_phys_id(struct net_device *dev, void __user *useraddr) | 1652 | static int ethtool_phys_id(struct net_device *dev, void __user *useraddr) |
1619 | { | 1653 | { |
1620 | struct ethtool_value id; | 1654 | struct ethtool_value id; |
1655 | static bool busy; | ||
1656 | int rc; | ||
1621 | 1657 | ||
1622 | if (!dev->ethtool_ops->phys_id) | 1658 | if (!dev->ethtool_ops->set_phys_id) |
1623 | return -EOPNOTSUPP; | 1659 | return -EOPNOTSUPP; |
1624 | 1660 | ||
1661 | if (busy) | ||
1662 | return -EBUSY; | ||
1663 | |||
1625 | if (copy_from_user(&id, useraddr, sizeof(id))) | 1664 | if (copy_from_user(&id, useraddr, sizeof(id))) |
1626 | return -EFAULT; | 1665 | return -EFAULT; |
1627 | 1666 | ||
1628 | return dev->ethtool_ops->phys_id(dev, id.data); | 1667 | rc = dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_ACTIVE); |
1668 | if (rc < 0) | ||
1669 | return rc; | ||
1670 | |||
1671 | /* Drop the RTNL lock while waiting, but prevent reentry or | ||
1672 | * removal of the device. | ||
1673 | */ | ||
1674 | busy = true; | ||
1675 | dev_hold(dev); | ||
1676 | rtnl_unlock(); | ||
1677 | |||
1678 | if (rc == 0) { | ||
1679 | /* Driver will handle this itself */ | ||
1680 | schedule_timeout_interruptible( | ||
1681 | id.data ? (id.data * HZ) : MAX_SCHEDULE_TIMEOUT); | ||
1682 | } else { | ||
1683 | /* Driver expects to be called at twice the frequency in rc */ | ||
1684 | int n = rc * 2, i, interval = HZ / n; | ||
1685 | |||
1686 | /* Count down seconds */ | ||
1687 | do { | ||
1688 | /* Count down iterations per second */ | ||
1689 | i = n; | ||
1690 | do { | ||
1691 | rtnl_lock(); | ||
1692 | rc = dev->ethtool_ops->set_phys_id(dev, | ||
1693 | (i & 1) ? ETHTOOL_ID_OFF : ETHTOOL_ID_ON); | ||
1694 | rtnl_unlock(); | ||
1695 | if (rc) | ||
1696 | break; | ||
1697 | schedule_timeout_interruptible(interval); | ||
1698 | } while (!signal_pending(current) && --i != 0); | ||
1699 | } while (!signal_pending(current) && | ||
1700 | (id.data == 0 || --id.data != 0)); | ||
1701 | } | ||
1702 | |||
1703 | rtnl_lock(); | ||
1704 | dev_put(dev); | ||
1705 | busy = false; | ||
1706 | |||
1707 | (void)dev->ethtool_ops->set_phys_id(dev, ETHTOOL_ID_INACTIVE); | ||
1708 | return rc; | ||
1629 | } | 1709 | } |
1630 | 1710 | ||
1631 | static int ethtool_get_stats(struct net_device *dev, void __user *useraddr) | 1711 | static int ethtool_get_stats(struct net_device *dev, void __user *useraddr) |
@@ -1743,6 +1823,87 @@ static noinline_for_stack int ethtool_flash_device(struct net_device *dev, | |||
1743 | return dev->ethtool_ops->flash_device(dev, &efl); | 1823 | return dev->ethtool_ops->flash_device(dev, &efl); |
1744 | } | 1824 | } |
1745 | 1825 | ||
1826 | static int ethtool_set_dump(struct net_device *dev, | ||
1827 | void __user *useraddr) | ||
1828 | { | ||
1829 | struct ethtool_dump dump; | ||
1830 | |||
1831 | if (!dev->ethtool_ops->set_dump) | ||
1832 | return -EOPNOTSUPP; | ||
1833 | |||
1834 | if (copy_from_user(&dump, useraddr, sizeof(dump))) | ||
1835 | return -EFAULT; | ||
1836 | |||
1837 | return dev->ethtool_ops->set_dump(dev, &dump); | ||
1838 | } | ||
1839 | |||
1840 | static int ethtool_get_dump_flag(struct net_device *dev, | ||
1841 | void __user *useraddr) | ||
1842 | { | ||
1843 | int ret; | ||
1844 | struct ethtool_dump dump; | ||
1845 | const struct ethtool_ops *ops = dev->ethtool_ops; | ||
1846 | |||
1847 | if (!dev->ethtool_ops->get_dump_flag) | ||
1848 | return -EOPNOTSUPP; | ||
1849 | |||
1850 | if (copy_from_user(&dump, useraddr, sizeof(dump))) | ||
1851 | return -EFAULT; | ||
1852 | |||
1853 | ret = ops->get_dump_flag(dev, &dump); | ||
1854 | if (ret) | ||
1855 | return ret; | ||
1856 | |||
1857 | if (copy_to_user(useraddr, &dump, sizeof(dump))) | ||
1858 | return -EFAULT; | ||
1859 | return 0; | ||
1860 | } | ||
1861 | |||
1862 | static int ethtool_get_dump_data(struct net_device *dev, | ||
1863 | void __user *useraddr) | ||
1864 | { | ||
1865 | int ret; | ||
1866 | __u32 len; | ||
1867 | struct ethtool_dump dump, tmp; | ||
1868 | const struct ethtool_ops *ops = dev->ethtool_ops; | ||
1869 | void *data = NULL; | ||
1870 | |||
1871 | if (!dev->ethtool_ops->get_dump_data || | ||
1872 | !dev->ethtool_ops->get_dump_flag) | ||
1873 | return -EOPNOTSUPP; | ||
1874 | |||
1875 | if (copy_from_user(&dump, useraddr, sizeof(dump))) | ||
1876 | return -EFAULT; | ||
1877 | |||
1878 | memset(&tmp, 0, sizeof(tmp)); | ||
1879 | tmp.cmd = ETHTOOL_GET_DUMP_FLAG; | ||
1880 | ret = ops->get_dump_flag(dev, &tmp); | ||
1881 | if (ret) | ||
1882 | return ret; | ||
1883 | |||
1884 | len = (tmp.len > dump.len) ? dump.len : tmp.len; | ||
1885 | if (!len) | ||
1886 | return -EFAULT; | ||
1887 | |||
1888 | data = vzalloc(tmp.len); | ||
1889 | if (!data) | ||
1890 | return -ENOMEM; | ||
1891 | ret = ops->get_dump_data(dev, &dump, data); | ||
1892 | if (ret) | ||
1893 | goto out; | ||
1894 | |||
1895 | if (copy_to_user(useraddr, &dump, sizeof(dump))) { | ||
1896 | ret = -EFAULT; | ||
1897 | goto out; | ||
1898 | } | ||
1899 | useraddr += offsetof(struct ethtool_dump, data); | ||
1900 | if (copy_to_user(useraddr, data, len)) | ||
1901 | ret = -EFAULT; | ||
1902 | out: | ||
1903 | vfree(data); | ||
1904 | return ret; | ||
1905 | } | ||
1906 | |||
1746 | /* The main entry point in this file. Called from net/core/dev.c */ | 1907 | /* The main entry point in this file. Called from net/core/dev.c */ |
1747 | 1908 | ||
1748 | int dev_ethtool(struct net *net, struct ifreq *ifr) | 1909 | int dev_ethtool(struct net *net, struct ifreq *ifr) |
@@ -1953,6 +2114,21 @@ int dev_ethtool(struct net *net, struct ifreq *ifr) | |||
1953 | case ETHTOOL_SGRO: | 2114 | case ETHTOOL_SGRO: |
1954 | rc = ethtool_set_one_feature(dev, useraddr, ethcmd); | 2115 | rc = ethtool_set_one_feature(dev, useraddr, ethcmd); |
1955 | break; | 2116 | break; |
2117 | case ETHTOOL_GCHANNELS: | ||
2118 | rc = ethtool_get_channels(dev, useraddr); | ||
2119 | break; | ||
2120 | case ETHTOOL_SCHANNELS: | ||
2121 | rc = ethtool_set_channels(dev, useraddr); | ||
2122 | break; | ||
2123 | case ETHTOOL_SET_DUMP: | ||
2124 | rc = ethtool_set_dump(dev, useraddr); | ||
2125 | break; | ||
2126 | case ETHTOOL_GET_DUMP_FLAG: | ||
2127 | rc = ethtool_get_dump_flag(dev, useraddr); | ||
2128 | break; | ||
2129 | case ETHTOOL_GET_DUMP_DATA: | ||
2130 | rc = ethtool_get_dump_data(dev, useraddr); | ||
2131 | break; | ||
1956 | default: | 2132 | default: |
1957 | rc = -EOPNOTSUPP; | 2133 | rc = -EOPNOTSUPP; |
1958 | } | 2134 | } |
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c index 8248ebb5891d..3911586e12e4 100644 --- a/net/core/fib_rules.c +++ b/net/core/fib_rules.c | |||
@@ -590,7 +590,8 @@ static int dump_rules(struct sk_buff *skb, struct netlink_callback *cb, | |||
590 | int idx = 0; | 590 | int idx = 0; |
591 | struct fib_rule *rule; | 591 | struct fib_rule *rule; |
592 | 592 | ||
593 | list_for_each_entry(rule, &ops->rules_list, list) { | 593 | rcu_read_lock(); |
594 | list_for_each_entry_rcu(rule, &ops->rules_list, list) { | ||
594 | if (idx < cb->args[1]) | 595 | if (idx < cb->args[1]) |
595 | goto skip; | 596 | goto skip; |
596 | 597 | ||
diff --git a/net/core/filter.c b/net/core/filter.c index 232b1873bb28..0eb8c4466eaa 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
@@ -39,65 +39,6 @@ | |||
39 | #include <linux/filter.h> | 39 | #include <linux/filter.h> |
40 | #include <linux/reciprocal_div.h> | 40 | #include <linux/reciprocal_div.h> |
41 | 41 | ||
42 | enum { | ||
43 | BPF_S_RET_K = 1, | ||
44 | BPF_S_RET_A, | ||
45 | BPF_S_ALU_ADD_K, | ||
46 | BPF_S_ALU_ADD_X, | ||
47 | BPF_S_ALU_SUB_K, | ||
48 | BPF_S_ALU_SUB_X, | ||
49 | BPF_S_ALU_MUL_K, | ||
50 | BPF_S_ALU_MUL_X, | ||
51 | BPF_S_ALU_DIV_X, | ||
52 | BPF_S_ALU_AND_K, | ||
53 | BPF_S_ALU_AND_X, | ||
54 | BPF_S_ALU_OR_K, | ||
55 | BPF_S_ALU_OR_X, | ||
56 | BPF_S_ALU_LSH_K, | ||
57 | BPF_S_ALU_LSH_X, | ||
58 | BPF_S_ALU_RSH_K, | ||
59 | BPF_S_ALU_RSH_X, | ||
60 | BPF_S_ALU_NEG, | ||
61 | BPF_S_LD_W_ABS, | ||
62 | BPF_S_LD_H_ABS, | ||
63 | BPF_S_LD_B_ABS, | ||
64 | BPF_S_LD_W_LEN, | ||
65 | BPF_S_LD_W_IND, | ||
66 | BPF_S_LD_H_IND, | ||
67 | BPF_S_LD_B_IND, | ||
68 | BPF_S_LD_IMM, | ||
69 | BPF_S_LDX_W_LEN, | ||
70 | BPF_S_LDX_B_MSH, | ||
71 | BPF_S_LDX_IMM, | ||
72 | BPF_S_MISC_TAX, | ||
73 | BPF_S_MISC_TXA, | ||
74 | BPF_S_ALU_DIV_K, | ||
75 | BPF_S_LD_MEM, | ||
76 | BPF_S_LDX_MEM, | ||
77 | BPF_S_ST, | ||
78 | BPF_S_STX, | ||
79 | BPF_S_JMP_JA, | ||
80 | BPF_S_JMP_JEQ_K, | ||
81 | BPF_S_JMP_JEQ_X, | ||
82 | BPF_S_JMP_JGE_K, | ||
83 | BPF_S_JMP_JGE_X, | ||
84 | BPF_S_JMP_JGT_K, | ||
85 | BPF_S_JMP_JGT_X, | ||
86 | BPF_S_JMP_JSET_K, | ||
87 | BPF_S_JMP_JSET_X, | ||
88 | /* Ancillary data */ | ||
89 | BPF_S_ANC_PROTOCOL, | ||
90 | BPF_S_ANC_PKTTYPE, | ||
91 | BPF_S_ANC_IFINDEX, | ||
92 | BPF_S_ANC_NLATTR, | ||
93 | BPF_S_ANC_NLATTR_NEST, | ||
94 | BPF_S_ANC_MARK, | ||
95 | BPF_S_ANC_QUEUE, | ||
96 | BPF_S_ANC_HATYPE, | ||
97 | BPF_S_ANC_RXHASH, | ||
98 | BPF_S_ANC_CPU, | ||
99 | }; | ||
100 | |||
101 | /* No hurry in this branch */ | 42 | /* No hurry in this branch */ |
102 | static void *__load_pointer(const struct sk_buff *skb, int k, unsigned int size) | 43 | static void *__load_pointer(const struct sk_buff *skb, int k, unsigned int size) |
103 | { | 44 | { |
@@ -145,7 +86,7 @@ int sk_filter(struct sock *sk, struct sk_buff *skb) | |||
145 | rcu_read_lock(); | 86 | rcu_read_lock(); |
146 | filter = rcu_dereference(sk->sk_filter); | 87 | filter = rcu_dereference(sk->sk_filter); |
147 | if (filter) { | 88 | if (filter) { |
148 | unsigned int pkt_len = sk_run_filter(skb, filter->insns); | 89 | unsigned int pkt_len = SK_RUN_FILTER(filter, skb); |
149 | 90 | ||
150 | err = pkt_len ? pskb_trim(skb, pkt_len) : -EPERM; | 91 | err = pkt_len ? pskb_trim(skb, pkt_len) : -EPERM; |
151 | } | 92 | } |
@@ -425,7 +366,7 @@ EXPORT_SYMBOL(sk_run_filter); | |||
425 | * As we dont want to clear mem[] array for each packet going through | 366 | * As we dont want to clear mem[] array for each packet going through |
426 | * sk_run_filter(), we check that filter loaded by user never try to read | 367 | * sk_run_filter(), we check that filter loaded by user never try to read |
427 | * a cell if not previously written, and we check all branches to be sure | 368 | * a cell if not previously written, and we check all branches to be sure |
428 | * a malicious user doesnt try to abuse us. | 369 | * a malicious user doesn't try to abuse us. |
429 | */ | 370 | */ |
430 | static int check_load_and_stores(struct sock_filter *filter, int flen) | 371 | static int check_load_and_stores(struct sock_filter *filter, int flen) |
431 | { | 372 | { |
@@ -638,6 +579,7 @@ void sk_filter_release_rcu(struct rcu_head *rcu) | |||
638 | { | 579 | { |
639 | struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu); | 580 | struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu); |
640 | 581 | ||
582 | bpf_jit_free(fp); | ||
641 | kfree(fp); | 583 | kfree(fp); |
642 | } | 584 | } |
643 | EXPORT_SYMBOL(sk_filter_release_rcu); | 585 | EXPORT_SYMBOL(sk_filter_release_rcu); |
@@ -672,6 +614,7 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) | |||
672 | 614 | ||
673 | atomic_set(&fp->refcnt, 1); | 615 | atomic_set(&fp->refcnt, 1); |
674 | fp->len = fprog->len; | 616 | fp->len = fprog->len; |
617 | fp->bpf_func = sk_run_filter; | ||
675 | 618 | ||
676 | err = sk_chk_filter(fp->insns, fp->len); | 619 | err = sk_chk_filter(fp->insns, fp->len); |
677 | if (err) { | 620 | if (err) { |
@@ -679,6 +622,8 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) | |||
679 | return err; | 622 | return err; |
680 | } | 623 | } |
681 | 624 | ||
625 | bpf_jit_compile(fp); | ||
626 | |||
682 | old_fp = rcu_dereference_protected(sk->sk_filter, | 627 | old_fp = rcu_dereference_protected(sk->sk_filter, |
683 | sock_owned_by_user(sk)); | 628 | sock_owned_by_user(sk)); |
684 | rcu_assign_pointer(sk->sk_filter, fp); | 629 | rcu_assign_pointer(sk->sk_filter, fp); |
diff --git a/net/core/link_watch.c b/net/core/link_watch.c index 01a1101b5936..a7b342131869 100644 --- a/net/core/link_watch.c +++ b/net/core/link_watch.c | |||
@@ -129,7 +129,7 @@ static void linkwatch_schedule_work(int urgent) | |||
129 | if (!cancel_delayed_work(&linkwatch_work)) | 129 | if (!cancel_delayed_work(&linkwatch_work)) |
130 | return; | 130 | return; |
131 | 131 | ||
132 | /* Otherwise we reschedule it again for immediate exection. */ | 132 | /* Otherwise we reschedule it again for immediate execution. */ |
133 | schedule_delayed_work(&linkwatch_work, 0); | 133 | schedule_delayed_work(&linkwatch_work, 0); |
134 | } | 134 | } |
135 | 135 | ||
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 5ceb257e860c..381813eae46c 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -28,6 +28,7 @@ | |||
28 | static const char fmt_hex[] = "%#x\n"; | 28 | static const char fmt_hex[] = "%#x\n"; |
29 | static const char fmt_long_hex[] = "%#lx\n"; | 29 | static const char fmt_long_hex[] = "%#lx\n"; |
30 | static const char fmt_dec[] = "%d\n"; | 30 | static const char fmt_dec[] = "%d\n"; |
31 | static const char fmt_udec[] = "%u\n"; | ||
31 | static const char fmt_ulong[] = "%lu\n"; | 32 | static const char fmt_ulong[] = "%lu\n"; |
32 | static const char fmt_u64[] = "%llu\n"; | 33 | static const char fmt_u64[] = "%llu\n"; |
33 | 34 | ||
@@ -145,13 +146,10 @@ static ssize_t show_speed(struct device *dev, | |||
145 | if (!rtnl_trylock()) | 146 | if (!rtnl_trylock()) |
146 | return restart_syscall(); | 147 | return restart_syscall(); |
147 | 148 | ||
148 | if (netif_running(netdev) && | 149 | if (netif_running(netdev)) { |
149 | netdev->ethtool_ops && | 150 | struct ethtool_cmd cmd; |
150 | netdev->ethtool_ops->get_settings) { | 151 | if (!dev_ethtool_get_settings(netdev, &cmd)) |
151 | struct ethtool_cmd cmd = { ETHTOOL_GSET }; | 152 | ret = sprintf(buf, fmt_udec, ethtool_cmd_speed(&cmd)); |
152 | |||
153 | if (!netdev->ethtool_ops->get_settings(netdev, &cmd)) | ||
154 | ret = sprintf(buf, fmt_dec, ethtool_cmd_speed(&cmd)); | ||
155 | } | 153 | } |
156 | rtnl_unlock(); | 154 | rtnl_unlock(); |
157 | return ret; | 155 | return ret; |
@@ -166,13 +164,11 @@ static ssize_t show_duplex(struct device *dev, | |||
166 | if (!rtnl_trylock()) | 164 | if (!rtnl_trylock()) |
167 | return restart_syscall(); | 165 | return restart_syscall(); |
168 | 166 | ||
169 | if (netif_running(netdev) && | 167 | if (netif_running(netdev)) { |
170 | netdev->ethtool_ops && | 168 | struct ethtool_cmd cmd; |
171 | netdev->ethtool_ops->get_settings) { | 169 | if (!dev_ethtool_get_settings(netdev, &cmd)) |
172 | struct ethtool_cmd cmd = { ETHTOOL_GSET }; | 170 | ret = sprintf(buf, "%s\n", |
173 | 171 | cmd.duplex ? "full" : "half"); | |
174 | if (!netdev->ethtool_ops->get_settings(netdev, &cmd)) | ||
175 | ret = sprintf(buf, "%s\n", cmd.duplex ? "full" : "half"); | ||
176 | } | 172 | } |
177 | rtnl_unlock(); | 173 | rtnl_unlock(); |
178 | return ret; | 174 | return ret; |
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 3f860261c5ee..1abb50841046 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c | |||
@@ -216,11 +216,14 @@ static void net_free(struct net *net) | |||
216 | kmem_cache_free(net_cachep, net); | 216 | kmem_cache_free(net_cachep, net); |
217 | } | 217 | } |
218 | 218 | ||
219 | static struct net *net_create(void) | 219 | struct net *copy_net_ns(unsigned long flags, struct net *old_net) |
220 | { | 220 | { |
221 | struct net *net; | 221 | struct net *net; |
222 | int rv; | 222 | int rv; |
223 | 223 | ||
224 | if (!(flags & CLONE_NEWNET)) | ||
225 | return get_net(old_net); | ||
226 | |||
224 | net = net_alloc(); | 227 | net = net_alloc(); |
225 | if (!net) | 228 | if (!net) |
226 | return ERR_PTR(-ENOMEM); | 229 | return ERR_PTR(-ENOMEM); |
@@ -239,13 +242,6 @@ static struct net *net_create(void) | |||
239 | return net; | 242 | return net; |
240 | } | 243 | } |
241 | 244 | ||
242 | struct net *copy_net_ns(unsigned long flags, struct net *old_net) | ||
243 | { | ||
244 | if (!(flags & CLONE_NEWNET)) | ||
245 | return get_net(old_net); | ||
246 | return net_create(); | ||
247 | } | ||
248 | |||
249 | static DEFINE_SPINLOCK(cleanup_list_lock); | 245 | static DEFINE_SPINLOCK(cleanup_list_lock); |
250 | static LIST_HEAD(cleanup_list); /* Must hold cleanup_list_lock to touch */ | 246 | static LIST_HEAD(cleanup_list); /* Must hold cleanup_list_lock to touch */ |
251 | 247 | ||
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index 06be2431753e..2d7d6d473781 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
@@ -539,7 +539,7 @@ int __netpoll_rx(struct sk_buff *skb) | |||
539 | { | 539 | { |
540 | int proto, len, ulen; | 540 | int proto, len, ulen; |
541 | int hits = 0; | 541 | int hits = 0; |
542 | struct iphdr *iph; | 542 | const struct iphdr *iph; |
543 | struct udphdr *uh; | 543 | struct udphdr *uh; |
544 | struct netpoll_info *npinfo = skb->dev->npinfo; | 544 | struct netpoll_info *npinfo = skb->dev->npinfo; |
545 | struct netpoll *np, *tmp; | 545 | struct netpoll *np, *tmp; |
@@ -698,32 +698,8 @@ int netpoll_parse_options(struct netpoll *np, char *opt) | |||
698 | 698 | ||
699 | if (*cur != 0) { | 699 | if (*cur != 0) { |
700 | /* MAC address */ | 700 | /* MAC address */ |
701 | if ((delim = strchr(cur, ':')) == NULL) | 701 | if (!mac_pton(cur, np->remote_mac)) |
702 | goto parse_failed; | ||
703 | *delim = 0; | ||
704 | np->remote_mac[0] = simple_strtol(cur, NULL, 16); | ||
705 | cur = delim + 1; | ||
706 | if ((delim = strchr(cur, ':')) == NULL) | ||
707 | goto parse_failed; | ||
708 | *delim = 0; | ||
709 | np->remote_mac[1] = simple_strtol(cur, NULL, 16); | ||
710 | cur = delim + 1; | ||
711 | if ((delim = strchr(cur, ':')) == NULL) | ||
712 | goto parse_failed; | 702 | goto parse_failed; |
713 | *delim = 0; | ||
714 | np->remote_mac[2] = simple_strtol(cur, NULL, 16); | ||
715 | cur = delim + 1; | ||
716 | if ((delim = strchr(cur, ':')) == NULL) | ||
717 | goto parse_failed; | ||
718 | *delim = 0; | ||
719 | np->remote_mac[3] = simple_strtol(cur, NULL, 16); | ||
720 | cur = delim + 1; | ||
721 | if ((delim = strchr(cur, ':')) == NULL) | ||
722 | goto parse_failed; | ||
723 | *delim = 0; | ||
724 | np->remote_mac[4] = simple_strtol(cur, NULL, 16); | ||
725 | cur = delim + 1; | ||
726 | np->remote_mac[5] = simple_strtol(cur, NULL, 16); | ||
727 | } | 703 | } |
728 | 704 | ||
729 | netpoll_print_options(np); | 705 | netpoll_print_options(np); |
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index aeeece72b72f..379270f14771 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c | |||
@@ -449,7 +449,6 @@ static void pktgen_stop(struct pktgen_thread *t); | |||
449 | static void pktgen_clear_counters(struct pktgen_dev *pkt_dev); | 449 | static void pktgen_clear_counters(struct pktgen_dev *pkt_dev); |
450 | 450 | ||
451 | static unsigned int scan_ip6(const char *s, char ip[16]); | 451 | static unsigned int scan_ip6(const char *s, char ip[16]); |
452 | static unsigned int fmt_ip6(char *s, const char ip[16]); | ||
453 | 452 | ||
454 | /* Module parameters, defaults. */ | 453 | /* Module parameters, defaults. */ |
455 | static int pg_count_d __read_mostly = 1000; | 454 | static int pg_count_d __read_mostly = 1000; |
@@ -556,21 +555,13 @@ static int pktgen_if_show(struct seq_file *seq, void *v) | |||
556 | pkt_dev->skb_priority); | 555 | pkt_dev->skb_priority); |
557 | 556 | ||
558 | if (pkt_dev->flags & F_IPV6) { | 557 | if (pkt_dev->flags & F_IPV6) { |
559 | char b1[128], b2[128], b3[128]; | ||
560 | fmt_ip6(b1, pkt_dev->in6_saddr.s6_addr); | ||
561 | fmt_ip6(b2, pkt_dev->min_in6_saddr.s6_addr); | ||
562 | fmt_ip6(b3, pkt_dev->max_in6_saddr.s6_addr); | ||
563 | seq_printf(seq, | 558 | seq_printf(seq, |
564 | " saddr: %s min_saddr: %s max_saddr: %s\n", b1, | 559 | " saddr: %pI6c min_saddr: %pI6c max_saddr: %pI6c\n" |
565 | b2, b3); | 560 | " daddr: %pI6c min_daddr: %pI6c max_daddr: %pI6c\n", |
566 | 561 | &pkt_dev->in6_saddr, | |
567 | fmt_ip6(b1, pkt_dev->in6_daddr.s6_addr); | 562 | &pkt_dev->min_in6_saddr, &pkt_dev->max_in6_saddr, |
568 | fmt_ip6(b2, pkt_dev->min_in6_daddr.s6_addr); | 563 | &pkt_dev->in6_daddr, |
569 | fmt_ip6(b3, pkt_dev->max_in6_daddr.s6_addr); | 564 | &pkt_dev->min_in6_daddr, &pkt_dev->max_in6_daddr); |
570 | seq_printf(seq, | ||
571 | " daddr: %s min_daddr: %s max_daddr: %s\n", b1, | ||
572 | b2, b3); | ||
573 | |||
574 | } else { | 565 | } else { |
575 | seq_printf(seq, | 566 | seq_printf(seq, |
576 | " dst_min: %s dst_max: %s\n", | 567 | " dst_min: %s dst_max: %s\n", |
@@ -706,10 +697,9 @@ static int pktgen_if_show(struct seq_file *seq, void *v) | |||
706 | pkt_dev->cur_src_mac_offset); | 697 | pkt_dev->cur_src_mac_offset); |
707 | 698 | ||
708 | if (pkt_dev->flags & F_IPV6) { | 699 | if (pkt_dev->flags & F_IPV6) { |
709 | char b1[128], b2[128]; | 700 | seq_printf(seq, " cur_saddr: %pI6c cur_daddr: %pI6c\n", |
710 | fmt_ip6(b1, pkt_dev->cur_in6_daddr.s6_addr); | 701 | &pkt_dev->cur_in6_saddr, |
711 | fmt_ip6(b2, pkt_dev->cur_in6_saddr.s6_addr); | 702 | &pkt_dev->cur_in6_daddr); |
712 | seq_printf(seq, " cur_saddr: %s cur_daddr: %s\n", b2, b1); | ||
713 | } else | 703 | } else |
714 | seq_printf(seq, " cur_saddr: 0x%x cur_daddr: 0x%x\n", | 704 | seq_printf(seq, " cur_saddr: 0x%x cur_daddr: 0x%x\n", |
715 | pkt_dev->cur_saddr, pkt_dev->cur_daddr); | 705 | pkt_dev->cur_saddr, pkt_dev->cur_daddr); |
@@ -1309,7 +1299,7 @@ static ssize_t pktgen_if_write(struct file *file, | |||
1309 | buf[len] = 0; | 1299 | buf[len] = 0; |
1310 | 1300 | ||
1311 | scan_ip6(buf, pkt_dev->in6_daddr.s6_addr); | 1301 | scan_ip6(buf, pkt_dev->in6_daddr.s6_addr); |
1312 | fmt_ip6(buf, pkt_dev->in6_daddr.s6_addr); | 1302 | snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->in6_daddr); |
1313 | 1303 | ||
1314 | ipv6_addr_copy(&pkt_dev->cur_in6_daddr, &pkt_dev->in6_daddr); | 1304 | ipv6_addr_copy(&pkt_dev->cur_in6_daddr, &pkt_dev->in6_daddr); |
1315 | 1305 | ||
@@ -1332,7 +1322,7 @@ static ssize_t pktgen_if_write(struct file *file, | |||
1332 | buf[len] = 0; | 1322 | buf[len] = 0; |
1333 | 1323 | ||
1334 | scan_ip6(buf, pkt_dev->min_in6_daddr.s6_addr); | 1324 | scan_ip6(buf, pkt_dev->min_in6_daddr.s6_addr); |
1335 | fmt_ip6(buf, pkt_dev->min_in6_daddr.s6_addr); | 1325 | snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->min_in6_daddr); |
1336 | 1326 | ||
1337 | ipv6_addr_copy(&pkt_dev->cur_in6_daddr, | 1327 | ipv6_addr_copy(&pkt_dev->cur_in6_daddr, |
1338 | &pkt_dev->min_in6_daddr); | 1328 | &pkt_dev->min_in6_daddr); |
@@ -1355,7 +1345,7 @@ static ssize_t pktgen_if_write(struct file *file, | |||
1355 | buf[len] = 0; | 1345 | buf[len] = 0; |
1356 | 1346 | ||
1357 | scan_ip6(buf, pkt_dev->max_in6_daddr.s6_addr); | 1347 | scan_ip6(buf, pkt_dev->max_in6_daddr.s6_addr); |
1358 | fmt_ip6(buf, pkt_dev->max_in6_daddr.s6_addr); | 1348 | snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->max_in6_daddr); |
1359 | 1349 | ||
1360 | if (debug) | 1350 | if (debug) |
1361 | printk(KERN_DEBUG "pktgen: dst6_max set to: %s\n", buf); | 1351 | printk(KERN_DEBUG "pktgen: dst6_max set to: %s\n", buf); |
@@ -1376,7 +1366,7 @@ static ssize_t pktgen_if_write(struct file *file, | |||
1376 | buf[len] = 0; | 1366 | buf[len] = 0; |
1377 | 1367 | ||
1378 | scan_ip6(buf, pkt_dev->in6_saddr.s6_addr); | 1368 | scan_ip6(buf, pkt_dev->in6_saddr.s6_addr); |
1379 | fmt_ip6(buf, pkt_dev->in6_saddr.s6_addr); | 1369 | snprintf(buf, sizeof(buf), "%pI6c", &pkt_dev->in6_saddr); |
1380 | 1370 | ||
1381 | ipv6_addr_copy(&pkt_dev->cur_in6_saddr, &pkt_dev->in6_saddr); | 1371 | ipv6_addr_copy(&pkt_dev->cur_in6_saddr, &pkt_dev->in6_saddr); |
1382 | 1372 | ||
@@ -1430,11 +1420,6 @@ static ssize_t pktgen_if_write(struct file *file, | |||
1430 | return count; | 1420 | return count; |
1431 | } | 1421 | } |
1432 | if (!strcmp(name, "dst_mac")) { | 1422 | if (!strcmp(name, "dst_mac")) { |
1433 | char *v = valstr; | ||
1434 | unsigned char old_dmac[ETH_ALEN]; | ||
1435 | unsigned char *m = pkt_dev->dst_mac; | ||
1436 | memcpy(old_dmac, pkt_dev->dst_mac, ETH_ALEN); | ||
1437 | |||
1438 | len = strn_len(&user_buffer[i], sizeof(valstr) - 1); | 1423 | len = strn_len(&user_buffer[i], sizeof(valstr) - 1); |
1439 | if (len < 0) | 1424 | if (len < 0) |
1440 | return len; | 1425 | return len; |
@@ -1442,35 +1427,16 @@ static ssize_t pktgen_if_write(struct file *file, | |||
1442 | memset(valstr, 0, sizeof(valstr)); | 1427 | memset(valstr, 0, sizeof(valstr)); |
1443 | if (copy_from_user(valstr, &user_buffer[i], len)) | 1428 | if (copy_from_user(valstr, &user_buffer[i], len)) |
1444 | return -EFAULT; | 1429 | return -EFAULT; |
1445 | i += len; | ||
1446 | |||
1447 | for (*m = 0; *v && m < pkt_dev->dst_mac + 6; v++) { | ||
1448 | int value; | ||
1449 | |||
1450 | value = hex_to_bin(*v); | ||
1451 | if (value >= 0) | ||
1452 | *m = *m * 16 + value; | ||
1453 | |||
1454 | if (*v == ':') { | ||
1455 | m++; | ||
1456 | *m = 0; | ||
1457 | } | ||
1458 | } | ||
1459 | 1430 | ||
1431 | if (!mac_pton(valstr, pkt_dev->dst_mac)) | ||
1432 | return -EINVAL; | ||
1460 | /* Set up Dest MAC */ | 1433 | /* Set up Dest MAC */ |
1461 | if (compare_ether_addr(old_dmac, pkt_dev->dst_mac)) | 1434 | memcpy(&pkt_dev->hh[0], pkt_dev->dst_mac, ETH_ALEN); |
1462 | memcpy(&(pkt_dev->hh[0]), pkt_dev->dst_mac, ETH_ALEN); | ||
1463 | 1435 | ||
1464 | sprintf(pg_result, "OK: dstmac"); | 1436 | sprintf(pg_result, "OK: dstmac %pM", pkt_dev->dst_mac); |
1465 | return count; | 1437 | return count; |
1466 | } | 1438 | } |
1467 | if (!strcmp(name, "src_mac")) { | 1439 | if (!strcmp(name, "src_mac")) { |
1468 | char *v = valstr; | ||
1469 | unsigned char old_smac[ETH_ALEN]; | ||
1470 | unsigned char *m = pkt_dev->src_mac; | ||
1471 | |||
1472 | memcpy(old_smac, pkt_dev->src_mac, ETH_ALEN); | ||
1473 | |||
1474 | len = strn_len(&user_buffer[i], sizeof(valstr) - 1); | 1440 | len = strn_len(&user_buffer[i], sizeof(valstr) - 1); |
1475 | if (len < 0) | 1441 | if (len < 0) |
1476 | return len; | 1442 | return len; |
@@ -1478,26 +1444,13 @@ static ssize_t pktgen_if_write(struct file *file, | |||
1478 | memset(valstr, 0, sizeof(valstr)); | 1444 | memset(valstr, 0, sizeof(valstr)); |
1479 | if (copy_from_user(valstr, &user_buffer[i], len)) | 1445 | if (copy_from_user(valstr, &user_buffer[i], len)) |
1480 | return -EFAULT; | 1446 | return -EFAULT; |
1481 | i += len; | ||
1482 | |||
1483 | for (*m = 0; *v && m < pkt_dev->src_mac + 6; v++) { | ||
1484 | int value; | ||
1485 | |||
1486 | value = hex_to_bin(*v); | ||
1487 | if (value >= 0) | ||
1488 | *m = *m * 16 + value; | ||
1489 | |||
1490 | if (*v == ':') { | ||
1491 | m++; | ||
1492 | *m = 0; | ||
1493 | } | ||
1494 | } | ||
1495 | 1447 | ||
1448 | if (!mac_pton(valstr, pkt_dev->src_mac)) | ||
1449 | return -EINVAL; | ||
1496 | /* Set up Src MAC */ | 1450 | /* Set up Src MAC */ |
1497 | if (compare_ether_addr(old_smac, pkt_dev->src_mac)) | 1451 | memcpy(&pkt_dev->hh[6], pkt_dev->src_mac, ETH_ALEN); |
1498 | memcpy(&(pkt_dev->hh[6]), pkt_dev->src_mac, ETH_ALEN); | ||
1499 | 1452 | ||
1500 | sprintf(pg_result, "OK: srcmac"); | 1453 | sprintf(pg_result, "OK: srcmac %pM", pkt_dev->src_mac); |
1501 | return count; | 1454 | return count; |
1502 | } | 1455 | } |
1503 | 1456 | ||
@@ -2514,7 +2467,6 @@ static int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev) | |||
2514 | { | 2467 | { |
2515 | struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x; | 2468 | struct xfrm_state *x = pkt_dev->flows[pkt_dev->curfl].x; |
2516 | int err = 0; | 2469 | int err = 0; |
2517 | struct iphdr *iph; | ||
2518 | 2470 | ||
2519 | if (!x) | 2471 | if (!x) |
2520 | return 0; | 2472 | return 0; |
@@ -2524,7 +2476,6 @@ static int pktgen_output_ipsec(struct sk_buff *skb, struct pktgen_dev *pkt_dev) | |||
2524 | return 0; | 2476 | return 0; |
2525 | 2477 | ||
2526 | spin_lock(&x->lock); | 2478 | spin_lock(&x->lock); |
2527 | iph = ip_hdr(skb); | ||
2528 | 2479 | ||
2529 | err = x->outer_mode->output(x, skb); | 2480 | err = x->outer_mode->output(x, skb); |
2530 | if (err) | 2481 | if (err) |
@@ -2624,6 +2575,7 @@ static void pktgen_finalize_skb(struct pktgen_dev *pkt_dev, struct sk_buff *skb, | |||
2624 | } else { | 2575 | } else { |
2625 | int frags = pkt_dev->nfrags; | 2576 | int frags = pkt_dev->nfrags; |
2626 | int i, len; | 2577 | int i, len; |
2578 | int frag_len; | ||
2627 | 2579 | ||
2628 | 2580 | ||
2629 | if (frags > MAX_SKB_FRAGS) | 2581 | if (frags > MAX_SKB_FRAGS) |
@@ -2635,6 +2587,8 @@ static void pktgen_finalize_skb(struct pktgen_dev *pkt_dev, struct sk_buff *skb, | |||
2635 | } | 2587 | } |
2636 | 2588 | ||
2637 | i = 0; | 2589 | i = 0; |
2590 | frag_len = (datalen/frags) < PAGE_SIZE ? | ||
2591 | (datalen/frags) : PAGE_SIZE; | ||
2638 | while (datalen > 0) { | 2592 | while (datalen > 0) { |
2639 | if (unlikely(!pkt_dev->page)) { | 2593 | if (unlikely(!pkt_dev->page)) { |
2640 | int node = numa_node_id(); | 2594 | int node = numa_node_id(); |
@@ -2648,38 +2602,18 @@ static void pktgen_finalize_skb(struct pktgen_dev *pkt_dev, struct sk_buff *skb, | |||
2648 | skb_shinfo(skb)->frags[i].page = pkt_dev->page; | 2602 | skb_shinfo(skb)->frags[i].page = pkt_dev->page; |
2649 | get_page(pkt_dev->page); | 2603 | get_page(pkt_dev->page); |
2650 | skb_shinfo(skb)->frags[i].page_offset = 0; | 2604 | skb_shinfo(skb)->frags[i].page_offset = 0; |
2651 | skb_shinfo(skb)->frags[i].size = | 2605 | /*last fragment, fill rest of data*/ |
2652 | (datalen < PAGE_SIZE ? datalen : PAGE_SIZE); | 2606 | if (i == (frags - 1)) |
2607 | skb_shinfo(skb)->frags[i].size = | ||
2608 | (datalen < PAGE_SIZE ? datalen : PAGE_SIZE); | ||
2609 | else | ||
2610 | skb_shinfo(skb)->frags[i].size = frag_len; | ||
2653 | datalen -= skb_shinfo(skb)->frags[i].size; | 2611 | datalen -= skb_shinfo(skb)->frags[i].size; |
2654 | skb->len += skb_shinfo(skb)->frags[i].size; | 2612 | skb->len += skb_shinfo(skb)->frags[i].size; |
2655 | skb->data_len += skb_shinfo(skb)->frags[i].size; | 2613 | skb->data_len += skb_shinfo(skb)->frags[i].size; |
2656 | i++; | 2614 | i++; |
2657 | skb_shinfo(skb)->nr_frags = i; | 2615 | skb_shinfo(skb)->nr_frags = i; |
2658 | } | 2616 | } |
2659 | |||
2660 | while (i < frags) { | ||
2661 | int rem; | ||
2662 | |||
2663 | if (i == 0) | ||
2664 | break; | ||
2665 | |||
2666 | rem = skb_shinfo(skb)->frags[i - 1].size / 2; | ||
2667 | if (rem == 0) | ||
2668 | break; | ||
2669 | |||
2670 | skb_shinfo(skb)->frags[i - 1].size -= rem; | ||
2671 | |||
2672 | skb_shinfo(skb)->frags[i] = | ||
2673 | skb_shinfo(skb)->frags[i - 1]; | ||
2674 | get_page(skb_shinfo(skb)->frags[i].page); | ||
2675 | skb_shinfo(skb)->frags[i].page = | ||
2676 | skb_shinfo(skb)->frags[i - 1].page; | ||
2677 | skb_shinfo(skb)->frags[i].page_offset += | ||
2678 | skb_shinfo(skb)->frags[i - 1].size; | ||
2679 | skb_shinfo(skb)->frags[i].size = rem; | ||
2680 | i++; | ||
2681 | skb_shinfo(skb)->nr_frags = i; | ||
2682 | } | ||
2683 | } | 2617 | } |
2684 | 2618 | ||
2685 | /* Stamp the time, and sequence number, | 2619 | /* Stamp the time, and sequence number, |
@@ -2917,79 +2851,6 @@ static unsigned int scan_ip6(const char *s, char ip[16]) | |||
2917 | return len; | 2851 | return len; |
2918 | } | 2852 | } |
2919 | 2853 | ||
2920 | static char tohex(char hexdigit) | ||
2921 | { | ||
2922 | return hexdigit > 9 ? hexdigit + 'a' - 10 : hexdigit + '0'; | ||
2923 | } | ||
2924 | |||
2925 | static int fmt_xlong(char *s, unsigned int i) | ||
2926 | { | ||
2927 | char *bak = s; | ||
2928 | *s = tohex((i >> 12) & 0xf); | ||
2929 | if (s != bak || *s != '0') | ||
2930 | ++s; | ||
2931 | *s = tohex((i >> 8) & 0xf); | ||
2932 | if (s != bak || *s != '0') | ||
2933 | ++s; | ||
2934 | *s = tohex((i >> 4) & 0xf); | ||
2935 | if (s != bak || *s != '0') | ||
2936 | ++s; | ||
2937 | *s = tohex(i & 0xf); | ||
2938 | return s - bak + 1; | ||
2939 | } | ||
2940 | |||
2941 | static unsigned int fmt_ip6(char *s, const char ip[16]) | ||
2942 | { | ||
2943 | unsigned int len; | ||
2944 | unsigned int i; | ||
2945 | unsigned int temp; | ||
2946 | unsigned int compressing; | ||
2947 | int j; | ||
2948 | |||
2949 | len = 0; | ||
2950 | compressing = 0; | ||
2951 | for (j = 0; j < 16; j += 2) { | ||
2952 | |||
2953 | #ifdef V4MAPPEDPREFIX | ||
2954 | if (j == 12 && !memcmp(ip, V4mappedprefix, 12)) { | ||
2955 | inet_ntoa_r(*(struct in_addr *)(ip + 12), s); | ||
2956 | temp = strlen(s); | ||
2957 | return len + temp; | ||
2958 | } | ||
2959 | #endif | ||
2960 | temp = ((unsigned long)(unsigned char)ip[j] << 8) + | ||
2961 | (unsigned long)(unsigned char)ip[j + 1]; | ||
2962 | if (temp == 0) { | ||
2963 | if (!compressing) { | ||
2964 | compressing = 1; | ||
2965 | if (j == 0) { | ||
2966 | *s++ = ':'; | ||
2967 | ++len; | ||
2968 | } | ||
2969 | } | ||
2970 | } else { | ||
2971 | if (compressing) { | ||
2972 | compressing = 0; | ||
2973 | *s++ = ':'; | ||
2974 | ++len; | ||
2975 | } | ||
2976 | i = fmt_xlong(s, temp); | ||
2977 | len += i; | ||
2978 | s += i; | ||
2979 | if (j < 14) { | ||
2980 | *s++ = ':'; | ||
2981 | ++len; | ||
2982 | } | ||
2983 | } | ||
2984 | } | ||
2985 | if (compressing) { | ||
2986 | *s++ = ':'; | ||
2987 | ++len; | ||
2988 | } | ||
2989 | *s = 0; | ||
2990 | return len; | ||
2991 | } | ||
2992 | |||
2993 | static struct sk_buff *fill_packet_ipv6(struct net_device *odev, | 2854 | static struct sk_buff *fill_packet_ipv6(struct net_device *odev, |
2994 | struct pktgen_dev *pkt_dev) | 2855 | struct pktgen_dev *pkt_dev) |
2995 | { | 2856 | { |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 49f7ea5b4c75..d2ba2597c75a 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -196,7 +196,7 @@ EXPORT_SYMBOL_GPL(__rtnl_register); | |||
196 | * as failure of this function is very unlikely, it can only happen due | 196 | * as failure of this function is very unlikely, it can only happen due |
197 | * to lack of memory when allocating the chain to store all message | 197 | * to lack of memory when allocating the chain to store all message |
198 | * handlers for a protocol. Meant for use in init functions where lack | 198 | * handlers for a protocol. Meant for use in init functions where lack |
199 | * of memory implies no sense in continueing. | 199 | * of memory implies no sense in continuing. |
200 | */ | 200 | */ |
201 | void rtnl_register(int protocol, int msgtype, | 201 | void rtnl_register(int protocol, int msgtype, |
202 | rtnl_doit_func doit, rtnl_dumpit_func dumpit) | 202 | rtnl_doit_func doit, rtnl_dumpit_func dumpit) |
@@ -1007,10 +1007,11 @@ static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | |||
1007 | s_h = cb->args[0]; | 1007 | s_h = cb->args[0]; |
1008 | s_idx = cb->args[1]; | 1008 | s_idx = cb->args[1]; |
1009 | 1009 | ||
1010 | rcu_read_lock(); | ||
1010 | for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { | 1011 | for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { |
1011 | idx = 0; | 1012 | idx = 0; |
1012 | head = &net->dev_index_head[h]; | 1013 | head = &net->dev_index_head[h]; |
1013 | hlist_for_each_entry(dev, node, head, index_hlist) { | 1014 | hlist_for_each_entry_rcu(dev, node, head, index_hlist) { |
1014 | if (idx < s_idx) | 1015 | if (idx < s_idx) |
1015 | goto cont; | 1016 | goto cont; |
1016 | if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK, | 1017 | if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK, |
@@ -1023,6 +1024,7 @@ cont: | |||
1023 | } | 1024 | } |
1024 | } | 1025 | } |
1025 | out: | 1026 | out: |
1027 | rcu_read_unlock(); | ||
1026 | cb->args[1] = idx; | 1028 | cb->args[1] = idx; |
1027 | cb->args[0] = h; | 1029 | cb->args[0] = h; |
1028 | 1030 | ||
@@ -1440,7 +1442,7 @@ static int do_setlink(struct net_device *dev, struct ifinfomsg *ifm, | |||
1440 | errout: | 1442 | errout: |
1441 | if (err < 0 && modified && net_ratelimit()) | 1443 | if (err < 0 && modified && net_ratelimit()) |
1442 | printk(KERN_WARNING "A link change request failed with " | 1444 | printk(KERN_WARNING "A link change request failed with " |
1443 | "some changes comitted already. Interface %s may " | 1445 | "some changes committed already. Interface %s may " |
1444 | "have been left with an inconsistent configuration, " | 1446 | "have been left with an inconsistent configuration, " |
1445 | "please check.\n", dev->name); | 1447 | "please check.\n", dev->name); |
1446 | 1448 | ||
@@ -1499,6 +1501,7 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
1499 | char ifname[IFNAMSIZ]; | 1501 | char ifname[IFNAMSIZ]; |
1500 | struct nlattr *tb[IFLA_MAX+1]; | 1502 | struct nlattr *tb[IFLA_MAX+1]; |
1501 | int err; | 1503 | int err; |
1504 | LIST_HEAD(list_kill); | ||
1502 | 1505 | ||
1503 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); | 1506 | err = nlmsg_parse(nlh, sizeof(*ifm), tb, IFLA_MAX, ifla_policy); |
1504 | if (err < 0) | 1507 | if (err < 0) |
@@ -1522,7 +1525,9 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg) | |||
1522 | if (!ops) | 1525 | if (!ops) |
1523 | return -EOPNOTSUPP; | 1526 | return -EOPNOTSUPP; |
1524 | 1527 | ||
1525 | ops->dellink(dev, NULL); | 1528 | ops->dellink(dev, &list_kill); |
1529 | unregister_netdevice_many(&list_kill); | ||
1530 | list_del(&list_kill); | ||
1526 | return 0; | 1531 | return 0; |
1527 | } | 1532 | } |
1528 | 1533 | ||
@@ -1570,12 +1575,6 @@ struct net_device *rtnl_create_link(struct net *src_net, struct net *net, | |||
1570 | dev->rtnl_link_state = RTNL_LINK_INITIALIZING; | 1575 | dev->rtnl_link_state = RTNL_LINK_INITIALIZING; |
1571 | dev->real_num_tx_queues = real_num_queues; | 1576 | dev->real_num_tx_queues = real_num_queues; |
1572 | 1577 | ||
1573 | if (strchr(dev->name, '%')) { | ||
1574 | err = dev_alloc_name(dev, dev->name); | ||
1575 | if (err < 0) | ||
1576 | goto err_free; | ||
1577 | } | ||
1578 | |||
1579 | if (tb[IFLA_MTU]) | 1578 | if (tb[IFLA_MTU]) |
1580 | dev->mtu = nla_get_u32(tb[IFLA_MTU]); | 1579 | dev->mtu = nla_get_u32(tb[IFLA_MTU]); |
1581 | if (tb[IFLA_ADDRESS]) | 1580 | if (tb[IFLA_ADDRESS]) |
@@ -1595,8 +1594,6 @@ struct net_device *rtnl_create_link(struct net *src_net, struct net *net, | |||
1595 | 1594 | ||
1596 | return dev; | 1595 | return dev; |
1597 | 1596 | ||
1598 | err_free: | ||
1599 | free_netdev(dev); | ||
1600 | err: | 1597 | err: |
1601 | return ERR_PTR(err); | 1598 | return ERR_PTR(err); |
1602 | } | 1599 | } |
@@ -1879,7 +1876,6 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
1879 | int min_len; | 1876 | int min_len; |
1880 | int family; | 1877 | int family; |
1881 | int type; | 1878 | int type; |
1882 | int err; | ||
1883 | 1879 | ||
1884 | type = nlh->nlmsg_type; | 1880 | type = nlh->nlmsg_type; |
1885 | if (type > RTM_MAX) | 1881 | if (type > RTM_MAX) |
@@ -1906,11 +1902,8 @@ static int rtnetlink_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
1906 | if (dumpit == NULL) | 1902 | if (dumpit == NULL) |
1907 | return -EOPNOTSUPP; | 1903 | return -EOPNOTSUPP; |
1908 | 1904 | ||
1909 | __rtnl_unlock(); | ||
1910 | rtnl = net->rtnl; | 1905 | rtnl = net->rtnl; |
1911 | err = netlink_dump_start(rtnl, skb, nlh, dumpit, NULL); | 1906 | return netlink_dump_start(rtnl, skb, nlh, dumpit, NULL); |
1912 | rtnl_lock(); | ||
1913 | return err; | ||
1914 | } | 1907 | } |
1915 | 1908 | ||
1916 | memset(rta_buf, 0, (rtattr_max * sizeof(struct rtattr *))); | 1909 | memset(rta_buf, 0, (rtattr_max * sizeof(struct rtattr *))); |
@@ -1980,7 +1973,7 @@ static int __net_init rtnetlink_net_init(struct net *net) | |||
1980 | { | 1973 | { |
1981 | struct sock *sk; | 1974 | struct sock *sk; |
1982 | sk = netlink_kernel_create(net, NETLINK_ROUTE, RTNLGRP_MAX, | 1975 | sk = netlink_kernel_create(net, NETLINK_ROUTE, RTNLGRP_MAX, |
1983 | rtnetlink_rcv, &rtnl_mutex, THIS_MODULE); | 1976 | rtnetlink_rcv, NULL, THIS_MODULE); |
1984 | if (!sk) | 1977 | if (!sk) |
1985 | return -ENOMEM; | 1978 | return -ENOMEM; |
1986 | net->rtnl = sk; | 1979 | net->rtnl = sk; |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 801dd08908f9..7ebeed0a877c 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -2267,7 +2267,7 @@ EXPORT_SYMBOL(skb_prepare_seq_read); | |||
2267 | * of bytes already consumed and the next call to | 2267 | * of bytes already consumed and the next call to |
2268 | * skb_seq_read() will return the remaining part of the block. | 2268 | * skb_seq_read() will return the remaining part of the block. |
2269 | * | 2269 | * |
2270 | * Note 1: The size of each block of data returned can be arbitary, | 2270 | * Note 1: The size of each block of data returned can be arbitrary, |
2271 | * this limitation is the cost for zerocopy seqeuental | 2271 | * this limitation is the cost for zerocopy seqeuental |
2272 | * reads of potentially non linear data. | 2272 | * reads of potentially non linear data. |
2273 | * | 2273 | * |
diff --git a/net/core/sock.c b/net/core/sock.c index 7dfed792434d..6e819780c232 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -215,7 +215,7 @@ __u32 sysctl_rmem_max __read_mostly = SK_RMEM_MAX; | |||
215 | __u32 sysctl_wmem_default __read_mostly = SK_WMEM_MAX; | 215 | __u32 sysctl_wmem_default __read_mostly = SK_WMEM_MAX; |
216 | __u32 sysctl_rmem_default __read_mostly = SK_RMEM_MAX; | 216 | __u32 sysctl_rmem_default __read_mostly = SK_RMEM_MAX; |
217 | 217 | ||
218 | /* Maximal space eaten by iovec or ancilliary data plus some space */ | 218 | /* Maximal space eaten by iovec or ancillary data plus some space */ |
219 | int sysctl_optmem_max __read_mostly = sizeof(unsigned long)*(2*UIO_MAXIOV+512); | 219 | int sysctl_optmem_max __read_mostly = sizeof(unsigned long)*(2*UIO_MAXIOV+512); |
220 | EXPORT_SYMBOL(sysctl_optmem_max); | 220 | EXPORT_SYMBOL(sysctl_optmem_max); |
221 | 221 | ||
@@ -1175,7 +1175,7 @@ static void __sk_free(struct sock *sk) | |||
1175 | void sk_free(struct sock *sk) | 1175 | void sk_free(struct sock *sk) |
1176 | { | 1176 | { |
1177 | /* | 1177 | /* |
1178 | * We substract one from sk_wmem_alloc and can know if | 1178 | * We subtract one from sk_wmem_alloc and can know if |
1179 | * some packets are still in some tx queue. | 1179 | * some packets are still in some tx queue. |
1180 | * If not null, sock_wfree() will call __sk_free(sk) later | 1180 | * If not null, sock_wfree() will call __sk_free(sk) later |
1181 | */ | 1181 | */ |
@@ -1185,10 +1185,10 @@ void sk_free(struct sock *sk) | |||
1185 | EXPORT_SYMBOL(sk_free); | 1185 | EXPORT_SYMBOL(sk_free); |
1186 | 1186 | ||
1187 | /* | 1187 | /* |
1188 | * Last sock_put should drop referrence to sk->sk_net. It has already | 1188 | * Last sock_put should drop reference to sk->sk_net. It has already |
1189 | * been dropped in sk_change_net. Taking referrence to stopping namespace | 1189 | * been dropped in sk_change_net. Taking reference to stopping namespace |
1190 | * is not an option. | 1190 | * is not an option. |
1191 | * Take referrence to a socket to remove it from hash _alive_ and after that | 1191 | * Take reference to a socket to remove it from hash _alive_ and after that |
1192 | * destroy it in the context of init_net. | 1192 | * destroy it in the context of init_net. |
1193 | */ | 1193 | */ |
1194 | void sk_release_kernel(struct sock *sk) | 1194 | void sk_release_kernel(struct sock *sk) |
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c index 385b6095fdc4..a829e3f60aeb 100644 --- a/net/core/sysctl_net_core.c +++ b/net/core/sysctl_net_core.c | |||
@@ -122,6 +122,15 @@ static struct ctl_table net_core_table[] = { | |||
122 | .mode = 0644, | 122 | .mode = 0644, |
123 | .proc_handler = proc_dointvec | 123 | .proc_handler = proc_dointvec |
124 | }, | 124 | }, |
125 | #ifdef CONFIG_BPF_JIT | ||
126 | { | ||
127 | .procname = "bpf_jit_enable", | ||
128 | .data = &bpf_jit_enable, | ||
129 | .maxlen = sizeof(int), | ||
130 | .mode = 0644, | ||
131 | .proc_handler = proc_dointvec | ||
132 | }, | ||
133 | #endif | ||
125 | { | 134 | { |
126 | .procname = "netdev_tstamp_prequeue", | 135 | .procname = "netdev_tstamp_prequeue", |
127 | .data = &netdev_tstamp_prequeue, | 136 | .data = &netdev_tstamp_prequeue, |
diff --git a/net/core/utils.c b/net/core/utils.c index 5fea0ab21902..2012bc797f9c 100644 --- a/net/core/utils.c +++ b/net/core/utils.c | |||
@@ -296,3 +296,27 @@ void inet_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb, | |||
296 | csum_unfold(*sum))); | 296 | csum_unfold(*sum))); |
297 | } | 297 | } |
298 | EXPORT_SYMBOL(inet_proto_csum_replace4); | 298 | EXPORT_SYMBOL(inet_proto_csum_replace4); |
299 | |||
300 | int mac_pton(const char *s, u8 *mac) | ||
301 | { | ||
302 | int i; | ||
303 | |||
304 | /* XX:XX:XX:XX:XX:XX */ | ||
305 | if (strlen(s) < 3 * ETH_ALEN - 1) | ||
306 | return 0; | ||
307 | |||
308 | /* Don't dirty result unless string is valid MAC. */ | ||
309 | for (i = 0; i < ETH_ALEN; i++) { | ||
310 | if (!strchr("0123456789abcdefABCDEF", s[i * 3])) | ||
311 | return 0; | ||
312 | if (!strchr("0123456789abcdefABCDEF", s[i * 3 + 1])) | ||
313 | return 0; | ||
314 | if (i != ETH_ALEN - 1 && s[i * 3 + 2] != ':') | ||
315 | return 0; | ||
316 | } | ||
317 | for (i = 0; i < ETH_ALEN; i++) { | ||
318 | mac[i] = (hex_to_bin(s[i * 3]) << 4) | hex_to_bin(s[i * 3 + 1]); | ||
319 | } | ||
320 | return 1; | ||
321 | } | ||
322 | EXPORT_SYMBOL(mac_pton); | ||
diff --git a/net/dccp/ipv4.c b/net/dccp/ipv4.c index ae451c6d83ba..46b15e9e9b57 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 | __be16 orig_sport, orig_dport; |
47 | struct rtable *rt; | ||
48 | __be32 daddr, nexthop; | 47 | __be32 daddr, nexthop; |
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,15 +59,19 @@ 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 | orig_sport = inet->inet_sport; | 71 | orig_sport = inet->inet_sport; |
67 | orig_dport = usin->sin_port; | 72 | orig_dport = usin->sin_port; |
68 | rt = ip_route_connect(nexthop, inet->inet_saddr, | 73 | fl4 = &inet->cork.fl.u.ip4; |
74 | rt = ip_route_connect(fl4, nexthop, inet->inet_saddr, | ||
69 | RT_CONN_FLAGS(sk), sk->sk_bound_dev_if, | 75 | RT_CONN_FLAGS(sk), sk->sk_bound_dev_if, |
70 | IPPROTO_DCCP, | 76 | IPPROTO_DCCP, |
71 | orig_sport, orig_dport, sk, true); | 77 | orig_sport, orig_dport, sk, true); |
@@ -77,19 +83,19 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
77 | return -ENETUNREACH; | 83 | return -ENETUNREACH; |
78 | } | 84 | } |
79 | 85 | ||
80 | if (inet->opt == NULL || !inet->opt->srr) | 86 | if (inet_opt == NULL || !inet_opt->opt.srr) |
81 | daddr = rt->rt_dst; | 87 | daddr = fl4->daddr; |
82 | 88 | ||
83 | if (inet->inet_saddr == 0) | 89 | if (inet->inet_saddr == 0) |
84 | inet->inet_saddr = rt->rt_src; | 90 | inet->inet_saddr = fl4->saddr; |
85 | inet->inet_rcv_saddr = inet->inet_saddr; | 91 | inet->inet_rcv_saddr = inet->inet_saddr; |
86 | 92 | ||
87 | inet->inet_dport = usin->sin_port; | 93 | inet->inet_dport = usin->sin_port; |
88 | inet->inet_daddr = daddr; | 94 | inet->inet_daddr = daddr; |
89 | 95 | ||
90 | inet_csk(sk)->icsk_ext_hdr_len = 0; | 96 | inet_csk(sk)->icsk_ext_hdr_len = 0; |
91 | if (inet->opt != NULL) | 97 | if (inet_opt) |
92 | inet_csk(sk)->icsk_ext_hdr_len = inet->opt->optlen; | 98 | inet_csk(sk)->icsk_ext_hdr_len = inet_opt->opt.optlen; |
93 | /* | 99 | /* |
94 | * Socket identity is still unknown (sport may be zero). | 100 | * Socket identity is still unknown (sport may be zero). |
95 | * However we set state to DCCP_REQUESTING and not releasing socket | 101 | * However we set state to DCCP_REQUESTING and not releasing socket |
@@ -101,8 +107,7 @@ int dccp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
101 | if (err != 0) | 107 | if (err != 0) |
102 | goto failure; | 108 | goto failure; |
103 | 109 | ||
104 | rt = ip_route_newports(rt, IPPROTO_DCCP, | 110 | rt = ip_route_newports(fl4, rt, orig_sport, orig_dport, |
105 | orig_sport, orig_dport, | ||
106 | inet->inet_sport, inet->inet_dport, sk); | 111 | inet->inet_sport, inet->inet_dport, sk); |
107 | if (IS_ERR(rt)) { | 112 | if (IS_ERR(rt)) { |
108 | rt = NULL; | 113 | rt = NULL; |
@@ -391,32 +396,30 @@ struct sock *dccp_v4_request_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
391 | if (sk_acceptq_is_full(sk)) | 396 | if (sk_acceptq_is_full(sk)) |
392 | goto exit_overflow; | 397 | goto exit_overflow; |
393 | 398 | ||
394 | if (dst == NULL && (dst = inet_csk_route_req(sk, req)) == NULL) | ||
395 | goto exit; | ||
396 | |||
397 | newsk = dccp_create_openreq_child(sk, req, skb); | 399 | newsk = dccp_create_openreq_child(sk, req, skb); |
398 | if (newsk == NULL) | 400 | if (newsk == NULL) |
399 | goto exit_nonewsk; | 401 | goto exit_nonewsk; |
400 | 402 | ||
401 | sk_setup_caps(newsk, dst); | ||
402 | |||
403 | newinet = inet_sk(newsk); | 403 | newinet = inet_sk(newsk); |
404 | ireq = inet_rsk(req); | 404 | ireq = inet_rsk(req); |
405 | newinet->inet_daddr = ireq->rmt_addr; | 405 | newinet->inet_daddr = ireq->rmt_addr; |
406 | newinet->inet_rcv_saddr = ireq->loc_addr; | 406 | newinet->inet_rcv_saddr = ireq->loc_addr; |
407 | newinet->inet_saddr = ireq->loc_addr; | 407 | newinet->inet_saddr = ireq->loc_addr; |
408 | newinet->opt = ireq->opt; | 408 | newinet->inet_opt = ireq->opt; |
409 | ireq->opt = NULL; | 409 | ireq->opt = NULL; |
410 | newinet->mc_index = inet_iif(skb); | 410 | newinet->mc_index = inet_iif(skb); |
411 | newinet->mc_ttl = ip_hdr(skb)->ttl; | 411 | newinet->mc_ttl = ip_hdr(skb)->ttl; |
412 | newinet->inet_id = jiffies; | 412 | newinet->inet_id = jiffies; |
413 | 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 | |||
414 | dccp_sync_mss(newsk, dst_mtu(dst)); | 419 | dccp_sync_mss(newsk, dst_mtu(dst)); |
415 | 420 | ||
416 | if (__inet_inherit_port(sk, newsk) < 0) { | 421 | if (__inet_inherit_port(sk, newsk) < 0) |
417 | sock_put(newsk); | 422 | goto put_and_exit; |
418 | goto exit; | ||
419 | } | ||
420 | __inet_hash_nolisten(newsk, NULL); | 423 | __inet_hash_nolisten(newsk, NULL); |
421 | 424 | ||
422 | return newsk; | 425 | return newsk; |
@@ -428,6 +431,9 @@ exit_nonewsk: | |||
428 | exit: | 431 | exit: |
429 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); | 432 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); |
430 | return NULL; | 433 | return NULL; |
434 | put_and_exit: | ||
435 | sock_put(newsk); | ||
436 | goto exit; | ||
431 | } | 437 | } |
432 | 438 | ||
433 | EXPORT_SYMBOL_GPL(dccp_v4_request_recv_sock); | 439 | EXPORT_SYMBOL_GPL(dccp_v4_request_recv_sock); |
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index de1b7e37ad5b..8dc4348774a5 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c | |||
@@ -54,8 +54,8 @@ static void dccp_v6_hash(struct sock *sk) | |||
54 | 54 | ||
55 | /* add pseudo-header to DCCP checksum stored in skb->csum */ | 55 | /* add pseudo-header to DCCP checksum stored in skb->csum */ |
56 | static inline __sum16 dccp_v6_csum_finish(struct sk_buff *skb, | 56 | static inline __sum16 dccp_v6_csum_finish(struct sk_buff *skb, |
57 | struct in6_addr *saddr, | 57 | const struct in6_addr *saddr, |
58 | struct in6_addr *daddr) | 58 | const struct in6_addr *daddr) |
59 | { | 59 | { |
60 | return csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_DCCP, skb->csum); | 60 | return csum_ipv6_magic(saddr, daddr, skb->len, IPPROTO_DCCP, skb->csum); |
61 | } | 61 | } |
@@ -87,7 +87,7 @@ static inline __u32 dccp_v6_init_sequence(struct sk_buff *skb) | |||
87 | static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 87 | static void dccp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
88 | u8 type, u8 code, int offset, __be32 info) | 88 | u8 type, u8 code, int offset, __be32 info) |
89 | { | 89 | { |
90 | struct ipv6hdr *hdr = (struct ipv6hdr *)skb->data; | 90 | const struct ipv6hdr *hdr = (const struct ipv6hdr *)skb->data; |
91 | const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset); | 91 | const struct dccp_hdr *dh = (struct dccp_hdr *)(skb->data + offset); |
92 | struct dccp_sock *dp; | 92 | struct dccp_sock *dp; |
93 | struct ipv6_pinfo *np; | 93 | struct ipv6_pinfo *np; |
@@ -296,7 +296,7 @@ static void dccp_v6_reqsk_destructor(struct request_sock *req) | |||
296 | 296 | ||
297 | static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb) | 297 | static void dccp_v6_ctl_send_reset(struct sock *sk, struct sk_buff *rxskb) |
298 | { | 298 | { |
299 | struct ipv6hdr *rxip6h; | 299 | const struct ipv6hdr *rxip6h; |
300 | struct sk_buff *skb; | 300 | struct sk_buff *skb; |
301 | struct flowi6 fl6; | 301 | struct flowi6 fl6; |
302 | struct net *net = dev_net(skb_dst(rxskb)->dev); | 302 | struct net *net = dev_net(skb_dst(rxskb)->dev); |
@@ -573,7 +573,7 @@ static struct sock *dccp_v6_request_recv_sock(struct sock *sk, | |||
573 | 573 | ||
574 | First: no IPv4 options. | 574 | First: no IPv4 options. |
575 | */ | 575 | */ |
576 | newinet->opt = NULL; | 576 | newinet->inet_opt = NULL; |
577 | 577 | ||
578 | /* Clone RX bits */ | 578 | /* Clone RX bits */ |
579 | newnp->rxopt.all = np->rxopt.all; | 579 | newnp->rxopt.all = np->rxopt.all; |
diff --git a/net/dccp/options.c b/net/dccp/options.c index f06ffcfc8d71..4b2ab657ac8e 100644 --- a/net/dccp/options.c +++ b/net/dccp/options.c | |||
@@ -123,6 +123,8 @@ int dccp_parse_options(struct sock *sk, struct dccp_request_sock *dreq, | |||
123 | case DCCPO_CHANGE_L ... DCCPO_CONFIRM_R: | 123 | case DCCPO_CHANGE_L ... DCCPO_CONFIRM_R: |
124 | if (pkt_type == DCCP_PKT_DATA) /* RFC 4340, 6 */ | 124 | if (pkt_type == DCCP_PKT_DATA) /* RFC 4340, 6 */ |
125 | break; | 125 | break; |
126 | if (len == 0) | ||
127 | goto out_invalid_option; | ||
126 | rc = dccp_feat_parse_options(sk, dreq, mandatory, opt, | 128 | rc = dccp_feat_parse_options(sk, dreq, mandatory, opt, |
127 | *value, value + 1, len - 1); | 129 | *value, value + 1, len - 1); |
128 | if (rc) | 130 | if (rc) |
diff --git a/net/dccp/output.c b/net/dccp/output.c index 784d30210543..fab108e51e5a 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c | |||
@@ -43,7 +43,7 @@ static void dccp_skb_entail(struct sock *sk, struct sk_buff *skb) | |||
43 | static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) | 43 | static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) |
44 | { | 44 | { |
45 | if (likely(skb != NULL)) { | 45 | if (likely(skb != NULL)) { |
46 | const struct inet_sock *inet = inet_sk(sk); | 46 | struct inet_sock *inet = inet_sk(sk); |
47 | const struct inet_connection_sock *icsk = inet_csk(sk); | 47 | const struct inet_connection_sock *icsk = inet_csk(sk); |
48 | struct dccp_sock *dp = dccp_sk(sk); | 48 | struct dccp_sock *dp = dccp_sk(sk); |
49 | struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); | 49 | struct dccp_skb_cb *dcb = DCCP_SKB_CB(skb); |
@@ -136,14 +136,14 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) | |||
136 | 136 | ||
137 | DCCP_INC_STATS(DCCP_MIB_OUTSEGS); | 137 | DCCP_INC_STATS(DCCP_MIB_OUTSEGS); |
138 | 138 | ||
139 | err = icsk->icsk_af_ops->queue_xmit(skb); | 139 | err = icsk->icsk_af_ops->queue_xmit(skb, &inet->cork.fl); |
140 | return net_xmit_eval(err); | 140 | return net_xmit_eval(err); |
141 | } | 141 | } |
142 | return -ENOBUFS; | 142 | return -ENOBUFS; |
143 | } | 143 | } |
144 | 144 | ||
145 | /** | 145 | /** |
146 | * dccp_determine_ccmps - Find out about CCID-specfic packet-size limits | 146 | * dccp_determine_ccmps - Find out about CCID-specific packet-size limits |
147 | * We only consider the HC-sender CCID for setting the CCMPS (RFC 4340, 14.), | 147 | * We only consider the HC-sender CCID for setting the CCMPS (RFC 4340, 14.), |
148 | * since the RX CCID is restricted to feedback packets (Acks), which are small | 148 | * since the RX CCID is restricted to feedback packets (Acks), which are small |
149 | * in comparison with the data traffic. A value of 0 means "no current CCMPS". | 149 | * in comparison with the data traffic. A value of 0 means "no current CCMPS". |
diff --git a/net/decnet/dn_dev.c b/net/decnet/dn_dev.c index 0dcaa903e00e..404fa1591027 100644 --- a/net/decnet/dn_dev.c +++ b/net/decnet/dn_dev.c | |||
@@ -752,7 +752,8 @@ static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) | |||
752 | skip_naddr = cb->args[1]; | 752 | skip_naddr = cb->args[1]; |
753 | 753 | ||
754 | idx = 0; | 754 | idx = 0; |
755 | for_each_netdev(&init_net, dev) { | 755 | rcu_read_lock(); |
756 | for_each_netdev_rcu(&init_net, dev) { | ||
756 | if (idx < skip_ndevs) | 757 | if (idx < skip_ndevs) |
757 | goto cont; | 758 | goto cont; |
758 | else if (idx > skip_ndevs) { | 759 | else if (idx > skip_ndevs) { |
@@ -761,11 +762,11 @@ static int dn_nl_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb) | |||
761 | skip_naddr = 0; | 762 | skip_naddr = 0; |
762 | } | 763 | } |
763 | 764 | ||
764 | if ((dn_db = rtnl_dereference(dev->dn_ptr)) == NULL) | 765 | if ((dn_db = rcu_dereference(dev->dn_ptr)) == NULL) |
765 | goto cont; | 766 | goto cont; |
766 | 767 | ||
767 | for (ifa = rtnl_dereference(dn_db->ifa_list), dn_idx = 0; ifa; | 768 | for (ifa = rcu_dereference(dn_db->ifa_list), dn_idx = 0; ifa; |
768 | ifa = rtnl_dereference(ifa->ifa_next), dn_idx++) { | 769 | ifa = rcu_dereference(ifa->ifa_next), dn_idx++) { |
769 | if (dn_idx < skip_naddr) | 770 | if (dn_idx < skip_naddr) |
770 | continue; | 771 | continue; |
771 | 772 | ||
@@ -778,6 +779,7 @@ cont: | |||
778 | idx++; | 779 | idx++; |
779 | } | 780 | } |
780 | done: | 781 | done: |
782 | rcu_read_unlock(); | ||
781 | cb->args[0] = idx; | 783 | cb->args[0] = idx; |
782 | cb->args[1] = dn_idx; | 784 | cb->args[1] = dn_idx; |
783 | 785 | ||
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index 9f09d4fc2880..74544bc6fdec 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c | |||
@@ -1125,13 +1125,11 @@ make_route: | |||
1125 | if (dev_out->flags & IFF_LOOPBACK) | 1125 | if (dev_out->flags & IFF_LOOPBACK) |
1126 | flags |= RTCF_LOCAL; | 1126 | flags |= RTCF_LOCAL; |
1127 | 1127 | ||
1128 | rt = dst_alloc(&dn_dst_ops, 0); | 1128 | rt = dst_alloc(&dn_dst_ops, dev_out, 1, 0, DST_HOST); |
1129 | if (rt == NULL) | 1129 | if (rt == NULL) |
1130 | goto e_nobufs; | 1130 | goto e_nobufs; |
1131 | 1131 | ||
1132 | atomic_set(&rt->dst.__refcnt, 1); | 1132 | memset(&rt->fld, 0, sizeof(rt->fld)); |
1133 | rt->dst.flags = DST_HOST; | ||
1134 | |||
1135 | rt->fld.saddr = oldflp->saddr; | 1133 | rt->fld.saddr = oldflp->saddr; |
1136 | rt->fld.daddr = oldflp->daddr; | 1134 | rt->fld.daddr = oldflp->daddr; |
1137 | rt->fld.flowidn_oif = oldflp->flowidn_oif; | 1135 | rt->fld.flowidn_oif = oldflp->flowidn_oif; |
@@ -1146,8 +1144,6 @@ make_route: | |||
1146 | rt->rt_dst_map = fld.daddr; | 1144 | rt->rt_dst_map = fld.daddr; |
1147 | rt->rt_src_map = fld.saddr; | 1145 | rt->rt_src_map = fld.saddr; |
1148 | 1146 | ||
1149 | rt->dst.dev = dev_out; | ||
1150 | dev_hold(dev_out); | ||
1151 | rt->dst.neighbour = neigh; | 1147 | rt->dst.neighbour = neigh; |
1152 | neigh = NULL; | 1148 | neigh = NULL; |
1153 | 1149 | ||
@@ -1399,10 +1395,11 @@ static int dn_route_input_slow(struct sk_buff *skb) | |||
1399 | } | 1395 | } |
1400 | 1396 | ||
1401 | make_route: | 1397 | make_route: |
1402 | rt = dst_alloc(&dn_dst_ops, 0); | 1398 | rt = dst_alloc(&dn_dst_ops, out_dev, 0, 0, DST_HOST); |
1403 | if (rt == NULL) | 1399 | if (rt == NULL) |
1404 | goto e_nobufs; | 1400 | goto e_nobufs; |
1405 | 1401 | ||
1402 | memset(&rt->fld, 0, sizeof(rt->fld)); | ||
1406 | rt->rt_saddr = fld.saddr; | 1403 | rt->rt_saddr = fld.saddr; |
1407 | rt->rt_daddr = fld.daddr; | 1404 | rt->rt_daddr = fld.daddr; |
1408 | rt->rt_gateway = fld.daddr; | 1405 | rt->rt_gateway = fld.daddr; |
@@ -1419,9 +1416,7 @@ make_route: | |||
1419 | rt->fld.flowidn_iif = in_dev->ifindex; | 1416 | rt->fld.flowidn_iif = in_dev->ifindex; |
1420 | rt->fld.flowidn_mark = fld.flowidn_mark; | 1417 | rt->fld.flowidn_mark = fld.flowidn_mark; |
1421 | 1418 | ||
1422 | rt->dst.flags = DST_HOST; | ||
1423 | rt->dst.neighbour = neigh; | 1419 | rt->dst.neighbour = neigh; |
1424 | rt->dst.dev = out_dev; | ||
1425 | rt->dst.lastuse = jiffies; | 1420 | rt->dst.lastuse = jiffies; |
1426 | rt->dst.output = dn_rt_bug; | 1421 | rt->dst.output = dn_rt_bug; |
1427 | switch(res.type) { | 1422 | switch(res.type) { |
@@ -1440,8 +1435,6 @@ make_route: | |||
1440 | rt->dst.input = dst_discard; | 1435 | rt->dst.input = dst_discard; |
1441 | } | 1436 | } |
1442 | rt->rt_flags = flags; | 1437 | rt->rt_flags = flags; |
1443 | if (rt->dst.dev) | ||
1444 | dev_hold(rt->dst.dev); | ||
1445 | 1438 | ||
1446 | err = dn_rt_set_next_hop(rt, &res); | 1439 | err = dn_rt_set_next_hop(rt, &res); |
1447 | if (err) | 1440 | if (err) |
diff --git a/net/decnet/dn_table.c b/net/decnet/dn_table.c index 99d8d3a40998..bd0a52dd1d40 100644 --- a/net/decnet/dn_table.c +++ b/net/decnet/dn_table.c | |||
@@ -123,11 +123,11 @@ static inline void dn_rebuild_zone(struct dn_zone *dz, | |||
123 | struct dn_fib_node **old_ht, | 123 | struct dn_fib_node **old_ht, |
124 | int old_divisor) | 124 | int old_divisor) |
125 | { | 125 | { |
126 | int i; | ||
127 | struct dn_fib_node *f, **fp, *next; | 126 | struct dn_fib_node *f, **fp, *next; |
127 | int i; | ||
128 | 128 | ||
129 | for(i = 0; i < old_divisor; i++) { | 129 | for(i = 0; i < old_divisor; i++) { |
130 | for(f = old_ht[i]; f; f = f->fn_next) { | 130 | for(f = old_ht[i]; f; f = next) { |
131 | next = f->fn_next; | 131 | next = f->fn_next; |
132 | for(fp = dn_chain_p(f->fn_key, dz); | 132 | for(fp = dn_chain_p(f->fn_key, dz); |
133 | *fp && dn_key_leq((*fp)->fn_key, f->fn_key); | 133 | *fp && dn_key_leq((*fp)->fn_key, f->fn_key); |
diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig index 87bb5f4de0e8..c53ded2a98df 100644 --- a/net/dsa/Kconfig +++ b/net/dsa/Kconfig | |||
@@ -41,12 +41,12 @@ config NET_DSA_MV88E6XXX_NEED_PPU | |||
41 | default n | 41 | default n |
42 | 42 | ||
43 | config NET_DSA_MV88E6131 | 43 | config NET_DSA_MV88E6131 |
44 | bool "Marvell 88E6095/6095F/6131 ethernet switch chip support" | 44 | bool "Marvell 88E6085/6095/6095F/6131 ethernet switch chip support" |
45 | select NET_DSA_MV88E6XXX | 45 | select NET_DSA_MV88E6XXX |
46 | select NET_DSA_MV88E6XXX_NEED_PPU | 46 | select NET_DSA_MV88E6XXX_NEED_PPU |
47 | select NET_DSA_TAG_DSA | 47 | select NET_DSA_TAG_DSA |
48 | ---help--- | 48 | ---help--- |
49 | This enables support for the Marvell 88E6095/6095F/6131 | 49 | This enables support for the Marvell 88E6085/6095/6095F/6131 |
50 | ethernet switch chips. | 50 | ethernet switch chips. |
51 | 51 | ||
52 | config NET_DSA_MV88E6123_61_65 | 52 | config NET_DSA_MV88E6123_61_65 |
diff --git a/net/dsa/mv88e6131.c b/net/dsa/mv88e6131.c index bb2b41bc854e..45f7411e90ba 100644 --- a/net/dsa/mv88e6131.c +++ b/net/dsa/mv88e6131.c | |||
@@ -14,6 +14,13 @@ | |||
14 | #include "dsa_priv.h" | 14 | #include "dsa_priv.h" |
15 | #include "mv88e6xxx.h" | 15 | #include "mv88e6xxx.h" |
16 | 16 | ||
17 | /* | ||
18 | * Switch product IDs | ||
19 | */ | ||
20 | #define ID_6085 0x04a0 | ||
21 | #define ID_6095 0x0950 | ||
22 | #define ID_6131 0x1060 | ||
23 | |||
17 | static char *mv88e6131_probe(struct mii_bus *bus, int sw_addr) | 24 | static char *mv88e6131_probe(struct mii_bus *bus, int sw_addr) |
18 | { | 25 | { |
19 | int ret; | 26 | int ret; |
@@ -21,9 +28,11 @@ static char *mv88e6131_probe(struct mii_bus *bus, int sw_addr) | |||
21 | ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), 0x03); | 28 | ret = __mv88e6xxx_reg_read(bus, sw_addr, REG_PORT(0), 0x03); |
22 | if (ret >= 0) { | 29 | if (ret >= 0) { |
23 | ret &= 0xfff0; | 30 | ret &= 0xfff0; |
24 | if (ret == 0x0950) | 31 | if (ret == ID_6085) |
32 | return "Marvell 88E6085"; | ||
33 | if (ret == ID_6095) | ||
25 | return "Marvell 88E6095/88E6095F"; | 34 | return "Marvell 88E6095/88E6095F"; |
26 | if (ret == 0x1060) | 35 | if (ret == ID_6131) |
27 | return "Marvell 88E6131"; | 36 | return "Marvell 88E6131"; |
28 | } | 37 | } |
29 | 38 | ||
@@ -124,7 +133,7 @@ static int mv88e6131_setup_global(struct dsa_switch *ds) | |||
124 | * Ignore removed tag data on doubly tagged packets, disable | 133 | * Ignore removed tag data on doubly tagged packets, disable |
125 | * flow control messages, force flow control priority to the | 134 | * flow control messages, force flow control priority to the |
126 | * highest, and send all special multicast frames to the CPU | 135 | * highest, and send all special multicast frames to the CPU |
127 | * port at the higest priority. | 136 | * port at the highest priority. |
128 | */ | 137 | */ |
129 | REG_WRITE(REG_GLOBAL2, 0x05, 0x00ff); | 138 | REG_WRITE(REG_GLOBAL2, 0x05, 0x00ff); |
130 | 139 | ||
@@ -164,6 +173,7 @@ static int mv88e6131_setup_global(struct dsa_switch *ds) | |||
164 | 173 | ||
165 | static int mv88e6131_setup_port(struct dsa_switch *ds, int p) | 174 | static int mv88e6131_setup_port(struct dsa_switch *ds, int p) |
166 | { | 175 | { |
176 | struct mv88e6xxx_priv_state *ps = (void *)(ds + 1); | ||
167 | int addr = REG_PORT(p); | 177 | int addr = REG_PORT(p); |
168 | u16 val; | 178 | u16 val; |
169 | 179 | ||
@@ -171,10 +181,13 @@ static int mv88e6131_setup_port(struct dsa_switch *ds, int p) | |||
171 | * MAC Forcing register: don't force link, speed, duplex | 181 | * MAC Forcing register: don't force link, speed, duplex |
172 | * or flow control state to any particular values on physical | 182 | * or flow control state to any particular values on physical |
173 | * ports, but force the CPU port and all DSA ports to 1000 Mb/s | 183 | * ports, but force the CPU port and all DSA ports to 1000 Mb/s |
174 | * full duplex. | 184 | * (100 Mb/s on 6085) full duplex. |
175 | */ | 185 | */ |
176 | if (dsa_is_cpu_port(ds, p) || ds->dsa_port_mask & (1 << p)) | 186 | if (dsa_is_cpu_port(ds, p) || ds->dsa_port_mask & (1 << p)) |
177 | REG_WRITE(addr, 0x01, 0x003e); | 187 | if (ps->id == ID_6085) |
188 | REG_WRITE(addr, 0x01, 0x003d); /* 100 Mb/s */ | ||
189 | else | ||
190 | REG_WRITE(addr, 0x01, 0x003e); /* 1000 Mb/s */ | ||
178 | else | 191 | else |
179 | REG_WRITE(addr, 0x01, 0x0003); | 192 | REG_WRITE(addr, 0x01, 0x0003); |
180 | 193 | ||
@@ -194,8 +207,15 @@ static int mv88e6131_setup_port(struct dsa_switch *ds, int p) | |||
194 | * mode, but do not enable forwarding of unknown unicasts. | 207 | * mode, but do not enable forwarding of unknown unicasts. |
195 | */ | 208 | */ |
196 | val = 0x0433; | 209 | val = 0x0433; |
197 | if (p == dsa_upstream_port(ds)) | 210 | if (p == dsa_upstream_port(ds)) { |
198 | val |= 0x0104; | 211 | val |= 0x0104; |
212 | /* | ||
213 | * On 6085, unknown multicast forward is controlled | ||
214 | * here rather than in Port Control 2 register. | ||
215 | */ | ||
216 | if (ps->id == ID_6085) | ||
217 | val |= 0x0008; | ||
218 | } | ||
199 | if (ds->dsa_port_mask & (1 << p)) | 219 | if (ds->dsa_port_mask & (1 << p)) |
200 | val |= 0x0100; | 220 | val |= 0x0100; |
201 | REG_WRITE(addr, 0x04, val); | 221 | REG_WRITE(addr, 0x04, val); |
@@ -238,10 +258,19 @@ static int mv88e6131_setup_port(struct dsa_switch *ds, int p) | |||
238 | * If this is the upstream port for this switch, enable | 258 | * If this is the upstream port for this switch, enable |
239 | * forwarding of unknown multicast addresses. | 259 | * forwarding of unknown multicast addresses. |
240 | */ | 260 | */ |
241 | val = 0x0080 | dsa_upstream_port(ds); | 261 | if (ps->id == ID_6085) |
242 | if (p == dsa_upstream_port(ds)) | 262 | /* |
243 | val |= 0x0040; | 263 | * on 6085, bits 3:0 are reserved, bit 6 control ARP |
244 | REG_WRITE(addr, 0x08, val); | 264 | * mirroring, and multicast forward is handled in |
265 | * Port Control register. | ||
266 | */ | ||
267 | REG_WRITE(addr, 0x08, 0x0080); | ||
268 | else { | ||
269 | val = 0x0080 | dsa_upstream_port(ds); | ||
270 | if (p == dsa_upstream_port(ds)) | ||
271 | val |= 0x0040; | ||
272 | REG_WRITE(addr, 0x08, val); | ||
273 | } | ||
245 | 274 | ||
246 | /* | 275 | /* |
247 | * Rate Control: disable ingress rate limiting. | 276 | * Rate Control: disable ingress rate limiting. |
@@ -286,6 +315,8 @@ static int mv88e6131_setup(struct dsa_switch *ds) | |||
286 | mv88e6xxx_ppu_state_init(ds); | 315 | mv88e6xxx_ppu_state_init(ds); |
287 | mutex_init(&ps->stats_mutex); | 316 | mutex_init(&ps->stats_mutex); |
288 | 317 | ||
318 | ps->id = REG_READ(REG_PORT(0), 0x03) & 0xfff0; | ||
319 | |||
289 | ret = mv88e6131_switch_reset(ds); | 320 | ret = mv88e6131_switch_reset(ds); |
290 | if (ret < 0) | 321 | if (ret < 0) |
291 | return ret; | 322 | return ret; |
diff --git a/net/dsa/mv88e6xxx.h b/net/dsa/mv88e6xxx.h index eb0e0aaa9f1b..61156ca26a0d 100644 --- a/net/dsa/mv88e6xxx.h +++ b/net/dsa/mv88e6xxx.h | |||
@@ -39,6 +39,8 @@ struct mv88e6xxx_priv_state { | |||
39 | * Hold this mutex over snapshot + dump sequences. | 39 | * Hold this mutex over snapshot + dump sequences. |
40 | */ | 40 | */ |
41 | struct mutex stats_mutex; | 41 | struct mutex stats_mutex; |
42 | |||
43 | int id; /* switch product id */ | ||
42 | }; | 44 | }; |
43 | 45 | ||
44 | struct mv88e6xxx_hw_stat { | 46 | struct mv88e6xxx_hw_stat { |
diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 64ca2a6fa0d4..0a47b6c37038 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c | |||
@@ -288,7 +288,6 @@ static const struct ethtool_ops dsa_slave_ethtool_ops = { | |||
288 | .get_drvinfo = dsa_slave_get_drvinfo, | 288 | .get_drvinfo = dsa_slave_get_drvinfo, |
289 | .nway_reset = dsa_slave_nway_reset, | 289 | .nway_reset = dsa_slave_nway_reset, |
290 | .get_link = dsa_slave_get_link, | 290 | .get_link = dsa_slave_get_link, |
291 | .set_sg = ethtool_op_set_sg, | ||
292 | .get_strings = dsa_slave_get_strings, | 291 | .get_strings = dsa_slave_get_strings, |
293 | .get_ethtool_stats = dsa_slave_get_ethtool_stats, | 292 | .get_ethtool_stats = dsa_slave_get_ethtool_stats, |
294 | .get_sset_count = dsa_slave_get_sset_count, | 293 | .get_sset_count = dsa_slave_get_sset_count, |
diff --git a/net/econet/af_econet.c b/net/econet/af_econet.c index 116d3fd3d669..a1d9f3787dd5 100644 --- a/net/econet/af_econet.c +++ b/net/econet/af_econet.c | |||
@@ -935,7 +935,6 @@ static void aun_data_available(struct sock *sk, int slen) | |||
935 | struct sk_buff *skb; | 935 | struct sk_buff *skb; |
936 | unsigned char *data; | 936 | unsigned char *data; |
937 | struct aunhdr *ah; | 937 | struct aunhdr *ah; |
938 | struct iphdr *ip; | ||
939 | size_t len; | 938 | size_t len; |
940 | 939 | ||
941 | while ((skb = skb_recv_datagram(sk, 0, 1, &err)) == NULL) { | 940 | while ((skb = skb_recv_datagram(sk, 0, 1, &err)) == NULL) { |
@@ -949,7 +948,6 @@ static void aun_data_available(struct sock *sk, int slen) | |||
949 | data = skb_transport_header(skb) + sizeof(struct udphdr); | 948 | data = skb_transport_header(skb) + sizeof(struct udphdr); |
950 | ah = (struct aunhdr *)data; | 949 | ah = (struct aunhdr *)data; |
951 | len = skb->len - sizeof(struct udphdr); | 950 | len = skb->len - sizeof(struct udphdr); |
952 | ip = ip_hdr(skb); | ||
953 | 951 | ||
954 | switch (ah->code) | 952 | switch (ah->code) |
955 | { | 953 | { |
@@ -962,12 +960,6 @@ static void aun_data_available(struct sock *sk, int slen) | |||
962 | case 4: | 960 | case 4: |
963 | aun_tx_ack(ah->handle, ECTYPE_TRANSMIT_NOT_LISTENING); | 961 | aun_tx_ack(ah->handle, ECTYPE_TRANSMIT_NOT_LISTENING); |
964 | break; | 962 | break; |
965 | #if 0 | ||
966 | /* This isn't quite right yet. */ | ||
967 | case 5: | ||
968 | aun_send_response(ip->saddr, ah->handle, 6, ah->cb); | ||
969 | break; | ||
970 | #endif | ||
971 | default: | 963 | default: |
972 | printk(KERN_DEBUG "unknown AUN packet (type %d)\n", data[0]); | 964 | printk(KERN_DEBUG "unknown AUN packet (type %d)\n", data[0]); |
973 | } | 965 | } |
diff --git a/net/ieee802154/Makefile b/net/ieee802154/Makefile index ce2d33582859..5761185f884e 100644 --- a/net/ieee802154/Makefile +++ b/net/ieee802154/Makefile | |||
@@ -1,5 +1,3 @@ | |||
1 | obj-$(CONFIG_IEEE802154) += ieee802154.o af_802154.o | 1 | obj-$(CONFIG_IEEE802154) += ieee802154.o af_802154.o |
2 | ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o | 2 | ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o |
3 | af_802154-y := af_ieee802154.o raw.o dgram.o | 3 | af_802154-y := af_ieee802154.o raw.o dgram.o |
4 | |||
5 | ccflags-y += -Wall -DDEBUG | ||
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile index 0dc772d0d125..f2dc69cffb57 100644 --- a/net/ipv4/Makefile +++ b/net/ipv4/Makefile | |||
@@ -11,7 +11,7 @@ obj-y := route.o inetpeer.o protocol.o \ | |||
11 | datagram.o raw.o udp.o udplite.o \ | 11 | datagram.o raw.o udp.o udplite.o \ |
12 | arp.o icmp.o devinet.o af_inet.o igmp.o \ | 12 | arp.o icmp.o devinet.o af_inet.o igmp.o \ |
13 | fib_frontend.o fib_semantics.o fib_trie.o \ | 13 | fib_frontend.o fib_semantics.o fib_trie.o \ |
14 | inet_fragment.o | 14 | inet_fragment.o ping.o |
15 | 15 | ||
16 | obj-$(CONFIG_SYSCTL) += sysctl_net_ipv4.o | 16 | obj-$(CONFIG_SYSCTL) += sysctl_net_ipv4.o |
17 | obj-$(CONFIG_PROC_FS) += proc.o | 17 | obj-$(CONFIG_PROC_FS) += proc.o |
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 807d83c02ef6..cc1463156cd0 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
@@ -105,6 +105,7 @@ | |||
105 | #include <net/tcp.h> | 105 | #include <net/tcp.h> |
106 | #include <net/udp.h> | 106 | #include <net/udp.h> |
107 | #include <net/udplite.h> | 107 | #include <net/udplite.h> |
108 | #include <net/ping.h> | ||
108 | #include <linux/skbuff.h> | 109 | #include <linux/skbuff.h> |
109 | #include <net/sock.h> | 110 | #include <net/sock.h> |
110 | #include <net/raw.h> | 111 | #include <net/raw.h> |
@@ -153,7 +154,7 @@ void inet_sock_destruct(struct sock *sk) | |||
153 | WARN_ON(sk->sk_wmem_queued); | 154 | WARN_ON(sk->sk_wmem_queued); |
154 | WARN_ON(sk->sk_forward_alloc); | 155 | WARN_ON(sk->sk_forward_alloc); |
155 | 156 | ||
156 | kfree(inet->opt); | 157 | kfree(rcu_dereference_protected(inet->inet_opt, 1)); |
157 | dst_release(rcu_dereference_check(sk->sk_dst_cache, 1)); | 158 | dst_release(rcu_dereference_check(sk->sk_dst_cache, 1)); |
158 | sk_refcnt_debug_dec(sk); | 159 | sk_refcnt_debug_dec(sk); |
159 | } | 160 | } |
@@ -1008,6 +1009,14 @@ static struct inet_protosw inetsw_array[] = | |||
1008 | .flags = INET_PROTOSW_PERMANENT, | 1009 | .flags = INET_PROTOSW_PERMANENT, |
1009 | }, | 1010 | }, |
1010 | 1011 | ||
1012 | { | ||
1013 | .type = SOCK_DGRAM, | ||
1014 | .protocol = IPPROTO_ICMP, | ||
1015 | .prot = &ping_prot, | ||
1016 | .ops = &inet_dgram_ops, | ||
1017 | .no_check = UDP_CSUM_DEFAULT, | ||
1018 | .flags = INET_PROTOSW_REUSE, | ||
1019 | }, | ||
1011 | 1020 | ||
1012 | { | 1021 | { |
1013 | .type = SOCK_RAW, | 1022 | .type = SOCK_RAW, |
@@ -1103,14 +1112,19 @@ static int inet_sk_reselect_saddr(struct sock *sk) | |||
1103 | struct inet_sock *inet = inet_sk(sk); | 1112 | struct inet_sock *inet = inet_sk(sk); |
1104 | __be32 old_saddr = inet->inet_saddr; | 1113 | __be32 old_saddr = inet->inet_saddr; |
1105 | __be32 daddr = inet->inet_daddr; | 1114 | __be32 daddr = inet->inet_daddr; |
1115 | struct flowi4 *fl4; | ||
1106 | struct rtable *rt; | 1116 | struct rtable *rt; |
1107 | __be32 new_saddr; | 1117 | __be32 new_saddr; |
1118 | struct ip_options_rcu *inet_opt; | ||
1108 | 1119 | ||
1109 | if (inet->opt && inet->opt->srr) | 1120 | inet_opt = rcu_dereference_protected(inet->inet_opt, |
1110 | daddr = inet->opt->faddr; | 1121 | sock_owned_by_user(sk)); |
1122 | if (inet_opt && inet_opt->opt.srr) | ||
1123 | daddr = inet_opt->opt.faddr; | ||
1111 | 1124 | ||
1112 | /* Query new route. */ | 1125 | /* Query new route. */ |
1113 | rt = ip_route_connect(daddr, 0, RT_CONN_FLAGS(sk), | 1126 | fl4 = &inet->cork.fl.u.ip4; |
1127 | rt = ip_route_connect(fl4, daddr, 0, RT_CONN_FLAGS(sk), | ||
1114 | sk->sk_bound_dev_if, sk->sk_protocol, | 1128 | sk->sk_bound_dev_if, sk->sk_protocol, |
1115 | inet->inet_sport, inet->inet_dport, sk, false); | 1129 | inet->inet_sport, inet->inet_dport, sk, false); |
1116 | if (IS_ERR(rt)) | 1130 | if (IS_ERR(rt)) |
@@ -1118,7 +1132,7 @@ static int inet_sk_reselect_saddr(struct sock *sk) | |||
1118 | 1132 | ||
1119 | sk_setup_caps(sk, &rt->dst); | 1133 | sk_setup_caps(sk, &rt->dst); |
1120 | 1134 | ||
1121 | new_saddr = rt->rt_src; | 1135 | new_saddr = fl4->saddr; |
1122 | 1136 | ||
1123 | if (new_saddr == old_saddr) | 1137 | if (new_saddr == old_saddr) |
1124 | return 0; | 1138 | return 0; |
@@ -1147,6 +1161,8 @@ int inet_sk_rebuild_header(struct sock *sk) | |||
1147 | struct inet_sock *inet = inet_sk(sk); | 1161 | struct inet_sock *inet = inet_sk(sk); |
1148 | struct rtable *rt = (struct rtable *)__sk_dst_check(sk, 0); | 1162 | struct rtable *rt = (struct rtable *)__sk_dst_check(sk, 0); |
1149 | __be32 daddr; | 1163 | __be32 daddr; |
1164 | struct ip_options_rcu *inet_opt; | ||
1165 | struct flowi4 *fl4; | ||
1150 | int err; | 1166 | int err; |
1151 | 1167 | ||
1152 | /* Route is OK, nothing to do. */ | 1168 | /* Route is OK, nothing to do. */ |
@@ -1154,10 +1170,14 @@ int inet_sk_rebuild_header(struct sock *sk) | |||
1154 | return 0; | 1170 | return 0; |
1155 | 1171 | ||
1156 | /* Reroute. */ | 1172 | /* Reroute. */ |
1173 | rcu_read_lock(); | ||
1174 | inet_opt = rcu_dereference(inet->inet_opt); | ||
1157 | daddr = inet->inet_daddr; | 1175 | daddr = inet->inet_daddr; |
1158 | if (inet->opt && inet->opt->srr) | 1176 | if (inet_opt && inet_opt->opt.srr) |
1159 | daddr = inet->opt->faddr; | 1177 | daddr = inet_opt->opt.faddr; |
1160 | rt = ip_route_output_ports(sock_net(sk), sk, daddr, inet->inet_saddr, | 1178 | rcu_read_unlock(); |
1179 | fl4 = &inet->cork.fl.u.ip4; | ||
1180 | rt = ip_route_output_ports(sock_net(sk), fl4, sk, daddr, inet->inet_saddr, | ||
1161 | inet->inet_dport, inet->inet_sport, | 1181 | inet->inet_dport, inet->inet_sport, |
1162 | sk->sk_protocol, RT_CONN_FLAGS(sk), | 1182 | sk->sk_protocol, RT_CONN_FLAGS(sk), |
1163 | sk->sk_bound_dev_if); | 1183 | sk->sk_bound_dev_if); |
@@ -1186,7 +1206,7 @@ EXPORT_SYMBOL(inet_sk_rebuild_header); | |||
1186 | 1206 | ||
1187 | static int inet_gso_send_check(struct sk_buff *skb) | 1207 | static int inet_gso_send_check(struct sk_buff *skb) |
1188 | { | 1208 | { |
1189 | struct iphdr *iph; | 1209 | const struct iphdr *iph; |
1190 | const struct net_protocol *ops; | 1210 | const struct net_protocol *ops; |
1191 | int proto; | 1211 | int proto; |
1192 | int ihl; | 1212 | int ihl; |
@@ -1293,7 +1313,7 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, | |||
1293 | const struct net_protocol *ops; | 1313 | const struct net_protocol *ops; |
1294 | struct sk_buff **pp = NULL; | 1314 | struct sk_buff **pp = NULL; |
1295 | struct sk_buff *p; | 1315 | struct sk_buff *p; |
1296 | struct iphdr *iph; | 1316 | const struct iphdr *iph; |
1297 | unsigned int hlen; | 1317 | unsigned int hlen; |
1298 | unsigned int off; | 1318 | unsigned int off; |
1299 | unsigned int id; | 1319 | unsigned int id; |
@@ -1516,6 +1536,7 @@ static const struct net_protocol udp_protocol = { | |||
1516 | 1536 | ||
1517 | static const struct net_protocol icmp_protocol = { | 1537 | static const struct net_protocol icmp_protocol = { |
1518 | .handler = icmp_rcv, | 1538 | .handler = icmp_rcv, |
1539 | .err_handler = ping_err, | ||
1519 | .no_policy = 1, | 1540 | .no_policy = 1, |
1520 | .netns_ok = 1, | 1541 | .netns_ok = 1, |
1521 | }; | 1542 | }; |
@@ -1631,6 +1652,10 @@ static int __init inet_init(void) | |||
1631 | if (rc) | 1652 | if (rc) |
1632 | goto out_unregister_udp_proto; | 1653 | goto out_unregister_udp_proto; |
1633 | 1654 | ||
1655 | rc = proto_register(&ping_prot, 1); | ||
1656 | if (rc) | ||
1657 | goto out_unregister_raw_proto; | ||
1658 | |||
1634 | /* | 1659 | /* |
1635 | * Tell SOCKET that we are alive... | 1660 | * Tell SOCKET that we are alive... |
1636 | */ | 1661 | */ |
@@ -1686,6 +1711,8 @@ static int __init inet_init(void) | |||
1686 | /* Add UDP-Lite (RFC 3828) */ | 1711 | /* Add UDP-Lite (RFC 3828) */ |
1687 | udplite4_register(); | 1712 | udplite4_register(); |
1688 | 1713 | ||
1714 | ping_init(); | ||
1715 | |||
1689 | /* | 1716 | /* |
1690 | * Set the ICMP layer up | 1717 | * Set the ICMP layer up |
1691 | */ | 1718 | */ |
@@ -1716,6 +1743,8 @@ static int __init inet_init(void) | |||
1716 | rc = 0; | 1743 | rc = 0; |
1717 | out: | 1744 | out: |
1718 | return rc; | 1745 | return rc; |
1746 | out_unregister_raw_proto: | ||
1747 | proto_unregister(&raw_prot); | ||
1719 | out_unregister_udp_proto: | 1748 | out_unregister_udp_proto: |
1720 | proto_unregister(&udp_prot); | 1749 | proto_unregister(&udp_prot); |
1721 | out_unregister_tcp_proto: | 1750 | out_unregister_tcp_proto: |
@@ -1740,11 +1769,15 @@ static int __init ipv4_proc_init(void) | |||
1740 | goto out_tcp; | 1769 | goto out_tcp; |
1741 | if (udp4_proc_init()) | 1770 | if (udp4_proc_init()) |
1742 | goto out_udp; | 1771 | goto out_udp; |
1772 | if (ping_proc_init()) | ||
1773 | goto out_ping; | ||
1743 | if (ip_misc_proc_init()) | 1774 | if (ip_misc_proc_init()) |
1744 | goto out_misc; | 1775 | goto out_misc; |
1745 | out: | 1776 | out: |
1746 | return rc; | 1777 | return rc; |
1747 | out_misc: | 1778 | out_misc: |
1779 | ping_proc_exit(); | ||
1780 | out_ping: | ||
1748 | udp4_proc_exit(); | 1781 | udp4_proc_exit(); |
1749 | out_udp: | 1782 | out_udp: |
1750 | tcp4_proc_exit(); | 1783 | tcp4_proc_exit(); |
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index 4286fd3cc0e2..c1f4154552fc 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c | |||
@@ -73,7 +73,7 @@ static inline struct scatterlist *ah_req_sg(struct crypto_ahash *ahash, | |||
73 | * into IP header for icv calculation. Options are already checked | 73 | * into IP header for icv calculation. Options are already checked |
74 | * for validity, so paranoia is not required. */ | 74 | * for validity, so paranoia is not required. */ |
75 | 75 | ||
76 | static int ip_clear_mutable_options(struct iphdr *iph, __be32 *daddr) | 76 | static int ip_clear_mutable_options(const struct iphdr *iph, __be32 *daddr) |
77 | { | 77 | { |
78 | unsigned char * optptr = (unsigned char*)(iph+1); | 78 | unsigned char * optptr = (unsigned char*)(iph+1); |
79 | int l = iph->ihl*4 - sizeof(struct iphdr); | 79 | int l = iph->ihl*4 - sizeof(struct iphdr); |
@@ -396,7 +396,7 @@ out: | |||
396 | static void ah4_err(struct sk_buff *skb, u32 info) | 396 | static void ah4_err(struct sk_buff *skb, u32 info) |
397 | { | 397 | { |
398 | struct net *net = dev_net(skb->dev); | 398 | struct net *net = dev_net(skb->dev); |
399 | struct iphdr *iph = (struct iphdr *)skb->data; | 399 | const struct iphdr *iph = (const struct iphdr *)skb->data; |
400 | struct ip_auth_hdr *ah = (struct ip_auth_hdr *)(skb->data+(iph->ihl<<2)); | 400 | struct ip_auth_hdr *ah = (struct ip_auth_hdr *)(skb->data+(iph->ihl<<2)); |
401 | struct xfrm_state *x; | 401 | struct xfrm_state *x; |
402 | 402 | ||
@@ -404,7 +404,8 @@ static void ah4_err(struct sk_buff *skb, u32 info) | |||
404 | icmp_hdr(skb)->code != ICMP_FRAG_NEEDED) | 404 | icmp_hdr(skb)->code != ICMP_FRAG_NEEDED) |
405 | return; | 405 | return; |
406 | 406 | ||
407 | x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, ah->spi, IPPROTO_AH, AF_INET); | 407 | x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, |
408 | ah->spi, IPPROTO_AH, AF_INET); | ||
408 | if (!x) | 409 | if (!x) |
409 | return; | 410 | return; |
410 | printk(KERN_DEBUG "pmtu discovery on SA AH/%08x/%08x\n", | 411 | printk(KERN_DEBUG "pmtu discovery on SA AH/%08x/%08x\n", |
diff --git a/net/ipv4/cipso_ipv4.c b/net/ipv4/cipso_ipv4.c index 094e150c6260..2b3c23c287cd 100644 --- a/net/ipv4/cipso_ipv4.c +++ b/net/ipv4/cipso_ipv4.c | |||
@@ -112,7 +112,7 @@ int cipso_v4_rbm_strictvalid = 1; | |||
112 | /* The maximum number of category ranges permitted in the ranged category tag | 112 | /* The maximum number of category ranges permitted in the ranged category tag |
113 | * (tag #5). You may note that the IETF draft states that the maximum number | 113 | * (tag #5). You may note that the IETF draft states that the maximum number |
114 | * of category ranges is 7, but if the low end of the last category range is | 114 | * of category ranges is 7, but if the low end of the last category range is |
115 | * zero then it is possibile to fit 8 category ranges because the zero should | 115 | * zero then it is possible to fit 8 category ranges because the zero should |
116 | * be omitted. */ | 116 | * be omitted. */ |
117 | #define CIPSO_V4_TAG_RNG_CAT_MAX 8 | 117 | #define CIPSO_V4_TAG_RNG_CAT_MAX 8 |
118 | 118 | ||
@@ -438,7 +438,7 @@ cache_add_failure: | |||
438 | * | 438 | * |
439 | * Description: | 439 | * Description: |
440 | * Search the DOI definition list for a DOI definition with a DOI value that | 440 | * Search the DOI definition list for a DOI definition with a DOI value that |
441 | * matches @doi. The caller is responsibile for calling rcu_read_[un]lock(). | 441 | * matches @doi. The caller is responsible for calling rcu_read_[un]lock(). |
442 | * Returns a pointer to the DOI definition on success and NULL on failure. | 442 | * Returns a pointer to the DOI definition on success and NULL on failure. |
443 | */ | 443 | */ |
444 | static struct cipso_v4_doi *cipso_v4_doi_search(u32 doi) | 444 | static struct cipso_v4_doi *cipso_v4_doi_search(u32 doi) |
@@ -1293,7 +1293,7 @@ static int cipso_v4_gentag_rbm(const struct cipso_v4_doi *doi_def, | |||
1293 | return ret_val; | 1293 | return ret_val; |
1294 | 1294 | ||
1295 | /* This will send packets using the "optimized" format when | 1295 | /* This will send packets using the "optimized" format when |
1296 | * possibile as specified in section 3.4.2.6 of the | 1296 | * possible as specified in section 3.4.2.6 of the |
1297 | * CIPSO draft. */ | 1297 | * CIPSO draft. */ |
1298 | if (cipso_v4_rbm_optfmt && ret_val > 0 && ret_val <= 10) | 1298 | if (cipso_v4_rbm_optfmt && ret_val > 0 && ret_val <= 10) |
1299 | tag_len = 14; | 1299 | tag_len = 14; |
@@ -1752,7 +1752,7 @@ validate_return: | |||
1752 | } | 1752 | } |
1753 | 1753 | ||
1754 | /** | 1754 | /** |
1755 | * cipso_v4_error - Send the correct reponse for a bad packet | 1755 | * cipso_v4_error - Send the correct response for a bad packet |
1756 | * @skb: the packet | 1756 | * @skb: the packet |
1757 | * @error: the error code | 1757 | * @error: the error code |
1758 | * @gateway: CIPSO gateway flag | 1758 | * @gateway: CIPSO gateway flag |
@@ -1857,6 +1857,11 @@ static int cipso_v4_genopt(unsigned char *buf, u32 buf_len, | |||
1857 | return CIPSO_V4_HDR_LEN + ret_val; | 1857 | return CIPSO_V4_HDR_LEN + ret_val; |
1858 | } | 1858 | } |
1859 | 1859 | ||
1860 | static void opt_kfree_rcu(struct rcu_head *head) | ||
1861 | { | ||
1862 | kfree(container_of(head, struct ip_options_rcu, rcu)); | ||
1863 | } | ||
1864 | |||
1860 | /** | 1865 | /** |
1861 | * cipso_v4_sock_setattr - Add a CIPSO option to a socket | 1866 | * cipso_v4_sock_setattr - Add a CIPSO option to a socket |
1862 | * @sk: the socket | 1867 | * @sk: the socket |
@@ -1879,7 +1884,7 @@ int cipso_v4_sock_setattr(struct sock *sk, | |||
1879 | unsigned char *buf = NULL; | 1884 | unsigned char *buf = NULL; |
1880 | u32 buf_len; | 1885 | u32 buf_len; |
1881 | u32 opt_len; | 1886 | u32 opt_len; |
1882 | struct ip_options *opt = NULL; | 1887 | struct ip_options_rcu *old, *opt = NULL; |
1883 | struct inet_sock *sk_inet; | 1888 | struct inet_sock *sk_inet; |
1884 | struct inet_connection_sock *sk_conn; | 1889 | struct inet_connection_sock *sk_conn; |
1885 | 1890 | ||
@@ -1915,22 +1920,25 @@ int cipso_v4_sock_setattr(struct sock *sk, | |||
1915 | ret_val = -ENOMEM; | 1920 | ret_val = -ENOMEM; |
1916 | goto socket_setattr_failure; | 1921 | goto socket_setattr_failure; |
1917 | } | 1922 | } |
1918 | memcpy(opt->__data, buf, buf_len); | 1923 | memcpy(opt->opt.__data, buf, buf_len); |
1919 | opt->optlen = opt_len; | 1924 | opt->opt.optlen = opt_len; |
1920 | opt->cipso = sizeof(struct iphdr); | 1925 | opt->opt.cipso = sizeof(struct iphdr); |
1921 | kfree(buf); | 1926 | kfree(buf); |
1922 | buf = NULL; | 1927 | buf = NULL; |
1923 | 1928 | ||
1924 | sk_inet = inet_sk(sk); | 1929 | sk_inet = inet_sk(sk); |
1930 | |||
1931 | old = rcu_dereference_protected(sk_inet->inet_opt, sock_owned_by_user(sk)); | ||
1925 | if (sk_inet->is_icsk) { | 1932 | if (sk_inet->is_icsk) { |
1926 | sk_conn = inet_csk(sk); | 1933 | sk_conn = inet_csk(sk); |
1927 | if (sk_inet->opt) | 1934 | if (old) |
1928 | sk_conn->icsk_ext_hdr_len -= sk_inet->opt->optlen; | 1935 | sk_conn->icsk_ext_hdr_len -= old->opt.optlen; |
1929 | sk_conn->icsk_ext_hdr_len += opt->optlen; | 1936 | sk_conn->icsk_ext_hdr_len += opt->opt.optlen; |
1930 | sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie); | 1937 | sk_conn->icsk_sync_mss(sk, sk_conn->icsk_pmtu_cookie); |
1931 | } | 1938 | } |
1932 | opt = xchg(&sk_inet->opt, opt); | 1939 | rcu_assign_pointer(sk_inet->inet_opt, opt); |
1933 | kfree(opt); | 1940 | if (old) |
1941 | call_rcu(&old->rcu, opt_kfree_rcu); | ||
1934 | 1942 | ||
1935 | return 0; | 1943 | return 0; |
1936 | 1944 | ||
@@ -1960,7 +1968,7 @@ int cipso_v4_req_setattr(struct request_sock *req, | |||
1960 | unsigned char *buf = NULL; | 1968 | unsigned char *buf = NULL; |
1961 | u32 buf_len; | 1969 | u32 buf_len; |
1962 | u32 opt_len; | 1970 | u32 opt_len; |
1963 | struct ip_options *opt = NULL; | 1971 | struct ip_options_rcu *opt = NULL; |
1964 | struct inet_request_sock *req_inet; | 1972 | struct inet_request_sock *req_inet; |
1965 | 1973 | ||
1966 | /* We allocate the maximum CIPSO option size here so we are probably | 1974 | /* We allocate the maximum CIPSO option size here so we are probably |
@@ -1988,15 +1996,16 @@ int cipso_v4_req_setattr(struct request_sock *req, | |||
1988 | ret_val = -ENOMEM; | 1996 | ret_val = -ENOMEM; |
1989 | goto req_setattr_failure; | 1997 | goto req_setattr_failure; |
1990 | } | 1998 | } |
1991 | memcpy(opt->__data, buf, buf_len); | 1999 | memcpy(opt->opt.__data, buf, buf_len); |
1992 | opt->optlen = opt_len; | 2000 | opt->opt.optlen = opt_len; |
1993 | opt->cipso = sizeof(struct iphdr); | 2001 | opt->opt.cipso = sizeof(struct iphdr); |
1994 | kfree(buf); | 2002 | kfree(buf); |
1995 | buf = NULL; | 2003 | buf = NULL; |
1996 | 2004 | ||
1997 | req_inet = inet_rsk(req); | 2005 | req_inet = inet_rsk(req); |
1998 | opt = xchg(&req_inet->opt, opt); | 2006 | opt = xchg(&req_inet->opt, opt); |
1999 | kfree(opt); | 2007 | if (opt) |
2008 | call_rcu(&opt->rcu, opt_kfree_rcu); | ||
2000 | 2009 | ||
2001 | return 0; | 2010 | return 0; |
2002 | 2011 | ||
@@ -2016,34 +2025,34 @@ req_setattr_failure: | |||
2016 | * values on failure. | 2025 | * values on failure. |
2017 | * | 2026 | * |
2018 | */ | 2027 | */ |
2019 | static int cipso_v4_delopt(struct ip_options **opt_ptr) | 2028 | static int cipso_v4_delopt(struct ip_options_rcu **opt_ptr) |
2020 | { | 2029 | { |
2021 | int hdr_delta = 0; | 2030 | int hdr_delta = 0; |
2022 | struct ip_options *opt = *opt_ptr; | 2031 | struct ip_options_rcu *opt = *opt_ptr; |
2023 | 2032 | ||
2024 | if (opt->srr || opt->rr || opt->ts || opt->router_alert) { | 2033 | if (opt->opt.srr || opt->opt.rr || opt->opt.ts || opt->opt.router_alert) { |
2025 | u8 cipso_len; | 2034 | u8 cipso_len; |
2026 | u8 cipso_off; | 2035 | u8 cipso_off; |
2027 | unsigned char *cipso_ptr; | 2036 | unsigned char *cipso_ptr; |
2028 | int iter; | 2037 | int iter; |
2029 | int optlen_new; | 2038 | int optlen_new; |
2030 | 2039 | ||
2031 | cipso_off = opt->cipso - sizeof(struct iphdr); | 2040 | cipso_off = opt->opt.cipso - sizeof(struct iphdr); |
2032 | cipso_ptr = &opt->__data[cipso_off]; | 2041 | cipso_ptr = &opt->opt.__data[cipso_off]; |
2033 | cipso_len = cipso_ptr[1]; | 2042 | cipso_len = cipso_ptr[1]; |
2034 | 2043 | ||
2035 | if (opt->srr > opt->cipso) | 2044 | if (opt->opt.srr > opt->opt.cipso) |
2036 | opt->srr -= cipso_len; | 2045 | opt->opt.srr -= cipso_len; |
2037 | if (opt->rr > opt->cipso) | 2046 | if (opt->opt.rr > opt->opt.cipso) |
2038 | opt->rr -= cipso_len; | 2047 | opt->opt.rr -= cipso_len; |
2039 | if (opt->ts > opt->cipso) | 2048 | if (opt->opt.ts > opt->opt.cipso) |
2040 | opt->ts -= cipso_len; | 2049 | opt->opt.ts -= cipso_len; |
2041 | if (opt->router_alert > opt->cipso) | 2050 | if (opt->opt.router_alert > opt->opt.cipso) |
2042 | opt->router_alert -= cipso_len; | 2051 | opt->opt.router_alert -= cipso_len; |
2043 | opt->cipso = 0; | 2052 | opt->opt.cipso = 0; |
2044 | 2053 | ||
2045 | memmove(cipso_ptr, cipso_ptr + cipso_len, | 2054 | memmove(cipso_ptr, cipso_ptr + cipso_len, |
2046 | opt->optlen - cipso_off - cipso_len); | 2055 | opt->opt.optlen - cipso_off - cipso_len); |
2047 | 2056 | ||
2048 | /* determining the new total option length is tricky because of | 2057 | /* determining the new total option length is tricky because of |
2049 | * the padding necessary, the only thing i can think to do at | 2058 | * the padding necessary, the only thing i can think to do at |
@@ -2052,21 +2061,21 @@ static int cipso_v4_delopt(struct ip_options **opt_ptr) | |||
2052 | * from there we can determine the new total option length */ | 2061 | * from there we can determine the new total option length */ |
2053 | iter = 0; | 2062 | iter = 0; |
2054 | optlen_new = 0; | 2063 | optlen_new = 0; |
2055 | while (iter < opt->optlen) | 2064 | while (iter < opt->opt.optlen) |
2056 | if (opt->__data[iter] != IPOPT_NOP) { | 2065 | if (opt->opt.__data[iter] != IPOPT_NOP) { |
2057 | iter += opt->__data[iter + 1]; | 2066 | iter += opt->opt.__data[iter + 1]; |
2058 | optlen_new = iter; | 2067 | optlen_new = iter; |
2059 | } else | 2068 | } else |
2060 | iter++; | 2069 | iter++; |
2061 | hdr_delta = opt->optlen; | 2070 | hdr_delta = opt->opt.optlen; |
2062 | opt->optlen = (optlen_new + 3) & ~3; | 2071 | opt->opt.optlen = (optlen_new + 3) & ~3; |
2063 | hdr_delta -= opt->optlen; | 2072 | hdr_delta -= opt->opt.optlen; |
2064 | } else { | 2073 | } else { |
2065 | /* only the cipso option was present on the socket so we can | 2074 | /* only the cipso option was present on the socket so we can |
2066 | * remove the entire option struct */ | 2075 | * remove the entire option struct */ |
2067 | *opt_ptr = NULL; | 2076 | *opt_ptr = NULL; |
2068 | hdr_delta = opt->optlen; | 2077 | hdr_delta = opt->opt.optlen; |
2069 | kfree(opt); | 2078 | call_rcu(&opt->rcu, opt_kfree_rcu); |
2070 | } | 2079 | } |
2071 | 2080 | ||
2072 | return hdr_delta; | 2081 | return hdr_delta; |
@@ -2083,15 +2092,15 @@ static int cipso_v4_delopt(struct ip_options **opt_ptr) | |||
2083 | void cipso_v4_sock_delattr(struct sock *sk) | 2092 | void cipso_v4_sock_delattr(struct sock *sk) |
2084 | { | 2093 | { |
2085 | int hdr_delta; | 2094 | int hdr_delta; |
2086 | struct ip_options *opt; | 2095 | struct ip_options_rcu *opt; |
2087 | struct inet_sock *sk_inet; | 2096 | struct inet_sock *sk_inet; |
2088 | 2097 | ||
2089 | sk_inet = inet_sk(sk); | 2098 | sk_inet = inet_sk(sk); |
2090 | opt = sk_inet->opt; | 2099 | opt = rcu_dereference_protected(sk_inet->inet_opt, 1); |
2091 | if (opt == NULL || opt->cipso == 0) | 2100 | if (opt == NULL || opt->opt.cipso == 0) |
2092 | return; | 2101 | return; |
2093 | 2102 | ||
2094 | hdr_delta = cipso_v4_delopt(&sk_inet->opt); | 2103 | hdr_delta = cipso_v4_delopt(&sk_inet->inet_opt); |
2095 | if (sk_inet->is_icsk && hdr_delta > 0) { | 2104 | if (sk_inet->is_icsk && hdr_delta > 0) { |
2096 | struct inet_connection_sock *sk_conn = inet_csk(sk); | 2105 | struct inet_connection_sock *sk_conn = inet_csk(sk); |
2097 | sk_conn->icsk_ext_hdr_len -= hdr_delta; | 2106 | sk_conn->icsk_ext_hdr_len -= hdr_delta; |
@@ -2109,12 +2118,12 @@ void cipso_v4_sock_delattr(struct sock *sk) | |||
2109 | */ | 2118 | */ |
2110 | void cipso_v4_req_delattr(struct request_sock *req) | 2119 | void cipso_v4_req_delattr(struct request_sock *req) |
2111 | { | 2120 | { |
2112 | struct ip_options *opt; | 2121 | struct ip_options_rcu *opt; |
2113 | struct inet_request_sock *req_inet; | 2122 | struct inet_request_sock *req_inet; |
2114 | 2123 | ||
2115 | req_inet = inet_rsk(req); | 2124 | req_inet = inet_rsk(req); |
2116 | opt = req_inet->opt; | 2125 | opt = req_inet->opt; |
2117 | if (opt == NULL || opt->cipso == 0) | 2126 | if (opt == NULL || opt->opt.cipso == 0) |
2118 | return; | 2127 | return; |
2119 | 2128 | ||
2120 | cipso_v4_delopt(&req_inet->opt); | 2129 | cipso_v4_delopt(&req_inet->opt); |
@@ -2184,14 +2193,18 @@ getattr_return: | |||
2184 | */ | 2193 | */ |
2185 | int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) | 2194 | int cipso_v4_sock_getattr(struct sock *sk, struct netlbl_lsm_secattr *secattr) |
2186 | { | 2195 | { |
2187 | struct ip_options *opt; | 2196 | struct ip_options_rcu *opt; |
2197 | int res = -ENOMSG; | ||
2188 | 2198 | ||
2189 | opt = inet_sk(sk)->opt; | 2199 | rcu_read_lock(); |
2190 | if (opt == NULL || opt->cipso == 0) | 2200 | opt = rcu_dereference(inet_sk(sk)->inet_opt); |
2191 | return -ENOMSG; | 2201 | if (opt && opt->opt.cipso) |
2192 | 2202 | res = cipso_v4_getattr(opt->opt.__data + | |
2193 | return cipso_v4_getattr(opt->__data + opt->cipso - sizeof(struct iphdr), | 2203 | opt->opt.cipso - |
2194 | secattr); | 2204 | sizeof(struct iphdr), |
2205 | secattr); | ||
2206 | rcu_read_unlock(); | ||
2207 | return res; | ||
2195 | } | 2208 | } |
2196 | 2209 | ||
2197 | /** | 2210 | /** |
diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c index 85bd24ca4f6d..424fafbc8cb0 100644 --- a/net/ipv4/datagram.c +++ b/net/ipv4/datagram.c | |||
@@ -24,6 +24,7 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
24 | { | 24 | { |
25 | struct inet_sock *inet = inet_sk(sk); | 25 | struct inet_sock *inet = inet_sk(sk); |
26 | struct sockaddr_in *usin = (struct sockaddr_in *) uaddr; | 26 | struct sockaddr_in *usin = (struct sockaddr_in *) uaddr; |
27 | struct flowi4 *fl4; | ||
27 | struct rtable *rt; | 28 | struct rtable *rt; |
28 | __be32 saddr; | 29 | __be32 saddr; |
29 | int oif; | 30 | int oif; |
@@ -38,6 +39,8 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
38 | 39 | ||
39 | sk_dst_reset(sk); | 40 | sk_dst_reset(sk); |
40 | 41 | ||
42 | lock_sock(sk); | ||
43 | |||
41 | oif = sk->sk_bound_dev_if; | 44 | oif = sk->sk_bound_dev_if; |
42 | saddr = inet->inet_saddr; | 45 | saddr = inet->inet_saddr; |
43 | if (ipv4_is_multicast(usin->sin_addr.s_addr)) { | 46 | if (ipv4_is_multicast(usin->sin_addr.s_addr)) { |
@@ -46,7 +49,8 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
46 | if (!saddr) | 49 | if (!saddr) |
47 | saddr = inet->mc_addr; | 50 | saddr = inet->mc_addr; |
48 | } | 51 | } |
49 | rt = ip_route_connect(usin->sin_addr.s_addr, saddr, | 52 | fl4 = &inet->cork.fl.u.ip4; |
53 | rt = ip_route_connect(fl4, usin->sin_addr.s_addr, saddr, | ||
50 | RT_CONN_FLAGS(sk), oif, | 54 | RT_CONN_FLAGS(sk), oif, |
51 | sk->sk_protocol, | 55 | sk->sk_protocol, |
52 | inet->inet_sport, usin->sin_port, sk, true); | 56 | inet->inet_sport, usin->sin_port, sk, true); |
@@ -54,26 +58,30 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
54 | err = PTR_ERR(rt); | 58 | err = PTR_ERR(rt); |
55 | if (err == -ENETUNREACH) | 59 | if (err == -ENETUNREACH) |
56 | IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); | 60 | IP_INC_STATS_BH(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); |
57 | return err; | 61 | goto out; |
58 | } | 62 | } |
59 | 63 | ||
60 | if ((rt->rt_flags & RTCF_BROADCAST) && !sock_flag(sk, SOCK_BROADCAST)) { | 64 | if ((rt->rt_flags & RTCF_BROADCAST) && !sock_flag(sk, SOCK_BROADCAST)) { |
61 | ip_rt_put(rt); | 65 | ip_rt_put(rt); |
62 | return -EACCES; | 66 | err = -EACCES; |
67 | goto out; | ||
63 | } | 68 | } |
64 | if (!inet->inet_saddr) | 69 | if (!inet->inet_saddr) |
65 | inet->inet_saddr = rt->rt_src; /* Update source address */ | 70 | inet->inet_saddr = fl4->saddr; /* Update source address */ |
66 | if (!inet->inet_rcv_saddr) { | 71 | if (!inet->inet_rcv_saddr) { |
67 | inet->inet_rcv_saddr = rt->rt_src; | 72 | inet->inet_rcv_saddr = fl4->saddr; |
68 | if (sk->sk_prot->rehash) | 73 | if (sk->sk_prot->rehash) |
69 | sk->sk_prot->rehash(sk); | 74 | sk->sk_prot->rehash(sk); |
70 | } | 75 | } |
71 | inet->inet_daddr = rt->rt_dst; | 76 | inet->inet_daddr = fl4->daddr; |
72 | inet->inet_dport = usin->sin_port; | 77 | inet->inet_dport = usin->sin_port; |
73 | sk->sk_state = TCP_ESTABLISHED; | 78 | sk->sk_state = TCP_ESTABLISHED; |
74 | inet->inet_id = jiffies; | 79 | inet->inet_id = jiffies; |
75 | 80 | ||
76 | sk_dst_set(sk, &rt->dst); | 81 | sk_dst_set(sk, &rt->dst); |
77 | return 0; | 82 | err = 0; |
83 | out: | ||
84 | release_sock(sk); | ||
85 | return err; | ||
78 | } | 86 | } |
79 | EXPORT_SYMBOL(ip4_datagram_connect); | 87 | EXPORT_SYMBOL(ip4_datagram_connect); |
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 5345b0bee6df..0d4a184af16f 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c | |||
@@ -1369,7 +1369,7 @@ errout: | |||
1369 | 1369 | ||
1370 | static size_t inet_get_link_af_size(const struct net_device *dev) | 1370 | static size_t inet_get_link_af_size(const struct net_device *dev) |
1371 | { | 1371 | { |
1372 | struct in_device *in_dev = __in_dev_get_rtnl(dev); | 1372 | struct in_device *in_dev = rcu_dereference_rtnl(dev->ip_ptr); |
1373 | 1373 | ||
1374 | if (!in_dev) | 1374 | if (!in_dev) |
1375 | return 0; | 1375 | return 0; |
@@ -1379,7 +1379,7 @@ static size_t inet_get_link_af_size(const struct net_device *dev) | |||
1379 | 1379 | ||
1380 | static int inet_fill_link_af(struct sk_buff *skb, const struct net_device *dev) | 1380 | static int inet_fill_link_af(struct sk_buff *skb, const struct net_device *dev) |
1381 | { | 1381 | { |
1382 | struct in_device *in_dev = __in_dev_get_rtnl(dev); | 1382 | struct in_device *in_dev = rcu_dereference_rtnl(dev->ip_ptr); |
1383 | struct nlattr *nla; | 1383 | struct nlattr *nla; |
1384 | int i; | 1384 | int i; |
1385 | 1385 | ||
@@ -1680,7 +1680,7 @@ static void __devinet_sysctl_unregister(struct ipv4_devconf *cnf) | |||
1680 | return; | 1680 | return; |
1681 | 1681 | ||
1682 | cnf->sysctl = NULL; | 1682 | cnf->sysctl = NULL; |
1683 | unregister_sysctl_table(t->sysctl_header); | 1683 | unregister_net_sysctl_table(t->sysctl_header); |
1684 | kfree(t->dev_name); | 1684 | kfree(t->dev_name); |
1685 | kfree(t); | 1685 | kfree(t); |
1686 | } | 1686 | } |
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 03f994bcf7de..a5b413416da3 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c | |||
@@ -276,7 +276,7 @@ error: | |||
276 | 276 | ||
277 | static int esp_input_done2(struct sk_buff *skb, int err) | 277 | static int esp_input_done2(struct sk_buff *skb, int err) |
278 | { | 278 | { |
279 | struct iphdr *iph; | 279 | const struct iphdr *iph; |
280 | struct xfrm_state *x = xfrm_input_state(skb); | 280 | struct xfrm_state *x = xfrm_input_state(skb); |
281 | struct esp_data *esp = x->data; | 281 | struct esp_data *esp = x->data; |
282 | struct crypto_aead *aead = esp->aead; | 282 | struct crypto_aead *aead = esp->aead; |
@@ -484,7 +484,7 @@ static u32 esp4_get_mtu(struct xfrm_state *x, int mtu) | |||
484 | static void esp4_err(struct sk_buff *skb, u32 info) | 484 | static void esp4_err(struct sk_buff *skb, u32 info) |
485 | { | 485 | { |
486 | struct net *net = dev_net(skb->dev); | 486 | struct net *net = dev_net(skb->dev); |
487 | struct iphdr *iph = (struct iphdr *)skb->data; | 487 | const struct iphdr *iph = (const struct iphdr *)skb->data; |
488 | struct ip_esp_hdr *esph = (struct ip_esp_hdr *)(skb->data+(iph->ihl<<2)); | 488 | struct ip_esp_hdr *esph = (struct ip_esp_hdr *)(skb->data+(iph->ihl<<2)); |
489 | struct xfrm_state *x; | 489 | struct xfrm_state *x; |
490 | 490 | ||
@@ -492,7 +492,8 @@ static void esp4_err(struct sk_buff *skb, u32 info) | |||
492 | icmp_hdr(skb)->code != ICMP_FRAG_NEEDED) | 492 | icmp_hdr(skb)->code != ICMP_FRAG_NEEDED) |
493 | return; | 493 | return; |
494 | 494 | ||
495 | x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET); | 495 | x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, |
496 | esph->spi, IPPROTO_ESP, AF_INET); | ||
496 | if (!x) | 497 | if (!x) |
497 | return; | 498 | return; |
498 | NETDEBUG(KERN_DEBUG "pmtu discovery on SA ESP/%08x/%08x\n", | 499 | NETDEBUG(KERN_DEBUG "pmtu discovery on SA ESP/%08x/%08x\n", |
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index 451088330bbb..22524716fe70 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <net/arp.h> | 44 | #include <net/arp.h> |
45 | #include <net/ip_fib.h> | 45 | #include <net/ip_fib.h> |
46 | #include <net/rtnetlink.h> | 46 | #include <net/rtnetlink.h> |
47 | #include <net/xfrm.h> | ||
47 | 48 | ||
48 | #ifndef CONFIG_IP_MULTIPLE_TABLES | 49 | #ifndef CONFIG_IP_MULTIPLE_TABLES |
49 | 50 | ||
@@ -188,9 +189,9 @@ EXPORT_SYMBOL(inet_dev_addr_type); | |||
188 | * - check, that packet arrived from expected physical interface. | 189 | * - check, that packet arrived from expected physical interface. |
189 | * called with rcu_read_lock() | 190 | * called with rcu_read_lock() |
190 | */ | 191 | */ |
191 | int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, | 192 | int fib_validate_source(struct sk_buff *skb, __be32 src, __be32 dst, u8 tos, |
192 | struct net_device *dev, __be32 *spec_dst, | 193 | int oif, struct net_device *dev, __be32 *spec_dst, |
193 | u32 *itag, u32 mark) | 194 | u32 *itag) |
194 | { | 195 | { |
195 | struct in_device *in_dev; | 196 | struct in_device *in_dev; |
196 | struct flowi4 fl4; | 197 | struct flowi4 fl4; |
@@ -202,7 +203,6 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, | |||
202 | 203 | ||
203 | fl4.flowi4_oif = 0; | 204 | fl4.flowi4_oif = 0; |
204 | fl4.flowi4_iif = oif; | 205 | fl4.flowi4_iif = oif; |
205 | fl4.flowi4_mark = mark; | ||
206 | fl4.daddr = src; | 206 | fl4.daddr = src; |
207 | fl4.saddr = dst; | 207 | fl4.saddr = dst; |
208 | fl4.flowi4_tos = tos; | 208 | fl4.flowi4_tos = tos; |
@@ -212,10 +212,12 @@ int fib_validate_source(__be32 src, __be32 dst, u8 tos, int oif, | |||
212 | in_dev = __in_dev_get_rcu(dev); | 212 | in_dev = __in_dev_get_rcu(dev); |
213 | if (in_dev) { | 213 | if (in_dev) { |
214 | no_addr = in_dev->ifa_list == NULL; | 214 | no_addr = in_dev->ifa_list == NULL; |
215 | rpf = IN_DEV_RPFILTER(in_dev); | 215 | |
216 | /* Ignore rp_filter for packets protected by IPsec. */ | ||
217 | rpf = secpath_exists(skb) ? 0 : IN_DEV_RPFILTER(in_dev); | ||
218 | |||
216 | accept_local = IN_DEV_ACCEPT_LOCAL(in_dev); | 219 | accept_local = IN_DEV_ACCEPT_LOCAL(in_dev); |
217 | if (mark && !IN_DEV_SRC_VMARK(in_dev)) | 220 | fl4.flowi4_mark = IN_DEV_SRC_VMARK(in_dev) ? skb->mark : 0; |
218 | fl4.flowi4_mark = 0; | ||
219 | } | 221 | } |
220 | 222 | ||
221 | if (in_dev == NULL) | 223 | if (in_dev == NULL) |
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index b92c86f6e9b3..6375c1c5f642 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
@@ -12,7 +12,7 @@ | |||
12 | * | 12 | * |
13 | * Hans Liss <hans.liss@its.uu.se> Uppsala Universitet | 13 | * Hans Liss <hans.liss@its.uu.se> Uppsala Universitet |
14 | * | 14 | * |
15 | * This work is based on the LPC-trie which is originally descibed in: | 15 | * This work is based on the LPC-trie which is originally described in: |
16 | * | 16 | * |
17 | * An experimental study of compression methods for dynamic tries | 17 | * An experimental study of compression methods for dynamic tries |
18 | * Stefan Nilsson and Matti Tikkanen. Algorithmica, 33(1):19-33, 2002. | 18 | * Stefan Nilsson and Matti Tikkanen. Algorithmica, 33(1):19-33, 2002. |
@@ -126,7 +126,7 @@ struct tnode { | |||
126 | struct work_struct work; | 126 | struct work_struct work; |
127 | struct tnode *tnode_free; | 127 | struct tnode *tnode_free; |
128 | }; | 128 | }; |
129 | struct rt_trie_node *child[0]; | 129 | struct rt_trie_node __rcu *child[0]; |
130 | }; | 130 | }; |
131 | 131 | ||
132 | #ifdef CONFIG_IP_FIB_TRIE_STATS | 132 | #ifdef CONFIG_IP_FIB_TRIE_STATS |
@@ -151,7 +151,7 @@ struct trie_stat { | |||
151 | }; | 151 | }; |
152 | 152 | ||
153 | struct trie { | 153 | struct trie { |
154 | struct rt_trie_node *trie; | 154 | struct rt_trie_node __rcu *trie; |
155 | #ifdef CONFIG_IP_FIB_TRIE_STATS | 155 | #ifdef CONFIG_IP_FIB_TRIE_STATS |
156 | struct trie_use_stats stats; | 156 | struct trie_use_stats stats; |
157 | #endif | 157 | #endif |
@@ -177,16 +177,29 @@ static const int sync_pages = 128; | |||
177 | static struct kmem_cache *fn_alias_kmem __read_mostly; | 177 | static struct kmem_cache *fn_alias_kmem __read_mostly; |
178 | static struct kmem_cache *trie_leaf_kmem __read_mostly; | 178 | static struct kmem_cache *trie_leaf_kmem __read_mostly; |
179 | 179 | ||
180 | static inline struct tnode *node_parent(struct rt_trie_node *node) | 180 | /* |
181 | * caller must hold RTNL | ||
182 | */ | ||
183 | static inline struct tnode *node_parent(const struct rt_trie_node *node) | ||
181 | { | 184 | { |
182 | return (struct tnode *)(node->parent & ~NODE_TYPE_MASK); | 185 | unsigned long parent; |
186 | |||
187 | parent = rcu_dereference_index_check(node->parent, lockdep_rtnl_is_held()); | ||
188 | |||
189 | return (struct tnode *)(parent & ~NODE_TYPE_MASK); | ||
183 | } | 190 | } |
184 | 191 | ||
185 | static inline struct tnode *node_parent_rcu(struct rt_trie_node *node) | 192 | /* |
193 | * caller must hold RCU read lock or RTNL | ||
194 | */ | ||
195 | static inline struct tnode *node_parent_rcu(const struct rt_trie_node *node) | ||
186 | { | 196 | { |
187 | struct tnode *ret = node_parent(node); | 197 | unsigned long parent; |
198 | |||
199 | parent = rcu_dereference_index_check(node->parent, rcu_read_lock_held() || | ||
200 | lockdep_rtnl_is_held()); | ||
188 | 201 | ||
189 | return rcu_dereference_rtnl(ret); | 202 | return (struct tnode *)(parent & ~NODE_TYPE_MASK); |
190 | } | 203 | } |
191 | 204 | ||
192 | /* Same as rcu_assign_pointer | 205 | /* Same as rcu_assign_pointer |
@@ -198,18 +211,24 @@ static inline void node_set_parent(struct rt_trie_node *node, struct tnode *ptr) | |||
198 | node->parent = (unsigned long)ptr | NODE_TYPE(node); | 211 | node->parent = (unsigned long)ptr | NODE_TYPE(node); |
199 | } | 212 | } |
200 | 213 | ||
201 | static inline struct rt_trie_node *tnode_get_child(struct tnode *tn, unsigned int i) | 214 | /* |
215 | * caller must hold RTNL | ||
216 | */ | ||
217 | static inline struct rt_trie_node *tnode_get_child(const struct tnode *tn, unsigned int i) | ||
202 | { | 218 | { |
203 | BUG_ON(i >= 1U << tn->bits); | 219 | BUG_ON(i >= 1U << tn->bits); |
204 | 220 | ||
205 | return tn->child[i]; | 221 | return rtnl_dereference(tn->child[i]); |
206 | } | 222 | } |
207 | 223 | ||
208 | static inline struct rt_trie_node *tnode_get_child_rcu(struct tnode *tn, unsigned int i) | 224 | /* |
225 | * caller must hold RCU read lock or RTNL | ||
226 | */ | ||
227 | static inline struct rt_trie_node *tnode_get_child_rcu(const struct tnode *tn, unsigned int i) | ||
209 | { | 228 | { |
210 | struct rt_trie_node *ret = tnode_get_child(tn, i); | 229 | BUG_ON(i >= 1U << tn->bits); |
211 | 230 | ||
212 | return rcu_dereference_rtnl(ret); | 231 | return rcu_dereference_rtnl(tn->child[i]); |
213 | } | 232 | } |
214 | 233 | ||
215 | static inline int tnode_child_length(const struct tnode *tn) | 234 | static inline int tnode_child_length(const struct tnode *tn) |
@@ -487,7 +506,7 @@ static inline void put_child(struct trie *t, struct tnode *tn, int i, | |||
487 | static void tnode_put_child_reorg(struct tnode *tn, int i, struct rt_trie_node *n, | 506 | static void tnode_put_child_reorg(struct tnode *tn, int i, struct rt_trie_node *n, |
488 | int wasfull) | 507 | int wasfull) |
489 | { | 508 | { |
490 | struct rt_trie_node *chi = tn->child[i]; | 509 | struct rt_trie_node *chi = rtnl_dereference(tn->child[i]); |
491 | int isfull; | 510 | int isfull; |
492 | 511 | ||
493 | BUG_ON(i >= 1<<tn->bits); | 512 | BUG_ON(i >= 1<<tn->bits); |
@@ -665,7 +684,7 @@ one_child: | |||
665 | for (i = 0; i < tnode_child_length(tn); i++) { | 684 | for (i = 0; i < tnode_child_length(tn); i++) { |
666 | struct rt_trie_node *n; | 685 | struct rt_trie_node *n; |
667 | 686 | ||
668 | n = tn->child[i]; | 687 | n = rtnl_dereference(tn->child[i]); |
669 | if (!n) | 688 | if (!n) |
670 | continue; | 689 | continue; |
671 | 690 | ||
@@ -679,6 +698,20 @@ one_child: | |||
679 | return (struct rt_trie_node *) tn; | 698 | return (struct rt_trie_node *) tn; |
680 | } | 699 | } |
681 | 700 | ||
701 | |||
702 | static void tnode_clean_free(struct tnode *tn) | ||
703 | { | ||
704 | int i; | ||
705 | struct tnode *tofree; | ||
706 | |||
707 | for (i = 0; i < tnode_child_length(tn); i++) { | ||
708 | tofree = (struct tnode *)rtnl_dereference(tn->child[i]); | ||
709 | if (tofree) | ||
710 | tnode_free(tofree); | ||
711 | } | ||
712 | tnode_free(tn); | ||
713 | } | ||
714 | |||
682 | static struct tnode *inflate(struct trie *t, struct tnode *tn) | 715 | static struct tnode *inflate(struct trie *t, struct tnode *tn) |
683 | { | 716 | { |
684 | struct tnode *oldtnode = tn; | 717 | struct tnode *oldtnode = tn; |
@@ -755,8 +788,8 @@ static struct tnode *inflate(struct trie *t, struct tnode *tn) | |||
755 | inode = (struct tnode *) node; | 788 | inode = (struct tnode *) node; |
756 | 789 | ||
757 | if (inode->bits == 1) { | 790 | if (inode->bits == 1) { |
758 | put_child(t, tn, 2*i, inode->child[0]); | 791 | put_child(t, tn, 2*i, rtnl_dereference(inode->child[0])); |
759 | put_child(t, tn, 2*i+1, inode->child[1]); | 792 | put_child(t, tn, 2*i+1, rtnl_dereference(inode->child[1])); |
760 | 793 | ||
761 | tnode_free_safe(inode); | 794 | tnode_free_safe(inode); |
762 | continue; | 795 | continue; |
@@ -797,8 +830,8 @@ static struct tnode *inflate(struct trie *t, struct tnode *tn) | |||
797 | 830 | ||
798 | size = tnode_child_length(left); | 831 | size = tnode_child_length(left); |
799 | for (j = 0; j < size; j++) { | 832 | for (j = 0; j < size; j++) { |
800 | put_child(t, left, j, inode->child[j]); | 833 | put_child(t, left, j, rtnl_dereference(inode->child[j])); |
801 | put_child(t, right, j, inode->child[j + size]); | 834 | put_child(t, right, j, rtnl_dereference(inode->child[j + size])); |
802 | } | 835 | } |
803 | put_child(t, tn, 2*i, resize(t, left)); | 836 | put_child(t, tn, 2*i, resize(t, left)); |
804 | put_child(t, tn, 2*i+1, resize(t, right)); | 837 | put_child(t, tn, 2*i+1, resize(t, right)); |
@@ -808,18 +841,8 @@ static struct tnode *inflate(struct trie *t, struct tnode *tn) | |||
808 | tnode_free_safe(oldtnode); | 841 | tnode_free_safe(oldtnode); |
809 | return tn; | 842 | return tn; |
810 | nomem: | 843 | nomem: |
811 | { | 844 | tnode_clean_free(tn); |
812 | int size = tnode_child_length(tn); | 845 | return ERR_PTR(-ENOMEM); |
813 | int j; | ||
814 | |||
815 | for (j = 0; j < size; j++) | ||
816 | if (tn->child[j]) | ||
817 | tnode_free((struct tnode *)tn->child[j]); | ||
818 | |||
819 | tnode_free(tn); | ||
820 | |||
821 | return ERR_PTR(-ENOMEM); | ||
822 | } | ||
823 | } | 846 | } |
824 | 847 | ||
825 | static struct tnode *halve(struct trie *t, struct tnode *tn) | 848 | static struct tnode *halve(struct trie *t, struct tnode *tn) |
@@ -890,18 +913,8 @@ static struct tnode *halve(struct trie *t, struct tnode *tn) | |||
890 | tnode_free_safe(oldtnode); | 913 | tnode_free_safe(oldtnode); |
891 | return tn; | 914 | return tn; |
892 | nomem: | 915 | nomem: |
893 | { | 916 | tnode_clean_free(tn); |
894 | int size = tnode_child_length(tn); | 917 | return ERR_PTR(-ENOMEM); |
895 | int j; | ||
896 | |||
897 | for (j = 0; j < size; j++) | ||
898 | if (tn->child[j]) | ||
899 | tnode_free((struct tnode *)tn->child[j]); | ||
900 | |||
901 | tnode_free(tn); | ||
902 | |||
903 | return ERR_PTR(-ENOMEM); | ||
904 | } | ||
905 | } | 918 | } |
906 | 919 | ||
907 | /* readside must use rcu_read_lock currently dump routines | 920 | /* readside must use rcu_read_lock currently dump routines |
@@ -1033,7 +1046,7 @@ static struct list_head *fib_insert_node(struct trie *t, u32 key, int plen) | |||
1033 | t_key cindex; | 1046 | t_key cindex; |
1034 | 1047 | ||
1035 | pos = 0; | 1048 | pos = 0; |
1036 | n = t->trie; | 1049 | n = rtnl_dereference(t->trie); |
1037 | 1050 | ||
1038 | /* If we point to NULL, stop. Either the tree is empty and we should | 1051 | /* If we point to NULL, stop. Either the tree is empty and we should |
1039 | * just put a new leaf in if, or we have reached an empty child slot, | 1052 | * just put a new leaf in if, or we have reached an empty child slot, |
@@ -1319,6 +1332,9 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg) | |||
1319 | } | 1332 | } |
1320 | } | 1333 | } |
1321 | 1334 | ||
1335 | if (!plen) | ||
1336 | tb->tb_num_default++; | ||
1337 | |||
1322 | list_add_tail_rcu(&new_fa->fa_list, | 1338 | list_add_tail_rcu(&new_fa->fa_list, |
1323 | (fa ? &fa->fa_list : fa_head)); | 1339 | (fa ? &fa->fa_list : fa_head)); |
1324 | 1340 | ||
@@ -1684,6 +1700,9 @@ int fib_table_delete(struct fib_table *tb, struct fib_config *cfg) | |||
1684 | 1700 | ||
1685 | list_del_rcu(&fa->fa_list); | 1701 | list_del_rcu(&fa->fa_list); |
1686 | 1702 | ||
1703 | if (!plen) | ||
1704 | tb->tb_num_default--; | ||
1705 | |||
1687 | if (list_empty(fa_head)) { | 1706 | if (list_empty(fa_head)) { |
1688 | hlist_del_rcu(&li->hlist); | 1707 | hlist_del_rcu(&li->hlist); |
1689 | free_leaf_info(li); | 1708 | free_leaf_info(li); |
@@ -1756,7 +1775,7 @@ static struct leaf *leaf_walk_rcu(struct tnode *p, struct rt_trie_node *c) | |||
1756 | continue; | 1775 | continue; |
1757 | 1776 | ||
1758 | if (IS_LEAF(c)) { | 1777 | if (IS_LEAF(c)) { |
1759 | prefetch(p->child[idx]); | 1778 | prefetch(rcu_dereference_rtnl(p->child[idx])); |
1760 | return (struct leaf *) c; | 1779 | return (struct leaf *) c; |
1761 | } | 1780 | } |
1762 | 1781 | ||
@@ -1974,13 +1993,11 @@ struct fib_table *fib_trie_table(u32 id) | |||
1974 | 1993 | ||
1975 | tb->tb_id = id; | 1994 | tb->tb_id = id; |
1976 | tb->tb_default = -1; | 1995 | tb->tb_default = -1; |
1996 | tb->tb_num_default = 0; | ||
1977 | 1997 | ||
1978 | t = (struct trie *) tb->tb_data; | 1998 | t = (struct trie *) tb->tb_data; |
1979 | memset(t, 0, sizeof(*t)); | 1999 | memset(t, 0, sizeof(*t)); |
1980 | 2000 | ||
1981 | if (id == RT_TABLE_LOCAL) | ||
1982 | pr_info("IPv4 FIB: Using LC-trie version %s\n", VERSION); | ||
1983 | |||
1984 | return tb; | 2001 | return tb; |
1985 | } | 2002 | } |
1986 | 2003 | ||
@@ -2272,7 +2289,7 @@ static void *fib_trie_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
2272 | 2289 | ||
2273 | /* walk rest of this hash chain */ | 2290 | /* walk rest of this hash chain */ |
2274 | h = tb->tb_id & (FIB_TABLE_HASHSZ - 1); | 2291 | h = tb->tb_id & (FIB_TABLE_HASHSZ - 1); |
2275 | while ( (tb_node = rcu_dereference(tb->tb_hlist.next)) ) { | 2292 | while ((tb_node = rcu_dereference(hlist_next_rcu(&tb->tb_hlist)))) { |
2276 | tb = hlist_entry(tb_node, struct fib_table, tb_hlist); | 2293 | tb = hlist_entry(tb_node, struct fib_table, tb_hlist); |
2277 | n = fib_trie_get_first(iter, (struct trie *) tb->tb_data); | 2294 | n = fib_trie_get_first(iter, (struct trie *) tb->tb_data); |
2278 | if (n) | 2295 | if (n) |
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index a91dc1611081..3f47585aad68 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c | |||
@@ -83,6 +83,7 @@ | |||
83 | #include <net/tcp.h> | 83 | #include <net/tcp.h> |
84 | #include <net/udp.h> | 84 | #include <net/udp.h> |
85 | #include <net/raw.h> | 85 | #include <net/raw.h> |
86 | #include <net/ping.h> | ||
86 | #include <linux/skbuff.h> | 87 | #include <linux/skbuff.h> |
87 | #include <net/sock.h> | 88 | #include <net/sock.h> |
88 | #include <linux/errno.h> | 89 | #include <linux/errno.h> |
@@ -108,8 +109,7 @@ struct icmp_bxm { | |||
108 | __be32 times[3]; | 109 | __be32 times[3]; |
109 | } data; | 110 | } data; |
110 | int head_len; | 111 | int head_len; |
111 | struct ip_options replyopts; | 112 | struct ip_options_data replyopts; |
112 | unsigned char optbuf[40]; | ||
113 | }; | 113 | }; |
114 | 114 | ||
115 | /* An array of errno for error messages from dest unreach. */ | 115 | /* An array of errno for error messages from dest unreach. */ |
@@ -291,13 +291,14 @@ static int icmp_glue_bits(void *from, char *to, int offset, int len, int odd, | |||
291 | } | 291 | } |
292 | 292 | ||
293 | static void icmp_push_reply(struct icmp_bxm *icmp_param, | 293 | static void icmp_push_reply(struct icmp_bxm *icmp_param, |
294 | struct flowi4 *fl4, | ||
294 | struct ipcm_cookie *ipc, struct rtable **rt) | 295 | struct ipcm_cookie *ipc, struct rtable **rt) |
295 | { | 296 | { |
296 | struct sock *sk; | 297 | struct sock *sk; |
297 | struct sk_buff *skb; | 298 | struct sk_buff *skb; |
298 | 299 | ||
299 | sk = icmp_sk(dev_net((*rt)->dst.dev)); | 300 | sk = icmp_sk(dev_net((*rt)->dst.dev)); |
300 | if (ip_append_data(sk, icmp_glue_bits, icmp_param, | 301 | if (ip_append_data(sk, fl4, icmp_glue_bits, icmp_param, |
301 | icmp_param->data_len+icmp_param->head_len, | 302 | icmp_param->data_len+icmp_param->head_len, |
302 | icmp_param->head_len, | 303 | icmp_param->head_len, |
303 | ipc, rt, MSG_DONTWAIT) < 0) { | 304 | ipc, rt, MSG_DONTWAIT) < 0) { |
@@ -316,7 +317,7 @@ static void icmp_push_reply(struct icmp_bxm *icmp_param, | |||
316 | icmp_param->head_len, csum); | 317 | icmp_param->head_len, csum); |
317 | icmph->checksum = csum_fold(csum); | 318 | icmph->checksum = csum_fold(csum); |
318 | skb->ip_summed = CHECKSUM_NONE; | 319 | skb->ip_summed = CHECKSUM_NONE; |
319 | ip_push_pending_frames(sk); | 320 | ip_push_pending_frames(sk, fl4); |
320 | } | 321 | } |
321 | } | 322 | } |
322 | 323 | ||
@@ -329,11 +330,12 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) | |||
329 | struct ipcm_cookie ipc; | 330 | struct ipcm_cookie ipc; |
330 | struct rtable *rt = skb_rtable(skb); | 331 | struct rtable *rt = skb_rtable(skb); |
331 | struct net *net = dev_net(rt->dst.dev); | 332 | struct net *net = dev_net(rt->dst.dev); |
333 | struct flowi4 fl4; | ||
332 | struct sock *sk; | 334 | struct sock *sk; |
333 | struct inet_sock *inet; | 335 | struct inet_sock *inet; |
334 | __be32 daddr; | 336 | __be32 daddr; |
335 | 337 | ||
336 | if (ip_options_echo(&icmp_param->replyopts, skb)) | 338 | if (ip_options_echo(&icmp_param->replyopts.opt.opt, skb)) |
337 | return; | 339 | return; |
338 | 340 | ||
339 | sk = icmp_xmit_lock(net); | 341 | sk = icmp_xmit_lock(net); |
@@ -344,65 +346,60 @@ static void icmp_reply(struct icmp_bxm *icmp_param, struct sk_buff *skb) | |||
344 | icmp_param->data.icmph.checksum = 0; | 346 | icmp_param->data.icmph.checksum = 0; |
345 | 347 | ||
346 | inet->tos = ip_hdr(skb)->tos; | 348 | inet->tos = ip_hdr(skb)->tos; |
347 | daddr = ipc.addr = rt->rt_src; | 349 | daddr = ipc.addr = ip_hdr(skb)->saddr; |
348 | ipc.opt = NULL; | 350 | ipc.opt = NULL; |
349 | ipc.tx_flags = 0; | 351 | ipc.tx_flags = 0; |
350 | if (icmp_param->replyopts.optlen) { | 352 | if (icmp_param->replyopts.opt.opt.optlen) { |
351 | ipc.opt = &icmp_param->replyopts; | 353 | ipc.opt = &icmp_param->replyopts.opt; |
352 | if (ipc.opt->srr) | 354 | if (ipc.opt->opt.srr) |
353 | daddr = icmp_param->replyopts.faddr; | 355 | daddr = icmp_param->replyopts.opt.opt.faddr; |
354 | } | ||
355 | { | ||
356 | struct flowi4 fl4 = { | ||
357 | .daddr = daddr, | ||
358 | .saddr = rt->rt_spec_dst, | ||
359 | .flowi4_tos = RT_TOS(ip_hdr(skb)->tos), | ||
360 | .flowi4_proto = IPPROTO_ICMP, | ||
361 | }; | ||
362 | security_skb_classify_flow(skb, flowi4_to_flowi(&fl4)); | ||
363 | rt = ip_route_output_key(net, &fl4); | ||
364 | if (IS_ERR(rt)) | ||
365 | goto out_unlock; | ||
366 | } | 356 | } |
357 | memset(&fl4, 0, sizeof(fl4)); | ||
358 | fl4.daddr = daddr; | ||
359 | fl4.saddr = rt->rt_spec_dst; | ||
360 | fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos); | ||
361 | fl4.flowi4_proto = IPPROTO_ICMP; | ||
362 | security_skb_classify_flow(skb, flowi4_to_flowi(&fl4)); | ||
363 | rt = ip_route_output_key(net, &fl4); | ||
364 | if (IS_ERR(rt)) | ||
365 | goto out_unlock; | ||
367 | if (icmpv4_xrlim_allow(net, rt, icmp_param->data.icmph.type, | 366 | if (icmpv4_xrlim_allow(net, rt, icmp_param->data.icmph.type, |
368 | icmp_param->data.icmph.code)) | 367 | icmp_param->data.icmph.code)) |
369 | icmp_push_reply(icmp_param, &ipc, &rt); | 368 | icmp_push_reply(icmp_param, &fl4, &ipc, &rt); |
370 | ip_rt_put(rt); | 369 | ip_rt_put(rt); |
371 | out_unlock: | 370 | out_unlock: |
372 | icmp_xmit_unlock(sk); | 371 | icmp_xmit_unlock(sk); |
373 | } | 372 | } |
374 | 373 | ||
375 | static struct rtable *icmp_route_lookup(struct net *net, struct sk_buff *skb_in, | 374 | static struct rtable *icmp_route_lookup(struct net *net, |
376 | struct iphdr *iph, | 375 | struct flowi4 *fl4, |
376 | struct sk_buff *skb_in, | ||
377 | const struct iphdr *iph, | ||
377 | __be32 saddr, u8 tos, | 378 | __be32 saddr, u8 tos, |
378 | int type, int code, | 379 | int type, int code, |
379 | struct icmp_bxm *param) | 380 | struct icmp_bxm *param) |
380 | { | 381 | { |
381 | struct flowi4 fl4 = { | ||
382 | .daddr = (param->replyopts.srr ? | ||
383 | param->replyopts.faddr : iph->saddr), | ||
384 | .saddr = saddr, | ||
385 | .flowi4_tos = RT_TOS(tos), | ||
386 | .flowi4_proto = IPPROTO_ICMP, | ||
387 | .fl4_icmp_type = type, | ||
388 | .fl4_icmp_code = code, | ||
389 | }; | ||
390 | struct rtable *rt, *rt2; | 382 | struct rtable *rt, *rt2; |
391 | int err; | 383 | int err; |
392 | 384 | ||
393 | security_skb_classify_flow(skb_in, flowi4_to_flowi(&fl4)); | 385 | memset(fl4, 0, sizeof(*fl4)); |
394 | rt = __ip_route_output_key(net, &fl4); | 386 | fl4->daddr = (param->replyopts.opt.opt.srr ? |
387 | param->replyopts.opt.opt.faddr : iph->saddr); | ||
388 | fl4->saddr = saddr; | ||
389 | fl4->flowi4_tos = RT_TOS(tos); | ||
390 | fl4->flowi4_proto = IPPROTO_ICMP; | ||
391 | fl4->fl4_icmp_type = type; | ||
392 | fl4->fl4_icmp_code = code; | ||
393 | security_skb_classify_flow(skb_in, flowi4_to_flowi(fl4)); | ||
394 | rt = __ip_route_output_key(net, fl4); | ||
395 | if (IS_ERR(rt)) | 395 | if (IS_ERR(rt)) |
396 | return rt; | 396 | return rt; |
397 | 397 | ||
398 | /* No need to clone since we're just using its address. */ | 398 | /* No need to clone since we're just using its address. */ |
399 | rt2 = rt; | 399 | rt2 = rt; |
400 | 400 | ||
401 | if (!fl4.saddr) | ||
402 | fl4.saddr = rt->rt_src; | ||
403 | |||
404 | rt = (struct rtable *) xfrm_lookup(net, &rt->dst, | 401 | rt = (struct rtable *) xfrm_lookup(net, &rt->dst, |
405 | flowi4_to_flowi(&fl4), NULL, 0); | 402 | flowi4_to_flowi(fl4), NULL, 0); |
406 | if (!IS_ERR(rt)) { | 403 | if (!IS_ERR(rt)) { |
407 | if (rt != rt2) | 404 | if (rt != rt2) |
408 | return rt; | 405 | return rt; |
@@ -411,19 +408,19 @@ static struct rtable *icmp_route_lookup(struct net *net, struct sk_buff *skb_in, | |||
411 | } else | 408 | } else |
412 | return rt; | 409 | return rt; |
413 | 410 | ||
414 | err = xfrm_decode_session_reverse(skb_in, flowi4_to_flowi(&fl4), AF_INET); | 411 | err = xfrm_decode_session_reverse(skb_in, flowi4_to_flowi(fl4), AF_INET); |
415 | if (err) | 412 | if (err) |
416 | goto relookup_failed; | 413 | goto relookup_failed; |
417 | 414 | ||
418 | if (inet_addr_type(net, fl4.saddr) == RTN_LOCAL) { | 415 | if (inet_addr_type(net, fl4->saddr) == RTN_LOCAL) { |
419 | rt2 = __ip_route_output_key(net, &fl4); | 416 | rt2 = __ip_route_output_key(net, fl4); |
420 | if (IS_ERR(rt2)) | 417 | if (IS_ERR(rt2)) |
421 | err = PTR_ERR(rt2); | 418 | err = PTR_ERR(rt2); |
422 | } else { | 419 | } else { |
423 | struct flowi4 fl4_2 = {}; | 420 | struct flowi4 fl4_2 = {}; |
424 | unsigned long orefdst; | 421 | unsigned long orefdst; |
425 | 422 | ||
426 | fl4_2.daddr = fl4.saddr; | 423 | fl4_2.daddr = fl4->saddr; |
427 | rt2 = ip_route_output_key(net, &fl4_2); | 424 | rt2 = ip_route_output_key(net, &fl4_2); |
428 | if (IS_ERR(rt2)) { | 425 | if (IS_ERR(rt2)) { |
429 | err = PTR_ERR(rt2); | 426 | err = PTR_ERR(rt2); |
@@ -431,7 +428,7 @@ static struct rtable *icmp_route_lookup(struct net *net, struct sk_buff *skb_in, | |||
431 | } | 428 | } |
432 | /* Ugh! */ | 429 | /* Ugh! */ |
433 | orefdst = skb_in->_skb_refdst; /* save old refdst */ | 430 | orefdst = skb_in->_skb_refdst; /* save old refdst */ |
434 | err = ip_route_input(skb_in, fl4.daddr, fl4.saddr, | 431 | err = ip_route_input(skb_in, fl4->daddr, fl4->saddr, |
435 | RT_TOS(tos), rt2->dst.dev); | 432 | RT_TOS(tos), rt2->dst.dev); |
436 | 433 | ||
437 | dst_release(&rt2->dst); | 434 | dst_release(&rt2->dst); |
@@ -443,7 +440,7 @@ static struct rtable *icmp_route_lookup(struct net *net, struct sk_buff *skb_in, | |||
443 | goto relookup_failed; | 440 | goto relookup_failed; |
444 | 441 | ||
445 | rt2 = (struct rtable *) xfrm_lookup(net, &rt2->dst, | 442 | rt2 = (struct rtable *) xfrm_lookup(net, &rt2->dst, |
446 | flowi4_to_flowi(&fl4), NULL, | 443 | flowi4_to_flowi(fl4), NULL, |
447 | XFRM_LOOKUP_ICMP); | 444 | XFRM_LOOKUP_ICMP); |
448 | if (!IS_ERR(rt2)) { | 445 | if (!IS_ERR(rt2)) { |
449 | dst_release(&rt->dst); | 446 | dst_release(&rt->dst); |
@@ -482,6 +479,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) | |||
482 | struct icmp_bxm icmp_param; | 479 | struct icmp_bxm icmp_param; |
483 | struct rtable *rt = skb_rtable(skb_in); | 480 | struct rtable *rt = skb_rtable(skb_in); |
484 | struct ipcm_cookie ipc; | 481 | struct ipcm_cookie ipc; |
482 | struct flowi4 fl4; | ||
485 | __be32 saddr; | 483 | __be32 saddr; |
486 | u8 tos; | 484 | u8 tos; |
487 | struct net *net; | 485 | struct net *net; |
@@ -581,7 +579,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) | |||
581 | IPTOS_PREC_INTERNETCONTROL) : | 579 | IPTOS_PREC_INTERNETCONTROL) : |
582 | iph->tos; | 580 | iph->tos; |
583 | 581 | ||
584 | if (ip_options_echo(&icmp_param.replyopts, skb_in)) | 582 | if (ip_options_echo(&icmp_param.replyopts.opt.opt, skb_in)) |
585 | goto out_unlock; | 583 | goto out_unlock; |
586 | 584 | ||
587 | 585 | ||
@@ -597,10 +595,10 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) | |||
597 | icmp_param.offset = skb_network_offset(skb_in); | 595 | icmp_param.offset = skb_network_offset(skb_in); |
598 | inet_sk(sk)->tos = tos; | 596 | inet_sk(sk)->tos = tos; |
599 | ipc.addr = iph->saddr; | 597 | ipc.addr = iph->saddr; |
600 | ipc.opt = &icmp_param.replyopts; | 598 | ipc.opt = &icmp_param.replyopts.opt; |
601 | ipc.tx_flags = 0; | 599 | ipc.tx_flags = 0; |
602 | 600 | ||
603 | rt = icmp_route_lookup(net, skb_in, iph, saddr, tos, | 601 | rt = icmp_route_lookup(net, &fl4, skb_in, iph, saddr, tos, |
604 | type, code, &icmp_param); | 602 | type, code, &icmp_param); |
605 | if (IS_ERR(rt)) | 603 | if (IS_ERR(rt)) |
606 | goto out_unlock; | 604 | goto out_unlock; |
@@ -613,7 +611,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) | |||
613 | room = dst_mtu(&rt->dst); | 611 | room = dst_mtu(&rt->dst); |
614 | if (room > 576) | 612 | if (room > 576) |
615 | room = 576; | 613 | room = 576; |
616 | room -= sizeof(struct iphdr) + icmp_param.replyopts.optlen; | 614 | room -= sizeof(struct iphdr) + icmp_param.replyopts.opt.opt.optlen; |
617 | room -= sizeof(struct icmphdr); | 615 | room -= sizeof(struct icmphdr); |
618 | 616 | ||
619 | icmp_param.data_len = skb_in->len - icmp_param.offset; | 617 | icmp_param.data_len = skb_in->len - icmp_param.offset; |
@@ -621,7 +619,7 @@ void icmp_send(struct sk_buff *skb_in, int type, int code, __be32 info) | |||
621 | icmp_param.data_len = room; | 619 | icmp_param.data_len = room; |
622 | icmp_param.head_len = sizeof(struct icmphdr); | 620 | icmp_param.head_len = sizeof(struct icmphdr); |
623 | 621 | ||
624 | icmp_push_reply(&icmp_param, &ipc, &rt); | 622 | icmp_push_reply(&icmp_param, &fl4, &ipc, &rt); |
625 | ende: | 623 | ende: |
626 | ip_rt_put(rt); | 624 | ip_rt_put(rt); |
627 | out_unlock: | 625 | out_unlock: |
@@ -637,7 +635,7 @@ EXPORT_SYMBOL(icmp_send); | |||
637 | 635 | ||
638 | static void icmp_unreach(struct sk_buff *skb) | 636 | static void icmp_unreach(struct sk_buff *skb) |
639 | { | 637 | { |
640 | struct iphdr *iph; | 638 | const struct iphdr *iph; |
641 | struct icmphdr *icmph; | 639 | struct icmphdr *icmph; |
642 | int hash, protocol; | 640 | int hash, protocol; |
643 | const struct net_protocol *ipprot; | 641 | const struct net_protocol *ipprot; |
@@ -656,7 +654,7 @@ static void icmp_unreach(struct sk_buff *skb) | |||
656 | goto out_err; | 654 | goto out_err; |
657 | 655 | ||
658 | icmph = icmp_hdr(skb); | 656 | icmph = icmp_hdr(skb); |
659 | iph = (struct iphdr *)skb->data; | 657 | iph = (const struct iphdr *)skb->data; |
660 | 658 | ||
661 | if (iph->ihl < 5) /* Mangled header, drop. */ | 659 | if (iph->ihl < 5) /* Mangled header, drop. */ |
662 | goto out_err; | 660 | goto out_err; |
@@ -704,7 +702,7 @@ static void icmp_unreach(struct sk_buff *skb) | |||
704 | */ | 702 | */ |
705 | 703 | ||
706 | /* | 704 | /* |
707 | * Check the other end isnt violating RFC 1122. Some routers send | 705 | * Check the other end isn't violating RFC 1122. Some routers send |
708 | * bogus responses to broadcast frames. If you see this message | 706 | * bogus responses to broadcast frames. If you see this message |
709 | * first check your netmask matches at both ends, if it does then | 707 | * first check your netmask matches at both ends, if it does then |
710 | * get the other vendor to fix their kit. | 708 | * get the other vendor to fix their kit. |
@@ -729,7 +727,7 @@ static void icmp_unreach(struct sk_buff *skb) | |||
729 | if (!pskb_may_pull(skb, iph->ihl * 4 + 8)) | 727 | if (!pskb_may_pull(skb, iph->ihl * 4 + 8)) |
730 | goto out; | 728 | goto out; |
731 | 729 | ||
732 | iph = (struct iphdr *)skb->data; | 730 | iph = (const struct iphdr *)skb->data; |
733 | protocol = iph->protocol; | 731 | protocol = iph->protocol; |
734 | 732 | ||
735 | /* | 733 | /* |
@@ -758,7 +756,7 @@ out_err: | |||
758 | 756 | ||
759 | static void icmp_redirect(struct sk_buff *skb) | 757 | static void icmp_redirect(struct sk_buff *skb) |
760 | { | 758 | { |
761 | struct iphdr *iph; | 759 | const struct iphdr *iph; |
762 | 760 | ||
763 | if (skb->len < sizeof(struct iphdr)) | 761 | if (skb->len < sizeof(struct iphdr)) |
764 | goto out_err; | 762 | goto out_err; |
@@ -769,7 +767,7 @@ static void icmp_redirect(struct sk_buff *skb) | |||
769 | if (!pskb_may_pull(skb, sizeof(struct iphdr))) | 767 | if (!pskb_may_pull(skb, sizeof(struct iphdr))) |
770 | goto out; | 768 | goto out; |
771 | 769 | ||
772 | iph = (struct iphdr *)skb->data; | 770 | iph = (const struct iphdr *)skb->data; |
773 | 771 | ||
774 | switch (icmp_hdr(skb)->code & 7) { | 772 | switch (icmp_hdr(skb)->code & 7) { |
775 | case ICMP_REDIR_NET: | 773 | case ICMP_REDIR_NET: |
@@ -784,6 +782,15 @@ static void icmp_redirect(struct sk_buff *skb) | |||
784 | iph->saddr, skb->dev); | 782 | iph->saddr, skb->dev); |
785 | break; | 783 | break; |
786 | } | 784 | } |
785 | |||
786 | /* Ping wants to see redirects. | ||
787 | * Let's pretend they are errors of sorts... */ | ||
788 | if (iph->protocol == IPPROTO_ICMP && | ||
789 | iph->ihl >= 5 && | ||
790 | pskb_may_pull(skb, (iph->ihl<<2)+8)) { | ||
791 | ping_err(skb, icmp_hdr(skb)->un.gateway); | ||
792 | } | ||
793 | |||
787 | out: | 794 | out: |
788 | return; | 795 | return; |
789 | out_err: | 796 | out_err: |
@@ -933,12 +940,12 @@ static void icmp_address_reply(struct sk_buff *skb) | |||
933 | BUG_ON(mp == NULL); | 940 | BUG_ON(mp == NULL); |
934 | for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) { | 941 | for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) { |
935 | if (*mp == ifa->ifa_mask && | 942 | if (*mp == ifa->ifa_mask && |
936 | inet_ifa_match(rt->rt_src, ifa)) | 943 | inet_ifa_match(ip_hdr(skb)->saddr, ifa)) |
937 | break; | 944 | break; |
938 | } | 945 | } |
939 | if (!ifa && net_ratelimit()) { | 946 | if (!ifa && net_ratelimit()) { |
940 | printk(KERN_INFO "Wrong address mask %pI4 from %s/%pI4\n", | 947 | printk(KERN_INFO "Wrong address mask %pI4 from %s/%pI4\n", |
941 | mp, dev->name, &rt->rt_src); | 948 | mp, dev->name, &ip_hdr(skb)->saddr); |
942 | } | 949 | } |
943 | } | 950 | } |
944 | } | 951 | } |
@@ -1044,7 +1051,7 @@ error: | |||
1044 | */ | 1051 | */ |
1045 | static const struct icmp_control icmp_pointers[NR_ICMP_TYPES + 1] = { | 1052 | static const struct icmp_control icmp_pointers[NR_ICMP_TYPES + 1] = { |
1046 | [ICMP_ECHOREPLY] = { | 1053 | [ICMP_ECHOREPLY] = { |
1047 | .handler = icmp_discard, | 1054 | .handler = ping_rcv, |
1048 | }, | 1055 | }, |
1049 | [1] = { | 1056 | [1] = { |
1050 | .handler = icmp_discard, | 1057 | .handler = icmp_discard, |
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 1fd3d9ce8398..ec03c2fda6ce 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c | |||
@@ -309,6 +309,7 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size) | |||
309 | struct iphdr *pip; | 309 | struct iphdr *pip; |
310 | struct igmpv3_report *pig; | 310 | struct igmpv3_report *pig; |
311 | struct net *net = dev_net(dev); | 311 | struct net *net = dev_net(dev); |
312 | struct flowi4 fl4; | ||
312 | 313 | ||
313 | while (1) { | 314 | while (1) { |
314 | skb = alloc_skb(size + LL_ALLOCATED_SPACE(dev), | 315 | skb = alloc_skb(size + LL_ALLOCATED_SPACE(dev), |
@@ -321,18 +322,13 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size) | |||
321 | } | 322 | } |
322 | igmp_skb_size(skb) = size; | 323 | igmp_skb_size(skb) = size; |
323 | 324 | ||
324 | rt = ip_route_output_ports(net, NULL, IGMPV3_ALL_MCR, 0, | 325 | rt = ip_route_output_ports(net, &fl4, NULL, IGMPV3_ALL_MCR, 0, |
325 | 0, 0, | 326 | 0, 0, |
326 | IPPROTO_IGMP, 0, dev->ifindex); | 327 | IPPROTO_IGMP, 0, dev->ifindex); |
327 | if (IS_ERR(rt)) { | 328 | if (IS_ERR(rt)) { |
328 | kfree_skb(skb); | 329 | kfree_skb(skb); |
329 | return NULL; | 330 | return NULL; |
330 | } | 331 | } |
331 | if (rt->rt_src == 0) { | ||
332 | kfree_skb(skb); | ||
333 | ip_rt_put(rt); | ||
334 | return NULL; | ||
335 | } | ||
336 | 332 | ||
337 | skb_dst_set(skb, &rt->dst); | 333 | skb_dst_set(skb, &rt->dst); |
338 | skb->dev = dev; | 334 | skb->dev = dev; |
@@ -348,8 +344,8 @@ static struct sk_buff *igmpv3_newpack(struct net_device *dev, int size) | |||
348 | pip->tos = 0xc0; | 344 | pip->tos = 0xc0; |
349 | pip->frag_off = htons(IP_DF); | 345 | pip->frag_off = htons(IP_DF); |
350 | pip->ttl = 1; | 346 | pip->ttl = 1; |
351 | pip->daddr = rt->rt_dst; | 347 | pip->daddr = fl4.daddr; |
352 | pip->saddr = rt->rt_src; | 348 | pip->saddr = fl4.saddr; |
353 | pip->protocol = IPPROTO_IGMP; | 349 | pip->protocol = IPPROTO_IGMP; |
354 | pip->tot_len = 0; /* filled in later */ | 350 | pip->tot_len = 0; /* filled in later */ |
355 | ip_select_ident(pip, &rt->dst, NULL); | 351 | ip_select_ident(pip, &rt->dst, NULL); |
@@ -655,6 +651,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc, | |||
655 | struct net_device *dev = in_dev->dev; | 651 | struct net_device *dev = in_dev->dev; |
656 | struct net *net = dev_net(dev); | 652 | struct net *net = dev_net(dev); |
657 | __be32 group = pmc ? pmc->multiaddr : 0; | 653 | __be32 group = pmc ? pmc->multiaddr : 0; |
654 | struct flowi4 fl4; | ||
658 | __be32 dst; | 655 | __be32 dst; |
659 | 656 | ||
660 | if (type == IGMPV3_HOST_MEMBERSHIP_REPORT) | 657 | if (type == IGMPV3_HOST_MEMBERSHIP_REPORT) |
@@ -664,17 +661,12 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc, | |||
664 | else | 661 | else |
665 | dst = group; | 662 | dst = group; |
666 | 663 | ||
667 | rt = ip_route_output_ports(net, NULL, dst, 0, | 664 | rt = ip_route_output_ports(net, &fl4, NULL, dst, 0, |
668 | 0, 0, | 665 | 0, 0, |
669 | IPPROTO_IGMP, 0, dev->ifindex); | 666 | IPPROTO_IGMP, 0, dev->ifindex); |
670 | if (IS_ERR(rt)) | 667 | if (IS_ERR(rt)) |
671 | return -1; | 668 | return -1; |
672 | 669 | ||
673 | if (rt->rt_src == 0) { | ||
674 | ip_rt_put(rt); | ||
675 | return -1; | ||
676 | } | ||
677 | |||
678 | skb = alloc_skb(IGMP_SIZE+LL_ALLOCATED_SPACE(dev), GFP_ATOMIC); | 670 | skb = alloc_skb(IGMP_SIZE+LL_ALLOCATED_SPACE(dev), GFP_ATOMIC); |
679 | if (skb == NULL) { | 671 | if (skb == NULL) { |
680 | ip_rt_put(rt); | 672 | ip_rt_put(rt); |
@@ -695,7 +687,7 @@ static int igmp_send_report(struct in_device *in_dev, struct ip_mc_list *pmc, | |||
695 | iph->frag_off = htons(IP_DF); | 687 | iph->frag_off = htons(IP_DF); |
696 | iph->ttl = 1; | 688 | iph->ttl = 1; |
697 | iph->daddr = dst; | 689 | iph->daddr = dst; |
698 | iph->saddr = rt->rt_src; | 690 | iph->saddr = fl4.saddr; |
699 | iph->protocol = IPPROTO_IGMP; | 691 | iph->protocol = IPPROTO_IGMP; |
700 | ip_select_ident(iph, &rt->dst, NULL); | 692 | ip_select_ident(iph, &rt->dst, NULL); |
701 | ((u8*)&iph[1])[0] = IPOPT_RA; | 693 | ((u8*)&iph[1])[0] = IPOPT_RA; |
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 6c0b7f4a3d7d..3a2ba5632dff 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c | |||
@@ -73,7 +73,7 @@ int inet_csk_bind_conflict(const struct sock *sk, | |||
73 | !sk2->sk_bound_dev_if || | 73 | !sk2->sk_bound_dev_if || |
74 | sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) { | 74 | sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) { |
75 | if (!reuse || !sk2->sk_reuse || | 75 | if (!reuse || !sk2->sk_reuse || |
76 | ((1 << sk2->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))) { | 76 | sk2->sk_state == TCP_LISTEN) { |
77 | const __be32 sk2_rcv_saddr = sk_rcv_saddr(sk2); | 77 | const __be32 sk2_rcv_saddr = sk_rcv_saddr(sk2); |
78 | if (!sk2_rcv_saddr || !sk_rcv_saddr(sk) || | 78 | if (!sk2_rcv_saddr || !sk_rcv_saddr(sk) || |
79 | sk2_rcv_saddr == sk_rcv_saddr(sk)) | 79 | sk2_rcv_saddr == sk_rcv_saddr(sk)) |
@@ -122,8 +122,7 @@ again: | |||
122 | (tb->num_owners < smallest_size || smallest_size == -1)) { | 122 | (tb->num_owners < smallest_size || smallest_size == -1)) { |
123 | smallest_size = tb->num_owners; | 123 | smallest_size = tb->num_owners; |
124 | smallest_rover = rover; | 124 | smallest_rover = rover; |
125 | if (atomic_read(&hashinfo->bsockets) > (high - low) + 1 && | 125 | if (atomic_read(&hashinfo->bsockets) > (high - low) + 1) { |
126 | !inet_csk(sk)->icsk_af_ops->bind_conflict(sk, tb)) { | ||
127 | spin_unlock(&head->lock); | 126 | spin_unlock(&head->lock); |
128 | snum = smallest_rover; | 127 | snum = smallest_rover; |
129 | goto have_snum; | 128 | goto have_snum; |
@@ -355,26 +354,20 @@ struct dst_entry *inet_csk_route_req(struct sock *sk, | |||
355 | { | 354 | { |
356 | struct rtable *rt; | 355 | struct rtable *rt; |
357 | const struct inet_request_sock *ireq = inet_rsk(req); | 356 | const struct inet_request_sock *ireq = inet_rsk(req); |
358 | struct ip_options *opt = inet_rsk(req)->opt; | 357 | struct ip_options_rcu *opt = inet_rsk(req)->opt; |
359 | struct flowi4 fl4 = { | ||
360 | .flowi4_oif = sk->sk_bound_dev_if, | ||
361 | .flowi4_mark = sk->sk_mark, | ||
362 | .daddr = ((opt && opt->srr) ? | ||
363 | opt->faddr : ireq->rmt_addr), | ||
364 | .saddr = ireq->loc_addr, | ||
365 | .flowi4_tos = RT_CONN_FLAGS(sk), | ||
366 | .flowi4_proto = sk->sk_protocol, | ||
367 | .flowi4_flags = inet_sk_flowi_flags(sk), | ||
368 | .fl4_sport = inet_sk(sk)->inet_sport, | ||
369 | .fl4_dport = ireq->rmt_port, | ||
370 | }; | ||
371 | struct net *net = sock_net(sk); | 358 | struct net *net = sock_net(sk); |
359 | struct flowi4 fl4; | ||
372 | 360 | ||
361 | flowi4_init_output(&fl4, sk->sk_bound_dev_if, sk->sk_mark, | ||
362 | RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, | ||
363 | sk->sk_protocol, inet_sk_flowi_flags(sk), | ||
364 | (opt && opt->opt.srr) ? opt->opt.faddr : ireq->rmt_addr, | ||
365 | ireq->loc_addr, ireq->rmt_port, inet_sk(sk)->inet_sport); | ||
373 | security_req_classify_flow(req, flowi4_to_flowi(&fl4)); | 366 | security_req_classify_flow(req, flowi4_to_flowi(&fl4)); |
374 | rt = ip_route_output_flow(net, &fl4, sk); | 367 | rt = ip_route_output_flow(net, &fl4, sk); |
375 | if (IS_ERR(rt)) | 368 | if (IS_ERR(rt)) |
376 | goto no_route; | 369 | goto no_route; |
377 | if (opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway) | 370 | if (opt && opt->opt.is_strictroute && fl4.daddr != rt->rt_gateway) |
378 | goto route_err; | 371 | goto route_err; |
379 | return &rt->dst; | 372 | return &rt->dst; |
380 | 373 | ||
@@ -386,6 +379,39 @@ no_route: | |||
386 | } | 379 | } |
387 | EXPORT_SYMBOL_GPL(inet_csk_route_req); | 380 | EXPORT_SYMBOL_GPL(inet_csk_route_req); |
388 | 381 | ||
382 | struct dst_entry *inet_csk_route_child_sock(struct sock *sk, | ||
383 | struct sock *newsk, | ||
384 | const struct request_sock *req) | ||
385 | { | ||
386 | const struct inet_request_sock *ireq = inet_rsk(req); | ||
387 | struct inet_sock *newinet = inet_sk(newsk); | ||
388 | struct ip_options_rcu *opt = ireq->opt; | ||
389 | struct net *net = sock_net(sk); | ||
390 | struct flowi4 *fl4; | ||
391 | struct rtable *rt; | ||
392 | |||
393 | fl4 = &newinet->cork.fl.u.ip4; | ||
394 | flowi4_init_output(fl4, sk->sk_bound_dev_if, sk->sk_mark, | ||
395 | RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, | ||
396 | sk->sk_protocol, inet_sk_flowi_flags(sk), | ||
397 | (opt && opt->opt.srr) ? opt->opt.faddr : ireq->rmt_addr, | ||
398 | ireq->loc_addr, ireq->rmt_port, inet_sk(sk)->inet_sport); | ||
399 | security_req_classify_flow(req, flowi4_to_flowi(fl4)); | ||
400 | rt = ip_route_output_flow(net, fl4, sk); | ||
401 | if (IS_ERR(rt)) | ||
402 | goto no_route; | ||
403 | if (opt && opt->opt.is_strictroute && fl4->daddr != rt->rt_gateway) | ||
404 | goto route_err; | ||
405 | return &rt->dst; | ||
406 | |||
407 | route_err: | ||
408 | ip_rt_put(rt); | ||
409 | no_route: | ||
410 | IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES); | ||
411 | return NULL; | ||
412 | } | ||
413 | EXPORT_SYMBOL_GPL(inet_csk_route_child_sock); | ||
414 | |||
389 | static inline u32 inet_synq_hash(const __be32 raddr, const __be16 rport, | 415 | static inline u32 inet_synq_hash(const __be32 raddr, const __be16 rport, |
390 | const u32 rnd, const u32 synq_hsize) | 416 | const u32 rnd, const u32 synq_hsize) |
391 | { | 417 | { |
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 2ada17129fce..6ffe94ca5bc9 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c | |||
@@ -124,7 +124,7 @@ static int inet_csk_diag_fill(struct sock *sk, | |||
124 | 124 | ||
125 | #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) | 125 | #if defined(CONFIG_IPV6) || defined (CONFIG_IPV6_MODULE) |
126 | if (r->idiag_family == AF_INET6) { | 126 | if (r->idiag_family == AF_INET6) { |
127 | struct ipv6_pinfo *np = inet6_sk(sk); | 127 | const struct ipv6_pinfo *np = inet6_sk(sk); |
128 | 128 | ||
129 | ipv6_addr_copy((struct in6_addr *)r->id.idiag_src, | 129 | ipv6_addr_copy((struct in6_addr *)r->id.idiag_src, |
130 | &np->rcv_saddr); | 130 | &np->rcv_saddr); |
diff --git a/net/ipv4/inet_lro.c b/net/ipv4/inet_lro.c index 47038cb6c138..85a0f75dae64 100644 --- a/net/ipv4/inet_lro.c +++ b/net/ipv4/inet_lro.c | |||
@@ -51,8 +51,8 @@ MODULE_DESCRIPTION("Large Receive Offload (ipv4 / tcp)"); | |||
51 | * Basic tcp checks whether packet is suitable for LRO | 51 | * Basic tcp checks whether packet is suitable for LRO |
52 | */ | 52 | */ |
53 | 53 | ||
54 | static int lro_tcp_ip_check(struct iphdr *iph, struct tcphdr *tcph, | 54 | static int lro_tcp_ip_check(const struct iphdr *iph, const struct tcphdr *tcph, |
55 | int len, struct net_lro_desc *lro_desc) | 55 | int len, const struct net_lro_desc *lro_desc) |
56 | { | 56 | { |
57 | /* check ip header: don't aggregate padded frames */ | 57 | /* check ip header: don't aggregate padded frames */ |
58 | if (ntohs(iph->tot_len) != len) | 58 | if (ntohs(iph->tot_len) != len) |
diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c index dd1b20eca1a2..9df4e635fb5f 100644 --- a/net/ipv4/inetpeer.c +++ b/net/ipv4/inetpeer.c | |||
@@ -354,7 +354,8 @@ static void inetpeer_free_rcu(struct rcu_head *head) | |||
354 | } | 354 | } |
355 | 355 | ||
356 | /* May be called with local BH enabled. */ | 356 | /* May be called with local BH enabled. */ |
357 | static void unlink_from_pool(struct inet_peer *p, struct inet_peer_base *base) | 357 | static void unlink_from_pool(struct inet_peer *p, struct inet_peer_base *base, |
358 | struct inet_peer __rcu **stack[PEER_MAXDEPTH]) | ||
358 | { | 359 | { |
359 | int do_free; | 360 | int do_free; |
360 | 361 | ||
@@ -368,7 +369,6 @@ static void unlink_from_pool(struct inet_peer *p, struct inet_peer_base *base) | |||
368 | * We use refcnt=-1 to alert lockless readers this entry is deleted. | 369 | * We use refcnt=-1 to alert lockless readers this entry is deleted. |
369 | */ | 370 | */ |
370 | if (atomic_cmpxchg(&p->refcnt, 1, -1) == 1) { | 371 | if (atomic_cmpxchg(&p->refcnt, 1, -1) == 1) { |
371 | struct inet_peer __rcu **stack[PEER_MAXDEPTH]; | ||
372 | struct inet_peer __rcu ***stackptr, ***delp; | 372 | struct inet_peer __rcu ***stackptr, ***delp; |
373 | if (lookup(&p->daddr, stack, base) != p) | 373 | if (lookup(&p->daddr, stack, base) != p) |
374 | BUG(); | 374 | BUG(); |
@@ -422,7 +422,7 @@ static struct inet_peer_base *peer_to_base(struct inet_peer *p) | |||
422 | } | 422 | } |
423 | 423 | ||
424 | /* May be called with local BH enabled. */ | 424 | /* May be called with local BH enabled. */ |
425 | static int cleanup_once(unsigned long ttl) | 425 | static int cleanup_once(unsigned long ttl, struct inet_peer __rcu **stack[PEER_MAXDEPTH]) |
426 | { | 426 | { |
427 | struct inet_peer *p = NULL; | 427 | struct inet_peer *p = NULL; |
428 | 428 | ||
@@ -454,7 +454,7 @@ static int cleanup_once(unsigned long ttl) | |||
454 | * happen because of entry limits in route cache. */ | 454 | * happen because of entry limits in route cache. */ |
455 | return -1; | 455 | return -1; |
456 | 456 | ||
457 | unlink_from_pool(p, peer_to_base(p)); | 457 | unlink_from_pool(p, peer_to_base(p), stack); |
458 | return 0; | 458 | return 0; |
459 | } | 459 | } |
460 | 460 | ||
@@ -524,7 +524,7 @@ struct inet_peer *inet_getpeer(struct inetpeer_addr *daddr, int create) | |||
524 | 524 | ||
525 | if (base->total >= inet_peer_threshold) | 525 | if (base->total >= inet_peer_threshold) |
526 | /* Remove one less-recently-used entry. */ | 526 | /* Remove one less-recently-used entry. */ |
527 | cleanup_once(0); | 527 | cleanup_once(0, stack); |
528 | 528 | ||
529 | return p; | 529 | return p; |
530 | } | 530 | } |
@@ -540,6 +540,7 @@ static void peer_check_expire(unsigned long dummy) | |||
540 | { | 540 | { |
541 | unsigned long now = jiffies; | 541 | unsigned long now = jiffies; |
542 | int ttl, total; | 542 | int ttl, total; |
543 | struct inet_peer __rcu **stack[PEER_MAXDEPTH]; | ||
543 | 544 | ||
544 | total = compute_total(); | 545 | total = compute_total(); |
545 | if (total >= inet_peer_threshold) | 546 | if (total >= inet_peer_threshold) |
@@ -548,7 +549,7 @@ static void peer_check_expire(unsigned long dummy) | |||
548 | ttl = inet_peer_maxttl | 549 | ttl = inet_peer_maxttl |
549 | - (inet_peer_maxttl - inet_peer_minttl) / HZ * | 550 | - (inet_peer_maxttl - inet_peer_minttl) / HZ * |
550 | total / inet_peer_threshold * HZ; | 551 | total / inet_peer_threshold * HZ; |
551 | while (!cleanup_once(ttl)) { | 552 | while (!cleanup_once(ttl, stack)) { |
552 | if (jiffies != now) | 553 | if (jiffies != now) |
553 | break; | 554 | break; |
554 | } | 555 | } |
diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index 99461f09320f..3b34d1c86270 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 && ip_hdr(skb)->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_fragment.c b/net/ipv4/ip_fragment.c index a1151b8adf3c..b1d282f11be7 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
@@ -223,31 +223,30 @@ static void ip_expire(unsigned long arg) | |||
223 | 223 | ||
224 | if ((qp->q.last_in & INET_FRAG_FIRST_IN) && qp->q.fragments != NULL) { | 224 | if ((qp->q.last_in & INET_FRAG_FIRST_IN) && qp->q.fragments != NULL) { |
225 | struct sk_buff *head = qp->q.fragments; | 225 | struct sk_buff *head = qp->q.fragments; |
226 | const struct iphdr *iph; | ||
227 | int err; | ||
226 | 228 | ||
227 | rcu_read_lock(); | 229 | rcu_read_lock(); |
228 | head->dev = dev_get_by_index_rcu(net, qp->iif); | 230 | head->dev = dev_get_by_index_rcu(net, qp->iif); |
229 | if (!head->dev) | 231 | if (!head->dev) |
230 | goto out_rcu_unlock; | 232 | goto out_rcu_unlock; |
231 | 233 | ||
234 | /* skb dst is stale, drop it, and perform route lookup again */ | ||
235 | skb_dst_drop(head); | ||
236 | iph = ip_hdr(head); | ||
237 | err = ip_route_input_noref(head, iph->daddr, iph->saddr, | ||
238 | iph->tos, head->dev); | ||
239 | if (err) | ||
240 | goto out_rcu_unlock; | ||
241 | |||
232 | /* | 242 | /* |
233 | * Only search router table for the head fragment, | 243 | * Only an end host needs to send an ICMP |
234 | * when defraging timeout at PRE_ROUTING HOOK. | 244 | * "Fragment Reassembly Timeout" message, per RFC792. |
235 | */ | 245 | */ |
236 | if (qp->user == IP_DEFRAG_CONNTRACK_IN && !skb_dst(head)) { | 246 | if (qp->user == IP_DEFRAG_CONNTRACK_IN && |
237 | const struct iphdr *iph = ip_hdr(head); | 247 | skb_rtable(head)->rt_type != RTN_LOCAL) |
238 | int err = ip_route_input(head, iph->daddr, iph->saddr, | 248 | goto out_rcu_unlock; |
239 | iph->tos, head->dev); | ||
240 | if (unlikely(err)) | ||
241 | goto out_rcu_unlock; | ||
242 | |||
243 | /* | ||
244 | * Only an end host needs to send an ICMP | ||
245 | * "Fragment Reassembly Timeout" message, per RFC792. | ||
246 | */ | ||
247 | if (skb_rtable(head)->rt_type != RTN_LOCAL) | ||
248 | goto out_rcu_unlock; | ||
249 | 249 | ||
250 | } | ||
251 | 250 | ||
252 | /* Send an ICMP "Fragment Reassembly Timeout" message. */ | 251 | /* Send an ICMP "Fragment Reassembly Timeout" message. */ |
253 | icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0); | 252 | icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0); |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index da5941f18c3c..8871067560db 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -413,11 +413,6 @@ static struct ip_tunnel *ipgre_tunnel_locate(struct net *net, | |||
413 | 413 | ||
414 | dev_net_set(dev, net); | 414 | dev_net_set(dev, net); |
415 | 415 | ||
416 | if (strchr(name, '%')) { | ||
417 | if (dev_alloc_name(dev, name) < 0) | ||
418 | goto failed_free; | ||
419 | } | ||
420 | |||
421 | nt = netdev_priv(dev); | 416 | nt = netdev_priv(dev); |
422 | nt->parms = *parms; | 417 | nt->parms = *parms; |
423 | dev->rtnl_link_ops = &ipgre_link_ops; | 418 | dev->rtnl_link_ops = &ipgre_link_ops; |
@@ -462,7 +457,7 @@ static void ipgre_err(struct sk_buff *skb, u32 info) | |||
462 | by themself??? | 457 | by themself??? |
463 | */ | 458 | */ |
464 | 459 | ||
465 | struct iphdr *iph = (struct iphdr *)skb->data; | 460 | const struct iphdr *iph = (const struct iphdr *)skb->data; |
466 | __be16 *p = (__be16*)(skb->data+(iph->ihl<<2)); | 461 | __be16 *p = (__be16*)(skb->data+(iph->ihl<<2)); |
467 | int grehlen = (iph->ihl<<2) + 4; | 462 | int grehlen = (iph->ihl<<2) + 4; |
468 | const int type = icmp_hdr(skb)->type; | 463 | const int type = icmp_hdr(skb)->type; |
@@ -534,7 +529,7 @@ out: | |||
534 | rcu_read_unlock(); | 529 | rcu_read_unlock(); |
535 | } | 530 | } |
536 | 531 | ||
537 | static inline void ipgre_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb) | 532 | static inline void ipgre_ecn_decapsulate(const struct iphdr *iph, struct sk_buff *skb) |
538 | { | 533 | { |
539 | if (INET_ECN_is_ce(iph->tos)) { | 534 | if (INET_ECN_is_ce(iph->tos)) { |
540 | if (skb->protocol == htons(ETH_P_IP)) { | 535 | if (skb->protocol == htons(ETH_P_IP)) { |
@@ -546,19 +541,19 @@ static inline void ipgre_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb) | |||
546 | } | 541 | } |
547 | 542 | ||
548 | static inline u8 | 543 | static inline u8 |
549 | ipgre_ecn_encapsulate(u8 tos, struct iphdr *old_iph, struct sk_buff *skb) | 544 | ipgre_ecn_encapsulate(u8 tos, const struct iphdr *old_iph, struct sk_buff *skb) |
550 | { | 545 | { |
551 | u8 inner = 0; | 546 | u8 inner = 0; |
552 | if (skb->protocol == htons(ETH_P_IP)) | 547 | if (skb->protocol == htons(ETH_P_IP)) |
553 | inner = old_iph->tos; | 548 | inner = old_iph->tos; |
554 | else if (skb->protocol == htons(ETH_P_IPV6)) | 549 | else if (skb->protocol == htons(ETH_P_IPV6)) |
555 | inner = ipv6_get_dsfield((struct ipv6hdr *)old_iph); | 550 | inner = ipv6_get_dsfield((const struct ipv6hdr *)old_iph); |
556 | return INET_ECN_encapsulate(tos, inner); | 551 | return INET_ECN_encapsulate(tos, inner); |
557 | } | 552 | } |
558 | 553 | ||
559 | static int ipgre_rcv(struct sk_buff *skb) | 554 | static int ipgre_rcv(struct sk_buff *skb) |
560 | { | 555 | { |
561 | struct iphdr *iph; | 556 | const struct iphdr *iph; |
562 | u8 *h; | 557 | u8 *h; |
563 | __be16 flags; | 558 | __be16 flags; |
564 | __sum16 csum = 0; | 559 | __sum16 csum = 0; |
@@ -697,8 +692,9 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev | |||
697 | { | 692 | { |
698 | struct ip_tunnel *tunnel = netdev_priv(dev); | 693 | struct ip_tunnel *tunnel = netdev_priv(dev); |
699 | struct pcpu_tstats *tstats; | 694 | struct pcpu_tstats *tstats; |
700 | struct iphdr *old_iph = ip_hdr(skb); | 695 | const struct iphdr *old_iph = ip_hdr(skb); |
701 | struct iphdr *tiph; | 696 | const struct iphdr *tiph; |
697 | struct flowi4 fl4; | ||
702 | u8 tos; | 698 | u8 tos; |
703 | __be16 df; | 699 | __be16 df; |
704 | struct rtable *rt; /* Route to the other host */ | 700 | struct rtable *rt; /* Route to the other host */ |
@@ -714,7 +710,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev | |||
714 | 710 | ||
715 | if (dev->header_ops && dev->type == ARPHRD_IPGRE) { | 711 | if (dev->header_ops && dev->type == ARPHRD_IPGRE) { |
716 | gre_hlen = 0; | 712 | gre_hlen = 0; |
717 | tiph = (struct iphdr *)skb->data; | 713 | tiph = (const struct iphdr *)skb->data; |
718 | } else { | 714 | } else { |
719 | gre_hlen = tunnel->hlen; | 715 | gre_hlen = tunnel->hlen; |
720 | tiph = &tunnel->parms.iph; | 716 | tiph = &tunnel->parms.iph; |
@@ -735,14 +731,14 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev | |||
735 | } | 731 | } |
736 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 732 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
737 | else if (skb->protocol == htons(ETH_P_IPV6)) { | 733 | else if (skb->protocol == htons(ETH_P_IPV6)) { |
738 | struct in6_addr *addr6; | 734 | const struct in6_addr *addr6; |
739 | int addr_type; | 735 | int addr_type; |
740 | struct neighbour *neigh = skb_dst(skb)->neighbour; | 736 | struct neighbour *neigh = skb_dst(skb)->neighbour; |
741 | 737 | ||
742 | if (neigh == NULL) | 738 | if (neigh == NULL) |
743 | goto tx_error; | 739 | goto tx_error; |
744 | 740 | ||
745 | addr6 = (struct in6_addr *)&neigh->primary_key; | 741 | addr6 = (const struct in6_addr *)&neigh->primary_key; |
746 | addr_type = ipv6_addr_type(addr6); | 742 | addr_type = ipv6_addr_type(addr6); |
747 | 743 | ||
748 | if (addr_type == IPV6_ADDR_ANY) { | 744 | if (addr_type == IPV6_ADDR_ANY) { |
@@ -766,10 +762,10 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev | |||
766 | if (skb->protocol == htons(ETH_P_IP)) | 762 | if (skb->protocol == htons(ETH_P_IP)) |
767 | tos = old_iph->tos; | 763 | tos = old_iph->tos; |
768 | else if (skb->protocol == htons(ETH_P_IPV6)) | 764 | else if (skb->protocol == htons(ETH_P_IPV6)) |
769 | tos = ipv6_get_dsfield((struct ipv6hdr *)old_iph); | 765 | tos = ipv6_get_dsfield((const struct ipv6hdr *)old_iph); |
770 | } | 766 | } |
771 | 767 | ||
772 | rt = ip_route_output_gre(dev_net(dev), dst, tiph->saddr, | 768 | rt = ip_route_output_gre(dev_net(dev), &fl4, dst, tiph->saddr, |
773 | tunnel->parms.o_key, RT_TOS(tos), | 769 | tunnel->parms.o_key, RT_TOS(tos), |
774 | tunnel->parms.link); | 770 | tunnel->parms.link); |
775 | if (IS_ERR(rt)) { | 771 | if (IS_ERR(rt)) { |
@@ -873,15 +869,15 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev | |||
873 | iph->frag_off = df; | 869 | iph->frag_off = df; |
874 | iph->protocol = IPPROTO_GRE; | 870 | iph->protocol = IPPROTO_GRE; |
875 | iph->tos = ipgre_ecn_encapsulate(tos, old_iph, skb); | 871 | iph->tos = ipgre_ecn_encapsulate(tos, old_iph, skb); |
876 | iph->daddr = rt->rt_dst; | 872 | iph->daddr = fl4.daddr; |
877 | iph->saddr = rt->rt_src; | 873 | iph->saddr = fl4.saddr; |
878 | 874 | ||
879 | if ((iph->ttl = tiph->ttl) == 0) { | 875 | if ((iph->ttl = tiph->ttl) == 0) { |
880 | if (skb->protocol == htons(ETH_P_IP)) | 876 | if (skb->protocol == htons(ETH_P_IP)) |
881 | iph->ttl = old_iph->ttl; | 877 | iph->ttl = old_iph->ttl; |
882 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 878 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
883 | else if (skb->protocol == htons(ETH_P_IPV6)) | 879 | else if (skb->protocol == htons(ETH_P_IPV6)) |
884 | iph->ttl = ((struct ipv6hdr *)old_iph)->hop_limit; | 880 | iph->ttl = ((const struct ipv6hdr *)old_iph)->hop_limit; |
885 | #endif | 881 | #endif |
886 | else | 882 | else |
887 | iph->ttl = ip4_dst_hoplimit(&rt->dst); | 883 | iph->ttl = ip4_dst_hoplimit(&rt->dst); |
@@ -927,7 +923,7 @@ static int ipgre_tunnel_bind_dev(struct net_device *dev) | |||
927 | { | 923 | { |
928 | struct net_device *tdev = NULL; | 924 | struct net_device *tdev = NULL; |
929 | struct ip_tunnel *tunnel; | 925 | struct ip_tunnel *tunnel; |
930 | struct iphdr *iph; | 926 | const struct iphdr *iph; |
931 | int hlen = LL_MAX_HEADER; | 927 | int hlen = LL_MAX_HEADER; |
932 | int mtu = ETH_DATA_LEN; | 928 | int mtu = ETH_DATA_LEN; |
933 | int addend = sizeof(struct iphdr) + 4; | 929 | int addend = sizeof(struct iphdr) + 4; |
@@ -938,12 +934,14 @@ static int ipgre_tunnel_bind_dev(struct net_device *dev) | |||
938 | /* Guess output device to choose reasonable mtu and needed_headroom */ | 934 | /* Guess output device to choose reasonable mtu and needed_headroom */ |
939 | 935 | ||
940 | if (iph->daddr) { | 936 | if (iph->daddr) { |
941 | struct rtable *rt = ip_route_output_gre(dev_net(dev), | 937 | struct flowi4 fl4; |
942 | iph->daddr, iph->saddr, | 938 | struct rtable *rt; |
943 | tunnel->parms.o_key, | 939 | |
944 | RT_TOS(iph->tos), | 940 | rt = ip_route_output_gre(dev_net(dev), &fl4, |
945 | tunnel->parms.link); | 941 | iph->daddr, iph->saddr, |
946 | 942 | tunnel->parms.o_key, | |
943 | RT_TOS(iph->tos), | ||
944 | tunnel->parms.link); | ||
947 | if (!IS_ERR(rt)) { | 945 | if (!IS_ERR(rt)) { |
948 | tdev = rt->dst.dev; | 946 | tdev = rt->dst.dev; |
949 | ip_rt_put(rt); | 947 | ip_rt_put(rt); |
@@ -1180,7 +1178,7 @@ static int ipgre_header(struct sk_buff *skb, struct net_device *dev, | |||
1180 | 1178 | ||
1181 | static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr) | 1179 | static int ipgre_header_parse(const struct sk_buff *skb, unsigned char *haddr) |
1182 | { | 1180 | { |
1183 | struct iphdr *iph = (struct iphdr *) skb_mac_header(skb); | 1181 | const struct iphdr *iph = (const struct iphdr *) skb_mac_header(skb); |
1184 | memcpy(haddr, &iph->saddr, 4); | 1182 | memcpy(haddr, &iph->saddr, 4); |
1185 | return 4; | 1183 | return 4; |
1186 | } | 1184 | } |
@@ -1196,13 +1194,15 @@ static int ipgre_open(struct net_device *dev) | |||
1196 | struct ip_tunnel *t = netdev_priv(dev); | 1194 | struct ip_tunnel *t = netdev_priv(dev); |
1197 | 1195 | ||
1198 | if (ipv4_is_multicast(t->parms.iph.daddr)) { | 1196 | if (ipv4_is_multicast(t->parms.iph.daddr)) { |
1199 | struct rtable *rt = ip_route_output_gre(dev_net(dev), | 1197 | struct flowi4 fl4; |
1200 | t->parms.iph.daddr, | 1198 | struct rtable *rt; |
1201 | t->parms.iph.saddr, | 1199 | |
1202 | t->parms.o_key, | 1200 | rt = ip_route_output_gre(dev_net(dev), &fl4, |
1203 | RT_TOS(t->parms.iph.tos), | 1201 | t->parms.iph.daddr, |
1204 | t->parms.link); | 1202 | t->parms.iph.saddr, |
1205 | 1203 | t->parms.o_key, | |
1204 | RT_TOS(t->parms.iph.tos), | ||
1205 | t->parms.link); | ||
1206 | if (IS_ERR(rt)) | 1206 | if (IS_ERR(rt)) |
1207 | return -EADDRNOTAVAIL; | 1207 | return -EADDRNOTAVAIL; |
1208 | dev = rt->dst.dev; | 1208 | dev = rt->dst.dev; |
diff --git a/net/ipv4/ip_input.c b/net/ipv4/ip_input.c index d7b2b0987a3b..c8f48efc5fd3 100644 --- a/net/ipv4/ip_input.c +++ b/net/ipv4/ip_input.c | |||
@@ -268,7 +268,7 @@ int ip_local_deliver(struct sk_buff *skb) | |||
268 | static inline int ip_rcv_options(struct sk_buff *skb) | 268 | static inline int ip_rcv_options(struct sk_buff *skb) |
269 | { | 269 | { |
270 | struct ip_options *opt; | 270 | struct ip_options *opt; |
271 | struct iphdr *iph; | 271 | const struct iphdr *iph; |
272 | struct net_device *dev = skb->dev; | 272 | struct net_device *dev = skb->dev; |
273 | 273 | ||
274 | /* It looks as overkill, because not all | 274 | /* It looks as overkill, because not all |
@@ -374,7 +374,7 @@ drop: | |||
374 | */ | 374 | */ |
375 | int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) | 375 | int ip_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) |
376 | { | 376 | { |
377 | struct iphdr *iph; | 377 | const struct iphdr *iph; |
378 | u32 len; | 378 | u32 len; |
379 | 379 | ||
380 | /* When the interface is in promisc. mode, drop all the crap | 380 | /* When the interface is in promisc. mode, drop all the crap |
diff --git a/net/ipv4/ip_options.c b/net/ipv4/ip_options.c index 28a736f3442f..c3118e1cd3bb 100644 --- a/net/ipv4/ip_options.c +++ b/net/ipv4/ip_options.c | |||
@@ -36,8 +36,8 @@ | |||
36 | * saddr is address of outgoing interface. | 36 | * saddr is address of outgoing interface. |
37 | */ | 37 | */ |
38 | 38 | ||
39 | void ip_options_build(struct sk_buff * skb, struct ip_options * opt, | 39 | void ip_options_build(struct sk_buff *skb, struct ip_options *opt, |
40 | __be32 daddr, struct rtable *rt, int is_frag) | 40 | __be32 daddr, struct rtable *rt, int is_frag) |
41 | { | 41 | { |
42 | unsigned char *iph = skb_network_header(skb); | 42 | unsigned char *iph = skb_network_header(skb); |
43 | 43 | ||
@@ -50,9 +50,9 @@ void ip_options_build(struct sk_buff * skb, struct ip_options * opt, | |||
50 | 50 | ||
51 | if (!is_frag) { | 51 | if (!is_frag) { |
52 | if (opt->rr_needaddr) | 52 | if (opt->rr_needaddr) |
53 | ip_rt_get_source(iph+opt->rr+iph[opt->rr+2]-5, rt); | 53 | ip_rt_get_source(iph+opt->rr+iph[opt->rr+2]-5, skb, rt); |
54 | if (opt->ts_needaddr) | 54 | if (opt->ts_needaddr) |
55 | ip_rt_get_source(iph+opt->ts+iph[opt->ts+2]-9, rt); | 55 | ip_rt_get_source(iph+opt->ts+iph[opt->ts+2]-9, skb, rt); |
56 | if (opt->ts_needtime) { | 56 | if (opt->ts_needtime) { |
57 | struct timespec tv; | 57 | struct timespec tv; |
58 | __be32 midtime; | 58 | __be32 midtime; |
@@ -83,9 +83,9 @@ void ip_options_build(struct sk_buff * skb, struct ip_options * opt, | |||
83 | * NOTE: dopt cannot point to skb. | 83 | * NOTE: dopt cannot point to skb. |
84 | */ | 84 | */ |
85 | 85 | ||
86 | int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb) | 86 | int ip_options_echo(struct ip_options *dopt, struct sk_buff *skb) |
87 | { | 87 | { |
88 | struct ip_options *sopt; | 88 | const struct ip_options *sopt; |
89 | unsigned char *sptr, *dptr; | 89 | unsigned char *sptr, *dptr; |
90 | int soffset, doffset; | 90 | int soffset, doffset; |
91 | int optlen; | 91 | int optlen; |
@@ -95,10 +95,8 @@ int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb) | |||
95 | 95 | ||
96 | sopt = &(IPCB(skb)->opt); | 96 | sopt = &(IPCB(skb)->opt); |
97 | 97 | ||
98 | if (sopt->optlen == 0) { | 98 | if (sopt->optlen == 0) |
99 | dopt->optlen = 0; | ||
100 | return 0; | 99 | return 0; |
101 | } | ||
102 | 100 | ||
103 | sptr = skb_network_header(skb); | 101 | sptr = skb_network_header(skb); |
104 | dptr = dopt->__data; | 102 | dptr = dopt->__data; |
@@ -157,7 +155,7 @@ int ip_options_echo(struct ip_options * dopt, struct sk_buff * skb) | |||
157 | dopt->optlen += optlen; | 155 | dopt->optlen += optlen; |
158 | } | 156 | } |
159 | if (sopt->srr) { | 157 | if (sopt->srr) { |
160 | unsigned char * start = sptr+sopt->srr; | 158 | unsigned char *start = sptr+sopt->srr; |
161 | __be32 faddr; | 159 | __be32 faddr; |
162 | 160 | ||
163 | optlen = start[1]; | 161 | optlen = start[1]; |
@@ -329,7 +327,7 @@ int ip_options_compile(struct net *net, | |||
329 | pp_ptr = optptr + 2; | 327 | pp_ptr = optptr + 2; |
330 | goto error; | 328 | goto error; |
331 | } | 329 | } |
332 | if (skb) { | 330 | if (rt) { |
333 | memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4); | 331 | memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4); |
334 | opt->is_changed = 1; | 332 | opt->is_changed = 1; |
335 | } | 333 | } |
@@ -371,7 +369,7 @@ int ip_options_compile(struct net *net, | |||
371 | goto error; | 369 | goto error; |
372 | } | 370 | } |
373 | opt->ts = optptr - iph; | 371 | opt->ts = optptr - iph; |
374 | if (skb) { | 372 | if (rt) { |
375 | memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4); | 373 | memcpy(&optptr[optptr[2]-1], &rt->rt_spec_dst, 4); |
376 | timeptr = (__be32*)&optptr[optptr[2]+3]; | 374 | timeptr = (__be32*)&optptr[optptr[2]+3]; |
377 | } | 375 | } |
@@ -499,19 +497,19 @@ void ip_options_undo(struct ip_options * opt) | |||
499 | } | 497 | } |
500 | } | 498 | } |
501 | 499 | ||
502 | static struct ip_options *ip_options_get_alloc(const int optlen) | 500 | static struct ip_options_rcu *ip_options_get_alloc(const int optlen) |
503 | { | 501 | { |
504 | return kzalloc(sizeof(struct ip_options) + ((optlen + 3) & ~3), | 502 | return kzalloc(sizeof(struct ip_options_rcu) + ((optlen + 3) & ~3), |
505 | GFP_KERNEL); | 503 | GFP_KERNEL); |
506 | } | 504 | } |
507 | 505 | ||
508 | static int ip_options_get_finish(struct net *net, struct ip_options **optp, | 506 | static int ip_options_get_finish(struct net *net, struct ip_options_rcu **optp, |
509 | struct ip_options *opt, int optlen) | 507 | struct ip_options_rcu *opt, int optlen) |
510 | { | 508 | { |
511 | while (optlen & 3) | 509 | while (optlen & 3) |
512 | opt->__data[optlen++] = IPOPT_END; | 510 | opt->opt.__data[optlen++] = IPOPT_END; |
513 | opt->optlen = optlen; | 511 | opt->opt.optlen = optlen; |
514 | if (optlen && ip_options_compile(net, opt, NULL)) { | 512 | if (optlen && ip_options_compile(net, &opt->opt, NULL)) { |
515 | kfree(opt); | 513 | kfree(opt); |
516 | return -EINVAL; | 514 | return -EINVAL; |
517 | } | 515 | } |
@@ -520,29 +518,29 @@ static int ip_options_get_finish(struct net *net, struct ip_options **optp, | |||
520 | return 0; | 518 | return 0; |
521 | } | 519 | } |
522 | 520 | ||
523 | int ip_options_get_from_user(struct net *net, struct ip_options **optp, | 521 | int ip_options_get_from_user(struct net *net, struct ip_options_rcu **optp, |
524 | unsigned char __user *data, int optlen) | 522 | unsigned char __user *data, int optlen) |
525 | { | 523 | { |
526 | struct ip_options *opt = ip_options_get_alloc(optlen); | 524 | struct ip_options_rcu *opt = ip_options_get_alloc(optlen); |
527 | 525 | ||
528 | if (!opt) | 526 | if (!opt) |
529 | return -ENOMEM; | 527 | return -ENOMEM; |
530 | if (optlen && copy_from_user(opt->__data, data, optlen)) { | 528 | if (optlen && copy_from_user(opt->opt.__data, data, optlen)) { |
531 | kfree(opt); | 529 | kfree(opt); |
532 | return -EFAULT; | 530 | return -EFAULT; |
533 | } | 531 | } |
534 | return ip_options_get_finish(net, optp, opt, optlen); | 532 | return ip_options_get_finish(net, optp, opt, optlen); |
535 | } | 533 | } |
536 | 534 | ||
537 | int ip_options_get(struct net *net, struct ip_options **optp, | 535 | int ip_options_get(struct net *net, struct ip_options_rcu **optp, |
538 | unsigned char *data, int optlen) | 536 | unsigned char *data, int optlen) |
539 | { | 537 | { |
540 | struct ip_options *opt = ip_options_get_alloc(optlen); | 538 | struct ip_options_rcu *opt = ip_options_get_alloc(optlen); |
541 | 539 | ||
542 | if (!opt) | 540 | if (!opt) |
543 | return -ENOMEM; | 541 | return -ENOMEM; |
544 | if (optlen) | 542 | if (optlen) |
545 | memcpy(opt->__data, data, optlen); | 543 | memcpy(opt->opt.__data, data, optlen); |
546 | return ip_options_get_finish(net, optp, opt, optlen); | 544 | return ip_options_get_finish(net, optp, opt, optlen); |
547 | } | 545 | } |
548 | 546 | ||
@@ -555,7 +553,7 @@ void ip_forward_options(struct sk_buff *skb) | |||
555 | 553 | ||
556 | if (opt->rr_needaddr) { | 554 | if (opt->rr_needaddr) { |
557 | optptr = (unsigned char *)raw + opt->rr; | 555 | optptr = (unsigned char *)raw + opt->rr; |
558 | ip_rt_get_source(&optptr[optptr[2]-5], rt); | 556 | ip_rt_get_source(&optptr[optptr[2]-5], skb, rt); |
559 | opt->is_changed = 1; | 557 | opt->is_changed = 1; |
560 | } | 558 | } |
561 | if (opt->srr_is_hit) { | 559 | if (opt->srr_is_hit) { |
@@ -569,19 +567,18 @@ void ip_forward_options(struct sk_buff *skb) | |||
569 | ) { | 567 | ) { |
570 | if (srrptr + 3 > srrspace) | 568 | if (srrptr + 3 > srrspace) |
571 | break; | 569 | break; |
572 | if (memcmp(&rt->rt_dst, &optptr[srrptr-1], 4) == 0) | 570 | if (memcmp(&ip_hdr(skb)->daddr, &optptr[srrptr-1], 4) == 0) |
573 | break; | 571 | break; |
574 | } | 572 | } |
575 | if (srrptr + 3 <= srrspace) { | 573 | if (srrptr + 3 <= srrspace) { |
576 | opt->is_changed = 1; | 574 | opt->is_changed = 1; |
577 | ip_rt_get_source(&optptr[srrptr-1], rt); | 575 | ip_rt_get_source(&optptr[srrptr-1], skb, rt); |
578 | ip_hdr(skb)->daddr = rt->rt_dst; | ||
579 | optptr[2] = srrptr+4; | 576 | optptr[2] = srrptr+4; |
580 | } else if (net_ratelimit()) | 577 | } else if (net_ratelimit()) |
581 | printk(KERN_CRIT "ip_forward(): Argh! Destination lost!\n"); | 578 | printk(KERN_CRIT "ip_forward(): Argh! Destination lost!\n"); |
582 | if (opt->ts_needaddr) { | 579 | if (opt->ts_needaddr) { |
583 | optptr = raw + opt->ts; | 580 | optptr = raw + opt->ts; |
584 | ip_rt_get_source(&optptr[optptr[2]-9], rt); | 581 | ip_rt_get_source(&optptr[optptr[2]-9], skb, rt); |
585 | opt->is_changed = 1; | 582 | opt->is_changed = 1; |
586 | } | 583 | } |
587 | } | 584 | } |
@@ -603,7 +600,7 @@ int ip_options_rcv_srr(struct sk_buff *skb) | |||
603 | unsigned long orefdst; | 600 | unsigned long orefdst; |
604 | int err; | 601 | int err; |
605 | 602 | ||
606 | if (!opt->srr) | 603 | if (!rt) |
607 | return 0; | 604 | return 0; |
608 | 605 | ||
609 | if (skb->pkt_type != PACKET_HOST) | 606 | if (skb->pkt_type != PACKET_HOST) |
@@ -637,7 +634,7 @@ int ip_options_rcv_srr(struct sk_buff *skb) | |||
637 | if (rt2->rt_type != RTN_LOCAL) | 634 | if (rt2->rt_type != RTN_LOCAL) |
638 | break; | 635 | break; |
639 | /* Superfast 8) loopback forward */ | 636 | /* Superfast 8) loopback forward */ |
640 | memcpy(&iph->daddr, &optptr[srrptr-1], 4); | 637 | iph->daddr = nexthop; |
641 | opt->is_changed = 1; | 638 | opt->is_changed = 1; |
642 | } | 639 | } |
643 | if (srrptr <= srrspace) { | 640 | if (srrptr <= srrspace) { |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 67f241b97649..98af3697c718 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -140,14 +140,14 @@ static inline int ip_select_ttl(struct inet_sock *inet, struct dst_entry *dst) | |||
140 | * | 140 | * |
141 | */ | 141 | */ |
142 | int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk, | 142 | int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk, |
143 | __be32 saddr, __be32 daddr, struct ip_options *opt) | 143 | __be32 saddr, __be32 daddr, struct ip_options_rcu *opt) |
144 | { | 144 | { |
145 | struct inet_sock *inet = inet_sk(sk); | 145 | struct inet_sock *inet = inet_sk(sk); |
146 | struct rtable *rt = skb_rtable(skb); | 146 | struct rtable *rt = skb_rtable(skb); |
147 | struct iphdr *iph; | 147 | struct iphdr *iph; |
148 | 148 | ||
149 | /* Build the IP header. */ | 149 | /* Build the IP header. */ |
150 | skb_push(skb, sizeof(struct iphdr) + (opt ? opt->optlen : 0)); | 150 | skb_push(skb, sizeof(struct iphdr) + (opt ? opt->opt.optlen : 0)); |
151 | skb_reset_network_header(skb); | 151 | skb_reset_network_header(skb); |
152 | iph = ip_hdr(skb); | 152 | iph = ip_hdr(skb); |
153 | iph->version = 4; | 153 | iph->version = 4; |
@@ -158,14 +158,14 @@ int ip_build_and_send_pkt(struct sk_buff *skb, struct sock *sk, | |||
158 | else | 158 | else |
159 | iph->frag_off = 0; | 159 | iph->frag_off = 0; |
160 | iph->ttl = ip_select_ttl(inet, &rt->dst); | 160 | iph->ttl = ip_select_ttl(inet, &rt->dst); |
161 | iph->daddr = rt->rt_dst; | 161 | iph->daddr = (opt && opt->opt.srr ? opt->opt.faddr : daddr); |
162 | iph->saddr = rt->rt_src; | 162 | iph->saddr = saddr; |
163 | iph->protocol = sk->sk_protocol; | 163 | iph->protocol = sk->sk_protocol; |
164 | ip_select_ident(iph, &rt->dst, sk); | 164 | ip_select_ident(iph, &rt->dst, sk); |
165 | 165 | ||
166 | if (opt && opt->optlen) { | 166 | if (opt && opt->opt.optlen) { |
167 | iph->ihl += opt->optlen>>2; | 167 | iph->ihl += opt->opt.optlen>>2; |
168 | ip_options_build(skb, opt, daddr, rt, 0); | 168 | ip_options_build(skb, &opt->opt, daddr, rt, 0); |
169 | } | 169 | } |
170 | 170 | ||
171 | skb->priority = sk->sk_priority; | 171 | skb->priority = sk->sk_priority; |
@@ -312,11 +312,12 @@ int ip_output(struct sk_buff *skb) | |||
312 | !(IPCB(skb)->flags & IPSKB_REROUTED)); | 312 | !(IPCB(skb)->flags & IPSKB_REROUTED)); |
313 | } | 313 | } |
314 | 314 | ||
315 | int ip_queue_xmit(struct sk_buff *skb) | 315 | int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl) |
316 | { | 316 | { |
317 | struct sock *sk = skb->sk; | 317 | struct sock *sk = skb->sk; |
318 | struct inet_sock *inet = inet_sk(sk); | 318 | struct inet_sock *inet = inet_sk(sk); |
319 | struct ip_options *opt = inet->opt; | 319 | struct ip_options_rcu *inet_opt; |
320 | struct flowi4 *fl4; | ||
320 | struct rtable *rt; | 321 | struct rtable *rt; |
321 | struct iphdr *iph; | 322 | struct iphdr *iph; |
322 | int res; | 323 | int res; |
@@ -325,6 +326,8 @@ int ip_queue_xmit(struct sk_buff *skb) | |||
325 | * f.e. by something like SCTP. | 326 | * f.e. by something like SCTP. |
326 | */ | 327 | */ |
327 | rcu_read_lock(); | 328 | rcu_read_lock(); |
329 | inet_opt = rcu_dereference(inet->inet_opt); | ||
330 | fl4 = &fl->u.ip4; | ||
328 | rt = skb_rtable(skb); | 331 | rt = skb_rtable(skb); |
329 | if (rt != NULL) | 332 | if (rt != NULL) |
330 | goto packet_routed; | 333 | goto packet_routed; |
@@ -336,14 +339,14 @@ int ip_queue_xmit(struct sk_buff *skb) | |||
336 | 339 | ||
337 | /* Use correct destination address if we have options. */ | 340 | /* Use correct destination address if we have options. */ |
338 | daddr = inet->inet_daddr; | 341 | daddr = inet->inet_daddr; |
339 | if(opt && opt->srr) | 342 | if (inet_opt && inet_opt->opt.srr) |
340 | daddr = opt->faddr; | 343 | daddr = inet_opt->opt.faddr; |
341 | 344 | ||
342 | /* If this fails, retransmit mechanism of transport layer will | 345 | /* If this fails, retransmit mechanism of transport layer will |
343 | * keep trying until route appears or the connection times | 346 | * keep trying until route appears or the connection times |
344 | * itself out. | 347 | * itself out. |
345 | */ | 348 | */ |
346 | rt = ip_route_output_ports(sock_net(sk), sk, | 349 | rt = ip_route_output_ports(sock_net(sk), fl4, sk, |
347 | daddr, inet->inet_saddr, | 350 | daddr, inet->inet_saddr, |
348 | inet->inet_dport, | 351 | inet->inet_dport, |
349 | inet->inet_sport, | 352 | inet->inet_sport, |
@@ -357,11 +360,11 @@ int ip_queue_xmit(struct sk_buff *skb) | |||
357 | skb_dst_set_noref(skb, &rt->dst); | 360 | skb_dst_set_noref(skb, &rt->dst); |
358 | 361 | ||
359 | packet_routed: | 362 | packet_routed: |
360 | if (opt && opt->is_strictroute && rt->rt_dst != rt->rt_gateway) | 363 | if (inet_opt && inet_opt->opt.is_strictroute && fl4->daddr != rt->rt_gateway) |
361 | goto no_route; | 364 | goto no_route; |
362 | 365 | ||
363 | /* OK, we know where to send it, allocate and build IP header. */ | 366 | /* OK, we know where to send it, allocate and build IP header. */ |
364 | skb_push(skb, sizeof(struct iphdr) + (opt ? opt->optlen : 0)); | 367 | skb_push(skb, sizeof(struct iphdr) + (inet_opt ? inet_opt->opt.optlen : 0)); |
365 | skb_reset_network_header(skb); | 368 | skb_reset_network_header(skb); |
366 | iph = ip_hdr(skb); | 369 | iph = ip_hdr(skb); |
367 | *((__be16 *)iph) = htons((4 << 12) | (5 << 8) | (inet->tos & 0xff)); | 370 | *((__be16 *)iph) = htons((4 << 12) | (5 << 8) | (inet->tos & 0xff)); |
@@ -371,13 +374,13 @@ packet_routed: | |||
371 | iph->frag_off = 0; | 374 | iph->frag_off = 0; |
372 | iph->ttl = ip_select_ttl(inet, &rt->dst); | 375 | iph->ttl = ip_select_ttl(inet, &rt->dst); |
373 | iph->protocol = sk->sk_protocol; | 376 | iph->protocol = sk->sk_protocol; |
374 | iph->saddr = rt->rt_src; | 377 | iph->saddr = fl4->saddr; |
375 | iph->daddr = rt->rt_dst; | 378 | iph->daddr = fl4->daddr; |
376 | /* Transport layer set skb->h.foo itself. */ | 379 | /* Transport layer set skb->h.foo itself. */ |
377 | 380 | ||
378 | if (opt && opt->optlen) { | 381 | if (inet_opt && inet_opt->opt.optlen) { |
379 | iph->ihl += opt->optlen >> 2; | 382 | iph->ihl += inet_opt->opt.optlen >> 2; |
380 | ip_options_build(skb, opt, inet->inet_daddr, rt, 0); | 383 | ip_options_build(skb, &inet_opt->opt, inet->inet_daddr, rt, 0); |
381 | } | 384 | } |
382 | 385 | ||
383 | ip_select_ident_more(iph, &rt->dst, sk, | 386 | ip_select_ident_more(iph, &rt->dst, sk, |
@@ -603,7 +606,7 @@ slow_path: | |||
603 | /* IF: it doesn't fit, use 'mtu' - the data space left */ | 606 | /* IF: it doesn't fit, use 'mtu' - the data space left */ |
604 | if (len > mtu) | 607 | if (len > mtu) |
605 | len = mtu; | 608 | len = mtu; |
606 | /* IF: we are not sending upto and including the packet end | 609 | /* IF: we are not sending up to and including the packet end |
607 | then align the next start on an eight byte boundary */ | 610 | then align the next start on an eight byte boundary */ |
608 | if (len < left) { | 611 | if (len < left) { |
609 | len &= ~7; | 612 | len &= ~7; |
@@ -773,7 +776,9 @@ static inline int ip_ufo_append_data(struct sock *sk, | |||
773 | (length - transhdrlen)); | 776 | (length - transhdrlen)); |
774 | } | 777 | } |
775 | 778 | ||
776 | static int __ip_append_data(struct sock *sk, struct sk_buff_head *queue, | 779 | static int __ip_append_data(struct sock *sk, |
780 | struct flowi4 *fl4, | ||
781 | struct sk_buff_head *queue, | ||
777 | struct inet_cork *cork, | 782 | struct inet_cork *cork, |
778 | int getfrag(void *from, char *to, int offset, | 783 | int getfrag(void *from, char *to, int offset, |
779 | int len, int odd, struct sk_buff *skb), | 784 | int len, int odd, struct sk_buff *skb), |
@@ -805,7 +810,7 @@ static int __ip_append_data(struct sock *sk, struct sk_buff_head *queue, | |||
805 | maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen; | 810 | maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen; |
806 | 811 | ||
807 | if (cork->length + length > 0xFFFF - fragheaderlen) { | 812 | if (cork->length + length > 0xFFFF - fragheaderlen) { |
808 | ip_local_error(sk, EMSGSIZE, rt->rt_dst, inet->inet_dport, | 813 | ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport, |
809 | mtu-exthdrlen); | 814 | mtu-exthdrlen); |
810 | return -EMSGSIZE; | 815 | return -EMSGSIZE; |
811 | } | 816 | } |
@@ -1033,7 +1038,7 @@ static int ip_setup_cork(struct sock *sk, struct inet_cork *cork, | |||
1033 | struct ipcm_cookie *ipc, struct rtable **rtp) | 1038 | struct ipcm_cookie *ipc, struct rtable **rtp) |
1034 | { | 1039 | { |
1035 | struct inet_sock *inet = inet_sk(sk); | 1040 | struct inet_sock *inet = inet_sk(sk); |
1036 | struct ip_options *opt; | 1041 | struct ip_options_rcu *opt; |
1037 | struct rtable *rt; | 1042 | struct rtable *rt; |
1038 | 1043 | ||
1039 | /* | 1044 | /* |
@@ -1047,7 +1052,7 @@ static int ip_setup_cork(struct sock *sk, struct inet_cork *cork, | |||
1047 | if (unlikely(cork->opt == NULL)) | 1052 | if (unlikely(cork->opt == NULL)) |
1048 | return -ENOBUFS; | 1053 | return -ENOBUFS; |
1049 | } | 1054 | } |
1050 | memcpy(cork->opt, opt, sizeof(struct ip_options) + opt->optlen); | 1055 | memcpy(cork->opt, &opt->opt, sizeof(struct ip_options) + opt->opt.optlen); |
1051 | cork->flags |= IPCORK_OPT; | 1056 | cork->flags |= IPCORK_OPT; |
1052 | cork->addr = ipc->addr; | 1057 | cork->addr = ipc->addr; |
1053 | } | 1058 | } |
@@ -1080,7 +1085,7 @@ static int ip_setup_cork(struct sock *sk, struct inet_cork *cork, | |||
1080 | * | 1085 | * |
1081 | * LATER: length must be adjusted by pad at tail, when it is required. | 1086 | * LATER: length must be adjusted by pad at tail, when it is required. |
1082 | */ | 1087 | */ |
1083 | int ip_append_data(struct sock *sk, | 1088 | int ip_append_data(struct sock *sk, struct flowi4 *fl4, |
1084 | int getfrag(void *from, char *to, int offset, int len, | 1089 | int getfrag(void *from, char *to, int offset, int len, |
1085 | int odd, struct sk_buff *skb), | 1090 | int odd, struct sk_buff *skb), |
1086 | void *from, int length, int transhdrlen, | 1091 | void *from, int length, int transhdrlen, |
@@ -1094,24 +1099,25 @@ int ip_append_data(struct sock *sk, | |||
1094 | return 0; | 1099 | return 0; |
1095 | 1100 | ||
1096 | if (skb_queue_empty(&sk->sk_write_queue)) { | 1101 | if (skb_queue_empty(&sk->sk_write_queue)) { |
1097 | err = ip_setup_cork(sk, &inet->cork, ipc, rtp); | 1102 | err = ip_setup_cork(sk, &inet->cork.base, ipc, rtp); |
1098 | if (err) | 1103 | if (err) |
1099 | return err; | 1104 | return err; |
1100 | } else { | 1105 | } else { |
1101 | transhdrlen = 0; | 1106 | transhdrlen = 0; |
1102 | } | 1107 | } |
1103 | 1108 | ||
1104 | return __ip_append_data(sk, &sk->sk_write_queue, &inet->cork, getfrag, | 1109 | return __ip_append_data(sk, fl4, &sk->sk_write_queue, &inet->cork.base, getfrag, |
1105 | from, length, transhdrlen, flags); | 1110 | from, length, transhdrlen, flags); |
1106 | } | 1111 | } |
1107 | 1112 | ||
1108 | ssize_t ip_append_page(struct sock *sk, struct page *page, | 1113 | ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page, |
1109 | int offset, size_t size, int flags) | 1114 | int offset, size_t size, int flags) |
1110 | { | 1115 | { |
1111 | struct inet_sock *inet = inet_sk(sk); | 1116 | struct inet_sock *inet = inet_sk(sk); |
1112 | struct sk_buff *skb; | 1117 | struct sk_buff *skb; |
1113 | struct rtable *rt; | 1118 | struct rtable *rt; |
1114 | struct ip_options *opt = NULL; | 1119 | struct ip_options *opt = NULL; |
1120 | struct inet_cork *cork; | ||
1115 | int hh_len; | 1121 | int hh_len; |
1116 | int mtu; | 1122 | int mtu; |
1117 | int len; | 1123 | int len; |
@@ -1127,28 +1133,29 @@ ssize_t ip_append_page(struct sock *sk, struct page *page, | |||
1127 | if (skb_queue_empty(&sk->sk_write_queue)) | 1133 | if (skb_queue_empty(&sk->sk_write_queue)) |
1128 | return -EINVAL; | 1134 | return -EINVAL; |
1129 | 1135 | ||
1130 | rt = (struct rtable *)inet->cork.dst; | 1136 | cork = &inet->cork.base; |
1131 | if (inet->cork.flags & IPCORK_OPT) | 1137 | rt = (struct rtable *)cork->dst; |
1132 | opt = inet->cork.opt; | 1138 | if (cork->flags & IPCORK_OPT) |
1139 | opt = cork->opt; | ||
1133 | 1140 | ||
1134 | if (!(rt->dst.dev->features&NETIF_F_SG)) | 1141 | if (!(rt->dst.dev->features&NETIF_F_SG)) |
1135 | return -EOPNOTSUPP; | 1142 | return -EOPNOTSUPP; |
1136 | 1143 | ||
1137 | hh_len = LL_RESERVED_SPACE(rt->dst.dev); | 1144 | hh_len = LL_RESERVED_SPACE(rt->dst.dev); |
1138 | mtu = inet->cork.fragsize; | 1145 | mtu = cork->fragsize; |
1139 | 1146 | ||
1140 | fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0); | 1147 | fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0); |
1141 | maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen; | 1148 | maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen; |
1142 | 1149 | ||
1143 | if (inet->cork.length + size > 0xFFFF - fragheaderlen) { | 1150 | if (cork->length + size > 0xFFFF - fragheaderlen) { |
1144 | ip_local_error(sk, EMSGSIZE, rt->rt_dst, inet->inet_dport, mtu); | 1151 | ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport, mtu); |
1145 | return -EMSGSIZE; | 1152 | return -EMSGSIZE; |
1146 | } | 1153 | } |
1147 | 1154 | ||
1148 | if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) | 1155 | if ((skb = skb_peek_tail(&sk->sk_write_queue)) == NULL) |
1149 | return -EINVAL; | 1156 | return -EINVAL; |
1150 | 1157 | ||
1151 | inet->cork.length += size; | 1158 | cork->length += size; |
1152 | if ((size + skb->len > mtu) && | 1159 | if ((size + skb->len > mtu) && |
1153 | (sk->sk_protocol == IPPROTO_UDP) && | 1160 | (sk->sk_protocol == IPPROTO_UDP) && |
1154 | (rt->dst.dev->features & NETIF_F_UFO)) { | 1161 | (rt->dst.dev->features & NETIF_F_UFO)) { |
@@ -1243,7 +1250,7 @@ ssize_t ip_append_page(struct sock *sk, struct page *page, | |||
1243 | return 0; | 1250 | return 0; |
1244 | 1251 | ||
1245 | error: | 1252 | error: |
1246 | inet->cork.length -= size; | 1253 | cork->length -= size; |
1247 | IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTDISCARDS); | 1254 | IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTDISCARDS); |
1248 | return err; | 1255 | return err; |
1249 | } | 1256 | } |
@@ -1262,6 +1269,7 @@ static void ip_cork_release(struct inet_cork *cork) | |||
1262 | * and push them out. | 1269 | * and push them out. |
1263 | */ | 1270 | */ |
1264 | struct sk_buff *__ip_make_skb(struct sock *sk, | 1271 | struct sk_buff *__ip_make_skb(struct sock *sk, |
1272 | struct flowi4 *fl4, | ||
1265 | struct sk_buff_head *queue, | 1273 | struct sk_buff_head *queue, |
1266 | struct inet_cork *cork) | 1274 | struct inet_cork *cork) |
1267 | { | 1275 | { |
@@ -1319,17 +1327,18 @@ struct sk_buff *__ip_make_skb(struct sock *sk, | |||
1319 | iph = (struct iphdr *)skb->data; | 1327 | iph = (struct iphdr *)skb->data; |
1320 | iph->version = 4; | 1328 | iph->version = 4; |
1321 | iph->ihl = 5; | 1329 | iph->ihl = 5; |
1322 | if (opt) { | ||
1323 | iph->ihl += opt->optlen>>2; | ||
1324 | ip_options_build(skb, opt, cork->addr, rt, 0); | ||
1325 | } | ||
1326 | iph->tos = inet->tos; | 1330 | iph->tos = inet->tos; |
1327 | iph->frag_off = df; | 1331 | iph->frag_off = df; |
1328 | ip_select_ident(iph, &rt->dst, sk); | 1332 | ip_select_ident(iph, &rt->dst, sk); |
1329 | iph->ttl = ttl; | 1333 | iph->ttl = ttl; |
1330 | iph->protocol = sk->sk_protocol; | 1334 | iph->protocol = sk->sk_protocol; |
1331 | iph->saddr = rt->rt_src; | 1335 | iph->saddr = fl4->saddr; |
1332 | iph->daddr = rt->rt_dst; | 1336 | iph->daddr = fl4->daddr; |
1337 | |||
1338 | if (opt) { | ||
1339 | iph->ihl += opt->optlen>>2; | ||
1340 | ip_options_build(skb, opt, cork->addr, rt, 0); | ||
1341 | } | ||
1333 | 1342 | ||
1334 | skb->priority = sk->sk_priority; | 1343 | skb->priority = sk->sk_priority; |
1335 | skb->mark = sk->sk_mark; | 1344 | skb->mark = sk->sk_mark; |
@@ -1365,11 +1374,11 @@ int ip_send_skb(struct sk_buff *skb) | |||
1365 | return err; | 1374 | return err; |
1366 | } | 1375 | } |
1367 | 1376 | ||
1368 | int ip_push_pending_frames(struct sock *sk) | 1377 | int ip_push_pending_frames(struct sock *sk, struct flowi4 *fl4) |
1369 | { | 1378 | { |
1370 | struct sk_buff *skb; | 1379 | struct sk_buff *skb; |
1371 | 1380 | ||
1372 | skb = ip_finish_skb(sk); | 1381 | skb = ip_finish_skb(sk, fl4); |
1373 | if (!skb) | 1382 | if (!skb) |
1374 | return 0; | 1383 | return 0; |
1375 | 1384 | ||
@@ -1394,17 +1403,18 @@ static void __ip_flush_pending_frames(struct sock *sk, | |||
1394 | 1403 | ||
1395 | void ip_flush_pending_frames(struct sock *sk) | 1404 | void ip_flush_pending_frames(struct sock *sk) |
1396 | { | 1405 | { |
1397 | __ip_flush_pending_frames(sk, &sk->sk_write_queue, &inet_sk(sk)->cork); | 1406 | __ip_flush_pending_frames(sk, &sk->sk_write_queue, &inet_sk(sk)->cork.base); |
1398 | } | 1407 | } |
1399 | 1408 | ||
1400 | struct sk_buff *ip_make_skb(struct sock *sk, | 1409 | struct sk_buff *ip_make_skb(struct sock *sk, |
1410 | struct flowi4 *fl4, | ||
1401 | int getfrag(void *from, char *to, int offset, | 1411 | int getfrag(void *from, char *to, int offset, |
1402 | int len, int odd, struct sk_buff *skb), | 1412 | int len, int odd, struct sk_buff *skb), |
1403 | void *from, int length, int transhdrlen, | 1413 | void *from, int length, int transhdrlen, |
1404 | struct ipcm_cookie *ipc, struct rtable **rtp, | 1414 | struct ipcm_cookie *ipc, struct rtable **rtp, |
1405 | unsigned int flags) | 1415 | unsigned int flags) |
1406 | { | 1416 | { |
1407 | struct inet_cork cork = {}; | 1417 | struct inet_cork cork; |
1408 | struct sk_buff_head queue; | 1418 | struct sk_buff_head queue; |
1409 | int err; | 1419 | int err; |
1410 | 1420 | ||
@@ -1413,18 +1423,21 @@ struct sk_buff *ip_make_skb(struct sock *sk, | |||
1413 | 1423 | ||
1414 | __skb_queue_head_init(&queue); | 1424 | __skb_queue_head_init(&queue); |
1415 | 1425 | ||
1426 | cork.flags = 0; | ||
1427 | cork.addr = 0; | ||
1428 | cork.opt = NULL; | ||
1416 | err = ip_setup_cork(sk, &cork, ipc, rtp); | 1429 | err = ip_setup_cork(sk, &cork, ipc, rtp); |
1417 | if (err) | 1430 | if (err) |
1418 | return ERR_PTR(err); | 1431 | return ERR_PTR(err); |
1419 | 1432 | ||
1420 | err = __ip_append_data(sk, &queue, &cork, getfrag, | 1433 | err = __ip_append_data(sk, fl4, &queue, &cork, getfrag, |
1421 | from, length, transhdrlen, flags); | 1434 | from, length, transhdrlen, flags); |
1422 | if (err) { | 1435 | if (err) { |
1423 | __ip_flush_pending_frames(sk, &queue, &cork); | 1436 | __ip_flush_pending_frames(sk, &queue, &cork); |
1424 | return ERR_PTR(err); | 1437 | return ERR_PTR(err); |
1425 | } | 1438 | } |
1426 | 1439 | ||
1427 | return __ip_make_skb(sk, &queue, &cork); | 1440 | return __ip_make_skb(sk, fl4, &queue, &cork); |
1428 | } | 1441 | } |
1429 | 1442 | ||
1430 | /* | 1443 | /* |
@@ -1447,48 +1460,39 @@ static int ip_reply_glue_bits(void *dptr, char *to, int offset, | |||
1447 | * Should run single threaded per socket because it uses the sock | 1460 | * Should run single threaded per socket because it uses the sock |
1448 | * structure to pass arguments. | 1461 | * structure to pass arguments. |
1449 | */ | 1462 | */ |
1450 | void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *arg, | 1463 | void ip_send_reply(struct sock *sk, struct sk_buff *skb, __be32 daddr, |
1451 | unsigned int len) | 1464 | struct ip_reply_arg *arg, unsigned int len) |
1452 | { | 1465 | { |
1453 | struct inet_sock *inet = inet_sk(sk); | 1466 | struct inet_sock *inet = inet_sk(sk); |
1454 | struct { | 1467 | struct ip_options_data replyopts; |
1455 | struct ip_options opt; | ||
1456 | char data[40]; | ||
1457 | } replyopts; | ||
1458 | struct ipcm_cookie ipc; | 1468 | struct ipcm_cookie ipc; |
1459 | __be32 daddr; | 1469 | struct flowi4 fl4; |
1460 | struct rtable *rt = skb_rtable(skb); | 1470 | struct rtable *rt = skb_rtable(skb); |
1461 | 1471 | ||
1462 | if (ip_options_echo(&replyopts.opt, skb)) | 1472 | if (ip_options_echo(&replyopts.opt.opt, skb)) |
1463 | return; | 1473 | return; |
1464 | 1474 | ||
1465 | daddr = ipc.addr = rt->rt_src; | 1475 | ipc.addr = daddr; |
1466 | ipc.opt = NULL; | 1476 | ipc.opt = NULL; |
1467 | ipc.tx_flags = 0; | 1477 | ipc.tx_flags = 0; |
1468 | 1478 | ||
1469 | if (replyopts.opt.optlen) { | 1479 | if (replyopts.opt.opt.optlen) { |
1470 | ipc.opt = &replyopts.opt; | 1480 | ipc.opt = &replyopts.opt; |
1471 | 1481 | ||
1472 | if (ipc.opt->srr) | 1482 | if (replyopts.opt.opt.srr) |
1473 | daddr = replyopts.opt.faddr; | 1483 | daddr = replyopts.opt.opt.faddr; |
1474 | } | 1484 | } |
1475 | 1485 | ||
1476 | { | 1486 | flowi4_init_output(&fl4, arg->bound_dev_if, 0, |
1477 | struct flowi4 fl4 = { | 1487 | RT_TOS(ip_hdr(skb)->tos), |
1478 | .flowi4_oif = arg->bound_dev_if, | 1488 | RT_SCOPE_UNIVERSE, sk->sk_protocol, |
1479 | .daddr = daddr, | 1489 | ip_reply_arg_flowi_flags(arg), |
1480 | .saddr = rt->rt_spec_dst, | 1490 | daddr, rt->rt_spec_dst, |
1481 | .flowi4_tos = RT_TOS(ip_hdr(skb)->tos), | 1491 | tcp_hdr(skb)->source, tcp_hdr(skb)->dest); |
1482 | .fl4_sport = tcp_hdr(skb)->dest, | 1492 | security_skb_classify_flow(skb, flowi4_to_flowi(&fl4)); |
1483 | .fl4_dport = tcp_hdr(skb)->source, | 1493 | rt = ip_route_output_key(sock_net(sk), &fl4); |
1484 | .flowi4_proto = sk->sk_protocol, | 1494 | if (IS_ERR(rt)) |
1485 | .flowi4_flags = ip_reply_arg_flowi_flags(arg), | 1495 | return; |
1486 | }; | ||
1487 | security_skb_classify_flow(skb, flowi4_to_flowi(&fl4)); | ||
1488 | rt = ip_route_output_key(sock_net(sk), &fl4); | ||
1489 | if (IS_ERR(rt)) | ||
1490 | return; | ||
1491 | } | ||
1492 | 1496 | ||
1493 | /* And let IP do all the hard work. | 1497 | /* And let IP do all the hard work. |
1494 | 1498 | ||
@@ -1501,7 +1505,7 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar | |||
1501 | sk->sk_priority = skb->priority; | 1505 | sk->sk_priority = skb->priority; |
1502 | sk->sk_protocol = ip_hdr(skb)->protocol; | 1506 | sk->sk_protocol = ip_hdr(skb)->protocol; |
1503 | sk->sk_bound_dev_if = arg->bound_dev_if; | 1507 | sk->sk_bound_dev_if = arg->bound_dev_if; |
1504 | ip_append_data(sk, ip_reply_glue_bits, arg->iov->iov_base, len, 0, | 1508 | ip_append_data(sk, &fl4, ip_reply_glue_bits, arg->iov->iov_base, len, 0, |
1505 | &ipc, &rt, MSG_DONTWAIT); | 1509 | &ipc, &rt, MSG_DONTWAIT); |
1506 | if ((skb = skb_peek(&sk->sk_write_queue)) != NULL) { | 1510 | if ((skb = skb_peek(&sk->sk_write_queue)) != NULL) { |
1507 | if (arg->csumoffset >= 0) | 1511 | if (arg->csumoffset >= 0) |
@@ -1509,7 +1513,7 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar | |||
1509 | arg->csumoffset) = csum_fold(csum_add(skb->csum, | 1513 | arg->csumoffset) = csum_fold(csum_add(skb->csum, |
1510 | arg->csum)); | 1514 | arg->csum)); |
1511 | skb->ip_summed = CHECKSUM_NONE; | 1515 | skb->ip_summed = CHECKSUM_NONE; |
1512 | ip_push_pending_frames(sk); | 1516 | ip_push_pending_frames(sk, &fl4); |
1513 | } | 1517 | } |
1514 | 1518 | ||
1515 | bh_unlock_sock(sk); | 1519 | bh_unlock_sock(sk); |
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 3948c86e59ca..ab0c9efd1efa 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c | |||
@@ -131,7 +131,7 @@ static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb) | |||
131 | static void ip_cmsg_recv_dstaddr(struct msghdr *msg, struct sk_buff *skb) | 131 | static void ip_cmsg_recv_dstaddr(struct msghdr *msg, struct sk_buff *skb) |
132 | { | 132 | { |
133 | struct sockaddr_in sin; | 133 | struct sockaddr_in sin; |
134 | struct iphdr *iph = ip_hdr(skb); | 134 | const struct iphdr *iph = ip_hdr(skb); |
135 | __be16 *ports = (__be16 *)skb_transport_header(skb); | 135 | __be16 *ports = (__be16 *)skb_transport_header(skb); |
136 | 136 | ||
137 | if (skb_transport_offset(skb) + 4 > skb->len) | 137 | if (skb_transport_offset(skb) + 4 > skb->len) |
@@ -451,6 +451,11 @@ out: | |||
451 | } | 451 | } |
452 | 452 | ||
453 | 453 | ||
454 | static void opt_kfree_rcu(struct rcu_head *head) | ||
455 | { | ||
456 | kfree(container_of(head, struct ip_options_rcu, rcu)); | ||
457 | } | ||
458 | |||
454 | /* | 459 | /* |
455 | * Socket option code for IP. This is the end of the line after any | 460 | * Socket option code for IP. This is the end of the line after any |
456 | * TCP,UDP etc options on an IP socket. | 461 | * TCP,UDP etc options on an IP socket. |
@@ -497,13 +502,16 @@ static int do_ip_setsockopt(struct sock *sk, int level, | |||
497 | switch (optname) { | 502 | switch (optname) { |
498 | case IP_OPTIONS: | 503 | case IP_OPTIONS: |
499 | { | 504 | { |
500 | struct ip_options *opt = NULL; | 505 | struct ip_options_rcu *old, *opt = NULL; |
506 | |||
501 | if (optlen > 40) | 507 | if (optlen > 40) |
502 | goto e_inval; | 508 | goto e_inval; |
503 | err = ip_options_get_from_user(sock_net(sk), &opt, | 509 | err = ip_options_get_from_user(sock_net(sk), &opt, |
504 | optval, optlen); | 510 | optval, optlen); |
505 | if (err) | 511 | if (err) |
506 | break; | 512 | break; |
513 | old = rcu_dereference_protected(inet->inet_opt, | ||
514 | sock_owned_by_user(sk)); | ||
507 | if (inet->is_icsk) { | 515 | if (inet->is_icsk) { |
508 | struct inet_connection_sock *icsk = inet_csk(sk); | 516 | struct inet_connection_sock *icsk = inet_csk(sk); |
509 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 517 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
@@ -512,17 +520,18 @@ static int do_ip_setsockopt(struct sock *sk, int level, | |||
512 | (TCPF_LISTEN | TCPF_CLOSE)) && | 520 | (TCPF_LISTEN | TCPF_CLOSE)) && |
513 | inet->inet_daddr != LOOPBACK4_IPV6)) { | 521 | inet->inet_daddr != LOOPBACK4_IPV6)) { |
514 | #endif | 522 | #endif |
515 | if (inet->opt) | 523 | if (old) |
516 | icsk->icsk_ext_hdr_len -= inet->opt->optlen; | 524 | icsk->icsk_ext_hdr_len -= old->opt.optlen; |
517 | if (opt) | 525 | if (opt) |
518 | icsk->icsk_ext_hdr_len += opt->optlen; | 526 | icsk->icsk_ext_hdr_len += opt->opt.optlen; |
519 | icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie); | 527 | icsk->icsk_sync_mss(sk, icsk->icsk_pmtu_cookie); |
520 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | 528 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) |
521 | } | 529 | } |
522 | #endif | 530 | #endif |
523 | } | 531 | } |
524 | opt = xchg(&inet->opt, opt); | 532 | rcu_assign_pointer(inet->inet_opt, opt); |
525 | kfree(opt); | 533 | if (old) |
534 | call_rcu(&old->rcu, opt_kfree_rcu); | ||
526 | break; | 535 | break; |
527 | } | 536 | } |
528 | case IP_PKTINFO: | 537 | case IP_PKTINFO: |
@@ -1081,12 +1090,16 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname, | |||
1081 | case IP_OPTIONS: | 1090 | case IP_OPTIONS: |
1082 | { | 1091 | { |
1083 | unsigned char optbuf[sizeof(struct ip_options)+40]; | 1092 | unsigned char optbuf[sizeof(struct ip_options)+40]; |
1084 | struct ip_options * opt = (struct ip_options *)optbuf; | 1093 | struct ip_options *opt = (struct ip_options *)optbuf; |
1094 | struct ip_options_rcu *inet_opt; | ||
1095 | |||
1096 | inet_opt = rcu_dereference_protected(inet->inet_opt, | ||
1097 | sock_owned_by_user(sk)); | ||
1085 | opt->optlen = 0; | 1098 | opt->optlen = 0; |
1086 | if (inet->opt) | 1099 | if (inet_opt) |
1087 | memcpy(optbuf, inet->opt, | 1100 | memcpy(optbuf, &inet_opt->opt, |
1088 | sizeof(struct ip_options)+ | 1101 | sizeof(struct ip_options) + |
1089 | inet->opt->optlen); | 1102 | inet_opt->opt.optlen); |
1090 | release_sock(sk); | 1103 | release_sock(sk); |
1091 | 1104 | ||
1092 | if (opt->optlen == 0) | 1105 | if (opt->optlen == 0) |
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index 629067571f02..c857f6f49b03 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c | |||
@@ -27,7 +27,7 @@ static void ipcomp4_err(struct sk_buff *skb, u32 info) | |||
27 | { | 27 | { |
28 | struct net *net = dev_net(skb->dev); | 28 | struct net *net = dev_net(skb->dev); |
29 | __be32 spi; | 29 | __be32 spi; |
30 | struct iphdr *iph = (struct iphdr *)skb->data; | 30 | const struct iphdr *iph = (const struct iphdr *)skb->data; |
31 | struct ip_comp_hdr *ipch = (struct ip_comp_hdr *)(skb->data+(iph->ihl<<2)); | 31 | struct ip_comp_hdr *ipch = (struct ip_comp_hdr *)(skb->data+(iph->ihl<<2)); |
32 | struct xfrm_state *x; | 32 | struct xfrm_state *x; |
33 | 33 | ||
@@ -36,7 +36,7 @@ static void ipcomp4_err(struct sk_buff *skb, u32 info) | |||
36 | return; | 36 | return; |
37 | 37 | ||
38 | spi = htonl(ntohs(ipch->cpi)); | 38 | spi = htonl(ntohs(ipch->cpi)); |
39 | x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, | 39 | x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, |
40 | spi, IPPROTO_COMP, AF_INET); | 40 | spi, IPPROTO_COMP, AF_INET); |
41 | if (!x) | 41 | if (!x) |
42 | return; | 42 | return; |
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index 2b097752426b..cbff2ecccf3d 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c | |||
@@ -1444,7 +1444,7 @@ static int __init ip_auto_config(void) | |||
1444 | root_server_addr = addr; | 1444 | root_server_addr = addr; |
1445 | 1445 | ||
1446 | /* | 1446 | /* |
1447 | * Use defaults whereever applicable. | 1447 | * Use defaults wherever applicable. |
1448 | */ | 1448 | */ |
1449 | if (ic_defaults() < 0) | 1449 | if (ic_defaults() < 0) |
1450 | return -1; | 1450 | return -1; |
diff --git a/net/ipv4/ipip.c b/net/ipv4/ipip.c index bfc17c5914e7..378b20b7ca6e 100644 --- a/net/ipv4/ipip.c +++ b/net/ipv4/ipip.c | |||
@@ -276,11 +276,6 @@ static struct ip_tunnel * ipip_tunnel_locate(struct net *net, | |||
276 | 276 | ||
277 | dev_net_set(dev, net); | 277 | dev_net_set(dev, net); |
278 | 278 | ||
279 | if (strchr(name, '%')) { | ||
280 | if (dev_alloc_name(dev, name) < 0) | ||
281 | goto failed_free; | ||
282 | } | ||
283 | |||
284 | nt = netdev_priv(dev); | 279 | nt = netdev_priv(dev); |
285 | nt->parms = *parms; | 280 | nt->parms = *parms; |
286 | 281 | ||
@@ -319,7 +314,7 @@ static int ipip_err(struct sk_buff *skb, u32 info) | |||
319 | 8 bytes of packet payload. It means, that precise relaying of | 314 | 8 bytes of packet payload. It means, that precise relaying of |
320 | ICMP in the real Internet is absolutely infeasible. | 315 | ICMP in the real Internet is absolutely infeasible. |
321 | */ | 316 | */ |
322 | struct iphdr *iph = (struct iphdr *)skb->data; | 317 | const struct iphdr *iph = (const struct iphdr *)skb->data; |
323 | const int type = icmp_hdr(skb)->type; | 318 | const int type = icmp_hdr(skb)->type; |
324 | const int code = icmp_hdr(skb)->code; | 319 | const int code = icmp_hdr(skb)->code; |
325 | struct ip_tunnel *t; | 320 | struct ip_tunnel *t; |
@@ -433,15 +428,16 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
433 | { | 428 | { |
434 | struct ip_tunnel *tunnel = netdev_priv(dev); | 429 | struct ip_tunnel *tunnel = netdev_priv(dev); |
435 | struct pcpu_tstats *tstats; | 430 | struct pcpu_tstats *tstats; |
436 | struct iphdr *tiph = &tunnel->parms.iph; | 431 | const struct iphdr *tiph = &tunnel->parms.iph; |
437 | u8 tos = tunnel->parms.iph.tos; | 432 | u8 tos = tunnel->parms.iph.tos; |
438 | __be16 df = tiph->frag_off; | 433 | __be16 df = tiph->frag_off; |
439 | struct rtable *rt; /* Route to the other host */ | 434 | struct rtable *rt; /* Route to the other host */ |
440 | struct net_device *tdev; /* Device to other host */ | 435 | struct net_device *tdev; /* Device to other host */ |
441 | struct iphdr *old_iph = ip_hdr(skb); | 436 | const struct iphdr *old_iph = ip_hdr(skb); |
442 | struct iphdr *iph; /* Our new IP header */ | 437 | struct iphdr *iph; /* Our new IP header */ |
443 | unsigned int max_headroom; /* The extra header space needed */ | 438 | unsigned int max_headroom; /* The extra header space needed */ |
444 | __be32 dst = tiph->daddr; | 439 | __be32 dst = tiph->daddr; |
440 | struct flowi4 fl4; | ||
445 | int mtu; | 441 | int mtu; |
446 | 442 | ||
447 | if (skb->protocol != htons(ETH_P_IP)) | 443 | if (skb->protocol != htons(ETH_P_IP)) |
@@ -460,7 +456,7 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
460 | goto tx_error_icmp; | 456 | goto tx_error_icmp; |
461 | } | 457 | } |
462 | 458 | ||
463 | rt = ip_route_output_ports(dev_net(dev), NULL, | 459 | rt = ip_route_output_ports(dev_net(dev), &fl4, NULL, |
464 | dst, tiph->saddr, | 460 | dst, tiph->saddr, |
465 | 0, 0, | 461 | 0, 0, |
466 | IPPROTO_IPIP, RT_TOS(tos), | 462 | IPPROTO_IPIP, RT_TOS(tos), |
@@ -549,8 +545,8 @@ static netdev_tx_t ipip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
549 | iph->frag_off = df; | 545 | iph->frag_off = df; |
550 | iph->protocol = IPPROTO_IPIP; | 546 | iph->protocol = IPPROTO_IPIP; |
551 | iph->tos = INET_ECN_encapsulate(tos, old_iph->tos); | 547 | iph->tos = INET_ECN_encapsulate(tos, old_iph->tos); |
552 | iph->daddr = rt->rt_dst; | 548 | iph->daddr = fl4.daddr; |
553 | iph->saddr = rt->rt_src; | 549 | iph->saddr = fl4.saddr; |
554 | 550 | ||
555 | if ((iph->ttl = tiph->ttl) == 0) | 551 | if ((iph->ttl = tiph->ttl) == 0) |
556 | iph->ttl = old_iph->ttl; | 552 | iph->ttl = old_iph->ttl; |
@@ -572,19 +568,21 @@ static void ipip_tunnel_bind_dev(struct net_device *dev) | |||
572 | { | 568 | { |
573 | struct net_device *tdev = NULL; | 569 | struct net_device *tdev = NULL; |
574 | struct ip_tunnel *tunnel; | 570 | struct ip_tunnel *tunnel; |
575 | struct iphdr *iph; | 571 | const struct iphdr *iph; |
576 | 572 | ||
577 | tunnel = netdev_priv(dev); | 573 | tunnel = netdev_priv(dev); |
578 | iph = &tunnel->parms.iph; | 574 | iph = &tunnel->parms.iph; |
579 | 575 | ||
580 | if (iph->daddr) { | 576 | if (iph->daddr) { |
581 | struct rtable *rt = ip_route_output_ports(dev_net(dev), NULL, | 577 | struct rtable *rt; |
582 | iph->daddr, iph->saddr, | 578 | struct flowi4 fl4; |
583 | 0, 0, | 579 | |
584 | IPPROTO_IPIP, | 580 | rt = ip_route_output_ports(dev_net(dev), &fl4, NULL, |
585 | RT_TOS(iph->tos), | 581 | iph->daddr, iph->saddr, |
586 | tunnel->parms.link); | 582 | 0, 0, |
587 | 583 | IPPROTO_IPIP, | |
584 | RT_TOS(iph->tos), | ||
585 | tunnel->parms.link); | ||
588 | if (!IS_ERR(rt)) { | 586 | if (!IS_ERR(rt)) { |
589 | tdev = rt->dst.dev; | 587 | tdev = rt->dst.dev; |
590 | ip_rt_put(rt); | 588 | ip_rt_put(rt); |
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 1f62eaeb6de4..30a7763c400e 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c | |||
@@ -1549,7 +1549,7 @@ static struct notifier_block ip_mr_notifier = { | |||
1549 | static void ip_encap(struct sk_buff *skb, __be32 saddr, __be32 daddr) | 1549 | static void ip_encap(struct sk_buff *skb, __be32 saddr, __be32 daddr) |
1550 | { | 1550 | { |
1551 | struct iphdr *iph; | 1551 | struct iphdr *iph; |
1552 | struct iphdr *old_iph = ip_hdr(skb); | 1552 | const struct iphdr *old_iph = ip_hdr(skb); |
1553 | 1553 | ||
1554 | skb_push(skb, sizeof(struct iphdr)); | 1554 | skb_push(skb, sizeof(struct iphdr)); |
1555 | skb->transport_header = skb->network_header; | 1555 | skb->transport_header = skb->network_header; |
@@ -1595,6 +1595,7 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt, | |||
1595 | struct vif_device *vif = &mrt->vif_table[vifi]; | 1595 | struct vif_device *vif = &mrt->vif_table[vifi]; |
1596 | struct net_device *dev; | 1596 | struct net_device *dev; |
1597 | struct rtable *rt; | 1597 | struct rtable *rt; |
1598 | struct flowi4 fl4; | ||
1598 | int encap = 0; | 1599 | int encap = 0; |
1599 | 1600 | ||
1600 | if (vif->dev == NULL) | 1601 | if (vif->dev == NULL) |
@@ -1612,7 +1613,7 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt, | |||
1612 | #endif | 1613 | #endif |
1613 | 1614 | ||
1614 | if (vif->flags & VIFF_TUNNEL) { | 1615 | if (vif->flags & VIFF_TUNNEL) { |
1615 | rt = ip_route_output_ports(net, NULL, | 1616 | rt = ip_route_output_ports(net, &fl4, NULL, |
1616 | vif->remote, vif->local, | 1617 | vif->remote, vif->local, |
1617 | 0, 0, | 1618 | 0, 0, |
1618 | IPPROTO_IPIP, | 1619 | IPPROTO_IPIP, |
@@ -1621,7 +1622,7 @@ static void ipmr_queue_xmit(struct net *net, struct mr_table *mrt, | |||
1621 | goto out_free; | 1622 | goto out_free; |
1622 | encap = sizeof(struct iphdr); | 1623 | encap = sizeof(struct iphdr); |
1623 | } else { | 1624 | } else { |
1624 | rt = ip_route_output_ports(net, NULL, iph->daddr, 0, | 1625 | rt = ip_route_output_ports(net, &fl4, NULL, iph->daddr, 0, |
1625 | 0, 0, | 1626 | 0, 0, |
1626 | IPPROTO_IPIP, | 1627 | IPPROTO_IPIP, |
1627 | RT_TOS(iph->tos), vif->link); | 1628 | RT_TOS(iph->tos), vif->link); |
@@ -1788,12 +1789,14 @@ dont_forward: | |||
1788 | return 0; | 1789 | return 0; |
1789 | } | 1790 | } |
1790 | 1791 | ||
1791 | static struct mr_table *ipmr_rt_fib_lookup(struct net *net, struct rtable *rt) | 1792 | static struct mr_table *ipmr_rt_fib_lookup(struct net *net, struct sk_buff *skb) |
1792 | { | 1793 | { |
1794 | struct rtable *rt = skb_rtable(skb); | ||
1795 | struct iphdr *iph = ip_hdr(skb); | ||
1793 | struct flowi4 fl4 = { | 1796 | struct flowi4 fl4 = { |
1794 | .daddr = rt->rt_key_dst, | 1797 | .daddr = iph->daddr, |
1795 | .saddr = rt->rt_key_src, | 1798 | .saddr = iph->saddr, |
1796 | .flowi4_tos = rt->rt_tos, | 1799 | .flowi4_tos = iph->tos, |
1797 | .flowi4_oif = rt->rt_oif, | 1800 | .flowi4_oif = rt->rt_oif, |
1798 | .flowi4_iif = rt->rt_iif, | 1801 | .flowi4_iif = rt->rt_iif, |
1799 | .flowi4_mark = rt->rt_mark, | 1802 | .flowi4_mark = rt->rt_mark, |
@@ -1825,7 +1828,7 @@ int ip_mr_input(struct sk_buff *skb) | |||
1825 | if (IPCB(skb)->flags & IPSKB_FORWARDED) | 1828 | if (IPCB(skb)->flags & IPSKB_FORWARDED) |
1826 | goto dont_forward; | 1829 | goto dont_forward; |
1827 | 1830 | ||
1828 | mrt = ipmr_rt_fib_lookup(net, skb_rtable(skb)); | 1831 | mrt = ipmr_rt_fib_lookup(net, skb); |
1829 | if (IS_ERR(mrt)) { | 1832 | if (IS_ERR(mrt)) { |
1830 | kfree_skb(skb); | 1833 | kfree_skb(skb); |
1831 | return PTR_ERR(mrt); | 1834 | return PTR_ERR(mrt); |
@@ -1957,7 +1960,7 @@ int pim_rcv_v1(struct sk_buff *skb) | |||
1957 | 1960 | ||
1958 | pim = igmp_hdr(skb); | 1961 | pim = igmp_hdr(skb); |
1959 | 1962 | ||
1960 | mrt = ipmr_rt_fib_lookup(net, skb_rtable(skb)); | 1963 | mrt = ipmr_rt_fib_lookup(net, skb); |
1961 | if (IS_ERR(mrt)) | 1964 | if (IS_ERR(mrt)) |
1962 | goto drop; | 1965 | goto drop; |
1963 | if (!mrt->mroute_do_pim || | 1966 | if (!mrt->mroute_do_pim || |
@@ -1989,7 +1992,7 @@ static int pim_rcv(struct sk_buff *skb) | |||
1989 | csum_fold(skb_checksum(skb, 0, skb->len, 0)))) | 1992 | csum_fold(skb_checksum(skb, 0, skb->len, 0)))) |
1990 | goto drop; | 1993 | goto drop; |
1991 | 1994 | ||
1992 | mrt = ipmr_rt_fib_lookup(net, skb_rtable(skb)); | 1995 | mrt = ipmr_rt_fib_lookup(net, skb); |
1993 | if (IS_ERR(mrt)) | 1996 | if (IS_ERR(mrt)) |
1994 | goto drop; | 1997 | goto drop; |
1995 | if (__pim_rcv(mrt, skb, sizeof(*pim))) { | 1998 | if (__pim_rcv(mrt, skb, sizeof(*pim))) { |
@@ -2038,20 +2041,20 @@ rtattr_failure: | |||
2038 | return -EMSGSIZE; | 2041 | return -EMSGSIZE; |
2039 | } | 2042 | } |
2040 | 2043 | ||
2041 | int ipmr_get_route(struct net *net, | 2044 | int ipmr_get_route(struct net *net, struct sk_buff *skb, |
2042 | struct sk_buff *skb, struct rtmsg *rtm, int nowait) | 2045 | __be32 saddr, __be32 daddr, |
2046 | struct rtmsg *rtm, int nowait) | ||
2043 | { | 2047 | { |
2044 | int err; | ||
2045 | struct mr_table *mrt; | ||
2046 | struct mfc_cache *cache; | 2048 | struct mfc_cache *cache; |
2047 | struct rtable *rt = skb_rtable(skb); | 2049 | struct mr_table *mrt; |
2050 | int err; | ||
2048 | 2051 | ||
2049 | mrt = ipmr_get_table(net, RT_TABLE_DEFAULT); | 2052 | mrt = ipmr_get_table(net, RT_TABLE_DEFAULT); |
2050 | if (mrt == NULL) | 2053 | if (mrt == NULL) |
2051 | return -ENOENT; | 2054 | return -ENOENT; |
2052 | 2055 | ||
2053 | rcu_read_lock(); | 2056 | rcu_read_lock(); |
2054 | cache = ipmr_cache_find(mrt, rt->rt_src, rt->rt_dst); | 2057 | cache = ipmr_cache_find(mrt, saddr, daddr); |
2055 | 2058 | ||
2056 | if (cache == NULL) { | 2059 | if (cache == NULL) { |
2057 | struct sk_buff *skb2; | 2060 | struct sk_buff *skb2; |
@@ -2084,8 +2087,8 @@ int ipmr_get_route(struct net *net, | |||
2084 | skb_reset_network_header(skb2); | 2087 | skb_reset_network_header(skb2); |
2085 | iph = ip_hdr(skb2); | 2088 | iph = ip_hdr(skb2); |
2086 | iph->ihl = sizeof(struct iphdr) >> 2; | 2089 | iph->ihl = sizeof(struct iphdr) >> 2; |
2087 | iph->saddr = rt->rt_src; | 2090 | iph->saddr = saddr; |
2088 | iph->daddr = rt->rt_dst; | 2091 | iph->daddr = daddr; |
2089 | iph->version = 0; | 2092 | iph->version = 0; |
2090 | err = ipmr_cache_unresolved(mrt, vif, skb2); | 2093 | err = ipmr_cache_unresolved(mrt, vif, skb2); |
2091 | read_unlock(&mrt_lock); | 2094 | read_unlock(&mrt_lock); |
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index f3c0b549b8e1..4614babdc45f 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c | |||
@@ -221,9 +221,10 @@ static __sum16 nf_ip_checksum_partial(struct sk_buff *skb, unsigned int hook, | |||
221 | return csum; | 221 | return csum; |
222 | } | 222 | } |
223 | 223 | ||
224 | static int nf_ip_route(struct dst_entry **dst, struct flowi *fl) | 224 | static int nf_ip_route(struct net *net, struct dst_entry **dst, |
225 | struct flowi *fl, bool strict __always_unused) | ||
225 | { | 226 | { |
226 | struct rtable *rt = ip_route_output_key(&init_net, &fl->u.ip4); | 227 | struct rtable *rt = ip_route_output_key(net, &fl->u.ip4); |
227 | if (IS_ERR(rt)) | 228 | if (IS_ERR(rt)) |
228 | return PTR_ERR(rt); | 229 | return PTR_ERR(rt); |
229 | *dst = &rt->dst; | 230 | *dst = &rt->dst; |
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 4b5d457c2d76..fd7a3f68917f 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c | |||
@@ -76,7 +76,7 @@ static inline int arp_devaddr_compare(const struct arpt_devaddr_info *ap, | |||
76 | } | 76 | } |
77 | 77 | ||
78 | /* | 78 | /* |
79 | * Unfortunatly, _b and _mask are not aligned to an int (or long int) | 79 | * Unfortunately, _b and _mask are not aligned to an int (or long int) |
80 | * Some arches dont care, unrolling the loop is a win on them. | 80 | * Some arches dont care, unrolling the loop is a win on them. |
81 | * For other arches, we only have a 16bit alignement. | 81 | * For other arches, we only have a 16bit alignement. |
82 | */ | 82 | */ |
@@ -260,6 +260,7 @@ unsigned int arpt_do_table(struct sk_buff *skb, | |||
260 | void *table_base; | 260 | void *table_base; |
261 | const struct xt_table_info *private; | 261 | const struct xt_table_info *private; |
262 | struct xt_action_param acpar; | 262 | struct xt_action_param acpar; |
263 | unsigned int addend; | ||
263 | 264 | ||
264 | if (!pskb_may_pull(skb, arp_hdr_len(skb->dev))) | 265 | if (!pskb_may_pull(skb, arp_hdr_len(skb->dev))) |
265 | return NF_DROP; | 266 | return NF_DROP; |
@@ -267,7 +268,8 @@ unsigned int arpt_do_table(struct sk_buff *skb, | |||
267 | indev = in ? in->name : nulldevname; | 268 | indev = in ? in->name : nulldevname; |
268 | outdev = out ? out->name : nulldevname; | 269 | outdev = out ? out->name : nulldevname; |
269 | 270 | ||
270 | xt_info_rdlock_bh(); | 271 | local_bh_disable(); |
272 | addend = xt_write_recseq_begin(); | ||
271 | private = table->private; | 273 | private = table->private; |
272 | table_base = private->entries[smp_processor_id()]; | 274 | table_base = private->entries[smp_processor_id()]; |
273 | 275 | ||
@@ -338,7 +340,8 @@ unsigned int arpt_do_table(struct sk_buff *skb, | |||
338 | /* Verdict */ | 340 | /* Verdict */ |
339 | break; | 341 | break; |
340 | } while (!acpar.hotdrop); | 342 | } while (!acpar.hotdrop); |
341 | xt_info_rdunlock_bh(); | 343 | xt_write_recseq_end(addend); |
344 | local_bh_enable(); | ||
342 | 345 | ||
343 | if (acpar.hotdrop) | 346 | if (acpar.hotdrop) |
344 | return NF_DROP; | 347 | return NF_DROP; |
@@ -712,7 +715,7 @@ static void get_counters(const struct xt_table_info *t, | |||
712 | unsigned int i; | 715 | unsigned int i; |
713 | 716 | ||
714 | for_each_possible_cpu(cpu) { | 717 | for_each_possible_cpu(cpu) { |
715 | seqlock_t *lock = &per_cpu(xt_info_locks, cpu).lock; | 718 | seqcount_t *s = &per_cpu(xt_recseq, cpu); |
716 | 719 | ||
717 | i = 0; | 720 | i = 0; |
718 | xt_entry_foreach(iter, t->entries[cpu], t->size) { | 721 | xt_entry_foreach(iter, t->entries[cpu], t->size) { |
@@ -720,10 +723,10 @@ static void get_counters(const struct xt_table_info *t, | |||
720 | unsigned int start; | 723 | unsigned int start; |
721 | 724 | ||
722 | do { | 725 | do { |
723 | start = read_seqbegin(lock); | 726 | start = read_seqcount_begin(s); |
724 | bcnt = iter->counters.bcnt; | 727 | bcnt = iter->counters.bcnt; |
725 | pcnt = iter->counters.pcnt; | 728 | pcnt = iter->counters.pcnt; |
726 | } while (read_seqretry(lock, start)); | 729 | } while (read_seqcount_retry(s, start)); |
727 | 730 | ||
728 | ADD_COUNTER(counters[i], bcnt, pcnt); | 731 | ADD_COUNTER(counters[i], bcnt, pcnt); |
729 | ++i; | 732 | ++i; |
@@ -1115,6 +1118,7 @@ static int do_add_counters(struct net *net, const void __user *user, | |||
1115 | int ret = 0; | 1118 | int ret = 0; |
1116 | void *loc_cpu_entry; | 1119 | void *loc_cpu_entry; |
1117 | struct arpt_entry *iter; | 1120 | struct arpt_entry *iter; |
1121 | unsigned int addend; | ||
1118 | #ifdef CONFIG_COMPAT | 1122 | #ifdef CONFIG_COMPAT |
1119 | struct compat_xt_counters_info compat_tmp; | 1123 | struct compat_xt_counters_info compat_tmp; |
1120 | 1124 | ||
@@ -1171,12 +1175,12 @@ static int do_add_counters(struct net *net, const void __user *user, | |||
1171 | /* Choose the copy that is on our node */ | 1175 | /* Choose the copy that is on our node */ |
1172 | curcpu = smp_processor_id(); | 1176 | curcpu = smp_processor_id(); |
1173 | loc_cpu_entry = private->entries[curcpu]; | 1177 | loc_cpu_entry = private->entries[curcpu]; |
1174 | xt_info_wrlock(curcpu); | 1178 | addend = xt_write_recseq_begin(); |
1175 | xt_entry_foreach(iter, loc_cpu_entry, private->size) { | 1179 | xt_entry_foreach(iter, loc_cpu_entry, private->size) { |
1176 | ADD_COUNTER(iter->counters, paddc[i].bcnt, paddc[i].pcnt); | 1180 | ADD_COUNTER(iter->counters, paddc[i].bcnt, paddc[i].pcnt); |
1177 | ++i; | 1181 | ++i; |
1178 | } | 1182 | } |
1179 | xt_info_wrunlock(curcpu); | 1183 | xt_write_recseq_end(addend); |
1180 | unlock_up_free: | 1184 | unlock_up_free: |
1181 | local_bh_enable(); | 1185 | local_bh_enable(); |
1182 | xt_table_unlock(t); | 1186 | xt_table_unlock(t); |
@@ -1874,7 +1878,7 @@ static int __init arp_tables_init(void) | |||
1874 | if (ret < 0) | 1878 | if (ret < 0) |
1875 | goto err1; | 1879 | goto err1; |
1876 | 1880 | ||
1877 | /* Noone else will be downing sem now, so we won't sleep */ | 1881 | /* No one else will be downing sem now, so we won't sleep */ |
1878 | ret = xt_register_targets(arpt_builtin_tg, ARRAY_SIZE(arpt_builtin_tg)); | 1882 | ret = xt_register_targets(arpt_builtin_tg, ARRAY_SIZE(arpt_builtin_tg)); |
1879 | if (ret < 0) | 1883 | if (ret < 0) |
1880 | goto err2; | 1884 | goto err2; |
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index ffcea0d1678e..764743843503 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c | |||
@@ -68,15 +68,6 @@ void *ipt_alloc_initial_table(const struct xt_table *info) | |||
68 | } | 68 | } |
69 | EXPORT_SYMBOL_GPL(ipt_alloc_initial_table); | 69 | EXPORT_SYMBOL_GPL(ipt_alloc_initial_table); |
70 | 70 | ||
71 | /* | ||
72 | We keep a set of rules for each CPU, so we can avoid write-locking | ||
73 | them in the softirq when updating the counters and therefore | ||
74 | only need to read-lock in the softirq; doing a write_lock_bh() in user | ||
75 | context stops packets coming through and allows user context to read | ||
76 | the counters or update the rules. | ||
77 | |||
78 | Hence the start of any table is given by get_table() below. */ | ||
79 | |||
80 | /* Returns whether matches rule or not. */ | 71 | /* Returns whether matches rule or not. */ |
81 | /* Performance critical - called for every packet */ | 72 | /* Performance critical - called for every packet */ |
82 | static inline bool | 73 | static inline bool |
@@ -311,6 +302,7 @@ ipt_do_table(struct sk_buff *skb, | |||
311 | unsigned int *stackptr, origptr, cpu; | 302 | unsigned int *stackptr, origptr, cpu; |
312 | const struct xt_table_info *private; | 303 | const struct xt_table_info *private; |
313 | struct xt_action_param acpar; | 304 | struct xt_action_param acpar; |
305 | unsigned int addend; | ||
314 | 306 | ||
315 | /* Initialization */ | 307 | /* Initialization */ |
316 | ip = ip_hdr(skb); | 308 | ip = ip_hdr(skb); |
@@ -331,7 +323,8 @@ ipt_do_table(struct sk_buff *skb, | |||
331 | acpar.hooknum = hook; | 323 | acpar.hooknum = hook; |
332 | 324 | ||
333 | IP_NF_ASSERT(table->valid_hooks & (1 << hook)); | 325 | IP_NF_ASSERT(table->valid_hooks & (1 << hook)); |
334 | xt_info_rdlock_bh(); | 326 | local_bh_disable(); |
327 | addend = xt_write_recseq_begin(); | ||
335 | private = table->private; | 328 | private = table->private; |
336 | cpu = smp_processor_id(); | 329 | cpu = smp_processor_id(); |
337 | table_base = private->entries[cpu]; | 330 | table_base = private->entries[cpu]; |
@@ -430,7 +423,9 @@ ipt_do_table(struct sk_buff *skb, | |||
430 | pr_debug("Exiting %s; resetting sp from %u to %u\n", | 423 | pr_debug("Exiting %s; resetting sp from %u to %u\n", |
431 | __func__, *stackptr, origptr); | 424 | __func__, *stackptr, origptr); |
432 | *stackptr = origptr; | 425 | *stackptr = origptr; |
433 | xt_info_rdunlock_bh(); | 426 | xt_write_recseq_end(addend); |
427 | local_bh_enable(); | ||
428 | |||
434 | #ifdef DEBUG_ALLOW_ALL | 429 | #ifdef DEBUG_ALLOW_ALL |
435 | return NF_ACCEPT; | 430 | return NF_ACCEPT; |
436 | #else | 431 | #else |
@@ -886,7 +881,7 @@ get_counters(const struct xt_table_info *t, | |||
886 | unsigned int i; | 881 | unsigned int i; |
887 | 882 | ||
888 | for_each_possible_cpu(cpu) { | 883 | for_each_possible_cpu(cpu) { |
889 | seqlock_t *lock = &per_cpu(xt_info_locks, cpu).lock; | 884 | seqcount_t *s = &per_cpu(xt_recseq, cpu); |
890 | 885 | ||
891 | i = 0; | 886 | i = 0; |
892 | xt_entry_foreach(iter, t->entries[cpu], t->size) { | 887 | xt_entry_foreach(iter, t->entries[cpu], t->size) { |
@@ -894,10 +889,10 @@ get_counters(const struct xt_table_info *t, | |||
894 | unsigned int start; | 889 | unsigned int start; |
895 | 890 | ||
896 | do { | 891 | do { |
897 | start = read_seqbegin(lock); | 892 | start = read_seqcount_begin(s); |
898 | bcnt = iter->counters.bcnt; | 893 | bcnt = iter->counters.bcnt; |
899 | pcnt = iter->counters.pcnt; | 894 | pcnt = iter->counters.pcnt; |
900 | } while (read_seqretry(lock, start)); | 895 | } while (read_seqcount_retry(s, start)); |
901 | 896 | ||
902 | ADD_COUNTER(counters[i], bcnt, pcnt); | 897 | ADD_COUNTER(counters[i], bcnt, pcnt); |
903 | ++i; /* macro does multi eval of i */ | 898 | ++i; /* macro does multi eval of i */ |
@@ -1312,6 +1307,7 @@ do_add_counters(struct net *net, const void __user *user, | |||
1312 | int ret = 0; | 1307 | int ret = 0; |
1313 | void *loc_cpu_entry; | 1308 | void *loc_cpu_entry; |
1314 | struct ipt_entry *iter; | 1309 | struct ipt_entry *iter; |
1310 | unsigned int addend; | ||
1315 | #ifdef CONFIG_COMPAT | 1311 | #ifdef CONFIG_COMPAT |
1316 | struct compat_xt_counters_info compat_tmp; | 1312 | struct compat_xt_counters_info compat_tmp; |
1317 | 1313 | ||
@@ -1368,12 +1364,12 @@ do_add_counters(struct net *net, const void __user *user, | |||
1368 | /* Choose the copy that is on our node */ | 1364 | /* Choose the copy that is on our node */ |
1369 | curcpu = smp_processor_id(); | 1365 | curcpu = smp_processor_id(); |
1370 | loc_cpu_entry = private->entries[curcpu]; | 1366 | loc_cpu_entry = private->entries[curcpu]; |
1371 | xt_info_wrlock(curcpu); | 1367 | addend = xt_write_recseq_begin(); |
1372 | xt_entry_foreach(iter, loc_cpu_entry, private->size) { | 1368 | xt_entry_foreach(iter, loc_cpu_entry, private->size) { |
1373 | ADD_COUNTER(iter->counters, paddc[i].bcnt, paddc[i].pcnt); | 1369 | ADD_COUNTER(iter->counters, paddc[i].bcnt, paddc[i].pcnt); |
1374 | ++i; | 1370 | ++i; |
1375 | } | 1371 | } |
1376 | xt_info_wrunlock(curcpu); | 1372 | xt_write_recseq_end(addend); |
1377 | unlock_up_free: | 1373 | unlock_up_free: |
1378 | local_bh_enable(); | 1374 | local_bh_enable(); |
1379 | xt_table_unlock(t); | 1375 | xt_table_unlock(t); |
@@ -2233,7 +2229,7 @@ static int __init ip_tables_init(void) | |||
2233 | if (ret < 0) | 2229 | if (ret < 0) |
2234 | goto err1; | 2230 | goto err1; |
2235 | 2231 | ||
2236 | /* Noone else will be downing sem now, so we won't sleep */ | 2232 | /* No one else will be downing sem now, so we won't sleep */ |
2237 | ret = xt_register_targets(ipt_builtin_tg, ARRAY_SIZE(ipt_builtin_tg)); | 2233 | ret = xt_register_targets(ipt_builtin_tg, ARRAY_SIZE(ipt_builtin_tg)); |
2238 | if (ret < 0) | 2234 | if (ret < 0) |
2239 | goto err2; | 2235 | goto err2; |
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/ipv4/netfilter/nf_nat_core.c index 21bcf471b25a..9c71b2755ce3 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/ipv4/netfilter/nf_nat_core.c | |||
@@ -521,7 +521,7 @@ int nf_nat_protocol_register(const struct nf_nat_protocol *proto) | |||
521 | } | 521 | } |
522 | EXPORT_SYMBOL(nf_nat_protocol_register); | 522 | EXPORT_SYMBOL(nf_nat_protocol_register); |
523 | 523 | ||
524 | /* Noone stores the protocol anywhere; simply delete it. */ | 524 | /* No one stores the protocol anywhere; simply delete it. */ |
525 | void nf_nat_protocol_unregister(const struct nf_nat_protocol *proto) | 525 | void nf_nat_protocol_unregister(const struct nf_nat_protocol *proto) |
526 | { | 526 | { |
527 | spin_lock_bh(&nf_nat_lock); | 527 | spin_lock_bh(&nf_nat_lock); |
@@ -532,7 +532,7 @@ void nf_nat_protocol_unregister(const struct nf_nat_protocol *proto) | |||
532 | } | 532 | } |
533 | EXPORT_SYMBOL(nf_nat_protocol_unregister); | 533 | EXPORT_SYMBOL(nf_nat_protocol_unregister); |
534 | 534 | ||
535 | /* Noone using conntrack by the time this called. */ | 535 | /* No one using conntrack by the time this called. */ |
536 | static void nf_nat_cleanup_conntrack(struct nf_conn *ct) | 536 | static void nf_nat_cleanup_conntrack(struct nf_conn *ct) |
537 | { | 537 | { |
538 | struct nf_conn_nat *nat = nf_ct_ext_find(ct, NF_CT_EXT_NAT); | 538 | struct nf_conn_nat *nat = nf_ct_ext_find(ct, NF_CT_EXT_NAT); |
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c index 31427fb57aa8..99cfa28b6d38 100644 --- a/net/ipv4/netfilter/nf_nat_helper.c +++ b/net/ipv4/netfilter/nf_nat_helper.c | |||
@@ -153,7 +153,7 @@ void nf_nat_set_seq_adjust(struct nf_conn *ct, enum ip_conntrack_info ctinfo, | |||
153 | } | 153 | } |
154 | EXPORT_SYMBOL_GPL(nf_nat_set_seq_adjust); | 154 | EXPORT_SYMBOL_GPL(nf_nat_set_seq_adjust); |
155 | 155 | ||
156 | static void nf_nat_csum(struct sk_buff *skb, struct iphdr *iph, void *data, | 156 | static void nf_nat_csum(struct sk_buff *skb, const struct iphdr *iph, void *data, |
157 | int datalen, __sum16 *check, int oldlen) | 157 | int datalen, __sum16 *check, int oldlen) |
158 | { | 158 | { |
159 | struct rtable *rt = skb_rtable(skb); | 159 | struct rtable *rt = skb_rtable(skb); |
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c new file mode 100644 index 000000000000..41836ab6c200 --- /dev/null +++ b/net/ipv4/ping.c | |||
@@ -0,0 +1,918 @@ | |||
1 | /* | ||
2 | * INET An implementation of the TCP/IP protocol suite for the LINUX | ||
3 | * operating system. INET is implemented using the BSD Socket | ||
4 | * interface as the means of communication with the user level. | ||
5 | * | ||
6 | * "Ping" sockets | ||
7 | * | ||
8 | * This program is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU General Public License | ||
10 | * as published by the Free Software Foundation; either version | ||
11 | * 2 of the License, or (at your option) any later version. | ||
12 | * | ||
13 | * Based on ipv4/udp.c code. | ||
14 | * | ||
15 | * Authors: Vasiliy Kulikov / Openwall (for Linux 2.6), | ||
16 | * Pavel Kankovsky (for Linux 2.4.32) | ||
17 | * | ||
18 | * Pavel gave all rights to bugs to Vasiliy, | ||
19 | * none of the bugs are Pavel's now. | ||
20 | * | ||
21 | */ | ||
22 | |||
23 | #include <asm/system.h> | ||
24 | #include <linux/uaccess.h> | ||
25 | #include <linux/types.h> | ||
26 | #include <linux/fcntl.h> | ||
27 | #include <linux/socket.h> | ||
28 | #include <linux/sockios.h> | ||
29 | #include <linux/in.h> | ||
30 | #include <linux/errno.h> | ||
31 | #include <linux/timer.h> | ||
32 | #include <linux/mm.h> | ||
33 | #include <linux/inet.h> | ||
34 | #include <linux/netdevice.h> | ||
35 | #include <net/snmp.h> | ||
36 | #include <net/ip.h> | ||
37 | #include <net/ipv6.h> | ||
38 | #include <net/icmp.h> | ||
39 | #include <net/protocol.h> | ||
40 | #include <linux/skbuff.h> | ||
41 | #include <linux/proc_fs.h> | ||
42 | #include <net/sock.h> | ||
43 | #include <net/ping.h> | ||
44 | #include <net/icmp.h> | ||
45 | #include <net/udp.h> | ||
46 | #include <net/route.h> | ||
47 | #include <net/inet_common.h> | ||
48 | #include <net/checksum.h> | ||
49 | |||
50 | |||
51 | static struct ping_table ping_table; | ||
52 | |||
53 | static u16 ping_port_rover; | ||
54 | |||
55 | static inline int ping_hashfn(struct net *net, unsigned num, unsigned mask) | ||
56 | { | ||
57 | int res = (num + net_hash_mix(net)) & mask; | ||
58 | pr_debug("hash(%d) = %d\n", num, res); | ||
59 | return res; | ||
60 | } | ||
61 | |||
62 | static inline struct hlist_nulls_head *ping_hashslot(struct ping_table *table, | ||
63 | struct net *net, unsigned num) | ||
64 | { | ||
65 | return &table->hash[ping_hashfn(net, num, PING_HTABLE_MASK)]; | ||
66 | } | ||
67 | |||
68 | static int ping_v4_get_port(struct sock *sk, unsigned short ident) | ||
69 | { | ||
70 | struct hlist_nulls_node *node; | ||
71 | struct hlist_nulls_head *hlist; | ||
72 | struct inet_sock *isk, *isk2; | ||
73 | struct sock *sk2 = NULL; | ||
74 | |||
75 | isk = inet_sk(sk); | ||
76 | write_lock_bh(&ping_table.lock); | ||
77 | if (ident == 0) { | ||
78 | u32 i; | ||
79 | u16 result = ping_port_rover + 1; | ||
80 | |||
81 | for (i = 0; i < (1L << 16); i++, result++) { | ||
82 | if (!result) | ||
83 | result++; /* avoid zero */ | ||
84 | hlist = ping_hashslot(&ping_table, sock_net(sk), | ||
85 | result); | ||
86 | ping_portaddr_for_each_entry(sk2, node, hlist) { | ||
87 | isk2 = inet_sk(sk2); | ||
88 | |||
89 | if (isk2->inet_num == result) | ||
90 | goto next_port; | ||
91 | } | ||
92 | |||
93 | /* found */ | ||
94 | ping_port_rover = ident = result; | ||
95 | break; | ||
96 | next_port: | ||
97 | ; | ||
98 | } | ||
99 | if (i >= (1L << 16)) | ||
100 | goto fail; | ||
101 | } else { | ||
102 | hlist = ping_hashslot(&ping_table, sock_net(sk), ident); | ||
103 | ping_portaddr_for_each_entry(sk2, node, hlist) { | ||
104 | isk2 = inet_sk(sk2); | ||
105 | |||
106 | if ((isk2->inet_num == ident) && | ||
107 | (sk2 != sk) && | ||
108 | (!sk2->sk_reuse || !sk->sk_reuse)) | ||
109 | goto fail; | ||
110 | } | ||
111 | } | ||
112 | |||
113 | pr_debug("found port/ident = %d\n", ident); | ||
114 | isk->inet_num = ident; | ||
115 | if (sk_unhashed(sk)) { | ||
116 | pr_debug("was not hashed\n"); | ||
117 | sock_hold(sk); | ||
118 | hlist_nulls_add_head(&sk->sk_nulls_node, hlist); | ||
119 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); | ||
120 | } | ||
121 | write_unlock_bh(&ping_table.lock); | ||
122 | return 0; | ||
123 | |||
124 | fail: | ||
125 | write_unlock_bh(&ping_table.lock); | ||
126 | return 1; | ||
127 | } | ||
128 | |||
129 | static void ping_v4_hash(struct sock *sk) | ||
130 | { | ||
131 | pr_debug("ping_v4_hash(sk->port=%u)\n", inet_sk(sk)->inet_num); | ||
132 | BUG(); /* "Please do not press this button again." */ | ||
133 | } | ||
134 | |||
135 | static void ping_v4_unhash(struct sock *sk) | ||
136 | { | ||
137 | struct inet_sock *isk = inet_sk(sk); | ||
138 | pr_debug("ping_v4_unhash(isk=%p,isk->num=%u)\n", isk, isk->inet_num); | ||
139 | if (sk_hashed(sk)) { | ||
140 | struct hlist_nulls_head *hslot; | ||
141 | |||
142 | hslot = ping_hashslot(&ping_table, sock_net(sk), isk->inet_num); | ||
143 | write_lock_bh(&ping_table.lock); | ||
144 | hlist_nulls_del(&sk->sk_nulls_node); | ||
145 | sock_put(sk); | ||
146 | isk->inet_num = isk->inet_sport = 0; | ||
147 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1); | ||
148 | write_unlock_bh(&ping_table.lock); | ||
149 | } | ||
150 | } | ||
151 | |||
152 | static struct sock *ping_v4_lookup(struct net *net, u32 saddr, u32 daddr, | ||
153 | u16 ident, int dif) | ||
154 | { | ||
155 | struct hlist_nulls_head *hslot = ping_hashslot(&ping_table, net, ident); | ||
156 | struct sock *sk = NULL; | ||
157 | struct inet_sock *isk; | ||
158 | struct hlist_nulls_node *hnode; | ||
159 | |||
160 | pr_debug("try to find: num = %d, daddr = %ld, dif = %d\n", | ||
161 | (int)ident, (unsigned long)daddr, dif); | ||
162 | read_lock_bh(&ping_table.lock); | ||
163 | |||
164 | ping_portaddr_for_each_entry(sk, hnode, hslot) { | ||
165 | isk = inet_sk(sk); | ||
166 | |||
167 | pr_debug("found: %p: num = %d, daddr = %ld, dif = %d\n", sk, | ||
168 | (int)isk->inet_num, (unsigned long)isk->inet_rcv_saddr, | ||
169 | sk->sk_bound_dev_if); | ||
170 | |||
171 | pr_debug("iterate\n"); | ||
172 | if (isk->inet_num != ident) | ||
173 | continue; | ||
174 | if (isk->inet_rcv_saddr && isk->inet_rcv_saddr != daddr) | ||
175 | continue; | ||
176 | if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif) | ||
177 | continue; | ||
178 | |||
179 | sock_hold(sk); | ||
180 | goto exit; | ||
181 | } | ||
182 | |||
183 | sk = NULL; | ||
184 | exit: | ||
185 | read_unlock_bh(&ping_table.lock); | ||
186 | |||
187 | return sk; | ||
188 | } | ||
189 | |||
190 | static int ping_init_sock(struct sock *sk) | ||
191 | { | ||
192 | struct net *net = sock_net(sk); | ||
193 | gid_t group = current_egid(); | ||
194 | gid_t range[2]; | ||
195 | struct group_info *group_info = get_current_groups(); | ||
196 | int i, j, count = group_info->ngroups; | ||
197 | |||
198 | inet_get_ping_group_range_net(net, range, range+1); | ||
199 | if (range[0] <= group && group <= range[1]) | ||
200 | return 0; | ||
201 | |||
202 | for (i = 0; i < group_info->nblocks; i++) { | ||
203 | int cp_count = min_t(int, NGROUPS_PER_BLOCK, count); | ||
204 | |||
205 | for (j = 0; j < cp_count; j++) { | ||
206 | group = group_info->blocks[i][j]; | ||
207 | if (range[0] <= group && group <= range[1]) | ||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | count -= cp_count; | ||
212 | } | ||
213 | |||
214 | return -EACCES; | ||
215 | } | ||
216 | |||
217 | static void ping_close(struct sock *sk, long timeout) | ||
218 | { | ||
219 | pr_debug("ping_close(sk=%p,sk->num=%u)\n", | ||
220 | inet_sk(sk), inet_sk(sk)->inet_num); | ||
221 | pr_debug("isk->refcnt = %d\n", sk->sk_refcnt.counter); | ||
222 | |||
223 | sk_common_release(sk); | ||
224 | } | ||
225 | |||
226 | /* | ||
227 | * We need our own bind because there are no privileged id's == local ports. | ||
228 | * Moreover, we don't allow binding to multi- and broadcast addresses. | ||
229 | */ | ||
230 | |||
231 | static int ping_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) | ||
232 | { | ||
233 | struct sockaddr_in *addr = (struct sockaddr_in *)uaddr; | ||
234 | struct inet_sock *isk = inet_sk(sk); | ||
235 | unsigned short snum; | ||
236 | int chk_addr_ret; | ||
237 | int err; | ||
238 | |||
239 | if (addr_len < sizeof(struct sockaddr_in)) | ||
240 | return -EINVAL; | ||
241 | |||
242 | pr_debug("ping_v4_bind(sk=%p,sa_addr=%08x,sa_port=%d)\n", | ||
243 | sk, addr->sin_addr.s_addr, ntohs(addr->sin_port)); | ||
244 | |||
245 | chk_addr_ret = inet_addr_type(sock_net(sk), addr->sin_addr.s_addr); | ||
246 | if (addr->sin_addr.s_addr == INADDR_ANY) | ||
247 | chk_addr_ret = RTN_LOCAL; | ||
248 | |||
249 | if ((sysctl_ip_nonlocal_bind == 0 && | ||
250 | isk->freebind == 0 && isk->transparent == 0 && | ||
251 | chk_addr_ret != RTN_LOCAL) || | ||
252 | chk_addr_ret == RTN_MULTICAST || | ||
253 | chk_addr_ret == RTN_BROADCAST) | ||
254 | return -EADDRNOTAVAIL; | ||
255 | |||
256 | lock_sock(sk); | ||
257 | |||
258 | err = -EINVAL; | ||
259 | if (isk->inet_num != 0) | ||
260 | goto out; | ||
261 | |||
262 | err = -EADDRINUSE; | ||
263 | isk->inet_rcv_saddr = isk->inet_saddr = addr->sin_addr.s_addr; | ||
264 | snum = ntohs(addr->sin_port); | ||
265 | if (ping_v4_get_port(sk, snum) != 0) { | ||
266 | isk->inet_saddr = isk->inet_rcv_saddr = 0; | ||
267 | goto out; | ||
268 | } | ||
269 | |||
270 | pr_debug("after bind(): num = %d, daddr = %ld, dif = %d\n", | ||
271 | (int)isk->inet_num, | ||
272 | (unsigned long) isk->inet_rcv_saddr, | ||
273 | (int)sk->sk_bound_dev_if); | ||
274 | |||
275 | err = 0; | ||
276 | if (isk->inet_rcv_saddr) | ||
277 | sk->sk_userlocks |= SOCK_BINDADDR_LOCK; | ||
278 | if (snum) | ||
279 | sk->sk_userlocks |= SOCK_BINDPORT_LOCK; | ||
280 | isk->inet_sport = htons(isk->inet_num); | ||
281 | isk->inet_daddr = 0; | ||
282 | isk->inet_dport = 0; | ||
283 | sk_dst_reset(sk); | ||
284 | out: | ||
285 | release_sock(sk); | ||
286 | pr_debug("ping_v4_bind -> %d\n", err); | ||
287 | return err; | ||
288 | } | ||
289 | |||
290 | /* | ||
291 | * Is this a supported type of ICMP message? | ||
292 | */ | ||
293 | |||
294 | static inline int ping_supported(int type, int code) | ||
295 | { | ||
296 | if (type == ICMP_ECHO && code == 0) | ||
297 | return 1; | ||
298 | return 0; | ||
299 | } | ||
300 | |||
301 | /* | ||
302 | * This routine is called by the ICMP module when it gets some | ||
303 | * sort of error condition. | ||
304 | */ | ||
305 | |||
306 | static int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb); | ||
307 | |||
308 | void ping_err(struct sk_buff *skb, u32 info) | ||
309 | { | ||
310 | struct iphdr *iph = (struct iphdr *)skb->data; | ||
311 | struct icmphdr *icmph = (struct icmphdr *)(skb->data+(iph->ihl<<2)); | ||
312 | struct inet_sock *inet_sock; | ||
313 | int type = icmph->type; | ||
314 | int code = icmph->code; | ||
315 | struct net *net = dev_net(skb->dev); | ||
316 | struct sock *sk; | ||
317 | int harderr; | ||
318 | int err; | ||
319 | |||
320 | /* We assume the packet has already been checked by icmp_unreach */ | ||
321 | |||
322 | if (!ping_supported(icmph->type, icmph->code)) | ||
323 | return; | ||
324 | |||
325 | pr_debug("ping_err(type=%04x,code=%04x,id=%04x,seq=%04x)\n", type, | ||
326 | code, ntohs(icmph->un.echo.id), ntohs(icmph->un.echo.sequence)); | ||
327 | |||
328 | sk = ping_v4_lookup(net, iph->daddr, iph->saddr, | ||
329 | ntohs(icmph->un.echo.id), skb->dev->ifindex); | ||
330 | if (sk == NULL) { | ||
331 | ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); | ||
332 | pr_debug("no socket, dropping\n"); | ||
333 | return; /* No socket for error */ | ||
334 | } | ||
335 | pr_debug("err on socket %p\n", sk); | ||
336 | |||
337 | err = 0; | ||
338 | harderr = 0; | ||
339 | inet_sock = inet_sk(sk); | ||
340 | |||
341 | switch (type) { | ||
342 | default: | ||
343 | case ICMP_TIME_EXCEEDED: | ||
344 | err = EHOSTUNREACH; | ||
345 | break; | ||
346 | case ICMP_SOURCE_QUENCH: | ||
347 | /* This is not a real error but ping wants to see it. | ||
348 | * Report it with some fake errno. */ | ||
349 | err = EREMOTEIO; | ||
350 | break; | ||
351 | case ICMP_PARAMETERPROB: | ||
352 | err = EPROTO; | ||
353 | harderr = 1; | ||
354 | break; | ||
355 | case ICMP_DEST_UNREACH: | ||
356 | if (code == ICMP_FRAG_NEEDED) { /* Path MTU discovery */ | ||
357 | if (inet_sock->pmtudisc != IP_PMTUDISC_DONT) { | ||
358 | err = EMSGSIZE; | ||
359 | harderr = 1; | ||
360 | break; | ||
361 | } | ||
362 | goto out; | ||
363 | } | ||
364 | err = EHOSTUNREACH; | ||
365 | if (code <= NR_ICMP_UNREACH) { | ||
366 | harderr = icmp_err_convert[code].fatal; | ||
367 | err = icmp_err_convert[code].errno; | ||
368 | } | ||
369 | break; | ||
370 | case ICMP_REDIRECT: | ||
371 | /* See ICMP_SOURCE_QUENCH */ | ||
372 | err = EREMOTEIO; | ||
373 | break; | ||
374 | } | ||
375 | |||
376 | /* | ||
377 | * RFC1122: OK. Passes ICMP errors back to application, as per | ||
378 | * 4.1.3.3. | ||
379 | */ | ||
380 | if (!inet_sock->recverr) { | ||
381 | if (!harderr || sk->sk_state != TCP_ESTABLISHED) | ||
382 | goto out; | ||
383 | } else { | ||
384 | ip_icmp_error(sk, skb, err, 0 /* no remote port */, | ||
385 | info, (u8 *)icmph); | ||
386 | } | ||
387 | sk->sk_err = err; | ||
388 | sk->sk_error_report(sk); | ||
389 | out: | ||
390 | sock_put(sk); | ||
391 | } | ||
392 | |||
393 | /* | ||
394 | * Copy and checksum an ICMP Echo packet from user space into a buffer. | ||
395 | */ | ||
396 | |||
397 | struct pingfakehdr { | ||
398 | struct icmphdr icmph; | ||
399 | struct iovec *iov; | ||
400 | u32 wcheck; | ||
401 | }; | ||
402 | |||
403 | static int ping_getfrag(void *from, char * to, | ||
404 | int offset, int fraglen, int odd, struct sk_buff *skb) | ||
405 | { | ||
406 | struct pingfakehdr *pfh = (struct pingfakehdr *)from; | ||
407 | |||
408 | if (offset == 0) { | ||
409 | if (fraglen < sizeof(struct icmphdr)) | ||
410 | BUG(); | ||
411 | if (csum_partial_copy_fromiovecend(to + sizeof(struct icmphdr), | ||
412 | pfh->iov, 0, fraglen - sizeof(struct icmphdr), | ||
413 | &pfh->wcheck)) | ||
414 | return -EFAULT; | ||
415 | |||
416 | return 0; | ||
417 | } | ||
418 | if (offset < sizeof(struct icmphdr)) | ||
419 | BUG(); | ||
420 | if (csum_partial_copy_fromiovecend | ||
421 | (to, pfh->iov, offset - sizeof(struct icmphdr), | ||
422 | fraglen, &pfh->wcheck)) | ||
423 | return -EFAULT; | ||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | static int ping_push_pending_frames(struct sock *sk, struct pingfakehdr *pfh, struct flowi4 *fl4) | ||
428 | { | ||
429 | struct sk_buff *skb = skb_peek(&sk->sk_write_queue); | ||
430 | |||
431 | pfh->wcheck = csum_partial((char *)&pfh->icmph, | ||
432 | sizeof(struct icmphdr), pfh->wcheck); | ||
433 | pfh->icmph.checksum = csum_fold(pfh->wcheck); | ||
434 | memcpy(icmp_hdr(skb), &pfh->icmph, sizeof(struct icmphdr)); | ||
435 | skb->ip_summed = CHECKSUM_NONE; | ||
436 | return ip_push_pending_frames(sk, fl4); | ||
437 | } | ||
438 | |||
439 | int ping_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | ||
440 | size_t len) | ||
441 | { | ||
442 | struct net *net = sock_net(sk); | ||
443 | struct flowi4 fl4; | ||
444 | struct inet_sock *inet = inet_sk(sk); | ||
445 | struct ipcm_cookie ipc; | ||
446 | struct icmphdr user_icmph; | ||
447 | struct pingfakehdr pfh; | ||
448 | struct rtable *rt = NULL; | ||
449 | struct ip_options_data opt_copy; | ||
450 | int free = 0; | ||
451 | u32 saddr, daddr, faddr; | ||
452 | u8 tos; | ||
453 | int err; | ||
454 | |||
455 | pr_debug("ping_sendmsg(sk=%p,sk->num=%u)\n", inet, inet->inet_num); | ||
456 | |||
457 | |||
458 | if (len > 0xFFFF) | ||
459 | return -EMSGSIZE; | ||
460 | |||
461 | /* | ||
462 | * Check the flags. | ||
463 | */ | ||
464 | |||
465 | /* Mirror BSD error message compatibility */ | ||
466 | if (msg->msg_flags & MSG_OOB) | ||
467 | return -EOPNOTSUPP; | ||
468 | |||
469 | /* | ||
470 | * Fetch the ICMP header provided by the userland. | ||
471 | * iovec is modified! | ||
472 | */ | ||
473 | |||
474 | if (memcpy_fromiovec((u8 *)&user_icmph, msg->msg_iov, | ||
475 | sizeof(struct icmphdr))) | ||
476 | return -EFAULT; | ||
477 | if (!ping_supported(user_icmph.type, user_icmph.code)) | ||
478 | return -EINVAL; | ||
479 | |||
480 | /* | ||
481 | * Get and verify the address. | ||
482 | */ | ||
483 | |||
484 | if (msg->msg_name) { | ||
485 | struct sockaddr_in *usin = (struct sockaddr_in *)msg->msg_name; | ||
486 | if (msg->msg_namelen < sizeof(*usin)) | ||
487 | return -EINVAL; | ||
488 | if (usin->sin_family != AF_INET) | ||
489 | return -EINVAL; | ||
490 | daddr = usin->sin_addr.s_addr; | ||
491 | /* no remote port */ | ||
492 | } else { | ||
493 | if (sk->sk_state != TCP_ESTABLISHED) | ||
494 | return -EDESTADDRREQ; | ||
495 | daddr = inet->inet_daddr; | ||
496 | /* no remote port */ | ||
497 | } | ||
498 | |||
499 | ipc.addr = inet->inet_saddr; | ||
500 | ipc.opt = NULL; | ||
501 | ipc.oif = sk->sk_bound_dev_if; | ||
502 | ipc.tx_flags = 0; | ||
503 | err = sock_tx_timestamp(sk, &ipc.tx_flags); | ||
504 | if (err) | ||
505 | return err; | ||
506 | |||
507 | if (msg->msg_controllen) { | ||
508 | err = ip_cmsg_send(sock_net(sk), msg, &ipc); | ||
509 | if (err) | ||
510 | return err; | ||
511 | if (ipc.opt) | ||
512 | free = 1; | ||
513 | } | ||
514 | if (!ipc.opt) { | ||
515 | struct ip_options_rcu *inet_opt; | ||
516 | |||
517 | rcu_read_lock(); | ||
518 | inet_opt = rcu_dereference(inet->inet_opt); | ||
519 | if (inet_opt) { | ||
520 | memcpy(&opt_copy, inet_opt, | ||
521 | sizeof(*inet_opt) + inet_opt->opt.optlen); | ||
522 | ipc.opt = &opt_copy.opt; | ||
523 | } | ||
524 | rcu_read_unlock(); | ||
525 | } | ||
526 | |||
527 | saddr = ipc.addr; | ||
528 | ipc.addr = faddr = daddr; | ||
529 | |||
530 | if (ipc.opt && ipc.opt->opt.srr) { | ||
531 | if (!daddr) | ||
532 | return -EINVAL; | ||
533 | faddr = ipc.opt->opt.faddr; | ||
534 | } | ||
535 | tos = RT_TOS(inet->tos); | ||
536 | if (sock_flag(sk, SOCK_LOCALROUTE) || | ||
537 | (msg->msg_flags & MSG_DONTROUTE) || | ||
538 | (ipc.opt && ipc.opt->opt.is_strictroute)) { | ||
539 | tos |= RTO_ONLINK; | ||
540 | } | ||
541 | |||
542 | if (ipv4_is_multicast(daddr)) { | ||
543 | if (!ipc.oif) | ||
544 | ipc.oif = inet->mc_index; | ||
545 | if (!saddr) | ||
546 | saddr = inet->mc_addr; | ||
547 | } | ||
548 | |||
549 | flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos, | ||
550 | RT_SCOPE_UNIVERSE, sk->sk_protocol, | ||
551 | inet_sk_flowi_flags(sk), faddr, saddr, 0, 0); | ||
552 | |||
553 | security_sk_classify_flow(sk, flowi4_to_flowi(&fl4)); | ||
554 | rt = ip_route_output_flow(net, &fl4, sk); | ||
555 | if (IS_ERR(rt)) { | ||
556 | err = PTR_ERR(rt); | ||
557 | rt = NULL; | ||
558 | if (err == -ENETUNREACH) | ||
559 | IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES); | ||
560 | goto out; | ||
561 | } | ||
562 | |||
563 | err = -EACCES; | ||
564 | if ((rt->rt_flags & RTCF_BROADCAST) && | ||
565 | !sock_flag(sk, SOCK_BROADCAST)) | ||
566 | goto out; | ||
567 | |||
568 | if (msg->msg_flags & MSG_CONFIRM) | ||
569 | goto do_confirm; | ||
570 | back_from_confirm: | ||
571 | |||
572 | if (!ipc.addr) | ||
573 | ipc.addr = fl4.daddr; | ||
574 | |||
575 | lock_sock(sk); | ||
576 | |||
577 | pfh.icmph.type = user_icmph.type; /* already checked */ | ||
578 | pfh.icmph.code = user_icmph.code; /* ditto */ | ||
579 | pfh.icmph.checksum = 0; | ||
580 | pfh.icmph.un.echo.id = inet->inet_sport; | ||
581 | pfh.icmph.un.echo.sequence = user_icmph.un.echo.sequence; | ||
582 | pfh.iov = msg->msg_iov; | ||
583 | pfh.wcheck = 0; | ||
584 | |||
585 | err = ip_append_data(sk, &fl4, ping_getfrag, &pfh, len, | ||
586 | 0, &ipc, &rt, msg->msg_flags); | ||
587 | if (err) | ||
588 | ip_flush_pending_frames(sk); | ||
589 | else | ||
590 | err = ping_push_pending_frames(sk, &pfh, &fl4); | ||
591 | release_sock(sk); | ||
592 | |||
593 | out: | ||
594 | ip_rt_put(rt); | ||
595 | if (free) | ||
596 | kfree(ipc.opt); | ||
597 | if (!err) { | ||
598 | icmp_out_count(sock_net(sk), user_icmph.type); | ||
599 | return len; | ||
600 | } | ||
601 | return err; | ||
602 | |||
603 | do_confirm: | ||
604 | dst_confirm(&rt->dst); | ||
605 | if (!(msg->msg_flags & MSG_PROBE) || len) | ||
606 | goto back_from_confirm; | ||
607 | err = 0; | ||
608 | goto out; | ||
609 | } | ||
610 | |||
611 | int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | ||
612 | size_t len, int noblock, int flags, int *addr_len) | ||
613 | { | ||
614 | struct inet_sock *isk = inet_sk(sk); | ||
615 | struct sockaddr_in *sin = (struct sockaddr_in *)msg->msg_name; | ||
616 | struct sk_buff *skb; | ||
617 | int copied, err; | ||
618 | |||
619 | pr_debug("ping_recvmsg(sk=%p,sk->num=%u)\n", isk, isk->inet_num); | ||
620 | |||
621 | if (flags & MSG_OOB) | ||
622 | goto out; | ||
623 | |||
624 | if (addr_len) | ||
625 | *addr_len = sizeof(*sin); | ||
626 | |||
627 | if (flags & MSG_ERRQUEUE) | ||
628 | return ip_recv_error(sk, msg, len); | ||
629 | |||
630 | skb = skb_recv_datagram(sk, flags, noblock, &err); | ||
631 | if (!skb) | ||
632 | goto out; | ||
633 | |||
634 | copied = skb->len; | ||
635 | if (copied > len) { | ||
636 | msg->msg_flags |= MSG_TRUNC; | ||
637 | copied = len; | ||
638 | } | ||
639 | |||
640 | /* Don't bother checking the checksum */ | ||
641 | err = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied); | ||
642 | if (err) | ||
643 | goto done; | ||
644 | |||
645 | sock_recv_timestamp(msg, sk, skb); | ||
646 | |||
647 | /* Copy the address. */ | ||
648 | if (sin) { | ||
649 | sin->sin_family = AF_INET; | ||
650 | sin->sin_port = 0 /* skb->h.uh->source */; | ||
651 | sin->sin_addr.s_addr = ip_hdr(skb)->saddr; | ||
652 | memset(sin->sin_zero, 0, sizeof(sin->sin_zero)); | ||
653 | } | ||
654 | if (isk->cmsg_flags) | ||
655 | ip_cmsg_recv(msg, skb); | ||
656 | err = copied; | ||
657 | |||
658 | done: | ||
659 | skb_free_datagram(sk, skb); | ||
660 | out: | ||
661 | pr_debug("ping_recvmsg -> %d\n", err); | ||
662 | return err; | ||
663 | } | ||
664 | |||
665 | static int ping_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | ||
666 | { | ||
667 | pr_debug("ping_queue_rcv_skb(sk=%p,sk->num=%d,skb=%p)\n", | ||
668 | inet_sk(sk), inet_sk(sk)->inet_num, skb); | ||
669 | if (sock_queue_rcv_skb(sk, skb) < 0) { | ||
670 | ICMP_INC_STATS_BH(sock_net(sk), ICMP_MIB_INERRORS); | ||
671 | kfree_skb(skb); | ||
672 | pr_debug("ping_queue_rcv_skb -> failed\n"); | ||
673 | return -1; | ||
674 | } | ||
675 | return 0; | ||
676 | } | ||
677 | |||
678 | |||
679 | /* | ||
680 | * All we need to do is get the socket. | ||
681 | */ | ||
682 | |||
683 | void ping_rcv(struct sk_buff *skb) | ||
684 | { | ||
685 | struct sock *sk; | ||
686 | struct net *net = dev_net(skb->dev); | ||
687 | struct iphdr *iph = ip_hdr(skb); | ||
688 | struct icmphdr *icmph = icmp_hdr(skb); | ||
689 | u32 saddr = iph->saddr; | ||
690 | u32 daddr = iph->daddr; | ||
691 | |||
692 | /* We assume the packet has already been checked by icmp_rcv */ | ||
693 | |||
694 | pr_debug("ping_rcv(skb=%p,id=%04x,seq=%04x)\n", | ||
695 | skb, ntohs(icmph->un.echo.id), ntohs(icmph->un.echo.sequence)); | ||
696 | |||
697 | /* Push ICMP header back */ | ||
698 | skb_push(skb, skb->data - (u8 *)icmph); | ||
699 | |||
700 | sk = ping_v4_lookup(net, saddr, daddr, ntohs(icmph->un.echo.id), | ||
701 | skb->dev->ifindex); | ||
702 | if (sk != NULL) { | ||
703 | pr_debug("rcv on socket %p\n", sk); | ||
704 | ping_queue_rcv_skb(sk, skb_get(skb)); | ||
705 | sock_put(sk); | ||
706 | return; | ||
707 | } | ||
708 | pr_debug("no socket, dropping\n"); | ||
709 | |||
710 | /* We're called from icmp_rcv(). kfree_skb() is done there. */ | ||
711 | } | ||
712 | |||
713 | struct proto ping_prot = { | ||
714 | .name = "PING", | ||
715 | .owner = THIS_MODULE, | ||
716 | .init = ping_init_sock, | ||
717 | .close = ping_close, | ||
718 | .connect = ip4_datagram_connect, | ||
719 | .disconnect = udp_disconnect, | ||
720 | .setsockopt = ip_setsockopt, | ||
721 | .getsockopt = ip_getsockopt, | ||
722 | .sendmsg = ping_sendmsg, | ||
723 | .recvmsg = ping_recvmsg, | ||
724 | .bind = ping_bind, | ||
725 | .backlog_rcv = ping_queue_rcv_skb, | ||
726 | .hash = ping_v4_hash, | ||
727 | .unhash = ping_v4_unhash, | ||
728 | .get_port = ping_v4_get_port, | ||
729 | .obj_size = sizeof(struct inet_sock), | ||
730 | }; | ||
731 | EXPORT_SYMBOL(ping_prot); | ||
732 | |||
733 | #ifdef CONFIG_PROC_FS | ||
734 | |||
735 | static struct sock *ping_get_first(struct seq_file *seq, int start) | ||
736 | { | ||
737 | struct sock *sk; | ||
738 | struct ping_iter_state *state = seq->private; | ||
739 | struct net *net = seq_file_net(seq); | ||
740 | |||
741 | for (state->bucket = start; state->bucket < PING_HTABLE_SIZE; | ||
742 | ++state->bucket) { | ||
743 | struct hlist_nulls_node *node; | ||
744 | struct hlist_nulls_head *hslot = &ping_table.hash[state->bucket]; | ||
745 | |||
746 | if (hlist_nulls_empty(hslot)) | ||
747 | continue; | ||
748 | |||
749 | sk_nulls_for_each(sk, node, hslot) { | ||
750 | if (net_eq(sock_net(sk), net)) | ||
751 | goto found; | ||
752 | } | ||
753 | } | ||
754 | sk = NULL; | ||
755 | found: | ||
756 | return sk; | ||
757 | } | ||
758 | |||
759 | static struct sock *ping_get_next(struct seq_file *seq, struct sock *sk) | ||
760 | { | ||
761 | struct ping_iter_state *state = seq->private; | ||
762 | struct net *net = seq_file_net(seq); | ||
763 | |||
764 | do { | ||
765 | sk = sk_nulls_next(sk); | ||
766 | } while (sk && (!net_eq(sock_net(sk), net))); | ||
767 | |||
768 | if (!sk) | ||
769 | return ping_get_first(seq, state->bucket + 1); | ||
770 | return sk; | ||
771 | } | ||
772 | |||
773 | static struct sock *ping_get_idx(struct seq_file *seq, loff_t pos) | ||
774 | { | ||
775 | struct sock *sk = ping_get_first(seq, 0); | ||
776 | |||
777 | if (sk) | ||
778 | while (pos && (sk = ping_get_next(seq, sk)) != NULL) | ||
779 | --pos; | ||
780 | return pos ? NULL : sk; | ||
781 | } | ||
782 | |||
783 | static void *ping_seq_start(struct seq_file *seq, loff_t *pos) | ||
784 | { | ||
785 | struct ping_iter_state *state = seq->private; | ||
786 | state->bucket = 0; | ||
787 | |||
788 | read_lock_bh(&ping_table.lock); | ||
789 | |||
790 | return *pos ? ping_get_idx(seq, *pos-1) : SEQ_START_TOKEN; | ||
791 | } | ||
792 | |||
793 | static void *ping_seq_next(struct seq_file *seq, void *v, loff_t *pos) | ||
794 | { | ||
795 | struct sock *sk; | ||
796 | |||
797 | if (v == SEQ_START_TOKEN) | ||
798 | sk = ping_get_idx(seq, 0); | ||
799 | else | ||
800 | sk = ping_get_next(seq, v); | ||
801 | |||
802 | ++*pos; | ||
803 | return sk; | ||
804 | } | ||
805 | |||
806 | static void ping_seq_stop(struct seq_file *seq, void *v) | ||
807 | { | ||
808 | read_unlock_bh(&ping_table.lock); | ||
809 | } | ||
810 | |||
811 | static void ping_format_sock(struct sock *sp, struct seq_file *f, | ||
812 | int bucket, int *len) | ||
813 | { | ||
814 | struct inet_sock *inet = inet_sk(sp); | ||
815 | __be32 dest = inet->inet_daddr; | ||
816 | __be32 src = inet->inet_rcv_saddr; | ||
817 | __u16 destp = ntohs(inet->inet_dport); | ||
818 | __u16 srcp = ntohs(inet->inet_sport); | ||
819 | |||
820 | seq_printf(f, "%5d: %08X:%04X %08X:%04X" | ||
821 | " %02X %08X:%08X %02X:%08lX %08X %5d %8d %lu %d %pK %d%n", | ||
822 | bucket, src, srcp, dest, destp, sp->sk_state, | ||
823 | sk_wmem_alloc_get(sp), | ||
824 | sk_rmem_alloc_get(sp), | ||
825 | 0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp), | ||
826 | atomic_read(&sp->sk_refcnt), sp, | ||
827 | atomic_read(&sp->sk_drops), len); | ||
828 | } | ||
829 | |||
830 | static int ping_seq_show(struct seq_file *seq, void *v) | ||
831 | { | ||
832 | if (v == SEQ_START_TOKEN) | ||
833 | seq_printf(seq, "%-127s\n", | ||
834 | " sl local_address rem_address st tx_queue " | ||
835 | "rx_queue tr tm->when retrnsmt uid timeout " | ||
836 | "inode ref pointer drops"); | ||
837 | else { | ||
838 | struct ping_iter_state *state = seq->private; | ||
839 | int len; | ||
840 | |||
841 | ping_format_sock(v, seq, state->bucket, &len); | ||
842 | seq_printf(seq, "%*s\n", 127 - len, ""); | ||
843 | } | ||
844 | return 0; | ||
845 | } | ||
846 | |||
847 | static const struct seq_operations ping_seq_ops = { | ||
848 | .show = ping_seq_show, | ||
849 | .start = ping_seq_start, | ||
850 | .next = ping_seq_next, | ||
851 | .stop = ping_seq_stop, | ||
852 | }; | ||
853 | |||
854 | static int ping_seq_open(struct inode *inode, struct file *file) | ||
855 | { | ||
856 | return seq_open_net(inode, file, &ping_seq_ops, | ||
857 | sizeof(struct ping_iter_state)); | ||
858 | } | ||
859 | |||
860 | static const struct file_operations ping_seq_fops = { | ||
861 | .open = ping_seq_open, | ||
862 | .read = seq_read, | ||
863 | .llseek = seq_lseek, | ||
864 | .release = seq_release_net, | ||
865 | }; | ||
866 | |||
867 | static int ping_proc_register(struct net *net) | ||
868 | { | ||
869 | struct proc_dir_entry *p; | ||
870 | int rc = 0; | ||
871 | |||
872 | p = proc_net_fops_create(net, "icmp", S_IRUGO, &ping_seq_fops); | ||
873 | if (!p) | ||
874 | rc = -ENOMEM; | ||
875 | return rc; | ||
876 | } | ||
877 | |||
878 | static void ping_proc_unregister(struct net *net) | ||
879 | { | ||
880 | proc_net_remove(net, "icmp"); | ||
881 | } | ||
882 | |||
883 | |||
884 | static int __net_init ping_proc_init_net(struct net *net) | ||
885 | { | ||
886 | return ping_proc_register(net); | ||
887 | } | ||
888 | |||
889 | static void __net_exit ping_proc_exit_net(struct net *net) | ||
890 | { | ||
891 | ping_proc_unregister(net); | ||
892 | } | ||
893 | |||
894 | static struct pernet_operations ping_net_ops = { | ||
895 | .init = ping_proc_init_net, | ||
896 | .exit = ping_proc_exit_net, | ||
897 | }; | ||
898 | |||
899 | int __init ping_proc_init(void) | ||
900 | { | ||
901 | return register_pernet_subsys(&ping_net_ops); | ||
902 | } | ||
903 | |||
904 | void ping_proc_exit(void) | ||
905 | { | ||
906 | unregister_pernet_subsys(&ping_net_ops); | ||
907 | } | ||
908 | |||
909 | #endif | ||
910 | |||
911 | void __init ping_init(void) | ||
912 | { | ||
913 | int i; | ||
914 | |||
915 | for (i = 0; i < PING_HTABLE_SIZE; i++) | ||
916 | INIT_HLIST_NULLS_HEAD(&ping_table.hash[i], i); | ||
917 | rwlock_init(&ping_table.lock); | ||
918 | } | ||
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 2d3c72e5bbbf..11e1780455f2 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
@@ -154,7 +154,7 @@ static __inline__ int icmp_filter(struct sock *sk, struct sk_buff *skb) | |||
154 | * RFC 1122: SHOULD pass TOS value up to the transport layer. | 154 | * RFC 1122: SHOULD pass TOS value up to the transport layer. |
155 | * -> It does. And not only TOS, but all IP header. | 155 | * -> It does. And not only TOS, but all IP header. |
156 | */ | 156 | */ |
157 | static int raw_v4_input(struct sk_buff *skb, struct iphdr *iph, int hash) | 157 | static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash) |
158 | { | 158 | { |
159 | struct sock *sk; | 159 | struct sock *sk; |
160 | struct hlist_head *head; | 160 | struct hlist_head *head; |
@@ -247,7 +247,7 @@ static void raw_err(struct sock *sk, struct sk_buff *skb, u32 info) | |||
247 | } | 247 | } |
248 | 248 | ||
249 | if (inet->recverr) { | 249 | if (inet->recverr) { |
250 | struct iphdr *iph = (struct iphdr *)skb->data; | 250 | const struct iphdr *iph = (const struct iphdr *)skb->data; |
251 | u8 *payload = skb->data + (iph->ihl << 2); | 251 | u8 *payload = skb->data + (iph->ihl << 2); |
252 | 252 | ||
253 | if (inet->hdrincl) | 253 | if (inet->hdrincl) |
@@ -265,7 +265,7 @@ void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info) | |||
265 | { | 265 | { |
266 | int hash; | 266 | int hash; |
267 | struct sock *raw_sk; | 267 | struct sock *raw_sk; |
268 | struct iphdr *iph; | 268 | const struct iphdr *iph; |
269 | struct net *net; | 269 | struct net *net; |
270 | 270 | ||
271 | hash = protocol & (RAW_HTABLE_SIZE - 1); | 271 | hash = protocol & (RAW_HTABLE_SIZE - 1); |
@@ -273,7 +273,7 @@ void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info) | |||
273 | read_lock(&raw_v4_hashinfo.lock); | 273 | read_lock(&raw_v4_hashinfo.lock); |
274 | raw_sk = sk_head(&raw_v4_hashinfo.ht[hash]); | 274 | raw_sk = sk_head(&raw_v4_hashinfo.ht[hash]); |
275 | if (raw_sk != NULL) { | 275 | if (raw_sk != NULL) { |
276 | iph = (struct iphdr *)skb->data; | 276 | iph = (const struct iphdr *)skb->data; |
277 | net = dev_net(skb->dev); | 277 | net = dev_net(skb->dev); |
278 | 278 | ||
279 | while ((raw_sk = __raw_v4_lookup(net, raw_sk, protocol, | 279 | while ((raw_sk = __raw_v4_lookup(net, raw_sk, protocol, |
@@ -281,7 +281,7 @@ void raw_icmp_error(struct sk_buff *skb, int protocol, u32 info) | |||
281 | skb->dev->ifindex)) != NULL) { | 281 | skb->dev->ifindex)) != NULL) { |
282 | raw_err(raw_sk, skb, info); | 282 | raw_err(raw_sk, skb, info); |
283 | raw_sk = sk_next(raw_sk); | 283 | raw_sk = sk_next(raw_sk); |
284 | iph = (struct iphdr *)skb->data; | 284 | iph = (const struct iphdr *)skb->data; |
285 | } | 285 | } |
286 | } | 286 | } |
287 | read_unlock(&raw_v4_hashinfo.lock); | 287 | read_unlock(&raw_v4_hashinfo.lock); |
@@ -314,9 +314,10 @@ int raw_rcv(struct sock *sk, struct sk_buff *skb) | |||
314 | return 0; | 314 | return 0; |
315 | } | 315 | } |
316 | 316 | ||
317 | static int raw_send_hdrinc(struct sock *sk, void *from, size_t length, | 317 | static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4, |
318 | struct rtable **rtp, | 318 | void *from, size_t length, |
319 | unsigned int flags) | 319 | struct rtable **rtp, |
320 | unsigned int flags) | ||
320 | { | 321 | { |
321 | struct inet_sock *inet = inet_sk(sk); | 322 | struct inet_sock *inet = inet_sk(sk); |
322 | struct net *net = sock_net(sk); | 323 | struct net *net = sock_net(sk); |
@@ -327,7 +328,7 @@ static int raw_send_hdrinc(struct sock *sk, void *from, size_t length, | |||
327 | struct rtable *rt = *rtp; | 328 | struct rtable *rt = *rtp; |
328 | 329 | ||
329 | if (length > rt->dst.dev->mtu) { | 330 | if (length > rt->dst.dev->mtu) { |
330 | ip_local_error(sk, EMSGSIZE, rt->rt_dst, inet->inet_dport, | 331 | ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport, |
331 | rt->dst.dev->mtu); | 332 | rt->dst.dev->mtu); |
332 | return -EMSGSIZE; | 333 | return -EMSGSIZE; |
333 | } | 334 | } |
@@ -372,7 +373,7 @@ static int raw_send_hdrinc(struct sock *sk, void *from, size_t length, | |||
372 | 373 | ||
373 | if (iphlen >= sizeof(*iph)) { | 374 | if (iphlen >= sizeof(*iph)) { |
374 | if (!iph->saddr) | 375 | if (!iph->saddr) |
375 | iph->saddr = rt->rt_src; | 376 | iph->saddr = fl4->saddr; |
376 | iph->check = 0; | 377 | iph->check = 0; |
377 | iph->tot_len = htons(length); | 378 | iph->tot_len = htons(length); |
378 | if (!iph->id) | 379 | if (!iph->id) |
@@ -455,11 +456,13 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
455 | struct inet_sock *inet = inet_sk(sk); | 456 | struct inet_sock *inet = inet_sk(sk); |
456 | struct ipcm_cookie ipc; | 457 | struct ipcm_cookie ipc; |
457 | struct rtable *rt = NULL; | 458 | struct rtable *rt = NULL; |
459 | struct flowi4 fl4; | ||
458 | int free = 0; | 460 | int free = 0; |
459 | __be32 daddr; | 461 | __be32 daddr; |
460 | __be32 saddr; | 462 | __be32 saddr; |
461 | u8 tos; | 463 | u8 tos; |
462 | int err; | 464 | int err; |
465 | struct ip_options_data opt_copy; | ||
463 | 466 | ||
464 | err = -EMSGSIZE; | 467 | err = -EMSGSIZE; |
465 | if (len > 0xFFFF) | 468 | if (len > 0xFFFF) |
@@ -520,8 +523,18 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
520 | saddr = ipc.addr; | 523 | saddr = ipc.addr; |
521 | ipc.addr = daddr; | 524 | ipc.addr = daddr; |
522 | 525 | ||
523 | if (!ipc.opt) | 526 | if (!ipc.opt) { |
524 | ipc.opt = inet->opt; | 527 | struct ip_options_rcu *inet_opt; |
528 | |||
529 | rcu_read_lock(); | ||
530 | inet_opt = rcu_dereference(inet->inet_opt); | ||
531 | if (inet_opt) { | ||
532 | memcpy(&opt_copy, inet_opt, | ||
533 | sizeof(*inet_opt) + inet_opt->opt.optlen); | ||
534 | ipc.opt = &opt_copy.opt; | ||
535 | } | ||
536 | rcu_read_unlock(); | ||
537 | } | ||
525 | 538 | ||
526 | if (ipc.opt) { | 539 | if (ipc.opt) { |
527 | err = -EINVAL; | 540 | err = -EINVAL; |
@@ -530,10 +543,10 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
530 | */ | 543 | */ |
531 | if (inet->hdrincl) | 544 | if (inet->hdrincl) |
532 | goto done; | 545 | goto done; |
533 | if (ipc.opt->srr) { | 546 | if (ipc.opt->opt.srr) { |
534 | if (!daddr) | 547 | if (!daddr) |
535 | goto done; | 548 | goto done; |
536 | daddr = ipc.opt->faddr; | 549 | daddr = ipc.opt->opt.faddr; |
537 | } | 550 | } |
538 | } | 551 | } |
539 | tos = RT_CONN_FLAGS(sk); | 552 | tos = RT_CONN_FLAGS(sk); |
@@ -547,31 +560,23 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
547 | saddr = inet->mc_addr; | 560 | saddr = inet->mc_addr; |
548 | } | 561 | } |
549 | 562 | ||
550 | { | 563 | flowi4_init_output(&fl4, ipc.oif, sk->sk_mark, tos, |
551 | struct flowi4 fl4 = { | 564 | RT_SCOPE_UNIVERSE, |
552 | .flowi4_oif = ipc.oif, | 565 | inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol, |
553 | .flowi4_mark = sk->sk_mark, | 566 | FLOWI_FLAG_CAN_SLEEP, daddr, saddr, 0, 0); |
554 | .daddr = daddr, | ||
555 | .saddr = saddr, | ||
556 | .flowi4_tos = tos, | ||
557 | .flowi4_proto = (inet->hdrincl ? | ||
558 | IPPROTO_RAW : | ||
559 | sk->sk_protocol), | ||
560 | .flowi4_flags = FLOWI_FLAG_CAN_SLEEP, | ||
561 | }; | ||
562 | if (!inet->hdrincl) { | ||
563 | err = raw_probe_proto_opt(&fl4, msg); | ||
564 | if (err) | ||
565 | goto done; | ||
566 | } | ||
567 | 567 | ||
568 | security_sk_classify_flow(sk, flowi4_to_flowi(&fl4)); | 568 | if (!inet->hdrincl) { |
569 | rt = ip_route_output_flow(sock_net(sk), &fl4, sk); | 569 | err = raw_probe_proto_opt(&fl4, msg); |
570 | if (IS_ERR(rt)) { | 570 | if (err) |
571 | err = PTR_ERR(rt); | ||
572 | rt = NULL; | ||
573 | goto done; | 571 | goto done; |
574 | } | 572 | } |
573 | |||
574 | security_sk_classify_flow(sk, flowi4_to_flowi(&fl4)); | ||
575 | rt = ip_route_output_flow(sock_net(sk), &fl4, sk); | ||
576 | if (IS_ERR(rt)) { | ||
577 | err = PTR_ERR(rt); | ||
578 | rt = NULL; | ||
579 | goto done; | ||
575 | } | 580 | } |
576 | 581 | ||
577 | err = -EACCES; | 582 | err = -EACCES; |
@@ -583,19 +588,20 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
583 | back_from_confirm: | 588 | back_from_confirm: |
584 | 589 | ||
585 | if (inet->hdrincl) | 590 | if (inet->hdrincl) |
586 | err = raw_send_hdrinc(sk, msg->msg_iov, len, | 591 | err = raw_send_hdrinc(sk, &fl4, msg->msg_iov, len, |
587 | &rt, msg->msg_flags); | 592 | &rt, msg->msg_flags); |
588 | 593 | ||
589 | else { | 594 | else { |
590 | if (!ipc.addr) | 595 | if (!ipc.addr) |
591 | ipc.addr = rt->rt_dst; | 596 | ipc.addr = fl4.daddr; |
592 | lock_sock(sk); | 597 | lock_sock(sk); |
593 | err = ip_append_data(sk, ip_generic_getfrag, msg->msg_iov, len, 0, | 598 | err = ip_append_data(sk, &fl4, ip_generic_getfrag, |
594 | &ipc, &rt, msg->msg_flags); | 599 | msg->msg_iov, len, 0, |
600 | &ipc, &rt, msg->msg_flags); | ||
595 | if (err) | 601 | if (err) |
596 | ip_flush_pending_frames(sk); | 602 | ip_flush_pending_frames(sk); |
597 | else if (!(msg->msg_flags & MSG_MORE)) { | 603 | else if (!(msg->msg_flags & MSG_MORE)) { |
598 | err = ip_push_pending_frames(sk); | 604 | err = ip_push_pending_frames(sk, &fl4); |
599 | if (err == -ENOBUFS && !inet->recverr) | 605 | if (err == -ENOBUFS && !inet->recverr) |
600 | err = 0; | 606 | err = 0; |
601 | } | 607 | } |
@@ -622,7 +628,7 @@ do_confirm: | |||
622 | static void raw_close(struct sock *sk, long timeout) | 628 | static void raw_close(struct sock *sk, long timeout) |
623 | { | 629 | { |
624 | /* | 630 | /* |
625 | * Raw sockets may have direct kernel refereneces. Kill them. | 631 | * Raw sockets may have direct kernel references. Kill them. |
626 | */ | 632 | */ |
627 | ip_ra_control(sk, 0, NULL); | 633 | ip_ra_control(sk, 0, NULL); |
628 | 634 | ||
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 4b0c81180804..ad141d894e4e 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -424,7 +424,7 @@ static int rt_cache_seq_show(struct seq_file *seq, void *v) | |||
424 | dst_metric(&r->dst, RTAX_WINDOW), | 424 | dst_metric(&r->dst, RTAX_WINDOW), |
425 | (int)((dst_metric(&r->dst, RTAX_RTT) >> 3) + | 425 | (int)((dst_metric(&r->dst, RTAX_RTT) >> 3) + |
426 | dst_metric(&r->dst, RTAX_RTTVAR)), | 426 | dst_metric(&r->dst, RTAX_RTTVAR)), |
427 | r->rt_tos, | 427 | r->rt_key_tos, |
428 | r->dst.hh ? atomic_read(&r->dst.hh->hh_refcnt) : -1, | 428 | r->dst.hh ? atomic_read(&r->dst.hh->hh_refcnt) : -1, |
429 | r->dst.hh ? (r->dst.hh->hh_output == | 429 | r->dst.hh ? (r->dst.hh->hh_output == |
430 | dev_queue_xmit) : 0, | 430 | dev_queue_xmit) : 0, |
@@ -724,7 +724,7 @@ static inline int compare_keys(struct rtable *rt1, struct rtable *rt2) | |||
724 | return (((__force u32)rt1->rt_key_dst ^ (__force u32)rt2->rt_key_dst) | | 724 | return (((__force u32)rt1->rt_key_dst ^ (__force u32)rt2->rt_key_dst) | |
725 | ((__force u32)rt1->rt_key_src ^ (__force u32)rt2->rt_key_src) | | 725 | ((__force u32)rt1->rt_key_src ^ (__force u32)rt2->rt_key_src) | |
726 | (rt1->rt_mark ^ rt2->rt_mark) | | 726 | (rt1->rt_mark ^ rt2->rt_mark) | |
727 | (rt1->rt_tos ^ rt2->rt_tos) | | 727 | (rt1->rt_key_tos ^ rt2->rt_key_tos) | |
728 | (rt1->rt_oif ^ rt2->rt_oif) | | 728 | (rt1->rt_oif ^ rt2->rt_oif) | |
729 | (rt1->rt_iif ^ rt2->rt_iif)) == 0; | 729 | (rt1->rt_iif ^ rt2->rt_iif)) == 0; |
730 | } | 730 | } |
@@ -821,7 +821,7 @@ static int has_noalias(const struct rtable *head, const struct rtable *rth) | |||
821 | } | 821 | } |
822 | 822 | ||
823 | /* | 823 | /* |
824 | * Pertubation of rt_genid by a small quantity [1..256] | 824 | * Perturbation of rt_genid by a small quantity [1..256] |
825 | * Using 8 bits of shuffling ensure we can call rt_cache_invalidate() | 825 | * Using 8 bits of shuffling ensure we can call rt_cache_invalidate() |
826 | * many times (2^24) without giving recent rt_genid. | 826 | * many times (2^24) without giving recent rt_genid. |
827 | * Jenkins hash is strong enough that litle changes of rt_genid are OK. | 827 | * Jenkins hash is strong enough that litle changes of rt_genid are OK. |
@@ -1191,7 +1191,7 @@ restart: | |||
1191 | #endif | 1191 | #endif |
1192 | /* | 1192 | /* |
1193 | * Since lookup is lockfree, we must make sure | 1193 | * Since lookup is lockfree, we must make sure |
1194 | * previous writes to rt are comitted to memory | 1194 | * previous writes to rt are committed to memory |
1195 | * before making rt visible to other CPUS. | 1195 | * before making rt visible to other CPUS. |
1196 | */ | 1196 | */ |
1197 | rcu_assign_pointer(rt_hash_table[hash].chain, rt); | 1197 | rcu_assign_pointer(rt_hash_table[hash].chain, rt); |
@@ -1349,7 +1349,7 @@ static struct dst_entry *ipv4_negative_advice(struct dst_entry *dst) | |||
1349 | rt_genid(dev_net(dst->dev))); | 1349 | rt_genid(dev_net(dst->dev))); |
1350 | #if RT_CACHE_DEBUG >= 1 | 1350 | #if RT_CACHE_DEBUG >= 1 |
1351 | printk(KERN_DEBUG "ipv4_negative_advice: redirect to %pI4/%02x dropped\n", | 1351 | printk(KERN_DEBUG "ipv4_negative_advice: redirect to %pI4/%02x dropped\n", |
1352 | &rt->rt_dst, rt->rt_tos); | 1352 | &rt->rt_dst, rt->rt_key_tos); |
1353 | #endif | 1353 | #endif |
1354 | rt_del(hash, rt); | 1354 | rt_del(hash, rt); |
1355 | ret = NULL; | 1355 | ret = NULL; |
@@ -1507,7 +1507,7 @@ static inline unsigned short guess_mtu(unsigned short old_mtu) | |||
1507 | return 68; | 1507 | return 68; |
1508 | } | 1508 | } |
1509 | 1509 | ||
1510 | unsigned short ip_rt_frag_needed(struct net *net, struct iphdr *iph, | 1510 | unsigned short ip_rt_frag_needed(struct net *net, const struct iphdr *iph, |
1511 | unsigned short new_mtu, | 1511 | unsigned short new_mtu, |
1512 | struct net_device *dev) | 1512 | struct net_device *dev) |
1513 | { | 1513 | { |
@@ -1699,22 +1699,26 @@ static int ip_rt_bug(struct sk_buff *skb) | |||
1699 | in IP options! | 1699 | in IP options! |
1700 | */ | 1700 | */ |
1701 | 1701 | ||
1702 | void ip_rt_get_source(u8 *addr, struct rtable *rt) | 1702 | void ip_rt_get_source(u8 *addr, struct sk_buff *skb, struct rtable *rt) |
1703 | { | 1703 | { |
1704 | __be32 src; | 1704 | __be32 src; |
1705 | struct fib_result res; | ||
1706 | 1705 | ||
1707 | if (rt_is_output_route(rt)) | 1706 | if (rt_is_output_route(rt)) |
1708 | src = rt->rt_src; | 1707 | src = rt->rt_src; |
1709 | else { | 1708 | else { |
1710 | struct flowi4 fl4 = { | 1709 | struct fib_result res; |
1711 | .daddr = rt->rt_key_dst, | 1710 | struct flowi4 fl4; |
1712 | .saddr = rt->rt_key_src, | 1711 | struct iphdr *iph; |
1713 | .flowi4_tos = rt->rt_tos, | 1712 | |
1714 | .flowi4_oif = rt->rt_oif, | 1713 | iph = ip_hdr(skb); |
1715 | .flowi4_iif = rt->rt_iif, | 1714 | |
1716 | .flowi4_mark = rt->rt_mark, | 1715 | memset(&fl4, 0, sizeof(fl4)); |
1717 | }; | 1716 | fl4.daddr = iph->daddr; |
1717 | fl4.saddr = iph->saddr; | ||
1718 | fl4.flowi4_tos = iph->tos; | ||
1719 | fl4.flowi4_oif = rt->dst.dev->ifindex; | ||
1720 | fl4.flowi4_iif = skb->dev->ifindex; | ||
1721 | fl4.flowi4_mark = skb->mark; | ||
1718 | 1722 | ||
1719 | rcu_read_lock(); | 1723 | rcu_read_lock(); |
1720 | if (fib_lookup(dev_net(rt->dst.dev), &fl4, &res) == 0) | 1724 | if (fib_lookup(dev_net(rt->dst.dev), &fl4, &res) == 0) |
@@ -1767,7 +1771,7 @@ static unsigned int ipv4_default_mtu(const struct dst_entry *dst) | |||
1767 | return mtu; | 1771 | return mtu; |
1768 | } | 1772 | } |
1769 | 1773 | ||
1770 | static void rt_init_metrics(struct rtable *rt, const struct flowi4 *oldflp4, | 1774 | static void rt_init_metrics(struct rtable *rt, const struct flowi4 *fl4, |
1771 | struct fib_info *fi) | 1775 | struct fib_info *fi) |
1772 | { | 1776 | { |
1773 | struct inet_peer *peer; | 1777 | struct inet_peer *peer; |
@@ -1776,7 +1780,7 @@ static void rt_init_metrics(struct rtable *rt, const struct flowi4 *oldflp4, | |||
1776 | /* If a peer entry exists for this destination, we must hook | 1780 | /* If a peer entry exists for this destination, we must hook |
1777 | * it up in order to get at cached metrics. | 1781 | * it up in order to get at cached metrics. |
1778 | */ | 1782 | */ |
1779 | if (oldflp4 && (oldflp4->flowi4_flags & FLOWI_FLAG_PRECOW_METRICS)) | 1783 | if (fl4 && (fl4->flowi4_flags & FLOWI_FLAG_PRECOW_METRICS)) |
1780 | create = 1; | 1784 | create = 1; |
1781 | 1785 | ||
1782 | rt->peer = peer = inet_getpeer_v4(rt->rt_dst, create); | 1786 | rt->peer = peer = inet_getpeer_v4(rt->rt_dst, create); |
@@ -1803,7 +1807,7 @@ static void rt_init_metrics(struct rtable *rt, const struct flowi4 *oldflp4, | |||
1803 | } | 1807 | } |
1804 | } | 1808 | } |
1805 | 1809 | ||
1806 | static void rt_set_nexthop(struct rtable *rt, const struct flowi4 *oldflp4, | 1810 | static void rt_set_nexthop(struct rtable *rt, const struct flowi4 *fl4, |
1807 | const struct fib_result *res, | 1811 | const struct fib_result *res, |
1808 | struct fib_info *fi, u16 type, u32 itag) | 1812 | struct fib_info *fi, u16 type, u32 itag) |
1809 | { | 1813 | { |
@@ -1813,7 +1817,7 @@ static void rt_set_nexthop(struct rtable *rt, const struct flowi4 *oldflp4, | |||
1813 | if (FIB_RES_GW(*res) && | 1817 | if (FIB_RES_GW(*res) && |
1814 | FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) | 1818 | FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) |
1815 | rt->rt_gateway = FIB_RES_GW(*res); | 1819 | rt->rt_gateway = FIB_RES_GW(*res); |
1816 | rt_init_metrics(rt, oldflp4, fi); | 1820 | rt_init_metrics(rt, fl4, fi); |
1817 | #ifdef CONFIG_IP_ROUTE_CLASSID | 1821 | #ifdef CONFIG_IP_ROUTE_CLASSID |
1818 | dst->tclassid = FIB_RES_NH(*res).nh_tclassid; | 1822 | dst->tclassid = FIB_RES_NH(*res).nh_tclassid; |
1819 | #endif | 1823 | #endif |
@@ -1830,20 +1834,15 @@ static void rt_set_nexthop(struct rtable *rt, const struct flowi4 *oldflp4, | |||
1830 | #endif | 1834 | #endif |
1831 | set_class_tag(rt, itag); | 1835 | set_class_tag(rt, itag); |
1832 | #endif | 1836 | #endif |
1833 | rt->rt_type = type; | ||
1834 | } | 1837 | } |
1835 | 1838 | ||
1836 | static struct rtable *rt_dst_alloc(bool nopolicy, bool noxfrm) | 1839 | static struct rtable *rt_dst_alloc(struct net_device *dev, |
1840 | bool nopolicy, bool noxfrm) | ||
1837 | { | 1841 | { |
1838 | struct rtable *rt = dst_alloc(&ipv4_dst_ops, 1); | 1842 | return dst_alloc(&ipv4_dst_ops, dev, 1, -1, |
1839 | if (rt) { | 1843 | DST_HOST | |
1840 | rt->dst.obsolete = -1; | 1844 | (nopolicy ? DST_NOPOLICY : 0) | |
1841 | 1845 | (noxfrm ? DST_NOXFRM : 0)); | |
1842 | rt->dst.flags = DST_HOST | | ||
1843 | (nopolicy ? DST_NOPOLICY : 0) | | ||
1844 | (noxfrm ? DST_NOXFRM : 0); | ||
1845 | } | ||
1846 | return rt; | ||
1847 | } | 1846 | } |
1848 | 1847 | ||
1849 | /* called in rcu_read_lock() section */ | 1848 | /* called in rcu_read_lock() section */ |
@@ -1871,35 +1870,38 @@ static int ip_route_input_mc(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
1871 | goto e_inval; | 1870 | goto e_inval; |
1872 | spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK); | 1871 | spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK); |
1873 | } else { | 1872 | } else { |
1874 | err = fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst, | 1873 | err = fib_validate_source(skb, saddr, 0, tos, 0, dev, &spec_dst, |
1875 | &itag, 0); | 1874 | &itag); |
1876 | if (err < 0) | 1875 | if (err < 0) |
1877 | goto e_err; | 1876 | goto e_err; |
1878 | } | 1877 | } |
1879 | rth = rt_dst_alloc(IN_DEV_CONF_GET(in_dev, NOPOLICY), false); | 1878 | rth = rt_dst_alloc(init_net.loopback_dev, |
1879 | IN_DEV_CONF_GET(in_dev, NOPOLICY), false); | ||
1880 | if (!rth) | 1880 | if (!rth) |
1881 | goto e_nobufs; | 1881 | goto e_nobufs; |
1882 | 1882 | ||
1883 | #ifdef CONFIG_IP_ROUTE_CLASSID | ||
1884 | rth->dst.tclassid = itag; | ||
1885 | #endif | ||
1883 | rth->dst.output = ip_rt_bug; | 1886 | rth->dst.output = ip_rt_bug; |
1884 | 1887 | ||
1885 | rth->rt_key_dst = daddr; | 1888 | rth->rt_key_dst = daddr; |
1886 | rth->rt_dst = daddr; | ||
1887 | rth->rt_tos = tos; | ||
1888 | rth->rt_mark = skb->mark; | ||
1889 | rth->rt_key_src = saddr; | 1889 | rth->rt_key_src = saddr; |
1890 | rth->rt_genid = rt_genid(dev_net(dev)); | ||
1891 | rth->rt_flags = RTCF_MULTICAST; | ||
1892 | rth->rt_type = RTN_MULTICAST; | ||
1893 | rth->rt_key_tos = tos; | ||
1894 | rth->rt_dst = daddr; | ||
1890 | rth->rt_src = saddr; | 1895 | rth->rt_src = saddr; |
1891 | #ifdef CONFIG_IP_ROUTE_CLASSID | 1896 | rth->rt_route_iif = dev->ifindex; |
1892 | rth->dst.tclassid = itag; | ||
1893 | #endif | ||
1894 | rth->rt_iif = dev->ifindex; | 1897 | rth->rt_iif = dev->ifindex; |
1895 | rth->dst.dev = init_net.loopback_dev; | ||
1896 | dev_hold(rth->dst.dev); | ||
1897 | rth->rt_oif = 0; | 1898 | rth->rt_oif = 0; |
1899 | rth->rt_mark = skb->mark; | ||
1898 | rth->rt_gateway = daddr; | 1900 | rth->rt_gateway = daddr; |
1899 | rth->rt_spec_dst= spec_dst; | 1901 | rth->rt_spec_dst= spec_dst; |
1900 | rth->rt_genid = rt_genid(dev_net(dev)); | 1902 | rth->rt_peer_genid = 0; |
1901 | rth->rt_flags = RTCF_MULTICAST; | 1903 | rth->peer = NULL; |
1902 | rth->rt_type = RTN_MULTICAST; | 1904 | rth->fi = NULL; |
1903 | if (our) { | 1905 | if (our) { |
1904 | rth->dst.input= ip_local_deliver; | 1906 | rth->dst.input= ip_local_deliver; |
1905 | rth->rt_flags |= RTCF_LOCAL; | 1907 | rth->rt_flags |= RTCF_LOCAL; |
@@ -1980,8 +1982,8 @@ static int __mkroute_input(struct sk_buff *skb, | |||
1980 | } | 1982 | } |
1981 | 1983 | ||
1982 | 1984 | ||
1983 | err = fib_validate_source(saddr, daddr, tos, FIB_RES_OIF(*res), | 1985 | err = fib_validate_source(skb, saddr, daddr, tos, FIB_RES_OIF(*res), |
1984 | in_dev->dev, &spec_dst, &itag, skb->mark); | 1986 | in_dev->dev, &spec_dst, &itag); |
1985 | if (err < 0) { | 1987 | if (err < 0) { |
1986 | ip_handle_martian_source(in_dev->dev, in_dev, skb, daddr, | 1988 | ip_handle_martian_source(in_dev->dev, in_dev, skb, daddr, |
1987 | saddr); | 1989 | saddr); |
@@ -2012,7 +2014,8 @@ static int __mkroute_input(struct sk_buff *skb, | |||
2012 | } | 2014 | } |
2013 | } | 2015 | } |
2014 | 2016 | ||
2015 | rth = rt_dst_alloc(IN_DEV_CONF_GET(in_dev, NOPOLICY), | 2017 | rth = rt_dst_alloc(out_dev->dev, |
2018 | IN_DEV_CONF_GET(in_dev, NOPOLICY), | ||
2016 | IN_DEV_CONF_GET(out_dev, NOXFRM)); | 2019 | IN_DEV_CONF_GET(out_dev, NOXFRM)); |
2017 | if (!rth) { | 2020 | if (!rth) { |
2018 | err = -ENOBUFS; | 2021 | err = -ENOBUFS; |
@@ -2020,26 +2023,28 @@ static int __mkroute_input(struct sk_buff *skb, | |||
2020 | } | 2023 | } |
2021 | 2024 | ||
2022 | rth->rt_key_dst = daddr; | 2025 | rth->rt_key_dst = daddr; |
2023 | rth->rt_dst = daddr; | ||
2024 | rth->rt_tos = tos; | ||
2025 | rth->rt_mark = skb->mark; | ||
2026 | rth->rt_key_src = saddr; | 2026 | rth->rt_key_src = saddr; |
2027 | rth->rt_genid = rt_genid(dev_net(rth->dst.dev)); | ||
2028 | rth->rt_flags = flags; | ||
2029 | rth->rt_type = res->type; | ||
2030 | rth->rt_key_tos = tos; | ||
2031 | rth->rt_dst = daddr; | ||
2027 | rth->rt_src = saddr; | 2032 | rth->rt_src = saddr; |
2028 | rth->rt_gateway = daddr; | 2033 | rth->rt_route_iif = in_dev->dev->ifindex; |
2029 | rth->rt_iif = in_dev->dev->ifindex; | 2034 | rth->rt_iif = in_dev->dev->ifindex; |
2030 | rth->dst.dev = (out_dev)->dev; | ||
2031 | dev_hold(rth->dst.dev); | ||
2032 | rth->rt_oif = 0; | 2035 | rth->rt_oif = 0; |
2036 | rth->rt_mark = skb->mark; | ||
2037 | rth->rt_gateway = daddr; | ||
2033 | rth->rt_spec_dst= spec_dst; | 2038 | rth->rt_spec_dst= spec_dst; |
2039 | rth->rt_peer_genid = 0; | ||
2040 | rth->peer = NULL; | ||
2041 | rth->fi = NULL; | ||
2034 | 2042 | ||
2035 | rth->dst.input = ip_forward; | 2043 | rth->dst.input = ip_forward; |
2036 | rth->dst.output = ip_output; | 2044 | rth->dst.output = ip_output; |
2037 | rth->rt_genid = rt_genid(dev_net(rth->dst.dev)); | ||
2038 | 2045 | ||
2039 | rt_set_nexthop(rth, NULL, res, res->fi, res->type, itag); | 2046 | rt_set_nexthop(rth, NULL, res, res->fi, res->type, itag); |
2040 | 2047 | ||
2041 | rth->rt_flags = flags; | ||
2042 | |||
2043 | *result = rth; | 2048 | *result = rth; |
2044 | err = 0; | 2049 | err = 0; |
2045 | cleanup: | 2050 | cleanup: |
@@ -2148,9 +2153,9 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
2148 | goto brd_input; | 2153 | goto brd_input; |
2149 | 2154 | ||
2150 | if (res.type == RTN_LOCAL) { | 2155 | if (res.type == RTN_LOCAL) { |
2151 | err = fib_validate_source(saddr, daddr, tos, | 2156 | err = fib_validate_source(skb, saddr, daddr, tos, |
2152 | net->loopback_dev->ifindex, | 2157 | net->loopback_dev->ifindex, |
2153 | dev, &spec_dst, &itag, skb->mark); | 2158 | dev, &spec_dst, &itag); |
2154 | if (err < 0) | 2159 | if (err < 0) |
2155 | goto martian_source_keep_err; | 2160 | goto martian_source_keep_err; |
2156 | if (err) | 2161 | if (err) |
@@ -2174,8 +2179,8 @@ brd_input: | |||
2174 | if (ipv4_is_zeronet(saddr)) | 2179 | if (ipv4_is_zeronet(saddr)) |
2175 | spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK); | 2180 | spec_dst = inet_select_addr(dev, 0, RT_SCOPE_LINK); |
2176 | else { | 2181 | else { |
2177 | err = fib_validate_source(saddr, 0, tos, 0, dev, &spec_dst, | 2182 | err = fib_validate_source(skb, saddr, 0, tos, 0, dev, &spec_dst, |
2178 | &itag, skb->mark); | 2183 | &itag); |
2179 | if (err < 0) | 2184 | if (err < 0) |
2180 | goto martian_source_keep_err; | 2185 | goto martian_source_keep_err; |
2181 | if (err) | 2186 | if (err) |
@@ -2186,35 +2191,42 @@ brd_input: | |||
2186 | RT_CACHE_STAT_INC(in_brd); | 2191 | RT_CACHE_STAT_INC(in_brd); |
2187 | 2192 | ||
2188 | local_input: | 2193 | local_input: |
2189 | rth = rt_dst_alloc(IN_DEV_CONF_GET(in_dev, NOPOLICY), false); | 2194 | rth = rt_dst_alloc(net->loopback_dev, |
2195 | IN_DEV_CONF_GET(in_dev, NOPOLICY), false); | ||
2190 | if (!rth) | 2196 | if (!rth) |
2191 | goto e_nobufs; | 2197 | goto e_nobufs; |
2192 | 2198 | ||
2199 | rth->dst.input= ip_local_deliver; | ||
2193 | rth->dst.output= ip_rt_bug; | 2200 | rth->dst.output= ip_rt_bug; |
2194 | rth->rt_genid = rt_genid(net); | 2201 | #ifdef CONFIG_IP_ROUTE_CLASSID |
2202 | rth->dst.tclassid = itag; | ||
2203 | #endif | ||
2195 | 2204 | ||
2196 | rth->rt_key_dst = daddr; | 2205 | rth->rt_key_dst = daddr; |
2197 | rth->rt_dst = daddr; | ||
2198 | rth->rt_tos = tos; | ||
2199 | rth->rt_mark = skb->mark; | ||
2200 | rth->rt_key_src = saddr; | 2206 | rth->rt_key_src = saddr; |
2207 | rth->rt_genid = rt_genid(net); | ||
2208 | rth->rt_flags = flags|RTCF_LOCAL; | ||
2209 | rth->rt_type = res.type; | ||
2210 | rth->rt_key_tos = tos; | ||
2211 | rth->rt_dst = daddr; | ||
2201 | rth->rt_src = saddr; | 2212 | rth->rt_src = saddr; |
2202 | #ifdef CONFIG_IP_ROUTE_CLASSID | 2213 | #ifdef CONFIG_IP_ROUTE_CLASSID |
2203 | rth->dst.tclassid = itag; | 2214 | rth->dst.tclassid = itag; |
2204 | #endif | 2215 | #endif |
2216 | rth->rt_route_iif = dev->ifindex; | ||
2205 | rth->rt_iif = dev->ifindex; | 2217 | rth->rt_iif = dev->ifindex; |
2206 | rth->dst.dev = net->loopback_dev; | 2218 | rth->rt_oif = 0; |
2207 | dev_hold(rth->dst.dev); | 2219 | rth->rt_mark = skb->mark; |
2208 | rth->rt_gateway = daddr; | 2220 | rth->rt_gateway = daddr; |
2209 | rth->rt_spec_dst= spec_dst; | 2221 | rth->rt_spec_dst= spec_dst; |
2210 | rth->dst.input= ip_local_deliver; | 2222 | rth->rt_peer_genid = 0; |
2211 | rth->rt_flags = flags|RTCF_LOCAL; | 2223 | rth->peer = NULL; |
2224 | rth->fi = NULL; | ||
2212 | if (res.type == RTN_UNREACHABLE) { | 2225 | if (res.type == RTN_UNREACHABLE) { |
2213 | rth->dst.input= ip_error; | 2226 | rth->dst.input= ip_error; |
2214 | rth->dst.error= -err; | 2227 | rth->dst.error= -err; |
2215 | rth->rt_flags &= ~RTCF_LOCAL; | 2228 | rth->rt_flags &= ~RTCF_LOCAL; |
2216 | } | 2229 | } |
2217 | rth->rt_type = res.type; | ||
2218 | hash = rt_hash(daddr, saddr, fl4.flowi4_iif, rt_genid(net)); | 2230 | hash = rt_hash(daddr, saddr, fl4.flowi4_iif, rt_genid(net)); |
2219 | rth = rt_intern_hash(hash, rth, skb, fl4.flowi4_iif); | 2231 | rth = rt_intern_hash(hash, rth, skb, fl4.flowi4_iif); |
2220 | err = 0; | 2232 | err = 0; |
@@ -2285,7 +2297,7 @@ int ip_route_input_common(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
2285 | ((__force u32)rth->rt_key_src ^ (__force u32)saddr) | | 2297 | ((__force u32)rth->rt_key_src ^ (__force u32)saddr) | |
2286 | (rth->rt_iif ^ iif) | | 2298 | (rth->rt_iif ^ iif) | |
2287 | rth->rt_oif | | 2299 | rth->rt_oif | |
2288 | (rth->rt_tos ^ tos)) == 0 && | 2300 | (rth->rt_key_tos ^ tos)) == 0 && |
2289 | rth->rt_mark == skb->mark && | 2301 | rth->rt_mark == skb->mark && |
2290 | net_eq(dev_net(rth->dst.dev), net) && | 2302 | net_eq(dev_net(rth->dst.dev), net) && |
2291 | !rt_is_expired(rth)) { | 2303 | !rt_is_expired(rth)) { |
@@ -2346,12 +2358,12 @@ EXPORT_SYMBOL(ip_route_input_common); | |||
2346 | /* called with rcu_read_lock() */ | 2358 | /* called with rcu_read_lock() */ |
2347 | static struct rtable *__mkroute_output(const struct fib_result *res, | 2359 | static struct rtable *__mkroute_output(const struct fib_result *res, |
2348 | const struct flowi4 *fl4, | 2360 | const struct flowi4 *fl4, |
2349 | const struct flowi4 *oldflp4, | 2361 | __be32 orig_daddr, __be32 orig_saddr, |
2350 | struct net_device *dev_out, | 2362 | int orig_oif, struct net_device *dev_out, |
2351 | unsigned int flags) | 2363 | unsigned int flags) |
2352 | { | 2364 | { |
2353 | struct fib_info *fi = res->fi; | 2365 | struct fib_info *fi = res->fi; |
2354 | u32 tos = RT_FL_TOS(oldflp4); | 2366 | u32 tos = RT_FL_TOS(fl4); |
2355 | struct in_device *in_dev; | 2367 | struct in_device *in_dev; |
2356 | u16 type = res->type; | 2368 | u16 type = res->type; |
2357 | struct rtable *rth; | 2369 | struct rtable *rth; |
@@ -2378,8 +2390,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res, | |||
2378 | fi = NULL; | 2390 | fi = NULL; |
2379 | } else if (type == RTN_MULTICAST) { | 2391 | } else if (type == RTN_MULTICAST) { |
2380 | flags |= RTCF_MULTICAST | RTCF_LOCAL; | 2392 | flags |= RTCF_MULTICAST | RTCF_LOCAL; |
2381 | if (!ip_check_mc_rcu(in_dev, oldflp4->daddr, oldflp4->saddr, | 2393 | if (!ip_check_mc_rcu(in_dev, fl4->daddr, fl4->saddr, |
2382 | oldflp4->flowi4_proto)) | 2394 | fl4->flowi4_proto)) |
2383 | flags &= ~RTCF_LOCAL; | 2395 | flags &= ~RTCF_LOCAL; |
2384 | /* If multicast route do not exist use | 2396 | /* If multicast route do not exist use |
2385 | * default one, but do not gateway in this case. | 2397 | * default one, but do not gateway in this case. |
@@ -2389,28 +2401,31 @@ static struct rtable *__mkroute_output(const struct fib_result *res, | |||
2389 | fi = NULL; | 2401 | fi = NULL; |
2390 | } | 2402 | } |
2391 | 2403 | ||
2392 | rth = rt_dst_alloc(IN_DEV_CONF_GET(in_dev, NOPOLICY), | 2404 | rth = rt_dst_alloc(dev_out, |
2405 | IN_DEV_CONF_GET(in_dev, NOPOLICY), | ||
2393 | IN_DEV_CONF_GET(in_dev, NOXFRM)); | 2406 | IN_DEV_CONF_GET(in_dev, NOXFRM)); |
2394 | if (!rth) | 2407 | if (!rth) |
2395 | return ERR_PTR(-ENOBUFS); | 2408 | return ERR_PTR(-ENOBUFS); |
2396 | 2409 | ||
2397 | rth->rt_key_dst = oldflp4->daddr; | 2410 | rth->dst.output = ip_output; |
2398 | rth->rt_tos = tos; | 2411 | |
2399 | rth->rt_key_src = oldflp4->saddr; | 2412 | rth->rt_key_dst = orig_daddr; |
2400 | rth->rt_oif = oldflp4->flowi4_oif; | 2413 | rth->rt_key_src = orig_saddr; |
2401 | rth->rt_mark = oldflp4->flowi4_mark; | 2414 | rth->rt_genid = rt_genid(dev_net(dev_out)); |
2415 | rth->rt_flags = flags; | ||
2416 | rth->rt_type = type; | ||
2417 | rth->rt_key_tos = tos; | ||
2402 | rth->rt_dst = fl4->daddr; | 2418 | rth->rt_dst = fl4->daddr; |
2403 | rth->rt_src = fl4->saddr; | 2419 | rth->rt_src = fl4->saddr; |
2404 | rth->rt_iif = 0; | 2420 | rth->rt_route_iif = 0; |
2405 | /* get references to the devices that are to be hold by the routing | 2421 | rth->rt_iif = orig_oif ? : dev_out->ifindex; |
2406 | cache entry */ | 2422 | rth->rt_oif = orig_oif; |
2407 | rth->dst.dev = dev_out; | 2423 | rth->rt_mark = fl4->flowi4_mark; |
2408 | dev_hold(dev_out); | ||
2409 | rth->rt_gateway = fl4->daddr; | 2424 | rth->rt_gateway = fl4->daddr; |
2410 | rth->rt_spec_dst= fl4->saddr; | 2425 | rth->rt_spec_dst= fl4->saddr; |
2411 | 2426 | rth->rt_peer_genid = 0; | |
2412 | rth->dst.output=ip_output; | 2427 | rth->peer = NULL; |
2413 | rth->rt_genid = rt_genid(dev_net(dev_out)); | 2428 | rth->fi = NULL; |
2414 | 2429 | ||
2415 | RT_CACHE_STAT_INC(out_slow_tot); | 2430 | RT_CACHE_STAT_INC(out_slow_tot); |
2416 | 2431 | ||
@@ -2428,7 +2443,7 @@ static struct rtable *__mkroute_output(const struct fib_result *res, | |||
2428 | #ifdef CONFIG_IP_MROUTE | 2443 | #ifdef CONFIG_IP_MROUTE |
2429 | if (type == RTN_MULTICAST) { | 2444 | if (type == RTN_MULTICAST) { |
2430 | if (IN_DEV_MFORWARD(in_dev) && | 2445 | if (IN_DEV_MFORWARD(in_dev) && |
2431 | !ipv4_is_local_multicast(oldflp4->daddr)) { | 2446 | !ipv4_is_local_multicast(fl4->daddr)) { |
2432 | rth->dst.input = ip_mr_input; | 2447 | rth->dst.input = ip_mr_input; |
2433 | rth->dst.output = ip_mc_output; | 2448 | rth->dst.output = ip_mc_output; |
2434 | } | 2449 | } |
@@ -2436,9 +2451,8 @@ static struct rtable *__mkroute_output(const struct fib_result *res, | |||
2436 | #endif | 2451 | #endif |
2437 | } | 2452 | } |
2438 | 2453 | ||
2439 | rt_set_nexthop(rth, oldflp4, res, fi, type, 0); | 2454 | rt_set_nexthop(rth, fl4, res, fi, type, 0); |
2440 | 2455 | ||
2441 | rth->rt_flags = flags; | ||
2442 | return rth; | 2456 | return rth; |
2443 | } | 2457 | } |
2444 | 2458 | ||
@@ -2447,36 +2461,37 @@ static struct rtable *__mkroute_output(const struct fib_result *res, | |||
2447 | * called with rcu_read_lock(); | 2461 | * called with rcu_read_lock(); |
2448 | */ | 2462 | */ |
2449 | 2463 | ||
2450 | static struct rtable *ip_route_output_slow(struct net *net, | 2464 | static struct rtable *ip_route_output_slow(struct net *net, struct flowi4 *fl4) |
2451 | const struct flowi4 *oldflp4) | ||
2452 | { | 2465 | { |
2453 | u32 tos = RT_FL_TOS(oldflp4); | ||
2454 | struct flowi4 fl4; | ||
2455 | struct fib_result res; | ||
2456 | unsigned int flags = 0; | ||
2457 | struct net_device *dev_out = NULL; | 2466 | struct net_device *dev_out = NULL; |
2467 | u32 tos = RT_FL_TOS(fl4); | ||
2468 | unsigned int flags = 0; | ||
2469 | struct fib_result res; | ||
2458 | struct rtable *rth; | 2470 | struct rtable *rth; |
2471 | __be32 orig_daddr; | ||
2472 | __be32 orig_saddr; | ||
2473 | int orig_oif; | ||
2459 | 2474 | ||
2460 | res.fi = NULL; | 2475 | res.fi = NULL; |
2461 | #ifdef CONFIG_IP_MULTIPLE_TABLES | 2476 | #ifdef CONFIG_IP_MULTIPLE_TABLES |
2462 | res.r = NULL; | 2477 | res.r = NULL; |
2463 | #endif | 2478 | #endif |
2464 | 2479 | ||
2465 | fl4.flowi4_oif = oldflp4->flowi4_oif; | 2480 | orig_daddr = fl4->daddr; |
2466 | fl4.flowi4_iif = net->loopback_dev->ifindex; | 2481 | orig_saddr = fl4->saddr; |
2467 | fl4.flowi4_mark = oldflp4->flowi4_mark; | 2482 | orig_oif = fl4->flowi4_oif; |
2468 | fl4.daddr = oldflp4->daddr; | 2483 | |
2469 | fl4.saddr = oldflp4->saddr; | 2484 | fl4->flowi4_iif = net->loopback_dev->ifindex; |
2470 | fl4.flowi4_tos = tos & IPTOS_RT_MASK; | 2485 | fl4->flowi4_tos = tos & IPTOS_RT_MASK; |
2471 | fl4.flowi4_scope = ((tos & RTO_ONLINK) ? | 2486 | fl4->flowi4_scope = ((tos & RTO_ONLINK) ? |
2472 | RT_SCOPE_LINK : RT_SCOPE_UNIVERSE); | 2487 | RT_SCOPE_LINK : RT_SCOPE_UNIVERSE); |
2473 | 2488 | ||
2474 | rcu_read_lock(); | 2489 | rcu_read_lock(); |
2475 | if (oldflp4->saddr) { | 2490 | if (fl4->saddr) { |
2476 | rth = ERR_PTR(-EINVAL); | 2491 | rth = ERR_PTR(-EINVAL); |
2477 | if (ipv4_is_multicast(oldflp4->saddr) || | 2492 | if (ipv4_is_multicast(fl4->saddr) || |
2478 | ipv4_is_lbcast(oldflp4->saddr) || | 2493 | ipv4_is_lbcast(fl4->saddr) || |
2479 | ipv4_is_zeronet(oldflp4->saddr)) | 2494 | ipv4_is_zeronet(fl4->saddr)) |
2480 | goto out; | 2495 | goto out; |
2481 | 2496 | ||
2482 | /* I removed check for oif == dev_out->oif here. | 2497 | /* I removed check for oif == dev_out->oif here. |
@@ -2487,11 +2502,11 @@ static struct rtable *ip_route_output_slow(struct net *net, | |||
2487 | of another iface. --ANK | 2502 | of another iface. --ANK |
2488 | */ | 2503 | */ |
2489 | 2504 | ||
2490 | if (oldflp4->flowi4_oif == 0 && | 2505 | if (fl4->flowi4_oif == 0 && |
2491 | (ipv4_is_multicast(oldflp4->daddr) || | 2506 | (ipv4_is_multicast(fl4->daddr) || |
2492 | ipv4_is_lbcast(oldflp4->daddr))) { | 2507 | ipv4_is_lbcast(fl4->daddr))) { |
2493 | /* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */ | 2508 | /* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */ |
2494 | dev_out = __ip_dev_find(net, oldflp4->saddr, false); | 2509 | dev_out = __ip_dev_find(net, fl4->saddr, false); |
2495 | if (dev_out == NULL) | 2510 | if (dev_out == NULL) |
2496 | goto out; | 2511 | goto out; |
2497 | 2512 | ||
@@ -2510,20 +2525,20 @@ static struct rtable *ip_route_output_slow(struct net *net, | |||
2510 | Luckily, this hack is good workaround. | 2525 | Luckily, this hack is good workaround. |
2511 | */ | 2526 | */ |
2512 | 2527 | ||
2513 | fl4.flowi4_oif = dev_out->ifindex; | 2528 | fl4->flowi4_oif = dev_out->ifindex; |
2514 | goto make_route; | 2529 | goto make_route; |
2515 | } | 2530 | } |
2516 | 2531 | ||
2517 | if (!(oldflp4->flowi4_flags & FLOWI_FLAG_ANYSRC)) { | 2532 | if (!(fl4->flowi4_flags & FLOWI_FLAG_ANYSRC)) { |
2518 | /* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */ | 2533 | /* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */ |
2519 | if (!__ip_dev_find(net, oldflp4->saddr, false)) | 2534 | if (!__ip_dev_find(net, fl4->saddr, false)) |
2520 | goto out; | 2535 | goto out; |
2521 | } | 2536 | } |
2522 | } | 2537 | } |
2523 | 2538 | ||
2524 | 2539 | ||
2525 | if (oldflp4->flowi4_oif) { | 2540 | if (fl4->flowi4_oif) { |
2526 | dev_out = dev_get_by_index_rcu(net, oldflp4->flowi4_oif); | 2541 | dev_out = dev_get_by_index_rcu(net, fl4->flowi4_oif); |
2527 | rth = ERR_PTR(-ENODEV); | 2542 | rth = ERR_PTR(-ENODEV); |
2528 | if (dev_out == NULL) | 2543 | if (dev_out == NULL) |
2529 | goto out; | 2544 | goto out; |
@@ -2533,37 +2548,37 @@ static struct rtable *ip_route_output_slow(struct net *net, | |||
2533 | rth = ERR_PTR(-ENETUNREACH); | 2548 | rth = ERR_PTR(-ENETUNREACH); |
2534 | goto out; | 2549 | goto out; |
2535 | } | 2550 | } |
2536 | if (ipv4_is_local_multicast(oldflp4->daddr) || | 2551 | if (ipv4_is_local_multicast(fl4->daddr) || |
2537 | ipv4_is_lbcast(oldflp4->daddr)) { | 2552 | ipv4_is_lbcast(fl4->daddr)) { |
2538 | if (!fl4.saddr) | 2553 | if (!fl4->saddr) |
2539 | fl4.saddr = inet_select_addr(dev_out, 0, | 2554 | fl4->saddr = inet_select_addr(dev_out, 0, |
2540 | RT_SCOPE_LINK); | 2555 | RT_SCOPE_LINK); |
2541 | goto make_route; | 2556 | goto make_route; |
2542 | } | 2557 | } |
2543 | if (!fl4.saddr) { | 2558 | if (fl4->saddr) { |
2544 | if (ipv4_is_multicast(oldflp4->daddr)) | 2559 | if (ipv4_is_multicast(fl4->daddr)) |
2545 | fl4.saddr = inet_select_addr(dev_out, 0, | 2560 | fl4->saddr = inet_select_addr(dev_out, 0, |
2546 | fl4.flowi4_scope); | 2561 | fl4->flowi4_scope); |
2547 | else if (!oldflp4->daddr) | 2562 | else if (!fl4->daddr) |
2548 | fl4.saddr = inet_select_addr(dev_out, 0, | 2563 | fl4->saddr = inet_select_addr(dev_out, 0, |
2549 | RT_SCOPE_HOST); | 2564 | RT_SCOPE_HOST); |
2550 | } | 2565 | } |
2551 | } | 2566 | } |
2552 | 2567 | ||
2553 | if (!fl4.daddr) { | 2568 | if (!fl4->daddr) { |
2554 | fl4.daddr = fl4.saddr; | 2569 | fl4->daddr = fl4->saddr; |
2555 | if (!fl4.daddr) | 2570 | if (!fl4->daddr) |
2556 | fl4.daddr = fl4.saddr = htonl(INADDR_LOOPBACK); | 2571 | fl4->daddr = fl4->saddr = htonl(INADDR_LOOPBACK); |
2557 | dev_out = net->loopback_dev; | 2572 | dev_out = net->loopback_dev; |
2558 | fl4.flowi4_oif = net->loopback_dev->ifindex; | 2573 | fl4->flowi4_oif = net->loopback_dev->ifindex; |
2559 | res.type = RTN_LOCAL; | 2574 | res.type = RTN_LOCAL; |
2560 | flags |= RTCF_LOCAL; | 2575 | flags |= RTCF_LOCAL; |
2561 | goto make_route; | 2576 | goto make_route; |
2562 | } | 2577 | } |
2563 | 2578 | ||
2564 | if (fib_lookup(net, &fl4, &res)) { | 2579 | if (fib_lookup(net, fl4, &res)) { |
2565 | res.fi = NULL; | 2580 | res.fi = NULL; |
2566 | if (oldflp4->flowi4_oif) { | 2581 | if (fl4->flowi4_oif) { |
2567 | /* Apparently, routing tables are wrong. Assume, | 2582 | /* Apparently, routing tables are wrong. Assume, |
2568 | that the destination is on link. | 2583 | that the destination is on link. |
2569 | 2584 | ||
@@ -2582,9 +2597,9 @@ static struct rtable *ip_route_output_slow(struct net *net, | |||
2582 | likely IPv6, but we do not. | 2597 | likely IPv6, but we do not. |
2583 | */ | 2598 | */ |
2584 | 2599 | ||
2585 | if (fl4.saddr == 0) | 2600 | if (fl4->saddr == 0) |
2586 | fl4.saddr = inet_select_addr(dev_out, 0, | 2601 | fl4->saddr = inet_select_addr(dev_out, 0, |
2587 | RT_SCOPE_LINK); | 2602 | RT_SCOPE_LINK); |
2588 | res.type = RTN_UNICAST; | 2603 | res.type = RTN_UNICAST; |
2589 | goto make_route; | 2604 | goto make_route; |
2590 | } | 2605 | } |
@@ -2593,42 +2608,45 @@ static struct rtable *ip_route_output_slow(struct net *net, | |||
2593 | } | 2608 | } |
2594 | 2609 | ||
2595 | if (res.type == RTN_LOCAL) { | 2610 | if (res.type == RTN_LOCAL) { |
2596 | if (!fl4.saddr) { | 2611 | if (!fl4->saddr) { |
2597 | if (res.fi->fib_prefsrc) | 2612 | if (res.fi->fib_prefsrc) |
2598 | fl4.saddr = res.fi->fib_prefsrc; | 2613 | fl4->saddr = res.fi->fib_prefsrc; |
2599 | else | 2614 | else |
2600 | fl4.saddr = fl4.daddr; | 2615 | fl4->saddr = fl4->daddr; |
2601 | } | 2616 | } |
2602 | dev_out = net->loopback_dev; | 2617 | dev_out = net->loopback_dev; |
2603 | fl4.flowi4_oif = dev_out->ifindex; | 2618 | fl4->flowi4_oif = dev_out->ifindex; |
2604 | res.fi = NULL; | 2619 | res.fi = NULL; |
2605 | flags |= RTCF_LOCAL; | 2620 | flags |= RTCF_LOCAL; |
2606 | goto make_route; | 2621 | goto make_route; |
2607 | } | 2622 | } |
2608 | 2623 | ||
2609 | #ifdef CONFIG_IP_ROUTE_MULTIPATH | 2624 | #ifdef CONFIG_IP_ROUTE_MULTIPATH |
2610 | if (res.fi->fib_nhs > 1 && fl4.flowi4_oif == 0) | 2625 | if (res.fi->fib_nhs > 1 && fl4->flowi4_oif == 0) |
2611 | fib_select_multipath(&res); | 2626 | fib_select_multipath(&res); |
2612 | else | 2627 | else |
2613 | #endif | 2628 | #endif |
2614 | if (!res.prefixlen && res.type == RTN_UNICAST && !fl4.flowi4_oif) | 2629 | if (!res.prefixlen && |
2630 | res.table->tb_num_default > 1 && | ||
2631 | res.type == RTN_UNICAST && !fl4->flowi4_oif) | ||
2615 | fib_select_default(&res); | 2632 | fib_select_default(&res); |
2616 | 2633 | ||
2617 | if (!fl4.saddr) | 2634 | if (!fl4->saddr) |
2618 | fl4.saddr = FIB_RES_PREFSRC(net, res); | 2635 | fl4->saddr = FIB_RES_PREFSRC(net, res); |
2619 | 2636 | ||
2620 | dev_out = FIB_RES_DEV(res); | 2637 | dev_out = FIB_RES_DEV(res); |
2621 | fl4.flowi4_oif = dev_out->ifindex; | 2638 | fl4->flowi4_oif = dev_out->ifindex; |
2622 | 2639 | ||
2623 | 2640 | ||
2624 | make_route: | 2641 | make_route: |
2625 | rth = __mkroute_output(&res, &fl4, oldflp4, dev_out, flags); | 2642 | rth = __mkroute_output(&res, fl4, orig_daddr, orig_saddr, orig_oif, |
2643 | dev_out, flags); | ||
2626 | if (!IS_ERR(rth)) { | 2644 | if (!IS_ERR(rth)) { |
2627 | unsigned int hash; | 2645 | unsigned int hash; |
2628 | 2646 | ||
2629 | hash = rt_hash(oldflp4->daddr, oldflp4->saddr, oldflp4->flowi4_oif, | 2647 | hash = rt_hash(orig_daddr, orig_saddr, orig_oif, |
2630 | rt_genid(dev_net(dev_out))); | 2648 | rt_genid(dev_net(dev_out))); |
2631 | rth = rt_intern_hash(hash, rth, NULL, oldflp4->flowi4_oif); | 2649 | rth = rt_intern_hash(hash, rth, NULL, orig_oif); |
2632 | } | 2650 | } |
2633 | 2651 | ||
2634 | out: | 2652 | out: |
@@ -2636,7 +2654,7 @@ out: | |||
2636 | return rth; | 2654 | return rth; |
2637 | } | 2655 | } |
2638 | 2656 | ||
2639 | struct rtable *__ip_route_output_key(struct net *net, const struct flowi4 *flp4) | 2657 | struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *flp4) |
2640 | { | 2658 | { |
2641 | struct rtable *rth; | 2659 | struct rtable *rth; |
2642 | unsigned int hash; | 2660 | unsigned int hash; |
@@ -2654,13 +2672,17 @@ struct rtable *__ip_route_output_key(struct net *net, const struct flowi4 *flp4) | |||
2654 | rt_is_output_route(rth) && | 2672 | rt_is_output_route(rth) && |
2655 | rth->rt_oif == flp4->flowi4_oif && | 2673 | rth->rt_oif == flp4->flowi4_oif && |
2656 | rth->rt_mark == flp4->flowi4_mark && | 2674 | rth->rt_mark == flp4->flowi4_mark && |
2657 | !((rth->rt_tos ^ flp4->flowi4_tos) & | 2675 | !((rth->rt_key_tos ^ flp4->flowi4_tos) & |
2658 | (IPTOS_RT_MASK | RTO_ONLINK)) && | 2676 | (IPTOS_RT_MASK | RTO_ONLINK)) && |
2659 | net_eq(dev_net(rth->dst.dev), net) && | 2677 | net_eq(dev_net(rth->dst.dev), net) && |
2660 | !rt_is_expired(rth)) { | 2678 | !rt_is_expired(rth)) { |
2661 | dst_use(&rth->dst, jiffies); | 2679 | dst_use(&rth->dst, jiffies); |
2662 | RT_CACHE_STAT_INC(out_hit); | 2680 | RT_CACHE_STAT_INC(out_hit); |
2663 | rcu_read_unlock_bh(); | 2681 | rcu_read_unlock_bh(); |
2682 | if (!flp4->saddr) | ||
2683 | flp4->saddr = rth->rt_src; | ||
2684 | if (!flp4->daddr) | ||
2685 | flp4->daddr = rth->rt_dst; | ||
2664 | return rth; | 2686 | return rth; |
2665 | } | 2687 | } |
2666 | RT_CACHE_STAT_INC(out_hlist_search); | 2688 | RT_CACHE_STAT_INC(out_hlist_search); |
@@ -2686,6 +2708,12 @@ static void ipv4_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) | |||
2686 | { | 2708 | { |
2687 | } | 2709 | } |
2688 | 2710 | ||
2711 | static u32 *ipv4_rt_blackhole_cow_metrics(struct dst_entry *dst, | ||
2712 | unsigned long old) | ||
2713 | { | ||
2714 | return NULL; | ||
2715 | } | ||
2716 | |||
2689 | static struct dst_ops ipv4_dst_blackhole_ops = { | 2717 | static struct dst_ops ipv4_dst_blackhole_ops = { |
2690 | .family = AF_INET, | 2718 | .family = AF_INET, |
2691 | .protocol = cpu_to_be16(ETH_P_IP), | 2719 | .protocol = cpu_to_be16(ETH_P_IP), |
@@ -2694,11 +2722,12 @@ static struct dst_ops ipv4_dst_blackhole_ops = { | |||
2694 | .default_mtu = ipv4_blackhole_default_mtu, | 2722 | .default_mtu = ipv4_blackhole_default_mtu, |
2695 | .default_advmss = ipv4_default_advmss, | 2723 | .default_advmss = ipv4_default_advmss, |
2696 | .update_pmtu = ipv4_rt_blackhole_update_pmtu, | 2724 | .update_pmtu = ipv4_rt_blackhole_update_pmtu, |
2725 | .cow_metrics = ipv4_rt_blackhole_cow_metrics, | ||
2697 | }; | 2726 | }; |
2698 | 2727 | ||
2699 | struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig) | 2728 | struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_orig) |
2700 | { | 2729 | { |
2701 | struct rtable *rt = dst_alloc(&ipv4_dst_blackhole_ops, 1); | 2730 | struct rtable *rt = dst_alloc(&ipv4_dst_blackhole_ops, NULL, 1, 0, 0); |
2702 | struct rtable *ort = (struct rtable *) dst_orig; | 2731 | struct rtable *ort = (struct rtable *) dst_orig; |
2703 | 2732 | ||
2704 | if (rt) { | 2733 | if (rt) { |
@@ -2715,7 +2744,8 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or | |||
2715 | 2744 | ||
2716 | rt->rt_key_dst = ort->rt_key_dst; | 2745 | rt->rt_key_dst = ort->rt_key_dst; |
2717 | rt->rt_key_src = ort->rt_key_src; | 2746 | rt->rt_key_src = ort->rt_key_src; |
2718 | rt->rt_tos = ort->rt_tos; | 2747 | rt->rt_key_tos = ort->rt_key_tos; |
2748 | rt->rt_route_iif = ort->rt_route_iif; | ||
2719 | rt->rt_iif = ort->rt_iif; | 2749 | rt->rt_iif = ort->rt_iif; |
2720 | rt->rt_oif = ort->rt_oif; | 2750 | rt->rt_oif = ort->rt_oif; |
2721 | rt->rt_mark = ort->rt_mark; | 2751 | rt->rt_mark = ort->rt_mark; |
@@ -2725,7 +2755,6 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or | |||
2725 | rt->rt_type = ort->rt_type; | 2755 | rt->rt_type = ort->rt_type; |
2726 | rt->rt_dst = ort->rt_dst; | 2756 | rt->rt_dst = ort->rt_dst; |
2727 | rt->rt_src = ort->rt_src; | 2757 | rt->rt_src = ort->rt_src; |
2728 | rt->rt_iif = ort->rt_iif; | ||
2729 | rt->rt_gateway = ort->rt_gateway; | 2758 | rt->rt_gateway = ort->rt_gateway; |
2730 | rt->rt_spec_dst = ort->rt_spec_dst; | 2759 | rt->rt_spec_dst = ort->rt_spec_dst; |
2731 | rt->peer = ort->peer; | 2760 | rt->peer = ort->peer; |
@@ -2751,15 +2780,10 @@ struct rtable *ip_route_output_flow(struct net *net, struct flowi4 *flp4, | |||
2751 | if (IS_ERR(rt)) | 2780 | if (IS_ERR(rt)) |
2752 | return rt; | 2781 | return rt; |
2753 | 2782 | ||
2754 | if (flp4->flowi4_proto) { | 2783 | if (flp4->flowi4_proto) |
2755 | if (!flp4->saddr) | ||
2756 | flp4->saddr = rt->rt_src; | ||
2757 | if (!flp4->daddr) | ||
2758 | flp4->daddr = rt->rt_dst; | ||
2759 | rt = (struct rtable *) xfrm_lookup(net, &rt->dst, | 2784 | rt = (struct rtable *) xfrm_lookup(net, &rt->dst, |
2760 | flowi4_to_flowi(flp4), | 2785 | flowi4_to_flowi(flp4), |
2761 | sk, 0); | 2786 | sk, 0); |
2762 | } | ||
2763 | 2787 | ||
2764 | return rt; | 2788 | return rt; |
2765 | } | 2789 | } |
@@ -2783,7 +2807,7 @@ static int rt_fill_info(struct net *net, | |||
2783 | r->rtm_family = AF_INET; | 2807 | r->rtm_family = AF_INET; |
2784 | r->rtm_dst_len = 32; | 2808 | r->rtm_dst_len = 32; |
2785 | r->rtm_src_len = 0; | 2809 | r->rtm_src_len = 0; |
2786 | r->rtm_tos = rt->rt_tos; | 2810 | r->rtm_tos = rt->rt_key_tos; |
2787 | r->rtm_table = RT_TABLE_MAIN; | 2811 | r->rtm_table = RT_TABLE_MAIN; |
2788 | NLA_PUT_U32(skb, RTA_TABLE, RT_TABLE_MAIN); | 2812 | NLA_PUT_U32(skb, RTA_TABLE, RT_TABLE_MAIN); |
2789 | r->rtm_type = rt->rt_type; | 2813 | r->rtm_type = rt->rt_type; |
@@ -2837,7 +2861,9 @@ static int rt_fill_info(struct net *net, | |||
2837 | 2861 | ||
2838 | if (ipv4_is_multicast(dst) && !ipv4_is_local_multicast(dst) && | 2862 | if (ipv4_is_multicast(dst) && !ipv4_is_local_multicast(dst) && |
2839 | IPV4_DEVCONF_ALL(net, MC_FORWARDING)) { | 2863 | IPV4_DEVCONF_ALL(net, MC_FORWARDING)) { |
2840 | int err = ipmr_get_route(net, skb, r, nowait); | 2864 | int err = ipmr_get_route(net, skb, |
2865 | rt->rt_src, rt->rt_dst, | ||
2866 | r, nowait); | ||
2841 | if (err <= 0) { | 2867 | if (err <= 0) { |
2842 | if (!nowait) { | 2868 | if (!nowait) { |
2843 | if (err == 0) | 2869 | if (err == 0) |
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index 8b44c6d2a79b..26461492a847 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c | |||
@@ -321,10 +321,10 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, | |||
321 | * the ACK carries the same options again (see RFC1122 4.2.3.8) | 321 | * the ACK carries the same options again (see RFC1122 4.2.3.8) |
322 | */ | 322 | */ |
323 | if (opt && opt->optlen) { | 323 | if (opt && opt->optlen) { |
324 | int opt_size = sizeof(struct ip_options) + opt->optlen; | 324 | int opt_size = sizeof(struct ip_options_rcu) + opt->optlen; |
325 | 325 | ||
326 | ireq->opt = kmalloc(opt_size, GFP_ATOMIC); | 326 | ireq->opt = kmalloc(opt_size, GFP_ATOMIC); |
327 | if (ireq->opt != NULL && ip_options_echo(ireq->opt, skb)) { | 327 | if (ireq->opt != NULL && ip_options_echo(&ireq->opt->opt, skb)) { |
328 | kfree(ireq->opt); | 328 | kfree(ireq->opt); |
329 | ireq->opt = NULL; | 329 | ireq->opt = NULL; |
330 | } | 330 | } |
@@ -345,17 +345,13 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, | |||
345 | * no easy way to do this. | 345 | * no easy way to do this. |
346 | */ | 346 | */ |
347 | { | 347 | { |
348 | struct flowi4 fl4 = { | 348 | struct flowi4 fl4; |
349 | .flowi4_mark = sk->sk_mark, | 349 | |
350 | .daddr = ((opt && opt->srr) ? | 350 | flowi4_init_output(&fl4, 0, sk->sk_mark, RT_CONN_FLAGS(sk), |
351 | opt->faddr : ireq->rmt_addr), | 351 | RT_SCOPE_UNIVERSE, IPPROTO_TCP, |
352 | .saddr = ireq->loc_addr, | 352 | inet_sk_flowi_flags(sk), |
353 | .flowi4_tos = RT_CONN_FLAGS(sk), | 353 | (opt && opt->srr) ? opt->faddr : ireq->rmt_addr, |
354 | .flowi4_proto = IPPROTO_TCP, | 354 | ireq->loc_addr, th->source, th->dest); |
355 | .flowi4_flags = inet_sk_flowi_flags(sk), | ||
356 | .fl4_sport = th->dest, | ||
357 | .fl4_dport = th->source, | ||
358 | }; | ||
359 | security_req_classify_flow(req, flowi4_to_flowi(&fl4)); | 355 | security_req_classify_flow(req, flowi4_to_flowi(&fl4)); |
360 | rt = ip_route_output_key(sock_net(sk), &fl4); | 356 | rt = ip_route_output_key(sock_net(sk), &fl4); |
361 | if (IS_ERR(rt)) { | 357 | if (IS_ERR(rt)) { |
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 1a456652086b..28e8273bbef8 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c | |||
@@ -13,6 +13,7 @@ | |||
13 | #include <linux/seqlock.h> | 13 | #include <linux/seqlock.h> |
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/slab.h> | 15 | #include <linux/slab.h> |
16 | #include <linux/nsproxy.h> | ||
16 | #include <net/snmp.h> | 17 | #include <net/snmp.h> |
17 | #include <net/icmp.h> | 18 | #include <net/icmp.h> |
18 | #include <net/ip.h> | 19 | #include <net/ip.h> |
@@ -21,6 +22,7 @@ | |||
21 | #include <net/udp.h> | 22 | #include <net/udp.h> |
22 | #include <net/cipso_ipv4.h> | 23 | #include <net/cipso_ipv4.h> |
23 | #include <net/inet_frag.h> | 24 | #include <net/inet_frag.h> |
25 | #include <net/ping.h> | ||
24 | 26 | ||
25 | static int zero; | 27 | static int zero; |
26 | static int tcp_retr1_max = 255; | 28 | static int tcp_retr1_max = 255; |
@@ -30,6 +32,8 @@ static int tcp_adv_win_scale_min = -31; | |||
30 | static int tcp_adv_win_scale_max = 31; | 32 | static int tcp_adv_win_scale_max = 31; |
31 | static int ip_ttl_min = 1; | 33 | static int ip_ttl_min = 1; |
32 | static int ip_ttl_max = 255; | 34 | static int ip_ttl_max = 255; |
35 | static int ip_ping_group_range_min[] = { 0, 0 }; | ||
36 | static int ip_ping_group_range_max[] = { GID_T_MAX, GID_T_MAX }; | ||
33 | 37 | ||
34 | /* Update system visible IP port range */ | 38 | /* Update system visible IP port range */ |
35 | static void set_local_port_range(int range[2]) | 39 | static void set_local_port_range(int range[2]) |
@@ -68,6 +72,65 @@ static int ipv4_local_port_range(ctl_table *table, int write, | |||
68 | return ret; | 72 | return ret; |
69 | } | 73 | } |
70 | 74 | ||
75 | |||
76 | void inet_get_ping_group_range_net(struct net *net, gid_t *low, gid_t *high) | ||
77 | { | ||
78 | gid_t *data = net->ipv4.sysctl_ping_group_range; | ||
79 | unsigned seq; | ||
80 | do { | ||
81 | seq = read_seqbegin(&sysctl_local_ports.lock); | ||
82 | |||
83 | *low = data[0]; | ||
84 | *high = data[1]; | ||
85 | } while (read_seqretry(&sysctl_local_ports.lock, seq)); | ||
86 | } | ||
87 | |||
88 | void inet_get_ping_group_range_table(struct ctl_table *table, gid_t *low, gid_t *high) | ||
89 | { | ||
90 | gid_t *data = table->data; | ||
91 | unsigned seq; | ||
92 | do { | ||
93 | seq = read_seqbegin(&sysctl_local_ports.lock); | ||
94 | |||
95 | *low = data[0]; | ||
96 | *high = data[1]; | ||
97 | } while (read_seqretry(&sysctl_local_ports.lock, seq)); | ||
98 | } | ||
99 | |||
100 | /* Update system visible IP port range */ | ||
101 | static void set_ping_group_range(struct ctl_table *table, int range[2]) | ||
102 | { | ||
103 | gid_t *data = table->data; | ||
104 | write_seqlock(&sysctl_local_ports.lock); | ||
105 | data[0] = range[0]; | ||
106 | data[1] = range[1]; | ||
107 | write_sequnlock(&sysctl_local_ports.lock); | ||
108 | } | ||
109 | |||
110 | /* Validate changes from /proc interface. */ | ||
111 | static int ipv4_ping_group_range(ctl_table *table, int write, | ||
112 | void __user *buffer, | ||
113 | size_t *lenp, loff_t *ppos) | ||
114 | { | ||
115 | int ret; | ||
116 | gid_t range[2]; | ||
117 | ctl_table tmp = { | ||
118 | .data = &range, | ||
119 | .maxlen = sizeof(range), | ||
120 | .mode = table->mode, | ||
121 | .extra1 = &ip_ping_group_range_min, | ||
122 | .extra2 = &ip_ping_group_range_max, | ||
123 | }; | ||
124 | |||
125 | inet_get_ping_group_range_table(table, range, range + 1); | ||
126 | ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos); | ||
127 | |||
128 | if (write && ret == 0) | ||
129 | set_ping_group_range(table, range); | ||
130 | |||
131 | return ret; | ||
132 | } | ||
133 | |||
71 | static int proc_tcp_congestion_control(ctl_table *ctl, int write, | 134 | static int proc_tcp_congestion_control(ctl_table *ctl, int write, |
72 | void __user *buffer, size_t *lenp, loff_t *ppos) | 135 | void __user *buffer, size_t *lenp, loff_t *ppos) |
73 | { | 136 | { |
@@ -311,7 +374,6 @@ static struct ctl_table ipv4_table[] = { | |||
311 | .mode = 0644, | 374 | .mode = 0644, |
312 | .proc_handler = proc_do_large_bitmap, | 375 | .proc_handler = proc_do_large_bitmap, |
313 | }, | 376 | }, |
314 | #ifdef CONFIG_IP_MULTICAST | ||
315 | { | 377 | { |
316 | .procname = "igmp_max_memberships", | 378 | .procname = "igmp_max_memberships", |
317 | .data = &sysctl_igmp_max_memberships, | 379 | .data = &sysctl_igmp_max_memberships, |
@@ -319,8 +381,6 @@ static struct ctl_table ipv4_table[] = { | |||
319 | .mode = 0644, | 381 | .mode = 0644, |
320 | .proc_handler = proc_dointvec | 382 | .proc_handler = proc_dointvec |
321 | }, | 383 | }, |
322 | |||
323 | #endif | ||
324 | { | 384 | { |
325 | .procname = "igmp_max_msf", | 385 | .procname = "igmp_max_msf", |
326 | .data = &sysctl_igmp_max_msf, | 386 | .data = &sysctl_igmp_max_msf, |
@@ -680,6 +740,13 @@ static struct ctl_table ipv4_net_table[] = { | |||
680 | .mode = 0644, | 740 | .mode = 0644, |
681 | .proc_handler = proc_dointvec | 741 | .proc_handler = proc_dointvec |
682 | }, | 742 | }, |
743 | { | ||
744 | .procname = "ping_group_range", | ||
745 | .data = &init_net.ipv4.sysctl_ping_group_range, | ||
746 | .maxlen = sizeof(init_net.ipv4.sysctl_ping_group_range), | ||
747 | .mode = 0644, | ||
748 | .proc_handler = ipv4_ping_group_range, | ||
749 | }, | ||
683 | { } | 750 | { } |
684 | }; | 751 | }; |
685 | 752 | ||
@@ -714,8 +781,18 @@ static __net_init int ipv4_sysctl_init_net(struct net *net) | |||
714 | &net->ipv4.sysctl_icmp_ratemask; | 781 | &net->ipv4.sysctl_icmp_ratemask; |
715 | table[6].data = | 782 | table[6].data = |
716 | &net->ipv4.sysctl_rt_cache_rebuild_count; | 783 | &net->ipv4.sysctl_rt_cache_rebuild_count; |
784 | table[7].data = | ||
785 | &net->ipv4.sysctl_ping_group_range; | ||
786 | |||
717 | } | 787 | } |
718 | 788 | ||
789 | /* | ||
790 | * Sane defaults - nobody may create ping sockets. | ||
791 | * Boot scripts should set this to distro-specific group. | ||
792 | */ | ||
793 | net->ipv4.sysctl_ping_group_range[0] = 1; | ||
794 | net->ipv4.sysctl_ping_group_range[1] = 0; | ||
795 | |||
719 | net->ipv4.sysctl_rt_cache_rebuild_count = 4; | 796 | net->ipv4.sysctl_rt_cache_rebuild_count = 4; |
720 | 797 | ||
721 | net->ipv4.ipv4_hdr = register_net_sysctl_table(net, | 798 | net->ipv4.ipv4_hdr = register_net_sysctl_table(net, |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index b22d45010545..054a59d21eb0 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -999,7 +999,8 @@ new_segment: | |||
999 | /* We have some space in skb head. Superb! */ | 999 | /* We have some space in skb head. Superb! */ |
1000 | if (copy > skb_tailroom(skb)) | 1000 | if (copy > skb_tailroom(skb)) |
1001 | copy = skb_tailroom(skb); | 1001 | copy = skb_tailroom(skb); |
1002 | if ((err = skb_add_data(skb, from, copy)) != 0) | 1002 | err = skb_add_data_nocache(sk, skb, from, copy); |
1003 | if (err) | ||
1003 | goto do_fault; | 1004 | goto do_fault; |
1004 | } else { | 1005 | } else { |
1005 | int merge = 0; | 1006 | int merge = 0; |
@@ -1042,8 +1043,8 @@ new_segment: | |||
1042 | 1043 | ||
1043 | /* Time to copy data. We are close to | 1044 | /* Time to copy data. We are close to |
1044 | * the end! */ | 1045 | * the end! */ |
1045 | err = skb_copy_to_page(sk, from, skb, page, | 1046 | err = skb_copy_to_page_nocache(sk, from, skb, |
1046 | off, copy); | 1047 | page, off, copy); |
1047 | if (err) { | 1048 | if (err) { |
1048 | /* If this page was new, give it to the | 1049 | /* If this page was new, give it to the |
1049 | * socket so it does not get leaked. | 1050 | * socket so it does not get leaked. |
diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c index 34340c9c95fa..f376b05cca81 100644 --- a/net/ipv4/tcp_cubic.c +++ b/net/ipv4/tcp_cubic.c | |||
@@ -93,6 +93,7 @@ struct bictcp { | |||
93 | u32 ack_cnt; /* number of acks */ | 93 | u32 ack_cnt; /* number of acks */ |
94 | u32 tcp_cwnd; /* estimated tcp cwnd */ | 94 | u32 tcp_cwnd; /* estimated tcp cwnd */ |
95 | #define ACK_RATIO_SHIFT 4 | 95 | #define ACK_RATIO_SHIFT 4 |
96 | #define ACK_RATIO_LIMIT (32u << ACK_RATIO_SHIFT) | ||
96 | u16 delayed_ack; /* estimate the ratio of Packets/ACKs << 4 */ | 97 | u16 delayed_ack; /* estimate the ratio of Packets/ACKs << 4 */ |
97 | u8 sample_cnt; /* number of samples to decide curr_rtt */ | 98 | u8 sample_cnt; /* number of samples to decide curr_rtt */ |
98 | u8 found; /* the exit point is found? */ | 99 | u8 found; /* the exit point is found? */ |
@@ -398,8 +399,12 @@ static void bictcp_acked(struct sock *sk, u32 cnt, s32 rtt_us) | |||
398 | u32 delay; | 399 | u32 delay; |
399 | 400 | ||
400 | if (icsk->icsk_ca_state == TCP_CA_Open) { | 401 | if (icsk->icsk_ca_state == TCP_CA_Open) { |
401 | cnt -= ca->delayed_ack >> ACK_RATIO_SHIFT; | 402 | u32 ratio = ca->delayed_ack; |
402 | ca->delayed_ack += cnt; | 403 | |
404 | ratio -= ca->delayed_ack >> ACK_RATIO_SHIFT; | ||
405 | ratio += cnt; | ||
406 | |||
407 | ca->delayed_ack = min(ratio, ACK_RATIO_LIMIT); | ||
403 | } | 408 | } |
404 | 409 | ||
405 | /* Some calls are for duplicates without timetamps */ | 410 | /* Some calls are for duplicates without timetamps */ |
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index f7e6c2c2d2bb..f67fb34e16e5 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -146,13 +146,15 @@ EXPORT_SYMBOL_GPL(tcp_twsk_unique); | |||
146 | /* This will initiate an outgoing connection. */ | 146 | /* This will initiate an outgoing connection. */ |
147 | int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | 147 | int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) |
148 | { | 148 | { |
149 | struct sockaddr_in *usin = (struct sockaddr_in *)uaddr; | ||
149 | struct inet_sock *inet = inet_sk(sk); | 150 | struct inet_sock *inet = inet_sk(sk); |
150 | struct tcp_sock *tp = tcp_sk(sk); | 151 | struct tcp_sock *tp = tcp_sk(sk); |
151 | struct sockaddr_in *usin = (struct sockaddr_in *)uaddr; | ||
152 | __be16 orig_sport, orig_dport; | 152 | __be16 orig_sport, orig_dport; |
153 | struct rtable *rt; | ||
154 | __be32 daddr, nexthop; | 153 | __be32 daddr, nexthop; |
154 | struct flowi4 *fl4; | ||
155 | struct rtable *rt; | ||
155 | int err; | 156 | int err; |
157 | struct ip_options_rcu *inet_opt; | ||
156 | 158 | ||
157 | if (addr_len < sizeof(struct sockaddr_in)) | 159 | if (addr_len < sizeof(struct sockaddr_in)) |
158 | return -EINVAL; | 160 | return -EINVAL; |
@@ -161,15 +163,18 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
161 | return -EAFNOSUPPORT; | 163 | return -EAFNOSUPPORT; |
162 | 164 | ||
163 | nexthop = daddr = usin->sin_addr.s_addr; | 165 | nexthop = daddr = usin->sin_addr.s_addr; |
164 | if (inet->opt && inet->opt->srr) { | 166 | inet_opt = rcu_dereference_protected(inet->inet_opt, |
167 | sock_owned_by_user(sk)); | ||
168 | if (inet_opt && inet_opt->opt.srr) { | ||
165 | if (!daddr) | 169 | if (!daddr) |
166 | return -EINVAL; | 170 | return -EINVAL; |
167 | nexthop = inet->opt->faddr; | 171 | nexthop = inet_opt->opt.faddr; |
168 | } | 172 | } |
169 | 173 | ||
170 | orig_sport = inet->inet_sport; | 174 | orig_sport = inet->inet_sport; |
171 | orig_dport = usin->sin_port; | 175 | orig_dport = usin->sin_port; |
172 | rt = ip_route_connect(nexthop, inet->inet_saddr, | 176 | fl4 = &inet->cork.fl.u.ip4; |
177 | rt = ip_route_connect(fl4, nexthop, inet->inet_saddr, | ||
173 | RT_CONN_FLAGS(sk), sk->sk_bound_dev_if, | 178 | RT_CONN_FLAGS(sk), sk->sk_bound_dev_if, |
174 | IPPROTO_TCP, | 179 | IPPROTO_TCP, |
175 | orig_sport, orig_dport, sk, true); | 180 | orig_sport, orig_dport, sk, true); |
@@ -185,11 +190,11 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
185 | return -ENETUNREACH; | 190 | return -ENETUNREACH; |
186 | } | 191 | } |
187 | 192 | ||
188 | if (!inet->opt || !inet->opt->srr) | 193 | if (!inet_opt || !inet_opt->opt.srr) |
189 | daddr = rt->rt_dst; | 194 | daddr = fl4->daddr; |
190 | 195 | ||
191 | if (!inet->inet_saddr) | 196 | if (!inet->inet_saddr) |
192 | inet->inet_saddr = rt->rt_src; | 197 | inet->inet_saddr = fl4->saddr; |
193 | inet->inet_rcv_saddr = inet->inet_saddr; | 198 | inet->inet_rcv_saddr = inet->inet_saddr; |
194 | 199 | ||
195 | if (tp->rx_opt.ts_recent_stamp && inet->inet_daddr != daddr) { | 200 | if (tp->rx_opt.ts_recent_stamp && inet->inet_daddr != daddr) { |
@@ -200,7 +205,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
200 | } | 205 | } |
201 | 206 | ||
202 | if (tcp_death_row.sysctl_tw_recycle && | 207 | if (tcp_death_row.sysctl_tw_recycle && |
203 | !tp->rx_opt.ts_recent_stamp && rt->rt_dst == daddr) { | 208 | !tp->rx_opt.ts_recent_stamp && fl4->daddr == daddr) { |
204 | struct inet_peer *peer = rt_get_peer(rt); | 209 | struct inet_peer *peer = rt_get_peer(rt); |
205 | /* | 210 | /* |
206 | * VJ's idea. We save last timestamp seen from | 211 | * VJ's idea. We save last timestamp seen from |
@@ -221,8 +226,8 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
221 | inet->inet_daddr = daddr; | 226 | inet->inet_daddr = daddr; |
222 | 227 | ||
223 | inet_csk(sk)->icsk_ext_hdr_len = 0; | 228 | inet_csk(sk)->icsk_ext_hdr_len = 0; |
224 | if (inet->opt) | 229 | if (inet_opt) |
225 | inet_csk(sk)->icsk_ext_hdr_len = inet->opt->optlen; | 230 | inet_csk(sk)->icsk_ext_hdr_len = inet_opt->opt.optlen; |
226 | 231 | ||
227 | tp->rx_opt.mss_clamp = TCP_MSS_DEFAULT; | 232 | tp->rx_opt.mss_clamp = TCP_MSS_DEFAULT; |
228 | 233 | ||
@@ -236,8 +241,7 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
236 | if (err) | 241 | if (err) |
237 | goto failure; | 242 | goto failure; |
238 | 243 | ||
239 | rt = ip_route_newports(rt, IPPROTO_TCP, | 244 | rt = ip_route_newports(fl4, rt, orig_sport, orig_dport, |
240 | orig_sport, orig_dport, | ||
241 | inet->inet_sport, inet->inet_dport, sk); | 245 | inet->inet_sport, inet->inet_dport, sk); |
242 | if (IS_ERR(rt)) { | 246 | if (IS_ERR(rt)) { |
243 | err = PTR_ERR(rt); | 247 | err = PTR_ERR(rt); |
@@ -279,7 +283,7 @@ EXPORT_SYMBOL(tcp_v4_connect); | |||
279 | /* | 283 | /* |
280 | * This routine does path mtu discovery as defined in RFC1191. | 284 | * This routine does path mtu discovery as defined in RFC1191. |
281 | */ | 285 | */ |
282 | static void do_pmtu_discovery(struct sock *sk, struct iphdr *iph, u32 mtu) | 286 | static void do_pmtu_discovery(struct sock *sk, const struct iphdr *iph, u32 mtu) |
283 | { | 287 | { |
284 | struct dst_entry *dst; | 288 | struct dst_entry *dst; |
285 | struct inet_sock *inet = inet_sk(sk); | 289 | struct inet_sock *inet = inet_sk(sk); |
@@ -341,7 +345,7 @@ static void do_pmtu_discovery(struct sock *sk, struct iphdr *iph, u32 mtu) | |||
341 | 345 | ||
342 | void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) | 346 | void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) |
343 | { | 347 | { |
344 | struct iphdr *iph = (struct iphdr *)icmp_skb->data; | 348 | const struct iphdr *iph = (const struct iphdr *)icmp_skb->data; |
345 | struct tcphdr *th = (struct tcphdr *)(icmp_skb->data + (iph->ihl << 2)); | 349 | struct tcphdr *th = (struct tcphdr *)(icmp_skb->data + (iph->ihl << 2)); |
346 | struct inet_connection_sock *icsk; | 350 | struct inet_connection_sock *icsk; |
347 | struct tcp_sock *tp; | 351 | struct tcp_sock *tp; |
@@ -647,7 +651,7 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb) | |||
647 | arg.flags = (sk && inet_sk(sk)->transparent) ? IP_REPLY_ARG_NOSRCCHECK : 0; | 651 | arg.flags = (sk && inet_sk(sk)->transparent) ? IP_REPLY_ARG_NOSRCCHECK : 0; |
648 | 652 | ||
649 | net = dev_net(skb_dst(skb)->dev); | 653 | net = dev_net(skb_dst(skb)->dev); |
650 | ip_send_reply(net->ipv4.tcp_sock, skb, | 654 | ip_send_reply(net->ipv4.tcp_sock, skb, ip_hdr(skb)->saddr, |
651 | &arg, arg.iov[0].iov_len); | 655 | &arg, arg.iov[0].iov_len); |
652 | 656 | ||
653 | TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); | 657 | TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); |
@@ -722,7 +726,7 @@ static void tcp_v4_send_ack(struct sk_buff *skb, u32 seq, u32 ack, | |||
722 | if (oif) | 726 | if (oif) |
723 | arg.bound_dev_if = oif; | 727 | arg.bound_dev_if = oif; |
724 | 728 | ||
725 | ip_send_reply(net->ipv4.tcp_sock, skb, | 729 | ip_send_reply(net->ipv4.tcp_sock, skb, ip_hdr(skb)->saddr, |
726 | &arg, arg.iov[0].iov_len); | 730 | &arg, arg.iov[0].iov_len); |
727 | 731 | ||
728 | TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); | 732 | TCP_INC_STATS_BH(net, TCP_MIB_OUTSEGS); |
@@ -820,17 +824,18 @@ static void syn_flood_warning(const struct sk_buff *skb) | |||
820 | /* | 824 | /* |
821 | * Save and compile IPv4 options into the request_sock if needed. | 825 | * Save and compile IPv4 options into the request_sock if needed. |
822 | */ | 826 | */ |
823 | static struct ip_options *tcp_v4_save_options(struct sock *sk, | 827 | static struct ip_options_rcu *tcp_v4_save_options(struct sock *sk, |
824 | struct sk_buff *skb) | 828 | struct sk_buff *skb) |
825 | { | 829 | { |
826 | struct ip_options *opt = &(IPCB(skb)->opt); | 830 | const struct ip_options *opt = &(IPCB(skb)->opt); |
827 | struct ip_options *dopt = NULL; | 831 | struct ip_options_rcu *dopt = NULL; |
828 | 832 | ||
829 | if (opt && opt->optlen) { | 833 | if (opt && opt->optlen) { |
830 | int opt_size = optlength(opt); | 834 | int opt_size = sizeof(*dopt) + opt->optlen; |
835 | |||
831 | dopt = kmalloc(opt_size, GFP_ATOMIC); | 836 | dopt = kmalloc(opt_size, GFP_ATOMIC); |
832 | if (dopt) { | 837 | if (dopt) { |
833 | if (ip_options_echo(dopt, skb)) { | 838 | if (ip_options_echo(&dopt->opt, skb)) { |
834 | kfree(dopt); | 839 | kfree(dopt); |
835 | dopt = NULL; | 840 | dopt = NULL; |
836 | } | 841 | } |
@@ -1411,19 +1416,16 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1411 | #ifdef CONFIG_TCP_MD5SIG | 1416 | #ifdef CONFIG_TCP_MD5SIG |
1412 | struct tcp_md5sig_key *key; | 1417 | struct tcp_md5sig_key *key; |
1413 | #endif | 1418 | #endif |
1419 | struct ip_options_rcu *inet_opt; | ||
1414 | 1420 | ||
1415 | if (sk_acceptq_is_full(sk)) | 1421 | if (sk_acceptq_is_full(sk)) |
1416 | goto exit_overflow; | 1422 | goto exit_overflow; |
1417 | 1423 | ||
1418 | if (!dst && (dst = inet_csk_route_req(sk, req)) == NULL) | ||
1419 | goto exit; | ||
1420 | |||
1421 | newsk = tcp_create_openreq_child(sk, req, skb); | 1424 | newsk = tcp_create_openreq_child(sk, req, skb); |
1422 | if (!newsk) | 1425 | if (!newsk) |
1423 | goto exit_nonewsk; | 1426 | goto exit_nonewsk; |
1424 | 1427 | ||
1425 | newsk->sk_gso_type = SKB_GSO_TCPV4; | 1428 | newsk->sk_gso_type = SKB_GSO_TCPV4; |
1426 | sk_setup_caps(newsk, dst); | ||
1427 | 1429 | ||
1428 | newtp = tcp_sk(newsk); | 1430 | newtp = tcp_sk(newsk); |
1429 | newinet = inet_sk(newsk); | 1431 | newinet = inet_sk(newsk); |
@@ -1431,15 +1433,21 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1431 | newinet->inet_daddr = ireq->rmt_addr; | 1433 | newinet->inet_daddr = ireq->rmt_addr; |
1432 | newinet->inet_rcv_saddr = ireq->loc_addr; | 1434 | newinet->inet_rcv_saddr = ireq->loc_addr; |
1433 | newinet->inet_saddr = ireq->loc_addr; | 1435 | newinet->inet_saddr = ireq->loc_addr; |
1434 | newinet->opt = ireq->opt; | 1436 | inet_opt = ireq->opt; |
1437 | rcu_assign_pointer(newinet->inet_opt, inet_opt); | ||
1435 | ireq->opt = NULL; | 1438 | ireq->opt = NULL; |
1436 | newinet->mc_index = inet_iif(skb); | 1439 | newinet->mc_index = inet_iif(skb); |
1437 | newinet->mc_ttl = ip_hdr(skb)->ttl; | 1440 | newinet->mc_ttl = ip_hdr(skb)->ttl; |
1438 | inet_csk(newsk)->icsk_ext_hdr_len = 0; | 1441 | inet_csk(newsk)->icsk_ext_hdr_len = 0; |
1439 | if (newinet->opt) | 1442 | if (inet_opt) |
1440 | inet_csk(newsk)->icsk_ext_hdr_len = newinet->opt->optlen; | 1443 | inet_csk(newsk)->icsk_ext_hdr_len = inet_opt->opt.optlen; |
1441 | newinet->inet_id = newtp->write_seq ^ jiffies; | 1444 | newinet->inet_id = newtp->write_seq ^ jiffies; |
1442 | 1445 | ||
1446 | if (!dst && (dst = inet_csk_route_child_sock(sk, newsk, req)) == NULL) | ||
1447 | goto put_and_exit; | ||
1448 | |||
1449 | sk_setup_caps(newsk, dst); | ||
1450 | |||
1443 | tcp_mtup_init(newsk); | 1451 | tcp_mtup_init(newsk); |
1444 | tcp_sync_mss(newsk, dst_mtu(dst)); | 1452 | tcp_sync_mss(newsk, dst_mtu(dst)); |
1445 | newtp->advmss = dst_metric_advmss(dst); | 1453 | newtp->advmss = dst_metric_advmss(dst); |
@@ -1467,10 +1475,8 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1467 | } | 1475 | } |
1468 | #endif | 1476 | #endif |
1469 | 1477 | ||
1470 | if (__inet_inherit_port(sk, newsk) < 0) { | 1478 | if (__inet_inherit_port(sk, newsk) < 0) |
1471 | sock_put(newsk); | 1479 | goto put_and_exit; |
1472 | goto exit; | ||
1473 | } | ||
1474 | __inet_hash_nolisten(newsk, NULL); | 1480 | __inet_hash_nolisten(newsk, NULL); |
1475 | 1481 | ||
1476 | return newsk; | 1482 | return newsk; |
@@ -1482,6 +1488,9 @@ exit_nonewsk: | |||
1482 | exit: | 1488 | exit: |
1483 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); | 1489 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); |
1484 | return NULL; | 1490 | return NULL; |
1491 | put_and_exit: | ||
1492 | sock_put(newsk); | ||
1493 | goto exit; | ||
1485 | } | 1494 | } |
1486 | EXPORT_SYMBOL(tcp_v4_syn_recv_sock); | 1495 | EXPORT_SYMBOL(tcp_v4_syn_recv_sock); |
1487 | 1496 | ||
@@ -1764,7 +1773,8 @@ struct inet_peer *tcp_v4_get_peer(struct sock *sk, bool *release_it) | |||
1764 | struct inet_sock *inet = inet_sk(sk); | 1773 | struct inet_sock *inet = inet_sk(sk); |
1765 | struct inet_peer *peer; | 1774 | struct inet_peer *peer; |
1766 | 1775 | ||
1767 | if (!rt || rt->rt_dst != inet->inet_daddr) { | 1776 | if (!rt || |
1777 | inet->cork.fl.u.ip4.daddr != inet->inet_daddr) { | ||
1768 | peer = inet_getpeer_v4(inet->inet_daddr, 1); | 1778 | peer = inet_getpeer_v4(inet->inet_daddr, 1); |
1769 | *release_it = true; | 1779 | *release_it = true; |
1770 | } else { | 1780 | } else { |
@@ -2527,7 +2537,7 @@ void tcp4_proc_exit(void) | |||
2527 | 2537 | ||
2528 | struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *skb) | 2538 | struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *skb) |
2529 | { | 2539 | { |
2530 | struct iphdr *iph = skb_gro_network_header(skb); | 2540 | const struct iphdr *iph = skb_gro_network_header(skb); |
2531 | 2541 | ||
2532 | switch (skb->ip_summed) { | 2542 | switch (skb->ip_summed) { |
2533 | case CHECKSUM_COMPLETE: | 2543 | case CHECKSUM_COMPLETE: |
@@ -2548,7 +2558,7 @@ struct sk_buff **tcp4_gro_receive(struct sk_buff **head, struct sk_buff *skb) | |||
2548 | 2558 | ||
2549 | int tcp4_gro_complete(struct sk_buff *skb) | 2559 | int tcp4_gro_complete(struct sk_buff *skb) |
2550 | { | 2560 | { |
2551 | struct iphdr *iph = ip_hdr(skb); | 2561 | const struct iphdr *iph = ip_hdr(skb); |
2552 | struct tcphdr *th = tcp_hdr(skb); | 2562 | struct tcphdr *th = tcp_hdr(skb); |
2553 | 2563 | ||
2554 | th->check = ~tcp_v4_check(skb->len - skb_transport_offset(skb), | 2564 | th->check = ~tcp_v4_check(skb->len - skb_transport_offset(skb), |
diff --git a/net/ipv4/tcp_lp.c b/net/ipv4/tcp_lp.c index 656d431c99ad..72f7218b03f5 100644 --- a/net/ipv4/tcp_lp.c +++ b/net/ipv4/tcp_lp.c | |||
@@ -12,7 +12,7 @@ | |||
12 | * within cong_avoid. | 12 | * within cong_avoid. |
13 | * o Error correcting in remote HZ, therefore remote HZ will be keeped | 13 | * o Error correcting in remote HZ, therefore remote HZ will be keeped |
14 | * on checking and updating. | 14 | * on checking and updating. |
15 | * o Handling calculation of One-Way-Delay (OWD) within rtt_sample, sicne | 15 | * o Handling calculation of One-Way-Delay (OWD) within rtt_sample, since |
16 | * OWD have a similar meaning as RTT. Also correct the buggy formular. | 16 | * OWD have a similar meaning as RTT. Also correct the buggy formular. |
17 | * o Handle reaction for Early Congestion Indication (ECI) within | 17 | * o Handle reaction for Early Congestion Indication (ECI) within |
18 | * pkts_acked, as mentioned within pseudo code. | 18 | * pkts_acked, as mentioned within pseudo code. |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 8b0d0167e44a..882e0b0964d0 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -73,7 +73,7 @@ static void tcp_event_new_data_sent(struct sock *sk, struct sk_buff *skb) | |||
73 | tcp_advance_send_head(sk, skb); | 73 | tcp_advance_send_head(sk, skb); |
74 | tp->snd_nxt = TCP_SKB_CB(skb)->end_seq; | 74 | tp->snd_nxt = TCP_SKB_CB(skb)->end_seq; |
75 | 75 | ||
76 | /* Don't override Nagle indefinately with F-RTO */ | 76 | /* Don't override Nagle indefinitely with F-RTO */ |
77 | if (tp->frto_counter == 2) | 77 | if (tp->frto_counter == 2) |
78 | tp->frto_counter = 3; | 78 | tp->frto_counter = 3; |
79 | 79 | ||
@@ -899,7 +899,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, | |||
899 | TCP_ADD_STATS(sock_net(sk), TCP_MIB_OUTSEGS, | 899 | TCP_ADD_STATS(sock_net(sk), TCP_MIB_OUTSEGS, |
900 | tcp_skb_pcount(skb)); | 900 | tcp_skb_pcount(skb)); |
901 | 901 | ||
902 | err = icsk->icsk_af_ops->queue_xmit(skb); | 902 | err = icsk->icsk_af_ops->queue_xmit(skb, &inet->cork.fl); |
903 | if (likely(err <= 0)) | 903 | if (likely(err <= 0)) |
904 | return err; | 904 | return err; |
905 | 905 | ||
diff --git a/net/ipv4/tcp_yeah.c b/net/ipv4/tcp_yeah.c index dc7f43179c9a..05c3b6f0e8e1 100644 --- a/net/ipv4/tcp_yeah.c +++ b/net/ipv4/tcp_yeah.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #define TCP_YEAH_DELTA 3 //log minimum fraction of cwnd to be removed on loss | 20 | #define TCP_YEAH_DELTA 3 //log minimum fraction of cwnd to be removed on loss |
21 | #define TCP_YEAH_EPSILON 1 //log maximum fraction to be removed on early decongestion | 21 | #define TCP_YEAH_EPSILON 1 //log maximum fraction to be removed on early decongestion |
22 | #define TCP_YEAH_PHY 8 //lin maximum delta from base | 22 | #define TCP_YEAH_PHY 8 //lin maximum delta from base |
23 | #define TCP_YEAH_RHO 16 //lin minumum number of consecutive rtt to consider competition on loss | 23 | #define TCP_YEAH_RHO 16 //lin minimum number of consecutive rtt to consider competition on loss |
24 | #define TCP_YEAH_ZETA 50 //lin minimum number of state switchs to reset reno_count | 24 | #define TCP_YEAH_ZETA 50 //lin minimum number of state switchs to reset reno_count |
25 | 25 | ||
26 | #define TCP_SCALABLE_AI_CNT 100U | 26 | #define TCP_SCALABLE_AI_CNT 100U |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 588f47af5faf..599374f65c76 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -189,7 +189,7 @@ static int udp_lib_lport_inuse2(struct net *net, __u16 num, | |||
189 | * @sk: socket struct in question | 189 | * @sk: socket struct in question |
190 | * @snum: port number to look up | 190 | * @snum: port number to look up |
191 | * @saddr_comp: AF-dependent comparison of bound local IP addresses | 191 | * @saddr_comp: AF-dependent comparison of bound local IP addresses |
192 | * @hash2_nulladdr: AF-dependant hash value in secondary hash chains, | 192 | * @hash2_nulladdr: AF-dependent hash value in secondary hash chains, |
193 | * with NULL address | 193 | * with NULL address |
194 | */ | 194 | */ |
195 | int udp_lib_get_port(struct sock *sk, unsigned short snum, | 195 | int udp_lib_get_port(struct sock *sk, unsigned short snum, |
@@ -578,7 +578,7 @@ found: | |||
578 | void __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable) | 578 | void __udp4_lib_err(struct sk_buff *skb, u32 info, struct udp_table *udptable) |
579 | { | 579 | { |
580 | struct inet_sock *inet; | 580 | struct inet_sock *inet; |
581 | struct iphdr *iph = (struct iphdr *)skb->data; | 581 | const struct iphdr *iph = (const struct iphdr *)skb->data; |
582 | struct udphdr *uh = (struct udphdr *)(skb->data+(iph->ihl<<2)); | 582 | struct udphdr *uh = (struct udphdr *)(skb->data+(iph->ihl<<2)); |
583 | const int type = icmp_hdr(skb)->type; | 583 | const int type = icmp_hdr(skb)->type; |
584 | const int code = icmp_hdr(skb)->code; | 584 | const int code = icmp_hdr(skb)->code; |
@@ -706,12 +706,11 @@ static void udp4_hwcsum(struct sk_buff *skb, __be32 src, __be32 dst) | |||
706 | } | 706 | } |
707 | } | 707 | } |
708 | 708 | ||
709 | static int udp_send_skb(struct sk_buff *skb, __be32 daddr, __be32 dport) | 709 | static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4) |
710 | { | 710 | { |
711 | struct sock *sk = skb->sk; | 711 | struct sock *sk = skb->sk; |
712 | struct inet_sock *inet = inet_sk(sk); | 712 | struct inet_sock *inet = inet_sk(sk); |
713 | struct udphdr *uh; | 713 | struct udphdr *uh; |
714 | struct rtable *rt = (struct rtable *)skb_dst(skb); | ||
715 | int err = 0; | 714 | int err = 0; |
716 | int is_udplite = IS_UDPLITE(sk); | 715 | int is_udplite = IS_UDPLITE(sk); |
717 | int offset = skb_transport_offset(skb); | 716 | int offset = skb_transport_offset(skb); |
@@ -723,7 +722,7 @@ static int udp_send_skb(struct sk_buff *skb, __be32 daddr, __be32 dport) | |||
723 | */ | 722 | */ |
724 | uh = udp_hdr(skb); | 723 | uh = udp_hdr(skb); |
725 | uh->source = inet->inet_sport; | 724 | uh->source = inet->inet_sport; |
726 | uh->dest = dport; | 725 | uh->dest = fl4->fl4_dport; |
727 | uh->len = htons(len); | 726 | uh->len = htons(len); |
728 | uh->check = 0; | 727 | uh->check = 0; |
729 | 728 | ||
@@ -737,14 +736,14 @@ static int udp_send_skb(struct sk_buff *skb, __be32 daddr, __be32 dport) | |||
737 | 736 | ||
738 | } else if (skb->ip_summed == CHECKSUM_PARTIAL) { /* UDP hardware csum */ | 737 | } else if (skb->ip_summed == CHECKSUM_PARTIAL) { /* UDP hardware csum */ |
739 | 738 | ||
740 | udp4_hwcsum(skb, rt->rt_src, daddr); | 739 | udp4_hwcsum(skb, fl4->saddr, fl4->daddr); |
741 | goto send; | 740 | goto send; |
742 | 741 | ||
743 | } else | 742 | } else |
744 | csum = udp_csum(skb); | 743 | csum = udp_csum(skb); |
745 | 744 | ||
746 | /* add protocol-dependent pseudo-header */ | 745 | /* add protocol-dependent pseudo-header */ |
747 | uh->check = csum_tcpudp_magic(rt->rt_src, daddr, len, | 746 | uh->check = csum_tcpudp_magic(fl4->saddr, fl4->daddr, len, |
748 | sk->sk_protocol, csum); | 747 | sk->sk_protocol, csum); |
749 | if (uh->check == 0) | 748 | if (uh->check == 0) |
750 | uh->check = CSUM_MANGLED_0; | 749 | uh->check = CSUM_MANGLED_0; |
@@ -774,11 +773,11 @@ static int udp_push_pending_frames(struct sock *sk) | |||
774 | struct sk_buff *skb; | 773 | struct sk_buff *skb; |
775 | int err = 0; | 774 | int err = 0; |
776 | 775 | ||
777 | skb = ip_finish_skb(sk); | 776 | skb = ip_finish_skb(sk, fl4); |
778 | if (!skb) | 777 | if (!skb) |
779 | goto out; | 778 | goto out; |
780 | 779 | ||
781 | err = udp_send_skb(skb, fl4->daddr, fl4->fl4_dport); | 780 | err = udp_send_skb(skb, fl4); |
782 | 781 | ||
783 | out: | 782 | out: |
784 | up->len = 0; | 783 | up->len = 0; |
@@ -791,6 +790,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
791 | { | 790 | { |
792 | struct inet_sock *inet = inet_sk(sk); | 791 | struct inet_sock *inet = inet_sk(sk); |
793 | struct udp_sock *up = udp_sk(sk); | 792 | struct udp_sock *up = udp_sk(sk); |
793 | struct flowi4 fl4_stack; | ||
794 | struct flowi4 *fl4; | 794 | struct flowi4 *fl4; |
795 | int ulen = len; | 795 | int ulen = len; |
796 | struct ipcm_cookie ipc; | 796 | struct ipcm_cookie ipc; |
@@ -804,6 +804,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
804 | int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; | 804 | int corkreq = up->corkflag || msg->msg_flags&MSG_MORE; |
805 | int (*getfrag)(void *, char *, int, int, int, struct sk_buff *); | 805 | int (*getfrag)(void *, char *, int, int, int, struct sk_buff *); |
806 | struct sk_buff *skb; | 806 | struct sk_buff *skb; |
807 | struct ip_options_data opt_copy; | ||
807 | 808 | ||
808 | if (len > 0xFFFF) | 809 | if (len > 0xFFFF) |
809 | return -EMSGSIZE; | 810 | return -EMSGSIZE; |
@@ -820,6 +821,7 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
820 | 821 | ||
821 | getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag; | 822 | getfrag = is_udplite ? udplite_getfrag : ip_generic_getfrag; |
822 | 823 | ||
824 | fl4 = &inet->cork.fl.u.ip4; | ||
823 | if (up->pending) { | 825 | if (up->pending) { |
824 | /* | 826 | /* |
825 | * There are pending frames. | 827 | * There are pending frames. |
@@ -877,22 +879,32 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
877 | free = 1; | 879 | free = 1; |
878 | connected = 0; | 880 | connected = 0; |
879 | } | 881 | } |
880 | if (!ipc.opt) | 882 | if (!ipc.opt) { |
881 | ipc.opt = inet->opt; | 883 | struct ip_options_rcu *inet_opt; |
884 | |||
885 | rcu_read_lock(); | ||
886 | inet_opt = rcu_dereference(inet->inet_opt); | ||
887 | if (inet_opt) { | ||
888 | memcpy(&opt_copy, inet_opt, | ||
889 | sizeof(*inet_opt) + inet_opt->opt.optlen); | ||
890 | ipc.opt = &opt_copy.opt; | ||
891 | } | ||
892 | rcu_read_unlock(); | ||
893 | } | ||
882 | 894 | ||
883 | saddr = ipc.addr; | 895 | saddr = ipc.addr; |
884 | ipc.addr = faddr = daddr; | 896 | ipc.addr = faddr = daddr; |
885 | 897 | ||
886 | if (ipc.opt && ipc.opt->srr) { | 898 | if (ipc.opt && ipc.opt->opt.srr) { |
887 | if (!daddr) | 899 | if (!daddr) |
888 | return -EINVAL; | 900 | return -EINVAL; |
889 | faddr = ipc.opt->faddr; | 901 | faddr = ipc.opt->opt.faddr; |
890 | connected = 0; | 902 | connected = 0; |
891 | } | 903 | } |
892 | tos = RT_TOS(inet->tos); | 904 | tos = RT_TOS(inet->tos); |
893 | if (sock_flag(sk, SOCK_LOCALROUTE) || | 905 | if (sock_flag(sk, SOCK_LOCALROUTE) || |
894 | (msg->msg_flags & MSG_DONTROUTE) || | 906 | (msg->msg_flags & MSG_DONTROUTE) || |
895 | (ipc.opt && ipc.opt->is_strictroute)) { | 907 | (ipc.opt && ipc.opt->opt.is_strictroute)) { |
896 | tos |= RTO_ONLINK; | 908 | tos |= RTO_ONLINK; |
897 | connected = 0; | 909 | connected = 0; |
898 | } | 910 | } |
@@ -909,22 +921,16 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
909 | rt = (struct rtable *)sk_dst_check(sk, 0); | 921 | rt = (struct rtable *)sk_dst_check(sk, 0); |
910 | 922 | ||
911 | if (rt == NULL) { | 923 | if (rt == NULL) { |
912 | struct flowi4 fl4 = { | ||
913 | .flowi4_oif = ipc.oif, | ||
914 | .flowi4_mark = sk->sk_mark, | ||
915 | .daddr = faddr, | ||
916 | .saddr = saddr, | ||
917 | .flowi4_tos = tos, | ||
918 | .flowi4_proto = sk->sk_protocol, | ||
919 | .flowi4_flags = (inet_sk_flowi_flags(sk) | | ||
920 | FLOWI_FLAG_CAN_SLEEP), | ||
921 | .fl4_sport = inet->inet_sport, | ||
922 | .fl4_dport = dport, | ||
923 | }; | ||
924 | struct net *net = sock_net(sk); | 924 | struct net *net = sock_net(sk); |
925 | 925 | ||
926 | security_sk_classify_flow(sk, flowi4_to_flowi(&fl4)); | 926 | fl4 = &fl4_stack; |
927 | rt = ip_route_output_flow(net, &fl4, sk); | 927 | flowi4_init_output(fl4, ipc.oif, sk->sk_mark, tos, |
928 | RT_SCOPE_UNIVERSE, sk->sk_protocol, | ||
929 | inet_sk_flowi_flags(sk)|FLOWI_FLAG_CAN_SLEEP, | ||
930 | faddr, saddr, dport, inet->inet_sport); | ||
931 | |||
932 | security_sk_classify_flow(sk, flowi4_to_flowi(fl4)); | ||
933 | rt = ip_route_output_flow(net, fl4, sk); | ||
928 | if (IS_ERR(rt)) { | 934 | if (IS_ERR(rt)) { |
929 | err = PTR_ERR(rt); | 935 | err = PTR_ERR(rt); |
930 | rt = NULL; | 936 | rt = NULL; |
@@ -945,18 +951,18 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
945 | goto do_confirm; | 951 | goto do_confirm; |
946 | back_from_confirm: | 952 | back_from_confirm: |
947 | 953 | ||
948 | saddr = rt->rt_src; | 954 | saddr = fl4->saddr; |
949 | if (!ipc.addr) | 955 | if (!ipc.addr) |
950 | daddr = ipc.addr = rt->rt_dst; | 956 | daddr = ipc.addr = fl4->daddr; |
951 | 957 | ||
952 | /* Lockless fast path for the non-corking case. */ | 958 | /* Lockless fast path for the non-corking case. */ |
953 | if (!corkreq) { | 959 | if (!corkreq) { |
954 | skb = ip_make_skb(sk, getfrag, msg->msg_iov, ulen, | 960 | skb = ip_make_skb(sk, fl4, getfrag, msg->msg_iov, ulen, |
955 | sizeof(struct udphdr), &ipc, &rt, | 961 | sizeof(struct udphdr), &ipc, &rt, |
956 | msg->msg_flags); | 962 | msg->msg_flags); |
957 | err = PTR_ERR(skb); | 963 | err = PTR_ERR(skb); |
958 | if (skb && !IS_ERR(skb)) | 964 | if (skb && !IS_ERR(skb)) |
959 | err = udp_send_skb(skb, daddr, dport); | 965 | err = udp_send_skb(skb, fl4); |
960 | goto out; | 966 | goto out; |
961 | } | 967 | } |
962 | 968 | ||
@@ -982,9 +988,9 @@ back_from_confirm: | |||
982 | 988 | ||
983 | do_append_data: | 989 | do_append_data: |
984 | up->len += ulen; | 990 | up->len += ulen; |
985 | err = ip_append_data(sk, getfrag, msg->msg_iov, ulen, | 991 | err = ip_append_data(sk, fl4, getfrag, msg->msg_iov, ulen, |
986 | sizeof(struct udphdr), &ipc, &rt, | 992 | sizeof(struct udphdr), &ipc, &rt, |
987 | corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags); | 993 | corkreq ? msg->msg_flags|MSG_MORE : msg->msg_flags); |
988 | if (err) | 994 | if (err) |
989 | udp_flush_pending_frames(sk); | 995 | udp_flush_pending_frames(sk); |
990 | else if (!corkreq) | 996 | else if (!corkreq) |
@@ -1024,6 +1030,7 @@ EXPORT_SYMBOL(udp_sendmsg); | |||
1024 | int udp_sendpage(struct sock *sk, struct page *page, int offset, | 1030 | int udp_sendpage(struct sock *sk, struct page *page, int offset, |
1025 | size_t size, int flags) | 1031 | size_t size, int flags) |
1026 | { | 1032 | { |
1033 | struct inet_sock *inet = inet_sk(sk); | ||
1027 | struct udp_sock *up = udp_sk(sk); | 1034 | struct udp_sock *up = udp_sk(sk); |
1028 | int ret; | 1035 | int ret; |
1029 | 1036 | ||
@@ -1048,7 +1055,8 @@ int udp_sendpage(struct sock *sk, struct page *page, int offset, | |||
1048 | return -EINVAL; | 1055 | return -EINVAL; |
1049 | } | 1056 | } |
1050 | 1057 | ||
1051 | ret = ip_append_page(sk, page, offset, size, flags); | 1058 | ret = ip_append_page(sk, &inet->cork.fl.u.ip4, |
1059 | page, offset, size, flags); | ||
1052 | if (ret == -EOPNOTSUPP) { | 1060 | if (ret == -EOPNOTSUPP) { |
1053 | release_sock(sk); | 1061 | release_sock(sk); |
1054 | return sock_no_sendpage(sk->sk_socket, page, offset, | 1062 | return sock_no_sendpage(sk->sk_socket, page, offset, |
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index 571aa96a175c..2d51840e53a1 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c | |||
@@ -69,7 +69,7 @@ int xfrm4_prepare_output(struct xfrm_state *x, struct sk_buff *skb) | |||
69 | } | 69 | } |
70 | EXPORT_SYMBOL(xfrm4_prepare_output); | 70 | EXPORT_SYMBOL(xfrm4_prepare_output); |
71 | 71 | ||
72 | static int xfrm4_output_finish(struct sk_buff *skb) | 72 | int xfrm4_output_finish(struct sk_buff *skb) |
73 | { | 73 | { |
74 | #ifdef CONFIG_NETFILTER | 74 | #ifdef CONFIG_NETFILTER |
75 | if (!skb_dst(skb)->xfrm) { | 75 | if (!skb_dst(skb)->xfrm) { |
@@ -86,7 +86,11 @@ static int xfrm4_output_finish(struct sk_buff *skb) | |||
86 | 86 | ||
87 | int xfrm4_output(struct sk_buff *skb) | 87 | int xfrm4_output(struct sk_buff *skb) |
88 | { | 88 | { |
89 | struct dst_entry *dst = skb_dst(skb); | ||
90 | struct xfrm_state *x = dst->xfrm; | ||
91 | |||
89 | return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb, | 92 | return NF_HOOK_COND(NFPROTO_IPV4, NF_INET_POST_ROUTING, skb, |
90 | NULL, skb_dst(skb)->dev, xfrm4_output_finish, | 93 | NULL, dst->dev, |
94 | x->outer_mode->afinfo->output_finish, | ||
91 | !(IPCB(skb)->flags & IPSKB_REROUTED)); | 95 | !(IPCB(skb)->flags & IPSKB_REROUTED)); |
92 | } | 96 | } |
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index 13e0e7f659ff..981e43eaf704 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c | |||
@@ -18,38 +18,46 @@ | |||
18 | 18 | ||
19 | static struct xfrm_policy_afinfo xfrm4_policy_afinfo; | 19 | static struct xfrm_policy_afinfo xfrm4_policy_afinfo; |
20 | 20 | ||
21 | static struct dst_entry *xfrm4_dst_lookup(struct net *net, int tos, | 21 | static struct dst_entry *__xfrm4_dst_lookup(struct net *net, struct flowi4 *fl4, |
22 | const xfrm_address_t *saddr, | 22 | int tos, |
23 | const xfrm_address_t *daddr) | 23 | const xfrm_address_t *saddr, |
24 | const xfrm_address_t *daddr) | ||
24 | { | 25 | { |
25 | struct flowi4 fl4 = { | ||
26 | .daddr = daddr->a4, | ||
27 | .flowi4_tos = tos, | ||
28 | }; | ||
29 | struct rtable *rt; | 26 | struct rtable *rt; |
30 | 27 | ||
28 | memset(fl4, 0, sizeof(*fl4)); | ||
29 | fl4->daddr = daddr->a4; | ||
30 | fl4->flowi4_tos = tos; | ||
31 | if (saddr) | 31 | if (saddr) |
32 | fl4.saddr = saddr->a4; | 32 | fl4->saddr = saddr->a4; |
33 | 33 | ||
34 | rt = __ip_route_output_key(net, &fl4); | 34 | rt = __ip_route_output_key(net, fl4); |
35 | if (!IS_ERR(rt)) | 35 | if (!IS_ERR(rt)) |
36 | return &rt->dst; | 36 | return &rt->dst; |
37 | 37 | ||
38 | return ERR_CAST(rt); | 38 | return ERR_CAST(rt); |
39 | } | 39 | } |
40 | 40 | ||
41 | static struct dst_entry *xfrm4_dst_lookup(struct net *net, int tos, | ||
42 | const xfrm_address_t *saddr, | ||
43 | const xfrm_address_t *daddr) | ||
44 | { | ||
45 | struct flowi4 fl4; | ||
46 | |||
47 | return __xfrm4_dst_lookup(net, &fl4, tos, saddr, daddr); | ||
48 | } | ||
49 | |||
41 | static int xfrm4_get_saddr(struct net *net, | 50 | static int xfrm4_get_saddr(struct net *net, |
42 | xfrm_address_t *saddr, xfrm_address_t *daddr) | 51 | xfrm_address_t *saddr, xfrm_address_t *daddr) |
43 | { | 52 | { |
44 | struct dst_entry *dst; | 53 | struct dst_entry *dst; |
45 | struct rtable *rt; | 54 | struct flowi4 fl4; |
46 | 55 | ||
47 | dst = xfrm4_dst_lookup(net, 0, NULL, daddr); | 56 | dst = __xfrm4_dst_lookup(net, &fl4, 0, NULL, daddr); |
48 | if (IS_ERR(dst)) | 57 | if (IS_ERR(dst)) |
49 | return -EHOSTUNREACH; | 58 | return -EHOSTUNREACH; |
50 | 59 | ||
51 | rt = (struct rtable *)dst; | 60 | saddr->a4 = fl4.saddr; |
52 | saddr->a4 = rt->rt_src; | ||
53 | dst_release(dst); | 61 | dst_release(dst); |
54 | return 0; | 62 | return 0; |
55 | } | 63 | } |
@@ -73,7 +81,8 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, | |||
73 | 81 | ||
74 | rt->rt_key_dst = fl4->daddr; | 82 | rt->rt_key_dst = fl4->daddr; |
75 | rt->rt_key_src = fl4->saddr; | 83 | rt->rt_key_src = fl4->saddr; |
76 | rt->rt_tos = fl4->flowi4_tos; | 84 | rt->rt_key_tos = fl4->flowi4_tos; |
85 | rt->rt_route_iif = fl4->flowi4_iif; | ||
77 | rt->rt_iif = fl4->flowi4_iif; | 86 | rt->rt_iif = fl4->flowi4_iif; |
78 | rt->rt_oif = fl4->flowi4_oif; | 87 | rt->rt_oif = fl4->flowi4_oif; |
79 | rt->rt_mark = fl4->flowi4_mark; | 88 | rt->rt_mark = fl4->flowi4_mark; |
@@ -101,7 +110,7 @@ static int xfrm4_fill_dst(struct xfrm_dst *xdst, struct net_device *dev, | |||
101 | static void | 110 | static void |
102 | _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) | 111 | _decode_session4(struct sk_buff *skb, struct flowi *fl, int reverse) |
103 | { | 112 | { |
104 | struct iphdr *iph = ip_hdr(skb); | 113 | const struct iphdr *iph = ip_hdr(skb); |
105 | u8 *xprth = skb_network_header(skb) + iph->ihl * 4; | 114 | u8 *xprth = skb_network_header(skb) + iph->ihl * 4; |
106 | struct flowi4 *fl4 = &fl->u.ip4; | 115 | struct flowi4 *fl4 = &fl->u.ip4; |
107 | 116 | ||
diff --git a/net/ipv4/xfrm4_state.c b/net/ipv4/xfrm4_state.c index 1717c64628d1..d9ac0a0058b5 100644 --- a/net/ipv4/xfrm4_state.c +++ b/net/ipv4/xfrm4_state.c | |||
@@ -55,7 +55,7 @@ xfrm4_init_temprop(struct xfrm_state *x, const struct xfrm_tmpl *tmpl, | |||
55 | 55 | ||
56 | int xfrm4_extract_header(struct sk_buff *skb) | 56 | int xfrm4_extract_header(struct sk_buff *skb) |
57 | { | 57 | { |
58 | struct iphdr *iph = ip_hdr(skb); | 58 | const struct iphdr *iph = ip_hdr(skb); |
59 | 59 | ||
60 | XFRM_MODE_SKB_CB(skb)->ihl = sizeof(*iph); | 60 | XFRM_MODE_SKB_CB(skb)->ihl = sizeof(*iph); |
61 | XFRM_MODE_SKB_CB(skb)->id = iph->id; | 61 | XFRM_MODE_SKB_CB(skb)->id = iph->id; |
@@ -78,6 +78,7 @@ static struct xfrm_state_afinfo xfrm4_state_afinfo = { | |||
78 | .init_tempsel = __xfrm4_init_tempsel, | 78 | .init_tempsel = __xfrm4_init_tempsel, |
79 | .init_temprop = xfrm4_init_temprop, | 79 | .init_temprop = xfrm4_init_temprop, |
80 | .output = xfrm4_output, | 80 | .output = xfrm4_output, |
81 | .output_finish = xfrm4_output_finish, | ||
81 | .extract_input = xfrm4_extract_input, | 82 | .extract_input = xfrm4_extract_input, |
82 | .extract_output = xfrm4_extract_output, | 83 | .extract_output = xfrm4_extract_output, |
83 | .transport_finish = xfrm4_transport_finish, | 84 | .transport_finish = xfrm4_transport_finish, |
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 3daaf3c7703c..f2f9b2e3cfe9 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -825,6 +825,8 @@ static void ipv6_del_addr(struct inet6_ifaddr *ifp) | |||
825 | dst_release(&rt->dst); | 825 | dst_release(&rt->dst); |
826 | } | 826 | } |
827 | 827 | ||
828 | /* clean up prefsrc entries */ | ||
829 | rt6_remove_prefsrc(ifp); | ||
828 | out: | 830 | out: |
829 | in6_ifa_put(ifp); | 831 | in6_ifa_put(ifp); |
830 | } | 832 | } |
@@ -1084,7 +1086,7 @@ static int ipv6_get_saddr_eval(struct net *net, | |||
1084 | case IPV6_SADDR_RULE_PRIVACY: | 1086 | case IPV6_SADDR_RULE_PRIVACY: |
1085 | { | 1087 | { |
1086 | /* Rule 7: Prefer public address | 1088 | /* Rule 7: Prefer public address |
1087 | * Note: prefer temprary address if use_tempaddr >= 2 | 1089 | * Note: prefer temporary address if use_tempaddr >= 2 |
1088 | */ | 1090 | */ |
1089 | int preftmp = dst->prefs & (IPV6_PREFER_SRC_PUBLIC|IPV6_PREFER_SRC_TMP) ? | 1091 | int preftmp = dst->prefs & (IPV6_PREFER_SRC_PUBLIC|IPV6_PREFER_SRC_TMP) ? |
1090 | !!(dst->prefs & IPV6_PREFER_SRC_TMP) : | 1092 | !!(dst->prefs & IPV6_PREFER_SRC_TMP) : |
@@ -1281,7 +1283,7 @@ static int ipv6_count_addresses(struct inet6_dev *idev) | |||
1281 | return cnt; | 1283 | return cnt; |
1282 | } | 1284 | } |
1283 | 1285 | ||
1284 | int ipv6_chk_addr(struct net *net, struct in6_addr *addr, | 1286 | int ipv6_chk_addr(struct net *net, const struct in6_addr *addr, |
1285 | struct net_device *dev, int strict) | 1287 | struct net_device *dev, int strict) |
1286 | { | 1288 | { |
1287 | struct inet6_ifaddr *ifp; | 1289 | struct inet6_ifaddr *ifp; |
@@ -1324,7 +1326,7 @@ static bool ipv6_chk_same_addr(struct net *net, const struct in6_addr *addr, | |||
1324 | return false; | 1326 | return false; |
1325 | } | 1327 | } |
1326 | 1328 | ||
1327 | int ipv6_chk_prefix(struct in6_addr *addr, struct net_device *dev) | 1329 | int ipv6_chk_prefix(const struct in6_addr *addr, struct net_device *dev) |
1328 | { | 1330 | { |
1329 | struct inet6_dev *idev; | 1331 | struct inet6_dev *idev; |
1330 | struct inet6_ifaddr *ifa; | 1332 | struct inet6_ifaddr *ifa; |
@@ -1455,7 +1457,7 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp) | |||
1455 | 1457 | ||
1456 | /* Join to solicited addr multicast group. */ | 1458 | /* Join to solicited addr multicast group. */ |
1457 | 1459 | ||
1458 | void addrconf_join_solict(struct net_device *dev, struct in6_addr *addr) | 1460 | void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr) |
1459 | { | 1461 | { |
1460 | struct in6_addr maddr; | 1462 | struct in6_addr maddr; |
1461 | 1463 | ||
@@ -1466,7 +1468,7 @@ void addrconf_join_solict(struct net_device *dev, struct in6_addr *addr) | |||
1466 | ipv6_dev_mc_inc(dev, &maddr); | 1468 | ipv6_dev_mc_inc(dev, &maddr); |
1467 | } | 1469 | } |
1468 | 1470 | ||
1469 | void addrconf_leave_solict(struct inet6_dev *idev, struct in6_addr *addr) | 1471 | void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr) |
1470 | { | 1472 | { |
1471 | struct in6_addr maddr; | 1473 | struct in6_addr maddr; |
1472 | 1474 | ||
@@ -1968,7 +1970,7 @@ ok: | |||
1968 | * to the stored lifetime since we'll | 1970 | * to the stored lifetime since we'll |
1969 | * be updating the timestamp below, | 1971 | * be updating the timestamp below, |
1970 | * else we'll set it back to the | 1972 | * else we'll set it back to the |
1971 | * minumum. | 1973 | * minimum. |
1972 | */ | 1974 | */ |
1973 | if (prefered_lft != ifp->prefered_lft) { | 1975 | if (prefered_lft != ifp->prefered_lft) { |
1974 | valid_lft = stored_lft; | 1976 | valid_lft = stored_lft; |
@@ -2111,7 +2113,7 @@ err_exit: | |||
2111 | /* | 2113 | /* |
2112 | * Manual configuration of address on an interface | 2114 | * Manual configuration of address on an interface |
2113 | */ | 2115 | */ |
2114 | static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx, | 2116 | static int inet6_addr_add(struct net *net, int ifindex, const struct in6_addr *pfx, |
2115 | unsigned int plen, __u8 ifa_flags, __u32 prefered_lft, | 2117 | unsigned int plen, __u8 ifa_flags, __u32 prefered_lft, |
2116 | __u32 valid_lft) | 2118 | __u32 valid_lft) |
2117 | { | 2119 | { |
@@ -2185,7 +2187,7 @@ static int inet6_addr_add(struct net *net, int ifindex, struct in6_addr *pfx, | |||
2185 | return PTR_ERR(ifp); | 2187 | return PTR_ERR(ifp); |
2186 | } | 2188 | } |
2187 | 2189 | ||
2188 | static int inet6_addr_del(struct net *net, int ifindex, struct in6_addr *pfx, | 2190 | static int inet6_addr_del(struct net *net, int ifindex, const struct in6_addr *pfx, |
2189 | unsigned int plen) | 2191 | unsigned int plen) |
2190 | { | 2192 | { |
2191 | struct inet6_ifaddr *ifp; | 2193 | struct inet6_ifaddr *ifp; |
@@ -2348,7 +2350,7 @@ static void init_loopback(struct net_device *dev) | |||
2348 | add_addr(idev, &in6addr_loopback, 128, IFA_HOST); | 2350 | add_addr(idev, &in6addr_loopback, 128, IFA_HOST); |
2349 | } | 2351 | } |
2350 | 2352 | ||
2351 | static void addrconf_add_linklocal(struct inet6_dev *idev, struct in6_addr *addr) | 2353 | static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr *addr) |
2352 | { | 2354 | { |
2353 | struct inet6_ifaddr * ifp; | 2355 | struct inet6_ifaddr * ifp; |
2354 | u32 addr_flags = IFA_F_PERMANENT; | 2356 | u32 addr_flags = IFA_F_PERMANENT; |
@@ -3119,7 +3121,7 @@ void if6_proc_exit(void) | |||
3119 | 3121 | ||
3120 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) | 3122 | #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE) |
3121 | /* Check if address is a home address configured on any interface. */ | 3123 | /* Check if address is a home address configured on any interface. */ |
3122 | int ipv6_chk_home_addr(struct net *net, struct in6_addr *addr) | 3124 | int ipv6_chk_home_addr(struct net *net, const struct in6_addr *addr) |
3123 | { | 3125 | { |
3124 | int ret = 0; | 3126 | int ret = 0; |
3125 | struct inet6_ifaddr *ifp = NULL; | 3127 | struct inet6_ifaddr *ifp = NULL; |
@@ -4537,7 +4539,7 @@ static void __addrconf_sysctl_unregister(struct ipv6_devconf *p) | |||
4537 | 4539 | ||
4538 | t = p->sysctl; | 4540 | t = p->sysctl; |
4539 | p->sysctl = NULL; | 4541 | p->sysctl = NULL; |
4540 | unregister_sysctl_table(t->sysctl_header); | 4542 | unregister_net_sysctl_table(t->sysctl_header); |
4541 | kfree(t->dev_name); | 4543 | kfree(t->dev_name); |
4542 | kfree(t); | 4544 | kfree(t); |
4543 | } | 4545 | } |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 4b13d5d8890e..b7919f901fbf 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -740,7 +740,7 @@ static int ipv6_gso_pull_exthdrs(struct sk_buff *skb, int proto) | |||
740 | 740 | ||
741 | static int ipv6_gso_send_check(struct sk_buff *skb) | 741 | static int ipv6_gso_send_check(struct sk_buff *skb) |
742 | { | 742 | { |
743 | struct ipv6hdr *ipv6h; | 743 | const struct ipv6hdr *ipv6h; |
744 | const struct inet6_protocol *ops; | 744 | const struct inet6_protocol *ops; |
745 | int err = -EINVAL; | 745 | int err = -EINVAL; |
746 | 746 | ||
@@ -1113,7 +1113,7 @@ static int __init inet6_init(void) | |||
1113 | /* | 1113 | /* |
1114 | * ipngwg API draft makes clear that the correct semantics | 1114 | * ipngwg API draft makes clear that the correct semantics |
1115 | * for TCP and UDP is to consider one TCP and UDP instance | 1115 | * for TCP and UDP is to consider one TCP and UDP instance |
1116 | * in a host availiable by both INET and INET6 APIs and | 1116 | * in a host available by both INET and INET6 APIs and |
1117 | * able to communicate via both network protocols. | 1117 | * able to communicate via both network protocols. |
1118 | */ | 1118 | */ |
1119 | 1119 | ||
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index 0e5e943446f0..674255f5e6b7 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c | |||
@@ -44,7 +44,7 @@ | |||
44 | 44 | ||
45 | #include <net/checksum.h> | 45 | #include <net/checksum.h> |
46 | 46 | ||
47 | static int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr); | 47 | static int ipv6_dev_ac_dec(struct net_device *dev, const struct in6_addr *addr); |
48 | 48 | ||
49 | /* Big ac list lock for all the sockets */ | 49 | /* Big ac list lock for all the sockets */ |
50 | static DEFINE_RWLOCK(ipv6_sk_ac_lock); | 50 | static DEFINE_RWLOCK(ipv6_sk_ac_lock); |
@@ -54,7 +54,7 @@ static DEFINE_RWLOCK(ipv6_sk_ac_lock); | |||
54 | * socket join an anycast group | 54 | * socket join an anycast group |
55 | */ | 55 | */ |
56 | 56 | ||
57 | int ipv6_sock_ac_join(struct sock *sk, int ifindex, struct in6_addr *addr) | 57 | int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr) |
58 | { | 58 | { |
59 | struct ipv6_pinfo *np = inet6_sk(sk); | 59 | struct ipv6_pinfo *np = inet6_sk(sk); |
60 | struct net_device *dev = NULL; | 60 | struct net_device *dev = NULL; |
@@ -145,7 +145,7 @@ error: | |||
145 | /* | 145 | /* |
146 | * socket leave an anycast group | 146 | * socket leave an anycast group |
147 | */ | 147 | */ |
148 | int ipv6_sock_ac_drop(struct sock *sk, int ifindex, struct in6_addr *addr) | 148 | int ipv6_sock_ac_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) |
149 | { | 149 | { |
150 | struct ipv6_pinfo *np = inet6_sk(sk); | 150 | struct ipv6_pinfo *np = inet6_sk(sk); |
151 | struct net_device *dev; | 151 | struct net_device *dev; |
@@ -252,7 +252,7 @@ static void aca_put(struct ifacaddr6 *ac) | |||
252 | /* | 252 | /* |
253 | * device anycast group inc (add if not found) | 253 | * device anycast group inc (add if not found) |
254 | */ | 254 | */ |
255 | int ipv6_dev_ac_inc(struct net_device *dev, struct in6_addr *addr) | 255 | int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr) |
256 | { | 256 | { |
257 | struct ifacaddr6 *aca; | 257 | struct ifacaddr6 *aca; |
258 | struct inet6_dev *idev; | 258 | struct inet6_dev *idev; |
@@ -324,7 +324,7 @@ out: | |||
324 | /* | 324 | /* |
325 | * device anycast group decrement | 325 | * device anycast group decrement |
326 | */ | 326 | */ |
327 | int __ipv6_dev_ac_dec(struct inet6_dev *idev, struct in6_addr *addr) | 327 | int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr) |
328 | { | 328 | { |
329 | struct ifacaddr6 *aca, *prev_aca; | 329 | struct ifacaddr6 *aca, *prev_aca; |
330 | 330 | ||
@@ -358,7 +358,7 @@ int __ipv6_dev_ac_dec(struct inet6_dev *idev, struct in6_addr *addr) | |||
358 | } | 358 | } |
359 | 359 | ||
360 | /* called with rcu_read_lock() */ | 360 | /* called with rcu_read_lock() */ |
361 | static int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr) | 361 | static int ipv6_dev_ac_dec(struct net_device *dev, const struct in6_addr *addr) |
362 | { | 362 | { |
363 | struct inet6_dev *idev = __in6_dev_get(dev); | 363 | struct inet6_dev *idev = __in6_dev_get(dev); |
364 | 364 | ||
@@ -371,7 +371,7 @@ static int ipv6_dev_ac_dec(struct net_device *dev, struct in6_addr *addr) | |||
371 | * check if the interface has this anycast address | 371 | * check if the interface has this anycast address |
372 | * called with rcu_read_lock() | 372 | * called with rcu_read_lock() |
373 | */ | 373 | */ |
374 | static int ipv6_chk_acast_dev(struct net_device *dev, struct in6_addr *addr) | 374 | static int ipv6_chk_acast_dev(struct net_device *dev, const struct in6_addr *addr) |
375 | { | 375 | { |
376 | struct inet6_dev *idev; | 376 | struct inet6_dev *idev; |
377 | struct ifacaddr6 *aca; | 377 | struct ifacaddr6 *aca; |
@@ -392,7 +392,7 @@ static int ipv6_chk_acast_dev(struct net_device *dev, struct in6_addr *addr) | |||
392 | * check if given interface (or any, if dev==0) has this anycast address | 392 | * check if given interface (or any, if dev==0) has this anycast address |
393 | */ | 393 | */ |
394 | int ipv6_chk_acast_addr(struct net *net, struct net_device *dev, | 394 | int ipv6_chk_acast_addr(struct net *net, struct net_device *dev, |
395 | struct in6_addr *addr) | 395 | const struct in6_addr *addr) |
396 | { | 396 | { |
397 | int found = 0; | 397 | int found = 0; |
398 | 398 | ||
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 5aa8ec88f194..1ac7938dd9ec 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c | |||
@@ -371,7 +371,7 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
371 | iv = esp_tmp_iv(aead, tmp, seqhilen); | 371 | iv = esp_tmp_iv(aead, tmp, seqhilen); |
372 | req = esp_tmp_req(aead, iv); | 372 | req = esp_tmp_req(aead, iv); |
373 | asg = esp_req_sg(aead, req); | 373 | asg = esp_req_sg(aead, req); |
374 | sg = asg + 1; | 374 | sg = asg + sglists; |
375 | 375 | ||
376 | skb->ip_summed = CHECKSUM_NONE; | 376 | skb->ip_summed = CHECKSUM_NONE; |
377 | 377 | ||
@@ -430,7 +430,7 @@ static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
430 | u8 type, u8 code, int offset, __be32 info) | 430 | u8 type, u8 code, int offset, __be32 info) |
431 | { | 431 | { |
432 | struct net *net = dev_net(skb->dev); | 432 | struct net *net = dev_net(skb->dev); |
433 | struct ipv6hdr *iph = (struct ipv6hdr*)skb->data; | 433 | const struct ipv6hdr *iph = (const struct ipv6hdr *)skb->data; |
434 | struct ip_esp_hdr *esph = (struct ip_esp_hdr *)(skb->data + offset); | 434 | struct ip_esp_hdr *esph = (struct ip_esp_hdr *)(skb->data + offset); |
435 | struct xfrm_state *x; | 435 | struct xfrm_state *x; |
436 | 436 | ||
@@ -438,7 +438,8 @@ static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
438 | type != ICMPV6_PKT_TOOBIG) | 438 | type != ICMPV6_PKT_TOOBIG) |
439 | return; | 439 | return; |
440 | 440 | ||
441 | x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, esph->spi, IPPROTO_ESP, AF_INET6); | 441 | x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, |
442 | esph->spi, IPPROTO_ESP, AF_INET6); | ||
442 | if (!x) | 443 | if (!x) |
443 | return; | 444 | return; |
444 | printk(KERN_DEBUG "pmtu discovery on SA ESP/%08x/%pI6\n", | 445 | printk(KERN_DEBUG "pmtu discovery on SA ESP/%08x/%pI6\n", |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index 83cb4f9add81..11900417b1cc 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -372,7 +372,7 @@ void icmpv6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) | |||
372 | struct ipv6hdr *hdr = ipv6_hdr(skb); | 372 | struct ipv6hdr *hdr = ipv6_hdr(skb); |
373 | struct sock *sk; | 373 | struct sock *sk; |
374 | struct ipv6_pinfo *np; | 374 | struct ipv6_pinfo *np; |
375 | struct in6_addr *saddr = NULL; | 375 | const struct in6_addr *saddr = NULL; |
376 | struct dst_entry *dst; | 376 | struct dst_entry *dst; |
377 | struct icmp6hdr tmp_hdr; | 377 | struct icmp6hdr tmp_hdr; |
378 | struct flowi6 fl6; | 378 | struct flowi6 fl6; |
@@ -521,7 +521,7 @@ static void icmpv6_echo_reply(struct sk_buff *skb) | |||
521 | struct sock *sk; | 521 | struct sock *sk; |
522 | struct inet6_dev *idev; | 522 | struct inet6_dev *idev; |
523 | struct ipv6_pinfo *np; | 523 | struct ipv6_pinfo *np; |
524 | struct in6_addr *saddr = NULL; | 524 | const struct in6_addr *saddr = NULL; |
525 | struct icmp6hdr *icmph = icmp6_hdr(skb); | 525 | struct icmp6hdr *icmph = icmp6_hdr(skb); |
526 | struct icmp6hdr tmp_hdr; | 526 | struct icmp6hdr tmp_hdr; |
527 | struct flowi6 fl6; | 527 | struct flowi6 fl6; |
@@ -645,8 +645,8 @@ static int icmpv6_rcv(struct sk_buff *skb) | |||
645 | { | 645 | { |
646 | struct net_device *dev = skb->dev; | 646 | struct net_device *dev = skb->dev; |
647 | struct inet6_dev *idev = __in6_dev_get(dev); | 647 | struct inet6_dev *idev = __in6_dev_get(dev); |
648 | struct in6_addr *saddr, *daddr; | 648 | const struct in6_addr *saddr, *daddr; |
649 | struct ipv6hdr *orig_hdr; | 649 | const struct ipv6hdr *orig_hdr; |
650 | struct icmp6hdr *hdr; | 650 | struct icmp6hdr *hdr; |
651 | u8 type; | 651 | u8 type; |
652 | 652 | ||
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index 166054650466..8a58e8cf6646 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c | |||
@@ -44,7 +44,7 @@ int inet6_csk_bind_conflict(const struct sock *sk, | |||
44 | !sk2->sk_bound_dev_if || | 44 | !sk2->sk_bound_dev_if || |
45 | sk->sk_bound_dev_if == sk2->sk_bound_dev_if) && | 45 | sk->sk_bound_dev_if == sk2->sk_bound_dev_if) && |
46 | (!sk->sk_reuse || !sk2->sk_reuse || | 46 | (!sk->sk_reuse || !sk2->sk_reuse || |
47 | ((1 << sk2->sk_state) & (TCPF_LISTEN | TCPF_CLOSE))) && | 47 | sk2->sk_state == TCP_LISTEN) && |
48 | ipv6_rcv_saddr_equal(sk, sk2)) | 48 | ipv6_rcv_saddr_equal(sk, sk2)) |
49 | break; | 49 | break; |
50 | } | 50 | } |
@@ -203,7 +203,7 @@ struct dst_entry *__inet6_csk_dst_check(struct sock *sk, u32 cookie) | |||
203 | return dst; | 203 | return dst; |
204 | } | 204 | } |
205 | 205 | ||
206 | int inet6_csk_xmit(struct sk_buff *skb) | 206 | int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl_unused) |
207 | { | 207 | { |
208 | struct sock *sk = skb->sk; | 208 | struct sock *sk = skb->sk; |
209 | struct inet_sock *inet = inet_sk(sk); | 209 | struct inet_sock *inet = inet_sk(sk); |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 7548905e79e1..4076a0b14b20 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
@@ -134,9 +134,9 @@ static __inline__ u32 fib6_new_sernum(void) | |||
134 | # define BITOP_BE32_SWIZZLE 0 | 134 | # define BITOP_BE32_SWIZZLE 0 |
135 | #endif | 135 | #endif |
136 | 136 | ||
137 | static __inline__ __be32 addr_bit_set(void *token, int fn_bit) | 137 | static __inline__ __be32 addr_bit_set(const void *token, int fn_bit) |
138 | { | 138 | { |
139 | __be32 *addr = token; | 139 | const __be32 *addr = token; |
140 | /* | 140 | /* |
141 | * Here, | 141 | * Here, |
142 | * 1 << ((~fn_bit ^ BITOP_BE32_SWIZZLE) & 0x1f) | 142 | * 1 << ((~fn_bit ^ BITOP_BE32_SWIZZLE) & 0x1f) |
@@ -394,10 +394,11 @@ static int inet6_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) | |||
394 | arg.net = net; | 394 | arg.net = net; |
395 | w->args = &arg; | 395 | w->args = &arg; |
396 | 396 | ||
397 | rcu_read_lock(); | ||
397 | for (h = s_h; h < FIB6_TABLE_HASHSZ; h++, s_e = 0) { | 398 | for (h = s_h; h < FIB6_TABLE_HASHSZ; h++, s_e = 0) { |
398 | e = 0; | 399 | e = 0; |
399 | head = &net->ipv6.fib_table_hash[h]; | 400 | head = &net->ipv6.fib_table_hash[h]; |
400 | hlist_for_each_entry(tb, node, head, tb6_hlist) { | 401 | hlist_for_each_entry_rcu(tb, node, head, tb6_hlist) { |
401 | if (e < s_e) | 402 | if (e < s_e) |
402 | goto next; | 403 | goto next; |
403 | res = fib6_dump_table(tb, skb, cb); | 404 | res = fib6_dump_table(tb, skb, cb); |
@@ -408,6 +409,7 @@ next: | |||
408 | } | 409 | } |
409 | } | 410 | } |
410 | out: | 411 | out: |
412 | rcu_read_unlock(); | ||
411 | cb->args[1] = e; | 413 | cb->args[1] = e; |
412 | cb->args[0] = h; | 414 | cb->args[0] = h; |
413 | 415 | ||
@@ -822,7 +824,7 @@ st_failure: | |||
822 | 824 | ||
823 | struct lookup_args { | 825 | struct lookup_args { |
824 | int offset; /* key offset on rt6_info */ | 826 | int offset; /* key offset on rt6_info */ |
825 | struct in6_addr *addr; /* search key */ | 827 | const struct in6_addr *addr; /* search key */ |
826 | }; | 828 | }; |
827 | 829 | ||
828 | static struct fib6_node * fib6_lookup_1(struct fib6_node *root, | 830 | static struct fib6_node * fib6_lookup_1(struct fib6_node *root, |
@@ -881,8 +883,8 @@ static struct fib6_node * fib6_lookup_1(struct fib6_node *root, | |||
881 | return NULL; | 883 | return NULL; |
882 | } | 884 | } |
883 | 885 | ||
884 | struct fib6_node * fib6_lookup(struct fib6_node *root, struct in6_addr *daddr, | 886 | struct fib6_node * fib6_lookup(struct fib6_node *root, const struct in6_addr *daddr, |
885 | struct in6_addr *saddr) | 887 | const struct in6_addr *saddr) |
886 | { | 888 | { |
887 | struct fib6_node *fn; | 889 | struct fib6_node *fn; |
888 | struct lookup_args args[] = { | 890 | struct lookup_args args[] = { |
@@ -916,7 +918,7 @@ struct fib6_node * fib6_lookup(struct fib6_node *root, struct in6_addr *daddr, | |||
916 | 918 | ||
917 | 919 | ||
918 | static struct fib6_node * fib6_locate_1(struct fib6_node *root, | 920 | static struct fib6_node * fib6_locate_1(struct fib6_node *root, |
919 | struct in6_addr *addr, | 921 | const struct in6_addr *addr, |
920 | int plen, int offset) | 922 | int plen, int offset) |
921 | { | 923 | { |
922 | struct fib6_node *fn; | 924 | struct fib6_node *fn; |
@@ -946,8 +948,8 @@ static struct fib6_node * fib6_locate_1(struct fib6_node *root, | |||
946 | } | 948 | } |
947 | 949 | ||
948 | struct fib6_node * fib6_locate(struct fib6_node *root, | 950 | struct fib6_node * fib6_locate(struct fib6_node *root, |
949 | struct in6_addr *daddr, int dst_len, | 951 | const struct in6_addr *daddr, int dst_len, |
950 | struct in6_addr *saddr, int src_len) | 952 | const struct in6_addr *saddr, int src_len) |
951 | { | 953 | { |
952 | struct fib6_node *fn; | 954 | struct fib6_node *fn; |
953 | 955 | ||
diff --git a/net/ipv6/ip6_input.c b/net/ipv6/ip6_input.c index a83e9209cecc..027c7ff6f1e5 100644 --- a/net/ipv6/ip6_input.c +++ b/net/ipv6/ip6_input.c | |||
@@ -57,7 +57,7 @@ inline int ip6_rcv_finish( struct sk_buff *skb) | |||
57 | 57 | ||
58 | int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) | 58 | int ipv6_rcv(struct sk_buff *skb, struct net_device *dev, struct packet_type *pt, struct net_device *orig_dev) |
59 | { | 59 | { |
60 | struct ipv6hdr *hdr; | 60 | const struct ipv6hdr *hdr; |
61 | u32 pkt_len; | 61 | u32 pkt_len; |
62 | struct inet6_dev *idev; | 62 | struct inet6_dev *idev; |
63 | struct net *net = dev_net(skb->dev); | 63 | struct net *net = dev_net(skb->dev); |
@@ -186,7 +186,7 @@ resubmit: | |||
186 | int ret; | 186 | int ret; |
187 | 187 | ||
188 | if (ipprot->flags & INET6_PROTO_FINAL) { | 188 | if (ipprot->flags & INET6_PROTO_FINAL) { |
189 | struct ipv6hdr *hdr; | 189 | const struct ipv6hdr *hdr; |
190 | 190 | ||
191 | /* Free reference early: we don't need it any more, | 191 | /* Free reference early: we don't need it any more, |
192 | and it may hold ip_conntrack module loaded | 192 | and it may hold ip_conntrack module loaded |
@@ -242,7 +242,7 @@ int ip6_input(struct sk_buff *skb) | |||
242 | 242 | ||
243 | int ip6_mc_input(struct sk_buff *skb) | 243 | int ip6_mc_input(struct sk_buff *skb) |
244 | { | 244 | { |
245 | struct ipv6hdr *hdr; | 245 | const struct ipv6hdr *hdr; |
246 | int deliver; | 246 | int deliver; |
247 | 247 | ||
248 | IP6_UPD_PO_STATS_BH(dev_net(skb_dst(skb)->dev), | 248 | IP6_UPD_PO_STATS_BH(dev_net(skb_dst(skb)->dev), |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 18208876aa8a..9d4b165837d6 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -779,7 +779,7 @@ slow_path: | |||
779 | /* IF: it doesn't fit, use 'mtu' - the data space left */ | 779 | /* IF: it doesn't fit, use 'mtu' - the data space left */ |
780 | if (len > mtu) | 780 | if (len > mtu) |
781 | len = mtu; | 781 | len = mtu; |
782 | /* IF: we are not sending upto and including the packet end | 782 | /* IF: we are not sending up to and including the packet end |
783 | then align the next start on an eight byte boundary */ | 783 | then align the next start on an eight byte boundary */ |
784 | if (len < left) { | 784 | if (len < left) { |
785 | len &= ~7; | 785 | len &= ~7; |
@@ -869,9 +869,9 @@ fail: | |||
869 | return err; | 869 | return err; |
870 | } | 870 | } |
871 | 871 | ||
872 | static inline int ip6_rt_check(struct rt6key *rt_key, | 872 | static inline int ip6_rt_check(const struct rt6key *rt_key, |
873 | struct in6_addr *fl_addr, | 873 | const struct in6_addr *fl_addr, |
874 | struct in6_addr *addr_cache) | 874 | const struct in6_addr *addr_cache) |
875 | { | 875 | { |
876 | return (rt_key->plen != 128 || !ipv6_addr_equal(fl_addr, &rt_key->addr)) && | 876 | return (rt_key->plen != 128 || !ipv6_addr_equal(fl_addr, &rt_key->addr)) && |
877 | (addr_cache == NULL || !ipv6_addr_equal(fl_addr, addr_cache)); | 877 | (addr_cache == NULL || !ipv6_addr_equal(fl_addr, addr_cache)); |
@@ -879,7 +879,7 @@ static inline int ip6_rt_check(struct rt6key *rt_key, | |||
879 | 879 | ||
880 | static struct dst_entry *ip6_sk_dst_check(struct sock *sk, | 880 | static struct dst_entry *ip6_sk_dst_check(struct sock *sk, |
881 | struct dst_entry *dst, | 881 | struct dst_entry *dst, |
882 | struct flowi6 *fl6) | 882 | const struct flowi6 *fl6) |
883 | { | 883 | { |
884 | struct ipv6_pinfo *np = inet6_sk(sk); | 884 | struct ipv6_pinfo *np = inet6_sk(sk); |
885 | struct rt6_info *rt = (struct rt6_info *)dst; | 885 | struct rt6_info *rt = (struct rt6_info *)dst; |
@@ -930,10 +930,10 @@ static int ip6_dst_lookup_tail(struct sock *sk, | |||
930 | goto out_err_release; | 930 | goto out_err_release; |
931 | 931 | ||
932 | if (ipv6_addr_any(&fl6->saddr)) { | 932 | if (ipv6_addr_any(&fl6->saddr)) { |
933 | err = ipv6_dev_get_saddr(net, ip6_dst_idev(*dst)->dev, | 933 | struct rt6_info *rt = (struct rt6_info *) *dst; |
934 | &fl6->daddr, | 934 | err = ip6_route_get_saddr(net, rt, &fl6->daddr, |
935 | sk ? inet6_sk(sk)->srcprefs : 0, | 935 | sk ? inet6_sk(sk)->srcprefs : 0, |
936 | &fl6->saddr); | 936 | &fl6->saddr); |
937 | if (err) | 937 | if (err) |
938 | goto out_err_release; | 938 | goto out_err_release; |
939 | } | 939 | } |
@@ -1150,6 +1150,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1150 | { | 1150 | { |
1151 | struct inet_sock *inet = inet_sk(sk); | 1151 | struct inet_sock *inet = inet_sk(sk); |
1152 | struct ipv6_pinfo *np = inet6_sk(sk); | 1152 | struct ipv6_pinfo *np = inet6_sk(sk); |
1153 | struct inet_cork *cork; | ||
1153 | struct sk_buff *skb; | 1154 | struct sk_buff *skb; |
1154 | unsigned int maxfraglen, fragheaderlen; | 1155 | unsigned int maxfraglen, fragheaderlen; |
1155 | int exthdrlen; | 1156 | int exthdrlen; |
@@ -1163,6 +1164,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1163 | 1164 | ||
1164 | if (flags&MSG_PROBE) | 1165 | if (flags&MSG_PROBE) |
1165 | return 0; | 1166 | return 0; |
1167 | cork = &inet->cork.base; | ||
1166 | if (skb_queue_empty(&sk->sk_write_queue)) { | 1168 | if (skb_queue_empty(&sk->sk_write_queue)) { |
1167 | /* | 1169 | /* |
1168 | * setup for corking | 1170 | * setup for corking |
@@ -1202,7 +1204,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1202 | /* need source address above miyazawa*/ | 1204 | /* need source address above miyazawa*/ |
1203 | } | 1205 | } |
1204 | dst_hold(&rt->dst); | 1206 | dst_hold(&rt->dst); |
1205 | inet->cork.dst = &rt->dst; | 1207 | cork->dst = &rt->dst; |
1206 | inet->cork.fl.u.ip6 = *fl6; | 1208 | inet->cork.fl.u.ip6 = *fl6; |
1207 | np->cork.hop_limit = hlimit; | 1209 | np->cork.hop_limit = hlimit; |
1208 | np->cork.tclass = tclass; | 1210 | np->cork.tclass = tclass; |
@@ -1212,10 +1214,10 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1212 | if (np->frag_size) | 1214 | if (np->frag_size) |
1213 | mtu = np->frag_size; | 1215 | mtu = np->frag_size; |
1214 | } | 1216 | } |
1215 | inet->cork.fragsize = mtu; | 1217 | cork->fragsize = mtu; |
1216 | if (dst_allfrag(rt->dst.path)) | 1218 | if (dst_allfrag(rt->dst.path)) |
1217 | inet->cork.flags |= IPCORK_ALLFRAG; | 1219 | cork->flags |= IPCORK_ALLFRAG; |
1218 | inet->cork.length = 0; | 1220 | cork->length = 0; |
1219 | sk->sk_sndmsg_page = NULL; | 1221 | sk->sk_sndmsg_page = NULL; |
1220 | sk->sk_sndmsg_off = 0; | 1222 | sk->sk_sndmsg_off = 0; |
1221 | exthdrlen = rt->dst.header_len + (opt ? opt->opt_flen : 0) - | 1223 | exthdrlen = rt->dst.header_len + (opt ? opt->opt_flen : 0) - |
@@ -1223,12 +1225,12 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1223 | length += exthdrlen; | 1225 | length += exthdrlen; |
1224 | transhdrlen += exthdrlen; | 1226 | transhdrlen += exthdrlen; |
1225 | } else { | 1227 | } else { |
1226 | rt = (struct rt6_info *)inet->cork.dst; | 1228 | rt = (struct rt6_info *)cork->dst; |
1227 | fl6 = &inet->cork.fl.u.ip6; | 1229 | fl6 = &inet->cork.fl.u.ip6; |
1228 | opt = np->cork.opt; | 1230 | opt = np->cork.opt; |
1229 | transhdrlen = 0; | 1231 | transhdrlen = 0; |
1230 | exthdrlen = 0; | 1232 | exthdrlen = 0; |
1231 | mtu = inet->cork.fragsize; | 1233 | mtu = cork->fragsize; |
1232 | } | 1234 | } |
1233 | 1235 | ||
1234 | hh_len = LL_RESERVED_SPACE(rt->dst.dev); | 1236 | hh_len = LL_RESERVED_SPACE(rt->dst.dev); |
@@ -1238,7 +1240,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1238 | maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - sizeof(struct frag_hdr); | 1240 | maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen - sizeof(struct frag_hdr); |
1239 | 1241 | ||
1240 | if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) { | 1242 | if (mtu <= sizeof(struct ipv6hdr) + IPV6_MAXPLEN) { |
1241 | if (inet->cork.length + length > sizeof(struct ipv6hdr) + IPV6_MAXPLEN - fragheaderlen) { | 1243 | if (cork->length + length > sizeof(struct ipv6hdr) + IPV6_MAXPLEN - fragheaderlen) { |
1242 | ipv6_local_error(sk, EMSGSIZE, fl6, mtu-exthdrlen); | 1244 | ipv6_local_error(sk, EMSGSIZE, fl6, mtu-exthdrlen); |
1243 | return -EMSGSIZE; | 1245 | return -EMSGSIZE; |
1244 | } | 1246 | } |
@@ -1267,7 +1269,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1267 | * --yoshfuji | 1269 | * --yoshfuji |
1268 | */ | 1270 | */ |
1269 | 1271 | ||
1270 | inet->cork.length += length; | 1272 | cork->length += length; |
1271 | if (length > mtu) { | 1273 | if (length > mtu) { |
1272 | int proto = sk->sk_protocol; | 1274 | int proto = sk->sk_protocol; |
1273 | if (dontfrag && (proto == IPPROTO_UDP || proto == IPPROTO_RAW)){ | 1275 | if (dontfrag && (proto == IPPROTO_UDP || proto == IPPROTO_RAW)){ |
@@ -1292,7 +1294,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1292 | 1294 | ||
1293 | while (length > 0) { | 1295 | while (length > 0) { |
1294 | /* Check if the remaining data fits into current packet. */ | 1296 | /* Check if the remaining data fits into current packet. */ |
1295 | copy = (inet->cork.length <= mtu && !(inet->cork.flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - skb->len; | 1297 | copy = (cork->length <= mtu && !(cork->flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - skb->len; |
1296 | if (copy < length) | 1298 | if (copy < length) |
1297 | copy = maxfraglen - skb->len; | 1299 | copy = maxfraglen - skb->len; |
1298 | 1300 | ||
@@ -1317,7 +1319,7 @@ alloc_new_skb: | |||
1317 | * we know we need more fragment(s). | 1319 | * we know we need more fragment(s). |
1318 | */ | 1320 | */ |
1319 | datalen = length + fraggap; | 1321 | datalen = length + fraggap; |
1320 | if (datalen > (inet->cork.length <= mtu && !(inet->cork.flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - fragheaderlen) | 1322 | if (datalen > (cork->length <= mtu && !(cork->flags & IPCORK_ALLFRAG) ? mtu : maxfraglen) - fragheaderlen) |
1321 | datalen = maxfraglen - fragheaderlen; | 1323 | datalen = maxfraglen - fragheaderlen; |
1322 | 1324 | ||
1323 | fraglen = datalen + fragheaderlen; | 1325 | fraglen = datalen + fragheaderlen; |
@@ -1481,7 +1483,7 @@ alloc_new_skb: | |||
1481 | } | 1483 | } |
1482 | return 0; | 1484 | return 0; |
1483 | error: | 1485 | error: |
1484 | inet->cork.length -= length; | 1486 | cork->length -= length; |
1485 | IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS); | 1487 | IP6_INC_STATS(sock_net(sk), rt->rt6i_idev, IPSTATS_MIB_OUTDISCARDS); |
1486 | return err; | 1488 | return err; |
1487 | } | 1489 | } |
@@ -1497,10 +1499,10 @@ static void ip6_cork_release(struct inet_sock *inet, struct ipv6_pinfo *np) | |||
1497 | np->cork.opt = NULL; | 1499 | np->cork.opt = NULL; |
1498 | } | 1500 | } |
1499 | 1501 | ||
1500 | if (inet->cork.dst) { | 1502 | if (inet->cork.base.dst) { |
1501 | dst_release(inet->cork.dst); | 1503 | dst_release(inet->cork.base.dst); |
1502 | inet->cork.dst = NULL; | 1504 | inet->cork.base.dst = NULL; |
1503 | inet->cork.flags &= ~IPCORK_ALLFRAG; | 1505 | inet->cork.base.flags &= ~IPCORK_ALLFRAG; |
1504 | } | 1506 | } |
1505 | memset(&inet->cork.fl, 0, sizeof(inet->cork.fl)); | 1507 | memset(&inet->cork.fl, 0, sizeof(inet->cork.fl)); |
1506 | } | 1508 | } |
@@ -1515,7 +1517,7 @@ int ip6_push_pending_frames(struct sock *sk) | |||
1515 | struct net *net = sock_net(sk); | 1517 | struct net *net = sock_net(sk); |
1516 | struct ipv6hdr *hdr; | 1518 | struct ipv6hdr *hdr; |
1517 | struct ipv6_txoptions *opt = np->cork.opt; | 1519 | struct ipv6_txoptions *opt = np->cork.opt; |
1518 | struct rt6_info *rt = (struct rt6_info *)inet->cork.dst; | 1520 | struct rt6_info *rt = (struct rt6_info *)inet->cork.base.dst; |
1519 | struct flowi6 *fl6 = &inet->cork.fl.u.ip6; | 1521 | struct flowi6 *fl6 = &inet->cork.fl.u.ip6; |
1520 | unsigned char proto = fl6->flowi6_proto; | 1522 | unsigned char proto = fl6->flowi6_proto; |
1521 | int err = 0; | 1523 | int err = 0; |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index c1b1bd312df2..36c2842a86b2 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -162,7 +162,7 @@ static inline void ip6_tnl_dst_store(struct ip6_tnl *t, struct dst_entry *dst) | |||
162 | for (t = rcu_dereference(start); t; t = rcu_dereference(t->next)) | 162 | for (t = rcu_dereference(start); t; t = rcu_dereference(t->next)) |
163 | 163 | ||
164 | static struct ip6_tnl * | 164 | static struct ip6_tnl * |
165 | ip6_tnl_lookup(struct net *net, struct in6_addr *remote, struct in6_addr *local) | 165 | ip6_tnl_lookup(struct net *net, const struct in6_addr *remote, const struct in6_addr *local) |
166 | { | 166 | { |
167 | unsigned int h0 = HASH(remote); | 167 | unsigned int h0 = HASH(remote); |
168 | unsigned int h1 = HASH(local); | 168 | unsigned int h1 = HASH(local); |
@@ -194,10 +194,10 @@ ip6_tnl_lookup(struct net *net, struct in6_addr *remote, struct in6_addr *local) | |||
194 | **/ | 194 | **/ |
195 | 195 | ||
196 | static struct ip6_tnl __rcu ** | 196 | static struct ip6_tnl __rcu ** |
197 | ip6_tnl_bucket(struct ip6_tnl_net *ip6n, struct ip6_tnl_parm *p) | 197 | ip6_tnl_bucket(struct ip6_tnl_net *ip6n, const struct ip6_tnl_parm *p) |
198 | { | 198 | { |
199 | struct in6_addr *remote = &p->raddr; | 199 | const struct in6_addr *remote = &p->raddr; |
200 | struct in6_addr *local = &p->laddr; | 200 | const struct in6_addr *local = &p->laddr; |
201 | unsigned h = 0; | 201 | unsigned h = 0; |
202 | int prio = 0; | 202 | int prio = 0; |
203 | 203 | ||
@@ -280,11 +280,6 @@ static struct ip6_tnl *ip6_tnl_create(struct net *net, struct ip6_tnl_parm *p) | |||
280 | 280 | ||
281 | dev_net_set(dev, net); | 281 | dev_net_set(dev, net); |
282 | 282 | ||
283 | if (strchr(name, '%')) { | ||
284 | if (dev_alloc_name(dev, name) < 0) | ||
285 | goto failed_free; | ||
286 | } | ||
287 | |||
288 | t = netdev_priv(dev); | 283 | t = netdev_priv(dev); |
289 | t->parms = *p; | 284 | t->parms = *p; |
290 | err = ip6_tnl_dev_init(dev); | 285 | err = ip6_tnl_dev_init(dev); |
@@ -321,8 +316,8 @@ failed: | |||
321 | static struct ip6_tnl *ip6_tnl_locate(struct net *net, | 316 | static struct ip6_tnl *ip6_tnl_locate(struct net *net, |
322 | struct ip6_tnl_parm *p, int create) | 317 | struct ip6_tnl_parm *p, int create) |
323 | { | 318 | { |
324 | struct in6_addr *remote = &p->raddr; | 319 | const struct in6_addr *remote = &p->raddr; |
325 | struct in6_addr *local = &p->laddr; | 320 | const struct in6_addr *local = &p->laddr; |
326 | struct ip6_tnl __rcu **tp; | 321 | struct ip6_tnl __rcu **tp; |
327 | struct ip6_tnl *t; | 322 | struct ip6_tnl *t; |
328 | struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); | 323 | struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); |
@@ -374,7 +369,7 @@ ip6_tnl_dev_uninit(struct net_device *dev) | |||
374 | static __u16 | 369 | static __u16 |
375 | parse_tlv_tnl_enc_lim(struct sk_buff *skb, __u8 * raw) | 370 | parse_tlv_tnl_enc_lim(struct sk_buff *skb, __u8 * raw) |
376 | { | 371 | { |
377 | struct ipv6hdr *ipv6h = (struct ipv6hdr *) raw; | 372 | const struct ipv6hdr *ipv6h = (const struct ipv6hdr *) raw; |
378 | __u8 nexthdr = ipv6h->nexthdr; | 373 | __u8 nexthdr = ipv6h->nexthdr; |
379 | __u16 off = sizeof (*ipv6h); | 374 | __u16 off = sizeof (*ipv6h); |
380 | 375 | ||
@@ -435,7 +430,7 @@ static int | |||
435 | ip6_tnl_err(struct sk_buff *skb, __u8 ipproto, struct inet6_skb_parm *opt, | 430 | ip6_tnl_err(struct sk_buff *skb, __u8 ipproto, struct inet6_skb_parm *opt, |
436 | u8 *type, u8 *code, int *msg, __u32 *info, int offset) | 431 | u8 *type, u8 *code, int *msg, __u32 *info, int offset) |
437 | { | 432 | { |
438 | struct ipv6hdr *ipv6h = (struct ipv6hdr *) skb->data; | 433 | const struct ipv6hdr *ipv6h = (const struct ipv6hdr *) skb->data; |
439 | struct ip6_tnl *t; | 434 | struct ip6_tnl *t; |
440 | int rel_msg = 0; | 435 | int rel_msg = 0; |
441 | u8 rel_type = ICMPV6_DEST_UNREACH; | 436 | u8 rel_type = ICMPV6_DEST_UNREACH; |
@@ -535,8 +530,9 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
535 | __u32 rel_info = ntohl(info); | 530 | __u32 rel_info = ntohl(info); |
536 | int err; | 531 | int err; |
537 | struct sk_buff *skb2; | 532 | struct sk_buff *skb2; |
538 | struct iphdr *eiph; | 533 | const struct iphdr *eiph; |
539 | struct rtable *rt; | 534 | struct rtable *rt; |
535 | struct flowi4 fl4; | ||
540 | 536 | ||
541 | err = ip6_tnl_err(skb, IPPROTO_IPIP, opt, &rel_type, &rel_code, | 537 | err = ip6_tnl_err(skb, IPPROTO_IPIP, opt, &rel_type, &rel_code, |
542 | &rel_msg, &rel_info, offset); | 538 | &rel_msg, &rel_info, offset); |
@@ -577,7 +573,7 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
577 | eiph = ip_hdr(skb2); | 573 | eiph = ip_hdr(skb2); |
578 | 574 | ||
579 | /* Try to guess incoming interface */ | 575 | /* Try to guess incoming interface */ |
580 | rt = ip_route_output_ports(dev_net(skb->dev), NULL, | 576 | rt = ip_route_output_ports(dev_net(skb->dev), &fl4, NULL, |
581 | eiph->saddr, 0, | 577 | eiph->saddr, 0, |
582 | 0, 0, | 578 | 0, 0, |
583 | IPPROTO_IPIP, RT_TOS(eiph->tos), 0); | 579 | IPPROTO_IPIP, RT_TOS(eiph->tos), 0); |
@@ -590,7 +586,7 @@ ip4ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
590 | if (rt->rt_flags & RTCF_LOCAL) { | 586 | if (rt->rt_flags & RTCF_LOCAL) { |
591 | ip_rt_put(rt); | 587 | ip_rt_put(rt); |
592 | rt = NULL; | 588 | rt = NULL; |
593 | rt = ip_route_output_ports(dev_net(skb->dev), NULL, | 589 | rt = ip_route_output_ports(dev_net(skb->dev), &fl4, NULL, |
594 | eiph->daddr, eiph->saddr, | 590 | eiph->daddr, eiph->saddr, |
595 | 0, 0, | 591 | 0, 0, |
596 | IPPROTO_IPIP, | 592 | IPPROTO_IPIP, |
@@ -669,8 +665,8 @@ ip6ip6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
669 | return 0; | 665 | return 0; |
670 | } | 666 | } |
671 | 667 | ||
672 | static void ip4ip6_dscp_ecn_decapsulate(struct ip6_tnl *t, | 668 | static void ip4ip6_dscp_ecn_decapsulate(const struct ip6_tnl *t, |
673 | struct ipv6hdr *ipv6h, | 669 | const struct ipv6hdr *ipv6h, |
674 | struct sk_buff *skb) | 670 | struct sk_buff *skb) |
675 | { | 671 | { |
676 | __u8 dsfield = ipv6_get_dsfield(ipv6h) & ~INET_ECN_MASK; | 672 | __u8 dsfield = ipv6_get_dsfield(ipv6h) & ~INET_ECN_MASK; |
@@ -682,8 +678,8 @@ static void ip4ip6_dscp_ecn_decapsulate(struct ip6_tnl *t, | |||
682 | IP_ECN_set_ce(ip_hdr(skb)); | 678 | IP_ECN_set_ce(ip_hdr(skb)); |
683 | } | 679 | } |
684 | 680 | ||
685 | static void ip6ip6_dscp_ecn_decapsulate(struct ip6_tnl *t, | 681 | static void ip6ip6_dscp_ecn_decapsulate(const struct ip6_tnl *t, |
686 | struct ipv6hdr *ipv6h, | 682 | const struct ipv6hdr *ipv6h, |
687 | struct sk_buff *skb) | 683 | struct sk_buff *skb) |
688 | { | 684 | { |
689 | if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY) | 685 | if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY) |
@@ -726,12 +722,12 @@ static inline int ip6_tnl_rcv_ctl(struct ip6_tnl *t) | |||
726 | 722 | ||
727 | static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol, | 723 | static int ip6_tnl_rcv(struct sk_buff *skb, __u16 protocol, |
728 | __u8 ipproto, | 724 | __u8 ipproto, |
729 | void (*dscp_ecn_decapsulate)(struct ip6_tnl *t, | 725 | void (*dscp_ecn_decapsulate)(const struct ip6_tnl *t, |
730 | struct ipv6hdr *ipv6h, | 726 | const struct ipv6hdr *ipv6h, |
731 | struct sk_buff *skb)) | 727 | struct sk_buff *skb)) |
732 | { | 728 | { |
733 | struct ip6_tnl *t; | 729 | struct ip6_tnl *t; |
734 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); | 730 | const struct ipv6hdr *ipv6h = ipv6_hdr(skb); |
735 | 731 | ||
736 | rcu_read_lock(); | 732 | rcu_read_lock(); |
737 | 733 | ||
@@ -828,7 +824,7 @@ static void init_tel_txopt(struct ipv6_tel_txoption *opt, __u8 encap_limit) | |||
828 | **/ | 824 | **/ |
829 | 825 | ||
830 | static inline int | 826 | static inline int |
831 | ip6_tnl_addr_conflict(struct ip6_tnl *t, struct ipv6hdr *hdr) | 827 | ip6_tnl_addr_conflict(const struct ip6_tnl *t, const struct ipv6hdr *hdr) |
832 | { | 828 | { |
833 | return ipv6_addr_equal(&t->parms.raddr, &hdr->saddr); | 829 | return ipv6_addr_equal(&t->parms.raddr, &hdr->saddr); |
834 | } | 830 | } |
@@ -1005,7 +1001,7 @@ static inline int | |||
1005 | ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | 1001 | ip4ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) |
1006 | { | 1002 | { |
1007 | struct ip6_tnl *t = netdev_priv(dev); | 1003 | struct ip6_tnl *t = netdev_priv(dev); |
1008 | struct iphdr *iph = ip_hdr(skb); | 1004 | const struct iphdr *iph = ip_hdr(skb); |
1009 | int encap_limit = -1; | 1005 | int encap_limit = -1; |
1010 | struct flowi6 fl6; | 1006 | struct flowi6 fl6; |
1011 | __u8 dsfield; | 1007 | __u8 dsfield; |
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 29e48593bf22..82a809901f8e 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -989,8 +989,8 @@ static int mif6_add(struct net *net, struct mr6_table *mrt, | |||
989 | } | 989 | } |
990 | 990 | ||
991 | static struct mfc6_cache *ip6mr_cache_find(struct mr6_table *mrt, | 991 | static struct mfc6_cache *ip6mr_cache_find(struct mr6_table *mrt, |
992 | struct in6_addr *origin, | 992 | const struct in6_addr *origin, |
993 | struct in6_addr *mcastgrp) | 993 | const struct in6_addr *mcastgrp) |
994 | { | 994 | { |
995 | int line = MFC6_HASH(mcastgrp, origin); | 995 | int line = MFC6_HASH(mcastgrp, origin); |
996 | struct mfc6_cache *c; | 996 | struct mfc6_cache *c; |
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index 85cccd6ed0b7..bba658d9a03c 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c | |||
@@ -55,7 +55,7 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
55 | { | 55 | { |
56 | struct net *net = dev_net(skb->dev); | 56 | struct net *net = dev_net(skb->dev); |
57 | __be32 spi; | 57 | __be32 spi; |
58 | struct ipv6hdr *iph = (struct ipv6hdr*)skb->data; | 58 | const struct ipv6hdr *iph = (const struct ipv6hdr *)skb->data; |
59 | struct ip_comp_hdr *ipcomph = | 59 | struct ip_comp_hdr *ipcomph = |
60 | (struct ip_comp_hdr *)(skb->data + offset); | 60 | (struct ip_comp_hdr *)(skb->data + offset); |
61 | struct xfrm_state *x; | 61 | struct xfrm_state *x; |
@@ -64,7 +64,8 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
64 | return; | 64 | return; |
65 | 65 | ||
66 | spi = htonl(ntohs(ipcomph->cpi)); | 66 | spi = htonl(ntohs(ipcomph->cpi)); |
67 | x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, spi, IPPROTO_COMP, AF_INET6); | 67 | x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, |
68 | spi, IPPROTO_COMP, AF_INET6); | ||
68 | if (!x) | 69 | if (!x) |
69 | return; | 70 | return; |
70 | 71 | ||
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 76b893771e6e..ff62e33ead07 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -92,16 +92,16 @@ static void mld_gq_timer_expire(unsigned long data); | |||
92 | static void mld_ifc_timer_expire(unsigned long data); | 92 | static void mld_ifc_timer_expire(unsigned long data); |
93 | static void mld_ifc_event(struct inet6_dev *idev); | 93 | static void mld_ifc_event(struct inet6_dev *idev); |
94 | static void mld_add_delrec(struct inet6_dev *idev, struct ifmcaddr6 *pmc); | 94 | static void mld_add_delrec(struct inet6_dev *idev, struct ifmcaddr6 *pmc); |
95 | static void mld_del_delrec(struct inet6_dev *idev, struct in6_addr *addr); | 95 | static void mld_del_delrec(struct inet6_dev *idev, const struct in6_addr *addr); |
96 | static void mld_clear_delrec(struct inet6_dev *idev); | 96 | static void mld_clear_delrec(struct inet6_dev *idev); |
97 | static int sf_setstate(struct ifmcaddr6 *pmc); | 97 | static int sf_setstate(struct ifmcaddr6 *pmc); |
98 | static void sf_markstate(struct ifmcaddr6 *pmc); | 98 | static void sf_markstate(struct ifmcaddr6 *pmc); |
99 | static void ip6_mc_clear_src(struct ifmcaddr6 *pmc); | 99 | static void ip6_mc_clear_src(struct ifmcaddr6 *pmc); |
100 | static int ip6_mc_del_src(struct inet6_dev *idev, struct in6_addr *pmca, | 100 | static int ip6_mc_del_src(struct inet6_dev *idev, const struct in6_addr *pmca, |
101 | int sfmode, int sfcount, struct in6_addr *psfsrc, | 101 | int sfmode, int sfcount, const struct in6_addr *psfsrc, |
102 | int delta); | 102 | int delta); |
103 | static int ip6_mc_add_src(struct inet6_dev *idev, struct in6_addr *pmca, | 103 | static int ip6_mc_add_src(struct inet6_dev *idev, const struct in6_addr *pmca, |
104 | int sfmode, int sfcount, struct in6_addr *psfsrc, | 104 | int sfmode, int sfcount, const struct in6_addr *psfsrc, |
105 | int delta); | 105 | int delta); |
106 | static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml, | 106 | static int ip6_mc_leave_src(struct sock *sk, struct ipv6_mc_socklist *iml, |
107 | struct inet6_dev *idev); | 107 | struct inet6_dev *idev); |
@@ -250,7 +250,7 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
250 | 250 | ||
251 | /* called with rcu_read_lock() */ | 251 | /* called with rcu_read_lock() */ |
252 | static struct inet6_dev *ip6_mc_find_dev_rcu(struct net *net, | 252 | static struct inet6_dev *ip6_mc_find_dev_rcu(struct net *net, |
253 | struct in6_addr *group, | 253 | const struct in6_addr *group, |
254 | int ifindex) | 254 | int ifindex) |
255 | { | 255 | { |
256 | struct net_device *dev = NULL; | 256 | struct net_device *dev = NULL; |
@@ -451,7 +451,7 @@ done: | |||
451 | 451 | ||
452 | int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf) | 452 | int ip6_mc_msfilter(struct sock *sk, struct group_filter *gsf) |
453 | { | 453 | { |
454 | struct in6_addr *group; | 454 | const struct in6_addr *group; |
455 | struct ipv6_mc_socklist *pmc; | 455 | struct ipv6_mc_socklist *pmc; |
456 | struct inet6_dev *idev; | 456 | struct inet6_dev *idev; |
457 | struct ipv6_pinfo *inet6 = inet6_sk(sk); | 457 | struct ipv6_pinfo *inet6 = inet6_sk(sk); |
@@ -542,7 +542,7 @@ int ip6_mc_msfget(struct sock *sk, struct group_filter *gsf, | |||
542 | struct group_filter __user *optval, int __user *optlen) | 542 | struct group_filter __user *optval, int __user *optlen) |
543 | { | 543 | { |
544 | int err, i, count, copycount; | 544 | int err, i, count, copycount; |
545 | struct in6_addr *group; | 545 | const struct in6_addr *group; |
546 | struct ipv6_mc_socklist *pmc; | 546 | struct ipv6_mc_socklist *pmc; |
547 | struct inet6_dev *idev; | 547 | struct inet6_dev *idev; |
548 | struct ipv6_pinfo *inet6 = inet6_sk(sk); | 548 | struct ipv6_pinfo *inet6 = inet6_sk(sk); |
@@ -752,7 +752,7 @@ static void mld_add_delrec(struct inet6_dev *idev, struct ifmcaddr6 *im) | |||
752 | spin_unlock_bh(&idev->mc_lock); | 752 | spin_unlock_bh(&idev->mc_lock); |
753 | } | 753 | } |
754 | 754 | ||
755 | static void mld_del_delrec(struct inet6_dev *idev, struct in6_addr *pmca) | 755 | static void mld_del_delrec(struct inet6_dev *idev, const struct in6_addr *pmca) |
756 | { | 756 | { |
757 | struct ifmcaddr6 *pmc, *pmc_prev; | 757 | struct ifmcaddr6 *pmc, *pmc_prev; |
758 | struct ip6_sf_list *psf, *psf_next; | 758 | struct ip6_sf_list *psf, *psf_next; |
@@ -1052,7 +1052,7 @@ static void igmp6_group_queried(struct ifmcaddr6 *ma, unsigned long resptime) | |||
1052 | 1052 | ||
1053 | /* mark EXCLUDE-mode sources */ | 1053 | /* mark EXCLUDE-mode sources */ |
1054 | static int mld_xmarksources(struct ifmcaddr6 *pmc, int nsrcs, | 1054 | static int mld_xmarksources(struct ifmcaddr6 *pmc, int nsrcs, |
1055 | struct in6_addr *srcs) | 1055 | const struct in6_addr *srcs) |
1056 | { | 1056 | { |
1057 | struct ip6_sf_list *psf; | 1057 | struct ip6_sf_list *psf; |
1058 | int i, scount; | 1058 | int i, scount; |
@@ -1080,7 +1080,7 @@ static int mld_xmarksources(struct ifmcaddr6 *pmc, int nsrcs, | |||
1080 | } | 1080 | } |
1081 | 1081 | ||
1082 | static int mld_marksources(struct ifmcaddr6 *pmc, int nsrcs, | 1082 | static int mld_marksources(struct ifmcaddr6 *pmc, int nsrcs, |
1083 | struct in6_addr *srcs) | 1083 | const struct in6_addr *srcs) |
1084 | { | 1084 | { |
1085 | struct ip6_sf_list *psf; | 1085 | struct ip6_sf_list *psf; |
1086 | int i, scount; | 1086 | int i, scount; |
@@ -1115,7 +1115,7 @@ int igmp6_event_query(struct sk_buff *skb) | |||
1115 | { | 1115 | { |
1116 | struct mld2_query *mlh2 = NULL; | 1116 | struct mld2_query *mlh2 = NULL; |
1117 | struct ifmcaddr6 *ma; | 1117 | struct ifmcaddr6 *ma; |
1118 | struct in6_addr *group; | 1118 | const struct in6_addr *group; |
1119 | unsigned long max_delay; | 1119 | unsigned long max_delay; |
1120 | struct inet6_dev *idev; | 1120 | struct inet6_dev *idev; |
1121 | struct mld_msg *mld; | 1121 | struct mld_msg *mld; |
@@ -1821,7 +1821,7 @@ err_out: | |||
1821 | } | 1821 | } |
1822 | 1822 | ||
1823 | static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode, | 1823 | static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode, |
1824 | struct in6_addr *psfsrc) | 1824 | const struct in6_addr *psfsrc) |
1825 | { | 1825 | { |
1826 | struct ip6_sf_list *psf, *psf_prev; | 1826 | struct ip6_sf_list *psf, *psf_prev; |
1827 | int rv = 0; | 1827 | int rv = 0; |
@@ -1857,8 +1857,8 @@ static int ip6_mc_del1_src(struct ifmcaddr6 *pmc, int sfmode, | |||
1857 | return rv; | 1857 | return rv; |
1858 | } | 1858 | } |
1859 | 1859 | ||
1860 | static int ip6_mc_del_src(struct inet6_dev *idev, struct in6_addr *pmca, | 1860 | static int ip6_mc_del_src(struct inet6_dev *idev, const struct in6_addr *pmca, |
1861 | int sfmode, int sfcount, struct in6_addr *psfsrc, | 1861 | int sfmode, int sfcount, const struct in6_addr *psfsrc, |
1862 | int delta) | 1862 | int delta) |
1863 | { | 1863 | { |
1864 | struct ifmcaddr6 *pmc; | 1864 | struct ifmcaddr6 *pmc; |
@@ -1918,7 +1918,7 @@ static int ip6_mc_del_src(struct inet6_dev *idev, struct in6_addr *pmca, | |||
1918 | * Add multicast single-source filter to the interface list | 1918 | * Add multicast single-source filter to the interface list |
1919 | */ | 1919 | */ |
1920 | static int ip6_mc_add1_src(struct ifmcaddr6 *pmc, int sfmode, | 1920 | static int ip6_mc_add1_src(struct ifmcaddr6 *pmc, int sfmode, |
1921 | struct in6_addr *psfsrc, int delta) | 1921 | const struct in6_addr *psfsrc, int delta) |
1922 | { | 1922 | { |
1923 | struct ip6_sf_list *psf, *psf_prev; | 1923 | struct ip6_sf_list *psf, *psf_prev; |
1924 | 1924 | ||
@@ -2021,8 +2021,8 @@ static int sf_setstate(struct ifmcaddr6 *pmc) | |||
2021 | /* | 2021 | /* |
2022 | * Add multicast source filter list to the interface list | 2022 | * Add multicast source filter list to the interface list |
2023 | */ | 2023 | */ |
2024 | static int ip6_mc_add_src(struct inet6_dev *idev, struct in6_addr *pmca, | 2024 | static int ip6_mc_add_src(struct inet6_dev *idev, const struct in6_addr *pmca, |
2025 | int sfmode, int sfcount, struct in6_addr *psfsrc, | 2025 | int sfmode, int sfcount, const struct in6_addr *psfsrc, |
2026 | int delta) | 2026 | int delta) |
2027 | { | 2027 | { |
2028 | struct ifmcaddr6 *pmc; | 2028 | struct ifmcaddr6 *pmc; |
diff --git a/net/ipv6/mip6.c b/net/ipv6/mip6.c index 9b210482fb05..43242e6e6103 100644 --- a/net/ipv6/mip6.c +++ b/net/ipv6/mip6.c | |||
@@ -126,7 +126,7 @@ static struct mip6_report_rate_limiter mip6_report_rl = { | |||
126 | 126 | ||
127 | static int mip6_destopt_input(struct xfrm_state *x, struct sk_buff *skb) | 127 | static int mip6_destopt_input(struct xfrm_state *x, struct sk_buff *skb) |
128 | { | 128 | { |
129 | struct ipv6hdr *iph = ipv6_hdr(skb); | 129 | const struct ipv6hdr *iph = ipv6_hdr(skb); |
130 | struct ipv6_destopt_hdr *destopt = (struct ipv6_destopt_hdr *)skb->data; | 130 | struct ipv6_destopt_hdr *destopt = (struct ipv6_destopt_hdr *)skb->data; |
131 | int err = destopt->nexthdr; | 131 | int err = destopt->nexthdr; |
132 | 132 | ||
@@ -181,8 +181,8 @@ static int mip6_destopt_output(struct xfrm_state *x, struct sk_buff *skb) | |||
181 | } | 181 | } |
182 | 182 | ||
183 | static inline int mip6_report_rl_allow(struct timeval *stamp, | 183 | static inline int mip6_report_rl_allow(struct timeval *stamp, |
184 | struct in6_addr *dst, | 184 | const struct in6_addr *dst, |
185 | struct in6_addr *src, int iif) | 185 | const struct in6_addr *src, int iif) |
186 | { | 186 | { |
187 | int allow = 0; | 187 | int allow = 0; |
188 | 188 | ||
@@ -349,7 +349,7 @@ static const struct xfrm_type mip6_destopt_type = | |||
349 | 349 | ||
350 | static int mip6_rthdr_input(struct xfrm_state *x, struct sk_buff *skb) | 350 | static int mip6_rthdr_input(struct xfrm_state *x, struct sk_buff *skb) |
351 | { | 351 | { |
352 | struct ipv6hdr *iph = ipv6_hdr(skb); | 352 | const struct ipv6hdr *iph = ipv6_hdr(skb); |
353 | struct rt2_hdr *rt2 = (struct rt2_hdr *)skb->data; | 353 | struct rt2_hdr *rt2 = (struct rt2_hdr *)skb->data; |
354 | int err = rt2->rt_hdr.nexthdr; | 354 | int err = rt2->rt_hdr.nexthdr; |
355 | 355 | ||
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index 92f952d093db..7596f071d308 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -324,7 +324,7 @@ static inline u8 *ndisc_opt_addr_data(struct nd_opt_hdr *p, | |||
324 | return lladdr + prepad; | 324 | return lladdr + prepad; |
325 | } | 325 | } |
326 | 326 | ||
327 | int ndisc_mc_map(struct in6_addr *addr, char *buf, struct net_device *dev, int dir) | 327 | int ndisc_mc_map(const struct in6_addr *addr, char *buf, struct net_device *dev, int dir) |
328 | { | 328 | { |
329 | switch (dev->type) { | 329 | switch (dev->type) { |
330 | case ARPHRD_ETHER: | 330 | case ARPHRD_ETHER: |
@@ -611,6 +611,29 @@ static void ndisc_send_na(struct net_device *dev, struct neighbour *neigh, | |||
611 | inc_opt ? ND_OPT_TARGET_LL_ADDR : 0); | 611 | inc_opt ? ND_OPT_TARGET_LL_ADDR : 0); |
612 | } | 612 | } |
613 | 613 | ||
614 | static void ndisc_send_unsol_na(struct net_device *dev) | ||
615 | { | ||
616 | struct inet6_dev *idev; | ||
617 | struct inet6_ifaddr *ifa; | ||
618 | struct in6_addr mcaddr; | ||
619 | |||
620 | idev = in6_dev_get(dev); | ||
621 | if (!idev) | ||
622 | return; | ||
623 | |||
624 | read_lock_bh(&idev->lock); | ||
625 | list_for_each_entry(ifa, &idev->addr_list, if_list) { | ||
626 | addrconf_addr_solict_mult(&ifa->addr, &mcaddr); | ||
627 | ndisc_send_na(dev, NULL, &mcaddr, &ifa->addr, | ||
628 | /*router=*/ !!idev->cnf.forwarding, | ||
629 | /*solicited=*/ false, /*override=*/ true, | ||
630 | /*inc_opt=*/ true); | ||
631 | } | ||
632 | read_unlock_bh(&idev->lock); | ||
633 | |||
634 | in6_dev_put(idev); | ||
635 | } | ||
636 | |||
614 | void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, | 637 | void ndisc_send_ns(struct net_device *dev, struct neighbour *neigh, |
615 | const struct in6_addr *solicit, | 638 | const struct in6_addr *solicit, |
616 | const struct in6_addr *daddr, const struct in6_addr *saddr) | 639 | const struct in6_addr *daddr, const struct in6_addr *saddr) |
@@ -725,8 +748,8 @@ static int pndisc_is_router(const void *pkey, | |||
725 | static void ndisc_recv_ns(struct sk_buff *skb) | 748 | static void ndisc_recv_ns(struct sk_buff *skb) |
726 | { | 749 | { |
727 | struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb); | 750 | struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb); |
728 | struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; | 751 | const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; |
729 | struct in6_addr *daddr = &ipv6_hdr(skb)->daddr; | 752 | const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr; |
730 | u8 *lladdr = NULL; | 753 | u8 *lladdr = NULL; |
731 | u32 ndoptlen = skb->tail - (skb->transport_header + | 754 | u32 ndoptlen = skb->tail - (skb->transport_header + |
732 | offsetof(struct nd_msg, opt)); | 755 | offsetof(struct nd_msg, opt)); |
@@ -901,8 +924,8 @@ out: | |||
901 | static void ndisc_recv_na(struct sk_buff *skb) | 924 | static void ndisc_recv_na(struct sk_buff *skb) |
902 | { | 925 | { |
903 | struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb); | 926 | struct nd_msg *msg = (struct nd_msg *)skb_transport_header(skb); |
904 | struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; | 927 | const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; |
905 | struct in6_addr *daddr = &ipv6_hdr(skb)->daddr; | 928 | const struct in6_addr *daddr = &ipv6_hdr(skb)->daddr; |
906 | u8 *lladdr = NULL; | 929 | u8 *lladdr = NULL; |
907 | u32 ndoptlen = skb->tail - (skb->transport_header + | 930 | u32 ndoptlen = skb->tail - (skb->transport_header + |
908 | offsetof(struct nd_msg, opt)); | 931 | offsetof(struct nd_msg, opt)); |
@@ -945,9 +968,10 @@ static void ndisc_recv_na(struct sk_buff *skb) | |||
945 | } | 968 | } |
946 | ifp = ipv6_get_ifaddr(dev_net(dev), &msg->target, dev, 1); | 969 | ifp = ipv6_get_ifaddr(dev_net(dev), &msg->target, dev, 1); |
947 | if (ifp) { | 970 | if (ifp) { |
948 | if (ifp->flags & IFA_F_TENTATIVE) { | 971 | if (skb->pkt_type != PACKET_LOOPBACK |
949 | addrconf_dad_failure(ifp); | 972 | && (ifp->flags & IFA_F_TENTATIVE)) { |
950 | return; | 973 | addrconf_dad_failure(ifp); |
974 | return; | ||
951 | } | 975 | } |
952 | /* What should we make now? The advertisement | 976 | /* What should we make now? The advertisement |
953 | is invalid, but ndisc specs say nothing | 977 | is invalid, but ndisc specs say nothing |
@@ -1014,7 +1038,7 @@ static void ndisc_recv_rs(struct sk_buff *skb) | |||
1014 | unsigned long ndoptlen = skb->len - sizeof(*rs_msg); | 1038 | unsigned long ndoptlen = skb->len - sizeof(*rs_msg); |
1015 | struct neighbour *neigh; | 1039 | struct neighbour *neigh; |
1016 | struct inet6_dev *idev; | 1040 | struct inet6_dev *idev; |
1017 | struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; | 1041 | const struct in6_addr *saddr = &ipv6_hdr(skb)->saddr; |
1018 | struct ndisc_options ndopts; | 1042 | struct ndisc_options ndopts; |
1019 | u8 *lladdr = NULL; | 1043 | u8 *lladdr = NULL; |
1020 | 1044 | ||
@@ -1411,8 +1435,8 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) | |||
1411 | { | 1435 | { |
1412 | struct inet6_dev *in6_dev; | 1436 | struct inet6_dev *in6_dev; |
1413 | struct icmp6hdr *icmph; | 1437 | struct icmp6hdr *icmph; |
1414 | struct in6_addr *dest; | 1438 | const struct in6_addr *dest; |
1415 | struct in6_addr *target; /* new first hop to destination */ | 1439 | const struct in6_addr *target; /* new first hop to destination */ |
1416 | struct neighbour *neigh; | 1440 | struct neighbour *neigh; |
1417 | int on_link = 0; | 1441 | int on_link = 0; |
1418 | struct ndisc_options ndopts; | 1442 | struct ndisc_options ndopts; |
@@ -1445,7 +1469,7 @@ static void ndisc_redirect_rcv(struct sk_buff *skb) | |||
1445 | } | 1469 | } |
1446 | 1470 | ||
1447 | icmph = icmp6_hdr(skb); | 1471 | icmph = icmp6_hdr(skb); |
1448 | target = (struct in6_addr *) (icmph + 1); | 1472 | target = (const struct in6_addr *) (icmph + 1); |
1449 | dest = target + 1; | 1473 | dest = target + 1; |
1450 | 1474 | ||
1451 | if (ipv6_addr_is_multicast(dest)) { | 1475 | if (ipv6_addr_is_multicast(dest)) { |
@@ -1722,6 +1746,9 @@ static int ndisc_netdev_event(struct notifier_block *this, unsigned long event, | |||
1722 | neigh_ifdown(&nd_tbl, dev); | 1746 | neigh_ifdown(&nd_tbl, dev); |
1723 | fib6_run_gc(~0UL, net); | 1747 | fib6_run_gc(~0UL, net); |
1724 | break; | 1748 | break; |
1749 | case NETDEV_NOTIFY_PEERS: | ||
1750 | ndisc_send_unsol_na(dev); | ||
1751 | break; | ||
1725 | default: | 1752 | default: |
1726 | break; | 1753 | break; |
1727 | } | 1754 | } |
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index 39aaca2b4fd2..30fcee465448 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c | |||
@@ -13,7 +13,7 @@ | |||
13 | int ip6_route_me_harder(struct sk_buff *skb) | 13 | int ip6_route_me_harder(struct sk_buff *skb) |
14 | { | 14 | { |
15 | struct net *net = dev_net(skb_dst(skb)->dev); | 15 | struct net *net = dev_net(skb_dst(skb)->dev); |
16 | struct ipv6hdr *iph = ipv6_hdr(skb); | 16 | const struct ipv6hdr *iph = ipv6_hdr(skb); |
17 | struct dst_entry *dst; | 17 | struct dst_entry *dst; |
18 | struct flowi6 fl6 = { | 18 | struct flowi6 fl6 = { |
19 | .flowi6_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0, | 19 | .flowi6_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0, |
@@ -67,7 +67,7 @@ static void nf_ip6_saveroute(const struct sk_buff *skb, | |||
67 | struct ip6_rt_info *rt_info = nf_queue_entry_reroute(entry); | 67 | struct ip6_rt_info *rt_info = nf_queue_entry_reroute(entry); |
68 | 68 | ||
69 | if (entry->hook == NF_INET_LOCAL_OUT) { | 69 | if (entry->hook == NF_INET_LOCAL_OUT) { |
70 | struct ipv6hdr *iph = ipv6_hdr(skb); | 70 | const struct ipv6hdr *iph = ipv6_hdr(skb); |
71 | 71 | ||
72 | rt_info->daddr = iph->daddr; | 72 | rt_info->daddr = iph->daddr; |
73 | rt_info->saddr = iph->saddr; | 73 | rt_info->saddr = iph->saddr; |
@@ -81,7 +81,7 @@ static int nf_ip6_reroute(struct sk_buff *skb, | |||
81 | struct ip6_rt_info *rt_info = nf_queue_entry_reroute(entry); | 81 | struct ip6_rt_info *rt_info = nf_queue_entry_reroute(entry); |
82 | 82 | ||
83 | if (entry->hook == NF_INET_LOCAL_OUT) { | 83 | if (entry->hook == NF_INET_LOCAL_OUT) { |
84 | struct ipv6hdr *iph = ipv6_hdr(skb); | 84 | const struct ipv6hdr *iph = ipv6_hdr(skb); |
85 | if (!ipv6_addr_equal(&iph->daddr, &rt_info->daddr) || | 85 | if (!ipv6_addr_equal(&iph->daddr, &rt_info->daddr) || |
86 | !ipv6_addr_equal(&iph->saddr, &rt_info->saddr) || | 86 | !ipv6_addr_equal(&iph->saddr, &rt_info->saddr) || |
87 | skb->mark != rt_info->mark) | 87 | skb->mark != rt_info->mark) |
@@ -90,16 +90,25 @@ static int nf_ip6_reroute(struct sk_buff *skb, | |||
90 | return 0; | 90 | return 0; |
91 | } | 91 | } |
92 | 92 | ||
93 | static int nf_ip6_route(struct dst_entry **dst, struct flowi *fl) | 93 | static int nf_ip6_route(struct net *net, struct dst_entry **dst, |
94 | struct flowi *fl, bool strict) | ||
94 | { | 95 | { |
95 | *dst = ip6_route_output(&init_net, NULL, &fl->u.ip6); | 96 | static const struct ipv6_pinfo fake_pinfo; |
97 | static const struct inet_sock fake_sk = { | ||
98 | /* makes ip6_route_output set RT6_LOOKUP_F_IFACE: */ | ||
99 | .sk.sk_bound_dev_if = 1, | ||
100 | .pinet6 = (struct ipv6_pinfo *) &fake_pinfo, | ||
101 | }; | ||
102 | const void *sk = strict ? &fake_sk : NULL; | ||
103 | |||
104 | *dst = ip6_route_output(net, sk, &fl->u.ip6); | ||
96 | return (*dst)->error; | 105 | return (*dst)->error; |
97 | } | 106 | } |
98 | 107 | ||
99 | __sum16 nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, | 108 | __sum16 nf_ip6_checksum(struct sk_buff *skb, unsigned int hook, |
100 | unsigned int dataoff, u_int8_t protocol) | 109 | unsigned int dataoff, u_int8_t protocol) |
101 | { | 110 | { |
102 | struct ipv6hdr *ip6h = ipv6_hdr(skb); | 111 | const struct ipv6hdr *ip6h = ipv6_hdr(skb); |
103 | __sum16 csum = 0; | 112 | __sum16 csum = 0; |
104 | 113 | ||
105 | switch (skb->ip_summed) { | 114 | switch (skb->ip_summed) { |
@@ -133,7 +142,7 @@ static __sum16 nf_ip6_checksum_partial(struct sk_buff *skb, unsigned int hook, | |||
133 | unsigned int dataoff, unsigned int len, | 142 | unsigned int dataoff, unsigned int len, |
134 | u_int8_t protocol) | 143 | u_int8_t protocol) |
135 | { | 144 | { |
136 | struct ipv6hdr *ip6h = ipv6_hdr(skb); | 145 | const struct ipv6hdr *ip6h = ipv6_hdr(skb); |
137 | __wsum hsum; | 146 | __wsum hsum; |
138 | __sum16 csum = 0; | 147 | __sum16 csum = 0; |
139 | 148 | ||
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 0b2af9b85cec..94874b0bdcdc 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
@@ -340,6 +340,7 @@ ip6t_do_table(struct sk_buff *skb, | |||
340 | unsigned int *stackptr, origptr, cpu; | 340 | unsigned int *stackptr, origptr, cpu; |
341 | const struct xt_table_info *private; | 341 | const struct xt_table_info *private; |
342 | struct xt_action_param acpar; | 342 | struct xt_action_param acpar; |
343 | unsigned int addend; | ||
343 | 344 | ||
344 | /* Initialization */ | 345 | /* Initialization */ |
345 | indev = in ? in->name : nulldevname; | 346 | indev = in ? in->name : nulldevname; |
@@ -358,7 +359,8 @@ ip6t_do_table(struct sk_buff *skb, | |||
358 | 359 | ||
359 | IP_NF_ASSERT(table->valid_hooks & (1 << hook)); | 360 | IP_NF_ASSERT(table->valid_hooks & (1 << hook)); |
360 | 361 | ||
361 | xt_info_rdlock_bh(); | 362 | local_bh_disable(); |
363 | addend = xt_write_recseq_begin(); | ||
362 | private = table->private; | 364 | private = table->private; |
363 | cpu = smp_processor_id(); | 365 | cpu = smp_processor_id(); |
364 | table_base = private->entries[cpu]; | 366 | table_base = private->entries[cpu]; |
@@ -442,7 +444,9 @@ ip6t_do_table(struct sk_buff *skb, | |||
442 | } while (!acpar.hotdrop); | 444 | } while (!acpar.hotdrop); |
443 | 445 | ||
444 | *stackptr = origptr; | 446 | *stackptr = origptr; |
445 | xt_info_rdunlock_bh(); | 447 | |
448 | xt_write_recseq_end(addend); | ||
449 | local_bh_enable(); | ||
446 | 450 | ||
447 | #ifdef DEBUG_ALLOW_ALL | 451 | #ifdef DEBUG_ALLOW_ALL |
448 | return NF_ACCEPT; | 452 | return NF_ACCEPT; |
@@ -899,7 +903,7 @@ get_counters(const struct xt_table_info *t, | |||
899 | unsigned int i; | 903 | unsigned int i; |
900 | 904 | ||
901 | for_each_possible_cpu(cpu) { | 905 | for_each_possible_cpu(cpu) { |
902 | seqlock_t *lock = &per_cpu(xt_info_locks, cpu).lock; | 906 | seqcount_t *s = &per_cpu(xt_recseq, cpu); |
903 | 907 | ||
904 | i = 0; | 908 | i = 0; |
905 | xt_entry_foreach(iter, t->entries[cpu], t->size) { | 909 | xt_entry_foreach(iter, t->entries[cpu], t->size) { |
@@ -907,10 +911,10 @@ get_counters(const struct xt_table_info *t, | |||
907 | unsigned int start; | 911 | unsigned int start; |
908 | 912 | ||
909 | do { | 913 | do { |
910 | start = read_seqbegin(lock); | 914 | start = read_seqcount_begin(s); |
911 | bcnt = iter->counters.bcnt; | 915 | bcnt = iter->counters.bcnt; |
912 | pcnt = iter->counters.pcnt; | 916 | pcnt = iter->counters.pcnt; |
913 | } while (read_seqretry(lock, start)); | 917 | } while (read_seqcount_retry(s, start)); |
914 | 918 | ||
915 | ADD_COUNTER(counters[i], bcnt, pcnt); | 919 | ADD_COUNTER(counters[i], bcnt, pcnt); |
916 | ++i; | 920 | ++i; |
@@ -1325,6 +1329,7 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len, | |||
1325 | int ret = 0; | 1329 | int ret = 0; |
1326 | const void *loc_cpu_entry; | 1330 | const void *loc_cpu_entry; |
1327 | struct ip6t_entry *iter; | 1331 | struct ip6t_entry *iter; |
1332 | unsigned int addend; | ||
1328 | #ifdef CONFIG_COMPAT | 1333 | #ifdef CONFIG_COMPAT |
1329 | struct compat_xt_counters_info compat_tmp; | 1334 | struct compat_xt_counters_info compat_tmp; |
1330 | 1335 | ||
@@ -1381,13 +1386,13 @@ do_add_counters(struct net *net, const void __user *user, unsigned int len, | |||
1381 | i = 0; | 1386 | i = 0; |
1382 | /* Choose the copy that is on our node */ | 1387 | /* Choose the copy that is on our node */ |
1383 | curcpu = smp_processor_id(); | 1388 | curcpu = smp_processor_id(); |
1384 | xt_info_wrlock(curcpu); | 1389 | addend = xt_write_recseq_begin(); |
1385 | loc_cpu_entry = private->entries[curcpu]; | 1390 | loc_cpu_entry = private->entries[curcpu]; |
1386 | xt_entry_foreach(iter, loc_cpu_entry, private->size) { | 1391 | xt_entry_foreach(iter, loc_cpu_entry, private->size) { |
1387 | ADD_COUNTER(iter->counters, paddc[i].bcnt, paddc[i].pcnt); | 1392 | ADD_COUNTER(iter->counters, paddc[i].bcnt, paddc[i].pcnt); |
1388 | ++i; | 1393 | ++i; |
1389 | } | 1394 | } |
1390 | xt_info_wrunlock(curcpu); | 1395 | xt_write_recseq_end(addend); |
1391 | 1396 | ||
1392 | unlock_up_free: | 1397 | unlock_up_free: |
1393 | local_bh_enable(); | 1398 | local_bh_enable(); |
@@ -1578,7 +1583,6 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr, | |||
1578 | struct xt_table_info *newinfo, unsigned char *base) | 1583 | struct xt_table_info *newinfo, unsigned char *base) |
1579 | { | 1584 | { |
1580 | struct xt_entry_target *t; | 1585 | struct xt_entry_target *t; |
1581 | struct xt_target *target; | ||
1582 | struct ip6t_entry *de; | 1586 | struct ip6t_entry *de; |
1583 | unsigned int origsize; | 1587 | unsigned int origsize; |
1584 | int ret, h; | 1588 | int ret, h; |
@@ -1600,7 +1604,6 @@ compat_copy_entry_from_user(struct compat_ip6t_entry *e, void **dstptr, | |||
1600 | } | 1604 | } |
1601 | de->target_offset = e->target_offset - (origsize - *size); | 1605 | de->target_offset = e->target_offset - (origsize - *size); |
1602 | t = compat_ip6t_get_target(e); | 1606 | t = compat_ip6t_get_target(e); |
1603 | target = t->u.kernel.target; | ||
1604 | xt_compat_target_from_user(t, dstptr, size); | 1607 | xt_compat_target_from_user(t, dstptr, size); |
1605 | 1608 | ||
1606 | de->next_offset = e->next_offset - (origsize - *size); | 1609 | de->next_offset = e->next_offset - (origsize - *size); |
@@ -2248,7 +2251,7 @@ static int __init ip6_tables_init(void) | |||
2248 | if (ret < 0) | 2251 | if (ret < 0) |
2249 | goto err1; | 2252 | goto err1; |
2250 | 2253 | ||
2251 | /* Noone else will be downing sem now, so we won't sleep */ | 2254 | /* No one else will be downing sem now, so we won't sleep */ |
2252 | ret = xt_register_targets(ip6t_builtin_tg, ARRAY_SIZE(ip6t_builtin_tg)); | 2255 | ret = xt_register_targets(ip6t_builtin_tg, ARRAY_SIZE(ip6t_builtin_tg)); |
2253 | if (ret < 0) | 2256 | if (ret < 0) |
2254 | goto err2; | 2257 | goto err2; |
diff --git a/net/ipv6/netfilter/ip6t_REJECT.c b/net/ipv6/netfilter/ip6t_REJECT.c index 28e74488a329..a5a4c5dd5396 100644 --- a/net/ipv6/netfilter/ip6t_REJECT.c +++ b/net/ipv6/netfilter/ip6t_REJECT.c | |||
@@ -45,6 +45,8 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) | |||
45 | int tcphoff, needs_ack; | 45 | int tcphoff, needs_ack; |
46 | const struct ipv6hdr *oip6h = ipv6_hdr(oldskb); | 46 | const struct ipv6hdr *oip6h = ipv6_hdr(oldskb); |
47 | struct ipv6hdr *ip6h; | 47 | struct ipv6hdr *ip6h; |
48 | #define DEFAULT_TOS_VALUE 0x0U | ||
49 | const __u8 tclass = DEFAULT_TOS_VALUE; | ||
48 | struct dst_entry *dst = NULL; | 50 | struct dst_entry *dst = NULL; |
49 | u8 proto; | 51 | u8 proto; |
50 | struct flowi6 fl6; | 52 | struct flowi6 fl6; |
@@ -124,7 +126,7 @@ static void send_reset(struct net *net, struct sk_buff *oldskb) | |||
124 | skb_put(nskb, sizeof(struct ipv6hdr)); | 126 | skb_put(nskb, sizeof(struct ipv6hdr)); |
125 | skb_reset_network_header(nskb); | 127 | skb_reset_network_header(nskb); |
126 | ip6h = ipv6_hdr(nskb); | 128 | ip6h = ipv6_hdr(nskb); |
127 | ip6h->version = 6; | 129 | *(__be32 *)ip6h = htonl(0x60000000 | (tclass << 20)); |
128 | ip6h->hop_limit = ip6_dst_hoplimit(dst); | 130 | ip6h->hop_limit = ip6_dst_hoplimit(dst); |
129 | ip6h->nexthdr = IPPROTO_TCP; | 131 | ip6h->nexthdr = IPPROTO_TCP; |
130 | ipv6_addr_copy(&ip6h->saddr, &oip6h->daddr); | 132 | ipv6_addr_copy(&ip6h->saddr, &oip6h->daddr); |
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index 679a0a3b7b3c..00d19173db7e 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c | |||
@@ -64,7 +64,8 @@ ip6t_mangle_out(struct sk_buff *skb, const struct net_device *out) | |||
64 | (memcmp(&ipv6_hdr(skb)->saddr, &saddr, sizeof(saddr)) || | 64 | (memcmp(&ipv6_hdr(skb)->saddr, &saddr, sizeof(saddr)) || |
65 | memcmp(&ipv6_hdr(skb)->daddr, &daddr, sizeof(daddr)) || | 65 | memcmp(&ipv6_hdr(skb)->daddr, &daddr, sizeof(daddr)) || |
66 | skb->mark != mark || | 66 | skb->mark != mark || |
67 | ipv6_hdr(skb)->hop_limit != hop_limit)) | 67 | ipv6_hdr(skb)->hop_limit != hop_limit || |
68 | flowlabel != *((u_int32_t *)ipv6_hdr(skb)))) | ||
68 | return ip6_route_me_harder(skb) == 0 ? ret : NF_DROP; | 69 | return ip6_route_me_harder(skb) == 0 ? ret : NF_DROP; |
69 | 70 | ||
70 | return ret; | 71 | return ret; |
diff --git a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c index 97c5b21b9674..cdd6d045e42e 100644 --- a/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c +++ b/net/ipv6/netfilter/nf_defrag_ipv6_hooks.c | |||
@@ -71,7 +71,7 @@ static unsigned int ipv6_defrag(unsigned int hooknum, | |||
71 | if (reasm == NULL) | 71 | if (reasm == NULL) |
72 | return NF_STOLEN; | 72 | return NF_STOLEN; |
73 | 73 | ||
74 | /* error occured or not fragmented */ | 74 | /* error occurred or not fragmented */ |
75 | if (reasm == skb) | 75 | if (reasm == skb) |
76 | return NF_ACCEPT; | 76 | return NF_ACCEPT; |
77 | 77 | ||
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 4a1c3b46c56b..ae64984f81aa 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -67,8 +67,8 @@ static struct raw_hashinfo raw_v6_hashinfo = { | |||
67 | }; | 67 | }; |
68 | 68 | ||
69 | static struct sock *__raw_v6_lookup(struct net *net, struct sock *sk, | 69 | static struct sock *__raw_v6_lookup(struct net *net, struct sock *sk, |
70 | unsigned short num, struct in6_addr *loc_addr, | 70 | unsigned short num, const struct in6_addr *loc_addr, |
71 | struct in6_addr *rmt_addr, int dif) | 71 | const struct in6_addr *rmt_addr, int dif) |
72 | { | 72 | { |
73 | struct hlist_node *node; | 73 | struct hlist_node *node; |
74 | int is_multicast = ipv6_addr_is_multicast(loc_addr); | 74 | int is_multicast = ipv6_addr_is_multicast(loc_addr); |
@@ -154,8 +154,8 @@ EXPORT_SYMBOL(rawv6_mh_filter_unregister); | |||
154 | */ | 154 | */ |
155 | static int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) | 155 | static int ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) |
156 | { | 156 | { |
157 | struct in6_addr *saddr; | 157 | const struct in6_addr *saddr; |
158 | struct in6_addr *daddr; | 158 | const struct in6_addr *daddr; |
159 | struct sock *sk; | 159 | struct sock *sk; |
160 | int delivered = 0; | 160 | int delivered = 0; |
161 | __u8 hash; | 161 | __u8 hash; |
@@ -348,7 +348,7 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr, | |||
348 | { | 348 | { |
349 | struct sock *sk; | 349 | struct sock *sk; |
350 | int hash; | 350 | int hash; |
351 | struct in6_addr *saddr, *daddr; | 351 | const struct in6_addr *saddr, *daddr; |
352 | struct net *net; | 352 | struct net *net; |
353 | 353 | ||
354 | hash = nexthdr & (RAW_HTABLE_SIZE - 1); | 354 | hash = nexthdr & (RAW_HTABLE_SIZE - 1); |
@@ -357,7 +357,7 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr, | |||
357 | sk = sk_head(&raw_v6_hashinfo.ht[hash]); | 357 | sk = sk_head(&raw_v6_hashinfo.ht[hash]); |
358 | if (sk != NULL) { | 358 | if (sk != NULL) { |
359 | /* Note: ipv6_hdr(skb) != skb->data */ | 359 | /* Note: ipv6_hdr(skb) != skb->data */ |
360 | struct ipv6hdr *ip6h = (struct ipv6hdr *)skb->data; | 360 | const struct ipv6hdr *ip6h = (const struct ipv6hdr *)skb->data; |
361 | saddr = &ip6h->saddr; | 361 | saddr = &ip6h->saddr; |
362 | daddr = &ip6h->daddr; | 362 | daddr = &ip6h->daddr; |
363 | net = dev_net(skb->dev); | 363 | net = dev_net(skb->dev); |
@@ -542,8 +542,8 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, | |||
542 | goto out; | 542 | goto out; |
543 | 543 | ||
544 | offset = rp->offset; | 544 | offset = rp->offset; |
545 | total_len = inet_sk(sk)->cork.length - (skb_network_header(skb) - | 545 | total_len = inet_sk(sk)->cork.base.length - (skb_network_header(skb) - |
546 | skb->data); | 546 | skb->data); |
547 | if (offset >= total_len - 1) { | 547 | if (offset >= total_len - 1) { |
548 | err = -EINVAL; | 548 | err = -EINVAL; |
549 | ip6_flush_pending_frames(sk); | 549 | ip6_flush_pending_frames(sk); |
@@ -1231,7 +1231,7 @@ struct proto rawv6_prot = { | |||
1231 | static void raw6_sock_seq_show(struct seq_file *seq, struct sock *sp, int i) | 1231 | static void raw6_sock_seq_show(struct seq_file *seq, struct sock *sp, int i) |
1232 | { | 1232 | { |
1233 | struct ipv6_pinfo *np = inet6_sk(sp); | 1233 | struct ipv6_pinfo *np = inet6_sk(sp); |
1234 | struct in6_addr *dest, *src; | 1234 | const struct in6_addr *dest, *src; |
1235 | __u16 destp, srcp; | 1235 | __u16 destp, srcp; |
1236 | 1236 | ||
1237 | dest = &np->daddr; | 1237 | dest = &np->daddr; |
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index 07beeb06f752..7b954e2539d0 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -224,7 +224,7 @@ out: | |||
224 | } | 224 | } |
225 | 225 | ||
226 | static __inline__ struct frag_queue * | 226 | static __inline__ struct frag_queue * |
227 | fq_find(struct net *net, __be32 id, struct in6_addr *src, struct in6_addr *dst) | 227 | fq_find(struct net *net, __be32 id, const struct in6_addr *src, const struct in6_addr *dst) |
228 | { | 228 | { |
229 | struct inet_frag_queue *q; | 229 | struct inet_frag_queue *q; |
230 | struct ip6_create_arg arg; | 230 | struct ip6_create_arg arg; |
@@ -535,7 +535,7 @@ static int ipv6_frag_rcv(struct sk_buff *skb) | |||
535 | { | 535 | { |
536 | struct frag_hdr *fhdr; | 536 | struct frag_hdr *fhdr; |
537 | struct frag_queue *fq; | 537 | struct frag_queue *fq; |
538 | struct ipv6hdr *hdr = ipv6_hdr(skb); | 538 | const struct ipv6hdr *hdr = ipv6_hdr(skb); |
539 | struct net *net = dev_net(skb_dst(skb)->dev); | 539 | struct net *net = dev_net(skb_dst(skb)->dev); |
540 | 540 | ||
541 | IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_REASMREQDS); | 541 | IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_REASMREQDS); |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 843406f14d7b..f1be5c5c85ef 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -89,12 +89,12 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu); | |||
89 | 89 | ||
90 | #ifdef CONFIG_IPV6_ROUTE_INFO | 90 | #ifdef CONFIG_IPV6_ROUTE_INFO |
91 | static struct rt6_info *rt6_add_route_info(struct net *net, | 91 | static struct rt6_info *rt6_add_route_info(struct net *net, |
92 | struct in6_addr *prefix, int prefixlen, | 92 | const struct in6_addr *prefix, int prefixlen, |
93 | struct in6_addr *gwaddr, int ifindex, | 93 | const struct in6_addr *gwaddr, int ifindex, |
94 | unsigned pref); | 94 | unsigned pref); |
95 | static struct rt6_info *rt6_get_route_info(struct net *net, | 95 | static struct rt6_info *rt6_get_route_info(struct net *net, |
96 | struct in6_addr *prefix, int prefixlen, | 96 | const struct in6_addr *prefix, int prefixlen, |
97 | struct in6_addr *gwaddr, int ifindex); | 97 | const struct in6_addr *gwaddr, int ifindex); |
98 | #endif | 98 | #endif |
99 | 99 | ||
100 | static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old) | 100 | static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old) |
@@ -153,6 +153,12 @@ static void ip6_rt_blackhole_update_pmtu(struct dst_entry *dst, u32 mtu) | |||
153 | { | 153 | { |
154 | } | 154 | } |
155 | 155 | ||
156 | static u32 *ip6_rt_blackhole_cow_metrics(struct dst_entry *dst, | ||
157 | unsigned long old) | ||
158 | { | ||
159 | return NULL; | ||
160 | } | ||
161 | |||
156 | static struct dst_ops ip6_dst_blackhole_ops = { | 162 | static struct dst_ops ip6_dst_blackhole_ops = { |
157 | .family = AF_INET6, | 163 | .family = AF_INET6, |
158 | .protocol = cpu_to_be16(ETH_P_IPV6), | 164 | .protocol = cpu_to_be16(ETH_P_IPV6), |
@@ -161,6 +167,7 @@ static struct dst_ops ip6_dst_blackhole_ops = { | |||
161 | .default_mtu = ip6_blackhole_default_mtu, | 167 | .default_mtu = ip6_blackhole_default_mtu, |
162 | .default_advmss = ip6_default_advmss, | 168 | .default_advmss = ip6_default_advmss, |
163 | .update_pmtu = ip6_rt_blackhole_update_pmtu, | 169 | .update_pmtu = ip6_rt_blackhole_update_pmtu, |
170 | .cow_metrics = ip6_rt_blackhole_cow_metrics, | ||
164 | }; | 171 | }; |
165 | 172 | ||
166 | static const u32 ip6_template_metrics[RTAX_MAX] = { | 173 | static const u32 ip6_template_metrics[RTAX_MAX] = { |
@@ -220,9 +227,14 @@ static struct rt6_info ip6_blk_hole_entry_template = { | |||
220 | #endif | 227 | #endif |
221 | 228 | ||
222 | /* allocate dst with ip6_dst_ops */ | 229 | /* allocate dst with ip6_dst_ops */ |
223 | static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops) | 230 | static inline struct rt6_info *ip6_dst_alloc(struct dst_ops *ops, |
231 | struct net_device *dev) | ||
224 | { | 232 | { |
225 | return (struct rt6_info *)dst_alloc(ops, 0); | 233 | struct rt6_info *rt = dst_alloc(ops, dev, 0, 0, 0); |
234 | |||
235 | memset(&rt->rt6i_table, 0, sizeof(*rt) - sizeof(struct dst_entry)); | ||
236 | |||
237 | return rt; | ||
226 | } | 238 | } |
227 | 239 | ||
228 | static void ip6_dst_destroy(struct dst_entry *dst) | 240 | static void ip6_dst_destroy(struct dst_entry *dst) |
@@ -283,7 +295,7 @@ static __inline__ int rt6_check_expired(const struct rt6_info *rt) | |||
283 | time_after(jiffies, rt->rt6i_expires); | 295 | time_after(jiffies, rt->rt6i_expires); |
284 | } | 296 | } |
285 | 297 | ||
286 | static inline int rt6_need_strict(struct in6_addr *daddr) | 298 | static inline int rt6_need_strict(const struct in6_addr *daddr) |
287 | { | 299 | { |
288 | return ipv6_addr_type(daddr) & | 300 | return ipv6_addr_type(daddr) & |
289 | (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK); | 301 | (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK); |
@@ -295,7 +307,7 @@ static inline int rt6_need_strict(struct in6_addr *daddr) | |||
295 | 307 | ||
296 | static inline struct rt6_info *rt6_device_match(struct net *net, | 308 | static inline struct rt6_info *rt6_device_match(struct net *net, |
297 | struct rt6_info *rt, | 309 | struct rt6_info *rt, |
298 | struct in6_addr *saddr, | 310 | const struct in6_addr *saddr, |
299 | int oif, | 311 | int oif, |
300 | int flags) | 312 | int flags) |
301 | { | 313 | { |
@@ -507,7 +519,7 @@ static struct rt6_info *rt6_select(struct fib6_node *fn, int oif, int strict) | |||
507 | 519 | ||
508 | #ifdef CONFIG_IPV6_ROUTE_INFO | 520 | #ifdef CONFIG_IPV6_ROUTE_INFO |
509 | int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, | 521 | int rt6_route_rcv(struct net_device *dev, u8 *opt, int len, |
510 | struct in6_addr *gwaddr) | 522 | const struct in6_addr *gwaddr) |
511 | { | 523 | { |
512 | struct net *net = dev_net(dev); | 524 | struct net *net = dev_net(dev); |
513 | struct route_info *rinfo = (struct route_info *) opt; | 525 | struct route_info *rinfo = (struct route_info *) opt; |
@@ -670,8 +682,8 @@ int ip6_ins_rt(struct rt6_info *rt) | |||
670 | return __ip6_ins_rt(rt, &info); | 682 | return __ip6_ins_rt(rt, &info); |
671 | } | 683 | } |
672 | 684 | ||
673 | static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *daddr, | 685 | static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, const struct in6_addr *daddr, |
674 | struct in6_addr *saddr) | 686 | const struct in6_addr *saddr) |
675 | { | 687 | { |
676 | struct rt6_info *rt; | 688 | struct rt6_info *rt; |
677 | 689 | ||
@@ -739,7 +751,7 @@ static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, struct in6_addr *dad | |||
739 | return rt; | 751 | return rt; |
740 | } | 752 | } |
741 | 753 | ||
742 | static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, struct in6_addr *daddr) | 754 | static struct rt6_info *rt6_alloc_clone(struct rt6_info *ort, const struct in6_addr *daddr) |
743 | { | 755 | { |
744 | struct rt6_info *rt = ip6_rt_copy(ort); | 756 | struct rt6_info *rt = ip6_rt_copy(ort); |
745 | if (rt) { | 757 | if (rt) { |
@@ -830,7 +842,7 @@ static struct rt6_info *ip6_pol_route_input(struct net *net, struct fib6_table * | |||
830 | 842 | ||
831 | void ip6_route_input(struct sk_buff *skb) | 843 | void ip6_route_input(struct sk_buff *skb) |
832 | { | 844 | { |
833 | struct ipv6hdr *iph = ipv6_hdr(skb); | 845 | const struct ipv6hdr *iph = ipv6_hdr(skb); |
834 | struct net *net = dev_net(skb->dev); | 846 | struct net *net = dev_net(skb->dev); |
835 | int flags = RT6_LOOKUP_F_HAS_SADDR; | 847 | int flags = RT6_LOOKUP_F_HAS_SADDR; |
836 | struct flowi6 fl6 = { | 848 | struct flowi6 fl6 = { |
@@ -874,11 +886,13 @@ EXPORT_SYMBOL(ip6_route_output); | |||
874 | 886 | ||
875 | struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_orig) | 887 | struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_orig) |
876 | { | 888 | { |
877 | struct rt6_info *rt = dst_alloc(&ip6_dst_blackhole_ops, 1); | 889 | struct rt6_info *rt, *ort = (struct rt6_info *) dst_orig; |
878 | struct rt6_info *ort = (struct rt6_info *) dst_orig; | ||
879 | struct dst_entry *new = NULL; | 890 | struct dst_entry *new = NULL; |
880 | 891 | ||
892 | rt = dst_alloc(&ip6_dst_blackhole_ops, ort->dst.dev, 1, 0, 0); | ||
881 | if (rt) { | 893 | if (rt) { |
894 | memset(&rt->rt6i_table, 0, sizeof(*rt) - sizeof(struct dst_entry)); | ||
895 | |||
882 | new = &rt->dst; | 896 | new = &rt->dst; |
883 | 897 | ||
884 | new->__use = 1; | 898 | new->__use = 1; |
@@ -886,9 +900,6 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori | |||
886 | new->output = dst_discard; | 900 | new->output = dst_discard; |
887 | 901 | ||
888 | dst_copy_metrics(new, &ort->dst); | 902 | dst_copy_metrics(new, &ort->dst); |
889 | new->dev = ort->dst.dev; | ||
890 | if (new->dev) | ||
891 | dev_hold(new->dev); | ||
892 | rt->rt6i_idev = ort->rt6i_idev; | 903 | rt->rt6i_idev = ort->rt6i_idev; |
893 | if (rt->rt6i_idev) | 904 | if (rt->rt6i_idev) |
894 | in6_dev_hold(rt->rt6i_idev); | 905 | in6_dev_hold(rt->rt6i_idev); |
@@ -1031,13 +1042,12 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | |||
1031 | if (unlikely(idev == NULL)) | 1042 | if (unlikely(idev == NULL)) |
1032 | return NULL; | 1043 | return NULL; |
1033 | 1044 | ||
1034 | rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops); | 1045 | rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, dev); |
1035 | if (unlikely(rt == NULL)) { | 1046 | if (unlikely(rt == NULL)) { |
1036 | in6_dev_put(idev); | 1047 | in6_dev_put(idev); |
1037 | goto out; | 1048 | goto out; |
1038 | } | 1049 | } |
1039 | 1050 | ||
1040 | dev_hold(dev); | ||
1041 | if (neigh) | 1051 | if (neigh) |
1042 | neigh_hold(neigh); | 1052 | neigh_hold(neigh); |
1043 | else { | 1053 | else { |
@@ -1046,7 +1056,6 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | |||
1046 | neigh = NULL; | 1056 | neigh = NULL; |
1047 | } | 1057 | } |
1048 | 1058 | ||
1049 | rt->rt6i_dev = dev; | ||
1050 | rt->rt6i_idev = idev; | 1059 | rt->rt6i_idev = idev; |
1051 | rt->rt6i_nexthop = neigh; | 1060 | rt->rt6i_nexthop = neigh; |
1052 | atomic_set(&rt->dst.__refcnt, 1); | 1061 | atomic_set(&rt->dst.__refcnt, 1); |
@@ -1205,7 +1214,7 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1205 | goto out; | 1214 | goto out; |
1206 | } | 1215 | } |
1207 | 1216 | ||
1208 | rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops); | 1217 | rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, NULL); |
1209 | 1218 | ||
1210 | if (rt == NULL) { | 1219 | if (rt == NULL) { |
1211 | err = -ENOMEM; | 1220 | err = -ENOMEM; |
@@ -1272,7 +1281,7 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1272 | } | 1281 | } |
1273 | 1282 | ||
1274 | if (cfg->fc_flags & RTF_GATEWAY) { | 1283 | if (cfg->fc_flags & RTF_GATEWAY) { |
1275 | struct in6_addr *gw_addr; | 1284 | const struct in6_addr *gw_addr; |
1276 | int gwa_type; | 1285 | int gwa_type; |
1277 | 1286 | ||
1278 | gw_addr = &cfg->fc_gateway; | 1287 | gw_addr = &cfg->fc_gateway; |
@@ -1325,6 +1334,16 @@ int ip6_route_add(struct fib6_config *cfg) | |||
1325 | if (dev == NULL) | 1334 | if (dev == NULL) |
1326 | goto out; | 1335 | goto out; |
1327 | 1336 | ||
1337 | if (!ipv6_addr_any(&cfg->fc_prefsrc)) { | ||
1338 | if (!ipv6_chk_addr(net, &cfg->fc_prefsrc, dev, 0)) { | ||
1339 | err = -EINVAL; | ||
1340 | goto out; | ||
1341 | } | ||
1342 | ipv6_addr_copy(&rt->rt6i_prefsrc.addr, &cfg->fc_prefsrc); | ||
1343 | rt->rt6i_prefsrc.plen = 128; | ||
1344 | } else | ||
1345 | rt->rt6i_prefsrc.plen = 0; | ||
1346 | |||
1328 | if (cfg->fc_flags & (RTF_GATEWAY | RTF_NONEXTHOP)) { | 1347 | if (cfg->fc_flags & (RTF_GATEWAY | RTF_NONEXTHOP)) { |
1329 | rt->rt6i_nexthop = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, dev); | 1348 | rt->rt6i_nexthop = __neigh_lookup_errno(&nd_tbl, &rt->rt6i_gateway, dev); |
1330 | if (IS_ERR(rt->rt6i_nexthop)) { | 1349 | if (IS_ERR(rt->rt6i_nexthop)) { |
@@ -1502,9 +1521,9 @@ out: | |||
1502 | return rt; | 1521 | return rt; |
1503 | }; | 1522 | }; |
1504 | 1523 | ||
1505 | static struct rt6_info *ip6_route_redirect(struct in6_addr *dest, | 1524 | static struct rt6_info *ip6_route_redirect(const struct in6_addr *dest, |
1506 | struct in6_addr *src, | 1525 | const struct in6_addr *src, |
1507 | struct in6_addr *gateway, | 1526 | const struct in6_addr *gateway, |
1508 | struct net_device *dev) | 1527 | struct net_device *dev) |
1509 | { | 1528 | { |
1510 | int flags = RT6_LOOKUP_F_HAS_SADDR; | 1529 | int flags = RT6_LOOKUP_F_HAS_SADDR; |
@@ -1526,8 +1545,8 @@ static struct rt6_info *ip6_route_redirect(struct in6_addr *dest, | |||
1526 | flags, __ip6_route_redirect); | 1545 | flags, __ip6_route_redirect); |
1527 | } | 1546 | } |
1528 | 1547 | ||
1529 | void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, | 1548 | void rt6_redirect(const struct in6_addr *dest, const struct in6_addr *src, |
1530 | struct in6_addr *saddr, | 1549 | const struct in6_addr *saddr, |
1531 | struct neighbour *neigh, u8 *lladdr, int on_link) | 1550 | struct neighbour *neigh, u8 *lladdr, int on_link) |
1532 | { | 1551 | { |
1533 | struct rt6_info *rt, *nrt = NULL; | 1552 | struct rt6_info *rt, *nrt = NULL; |
@@ -1601,7 +1620,7 @@ out: | |||
1601 | * i.e. Path MTU discovery | 1620 | * i.e. Path MTU discovery |
1602 | */ | 1621 | */ |
1603 | 1622 | ||
1604 | static void rt6_do_pmtu_disc(struct in6_addr *daddr, struct in6_addr *saddr, | 1623 | static void rt6_do_pmtu_disc(const struct in6_addr *daddr, const struct in6_addr *saddr, |
1605 | struct net *net, u32 pmtu, int ifindex) | 1624 | struct net *net, u32 pmtu, int ifindex) |
1606 | { | 1625 | { |
1607 | struct rt6_info *rt, *nrt; | 1626 | struct rt6_info *rt, *nrt; |
@@ -1686,7 +1705,7 @@ out: | |||
1686 | dst_release(&rt->dst); | 1705 | dst_release(&rt->dst); |
1687 | } | 1706 | } |
1688 | 1707 | ||
1689 | void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, | 1708 | void rt6_pmtu_discovery(const struct in6_addr *daddr, const struct in6_addr *saddr, |
1690 | struct net_device *dev, u32 pmtu) | 1709 | struct net_device *dev, u32 pmtu) |
1691 | { | 1710 | { |
1692 | struct net *net = dev_net(dev); | 1711 | struct net *net = dev_net(dev); |
@@ -1714,7 +1733,8 @@ void rt6_pmtu_discovery(struct in6_addr *daddr, struct in6_addr *saddr, | |||
1714 | static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) | 1733 | static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) |
1715 | { | 1734 | { |
1716 | struct net *net = dev_net(ort->rt6i_dev); | 1735 | struct net *net = dev_net(ort->rt6i_dev); |
1717 | struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops); | 1736 | struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, |
1737 | ort->dst.dev); | ||
1718 | 1738 | ||
1719 | if (rt) { | 1739 | if (rt) { |
1720 | rt->dst.input = ort->dst.input; | 1740 | rt->dst.input = ort->dst.input; |
@@ -1722,9 +1742,6 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) | |||
1722 | 1742 | ||
1723 | dst_copy_metrics(&rt->dst, &ort->dst); | 1743 | dst_copy_metrics(&rt->dst, &ort->dst); |
1724 | rt->dst.error = ort->dst.error; | 1744 | rt->dst.error = ort->dst.error; |
1725 | rt->dst.dev = ort->dst.dev; | ||
1726 | if (rt->dst.dev) | ||
1727 | dev_hold(rt->dst.dev); | ||
1728 | rt->rt6i_idev = ort->rt6i_idev; | 1745 | rt->rt6i_idev = ort->rt6i_idev; |
1729 | if (rt->rt6i_idev) | 1746 | if (rt->rt6i_idev) |
1730 | in6_dev_hold(rt->rt6i_idev); | 1747 | in6_dev_hold(rt->rt6i_idev); |
@@ -1746,8 +1763,8 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) | |||
1746 | 1763 | ||
1747 | #ifdef CONFIG_IPV6_ROUTE_INFO | 1764 | #ifdef CONFIG_IPV6_ROUTE_INFO |
1748 | static struct rt6_info *rt6_get_route_info(struct net *net, | 1765 | static struct rt6_info *rt6_get_route_info(struct net *net, |
1749 | struct in6_addr *prefix, int prefixlen, | 1766 | const struct in6_addr *prefix, int prefixlen, |
1750 | struct in6_addr *gwaddr, int ifindex) | 1767 | const struct in6_addr *gwaddr, int ifindex) |
1751 | { | 1768 | { |
1752 | struct fib6_node *fn; | 1769 | struct fib6_node *fn; |
1753 | struct rt6_info *rt = NULL; | 1770 | struct rt6_info *rt = NULL; |
@@ -1778,8 +1795,8 @@ out: | |||
1778 | } | 1795 | } |
1779 | 1796 | ||
1780 | static struct rt6_info *rt6_add_route_info(struct net *net, | 1797 | static struct rt6_info *rt6_add_route_info(struct net *net, |
1781 | struct in6_addr *prefix, int prefixlen, | 1798 | const struct in6_addr *prefix, int prefixlen, |
1782 | struct in6_addr *gwaddr, int ifindex, | 1799 | const struct in6_addr *gwaddr, int ifindex, |
1783 | unsigned pref) | 1800 | unsigned pref) |
1784 | { | 1801 | { |
1785 | struct fib6_config cfg = { | 1802 | struct fib6_config cfg = { |
@@ -1807,7 +1824,7 @@ static struct rt6_info *rt6_add_route_info(struct net *net, | |||
1807 | } | 1824 | } |
1808 | #endif | 1825 | #endif |
1809 | 1826 | ||
1810 | struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *dev) | 1827 | struct rt6_info *rt6_get_dflt_router(const struct in6_addr *addr, struct net_device *dev) |
1811 | { | 1828 | { |
1812 | struct rt6_info *rt; | 1829 | struct rt6_info *rt; |
1813 | struct fib6_table *table; | 1830 | struct fib6_table *table; |
@@ -1829,7 +1846,7 @@ struct rt6_info *rt6_get_dflt_router(struct in6_addr *addr, struct net_device *d | |||
1829 | return rt; | 1846 | return rt; |
1830 | } | 1847 | } |
1831 | 1848 | ||
1832 | struct rt6_info *rt6_add_dflt_router(struct in6_addr *gwaddr, | 1849 | struct rt6_info *rt6_add_dflt_router(const struct in6_addr *gwaddr, |
1833 | struct net_device *dev, | 1850 | struct net_device *dev, |
1834 | unsigned int pref) | 1851 | unsigned int pref) |
1835 | { | 1852 | { |
@@ -1994,7 +2011,8 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
1994 | int anycast) | 2011 | int anycast) |
1995 | { | 2012 | { |
1996 | struct net *net = dev_net(idev->dev); | 2013 | struct net *net = dev_net(idev->dev); |
1997 | struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops); | 2014 | struct rt6_info *rt = ip6_dst_alloc(&net->ipv6.ip6_dst_ops, |
2015 | net->loopback_dev); | ||
1998 | struct neighbour *neigh; | 2016 | struct neighbour *neigh; |
1999 | 2017 | ||
2000 | if (rt == NULL) { | 2018 | if (rt == NULL) { |
@@ -2004,15 +2022,12 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
2004 | return ERR_PTR(-ENOMEM); | 2022 | return ERR_PTR(-ENOMEM); |
2005 | } | 2023 | } |
2006 | 2024 | ||
2007 | dev_hold(net->loopback_dev); | ||
2008 | in6_dev_hold(idev); | 2025 | in6_dev_hold(idev); |
2009 | 2026 | ||
2010 | rt->dst.flags = DST_HOST; | 2027 | rt->dst.flags = DST_HOST; |
2011 | rt->dst.input = ip6_input; | 2028 | rt->dst.input = ip6_input; |
2012 | rt->dst.output = ip6_output; | 2029 | rt->dst.output = ip6_output; |
2013 | rt->rt6i_dev = net->loopback_dev; | ||
2014 | rt->rt6i_idev = idev; | 2030 | rt->rt6i_idev = idev; |
2015 | dst_metric_set(&rt->dst, RTAX_HOPLIMIT, -1); | ||
2016 | rt->dst.obsolete = -1; | 2031 | rt->dst.obsolete = -1; |
2017 | 2032 | ||
2018 | rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP; | 2033 | rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP; |
@@ -2037,6 +2052,55 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
2037 | return rt; | 2052 | return rt; |
2038 | } | 2053 | } |
2039 | 2054 | ||
2055 | int ip6_route_get_saddr(struct net *net, | ||
2056 | struct rt6_info *rt, | ||
2057 | const struct in6_addr *daddr, | ||
2058 | unsigned int prefs, | ||
2059 | struct in6_addr *saddr) | ||
2060 | { | ||
2061 | struct inet6_dev *idev = ip6_dst_idev((struct dst_entry*)rt); | ||
2062 | int err = 0; | ||
2063 | if (rt->rt6i_prefsrc.plen) | ||
2064 | ipv6_addr_copy(saddr, &rt->rt6i_prefsrc.addr); | ||
2065 | else | ||
2066 | err = ipv6_dev_get_saddr(net, idev ? idev->dev : NULL, | ||
2067 | daddr, prefs, saddr); | ||
2068 | return err; | ||
2069 | } | ||
2070 | |||
2071 | /* remove deleted ip from prefsrc entries */ | ||
2072 | struct arg_dev_net_ip { | ||
2073 | struct net_device *dev; | ||
2074 | struct net *net; | ||
2075 | struct in6_addr *addr; | ||
2076 | }; | ||
2077 | |||
2078 | static int fib6_remove_prefsrc(struct rt6_info *rt, void *arg) | ||
2079 | { | ||
2080 | struct net_device *dev = ((struct arg_dev_net_ip *)arg)->dev; | ||
2081 | struct net *net = ((struct arg_dev_net_ip *)arg)->net; | ||
2082 | struct in6_addr *addr = ((struct arg_dev_net_ip *)arg)->addr; | ||
2083 | |||
2084 | if (((void *)rt->rt6i_dev == dev || dev == NULL) && | ||
2085 | rt != net->ipv6.ip6_null_entry && | ||
2086 | ipv6_addr_equal(addr, &rt->rt6i_prefsrc.addr)) { | ||
2087 | /* remove prefsrc entry */ | ||
2088 | rt->rt6i_prefsrc.plen = 0; | ||
2089 | } | ||
2090 | return 0; | ||
2091 | } | ||
2092 | |||
2093 | void rt6_remove_prefsrc(struct inet6_ifaddr *ifp) | ||
2094 | { | ||
2095 | struct net *net = dev_net(ifp->idev->dev); | ||
2096 | struct arg_dev_net_ip adni = { | ||
2097 | .dev = ifp->idev->dev, | ||
2098 | .net = net, | ||
2099 | .addr = &ifp->addr, | ||
2100 | }; | ||
2101 | fib6_clean_all(net, fib6_remove_prefsrc, 0, &adni); | ||
2102 | } | ||
2103 | |||
2040 | struct arg_dev_net { | 2104 | struct arg_dev_net { |
2041 | struct net_device *dev; | 2105 | struct net_device *dev; |
2042 | struct net *net; | 2106 | struct net *net; |
@@ -2183,6 +2247,9 @@ static int rtm_to_fib6_config(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
2183 | nla_memcpy(&cfg->fc_src, tb[RTA_SRC], plen); | 2247 | nla_memcpy(&cfg->fc_src, tb[RTA_SRC], plen); |
2184 | } | 2248 | } |
2185 | 2249 | ||
2250 | if (tb[RTA_PREFSRC]) | ||
2251 | nla_memcpy(&cfg->fc_prefsrc, tb[RTA_PREFSRC], 16); | ||
2252 | |||
2186 | if (tb[RTA_OIF]) | 2253 | if (tb[RTA_OIF]) |
2187 | cfg->fc_ifindex = nla_get_u32(tb[RTA_OIF]); | 2254 | cfg->fc_ifindex = nla_get_u32(tb[RTA_OIF]); |
2188 | 2255 | ||
@@ -2325,13 +2392,17 @@ static int rt6_fill_node(struct net *net, | |||
2325 | #endif | 2392 | #endif |
2326 | NLA_PUT_U32(skb, RTA_IIF, iif); | 2393 | NLA_PUT_U32(skb, RTA_IIF, iif); |
2327 | } else if (dst) { | 2394 | } else if (dst) { |
2328 | struct inet6_dev *idev = ip6_dst_idev(&rt->dst); | ||
2329 | struct in6_addr saddr_buf; | 2395 | struct in6_addr saddr_buf; |
2330 | if (ipv6_dev_get_saddr(net, idev ? idev->dev : NULL, | 2396 | if (ip6_route_get_saddr(net, rt, dst, 0, &saddr_buf) == 0) |
2331 | dst, 0, &saddr_buf) == 0) | ||
2332 | NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); | 2397 | NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); |
2333 | } | 2398 | } |
2334 | 2399 | ||
2400 | if (rt->rt6i_prefsrc.plen) { | ||
2401 | struct in6_addr saddr_buf; | ||
2402 | ipv6_addr_copy(&saddr_buf, &rt->rt6i_prefsrc.addr); | ||
2403 | NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); | ||
2404 | } | ||
2405 | |||
2335 | if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0) | 2406 | if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0) |
2336 | goto nla_put_failure; | 2407 | goto nla_put_failure; |
2337 | 2408 | ||
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 43b33373adb2..a6a32b39b607 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -250,11 +250,6 @@ static struct ip_tunnel *ipip6_tunnel_locate(struct net *net, | |||
250 | 250 | ||
251 | dev_net_set(dev, net); | 251 | dev_net_set(dev, net); |
252 | 252 | ||
253 | if (strchr(name, '%')) { | ||
254 | if (dev_alloc_name(dev, name) < 0) | ||
255 | goto failed_free; | ||
256 | } | ||
257 | |||
258 | nt = netdev_priv(dev); | 253 | nt = netdev_priv(dev); |
259 | 254 | ||
260 | nt->parms = *parms; | 255 | nt->parms = *parms; |
@@ -452,7 +447,7 @@ out: | |||
452 | } | 447 | } |
453 | 448 | ||
454 | static int | 449 | static int |
455 | isatap_chksrc(struct sk_buff *skb, struct iphdr *iph, struct ip_tunnel *t) | 450 | isatap_chksrc(struct sk_buff *skb, const struct iphdr *iph, struct ip_tunnel *t) |
456 | { | 451 | { |
457 | struct ip_tunnel_prl_entry *p; | 452 | struct ip_tunnel_prl_entry *p; |
458 | int ok = 1; | 453 | int ok = 1; |
@@ -465,7 +460,8 @@ isatap_chksrc(struct sk_buff *skb, struct iphdr *iph, struct ip_tunnel *t) | |||
465 | else | 460 | else |
466 | skb->ndisc_nodetype = NDISC_NODETYPE_NODEFAULT; | 461 | skb->ndisc_nodetype = NDISC_NODETYPE_NODEFAULT; |
467 | } else { | 462 | } else { |
468 | struct in6_addr *addr6 = &ipv6_hdr(skb)->saddr; | 463 | const struct in6_addr *addr6 = &ipv6_hdr(skb)->saddr; |
464 | |||
469 | if (ipv6_addr_is_isatap(addr6) && | 465 | if (ipv6_addr_is_isatap(addr6) && |
470 | (addr6->s6_addr32[3] == iph->saddr) && | 466 | (addr6->s6_addr32[3] == iph->saddr) && |
471 | ipv6_chk_prefix(addr6, t->dev)) | 467 | ipv6_chk_prefix(addr6, t->dev)) |
@@ -499,7 +495,7 @@ static int ipip6_err(struct sk_buff *skb, u32 info) | |||
499 | 8 bytes of packet payload. It means, that precise relaying of | 495 | 8 bytes of packet payload. It means, that precise relaying of |
500 | ICMP in the real Internet is absolutely infeasible. | 496 | ICMP in the real Internet is absolutely infeasible. |
501 | */ | 497 | */ |
502 | struct iphdr *iph = (struct iphdr*)skb->data; | 498 | const struct iphdr *iph = (const struct iphdr *)skb->data; |
503 | const int type = icmp_hdr(skb)->type; | 499 | const int type = icmp_hdr(skb)->type; |
504 | const int code = icmp_hdr(skb)->code; | 500 | const int code = icmp_hdr(skb)->code; |
505 | struct ip_tunnel *t; | 501 | struct ip_tunnel *t; |
@@ -557,7 +553,7 @@ out: | |||
557 | return err; | 553 | return err; |
558 | } | 554 | } |
559 | 555 | ||
560 | static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb) | 556 | static inline void ipip6_ecn_decapsulate(const struct iphdr *iph, struct sk_buff *skb) |
561 | { | 557 | { |
562 | if (INET_ECN_is_ce(iph->tos)) | 558 | if (INET_ECN_is_ce(iph->tos)) |
563 | IP6_ECN_set_ce(ipv6_hdr(skb)); | 559 | IP6_ECN_set_ce(ipv6_hdr(skb)); |
@@ -565,7 +561,7 @@ static inline void ipip6_ecn_decapsulate(struct iphdr *iph, struct sk_buff *skb) | |||
565 | 561 | ||
566 | static int ipip6_rcv(struct sk_buff *skb) | 562 | static int ipip6_rcv(struct sk_buff *skb) |
567 | { | 563 | { |
568 | struct iphdr *iph; | 564 | const struct iphdr *iph; |
569 | struct ip_tunnel *tunnel; | 565 | struct ip_tunnel *tunnel; |
570 | 566 | ||
571 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) | 567 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) |
@@ -621,7 +617,7 @@ out: | |||
621 | * comes from 6rd / 6to4 (RFC 3056) addr space. | 617 | * comes from 6rd / 6to4 (RFC 3056) addr space. |
622 | */ | 618 | */ |
623 | static inline | 619 | static inline |
624 | __be32 try_6rd(struct in6_addr *v6dst, struct ip_tunnel *tunnel) | 620 | __be32 try_6rd(const struct in6_addr *v6dst, struct ip_tunnel *tunnel) |
625 | { | 621 | { |
626 | __be32 dst = 0; | 622 | __be32 dst = 0; |
627 | 623 | ||
@@ -664,8 +660,8 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
664 | { | 660 | { |
665 | struct ip_tunnel *tunnel = netdev_priv(dev); | 661 | struct ip_tunnel *tunnel = netdev_priv(dev); |
666 | struct pcpu_tstats *tstats; | 662 | struct pcpu_tstats *tstats; |
667 | struct iphdr *tiph = &tunnel->parms.iph; | 663 | const struct iphdr *tiph = &tunnel->parms.iph; |
668 | struct ipv6hdr *iph6 = ipv6_hdr(skb); | 664 | const struct ipv6hdr *iph6 = ipv6_hdr(skb); |
669 | u8 tos = tunnel->parms.iph.tos; | 665 | u8 tos = tunnel->parms.iph.tos; |
670 | __be16 df = tiph->frag_off; | 666 | __be16 df = tiph->frag_off; |
671 | struct rtable *rt; /* Route to the other host */ | 667 | struct rtable *rt; /* Route to the other host */ |
@@ -673,8 +669,9 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
673 | struct iphdr *iph; /* Our new IP header */ | 669 | struct iphdr *iph; /* Our new IP header */ |
674 | unsigned int max_headroom; /* The extra header space needed */ | 670 | unsigned int max_headroom; /* The extra header space needed */ |
675 | __be32 dst = tiph->daddr; | 671 | __be32 dst = tiph->daddr; |
672 | struct flowi4 fl4; | ||
676 | int mtu; | 673 | int mtu; |
677 | struct in6_addr *addr6; | 674 | const struct in6_addr *addr6; |
678 | int addr_type; | 675 | int addr_type; |
679 | 676 | ||
680 | if (skb->protocol != htons(ETH_P_IPV6)) | 677 | if (skb->protocol != htons(ETH_P_IPV6)) |
@@ -693,7 +690,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
693 | goto tx_error; | 690 | goto tx_error; |
694 | } | 691 | } |
695 | 692 | ||
696 | addr6 = (struct in6_addr*)&neigh->primary_key; | 693 | addr6 = (const struct in6_addr*)&neigh->primary_key; |
697 | addr_type = ipv6_addr_type(addr6); | 694 | addr_type = ipv6_addr_type(addr6); |
698 | 695 | ||
699 | if ((addr_type & IPV6_ADDR_UNICAST) && | 696 | if ((addr_type & IPV6_ADDR_UNICAST) && |
@@ -718,7 +715,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
718 | goto tx_error; | 715 | goto tx_error; |
719 | } | 716 | } |
720 | 717 | ||
721 | addr6 = (struct in6_addr*)&neigh->primary_key; | 718 | addr6 = (const struct in6_addr*)&neigh->primary_key; |
722 | addr_type = ipv6_addr_type(addr6); | 719 | addr_type = ipv6_addr_type(addr6); |
723 | 720 | ||
724 | if (addr_type == IPV6_ADDR_ANY) { | 721 | if (addr_type == IPV6_ADDR_ANY) { |
@@ -732,7 +729,7 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
732 | dst = addr6->s6_addr32[3]; | 729 | dst = addr6->s6_addr32[3]; |
733 | } | 730 | } |
734 | 731 | ||
735 | rt = ip_route_output_ports(dev_net(dev), NULL, | 732 | rt = ip_route_output_ports(dev_net(dev), &fl4, NULL, |
736 | dst, tiph->saddr, | 733 | dst, tiph->saddr, |
737 | 0, 0, | 734 | 0, 0, |
738 | IPPROTO_IPV6, RT_TOS(tos), | 735 | IPPROTO_IPV6, RT_TOS(tos), |
@@ -826,8 +823,8 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
826 | iph->frag_off = df; | 823 | iph->frag_off = df; |
827 | iph->protocol = IPPROTO_IPV6; | 824 | iph->protocol = IPPROTO_IPV6; |
828 | iph->tos = INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6)); | 825 | iph->tos = INET_ECN_encapsulate(tos, ipv6_get_dsfield(iph6)); |
829 | iph->daddr = rt->rt_dst; | 826 | iph->daddr = fl4.daddr; |
830 | iph->saddr = rt->rt_src; | 827 | iph->saddr = fl4.saddr; |
831 | 828 | ||
832 | if ((iph->ttl = tiph->ttl) == 0) | 829 | if ((iph->ttl = tiph->ttl) == 0) |
833 | iph->ttl = iph6->hop_limit; | 830 | iph->ttl = iph6->hop_limit; |
@@ -849,13 +846,14 @@ static void ipip6_tunnel_bind_dev(struct net_device *dev) | |||
849 | { | 846 | { |
850 | struct net_device *tdev = NULL; | 847 | struct net_device *tdev = NULL; |
851 | struct ip_tunnel *tunnel; | 848 | struct ip_tunnel *tunnel; |
852 | struct iphdr *iph; | 849 | const struct iphdr *iph; |
850 | struct flowi4 fl4; | ||
853 | 851 | ||
854 | tunnel = netdev_priv(dev); | 852 | tunnel = netdev_priv(dev); |
855 | iph = &tunnel->parms.iph; | 853 | iph = &tunnel->parms.iph; |
856 | 854 | ||
857 | if (iph->daddr) { | 855 | if (iph->daddr) { |
858 | struct rtable *rt = ip_route_output_ports(dev_net(dev), NULL, | 856 | struct rtable *rt = ip_route_output_ports(dev_net(dev), &fl4, NULL, |
859 | iph->daddr, iph->saddr, | 857 | iph->daddr, iph->saddr, |
860 | 0, 0, | 858 | 0, 0, |
861 | IPPROTO_IPV6, | 859 | IPPROTO_IPV6, |
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index 352c26081f5d..8b9644a8b697 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c | |||
@@ -66,7 +66,7 @@ static inline struct sock *get_cookie_sock(struct sock *sk, struct sk_buff *skb, | |||
66 | static DEFINE_PER_CPU(__u32 [16 + 5 + SHA_WORKSPACE_WORDS], | 66 | static DEFINE_PER_CPU(__u32 [16 + 5 + SHA_WORKSPACE_WORDS], |
67 | ipv6_cookie_scratch); | 67 | ipv6_cookie_scratch); |
68 | 68 | ||
69 | static u32 cookie_hash(struct in6_addr *saddr, struct in6_addr *daddr, | 69 | static u32 cookie_hash(const struct in6_addr *saddr, const struct in6_addr *daddr, |
70 | __be16 sport, __be16 dport, u32 count, int c) | 70 | __be16 sport, __be16 dport, u32 count, int c) |
71 | { | 71 | { |
72 | __u32 *tmp = __get_cpu_var(ipv6_cookie_scratch); | 72 | __u32 *tmp = __get_cpu_var(ipv6_cookie_scratch); |
@@ -86,7 +86,8 @@ static u32 cookie_hash(struct in6_addr *saddr, struct in6_addr *daddr, | |||
86 | return tmp[17]; | 86 | return tmp[17]; |
87 | } | 87 | } |
88 | 88 | ||
89 | static __u32 secure_tcp_syn_cookie(struct in6_addr *saddr, struct in6_addr *daddr, | 89 | static __u32 secure_tcp_syn_cookie(const struct in6_addr *saddr, |
90 | const struct in6_addr *daddr, | ||
90 | __be16 sport, __be16 dport, __u32 sseq, | 91 | __be16 sport, __be16 dport, __u32 sseq, |
91 | __u32 count, __u32 data) | 92 | __u32 count, __u32 data) |
92 | { | 93 | { |
@@ -96,8 +97,8 @@ static __u32 secure_tcp_syn_cookie(struct in6_addr *saddr, struct in6_addr *dadd | |||
96 | & COOKIEMASK)); | 97 | & COOKIEMASK)); |
97 | } | 98 | } |
98 | 99 | ||
99 | static __u32 check_tcp_syn_cookie(__u32 cookie, struct in6_addr *saddr, | 100 | static __u32 check_tcp_syn_cookie(__u32 cookie, const struct in6_addr *saddr, |
100 | struct in6_addr *daddr, __be16 sport, | 101 | const struct in6_addr *daddr, __be16 sport, |
101 | __be16 dport, __u32 sseq, __u32 count, | 102 | __be16 dport, __u32 sseq, __u32 count, |
102 | __u32 maxdiff) | 103 | __u32 maxdiff) |
103 | { | 104 | { |
@@ -116,7 +117,7 @@ static __u32 check_tcp_syn_cookie(__u32 cookie, struct in6_addr *saddr, | |||
116 | 117 | ||
117 | __u32 cookie_v6_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mssp) | 118 | __u32 cookie_v6_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mssp) |
118 | { | 119 | { |
119 | struct ipv6hdr *iph = ipv6_hdr(skb); | 120 | const struct ipv6hdr *iph = ipv6_hdr(skb); |
120 | const struct tcphdr *th = tcp_hdr(skb); | 121 | const struct tcphdr *th = tcp_hdr(skb); |
121 | int mssind; | 122 | int mssind; |
122 | const __u16 mss = *mssp; | 123 | const __u16 mss = *mssp; |
@@ -138,7 +139,7 @@ __u32 cookie_v6_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mssp) | |||
138 | 139 | ||
139 | static inline int cookie_check(struct sk_buff *skb, __u32 cookie) | 140 | static inline int cookie_check(struct sk_buff *skb, __u32 cookie) |
140 | { | 141 | { |
141 | struct ipv6hdr *iph = ipv6_hdr(skb); | 142 | const struct ipv6hdr *iph = ipv6_hdr(skb); |
142 | const struct tcphdr *th = tcp_hdr(skb); | 143 | const struct tcphdr *th = tcp_hdr(skb); |
143 | __u32 seq = ntohl(th->seq) - 1; | 144 | __u32 seq = ntohl(th->seq) - 1; |
144 | __u32 mssind = check_tcp_syn_cookie(cookie, &iph->saddr, &iph->daddr, | 145 | __u32 mssind = check_tcp_syn_cookie(cookie, &iph->saddr, &iph->daddr, |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 2b0c186862c8..868366470b4a 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -76,8 +76,8 @@ static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, | |||
76 | 76 | ||
77 | static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb); | 77 | static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb); |
78 | static void __tcp_v6_send_check(struct sk_buff *skb, | 78 | static void __tcp_v6_send_check(struct sk_buff *skb, |
79 | struct in6_addr *saddr, | 79 | const struct in6_addr *saddr, |
80 | struct in6_addr *daddr); | 80 | const struct in6_addr *daddr); |
81 | 81 | ||
82 | static const struct inet_connection_sock_af_ops ipv6_mapped; | 82 | static const struct inet_connection_sock_af_ops ipv6_mapped; |
83 | static const struct inet_connection_sock_af_ops ipv6_specific; | 83 | static const struct inet_connection_sock_af_ops ipv6_specific; |
@@ -86,7 +86,7 @@ static const struct tcp_sock_af_ops tcp_sock_ipv6_specific; | |||
86 | static const struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific; | 86 | static const struct tcp_sock_af_ops tcp_sock_ipv6_mapped_specific; |
87 | #else | 87 | #else |
88 | static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, | 88 | static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, |
89 | struct in6_addr *addr) | 89 | const struct in6_addr *addr) |
90 | { | 90 | { |
91 | return NULL; | 91 | return NULL; |
92 | } | 92 | } |
@@ -106,8 +106,8 @@ static void tcp_v6_hash(struct sock *sk) | |||
106 | } | 106 | } |
107 | 107 | ||
108 | static __inline__ __sum16 tcp_v6_check(int len, | 108 | static __inline__ __sum16 tcp_v6_check(int len, |
109 | struct in6_addr *saddr, | 109 | const struct in6_addr *saddr, |
110 | struct in6_addr *daddr, | 110 | const struct in6_addr *daddr, |
111 | __wsum base) | 111 | __wsum base) |
112 | { | 112 | { |
113 | return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base); | 113 | return csum_ipv6_magic(saddr, daddr, len, IPPROTO_TCP, base); |
@@ -331,7 +331,7 @@ failure: | |||
331 | static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 331 | static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
332 | u8 type, u8 code, int offset, __be32 info) | 332 | u8 type, u8 code, int offset, __be32 info) |
333 | { | 333 | { |
334 | struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data; | 334 | const struct ipv6hdr *hdr = (const struct ipv6hdr*)skb->data; |
335 | const struct tcphdr *th = (struct tcphdr *)(skb->data+offset); | 335 | const struct tcphdr *th = (struct tcphdr *)(skb->data+offset); |
336 | struct ipv6_pinfo *np; | 336 | struct ipv6_pinfo *np; |
337 | struct sock *sk; | 337 | struct sock *sk; |
@@ -503,6 +503,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct request_sock *req, | |||
503 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false); | 503 | dst = ip6_dst_lookup_flow(sk, &fl6, final_p, false); |
504 | if (IS_ERR(dst)) { | 504 | if (IS_ERR(dst)) { |
505 | err = PTR_ERR(dst); | 505 | err = PTR_ERR(dst); |
506 | dst = NULL; | ||
506 | goto done; | 507 | goto done; |
507 | } | 508 | } |
508 | skb = tcp_make_synack(sk, dst, req, rvp); | 509 | skb = tcp_make_synack(sk, dst, req, rvp); |
@@ -550,7 +551,7 @@ static void tcp_v6_reqsk_destructor(struct request_sock *req) | |||
550 | 551 | ||
551 | #ifdef CONFIG_TCP_MD5SIG | 552 | #ifdef CONFIG_TCP_MD5SIG |
552 | static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, | 553 | static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, |
553 | struct in6_addr *addr) | 554 | const struct in6_addr *addr) |
554 | { | 555 | { |
555 | struct tcp_sock *tp = tcp_sk(sk); | 556 | struct tcp_sock *tp = tcp_sk(sk); |
556 | int i; | 557 | int i; |
@@ -579,7 +580,7 @@ static struct tcp_md5sig_key *tcp_v6_reqsk_md5_lookup(struct sock *sk, | |||
579 | return tcp_v6_md5_do_lookup(sk, &inet6_rsk(req)->rmt_addr); | 580 | return tcp_v6_md5_do_lookup(sk, &inet6_rsk(req)->rmt_addr); |
580 | } | 581 | } |
581 | 582 | ||
582 | static int tcp_v6_md5_do_add(struct sock *sk, struct in6_addr *peer, | 583 | static int tcp_v6_md5_do_add(struct sock *sk, const struct in6_addr *peer, |
583 | char *newkey, u8 newkeylen) | 584 | char *newkey, u8 newkeylen) |
584 | { | 585 | { |
585 | /* Add key to the list */ | 586 | /* Add key to the list */ |
@@ -644,7 +645,7 @@ static int tcp_v6_md5_add_func(struct sock *sk, struct sock *addr_sk, | |||
644 | newkey, newkeylen); | 645 | newkey, newkeylen); |
645 | } | 646 | } |
646 | 647 | ||
647 | static int tcp_v6_md5_do_del(struct sock *sk, struct in6_addr *peer) | 648 | static int tcp_v6_md5_do_del(struct sock *sk, const struct in6_addr *peer) |
648 | { | 649 | { |
649 | struct tcp_sock *tp = tcp_sk(sk); | 650 | struct tcp_sock *tp = tcp_sk(sk); |
650 | int i; | 651 | int i; |
@@ -752,8 +753,8 @@ static int tcp_v6_parse_md5_keys (struct sock *sk, char __user *optval, | |||
752 | } | 753 | } |
753 | 754 | ||
754 | static int tcp_v6_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp, | 755 | static int tcp_v6_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp, |
755 | struct in6_addr *daddr, | 756 | const struct in6_addr *daddr, |
756 | struct in6_addr *saddr, int nbytes) | 757 | const struct in6_addr *saddr, int nbytes) |
757 | { | 758 | { |
758 | struct tcp6_pseudohdr *bp; | 759 | struct tcp6_pseudohdr *bp; |
759 | struct scatterlist sg; | 760 | struct scatterlist sg; |
@@ -770,7 +771,7 @@ static int tcp_v6_md5_hash_pseudoheader(struct tcp_md5sig_pool *hp, | |||
770 | } | 771 | } |
771 | 772 | ||
772 | static int tcp_v6_md5_hash_hdr(char *md5_hash, struct tcp_md5sig_key *key, | 773 | static int tcp_v6_md5_hash_hdr(char *md5_hash, struct tcp_md5sig_key *key, |
773 | struct in6_addr *daddr, struct in6_addr *saddr, | 774 | const struct in6_addr *daddr, struct in6_addr *saddr, |
774 | struct tcphdr *th) | 775 | struct tcphdr *th) |
775 | { | 776 | { |
776 | struct tcp_md5sig_pool *hp; | 777 | struct tcp_md5sig_pool *hp; |
@@ -806,7 +807,7 @@ static int tcp_v6_md5_hash_skb(char *md5_hash, struct tcp_md5sig_key *key, | |||
806 | struct sock *sk, struct request_sock *req, | 807 | struct sock *sk, struct request_sock *req, |
807 | struct sk_buff *skb) | 808 | struct sk_buff *skb) |
808 | { | 809 | { |
809 | struct in6_addr *saddr, *daddr; | 810 | const struct in6_addr *saddr, *daddr; |
810 | struct tcp_md5sig_pool *hp; | 811 | struct tcp_md5sig_pool *hp; |
811 | struct hash_desc *desc; | 812 | struct hash_desc *desc; |
812 | struct tcphdr *th = tcp_hdr(skb); | 813 | struct tcphdr *th = tcp_hdr(skb); |
@@ -818,7 +819,7 @@ static int tcp_v6_md5_hash_skb(char *md5_hash, struct tcp_md5sig_key *key, | |||
818 | saddr = &inet6_rsk(req)->loc_addr; | 819 | saddr = &inet6_rsk(req)->loc_addr; |
819 | daddr = &inet6_rsk(req)->rmt_addr; | 820 | daddr = &inet6_rsk(req)->rmt_addr; |
820 | } else { | 821 | } else { |
821 | struct ipv6hdr *ip6h = ipv6_hdr(skb); | 822 | const struct ipv6hdr *ip6h = ipv6_hdr(skb); |
822 | saddr = &ip6h->saddr; | 823 | saddr = &ip6h->saddr; |
823 | daddr = &ip6h->daddr; | 824 | daddr = &ip6h->daddr; |
824 | } | 825 | } |
@@ -856,7 +857,7 @@ static int tcp_v6_inbound_md5_hash (struct sock *sk, struct sk_buff *skb) | |||
856 | { | 857 | { |
857 | __u8 *hash_location = NULL; | 858 | __u8 *hash_location = NULL; |
858 | struct tcp_md5sig_key *hash_expected; | 859 | struct tcp_md5sig_key *hash_expected; |
859 | struct ipv6hdr *ip6h = ipv6_hdr(skb); | 860 | const struct ipv6hdr *ip6h = ipv6_hdr(skb); |
860 | struct tcphdr *th = tcp_hdr(skb); | 861 | struct tcphdr *th = tcp_hdr(skb); |
861 | int genhash; | 862 | int genhash; |
862 | u8 newhash[16]; | 863 | u8 newhash[16]; |
@@ -914,7 +915,7 @@ static const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { | |||
914 | #endif | 915 | #endif |
915 | 916 | ||
916 | static void __tcp_v6_send_check(struct sk_buff *skb, | 917 | static void __tcp_v6_send_check(struct sk_buff *skb, |
917 | struct in6_addr *saddr, struct in6_addr *daddr) | 918 | const struct in6_addr *saddr, const struct in6_addr *daddr) |
918 | { | 919 | { |
919 | struct tcphdr *th = tcp_hdr(skb); | 920 | struct tcphdr *th = tcp_hdr(skb); |
920 | 921 | ||
@@ -938,7 +939,7 @@ static void tcp_v6_send_check(struct sock *sk, struct sk_buff *skb) | |||
938 | 939 | ||
939 | static int tcp_v6_gso_send_check(struct sk_buff *skb) | 940 | static int tcp_v6_gso_send_check(struct sk_buff *skb) |
940 | { | 941 | { |
941 | struct ipv6hdr *ipv6h; | 942 | const struct ipv6hdr *ipv6h; |
942 | struct tcphdr *th; | 943 | struct tcphdr *th; |
943 | 944 | ||
944 | if (!pskb_may_pull(skb, sizeof(*th))) | 945 | if (!pskb_may_pull(skb, sizeof(*th))) |
@@ -956,7 +957,7 @@ static int tcp_v6_gso_send_check(struct sk_buff *skb) | |||
956 | static struct sk_buff **tcp6_gro_receive(struct sk_buff **head, | 957 | static struct sk_buff **tcp6_gro_receive(struct sk_buff **head, |
957 | struct sk_buff *skb) | 958 | struct sk_buff *skb) |
958 | { | 959 | { |
959 | struct ipv6hdr *iph = skb_gro_network_header(skb); | 960 | const struct ipv6hdr *iph = skb_gro_network_header(skb); |
960 | 961 | ||
961 | switch (skb->ip_summed) { | 962 | switch (skb->ip_summed) { |
962 | case CHECKSUM_COMPLETE: | 963 | case CHECKSUM_COMPLETE: |
@@ -977,7 +978,7 @@ static struct sk_buff **tcp6_gro_receive(struct sk_buff **head, | |||
977 | 978 | ||
978 | static int tcp6_gro_complete(struct sk_buff *skb) | 979 | static int tcp6_gro_complete(struct sk_buff *skb) |
979 | { | 980 | { |
980 | struct ipv6hdr *iph = ipv6_hdr(skb); | 981 | const struct ipv6hdr *iph = ipv6_hdr(skb); |
981 | struct tcphdr *th = tcp_hdr(skb); | 982 | struct tcphdr *th = tcp_hdr(skb); |
982 | 983 | ||
983 | th->check = ~tcp_v6_check(skb->len - skb_transport_offset(skb), | 984 | th->check = ~tcp_v6_check(skb->len - skb_transport_offset(skb), |
@@ -1468,7 +1469,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1468 | 1469 | ||
1469 | First: no IPv4 options. | 1470 | First: no IPv4 options. |
1470 | */ | 1471 | */ |
1471 | newinet->opt = NULL; | 1472 | newinet->inet_opt = NULL; |
1472 | newnp->ipv6_fl_list = NULL; | 1473 | newnp->ipv6_fl_list = NULL; |
1473 | 1474 | ||
1474 | /* Clone RX bits */ | 1475 | /* Clone RX bits */ |
@@ -1621,6 +1622,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
1621 | opt_skb = skb_clone(skb, GFP_ATOMIC); | 1622 | opt_skb = skb_clone(skb, GFP_ATOMIC); |
1622 | 1623 | ||
1623 | if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ | 1624 | if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ |
1625 | sock_rps_save_rxhash(sk, skb->rxhash); | ||
1624 | if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) | 1626 | if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) |
1625 | goto reset; | 1627 | goto reset; |
1626 | if (opt_skb) | 1628 | if (opt_skb) |
@@ -1648,7 +1650,8 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
1648 | __kfree_skb(opt_skb); | 1650 | __kfree_skb(opt_skb); |
1649 | return 0; | 1651 | return 0; |
1650 | } | 1652 | } |
1651 | } | 1653 | } else |
1654 | sock_rps_save_rxhash(sk, skb->rxhash); | ||
1652 | 1655 | ||
1653 | if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len)) | 1656 | if (tcp_rcv_state_process(sk, skb, tcp_hdr(skb), skb->len)) |
1654 | goto reset; | 1657 | goto reset; |
@@ -1699,7 +1702,7 @@ ipv6_pktoptions: | |||
1699 | static int tcp_v6_rcv(struct sk_buff *skb) | 1702 | static int tcp_v6_rcv(struct sk_buff *skb) |
1700 | { | 1703 | { |
1701 | struct tcphdr *th; | 1704 | struct tcphdr *th; |
1702 | struct ipv6hdr *hdr; | 1705 | const struct ipv6hdr *hdr; |
1703 | struct sock *sk; | 1706 | struct sock *sk; |
1704 | int ret; | 1707 | int ret; |
1705 | struct net *net = dev_net(skb->dev); | 1708 | struct net *net = dev_net(skb->dev); |
@@ -2025,8 +2028,8 @@ static void get_openreq6(struct seq_file *seq, | |||
2025 | struct sock *sk, struct request_sock *req, int i, int uid) | 2028 | struct sock *sk, struct request_sock *req, int i, int uid) |
2026 | { | 2029 | { |
2027 | int ttd = req->expires - jiffies; | 2030 | int ttd = req->expires - jiffies; |
2028 | struct in6_addr *src = &inet6_rsk(req)->loc_addr; | 2031 | const struct in6_addr *src = &inet6_rsk(req)->loc_addr; |
2029 | struct in6_addr *dest = &inet6_rsk(req)->rmt_addr; | 2032 | const struct in6_addr *dest = &inet6_rsk(req)->rmt_addr; |
2030 | 2033 | ||
2031 | if (ttd < 0) | 2034 | if (ttd < 0) |
2032 | ttd = 0; | 2035 | ttd = 0; |
@@ -2054,7 +2057,7 @@ static void get_openreq6(struct seq_file *seq, | |||
2054 | 2057 | ||
2055 | static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) | 2058 | static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) |
2056 | { | 2059 | { |
2057 | struct in6_addr *dest, *src; | 2060 | const struct in6_addr *dest, *src; |
2058 | __u16 destp, srcp; | 2061 | __u16 destp, srcp; |
2059 | int timer_active; | 2062 | int timer_active; |
2060 | unsigned long timer_expires; | 2063 | unsigned long timer_expires; |
@@ -2111,7 +2114,7 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) | |||
2111 | static void get_timewait6_sock(struct seq_file *seq, | 2114 | static void get_timewait6_sock(struct seq_file *seq, |
2112 | struct inet_timewait_sock *tw, int i) | 2115 | struct inet_timewait_sock *tw, int i) |
2113 | { | 2116 | { |
2114 | struct in6_addr *dest, *src; | 2117 | const struct in6_addr *dest, *src; |
2115 | __u16 destp, srcp; | 2118 | __u16 destp, srcp; |
2116 | struct inet6_timewait_sock *tw6 = inet6_twsk((struct sock *)tw); | 2119 | struct inet6_timewait_sock *tw6 = inet6_twsk((struct sock *)tw); |
2117 | int ttd = tw->tw_ttd - jiffies; | 2120 | int ttd = tw->tw_ttd - jiffies; |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index d7037c006e13..fc0c42a88e54 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -311,7 +311,7 @@ static struct sock *__udp6_lib_lookup_skb(struct sk_buff *skb, | |||
311 | struct udp_table *udptable) | 311 | struct udp_table *udptable) |
312 | { | 312 | { |
313 | struct sock *sk; | 313 | struct sock *sk; |
314 | struct ipv6hdr *iph = ipv6_hdr(skb); | 314 | const struct ipv6hdr *iph = ipv6_hdr(skb); |
315 | 315 | ||
316 | if (unlikely(sk = skb_steal_sock(skb))) | 316 | if (unlikely(sk = skb_steal_sock(skb))) |
317 | return sk; | 317 | return sk; |
@@ -463,9 +463,9 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
463 | struct udp_table *udptable) | 463 | struct udp_table *udptable) |
464 | { | 464 | { |
465 | struct ipv6_pinfo *np; | 465 | struct ipv6_pinfo *np; |
466 | struct ipv6hdr *hdr = (struct ipv6hdr*)skb->data; | 466 | const struct ipv6hdr *hdr = (const struct ipv6hdr *)skb->data; |
467 | struct in6_addr *saddr = &hdr->saddr; | 467 | const struct in6_addr *saddr = &hdr->saddr; |
468 | struct in6_addr *daddr = &hdr->daddr; | 468 | const struct in6_addr *daddr = &hdr->daddr; |
469 | struct udphdr *uh = (struct udphdr*)(skb->data+offset); | 469 | struct udphdr *uh = (struct udphdr*)(skb->data+offset); |
470 | struct sock *sk; | 470 | struct sock *sk; |
471 | int err; | 471 | int err; |
@@ -505,6 +505,9 @@ int udpv6_queue_rcv_skb(struct sock * sk, struct sk_buff *skb) | |||
505 | int rc; | 505 | int rc; |
506 | int is_udplite = IS_UDPLITE(sk); | 506 | int is_udplite = IS_UDPLITE(sk); |
507 | 507 | ||
508 | if (!ipv6_addr_any(&inet6_sk(sk)->daddr)) | ||
509 | sock_rps_save_rxhash(sk, skb->rxhash); | ||
510 | |||
508 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) | 511 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) |
509 | goto drop; | 512 | goto drop; |
510 | 513 | ||
@@ -550,8 +553,8 @@ drop_no_sk_drops_inc: | |||
550 | } | 553 | } |
551 | 554 | ||
552 | static struct sock *udp_v6_mcast_next(struct net *net, struct sock *sk, | 555 | static struct sock *udp_v6_mcast_next(struct net *net, struct sock *sk, |
553 | __be16 loc_port, struct in6_addr *loc_addr, | 556 | __be16 loc_port, const struct in6_addr *loc_addr, |
554 | __be16 rmt_port, struct in6_addr *rmt_addr, | 557 | __be16 rmt_port, const struct in6_addr *rmt_addr, |
555 | int dif) | 558 | int dif) |
556 | { | 559 | { |
557 | struct hlist_nulls_node *node; | 560 | struct hlist_nulls_node *node; |
@@ -630,7 +633,7 @@ drop: | |||
630 | * so we don't need to lock the hashes. | 633 | * so we don't need to lock the hashes. |
631 | */ | 634 | */ |
632 | static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb, | 635 | static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb, |
633 | struct in6_addr *saddr, struct in6_addr *daddr, | 636 | const struct in6_addr *saddr, const struct in6_addr *daddr, |
634 | struct udp_table *udptable) | 637 | struct udp_table *udptable) |
635 | { | 638 | { |
636 | struct sock *sk, *stack[256 / sizeof(struct sock *)]; | 639 | struct sock *sk, *stack[256 / sizeof(struct sock *)]; |
@@ -713,7 +716,7 @@ int __udp6_lib_rcv(struct sk_buff *skb, struct udp_table *udptable, | |||
713 | struct net *net = dev_net(skb->dev); | 716 | struct net *net = dev_net(skb->dev); |
714 | struct sock *sk; | 717 | struct sock *sk; |
715 | struct udphdr *uh; | 718 | struct udphdr *uh; |
716 | struct in6_addr *saddr, *daddr; | 719 | const struct in6_addr *saddr, *daddr; |
717 | u32 ulen = 0; | 720 | u32 ulen = 0; |
718 | 721 | ||
719 | if (!pskb_may_pull(skb, sizeof(struct udphdr))) | 722 | if (!pskb_may_pull(skb, sizeof(struct udphdr))) |
@@ -1275,7 +1278,7 @@ int compat_udpv6_getsockopt(struct sock *sk, int level, int optname, | |||
1275 | 1278 | ||
1276 | static int udp6_ufo_send_check(struct sk_buff *skb) | 1279 | static int udp6_ufo_send_check(struct sk_buff *skb) |
1277 | { | 1280 | { |
1278 | struct ipv6hdr *ipv6h; | 1281 | const struct ipv6hdr *ipv6h; |
1279 | struct udphdr *uh; | 1282 | struct udphdr *uh; |
1280 | 1283 | ||
1281 | if (!pskb_may_pull(skb, sizeof(*uh))) | 1284 | if (!pskb_may_pull(skb, sizeof(*uh))) |
@@ -1325,14 +1328,14 @@ static struct sk_buff *udp6_ufo_fragment(struct sk_buff *skb, u32 features) | |||
1325 | /* Do software UFO. Complete and fill in the UDP checksum as HW cannot | 1328 | /* Do software UFO. Complete and fill in the UDP checksum as HW cannot |
1326 | * do checksum of UDP packets sent as multiple IP fragments. | 1329 | * do checksum of UDP packets sent as multiple IP fragments. |
1327 | */ | 1330 | */ |
1328 | offset = skb->csum_start - skb_headroom(skb); | 1331 | offset = skb_checksum_start_offset(skb); |
1329 | csum = skb_checksum(skb, offset, skb->len- offset, 0); | 1332 | csum = skb_checksum(skb, offset, skb->len- offset, 0); |
1330 | offset += skb->csum_offset; | 1333 | offset += skb->csum_offset; |
1331 | *(__sum16 *)(skb->data + offset) = csum_fold(csum); | 1334 | *(__sum16 *)(skb->data + offset) = csum_fold(csum); |
1332 | skb->ip_summed = CHECKSUM_NONE; | 1335 | skb->ip_summed = CHECKSUM_NONE; |
1333 | 1336 | ||
1334 | /* Check if there is enough headroom to insert fragment header. */ | 1337 | /* Check if there is enough headroom to insert fragment header. */ |
1335 | if ((skb_headroom(skb) < frag_hdr_sz) && | 1338 | if ((skb_mac_header(skb) < skb->head + frag_hdr_sz) && |
1336 | pskb_expand_head(skb, frag_hdr_sz, 0, GFP_ATOMIC)) | 1339 | pskb_expand_head(skb, frag_hdr_sz, 0, GFP_ATOMIC)) |
1337 | goto out; | 1340 | goto out; |
1338 | 1341 | ||
@@ -1379,7 +1382,7 @@ static void udp6_sock_seq_show(struct seq_file *seq, struct sock *sp, int bucket | |||
1379 | { | 1382 | { |
1380 | struct inet_sock *inet = inet_sk(sp); | 1383 | struct inet_sock *inet = inet_sk(sp); |
1381 | struct ipv6_pinfo *np = inet6_sk(sp); | 1384 | struct ipv6_pinfo *np = inet6_sk(sp); |
1382 | struct in6_addr *dest, *src; | 1385 | const struct in6_addr *dest, *src; |
1383 | __u16 destp, srcp; | 1386 | __u16 destp, srcp; |
1384 | 1387 | ||
1385 | dest = &np->daddr; | 1388 | dest = &np->daddr; |
diff --git a/net/ipv6/xfrm6_mode_beet.c b/net/ipv6/xfrm6_mode_beet.c index bbd48b101bae..3437d7d4eed6 100644 --- a/net/ipv6/xfrm6_mode_beet.c +++ b/net/ipv6/xfrm6_mode_beet.c | |||
@@ -41,10 +41,8 @@ static int xfrm6_beet_output(struct xfrm_state *x, struct sk_buff *skb) | |||
41 | { | 41 | { |
42 | struct ipv6hdr *top_iph; | 42 | struct ipv6hdr *top_iph; |
43 | struct ip_beet_phdr *ph; | 43 | struct ip_beet_phdr *ph; |
44 | struct iphdr *iphv4; | ||
45 | int optlen, hdr_len; | 44 | int optlen, hdr_len; |
46 | 45 | ||
47 | iphv4 = ip_hdr(skb); | ||
48 | hdr_len = 0; | 46 | hdr_len = 0; |
49 | optlen = XFRM_MODE_SKB_CB(skb)->optlen; | 47 | optlen = XFRM_MODE_SKB_CB(skb)->optlen; |
50 | if (unlikely(optlen)) | 48 | if (unlikely(optlen)) |
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c index 645cb968d450..4d6edff0498f 100644 --- a/net/ipv6/xfrm6_mode_tunnel.c +++ b/net/ipv6/xfrm6_mode_tunnel.c | |||
@@ -20,7 +20,7 @@ | |||
20 | 20 | ||
21 | static inline void ipip6_ecn_decapsulate(struct sk_buff *skb) | 21 | static inline void ipip6_ecn_decapsulate(struct sk_buff *skb) |
22 | { | 22 | { |
23 | struct ipv6hdr *outer_iph = ipv6_hdr(skb); | 23 | const struct ipv6hdr *outer_iph = ipv6_hdr(skb); |
24 | struct ipv6hdr *inner_iph = ipipv6_hdr(skb); | 24 | struct ipv6hdr *inner_iph = ipipv6_hdr(skb); |
25 | 25 | ||
26 | if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph))) | 26 | if (INET_ECN_is_ce(ipv6_get_dsfield(outer_iph))) |
@@ -55,8 +55,8 @@ static int xfrm6_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) | |||
55 | dsfield &= ~INET_ECN_MASK; | 55 | dsfield &= ~INET_ECN_MASK; |
56 | ipv6_change_dsfield(top_iph, 0, dsfield); | 56 | ipv6_change_dsfield(top_iph, 0, dsfield); |
57 | top_iph->hop_limit = ip6_dst_hoplimit(dst->child); | 57 | top_iph->hop_limit = ip6_dst_hoplimit(dst->child); |
58 | ipv6_addr_copy(&top_iph->saddr, (struct in6_addr *)&x->props.saddr); | 58 | ipv6_addr_copy(&top_iph->saddr, (const struct in6_addr *)&x->props.saddr); |
59 | ipv6_addr_copy(&top_iph->daddr, (struct in6_addr *)&x->id.daddr); | 59 | ipv6_addr_copy(&top_iph->daddr, (const struct in6_addr *)&x->id.daddr); |
60 | return 0; | 60 | return 0; |
61 | } | 61 | } |
62 | 62 | ||
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index 8e688b3de9ab..49a91c5f5623 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c | |||
@@ -79,7 +79,7 @@ int xfrm6_prepare_output(struct xfrm_state *x, struct sk_buff *skb) | |||
79 | } | 79 | } |
80 | EXPORT_SYMBOL(xfrm6_prepare_output); | 80 | EXPORT_SYMBOL(xfrm6_prepare_output); |
81 | 81 | ||
82 | static int xfrm6_output_finish(struct sk_buff *skb) | 82 | int xfrm6_output_finish(struct sk_buff *skb) |
83 | { | 83 | { |
84 | #ifdef CONFIG_NETFILTER | 84 | #ifdef CONFIG_NETFILTER |
85 | IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED; | 85 | IP6CB(skb)->flags |= IP6SKB_XFRM_TRANSFORMED; |
@@ -97,9 +97,9 @@ static int __xfrm6_output(struct sk_buff *skb) | |||
97 | if ((x && x->props.mode == XFRM_MODE_TUNNEL) && | 97 | if ((x && x->props.mode == XFRM_MODE_TUNNEL) && |
98 | ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || | 98 | ((skb->len > ip6_skb_dst_mtu(skb) && !skb_is_gso(skb)) || |
99 | dst_allfrag(skb_dst(skb)))) { | 99 | dst_allfrag(skb_dst(skb)))) { |
100 | return ip6_fragment(skb, xfrm6_output_finish); | 100 | return ip6_fragment(skb, x->outer_mode->afinfo->output_finish); |
101 | } | 101 | } |
102 | return xfrm6_output_finish(skb); | 102 | return x->outer_mode->afinfo->output_finish(skb); |
103 | } | 103 | } |
104 | 104 | ||
105 | int xfrm6_output(struct sk_buff *skb) | 105 | int xfrm6_output(struct sk_buff *skb) |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 05e34c8ec913..d879f7efbd10 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -124,7 +124,7 @@ _decode_session6(struct sk_buff *skb, struct flowi *fl, int reverse) | |||
124 | struct flowi6 *fl6 = &fl->u.ip6; | 124 | struct flowi6 *fl6 = &fl->u.ip6; |
125 | int onlyproto = 0; | 125 | int onlyproto = 0; |
126 | u16 offset = skb_network_header_len(skb); | 126 | u16 offset = skb_network_header_len(skb); |
127 | struct ipv6hdr *hdr = ipv6_hdr(skb); | 127 | const struct ipv6hdr *hdr = ipv6_hdr(skb); |
128 | struct ipv6_opt_hdr *exthdr; | 128 | struct ipv6_opt_hdr *exthdr; |
129 | const unsigned char *nh = skb_network_header(skb); | 129 | const unsigned char *nh = skb_network_header(skb); |
130 | u8 nexthdr = nh[IP6CB(skb)->nhoff]; | 130 | u8 nexthdr = nh[IP6CB(skb)->nhoff]; |
diff --git a/net/ipv6/xfrm6_state.c b/net/ipv6/xfrm6_state.c index afe941e9415c..248f0b2a7ee9 100644 --- a/net/ipv6/xfrm6_state.c +++ b/net/ipv6/xfrm6_state.c | |||
@@ -178,6 +178,7 @@ static struct xfrm_state_afinfo xfrm6_state_afinfo = { | |||
178 | .tmpl_sort = __xfrm6_tmpl_sort, | 178 | .tmpl_sort = __xfrm6_tmpl_sort, |
179 | .state_sort = __xfrm6_state_sort, | 179 | .state_sort = __xfrm6_state_sort, |
180 | .output = xfrm6_output, | 180 | .output = xfrm6_output, |
181 | .output_finish = xfrm6_output_finish, | ||
181 | .extract_input = xfrm6_extract_input, | 182 | .extract_input = xfrm6_extract_input, |
182 | .extract_output = xfrm6_extract_output, | 183 | .extract_output = xfrm6_extract_output, |
183 | .transport_finish = xfrm6_transport_finish, | 184 | .transport_finish = xfrm6_transport_finish, |
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c index 2969cad408de..a6770a04e3bd 100644 --- a/net/ipv6/xfrm6_tunnel.c +++ b/net/ipv6/xfrm6_tunnel.c | |||
@@ -68,7 +68,7 @@ static DEFINE_SPINLOCK(xfrm6_tunnel_spi_lock); | |||
68 | 68 | ||
69 | static struct kmem_cache *xfrm6_tunnel_spi_kmem __read_mostly; | 69 | static struct kmem_cache *xfrm6_tunnel_spi_kmem __read_mostly; |
70 | 70 | ||
71 | static inline unsigned xfrm6_tunnel_spi_hash_byaddr(xfrm_address_t *addr) | 71 | static inline unsigned xfrm6_tunnel_spi_hash_byaddr(const xfrm_address_t *addr) |
72 | { | 72 | { |
73 | unsigned h; | 73 | unsigned h; |
74 | 74 | ||
@@ -85,7 +85,7 @@ static inline unsigned xfrm6_tunnel_spi_hash_byspi(u32 spi) | |||
85 | return spi % XFRM6_TUNNEL_SPI_BYSPI_HSIZE; | 85 | return spi % XFRM6_TUNNEL_SPI_BYSPI_HSIZE; |
86 | } | 86 | } |
87 | 87 | ||
88 | static struct xfrm6_tunnel_spi *__xfrm6_tunnel_spi_lookup(struct net *net, xfrm_address_t *saddr) | 88 | static struct xfrm6_tunnel_spi *__xfrm6_tunnel_spi_lookup(struct net *net, const xfrm_address_t *saddr) |
89 | { | 89 | { |
90 | struct xfrm6_tunnel_net *xfrm6_tn = xfrm6_tunnel_pernet(net); | 90 | struct xfrm6_tunnel_net *xfrm6_tn = xfrm6_tunnel_pernet(net); |
91 | struct xfrm6_tunnel_spi *x6spi; | 91 | struct xfrm6_tunnel_spi *x6spi; |
@@ -101,7 +101,7 @@ static struct xfrm6_tunnel_spi *__xfrm6_tunnel_spi_lookup(struct net *net, xfrm_ | |||
101 | return NULL; | 101 | return NULL; |
102 | } | 102 | } |
103 | 103 | ||
104 | __be32 xfrm6_tunnel_spi_lookup(struct net *net, xfrm_address_t *saddr) | 104 | __be32 xfrm6_tunnel_spi_lookup(struct net *net, const xfrm_address_t *saddr) |
105 | { | 105 | { |
106 | struct xfrm6_tunnel_spi *x6spi; | 106 | struct xfrm6_tunnel_spi *x6spi; |
107 | u32 spi; | 107 | u32 spi; |
@@ -237,10 +237,10 @@ static int xfrm6_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) | |||
237 | static int xfrm6_tunnel_rcv(struct sk_buff *skb) | 237 | static int xfrm6_tunnel_rcv(struct sk_buff *skb) |
238 | { | 238 | { |
239 | struct net *net = dev_net(skb->dev); | 239 | struct net *net = dev_net(skb->dev); |
240 | struct ipv6hdr *iph = ipv6_hdr(skb); | 240 | const struct ipv6hdr *iph = ipv6_hdr(skb); |
241 | __be32 spi; | 241 | __be32 spi; |
242 | 242 | ||
243 | spi = xfrm6_tunnel_spi_lookup(net, (xfrm_address_t *)&iph->saddr); | 243 | spi = xfrm6_tunnel_spi_lookup(net, (const xfrm_address_t *)&iph->saddr); |
244 | return xfrm6_rcv_spi(skb, IPPROTO_IPV6, spi) > 0 ? : 0; | 244 | return xfrm6_rcv_spi(skb, IPPROTO_IPV6, spi) > 0 ? : 0; |
245 | } | 245 | } |
246 | 246 | ||
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index c9890e25cd4c..cc616974a447 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c | |||
@@ -1297,8 +1297,7 @@ static int irda_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1297 | /* Note : socket.c set MSG_EOR on SEQPACKET sockets */ | 1297 | /* Note : socket.c set MSG_EOR on SEQPACKET sockets */ |
1298 | if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_EOR | MSG_CMSG_COMPAT | | 1298 | if (msg->msg_flags & ~(MSG_DONTWAIT | MSG_EOR | MSG_CMSG_COMPAT | |
1299 | MSG_NOSIGNAL)) { | 1299 | MSG_NOSIGNAL)) { |
1300 | err = -EINVAL; | 1300 | return -EINVAL; |
1301 | goto out; | ||
1302 | } | 1301 | } |
1303 | 1302 | ||
1304 | lock_sock(sk); | 1303 | lock_sock(sk); |
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/irda/irlap.c b/net/irda/irlap.c index 783c5f367d29..005b424494a0 100644 --- a/net/irda/irlap.c +++ b/net/irda/irlap.c | |||
@@ -165,7 +165,7 @@ struct irlap_cb *irlap_open(struct net_device *dev, struct qos_info *qos, | |||
165 | 165 | ||
166 | irlap_apply_default_connection_parameters(self); | 166 | irlap_apply_default_connection_parameters(self); |
167 | 167 | ||
168 | self->N3 = 3; /* # connections attemts to try before giving up */ | 168 | self->N3 = 3; /* # connections attempts to try before giving up */ |
169 | 169 | ||
170 | self->state = LAP_NDM; | 170 | self->state = LAP_NDM; |
171 | 171 | ||
diff --git a/net/irda/irlap_event.c b/net/irda/irlap_event.c index d434c8880745..ccd214f9d196 100644 --- a/net/irda/irlap_event.c +++ b/net/irda/irlap_event.c | |||
@@ -708,7 +708,7 @@ static int irlap_state_reply(struct irlap_cb *self, IRLAP_EVENT event, | |||
708 | 708 | ||
709 | self->frame_sent = TRUE; | 709 | self->frame_sent = TRUE; |
710 | } | 710 | } |
711 | /* Readjust our timer to accomodate devices | 711 | /* Readjust our timer to accommodate devices |
712 | * doing faster or slower discovery than us... | 712 | * doing faster or slower discovery than us... |
713 | * Jean II */ | 713 | * Jean II */ |
714 | irlap_start_query_timer(self, info->S, info->s); | 714 | irlap_start_query_timer(self, info->S, info->s); |
@@ -931,7 +931,7 @@ static int irlap_state_setup(struct irlap_cb *self, IRLAP_EVENT event, | |||
931 | irlap_send_rr_frame(self, CMD_FRAME); | 931 | irlap_send_rr_frame(self, CMD_FRAME); |
932 | 932 | ||
933 | /* The timer is set to half the normal timer to quickly | 933 | /* The timer is set to half the normal timer to quickly |
934 | * detect a failure to negociate the new connection | 934 | * detect a failure to negotiate the new connection |
935 | * parameters. IrLAP 6.11.3.2, note 3. | 935 | * parameters. IrLAP 6.11.3.2, note 3. |
936 | * Note that currently we don't process this failure | 936 | * Note that currently we don't process this failure |
937 | * properly, as we should do a quick disconnect. | 937 | * properly, as we should do a quick disconnect. |
@@ -1052,7 +1052,7 @@ static int irlap_state_xmit_p(struct irlap_cb *self, IRLAP_EVENT event, | |||
1052 | return -EPROTO; | 1052 | return -EPROTO; |
1053 | } | 1053 | } |
1054 | 1054 | ||
1055 | /* Substract space used by this skb */ | 1055 | /* Subtract space used by this skb */ |
1056 | self->bytes_left -= skb->len; | 1056 | self->bytes_left -= skb->len; |
1057 | #else /* CONFIG_IRDA_DYNAMIC_WINDOW */ | 1057 | #else /* CONFIG_IRDA_DYNAMIC_WINDOW */ |
1058 | /* Window has been adjusted for the max packet | 1058 | /* Window has been adjusted for the max packet |
@@ -1808,7 +1808,7 @@ static int irlap_state_xmit_s(struct irlap_cb *self, IRLAP_EVENT event, | |||
1808 | 1808 | ||
1809 | return -EPROTO; /* Try again later */ | 1809 | return -EPROTO; /* Try again later */ |
1810 | } | 1810 | } |
1811 | /* Substract space used by this skb */ | 1811 | /* Subtract space used by this skb */ |
1812 | self->bytes_left -= skb->len; | 1812 | self->bytes_left -= skb->len; |
1813 | #else /* CONFIG_IRDA_DYNAMIC_WINDOW */ | 1813 | #else /* CONFIG_IRDA_DYNAMIC_WINDOW */ |
1814 | /* Window has been adjusted for the max packet | 1814 | /* Window has been adjusted for the max packet |
@@ -2227,8 +2227,6 @@ static int irlap_state_nrm_s(struct irlap_cb *self, IRLAP_EVENT event, | |||
2227 | static int irlap_state_sclose(struct irlap_cb *self, IRLAP_EVENT event, | 2227 | static int irlap_state_sclose(struct irlap_cb *self, IRLAP_EVENT event, |
2228 | struct sk_buff *skb, struct irlap_info *info) | 2228 | struct sk_buff *skb, struct irlap_info *info) |
2229 | { | 2229 | { |
2230 | int ret = 0; | ||
2231 | |||
2232 | IRDA_DEBUG(1, "%s()\n", __func__); | 2230 | IRDA_DEBUG(1, "%s()\n", __func__); |
2233 | 2231 | ||
2234 | IRDA_ASSERT(self != NULL, return -ENODEV;); | 2232 | IRDA_ASSERT(self != NULL, return -ENODEV;); |
@@ -2289,7 +2287,6 @@ static int irlap_state_sclose(struct irlap_cb *self, IRLAP_EVENT event, | |||
2289 | IRDA_DEBUG(1, "%s(), Unknown event %d, (%s)\n", __func__, | 2287 | IRDA_DEBUG(1, "%s(), Unknown event %d, (%s)\n", __func__, |
2290 | event, irlap_event[event]); | 2288 | event, irlap_event[event]); |
2291 | 2289 | ||
2292 | ret = -EINVAL; | ||
2293 | break; | 2290 | break; |
2294 | } | 2291 | } |
2295 | 2292 | ||
diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c index 688222cbf55b..8c004161a843 100644 --- a/net/irda/irlap_frame.c +++ b/net/irda/irlap_frame.c | |||
@@ -848,7 +848,7 @@ void irlap_send_data_primary_poll(struct irlap_cb *self, struct sk_buff *skb) | |||
848 | * though IrLAP is currently sending the *last* frame of the | 848 | * though IrLAP is currently sending the *last* frame of the |
849 | * tx-window, the driver most likely has only just started | 849 | * tx-window, the driver most likely has only just started |
850 | * sending the *first* frame of the same tx-window. | 850 | * sending the *first* frame of the same tx-window. |
851 | * I.e. we are always at the very begining of or Tx window. | 851 | * I.e. we are always at the very beginning of or Tx window. |
852 | * Now, we are supposed to set the final timer from the end | 852 | * Now, we are supposed to set the final timer from the end |
853 | * of our tx-window to let the other peer reply. So, we need | 853 | * of our tx-window to let the other peer reply. So, we need |
854 | * to add extra time to compensate for the fact that we | 854 | * to add extra time to compensate for the fact that we |
diff --git a/net/irda/irlmp_event.c b/net/irda/irlmp_event.c index c1fb5db81042..9505a7d06f1a 100644 --- a/net/irda/irlmp_event.c +++ b/net/irda/irlmp_event.c | |||
@@ -498,7 +498,7 @@ static int irlmp_state_disconnected(struct lsap_cb *self, IRLMP_EVENT event, | |||
498 | switch (event) { | 498 | switch (event) { |
499 | #ifdef CONFIG_IRDA_ULTRA | 499 | #ifdef CONFIG_IRDA_ULTRA |
500 | case LM_UDATA_INDICATION: | 500 | case LM_UDATA_INDICATION: |
501 | /* This is most bizzare. Those packets are aka unreliable | 501 | /* This is most bizarre. Those packets are aka unreliable |
502 | * connected, aka IrLPT or SOCK_DGRAM/IRDAPROTO_UNITDATA. | 502 | * connected, aka IrLPT or SOCK_DGRAM/IRDAPROTO_UNITDATA. |
503 | * Why do we pass them as Ultra ??? Jean II */ | 503 | * Why do we pass them as Ultra ??? Jean II */ |
504 | irlmp_connless_data_indication(self, skb); | 504 | irlmp_connless_data_indication(self, skb); |
diff --git a/net/irda/irnet/irnet.h b/net/irda/irnet/irnet.h index 0d82ff5aeff1..979ecb2435a7 100644 --- a/net/irda/irnet/irnet.h +++ b/net/irda/irnet/irnet.h | |||
@@ -73,7 +73,7 @@ | |||
73 | * Infinite thanks to those brave souls for providing the infrastructure | 73 | * Infinite thanks to those brave souls for providing the infrastructure |
74 | * upon which IrNET is built. | 74 | * upon which IrNET is built. |
75 | * | 75 | * |
76 | * Thanks to all my collegues in HP for helping me. In particular, | 76 | * Thanks to all my colleagues in HP for helping me. In particular, |
77 | * thanks to Salil Pradhan and Bill Serra for W2k testing... | 77 | * thanks to Salil Pradhan and Bill Serra for W2k testing... |
78 | * Thanks to Luiz Magalhaes for irnetd and much testing... | 78 | * Thanks to Luiz Magalhaes for irnetd and much testing... |
79 | * | 79 | * |
diff --git a/net/irda/irproc.c b/net/irda/irproc.c index 318766e5dbdf..b9ac598e2116 100644 --- a/net/irda/irproc.c +++ b/net/irda/irproc.c | |||
@@ -65,15 +65,14 @@ static const struct irda_entry irda_dirs[] = { | |||
65 | void __init irda_proc_register(void) | 65 | void __init irda_proc_register(void) |
66 | { | 66 | { |
67 | int i; | 67 | int i; |
68 | struct proc_dir_entry *d; | ||
69 | 68 | ||
70 | proc_irda = proc_mkdir("irda", init_net.proc_net); | 69 | proc_irda = proc_mkdir("irda", init_net.proc_net); |
71 | if (proc_irda == NULL) | 70 | if (proc_irda == NULL) |
72 | return; | 71 | return; |
73 | 72 | ||
74 | for (i = 0; i < ARRAY_SIZE(irda_dirs); i++) | 73 | for (i = 0; i < ARRAY_SIZE(irda_dirs); i++) |
75 | d = proc_create(irda_dirs[i].name, 0, proc_irda, | 74 | (void) proc_create(irda_dirs[i].name, 0, proc_irda, |
76 | irda_dirs[i].fops); | 75 | irda_dirs[i].fops); |
77 | } | 76 | } |
78 | 77 | ||
79 | /* | 78 | /* |
diff --git a/net/irda/irqueue.c b/net/irda/irqueue.c index 849aaf0dabb5..9715e6e5900b 100644 --- a/net/irda/irqueue.c +++ b/net/irda/irqueue.c | |||
@@ -40,7 +40,7 @@ | |||
40 | * o the hash function for ints is pathetic (but could be changed) | 40 | * o the hash function for ints is pathetic (but could be changed) |
41 | * o locking is sometime suspicious (especially during enumeration) | 41 | * o locking is sometime suspicious (especially during enumeration) |
42 | * o most users have only a few elements (== overhead) | 42 | * o most users have only a few elements (== overhead) |
43 | * o most users never use seach, so don't benefit from hashing | 43 | * o most users never use search, so don't benefit from hashing |
44 | * Problem already fixed : | 44 | * Problem already fixed : |
45 | * o not 64 bit compliant (most users do hashv = (int) self) | 45 | * o not 64 bit compliant (most users do hashv = (int) self) |
46 | * o hashbin_remove() is broken => use hashbin_remove_this() | 46 | * o hashbin_remove() is broken => use hashbin_remove_this() |
diff --git a/net/irda/irttp.c b/net/irda/irttp.c index f6054f9ccbe3..9d9af4606970 100644 --- a/net/irda/irttp.c +++ b/net/irda/irttp.c | |||
@@ -1193,7 +1193,7 @@ EXPORT_SYMBOL(irttp_connect_request); | |||
1193 | /* | 1193 | /* |
1194 | * Function irttp_connect_confirm (handle, qos, skb) | 1194 | * Function irttp_connect_confirm (handle, qos, skb) |
1195 | * | 1195 | * |
1196 | * Sevice user confirms TSAP connection with peer. | 1196 | * Service user confirms TSAP connection with peer. |
1197 | * | 1197 | * |
1198 | */ | 1198 | */ |
1199 | static void irttp_connect_confirm(void *instance, void *sap, | 1199 | static void irttp_connect_confirm(void *instance, void *sap, |
diff --git a/net/irda/qos.c b/net/irda/qos.c index 2b00974e5bae..1b51bcf42394 100644 --- a/net/irda/qos.c +++ b/net/irda/qos.c | |||
@@ -39,16 +39,16 @@ | |||
39 | #include <net/irda/irlap_frame.h> | 39 | #include <net/irda/irlap_frame.h> |
40 | 40 | ||
41 | /* | 41 | /* |
42 | * Maximum values of the baud rate we negociate with the other end. | 42 | * Maximum values of the baud rate we negotiate with the other end. |
43 | * Most often, you don't have to change that, because Linux-IrDA will | 43 | * Most often, you don't have to change that, because Linux-IrDA will |
44 | * use the maximum offered by the link layer, which usually works fine. | 44 | * use the maximum offered by the link layer, which usually works fine. |
45 | * In some very rare cases, you may want to limit it to lower speeds... | 45 | * In some very rare cases, you may want to limit it to lower speeds... |
46 | */ | 46 | */ |
47 | int sysctl_max_baud_rate = 16000000; | 47 | int sysctl_max_baud_rate = 16000000; |
48 | /* | 48 | /* |
49 | * Maximum value of the lap disconnect timer we negociate with the other end. | 49 | * Maximum value of the lap disconnect timer we negotiate with the other end. |
50 | * Most often, the value below represent the best compromise, but some user | 50 | * Most often, the value below represent the best compromise, but some user |
51 | * may want to keep the LAP alive longuer or shorter in case of link failure. | 51 | * may want to keep the LAP alive longer or shorter in case of link failure. |
52 | * Remember that the threshold time (early warning) is fixed to 3s... | 52 | * Remember that the threshold time (early warning) is fixed to 3s... |
53 | */ | 53 | */ |
54 | int sysctl_max_noreply_time = 12; | 54 | int sysctl_max_noreply_time = 12; |
@@ -411,7 +411,7 @@ static void irlap_adjust_qos_settings(struct qos_info *qos) | |||
411 | * Fix tx data size according to user limits - Jean II | 411 | * Fix tx data size according to user limits - Jean II |
412 | */ | 412 | */ |
413 | if (qos->data_size.value > sysctl_max_tx_data_size) | 413 | if (qos->data_size.value > sysctl_max_tx_data_size) |
414 | /* Allow non discrete adjustement to avoid loosing capacity */ | 414 | /* Allow non discrete adjustement to avoid losing capacity */ |
415 | qos->data_size.value = sysctl_max_tx_data_size; | 415 | qos->data_size.value = sysctl_max_tx_data_size; |
416 | /* | 416 | /* |
417 | * Override Tx window if user request it. - Jean II | 417 | * Override Tx window if user request it. - Jean II |
diff --git a/net/irda/timer.c b/net/irda/timer.c index 0335ba0cc593..f418cb2ad49c 100644 --- a/net/irda/timer.c +++ b/net/irda/timer.c | |||
@@ -59,7 +59,7 @@ void irlap_start_query_timer(struct irlap_cb *self, int S, int s) | |||
59 | * slot time, plus add some extra time to properly receive the last | 59 | * slot time, plus add some extra time to properly receive the last |
60 | * discovery packet (which is longer due to extra discovery info), | 60 | * discovery packet (which is longer due to extra discovery info), |
61 | * to avoid messing with for incomming connections requests and | 61 | * to avoid messing with for incomming connections requests and |
62 | * to accomodate devices that perform discovery slower than us. | 62 | * to accommodate devices that perform discovery slower than us. |
63 | * Jean II */ | 63 | * Jean II */ |
64 | timeout = ((sysctl_slot_timeout * HZ / 1000) * (S - s) | 64 | timeout = ((sysctl_slot_timeout * HZ / 1000) * (S - s) |
65 | + XIDEXTRA_TIMEOUT + SMALLBUSY_TIMEOUT); | 65 | + XIDEXTRA_TIMEOUT + SMALLBUSY_TIMEOUT); |
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 9637e45744fa..e2013e434d03 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c | |||
@@ -190,7 +190,6 @@ static int afiucv_pm_freeze(struct device *dev) | |||
190 | */ | 190 | */ |
191 | static int afiucv_pm_restore_thaw(struct device *dev) | 191 | static int afiucv_pm_restore_thaw(struct device *dev) |
192 | { | 192 | { |
193 | struct iucv_sock *iucv; | ||
194 | struct sock *sk; | 193 | struct sock *sk; |
195 | struct hlist_node *node; | 194 | struct hlist_node *node; |
196 | 195 | ||
@@ -199,7 +198,6 @@ static int afiucv_pm_restore_thaw(struct device *dev) | |||
199 | #endif | 198 | #endif |
200 | read_lock(&iucv_sk_list.lock); | 199 | read_lock(&iucv_sk_list.lock); |
201 | sk_for_each(sk, node, &iucv_sk_list.head) { | 200 | sk_for_each(sk, node, &iucv_sk_list.head) { |
202 | iucv = iucv_sk(sk); | ||
203 | switch (sk->sk_state) { | 201 | switch (sk->sk_state) { |
204 | case IUCV_CONNECTED: | 202 | case IUCV_CONNECTED: |
205 | sk->sk_err = EPIPE; | 203 | sk->sk_err = EPIPE; |
@@ -250,7 +248,7 @@ static struct device *af_iucv_dev; | |||
250 | * PRMDATA[0..6] socket data (max 7 bytes); | 248 | * PRMDATA[0..6] socket data (max 7 bytes); |
251 | * PRMDATA[7] socket data length value (len is 0xff - PRMDATA[7]) | 249 | * PRMDATA[7] socket data length value (len is 0xff - PRMDATA[7]) |
252 | * | 250 | * |
253 | * The socket data length is computed by substracting the socket data length | 251 | * The socket data length is computed by subtracting the socket data length |
254 | * value from 0xFF. | 252 | * value from 0xFF. |
255 | * If the socket data len is greater 7, then PRMDATA can be used for special | 253 | * If the socket data len is greater 7, then PRMDATA can be used for special |
256 | * notifications (see iucv_sock_shutdown); and further, | 254 | * notifications (see iucv_sock_shutdown); and further, |
@@ -381,7 +379,6 @@ static void iucv_sock_close(struct sock *sk) | |||
381 | { | 379 | { |
382 | unsigned char user_data[16]; | 380 | unsigned char user_data[16]; |
383 | struct iucv_sock *iucv = iucv_sk(sk); | 381 | struct iucv_sock *iucv = iucv_sk(sk); |
384 | int err; | ||
385 | unsigned long timeo; | 382 | unsigned long timeo; |
386 | 383 | ||
387 | iucv_sock_clear_timer(sk); | 384 | iucv_sock_clear_timer(sk); |
@@ -394,8 +391,6 @@ static void iucv_sock_close(struct sock *sk) | |||
394 | 391 | ||
395 | case IUCV_CONNECTED: | 392 | case IUCV_CONNECTED: |
396 | case IUCV_DISCONN: | 393 | case IUCV_DISCONN: |
397 | err = 0; | ||
398 | |||
399 | sk->sk_state = IUCV_CLOSING; | 394 | sk->sk_state = IUCV_CLOSING; |
400 | sk->sk_state_change(sk); | 395 | sk->sk_state_change(sk); |
401 | 396 | ||
@@ -404,7 +399,7 @@ static void iucv_sock_close(struct sock *sk) | |||
404 | timeo = sk->sk_lingertime; | 399 | timeo = sk->sk_lingertime; |
405 | else | 400 | else |
406 | timeo = IUCV_DISCONN_TIMEOUT; | 401 | timeo = IUCV_DISCONN_TIMEOUT; |
407 | err = iucv_sock_wait(sk, | 402 | iucv_sock_wait(sk, |
408 | iucv_sock_in_state(sk, IUCV_CLOSED, 0), | 403 | iucv_sock_in_state(sk, IUCV_CLOSED, 0), |
409 | timeo); | 404 | timeo); |
410 | } | 405 | } |
@@ -417,7 +412,7 @@ static void iucv_sock_close(struct sock *sk) | |||
417 | low_nmcpy(user_data, iucv->src_name); | 412 | low_nmcpy(user_data, iucv->src_name); |
418 | high_nmcpy(user_data, iucv->dst_name); | 413 | high_nmcpy(user_data, iucv->dst_name); |
419 | ASCEBC(user_data, sizeof(user_data)); | 414 | ASCEBC(user_data, sizeof(user_data)); |
420 | err = iucv_path_sever(iucv->path, user_data); | 415 | iucv_path_sever(iucv->path, user_data); |
421 | iucv_path_free(iucv->path); | 416 | iucv_path_free(iucv->path); |
422 | iucv->path = NULL; | 417 | iucv->path = NULL; |
423 | } | 418 | } |
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index 1ee5dab3cfae..a15c01524959 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c | |||
@@ -128,8 +128,8 @@ struct iucv_irq_list { | |||
128 | }; | 128 | }; |
129 | 129 | ||
130 | static struct iucv_irq_data *iucv_irq_data[NR_CPUS]; | 130 | static struct iucv_irq_data *iucv_irq_data[NR_CPUS]; |
131 | static cpumask_t iucv_buffer_cpumask = CPU_MASK_NONE; | 131 | static cpumask_t iucv_buffer_cpumask = { CPU_BITS_NONE }; |
132 | static cpumask_t iucv_irq_cpumask = CPU_MASK_NONE; | 132 | static cpumask_t iucv_irq_cpumask = { CPU_BITS_NONE }; |
133 | 133 | ||
134 | /* | 134 | /* |
135 | * Queue of interrupt buffers lock for delivery via the tasklet | 135 | * Queue of interrupt buffers lock for delivery via the tasklet |
@@ -406,7 +406,7 @@ static void iucv_allow_cpu(void *data) | |||
406 | parm->set_mask.ipmask = 0xf8; | 406 | parm->set_mask.ipmask = 0xf8; |
407 | iucv_call_b2f0(IUCV_SETCONTROLMASK, parm); | 407 | iucv_call_b2f0(IUCV_SETCONTROLMASK, parm); |
408 | /* Set indication that iucv interrupts are allowed for this cpu. */ | 408 | /* Set indication that iucv interrupts are allowed for this cpu. */ |
409 | cpu_set(cpu, iucv_irq_cpumask); | 409 | cpumask_set_cpu(cpu, &iucv_irq_cpumask); |
410 | } | 410 | } |
411 | 411 | ||
412 | /** | 412 | /** |
@@ -426,7 +426,7 @@ static void iucv_block_cpu(void *data) | |||
426 | iucv_call_b2f0(IUCV_SETMASK, parm); | 426 | iucv_call_b2f0(IUCV_SETMASK, parm); |
427 | 427 | ||
428 | /* Clear indication that iucv interrupts are allowed for this cpu. */ | 428 | /* Clear indication that iucv interrupts are allowed for this cpu. */ |
429 | cpu_clear(cpu, iucv_irq_cpumask); | 429 | cpumask_clear_cpu(cpu, &iucv_irq_cpumask); |
430 | } | 430 | } |
431 | 431 | ||
432 | /** | 432 | /** |
@@ -451,7 +451,7 @@ static void iucv_block_cpu_almost(void *data) | |||
451 | iucv_call_b2f0(IUCV_SETCONTROLMASK, parm); | 451 | iucv_call_b2f0(IUCV_SETCONTROLMASK, parm); |
452 | 452 | ||
453 | /* Clear indication that iucv interrupts are allowed for this cpu. */ | 453 | /* Clear indication that iucv interrupts are allowed for this cpu. */ |
454 | cpu_clear(cpu, iucv_irq_cpumask); | 454 | cpumask_clear_cpu(cpu, &iucv_irq_cpumask); |
455 | } | 455 | } |
456 | 456 | ||
457 | /** | 457 | /** |
@@ -466,7 +466,7 @@ static void iucv_declare_cpu(void *data) | |||
466 | union iucv_param *parm; | 466 | union iucv_param *parm; |
467 | int rc; | 467 | int rc; |
468 | 468 | ||
469 | if (cpu_isset(cpu, iucv_buffer_cpumask)) | 469 | if (cpumask_test_cpu(cpu, &iucv_buffer_cpumask)) |
470 | return; | 470 | return; |
471 | 471 | ||
472 | /* Declare interrupt buffer. */ | 472 | /* Declare interrupt buffer. */ |
@@ -499,9 +499,9 @@ static void iucv_declare_cpu(void *data) | |||
499 | } | 499 | } |
500 | 500 | ||
501 | /* Set indication that an iucv buffer exists for this cpu. */ | 501 | /* Set indication that an iucv buffer exists for this cpu. */ |
502 | cpu_set(cpu, iucv_buffer_cpumask); | 502 | cpumask_set_cpu(cpu, &iucv_buffer_cpumask); |
503 | 503 | ||
504 | if (iucv_nonsmp_handler == 0 || cpus_empty(iucv_irq_cpumask)) | 504 | if (iucv_nonsmp_handler == 0 || cpumask_empty(&iucv_irq_cpumask)) |
505 | /* Enable iucv interrupts on this cpu. */ | 505 | /* Enable iucv interrupts on this cpu. */ |
506 | iucv_allow_cpu(NULL); | 506 | iucv_allow_cpu(NULL); |
507 | else | 507 | else |
@@ -520,7 +520,7 @@ static void iucv_retrieve_cpu(void *data) | |||
520 | int cpu = smp_processor_id(); | 520 | int cpu = smp_processor_id(); |
521 | union iucv_param *parm; | 521 | union iucv_param *parm; |
522 | 522 | ||
523 | if (!cpu_isset(cpu, iucv_buffer_cpumask)) | 523 | if (!cpumask_test_cpu(cpu, &iucv_buffer_cpumask)) |
524 | return; | 524 | return; |
525 | 525 | ||
526 | /* Block iucv interrupts. */ | 526 | /* Block iucv interrupts. */ |
@@ -531,7 +531,7 @@ static void iucv_retrieve_cpu(void *data) | |||
531 | iucv_call_b2f0(IUCV_RETRIEVE_BUFFER, parm); | 531 | iucv_call_b2f0(IUCV_RETRIEVE_BUFFER, parm); |
532 | 532 | ||
533 | /* Clear indication that an iucv buffer exists for this cpu. */ | 533 | /* Clear indication that an iucv buffer exists for this cpu. */ |
534 | cpu_clear(cpu, iucv_buffer_cpumask); | 534 | cpumask_clear_cpu(cpu, &iucv_buffer_cpumask); |
535 | } | 535 | } |
536 | 536 | ||
537 | /** | 537 | /** |
@@ -546,8 +546,8 @@ static void iucv_setmask_mp(void) | |||
546 | get_online_cpus(); | 546 | get_online_cpus(); |
547 | for_each_online_cpu(cpu) | 547 | for_each_online_cpu(cpu) |
548 | /* Enable all cpus with a declared buffer. */ | 548 | /* Enable all cpus with a declared buffer. */ |
549 | if (cpu_isset(cpu, iucv_buffer_cpumask) && | 549 | if (cpumask_test_cpu(cpu, &iucv_buffer_cpumask) && |
550 | !cpu_isset(cpu, iucv_irq_cpumask)) | 550 | !cpumask_test_cpu(cpu, &iucv_irq_cpumask)) |
551 | smp_call_function_single(cpu, iucv_allow_cpu, | 551 | smp_call_function_single(cpu, iucv_allow_cpu, |
552 | NULL, 1); | 552 | NULL, 1); |
553 | put_online_cpus(); | 553 | put_online_cpus(); |
@@ -564,9 +564,9 @@ static void iucv_setmask_up(void) | |||
564 | int cpu; | 564 | int cpu; |
565 | 565 | ||
566 | /* Disable all cpu but the first in cpu_irq_cpumask. */ | 566 | /* Disable all cpu but the first in cpu_irq_cpumask. */ |
567 | cpumask = iucv_irq_cpumask; | 567 | cpumask_copy(&cpumask, &iucv_irq_cpumask); |
568 | cpu_clear(first_cpu(iucv_irq_cpumask), cpumask); | 568 | cpumask_clear_cpu(cpumask_first(&iucv_irq_cpumask), &cpumask); |
569 | for_each_cpu_mask_nr(cpu, cpumask) | 569 | for_each_cpu(cpu, &cpumask) |
570 | smp_call_function_single(cpu, iucv_block_cpu, NULL, 1); | 570 | smp_call_function_single(cpu, iucv_block_cpu, NULL, 1); |
571 | } | 571 | } |
572 | 572 | ||
@@ -593,7 +593,7 @@ static int iucv_enable(void) | |||
593 | rc = -EIO; | 593 | rc = -EIO; |
594 | for_each_online_cpu(cpu) | 594 | for_each_online_cpu(cpu) |
595 | smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1); | 595 | smp_call_function_single(cpu, iucv_declare_cpu, NULL, 1); |
596 | if (cpus_empty(iucv_buffer_cpumask)) | 596 | if (cpumask_empty(&iucv_buffer_cpumask)) |
597 | /* No cpu could declare an iucv buffer. */ | 597 | /* No cpu could declare an iucv buffer. */ |
598 | goto out; | 598 | goto out; |
599 | put_online_cpus(); | 599 | put_online_cpus(); |
@@ -675,15 +675,16 @@ static int __cpuinit iucv_cpu_notify(struct notifier_block *self, | |||
675 | case CPU_DOWN_PREPARE_FROZEN: | 675 | case CPU_DOWN_PREPARE_FROZEN: |
676 | if (!iucv_path_table) | 676 | if (!iucv_path_table) |
677 | break; | 677 | break; |
678 | cpumask = iucv_buffer_cpumask; | 678 | cpumask_copy(&cpumask, &iucv_buffer_cpumask); |
679 | cpu_clear(cpu, cpumask); | 679 | cpumask_clear_cpu(cpu, &cpumask); |
680 | if (cpus_empty(cpumask)) | 680 | if (cpumask_empty(&cpumask)) |
681 | /* Can't offline last IUCV enabled cpu. */ | 681 | /* Can't offline last IUCV enabled cpu. */ |
682 | return notifier_from_errno(-EINVAL); | 682 | return notifier_from_errno(-EINVAL); |
683 | smp_call_function_single(cpu, iucv_retrieve_cpu, NULL, 1); | 683 | smp_call_function_single(cpu, iucv_retrieve_cpu, NULL, 1); |
684 | if (cpus_empty(iucv_irq_cpumask)) | 684 | if (cpumask_empty(&iucv_irq_cpumask)) |
685 | smp_call_function_single(first_cpu(iucv_buffer_cpumask), | 685 | smp_call_function_single( |
686 | iucv_allow_cpu, NULL, 1); | 686 | cpumask_first(&iucv_buffer_cpumask), |
687 | iucv_allow_cpu, NULL, 1); | ||
687 | break; | 688 | break; |
688 | } | 689 | } |
689 | return NOTIFY_OK; | 690 | return NOTIFY_OK; |
@@ -735,7 +736,7 @@ static void iucv_cleanup_queue(void) | |||
735 | struct iucv_irq_list *p, *n; | 736 | struct iucv_irq_list *p, *n; |
736 | 737 | ||
737 | /* | 738 | /* |
738 | * When a path is severed, the pathid can be reused immediatly | 739 | * When a path is severed, the pathid can be reused immediately |
739 | * on a iucv connect or a connection pending interrupt. Remove | 740 | * on a iucv connect or a connection pending interrupt. Remove |
740 | * all entries from the task queue that refer to a stale pathid | 741 | * all entries from the task queue that refer to a stale pathid |
741 | * (iucv_path_table[ix] == NULL). Only then do the iucv connect | 742 | * (iucv_path_table[ix] == NULL). Only then do the iucv connect |
@@ -807,7 +808,7 @@ void iucv_unregister(struct iucv_handler *handler, int smp) | |||
807 | spin_lock_bh(&iucv_table_lock); | 808 | spin_lock_bh(&iucv_table_lock); |
808 | /* Remove handler from the iucv_handler_list. */ | 809 | /* Remove handler from the iucv_handler_list. */ |
809 | list_del_init(&handler->list); | 810 | list_del_init(&handler->list); |
810 | /* Sever all pathids still refering to the handler. */ | 811 | /* Sever all pathids still referring to the handler. */ |
811 | list_for_each_entry_safe(p, n, &handler->paths, list) { | 812 | list_for_each_entry_safe(p, n, &handler->paths, list) { |
812 | iucv_sever_pathid(p->pathid, NULL); | 813 | iucv_sever_pathid(p->pathid, NULL); |
813 | iucv_path_table[p->pathid] = NULL; | 814 | iucv_path_table[p->pathid] = NULL; |
@@ -828,14 +829,14 @@ EXPORT_SYMBOL(iucv_unregister); | |||
828 | static int iucv_reboot_event(struct notifier_block *this, | 829 | static int iucv_reboot_event(struct notifier_block *this, |
829 | unsigned long event, void *ptr) | 830 | unsigned long event, void *ptr) |
830 | { | 831 | { |
831 | int i, rc; | 832 | int i; |
832 | 833 | ||
833 | get_online_cpus(); | 834 | get_online_cpus(); |
834 | on_each_cpu(iucv_block_cpu, NULL, 1); | 835 | on_each_cpu(iucv_block_cpu, NULL, 1); |
835 | preempt_disable(); | 836 | preempt_disable(); |
836 | for (i = 0; i < iucv_max_pathid; i++) { | 837 | for (i = 0; i < iucv_max_pathid; i++) { |
837 | if (iucv_path_table[i]) | 838 | if (iucv_path_table[i]) |
838 | rc = iucv_sever_pathid(i, NULL); | 839 | iucv_sever_pathid(i, NULL); |
839 | } | 840 | } |
840 | preempt_enable(); | 841 | preempt_enable(); |
841 | put_online_cpus(); | 842 | put_online_cpus(); |
@@ -866,7 +867,7 @@ int iucv_path_accept(struct iucv_path *path, struct iucv_handler *handler, | |||
866 | int rc; | 867 | int rc; |
867 | 868 | ||
868 | local_bh_disable(); | 869 | local_bh_disable(); |
869 | if (cpus_empty(iucv_buffer_cpumask)) { | 870 | if (cpumask_empty(&iucv_buffer_cpumask)) { |
870 | rc = -EIO; | 871 | rc = -EIO; |
871 | goto out; | 872 | goto out; |
872 | } | 873 | } |
@@ -915,7 +916,7 @@ int iucv_path_connect(struct iucv_path *path, struct iucv_handler *handler, | |||
915 | 916 | ||
916 | spin_lock_bh(&iucv_table_lock); | 917 | spin_lock_bh(&iucv_table_lock); |
917 | iucv_cleanup_queue(); | 918 | iucv_cleanup_queue(); |
918 | if (cpus_empty(iucv_buffer_cpumask)) { | 919 | if (cpumask_empty(&iucv_buffer_cpumask)) { |
919 | rc = -EIO; | 920 | rc = -EIO; |
920 | goto out; | 921 | goto out; |
921 | } | 922 | } |
@@ -975,7 +976,7 @@ int iucv_path_quiesce(struct iucv_path *path, u8 userdata[16]) | |||
975 | int rc; | 976 | int rc; |
976 | 977 | ||
977 | local_bh_disable(); | 978 | local_bh_disable(); |
978 | if (cpus_empty(iucv_buffer_cpumask)) { | 979 | if (cpumask_empty(&iucv_buffer_cpumask)) { |
979 | rc = -EIO; | 980 | rc = -EIO; |
980 | goto out; | 981 | goto out; |
981 | } | 982 | } |
@@ -1007,7 +1008,7 @@ int iucv_path_resume(struct iucv_path *path, u8 userdata[16]) | |||
1007 | int rc; | 1008 | int rc; |
1008 | 1009 | ||
1009 | local_bh_disable(); | 1010 | local_bh_disable(); |
1010 | if (cpus_empty(iucv_buffer_cpumask)) { | 1011 | if (cpumask_empty(&iucv_buffer_cpumask)) { |
1011 | rc = -EIO; | 1012 | rc = -EIO; |
1012 | goto out; | 1013 | goto out; |
1013 | } | 1014 | } |
@@ -1036,7 +1037,7 @@ int iucv_path_sever(struct iucv_path *path, u8 userdata[16]) | |||
1036 | int rc; | 1037 | int rc; |
1037 | 1038 | ||
1038 | preempt_disable(); | 1039 | preempt_disable(); |
1039 | if (cpus_empty(iucv_buffer_cpumask)) { | 1040 | if (cpumask_empty(&iucv_buffer_cpumask)) { |
1040 | rc = -EIO; | 1041 | rc = -EIO; |
1041 | goto out; | 1042 | goto out; |
1042 | } | 1043 | } |
@@ -1070,7 +1071,7 @@ int iucv_message_purge(struct iucv_path *path, struct iucv_message *msg, | |||
1070 | int rc; | 1071 | int rc; |
1071 | 1072 | ||
1072 | local_bh_disable(); | 1073 | local_bh_disable(); |
1073 | if (cpus_empty(iucv_buffer_cpumask)) { | 1074 | if (cpumask_empty(&iucv_buffer_cpumask)) { |
1074 | rc = -EIO; | 1075 | rc = -EIO; |
1075 | goto out; | 1076 | goto out; |
1076 | } | 1077 | } |
@@ -1162,7 +1163,7 @@ int __iucv_message_receive(struct iucv_path *path, struct iucv_message *msg, | |||
1162 | if (msg->flags & IUCV_IPRMDATA) | 1163 | if (msg->flags & IUCV_IPRMDATA) |
1163 | return iucv_message_receive_iprmdata(path, msg, flags, | 1164 | return iucv_message_receive_iprmdata(path, msg, flags, |
1164 | buffer, size, residual); | 1165 | buffer, size, residual); |
1165 | if (cpus_empty(iucv_buffer_cpumask)) { | 1166 | if (cpumask_empty(&iucv_buffer_cpumask)) { |
1166 | rc = -EIO; | 1167 | rc = -EIO; |
1167 | goto out; | 1168 | goto out; |
1168 | } | 1169 | } |
@@ -1235,7 +1236,7 @@ int iucv_message_reject(struct iucv_path *path, struct iucv_message *msg) | |||
1235 | int rc; | 1236 | int rc; |
1236 | 1237 | ||
1237 | local_bh_disable(); | 1238 | local_bh_disable(); |
1238 | if (cpus_empty(iucv_buffer_cpumask)) { | 1239 | if (cpumask_empty(&iucv_buffer_cpumask)) { |
1239 | rc = -EIO; | 1240 | rc = -EIO; |
1240 | goto out; | 1241 | goto out; |
1241 | } | 1242 | } |
@@ -1274,7 +1275,7 @@ int iucv_message_reply(struct iucv_path *path, struct iucv_message *msg, | |||
1274 | int rc; | 1275 | int rc; |
1275 | 1276 | ||
1276 | local_bh_disable(); | 1277 | local_bh_disable(); |
1277 | if (cpus_empty(iucv_buffer_cpumask)) { | 1278 | if (cpumask_empty(&iucv_buffer_cpumask)) { |
1278 | rc = -EIO; | 1279 | rc = -EIO; |
1279 | goto out; | 1280 | goto out; |
1280 | } | 1281 | } |
@@ -1324,7 +1325,7 @@ int __iucv_message_send(struct iucv_path *path, struct iucv_message *msg, | |||
1324 | union iucv_param *parm; | 1325 | union iucv_param *parm; |
1325 | int rc; | 1326 | int rc; |
1326 | 1327 | ||
1327 | if (cpus_empty(iucv_buffer_cpumask)) { | 1328 | if (cpumask_empty(&iucv_buffer_cpumask)) { |
1328 | rc = -EIO; | 1329 | rc = -EIO; |
1329 | goto out; | 1330 | goto out; |
1330 | } | 1331 | } |
@@ -1411,7 +1412,7 @@ int iucv_message_send2way(struct iucv_path *path, struct iucv_message *msg, | |||
1411 | int rc; | 1412 | int rc; |
1412 | 1413 | ||
1413 | local_bh_disable(); | 1414 | local_bh_disable(); |
1414 | if (cpus_empty(iucv_buffer_cpumask)) { | 1415 | if (cpumask_empty(&iucv_buffer_cpumask)) { |
1415 | rc = -EIO; | 1416 | rc = -EIO; |
1416 | goto out; | 1417 | goto out; |
1417 | } | 1418 | } |
@@ -1888,7 +1889,7 @@ static int iucv_pm_freeze(struct device *dev) | |||
1888 | printk(KERN_WARNING "iucv_pm_freeze\n"); | 1889 | printk(KERN_WARNING "iucv_pm_freeze\n"); |
1889 | #endif | 1890 | #endif |
1890 | if (iucv_pm_state != IUCV_PM_FREEZING) { | 1891 | if (iucv_pm_state != IUCV_PM_FREEZING) { |
1891 | for_each_cpu_mask_nr(cpu, iucv_irq_cpumask) | 1892 | for_each_cpu(cpu, &iucv_irq_cpumask) |
1892 | smp_call_function_single(cpu, iucv_block_cpu_almost, | 1893 | smp_call_function_single(cpu, iucv_block_cpu_almost, |
1893 | NULL, 1); | 1894 | NULL, 1); |
1894 | cancel_work_sync(&iucv_work); | 1895 | cancel_work_sync(&iucv_work); |
@@ -1928,7 +1929,7 @@ static int iucv_pm_thaw(struct device *dev) | |||
1928 | if (rc) | 1929 | if (rc) |
1929 | goto out; | 1930 | goto out; |
1930 | } | 1931 | } |
1931 | if (cpus_empty(iucv_irq_cpumask)) { | 1932 | if (cpumask_empty(&iucv_irq_cpumask)) { |
1932 | if (iucv_nonsmp_handler) | 1933 | if (iucv_nonsmp_handler) |
1933 | /* enable interrupts on one cpu */ | 1934 | /* enable interrupts on one cpu */ |
1934 | iucv_allow_cpu(NULL); | 1935 | iucv_allow_cpu(NULL); |
@@ -1961,7 +1962,7 @@ static int iucv_pm_restore(struct device *dev) | |||
1961 | pr_warning("Suspending Linux did not completely close all IUCV " | 1962 | pr_warning("Suspending Linux did not completely close all IUCV " |
1962 | "connections\n"); | 1963 | "connections\n"); |
1963 | iucv_pm_state = IUCV_PM_RESTORING; | 1964 | iucv_pm_state = IUCV_PM_RESTORING; |
1964 | if (cpus_empty(iucv_irq_cpumask)) { | 1965 | if (cpumask_empty(&iucv_irq_cpumask)) { |
1965 | rc = iucv_query_maxconn(); | 1966 | rc = iucv_query_maxconn(); |
1966 | rc = iucv_enable(); | 1967 | rc = iucv_enable(); |
1967 | if (rc) | 1968 | if (rc) |
diff --git a/net/key/af_key.c b/net/key/af_key.c index 7db86ffcf070..d62401c25684 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
@@ -712,7 +712,7 @@ static unsigned int pfkey_sockaddr_fill(const xfrm_address_t *xaddr, __be16 port | |||
712 | sin6->sin6_family = AF_INET6; | 712 | sin6->sin6_family = AF_INET6; |
713 | sin6->sin6_port = port; | 713 | sin6->sin6_port = port; |
714 | sin6->sin6_flowinfo = 0; | 714 | sin6->sin6_flowinfo = 0; |
715 | ipv6_addr_copy(&sin6->sin6_addr, (struct in6_addr *)xaddr->a6); | 715 | ipv6_addr_copy(&sin6->sin6_addr, (const struct in6_addr *)xaddr->a6); |
716 | sin6->sin6_scope_id = 0; | 716 | sin6->sin6_scope_id = 0; |
717 | return 128; | 717 | return 128; |
718 | } | 718 | } |
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index c64ce0a0bb03..ed8a2335442f 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c | |||
@@ -954,7 +954,7 @@ static int l2tp_build_l2tpv3_header(struct l2tp_session *session, void *buf) | |||
954 | } | 954 | } |
955 | 955 | ||
956 | static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, | 956 | static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, |
957 | size_t data_len) | 957 | struct flowi *fl, size_t data_len) |
958 | { | 958 | { |
959 | struct l2tp_tunnel *tunnel = session->tunnel; | 959 | struct l2tp_tunnel *tunnel = session->tunnel; |
960 | unsigned int len = skb->len; | 960 | unsigned int len = skb->len; |
@@ -987,7 +987,7 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, | |||
987 | 987 | ||
988 | /* Queue the packet to IP for output */ | 988 | /* Queue the packet to IP for output */ |
989 | skb->local_df = 1; | 989 | skb->local_df = 1; |
990 | error = ip_queue_xmit(skb); | 990 | error = ip_queue_xmit(skb, fl); |
991 | 991 | ||
992 | /* Update stats */ | 992 | /* Update stats */ |
993 | if (error >= 0) { | 993 | if (error >= 0) { |
@@ -1028,6 +1028,7 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len | |||
1028 | int data_len = skb->len; | 1028 | int data_len = skb->len; |
1029 | struct l2tp_tunnel *tunnel = session->tunnel; | 1029 | struct l2tp_tunnel *tunnel = session->tunnel; |
1030 | struct sock *sk = tunnel->sock; | 1030 | struct sock *sk = tunnel->sock; |
1031 | struct flowi *fl; | ||
1031 | struct udphdr *uh; | 1032 | struct udphdr *uh; |
1032 | struct inet_sock *inet; | 1033 | struct inet_sock *inet; |
1033 | __wsum csum; | 1034 | __wsum csum; |
@@ -1060,14 +1061,21 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len | |||
1060 | IPSKB_REROUTED); | 1061 | IPSKB_REROUTED); |
1061 | nf_reset(skb); | 1062 | nf_reset(skb); |
1062 | 1063 | ||
1064 | bh_lock_sock(sk); | ||
1065 | if (sock_owned_by_user(sk)) { | ||
1066 | dev_kfree_skb(skb); | ||
1067 | goto out_unlock; | ||
1068 | } | ||
1069 | |||
1063 | /* Get routing info from the tunnel socket */ | 1070 | /* Get routing info from the tunnel socket */ |
1064 | skb_dst_drop(skb); | 1071 | skb_dst_drop(skb); |
1065 | skb_dst_set(skb, dst_clone(__sk_dst_get(sk))); | 1072 | skb_dst_set(skb, dst_clone(__sk_dst_get(sk))); |
1066 | 1073 | ||
1074 | inet = inet_sk(sk); | ||
1075 | fl = &inet->cork.fl; | ||
1067 | switch (tunnel->encap) { | 1076 | switch (tunnel->encap) { |
1068 | case L2TP_ENCAPTYPE_UDP: | 1077 | case L2TP_ENCAPTYPE_UDP: |
1069 | /* Setup UDP header */ | 1078 | /* Setup UDP header */ |
1070 | inet = inet_sk(sk); | ||
1071 | __skb_push(skb, sizeof(*uh)); | 1079 | __skb_push(skb, sizeof(*uh)); |
1072 | skb_reset_transport_header(skb); | 1080 | skb_reset_transport_header(skb); |
1073 | uh = udp_hdr(skb); | 1081 | uh = udp_hdr(skb); |
@@ -1105,7 +1113,9 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len | |||
1105 | 1113 | ||
1106 | l2tp_skb_set_owner_w(skb, sk); | 1114 | l2tp_skb_set_owner_w(skb, sk); |
1107 | 1115 | ||
1108 | l2tp_xmit_core(session, skb, data_len); | 1116 | l2tp_xmit_core(session, skb, fl, data_len); |
1117 | out_unlock: | ||
1118 | bh_unlock_sock(sk); | ||
1109 | 1119 | ||
1110 | abort: | 1120 | abort: |
1111 | return 0; | 1121 | return 0; |
@@ -1425,16 +1435,15 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 | |||
1425 | 1435 | ||
1426 | /* Add tunnel to our list */ | 1436 | /* Add tunnel to our list */ |
1427 | INIT_LIST_HEAD(&tunnel->list); | 1437 | INIT_LIST_HEAD(&tunnel->list); |
1428 | spin_lock_bh(&pn->l2tp_tunnel_list_lock); | ||
1429 | list_add_rcu(&tunnel->list, &pn->l2tp_tunnel_list); | ||
1430 | spin_unlock_bh(&pn->l2tp_tunnel_list_lock); | ||
1431 | synchronize_rcu(); | ||
1432 | atomic_inc(&l2tp_tunnel_count); | 1438 | atomic_inc(&l2tp_tunnel_count); |
1433 | 1439 | ||
1434 | /* Bump the reference count. The tunnel context is deleted | 1440 | /* Bump the reference count. The tunnel context is deleted |
1435 | * only when this drops to zero. | 1441 | * only when this drops to zero. Must be done before list insertion |
1436 | */ | 1442 | */ |
1437 | 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); | ||
1438 | 1447 | ||
1439 | err = 0; | 1448 | err = 0; |
1440 | err: | 1449 | err: |
@@ -1626,7 +1635,6 @@ struct l2tp_session *l2tp_session_create(int priv_size, struct l2tp_tunnel *tunn | |||
1626 | hlist_add_head_rcu(&session->global_hlist, | 1635 | hlist_add_head_rcu(&session->global_hlist, |
1627 | l2tp_session_id_hash_2(pn, session_id)); | 1636 | l2tp_session_id_hash_2(pn, session_id)); |
1628 | spin_unlock_bh(&pn->l2tp_session_hlist_lock); | 1637 | spin_unlock_bh(&pn->l2tp_session_hlist_lock); |
1629 | synchronize_rcu(); | ||
1630 | } | 1638 | } |
1631 | 1639 | ||
1632 | /* Ignore management session in session count value */ | 1640 | /* Ignore management session in session count value */ |
diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c index fce9bd3bd3fe..f7fb09ecaf89 100644 --- a/net/l2tp/l2tp_ip.c +++ b/net/l2tp/l2tp_ip.c | |||
@@ -296,12 +296,12 @@ out_in_use: | |||
296 | 296 | ||
297 | static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | 297 | static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) |
298 | { | 298 | { |
299 | int rc; | ||
300 | struct inet_sock *inet = inet_sk(sk); | ||
301 | struct sockaddr_l2tpip *lsa = (struct sockaddr_l2tpip *) uaddr; | 299 | struct sockaddr_l2tpip *lsa = (struct sockaddr_l2tpip *) uaddr; |
300 | struct inet_sock *inet = inet_sk(sk); | ||
301 | struct flowi4 *fl4; | ||
302 | struct rtable *rt; | 302 | struct rtable *rt; |
303 | __be32 saddr; | 303 | __be32 saddr; |
304 | int oif; | 304 | int oif, rc; |
305 | 305 | ||
306 | rc = -EINVAL; | 306 | rc = -EINVAL; |
307 | if (addr_len < sizeof(*lsa)) | 307 | if (addr_len < sizeof(*lsa)) |
@@ -311,6 +311,8 @@ static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len | |||
311 | if (lsa->l2tp_family != AF_INET) | 311 | if (lsa->l2tp_family != AF_INET) |
312 | goto out; | 312 | goto out; |
313 | 313 | ||
314 | lock_sock(sk); | ||
315 | |||
314 | sk_dst_reset(sk); | 316 | sk_dst_reset(sk); |
315 | 317 | ||
316 | oif = sk->sk_bound_dev_if; | 318 | oif = sk->sk_bound_dev_if; |
@@ -320,7 +322,8 @@ static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len | |||
320 | if (ipv4_is_multicast(lsa->l2tp_addr.s_addr)) | 322 | if (ipv4_is_multicast(lsa->l2tp_addr.s_addr)) |
321 | goto out; | 323 | goto out; |
322 | 324 | ||
323 | rt = ip_route_connect(lsa->l2tp_addr.s_addr, saddr, | 325 | fl4 = &inet->cork.fl.u.ip4; |
326 | rt = ip_route_connect(fl4, lsa->l2tp_addr.s_addr, saddr, | ||
324 | RT_CONN_FLAGS(sk), oif, | 327 | RT_CONN_FLAGS(sk), oif, |
325 | IPPROTO_L2TP, | 328 | IPPROTO_L2TP, |
326 | 0, 0, sk, true); | 329 | 0, 0, sk, true); |
@@ -340,10 +343,10 @@ static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len | |||
340 | l2tp_ip_sk(sk)->peer_conn_id = lsa->l2tp_conn_id; | 343 | l2tp_ip_sk(sk)->peer_conn_id = lsa->l2tp_conn_id; |
341 | 344 | ||
342 | if (!inet->inet_saddr) | 345 | if (!inet->inet_saddr) |
343 | inet->inet_saddr = rt->rt_src; | 346 | inet->inet_saddr = fl4->saddr; |
344 | if (!inet->inet_rcv_saddr) | 347 | if (!inet->inet_rcv_saddr) |
345 | inet->inet_rcv_saddr = rt->rt_src; | 348 | inet->inet_rcv_saddr = fl4->saddr; |
346 | inet->inet_daddr = rt->rt_dst; | 349 | inet->inet_daddr = fl4->daddr; |
347 | sk->sk_state = TCP_ESTABLISHED; | 350 | sk->sk_state = TCP_ESTABLISHED; |
348 | inet->inet_id = jiffies; | 351 | inet->inet_id = jiffies; |
349 | 352 | ||
@@ -356,6 +359,7 @@ static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len | |||
356 | 359 | ||
357 | rc = 0; | 360 | rc = 0; |
358 | out: | 361 | out: |
362 | release_sock(sk); | ||
359 | return rc; | 363 | return rc; |
360 | } | 364 | } |
361 | 365 | ||
@@ -416,23 +420,28 @@ static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m | |||
416 | int rc; | 420 | int rc; |
417 | struct l2tp_ip_sock *lsa = l2tp_ip_sk(sk); | 421 | struct l2tp_ip_sock *lsa = l2tp_ip_sk(sk); |
418 | struct inet_sock *inet = inet_sk(sk); | 422 | struct inet_sock *inet = inet_sk(sk); |
419 | struct ip_options *opt = inet->opt; | ||
420 | struct rtable *rt = NULL; | 423 | struct rtable *rt = NULL; |
424 | struct flowi4 *fl4; | ||
421 | int connected = 0; | 425 | int connected = 0; |
422 | __be32 daddr; | 426 | __be32 daddr; |
423 | 427 | ||
428 | lock_sock(sk); | ||
429 | |||
430 | rc = -ENOTCONN; | ||
424 | if (sock_flag(sk, SOCK_DEAD)) | 431 | if (sock_flag(sk, SOCK_DEAD)) |
425 | return -ENOTCONN; | 432 | goto out; |
426 | 433 | ||
427 | /* Get and verify the address. */ | 434 | /* Get and verify the address. */ |
428 | if (msg->msg_name) { | 435 | if (msg->msg_name) { |
429 | struct sockaddr_l2tpip *lip = (struct sockaddr_l2tpip *) msg->msg_name; | 436 | struct sockaddr_l2tpip *lip = (struct sockaddr_l2tpip *) msg->msg_name; |
437 | rc = -EINVAL; | ||
430 | if (msg->msg_namelen < sizeof(*lip)) | 438 | if (msg->msg_namelen < sizeof(*lip)) |
431 | return -EINVAL; | 439 | goto out; |
432 | 440 | ||
433 | if (lip->l2tp_family != AF_INET) { | 441 | if (lip->l2tp_family != AF_INET) { |
442 | rc = -EAFNOSUPPORT; | ||
434 | if (lip->l2tp_family != AF_UNSPEC) | 443 | if (lip->l2tp_family != AF_UNSPEC) |
435 | return -EAFNOSUPPORT; | 444 | goto out; |
436 | } | 445 | } |
437 | 446 | ||
438 | daddr = lip->l2tp_addr.s_addr; | 447 | daddr = lip->l2tp_addr.s_addr; |
@@ -467,19 +476,27 @@ static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m | |||
467 | goto error; | 476 | goto error; |
468 | } | 477 | } |
469 | 478 | ||
479 | fl4 = &inet->cork.fl.u.ip4; | ||
470 | if (connected) | 480 | if (connected) |
471 | rt = (struct rtable *) __sk_dst_check(sk, 0); | 481 | rt = (struct rtable *) __sk_dst_check(sk, 0); |
472 | 482 | ||
473 | if (rt == NULL) { | 483 | if (rt == NULL) { |
484 | struct ip_options_rcu *inet_opt; | ||
485 | |||
486 | rcu_read_lock(); | ||
487 | inet_opt = rcu_dereference(inet->inet_opt); | ||
488 | |||
474 | /* Use correct destination address if we have options. */ | 489 | /* Use correct destination address if we have options. */ |
475 | if (opt && opt->srr) | 490 | if (inet_opt && inet_opt->opt.srr) |
476 | daddr = opt->faddr; | 491 | daddr = inet_opt->opt.faddr; |
492 | |||
493 | rcu_read_unlock(); | ||
477 | 494 | ||
478 | /* If this fails, retransmit mechanism of transport layer will | 495 | /* If this fails, retransmit mechanism of transport layer will |
479 | * keep trying until route appears or the connection times | 496 | * keep trying until route appears or the connection times |
480 | * itself out. | 497 | * itself out. |
481 | */ | 498 | */ |
482 | rt = ip_route_output_ports(sock_net(sk), sk, | 499 | rt = ip_route_output_ports(sock_net(sk), fl4, sk, |
483 | daddr, inet->inet_saddr, | 500 | daddr, inet->inet_saddr, |
484 | inet->inet_dport, inet->inet_sport, | 501 | inet->inet_dport, inet->inet_sport, |
485 | sk->sk_protocol, RT_CONN_FLAGS(sk), | 502 | sk->sk_protocol, RT_CONN_FLAGS(sk), |
@@ -491,7 +508,7 @@ static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m | |||
491 | skb_dst_set(skb, dst_clone(&rt->dst)); | 508 | skb_dst_set(skb, dst_clone(&rt->dst)); |
492 | 509 | ||
493 | /* Queue the packet to IP for output */ | 510 | /* Queue the packet to IP for output */ |
494 | rc = ip_queue_xmit(skb); | 511 | rc = ip_queue_xmit(skb, &inet->cork.fl); |
495 | 512 | ||
496 | error: | 513 | error: |
497 | /* Update stats */ | 514 | /* Update stats */ |
@@ -503,12 +520,15 @@ error: | |||
503 | lsa->tx_errors++; | 520 | lsa->tx_errors++; |
504 | } | 521 | } |
505 | 522 | ||
523 | out: | ||
524 | release_sock(sk); | ||
506 | return rc; | 525 | return rc; |
507 | 526 | ||
508 | no_route: | 527 | no_route: |
509 | IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); | 528 | IP_INC_STATS(sock_net(sk), IPSTATS_MIB_OUTNOROUTES); |
510 | kfree_skb(skb); | 529 | kfree_skb(skb); |
511 | return -EHOSTUNREACH; | 530 | rc = -EHOSTUNREACH; |
531 | goto out; | ||
512 | } | 532 | } |
513 | 533 | ||
514 | static int l2tp_ip_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | 534 | static int l2tp_ip_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, |
diff --git a/net/l2tp/l2tp_netlink.c b/net/l2tp/l2tp_netlink.c index 4c1e540732d7..93a41a09458b 100644 --- a/net/l2tp/l2tp_netlink.c +++ b/net/l2tp/l2tp_netlink.c | |||
@@ -795,11 +795,12 @@ int l2tp_nl_register_ops(enum l2tp_pwtype pw_type, const struct l2tp_nl_cmd_ops | |||
795 | goto out; | 795 | goto out; |
796 | 796 | ||
797 | l2tp_nl_cmd_ops[pw_type] = ops; | 797 | l2tp_nl_cmd_ops[pw_type] = ops; |
798 | ret = 0; | ||
798 | 799 | ||
799 | out: | 800 | out: |
800 | genl_unlock(); | 801 | genl_unlock(); |
801 | err: | 802 | err: |
802 | return 0; | 803 | return ret; |
803 | } | 804 | } |
804 | EXPORT_SYMBOL_GPL(l2tp_nl_register_ops); | 805 | EXPORT_SYMBOL_GPL(l2tp_nl_register_ops); |
805 | 806 | ||
diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c index 058f1e9a9128..903242111317 100644 --- a/net/llc/llc_input.c +++ b/net/llc/llc_input.c | |||
@@ -121,8 +121,7 @@ static inline int llc_fixup_skb(struct sk_buff *skb) | |||
121 | s32 data_size = ntohs(pdulen) - llc_len; | 121 | s32 data_size = ntohs(pdulen) - llc_len; |
122 | 122 | ||
123 | if (data_size < 0 || | 123 | if (data_size < 0 || |
124 | ((skb_tail_pointer(skb) - | 124 | !pskb_may_pull(skb, data_size)) |
125 | (u8 *)pdu) - llc_len) < data_size) | ||
126 | return 0; | 125 | return 0; |
127 | if (unlikely(pskb_trim_rcsum(skb, data_size))) | 126 | if (unlikely(pskb_trim_rcsum(skb, data_size))) |
128 | return 0; | 127 | return 0; |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index ed755889645d..2025af52b195 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -97,7 +97,7 @@ struct ieee80211_bss { | |||
97 | size_t supp_rates_len; | 97 | size_t supp_rates_len; |
98 | 98 | ||
99 | /* | 99 | /* |
100 | * During assocation, we save an ERP value from a probe response so | 100 | * During association, we save an ERP value from a probe response so |
101 | * that we can feed ERP info to the driver when handling the | 101 | * that we can feed ERP info to the driver when handling the |
102 | * association completes. these fields probably won't be up-to-date | 102 | * association completes. these fields probably won't be up-to-date |
103 | * otherwise, you probably don't want to use them. | 103 | * otherwise, you probably don't want to use them. |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 0d00ac93d958..7dfbe71dc637 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -1145,10 +1145,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1145 | + IEEE80211_ENCRYPT_HEADROOM; | 1145 | + IEEE80211_ENCRYPT_HEADROOM; |
1146 | ndev->needed_tailroom = IEEE80211_ENCRYPT_TAILROOM; | 1146 | ndev->needed_tailroom = IEEE80211_ENCRYPT_TAILROOM; |
1147 | 1147 | ||
1148 | ret = dev_alloc_name(ndev, ndev->name); | ||
1149 | if (ret < 0) | ||
1150 | goto fail; | ||
1151 | |||
1152 | ieee80211_assign_perm_addr(local, ndev, type); | 1148 | ieee80211_assign_perm_addr(local, ndev, type); |
1153 | memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN); | 1149 | memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN); |
1154 | SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); | 1150 | SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 0aa96cd6bd27..83ce48e31913 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -680,7 +680,7 @@ void mesh_path_discard_frame(struct sk_buff *skb, | |||
680 | * | 680 | * |
681 | * @mpath: mesh path whose queue has to be freed | 681 | * @mpath: mesh path whose queue has to be freed |
682 | * | 682 | * |
683 | * Locking: the function must me called withing a rcu_read_lock region | 683 | * Locking: the function must me called within a rcu_read_lock region |
684 | */ | 684 | */ |
685 | void mesh_path_flush_pending(struct mesh_path *mpath) | 685 | void mesh_path_flush_pending(struct mesh_path *mpath) |
686 | { | 686 | { |
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index 3d09c58938e2..333b5118be6d 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
@@ -259,7 +259,7 @@ minstrel_ht_update_stats(struct minstrel_priv *mp, struct minstrel_ht_sta *mi) | |||
259 | } | 259 | } |
260 | } | 260 | } |
261 | 261 | ||
262 | /* try to sample up to half of the availble rates during each interval */ | 262 | /* try to sample up to half of the available rates during each interval */ |
263 | mi->sample_count *= 4; | 263 | mi->sample_count *= 4; |
264 | 264 | ||
265 | cur_prob = 0; | 265 | cur_prob = 0; |
diff --git a/net/mac80211/rc80211_pid.h b/net/mac80211/rc80211_pid.h index 6510f8ee738e..19111c7bf454 100644 --- a/net/mac80211/rc80211_pid.h +++ b/net/mac80211/rc80211_pid.h | |||
@@ -77,7 +77,7 @@ union rc_pid_event_data { | |||
77 | }; | 77 | }; |
78 | 78 | ||
79 | struct rc_pid_event { | 79 | struct rc_pid_event { |
80 | /* The time when the event occured */ | 80 | /* The time when the event occurred */ |
81 | unsigned long timestamp; | 81 | unsigned long timestamp; |
82 | 82 | ||
83 | /* Event ID number */ | 83 | /* Event ID number */ |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 78c72a41d864..7fa8c6be7bf0 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -382,7 +382,7 @@ static void ieee80211_parse_qos(struct ieee80211_rx_data *rx) | |||
382 | * specs were sane enough this time around to require padding each A-MSDU | 382 | * specs were sane enough this time around to require padding each A-MSDU |
383 | * subframe to a length that is a multiple of four. | 383 | * subframe to a length that is a multiple of four. |
384 | * | 384 | * |
385 | * Padding like Atheros hardware adds which is inbetween the 802.11 header and | 385 | * Padding like Atheros hardware adds which is between the 802.11 header and |
386 | * the payload is not supported, the driver is required to move the 802.11 | 386 | * the payload is not supported, the driver is required to move the 802.11 |
387 | * header to be directly in front of the payload in that case. | 387 | * header to be directly in front of the payload in that case. |
388 | */ | 388 | */ |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 4a15f9603562..b83870bf60fa 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -47,9 +47,9 @@ | |||
47 | * Station entries are added by mac80211 when you establish a link with a | 47 | * Station entries are added by mac80211 when you establish a link with a |
48 | * peer. This means different things for the different type of interfaces | 48 | * peer. This means different things for the different type of interfaces |
49 | * we support. For a regular station this mean we add the AP sta when we | 49 | * we support. For a regular station this mean we add the AP sta when we |
50 | * receive an assocation response from the AP. For IBSS this occurs when | 50 | * receive an association response from the AP. For IBSS this occurs when |
51 | * get to know about a peer on the same IBSS. For WDS we add the sta for | 51 | * get to know about a peer on the same IBSS. For WDS we add the sta for |
52 | * the peer imediately upon device open. When using AP mode we add stations | 52 | * the peer immediately upon device open. When using AP mode we add stations |
53 | * for each respective station upon request from userspace through nl80211. | 53 | * for each respective station upon request from userspace through nl80211. |
54 | * | 54 | * |
55 | * In order to remove a STA info structure, various sta_info_destroy_*() | 55 | * In order to remove a STA info structure, various sta_info_destroy_*() |
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index c3f988aa1152..32bff6d86cb2 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
@@ -652,7 +652,6 @@ comment "Xtables matches" | |||
652 | config NETFILTER_XT_MATCH_ADDRTYPE | 652 | config NETFILTER_XT_MATCH_ADDRTYPE |
653 | tristate '"addrtype" address type match support' | 653 | tristate '"addrtype" address type match support' |
654 | depends on NETFILTER_ADVANCED | 654 | depends on NETFILTER_ADVANCED |
655 | depends on (IPV6 || IPV6=n) | ||
656 | ---help--- | 655 | ---help--- |
657 | This option allows you to match what routing thinks of an address, | 656 | This option allows you to match what routing thinks of an address, |
658 | eg. UNICAST, LOCAL, BROADCAST, ... | 657 | eg. UNICAST, LOCAL, BROADCAST, ... |
diff --git a/net/netfilter/ipset/ip_set_bitmap_ip.c b/net/netfilter/ipset/ip_set_bitmap_ip.c index bca96990218d..a113ff066928 100644 --- a/net/netfilter/ipset/ip_set_bitmap_ip.c +++ b/net/netfilter/ipset/ip_set_bitmap_ip.c | |||
@@ -338,8 +338,7 @@ bitmap_ip_head(struct ip_set *set, struct sk_buff *skb) | |||
338 | NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip)); | 338 | NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip)); |
339 | if (map->netmask != 32) | 339 | if (map->netmask != 32) |
340 | NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, map->netmask); | 340 | NLA_PUT_U8(skb, IPSET_ATTR_NETMASK, map->netmask); |
341 | NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, | 341 | NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)); |
342 | htonl(atomic_read(&set->ref) - 1)); | ||
343 | NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, | 342 | NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, |
344 | htonl(sizeof(*map) + map->memsize)); | 343 | htonl(sizeof(*map) + map->memsize)); |
345 | if (with_timeout(map->timeout)) | 344 | if (with_timeout(map->timeout)) |
diff --git a/net/netfilter/ipset/ip_set_bitmap_ipmac.c b/net/netfilter/ipset/ip_set_bitmap_ipmac.c index 5e790172deff..a274300b6a56 100644 --- a/net/netfilter/ipset/ip_set_bitmap_ipmac.c +++ b/net/netfilter/ipset/ip_set_bitmap_ipmac.c | |||
@@ -343,6 +343,10 @@ bitmap_ipmac_kadt(struct ip_set *set, const struct sk_buff *skb, | |||
343 | ipset_adtfn adtfn = set->variant->adt[adt]; | 343 | ipset_adtfn adtfn = set->variant->adt[adt]; |
344 | struct ipmac data; | 344 | struct ipmac data; |
345 | 345 | ||
346 | /* MAC can be src only */ | ||
347 | if (!(flags & IPSET_DIM_TWO_SRC)) | ||
348 | return 0; | ||
349 | |||
346 | data.id = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC)); | 350 | data.id = ntohl(ip4addr(skb, flags & IPSET_DIM_ONE_SRC)); |
347 | if (data.id < map->first_ip || data.id > map->last_ip) | 351 | if (data.id < map->first_ip || data.id > map->last_ip) |
348 | return -IPSET_ERR_BITMAP_RANGE; | 352 | return -IPSET_ERR_BITMAP_RANGE; |
@@ -434,8 +438,7 @@ bitmap_ipmac_head(struct ip_set *set, struct sk_buff *skb) | |||
434 | goto nla_put_failure; | 438 | goto nla_put_failure; |
435 | NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, htonl(map->first_ip)); | 439 | NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP, htonl(map->first_ip)); |
436 | NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip)); | 440 | NLA_PUT_IPADDR4(skb, IPSET_ATTR_IP_TO, htonl(map->last_ip)); |
437 | NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, | 441 | NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)); |
438 | htonl(atomic_read(&set->ref) - 1)); | ||
439 | NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, | 442 | NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, |
440 | htonl(sizeof(*map) | 443 | htonl(sizeof(*map) |
441 | + (map->last_ip - map->first_ip + 1) * map->dsize)); | 444 | + (map->last_ip - map->first_ip + 1) * map->dsize)); |
diff --git a/net/netfilter/ipset/ip_set_bitmap_port.c b/net/netfilter/ipset/ip_set_bitmap_port.c index 165f09b1a9cb..6b38eb8f6ed8 100644 --- a/net/netfilter/ipset/ip_set_bitmap_port.c +++ b/net/netfilter/ipset/ip_set_bitmap_port.c | |||
@@ -320,8 +320,7 @@ bitmap_port_head(struct ip_set *set, struct sk_buff *skb) | |||
320 | goto nla_put_failure; | 320 | goto nla_put_failure; |
321 | NLA_PUT_NET16(skb, IPSET_ATTR_PORT, htons(map->first_port)); | 321 | NLA_PUT_NET16(skb, IPSET_ATTR_PORT, htons(map->first_port)); |
322 | NLA_PUT_NET16(skb, IPSET_ATTR_PORT_TO, htons(map->last_port)); | 322 | NLA_PUT_NET16(skb, IPSET_ATTR_PORT_TO, htons(map->last_port)); |
323 | NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, | 323 | NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)); |
324 | htonl(atomic_read(&set->ref) - 1)); | ||
325 | NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, | 324 | NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, |
326 | htonl(sizeof(*map) + map->memsize)); | 325 | htonl(sizeof(*map) + map->memsize)); |
327 | if (with_timeout(map->timeout)) | 326 | if (with_timeout(map->timeout)) |
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c index d6b48230a540..72d1ac611fdc 100644 --- a/net/netfilter/ipset/ip_set_core.c +++ b/net/netfilter/ipset/ip_set_core.c | |||
@@ -26,6 +26,7 @@ | |||
26 | 26 | ||
27 | static LIST_HEAD(ip_set_type_list); /* all registered set types */ | 27 | static LIST_HEAD(ip_set_type_list); /* all registered set types */ |
28 | static DEFINE_MUTEX(ip_set_type_mutex); /* protects ip_set_type_list */ | 28 | static DEFINE_MUTEX(ip_set_type_mutex); /* protects ip_set_type_list */ |
29 | static DEFINE_RWLOCK(ip_set_ref_lock); /* protects the set refs */ | ||
29 | 30 | ||
30 | static struct ip_set **ip_set_list; /* all individual sets */ | 31 | static struct ip_set **ip_set_list; /* all individual sets */ |
31 | static ip_set_id_t ip_set_max = CONFIG_IP_SET_MAX; /* max number of sets */ | 32 | static ip_set_id_t ip_set_max = CONFIG_IP_SET_MAX; /* max number of sets */ |
@@ -301,13 +302,18 @@ EXPORT_SYMBOL_GPL(ip_set_get_ipaddr6); | |||
301 | static inline void | 302 | static inline void |
302 | __ip_set_get(ip_set_id_t index) | 303 | __ip_set_get(ip_set_id_t index) |
303 | { | 304 | { |
304 | atomic_inc(&ip_set_list[index]->ref); | 305 | write_lock_bh(&ip_set_ref_lock); |
306 | ip_set_list[index]->ref++; | ||
307 | write_unlock_bh(&ip_set_ref_lock); | ||
305 | } | 308 | } |
306 | 309 | ||
307 | static inline void | 310 | static inline void |
308 | __ip_set_put(ip_set_id_t index) | 311 | __ip_set_put(ip_set_id_t index) |
309 | { | 312 | { |
310 | atomic_dec(&ip_set_list[index]->ref); | 313 | write_lock_bh(&ip_set_ref_lock); |
314 | BUG_ON(ip_set_list[index]->ref == 0); | ||
315 | ip_set_list[index]->ref--; | ||
316 | write_unlock_bh(&ip_set_ref_lock); | ||
311 | } | 317 | } |
312 | 318 | ||
313 | /* | 319 | /* |
@@ -324,7 +330,7 @@ ip_set_test(ip_set_id_t index, const struct sk_buff *skb, | |||
324 | struct ip_set *set = ip_set_list[index]; | 330 | struct ip_set *set = ip_set_list[index]; |
325 | int ret = 0; | 331 | int ret = 0; |
326 | 332 | ||
327 | BUG_ON(set == NULL || atomic_read(&set->ref) == 0); | 333 | BUG_ON(set == NULL); |
328 | pr_debug("set %s, index %u\n", set->name, index); | 334 | pr_debug("set %s, index %u\n", set->name, index); |
329 | 335 | ||
330 | if (dim < set->type->dimension || | 336 | if (dim < set->type->dimension || |
@@ -356,7 +362,7 @@ ip_set_add(ip_set_id_t index, const struct sk_buff *skb, | |||
356 | struct ip_set *set = ip_set_list[index]; | 362 | struct ip_set *set = ip_set_list[index]; |
357 | int ret; | 363 | int ret; |
358 | 364 | ||
359 | BUG_ON(set == NULL || atomic_read(&set->ref) == 0); | 365 | BUG_ON(set == NULL); |
360 | pr_debug("set %s, index %u\n", set->name, index); | 366 | pr_debug("set %s, index %u\n", set->name, index); |
361 | 367 | ||
362 | if (dim < set->type->dimension || | 368 | if (dim < set->type->dimension || |
@@ -378,7 +384,7 @@ ip_set_del(ip_set_id_t index, const struct sk_buff *skb, | |||
378 | struct ip_set *set = ip_set_list[index]; | 384 | struct ip_set *set = ip_set_list[index]; |
379 | int ret = 0; | 385 | int ret = 0; |
380 | 386 | ||
381 | BUG_ON(set == NULL || atomic_read(&set->ref) == 0); | 387 | BUG_ON(set == NULL); |
382 | pr_debug("set %s, index %u\n", set->name, index); | 388 | pr_debug("set %s, index %u\n", set->name, index); |
383 | 389 | ||
384 | if (dim < set->type->dimension || | 390 | if (dim < set->type->dimension || |
@@ -397,7 +403,6 @@ EXPORT_SYMBOL_GPL(ip_set_del); | |||
397 | * Find set by name, reference it once. The reference makes sure the | 403 | * Find set by name, reference it once. The reference makes sure the |
398 | * thing pointed to, does not go away under our feet. | 404 | * thing pointed to, does not go away under our feet. |
399 | * | 405 | * |
400 | * The nfnl mutex must already be activated. | ||
401 | */ | 406 | */ |
402 | ip_set_id_t | 407 | ip_set_id_t |
403 | ip_set_get_byname(const char *name, struct ip_set **set) | 408 | ip_set_get_byname(const char *name, struct ip_set **set) |
@@ -423,15 +428,12 @@ EXPORT_SYMBOL_GPL(ip_set_get_byname); | |||
423 | * reference count by 1. The caller shall not assume the index | 428 | * reference count by 1. The caller shall not assume the index |
424 | * to be valid, after calling this function. | 429 | * to be valid, after calling this function. |
425 | * | 430 | * |
426 | * The nfnl mutex must already be activated. | ||
427 | */ | 431 | */ |
428 | void | 432 | void |
429 | ip_set_put_byindex(ip_set_id_t index) | 433 | ip_set_put_byindex(ip_set_id_t index) |
430 | { | 434 | { |
431 | if (ip_set_list[index] != NULL) { | 435 | if (ip_set_list[index] != NULL) |
432 | BUG_ON(atomic_read(&ip_set_list[index]->ref) == 0); | ||
433 | __ip_set_put(index); | 436 | __ip_set_put(index); |
434 | } | ||
435 | } | 437 | } |
436 | EXPORT_SYMBOL_GPL(ip_set_put_byindex); | 438 | EXPORT_SYMBOL_GPL(ip_set_put_byindex); |
437 | 439 | ||
@@ -441,7 +443,6 @@ EXPORT_SYMBOL_GPL(ip_set_put_byindex); | |||
441 | * can't be destroyed. The set cannot be renamed due to | 443 | * can't be destroyed. The set cannot be renamed due to |
442 | * the referencing either. | 444 | * the referencing either. |
443 | * | 445 | * |
444 | * The nfnl mutex must already be activated. | ||
445 | */ | 446 | */ |
446 | const char * | 447 | const char * |
447 | ip_set_name_byindex(ip_set_id_t index) | 448 | ip_set_name_byindex(ip_set_id_t index) |
@@ -449,7 +450,7 @@ ip_set_name_byindex(ip_set_id_t index) | |||
449 | const struct ip_set *set = ip_set_list[index]; | 450 | const struct ip_set *set = ip_set_list[index]; |
450 | 451 | ||
451 | BUG_ON(set == NULL); | 452 | BUG_ON(set == NULL); |
452 | BUG_ON(atomic_read(&set->ref) == 0); | 453 | BUG_ON(set->ref == 0); |
453 | 454 | ||
454 | /* Referenced, so it's safe */ | 455 | /* Referenced, so it's safe */ |
455 | return set->name; | 456 | return set->name; |
@@ -515,10 +516,7 @@ void | |||
515 | ip_set_nfnl_put(ip_set_id_t index) | 516 | ip_set_nfnl_put(ip_set_id_t index) |
516 | { | 517 | { |
517 | nfnl_lock(); | 518 | nfnl_lock(); |
518 | if (ip_set_list[index] != NULL) { | 519 | ip_set_put_byindex(index); |
519 | BUG_ON(atomic_read(&ip_set_list[index]->ref) == 0); | ||
520 | __ip_set_put(index); | ||
521 | } | ||
522 | nfnl_unlock(); | 520 | nfnl_unlock(); |
523 | } | 521 | } |
524 | EXPORT_SYMBOL_GPL(ip_set_nfnl_put); | 522 | EXPORT_SYMBOL_GPL(ip_set_nfnl_put); |
@@ -526,7 +524,7 @@ EXPORT_SYMBOL_GPL(ip_set_nfnl_put); | |||
526 | /* | 524 | /* |
527 | * Communication protocol with userspace over netlink. | 525 | * Communication protocol with userspace over netlink. |
528 | * | 526 | * |
529 | * We already locked by nfnl_lock. | 527 | * The commands are serialized by the nfnl mutex. |
530 | */ | 528 | */ |
531 | 529 | ||
532 | static inline bool | 530 | static inline bool |
@@ -657,7 +655,6 @@ ip_set_create(struct sock *ctnl, struct sk_buff *skb, | |||
657 | return -ENOMEM; | 655 | return -ENOMEM; |
658 | rwlock_init(&set->lock); | 656 | rwlock_init(&set->lock); |
659 | strlcpy(set->name, name, IPSET_MAXNAMELEN); | 657 | strlcpy(set->name, name, IPSET_MAXNAMELEN); |
660 | atomic_set(&set->ref, 0); | ||
661 | set->family = family; | 658 | set->family = family; |
662 | 659 | ||
663 | /* | 660 | /* |
@@ -690,8 +687,8 @@ ip_set_create(struct sock *ctnl, struct sk_buff *skb, | |||
690 | 687 | ||
691 | /* | 688 | /* |
692 | * Here, we have a valid, constructed set and we are protected | 689 | * Here, we have a valid, constructed set and we are protected |
693 | * by nfnl_lock. Find the first free index in ip_set_list and | 690 | * by the nfnl mutex. Find the first free index in ip_set_list |
694 | * check clashing. | 691 | * and check clashing. |
695 | */ | 692 | */ |
696 | if ((ret = find_free_id(set->name, &index, &clash)) != 0) { | 693 | if ((ret = find_free_id(set->name, &index, &clash)) != 0) { |
697 | /* If this is the same set and requested, ignore error */ | 694 | /* If this is the same set and requested, ignore error */ |
@@ -751,31 +748,51 @@ ip_set_destroy(struct sock *ctnl, struct sk_buff *skb, | |||
751 | const struct nlattr * const attr[]) | 748 | const struct nlattr * const attr[]) |
752 | { | 749 | { |
753 | ip_set_id_t i; | 750 | ip_set_id_t i; |
751 | int ret = 0; | ||
754 | 752 | ||
755 | if (unlikely(protocol_failed(attr))) | 753 | if (unlikely(protocol_failed(attr))) |
756 | return -IPSET_ERR_PROTOCOL; | 754 | return -IPSET_ERR_PROTOCOL; |
757 | 755 | ||
758 | /* References are protected by the nfnl mutex */ | 756 | /* Commands are serialized and references are |
757 | * protected by the ip_set_ref_lock. | ||
758 | * External systems (i.e. xt_set) must call | ||
759 | * ip_set_put|get_nfnl_* functions, that way we | ||
760 | * can safely check references here. | ||
761 | * | ||
762 | * list:set timer can only decrement the reference | ||
763 | * counter, so if it's already zero, we can proceed | ||
764 | * without holding the lock. | ||
765 | */ | ||
766 | read_lock_bh(&ip_set_ref_lock); | ||
759 | if (!attr[IPSET_ATTR_SETNAME]) { | 767 | if (!attr[IPSET_ATTR_SETNAME]) { |
760 | for (i = 0; i < ip_set_max; i++) { | 768 | for (i = 0; i < ip_set_max; i++) { |
761 | if (ip_set_list[i] != NULL && | 769 | if (ip_set_list[i] != NULL && ip_set_list[i]->ref) { |
762 | (atomic_read(&ip_set_list[i]->ref))) | 770 | ret = IPSET_ERR_BUSY; |
763 | return -IPSET_ERR_BUSY; | 771 | goto out; |
772 | } | ||
764 | } | 773 | } |
774 | read_unlock_bh(&ip_set_ref_lock); | ||
765 | for (i = 0; i < ip_set_max; i++) { | 775 | for (i = 0; i < ip_set_max; i++) { |
766 | if (ip_set_list[i] != NULL) | 776 | if (ip_set_list[i] != NULL) |
767 | ip_set_destroy_set(i); | 777 | ip_set_destroy_set(i); |
768 | } | 778 | } |
769 | } else { | 779 | } else { |
770 | i = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME])); | 780 | i = find_set_id(nla_data(attr[IPSET_ATTR_SETNAME])); |
771 | if (i == IPSET_INVALID_ID) | 781 | if (i == IPSET_INVALID_ID) { |
772 | return -ENOENT; | 782 | ret = -ENOENT; |
773 | else if (atomic_read(&ip_set_list[i]->ref)) | 783 | goto out; |
774 | return -IPSET_ERR_BUSY; | 784 | } else if (ip_set_list[i]->ref) { |
785 | ret = -IPSET_ERR_BUSY; | ||
786 | goto out; | ||
787 | } | ||
788 | read_unlock_bh(&ip_set_ref_lock); | ||
775 | 789 | ||
776 | ip_set_destroy_set(i); | 790 | ip_set_destroy_set(i); |
777 | } | 791 | } |
778 | return 0; | 792 | return 0; |
793 | out: | ||
794 | read_unlock_bh(&ip_set_ref_lock); | ||
795 | return ret; | ||
779 | } | 796 | } |
780 | 797 | ||
781 | /* Flush sets */ | 798 | /* Flush sets */ |
@@ -834,6 +851,7 @@ ip_set_rename(struct sock *ctnl, struct sk_buff *skb, | |||
834 | struct ip_set *set; | 851 | struct ip_set *set; |
835 | const char *name2; | 852 | const char *name2; |
836 | ip_set_id_t i; | 853 | ip_set_id_t i; |
854 | int ret = 0; | ||
837 | 855 | ||
838 | if (unlikely(protocol_failed(attr) || | 856 | if (unlikely(protocol_failed(attr) || |
839 | attr[IPSET_ATTR_SETNAME] == NULL || | 857 | attr[IPSET_ATTR_SETNAME] == NULL || |
@@ -843,25 +861,33 @@ ip_set_rename(struct sock *ctnl, struct sk_buff *skb, | |||
843 | set = find_set(nla_data(attr[IPSET_ATTR_SETNAME])); | 861 | set = find_set(nla_data(attr[IPSET_ATTR_SETNAME])); |
844 | if (set == NULL) | 862 | if (set == NULL) |
845 | return -ENOENT; | 863 | return -ENOENT; |
846 | if (atomic_read(&set->ref) != 0) | 864 | |
847 | return -IPSET_ERR_REFERENCED; | 865 | read_lock_bh(&ip_set_ref_lock); |
866 | if (set->ref != 0) { | ||
867 | ret = -IPSET_ERR_REFERENCED; | ||
868 | goto out; | ||
869 | } | ||
848 | 870 | ||
849 | name2 = nla_data(attr[IPSET_ATTR_SETNAME2]); | 871 | name2 = nla_data(attr[IPSET_ATTR_SETNAME2]); |
850 | for (i = 0; i < ip_set_max; i++) { | 872 | for (i = 0; i < ip_set_max; i++) { |
851 | if (ip_set_list[i] != NULL && | 873 | if (ip_set_list[i] != NULL && |
852 | STREQ(ip_set_list[i]->name, name2)) | 874 | STREQ(ip_set_list[i]->name, name2)) { |
853 | return -IPSET_ERR_EXIST_SETNAME2; | 875 | ret = -IPSET_ERR_EXIST_SETNAME2; |
876 | goto out; | ||
877 | } | ||
854 | } | 878 | } |
855 | strncpy(set->name, name2, IPSET_MAXNAMELEN); | 879 | strncpy(set->name, name2, IPSET_MAXNAMELEN); |
856 | 880 | ||
857 | return 0; | 881 | out: |
882 | read_unlock_bh(&ip_set_ref_lock); | ||
883 | return ret; | ||
858 | } | 884 | } |
859 | 885 | ||
860 | /* Swap two sets so that name/index points to the other. | 886 | /* Swap two sets so that name/index points to the other. |
861 | * References and set names are also swapped. | 887 | * References and set names are also swapped. |
862 | * | 888 | * |
863 | * We are protected by the nfnl mutex and references are | 889 | * The commands are serialized by the nfnl mutex and references are |
864 | * manipulated only by holding the mutex. The kernel interfaces | 890 | * protected by the ip_set_ref_lock. The kernel interfaces |
865 | * do not hold the mutex but the pointer settings are atomic | 891 | * do not hold the mutex but the pointer settings are atomic |
866 | * so the ip_set_list always contains valid pointers to the sets. | 892 | * so the ip_set_list always contains valid pointers to the sets. |
867 | */ | 893 | */ |
@@ -874,7 +900,6 @@ ip_set_swap(struct sock *ctnl, struct sk_buff *skb, | |||
874 | struct ip_set *from, *to; | 900 | struct ip_set *from, *to; |
875 | ip_set_id_t from_id, to_id; | 901 | ip_set_id_t from_id, to_id; |
876 | char from_name[IPSET_MAXNAMELEN]; | 902 | char from_name[IPSET_MAXNAMELEN]; |
877 | u32 from_ref; | ||
878 | 903 | ||
879 | if (unlikely(protocol_failed(attr) || | 904 | if (unlikely(protocol_failed(attr) || |
880 | attr[IPSET_ATTR_SETNAME] == NULL || | 905 | attr[IPSET_ATTR_SETNAME] == NULL || |
@@ -893,23 +918,21 @@ ip_set_swap(struct sock *ctnl, struct sk_buff *skb, | |||
893 | to = ip_set_list[to_id]; | 918 | to = ip_set_list[to_id]; |
894 | 919 | ||
895 | /* Features must not change. | 920 | /* Features must not change. |
896 | * Not an artifical restriction anymore, as we must prevent | 921 | * Not an artificial restriction anymore, as we must prevent |
897 | * possible loops created by swapping in setlist type of sets. */ | 922 | * possible loops created by swapping in setlist type of sets. */ |
898 | if (!(from->type->features == to->type->features && | 923 | if (!(from->type->features == to->type->features && |
899 | from->type->family == to->type->family)) | 924 | from->type->family == to->type->family)) |
900 | return -IPSET_ERR_TYPE_MISMATCH; | 925 | return -IPSET_ERR_TYPE_MISMATCH; |
901 | 926 | ||
902 | /* No magic here: ref munging protected by the nfnl_lock */ | ||
903 | strncpy(from_name, from->name, IPSET_MAXNAMELEN); | 927 | strncpy(from_name, from->name, IPSET_MAXNAMELEN); |
904 | from_ref = atomic_read(&from->ref); | ||
905 | |||
906 | strncpy(from->name, to->name, IPSET_MAXNAMELEN); | 928 | strncpy(from->name, to->name, IPSET_MAXNAMELEN); |
907 | atomic_set(&from->ref, atomic_read(&to->ref)); | ||
908 | strncpy(to->name, from_name, IPSET_MAXNAMELEN); | 929 | strncpy(to->name, from_name, IPSET_MAXNAMELEN); |
909 | atomic_set(&to->ref, from_ref); | ||
910 | 930 | ||
931 | write_lock_bh(&ip_set_ref_lock); | ||
932 | swap(from->ref, to->ref); | ||
911 | ip_set_list[from_id] = to; | 933 | ip_set_list[from_id] = to; |
912 | ip_set_list[to_id] = from; | 934 | ip_set_list[to_id] = from; |
935 | write_unlock_bh(&ip_set_ref_lock); | ||
913 | 936 | ||
914 | return 0; | 937 | return 0; |
915 | } | 938 | } |
@@ -926,7 +949,7 @@ ip_set_dump_done(struct netlink_callback *cb) | |||
926 | { | 949 | { |
927 | if (cb->args[2]) { | 950 | if (cb->args[2]) { |
928 | pr_debug("release set %s\n", ip_set_list[cb->args[1]]->name); | 951 | pr_debug("release set %s\n", ip_set_list[cb->args[1]]->name); |
929 | __ip_set_put((ip_set_id_t) cb->args[1]); | 952 | ip_set_put_byindex((ip_set_id_t) cb->args[1]); |
930 | } | 953 | } |
931 | return 0; | 954 | return 0; |
932 | } | 955 | } |
@@ -999,8 +1022,9 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb) | |||
999 | if (cb->args[1] >= ip_set_max) | 1022 | if (cb->args[1] >= ip_set_max) |
1000 | goto out; | 1023 | goto out; |
1001 | 1024 | ||
1002 | pr_debug("args[0]: %ld args[1]: %ld\n", cb->args[0], cb->args[1]); | ||
1003 | max = cb->args[0] == DUMP_ONE ? cb->args[1] + 1 : ip_set_max; | 1025 | max = cb->args[0] == DUMP_ONE ? cb->args[1] + 1 : ip_set_max; |
1026 | dump_last: | ||
1027 | pr_debug("args[0]: %ld args[1]: %ld\n", cb->args[0], cb->args[1]); | ||
1004 | for (; cb->args[1] < max; cb->args[1]++) { | 1028 | for (; cb->args[1] < max; cb->args[1]++) { |
1005 | index = (ip_set_id_t) cb->args[1]; | 1029 | index = (ip_set_id_t) cb->args[1]; |
1006 | set = ip_set_list[index]; | 1030 | set = ip_set_list[index]; |
@@ -1015,8 +1039,8 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb) | |||
1015 | * so that lists (unions of sets) are dumped last. | 1039 | * so that lists (unions of sets) are dumped last. |
1016 | */ | 1040 | */ |
1017 | if (cb->args[0] != DUMP_ONE && | 1041 | if (cb->args[0] != DUMP_ONE && |
1018 | !((cb->args[0] == DUMP_ALL) ^ | 1042 | ((cb->args[0] == DUMP_ALL) == |
1019 | (set->type->features & IPSET_DUMP_LAST))) | 1043 | !!(set->type->features & IPSET_DUMP_LAST))) |
1020 | continue; | 1044 | continue; |
1021 | pr_debug("List set: %s\n", set->name); | 1045 | pr_debug("List set: %s\n", set->name); |
1022 | if (!cb->args[2]) { | 1046 | if (!cb->args[2]) { |
@@ -1060,6 +1084,12 @@ ip_set_dump_start(struct sk_buff *skb, struct netlink_callback *cb) | |||
1060 | goto release_refcount; | 1084 | goto release_refcount; |
1061 | } | 1085 | } |
1062 | } | 1086 | } |
1087 | /* If we dump all sets, continue with dumping last ones */ | ||
1088 | if (cb->args[0] == DUMP_ALL) { | ||
1089 | cb->args[0] = DUMP_LAST; | ||
1090 | cb->args[1] = 0; | ||
1091 | goto dump_last; | ||
1092 | } | ||
1063 | goto out; | 1093 | goto out; |
1064 | 1094 | ||
1065 | nla_put_failure: | 1095 | nla_put_failure: |
@@ -1068,13 +1098,8 @@ release_refcount: | |||
1068 | /* If there was an error or set is done, release set */ | 1098 | /* If there was an error or set is done, release set */ |
1069 | if (ret || !cb->args[2]) { | 1099 | if (ret || !cb->args[2]) { |
1070 | pr_debug("release set %s\n", ip_set_list[index]->name); | 1100 | pr_debug("release set %s\n", ip_set_list[index]->name); |
1071 | __ip_set_put(index); | 1101 | ip_set_put_byindex(index); |
1072 | } | 1102 | } |
1073 | |||
1074 | /* If we dump all sets, continue with dumping last ones */ | ||
1075 | if (cb->args[0] == DUMP_ALL && cb->args[1] >= max && !cb->args[2]) | ||
1076 | cb->args[0] = DUMP_LAST; | ||
1077 | |||
1078 | out: | 1103 | out: |
1079 | if (nlh) { | 1104 | if (nlh) { |
1080 | nlmsg_end(skb, nlh); | 1105 | nlmsg_end(skb, nlh); |
diff --git a/net/netfilter/ipset/ip_set_getport.c b/net/netfilter/ipset/ip_set_getport.c index 8d5227212686..757143b2240a 100644 --- a/net/netfilter/ipset/ip_set_getport.c +++ b/net/netfilter/ipset/ip_set_getport.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/skbuff.h> | 11 | #include <linux/skbuff.h> |
12 | #include <linux/icmp.h> | 12 | #include <linux/icmp.h> |
13 | #include <linux/icmpv6.h> | 13 | #include <linux/icmpv6.h> |
14 | #include <linux/sctp.h> | ||
14 | #include <linux/netfilter_ipv6/ip6_tables.h> | 15 | #include <linux/netfilter_ipv6/ip6_tables.h> |
15 | #include <net/ip.h> | 16 | #include <net/ip.h> |
16 | #include <net/ipv6.h> | 17 | #include <net/ipv6.h> |
@@ -35,7 +36,20 @@ get_port(const struct sk_buff *skb, int protocol, unsigned int protooff, | |||
35 | *port = src ? th->source : th->dest; | 36 | *port = src ? th->source : th->dest; |
36 | break; | 37 | break; |
37 | } | 38 | } |
38 | case IPPROTO_UDP: { | 39 | case IPPROTO_SCTP: { |
40 | sctp_sctphdr_t _sh; | ||
41 | const sctp_sctphdr_t *sh; | ||
42 | |||
43 | sh = skb_header_pointer(skb, protooff, sizeof(_sh), &_sh); | ||
44 | if (sh == NULL) | ||
45 | /* No choice either */ | ||
46 | return false; | ||
47 | |||
48 | *port = src ? sh->source : sh->dest; | ||
49 | break; | ||
50 | } | ||
51 | case IPPROTO_UDP: | ||
52 | case IPPROTO_UDPLITE: { | ||
39 | struct udphdr _udph; | 53 | struct udphdr _udph; |
40 | const struct udphdr *uh; | 54 | const struct udphdr *uh; |
41 | 55 | ||
diff --git a/net/netfilter/ipset/ip_set_hash_ipport.c b/net/netfilter/ipset/ip_set_hash_ipport.c index b9214145d357..14281b6b8074 100644 --- a/net/netfilter/ipset/ip_set_hash_ipport.c +++ b/net/netfilter/ipset/ip_set_hash_ipport.c | |||
@@ -491,7 +491,7 @@ static struct ip_set_type hash_ipport_type __read_mostly = { | |||
491 | .features = IPSET_TYPE_IP | IPSET_TYPE_PORT, | 491 | .features = IPSET_TYPE_IP | IPSET_TYPE_PORT, |
492 | .dimension = IPSET_DIM_TWO, | 492 | .dimension = IPSET_DIM_TWO, |
493 | .family = AF_UNSPEC, | 493 | .family = AF_UNSPEC, |
494 | .revision = 0, | 494 | .revision = 1, |
495 | .create = hash_ipport_create, | 495 | .create = hash_ipport_create, |
496 | .create_policy = { | 496 | .create_policy = { |
497 | [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, | 497 | [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, |
diff --git a/net/netfilter/ipset/ip_set_hash_ipportip.c b/net/netfilter/ipset/ip_set_hash_ipportip.c index 4642872df6e1..401c8a2531db 100644 --- a/net/netfilter/ipset/ip_set_hash_ipportip.c +++ b/net/netfilter/ipset/ip_set_hash_ipportip.c | |||
@@ -509,7 +509,7 @@ static struct ip_set_type hash_ipportip_type __read_mostly = { | |||
509 | .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2, | 509 | .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2, |
510 | .dimension = IPSET_DIM_THREE, | 510 | .dimension = IPSET_DIM_THREE, |
511 | .family = AF_UNSPEC, | 511 | .family = AF_UNSPEC, |
512 | .revision = 0, | 512 | .revision = 1, |
513 | .create = hash_ipportip_create, | 513 | .create = hash_ipportip_create, |
514 | .create_policy = { | 514 | .create_policy = { |
515 | [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, | 515 | [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, |
diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c index 2cb84a54b7ad..4743e5402522 100644 --- a/net/netfilter/ipset/ip_set_hash_ipportnet.c +++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c | |||
@@ -574,7 +574,7 @@ static struct ip_set_type hash_ipportnet_type __read_mostly = { | |||
574 | .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2, | 574 | .features = IPSET_TYPE_IP | IPSET_TYPE_PORT | IPSET_TYPE_IP2, |
575 | .dimension = IPSET_DIM_THREE, | 575 | .dimension = IPSET_DIM_THREE, |
576 | .family = AF_UNSPEC, | 576 | .family = AF_UNSPEC, |
577 | .revision = 0, | 577 | .revision = 1, |
578 | .create = hash_ipportnet_create, | 578 | .create = hash_ipportnet_create, |
579 | .create_policy = { | 579 | .create_policy = { |
580 | [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, | 580 | [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, |
diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c index 8598676f2a05..d2a40362dd3a 100644 --- a/net/netfilter/ipset/ip_set_hash_netport.c +++ b/net/netfilter/ipset/ip_set_hash_netport.c | |||
@@ -526,7 +526,7 @@ static struct ip_set_type hash_netport_type __read_mostly = { | |||
526 | .features = IPSET_TYPE_IP | IPSET_TYPE_PORT, | 526 | .features = IPSET_TYPE_IP | IPSET_TYPE_PORT, |
527 | .dimension = IPSET_DIM_TWO, | 527 | .dimension = IPSET_DIM_TWO, |
528 | .family = AF_UNSPEC, | 528 | .family = AF_UNSPEC, |
529 | .revision = 0, | 529 | .revision = 1, |
530 | .create = hash_netport_create, | 530 | .create = hash_netport_create, |
531 | .create_policy = { | 531 | .create_policy = { |
532 | [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, | 532 | [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, |
diff --git a/net/netfilter/ipset/ip_set_list_set.c b/net/netfilter/ipset/ip_set_list_set.c index a47c32982f06..e9159e99fc4b 100644 --- a/net/netfilter/ipset/ip_set_list_set.c +++ b/net/netfilter/ipset/ip_set_list_set.c | |||
@@ -43,14 +43,19 @@ struct list_set { | |||
43 | static inline struct set_elem * | 43 | static inline struct set_elem * |
44 | list_set_elem(const struct list_set *map, u32 id) | 44 | list_set_elem(const struct list_set *map, u32 id) |
45 | { | 45 | { |
46 | return (struct set_elem *)((char *)map->members + id * map->dsize); | 46 | return (struct set_elem *)((void *)map->members + id * map->dsize); |
47 | } | ||
48 | |||
49 | static inline struct set_telem * | ||
50 | list_set_telem(const struct list_set *map, u32 id) | ||
51 | { | ||
52 | return (struct set_telem *)((void *)map->members + id * map->dsize); | ||
47 | } | 53 | } |
48 | 54 | ||
49 | static inline bool | 55 | static inline bool |
50 | list_set_timeout(const struct list_set *map, u32 id) | 56 | list_set_timeout(const struct list_set *map, u32 id) |
51 | { | 57 | { |
52 | const struct set_telem *elem = | 58 | const struct set_telem *elem = list_set_telem(map, id); |
53 | (const struct set_telem *) list_set_elem(map, id); | ||
54 | 59 | ||
55 | return ip_set_timeout_test(elem->timeout); | 60 | return ip_set_timeout_test(elem->timeout); |
56 | } | 61 | } |
@@ -58,19 +63,11 @@ list_set_timeout(const struct list_set *map, u32 id) | |||
58 | static inline bool | 63 | static inline bool |
59 | list_set_expired(const struct list_set *map, u32 id) | 64 | list_set_expired(const struct list_set *map, u32 id) |
60 | { | 65 | { |
61 | const struct set_telem *elem = | 66 | const struct set_telem *elem = list_set_telem(map, id); |
62 | (const struct set_telem *) list_set_elem(map, id); | ||
63 | 67 | ||
64 | return ip_set_timeout_expired(elem->timeout); | 68 | return ip_set_timeout_expired(elem->timeout); |
65 | } | 69 | } |
66 | 70 | ||
67 | static inline int | ||
68 | list_set_exist(const struct set_telem *elem) | ||
69 | { | ||
70 | return elem->id != IPSET_INVALID_ID && | ||
71 | !ip_set_timeout_expired(elem->timeout); | ||
72 | } | ||
73 | |||
74 | /* Set list without and with timeout */ | 71 | /* Set list without and with timeout */ |
75 | 72 | ||
76 | static int | 73 | static int |
@@ -146,11 +143,11 @@ list_elem_tadd(struct list_set *map, u32 i, ip_set_id_t id, | |||
146 | struct set_telem *e; | 143 | struct set_telem *e; |
147 | 144 | ||
148 | for (; i < map->size; i++) { | 145 | for (; i < map->size; i++) { |
149 | e = (struct set_telem *)list_set_elem(map, i); | 146 | e = list_set_telem(map, i); |
150 | swap(e->id, id); | 147 | swap(e->id, id); |
148 | swap(e->timeout, timeout); | ||
151 | if (e->id == IPSET_INVALID_ID) | 149 | if (e->id == IPSET_INVALID_ID) |
152 | break; | 150 | break; |
153 | swap(e->timeout, timeout); | ||
154 | } | 151 | } |
155 | } | 152 | } |
156 | 153 | ||
@@ -164,7 +161,7 @@ list_set_add(struct list_set *map, u32 i, ip_set_id_t id, | |||
164 | /* Last element replaced: e.g. add new,before,last */ | 161 | /* Last element replaced: e.g. add new,before,last */ |
165 | ip_set_put_byindex(e->id); | 162 | ip_set_put_byindex(e->id); |
166 | if (with_timeout(map->timeout)) | 163 | if (with_timeout(map->timeout)) |
167 | list_elem_tadd(map, i, id, timeout); | 164 | list_elem_tadd(map, i, id, ip_set_timeout_set(timeout)); |
168 | else | 165 | else |
169 | list_elem_add(map, i, id); | 166 | list_elem_add(map, i, id); |
170 | 167 | ||
@@ -172,11 +169,11 @@ list_set_add(struct list_set *map, u32 i, ip_set_id_t id, | |||
172 | } | 169 | } |
173 | 170 | ||
174 | static int | 171 | static int |
175 | list_set_del(struct list_set *map, ip_set_id_t id, u32 i) | 172 | list_set_del(struct list_set *map, u32 i) |
176 | { | 173 | { |
177 | struct set_elem *a = list_set_elem(map, i), *b; | 174 | struct set_elem *a = list_set_elem(map, i), *b; |
178 | 175 | ||
179 | ip_set_put_byindex(id); | 176 | ip_set_put_byindex(a->id); |
180 | 177 | ||
181 | for (; i < map->size - 1; i++) { | 178 | for (; i < map->size - 1; i++) { |
182 | b = list_set_elem(map, i + 1); | 179 | b = list_set_elem(map, i + 1); |
@@ -308,11 +305,11 @@ list_set_uadt(struct ip_set *set, struct nlattr *tb[], | |||
308 | (before == 0 || | 305 | (before == 0 || |
309 | (before > 0 && | 306 | (before > 0 && |
310 | next_id_eq(map, i, refid)))) | 307 | next_id_eq(map, i, refid)))) |
311 | ret = list_set_del(map, id, i); | 308 | ret = list_set_del(map, i); |
312 | else if (before < 0 && | 309 | else if (before < 0 && |
313 | elem->id == refid && | 310 | elem->id == refid && |
314 | next_id_eq(map, i, id)) | 311 | next_id_eq(map, i, id)) |
315 | ret = list_set_del(map, id, i + 1); | 312 | ret = list_set_del(map, i + 1); |
316 | } | 313 | } |
317 | break; | 314 | break; |
318 | default: | 315 | default: |
@@ -369,8 +366,7 @@ list_set_head(struct ip_set *set, struct sk_buff *skb) | |||
369 | NLA_PUT_NET32(skb, IPSET_ATTR_SIZE, htonl(map->size)); | 366 | NLA_PUT_NET32(skb, IPSET_ATTR_SIZE, htonl(map->size)); |
370 | if (with_timeout(map->timeout)) | 367 | if (with_timeout(map->timeout)) |
371 | NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout)); | 368 | NLA_PUT_NET32(skb, IPSET_ATTR_TIMEOUT, htonl(map->timeout)); |
372 | NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, | 369 | NLA_PUT_NET32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)); |
373 | htonl(atomic_read(&set->ref) - 1)); | ||
374 | NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, | 370 | NLA_PUT_NET32(skb, IPSET_ATTR_MEMSIZE, |
375 | htonl(sizeof(*map) + map->size * map->dsize)); | 371 | htonl(sizeof(*map) + map->size * map->dsize)); |
376 | ipset_nest_end(skb, nested); | 372 | ipset_nest_end(skb, nested); |
@@ -461,16 +457,13 @@ list_set_gc(unsigned long ul_set) | |||
461 | struct set_telem *e; | 457 | struct set_telem *e; |
462 | u32 i; | 458 | u32 i; |
463 | 459 | ||
464 | /* We run parallel with other readers (test element) | 460 | write_lock_bh(&set->lock); |
465 | * but adding/deleting new entries is locked out */ | 461 | for (i = 0; i < map->size; i++) { |
466 | read_lock_bh(&set->lock); | 462 | e = list_set_telem(map, i); |
467 | for (i = map->size - 1; i >= 0; i--) { | 463 | if (e->id != IPSET_INVALID_ID && list_set_expired(map, i)) |
468 | e = (struct set_telem *) list_set_elem(map, i); | 464 | list_set_del(map, i); |
469 | if (e->id != IPSET_INVALID_ID && | ||
470 | list_set_expired(map, i)) | ||
471 | list_set_del(map, e->id, i); | ||
472 | } | 465 | } |
473 | read_unlock_bh(&set->lock); | 466 | write_unlock_bh(&set->lock); |
474 | 467 | ||
475 | map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; | 468 | map->gc.expires = jiffies + IPSET_GC_PERIOD(map->timeout) * HZ; |
476 | add_timer(&map->gc); | 469 | add_timer(&map->gc); |
diff --git a/net/netfilter/ipvs/ip_vs_app.c b/net/netfilter/ipvs/ip_vs_app.c index 2dc6de13ac18..51f3af7c4743 100644 --- a/net/netfilter/ipvs/ip_vs_app.c +++ b/net/netfilter/ipvs/ip_vs_app.c | |||
@@ -576,7 +576,7 @@ static const struct file_operations ip_vs_app_fops = { | |||
576 | }; | 576 | }; |
577 | #endif | 577 | #endif |
578 | 578 | ||
579 | static int __net_init __ip_vs_app_init(struct net *net) | 579 | int __net_init __ip_vs_app_init(struct net *net) |
580 | { | 580 | { |
581 | struct netns_ipvs *ipvs = net_ipvs(net); | 581 | struct netns_ipvs *ipvs = net_ipvs(net); |
582 | 582 | ||
@@ -585,26 +585,17 @@ static int __net_init __ip_vs_app_init(struct net *net) | |||
585 | return 0; | 585 | return 0; |
586 | } | 586 | } |
587 | 587 | ||
588 | static void __net_exit __ip_vs_app_cleanup(struct net *net) | 588 | void __net_exit __ip_vs_app_cleanup(struct net *net) |
589 | { | 589 | { |
590 | proc_net_remove(net, "ip_vs_app"); | 590 | proc_net_remove(net, "ip_vs_app"); |
591 | } | 591 | } |
592 | 592 | ||
593 | static struct pernet_operations ip_vs_app_ops = { | ||
594 | .init = __ip_vs_app_init, | ||
595 | .exit = __ip_vs_app_cleanup, | ||
596 | }; | ||
597 | |||
598 | int __init ip_vs_app_init(void) | 593 | int __init ip_vs_app_init(void) |
599 | { | 594 | { |
600 | int rv; | 595 | return 0; |
601 | |||
602 | rv = register_pernet_subsys(&ip_vs_app_ops); | ||
603 | return rv; | ||
604 | } | 596 | } |
605 | 597 | ||
606 | 598 | ||
607 | void ip_vs_app_cleanup(void) | 599 | void ip_vs_app_cleanup(void) |
608 | { | 600 | { |
609 | unregister_pernet_subsys(&ip_vs_app_ops); | ||
610 | } | 601 | } |
diff --git a/net/netfilter/ipvs/ip_vs_conn.c b/net/netfilter/ipvs/ip_vs_conn.c index f289306cbf12..d3fd91bbba49 100644 --- a/net/netfilter/ipvs/ip_vs_conn.c +++ b/net/netfilter/ipvs/ip_vs_conn.c | |||
@@ -595,7 +595,7 @@ ip_vs_bind_dest(struct ip_vs_conn *cp, struct ip_vs_dest *dest) | |||
595 | atomic_inc(&dest->inactconns); | 595 | atomic_inc(&dest->inactconns); |
596 | } else { | 596 | } else { |
597 | /* It is a persistent connection/template, so increase | 597 | /* It is a persistent connection/template, so increase |
598 | the peristent connection counter */ | 598 | the persistent connection counter */ |
599 | atomic_inc(&dest->persistconns); | 599 | atomic_inc(&dest->persistconns); |
600 | } | 600 | } |
601 | 601 | ||
@@ -657,7 +657,7 @@ static inline void ip_vs_unbind_dest(struct ip_vs_conn *cp) | |||
657 | } | 657 | } |
658 | } else { | 658 | } else { |
659 | /* It is a persistent connection/template, so decrease | 659 | /* It is a persistent connection/template, so decrease |
660 | the peristent connection counter */ | 660 | the persistent connection counter */ |
661 | atomic_dec(&dest->persistconns); | 661 | atomic_dec(&dest->persistconns); |
662 | } | 662 | } |
663 | 663 | ||
@@ -1258,22 +1258,17 @@ int __net_init __ip_vs_conn_init(struct net *net) | |||
1258 | return 0; | 1258 | return 0; |
1259 | } | 1259 | } |
1260 | 1260 | ||
1261 | static void __net_exit __ip_vs_conn_cleanup(struct net *net) | 1261 | void __net_exit __ip_vs_conn_cleanup(struct net *net) |
1262 | { | 1262 | { |
1263 | /* flush all the connection entries first */ | 1263 | /* flush all the connection entries first */ |
1264 | ip_vs_conn_flush(net); | 1264 | ip_vs_conn_flush(net); |
1265 | proc_net_remove(net, "ip_vs_conn"); | 1265 | proc_net_remove(net, "ip_vs_conn"); |
1266 | proc_net_remove(net, "ip_vs_conn_sync"); | 1266 | proc_net_remove(net, "ip_vs_conn_sync"); |
1267 | } | 1267 | } |
1268 | static struct pernet_operations ipvs_conn_ops = { | ||
1269 | .init = __ip_vs_conn_init, | ||
1270 | .exit = __ip_vs_conn_cleanup, | ||
1271 | }; | ||
1272 | 1268 | ||
1273 | int __init ip_vs_conn_init(void) | 1269 | int __init ip_vs_conn_init(void) |
1274 | { | 1270 | { |
1275 | int idx; | 1271 | int idx; |
1276 | int retc; | ||
1277 | 1272 | ||
1278 | /* Compute size and mask */ | 1273 | /* Compute size and mask */ |
1279 | ip_vs_conn_tab_size = 1 << ip_vs_conn_tab_bits; | 1274 | ip_vs_conn_tab_size = 1 << ip_vs_conn_tab_bits; |
@@ -1309,17 +1304,14 @@ int __init ip_vs_conn_init(void) | |||
1309 | rwlock_init(&__ip_vs_conntbl_lock_array[idx].l); | 1304 | rwlock_init(&__ip_vs_conntbl_lock_array[idx].l); |
1310 | } | 1305 | } |
1311 | 1306 | ||
1312 | retc = register_pernet_subsys(&ipvs_conn_ops); | ||
1313 | |||
1314 | /* calculate the random value for connection hash */ | 1307 | /* calculate the random value for connection hash */ |
1315 | get_random_bytes(&ip_vs_conn_rnd, sizeof(ip_vs_conn_rnd)); | 1308 | get_random_bytes(&ip_vs_conn_rnd, sizeof(ip_vs_conn_rnd)); |
1316 | 1309 | ||
1317 | return retc; | 1310 | return 0; |
1318 | } | 1311 | } |
1319 | 1312 | ||
1320 | void ip_vs_conn_cleanup(void) | 1313 | void ip_vs_conn_cleanup(void) |
1321 | { | 1314 | { |
1322 | unregister_pernet_subsys(&ipvs_conn_ops); | ||
1323 | /* Release the empty cache */ | 1315 | /* Release the empty cache */ |
1324 | kmem_cache_destroy(ip_vs_conn_cachep); | 1316 | kmem_cache_destroy(ip_vs_conn_cachep); |
1325 | vfree(ip_vs_conn_tab); | 1317 | vfree(ip_vs_conn_tab); |
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index 07accf6b2401..bfa808f4da13 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c | |||
@@ -1113,6 +1113,9 @@ ip_vs_out(unsigned int hooknum, struct sk_buff *skb, int af) | |||
1113 | return NF_ACCEPT; | 1113 | return NF_ACCEPT; |
1114 | 1114 | ||
1115 | net = skb_net(skb); | 1115 | net = skb_net(skb); |
1116 | if (!net_ipvs(net)->enable) | ||
1117 | return NF_ACCEPT; | ||
1118 | |||
1116 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); | 1119 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); |
1117 | #ifdef CONFIG_IP_VS_IPV6 | 1120 | #ifdef CONFIG_IP_VS_IPV6 |
1118 | if (af == AF_INET6) { | 1121 | if (af == AF_INET6) { |
@@ -1343,6 +1346,7 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) | |||
1343 | return NF_ACCEPT; /* The packet looks wrong, ignore */ | 1346 | return NF_ACCEPT; /* The packet looks wrong, ignore */ |
1344 | 1347 | ||
1345 | net = skb_net(skb); | 1348 | net = skb_net(skb); |
1349 | |||
1346 | pd = ip_vs_proto_data_get(net, cih->protocol); | 1350 | pd = ip_vs_proto_data_get(net, cih->protocol); |
1347 | if (!pd) | 1351 | if (!pd) |
1348 | return NF_ACCEPT; | 1352 | return NF_ACCEPT; |
@@ -1378,15 +1382,7 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) | |||
1378 | ip_vs_in_stats(cp, skb); | 1382 | ip_vs_in_stats(cp, skb); |
1379 | if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol) | 1383 | if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol) |
1380 | offset += 2 * sizeof(__u16); | 1384 | offset += 2 * sizeof(__u16); |
1381 | verdict = ip_vs_icmp_xmit(skb, cp, pp, offset); | 1385 | verdict = ip_vs_icmp_xmit(skb, cp, pp, offset, hooknum); |
1382 | /* LOCALNODE from FORWARD hook is not supported */ | ||
1383 | if (verdict == NF_ACCEPT && hooknum == NF_INET_FORWARD && | ||
1384 | skb_rtable(skb)->rt_flags & RTCF_LOCAL) { | ||
1385 | IP_VS_DBG(1, "%s(): " | ||
1386 | "local delivery to %pI4 but in FORWARD\n", | ||
1387 | __func__, &skb_rtable(skb)->rt_dst); | ||
1388 | verdict = NF_DROP; | ||
1389 | } | ||
1390 | 1386 | ||
1391 | out: | 1387 | out: |
1392 | __ip_vs_conn_put(cp); | 1388 | __ip_vs_conn_put(cp); |
@@ -1408,7 +1404,6 @@ ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum) | |||
1408 | struct ip_vs_protocol *pp; | 1404 | struct ip_vs_protocol *pp; |
1409 | struct ip_vs_proto_data *pd; | 1405 | struct ip_vs_proto_data *pd; |
1410 | unsigned int offset, verdict; | 1406 | unsigned int offset, verdict; |
1411 | struct rt6_info *rt; | ||
1412 | 1407 | ||
1413 | *related = 1; | 1408 | *related = 1; |
1414 | 1409 | ||
@@ -1470,23 +1465,12 @@ ip_vs_in_icmp_v6(struct sk_buff *skb, int *related, unsigned int hooknum) | |||
1470 | if (!cp) | 1465 | if (!cp) |
1471 | return NF_ACCEPT; | 1466 | return NF_ACCEPT; |
1472 | 1467 | ||
1473 | verdict = NF_DROP; | ||
1474 | |||
1475 | /* do the statistics and put it back */ | 1468 | /* do the statistics and put it back */ |
1476 | ip_vs_in_stats(cp, skb); | 1469 | ip_vs_in_stats(cp, skb); |
1477 | if (IPPROTO_TCP == cih->nexthdr || IPPROTO_UDP == cih->nexthdr || | 1470 | if (IPPROTO_TCP == cih->nexthdr || IPPROTO_UDP == cih->nexthdr || |
1478 | IPPROTO_SCTP == cih->nexthdr) | 1471 | IPPROTO_SCTP == cih->nexthdr) |
1479 | offset += 2 * sizeof(__u16); | 1472 | offset += 2 * sizeof(__u16); |
1480 | verdict = ip_vs_icmp_xmit_v6(skb, cp, pp, offset); | 1473 | verdict = ip_vs_icmp_xmit_v6(skb, cp, pp, offset, hooknum); |
1481 | /* LOCALNODE from FORWARD hook is not supported */ | ||
1482 | if (verdict == NF_ACCEPT && hooknum == NF_INET_FORWARD && | ||
1483 | (rt = (struct rt6_info *) skb_dst(skb)) && | ||
1484 | rt->rt6i_dev && rt->rt6i_dev->flags & IFF_LOOPBACK) { | ||
1485 | IP_VS_DBG(1, "%s(): " | ||
1486 | "local delivery to %pI6 but in FORWARD\n", | ||
1487 | __func__, &rt->rt6i_dst); | ||
1488 | verdict = NF_DROP; | ||
1489 | } | ||
1490 | 1474 | ||
1491 | __ip_vs_conn_put(cp); | 1475 | __ip_vs_conn_put(cp); |
1492 | 1476 | ||
@@ -1529,6 +1513,11 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) | |||
1529 | IP_VS_DBG_ADDR(af, &iph.daddr), hooknum); | 1513 | IP_VS_DBG_ADDR(af, &iph.daddr), hooknum); |
1530 | return NF_ACCEPT; | 1514 | return NF_ACCEPT; |
1531 | } | 1515 | } |
1516 | /* ipvs enabled in this netns ? */ | ||
1517 | net = skb_net(skb); | ||
1518 | if (!net_ipvs(net)->enable) | ||
1519 | return NF_ACCEPT; | ||
1520 | |||
1532 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); | 1521 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); |
1533 | 1522 | ||
1534 | /* Bad... Do not break raw sockets */ | 1523 | /* Bad... Do not break raw sockets */ |
@@ -1562,7 +1551,6 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) | |||
1562 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); | 1551 | ip_vs_fill_iphdr(af, skb_network_header(skb), &iph); |
1563 | } | 1552 | } |
1564 | 1553 | ||
1565 | net = skb_net(skb); | ||
1566 | /* Protocol supported? */ | 1554 | /* Protocol supported? */ |
1567 | pd = ip_vs_proto_data_get(net, iph.protocol); | 1555 | pd = ip_vs_proto_data_get(net, iph.protocol); |
1568 | if (unlikely(!pd)) | 1556 | if (unlikely(!pd)) |
@@ -1588,7 +1576,6 @@ ip_vs_in(unsigned int hooknum, struct sk_buff *skb, int af) | |||
1588 | } | 1576 | } |
1589 | 1577 | ||
1590 | IP_VS_DBG_PKT(11, af, pp, skb, 0, "Incoming packet"); | 1578 | IP_VS_DBG_PKT(11, af, pp, skb, 0, "Incoming packet"); |
1591 | net = skb_net(skb); | ||
1592 | ipvs = net_ipvs(net); | 1579 | ipvs = net_ipvs(net); |
1593 | /* Check the server status */ | 1580 | /* Check the server status */ |
1594 | if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) { | 1581 | if (cp->dest && !(cp->dest->flags & IP_VS_DEST_F_AVAILABLE)) { |
@@ -1743,10 +1730,16 @@ ip_vs_forward_icmp(unsigned int hooknum, struct sk_buff *skb, | |||
1743 | int (*okfn)(struct sk_buff *)) | 1730 | int (*okfn)(struct sk_buff *)) |
1744 | { | 1731 | { |
1745 | int r; | 1732 | int r; |
1733 | struct net *net; | ||
1746 | 1734 | ||
1747 | if (ip_hdr(skb)->protocol != IPPROTO_ICMP) | 1735 | if (ip_hdr(skb)->protocol != IPPROTO_ICMP) |
1748 | return NF_ACCEPT; | 1736 | return NF_ACCEPT; |
1749 | 1737 | ||
1738 | /* ipvs enabled in this netns ? */ | ||
1739 | net = skb_net(skb); | ||
1740 | if (!net_ipvs(net)->enable) | ||
1741 | return NF_ACCEPT; | ||
1742 | |||
1750 | return ip_vs_in_icmp(skb, &r, hooknum); | 1743 | return ip_vs_in_icmp(skb, &r, hooknum); |
1751 | } | 1744 | } |
1752 | 1745 | ||
@@ -1757,10 +1750,16 @@ ip_vs_forward_icmp_v6(unsigned int hooknum, struct sk_buff *skb, | |||
1757 | int (*okfn)(struct sk_buff *)) | 1750 | int (*okfn)(struct sk_buff *)) |
1758 | { | 1751 | { |
1759 | int r; | 1752 | int r; |
1753 | struct net *net; | ||
1760 | 1754 | ||
1761 | if (ipv6_hdr(skb)->nexthdr != IPPROTO_ICMPV6) | 1755 | if (ipv6_hdr(skb)->nexthdr != IPPROTO_ICMPV6) |
1762 | return NF_ACCEPT; | 1756 | return NF_ACCEPT; |
1763 | 1757 | ||
1758 | /* ipvs enabled in this netns ? */ | ||
1759 | net = skb_net(skb); | ||
1760 | if (!net_ipvs(net)->enable) | ||
1761 | return NF_ACCEPT; | ||
1762 | |||
1764 | return ip_vs_in_icmp_v6(skb, &r, hooknum); | 1763 | return ip_vs_in_icmp_v6(skb, &r, hooknum); |
1765 | } | 1764 | } |
1766 | #endif | 1765 | #endif |
@@ -1884,19 +1883,70 @@ static int __net_init __ip_vs_init(struct net *net) | |||
1884 | pr_err("%s(): no memory.\n", __func__); | 1883 | pr_err("%s(): no memory.\n", __func__); |
1885 | return -ENOMEM; | 1884 | return -ENOMEM; |
1886 | } | 1885 | } |
1886 | /* Hold the beast until a service is registerd */ | ||
1887 | ipvs->enable = 0; | ||
1887 | ipvs->net = net; | 1888 | ipvs->net = net; |
1888 | /* Counters used for creating unique names */ | 1889 | /* Counters used for creating unique names */ |
1889 | ipvs->gen = atomic_read(&ipvs_netns_cnt); | 1890 | ipvs->gen = atomic_read(&ipvs_netns_cnt); |
1890 | atomic_inc(&ipvs_netns_cnt); | 1891 | atomic_inc(&ipvs_netns_cnt); |
1891 | net->ipvs = ipvs; | 1892 | net->ipvs = ipvs; |
1893 | |||
1894 | if (__ip_vs_estimator_init(net) < 0) | ||
1895 | goto estimator_fail; | ||
1896 | |||
1897 | if (__ip_vs_control_init(net) < 0) | ||
1898 | goto control_fail; | ||
1899 | |||
1900 | if (__ip_vs_protocol_init(net) < 0) | ||
1901 | goto protocol_fail; | ||
1902 | |||
1903 | if (__ip_vs_app_init(net) < 0) | ||
1904 | goto app_fail; | ||
1905 | |||
1906 | if (__ip_vs_conn_init(net) < 0) | ||
1907 | goto conn_fail; | ||
1908 | |||
1909 | if (__ip_vs_sync_init(net) < 0) | ||
1910 | goto sync_fail; | ||
1911 | |||
1892 | printk(KERN_INFO "IPVS: Creating netns size=%zu id=%d\n", | 1912 | printk(KERN_INFO "IPVS: Creating netns size=%zu id=%d\n", |
1893 | sizeof(struct netns_ipvs), ipvs->gen); | 1913 | sizeof(struct netns_ipvs), ipvs->gen); |
1894 | return 0; | 1914 | return 0; |
1915 | /* | ||
1916 | * Error handling | ||
1917 | */ | ||
1918 | |||
1919 | sync_fail: | ||
1920 | __ip_vs_conn_cleanup(net); | ||
1921 | conn_fail: | ||
1922 | __ip_vs_app_cleanup(net); | ||
1923 | app_fail: | ||
1924 | __ip_vs_protocol_cleanup(net); | ||
1925 | protocol_fail: | ||
1926 | __ip_vs_control_cleanup(net); | ||
1927 | control_fail: | ||
1928 | __ip_vs_estimator_cleanup(net); | ||
1929 | estimator_fail: | ||
1930 | return -ENOMEM; | ||
1895 | } | 1931 | } |
1896 | 1932 | ||
1897 | static void __net_exit __ip_vs_cleanup(struct net *net) | 1933 | static void __net_exit __ip_vs_cleanup(struct net *net) |
1898 | { | 1934 | { |
1899 | IP_VS_DBG(10, "ipvs netns %d released\n", net_ipvs(net)->gen); | 1935 | __ip_vs_service_cleanup(net); /* ip_vs_flush() with locks */ |
1936 | __ip_vs_conn_cleanup(net); | ||
1937 | __ip_vs_app_cleanup(net); | ||
1938 | __ip_vs_protocol_cleanup(net); | ||
1939 | __ip_vs_control_cleanup(net); | ||
1940 | __ip_vs_estimator_cleanup(net); | ||
1941 | IP_VS_DBG(2, "ipvs netns %d released\n", net_ipvs(net)->gen); | ||
1942 | } | ||
1943 | |||
1944 | static void __net_exit __ip_vs_dev_cleanup(struct net *net) | ||
1945 | { | ||
1946 | EnterFunction(2); | ||
1947 | net_ipvs(net)->enable = 0; /* Disable packet reception */ | ||
1948 | __ip_vs_sync_cleanup(net); | ||
1949 | LeaveFunction(2); | ||
1900 | } | 1950 | } |
1901 | 1951 | ||
1902 | static struct pernet_operations ipvs_core_ops = { | 1952 | static struct pernet_operations ipvs_core_ops = { |
@@ -1906,6 +1956,10 @@ static struct pernet_operations ipvs_core_ops = { | |||
1906 | .size = sizeof(struct netns_ipvs), | 1956 | .size = sizeof(struct netns_ipvs), |
1907 | }; | 1957 | }; |
1908 | 1958 | ||
1959 | static struct pernet_operations ipvs_core_dev_ops = { | ||
1960 | .exit = __ip_vs_dev_cleanup, | ||
1961 | }; | ||
1962 | |||
1909 | /* | 1963 | /* |
1910 | * Initialize IP Virtual Server | 1964 | * Initialize IP Virtual Server |
1911 | */ | 1965 | */ |
@@ -1913,10 +1967,6 @@ static int __init ip_vs_init(void) | |||
1913 | { | 1967 | { |
1914 | int ret; | 1968 | int ret; |
1915 | 1969 | ||
1916 | ret = register_pernet_subsys(&ipvs_core_ops); /* Alloc ip_vs struct */ | ||
1917 | if (ret < 0) | ||
1918 | return ret; | ||
1919 | |||
1920 | ip_vs_estimator_init(); | 1970 | ip_vs_estimator_init(); |
1921 | ret = ip_vs_control_init(); | 1971 | ret = ip_vs_control_init(); |
1922 | if (ret < 0) { | 1972 | if (ret < 0) { |
@@ -1944,15 +1994,28 @@ static int __init ip_vs_init(void) | |||
1944 | goto cleanup_conn; | 1994 | goto cleanup_conn; |
1945 | } | 1995 | } |
1946 | 1996 | ||
1997 | ret = register_pernet_subsys(&ipvs_core_ops); /* Alloc ip_vs struct */ | ||
1998 | if (ret < 0) | ||
1999 | goto cleanup_sync; | ||
2000 | |||
2001 | ret = register_pernet_device(&ipvs_core_dev_ops); | ||
2002 | if (ret < 0) | ||
2003 | goto cleanup_sub; | ||
2004 | |||
1947 | ret = nf_register_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); | 2005 | ret = nf_register_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); |
1948 | if (ret < 0) { | 2006 | if (ret < 0) { |
1949 | pr_err("can't register hooks.\n"); | 2007 | pr_err("can't register hooks.\n"); |
1950 | goto cleanup_sync; | 2008 | goto cleanup_dev; |
1951 | } | 2009 | } |
1952 | 2010 | ||
1953 | pr_info("ipvs loaded.\n"); | 2011 | pr_info("ipvs loaded.\n"); |
2012 | |||
1954 | return ret; | 2013 | return ret; |
1955 | 2014 | ||
2015 | cleanup_dev: | ||
2016 | unregister_pernet_device(&ipvs_core_dev_ops); | ||
2017 | cleanup_sub: | ||
2018 | unregister_pernet_subsys(&ipvs_core_ops); | ||
1956 | cleanup_sync: | 2019 | cleanup_sync: |
1957 | ip_vs_sync_cleanup(); | 2020 | ip_vs_sync_cleanup(); |
1958 | cleanup_conn: | 2021 | cleanup_conn: |
@@ -1964,20 +2027,20 @@ cleanup_sync: | |||
1964 | ip_vs_control_cleanup(); | 2027 | ip_vs_control_cleanup(); |
1965 | cleanup_estimator: | 2028 | cleanup_estimator: |
1966 | ip_vs_estimator_cleanup(); | 2029 | ip_vs_estimator_cleanup(); |
1967 | unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */ | ||
1968 | return ret; | 2030 | return ret; |
1969 | } | 2031 | } |
1970 | 2032 | ||
1971 | static void __exit ip_vs_cleanup(void) | 2033 | static void __exit ip_vs_cleanup(void) |
1972 | { | 2034 | { |
1973 | nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); | 2035 | nf_unregister_hooks(ip_vs_ops, ARRAY_SIZE(ip_vs_ops)); |
2036 | unregister_pernet_device(&ipvs_core_dev_ops); | ||
2037 | unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */ | ||
1974 | ip_vs_sync_cleanup(); | 2038 | ip_vs_sync_cleanup(); |
1975 | ip_vs_conn_cleanup(); | 2039 | ip_vs_conn_cleanup(); |
1976 | ip_vs_app_cleanup(); | 2040 | ip_vs_app_cleanup(); |
1977 | ip_vs_protocol_cleanup(); | 2041 | ip_vs_protocol_cleanup(); |
1978 | ip_vs_control_cleanup(); | 2042 | ip_vs_control_cleanup(); |
1979 | ip_vs_estimator_cleanup(); | 2043 | ip_vs_estimator_cleanup(); |
1980 | unregister_pernet_subsys(&ipvs_core_ops); /* free ip_vs struct */ | ||
1981 | pr_info("ipvs unloaded.\n"); | 2044 | pr_info("ipvs unloaded.\n"); |
1982 | } | 2045 | } |
1983 | 2046 | ||
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 33733c8872e7..89842f06931d 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c | |||
@@ -69,6 +69,11 @@ int ip_vs_get_debug_level(void) | |||
69 | } | 69 | } |
70 | #endif | 70 | #endif |
71 | 71 | ||
72 | |||
73 | /* Protos */ | ||
74 | static void __ip_vs_del_service(struct ip_vs_service *svc); | ||
75 | |||
76 | |||
72 | #ifdef CONFIG_IP_VS_IPV6 | 77 | #ifdef CONFIG_IP_VS_IPV6 |
73 | /* Taken from rt6_fill_node() in net/ipv6/route.c, is there a better way? */ | 78 | /* Taken from rt6_fill_node() in net/ipv6/route.c, is there a better way? */ |
74 | static int __ip_vs_addr_is_local_v6(struct net *net, | 79 | static int __ip_vs_addr_is_local_v6(struct net *net, |
@@ -1214,6 +1219,8 @@ ip_vs_add_service(struct net *net, struct ip_vs_service_user_kern *u, | |||
1214 | write_unlock_bh(&__ip_vs_svc_lock); | 1219 | write_unlock_bh(&__ip_vs_svc_lock); |
1215 | 1220 | ||
1216 | *svc_p = svc; | 1221 | *svc_p = svc; |
1222 | /* Now there is a service - full throttle */ | ||
1223 | ipvs->enable = 1; | ||
1217 | return 0; | 1224 | return 0; |
1218 | 1225 | ||
1219 | 1226 | ||
@@ -1472,6 +1479,84 @@ static int ip_vs_flush(struct net *net) | |||
1472 | return 0; | 1479 | return 0; |
1473 | } | 1480 | } |
1474 | 1481 | ||
1482 | /* | ||
1483 | * Delete service by {netns} in the service table. | ||
1484 | * Called by __ip_vs_cleanup() | ||
1485 | */ | ||
1486 | void __ip_vs_service_cleanup(struct net *net) | ||
1487 | { | ||
1488 | EnterFunction(2); | ||
1489 | /* Check for "full" addressed entries */ | ||
1490 | mutex_lock(&__ip_vs_mutex); | ||
1491 | ip_vs_flush(net); | ||
1492 | mutex_unlock(&__ip_vs_mutex); | ||
1493 | LeaveFunction(2); | ||
1494 | } | ||
1495 | /* | ||
1496 | * Release dst hold by dst_cache | ||
1497 | */ | ||
1498 | static inline void | ||
1499 | __ip_vs_dev_reset(struct ip_vs_dest *dest, struct net_device *dev) | ||
1500 | { | ||
1501 | spin_lock_bh(&dest->dst_lock); | ||
1502 | if (dest->dst_cache && dest->dst_cache->dev == dev) { | ||
1503 | IP_VS_DBG_BUF(3, "Reset dev:%s dest %s:%u ,dest->refcnt=%d\n", | ||
1504 | dev->name, | ||
1505 | IP_VS_DBG_ADDR(dest->af, &dest->addr), | ||
1506 | ntohs(dest->port), | ||
1507 | atomic_read(&dest->refcnt)); | ||
1508 | ip_vs_dst_reset(dest); | ||
1509 | } | ||
1510 | spin_unlock_bh(&dest->dst_lock); | ||
1511 | |||
1512 | } | ||
1513 | /* | ||
1514 | * Netdev event receiver | ||
1515 | * Currently only NETDEV_UNREGISTER is handled, i.e. if we hold a reference to | ||
1516 | * a device that is "unregister" it must be released. | ||
1517 | */ | ||
1518 | static int ip_vs_dst_event(struct notifier_block *this, unsigned long event, | ||
1519 | void *ptr) | ||
1520 | { | ||
1521 | struct net_device *dev = ptr; | ||
1522 | struct net *net = dev_net(dev); | ||
1523 | struct ip_vs_service *svc; | ||
1524 | struct ip_vs_dest *dest; | ||
1525 | unsigned int idx; | ||
1526 | |||
1527 | if (event != NETDEV_UNREGISTER) | ||
1528 | return NOTIFY_DONE; | ||
1529 | IP_VS_DBG(3, "%s() dev=%s\n", __func__, dev->name); | ||
1530 | EnterFunction(2); | ||
1531 | mutex_lock(&__ip_vs_mutex); | ||
1532 | for (idx = 0; idx < IP_VS_SVC_TAB_SIZE; idx++) { | ||
1533 | list_for_each_entry(svc, &ip_vs_svc_table[idx], s_list) { | ||
1534 | if (net_eq(svc->net, net)) { | ||
1535 | list_for_each_entry(dest, &svc->destinations, | ||
1536 | n_list) { | ||
1537 | __ip_vs_dev_reset(dest, dev); | ||
1538 | } | ||
1539 | } | ||
1540 | } | ||
1541 | |||
1542 | list_for_each_entry(svc, &ip_vs_svc_fwm_table[idx], f_list) { | ||
1543 | if (net_eq(svc->net, net)) { | ||
1544 | list_for_each_entry(dest, &svc->destinations, | ||
1545 | n_list) { | ||
1546 | __ip_vs_dev_reset(dest, dev); | ||
1547 | } | ||
1548 | } | ||
1549 | |||
1550 | } | ||
1551 | } | ||
1552 | |||
1553 | list_for_each_entry(dest, &net_ipvs(net)->dest_trash, n_list) { | ||
1554 | __ip_vs_dev_reset(dest, dev); | ||
1555 | } | ||
1556 | mutex_unlock(&__ip_vs_mutex); | ||
1557 | LeaveFunction(2); | ||
1558 | return NOTIFY_DONE; | ||
1559 | } | ||
1475 | 1560 | ||
1476 | /* | 1561 | /* |
1477 | * Zero counters in a service or all services | 1562 | * Zero counters in a service or all services |
@@ -1984,9 +2069,6 @@ static const struct file_operations ip_vs_info_fops = { | |||
1984 | .release = seq_release_private, | 2069 | .release = seq_release_private, |
1985 | }; | 2070 | }; |
1986 | 2071 | ||
1987 | #endif | ||
1988 | |||
1989 | #ifdef CONFIG_PROC_FS | ||
1990 | static int ip_vs_stats_show(struct seq_file *seq, void *v) | 2072 | static int ip_vs_stats_show(struct seq_file *seq, void *v) |
1991 | { | 2073 | { |
1992 | struct net *net = seq_file_single_net(seq); | 2074 | struct net *net = seq_file_single_net(seq); |
@@ -3120,7 +3202,7 @@ nla_put_failure: | |||
3120 | static int ip_vs_genl_dump_daemons(struct sk_buff *skb, | 3202 | static int ip_vs_genl_dump_daemons(struct sk_buff *skb, |
3121 | struct netlink_callback *cb) | 3203 | struct netlink_callback *cb) |
3122 | { | 3204 | { |
3123 | struct net *net = skb_net(skb); | 3205 | struct net *net = skb_sknet(skb); |
3124 | struct netns_ipvs *ipvs = net_ipvs(net); | 3206 | struct netns_ipvs *ipvs = net_ipvs(net); |
3125 | 3207 | ||
3126 | mutex_lock(&__ip_vs_mutex); | 3208 | mutex_lock(&__ip_vs_mutex); |
@@ -3588,6 +3670,10 @@ void __net_init __ip_vs_control_cleanup_sysctl(struct net *net) { } | |||
3588 | 3670 | ||
3589 | #endif | 3671 | #endif |
3590 | 3672 | ||
3673 | static struct notifier_block ip_vs_dst_notifier = { | ||
3674 | .notifier_call = ip_vs_dst_event, | ||
3675 | }; | ||
3676 | |||
3591 | int __net_init __ip_vs_control_init(struct net *net) | 3677 | int __net_init __ip_vs_control_init(struct net *net) |
3592 | { | 3678 | { |
3593 | int idx; | 3679 | int idx; |
@@ -3626,7 +3712,7 @@ err: | |||
3626 | return -ENOMEM; | 3712 | return -ENOMEM; |
3627 | } | 3713 | } |
3628 | 3714 | ||
3629 | static void __net_exit __ip_vs_control_cleanup(struct net *net) | 3715 | void __net_exit __ip_vs_control_cleanup(struct net *net) |
3630 | { | 3716 | { |
3631 | struct netns_ipvs *ipvs = net_ipvs(net); | 3717 | struct netns_ipvs *ipvs = net_ipvs(net); |
3632 | 3718 | ||
@@ -3639,11 +3725,6 @@ static void __net_exit __ip_vs_control_cleanup(struct net *net) | |||
3639 | free_percpu(ipvs->tot_stats.cpustats); | 3725 | free_percpu(ipvs->tot_stats.cpustats); |
3640 | } | 3726 | } |
3641 | 3727 | ||
3642 | static struct pernet_operations ipvs_control_ops = { | ||
3643 | .init = __ip_vs_control_init, | ||
3644 | .exit = __ip_vs_control_cleanup, | ||
3645 | }; | ||
3646 | |||
3647 | int __init ip_vs_control_init(void) | 3728 | int __init ip_vs_control_init(void) |
3648 | { | 3729 | { |
3649 | int idx; | 3730 | int idx; |
@@ -3657,33 +3738,32 @@ int __init ip_vs_control_init(void) | |||
3657 | INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]); | 3738 | INIT_LIST_HEAD(&ip_vs_svc_fwm_table[idx]); |
3658 | } | 3739 | } |
3659 | 3740 | ||
3660 | ret = register_pernet_subsys(&ipvs_control_ops); | ||
3661 | if (ret) { | ||
3662 | pr_err("cannot register namespace.\n"); | ||
3663 | goto err; | ||
3664 | } | ||
3665 | |||
3666 | smp_wmb(); /* Do we really need it now ? */ | 3741 | smp_wmb(); /* Do we really need it now ? */ |
3667 | 3742 | ||
3668 | ret = nf_register_sockopt(&ip_vs_sockopts); | 3743 | ret = nf_register_sockopt(&ip_vs_sockopts); |
3669 | if (ret) { | 3744 | if (ret) { |
3670 | pr_err("cannot register sockopt.\n"); | 3745 | pr_err("cannot register sockopt.\n"); |
3671 | goto err_net; | 3746 | goto err_sock; |
3672 | } | 3747 | } |
3673 | 3748 | ||
3674 | ret = ip_vs_genl_register(); | 3749 | ret = ip_vs_genl_register(); |
3675 | if (ret) { | 3750 | if (ret) { |
3676 | pr_err("cannot register Generic Netlink interface.\n"); | 3751 | pr_err("cannot register Generic Netlink interface.\n"); |
3677 | nf_unregister_sockopt(&ip_vs_sockopts); | 3752 | goto err_genl; |
3678 | goto err_net; | ||
3679 | } | 3753 | } |
3680 | 3754 | ||
3755 | ret = register_netdevice_notifier(&ip_vs_dst_notifier); | ||
3756 | if (ret < 0) | ||
3757 | goto err_notf; | ||
3758 | |||
3681 | LeaveFunction(2); | 3759 | LeaveFunction(2); |
3682 | return 0; | 3760 | return 0; |
3683 | 3761 | ||
3684 | err_net: | 3762 | err_notf: |
3685 | unregister_pernet_subsys(&ipvs_control_ops); | 3763 | ip_vs_genl_unregister(); |
3686 | err: | 3764 | err_genl: |
3765 | nf_unregister_sockopt(&ip_vs_sockopts); | ||
3766 | err_sock: | ||
3687 | return ret; | 3767 | return ret; |
3688 | } | 3768 | } |
3689 | 3769 | ||
@@ -3691,7 +3771,6 @@ err: | |||
3691 | void ip_vs_control_cleanup(void) | 3771 | void ip_vs_control_cleanup(void) |
3692 | { | 3772 | { |
3693 | EnterFunction(2); | 3773 | EnterFunction(2); |
3694 | unregister_pernet_subsys(&ipvs_control_ops); | ||
3695 | ip_vs_genl_unregister(); | 3774 | ip_vs_genl_unregister(); |
3696 | nf_unregister_sockopt(&ip_vs_sockopts); | 3775 | nf_unregister_sockopt(&ip_vs_sockopts); |
3697 | LeaveFunction(2); | 3776 | LeaveFunction(2); |
diff --git a/net/netfilter/ipvs/ip_vs_est.c b/net/netfilter/ipvs/ip_vs_est.c index 8c8766ca56ad..508cce98777c 100644 --- a/net/netfilter/ipvs/ip_vs_est.c +++ b/net/netfilter/ipvs/ip_vs_est.c | |||
@@ -192,7 +192,7 @@ void ip_vs_read_estimator(struct ip_vs_stats_user *dst, | |||
192 | dst->outbps = (e->outbps + 0xF) >> 5; | 192 | dst->outbps = (e->outbps + 0xF) >> 5; |
193 | } | 193 | } |
194 | 194 | ||
195 | static int __net_init __ip_vs_estimator_init(struct net *net) | 195 | int __net_init __ip_vs_estimator_init(struct net *net) |
196 | { | 196 | { |
197 | struct netns_ipvs *ipvs = net_ipvs(net); | 197 | struct netns_ipvs *ipvs = net_ipvs(net); |
198 | 198 | ||
@@ -203,24 +203,16 @@ static int __net_init __ip_vs_estimator_init(struct net *net) | |||
203 | return 0; | 203 | return 0; |
204 | } | 204 | } |
205 | 205 | ||
206 | static void __net_exit __ip_vs_estimator_exit(struct net *net) | 206 | void __net_exit __ip_vs_estimator_cleanup(struct net *net) |
207 | { | 207 | { |
208 | del_timer_sync(&net_ipvs(net)->est_timer); | 208 | del_timer_sync(&net_ipvs(net)->est_timer); |
209 | } | 209 | } |
210 | static struct pernet_operations ip_vs_app_ops = { | ||
211 | .init = __ip_vs_estimator_init, | ||
212 | .exit = __ip_vs_estimator_exit, | ||
213 | }; | ||
214 | 210 | ||
215 | int __init ip_vs_estimator_init(void) | 211 | int __init ip_vs_estimator_init(void) |
216 | { | 212 | { |
217 | int rv; | 213 | return 0; |
218 | |||
219 | rv = register_pernet_subsys(&ip_vs_app_ops); | ||
220 | return rv; | ||
221 | } | 214 | } |
222 | 215 | ||
223 | void ip_vs_estimator_cleanup(void) | 216 | void ip_vs_estimator_cleanup(void) |
224 | { | 217 | { |
225 | unregister_pernet_subsys(&ip_vs_app_ops); | ||
226 | } | 218 | } |
diff --git a/net/netfilter/ipvs/ip_vs_lblc.c b/net/netfilter/ipvs/ip_vs_lblc.c index f276df9896b3..87e40ea77a95 100644 --- a/net/netfilter/ipvs/ip_vs_lblc.c +++ b/net/netfilter/ipvs/ip_vs_lblc.c | |||
@@ -131,7 +131,7 @@ static inline void ip_vs_lblc_free(struct ip_vs_lblc_entry *en) | |||
131 | { | 131 | { |
132 | list_del(&en->list); | 132 | list_del(&en->list); |
133 | /* | 133 | /* |
134 | * We don't kfree dest because it is refered either by its service | 134 | * We don't kfree dest because it is referred either by its service |
135 | * or the trash dest list. | 135 | * or the trash dest list. |
136 | */ | 136 | */ |
137 | atomic_dec(&en->dest->refcnt); | 137 | atomic_dec(&en->dest->refcnt); |
diff --git a/net/netfilter/ipvs/ip_vs_lblcr.c b/net/netfilter/ipvs/ip_vs_lblcr.c index cb1c9913d38b..90f618ab6dda 100644 --- a/net/netfilter/ipvs/ip_vs_lblcr.c +++ b/net/netfilter/ipvs/ip_vs_lblcr.c | |||
@@ -152,7 +152,7 @@ static void ip_vs_dest_set_eraseall(struct ip_vs_dest_set *set) | |||
152 | write_lock(&set->lock); | 152 | write_lock(&set->lock); |
153 | list_for_each_entry_safe(e, ep, &set->list, list) { | 153 | list_for_each_entry_safe(e, ep, &set->list, list) { |
154 | /* | 154 | /* |
155 | * We don't kfree dest because it is refered either | 155 | * We don't kfree dest because it is referred either |
156 | * by its service or by the trash dest list. | 156 | * by its service or by the trash dest list. |
157 | */ | 157 | */ |
158 | atomic_dec(&e->dest->refcnt); | 158 | atomic_dec(&e->dest->refcnt); |
diff --git a/net/netfilter/ipvs/ip_vs_proto.c b/net/netfilter/ipvs/ip_vs_proto.c index 17484a4416ef..eb86028536fc 100644 --- a/net/netfilter/ipvs/ip_vs_proto.c +++ b/net/netfilter/ipvs/ip_vs_proto.c | |||
@@ -316,7 +316,7 @@ ip_vs_tcpudp_debug_packet(int af, struct ip_vs_protocol *pp, | |||
316 | /* | 316 | /* |
317 | * per network name-space init | 317 | * per network name-space init |
318 | */ | 318 | */ |
319 | static int __net_init __ip_vs_protocol_init(struct net *net) | 319 | int __net_init __ip_vs_protocol_init(struct net *net) |
320 | { | 320 | { |
321 | #ifdef CONFIG_IP_VS_PROTO_TCP | 321 | #ifdef CONFIG_IP_VS_PROTO_TCP |
322 | register_ip_vs_proto_netns(net, &ip_vs_protocol_tcp); | 322 | register_ip_vs_proto_netns(net, &ip_vs_protocol_tcp); |
@@ -336,7 +336,7 @@ static int __net_init __ip_vs_protocol_init(struct net *net) | |||
336 | return 0; | 336 | return 0; |
337 | } | 337 | } |
338 | 338 | ||
339 | static void __net_exit __ip_vs_protocol_cleanup(struct net *net) | 339 | void __net_exit __ip_vs_protocol_cleanup(struct net *net) |
340 | { | 340 | { |
341 | struct netns_ipvs *ipvs = net_ipvs(net); | 341 | struct netns_ipvs *ipvs = net_ipvs(net); |
342 | struct ip_vs_proto_data *pd; | 342 | struct ip_vs_proto_data *pd; |
@@ -349,11 +349,6 @@ static void __net_exit __ip_vs_protocol_cleanup(struct net *net) | |||
349 | } | 349 | } |
350 | } | 350 | } |
351 | 351 | ||
352 | static struct pernet_operations ipvs_proto_ops = { | ||
353 | .init = __ip_vs_protocol_init, | ||
354 | .exit = __ip_vs_protocol_cleanup, | ||
355 | }; | ||
356 | |||
357 | int __init ip_vs_protocol_init(void) | 352 | int __init ip_vs_protocol_init(void) |
358 | { | 353 | { |
359 | char protocols[64]; | 354 | char protocols[64]; |
@@ -382,7 +377,6 @@ int __init ip_vs_protocol_init(void) | |||
382 | REGISTER_PROTOCOL(&ip_vs_protocol_esp); | 377 | REGISTER_PROTOCOL(&ip_vs_protocol_esp); |
383 | #endif | 378 | #endif |
384 | pr_info("Registered protocols (%s)\n", &protocols[2]); | 379 | pr_info("Registered protocols (%s)\n", &protocols[2]); |
385 | return register_pernet_subsys(&ipvs_proto_ops); | ||
386 | 380 | ||
387 | return 0; | 381 | return 0; |
388 | } | 382 | } |
@@ -393,7 +387,6 @@ void ip_vs_protocol_cleanup(void) | |||
393 | struct ip_vs_protocol *pp; | 387 | struct ip_vs_protocol *pp; |
394 | int i; | 388 | int i; |
395 | 389 | ||
396 | unregister_pernet_subsys(&ipvs_proto_ops); | ||
397 | /* unregister all the ipvs protocols */ | 390 | /* unregister all the ipvs protocols */ |
398 | for (i = 0; i < IP_VS_PROTO_TAB_SIZE; i++) { | 391 | for (i = 0; i < IP_VS_PROTO_TAB_SIZE; i++) { |
399 | while ((pp = ip_vs_proto_table[i]) != NULL) | 392 | while ((pp = ip_vs_proto_table[i]) != NULL) |
diff --git a/net/netfilter/ipvs/ip_vs_proto_sctp.c b/net/netfilter/ipvs/ip_vs_proto_sctp.c index b027ccc49f43..d12ed53ec95f 100644 --- a/net/netfilter/ipvs/ip_vs_proto_sctp.c +++ b/net/netfilter/ipvs/ip_vs_proto_sctp.c | |||
@@ -566,7 +566,7 @@ static struct ipvs_sctp_nextstate | |||
566 | * SHUTDOWN sent from the client, waitinf for SHUT ACK from the server | 566 | * SHUTDOWN sent from the client, waitinf for SHUT ACK from the server |
567 | */ | 567 | */ |
568 | /* | 568 | /* |
569 | * We recieved the data chuck, keep the state unchanged. I assume | 569 | * We received the data chuck, keep the state unchanged. I assume |
570 | * that still data chuncks can be received by both the peers in | 570 | * that still data chuncks can be received by both the peers in |
571 | * SHUDOWN state | 571 | * SHUDOWN state |
572 | */ | 572 | */ |
@@ -633,7 +633,7 @@ static struct ipvs_sctp_nextstate | |||
633 | * SHUTDOWN sent from the server, waitinf for SHUTDOWN ACK from client | 633 | * SHUTDOWN sent from the server, waitinf for SHUTDOWN ACK from client |
634 | */ | 634 | */ |
635 | /* | 635 | /* |
636 | * We recieved the data chuck, keep the state unchanged. I assume | 636 | * We received the data chuck, keep the state unchanged. I assume |
637 | * that still data chuncks can be received by both the peers in | 637 | * that still data chuncks can be received by both the peers in |
638 | * SHUDOWN state | 638 | * SHUDOWN state |
639 | */ | 639 | */ |
@@ -701,7 +701,7 @@ static struct ipvs_sctp_nextstate | |||
701 | * SHUTDOWN ACK from the client, awaiting for SHUTDOWN COM from server | 701 | * SHUTDOWN ACK from the client, awaiting for SHUTDOWN COM from server |
702 | */ | 702 | */ |
703 | /* | 703 | /* |
704 | * We recieved the data chuck, keep the state unchanged. I assume | 704 | * We received the data chuck, keep the state unchanged. I assume |
705 | * that still data chuncks can be received by both the peers in | 705 | * that still data chuncks can be received by both the peers in |
706 | * SHUDOWN state | 706 | * SHUDOWN state |
707 | */ | 707 | */ |
@@ -771,7 +771,7 @@ static struct ipvs_sctp_nextstate | |||
771 | * SHUTDOWN ACK from the server, awaiting for SHUTDOWN COM from client | 771 | * SHUTDOWN ACK from the server, awaiting for SHUTDOWN COM from client |
772 | */ | 772 | */ |
773 | /* | 773 | /* |
774 | * We recieved the data chuck, keep the state unchanged. I assume | 774 | * We received the data chuck, keep the state unchanged. I assume |
775 | * that still data chuncks can be received by both the peers in | 775 | * that still data chuncks can be received by both the peers in |
776 | * SHUDOWN state | 776 | * SHUDOWN state |
777 | */ | 777 | */ |
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c index 3e7961e85e9c..e292e5bddc70 100644 --- a/net/netfilter/ipvs/ip_vs_sync.c +++ b/net/netfilter/ipvs/ip_vs_sync.c | |||
@@ -1303,13 +1303,18 @@ static struct socket *make_send_sock(struct net *net) | |||
1303 | struct socket *sock; | 1303 | struct socket *sock; |
1304 | int result; | 1304 | int result; |
1305 | 1305 | ||
1306 | /* First create a socket */ | 1306 | /* First create a socket move it to right name space later */ |
1307 | result = __sock_create(net, PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock, 1); | 1307 | result = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock); |
1308 | if (result < 0) { | 1308 | if (result < 0) { |
1309 | pr_err("Error during creation of socket; terminating\n"); | 1309 | pr_err("Error during creation of socket; terminating\n"); |
1310 | return ERR_PTR(result); | 1310 | return ERR_PTR(result); |
1311 | } | 1311 | } |
1312 | 1312 | /* | |
1313 | * Kernel sockets that are a part of a namespace, should not | ||
1314 | * hold a reference to a namespace in order to allow to stop it. | ||
1315 | * After sk_change_net should be released using sk_release_kernel. | ||
1316 | */ | ||
1317 | sk_change_net(sock->sk, net); | ||
1313 | result = set_mcast_if(sock->sk, ipvs->master_mcast_ifn); | 1318 | result = set_mcast_if(sock->sk, ipvs->master_mcast_ifn); |
1314 | if (result < 0) { | 1319 | if (result < 0) { |
1315 | pr_err("Error setting outbound mcast interface\n"); | 1320 | pr_err("Error setting outbound mcast interface\n"); |
@@ -1334,8 +1339,8 @@ static struct socket *make_send_sock(struct net *net) | |||
1334 | 1339 | ||
1335 | return sock; | 1340 | return sock; |
1336 | 1341 | ||
1337 | error: | 1342 | error: |
1338 | sock_release(sock); | 1343 | sk_release_kernel(sock->sk); |
1339 | return ERR_PTR(result); | 1344 | return ERR_PTR(result); |
1340 | } | 1345 | } |
1341 | 1346 | ||
@@ -1350,12 +1355,17 @@ static struct socket *make_receive_sock(struct net *net) | |||
1350 | int result; | 1355 | int result; |
1351 | 1356 | ||
1352 | /* First create a socket */ | 1357 | /* First create a socket */ |
1353 | result = __sock_create(net, PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock, 1); | 1358 | result = sock_create_kern(PF_INET, SOCK_DGRAM, IPPROTO_UDP, &sock); |
1354 | if (result < 0) { | 1359 | if (result < 0) { |
1355 | pr_err("Error during creation of socket; terminating\n"); | 1360 | pr_err("Error during creation of socket; terminating\n"); |
1356 | return ERR_PTR(result); | 1361 | return ERR_PTR(result); |
1357 | } | 1362 | } |
1358 | 1363 | /* | |
1364 | * Kernel sockets that are a part of a namespace, should not | ||
1365 | * hold a reference to a namespace in order to allow to stop it. | ||
1366 | * After sk_change_net should be released using sk_release_kernel. | ||
1367 | */ | ||
1368 | sk_change_net(sock->sk, net); | ||
1359 | /* it is equivalent to the REUSEADDR option in user-space */ | 1369 | /* it is equivalent to the REUSEADDR option in user-space */ |
1360 | sock->sk->sk_reuse = 1; | 1370 | sock->sk->sk_reuse = 1; |
1361 | 1371 | ||
@@ -1377,8 +1387,8 @@ static struct socket *make_receive_sock(struct net *net) | |||
1377 | 1387 | ||
1378 | return sock; | 1388 | return sock; |
1379 | 1389 | ||
1380 | error: | 1390 | error: |
1381 | sock_release(sock); | 1391 | sk_release_kernel(sock->sk); |
1382 | return ERR_PTR(result); | 1392 | return ERR_PTR(result); |
1383 | } | 1393 | } |
1384 | 1394 | ||
@@ -1473,7 +1483,7 @@ static int sync_thread_master(void *data) | |||
1473 | ip_vs_sync_buff_release(sb); | 1483 | ip_vs_sync_buff_release(sb); |
1474 | 1484 | ||
1475 | /* release the sending multicast socket */ | 1485 | /* release the sending multicast socket */ |
1476 | sock_release(tinfo->sock); | 1486 | sk_release_kernel(tinfo->sock->sk); |
1477 | kfree(tinfo); | 1487 | kfree(tinfo); |
1478 | 1488 | ||
1479 | return 0; | 1489 | return 0; |
@@ -1513,7 +1523,7 @@ static int sync_thread_backup(void *data) | |||
1513 | } | 1523 | } |
1514 | 1524 | ||
1515 | /* release the sending multicast socket */ | 1525 | /* release the sending multicast socket */ |
1516 | sock_release(tinfo->sock); | 1526 | sk_release_kernel(tinfo->sock->sk); |
1517 | kfree(tinfo->buf); | 1527 | kfree(tinfo->buf); |
1518 | kfree(tinfo); | 1528 | kfree(tinfo); |
1519 | 1529 | ||
@@ -1601,7 +1611,7 @@ outtinfo: | |||
1601 | outbuf: | 1611 | outbuf: |
1602 | kfree(buf); | 1612 | kfree(buf); |
1603 | outsocket: | 1613 | outsocket: |
1604 | sock_release(sock); | 1614 | sk_release_kernel(sock->sk); |
1605 | out: | 1615 | out: |
1606 | return result; | 1616 | return result; |
1607 | } | 1617 | } |
@@ -1610,6 +1620,7 @@ out: | |||
1610 | int stop_sync_thread(struct net *net, int state) | 1620 | int stop_sync_thread(struct net *net, int state) |
1611 | { | 1621 | { |
1612 | struct netns_ipvs *ipvs = net_ipvs(net); | 1622 | struct netns_ipvs *ipvs = net_ipvs(net); |
1623 | int retc = -EINVAL; | ||
1613 | 1624 | ||
1614 | IP_VS_DBG(7, "%s(): pid %d\n", __func__, task_pid_nr(current)); | 1625 | IP_VS_DBG(7, "%s(): pid %d\n", __func__, task_pid_nr(current)); |
1615 | 1626 | ||
@@ -1629,7 +1640,7 @@ int stop_sync_thread(struct net *net, int state) | |||
1629 | spin_lock_bh(&ipvs->sync_lock); | 1640 | spin_lock_bh(&ipvs->sync_lock); |
1630 | ipvs->sync_state &= ~IP_VS_STATE_MASTER; | 1641 | ipvs->sync_state &= ~IP_VS_STATE_MASTER; |
1631 | spin_unlock_bh(&ipvs->sync_lock); | 1642 | spin_unlock_bh(&ipvs->sync_lock); |
1632 | kthread_stop(ipvs->master_thread); | 1643 | retc = kthread_stop(ipvs->master_thread); |
1633 | ipvs->master_thread = NULL; | 1644 | ipvs->master_thread = NULL; |
1634 | } else if (state == IP_VS_STATE_BACKUP) { | 1645 | } else if (state == IP_VS_STATE_BACKUP) { |
1635 | if (!ipvs->backup_thread) | 1646 | if (!ipvs->backup_thread) |
@@ -1639,22 +1650,20 @@ int stop_sync_thread(struct net *net, int state) | |||
1639 | task_pid_nr(ipvs->backup_thread)); | 1650 | task_pid_nr(ipvs->backup_thread)); |
1640 | 1651 | ||
1641 | ipvs->sync_state &= ~IP_VS_STATE_BACKUP; | 1652 | ipvs->sync_state &= ~IP_VS_STATE_BACKUP; |
1642 | kthread_stop(ipvs->backup_thread); | 1653 | retc = kthread_stop(ipvs->backup_thread); |
1643 | ipvs->backup_thread = NULL; | 1654 | ipvs->backup_thread = NULL; |
1644 | } else { | ||
1645 | return -EINVAL; | ||
1646 | } | 1655 | } |
1647 | 1656 | ||
1648 | /* decrease the module use count */ | 1657 | /* decrease the module use count */ |
1649 | ip_vs_use_count_dec(); | 1658 | ip_vs_use_count_dec(); |
1650 | 1659 | ||
1651 | return 0; | 1660 | return retc; |
1652 | } | 1661 | } |
1653 | 1662 | ||
1654 | /* | 1663 | /* |
1655 | * Initialize data struct for each netns | 1664 | * Initialize data struct for each netns |
1656 | */ | 1665 | */ |
1657 | static int __net_init __ip_vs_sync_init(struct net *net) | 1666 | int __net_init __ip_vs_sync_init(struct net *net) |
1658 | { | 1667 | { |
1659 | struct netns_ipvs *ipvs = net_ipvs(net); | 1668 | struct netns_ipvs *ipvs = net_ipvs(net); |
1660 | 1669 | ||
@@ -1668,24 +1677,24 @@ static int __net_init __ip_vs_sync_init(struct net *net) | |||
1668 | return 0; | 1677 | return 0; |
1669 | } | 1678 | } |
1670 | 1679 | ||
1671 | static void __ip_vs_sync_cleanup(struct net *net) | 1680 | void __ip_vs_sync_cleanup(struct net *net) |
1672 | { | 1681 | { |
1673 | stop_sync_thread(net, IP_VS_STATE_MASTER); | 1682 | int retc; |
1674 | stop_sync_thread(net, IP_VS_STATE_BACKUP); | ||
1675 | } | ||
1676 | 1683 | ||
1677 | static struct pernet_operations ipvs_sync_ops = { | 1684 | retc = stop_sync_thread(net, IP_VS_STATE_MASTER); |
1678 | .init = __ip_vs_sync_init, | 1685 | if (retc && retc != -ESRCH) |
1679 | .exit = __ip_vs_sync_cleanup, | 1686 | pr_err("Failed to stop Master Daemon\n"); |
1680 | }; | ||
1681 | 1687 | ||
1688 | retc = stop_sync_thread(net, IP_VS_STATE_BACKUP); | ||
1689 | if (retc && retc != -ESRCH) | ||
1690 | pr_err("Failed to stop Backup Daemon\n"); | ||
1691 | } | ||
1682 | 1692 | ||
1683 | int __init ip_vs_sync_init(void) | 1693 | int __init ip_vs_sync_init(void) |
1684 | { | 1694 | { |
1685 | return register_pernet_subsys(&ipvs_sync_ops); | 1695 | return 0; |
1686 | } | 1696 | } |
1687 | 1697 | ||
1688 | void ip_vs_sync_cleanup(void) | 1698 | void ip_vs_sync_cleanup(void) |
1689 | { | 1699 | { |
1690 | unregister_pernet_subsys(&ipvs_sync_ops); | ||
1691 | } | 1700 | } |
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/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 941286ca911d..2e1c11f78419 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -453,7 +453,7 @@ __nf_conntrack_confirm(struct sk_buff *skb) | |||
453 | REJECT will give spurious warnings here. */ | 453 | REJECT will give spurious warnings here. */ |
454 | /* NF_CT_ASSERT(atomic_read(&ct->ct_general.use) == 1); */ | 454 | /* NF_CT_ASSERT(atomic_read(&ct->ct_general.use) == 1); */ |
455 | 455 | ||
456 | /* No external references means noone else could have | 456 | /* No external references means no one else could have |
457 | confirmed us. */ | 457 | confirmed us. */ |
458 | NF_CT_ASSERT(!nf_ct_is_confirmed(ct)); | 458 | NF_CT_ASSERT(!nf_ct_is_confirmed(ct)); |
459 | pr_debug("Confirming conntrack %p\n", ct); | 459 | pr_debug("Confirming conntrack %p\n", ct); |
@@ -901,7 +901,7 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, | |||
901 | ret = l3proto->get_l4proto(skb, skb_network_offset(skb), | 901 | ret = l3proto->get_l4proto(skb, skb_network_offset(skb), |
902 | &dataoff, &protonum); | 902 | &dataoff, &protonum); |
903 | if (ret <= 0) { | 903 | if (ret <= 0) { |
904 | pr_debug("not prepared to track yet or error occured\n"); | 904 | pr_debug("not prepared to track yet or error occurred\n"); |
905 | NF_CT_STAT_INC_ATOMIC(net, error); | 905 | NF_CT_STAT_INC_ATOMIC(net, error); |
906 | NF_CT_STAT_INC_ATOMIC(net, invalid); | 906 | NF_CT_STAT_INC_ATOMIC(net, invalid); |
907 | ret = -ret; | 907 | ret = -ret; |
diff --git a/net/netfilter/nf_conntrack_h323_asn1.c b/net/netfilter/nf_conntrack_h323_asn1.c index 867882313e49..bcd5ed6b7130 100644 --- a/net/netfilter/nf_conntrack_h323_asn1.c +++ b/net/netfilter/nf_conntrack_h323_asn1.c | |||
@@ -631,7 +631,7 @@ static int decode_seqof(bitstr_t *bs, const struct field_t *f, | |||
631 | CHECK_BOUND(bs, 2); | 631 | CHECK_BOUND(bs, 2); |
632 | count = *bs->cur++; | 632 | count = *bs->cur++; |
633 | count <<= 8; | 633 | count <<= 8; |
634 | count = *bs->cur++; | 634 | count += *bs->cur++; |
635 | break; | 635 | break; |
636 | case SEMI: | 636 | case SEMI: |
637 | BYTE_ALIGN(bs); | 637 | BYTE_ALIGN(bs); |
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index 533a183e6661..18b2ce5c8ced 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c | |||
@@ -731,10 +731,10 @@ static int callforward_do_filter(const union nf_inet_addr *src, | |||
731 | 731 | ||
732 | memset(&fl2, 0, sizeof(fl2)); | 732 | memset(&fl2, 0, sizeof(fl2)); |
733 | fl2.daddr = dst->ip; | 733 | fl2.daddr = dst->ip; |
734 | if (!afinfo->route((struct dst_entry **)&rt1, | 734 | if (!afinfo->route(&init_net, (struct dst_entry **)&rt1, |
735 | flowi4_to_flowi(&fl1))) { | 735 | flowi4_to_flowi(&fl1), false)) { |
736 | if (!afinfo->route((struct dst_entry **)&rt2, | 736 | if (!afinfo->route(&init_net, (struct dst_entry **)&rt2, |
737 | flowi4_to_flowi(&fl2))) { | 737 | flowi4_to_flowi(&fl2), false)) { |
738 | if (rt1->rt_gateway == rt2->rt_gateway && | 738 | if (rt1->rt_gateway == rt2->rt_gateway && |
739 | rt1->dst.dev == rt2->dst.dev) | 739 | rt1->dst.dev == rt2->dst.dev) |
740 | ret = 1; | 740 | ret = 1; |
@@ -755,10 +755,10 @@ static int callforward_do_filter(const union nf_inet_addr *src, | |||
755 | 755 | ||
756 | memset(&fl2, 0, sizeof(fl2)); | 756 | memset(&fl2, 0, sizeof(fl2)); |
757 | ipv6_addr_copy(&fl2.daddr, &dst->in6); | 757 | ipv6_addr_copy(&fl2.daddr, &dst->in6); |
758 | if (!afinfo->route((struct dst_entry **)&rt1, | 758 | if (!afinfo->route(&init_net, (struct dst_entry **)&rt1, |
759 | flowi6_to_flowi(&fl1))) { | 759 | flowi6_to_flowi(&fl1), false)) { |
760 | if (!afinfo->route((struct dst_entry **)&rt2, | 760 | if (!afinfo->route(&init_net, (struct dst_entry **)&rt2, |
761 | flowi6_to_flowi(&fl2))) { | 761 | flowi6_to_flowi(&fl2), false)) { |
762 | if (!memcmp(&rt1->rt6i_gateway, &rt2->rt6i_gateway, | 762 | if (!memcmp(&rt1->rt6i_gateway, &rt2->rt6i_gateway, |
763 | sizeof(rt1->rt6i_gateway)) && | 763 | sizeof(rt1->rt6i_gateway)) && |
764 | rt1->dst.dev == rt2->dst.dev) | 764 | rt1->dst.dev == rt2->dst.dev) |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 30bf8a167fc8..482e90c61850 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -1334,6 +1334,7 @@ ctnetlink_create_conntrack(struct net *net, u16 zone, | |||
1334 | struct nf_conn *ct; | 1334 | struct nf_conn *ct; |
1335 | int err = -EINVAL; | 1335 | int err = -EINVAL; |
1336 | struct nf_conntrack_helper *helper; | 1336 | struct nf_conntrack_helper *helper; |
1337 | struct nf_conn_tstamp *tstamp; | ||
1337 | 1338 | ||
1338 | ct = nf_conntrack_alloc(net, zone, otuple, rtuple, GFP_ATOMIC); | 1339 | ct = nf_conntrack_alloc(net, zone, otuple, rtuple, GFP_ATOMIC); |
1339 | if (IS_ERR(ct)) | 1340 | if (IS_ERR(ct)) |
@@ -1451,6 +1452,9 @@ ctnetlink_create_conntrack(struct net *net, u16 zone, | |||
1451 | __set_bit(IPS_EXPECTED_BIT, &ct->status); | 1452 | __set_bit(IPS_EXPECTED_BIT, &ct->status); |
1452 | ct->master = master_ct; | 1453 | ct->master = master_ct; |
1453 | } | 1454 | } |
1455 | tstamp = nf_conn_tstamp_find(ct); | ||
1456 | if (tstamp) | ||
1457 | tstamp->start = ktime_to_ns(ktime_get_real()); | ||
1454 | 1458 | ||
1455 | add_timer(&ct->timeout); | 1459 | add_timer(&ct->timeout); |
1456 | nf_conntrack_hash_insert(ct); | 1460 | nf_conntrack_hash_insert(ct); |
diff --git a/net/netfilter/nf_conntrack_proto_dccp.c b/net/netfilter/nf_conntrack_proto_dccp.c index 9ae57c57c50e..2e664a69d7db 100644 --- a/net/netfilter/nf_conntrack_proto_dccp.c +++ b/net/netfilter/nf_conntrack_proto_dccp.c | |||
@@ -98,7 +98,7 @@ static const char * const dccp_state_names[] = { | |||
98 | #define sIV CT_DCCP_INVALID | 98 | #define sIV CT_DCCP_INVALID |
99 | 99 | ||
100 | /* | 100 | /* |
101 | * DCCP state transistion table | 101 | * DCCP state transition table |
102 | * | 102 | * |
103 | * The assumption is the same as for TCP tracking: | 103 | * The assumption is the same as for TCP tracking: |
104 | * | 104 | * |
diff --git a/net/netfilter/nf_conntrack_proto_sctp.c b/net/netfilter/nf_conntrack_proto_sctp.c index 6f4ee70f460b..6772b1154654 100644 --- a/net/netfilter/nf_conntrack_proto_sctp.c +++ b/net/netfilter/nf_conntrack_proto_sctp.c | |||
@@ -107,9 +107,9 @@ static const u8 sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = { | |||
107 | /* abort */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL}, | 107 | /* abort */ {sCL, sCL, sCL, sCL, sCL, sCL, sCL, sCL}, |
108 | /* shutdown */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA}, | 108 | /* shutdown */ {sCL, sCL, sCW, sCE, sSS, sSS, sSR, sSA}, |
109 | /* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA}, | 109 | /* shutdown_ack */ {sSA, sCL, sCW, sCE, sES, sSA, sSA, sSA}, |
110 | /* error */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant have Stale cookie*/ | 110 | /* error */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Can't have Stale cookie*/ |
111 | /* cookie_echo */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA},/* 5.2.4 - Big TODO */ | 111 | /* cookie_echo */ {sCL, sCL, sCE, sCE, sES, sSS, sSR, sSA},/* 5.2.4 - Big TODO */ |
112 | /* cookie_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in orig dir */ | 112 | /* cookie_ack */ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Can't come in orig dir */ |
113 | /* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL} | 113 | /* shutdown_comp*/ {sCL, sCL, sCW, sCE, sES, sSS, sSR, sCL} |
114 | }, | 114 | }, |
115 | { | 115 | { |
@@ -121,7 +121,7 @@ static const u8 sctp_conntracks[2][9][SCTP_CONNTRACK_MAX] = { | |||
121 | /* shutdown */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA}, | 121 | /* shutdown */ {sIV, sCL, sCW, sCE, sSR, sSS, sSR, sSA}, |
122 | /* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA}, | 122 | /* shutdown_ack */ {sIV, sCL, sCW, sCE, sES, sSA, sSA, sSA}, |
123 | /* error */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA}, | 123 | /* error */ {sIV, sCL, sCW, sCL, sES, sSS, sSR, sSA}, |
124 | /* cookie_echo */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Cant come in reply dir */ | 124 | /* cookie_echo */ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sSA},/* Can't come in reply dir */ |
125 | /* cookie_ack */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA}, | 125 | /* cookie_ack */ {sIV, sCL, sCW, sES, sES, sSS, sSR, sSA}, |
126 | /* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL} | 126 | /* shutdown_comp*/ {sIV, sCL, sCW, sCE, sES, sSS, sSR, sCL} |
127 | } | 127 | } |
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index bcf47eb518ef..237cc1981b89 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c | |||
@@ -707,7 +707,7 @@ static const char *ct_sdp_header_search(const char *dptr, const char *limit, | |||
707 | } | 707 | } |
708 | 708 | ||
709 | /* Locate a SDP header (optionally a substring within the header value), | 709 | /* Locate a SDP header (optionally a substring within the header value), |
710 | * optionally stopping at the first occurence of the term header, parse | 710 | * optionally stopping at the first occurrence of the term header, parse |
711 | * it and return the offset and length of the data we're interested in. | 711 | * it and return the offset and length of the data we're interested in. |
712 | */ | 712 | */ |
713 | int ct_sip_get_sdp_header(const struct nf_conn *ct, const char *dptr, | 713 | int ct_sip_get_sdp_header(const struct nf_conn *ct, const char *dptr, |
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 0ae142825881..05e9feb101c3 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c | |||
@@ -245,7 +245,7 @@ static int ct_seq_show(struct seq_file *s, void *v) | |||
245 | ret = 0; | 245 | ret = 0; |
246 | release: | 246 | release: |
247 | nf_ct_put(ct); | 247 | nf_ct_put(ct); |
248 | return 0; | 248 | return ret; |
249 | } | 249 | } |
250 | 250 | ||
251 | static const struct seq_operations ct_seq_ops = { | 251 | static const struct seq_operations ct_seq_ops = { |
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index 5ab22e2bbd7d..5b466cd1272f 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c | |||
@@ -134,7 +134,7 @@ static int __nf_queue(struct sk_buff *skb, | |||
134 | const struct nf_afinfo *afinfo; | 134 | const struct nf_afinfo *afinfo; |
135 | const struct nf_queue_handler *qh; | 135 | const struct nf_queue_handler *qh; |
136 | 136 | ||
137 | /* QUEUE == DROP if noone is waiting, to be safe. */ | 137 | /* QUEUE == DROP if no one is waiting, to be safe. */ |
138 | rcu_read_lock(); | 138 | rcu_read_lock(); |
139 | 139 | ||
140 | qh = rcu_dereference(queue_handler[pf]); | 140 | qh = rcu_dereference(queue_handler[pf]); |
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 985e9b76c916..e0ee010935e7 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c | |||
@@ -381,7 +381,6 @@ __build_packet_message(struct nfulnl_instance *inst, | |||
381 | struct nfulnl_msg_packet_hdr pmsg; | 381 | struct nfulnl_msg_packet_hdr pmsg; |
382 | struct nlmsghdr *nlh; | 382 | struct nlmsghdr *nlh; |
383 | struct nfgenmsg *nfmsg; | 383 | struct nfgenmsg *nfmsg; |
384 | __be32 tmp_uint; | ||
385 | sk_buff_data_t old_tail = inst->skb->tail; | 384 | sk_buff_data_t old_tail = inst->skb->tail; |
386 | 385 | ||
387 | nlh = NLMSG_PUT(inst->skb, 0, 0, | 386 | nlh = NLMSG_PUT(inst->skb, 0, 0, |
@@ -428,7 +427,6 @@ __build_packet_message(struct nfulnl_instance *inst, | |||
428 | } | 427 | } |
429 | 428 | ||
430 | if (outdev) { | 429 | if (outdev) { |
431 | tmp_uint = htonl(outdev->ifindex); | ||
432 | #ifndef CONFIG_BRIDGE_NETFILTER | 430 | #ifndef CONFIG_BRIDGE_NETFILTER |
433 | NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_OUTDEV, | 431 | NLA_PUT_BE32(inst->skb, NFULA_IFINDEX_OUTDEV, |
434 | htonl(outdev->ifindex)); | 432 | htonl(outdev->ifindex)); |
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index a9adf4c6b299..b0869fe3633b 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c | |||
@@ -455,6 +455,7 @@ void xt_compat_flush_offsets(u_int8_t af) | |||
455 | vfree(xt[af].compat_tab); | 455 | vfree(xt[af].compat_tab); |
456 | xt[af].compat_tab = NULL; | 456 | xt[af].compat_tab = NULL; |
457 | xt[af].number = 0; | 457 | xt[af].number = 0; |
458 | xt[af].cur = 0; | ||
458 | } | 459 | } |
459 | } | 460 | } |
460 | EXPORT_SYMBOL_GPL(xt_compat_flush_offsets); | 461 | EXPORT_SYMBOL_GPL(xt_compat_flush_offsets); |
@@ -473,8 +474,7 @@ int xt_compat_calc_jump(u_int8_t af, unsigned int offset) | |||
473 | else | 474 | else |
474 | return mid ? tmp[mid - 1].delta : 0; | 475 | return mid ? tmp[mid - 1].delta : 0; |
475 | } | 476 | } |
476 | WARN_ON_ONCE(1); | 477 | return left ? tmp[left - 1].delta : 0; |
477 | return 0; | ||
478 | } | 478 | } |
479 | EXPORT_SYMBOL_GPL(xt_compat_calc_jump); | 479 | EXPORT_SYMBOL_GPL(xt_compat_calc_jump); |
480 | 480 | ||
@@ -762,8 +762,8 @@ void xt_compat_unlock(u_int8_t af) | |||
762 | EXPORT_SYMBOL_GPL(xt_compat_unlock); | 762 | EXPORT_SYMBOL_GPL(xt_compat_unlock); |
763 | #endif | 763 | #endif |
764 | 764 | ||
765 | DEFINE_PER_CPU(struct xt_info_lock, xt_info_locks); | 765 | DEFINE_PER_CPU(seqcount_t, xt_recseq); |
766 | EXPORT_PER_CPU_SYMBOL_GPL(xt_info_locks); | 766 | EXPORT_PER_CPU_SYMBOL_GPL(xt_recseq); |
767 | 767 | ||
768 | static int xt_jumpstack_alloc(struct xt_table_info *i) | 768 | static int xt_jumpstack_alloc(struct xt_table_info *i) |
769 | { | 769 | { |
@@ -1362,10 +1362,7 @@ static int __init xt_init(void) | |||
1362 | int rv; | 1362 | int rv; |
1363 | 1363 | ||
1364 | for_each_possible_cpu(i) { | 1364 | for_each_possible_cpu(i) { |
1365 | struct xt_info_lock *lock = &per_cpu(xt_info_locks, i); | 1365 | seqcount_init(&per_cpu(xt_recseq, i)); |
1366 | |||
1367 | seqlock_init(&lock->lock); | ||
1368 | lock->readers = 0; | ||
1369 | } | 1366 | } |
1370 | 1367 | ||
1371 | xt = kmalloc(sizeof(struct xt_af) * NFPROTO_NUMPROTO, GFP_KERNEL); | 1368 | xt = kmalloc(sizeof(struct xt_af) * NFPROTO_NUMPROTO, GFP_KERNEL); |
diff --git a/net/netfilter/xt_DSCP.c b/net/netfilter/xt_DSCP.c index 0a229191e55b..ae8271652efa 100644 --- a/net/netfilter/xt_DSCP.c +++ b/net/netfilter/xt_DSCP.c | |||
@@ -99,7 +99,7 @@ tos_tg6(struct sk_buff *skb, const struct xt_action_param *par) | |||
99 | u_int8_t orig, nv; | 99 | u_int8_t orig, nv; |
100 | 100 | ||
101 | orig = ipv6_get_dsfield(iph); | 101 | orig = ipv6_get_dsfield(iph); |
102 | nv = (orig & info->tos_mask) ^ info->tos_value; | 102 | nv = (orig & ~info->tos_mask) ^ info->tos_value; |
103 | 103 | ||
104 | if (orig != nv) { | 104 | if (orig != nv) { |
105 | if (!skb_make_writable(skb, sizeof(struct iphdr))) | 105 | if (!skb_make_writable(skb, sizeof(struct iphdr))) |
diff --git a/net/netfilter/xt_TCPMSS.c b/net/netfilter/xt_TCPMSS.c index 6e6b46cb1db9..9e63b43faeed 100644 --- a/net/netfilter/xt_TCPMSS.c +++ b/net/netfilter/xt_TCPMSS.c | |||
@@ -166,7 +166,7 @@ static u_int32_t tcpmss_reverse_mtu(const struct sk_buff *skb, | |||
166 | rcu_read_lock(); | 166 | rcu_read_lock(); |
167 | ai = nf_get_afinfo(family); | 167 | ai = nf_get_afinfo(family); |
168 | if (ai != NULL) | 168 | if (ai != NULL) |
169 | ai->route((struct dst_entry **)&rt, &fl); | 169 | ai->route(&init_net, (struct dst_entry **)&rt, &fl, false); |
170 | rcu_read_unlock(); | 170 | rcu_read_unlock(); |
171 | 171 | ||
172 | if (rt != NULL) { | 172 | if (rt != NULL) { |
diff --git a/net/netfilter/xt_addrtype.c b/net/netfilter/xt_addrtype.c index 2220b85e9519..b77d383cec78 100644 --- a/net/netfilter/xt_addrtype.c +++ b/net/netfilter/xt_addrtype.c | |||
@@ -32,11 +32,32 @@ MODULE_ALIAS("ipt_addrtype"); | |||
32 | MODULE_ALIAS("ip6t_addrtype"); | 32 | MODULE_ALIAS("ip6t_addrtype"); |
33 | 33 | ||
34 | #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) | 34 | #if defined(CONFIG_IP6_NF_IPTABLES) || defined(CONFIG_IP6_NF_IPTABLES_MODULE) |
35 | static u32 xt_addrtype_rt6_to_type(const struct rt6_info *rt) | 35 | static u32 match_lookup_rt6(struct net *net, const struct net_device *dev, |
36 | const struct in6_addr *addr) | ||
36 | { | 37 | { |
38 | const struct nf_afinfo *afinfo; | ||
39 | struct flowi6 flow; | ||
40 | struct rt6_info *rt; | ||
37 | u32 ret; | 41 | u32 ret; |
42 | int route_err; | ||
38 | 43 | ||
39 | if (!rt) | 44 | memset(&flow, 0, sizeof(flow)); |
45 | ipv6_addr_copy(&flow.daddr, addr); | ||
46 | if (dev) | ||
47 | flow.flowi6_oif = dev->ifindex; | ||
48 | |||
49 | rcu_read_lock(); | ||
50 | |||
51 | afinfo = nf_get_afinfo(NFPROTO_IPV6); | ||
52 | if (afinfo != NULL) | ||
53 | route_err = afinfo->route(net, (struct dst_entry **)&rt, | ||
54 | flowi6_to_flowi(&flow), !!dev); | ||
55 | else | ||
56 | route_err = 1; | ||
57 | |||
58 | rcu_read_unlock(); | ||
59 | |||
60 | if (route_err) | ||
40 | return XT_ADDRTYPE_UNREACHABLE; | 61 | return XT_ADDRTYPE_UNREACHABLE; |
41 | 62 | ||
42 | if (rt->rt6i_flags & RTF_REJECT) | 63 | if (rt->rt6i_flags & RTF_REJECT) |
@@ -48,6 +69,9 @@ static u32 xt_addrtype_rt6_to_type(const struct rt6_info *rt) | |||
48 | ret |= XT_ADDRTYPE_LOCAL; | 69 | ret |= XT_ADDRTYPE_LOCAL; |
49 | if (rt->rt6i_flags & RTF_ANYCAST) | 70 | if (rt->rt6i_flags & RTF_ANYCAST) |
50 | ret |= XT_ADDRTYPE_ANYCAST; | 71 | ret |= XT_ADDRTYPE_ANYCAST; |
72 | |||
73 | |||
74 | dst_release(&rt->dst); | ||
51 | return ret; | 75 | return ret; |
52 | } | 76 | } |
53 | 77 | ||
@@ -65,18 +89,8 @@ static bool match_type6(struct net *net, const struct net_device *dev, | |||
65 | return false; | 89 | return false; |
66 | 90 | ||
67 | if ((XT_ADDRTYPE_LOCAL | XT_ADDRTYPE_ANYCAST | | 91 | if ((XT_ADDRTYPE_LOCAL | XT_ADDRTYPE_ANYCAST | |
68 | XT_ADDRTYPE_UNREACHABLE) & mask) { | 92 | XT_ADDRTYPE_UNREACHABLE) & mask) |
69 | struct rt6_info *rt; | 93 | return !!(mask & match_lookup_rt6(net, dev, addr)); |
70 | u32 type; | ||
71 | int ifindex = dev ? dev->ifindex : 0; | ||
72 | |||
73 | rt = rt6_lookup(net, addr, NULL, ifindex, !!dev); | ||
74 | |||
75 | type = xt_addrtype_rt6_to_type(rt); | ||
76 | |||
77 | dst_release(&rt->dst); | ||
78 | return !!(mask & type); | ||
79 | } | ||
80 | return true; | 94 | return true; |
81 | } | 95 | } |
82 | 96 | ||
diff --git a/net/netfilter/xt_conntrack.c b/net/netfilter/xt_conntrack.c index 2c0086a4751e..61805d7b38aa 100644 --- a/net/netfilter/xt_conntrack.c +++ b/net/netfilter/xt_conntrack.c | |||
@@ -195,7 +195,7 @@ conntrack_mt(const struct sk_buff *skb, struct xt_action_param *par, | |||
195 | return info->match_flags & XT_CONNTRACK_STATE; | 195 | return info->match_flags & XT_CONNTRACK_STATE; |
196 | if ((info->match_flags & XT_CONNTRACK_DIRECTION) && | 196 | if ((info->match_flags & XT_CONNTRACK_DIRECTION) && |
197 | (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) ^ | 197 | (CTINFO2DIR(ctinfo) == IP_CT_DIR_ORIGINAL) ^ |
198 | !!(info->invert_flags & XT_CONNTRACK_DIRECTION)) | 198 | !(info->invert_flags & XT_CONNTRACK_DIRECTION)) |
199 | return false; | 199 | return false; |
200 | 200 | ||
201 | if (info->match_flags & XT_CONNTRACK_ORIGSRC) | 201 | if (info->match_flags & XT_CONNTRACK_ORIGSRC) |
@@ -272,11 +272,6 @@ static int conntrack_mt_check(const struct xt_mtchk_param *par) | |||
272 | { | 272 | { |
273 | int ret; | 273 | int ret; |
274 | 274 | ||
275 | if (strcmp(par->table, "raw") == 0) { | ||
276 | pr_info("state is undetermined at the time of raw table\n"); | ||
277 | return -EINVAL; | ||
278 | } | ||
279 | |||
280 | ret = nf_ct_l3proto_try_module_get(par->family); | 275 | ret = nf_ct_l3proto_try_module_get(par->family); |
281 | if (ret < 0) | 276 | if (ret < 0) |
282 | pr_info("cannot load conntrack support for proto=%u\n", | 277 | pr_info("cannot load conntrack support for proto=%u\n", |
diff --git a/net/netfilter/xt_set.c b/net/netfilter/xt_set.c index 061d48cec137..b3babaed7719 100644 --- a/net/netfilter/xt_set.c +++ b/net/netfilter/xt_set.c | |||
@@ -81,6 +81,7 @@ set_match_v0_checkentry(const struct xt_mtchk_param *par) | |||
81 | if (info->match_set.u.flags[IPSET_DIM_MAX-1] != 0) { | 81 | if (info->match_set.u.flags[IPSET_DIM_MAX-1] != 0) { |
82 | pr_warning("Protocol error: set match dimension " | 82 | pr_warning("Protocol error: set match dimension " |
83 | "is over the limit!\n"); | 83 | "is over the limit!\n"); |
84 | ip_set_nfnl_put(info->match_set.index); | ||
84 | return -ERANGE; | 85 | return -ERANGE; |
85 | } | 86 | } |
86 | 87 | ||
@@ -135,6 +136,8 @@ set_target_v0_checkentry(const struct xt_tgchk_param *par) | |||
135 | if (index == IPSET_INVALID_ID) { | 136 | if (index == IPSET_INVALID_ID) { |
136 | pr_warning("Cannot find del_set index %u as target\n", | 137 | pr_warning("Cannot find del_set index %u as target\n", |
137 | info->del_set.index); | 138 | info->del_set.index); |
139 | if (info->add_set.index != IPSET_INVALID_ID) | ||
140 | ip_set_nfnl_put(info->add_set.index); | ||
138 | return -ENOENT; | 141 | return -ENOENT; |
139 | } | 142 | } |
140 | } | 143 | } |
@@ -142,6 +145,10 @@ set_target_v0_checkentry(const struct xt_tgchk_param *par) | |||
142 | info->del_set.u.flags[IPSET_DIM_MAX-1] != 0) { | 145 | info->del_set.u.flags[IPSET_DIM_MAX-1] != 0) { |
143 | pr_warning("Protocol error: SET target dimension " | 146 | pr_warning("Protocol error: SET target dimension " |
144 | "is over the limit!\n"); | 147 | "is over the limit!\n"); |
148 | if (info->add_set.index != IPSET_INVALID_ID) | ||
149 | ip_set_nfnl_put(info->add_set.index); | ||
150 | if (info->del_set.index != IPSET_INVALID_ID) | ||
151 | ip_set_nfnl_put(info->del_set.index); | ||
145 | return -ERANGE; | 152 | return -ERANGE; |
146 | } | 153 | } |
147 | 154 | ||
@@ -192,6 +199,7 @@ set_match_checkentry(const struct xt_mtchk_param *par) | |||
192 | if (info->match_set.dim > IPSET_DIM_MAX) { | 199 | if (info->match_set.dim > IPSET_DIM_MAX) { |
193 | pr_warning("Protocol error: set match dimension " | 200 | pr_warning("Protocol error: set match dimension " |
194 | "is over the limit!\n"); | 201 | "is over the limit!\n"); |
202 | ip_set_nfnl_put(info->match_set.index); | ||
195 | return -ERANGE; | 203 | return -ERANGE; |
196 | } | 204 | } |
197 | 205 | ||
@@ -219,7 +227,7 @@ set_target(struct sk_buff *skb, const struct xt_action_param *par) | |||
219 | if (info->del_set.index != IPSET_INVALID_ID) | 227 | if (info->del_set.index != IPSET_INVALID_ID) |
220 | ip_set_del(info->del_set.index, | 228 | ip_set_del(info->del_set.index, |
221 | skb, par->family, | 229 | skb, par->family, |
222 | info->add_set.dim, | 230 | info->del_set.dim, |
223 | info->del_set.flags); | 231 | info->del_set.flags); |
224 | 232 | ||
225 | return XT_CONTINUE; | 233 | return XT_CONTINUE; |
@@ -245,13 +253,19 @@ set_target_checkentry(const struct xt_tgchk_param *par) | |||
245 | if (index == IPSET_INVALID_ID) { | 253 | if (index == IPSET_INVALID_ID) { |
246 | pr_warning("Cannot find del_set index %u as target\n", | 254 | pr_warning("Cannot find del_set index %u as target\n", |
247 | info->del_set.index); | 255 | info->del_set.index); |
256 | if (info->add_set.index != IPSET_INVALID_ID) | ||
257 | ip_set_nfnl_put(info->add_set.index); | ||
248 | return -ENOENT; | 258 | return -ENOENT; |
249 | } | 259 | } |
250 | } | 260 | } |
251 | if (info->add_set.dim > IPSET_DIM_MAX || | 261 | if (info->add_set.dim > IPSET_DIM_MAX || |
252 | info->del_set.flags > IPSET_DIM_MAX) { | 262 | info->del_set.dim > IPSET_DIM_MAX) { |
253 | pr_warning("Protocol error: SET target dimension " | 263 | pr_warning("Protocol error: SET target dimension " |
254 | "is over the limit!\n"); | 264 | "is over the limit!\n"); |
265 | if (info->add_set.index != IPSET_INVALID_ID) | ||
266 | ip_set_nfnl_put(info->add_set.index); | ||
267 | if (info->del_set.index != IPSET_INVALID_ID) | ||
268 | ip_set_nfnl_put(info->del_set.index); | ||
255 | return -ERANGE; | 269 | return -ERANGE; |
256 | } | 270 | } |
257 | 271 | ||
diff --git a/net/netlabel/netlabel_cipso_v4.c b/net/netlabel/netlabel_cipso_v4.c index 5f14c8462e30..bae5756b1626 100644 --- a/net/netlabel/netlabel_cipso_v4.c +++ b/net/netlabel/netlabel_cipso_v4.c | |||
@@ -422,7 +422,6 @@ static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info) | |||
422 | 422 | ||
423 | { | 423 | { |
424 | int ret_val = -EINVAL; | 424 | int ret_val = -EINVAL; |
425 | const char *type_str = "(unknown)"; | ||
426 | struct netlbl_audit audit_info; | 425 | struct netlbl_audit audit_info; |
427 | 426 | ||
428 | if (!info->attrs[NLBL_CIPSOV4_A_DOI] || | 427 | if (!info->attrs[NLBL_CIPSOV4_A_DOI] || |
@@ -432,15 +431,12 @@ static int netlbl_cipsov4_add(struct sk_buff *skb, struct genl_info *info) | |||
432 | netlbl_netlink_auditinfo(skb, &audit_info); | 431 | netlbl_netlink_auditinfo(skb, &audit_info); |
433 | switch (nla_get_u32(info->attrs[NLBL_CIPSOV4_A_MTYPE])) { | 432 | switch (nla_get_u32(info->attrs[NLBL_CIPSOV4_A_MTYPE])) { |
434 | case CIPSO_V4_MAP_TRANS: | 433 | case CIPSO_V4_MAP_TRANS: |
435 | type_str = "trans"; | ||
436 | ret_val = netlbl_cipsov4_add_std(info, &audit_info); | 434 | ret_val = netlbl_cipsov4_add_std(info, &audit_info); |
437 | break; | 435 | break; |
438 | case CIPSO_V4_MAP_PASS: | 436 | case CIPSO_V4_MAP_PASS: |
439 | type_str = "pass"; | ||
440 | ret_val = netlbl_cipsov4_add_pass(info, &audit_info); | 437 | ret_val = netlbl_cipsov4_add_pass(info, &audit_info); |
441 | break; | 438 | break; |
442 | case CIPSO_V4_MAP_LOCAL: | 439 | case CIPSO_V4_MAP_LOCAL: |
443 | type_str = "local"; | ||
444 | ret_val = netlbl_cipsov4_add_local(info, &audit_info); | 440 | ret_val = netlbl_cipsov4_add_local(info, &audit_info); |
445 | break; | 441 | break; |
446 | } | 442 | } |
diff --git a/net/netlabel/netlabel_domainhash.c b/net/netlabel/netlabel_domainhash.c index d37b7f80fa37..de0d8e4cbfb6 100644 --- a/net/netlabel/netlabel_domainhash.c +++ b/net/netlabel/netlabel_domainhash.c | |||
@@ -109,7 +109,7 @@ static void netlbl_domhsh_free_entry(struct rcu_head *entry) | |||
109 | * | 109 | * |
110 | * Description: | 110 | * Description: |
111 | * This is the hashing function for the domain hash table, it returns the | 111 | * This is the hashing function for the domain hash table, it returns the |
112 | * correct bucket number for the domain. The caller is responsibile for | 112 | * correct bucket number for the domain. The caller is responsible for |
113 | * ensuring that the hash table is protected with either a RCU read lock or the | 113 | * ensuring that the hash table is protected with either a RCU read lock or the |
114 | * hash table lock. | 114 | * hash table lock. |
115 | * | 115 | * |
@@ -134,7 +134,7 @@ static u32 netlbl_domhsh_hash(const char *key) | |||
134 | * | 134 | * |
135 | * Description: | 135 | * Description: |
136 | * Searches the domain hash table and returns a pointer to the hash table | 136 | * Searches the domain hash table and returns a pointer to the hash table |
137 | * entry if found, otherwise NULL is returned. The caller is responsibile for | 137 | * entry if found, otherwise NULL is returned. The caller is responsible for |
138 | * ensuring that the hash table is protected with either a RCU read lock or the | 138 | * ensuring that the hash table is protected with either a RCU read lock or the |
139 | * hash table lock. | 139 | * hash table lock. |
140 | * | 140 | * |
@@ -165,7 +165,7 @@ static struct netlbl_dom_map *netlbl_domhsh_search(const char *domain) | |||
165 | * Searches the domain hash table and returns a pointer to the hash table | 165 | * Searches the domain hash table and returns a pointer to the hash table |
166 | * entry if an exact match is found, if an exact match is not present in the | 166 | * entry if an exact match is found, if an exact match is not present in the |
167 | * hash table then the default entry is returned if valid otherwise NULL is | 167 | * hash table then the default entry is returned if valid otherwise NULL is |
168 | * returned. The caller is responsibile ensuring that the hash table is | 168 | * returned. The caller is responsible ensuring that the hash table is |
169 | * protected with either a RCU read lock or the hash table lock. | 169 | * protected with either a RCU read lock or the hash table lock. |
170 | * | 170 | * |
171 | */ | 171 | */ |
@@ -193,7 +193,7 @@ static struct netlbl_dom_map *netlbl_domhsh_search_def(const char *domain) | |||
193 | * | 193 | * |
194 | * Description: | 194 | * Description: |
195 | * Generate an audit record for adding a new NetLabel/LSM mapping entry with | 195 | * Generate an audit record for adding a new NetLabel/LSM mapping entry with |
196 | * the given information. Caller is responsibile for holding the necessary | 196 | * the given information. Caller is responsible for holding the necessary |
197 | * locks. | 197 | * locks. |
198 | * | 198 | * |
199 | */ | 199 | */ |
@@ -605,7 +605,7 @@ int netlbl_domhsh_remove_default(struct netlbl_audit *audit_info) | |||
605 | * | 605 | * |
606 | * Description: | 606 | * Description: |
607 | * Look through the domain hash table searching for an entry to match @domain, | 607 | * Look through the domain hash table searching for an entry to match @domain, |
608 | * return a pointer to a copy of the entry or NULL. The caller is responsibile | 608 | * return a pointer to a copy of the entry or NULL. The caller is responsible |
609 | * for ensuring that rcu_read_[un]lock() is called. | 609 | * for ensuring that rcu_read_[un]lock() is called. |
610 | * | 610 | * |
611 | */ | 611 | */ |
diff --git a/net/netlabel/netlabel_mgmt.c b/net/netlabel/netlabel_mgmt.c index 998e85e895d0..4f251b19fbcc 100644 --- a/net/netlabel/netlabel_mgmt.c +++ b/net/netlabel/netlabel_mgmt.c | |||
@@ -259,7 +259,7 @@ add_failure: | |||
259 | * | 259 | * |
260 | * Description: | 260 | * Description: |
261 | * This function is a helper function used by the LISTALL and LISTDEF command | 261 | * This function is a helper function used by the LISTALL and LISTDEF command |
262 | * handlers. The caller is responsibile for ensuring that the RCU read lock | 262 | * handlers. The caller is responsible for ensuring that the RCU read lock |
263 | * is held. Returns zero on success, negative values on failure. | 263 | * is held. Returns zero on success, negative values on failure. |
264 | * | 264 | * |
265 | */ | 265 | */ |
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index 06cb02796a0e..732152f718e0 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c | |||
@@ -591,7 +591,6 @@ static int nr_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
591 | return -EINVAL; | 591 | return -EINVAL; |
592 | } | 592 | } |
593 | if ((dev = nr_dev_get(&addr->fsa_ax25.sax25_call)) == NULL) { | 593 | if ((dev = nr_dev_get(&addr->fsa_ax25.sax25_call)) == NULL) { |
594 | SOCK_DEBUG(sk, "NET/ROM: bind failed: invalid node callsign\n"); | ||
595 | release_sock(sk); | 594 | release_sock(sk); |
596 | return -EADDRNOTAVAIL; | 595 | return -EADDRNOTAVAIL; |
597 | } | 596 | } |
@@ -632,7 +631,7 @@ static int nr_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
632 | sock_reset_flag(sk, SOCK_ZAPPED); | 631 | sock_reset_flag(sk, SOCK_ZAPPED); |
633 | dev_put(dev); | 632 | dev_put(dev); |
634 | release_sock(sk); | 633 | release_sock(sk); |
635 | SOCK_DEBUG(sk, "NET/ROM: socket is bound\n"); | 634 | |
636 | return 0; | 635 | return 0; |
637 | } | 636 | } |
638 | 637 | ||
@@ -1082,8 +1081,6 @@ static int nr_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1082 | sax.sax25_call = nr->dest_addr; | 1081 | sax.sax25_call = nr->dest_addr; |
1083 | } | 1082 | } |
1084 | 1083 | ||
1085 | SOCK_DEBUG(sk, "NET/ROM: sendto: Addresses built.\n"); | ||
1086 | |||
1087 | /* Build a packet - the conventional user limit is 236 bytes. We can | 1084 | /* Build a packet - the conventional user limit is 236 bytes. We can |
1088 | do ludicrously large NetROM frames but must not overflow */ | 1085 | do ludicrously large NetROM frames but must not overflow */ |
1089 | if (len > 65536) { | 1086 | if (len > 65536) { |
@@ -1091,7 +1088,6 @@ static int nr_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1091 | goto out; | 1088 | goto out; |
1092 | } | 1089 | } |
1093 | 1090 | ||
1094 | SOCK_DEBUG(sk, "NET/ROM: sendto: building packet.\n"); | ||
1095 | size = len + NR_NETWORK_LEN + NR_TRANSPORT_LEN; | 1091 | size = len + NR_NETWORK_LEN + NR_TRANSPORT_LEN; |
1096 | 1092 | ||
1097 | if ((skb = sock_alloc_send_skb(sk, size, msg->msg_flags & MSG_DONTWAIT, &err)) == NULL) | 1093 | if ((skb = sock_alloc_send_skb(sk, size, msg->msg_flags & MSG_DONTWAIT, &err)) == NULL) |
@@ -1105,7 +1101,6 @@ static int nr_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1105 | */ | 1101 | */ |
1106 | 1102 | ||
1107 | asmptr = skb_push(skb, NR_TRANSPORT_LEN); | 1103 | asmptr = skb_push(skb, NR_TRANSPORT_LEN); |
1108 | SOCK_DEBUG(sk, "Building NET/ROM Header.\n"); | ||
1109 | 1104 | ||
1110 | /* Build a NET/ROM Transport header */ | 1105 | /* Build a NET/ROM Transport header */ |
1111 | 1106 | ||
@@ -1114,15 +1109,12 @@ static int nr_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1114 | *asmptr++ = 0; /* To be filled in later */ | 1109 | *asmptr++ = 0; /* To be filled in later */ |
1115 | *asmptr++ = 0; /* Ditto */ | 1110 | *asmptr++ = 0; /* Ditto */ |
1116 | *asmptr++ = NR_INFO; | 1111 | *asmptr++ = NR_INFO; |
1117 | SOCK_DEBUG(sk, "Built header.\n"); | ||
1118 | 1112 | ||
1119 | /* | 1113 | /* |
1120 | * Put the data on the end | 1114 | * Put the data on the end |
1121 | */ | 1115 | */ |
1122 | skb_put(skb, len); | 1116 | skb_put(skb, len); |
1123 | 1117 | ||
1124 | SOCK_DEBUG(sk, "NET/ROM: Appending user data\n"); | ||
1125 | |||
1126 | /* User data follows immediately after the NET/ROM transport header */ | 1118 | /* User data follows immediately after the NET/ROM transport header */ |
1127 | if (memcpy_fromiovec(skb_transport_header(skb), msg->msg_iov, len)) { | 1119 | if (memcpy_fromiovec(skb_transport_header(skb), msg->msg_iov, len)) { |
1128 | kfree_skb(skb); | 1120 | kfree_skb(skb); |
@@ -1130,8 +1122,6 @@ static int nr_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1130 | goto out; | 1122 | goto out; |
1131 | } | 1123 | } |
1132 | 1124 | ||
1133 | SOCK_DEBUG(sk, "NET/ROM: Transmitting buffer\n"); | ||
1134 | |||
1135 | if (sk->sk_state != TCP_ESTABLISHED) { | 1125 | if (sk->sk_state != TCP_ESTABLISHED) { |
1136 | kfree_skb(skb); | 1126 | kfree_skb(skb); |
1137 | err = -ENOTCONN; | 1127 | err = -ENOTCONN; |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index b5362e96022b..549527bca87a 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -538,7 +538,7 @@ static inline unsigned int run_filter(const struct sk_buff *skb, | |||
538 | rcu_read_lock(); | 538 | rcu_read_lock(); |
539 | filter = rcu_dereference(sk->sk_filter); | 539 | filter = rcu_dereference(sk->sk_filter); |
540 | if (filter != NULL) | 540 | if (filter != NULL) |
541 | res = sk_run_filter(skb, filter->insns); | 541 | res = SK_RUN_FILTER(filter, skb); |
542 | rcu_read_unlock(); | 542 | rcu_read_unlock(); |
543 | 543 | ||
544 | return res; | 544 | return res; |
diff --git a/net/phonet/pn_dev.c b/net/phonet/pn_dev.c index 947038ddd04c..47b3452675b6 100644 --- a/net/phonet/pn_dev.c +++ b/net/phonet/pn_dev.c | |||
@@ -426,18 +426,14 @@ int phonet_route_del(struct net_device *dev, u8 daddr) | |||
426 | return 0; | 426 | return 0; |
427 | } | 427 | } |
428 | 428 | ||
429 | struct net_device *phonet_route_get(struct net *net, u8 daddr) | 429 | struct net_device *phonet_route_get_rcu(struct net *net, u8 daddr) |
430 | { | 430 | { |
431 | struct phonet_net *pnn = phonet_pernet(net); | 431 | struct phonet_net *pnn = phonet_pernet(net); |
432 | struct phonet_routes *routes = &pnn->routes; | 432 | struct phonet_routes *routes = &pnn->routes; |
433 | struct net_device *dev; | 433 | struct net_device *dev; |
434 | 434 | ||
435 | ASSERT_RTNL(); /* no need to hold the device */ | ||
436 | |||
437 | daddr >>= 2; | 435 | daddr >>= 2; |
438 | rcu_read_lock(); | ||
439 | dev = rcu_dereference(routes->table[daddr]); | 436 | dev = rcu_dereference(routes->table[daddr]); |
440 | rcu_read_unlock(); | ||
441 | return dev; | 437 | return dev; |
442 | } | 438 | } |
443 | 439 | ||
diff --git a/net/phonet/pn_netlink.c b/net/phonet/pn_netlink.c index 58b3b1f991ed..438accb7a5a8 100644 --- a/net/phonet/pn_netlink.c +++ b/net/phonet/pn_netlink.c | |||
@@ -264,10 +264,11 @@ static int route_dumpit(struct sk_buff *skb, struct netlink_callback *cb) | |||
264 | struct net *net = sock_net(skb->sk); | 264 | struct net *net = sock_net(skb->sk); |
265 | u8 addr, addr_idx = 0, addr_start_idx = cb->args[0]; | 265 | u8 addr, addr_idx = 0, addr_start_idx = cb->args[0]; |
266 | 266 | ||
267 | rcu_read_lock(); | ||
267 | for (addr = 0; addr < 64; addr++) { | 268 | for (addr = 0; addr < 64; addr++) { |
268 | struct net_device *dev; | 269 | struct net_device *dev; |
269 | 270 | ||
270 | dev = phonet_route_get(net, addr << 2); | 271 | dev = phonet_route_get_rcu(net, addr << 2); |
271 | if (!dev) | 272 | if (!dev) |
272 | continue; | 273 | continue; |
273 | 274 | ||
@@ -279,6 +280,7 @@ static int route_dumpit(struct sk_buff *skb, struct netlink_callback *cb) | |||
279 | } | 280 | } |
280 | 281 | ||
281 | out: | 282 | out: |
283 | rcu_read_unlock(); | ||
282 | cb->args[0] = addr_idx; | 284 | cb->args[0] = addr_idx; |
283 | cb->args[1] = 0; | 285 | cb->args[1] = 0; |
284 | 286 | ||
diff --git a/net/phonet/socket.c b/net/phonet/socket.c index b1adafab377c..8c5bfcef92cb 100644 --- a/net/phonet/socket.c +++ b/net/phonet/socket.c | |||
@@ -52,7 +52,7 @@ static int pn_socket_release(struct socket *sock) | |||
52 | 52 | ||
53 | static struct { | 53 | static struct { |
54 | struct hlist_head hlist[PN_HASHSIZE]; | 54 | struct hlist_head hlist[PN_HASHSIZE]; |
55 | spinlock_t lock; | 55 | struct mutex lock; |
56 | } pnsocks; | 56 | } pnsocks; |
57 | 57 | ||
58 | void __init pn_sock_init(void) | 58 | void __init pn_sock_init(void) |
@@ -61,7 +61,7 @@ void __init pn_sock_init(void) | |||
61 | 61 | ||
62 | for (i = 0; i < PN_HASHSIZE; i++) | 62 | for (i = 0; i < PN_HASHSIZE; i++) |
63 | INIT_HLIST_HEAD(pnsocks.hlist + i); | 63 | INIT_HLIST_HEAD(pnsocks.hlist + i); |
64 | spin_lock_init(&pnsocks.lock); | 64 | mutex_init(&pnsocks.lock); |
65 | } | 65 | } |
66 | 66 | ||
67 | static struct hlist_head *pn_hash_list(u16 obj) | 67 | static struct hlist_head *pn_hash_list(u16 obj) |
@@ -82,9 +82,8 @@ struct sock *pn_find_sock_by_sa(struct net *net, const struct sockaddr_pn *spn) | |||
82 | u8 res = spn->spn_resource; | 82 | u8 res = spn->spn_resource; |
83 | struct hlist_head *hlist = pn_hash_list(obj); | 83 | struct hlist_head *hlist = pn_hash_list(obj); |
84 | 84 | ||
85 | spin_lock_bh(&pnsocks.lock); | 85 | rcu_read_lock(); |
86 | 86 | sk_for_each_rcu(sknode, node, hlist) { | |
87 | sk_for_each(sknode, node, hlist) { | ||
88 | struct pn_sock *pn = pn_sk(sknode); | 87 | struct pn_sock *pn = pn_sk(sknode); |
89 | BUG_ON(!pn->sobject); /* unbound socket */ | 88 | BUG_ON(!pn->sobject); /* unbound socket */ |
90 | 89 | ||
@@ -107,8 +106,7 @@ struct sock *pn_find_sock_by_sa(struct net *net, const struct sockaddr_pn *spn) | |||
107 | sock_hold(sknode); | 106 | sock_hold(sknode); |
108 | break; | 107 | break; |
109 | } | 108 | } |
110 | 109 | rcu_read_unlock(); | |
111 | spin_unlock_bh(&pnsocks.lock); | ||
112 | 110 | ||
113 | return rval; | 111 | return rval; |
114 | } | 112 | } |
@@ -119,7 +117,7 @@ void pn_deliver_sock_broadcast(struct net *net, struct sk_buff *skb) | |||
119 | struct hlist_head *hlist = pnsocks.hlist; | 117 | struct hlist_head *hlist = pnsocks.hlist; |
120 | unsigned h; | 118 | unsigned h; |
121 | 119 | ||
122 | spin_lock(&pnsocks.lock); | 120 | rcu_read_lock(); |
123 | for (h = 0; h < PN_HASHSIZE; h++) { | 121 | for (h = 0; h < PN_HASHSIZE; h++) { |
124 | struct hlist_node *node; | 122 | struct hlist_node *node; |
125 | struct sock *sknode; | 123 | struct sock *sknode; |
@@ -140,25 +138,26 @@ void pn_deliver_sock_broadcast(struct net *net, struct sk_buff *skb) | |||
140 | } | 138 | } |
141 | hlist++; | 139 | hlist++; |
142 | } | 140 | } |
143 | spin_unlock(&pnsocks.lock); | 141 | rcu_read_unlock(); |
144 | } | 142 | } |
145 | 143 | ||
146 | void pn_sock_hash(struct sock *sk) | 144 | void pn_sock_hash(struct sock *sk) |
147 | { | 145 | { |
148 | struct hlist_head *hlist = pn_hash_list(pn_sk(sk)->sobject); | 146 | struct hlist_head *hlist = pn_hash_list(pn_sk(sk)->sobject); |
149 | 147 | ||
150 | spin_lock_bh(&pnsocks.lock); | 148 | mutex_lock(&pnsocks.lock); |
151 | sk_add_node(sk, hlist); | 149 | sk_add_node_rcu(sk, hlist); |
152 | spin_unlock_bh(&pnsocks.lock); | 150 | mutex_unlock(&pnsocks.lock); |
153 | } | 151 | } |
154 | EXPORT_SYMBOL(pn_sock_hash); | 152 | EXPORT_SYMBOL(pn_sock_hash); |
155 | 153 | ||
156 | void pn_sock_unhash(struct sock *sk) | 154 | void pn_sock_unhash(struct sock *sk) |
157 | { | 155 | { |
158 | spin_lock_bh(&pnsocks.lock); | 156 | mutex_lock(&pnsocks.lock); |
159 | sk_del_node_init(sk); | 157 | sk_del_node_init_rcu(sk); |
160 | spin_unlock_bh(&pnsocks.lock); | 158 | mutex_unlock(&pnsocks.lock); |
161 | pn_sock_unbind_all_res(sk); | 159 | pn_sock_unbind_all_res(sk); |
160 | synchronize_rcu(); | ||
162 | } | 161 | } |
163 | EXPORT_SYMBOL(pn_sock_unhash); | 162 | EXPORT_SYMBOL(pn_sock_unhash); |
164 | 163 | ||
@@ -548,7 +547,7 @@ static struct sock *pn_sock_get_idx(struct seq_file *seq, loff_t pos) | |||
548 | unsigned h; | 547 | unsigned h; |
549 | 548 | ||
550 | for (h = 0; h < PN_HASHSIZE; h++) { | 549 | for (h = 0; h < PN_HASHSIZE; h++) { |
551 | sk_for_each(sknode, node, hlist) { | 550 | sk_for_each_rcu(sknode, node, hlist) { |
552 | if (!net_eq(net, sock_net(sknode))) | 551 | if (!net_eq(net, sock_net(sknode))) |
553 | continue; | 552 | continue; |
554 | if (!pos) | 553 | if (!pos) |
@@ -572,9 +571,9 @@ static struct sock *pn_sock_get_next(struct seq_file *seq, struct sock *sk) | |||
572 | } | 571 | } |
573 | 572 | ||
574 | static void *pn_sock_seq_start(struct seq_file *seq, loff_t *pos) | 573 | static void *pn_sock_seq_start(struct seq_file *seq, loff_t *pos) |
575 | __acquires(pnsocks.lock) | 574 | __acquires(rcu) |
576 | { | 575 | { |
577 | spin_lock_bh(&pnsocks.lock); | 576 | rcu_read_lock(); |
578 | return *pos ? pn_sock_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; | 577 | return *pos ? pn_sock_get_idx(seq, *pos - 1) : SEQ_START_TOKEN; |
579 | } | 578 | } |
580 | 579 | ||
@@ -591,9 +590,9 @@ static void *pn_sock_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
591 | } | 590 | } |
592 | 591 | ||
593 | static void pn_sock_seq_stop(struct seq_file *seq, void *v) | 592 | static void pn_sock_seq_stop(struct seq_file *seq, void *v) |
594 | __releases(pnsocks.lock) | 593 | __releases(rcu) |
595 | { | 594 | { |
596 | spin_unlock_bh(&pnsocks.lock); | 595 | rcu_read_unlock(); |
597 | } | 596 | } |
598 | 597 | ||
599 | static int pn_sock_seq_show(struct seq_file *seq, void *v) | 598 | static int pn_sock_seq_show(struct seq_file *seq, void *v) |
@@ -721,13 +720,11 @@ void pn_sock_unbind_all_res(struct sock *sk) | |||
721 | } | 720 | } |
722 | mutex_unlock(&resource_mutex); | 721 | mutex_unlock(&resource_mutex); |
723 | 722 | ||
724 | if (match == 0) | ||
725 | return; | ||
726 | synchronize_rcu(); | ||
727 | while (match > 0) { | 723 | while (match > 0) { |
728 | sock_put(sk); | 724 | __sock_put(sk); |
729 | match--; | 725 | match--; |
730 | } | 726 | } |
727 | /* Caller is responsible for RCU sync before final sock_put() */ | ||
731 | } | 728 | } |
732 | 729 | ||
733 | #ifdef CONFIG_PROC_FS | 730 | #ifdef CONFIG_PROC_FS |
diff --git a/net/rds/ib_send.c b/net/rds/ib_send.c index c47a511f203d..7c4dce8fa5e6 100644 --- a/net/rds/ib_send.c +++ b/net/rds/ib_send.c | |||
@@ -355,7 +355,7 @@ void rds_ib_send_cq_comp_handler(struct ib_cq *cq, void *context) | |||
355 | * | 355 | * |
356 | * Conceptually, we have two counters: | 356 | * Conceptually, we have two counters: |
357 | * - send credits: this tells us how many WRs we're allowed | 357 | * - send credits: this tells us how many WRs we're allowed |
358 | * to submit without overruning the reciever's queue. For | 358 | * to submit without overruning the receiver's queue. For |
359 | * each SEND WR we post, we decrement this by one. | 359 | * each SEND WR we post, we decrement this by one. |
360 | * | 360 | * |
361 | * - posted credits: this tells us how many WRs we recently | 361 | * - posted credits: this tells us how many WRs we recently |
diff --git a/net/rds/iw_cm.c b/net/rds/iw_cm.c index 712cf2d1f28e..3a60a15d1b4a 100644 --- a/net/rds/iw_cm.c +++ b/net/rds/iw_cm.c | |||
@@ -181,7 +181,7 @@ static int rds_iw_init_qp_attrs(struct ib_qp_init_attr *attr, | |||
181 | unsigned int send_size, recv_size; | 181 | unsigned int send_size, recv_size; |
182 | int ret; | 182 | int ret; |
183 | 183 | ||
184 | /* The offset of 1 is to accomodate the additional ACK WR. */ | 184 | /* The offset of 1 is to accommodate the additional ACK WR. */ |
185 | send_size = min_t(unsigned int, rds_iwdev->max_wrs, rds_iw_sysctl_max_send_wr + 1); | 185 | send_size = min_t(unsigned int, rds_iwdev->max_wrs, rds_iw_sysctl_max_send_wr + 1); |
186 | recv_size = min_t(unsigned int, rds_iwdev->max_wrs, rds_iw_sysctl_max_recv_wr + 1); | 186 | recv_size = min_t(unsigned int, rds_iwdev->max_wrs, rds_iw_sysctl_max_recv_wr + 1); |
187 | rds_iw_ring_resize(send_ring, send_size - 1); | 187 | rds_iw_ring_resize(send_ring, send_size - 1); |
diff --git a/net/rds/iw_rdma.c b/net/rds/iw_rdma.c index 59509e9a9e72..6deaa77495e3 100644 --- a/net/rds/iw_rdma.c +++ b/net/rds/iw_rdma.c | |||
@@ -122,7 +122,7 @@ static int rds_iw_get_device(struct rds_sock *rs, struct rds_iw_device **rds_iwd | |||
122 | #else | 122 | #else |
123 | /* FIXME - needs to compare the local and remote | 123 | /* FIXME - needs to compare the local and remote |
124 | * ipaddr/port tuple, but the ipaddr is the only | 124 | * ipaddr/port tuple, but the ipaddr is the only |
125 | * available infomation in the rds_sock (as the rest are | 125 | * available information in the rds_sock (as the rest are |
126 | * zero'ed. It doesn't appear to be properly populated | 126 | * zero'ed. It doesn't appear to be properly populated |
127 | * during connection setup... | 127 | * during connection setup... |
128 | */ | 128 | */ |
diff --git a/net/rds/iw_send.c b/net/rds/iw_send.c index 6280ea020d4e..545d8ee3efb1 100644 --- a/net/rds/iw_send.c +++ b/net/rds/iw_send.c | |||
@@ -307,7 +307,7 @@ void rds_iw_send_cq_comp_handler(struct ib_cq *cq, void *context) | |||
307 | * | 307 | * |
308 | * Conceptually, we have two counters: | 308 | * Conceptually, we have two counters: |
309 | * - send credits: this tells us how many WRs we're allowed | 309 | * - send credits: this tells us how many WRs we're allowed |
310 | * to submit without overruning the reciever's queue. For | 310 | * to submit without overruning the receiver's queue. For |
311 | * each SEND WR we post, we decrement this by one. | 311 | * each SEND WR we post, we decrement this by one. |
312 | * | 312 | * |
313 | * - posted credits: this tells us how many WRs we recently | 313 | * - posted credits: this tells us how many WRs we recently |
diff --git a/net/rds/send.c b/net/rds/send.c index 35b9c2e9caf1..d58ae5f9339e 100644 --- a/net/rds/send.c +++ b/net/rds/send.c | |||
@@ -116,7 +116,7 @@ static void release_in_xmit(struct rds_connection *conn) | |||
116 | } | 116 | } |
117 | 117 | ||
118 | /* | 118 | /* |
119 | * We're making the concious trade-off here to only send one message | 119 | * We're making the conscious trade-off here to only send one message |
120 | * down the connection at a time. | 120 | * down the connection at a time. |
121 | * Pro: | 121 | * Pro: |
122 | * - tx queueing is a simple fifo list | 122 | * - tx queueing is a simple fifo list |
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index a80aef6e3d1f..f9ea925ad9cb 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c | |||
@@ -682,10 +682,8 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
682 | if ((unsigned int) addr->srose_ndigis > ROSE_MAX_DIGIS) | 682 | if ((unsigned int) addr->srose_ndigis > ROSE_MAX_DIGIS) |
683 | return -EINVAL; | 683 | return -EINVAL; |
684 | 684 | ||
685 | if ((dev = rose_dev_get(&addr->srose_addr)) == NULL) { | 685 | if ((dev = rose_dev_get(&addr->srose_addr)) == NULL) |
686 | SOCK_DEBUG(sk, "ROSE: bind failed: invalid address\n"); | ||
687 | return -EADDRNOTAVAIL; | 686 | return -EADDRNOTAVAIL; |
688 | } | ||
689 | 687 | ||
690 | source = &addr->srose_call; | 688 | source = &addr->srose_call; |
691 | 689 | ||
@@ -716,7 +714,7 @@ static int rose_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
716 | rose_insert_socket(sk); | 714 | rose_insert_socket(sk); |
717 | 715 | ||
718 | sock_reset_flag(sk, SOCK_ZAPPED); | 716 | sock_reset_flag(sk, SOCK_ZAPPED); |
719 | SOCK_DEBUG(sk, "ROSE: socket is bound\n"); | 717 | |
720 | return 0; | 718 | return 0; |
721 | } | 719 | } |
722 | 720 | ||
@@ -1109,10 +1107,7 @@ static int rose_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1109 | srose.srose_digis[n] = rose->dest_digis[n]; | 1107 | srose.srose_digis[n] = rose->dest_digis[n]; |
1110 | } | 1108 | } |
1111 | 1109 | ||
1112 | SOCK_DEBUG(sk, "ROSE: sendto: Addresses built.\n"); | ||
1113 | |||
1114 | /* Build a packet */ | 1110 | /* Build a packet */ |
1115 | SOCK_DEBUG(sk, "ROSE: sendto: building packet.\n"); | ||
1116 | /* Sanity check the packet size */ | 1111 | /* Sanity check the packet size */ |
1117 | if (len > 65535) | 1112 | if (len > 65535) |
1118 | return -EMSGSIZE; | 1113 | return -EMSGSIZE; |
@@ -1127,7 +1122,6 @@ static int rose_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1127 | /* | 1122 | /* |
1128 | * Put the data on the end | 1123 | * Put the data on the end |
1129 | */ | 1124 | */ |
1130 | SOCK_DEBUG(sk, "ROSE: Appending user data\n"); | ||
1131 | 1125 | ||
1132 | skb_reset_transport_header(skb); | 1126 | skb_reset_transport_header(skb); |
1133 | skb_put(skb, len); | 1127 | skb_put(skb, len); |
@@ -1152,8 +1146,6 @@ static int rose_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1152 | */ | 1146 | */ |
1153 | asmptr = skb_push(skb, ROSE_MIN_LEN); | 1147 | asmptr = skb_push(skb, ROSE_MIN_LEN); |
1154 | 1148 | ||
1155 | SOCK_DEBUG(sk, "ROSE: Building Network Header.\n"); | ||
1156 | |||
1157 | /* Build a ROSE Network header */ | 1149 | /* Build a ROSE Network header */ |
1158 | asmptr[0] = ((rose->lci >> 8) & 0x0F) | ROSE_GFI; | 1150 | asmptr[0] = ((rose->lci >> 8) & 0x0F) | ROSE_GFI; |
1159 | asmptr[1] = (rose->lci >> 0) & 0xFF; | 1151 | asmptr[1] = (rose->lci >> 0) & 0xFF; |
@@ -1162,10 +1154,6 @@ static int rose_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1162 | if (qbit) | 1154 | if (qbit) |
1163 | asmptr[0] |= ROSE_Q_BIT; | 1155 | asmptr[0] |= ROSE_Q_BIT; |
1164 | 1156 | ||
1165 | SOCK_DEBUG(sk, "ROSE: Built header.\n"); | ||
1166 | |||
1167 | SOCK_DEBUG(sk, "ROSE: Transmitting buffer\n"); | ||
1168 | |||
1169 | if (sk->sk_state != TCP_ESTABLISHED) { | 1157 | if (sk->sk_state != TCP_ESTABLISHED) { |
1170 | kfree_skb(skb); | 1158 | kfree_skb(skb); |
1171 | return -ENOTCONN; | 1159 | return -ENOTCONN; |
diff --git a/net/rose/rose_route.c b/net/rose/rose_route.c index 08dcd2f29cdc..479cae57d187 100644 --- a/net/rose/rose_route.c +++ b/net/rose/rose_route.c | |||
@@ -587,7 +587,7 @@ static int rose_clear_routes(void) | |||
587 | 587 | ||
588 | /* | 588 | /* |
589 | * Check that the device given is a valid AX.25 interface that is "up". | 589 | * Check that the device given is a valid AX.25 interface that is "up". |
590 | * called whith RTNL | 590 | * called with RTNL |
591 | */ | 591 | */ |
592 | static struct net_device *rose_ax25_dev_find(char *devname) | 592 | static struct net_device *rose_ax25_dev_find(char *devname) |
593 | { | 593 | { |
diff --git a/net/rxrpc/ar-peer.c b/net/rxrpc/ar-peer.c index 55b93dc60d0c..b6ff06351d67 100644 --- a/net/rxrpc/ar-peer.c +++ b/net/rxrpc/ar-peer.c | |||
@@ -36,10 +36,11 @@ static void rxrpc_destroy_peer(struct work_struct *work); | |||
36 | static void rxrpc_assess_MTU_size(struct rxrpc_peer *peer) | 36 | static void rxrpc_assess_MTU_size(struct rxrpc_peer *peer) |
37 | { | 37 | { |
38 | struct rtable *rt; | 38 | struct rtable *rt; |
39 | struct flowi4 fl4; | ||
39 | 40 | ||
40 | peer->if_mtu = 1500; | 41 | peer->if_mtu = 1500; |
41 | 42 | ||
42 | rt = ip_route_output_ports(&init_net, NULL, | 43 | rt = ip_route_output_ports(&init_net, &fl4, NULL, |
43 | peer->srx.transport.sin.sin_addr.s_addr, 0, | 44 | peer->srx.transport.sin.sin_addr.s_addr, 0, |
44 | htons(7000), htons(7001), | 45 | htons(7000), htons(7001), |
45 | IPPROTO_UDP, 0, 0); | 46 | IPPROTO_UDP, 0, 0); |
diff --git a/net/sched/Kconfig b/net/sched/Kconfig index a7a5583d4f68..aeaa2110b699 100644 --- a/net/sched/Kconfig +++ b/net/sched/Kconfig | |||
@@ -239,6 +239,17 @@ config NET_SCH_CHOKE | |||
239 | To compile this code as a module, choose M here: the | 239 | To compile this code as a module, choose M here: the |
240 | module will be called sch_choke. | 240 | module will be called sch_choke. |
241 | 241 | ||
242 | config NET_SCH_QFQ | ||
243 | tristate "Quick Fair Queueing scheduler (QFQ)" | ||
244 | help | ||
245 | Say Y here if you want to use the Quick Fair Queueing Scheduler (QFQ) | ||
246 | packet scheduling algorithm. | ||
247 | |||
248 | To compile this driver as a module, choose M here: the module | ||
249 | will be called sch_qfq. | ||
250 | |||
251 | If unsure, say N. | ||
252 | |||
242 | config NET_SCH_INGRESS | 253 | config NET_SCH_INGRESS |
243 | tristate "Ingress Qdisc" | 254 | tristate "Ingress Qdisc" |
244 | depends on NET_CLS_ACT | 255 | depends on NET_CLS_ACT |
diff --git a/net/sched/Makefile b/net/sched/Makefile index 2e77b8dba22e..dc5889c0a15a 100644 --- a/net/sched/Makefile +++ b/net/sched/Makefile | |||
@@ -35,6 +35,7 @@ obj-$(CONFIG_NET_SCH_NETEM) += sch_netem.o | |||
35 | obj-$(CONFIG_NET_SCH_DRR) += sch_drr.o | 35 | obj-$(CONFIG_NET_SCH_DRR) += sch_drr.o |
36 | obj-$(CONFIG_NET_SCH_MQPRIO) += sch_mqprio.o | 36 | obj-$(CONFIG_NET_SCH_MQPRIO) += sch_mqprio.o |
37 | obj-$(CONFIG_NET_SCH_CHOKE) += sch_choke.o | 37 | obj-$(CONFIG_NET_SCH_CHOKE) += sch_choke.o |
38 | obj-$(CONFIG_NET_SCH_QFQ) += sch_qfq.o | ||
38 | 39 | ||
39 | obj-$(CONFIG_NET_CLS_U32) += cls_u32.o | 40 | obj-$(CONFIG_NET_CLS_U32) += cls_u32.o |
40 | obj-$(CONFIG_NET_CLS_ROUTE4) += cls_route.o | 41 | obj-$(CONFIG_NET_CLS_ROUTE4) += cls_route.o |
diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 15873e14cb54..14b42f4ad791 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c | |||
@@ -999,7 +999,7 @@ static int tc_ctl_action(struct sk_buff *skb, struct nlmsghdr *n, void *arg) | |||
999 | switch (n->nlmsg_type) { | 999 | switch (n->nlmsg_type) { |
1000 | case RTM_NEWACTION: | 1000 | case RTM_NEWACTION: |
1001 | /* we are going to assume all other flags | 1001 | /* we are going to assume all other flags |
1002 | * imply create only if it doesnt exist | 1002 | * imply create only if it doesn't exist |
1003 | * Note that CREATE | EXCL implies that | 1003 | * Note that CREATE | EXCL implies that |
1004 | * but since we want avoid ambiguity (eg when flags | 1004 | * but since we want avoid ambiguity (eg when flags |
1005 | * is zero) then just set this | 1005 | * is zero) then just set this |
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c index 50c7c06c019d..7affe9a92757 100644 --- a/net/sched/act_pedit.c +++ b/net/sched/act_pedit.c | |||
@@ -161,7 +161,7 @@ static int tcf_pedit(struct sk_buff *skb, struct tc_action *a, | |||
161 | } | 161 | } |
162 | if (offset > 0 && offset > skb->len) { | 162 | if (offset > 0 && offset > skb->len) { |
163 | pr_info("tc filter pedit" | 163 | pr_info("tc filter pedit" |
164 | " offset %d cant exceed pkt length %d\n", | 164 | " offset %d can't exceed pkt length %d\n", |
165 | offset, skb->len); | 165 | offset, skb->len); |
166 | goto bad; | 166 | goto bad; |
167 | } | 167 | } |
diff --git a/net/sched/em_meta.c b/net/sched/em_meta.c index a4de67eca824..49130e8abff0 100644 --- a/net/sched/em_meta.c +++ b/net/sched/em_meta.c | |||
@@ -47,7 +47,7 @@ | |||
47 | * on the meta type. Obviously, the length of the data must also | 47 | * on the meta type. Obviously, the length of the data must also |
48 | * be provided for non-numeric types. | 48 | * be provided for non-numeric types. |
49 | * | 49 | * |
50 | * Additionaly, type dependant modifiers such as shift operators | 50 | * Additionally, type dependent modifiers such as shift operators |
51 | * or mask may be applied to extend the functionaliy. As of now, | 51 | * or mask may be applied to extend the functionaliy. As of now, |
52 | * the variable length type supports shifting the byte string to | 52 | * the variable length type supports shifting the byte string to |
53 | * the right, eating up any number of octets and thus supporting | 53 | * the right, eating up any number of octets and thus supporting |
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index e1429a85091f..29b942ce9e82 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c | |||
@@ -183,7 +183,7 @@ static inline struct htb_class *htb_find(u32 handle, struct Qdisc *sch) | |||
183 | * filters in qdisc and in inner nodes (if higher filter points to the inner | 183 | * filters in qdisc and in inner nodes (if higher filter points to the inner |
184 | * node). If we end up with classid MAJOR:0 we enqueue the skb into special | 184 | * node). If we end up with classid MAJOR:0 we enqueue the skb into special |
185 | * internal fifo (direct). These packets then go directly thru. If we still | 185 | * internal fifo (direct). These packets then go directly thru. If we still |
186 | * have no valid leaf we try to use MAJOR:default leaf. It still unsuccessfull | 186 | * have no valid leaf we try to use MAJOR:default leaf. It still unsuccessful |
187 | * then finish and return direct queue. | 187 | * then finish and return direct queue. |
188 | */ | 188 | */ |
189 | #define HTB_DIRECT ((struct htb_class *)-1L) | 189 | #define HTB_DIRECT ((struct htb_class *)-1L) |
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index edbbf7ad6623..69c35f6cd13f 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c | |||
@@ -160,7 +160,7 @@ static bool loss_4state(struct netem_sched_data *q) | |||
160 | u32 rnd = net_random(); | 160 | u32 rnd = net_random(); |
161 | 161 | ||
162 | /* | 162 | /* |
163 | * Makes a comparision between rnd and the transition | 163 | * Makes a comparison between rnd and the transition |
164 | * probabilities outgoing from the current state, then decides the | 164 | * probabilities outgoing from the current state, then decides the |
165 | * next state and if the next packet has to be transmitted or lost. | 165 | * next state and if the next packet has to be transmitted or lost. |
166 | * The four states correspond to: | 166 | * The four states correspond to: |
@@ -212,9 +212,9 @@ static bool loss_4state(struct netem_sched_data *q) | |||
212 | * Generates losses according to the Gilbert-Elliot loss model or | 212 | * Generates losses according to the Gilbert-Elliot loss model or |
213 | * its special cases (Gilbert or Simple Gilbert) | 213 | * its special cases (Gilbert or Simple Gilbert) |
214 | * | 214 | * |
215 | * Makes a comparision between random number and the transition | 215 | * Makes a comparison between random number and the transition |
216 | * probabilities outgoing from the current state, then decides the | 216 | * probabilities outgoing from the current state, then decides the |
217 | * next state. A second random number is extracted and the comparision | 217 | * next state. A second random number is extracted and the comparison |
218 | * with the loss probability of the current state decides if the next | 218 | * with the loss probability of the current state decides if the next |
219 | * packet will be transmitted or lost. | 219 | * packet will be transmitted or lost. |
220 | */ | 220 | */ |
diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c new file mode 100644 index 000000000000..103343408593 --- /dev/null +++ b/net/sched/sch_qfq.c | |||
@@ -0,0 +1,1137 @@ | |||
1 | /* | ||
2 | * net/sched/sch_qfq.c Quick Fair Queueing Scheduler. | ||
3 | * | ||
4 | * Copyright (c) 2009 Fabio Checconi, Luigi Rizzo, and Paolo Valente. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * version 2 as published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/bitops.h> | ||
14 | #include <linux/errno.h> | ||
15 | #include <linux/netdevice.h> | ||
16 | #include <linux/pkt_sched.h> | ||
17 | #include <net/sch_generic.h> | ||
18 | #include <net/pkt_sched.h> | ||
19 | #include <net/pkt_cls.h> | ||
20 | |||
21 | |||
22 | /* Quick Fair Queueing | ||
23 | =================== | ||
24 | |||
25 | Sources: | ||
26 | |||
27 | Fabio Checconi, Luigi Rizzo, and Paolo Valente: "QFQ: Efficient | ||
28 | Packet Scheduling with Tight Bandwidth Distribution Guarantees." | ||
29 | |||
30 | See also: | ||
31 | http://retis.sssup.it/~fabio/linux/qfq/ | ||
32 | */ | ||
33 | |||
34 | /* | ||
35 | |||
36 | Virtual time computations. | ||
37 | |||
38 | S, F and V are all computed in fixed point arithmetic with | ||
39 | FRAC_BITS decimal bits. | ||
40 | |||
41 | QFQ_MAX_INDEX is the maximum index allowed for a group. We need | ||
42 | one bit per index. | ||
43 | QFQ_MAX_WSHIFT is the maximum power of two supported as a weight. | ||
44 | |||
45 | The layout of the bits is as below: | ||
46 | |||
47 | [ MTU_SHIFT ][ FRAC_BITS ] | ||
48 | [ MAX_INDEX ][ MIN_SLOT_SHIFT ] | ||
49 | ^.__grp->index = 0 | ||
50 | *.__grp->slot_shift | ||
51 | |||
52 | where MIN_SLOT_SHIFT is derived by difference from the others. | ||
53 | |||
54 | The max group index corresponds to Lmax/w_min, where | ||
55 | Lmax=1<<MTU_SHIFT, w_min = 1 . | ||
56 | From this, and knowing how many groups (MAX_INDEX) we want, | ||
57 | we can derive the shift corresponding to each group. | ||
58 | |||
59 | Because we often need to compute | ||
60 | F = S + len/w_i and V = V + len/wsum | ||
61 | instead of storing w_i store the value | ||
62 | inv_w = (1<<FRAC_BITS)/w_i | ||
63 | so we can do F = S + len * inv_w * wsum. | ||
64 | We use W_TOT in the formulas so we can easily move between | ||
65 | static and adaptive weight sum. | ||
66 | |||
67 | The per-scheduler-instance data contain all the data structures | ||
68 | for the scheduler: bitmaps and bucket lists. | ||
69 | |||
70 | */ | ||
71 | |||
72 | /* | ||
73 | * Maximum number of consecutive slots occupied by backlogged classes | ||
74 | * inside a group. | ||
75 | */ | ||
76 | #define QFQ_MAX_SLOTS 32 | ||
77 | |||
78 | /* | ||
79 | * Shifts used for class<->group mapping. We allow class weights that are | ||
80 | * in the range [1, 2^MAX_WSHIFT], and we try to map each class i to the | ||
81 | * group with the smallest index that can support the L_i / r_i configured | ||
82 | * for the class. | ||
83 | * | ||
84 | * grp->index is the index of the group; and grp->slot_shift | ||
85 | * is the shift for the corresponding (scaled) sigma_i. | ||
86 | */ | ||
87 | #define QFQ_MAX_INDEX 19 | ||
88 | #define QFQ_MAX_WSHIFT 16 | ||
89 | |||
90 | #define QFQ_MAX_WEIGHT (1<<QFQ_MAX_WSHIFT) | ||
91 | #define QFQ_MAX_WSUM (2*QFQ_MAX_WEIGHT) | ||
92 | |||
93 | #define FRAC_BITS 30 /* fixed point arithmetic */ | ||
94 | #define ONE_FP (1UL << FRAC_BITS) | ||
95 | #define IWSUM (ONE_FP/QFQ_MAX_WSUM) | ||
96 | |||
97 | #define QFQ_MTU_SHIFT 11 | ||
98 | #define QFQ_MIN_SLOT_SHIFT (FRAC_BITS + QFQ_MTU_SHIFT - QFQ_MAX_INDEX) | ||
99 | |||
100 | /* | ||
101 | * Possible group states. These values are used as indexes for the bitmaps | ||
102 | * array of struct qfq_queue. | ||
103 | */ | ||
104 | enum qfq_state { ER, IR, EB, IB, QFQ_MAX_STATE }; | ||
105 | |||
106 | struct qfq_group; | ||
107 | |||
108 | struct qfq_class { | ||
109 | struct Qdisc_class_common common; | ||
110 | |||
111 | unsigned int refcnt; | ||
112 | unsigned int filter_cnt; | ||
113 | |||
114 | struct gnet_stats_basic_packed bstats; | ||
115 | struct gnet_stats_queue qstats; | ||
116 | struct gnet_stats_rate_est rate_est; | ||
117 | struct Qdisc *qdisc; | ||
118 | |||
119 | struct hlist_node next; /* Link for the slot list. */ | ||
120 | u64 S, F; /* flow timestamps (exact) */ | ||
121 | |||
122 | /* group we belong to. In principle we would need the index, | ||
123 | * which is log_2(lmax/weight), but we never reference it | ||
124 | * directly, only the group. | ||
125 | */ | ||
126 | struct qfq_group *grp; | ||
127 | |||
128 | /* these are copied from the flowset. */ | ||
129 | u32 inv_w; /* ONE_FP/weight */ | ||
130 | u32 lmax; /* Max packet size for this flow. */ | ||
131 | }; | ||
132 | |||
133 | struct qfq_group { | ||
134 | u64 S, F; /* group timestamps (approx). */ | ||
135 | unsigned int slot_shift; /* Slot shift. */ | ||
136 | unsigned int index; /* Group index. */ | ||
137 | unsigned int front; /* Index of the front slot. */ | ||
138 | unsigned long full_slots; /* non-empty slots */ | ||
139 | |||
140 | /* Array of RR lists of active classes. */ | ||
141 | struct hlist_head slots[QFQ_MAX_SLOTS]; | ||
142 | }; | ||
143 | |||
144 | struct qfq_sched { | ||
145 | struct tcf_proto *filter_list; | ||
146 | struct Qdisc_class_hash clhash; | ||
147 | |||
148 | u64 V; /* Precise virtual time. */ | ||
149 | u32 wsum; /* weight sum */ | ||
150 | |||
151 | unsigned long bitmaps[QFQ_MAX_STATE]; /* Group bitmaps. */ | ||
152 | struct qfq_group groups[QFQ_MAX_INDEX + 1]; /* The groups. */ | ||
153 | }; | ||
154 | |||
155 | static struct qfq_class *qfq_find_class(struct Qdisc *sch, u32 classid) | ||
156 | { | ||
157 | struct qfq_sched *q = qdisc_priv(sch); | ||
158 | struct Qdisc_class_common *clc; | ||
159 | |||
160 | clc = qdisc_class_find(&q->clhash, classid); | ||
161 | if (clc == NULL) | ||
162 | return NULL; | ||
163 | return container_of(clc, struct qfq_class, common); | ||
164 | } | ||
165 | |||
166 | static void qfq_purge_queue(struct qfq_class *cl) | ||
167 | { | ||
168 | unsigned int len = cl->qdisc->q.qlen; | ||
169 | |||
170 | qdisc_reset(cl->qdisc); | ||
171 | qdisc_tree_decrease_qlen(cl->qdisc, len); | ||
172 | } | ||
173 | |||
174 | static const struct nla_policy qfq_policy[TCA_QFQ_MAX + 1] = { | ||
175 | [TCA_QFQ_WEIGHT] = { .type = NLA_U32 }, | ||
176 | [TCA_QFQ_LMAX] = { .type = NLA_U32 }, | ||
177 | }; | ||
178 | |||
179 | /* | ||
180 | * Calculate a flow index, given its weight and maximum packet length. | ||
181 | * index = log_2(maxlen/weight) but we need to apply the scaling. | ||
182 | * This is used only once at flow creation. | ||
183 | */ | ||
184 | static int qfq_calc_index(u32 inv_w, unsigned int maxlen) | ||
185 | { | ||
186 | u64 slot_size = (u64)maxlen * inv_w; | ||
187 | unsigned long size_map; | ||
188 | int index = 0; | ||
189 | |||
190 | size_map = slot_size >> QFQ_MIN_SLOT_SHIFT; | ||
191 | if (!size_map) | ||
192 | goto out; | ||
193 | |||
194 | index = __fls(size_map) + 1; /* basically a log_2 */ | ||
195 | index -= !(slot_size - (1ULL << (index + QFQ_MIN_SLOT_SHIFT - 1))); | ||
196 | |||
197 | if (index < 0) | ||
198 | index = 0; | ||
199 | out: | ||
200 | pr_debug("qfq calc_index: W = %lu, L = %u, I = %d\n", | ||
201 | (unsigned long) ONE_FP/inv_w, maxlen, index); | ||
202 | |||
203 | return index; | ||
204 | } | ||
205 | |||
206 | static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, | ||
207 | struct nlattr **tca, unsigned long *arg) | ||
208 | { | ||
209 | struct qfq_sched *q = qdisc_priv(sch); | ||
210 | struct qfq_class *cl = (struct qfq_class *)*arg; | ||
211 | struct nlattr *tb[TCA_QFQ_MAX + 1]; | ||
212 | u32 weight, lmax, inv_w; | ||
213 | int i, err; | ||
214 | |||
215 | if (tca[TCA_OPTIONS] == NULL) { | ||
216 | pr_notice("qfq: no options\n"); | ||
217 | return -EINVAL; | ||
218 | } | ||
219 | |||
220 | err = nla_parse_nested(tb, TCA_QFQ_MAX, tca[TCA_OPTIONS], qfq_policy); | ||
221 | if (err < 0) | ||
222 | return err; | ||
223 | |||
224 | if (tb[TCA_QFQ_WEIGHT]) { | ||
225 | weight = nla_get_u32(tb[TCA_QFQ_WEIGHT]); | ||
226 | if (!weight || weight > (1UL << QFQ_MAX_WSHIFT)) { | ||
227 | pr_notice("qfq: invalid weight %u\n", weight); | ||
228 | return -EINVAL; | ||
229 | } | ||
230 | } else | ||
231 | weight = 1; | ||
232 | |||
233 | inv_w = ONE_FP / weight; | ||
234 | weight = ONE_FP / inv_w; | ||
235 | if (q->wsum + weight > QFQ_MAX_WSUM) { | ||
236 | pr_notice("qfq: total weight out of range (%u + %u)\n", | ||
237 | weight, q->wsum); | ||
238 | return -EINVAL; | ||
239 | } | ||
240 | |||
241 | if (tb[TCA_QFQ_LMAX]) { | ||
242 | lmax = nla_get_u32(tb[TCA_QFQ_LMAX]); | ||
243 | if (!lmax || lmax > (1UL << QFQ_MTU_SHIFT)) { | ||
244 | pr_notice("qfq: invalid max length %u\n", lmax); | ||
245 | return -EINVAL; | ||
246 | } | ||
247 | } else | ||
248 | lmax = 1UL << QFQ_MTU_SHIFT; | ||
249 | |||
250 | if (cl != NULL) { | ||
251 | if (tca[TCA_RATE]) { | ||
252 | err = gen_replace_estimator(&cl->bstats, &cl->rate_est, | ||
253 | qdisc_root_sleeping_lock(sch), | ||
254 | tca[TCA_RATE]); | ||
255 | if (err) | ||
256 | return err; | ||
257 | } | ||
258 | |||
259 | sch_tree_lock(sch); | ||
260 | if (tb[TCA_QFQ_WEIGHT]) { | ||
261 | q->wsum = weight - ONE_FP / cl->inv_w; | ||
262 | cl->inv_w = inv_w; | ||
263 | } | ||
264 | sch_tree_unlock(sch); | ||
265 | |||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | cl = kzalloc(sizeof(struct qfq_class), GFP_KERNEL); | ||
270 | if (cl == NULL) | ||
271 | return -ENOBUFS; | ||
272 | |||
273 | cl->refcnt = 1; | ||
274 | cl->common.classid = classid; | ||
275 | cl->lmax = lmax; | ||
276 | cl->inv_w = inv_w; | ||
277 | i = qfq_calc_index(cl->inv_w, cl->lmax); | ||
278 | |||
279 | cl->grp = &q->groups[i]; | ||
280 | q->wsum += weight; | ||
281 | |||
282 | cl->qdisc = qdisc_create_dflt(sch->dev_queue, | ||
283 | &pfifo_qdisc_ops, classid); | ||
284 | if (cl->qdisc == NULL) | ||
285 | cl->qdisc = &noop_qdisc; | ||
286 | |||
287 | if (tca[TCA_RATE]) { | ||
288 | err = gen_new_estimator(&cl->bstats, &cl->rate_est, | ||
289 | qdisc_root_sleeping_lock(sch), | ||
290 | tca[TCA_RATE]); | ||
291 | if (err) { | ||
292 | qdisc_destroy(cl->qdisc); | ||
293 | kfree(cl); | ||
294 | return err; | ||
295 | } | ||
296 | } | ||
297 | |||
298 | sch_tree_lock(sch); | ||
299 | qdisc_class_hash_insert(&q->clhash, &cl->common); | ||
300 | sch_tree_unlock(sch); | ||
301 | |||
302 | qdisc_class_hash_grow(sch, &q->clhash); | ||
303 | |||
304 | *arg = (unsigned long)cl; | ||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | static void qfq_destroy_class(struct Qdisc *sch, struct qfq_class *cl) | ||
309 | { | ||
310 | struct qfq_sched *q = qdisc_priv(sch); | ||
311 | |||
312 | if (cl->inv_w) { | ||
313 | q->wsum -= ONE_FP / cl->inv_w; | ||
314 | cl->inv_w = 0; | ||
315 | } | ||
316 | |||
317 | gen_kill_estimator(&cl->bstats, &cl->rate_est); | ||
318 | qdisc_destroy(cl->qdisc); | ||
319 | kfree(cl); | ||
320 | } | ||
321 | |||
322 | static int qfq_delete_class(struct Qdisc *sch, unsigned long arg) | ||
323 | { | ||
324 | struct qfq_sched *q = qdisc_priv(sch); | ||
325 | struct qfq_class *cl = (struct qfq_class *)arg; | ||
326 | |||
327 | if (cl->filter_cnt > 0) | ||
328 | return -EBUSY; | ||
329 | |||
330 | sch_tree_lock(sch); | ||
331 | |||
332 | qfq_purge_queue(cl); | ||
333 | qdisc_class_hash_remove(&q->clhash, &cl->common); | ||
334 | |||
335 | BUG_ON(--cl->refcnt == 0); | ||
336 | /* | ||
337 | * This shouldn't happen: we "hold" one cops->get() when called | ||
338 | * from tc_ctl_tclass; the destroy method is done from cops->put(). | ||
339 | */ | ||
340 | |||
341 | sch_tree_unlock(sch); | ||
342 | return 0; | ||
343 | } | ||
344 | |||
345 | static unsigned long qfq_get_class(struct Qdisc *sch, u32 classid) | ||
346 | { | ||
347 | struct qfq_class *cl = qfq_find_class(sch, classid); | ||
348 | |||
349 | if (cl != NULL) | ||
350 | cl->refcnt++; | ||
351 | |||
352 | return (unsigned long)cl; | ||
353 | } | ||
354 | |||
355 | static void qfq_put_class(struct Qdisc *sch, unsigned long arg) | ||
356 | { | ||
357 | struct qfq_class *cl = (struct qfq_class *)arg; | ||
358 | |||
359 | if (--cl->refcnt == 0) | ||
360 | qfq_destroy_class(sch, cl); | ||
361 | } | ||
362 | |||
363 | static struct tcf_proto **qfq_tcf_chain(struct Qdisc *sch, unsigned long cl) | ||
364 | { | ||
365 | struct qfq_sched *q = qdisc_priv(sch); | ||
366 | |||
367 | if (cl) | ||
368 | return NULL; | ||
369 | |||
370 | return &q->filter_list; | ||
371 | } | ||
372 | |||
373 | static unsigned long qfq_bind_tcf(struct Qdisc *sch, unsigned long parent, | ||
374 | u32 classid) | ||
375 | { | ||
376 | struct qfq_class *cl = qfq_find_class(sch, classid); | ||
377 | |||
378 | if (cl != NULL) | ||
379 | cl->filter_cnt++; | ||
380 | |||
381 | return (unsigned long)cl; | ||
382 | } | ||
383 | |||
384 | static void qfq_unbind_tcf(struct Qdisc *sch, unsigned long arg) | ||
385 | { | ||
386 | struct qfq_class *cl = (struct qfq_class *)arg; | ||
387 | |||
388 | cl->filter_cnt--; | ||
389 | } | ||
390 | |||
391 | static int qfq_graft_class(struct Qdisc *sch, unsigned long arg, | ||
392 | struct Qdisc *new, struct Qdisc **old) | ||
393 | { | ||
394 | struct qfq_class *cl = (struct qfq_class *)arg; | ||
395 | |||
396 | if (new == NULL) { | ||
397 | new = qdisc_create_dflt(sch->dev_queue, | ||
398 | &pfifo_qdisc_ops, cl->common.classid); | ||
399 | if (new == NULL) | ||
400 | new = &noop_qdisc; | ||
401 | } | ||
402 | |||
403 | sch_tree_lock(sch); | ||
404 | qfq_purge_queue(cl); | ||
405 | *old = cl->qdisc; | ||
406 | cl->qdisc = new; | ||
407 | sch_tree_unlock(sch); | ||
408 | return 0; | ||
409 | } | ||
410 | |||
411 | static struct Qdisc *qfq_class_leaf(struct Qdisc *sch, unsigned long arg) | ||
412 | { | ||
413 | struct qfq_class *cl = (struct qfq_class *)arg; | ||
414 | |||
415 | return cl->qdisc; | ||
416 | } | ||
417 | |||
418 | static int qfq_dump_class(struct Qdisc *sch, unsigned long arg, | ||
419 | struct sk_buff *skb, struct tcmsg *tcm) | ||
420 | { | ||
421 | struct qfq_class *cl = (struct qfq_class *)arg; | ||
422 | struct nlattr *nest; | ||
423 | |||
424 | tcm->tcm_parent = TC_H_ROOT; | ||
425 | tcm->tcm_handle = cl->common.classid; | ||
426 | tcm->tcm_info = cl->qdisc->handle; | ||
427 | |||
428 | nest = nla_nest_start(skb, TCA_OPTIONS); | ||
429 | if (nest == NULL) | ||
430 | goto nla_put_failure; | ||
431 | NLA_PUT_U32(skb, TCA_QFQ_WEIGHT, ONE_FP/cl->inv_w); | ||
432 | NLA_PUT_U32(skb, TCA_QFQ_LMAX, cl->lmax); | ||
433 | return nla_nest_end(skb, nest); | ||
434 | |||
435 | nla_put_failure: | ||
436 | nla_nest_cancel(skb, nest); | ||
437 | return -EMSGSIZE; | ||
438 | } | ||
439 | |||
440 | static int qfq_dump_class_stats(struct Qdisc *sch, unsigned long arg, | ||
441 | struct gnet_dump *d) | ||
442 | { | ||
443 | struct qfq_class *cl = (struct qfq_class *)arg; | ||
444 | struct tc_qfq_stats xstats; | ||
445 | |||
446 | memset(&xstats, 0, sizeof(xstats)); | ||
447 | cl->qdisc->qstats.qlen = cl->qdisc->q.qlen; | ||
448 | |||
449 | xstats.weight = ONE_FP/cl->inv_w; | ||
450 | xstats.lmax = cl->lmax; | ||
451 | |||
452 | if (gnet_stats_copy_basic(d, &cl->bstats) < 0 || | ||
453 | gnet_stats_copy_rate_est(d, &cl->bstats, &cl->rate_est) < 0 || | ||
454 | gnet_stats_copy_queue(d, &cl->qdisc->qstats) < 0) | ||
455 | return -1; | ||
456 | |||
457 | return gnet_stats_copy_app(d, &xstats, sizeof(xstats)); | ||
458 | } | ||
459 | |||
460 | static void qfq_walk(struct Qdisc *sch, struct qdisc_walker *arg) | ||
461 | { | ||
462 | struct qfq_sched *q = qdisc_priv(sch); | ||
463 | struct qfq_class *cl; | ||
464 | struct hlist_node *n; | ||
465 | unsigned int i; | ||
466 | |||
467 | if (arg->stop) | ||
468 | return; | ||
469 | |||
470 | for (i = 0; i < q->clhash.hashsize; i++) { | ||
471 | hlist_for_each_entry(cl, n, &q->clhash.hash[i], common.hnode) { | ||
472 | if (arg->count < arg->skip) { | ||
473 | arg->count++; | ||
474 | continue; | ||
475 | } | ||
476 | if (arg->fn(sch, (unsigned long)cl, arg) < 0) { | ||
477 | arg->stop = 1; | ||
478 | return; | ||
479 | } | ||
480 | arg->count++; | ||
481 | } | ||
482 | } | ||
483 | } | ||
484 | |||
485 | static struct qfq_class *qfq_classify(struct sk_buff *skb, struct Qdisc *sch, | ||
486 | int *qerr) | ||
487 | { | ||
488 | struct qfq_sched *q = qdisc_priv(sch); | ||
489 | struct qfq_class *cl; | ||
490 | struct tcf_result res; | ||
491 | int result; | ||
492 | |||
493 | if (TC_H_MAJ(skb->priority ^ sch->handle) == 0) { | ||
494 | pr_debug("qfq_classify: found %d\n", skb->priority); | ||
495 | cl = qfq_find_class(sch, skb->priority); | ||
496 | if (cl != NULL) | ||
497 | return cl; | ||
498 | } | ||
499 | |||
500 | *qerr = NET_XMIT_SUCCESS | __NET_XMIT_BYPASS; | ||
501 | result = tc_classify(skb, q->filter_list, &res); | ||
502 | if (result >= 0) { | ||
503 | #ifdef CONFIG_NET_CLS_ACT | ||
504 | switch (result) { | ||
505 | case TC_ACT_QUEUED: | ||
506 | case TC_ACT_STOLEN: | ||
507 | *qerr = NET_XMIT_SUCCESS | __NET_XMIT_STOLEN; | ||
508 | case TC_ACT_SHOT: | ||
509 | return NULL; | ||
510 | } | ||
511 | #endif | ||
512 | cl = (struct qfq_class *)res.class; | ||
513 | if (cl == NULL) | ||
514 | cl = qfq_find_class(sch, res.classid); | ||
515 | return cl; | ||
516 | } | ||
517 | |||
518 | return NULL; | ||
519 | } | ||
520 | |||
521 | /* Generic comparison function, handling wraparound. */ | ||
522 | static inline int qfq_gt(u64 a, u64 b) | ||
523 | { | ||
524 | return (s64)(a - b) > 0; | ||
525 | } | ||
526 | |||
527 | /* Round a precise timestamp to its slotted value. */ | ||
528 | static inline u64 qfq_round_down(u64 ts, unsigned int shift) | ||
529 | { | ||
530 | return ts & ~((1ULL << shift) - 1); | ||
531 | } | ||
532 | |||
533 | /* return the pointer to the group with lowest index in the bitmap */ | ||
534 | static inline struct qfq_group *qfq_ffs(struct qfq_sched *q, | ||
535 | unsigned long bitmap) | ||
536 | { | ||
537 | int index = __ffs(bitmap); | ||
538 | return &q->groups[index]; | ||
539 | } | ||
540 | /* Calculate a mask to mimic what would be ffs_from(). */ | ||
541 | static inline unsigned long mask_from(unsigned long bitmap, int from) | ||
542 | { | ||
543 | return bitmap & ~((1UL << from) - 1); | ||
544 | } | ||
545 | |||
546 | /* | ||
547 | * The state computation relies on ER=0, IR=1, EB=2, IB=3 | ||
548 | * First compute eligibility comparing grp->S, q->V, | ||
549 | * then check if someone is blocking us and possibly add EB | ||
550 | */ | ||
551 | static int qfq_calc_state(struct qfq_sched *q, const struct qfq_group *grp) | ||
552 | { | ||
553 | /* if S > V we are not eligible */ | ||
554 | unsigned int state = qfq_gt(grp->S, q->V); | ||
555 | unsigned long mask = mask_from(q->bitmaps[ER], grp->index); | ||
556 | struct qfq_group *next; | ||
557 | |||
558 | if (mask) { | ||
559 | next = qfq_ffs(q, mask); | ||
560 | if (qfq_gt(grp->F, next->F)) | ||
561 | state |= EB; | ||
562 | } | ||
563 | |||
564 | return state; | ||
565 | } | ||
566 | |||
567 | |||
568 | /* | ||
569 | * In principle | ||
570 | * q->bitmaps[dst] |= q->bitmaps[src] & mask; | ||
571 | * q->bitmaps[src] &= ~mask; | ||
572 | * but we should make sure that src != dst | ||
573 | */ | ||
574 | static inline void qfq_move_groups(struct qfq_sched *q, unsigned long mask, | ||
575 | int src, int dst) | ||
576 | { | ||
577 | q->bitmaps[dst] |= q->bitmaps[src] & mask; | ||
578 | q->bitmaps[src] &= ~mask; | ||
579 | } | ||
580 | |||
581 | static void qfq_unblock_groups(struct qfq_sched *q, int index, u64 old_F) | ||
582 | { | ||
583 | unsigned long mask = mask_from(q->bitmaps[ER], index + 1); | ||
584 | struct qfq_group *next; | ||
585 | |||
586 | if (mask) { | ||
587 | next = qfq_ffs(q, mask); | ||
588 | if (!qfq_gt(next->F, old_F)) | ||
589 | return; | ||
590 | } | ||
591 | |||
592 | mask = (1UL << index) - 1; | ||
593 | qfq_move_groups(q, mask, EB, ER); | ||
594 | qfq_move_groups(q, mask, IB, IR); | ||
595 | } | ||
596 | |||
597 | /* | ||
598 | * perhaps | ||
599 | * | ||
600 | old_V ^= q->V; | ||
601 | old_V >>= QFQ_MIN_SLOT_SHIFT; | ||
602 | if (old_V) { | ||
603 | ... | ||
604 | } | ||
605 | * | ||
606 | */ | ||
607 | static void qfq_make_eligible(struct qfq_sched *q, u64 old_V) | ||
608 | { | ||
609 | unsigned long vslot = q->V >> QFQ_MIN_SLOT_SHIFT; | ||
610 | unsigned long old_vslot = old_V >> QFQ_MIN_SLOT_SHIFT; | ||
611 | |||
612 | if (vslot != old_vslot) { | ||
613 | unsigned long mask = (1UL << fls(vslot ^ old_vslot)) - 1; | ||
614 | qfq_move_groups(q, mask, IR, ER); | ||
615 | qfq_move_groups(q, mask, IB, EB); | ||
616 | } | ||
617 | } | ||
618 | |||
619 | |||
620 | /* | ||
621 | * XXX we should make sure that slot becomes less than 32. | ||
622 | * This is guaranteed by the input values. | ||
623 | * roundedS is always cl->S rounded on grp->slot_shift bits. | ||
624 | */ | ||
625 | static void qfq_slot_insert(struct qfq_group *grp, struct qfq_class *cl, | ||
626 | u64 roundedS) | ||
627 | { | ||
628 | u64 slot = (roundedS - grp->S) >> grp->slot_shift; | ||
629 | unsigned int i = (grp->front + slot) % QFQ_MAX_SLOTS; | ||
630 | |||
631 | hlist_add_head(&cl->next, &grp->slots[i]); | ||
632 | __set_bit(slot, &grp->full_slots); | ||
633 | } | ||
634 | |||
635 | /* Maybe introduce hlist_first_entry?? */ | ||
636 | static struct qfq_class *qfq_slot_head(struct qfq_group *grp) | ||
637 | { | ||
638 | return hlist_entry(grp->slots[grp->front].first, | ||
639 | struct qfq_class, next); | ||
640 | } | ||
641 | |||
642 | /* | ||
643 | * remove the entry from the slot | ||
644 | */ | ||
645 | static void qfq_front_slot_remove(struct qfq_group *grp) | ||
646 | { | ||
647 | struct qfq_class *cl = qfq_slot_head(grp); | ||
648 | |||
649 | BUG_ON(!cl); | ||
650 | hlist_del(&cl->next); | ||
651 | if (hlist_empty(&grp->slots[grp->front])) | ||
652 | __clear_bit(0, &grp->full_slots); | ||
653 | } | ||
654 | |||
655 | /* | ||
656 | * Returns the first full queue in a group. As a side effect, | ||
657 | * adjust the bucket list so the first non-empty bucket is at | ||
658 | * position 0 in full_slots. | ||
659 | */ | ||
660 | static struct qfq_class *qfq_slot_scan(struct qfq_group *grp) | ||
661 | { | ||
662 | unsigned int i; | ||
663 | |||
664 | pr_debug("qfq slot_scan: grp %u full %#lx\n", | ||
665 | grp->index, grp->full_slots); | ||
666 | |||
667 | if (grp->full_slots == 0) | ||
668 | return NULL; | ||
669 | |||
670 | i = __ffs(grp->full_slots); /* zero based */ | ||
671 | if (i > 0) { | ||
672 | grp->front = (grp->front + i) % QFQ_MAX_SLOTS; | ||
673 | grp->full_slots >>= i; | ||
674 | } | ||
675 | |||
676 | return qfq_slot_head(grp); | ||
677 | } | ||
678 | |||
679 | /* | ||
680 | * adjust the bucket list. When the start time of a group decreases, | ||
681 | * we move the index down (modulo QFQ_MAX_SLOTS) so we don't need to | ||
682 | * move the objects. The mask of occupied slots must be shifted | ||
683 | * because we use ffs() to find the first non-empty slot. | ||
684 | * This covers decreases in the group's start time, but what about | ||
685 | * increases of the start time ? | ||
686 | * Here too we should make sure that i is less than 32 | ||
687 | */ | ||
688 | static void qfq_slot_rotate(struct qfq_group *grp, u64 roundedS) | ||
689 | { | ||
690 | unsigned int i = (grp->S - roundedS) >> grp->slot_shift; | ||
691 | |||
692 | grp->full_slots <<= i; | ||
693 | grp->front = (grp->front - i) % QFQ_MAX_SLOTS; | ||
694 | } | ||
695 | |||
696 | static void qfq_update_eligible(struct qfq_sched *q, u64 old_V) | ||
697 | { | ||
698 | struct qfq_group *grp; | ||
699 | unsigned long ineligible; | ||
700 | |||
701 | ineligible = q->bitmaps[IR] | q->bitmaps[IB]; | ||
702 | if (ineligible) { | ||
703 | if (!q->bitmaps[ER]) { | ||
704 | grp = qfq_ffs(q, ineligible); | ||
705 | if (qfq_gt(grp->S, q->V)) | ||
706 | q->V = grp->S; | ||
707 | } | ||
708 | qfq_make_eligible(q, old_V); | ||
709 | } | ||
710 | } | ||
711 | |||
712 | /* What is length of next packet in queue (0 if queue is empty) */ | ||
713 | static unsigned int qdisc_peek_len(struct Qdisc *sch) | ||
714 | { | ||
715 | struct sk_buff *skb; | ||
716 | |||
717 | skb = sch->ops->peek(sch); | ||
718 | return skb ? qdisc_pkt_len(skb) : 0; | ||
719 | } | ||
720 | |||
721 | /* | ||
722 | * Updates the class, returns true if also the group needs to be updated. | ||
723 | */ | ||
724 | static bool qfq_update_class(struct qfq_group *grp, struct qfq_class *cl) | ||
725 | { | ||
726 | unsigned int len = qdisc_peek_len(cl->qdisc); | ||
727 | |||
728 | cl->S = cl->F; | ||
729 | if (!len) | ||
730 | qfq_front_slot_remove(grp); /* queue is empty */ | ||
731 | else { | ||
732 | u64 roundedS; | ||
733 | |||
734 | cl->F = cl->S + (u64)len * cl->inv_w; | ||
735 | roundedS = qfq_round_down(cl->S, grp->slot_shift); | ||
736 | if (roundedS == grp->S) | ||
737 | return false; | ||
738 | |||
739 | qfq_front_slot_remove(grp); | ||
740 | qfq_slot_insert(grp, cl, roundedS); | ||
741 | } | ||
742 | |||
743 | return true; | ||
744 | } | ||
745 | |||
746 | static struct sk_buff *qfq_dequeue(struct Qdisc *sch) | ||
747 | { | ||
748 | struct qfq_sched *q = qdisc_priv(sch); | ||
749 | struct qfq_group *grp; | ||
750 | struct qfq_class *cl; | ||
751 | struct sk_buff *skb; | ||
752 | unsigned int len; | ||
753 | u64 old_V; | ||
754 | |||
755 | if (!q->bitmaps[ER]) | ||
756 | return NULL; | ||
757 | |||
758 | grp = qfq_ffs(q, q->bitmaps[ER]); | ||
759 | |||
760 | cl = qfq_slot_head(grp); | ||
761 | skb = qdisc_dequeue_peeked(cl->qdisc); | ||
762 | if (!skb) { | ||
763 | WARN_ONCE(1, "qfq_dequeue: non-workconserving leaf\n"); | ||
764 | return NULL; | ||
765 | } | ||
766 | |||
767 | sch->q.qlen--; | ||
768 | qdisc_bstats_update(sch, skb); | ||
769 | |||
770 | old_V = q->V; | ||
771 | len = qdisc_pkt_len(skb); | ||
772 | q->V += (u64)len * IWSUM; | ||
773 | pr_debug("qfq dequeue: len %u F %lld now %lld\n", | ||
774 | len, (unsigned long long) cl->F, (unsigned long long) q->V); | ||
775 | |||
776 | if (qfq_update_class(grp, cl)) { | ||
777 | u64 old_F = grp->F; | ||
778 | |||
779 | cl = qfq_slot_scan(grp); | ||
780 | if (!cl) | ||
781 | __clear_bit(grp->index, &q->bitmaps[ER]); | ||
782 | else { | ||
783 | u64 roundedS = qfq_round_down(cl->S, grp->slot_shift); | ||
784 | unsigned int s; | ||
785 | |||
786 | if (grp->S == roundedS) | ||
787 | goto skip_unblock; | ||
788 | grp->S = roundedS; | ||
789 | grp->F = roundedS + (2ULL << grp->slot_shift); | ||
790 | __clear_bit(grp->index, &q->bitmaps[ER]); | ||
791 | s = qfq_calc_state(q, grp); | ||
792 | __set_bit(grp->index, &q->bitmaps[s]); | ||
793 | } | ||
794 | |||
795 | qfq_unblock_groups(q, grp->index, old_F); | ||
796 | } | ||
797 | |||
798 | skip_unblock: | ||
799 | qfq_update_eligible(q, old_V); | ||
800 | |||
801 | return skb; | ||
802 | } | ||
803 | |||
804 | /* | ||
805 | * Assign a reasonable start time for a new flow k in group i. | ||
806 | * Admissible values for \hat(F) are multiples of \sigma_i | ||
807 | * no greater than V+\sigma_i . Larger values mean that | ||
808 | * we had a wraparound so we consider the timestamp to be stale. | ||
809 | * | ||
810 | * If F is not stale and F >= V then we set S = F. | ||
811 | * Otherwise we should assign S = V, but this may violate | ||
812 | * the ordering in ER. So, if we have groups in ER, set S to | ||
813 | * the F_j of the first group j which would be blocking us. | ||
814 | * We are guaranteed not to move S backward because | ||
815 | * otherwise our group i would still be blocked. | ||
816 | */ | ||
817 | static void qfq_update_start(struct qfq_sched *q, struct qfq_class *cl) | ||
818 | { | ||
819 | unsigned long mask; | ||
820 | uint32_t limit, roundedF; | ||
821 | int slot_shift = cl->grp->slot_shift; | ||
822 | |||
823 | roundedF = qfq_round_down(cl->F, slot_shift); | ||
824 | limit = qfq_round_down(q->V, slot_shift) + (1UL << slot_shift); | ||
825 | |||
826 | if (!qfq_gt(cl->F, q->V) || qfq_gt(roundedF, limit)) { | ||
827 | /* timestamp was stale */ | ||
828 | mask = mask_from(q->bitmaps[ER], cl->grp->index); | ||
829 | if (mask) { | ||
830 | struct qfq_group *next = qfq_ffs(q, mask); | ||
831 | if (qfq_gt(roundedF, next->F)) { | ||
832 | cl->S = next->F; | ||
833 | return; | ||
834 | } | ||
835 | } | ||
836 | cl->S = q->V; | ||
837 | } else /* timestamp is not stale */ | ||
838 | cl->S = cl->F; | ||
839 | } | ||
840 | |||
841 | static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch) | ||
842 | { | ||
843 | struct qfq_sched *q = qdisc_priv(sch); | ||
844 | struct qfq_group *grp; | ||
845 | struct qfq_class *cl; | ||
846 | int err; | ||
847 | u64 roundedS; | ||
848 | int s; | ||
849 | |||
850 | cl = qfq_classify(skb, sch, &err); | ||
851 | if (cl == NULL) { | ||
852 | if (err & __NET_XMIT_BYPASS) | ||
853 | sch->qstats.drops++; | ||
854 | kfree_skb(skb); | ||
855 | return err; | ||
856 | } | ||
857 | pr_debug("qfq_enqueue: cl = %x\n", cl->common.classid); | ||
858 | |||
859 | err = qdisc_enqueue(skb, cl->qdisc); | ||
860 | if (unlikely(err != NET_XMIT_SUCCESS)) { | ||
861 | pr_debug("qfq_enqueue: enqueue failed %d\n", err); | ||
862 | if (net_xmit_drop_count(err)) { | ||
863 | cl->qstats.drops++; | ||
864 | sch->qstats.drops++; | ||
865 | } | ||
866 | return err; | ||
867 | } | ||
868 | |||
869 | bstats_update(&cl->bstats, skb); | ||
870 | ++sch->q.qlen; | ||
871 | |||
872 | /* If the new skb is not the head of queue, then done here. */ | ||
873 | if (cl->qdisc->q.qlen != 1) | ||
874 | return err; | ||
875 | |||
876 | /* If reach this point, queue q was idle */ | ||
877 | grp = cl->grp; | ||
878 | qfq_update_start(q, cl); | ||
879 | |||
880 | /* compute new finish time and rounded start. */ | ||
881 | cl->F = cl->S + (u64)qdisc_pkt_len(skb) * cl->inv_w; | ||
882 | roundedS = qfq_round_down(cl->S, grp->slot_shift); | ||
883 | |||
884 | /* | ||
885 | * insert cl in the correct bucket. | ||
886 | * If cl->S >= grp->S we don't need to adjust the | ||
887 | * bucket list and simply go to the insertion phase. | ||
888 | * Otherwise grp->S is decreasing, we must make room | ||
889 | * in the bucket list, and also recompute the group state. | ||
890 | * Finally, if there were no flows in this group and nobody | ||
891 | * was in ER make sure to adjust V. | ||
892 | */ | ||
893 | if (grp->full_slots) { | ||
894 | if (!qfq_gt(grp->S, cl->S)) | ||
895 | goto skip_update; | ||
896 | |||
897 | /* create a slot for this cl->S */ | ||
898 | qfq_slot_rotate(grp, roundedS); | ||
899 | /* group was surely ineligible, remove */ | ||
900 | __clear_bit(grp->index, &q->bitmaps[IR]); | ||
901 | __clear_bit(grp->index, &q->bitmaps[IB]); | ||
902 | } else if (!q->bitmaps[ER] && qfq_gt(roundedS, q->V)) | ||
903 | q->V = roundedS; | ||
904 | |||
905 | grp->S = roundedS; | ||
906 | grp->F = roundedS + (2ULL << grp->slot_shift); | ||
907 | s = qfq_calc_state(q, grp); | ||
908 | __set_bit(grp->index, &q->bitmaps[s]); | ||
909 | |||
910 | pr_debug("qfq enqueue: new state %d %#lx S %lld F %lld V %lld\n", | ||
911 | s, q->bitmaps[s], | ||
912 | (unsigned long long) cl->S, | ||
913 | (unsigned long long) cl->F, | ||
914 | (unsigned long long) q->V); | ||
915 | |||
916 | skip_update: | ||
917 | qfq_slot_insert(grp, cl, roundedS); | ||
918 | |||
919 | return err; | ||
920 | } | ||
921 | |||
922 | |||
923 | static void qfq_slot_remove(struct qfq_sched *q, struct qfq_group *grp, | ||
924 | struct qfq_class *cl) | ||
925 | { | ||
926 | unsigned int i, offset; | ||
927 | u64 roundedS; | ||
928 | |||
929 | roundedS = qfq_round_down(cl->S, grp->slot_shift); | ||
930 | offset = (roundedS - grp->S) >> grp->slot_shift; | ||
931 | i = (grp->front + offset) % QFQ_MAX_SLOTS; | ||
932 | |||
933 | hlist_del(&cl->next); | ||
934 | if (hlist_empty(&grp->slots[i])) | ||
935 | __clear_bit(offset, &grp->full_slots); | ||
936 | } | ||
937 | |||
938 | /* | ||
939 | * called to forcibly destroy a queue. | ||
940 | * If the queue is not in the front bucket, or if it has | ||
941 | * other queues in the front bucket, we can simply remove | ||
942 | * the queue with no other side effects. | ||
943 | * Otherwise we must propagate the event up. | ||
944 | */ | ||
945 | static void qfq_deactivate_class(struct qfq_sched *q, struct qfq_class *cl) | ||
946 | { | ||
947 | struct qfq_group *grp = cl->grp; | ||
948 | unsigned long mask; | ||
949 | u64 roundedS; | ||
950 | int s; | ||
951 | |||
952 | cl->F = cl->S; | ||
953 | qfq_slot_remove(q, grp, cl); | ||
954 | |||
955 | if (!grp->full_slots) { | ||
956 | __clear_bit(grp->index, &q->bitmaps[IR]); | ||
957 | __clear_bit(grp->index, &q->bitmaps[EB]); | ||
958 | __clear_bit(grp->index, &q->bitmaps[IB]); | ||
959 | |||
960 | if (test_bit(grp->index, &q->bitmaps[ER]) && | ||
961 | !(q->bitmaps[ER] & ~((1UL << grp->index) - 1))) { | ||
962 | mask = q->bitmaps[ER] & ((1UL << grp->index) - 1); | ||
963 | if (mask) | ||
964 | mask = ~((1UL << __fls(mask)) - 1); | ||
965 | else | ||
966 | mask = ~0UL; | ||
967 | qfq_move_groups(q, mask, EB, ER); | ||
968 | qfq_move_groups(q, mask, IB, IR); | ||
969 | } | ||
970 | __clear_bit(grp->index, &q->bitmaps[ER]); | ||
971 | } else if (hlist_empty(&grp->slots[grp->front])) { | ||
972 | cl = qfq_slot_scan(grp); | ||
973 | roundedS = qfq_round_down(cl->S, grp->slot_shift); | ||
974 | if (grp->S != roundedS) { | ||
975 | __clear_bit(grp->index, &q->bitmaps[ER]); | ||
976 | __clear_bit(grp->index, &q->bitmaps[IR]); | ||
977 | __clear_bit(grp->index, &q->bitmaps[EB]); | ||
978 | __clear_bit(grp->index, &q->bitmaps[IB]); | ||
979 | grp->S = roundedS; | ||
980 | grp->F = roundedS + (2ULL << grp->slot_shift); | ||
981 | s = qfq_calc_state(q, grp); | ||
982 | __set_bit(grp->index, &q->bitmaps[s]); | ||
983 | } | ||
984 | } | ||
985 | |||
986 | qfq_update_eligible(q, q->V); | ||
987 | } | ||
988 | |||
989 | static void qfq_qlen_notify(struct Qdisc *sch, unsigned long arg) | ||
990 | { | ||
991 | struct qfq_sched *q = qdisc_priv(sch); | ||
992 | struct qfq_class *cl = (struct qfq_class *)arg; | ||
993 | |||
994 | if (cl->qdisc->q.qlen == 0) | ||
995 | qfq_deactivate_class(q, cl); | ||
996 | } | ||
997 | |||
998 | static unsigned int qfq_drop(struct Qdisc *sch) | ||
999 | { | ||
1000 | struct qfq_sched *q = qdisc_priv(sch); | ||
1001 | struct qfq_group *grp; | ||
1002 | unsigned int i, j, len; | ||
1003 | |||
1004 | for (i = 0; i <= QFQ_MAX_INDEX; i++) { | ||
1005 | grp = &q->groups[i]; | ||
1006 | for (j = 0; j < QFQ_MAX_SLOTS; j++) { | ||
1007 | struct qfq_class *cl; | ||
1008 | struct hlist_node *n; | ||
1009 | |||
1010 | hlist_for_each_entry(cl, n, &grp->slots[j], next) { | ||
1011 | |||
1012 | if (!cl->qdisc->ops->drop) | ||
1013 | continue; | ||
1014 | |||
1015 | len = cl->qdisc->ops->drop(cl->qdisc); | ||
1016 | if (len > 0) { | ||
1017 | sch->q.qlen--; | ||
1018 | if (!cl->qdisc->q.qlen) | ||
1019 | qfq_deactivate_class(q, cl); | ||
1020 | |||
1021 | return len; | ||
1022 | } | ||
1023 | } | ||
1024 | } | ||
1025 | } | ||
1026 | |||
1027 | return 0; | ||
1028 | } | ||
1029 | |||
1030 | static int qfq_init_qdisc(struct Qdisc *sch, struct nlattr *opt) | ||
1031 | { | ||
1032 | struct qfq_sched *q = qdisc_priv(sch); | ||
1033 | struct qfq_group *grp; | ||
1034 | int i, j, err; | ||
1035 | |||
1036 | err = qdisc_class_hash_init(&q->clhash); | ||
1037 | if (err < 0) | ||
1038 | return err; | ||
1039 | |||
1040 | for (i = 0; i <= QFQ_MAX_INDEX; i++) { | ||
1041 | grp = &q->groups[i]; | ||
1042 | grp->index = i; | ||
1043 | grp->slot_shift = QFQ_MTU_SHIFT + FRAC_BITS | ||
1044 | - (QFQ_MAX_INDEX - i); | ||
1045 | for (j = 0; j < QFQ_MAX_SLOTS; j++) | ||
1046 | INIT_HLIST_HEAD(&grp->slots[j]); | ||
1047 | } | ||
1048 | |||
1049 | return 0; | ||
1050 | } | ||
1051 | |||
1052 | static void qfq_reset_qdisc(struct Qdisc *sch) | ||
1053 | { | ||
1054 | struct qfq_sched *q = qdisc_priv(sch); | ||
1055 | struct qfq_group *grp; | ||
1056 | struct qfq_class *cl; | ||
1057 | struct hlist_node *n, *tmp; | ||
1058 | unsigned int i, j; | ||
1059 | |||
1060 | for (i = 0; i <= QFQ_MAX_INDEX; i++) { | ||
1061 | grp = &q->groups[i]; | ||
1062 | for (j = 0; j < QFQ_MAX_SLOTS; j++) { | ||
1063 | hlist_for_each_entry_safe(cl, n, tmp, | ||
1064 | &grp->slots[j], next) { | ||
1065 | qfq_deactivate_class(q, cl); | ||
1066 | } | ||
1067 | } | ||
1068 | } | ||
1069 | |||
1070 | for (i = 0; i < q->clhash.hashsize; i++) { | ||
1071 | hlist_for_each_entry(cl, n, &q->clhash.hash[i], common.hnode) | ||
1072 | qdisc_reset(cl->qdisc); | ||
1073 | } | ||
1074 | sch->q.qlen = 0; | ||
1075 | } | ||
1076 | |||
1077 | static void qfq_destroy_qdisc(struct Qdisc *sch) | ||
1078 | { | ||
1079 | struct qfq_sched *q = qdisc_priv(sch); | ||
1080 | struct qfq_class *cl; | ||
1081 | struct hlist_node *n, *next; | ||
1082 | unsigned int i; | ||
1083 | |||
1084 | tcf_destroy_chain(&q->filter_list); | ||
1085 | |||
1086 | for (i = 0; i < q->clhash.hashsize; i++) { | ||
1087 | hlist_for_each_entry_safe(cl, n, next, &q->clhash.hash[i], | ||
1088 | common.hnode) { | ||
1089 | qfq_destroy_class(sch, cl); | ||
1090 | } | ||
1091 | } | ||
1092 | qdisc_class_hash_destroy(&q->clhash); | ||
1093 | } | ||
1094 | |||
1095 | static const struct Qdisc_class_ops qfq_class_ops = { | ||
1096 | .change = qfq_change_class, | ||
1097 | .delete = qfq_delete_class, | ||
1098 | .get = qfq_get_class, | ||
1099 | .put = qfq_put_class, | ||
1100 | .tcf_chain = qfq_tcf_chain, | ||
1101 | .bind_tcf = qfq_bind_tcf, | ||
1102 | .unbind_tcf = qfq_unbind_tcf, | ||
1103 | .graft = qfq_graft_class, | ||
1104 | .leaf = qfq_class_leaf, | ||
1105 | .qlen_notify = qfq_qlen_notify, | ||
1106 | .dump = qfq_dump_class, | ||
1107 | .dump_stats = qfq_dump_class_stats, | ||
1108 | .walk = qfq_walk, | ||
1109 | }; | ||
1110 | |||
1111 | static struct Qdisc_ops qfq_qdisc_ops __read_mostly = { | ||
1112 | .cl_ops = &qfq_class_ops, | ||
1113 | .id = "qfq", | ||
1114 | .priv_size = sizeof(struct qfq_sched), | ||
1115 | .enqueue = qfq_enqueue, | ||
1116 | .dequeue = qfq_dequeue, | ||
1117 | .peek = qdisc_peek_dequeued, | ||
1118 | .drop = qfq_drop, | ||
1119 | .init = qfq_init_qdisc, | ||
1120 | .reset = qfq_reset_qdisc, | ||
1121 | .destroy = qfq_destroy_qdisc, | ||
1122 | .owner = THIS_MODULE, | ||
1123 | }; | ||
1124 | |||
1125 | static int __init qfq_init(void) | ||
1126 | { | ||
1127 | return register_qdisc(&qfq_qdisc_ops); | ||
1128 | } | ||
1129 | |||
1130 | static void __exit qfq_exit(void) | ||
1131 | { | ||
1132 | unregister_qdisc(&qfq_qdisc_ops); | ||
1133 | } | ||
1134 | |||
1135 | module_init(qfq_init); | ||
1136 | module_exit(qfq_exit); | ||
1137 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/sched/sch_sfq.c b/net/sched/sch_sfq.c index c2e628dfaacc..7ef87f9eb675 100644 --- a/net/sched/sch_sfq.c +++ b/net/sched/sch_sfq.c | |||
@@ -169,7 +169,7 @@ static unsigned int sfq_hash(struct sfq_sched_data *q, struct sk_buff *skb) | |||
169 | } | 169 | } |
170 | case htons(ETH_P_IPV6): | 170 | case htons(ETH_P_IPV6): |
171 | { | 171 | { |
172 | struct ipv6hdr *iph; | 172 | const struct ipv6hdr *iph; |
173 | int poff; | 173 | int poff; |
174 | 174 | ||
175 | if (!pskb_network_may_pull(skb, sizeof(*iph))) | 175 | if (!pskb_network_may_pull(skb, sizeof(*iph))) |
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 6b04287913cd..1a21c571aa03 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -569,6 +569,8 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc, | |||
569 | sctp_assoc_set_primary(asoc, transport); | 569 | sctp_assoc_set_primary(asoc, transport); |
570 | if (asoc->peer.active_path == peer) | 570 | if (asoc->peer.active_path == peer) |
571 | asoc->peer.active_path = transport; | 571 | asoc->peer.active_path = transport; |
572 | if (asoc->peer.retran_path == peer) | ||
573 | asoc->peer.retran_path = transport; | ||
572 | if (asoc->peer.last_data_from == peer) | 574 | if (asoc->peer.last_data_from == peer) |
573 | asoc->peer.last_data_from = transport; | 575 | asoc->peer.last_data_from = transport; |
574 | 576 | ||
@@ -1323,6 +1325,8 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc) | |||
1323 | 1325 | ||
1324 | if (t) | 1326 | if (t) |
1325 | asoc->peer.retran_path = t; | 1327 | asoc->peer.retran_path = t; |
1328 | else | ||
1329 | t = asoc->peer.retran_path; | ||
1326 | 1330 | ||
1327 | SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association" | 1331 | SCTP_DEBUG_PRINTK_IPADDR("sctp_assoc_update_retran_path:association" |
1328 | " %p addr: ", | 1332 | " %p addr: ", |
@@ -1593,7 +1597,7 @@ void sctp_assoc_clean_asconf_ack_cache(const struct sctp_association *asoc) | |||
1593 | struct sctp_chunk *ack; | 1597 | struct sctp_chunk *ack; |
1594 | struct sctp_chunk *tmp; | 1598 | struct sctp_chunk *tmp; |
1595 | 1599 | ||
1596 | /* We can remove all the entries from the queue upto | 1600 | /* We can remove all the entries from the queue up to |
1597 | * the "Peer-Sequence-Number". | 1601 | * the "Peer-Sequence-Number". |
1598 | */ | 1602 | */ |
1599 | list_for_each_entry_safe(ack, tmp, &asoc->asconf_ack_list, | 1603 | list_for_each_entry_safe(ack, tmp, &asoc->asconf_ack_list, |
diff --git a/net/sctp/auth.c b/net/sctp/auth.c index ddbbf7c81fa1..865e68fef21c 100644 --- a/net/sctp/auth.c +++ b/net/sctp/auth.c | |||
@@ -113,7 +113,7 @@ struct sctp_shared_key *sctp_auth_shkey_create(__u16 key_id, gfp_t gfp) | |||
113 | return new; | 113 | return new; |
114 | } | 114 | } |
115 | 115 | ||
116 | /* Free the shared key stucture */ | 116 | /* Free the shared key structure */ |
117 | static void sctp_auth_shkey_free(struct sctp_shared_key *sh_key) | 117 | static void sctp_auth_shkey_free(struct sctp_shared_key *sh_key) |
118 | { | 118 | { |
119 | BUG_ON(!list_empty(&sh_key->key_list)); | 119 | BUG_ON(!list_empty(&sh_key->key_list)); |
@@ -122,7 +122,7 @@ static void sctp_auth_shkey_free(struct sctp_shared_key *sh_key) | |||
122 | kfree(sh_key); | 122 | kfree(sh_key); |
123 | } | 123 | } |
124 | 124 | ||
125 | /* Destory the entire key list. This is done during the | 125 | /* Destroy the entire key list. This is done during the |
126 | * associon and endpoint free process. | 126 | * associon and endpoint free process. |
127 | */ | 127 | */ |
128 | void sctp_auth_destroy_keys(struct list_head *keys) | 128 | void sctp_auth_destroy_keys(struct list_head *keys) |
@@ -324,7 +324,7 @@ static struct sctp_auth_bytes *sctp_auth_asoc_create_secret( | |||
324 | if (!peer_key_vector || !local_key_vector) | 324 | if (!peer_key_vector || !local_key_vector) |
325 | goto out; | 325 | goto out; |
326 | 326 | ||
327 | /* Figure out the order in wich the key_vectors will be | 327 | /* Figure out the order in which the key_vectors will be |
328 | * added to the endpoint shared key. | 328 | * added to the endpoint shared key. |
329 | * SCTP-AUTH, Section 6.1: | 329 | * SCTP-AUTH, Section 6.1: |
330 | * This is performed by selecting the numerically smaller key | 330 | * This is performed by selecting the numerically smaller key |
diff --git a/net/sctp/debug.c b/net/sctp/debug.c index bf24fa697de2..ec997cfe0a7e 100644 --- a/net/sctp/debug.c +++ b/net/sctp/debug.c | |||
@@ -98,7 +98,6 @@ const char *sctp_cname(const sctp_subtype_t cid) | |||
98 | 98 | ||
99 | /* These are printable forms of the states. */ | 99 | /* These are printable forms of the states. */ |
100 | const char *const sctp_state_tbl[SCTP_STATE_NUM_STATES] = { | 100 | const char *const sctp_state_tbl[SCTP_STATE_NUM_STATES] = { |
101 | "STATE_EMPTY", | ||
102 | "STATE_CLOSED", | 101 | "STATE_CLOSED", |
103 | "STATE_COOKIE_WAIT", | 102 | "STATE_COOKIE_WAIT", |
104 | "STATE_COOKIE_ECHOED", | 103 | "STATE_COOKIE_ECHOED", |
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index e10acc01c75f..c8cc24e282c3 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c | |||
@@ -325,6 +325,7 @@ static struct sctp_association *__sctp_endpoint_lookup_assoc( | |||
325 | struct sctp_transport **transport) | 325 | struct sctp_transport **transport) |
326 | { | 326 | { |
327 | struct sctp_association *asoc = NULL; | 327 | struct sctp_association *asoc = NULL; |
328 | struct sctp_association *tmp; | ||
328 | struct sctp_transport *t = NULL; | 329 | struct sctp_transport *t = NULL; |
329 | struct sctp_hashbucket *head; | 330 | struct sctp_hashbucket *head; |
330 | struct sctp_ep_common *epb; | 331 | struct sctp_ep_common *epb; |
@@ -333,25 +334,32 @@ static struct sctp_association *__sctp_endpoint_lookup_assoc( | |||
333 | int rport; | 334 | int rport; |
334 | 335 | ||
335 | *transport = NULL; | 336 | *transport = NULL; |
337 | |||
338 | /* If the local port is not set, there can't be any associations | ||
339 | * on this endpoint. | ||
340 | */ | ||
341 | if (!ep->base.bind_addr.port) | ||
342 | goto out; | ||
343 | |||
336 | rport = ntohs(paddr->v4.sin_port); | 344 | rport = ntohs(paddr->v4.sin_port); |
337 | 345 | ||
338 | hash = sctp_assoc_hashfn(ep->base.bind_addr.port, rport); | 346 | hash = sctp_assoc_hashfn(ep->base.bind_addr.port, rport); |
339 | head = &sctp_assoc_hashtable[hash]; | 347 | head = &sctp_assoc_hashtable[hash]; |
340 | read_lock(&head->lock); | 348 | read_lock(&head->lock); |
341 | sctp_for_each_hentry(epb, node, &head->chain) { | 349 | sctp_for_each_hentry(epb, node, &head->chain) { |
342 | asoc = sctp_assoc(epb); | 350 | tmp = sctp_assoc(epb); |
343 | if (asoc->ep != ep || rport != asoc->peer.port) | 351 | if (tmp->ep != ep || rport != tmp->peer.port) |
344 | goto next; | 352 | continue; |
345 | 353 | ||
346 | t = sctp_assoc_lookup_paddr(asoc, paddr); | 354 | t = sctp_assoc_lookup_paddr(tmp, paddr); |
347 | if (t) { | 355 | if (t) { |
356 | asoc = tmp; | ||
348 | *transport = t; | 357 | *transport = t; |
349 | break; | 358 | break; |
350 | } | 359 | } |
351 | next: | ||
352 | asoc = NULL; | ||
353 | } | 360 | } |
354 | read_unlock(&head->lock); | 361 | read_unlock(&head->lock); |
362 | out: | ||
355 | return asoc; | 363 | return asoc; |
356 | } | 364 | } |
357 | 365 | ||
diff --git a/net/sctp/input.c b/net/sctp/input.c index 826661be73e7..741ed1648838 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
@@ -565,7 +565,7 @@ void sctp_err_finish(struct sock *sk, struct sctp_association *asoc) | |||
565 | */ | 565 | */ |
566 | void sctp_v4_err(struct sk_buff *skb, __u32 info) | 566 | void sctp_v4_err(struct sk_buff *skb, __u32 info) |
567 | { | 567 | { |
568 | struct iphdr *iph = (struct iphdr *)skb->data; | 568 | const struct iphdr *iph = (const struct iphdr *)skb->data; |
569 | const int ihlen = iph->ihl * 4; | 569 | const int ihlen = iph->ihl * 4; |
570 | const int type = icmp_hdr(skb)->type; | 570 | const int type = icmp_hdr(skb)->type; |
571 | const int code = icmp_hdr(skb)->code; | 571 | const int code = icmp_hdr(skb)->code; |
@@ -661,7 +661,6 @@ static int sctp_rcv_ootb(struct sk_buff *skb) | |||
661 | { | 661 | { |
662 | sctp_chunkhdr_t *ch; | 662 | sctp_chunkhdr_t *ch; |
663 | __u8 *ch_end; | 663 | __u8 *ch_end; |
664 | sctp_errhdr_t *err; | ||
665 | 664 | ||
666 | ch = (sctp_chunkhdr_t *) skb->data; | 665 | ch = (sctp_chunkhdr_t *) skb->data; |
667 | 666 | ||
@@ -697,20 +696,6 @@ static int sctp_rcv_ootb(struct sk_buff *skb) | |||
697 | if (SCTP_CID_INIT == ch->type && (void *)ch != skb->data) | 696 | if (SCTP_CID_INIT == ch->type && (void *)ch != skb->data) |
698 | goto discard; | 697 | goto discard; |
699 | 698 | ||
700 | /* RFC 8.4, 7) If the packet contains a "Stale cookie" ERROR | ||
701 | * or a COOKIE ACK the SCTP Packet should be silently | ||
702 | * discarded. | ||
703 | */ | ||
704 | if (SCTP_CID_COOKIE_ACK == ch->type) | ||
705 | goto discard; | ||
706 | |||
707 | if (SCTP_CID_ERROR == ch->type) { | ||
708 | sctp_walk_errors(err, ch) { | ||
709 | if (SCTP_ERROR_STALE_COOKIE == err->cause) | ||
710 | goto discard; | ||
711 | } | ||
712 | } | ||
713 | |||
714 | ch = (sctp_chunkhdr_t *) ch_end; | 699 | ch = (sctp_chunkhdr_t *) ch_end; |
715 | } while (ch_end < skb_tail_pointer(skb)); | 700 | } while (ch_end < skb_tail_pointer(skb)); |
716 | 701 | ||
@@ -1017,7 +1002,7 @@ static struct sctp_association *__sctp_rcv_asconf_lookup( | |||
1017 | /* Skip over the ADDIP header and find the Address parameter */ | 1002 | /* Skip over the ADDIP header and find the Address parameter */ |
1018 | param = (union sctp_addr_param *)(asconf + 1); | 1003 | param = (union sctp_addr_param *)(asconf + 1); |
1019 | 1004 | ||
1020 | af = sctp_get_af_specific(param_type2af(param->v4.param_hdr.type)); | 1005 | af = sctp_get_af_specific(param_type2af(param->p.type)); |
1021 | if (unlikely(!af)) | 1006 | if (unlikely(!af)) |
1022 | return NULL; | 1007 | return NULL; |
1023 | 1008 | ||
@@ -1034,7 +1019,7 @@ static struct sctp_association *__sctp_rcv_asconf_lookup( | |||
1034 | * association. | 1019 | * association. |
1035 | * | 1020 | * |
1036 | * This means that any chunks that can help us identify the association need | 1021 | * This means that any chunks that can help us identify the association need |
1037 | * to be looked at to find this assocation. | 1022 | * to be looked at to find this association. |
1038 | */ | 1023 | */ |
1039 | static struct sctp_association *__sctp_rcv_walk_lookup(struct sk_buff *skb, | 1024 | static struct sctp_association *__sctp_rcv_walk_lookup(struct sk_buff *skb, |
1040 | const union sctp_addr *laddr, | 1025 | const union sctp_addr *laddr, |
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 865ce7ba4e14..500875f4dc41 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -80,6 +80,13 @@ | |||
80 | 80 | ||
81 | #include <asm/uaccess.h> | 81 | #include <asm/uaccess.h> |
82 | 82 | ||
83 | static inline int sctp_v6_addr_match_len(union sctp_addr *s1, | ||
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); | ||
89 | |||
83 | /* Event handler for inet6 address addition/deletion events. | 90 | /* Event handler for inet6 address addition/deletion events. |
84 | * 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 |
85 | * multiple notifiers (say IPv4 and IPv6) may be running at the same | 92 | * multiple notifiers (say IPv4 and IPv6) may be running at the same |
@@ -240,37 +247,107 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport) | |||
240 | /* Returns the dst cache entry for the given source and destination ip | 247 | /* Returns the dst cache entry for the given source and destination ip |
241 | * addresses. | 248 | * addresses. |
242 | */ | 249 | */ |
243 | static struct dst_entry *sctp_v6_get_dst(struct sctp_association *asoc, | 250 | static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr, |
244 | union sctp_addr *daddr, | 251 | struct flowi *fl, struct sock *sk) |
245 | union sctp_addr *saddr) | ||
246 | { | 252 | { |
247 | struct dst_entry *dst; | 253 | struct sctp_association *asoc = t->asoc; |
248 | struct flowi6 fl6; | 254 | struct dst_entry *dst = NULL; |
255 | struct flowi6 *fl6 = &fl->u.ip6; | ||
256 | struct sctp_bind_addr *bp; | ||
257 | struct sctp_sockaddr_entry *laddr; | ||
258 | union sctp_addr *baddr = NULL; | ||
259 | union sctp_addr *daddr = &t->ipaddr; | ||
260 | union sctp_addr dst_saddr; | ||
261 | __u8 matchlen = 0; | ||
262 | __u8 bmatchlen; | ||
263 | sctp_scope_t scope; | ||
249 | 264 | ||
250 | memset(&fl6, 0, sizeof(fl6)); | 265 | memset(fl6, 0, sizeof(struct flowi6)); |
251 | ipv6_addr_copy(&fl6.daddr, &daddr->v6.sin6_addr); | 266 | ipv6_addr_copy(&fl6->daddr, &daddr->v6.sin6_addr); |
267 | fl6->fl6_dport = daddr->v6.sin6_port; | ||
268 | fl6->flowi6_proto = IPPROTO_SCTP; | ||
252 | if (ipv6_addr_type(&daddr->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL) | 269 | if (ipv6_addr_type(&daddr->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL) |
253 | fl6.flowi6_oif = daddr->v6.sin6_scope_id; | 270 | fl6->flowi6_oif = daddr->v6.sin6_scope_id; |
254 | 271 | ||
272 | SCTP_DEBUG_PRINTK("%s: DST=%pI6 ", __func__, &fl6->daddr); | ||
255 | 273 | ||
256 | SCTP_DEBUG_PRINTK("%s: DST=%pI6 ", __func__, &fl6.daddr); | 274 | if (asoc) |
275 | fl6->fl6_sport = htons(asoc->base.bind_addr.port); | ||
257 | 276 | ||
258 | if (saddr) { | 277 | if (saddr) { |
259 | ipv6_addr_copy(&fl6.saddr, &saddr->v6.sin6_addr); | 278 | ipv6_addr_copy(&fl6->saddr, &saddr->v6.sin6_addr); |
260 | SCTP_DEBUG_PRINTK("SRC=%pI6 - ", &fl6.saddr); | 279 | fl6->fl6_sport = saddr->v6.sin6_port; |
280 | SCTP_DEBUG_PRINTK("SRC=%pI6 - ", &fl6->saddr); | ||
281 | } | ||
282 | |||
283 | dst = ip6_dst_lookup_flow(sk, fl6, NULL, false); | ||
284 | if (!asoc || saddr) | ||
285 | goto out; | ||
286 | |||
287 | bp = &asoc->base.bind_addr; | ||
288 | scope = sctp_scope(daddr); | ||
289 | /* ip6_dst_lookup has filled in the fl6->saddr for us. Check | ||
290 | * to see if we can use it. | ||
291 | */ | ||
292 | if (!IS_ERR(dst)) { | ||
293 | /* Walk through the bind address list and look for a bind | ||
294 | * address that matches the source address of the returned dst. | ||
295 | */ | ||
296 | sctp_v6_to_addr(&dst_saddr, &fl6->saddr, htons(bp->port)); | ||
297 | rcu_read_lock(); | ||
298 | list_for_each_entry_rcu(laddr, &bp->address_list, list) { | ||
299 | if (!laddr->valid || (laddr->state != SCTP_ADDR_SRC)) | ||
300 | continue; | ||
301 | |||
302 | /* Do not compare against v4 addrs */ | ||
303 | if ((laddr->a.sa.sa_family == AF_INET6) && | ||
304 | (sctp_v6_cmp_addr(&dst_saddr, &laddr->a))) { | ||
305 | rcu_read_unlock(); | ||
306 | goto out; | ||
307 | } | ||
308 | } | ||
309 | rcu_read_unlock(); | ||
310 | /* None of the bound addresses match the source address of the | ||
311 | * dst. So release it. | ||
312 | */ | ||
313 | dst_release(dst); | ||
314 | dst = NULL; | ||
261 | } | 315 | } |
262 | 316 | ||
263 | dst = ip6_route_output(&init_net, NULL, &fl6); | 317 | /* Walk through the bind address list and try to get the |
264 | if (!dst->error) { | 318 | * best source address for a given destination. |
319 | */ | ||
320 | rcu_read_lock(); | ||
321 | list_for_each_entry_rcu(laddr, &bp->address_list, list) { | ||
322 | if (!laddr->valid && laddr->state != SCTP_ADDR_SRC) | ||
323 | continue; | ||
324 | if ((laddr->a.sa.sa_family == AF_INET6) && | ||
325 | (scope <= sctp_scope(&laddr->a))) { | ||
326 | bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a); | ||
327 | if (!baddr || (matchlen < bmatchlen)) { | ||
328 | baddr = &laddr->a; | ||
329 | matchlen = bmatchlen; | ||
330 | } | ||
331 | } | ||
332 | } | ||
333 | rcu_read_unlock(); | ||
334 | if (baddr) { | ||
335 | ipv6_addr_copy(&fl6->saddr, &baddr->v6.sin6_addr); | ||
336 | fl6->fl6_sport = baddr->v6.sin6_port; | ||
337 | dst = ip6_dst_lookup_flow(sk, fl6, NULL, false); | ||
338 | } | ||
339 | |||
340 | out: | ||
341 | if (!IS_ERR(dst)) { | ||
265 | struct rt6_info *rt; | 342 | struct rt6_info *rt; |
266 | rt = (struct rt6_info *)dst; | 343 | rt = (struct rt6_info *)dst; |
344 | t->dst = dst; | ||
267 | SCTP_DEBUG_PRINTK("rt6_dst:%pI6 rt6_src:%pI6\n", | 345 | SCTP_DEBUG_PRINTK("rt6_dst:%pI6 rt6_src:%pI6\n", |
268 | &rt->rt6i_dst.addr, &rt->rt6i_src.addr); | 346 | &rt->rt6i_dst.addr, &fl6->saddr); |
269 | return dst; | 347 | } else { |
348 | t->dst = NULL; | ||
349 | SCTP_DEBUG_PRINTK("NO ROUTE\n"); | ||
270 | } | 350 | } |
271 | SCTP_DEBUG_PRINTK("NO ROUTE\n"); | ||
272 | dst_release(dst); | ||
273 | return NULL; | ||
274 | } | 351 | } |
275 | 352 | ||
276 | /* Returns the number of consecutive initial bits that match in the 2 ipv6 | 353 | /* Returns the number of consecutive initial bits that match in the 2 ipv6 |
@@ -286,64 +363,18 @@ static inline int sctp_v6_addr_match_len(union sctp_addr *s1, | |||
286 | * and asoc's bind address list. | 363 | * and asoc's bind address list. |
287 | */ | 364 | */ |
288 | static void sctp_v6_get_saddr(struct sctp_sock *sk, | 365 | static void sctp_v6_get_saddr(struct sctp_sock *sk, |
289 | struct sctp_association *asoc, | 366 | struct sctp_transport *t, |
290 | struct dst_entry *dst, | 367 | struct flowi *fl) |
291 | union sctp_addr *daddr, | ||
292 | union sctp_addr *saddr) | ||
293 | { | 368 | { |
294 | struct sctp_bind_addr *bp; | 369 | struct flowi6 *fl6 = &fl->u.ip6; |
295 | struct sctp_sockaddr_entry *laddr; | 370 | union sctp_addr *saddr = &t->saddr; |
296 | sctp_scope_t scope; | ||
297 | union sctp_addr *baddr = NULL; | ||
298 | __u8 matchlen = 0; | ||
299 | __u8 bmatchlen; | ||
300 | 371 | ||
301 | SCTP_DEBUG_PRINTK("%s: asoc:%p dst:%p daddr:%pI6 ", | 372 | SCTP_DEBUG_PRINTK("%s: asoc:%p dst:%p\n", __func__, t->asoc, t->dst); |
302 | __func__, asoc, dst, &daddr->v6.sin6_addr); | ||
303 | |||
304 | if (!asoc) { | ||
305 | ipv6_dev_get_saddr(sock_net(sctp_opt2sk(sk)), | ||
306 | dst ? ip6_dst_idev(dst)->dev : NULL, | ||
307 | &daddr->v6.sin6_addr, | ||
308 | inet6_sk(&sk->inet.sk)->srcprefs, | ||
309 | &saddr->v6.sin6_addr); | ||
310 | SCTP_DEBUG_PRINTK("saddr from ipv6_get_saddr: %pI6\n", | ||
311 | &saddr->v6.sin6_addr); | ||
312 | return; | ||
313 | } | ||
314 | |||
315 | scope = sctp_scope(daddr); | ||
316 | |||
317 | bp = &asoc->base.bind_addr; | ||
318 | 373 | ||
319 | /* Go through the bind address list and find the best source address | 374 | if (t->dst) { |
320 | * that matches the scope of the destination address. | 375 | saddr->v6.sin6_family = AF_INET6; |
321 | */ | 376 | ipv6_addr_copy(&saddr->v6.sin6_addr, &fl6->saddr); |
322 | rcu_read_lock(); | ||
323 | list_for_each_entry_rcu(laddr, &bp->address_list, list) { | ||
324 | if (!laddr->valid) | ||
325 | continue; | ||
326 | if ((laddr->state == SCTP_ADDR_SRC) && | ||
327 | (laddr->a.sa.sa_family == AF_INET6) && | ||
328 | (scope <= sctp_scope(&laddr->a))) { | ||
329 | bmatchlen = sctp_v6_addr_match_len(daddr, &laddr->a); | ||
330 | if (!baddr || (matchlen < bmatchlen)) { | ||
331 | baddr = &laddr->a; | ||
332 | matchlen = bmatchlen; | ||
333 | } | ||
334 | } | ||
335 | } | ||
336 | |||
337 | if (baddr) { | ||
338 | memcpy(saddr, baddr, sizeof(union sctp_addr)); | ||
339 | SCTP_DEBUG_PRINTK("saddr: %pI6\n", &saddr->v6.sin6_addr); | ||
340 | } else { | ||
341 | pr_err("%s: asoc:%p Could not find a valid source " | ||
342 | "address for the dest:%pI6\n", | ||
343 | __func__, asoc, &daddr->v6.sin6_addr); | ||
344 | } | 377 | } |
345 | |||
346 | rcu_read_unlock(); | ||
347 | } | 378 | } |
348 | 379 | ||
349 | /* Make a copy of all potential local addresses. */ | 380 | /* Make a copy of all potential local addresses. */ |
@@ -465,14 +496,13 @@ static int sctp_v6_to_addr_param(const union sctp_addr *addr, | |||
465 | return length; | 496 | return length; |
466 | } | 497 | } |
467 | 498 | ||
468 | /* Initialize a sctp_addr from a dst_entry. */ | 499 | /* Initialize a sctp_addr from struct in6_addr. */ |
469 | static void sctp_v6_dst_saddr(union sctp_addr *addr, struct dst_entry *dst, | 500 | static void sctp_v6_to_addr(union sctp_addr *addr, struct in6_addr *saddr, |
470 | __be16 port) | 501 | __be16 port) |
471 | { | 502 | { |
472 | struct rt6_info *rt = (struct rt6_info *)dst; | ||
473 | addr->sa.sa_family = AF_INET6; | 503 | addr->sa.sa_family = AF_INET6; |
474 | addr->v6.sin6_port = port; | 504 | addr->v6.sin6_port = port; |
475 | ipv6_addr_copy(&addr->v6.sin6_addr, &rt->rt6i_src.addr); | 505 | ipv6_addr_copy(&addr->v6.sin6_addr, saddr); |
476 | } | 506 | } |
477 | 507 | ||
478 | /* Compare addresses exactly. | 508 | /* Compare addresses exactly. |
@@ -531,7 +561,7 @@ static int sctp_v6_is_any(const union sctp_addr *addr) | |||
531 | static int sctp_v6_available(union sctp_addr *addr, struct sctp_sock *sp) | 561 | static int sctp_v6_available(union sctp_addr *addr, struct sctp_sock *sp) |
532 | { | 562 | { |
533 | int type; | 563 | int type; |
534 | struct in6_addr *in6 = (struct in6_addr *)&addr->v6.sin6_addr; | 564 | const struct in6_addr *in6 = (const struct in6_addr *)&addr->v6.sin6_addr; |
535 | 565 | ||
536 | type = ipv6_addr_type(in6); | 566 | type = ipv6_addr_type(in6); |
537 | if (IPV6_ADDR_ANY == type) | 567 | if (IPV6_ADDR_ANY == type) |
@@ -959,7 +989,6 @@ static struct sctp_af sctp_af_inet6 = { | |||
959 | .to_sk_daddr = sctp_v6_to_sk_daddr, | 989 | .to_sk_daddr = sctp_v6_to_sk_daddr, |
960 | .from_addr_param = sctp_v6_from_addr_param, | 990 | .from_addr_param = sctp_v6_from_addr_param, |
961 | .to_addr_param = sctp_v6_to_addr_param, | 991 | .to_addr_param = sctp_v6_to_addr_param, |
962 | .dst_saddr = sctp_v6_dst_saddr, | ||
963 | .cmp_addr = sctp_v6_cmp_addr, | 992 | .cmp_addr = sctp_v6_cmp_addr, |
964 | .scope = sctp_v6_scope, | 993 | .scope = sctp_v6_scope, |
965 | .addr_valid = sctp_v6_addr_valid, | 994 | .addr_valid = sctp_v6_addr_valid, |
diff --git a/net/sctp/output.c b/net/sctp/output.c index 60600d337a3a..b4f3cf06d8da 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c | |||
@@ -510,7 +510,7 @@ int sctp_packet_transmit(struct sctp_packet *packet) | |||
510 | sh->checksum = sctp_end_cksum(crc32); | 510 | sh->checksum = sctp_end_cksum(crc32); |
511 | } else { | 511 | } else { |
512 | if (dst->dev->features & NETIF_F_SCTP_CSUM) { | 512 | if (dst->dev->features & NETIF_F_SCTP_CSUM) { |
513 | /* no need to seed psuedo checksum for SCTP */ | 513 | /* no need to seed pseudo checksum for SCTP */ |
514 | nskb->ip_summed = CHECKSUM_PARTIAL; | 514 | nskb->ip_summed = CHECKSUM_PARTIAL; |
515 | nskb->csum_start = (skb_transport_header(nskb) - | 515 | nskb->csum_start = (skb_transport_header(nskb) - |
516 | nskb->head); | 516 | nskb->head); |
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 26dc005113a0..1c88c8911dc5 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
@@ -131,7 +131,8 @@ static inline int sctp_cacc_skip_3_1_d(struct sctp_transport *primary, | |||
131 | static inline int sctp_cacc_skip_3_1_f(struct sctp_transport *transport, | 131 | static inline int sctp_cacc_skip_3_1_f(struct sctp_transport *transport, |
132 | int count_of_newacks) | 132 | int count_of_newacks) |
133 | { | 133 | { |
134 | if (count_of_newacks < 2 && !transport->cacc.cacc_saw_newack) | 134 | if (count_of_newacks < 2 && |
135 | (transport && !transport->cacc.cacc_saw_newack)) | ||
135 | return 1; | 136 | return 1; |
136 | return 0; | 137 | return 0; |
137 | } | 138 | } |
@@ -177,13 +178,13 @@ static inline int sctp_cacc_skip_3_2(struct sctp_transport *primary, __u32 tsn) | |||
177 | * 3) If the missing report count for TSN t is to be | 178 | * 3) If the missing report count for TSN t is to be |
178 | * incremented according to [RFC2960] and | 179 | * incremented according to [RFC2960] and |
179 | * [SCTP_STEWART-2002], and CHANGEOVER_ACTIVE is set, | 180 | * [SCTP_STEWART-2002], and CHANGEOVER_ACTIVE is set, |
180 | * then the sender MUST futher execute steps 3.1 and | 181 | * then the sender MUST further execute steps 3.1 and |
181 | * 3.2 to determine if the missing report count for | 182 | * 3.2 to determine if the missing report count for |
182 | * TSN t SHOULD NOT be incremented. | 183 | * TSN t SHOULD NOT be incremented. |
183 | * | 184 | * |
184 | * 3.3) If 3.1 and 3.2 do not dictate that the missing | 185 | * 3.3) If 3.1 and 3.2 do not dictate that the missing |
185 | * report count for t should not be incremented, then | 186 | * report count for t should not be incremented, then |
186 | * the sender SOULD increment missing report count for | 187 | * the sender SHOULD increment missing report count for |
187 | * t (according to [RFC2960] and [SCTP_STEWART_2002]). | 188 | * t (according to [RFC2960] and [SCTP_STEWART_2002]). |
188 | */ | 189 | */ |
189 | static inline int sctp_cacc_skip(struct sctp_transport *primary, | 190 | static inline int sctp_cacc_skip(struct sctp_transport *primary, |
@@ -319,7 +320,6 @@ int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk) | |||
319 | * chunk. | 320 | * chunk. |
320 | */ | 321 | */ |
321 | switch (q->asoc->state) { | 322 | switch (q->asoc->state) { |
322 | case SCTP_STATE_EMPTY: | ||
323 | case SCTP_STATE_CLOSED: | 323 | case SCTP_STATE_CLOSED: |
324 | case SCTP_STATE_SHUTDOWN_PENDING: | 324 | case SCTP_STATE_SHUTDOWN_PENDING: |
325 | case SCTP_STATE_SHUTDOWN_SENT: | 325 | case SCTP_STATE_SHUTDOWN_SENT: |
@@ -577,6 +577,13 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt, | |||
577 | * try to send as much as possible. | 577 | * try to send as much as possible. |
578 | */ | 578 | */ |
579 | list_for_each_entry_safe(chunk, chunk1, lqueue, transmitted_list) { | 579 | list_for_each_entry_safe(chunk, chunk1, lqueue, transmitted_list) { |
580 | /* If the chunk is abandoned, move it to abandoned list. */ | ||
581 | if (sctp_chunk_abandoned(chunk)) { | ||
582 | list_del_init(&chunk->transmitted_list); | ||
583 | sctp_insert_list(&q->abandoned, | ||
584 | &chunk->transmitted_list); | ||
585 | continue; | ||
586 | } | ||
580 | 587 | ||
581 | /* Make sure that Gap Acked TSNs are not retransmitted. A | 588 | /* Make sure that Gap Acked TSNs are not retransmitted. A |
582 | * simple approach is just to move such TSNs out of the | 589 | * simple approach is just to move such TSNs out of the |
@@ -618,9 +625,12 @@ redo: | |||
618 | 625 | ||
619 | /* If we are retransmitting, we should only | 626 | /* If we are retransmitting, we should only |
620 | * send a single packet. | 627 | * send a single packet. |
628 | * Otherwise, try appending this chunk again. | ||
621 | */ | 629 | */ |
622 | if (rtx_timeout || fast_rtx) | 630 | if (rtx_timeout || fast_rtx) |
623 | done = 1; | 631 | done = 1; |
632 | else | ||
633 | goto redo; | ||
624 | 634 | ||
625 | /* Bundle next chunk in the next round. */ | 635 | /* Bundle next chunk in the next round. */ |
626 | break; | 636 | break; |
@@ -843,7 +853,7 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
843 | case SCTP_CID_ECN_CWR: | 853 | case SCTP_CID_ECN_CWR: |
844 | case SCTP_CID_ASCONF_ACK: | 854 | case SCTP_CID_ASCONF_ACK: |
845 | one_packet = 1; | 855 | one_packet = 1; |
846 | /* Fall throught */ | 856 | /* Fall through */ |
847 | 857 | ||
848 | case SCTP_CID_SACK: | 858 | case SCTP_CID_SACK: |
849 | case SCTP_CID_HEARTBEAT: | 859 | case SCTP_CID_HEARTBEAT: |
@@ -1683,8 +1693,9 @@ static void sctp_mark_missing(struct sctp_outq *q, | |||
1683 | /* SFR-CACC may require us to skip marking | 1693 | /* SFR-CACC may require us to skip marking |
1684 | * this chunk as missing. | 1694 | * this chunk as missing. |
1685 | */ | 1695 | */ |
1686 | if (!transport || !sctp_cacc_skip(primary, transport, | 1696 | if (!transport || !sctp_cacc_skip(primary, |
1687 | count_of_newacks, tsn)) { | 1697 | chunk->transport, |
1698 | count_of_newacks, tsn)) { | ||
1688 | chunk->tsn_missing_report++; | 1699 | chunk->tsn_missing_report++; |
1689 | 1700 | ||
1690 | SCTP_DEBUG_PRINTK( | 1701 | SCTP_DEBUG_PRINTK( |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index d5bf91d04f63..4de77cb80d88 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -339,13 +339,12 @@ static int sctp_v4_to_addr_param(const union sctp_addr *addr, | |||
339 | } | 339 | } |
340 | 340 | ||
341 | /* Initialize a sctp_addr from a dst_entry. */ | 341 | /* Initialize a sctp_addr from a dst_entry. */ |
342 | static void sctp_v4_dst_saddr(union sctp_addr *saddr, struct dst_entry *dst, | 342 | static void sctp_v4_dst_saddr(union sctp_addr *saddr, struct flowi4 *fl4, |
343 | __be16 port) | 343 | __be16 port) |
344 | { | 344 | { |
345 | struct rtable *rt = (struct rtable *)dst; | ||
346 | saddr->v4.sin_family = AF_INET; | 345 | saddr->v4.sin_family = AF_INET; |
347 | saddr->v4.sin_port = port; | 346 | saddr->v4.sin_port = port; |
348 | saddr->v4.sin_addr.s_addr = rt->rt_src; | 347 | saddr->v4.sin_addr.s_addr = fl4->saddr; |
349 | } | 348 | } |
350 | 349 | ||
351 | /* Compare two addresses exactly. */ | 350 | /* Compare two addresses exactly. */ |
@@ -463,35 +462,36 @@ static sctp_scope_t sctp_v4_scope(union sctp_addr *addr) | |||
463 | * addresses. If an association is passed, trys to get a dst entry with a | 462 | * addresses. If an association is passed, trys to get a dst entry with a |
464 | * source address that matches an address in the bind address list. | 463 | * source address that matches an address in the bind address list. |
465 | */ | 464 | */ |
466 | static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, | 465 | static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr, |
467 | union sctp_addr *daddr, | 466 | struct flowi *fl, struct sock *sk) |
468 | union sctp_addr *saddr) | ||
469 | { | 467 | { |
468 | struct sctp_association *asoc = t->asoc; | ||
470 | struct rtable *rt; | 469 | struct rtable *rt; |
471 | struct flowi4 fl4; | 470 | struct flowi4 *fl4 = &fl->u.ip4; |
472 | struct sctp_bind_addr *bp; | 471 | struct sctp_bind_addr *bp; |
473 | struct sctp_sockaddr_entry *laddr; | 472 | struct sctp_sockaddr_entry *laddr; |
474 | struct dst_entry *dst = NULL; | 473 | struct dst_entry *dst = NULL; |
474 | union sctp_addr *daddr = &t->ipaddr; | ||
475 | union sctp_addr dst_saddr; | 475 | union sctp_addr dst_saddr; |
476 | 476 | ||
477 | memset(&fl4, 0x0, sizeof(struct flowi4)); | 477 | memset(fl4, 0x0, sizeof(struct flowi4)); |
478 | fl4.daddr = daddr->v4.sin_addr.s_addr; | 478 | fl4->daddr = daddr->v4.sin_addr.s_addr; |
479 | fl4.fl4_dport = daddr->v4.sin_port; | 479 | fl4->fl4_dport = daddr->v4.sin_port; |
480 | fl4.flowi4_proto = IPPROTO_SCTP; | 480 | fl4->flowi4_proto = IPPROTO_SCTP; |
481 | if (asoc) { | 481 | if (asoc) { |
482 | fl4.flowi4_tos = RT_CONN_FLAGS(asoc->base.sk); | 482 | fl4->flowi4_tos = RT_CONN_FLAGS(asoc->base.sk); |
483 | fl4.flowi4_oif = asoc->base.sk->sk_bound_dev_if; | 483 | fl4->flowi4_oif = asoc->base.sk->sk_bound_dev_if; |
484 | fl4.fl4_sport = htons(asoc->base.bind_addr.port); | 484 | fl4->fl4_sport = htons(asoc->base.bind_addr.port); |
485 | } | 485 | } |
486 | if (saddr) { | 486 | if (saddr) { |
487 | fl4.saddr = saddr->v4.sin_addr.s_addr; | 487 | fl4->saddr = saddr->v4.sin_addr.s_addr; |
488 | fl4.fl4_sport = saddr->v4.sin_port; | 488 | fl4->fl4_sport = saddr->v4.sin_port; |
489 | } | 489 | } |
490 | 490 | ||
491 | SCTP_DEBUG_PRINTK("%s: DST:%pI4, SRC:%pI4 - ", | 491 | SCTP_DEBUG_PRINTK("%s: DST:%pI4, SRC:%pI4 - ", |
492 | __func__, &fl4.daddr, &fl4.saddr); | 492 | __func__, &fl4->daddr, &fl4->saddr); |
493 | 493 | ||
494 | rt = ip_route_output_key(&init_net, &fl4); | 494 | rt = ip_route_output_key(&init_net, fl4); |
495 | if (!IS_ERR(rt)) | 495 | if (!IS_ERR(rt)) |
496 | dst = &rt->dst; | 496 | dst = &rt->dst; |
497 | 497 | ||
@@ -507,7 +507,7 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, | |||
507 | /* Walk through the bind address list and look for a bind | 507 | /* Walk through the bind address list and look for a bind |
508 | * address that matches the source address of the returned dst. | 508 | * address that matches the source address of the returned dst. |
509 | */ | 509 | */ |
510 | sctp_v4_dst_saddr(&dst_saddr, dst, htons(bp->port)); | 510 | sctp_v4_dst_saddr(&dst_saddr, fl4, htons(bp->port)); |
511 | rcu_read_lock(); | 511 | rcu_read_lock(); |
512 | list_for_each_entry_rcu(laddr, &bp->address_list, list) { | 512 | list_for_each_entry_rcu(laddr, &bp->address_list, list) { |
513 | if (!laddr->valid || (laddr->state != SCTP_ADDR_SRC)) | 513 | if (!laddr->valid || (laddr->state != SCTP_ADDR_SRC)) |
@@ -533,9 +533,9 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, | |||
533 | continue; | 533 | continue; |
534 | if ((laddr->state == SCTP_ADDR_SRC) && | 534 | if ((laddr->state == SCTP_ADDR_SRC) && |
535 | (AF_INET == laddr->a.sa.sa_family)) { | 535 | (AF_INET == laddr->a.sa.sa_family)) { |
536 | fl4.saddr = laddr->a.v4.sin_addr.s_addr; | 536 | fl4->saddr = laddr->a.v4.sin_addr.s_addr; |
537 | fl4.fl4_sport = laddr->a.v4.sin_port; | 537 | fl4->fl4_sport = laddr->a.v4.sin_port; |
538 | rt = ip_route_output_key(&init_net, &fl4); | 538 | rt = ip_route_output_key(&init_net, fl4); |
539 | if (!IS_ERR(rt)) { | 539 | if (!IS_ERR(rt)) { |
540 | dst = &rt->dst; | 540 | dst = &rt->dst; |
541 | goto out_unlock; | 541 | goto out_unlock; |
@@ -546,33 +546,27 @@ static struct dst_entry *sctp_v4_get_dst(struct sctp_association *asoc, | |||
546 | out_unlock: | 546 | out_unlock: |
547 | rcu_read_unlock(); | 547 | rcu_read_unlock(); |
548 | out: | 548 | out: |
549 | t->dst = dst; | ||
549 | if (dst) | 550 | if (dst) |
550 | SCTP_DEBUG_PRINTK("rt_dst:%pI4, rt_src:%pI4\n", | 551 | SCTP_DEBUG_PRINTK("rt_dst:%pI4, rt_src:%pI4\n", |
551 | &rt->rt_dst, &rt->rt_src); | 552 | &fl4->daddr, &fl4->saddr); |
552 | else | 553 | else |
553 | SCTP_DEBUG_PRINTK("NO ROUTE\n"); | 554 | SCTP_DEBUG_PRINTK("NO ROUTE\n"); |
554 | |||
555 | return dst; | ||
556 | } | 555 | } |
557 | 556 | ||
558 | /* For v4, the source address is cached in the route entry(dst). So no need | 557 | /* For v4, the source address is cached in the route entry(dst). So no need |
559 | * to cache it separately and hence this is an empty routine. | 558 | * to cache it separately and hence this is an empty routine. |
560 | */ | 559 | */ |
561 | static void sctp_v4_get_saddr(struct sctp_sock *sk, | 560 | static void sctp_v4_get_saddr(struct sctp_sock *sk, |
562 | struct sctp_association *asoc, | 561 | struct sctp_transport *t, |
563 | struct dst_entry *dst, | 562 | struct flowi *fl) |
564 | union sctp_addr *daddr, | ||
565 | union sctp_addr *saddr) | ||
566 | { | 563 | { |
567 | struct rtable *rt = (struct rtable *)dst; | 564 | union sctp_addr *saddr = &t->saddr; |
568 | 565 | struct rtable *rt = (struct rtable *)t->dst; | |
569 | if (!asoc) | ||
570 | return; | ||
571 | 566 | ||
572 | if (rt) { | 567 | if (rt) { |
573 | saddr->v4.sin_family = AF_INET; | 568 | saddr->v4.sin_family = AF_INET; |
574 | saddr->v4.sin_port = htons(asoc->base.bind_addr.port); | 569 | saddr->v4.sin_addr.s_addr = fl->u.ip4.saddr; |
575 | saddr->v4.sin_addr.s_addr = rt->rt_src; | ||
576 | } | 570 | } |
577 | } | 571 | } |
578 | 572 | ||
@@ -854,14 +848,14 @@ static inline int sctp_v4_xmit(struct sk_buff *skb, | |||
854 | 848 | ||
855 | SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, src:%pI4, dst:%pI4\n", | 849 | SCTP_DEBUG_PRINTK("%s: skb:%p, len:%d, src:%pI4, dst:%pI4\n", |
856 | __func__, skb, skb->len, | 850 | __func__, skb, skb->len, |
857 | &skb_rtable(skb)->rt_src, | 851 | &transport->fl.u.ip4.saddr, |
858 | &skb_rtable(skb)->rt_dst); | 852 | &transport->fl.u.ip4.daddr); |
859 | 853 | ||
860 | inet->pmtudisc = transport->param_flags & SPP_PMTUD_ENABLE ? | 854 | inet->pmtudisc = transport->param_flags & SPP_PMTUD_ENABLE ? |
861 | IP_PMTUDISC_DO : IP_PMTUDISC_DONT; | 855 | IP_PMTUDISC_DO : IP_PMTUDISC_DONT; |
862 | 856 | ||
863 | SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS); | 857 | SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS); |
864 | return ip_queue_xmit(skb); | 858 | return ip_queue_xmit(skb, &transport->fl); |
865 | } | 859 | } |
866 | 860 | ||
867 | static struct sctp_af sctp_af_inet; | 861 | static struct sctp_af sctp_af_inet; |
@@ -950,7 +944,6 @@ static struct sctp_af sctp_af_inet = { | |||
950 | .to_sk_daddr = sctp_v4_to_sk_daddr, | 944 | .to_sk_daddr = sctp_v4_to_sk_daddr, |
951 | .from_addr_param = sctp_v4_from_addr_param, | 945 | .from_addr_param = sctp_v4_from_addr_param, |
952 | .to_addr_param = sctp_v4_to_addr_param, | 946 | .to_addr_param = sctp_v4_to_addr_param, |
953 | .dst_saddr = sctp_v4_dst_saddr, | ||
954 | .cmp_addr = sctp_v4_cmp_addr, | 947 | .cmp_addr = sctp_v4_cmp_addr, |
955 | .addr_valid = sctp_v4_addr_valid, | 948 | .addr_valid = sctp_v4_addr_valid, |
956 | .inaddr_any = sctp_v4_inaddr_any, | 949 | .inaddr_any = sctp_v4_inaddr_any, |
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index b3434cc7d0cf..58eb27fed4b4 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -1075,20 +1075,28 @@ nodata: | |||
1075 | 1075 | ||
1076 | /* Make a HEARTBEAT chunk. */ | 1076 | /* Make a HEARTBEAT chunk. */ |
1077 | struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc, | 1077 | struct sctp_chunk *sctp_make_heartbeat(const struct sctp_association *asoc, |
1078 | const struct sctp_transport *transport, | 1078 | const struct sctp_transport *transport) |
1079 | const void *payload, const size_t paylen) | ||
1080 | { | 1079 | { |
1081 | struct sctp_chunk *retval = sctp_make_chunk(asoc, SCTP_CID_HEARTBEAT, | 1080 | struct sctp_chunk *retval; |
1082 | 0, paylen); | 1081 | sctp_sender_hb_info_t hbinfo; |
1082 | |||
1083 | retval = sctp_make_chunk(asoc, SCTP_CID_HEARTBEAT, 0, sizeof(hbinfo)); | ||
1083 | 1084 | ||
1084 | if (!retval) | 1085 | if (!retval) |
1085 | goto nodata; | 1086 | goto nodata; |
1086 | 1087 | ||
1088 | hbinfo.param_hdr.type = SCTP_PARAM_HEARTBEAT_INFO; | ||
1089 | hbinfo.param_hdr.length = htons(sizeof(sctp_sender_hb_info_t)); | ||
1090 | hbinfo.daddr = transport->ipaddr; | ||
1091 | hbinfo.sent_at = jiffies; | ||
1092 | hbinfo.hb_nonce = transport->hb_nonce; | ||
1093 | |||
1087 | /* Cast away the 'const', as this is just telling the chunk | 1094 | /* Cast away the 'const', as this is just telling the chunk |
1088 | * what transport it belongs to. | 1095 | * what transport it belongs to. |
1089 | */ | 1096 | */ |
1090 | retval->transport = (struct sctp_transport *) transport; | 1097 | retval->transport = (struct sctp_transport *) transport; |
1091 | retval->subh.hbs_hdr = sctp_addto_chunk(retval, paylen, payload); | 1098 | retval->subh.hbs_hdr = sctp_addto_chunk(retval, sizeof(hbinfo), |
1099 | &hbinfo); | ||
1092 | 1100 | ||
1093 | nodata: | 1101 | nodata: |
1094 | return retval; | 1102 | return retval; |
@@ -2242,14 +2250,17 @@ int sctp_verify_init(const struct sctp_association *asoc, | |||
2242 | * Returns 0 on failure, else success. | 2250 | * Returns 0 on failure, else success. |
2243 | * FIXME: This is an association method. | 2251 | * FIXME: This is an association method. |
2244 | */ | 2252 | */ |
2245 | int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, | 2253 | int sctp_process_init(struct sctp_association *asoc, struct sctp_chunk *chunk, |
2246 | const union sctp_addr *peer_addr, | 2254 | const union sctp_addr *peer_addr, |
2247 | sctp_init_chunk_t *peer_init, gfp_t gfp) | 2255 | sctp_init_chunk_t *peer_init, gfp_t gfp) |
2248 | { | 2256 | { |
2249 | union sctp_params param; | 2257 | union sctp_params param; |
2250 | struct sctp_transport *transport; | 2258 | struct sctp_transport *transport; |
2251 | struct list_head *pos, *temp; | 2259 | struct list_head *pos, *temp; |
2260 | struct sctp_af *af; | ||
2261 | union sctp_addr addr; | ||
2252 | char *cookie; | 2262 | char *cookie; |
2263 | int src_match = 0; | ||
2253 | 2264 | ||
2254 | /* We must include the address that the INIT packet came from. | 2265 | /* We must include the address that the INIT packet came from. |
2255 | * This is the only address that matters for an INIT packet. | 2266 | * This is the only address that matters for an INIT packet. |
@@ -2261,18 +2272,31 @@ int sctp_process_init(struct sctp_association *asoc, sctp_cid_t cid, | |||
2261 | * added as the primary transport. The source address seems to | 2272 | * added as the primary transport. The source address seems to |
2262 | * be a a better choice than any of the embedded addresses. | 2273 | * be a a better choice than any of the embedded addresses. |
2263 | */ | 2274 | */ |
2264 | if (peer_addr) { | 2275 | if(!sctp_assoc_add_peer(asoc, peer_addr, gfp, SCTP_ACTIVE)) |
2265 | if(!sctp_assoc_add_peer(asoc, peer_addr, gfp, SCTP_ACTIVE)) | 2276 | goto nomem; |
2266 | goto nomem; | 2277 | |
2267 | } | 2278 | if (sctp_cmp_addr_exact(sctp_source(chunk), peer_addr)) |
2279 | src_match = 1; | ||
2268 | 2280 | ||
2269 | /* Process the initialization parameters. */ | 2281 | /* Process the initialization parameters. */ |
2270 | sctp_walk_params(param, peer_init, init_hdr.params) { | 2282 | sctp_walk_params(param, peer_init, init_hdr.params) { |
2283 | if (!src_match && (param.p->type == SCTP_PARAM_IPV4_ADDRESS || | ||
2284 | param.p->type == SCTP_PARAM_IPV6_ADDRESS)) { | ||
2285 | af = sctp_get_af_specific(param_type2af(param.p->type)); | ||
2286 | af->from_addr_param(&addr, param.addr, | ||
2287 | chunk->sctp_hdr->source, 0); | ||
2288 | if (sctp_cmp_addr_exact(sctp_source(chunk), &addr)) | ||
2289 | src_match = 1; | ||
2290 | } | ||
2271 | 2291 | ||
2272 | if (!sctp_process_param(asoc, param, peer_addr, gfp)) | 2292 | if (!sctp_process_param(asoc, param, peer_addr, gfp)) |
2273 | goto clean_up; | 2293 | goto clean_up; |
2274 | } | 2294 | } |
2275 | 2295 | ||
2296 | /* source address of chunk may not match any valid address */ | ||
2297 | if (!src_match) | ||
2298 | goto clean_up; | ||
2299 | |||
2276 | /* AUTH: After processing the parameters, make sure that we | 2300 | /* AUTH: After processing the parameters, make sure that we |
2277 | * have all the required info to potentially do authentications. | 2301 | * have all the required info to potentially do authentications. |
2278 | */ | 2302 | */ |
@@ -2923,7 +2947,7 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, | |||
2923 | asconf_param->param_hdr.type != SCTP_PARAM_SET_PRIMARY) | 2947 | asconf_param->param_hdr.type != SCTP_PARAM_SET_PRIMARY) |
2924 | return SCTP_ERROR_UNKNOWN_PARAM; | 2948 | return SCTP_ERROR_UNKNOWN_PARAM; |
2925 | 2949 | ||
2926 | switch (addr_param->v4.param_hdr.type) { | 2950 | switch (addr_param->p.type) { |
2927 | case SCTP_PARAM_IPV6_ADDRESS: | 2951 | case SCTP_PARAM_IPV6_ADDRESS: |
2928 | if (!asoc->peer.ipv6_address) | 2952 | if (!asoc->peer.ipv6_address) |
2929 | return SCTP_ERROR_DNS_FAILED; | 2953 | return SCTP_ERROR_DNS_FAILED; |
@@ -2936,7 +2960,7 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc, | |||
2936 | return SCTP_ERROR_DNS_FAILED; | 2960 | return SCTP_ERROR_DNS_FAILED; |
2937 | } | 2961 | } |
2938 | 2962 | ||
2939 | af = sctp_get_af_specific(param_type2af(addr_param->v4.param_hdr.type)); | 2963 | af = sctp_get_af_specific(param_type2af(addr_param->p.type)); |
2940 | if (unlikely(!af)) | 2964 | if (unlikely(!af)) |
2941 | return SCTP_ERROR_DNS_FAILED; | 2965 | return SCTP_ERROR_DNS_FAILED; |
2942 | 2966 | ||
@@ -3100,7 +3124,7 @@ struct sctp_chunk *sctp_process_asconf(struct sctp_association *asoc, | |||
3100 | /* Skip the address parameter and store a pointer to the first | 3124 | /* Skip the address parameter and store a pointer to the first |
3101 | * asconf parameter. | 3125 | * asconf parameter. |
3102 | */ | 3126 | */ |
3103 | length = ntohs(addr_param->v4.param_hdr.length); | 3127 | length = ntohs(addr_param->p.length); |
3104 | asconf_param = (sctp_addip_param_t *)((void *)addr_param + length); | 3128 | asconf_param = (sctp_addip_param_t *)((void *)addr_param + length); |
3105 | chunk_len -= length; | 3129 | chunk_len -= length; |
3106 | 3130 | ||
@@ -3177,7 +3201,7 @@ static void sctp_asconf_param_success(struct sctp_association *asoc, | |||
3177 | ((void *)asconf_param + sizeof(sctp_addip_param_t)); | 3201 | ((void *)asconf_param + sizeof(sctp_addip_param_t)); |
3178 | 3202 | ||
3179 | /* We have checked the packet before, so we do not check again. */ | 3203 | /* We have checked the packet before, so we do not check again. */ |
3180 | af = sctp_get_af_specific(param_type2af(addr_param->v4.param_hdr.type)); | 3204 | af = sctp_get_af_specific(param_type2af(addr_param->p.type)); |
3181 | af->from_addr_param(&addr, addr_param, htons(bp->port), 0); | 3205 | af->from_addr_param(&addr, addr_param, htons(bp->port), 0); |
3182 | 3206 | ||
3183 | switch (asconf_param->param_hdr.type) { | 3207 | switch (asconf_param->param_hdr.type) { |
@@ -3193,11 +3217,8 @@ static void sctp_asconf_param_success(struct sctp_association *asoc, | |||
3193 | local_bh_enable(); | 3217 | local_bh_enable(); |
3194 | list_for_each_entry(transport, &asoc->peer.transport_addr_list, | 3218 | list_for_each_entry(transport, &asoc->peer.transport_addr_list, |
3195 | transports) { | 3219 | transports) { |
3196 | if (transport->state == SCTP_ACTIVE) | ||
3197 | continue; | ||
3198 | dst_release(transport->dst); | 3220 | dst_release(transport->dst); |
3199 | sctp_transport_route(transport, NULL, | 3221 | transport->dst = NULL; |
3200 | sctp_sk(asoc->base.sk)); | ||
3201 | } | 3222 | } |
3202 | break; | 3223 | break; |
3203 | case SCTP_PARAM_DEL_IP: | 3224 | case SCTP_PARAM_DEL_IP: |
@@ -3207,8 +3228,7 @@ static void sctp_asconf_param_success(struct sctp_association *asoc, | |||
3207 | list_for_each_entry(transport, &asoc->peer.transport_addr_list, | 3228 | list_for_each_entry(transport, &asoc->peer.transport_addr_list, |
3208 | transports) { | 3229 | transports) { |
3209 | dst_release(transport->dst); | 3230 | dst_release(transport->dst); |
3210 | sctp_transport_route(transport, NULL, | 3231 | transport->dst = NULL; |
3211 | sctp_sk(asoc->base.sk)); | ||
3212 | } | 3232 | } |
3213 | break; | 3233 | break; |
3214 | default: | 3234 | default: |
@@ -3304,7 +3324,7 @@ int sctp_process_asconf_ack(struct sctp_association *asoc, | |||
3304 | /* Skip the address parameter in the last asconf sent and store a | 3324 | /* Skip the address parameter in the last asconf sent and store a |
3305 | * pointer to the first asconf parameter. | 3325 | * pointer to the first asconf parameter. |
3306 | */ | 3326 | */ |
3307 | length = ntohs(addr_param->v4.param_hdr.length); | 3327 | length = ntohs(addr_param->p.length); |
3308 | asconf_param = (sctp_addip_param_t *)((void *)addr_param + length); | 3328 | asconf_param = (sctp_addip_param_t *)((void *)addr_param + length); |
3309 | asconf_len -= length; | 3329 | asconf_len -= length; |
3310 | 3330 | ||
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index b21b218d564f..d612ca1ca6c0 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -482,7 +482,7 @@ static void sctp_do_8_2_transport_strike(struct sctp_association *asoc, | |||
482 | * If the timer was a heartbeat, we only increment error counts | 482 | * If the timer was a heartbeat, we only increment error counts |
483 | * when we already have an outstanding HEARTBEAT that has not | 483 | * when we already have an outstanding HEARTBEAT that has not |
484 | * been acknowledged. | 484 | * been acknowledged. |
485 | * Additionaly, some tranport states inhibit error increments. | 485 | * Additionally, some tranport states inhibit error increments. |
486 | */ | 486 | */ |
487 | if (!is_hb) { | 487 | if (!is_hb) { |
488 | asoc->overall_error_count++; | 488 | asoc->overall_error_count++; |
@@ -595,8 +595,7 @@ static int sctp_cmd_process_init(sctp_cmd_seq_t *commands, | |||
595 | * fail during INIT processing (due to malloc problems), | 595 | * fail during INIT processing (due to malloc problems), |
596 | * just return the error and stop processing the stack. | 596 | * just return the error and stop processing the stack. |
597 | */ | 597 | */ |
598 | if (!sctp_process_init(asoc, chunk->chunk_hdr->type, | 598 | if (!sctp_process_init(asoc, chunk, sctp_source(chunk), peer_init, gfp)) |
599 | sctp_source(chunk), peer_init, gfp)) | ||
600 | error = -ENOMEM; | 599 | error = -ENOMEM; |
601 | else | 600 | else |
602 | error = 0; | 601 | error = 0; |
@@ -1415,12 +1414,6 @@ static int sctp_cmd_interpreter(sctp_event_t event_type, | |||
1415 | SCTP_RTXR_T3_RTX); | 1414 | SCTP_RTXR_T3_RTX); |
1416 | break; | 1415 | break; |
1417 | 1416 | ||
1418 | case SCTP_CMD_TRANSMIT: | ||
1419 | /* Kick start transmission. */ | ||
1420 | error = sctp_outq_uncork(&asoc->outqueue); | ||
1421 | local_cork = 0; | ||
1422 | break; | ||
1423 | |||
1424 | case SCTP_CMD_ECN_CE: | 1417 | case SCTP_CMD_ECN_CE: |
1425 | /* Do delayed CE processing. */ | 1418 | /* Do delayed CE processing. */ |
1426 | sctp_do_ecn_ce_work(asoc, cmd->obj.u32); | 1419 | sctp_do_ecn_ce_work(asoc, cmd->obj.u32); |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 4b4eb7c96bbd..7f4a4f8368ee 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -393,8 +393,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep, | |||
393 | goto nomem_init; | 393 | goto nomem_init; |
394 | 394 | ||
395 | /* The call, sctp_process_init(), can fail on memory allocation. */ | 395 | /* The call, sctp_process_init(), can fail on memory allocation. */ |
396 | if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type, | 396 | if (!sctp_process_init(new_asoc, chunk, sctp_source(chunk), |
397 | sctp_source(chunk), | ||
398 | (sctp_init_chunk_t *)chunk->chunk_hdr, | 397 | (sctp_init_chunk_t *)chunk->chunk_hdr, |
399 | GFP_ATOMIC)) | 398 | GFP_ATOMIC)) |
400 | goto nomem_init; | 399 | goto nomem_init; |
@@ -551,7 +550,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep, | |||
551 | * | 550 | * |
552 | * This means that if we only want to abort associations | 551 | * This means that if we only want to abort associations |
553 | * in an authenticated way (i.e AUTH+ABORT), then we | 552 | * in an authenticated way (i.e AUTH+ABORT), then we |
554 | * can't destroy this association just becuase the packet | 553 | * can't destroy this association just because the packet |
555 | * was malformed. | 554 | * was malformed. |
556 | */ | 555 | */ |
557 | if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) | 556 | if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) |
@@ -725,7 +724,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, | |||
725 | */ | 724 | */ |
726 | peer_init = &chunk->subh.cookie_hdr->c.peer_init[0]; | 725 | peer_init = &chunk->subh.cookie_hdr->c.peer_init[0]; |
727 | 726 | ||
728 | if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type, | 727 | if (!sctp_process_init(new_asoc, chunk, |
729 | &chunk->subh.cookie_hdr->c.peer_addr, | 728 | &chunk->subh.cookie_hdr->c.peer_addr, |
730 | peer_init, GFP_ATOMIC)) | 729 | peer_init, GFP_ATOMIC)) |
731 | goto nomem_init; | 730 | goto nomem_init; |
@@ -942,18 +941,9 @@ static sctp_disposition_t sctp_sf_heartbeat(const struct sctp_endpoint *ep, | |||
942 | { | 941 | { |
943 | struct sctp_transport *transport = (struct sctp_transport *) arg; | 942 | struct sctp_transport *transport = (struct sctp_transport *) arg; |
944 | struct sctp_chunk *reply; | 943 | struct sctp_chunk *reply; |
945 | sctp_sender_hb_info_t hbinfo; | ||
946 | size_t paylen = 0; | ||
947 | |||
948 | hbinfo.param_hdr.type = SCTP_PARAM_HEARTBEAT_INFO; | ||
949 | hbinfo.param_hdr.length = htons(sizeof(sctp_sender_hb_info_t)); | ||
950 | hbinfo.daddr = transport->ipaddr; | ||
951 | hbinfo.sent_at = jiffies; | ||
952 | hbinfo.hb_nonce = transport->hb_nonce; | ||
953 | 944 | ||
954 | /* Send a heartbeat to our peer. */ | 945 | /* Send a heartbeat to our peer. */ |
955 | paylen = sizeof(sctp_sender_hb_info_t); | 946 | reply = sctp_make_heartbeat(asoc, transport); |
956 | reply = sctp_make_heartbeat(asoc, transport, &hbinfo, paylen); | ||
957 | if (!reply) | 947 | if (!reply) |
958 | return SCTP_DISPOSITION_NOMEM; | 948 | return SCTP_DISPOSITION_NOMEM; |
959 | 949 | ||
@@ -1464,8 +1454,7 @@ static sctp_disposition_t sctp_sf_do_unexpected_init( | |||
1464 | * Verification Tag and Peers Verification tag into a reserved | 1454 | * Verification Tag and Peers Verification tag into a reserved |
1465 | * place (local tie-tag and per tie-tag) within the state cookie. | 1455 | * place (local tie-tag and per tie-tag) within the state cookie. |
1466 | */ | 1456 | */ |
1467 | if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type, | 1457 | if (!sctp_process_init(new_asoc, chunk, sctp_source(chunk), |
1468 | sctp_source(chunk), | ||
1469 | (sctp_init_chunk_t *)chunk->chunk_hdr, | 1458 | (sctp_init_chunk_t *)chunk->chunk_hdr, |
1470 | GFP_ATOMIC)) | 1459 | GFP_ATOMIC)) |
1471 | goto nomem; | 1460 | goto nomem; |
@@ -1546,7 +1535,7 @@ cleanup: | |||
1546 | } | 1535 | } |
1547 | 1536 | ||
1548 | /* | 1537 | /* |
1549 | * Handle simultanous INIT. | 1538 | * Handle simultaneous INIT. |
1550 | * This means we started an INIT and then we got an INIT request from | 1539 | * This means we started an INIT and then we got an INIT request from |
1551 | * our peer. | 1540 | * our peer. |
1552 | * | 1541 | * |
@@ -1694,8 +1683,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep, | |||
1694 | */ | 1683 | */ |
1695 | peer_init = &chunk->subh.cookie_hdr->c.peer_init[0]; | 1684 | peer_init = &chunk->subh.cookie_hdr->c.peer_init[0]; |
1696 | 1685 | ||
1697 | if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type, | 1686 | if (!sctp_process_init(new_asoc, chunk, sctp_source(chunk), peer_init, |
1698 | sctp_source(chunk), peer_init, | ||
1699 | GFP_ATOMIC)) | 1687 | GFP_ATOMIC)) |
1700 | goto nomem; | 1688 | goto nomem; |
1701 | 1689 | ||
@@ -1780,8 +1768,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_b(const struct sctp_endpoint *ep, | |||
1780 | * side effects--it is safe to run them here. | 1768 | * side effects--it is safe to run them here. |
1781 | */ | 1769 | */ |
1782 | peer_init = &chunk->subh.cookie_hdr->c.peer_init[0]; | 1770 | peer_init = &chunk->subh.cookie_hdr->c.peer_init[0]; |
1783 | if (!sctp_process_init(new_asoc, chunk->chunk_hdr->type, | 1771 | if (!sctp_process_init(new_asoc, chunk, sctp_source(chunk), peer_init, |
1784 | sctp_source(chunk), peer_init, | ||
1785 | GFP_ATOMIC)) | 1772 | GFP_ATOMIC)) |
1786 | goto nomem; | 1773 | goto nomem; |
1787 | 1774 | ||
@@ -2079,7 +2066,7 @@ sctp_disposition_t sctp_sf_shutdown_pending_abort( | |||
2079 | * RFC 2960, Section 3.3.7 | 2066 | * RFC 2960, Section 3.3.7 |
2080 | * If an endpoint receives an ABORT with a format error or for an | 2067 | * If an endpoint receives an ABORT with a format error or for an |
2081 | * association that doesn't exist, it MUST silently discard it. | 2068 | * association that doesn't exist, it MUST silently discard it. |
2082 | * Becasue the length is "invalid", we can't really discard just | 2069 | * Because the length is "invalid", we can't really discard just |
2083 | * as we do not know its true length. So, to be safe, discard the | 2070 | * as we do not know its true length. So, to be safe, discard the |
2084 | * packet. | 2071 | * packet. |
2085 | */ | 2072 | */ |
@@ -2120,7 +2107,7 @@ sctp_disposition_t sctp_sf_shutdown_sent_abort(const struct sctp_endpoint *ep, | |||
2120 | * RFC 2960, Section 3.3.7 | 2107 | * RFC 2960, Section 3.3.7 |
2121 | * If an endpoint receives an ABORT with a format error or for an | 2108 | * If an endpoint receives an ABORT with a format error or for an |
2122 | * association that doesn't exist, it MUST silently discard it. | 2109 | * association that doesn't exist, it MUST silently discard it. |
2123 | * Becasue the length is "invalid", we can't really discard just | 2110 | * Because the length is "invalid", we can't really discard just |
2124 | * as we do not know its true length. So, to be safe, discard the | 2111 | * as we do not know its true length. So, to be safe, discard the |
2125 | * packet. | 2112 | * packet. |
2126 | */ | 2113 | */ |
@@ -2381,7 +2368,7 @@ sctp_disposition_t sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep, | |||
2381 | * RFC 2960, Section 3.3.7 | 2368 | * RFC 2960, Section 3.3.7 |
2382 | * If an endpoint receives an ABORT with a format error or for an | 2369 | * If an endpoint receives an ABORT with a format error or for an |
2383 | * association that doesn't exist, it MUST silently discard it. | 2370 | * association that doesn't exist, it MUST silently discard it. |
2384 | * Becasue the length is "invalid", we can't really discard just | 2371 | * Because the length is "invalid", we can't really discard just |
2385 | * as we do not know its true length. So, to be safe, discard the | 2372 | * as we do not know its true length. So, to be safe, discard the |
2386 | * packet. | 2373 | * packet. |
2387 | */ | 2374 | */ |
@@ -2412,8 +2399,15 @@ static sctp_disposition_t __sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep, | |||
2412 | 2399 | ||
2413 | /* See if we have an error cause code in the chunk. */ | 2400 | /* See if we have an error cause code in the chunk. */ |
2414 | len = ntohs(chunk->chunk_hdr->length); | 2401 | len = ntohs(chunk->chunk_hdr->length); |
2415 | if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) | 2402 | if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) { |
2403 | |||
2404 | sctp_errhdr_t *err; | ||
2405 | sctp_walk_errors(err, chunk->chunk_hdr); | ||
2406 | if ((void *)err != (void *)chunk->chunk_end) | ||
2407 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | ||
2408 | |||
2416 | error = ((sctp_errhdr_t *)chunk->skb->data)->cause; | 2409 | error = ((sctp_errhdr_t *)chunk->skb->data)->cause; |
2410 | } | ||
2417 | 2411 | ||
2418 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNRESET)); | 2412 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNRESET)); |
2419 | /* ASSOC_FAILED will DELETE_TCB. */ | 2413 | /* ASSOC_FAILED will DELETE_TCB. */ |
@@ -2448,7 +2442,7 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const struct sctp_endpoint *ep, | |||
2448 | * RFC 2960, Section 3.3.7 | 2442 | * RFC 2960, Section 3.3.7 |
2449 | * If an endpoint receives an ABORT with a format error or for an | 2443 | * If an endpoint receives an ABORT with a format error or for an |
2450 | * association that doesn't exist, it MUST silently discard it. | 2444 | * association that doesn't exist, it MUST silently discard it. |
2451 | * Becasue the length is "invalid", we can't really discard just | 2445 | * Because the length is "invalid", we can't really discard just |
2452 | * as we do not know its true length. So, to be safe, discard the | 2446 | * as we do not know its true length. So, to be safe, discard the |
2453 | * packet. | 2447 | * packet. |
2454 | */ | 2448 | */ |
@@ -3204,6 +3198,7 @@ sctp_disposition_t sctp_sf_operr_notify(const struct sctp_endpoint *ep, | |||
3204 | sctp_cmd_seq_t *commands) | 3198 | sctp_cmd_seq_t *commands) |
3205 | { | 3199 | { |
3206 | struct sctp_chunk *chunk = arg; | 3200 | struct sctp_chunk *chunk = arg; |
3201 | sctp_errhdr_t *err; | ||
3207 | 3202 | ||
3208 | if (!sctp_vtag_verify(chunk, asoc)) | 3203 | if (!sctp_vtag_verify(chunk, asoc)) |
3209 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 3204 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); |
@@ -3212,6 +3207,10 @@ sctp_disposition_t sctp_sf_operr_notify(const struct sctp_endpoint *ep, | |||
3212 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_operr_chunk_t))) | 3207 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_operr_chunk_t))) |
3213 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 3208 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, |
3214 | commands); | 3209 | commands); |
3210 | sctp_walk_errors(err, chunk->chunk_hdr); | ||
3211 | if ((void *)err != (void *)chunk->chunk_end) | ||
3212 | return sctp_sf_violation_paramlen(ep, asoc, type, arg, | ||
3213 | (void *)err, commands); | ||
3215 | 3214 | ||
3216 | sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_OPERR, | 3215 | sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_OPERR, |
3217 | SCTP_CHUNK(chunk)); | 3216 | SCTP_CHUNK(chunk)); |
@@ -3320,8 +3319,10 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep, | |||
3320 | struct sctp_chunk *chunk = arg; | 3319 | struct sctp_chunk *chunk = arg; |
3321 | struct sk_buff *skb = chunk->skb; | 3320 | struct sk_buff *skb = chunk->skb; |
3322 | sctp_chunkhdr_t *ch; | 3321 | sctp_chunkhdr_t *ch; |
3322 | sctp_errhdr_t *err; | ||
3323 | __u8 *ch_end; | 3323 | __u8 *ch_end; |
3324 | int ootb_shut_ack = 0; | 3324 | int ootb_shut_ack = 0; |
3325 | int ootb_cookie_ack = 0; | ||
3325 | 3326 | ||
3326 | SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES); | 3327 | SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES); |
3327 | 3328 | ||
@@ -3346,6 +3347,23 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep, | |||
3346 | if (SCTP_CID_ABORT == ch->type) | 3347 | if (SCTP_CID_ABORT == ch->type) |
3347 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 3348 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); |
3348 | 3349 | ||
3350 | /* RFC 8.4, 7) If the packet contains a "Stale cookie" ERROR | ||
3351 | * or a COOKIE ACK the SCTP Packet should be silently | ||
3352 | * discarded. | ||
3353 | */ | ||
3354 | |||
3355 | if (SCTP_CID_COOKIE_ACK == ch->type) | ||
3356 | ootb_cookie_ack = 1; | ||
3357 | |||
3358 | if (SCTP_CID_ERROR == ch->type) { | ||
3359 | sctp_walk_errors(err, ch) { | ||
3360 | if (SCTP_ERROR_STALE_COOKIE == err->cause) { | ||
3361 | ootb_cookie_ack = 1; | ||
3362 | break; | ||
3363 | } | ||
3364 | } | ||
3365 | } | ||
3366 | |||
3349 | /* Report violation if chunk len overflows */ | 3367 | /* Report violation if chunk len overflows */ |
3350 | ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length)); | 3368 | ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length)); |
3351 | if (ch_end > skb_tail_pointer(skb)) | 3369 | if (ch_end > skb_tail_pointer(skb)) |
@@ -3357,6 +3375,8 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep, | |||
3357 | 3375 | ||
3358 | if (ootb_shut_ack) | 3376 | if (ootb_shut_ack) |
3359 | return sctp_sf_shut_8_4_5(ep, asoc, type, arg, commands); | 3377 | return sctp_sf_shut_8_4_5(ep, asoc, type, arg, commands); |
3378 | else if (ootb_cookie_ack) | ||
3379 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | ||
3360 | else | 3380 | else |
3361 | return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands); | 3381 | return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands); |
3362 | } | 3382 | } |
@@ -3855,7 +3875,7 @@ gen_shutdown: | |||
3855 | } | 3875 | } |
3856 | 3876 | ||
3857 | /* | 3877 | /* |
3858 | * SCTP-AUTH Section 6.3 Receving authenticated chukns | 3878 | * SCTP-AUTH Section 6.3 Receiving authenticated chukns |
3859 | * | 3879 | * |
3860 | * The receiver MUST use the HMAC algorithm indicated in the HMAC | 3880 | * The receiver MUST use the HMAC algorithm indicated in the HMAC |
3861 | * Identifier field. If this algorithm was not specified by the | 3881 | * Identifier field. If this algorithm was not specified by the |
@@ -4231,7 +4251,7 @@ static sctp_disposition_t sctp_sf_abort_violation( | |||
4231 | * | 4251 | * |
4232 | * This means that if we only want to abort associations | 4252 | * This means that if we only want to abort associations |
4233 | * in an authenticated way (i.e AUTH+ABORT), then we | 4253 | * in an authenticated way (i.e AUTH+ABORT), then we |
4234 | * can't destroy this association just becuase the packet | 4254 | * can't destroy this association just because the packet |
4235 | * was malformed. | 4255 | * was malformed. |
4236 | */ | 4256 | */ |
4237 | if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) | 4257 | if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) |
@@ -4343,8 +4363,9 @@ static sctp_disposition_t sctp_sf_violation_chunklen( | |||
4343 | 4363 | ||
4344 | /* | 4364 | /* |
4345 | * Handle a protocol violation when the parameter length is invalid. | 4365 | * Handle a protocol violation when the parameter length is invalid. |
4346 | * "Invalid" length is identified as smaller than the minimal length a | 4366 | * If the length is smaller than the minimum length of a given parameter, |
4347 | * given parameter can be. | 4367 | * or accumulated length in multi parameters exceeds the end of the chunk, |
4368 | * the length is considered as invalid. | ||
4348 | */ | 4369 | */ |
4349 | static sctp_disposition_t sctp_sf_violation_paramlen( | 4370 | static sctp_disposition_t sctp_sf_violation_paramlen( |
4350 | const struct sctp_endpoint *ep, | 4371 | const struct sctp_endpoint *ep, |
@@ -4402,9 +4423,9 @@ static sctp_disposition_t sctp_sf_violation_ctsn( | |||
4402 | } | 4423 | } |
4403 | 4424 | ||
4404 | /* Handle protocol violation of an invalid chunk bundling. For example, | 4425 | /* Handle protocol violation of an invalid chunk bundling. For example, |
4405 | * when we have an association and we recieve bundled INIT-ACK, or | 4426 | * when we have an association and we receive bundled INIT-ACK, or |
4406 | * SHUDOWN-COMPLETE, our peer is clearly violationg the "MUST NOT bundle" | 4427 | * SHUDOWN-COMPLETE, our peer is clearly violationg the "MUST NOT bundle" |
4407 | * statement from the specs. Additinally, there might be an attacker | 4428 | * statement from the specs. Additionally, there might be an attacker |
4408 | * on the path and we may not want to continue this communication. | 4429 | * on the path and we may not want to continue this communication. |
4409 | */ | 4430 | */ |
4410 | static sctp_disposition_t sctp_sf_violation_chunk( | 4431 | static sctp_disposition_t sctp_sf_violation_chunk( |
@@ -5056,6 +5077,30 @@ sctp_disposition_t sctp_sf_ignore_primitive( | |||
5056 | ***************************************************************************/ | 5077 | ***************************************************************************/ |
5057 | 5078 | ||
5058 | /* | 5079 | /* |
5080 | * When the SCTP stack has no more user data to send or retransmit, this | ||
5081 | * notification is given to the user. Also, at the time when a user app | ||
5082 | * subscribes to this event, if there is no data to be sent or | ||
5083 | * retransmit, the stack will immediately send up this notification. | ||
5084 | */ | ||
5085 | sctp_disposition_t sctp_sf_do_no_pending_tsn( | ||
5086 | const struct sctp_endpoint *ep, | ||
5087 | const struct sctp_association *asoc, | ||
5088 | const sctp_subtype_t type, | ||
5089 | void *arg, | ||
5090 | sctp_cmd_seq_t *commands) | ||
5091 | { | ||
5092 | struct sctp_ulpevent *event; | ||
5093 | |||
5094 | event = sctp_ulpevent_make_sender_dry_event(asoc, GFP_ATOMIC); | ||
5095 | if (!event) | ||
5096 | return SCTP_DISPOSITION_NOMEM; | ||
5097 | |||
5098 | sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(event)); | ||
5099 | |||
5100 | return SCTP_DISPOSITION_CONSUME; | ||
5101 | } | ||
5102 | |||
5103 | /* | ||
5059 | * Start the shutdown negotiation. | 5104 | * Start the shutdown negotiation. |
5060 | * | 5105 | * |
5061 | * From Section 9.2: | 5106 | * From Section 9.2: |
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c index 546d4387fb3c..0338dc6fdc9d 100644 --- a/net/sctp/sm_statetable.c +++ b/net/sctp/sm_statetable.c | |||
@@ -107,8 +107,6 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, | |||
107 | #define TYPE_SCTP_FUNC(func) {.fn = func, .name = #func} | 107 | #define TYPE_SCTP_FUNC(func) {.fn = func, .name = #func} |
108 | 108 | ||
109 | #define TYPE_SCTP_DATA { \ | 109 | #define TYPE_SCTP_DATA { \ |
110 | /* SCTP_STATE_EMPTY */ \ | ||
111 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ | ||
112 | /* SCTP_STATE_CLOSED */ \ | 110 | /* SCTP_STATE_CLOSED */ \ |
113 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ | 111 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ |
114 | /* SCTP_STATE_COOKIE_WAIT */ \ | 112 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -128,8 +126,6 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, | |||
128 | } /* TYPE_SCTP_DATA */ | 126 | } /* TYPE_SCTP_DATA */ |
129 | 127 | ||
130 | #define TYPE_SCTP_INIT { \ | 128 | #define TYPE_SCTP_INIT { \ |
131 | /* SCTP_STATE_EMPTY */ \ | ||
132 | TYPE_SCTP_FUNC(sctp_sf_bug), \ | ||
133 | /* SCTP_STATE_CLOSED */ \ | 129 | /* SCTP_STATE_CLOSED */ \ |
134 | TYPE_SCTP_FUNC(sctp_sf_do_5_1B_init), \ | 130 | TYPE_SCTP_FUNC(sctp_sf_do_5_1B_init), \ |
135 | /* SCTP_STATE_COOKIE_WAIT */ \ | 131 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -149,8 +145,6 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, | |||
149 | } /* TYPE_SCTP_INIT */ | 145 | } /* TYPE_SCTP_INIT */ |
150 | 146 | ||
151 | #define TYPE_SCTP_INIT_ACK { \ | 147 | #define TYPE_SCTP_INIT_ACK { \ |
152 | /* SCTP_STATE_EMPTY */ \ | ||
153 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ | ||
154 | /* SCTP_STATE_CLOSED */ \ | 148 | /* SCTP_STATE_CLOSED */ \ |
155 | TYPE_SCTP_FUNC(sctp_sf_do_5_2_3_initack), \ | 149 | TYPE_SCTP_FUNC(sctp_sf_do_5_2_3_initack), \ |
156 | /* SCTP_STATE_COOKIE_WAIT */ \ | 150 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -170,8 +164,6 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, | |||
170 | } /* TYPE_SCTP_INIT_ACK */ | 164 | } /* TYPE_SCTP_INIT_ACK */ |
171 | 165 | ||
172 | #define TYPE_SCTP_SACK { \ | 166 | #define TYPE_SCTP_SACK { \ |
173 | /* SCTP_STATE_EMPTY */ \ | ||
174 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ | ||
175 | /* SCTP_STATE_CLOSED */ \ | 167 | /* SCTP_STATE_CLOSED */ \ |
176 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ | 168 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ |
177 | /* SCTP_STATE_COOKIE_WAIT */ \ | 169 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -191,8 +183,6 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, | |||
191 | } /* TYPE_SCTP_SACK */ | 183 | } /* TYPE_SCTP_SACK */ |
192 | 184 | ||
193 | #define TYPE_SCTP_HEARTBEAT { \ | 185 | #define TYPE_SCTP_HEARTBEAT { \ |
194 | /* SCTP_STATE_EMPTY */ \ | ||
195 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ | ||
196 | /* SCTP_STATE_CLOSED */ \ | 186 | /* SCTP_STATE_CLOSED */ \ |
197 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ | 187 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ |
198 | /* SCTP_STATE_COOKIE_WAIT */ \ | 188 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -213,8 +203,6 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, | |||
213 | } /* TYPE_SCTP_HEARTBEAT */ | 203 | } /* TYPE_SCTP_HEARTBEAT */ |
214 | 204 | ||
215 | #define TYPE_SCTP_HEARTBEAT_ACK { \ | 205 | #define TYPE_SCTP_HEARTBEAT_ACK { \ |
216 | /* SCTP_STATE_EMPTY */ \ | ||
217 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ | ||
218 | /* SCTP_STATE_CLOSED */ \ | 206 | /* SCTP_STATE_CLOSED */ \ |
219 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ | 207 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ |
220 | /* SCTP_STATE_COOKIE_WAIT */ \ | 208 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -234,8 +222,6 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, | |||
234 | } /* TYPE_SCTP_HEARTBEAT_ACK */ | 222 | } /* TYPE_SCTP_HEARTBEAT_ACK */ |
235 | 223 | ||
236 | #define TYPE_SCTP_ABORT { \ | 224 | #define TYPE_SCTP_ABORT { \ |
237 | /* SCTP_STATE_EMPTY */ \ | ||
238 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ | ||
239 | /* SCTP_STATE_CLOSED */ \ | 225 | /* SCTP_STATE_CLOSED */ \ |
240 | TYPE_SCTP_FUNC(sctp_sf_pdiscard), \ | 226 | TYPE_SCTP_FUNC(sctp_sf_pdiscard), \ |
241 | /* SCTP_STATE_COOKIE_WAIT */ \ | 227 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -255,8 +241,6 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, | |||
255 | } /* TYPE_SCTP_ABORT */ | 241 | } /* TYPE_SCTP_ABORT */ |
256 | 242 | ||
257 | #define TYPE_SCTP_SHUTDOWN { \ | 243 | #define TYPE_SCTP_SHUTDOWN { \ |
258 | /* SCTP_STATE_EMPTY */ \ | ||
259 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ | ||
260 | /* SCTP_STATE_CLOSED */ \ | 244 | /* SCTP_STATE_CLOSED */ \ |
261 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ | 245 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ |
262 | /* SCTP_STATE_COOKIE_WAIT */ \ | 246 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -276,8 +260,6 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, | |||
276 | } /* TYPE_SCTP_SHUTDOWN */ | 260 | } /* TYPE_SCTP_SHUTDOWN */ |
277 | 261 | ||
278 | #define TYPE_SCTP_SHUTDOWN_ACK { \ | 262 | #define TYPE_SCTP_SHUTDOWN_ACK { \ |
279 | /* SCTP_STATE_EMPTY */ \ | ||
280 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ | ||
281 | /* SCTP_STATE_CLOSED */ \ | 263 | /* SCTP_STATE_CLOSED */ \ |
282 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ | 264 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ |
283 | /* SCTP_STATE_COOKIE_WAIT */ \ | 265 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -297,8 +279,6 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, | |||
297 | } /* TYPE_SCTP_SHUTDOWN_ACK */ | 279 | } /* TYPE_SCTP_SHUTDOWN_ACK */ |
298 | 280 | ||
299 | #define TYPE_SCTP_ERROR { \ | 281 | #define TYPE_SCTP_ERROR { \ |
300 | /* SCTP_STATE_EMPTY */ \ | ||
301 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ | ||
302 | /* SCTP_STATE_CLOSED */ \ | 282 | /* SCTP_STATE_CLOSED */ \ |
303 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ | 283 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ |
304 | /* SCTP_STATE_COOKIE_WAIT */ \ | 284 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -318,8 +298,6 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, | |||
318 | } /* TYPE_SCTP_ERROR */ | 298 | } /* TYPE_SCTP_ERROR */ |
319 | 299 | ||
320 | #define TYPE_SCTP_COOKIE_ECHO { \ | 300 | #define TYPE_SCTP_COOKIE_ECHO { \ |
321 | /* SCTP_STATE_EMPTY */ \ | ||
322 | TYPE_SCTP_FUNC(sctp_sf_bug), \ | ||
323 | /* SCTP_STATE_CLOSED */ \ | 301 | /* SCTP_STATE_CLOSED */ \ |
324 | TYPE_SCTP_FUNC(sctp_sf_do_5_1D_ce), \ | 302 | TYPE_SCTP_FUNC(sctp_sf_do_5_1D_ce), \ |
325 | /* SCTP_STATE_COOKIE_WAIT */ \ | 303 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -339,8 +317,6 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, | |||
339 | } /* TYPE_SCTP_COOKIE_ECHO */ | 317 | } /* TYPE_SCTP_COOKIE_ECHO */ |
340 | 318 | ||
341 | #define TYPE_SCTP_COOKIE_ACK { \ | 319 | #define TYPE_SCTP_COOKIE_ACK { \ |
342 | /* SCTP_STATE_EMPTY */ \ | ||
343 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ | ||
344 | /* SCTP_STATE_CLOSED */ \ | 320 | /* SCTP_STATE_CLOSED */ \ |
345 | TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ | 321 | TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ |
346 | /* SCTP_STATE_COOKIE_WAIT */ \ | 322 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -360,8 +336,6 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, | |||
360 | } /* TYPE_SCTP_COOKIE_ACK */ | 336 | } /* TYPE_SCTP_COOKIE_ACK */ |
361 | 337 | ||
362 | #define TYPE_SCTP_ECN_ECNE { \ | 338 | #define TYPE_SCTP_ECN_ECNE { \ |
363 | /* SCTP_STATE_EMPTY */ \ | ||
364 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ | ||
365 | /* SCTP_STATE_CLOSED */ \ | 339 | /* SCTP_STATE_CLOSED */ \ |
366 | TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ | 340 | TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ |
367 | /* SCTP_STATE_COOKIE_WAIT */ \ | 341 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -381,8 +355,6 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, | |||
381 | } /* TYPE_SCTP_ECN_ECNE */ | 355 | } /* TYPE_SCTP_ECN_ECNE */ |
382 | 356 | ||
383 | #define TYPE_SCTP_ECN_CWR { \ | 357 | #define TYPE_SCTP_ECN_CWR { \ |
384 | /* SCTP_STATE_EMPTY */ \ | ||
385 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ | ||
386 | /* SCTP_STATE_CLOSED */ \ | 358 | /* SCTP_STATE_CLOSED */ \ |
387 | TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ | 359 | TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ |
388 | /* SCTP_STATE_COOKIE_WAIT */ \ | 360 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -402,8 +374,6 @@ const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, | |||
402 | } /* TYPE_SCTP_ECN_CWR */ | 374 | } /* TYPE_SCTP_ECN_CWR */ |
403 | 375 | ||
404 | #define TYPE_SCTP_SHUTDOWN_COMPLETE { \ | 376 | #define TYPE_SCTP_SHUTDOWN_COMPLETE { \ |
405 | /* SCTP_STATE_EMPTY */ \ | ||
406 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ | ||
407 | /* SCTP_STATE_CLOSED */ \ | 377 | /* SCTP_STATE_CLOSED */ \ |
408 | TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ | 378 | TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ |
409 | /* SCTP_STATE_COOKIE_WAIT */ \ | 379 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -446,8 +416,6 @@ static const sctp_sm_table_entry_t chunk_event_table[SCTP_NUM_BASE_CHUNK_TYPES][ | |||
446 | }; /* state_fn_t chunk_event_table[][] */ | 416 | }; /* state_fn_t chunk_event_table[][] */ |
447 | 417 | ||
448 | #define TYPE_SCTP_ASCONF { \ | 418 | #define TYPE_SCTP_ASCONF { \ |
449 | /* SCTP_STATE_EMPTY */ \ | ||
450 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ | ||
451 | /* SCTP_STATE_CLOSED */ \ | 419 | /* SCTP_STATE_CLOSED */ \ |
452 | TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ | 420 | TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ |
453 | /* SCTP_STATE_COOKIE_WAIT */ \ | 421 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -467,8 +435,6 @@ static const sctp_sm_table_entry_t chunk_event_table[SCTP_NUM_BASE_CHUNK_TYPES][ | |||
467 | } /* TYPE_SCTP_ASCONF */ | 435 | } /* TYPE_SCTP_ASCONF */ |
468 | 436 | ||
469 | #define TYPE_SCTP_ASCONF_ACK { \ | 437 | #define TYPE_SCTP_ASCONF_ACK { \ |
470 | /* SCTP_STATE_EMPTY */ \ | ||
471 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ | ||
472 | /* SCTP_STATE_CLOSED */ \ | 438 | /* SCTP_STATE_CLOSED */ \ |
473 | TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ | 439 | TYPE_SCTP_FUNC(sctp_sf_discard_chunk), \ |
474 | /* SCTP_STATE_COOKIE_WAIT */ \ | 440 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -496,8 +462,6 @@ static const sctp_sm_table_entry_t addip_chunk_event_table[SCTP_NUM_ADDIP_CHUNK_ | |||
496 | }; /*state_fn_t addip_chunk_event_table[][] */ | 462 | }; /*state_fn_t addip_chunk_event_table[][] */ |
497 | 463 | ||
498 | #define TYPE_SCTP_FWD_TSN { \ | 464 | #define TYPE_SCTP_FWD_TSN { \ |
499 | /* SCTP_STATE_EMPTY */ \ | ||
500 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ | ||
501 | /* SCTP_STATE_CLOSED */ \ | 465 | /* SCTP_STATE_CLOSED */ \ |
502 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ | 466 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ |
503 | /* SCTP_STATE_COOKIE_WAIT */ \ | 467 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -524,8 +488,6 @@ static const sctp_sm_table_entry_t prsctp_chunk_event_table[SCTP_NUM_PRSCTP_CHUN | |||
524 | }; /*state_fn_t prsctp_chunk_event_table[][] */ | 488 | }; /*state_fn_t prsctp_chunk_event_table[][] */ |
525 | 489 | ||
526 | #define TYPE_SCTP_AUTH { \ | 490 | #define TYPE_SCTP_AUTH { \ |
527 | /* SCTP_STATE_EMPTY */ \ | ||
528 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ | ||
529 | /* SCTP_STATE_CLOSED */ \ | 491 | /* SCTP_STATE_CLOSED */ \ |
530 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ | 492 | TYPE_SCTP_FUNC(sctp_sf_ootb), \ |
531 | /* SCTP_STATE_COOKIE_WAIT */ \ | 493 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -553,8 +515,6 @@ static const sctp_sm_table_entry_t auth_chunk_event_table[SCTP_NUM_AUTH_CHUNK_TY | |||
553 | 515 | ||
554 | static const sctp_sm_table_entry_t | 516 | static const sctp_sm_table_entry_t |
555 | chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = { | 517 | chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = { |
556 | /* SCTP_STATE_EMPTY */ | ||
557 | TYPE_SCTP_FUNC(sctp_sf_ootb), | ||
558 | /* SCTP_STATE_CLOSED */ | 518 | /* SCTP_STATE_CLOSED */ |
559 | TYPE_SCTP_FUNC(sctp_sf_ootb), | 519 | TYPE_SCTP_FUNC(sctp_sf_ootb), |
560 | /* SCTP_STATE_COOKIE_WAIT */ | 520 | /* SCTP_STATE_COOKIE_WAIT */ |
@@ -575,8 +535,6 @@ chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = { | |||
575 | 535 | ||
576 | 536 | ||
577 | #define TYPE_SCTP_PRIMITIVE_ASSOCIATE { \ | 537 | #define TYPE_SCTP_PRIMITIVE_ASSOCIATE { \ |
578 | /* SCTP_STATE_EMPTY */ \ | ||
579 | TYPE_SCTP_FUNC(sctp_sf_bug), \ | ||
580 | /* SCTP_STATE_CLOSED */ \ | 538 | /* SCTP_STATE_CLOSED */ \ |
581 | TYPE_SCTP_FUNC(sctp_sf_do_prm_asoc), \ | 539 | TYPE_SCTP_FUNC(sctp_sf_do_prm_asoc), \ |
582 | /* SCTP_STATE_COOKIE_WAIT */ \ | 540 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -596,8 +554,6 @@ chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = { | |||
596 | } /* TYPE_SCTP_PRIMITIVE_ASSOCIATE */ | 554 | } /* TYPE_SCTP_PRIMITIVE_ASSOCIATE */ |
597 | 555 | ||
598 | #define TYPE_SCTP_PRIMITIVE_SHUTDOWN { \ | 556 | #define TYPE_SCTP_PRIMITIVE_SHUTDOWN { \ |
599 | /* SCTP_STATE_EMPTY */ \ | ||
600 | TYPE_SCTP_FUNC(sctp_sf_bug), \ | ||
601 | /* SCTP_STATE_CLOSED */ \ | 557 | /* SCTP_STATE_CLOSED */ \ |
602 | TYPE_SCTP_FUNC(sctp_sf_error_closed), \ | 558 | TYPE_SCTP_FUNC(sctp_sf_error_closed), \ |
603 | /* SCTP_STATE_COOKIE_WAIT */ \ | 559 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -617,8 +573,6 @@ chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = { | |||
617 | } /* TYPE_SCTP_PRIMITIVE_SHUTDOWN */ | 573 | } /* TYPE_SCTP_PRIMITIVE_SHUTDOWN */ |
618 | 574 | ||
619 | #define TYPE_SCTP_PRIMITIVE_ABORT { \ | 575 | #define TYPE_SCTP_PRIMITIVE_ABORT { \ |
620 | /* SCTP_STATE_EMPTY */ \ | ||
621 | TYPE_SCTP_FUNC(sctp_sf_bug), \ | ||
622 | /* SCTP_STATE_CLOSED */ \ | 576 | /* SCTP_STATE_CLOSED */ \ |
623 | TYPE_SCTP_FUNC(sctp_sf_error_closed), \ | 577 | TYPE_SCTP_FUNC(sctp_sf_error_closed), \ |
624 | /* SCTP_STATE_COOKIE_WAIT */ \ | 578 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -638,8 +592,6 @@ chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = { | |||
638 | } /* TYPE_SCTP_PRIMITIVE_ABORT */ | 592 | } /* TYPE_SCTP_PRIMITIVE_ABORT */ |
639 | 593 | ||
640 | #define TYPE_SCTP_PRIMITIVE_SEND { \ | 594 | #define TYPE_SCTP_PRIMITIVE_SEND { \ |
641 | /* SCTP_STATE_EMPTY */ \ | ||
642 | TYPE_SCTP_FUNC(sctp_sf_bug), \ | ||
643 | /* SCTP_STATE_CLOSED */ \ | 595 | /* SCTP_STATE_CLOSED */ \ |
644 | TYPE_SCTP_FUNC(sctp_sf_error_closed), \ | 596 | TYPE_SCTP_FUNC(sctp_sf_error_closed), \ |
645 | /* SCTP_STATE_COOKIE_WAIT */ \ | 597 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -659,8 +611,6 @@ chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = { | |||
659 | } /* TYPE_SCTP_PRIMITIVE_SEND */ | 611 | } /* TYPE_SCTP_PRIMITIVE_SEND */ |
660 | 612 | ||
661 | #define TYPE_SCTP_PRIMITIVE_REQUESTHEARTBEAT { \ | 613 | #define TYPE_SCTP_PRIMITIVE_REQUESTHEARTBEAT { \ |
662 | /* SCTP_STATE_EMPTY */ \ | ||
663 | TYPE_SCTP_FUNC(sctp_sf_bug), \ | ||
664 | /* SCTP_STATE_CLOSED */ \ | 614 | /* SCTP_STATE_CLOSED */ \ |
665 | TYPE_SCTP_FUNC(sctp_sf_error_closed), \ | 615 | TYPE_SCTP_FUNC(sctp_sf_error_closed), \ |
666 | /* SCTP_STATE_COOKIE_WAIT */ \ | 616 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -680,8 +630,6 @@ chunk_event_table_unknown[SCTP_STATE_NUM_STATES] = { | |||
680 | } /* TYPE_SCTP_PRIMITIVE_REQUESTHEARTBEAT */ | 630 | } /* TYPE_SCTP_PRIMITIVE_REQUESTHEARTBEAT */ |
681 | 631 | ||
682 | #define TYPE_SCTP_PRIMITIVE_ASCONF { \ | 632 | #define TYPE_SCTP_PRIMITIVE_ASCONF { \ |
683 | /* SCTP_STATE_EMPTY */ \ | ||
684 | TYPE_SCTP_FUNC(sctp_sf_bug), \ | ||
685 | /* SCTP_STATE_CLOSED */ \ | 633 | /* SCTP_STATE_CLOSED */ \ |
686 | TYPE_SCTP_FUNC(sctp_sf_error_closed), \ | 634 | TYPE_SCTP_FUNC(sctp_sf_error_closed), \ |
687 | /* SCTP_STATE_COOKIE_WAIT */ \ | 635 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -713,8 +661,6 @@ static const sctp_sm_table_entry_t primitive_event_table[SCTP_NUM_PRIMITIVE_TYPE | |||
713 | }; | 661 | }; |
714 | 662 | ||
715 | #define TYPE_SCTP_OTHER_NO_PENDING_TSN { \ | 663 | #define TYPE_SCTP_OTHER_NO_PENDING_TSN { \ |
716 | /* SCTP_STATE_EMPTY */ \ | ||
717 | TYPE_SCTP_FUNC(sctp_sf_bug), \ | ||
718 | /* SCTP_STATE_CLOSED */ \ | 664 | /* SCTP_STATE_CLOSED */ \ |
719 | TYPE_SCTP_FUNC(sctp_sf_ignore_other), \ | 665 | TYPE_SCTP_FUNC(sctp_sf_ignore_other), \ |
720 | /* SCTP_STATE_COOKIE_WAIT */ \ | 666 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -722,7 +668,7 @@ static const sctp_sm_table_entry_t primitive_event_table[SCTP_NUM_PRIMITIVE_TYPE | |||
722 | /* SCTP_STATE_COOKIE_ECHOED */ \ | 668 | /* SCTP_STATE_COOKIE_ECHOED */ \ |
723 | TYPE_SCTP_FUNC(sctp_sf_ignore_other), \ | 669 | TYPE_SCTP_FUNC(sctp_sf_ignore_other), \ |
724 | /* SCTP_STATE_ESTABLISHED */ \ | 670 | /* SCTP_STATE_ESTABLISHED */ \ |
725 | TYPE_SCTP_FUNC(sctp_sf_ignore_other), \ | 671 | TYPE_SCTP_FUNC(sctp_sf_do_no_pending_tsn), \ |
726 | /* SCTP_STATE_SHUTDOWN_PENDING */ \ | 672 | /* SCTP_STATE_SHUTDOWN_PENDING */ \ |
727 | TYPE_SCTP_FUNC(sctp_sf_do_9_2_start_shutdown), \ | 673 | TYPE_SCTP_FUNC(sctp_sf_do_9_2_start_shutdown), \ |
728 | /* SCTP_STATE_SHUTDOWN_SENT */ \ | 674 | /* SCTP_STATE_SHUTDOWN_SENT */ \ |
@@ -734,8 +680,6 @@ static const sctp_sm_table_entry_t primitive_event_table[SCTP_NUM_PRIMITIVE_TYPE | |||
734 | } | 680 | } |
735 | 681 | ||
736 | #define TYPE_SCTP_OTHER_ICMP_PROTO_UNREACH { \ | 682 | #define TYPE_SCTP_OTHER_ICMP_PROTO_UNREACH { \ |
737 | /* SCTP_STATE_EMPTY */ \ | ||
738 | TYPE_SCTP_FUNC(sctp_sf_bug), \ | ||
739 | /* SCTP_STATE_CLOSED */ \ | 683 | /* SCTP_STATE_CLOSED */ \ |
740 | TYPE_SCTP_FUNC(sctp_sf_ignore_other), \ | 684 | TYPE_SCTP_FUNC(sctp_sf_ignore_other), \ |
741 | /* SCTP_STATE_COOKIE_WAIT */ \ | 685 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -760,8 +704,6 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ | |||
760 | }; | 704 | }; |
761 | 705 | ||
762 | #define TYPE_SCTP_EVENT_TIMEOUT_NONE { \ | 706 | #define TYPE_SCTP_EVENT_TIMEOUT_NONE { \ |
763 | /* SCTP_STATE_EMPTY */ \ | ||
764 | TYPE_SCTP_FUNC(sctp_sf_bug), \ | ||
765 | /* SCTP_STATE_CLOSED */ \ | 707 | /* SCTP_STATE_CLOSED */ \ |
766 | TYPE_SCTP_FUNC(sctp_sf_bug), \ | 708 | TYPE_SCTP_FUNC(sctp_sf_bug), \ |
767 | /* SCTP_STATE_COOKIE_WAIT */ \ | 709 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -781,8 +723,6 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ | |||
781 | } | 723 | } |
782 | 724 | ||
783 | #define TYPE_SCTP_EVENT_TIMEOUT_T1_COOKIE { \ | 725 | #define TYPE_SCTP_EVENT_TIMEOUT_T1_COOKIE { \ |
784 | /* SCTP_STATE_EMPTY */ \ | ||
785 | TYPE_SCTP_FUNC(sctp_sf_bug), \ | ||
786 | /* SCTP_STATE_CLOSED */ \ | 726 | /* SCTP_STATE_CLOSED */ \ |
787 | TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ | 727 | TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ |
788 | /* SCTP_STATE_COOKIE_WAIT */ \ | 728 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -802,8 +742,6 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ | |||
802 | } | 742 | } |
803 | 743 | ||
804 | #define TYPE_SCTP_EVENT_TIMEOUT_T1_INIT { \ | 744 | #define TYPE_SCTP_EVENT_TIMEOUT_T1_INIT { \ |
805 | /* SCTP_STATE_EMPTY */ \ | ||
806 | TYPE_SCTP_FUNC(sctp_sf_bug), \ | ||
807 | /* SCTP_STATE_CLOSED */ \ | 745 | /* SCTP_STATE_CLOSED */ \ |
808 | TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ | 746 | TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ |
809 | /* SCTP_STATE_COOKIE_WAIT */ \ | 747 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -823,8 +761,6 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ | |||
823 | } | 761 | } |
824 | 762 | ||
825 | #define TYPE_SCTP_EVENT_TIMEOUT_T2_SHUTDOWN { \ | 763 | #define TYPE_SCTP_EVENT_TIMEOUT_T2_SHUTDOWN { \ |
826 | /* SCTP_STATE_EMPTY */ \ | ||
827 | TYPE_SCTP_FUNC(sctp_sf_bug), \ | ||
828 | /* SCTP_STATE_CLOSED */ \ | 764 | /* SCTP_STATE_CLOSED */ \ |
829 | TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ | 765 | TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ |
830 | /* SCTP_STATE_COOKIE_WAIT */ \ | 766 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -844,8 +780,6 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ | |||
844 | } | 780 | } |
845 | 781 | ||
846 | #define TYPE_SCTP_EVENT_TIMEOUT_T3_RTX { \ | 782 | #define TYPE_SCTP_EVENT_TIMEOUT_T3_RTX { \ |
847 | /* SCTP_STATE_EMPTY */ \ | ||
848 | TYPE_SCTP_FUNC(sctp_sf_bug), \ | ||
849 | /* SCTP_STATE_CLOSED */ \ | 783 | /* SCTP_STATE_CLOSED */ \ |
850 | TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ | 784 | TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ |
851 | /* SCTP_STATE_COOKIE_WAIT */ \ | 785 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -865,8 +799,6 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ | |||
865 | } | 799 | } |
866 | 800 | ||
867 | #define TYPE_SCTP_EVENT_TIMEOUT_T4_RTO { \ | 801 | #define TYPE_SCTP_EVENT_TIMEOUT_T4_RTO { \ |
868 | /* SCTP_STATE_EMPTY */ \ | ||
869 | TYPE_SCTP_FUNC(sctp_sf_bug), \ | ||
870 | /* SCTP_STATE_CLOSED */ \ | 802 | /* SCTP_STATE_CLOSED */ \ |
871 | TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ | 803 | TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ |
872 | /* SCTP_STATE_COOKIE_WAIT */ \ | 804 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -886,8 +818,6 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ | |||
886 | } | 818 | } |
887 | 819 | ||
888 | #define TYPE_SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD { \ | 820 | #define TYPE_SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD { \ |
889 | /* SCTP_STATE_EMPTY */ \ | ||
890 | TYPE_SCTP_FUNC(sctp_sf_bug), \ | ||
891 | /* SCTP_STATE_CLOSED */ \ | 821 | /* SCTP_STATE_CLOSED */ \ |
892 | TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ | 822 | TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ |
893 | /* SCTP_STATE_COOKIE_WAIT */ \ | 823 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -907,8 +837,6 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ | |||
907 | } | 837 | } |
908 | 838 | ||
909 | #define TYPE_SCTP_EVENT_TIMEOUT_HEARTBEAT { \ | 839 | #define TYPE_SCTP_EVENT_TIMEOUT_HEARTBEAT { \ |
910 | /* SCTP_STATE_EMPTY */ \ | ||
911 | TYPE_SCTP_FUNC(sctp_sf_bug), \ | ||
912 | /* SCTP_STATE_CLOSED */ \ | 840 | /* SCTP_STATE_CLOSED */ \ |
913 | TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ | 841 | TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ |
914 | /* SCTP_STATE_COOKIE_WAIT */ \ | 842 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -928,8 +856,6 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ | |||
928 | } | 856 | } |
929 | 857 | ||
930 | #define TYPE_SCTP_EVENT_TIMEOUT_SACK { \ | 858 | #define TYPE_SCTP_EVENT_TIMEOUT_SACK { \ |
931 | /* SCTP_STATE_EMPTY */ \ | ||
932 | TYPE_SCTP_FUNC(sctp_sf_bug), \ | ||
933 | /* SCTP_STATE_CLOSED */ \ | 859 | /* SCTP_STATE_CLOSED */ \ |
934 | TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ | 860 | TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ |
935 | /* SCTP_STATE_COOKIE_WAIT */ \ | 861 | /* SCTP_STATE_COOKIE_WAIT */ \ |
@@ -949,8 +875,6 @@ static const sctp_sm_table_entry_t other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_ | |||
949 | } | 875 | } |
950 | 876 | ||
951 | #define TYPE_SCTP_EVENT_TIMEOUT_AUTOCLOSE { \ | 877 | #define TYPE_SCTP_EVENT_TIMEOUT_AUTOCLOSE { \ |
952 | /* SCTP_STATE_EMPTY */ \ | ||
953 | TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ | ||
954 | /* SCTP_STATE_CLOSED */ \ | 878 | /* SCTP_STATE_CLOSED */ \ |
955 | TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ | 879 | TYPE_SCTP_FUNC(sctp_sf_timer_ignore), \ |
956 | /* SCTP_STATE_COOKIE_WAIT */ \ | 880 | /* SCTP_STATE_COOKIE_WAIT */ \ |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 3951a10605bc..6766913a53e6 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -658,11 +658,15 @@ static int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt) | |||
658 | goto err_bindx_rem; | 658 | goto err_bindx_rem; |
659 | } | 659 | } |
660 | 660 | ||
661 | if (sa_addr->v4.sin_port != htons(bp->port)) { | 661 | if (sa_addr->v4.sin_port && |
662 | sa_addr->v4.sin_port != htons(bp->port)) { | ||
662 | retval = -EINVAL; | 663 | retval = -EINVAL; |
663 | goto err_bindx_rem; | 664 | goto err_bindx_rem; |
664 | } | 665 | } |
665 | 666 | ||
667 | if (!sa_addr->v4.sin_port) | ||
668 | sa_addr->v4.sin_port = htons(bp->port); | ||
669 | |||
666 | /* FIXME - There is probably a need to check if sk->sk_saddr and | 670 | /* FIXME - There is probably a need to check if sk->sk_saddr and |
667 | * sk->sk_rcv_addr are currently set to one of the addresses to | 671 | * sk->sk_rcv_addr are currently set to one of the addresses to |
668 | * be removed. This is something which needs to be looked into | 672 | * be removed. This is something which needs to be looked into |
@@ -1193,7 +1197,7 @@ out_free: | |||
1193 | * an endpoint that is multi-homed. Much like sctp_bindx() this call | 1197 | * an endpoint that is multi-homed. Much like sctp_bindx() this call |
1194 | * allows a caller to specify multiple addresses at which a peer can be | 1198 | * allows a caller to specify multiple addresses at which a peer can be |
1195 | * reached. The way the SCTP stack uses the list of addresses to set up | 1199 | * reached. The way the SCTP stack uses the list of addresses to set up |
1196 | * the association is implementation dependant. This function only | 1200 | * the association is implementation dependent. This function only |
1197 | * specifies that the stack will try to make use of all the addresses in | 1201 | * specifies that the stack will try to make use of all the addresses in |
1198 | * the list when needed. | 1202 | * the list when needed. |
1199 | * | 1203 | * |
@@ -1492,7 +1496,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1492 | struct sctp_chunk *chunk; | 1496 | struct sctp_chunk *chunk; |
1493 | union sctp_addr to; | 1497 | union sctp_addr to; |
1494 | struct sockaddr *msg_name = NULL; | 1498 | struct sockaddr *msg_name = NULL; |
1495 | struct sctp_sndrcvinfo default_sinfo = { 0 }; | 1499 | struct sctp_sndrcvinfo default_sinfo; |
1496 | struct sctp_sndrcvinfo *sinfo; | 1500 | struct sctp_sndrcvinfo *sinfo; |
1497 | struct sctp_initmsg *sinit; | 1501 | struct sctp_initmsg *sinit; |
1498 | sctp_assoc_t associd = 0; | 1502 | sctp_assoc_t associd = 0; |
@@ -1756,6 +1760,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1756 | /* If the user didn't specify SNDRCVINFO, make up one with | 1760 | /* If the user didn't specify SNDRCVINFO, make up one with |
1757 | * some defaults. | 1761 | * some defaults. |
1758 | */ | 1762 | */ |
1763 | memset(&default_sinfo, 0, sizeof(default_sinfo)); | ||
1759 | default_sinfo.sinfo_stream = asoc->default_stream; | 1764 | default_sinfo.sinfo_stream = asoc->default_stream; |
1760 | default_sinfo.sinfo_flags = asoc->default_flags; | 1765 | default_sinfo.sinfo_flags = asoc->default_flags; |
1761 | default_sinfo.sinfo_ppid = asoc->default_ppid; | 1766 | default_sinfo.sinfo_ppid = asoc->default_ppid; |
@@ -1786,12 +1791,10 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1786 | goto out_free; | 1791 | goto out_free; |
1787 | } | 1792 | } |
1788 | 1793 | ||
1789 | if (sinfo) { | 1794 | /* Check for invalid stream. */ |
1790 | /* Check for invalid stream. */ | 1795 | if (sinfo->sinfo_stream >= asoc->c.sinit_num_ostreams) { |
1791 | if (sinfo->sinfo_stream >= asoc->c.sinit_num_ostreams) { | 1796 | err = -EINVAL; |
1792 | err = -EINVAL; | 1797 | goto out_free; |
1793 | goto out_free; | ||
1794 | } | ||
1795 | } | 1798 | } |
1796 | 1799 | ||
1797 | timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); | 1800 | timeo = sock_sndtimeo(sk, msg->msg_flags & MSG_DONTWAIT); |
@@ -2283,7 +2286,7 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params, | |||
2283 | trans->param_flags = | 2286 | trans->param_flags = |
2284 | (trans->param_flags & ~SPP_PMTUD) | pmtud_change; | 2287 | (trans->param_flags & ~SPP_PMTUD) | pmtud_change; |
2285 | if (update) { | 2288 | if (update) { |
2286 | sctp_transport_pmtu(trans); | 2289 | sctp_transport_pmtu(trans, sctp_opt2sk(sp)); |
2287 | sctp_assoc_sync_pmtu(asoc); | 2290 | sctp_assoc_sync_pmtu(asoc); |
2288 | } | 2291 | } |
2289 | } else if (asoc) { | 2292 | } else if (asoc) { |
@@ -3215,14 +3218,9 @@ static int sctp_setsockopt_hmac_ident(struct sock *sk, | |||
3215 | if (optlen < sizeof(struct sctp_hmacalgo)) | 3218 | if (optlen < sizeof(struct sctp_hmacalgo)) |
3216 | return -EINVAL; | 3219 | return -EINVAL; |
3217 | 3220 | ||
3218 | hmacs = kmalloc(optlen, GFP_KERNEL); | 3221 | hmacs= memdup_user(optval, optlen); |
3219 | if (!hmacs) | 3222 | if (IS_ERR(hmacs)) |
3220 | return -ENOMEM; | 3223 | return PTR_ERR(hmacs); |
3221 | |||
3222 | if (copy_from_user(hmacs, optval, optlen)) { | ||
3223 | err = -EFAULT; | ||
3224 | goto out; | ||
3225 | } | ||
3226 | 3224 | ||
3227 | idents = hmacs->shmac_num_idents; | 3225 | idents = hmacs->shmac_num_idents; |
3228 | if (idents == 0 || idents > SCTP_AUTH_NUM_HMACS || | 3226 | if (idents == 0 || idents > SCTP_AUTH_NUM_HMACS || |
@@ -3257,14 +3255,9 @@ static int sctp_setsockopt_auth_key(struct sock *sk, | |||
3257 | if (optlen <= sizeof(struct sctp_authkey)) | 3255 | if (optlen <= sizeof(struct sctp_authkey)) |
3258 | return -EINVAL; | 3256 | return -EINVAL; |
3259 | 3257 | ||
3260 | authkey = kmalloc(optlen, GFP_KERNEL); | 3258 | authkey= memdup_user(optval, optlen); |
3261 | if (!authkey) | 3259 | if (IS_ERR(authkey)) |
3262 | return -ENOMEM; | 3260 | return PTR_ERR(authkey); |
3263 | |||
3264 | if (copy_from_user(authkey, optval, optlen)) { | ||
3265 | ret = -EFAULT; | ||
3266 | goto out; | ||
3267 | } | ||
3268 | 3261 | ||
3269 | if (authkey->sca_keylength > optlen - sizeof(struct sctp_authkey)) { | 3262 | if (authkey->sca_keylength > optlen - sizeof(struct sctp_authkey)) { |
3270 | ret = -EINVAL; | 3263 | ret = -EINVAL; |
@@ -5283,6 +5276,55 @@ static int sctp_getsockopt_assoc_number(struct sock *sk, int len, | |||
5283 | return 0; | 5276 | return 0; |
5284 | } | 5277 | } |
5285 | 5278 | ||
5279 | /* | ||
5280 | * 8.2.6. Get the Current Identifiers of Associations | ||
5281 | * (SCTP_GET_ASSOC_ID_LIST) | ||
5282 | * | ||
5283 | * This option gets the current list of SCTP association identifiers of | ||
5284 | * the SCTP associations handled by a one-to-many style socket. | ||
5285 | */ | ||
5286 | static int sctp_getsockopt_assoc_ids(struct sock *sk, int len, | ||
5287 | char __user *optval, int __user *optlen) | ||
5288 | { | ||
5289 | struct sctp_sock *sp = sctp_sk(sk); | ||
5290 | struct sctp_association *asoc; | ||
5291 | struct sctp_assoc_ids *ids; | ||
5292 | u32 num = 0; | ||
5293 | |||
5294 | if (sctp_style(sk, TCP)) | ||
5295 | return -EOPNOTSUPP; | ||
5296 | |||
5297 | if (len < sizeof(struct sctp_assoc_ids)) | ||
5298 | return -EINVAL; | ||
5299 | |||
5300 | list_for_each_entry(asoc, &(sp->ep->asocs), asocs) { | ||
5301 | num++; | ||
5302 | } | ||
5303 | |||
5304 | if (len < sizeof(struct sctp_assoc_ids) + sizeof(sctp_assoc_t) * num) | ||
5305 | return -EINVAL; | ||
5306 | |||
5307 | len = sizeof(struct sctp_assoc_ids) + sizeof(sctp_assoc_t) * num; | ||
5308 | |||
5309 | ids = kmalloc(len, GFP_KERNEL); | ||
5310 | if (unlikely(!ids)) | ||
5311 | return -ENOMEM; | ||
5312 | |||
5313 | ids->gaids_number_of_ids = num; | ||
5314 | num = 0; | ||
5315 | list_for_each_entry(asoc, &(sp->ep->asocs), asocs) { | ||
5316 | ids->gaids_assoc_id[num++] = asoc->assoc_id; | ||
5317 | } | ||
5318 | |||
5319 | if (put_user(len, optlen) || copy_to_user(optval, ids, len)) { | ||
5320 | kfree(ids); | ||
5321 | return -EFAULT; | ||
5322 | } | ||
5323 | |||
5324 | kfree(ids); | ||
5325 | return 0; | ||
5326 | } | ||
5327 | |||
5286 | SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | 5328 | SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, |
5287 | char __user *optval, int __user *optlen) | 5329 | char __user *optval, int __user *optlen) |
5288 | { | 5330 | { |
@@ -5415,6 +5457,9 @@ SCTP_STATIC int sctp_getsockopt(struct sock *sk, int level, int optname, | |||
5415 | case SCTP_GET_ASSOC_NUMBER: | 5457 | case SCTP_GET_ASSOC_NUMBER: |
5416 | retval = sctp_getsockopt_assoc_number(sk, len, optval, optlen); | 5458 | retval = sctp_getsockopt_assoc_number(sk, len, optval, optlen); |
5417 | break; | 5459 | break; |
5460 | case SCTP_GET_ASSOC_ID_LIST: | ||
5461 | retval = sctp_getsockopt_assoc_ids(sk, len, optval, optlen); | ||
5462 | break; | ||
5418 | default: | 5463 | default: |
5419 | retval = -ENOPROTOOPT; | 5464 | retval = -ENOPROTOOPT; |
5420 | break; | 5465 | break; |
diff --git a/net/sctp/transport.c b/net/sctp/transport.c index d3ae493d234a..394c57ca2f54 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c | |||
@@ -211,15 +211,17 @@ 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 | /* If we don't have a fresh route, look one up */ |
217 | 217 | if (!transport->dst || transport->dst->obsolete > 1) { | |
218 | dst = transport->af_specific->get_dst(NULL, &transport->ipaddr, NULL); | 218 | dst_release(transport->dst); |
219 | transport->af_specific->get_dst(transport, &transport->saddr, | ||
220 | &transport->fl, sk); | ||
221 | } | ||
219 | 222 | ||
220 | if (dst) { | 223 | if (transport->dst) { |
221 | transport->pathmtu = dst_mtu(dst); | 224 | transport->pathmtu = dst_mtu(transport->dst); |
222 | dst_release(dst); | ||
223 | } else | 225 | } else |
224 | transport->pathmtu = SCTP_DEFAULT_MAXSEGMENT; | 226 | transport->pathmtu = SCTP_DEFAULT_MAXSEGMENT; |
225 | } | 227 | } |
@@ -270,22 +272,19 @@ void sctp_transport_route(struct sctp_transport *transport, | |||
270 | { | 272 | { |
271 | struct sctp_association *asoc = transport->asoc; | 273 | struct sctp_association *asoc = transport->asoc; |
272 | struct sctp_af *af = transport->af_specific; | 274 | struct sctp_af *af = transport->af_specific; |
273 | union sctp_addr *daddr = &transport->ipaddr; | ||
274 | struct dst_entry *dst; | ||
275 | 275 | ||
276 | dst = af->get_dst(asoc, daddr, saddr); | 276 | af->get_dst(transport, saddr, &transport->fl, sctp_opt2sk(opt)); |
277 | 277 | ||
278 | if (saddr) | 278 | if (saddr) |
279 | memcpy(&transport->saddr, saddr, sizeof(union sctp_addr)); | 279 | memcpy(&transport->saddr, saddr, sizeof(union sctp_addr)); |
280 | else | 280 | else |
281 | af->get_saddr(opt, asoc, dst, daddr, &transport->saddr); | 281 | af->get_saddr(opt, transport, &transport->fl); |
282 | 282 | ||
283 | transport->dst = dst; | ||
284 | if ((transport->param_flags & SPP_PMTUD_DISABLE) && transport->pathmtu) { | 283 | if ((transport->param_flags & SPP_PMTUD_DISABLE) && transport->pathmtu) { |
285 | return; | 284 | return; |
286 | } | 285 | } |
287 | if (dst) { | 286 | if (transport->dst) { |
288 | transport->pathmtu = dst_mtu(dst); | 287 | transport->pathmtu = dst_mtu(transport->dst); |
289 | 288 | ||
290 | /* Initialize sk->sk_rcv_saddr, if the transport is the | 289 | /* Initialize sk->sk_rcv_saddr, if the transport is the |
291 | * association's active path for getsockname(). | 290 | * association's active path for getsockname(). |
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index aa72e89c3ee1..c962c6062aab 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c | |||
@@ -554,7 +554,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_send_failed( | |||
554 | memcpy(&ssf->ssf_info, &chunk->sinfo, sizeof(struct sctp_sndrcvinfo)); | 554 | memcpy(&ssf->ssf_info, &chunk->sinfo, sizeof(struct sctp_sndrcvinfo)); |
555 | 555 | ||
556 | /* Per TSVWG discussion with Randy. Allow the application to | 556 | /* Per TSVWG discussion with Randy. Allow the application to |
557 | * ressemble a fragmented message. | 557 | * resemble a fragmented message. |
558 | */ | 558 | */ |
559 | ssf->ssf_info.sinfo_flags = chunk->chunk_hdr->flags; | 559 | ssf->ssf_info.sinfo_flags = chunk->chunk_hdr->flags; |
560 | 560 | ||
@@ -843,7 +843,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_authkey( | |||
843 | ak = (struct sctp_authkey_event *) | 843 | ak = (struct sctp_authkey_event *) |
844 | skb_put(skb, sizeof(struct sctp_authkey_event)); | 844 | skb_put(skb, sizeof(struct sctp_authkey_event)); |
845 | 845 | ||
846 | ak->auth_type = SCTP_AUTHENTICATION_INDICATION; | 846 | ak->auth_type = SCTP_AUTHENTICATION_EVENT; |
847 | ak->auth_flags = 0; | 847 | ak->auth_flags = 0; |
848 | ak->auth_length = sizeof(struct sctp_authkey_event); | 848 | ak->auth_length = sizeof(struct sctp_authkey_event); |
849 | 849 | ||
@@ -862,6 +862,34 @@ fail: | |||
862 | return NULL; | 862 | return NULL; |
863 | } | 863 | } |
864 | 864 | ||
865 | /* | ||
866 | * Socket Extensions for SCTP | ||
867 | * 6.3.10. SCTP_SENDER_DRY_EVENT | ||
868 | */ | ||
869 | struct sctp_ulpevent *sctp_ulpevent_make_sender_dry_event( | ||
870 | const struct sctp_association *asoc, gfp_t gfp) | ||
871 | { | ||
872 | struct sctp_ulpevent *event; | ||
873 | struct sctp_sender_dry_event *sdry; | ||
874 | struct sk_buff *skb; | ||
875 | |||
876 | event = sctp_ulpevent_new(sizeof(struct sctp_sender_dry_event), | ||
877 | MSG_NOTIFICATION, gfp); | ||
878 | if (!event) | ||
879 | return NULL; | ||
880 | |||
881 | skb = sctp_event2skb(event); | ||
882 | sdry = (struct sctp_sender_dry_event *) | ||
883 | skb_put(skb, sizeof(struct sctp_sender_dry_event)); | ||
884 | |||
885 | sdry->sender_dry_type = SCTP_SENDER_DRY_EVENT; | ||
886 | sdry->sender_dry_flags = 0; | ||
887 | sdry->sender_dry_length = sizeof(struct sctp_sender_dry_event); | ||
888 | sctp_ulpevent_set_owner(event, asoc); | ||
889 | sdry->sender_dry_assoc_id = sctp_assoc2id(asoc); | ||
890 | |||
891 | return event; | ||
892 | } | ||
865 | 893 | ||
866 | /* Return the notification type, assuming this is a notification | 894 | /* Return the notification type, assuming this is a notification |
867 | * event. | 895 | * event. |
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index 17678189d054..f2d1de7f2ffb 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c | |||
@@ -240,7 +240,7 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event) | |||
240 | } else { | 240 | } else { |
241 | /* | 241 | /* |
242 | * If fragment interleave is enabled, we | 242 | * If fragment interleave is enabled, we |
243 | * can queue this to the recieve queue instead | 243 | * can queue this to the receive queue instead |
244 | * of the lobby. | 244 | * of the lobby. |
245 | */ | 245 | */ |
246 | if (sctp_sk(sk)->frag_interleave) | 246 | if (sctp_sk(sk)->frag_interleave) |
diff --git a/net/socket.c b/net/socket.c index 5212447c86e7..ed50255143d5 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -551,11 +551,10 @@ int sock_tx_timestamp(struct sock *sk, __u8 *tx_flags) | |||
551 | } | 551 | } |
552 | EXPORT_SYMBOL(sock_tx_timestamp); | 552 | EXPORT_SYMBOL(sock_tx_timestamp); |
553 | 553 | ||
554 | static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock, | 554 | static inline int __sock_sendmsg_nosec(struct kiocb *iocb, struct socket *sock, |
555 | struct msghdr *msg, size_t size) | 555 | struct msghdr *msg, size_t size) |
556 | { | 556 | { |
557 | struct sock_iocb *si = kiocb_to_siocb(iocb); | 557 | struct sock_iocb *si = kiocb_to_siocb(iocb); |
558 | int err; | ||
559 | 558 | ||
560 | sock_update_classid(sock->sk); | 559 | sock_update_classid(sock->sk); |
561 | 560 | ||
@@ -564,13 +563,17 @@ static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
564 | si->msg = msg; | 563 | si->msg = msg; |
565 | si->size = size; | 564 | si->size = size; |
566 | 565 | ||
567 | err = security_socket_sendmsg(sock, msg, size); | ||
568 | if (err) | ||
569 | return err; | ||
570 | |||
571 | return sock->ops->sendmsg(iocb, sock, msg, size); | 566 | return sock->ops->sendmsg(iocb, sock, msg, size); |
572 | } | 567 | } |
573 | 568 | ||
569 | static inline int __sock_sendmsg(struct kiocb *iocb, struct socket *sock, | ||
570 | struct msghdr *msg, size_t size) | ||
571 | { | ||
572 | int err = security_socket_sendmsg(sock, msg, size); | ||
573 | |||
574 | return err ?: __sock_sendmsg_nosec(iocb, sock, msg, size); | ||
575 | } | ||
576 | |||
574 | int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) | 577 | int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) |
575 | { | 578 | { |
576 | struct kiocb iocb; | 579 | struct kiocb iocb; |
@@ -586,6 +589,20 @@ int sock_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) | |||
586 | } | 589 | } |
587 | EXPORT_SYMBOL(sock_sendmsg); | 590 | EXPORT_SYMBOL(sock_sendmsg); |
588 | 591 | ||
592 | int sock_sendmsg_nosec(struct socket *sock, struct msghdr *msg, size_t size) | ||
593 | { | ||
594 | struct kiocb iocb; | ||
595 | struct sock_iocb siocb; | ||
596 | int ret; | ||
597 | |||
598 | init_sync_kiocb(&iocb, NULL); | ||
599 | iocb.private = &siocb; | ||
600 | ret = __sock_sendmsg_nosec(&iocb, sock, msg, size); | ||
601 | if (-EIOCBQUEUED == ret) | ||
602 | ret = wait_on_sync_kiocb(&iocb); | ||
603 | return ret; | ||
604 | } | ||
605 | |||
589 | int kernel_sendmsg(struct socket *sock, struct msghdr *msg, | 606 | int kernel_sendmsg(struct socket *sock, struct msghdr *msg, |
590 | struct kvec *vec, size_t num, size_t size) | 607 | struct kvec *vec, size_t num, size_t size) |
591 | { | 608 | { |
@@ -1863,57 +1880,47 @@ SYSCALL_DEFINE2(shutdown, int, fd, int, how) | |||
1863 | #define COMPAT_NAMELEN(msg) COMPAT_MSG(msg, msg_namelen) | 1880 | #define COMPAT_NAMELEN(msg) COMPAT_MSG(msg, msg_namelen) |
1864 | #define COMPAT_FLAGS(msg) COMPAT_MSG(msg, msg_flags) | 1881 | #define COMPAT_FLAGS(msg) COMPAT_MSG(msg, msg_flags) |
1865 | 1882 | ||
1866 | /* | 1883 | static int __sys_sendmsg(struct socket *sock, struct msghdr __user *msg, |
1867 | * BSD sendmsg interface | 1884 | struct msghdr *msg_sys, unsigned flags, int nosec) |
1868 | */ | ||
1869 | |||
1870 | SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned, flags) | ||
1871 | { | 1885 | { |
1872 | struct compat_msghdr __user *msg_compat = | 1886 | struct compat_msghdr __user *msg_compat = |
1873 | (struct compat_msghdr __user *)msg; | 1887 | (struct compat_msghdr __user *)msg; |
1874 | struct socket *sock; | ||
1875 | struct sockaddr_storage address; | 1888 | struct sockaddr_storage address; |
1876 | struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; | 1889 | struct iovec iovstack[UIO_FASTIOV], *iov = iovstack; |
1877 | unsigned char ctl[sizeof(struct cmsghdr) + 20] | 1890 | unsigned char ctl[sizeof(struct cmsghdr) + 20] |
1878 | __attribute__ ((aligned(sizeof(__kernel_size_t)))); | 1891 | __attribute__ ((aligned(sizeof(__kernel_size_t)))); |
1879 | /* 20 is size of ipv6_pktinfo */ | 1892 | /* 20 is size of ipv6_pktinfo */ |
1880 | unsigned char *ctl_buf = ctl; | 1893 | unsigned char *ctl_buf = ctl; |
1881 | struct msghdr msg_sys; | ||
1882 | int err, ctl_len, iov_size, total_len; | 1894 | int err, ctl_len, iov_size, total_len; |
1883 | int fput_needed; | ||
1884 | 1895 | ||
1885 | err = -EFAULT; | 1896 | err = -EFAULT; |
1886 | if (MSG_CMSG_COMPAT & flags) { | 1897 | if (MSG_CMSG_COMPAT & flags) { |
1887 | if (get_compat_msghdr(&msg_sys, msg_compat)) | 1898 | if (get_compat_msghdr(msg_sys, msg_compat)) |
1888 | return -EFAULT; | 1899 | return -EFAULT; |
1889 | } else if (copy_from_user(&msg_sys, msg, sizeof(struct msghdr))) | 1900 | } else if (copy_from_user(msg_sys, msg, sizeof(struct msghdr))) |
1890 | return -EFAULT; | 1901 | return -EFAULT; |
1891 | 1902 | ||
1892 | sock = sockfd_lookup_light(fd, &err, &fput_needed); | ||
1893 | if (!sock) | ||
1894 | goto out; | ||
1895 | |||
1896 | /* do not move before msg_sys is valid */ | 1903 | /* do not move before msg_sys is valid */ |
1897 | err = -EMSGSIZE; | 1904 | err = -EMSGSIZE; |
1898 | if (msg_sys.msg_iovlen > UIO_MAXIOV) | 1905 | if (msg_sys->msg_iovlen > UIO_MAXIOV) |
1899 | goto out_put; | 1906 | goto out; |
1900 | 1907 | ||
1901 | /* Check whether to allocate the iovec area */ | 1908 | /* Check whether to allocate the iovec area */ |
1902 | err = -ENOMEM; | 1909 | err = -ENOMEM; |
1903 | iov_size = msg_sys.msg_iovlen * sizeof(struct iovec); | 1910 | iov_size = msg_sys->msg_iovlen * sizeof(struct iovec); |
1904 | if (msg_sys.msg_iovlen > UIO_FASTIOV) { | 1911 | if (msg_sys->msg_iovlen > UIO_FASTIOV) { |
1905 | iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); | 1912 | iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL); |
1906 | if (!iov) | 1913 | if (!iov) |
1907 | goto out_put; | 1914 | goto out; |
1908 | } | 1915 | } |
1909 | 1916 | ||
1910 | /* This will also move the address data into kernel space */ | 1917 | /* This will also move the address data into kernel space */ |
1911 | if (MSG_CMSG_COMPAT & flags) { | 1918 | if (MSG_CMSG_COMPAT & flags) { |
1912 | err = verify_compat_iovec(&msg_sys, iov, | 1919 | err = verify_compat_iovec(msg_sys, iov, |
1913 | (struct sockaddr *)&address, | 1920 | (struct sockaddr *)&address, |
1914 | VERIFY_READ); | 1921 | VERIFY_READ); |
1915 | } else | 1922 | } else |
1916 | err = verify_iovec(&msg_sys, iov, | 1923 | err = verify_iovec(msg_sys, iov, |
1917 | (struct sockaddr *)&address, | 1924 | (struct sockaddr *)&address, |
1918 | VERIFY_READ); | 1925 | VERIFY_READ); |
1919 | if (err < 0) | 1926 | if (err < 0) |
@@ -1922,17 +1929,17 @@ SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned, flags) | |||
1922 | 1929 | ||
1923 | err = -ENOBUFS; | 1930 | err = -ENOBUFS; |
1924 | 1931 | ||
1925 | if (msg_sys.msg_controllen > INT_MAX) | 1932 | if (msg_sys->msg_controllen > INT_MAX) |
1926 | goto out_freeiov; | 1933 | goto out_freeiov; |
1927 | ctl_len = msg_sys.msg_controllen; | 1934 | ctl_len = msg_sys->msg_controllen; |
1928 | if ((MSG_CMSG_COMPAT & flags) && ctl_len) { | 1935 | if ((MSG_CMSG_COMPAT & flags) && ctl_len) { |
1929 | err = | 1936 | err = |
1930 | cmsghdr_from_user_compat_to_kern(&msg_sys, sock->sk, ctl, | 1937 | cmsghdr_from_user_compat_to_kern(msg_sys, sock->sk, ctl, |
1931 | sizeof(ctl)); | 1938 | sizeof(ctl)); |
1932 | if (err) | 1939 | if (err) |
1933 | goto out_freeiov; | 1940 | goto out_freeiov; |
1934 | ctl_buf = msg_sys.msg_control; | 1941 | ctl_buf = msg_sys->msg_control; |
1935 | ctl_len = msg_sys.msg_controllen; | 1942 | ctl_len = msg_sys->msg_controllen; |
1936 | } else if (ctl_len) { | 1943 | } else if (ctl_len) { |
1937 | if (ctl_len > sizeof(ctl)) { | 1944 | if (ctl_len > sizeof(ctl)) { |
1938 | ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL); | 1945 | ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL); |
@@ -1941,21 +1948,22 @@ SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned, flags) | |||
1941 | } | 1948 | } |
1942 | err = -EFAULT; | 1949 | err = -EFAULT; |
1943 | /* | 1950 | /* |
1944 | * Careful! Before this, msg_sys.msg_control contains a user pointer. | 1951 | * Careful! Before this, msg_sys->msg_control contains a user pointer. |
1945 | * Afterwards, it will be a kernel pointer. Thus the compiler-assisted | 1952 | * Afterwards, it will be a kernel pointer. Thus the compiler-assisted |
1946 | * checking falls down on this. | 1953 | * checking falls down on this. |
1947 | */ | 1954 | */ |
1948 | if (copy_from_user(ctl_buf, | 1955 | if (copy_from_user(ctl_buf, |
1949 | (void __user __force *)msg_sys.msg_control, | 1956 | (void __user __force *)msg_sys->msg_control, |
1950 | ctl_len)) | 1957 | ctl_len)) |
1951 | goto out_freectl; | 1958 | goto out_freectl; |
1952 | msg_sys.msg_control = ctl_buf; | 1959 | msg_sys->msg_control = ctl_buf; |
1953 | } | 1960 | } |
1954 | msg_sys.msg_flags = flags; | 1961 | msg_sys->msg_flags = flags; |
1955 | 1962 | ||
1956 | if (sock->file->f_flags & O_NONBLOCK) | 1963 | if (sock->file->f_flags & O_NONBLOCK) |
1957 | msg_sys.msg_flags |= MSG_DONTWAIT; | 1964 | msg_sys->msg_flags |= MSG_DONTWAIT; |
1958 | err = sock_sendmsg(sock, &msg_sys, total_len); | 1965 | err = (nosec ? sock_sendmsg_nosec : sock_sendmsg)(sock, msg_sys, |
1966 | total_len); | ||
1959 | 1967 | ||
1960 | out_freectl: | 1968 | out_freectl: |
1961 | if (ctl_buf != ctl) | 1969 | if (ctl_buf != ctl) |
@@ -1963,12 +1971,114 @@ out_freectl: | |||
1963 | out_freeiov: | 1971 | out_freeiov: |
1964 | if (iov != iovstack) | 1972 | if (iov != iovstack) |
1965 | sock_kfree_s(sock->sk, iov, iov_size); | 1973 | sock_kfree_s(sock->sk, iov, iov_size); |
1966 | out_put: | 1974 | out: |
1975 | return err; | ||
1976 | } | ||
1977 | |||
1978 | /* | ||
1979 | * BSD sendmsg interface | ||
1980 | */ | ||
1981 | |||
1982 | SYSCALL_DEFINE3(sendmsg, int, fd, struct msghdr __user *, msg, unsigned, flags) | ||
1983 | { | ||
1984 | int fput_needed, err; | ||
1985 | struct msghdr msg_sys; | ||
1986 | struct socket *sock = sockfd_lookup_light(fd, &err, &fput_needed); | ||
1987 | |||
1988 | if (!sock) | ||
1989 | goto out; | ||
1990 | |||
1991 | err = __sys_sendmsg(sock, msg, &msg_sys, flags, 0); | ||
1992 | |||
1967 | fput_light(sock->file, fput_needed); | 1993 | fput_light(sock->file, fput_needed); |
1968 | out: | 1994 | out: |
1969 | return err; | 1995 | return err; |
1970 | } | 1996 | } |
1971 | 1997 | ||
1998 | /* | ||
1999 | * Linux sendmmsg interface | ||
2000 | */ | ||
2001 | |||
2002 | int __sys_sendmmsg(int fd, struct mmsghdr __user *mmsg, unsigned int vlen, | ||
2003 | unsigned int flags) | ||
2004 | { | ||
2005 | int fput_needed, err, datagrams; | ||
2006 | struct socket *sock; | ||
2007 | struct mmsghdr __user *entry; | ||
2008 | struct compat_mmsghdr __user *compat_entry; | ||
2009 | struct msghdr msg_sys; | ||
2010 | |||
2011 | datagrams = 0; | ||
2012 | |||
2013 | sock = sockfd_lookup_light(fd, &err, &fput_needed); | ||
2014 | if (!sock) | ||
2015 | return err; | ||
2016 | |||
2017 | err = sock_error(sock->sk); | ||
2018 | if (err) | ||
2019 | goto out_put; | ||
2020 | |||
2021 | entry = mmsg; | ||
2022 | compat_entry = (struct compat_mmsghdr __user *)mmsg; | ||
2023 | |||
2024 | while (datagrams < vlen) { | ||
2025 | /* | ||
2026 | * No need to ask LSM for more than the first datagram. | ||
2027 | */ | ||
2028 | if (MSG_CMSG_COMPAT & flags) { | ||
2029 | err = __sys_sendmsg(sock, (struct msghdr __user *)compat_entry, | ||
2030 | &msg_sys, flags, datagrams); | ||
2031 | if (err < 0) | ||
2032 | break; | ||
2033 | err = __put_user(err, &compat_entry->msg_len); | ||
2034 | ++compat_entry; | ||
2035 | } else { | ||
2036 | err = __sys_sendmsg(sock, (struct msghdr __user *)entry, | ||
2037 | &msg_sys, flags, datagrams); | ||
2038 | if (err < 0) | ||
2039 | break; | ||
2040 | err = put_user(err, &entry->msg_len); | ||
2041 | ++entry; | ||
2042 | } | ||
2043 | |||
2044 | if (err) | ||
2045 | break; | ||
2046 | ++datagrams; | ||
2047 | } | ||
2048 | |||
2049 | out_put: | ||
2050 | fput_light(sock->file, fput_needed); | ||
2051 | |||
2052 | if (err == 0) | ||
2053 | return datagrams; | ||
2054 | |||
2055 | if (datagrams != 0) { | ||
2056 | /* | ||
2057 | * We may send less entries than requested (vlen) if the | ||
2058 | * sock is non blocking... | ||
2059 | */ | ||
2060 | if (err != -EAGAIN) { | ||
2061 | /* | ||
2062 | * ... or if sendmsg returns an error after we | ||
2063 | * send some datagrams, where we record the | ||
2064 | * error to return on the next call or if the | ||
2065 | * app asks about it using getsockopt(SO_ERROR). | ||
2066 | */ | ||
2067 | sock->sk->sk_err = -err; | ||
2068 | } | ||
2069 | |||
2070 | return datagrams; | ||
2071 | } | ||
2072 | |||
2073 | return err; | ||
2074 | } | ||
2075 | |||
2076 | SYSCALL_DEFINE4(sendmmsg, int, fd, struct mmsghdr __user *, mmsg, | ||
2077 | unsigned int, vlen, unsigned int, flags) | ||
2078 | { | ||
2079 | return __sys_sendmmsg(fd, mmsg, vlen, flags); | ||
2080 | } | ||
2081 | |||
1972 | static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg, | 2082 | static int __sys_recvmsg(struct socket *sock, struct msghdr __user *msg, |
1973 | struct msghdr *msg_sys, unsigned flags, int nosec) | 2083 | struct msghdr *msg_sys, unsigned flags, int nosec) |
1974 | { | 2084 | { |
@@ -2214,11 +2324,11 @@ SYSCALL_DEFINE5(recvmmsg, int, fd, struct mmsghdr __user *, mmsg, | |||
2214 | #ifdef __ARCH_WANT_SYS_SOCKETCALL | 2324 | #ifdef __ARCH_WANT_SYS_SOCKETCALL |
2215 | /* Argument list sizes for sys_socketcall */ | 2325 | /* Argument list sizes for sys_socketcall */ |
2216 | #define AL(x) ((x) * sizeof(unsigned long)) | 2326 | #define AL(x) ((x) * sizeof(unsigned long)) |
2217 | static const unsigned char nargs[20] = { | 2327 | static const unsigned char nargs[21] = { |
2218 | AL(0), AL(3), AL(3), AL(3), AL(2), AL(3), | 2328 | AL(0), AL(3), AL(3), AL(3), AL(2), AL(3), |
2219 | AL(3), AL(3), AL(4), AL(4), AL(4), AL(6), | 2329 | AL(3), AL(3), AL(4), AL(4), AL(4), AL(6), |
2220 | AL(6), AL(2), AL(5), AL(5), AL(3), AL(3), | 2330 | AL(6), AL(2), AL(5), AL(5), AL(3), AL(3), |
2221 | AL(4), AL(5) | 2331 | AL(4), AL(5), AL(4) |
2222 | }; | 2332 | }; |
2223 | 2333 | ||
2224 | #undef AL | 2334 | #undef AL |
@@ -2238,7 +2348,7 @@ SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args) | |||
2238 | int err; | 2348 | int err; |
2239 | unsigned int len; | 2349 | unsigned int len; |
2240 | 2350 | ||
2241 | if (call < 1 || call > SYS_RECVMMSG) | 2351 | if (call < 1 || call > SYS_SENDMMSG) |
2242 | return -EINVAL; | 2352 | return -EINVAL; |
2243 | 2353 | ||
2244 | len = nargs[call]; | 2354 | len = nargs[call]; |
@@ -2313,6 +2423,9 @@ SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args) | |||
2313 | case SYS_SENDMSG: | 2423 | case SYS_SENDMSG: |
2314 | err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]); | 2424 | err = sys_sendmsg(a0, (struct msghdr __user *)a1, a[2]); |
2315 | break; | 2425 | break; |
2426 | case SYS_SENDMMSG: | ||
2427 | err = sys_sendmmsg(a0, (struct mmsghdr __user *)a1, a[2], a[3]); | ||
2428 | break; | ||
2316 | case SYS_RECVMSG: | 2429 | case SYS_RECVMSG: |
2317 | err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]); | 2430 | err = sys_recvmsg(a0, (struct msghdr __user *)a1, a[2]); |
2318 | break; | 2431 | break; |
@@ -2643,13 +2756,13 @@ static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32) | |||
2643 | return -EFAULT; | 2756 | return -EFAULT; |
2644 | 2757 | ||
2645 | if (convert_in) { | 2758 | if (convert_in) { |
2646 | /* We expect there to be holes between fs.m_u and | 2759 | /* We expect there to be holes between fs.m_ext and |
2647 | * fs.ring_cookie and at the end of fs, but nowhere else. | 2760 | * fs.ring_cookie and at the end of fs, but nowhere else. |
2648 | */ | 2761 | */ |
2649 | BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_u) + | 2762 | BUILD_BUG_ON(offsetof(struct compat_ethtool_rxnfc, fs.m_ext) + |
2650 | sizeof(compat_rxnfc->fs.m_u) != | 2763 | sizeof(compat_rxnfc->fs.m_ext) != |
2651 | offsetof(struct ethtool_rxnfc, fs.m_u) + | 2764 | offsetof(struct ethtool_rxnfc, fs.m_ext) + |
2652 | sizeof(rxnfc->fs.m_u)); | 2765 | sizeof(rxnfc->fs.m_ext)); |
2653 | BUILD_BUG_ON( | 2766 | BUILD_BUG_ON( |
2654 | offsetof(struct compat_ethtool_rxnfc, fs.location) - | 2767 | offsetof(struct compat_ethtool_rxnfc, fs.location) - |
2655 | offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) != | 2768 | offsetof(struct compat_ethtool_rxnfc, fs.ring_cookie) != |
@@ -2657,7 +2770,7 @@ static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32) | |||
2657 | offsetof(struct ethtool_rxnfc, fs.ring_cookie)); | 2770 | offsetof(struct ethtool_rxnfc, fs.ring_cookie)); |
2658 | 2771 | ||
2659 | if (copy_in_user(rxnfc, compat_rxnfc, | 2772 | if (copy_in_user(rxnfc, compat_rxnfc, |
2660 | (void *)(&rxnfc->fs.m_u + 1) - | 2773 | (void *)(&rxnfc->fs.m_ext + 1) - |
2661 | (void *)rxnfc) || | 2774 | (void *)rxnfc) || |
2662 | copy_in_user(&rxnfc->fs.ring_cookie, | 2775 | copy_in_user(&rxnfc->fs.ring_cookie, |
2663 | &compat_rxnfc->fs.ring_cookie, | 2776 | &compat_rxnfc->fs.ring_cookie, |
@@ -2674,7 +2787,7 @@ static int ethtool_ioctl(struct net *net, struct compat_ifreq __user *ifr32) | |||
2674 | 2787 | ||
2675 | if (convert_out) { | 2788 | if (convert_out) { |
2676 | if (copy_in_user(compat_rxnfc, rxnfc, | 2789 | if (copy_in_user(compat_rxnfc, rxnfc, |
2677 | (const void *)(&rxnfc->fs.m_u + 1) - | 2790 | (const void *)(&rxnfc->fs.m_ext + 1) - |
2678 | (const void *)rxnfc) || | 2791 | (const void *)rxnfc) || |
2679 | copy_in_user(&compat_rxnfc->fs.ring_cookie, | 2792 | copy_in_user(&compat_rxnfc->fs.ring_cookie, |
2680 | &rxnfc->fs.ring_cookie, | 2793 | &rxnfc->fs.ring_cookie, |
@@ -2986,7 +3099,7 @@ out: | |||
2986 | 3099 | ||
2987 | /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE | 3100 | /* Since old style bridge ioctl's endup using SIOCDEVPRIVATE |
2988 | * for some operations; this forces use of the newer bridge-utils that | 3101 | * for some operations; this forces use of the newer bridge-utils that |
2989 | * use compatiable ioctls | 3102 | * use compatible ioctls |
2990 | */ | 3103 | */ |
2991 | static int old_bridge_ioctl(compat_ulong_t __user *argp) | 3104 | static int old_bridge_ioctl(compat_ulong_t __user *argp) |
2992 | { | 3105 | { |
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c index 9022f0a6503e..0a9a2ec2e469 100644 --- a/net/sunrpc/auth_gss/gss_krb5_mech.c +++ b/net/sunrpc/auth_gss/gss_krb5_mech.c | |||
@@ -427,7 +427,7 @@ static int | |||
427 | context_derive_keys_rc4(struct krb5_ctx *ctx) | 427 | context_derive_keys_rc4(struct krb5_ctx *ctx) |
428 | { | 428 | { |
429 | struct crypto_hash *hmac; | 429 | struct crypto_hash *hmac; |
430 | static const char sigkeyconstant[] = "signaturekey"; | 430 | char sigkeyconstant[] = "signaturekey"; |
431 | int slen = strlen(sigkeyconstant) + 1; /* include null terminator */ | 431 | int slen = strlen(sigkeyconstant) + 1; /* include null terminator */ |
432 | struct hash_desc desc; | 432 | struct hash_desc desc; |
433 | struct scatterlist sg[1]; | 433 | struct scatterlist sg[1]; |
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index bcdae78fdfc6..8d0f7d3c71c8 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c | |||
@@ -1101,7 +1101,7 @@ svcauth_gss_accept(struct svc_rqst *rqstp, __be32 *authp) | |||
1101 | 1101 | ||
1102 | /* credential is: | 1102 | /* credential is: |
1103 | * version(==1), proc(0,1,2,3), seq, service (1,2,3), handle | 1103 | * version(==1), proc(0,1,2,3), seq, service (1,2,3), handle |
1104 | * at least 5 u32s, and is preceeded by length, so that makes 6. | 1104 | * at least 5 u32s, and is preceded by length, so that makes 6. |
1105 | */ | 1105 | */ |
1106 | 1106 | ||
1107 | if (argv->iov_len < 5 * 4) | 1107 | if (argv->iov_len < 5 * 4) |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 1e336a06d3e6..bf005d3c65ef 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -504,7 +504,7 @@ static int xs_nospace(struct rpc_task *task) | |||
504 | * EAGAIN: The socket was blocked, please call again later to | 504 | * EAGAIN: The socket was blocked, please call again later to |
505 | * complete the request | 505 | * complete the request |
506 | * ENOTCONN: Caller needs to invoke connect logic then call again | 506 | * ENOTCONN: Caller needs to invoke connect logic then call again |
507 | * other: Some other error occured, the request was not sent | 507 | * other: Some other error occurred, the request was not sent |
508 | */ | 508 | */ |
509 | static int xs_udp_send_request(struct rpc_task *task) | 509 | static int xs_udp_send_request(struct rpc_task *task) |
510 | { | 510 | { |
@@ -590,7 +590,7 @@ static inline void xs_encode_tcp_record_marker(struct xdr_buf *buf) | |||
590 | * EAGAIN: The socket was blocked, please call again later to | 590 | * EAGAIN: The socket was blocked, please call again later to |
591 | * complete the request | 591 | * complete the request |
592 | * ENOTCONN: Caller needs to invoke connect logic then call again | 592 | * ENOTCONN: Caller needs to invoke connect logic then call again |
593 | * other: Some other error occured, the request was not sent | 593 | * other: Some other error occurred, the request was not sent |
594 | * | 594 | * |
595 | * XXX: In the case of soft timeouts, should we eventually give up | 595 | * XXX: In the case of soft timeouts, should we eventually give up |
596 | * if sendmsg is not able to make progress? | 596 | * if sendmsg is not able to make progress? |
diff --git a/net/tipc/addr.h b/net/tipc/addr.h index 8971aba99aea..e4f35afe3207 100644 --- a/net/tipc/addr.h +++ b/net/tipc/addr.h | |||
@@ -37,14 +37,17 @@ | |||
37 | #ifndef _TIPC_ADDR_H | 37 | #ifndef _TIPC_ADDR_H |
38 | #define _TIPC_ADDR_H | 38 | #define _TIPC_ADDR_H |
39 | 39 | ||
40 | #define TIPC_ZONE_MASK 0xff000000u | ||
41 | #define TIPC_CLUSTER_MASK 0xfffff000u | ||
42 | |||
40 | static inline u32 tipc_zone_mask(u32 addr) | 43 | static inline u32 tipc_zone_mask(u32 addr) |
41 | { | 44 | { |
42 | return addr & 0xff000000u; | 45 | return addr & TIPC_ZONE_MASK; |
43 | } | 46 | } |
44 | 47 | ||
45 | static inline u32 tipc_cluster_mask(u32 addr) | 48 | static inline u32 tipc_cluster_mask(u32 addr) |
46 | { | 49 | { |
47 | return addr & 0xfffff000u; | 50 | return addr & TIPC_CLUSTER_MASK; |
48 | } | 51 | } |
49 | 52 | ||
50 | static inline int in_own_cluster(u32 addr) | 53 | static inline int in_own_cluster(u32 addr) |
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 7dc1dc7151ea..fa68d1e9ff4b 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c | |||
@@ -44,13 +44,6 @@ | |||
44 | 44 | ||
45 | #define BCLINK_WIN_DEFAULT 20 /* bcast link window size (default) */ | 45 | #define BCLINK_WIN_DEFAULT 20 /* bcast link window size (default) */ |
46 | 46 | ||
47 | /* | ||
48 | * Loss rate for incoming broadcast frames; used to test retransmission code. | ||
49 | * Set to N to cause every N'th frame to be discarded; 0 => don't discard any. | ||
50 | */ | ||
51 | |||
52 | #define TIPC_BCAST_LOSS_RATE 0 | ||
53 | |||
54 | /** | 47 | /** |
55 | * struct bcbearer_pair - a pair of bearers used by broadcast link | 48 | * struct bcbearer_pair - a pair of bearers used by broadcast link |
56 | * @primary: pointer to primary bearer | 49 | * @primary: pointer to primary bearer |
@@ -414,9 +407,7 @@ int tipc_bclink_send_msg(struct sk_buff *buf) | |||
414 | spin_lock_bh(&bc_lock); | 407 | spin_lock_bh(&bc_lock); |
415 | 408 | ||
416 | res = tipc_link_send_buf(bcl, buf); | 409 | res = tipc_link_send_buf(bcl, buf); |
417 | if (unlikely(res == -ELINKCONG)) | 410 | if (likely(res > 0)) |
418 | buf_discard(buf); | ||
419 | else | ||
420 | bclink_set_last_sent(); | 411 | bclink_set_last_sent(); |
421 | 412 | ||
422 | bcl->stats.queue_sz_counts++; | 413 | bcl->stats.queue_sz_counts++; |
@@ -434,9 +425,6 @@ int tipc_bclink_send_msg(struct sk_buff *buf) | |||
434 | 425 | ||
435 | void tipc_bclink_recv_pkt(struct sk_buff *buf) | 426 | void tipc_bclink_recv_pkt(struct sk_buff *buf) |
436 | { | 427 | { |
437 | #if (TIPC_BCAST_LOSS_RATE) | ||
438 | static int rx_count; | ||
439 | #endif | ||
440 | struct tipc_msg *msg = buf_msg(buf); | 428 | struct tipc_msg *msg = buf_msg(buf); |
441 | struct tipc_node *node = tipc_node_find(msg_prevnode(msg)); | 429 | struct tipc_node *node = tipc_node_find(msg_prevnode(msg)); |
442 | u32 next_in; | 430 | u32 next_in; |
@@ -470,14 +458,6 @@ void tipc_bclink_recv_pkt(struct sk_buff *buf) | |||
470 | return; | 458 | return; |
471 | } | 459 | } |
472 | 460 | ||
473 | #if (TIPC_BCAST_LOSS_RATE) | ||
474 | if (++rx_count == TIPC_BCAST_LOSS_RATE) { | ||
475 | rx_count = 0; | ||
476 | buf_discard(buf); | ||
477 | return; | ||
478 | } | ||
479 | #endif | ||
480 | |||
481 | tipc_node_lock(node); | 461 | tipc_node_lock(node); |
482 | receive: | 462 | receive: |
483 | deferred = node->bclink.deferred_head; | 463 | deferred = node->bclink.deferred_head; |
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 411719feb803..85209eadfae6 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c | |||
@@ -46,6 +46,8 @@ static u32 media_count; | |||
46 | 46 | ||
47 | struct tipc_bearer tipc_bearers[MAX_BEARERS]; | 47 | struct tipc_bearer tipc_bearers[MAX_BEARERS]; |
48 | 48 | ||
49 | static void bearer_disable(struct tipc_bearer *b_ptr); | ||
50 | |||
49 | /** | 51 | /** |
50 | * media_name_valid - validate media name | 52 | * media_name_valid - validate media name |
51 | * | 53 | * |
@@ -342,15 +344,15 @@ struct sk_buff *tipc_bearer_get_names(void) | |||
342 | void tipc_bearer_add_dest(struct tipc_bearer *b_ptr, u32 dest) | 344 | void tipc_bearer_add_dest(struct tipc_bearer *b_ptr, u32 dest) |
343 | { | 345 | { |
344 | tipc_nmap_add(&b_ptr->nodes, dest); | 346 | tipc_nmap_add(&b_ptr->nodes, dest); |
345 | tipc_disc_update_link_req(b_ptr->link_req); | ||
346 | tipc_bcbearer_sort(); | 347 | tipc_bcbearer_sort(); |
348 | tipc_disc_add_dest(b_ptr->link_req); | ||
347 | } | 349 | } |
348 | 350 | ||
349 | void tipc_bearer_remove_dest(struct tipc_bearer *b_ptr, u32 dest) | 351 | void tipc_bearer_remove_dest(struct tipc_bearer *b_ptr, u32 dest) |
350 | { | 352 | { |
351 | tipc_nmap_remove(&b_ptr->nodes, dest); | 353 | tipc_nmap_remove(&b_ptr->nodes, dest); |
352 | tipc_disc_update_link_req(b_ptr->link_req); | ||
353 | tipc_bcbearer_sort(); | 354 | tipc_bcbearer_sort(); |
355 | tipc_disc_remove_dest(b_ptr->link_req); | ||
354 | } | 356 | } |
355 | 357 | ||
356 | /* | 358 | /* |
@@ -493,8 +495,15 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority) | |||
493 | warn("Bearer <%s> rejected, illegal name\n", name); | 495 | warn("Bearer <%s> rejected, illegal name\n", name); |
494 | return -EINVAL; | 496 | return -EINVAL; |
495 | } | 497 | } |
496 | if (!tipc_addr_domain_valid(disc_domain) || | 498 | if (tipc_addr_domain_valid(disc_domain) && |
497 | !tipc_in_scope(disc_domain, tipc_own_addr)) { | 499 | (disc_domain != tipc_own_addr)) { |
500 | if (tipc_in_scope(disc_domain, tipc_own_addr)) { | ||
501 | disc_domain = tipc_own_addr & TIPC_CLUSTER_MASK; | ||
502 | res = 0; /* accept any node in own cluster */ | ||
503 | } else if (in_own_cluster(disc_domain)) | ||
504 | res = 0; /* accept specified node in own cluster */ | ||
505 | } | ||
506 | if (res) { | ||
498 | warn("Bearer <%s> rejected, illegal discovery domain\n", name); | 507 | warn("Bearer <%s> rejected, illegal discovery domain\n", name); |
499 | return -EINVAL; | 508 | return -EINVAL; |
500 | } | 509 | } |
@@ -511,7 +520,7 @@ int tipc_enable_bearer(const char *name, u32 disc_domain, u32 priority) | |||
511 | if (!m_ptr) { | 520 | if (!m_ptr) { |
512 | warn("Bearer <%s> rejected, media <%s> not registered\n", name, | 521 | warn("Bearer <%s> rejected, media <%s> not registered\n", name, |
513 | b_name.media_name); | 522 | b_name.media_name); |
514 | goto failed; | 523 | goto exit; |
515 | } | 524 | } |
516 | 525 | ||
517 | if (priority == TIPC_MEDIA_LINK_PRI) | 526 | if (priority == TIPC_MEDIA_LINK_PRI) |
@@ -527,14 +536,14 @@ restart: | |||
527 | } | 536 | } |
528 | if (!strcmp(name, tipc_bearers[i].name)) { | 537 | if (!strcmp(name, tipc_bearers[i].name)) { |
529 | warn("Bearer <%s> rejected, already enabled\n", name); | 538 | warn("Bearer <%s> rejected, already enabled\n", name); |
530 | goto failed; | 539 | goto exit; |
531 | } | 540 | } |
532 | if ((tipc_bearers[i].priority == priority) && | 541 | if ((tipc_bearers[i].priority == priority) && |
533 | (++with_this_prio > 2)) { | 542 | (++with_this_prio > 2)) { |
534 | if (priority-- == 0) { | 543 | if (priority-- == 0) { |
535 | warn("Bearer <%s> rejected, duplicate priority\n", | 544 | warn("Bearer <%s> rejected, duplicate priority\n", |
536 | name); | 545 | name); |
537 | goto failed; | 546 | goto exit; |
538 | } | 547 | } |
539 | warn("Bearer <%s> priority adjustment required %u->%u\n", | 548 | warn("Bearer <%s> priority adjustment required %u->%u\n", |
540 | name, priority + 1, priority); | 549 | name, priority + 1, priority); |
@@ -544,7 +553,7 @@ restart: | |||
544 | if (bearer_id >= MAX_BEARERS) { | 553 | if (bearer_id >= MAX_BEARERS) { |
545 | warn("Bearer <%s> rejected, bearer limit reached (%u)\n", | 554 | warn("Bearer <%s> rejected, bearer limit reached (%u)\n", |
546 | name, MAX_BEARERS); | 555 | name, MAX_BEARERS); |
547 | goto failed; | 556 | goto exit; |
548 | } | 557 | } |
549 | 558 | ||
550 | b_ptr = &tipc_bearers[bearer_id]; | 559 | b_ptr = &tipc_bearers[bearer_id]; |
@@ -552,7 +561,7 @@ restart: | |||
552 | res = m_ptr->enable_bearer(b_ptr); | 561 | res = m_ptr->enable_bearer(b_ptr); |
553 | if (res) { | 562 | if (res) { |
554 | warn("Bearer <%s> rejected, enable failure (%d)\n", name, -res); | 563 | warn("Bearer <%s> rejected, enable failure (%d)\n", name, -res); |
555 | goto failed; | 564 | goto exit; |
556 | } | 565 | } |
557 | 566 | ||
558 | b_ptr->identity = bearer_id; | 567 | b_ptr->identity = bearer_id; |
@@ -562,14 +571,18 @@ restart: | |||
562 | b_ptr->priority = priority; | 571 | b_ptr->priority = priority; |
563 | INIT_LIST_HEAD(&b_ptr->cong_links); | 572 | INIT_LIST_HEAD(&b_ptr->cong_links); |
564 | INIT_LIST_HEAD(&b_ptr->links); | 573 | INIT_LIST_HEAD(&b_ptr->links); |
565 | b_ptr->link_req = tipc_disc_init_link_req(b_ptr, &m_ptr->bcast_addr, | ||
566 | disc_domain); | ||
567 | spin_lock_init(&b_ptr->lock); | 574 | spin_lock_init(&b_ptr->lock); |
568 | write_unlock_bh(&tipc_net_lock); | 575 | |
576 | res = tipc_disc_create(b_ptr, &m_ptr->bcast_addr, disc_domain); | ||
577 | if (res) { | ||
578 | bearer_disable(b_ptr); | ||
579 | warn("Bearer <%s> rejected, discovery object creation failed\n", | ||
580 | name); | ||
581 | goto exit; | ||
582 | } | ||
569 | info("Enabled bearer <%s>, discovery domain %s, priority %u\n", | 583 | info("Enabled bearer <%s>, discovery domain %s, priority %u\n", |
570 | name, tipc_addr_string_fill(addr_string, disc_domain), priority); | 584 | name, tipc_addr_string_fill(addr_string, disc_domain), priority); |
571 | return 0; | 585 | exit: |
572 | failed: | ||
573 | write_unlock_bh(&tipc_net_lock); | 586 | write_unlock_bh(&tipc_net_lock); |
574 | return res; | 587 | return res; |
575 | } | 588 | } |
@@ -620,14 +633,14 @@ static void bearer_disable(struct tipc_bearer *b_ptr) | |||
620 | struct link *temp_l_ptr; | 633 | struct link *temp_l_ptr; |
621 | 634 | ||
622 | info("Disabling bearer <%s>\n", b_ptr->name); | 635 | info("Disabling bearer <%s>\n", b_ptr->name); |
623 | tipc_disc_stop_link_req(b_ptr->link_req); | ||
624 | spin_lock_bh(&b_ptr->lock); | 636 | spin_lock_bh(&b_ptr->lock); |
625 | b_ptr->link_req = NULL; | ||
626 | b_ptr->blocked = 1; | 637 | b_ptr->blocked = 1; |
627 | b_ptr->media->disable_bearer(b_ptr); | 638 | b_ptr->media->disable_bearer(b_ptr); |
628 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { | 639 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { |
629 | tipc_link_delete(l_ptr); | 640 | tipc_link_delete(l_ptr); |
630 | } | 641 | } |
642 | if (b_ptr->link_req) | ||
643 | tipc_disc_delete(b_ptr->link_req); | ||
631 | spin_unlock_bh(&b_ptr->lock); | 644 | spin_unlock_bh(&b_ptr->lock); |
632 | memset(b_ptr, 0, sizeof(struct tipc_bearer)); | 645 | memset(b_ptr, 0, sizeof(struct tipc_bearer)); |
633 | } | 646 | } |
diff --git a/net/tipc/core.c b/net/tipc/core.c index c9a73e7763f6..943b6af84265 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c | |||
@@ -179,8 +179,7 @@ static int __init tipc_init(void) | |||
179 | if (tipc_log_resize(CONFIG_TIPC_LOG) != 0) | 179 | if (tipc_log_resize(CONFIG_TIPC_LOG) != 0) |
180 | warn("Unable to create log buffer\n"); | 180 | warn("Unable to create log buffer\n"); |
181 | 181 | ||
182 | info("Activated (version " TIPC_MOD_VER | 182 | info("Activated (version " TIPC_MOD_VER ")\n"); |
183 | " compiled " __DATE__ " " __TIME__ ")\n"); | ||
184 | 183 | ||
185 | tipc_own_addr = 0; | 184 | tipc_own_addr = 0; |
186 | tipc_remote_management = 1; | 185 | tipc_remote_management = 1; |
diff --git a/net/tipc/discover.c b/net/tipc/discover.c index 491eff56b9da..0987933155b9 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c | |||
@@ -39,19 +39,17 @@ | |||
39 | #include "discover.h" | 39 | #include "discover.h" |
40 | 40 | ||
41 | #define TIPC_LINK_REQ_INIT 125 /* min delay during bearer start up */ | 41 | #define TIPC_LINK_REQ_INIT 125 /* min delay during bearer start up */ |
42 | #define TIPC_LINK_REQ_FAST 2000 /* normal delay if bearer has no links */ | 42 | #define TIPC_LINK_REQ_FAST 1000 /* max delay if bearer has no links */ |
43 | #define TIPC_LINK_REQ_SLOW 600000 /* normal delay if bearer has links */ | 43 | #define TIPC_LINK_REQ_SLOW 60000 /* max delay if bearer has links */ |
44 | 44 | #define TIPC_LINK_REQ_INACTIVE 0xffffffff /* indicates no timer in use */ | |
45 | /* | ||
46 | * TODO: Most of the inter-cluster setup stuff should be | ||
47 | * rewritten, and be made conformant with specification. | ||
48 | */ | ||
49 | 45 | ||
50 | 46 | ||
51 | /** | 47 | /** |
52 | * struct link_req - information about an ongoing link setup request | 48 | * struct link_req - information about an ongoing link setup request |
53 | * @bearer: bearer issuing requests | 49 | * @bearer: bearer issuing requests |
54 | * @dest: destination address for request messages | 50 | * @dest: destination address for request messages |
51 | * @domain: network domain to which links can be established | ||
52 | * @num_nodes: number of nodes currently discovered (i.e. with an active link) | ||
55 | * @buf: request message to be (repeatedly) sent | 53 | * @buf: request message to be (repeatedly) sent |
56 | * @timer: timer governing period between requests | 54 | * @timer: timer governing period between requests |
57 | * @timer_intv: current interval between requests (in ms) | 55 | * @timer_intv: current interval between requests (in ms) |
@@ -59,6 +57,8 @@ | |||
59 | struct link_req { | 57 | struct link_req { |
60 | struct tipc_bearer *bearer; | 58 | struct tipc_bearer *bearer; |
61 | struct tipc_media_addr dest; | 59 | struct tipc_media_addr dest; |
60 | u32 domain; | ||
61 | int num_nodes; | ||
62 | struct sk_buff *buf; | 62 | struct sk_buff *buf; |
63 | struct timer_list timer; | 63 | struct timer_list timer; |
64 | unsigned int timer_intv; | 64 | unsigned int timer_intv; |
@@ -147,7 +147,7 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr) | |||
147 | } | 147 | } |
148 | if (!tipc_in_scope(dest, tipc_own_addr)) | 148 | if (!tipc_in_scope(dest, tipc_own_addr)) |
149 | return; | 149 | return; |
150 | if (!in_own_cluster(orig)) | 150 | if (!tipc_in_scope(b_ptr->link_req->domain, orig)) |
151 | return; | 151 | return; |
152 | 152 | ||
153 | /* Locate structure corresponding to requesting node */ | 153 | /* Locate structure corresponding to requesting node */ |
@@ -214,44 +214,54 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr) | |||
214 | } | 214 | } |
215 | 215 | ||
216 | /** | 216 | /** |
217 | * tipc_disc_stop_link_req - stop sending periodic link setup requests | 217 | * disc_update - update frequency of periodic link setup requests |
218 | * @req: ptr to link request structure | 218 | * @req: ptr to link request structure |
219 | * | ||
220 | * Reinitiates discovery process if discovery object has no associated nodes | ||
221 | * and is either not currently searching or is searching at a slow rate | ||
219 | */ | 222 | */ |
220 | 223 | ||
221 | void tipc_disc_stop_link_req(struct link_req *req) | 224 | static void disc_update(struct link_req *req) |
222 | { | 225 | { |
223 | if (!req) | 226 | if (!req->num_nodes) { |
224 | return; | 227 | if ((req->timer_intv == TIPC_LINK_REQ_INACTIVE) || |
228 | (req->timer_intv > TIPC_LINK_REQ_FAST)) { | ||
229 | req->timer_intv = TIPC_LINK_REQ_INIT; | ||
230 | k_start_timer(&req->timer, req->timer_intv); | ||
231 | } | ||
232 | } | ||
233 | } | ||
225 | 234 | ||
226 | k_cancel_timer(&req->timer); | 235 | /** |
227 | k_term_timer(&req->timer); | 236 | * tipc_disc_add_dest - increment set of discovered nodes |
228 | buf_discard(req->buf); | 237 | * @req: ptr to link request structure |
229 | kfree(req); | 238 | */ |
239 | |||
240 | void tipc_disc_add_dest(struct link_req *req) | ||
241 | { | ||
242 | req->num_nodes++; | ||
230 | } | 243 | } |
231 | 244 | ||
232 | /** | 245 | /** |
233 | * tipc_disc_update_link_req - update frequency of periodic link setup requests | 246 | * tipc_disc_remove_dest - decrement set of discovered nodes |
234 | * @req: ptr to link request structure | 247 | * @req: ptr to link request structure |
235 | */ | 248 | */ |
236 | 249 | ||
237 | void tipc_disc_update_link_req(struct link_req *req) | 250 | void tipc_disc_remove_dest(struct link_req *req) |
238 | { | 251 | { |
239 | if (!req) | 252 | req->num_nodes--; |
240 | return; | 253 | disc_update(req); |
254 | } | ||
241 | 255 | ||
242 | if (req->timer_intv == TIPC_LINK_REQ_SLOW) { | 256 | /** |
243 | if (!req->bearer->nodes.count) { | 257 | * disc_send_msg - send link setup request message |
244 | req->timer_intv = TIPC_LINK_REQ_FAST; | 258 | * @req: ptr to link request structure |
245 | k_start_timer(&req->timer, req->timer_intv); | 259 | */ |
246 | } | 260 | |
247 | } else if (req->timer_intv == TIPC_LINK_REQ_FAST) { | 261 | static void disc_send_msg(struct link_req *req) |
248 | if (req->bearer->nodes.count) { | 262 | { |
249 | req->timer_intv = TIPC_LINK_REQ_SLOW; | 263 | if (!req->bearer->blocked) |
250 | k_start_timer(&req->timer, req->timer_intv); | 264 | tipc_bearer_send(req->bearer, req->buf, &req->dest); |
251 | } | ||
252 | } else { | ||
253 | /* leave timer "as is" if haven't yet reached a "normal" rate */ | ||
254 | } | ||
255 | } | 265 | } |
256 | 266 | ||
257 | /** | 267 | /** |
@@ -263,56 +273,86 @@ void tipc_disc_update_link_req(struct link_req *req) | |||
263 | 273 | ||
264 | static void disc_timeout(struct link_req *req) | 274 | static void disc_timeout(struct link_req *req) |
265 | { | 275 | { |
276 | int max_delay; | ||
277 | |||
266 | spin_lock_bh(&req->bearer->lock); | 278 | spin_lock_bh(&req->bearer->lock); |
267 | 279 | ||
268 | req->bearer->media->send_msg(req->buf, req->bearer, &req->dest); | 280 | /* Stop searching if only desired node has been found */ |
269 | 281 | ||
270 | if ((req->timer_intv == TIPC_LINK_REQ_SLOW) || | 282 | if (tipc_node(req->domain) && req->num_nodes) { |
271 | (req->timer_intv == TIPC_LINK_REQ_FAST)) { | 283 | req->timer_intv = TIPC_LINK_REQ_INACTIVE; |
272 | /* leave timer interval "as is" if already at a "normal" rate */ | 284 | goto exit; |
273 | } else { | ||
274 | req->timer_intv *= 2; | ||
275 | if (req->timer_intv > TIPC_LINK_REQ_FAST) | ||
276 | req->timer_intv = TIPC_LINK_REQ_FAST; | ||
277 | if ((req->timer_intv == TIPC_LINK_REQ_FAST) && | ||
278 | (req->bearer->nodes.count)) | ||
279 | req->timer_intv = TIPC_LINK_REQ_SLOW; | ||
280 | } | 285 | } |
281 | k_start_timer(&req->timer, req->timer_intv); | ||
282 | 286 | ||
287 | /* | ||
288 | * Send discovery message, then update discovery timer | ||
289 | * | ||
290 | * Keep doubling time between requests until limit is reached; | ||
291 | * hold at fast polling rate if don't have any associated nodes, | ||
292 | * otherwise hold at slow polling rate | ||
293 | */ | ||
294 | |||
295 | disc_send_msg(req); | ||
296 | |||
297 | req->timer_intv *= 2; | ||
298 | if (req->num_nodes) | ||
299 | max_delay = TIPC_LINK_REQ_SLOW; | ||
300 | else | ||
301 | max_delay = TIPC_LINK_REQ_FAST; | ||
302 | if (req->timer_intv > max_delay) | ||
303 | req->timer_intv = max_delay; | ||
304 | |||
305 | k_start_timer(&req->timer, req->timer_intv); | ||
306 | exit: | ||
283 | spin_unlock_bh(&req->bearer->lock); | 307 | spin_unlock_bh(&req->bearer->lock); |
284 | } | 308 | } |
285 | 309 | ||
286 | /** | 310 | /** |
287 | * tipc_disc_init_link_req - start sending periodic link setup requests | 311 | * tipc_disc_create - create object to send periodic link setup requests |
288 | * @b_ptr: ptr to bearer issuing requests | 312 | * @b_ptr: ptr to bearer issuing requests |
289 | * @dest: destination address for request messages | 313 | * @dest: destination address for request messages |
290 | * @dest_domain: network domain of node(s) which should respond to message | 314 | * @dest_domain: network domain to which links can be established |
291 | * | 315 | * |
292 | * Returns pointer to link request structure, or NULL if unable to create. | 316 | * Returns 0 if successful, otherwise -errno. |
293 | */ | 317 | */ |
294 | 318 | ||
295 | struct link_req *tipc_disc_init_link_req(struct tipc_bearer *b_ptr, | 319 | int tipc_disc_create(struct tipc_bearer *b_ptr, |
296 | const struct tipc_media_addr *dest, | 320 | struct tipc_media_addr *dest, u32 dest_domain) |
297 | u32 dest_domain) | ||
298 | { | 321 | { |
299 | struct link_req *req; | 322 | struct link_req *req; |
300 | 323 | ||
301 | req = kmalloc(sizeof(*req), GFP_ATOMIC); | 324 | req = kmalloc(sizeof(*req), GFP_ATOMIC); |
302 | if (!req) | 325 | if (!req) |
303 | return NULL; | 326 | return -ENOMEM; |
304 | 327 | ||
305 | req->buf = tipc_disc_init_msg(DSC_REQ_MSG, dest_domain, b_ptr); | 328 | req->buf = tipc_disc_init_msg(DSC_REQ_MSG, dest_domain, b_ptr); |
306 | if (!req->buf) { | 329 | if (!req->buf) { |
307 | kfree(req); | 330 | kfree(req); |
308 | return NULL; | 331 | return -ENOMSG; |
309 | } | 332 | } |
310 | 333 | ||
311 | memcpy(&req->dest, dest, sizeof(*dest)); | 334 | memcpy(&req->dest, dest, sizeof(*dest)); |
312 | req->bearer = b_ptr; | 335 | req->bearer = b_ptr; |
336 | req->domain = dest_domain; | ||
337 | req->num_nodes = 0; | ||
313 | req->timer_intv = TIPC_LINK_REQ_INIT; | 338 | req->timer_intv = TIPC_LINK_REQ_INIT; |
314 | k_init_timer(&req->timer, (Handler)disc_timeout, (unsigned long)req); | 339 | k_init_timer(&req->timer, (Handler)disc_timeout, (unsigned long)req); |
315 | k_start_timer(&req->timer, req->timer_intv); | 340 | k_start_timer(&req->timer, req->timer_intv); |
316 | return req; | 341 | b_ptr->link_req = req; |
342 | disc_send_msg(req); | ||
343 | return 0; | ||
344 | } | ||
345 | |||
346 | /** | ||
347 | * tipc_disc_delete - destroy object sending periodic link setup requests | ||
348 | * @req: ptr to link request structure | ||
349 | */ | ||
350 | |||
351 | void tipc_disc_delete(struct link_req *req) | ||
352 | { | ||
353 | k_cancel_timer(&req->timer); | ||
354 | k_term_timer(&req->timer); | ||
355 | buf_discard(req->buf); | ||
356 | kfree(req); | ||
317 | } | 357 | } |
318 | 358 | ||
diff --git a/net/tipc/discover.h b/net/tipc/discover.h index e48a167e47b2..a3af595b86cb 100644 --- a/net/tipc/discover.h +++ b/net/tipc/discover.h | |||
@@ -39,12 +39,11 @@ | |||
39 | 39 | ||
40 | struct link_req; | 40 | struct link_req; |
41 | 41 | ||
42 | struct link_req *tipc_disc_init_link_req(struct tipc_bearer *b_ptr, | 42 | int tipc_disc_create(struct tipc_bearer *b_ptr, struct tipc_media_addr *dest, |
43 | const struct tipc_media_addr *dest, | 43 | u32 dest_domain); |
44 | u32 dest_domain); | 44 | void tipc_disc_delete(struct link_req *req); |
45 | void tipc_disc_update_link_req(struct link_req *req); | 45 | void tipc_disc_add_dest(struct link_req *req); |
46 | void tipc_disc_stop_link_req(struct link_req *req); | 46 | void tipc_disc_remove_dest(struct link_req *req); |
47 | |||
48 | void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr); | 47 | void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr); |
49 | 48 | ||
50 | #endif | 49 | #endif |
diff --git a/net/tipc/link.c b/net/tipc/link.c index 43639ff1cbec..5ed4b4f7452d 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
@@ -92,7 +92,8 @@ static int link_recv_changeover_msg(struct link **l_ptr, struct sk_buff **buf); | |||
92 | static void link_set_supervision_props(struct link *l_ptr, u32 tolerance); | 92 | static void link_set_supervision_props(struct link *l_ptr, u32 tolerance); |
93 | static int link_send_sections_long(struct tipc_port *sender, | 93 | static int link_send_sections_long(struct tipc_port *sender, |
94 | struct iovec const *msg_sect, | 94 | struct iovec const *msg_sect, |
95 | u32 num_sect, u32 destnode); | 95 | u32 num_sect, unsigned int total_len, |
96 | u32 destnode); | ||
96 | static void link_check_defragm_bufs(struct link *l_ptr); | 97 | static void link_check_defragm_bufs(struct link *l_ptr); |
97 | static void link_state_event(struct link *l_ptr, u32 event); | 98 | static void link_state_event(struct link *l_ptr, u32 event); |
98 | static void link_reset_statistics(struct link *l_ptr); | 99 | static void link_reset_statistics(struct link *l_ptr); |
@@ -842,6 +843,25 @@ static void link_add_to_outqueue(struct link *l_ptr, | |||
842 | l_ptr->stats.max_queue_sz = l_ptr->out_queue_size; | 843 | l_ptr->stats.max_queue_sz = l_ptr->out_queue_size; |
843 | } | 844 | } |
844 | 845 | ||
846 | static void link_add_chain_to_outqueue(struct link *l_ptr, | ||
847 | struct sk_buff *buf_chain, | ||
848 | u32 long_msgno) | ||
849 | { | ||
850 | struct sk_buff *buf; | ||
851 | struct tipc_msg *msg; | ||
852 | |||
853 | if (!l_ptr->next_out) | ||
854 | l_ptr->next_out = buf_chain; | ||
855 | while (buf_chain) { | ||
856 | buf = buf_chain; | ||
857 | buf_chain = buf_chain->next; | ||
858 | |||
859 | msg = buf_msg(buf); | ||
860 | msg_set_long_msgno(msg, long_msgno); | ||
861 | link_add_to_outqueue(l_ptr, buf, msg); | ||
862 | } | ||
863 | } | ||
864 | |||
845 | /* | 865 | /* |
846 | * tipc_link_send_buf() is the 'full path' for messages, called from | 866 | * tipc_link_send_buf() is the 'full path' for messages, called from |
847 | * inside TIPC when the 'fast path' in tipc_send_buf | 867 | * inside TIPC when the 'fast path' in tipc_send_buf |
@@ -864,8 +884,9 @@ int tipc_link_send_buf(struct link *l_ptr, struct sk_buff *buf) | |||
864 | 884 | ||
865 | if (unlikely(queue_size >= queue_limit)) { | 885 | if (unlikely(queue_size >= queue_limit)) { |
866 | if (imp <= TIPC_CRITICAL_IMPORTANCE) { | 886 | if (imp <= TIPC_CRITICAL_IMPORTANCE) { |
867 | return link_schedule_port(l_ptr, msg_origport(msg), | 887 | link_schedule_port(l_ptr, msg_origport(msg), size); |
868 | size); | 888 | buf_discard(buf); |
889 | return -ELINKCONG; | ||
869 | } | 890 | } |
870 | buf_discard(buf); | 891 | buf_discard(buf); |
871 | if (imp > CONN_MANAGER) { | 892 | if (imp > CONN_MANAGER) { |
@@ -1042,6 +1063,7 @@ int tipc_send_buf_fast(struct sk_buff *buf, u32 destnode) | |||
1042 | int tipc_link_send_sections_fast(struct tipc_port *sender, | 1063 | int tipc_link_send_sections_fast(struct tipc_port *sender, |
1043 | struct iovec const *msg_sect, | 1064 | struct iovec const *msg_sect, |
1044 | const u32 num_sect, | 1065 | const u32 num_sect, |
1066 | unsigned int total_len, | ||
1045 | u32 destaddr) | 1067 | u32 destaddr) |
1046 | { | 1068 | { |
1047 | struct tipc_msg *hdr = &sender->phdr; | 1069 | struct tipc_msg *hdr = &sender->phdr; |
@@ -1057,8 +1079,8 @@ again: | |||
1057 | * (Must not hold any locks while building message.) | 1079 | * (Must not hold any locks while building message.) |
1058 | */ | 1080 | */ |
1059 | 1081 | ||
1060 | res = tipc_msg_build(hdr, msg_sect, num_sect, sender->max_pkt, | 1082 | res = tipc_msg_build(hdr, msg_sect, num_sect, total_len, |
1061 | !sender->user_port, &buf); | 1083 | sender->max_pkt, !sender->user_port, &buf); |
1062 | 1084 | ||
1063 | read_lock_bh(&tipc_net_lock); | 1085 | read_lock_bh(&tipc_net_lock); |
1064 | node = tipc_node_find(destaddr); | 1086 | node = tipc_node_find(destaddr); |
@@ -1069,8 +1091,6 @@ again: | |||
1069 | if (likely(buf)) { | 1091 | if (likely(buf)) { |
1070 | res = link_send_buf_fast(l_ptr, buf, | 1092 | res = link_send_buf_fast(l_ptr, buf, |
1071 | &sender->max_pkt); | 1093 | &sender->max_pkt); |
1072 | if (unlikely(res < 0)) | ||
1073 | buf_discard(buf); | ||
1074 | exit: | 1094 | exit: |
1075 | tipc_node_unlock(node); | 1095 | tipc_node_unlock(node); |
1076 | read_unlock_bh(&tipc_net_lock); | 1096 | read_unlock_bh(&tipc_net_lock); |
@@ -1105,7 +1125,8 @@ exit: | |||
1105 | goto again; | 1125 | goto again; |
1106 | 1126 | ||
1107 | return link_send_sections_long(sender, msg_sect, | 1127 | return link_send_sections_long(sender, msg_sect, |
1108 | num_sect, destaddr); | 1128 | num_sect, total_len, |
1129 | destaddr); | ||
1109 | } | 1130 | } |
1110 | tipc_node_unlock(node); | 1131 | tipc_node_unlock(node); |
1111 | } | 1132 | } |
@@ -1117,7 +1138,7 @@ exit: | |||
1117 | return tipc_reject_msg(buf, TIPC_ERR_NO_NODE); | 1138 | return tipc_reject_msg(buf, TIPC_ERR_NO_NODE); |
1118 | if (res >= 0) | 1139 | if (res >= 0) |
1119 | return tipc_port_reject_sections(sender, hdr, msg_sect, num_sect, | 1140 | return tipc_port_reject_sections(sender, hdr, msg_sect, num_sect, |
1120 | TIPC_ERR_NO_NODE); | 1141 | total_len, TIPC_ERR_NO_NODE); |
1121 | return res; | 1142 | return res; |
1122 | } | 1143 | } |
1123 | 1144 | ||
@@ -1138,12 +1159,13 @@ exit: | |||
1138 | static int link_send_sections_long(struct tipc_port *sender, | 1159 | static int link_send_sections_long(struct tipc_port *sender, |
1139 | struct iovec const *msg_sect, | 1160 | struct iovec const *msg_sect, |
1140 | u32 num_sect, | 1161 | u32 num_sect, |
1162 | unsigned int total_len, | ||
1141 | u32 destaddr) | 1163 | u32 destaddr) |
1142 | { | 1164 | { |
1143 | struct link *l_ptr; | 1165 | struct link *l_ptr; |
1144 | struct tipc_node *node; | 1166 | struct tipc_node *node; |
1145 | struct tipc_msg *hdr = &sender->phdr; | 1167 | struct tipc_msg *hdr = &sender->phdr; |
1146 | u32 dsz = msg_data_sz(hdr); | 1168 | u32 dsz = total_len; |
1147 | u32 max_pkt, fragm_sz, rest; | 1169 | u32 max_pkt, fragm_sz, rest; |
1148 | struct tipc_msg fragm_hdr; | 1170 | struct tipc_msg fragm_hdr; |
1149 | struct sk_buff *buf, *buf_chain, *prev; | 1171 | struct sk_buff *buf, *buf_chain, *prev; |
@@ -1169,7 +1191,6 @@ again: | |||
1169 | 1191 | ||
1170 | tipc_msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT, | 1192 | tipc_msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT, |
1171 | INT_H_SIZE, msg_destnode(hdr)); | 1193 | INT_H_SIZE, msg_destnode(hdr)); |
1172 | msg_set_link_selector(&fragm_hdr, sender->ref); | ||
1173 | msg_set_size(&fragm_hdr, max_pkt); | 1194 | msg_set_size(&fragm_hdr, max_pkt); |
1174 | msg_set_fragm_no(&fragm_hdr, 1); | 1195 | msg_set_fragm_no(&fragm_hdr, 1); |
1175 | 1196 | ||
@@ -1271,28 +1292,15 @@ reject: | |||
1271 | buf_discard(buf_chain); | 1292 | buf_discard(buf_chain); |
1272 | } | 1293 | } |
1273 | return tipc_port_reject_sections(sender, hdr, msg_sect, num_sect, | 1294 | return tipc_port_reject_sections(sender, hdr, msg_sect, num_sect, |
1274 | TIPC_ERR_NO_NODE); | 1295 | total_len, TIPC_ERR_NO_NODE); |
1275 | } | 1296 | } |
1276 | 1297 | ||
1277 | /* Append whole chain to send queue: */ | 1298 | /* Append chain of fragments to send queue & send them */ |
1278 | 1299 | ||
1279 | buf = buf_chain; | 1300 | l_ptr->long_msg_seq_no++; |
1280 | l_ptr->long_msg_seq_no = mod(l_ptr->long_msg_seq_no + 1); | 1301 | link_add_chain_to_outqueue(l_ptr, buf_chain, l_ptr->long_msg_seq_no); |
1281 | if (!l_ptr->next_out) | 1302 | l_ptr->stats.sent_fragments += fragm_no; |
1282 | l_ptr->next_out = buf_chain; | ||
1283 | l_ptr->stats.sent_fragmented++; | 1303 | l_ptr->stats.sent_fragmented++; |
1284 | while (buf) { | ||
1285 | struct sk_buff *next = buf->next; | ||
1286 | struct tipc_msg *msg = buf_msg(buf); | ||
1287 | |||
1288 | l_ptr->stats.sent_fragments++; | ||
1289 | msg_set_long_msgno(msg, l_ptr->long_msg_seq_no); | ||
1290 | link_add_to_outqueue(l_ptr, buf, msg); | ||
1291 | buf = next; | ||
1292 | } | ||
1293 | |||
1294 | /* Send it, if possible: */ | ||
1295 | |||
1296 | tipc_link_push_queue(l_ptr); | 1304 | tipc_link_push_queue(l_ptr); |
1297 | tipc_node_unlock(node); | 1305 | tipc_node_unlock(node); |
1298 | return dsz; | 1306 | return dsz; |
@@ -2407,6 +2415,8 @@ void tipc_link_recv_bundle(struct sk_buff *buf) | |||
2407 | */ | 2415 | */ |
2408 | static int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf) | 2416 | static int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf) |
2409 | { | 2417 | { |
2418 | struct sk_buff *buf_chain = NULL; | ||
2419 | struct sk_buff *buf_chain_tail = (struct sk_buff *)&buf_chain; | ||
2410 | struct tipc_msg *inmsg = buf_msg(buf); | 2420 | struct tipc_msg *inmsg = buf_msg(buf); |
2411 | struct tipc_msg fragm_hdr; | 2421 | struct tipc_msg fragm_hdr; |
2412 | u32 insize = msg_size(inmsg); | 2422 | u32 insize = msg_size(inmsg); |
@@ -2415,7 +2425,7 @@ static int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf) | |||
2415 | u32 rest = insize; | 2425 | u32 rest = insize; |
2416 | u32 pack_sz = l_ptr->max_pkt; | 2426 | u32 pack_sz = l_ptr->max_pkt; |
2417 | u32 fragm_sz = pack_sz - INT_H_SIZE; | 2427 | u32 fragm_sz = pack_sz - INT_H_SIZE; |
2418 | u32 fragm_no = 1; | 2428 | u32 fragm_no = 0; |
2419 | u32 destaddr; | 2429 | u32 destaddr; |
2420 | 2430 | ||
2421 | if (msg_short(inmsg)) | 2431 | if (msg_short(inmsg)) |
@@ -2427,10 +2437,6 @@ static int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf) | |||
2427 | 2437 | ||
2428 | tipc_msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT, | 2438 | tipc_msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT, |
2429 | INT_H_SIZE, destaddr); | 2439 | INT_H_SIZE, destaddr); |
2430 | msg_set_link_selector(&fragm_hdr, msg_link_selector(inmsg)); | ||
2431 | msg_set_long_msgno(&fragm_hdr, mod(l_ptr->long_msg_seq_no++)); | ||
2432 | msg_set_fragm_no(&fragm_hdr, fragm_no); | ||
2433 | l_ptr->stats.sent_fragmented++; | ||
2434 | 2440 | ||
2435 | /* Chop up message: */ | 2441 | /* Chop up message: */ |
2436 | 2442 | ||
@@ -2443,27 +2449,37 @@ static int link_send_long_buf(struct link *l_ptr, struct sk_buff *buf) | |||
2443 | } | 2449 | } |
2444 | fragm = tipc_buf_acquire(fragm_sz + INT_H_SIZE); | 2450 | fragm = tipc_buf_acquire(fragm_sz + INT_H_SIZE); |
2445 | if (fragm == NULL) { | 2451 | if (fragm == NULL) { |
2446 | warn("Link unable to fragment message\n"); | 2452 | buf_discard(buf); |
2447 | dsz = -ENOMEM; | 2453 | while (buf_chain) { |
2448 | goto exit; | 2454 | buf = buf_chain; |
2455 | buf_chain = buf_chain->next; | ||
2456 | buf_discard(buf); | ||
2457 | } | ||
2458 | return -ENOMEM; | ||
2449 | } | 2459 | } |
2450 | msg_set_size(&fragm_hdr, fragm_sz + INT_H_SIZE); | 2460 | msg_set_size(&fragm_hdr, fragm_sz + INT_H_SIZE); |
2461 | fragm_no++; | ||
2462 | msg_set_fragm_no(&fragm_hdr, fragm_no); | ||
2451 | skb_copy_to_linear_data(fragm, &fragm_hdr, INT_H_SIZE); | 2463 | skb_copy_to_linear_data(fragm, &fragm_hdr, INT_H_SIZE); |
2452 | skb_copy_to_linear_data_offset(fragm, INT_H_SIZE, crs, | 2464 | skb_copy_to_linear_data_offset(fragm, INT_H_SIZE, crs, |
2453 | fragm_sz); | 2465 | fragm_sz); |
2454 | /* Send queued messages first, if any: */ | 2466 | buf_chain_tail->next = fragm; |
2467 | buf_chain_tail = fragm; | ||
2455 | 2468 | ||
2456 | l_ptr->stats.sent_fragments++; | ||
2457 | tipc_link_send_buf(l_ptr, fragm); | ||
2458 | if (!tipc_link_is_up(l_ptr)) | ||
2459 | return dsz; | ||
2460 | msg_set_fragm_no(&fragm_hdr, ++fragm_no); | ||
2461 | rest -= fragm_sz; | 2469 | rest -= fragm_sz; |
2462 | crs += fragm_sz; | 2470 | crs += fragm_sz; |
2463 | msg_set_type(&fragm_hdr, FRAGMENT); | 2471 | msg_set_type(&fragm_hdr, FRAGMENT); |
2464 | } | 2472 | } |
2465 | exit: | ||
2466 | buf_discard(buf); | 2473 | buf_discard(buf); |
2474 | |||
2475 | /* Append chain of fragments to send queue & send them */ | ||
2476 | |||
2477 | l_ptr->long_msg_seq_no++; | ||
2478 | link_add_chain_to_outqueue(l_ptr, buf_chain, l_ptr->long_msg_seq_no); | ||
2479 | l_ptr->stats.sent_fragments += fragm_no; | ||
2480 | l_ptr->stats.sent_fragmented++; | ||
2481 | tipc_link_push_queue(l_ptr); | ||
2482 | |||
2467 | return dsz; | 2483 | return dsz; |
2468 | } | 2484 | } |
2469 | 2485 | ||
@@ -2471,7 +2487,7 @@ exit: | |||
2471 | * A pending message being re-assembled must store certain values | 2487 | * A pending message being re-assembled must store certain values |
2472 | * to handle subsequent fragments correctly. The following functions | 2488 | * to handle subsequent fragments correctly. The following functions |
2473 | * help storing these values in unused, available fields in the | 2489 | * help storing these values in unused, available fields in the |
2474 | * pending message. This makes dynamic memory allocation unecessary. | 2490 | * pending message. This makes dynamic memory allocation unnecessary. |
2475 | */ | 2491 | */ |
2476 | 2492 | ||
2477 | static void set_long_msg_seqno(struct sk_buff *buf, u32 seqno) | 2493 | static void set_long_msg_seqno(struct sk_buff *buf, u32 seqno) |
diff --git a/net/tipc/link.h b/net/tipc/link.h index e6a30dbe1aaa..74fbecab1ea0 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h | |||
@@ -228,6 +228,7 @@ u32 tipc_link_get_max_pkt(u32 dest, u32 selector); | |||
228 | int tipc_link_send_sections_fast(struct tipc_port *sender, | 228 | int tipc_link_send_sections_fast(struct tipc_port *sender, |
229 | struct iovec const *msg_sect, | 229 | struct iovec const *msg_sect, |
230 | const u32 num_sect, | 230 | const u32 num_sect, |
231 | unsigned int total_len, | ||
231 | u32 destnode); | 232 | u32 destnode); |
232 | void tipc_link_recv_bundle(struct sk_buff *buf); | 233 | void tipc_link_recv_bundle(struct sk_buff *buf); |
233 | int tipc_link_recv_fragment(struct sk_buff **pending, | 234 | int tipc_link_recv_fragment(struct sk_buff **pending, |
diff --git a/net/tipc/msg.c b/net/tipc/msg.c index 6d92d17e7fb5..03e57bf92c73 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c | |||
@@ -68,20 +68,6 @@ void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, | |||
68 | } | 68 | } |
69 | 69 | ||
70 | /** | 70 | /** |
71 | * tipc_msg_calc_data_size - determine total data size for message | ||
72 | */ | ||
73 | |||
74 | int tipc_msg_calc_data_size(struct iovec const *msg_sect, u32 num_sect) | ||
75 | { | ||
76 | int dsz = 0; | ||
77 | int i; | ||
78 | |||
79 | for (i = 0; i < num_sect; i++) | ||
80 | dsz += msg_sect[i].iov_len; | ||
81 | return dsz; | ||
82 | } | ||
83 | |||
84 | /** | ||
85 | * tipc_msg_build - create message using specified header and data | 71 | * tipc_msg_build - create message using specified header and data |
86 | * | 72 | * |
87 | * Note: Caller must not hold any locks in case copy_from_user() is interrupted! | 73 | * Note: Caller must not hold any locks in case copy_from_user() is interrupted! |
@@ -89,18 +75,13 @@ int tipc_msg_calc_data_size(struct iovec const *msg_sect, u32 num_sect) | |||
89 | * Returns message data size or errno | 75 | * Returns message data size or errno |
90 | */ | 76 | */ |
91 | 77 | ||
92 | int tipc_msg_build(struct tipc_msg *hdr, | 78 | int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect, |
93 | struct iovec const *msg_sect, u32 num_sect, | 79 | u32 num_sect, unsigned int total_len, |
94 | int max_size, int usrmem, struct sk_buff **buf) | 80 | int max_size, int usrmem, struct sk_buff **buf) |
95 | { | 81 | { |
96 | int dsz, sz, hsz, pos, res, cnt; | 82 | int dsz, sz, hsz, pos, res, cnt; |
97 | 83 | ||
98 | dsz = tipc_msg_calc_data_size(msg_sect, num_sect); | 84 | dsz = total_len; |
99 | if (unlikely(dsz > TIPC_MAX_USER_MSG_SIZE)) { | ||
100 | *buf = NULL; | ||
101 | return -EINVAL; | ||
102 | } | ||
103 | |||
104 | pos = hsz = msg_hdr_sz(hdr); | 85 | pos = hsz = msg_hdr_sz(hdr); |
105 | sz = hsz + dsz; | 86 | sz = hsz + dsz; |
106 | msg_set_size(hdr, sz); | 87 | msg_set_size(hdr, sz); |
diff --git a/net/tipc/msg.h b/net/tipc/msg.h index de02339fc175..8452454731fa 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h | |||
@@ -39,41 +39,24 @@ | |||
39 | 39 | ||
40 | #include "bearer.h" | 40 | #include "bearer.h" |
41 | 41 | ||
42 | /* | ||
43 | * Constants and routines used to read and write TIPC payload message headers | ||
44 | * | ||
45 | * Note: Some items are also used with TIPC internal message headers | ||
46 | */ | ||
47 | |||
42 | #define TIPC_VERSION 2 | 48 | #define TIPC_VERSION 2 |
43 | 49 | ||
44 | /* | 50 | /* |
45 | * TIPC user data message header format, version 2: | 51 | * Payload message users are defined in TIPC's public API: |
46 | * | 52 | * - TIPC_LOW_IMPORTANCE |
47 | * | 53 | * - TIPC_MEDIUM_IMPORTANCE |
48 | * 1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0 | 54 | * - TIPC_HIGH_IMPORTANCE |
49 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 55 | * - TIPC_CRITICAL_IMPORTANCE |
50 | * w0:|vers | user |hdr sz |n|d|s|-| message size | | 56 | */ |
51 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 57 | |
52 | * w1:|mstyp| error |rer cnt|lsc|opt p| broadcast ack no | | 58 | /* |
53 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | 59 | * Payload message types |
54 | * w2:| link level ack no | broadcast/link level seq no | | ||
55 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
56 | * w3:| previous node | | ||
57 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
58 | * w4:| originating port | | ||
59 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
60 | * w5:| destination port | | ||
61 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
62 | * w6:| originating node | | ||
63 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
64 | * w7:| destination node | | ||
65 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
66 | * w8:| name type / transport sequence number | | ||
67 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
68 | * w9:| name instance/multicast lower bound | | ||
69 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
70 | * wA:| multicast upper bound | | ||
71 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
72 | * / / | ||
73 | * \ options \ | ||
74 | * / / | ||
75 | * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
76 | * | ||
77 | */ | 60 | */ |
78 | 61 | ||
79 | #define TIPC_CONN_MSG 0 | 62 | #define TIPC_CONN_MSG 0 |
@@ -81,6 +64,9 @@ | |||
81 | #define TIPC_NAMED_MSG 2 | 64 | #define TIPC_NAMED_MSG 2 |
82 | #define TIPC_DIRECT_MSG 3 | 65 | #define TIPC_DIRECT_MSG 3 |
83 | 66 | ||
67 | /* | ||
68 | * Message header sizes | ||
69 | */ | ||
84 | 70 | ||
85 | #define SHORT_H_SIZE 24 /* Connected, in-cluster messages */ | 71 | #define SHORT_H_SIZE 24 /* Connected, in-cluster messages */ |
86 | #define DIR_MSG_H_SIZE 32 /* Directly addressed messages */ | 72 | #define DIR_MSG_H_SIZE 32 /* Directly addressed messages */ |
@@ -473,40 +459,11 @@ static inline struct tipc_msg *msg_get_wrapped(struct tipc_msg *m) | |||
473 | 459 | ||
474 | 460 | ||
475 | /* | 461 | /* |
476 | TIPC internal message header format, version 2 | 462 | * Constants and routines used to read and write TIPC internal message headers |
477 | 463 | */ | |
478 | 1 0 9 8 7 6 5 4|3 2 1 0 9 8 7 6|5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0 | ||
479 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
480 | w0:|vers |msg usr|hdr sz |n|resrv| packet size | | ||
481 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
482 | w1:|m typ| sequence gap | broadcast ack no | | ||
483 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
484 | w2:| link level ack no/bc_gap_from | seq no / bcast_gap_to | | ||
485 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
486 | w3:| previous node | | ||
487 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
488 | w4:| next sent broadcast/fragm no | next sent pkt/ fragm msg no | | ||
489 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
490 | w5:| session no |rsv=0|r|berid|link prio|netpl|p| | ||
491 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
492 | w6:| originating node | | ||
493 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
494 | w7:| destination node | | ||
495 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
496 | w8:| transport sequence number | | ||
497 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
498 | w9:| msg count / bcast tag | link tolerance | | ||
499 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
500 | \ \ | ||
501 | / User Specific Data / | ||
502 | \ \ | ||
503 | +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | ||
504 | |||
505 | NB: CONN_MANAGER use data message format. LINK_CONFIG has own format. | ||
506 | */ | ||
507 | 464 | ||
508 | /* | 465 | /* |
509 | * Internal users | 466 | * Internal message users |
510 | */ | 467 | */ |
511 | 468 | ||
512 | #define BCAST_PROTOCOL 5 | 469 | #define BCAST_PROTOCOL 5 |
@@ -520,7 +477,7 @@ static inline struct tipc_msg *msg_get_wrapped(struct tipc_msg *m) | |||
520 | #define LINK_CONFIG 13 | 477 | #define LINK_CONFIG 13 |
521 | 478 | ||
522 | /* | 479 | /* |
523 | * Connection management protocol messages | 480 | * Connection management protocol message types |
524 | */ | 481 | */ |
525 | 482 | ||
526 | #define CONN_PROBE 0 | 483 | #define CONN_PROBE 0 |
@@ -528,12 +485,41 @@ static inline struct tipc_msg *msg_get_wrapped(struct tipc_msg *m) | |||
528 | #define CONN_ACK 2 | 485 | #define CONN_ACK 2 |
529 | 486 | ||
530 | /* | 487 | /* |
531 | * Name distributor messages | 488 | * Name distributor message types |
532 | */ | 489 | */ |
533 | 490 | ||
534 | #define PUBLICATION 0 | 491 | #define PUBLICATION 0 |
535 | #define WITHDRAWAL 1 | 492 | #define WITHDRAWAL 1 |
536 | 493 | ||
494 | /* | ||
495 | * Segmentation message types | ||
496 | */ | ||
497 | |||
498 | #define FIRST_FRAGMENT 0 | ||
499 | #define FRAGMENT 1 | ||
500 | #define LAST_FRAGMENT 2 | ||
501 | |||
502 | /* | ||
503 | * Link management protocol message types | ||
504 | */ | ||
505 | |||
506 | #define STATE_MSG 0 | ||
507 | #define RESET_MSG 1 | ||
508 | #define ACTIVATE_MSG 2 | ||
509 | |||
510 | /* | ||
511 | * Changeover tunnel message types | ||
512 | */ | ||
513 | #define DUPLICATE_MSG 0 | ||
514 | #define ORIGINAL_MSG 1 | ||
515 | |||
516 | /* | ||
517 | * Config protocol message types | ||
518 | */ | ||
519 | |||
520 | #define DSC_REQ_MSG 0 | ||
521 | #define DSC_RESP_MSG 1 | ||
522 | |||
537 | 523 | ||
538 | /* | 524 | /* |
539 | * Word 1 | 525 | * Word 1 |
@@ -761,50 +747,11 @@ static inline void msg_set_link_tolerance(struct tipc_msg *m, u32 n) | |||
761 | msg_set_bits(m, 9, 0, 0xffff, n); | 747 | msg_set_bits(m, 9, 0, 0xffff, n); |
762 | } | 748 | } |
763 | 749 | ||
764 | /* | ||
765 | * Segmentation message types | ||
766 | */ | ||
767 | |||
768 | #define FIRST_FRAGMENT 0 | ||
769 | #define FRAGMENT 1 | ||
770 | #define LAST_FRAGMENT 2 | ||
771 | |||
772 | /* | ||
773 | * Link management protocol message types | ||
774 | */ | ||
775 | |||
776 | #define STATE_MSG 0 | ||
777 | #define RESET_MSG 1 | ||
778 | #define ACTIVATE_MSG 2 | ||
779 | |||
780 | /* | ||
781 | * Changeover tunnel message types | ||
782 | */ | ||
783 | #define DUPLICATE_MSG 0 | ||
784 | #define ORIGINAL_MSG 1 | ||
785 | |||
786 | /* | ||
787 | * Routing table message types | ||
788 | */ | ||
789 | #define EXT_ROUTING_TABLE 0 | ||
790 | #define LOCAL_ROUTING_TABLE 1 /* obsoleted */ | ||
791 | #define SLAVE_ROUTING_TABLE 2 | ||
792 | #define ROUTE_ADDITION 3 | ||
793 | #define ROUTE_REMOVAL 4 | ||
794 | |||
795 | /* | ||
796 | * Config protocol message types | ||
797 | */ | ||
798 | |||
799 | #define DSC_REQ_MSG 0 | ||
800 | #define DSC_RESP_MSG 1 | ||
801 | |||
802 | u32 tipc_msg_tot_importance(struct tipc_msg *m); | 750 | u32 tipc_msg_tot_importance(struct tipc_msg *m); |
803 | void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, | 751 | void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, |
804 | u32 hsize, u32 destnode); | 752 | u32 hsize, u32 destnode); |
805 | int tipc_msg_calc_data_size(struct iovec const *msg_sect, u32 num_sect); | 753 | int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect, |
806 | int tipc_msg_build(struct tipc_msg *hdr, | 754 | u32 num_sect, unsigned int total_len, |
807 | struct iovec const *msg_sect, u32 num_sect, | ||
808 | int max_size, int usrmem, struct sk_buff **buf); | 755 | int max_size, int usrmem, struct sk_buff **buf); |
809 | 756 | ||
810 | static inline void msg_set_media_addr(struct tipc_msg *m, struct tipc_media_addr *a) | 757 | static inline void msg_set_media_addr(struct tipc_msg *m, struct tipc_media_addr *a) |
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index c9fa6dfcf287..80025a1b3bfd 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c | |||
@@ -160,7 +160,7 @@ void tipc_named_withdraw(struct publication *publ) | |||
160 | 160 | ||
161 | buf = named_prepare_buf(WITHDRAWAL, ITEM_SIZE, 0); | 161 | buf = named_prepare_buf(WITHDRAWAL, ITEM_SIZE, 0); |
162 | if (!buf) { | 162 | if (!buf) { |
163 | warn("Withdrawl distribution failure\n"); | 163 | warn("Withdrawal distribution failure\n"); |
164 | return; | 164 | return; |
165 | } | 165 | } |
166 | 166 | ||
diff --git a/net/tipc/port.c b/net/tipc/port.c index 6ff78f9c7d65..c68dc956a423 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c | |||
@@ -74,7 +74,8 @@ static u32 port_peerport(struct tipc_port *p_ptr) | |||
74 | */ | 74 | */ |
75 | 75 | ||
76 | int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, | 76 | int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, |
77 | u32 num_sect, struct iovec const *msg_sect) | 77 | u32 num_sect, struct iovec const *msg_sect, |
78 | unsigned int total_len) | ||
78 | { | 79 | { |
79 | struct tipc_msg *hdr; | 80 | struct tipc_msg *hdr; |
80 | struct sk_buff *buf; | 81 | struct sk_buff *buf; |
@@ -91,11 +92,14 @@ int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, | |||
91 | 92 | ||
92 | hdr = &oport->phdr; | 93 | hdr = &oport->phdr; |
93 | msg_set_type(hdr, TIPC_MCAST_MSG); | 94 | msg_set_type(hdr, TIPC_MCAST_MSG); |
95 | msg_set_lookup_scope(hdr, TIPC_CLUSTER_SCOPE); | ||
96 | msg_set_destport(hdr, 0); | ||
97 | msg_set_destnode(hdr, 0); | ||
94 | msg_set_nametype(hdr, seq->type); | 98 | msg_set_nametype(hdr, seq->type); |
95 | msg_set_namelower(hdr, seq->lower); | 99 | msg_set_namelower(hdr, seq->lower); |
96 | msg_set_nameupper(hdr, seq->upper); | 100 | msg_set_nameupper(hdr, seq->upper); |
97 | msg_set_hdr_sz(hdr, MCAST_H_SIZE); | 101 | msg_set_hdr_sz(hdr, MCAST_H_SIZE); |
98 | res = tipc_msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE, | 102 | res = tipc_msg_build(hdr, msg_sect, num_sect, total_len, MAX_MSG_SIZE, |
99 | !oport->user_port, &buf); | 103 | !oport->user_port, &buf); |
100 | if (unlikely(!buf)) | 104 | if (unlikely(!buf)) |
101 | return res; | 105 | return res; |
@@ -161,6 +165,7 @@ void tipc_port_recv_mcast(struct sk_buff *buf, struct port_list *dp) | |||
161 | /* Deliver a copy of message to each destination port */ | 165 | /* Deliver a copy of message to each destination port */ |
162 | 166 | ||
163 | if (dp->count != 0) { | 167 | if (dp->count != 0) { |
168 | msg_set_destnode(msg, tipc_own_addr); | ||
164 | if (dp->count == 1) { | 169 | if (dp->count == 1) { |
165 | msg_set_destport(msg, dp->ports[0]); | 170 | msg_set_destport(msg, dp->ports[0]); |
166 | tipc_port_recv_msg(buf); | 171 | tipc_port_recv_msg(buf); |
@@ -414,12 +419,12 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err) | |||
414 | 419 | ||
415 | int tipc_port_reject_sections(struct tipc_port *p_ptr, struct tipc_msg *hdr, | 420 | int tipc_port_reject_sections(struct tipc_port *p_ptr, struct tipc_msg *hdr, |
416 | struct iovec const *msg_sect, u32 num_sect, | 421 | struct iovec const *msg_sect, u32 num_sect, |
417 | int err) | 422 | unsigned int total_len, int err) |
418 | { | 423 | { |
419 | struct sk_buff *buf; | 424 | struct sk_buff *buf; |
420 | int res; | 425 | int res; |
421 | 426 | ||
422 | res = tipc_msg_build(hdr, msg_sect, num_sect, MAX_MSG_SIZE, | 427 | res = tipc_msg_build(hdr, msg_sect, num_sect, total_len, MAX_MSG_SIZE, |
423 | !p_ptr->user_port, &buf); | 428 | !p_ptr->user_port, &buf); |
424 | if (!buf) | 429 | if (!buf) |
425 | return res; | 430 | return res; |
@@ -1065,6 +1070,7 @@ int tipc_connect2port(u32 ref, struct tipc_portid const *peer) | |||
1065 | msg_set_orignode(msg, tipc_own_addr); | 1070 | msg_set_orignode(msg, tipc_own_addr); |
1066 | msg_set_origport(msg, p_ptr->ref); | 1071 | msg_set_origport(msg, p_ptr->ref); |
1067 | msg_set_type(msg, TIPC_CONN_MSG); | 1072 | msg_set_type(msg, TIPC_CONN_MSG); |
1073 | msg_set_lookup_scope(msg, 0); | ||
1068 | msg_set_hdr_sz(msg, SHORT_H_SIZE); | 1074 | msg_set_hdr_sz(msg, SHORT_H_SIZE); |
1069 | 1075 | ||
1070 | p_ptr->probing_interval = PROBING_INTERVAL; | 1076 | p_ptr->probing_interval = PROBING_INTERVAL; |
@@ -1158,12 +1164,13 @@ int tipc_shutdown(u32 ref) | |||
1158 | */ | 1164 | */ |
1159 | 1165 | ||
1160 | static int tipc_port_recv_sections(struct tipc_port *sender, unsigned int num_sect, | 1166 | static int tipc_port_recv_sections(struct tipc_port *sender, unsigned int num_sect, |
1161 | struct iovec const *msg_sect) | 1167 | struct iovec const *msg_sect, |
1168 | unsigned int total_len) | ||
1162 | { | 1169 | { |
1163 | struct sk_buff *buf; | 1170 | struct sk_buff *buf; |
1164 | int res; | 1171 | int res; |
1165 | 1172 | ||
1166 | res = tipc_msg_build(&sender->phdr, msg_sect, num_sect, | 1173 | res = tipc_msg_build(&sender->phdr, msg_sect, num_sect, total_len, |
1167 | MAX_MSG_SIZE, !sender->user_port, &buf); | 1174 | MAX_MSG_SIZE, !sender->user_port, &buf); |
1168 | if (likely(buf)) | 1175 | if (likely(buf)) |
1169 | tipc_port_recv_msg(buf); | 1176 | tipc_port_recv_msg(buf); |
@@ -1174,7 +1181,8 @@ static int tipc_port_recv_sections(struct tipc_port *sender, unsigned int num_se | |||
1174 | * tipc_send - send message sections on connection | 1181 | * tipc_send - send message sections on connection |
1175 | */ | 1182 | */ |
1176 | 1183 | ||
1177 | int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect) | 1184 | int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect, |
1185 | unsigned int total_len) | ||
1178 | { | 1186 | { |
1179 | struct tipc_port *p_ptr; | 1187 | struct tipc_port *p_ptr; |
1180 | u32 destnode; | 1188 | u32 destnode; |
@@ -1189,9 +1197,10 @@ int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect) | |||
1189 | destnode = port_peernode(p_ptr); | 1197 | destnode = port_peernode(p_ptr); |
1190 | if (likely(destnode != tipc_own_addr)) | 1198 | if (likely(destnode != tipc_own_addr)) |
1191 | res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect, | 1199 | res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect, |
1192 | destnode); | 1200 | total_len, destnode); |
1193 | else | 1201 | else |
1194 | res = tipc_port_recv_sections(p_ptr, num_sect, msg_sect); | 1202 | res = tipc_port_recv_sections(p_ptr, num_sect, msg_sect, |
1203 | total_len); | ||
1195 | 1204 | ||
1196 | if (likely(res != -ELINKCONG)) { | 1205 | if (likely(res != -ELINKCONG)) { |
1197 | p_ptr->congested = 0; | 1206 | p_ptr->congested = 0; |
@@ -1202,8 +1211,7 @@ int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect) | |||
1202 | } | 1211 | } |
1203 | if (port_unreliable(p_ptr)) { | 1212 | if (port_unreliable(p_ptr)) { |
1204 | p_ptr->congested = 0; | 1213 | p_ptr->congested = 0; |
1205 | /* Just calculate msg length and return */ | 1214 | return total_len; |
1206 | return tipc_msg_calc_data_size(msg_sect, num_sect); | ||
1207 | } | 1215 | } |
1208 | return -ELINKCONG; | 1216 | return -ELINKCONG; |
1209 | } | 1217 | } |
@@ -1213,7 +1221,8 @@ int tipc_send(u32 ref, unsigned int num_sect, struct iovec const *msg_sect) | |||
1213 | */ | 1221 | */ |
1214 | 1222 | ||
1215 | int tipc_send2name(u32 ref, struct tipc_name const *name, unsigned int domain, | 1223 | int tipc_send2name(u32 ref, struct tipc_name const *name, unsigned int domain, |
1216 | unsigned int num_sect, struct iovec const *msg_sect) | 1224 | unsigned int num_sect, struct iovec const *msg_sect, |
1225 | unsigned int total_len) | ||
1217 | { | 1226 | { |
1218 | struct tipc_port *p_ptr; | 1227 | struct tipc_port *p_ptr; |
1219 | struct tipc_msg *msg; | 1228 | struct tipc_msg *msg; |
@@ -1240,23 +1249,23 @@ int tipc_send2name(u32 ref, struct tipc_name const *name, unsigned int domain, | |||
1240 | if (likely(destport)) { | 1249 | if (likely(destport)) { |
1241 | if (likely(destnode == tipc_own_addr)) | 1250 | if (likely(destnode == tipc_own_addr)) |
1242 | res = tipc_port_recv_sections(p_ptr, num_sect, | 1251 | res = tipc_port_recv_sections(p_ptr, num_sect, |
1243 | msg_sect); | 1252 | msg_sect, total_len); |
1244 | else | 1253 | else |
1245 | res = tipc_link_send_sections_fast(p_ptr, msg_sect, | 1254 | res = tipc_link_send_sections_fast(p_ptr, msg_sect, |
1246 | num_sect, destnode); | 1255 | num_sect, total_len, |
1256 | destnode); | ||
1247 | if (likely(res != -ELINKCONG)) { | 1257 | if (likely(res != -ELINKCONG)) { |
1248 | if (res > 0) | 1258 | if (res > 0) |
1249 | p_ptr->sent++; | 1259 | p_ptr->sent++; |
1250 | return res; | 1260 | return res; |
1251 | } | 1261 | } |
1252 | if (port_unreliable(p_ptr)) { | 1262 | if (port_unreliable(p_ptr)) { |
1253 | /* Just calculate msg length and return */ | 1263 | return total_len; |
1254 | return tipc_msg_calc_data_size(msg_sect, num_sect); | ||
1255 | } | 1264 | } |
1256 | return -ELINKCONG; | 1265 | return -ELINKCONG; |
1257 | } | 1266 | } |
1258 | return tipc_port_reject_sections(p_ptr, msg, msg_sect, num_sect, | 1267 | return tipc_port_reject_sections(p_ptr, msg, msg_sect, num_sect, |
1259 | TIPC_ERR_NO_NAME); | 1268 | total_len, TIPC_ERR_NO_NAME); |
1260 | } | 1269 | } |
1261 | 1270 | ||
1262 | /** | 1271 | /** |
@@ -1264,7 +1273,8 @@ int tipc_send2name(u32 ref, struct tipc_name const *name, unsigned int domain, | |||
1264 | */ | 1273 | */ |
1265 | 1274 | ||
1266 | int tipc_send2port(u32 ref, struct tipc_portid const *dest, | 1275 | int tipc_send2port(u32 ref, struct tipc_portid const *dest, |
1267 | unsigned int num_sect, struct iovec const *msg_sect) | 1276 | unsigned int num_sect, struct iovec const *msg_sect, |
1277 | unsigned int total_len) | ||
1268 | { | 1278 | { |
1269 | struct tipc_port *p_ptr; | 1279 | struct tipc_port *p_ptr; |
1270 | struct tipc_msg *msg; | 1280 | struct tipc_msg *msg; |
@@ -1276,6 +1286,7 @@ int tipc_send2port(u32 ref, struct tipc_portid const *dest, | |||
1276 | 1286 | ||
1277 | msg = &p_ptr->phdr; | 1287 | msg = &p_ptr->phdr; |
1278 | msg_set_type(msg, TIPC_DIRECT_MSG); | 1288 | msg_set_type(msg, TIPC_DIRECT_MSG); |
1289 | msg_set_lookup_scope(msg, 0); | ||
1279 | msg_set_orignode(msg, tipc_own_addr); | 1290 | msg_set_orignode(msg, tipc_own_addr); |
1280 | msg_set_origport(msg, ref); | 1291 | msg_set_origport(msg, ref); |
1281 | msg_set_destnode(msg, dest->node); | 1292 | msg_set_destnode(msg, dest->node); |
@@ -1283,18 +1294,18 @@ int tipc_send2port(u32 ref, struct tipc_portid const *dest, | |||
1283 | msg_set_hdr_sz(msg, DIR_MSG_H_SIZE); | 1294 | msg_set_hdr_sz(msg, DIR_MSG_H_SIZE); |
1284 | 1295 | ||
1285 | if (dest->node == tipc_own_addr) | 1296 | if (dest->node == tipc_own_addr) |
1286 | res = tipc_port_recv_sections(p_ptr, num_sect, msg_sect); | 1297 | res = tipc_port_recv_sections(p_ptr, num_sect, msg_sect, |
1298 | total_len); | ||
1287 | else | 1299 | else |
1288 | res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect, | 1300 | res = tipc_link_send_sections_fast(p_ptr, msg_sect, num_sect, |
1289 | dest->node); | 1301 | total_len, dest->node); |
1290 | if (likely(res != -ELINKCONG)) { | 1302 | if (likely(res != -ELINKCONG)) { |
1291 | if (res > 0) | 1303 | if (res > 0) |
1292 | p_ptr->sent++; | 1304 | p_ptr->sent++; |
1293 | return res; | 1305 | return res; |
1294 | } | 1306 | } |
1295 | if (port_unreliable(p_ptr)) { | 1307 | if (port_unreliable(p_ptr)) { |
1296 | /* Just calculate msg length and return */ | 1308 | return total_len; |
1297 | return tipc_msg_calc_data_size(msg_sect, num_sect); | ||
1298 | } | 1309 | } |
1299 | return -ELINKCONG; | 1310 | return -ELINKCONG; |
1300 | } | 1311 | } |
diff --git a/net/tipc/port.h b/net/tipc/port.h index 87b9424ae0ec..b9aa34195aec 100644 --- a/net/tipc/port.h +++ b/net/tipc/port.h | |||
@@ -205,23 +205,27 @@ int tipc_disconnect_port(struct tipc_port *tp_ptr); | |||
205 | /* | 205 | /* |
206 | * TIPC messaging routines | 206 | * TIPC messaging routines |
207 | */ | 207 | */ |
208 | int tipc_send(u32 portref, unsigned int num_sect, struct iovec const *msg_sect); | 208 | int tipc_send(u32 portref, unsigned int num_sect, struct iovec const *msg_sect, |
209 | unsigned int total_len); | ||
209 | 210 | ||
210 | int tipc_send2name(u32 portref, struct tipc_name const *name, u32 domain, | 211 | int tipc_send2name(u32 portref, struct tipc_name const *name, u32 domain, |
211 | unsigned int num_sect, struct iovec const *msg_sect); | 212 | unsigned int num_sect, struct iovec const *msg_sect, |
213 | unsigned int total_len); | ||
212 | 214 | ||
213 | int tipc_send2port(u32 portref, struct tipc_portid const *dest, | 215 | int tipc_send2port(u32 portref, struct tipc_portid const *dest, |
214 | unsigned int num_sect, struct iovec const *msg_sect); | 216 | unsigned int num_sect, struct iovec const *msg_sect, |
217 | unsigned int total_len); | ||
215 | 218 | ||
216 | int tipc_send_buf2port(u32 portref, struct tipc_portid const *dest, | 219 | int tipc_send_buf2port(u32 portref, struct tipc_portid const *dest, |
217 | struct sk_buff *buf, unsigned int dsz); | 220 | struct sk_buff *buf, unsigned int dsz); |
218 | 221 | ||
219 | int tipc_multicast(u32 portref, struct tipc_name_seq const *seq, | 222 | int tipc_multicast(u32 portref, struct tipc_name_seq const *seq, |
220 | unsigned int section_count, struct iovec const *msg); | 223 | unsigned int section_count, struct iovec const *msg, |
224 | unsigned int total_len); | ||
221 | 225 | ||
222 | int tipc_port_reject_sections(struct tipc_port *p_ptr, struct tipc_msg *hdr, | 226 | int tipc_port_reject_sections(struct tipc_port *p_ptr, struct tipc_msg *hdr, |
223 | struct iovec const *msg_sect, u32 num_sect, | 227 | struct iovec const *msg_sect, u32 num_sect, |
224 | int err); | 228 | unsigned int total_len, int err); |
225 | struct sk_buff *tipc_port_get_ports(void); | 229 | struct sk_buff *tipc_port_get_ports(void); |
226 | void tipc_port_recv_proto_msg(struct sk_buff *buf); | 230 | void tipc_port_recv_proto_msg(struct sk_buff *buf); |
227 | void tipc_port_recv_mcast(struct sk_buff *buf, struct port_list *dp); | 231 | void tipc_port_recv_mcast(struct sk_buff *buf, struct port_list *dp); |
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 29d94d53198d..338837396642 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -535,6 +535,9 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, | |||
535 | if (unlikely((m->msg_namelen < sizeof(*dest)) || | 535 | if (unlikely((m->msg_namelen < sizeof(*dest)) || |
536 | (dest->family != AF_TIPC))) | 536 | (dest->family != AF_TIPC))) |
537 | return -EINVAL; | 537 | return -EINVAL; |
538 | if ((total_len > TIPC_MAX_USER_MSG_SIZE) || | ||
539 | (m->msg_iovlen > (unsigned)INT_MAX)) | ||
540 | return -EMSGSIZE; | ||
538 | 541 | ||
539 | if (iocb) | 542 | if (iocb) |
540 | lock_sock(sk); | 543 | lock_sock(sk); |
@@ -573,12 +576,14 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, | |||
573 | &dest->addr.name.name, | 576 | &dest->addr.name.name, |
574 | dest->addr.name.domain, | 577 | dest->addr.name.domain, |
575 | m->msg_iovlen, | 578 | m->msg_iovlen, |
576 | m->msg_iov); | 579 | m->msg_iov, |
580 | total_len); | ||
577 | } else if (dest->addrtype == TIPC_ADDR_ID) { | 581 | } else if (dest->addrtype == TIPC_ADDR_ID) { |
578 | res = tipc_send2port(tport->ref, | 582 | res = tipc_send2port(tport->ref, |
579 | &dest->addr.id, | 583 | &dest->addr.id, |
580 | m->msg_iovlen, | 584 | m->msg_iovlen, |
581 | m->msg_iov); | 585 | m->msg_iov, |
586 | total_len); | ||
582 | } else if (dest->addrtype == TIPC_ADDR_MCAST) { | 587 | } else if (dest->addrtype == TIPC_ADDR_MCAST) { |
583 | if (needs_conn) { | 588 | if (needs_conn) { |
584 | res = -EOPNOTSUPP; | 589 | res = -EOPNOTSUPP; |
@@ -590,7 +595,8 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, | |||
590 | res = tipc_multicast(tport->ref, | 595 | res = tipc_multicast(tport->ref, |
591 | &dest->addr.nameseq, | 596 | &dest->addr.nameseq, |
592 | m->msg_iovlen, | 597 | m->msg_iovlen, |
593 | m->msg_iov); | 598 | m->msg_iov, |
599 | total_len); | ||
594 | } | 600 | } |
595 | if (likely(res != -ELINKCONG)) { | 601 | if (likely(res != -ELINKCONG)) { |
596 | if (needs_conn && (res >= 0)) | 602 | if (needs_conn && (res >= 0)) |
@@ -640,6 +646,10 @@ static int send_packet(struct kiocb *iocb, struct socket *sock, | |||
640 | if (unlikely(dest)) | 646 | if (unlikely(dest)) |
641 | return send_msg(iocb, sock, m, total_len); | 647 | return send_msg(iocb, sock, m, total_len); |
642 | 648 | ||
649 | if ((total_len > TIPC_MAX_USER_MSG_SIZE) || | ||
650 | (m->msg_iovlen > (unsigned)INT_MAX)) | ||
651 | return -EMSGSIZE; | ||
652 | |||
643 | if (iocb) | 653 | if (iocb) |
644 | lock_sock(sk); | 654 | lock_sock(sk); |
645 | 655 | ||
@@ -652,7 +662,8 @@ static int send_packet(struct kiocb *iocb, struct socket *sock, | |||
652 | break; | 662 | break; |
653 | } | 663 | } |
654 | 664 | ||
655 | res = tipc_send(tport->ref, m->msg_iovlen, m->msg_iov); | 665 | res = tipc_send(tport->ref, m->msg_iovlen, m->msg_iov, |
666 | total_len); | ||
656 | if (likely(res != -ELINKCONG)) | 667 | if (likely(res != -ELINKCONG)) |
657 | break; | 668 | break; |
658 | if (m->msg_flags & MSG_DONTWAIT) { | 669 | if (m->msg_flags & MSG_DONTWAIT) { |
@@ -723,6 +734,12 @@ static int send_stream(struct kiocb *iocb, struct socket *sock, | |||
723 | goto exit; | 734 | goto exit; |
724 | } | 735 | } |
725 | 736 | ||
737 | if ((total_len > (unsigned)INT_MAX) || | ||
738 | (m->msg_iovlen > (unsigned)INT_MAX)) { | ||
739 | res = -EMSGSIZE; | ||
740 | goto exit; | ||
741 | } | ||
742 | |||
726 | /* | 743 | /* |
727 | * Send each iovec entry using one or more messages | 744 | * Send each iovec entry using one or more messages |
728 | * | 745 | * |
@@ -753,7 +770,7 @@ static int send_stream(struct kiocb *iocb, struct socket *sock, | |||
753 | bytes_to_send = curr_left; | 770 | bytes_to_send = curr_left; |
754 | my_iov.iov_base = curr_start; | 771 | my_iov.iov_base = curr_start; |
755 | my_iov.iov_len = bytes_to_send; | 772 | my_iov.iov_len = bytes_to_send; |
756 | res = send_packet(NULL, sock, &my_msg, 0); | 773 | res = send_packet(NULL, sock, &my_msg, bytes_to_send); |
757 | if (res < 0) { | 774 | if (res < 0) { |
758 | if (bytes_sent) | 775 | if (bytes_sent) |
759 | res = bytes_sent; | 776 | res = bytes_sent; |
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index aae9eae13404..6cf726863485 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c | |||
@@ -109,7 +109,7 @@ static void subscr_send_event(struct subscription *sub, | |||
109 | sub->evt.found_upper = htohl(found_upper, sub->swap); | 109 | sub->evt.found_upper = htohl(found_upper, sub->swap); |
110 | sub->evt.port.ref = htohl(port_ref, sub->swap); | 110 | sub->evt.port.ref = htohl(port_ref, sub->swap); |
111 | sub->evt.port.node = htohl(node, sub->swap); | 111 | sub->evt.port.node = htohl(node, sub->swap); |
112 | tipc_send(sub->server_ref, 1, &msg_sect); | 112 | tipc_send(sub->server_ref, 1, &msg_sect, msg_sect.iov_len); |
113 | } | 113 | } |
114 | 114 | ||
115 | /** | 115 | /** |
@@ -521,7 +521,7 @@ static void subscr_named_msg_event(void *usr_handle, | |||
521 | 521 | ||
522 | /* Send an ACK- to complete connection handshaking */ | 522 | /* Send an ACK- to complete connection handshaking */ |
523 | 523 | ||
524 | tipc_send(server_port_ref, 0, NULL); | 524 | tipc_send(server_port_ref, 0, NULL, 0); |
525 | 525 | ||
526 | /* Handle optional subscription request */ | 526 | /* Handle optional subscription request */ |
527 | 527 | ||
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 1663e1a2efdd..b1d75beb7e20 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -207,7 +207,7 @@ static int unix_mkname(struct sockaddr_un *sunaddr, int len, unsigned *hashp) | |||
207 | /* | 207 | /* |
208 | * This may look like an off by one error but it is a bit more | 208 | * This may look like an off by one error but it is a bit more |
209 | * subtle. 108 is the longest valid AF_UNIX path for a binding. | 209 | * subtle. 108 is the longest valid AF_UNIX path for a binding. |
210 | * sun_path[108] doesnt as such exist. However in kernel space | 210 | * sun_path[108] doesn't as such exist. However in kernel space |
211 | * we are guaranteed that it is a valid memory location in our | 211 | * we are guaranteed that it is a valid memory location in our |
212 | * kernel address buffer. | 212 | * kernel address buffer. |
213 | */ | 213 | */ |
@@ -524,6 +524,8 @@ static int unix_dgram_connect(struct socket *, struct sockaddr *, | |||
524 | int, int); | 524 | int, int); |
525 | static int unix_seqpacket_sendmsg(struct kiocb *, struct socket *, | 525 | static int unix_seqpacket_sendmsg(struct kiocb *, struct socket *, |
526 | struct msghdr *, size_t); | 526 | struct msghdr *, size_t); |
527 | static int unix_seqpacket_recvmsg(struct kiocb *, struct socket *, | ||
528 | struct msghdr *, size_t, int); | ||
527 | 529 | ||
528 | static const struct proto_ops unix_stream_ops = { | 530 | static const struct proto_ops unix_stream_ops = { |
529 | .family = PF_UNIX, | 531 | .family = PF_UNIX, |
@@ -583,7 +585,7 @@ static const struct proto_ops unix_seqpacket_ops = { | |||
583 | .setsockopt = sock_no_setsockopt, | 585 | .setsockopt = sock_no_setsockopt, |
584 | .getsockopt = sock_no_getsockopt, | 586 | .getsockopt = sock_no_getsockopt, |
585 | .sendmsg = unix_seqpacket_sendmsg, | 587 | .sendmsg = unix_seqpacket_sendmsg, |
586 | .recvmsg = unix_dgram_recvmsg, | 588 | .recvmsg = unix_seqpacket_recvmsg, |
587 | .mmap = sock_no_mmap, | 589 | .mmap = sock_no_mmap, |
588 | .sendpage = sock_no_sendpage, | 590 | .sendpage = sock_no_sendpage, |
589 | }; | 591 | }; |
@@ -1699,6 +1701,18 @@ static int unix_seqpacket_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1699 | return unix_dgram_sendmsg(kiocb, sock, msg, len); | 1701 | return unix_dgram_sendmsg(kiocb, sock, msg, len); |
1700 | } | 1702 | } |
1701 | 1703 | ||
1704 | static int unix_seqpacket_recvmsg(struct kiocb *iocb, struct socket *sock, | ||
1705 | struct msghdr *msg, size_t size, | ||
1706 | int flags) | ||
1707 | { | ||
1708 | struct sock *sk = sock->sk; | ||
1709 | |||
1710 | if (sk->sk_state != TCP_ESTABLISHED) | ||
1711 | return -ENOTCONN; | ||
1712 | |||
1713 | return unix_dgram_recvmsg(iocb, sock, msg, size, flags); | ||
1714 | } | ||
1715 | |||
1702 | static void unix_copy_addr(struct msghdr *msg, struct sock *sk) | 1716 | static void unix_copy_addr(struct msghdr *msg, struct sock *sk) |
1703 | { | 1717 | { |
1704 | struct unix_sock *u = unix_sk(sk); | 1718 | struct unix_sock *u = unix_sk(sk); |
diff --git a/net/wanrouter/wanproc.c b/net/wanrouter/wanproc.c index 11f25c7a7a05..f346395314ba 100644 --- a/net/wanrouter/wanproc.c +++ b/net/wanrouter/wanproc.c | |||
@@ -51,7 +51,7 @@ | |||
51 | 51 | ||
52 | /* | 52 | /* |
53 | * Structures for interfacing with the /proc filesystem. | 53 | * Structures for interfacing with the /proc filesystem. |
54 | * Router creates its own directory /proc/net/router with the folowing | 54 | * Router creates its own directory /proc/net/router with the following |
55 | * entries: | 55 | * entries: |
56 | * config device configuration | 56 | * config device configuration |
57 | * status global device statistics | 57 | * status global device statistics |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 798cb4cd0702..1ad0f39fe091 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -810,7 +810,7 @@ static void handle_channel(struct wiphy *wiphy, | |||
810 | if (r) { | 810 | if (r) { |
811 | /* | 811 | /* |
812 | * We will disable all channels that do not match our | 812 | * We will disable all channels that do not match our |
813 | * recieved regulatory rule unless the hint is coming | 813 | * received regulatory rule unless the hint is coming |
814 | * from a Country IE and the Country IE had no information | 814 | * from a Country IE and the Country IE had no information |
815 | * about a band. The IEEE 802.11 spec allows for an AP | 815 | * about a band. The IEEE 802.11 spec allows for an AP |
816 | * to send only a subset of the regulatory rules allowed, | 816 | * to send only a subset of the regulatory rules allowed, |
@@ -839,7 +839,7 @@ static void handle_channel(struct wiphy *wiphy, | |||
839 | request_wiphy && request_wiphy == wiphy && | 839 | request_wiphy && request_wiphy == wiphy && |
840 | request_wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) { | 840 | request_wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) { |
841 | /* | 841 | /* |
842 | * This gaurantees the driver's requested regulatory domain | 842 | * This guarantees the driver's requested regulatory domain |
843 | * will always be used as a base for further regulatory | 843 | * will always be used as a base for further regulatory |
844 | * settings | 844 | * settings |
845 | */ | 845 | */ |
diff --git a/net/x25/x25_facilities.c b/net/x25/x25_facilities.c index 406207515b5e..f77e4e75f914 100644 --- a/net/x25/x25_facilities.c +++ b/net/x25/x25_facilities.c | |||
@@ -31,7 +31,7 @@ | |||
31 | * x25_parse_facilities - Parse facilities from skb into the facilities structs | 31 | * x25_parse_facilities - Parse facilities from skb into the facilities structs |
32 | * | 32 | * |
33 | * @skb: sk_buff to parse | 33 | * @skb: sk_buff to parse |
34 | * @facilities: Regular facilites, updated as facilities are found | 34 | * @facilities: Regular facilities, updated as facilities are found |
35 | * @dte_facs: ITU DTE facilities, updated as DTE facilities are found | 35 | * @dte_facs: ITU DTE facilities, updated as DTE facilities are found |
36 | * @vc_fac_mask: mask is updated with all facilities found | 36 | * @vc_fac_mask: mask is updated with all facilities found |
37 | * | 37 | * |
diff --git a/net/x25/x25_forward.c b/net/x25/x25_forward.c index 25a810793968..c541b622ae16 100644 --- a/net/x25/x25_forward.c +++ b/net/x25/x25_forward.c | |||
@@ -31,7 +31,7 @@ int x25_forward_call(struct x25_address *dest_addr, struct x25_neigh *from, | |||
31 | goto out_no_route; | 31 | goto out_no_route; |
32 | 32 | ||
33 | if ((neigh_new = x25_get_neigh(rt->dev)) == NULL) { | 33 | if ((neigh_new = x25_get_neigh(rt->dev)) == NULL) { |
34 | /* This shouldnt happen, if it occurs somehow | 34 | /* This shouldn't happen, if it occurs somehow |
35 | * do something sensible | 35 | * do something sensible |
36 | */ | 36 | */ |
37 | goto out_put_route; | 37 | goto out_put_route; |
@@ -45,7 +45,7 @@ int x25_forward_call(struct x25_address *dest_addr, struct x25_neigh *from, | |||
45 | } | 45 | } |
46 | 46 | ||
47 | /* Remote end sending a call request on an already | 47 | /* Remote end sending a call request on an already |
48 | * established LCI? It shouldnt happen, just in case.. | 48 | * established LCI? It shouldn't happen, just in case.. |
49 | */ | 49 | */ |
50 | read_lock_bh(&x25_forward_list_lock); | 50 | read_lock_bh(&x25_forward_list_lock); |
51 | list_for_each(entry, &x25_forward_list) { | 51 | list_for_each(entry, &x25_forward_list) { |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 15792d8b6272..9bec2e8a838c 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -1348,7 +1348,8 @@ static inline struct xfrm_dst *xfrm_alloc_dst(struct net *net, int family) | |||
1348 | default: | 1348 | default: |
1349 | BUG(); | 1349 | BUG(); |
1350 | } | 1350 | } |
1351 | xdst = dst_alloc(dst_ops, 0); | 1351 | xdst = dst_alloc(dst_ops, NULL, 0, 0, 0); |
1352 | memset(&xdst->u.rt6.rt6i_table, 0, sizeof(*xdst) - sizeof(struct dst_entry)); | ||
1352 | xfrm_policy_put_afinfo(afinfo); | 1353 | xfrm_policy_put_afinfo(afinfo); |
1353 | 1354 | ||
1354 | if (likely(xdst)) | 1355 | if (likely(xdst)) |
@@ -1406,6 +1407,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, | |||
1406 | struct net *net = xp_net(policy); | 1407 | struct net *net = xp_net(policy); |
1407 | unsigned long now = jiffies; | 1408 | unsigned long now = jiffies; |
1408 | struct net_device *dev; | 1409 | struct net_device *dev; |
1410 | struct xfrm_mode *inner_mode; | ||
1409 | struct dst_entry *dst_prev = NULL; | 1411 | struct dst_entry *dst_prev = NULL; |
1410 | struct dst_entry *dst0 = NULL; | 1412 | struct dst_entry *dst0 = NULL; |
1411 | int i = 0; | 1413 | int i = 0; |
@@ -1436,6 +1438,17 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, | |||
1436 | goto put_states; | 1438 | goto put_states; |
1437 | } | 1439 | } |
1438 | 1440 | ||
1441 | if (xfrm[i]->sel.family == AF_UNSPEC) { | ||
1442 | inner_mode = xfrm_ip2inner_mode(xfrm[i], | ||
1443 | xfrm_af2proto(family)); | ||
1444 | if (!inner_mode) { | ||
1445 | err = -EAFNOSUPPORT; | ||
1446 | dst_release(dst); | ||
1447 | goto put_states; | ||
1448 | } | ||
1449 | } else | ||
1450 | inner_mode = xfrm[i]->inner_mode; | ||
1451 | |||
1439 | if (!dst_prev) | 1452 | if (!dst_prev) |
1440 | dst0 = dst1; | 1453 | dst0 = dst1; |
1441 | else { | 1454 | else { |
@@ -1464,7 +1477,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, | |||
1464 | dst1->lastuse = now; | 1477 | dst1->lastuse = now; |
1465 | 1478 | ||
1466 | dst1->input = dst_discard; | 1479 | dst1->input = dst_discard; |
1467 | dst1->output = xfrm[i]->outer_mode->afinfo->output; | 1480 | dst1->output = inner_mode->afinfo->output; |
1468 | 1481 | ||
1469 | dst1->next = dst_prev; | 1482 | dst1->next = dst_prev; |
1470 | dst_prev = dst1; | 1483 | dst_prev = dst1; |
diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c index f218385950ca..47f1b8638df9 100644 --- a/net/xfrm/xfrm_replay.c +++ b/net/xfrm/xfrm_replay.c | |||
@@ -532,9 +532,12 @@ int xfrm_init_replay(struct xfrm_state *x) | |||
532 | 532 | ||
533 | if (replay_esn) { | 533 | if (replay_esn) { |
534 | if (replay_esn->replay_window > | 534 | if (replay_esn->replay_window > |
535 | replay_esn->bmp_len * sizeof(__u32)) | 535 | replay_esn->bmp_len * sizeof(__u32) * 8) |
536 | return -EINVAL; | 536 | return -EINVAL; |
537 | 537 | ||
538 | if ((x->props.flags & XFRM_STATE_ESN) && replay_esn->replay_window == 0) | ||
539 | return -EINVAL; | ||
540 | |||
538 | if ((x->props.flags & XFRM_STATE_ESN) && x->replay_esn) | 541 | if ((x->props.flags & XFRM_STATE_ESN) && x->replay_esn) |
539 | x->repl = &xfrm_replay_esn; | 542 | x->repl = &xfrm_replay_esn; |
540 | else | 543 | else |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index dd78536d40de..d70f85eb7864 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -1036,15 +1036,15 @@ static struct xfrm_state *__find_acq_core(struct net *net, struct xfrm_mark *m, | |||
1036 | 1036 | ||
1037 | case AF_INET6: | 1037 | case AF_INET6: |
1038 | ipv6_addr_copy((struct in6_addr *)x->sel.daddr.a6, | 1038 | ipv6_addr_copy((struct in6_addr *)x->sel.daddr.a6, |
1039 | (struct in6_addr *)daddr); | 1039 | (const struct in6_addr *)daddr); |
1040 | ipv6_addr_copy((struct in6_addr *)x->sel.saddr.a6, | 1040 | ipv6_addr_copy((struct in6_addr *)x->sel.saddr.a6, |
1041 | (struct in6_addr *)saddr); | 1041 | (const struct in6_addr *)saddr); |
1042 | x->sel.prefixlen_d = 128; | 1042 | x->sel.prefixlen_d = 128; |
1043 | x->sel.prefixlen_s = 128; | 1043 | x->sel.prefixlen_s = 128; |
1044 | ipv6_addr_copy((struct in6_addr *)x->props.saddr.a6, | 1044 | ipv6_addr_copy((struct in6_addr *)x->props.saddr.a6, |
1045 | (struct in6_addr *)saddr); | 1045 | (const struct in6_addr *)saddr); |
1046 | ipv6_addr_copy((struct in6_addr *)x->id.daddr.a6, | 1046 | ipv6_addr_copy((struct in6_addr *)x->id.daddr.a6, |
1047 | (struct in6_addr *)daddr); | 1047 | (const struct in6_addr *)daddr); |
1048 | break; | 1048 | break; |
1049 | } | 1049 | } |
1050 | 1050 | ||
@@ -2092,8 +2092,8 @@ static void xfrm_audit_helper_sainfo(struct xfrm_state *x, | |||
2092 | static void xfrm_audit_helper_pktinfo(struct sk_buff *skb, u16 family, | 2092 | static void xfrm_audit_helper_pktinfo(struct sk_buff *skb, u16 family, |
2093 | struct audit_buffer *audit_buf) | 2093 | struct audit_buffer *audit_buf) |
2094 | { | 2094 | { |
2095 | struct iphdr *iph4; | 2095 | const struct iphdr *iph4; |
2096 | struct ipv6hdr *iph6; | 2096 | const struct ipv6hdr *iph6; |
2097 | 2097 | ||
2098 | switch (family) { | 2098 | switch (family) { |
2099 | case AF_INET: | 2099 | case AF_INET: |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 3d15d3e1b2c4..c658cb3bc7c3 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -124,6 +124,9 @@ static inline int verify_replay(struct xfrm_usersa_info *p, | |||
124 | { | 124 | { |
125 | struct nlattr *rt = attrs[XFRMA_REPLAY_ESN_VAL]; | 125 | struct nlattr *rt = attrs[XFRMA_REPLAY_ESN_VAL]; |
126 | 126 | ||
127 | if ((p->flags & XFRM_STATE_ESN) && !rt) | ||
128 | return -EINVAL; | ||
129 | |||
127 | if (!rt) | 130 | if (!rt) |
128 | return 0; | 131 | return 0; |
129 | 132 | ||
@@ -894,7 +897,7 @@ static int build_spdinfo(struct sk_buff *skb, struct net *net, | |||
894 | u32 *f; | 897 | u32 *f; |
895 | 898 | ||
896 | nlh = nlmsg_put(skb, pid, seq, XFRM_MSG_NEWSPDINFO, sizeof(u32), 0); | 899 | nlh = nlmsg_put(skb, pid, seq, XFRM_MSG_NEWSPDINFO, sizeof(u32), 0); |
897 | if (nlh == NULL) /* shouldnt really happen ... */ | 900 | if (nlh == NULL) /* shouldn't really happen ... */ |
898 | return -EMSGSIZE; | 901 | return -EMSGSIZE; |
899 | 902 | ||
900 | f = nlmsg_data(nlh); | 903 | f = nlmsg_data(nlh); |
@@ -954,7 +957,7 @@ static int build_sadinfo(struct sk_buff *skb, struct net *net, | |||
954 | u32 *f; | 957 | u32 *f; |
955 | 958 | ||
956 | nlh = nlmsg_put(skb, pid, seq, XFRM_MSG_NEWSADINFO, sizeof(u32), 0); | 959 | nlh = nlmsg_put(skb, pid, seq, XFRM_MSG_NEWSADINFO, sizeof(u32), 0); |
957 | if (nlh == NULL) /* shouldnt really happen ... */ | 960 | if (nlh == NULL) /* shouldn't really happen ... */ |
958 | return -EMSGSIZE; | 961 | return -EMSGSIZE; |
959 | 962 | ||
960 | f = nlmsg_data(nlh); | 963 | f = nlmsg_data(nlh); |
@@ -1361,7 +1364,7 @@ static int xfrm_add_policy(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
1361 | if (!xp) | 1364 | if (!xp) |
1362 | return err; | 1365 | return err; |
1363 | 1366 | ||
1364 | /* shouldnt excl be based on nlh flags?? | 1367 | /* shouldn't excl be based on nlh flags?? |
1365 | * Aha! this is anti-netlink really i.e more pfkey derived | 1368 | * Aha! this is anti-netlink really i.e more pfkey derived |
1366 | * in netlink excl is a flag and you wouldnt need | 1369 | * in netlink excl is a flag and you wouldnt need |
1367 | * a type XFRM_MSG_UPDPOLICY - JHS */ | 1370 | * a type XFRM_MSG_UPDPOLICY - JHS */ |