diff options
Diffstat (limited to 'net')
300 files changed, 11241 insertions, 4916 deletions
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index 8ca533c95de0..b258da88f675 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c | |||
@@ -368,3 +368,9 @@ void vlan_vids_del_by_dev(struct net_device *dev, | |||
368 | vlan_vid_del(dev, vid_info->vid); | 368 | vlan_vid_del(dev, vid_info->vid); |
369 | } | 369 | } |
370 | EXPORT_SYMBOL(vlan_vids_del_by_dev); | 370 | EXPORT_SYMBOL(vlan_vids_del_by_dev); |
371 | |||
372 | bool vlan_uses_dev(const struct net_device *dev) | ||
373 | { | ||
374 | return rtnl_dereference(dev->vlan_info) ? true : false; | ||
375 | } | ||
376 | EXPORT_SYMBOL(vlan_uses_dev); | ||
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 73a2a83ee2da..402442402af7 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
@@ -137,9 +137,21 @@ static int vlan_dev_hard_header(struct sk_buff *skb, struct net_device *dev, | |||
137 | return rc; | 137 | return rc; |
138 | } | 138 | } |
139 | 139 | ||
140 | static inline netdev_tx_t vlan_netpoll_send_skb(struct vlan_dev_priv *vlan, struct sk_buff *skb) | ||
141 | { | ||
142 | #ifdef CONFIG_NET_POLL_CONTROLLER | ||
143 | if (vlan->netpoll) | ||
144 | netpoll_send_skb(vlan->netpoll, skb); | ||
145 | #else | ||
146 | BUG(); | ||
147 | #endif | ||
148 | return NETDEV_TX_OK; | ||
149 | } | ||
150 | |||
140 | static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb, | 151 | static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb, |
141 | struct net_device *dev) | 152 | struct net_device *dev) |
142 | { | 153 | { |
154 | struct vlan_dev_priv *vlan = vlan_dev_priv(dev); | ||
143 | struct vlan_ethhdr *veth = (struct vlan_ethhdr *)(skb->data); | 155 | struct vlan_ethhdr *veth = (struct vlan_ethhdr *)(skb->data); |
144 | unsigned int len; | 156 | unsigned int len; |
145 | int ret; | 157 | int ret; |
@@ -150,29 +162,30 @@ static netdev_tx_t vlan_dev_hard_start_xmit(struct sk_buff *skb, | |||
150 | * OTHER THINGS LIKE FDDI/TokenRing/802.3 SNAPs... | 162 | * OTHER THINGS LIKE FDDI/TokenRing/802.3 SNAPs... |
151 | */ | 163 | */ |
152 | if (veth->h_vlan_proto != htons(ETH_P_8021Q) || | 164 | if (veth->h_vlan_proto != htons(ETH_P_8021Q) || |
153 | vlan_dev_priv(dev)->flags & VLAN_FLAG_REORDER_HDR) { | 165 | vlan->flags & VLAN_FLAG_REORDER_HDR) { |
154 | u16 vlan_tci; | 166 | u16 vlan_tci; |
155 | vlan_tci = vlan_dev_priv(dev)->vlan_id; | 167 | vlan_tci = vlan->vlan_id; |
156 | vlan_tci |= vlan_dev_get_egress_qos_mask(dev, skb); | 168 | vlan_tci |= vlan_dev_get_egress_qos_mask(dev, skb); |
157 | skb = __vlan_hwaccel_put_tag(skb, vlan_tci); | 169 | skb = __vlan_hwaccel_put_tag(skb, vlan_tci); |
158 | } | 170 | } |
159 | 171 | ||
160 | skb->dev = vlan_dev_priv(dev)->real_dev; | 172 | skb->dev = vlan->real_dev; |
161 | len = skb->len; | 173 | len = skb->len; |
162 | if (netpoll_tx_running(dev)) | 174 | if (unlikely(netpoll_tx_running(dev))) |
163 | return skb->dev->netdev_ops->ndo_start_xmit(skb, skb->dev); | 175 | return vlan_netpoll_send_skb(vlan, skb); |
176 | |||
164 | ret = dev_queue_xmit(skb); | 177 | ret = dev_queue_xmit(skb); |
165 | 178 | ||
166 | if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) { | 179 | if (likely(ret == NET_XMIT_SUCCESS || ret == NET_XMIT_CN)) { |
167 | struct vlan_pcpu_stats *stats; | 180 | struct vlan_pcpu_stats *stats; |
168 | 181 | ||
169 | stats = this_cpu_ptr(vlan_dev_priv(dev)->vlan_pcpu_stats); | 182 | stats = this_cpu_ptr(vlan->vlan_pcpu_stats); |
170 | u64_stats_update_begin(&stats->syncp); | 183 | u64_stats_update_begin(&stats->syncp); |
171 | stats->tx_packets++; | 184 | stats->tx_packets++; |
172 | stats->tx_bytes += len; | 185 | stats->tx_bytes += len; |
173 | u64_stats_update_end(&stats->syncp); | 186 | u64_stats_update_end(&stats->syncp); |
174 | } else { | 187 | } else { |
175 | this_cpu_inc(vlan_dev_priv(dev)->vlan_pcpu_stats->tx_dropped); | 188 | this_cpu_inc(vlan->vlan_pcpu_stats->tx_dropped); |
176 | } | 189 | } |
177 | 190 | ||
178 | return ret; | 191 | return ret; |
@@ -669,25 +682,26 @@ static void vlan_dev_poll_controller(struct net_device *dev) | |||
669 | return; | 682 | return; |
670 | } | 683 | } |
671 | 684 | ||
672 | static int vlan_dev_netpoll_setup(struct net_device *dev, struct netpoll_info *npinfo) | 685 | static int vlan_dev_netpoll_setup(struct net_device *dev, struct netpoll_info *npinfo, |
686 | gfp_t gfp) | ||
673 | { | 687 | { |
674 | struct vlan_dev_priv *info = vlan_dev_priv(dev); | 688 | struct vlan_dev_priv *vlan = vlan_dev_priv(dev); |
675 | struct net_device *real_dev = info->real_dev; | 689 | struct net_device *real_dev = vlan->real_dev; |
676 | struct netpoll *netpoll; | 690 | struct netpoll *netpoll; |
677 | int err = 0; | 691 | int err = 0; |
678 | 692 | ||
679 | netpoll = kzalloc(sizeof(*netpoll), GFP_KERNEL); | 693 | netpoll = kzalloc(sizeof(*netpoll), gfp); |
680 | err = -ENOMEM; | 694 | err = -ENOMEM; |
681 | if (!netpoll) | 695 | if (!netpoll) |
682 | goto out; | 696 | goto out; |
683 | 697 | ||
684 | err = __netpoll_setup(netpoll, real_dev); | 698 | err = __netpoll_setup(netpoll, real_dev, gfp); |
685 | if (err) { | 699 | if (err) { |
686 | kfree(netpoll); | 700 | kfree(netpoll); |
687 | goto out; | 701 | goto out; |
688 | } | 702 | } |
689 | 703 | ||
690 | info->netpoll = netpoll; | 704 | vlan->netpoll = netpoll; |
691 | 705 | ||
692 | out: | 706 | out: |
693 | return err; | 707 | return err; |
@@ -695,19 +709,15 @@ out: | |||
695 | 709 | ||
696 | static void vlan_dev_netpoll_cleanup(struct net_device *dev) | 710 | static void vlan_dev_netpoll_cleanup(struct net_device *dev) |
697 | { | 711 | { |
698 | struct vlan_dev_priv *info = vlan_dev_priv(dev); | 712 | struct vlan_dev_priv *vlan= vlan_dev_priv(dev); |
699 | struct netpoll *netpoll = info->netpoll; | 713 | struct netpoll *netpoll = vlan->netpoll; |
700 | 714 | ||
701 | if (!netpoll) | 715 | if (!netpoll) |
702 | return; | 716 | return; |
703 | 717 | ||
704 | info->netpoll = NULL; | 718 | vlan->netpoll = NULL; |
705 | |||
706 | /* Wait for transmitting packets to finish before freeing. */ | ||
707 | synchronize_rcu_bh(); | ||
708 | 719 | ||
709 | __netpoll_cleanup(netpoll); | 720 | __netpoll_free_rcu(netpoll); |
710 | kfree(netpoll); | ||
711 | } | 721 | } |
712 | #endif /* CONFIG_NET_POLL_CONTROLLER */ | 722 | #endif /* CONFIG_NET_POLL_CONTROLLER */ |
713 | 723 | ||
diff --git a/net/Kconfig b/net/Kconfig index 245831bec09a..30b48f523135 100644 --- a/net/Kconfig +++ b/net/Kconfig | |||
@@ -52,6 +52,8 @@ source "net/iucv/Kconfig" | |||
52 | 52 | ||
53 | config INET | 53 | config INET |
54 | bool "TCP/IP networking" | 54 | bool "TCP/IP networking" |
55 | select CRYPTO | ||
56 | select CRYPTO_AES | ||
55 | ---help--- | 57 | ---help--- |
56 | These are the protocols used on the Internet and on most local | 58 | These are the protocols used on the Internet and on most local |
57 | Ethernets. It is highly recommended to say Y here (this will enlarge | 59 | Ethernets. It is highly recommended to say Y here (this will enlarge |
diff --git a/net/appletalk/atalk_proc.c b/net/appletalk/atalk_proc.c index b5b1a221c242..c30f3a0717fb 100644 --- a/net/appletalk/atalk_proc.c +++ b/net/appletalk/atalk_proc.c | |||
@@ -183,7 +183,8 @@ static int atalk_seq_socket_show(struct seq_file *seq, void *v) | |||
183 | ntohs(at->dest_net), at->dest_node, at->dest_port, | 183 | ntohs(at->dest_net), at->dest_node, at->dest_port, |
184 | sk_wmem_alloc_get(s), | 184 | sk_wmem_alloc_get(s), |
185 | sk_rmem_alloc_get(s), | 185 | sk_rmem_alloc_get(s), |
186 | s->sk_state, SOCK_INODE(s->sk_socket)->i_uid); | 186 | s->sk_state, |
187 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(s))); | ||
187 | out: | 188 | out: |
188 | return 0; | 189 | return 0; |
189 | } | 190 | } |
diff --git a/net/atm/common.c b/net/atm/common.c index b4b44dbed645..0c0ad930a632 100644 --- a/net/atm/common.c +++ b/net/atm/common.c | |||
@@ -812,6 +812,7 @@ int vcc_getsockopt(struct socket *sock, int level, int optname, | |||
812 | 812 | ||
813 | if (!vcc->dev || !test_bit(ATM_VF_ADDR, &vcc->flags)) | 813 | if (!vcc->dev || !test_bit(ATM_VF_ADDR, &vcc->flags)) |
814 | return -ENOTCONN; | 814 | return -ENOTCONN; |
815 | memset(&pvc, 0, sizeof(pvc)); | ||
815 | pvc.sap_family = AF_ATMPVC; | 816 | pvc.sap_family = AF_ATMPVC; |
816 | pvc.sap_addr.itf = vcc->dev->number; | 817 | pvc.sap_addr.itf = vcc->dev->number; |
817 | pvc.sap_addr.vpi = vcc->vpi; | 818 | pvc.sap_addr.vpi = vcc->vpi; |
diff --git a/net/atm/pvc.c b/net/atm/pvc.c index 3a734919c36c..ae0324021407 100644 --- a/net/atm/pvc.c +++ b/net/atm/pvc.c | |||
@@ -95,6 +95,7 @@ static int pvc_getname(struct socket *sock, struct sockaddr *sockaddr, | |||
95 | return -ENOTCONN; | 95 | return -ENOTCONN; |
96 | *sockaddr_len = sizeof(struct sockaddr_atmpvc); | 96 | *sockaddr_len = sizeof(struct sockaddr_atmpvc); |
97 | addr = (struct sockaddr_atmpvc *)sockaddr; | 97 | addr = (struct sockaddr_atmpvc *)sockaddr; |
98 | memset(addr, 0, sizeof(*addr)); | ||
98 | addr->sap_family = AF_ATMPVC; | 99 | addr->sap_family = AF_ATMPVC; |
99 | addr->sap_addr.itf = vcc->dev->number; | 100 | addr->sap_addr.itf = vcc->dev->number; |
100 | addr->sap_addr.vpi = vcc->vpi; | 101 | addr->sap_addr.vpi = vcc->vpi; |
diff --git a/net/atm/resources.c b/net/atm/resources.c index 23f45ce6f351..0447d5d0b639 100644 --- a/net/atm/resources.c +++ b/net/atm/resources.c | |||
@@ -432,7 +432,7 @@ int atm_dev_ioctl(unsigned int cmd, void __user *arg, int compat) | |||
432 | size = dev->ops->ioctl(dev, cmd, buf); | 432 | size = dev->ops->ioctl(dev, cmd, buf); |
433 | } | 433 | } |
434 | if (size < 0) { | 434 | if (size < 0) { |
435 | error = (size == -ENOIOCTLCMD ? -EINVAL : size); | 435 | error = (size == -ENOIOCTLCMD ? -ENOTTY : size); |
436 | goto done; | 436 | goto done; |
437 | } | 437 | } |
438 | } | 438 | } |
diff --git a/net/ax25/ax25_uid.c b/net/ax25/ax25_uid.c index e3c579ba6325..957999e43ff7 100644 --- a/net/ax25/ax25_uid.c +++ b/net/ax25/ax25_uid.c | |||
@@ -51,14 +51,14 @@ int ax25_uid_policy; | |||
51 | 51 | ||
52 | EXPORT_SYMBOL(ax25_uid_policy); | 52 | EXPORT_SYMBOL(ax25_uid_policy); |
53 | 53 | ||
54 | ax25_uid_assoc *ax25_findbyuid(uid_t uid) | 54 | ax25_uid_assoc *ax25_findbyuid(kuid_t uid) |
55 | { | 55 | { |
56 | ax25_uid_assoc *ax25_uid, *res = NULL; | 56 | ax25_uid_assoc *ax25_uid, *res = NULL; |
57 | struct hlist_node *node; | 57 | struct hlist_node *node; |
58 | 58 | ||
59 | read_lock(&ax25_uid_lock); | 59 | read_lock(&ax25_uid_lock); |
60 | ax25_uid_for_each(ax25_uid, node, &ax25_uid_list) { | 60 | ax25_uid_for_each(ax25_uid, node, &ax25_uid_list) { |
61 | if (ax25_uid->uid == uid) { | 61 | if (uid_eq(ax25_uid->uid, uid)) { |
62 | ax25_uid_hold(ax25_uid); | 62 | ax25_uid_hold(ax25_uid); |
63 | res = ax25_uid; | 63 | res = ax25_uid; |
64 | break; | 64 | break; |
@@ -84,7 +84,7 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax) | |||
84 | read_lock(&ax25_uid_lock); | 84 | read_lock(&ax25_uid_lock); |
85 | ax25_uid_for_each(ax25_uid, node, &ax25_uid_list) { | 85 | ax25_uid_for_each(ax25_uid, node, &ax25_uid_list) { |
86 | if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0) { | 86 | if (ax25cmp(&sax->sax25_call, &ax25_uid->call) == 0) { |
87 | res = ax25_uid->uid; | 87 | res = from_kuid_munged(current_user_ns(), ax25_uid->uid); |
88 | break; | 88 | break; |
89 | } | 89 | } |
90 | } | 90 | } |
@@ -93,9 +93,14 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax) | |||
93 | return res; | 93 | return res; |
94 | 94 | ||
95 | case SIOCAX25ADDUID: | 95 | case SIOCAX25ADDUID: |
96 | { | ||
97 | kuid_t sax25_kuid; | ||
96 | if (!capable(CAP_NET_ADMIN)) | 98 | if (!capable(CAP_NET_ADMIN)) |
97 | return -EPERM; | 99 | return -EPERM; |
98 | user = ax25_findbyuid(sax->sax25_uid); | 100 | sax25_kuid = make_kuid(current_user_ns(), sax->sax25_uid); |
101 | if (!uid_valid(sax25_kuid)) | ||
102 | return -EINVAL; | ||
103 | user = ax25_findbyuid(sax25_kuid); | ||
99 | if (user) { | 104 | if (user) { |
100 | ax25_uid_put(user); | 105 | ax25_uid_put(user); |
101 | return -EEXIST; | 106 | return -EEXIST; |
@@ -106,7 +111,7 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax) | |||
106 | return -ENOMEM; | 111 | return -ENOMEM; |
107 | 112 | ||
108 | atomic_set(&ax25_uid->refcount, 1); | 113 | atomic_set(&ax25_uid->refcount, 1); |
109 | ax25_uid->uid = sax->sax25_uid; | 114 | ax25_uid->uid = sax25_kuid; |
110 | ax25_uid->call = sax->sax25_call; | 115 | ax25_uid->call = sax->sax25_call; |
111 | 116 | ||
112 | write_lock(&ax25_uid_lock); | 117 | write_lock(&ax25_uid_lock); |
@@ -114,7 +119,7 @@ int ax25_uid_ioctl(int cmd, struct sockaddr_ax25 *sax) | |||
114 | write_unlock(&ax25_uid_lock); | 119 | write_unlock(&ax25_uid_lock); |
115 | 120 | ||
116 | return 0; | 121 | return 0; |
117 | 122 | } | |
118 | case SIOCAX25DELUID: | 123 | case SIOCAX25DELUID: |
119 | if (!capable(CAP_NET_ADMIN)) | 124 | if (!capable(CAP_NET_ADMIN)) |
120 | return -EPERM; | 125 | return -EPERM; |
@@ -172,7 +177,9 @@ static int ax25_uid_seq_show(struct seq_file *seq, void *v) | |||
172 | struct ax25_uid_assoc *pt; | 177 | struct ax25_uid_assoc *pt; |
173 | 178 | ||
174 | pt = hlist_entry(v, struct ax25_uid_assoc, uid_node); | 179 | pt = hlist_entry(v, struct ax25_uid_assoc, uid_node); |
175 | seq_printf(seq, "%6d %s\n", pt->uid, ax2asc(buf, &pt->call)); | 180 | seq_printf(seq, "%6d %s\n", |
181 | from_kuid_munged(seq_user_ns(seq), pt->uid), | ||
182 | ax2asc(buf, &pt->call)); | ||
176 | } | 183 | } |
177 | return 0; | 184 | return 0; |
178 | } | 185 | } |
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index e877af8bdd1e..df79300dcb7b 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c | |||
@@ -166,13 +166,15 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet, | |||
166 | int16_t buff_pos; | 166 | int16_t buff_pos; |
167 | struct batadv_ogm_packet *batadv_ogm_packet; | 167 | struct batadv_ogm_packet *batadv_ogm_packet; |
168 | struct sk_buff *skb; | 168 | struct sk_buff *skb; |
169 | uint8_t *packet_pos; | ||
169 | 170 | ||
170 | if (hard_iface->if_status != BATADV_IF_ACTIVE) | 171 | if (hard_iface->if_status != BATADV_IF_ACTIVE) |
171 | return; | 172 | return; |
172 | 173 | ||
173 | packet_num = 0; | 174 | packet_num = 0; |
174 | buff_pos = 0; | 175 | buff_pos = 0; |
175 | batadv_ogm_packet = (struct batadv_ogm_packet *)forw_packet->skb->data; | 176 | packet_pos = forw_packet->skb->data; |
177 | batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos; | ||
176 | 178 | ||
177 | /* adjust all flags and log packets */ | 179 | /* adjust all flags and log packets */ |
178 | while (batadv_iv_ogm_aggr_packet(buff_pos, forw_packet->packet_len, | 180 | while (batadv_iv_ogm_aggr_packet(buff_pos, forw_packet->packet_len, |
@@ -181,15 +183,17 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet, | |||
181 | /* we might have aggregated direct link packets with an | 183 | /* we might have aggregated direct link packets with an |
182 | * ordinary base packet | 184 | * ordinary base packet |
183 | */ | 185 | */ |
184 | if ((forw_packet->direct_link_flags & (1 << packet_num)) && | 186 | if (forw_packet->direct_link_flags & BIT(packet_num) && |
185 | (forw_packet->if_incoming == hard_iface)) | 187 | forw_packet->if_incoming == hard_iface) |
186 | batadv_ogm_packet->flags |= BATADV_DIRECTLINK; | 188 | batadv_ogm_packet->flags |= BATADV_DIRECTLINK; |
187 | else | 189 | else |
188 | batadv_ogm_packet->flags &= ~BATADV_DIRECTLINK; | 190 | batadv_ogm_packet->flags &= ~BATADV_DIRECTLINK; |
189 | 191 | ||
190 | fwd_str = (packet_num > 0 ? "Forwarding" : (forw_packet->own ? | 192 | if (packet_num > 0 || !forw_packet->own) |
191 | "Sending own" : | 193 | fwd_str = "Forwarding"; |
192 | "Forwarding")); | 194 | else |
195 | fwd_str = "Sending own"; | ||
196 | |||
193 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 197 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
194 | "%s %spacket (originator %pM, seqno %u, TQ %d, TTL %d, IDF %s, ttvn %d) on interface %s [%pM]\n", | 198 | "%s %spacket (originator %pM, seqno %u, TQ %d, TTL %d, IDF %s, ttvn %d) on interface %s [%pM]\n", |
195 | fwd_str, (packet_num > 0 ? "aggregated " : ""), | 199 | fwd_str, (packet_num > 0 ? "aggregated " : ""), |
@@ -204,8 +208,8 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet, | |||
204 | buff_pos += BATADV_OGM_HLEN; | 208 | buff_pos += BATADV_OGM_HLEN; |
205 | buff_pos += batadv_tt_len(batadv_ogm_packet->tt_num_changes); | 209 | buff_pos += batadv_tt_len(batadv_ogm_packet->tt_num_changes); |
206 | packet_num++; | 210 | packet_num++; |
207 | batadv_ogm_packet = (struct batadv_ogm_packet *) | 211 | packet_pos = forw_packet->skb->data + buff_pos; |
208 | (forw_packet->skb->data + buff_pos); | 212 | batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos; |
209 | } | 213 | } |
210 | 214 | ||
211 | /* create clone because function is called more than once */ | 215 | /* create clone because function is called more than once */ |
@@ -227,9 +231,10 @@ static void batadv_iv_ogm_emit(struct batadv_forw_packet *forw_packet) | |||
227 | struct batadv_hard_iface *primary_if = NULL; | 231 | struct batadv_hard_iface *primary_if = NULL; |
228 | struct batadv_ogm_packet *batadv_ogm_packet; | 232 | struct batadv_ogm_packet *batadv_ogm_packet; |
229 | unsigned char directlink; | 233 | unsigned char directlink; |
234 | uint8_t *packet_pos; | ||
230 | 235 | ||
231 | batadv_ogm_packet = (struct batadv_ogm_packet *) | 236 | packet_pos = forw_packet->skb->data; |
232 | (forw_packet->skb->data); | 237 | batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos; |
233 | directlink = (batadv_ogm_packet->flags & BATADV_DIRECTLINK ? 1 : 0); | 238 | directlink = (batadv_ogm_packet->flags & BATADV_DIRECTLINK ? 1 : 0); |
234 | 239 | ||
235 | if (!forw_packet->if_incoming) { | 240 | if (!forw_packet->if_incoming) { |
@@ -454,6 +459,7 @@ static void batadv_iv_ogm_aggregate(struct batadv_forw_packet *forw_packet_aggr, | |||
454 | int packet_len, bool direct_link) | 459 | int packet_len, bool direct_link) |
455 | { | 460 | { |
456 | unsigned char *skb_buff; | 461 | unsigned char *skb_buff; |
462 | unsigned long new_direct_link_flag; | ||
457 | 463 | ||
458 | skb_buff = skb_put(forw_packet_aggr->skb, packet_len); | 464 | skb_buff = skb_put(forw_packet_aggr->skb, packet_len); |
459 | memcpy(skb_buff, packet_buff, packet_len); | 465 | memcpy(skb_buff, packet_buff, packet_len); |
@@ -461,9 +467,10 @@ static void batadv_iv_ogm_aggregate(struct batadv_forw_packet *forw_packet_aggr, | |||
461 | forw_packet_aggr->num_packets++; | 467 | forw_packet_aggr->num_packets++; |
462 | 468 | ||
463 | /* save packet direct link flag status */ | 469 | /* save packet direct link flag status */ |
464 | if (direct_link) | 470 | if (direct_link) { |
465 | forw_packet_aggr->direct_link_flags |= | 471 | new_direct_link_flag = BIT(forw_packet_aggr->num_packets); |
466 | (1 << forw_packet_aggr->num_packets); | 472 | forw_packet_aggr->direct_link_flags |= new_direct_link_flag; |
473 | } | ||
467 | } | 474 | } |
468 | 475 | ||
469 | static void batadv_iv_ogm_queue_add(struct batadv_priv *bat_priv, | 476 | static void batadv_iv_ogm_queue_add(struct batadv_priv *bat_priv, |
@@ -586,6 +593,8 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) | |||
586 | struct batadv_ogm_packet *batadv_ogm_packet; | 593 | struct batadv_ogm_packet *batadv_ogm_packet; |
587 | struct batadv_hard_iface *primary_if; | 594 | struct batadv_hard_iface *primary_if; |
588 | int vis_server, tt_num_changes = 0; | 595 | int vis_server, tt_num_changes = 0; |
596 | uint32_t seqno; | ||
597 | uint8_t bandwidth; | ||
589 | 598 | ||
590 | vis_server = atomic_read(&bat_priv->vis_mode); | 599 | vis_server = atomic_read(&bat_priv->vis_mode); |
591 | primary_if = batadv_primary_if_get_selected(bat_priv); | 600 | primary_if = batadv_primary_if_get_selected(bat_priv); |
@@ -599,12 +608,12 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) | |||
599 | batadv_ogm_packet = (struct batadv_ogm_packet *)hard_iface->packet_buff; | 608 | batadv_ogm_packet = (struct batadv_ogm_packet *)hard_iface->packet_buff; |
600 | 609 | ||
601 | /* change sequence number to network order */ | 610 | /* change sequence number to network order */ |
602 | batadv_ogm_packet->seqno = | 611 | seqno = (uint32_t)atomic_read(&hard_iface->seqno); |
603 | htonl((uint32_t)atomic_read(&hard_iface->seqno)); | 612 | batadv_ogm_packet->seqno = htonl(seqno); |
604 | atomic_inc(&hard_iface->seqno); | 613 | atomic_inc(&hard_iface->seqno); |
605 | 614 | ||
606 | batadv_ogm_packet->ttvn = atomic_read(&bat_priv->ttvn); | 615 | batadv_ogm_packet->ttvn = atomic_read(&bat_priv->tt.vn); |
607 | batadv_ogm_packet->tt_crc = htons(bat_priv->tt_crc); | 616 | batadv_ogm_packet->tt_crc = htons(bat_priv->tt.local_crc); |
608 | if (tt_num_changes >= 0) | 617 | if (tt_num_changes >= 0) |
609 | batadv_ogm_packet->tt_num_changes = tt_num_changes; | 618 | batadv_ogm_packet->tt_num_changes = tt_num_changes; |
610 | 619 | ||
@@ -613,12 +622,13 @@ static void batadv_iv_ogm_schedule(struct batadv_hard_iface *hard_iface) | |||
613 | else | 622 | else |
614 | batadv_ogm_packet->flags &= ~BATADV_VIS_SERVER; | 623 | batadv_ogm_packet->flags &= ~BATADV_VIS_SERVER; |
615 | 624 | ||
616 | if ((hard_iface == primary_if) && | 625 | if (hard_iface == primary_if && |
617 | (atomic_read(&bat_priv->gw_mode) == BATADV_GW_MODE_SERVER)) | 626 | atomic_read(&bat_priv->gw_mode) == BATADV_GW_MODE_SERVER) { |
618 | batadv_ogm_packet->gw_flags = | 627 | bandwidth = (uint8_t)atomic_read(&bat_priv->gw_bandwidth); |
619 | (uint8_t)atomic_read(&bat_priv->gw_bandwidth); | 628 | batadv_ogm_packet->gw_flags = bandwidth; |
620 | else | 629 | } else { |
621 | batadv_ogm_packet->gw_flags = BATADV_NO_FLAGS; | 630 | batadv_ogm_packet->gw_flags = BATADV_NO_FLAGS; |
631 | } | ||
622 | 632 | ||
623 | batadv_slide_own_bcast_window(hard_iface); | 633 | batadv_slide_own_bcast_window(hard_iface); |
624 | batadv_iv_ogm_queue_add(bat_priv, hard_iface->packet_buff, | 634 | batadv_iv_ogm_queue_add(bat_priv, hard_iface->packet_buff, |
@@ -642,8 +652,9 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, | |||
642 | struct batadv_neigh_node *router = NULL; | 652 | struct batadv_neigh_node *router = NULL; |
643 | struct batadv_orig_node *orig_node_tmp; | 653 | struct batadv_orig_node *orig_node_tmp; |
644 | struct hlist_node *node; | 654 | struct hlist_node *node; |
645 | uint8_t bcast_own_sum_orig, bcast_own_sum_neigh; | 655 | uint8_t sum_orig, sum_neigh; |
646 | uint8_t *neigh_addr; | 656 | uint8_t *neigh_addr; |
657 | uint8_t tq_avg; | ||
647 | 658 | ||
648 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 659 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
649 | "update_originator(): Searching and updating originator entry of received packet\n"); | 660 | "update_originator(): Searching and updating originator entry of received packet\n"); |
@@ -667,8 +678,8 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, | |||
667 | spin_lock_bh(&tmp_neigh_node->lq_update_lock); | 678 | spin_lock_bh(&tmp_neigh_node->lq_update_lock); |
668 | batadv_ring_buffer_set(tmp_neigh_node->tq_recv, | 679 | batadv_ring_buffer_set(tmp_neigh_node->tq_recv, |
669 | &tmp_neigh_node->tq_index, 0); | 680 | &tmp_neigh_node->tq_index, 0); |
670 | tmp_neigh_node->tq_avg = | 681 | tq_avg = batadv_ring_buffer_avg(tmp_neigh_node->tq_recv); |
671 | batadv_ring_buffer_avg(tmp_neigh_node->tq_recv); | 682 | tmp_neigh_node->tq_avg = tq_avg; |
672 | spin_unlock_bh(&tmp_neigh_node->lq_update_lock); | 683 | spin_unlock_bh(&tmp_neigh_node->lq_update_lock); |
673 | } | 684 | } |
674 | 685 | ||
@@ -727,17 +738,15 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv, | |||
727 | if (router && (neigh_node->tq_avg == router->tq_avg)) { | 738 | if (router && (neigh_node->tq_avg == router->tq_avg)) { |
728 | orig_node_tmp = router->orig_node; | 739 | orig_node_tmp = router->orig_node; |
729 | spin_lock_bh(&orig_node_tmp->ogm_cnt_lock); | 740 | spin_lock_bh(&orig_node_tmp->ogm_cnt_lock); |
730 | bcast_own_sum_orig = | 741 | sum_orig = orig_node_tmp->bcast_own_sum[if_incoming->if_num]; |
731 | orig_node_tmp->bcast_own_sum[if_incoming->if_num]; | ||
732 | spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock); | 742 | spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock); |
733 | 743 | ||
734 | orig_node_tmp = neigh_node->orig_node; | 744 | orig_node_tmp = neigh_node->orig_node; |
735 | spin_lock_bh(&orig_node_tmp->ogm_cnt_lock); | 745 | spin_lock_bh(&orig_node_tmp->ogm_cnt_lock); |
736 | bcast_own_sum_neigh = | 746 | sum_neigh = orig_node_tmp->bcast_own_sum[if_incoming->if_num]; |
737 | orig_node_tmp->bcast_own_sum[if_incoming->if_num]; | ||
738 | spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock); | 747 | spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock); |
739 | 748 | ||
740 | if (bcast_own_sum_orig >= bcast_own_sum_neigh) | 749 | if (sum_orig >= sum_neigh) |
741 | goto update_tt; | 750 | goto update_tt; |
742 | } | 751 | } |
743 | 752 | ||
@@ -835,8 +844,10 @@ static int batadv_iv_ogm_calc_tq(struct batadv_orig_node *orig_node, | |||
835 | spin_unlock_bh(&orig_node->ogm_cnt_lock); | 844 | spin_unlock_bh(&orig_node->ogm_cnt_lock); |
836 | 845 | ||
837 | /* pay attention to not get a value bigger than 100 % */ | 846 | /* pay attention to not get a value bigger than 100 % */ |
838 | total_count = (orig_eq_count > neigh_rq_count ? | 847 | if (orig_eq_count > neigh_rq_count) |
839 | neigh_rq_count : orig_eq_count); | 848 | total_count = neigh_rq_count; |
849 | else | ||
850 | total_count = orig_eq_count; | ||
840 | 851 | ||
841 | /* if we have too few packets (too less data) we set tq_own to zero | 852 | /* if we have too few packets (too less data) we set tq_own to zero |
842 | * if we receive too few packets it is not considered bidirectional | 853 | * if we receive too few packets it is not considered bidirectional |
@@ -910,6 +921,7 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, | |||
910 | int set_mark, ret = -1; | 921 | int set_mark, ret = -1; |
911 | uint32_t seqno = ntohl(batadv_ogm_packet->seqno); | 922 | uint32_t seqno = ntohl(batadv_ogm_packet->seqno); |
912 | uint8_t *neigh_addr; | 923 | uint8_t *neigh_addr; |
924 | uint8_t packet_count; | ||
913 | 925 | ||
914 | orig_node = batadv_get_orig_node(bat_priv, batadv_ogm_packet->orig); | 926 | orig_node = batadv_get_orig_node(bat_priv, batadv_ogm_packet->orig); |
915 | if (!orig_node) | 927 | if (!orig_node) |
@@ -944,9 +956,9 @@ batadv_iv_ogm_update_seqnos(const struct ethhdr *ethhdr, | |||
944 | tmp_neigh_node->real_bits, | 956 | tmp_neigh_node->real_bits, |
945 | seq_diff, set_mark); | 957 | seq_diff, set_mark); |
946 | 958 | ||
947 | tmp_neigh_node->real_packet_count = | 959 | packet_count = bitmap_weight(tmp_neigh_node->real_bits, |
948 | bitmap_weight(tmp_neigh_node->real_bits, | 960 | BATADV_TQ_LOCAL_WINDOW_SIZE); |
949 | BATADV_TQ_LOCAL_WINDOW_SIZE); | 961 | tmp_neigh_node->real_packet_count = packet_count; |
950 | } | 962 | } |
951 | rcu_read_unlock(); | 963 | rcu_read_unlock(); |
952 | 964 | ||
@@ -1163,9 +1175,12 @@ static void batadv_iv_ogm_process(const struct ethhdr *ethhdr, | |||
1163 | /* if sender is a direct neighbor the sender mac equals | 1175 | /* if sender is a direct neighbor the sender mac equals |
1164 | * originator mac | 1176 | * originator mac |
1165 | */ | 1177 | */ |
1166 | orig_neigh_node = (is_single_hop_neigh ? | 1178 | if (is_single_hop_neigh) |
1167 | orig_node : | 1179 | orig_neigh_node = orig_node; |
1168 | batadv_get_orig_node(bat_priv, ethhdr->h_source)); | 1180 | else |
1181 | orig_neigh_node = batadv_get_orig_node(bat_priv, | ||
1182 | ethhdr->h_source); | ||
1183 | |||
1169 | if (!orig_neigh_node) | 1184 | if (!orig_neigh_node) |
1170 | goto out; | 1185 | goto out; |
1171 | 1186 | ||
@@ -1251,6 +1266,7 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb, | |||
1251 | int buff_pos = 0, packet_len; | 1266 | int buff_pos = 0, packet_len; |
1252 | unsigned char *tt_buff, *packet_buff; | 1267 | unsigned char *tt_buff, *packet_buff; |
1253 | bool ret; | 1268 | bool ret; |
1269 | uint8_t *packet_pos; | ||
1254 | 1270 | ||
1255 | ret = batadv_check_management_packet(skb, if_incoming, BATADV_OGM_HLEN); | 1271 | ret = batadv_check_management_packet(skb, if_incoming, BATADV_OGM_HLEN); |
1256 | if (!ret) | 1272 | if (!ret) |
@@ -1281,8 +1297,8 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb, | |||
1281 | buff_pos += BATADV_OGM_HLEN; | 1297 | buff_pos += BATADV_OGM_HLEN; |
1282 | buff_pos += batadv_tt_len(batadv_ogm_packet->tt_num_changes); | 1298 | buff_pos += batadv_tt_len(batadv_ogm_packet->tt_num_changes); |
1283 | 1299 | ||
1284 | batadv_ogm_packet = (struct batadv_ogm_packet *) | 1300 | packet_pos = packet_buff + buff_pos; |
1285 | (packet_buff + buff_pos); | 1301 | batadv_ogm_packet = (struct batadv_ogm_packet *)packet_pos; |
1286 | } while (batadv_iv_ogm_aggr_packet(buff_pos, packet_len, | 1302 | } while (batadv_iv_ogm_aggr_packet(buff_pos, packet_len, |
1287 | batadv_ogm_packet->tt_num_changes)); | 1303 | batadv_ogm_packet->tt_num_changes)); |
1288 | 1304 | ||
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index 6705d35b17ce..0a9084ad19a6 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c | |||
@@ -133,7 +133,7 @@ static void batadv_claim_free_ref(struct batadv_claim *claim) | |||
133 | static struct batadv_claim *batadv_claim_hash_find(struct batadv_priv *bat_priv, | 133 | static struct batadv_claim *batadv_claim_hash_find(struct batadv_priv *bat_priv, |
134 | struct batadv_claim *data) | 134 | struct batadv_claim *data) |
135 | { | 135 | { |
136 | struct batadv_hashtable *hash = bat_priv->claim_hash; | 136 | struct batadv_hashtable *hash = bat_priv->bla.claim_hash; |
137 | struct hlist_head *head; | 137 | struct hlist_head *head; |
138 | struct hlist_node *node; | 138 | struct hlist_node *node; |
139 | struct batadv_claim *claim; | 139 | struct batadv_claim *claim; |
@@ -174,7 +174,7 @@ static struct batadv_backbone_gw * | |||
174 | batadv_backbone_hash_find(struct batadv_priv *bat_priv, | 174 | batadv_backbone_hash_find(struct batadv_priv *bat_priv, |
175 | uint8_t *addr, short vid) | 175 | uint8_t *addr, short vid) |
176 | { | 176 | { |
177 | struct batadv_hashtable *hash = bat_priv->backbone_hash; | 177 | struct batadv_hashtable *hash = bat_priv->bla.backbone_hash; |
178 | struct hlist_head *head; | 178 | struct hlist_head *head; |
179 | struct hlist_node *node; | 179 | struct hlist_node *node; |
180 | struct batadv_backbone_gw search_entry, *backbone_gw; | 180 | struct batadv_backbone_gw search_entry, *backbone_gw; |
@@ -218,7 +218,7 @@ batadv_bla_del_backbone_claims(struct batadv_backbone_gw *backbone_gw) | |||
218 | int i; | 218 | int i; |
219 | spinlock_t *list_lock; /* protects write access to the hash lists */ | 219 | spinlock_t *list_lock; /* protects write access to the hash lists */ |
220 | 220 | ||
221 | hash = backbone_gw->bat_priv->claim_hash; | 221 | hash = backbone_gw->bat_priv->bla.claim_hash; |
222 | if (!hash) | 222 | if (!hash) |
223 | return; | 223 | return; |
224 | 224 | ||
@@ -265,7 +265,7 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac, | |||
265 | if (!primary_if) | 265 | if (!primary_if) |
266 | return; | 266 | return; |
267 | 267 | ||
268 | memcpy(&local_claim_dest, &bat_priv->claim_dest, | 268 | memcpy(&local_claim_dest, &bat_priv->bla.claim_dest, |
269 | sizeof(local_claim_dest)); | 269 | sizeof(local_claim_dest)); |
270 | local_claim_dest.type = claimtype; | 270 | local_claim_dest.type = claimtype; |
271 | 271 | ||
@@ -281,7 +281,7 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac, | |||
281 | NULL, | 281 | NULL, |
282 | /* Ethernet SRC/HW SRC: originator mac */ | 282 | /* Ethernet SRC/HW SRC: originator mac */ |
283 | primary_if->net_dev->dev_addr, | 283 | primary_if->net_dev->dev_addr, |
284 | /* HW DST: FF:43:05:XX:00:00 | 284 | /* HW DST: FF:43:05:XX:YY:YY |
285 | * with XX = claim type | 285 | * with XX = claim type |
286 | * and YY:YY = group id | 286 | * and YY:YY = group id |
287 | */ | 287 | */ |
@@ -295,7 +295,7 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac, | |||
295 | 295 | ||
296 | /* now we pretend that the client would have sent this ... */ | 296 | /* now we pretend that the client would have sent this ... */ |
297 | switch (claimtype) { | 297 | switch (claimtype) { |
298 | case BATADV_CLAIM_TYPE_ADD: | 298 | case BATADV_CLAIM_TYPE_CLAIM: |
299 | /* normal claim frame | 299 | /* normal claim frame |
300 | * set Ethernet SRC to the clients mac | 300 | * set Ethernet SRC to the clients mac |
301 | */ | 301 | */ |
@@ -303,7 +303,7 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac, | |||
303 | batadv_dbg(BATADV_DBG_BLA, bat_priv, | 303 | batadv_dbg(BATADV_DBG_BLA, bat_priv, |
304 | "bla_send_claim(): CLAIM %pM on vid %d\n", mac, vid); | 304 | "bla_send_claim(): CLAIM %pM on vid %d\n", mac, vid); |
305 | break; | 305 | break; |
306 | case BATADV_CLAIM_TYPE_DEL: | 306 | case BATADV_CLAIM_TYPE_UNCLAIM: |
307 | /* unclaim frame | 307 | /* unclaim frame |
308 | * set HW SRC to the clients mac | 308 | * set HW SRC to the clients mac |
309 | */ | 309 | */ |
@@ -323,7 +323,8 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac, | |||
323 | break; | 323 | break; |
324 | case BATADV_CLAIM_TYPE_REQUEST: | 324 | case BATADV_CLAIM_TYPE_REQUEST: |
325 | /* request frame | 325 | /* request frame |
326 | * set HW SRC to the special mac containg the crc | 326 | * set HW SRC and header destination to the receiving backbone |
327 | * gws mac | ||
327 | */ | 328 | */ |
328 | memcpy(hw_src, mac, ETH_ALEN); | 329 | memcpy(hw_src, mac, ETH_ALEN); |
329 | memcpy(ethhdr->h_dest, mac, ETH_ALEN); | 330 | memcpy(ethhdr->h_dest, mac, ETH_ALEN); |
@@ -339,8 +340,9 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac, | |||
339 | 340 | ||
340 | skb_reset_mac_header(skb); | 341 | skb_reset_mac_header(skb); |
341 | skb->protocol = eth_type_trans(skb, soft_iface); | 342 | skb->protocol = eth_type_trans(skb, soft_iface); |
342 | bat_priv->stats.rx_packets++; | 343 | batadv_inc_counter(bat_priv, BATADV_CNT_RX); |
343 | bat_priv->stats.rx_bytes += skb->len + ETH_HLEN; | 344 | batadv_add_counter(bat_priv, BATADV_CNT_RX_BYTES, |
345 | skb->len + ETH_HLEN); | ||
344 | soft_iface->last_rx = jiffies; | 346 | soft_iface->last_rx = jiffies; |
345 | 347 | ||
346 | netif_rx(skb); | 348 | netif_rx(skb); |
@@ -389,7 +391,7 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig, | |||
389 | /* one for the hash, one for returning */ | 391 | /* one for the hash, one for returning */ |
390 | atomic_set(&entry->refcount, 2); | 392 | atomic_set(&entry->refcount, 2); |
391 | 393 | ||
392 | hash_added = batadv_hash_add(bat_priv->backbone_hash, | 394 | hash_added = batadv_hash_add(bat_priv->bla.backbone_hash, |
393 | batadv_compare_backbone_gw, | 395 | batadv_compare_backbone_gw, |
394 | batadv_choose_backbone_gw, entry, | 396 | batadv_choose_backbone_gw, entry, |
395 | &entry->hash_entry); | 397 | &entry->hash_entry); |
@@ -456,7 +458,7 @@ static void batadv_bla_answer_request(struct batadv_priv *bat_priv, | |||
456 | if (!backbone_gw) | 458 | if (!backbone_gw) |
457 | return; | 459 | return; |
458 | 460 | ||
459 | hash = bat_priv->claim_hash; | 461 | hash = bat_priv->bla.claim_hash; |
460 | for (i = 0; i < hash->size; i++) { | 462 | for (i = 0; i < hash->size; i++) { |
461 | head = &hash->table[i]; | 463 | head = &hash->table[i]; |
462 | 464 | ||
@@ -467,7 +469,7 @@ static void batadv_bla_answer_request(struct batadv_priv *bat_priv, | |||
467 | continue; | 469 | continue; |
468 | 470 | ||
469 | batadv_bla_send_claim(bat_priv, claim->addr, claim->vid, | 471 | batadv_bla_send_claim(bat_priv, claim->addr, claim->vid, |
470 | BATADV_CLAIM_TYPE_ADD); | 472 | BATADV_CLAIM_TYPE_CLAIM); |
471 | } | 473 | } |
472 | rcu_read_unlock(); | 474 | rcu_read_unlock(); |
473 | } | 475 | } |
@@ -497,7 +499,7 @@ static void batadv_bla_send_request(struct batadv_backbone_gw *backbone_gw) | |||
497 | 499 | ||
498 | /* no local broadcasts should be sent or received, for now. */ | 500 | /* no local broadcasts should be sent or received, for now. */ |
499 | if (!atomic_read(&backbone_gw->request_sent)) { | 501 | if (!atomic_read(&backbone_gw->request_sent)) { |
500 | atomic_inc(&backbone_gw->bat_priv->bla_num_requests); | 502 | atomic_inc(&backbone_gw->bat_priv->bla.num_requests); |
501 | atomic_set(&backbone_gw->request_sent, 1); | 503 | atomic_set(&backbone_gw->request_sent, 1); |
502 | } | 504 | } |
503 | } | 505 | } |
@@ -557,7 +559,7 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv, | |||
557 | batadv_dbg(BATADV_DBG_BLA, bat_priv, | 559 | batadv_dbg(BATADV_DBG_BLA, bat_priv, |
558 | "bla_add_claim(): adding new entry %pM, vid %d to hash ...\n", | 560 | "bla_add_claim(): adding new entry %pM, vid %d to hash ...\n", |
559 | mac, vid); | 561 | mac, vid); |
560 | hash_added = batadv_hash_add(bat_priv->claim_hash, | 562 | hash_added = batadv_hash_add(bat_priv->bla.claim_hash, |
561 | batadv_compare_claim, | 563 | batadv_compare_claim, |
562 | batadv_choose_claim, claim, | 564 | batadv_choose_claim, claim, |
563 | &claim->hash_entry); | 565 | &claim->hash_entry); |
@@ -577,8 +579,7 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv, | |||
577 | "bla_add_claim(): changing ownership for %pM, vid %d\n", | 579 | "bla_add_claim(): changing ownership for %pM, vid %d\n", |
578 | mac, vid); | 580 | mac, vid); |
579 | 581 | ||
580 | claim->backbone_gw->crc ^= | 582 | claim->backbone_gw->crc ^= crc16(0, claim->addr, ETH_ALEN); |
581 | crc16(0, claim->addr, ETH_ALEN); | ||
582 | batadv_backbone_gw_free_ref(claim->backbone_gw); | 583 | batadv_backbone_gw_free_ref(claim->backbone_gw); |
583 | 584 | ||
584 | } | 585 | } |
@@ -610,7 +611,7 @@ static void batadv_bla_del_claim(struct batadv_priv *bat_priv, | |||
610 | batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_del_claim(): %pM, vid %d\n", | 611 | batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla_del_claim(): %pM, vid %d\n", |
611 | mac, vid); | 612 | mac, vid); |
612 | 613 | ||
613 | batadv_hash_remove(bat_priv->claim_hash, batadv_compare_claim, | 614 | batadv_hash_remove(bat_priv->bla.claim_hash, batadv_compare_claim, |
614 | batadv_choose_claim, claim); | 615 | batadv_choose_claim, claim); |
615 | batadv_claim_free_ref(claim); /* reference from the hash is gone */ | 616 | batadv_claim_free_ref(claim); /* reference from the hash is gone */ |
616 | 617 | ||
@@ -657,7 +658,7 @@ static int batadv_handle_announce(struct batadv_priv *bat_priv, | |||
657 | * we can allow traffic again. | 658 | * we can allow traffic again. |
658 | */ | 659 | */ |
659 | if (atomic_read(&backbone_gw->request_sent)) { | 660 | if (atomic_read(&backbone_gw->request_sent)) { |
660 | atomic_dec(&backbone_gw->bat_priv->bla_num_requests); | 661 | atomic_dec(&backbone_gw->bat_priv->bla.num_requests); |
661 | atomic_set(&backbone_gw->request_sent, 0); | 662 | atomic_set(&backbone_gw->request_sent, 0); |
662 | } | 663 | } |
663 | } | 664 | } |
@@ -702,7 +703,7 @@ static int batadv_handle_unclaim(struct batadv_priv *bat_priv, | |||
702 | if (primary_if && batadv_compare_eth(backbone_addr, | 703 | if (primary_if && batadv_compare_eth(backbone_addr, |
703 | primary_if->net_dev->dev_addr)) | 704 | primary_if->net_dev->dev_addr)) |
704 | batadv_bla_send_claim(bat_priv, claim_addr, vid, | 705 | batadv_bla_send_claim(bat_priv, claim_addr, vid, |
705 | BATADV_CLAIM_TYPE_DEL); | 706 | BATADV_CLAIM_TYPE_UNCLAIM); |
706 | 707 | ||
707 | backbone_gw = batadv_backbone_hash_find(bat_priv, backbone_addr, vid); | 708 | backbone_gw = batadv_backbone_hash_find(bat_priv, backbone_addr, vid); |
708 | 709 | ||
@@ -738,7 +739,7 @@ static int batadv_handle_claim(struct batadv_priv *bat_priv, | |||
738 | batadv_bla_add_claim(bat_priv, claim_addr, vid, backbone_gw); | 739 | batadv_bla_add_claim(bat_priv, claim_addr, vid, backbone_gw); |
739 | if (batadv_compare_eth(backbone_addr, primary_if->net_dev->dev_addr)) | 740 | if (batadv_compare_eth(backbone_addr, primary_if->net_dev->dev_addr)) |
740 | batadv_bla_send_claim(bat_priv, claim_addr, vid, | 741 | batadv_bla_send_claim(bat_priv, claim_addr, vid, |
741 | BATADV_CLAIM_TYPE_ADD); | 742 | BATADV_CLAIM_TYPE_CLAIM); |
742 | 743 | ||
743 | /* TODO: we could call something like tt_local_del() here. */ | 744 | /* TODO: we could call something like tt_local_del() here. */ |
744 | 745 | ||
@@ -772,7 +773,7 @@ static int batadv_check_claim_group(struct batadv_priv *bat_priv, | |||
772 | struct batadv_bla_claim_dst *bla_dst, *bla_dst_own; | 773 | struct batadv_bla_claim_dst *bla_dst, *bla_dst_own; |
773 | 774 | ||
774 | bla_dst = (struct batadv_bla_claim_dst *)hw_dst; | 775 | bla_dst = (struct batadv_bla_claim_dst *)hw_dst; |
775 | bla_dst_own = &bat_priv->claim_dest; | 776 | bla_dst_own = &bat_priv->bla.claim_dest; |
776 | 777 | ||
777 | /* check if it is a claim packet in general */ | 778 | /* check if it is a claim packet in general */ |
778 | if (memcmp(bla_dst->magic, bla_dst_own->magic, | 779 | if (memcmp(bla_dst->magic, bla_dst_own->magic, |
@@ -783,12 +784,12 @@ static int batadv_check_claim_group(struct batadv_priv *bat_priv, | |||
783 | * otherwise assume it is in the hw_src | 784 | * otherwise assume it is in the hw_src |
784 | */ | 785 | */ |
785 | switch (bla_dst->type) { | 786 | switch (bla_dst->type) { |
786 | case BATADV_CLAIM_TYPE_ADD: | 787 | case BATADV_CLAIM_TYPE_CLAIM: |
787 | backbone_addr = hw_src; | 788 | backbone_addr = hw_src; |
788 | break; | 789 | break; |
789 | case BATADV_CLAIM_TYPE_REQUEST: | 790 | case BATADV_CLAIM_TYPE_REQUEST: |
790 | case BATADV_CLAIM_TYPE_ANNOUNCE: | 791 | case BATADV_CLAIM_TYPE_ANNOUNCE: |
791 | case BATADV_CLAIM_TYPE_DEL: | 792 | case BATADV_CLAIM_TYPE_UNCLAIM: |
792 | backbone_addr = ethhdr->h_source; | 793 | backbone_addr = ethhdr->h_source; |
793 | break; | 794 | break; |
794 | default: | 795 | default: |
@@ -904,12 +905,12 @@ static int batadv_bla_process_claim(struct batadv_priv *bat_priv, | |||
904 | 905 | ||
905 | /* check for the different types of claim frames ... */ | 906 | /* check for the different types of claim frames ... */ |
906 | switch (bla_dst->type) { | 907 | switch (bla_dst->type) { |
907 | case BATADV_CLAIM_TYPE_ADD: | 908 | case BATADV_CLAIM_TYPE_CLAIM: |
908 | if (batadv_handle_claim(bat_priv, primary_if, hw_src, | 909 | if (batadv_handle_claim(bat_priv, primary_if, hw_src, |
909 | ethhdr->h_source, vid)) | 910 | ethhdr->h_source, vid)) |
910 | return 1; | 911 | return 1; |
911 | break; | 912 | break; |
912 | case BATADV_CLAIM_TYPE_DEL: | 913 | case BATADV_CLAIM_TYPE_UNCLAIM: |
913 | if (batadv_handle_unclaim(bat_priv, primary_if, | 914 | if (batadv_handle_unclaim(bat_priv, primary_if, |
914 | ethhdr->h_source, hw_src, vid)) | 915 | ethhdr->h_source, hw_src, vid)) |
915 | return 1; | 916 | return 1; |
@@ -945,7 +946,7 @@ static void batadv_bla_purge_backbone_gw(struct batadv_priv *bat_priv, int now) | |||
945 | spinlock_t *list_lock; /* protects write access to the hash lists */ | 946 | spinlock_t *list_lock; /* protects write access to the hash lists */ |
946 | int i; | 947 | int i; |
947 | 948 | ||
948 | hash = bat_priv->backbone_hash; | 949 | hash = bat_priv->bla.backbone_hash; |
949 | if (!hash) | 950 | if (!hash) |
950 | return; | 951 | return; |
951 | 952 | ||
@@ -969,7 +970,7 @@ static void batadv_bla_purge_backbone_gw(struct batadv_priv *bat_priv, int now) | |||
969 | purge_now: | 970 | purge_now: |
970 | /* don't wait for the pending request anymore */ | 971 | /* don't wait for the pending request anymore */ |
971 | if (atomic_read(&backbone_gw->request_sent)) | 972 | if (atomic_read(&backbone_gw->request_sent)) |
972 | atomic_dec(&bat_priv->bla_num_requests); | 973 | atomic_dec(&bat_priv->bla.num_requests); |
973 | 974 | ||
974 | batadv_bla_del_backbone_claims(backbone_gw); | 975 | batadv_bla_del_backbone_claims(backbone_gw); |
975 | 976 | ||
@@ -999,7 +1000,7 @@ static void batadv_bla_purge_claims(struct batadv_priv *bat_priv, | |||
999 | struct batadv_hashtable *hash; | 1000 | struct batadv_hashtable *hash; |
1000 | int i; | 1001 | int i; |
1001 | 1002 | ||
1002 | hash = bat_priv->claim_hash; | 1003 | hash = bat_priv->bla.claim_hash; |
1003 | if (!hash) | 1004 | if (!hash) |
1004 | return; | 1005 | return; |
1005 | 1006 | ||
@@ -1046,11 +1047,12 @@ void batadv_bla_update_orig_address(struct batadv_priv *bat_priv, | |||
1046 | struct hlist_node *node; | 1047 | struct hlist_node *node; |
1047 | struct hlist_head *head; | 1048 | struct hlist_head *head; |
1048 | struct batadv_hashtable *hash; | 1049 | struct batadv_hashtable *hash; |
1050 | __be16 group; | ||
1049 | int i; | 1051 | int i; |
1050 | 1052 | ||
1051 | /* reset bridge loop avoidance group id */ | 1053 | /* reset bridge loop avoidance group id */ |
1052 | bat_priv->claim_dest.group = | 1054 | group = htons(crc16(0, primary_if->net_dev->dev_addr, ETH_ALEN)); |
1053 | htons(crc16(0, primary_if->net_dev->dev_addr, ETH_ALEN)); | 1055 | bat_priv->bla.claim_dest.group = group; |
1054 | 1056 | ||
1055 | if (!oldif) { | 1057 | if (!oldif) { |
1056 | batadv_bla_purge_claims(bat_priv, NULL, 1); | 1058 | batadv_bla_purge_claims(bat_priv, NULL, 1); |
@@ -1058,7 +1060,7 @@ void batadv_bla_update_orig_address(struct batadv_priv *bat_priv, | |||
1058 | return; | 1060 | return; |
1059 | } | 1061 | } |
1060 | 1062 | ||
1061 | hash = bat_priv->backbone_hash; | 1063 | hash = bat_priv->bla.backbone_hash; |
1062 | if (!hash) | 1064 | if (!hash) |
1063 | return; | 1065 | return; |
1064 | 1066 | ||
@@ -1088,8 +1090,8 @@ void batadv_bla_update_orig_address(struct batadv_priv *bat_priv, | |||
1088 | /* (re)start the timer */ | 1090 | /* (re)start the timer */ |
1089 | static void batadv_bla_start_timer(struct batadv_priv *bat_priv) | 1091 | static void batadv_bla_start_timer(struct batadv_priv *bat_priv) |
1090 | { | 1092 | { |
1091 | INIT_DELAYED_WORK(&bat_priv->bla_work, batadv_bla_periodic_work); | 1093 | INIT_DELAYED_WORK(&bat_priv->bla.work, batadv_bla_periodic_work); |
1092 | queue_delayed_work(batadv_event_workqueue, &bat_priv->bla_work, | 1094 | queue_delayed_work(batadv_event_workqueue, &bat_priv->bla.work, |
1093 | msecs_to_jiffies(BATADV_BLA_PERIOD_LENGTH)); | 1095 | msecs_to_jiffies(BATADV_BLA_PERIOD_LENGTH)); |
1094 | } | 1096 | } |
1095 | 1097 | ||
@@ -1099,9 +1101,9 @@ static void batadv_bla_start_timer(struct batadv_priv *bat_priv) | |||
1099 | */ | 1101 | */ |
1100 | static void batadv_bla_periodic_work(struct work_struct *work) | 1102 | static void batadv_bla_periodic_work(struct work_struct *work) |
1101 | { | 1103 | { |
1102 | struct delayed_work *delayed_work = | 1104 | struct delayed_work *delayed_work; |
1103 | container_of(work, struct delayed_work, work); | ||
1104 | struct batadv_priv *bat_priv; | 1105 | struct batadv_priv *bat_priv; |
1106 | struct batadv_priv_bla *priv_bla; | ||
1105 | struct hlist_node *node; | 1107 | struct hlist_node *node; |
1106 | struct hlist_head *head; | 1108 | struct hlist_head *head; |
1107 | struct batadv_backbone_gw *backbone_gw; | 1109 | struct batadv_backbone_gw *backbone_gw; |
@@ -1109,7 +1111,9 @@ static void batadv_bla_periodic_work(struct work_struct *work) | |||
1109 | struct batadv_hard_iface *primary_if; | 1111 | struct batadv_hard_iface *primary_if; |
1110 | int i; | 1112 | int i; |
1111 | 1113 | ||
1112 | bat_priv = container_of(delayed_work, struct batadv_priv, bla_work); | 1114 | delayed_work = container_of(work, struct delayed_work, work); |
1115 | priv_bla = container_of(delayed_work, struct batadv_priv_bla, work); | ||
1116 | bat_priv = container_of(priv_bla, struct batadv_priv, bla); | ||
1113 | primary_if = batadv_primary_if_get_selected(bat_priv); | 1117 | primary_if = batadv_primary_if_get_selected(bat_priv); |
1114 | if (!primary_if) | 1118 | if (!primary_if) |
1115 | goto out; | 1119 | goto out; |
@@ -1120,7 +1124,7 @@ static void batadv_bla_periodic_work(struct work_struct *work) | |||
1120 | if (!atomic_read(&bat_priv->bridge_loop_avoidance)) | 1124 | if (!atomic_read(&bat_priv->bridge_loop_avoidance)) |
1121 | goto out; | 1125 | goto out; |
1122 | 1126 | ||
1123 | hash = bat_priv->backbone_hash; | 1127 | hash = bat_priv->bla.backbone_hash; |
1124 | if (!hash) | 1128 | if (!hash) |
1125 | goto out; | 1129 | goto out; |
1126 | 1130 | ||
@@ -1160,40 +1164,41 @@ int batadv_bla_init(struct batadv_priv *bat_priv) | |||
1160 | int i; | 1164 | int i; |
1161 | uint8_t claim_dest[ETH_ALEN] = {0xff, 0x43, 0x05, 0x00, 0x00, 0x00}; | 1165 | uint8_t claim_dest[ETH_ALEN] = {0xff, 0x43, 0x05, 0x00, 0x00, 0x00}; |
1162 | struct batadv_hard_iface *primary_if; | 1166 | struct batadv_hard_iface *primary_if; |
1167 | uint16_t crc; | ||
1168 | unsigned long entrytime; | ||
1163 | 1169 | ||
1164 | batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hash registering\n"); | 1170 | batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hash registering\n"); |
1165 | 1171 | ||
1166 | /* setting claim destination address */ | 1172 | /* setting claim destination address */ |
1167 | memcpy(&bat_priv->claim_dest.magic, claim_dest, 3); | 1173 | memcpy(&bat_priv->bla.claim_dest.magic, claim_dest, 3); |
1168 | bat_priv->claim_dest.type = 0; | 1174 | bat_priv->bla.claim_dest.type = 0; |
1169 | primary_if = batadv_primary_if_get_selected(bat_priv); | 1175 | primary_if = batadv_primary_if_get_selected(bat_priv); |
1170 | if (primary_if) { | 1176 | if (primary_if) { |
1171 | bat_priv->claim_dest.group = | 1177 | crc = crc16(0, primary_if->net_dev->dev_addr, ETH_ALEN); |
1172 | htons(crc16(0, primary_if->net_dev->dev_addr, | 1178 | bat_priv->bla.claim_dest.group = htons(crc); |
1173 | ETH_ALEN)); | ||
1174 | batadv_hardif_free_ref(primary_if); | 1179 | batadv_hardif_free_ref(primary_if); |
1175 | } else { | 1180 | } else { |
1176 | bat_priv->claim_dest.group = 0; /* will be set later */ | 1181 | bat_priv->bla.claim_dest.group = 0; /* will be set later */ |
1177 | } | 1182 | } |
1178 | 1183 | ||
1179 | /* initialize the duplicate list */ | 1184 | /* initialize the duplicate list */ |
1185 | entrytime = jiffies - msecs_to_jiffies(BATADV_DUPLIST_TIMEOUT); | ||
1180 | for (i = 0; i < BATADV_DUPLIST_SIZE; i++) | 1186 | for (i = 0; i < BATADV_DUPLIST_SIZE; i++) |
1181 | bat_priv->bcast_duplist[i].entrytime = | 1187 | bat_priv->bla.bcast_duplist[i].entrytime = entrytime; |
1182 | jiffies - msecs_to_jiffies(BATADV_DUPLIST_TIMEOUT); | 1188 | bat_priv->bla.bcast_duplist_curr = 0; |
1183 | bat_priv->bcast_duplist_curr = 0; | ||
1184 | 1189 | ||
1185 | if (bat_priv->claim_hash) | 1190 | if (bat_priv->bla.claim_hash) |
1186 | return 0; | 1191 | return 0; |
1187 | 1192 | ||
1188 | bat_priv->claim_hash = batadv_hash_new(128); | 1193 | bat_priv->bla.claim_hash = batadv_hash_new(128); |
1189 | bat_priv->backbone_hash = batadv_hash_new(32); | 1194 | bat_priv->bla.backbone_hash = batadv_hash_new(32); |
1190 | 1195 | ||
1191 | if (!bat_priv->claim_hash || !bat_priv->backbone_hash) | 1196 | if (!bat_priv->bla.claim_hash || !bat_priv->bla.backbone_hash) |
1192 | return -ENOMEM; | 1197 | return -ENOMEM; |
1193 | 1198 | ||
1194 | batadv_hash_set_lock_class(bat_priv->claim_hash, | 1199 | batadv_hash_set_lock_class(bat_priv->bla.claim_hash, |
1195 | &batadv_claim_hash_lock_class_key); | 1200 | &batadv_claim_hash_lock_class_key); |
1196 | batadv_hash_set_lock_class(bat_priv->backbone_hash, | 1201 | batadv_hash_set_lock_class(bat_priv->bla.backbone_hash, |
1197 | &batadv_backbone_hash_lock_class_key); | 1202 | &batadv_backbone_hash_lock_class_key); |
1198 | 1203 | ||
1199 | batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hashes initialized\n"); | 1204 | batadv_dbg(BATADV_DBG_BLA, bat_priv, "bla hashes initialized\n"); |
@@ -1234,8 +1239,9 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, | |||
1234 | crc = crc16(0, content, length); | 1239 | crc = crc16(0, content, length); |
1235 | 1240 | ||
1236 | for (i = 0; i < BATADV_DUPLIST_SIZE; i++) { | 1241 | for (i = 0; i < BATADV_DUPLIST_SIZE; i++) { |
1237 | curr = (bat_priv->bcast_duplist_curr + i) % BATADV_DUPLIST_SIZE; | 1242 | curr = (bat_priv->bla.bcast_duplist_curr + i); |
1238 | entry = &bat_priv->bcast_duplist[curr]; | 1243 | curr %= BATADV_DUPLIST_SIZE; |
1244 | entry = &bat_priv->bla.bcast_duplist[curr]; | ||
1239 | 1245 | ||
1240 | /* we can stop searching if the entry is too old ; | 1246 | /* we can stop searching if the entry is too old ; |
1241 | * later entries will be even older | 1247 | * later entries will be even older |
@@ -1256,13 +1262,13 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, | |||
1256 | return 1; | 1262 | return 1; |
1257 | } | 1263 | } |
1258 | /* not found, add a new entry (overwrite the oldest entry) */ | 1264 | /* not found, add a new entry (overwrite the oldest entry) */ |
1259 | curr = (bat_priv->bcast_duplist_curr + BATADV_DUPLIST_SIZE - 1); | 1265 | curr = (bat_priv->bla.bcast_duplist_curr + BATADV_DUPLIST_SIZE - 1); |
1260 | curr %= BATADV_DUPLIST_SIZE; | 1266 | curr %= BATADV_DUPLIST_SIZE; |
1261 | entry = &bat_priv->bcast_duplist[curr]; | 1267 | entry = &bat_priv->bla.bcast_duplist[curr]; |
1262 | entry->crc = crc; | 1268 | entry->crc = crc; |
1263 | entry->entrytime = jiffies; | 1269 | entry->entrytime = jiffies; |
1264 | memcpy(entry->orig, bcast_packet->orig, ETH_ALEN); | 1270 | memcpy(entry->orig, bcast_packet->orig, ETH_ALEN); |
1265 | bat_priv->bcast_duplist_curr = curr; | 1271 | bat_priv->bla.bcast_duplist_curr = curr; |
1266 | 1272 | ||
1267 | /* allow it, its the first occurence. */ | 1273 | /* allow it, its the first occurence. */ |
1268 | return 0; | 1274 | return 0; |
@@ -1279,7 +1285,7 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, | |||
1279 | */ | 1285 | */ |
1280 | int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, uint8_t *orig) | 1286 | int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, uint8_t *orig) |
1281 | { | 1287 | { |
1282 | struct batadv_hashtable *hash = bat_priv->backbone_hash; | 1288 | struct batadv_hashtable *hash = bat_priv->bla.backbone_hash; |
1283 | struct hlist_head *head; | 1289 | struct hlist_head *head; |
1284 | struct hlist_node *node; | 1290 | struct hlist_node *node; |
1285 | struct batadv_backbone_gw *backbone_gw; | 1291 | struct batadv_backbone_gw *backbone_gw; |
@@ -1339,8 +1345,7 @@ int batadv_bla_is_backbone_gw(struct sk_buff *skb, | |||
1339 | if (!pskb_may_pull(skb, hdr_size + sizeof(struct vlan_ethhdr))) | 1345 | if (!pskb_may_pull(skb, hdr_size + sizeof(struct vlan_ethhdr))) |
1340 | return 0; | 1346 | return 0; |
1341 | 1347 | ||
1342 | vhdr = (struct vlan_ethhdr *)(((uint8_t *)skb->data) + | 1348 | vhdr = (struct vlan_ethhdr *)(skb->data + hdr_size); |
1343 | hdr_size); | ||
1344 | vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK; | 1349 | vid = ntohs(vhdr->h_vlan_TCI) & VLAN_VID_MASK; |
1345 | } | 1350 | } |
1346 | 1351 | ||
@@ -1359,18 +1364,18 @@ void batadv_bla_free(struct batadv_priv *bat_priv) | |||
1359 | { | 1364 | { |
1360 | struct batadv_hard_iface *primary_if; | 1365 | struct batadv_hard_iface *primary_if; |
1361 | 1366 | ||
1362 | cancel_delayed_work_sync(&bat_priv->bla_work); | 1367 | cancel_delayed_work_sync(&bat_priv->bla.work); |
1363 | primary_if = batadv_primary_if_get_selected(bat_priv); | 1368 | primary_if = batadv_primary_if_get_selected(bat_priv); |
1364 | 1369 | ||
1365 | if (bat_priv->claim_hash) { | 1370 | if (bat_priv->bla.claim_hash) { |
1366 | batadv_bla_purge_claims(bat_priv, primary_if, 1); | 1371 | batadv_bla_purge_claims(bat_priv, primary_if, 1); |
1367 | batadv_hash_destroy(bat_priv->claim_hash); | 1372 | batadv_hash_destroy(bat_priv->bla.claim_hash); |
1368 | bat_priv->claim_hash = NULL; | 1373 | bat_priv->bla.claim_hash = NULL; |
1369 | } | 1374 | } |
1370 | if (bat_priv->backbone_hash) { | 1375 | if (bat_priv->bla.backbone_hash) { |
1371 | batadv_bla_purge_backbone_gw(bat_priv, 1); | 1376 | batadv_bla_purge_backbone_gw(bat_priv, 1); |
1372 | batadv_hash_destroy(bat_priv->backbone_hash); | 1377 | batadv_hash_destroy(bat_priv->bla.backbone_hash); |
1373 | bat_priv->backbone_hash = NULL; | 1378 | bat_priv->bla.backbone_hash = NULL; |
1374 | } | 1379 | } |
1375 | if (primary_if) | 1380 | if (primary_if) |
1376 | batadv_hardif_free_ref(primary_if); | 1381 | batadv_hardif_free_ref(primary_if); |
@@ -1409,7 +1414,7 @@ int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid, | |||
1409 | goto allow; | 1414 | goto allow; |
1410 | 1415 | ||
1411 | 1416 | ||
1412 | if (unlikely(atomic_read(&bat_priv->bla_num_requests))) | 1417 | if (unlikely(atomic_read(&bat_priv->bla.num_requests))) |
1413 | /* don't allow broadcasts while requests are in flight */ | 1418 | /* don't allow broadcasts while requests are in flight */ |
1414 | if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast) | 1419 | if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast) |
1415 | goto handled; | 1420 | goto handled; |
@@ -1508,7 +1513,7 @@ int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid) | |||
1508 | 1513 | ||
1509 | ethhdr = (struct ethhdr *)skb_mac_header(skb); | 1514 | ethhdr = (struct ethhdr *)skb_mac_header(skb); |
1510 | 1515 | ||
1511 | if (unlikely(atomic_read(&bat_priv->bla_num_requests))) | 1516 | if (unlikely(atomic_read(&bat_priv->bla.num_requests))) |
1512 | /* don't allow broadcasts while requests are in flight */ | 1517 | /* don't allow broadcasts while requests are in flight */ |
1513 | if (is_multicast_ether_addr(ethhdr->h_dest)) | 1518 | if (is_multicast_ether_addr(ethhdr->h_dest)) |
1514 | goto handled; | 1519 | goto handled; |
@@ -1564,7 +1569,7 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset) | |||
1564 | { | 1569 | { |
1565 | struct net_device *net_dev = (struct net_device *)seq->private; | 1570 | struct net_device *net_dev = (struct net_device *)seq->private; |
1566 | struct batadv_priv *bat_priv = netdev_priv(net_dev); | 1571 | struct batadv_priv *bat_priv = netdev_priv(net_dev); |
1567 | struct batadv_hashtable *hash = bat_priv->claim_hash; | 1572 | struct batadv_hashtable *hash = bat_priv->bla.claim_hash; |
1568 | struct batadv_claim *claim; | 1573 | struct batadv_claim *claim; |
1569 | struct batadv_hard_iface *primary_if; | 1574 | struct batadv_hard_iface *primary_if; |
1570 | struct hlist_node *node; | 1575 | struct hlist_node *node; |
@@ -1593,7 +1598,7 @@ int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset) | |||
1593 | seq_printf(seq, | 1598 | seq_printf(seq, |
1594 | "Claims announced for the mesh %s (orig %pM, group id %04x)\n", | 1599 | "Claims announced for the mesh %s (orig %pM, group id %04x)\n", |
1595 | net_dev->name, primary_addr, | 1600 | net_dev->name, primary_addr, |
1596 | ntohs(bat_priv->claim_dest.group)); | 1601 | ntohs(bat_priv->bla.claim_dest.group)); |
1597 | seq_printf(seq, " %-17s %-5s %-17s [o] (%-4s)\n", | 1602 | seq_printf(seq, " %-17s %-5s %-17s [o] (%-4s)\n", |
1598 | "Client", "VID", "Originator", "CRC"); | 1603 | "Client", "VID", "Originator", "CRC"); |
1599 | for (i = 0; i < hash->size; i++) { | 1604 | for (i = 0; i < hash->size; i++) { |
@@ -1616,3 +1621,68 @@ out: | |||
1616 | batadv_hardif_free_ref(primary_if); | 1621 | batadv_hardif_free_ref(primary_if); |
1617 | return ret; | 1622 | return ret; |
1618 | } | 1623 | } |
1624 | |||
1625 | int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, void *offset) | ||
1626 | { | ||
1627 | struct net_device *net_dev = (struct net_device *)seq->private; | ||
1628 | struct batadv_priv *bat_priv = netdev_priv(net_dev); | ||
1629 | struct batadv_hashtable *hash = bat_priv->bla.backbone_hash; | ||
1630 | struct batadv_backbone_gw *backbone_gw; | ||
1631 | struct batadv_hard_iface *primary_if; | ||
1632 | struct hlist_node *node; | ||
1633 | struct hlist_head *head; | ||
1634 | int secs, msecs; | ||
1635 | uint32_t i; | ||
1636 | bool is_own; | ||
1637 | int ret = 0; | ||
1638 | uint8_t *primary_addr; | ||
1639 | |||
1640 | primary_if = batadv_primary_if_get_selected(bat_priv); | ||
1641 | if (!primary_if) { | ||
1642 | ret = seq_printf(seq, | ||
1643 | "BATMAN mesh %s disabled - please specify interfaces to enable it\n", | ||
1644 | net_dev->name); | ||
1645 | goto out; | ||
1646 | } | ||
1647 | |||
1648 | if (primary_if->if_status != BATADV_IF_ACTIVE) { | ||
1649 | ret = seq_printf(seq, | ||
1650 | "BATMAN mesh %s disabled - primary interface not active\n", | ||
1651 | net_dev->name); | ||
1652 | goto out; | ||
1653 | } | ||
1654 | |||
1655 | primary_addr = primary_if->net_dev->dev_addr; | ||
1656 | seq_printf(seq, | ||
1657 | "Backbones announced for the mesh %s (orig %pM, group id %04x)\n", | ||
1658 | net_dev->name, primary_addr, | ||
1659 | ntohs(bat_priv->bla.claim_dest.group)); | ||
1660 | seq_printf(seq, " %-17s %-5s %-9s (%-4s)\n", | ||
1661 | "Originator", "VID", "last seen", "CRC"); | ||
1662 | for (i = 0; i < hash->size; i++) { | ||
1663 | head = &hash->table[i]; | ||
1664 | |||
1665 | rcu_read_lock(); | ||
1666 | hlist_for_each_entry_rcu(backbone_gw, node, head, hash_entry) { | ||
1667 | msecs = jiffies_to_msecs(jiffies - | ||
1668 | backbone_gw->lasttime); | ||
1669 | secs = msecs / 1000; | ||
1670 | msecs = msecs % 1000; | ||
1671 | |||
1672 | is_own = batadv_compare_eth(backbone_gw->orig, | ||
1673 | primary_addr); | ||
1674 | if (is_own) | ||
1675 | continue; | ||
1676 | |||
1677 | seq_printf(seq, | ||
1678 | " * %pM on % 5d % 4i.%03is (%04x)\n", | ||
1679 | backbone_gw->orig, backbone_gw->vid, | ||
1680 | secs, msecs, backbone_gw->crc); | ||
1681 | } | ||
1682 | rcu_read_unlock(); | ||
1683 | } | ||
1684 | out: | ||
1685 | if (primary_if) | ||
1686 | batadv_hardif_free_ref(primary_if); | ||
1687 | return ret; | ||
1688 | } | ||
diff --git a/net/batman-adv/bridge_loop_avoidance.h b/net/batman-adv/bridge_loop_avoidance.h index 563cfbf94a7f..789cb73bde67 100644 --- a/net/batman-adv/bridge_loop_avoidance.h +++ b/net/batman-adv/bridge_loop_avoidance.h | |||
@@ -27,6 +27,8 @@ int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, short vid); | |||
27 | int batadv_bla_is_backbone_gw(struct sk_buff *skb, | 27 | int batadv_bla_is_backbone_gw(struct sk_buff *skb, |
28 | struct batadv_orig_node *orig_node, int hdr_size); | 28 | struct batadv_orig_node *orig_node, int hdr_size); |
29 | int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset); | 29 | int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, void *offset); |
30 | int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, | ||
31 | void *offset); | ||
30 | int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, uint8_t *orig); | 32 | int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, uint8_t *orig); |
31 | int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, | 33 | int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, |
32 | struct batadv_bcast_packet *bcast_packet, | 34 | struct batadv_bcast_packet *bcast_packet, |
@@ -41,8 +43,7 @@ void batadv_bla_free(struct batadv_priv *bat_priv); | |||
41 | #else /* ifdef CONFIG_BATMAN_ADV_BLA */ | 43 | #else /* ifdef CONFIG_BATMAN_ADV_BLA */ |
42 | 44 | ||
43 | static inline int batadv_bla_rx(struct batadv_priv *bat_priv, | 45 | static inline int batadv_bla_rx(struct batadv_priv *bat_priv, |
44 | struct sk_buff *skb, short vid, | 46 | struct sk_buff *skb, short vid, bool is_bcast) |
45 | bool is_bcast) | ||
46 | { | 47 | { |
47 | return 0; | 48 | return 0; |
48 | } | 49 | } |
@@ -66,6 +67,12 @@ static inline int batadv_bla_claim_table_seq_print_text(struct seq_file *seq, | |||
66 | return 0; | 67 | return 0; |
67 | } | 68 | } |
68 | 69 | ||
70 | static inline int batadv_bla_backbone_table_seq_print_text(struct seq_file *seq, | ||
71 | void *offset) | ||
72 | { | ||
73 | return 0; | ||
74 | } | ||
75 | |||
69 | static inline int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, | 76 | static inline int batadv_bla_is_backbone_gw_orig(struct batadv_priv *bat_priv, |
70 | uint8_t *orig) | 77 | uint8_t *orig) |
71 | { | 78 | { |
diff --git a/net/batman-adv/debugfs.c b/net/batman-adv/debugfs.c index 34fbb1667bcd..391d4fb2026f 100644 --- a/net/batman-adv/debugfs.c +++ b/net/batman-adv/debugfs.c | |||
@@ -267,6 +267,15 @@ static int batadv_bla_claim_table_open(struct inode *inode, struct file *file) | |||
267 | return single_open(file, batadv_bla_claim_table_seq_print_text, | 267 | return single_open(file, batadv_bla_claim_table_seq_print_text, |
268 | net_dev); | 268 | net_dev); |
269 | } | 269 | } |
270 | |||
271 | static int batadv_bla_backbone_table_open(struct inode *inode, | ||
272 | struct file *file) | ||
273 | { | ||
274 | struct net_device *net_dev = (struct net_device *)inode->i_private; | ||
275 | return single_open(file, batadv_bla_backbone_table_seq_print_text, | ||
276 | net_dev); | ||
277 | } | ||
278 | |||
270 | #endif | 279 | #endif |
271 | 280 | ||
272 | static int batadv_transtable_local_open(struct inode *inode, struct file *file) | 281 | static int batadv_transtable_local_open(struct inode *inode, struct file *file) |
@@ -305,6 +314,8 @@ static BATADV_DEBUGINFO(transtable_global, S_IRUGO, | |||
305 | batadv_transtable_global_open); | 314 | batadv_transtable_global_open); |
306 | #ifdef CONFIG_BATMAN_ADV_BLA | 315 | #ifdef CONFIG_BATMAN_ADV_BLA |
307 | static BATADV_DEBUGINFO(bla_claim_table, S_IRUGO, batadv_bla_claim_table_open); | 316 | static BATADV_DEBUGINFO(bla_claim_table, S_IRUGO, batadv_bla_claim_table_open); |
317 | static BATADV_DEBUGINFO(bla_backbone_table, S_IRUGO, | ||
318 | batadv_bla_backbone_table_open); | ||
308 | #endif | 319 | #endif |
309 | static BATADV_DEBUGINFO(transtable_local, S_IRUGO, | 320 | static BATADV_DEBUGINFO(transtable_local, S_IRUGO, |
310 | batadv_transtable_local_open); | 321 | batadv_transtable_local_open); |
@@ -316,6 +327,7 @@ static struct batadv_debuginfo *batadv_mesh_debuginfos[] = { | |||
316 | &batadv_debuginfo_transtable_global, | 327 | &batadv_debuginfo_transtable_global, |
317 | #ifdef CONFIG_BATMAN_ADV_BLA | 328 | #ifdef CONFIG_BATMAN_ADV_BLA |
318 | &batadv_debuginfo_bla_claim_table, | 329 | &batadv_debuginfo_bla_claim_table, |
330 | &batadv_debuginfo_bla_backbone_table, | ||
319 | #endif | 331 | #endif |
320 | &batadv_debuginfo_transtable_local, | 332 | &batadv_debuginfo_transtable_local, |
321 | &batadv_debuginfo_vis_data, | 333 | &batadv_debuginfo_vis_data, |
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index b421cc49d2cd..15d67abc10a4 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c | |||
@@ -48,7 +48,7 @@ batadv_gw_get_selected_gw_node(struct batadv_priv *bat_priv) | |||
48 | struct batadv_gw_node *gw_node; | 48 | struct batadv_gw_node *gw_node; |
49 | 49 | ||
50 | rcu_read_lock(); | 50 | rcu_read_lock(); |
51 | gw_node = rcu_dereference(bat_priv->curr_gw); | 51 | gw_node = rcu_dereference(bat_priv->gw.curr_gw); |
52 | if (!gw_node) | 52 | if (!gw_node) |
53 | goto out; | 53 | goto out; |
54 | 54 | ||
@@ -91,23 +91,23 @@ static void batadv_gw_select(struct batadv_priv *bat_priv, | |||
91 | { | 91 | { |
92 | struct batadv_gw_node *curr_gw_node; | 92 | struct batadv_gw_node *curr_gw_node; |
93 | 93 | ||
94 | spin_lock_bh(&bat_priv->gw_list_lock); | 94 | spin_lock_bh(&bat_priv->gw.list_lock); |
95 | 95 | ||
96 | if (new_gw_node && !atomic_inc_not_zero(&new_gw_node->refcount)) | 96 | if (new_gw_node && !atomic_inc_not_zero(&new_gw_node->refcount)) |
97 | new_gw_node = NULL; | 97 | new_gw_node = NULL; |
98 | 98 | ||
99 | curr_gw_node = rcu_dereference_protected(bat_priv->curr_gw, 1); | 99 | curr_gw_node = rcu_dereference_protected(bat_priv->gw.curr_gw, 1); |
100 | rcu_assign_pointer(bat_priv->curr_gw, new_gw_node); | 100 | rcu_assign_pointer(bat_priv->gw.curr_gw, new_gw_node); |
101 | 101 | ||
102 | if (curr_gw_node) | 102 | if (curr_gw_node) |
103 | batadv_gw_node_free_ref(curr_gw_node); | 103 | batadv_gw_node_free_ref(curr_gw_node); |
104 | 104 | ||
105 | spin_unlock_bh(&bat_priv->gw_list_lock); | 105 | spin_unlock_bh(&bat_priv->gw.list_lock); |
106 | } | 106 | } |
107 | 107 | ||
108 | void batadv_gw_deselect(struct batadv_priv *bat_priv) | 108 | void batadv_gw_deselect(struct batadv_priv *bat_priv) |
109 | { | 109 | { |
110 | atomic_set(&bat_priv->gw_reselect, 1); | 110 | atomic_set(&bat_priv->gw.reselect, 1); |
111 | } | 111 | } |
112 | 112 | ||
113 | static struct batadv_gw_node * | 113 | static struct batadv_gw_node * |
@@ -117,12 +117,17 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv) | |||
117 | struct hlist_node *node; | 117 | struct hlist_node *node; |
118 | struct batadv_gw_node *gw_node, *curr_gw = NULL; | 118 | struct batadv_gw_node *gw_node, *curr_gw = NULL; |
119 | uint32_t max_gw_factor = 0, tmp_gw_factor = 0; | 119 | uint32_t max_gw_factor = 0, tmp_gw_factor = 0; |
120 | uint32_t gw_divisor; | ||
120 | uint8_t max_tq = 0; | 121 | uint8_t max_tq = 0; |
121 | int down, up; | 122 | int down, up; |
123 | uint8_t tq_avg; | ||
122 | struct batadv_orig_node *orig_node; | 124 | struct batadv_orig_node *orig_node; |
123 | 125 | ||
126 | gw_divisor = BATADV_TQ_LOCAL_WINDOW_SIZE * BATADV_TQ_LOCAL_WINDOW_SIZE; | ||
127 | gw_divisor *= 64; | ||
128 | |||
124 | rcu_read_lock(); | 129 | rcu_read_lock(); |
125 | hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { | 130 | hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw.list, list) { |
126 | if (gw_node->deleted) | 131 | if (gw_node->deleted) |
127 | continue; | 132 | continue; |
128 | 133 | ||
@@ -134,19 +139,19 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv) | |||
134 | if (!atomic_inc_not_zero(&gw_node->refcount)) | 139 | if (!atomic_inc_not_zero(&gw_node->refcount)) |
135 | goto next; | 140 | goto next; |
136 | 141 | ||
142 | tq_avg = router->tq_avg; | ||
143 | |||
137 | switch (atomic_read(&bat_priv->gw_sel_class)) { | 144 | switch (atomic_read(&bat_priv->gw_sel_class)) { |
138 | case 1: /* fast connection */ | 145 | case 1: /* fast connection */ |
139 | batadv_gw_bandwidth_to_kbit(orig_node->gw_flags, | 146 | batadv_gw_bandwidth_to_kbit(orig_node->gw_flags, |
140 | &down, &up); | 147 | &down, &up); |
141 | 148 | ||
142 | tmp_gw_factor = (router->tq_avg * router->tq_avg * | 149 | tmp_gw_factor = tq_avg * tq_avg * down * 100 * 100; |
143 | down * 100 * 100) / | 150 | tmp_gw_factor /= gw_divisor; |
144 | (BATADV_TQ_LOCAL_WINDOW_SIZE * | ||
145 | BATADV_TQ_LOCAL_WINDOW_SIZE * 64); | ||
146 | 151 | ||
147 | if ((tmp_gw_factor > max_gw_factor) || | 152 | if ((tmp_gw_factor > max_gw_factor) || |
148 | ((tmp_gw_factor == max_gw_factor) && | 153 | ((tmp_gw_factor == max_gw_factor) && |
149 | (router->tq_avg > max_tq))) { | 154 | (tq_avg > max_tq))) { |
150 | if (curr_gw) | 155 | if (curr_gw) |
151 | batadv_gw_node_free_ref(curr_gw); | 156 | batadv_gw_node_free_ref(curr_gw); |
152 | curr_gw = gw_node; | 157 | curr_gw = gw_node; |
@@ -161,7 +166,7 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv) | |||
161 | * soon as a better gateway appears which has | 166 | * soon as a better gateway appears which has |
162 | * $routing_class more tq points) | 167 | * $routing_class more tq points) |
163 | */ | 168 | */ |
164 | if (router->tq_avg > max_tq) { | 169 | if (tq_avg > max_tq) { |
165 | if (curr_gw) | 170 | if (curr_gw) |
166 | batadv_gw_node_free_ref(curr_gw); | 171 | batadv_gw_node_free_ref(curr_gw); |
167 | curr_gw = gw_node; | 172 | curr_gw = gw_node; |
@@ -170,8 +175,8 @@ batadv_gw_get_best_gw_node(struct batadv_priv *bat_priv) | |||
170 | break; | 175 | break; |
171 | } | 176 | } |
172 | 177 | ||
173 | if (router->tq_avg > max_tq) | 178 | if (tq_avg > max_tq) |
174 | max_tq = router->tq_avg; | 179 | max_tq = tq_avg; |
175 | 180 | ||
176 | if (tmp_gw_factor > max_gw_factor) | 181 | if (tmp_gw_factor > max_gw_factor) |
177 | max_gw_factor = tmp_gw_factor; | 182 | max_gw_factor = tmp_gw_factor; |
@@ -200,11 +205,11 @@ void batadv_gw_election(struct batadv_priv *bat_priv) | |||
200 | if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_CLIENT) | 205 | if (atomic_read(&bat_priv->gw_mode) != BATADV_GW_MODE_CLIENT) |
201 | goto out; | 206 | goto out; |
202 | 207 | ||
203 | if (!batadv_atomic_dec_not_zero(&bat_priv->gw_reselect)) | ||
204 | goto out; | ||
205 | |||
206 | curr_gw = batadv_gw_get_selected_gw_node(bat_priv); | 208 | curr_gw = batadv_gw_get_selected_gw_node(bat_priv); |
207 | 209 | ||
210 | if (!batadv_atomic_dec_not_zero(&bat_priv->gw.reselect) && curr_gw) | ||
211 | goto out; | ||
212 | |||
208 | next_gw = batadv_gw_get_best_gw_node(bat_priv); | 213 | next_gw = batadv_gw_get_best_gw_node(bat_priv); |
209 | 214 | ||
210 | if (curr_gw == next_gw) | 215 | if (curr_gw == next_gw) |
@@ -321,9 +326,9 @@ static void batadv_gw_node_add(struct batadv_priv *bat_priv, | |||
321 | gw_node->orig_node = orig_node; | 326 | gw_node->orig_node = orig_node; |
322 | atomic_set(&gw_node->refcount, 1); | 327 | atomic_set(&gw_node->refcount, 1); |
323 | 328 | ||
324 | spin_lock_bh(&bat_priv->gw_list_lock); | 329 | spin_lock_bh(&bat_priv->gw.list_lock); |
325 | hlist_add_head_rcu(&gw_node->list, &bat_priv->gw_list); | 330 | hlist_add_head_rcu(&gw_node->list, &bat_priv->gw.list); |
326 | spin_unlock_bh(&bat_priv->gw_list_lock); | 331 | spin_unlock_bh(&bat_priv->gw.list_lock); |
327 | 332 | ||
328 | batadv_gw_bandwidth_to_kbit(new_gwflags, &down, &up); | 333 | batadv_gw_bandwidth_to_kbit(new_gwflags, &down, &up); |
329 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 334 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
@@ -350,7 +355,7 @@ void batadv_gw_node_update(struct batadv_priv *bat_priv, | |||
350 | curr_gw = batadv_gw_get_selected_gw_node(bat_priv); | 355 | curr_gw = batadv_gw_get_selected_gw_node(bat_priv); |
351 | 356 | ||
352 | rcu_read_lock(); | 357 | rcu_read_lock(); |
353 | hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { | 358 | hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw.list, list) { |
354 | if (gw_node->orig_node != orig_node) | 359 | if (gw_node->orig_node != orig_node) |
355 | continue; | 360 | continue; |
356 | 361 | ||
@@ -404,10 +409,10 @@ void batadv_gw_node_purge(struct batadv_priv *bat_priv) | |||
404 | 409 | ||
405 | curr_gw = batadv_gw_get_selected_gw_node(bat_priv); | 410 | curr_gw = batadv_gw_get_selected_gw_node(bat_priv); |
406 | 411 | ||
407 | spin_lock_bh(&bat_priv->gw_list_lock); | 412 | spin_lock_bh(&bat_priv->gw.list_lock); |
408 | 413 | ||
409 | hlist_for_each_entry_safe(gw_node, node, node_tmp, | 414 | hlist_for_each_entry_safe(gw_node, node, node_tmp, |
410 | &bat_priv->gw_list, list) { | 415 | &bat_priv->gw.list, list) { |
411 | if (((!gw_node->deleted) || | 416 | if (((!gw_node->deleted) || |
412 | (time_before(jiffies, gw_node->deleted + timeout))) && | 417 | (time_before(jiffies, gw_node->deleted + timeout))) && |
413 | atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE) | 418 | atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE) |
@@ -420,7 +425,7 @@ void batadv_gw_node_purge(struct batadv_priv *bat_priv) | |||
420 | batadv_gw_node_free_ref(gw_node); | 425 | batadv_gw_node_free_ref(gw_node); |
421 | } | 426 | } |
422 | 427 | ||
423 | spin_unlock_bh(&bat_priv->gw_list_lock); | 428 | spin_unlock_bh(&bat_priv->gw.list_lock); |
424 | 429 | ||
425 | /* gw_deselect() needs to acquire the gw_list_lock */ | 430 | /* gw_deselect() needs to acquire the gw_list_lock */ |
426 | if (do_deselect) | 431 | if (do_deselect) |
@@ -496,7 +501,7 @@ int batadv_gw_client_seq_print_text(struct seq_file *seq, void *offset) | |||
496 | primary_if->net_dev->dev_addr, net_dev->name); | 501 | primary_if->net_dev->dev_addr, net_dev->name); |
497 | 502 | ||
498 | rcu_read_lock(); | 503 | rcu_read_lock(); |
499 | hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw_list, list) { | 504 | hlist_for_each_entry_rcu(gw_node, node, &bat_priv->gw.list, list) { |
500 | if (gw_node->deleted) | 505 | if (gw_node->deleted) |
501 | continue; | 506 | continue; |
502 | 507 | ||
diff --git a/net/batman-adv/hard-interface.c b/net/batman-adv/hard-interface.c index 282bf6e9353e..d112fd6750b0 100644 --- a/net/batman-adv/hard-interface.c +++ b/net/batman-adv/hard-interface.c | |||
@@ -103,13 +103,14 @@ static void batadv_primary_if_update_addr(struct batadv_priv *bat_priv, | |||
103 | { | 103 | { |
104 | struct batadv_vis_packet *vis_packet; | 104 | struct batadv_vis_packet *vis_packet; |
105 | struct batadv_hard_iface *primary_if; | 105 | struct batadv_hard_iface *primary_if; |
106 | struct sk_buff *skb; | ||
106 | 107 | ||
107 | primary_if = batadv_primary_if_get_selected(bat_priv); | 108 | primary_if = batadv_primary_if_get_selected(bat_priv); |
108 | if (!primary_if) | 109 | if (!primary_if) |
109 | goto out; | 110 | goto out; |
110 | 111 | ||
111 | vis_packet = (struct batadv_vis_packet *) | 112 | skb = bat_priv->vis.my_info->skb_packet; |
112 | bat_priv->my_vis_info->skb_packet->data; | 113 | vis_packet = (struct batadv_vis_packet *)skb->data; |
113 | memcpy(vis_packet->vis_orig, primary_if->net_dev->dev_addr, ETH_ALEN); | 114 | memcpy(vis_packet->vis_orig, primary_if->net_dev->dev_addr, ETH_ALEN); |
114 | memcpy(vis_packet->sender_orig, | 115 | memcpy(vis_packet->sender_orig, |
115 | primary_if->net_dev->dev_addr, ETH_ALEN); | 116 | primary_if->net_dev->dev_addr, ETH_ALEN); |
@@ -313,7 +314,13 @@ int batadv_hardif_enable_interface(struct batadv_hard_iface *hard_iface, | |||
313 | hard_iface->if_num = bat_priv->num_ifaces; | 314 | hard_iface->if_num = bat_priv->num_ifaces; |
314 | bat_priv->num_ifaces++; | 315 | bat_priv->num_ifaces++; |
315 | hard_iface->if_status = BATADV_IF_INACTIVE; | 316 | hard_iface->if_status = BATADV_IF_INACTIVE; |
316 | batadv_orig_hash_add_if(hard_iface, bat_priv->num_ifaces); | 317 | ret = batadv_orig_hash_add_if(hard_iface, bat_priv->num_ifaces); |
318 | if (ret < 0) { | ||
319 | bat_priv->bat_algo_ops->bat_iface_disable(hard_iface); | ||
320 | bat_priv->num_ifaces--; | ||
321 | hard_iface->if_status = BATADV_IF_NOT_IN_USE; | ||
322 | goto err_dev; | ||
323 | } | ||
317 | 324 | ||
318 | hard_iface->batman_adv_ptype.type = ethertype; | 325 | hard_iface->batman_adv_ptype.type = ethertype; |
319 | hard_iface->batman_adv_ptype.func = batadv_batman_skb_recv; | 326 | hard_iface->batman_adv_ptype.func = batadv_batman_skb_recv; |
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 13c88b25ab31..b4aa470bc4a6 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c | |||
@@ -58,9 +58,6 @@ static int __init batadv_init(void) | |||
58 | 58 | ||
59 | batadv_iv_init(); | 59 | batadv_iv_init(); |
60 | 60 | ||
61 | /* the name should not be longer than 10 chars - see | ||
62 | * http://lwn.net/Articles/23634/ | ||
63 | */ | ||
64 | batadv_event_workqueue = create_singlethread_workqueue("bat_events"); | 61 | batadv_event_workqueue = create_singlethread_workqueue("bat_events"); |
65 | 62 | ||
66 | if (!batadv_event_workqueue) | 63 | if (!batadv_event_workqueue) |
@@ -97,20 +94,20 @@ int batadv_mesh_init(struct net_device *soft_iface) | |||
97 | 94 | ||
98 | spin_lock_init(&bat_priv->forw_bat_list_lock); | 95 | spin_lock_init(&bat_priv->forw_bat_list_lock); |
99 | spin_lock_init(&bat_priv->forw_bcast_list_lock); | 96 | spin_lock_init(&bat_priv->forw_bcast_list_lock); |
100 | spin_lock_init(&bat_priv->tt_changes_list_lock); | 97 | spin_lock_init(&bat_priv->tt.changes_list_lock); |
101 | spin_lock_init(&bat_priv->tt_req_list_lock); | 98 | spin_lock_init(&bat_priv->tt.req_list_lock); |
102 | spin_lock_init(&bat_priv->tt_roam_list_lock); | 99 | spin_lock_init(&bat_priv->tt.roam_list_lock); |
103 | spin_lock_init(&bat_priv->tt_buff_lock); | 100 | spin_lock_init(&bat_priv->tt.last_changeset_lock); |
104 | spin_lock_init(&bat_priv->gw_list_lock); | 101 | spin_lock_init(&bat_priv->gw.list_lock); |
105 | spin_lock_init(&bat_priv->vis_hash_lock); | 102 | spin_lock_init(&bat_priv->vis.hash_lock); |
106 | spin_lock_init(&bat_priv->vis_list_lock); | 103 | spin_lock_init(&bat_priv->vis.list_lock); |
107 | 104 | ||
108 | INIT_HLIST_HEAD(&bat_priv->forw_bat_list); | 105 | INIT_HLIST_HEAD(&bat_priv->forw_bat_list); |
109 | INIT_HLIST_HEAD(&bat_priv->forw_bcast_list); | 106 | INIT_HLIST_HEAD(&bat_priv->forw_bcast_list); |
110 | INIT_HLIST_HEAD(&bat_priv->gw_list); | 107 | INIT_HLIST_HEAD(&bat_priv->gw.list); |
111 | INIT_LIST_HEAD(&bat_priv->tt_changes_list); | 108 | INIT_LIST_HEAD(&bat_priv->tt.changes_list); |
112 | INIT_LIST_HEAD(&bat_priv->tt_req_list); | 109 | INIT_LIST_HEAD(&bat_priv->tt.req_list); |
113 | INIT_LIST_HEAD(&bat_priv->tt_roam_list); | 110 | INIT_LIST_HEAD(&bat_priv->tt.roam_list); |
114 | 111 | ||
115 | ret = batadv_originator_init(bat_priv); | 112 | ret = batadv_originator_init(bat_priv); |
116 | if (ret < 0) | 113 | if (ret < 0) |
@@ -131,7 +128,7 @@ int batadv_mesh_init(struct net_device *soft_iface) | |||
131 | if (ret < 0) | 128 | if (ret < 0) |
132 | goto err; | 129 | goto err; |
133 | 130 | ||
134 | atomic_set(&bat_priv->gw_reselect, 0); | 131 | atomic_set(&bat_priv->gw.reselect, 0); |
135 | atomic_set(&bat_priv->mesh_state, BATADV_MESH_ACTIVE); | 132 | atomic_set(&bat_priv->mesh_state, BATADV_MESH_ACTIVE); |
136 | 133 | ||
137 | return 0; | 134 | return 0; |
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index 5d8fa0757947..d57b746219de 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h | |||
@@ -26,7 +26,7 @@ | |||
26 | #define BATADV_DRIVER_DEVICE "batman-adv" | 26 | #define BATADV_DRIVER_DEVICE "batman-adv" |
27 | 27 | ||
28 | #ifndef BATADV_SOURCE_VERSION | 28 | #ifndef BATADV_SOURCE_VERSION |
29 | #define BATADV_SOURCE_VERSION "2012.3.0" | 29 | #define BATADV_SOURCE_VERSION "2012.4.0" |
30 | #endif | 30 | #endif |
31 | 31 | ||
32 | /* B.A.T.M.A.N. parameters */ | 32 | /* B.A.T.M.A.N. parameters */ |
@@ -41,13 +41,14 @@ | |||
41 | * -> TODO: check influence on BATADV_TQ_LOCAL_WINDOW_SIZE | 41 | * -> TODO: check influence on BATADV_TQ_LOCAL_WINDOW_SIZE |
42 | */ | 42 | */ |
43 | #define BATADV_PURGE_TIMEOUT 200000 /* 200 seconds */ | 43 | #define BATADV_PURGE_TIMEOUT 200000 /* 200 seconds */ |
44 | #define BATADV_TT_LOCAL_TIMEOUT 3600000 /* in miliseconds */ | 44 | #define BATADV_TT_LOCAL_TIMEOUT 3600000 /* in milliseconds */ |
45 | #define BATADV_TT_CLIENT_ROAM_TIMEOUT 600000 /* in miliseconds */ | 45 | #define BATADV_TT_CLIENT_ROAM_TIMEOUT 600000 /* in milliseconds */ |
46 | #define BATADV_TT_CLIENT_TEMP_TIMEOUT 600000 /* in milliseconds */ | ||
46 | /* sliding packet range of received originator messages in sequence numbers | 47 | /* sliding packet range of received originator messages in sequence numbers |
47 | * (should be a multiple of our word size) | 48 | * (should be a multiple of our word size) |
48 | */ | 49 | */ |
49 | #define BATADV_TQ_LOCAL_WINDOW_SIZE 64 | 50 | #define BATADV_TQ_LOCAL_WINDOW_SIZE 64 |
50 | /* miliseconds we have to keep pending tt_req */ | 51 | /* milliseconds we have to keep pending tt_req */ |
51 | #define BATADV_TT_REQUEST_TIMEOUT 3000 | 52 | #define BATADV_TT_REQUEST_TIMEOUT 3000 |
52 | 53 | ||
53 | #define BATADV_TQ_GLOBAL_WINDOW_SIZE 5 | 54 | #define BATADV_TQ_GLOBAL_WINDOW_SIZE 5 |
@@ -59,7 +60,7 @@ | |||
59 | #define BATADV_TT_OGM_APPEND_MAX 3 | 60 | #define BATADV_TT_OGM_APPEND_MAX 3 |
60 | 61 | ||
61 | /* Time in which a client can roam at most ROAMING_MAX_COUNT times in | 62 | /* Time in which a client can roam at most ROAMING_MAX_COUNT times in |
62 | * miliseconds | 63 | * milliseconds |
63 | */ | 64 | */ |
64 | #define BATADV_ROAMING_MAX_TIME 20000 | 65 | #define BATADV_ROAMING_MAX_TIME 20000 |
65 | #define BATADV_ROAMING_MAX_COUNT 5 | 66 | #define BATADV_ROAMING_MAX_COUNT 5 |
@@ -123,15 +124,6 @@ enum batadv_uev_type { | |||
123 | /* Append 'batman-adv: ' before kernel messages */ | 124 | /* Append 'batman-adv: ' before kernel messages */ |
124 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 125 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
125 | 126 | ||
126 | /* all messages related to routing / flooding / broadcasting / etc */ | ||
127 | enum batadv_dbg_level { | ||
128 | BATADV_DBG_BATMAN = 1 << 0, | ||
129 | BATADV_DBG_ROUTES = 1 << 1, /* route added / changed / deleted */ | ||
130 | BATADV_DBG_TT = 1 << 2, /* translation table operations */ | ||
131 | BATADV_DBG_BLA = 1 << 3, /* bridge loop avoidance */ | ||
132 | BATADV_DBG_ALL = 15, | ||
133 | }; | ||
134 | |||
135 | /* Kernel headers */ | 127 | /* Kernel headers */ |
136 | 128 | ||
137 | #include <linux/mutex.h> /* mutex */ | 129 | #include <linux/mutex.h> /* mutex */ |
@@ -173,6 +165,15 @@ int batadv_algo_register(struct batadv_algo_ops *bat_algo_ops); | |||
173 | int batadv_algo_select(struct batadv_priv *bat_priv, char *name); | 165 | int batadv_algo_select(struct batadv_priv *bat_priv, char *name); |
174 | int batadv_algo_seq_print_text(struct seq_file *seq, void *offset); | 166 | int batadv_algo_seq_print_text(struct seq_file *seq, void *offset); |
175 | 167 | ||
168 | /* all messages related to routing / flooding / broadcasting / etc */ | ||
169 | enum batadv_dbg_level { | ||
170 | BATADV_DBG_BATMAN = BIT(0), | ||
171 | BATADV_DBG_ROUTES = BIT(1), /* route added / changed / deleted */ | ||
172 | BATADV_DBG_TT = BIT(2), /* translation table operations */ | ||
173 | BATADV_DBG_BLA = BIT(3), /* bridge loop avoidance */ | ||
174 | BATADV_DBG_ALL = 15, | ||
175 | }; | ||
176 | |||
176 | #ifdef CONFIG_BATMAN_ADV_DEBUG | 177 | #ifdef CONFIG_BATMAN_ADV_DEBUG |
177 | int batadv_debug_log(struct batadv_priv *bat_priv, const char *fmt, ...) | 178 | int batadv_debug_log(struct batadv_priv *bat_priv, const char *fmt, ...) |
178 | __printf(2, 3); | 179 | __printf(2, 3); |
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h index 8d3e55a96adc..2d23a14c220e 100644 --- a/net/batman-adv/packet.h +++ b/net/batman-adv/packet.h | |||
@@ -37,10 +37,10 @@ enum batadv_packettype { | |||
37 | #define BATADV_COMPAT_VERSION 14 | 37 | #define BATADV_COMPAT_VERSION 14 |
38 | 38 | ||
39 | enum batadv_iv_flags { | 39 | enum batadv_iv_flags { |
40 | BATADV_NOT_BEST_NEXT_HOP = 1 << 3, | 40 | BATADV_NOT_BEST_NEXT_HOP = BIT(3), |
41 | BATADV_PRIMARIES_FIRST_HOP = 1 << 4, | 41 | BATADV_PRIMARIES_FIRST_HOP = BIT(4), |
42 | BATADV_VIS_SERVER = 1 << 5, | 42 | BATADV_VIS_SERVER = BIT(5), |
43 | BATADV_DIRECTLINK = 1 << 6, | 43 | BATADV_DIRECTLINK = BIT(6), |
44 | }; | 44 | }; |
45 | 45 | ||
46 | /* ICMP message types */ | 46 | /* ICMP message types */ |
@@ -60,8 +60,8 @@ enum batadv_vis_packettype { | |||
60 | 60 | ||
61 | /* fragmentation defines */ | 61 | /* fragmentation defines */ |
62 | enum batadv_unicast_frag_flags { | 62 | enum batadv_unicast_frag_flags { |
63 | BATADV_UNI_FRAG_HEAD = 1 << 0, | 63 | BATADV_UNI_FRAG_HEAD = BIT(0), |
64 | BATADV_UNI_FRAG_LARGETAIL = 1 << 1, | 64 | BATADV_UNI_FRAG_LARGETAIL = BIT(1), |
65 | }; | 65 | }; |
66 | 66 | ||
67 | /* TT_QUERY subtypes */ | 67 | /* TT_QUERY subtypes */ |
@@ -74,26 +74,27 @@ enum batadv_tt_query_packettype { | |||
74 | 74 | ||
75 | /* TT_QUERY flags */ | 75 | /* TT_QUERY flags */ |
76 | enum batadv_tt_query_flags { | 76 | enum batadv_tt_query_flags { |
77 | BATADV_TT_FULL_TABLE = 1 << 2, | 77 | BATADV_TT_FULL_TABLE = BIT(2), |
78 | }; | 78 | }; |
79 | 79 | ||
80 | /* BATADV_TT_CLIENT flags. | 80 | /* BATADV_TT_CLIENT flags. |
81 | * Flags from 1 to 1 << 7 are sent on the wire, while flags from 1 << 8 to | 81 | * Flags from BIT(0) to BIT(7) are sent on the wire, while flags from BIT(8) to |
82 | * 1 << 15 are used for local computation only | 82 | * BIT(15) are used for local computation only |
83 | */ | 83 | */ |
84 | enum batadv_tt_client_flags { | 84 | enum batadv_tt_client_flags { |
85 | BATADV_TT_CLIENT_DEL = 1 << 0, | 85 | BATADV_TT_CLIENT_DEL = BIT(0), |
86 | BATADV_TT_CLIENT_ROAM = 1 << 1, | 86 | BATADV_TT_CLIENT_ROAM = BIT(1), |
87 | BATADV_TT_CLIENT_WIFI = 1 << 2, | 87 | BATADV_TT_CLIENT_WIFI = BIT(2), |
88 | BATADV_TT_CLIENT_NOPURGE = 1 << 8, | 88 | BATADV_TT_CLIENT_TEMP = BIT(3), |
89 | BATADV_TT_CLIENT_NEW = 1 << 9, | 89 | BATADV_TT_CLIENT_NOPURGE = BIT(8), |
90 | BATADV_TT_CLIENT_PENDING = 1 << 10, | 90 | BATADV_TT_CLIENT_NEW = BIT(9), |
91 | BATADV_TT_CLIENT_PENDING = BIT(10), | ||
91 | }; | 92 | }; |
92 | 93 | ||
93 | /* claim frame types for the bridge loop avoidance */ | 94 | /* claim frame types for the bridge loop avoidance */ |
94 | enum batadv_bla_claimframe { | 95 | enum batadv_bla_claimframe { |
95 | BATADV_CLAIM_TYPE_ADD = 0x00, | 96 | BATADV_CLAIM_TYPE_CLAIM = 0x00, |
96 | BATADV_CLAIM_TYPE_DEL = 0x01, | 97 | BATADV_CLAIM_TYPE_UNCLAIM = 0x01, |
97 | BATADV_CLAIM_TYPE_ANNOUNCE = 0x02, | 98 | BATADV_CLAIM_TYPE_ANNOUNCE = 0x02, |
98 | BATADV_CLAIM_TYPE_REQUEST = 0x03, | 99 | BATADV_CLAIM_TYPE_REQUEST = 0x03, |
99 | }; | 100 | }; |
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index bc2b88bbea1f..939fc01371df 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c | |||
@@ -579,32 +579,45 @@ batadv_find_ifalter_router(struct batadv_orig_node *primary_orig, | |||
579 | return router; | 579 | return router; |
580 | } | 580 | } |
581 | 581 | ||
582 | int batadv_recv_tt_query(struct sk_buff *skb, struct batadv_hard_iface *recv_if) | 582 | static int batadv_check_unicast_packet(struct sk_buff *skb, int hdr_size) |
583 | { | 583 | { |
584 | struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); | ||
585 | struct batadv_tt_query_packet *tt_query; | ||
586 | uint16_t tt_size; | ||
587 | struct ethhdr *ethhdr; | 584 | struct ethhdr *ethhdr; |
588 | char tt_flag; | ||
589 | size_t packet_size; | ||
590 | 585 | ||
591 | /* drop packet if it has not necessary minimum size */ | 586 | /* drop packet if it has not necessary minimum size */ |
592 | if (unlikely(!pskb_may_pull(skb, | 587 | if (unlikely(!pskb_may_pull(skb, hdr_size))) |
593 | sizeof(struct batadv_tt_query_packet)))) | 588 | return -1; |
594 | goto out; | ||
595 | |||
596 | /* I could need to modify it */ | ||
597 | if (skb_cow(skb, sizeof(struct batadv_tt_query_packet)) < 0) | ||
598 | goto out; | ||
599 | 589 | ||
600 | ethhdr = (struct ethhdr *)skb_mac_header(skb); | 590 | ethhdr = (struct ethhdr *)skb_mac_header(skb); |
601 | 591 | ||
602 | /* packet with unicast indication but broadcast recipient */ | 592 | /* packet with unicast indication but broadcast recipient */ |
603 | if (is_broadcast_ether_addr(ethhdr->h_dest)) | 593 | if (is_broadcast_ether_addr(ethhdr->h_dest)) |
604 | goto out; | 594 | return -1; |
605 | 595 | ||
606 | /* packet with broadcast sender address */ | 596 | /* packet with broadcast sender address */ |
607 | if (is_broadcast_ether_addr(ethhdr->h_source)) | 597 | if (is_broadcast_ether_addr(ethhdr->h_source)) |
598 | return -1; | ||
599 | |||
600 | /* not for me */ | ||
601 | if (!batadv_is_my_mac(ethhdr->h_dest)) | ||
602 | return -1; | ||
603 | |||
604 | return 0; | ||
605 | } | ||
606 | |||
607 | int batadv_recv_tt_query(struct sk_buff *skb, struct batadv_hard_iface *recv_if) | ||
608 | { | ||
609 | struct batadv_priv *bat_priv = netdev_priv(recv_if->soft_iface); | ||
610 | struct batadv_tt_query_packet *tt_query; | ||
611 | uint16_t tt_size; | ||
612 | int hdr_size = sizeof(*tt_query); | ||
613 | char tt_flag; | ||
614 | size_t packet_size; | ||
615 | |||
616 | if (batadv_check_unicast_packet(skb, hdr_size) < 0) | ||
617 | return NET_RX_DROP; | ||
618 | |||
619 | /* I could need to modify it */ | ||
620 | if (skb_cow(skb, sizeof(struct batadv_tt_query_packet)) < 0) | ||
608 | goto out; | 621 | goto out; |
609 | 622 | ||
610 | tt_query = (struct batadv_tt_query_packet *)skb->data; | 623 | tt_query = (struct batadv_tt_query_packet *)skb->data; |
@@ -721,7 +734,7 @@ int batadv_recv_roam_adv(struct sk_buff *skb, struct batadv_hard_iface *recv_if) | |||
721 | * been incremented yet. This flag will make me check all the incoming | 734 | * been incremented yet. This flag will make me check all the incoming |
722 | * packets for the correct destination. | 735 | * packets for the correct destination. |
723 | */ | 736 | */ |
724 | bat_priv->tt_poss_change = true; | 737 | bat_priv->tt.poss_change = true; |
725 | 738 | ||
726 | batadv_orig_node_free_ref(orig_node); | 739 | batadv_orig_node_free_ref(orig_node); |
727 | out: | 740 | out: |
@@ -819,31 +832,6 @@ err: | |||
819 | return NULL; | 832 | return NULL; |
820 | } | 833 | } |
821 | 834 | ||
822 | static int batadv_check_unicast_packet(struct sk_buff *skb, int hdr_size) | ||
823 | { | ||
824 | struct ethhdr *ethhdr; | ||
825 | |||
826 | /* drop packet if it has not necessary minimum size */ | ||
827 | if (unlikely(!pskb_may_pull(skb, hdr_size))) | ||
828 | return -1; | ||
829 | |||
830 | ethhdr = (struct ethhdr *)skb_mac_header(skb); | ||
831 | |||
832 | /* packet with unicast indication but broadcast recipient */ | ||
833 | if (is_broadcast_ether_addr(ethhdr->h_dest)) | ||
834 | return -1; | ||
835 | |||
836 | /* packet with broadcast sender address */ | ||
837 | if (is_broadcast_ether_addr(ethhdr->h_source)) | ||
838 | return -1; | ||
839 | |||
840 | /* not for me */ | ||
841 | if (!batadv_is_my_mac(ethhdr->h_dest)) | ||
842 | return -1; | ||
843 | |||
844 | return 0; | ||
845 | } | ||
846 | |||
847 | static int batadv_route_unicast_packet(struct sk_buff *skb, | 835 | static int batadv_route_unicast_packet(struct sk_buff *skb, |
848 | struct batadv_hard_iface *recv_if) | 836 | struct batadv_hard_iface *recv_if) |
849 | { | 837 | { |
@@ -947,8 +935,8 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv, | |||
947 | unicast_packet = (struct batadv_unicast_packet *)skb->data; | 935 | unicast_packet = (struct batadv_unicast_packet *)skb->data; |
948 | 936 | ||
949 | if (batadv_is_my_mac(unicast_packet->dest)) { | 937 | if (batadv_is_my_mac(unicast_packet->dest)) { |
950 | tt_poss_change = bat_priv->tt_poss_change; | 938 | tt_poss_change = bat_priv->tt.poss_change; |
951 | curr_ttvn = (uint8_t)atomic_read(&bat_priv->ttvn); | 939 | curr_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); |
952 | } else { | 940 | } else { |
953 | orig_node = batadv_orig_hash_find(bat_priv, | 941 | orig_node = batadv_orig_hash_find(bat_priv, |
954 | unicast_packet->dest); | 942 | unicast_packet->dest); |
@@ -993,8 +981,7 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv, | |||
993 | } else { | 981 | } else { |
994 | memcpy(unicast_packet->dest, orig_node->orig, | 982 | memcpy(unicast_packet->dest, orig_node->orig, |
995 | ETH_ALEN); | 983 | ETH_ALEN); |
996 | curr_ttvn = (uint8_t) | 984 | curr_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); |
997 | atomic_read(&orig_node->last_ttvn); | ||
998 | batadv_orig_node_free_ref(orig_node); | 985 | batadv_orig_node_free_ref(orig_node); |
999 | } | 986 | } |
1000 | 987 | ||
@@ -1025,8 +1012,9 @@ int batadv_recv_unicast_packet(struct sk_buff *skb, | |||
1025 | 1012 | ||
1026 | /* packet for me */ | 1013 | /* packet for me */ |
1027 | if (batadv_is_my_mac(unicast_packet->dest)) { | 1014 | if (batadv_is_my_mac(unicast_packet->dest)) { |
1028 | batadv_interface_rx(recv_if->soft_iface, skb, recv_if, | 1015 | batadv_interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size, |
1029 | hdr_size); | 1016 | NULL); |
1017 | |||
1030 | return NET_RX_SUCCESS; | 1018 | return NET_RX_SUCCESS; |
1031 | } | 1019 | } |
1032 | 1020 | ||
@@ -1063,7 +1051,7 @@ int batadv_recv_ucast_frag_packet(struct sk_buff *skb, | |||
1063 | return NET_RX_SUCCESS; | 1051 | return NET_RX_SUCCESS; |
1064 | 1052 | ||
1065 | batadv_interface_rx(recv_if->soft_iface, new_skb, recv_if, | 1053 | batadv_interface_rx(recv_if->soft_iface, new_skb, recv_if, |
1066 | sizeof(struct batadv_unicast_packet)); | 1054 | sizeof(struct batadv_unicast_packet), NULL); |
1067 | return NET_RX_SUCCESS; | 1055 | return NET_RX_SUCCESS; |
1068 | } | 1056 | } |
1069 | 1057 | ||
@@ -1150,7 +1138,8 @@ int batadv_recv_bcast_packet(struct sk_buff *skb, | |||
1150 | goto out; | 1138 | goto out; |
1151 | 1139 | ||
1152 | /* broadcast for me */ | 1140 | /* broadcast for me */ |
1153 | batadv_interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size); | 1141 | batadv_interface_rx(recv_if->soft_iface, skb, recv_if, hdr_size, |
1142 | orig_node); | ||
1154 | ret = NET_RX_SUCCESS; | 1143 | ret = NET_RX_SUCCESS; |
1155 | goto out; | 1144 | goto out; |
1156 | 1145 | ||
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index 3b4b2daa3b3e..570a8bce0364 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c | |||
@@ -190,13 +190,13 @@ out: | |||
190 | static void batadv_send_outstanding_bcast_packet(struct work_struct *work) | 190 | static void batadv_send_outstanding_bcast_packet(struct work_struct *work) |
191 | { | 191 | { |
192 | struct batadv_hard_iface *hard_iface; | 192 | struct batadv_hard_iface *hard_iface; |
193 | struct delayed_work *delayed_work = | 193 | struct delayed_work *delayed_work; |
194 | container_of(work, struct delayed_work, work); | ||
195 | struct batadv_forw_packet *forw_packet; | 194 | struct batadv_forw_packet *forw_packet; |
196 | struct sk_buff *skb1; | 195 | struct sk_buff *skb1; |
197 | struct net_device *soft_iface; | 196 | struct net_device *soft_iface; |
198 | struct batadv_priv *bat_priv; | 197 | struct batadv_priv *bat_priv; |
199 | 198 | ||
199 | delayed_work = container_of(work, struct delayed_work, work); | ||
200 | forw_packet = container_of(delayed_work, struct batadv_forw_packet, | 200 | forw_packet = container_of(delayed_work, struct batadv_forw_packet, |
201 | delayed_work); | 201 | delayed_work); |
202 | soft_iface = forw_packet->if_incoming->soft_iface; | 202 | soft_iface = forw_packet->if_incoming->soft_iface; |
@@ -239,11 +239,11 @@ out: | |||
239 | 239 | ||
240 | void batadv_send_outstanding_bat_ogm_packet(struct work_struct *work) | 240 | void batadv_send_outstanding_bat_ogm_packet(struct work_struct *work) |
241 | { | 241 | { |
242 | struct delayed_work *delayed_work = | 242 | struct delayed_work *delayed_work; |
243 | container_of(work, struct delayed_work, work); | ||
244 | struct batadv_forw_packet *forw_packet; | 243 | struct batadv_forw_packet *forw_packet; |
245 | struct batadv_priv *bat_priv; | 244 | struct batadv_priv *bat_priv; |
246 | 245 | ||
246 | delayed_work = container_of(work, struct delayed_work, work); | ||
247 | forw_packet = container_of(delayed_work, struct batadv_forw_packet, | 247 | forw_packet = container_of(delayed_work, struct batadv_forw_packet, |
248 | delayed_work); | 248 | delayed_work); |
249 | bat_priv = netdev_priv(forw_packet->if_incoming->soft_iface); | 249 | bat_priv = netdev_priv(forw_packet->if_incoming->soft_iface); |
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index 109ea2aae96c..7b683e0bd668 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c | |||
@@ -93,7 +93,14 @@ static int batadv_interface_release(struct net_device *dev) | |||
93 | static struct net_device_stats *batadv_interface_stats(struct net_device *dev) | 93 | static struct net_device_stats *batadv_interface_stats(struct net_device *dev) |
94 | { | 94 | { |
95 | struct batadv_priv *bat_priv = netdev_priv(dev); | 95 | struct batadv_priv *bat_priv = netdev_priv(dev); |
96 | return &bat_priv->stats; | 96 | struct net_device_stats *stats = &bat_priv->stats; |
97 | |||
98 | stats->tx_packets = batadv_sum_counter(bat_priv, BATADV_CNT_TX); | ||
99 | stats->tx_bytes = batadv_sum_counter(bat_priv, BATADV_CNT_TX_BYTES); | ||
100 | stats->tx_dropped = batadv_sum_counter(bat_priv, BATADV_CNT_TX_DROPPED); | ||
101 | stats->rx_packets = batadv_sum_counter(bat_priv, BATADV_CNT_RX); | ||
102 | stats->rx_bytes = batadv_sum_counter(bat_priv, BATADV_CNT_RX_BYTES); | ||
103 | return stats; | ||
97 | } | 104 | } |
98 | 105 | ||
99 | static int batadv_interface_set_mac_addr(struct net_device *dev, void *p) | 106 | static int batadv_interface_set_mac_addr(struct net_device *dev, void *p) |
@@ -142,6 +149,7 @@ static int batadv_interface_tx(struct sk_buff *skb, | |||
142 | int data_len = skb->len, ret; | 149 | int data_len = skb->len, ret; |
143 | short vid __maybe_unused = -1; | 150 | short vid __maybe_unused = -1; |
144 | bool do_bcast = false; | 151 | bool do_bcast = false; |
152 | uint32_t seqno; | ||
145 | 153 | ||
146 | if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) | 154 | if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) |
147 | goto dropped; | 155 | goto dropped; |
@@ -223,8 +231,8 @@ static int batadv_interface_tx(struct sk_buff *skb, | |||
223 | primary_if->net_dev->dev_addr, ETH_ALEN); | 231 | primary_if->net_dev->dev_addr, ETH_ALEN); |
224 | 232 | ||
225 | /* set broadcast sequence number */ | 233 | /* set broadcast sequence number */ |
226 | bcast_packet->seqno = | 234 | seqno = atomic_inc_return(&bat_priv->bcast_seqno); |
227 | htonl(atomic_inc_return(&bat_priv->bcast_seqno)); | 235 | bcast_packet->seqno = htonl(seqno); |
228 | 236 | ||
229 | batadv_add_bcast_packet_to_list(bat_priv, skb, 1); | 237 | batadv_add_bcast_packet_to_list(bat_priv, skb, 1); |
230 | 238 | ||
@@ -246,14 +254,14 @@ static int batadv_interface_tx(struct sk_buff *skb, | |||
246 | goto dropped_freed; | 254 | goto dropped_freed; |
247 | } | 255 | } |
248 | 256 | ||
249 | bat_priv->stats.tx_packets++; | 257 | batadv_inc_counter(bat_priv, BATADV_CNT_TX); |
250 | bat_priv->stats.tx_bytes += data_len; | 258 | batadv_add_counter(bat_priv, BATADV_CNT_TX_BYTES, data_len); |
251 | goto end; | 259 | goto end; |
252 | 260 | ||
253 | dropped: | 261 | dropped: |
254 | kfree_skb(skb); | 262 | kfree_skb(skb); |
255 | dropped_freed: | 263 | dropped_freed: |
256 | bat_priv->stats.tx_dropped++; | 264 | batadv_inc_counter(bat_priv, BATADV_CNT_TX_DROPPED); |
257 | end: | 265 | end: |
258 | if (primary_if) | 266 | if (primary_if) |
259 | batadv_hardif_free_ref(primary_if); | 267 | batadv_hardif_free_ref(primary_if); |
@@ -262,7 +270,7 @@ end: | |||
262 | 270 | ||
263 | void batadv_interface_rx(struct net_device *soft_iface, | 271 | void batadv_interface_rx(struct net_device *soft_iface, |
264 | struct sk_buff *skb, struct batadv_hard_iface *recv_if, | 272 | struct sk_buff *skb, struct batadv_hard_iface *recv_if, |
265 | int hdr_size) | 273 | int hdr_size, struct batadv_orig_node *orig_node) |
266 | { | 274 | { |
267 | struct batadv_priv *bat_priv = netdev_priv(soft_iface); | 275 | struct batadv_priv *bat_priv = netdev_priv(soft_iface); |
268 | struct ethhdr *ethhdr; | 276 | struct ethhdr *ethhdr; |
@@ -308,11 +316,16 @@ void batadv_interface_rx(struct net_device *soft_iface, | |||
308 | 316 | ||
309 | /* skb->ip_summed = CHECKSUM_UNNECESSARY; */ | 317 | /* skb->ip_summed = CHECKSUM_UNNECESSARY; */ |
310 | 318 | ||
311 | bat_priv->stats.rx_packets++; | 319 | batadv_inc_counter(bat_priv, BATADV_CNT_RX); |
312 | bat_priv->stats.rx_bytes += skb->len + ETH_HLEN; | 320 | batadv_add_counter(bat_priv, BATADV_CNT_RX_BYTES, |
321 | skb->len + ETH_HLEN); | ||
313 | 322 | ||
314 | soft_iface->last_rx = jiffies; | 323 | soft_iface->last_rx = jiffies; |
315 | 324 | ||
325 | if (orig_node) | ||
326 | batadv_tt_add_temporary_global_entry(bat_priv, orig_node, | ||
327 | ethhdr->h_source); | ||
328 | |||
316 | if (batadv_is_ap_isolated(bat_priv, ethhdr->h_source, ethhdr->h_dest)) | 329 | if (batadv_is_ap_isolated(bat_priv, ethhdr->h_source, ethhdr->h_dest)) |
317 | goto dropped; | 330 | goto dropped; |
318 | 331 | ||
@@ -379,15 +392,22 @@ struct net_device *batadv_softif_create(const char *name) | |||
379 | if (!soft_iface) | 392 | if (!soft_iface) |
380 | goto out; | 393 | goto out; |
381 | 394 | ||
395 | bat_priv = netdev_priv(soft_iface); | ||
396 | |||
397 | /* batadv_interface_stats() needs to be available as soon as | ||
398 | * register_netdevice() has been called | ||
399 | */ | ||
400 | bat_priv->bat_counters = __alloc_percpu(cnt_len, __alignof__(uint64_t)); | ||
401 | if (!bat_priv->bat_counters) | ||
402 | goto free_soft_iface; | ||
403 | |||
382 | ret = register_netdevice(soft_iface); | 404 | ret = register_netdevice(soft_iface); |
383 | if (ret < 0) { | 405 | if (ret < 0) { |
384 | pr_err("Unable to register the batman interface '%s': %i\n", | 406 | pr_err("Unable to register the batman interface '%s': %i\n", |
385 | name, ret); | 407 | name, ret); |
386 | goto free_soft_iface; | 408 | goto free_bat_counters; |
387 | } | 409 | } |
388 | 410 | ||
389 | bat_priv = netdev_priv(soft_iface); | ||
390 | |||
391 | atomic_set(&bat_priv->aggregated_ogms, 1); | 411 | atomic_set(&bat_priv->aggregated_ogms, 1); |
392 | atomic_set(&bat_priv->bonding, 0); | 412 | atomic_set(&bat_priv->bonding, 0); |
393 | atomic_set(&bat_priv->bridge_loop_avoidance, 0); | 413 | atomic_set(&bat_priv->bridge_loop_avoidance, 0); |
@@ -405,29 +425,26 @@ struct net_device *batadv_softif_create(const char *name) | |||
405 | 425 | ||
406 | atomic_set(&bat_priv->mesh_state, BATADV_MESH_INACTIVE); | 426 | atomic_set(&bat_priv->mesh_state, BATADV_MESH_INACTIVE); |
407 | atomic_set(&bat_priv->bcast_seqno, 1); | 427 | atomic_set(&bat_priv->bcast_seqno, 1); |
408 | atomic_set(&bat_priv->ttvn, 0); | 428 | atomic_set(&bat_priv->tt.vn, 0); |
409 | atomic_set(&bat_priv->tt_local_changes, 0); | 429 | atomic_set(&bat_priv->tt.local_changes, 0); |
410 | atomic_set(&bat_priv->tt_ogm_append_cnt, 0); | 430 | atomic_set(&bat_priv->tt.ogm_append_cnt, 0); |
411 | atomic_set(&bat_priv->bla_num_requests, 0); | 431 | #ifdef CONFIG_BATMAN_ADV_BLA |
412 | 432 | atomic_set(&bat_priv->bla.num_requests, 0); | |
413 | bat_priv->tt_buff = NULL; | 433 | #endif |
414 | bat_priv->tt_buff_len = 0; | 434 | bat_priv->tt.last_changeset = NULL; |
415 | bat_priv->tt_poss_change = false; | 435 | bat_priv->tt.last_changeset_len = 0; |
436 | bat_priv->tt.poss_change = false; | ||
416 | 437 | ||
417 | bat_priv->primary_if = NULL; | 438 | bat_priv->primary_if = NULL; |
418 | bat_priv->num_ifaces = 0; | 439 | bat_priv->num_ifaces = 0; |
419 | 440 | ||
420 | bat_priv->bat_counters = __alloc_percpu(cnt_len, __alignof__(uint64_t)); | ||
421 | if (!bat_priv->bat_counters) | ||
422 | goto unreg_soft_iface; | ||
423 | |||
424 | ret = batadv_algo_select(bat_priv, batadv_routing_algo); | 441 | ret = batadv_algo_select(bat_priv, batadv_routing_algo); |
425 | if (ret < 0) | 442 | if (ret < 0) |
426 | goto free_bat_counters; | 443 | goto unreg_soft_iface; |
427 | 444 | ||
428 | ret = batadv_sysfs_add_meshif(soft_iface); | 445 | ret = batadv_sysfs_add_meshif(soft_iface); |
429 | if (ret < 0) | 446 | if (ret < 0) |
430 | goto free_bat_counters; | 447 | goto unreg_soft_iface; |
431 | 448 | ||
432 | ret = batadv_debugfs_add_meshif(soft_iface); | 449 | ret = batadv_debugfs_add_meshif(soft_iface); |
433 | if (ret < 0) | 450 | if (ret < 0) |
@@ -443,12 +460,13 @@ unreg_debugfs: | |||
443 | batadv_debugfs_del_meshif(soft_iface); | 460 | batadv_debugfs_del_meshif(soft_iface); |
444 | unreg_sysfs: | 461 | unreg_sysfs: |
445 | batadv_sysfs_del_meshif(soft_iface); | 462 | batadv_sysfs_del_meshif(soft_iface); |
446 | free_bat_counters: | ||
447 | free_percpu(bat_priv->bat_counters); | ||
448 | unreg_soft_iface: | 463 | unreg_soft_iface: |
464 | free_percpu(bat_priv->bat_counters); | ||
449 | unregister_netdevice(soft_iface); | 465 | unregister_netdevice(soft_iface); |
450 | return NULL; | 466 | return NULL; |
451 | 467 | ||
468 | free_bat_counters: | ||
469 | free_percpu(bat_priv->bat_counters); | ||
452 | free_soft_iface: | 470 | free_soft_iface: |
453 | free_netdev(soft_iface); | 471 | free_netdev(soft_iface); |
454 | out: | 472 | out: |
@@ -518,6 +536,11 @@ static u32 batadv_get_link(struct net_device *dev) | |||
518 | static const struct { | 536 | static const struct { |
519 | const char name[ETH_GSTRING_LEN]; | 537 | const char name[ETH_GSTRING_LEN]; |
520 | } batadv_counters_strings[] = { | 538 | } batadv_counters_strings[] = { |
539 | { "tx" }, | ||
540 | { "tx_bytes" }, | ||
541 | { "tx_dropped" }, | ||
542 | { "rx" }, | ||
543 | { "rx_bytes" }, | ||
521 | { "forward" }, | 544 | { "forward" }, |
522 | { "forward_bytes" }, | 545 | { "forward_bytes" }, |
523 | { "mgmt_tx" }, | 546 | { "mgmt_tx" }, |
diff --git a/net/batman-adv/soft-interface.h b/net/batman-adv/soft-interface.h index 852c683b06a1..07a08fed28b9 100644 --- a/net/batman-adv/soft-interface.h +++ b/net/batman-adv/soft-interface.h | |||
@@ -21,8 +21,9 @@ | |||
21 | #define _NET_BATMAN_ADV_SOFT_INTERFACE_H_ | 21 | #define _NET_BATMAN_ADV_SOFT_INTERFACE_H_ |
22 | 22 | ||
23 | int batadv_skb_head_push(struct sk_buff *skb, unsigned int len); | 23 | int batadv_skb_head_push(struct sk_buff *skb, unsigned int len); |
24 | void batadv_interface_rx(struct net_device *soft_iface, struct sk_buff *skb, | 24 | void batadv_interface_rx(struct net_device *soft_iface, |
25 | struct batadv_hard_iface *recv_if, int hdr_size); | 25 | struct sk_buff *skb, struct batadv_hard_iface *recv_if, |
26 | int hdr_size, struct batadv_orig_node *orig_node); | ||
26 | struct net_device *batadv_softif_create(const char *name); | 27 | struct net_device *batadv_softif_create(const char *name); |
27 | void batadv_softif_destroy(struct net_device *soft_iface); | 28 | void batadv_softif_destroy(struct net_device *soft_iface); |
28 | int batadv_softif_is_valid(const struct net_device *net_dev); | 29 | int batadv_softif_is_valid(const struct net_device *net_dev); |
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index a438f4b582fc..112edd371b2f 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c | |||
@@ -34,6 +34,10 @@ static void batadv_send_roam_adv(struct batadv_priv *bat_priv, uint8_t *client, | |||
34 | static void batadv_tt_purge(struct work_struct *work); | 34 | static void batadv_tt_purge(struct work_struct *work); |
35 | static void | 35 | static void |
36 | batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry); | 36 | batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry); |
37 | static void batadv_tt_global_del(struct batadv_priv *bat_priv, | ||
38 | struct batadv_orig_node *orig_node, | ||
39 | const unsigned char *addr, | ||
40 | const char *message, bool roaming); | ||
37 | 41 | ||
38 | /* returns 1 if they are the same mac addr */ | 42 | /* returns 1 if they are the same mac addr */ |
39 | static int batadv_compare_tt(const struct hlist_node *node, const void *data2) | 43 | static int batadv_compare_tt(const struct hlist_node *node, const void *data2) |
@@ -46,8 +50,8 @@ static int batadv_compare_tt(const struct hlist_node *node, const void *data2) | |||
46 | 50 | ||
47 | static void batadv_tt_start_timer(struct batadv_priv *bat_priv) | 51 | static void batadv_tt_start_timer(struct batadv_priv *bat_priv) |
48 | { | 52 | { |
49 | INIT_DELAYED_WORK(&bat_priv->tt_work, batadv_tt_purge); | 53 | INIT_DELAYED_WORK(&bat_priv->tt.work, batadv_tt_purge); |
50 | queue_delayed_work(batadv_event_workqueue, &bat_priv->tt_work, | 54 | queue_delayed_work(batadv_event_workqueue, &bat_priv->tt.work, |
51 | msecs_to_jiffies(5000)); | 55 | msecs_to_jiffies(5000)); |
52 | } | 56 | } |
53 | 57 | ||
@@ -88,7 +92,7 @@ batadv_tt_local_hash_find(struct batadv_priv *bat_priv, const void *data) | |||
88 | struct batadv_tt_common_entry *tt_common_entry; | 92 | struct batadv_tt_common_entry *tt_common_entry; |
89 | struct batadv_tt_local_entry *tt_local_entry = NULL; | 93 | struct batadv_tt_local_entry *tt_local_entry = NULL; |
90 | 94 | ||
91 | tt_common_entry = batadv_tt_hash_find(bat_priv->tt_local_hash, data); | 95 | tt_common_entry = batadv_tt_hash_find(bat_priv->tt.local_hash, data); |
92 | if (tt_common_entry) | 96 | if (tt_common_entry) |
93 | tt_local_entry = container_of(tt_common_entry, | 97 | tt_local_entry = container_of(tt_common_entry, |
94 | struct batadv_tt_local_entry, | 98 | struct batadv_tt_local_entry, |
@@ -102,7 +106,7 @@ batadv_tt_global_hash_find(struct batadv_priv *bat_priv, const void *data) | |||
102 | struct batadv_tt_common_entry *tt_common_entry; | 106 | struct batadv_tt_common_entry *tt_common_entry; |
103 | struct batadv_tt_global_entry *tt_global_entry = NULL; | 107 | struct batadv_tt_global_entry *tt_global_entry = NULL; |
104 | 108 | ||
105 | tt_common_entry = batadv_tt_hash_find(bat_priv->tt_global_hash, data); | 109 | tt_common_entry = batadv_tt_hash_find(bat_priv->tt.global_hash, data); |
106 | if (tt_common_entry) | 110 | if (tt_common_entry) |
107 | tt_global_entry = container_of(tt_common_entry, | 111 | tt_global_entry = container_of(tt_common_entry, |
108 | struct batadv_tt_global_entry, | 112 | struct batadv_tt_global_entry, |
@@ -152,6 +156,8 @@ static void batadv_tt_orig_list_entry_free_rcu(struct rcu_head *rcu) | |||
152 | static void | 156 | static void |
153 | batadv_tt_orig_list_entry_free_ref(struct batadv_tt_orig_list_entry *orig_entry) | 157 | batadv_tt_orig_list_entry_free_ref(struct batadv_tt_orig_list_entry *orig_entry) |
154 | { | 158 | { |
159 | if (!atomic_dec_and_test(&orig_entry->refcount)) | ||
160 | return; | ||
155 | /* to avoid race conditions, immediately decrease the tt counter */ | 161 | /* to avoid race conditions, immediately decrease the tt counter */ |
156 | atomic_dec(&orig_entry->orig_node->tt_size); | 162 | atomic_dec(&orig_entry->orig_node->tt_size); |
157 | call_rcu(&orig_entry->rcu, batadv_tt_orig_list_entry_free_rcu); | 163 | call_rcu(&orig_entry->rcu, batadv_tt_orig_list_entry_free_rcu); |
@@ -175,8 +181,8 @@ static void batadv_tt_local_event(struct batadv_priv *bat_priv, | |||
175 | del_op_requested = flags & BATADV_TT_CLIENT_DEL; | 181 | del_op_requested = flags & BATADV_TT_CLIENT_DEL; |
176 | 182 | ||
177 | /* check for ADD+DEL or DEL+ADD events */ | 183 | /* check for ADD+DEL or DEL+ADD events */ |
178 | spin_lock_bh(&bat_priv->tt_changes_list_lock); | 184 | spin_lock_bh(&bat_priv->tt.changes_list_lock); |
179 | list_for_each_entry_safe(entry, safe, &bat_priv->tt_changes_list, | 185 | list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list, |
180 | list) { | 186 | list) { |
181 | if (!batadv_compare_eth(entry->change.addr, addr)) | 187 | if (!batadv_compare_eth(entry->change.addr, addr)) |
182 | continue; | 188 | continue; |
@@ -197,20 +203,21 @@ static void batadv_tt_local_event(struct batadv_priv *bat_priv, | |||
197 | del: | 203 | del: |
198 | list_del(&entry->list); | 204 | list_del(&entry->list); |
199 | kfree(entry); | 205 | kfree(entry); |
206 | kfree(tt_change_node); | ||
200 | event_removed = true; | 207 | event_removed = true; |
201 | goto unlock; | 208 | goto unlock; |
202 | } | 209 | } |
203 | 210 | ||
204 | /* track the change in the OGMinterval list */ | 211 | /* track the change in the OGMinterval list */ |
205 | list_add_tail(&tt_change_node->list, &bat_priv->tt_changes_list); | 212 | list_add_tail(&tt_change_node->list, &bat_priv->tt.changes_list); |
206 | 213 | ||
207 | unlock: | 214 | unlock: |
208 | spin_unlock_bh(&bat_priv->tt_changes_list_lock); | 215 | spin_unlock_bh(&bat_priv->tt.changes_list_lock); |
209 | 216 | ||
210 | if (event_removed) | 217 | if (event_removed) |
211 | atomic_dec(&bat_priv->tt_local_changes); | 218 | atomic_dec(&bat_priv->tt.local_changes); |
212 | else | 219 | else |
213 | atomic_inc(&bat_priv->tt_local_changes); | 220 | atomic_inc(&bat_priv->tt.local_changes); |
214 | } | 221 | } |
215 | 222 | ||
216 | int batadv_tt_len(int changes_num) | 223 | int batadv_tt_len(int changes_num) |
@@ -220,12 +227,12 @@ int batadv_tt_len(int changes_num) | |||
220 | 227 | ||
221 | static int batadv_tt_local_init(struct batadv_priv *bat_priv) | 228 | static int batadv_tt_local_init(struct batadv_priv *bat_priv) |
222 | { | 229 | { |
223 | if (bat_priv->tt_local_hash) | 230 | if (bat_priv->tt.local_hash) |
224 | return 0; | 231 | return 0; |
225 | 232 | ||
226 | bat_priv->tt_local_hash = batadv_hash_new(1024); | 233 | bat_priv->tt.local_hash = batadv_hash_new(1024); |
227 | 234 | ||
228 | if (!bat_priv->tt_local_hash) | 235 | if (!bat_priv->tt.local_hash) |
229 | return -ENOMEM; | 236 | return -ENOMEM; |
230 | 237 | ||
231 | return 0; | 238 | return 0; |
@@ -257,7 +264,7 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, | |||
257 | 264 | ||
258 | batadv_dbg(BATADV_DBG_TT, bat_priv, | 265 | batadv_dbg(BATADV_DBG_TT, bat_priv, |
259 | "Creating new local tt entry: %pM (ttvn: %d)\n", addr, | 266 | "Creating new local tt entry: %pM (ttvn: %d)\n", addr, |
260 | (uint8_t)atomic_read(&bat_priv->ttvn)); | 267 | (uint8_t)atomic_read(&bat_priv->tt.vn)); |
261 | 268 | ||
262 | memcpy(tt_local_entry->common.addr, addr, ETH_ALEN); | 269 | memcpy(tt_local_entry->common.addr, addr, ETH_ALEN); |
263 | tt_local_entry->common.flags = BATADV_NO_FLAGS; | 270 | tt_local_entry->common.flags = BATADV_NO_FLAGS; |
@@ -265,6 +272,7 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, | |||
265 | tt_local_entry->common.flags |= BATADV_TT_CLIENT_WIFI; | 272 | tt_local_entry->common.flags |= BATADV_TT_CLIENT_WIFI; |
266 | atomic_set(&tt_local_entry->common.refcount, 2); | 273 | atomic_set(&tt_local_entry->common.refcount, 2); |
267 | tt_local_entry->last_seen = jiffies; | 274 | tt_local_entry->last_seen = jiffies; |
275 | tt_local_entry->common.added_at = tt_local_entry->last_seen; | ||
268 | 276 | ||
269 | /* the batman interface mac address should never be purged */ | 277 | /* the batman interface mac address should never be purged */ |
270 | if (batadv_compare_eth(addr, soft_iface->dev_addr)) | 278 | if (batadv_compare_eth(addr, soft_iface->dev_addr)) |
@@ -276,7 +284,7 @@ void batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, | |||
276 | */ | 284 | */ |
277 | tt_local_entry->common.flags |= BATADV_TT_CLIENT_NEW; | 285 | tt_local_entry->common.flags |= BATADV_TT_CLIENT_NEW; |
278 | 286 | ||
279 | hash_added = batadv_hash_add(bat_priv->tt_local_hash, batadv_compare_tt, | 287 | hash_added = batadv_hash_add(bat_priv->tt.local_hash, batadv_compare_tt, |
280 | batadv_choose_orig, | 288 | batadv_choose_orig, |
281 | &tt_local_entry->common, | 289 | &tt_local_entry->common, |
282 | &tt_local_entry->common.hash_entry); | 290 | &tt_local_entry->common.hash_entry); |
@@ -347,7 +355,7 @@ static void batadv_tt_prepare_packet_buff(struct batadv_priv *bat_priv, | |||
347 | primary_if = batadv_primary_if_get_selected(bat_priv); | 355 | primary_if = batadv_primary_if_get_selected(bat_priv); |
348 | 356 | ||
349 | req_len = min_packet_len; | 357 | req_len = min_packet_len; |
350 | req_len += batadv_tt_len(atomic_read(&bat_priv->tt_local_changes)); | 358 | req_len += batadv_tt_len(atomic_read(&bat_priv->tt.local_changes)); |
351 | 359 | ||
352 | /* if we have too many changes for one packet don't send any | 360 | /* if we have too many changes for one packet don't send any |
353 | * and wait for the tt table request which will be fragmented | 361 | * and wait for the tt table request which will be fragmented |
@@ -380,10 +388,10 @@ static int batadv_tt_changes_fill_buff(struct batadv_priv *bat_priv, | |||
380 | if (new_len > 0) | 388 | if (new_len > 0) |
381 | tot_changes = new_len / batadv_tt_len(1); | 389 | tot_changes = new_len / batadv_tt_len(1); |
382 | 390 | ||
383 | spin_lock_bh(&bat_priv->tt_changes_list_lock); | 391 | spin_lock_bh(&bat_priv->tt.changes_list_lock); |
384 | atomic_set(&bat_priv->tt_local_changes, 0); | 392 | atomic_set(&bat_priv->tt.local_changes, 0); |
385 | 393 | ||
386 | list_for_each_entry_safe(entry, safe, &bat_priv->tt_changes_list, | 394 | list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list, |
387 | list) { | 395 | list) { |
388 | if (count < tot_changes) { | 396 | if (count < tot_changes) { |
389 | memcpy(tt_buff + batadv_tt_len(count), | 397 | memcpy(tt_buff + batadv_tt_len(count), |
@@ -393,25 +401,25 @@ static int batadv_tt_changes_fill_buff(struct batadv_priv *bat_priv, | |||
393 | list_del(&entry->list); | 401 | list_del(&entry->list); |
394 | kfree(entry); | 402 | kfree(entry); |
395 | } | 403 | } |
396 | spin_unlock_bh(&bat_priv->tt_changes_list_lock); | 404 | spin_unlock_bh(&bat_priv->tt.changes_list_lock); |
397 | 405 | ||
398 | /* Keep the buffer for possible tt_request */ | 406 | /* Keep the buffer for possible tt_request */ |
399 | spin_lock_bh(&bat_priv->tt_buff_lock); | 407 | spin_lock_bh(&bat_priv->tt.last_changeset_lock); |
400 | kfree(bat_priv->tt_buff); | 408 | kfree(bat_priv->tt.last_changeset); |
401 | bat_priv->tt_buff_len = 0; | 409 | bat_priv->tt.last_changeset_len = 0; |
402 | bat_priv->tt_buff = NULL; | 410 | bat_priv->tt.last_changeset = NULL; |
403 | /* check whether this new OGM has no changes due to size problems */ | 411 | /* check whether this new OGM has no changes due to size problems */ |
404 | if (new_len > 0) { | 412 | if (new_len > 0) { |
405 | /* if kmalloc() fails we will reply with the full table | 413 | /* if kmalloc() fails we will reply with the full table |
406 | * instead of providing the diff | 414 | * instead of providing the diff |
407 | */ | 415 | */ |
408 | bat_priv->tt_buff = kmalloc(new_len, GFP_ATOMIC); | 416 | bat_priv->tt.last_changeset = kmalloc(new_len, GFP_ATOMIC); |
409 | if (bat_priv->tt_buff) { | 417 | if (bat_priv->tt.last_changeset) { |
410 | memcpy(bat_priv->tt_buff, tt_buff, new_len); | 418 | memcpy(bat_priv->tt.last_changeset, tt_buff, new_len); |
411 | bat_priv->tt_buff_len = new_len; | 419 | bat_priv->tt.last_changeset_len = new_len; |
412 | } | 420 | } |
413 | } | 421 | } |
414 | spin_unlock_bh(&bat_priv->tt_buff_lock); | 422 | spin_unlock_bh(&bat_priv->tt.last_changeset_lock); |
415 | 423 | ||
416 | return count; | 424 | return count; |
417 | } | 425 | } |
@@ -420,7 +428,7 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset) | |||
420 | { | 428 | { |
421 | struct net_device *net_dev = (struct net_device *)seq->private; | 429 | struct net_device *net_dev = (struct net_device *)seq->private; |
422 | struct batadv_priv *bat_priv = netdev_priv(net_dev); | 430 | struct batadv_priv *bat_priv = netdev_priv(net_dev); |
423 | struct batadv_hashtable *hash = bat_priv->tt_local_hash; | 431 | struct batadv_hashtable *hash = bat_priv->tt.local_hash; |
424 | struct batadv_tt_common_entry *tt_common_entry; | 432 | struct batadv_tt_common_entry *tt_common_entry; |
425 | struct batadv_hard_iface *primary_if; | 433 | struct batadv_hard_iface *primary_if; |
426 | struct hlist_node *node; | 434 | struct hlist_node *node; |
@@ -445,7 +453,7 @@ int batadv_tt_local_seq_print_text(struct seq_file *seq, void *offset) | |||
445 | 453 | ||
446 | seq_printf(seq, | 454 | seq_printf(seq, |
447 | "Locally retrieved addresses (from %s) announced via TT (TTVN: %u):\n", | 455 | "Locally retrieved addresses (from %s) announced via TT (TTVN: %u):\n", |
448 | net_dev->name, (uint8_t)atomic_read(&bat_priv->ttvn)); | 456 | net_dev->name, (uint8_t)atomic_read(&bat_priv->tt.vn)); |
449 | 457 | ||
450 | for (i = 0; i < hash->size; i++) { | 458 | for (i = 0; i < hash->size; i++) { |
451 | head = &hash->table[i]; | 459 | head = &hash->table[i]; |
@@ -543,7 +551,7 @@ static void batadv_tt_local_purge_list(struct batadv_priv *bat_priv, | |||
543 | 551 | ||
544 | static void batadv_tt_local_purge(struct batadv_priv *bat_priv) | 552 | static void batadv_tt_local_purge(struct batadv_priv *bat_priv) |
545 | { | 553 | { |
546 | struct batadv_hashtable *hash = bat_priv->tt_local_hash; | 554 | struct batadv_hashtable *hash = bat_priv->tt.local_hash; |
547 | struct hlist_head *head; | 555 | struct hlist_head *head; |
548 | spinlock_t *list_lock; /* protects write access to the hash lists */ | 556 | spinlock_t *list_lock; /* protects write access to the hash lists */ |
549 | uint32_t i; | 557 | uint32_t i; |
@@ -569,10 +577,10 @@ static void batadv_tt_local_table_free(struct batadv_priv *bat_priv) | |||
569 | struct hlist_head *head; | 577 | struct hlist_head *head; |
570 | uint32_t i; | 578 | uint32_t i; |
571 | 579 | ||
572 | if (!bat_priv->tt_local_hash) | 580 | if (!bat_priv->tt.local_hash) |
573 | return; | 581 | return; |
574 | 582 | ||
575 | hash = bat_priv->tt_local_hash; | 583 | hash = bat_priv->tt.local_hash; |
576 | 584 | ||
577 | for (i = 0; i < hash->size; i++) { | 585 | for (i = 0; i < hash->size; i++) { |
578 | head = &hash->table[i]; | 586 | head = &hash->table[i]; |
@@ -592,17 +600,17 @@ static void batadv_tt_local_table_free(struct batadv_priv *bat_priv) | |||
592 | 600 | ||
593 | batadv_hash_destroy(hash); | 601 | batadv_hash_destroy(hash); |
594 | 602 | ||
595 | bat_priv->tt_local_hash = NULL; | 603 | bat_priv->tt.local_hash = NULL; |
596 | } | 604 | } |
597 | 605 | ||
598 | static int batadv_tt_global_init(struct batadv_priv *bat_priv) | 606 | static int batadv_tt_global_init(struct batadv_priv *bat_priv) |
599 | { | 607 | { |
600 | if (bat_priv->tt_global_hash) | 608 | if (bat_priv->tt.global_hash) |
601 | return 0; | 609 | return 0; |
602 | 610 | ||
603 | bat_priv->tt_global_hash = batadv_hash_new(1024); | 611 | bat_priv->tt.global_hash = batadv_hash_new(1024); |
604 | 612 | ||
605 | if (!bat_priv->tt_global_hash) | 613 | if (!bat_priv->tt.global_hash) |
606 | return -ENOMEM; | 614 | return -ENOMEM; |
607 | 615 | ||
608 | return 0; | 616 | return 0; |
@@ -612,62 +620,99 @@ static void batadv_tt_changes_list_free(struct batadv_priv *bat_priv) | |||
612 | { | 620 | { |
613 | struct batadv_tt_change_node *entry, *safe; | 621 | struct batadv_tt_change_node *entry, *safe; |
614 | 622 | ||
615 | spin_lock_bh(&bat_priv->tt_changes_list_lock); | 623 | spin_lock_bh(&bat_priv->tt.changes_list_lock); |
616 | 624 | ||
617 | list_for_each_entry_safe(entry, safe, &bat_priv->tt_changes_list, | 625 | list_for_each_entry_safe(entry, safe, &bat_priv->tt.changes_list, |
618 | list) { | 626 | list) { |
619 | list_del(&entry->list); | 627 | list_del(&entry->list); |
620 | kfree(entry); | 628 | kfree(entry); |
621 | } | 629 | } |
622 | 630 | ||
623 | atomic_set(&bat_priv->tt_local_changes, 0); | 631 | atomic_set(&bat_priv->tt.local_changes, 0); |
624 | spin_unlock_bh(&bat_priv->tt_changes_list_lock); | 632 | spin_unlock_bh(&bat_priv->tt.changes_list_lock); |
625 | } | 633 | } |
626 | 634 | ||
627 | /* find out if an orig_node is already in the list of a tt_global_entry. | 635 | /* retrieves the orig_tt_list_entry belonging to orig_node from the |
628 | * returns 1 if found, 0 otherwise | 636 | * batadv_tt_global_entry list |
637 | * | ||
638 | * returns it with an increased refcounter, NULL if not found | ||
629 | */ | 639 | */ |
630 | static bool | 640 | static struct batadv_tt_orig_list_entry * |
631 | batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry, | 641 | batadv_tt_global_orig_entry_find(const struct batadv_tt_global_entry *entry, |
632 | const struct batadv_orig_node *orig_node) | 642 | const struct batadv_orig_node *orig_node) |
633 | { | 643 | { |
634 | struct batadv_tt_orig_list_entry *tmp_orig_entry; | 644 | struct batadv_tt_orig_list_entry *tmp_orig_entry, *orig_entry = NULL; |
635 | const struct hlist_head *head; | 645 | const struct hlist_head *head; |
636 | struct hlist_node *node; | 646 | struct hlist_node *node; |
637 | bool found = false; | ||
638 | 647 | ||
639 | rcu_read_lock(); | 648 | rcu_read_lock(); |
640 | head = &entry->orig_list; | 649 | head = &entry->orig_list; |
641 | hlist_for_each_entry_rcu(tmp_orig_entry, node, head, list) { | 650 | hlist_for_each_entry_rcu(tmp_orig_entry, node, head, list) { |
642 | if (tmp_orig_entry->orig_node == orig_node) { | 651 | if (tmp_orig_entry->orig_node != orig_node) |
643 | found = true; | 652 | continue; |
644 | break; | 653 | if (!atomic_inc_not_zero(&tmp_orig_entry->refcount)) |
645 | } | 654 | continue; |
655 | |||
656 | orig_entry = tmp_orig_entry; | ||
657 | break; | ||
646 | } | 658 | } |
647 | rcu_read_unlock(); | 659 | rcu_read_unlock(); |
660 | |||
661 | return orig_entry; | ||
662 | } | ||
663 | |||
664 | /* find out if an orig_node is already in the list of a tt_global_entry. | ||
665 | * returns true if found, false otherwise | ||
666 | */ | ||
667 | static bool | ||
668 | batadv_tt_global_entry_has_orig(const struct batadv_tt_global_entry *entry, | ||
669 | const struct batadv_orig_node *orig_node) | ||
670 | { | ||
671 | struct batadv_tt_orig_list_entry *orig_entry; | ||
672 | bool found = false; | ||
673 | |||
674 | orig_entry = batadv_tt_global_orig_entry_find(entry, orig_node); | ||
675 | if (orig_entry) { | ||
676 | found = true; | ||
677 | batadv_tt_orig_list_entry_free_ref(orig_entry); | ||
678 | } | ||
679 | |||
648 | return found; | 680 | return found; |
649 | } | 681 | } |
650 | 682 | ||
651 | static void | 683 | static void |
652 | batadv_tt_global_add_orig_entry(struct batadv_tt_global_entry *tt_global_entry, | 684 | batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global, |
653 | struct batadv_orig_node *orig_node, int ttvn) | 685 | struct batadv_orig_node *orig_node, int ttvn) |
654 | { | 686 | { |
655 | struct batadv_tt_orig_list_entry *orig_entry; | 687 | struct batadv_tt_orig_list_entry *orig_entry; |
656 | 688 | ||
689 | orig_entry = batadv_tt_global_orig_entry_find(tt_global, orig_node); | ||
690 | if (orig_entry) { | ||
691 | /* refresh the ttvn: the current value could be a bogus one that | ||
692 | * was added during a "temporary client detection" | ||
693 | */ | ||
694 | orig_entry->ttvn = ttvn; | ||
695 | goto out; | ||
696 | } | ||
697 | |||
657 | orig_entry = kzalloc(sizeof(*orig_entry), GFP_ATOMIC); | 698 | orig_entry = kzalloc(sizeof(*orig_entry), GFP_ATOMIC); |
658 | if (!orig_entry) | 699 | if (!orig_entry) |
659 | return; | 700 | goto out; |
660 | 701 | ||
661 | INIT_HLIST_NODE(&orig_entry->list); | 702 | INIT_HLIST_NODE(&orig_entry->list); |
662 | atomic_inc(&orig_node->refcount); | 703 | atomic_inc(&orig_node->refcount); |
663 | atomic_inc(&orig_node->tt_size); | 704 | atomic_inc(&orig_node->tt_size); |
664 | orig_entry->orig_node = orig_node; | 705 | orig_entry->orig_node = orig_node; |
665 | orig_entry->ttvn = ttvn; | 706 | orig_entry->ttvn = ttvn; |
707 | atomic_set(&orig_entry->refcount, 2); | ||
666 | 708 | ||
667 | spin_lock_bh(&tt_global_entry->list_lock); | 709 | spin_lock_bh(&tt_global->list_lock); |
668 | hlist_add_head_rcu(&orig_entry->list, | 710 | hlist_add_head_rcu(&orig_entry->list, |
669 | &tt_global_entry->orig_list); | 711 | &tt_global->orig_list); |
670 | spin_unlock_bh(&tt_global_entry->list_lock); | 712 | spin_unlock_bh(&tt_global->list_lock); |
713 | out: | ||
714 | if (orig_entry) | ||
715 | batadv_tt_orig_list_entry_free_ref(orig_entry); | ||
671 | } | 716 | } |
672 | 717 | ||
673 | /* caller must hold orig_node refcount */ | 718 | /* caller must hold orig_node refcount */ |
@@ -694,11 +739,12 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv, | |||
694 | common->flags = flags; | 739 | common->flags = flags; |
695 | tt_global_entry->roam_at = 0; | 740 | tt_global_entry->roam_at = 0; |
696 | atomic_set(&common->refcount, 2); | 741 | atomic_set(&common->refcount, 2); |
742 | common->added_at = jiffies; | ||
697 | 743 | ||
698 | INIT_HLIST_HEAD(&tt_global_entry->orig_list); | 744 | INIT_HLIST_HEAD(&tt_global_entry->orig_list); |
699 | spin_lock_init(&tt_global_entry->list_lock); | 745 | spin_lock_init(&tt_global_entry->list_lock); |
700 | 746 | ||
701 | hash_added = batadv_hash_add(bat_priv->tt_global_hash, | 747 | hash_added = batadv_hash_add(bat_priv->tt.global_hash, |
702 | batadv_compare_tt, | 748 | batadv_compare_tt, |
703 | batadv_choose_orig, common, | 749 | batadv_choose_orig, common, |
704 | &common->hash_entry); | 750 | &common->hash_entry); |
@@ -708,11 +754,20 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv, | |||
708 | batadv_tt_global_entry_free_ref(tt_global_entry); | 754 | batadv_tt_global_entry_free_ref(tt_global_entry); |
709 | goto out_remove; | 755 | goto out_remove; |
710 | } | 756 | } |
711 | |||
712 | batadv_tt_global_add_orig_entry(tt_global_entry, orig_node, | ||
713 | ttvn); | ||
714 | } else { | 757 | } else { |
715 | /* there is already a global entry, use this one. */ | 758 | /* If there is already a global entry, we can use this one for |
759 | * our processing. | ||
760 | * But if we are trying to add a temporary client we can exit | ||
761 | * directly because the temporary information should never | ||
762 | * override any already known client state (whatever it is) | ||
763 | */ | ||
764 | if (flags & BATADV_TT_CLIENT_TEMP) | ||
765 | goto out; | ||
766 | |||
767 | /* if the client was temporary added before receiving the first | ||
768 | * OGM announcing it, we have to clear the TEMP flag | ||
769 | */ | ||
770 | tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_TEMP; | ||
716 | 771 | ||
717 | /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only | 772 | /* If there is the BATADV_TT_CLIENT_ROAM flag set, there is only |
718 | * one originator left in the list and we previously received a | 773 | * one originator left in the list and we previously received a |
@@ -726,12 +781,9 @@ int batadv_tt_global_add(struct batadv_priv *bat_priv, | |||
726 | tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM; | 781 | tt_global_entry->common.flags &= ~BATADV_TT_CLIENT_ROAM; |
727 | tt_global_entry->roam_at = 0; | 782 | tt_global_entry->roam_at = 0; |
728 | } | 783 | } |
729 | |||
730 | if (!batadv_tt_global_entry_has_orig(tt_global_entry, | ||
731 | orig_node)) | ||
732 | batadv_tt_global_add_orig_entry(tt_global_entry, | ||
733 | orig_node, ttvn); | ||
734 | } | 784 | } |
785 | /* add the new orig_entry (if needed) or update it */ | ||
786 | batadv_tt_global_orig_entry_add(tt_global_entry, orig_node, ttvn); | ||
735 | 787 | ||
736 | batadv_dbg(BATADV_DBG_TT, bat_priv, | 788 | batadv_dbg(BATADV_DBG_TT, bat_priv, |
737 | "Creating new global tt entry: %pM (via %pM)\n", | 789 | "Creating new global tt entry: %pM (via %pM)\n", |
@@ -770,11 +822,12 @@ batadv_tt_global_print_entry(struct batadv_tt_global_entry *tt_global_entry, | |||
770 | hlist_for_each_entry_rcu(orig_entry, node, head, list) { | 822 | hlist_for_each_entry_rcu(orig_entry, node, head, list) { |
771 | flags = tt_common_entry->flags; | 823 | flags = tt_common_entry->flags; |
772 | last_ttvn = atomic_read(&orig_entry->orig_node->last_ttvn); | 824 | last_ttvn = atomic_read(&orig_entry->orig_node->last_ttvn); |
773 | seq_printf(seq, " * %pM (%3u) via %pM (%3u) [%c%c]\n", | 825 | seq_printf(seq, " * %pM (%3u) via %pM (%3u) [%c%c%c]\n", |
774 | tt_global_entry->common.addr, orig_entry->ttvn, | 826 | tt_global_entry->common.addr, orig_entry->ttvn, |
775 | orig_entry->orig_node->orig, last_ttvn, | 827 | orig_entry->orig_node->orig, last_ttvn, |
776 | (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'), | 828 | (flags & BATADV_TT_CLIENT_ROAM ? 'R' : '.'), |
777 | (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.')); | 829 | (flags & BATADV_TT_CLIENT_WIFI ? 'W' : '.'), |
830 | (flags & BATADV_TT_CLIENT_TEMP ? 'T' : '.')); | ||
778 | } | 831 | } |
779 | } | 832 | } |
780 | 833 | ||
@@ -782,7 +835,7 @@ int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset) | |||
782 | { | 835 | { |
783 | struct net_device *net_dev = (struct net_device *)seq->private; | 836 | struct net_device *net_dev = (struct net_device *)seq->private; |
784 | struct batadv_priv *bat_priv = netdev_priv(net_dev); | 837 | struct batadv_priv *bat_priv = netdev_priv(net_dev); |
785 | struct batadv_hashtable *hash = bat_priv->tt_global_hash; | 838 | struct batadv_hashtable *hash = bat_priv->tt.global_hash; |
786 | struct batadv_tt_common_entry *tt_common_entry; | 839 | struct batadv_tt_common_entry *tt_common_entry; |
787 | struct batadv_tt_global_entry *tt_global; | 840 | struct batadv_tt_global_entry *tt_global; |
788 | struct batadv_hard_iface *primary_if; | 841 | struct batadv_hard_iface *primary_if; |
@@ -883,7 +936,7 @@ batadv_tt_global_del_struct(struct batadv_priv *bat_priv, | |||
883 | "Deleting global tt entry %pM: %s\n", | 936 | "Deleting global tt entry %pM: %s\n", |
884 | tt_global_entry->common.addr, message); | 937 | tt_global_entry->common.addr, message); |
885 | 938 | ||
886 | batadv_hash_remove(bat_priv->tt_global_hash, batadv_compare_tt, | 939 | batadv_hash_remove(bat_priv->tt.global_hash, batadv_compare_tt, |
887 | batadv_choose_orig, tt_global_entry->common.addr); | 940 | batadv_choose_orig, tt_global_entry->common.addr); |
888 | batadv_tt_global_entry_free_ref(tt_global_entry); | 941 | batadv_tt_global_entry_free_ref(tt_global_entry); |
889 | 942 | ||
@@ -994,7 +1047,7 @@ void batadv_tt_global_del_orig(struct batadv_priv *bat_priv, | |||
994 | struct batadv_tt_global_entry *tt_global; | 1047 | struct batadv_tt_global_entry *tt_global; |
995 | struct batadv_tt_common_entry *tt_common_entry; | 1048 | struct batadv_tt_common_entry *tt_common_entry; |
996 | uint32_t i; | 1049 | uint32_t i; |
997 | struct batadv_hashtable *hash = bat_priv->tt_global_hash; | 1050 | struct batadv_hashtable *hash = bat_priv->tt.global_hash; |
998 | struct hlist_node *node, *safe; | 1051 | struct hlist_node *node, *safe; |
999 | struct hlist_head *head; | 1052 | struct hlist_head *head; |
1000 | spinlock_t *list_lock; /* protects write access to the hash lists */ | 1053 | spinlock_t *list_lock; /* protects write access to the hash lists */ |
@@ -1029,49 +1082,63 @@ void batadv_tt_global_del_orig(struct batadv_priv *bat_priv, | |||
1029 | orig_node->tt_initialised = false; | 1082 | orig_node->tt_initialised = false; |
1030 | } | 1083 | } |
1031 | 1084 | ||
1032 | static void batadv_tt_global_roam_purge_list(struct batadv_priv *bat_priv, | 1085 | static bool batadv_tt_global_to_purge(struct batadv_tt_global_entry *tt_global, |
1033 | struct hlist_head *head) | 1086 | char **msg) |
1034 | { | 1087 | { |
1035 | struct batadv_tt_common_entry *tt_common_entry; | 1088 | bool purge = false; |
1036 | struct batadv_tt_global_entry *tt_global_entry; | 1089 | unsigned long roam_timeout = BATADV_TT_CLIENT_ROAM_TIMEOUT; |
1037 | struct hlist_node *node, *node_tmp; | 1090 | unsigned long temp_timeout = BATADV_TT_CLIENT_TEMP_TIMEOUT; |
1038 | |||
1039 | hlist_for_each_entry_safe(tt_common_entry, node, node_tmp, head, | ||
1040 | hash_entry) { | ||
1041 | tt_global_entry = container_of(tt_common_entry, | ||
1042 | struct batadv_tt_global_entry, | ||
1043 | common); | ||
1044 | if (!(tt_global_entry->common.flags & BATADV_TT_CLIENT_ROAM)) | ||
1045 | continue; | ||
1046 | if (!batadv_has_timed_out(tt_global_entry->roam_at, | ||
1047 | BATADV_TT_CLIENT_ROAM_TIMEOUT)) | ||
1048 | continue; | ||
1049 | 1091 | ||
1050 | batadv_dbg(BATADV_DBG_TT, bat_priv, | 1092 | if ((tt_global->common.flags & BATADV_TT_CLIENT_ROAM) && |
1051 | "Deleting global tt entry (%pM): Roaming timeout\n", | 1093 | batadv_has_timed_out(tt_global->roam_at, roam_timeout)) { |
1052 | tt_global_entry->common.addr); | 1094 | purge = true; |
1095 | *msg = "Roaming timeout\n"; | ||
1096 | } | ||
1053 | 1097 | ||
1054 | hlist_del_rcu(node); | 1098 | if ((tt_global->common.flags & BATADV_TT_CLIENT_TEMP) && |
1055 | batadv_tt_global_entry_free_ref(tt_global_entry); | 1099 | batadv_has_timed_out(tt_global->common.added_at, temp_timeout)) { |
1100 | purge = true; | ||
1101 | *msg = "Temporary client timeout\n"; | ||
1056 | } | 1102 | } |
1103 | |||
1104 | return purge; | ||
1057 | } | 1105 | } |
1058 | 1106 | ||
1059 | static void batadv_tt_global_roam_purge(struct batadv_priv *bat_priv) | 1107 | static void batadv_tt_global_purge(struct batadv_priv *bat_priv) |
1060 | { | 1108 | { |
1061 | struct batadv_hashtable *hash = bat_priv->tt_global_hash; | 1109 | struct batadv_hashtable *hash = bat_priv->tt.global_hash; |
1062 | struct hlist_head *head; | 1110 | struct hlist_head *head; |
1111 | struct hlist_node *node, *node_tmp; | ||
1063 | spinlock_t *list_lock; /* protects write access to the hash lists */ | 1112 | spinlock_t *list_lock; /* protects write access to the hash lists */ |
1064 | uint32_t i; | 1113 | uint32_t i; |
1114 | char *msg = NULL; | ||
1115 | struct batadv_tt_common_entry *tt_common; | ||
1116 | struct batadv_tt_global_entry *tt_global; | ||
1065 | 1117 | ||
1066 | for (i = 0; i < hash->size; i++) { | 1118 | for (i = 0; i < hash->size; i++) { |
1067 | head = &hash->table[i]; | 1119 | head = &hash->table[i]; |
1068 | list_lock = &hash->list_locks[i]; | 1120 | list_lock = &hash->list_locks[i]; |
1069 | 1121 | ||
1070 | spin_lock_bh(list_lock); | 1122 | spin_lock_bh(list_lock); |
1071 | batadv_tt_global_roam_purge_list(bat_priv, head); | 1123 | hlist_for_each_entry_safe(tt_common, node, node_tmp, head, |
1124 | hash_entry) { | ||
1125 | tt_global = container_of(tt_common, | ||
1126 | struct batadv_tt_global_entry, | ||
1127 | common); | ||
1128 | |||
1129 | if (!batadv_tt_global_to_purge(tt_global, &msg)) | ||
1130 | continue; | ||
1131 | |||
1132 | batadv_dbg(BATADV_DBG_TT, bat_priv, | ||
1133 | "Deleting global tt entry (%pM): %s\n", | ||
1134 | tt_global->common.addr, msg); | ||
1135 | |||
1136 | hlist_del_rcu(node); | ||
1137 | |||
1138 | batadv_tt_global_entry_free_ref(tt_global); | ||
1139 | } | ||
1072 | spin_unlock_bh(list_lock); | 1140 | spin_unlock_bh(list_lock); |
1073 | } | 1141 | } |
1074 | |||
1075 | } | 1142 | } |
1076 | 1143 | ||
1077 | static void batadv_tt_global_table_free(struct batadv_priv *bat_priv) | 1144 | static void batadv_tt_global_table_free(struct batadv_priv *bat_priv) |
@@ -1084,10 +1151,10 @@ static void batadv_tt_global_table_free(struct batadv_priv *bat_priv) | |||
1084 | struct hlist_head *head; | 1151 | struct hlist_head *head; |
1085 | uint32_t i; | 1152 | uint32_t i; |
1086 | 1153 | ||
1087 | if (!bat_priv->tt_global_hash) | 1154 | if (!bat_priv->tt.global_hash) |
1088 | return; | 1155 | return; |
1089 | 1156 | ||
1090 | hash = bat_priv->tt_global_hash; | 1157 | hash = bat_priv->tt.global_hash; |
1091 | 1158 | ||
1092 | for (i = 0; i < hash->size; i++) { | 1159 | for (i = 0; i < hash->size; i++) { |
1093 | head = &hash->table[i]; | 1160 | head = &hash->table[i]; |
@@ -1107,7 +1174,7 @@ static void batadv_tt_global_table_free(struct batadv_priv *bat_priv) | |||
1107 | 1174 | ||
1108 | batadv_hash_destroy(hash); | 1175 | batadv_hash_destroy(hash); |
1109 | 1176 | ||
1110 | bat_priv->tt_global_hash = NULL; | 1177 | bat_priv->tt.global_hash = NULL; |
1111 | } | 1178 | } |
1112 | 1179 | ||
1113 | static bool | 1180 | static bool |
@@ -1186,7 +1253,7 @@ static uint16_t batadv_tt_global_crc(struct batadv_priv *bat_priv, | |||
1186 | struct batadv_orig_node *orig_node) | 1253 | struct batadv_orig_node *orig_node) |
1187 | { | 1254 | { |
1188 | uint16_t total = 0, total_one; | 1255 | uint16_t total = 0, total_one; |
1189 | struct batadv_hashtable *hash = bat_priv->tt_global_hash; | 1256 | struct batadv_hashtable *hash = bat_priv->tt.global_hash; |
1190 | struct batadv_tt_common_entry *tt_common; | 1257 | struct batadv_tt_common_entry *tt_common; |
1191 | struct batadv_tt_global_entry *tt_global; | 1258 | struct batadv_tt_global_entry *tt_global; |
1192 | struct hlist_node *node; | 1259 | struct hlist_node *node; |
@@ -1209,6 +1276,12 @@ static uint16_t batadv_tt_global_crc(struct batadv_priv *bat_priv, | |||
1209 | */ | 1276 | */ |
1210 | if (tt_common->flags & BATADV_TT_CLIENT_ROAM) | 1277 | if (tt_common->flags & BATADV_TT_CLIENT_ROAM) |
1211 | continue; | 1278 | continue; |
1279 | /* Temporary clients have not been announced yet, so | ||
1280 | * they have to be skipped while computing the global | ||
1281 | * crc | ||
1282 | */ | ||
1283 | if (tt_common->flags & BATADV_TT_CLIENT_TEMP) | ||
1284 | continue; | ||
1212 | 1285 | ||
1213 | /* find out if this global entry is announced by this | 1286 | /* find out if this global entry is announced by this |
1214 | * originator | 1287 | * originator |
@@ -1233,7 +1306,7 @@ static uint16_t batadv_tt_global_crc(struct batadv_priv *bat_priv, | |||
1233 | static uint16_t batadv_tt_local_crc(struct batadv_priv *bat_priv) | 1306 | static uint16_t batadv_tt_local_crc(struct batadv_priv *bat_priv) |
1234 | { | 1307 | { |
1235 | uint16_t total = 0, total_one; | 1308 | uint16_t total = 0, total_one; |
1236 | struct batadv_hashtable *hash = bat_priv->tt_local_hash; | 1309 | struct batadv_hashtable *hash = bat_priv->tt.local_hash; |
1237 | struct batadv_tt_common_entry *tt_common; | 1310 | struct batadv_tt_common_entry *tt_common; |
1238 | struct hlist_node *node; | 1311 | struct hlist_node *node; |
1239 | struct hlist_head *head; | 1312 | struct hlist_head *head; |
@@ -1266,14 +1339,14 @@ static void batadv_tt_req_list_free(struct batadv_priv *bat_priv) | |||
1266 | { | 1339 | { |
1267 | struct batadv_tt_req_node *node, *safe; | 1340 | struct batadv_tt_req_node *node, *safe; |
1268 | 1341 | ||
1269 | spin_lock_bh(&bat_priv->tt_req_list_lock); | 1342 | spin_lock_bh(&bat_priv->tt.req_list_lock); |
1270 | 1343 | ||
1271 | list_for_each_entry_safe(node, safe, &bat_priv->tt_req_list, list) { | 1344 | list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) { |
1272 | list_del(&node->list); | 1345 | list_del(&node->list); |
1273 | kfree(node); | 1346 | kfree(node); |
1274 | } | 1347 | } |
1275 | 1348 | ||
1276 | spin_unlock_bh(&bat_priv->tt_req_list_lock); | 1349 | spin_unlock_bh(&bat_priv->tt.req_list_lock); |
1277 | } | 1350 | } |
1278 | 1351 | ||
1279 | static void batadv_tt_save_orig_buffer(struct batadv_priv *bat_priv, | 1352 | static void batadv_tt_save_orig_buffer(struct batadv_priv *bat_priv, |
@@ -1303,15 +1376,15 @@ static void batadv_tt_req_purge(struct batadv_priv *bat_priv) | |||
1303 | { | 1376 | { |
1304 | struct batadv_tt_req_node *node, *safe; | 1377 | struct batadv_tt_req_node *node, *safe; |
1305 | 1378 | ||
1306 | spin_lock_bh(&bat_priv->tt_req_list_lock); | 1379 | spin_lock_bh(&bat_priv->tt.req_list_lock); |
1307 | list_for_each_entry_safe(node, safe, &bat_priv->tt_req_list, list) { | 1380 | list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) { |
1308 | if (batadv_has_timed_out(node->issued_at, | 1381 | if (batadv_has_timed_out(node->issued_at, |
1309 | BATADV_TT_REQUEST_TIMEOUT)) { | 1382 | BATADV_TT_REQUEST_TIMEOUT)) { |
1310 | list_del(&node->list); | 1383 | list_del(&node->list); |
1311 | kfree(node); | 1384 | kfree(node); |
1312 | } | 1385 | } |
1313 | } | 1386 | } |
1314 | spin_unlock_bh(&bat_priv->tt_req_list_lock); | 1387 | spin_unlock_bh(&bat_priv->tt.req_list_lock); |
1315 | } | 1388 | } |
1316 | 1389 | ||
1317 | /* returns the pointer to the new tt_req_node struct if no request | 1390 | /* returns the pointer to the new tt_req_node struct if no request |
@@ -1323,8 +1396,8 @@ batadv_new_tt_req_node(struct batadv_priv *bat_priv, | |||
1323 | { | 1396 | { |
1324 | struct batadv_tt_req_node *tt_req_node_tmp, *tt_req_node = NULL; | 1397 | struct batadv_tt_req_node *tt_req_node_tmp, *tt_req_node = NULL; |
1325 | 1398 | ||
1326 | spin_lock_bh(&bat_priv->tt_req_list_lock); | 1399 | spin_lock_bh(&bat_priv->tt.req_list_lock); |
1327 | list_for_each_entry(tt_req_node_tmp, &bat_priv->tt_req_list, list) { | 1400 | list_for_each_entry(tt_req_node_tmp, &bat_priv->tt.req_list, list) { |
1328 | if (batadv_compare_eth(tt_req_node_tmp, orig_node) && | 1401 | if (batadv_compare_eth(tt_req_node_tmp, orig_node) && |
1329 | !batadv_has_timed_out(tt_req_node_tmp->issued_at, | 1402 | !batadv_has_timed_out(tt_req_node_tmp->issued_at, |
1330 | BATADV_TT_REQUEST_TIMEOUT)) | 1403 | BATADV_TT_REQUEST_TIMEOUT)) |
@@ -1338,9 +1411,9 @@ batadv_new_tt_req_node(struct batadv_priv *bat_priv, | |||
1338 | memcpy(tt_req_node->addr, orig_node->orig, ETH_ALEN); | 1411 | memcpy(tt_req_node->addr, orig_node->orig, ETH_ALEN); |
1339 | tt_req_node->issued_at = jiffies; | 1412 | tt_req_node->issued_at = jiffies; |
1340 | 1413 | ||
1341 | list_add(&tt_req_node->list, &bat_priv->tt_req_list); | 1414 | list_add(&tt_req_node->list, &bat_priv->tt.req_list); |
1342 | unlock: | 1415 | unlock: |
1343 | spin_unlock_bh(&bat_priv->tt_req_list_lock); | 1416 | spin_unlock_bh(&bat_priv->tt.req_list_lock); |
1344 | return tt_req_node; | 1417 | return tt_req_node; |
1345 | } | 1418 | } |
1346 | 1419 | ||
@@ -1362,7 +1435,8 @@ static int batadv_tt_global_valid(const void *entry_ptr, | |||
1362 | const struct batadv_tt_global_entry *tt_global_entry; | 1435 | const struct batadv_tt_global_entry *tt_global_entry; |
1363 | const struct batadv_orig_node *orig_node = data_ptr; | 1436 | const struct batadv_orig_node *orig_node = data_ptr; |
1364 | 1437 | ||
1365 | if (tt_common_entry->flags & BATADV_TT_CLIENT_ROAM) | 1438 | if (tt_common_entry->flags & BATADV_TT_CLIENT_ROAM || |
1439 | tt_common_entry->flags & BATADV_TT_CLIENT_TEMP) | ||
1366 | return 0; | 1440 | return 0; |
1367 | 1441 | ||
1368 | tt_global_entry = container_of(tt_common_entry, | 1442 | tt_global_entry = container_of(tt_common_entry, |
@@ -1506,9 +1580,9 @@ out: | |||
1506 | if (ret) | 1580 | if (ret) |
1507 | kfree_skb(skb); | 1581 | kfree_skb(skb); |
1508 | if (ret && tt_req_node) { | 1582 | if (ret && tt_req_node) { |
1509 | spin_lock_bh(&bat_priv->tt_req_list_lock); | 1583 | spin_lock_bh(&bat_priv->tt.req_list_lock); |
1510 | list_del(&tt_req_node->list); | 1584 | list_del(&tt_req_node->list); |
1511 | spin_unlock_bh(&bat_priv->tt_req_list_lock); | 1585 | spin_unlock_bh(&bat_priv->tt.req_list_lock); |
1512 | kfree(tt_req_node); | 1586 | kfree(tt_req_node); |
1513 | } | 1587 | } |
1514 | return ret; | 1588 | return ret; |
@@ -1529,6 +1603,7 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv, | |||
1529 | uint16_t tt_len, tt_tot; | 1603 | uint16_t tt_len, tt_tot; |
1530 | struct sk_buff *skb = NULL; | 1604 | struct sk_buff *skb = NULL; |
1531 | struct batadv_tt_query_packet *tt_response; | 1605 | struct batadv_tt_query_packet *tt_response; |
1606 | uint8_t *packet_pos; | ||
1532 | size_t len; | 1607 | size_t len; |
1533 | 1608 | ||
1534 | batadv_dbg(BATADV_DBG_TT, bat_priv, | 1609 | batadv_dbg(BATADV_DBG_TT, bat_priv, |
@@ -1582,8 +1657,8 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv, | |||
1582 | goto unlock; | 1657 | goto unlock; |
1583 | 1658 | ||
1584 | skb_reserve(skb, ETH_HLEN); | 1659 | skb_reserve(skb, ETH_HLEN); |
1585 | tt_response = (struct batadv_tt_query_packet *)skb_put(skb, | 1660 | packet_pos = skb_put(skb, len); |
1586 | len); | 1661 | tt_response = (struct batadv_tt_query_packet *)packet_pos; |
1587 | tt_response->ttvn = req_ttvn; | 1662 | tt_response->ttvn = req_ttvn; |
1588 | tt_response->tt_data = htons(tt_tot); | 1663 | tt_response->tt_data = htons(tt_tot); |
1589 | 1664 | ||
@@ -1599,7 +1674,7 @@ batadv_send_other_tt_response(struct batadv_priv *bat_priv, | |||
1599 | ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn); | 1674 | ttvn = (uint8_t)atomic_read(&req_dst_orig_node->last_ttvn); |
1600 | 1675 | ||
1601 | skb = batadv_tt_response_fill_table(tt_len, ttvn, | 1676 | skb = batadv_tt_response_fill_table(tt_len, ttvn, |
1602 | bat_priv->tt_global_hash, | 1677 | bat_priv->tt.global_hash, |
1603 | primary_if, | 1678 | primary_if, |
1604 | batadv_tt_global_valid, | 1679 | batadv_tt_global_valid, |
1605 | req_dst_orig_node); | 1680 | req_dst_orig_node); |
@@ -1662,6 +1737,7 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv, | |||
1662 | uint16_t tt_len, tt_tot; | 1737 | uint16_t tt_len, tt_tot; |
1663 | struct sk_buff *skb = NULL; | 1738 | struct sk_buff *skb = NULL; |
1664 | struct batadv_tt_query_packet *tt_response; | 1739 | struct batadv_tt_query_packet *tt_response; |
1740 | uint8_t *packet_pos; | ||
1665 | size_t len; | 1741 | size_t len; |
1666 | 1742 | ||
1667 | batadv_dbg(BATADV_DBG_TT, bat_priv, | 1743 | batadv_dbg(BATADV_DBG_TT, bat_priv, |
@@ -1670,7 +1746,7 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv, | |||
1670 | (tt_request->flags & BATADV_TT_FULL_TABLE ? 'F' : '.')); | 1746 | (tt_request->flags & BATADV_TT_FULL_TABLE ? 'F' : '.')); |
1671 | 1747 | ||
1672 | 1748 | ||
1673 | my_ttvn = (uint8_t)atomic_read(&bat_priv->ttvn); | 1749 | my_ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); |
1674 | req_ttvn = tt_request->ttvn; | 1750 | req_ttvn = tt_request->ttvn; |
1675 | 1751 | ||
1676 | orig_node = batadv_orig_hash_find(bat_priv, tt_request->src); | 1752 | orig_node = batadv_orig_hash_find(bat_priv, tt_request->src); |
@@ -1689,7 +1765,7 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv, | |||
1689 | * is too big send the whole local translation table | 1765 | * is too big send the whole local translation table |
1690 | */ | 1766 | */ |
1691 | if (tt_request->flags & BATADV_TT_FULL_TABLE || my_ttvn != req_ttvn || | 1767 | if (tt_request->flags & BATADV_TT_FULL_TABLE || my_ttvn != req_ttvn || |
1692 | !bat_priv->tt_buff) | 1768 | !bat_priv->tt.last_changeset) |
1693 | full_table = true; | 1769 | full_table = true; |
1694 | else | 1770 | else |
1695 | full_table = false; | 1771 | full_table = false; |
@@ -1698,8 +1774,8 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv, | |||
1698 | * I'll send only one packet with as much TT entries as I can | 1774 | * I'll send only one packet with as much TT entries as I can |
1699 | */ | 1775 | */ |
1700 | if (!full_table) { | 1776 | if (!full_table) { |
1701 | spin_lock_bh(&bat_priv->tt_buff_lock); | 1777 | spin_lock_bh(&bat_priv->tt.last_changeset_lock); |
1702 | tt_len = bat_priv->tt_buff_len; | 1778 | tt_len = bat_priv->tt.last_changeset_len; |
1703 | tt_tot = tt_len / sizeof(struct batadv_tt_change); | 1779 | tt_tot = tt_len / sizeof(struct batadv_tt_change); |
1704 | 1780 | ||
1705 | len = sizeof(*tt_response) + tt_len; | 1781 | len = sizeof(*tt_response) + tt_len; |
@@ -1708,22 +1784,22 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv, | |||
1708 | goto unlock; | 1784 | goto unlock; |
1709 | 1785 | ||
1710 | skb_reserve(skb, ETH_HLEN); | 1786 | skb_reserve(skb, ETH_HLEN); |
1711 | tt_response = (struct batadv_tt_query_packet *)skb_put(skb, | 1787 | packet_pos = skb_put(skb, len); |
1712 | len); | 1788 | tt_response = (struct batadv_tt_query_packet *)packet_pos; |
1713 | tt_response->ttvn = req_ttvn; | 1789 | tt_response->ttvn = req_ttvn; |
1714 | tt_response->tt_data = htons(tt_tot); | 1790 | tt_response->tt_data = htons(tt_tot); |
1715 | 1791 | ||
1716 | tt_buff = skb->data + sizeof(*tt_response); | 1792 | tt_buff = skb->data + sizeof(*tt_response); |
1717 | memcpy(tt_buff, bat_priv->tt_buff, | 1793 | memcpy(tt_buff, bat_priv->tt.last_changeset, |
1718 | bat_priv->tt_buff_len); | 1794 | bat_priv->tt.last_changeset_len); |
1719 | spin_unlock_bh(&bat_priv->tt_buff_lock); | 1795 | spin_unlock_bh(&bat_priv->tt.last_changeset_lock); |
1720 | } else { | 1796 | } else { |
1721 | tt_len = (uint16_t)atomic_read(&bat_priv->num_local_tt); | 1797 | tt_len = (uint16_t)atomic_read(&bat_priv->tt.local_entry_num); |
1722 | tt_len *= sizeof(struct batadv_tt_change); | 1798 | tt_len *= sizeof(struct batadv_tt_change); |
1723 | ttvn = (uint8_t)atomic_read(&bat_priv->ttvn); | 1799 | ttvn = (uint8_t)atomic_read(&bat_priv->tt.vn); |
1724 | 1800 | ||
1725 | skb = batadv_tt_response_fill_table(tt_len, ttvn, | 1801 | skb = batadv_tt_response_fill_table(tt_len, ttvn, |
1726 | bat_priv->tt_local_hash, | 1802 | bat_priv->tt.local_hash, |
1727 | primary_if, | 1803 | primary_if, |
1728 | batadv_tt_local_valid_entry, | 1804 | batadv_tt_local_valid_entry, |
1729 | NULL); | 1805 | NULL); |
@@ -1755,7 +1831,7 @@ batadv_send_my_tt_response(struct batadv_priv *bat_priv, | |||
1755 | goto out; | 1831 | goto out; |
1756 | 1832 | ||
1757 | unlock: | 1833 | unlock: |
1758 | spin_unlock_bh(&bat_priv->tt_buff_lock); | 1834 | spin_unlock_bh(&bat_priv->tt.last_changeset_lock); |
1759 | out: | 1835 | out: |
1760 | if (orig_node) | 1836 | if (orig_node) |
1761 | batadv_orig_node_free_ref(orig_node); | 1837 | batadv_orig_node_free_ref(orig_node); |
@@ -1908,14 +1984,14 @@ void batadv_handle_tt_response(struct batadv_priv *bat_priv, | |||
1908 | } | 1984 | } |
1909 | 1985 | ||
1910 | /* Delete the tt_req_node from pending tt_requests list */ | 1986 | /* Delete the tt_req_node from pending tt_requests list */ |
1911 | spin_lock_bh(&bat_priv->tt_req_list_lock); | 1987 | spin_lock_bh(&bat_priv->tt.req_list_lock); |
1912 | list_for_each_entry_safe(node, safe, &bat_priv->tt_req_list, list) { | 1988 | list_for_each_entry_safe(node, safe, &bat_priv->tt.req_list, list) { |
1913 | if (!batadv_compare_eth(node->addr, tt_response->src)) | 1989 | if (!batadv_compare_eth(node->addr, tt_response->src)) |
1914 | continue; | 1990 | continue; |
1915 | list_del(&node->list); | 1991 | list_del(&node->list); |
1916 | kfree(node); | 1992 | kfree(node); |
1917 | } | 1993 | } |
1918 | spin_unlock_bh(&bat_priv->tt_req_list_lock); | 1994 | spin_unlock_bh(&bat_priv->tt.req_list_lock); |
1919 | 1995 | ||
1920 | /* Recalculate the CRC for this orig_node and store it */ | 1996 | /* Recalculate the CRC for this orig_node and store it */ |
1921 | orig_node->tt_crc = batadv_tt_global_crc(bat_priv, orig_node); | 1997 | orig_node->tt_crc = batadv_tt_global_crc(bat_priv, orig_node); |
@@ -1949,22 +2025,22 @@ static void batadv_tt_roam_list_free(struct batadv_priv *bat_priv) | |||
1949 | { | 2025 | { |
1950 | struct batadv_tt_roam_node *node, *safe; | 2026 | struct batadv_tt_roam_node *node, *safe; |
1951 | 2027 | ||
1952 | spin_lock_bh(&bat_priv->tt_roam_list_lock); | 2028 | spin_lock_bh(&bat_priv->tt.roam_list_lock); |
1953 | 2029 | ||
1954 | list_for_each_entry_safe(node, safe, &bat_priv->tt_roam_list, list) { | 2030 | list_for_each_entry_safe(node, safe, &bat_priv->tt.roam_list, list) { |
1955 | list_del(&node->list); | 2031 | list_del(&node->list); |
1956 | kfree(node); | 2032 | kfree(node); |
1957 | } | 2033 | } |
1958 | 2034 | ||
1959 | spin_unlock_bh(&bat_priv->tt_roam_list_lock); | 2035 | spin_unlock_bh(&bat_priv->tt.roam_list_lock); |
1960 | } | 2036 | } |
1961 | 2037 | ||
1962 | static void batadv_tt_roam_purge(struct batadv_priv *bat_priv) | 2038 | static void batadv_tt_roam_purge(struct batadv_priv *bat_priv) |
1963 | { | 2039 | { |
1964 | struct batadv_tt_roam_node *node, *safe; | 2040 | struct batadv_tt_roam_node *node, *safe; |
1965 | 2041 | ||
1966 | spin_lock_bh(&bat_priv->tt_roam_list_lock); | 2042 | spin_lock_bh(&bat_priv->tt.roam_list_lock); |
1967 | list_for_each_entry_safe(node, safe, &bat_priv->tt_roam_list, list) { | 2043 | list_for_each_entry_safe(node, safe, &bat_priv->tt.roam_list, list) { |
1968 | if (!batadv_has_timed_out(node->first_time, | 2044 | if (!batadv_has_timed_out(node->first_time, |
1969 | BATADV_ROAMING_MAX_TIME)) | 2045 | BATADV_ROAMING_MAX_TIME)) |
1970 | continue; | 2046 | continue; |
@@ -1972,7 +2048,7 @@ static void batadv_tt_roam_purge(struct batadv_priv *bat_priv) | |||
1972 | list_del(&node->list); | 2048 | list_del(&node->list); |
1973 | kfree(node); | 2049 | kfree(node); |
1974 | } | 2050 | } |
1975 | spin_unlock_bh(&bat_priv->tt_roam_list_lock); | 2051 | spin_unlock_bh(&bat_priv->tt.roam_list_lock); |
1976 | } | 2052 | } |
1977 | 2053 | ||
1978 | /* This function checks whether the client already reached the | 2054 | /* This function checks whether the client already reached the |
@@ -1987,11 +2063,11 @@ static bool batadv_tt_check_roam_count(struct batadv_priv *bat_priv, | |||
1987 | struct batadv_tt_roam_node *tt_roam_node; | 2063 | struct batadv_tt_roam_node *tt_roam_node; |
1988 | bool ret = false; | 2064 | bool ret = false; |
1989 | 2065 | ||
1990 | spin_lock_bh(&bat_priv->tt_roam_list_lock); | 2066 | spin_lock_bh(&bat_priv->tt.roam_list_lock); |
1991 | /* The new tt_req will be issued only if I'm not waiting for a | 2067 | /* The new tt_req will be issued only if I'm not waiting for a |
1992 | * reply from the same orig_node yet | 2068 | * reply from the same orig_node yet |
1993 | */ | 2069 | */ |
1994 | list_for_each_entry(tt_roam_node, &bat_priv->tt_roam_list, list) { | 2070 | list_for_each_entry(tt_roam_node, &bat_priv->tt.roam_list, list) { |
1995 | if (!batadv_compare_eth(tt_roam_node->addr, client)) | 2071 | if (!batadv_compare_eth(tt_roam_node->addr, client)) |
1996 | continue; | 2072 | continue; |
1997 | 2073 | ||
@@ -2016,12 +2092,12 @@ static bool batadv_tt_check_roam_count(struct batadv_priv *bat_priv, | |||
2016 | BATADV_ROAMING_MAX_COUNT - 1); | 2092 | BATADV_ROAMING_MAX_COUNT - 1); |
2017 | memcpy(tt_roam_node->addr, client, ETH_ALEN); | 2093 | memcpy(tt_roam_node->addr, client, ETH_ALEN); |
2018 | 2094 | ||
2019 | list_add(&tt_roam_node->list, &bat_priv->tt_roam_list); | 2095 | list_add(&tt_roam_node->list, &bat_priv->tt.roam_list); |
2020 | ret = true; | 2096 | ret = true; |
2021 | } | 2097 | } |
2022 | 2098 | ||
2023 | unlock: | 2099 | unlock: |
2024 | spin_unlock_bh(&bat_priv->tt_roam_list_lock); | 2100 | spin_unlock_bh(&bat_priv->tt.roam_list_lock); |
2025 | return ret; | 2101 | return ret; |
2026 | } | 2102 | } |
2027 | 2103 | ||
@@ -2085,13 +2161,15 @@ out: | |||
2085 | static void batadv_tt_purge(struct work_struct *work) | 2161 | static void batadv_tt_purge(struct work_struct *work) |
2086 | { | 2162 | { |
2087 | struct delayed_work *delayed_work; | 2163 | struct delayed_work *delayed_work; |
2164 | struct batadv_priv_tt *priv_tt; | ||
2088 | struct batadv_priv *bat_priv; | 2165 | struct batadv_priv *bat_priv; |
2089 | 2166 | ||
2090 | delayed_work = container_of(work, struct delayed_work, work); | 2167 | delayed_work = container_of(work, struct delayed_work, work); |
2091 | bat_priv = container_of(delayed_work, struct batadv_priv, tt_work); | 2168 | priv_tt = container_of(delayed_work, struct batadv_priv_tt, work); |
2169 | bat_priv = container_of(priv_tt, struct batadv_priv, tt); | ||
2092 | 2170 | ||
2093 | batadv_tt_local_purge(bat_priv); | 2171 | batadv_tt_local_purge(bat_priv); |
2094 | batadv_tt_global_roam_purge(bat_priv); | 2172 | batadv_tt_global_purge(bat_priv); |
2095 | batadv_tt_req_purge(bat_priv); | 2173 | batadv_tt_req_purge(bat_priv); |
2096 | batadv_tt_roam_purge(bat_priv); | 2174 | batadv_tt_roam_purge(bat_priv); |
2097 | 2175 | ||
@@ -2100,7 +2178,7 @@ static void batadv_tt_purge(struct work_struct *work) | |||
2100 | 2178 | ||
2101 | void batadv_tt_free(struct batadv_priv *bat_priv) | 2179 | void batadv_tt_free(struct batadv_priv *bat_priv) |
2102 | { | 2180 | { |
2103 | cancel_delayed_work_sync(&bat_priv->tt_work); | 2181 | cancel_delayed_work_sync(&bat_priv->tt.work); |
2104 | 2182 | ||
2105 | batadv_tt_local_table_free(bat_priv); | 2183 | batadv_tt_local_table_free(bat_priv); |
2106 | batadv_tt_global_table_free(bat_priv); | 2184 | batadv_tt_global_table_free(bat_priv); |
@@ -2108,7 +2186,7 @@ void batadv_tt_free(struct batadv_priv *bat_priv) | |||
2108 | batadv_tt_changes_list_free(bat_priv); | 2186 | batadv_tt_changes_list_free(bat_priv); |
2109 | batadv_tt_roam_list_free(bat_priv); | 2187 | batadv_tt_roam_list_free(bat_priv); |
2110 | 2188 | ||
2111 | kfree(bat_priv->tt_buff); | 2189 | kfree(bat_priv->tt.last_changeset); |
2112 | } | 2190 | } |
2113 | 2191 | ||
2114 | /* This function will enable or disable the specified flags for all the entries | 2192 | /* This function will enable or disable the specified flags for all the entries |
@@ -2152,7 +2230,7 @@ out: | |||
2152 | /* Purge out all the tt local entries marked with BATADV_TT_CLIENT_PENDING */ | 2230 | /* Purge out all the tt local entries marked with BATADV_TT_CLIENT_PENDING */ |
2153 | static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv) | 2231 | static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv) |
2154 | { | 2232 | { |
2155 | struct batadv_hashtable *hash = bat_priv->tt_local_hash; | 2233 | struct batadv_hashtable *hash = bat_priv->tt.local_hash; |
2156 | struct batadv_tt_common_entry *tt_common; | 2234 | struct batadv_tt_common_entry *tt_common; |
2157 | struct batadv_tt_local_entry *tt_local; | 2235 | struct batadv_tt_local_entry *tt_local; |
2158 | struct hlist_node *node, *node_tmp; | 2236 | struct hlist_node *node, *node_tmp; |
@@ -2177,7 +2255,7 @@ static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv) | |||
2177 | "Deleting local tt entry (%pM): pending\n", | 2255 | "Deleting local tt entry (%pM): pending\n", |
2178 | tt_common->addr); | 2256 | tt_common->addr); |
2179 | 2257 | ||
2180 | atomic_dec(&bat_priv->num_local_tt); | 2258 | atomic_dec(&bat_priv->tt.local_entry_num); |
2181 | hlist_del_rcu(node); | 2259 | hlist_del_rcu(node); |
2182 | tt_local = container_of(tt_common, | 2260 | tt_local = container_of(tt_common, |
2183 | struct batadv_tt_local_entry, | 2261 | struct batadv_tt_local_entry, |
@@ -2195,26 +2273,26 @@ static int batadv_tt_commit_changes(struct batadv_priv *bat_priv, | |||
2195 | { | 2273 | { |
2196 | uint16_t changed_num = 0; | 2274 | uint16_t changed_num = 0; |
2197 | 2275 | ||
2198 | if (atomic_read(&bat_priv->tt_local_changes) < 1) | 2276 | if (atomic_read(&bat_priv->tt.local_changes) < 1) |
2199 | return -ENOENT; | 2277 | return -ENOENT; |
2200 | 2278 | ||
2201 | changed_num = batadv_tt_set_flags(bat_priv->tt_local_hash, | 2279 | changed_num = batadv_tt_set_flags(bat_priv->tt.local_hash, |
2202 | BATADV_TT_CLIENT_NEW, false); | 2280 | BATADV_TT_CLIENT_NEW, false); |
2203 | 2281 | ||
2204 | /* all reset entries have to be counted as local entries */ | 2282 | /* all reset entries have to be counted as local entries */ |
2205 | atomic_add(changed_num, &bat_priv->num_local_tt); | 2283 | atomic_add(changed_num, &bat_priv->tt.local_entry_num); |
2206 | batadv_tt_local_purge_pending_clients(bat_priv); | 2284 | batadv_tt_local_purge_pending_clients(bat_priv); |
2207 | bat_priv->tt_crc = batadv_tt_local_crc(bat_priv); | 2285 | bat_priv->tt.local_crc = batadv_tt_local_crc(bat_priv); |
2208 | 2286 | ||
2209 | /* Increment the TTVN only once per OGM interval */ | 2287 | /* Increment the TTVN only once per OGM interval */ |
2210 | atomic_inc(&bat_priv->ttvn); | 2288 | atomic_inc(&bat_priv->tt.vn); |
2211 | batadv_dbg(BATADV_DBG_TT, bat_priv, | 2289 | batadv_dbg(BATADV_DBG_TT, bat_priv, |
2212 | "Local changes committed, updating to ttvn %u\n", | 2290 | "Local changes committed, updating to ttvn %u\n", |
2213 | (uint8_t)atomic_read(&bat_priv->ttvn)); | 2291 | (uint8_t)atomic_read(&bat_priv->tt.vn)); |
2214 | bat_priv->tt_poss_change = false; | 2292 | bat_priv->tt.poss_change = false; |
2215 | 2293 | ||
2216 | /* reset the sending counter */ | 2294 | /* reset the sending counter */ |
2217 | atomic_set(&bat_priv->tt_ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX); | 2295 | atomic_set(&bat_priv->tt.ogm_append_cnt, BATADV_TT_OGM_APPEND_MAX); |
2218 | 2296 | ||
2219 | return batadv_tt_changes_fill_buff(bat_priv, packet_buff, | 2297 | return batadv_tt_changes_fill_buff(bat_priv, packet_buff, |
2220 | packet_buff_len, packet_min_len); | 2298 | packet_buff_len, packet_min_len); |
@@ -2234,7 +2312,7 @@ int batadv_tt_append_diff(struct batadv_priv *bat_priv, | |||
2234 | 2312 | ||
2235 | /* if the changes have been sent often enough */ | 2313 | /* if the changes have been sent often enough */ |
2236 | if ((tt_num_changes < 0) && | 2314 | if ((tt_num_changes < 0) && |
2237 | (!batadv_atomic_dec_not_zero(&bat_priv->tt_ogm_append_cnt))) { | 2315 | (!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt))) { |
2238 | batadv_tt_realloc_packet_buff(packet_buff, packet_buff_len, | 2316 | batadv_tt_realloc_packet_buff(packet_buff, packet_buff_len, |
2239 | packet_min_len, packet_min_len); | 2317 | packet_min_len, packet_min_len); |
2240 | tt_num_changes = 0; | 2318 | tt_num_changes = 0; |
@@ -2365,3 +2443,22 @@ bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv, | |||
2365 | out: | 2443 | out: |
2366 | return ret; | 2444 | return ret; |
2367 | } | 2445 | } |
2446 | |||
2447 | bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv, | ||
2448 | struct batadv_orig_node *orig_node, | ||
2449 | const unsigned char *addr) | ||
2450 | { | ||
2451 | bool ret = false; | ||
2452 | |||
2453 | if (!batadv_tt_global_add(bat_priv, orig_node, addr, | ||
2454 | BATADV_TT_CLIENT_TEMP, | ||
2455 | atomic_read(&orig_node->last_ttvn))) | ||
2456 | goto out; | ||
2457 | |||
2458 | batadv_dbg(BATADV_DBG_TT, bat_priv, | ||
2459 | "Added temporary global client (addr: %pM orig: %pM)\n", | ||
2460 | addr, orig_node->orig); | ||
2461 | ret = true; | ||
2462 | out: | ||
2463 | return ret; | ||
2464 | } | ||
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h index ffa87355096b..811fffd4760c 100644 --- a/net/batman-adv/translation-table.h +++ b/net/batman-adv/translation-table.h | |||
@@ -59,6 +59,8 @@ int batadv_tt_append_diff(struct batadv_priv *bat_priv, | |||
59 | int packet_min_len); | 59 | int packet_min_len); |
60 | bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv, | 60 | bool batadv_tt_global_client_is_roaming(struct batadv_priv *bat_priv, |
61 | uint8_t *addr); | 61 | uint8_t *addr); |
62 | 62 | bool batadv_tt_add_temporary_global_entry(struct batadv_priv *bat_priv, | |
63 | struct batadv_orig_node *orig_node, | ||
64 | const unsigned char *addr); | ||
63 | 65 | ||
64 | #endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */ | 66 | #endif /* _NET_BATMAN_ADV_TRANSLATION_TABLE_H_ */ |
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 12635fd2c3d3..2ed82caacdca 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h | |||
@@ -145,6 +145,11 @@ struct batadv_bcast_duplist_entry { | |||
145 | #endif | 145 | #endif |
146 | 146 | ||
147 | enum batadv_counters { | 147 | enum batadv_counters { |
148 | BATADV_CNT_TX, | ||
149 | BATADV_CNT_TX_BYTES, | ||
150 | BATADV_CNT_TX_DROPPED, | ||
151 | BATADV_CNT_RX, | ||
152 | BATADV_CNT_RX_BYTES, | ||
148 | BATADV_CNT_FORWARD, | 153 | BATADV_CNT_FORWARD, |
149 | BATADV_CNT_FORWARD_BYTES, | 154 | BATADV_CNT_FORWARD_BYTES, |
150 | BATADV_CNT_MGMT_TX, | 155 | BATADV_CNT_MGMT_TX, |
@@ -160,6 +165,67 @@ enum batadv_counters { | |||
160 | BATADV_CNT_NUM, | 165 | BATADV_CNT_NUM, |
161 | }; | 166 | }; |
162 | 167 | ||
168 | /** | ||
169 | * struct batadv_priv_tt - per mesh interface translation table data | ||
170 | * @vn: translation table version number | ||
171 | * @local_changes: changes registered in an originator interval | ||
172 | * @poss_change: Detect an ongoing roaming phase. If true, then this node | ||
173 | * received a roaming_adv and has to inspect every packet directed to it to | ||
174 | * check whether it still is the true destination or not. This flag will be | ||
175 | * reset to false as soon as the this node's ttvn is increased | ||
176 | * @changes_list: tracks tt local changes within an originator interval | ||
177 | * @req_list: list of pending tt_requests | ||
178 | * @local_crc: Checksum of the local table, recomputed before sending a new OGM | ||
179 | */ | ||
180 | struct batadv_priv_tt { | ||
181 | atomic_t vn; | ||
182 | atomic_t ogm_append_cnt; | ||
183 | atomic_t local_changes; | ||
184 | bool poss_change; | ||
185 | struct list_head changes_list; | ||
186 | struct batadv_hashtable *local_hash; | ||
187 | struct batadv_hashtable *global_hash; | ||
188 | struct list_head req_list; | ||
189 | struct list_head roam_list; | ||
190 | spinlock_t changes_list_lock; /* protects changes */ | ||
191 | spinlock_t req_list_lock; /* protects req_list */ | ||
192 | spinlock_t roam_list_lock; /* protects roam_list */ | ||
193 | atomic_t local_entry_num; | ||
194 | uint16_t local_crc; | ||
195 | unsigned char *last_changeset; | ||
196 | int16_t last_changeset_len; | ||
197 | spinlock_t last_changeset_lock; /* protects last_changeset */ | ||
198 | struct delayed_work work; | ||
199 | }; | ||
200 | |||
201 | #ifdef CONFIG_BATMAN_ADV_BLA | ||
202 | struct batadv_priv_bla { | ||
203 | atomic_t num_requests; /* number of bla requests in flight */ | ||
204 | struct batadv_hashtable *claim_hash; | ||
205 | struct batadv_hashtable *backbone_hash; | ||
206 | struct batadv_bcast_duplist_entry bcast_duplist[BATADV_DUPLIST_SIZE]; | ||
207 | int bcast_duplist_curr; | ||
208 | struct batadv_bla_claim_dst claim_dest; | ||
209 | struct delayed_work work; | ||
210 | }; | ||
211 | #endif | ||
212 | |||
213 | struct batadv_priv_gw { | ||
214 | struct hlist_head list; | ||
215 | spinlock_t list_lock; /* protects gw_list and curr_gw */ | ||
216 | struct batadv_gw_node __rcu *curr_gw; /* rcu protected pointer */ | ||
217 | atomic_t reselect; | ||
218 | }; | ||
219 | |||
220 | struct batadv_priv_vis { | ||
221 | struct list_head send_list; | ||
222 | struct batadv_hashtable *hash; | ||
223 | spinlock_t hash_lock; /* protects hash */ | ||
224 | spinlock_t list_lock; /* protects info::recv_list */ | ||
225 | struct delayed_work work; | ||
226 | struct batadv_vis_info *my_info; | ||
227 | }; | ||
228 | |||
163 | struct batadv_priv { | 229 | struct batadv_priv { |
164 | atomic_t mesh_state; | 230 | atomic_t mesh_state; |
165 | struct net_device_stats stats; | 231 | struct net_device_stats stats; |
@@ -179,64 +245,24 @@ struct batadv_priv { | |||
179 | atomic_t bcast_seqno; | 245 | atomic_t bcast_seqno; |
180 | atomic_t bcast_queue_left; | 246 | atomic_t bcast_queue_left; |
181 | atomic_t batman_queue_left; | 247 | atomic_t batman_queue_left; |
182 | atomic_t ttvn; /* translation table version number */ | ||
183 | atomic_t tt_ogm_append_cnt; | ||
184 | atomic_t tt_local_changes; /* changes registered in a OGM interval */ | ||
185 | atomic_t bla_num_requests; /* number of bla requests in flight */ | ||
186 | /* The tt_poss_change flag is used to detect an ongoing roaming phase. | ||
187 | * If true, then I received a Roaming_adv and I have to inspect every | ||
188 | * packet directed to me to check whether I am still the true | ||
189 | * destination or not. This flag will be reset to false as soon as I | ||
190 | * increase my TTVN | ||
191 | */ | ||
192 | bool tt_poss_change; | ||
193 | char num_ifaces; | 248 | char num_ifaces; |
194 | struct batadv_debug_log *debug_log; | 249 | struct batadv_debug_log *debug_log; |
195 | struct kobject *mesh_obj; | 250 | struct kobject *mesh_obj; |
196 | struct dentry *debug_dir; | 251 | struct dentry *debug_dir; |
197 | struct hlist_head forw_bat_list; | 252 | struct hlist_head forw_bat_list; |
198 | struct hlist_head forw_bcast_list; | 253 | struct hlist_head forw_bcast_list; |
199 | struct hlist_head gw_list; | ||
200 | struct list_head tt_changes_list; /* tracks changes in a OGM int */ | ||
201 | struct list_head vis_send_list; | ||
202 | struct batadv_hashtable *orig_hash; | 254 | struct batadv_hashtable *orig_hash; |
203 | struct batadv_hashtable *tt_local_hash; | ||
204 | struct batadv_hashtable *tt_global_hash; | ||
205 | #ifdef CONFIG_BATMAN_ADV_BLA | ||
206 | struct batadv_hashtable *claim_hash; | ||
207 | struct batadv_hashtable *backbone_hash; | ||
208 | #endif | ||
209 | struct list_head tt_req_list; /* list of pending tt_requests */ | ||
210 | struct list_head tt_roam_list; | ||
211 | struct batadv_hashtable *vis_hash; | ||
212 | #ifdef CONFIG_BATMAN_ADV_BLA | ||
213 | struct batadv_bcast_duplist_entry bcast_duplist[BATADV_DUPLIST_SIZE]; | ||
214 | int bcast_duplist_curr; | ||
215 | struct batadv_bla_claim_dst claim_dest; | ||
216 | #endif | ||
217 | spinlock_t forw_bat_list_lock; /* protects forw_bat_list */ | 255 | spinlock_t forw_bat_list_lock; /* protects forw_bat_list */ |
218 | spinlock_t forw_bcast_list_lock; /* protects */ | 256 | spinlock_t forw_bcast_list_lock; /* protects */ |
219 | spinlock_t tt_changes_list_lock; /* protects tt_changes */ | ||
220 | spinlock_t tt_req_list_lock; /* protects tt_req_list */ | ||
221 | spinlock_t tt_roam_list_lock; /* protects tt_roam_list */ | ||
222 | spinlock_t gw_list_lock; /* protects gw_list and curr_gw */ | ||
223 | spinlock_t vis_hash_lock; /* protects vis_hash */ | ||
224 | spinlock_t vis_list_lock; /* protects vis_info::recv_list */ | ||
225 | atomic_t num_local_tt; | ||
226 | /* Checksum of the local table, recomputed before sending a new OGM */ | ||
227 | uint16_t tt_crc; | ||
228 | unsigned char *tt_buff; | ||
229 | int16_t tt_buff_len; | ||
230 | spinlock_t tt_buff_lock; /* protects tt_buff */ | ||
231 | struct delayed_work tt_work; | ||
232 | struct delayed_work orig_work; | 257 | struct delayed_work orig_work; |
233 | struct delayed_work vis_work; | ||
234 | struct delayed_work bla_work; | ||
235 | struct batadv_gw_node __rcu *curr_gw; /* rcu protected pointer */ | ||
236 | atomic_t gw_reselect; | ||
237 | struct batadv_hard_iface __rcu *primary_if; /* rcu protected pointer */ | 258 | struct batadv_hard_iface __rcu *primary_if; /* rcu protected pointer */ |
238 | struct batadv_vis_info *my_vis_info; | ||
239 | struct batadv_algo_ops *bat_algo_ops; | 259 | struct batadv_algo_ops *bat_algo_ops; |
260 | #ifdef CONFIG_BATMAN_ADV_BLA | ||
261 | struct batadv_priv_bla bla; | ||
262 | #endif | ||
263 | struct batadv_priv_gw gw; | ||
264 | struct batadv_priv_tt tt; | ||
265 | struct batadv_priv_vis vis; | ||
240 | }; | 266 | }; |
241 | 267 | ||
242 | struct batadv_socket_client { | 268 | struct batadv_socket_client { |
@@ -258,6 +284,7 @@ struct batadv_tt_common_entry { | |||
258 | uint8_t addr[ETH_ALEN]; | 284 | uint8_t addr[ETH_ALEN]; |
259 | struct hlist_node hash_entry; | 285 | struct hlist_node hash_entry; |
260 | uint16_t flags; | 286 | uint16_t flags; |
287 | unsigned long added_at; | ||
261 | atomic_t refcount; | 288 | atomic_t refcount; |
262 | struct rcu_head rcu; | 289 | struct rcu_head rcu; |
263 | }; | 290 | }; |
@@ -277,6 +304,7 @@ struct batadv_tt_global_entry { | |||
277 | struct batadv_tt_orig_list_entry { | 304 | struct batadv_tt_orig_list_entry { |
278 | struct batadv_orig_node *orig_node; | 305 | struct batadv_orig_node *orig_node; |
279 | uint8_t ttvn; | 306 | uint8_t ttvn; |
307 | atomic_t refcount; | ||
280 | struct rcu_head rcu; | 308 | struct rcu_head rcu; |
281 | struct hlist_node list; | 309 | struct hlist_node list; |
282 | }; | 310 | }; |
diff --git a/net/batman-adv/unicast.c b/net/batman-adv/unicast.c index 00164645b3f7..f39723281ca1 100644 --- a/net/batman-adv/unicast.c +++ b/net/batman-adv/unicast.c | |||
@@ -39,6 +39,7 @@ batadv_frag_merge_packet(struct list_head *head, | |||
39 | struct batadv_unicast_packet *unicast_packet; | 39 | struct batadv_unicast_packet *unicast_packet; |
40 | int hdr_len = sizeof(*unicast_packet); | 40 | int hdr_len = sizeof(*unicast_packet); |
41 | int uni_diff = sizeof(*up) - hdr_len; | 41 | int uni_diff = sizeof(*up) - hdr_len; |
42 | uint8_t *packet_pos; | ||
42 | 43 | ||
43 | up = (struct batadv_unicast_frag_packet *)skb->data; | 44 | up = (struct batadv_unicast_frag_packet *)skb->data; |
44 | /* set skb to the first part and tmp_skb to the second part */ | 45 | /* set skb to the first part and tmp_skb to the second part */ |
@@ -65,8 +66,8 @@ batadv_frag_merge_packet(struct list_head *head, | |||
65 | kfree_skb(tmp_skb); | 66 | kfree_skb(tmp_skb); |
66 | 67 | ||
67 | memmove(skb->data + uni_diff, skb->data, hdr_len); | 68 | memmove(skb->data + uni_diff, skb->data, hdr_len); |
68 | unicast_packet = (struct batadv_unicast_packet *)skb_pull(skb, | 69 | packet_pos = skb_pull(skb, uni_diff); |
69 | uni_diff); | 70 | unicast_packet = (struct batadv_unicast_packet *)packet_pos; |
70 | unicast_packet->header.packet_type = BATADV_UNICAST; | 71 | unicast_packet->header.packet_type = BATADV_UNICAST; |
71 | 72 | ||
72 | return skb; | 73 | return skb; |
@@ -121,6 +122,7 @@ batadv_frag_search_packet(struct list_head *head, | |||
121 | { | 122 | { |
122 | struct batadv_frag_packet_list_entry *tfp; | 123 | struct batadv_frag_packet_list_entry *tfp; |
123 | struct batadv_unicast_frag_packet *tmp_up = NULL; | 124 | struct batadv_unicast_frag_packet *tmp_up = NULL; |
125 | int is_head_tmp, is_head; | ||
124 | uint16_t search_seqno; | 126 | uint16_t search_seqno; |
125 | 127 | ||
126 | if (up->flags & BATADV_UNI_FRAG_HEAD) | 128 | if (up->flags & BATADV_UNI_FRAG_HEAD) |
@@ -128,6 +130,8 @@ batadv_frag_search_packet(struct list_head *head, | |||
128 | else | 130 | else |
129 | search_seqno = ntohs(up->seqno)-1; | 131 | search_seqno = ntohs(up->seqno)-1; |
130 | 132 | ||
133 | is_head = !!(up->flags & BATADV_UNI_FRAG_HEAD); | ||
134 | |||
131 | list_for_each_entry(tfp, head, list) { | 135 | list_for_each_entry(tfp, head, list) { |
132 | 136 | ||
133 | if (!tfp->skb) | 137 | if (!tfp->skb) |
@@ -139,9 +143,8 @@ batadv_frag_search_packet(struct list_head *head, | |||
139 | tmp_up = (struct batadv_unicast_frag_packet *)tfp->skb->data; | 143 | tmp_up = (struct batadv_unicast_frag_packet *)tfp->skb->data; |
140 | 144 | ||
141 | if (tfp->seqno == search_seqno) { | 145 | if (tfp->seqno == search_seqno) { |
142 | 146 | is_head_tmp = !!(tmp_up->flags & BATADV_UNI_FRAG_HEAD); | |
143 | if ((tmp_up->flags & BATADV_UNI_FRAG_HEAD) != | 147 | if (is_head_tmp != is_head) |
144 | (up->flags & BATADV_UNI_FRAG_HEAD)) | ||
145 | return tfp; | 148 | return tfp; |
146 | else | 149 | else |
147 | goto mov_tail; | 150 | goto mov_tail; |
@@ -334,8 +337,7 @@ find_router: | |||
334 | /* copy the destination for faster routing */ | 337 | /* copy the destination for faster routing */ |
335 | memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN); | 338 | memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN); |
336 | /* set the destination tt version number */ | 339 | /* set the destination tt version number */ |
337 | unicast_packet->ttvn = | 340 | unicast_packet->ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); |
338 | (uint8_t)atomic_read(&orig_node->last_ttvn); | ||
339 | 341 | ||
340 | /* inform the destination node that we are still missing a correct route | 342 | /* inform the destination node that we are still missing a correct route |
341 | * for this client. The destination will receive this packet and will | 343 | * for this client. The destination will receive this packet and will |
diff --git a/net/batman-adv/vis.c b/net/batman-adv/vis.c index 2a2ea0681469..5abd1454fb07 100644 --- a/net/batman-adv/vis.c +++ b/net/batman-adv/vis.c | |||
@@ -41,13 +41,13 @@ static void batadv_free_info(struct kref *ref) | |||
41 | bat_priv = info->bat_priv; | 41 | bat_priv = info->bat_priv; |
42 | 42 | ||
43 | list_del_init(&info->send_list); | 43 | list_del_init(&info->send_list); |
44 | spin_lock_bh(&bat_priv->vis_list_lock); | 44 | spin_lock_bh(&bat_priv->vis.list_lock); |
45 | list_for_each_entry_safe(entry, tmp, &info->recv_list, list) { | 45 | list_for_each_entry_safe(entry, tmp, &info->recv_list, list) { |
46 | list_del(&entry->list); | 46 | list_del(&entry->list); |
47 | kfree(entry); | 47 | kfree(entry); |
48 | } | 48 | } |
49 | 49 | ||
50 | spin_unlock_bh(&bat_priv->vis_list_lock); | 50 | spin_unlock_bh(&bat_priv->vis.list_lock); |
51 | kfree_skb(info->skb_packet); | 51 | kfree_skb(info->skb_packet); |
52 | kfree(info); | 52 | kfree(info); |
53 | } | 53 | } |
@@ -94,7 +94,7 @@ static uint32_t batadv_vis_info_choose(const void *data, uint32_t size) | |||
94 | static struct batadv_vis_info * | 94 | static struct batadv_vis_info * |
95 | batadv_vis_hash_find(struct batadv_priv *bat_priv, const void *data) | 95 | batadv_vis_hash_find(struct batadv_priv *bat_priv, const void *data) |
96 | { | 96 | { |
97 | struct batadv_hashtable *hash = bat_priv->vis_hash; | 97 | struct batadv_hashtable *hash = bat_priv->vis.hash; |
98 | struct hlist_head *head; | 98 | struct hlist_head *head; |
99 | struct hlist_node *node; | 99 | struct hlist_node *node; |
100 | struct batadv_vis_info *vis_info, *vis_info_tmp = NULL; | 100 | struct batadv_vis_info *vis_info, *vis_info_tmp = NULL; |
@@ -252,7 +252,7 @@ int batadv_vis_seq_print_text(struct seq_file *seq, void *offset) | |||
252 | struct hlist_head *head; | 252 | struct hlist_head *head; |
253 | struct net_device *net_dev = (struct net_device *)seq->private; | 253 | struct net_device *net_dev = (struct net_device *)seq->private; |
254 | struct batadv_priv *bat_priv = netdev_priv(net_dev); | 254 | struct batadv_priv *bat_priv = netdev_priv(net_dev); |
255 | struct batadv_hashtable *hash = bat_priv->vis_hash; | 255 | struct batadv_hashtable *hash = bat_priv->vis.hash; |
256 | uint32_t i; | 256 | uint32_t i; |
257 | int ret = 0; | 257 | int ret = 0; |
258 | int vis_server = atomic_read(&bat_priv->vis_mode); | 258 | int vis_server = atomic_read(&bat_priv->vis_mode); |
@@ -264,12 +264,12 @@ int batadv_vis_seq_print_text(struct seq_file *seq, void *offset) | |||
264 | if (vis_server == BATADV_VIS_TYPE_CLIENT_UPDATE) | 264 | if (vis_server == BATADV_VIS_TYPE_CLIENT_UPDATE) |
265 | goto out; | 265 | goto out; |
266 | 266 | ||
267 | spin_lock_bh(&bat_priv->vis_hash_lock); | 267 | spin_lock_bh(&bat_priv->vis.hash_lock); |
268 | for (i = 0; i < hash->size; i++) { | 268 | for (i = 0; i < hash->size; i++) { |
269 | head = &hash->table[i]; | 269 | head = &hash->table[i]; |
270 | batadv_vis_seq_print_text_bucket(seq, head); | 270 | batadv_vis_seq_print_text_bucket(seq, head); |
271 | } | 271 | } |
272 | spin_unlock_bh(&bat_priv->vis_hash_lock); | 272 | spin_unlock_bh(&bat_priv->vis.hash_lock); |
273 | 273 | ||
274 | out: | 274 | out: |
275 | if (primary_if) | 275 | if (primary_if) |
@@ -285,7 +285,7 @@ static void batadv_send_list_add(struct batadv_priv *bat_priv, | |||
285 | { | 285 | { |
286 | if (list_empty(&info->send_list)) { | 286 | if (list_empty(&info->send_list)) { |
287 | kref_get(&info->refcount); | 287 | kref_get(&info->refcount); |
288 | list_add_tail(&info->send_list, &bat_priv->vis_send_list); | 288 | list_add_tail(&info->send_list, &bat_priv->vis.send_list); |
289 | } | 289 | } |
290 | } | 290 | } |
291 | 291 | ||
@@ -311,9 +311,9 @@ static void batadv_recv_list_add(struct batadv_priv *bat_priv, | |||
311 | return; | 311 | return; |
312 | 312 | ||
313 | memcpy(entry->mac, mac, ETH_ALEN); | 313 | memcpy(entry->mac, mac, ETH_ALEN); |
314 | spin_lock_bh(&bat_priv->vis_list_lock); | 314 | spin_lock_bh(&bat_priv->vis.list_lock); |
315 | list_add_tail(&entry->list, recv_list); | 315 | list_add_tail(&entry->list, recv_list); |
316 | spin_unlock_bh(&bat_priv->vis_list_lock); | 316 | spin_unlock_bh(&bat_priv->vis.list_lock); |
317 | } | 317 | } |
318 | 318 | ||
319 | /* returns 1 if this mac is in the recv_list */ | 319 | /* returns 1 if this mac is in the recv_list */ |
@@ -323,14 +323,14 @@ static int batadv_recv_list_is_in(struct batadv_priv *bat_priv, | |||
323 | { | 323 | { |
324 | const struct batadv_recvlist_node *entry; | 324 | const struct batadv_recvlist_node *entry; |
325 | 325 | ||
326 | spin_lock_bh(&bat_priv->vis_list_lock); | 326 | spin_lock_bh(&bat_priv->vis.list_lock); |
327 | list_for_each_entry(entry, recv_list, list) { | 327 | list_for_each_entry(entry, recv_list, list) { |
328 | if (batadv_compare_eth(entry->mac, mac)) { | 328 | if (batadv_compare_eth(entry->mac, mac)) { |
329 | spin_unlock_bh(&bat_priv->vis_list_lock); | 329 | spin_unlock_bh(&bat_priv->vis.list_lock); |
330 | return 1; | 330 | return 1; |
331 | } | 331 | } |
332 | } | 332 | } |
333 | spin_unlock_bh(&bat_priv->vis_list_lock); | 333 | spin_unlock_bh(&bat_priv->vis.list_lock); |
334 | return 0; | 334 | return 0; |
335 | } | 335 | } |
336 | 336 | ||
@@ -354,7 +354,7 @@ batadv_add_packet(struct batadv_priv *bat_priv, | |||
354 | 354 | ||
355 | *is_new = 0; | 355 | *is_new = 0; |
356 | /* sanity check */ | 356 | /* sanity check */ |
357 | if (!bat_priv->vis_hash) | 357 | if (!bat_priv->vis.hash) |
358 | return NULL; | 358 | return NULL; |
359 | 359 | ||
360 | /* see if the packet is already in vis_hash */ | 360 | /* see if the packet is already in vis_hash */ |
@@ -385,7 +385,7 @@ batadv_add_packet(struct batadv_priv *bat_priv, | |||
385 | } | 385 | } |
386 | } | 386 | } |
387 | /* remove old entry */ | 387 | /* remove old entry */ |
388 | batadv_hash_remove(bat_priv->vis_hash, batadv_vis_info_cmp, | 388 | batadv_hash_remove(bat_priv->vis.hash, batadv_vis_info_cmp, |
389 | batadv_vis_info_choose, old_info); | 389 | batadv_vis_info_choose, old_info); |
390 | batadv_send_list_del(old_info); | 390 | batadv_send_list_del(old_info); |
391 | kref_put(&old_info->refcount, batadv_free_info); | 391 | kref_put(&old_info->refcount, batadv_free_info); |
@@ -426,7 +426,7 @@ batadv_add_packet(struct batadv_priv *bat_priv, | |||
426 | batadv_recv_list_add(bat_priv, &info->recv_list, packet->sender_orig); | 426 | batadv_recv_list_add(bat_priv, &info->recv_list, packet->sender_orig); |
427 | 427 | ||
428 | /* try to add it */ | 428 | /* try to add it */ |
429 | hash_added = batadv_hash_add(bat_priv->vis_hash, batadv_vis_info_cmp, | 429 | hash_added = batadv_hash_add(bat_priv->vis.hash, batadv_vis_info_cmp, |
430 | batadv_vis_info_choose, info, | 430 | batadv_vis_info_choose, info, |
431 | &info->hash_entry); | 431 | &info->hash_entry); |
432 | if (hash_added != 0) { | 432 | if (hash_added != 0) { |
@@ -449,7 +449,7 @@ void batadv_receive_server_sync_packet(struct batadv_priv *bat_priv, | |||
449 | 449 | ||
450 | make_broadcast = (vis_server == BATADV_VIS_TYPE_SERVER_SYNC); | 450 | make_broadcast = (vis_server == BATADV_VIS_TYPE_SERVER_SYNC); |
451 | 451 | ||
452 | spin_lock_bh(&bat_priv->vis_hash_lock); | 452 | spin_lock_bh(&bat_priv->vis.hash_lock); |
453 | info = batadv_add_packet(bat_priv, vis_packet, vis_info_len, | 453 | info = batadv_add_packet(bat_priv, vis_packet, vis_info_len, |
454 | &is_new, make_broadcast); | 454 | &is_new, make_broadcast); |
455 | if (!info) | 455 | if (!info) |
@@ -461,7 +461,7 @@ void batadv_receive_server_sync_packet(struct batadv_priv *bat_priv, | |||
461 | if (vis_server == BATADV_VIS_TYPE_SERVER_SYNC && is_new) | 461 | if (vis_server == BATADV_VIS_TYPE_SERVER_SYNC && is_new) |
462 | batadv_send_list_add(bat_priv, info); | 462 | batadv_send_list_add(bat_priv, info); |
463 | end: | 463 | end: |
464 | spin_unlock_bh(&bat_priv->vis_hash_lock); | 464 | spin_unlock_bh(&bat_priv->vis.hash_lock); |
465 | } | 465 | } |
466 | 466 | ||
467 | /* handle an incoming client update packet and schedule forward if needed. */ | 467 | /* handle an incoming client update packet and schedule forward if needed. */ |
@@ -484,7 +484,7 @@ void batadv_receive_client_update_packet(struct batadv_priv *bat_priv, | |||
484 | batadv_is_my_mac(vis_packet->target_orig)) | 484 | batadv_is_my_mac(vis_packet->target_orig)) |
485 | are_target = 1; | 485 | are_target = 1; |
486 | 486 | ||
487 | spin_lock_bh(&bat_priv->vis_hash_lock); | 487 | spin_lock_bh(&bat_priv->vis.hash_lock); |
488 | info = batadv_add_packet(bat_priv, vis_packet, vis_info_len, | 488 | info = batadv_add_packet(bat_priv, vis_packet, vis_info_len, |
489 | &is_new, are_target); | 489 | &is_new, are_target); |
490 | 490 | ||
@@ -505,7 +505,7 @@ void batadv_receive_client_update_packet(struct batadv_priv *bat_priv, | |||
505 | } | 505 | } |
506 | 506 | ||
507 | end: | 507 | end: |
508 | spin_unlock_bh(&bat_priv->vis_hash_lock); | 508 | spin_unlock_bh(&bat_priv->vis.hash_lock); |
509 | } | 509 | } |
510 | 510 | ||
511 | /* Walk the originators and find the VIS server with the best tq. Set the packet | 511 | /* Walk the originators and find the VIS server with the best tq. Set the packet |
@@ -574,10 +574,11 @@ static int batadv_generate_vis_packet(struct batadv_priv *bat_priv) | |||
574 | struct hlist_head *head; | 574 | struct hlist_head *head; |
575 | struct batadv_orig_node *orig_node; | 575 | struct batadv_orig_node *orig_node; |
576 | struct batadv_neigh_node *router; | 576 | struct batadv_neigh_node *router; |
577 | struct batadv_vis_info *info = bat_priv->my_vis_info; | 577 | struct batadv_vis_info *info = bat_priv->vis.my_info; |
578 | struct batadv_vis_packet *packet; | 578 | struct batadv_vis_packet *packet; |
579 | struct batadv_vis_info_entry *entry; | 579 | struct batadv_vis_info_entry *entry; |
580 | struct batadv_tt_common_entry *tt_common_entry; | 580 | struct batadv_tt_common_entry *tt_common_entry; |
581 | uint8_t *packet_pos; | ||
581 | int best_tq = -1; | 582 | int best_tq = -1; |
582 | uint32_t i; | 583 | uint32_t i; |
583 | 584 | ||
@@ -618,8 +619,8 @@ static int batadv_generate_vis_packet(struct batadv_priv *bat_priv) | |||
618 | goto next; | 619 | goto next; |
619 | 620 | ||
620 | /* fill one entry into buffer. */ | 621 | /* fill one entry into buffer. */ |
621 | entry = (struct batadv_vis_info_entry *) | 622 | packet_pos = skb_put(info->skb_packet, sizeof(*entry)); |
622 | skb_put(info->skb_packet, sizeof(*entry)); | 623 | entry = (struct batadv_vis_info_entry *)packet_pos; |
623 | memcpy(entry->src, | 624 | memcpy(entry->src, |
624 | router->if_incoming->net_dev->dev_addr, | 625 | router->if_incoming->net_dev->dev_addr, |
625 | ETH_ALEN); | 626 | ETH_ALEN); |
@@ -636,7 +637,7 @@ next: | |||
636 | rcu_read_unlock(); | 637 | rcu_read_unlock(); |
637 | } | 638 | } |
638 | 639 | ||
639 | hash = bat_priv->tt_local_hash; | 640 | hash = bat_priv->tt.local_hash; |
640 | 641 | ||
641 | for (i = 0; i < hash->size; i++) { | 642 | for (i = 0; i < hash->size; i++) { |
642 | head = &hash->table[i]; | 643 | head = &hash->table[i]; |
@@ -644,9 +645,8 @@ next: | |||
644 | rcu_read_lock(); | 645 | rcu_read_lock(); |
645 | hlist_for_each_entry_rcu(tt_common_entry, node, head, | 646 | hlist_for_each_entry_rcu(tt_common_entry, node, head, |
646 | hash_entry) { | 647 | hash_entry) { |
647 | entry = (struct batadv_vis_info_entry *) | 648 | packet_pos = skb_put(info->skb_packet, sizeof(*entry)); |
648 | skb_put(info->skb_packet, | 649 | entry = (struct batadv_vis_info_entry *)packet_pos; |
649 | sizeof(*entry)); | ||
650 | memset(entry->src, 0, ETH_ALEN); | 650 | memset(entry->src, 0, ETH_ALEN); |
651 | memcpy(entry->dest, tt_common_entry->addr, ETH_ALEN); | 651 | memcpy(entry->dest, tt_common_entry->addr, ETH_ALEN); |
652 | entry->quality = 0; /* 0 means TT */ | 652 | entry->quality = 0; /* 0 means TT */ |
@@ -671,7 +671,7 @@ unlock: | |||
671 | static void batadv_purge_vis_packets(struct batadv_priv *bat_priv) | 671 | static void batadv_purge_vis_packets(struct batadv_priv *bat_priv) |
672 | { | 672 | { |
673 | uint32_t i; | 673 | uint32_t i; |
674 | struct batadv_hashtable *hash = bat_priv->vis_hash; | 674 | struct batadv_hashtable *hash = bat_priv->vis.hash; |
675 | struct hlist_node *node, *node_tmp; | 675 | struct hlist_node *node, *node_tmp; |
676 | struct hlist_head *head; | 676 | struct hlist_head *head; |
677 | struct batadv_vis_info *info; | 677 | struct batadv_vis_info *info; |
@@ -682,7 +682,7 @@ static void batadv_purge_vis_packets(struct batadv_priv *bat_priv) | |||
682 | hlist_for_each_entry_safe(info, node, node_tmp, | 682 | hlist_for_each_entry_safe(info, node, node_tmp, |
683 | head, hash_entry) { | 683 | head, hash_entry) { |
684 | /* never purge own data. */ | 684 | /* never purge own data. */ |
685 | if (info == bat_priv->my_vis_info) | 685 | if (info == bat_priv->vis.my_info) |
686 | continue; | 686 | continue; |
687 | 687 | ||
688 | if (batadv_has_timed_out(info->first_seen, | 688 | if (batadv_has_timed_out(info->first_seen, |
@@ -814,34 +814,36 @@ out: | |||
814 | /* called from timer; send (and maybe generate) vis packet. */ | 814 | /* called from timer; send (and maybe generate) vis packet. */ |
815 | static void batadv_send_vis_packets(struct work_struct *work) | 815 | static void batadv_send_vis_packets(struct work_struct *work) |
816 | { | 816 | { |
817 | struct delayed_work *delayed_work = | 817 | struct delayed_work *delayed_work; |
818 | container_of(work, struct delayed_work, work); | ||
819 | struct batadv_priv *bat_priv; | 818 | struct batadv_priv *bat_priv; |
819 | struct batadv_priv_vis *priv_vis; | ||
820 | struct batadv_vis_info *info; | 820 | struct batadv_vis_info *info; |
821 | 821 | ||
822 | bat_priv = container_of(delayed_work, struct batadv_priv, vis_work); | 822 | delayed_work = container_of(work, struct delayed_work, work); |
823 | spin_lock_bh(&bat_priv->vis_hash_lock); | 823 | priv_vis = container_of(delayed_work, struct batadv_priv_vis, work); |
824 | bat_priv = container_of(priv_vis, struct batadv_priv, vis); | ||
825 | spin_lock_bh(&bat_priv->vis.hash_lock); | ||
824 | batadv_purge_vis_packets(bat_priv); | 826 | batadv_purge_vis_packets(bat_priv); |
825 | 827 | ||
826 | if (batadv_generate_vis_packet(bat_priv) == 0) { | 828 | if (batadv_generate_vis_packet(bat_priv) == 0) { |
827 | /* schedule if generation was successful */ | 829 | /* schedule if generation was successful */ |
828 | batadv_send_list_add(bat_priv, bat_priv->my_vis_info); | 830 | batadv_send_list_add(bat_priv, bat_priv->vis.my_info); |
829 | } | 831 | } |
830 | 832 | ||
831 | while (!list_empty(&bat_priv->vis_send_list)) { | 833 | while (!list_empty(&bat_priv->vis.send_list)) { |
832 | info = list_first_entry(&bat_priv->vis_send_list, | 834 | info = list_first_entry(&bat_priv->vis.send_list, |
833 | typeof(*info), send_list); | 835 | typeof(*info), send_list); |
834 | 836 | ||
835 | kref_get(&info->refcount); | 837 | kref_get(&info->refcount); |
836 | spin_unlock_bh(&bat_priv->vis_hash_lock); | 838 | spin_unlock_bh(&bat_priv->vis.hash_lock); |
837 | 839 | ||
838 | batadv_send_vis_packet(bat_priv, info); | 840 | batadv_send_vis_packet(bat_priv, info); |
839 | 841 | ||
840 | spin_lock_bh(&bat_priv->vis_hash_lock); | 842 | spin_lock_bh(&bat_priv->vis.hash_lock); |
841 | batadv_send_list_del(info); | 843 | batadv_send_list_del(info); |
842 | kref_put(&info->refcount, batadv_free_info); | 844 | kref_put(&info->refcount, batadv_free_info); |
843 | } | 845 | } |
844 | spin_unlock_bh(&bat_priv->vis_hash_lock); | 846 | spin_unlock_bh(&bat_priv->vis.hash_lock); |
845 | batadv_start_vis_timer(bat_priv); | 847 | batadv_start_vis_timer(bat_priv); |
846 | } | 848 | } |
847 | 849 | ||
@@ -856,37 +858,37 @@ int batadv_vis_init(struct batadv_priv *bat_priv) | |||
856 | unsigned long first_seen; | 858 | unsigned long first_seen; |
857 | struct sk_buff *tmp_skb; | 859 | struct sk_buff *tmp_skb; |
858 | 860 | ||
859 | if (bat_priv->vis_hash) | 861 | if (bat_priv->vis.hash) |
860 | return 0; | 862 | return 0; |
861 | 863 | ||
862 | spin_lock_bh(&bat_priv->vis_hash_lock); | 864 | spin_lock_bh(&bat_priv->vis.hash_lock); |
863 | 865 | ||
864 | bat_priv->vis_hash = batadv_hash_new(256); | 866 | bat_priv->vis.hash = batadv_hash_new(256); |
865 | if (!bat_priv->vis_hash) { | 867 | if (!bat_priv->vis.hash) { |
866 | pr_err("Can't initialize vis_hash\n"); | 868 | pr_err("Can't initialize vis_hash\n"); |
867 | goto err; | 869 | goto err; |
868 | } | 870 | } |
869 | 871 | ||
870 | bat_priv->my_vis_info = kmalloc(BATADV_MAX_VIS_PACKET_SIZE, GFP_ATOMIC); | 872 | bat_priv->vis.my_info = kmalloc(BATADV_MAX_VIS_PACKET_SIZE, GFP_ATOMIC); |
871 | if (!bat_priv->my_vis_info) | 873 | if (!bat_priv->vis.my_info) |
872 | goto err; | 874 | goto err; |
873 | 875 | ||
874 | len = sizeof(*packet) + BATADV_MAX_VIS_PACKET_SIZE + ETH_HLEN; | 876 | len = sizeof(*packet) + BATADV_MAX_VIS_PACKET_SIZE + ETH_HLEN; |
875 | bat_priv->my_vis_info->skb_packet = dev_alloc_skb(len); | 877 | bat_priv->vis.my_info->skb_packet = dev_alloc_skb(len); |
876 | if (!bat_priv->my_vis_info->skb_packet) | 878 | if (!bat_priv->vis.my_info->skb_packet) |
877 | goto free_info; | 879 | goto free_info; |
878 | 880 | ||
879 | skb_reserve(bat_priv->my_vis_info->skb_packet, ETH_HLEN); | 881 | skb_reserve(bat_priv->vis.my_info->skb_packet, ETH_HLEN); |
880 | tmp_skb = bat_priv->my_vis_info->skb_packet; | 882 | tmp_skb = bat_priv->vis.my_info->skb_packet; |
881 | packet = (struct batadv_vis_packet *)skb_put(tmp_skb, sizeof(*packet)); | 883 | packet = (struct batadv_vis_packet *)skb_put(tmp_skb, sizeof(*packet)); |
882 | 884 | ||
883 | /* prefill the vis info */ | 885 | /* prefill the vis info */ |
884 | first_seen = jiffies - msecs_to_jiffies(BATADV_VIS_INTERVAL); | 886 | first_seen = jiffies - msecs_to_jiffies(BATADV_VIS_INTERVAL); |
885 | bat_priv->my_vis_info->first_seen = first_seen; | 887 | bat_priv->vis.my_info->first_seen = first_seen; |
886 | INIT_LIST_HEAD(&bat_priv->my_vis_info->recv_list); | 888 | INIT_LIST_HEAD(&bat_priv->vis.my_info->recv_list); |
887 | INIT_LIST_HEAD(&bat_priv->my_vis_info->send_list); | 889 | INIT_LIST_HEAD(&bat_priv->vis.my_info->send_list); |
888 | kref_init(&bat_priv->my_vis_info->refcount); | 890 | kref_init(&bat_priv->vis.my_info->refcount); |
889 | bat_priv->my_vis_info->bat_priv = bat_priv; | 891 | bat_priv->vis.my_info->bat_priv = bat_priv; |
890 | packet->header.version = BATADV_COMPAT_VERSION; | 892 | packet->header.version = BATADV_COMPAT_VERSION; |
891 | packet->header.packet_type = BATADV_VIS; | 893 | packet->header.packet_type = BATADV_VIS; |
892 | packet->header.ttl = BATADV_TTL; | 894 | packet->header.ttl = BATADV_TTL; |
@@ -894,28 +896,28 @@ int batadv_vis_init(struct batadv_priv *bat_priv) | |||
894 | packet->reserved = 0; | 896 | packet->reserved = 0; |
895 | packet->entries = 0; | 897 | packet->entries = 0; |
896 | 898 | ||
897 | INIT_LIST_HEAD(&bat_priv->vis_send_list); | 899 | INIT_LIST_HEAD(&bat_priv->vis.send_list); |
898 | 900 | ||
899 | hash_added = batadv_hash_add(bat_priv->vis_hash, batadv_vis_info_cmp, | 901 | hash_added = batadv_hash_add(bat_priv->vis.hash, batadv_vis_info_cmp, |
900 | batadv_vis_info_choose, | 902 | batadv_vis_info_choose, |
901 | bat_priv->my_vis_info, | 903 | bat_priv->vis.my_info, |
902 | &bat_priv->my_vis_info->hash_entry); | 904 | &bat_priv->vis.my_info->hash_entry); |
903 | if (hash_added != 0) { | 905 | if (hash_added != 0) { |
904 | pr_err("Can't add own vis packet into hash\n"); | 906 | pr_err("Can't add own vis packet into hash\n"); |
905 | /* not in hash, need to remove it manually. */ | 907 | /* not in hash, need to remove it manually. */ |
906 | kref_put(&bat_priv->my_vis_info->refcount, batadv_free_info); | 908 | kref_put(&bat_priv->vis.my_info->refcount, batadv_free_info); |
907 | goto err; | 909 | goto err; |
908 | } | 910 | } |
909 | 911 | ||
910 | spin_unlock_bh(&bat_priv->vis_hash_lock); | 912 | spin_unlock_bh(&bat_priv->vis.hash_lock); |
911 | batadv_start_vis_timer(bat_priv); | 913 | batadv_start_vis_timer(bat_priv); |
912 | return 0; | 914 | return 0; |
913 | 915 | ||
914 | free_info: | 916 | free_info: |
915 | kfree(bat_priv->my_vis_info); | 917 | kfree(bat_priv->vis.my_info); |
916 | bat_priv->my_vis_info = NULL; | 918 | bat_priv->vis.my_info = NULL; |
917 | err: | 919 | err: |
918 | spin_unlock_bh(&bat_priv->vis_hash_lock); | 920 | spin_unlock_bh(&bat_priv->vis.hash_lock); |
919 | batadv_vis_quit(bat_priv); | 921 | batadv_vis_quit(bat_priv); |
920 | return -ENOMEM; | 922 | return -ENOMEM; |
921 | } | 923 | } |
@@ -933,23 +935,23 @@ static void batadv_free_info_ref(struct hlist_node *node, void *arg) | |||
933 | /* shutdown vis-server */ | 935 | /* shutdown vis-server */ |
934 | void batadv_vis_quit(struct batadv_priv *bat_priv) | 936 | void batadv_vis_quit(struct batadv_priv *bat_priv) |
935 | { | 937 | { |
936 | if (!bat_priv->vis_hash) | 938 | if (!bat_priv->vis.hash) |
937 | return; | 939 | return; |
938 | 940 | ||
939 | cancel_delayed_work_sync(&bat_priv->vis_work); | 941 | cancel_delayed_work_sync(&bat_priv->vis.work); |
940 | 942 | ||
941 | spin_lock_bh(&bat_priv->vis_hash_lock); | 943 | spin_lock_bh(&bat_priv->vis.hash_lock); |
942 | /* properly remove, kill timers ... */ | 944 | /* properly remove, kill timers ... */ |
943 | batadv_hash_delete(bat_priv->vis_hash, batadv_free_info_ref, NULL); | 945 | batadv_hash_delete(bat_priv->vis.hash, batadv_free_info_ref, NULL); |
944 | bat_priv->vis_hash = NULL; | 946 | bat_priv->vis.hash = NULL; |
945 | bat_priv->my_vis_info = NULL; | 947 | bat_priv->vis.my_info = NULL; |
946 | spin_unlock_bh(&bat_priv->vis_hash_lock); | 948 | spin_unlock_bh(&bat_priv->vis.hash_lock); |
947 | } | 949 | } |
948 | 950 | ||
949 | /* schedule packets for (re)transmission */ | 951 | /* schedule packets for (re)transmission */ |
950 | static void batadv_start_vis_timer(struct batadv_priv *bat_priv) | 952 | static void batadv_start_vis_timer(struct batadv_priv *bat_priv) |
951 | { | 953 | { |
952 | INIT_DELAYED_WORK(&bat_priv->vis_work, batadv_send_vis_packets); | 954 | INIT_DELAYED_WORK(&bat_priv->vis.work, batadv_send_vis_packets); |
953 | queue_delayed_work(batadv_event_workqueue, &bat_priv->vis_work, | 955 | queue_delayed_work(batadv_event_workqueue, &bat_priv->vis.work, |
954 | msecs_to_jiffies(BATADV_VIS_INTERVAL)); | 956 | msecs_to_jiffies(BATADV_VIS_INTERVAL)); |
955 | } | 957 | } |
diff --git a/net/batman-adv/vis.h b/net/batman-adv/vis.h index 84e716ed8963..873282fa86da 100644 --- a/net/batman-adv/vis.h +++ b/net/batman-adv/vis.h | |||
@@ -20,7 +20,7 @@ | |||
20 | #ifndef _NET_BATMAN_ADV_VIS_H_ | 20 | #ifndef _NET_BATMAN_ADV_VIS_H_ |
21 | #define _NET_BATMAN_ADV_VIS_H_ | 21 | #define _NET_BATMAN_ADV_VIS_H_ |
22 | 22 | ||
23 | /* timeout of vis packets in miliseconds */ | 23 | /* timeout of vis packets in milliseconds */ |
24 | #define BATADV_VIS_TIMEOUT 200000 | 24 | #define BATADV_VIS_TIMEOUT 200000 |
25 | 25 | ||
26 | int batadv_vis_seq_print_text(struct seq_file *seq, void *offset); | 26 | int batadv_vis_seq_print_text(struct seq_file *seq, void *offset); |
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index 4ff0bf3ba9a5..0760d1fed6f0 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c | |||
@@ -316,7 +316,7 @@ send_rsp: | |||
316 | static inline int a2mp_cmd_rsp(struct amp_mgr *mgr, struct sk_buff *skb, | 316 | static inline int a2mp_cmd_rsp(struct amp_mgr *mgr, struct sk_buff *skb, |
317 | struct a2mp_cmd *hdr) | 317 | struct a2mp_cmd *hdr) |
318 | { | 318 | { |
319 | BT_DBG("ident %d code %d", hdr->ident, hdr->code); | 319 | BT_DBG("ident %d code 0x%2.2x", hdr->ident, hdr->code); |
320 | 320 | ||
321 | skb_pull(skb, le16_to_cpu(hdr->len)); | 321 | skb_pull(skb, le16_to_cpu(hdr->len)); |
322 | return 0; | 322 | return 0; |
@@ -325,17 +325,19 @@ static inline int a2mp_cmd_rsp(struct amp_mgr *mgr, struct sk_buff *skb, | |||
325 | /* Handle A2MP signalling */ | 325 | /* Handle A2MP signalling */ |
326 | static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) | 326 | static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) |
327 | { | 327 | { |
328 | struct a2mp_cmd *hdr = (void *) skb->data; | 328 | struct a2mp_cmd *hdr; |
329 | struct amp_mgr *mgr = chan->data; | 329 | struct amp_mgr *mgr = chan->data; |
330 | int err = 0; | 330 | int err = 0; |
331 | 331 | ||
332 | amp_mgr_get(mgr); | 332 | amp_mgr_get(mgr); |
333 | 333 | ||
334 | while (skb->len >= sizeof(*hdr)) { | 334 | while (skb->len >= sizeof(*hdr)) { |
335 | struct a2mp_cmd *hdr = (void *) skb->data; | 335 | u16 len; |
336 | u16 len = le16_to_cpu(hdr->len); | ||
337 | 336 | ||
338 | BT_DBG("code 0x%02x id %d len %d", hdr->code, hdr->ident, len); | 337 | hdr = (void *) skb->data; |
338 | len = le16_to_cpu(hdr->len); | ||
339 | |||
340 | BT_DBG("code 0x%2.2x id %d len %u", hdr->code, hdr->ident, len); | ||
339 | 341 | ||
340 | skb_pull(skb, sizeof(*hdr)); | 342 | skb_pull(skb, sizeof(*hdr)); |
341 | 343 | ||
@@ -393,7 +395,9 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) | |||
393 | 395 | ||
394 | if (err) { | 396 | if (err) { |
395 | struct a2mp_cmd_rej rej; | 397 | struct a2mp_cmd_rej rej; |
398 | |||
396 | rej.reason = __constant_cpu_to_le16(0); | 399 | rej.reason = __constant_cpu_to_le16(0); |
400 | hdr = (void *) skb->data; | ||
397 | 401 | ||
398 | BT_DBG("Send A2MP Rej: cmd 0x%2.2x err %d", hdr->code, err); | 402 | BT_DBG("Send A2MP Rej: cmd 0x%2.2x err %d", hdr->code, err); |
399 | 403 | ||
@@ -412,7 +416,7 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) | |||
412 | 416 | ||
413 | static void a2mp_chan_close_cb(struct l2cap_chan *chan) | 417 | static void a2mp_chan_close_cb(struct l2cap_chan *chan) |
414 | { | 418 | { |
415 | l2cap_chan_destroy(chan); | 419 | l2cap_chan_put(chan); |
416 | } | 420 | } |
417 | 421 | ||
418 | static void a2mp_chan_state_change_cb(struct l2cap_chan *chan, int state) | 422 | static void a2mp_chan_state_change_cb(struct l2cap_chan *chan, int state) |
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index f7db5792ec64..58f9762b339a 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <asm/ioctls.h> | 28 | #include <asm/ioctls.h> |
29 | 29 | ||
30 | #include <net/bluetooth/bluetooth.h> | 30 | #include <net/bluetooth/bluetooth.h> |
31 | #include <linux/proc_fs.h> | ||
31 | 32 | ||
32 | #define VERSION "2.16" | 33 | #define VERSION "2.16" |
33 | 34 | ||
@@ -532,6 +533,146 @@ int bt_sock_wait_state(struct sock *sk, int state, unsigned long timeo) | |||
532 | } | 533 | } |
533 | EXPORT_SYMBOL(bt_sock_wait_state); | 534 | EXPORT_SYMBOL(bt_sock_wait_state); |
534 | 535 | ||
536 | #ifdef CONFIG_PROC_FS | ||
537 | struct bt_seq_state { | ||
538 | struct bt_sock_list *l; | ||
539 | }; | ||
540 | |||
541 | static void *bt_seq_start(struct seq_file *seq, loff_t *pos) | ||
542 | __acquires(seq->private->l->lock) | ||
543 | { | ||
544 | struct bt_seq_state *s = seq->private; | ||
545 | struct bt_sock_list *l = s->l; | ||
546 | |||
547 | read_lock(&l->lock); | ||
548 | return seq_hlist_start_head(&l->head, *pos); | ||
549 | } | ||
550 | |||
551 | static void *bt_seq_next(struct seq_file *seq, void *v, loff_t *pos) | ||
552 | { | ||
553 | struct bt_seq_state *s = seq->private; | ||
554 | struct bt_sock_list *l = s->l; | ||
555 | |||
556 | return seq_hlist_next(v, &l->head, pos); | ||
557 | } | ||
558 | |||
559 | static void bt_seq_stop(struct seq_file *seq, void *v) | ||
560 | __releases(seq->private->l->lock) | ||
561 | { | ||
562 | struct bt_seq_state *s = seq->private; | ||
563 | struct bt_sock_list *l = s->l; | ||
564 | |||
565 | read_unlock(&l->lock); | ||
566 | } | ||
567 | |||
568 | static int bt_seq_show(struct seq_file *seq, void *v) | ||
569 | { | ||
570 | struct sock *sk; | ||
571 | struct bt_sock *bt; | ||
572 | struct bt_seq_state *s = seq->private; | ||
573 | struct bt_sock_list *l = s->l; | ||
574 | bdaddr_t src_baswapped, dst_baswapped; | ||
575 | |||
576 | if (v == SEQ_START_TOKEN) { | ||
577 | seq_puts(seq ,"sk RefCnt Rmem Wmem User Inode Src Dst Parent"); | ||
578 | |||
579 | if (l->custom_seq_show) { | ||
580 | seq_putc(seq, ' '); | ||
581 | l->custom_seq_show(seq, v); | ||
582 | } | ||
583 | |||
584 | seq_putc(seq, '\n'); | ||
585 | } else { | ||
586 | sk = sk_entry(v); | ||
587 | bt = bt_sk(sk); | ||
588 | baswap(&src_baswapped, &bt->src); | ||
589 | baswap(&dst_baswapped, &bt->dst); | ||
590 | |||
591 | seq_printf(seq, "%pK %-6d %-6u %-6u %-6u %-6lu %pM %pM %-6lu", | ||
592 | sk, | ||
593 | atomic_read(&sk->sk_refcnt), | ||
594 | sk_rmem_alloc_get(sk), | ||
595 | sk_wmem_alloc_get(sk), | ||
596 | sock_i_uid(sk), | ||
597 | sock_i_ino(sk), | ||
598 | &src_baswapped, | ||
599 | &dst_baswapped, | ||
600 | bt->parent? sock_i_ino(bt->parent): 0LU); | ||
601 | |||
602 | if (l->custom_seq_show) { | ||
603 | seq_putc(seq, ' '); | ||
604 | l->custom_seq_show(seq, v); | ||
605 | } | ||
606 | |||
607 | seq_putc(seq, '\n'); | ||
608 | } | ||
609 | return 0; | ||
610 | } | ||
611 | |||
612 | static struct seq_operations bt_seq_ops = { | ||
613 | .start = bt_seq_start, | ||
614 | .next = bt_seq_next, | ||
615 | .stop = bt_seq_stop, | ||
616 | .show = bt_seq_show, | ||
617 | }; | ||
618 | |||
619 | static int bt_seq_open(struct inode *inode, struct file *file) | ||
620 | { | ||
621 | struct bt_sock_list *sk_list; | ||
622 | struct bt_seq_state *s; | ||
623 | |||
624 | sk_list = PDE(inode)->data; | ||
625 | s = __seq_open_private(file, &bt_seq_ops, | ||
626 | sizeof(struct bt_seq_state)); | ||
627 | if (s == NULL) | ||
628 | return -ENOMEM; | ||
629 | |||
630 | s->l = sk_list; | ||
631 | return 0; | ||
632 | } | ||
633 | |||
634 | int bt_procfs_init(struct module* module, struct net *net, const char *name, | ||
635 | struct bt_sock_list* sk_list, | ||
636 | int (* seq_show)(struct seq_file *, void *)) | ||
637 | { | ||
638 | struct proc_dir_entry * pde; | ||
639 | |||
640 | sk_list->custom_seq_show = seq_show; | ||
641 | |||
642 | sk_list->fops.owner = module; | ||
643 | sk_list->fops.open = bt_seq_open; | ||
644 | sk_list->fops.read = seq_read; | ||
645 | sk_list->fops.llseek = seq_lseek; | ||
646 | sk_list->fops.release = seq_release_private; | ||
647 | |||
648 | pde = proc_net_fops_create(net, name, 0, &sk_list->fops); | ||
649 | if (pde == NULL) | ||
650 | return -ENOMEM; | ||
651 | |||
652 | pde->data = sk_list; | ||
653 | |||
654 | return 0; | ||
655 | } | ||
656 | |||
657 | void bt_procfs_cleanup(struct net *net, const char *name) | ||
658 | { | ||
659 | proc_net_remove(net, name); | ||
660 | } | ||
661 | #else | ||
662 | int bt_procfs_init(struct module* module, struct net *net, const char *name, | ||
663 | struct bt_sock_list* sk_list, | ||
664 | int (* seq_show)(struct seq_file *, void *)) | ||
665 | { | ||
666 | return 0; | ||
667 | } | ||
668 | |||
669 | void bt_procfs_cleanup(struct net *net, const char *name) | ||
670 | { | ||
671 | } | ||
672 | #endif | ||
673 | EXPORT_SYMBOL(bt_procfs_init); | ||
674 | EXPORT_SYMBOL(bt_procfs_cleanup); | ||
675 | |||
535 | static struct net_proto_family bt_sock_family_ops = { | 676 | static struct net_proto_family bt_sock_family_ops = { |
536 | .owner = THIS_MODULE, | 677 | .owner = THIS_MODULE, |
537 | .family = PF_BLUETOOTH, | 678 | .family = PF_BLUETOOTH, |
diff --git a/net/bluetooth/bnep/sock.c b/net/bluetooth/bnep/sock.c index 5e5f5b410e0b..5b6cc0bf4dec 100644 --- a/net/bluetooth/bnep/sock.c +++ b/net/bluetooth/bnep/sock.c | |||
@@ -29,6 +29,10 @@ | |||
29 | 29 | ||
30 | #include "bnep.h" | 30 | #include "bnep.h" |
31 | 31 | ||
32 | static struct bt_sock_list bnep_sk_list = { | ||
33 | .lock = __RW_LOCK_UNLOCKED(bnep_sk_list.lock) | ||
34 | }; | ||
35 | |||
32 | static int bnep_sock_release(struct socket *sock) | 36 | static int bnep_sock_release(struct socket *sock) |
33 | { | 37 | { |
34 | struct sock *sk = sock->sk; | 38 | struct sock *sk = sock->sk; |
@@ -38,6 +42,8 @@ static int bnep_sock_release(struct socket *sock) | |||
38 | if (!sk) | 42 | if (!sk) |
39 | return 0; | 43 | return 0; |
40 | 44 | ||
45 | bt_sock_unlink(&bnep_sk_list, sk); | ||
46 | |||
41 | sock_orphan(sk); | 47 | sock_orphan(sk); |
42 | sock_put(sk); | 48 | sock_put(sk); |
43 | return 0; | 49 | return 0; |
@@ -204,6 +210,7 @@ static int bnep_sock_create(struct net *net, struct socket *sock, int protocol, | |||
204 | sk->sk_protocol = protocol; | 210 | sk->sk_protocol = protocol; |
205 | sk->sk_state = BT_OPEN; | 211 | sk->sk_state = BT_OPEN; |
206 | 212 | ||
213 | bt_sock_link(&bnep_sk_list, sk); | ||
207 | return 0; | 214 | return 0; |
208 | } | 215 | } |
209 | 216 | ||
@@ -222,19 +229,30 @@ int __init bnep_sock_init(void) | |||
222 | return err; | 229 | return err; |
223 | 230 | ||
224 | err = bt_sock_register(BTPROTO_BNEP, &bnep_sock_family_ops); | 231 | err = bt_sock_register(BTPROTO_BNEP, &bnep_sock_family_ops); |
225 | if (err < 0) | 232 | if (err < 0) { |
233 | BT_ERR("Can't register BNEP socket"); | ||
226 | goto error; | 234 | goto error; |
235 | } | ||
236 | |||
237 | err = bt_procfs_init(THIS_MODULE, &init_net, "bnep", &bnep_sk_list, NULL); | ||
238 | if (err < 0) { | ||
239 | BT_ERR("Failed to create BNEP proc file"); | ||
240 | bt_sock_unregister(BTPROTO_BNEP); | ||
241 | goto error; | ||
242 | } | ||
243 | |||
244 | BT_INFO("BNEP socket layer initialized"); | ||
227 | 245 | ||
228 | return 0; | 246 | return 0; |
229 | 247 | ||
230 | error: | 248 | error: |
231 | BT_ERR("Can't register BNEP socket"); | ||
232 | proto_unregister(&bnep_proto); | 249 | proto_unregister(&bnep_proto); |
233 | return err; | 250 | return err; |
234 | } | 251 | } |
235 | 252 | ||
236 | void __exit bnep_sock_cleanup(void) | 253 | void __exit bnep_sock_cleanup(void) |
237 | { | 254 | { |
255 | bt_procfs_cleanup(&init_net, "bnep"); | ||
238 | if (bt_sock_unregister(BTPROTO_BNEP) < 0) | 256 | if (bt_sock_unregister(BTPROTO_BNEP) < 0) |
239 | BT_ERR("Can't unregister BNEP socket"); | 257 | BT_ERR("Can't unregister BNEP socket"); |
240 | 258 | ||
diff --git a/net/bluetooth/cmtp/sock.c b/net/bluetooth/cmtp/sock.c index 311668d14571..d5cacef52748 100644 --- a/net/bluetooth/cmtp/sock.c +++ b/net/bluetooth/cmtp/sock.c | |||
@@ -42,6 +42,10 @@ | |||
42 | 42 | ||
43 | #include "cmtp.h" | 43 | #include "cmtp.h" |
44 | 44 | ||
45 | static struct bt_sock_list cmtp_sk_list = { | ||
46 | .lock = __RW_LOCK_UNLOCKED(cmtp_sk_list.lock) | ||
47 | }; | ||
48 | |||
45 | static int cmtp_sock_release(struct socket *sock) | 49 | static int cmtp_sock_release(struct socket *sock) |
46 | { | 50 | { |
47 | struct sock *sk = sock->sk; | 51 | struct sock *sk = sock->sk; |
@@ -51,6 +55,8 @@ static int cmtp_sock_release(struct socket *sock) | |||
51 | if (!sk) | 55 | if (!sk) |
52 | return 0; | 56 | return 0; |
53 | 57 | ||
58 | bt_sock_unlink(&cmtp_sk_list, sk); | ||
59 | |||
54 | sock_orphan(sk); | 60 | sock_orphan(sk); |
55 | sock_put(sk); | 61 | sock_put(sk); |
56 | 62 | ||
@@ -214,6 +220,8 @@ static int cmtp_sock_create(struct net *net, struct socket *sock, int protocol, | |||
214 | sk->sk_protocol = protocol; | 220 | sk->sk_protocol = protocol; |
215 | sk->sk_state = BT_OPEN; | 221 | sk->sk_state = BT_OPEN; |
216 | 222 | ||
223 | bt_sock_link(&cmtp_sk_list, sk); | ||
224 | |||
217 | return 0; | 225 | return 0; |
218 | } | 226 | } |
219 | 227 | ||
@@ -232,19 +240,30 @@ int cmtp_init_sockets(void) | |||
232 | return err; | 240 | return err; |
233 | 241 | ||
234 | err = bt_sock_register(BTPROTO_CMTP, &cmtp_sock_family_ops); | 242 | err = bt_sock_register(BTPROTO_CMTP, &cmtp_sock_family_ops); |
235 | if (err < 0) | 243 | if (err < 0) { |
244 | BT_ERR("Can't register CMTP socket"); | ||
236 | goto error; | 245 | goto error; |
246 | } | ||
247 | |||
248 | err = bt_procfs_init(THIS_MODULE, &init_net, "cmtp", &cmtp_sk_list, NULL); | ||
249 | if (err < 0) { | ||
250 | BT_ERR("Failed to create CMTP proc file"); | ||
251 | bt_sock_unregister(BTPROTO_HIDP); | ||
252 | goto error; | ||
253 | } | ||
254 | |||
255 | BT_INFO("CMTP socket layer initialized"); | ||
237 | 256 | ||
238 | return 0; | 257 | return 0; |
239 | 258 | ||
240 | error: | 259 | error: |
241 | BT_ERR("Can't register CMTP socket"); | ||
242 | proto_unregister(&cmtp_proto); | 260 | proto_unregister(&cmtp_proto); |
243 | return err; | 261 | return err; |
244 | } | 262 | } |
245 | 263 | ||
246 | void cmtp_cleanup_sockets(void) | 264 | void cmtp_cleanup_sockets(void) |
247 | { | 265 | { |
266 | bt_procfs_cleanup(&init_net, "cmtp"); | ||
248 | if (bt_sock_unregister(BTPROTO_CMTP) < 0) | 267 | if (bt_sock_unregister(BTPROTO_CMTP) < 0) |
249 | BT_ERR("Can't unregister CMTP socket"); | 268 | BT_ERR("Can't unregister CMTP socket"); |
250 | 269 | ||
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index d4de5db18d5a..fa974a19d365 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -696,7 +696,8 @@ int hci_dev_open(__u16 dev) | |||
696 | hci_dev_hold(hdev); | 696 | hci_dev_hold(hdev); |
697 | set_bit(HCI_UP, &hdev->flags); | 697 | set_bit(HCI_UP, &hdev->flags); |
698 | hci_notify(hdev, HCI_DEV_UP); | 698 | hci_notify(hdev, HCI_DEV_UP); |
699 | if (!test_bit(HCI_SETUP, &hdev->dev_flags)) { | 699 | if (!test_bit(HCI_SETUP, &hdev->dev_flags) && |
700 | mgmt_valid_hdev(hdev)) { | ||
700 | hci_dev_lock(hdev); | 701 | hci_dev_lock(hdev); |
701 | mgmt_powered(hdev, 1); | 702 | mgmt_powered(hdev, 1); |
702 | hci_dev_unlock(hdev); | 703 | hci_dev_unlock(hdev); |
@@ -797,7 +798,8 @@ static int hci_dev_do_close(struct hci_dev *hdev) | |||
797 | * and no tasks are scheduled. */ | 798 | * and no tasks are scheduled. */ |
798 | hdev->close(hdev); | 799 | hdev->close(hdev); |
799 | 800 | ||
800 | if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) { | 801 | if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags) && |
802 | mgmt_valid_hdev(hdev)) { | ||
801 | hci_dev_lock(hdev); | 803 | hci_dev_lock(hdev); |
802 | mgmt_powered(hdev, 0); | 804 | mgmt_powered(hdev, 0); |
803 | hci_dev_unlock(hdev); | 805 | hci_dev_unlock(hdev); |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 41ff978a33f9..4fd2cf3bcd05 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -513,7 +513,7 @@ static void hci_setup_event_mask(struct hci_dev *hdev) | |||
513 | if (hdev->features[3] & LMP_RSSI_INQ) | 513 | if (hdev->features[3] & LMP_RSSI_INQ) |
514 | events[4] |= 0x02; /* Inquiry Result with RSSI */ | 514 | events[4] |= 0x02; /* Inquiry Result with RSSI */ |
515 | 515 | ||
516 | if (hdev->features[5] & LMP_SNIFF_SUBR) | 516 | if (lmp_sniffsubr_capable(hdev)) |
517 | events[5] |= 0x20; /* Sniff Subrating */ | 517 | events[5] |= 0x20; /* Sniff Subrating */ |
518 | 518 | ||
519 | if (hdev->features[5] & LMP_PAUSE_ENC) | 519 | if (hdev->features[5] & LMP_PAUSE_ENC) |
@@ -522,13 +522,13 @@ static void hci_setup_event_mask(struct hci_dev *hdev) | |||
522 | if (hdev->features[6] & LMP_EXT_INQ) | 522 | if (hdev->features[6] & LMP_EXT_INQ) |
523 | events[5] |= 0x40; /* Extended Inquiry Result */ | 523 | events[5] |= 0x40; /* Extended Inquiry Result */ |
524 | 524 | ||
525 | if (hdev->features[6] & LMP_NO_FLUSH) | 525 | if (lmp_no_flush_capable(hdev)) |
526 | events[7] |= 0x01; /* Enhanced Flush Complete */ | 526 | events[7] |= 0x01; /* Enhanced Flush Complete */ |
527 | 527 | ||
528 | if (hdev->features[7] & LMP_LSTO) | 528 | if (hdev->features[7] & LMP_LSTO) |
529 | events[6] |= 0x80; /* Link Supervision Timeout Changed */ | 529 | events[6] |= 0x80; /* Link Supervision Timeout Changed */ |
530 | 530 | ||
531 | if (hdev->features[6] & LMP_SIMPLE_PAIR) { | 531 | if (lmp_ssp_capable(hdev)) { |
532 | events[6] |= 0x01; /* IO Capability Request */ | 532 | events[6] |= 0x01; /* IO Capability Request */ |
533 | events[6] |= 0x02; /* IO Capability Response */ | 533 | events[6] |= 0x02; /* IO Capability Response */ |
534 | events[6] |= 0x04; /* User Confirmation Request */ | 534 | events[6] |= 0x04; /* User Confirmation Request */ |
@@ -541,7 +541,7 @@ static void hci_setup_event_mask(struct hci_dev *hdev) | |||
541 | * Features Notification */ | 541 | * Features Notification */ |
542 | } | 542 | } |
543 | 543 | ||
544 | if (hdev->features[4] & LMP_LE) | 544 | if (lmp_le_capable(hdev)) |
545 | events[7] |= 0x20; /* LE Meta-Event */ | 545 | events[7] |= 0x20; /* LE Meta-Event */ |
546 | 546 | ||
547 | hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); | 547 | hci_send_cmd(hdev, HCI_OP_SET_EVENT_MASK, sizeof(events), events); |
@@ -623,11 +623,11 @@ static void hci_setup_link_policy(struct hci_dev *hdev) | |||
623 | struct hci_cp_write_def_link_policy cp; | 623 | struct hci_cp_write_def_link_policy cp; |
624 | u16 link_policy = 0; | 624 | u16 link_policy = 0; |
625 | 625 | ||
626 | if (hdev->features[0] & LMP_RSWITCH) | 626 | if (lmp_rswitch_capable(hdev)) |
627 | link_policy |= HCI_LP_RSWITCH; | 627 | link_policy |= HCI_LP_RSWITCH; |
628 | if (hdev->features[0] & LMP_HOLD) | 628 | if (hdev->features[0] & LMP_HOLD) |
629 | link_policy |= HCI_LP_HOLD; | 629 | link_policy |= HCI_LP_HOLD; |
630 | if (hdev->features[0] & LMP_SNIFF) | 630 | if (lmp_sniff_capable(hdev)) |
631 | link_policy |= HCI_LP_SNIFF; | 631 | link_policy |= HCI_LP_SNIFF; |
632 | if (hdev->features[1] & LMP_PARK) | 632 | if (hdev->features[1] & LMP_PARK) |
633 | link_policy |= HCI_LP_PARK; | 633 | link_policy |= HCI_LP_PARK; |
@@ -686,7 +686,7 @@ static void hci_cc_read_local_features(struct hci_dev *hdev, | |||
686 | hdev->esco_type |= (ESCO_HV3); | 686 | hdev->esco_type |= (ESCO_HV3); |
687 | } | 687 | } |
688 | 688 | ||
689 | if (hdev->features[3] & LMP_ESCO) | 689 | if (lmp_esco_capable(hdev)) |
690 | hdev->esco_type |= (ESCO_EV3); | 690 | hdev->esco_type |= (ESCO_EV3); |
691 | 691 | ||
692 | if (hdev->features[4] & LMP_EV4) | 692 | if (hdev->features[4] & LMP_EV4) |
@@ -746,7 +746,7 @@ static void hci_cc_read_local_ext_features(struct hci_dev *hdev, | |||
746 | break; | 746 | break; |
747 | } | 747 | } |
748 | 748 | ||
749 | if (test_bit(HCI_INIT, &hdev->flags) && hdev->features[4] & LMP_LE) | 749 | if (test_bit(HCI_INIT, &hdev->flags) && lmp_le_capable(hdev)) |
750 | hci_set_le_support(hdev); | 750 | hci_set_le_support(hdev); |
751 | 751 | ||
752 | done: | 752 | done: |
@@ -1365,6 +1365,9 @@ static bool hci_resolve_next_name(struct hci_dev *hdev) | |||
1365 | return false; | 1365 | return false; |
1366 | 1366 | ||
1367 | e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); | 1367 | e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, NAME_NEEDED); |
1368 | if (!e) | ||
1369 | return false; | ||
1370 | |||
1368 | if (hci_resolve_name(hdev, e) == 0) { | 1371 | if (hci_resolve_name(hdev, e) == 0) { |
1369 | e->name_state = NAME_PENDING; | 1372 | e->name_state = NAME_PENDING; |
1370 | return true; | 1373 | return true; |
@@ -1393,12 +1396,20 @@ static void hci_check_pending_name(struct hci_dev *hdev, struct hci_conn *conn, | |||
1393 | return; | 1396 | return; |
1394 | 1397 | ||
1395 | e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING); | 1398 | e = hci_inquiry_cache_lookup_resolve(hdev, bdaddr, NAME_PENDING); |
1396 | if (e) { | 1399 | /* If the device was not found in a list of found devices names of which |
1400 | * are pending. there is no need to continue resolving a next name as it | ||
1401 | * will be done upon receiving another Remote Name Request Complete | ||
1402 | * Event */ | ||
1403 | if (!e) | ||
1404 | return; | ||
1405 | |||
1406 | list_del(&e->list); | ||
1407 | if (name) { | ||
1397 | e->name_state = NAME_KNOWN; | 1408 | e->name_state = NAME_KNOWN; |
1398 | list_del(&e->list); | 1409 | mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, |
1399 | if (name) | 1410 | e->data.rssi, name, name_len); |
1400 | mgmt_remote_name(hdev, bdaddr, ACL_LINK, 0x00, | 1411 | } else { |
1401 | e->data.rssi, name, name_len); | 1412 | e->name_state = NAME_NOT_KNOWN; |
1402 | } | 1413 | } |
1403 | 1414 | ||
1404 | if (hci_resolve_next_name(hdev)) | 1415 | if (hci_resolve_next_name(hdev)) |
@@ -1614,43 +1625,30 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) | |||
1614 | 1625 | ||
1615 | static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) | 1626 | static void hci_cs_le_create_conn(struct hci_dev *hdev, __u8 status) |
1616 | { | 1627 | { |
1617 | struct hci_cp_le_create_conn *cp; | ||
1618 | struct hci_conn *conn; | 1628 | struct hci_conn *conn; |
1619 | 1629 | ||
1620 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | 1630 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
1621 | 1631 | ||
1622 | cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN); | 1632 | if (status) { |
1623 | if (!cp) | 1633 | hci_dev_lock(hdev); |
1624 | return; | ||
1625 | 1634 | ||
1626 | hci_dev_lock(hdev); | 1635 | conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); |
1636 | if (!conn) { | ||
1637 | hci_dev_unlock(hdev); | ||
1638 | return; | ||
1639 | } | ||
1627 | 1640 | ||
1628 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr); | 1641 | BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&conn->dst), |
1642 | conn); | ||
1629 | 1643 | ||
1630 | BT_DBG("%s bdaddr %s conn %p", hdev->name, batostr(&cp->peer_addr), | 1644 | conn->state = BT_CLOSED; |
1631 | conn); | 1645 | mgmt_connect_failed(hdev, &conn->dst, conn->type, |
1646 | conn->dst_type, status); | ||
1647 | hci_proto_connect_cfm(conn, status); | ||
1648 | hci_conn_del(conn); | ||
1632 | 1649 | ||
1633 | if (status) { | 1650 | hci_dev_unlock(hdev); |
1634 | if (conn && conn->state == BT_CONNECT) { | ||
1635 | conn->state = BT_CLOSED; | ||
1636 | mgmt_connect_failed(hdev, &cp->peer_addr, conn->type, | ||
1637 | conn->dst_type, status); | ||
1638 | hci_proto_connect_cfm(conn, status); | ||
1639 | hci_conn_del(conn); | ||
1640 | } | ||
1641 | } else { | ||
1642 | if (!conn) { | ||
1643 | conn = hci_conn_add(hdev, LE_LINK, &cp->peer_addr); | ||
1644 | if (conn) { | ||
1645 | conn->dst_type = cp->peer_addr_type; | ||
1646 | conn->out = true; | ||
1647 | } else { | ||
1648 | BT_ERR("No memory for new connection"); | ||
1649 | } | ||
1650 | } | ||
1651 | } | 1651 | } |
1652 | |||
1653 | hci_dev_unlock(hdev); | ||
1654 | } | 1652 | } |
1655 | 1653 | ||
1656 | static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) | 1654 | static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) |
@@ -1762,7 +1760,12 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
1762 | if (conn->type == ACL_LINK) { | 1760 | if (conn->type == ACL_LINK) { |
1763 | conn->state = BT_CONFIG; | 1761 | conn->state = BT_CONFIG; |
1764 | hci_conn_hold(conn); | 1762 | hci_conn_hold(conn); |
1765 | conn->disc_timeout = HCI_DISCONN_TIMEOUT; | 1763 | |
1764 | if (!conn->out && !hci_conn_ssp_enabled(conn) && | ||
1765 | !hci_find_link_key(hdev, &ev->bdaddr)) | ||
1766 | conn->disc_timeout = HCI_PAIRING_TIMEOUT; | ||
1767 | else | ||
1768 | conn->disc_timeout = HCI_DISCONN_TIMEOUT; | ||
1766 | } else | 1769 | } else |
1767 | conn->state = BT_CONNECTED; | 1770 | conn->state = BT_CONNECTED; |
1768 | 1771 | ||
@@ -3252,12 +3255,8 @@ static void hci_user_passkey_request_evt(struct hci_dev *hdev, | |||
3252 | 3255 | ||
3253 | BT_DBG("%s", hdev->name); | 3256 | BT_DBG("%s", hdev->name); |
3254 | 3257 | ||
3255 | hci_dev_lock(hdev); | ||
3256 | |||
3257 | if (test_bit(HCI_MGMT, &hdev->dev_flags)) | 3258 | if (test_bit(HCI_MGMT, &hdev->dev_flags)) |
3258 | mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); | 3259 | mgmt_user_passkey_request(hdev, &ev->bdaddr, ACL_LINK, 0); |
3259 | |||
3260 | hci_dev_unlock(hdev); | ||
3261 | } | 3260 | } |
3262 | 3261 | ||
3263 | static void hci_simple_pair_complete_evt(struct hci_dev *hdev, | 3262 | static void hci_simple_pair_complete_evt(struct hci_dev *hdev, |
@@ -3350,11 +3349,23 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
3350 | 3349 | ||
3351 | hci_dev_lock(hdev); | 3350 | hci_dev_lock(hdev); |
3352 | 3351 | ||
3353 | if (ev->status) { | 3352 | conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); |
3354 | conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); | 3353 | if (!conn) { |
3355 | if (!conn) | 3354 | conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); |
3355 | if (!conn) { | ||
3356 | BT_ERR("No memory for new connection"); | ||
3356 | goto unlock; | 3357 | goto unlock; |
3358 | } | ||
3359 | |||
3360 | conn->dst_type = ev->bdaddr_type; | ||
3357 | 3361 | ||
3362 | if (ev->role == LE_CONN_ROLE_MASTER) { | ||
3363 | conn->out = true; | ||
3364 | conn->link_mode |= HCI_LM_MASTER; | ||
3365 | } | ||
3366 | } | ||
3367 | |||
3368 | if (ev->status) { | ||
3358 | mgmt_connect_failed(hdev, &conn->dst, conn->type, | 3369 | mgmt_connect_failed(hdev, &conn->dst, conn->type, |
3359 | conn->dst_type, ev->status); | 3370 | conn->dst_type, ev->status); |
3360 | hci_proto_connect_cfm(conn, ev->status); | 3371 | hci_proto_connect_cfm(conn, ev->status); |
@@ -3363,18 +3374,6 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
3363 | goto unlock; | 3374 | goto unlock; |
3364 | } | 3375 | } |
3365 | 3376 | ||
3366 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &ev->bdaddr); | ||
3367 | if (!conn) { | ||
3368 | conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); | ||
3369 | if (!conn) { | ||
3370 | BT_ERR("No memory for new connection"); | ||
3371 | hci_dev_unlock(hdev); | ||
3372 | return; | ||
3373 | } | ||
3374 | |||
3375 | conn->dst_type = ev->bdaddr_type; | ||
3376 | } | ||
3377 | |||
3378 | if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) | 3377 | if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) |
3379 | mgmt_device_connected(hdev, &ev->bdaddr, conn->type, | 3378 | mgmt_device_connected(hdev, &ev->bdaddr, conn->type, |
3380 | conn->dst_type, 0, NULL, 0, NULL); | 3379 | conn->dst_type, 0, NULL, 0, NULL); |
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index a7f04de03d79..bb64331db3b7 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c | |||
@@ -694,6 +694,7 @@ static int hci_sock_getname(struct socket *sock, struct sockaddr *addr, | |||
694 | *addr_len = sizeof(*haddr); | 694 | *addr_len = sizeof(*haddr); |
695 | haddr->hci_family = AF_BLUETOOTH; | 695 | haddr->hci_family = AF_BLUETOOTH; |
696 | haddr->hci_dev = hdev->id; | 696 | haddr->hci_dev = hdev->id; |
697 | haddr->hci_channel= 0; | ||
697 | 698 | ||
698 | release_sock(sk); | 699 | release_sock(sk); |
699 | return 0; | 700 | return 0; |
@@ -1009,6 +1010,7 @@ static int hci_sock_getsockopt(struct socket *sock, int level, int optname, | |||
1009 | { | 1010 | { |
1010 | struct hci_filter *f = &hci_pi(sk)->filter; | 1011 | struct hci_filter *f = &hci_pi(sk)->filter; |
1011 | 1012 | ||
1013 | memset(&uf, 0, sizeof(uf)); | ||
1012 | uf.type_mask = f->type_mask; | 1014 | uf.type_mask = f->type_mask; |
1013 | uf.opcode = f->opcode; | 1015 | uf.opcode = f->opcode; |
1014 | uf.event_mask[0] = *((u32 *) f->event_mask + 0); | 1016 | uf.event_mask[0] = *((u32 *) f->event_mask + 0); |
@@ -1100,21 +1102,30 @@ int __init hci_sock_init(void) | |||
1100 | return err; | 1102 | return err; |
1101 | 1103 | ||
1102 | err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops); | 1104 | err = bt_sock_register(BTPROTO_HCI, &hci_sock_family_ops); |
1103 | if (err < 0) | 1105 | if (err < 0) { |
1106 | BT_ERR("HCI socket registration failed"); | ||
1104 | goto error; | 1107 | goto error; |
1108 | } | ||
1109 | |||
1110 | err = bt_procfs_init(THIS_MODULE, &init_net, "hci", &hci_sk_list, NULL); | ||
1111 | if (err < 0) { | ||
1112 | BT_ERR("Failed to create HCI proc file"); | ||
1113 | bt_sock_unregister(BTPROTO_HCI); | ||
1114 | goto error; | ||
1115 | } | ||
1105 | 1116 | ||
1106 | BT_INFO("HCI socket layer initialized"); | 1117 | BT_INFO("HCI socket layer initialized"); |
1107 | 1118 | ||
1108 | return 0; | 1119 | return 0; |
1109 | 1120 | ||
1110 | error: | 1121 | error: |
1111 | BT_ERR("HCI socket registration failed"); | ||
1112 | proto_unregister(&hci_sk_proto); | 1122 | proto_unregister(&hci_sk_proto); |
1113 | return err; | 1123 | return err; |
1114 | } | 1124 | } |
1115 | 1125 | ||
1116 | void hci_sock_cleanup(void) | 1126 | void hci_sock_cleanup(void) |
1117 | { | 1127 | { |
1128 | bt_procfs_cleanup(&init_net, "hci"); | ||
1118 | if (bt_sock_unregister(BTPROTO_HCI) < 0) | 1129 | if (bt_sock_unregister(BTPROTO_HCI) < 0) |
1119 | BT_ERR("HCI socket unregistration failed"); | 1130 | BT_ERR("HCI socket unregistration failed"); |
1120 | 1131 | ||
diff --git a/net/bluetooth/hidp/sock.c b/net/bluetooth/hidp/sock.c index 18b3f6892a36..eca3889371c4 100644 --- a/net/bluetooth/hidp/sock.c +++ b/net/bluetooth/hidp/sock.c | |||
@@ -25,6 +25,10 @@ | |||
25 | 25 | ||
26 | #include "hidp.h" | 26 | #include "hidp.h" |
27 | 27 | ||
28 | static struct bt_sock_list hidp_sk_list = { | ||
29 | .lock = __RW_LOCK_UNLOCKED(hidp_sk_list.lock) | ||
30 | }; | ||
31 | |||
28 | static int hidp_sock_release(struct socket *sock) | 32 | static int hidp_sock_release(struct socket *sock) |
29 | { | 33 | { |
30 | struct sock *sk = sock->sk; | 34 | struct sock *sk = sock->sk; |
@@ -34,6 +38,8 @@ static int hidp_sock_release(struct socket *sock) | |||
34 | if (!sk) | 38 | if (!sk) |
35 | return 0; | 39 | return 0; |
36 | 40 | ||
41 | bt_sock_unlink(&hidp_sk_list, sk); | ||
42 | |||
37 | sock_orphan(sk); | 43 | sock_orphan(sk); |
38 | sock_put(sk); | 44 | sock_put(sk); |
39 | 45 | ||
@@ -253,6 +259,8 @@ static int hidp_sock_create(struct net *net, struct socket *sock, int protocol, | |||
253 | sk->sk_protocol = protocol; | 259 | sk->sk_protocol = protocol; |
254 | sk->sk_state = BT_OPEN; | 260 | sk->sk_state = BT_OPEN; |
255 | 261 | ||
262 | bt_sock_link(&hidp_sk_list, sk); | ||
263 | |||
256 | return 0; | 264 | return 0; |
257 | } | 265 | } |
258 | 266 | ||
@@ -271,8 +279,19 @@ int __init hidp_init_sockets(void) | |||
271 | return err; | 279 | return err; |
272 | 280 | ||
273 | err = bt_sock_register(BTPROTO_HIDP, &hidp_sock_family_ops); | 281 | err = bt_sock_register(BTPROTO_HIDP, &hidp_sock_family_ops); |
274 | if (err < 0) | 282 | if (err < 0) { |
283 | BT_ERR("Can't register HIDP socket"); | ||
275 | goto error; | 284 | goto error; |
285 | } | ||
286 | |||
287 | err = bt_procfs_init(THIS_MODULE, &init_net, "hidp", &hidp_sk_list, NULL); | ||
288 | if (err < 0) { | ||
289 | BT_ERR("Failed to create HIDP proc file"); | ||
290 | bt_sock_unregister(BTPROTO_HIDP); | ||
291 | goto error; | ||
292 | } | ||
293 | |||
294 | BT_INFO("HIDP socket layer initialized"); | ||
276 | 295 | ||
277 | return 0; | 296 | return 0; |
278 | 297 | ||
@@ -284,6 +303,7 @@ error: | |||
284 | 303 | ||
285 | void __exit hidp_cleanup_sockets(void) | 304 | void __exit hidp_cleanup_sockets(void) |
286 | { | 305 | { |
306 | bt_procfs_cleanup(&init_net, "hidp"); | ||
287 | if (bt_sock_unregister(BTPROTO_HIDP) < 0) | 307 | if (bt_sock_unregister(BTPROTO_HIDP) < 0) |
288 | BT_ERR("Can't unregister HIDP socket"); | 308 | BT_ERR("Can't unregister HIDP socket"); |
289 | 309 | ||
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index a8964db04bfb..f0a3ab156ec6 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -416,13 +416,30 @@ struct l2cap_chan *l2cap_chan_create(void) | |||
416 | return chan; | 416 | return chan; |
417 | } | 417 | } |
418 | 418 | ||
419 | void l2cap_chan_destroy(struct l2cap_chan *chan) | 419 | static void l2cap_chan_destroy(struct l2cap_chan *chan) |
420 | { | 420 | { |
421 | BT_DBG("chan %p", chan); | ||
422 | |||
421 | write_lock(&chan_list_lock); | 423 | write_lock(&chan_list_lock); |
422 | list_del(&chan->global_l); | 424 | list_del(&chan->global_l); |
423 | write_unlock(&chan_list_lock); | 425 | write_unlock(&chan_list_lock); |
424 | 426 | ||
425 | l2cap_chan_put(chan); | 427 | kfree(chan); |
428 | } | ||
429 | |||
430 | void l2cap_chan_hold(struct l2cap_chan *c) | ||
431 | { | ||
432 | BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt)); | ||
433 | |||
434 | atomic_inc(&c->refcnt); | ||
435 | } | ||
436 | |||
437 | void l2cap_chan_put(struct l2cap_chan *c) | ||
438 | { | ||
439 | BT_DBG("chan %p orig refcnt %d", c, atomic_read(&c->refcnt)); | ||
440 | |||
441 | if (atomic_dec_and_test(&c->refcnt)) | ||
442 | l2cap_chan_destroy(c); | ||
426 | } | 443 | } |
427 | 444 | ||
428 | void l2cap_chan_set_defaults(struct l2cap_chan *chan) | 445 | void l2cap_chan_set_defaults(struct l2cap_chan *chan) |
@@ -1181,6 +1198,7 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) | |||
1181 | sk = chan->sk; | 1198 | sk = chan->sk; |
1182 | 1199 | ||
1183 | hci_conn_hold(conn->hcon); | 1200 | hci_conn_hold(conn->hcon); |
1201 | conn->hcon->disc_timeout = HCI_DISCONN_TIMEOUT; | ||
1184 | 1202 | ||
1185 | bacpy(&bt_sk(sk)->src, conn->src); | 1203 | bacpy(&bt_sk(sk)->src, conn->src); |
1186 | bacpy(&bt_sk(sk)->dst, conn->dst); | 1204 | bacpy(&bt_sk(sk)->dst, conn->dst); |
@@ -5329,7 +5347,7 @@ int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) | |||
5329 | return exact ? lm1 : lm2; | 5347 | return exact ? lm1 : lm2; |
5330 | } | 5348 | } |
5331 | 5349 | ||
5332 | int l2cap_connect_cfm(struct hci_conn *hcon, u8 status) | 5350 | void l2cap_connect_cfm(struct hci_conn *hcon, u8 status) |
5333 | { | 5351 | { |
5334 | struct l2cap_conn *conn; | 5352 | struct l2cap_conn *conn; |
5335 | 5353 | ||
@@ -5342,7 +5360,6 @@ int l2cap_connect_cfm(struct hci_conn *hcon, u8 status) | |||
5342 | } else | 5360 | } else |
5343 | l2cap_conn_del(hcon, bt_to_errno(status)); | 5361 | l2cap_conn_del(hcon, bt_to_errno(status)); |
5344 | 5362 | ||
5345 | return 0; | ||
5346 | } | 5363 | } |
5347 | 5364 | ||
5348 | int l2cap_disconn_ind(struct hci_conn *hcon) | 5365 | int l2cap_disconn_ind(struct hci_conn *hcon) |
@@ -5356,12 +5373,11 @@ int l2cap_disconn_ind(struct hci_conn *hcon) | |||
5356 | return conn->disc_reason; | 5373 | return conn->disc_reason; |
5357 | } | 5374 | } |
5358 | 5375 | ||
5359 | int l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) | 5376 | void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) |
5360 | { | 5377 | { |
5361 | BT_DBG("hcon %p reason %d", hcon, reason); | 5378 | BT_DBG("hcon %p reason %d", hcon, reason); |
5362 | 5379 | ||
5363 | l2cap_conn_del(hcon, bt_to_errno(reason)); | 5380 | l2cap_conn_del(hcon, bt_to_errno(reason)); |
5364 | return 0; | ||
5365 | } | 5381 | } |
5366 | 5382 | ||
5367 | static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) | 5383 | static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) |
@@ -5404,6 +5420,11 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
5404 | BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid, | 5420 | BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid, |
5405 | state_to_string(chan->state)); | 5421 | state_to_string(chan->state)); |
5406 | 5422 | ||
5423 | if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { | ||
5424 | l2cap_chan_unlock(chan); | ||
5425 | continue; | ||
5426 | } | ||
5427 | |||
5407 | if (chan->scid == L2CAP_CID_LE_DATA) { | 5428 | if (chan->scid == L2CAP_CID_LE_DATA) { |
5408 | if (!status && encrypt) { | 5429 | if (!status && encrypt) { |
5409 | chan->sec_level = hcon->sec_level; | 5430 | chan->sec_level = hcon->sec_level; |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index a4bb27e8427e..3a6ce73541d9 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -34,6 +34,10 @@ | |||
34 | #include <net/bluetooth/l2cap.h> | 34 | #include <net/bluetooth/l2cap.h> |
35 | #include <net/bluetooth/smp.h> | 35 | #include <net/bluetooth/smp.h> |
36 | 36 | ||
37 | static struct bt_sock_list l2cap_sk_list = { | ||
38 | .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock) | ||
39 | }; | ||
40 | |||
37 | static const struct proto_ops l2cap_sock_ops; | 41 | static const struct proto_ops l2cap_sock_ops; |
38 | static void l2cap_sock_init(struct sock *sk, struct sock *parent); | 42 | static void l2cap_sock_init(struct sock *sk, struct sock *parent); |
39 | static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio); | 43 | static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int proto, gfp_t prio); |
@@ -245,6 +249,7 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, int *l | |||
245 | 249 | ||
246 | BT_DBG("sock %p, sk %p", sock, sk); | 250 | BT_DBG("sock %p, sk %p", sock, sk); |
247 | 251 | ||
252 | memset(la, 0, sizeof(struct sockaddr_l2)); | ||
248 | addr->sa_family = AF_BLUETOOTH; | 253 | addr->sa_family = AF_BLUETOOTH; |
249 | *len = sizeof(struct sockaddr_l2); | 254 | *len = sizeof(struct sockaddr_l2); |
250 | 255 | ||
@@ -823,7 +828,7 @@ static void l2cap_sock_kill(struct sock *sk) | |||
823 | 828 | ||
824 | /* Kill poor orphan */ | 829 | /* Kill poor orphan */ |
825 | 830 | ||
826 | l2cap_chan_destroy(l2cap_pi(sk)->chan); | 831 | l2cap_chan_put(l2cap_pi(sk)->chan); |
827 | sock_set_flag(sk, SOCK_DEAD); | 832 | sock_set_flag(sk, SOCK_DEAD); |
828 | sock_put(sk); | 833 | sock_put(sk); |
829 | } | 834 | } |
@@ -886,6 +891,8 @@ static int l2cap_sock_release(struct socket *sock) | |||
886 | if (!sk) | 891 | if (!sk) |
887 | return 0; | 892 | return 0; |
888 | 893 | ||
894 | bt_sock_unlink(&l2cap_sk_list, sk); | ||
895 | |||
889 | err = l2cap_sock_shutdown(sock, 2); | 896 | err = l2cap_sock_shutdown(sock, 2); |
890 | 897 | ||
891 | sock_orphan(sk); | 898 | sock_orphan(sk); |
@@ -1174,7 +1181,7 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock, int p | |||
1174 | 1181 | ||
1175 | chan = l2cap_chan_create(); | 1182 | chan = l2cap_chan_create(); |
1176 | if (!chan) { | 1183 | if (!chan) { |
1177 | l2cap_sock_kill(sk); | 1184 | sk_free(sk); |
1178 | return NULL; | 1185 | return NULL; |
1179 | } | 1186 | } |
1180 | 1187 | ||
@@ -1210,6 +1217,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol, | |||
1210 | return -ENOMEM; | 1217 | return -ENOMEM; |
1211 | 1218 | ||
1212 | l2cap_sock_init(sk, NULL); | 1219 | l2cap_sock_init(sk, NULL); |
1220 | bt_sock_link(&l2cap_sk_list, sk); | ||
1213 | return 0; | 1221 | return 0; |
1214 | } | 1222 | } |
1215 | 1223 | ||
@@ -1248,21 +1256,30 @@ int __init l2cap_init_sockets(void) | |||
1248 | return err; | 1256 | return err; |
1249 | 1257 | ||
1250 | err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops); | 1258 | err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops); |
1251 | if (err < 0) | 1259 | if (err < 0) { |
1260 | BT_ERR("L2CAP socket registration failed"); | ||
1252 | goto error; | 1261 | goto error; |
1262 | } | ||
1263 | |||
1264 | err = bt_procfs_init(THIS_MODULE, &init_net, "l2cap", &l2cap_sk_list, NULL); | ||
1265 | if (err < 0) { | ||
1266 | BT_ERR("Failed to create L2CAP proc file"); | ||
1267 | bt_sock_unregister(BTPROTO_L2CAP); | ||
1268 | goto error; | ||
1269 | } | ||
1253 | 1270 | ||
1254 | BT_INFO("L2CAP socket layer initialized"); | 1271 | BT_INFO("L2CAP socket layer initialized"); |
1255 | 1272 | ||
1256 | return 0; | 1273 | return 0; |
1257 | 1274 | ||
1258 | error: | 1275 | error: |
1259 | BT_ERR("L2CAP socket registration failed"); | ||
1260 | proto_unregister(&l2cap_proto); | 1276 | proto_unregister(&l2cap_proto); |
1261 | return err; | 1277 | return err; |
1262 | } | 1278 | } |
1263 | 1279 | ||
1264 | void l2cap_cleanup_sockets(void) | 1280 | void l2cap_cleanup_sockets(void) |
1265 | { | 1281 | { |
1282 | bt_procfs_cleanup(&init_net, "l2cap"); | ||
1266 | if (bt_sock_unregister(BTPROTO_L2CAP) < 0) | 1283 | if (bt_sock_unregister(BTPROTO_L2CAP) < 0) |
1267 | BT_ERR("L2CAP socket unregistration failed"); | 1284 | BT_ERR("L2CAP socket unregistration failed"); |
1268 | 1285 | ||
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index ad6613d17ca6..a3329cbd3e4d 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -193,6 +193,11 @@ static u8 mgmt_status_table[] = { | |||
193 | MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */ | 193 | MGMT_STATUS_CONNECT_FAILED, /* MAC Connection Failed */ |
194 | }; | 194 | }; |
195 | 195 | ||
196 | bool mgmt_valid_hdev(struct hci_dev *hdev) | ||
197 | { | ||
198 | return hdev->dev_type == HCI_BREDR; | ||
199 | } | ||
200 | |||
196 | static u8 mgmt_status(u8 hci_status) | 201 | static u8 mgmt_status(u8 hci_status) |
197 | { | 202 | { |
198 | if (hci_status < ARRAY_SIZE(mgmt_status_table)) | 203 | if (hci_status < ARRAY_SIZE(mgmt_status_table)) |
@@ -317,7 +322,6 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, | |||
317 | u16 data_len) | 322 | u16 data_len) |
318 | { | 323 | { |
319 | struct mgmt_rp_read_index_list *rp; | 324 | struct mgmt_rp_read_index_list *rp; |
320 | struct list_head *p; | ||
321 | struct hci_dev *d; | 325 | struct hci_dev *d; |
322 | size_t rp_len; | 326 | size_t rp_len; |
323 | u16 count; | 327 | u16 count; |
@@ -328,7 +332,10 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, | |||
328 | read_lock(&hci_dev_list_lock); | 332 | read_lock(&hci_dev_list_lock); |
329 | 333 | ||
330 | count = 0; | 334 | count = 0; |
331 | list_for_each(p, &hci_dev_list) { | 335 | list_for_each_entry(d, &hci_dev_list, list) { |
336 | if (!mgmt_valid_hdev(d)) | ||
337 | continue; | ||
338 | |||
332 | count++; | 339 | count++; |
333 | } | 340 | } |
334 | 341 | ||
@@ -346,6 +353,9 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, | |||
346 | if (test_bit(HCI_SETUP, &d->dev_flags)) | 353 | if (test_bit(HCI_SETUP, &d->dev_flags)) |
347 | continue; | 354 | continue; |
348 | 355 | ||
356 | if (!mgmt_valid_hdev(d)) | ||
357 | continue; | ||
358 | |||
349 | rp->index[i++] = cpu_to_le16(d->id); | 359 | rp->index[i++] = cpu_to_le16(d->id); |
350 | BT_DBG("Added hci%u", d->id); | 360 | BT_DBG("Added hci%u", d->id); |
351 | } | 361 | } |
@@ -370,10 +380,10 @@ static u32 get_supported_settings(struct hci_dev *hdev) | |||
370 | settings |= MGMT_SETTING_DISCOVERABLE; | 380 | settings |= MGMT_SETTING_DISCOVERABLE; |
371 | settings |= MGMT_SETTING_PAIRABLE; | 381 | settings |= MGMT_SETTING_PAIRABLE; |
372 | 382 | ||
373 | if (hdev->features[6] & LMP_SIMPLE_PAIR) | 383 | if (lmp_ssp_capable(hdev)) |
374 | settings |= MGMT_SETTING_SSP; | 384 | settings |= MGMT_SETTING_SSP; |
375 | 385 | ||
376 | if (!(hdev->features[4] & LMP_NO_BREDR)) { | 386 | if (lmp_bredr_capable(hdev)) { |
377 | settings |= MGMT_SETTING_BREDR; | 387 | settings |= MGMT_SETTING_BREDR; |
378 | settings |= MGMT_SETTING_LINK_SECURITY; | 388 | settings |= MGMT_SETTING_LINK_SECURITY; |
379 | } | 389 | } |
@@ -381,7 +391,7 @@ static u32 get_supported_settings(struct hci_dev *hdev) | |||
381 | if (enable_hs) | 391 | if (enable_hs) |
382 | settings |= MGMT_SETTING_HS; | 392 | settings |= MGMT_SETTING_HS; |
383 | 393 | ||
384 | if (hdev->features[4] & LMP_LE) | 394 | if (lmp_le_capable(hdev)) |
385 | settings |= MGMT_SETTING_LE; | 395 | settings |= MGMT_SETTING_LE; |
386 | 396 | ||
387 | return settings; | 397 | return settings; |
@@ -403,7 +413,7 @@ static u32 get_current_settings(struct hci_dev *hdev) | |||
403 | if (test_bit(HCI_PAIRABLE, &hdev->dev_flags)) | 413 | if (test_bit(HCI_PAIRABLE, &hdev->dev_flags)) |
404 | settings |= MGMT_SETTING_PAIRABLE; | 414 | settings |= MGMT_SETTING_PAIRABLE; |
405 | 415 | ||
406 | if (!(hdev->features[4] & LMP_NO_BREDR)) | 416 | if (lmp_bredr_capable(hdev)) |
407 | settings |= MGMT_SETTING_BREDR; | 417 | settings |= MGMT_SETTING_BREDR; |
408 | 418 | ||
409 | if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) | 419 | if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) |
@@ -1111,7 +1121,7 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
1111 | 1121 | ||
1112 | hci_dev_lock(hdev); | 1122 | hci_dev_lock(hdev); |
1113 | 1123 | ||
1114 | if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) { | 1124 | if (!lmp_ssp_capable(hdev)) { |
1115 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, | 1125 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_SSP, |
1116 | MGMT_STATUS_NOT_SUPPORTED); | 1126 | MGMT_STATUS_NOT_SUPPORTED); |
1117 | goto failed; | 1127 | goto failed; |
@@ -1195,7 +1205,7 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
1195 | 1205 | ||
1196 | hci_dev_lock(hdev); | 1206 | hci_dev_lock(hdev); |
1197 | 1207 | ||
1198 | if (!(hdev->features[4] & LMP_LE)) { | 1208 | if (!lmp_le_capable(hdev)) { |
1199 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE, | 1209 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_LE, |
1200 | MGMT_STATUS_NOT_SUPPORTED); | 1210 | MGMT_STATUS_NOT_SUPPORTED); |
1201 | goto unlock; | 1211 | goto unlock; |
@@ -2191,7 +2201,7 @@ static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev, | |||
2191 | goto unlock; | 2201 | goto unlock; |
2192 | } | 2202 | } |
2193 | 2203 | ||
2194 | if (!(hdev->features[6] & LMP_SIMPLE_PAIR)) { | 2204 | if (!lmp_ssp_capable(hdev)) { |
2195 | err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, | 2205 | err = cmd_status(sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, |
2196 | MGMT_STATUS_NOT_SUPPORTED); | 2206 | MGMT_STATUS_NOT_SUPPORTED); |
2197 | goto unlock; | 2207 | goto unlock; |
@@ -2820,6 +2830,9 @@ static void cmd_status_rsp(struct pending_cmd *cmd, void *data) | |||
2820 | 2830 | ||
2821 | int mgmt_index_added(struct hci_dev *hdev) | 2831 | int mgmt_index_added(struct hci_dev *hdev) |
2822 | { | 2832 | { |
2833 | if (!mgmt_valid_hdev(hdev)) | ||
2834 | return -ENOTSUPP; | ||
2835 | |||
2823 | return mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL); | 2836 | return mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL); |
2824 | } | 2837 | } |
2825 | 2838 | ||
@@ -2827,6 +2840,9 @@ int mgmt_index_removed(struct hci_dev *hdev) | |||
2827 | { | 2840 | { |
2828 | u8 status = MGMT_STATUS_INVALID_INDEX; | 2841 | u8 status = MGMT_STATUS_INVALID_INDEX; |
2829 | 2842 | ||
2843 | if (!mgmt_valid_hdev(hdev)) | ||
2844 | return -ENOTSUPP; | ||
2845 | |||
2830 | mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); | 2846 | mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); |
2831 | 2847 | ||
2832 | return mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL); | 2848 | return mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL); |
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 7e1e59645c05..b3226f3658cf 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c | |||
@@ -528,6 +528,7 @@ static int rfcomm_sock_getname(struct socket *sock, struct sockaddr *addr, int * | |||
528 | 528 | ||
529 | BT_DBG("sock %p, sk %p", sock, sk); | 529 | BT_DBG("sock %p, sk %p", sock, sk); |
530 | 530 | ||
531 | memset(sa, 0, sizeof(*sa)); | ||
531 | sa->rc_family = AF_BLUETOOTH; | 532 | sa->rc_family = AF_BLUETOOTH; |
532 | sa->rc_channel = rfcomm_pi(sk)->channel; | 533 | sa->rc_channel = rfcomm_pi(sk)->channel; |
533 | if (peer) | 534 | if (peer) |
@@ -822,6 +823,7 @@ static int rfcomm_sock_getsockopt(struct socket *sock, int level, int optname, c | |||
822 | } | 823 | } |
823 | 824 | ||
824 | sec.level = rfcomm_pi(sk)->sec_level; | 825 | sec.level = rfcomm_pi(sk)->sec_level; |
826 | sec.key_size = 0; | ||
825 | 827 | ||
826 | len = min_t(unsigned int, len, sizeof(sec)); | 828 | len = min_t(unsigned int, len, sizeof(sec)); |
827 | if (copy_to_user(optval, (char *) &sec, len)) | 829 | if (copy_to_user(optval, (char *) &sec, len)) |
@@ -1033,8 +1035,17 @@ int __init rfcomm_init_sockets(void) | |||
1033 | return err; | 1035 | return err; |
1034 | 1036 | ||
1035 | err = bt_sock_register(BTPROTO_RFCOMM, &rfcomm_sock_family_ops); | 1037 | err = bt_sock_register(BTPROTO_RFCOMM, &rfcomm_sock_family_ops); |
1036 | if (err < 0) | 1038 | if (err < 0) { |
1039 | BT_ERR("RFCOMM socket layer registration failed"); | ||
1040 | goto error; | ||
1041 | } | ||
1042 | |||
1043 | err = bt_procfs_init(THIS_MODULE, &init_net, "rfcomm", &rfcomm_sk_list, NULL); | ||
1044 | if (err < 0) { | ||
1045 | BT_ERR("Failed to create RFCOMM proc file"); | ||
1046 | bt_sock_unregister(BTPROTO_RFCOMM); | ||
1037 | goto error; | 1047 | goto error; |
1048 | } | ||
1038 | 1049 | ||
1039 | if (bt_debugfs) { | 1050 | if (bt_debugfs) { |
1040 | rfcomm_sock_debugfs = debugfs_create_file("rfcomm", 0444, | 1051 | rfcomm_sock_debugfs = debugfs_create_file("rfcomm", 0444, |
@@ -1048,13 +1059,14 @@ int __init rfcomm_init_sockets(void) | |||
1048 | return 0; | 1059 | return 0; |
1049 | 1060 | ||
1050 | error: | 1061 | error: |
1051 | BT_ERR("RFCOMM socket layer registration failed"); | ||
1052 | proto_unregister(&rfcomm_proto); | 1062 | proto_unregister(&rfcomm_proto); |
1053 | return err; | 1063 | return err; |
1054 | } | 1064 | } |
1055 | 1065 | ||
1056 | void __exit rfcomm_cleanup_sockets(void) | 1066 | void __exit rfcomm_cleanup_sockets(void) |
1057 | { | 1067 | { |
1068 | bt_procfs_cleanup(&init_net, "rfcomm"); | ||
1069 | |||
1058 | debugfs_remove(rfcomm_sock_debugfs); | 1070 | debugfs_remove(rfcomm_sock_debugfs); |
1059 | 1071 | ||
1060 | if (bt_sock_unregister(BTPROTO_RFCOMM) < 0) | 1072 | if (bt_sock_unregister(BTPROTO_RFCOMM) < 0) |
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index cb960773c002..56f182393c4c 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c | |||
@@ -456,7 +456,7 @@ static int rfcomm_get_dev_list(void __user *arg) | |||
456 | 456 | ||
457 | size = sizeof(*dl) + dev_num * sizeof(*di); | 457 | size = sizeof(*dl) + dev_num * sizeof(*di); |
458 | 458 | ||
459 | dl = kmalloc(size, GFP_KERNEL); | 459 | dl = kzalloc(size, GFP_KERNEL); |
460 | if (!dl) | 460 | if (!dl) |
461 | return -ENOMEM; | 461 | return -ENOMEM; |
462 | 462 | ||
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 40bbe25dcff7..dc42b917aaaf 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
@@ -131,6 +131,15 @@ static int sco_conn_del(struct hci_conn *hcon, int err) | |||
131 | sco_sock_clear_timer(sk); | 131 | sco_sock_clear_timer(sk); |
132 | sco_chan_del(sk, err); | 132 | sco_chan_del(sk, err); |
133 | bh_unlock_sock(sk); | 133 | bh_unlock_sock(sk); |
134 | |||
135 | sco_conn_lock(conn); | ||
136 | conn->sk = NULL; | ||
137 | sco_pi(sk)->conn = NULL; | ||
138 | sco_conn_unlock(conn); | ||
139 | |||
140 | if (conn->hcon) | ||
141 | hci_conn_put(conn->hcon); | ||
142 | |||
134 | sco_sock_kill(sk); | 143 | sco_sock_kill(sk); |
135 | } | 144 | } |
136 | 145 | ||
@@ -821,16 +830,6 @@ static void sco_chan_del(struct sock *sk, int err) | |||
821 | 830 | ||
822 | BT_DBG("sk %p, conn %p, err %d", sk, conn, err); | 831 | BT_DBG("sk %p, conn %p, err %d", sk, conn, err); |
823 | 832 | ||
824 | if (conn) { | ||
825 | sco_conn_lock(conn); | ||
826 | conn->sk = NULL; | ||
827 | sco_pi(sk)->conn = NULL; | ||
828 | sco_conn_unlock(conn); | ||
829 | |||
830 | if (conn->hcon) | ||
831 | hci_conn_put(conn->hcon); | ||
832 | } | ||
833 | |||
834 | sk->sk_state = BT_CLOSED; | 833 | sk->sk_state = BT_CLOSED; |
835 | sk->sk_err = err; | 834 | sk->sk_err = err; |
836 | sk->sk_state_change(sk); | 835 | sk->sk_state_change(sk); |
@@ -913,7 +912,7 @@ int sco_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) | |||
913 | return lm; | 912 | return lm; |
914 | } | 913 | } |
915 | 914 | ||
916 | int sco_connect_cfm(struct hci_conn *hcon, __u8 status) | 915 | void sco_connect_cfm(struct hci_conn *hcon, __u8 status) |
917 | { | 916 | { |
918 | BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); | 917 | BT_DBG("hcon %p bdaddr %s status %d", hcon, batostr(&hcon->dst), status); |
919 | if (!status) { | 918 | if (!status) { |
@@ -924,16 +923,13 @@ int sco_connect_cfm(struct hci_conn *hcon, __u8 status) | |||
924 | sco_conn_ready(conn); | 923 | sco_conn_ready(conn); |
925 | } else | 924 | } else |
926 | sco_conn_del(hcon, bt_to_errno(status)); | 925 | sco_conn_del(hcon, bt_to_errno(status)); |
927 | |||
928 | return 0; | ||
929 | } | 926 | } |
930 | 927 | ||
931 | int sco_disconn_cfm(struct hci_conn *hcon, __u8 reason) | 928 | void sco_disconn_cfm(struct hci_conn *hcon, __u8 reason) |
932 | { | 929 | { |
933 | BT_DBG("hcon %p reason %d", hcon, reason); | 930 | BT_DBG("hcon %p reason %d", hcon, reason); |
934 | 931 | ||
935 | sco_conn_del(hcon, bt_to_errno(reason)); | 932 | sco_conn_del(hcon, bt_to_errno(reason)); |
936 | return 0; | ||
937 | } | 933 | } |
938 | 934 | ||
939 | int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb) | 935 | int sco_recv_scodata(struct hci_conn *hcon, struct sk_buff *skb) |
@@ -1026,6 +1022,13 @@ int __init sco_init(void) | |||
1026 | goto error; | 1022 | goto error; |
1027 | } | 1023 | } |
1028 | 1024 | ||
1025 | err = bt_procfs_init(THIS_MODULE, &init_net, "sco", &sco_sk_list, NULL); | ||
1026 | if (err < 0) { | ||
1027 | BT_ERR("Failed to create SCO proc file"); | ||
1028 | bt_sock_unregister(BTPROTO_SCO); | ||
1029 | goto error; | ||
1030 | } | ||
1031 | |||
1029 | if (bt_debugfs) { | 1032 | if (bt_debugfs) { |
1030 | sco_debugfs = debugfs_create_file("sco", 0444, bt_debugfs, | 1033 | sco_debugfs = debugfs_create_file("sco", 0444, bt_debugfs, |
1031 | NULL, &sco_debugfs_fops); | 1034 | NULL, &sco_debugfs_fops); |
@@ -1044,6 +1047,8 @@ error: | |||
1044 | 1047 | ||
1045 | void __exit sco_exit(void) | 1048 | void __exit sco_exit(void) |
1046 | { | 1049 | { |
1050 | bt_procfs_cleanup(&init_net, "sco"); | ||
1051 | |||
1047 | debugfs_remove(sco_debugfs); | 1052 | debugfs_remove(sco_debugfs); |
1048 | 1053 | ||
1049 | if (bt_sock_unregister(BTPROTO_SCO) < 0) | 1054 | if (bt_sock_unregister(BTPROTO_SCO) < 0) |
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 16ef0dc85a0a..901a616c8083 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
@@ -579,8 +579,11 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
579 | 579 | ||
580 | if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) | 580 | if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) |
581 | smp = smp_chan_create(conn); | 581 | smp = smp_chan_create(conn); |
582 | else | ||
583 | smp = conn->smp_chan; | ||
582 | 584 | ||
583 | smp = conn->smp_chan; | 585 | if (!smp) |
586 | return SMP_UNSPECIFIED; | ||
584 | 587 | ||
585 | smp->preq[0] = SMP_CMD_PAIRING_REQ; | 588 | smp->preq[0] = SMP_CMD_PAIRING_REQ; |
586 | memcpy(&smp->preq[1], req, sizeof(*req)); | 589 | memcpy(&smp->preq[1], req, sizeof(*req)); |
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 333484537600..070e8a68cfc6 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c | |||
@@ -31,9 +31,11 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) | |||
31 | struct net_bridge_mdb_entry *mdst; | 31 | struct net_bridge_mdb_entry *mdst; |
32 | struct br_cpu_netstats *brstats = this_cpu_ptr(br->stats); | 32 | struct br_cpu_netstats *brstats = this_cpu_ptr(br->stats); |
33 | 33 | ||
34 | rcu_read_lock(); | ||
34 | #ifdef CONFIG_BRIDGE_NETFILTER | 35 | #ifdef CONFIG_BRIDGE_NETFILTER |
35 | if (skb->nf_bridge && (skb->nf_bridge->mask & BRNF_BRIDGED_DNAT)) { | 36 | if (skb->nf_bridge && (skb->nf_bridge->mask & BRNF_BRIDGED_DNAT)) { |
36 | br_nf_pre_routing_finish_bridge_slow(skb); | 37 | br_nf_pre_routing_finish_bridge_slow(skb); |
38 | rcu_read_unlock(); | ||
37 | return NETDEV_TX_OK; | 39 | return NETDEV_TX_OK; |
38 | } | 40 | } |
39 | #endif | 41 | #endif |
@@ -48,7 +50,6 @@ netdev_tx_t br_dev_xmit(struct sk_buff *skb, struct net_device *dev) | |||
48 | skb_reset_mac_header(skb); | 50 | skb_reset_mac_header(skb); |
49 | skb_pull(skb, ETH_HLEN); | 51 | skb_pull(skb, ETH_HLEN); |
50 | 52 | ||
51 | rcu_read_lock(); | ||
52 | if (is_broadcast_ether_addr(dest)) | 53 | if (is_broadcast_ether_addr(dest)) |
53 | br_flood_deliver(br, skb); | 54 | br_flood_deliver(br, skb); |
54 | else if (is_multicast_ether_addr(dest)) { | 55 | else if (is_multicast_ether_addr(dest)) { |
@@ -206,24 +207,23 @@ static void br_poll_controller(struct net_device *br_dev) | |||
206 | static void br_netpoll_cleanup(struct net_device *dev) | 207 | static void br_netpoll_cleanup(struct net_device *dev) |
207 | { | 208 | { |
208 | struct net_bridge *br = netdev_priv(dev); | 209 | struct net_bridge *br = netdev_priv(dev); |
209 | struct net_bridge_port *p, *n; | 210 | struct net_bridge_port *p; |
210 | 211 | ||
211 | list_for_each_entry_safe(p, n, &br->port_list, list) { | 212 | list_for_each_entry(p, &br->port_list, list) |
212 | br_netpoll_disable(p); | 213 | br_netpoll_disable(p); |
213 | } | ||
214 | } | 214 | } |
215 | 215 | ||
216 | static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni) | 216 | static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, |
217 | gfp_t gfp) | ||
217 | { | 218 | { |
218 | struct net_bridge *br = netdev_priv(dev); | 219 | struct net_bridge *br = netdev_priv(dev); |
219 | struct net_bridge_port *p, *n; | 220 | struct net_bridge_port *p; |
220 | int err = 0; | 221 | int err = 0; |
221 | 222 | ||
222 | list_for_each_entry_safe(p, n, &br->port_list, list) { | 223 | list_for_each_entry(p, &br->port_list, list) { |
223 | if (!p->dev) | 224 | if (!p->dev) |
224 | continue; | 225 | continue; |
225 | 226 | err = br_netpoll_enable(p, gfp); | |
226 | err = br_netpoll_enable(p); | ||
227 | if (err) | 227 | if (err) |
228 | goto fail; | 228 | goto fail; |
229 | } | 229 | } |
@@ -236,17 +236,17 @@ fail: | |||
236 | goto out; | 236 | goto out; |
237 | } | 237 | } |
238 | 238 | ||
239 | int br_netpoll_enable(struct net_bridge_port *p) | 239 | int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp) |
240 | { | 240 | { |
241 | struct netpoll *np; | 241 | struct netpoll *np; |
242 | int err = 0; | 242 | int err = 0; |
243 | 243 | ||
244 | np = kzalloc(sizeof(*p->np), GFP_KERNEL); | 244 | np = kzalloc(sizeof(*p->np), gfp); |
245 | err = -ENOMEM; | 245 | err = -ENOMEM; |
246 | if (!np) | 246 | if (!np) |
247 | goto out; | 247 | goto out; |
248 | 248 | ||
249 | err = __netpoll_setup(np, p->dev); | 249 | err = __netpoll_setup(np, p->dev, gfp); |
250 | if (err) { | 250 | if (err) { |
251 | kfree(np); | 251 | kfree(np); |
252 | goto out; | 252 | goto out; |
@@ -267,11 +267,7 @@ void br_netpoll_disable(struct net_bridge_port *p) | |||
267 | 267 | ||
268 | p->np = NULL; | 268 | p->np = NULL; |
269 | 269 | ||
270 | /* Wait for transmitting packets to finish before freeing. */ | 270 | __netpoll_free_rcu(np); |
271 | synchronize_rcu_bh(); | ||
272 | |||
273 | __netpoll_cleanup(np); | ||
274 | kfree(np); | ||
275 | } | 271 | } |
276 | 272 | ||
277 | #endif | 273 | #endif |
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index d21f32383517..9ce430b4657c 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c | |||
@@ -312,7 +312,7 @@ int br_fdb_fillbuf(struct net_bridge *br, void *buf, | |||
312 | 312 | ||
313 | fe->is_local = f->is_local; | 313 | fe->is_local = f->is_local; |
314 | if (!f->is_static) | 314 | if (!f->is_static) |
315 | fe->ageing_timer_value = jiffies_to_clock_t(jiffies - f->updated); | 315 | fe->ageing_timer_value = jiffies_delta_to_clock_t(jiffies - f->updated); |
316 | ++fe; | 316 | ++fe; |
317 | ++num; | 317 | ++num; |
318 | } | 318 | } |
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index e9466d412707..02015a505d2a 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c | |||
@@ -65,7 +65,7 @@ static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb) | |||
65 | { | 65 | { |
66 | skb->dev = to->dev; | 66 | skb->dev = to->dev; |
67 | 67 | ||
68 | if (unlikely(netpoll_tx_running(to->dev))) { | 68 | if (unlikely(netpoll_tx_running(to->br->dev))) { |
69 | if (packet_length(skb) > skb->dev->mtu && !skb_is_gso(skb)) | 69 | if (packet_length(skb) > skb->dev->mtu && !skb_is_gso(skb)) |
70 | kfree_skb(skb); | 70 | kfree_skb(skb); |
71 | else { | 71 | else { |
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index e1144e1617be..1c8fdc3558cd 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
@@ -361,7 +361,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
361 | if (err) | 361 | if (err) |
362 | goto err2; | 362 | goto err2; |
363 | 363 | ||
364 | if (br_netpoll_info(br) && ((err = br_netpoll_enable(p)))) | 364 | if (br_netpoll_info(br) && ((err = br_netpoll_enable(p, GFP_KERNEL)))) |
365 | goto err3; | 365 | goto err3; |
366 | 366 | ||
367 | err = netdev_set_master(dev, br->dev); | 367 | err = netdev_set_master(dev, br->dev); |
@@ -427,6 +427,10 @@ int br_del_if(struct net_bridge *br, struct net_device *dev) | |||
427 | if (!p || p->br != br) | 427 | if (!p || p->br != br) |
428 | return -EINVAL; | 428 | return -EINVAL; |
429 | 429 | ||
430 | /* Since more than one interface can be attached to a bridge, | ||
431 | * there still maybe an alternate path for netconsole to use; | ||
432 | * therefore there is no reason for a NETDEV_RELEASE event. | ||
433 | */ | ||
430 | del_nbp(p); | 434 | del_nbp(p); |
431 | 435 | ||
432 | spin_lock_bh(&br->lock); | 436 | spin_lock_bh(&br->lock); |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index a768b2408edf..f507d2af9646 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
@@ -316,7 +316,7 @@ static inline void br_netpoll_send_skb(const struct net_bridge_port *p, | |||
316 | netpoll_send_skb(np, skb); | 316 | netpoll_send_skb(np, skb); |
317 | } | 317 | } |
318 | 318 | ||
319 | extern int br_netpoll_enable(struct net_bridge_port *p); | 319 | extern int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp); |
320 | extern void br_netpoll_disable(struct net_bridge_port *p); | 320 | extern void br_netpoll_disable(struct net_bridge_port *p); |
321 | #else | 321 | #else |
322 | static inline struct netpoll_info *br_netpoll_info(struct net_bridge *br) | 322 | static inline struct netpoll_info *br_netpoll_info(struct net_bridge *br) |
@@ -329,7 +329,7 @@ static inline void br_netpoll_send_skb(const struct net_bridge_port *p, | |||
329 | { | 329 | { |
330 | } | 330 | } |
331 | 331 | ||
332 | static inline int br_netpoll_enable(struct net_bridge_port *p) | 332 | static inline int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp) |
333 | { | 333 | { |
334 | return 0; | 334 | return 0; |
335 | } | 335 | } |
diff --git a/net/bridge/br_stp_timer.c b/net/bridge/br_stp_timer.c index a6747e673426..c3530a81a33b 100644 --- a/net/bridge/br_stp_timer.c +++ b/net/bridge/br_stp_timer.c | |||
@@ -170,5 +170,5 @@ void br_stp_port_timer_init(struct net_bridge_port *p) | |||
170 | unsigned long br_timer_value(const struct timer_list *timer) | 170 | unsigned long br_timer_value(const struct timer_list *timer) |
171 | { | 171 | { |
172 | return timer_pending(timer) | 172 | return timer_pending(timer) |
173 | ? jiffies_to_clock_t(timer->expires - jiffies) : 0; | 173 | ? jiffies_delta_to_clock_t(timer->expires - jiffies) : 0; |
174 | } | 174 | } |
diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c index 42e6bd094574..3c2e9dced9e0 100644 --- a/net/bridge/netfilter/ebtable_filter.c +++ b/net/bridge/netfilter/ebtable_filter.c | |||
@@ -100,9 +100,7 @@ static struct nf_hook_ops ebt_ops_filter[] __read_mostly = { | |||
100 | static int __net_init frame_filter_net_init(struct net *net) | 100 | static int __net_init frame_filter_net_init(struct net *net) |
101 | { | 101 | { |
102 | net->xt.frame_filter = ebt_register_table(net, &frame_filter); | 102 | net->xt.frame_filter = ebt_register_table(net, &frame_filter); |
103 | if (IS_ERR(net->xt.frame_filter)) | 103 | return PTR_RET(net->xt.frame_filter); |
104 | return PTR_ERR(net->xt.frame_filter); | ||
105 | return 0; | ||
106 | } | 104 | } |
107 | 105 | ||
108 | static void __net_exit frame_filter_net_exit(struct net *net) | 106 | static void __net_exit frame_filter_net_exit(struct net *net) |
diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c index 6dc2f878ae05..10871bc77908 100644 --- a/net/bridge/netfilter/ebtable_nat.c +++ b/net/bridge/netfilter/ebtable_nat.c | |||
@@ -100,9 +100,7 @@ static struct nf_hook_ops ebt_ops_nat[] __read_mostly = { | |||
100 | static int __net_init frame_nat_net_init(struct net *net) | 100 | static int __net_init frame_nat_net_init(struct net *net) |
101 | { | 101 | { |
102 | net->xt.frame_nat = ebt_register_table(net, &frame_nat); | 102 | net->xt.frame_nat = ebt_register_table(net, &frame_nat); |
103 | if (IS_ERR(net->xt.frame_nat)) | 103 | return PTR_RET(net->xt.frame_nat); |
104 | return PTR_ERR(net->xt.frame_nat); | ||
105 | return 0; | ||
106 | } | 104 | } |
107 | 105 | ||
108 | static void __net_exit frame_nat_net_exit(struct net *net) | 106 | static void __net_exit frame_nat_net_exit(struct net *net) |
diff --git a/net/caif/chnl_net.c b/net/caif/chnl_net.c index 69771c04ba8f..e597733affb8 100644 --- a/net/caif/chnl_net.c +++ b/net/caif/chnl_net.c | |||
@@ -94,6 +94,10 @@ static int chnl_recv_cb(struct cflayer *layr, struct cfpkt *pkt) | |||
94 | 94 | ||
95 | /* check the version of IP */ | 95 | /* check the version of IP */ |
96 | ip_version = skb_header_pointer(skb, 0, 1, &buf); | 96 | ip_version = skb_header_pointer(skb, 0, 1, &buf); |
97 | if (!ip_version) { | ||
98 | kfree_skb(skb); | ||
99 | return -EINVAL; | ||
100 | } | ||
97 | 101 | ||
98 | switch (*ip_version >> 4) { | 102 | switch (*ip_version >> 4) { |
99 | case 4: | 103 | case 4: |
diff --git a/net/ceph/ceph_common.c b/net/ceph/ceph_common.c index 69e38db28e5f..a8020293f342 100644 --- a/net/ceph/ceph_common.c +++ b/net/ceph/ceph_common.c | |||
@@ -84,7 +84,6 @@ int ceph_check_fsid(struct ceph_client *client, struct ceph_fsid *fsid) | |||
84 | return -1; | 84 | return -1; |
85 | } | 85 | } |
86 | } else { | 86 | } else { |
87 | pr_info("client%lld fsid %pU\n", ceph_client_id(client), fsid); | ||
88 | memcpy(&client->fsid, fsid, sizeof(*fsid)); | 87 | memcpy(&client->fsid, fsid, sizeof(*fsid)); |
89 | } | 88 | } |
90 | return 0; | 89 | return 0; |
diff --git a/net/ceph/debugfs.c b/net/ceph/debugfs.c index 54b531a01121..38b5dc1823d4 100644 --- a/net/ceph/debugfs.c +++ b/net/ceph/debugfs.c | |||
@@ -189,6 +189,9 @@ int ceph_debugfs_client_init(struct ceph_client *client) | |||
189 | snprintf(name, sizeof(name), "%pU.client%lld", &client->fsid, | 189 | snprintf(name, sizeof(name), "%pU.client%lld", &client->fsid, |
190 | client->monc.auth->global_id); | 190 | client->monc.auth->global_id); |
191 | 191 | ||
192 | dout("ceph_debugfs_client_init %p %s\n", client, name); | ||
193 | |||
194 | BUG_ON(client->debugfs_dir); | ||
192 | client->debugfs_dir = debugfs_create_dir(name, ceph_debugfs_dir); | 195 | client->debugfs_dir = debugfs_create_dir(name, ceph_debugfs_dir); |
193 | if (!client->debugfs_dir) | 196 | if (!client->debugfs_dir) |
194 | goto out; | 197 | goto out; |
@@ -234,6 +237,7 @@ out: | |||
234 | 237 | ||
235 | void ceph_debugfs_client_cleanup(struct ceph_client *client) | 238 | void ceph_debugfs_client_cleanup(struct ceph_client *client) |
236 | { | 239 | { |
240 | dout("ceph_debugfs_client_cleanup %p\n", client); | ||
237 | debugfs_remove(client->debugfs_osdmap); | 241 | debugfs_remove(client->debugfs_osdmap); |
238 | debugfs_remove(client->debugfs_monmap); | 242 | debugfs_remove(client->debugfs_monmap); |
239 | debugfs_remove(client->osdc.debugfs_file); | 243 | debugfs_remove(client->osdc.debugfs_file); |
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index b9796750034a..24c5eea8c45b 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c | |||
@@ -915,7 +915,6 @@ static int prepare_write_connect(struct ceph_connection *con) | |||
915 | con->out_connect.authorizer_len = auth ? | 915 | con->out_connect.authorizer_len = auth ? |
916 | cpu_to_le32(auth->authorizer_buf_len) : 0; | 916 | cpu_to_le32(auth->authorizer_buf_len) : 0; |
917 | 917 | ||
918 | con_out_kvec_reset(con); | ||
919 | con_out_kvec_add(con, sizeof (con->out_connect), | 918 | con_out_kvec_add(con, sizeof (con->out_connect), |
920 | &con->out_connect); | 919 | &con->out_connect); |
921 | if (auth && auth->authorizer_buf_len) | 920 | if (auth && auth->authorizer_buf_len) |
@@ -1557,6 +1556,7 @@ static int process_connect(struct ceph_connection *con) | |||
1557 | return -1; | 1556 | return -1; |
1558 | } | 1557 | } |
1559 | con->auth_retry = 1; | 1558 | con->auth_retry = 1; |
1559 | con_out_kvec_reset(con); | ||
1560 | ret = prepare_write_connect(con); | 1560 | ret = prepare_write_connect(con); |
1561 | if (ret < 0) | 1561 | if (ret < 0) |
1562 | return ret; | 1562 | return ret; |
@@ -1577,6 +1577,7 @@ static int process_connect(struct ceph_connection *con) | |||
1577 | ENTITY_NAME(con->peer_name), | 1577 | ENTITY_NAME(con->peer_name), |
1578 | ceph_pr_addr(&con->peer_addr.in_addr)); | 1578 | ceph_pr_addr(&con->peer_addr.in_addr)); |
1579 | reset_connection(con); | 1579 | reset_connection(con); |
1580 | con_out_kvec_reset(con); | ||
1580 | ret = prepare_write_connect(con); | 1581 | ret = prepare_write_connect(con); |
1581 | if (ret < 0) | 1582 | if (ret < 0) |
1582 | return ret; | 1583 | return ret; |
@@ -1601,6 +1602,7 @@ static int process_connect(struct ceph_connection *con) | |||
1601 | le32_to_cpu(con->out_connect.connect_seq), | 1602 | le32_to_cpu(con->out_connect.connect_seq), |
1602 | le32_to_cpu(con->in_reply.connect_seq)); | 1603 | le32_to_cpu(con->in_reply.connect_seq)); |
1603 | con->connect_seq = le32_to_cpu(con->in_reply.connect_seq); | 1604 | con->connect_seq = le32_to_cpu(con->in_reply.connect_seq); |
1605 | con_out_kvec_reset(con); | ||
1604 | ret = prepare_write_connect(con); | 1606 | ret = prepare_write_connect(con); |
1605 | if (ret < 0) | 1607 | if (ret < 0) |
1606 | return ret; | 1608 | return ret; |
@@ -1617,6 +1619,7 @@ static int process_connect(struct ceph_connection *con) | |||
1617 | le32_to_cpu(con->in_reply.global_seq)); | 1619 | le32_to_cpu(con->in_reply.global_seq)); |
1618 | get_global_seq(con->msgr, | 1620 | get_global_seq(con->msgr, |
1619 | le32_to_cpu(con->in_reply.global_seq)); | 1621 | le32_to_cpu(con->in_reply.global_seq)); |
1622 | con_out_kvec_reset(con); | ||
1620 | ret = prepare_write_connect(con); | 1623 | ret = prepare_write_connect(con); |
1621 | if (ret < 0) | 1624 | if (ret < 0) |
1622 | return ret; | 1625 | return ret; |
@@ -2135,7 +2138,11 @@ more: | |||
2135 | BUG_ON(con->state != CON_STATE_CONNECTING); | 2138 | BUG_ON(con->state != CON_STATE_CONNECTING); |
2136 | con->state = CON_STATE_NEGOTIATING; | 2139 | con->state = CON_STATE_NEGOTIATING; |
2137 | 2140 | ||
2138 | /* Banner is good, exchange connection info */ | 2141 | /* |
2142 | * Received banner is good, exchange connection info. | ||
2143 | * Do not reset out_kvec, as sending our banner raced | ||
2144 | * with receiving peer banner after connect completed. | ||
2145 | */ | ||
2139 | ret = prepare_write_connect(con); | 2146 | ret = prepare_write_connect(con); |
2140 | if (ret < 0) | 2147 | if (ret < 0) |
2141 | goto out; | 2148 | goto out; |
diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 105d533b55f3..900ea0f043fc 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c | |||
@@ -311,6 +311,17 @@ int ceph_monc_open_session(struct ceph_mon_client *monc) | |||
311 | EXPORT_SYMBOL(ceph_monc_open_session); | 311 | EXPORT_SYMBOL(ceph_monc_open_session); |
312 | 312 | ||
313 | /* | 313 | /* |
314 | * We require the fsid and global_id in order to initialize our | ||
315 | * debugfs dir. | ||
316 | */ | ||
317 | static bool have_debugfs_info(struct ceph_mon_client *monc) | ||
318 | { | ||
319 | dout("have_debugfs_info fsid %d globalid %lld\n", | ||
320 | (int)monc->client->have_fsid, monc->auth->global_id); | ||
321 | return monc->client->have_fsid && monc->auth->global_id > 0; | ||
322 | } | ||
323 | |||
324 | /* | ||
314 | * The monitor responds with mount ack indicate mount success. The | 325 | * The monitor responds with mount ack indicate mount success. The |
315 | * included client ticket allows the client to talk to MDSs and OSDs. | 326 | * included client ticket allows the client to talk to MDSs and OSDs. |
316 | */ | 327 | */ |
@@ -320,9 +331,12 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc, | |||
320 | struct ceph_client *client = monc->client; | 331 | struct ceph_client *client = monc->client; |
321 | struct ceph_monmap *monmap = NULL, *old = monc->monmap; | 332 | struct ceph_monmap *monmap = NULL, *old = monc->monmap; |
322 | void *p, *end; | 333 | void *p, *end; |
334 | int had_debugfs_info, init_debugfs = 0; | ||
323 | 335 | ||
324 | mutex_lock(&monc->mutex); | 336 | mutex_lock(&monc->mutex); |
325 | 337 | ||
338 | had_debugfs_info = have_debugfs_info(monc); | ||
339 | |||
326 | dout("handle_monmap\n"); | 340 | dout("handle_monmap\n"); |
327 | p = msg->front.iov_base; | 341 | p = msg->front.iov_base; |
328 | end = p + msg->front.iov_len; | 342 | end = p + msg->front.iov_len; |
@@ -344,12 +358,22 @@ static void ceph_monc_handle_map(struct ceph_mon_client *monc, | |||
344 | 358 | ||
345 | if (!client->have_fsid) { | 359 | if (!client->have_fsid) { |
346 | client->have_fsid = true; | 360 | client->have_fsid = true; |
361 | if (!had_debugfs_info && have_debugfs_info(monc)) { | ||
362 | pr_info("client%lld fsid %pU\n", | ||
363 | ceph_client_id(monc->client), | ||
364 | &monc->client->fsid); | ||
365 | init_debugfs = 1; | ||
366 | } | ||
347 | mutex_unlock(&monc->mutex); | 367 | mutex_unlock(&monc->mutex); |
348 | /* | 368 | |
349 | * do debugfs initialization without mutex to avoid | 369 | if (init_debugfs) { |
350 | * creating a locking dependency | 370 | /* |
351 | */ | 371 | * do debugfs initialization without mutex to avoid |
352 | ceph_debugfs_client_init(client); | 372 | * creating a locking dependency |
373 | */ | ||
374 | ceph_debugfs_client_init(monc->client); | ||
375 | } | ||
376 | |||
353 | goto out_unlocked; | 377 | goto out_unlocked; |
354 | } | 378 | } |
355 | out: | 379 | out: |
@@ -865,8 +889,10 @@ static void handle_auth_reply(struct ceph_mon_client *monc, | |||
865 | { | 889 | { |
866 | int ret; | 890 | int ret; |
867 | int was_auth = 0; | 891 | int was_auth = 0; |
892 | int had_debugfs_info, init_debugfs = 0; | ||
868 | 893 | ||
869 | mutex_lock(&monc->mutex); | 894 | mutex_lock(&monc->mutex); |
895 | had_debugfs_info = have_debugfs_info(monc); | ||
870 | if (monc->auth->ops) | 896 | if (monc->auth->ops) |
871 | was_auth = monc->auth->ops->is_authenticated(monc->auth); | 897 | was_auth = monc->auth->ops->is_authenticated(monc->auth); |
872 | monc->pending_auth = 0; | 898 | monc->pending_auth = 0; |
@@ -889,7 +915,22 @@ static void handle_auth_reply(struct ceph_mon_client *monc, | |||
889 | __send_subscribe(monc); | 915 | __send_subscribe(monc); |
890 | __resend_generic_request(monc); | 916 | __resend_generic_request(monc); |
891 | } | 917 | } |
918 | |||
919 | if (!had_debugfs_info && have_debugfs_info(monc)) { | ||
920 | pr_info("client%lld fsid %pU\n", | ||
921 | ceph_client_id(monc->client), | ||
922 | &monc->client->fsid); | ||
923 | init_debugfs = 1; | ||
924 | } | ||
892 | mutex_unlock(&monc->mutex); | 925 | mutex_unlock(&monc->mutex); |
926 | |||
927 | if (init_debugfs) { | ||
928 | /* | ||
929 | * do debugfs initialization without mutex to avoid | ||
930 | * creating a locking dependency | ||
931 | */ | ||
932 | ceph_debugfs_client_init(monc->client); | ||
933 | } | ||
893 | } | 934 | } |
894 | 935 | ||
895 | static int __validate_auth(struct ceph_mon_client *monc) | 936 | static int __validate_auth(struct ceph_mon_client *monc) |
diff --git a/net/core/dev.c b/net/core/dev.c index 0cb3fe8d8e72..b1e6d6385516 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -1055,6 +1055,8 @@ rollback: | |||
1055 | */ | 1055 | */ |
1056 | int dev_set_alias(struct net_device *dev, const char *alias, size_t len) | 1056 | int dev_set_alias(struct net_device *dev, const char *alias, size_t len) |
1057 | { | 1057 | { |
1058 | char *new_ifalias; | ||
1059 | |||
1058 | ASSERT_RTNL(); | 1060 | ASSERT_RTNL(); |
1059 | 1061 | ||
1060 | if (len >= IFALIASZ) | 1062 | if (len >= IFALIASZ) |
@@ -1068,9 +1070,10 @@ int dev_set_alias(struct net_device *dev, const char *alias, size_t len) | |||
1068 | return 0; | 1070 | return 0; |
1069 | } | 1071 | } |
1070 | 1072 | ||
1071 | dev->ifalias = krealloc(dev->ifalias, len + 1, GFP_KERNEL); | 1073 | new_ifalias = krealloc(dev->ifalias, len + 1, GFP_KERNEL); |
1072 | if (!dev->ifalias) | 1074 | if (!new_ifalias) |
1073 | return -ENOMEM; | 1075 | return -ENOMEM; |
1076 | dev->ifalias = new_ifalias; | ||
1074 | 1077 | ||
1075 | strlcpy(dev->ifalias, alias, len+1); | 1078 | strlcpy(dev->ifalias, alias, len+1); |
1076 | return len; | 1079 | return len; |
@@ -1106,11 +1109,23 @@ void netdev_state_change(struct net_device *dev) | |||
1106 | } | 1109 | } |
1107 | EXPORT_SYMBOL(netdev_state_change); | 1110 | EXPORT_SYMBOL(netdev_state_change); |
1108 | 1111 | ||
1109 | int netdev_bonding_change(struct net_device *dev, unsigned long event) | 1112 | /** |
1113 | * netdev_notify_peers - notify network peers about existence of @dev | ||
1114 | * @dev: network device | ||
1115 | * | ||
1116 | * Generate traffic such that interested network peers are aware of | ||
1117 | * @dev, such as by generating a gratuitous ARP. This may be used when | ||
1118 | * a device wants to inform the rest of the network about some sort of | ||
1119 | * reconfiguration such as a failover event or virtual machine | ||
1120 | * migration. | ||
1121 | */ | ||
1122 | void netdev_notify_peers(struct net_device *dev) | ||
1110 | { | 1123 | { |
1111 | return call_netdevice_notifiers(event, dev); | 1124 | rtnl_lock(); |
1125 | call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, dev); | ||
1126 | rtnl_unlock(); | ||
1112 | } | 1127 | } |
1113 | EXPORT_SYMBOL(netdev_bonding_change); | 1128 | EXPORT_SYMBOL(netdev_notify_peers); |
1114 | 1129 | ||
1115 | /** | 1130 | /** |
1116 | * dev_load - load a network module | 1131 | * dev_load - load a network module |
@@ -1391,7 +1406,6 @@ rollback: | |||
1391 | nb->notifier_call(nb, NETDEV_DOWN, dev); | 1406 | nb->notifier_call(nb, NETDEV_DOWN, dev); |
1392 | } | 1407 | } |
1393 | nb->notifier_call(nb, NETDEV_UNREGISTER, dev); | 1408 | nb->notifier_call(nb, NETDEV_UNREGISTER, dev); |
1394 | nb->notifier_call(nb, NETDEV_UNREGISTER_BATCH, dev); | ||
1395 | } | 1409 | } |
1396 | } | 1410 | } |
1397 | 1411 | ||
@@ -1433,7 +1447,6 @@ int unregister_netdevice_notifier(struct notifier_block *nb) | |||
1433 | nb->notifier_call(nb, NETDEV_DOWN, dev); | 1447 | nb->notifier_call(nb, NETDEV_DOWN, dev); |
1434 | } | 1448 | } |
1435 | nb->notifier_call(nb, NETDEV_UNREGISTER, dev); | 1449 | nb->notifier_call(nb, NETDEV_UNREGISTER, dev); |
1436 | nb->notifier_call(nb, NETDEV_UNREGISTER_BATCH, dev); | ||
1437 | } | 1450 | } |
1438 | } | 1451 | } |
1439 | unlock: | 1452 | unlock: |
@@ -1639,6 +1652,19 @@ static inline int deliver_skb(struct sk_buff *skb, | |||
1639 | return pt_prev->func(skb, skb->dev, pt_prev, orig_dev); | 1652 | return pt_prev->func(skb, skb->dev, pt_prev, orig_dev); |
1640 | } | 1653 | } |
1641 | 1654 | ||
1655 | static inline bool skb_loop_sk(struct packet_type *ptype, struct sk_buff *skb) | ||
1656 | { | ||
1657 | if (ptype->af_packet_priv == NULL) | ||
1658 | return false; | ||
1659 | |||
1660 | if (ptype->id_match) | ||
1661 | return ptype->id_match(ptype, skb->sk); | ||
1662 | else if ((struct sock *)ptype->af_packet_priv == skb->sk) | ||
1663 | return true; | ||
1664 | |||
1665 | return false; | ||
1666 | } | ||
1667 | |||
1642 | /* | 1668 | /* |
1643 | * Support routine. Sends outgoing frames to any network | 1669 | * Support routine. Sends outgoing frames to any network |
1644 | * taps currently in use. | 1670 | * taps currently in use. |
@@ -1656,8 +1682,7 @@ static void dev_queue_xmit_nit(struct sk_buff *skb, struct net_device *dev) | |||
1656 | * they originated from - MvS (miquels@drinkel.ow.org) | 1682 | * they originated from - MvS (miquels@drinkel.ow.org) |
1657 | */ | 1683 | */ |
1658 | if ((ptype->dev == dev || !ptype->dev) && | 1684 | if ((ptype->dev == dev || !ptype->dev) && |
1659 | (ptype->af_packet_priv == NULL || | 1685 | (!skb_loop_sk(ptype, skb))) { |
1660 | (struct sock *)ptype->af_packet_priv != skb->sk)) { | ||
1661 | if (pt_prev) { | 1686 | if (pt_prev) { |
1662 | deliver_skb(skb2, pt_prev, skb->dev); | 1687 | deliver_skb(skb2, pt_prev, skb->dev); |
1663 | pt_prev = ptype; | 1688 | pt_prev = ptype; |
@@ -2134,6 +2159,9 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) | |||
2134 | __be16 protocol = skb->protocol; | 2159 | __be16 protocol = skb->protocol; |
2135 | netdev_features_t features = skb->dev->features; | 2160 | netdev_features_t features = skb->dev->features; |
2136 | 2161 | ||
2162 | if (skb_shinfo(skb)->gso_segs > skb->dev->gso_max_segs) | ||
2163 | features &= ~NETIF_F_GSO_MASK; | ||
2164 | |||
2137 | if (protocol == htons(ETH_P_8021Q)) { | 2165 | if (protocol == htons(ETH_P_8021Q)) { |
2138 | struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; | 2166 | struct vlan_ethhdr *veh = (struct vlan_ethhdr *)skb->data; |
2139 | protocol = veh->h_vlan_encapsulated_proto; | 2167 | protocol = veh->h_vlan_encapsulated_proto; |
@@ -2156,9 +2184,7 @@ EXPORT_SYMBOL(netif_skb_features); | |||
2156 | /* | 2184 | /* |
2157 | * Returns true if either: | 2185 | * Returns true if either: |
2158 | * 1. skb has frag_list and the device doesn't support FRAGLIST, or | 2186 | * 1. skb has frag_list and the device doesn't support FRAGLIST, or |
2159 | * 2. skb is fragmented and the device does not support SG, or if | 2187 | * 2. skb is fragmented and the device does not support SG. |
2160 | * at least one of fragments is in highmem and device does not | ||
2161 | * support DMA from it. | ||
2162 | */ | 2188 | */ |
2163 | static inline int skb_needs_linearize(struct sk_buff *skb, | 2189 | static inline int skb_needs_linearize(struct sk_buff *skb, |
2164 | int features) | 2190 | int features) |
@@ -4492,8 +4518,8 @@ static void dev_change_rx_flags(struct net_device *dev, int flags) | |||
4492 | static int __dev_set_promiscuity(struct net_device *dev, int inc) | 4518 | static int __dev_set_promiscuity(struct net_device *dev, int inc) |
4493 | { | 4519 | { |
4494 | unsigned int old_flags = dev->flags; | 4520 | unsigned int old_flags = dev->flags; |
4495 | uid_t uid; | 4521 | kuid_t uid; |
4496 | gid_t gid; | 4522 | kgid_t gid; |
4497 | 4523 | ||
4498 | ASSERT_RTNL(); | 4524 | ASSERT_RTNL(); |
4499 | 4525 | ||
@@ -4525,7 +4551,8 @@ static int __dev_set_promiscuity(struct net_device *dev, int inc) | |||
4525 | dev->name, (dev->flags & IFF_PROMISC), | 4551 | dev->name, (dev->flags & IFF_PROMISC), |
4526 | (old_flags & IFF_PROMISC), | 4552 | (old_flags & IFF_PROMISC), |
4527 | audit_get_loginuid(current), | 4553 | audit_get_loginuid(current), |
4528 | uid, gid, | 4554 | from_kuid(&init_user_ns, uid), |
4555 | from_kgid(&init_user_ns, gid), | ||
4529 | audit_get_sessionid(current)); | 4556 | audit_get_sessionid(current)); |
4530 | } | 4557 | } |
4531 | 4558 | ||
@@ -5218,12 +5245,12 @@ int dev_ioctl(struct net *net, unsigned int cmd, void __user *arg) | |||
5218 | */ | 5245 | */ |
5219 | static int dev_new_index(struct net *net) | 5246 | static int dev_new_index(struct net *net) |
5220 | { | 5247 | { |
5221 | static int ifindex; | 5248 | int ifindex = net->ifindex; |
5222 | for (;;) { | 5249 | for (;;) { |
5223 | if (++ifindex <= 0) | 5250 | if (++ifindex <= 0) |
5224 | ifindex = 1; | 5251 | ifindex = 1; |
5225 | if (!__dev_get_by_index(net, ifindex)) | 5252 | if (!__dev_get_by_index(net, ifindex)) |
5226 | return ifindex; | 5253 | return net->ifindex = ifindex; |
5227 | } | 5254 | } |
5228 | } | 5255 | } |
5229 | 5256 | ||
@@ -5301,10 +5328,6 @@ static void rollback_registered_many(struct list_head *head) | |||
5301 | netdev_unregister_kobject(dev); | 5328 | netdev_unregister_kobject(dev); |
5302 | } | 5329 | } |
5303 | 5330 | ||
5304 | /* Process any work delayed until the end of the batch */ | ||
5305 | dev = list_first_entry(head, struct net_device, unreg_list); | ||
5306 | call_netdevice_notifiers(NETDEV_UNREGISTER_BATCH, dev); | ||
5307 | |||
5308 | synchronize_net(); | 5331 | synchronize_net(); |
5309 | 5332 | ||
5310 | list_for_each_entry(dev, head, unreg_list) | 5333 | list_for_each_entry(dev, head, unreg_list) |
@@ -5576,7 +5599,12 @@ int register_netdevice(struct net_device *dev) | |||
5576 | } | 5599 | } |
5577 | } | 5600 | } |
5578 | 5601 | ||
5579 | dev->ifindex = dev_new_index(net); | 5602 | ret = -EBUSY; |
5603 | if (!dev->ifindex) | ||
5604 | dev->ifindex = dev_new_index(net); | ||
5605 | else if (__dev_get_by_index(net, dev->ifindex)) | ||
5606 | goto err_uninit; | ||
5607 | |||
5580 | if (dev->iflink == -1) | 5608 | if (dev->iflink == -1) |
5581 | dev->iflink = dev->ifindex; | 5609 | dev->iflink = dev->ifindex; |
5582 | 5610 | ||
@@ -5619,6 +5647,8 @@ int register_netdevice(struct net_device *dev) | |||
5619 | 5647 | ||
5620 | set_bit(__LINK_STATE_PRESENT, &dev->state); | 5648 | set_bit(__LINK_STATE_PRESENT, &dev->state); |
5621 | 5649 | ||
5650 | linkwatch_init_dev(dev); | ||
5651 | |||
5622 | dev_init_scheduler(dev); | 5652 | dev_init_scheduler(dev); |
5623 | dev_hold(dev); | 5653 | dev_hold(dev); |
5624 | list_netdevice(dev); | 5654 | list_netdevice(dev); |
@@ -5726,6 +5756,7 @@ EXPORT_SYMBOL(netdev_refcnt_read); | |||
5726 | 5756 | ||
5727 | /** | 5757 | /** |
5728 | * netdev_wait_allrefs - wait until all references are gone. | 5758 | * netdev_wait_allrefs - wait until all references are gone. |
5759 | * @dev: target net_device | ||
5729 | * | 5760 | * |
5730 | * This is called when unregistering network devices. | 5761 | * This is called when unregistering network devices. |
5731 | * | 5762 | * |
@@ -5751,9 +5782,12 @@ static void netdev_wait_allrefs(struct net_device *dev) | |||
5751 | 5782 | ||
5752 | /* Rebroadcast unregister notification */ | 5783 | /* Rebroadcast unregister notification */ |
5753 | call_netdevice_notifiers(NETDEV_UNREGISTER, dev); | 5784 | call_netdevice_notifiers(NETDEV_UNREGISTER, dev); |
5754 | /* don't resend NETDEV_UNREGISTER_BATCH, _BATCH users | ||
5755 | * should have already handle it the first time */ | ||
5756 | 5785 | ||
5786 | __rtnl_unlock(); | ||
5787 | rcu_barrier(); | ||
5788 | rtnl_lock(); | ||
5789 | |||
5790 | call_netdevice_notifiers(NETDEV_UNREGISTER_FINAL, dev); | ||
5757 | if (test_bit(__LINK_STATE_LINKWATCH_PENDING, | 5791 | if (test_bit(__LINK_STATE_LINKWATCH_PENDING, |
5758 | &dev->state)) { | 5792 | &dev->state)) { |
5759 | /* We must not have linkwatch events | 5793 | /* We must not have linkwatch events |
@@ -5815,9 +5849,8 @@ void netdev_run_todo(void) | |||
5815 | 5849 | ||
5816 | __rtnl_unlock(); | 5850 | __rtnl_unlock(); |
5817 | 5851 | ||
5818 | /* Wait for rcu callbacks to finish before attempting to drain | 5852 | |
5819 | * the device list. This usually avoids a 250ms wait. | 5853 | /* Wait for rcu callbacks to finish before next phase */ |
5820 | */ | ||
5821 | if (!list_empty(&list)) | 5854 | if (!list_empty(&list)) |
5822 | rcu_barrier(); | 5855 | rcu_barrier(); |
5823 | 5856 | ||
@@ -5826,6 +5859,10 @@ void netdev_run_todo(void) | |||
5826 | = list_first_entry(&list, struct net_device, todo_list); | 5859 | = list_first_entry(&list, struct net_device, todo_list); |
5827 | list_del(&dev->todo_list); | 5860 | list_del(&dev->todo_list); |
5828 | 5861 | ||
5862 | rtnl_lock(); | ||
5863 | call_netdevice_notifiers(NETDEV_UNREGISTER_FINAL, dev); | ||
5864 | __rtnl_unlock(); | ||
5865 | |||
5829 | if (unlikely(dev->reg_state != NETREG_UNREGISTERING)) { | 5866 | if (unlikely(dev->reg_state != NETREG_UNREGISTERING)) { |
5830 | pr_err("network todo '%s' but state %d\n", | 5867 | pr_err("network todo '%s' but state %d\n", |
5831 | dev->name, dev->reg_state); | 5868 | dev->name, dev->reg_state); |
@@ -5986,6 +6023,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, | |||
5986 | dev_net_set(dev, &init_net); | 6023 | dev_net_set(dev, &init_net); |
5987 | 6024 | ||
5988 | dev->gso_max_size = GSO_MAX_SIZE; | 6025 | dev->gso_max_size = GSO_MAX_SIZE; |
6026 | dev->gso_max_segs = GSO_MAX_SEGS; | ||
5989 | 6027 | ||
5990 | INIT_LIST_HEAD(&dev->napi_list); | 6028 | INIT_LIST_HEAD(&dev->napi_list); |
5991 | INIT_LIST_HEAD(&dev->unreg_list); | 6029 | INIT_LIST_HEAD(&dev->unreg_list); |
@@ -6219,7 +6257,8 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char | |||
6219 | the device is just moving and can keep their slaves up. | 6257 | the device is just moving and can keep their slaves up. |
6220 | */ | 6258 | */ |
6221 | call_netdevice_notifiers(NETDEV_UNREGISTER, dev); | 6259 | call_netdevice_notifiers(NETDEV_UNREGISTER, dev); |
6222 | call_netdevice_notifiers(NETDEV_UNREGISTER_BATCH, dev); | 6260 | rcu_barrier(); |
6261 | call_netdevice_notifiers(NETDEV_UNREGISTER_FINAL, dev); | ||
6223 | rtmsg_ifinfo(RTM_DELLINK, dev, ~0U); | 6262 | rtmsg_ifinfo(RTM_DELLINK, dev, ~0U); |
6224 | 6263 | ||
6225 | /* | 6264 | /* |
diff --git a/net/core/dst.c b/net/core/dst.c index 069d51d29414..f6593d238e9a 100644 --- a/net/core/dst.c +++ b/net/core/dst.c | |||
@@ -149,7 +149,15 @@ int dst_discard(struct sk_buff *skb) | |||
149 | } | 149 | } |
150 | EXPORT_SYMBOL(dst_discard); | 150 | EXPORT_SYMBOL(dst_discard); |
151 | 151 | ||
152 | const u32 dst_default_metrics[RTAX_MAX]; | 152 | const u32 dst_default_metrics[RTAX_MAX + 1] = { |
153 | /* This initializer is needed to force linker to place this variable | ||
154 | * into const section. Otherwise it might end into bss section. | ||
155 | * We really want to avoid false sharing on this variable, and catch | ||
156 | * any writes on it. | ||
157 | */ | ||
158 | [RTAX_MAX] = 0xdeadbeef, | ||
159 | }; | ||
160 | |||
153 | 161 | ||
154 | void *dst_alloc(struct dst_ops *ops, struct net_device *dev, | 162 | void *dst_alloc(struct dst_ops *ops, struct net_device *dev, |
155 | int initial_ref, int initial_obsolete, unsigned short flags) | 163 | int initial_ref, int initial_obsolete, unsigned short flags) |
@@ -366,7 +374,7 @@ static int dst_dev_event(struct notifier_block *this, unsigned long event, | |||
366 | struct dst_entry *dst, *last = NULL; | 374 | struct dst_entry *dst, *last = NULL; |
367 | 375 | ||
368 | switch (event) { | 376 | switch (event) { |
369 | case NETDEV_UNREGISTER: | 377 | case NETDEV_UNREGISTER_FINAL: |
370 | case NETDEV_DOWN: | 378 | case NETDEV_DOWN: |
371 | mutex_lock(&dst_gc_mutex); | 379 | mutex_lock(&dst_gc_mutex); |
372 | for (dst = dst_busy_list; dst; dst = dst->next) { | 380 | for (dst = dst_busy_list; dst; dst = dst->next) { |
diff --git a/net/core/link_watch.c b/net/core/link_watch.c index c3519c6d1b16..a01922219a23 100644 --- a/net/core/link_watch.c +++ b/net/core/link_watch.c | |||
@@ -76,6 +76,14 @@ static void rfc2863_policy(struct net_device *dev) | |||
76 | } | 76 | } |
77 | 77 | ||
78 | 78 | ||
79 | void linkwatch_init_dev(struct net_device *dev) | ||
80 | { | ||
81 | /* Handle pre-registration link state changes */ | ||
82 | if (!netif_carrier_ok(dev) || netif_dormant(dev)) | ||
83 | rfc2863_policy(dev); | ||
84 | } | ||
85 | |||
86 | |||
79 | static bool linkwatch_urgent_event(struct net_device *dev) | 87 | static bool linkwatch_urgent_event(struct net_device *dev) |
80 | { | 88 | { |
81 | if (!netif_running(dev)) | 89 | if (!netif_running(dev)) |
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index b4c90e42b443..dd67818025d1 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/workqueue.h> | 26 | #include <linux/workqueue.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/export.h> | 28 | #include <linux/export.h> |
29 | #include <linux/if_vlan.h> | ||
29 | #include <net/tcp.h> | 30 | #include <net/tcp.h> |
30 | #include <net/udp.h> | 31 | #include <net/udp.h> |
31 | #include <asm/unaligned.h> | 32 | #include <asm/unaligned.h> |
@@ -54,7 +55,7 @@ static atomic_t trapped; | |||
54 | MAX_UDP_CHUNK) | 55 | MAX_UDP_CHUNK) |
55 | 56 | ||
56 | static void zap_completion_queue(void); | 57 | static void zap_completion_queue(void); |
57 | static void arp_reply(struct sk_buff *skb); | 58 | static void netpoll_arp_reply(struct sk_buff *skb, struct netpoll_info *npinfo); |
58 | 59 | ||
59 | static unsigned int carrier_timeout = 4; | 60 | static unsigned int carrier_timeout = 4; |
60 | module_param(carrier_timeout, uint, 0644); | 61 | module_param(carrier_timeout, uint, 0644); |
@@ -170,7 +171,8 @@ static void poll_napi(struct net_device *dev) | |||
170 | list_for_each_entry(napi, &dev->napi_list, dev_list) { | 171 | list_for_each_entry(napi, &dev->napi_list, dev_list) { |
171 | if (napi->poll_owner != smp_processor_id() && | 172 | if (napi->poll_owner != smp_processor_id() && |
172 | spin_trylock(&napi->poll_lock)) { | 173 | spin_trylock(&napi->poll_lock)) { |
173 | budget = poll_one_napi(dev->npinfo, napi, budget); | 174 | budget = poll_one_napi(rcu_dereference_bh(dev->npinfo), |
175 | napi, budget); | ||
174 | spin_unlock(&napi->poll_lock); | 176 | spin_unlock(&napi->poll_lock); |
175 | 177 | ||
176 | if (!budget) | 178 | if (!budget) |
@@ -185,13 +187,14 @@ static void service_arp_queue(struct netpoll_info *npi) | |||
185 | struct sk_buff *skb; | 187 | struct sk_buff *skb; |
186 | 188 | ||
187 | while ((skb = skb_dequeue(&npi->arp_tx))) | 189 | while ((skb = skb_dequeue(&npi->arp_tx))) |
188 | arp_reply(skb); | 190 | netpoll_arp_reply(skb, npi); |
189 | } | 191 | } |
190 | } | 192 | } |
191 | 193 | ||
192 | static void netpoll_poll_dev(struct net_device *dev) | 194 | static void netpoll_poll_dev(struct net_device *dev) |
193 | { | 195 | { |
194 | const struct net_device_ops *ops; | 196 | const struct net_device_ops *ops; |
197 | struct netpoll_info *ni = rcu_dereference_bh(dev->npinfo); | ||
195 | 198 | ||
196 | if (!dev || !netif_running(dev)) | 199 | if (!dev || !netif_running(dev)) |
197 | return; | 200 | return; |
@@ -206,17 +209,18 @@ static void netpoll_poll_dev(struct net_device *dev) | |||
206 | poll_napi(dev); | 209 | poll_napi(dev); |
207 | 210 | ||
208 | if (dev->flags & IFF_SLAVE) { | 211 | if (dev->flags & IFF_SLAVE) { |
209 | if (dev->npinfo) { | 212 | if (ni) { |
210 | struct net_device *bond_dev = dev->master; | 213 | struct net_device *bond_dev = dev->master; |
211 | struct sk_buff *skb; | 214 | struct sk_buff *skb; |
212 | while ((skb = skb_dequeue(&dev->npinfo->arp_tx))) { | 215 | struct netpoll_info *bond_ni = rcu_dereference_bh(bond_dev->npinfo); |
216 | while ((skb = skb_dequeue(&ni->arp_tx))) { | ||
213 | skb->dev = bond_dev; | 217 | skb->dev = bond_dev; |
214 | skb_queue_tail(&bond_dev->npinfo->arp_tx, skb); | 218 | skb_queue_tail(&bond_ni->arp_tx, skb); |
215 | } | 219 | } |
216 | } | 220 | } |
217 | } | 221 | } |
218 | 222 | ||
219 | service_arp_queue(dev->npinfo); | 223 | service_arp_queue(ni); |
220 | 224 | ||
221 | zap_completion_queue(); | 225 | zap_completion_queue(); |
222 | } | 226 | } |
@@ -302,6 +306,7 @@ static int netpoll_owner_active(struct net_device *dev) | |||
302 | return 0; | 306 | return 0; |
303 | } | 307 | } |
304 | 308 | ||
309 | /* call with IRQ disabled */ | ||
305 | void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, | 310 | void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, |
306 | struct net_device *dev) | 311 | struct net_device *dev) |
307 | { | 312 | { |
@@ -309,8 +314,11 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, | |||
309 | unsigned long tries; | 314 | unsigned long tries; |
310 | const struct net_device_ops *ops = dev->netdev_ops; | 315 | const struct net_device_ops *ops = dev->netdev_ops; |
311 | /* It is up to the caller to keep npinfo alive. */ | 316 | /* It is up to the caller to keep npinfo alive. */ |
312 | struct netpoll_info *npinfo = np->dev->npinfo; | 317 | struct netpoll_info *npinfo; |
318 | |||
319 | WARN_ON_ONCE(!irqs_disabled()); | ||
313 | 320 | ||
321 | npinfo = rcu_dereference_bh(np->dev->npinfo); | ||
314 | if (!npinfo || !netif_running(dev) || !netif_device_present(dev)) { | 322 | if (!npinfo || !netif_running(dev) || !netif_device_present(dev)) { |
315 | __kfree_skb(skb); | 323 | __kfree_skb(skb); |
316 | return; | 324 | return; |
@@ -319,16 +327,22 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, | |||
319 | /* don't get messages out of order, and no recursion */ | 327 | /* don't get messages out of order, and no recursion */ |
320 | if (skb_queue_len(&npinfo->txq) == 0 && !netpoll_owner_active(dev)) { | 328 | if (skb_queue_len(&npinfo->txq) == 0 && !netpoll_owner_active(dev)) { |
321 | struct netdev_queue *txq; | 329 | struct netdev_queue *txq; |
322 | unsigned long flags; | ||
323 | 330 | ||
324 | txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); | 331 | txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); |
325 | 332 | ||
326 | local_irq_save(flags); | ||
327 | /* try until next clock tick */ | 333 | /* try until next clock tick */ |
328 | for (tries = jiffies_to_usecs(1)/USEC_PER_POLL; | 334 | for (tries = jiffies_to_usecs(1)/USEC_PER_POLL; |
329 | tries > 0; --tries) { | 335 | tries > 0; --tries) { |
330 | if (__netif_tx_trylock(txq)) { | 336 | if (__netif_tx_trylock(txq)) { |
331 | if (!netif_xmit_stopped(txq)) { | 337 | if (!netif_xmit_stopped(txq)) { |
338 | if (vlan_tx_tag_present(skb) && | ||
339 | !(netif_skb_features(skb) & NETIF_F_HW_VLAN_TX)) { | ||
340 | skb = __vlan_put_tag(skb, vlan_tx_tag_get(skb)); | ||
341 | if (unlikely(!skb)) | ||
342 | break; | ||
343 | skb->vlan_tci = 0; | ||
344 | } | ||
345 | |||
332 | status = ops->ndo_start_xmit(skb, dev); | 346 | status = ops->ndo_start_xmit(skb, dev); |
333 | if (status == NETDEV_TX_OK) | 347 | if (status == NETDEV_TX_OK) |
334 | txq_trans_update(txq); | 348 | txq_trans_update(txq); |
@@ -347,10 +361,9 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, | |||
347 | } | 361 | } |
348 | 362 | ||
349 | WARN_ONCE(!irqs_disabled(), | 363 | WARN_ONCE(!irqs_disabled(), |
350 | "netpoll_send_skb(): %s enabled interrupts in poll (%pF)\n", | 364 | "netpoll_send_skb_on_dev(): %s enabled interrupts in poll (%pF)\n", |
351 | dev->name, ops->ndo_start_xmit); | 365 | dev->name, ops->ndo_start_xmit); |
352 | 366 | ||
353 | local_irq_restore(flags); | ||
354 | } | 367 | } |
355 | 368 | ||
356 | if (status != NETDEV_TX_OK) { | 369 | if (status != NETDEV_TX_OK) { |
@@ -367,6 +380,7 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len) | |||
367 | struct udphdr *udph; | 380 | struct udphdr *udph; |
368 | struct iphdr *iph; | 381 | struct iphdr *iph; |
369 | struct ethhdr *eth; | 382 | struct ethhdr *eth; |
383 | static atomic_t ip_ident; | ||
370 | 384 | ||
371 | udp_len = len + sizeof(*udph); | 385 | udp_len = len + sizeof(*udph); |
372 | ip_len = udp_len + sizeof(*iph); | 386 | ip_len = udp_len + sizeof(*iph); |
@@ -402,7 +416,7 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len) | |||
402 | put_unaligned(0x45, (unsigned char *)iph); | 416 | put_unaligned(0x45, (unsigned char *)iph); |
403 | iph->tos = 0; | 417 | iph->tos = 0; |
404 | put_unaligned(htons(ip_len), &(iph->tot_len)); | 418 | put_unaligned(htons(ip_len), &(iph->tot_len)); |
405 | iph->id = 0; | 419 | iph->id = htons(atomic_inc_return(&ip_ident)); |
406 | iph->frag_off = 0; | 420 | iph->frag_off = 0; |
407 | iph->ttl = 64; | 421 | iph->ttl = 64; |
408 | iph->protocol = IPPROTO_UDP; | 422 | iph->protocol = IPPROTO_UDP; |
@@ -423,9 +437,8 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len) | |||
423 | } | 437 | } |
424 | EXPORT_SYMBOL(netpoll_send_udp); | 438 | EXPORT_SYMBOL(netpoll_send_udp); |
425 | 439 | ||
426 | static void arp_reply(struct sk_buff *skb) | 440 | static void netpoll_arp_reply(struct sk_buff *skb, struct netpoll_info *npinfo) |
427 | { | 441 | { |
428 | struct netpoll_info *npinfo = skb->dev->npinfo; | ||
429 | struct arphdr *arp; | 442 | struct arphdr *arp; |
430 | unsigned char *arp_ptr; | 443 | unsigned char *arp_ptr; |
431 | int size, type = ARPOP_REPLY, ptype = ETH_P_ARP; | 444 | int size, type = ARPOP_REPLY, ptype = ETH_P_ARP; |
@@ -543,13 +556,12 @@ static void arp_reply(struct sk_buff *skb) | |||
543 | spin_unlock_irqrestore(&npinfo->rx_lock, flags); | 556 | spin_unlock_irqrestore(&npinfo->rx_lock, flags); |
544 | } | 557 | } |
545 | 558 | ||
546 | int __netpoll_rx(struct sk_buff *skb) | 559 | int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo) |
547 | { | 560 | { |
548 | int proto, len, ulen; | 561 | int proto, len, ulen; |
549 | int hits = 0; | 562 | int hits = 0; |
550 | const struct iphdr *iph; | 563 | const struct iphdr *iph; |
551 | struct udphdr *uh; | 564 | struct udphdr *uh; |
552 | struct netpoll_info *npinfo = skb->dev->npinfo; | ||
553 | struct netpoll *np, *tmp; | 565 | struct netpoll *np, *tmp; |
554 | 566 | ||
555 | if (list_empty(&npinfo->rx_np)) | 567 | if (list_empty(&npinfo->rx_np)) |
@@ -565,6 +577,12 @@ int __netpoll_rx(struct sk_buff *skb) | |||
565 | return 1; | 577 | return 1; |
566 | } | 578 | } |
567 | 579 | ||
580 | if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) { | ||
581 | skb = vlan_untag(skb); | ||
582 | if (unlikely(!skb)) | ||
583 | goto out; | ||
584 | } | ||
585 | |||
568 | proto = ntohs(eth_hdr(skb)->h_proto); | 586 | proto = ntohs(eth_hdr(skb)->h_proto); |
569 | if (proto != ETH_P_IP) | 587 | if (proto != ETH_P_IP) |
570 | goto out; | 588 | goto out; |
@@ -715,7 +733,7 @@ int netpoll_parse_options(struct netpoll *np, char *opt) | |||
715 | } | 733 | } |
716 | EXPORT_SYMBOL(netpoll_parse_options); | 734 | EXPORT_SYMBOL(netpoll_parse_options); |
717 | 735 | ||
718 | int __netpoll_setup(struct netpoll *np, struct net_device *ndev) | 736 | int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp) |
719 | { | 737 | { |
720 | struct netpoll_info *npinfo; | 738 | struct netpoll_info *npinfo; |
721 | const struct net_device_ops *ops; | 739 | const struct net_device_ops *ops; |
@@ -734,7 +752,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev) | |||
734 | } | 752 | } |
735 | 753 | ||
736 | if (!ndev->npinfo) { | 754 | if (!ndev->npinfo) { |
737 | npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL); | 755 | npinfo = kmalloc(sizeof(*npinfo), gfp); |
738 | if (!npinfo) { | 756 | if (!npinfo) { |
739 | err = -ENOMEM; | 757 | err = -ENOMEM; |
740 | goto out; | 758 | goto out; |
@@ -752,7 +770,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev) | |||
752 | 770 | ||
753 | ops = np->dev->netdev_ops; | 771 | ops = np->dev->netdev_ops; |
754 | if (ops->ndo_netpoll_setup) { | 772 | if (ops->ndo_netpoll_setup) { |
755 | err = ops->ndo_netpoll_setup(ndev, npinfo); | 773 | err = ops->ndo_netpoll_setup(ndev, npinfo, gfp); |
756 | if (err) | 774 | if (err) |
757 | goto free_npinfo; | 775 | goto free_npinfo; |
758 | } | 776 | } |
@@ -857,7 +875,7 @@ int netpoll_setup(struct netpoll *np) | |||
857 | refill_skbs(); | 875 | refill_skbs(); |
858 | 876 | ||
859 | rtnl_lock(); | 877 | rtnl_lock(); |
860 | err = __netpoll_setup(np, ndev); | 878 | err = __netpoll_setup(np, ndev, GFP_KERNEL); |
861 | rtnl_unlock(); | 879 | rtnl_unlock(); |
862 | 880 | ||
863 | if (err) | 881 | if (err) |
@@ -878,6 +896,24 @@ static int __init netpoll_init(void) | |||
878 | } | 896 | } |
879 | core_initcall(netpoll_init); | 897 | core_initcall(netpoll_init); |
880 | 898 | ||
899 | static void rcu_cleanup_netpoll_info(struct rcu_head *rcu_head) | ||
900 | { | ||
901 | struct netpoll_info *npinfo = | ||
902 | container_of(rcu_head, struct netpoll_info, rcu); | ||
903 | |||
904 | skb_queue_purge(&npinfo->arp_tx); | ||
905 | skb_queue_purge(&npinfo->txq); | ||
906 | |||
907 | /* we can't call cancel_delayed_work_sync here, as we are in softirq */ | ||
908 | cancel_delayed_work(&npinfo->tx_work); | ||
909 | |||
910 | /* clean after last, unfinished work */ | ||
911 | __skb_queue_purge(&npinfo->txq); | ||
912 | /* now cancel it again */ | ||
913 | cancel_delayed_work(&npinfo->tx_work); | ||
914 | kfree(npinfo); | ||
915 | } | ||
916 | |||
881 | void __netpoll_cleanup(struct netpoll *np) | 917 | void __netpoll_cleanup(struct netpoll *np) |
882 | { | 918 | { |
883 | struct netpoll_info *npinfo; | 919 | struct netpoll_info *npinfo; |
@@ -903,20 +939,24 @@ void __netpoll_cleanup(struct netpoll *np) | |||
903 | ops->ndo_netpoll_cleanup(np->dev); | 939 | ops->ndo_netpoll_cleanup(np->dev); |
904 | 940 | ||
905 | RCU_INIT_POINTER(np->dev->npinfo, NULL); | 941 | RCU_INIT_POINTER(np->dev->npinfo, NULL); |
942 | call_rcu_bh(&npinfo->rcu, rcu_cleanup_netpoll_info); | ||
943 | } | ||
944 | } | ||
945 | EXPORT_SYMBOL_GPL(__netpoll_cleanup); | ||
906 | 946 | ||
907 | /* avoid racing with NAPI reading npinfo */ | 947 | static void rcu_cleanup_netpoll(struct rcu_head *rcu_head) |
908 | synchronize_rcu_bh(); | 948 | { |
949 | struct netpoll *np = container_of(rcu_head, struct netpoll, rcu); | ||
909 | 950 | ||
910 | skb_queue_purge(&npinfo->arp_tx); | 951 | __netpoll_cleanup(np); |
911 | skb_queue_purge(&npinfo->txq); | 952 | kfree(np); |
912 | cancel_delayed_work_sync(&npinfo->tx_work); | 953 | } |
913 | 954 | ||
914 | /* clean after last, unfinished work */ | 955 | void __netpoll_free_rcu(struct netpoll *np) |
915 | __skb_queue_purge(&npinfo->txq); | 956 | { |
916 | kfree(npinfo); | 957 | call_rcu_bh(&np->rcu, rcu_cleanup_netpoll); |
917 | } | ||
918 | } | 958 | } |
919 | EXPORT_SYMBOL_GPL(__netpoll_cleanup); | 959 | EXPORT_SYMBOL_GPL(__netpoll_free_rcu); |
920 | 960 | ||
921 | void netpoll_cleanup(struct netpoll *np) | 961 | void netpoll_cleanup(struct netpoll *np) |
922 | { | 962 | { |
diff --git a/net/core/netprio_cgroup.c b/net/core/netprio_cgroup.c index ed0c0431fcd8..c75e3f9d060f 100644 --- a/net/core/netprio_cgroup.c +++ b/net/core/netprio_cgroup.c | |||
@@ -101,12 +101,10 @@ static int write_update_netdev_table(struct net_device *dev) | |||
101 | u32 max_len; | 101 | u32 max_len; |
102 | struct netprio_map *map; | 102 | struct netprio_map *map; |
103 | 103 | ||
104 | rtnl_lock(); | ||
105 | max_len = atomic_read(&max_prioidx) + 1; | 104 | max_len = atomic_read(&max_prioidx) + 1; |
106 | map = rtnl_dereference(dev->priomap); | 105 | map = rtnl_dereference(dev->priomap); |
107 | if (!map || map->priomap_len < max_len) | 106 | if (!map || map->priomap_len < max_len) |
108 | ret = extend_netdev_table(dev, max_len); | 107 | ret = extend_netdev_table(dev, max_len); |
109 | rtnl_unlock(); | ||
110 | 108 | ||
111 | return ret; | 109 | return ret; |
112 | } | 110 | } |
@@ -256,17 +254,17 @@ static int write_priomap(struct cgroup *cgrp, struct cftype *cft, | |||
256 | if (!dev) | 254 | if (!dev) |
257 | goto out_free_devname; | 255 | goto out_free_devname; |
258 | 256 | ||
257 | rtnl_lock(); | ||
259 | ret = write_update_netdev_table(dev); | 258 | ret = write_update_netdev_table(dev); |
260 | if (ret < 0) | 259 | if (ret < 0) |
261 | goto out_put_dev; | 260 | goto out_put_dev; |
262 | 261 | ||
263 | rcu_read_lock(); | 262 | map = rtnl_dereference(dev->priomap); |
264 | map = rcu_dereference(dev->priomap); | ||
265 | if (map) | 263 | if (map) |
266 | map->priomap[prioidx] = priority; | 264 | map->priomap[prioidx] = priority; |
267 | rcu_read_unlock(); | ||
268 | 265 | ||
269 | out_put_dev: | 266 | out_put_dev: |
267 | rtnl_unlock(); | ||
270 | dev_put(dev); | 268 | dev_put(dev); |
271 | 269 | ||
272 | out_free_devname: | 270 | out_free_devname: |
@@ -277,12 +275,6 @@ out_free_devname: | |||
277 | void net_prio_attach(struct cgroup *cgrp, struct cgroup_taskset *tset) | 275 | void net_prio_attach(struct cgroup *cgrp, struct cgroup_taskset *tset) |
278 | { | 276 | { |
279 | struct task_struct *p; | 277 | struct task_struct *p; |
280 | char *tmp = kzalloc(sizeof(char) * PATH_MAX, GFP_KERNEL); | ||
281 | |||
282 | if (!tmp) { | ||
283 | pr_warn("Unable to attach cgrp due to alloc failure!\n"); | ||
284 | return; | ||
285 | } | ||
286 | 278 | ||
287 | cgroup_taskset_for_each(p, cgrp, tset) { | 279 | cgroup_taskset_for_each(p, cgrp, tset) { |
288 | unsigned int fd; | 280 | unsigned int fd; |
@@ -296,32 +288,24 @@ void net_prio_attach(struct cgroup *cgrp, struct cgroup_taskset *tset) | |||
296 | continue; | 288 | continue; |
297 | } | 289 | } |
298 | 290 | ||
299 | rcu_read_lock(); | 291 | spin_lock(&files->file_lock); |
300 | fdt = files_fdtable(files); | 292 | fdt = files_fdtable(files); |
301 | for (fd = 0; fd < fdt->max_fds; fd++) { | 293 | for (fd = 0; fd < fdt->max_fds; fd++) { |
302 | char *path; | ||
303 | struct file *file; | 294 | struct file *file; |
304 | struct socket *sock; | 295 | struct socket *sock; |
305 | unsigned long s; | 296 | int err; |
306 | int rv, err = 0; | ||
307 | 297 | ||
308 | file = fcheck_files(files, fd); | 298 | file = fcheck_files(files, fd); |
309 | if (!file) | 299 | if (!file) |
310 | continue; | 300 | continue; |
311 | 301 | ||
312 | path = d_path(&file->f_path, tmp, PAGE_SIZE); | ||
313 | rv = sscanf(path, "socket:[%lu]", &s); | ||
314 | if (rv <= 0) | ||
315 | continue; | ||
316 | |||
317 | sock = sock_from_file(file, &err); | 302 | sock = sock_from_file(file, &err); |
318 | if (!err) | 303 | if (sock) |
319 | sock_update_netprioidx(sock->sk, p); | 304 | sock_update_netprioidx(sock->sk, p); |
320 | } | 305 | } |
321 | rcu_read_unlock(); | 306 | spin_unlock(&files->file_lock); |
322 | task_unlock(p); | 307 | task_unlock(p); |
323 | } | 308 | } |
324 | kfree(tmp); | ||
325 | } | 309 | } |
326 | 310 | ||
327 | static struct cftype ss_files[] = { | 311 | static struct cftype ss_files[] = { |
diff --git a/net/core/request_sock.c b/net/core/request_sock.c index 9b570a6a33c5..c31d9e8668c3 100644 --- a/net/core/request_sock.c +++ b/net/core/request_sock.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/random.h> | 15 | #include <linux/random.h> |
16 | #include <linux/slab.h> | 16 | #include <linux/slab.h> |
17 | #include <linux/string.h> | 17 | #include <linux/string.h> |
18 | #include <linux/tcp.h> | ||
18 | #include <linux/vmalloc.h> | 19 | #include <linux/vmalloc.h> |
19 | 20 | ||
20 | #include <net/request_sock.h> | 21 | #include <net/request_sock.h> |
@@ -130,3 +131,97 @@ void reqsk_queue_destroy(struct request_sock_queue *queue) | |||
130 | kfree(lopt); | 131 | kfree(lopt); |
131 | } | 132 | } |
132 | 133 | ||
134 | /* | ||
135 | * This function is called to set a Fast Open socket's "fastopen_rsk" field | ||
136 | * to NULL when a TFO socket no longer needs to access the request_sock. | ||
137 | * This happens only after 3WHS has been either completed or aborted (e.g., | ||
138 | * RST is received). | ||
139 | * | ||
140 | * Before TFO, a child socket is created only after 3WHS is completed, | ||
141 | * hence it never needs to access the request_sock. things get a lot more | ||
142 | * complex with TFO. A child socket, accepted or not, has to access its | ||
143 | * request_sock for 3WHS processing, e.g., to retransmit SYN-ACK pkts, | ||
144 | * until 3WHS is either completed or aborted. Afterwards the req will stay | ||
145 | * until either the child socket is accepted, or in the rare case when the | ||
146 | * listener is closed before the child is accepted. | ||
147 | * | ||
148 | * In short, a request socket is only freed after BOTH 3WHS has completed | ||
149 | * (or aborted) and the child socket has been accepted (or listener closed). | ||
150 | * When a child socket is accepted, its corresponding req->sk is set to | ||
151 | * NULL since it's no longer needed. More importantly, "req->sk == NULL" | ||
152 | * will be used by the code below to determine if a child socket has been | ||
153 | * accepted or not, and the check is protected by the fastopenq->lock | ||
154 | * described below. | ||
155 | * | ||
156 | * Note that fastopen_rsk is only accessed from the child socket's context | ||
157 | * with its socket lock held. But a request_sock (req) can be accessed by | ||
158 | * both its child socket through fastopen_rsk, and a listener socket through | ||
159 | * icsk_accept_queue.rskq_accept_head. To protect the access a simple spin | ||
160 | * lock per listener "icsk->icsk_accept_queue.fastopenq->lock" is created. | ||
161 | * only in the rare case when both the listener and the child locks are held, | ||
162 | * e.g., in inet_csk_listen_stop() do we not need to acquire the lock. | ||
163 | * The lock also protects other fields such as fastopenq->qlen, which is | ||
164 | * decremented by this function when fastopen_rsk is no longer needed. | ||
165 | * | ||
166 | * Note that another solution was to simply use the existing socket lock | ||
167 | * from the listener. But first socket lock is difficult to use. It is not | ||
168 | * a simple spin lock - one must consider sock_owned_by_user() and arrange | ||
169 | * to use sk_add_backlog() stuff. But what really makes it infeasible is the | ||
170 | * locking hierarchy violation. E.g., inet_csk_listen_stop() may try to | ||
171 | * acquire a child's lock while holding listener's socket lock. A corner | ||
172 | * case might also exist in tcp_v4_hnd_req() that will trigger this locking | ||
173 | * order. | ||
174 | * | ||
175 | * When a TFO req is created, it needs to sock_hold its listener to prevent | ||
176 | * the latter data structure from going away. | ||
177 | * | ||
178 | * This function also sets "treq->listener" to NULL and unreference listener | ||
179 | * socket. treq->listener is used by the listener so it is protected by the | ||
180 | * fastopenq->lock in this function. | ||
181 | */ | ||
182 | void reqsk_fastopen_remove(struct sock *sk, struct request_sock *req, | ||
183 | bool reset) | ||
184 | { | ||
185 | struct sock *lsk = tcp_rsk(req)->listener; | ||
186 | struct fastopen_queue *fastopenq = | ||
187 | inet_csk(lsk)->icsk_accept_queue.fastopenq; | ||
188 | |||
189 | BUG_ON(!spin_is_locked(&sk->sk_lock.slock) && !sock_owned_by_user(sk)); | ||
190 | |||
191 | tcp_sk(sk)->fastopen_rsk = NULL; | ||
192 | spin_lock_bh(&fastopenq->lock); | ||
193 | fastopenq->qlen--; | ||
194 | tcp_rsk(req)->listener = NULL; | ||
195 | if (req->sk) /* the child socket hasn't been accepted yet */ | ||
196 | goto out; | ||
197 | |||
198 | if (!reset || lsk->sk_state != TCP_LISTEN) { | ||
199 | /* If the listener has been closed don't bother with the | ||
200 | * special RST handling below. | ||
201 | */ | ||
202 | spin_unlock_bh(&fastopenq->lock); | ||
203 | sock_put(lsk); | ||
204 | reqsk_free(req); | ||
205 | return; | ||
206 | } | ||
207 | /* Wait for 60secs before removing a req that has triggered RST. | ||
208 | * This is a simple defense against TFO spoofing attack - by | ||
209 | * counting the req against fastopen.max_qlen, and disabling | ||
210 | * TFO when the qlen exceeds max_qlen. | ||
211 | * | ||
212 | * For more details see CoNext'11 "TCP Fast Open" paper. | ||
213 | */ | ||
214 | req->expires = jiffies + 60*HZ; | ||
215 | if (fastopenq->rskq_rst_head == NULL) | ||
216 | fastopenq->rskq_rst_head = req; | ||
217 | else | ||
218 | fastopenq->rskq_rst_tail->dl_next = req; | ||
219 | |||
220 | req->dl_next = NULL; | ||
221 | fastopenq->rskq_rst_tail = req; | ||
222 | fastopenq->qlen++; | ||
223 | out: | ||
224 | spin_unlock_bh(&fastopenq->lock); | ||
225 | sock_put(lsk); | ||
226 | return; | ||
227 | } | ||
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 2c5a0a06c4ce..c64efcff8078 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -618,7 +618,7 @@ int rtnl_put_cacheinfo(struct sk_buff *skb, struct dst_entry *dst, u32 id, | |||
618 | long expires, u32 error) | 618 | long expires, u32 error) |
619 | { | 619 | { |
620 | struct rta_cacheinfo ci = { | 620 | struct rta_cacheinfo ci = { |
621 | .rta_lastuse = jiffies_to_clock_t(jiffies - dst->lastuse), | 621 | .rta_lastuse = jiffies_delta_to_clock_t(jiffies - dst->lastuse), |
622 | .rta_used = dst->__use, | 622 | .rta_used = dst->__use, |
623 | .rta_clntref = atomic_read(&(dst->__refcnt)), | 623 | .rta_clntref = atomic_read(&(dst->__refcnt)), |
624 | .rta_error = error, | 624 | .rta_error = error, |
@@ -1812,8 +1812,6 @@ replay: | |||
1812 | return -ENODEV; | 1812 | return -ENODEV; |
1813 | } | 1813 | } |
1814 | 1814 | ||
1815 | if (ifm->ifi_index) | ||
1816 | return -EOPNOTSUPP; | ||
1817 | if (tb[IFLA_MAP] || tb[IFLA_MASTER] || tb[IFLA_PROTINFO]) | 1815 | if (tb[IFLA_MAP] || tb[IFLA_MASTER] || tb[IFLA_PROTINFO]) |
1818 | return -EOPNOTSUPP; | 1816 | return -EOPNOTSUPP; |
1819 | 1817 | ||
@@ -1839,10 +1837,14 @@ replay: | |||
1839 | return PTR_ERR(dest_net); | 1837 | return PTR_ERR(dest_net); |
1840 | 1838 | ||
1841 | dev = rtnl_create_link(net, dest_net, ifname, ops, tb); | 1839 | dev = rtnl_create_link(net, dest_net, ifname, ops, tb); |
1842 | 1840 | if (IS_ERR(dev)) { | |
1843 | if (IS_ERR(dev)) | ||
1844 | err = PTR_ERR(dev); | 1841 | err = PTR_ERR(dev); |
1845 | else if (ops->newlink) | 1842 | goto out; |
1843 | } | ||
1844 | |||
1845 | dev->ifindex = ifm->ifi_index; | ||
1846 | |||
1847 | if (ops->newlink) | ||
1846 | err = ops->newlink(net, dev, tb, data); | 1848 | err = ops->newlink(net, dev, tb, data); |
1847 | else | 1849 | else |
1848 | err = register_netdevice(dev); | 1850 | err = register_netdevice(dev); |
@@ -2356,7 +2358,7 @@ static int rtnetlink_event(struct notifier_block *this, unsigned long event, voi | |||
2356 | case NETDEV_PRE_TYPE_CHANGE: | 2358 | case NETDEV_PRE_TYPE_CHANGE: |
2357 | case NETDEV_GOING_DOWN: | 2359 | case NETDEV_GOING_DOWN: |
2358 | case NETDEV_UNREGISTER: | 2360 | case NETDEV_UNREGISTER: |
2359 | case NETDEV_UNREGISTER_BATCH: | 2361 | case NETDEV_UNREGISTER_FINAL: |
2360 | case NETDEV_RELEASE: | 2362 | case NETDEV_RELEASE: |
2361 | case NETDEV_JOIN: | 2363 | case NETDEV_JOIN: |
2362 | break; | 2364 | break; |
diff --git a/net/core/scm.c b/net/core/scm.c index 8f6ccfd68ef4..6ab491d6c26f 100644 --- a/net/core/scm.c +++ b/net/core/scm.c | |||
@@ -45,12 +45,17 @@ | |||
45 | static __inline__ int scm_check_creds(struct ucred *creds) | 45 | static __inline__ int scm_check_creds(struct ucred *creds) |
46 | { | 46 | { |
47 | const struct cred *cred = current_cred(); | 47 | const struct cred *cred = current_cred(); |
48 | kuid_t uid = make_kuid(cred->user_ns, creds->uid); | ||
49 | kgid_t gid = make_kgid(cred->user_ns, creds->gid); | ||
50 | |||
51 | if (!uid_valid(uid) || !gid_valid(gid)) | ||
52 | return -EINVAL; | ||
48 | 53 | ||
49 | if ((creds->pid == task_tgid_vnr(current) || capable(CAP_SYS_ADMIN)) && | 54 | if ((creds->pid == task_tgid_vnr(current) || capable(CAP_SYS_ADMIN)) && |
50 | ((creds->uid == cred->uid || creds->uid == cred->euid || | 55 | ((uid_eq(uid, cred->uid) || uid_eq(uid, cred->euid) || |
51 | creds->uid == cred->suid) || capable(CAP_SETUID)) && | 56 | uid_eq(uid, cred->suid)) || capable(CAP_SETUID)) && |
52 | ((creds->gid == cred->gid || creds->gid == cred->egid || | 57 | ((gid_eq(gid, cred->gid) || gid_eq(gid, cred->egid) || |
53 | creds->gid == cred->sgid) || capable(CAP_SETGID))) { | 58 | gid_eq(gid, cred->sgid)) || capable(CAP_SETGID))) { |
54 | return 0; | 59 | return 0; |
55 | } | 60 | } |
56 | return -EPERM; | 61 | return -EPERM; |
@@ -149,6 +154,9 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p) | |||
149 | goto error; | 154 | goto error; |
150 | break; | 155 | break; |
151 | case SCM_CREDENTIALS: | 156 | case SCM_CREDENTIALS: |
157 | { | ||
158 | kuid_t uid; | ||
159 | kgid_t gid; | ||
152 | if (cmsg->cmsg_len != CMSG_LEN(sizeof(struct ucred))) | 160 | if (cmsg->cmsg_len != CMSG_LEN(sizeof(struct ucred))) |
153 | goto error; | 161 | goto error; |
154 | memcpy(&p->creds, CMSG_DATA(cmsg), sizeof(struct ucred)); | 162 | memcpy(&p->creds, CMSG_DATA(cmsg), sizeof(struct ucred)); |
@@ -166,22 +174,29 @@ int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *p) | |||
166 | p->pid = pid; | 174 | p->pid = pid; |
167 | } | 175 | } |
168 | 176 | ||
177 | err = -EINVAL; | ||
178 | uid = make_kuid(current_user_ns(), p->creds.uid); | ||
179 | gid = make_kgid(current_user_ns(), p->creds.gid); | ||
180 | if (!uid_valid(uid) || !gid_valid(gid)) | ||
181 | goto error; | ||
182 | |||
169 | if (!p->cred || | 183 | if (!p->cred || |
170 | (p->cred->euid != p->creds.uid) || | 184 | !uid_eq(p->cred->euid, uid) || |
171 | (p->cred->egid != p->creds.gid)) { | 185 | !gid_eq(p->cred->egid, gid)) { |
172 | struct cred *cred; | 186 | struct cred *cred; |
173 | err = -ENOMEM; | 187 | err = -ENOMEM; |
174 | cred = prepare_creds(); | 188 | cred = prepare_creds(); |
175 | if (!cred) | 189 | if (!cred) |
176 | goto error; | 190 | goto error; |
177 | 191 | ||
178 | cred->uid = cred->euid = p->creds.uid; | 192 | cred->uid = cred->euid = uid; |
179 | cred->gid = cred->egid = p->creds.gid; | 193 | cred->gid = cred->egid = gid; |
180 | if (p->cred) | 194 | if (p->cred) |
181 | put_cred(p->cred); | 195 | put_cred(p->cred); |
182 | p->cred = cred; | 196 | p->cred = cred; |
183 | } | 197 | } |
184 | break; | 198 | break; |
199 | } | ||
185 | default: | 200 | default: |
186 | goto error; | 201 | goto error; |
187 | } | 202 | } |
@@ -265,6 +280,7 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm) | |||
265 | for (i=0, cmfptr=(__force int __user *)CMSG_DATA(cm); i<fdmax; | 280 | for (i=0, cmfptr=(__force int __user *)CMSG_DATA(cm); i<fdmax; |
266 | i++, cmfptr++) | 281 | i++, cmfptr++) |
267 | { | 282 | { |
283 | struct socket *sock; | ||
268 | int new_fd; | 284 | int new_fd; |
269 | err = security_file_receive(fp[i]); | 285 | err = security_file_receive(fp[i]); |
270 | if (err) | 286 | if (err) |
@@ -281,6 +297,9 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm) | |||
281 | } | 297 | } |
282 | /* Bump the usage count and install the file. */ | 298 | /* Bump the usage count and install the file. */ |
283 | get_file(fp[i]); | 299 | get_file(fp[i]); |
300 | sock = sock_from_file(fp[i], &err); | ||
301 | if (sock) | ||
302 | sock_update_netprioidx(sock->sk, current); | ||
284 | fd_install(new_fd, fp[i]); | 303 | fd_install(new_fd, fp[i]); |
285 | } | 304 | } |
286 | 305 | ||
diff --git a/net/core/secure_seq.c b/net/core/secure_seq.c index 99b2596531bb..e61a8bb7fce7 100644 --- a/net/core/secure_seq.c +++ b/net/core/secure_seq.c | |||
@@ -76,6 +76,7 @@ u32 secure_ipv6_port_ephemeral(const __be32 *saddr, const __be32 *daddr, | |||
76 | 76 | ||
77 | return hash[0]; | 77 | return hash[0]; |
78 | } | 78 | } |
79 | EXPORT_SYMBOL(secure_ipv6_port_ephemeral); | ||
79 | #endif | 80 | #endif |
80 | 81 | ||
81 | #ifdef CONFIG_INET | 82 | #ifdef CONFIG_INET |
diff --git a/net/core/sock.c b/net/core/sock.c index 6b654b3ddfda..d765156eab65 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -868,8 +868,8 @@ void cred_to_ucred(struct pid *pid, const struct cred *cred, | |||
868 | if (cred) { | 868 | if (cred) { |
869 | struct user_namespace *current_ns = current_user_ns(); | 869 | struct user_namespace *current_ns = current_user_ns(); |
870 | 870 | ||
871 | ucred->uid = from_kuid(current_ns, cred->euid); | 871 | ucred->uid = from_kuid_munged(current_ns, cred->euid); |
872 | ucred->gid = from_kgid(current_ns, cred->egid); | 872 | ucred->gid = from_kgid_munged(current_ns, cred->egid); |
873 | } | 873 | } |
874 | } | 874 | } |
875 | EXPORT_SYMBOL_GPL(cred_to_ucred); | 875 | EXPORT_SYMBOL_GPL(cred_to_ucred); |
@@ -1230,7 +1230,7 @@ void sock_update_classid(struct sock *sk) | |||
1230 | rcu_read_lock(); /* doing current task, which cannot vanish. */ | 1230 | rcu_read_lock(); /* doing current task, which cannot vanish. */ |
1231 | classid = task_cls_classid(current); | 1231 | classid = task_cls_classid(current); |
1232 | rcu_read_unlock(); | 1232 | rcu_read_unlock(); |
1233 | if (classid && classid != sk->sk_classid) | 1233 | if (classid != sk->sk_classid) |
1234 | sk->sk_classid = classid; | 1234 | sk->sk_classid = classid; |
1235 | } | 1235 | } |
1236 | EXPORT_SYMBOL(sock_update_classid); | 1236 | EXPORT_SYMBOL(sock_update_classid); |
@@ -1458,6 +1458,7 @@ void sk_setup_caps(struct sock *sk, struct dst_entry *dst) | |||
1458 | } else { | 1458 | } else { |
1459 | sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM; | 1459 | sk->sk_route_caps |= NETIF_F_SG | NETIF_F_HW_CSUM; |
1460 | sk->sk_gso_max_size = dst->dev->gso_max_size; | 1460 | sk->sk_gso_max_size = dst->dev->gso_max_size; |
1461 | sk->sk_gso_max_segs = dst->dev->gso_max_segs; | ||
1461 | } | 1462 | } |
1462 | } | 1463 | } |
1463 | } | 1464 | } |
@@ -1526,12 +1527,12 @@ void sock_edemux(struct sk_buff *skb) | |||
1526 | } | 1527 | } |
1527 | EXPORT_SYMBOL(sock_edemux); | 1528 | EXPORT_SYMBOL(sock_edemux); |
1528 | 1529 | ||
1529 | int sock_i_uid(struct sock *sk) | 1530 | kuid_t sock_i_uid(struct sock *sk) |
1530 | { | 1531 | { |
1531 | int uid; | 1532 | kuid_t uid; |
1532 | 1533 | ||
1533 | read_lock_bh(&sk->sk_callback_lock); | 1534 | read_lock_bh(&sk->sk_callback_lock); |
1534 | uid = sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_uid : 0; | 1535 | uid = sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_uid : GLOBAL_ROOT_UID; |
1535 | read_unlock_bh(&sk->sk_callback_lock); | 1536 | read_unlock_bh(&sk->sk_callback_lock); |
1536 | return uid; | 1537 | return uid; |
1537 | } | 1538 | } |
diff --git a/net/core/utils.c b/net/core/utils.c index 39895a65e54a..f5613d569c23 100644 --- a/net/core/utils.c +++ b/net/core/utils.c | |||
@@ -294,6 +294,26 @@ void inet_proto_csum_replace4(__sum16 *sum, struct sk_buff *skb, | |||
294 | } | 294 | } |
295 | EXPORT_SYMBOL(inet_proto_csum_replace4); | 295 | EXPORT_SYMBOL(inet_proto_csum_replace4); |
296 | 296 | ||
297 | void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb, | ||
298 | const __be32 *from, const __be32 *to, | ||
299 | int pseudohdr) | ||
300 | { | ||
301 | __be32 diff[] = { | ||
302 | ~from[0], ~from[1], ~from[2], ~from[3], | ||
303 | to[0], to[1], to[2], to[3], | ||
304 | }; | ||
305 | if (skb->ip_summed != CHECKSUM_PARTIAL) { | ||
306 | *sum = csum_fold(csum_partial(diff, sizeof(diff), | ||
307 | ~csum_unfold(*sum))); | ||
308 | if (skb->ip_summed == CHECKSUM_COMPLETE && pseudohdr) | ||
309 | skb->csum = ~csum_partial(diff, sizeof(diff), | ||
310 | ~skb->csum); | ||
311 | } else if (pseudohdr) | ||
312 | *sum = ~csum_fold(csum_partial(diff, sizeof(diff), | ||
313 | csum_unfold(*sum))); | ||
314 | } | ||
315 | EXPORT_SYMBOL(inet_proto_csum_replace16); | ||
316 | |||
297 | int mac_pton(const char *s, u8 *mac) | 317 | int mac_pton(const char *s, u8 *mac) |
298 | { | 318 | { |
299 | int i; | 319 | int i; |
diff --git a/net/dccp/ccid.h b/net/dccp/ccid.h index 75c3582a7678..fb85d371a8de 100644 --- a/net/dccp/ccid.h +++ b/net/dccp/ccid.h | |||
@@ -246,7 +246,7 @@ static inline int ccid_hc_rx_getsockopt(struct ccid *ccid, struct sock *sk, | |||
246 | u32 __user *optval, int __user *optlen) | 246 | u32 __user *optval, int __user *optlen) |
247 | { | 247 | { |
248 | int rc = -ENOPROTOOPT; | 248 | int rc = -ENOPROTOOPT; |
249 | if (ccid->ccid_ops->ccid_hc_rx_getsockopt != NULL) | 249 | if (ccid != NULL && ccid->ccid_ops->ccid_hc_rx_getsockopt != NULL) |
250 | rc = ccid->ccid_ops->ccid_hc_rx_getsockopt(sk, optname, len, | 250 | rc = ccid->ccid_ops->ccid_hc_rx_getsockopt(sk, optname, len, |
251 | optval, optlen); | 251 | optval, optlen); |
252 | return rc; | 252 | return rc; |
@@ -257,7 +257,7 @@ static inline int ccid_hc_tx_getsockopt(struct ccid *ccid, struct sock *sk, | |||
257 | u32 __user *optval, int __user *optlen) | 257 | u32 __user *optval, int __user *optlen) |
258 | { | 258 | { |
259 | int rc = -ENOPROTOOPT; | 259 | int rc = -ENOPROTOOPT; |
260 | if (ccid->ccid_ops->ccid_hc_tx_getsockopt != NULL) | 260 | if (ccid != NULL && ccid->ccid_ops->ccid_hc_tx_getsockopt != NULL) |
261 | rc = ccid->ccid_ops->ccid_hc_tx_getsockopt(sk, optname, len, | 261 | rc = ccid->ccid_ops->ccid_hc_tx_getsockopt(sk, optname, len, |
262 | optval, optlen); | 262 | optval, optlen); |
263 | return rc; | 263 | return rc; |
diff --git a/net/dccp/ccids/ccid3.c b/net/dccp/ccids/ccid3.c index d65e98798eca..119c04317d48 100644 --- a/net/dccp/ccids/ccid3.c +++ b/net/dccp/ccids/ccid3.c | |||
@@ -535,6 +535,7 @@ static int ccid3_hc_tx_getsockopt(struct sock *sk, const int optname, int len, | |||
535 | case DCCP_SOCKOPT_CCID_TX_INFO: | 535 | case DCCP_SOCKOPT_CCID_TX_INFO: |
536 | if (len < sizeof(tfrc)) | 536 | if (len < sizeof(tfrc)) |
537 | return -EINVAL; | 537 | return -EINVAL; |
538 | memset(&tfrc, 0, sizeof(tfrc)); | ||
538 | tfrc.tfrctx_x = hc->tx_x; | 539 | tfrc.tfrctx_x = hc->tx_x; |
539 | tfrc.tfrctx_x_recv = hc->tx_x_recv; | 540 | tfrc.tfrctx_x_recv = hc->tx_x_recv; |
540 | tfrc.tfrctx_x_calc = hc->tx_x_calc; | 541 | tfrc.tfrctx_x_calc = hc->tx_x_calc; |
diff --git a/net/decnet/af_decnet.c b/net/decnet/af_decnet.c index 2ba1a2814c24..307c322d53bb 100644 --- a/net/decnet/af_decnet.c +++ b/net/decnet/af_decnet.c | |||
@@ -1313,10 +1313,10 @@ static int dn_shutdown(struct socket *sock, int how) | |||
1313 | if (scp->state == DN_O) | 1313 | if (scp->state == DN_O) |
1314 | goto out; | 1314 | goto out; |
1315 | 1315 | ||
1316 | if (how != SHUTDOWN_MASK) | 1316 | if (how != SHUT_RDWR) |
1317 | goto out; | 1317 | goto out; |
1318 | 1318 | ||
1319 | sk->sk_shutdown = how; | 1319 | sk->sk_shutdown = SHUTDOWN_MASK; |
1320 | dn_destroy_sock(sk); | 1320 | dn_destroy_sock(sk); |
1321 | err = 0; | 1321 | err = 0; |
1322 | 1322 | ||
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index 85a3604c87c8..c855e8d0738f 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c | |||
@@ -961,7 +961,7 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowidn *o | |||
961 | .saddr = oldflp->saddr, | 961 | .saddr = oldflp->saddr, |
962 | .flowidn_scope = RT_SCOPE_UNIVERSE, | 962 | .flowidn_scope = RT_SCOPE_UNIVERSE, |
963 | .flowidn_mark = oldflp->flowidn_mark, | 963 | .flowidn_mark = oldflp->flowidn_mark, |
964 | .flowidn_iif = init_net.loopback_dev->ifindex, | 964 | .flowidn_iif = LOOPBACK_IFINDEX, |
965 | .flowidn_oif = oldflp->flowidn_oif, | 965 | .flowidn_oif = oldflp->flowidn_oif, |
966 | }; | 966 | }; |
967 | struct dn_route *rt = NULL; | 967 | struct dn_route *rt = NULL; |
@@ -979,7 +979,7 @@ static int dn_route_output_slow(struct dst_entry **pprt, const struct flowidn *o | |||
979 | "dn_route_output_slow: dst=%04x src=%04x mark=%d" | 979 | "dn_route_output_slow: dst=%04x src=%04x mark=%d" |
980 | " iif=%d oif=%d\n", le16_to_cpu(oldflp->daddr), | 980 | " iif=%d oif=%d\n", le16_to_cpu(oldflp->daddr), |
981 | le16_to_cpu(oldflp->saddr), | 981 | le16_to_cpu(oldflp->saddr), |
982 | oldflp->flowidn_mark, init_net.loopback_dev->ifindex, | 982 | oldflp->flowidn_mark, LOOPBACK_IFINDEX, |
983 | oldflp->flowidn_oif); | 983 | oldflp->flowidn_oif); |
984 | 984 | ||
985 | /* If we have an output interface, verify its a DECnet device */ | 985 | /* If we have an output interface, verify its a DECnet device */ |
@@ -1042,7 +1042,7 @@ source_ok: | |||
1042 | if (!fld.daddr) | 1042 | if (!fld.daddr) |
1043 | goto out; | 1043 | goto out; |
1044 | } | 1044 | } |
1045 | fld.flowidn_oif = init_net.loopback_dev->ifindex; | 1045 | fld.flowidn_oif = LOOPBACK_IFINDEX; |
1046 | res.type = RTN_LOCAL; | 1046 | res.type = RTN_LOCAL; |
1047 | goto make_route; | 1047 | goto make_route; |
1048 | } | 1048 | } |
diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan.c index 6a095225148e..d5291113584f 100644 --- a/net/ieee802154/6lowpan.c +++ b/net/ieee802154/6lowpan.c | |||
@@ -1063,12 +1063,6 @@ out: | |||
1063 | return (err < 0 ? NETDEV_TX_BUSY : NETDEV_TX_OK); | 1063 | return (err < 0 ? NETDEV_TX_BUSY : NETDEV_TX_OK); |
1064 | } | 1064 | } |
1065 | 1065 | ||
1066 | static void lowpan_dev_free(struct net_device *dev) | ||
1067 | { | ||
1068 | dev_put(lowpan_dev_info(dev)->real_dev); | ||
1069 | free_netdev(dev); | ||
1070 | } | ||
1071 | |||
1072 | static struct wpan_phy *lowpan_get_phy(const struct net_device *dev) | 1066 | static struct wpan_phy *lowpan_get_phy(const struct net_device *dev) |
1073 | { | 1067 | { |
1074 | struct net_device *real_dev = lowpan_dev_info(dev)->real_dev; | 1068 | struct net_device *real_dev = lowpan_dev_info(dev)->real_dev; |
@@ -1118,7 +1112,7 @@ static void lowpan_setup(struct net_device *dev) | |||
1118 | dev->netdev_ops = &lowpan_netdev_ops; | 1112 | dev->netdev_ops = &lowpan_netdev_ops; |
1119 | dev->header_ops = &lowpan_header_ops; | 1113 | dev->header_ops = &lowpan_header_ops; |
1120 | dev->ml_priv = &lowpan_mlme; | 1114 | dev->ml_priv = &lowpan_mlme; |
1121 | dev->destructor = lowpan_dev_free; | 1115 | dev->destructor = free_netdev; |
1122 | } | 1116 | } |
1123 | 1117 | ||
1124 | static int lowpan_validate(struct nlattr *tb[], struct nlattr *data[]) | 1118 | static int lowpan_validate(struct nlattr *tb[], struct nlattr *data[]) |
@@ -1133,6 +1127,8 @@ static int lowpan_validate(struct nlattr *tb[], struct nlattr *data[]) | |||
1133 | static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev, | 1127 | static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev, |
1134 | struct packet_type *pt, struct net_device *orig_dev) | 1128 | struct packet_type *pt, struct net_device *orig_dev) |
1135 | { | 1129 | { |
1130 | struct sk_buff *local_skb; | ||
1131 | |||
1136 | if (!netif_running(dev)) | 1132 | if (!netif_running(dev)) |
1137 | goto drop; | 1133 | goto drop; |
1138 | 1134 | ||
@@ -1144,7 +1140,12 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev, | |||
1144 | case LOWPAN_DISPATCH_IPHC: /* ipv6 datagram */ | 1140 | case LOWPAN_DISPATCH_IPHC: /* ipv6 datagram */ |
1145 | case LOWPAN_DISPATCH_FRAG1: /* first fragment header */ | 1141 | case LOWPAN_DISPATCH_FRAG1: /* first fragment header */ |
1146 | case LOWPAN_DISPATCH_FRAGN: /* next fragments headers */ | 1142 | case LOWPAN_DISPATCH_FRAGN: /* next fragments headers */ |
1147 | lowpan_process_data(skb); | 1143 | local_skb = skb_clone(skb, GFP_ATOMIC); |
1144 | if (!local_skb) | ||
1145 | goto drop; | ||
1146 | lowpan_process_data(local_skb); | ||
1147 | |||
1148 | kfree_skb(skb); | ||
1148 | break; | 1149 | break; |
1149 | default: | 1150 | default: |
1150 | break; | 1151 | break; |
@@ -1237,6 +1238,34 @@ static inline void __init lowpan_netlink_fini(void) | |||
1237 | rtnl_link_unregister(&lowpan_link_ops); | 1238 | rtnl_link_unregister(&lowpan_link_ops); |
1238 | } | 1239 | } |
1239 | 1240 | ||
1241 | static int lowpan_device_event(struct notifier_block *unused, | ||
1242 | unsigned long event, | ||
1243 | void *ptr) | ||
1244 | { | ||
1245 | struct net_device *dev = ptr; | ||
1246 | LIST_HEAD(del_list); | ||
1247 | struct lowpan_dev_record *entry, *tmp; | ||
1248 | |||
1249 | if (dev->type != ARPHRD_IEEE802154) | ||
1250 | goto out; | ||
1251 | |||
1252 | if (event == NETDEV_UNREGISTER) { | ||
1253 | list_for_each_entry_safe(entry, tmp, &lowpan_devices, list) { | ||
1254 | if (lowpan_dev_info(entry->ldev)->real_dev == dev) | ||
1255 | lowpan_dellink(entry->ldev, &del_list); | ||
1256 | } | ||
1257 | |||
1258 | unregister_netdevice_many(&del_list); | ||
1259 | }; | ||
1260 | |||
1261 | out: | ||
1262 | return NOTIFY_DONE; | ||
1263 | } | ||
1264 | |||
1265 | static struct notifier_block lowpan_dev_notifier = { | ||
1266 | .notifier_call = lowpan_device_event, | ||
1267 | }; | ||
1268 | |||
1240 | static struct packet_type lowpan_packet_type = { | 1269 | static struct packet_type lowpan_packet_type = { |
1241 | .type = __constant_htons(ETH_P_IEEE802154), | 1270 | .type = __constant_htons(ETH_P_IEEE802154), |
1242 | .func = lowpan_rcv, | 1271 | .func = lowpan_rcv, |
@@ -1251,6 +1280,12 @@ static int __init lowpan_init_module(void) | |||
1251 | goto out; | 1280 | goto out; |
1252 | 1281 | ||
1253 | dev_add_pack(&lowpan_packet_type); | 1282 | dev_add_pack(&lowpan_packet_type); |
1283 | |||
1284 | err = register_netdevice_notifier(&lowpan_dev_notifier); | ||
1285 | if (err < 0) { | ||
1286 | dev_remove_pack(&lowpan_packet_type); | ||
1287 | lowpan_netlink_fini(); | ||
1288 | } | ||
1254 | out: | 1289 | out: |
1255 | return err; | 1290 | return err; |
1256 | } | 1291 | } |
@@ -1263,6 +1298,8 @@ static void __exit lowpan_cleanup_module(void) | |||
1263 | 1298 | ||
1264 | dev_remove_pack(&lowpan_packet_type); | 1299 | dev_remove_pack(&lowpan_packet_type); |
1265 | 1300 | ||
1301 | unregister_netdevice_notifier(&lowpan_dev_notifier); | ||
1302 | |||
1266 | /* Now 6lowpan packet_type is removed, so no new fragments are | 1303 | /* Now 6lowpan packet_type is removed, so no new fragments are |
1267 | * expected on RX, therefore that's the time to clean incomplete | 1304 | * expected on RX, therefore that's the time to clean incomplete |
1268 | * fragments. | 1305 | * fragments. |
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index fe4582ca969a..4f70ef0b946d 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
@@ -149,6 +149,11 @@ void inet_sock_destruct(struct sock *sk) | |||
149 | pr_err("Attempt to release alive inet socket %p\n", sk); | 149 | pr_err("Attempt to release alive inet socket %p\n", sk); |
150 | return; | 150 | return; |
151 | } | 151 | } |
152 | if (sk->sk_type == SOCK_STREAM) { | ||
153 | struct fastopen_queue *fastopenq = | ||
154 | inet_csk(sk)->icsk_accept_queue.fastopenq; | ||
155 | kfree(fastopenq); | ||
156 | } | ||
152 | 157 | ||
153 | WARN_ON(atomic_read(&sk->sk_rmem_alloc)); | 158 | WARN_ON(atomic_read(&sk->sk_rmem_alloc)); |
154 | WARN_ON(atomic_read(&sk->sk_wmem_alloc)); | 159 | WARN_ON(atomic_read(&sk->sk_wmem_alloc)); |
@@ -212,6 +217,26 @@ int inet_listen(struct socket *sock, int backlog) | |||
212 | * we can only allow the backlog to be adjusted. | 217 | * we can only allow the backlog to be adjusted. |
213 | */ | 218 | */ |
214 | if (old_state != TCP_LISTEN) { | 219 | if (old_state != TCP_LISTEN) { |
220 | /* Check special setups for testing purpose to enable TFO w/o | ||
221 | * requiring TCP_FASTOPEN sockopt. | ||
222 | * Note that only TCP sockets (SOCK_STREAM) will reach here. | ||
223 | * Also fastopenq may already been allocated because this | ||
224 | * socket was in TCP_LISTEN state previously but was | ||
225 | * shutdown() (rather than close()). | ||
226 | */ | ||
227 | if ((sysctl_tcp_fastopen & TFO_SERVER_ENABLE) != 0 && | ||
228 | inet_csk(sk)->icsk_accept_queue.fastopenq == NULL) { | ||
229 | if ((sysctl_tcp_fastopen & TFO_SERVER_WO_SOCKOPT1) != 0) | ||
230 | err = fastopen_init_queue(sk, backlog); | ||
231 | else if ((sysctl_tcp_fastopen & | ||
232 | TFO_SERVER_WO_SOCKOPT2) != 0) | ||
233 | err = fastopen_init_queue(sk, | ||
234 | ((uint)sysctl_tcp_fastopen) >> 16); | ||
235 | else | ||
236 | err = 0; | ||
237 | if (err) | ||
238 | goto out; | ||
239 | } | ||
215 | err = inet_csk_listen_start(sk, backlog); | 240 | err = inet_csk_listen_start(sk, backlog); |
216 | if (err) | 241 | if (err) |
217 | goto out; | 242 | goto out; |
@@ -701,7 +726,8 @@ int inet_accept(struct socket *sock, struct socket *newsock, int flags) | |||
701 | 726 | ||
702 | sock_rps_record_flow(sk2); | 727 | sock_rps_record_flow(sk2); |
703 | WARN_ON(!((1 << sk2->sk_state) & | 728 | WARN_ON(!((1 << sk2->sk_state) & |
704 | (TCPF_ESTABLISHED | TCPF_CLOSE_WAIT | TCPF_CLOSE))); | 729 | (TCPF_ESTABLISHED | TCPF_SYN_RECV | |
730 | TCPF_CLOSE_WAIT | TCPF_CLOSE))); | ||
705 | 731 | ||
706 | sock_graft(sk2, newsock); | 732 | sock_graft(sk2, newsock); |
707 | 733 | ||
@@ -1364,7 +1390,7 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, | |||
1364 | if (*(u8 *)iph != 0x45) | 1390 | if (*(u8 *)iph != 0x45) |
1365 | goto out_unlock; | 1391 | goto out_unlock; |
1366 | 1392 | ||
1367 | if (unlikely(ip_fast_csum((u8 *)iph, iph->ihl))) | 1393 | if (unlikely(ip_fast_csum((u8 *)iph, 5))) |
1368 | goto out_unlock; | 1394 | goto out_unlock; |
1369 | 1395 | ||
1370 | id = ntohl(*(__be32 *)&iph->id); | 1396 | id = ntohl(*(__be32 *)&iph->id); |
@@ -1380,7 +1406,6 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, | |||
1380 | iph2 = ip_hdr(p); | 1406 | iph2 = ip_hdr(p); |
1381 | 1407 | ||
1382 | if ((iph->protocol ^ iph2->protocol) | | 1408 | if ((iph->protocol ^ iph2->protocol) | |
1383 | (iph->tos ^ iph2->tos) | | ||
1384 | ((__force u32)iph->saddr ^ (__force u32)iph2->saddr) | | 1409 | ((__force u32)iph->saddr ^ (__force u32)iph2->saddr) | |
1385 | ((__force u32)iph->daddr ^ (__force u32)iph2->daddr)) { | 1410 | ((__force u32)iph->daddr ^ (__force u32)iph2->daddr)) { |
1386 | NAPI_GRO_CB(p)->same_flow = 0; | 1411 | NAPI_GRO_CB(p)->same_flow = 0; |
@@ -1390,6 +1415,7 @@ static struct sk_buff **inet_gro_receive(struct sk_buff **head, | |||
1390 | /* All fields must match except length and checksum. */ | 1415 | /* All fields must match except length and checksum. */ |
1391 | NAPI_GRO_CB(p)->flush |= | 1416 | NAPI_GRO_CB(p)->flush |= |
1392 | (iph->ttl ^ iph2->ttl) | | 1417 | (iph->ttl ^ iph2->ttl) | |
1418 | (iph->tos ^ iph2->tos) | | ||
1393 | ((u16)(ntohs(iph2->id) + NAPI_GRO_CB(p)->count) ^ id); | 1419 | ((u16)(ntohs(iph2->id) + NAPI_GRO_CB(p)->count) ^ id); |
1394 | 1420 | ||
1395 | NAPI_GRO_CB(p)->flush |= flush; | 1421 | NAPI_GRO_CB(p)->flush |= flush; |
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 44bf82e3aef7..adf273f8ad2e 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c | |||
@@ -94,25 +94,22 @@ static const struct nla_policy ifa_ipv4_policy[IFA_MAX+1] = { | |||
94 | [IFA_LABEL] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, | 94 | [IFA_LABEL] = { .type = NLA_STRING, .len = IFNAMSIZ - 1 }, |
95 | }; | 95 | }; |
96 | 96 | ||
97 | /* inet_addr_hash's shifting is dependent upon this IN4_ADDR_HSIZE | 97 | #define IN4_ADDR_HSIZE_SHIFT 8 |
98 | * value. So if you change this define, make appropriate changes to | 98 | #define IN4_ADDR_HSIZE (1U << IN4_ADDR_HSIZE_SHIFT) |
99 | * inet_addr_hash as well. | 99 | |
100 | */ | ||
101 | #define IN4_ADDR_HSIZE 256 | ||
102 | static struct hlist_head inet_addr_lst[IN4_ADDR_HSIZE]; | 100 | static struct hlist_head inet_addr_lst[IN4_ADDR_HSIZE]; |
103 | static DEFINE_SPINLOCK(inet_addr_hash_lock); | 101 | static DEFINE_SPINLOCK(inet_addr_hash_lock); |
104 | 102 | ||
105 | static inline unsigned int inet_addr_hash(struct net *net, __be32 addr) | 103 | static u32 inet_addr_hash(struct net *net, __be32 addr) |
106 | { | 104 | { |
107 | u32 val = (__force u32) addr ^ hash_ptr(net, 8); | 105 | u32 val = (__force u32) addr ^ net_hash_mix(net); |
108 | 106 | ||
109 | return ((val ^ (val >> 8) ^ (val >> 16) ^ (val >> 24)) & | 107 | return hash_32(val, IN4_ADDR_HSIZE_SHIFT); |
110 | (IN4_ADDR_HSIZE - 1)); | ||
111 | } | 108 | } |
112 | 109 | ||
113 | static void inet_hash_insert(struct net *net, struct in_ifaddr *ifa) | 110 | static void inet_hash_insert(struct net *net, struct in_ifaddr *ifa) |
114 | { | 111 | { |
115 | unsigned int hash = inet_addr_hash(net, ifa->ifa_local); | 112 | u32 hash = inet_addr_hash(net, ifa->ifa_local); |
116 | 113 | ||
117 | spin_lock(&inet_addr_hash_lock); | 114 | spin_lock(&inet_addr_hash_lock); |
118 | hlist_add_head_rcu(&ifa->hash, &inet_addr_lst[hash]); | 115 | hlist_add_head_rcu(&ifa->hash, &inet_addr_lst[hash]); |
@@ -136,18 +133,18 @@ static void inet_hash_remove(struct in_ifaddr *ifa) | |||
136 | */ | 133 | */ |
137 | struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref) | 134 | struct net_device *__ip_dev_find(struct net *net, __be32 addr, bool devref) |
138 | { | 135 | { |
139 | unsigned int hash = inet_addr_hash(net, addr); | 136 | u32 hash = inet_addr_hash(net, addr); |
140 | struct net_device *result = NULL; | 137 | struct net_device *result = NULL; |
141 | struct in_ifaddr *ifa; | 138 | struct in_ifaddr *ifa; |
142 | struct hlist_node *node; | 139 | struct hlist_node *node; |
143 | 140 | ||
144 | rcu_read_lock(); | 141 | rcu_read_lock(); |
145 | hlist_for_each_entry_rcu(ifa, node, &inet_addr_lst[hash], hash) { | 142 | hlist_for_each_entry_rcu(ifa, node, &inet_addr_lst[hash], hash) { |
146 | struct net_device *dev = ifa->ifa_dev->dev; | ||
147 | |||
148 | if (!net_eq(dev_net(dev), net)) | ||
149 | continue; | ||
150 | if (ifa->ifa_local == addr) { | 143 | if (ifa->ifa_local == addr) { |
144 | struct net_device *dev = ifa->ifa_dev->dev; | ||
145 | |||
146 | if (!net_eq(dev_net(dev), net)) | ||
147 | continue; | ||
151 | result = dev; | 148 | result = dev; |
152 | break; | 149 | break; |
153 | } | 150 | } |
@@ -182,10 +179,10 @@ static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, | |||
182 | static void devinet_sysctl_register(struct in_device *idev); | 179 | static void devinet_sysctl_register(struct in_device *idev); |
183 | static void devinet_sysctl_unregister(struct in_device *idev); | 180 | static void devinet_sysctl_unregister(struct in_device *idev); |
184 | #else | 181 | #else |
185 | static inline void devinet_sysctl_register(struct in_device *idev) | 182 | static void devinet_sysctl_register(struct in_device *idev) |
186 | { | 183 | { |
187 | } | 184 | } |
188 | static inline void devinet_sysctl_unregister(struct in_device *idev) | 185 | static void devinet_sysctl_unregister(struct in_device *idev) |
189 | { | 186 | { |
190 | } | 187 | } |
191 | #endif | 188 | #endif |
@@ -205,7 +202,7 @@ static void inet_rcu_free_ifa(struct rcu_head *head) | |||
205 | kfree(ifa); | 202 | kfree(ifa); |
206 | } | 203 | } |
207 | 204 | ||
208 | static inline void inet_free_ifa(struct in_ifaddr *ifa) | 205 | static void inet_free_ifa(struct in_ifaddr *ifa) |
209 | { | 206 | { |
210 | call_rcu(&ifa->rcu_head, inet_rcu_free_ifa); | 207 | call_rcu(&ifa->rcu_head, inet_rcu_free_ifa); |
211 | } | 208 | } |
@@ -659,7 +656,7 @@ static int inet_rtm_newaddr(struct sk_buff *skb, struct nlmsghdr *nlh, void *arg | |||
659 | * Determine a default network mask, based on the IP address. | 656 | * Determine a default network mask, based on the IP address. |
660 | */ | 657 | */ |
661 | 658 | ||
662 | static inline int inet_abc_len(__be32 addr) | 659 | static int inet_abc_len(__be32 addr) |
663 | { | 660 | { |
664 | int rc = -1; /* Something else, probably a multicast. */ | 661 | int rc = -1; /* Something else, probably a multicast. */ |
665 | 662 | ||
@@ -1124,7 +1121,7 @@ skip: | |||
1124 | } | 1121 | } |
1125 | } | 1122 | } |
1126 | 1123 | ||
1127 | static inline bool inetdev_valid_mtu(unsigned int mtu) | 1124 | static bool inetdev_valid_mtu(unsigned int mtu) |
1128 | { | 1125 | { |
1129 | return mtu >= 68; | 1126 | return mtu >= 68; |
1130 | } | 1127 | } |
@@ -1239,7 +1236,7 @@ static struct notifier_block ip_netdev_notifier = { | |||
1239 | .notifier_call = inetdev_event, | 1236 | .notifier_call = inetdev_event, |
1240 | }; | 1237 | }; |
1241 | 1238 | ||
1242 | static inline size_t inet_nlmsg_size(void) | 1239 | static size_t inet_nlmsg_size(void) |
1243 | { | 1240 | { |
1244 | return NLMSG_ALIGN(sizeof(struct ifaddrmsg)) | 1241 | return NLMSG_ALIGN(sizeof(struct ifaddrmsg)) |
1245 | + nla_total_size(4) /* IFA_ADDRESS */ | 1242 | + nla_total_size(4) /* IFA_ADDRESS */ |
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index c43ae3fba792..acdee325d972 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
@@ -218,7 +218,7 @@ __be32 fib_compute_spec_dst(struct sk_buff *skb) | |||
218 | scope = RT_SCOPE_UNIVERSE; | 218 | scope = RT_SCOPE_UNIVERSE; |
219 | if (!ipv4_is_zeronet(ip_hdr(skb)->saddr)) { | 219 | if (!ipv4_is_zeronet(ip_hdr(skb)->saddr)) { |
220 | fl4.flowi4_oif = 0; | 220 | fl4.flowi4_oif = 0; |
221 | fl4.flowi4_iif = net->loopback_dev->ifindex; | 221 | fl4.flowi4_iif = LOOPBACK_IFINDEX; |
222 | fl4.daddr = ip_hdr(skb)->saddr; | 222 | fl4.daddr = ip_hdr(skb)->saddr; |
223 | fl4.saddr = 0; | 223 | fl4.saddr = 0; |
224 | fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos); | 224 | fl4.flowi4_tos = RT_TOS(ip_hdr(skb)->tos); |
@@ -1041,7 +1041,7 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event, | |||
1041 | static int fib_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) | 1041 | static int fib_netdev_event(struct notifier_block *this, unsigned long event, void *ptr) |
1042 | { | 1042 | { |
1043 | struct net_device *dev = ptr; | 1043 | struct net_device *dev = ptr; |
1044 | struct in_device *in_dev = __in_dev_get_rtnl(dev); | 1044 | struct in_device *in_dev; |
1045 | struct net *net = dev_net(dev); | 1045 | struct net *net = dev_net(dev); |
1046 | 1046 | ||
1047 | if (event == NETDEV_UNREGISTER) { | 1047 | if (event == NETDEV_UNREGISTER) { |
@@ -1050,8 +1050,7 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo | |||
1050 | return NOTIFY_DONE; | 1050 | return NOTIFY_DONE; |
1051 | } | 1051 | } |
1052 | 1052 | ||
1053 | if (!in_dev) | 1053 | in_dev = __in_dev_get_rtnl(dev); |
1054 | return NOTIFY_DONE; | ||
1055 | 1054 | ||
1056 | switch (event) { | 1055 | switch (event) { |
1057 | case NETDEV_UP: | 1056 | case NETDEV_UP: |
@@ -1062,16 +1061,14 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo | |||
1062 | fib_sync_up(dev); | 1061 | fib_sync_up(dev); |
1063 | #endif | 1062 | #endif |
1064 | atomic_inc(&net->ipv4.dev_addr_genid); | 1063 | atomic_inc(&net->ipv4.dev_addr_genid); |
1065 | rt_cache_flush(dev_net(dev), -1); | 1064 | rt_cache_flush(net, -1); |
1066 | break; | 1065 | break; |
1067 | case NETDEV_DOWN: | 1066 | case NETDEV_DOWN: |
1068 | fib_disable_ip(dev, 0, 0); | 1067 | fib_disable_ip(dev, 0, 0); |
1069 | break; | 1068 | break; |
1070 | case NETDEV_CHANGEMTU: | 1069 | case NETDEV_CHANGEMTU: |
1071 | case NETDEV_CHANGE: | 1070 | case NETDEV_CHANGE: |
1072 | rt_cache_flush(dev_net(dev), 0); | 1071 | rt_cache_flush(net, 0); |
1073 | break; | ||
1074 | case NETDEV_UNREGISTER_BATCH: | ||
1075 | break; | 1072 | break; |
1076 | } | 1073 | } |
1077 | return NOTIFY_DONE; | 1074 | return NOTIFY_DONE; |
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index f0cdb30921c0..3c820dae235e 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
@@ -367,7 +367,7 @@ static void __leaf_free_rcu(struct rcu_head *head) | |||
367 | 367 | ||
368 | static inline void free_leaf(struct leaf *l) | 368 | static inline void free_leaf(struct leaf *l) |
369 | { | 369 | { |
370 | call_rcu_bh(&l->rcu, __leaf_free_rcu); | 370 | call_rcu(&l->rcu, __leaf_free_rcu); |
371 | } | 371 | } |
372 | 372 | ||
373 | static inline void free_leaf_info(struct leaf_info *leaf) | 373 | static inline void free_leaf_info(struct leaf_info *leaf) |
@@ -1550,7 +1550,8 @@ int fib_table_lookup(struct fib_table *tb, const struct flowi4 *flp, | |||
1550 | * state.directly. | 1550 | * state.directly. |
1551 | */ | 1551 | */ |
1552 | if (pref_mismatch) { | 1552 | if (pref_mismatch) { |
1553 | int mp = KEYLENGTH - fls(pref_mismatch); | 1553 | /* fls(x) = __fls(x) + 1 */ |
1554 | int mp = KEYLENGTH - __fls(pref_mismatch) - 1; | ||
1554 | 1555 | ||
1555 | if (tkey_extract_bits(cn->key, mp, cn->pos - mp) != 0) | 1556 | if (tkey_extract_bits(cn->key, mp, cn->pos - mp) != 0) |
1556 | goto backtrace; | 1557 | goto backtrace; |
@@ -1655,7 +1656,12 @@ int fib_table_delete(struct fib_table *tb, struct fib_config *cfg) | |||
1655 | if (!l) | 1656 | if (!l) |
1656 | return -ESRCH; | 1657 | return -ESRCH; |
1657 | 1658 | ||
1658 | fa_head = get_fa_head(l, plen); | 1659 | li = find_leaf_info(l, plen); |
1660 | |||
1661 | if (!li) | ||
1662 | return -ESRCH; | ||
1663 | |||
1664 | fa_head = &li->falh; | ||
1659 | fa = fib_find_alias(fa_head, tos, 0); | 1665 | fa = fib_find_alias(fa_head, tos, 0); |
1660 | 1666 | ||
1661 | if (!fa) | 1667 | if (!fa) |
@@ -1691,9 +1697,6 @@ int fib_table_delete(struct fib_table *tb, struct fib_config *cfg) | |||
1691 | rtmsg_fib(RTM_DELROUTE, htonl(key), fa, plen, tb->tb_id, | 1697 | rtmsg_fib(RTM_DELROUTE, htonl(key), fa, plen, tb->tb_id, |
1692 | &cfg->fc_nlinfo, 0); | 1698 | &cfg->fc_nlinfo, 0); |
1693 | 1699 | ||
1694 | l = fib_find_node(t, key); | ||
1695 | li = find_leaf_info(l, plen); | ||
1696 | |||
1697 | list_del_rcu(&fa->fa_list); | 1700 | list_del_rcu(&fa->fa_list); |
1698 | 1701 | ||
1699 | if (!plen) | 1702 | if (!plen) |
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index 6699f23e6f55..0b5580c69f2d 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c | |||
@@ -2435,6 +2435,8 @@ static int igmp_mc_seq_show(struct seq_file *seq, void *v) | |||
2435 | struct ip_mc_list *im = (struct ip_mc_list *)v; | 2435 | struct ip_mc_list *im = (struct ip_mc_list *)v; |
2436 | struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq); | 2436 | struct igmp_mc_iter_state *state = igmp_mc_seq_private(seq); |
2437 | char *querier; | 2437 | char *querier; |
2438 | long delta; | ||
2439 | |||
2438 | #ifdef CONFIG_IP_MULTICAST | 2440 | #ifdef CONFIG_IP_MULTICAST |
2439 | querier = IGMP_V1_SEEN(state->in_dev) ? "V1" : | 2441 | querier = IGMP_V1_SEEN(state->in_dev) ? "V1" : |
2440 | IGMP_V2_SEEN(state->in_dev) ? "V2" : | 2442 | IGMP_V2_SEEN(state->in_dev) ? "V2" : |
@@ -2448,11 +2450,12 @@ static int igmp_mc_seq_show(struct seq_file *seq, void *v) | |||
2448 | state->dev->ifindex, state->dev->name, state->in_dev->mc_count, querier); | 2450 | state->dev->ifindex, state->dev->name, state->in_dev->mc_count, querier); |
2449 | } | 2451 | } |
2450 | 2452 | ||
2453 | delta = im->timer.expires - jiffies; | ||
2451 | seq_printf(seq, | 2454 | seq_printf(seq, |
2452 | "\t\t\t\t%08X %5d %d:%08lX\t\t%d\n", | 2455 | "\t\t\t\t%08X %5d %d:%08lX\t\t%d\n", |
2453 | im->multiaddr, im->users, | 2456 | im->multiaddr, im->users, |
2454 | im->tm_running, im->tm_running ? | 2457 | im->tm_running, |
2455 | jiffies_to_clock_t(im->timer.expires-jiffies) : 0, | 2458 | im->tm_running ? jiffies_delta_to_clock_t(delta) : 0, |
2456 | im->reporter); | 2459 | im->reporter); |
2457 | } | 2460 | } |
2458 | return 0; | 2461 | return 0; |
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index db0cf17c00f7..8464b79c493f 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c | |||
@@ -283,7 +283,9 @@ static int inet_csk_wait_for_connect(struct sock *sk, long timeo) | |||
283 | struct sock *inet_csk_accept(struct sock *sk, int flags, int *err) | 283 | struct sock *inet_csk_accept(struct sock *sk, int flags, int *err) |
284 | { | 284 | { |
285 | struct inet_connection_sock *icsk = inet_csk(sk); | 285 | struct inet_connection_sock *icsk = inet_csk(sk); |
286 | struct request_sock_queue *queue = &icsk->icsk_accept_queue; | ||
286 | struct sock *newsk; | 287 | struct sock *newsk; |
288 | struct request_sock *req; | ||
287 | int error; | 289 | int error; |
288 | 290 | ||
289 | lock_sock(sk); | 291 | lock_sock(sk); |
@@ -296,7 +298,7 @@ struct sock *inet_csk_accept(struct sock *sk, int flags, int *err) | |||
296 | goto out_err; | 298 | goto out_err; |
297 | 299 | ||
298 | /* Find already established connection */ | 300 | /* Find already established connection */ |
299 | if (reqsk_queue_empty(&icsk->icsk_accept_queue)) { | 301 | if (reqsk_queue_empty(queue)) { |
300 | long timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); | 302 | long timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); |
301 | 303 | ||
302 | /* If this is a non blocking socket don't sleep */ | 304 | /* If this is a non blocking socket don't sleep */ |
@@ -308,14 +310,32 @@ struct sock *inet_csk_accept(struct sock *sk, int flags, int *err) | |||
308 | if (error) | 310 | if (error) |
309 | goto out_err; | 311 | goto out_err; |
310 | } | 312 | } |
311 | 313 | req = reqsk_queue_remove(queue); | |
312 | newsk = reqsk_queue_get_child(&icsk->icsk_accept_queue, sk); | 314 | newsk = req->sk; |
313 | WARN_ON(newsk->sk_state == TCP_SYN_RECV); | 315 | |
316 | sk_acceptq_removed(sk); | ||
317 | if (sk->sk_type == SOCK_STREAM && queue->fastopenq != NULL) { | ||
318 | spin_lock_bh(&queue->fastopenq->lock); | ||
319 | if (tcp_rsk(req)->listener) { | ||
320 | /* We are still waiting for the final ACK from 3WHS | ||
321 | * so can't free req now. Instead, we set req->sk to | ||
322 | * NULL to signify that the child socket is taken | ||
323 | * so reqsk_fastopen_remove() will free the req | ||
324 | * when 3WHS finishes (or is aborted). | ||
325 | */ | ||
326 | req->sk = NULL; | ||
327 | req = NULL; | ||
328 | } | ||
329 | spin_unlock_bh(&queue->fastopenq->lock); | ||
330 | } | ||
314 | out: | 331 | out: |
315 | release_sock(sk); | 332 | release_sock(sk); |
333 | if (req) | ||
334 | __reqsk_free(req); | ||
316 | return newsk; | 335 | return newsk; |
317 | out_err: | 336 | out_err: |
318 | newsk = NULL; | 337 | newsk = NULL; |
338 | req = NULL; | ||
319 | *err = error; | 339 | *err = error; |
320 | goto out; | 340 | goto out; |
321 | } | 341 | } |
@@ -404,12 +424,15 @@ struct dst_entry *inet_csk_route_child_sock(struct sock *sk, | |||
404 | { | 424 | { |
405 | const struct inet_request_sock *ireq = inet_rsk(req); | 425 | const struct inet_request_sock *ireq = inet_rsk(req); |
406 | struct inet_sock *newinet = inet_sk(newsk); | 426 | struct inet_sock *newinet = inet_sk(newsk); |
407 | struct ip_options_rcu *opt = ireq->opt; | 427 | struct ip_options_rcu *opt; |
408 | struct net *net = sock_net(sk); | 428 | struct net *net = sock_net(sk); |
409 | struct flowi4 *fl4; | 429 | struct flowi4 *fl4; |
410 | struct rtable *rt; | 430 | struct rtable *rt; |
411 | 431 | ||
412 | fl4 = &newinet->cork.fl.u.ip4; | 432 | fl4 = &newinet->cork.fl.u.ip4; |
433 | |||
434 | rcu_read_lock(); | ||
435 | opt = rcu_dereference(newinet->inet_opt); | ||
413 | flowi4_init_output(fl4, sk->sk_bound_dev_if, sk->sk_mark, | 436 | flowi4_init_output(fl4, sk->sk_bound_dev_if, sk->sk_mark, |
414 | RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, | 437 | RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE, |
415 | sk->sk_protocol, inet_sk_flowi_flags(sk), | 438 | sk->sk_protocol, inet_sk_flowi_flags(sk), |
@@ -421,11 +444,13 @@ struct dst_entry *inet_csk_route_child_sock(struct sock *sk, | |||
421 | goto no_route; | 444 | goto no_route; |
422 | if (opt && opt->opt.is_strictroute && rt->rt_gateway) | 445 | if (opt && opt->opt.is_strictroute && rt->rt_gateway) |
423 | goto route_err; | 446 | goto route_err; |
447 | rcu_read_unlock(); | ||
424 | return &rt->dst; | 448 | return &rt->dst; |
425 | 449 | ||
426 | route_err: | 450 | route_err: |
427 | ip_rt_put(rt); | 451 | ip_rt_put(rt); |
428 | no_route: | 452 | no_route: |
453 | rcu_read_unlock(); | ||
429 | IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES); | 454 | IP_INC_STATS_BH(net, IPSTATS_MIB_OUTNOROUTES); |
430 | return NULL; | 455 | return NULL; |
431 | } | 456 | } |
@@ -715,13 +740,14 @@ EXPORT_SYMBOL_GPL(inet_csk_listen_start); | |||
715 | void inet_csk_listen_stop(struct sock *sk) | 740 | void inet_csk_listen_stop(struct sock *sk) |
716 | { | 741 | { |
717 | struct inet_connection_sock *icsk = inet_csk(sk); | 742 | struct inet_connection_sock *icsk = inet_csk(sk); |
743 | struct request_sock_queue *queue = &icsk->icsk_accept_queue; | ||
718 | struct request_sock *acc_req; | 744 | struct request_sock *acc_req; |
719 | struct request_sock *req; | 745 | struct request_sock *req; |
720 | 746 | ||
721 | inet_csk_delete_keepalive_timer(sk); | 747 | inet_csk_delete_keepalive_timer(sk); |
722 | 748 | ||
723 | /* make all the listen_opt local to us */ | 749 | /* make all the listen_opt local to us */ |
724 | acc_req = reqsk_queue_yank_acceptq(&icsk->icsk_accept_queue); | 750 | acc_req = reqsk_queue_yank_acceptq(queue); |
725 | 751 | ||
726 | /* Following specs, it would be better either to send FIN | 752 | /* Following specs, it would be better either to send FIN |
727 | * (and enter FIN-WAIT-1, it is normal close) | 753 | * (and enter FIN-WAIT-1, it is normal close) |
@@ -731,7 +757,7 @@ void inet_csk_listen_stop(struct sock *sk) | |||
731 | * To be honest, we are not able to make either | 757 | * To be honest, we are not able to make either |
732 | * of the variants now. --ANK | 758 | * of the variants now. --ANK |
733 | */ | 759 | */ |
734 | reqsk_queue_destroy(&icsk->icsk_accept_queue); | 760 | reqsk_queue_destroy(queue); |
735 | 761 | ||
736 | while ((req = acc_req) != NULL) { | 762 | while ((req = acc_req) != NULL) { |
737 | struct sock *child = req->sk; | 763 | struct sock *child = req->sk; |
@@ -749,6 +775,19 @@ void inet_csk_listen_stop(struct sock *sk) | |||
749 | 775 | ||
750 | percpu_counter_inc(sk->sk_prot->orphan_count); | 776 | percpu_counter_inc(sk->sk_prot->orphan_count); |
751 | 777 | ||
778 | if (sk->sk_type == SOCK_STREAM && tcp_rsk(req)->listener) { | ||
779 | BUG_ON(tcp_sk(child)->fastopen_rsk != req); | ||
780 | BUG_ON(sk != tcp_rsk(req)->listener); | ||
781 | |||
782 | /* Paranoid, to prevent race condition if | ||
783 | * an inbound pkt destined for child is | ||
784 | * blocked by sock lock in tcp_v4_rcv(). | ||
785 | * Also to satisfy an assertion in | ||
786 | * tcp_v4_destroy_sock(). | ||
787 | */ | ||
788 | tcp_sk(child)->fastopen_rsk = NULL; | ||
789 | sock_put(sk); | ||
790 | } | ||
752 | inet_csk_destroy_sock(child); | 791 | inet_csk_destroy_sock(child); |
753 | 792 | ||
754 | bh_unlock_sock(child); | 793 | bh_unlock_sock(child); |
@@ -758,6 +797,17 @@ void inet_csk_listen_stop(struct sock *sk) | |||
758 | sk_acceptq_removed(sk); | 797 | sk_acceptq_removed(sk); |
759 | __reqsk_free(req); | 798 | __reqsk_free(req); |
760 | } | 799 | } |
800 | if (queue->fastopenq != NULL) { | ||
801 | /* Free all the reqs queued in rskq_rst_head. */ | ||
802 | spin_lock_bh(&queue->fastopenq->lock); | ||
803 | acc_req = queue->fastopenq->rskq_rst_head; | ||
804 | queue->fastopenq->rskq_rst_head = NULL; | ||
805 | spin_unlock_bh(&queue->fastopenq->lock); | ||
806 | while ((req = acc_req) != NULL) { | ||
807 | acc_req = req->dl_next; | ||
808 | __reqsk_free(req); | ||
809 | } | ||
810 | } | ||
761 | WARN_ON(sk->sk_ack_backlog); | 811 | WARN_ON(sk->sk_ack_backlog); |
762 | } | 812 | } |
763 | EXPORT_SYMBOL_GPL(inet_csk_listen_stop); | 813 | EXPORT_SYMBOL_GPL(inet_csk_listen_stop); |
diff --git a/net/ipv4/inet_diag.c b/net/ipv4/inet_diag.c index 570e61f9611f..8bc005b1435f 100644 --- a/net/ipv4/inet_diag.c +++ b/net/ipv4/inet_diag.c | |||
@@ -69,6 +69,7 @@ static inline void inet_diag_unlock_handler( | |||
69 | 69 | ||
70 | int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, | 70 | int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, |
71 | struct sk_buff *skb, struct inet_diag_req_v2 *req, | 71 | struct sk_buff *skb, struct inet_diag_req_v2 *req, |
72 | struct user_namespace *user_ns, | ||
72 | u32 pid, u32 seq, u16 nlmsg_flags, | 73 | u32 pid, u32 seq, u16 nlmsg_flags, |
73 | const struct nlmsghdr *unlh) | 74 | const struct nlmsghdr *unlh) |
74 | { | 75 | { |
@@ -124,7 +125,7 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk, | |||
124 | } | 125 | } |
125 | #endif | 126 | #endif |
126 | 127 | ||
127 | r->idiag_uid = sock_i_uid(sk); | 128 | r->idiag_uid = from_kuid_munged(user_ns, sock_i_uid(sk)); |
128 | r->idiag_inode = sock_i_ino(sk); | 129 | r->idiag_inode = sock_i_ino(sk); |
129 | 130 | ||
130 | if (ext & (1 << (INET_DIAG_MEMINFO - 1))) { | 131 | if (ext & (1 << (INET_DIAG_MEMINFO - 1))) { |
@@ -199,11 +200,12 @@ EXPORT_SYMBOL_GPL(inet_sk_diag_fill); | |||
199 | 200 | ||
200 | static int inet_csk_diag_fill(struct sock *sk, | 201 | static int inet_csk_diag_fill(struct sock *sk, |
201 | struct sk_buff *skb, struct inet_diag_req_v2 *req, | 202 | struct sk_buff *skb, struct inet_diag_req_v2 *req, |
203 | struct user_namespace *user_ns, | ||
202 | u32 pid, u32 seq, u16 nlmsg_flags, | 204 | u32 pid, u32 seq, u16 nlmsg_flags, |
203 | const struct nlmsghdr *unlh) | 205 | const struct nlmsghdr *unlh) |
204 | { | 206 | { |
205 | return inet_sk_diag_fill(sk, inet_csk(sk), | 207 | return inet_sk_diag_fill(sk, inet_csk(sk), |
206 | skb, req, pid, seq, nlmsg_flags, unlh); | 208 | skb, req, user_ns, pid, seq, nlmsg_flags, unlh); |
207 | } | 209 | } |
208 | 210 | ||
209 | static int inet_twsk_diag_fill(struct inet_timewait_sock *tw, | 211 | static int inet_twsk_diag_fill(struct inet_timewait_sock *tw, |
@@ -256,14 +258,16 @@ static int inet_twsk_diag_fill(struct inet_timewait_sock *tw, | |||
256 | } | 258 | } |
257 | 259 | ||
258 | static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, | 260 | static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, |
259 | struct inet_diag_req_v2 *r, u32 pid, u32 seq, u16 nlmsg_flags, | 261 | struct inet_diag_req_v2 *r, |
262 | struct user_namespace *user_ns, | ||
263 | u32 pid, u32 seq, u16 nlmsg_flags, | ||
260 | const struct nlmsghdr *unlh) | 264 | const struct nlmsghdr *unlh) |
261 | { | 265 | { |
262 | if (sk->sk_state == TCP_TIME_WAIT) | 266 | if (sk->sk_state == TCP_TIME_WAIT) |
263 | return inet_twsk_diag_fill((struct inet_timewait_sock *)sk, | 267 | return inet_twsk_diag_fill((struct inet_timewait_sock *)sk, |
264 | skb, r, pid, seq, nlmsg_flags, | 268 | skb, r, pid, seq, nlmsg_flags, |
265 | unlh); | 269 | unlh); |
266 | return inet_csk_diag_fill(sk, skb, r, pid, seq, nlmsg_flags, unlh); | 270 | return inet_csk_diag_fill(sk, skb, r, user_ns, pid, seq, nlmsg_flags, unlh); |
267 | } | 271 | } |
268 | 272 | ||
269 | int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_skb, | 273 | int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_skb, |
@@ -311,6 +315,7 @@ int inet_diag_dump_one_icsk(struct inet_hashinfo *hashinfo, struct sk_buff *in_s | |||
311 | } | 315 | } |
312 | 316 | ||
313 | err = sk_diag_fill(sk, rep, req, | 317 | err = sk_diag_fill(sk, rep, req, |
318 | sk_user_ns(NETLINK_CB(in_skb).ssk), | ||
314 | NETLINK_CB(in_skb).pid, | 319 | NETLINK_CB(in_skb).pid, |
315 | nlh->nlmsg_seq, 0, nlh); | 320 | nlh->nlmsg_seq, 0, nlh); |
316 | if (err < 0) { | 321 | if (err < 0) { |
@@ -551,6 +556,7 @@ static int inet_csk_diag_dump(struct sock *sk, | |||
551 | return 0; | 556 | return 0; |
552 | 557 | ||
553 | return inet_csk_diag_fill(sk, skb, r, | 558 | return inet_csk_diag_fill(sk, skb, r, |
559 | sk_user_ns(NETLINK_CB(cb->skb).ssk), | ||
554 | NETLINK_CB(cb->skb).pid, | 560 | NETLINK_CB(cb->skb).pid, |
555 | cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); | 561 | cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); |
556 | } | 562 | } |
@@ -591,7 +597,9 @@ static int inet_twsk_diag_dump(struct inet_timewait_sock *tw, | |||
591 | } | 597 | } |
592 | 598 | ||
593 | static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk, | 599 | static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk, |
594 | struct request_sock *req, u32 pid, u32 seq, | 600 | struct request_sock *req, |
601 | struct user_namespace *user_ns, | ||
602 | u32 pid, u32 seq, | ||
595 | const struct nlmsghdr *unlh) | 603 | const struct nlmsghdr *unlh) |
596 | { | 604 | { |
597 | const struct inet_request_sock *ireq = inet_rsk(req); | 605 | const struct inet_request_sock *ireq = inet_rsk(req); |
@@ -625,7 +633,7 @@ static int inet_diag_fill_req(struct sk_buff *skb, struct sock *sk, | |||
625 | r->idiag_expires = jiffies_to_msecs(tmo); | 633 | r->idiag_expires = jiffies_to_msecs(tmo); |
626 | r->idiag_rqueue = 0; | 634 | r->idiag_rqueue = 0; |
627 | r->idiag_wqueue = 0; | 635 | r->idiag_wqueue = 0; |
628 | r->idiag_uid = sock_i_uid(sk); | 636 | r->idiag_uid = from_kuid_munged(user_ns, sock_i_uid(sk)); |
629 | r->idiag_inode = 0; | 637 | r->idiag_inode = 0; |
630 | #if IS_ENABLED(CONFIG_IPV6) | 638 | #if IS_ENABLED(CONFIG_IPV6) |
631 | if (r->idiag_family == AF_INET6) { | 639 | if (r->idiag_family == AF_INET6) { |
@@ -702,6 +710,7 @@ static int inet_diag_dump_reqs(struct sk_buff *skb, struct sock *sk, | |||
702 | } | 710 | } |
703 | 711 | ||
704 | err = inet_diag_fill_req(skb, sk, req, | 712 | err = inet_diag_fill_req(skb, sk, req, |
713 | sk_user_ns(NETLINK_CB(cb->skb).ssk), | ||
705 | NETLINK_CB(cb->skb).pid, | 714 | NETLINK_CB(cb->skb).pid, |
706 | cb->nlh->nlmsg_seq, cb->nlh); | 715 | cb->nlh->nlmsg_seq, cb->nlh); |
707 | if (err < 0) { | 716 | if (err < 0) { |
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index 8d07c973409c..fa6a12c51066 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
@@ -523,6 +523,10 @@ found: | |||
523 | if (offset == 0) | 523 | if (offset == 0) |
524 | qp->q.last_in |= INET_FRAG_FIRST_IN; | 524 | qp->q.last_in |= INET_FRAG_FIRST_IN; |
525 | 525 | ||
526 | if (ip_hdr(skb)->frag_off & htons(IP_DF) && | ||
527 | skb->len + ihl > qp->q.max_size) | ||
528 | qp->q.max_size = skb->len + ihl; | ||
529 | |||
526 | if (qp->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && | 530 | if (qp->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && |
527 | qp->q.meat == qp->q.len) | 531 | qp->q.meat == qp->q.len) |
528 | return ip_frag_reasm(qp, prev, dev); | 532 | return ip_frag_reasm(qp, prev, dev); |
@@ -646,9 +650,11 @@ static int ip_frag_reasm(struct ipq *qp, struct sk_buff *prev, | |||
646 | head->next = NULL; | 650 | head->next = NULL; |
647 | head->dev = dev; | 651 | head->dev = dev; |
648 | head->tstamp = qp->q.stamp; | 652 | head->tstamp = qp->q.stamp; |
653 | IPCB(head)->frag_max_size = qp->q.max_size; | ||
649 | 654 | ||
650 | iph = ip_hdr(head); | 655 | iph = ip_hdr(head); |
651 | iph->frag_off = 0; | 656 | /* max_size != 0 implies at least one fragment had IP_DF set */ |
657 | iph->frag_off = qp->q.max_size ? htons(IP_DF) : 0; | ||
652 | iph->tot_len = htons(len); | 658 | iph->tot_len = htons(len); |
653 | iph->tos |= ecn; | 659 | iph->tos |= ecn; |
654 | IP_INC_STATS_BH(net, IPSTATS_MIB_REASMOKS); | 660 | IP_INC_STATS_BH(net, IPSTATS_MIB_REASMOKS); |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index ba39a52d18c1..a5beab1dc958 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -197,7 +197,7 @@ static inline int ip_finish_output2(struct sk_buff *skb) | |||
197 | neigh = __ipv4_neigh_lookup_noref(dev, nexthop); | 197 | neigh = __ipv4_neigh_lookup_noref(dev, nexthop); |
198 | if (unlikely(!neigh)) | 198 | if (unlikely(!neigh)) |
199 | neigh = __neigh_create(&arp_tbl, &nexthop, dev, false); | 199 | neigh = __neigh_create(&arp_tbl, &nexthop, dev, false); |
200 | if (neigh) { | 200 | if (!IS_ERR(neigh)) { |
201 | int res = dst_neigh_output(dst, neigh, skb); | 201 | int res = dst_neigh_output(dst, neigh, skb); |
202 | 202 | ||
203 | rcu_read_unlock_bh(); | 203 | rcu_read_unlock_bh(); |
@@ -467,7 +467,9 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
467 | 467 | ||
468 | iph = ip_hdr(skb); | 468 | iph = ip_hdr(skb); |
469 | 469 | ||
470 | if (unlikely((iph->frag_off & htons(IP_DF)) && !skb->local_df)) { | 470 | if (unlikely(((iph->frag_off & htons(IP_DF)) && !skb->local_df) || |
471 | (IPCB(skb)->frag_max_size && | ||
472 | IPCB(skb)->frag_max_size > dst_mtu(&rt->dst)))) { | ||
471 | IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGFAILS); | 473 | IP_INC_STATS(dev_net(dev), IPSTATS_MIB_FRAGFAILS); |
472 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, | 474 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, |
473 | htonl(ip_skb_dst_mtu(skb))); | 475 | htonl(ip_skb_dst_mtu(skb))); |
@@ -1338,10 +1340,10 @@ struct sk_buff *__ip_make_skb(struct sock *sk, | |||
1338 | iph->ihl = 5; | 1340 | iph->ihl = 5; |
1339 | iph->tos = inet->tos; | 1341 | iph->tos = inet->tos; |
1340 | iph->frag_off = df; | 1342 | iph->frag_off = df; |
1341 | ip_select_ident(iph, &rt->dst, sk); | ||
1342 | iph->ttl = ttl; | 1343 | iph->ttl = ttl; |
1343 | iph->protocol = sk->sk_protocol; | 1344 | iph->protocol = sk->sk_protocol; |
1344 | ip_copy_addrs(iph, fl4); | 1345 | ip_copy_addrs(iph, fl4); |
1346 | ip_select_ident(iph, &rt->dst, sk); | ||
1345 | 1347 | ||
1346 | if (opt) { | 1348 | if (opt) { |
1347 | iph->ihl += opt->optlen>>2; | 1349 | iph->ihl += opt->optlen>>2; |
@@ -1366,9 +1368,8 @@ out: | |||
1366 | return skb; | 1368 | return skb; |
1367 | } | 1369 | } |
1368 | 1370 | ||
1369 | int ip_send_skb(struct sk_buff *skb) | 1371 | int ip_send_skb(struct net *net, struct sk_buff *skb) |
1370 | { | 1372 | { |
1371 | struct net *net = sock_net(skb->sk); | ||
1372 | int err; | 1373 | int err; |
1373 | 1374 | ||
1374 | err = ip_local_out(skb); | 1375 | err = ip_local_out(skb); |
@@ -1391,7 +1392,7 @@ int ip_push_pending_frames(struct sock *sk, struct flowi4 *fl4) | |||
1391 | return 0; | 1392 | return 0; |
1392 | 1393 | ||
1393 | /* Netfilter gets whole the not fragmented skb. */ | 1394 | /* Netfilter gets whole the not fragmented skb. */ |
1394 | return ip_send_skb(skb); | 1395 | return ip_send_skb(sock_net(sk), skb); |
1395 | } | 1396 | } |
1396 | 1397 | ||
1397 | /* | 1398 | /* |
@@ -1536,6 +1537,7 @@ void ip_send_unicast_reply(struct net *net, struct sk_buff *skb, __be32 daddr, | |||
1536 | arg->csumoffset) = csum_fold(csum_add(nskb->csum, | 1537 | arg->csumoffset) = csum_fold(csum_add(nskb->csum, |
1537 | arg->csum)); | 1538 | arg->csum)); |
1538 | nskb->ip_summed = CHECKSUM_NONE; | 1539 | nskb->ip_summed = CHECKSUM_NONE; |
1540 | skb_orphan(nskb); | ||
1539 | skb_set_queue_mapping(nskb, skb_get_queue_mapping(skb)); | 1541 | skb_set_queue_mapping(nskb, skb_get_queue_mapping(skb)); |
1540 | ip_push_pending_frames(sk, &fl4); | 1542 | ip_push_pending_frames(sk, &fl4); |
1541 | } | 1543 | } |
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 8eec8f4a0536..8aa7a4cf9139 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c | |||
@@ -124,6 +124,8 @@ static DEFINE_SPINLOCK(mfc_unres_lock); | |||
124 | static struct kmem_cache *mrt_cachep __read_mostly; | 124 | static struct kmem_cache *mrt_cachep __read_mostly; |
125 | 125 | ||
126 | static struct mr_table *ipmr_new_table(struct net *net, u32 id); | 126 | static struct mr_table *ipmr_new_table(struct net *net, u32 id); |
127 | static void ipmr_free_table(struct mr_table *mrt); | ||
128 | |||
127 | static int ip_mr_forward(struct net *net, struct mr_table *mrt, | 129 | static int ip_mr_forward(struct net *net, struct mr_table *mrt, |
128 | struct sk_buff *skb, struct mfc_cache *cache, | 130 | struct sk_buff *skb, struct mfc_cache *cache, |
129 | int local); | 131 | int local); |
@@ -131,6 +133,7 @@ static int ipmr_cache_report(struct mr_table *mrt, | |||
131 | struct sk_buff *pkt, vifi_t vifi, int assert); | 133 | struct sk_buff *pkt, vifi_t vifi, int assert); |
132 | static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, | 134 | static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb, |
133 | struct mfc_cache *c, struct rtmsg *rtm); | 135 | struct mfc_cache *c, struct rtmsg *rtm); |
136 | static void mroute_clean_tables(struct mr_table *mrt); | ||
134 | static void ipmr_expire_process(unsigned long arg); | 137 | static void ipmr_expire_process(unsigned long arg); |
135 | 138 | ||
136 | #ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES | 139 | #ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES |
@@ -271,7 +274,7 @@ static void __net_exit ipmr_rules_exit(struct net *net) | |||
271 | 274 | ||
272 | list_for_each_entry_safe(mrt, next, &net->ipv4.mr_tables, list) { | 275 | list_for_each_entry_safe(mrt, next, &net->ipv4.mr_tables, list) { |
273 | list_del(&mrt->list); | 276 | list_del(&mrt->list); |
274 | kfree(mrt); | 277 | ipmr_free_table(mrt); |
275 | } | 278 | } |
276 | fib_rules_unregister(net->ipv4.mr_rules_ops); | 279 | fib_rules_unregister(net->ipv4.mr_rules_ops); |
277 | } | 280 | } |
@@ -299,7 +302,7 @@ static int __net_init ipmr_rules_init(struct net *net) | |||
299 | 302 | ||
300 | static void __net_exit ipmr_rules_exit(struct net *net) | 303 | static void __net_exit ipmr_rules_exit(struct net *net) |
301 | { | 304 | { |
302 | kfree(net->ipv4.mrt); | 305 | ipmr_free_table(net->ipv4.mrt); |
303 | } | 306 | } |
304 | #endif | 307 | #endif |
305 | 308 | ||
@@ -336,6 +339,13 @@ static struct mr_table *ipmr_new_table(struct net *net, u32 id) | |||
336 | return mrt; | 339 | return mrt; |
337 | } | 340 | } |
338 | 341 | ||
342 | static void ipmr_free_table(struct mr_table *mrt) | ||
343 | { | ||
344 | del_timer_sync(&mrt->ipmr_expire_timer); | ||
345 | mroute_clean_tables(mrt); | ||
346 | kfree(mrt); | ||
347 | } | ||
348 | |||
339 | /* Service routines creating virtual interfaces: DVMRP tunnels and PIMREG */ | 349 | /* Service routines creating virtual interfaces: DVMRP tunnels and PIMREG */ |
340 | 350 | ||
341 | static void ipmr_del_tunnel(struct net_device *dev, struct vifctl *v) | 351 | static void ipmr_del_tunnel(struct net_device *dev, struct vifctl *v) |
@@ -1798,7 +1808,7 @@ static struct mr_table *ipmr_rt_fib_lookup(struct net *net, struct sk_buff *skb) | |||
1798 | .flowi4_oif = (rt_is_output_route(rt) ? | 1808 | .flowi4_oif = (rt_is_output_route(rt) ? |
1799 | skb->dev->ifindex : 0), | 1809 | skb->dev->ifindex : 0), |
1800 | .flowi4_iif = (rt_is_output_route(rt) ? | 1810 | .flowi4_iif = (rt_is_output_route(rt) ? |
1801 | net->loopback_dev->ifindex : | 1811 | LOOPBACK_IFINDEX : |
1802 | skb->dev->ifindex), | 1812 | skb->dev->ifindex), |
1803 | .flowi4_mark = skb->mark, | 1813 | .flowi4_mark = skb->mark, |
1804 | }; | 1814 | }; |
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index ed1b36783192..4c0cf63dd92e 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c | |||
@@ -72,43 +72,6 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned int addr_type) | |||
72 | } | 72 | } |
73 | EXPORT_SYMBOL(ip_route_me_harder); | 73 | EXPORT_SYMBOL(ip_route_me_harder); |
74 | 74 | ||
75 | #ifdef CONFIG_XFRM | ||
76 | int ip_xfrm_me_harder(struct sk_buff *skb) | ||
77 | { | ||
78 | struct flowi fl; | ||
79 | unsigned int hh_len; | ||
80 | struct dst_entry *dst; | ||
81 | |||
82 | if (IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) | ||
83 | return 0; | ||
84 | if (xfrm_decode_session(skb, &fl, AF_INET) < 0) | ||
85 | return -1; | ||
86 | |||
87 | dst = skb_dst(skb); | ||
88 | if (dst->xfrm) | ||
89 | dst = ((struct xfrm_dst *)dst)->route; | ||
90 | dst_hold(dst); | ||
91 | |||
92 | dst = xfrm_lookup(dev_net(dst->dev), dst, &fl, skb->sk, 0); | ||
93 | if (IS_ERR(dst)) | ||
94 | return -1; | ||
95 | |||
96 | skb_dst_drop(skb); | ||
97 | skb_dst_set(skb, dst); | ||
98 | |||
99 | /* Change in oif may mean change in hh_len. */ | ||
100 | hh_len = skb_dst(skb)->dev->hard_header_len; | ||
101 | if (skb_headroom(skb) < hh_len && | ||
102 | pskb_expand_head(skb, hh_len - skb_headroom(skb), 0, GFP_ATOMIC)) | ||
103 | return -1; | ||
104 | return 0; | ||
105 | } | ||
106 | EXPORT_SYMBOL(ip_xfrm_me_harder); | ||
107 | #endif | ||
108 | |||
109 | void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *); | ||
110 | EXPORT_SYMBOL(ip_nat_decode_session); | ||
111 | |||
112 | /* | 75 | /* |
113 | * Extra routing may needed on local out, as the QUEUE target never | 76 | * Extra routing may needed on local out, as the QUEUE target never |
114 | * returns control to the table. | 77 | * returns control to the table. |
@@ -225,12 +188,12 @@ static const struct nf_afinfo nf_ip_afinfo = { | |||
225 | .route_key_size = sizeof(struct ip_rt_info), | 188 | .route_key_size = sizeof(struct ip_rt_info), |
226 | }; | 189 | }; |
227 | 190 | ||
228 | static int ipv4_netfilter_init(void) | 191 | static int __init ipv4_netfilter_init(void) |
229 | { | 192 | { |
230 | return nf_register_afinfo(&nf_ip_afinfo); | 193 | return nf_register_afinfo(&nf_ip_afinfo); |
231 | } | 194 | } |
232 | 195 | ||
233 | static void ipv4_netfilter_fini(void) | 196 | static void __exit ipv4_netfilter_fini(void) |
234 | { | 197 | { |
235 | nf_unregister_afinfo(&nf_ip_afinfo); | 198 | nf_unregister_afinfo(&nf_ip_afinfo); |
236 | } | 199 | } |
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index fcc543cd987a..131e53702e77 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig | |||
@@ -143,25 +143,22 @@ config IP_NF_TARGET_ULOG | |||
143 | To compile it as a module, choose M here. If unsure, say N. | 143 | To compile it as a module, choose M here. If unsure, say N. |
144 | 144 | ||
145 | # NAT + specific targets: nf_conntrack | 145 | # NAT + specific targets: nf_conntrack |
146 | config NF_NAT | 146 | config NF_NAT_IPV4 |
147 | tristate "Full NAT" | 147 | tristate "IPv4 NAT" |
148 | depends on NF_CONNTRACK_IPV4 | 148 | depends on NF_CONNTRACK_IPV4 |
149 | default m if NETFILTER_ADVANCED=n | 149 | default m if NETFILTER_ADVANCED=n |
150 | select NF_NAT | ||
150 | help | 151 | help |
151 | The Full NAT option allows masquerading, port forwarding and other | 152 | The IPv4 NAT option allows masquerading, port forwarding and other |
152 | forms of full Network Address Port Translation. It is controlled by | 153 | forms of full Network Address Port Translation. It is controlled by |
153 | the `nat' table in iptables: see the man page for iptables(8). | 154 | the `nat' table in iptables: see the man page for iptables(8). |
154 | 155 | ||
155 | To compile it as a module, choose M here. If unsure, say N. | 156 | To compile it as a module, choose M here. If unsure, say N. |
156 | 157 | ||
157 | config NF_NAT_NEEDED | 158 | if NF_NAT_IPV4 |
158 | bool | ||
159 | depends on NF_NAT | ||
160 | default y | ||
161 | 159 | ||
162 | config IP_NF_TARGET_MASQUERADE | 160 | config IP_NF_TARGET_MASQUERADE |
163 | tristate "MASQUERADE target support" | 161 | tristate "MASQUERADE target support" |
164 | depends on NF_NAT | ||
165 | default m if NETFILTER_ADVANCED=n | 162 | default m if NETFILTER_ADVANCED=n |
166 | help | 163 | help |
167 | Masquerading is a special case of NAT: all outgoing connections are | 164 | Masquerading is a special case of NAT: all outgoing connections are |
@@ -174,7 +171,6 @@ config IP_NF_TARGET_MASQUERADE | |||
174 | 171 | ||
175 | config IP_NF_TARGET_NETMAP | 172 | config IP_NF_TARGET_NETMAP |
176 | tristate "NETMAP target support" | 173 | tristate "NETMAP target support" |
177 | depends on NF_NAT | ||
178 | depends on NETFILTER_ADVANCED | 174 | depends on NETFILTER_ADVANCED |
179 | help | 175 | help |
180 | NETMAP is an implementation of static 1:1 NAT mapping of network | 176 | NETMAP is an implementation of static 1:1 NAT mapping of network |
@@ -185,7 +181,6 @@ config IP_NF_TARGET_NETMAP | |||
185 | 181 | ||
186 | config IP_NF_TARGET_REDIRECT | 182 | config IP_NF_TARGET_REDIRECT |
187 | tristate "REDIRECT target support" | 183 | tristate "REDIRECT target support" |
188 | depends on NF_NAT | ||
189 | depends on NETFILTER_ADVANCED | 184 | depends on NETFILTER_ADVANCED |
190 | help | 185 | help |
191 | REDIRECT is a special case of NAT: all incoming connections are | 186 | REDIRECT is a special case of NAT: all incoming connections are |
@@ -195,9 +190,11 @@ config IP_NF_TARGET_REDIRECT | |||
195 | 190 | ||
196 | To compile it as a module, choose M here. If unsure, say N. | 191 | To compile it as a module, choose M here. If unsure, say N. |
197 | 192 | ||
193 | endif | ||
194 | |||
198 | config NF_NAT_SNMP_BASIC | 195 | config NF_NAT_SNMP_BASIC |
199 | tristate "Basic SNMP-ALG support" | 196 | tristate "Basic SNMP-ALG support" |
200 | depends on NF_CONNTRACK_SNMP && NF_NAT | 197 | depends on NF_CONNTRACK_SNMP && NF_NAT_IPV4 |
201 | depends on NETFILTER_ADVANCED | 198 | depends on NETFILTER_ADVANCED |
202 | default NF_NAT && NF_CONNTRACK_SNMP | 199 | default NF_NAT && NF_CONNTRACK_SNMP |
203 | ---help--- | 200 | ---help--- |
@@ -219,61 +216,21 @@ config NF_NAT_SNMP_BASIC | |||
219 | # <expr> '&&' <expr> (6) | 216 | # <expr> '&&' <expr> (6) |
220 | # | 217 | # |
221 | # (6) Returns the result of min(/expr/, /expr/). | 218 | # (6) Returns the result of min(/expr/, /expr/). |
222 | config NF_NAT_PROTO_DCCP | ||
223 | tristate | ||
224 | depends on NF_NAT && NF_CT_PROTO_DCCP | ||
225 | default NF_NAT && NF_CT_PROTO_DCCP | ||
226 | 219 | ||
227 | config NF_NAT_PROTO_GRE | 220 | config NF_NAT_PROTO_GRE |
228 | tristate | 221 | tristate |
229 | depends on NF_NAT && NF_CT_PROTO_GRE | 222 | depends on NF_NAT_IPV4 && NF_CT_PROTO_GRE |
230 | |||
231 | config NF_NAT_PROTO_UDPLITE | ||
232 | tristate | ||
233 | depends on NF_NAT && NF_CT_PROTO_UDPLITE | ||
234 | default NF_NAT && NF_CT_PROTO_UDPLITE | ||
235 | |||
236 | config NF_NAT_PROTO_SCTP | ||
237 | tristate | ||
238 | default NF_NAT && NF_CT_PROTO_SCTP | ||
239 | depends on NF_NAT && NF_CT_PROTO_SCTP | ||
240 | select LIBCRC32C | ||
241 | |||
242 | config NF_NAT_FTP | ||
243 | tristate | ||
244 | depends on NF_CONNTRACK && NF_NAT | ||
245 | default NF_NAT && NF_CONNTRACK_FTP | ||
246 | |||
247 | config NF_NAT_IRC | ||
248 | tristate | ||
249 | depends on NF_CONNTRACK && NF_NAT | ||
250 | default NF_NAT && NF_CONNTRACK_IRC | ||
251 | |||
252 | config NF_NAT_TFTP | ||
253 | tristate | ||
254 | depends on NF_CONNTRACK && NF_NAT | ||
255 | default NF_NAT && NF_CONNTRACK_TFTP | ||
256 | |||
257 | config NF_NAT_AMANDA | ||
258 | tristate | ||
259 | depends on NF_CONNTRACK && NF_NAT | ||
260 | default NF_NAT && NF_CONNTRACK_AMANDA | ||
261 | 223 | ||
262 | config NF_NAT_PPTP | 224 | config NF_NAT_PPTP |
263 | tristate | 225 | tristate |
264 | depends on NF_CONNTRACK && NF_NAT | 226 | depends on NF_CONNTRACK && NF_NAT_IPV4 |
265 | default NF_NAT && NF_CONNTRACK_PPTP | 227 | default NF_NAT_IPV4 && NF_CONNTRACK_PPTP |
266 | select NF_NAT_PROTO_GRE | 228 | select NF_NAT_PROTO_GRE |
267 | 229 | ||
268 | config NF_NAT_H323 | 230 | config NF_NAT_H323 |
269 | tristate | 231 | tristate |
270 | depends on NF_CONNTRACK && NF_NAT | 232 | depends on NF_CONNTRACK && NF_NAT_IPV4 |
271 | default NF_NAT && NF_CONNTRACK_H323 | 233 | default NF_NAT_IPV4 && NF_CONNTRACK_H323 |
272 | |||
273 | config NF_NAT_SIP | ||
274 | tristate | ||
275 | depends on NF_CONNTRACK && NF_NAT | ||
276 | default NF_NAT && NF_CONNTRACK_SIP | ||
277 | 234 | ||
278 | # mangle + specific targets | 235 | # mangle + specific targets |
279 | config IP_NF_MANGLE | 236 | config IP_NF_MANGLE |
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index c20674dc9452..b7dd18987237 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile | |||
@@ -10,32 +10,22 @@ nf_conntrack_ipv4-objs += nf_conntrack_l3proto_ipv4_compat.o | |||
10 | endif | 10 | endif |
11 | endif | 11 | endif |
12 | 12 | ||
13 | nf_nat-y := nf_nat_core.o nf_nat_helper.o nf_nat_proto_unknown.o nf_nat_proto_common.o nf_nat_proto_tcp.o nf_nat_proto_udp.o nf_nat_proto_icmp.o | ||
14 | iptable_nat-y := nf_nat_rule.o nf_nat_standalone.o | ||
15 | |||
16 | # connection tracking | 13 | # connection tracking |
17 | obj-$(CONFIG_NF_CONNTRACK_IPV4) += nf_conntrack_ipv4.o | 14 | obj-$(CONFIG_NF_CONNTRACK_IPV4) += nf_conntrack_ipv4.o |
18 | 15 | ||
19 | obj-$(CONFIG_NF_NAT) += nf_nat.o | 16 | nf_nat_ipv4-y := nf_nat_l3proto_ipv4.o nf_nat_proto_icmp.o |
17 | obj-$(CONFIG_NF_NAT_IPV4) += nf_nat_ipv4.o | ||
20 | 18 | ||
21 | # defrag | 19 | # defrag |
22 | obj-$(CONFIG_NF_DEFRAG_IPV4) += nf_defrag_ipv4.o | 20 | obj-$(CONFIG_NF_DEFRAG_IPV4) += nf_defrag_ipv4.o |
23 | 21 | ||
24 | # NAT helpers (nf_conntrack) | 22 | # NAT helpers (nf_conntrack) |
25 | obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o | ||
26 | obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o | ||
27 | obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o | 23 | obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o |
28 | obj-$(CONFIG_NF_NAT_IRC) += nf_nat_irc.o | ||
29 | obj-$(CONFIG_NF_NAT_PPTP) += nf_nat_pptp.o | 24 | obj-$(CONFIG_NF_NAT_PPTP) += nf_nat_pptp.o |
30 | obj-$(CONFIG_NF_NAT_SIP) += nf_nat_sip.o | ||
31 | obj-$(CONFIG_NF_NAT_SNMP_BASIC) += nf_nat_snmp_basic.o | 25 | obj-$(CONFIG_NF_NAT_SNMP_BASIC) += nf_nat_snmp_basic.o |
32 | obj-$(CONFIG_NF_NAT_TFTP) += nf_nat_tftp.o | ||
33 | 26 | ||
34 | # NAT protocols (nf_nat) | 27 | # NAT protocols (nf_nat) |
35 | obj-$(CONFIG_NF_NAT_PROTO_DCCP) += nf_nat_proto_dccp.o | ||
36 | obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o | 28 | obj-$(CONFIG_NF_NAT_PROTO_GRE) += nf_nat_proto_gre.o |
37 | obj-$(CONFIG_NF_NAT_PROTO_UDPLITE) += nf_nat_proto_udplite.o | ||
38 | obj-$(CONFIG_NF_NAT_PROTO_SCTP) += nf_nat_proto_sctp.o | ||
39 | 29 | ||
40 | # generic IP tables | 30 | # generic IP tables |
41 | obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o | 31 | obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o |
@@ -43,7 +33,7 @@ obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o | |||
43 | # the three instances of ip_tables | 33 | # the three instances of ip_tables |
44 | obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o | 34 | obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o |
45 | obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o | 35 | obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o |
46 | obj-$(CONFIG_NF_NAT) += iptable_nat.o | 36 | obj-$(CONFIG_NF_NAT_IPV4) += iptable_nat.o |
47 | obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o | 37 | obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o |
48 | obj-$(CONFIG_IP_NF_SECURITY) += iptable_security.o | 38 | obj-$(CONFIG_IP_NF_SECURITY) += iptable_security.o |
49 | 39 | ||
diff --git a/net/ipv4/netfilter/ipt_MASQUERADE.c b/net/ipv4/netfilter/ipt_MASQUERADE.c index cbb6a1a6f6f7..5d5d4d1be9c2 100644 --- a/net/ipv4/netfilter/ipt_MASQUERADE.c +++ b/net/ipv4/netfilter/ipt_MASQUERADE.c | |||
@@ -19,9 +19,9 @@ | |||
19 | #include <net/ip.h> | 19 | #include <net/ip.h> |
20 | #include <net/checksum.h> | 20 | #include <net/checksum.h> |
21 | #include <net/route.h> | 21 | #include <net/route.h> |
22 | #include <net/netfilter/nf_nat_rule.h> | ||
23 | #include <linux/netfilter_ipv4.h> | 22 | #include <linux/netfilter_ipv4.h> |
24 | #include <linux/netfilter/x_tables.h> | 23 | #include <linux/netfilter/x_tables.h> |
24 | #include <net/netfilter/nf_nat.h> | ||
25 | 25 | ||
26 | MODULE_LICENSE("GPL"); | 26 | MODULE_LICENSE("GPL"); |
27 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); | 27 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); |
@@ -49,7 +49,7 @@ masquerade_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
49 | struct nf_conn *ct; | 49 | struct nf_conn *ct; |
50 | struct nf_conn_nat *nat; | 50 | struct nf_conn_nat *nat; |
51 | enum ip_conntrack_info ctinfo; | 51 | enum ip_conntrack_info ctinfo; |
52 | struct nf_nat_ipv4_range newrange; | 52 | struct nf_nat_range newrange; |
53 | const struct nf_nat_ipv4_multi_range_compat *mr; | 53 | const struct nf_nat_ipv4_multi_range_compat *mr; |
54 | const struct rtable *rt; | 54 | const struct rtable *rt; |
55 | __be32 newsrc, nh; | 55 | __be32 newsrc, nh; |
@@ -80,10 +80,13 @@ masquerade_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
80 | nat->masq_index = par->out->ifindex; | 80 | nat->masq_index = par->out->ifindex; |
81 | 81 | ||
82 | /* Transfer from original range. */ | 82 | /* Transfer from original range. */ |
83 | newrange = ((struct nf_nat_ipv4_range) | 83 | memset(&newrange.min_addr, 0, sizeof(newrange.min_addr)); |
84 | { mr->range[0].flags | NF_NAT_RANGE_MAP_IPS, | 84 | memset(&newrange.max_addr, 0, sizeof(newrange.max_addr)); |
85 | newsrc, newsrc, | 85 | newrange.flags = mr->range[0].flags | NF_NAT_RANGE_MAP_IPS; |
86 | mr->range[0].min, mr->range[0].max }); | 86 | newrange.min_addr.ip = newsrc; |
87 | newrange.max_addr.ip = newsrc; | ||
88 | newrange.min_proto = mr->range[0].min; | ||
89 | newrange.max_proto = mr->range[0].max; | ||
87 | 90 | ||
88 | /* Hand modified range to generic setup. */ | 91 | /* Hand modified range to generic setup. */ |
89 | return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_SRC); | 92 | return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_SRC); |
@@ -96,7 +99,8 @@ device_cmp(struct nf_conn *i, void *ifindex) | |||
96 | 99 | ||
97 | if (!nat) | 100 | if (!nat) |
98 | return 0; | 101 | return 0; |
99 | 102 | if (nf_ct_l3num(i) != NFPROTO_IPV4) | |
103 | return 0; | ||
100 | return nat->masq_index == (int)(long)ifindex; | 104 | return nat->masq_index == (int)(long)ifindex; |
101 | } | 105 | } |
102 | 106 | ||
diff --git a/net/ipv4/netfilter/ipt_NETMAP.c b/net/ipv4/netfilter/ipt_NETMAP.c index b5bfbbabf70d..85028dc0425d 100644 --- a/net/ipv4/netfilter/ipt_NETMAP.c +++ b/net/ipv4/netfilter/ipt_NETMAP.c | |||
@@ -16,7 +16,7 @@ | |||
16 | #include <linux/netfilter.h> | 16 | #include <linux/netfilter.h> |
17 | #include <linux/netfilter_ipv4.h> | 17 | #include <linux/netfilter_ipv4.h> |
18 | #include <linux/netfilter/x_tables.h> | 18 | #include <linux/netfilter/x_tables.h> |
19 | #include <net/netfilter/nf_nat_rule.h> | 19 | #include <net/netfilter/nf_nat.h> |
20 | 20 | ||
21 | MODULE_LICENSE("GPL"); | 21 | MODULE_LICENSE("GPL"); |
22 | MODULE_AUTHOR("Svenning Soerensen <svenning@post5.tele.dk>"); | 22 | MODULE_AUTHOR("Svenning Soerensen <svenning@post5.tele.dk>"); |
@@ -44,7 +44,7 @@ netmap_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
44 | enum ip_conntrack_info ctinfo; | 44 | enum ip_conntrack_info ctinfo; |
45 | __be32 new_ip, netmask; | 45 | __be32 new_ip, netmask; |
46 | const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; | 46 | const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; |
47 | struct nf_nat_ipv4_range newrange; | 47 | struct nf_nat_range newrange; |
48 | 48 | ||
49 | NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING || | 49 | NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING || |
50 | par->hooknum == NF_INET_POST_ROUTING || | 50 | par->hooknum == NF_INET_POST_ROUTING || |
@@ -61,10 +61,13 @@ netmap_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
61 | new_ip = ip_hdr(skb)->saddr & ~netmask; | 61 | new_ip = ip_hdr(skb)->saddr & ~netmask; |
62 | new_ip |= mr->range[0].min_ip & netmask; | 62 | new_ip |= mr->range[0].min_ip & netmask; |
63 | 63 | ||
64 | newrange = ((struct nf_nat_ipv4_range) | 64 | memset(&newrange.min_addr, 0, sizeof(newrange.min_addr)); |
65 | { mr->range[0].flags | NF_NAT_RANGE_MAP_IPS, | 65 | memset(&newrange.max_addr, 0, sizeof(newrange.max_addr)); |
66 | new_ip, new_ip, | 66 | newrange.flags = mr->range[0].flags | NF_NAT_RANGE_MAP_IPS; |
67 | mr->range[0].min, mr->range[0].max }); | 67 | newrange.min_addr.ip = new_ip; |
68 | newrange.max_addr.ip = new_ip; | ||
69 | newrange.min_proto = mr->range[0].min; | ||
70 | newrange.max_proto = mr->range[0].max; | ||
68 | 71 | ||
69 | /* Hand modified range to generic setup. */ | 72 | /* Hand modified range to generic setup. */ |
70 | return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(par->hooknum)); | 73 | return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(par->hooknum)); |
diff --git a/net/ipv4/netfilter/ipt_REDIRECT.c b/net/ipv4/netfilter/ipt_REDIRECT.c index 7c0103a5203e..11407d7d2472 100644 --- a/net/ipv4/netfilter/ipt_REDIRECT.c +++ b/net/ipv4/netfilter/ipt_REDIRECT.c | |||
@@ -19,7 +19,7 @@ | |||
19 | #include <net/checksum.h> | 19 | #include <net/checksum.h> |
20 | #include <linux/netfilter_ipv4.h> | 20 | #include <linux/netfilter_ipv4.h> |
21 | #include <linux/netfilter/x_tables.h> | 21 | #include <linux/netfilter/x_tables.h> |
22 | #include <net/netfilter/nf_nat_rule.h> | 22 | #include <net/netfilter/nf_nat.h> |
23 | 23 | ||
24 | MODULE_LICENSE("GPL"); | 24 | MODULE_LICENSE("GPL"); |
25 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); | 25 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); |
@@ -48,7 +48,7 @@ redirect_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
48 | enum ip_conntrack_info ctinfo; | 48 | enum ip_conntrack_info ctinfo; |
49 | __be32 newdst; | 49 | __be32 newdst; |
50 | const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; | 50 | const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; |
51 | struct nf_nat_ipv4_range newrange; | 51 | struct nf_nat_range newrange; |
52 | 52 | ||
53 | NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING || | 53 | NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING || |
54 | par->hooknum == NF_INET_LOCAL_OUT); | 54 | par->hooknum == NF_INET_LOCAL_OUT); |
@@ -76,10 +76,13 @@ redirect_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
76 | } | 76 | } |
77 | 77 | ||
78 | /* Transfer from original range. */ | 78 | /* Transfer from original range. */ |
79 | newrange = ((struct nf_nat_ipv4_range) | 79 | memset(&newrange.min_addr, 0, sizeof(newrange.min_addr)); |
80 | { mr->range[0].flags | NF_NAT_RANGE_MAP_IPS, | 80 | memset(&newrange.max_addr, 0, sizeof(newrange.max_addr)); |
81 | newdst, newdst, | 81 | newrange.flags = mr->range[0].flags | NF_NAT_RANGE_MAP_IPS; |
82 | mr->range[0].min, mr->range[0].max }); | 82 | newrange.min_addr.ip = newdst; |
83 | newrange.max_addr.ip = newdst; | ||
84 | newrange.min_proto = mr->range[0].min; | ||
85 | newrange.max_proto = mr->range[0].max; | ||
83 | 86 | ||
84 | /* Hand modified range to generic setup. */ | 87 | /* Hand modified range to generic setup. */ |
85 | return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST); | 88 | return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST); |
diff --git a/net/ipv4/netfilter/ipt_rpfilter.c b/net/ipv4/netfilter/ipt_rpfilter.c index 31371be8174b..c30130062cd6 100644 --- a/net/ipv4/netfilter/ipt_rpfilter.c +++ b/net/ipv4/netfilter/ipt_rpfilter.c | |||
@@ -85,7 +85,7 @@ static bool rpfilter_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
85 | return ipv4_is_local_multicast(iph->daddr) ^ invert; | 85 | return ipv4_is_local_multicast(iph->daddr) ^ invert; |
86 | flow.flowi4_iif = 0; | 86 | flow.flowi4_iif = 0; |
87 | } else { | 87 | } else { |
88 | flow.flowi4_iif = dev_net(par->in)->loopback_dev->ifindex; | 88 | flow.flowi4_iif = LOOPBACK_IFINDEX; |
89 | } | 89 | } |
90 | 90 | ||
91 | flow.daddr = iph->saddr; | 91 | flow.daddr = iph->saddr; |
diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c index 851acec852d2..6b3da5cf54e9 100644 --- a/net/ipv4/netfilter/iptable_filter.c +++ b/net/ipv4/netfilter/iptable_filter.c | |||
@@ -69,9 +69,7 @@ static int __net_init iptable_filter_net_init(struct net *net) | |||
69 | net->ipv4.iptable_filter = | 69 | net->ipv4.iptable_filter = |
70 | ipt_register_table(net, &packet_filter, repl); | 70 | ipt_register_table(net, &packet_filter, repl); |
71 | kfree(repl); | 71 | kfree(repl); |
72 | if (IS_ERR(net->ipv4.iptable_filter)) | 72 | return PTR_RET(net->ipv4.iptable_filter); |
73 | return PTR_ERR(net->ipv4.iptable_filter); | ||
74 | return 0; | ||
75 | } | 73 | } |
76 | 74 | ||
77 | static void __net_exit iptable_filter_net_exit(struct net *net) | 75 | static void __net_exit iptable_filter_net_exit(struct net *net) |
@@ -96,14 +94,10 @@ static int __init iptable_filter_init(void) | |||
96 | filter_ops = xt_hook_link(&packet_filter, iptable_filter_hook); | 94 | filter_ops = xt_hook_link(&packet_filter, iptable_filter_hook); |
97 | if (IS_ERR(filter_ops)) { | 95 | if (IS_ERR(filter_ops)) { |
98 | ret = PTR_ERR(filter_ops); | 96 | ret = PTR_ERR(filter_ops); |
99 | goto cleanup_table; | 97 | unregister_pernet_subsys(&iptable_filter_net_ops); |
100 | } | 98 | } |
101 | 99 | ||
102 | return ret; | 100 | return ret; |
103 | |||
104 | cleanup_table: | ||
105 | unregister_pernet_subsys(&iptable_filter_net_ops); | ||
106 | return ret; | ||
107 | } | 101 | } |
108 | 102 | ||
109 | static void __exit iptable_filter_fini(void) | 103 | static void __exit iptable_filter_fini(void) |
diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c index aef5d1fbe77d..85d88f206447 100644 --- a/net/ipv4/netfilter/iptable_mangle.c +++ b/net/ipv4/netfilter/iptable_mangle.c | |||
@@ -104,9 +104,7 @@ static int __net_init iptable_mangle_net_init(struct net *net) | |||
104 | net->ipv4.iptable_mangle = | 104 | net->ipv4.iptable_mangle = |
105 | ipt_register_table(net, &packet_mangler, repl); | 105 | ipt_register_table(net, &packet_mangler, repl); |
106 | kfree(repl); | 106 | kfree(repl); |
107 | if (IS_ERR(net->ipv4.iptable_mangle)) | 107 | return PTR_RET(net->ipv4.iptable_mangle); |
108 | return PTR_ERR(net->ipv4.iptable_mangle); | ||
109 | return 0; | ||
110 | } | 108 | } |
111 | 109 | ||
112 | static void __net_exit iptable_mangle_net_exit(struct net *net) | 110 | static void __net_exit iptable_mangle_net_exit(struct net *net) |
@@ -131,14 +129,10 @@ static int __init iptable_mangle_init(void) | |||
131 | mangle_ops = xt_hook_link(&packet_mangler, iptable_mangle_hook); | 129 | mangle_ops = xt_hook_link(&packet_mangler, iptable_mangle_hook); |
132 | if (IS_ERR(mangle_ops)) { | 130 | if (IS_ERR(mangle_ops)) { |
133 | ret = PTR_ERR(mangle_ops); | 131 | ret = PTR_ERR(mangle_ops); |
134 | goto cleanup_table; | 132 | unregister_pernet_subsys(&iptable_mangle_net_ops); |
135 | } | 133 | } |
136 | 134 | ||
137 | return ret; | 135 | return ret; |
138 | |||
139 | cleanup_table: | ||
140 | unregister_pernet_subsys(&iptable_mangle_net_ops); | ||
141 | return ret; | ||
142 | } | 136 | } |
143 | 137 | ||
144 | static void __exit iptable_mangle_fini(void) | 138 | static void __exit iptable_mangle_fini(void) |
diff --git a/net/ipv4/netfilter/nf_nat_standalone.c b/net/ipv4/netfilter/iptable_nat.c index 3828a4229822..9e0ffaf1d942 100644 --- a/net/ipv4/netfilter/nf_nat_standalone.c +++ b/net/ipv4/netfilter/iptable_nat.c | |||
@@ -1,84 +1,71 @@ | |||
1 | /* (C) 1999-2001 Paul `Rusty' Russell | 1 | /* (C) 1999-2001 Paul `Rusty' Russell |
2 | * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org> | 2 | * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org> |
3 | * (C) 2011 Patrick McHardy <kaber@trash.net> | ||
3 | * | 4 | * |
4 | * This program is free software; you can redistribute it and/or modify | 5 | * This program is free software; you can redistribute it and/or modify |
5 | * it under the terms of the GNU General Public License version 2 as | 6 | * it under the terms of the GNU General Public License version 2 as |
6 | * published by the Free Software Foundation. | 7 | * published by the Free Software Foundation. |
7 | */ | 8 | */ |
8 | #include <linux/types.h> | 9 | |
9 | #include <linux/icmp.h> | 10 | #include <linux/module.h> |
10 | #include <linux/gfp.h> | ||
11 | #include <linux/ip.h> | ||
12 | #include <linux/netfilter.h> | 11 | #include <linux/netfilter.h> |
13 | #include <linux/netfilter_ipv4.h> | 12 | #include <linux/netfilter_ipv4.h> |
14 | #include <linux/module.h> | 13 | #include <linux/netfilter_ipv4/ip_tables.h> |
15 | #include <linux/skbuff.h> | 14 | #include <linux/ip.h> |
16 | #include <linux/proc_fs.h> | ||
17 | #include <net/ip.h> | 15 | #include <net/ip.h> |
18 | #include <net/checksum.h> | ||
19 | #include <linux/spinlock.h> | ||
20 | 16 | ||
21 | #include <net/netfilter/nf_conntrack.h> | ||
22 | #include <net/netfilter/nf_conntrack_core.h> | ||
23 | #include <net/netfilter/nf_conntrack_extend.h> | ||
24 | #include <net/netfilter/nf_nat.h> | 17 | #include <net/netfilter/nf_nat.h> |
25 | #include <net/netfilter/nf_nat_rule.h> | ||
26 | #include <net/netfilter/nf_nat_protocol.h> | ||
27 | #include <net/netfilter/nf_nat_core.h> | 18 | #include <net/netfilter/nf_nat_core.h> |
28 | #include <net/netfilter/nf_nat_helper.h> | 19 | #include <net/netfilter/nf_nat_l3proto.h> |
29 | #include <linux/netfilter_ipv4/ip_tables.h> | 20 | |
21 | static const struct xt_table nf_nat_ipv4_table = { | ||
22 | .name = "nat", | ||
23 | .valid_hooks = (1 << NF_INET_PRE_ROUTING) | | ||
24 | (1 << NF_INET_POST_ROUTING) | | ||
25 | (1 << NF_INET_LOCAL_OUT) | | ||
26 | (1 << NF_INET_LOCAL_IN), | ||
27 | .me = THIS_MODULE, | ||
28 | .af = NFPROTO_IPV4, | ||
29 | }; | ||
30 | 30 | ||
31 | #ifdef CONFIG_XFRM | 31 | static unsigned int alloc_null_binding(struct nf_conn *ct, unsigned int hooknum) |
32 | static void nat_decode_session(struct sk_buff *skb, struct flowi *fl) | ||
33 | { | 32 | { |
34 | struct flowi4 *fl4 = &fl->u.ip4; | 33 | /* Force range to this IP; let proto decide mapping for |
35 | const struct nf_conn *ct; | 34 | * per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED). |
36 | const struct nf_conntrack_tuple *t; | 35 | */ |
37 | enum ip_conntrack_info ctinfo; | 36 | struct nf_nat_range range; |
38 | enum ip_conntrack_dir dir; | 37 | |
39 | unsigned long statusbit; | 38 | range.flags = 0; |
40 | 39 | pr_debug("Allocating NULL binding for %p (%pI4)\n", ct, | |
41 | ct = nf_ct_get(skb, &ctinfo); | 40 | HOOK2MANIP(hooknum) == NF_NAT_MANIP_SRC ? |
42 | if (ct == NULL) | 41 | &ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip : |
43 | return; | 42 | &ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip); |
44 | dir = CTINFO2DIR(ctinfo); | 43 | |
45 | t = &ct->tuplehash[dir].tuple; | 44 | return nf_nat_setup_info(ct, &range, HOOK2MANIP(hooknum)); |
46 | 45 | } | |
47 | if (dir == IP_CT_DIR_ORIGINAL) | ||
48 | statusbit = IPS_DST_NAT; | ||
49 | else | ||
50 | statusbit = IPS_SRC_NAT; | ||
51 | |||
52 | if (ct->status & statusbit) { | ||
53 | fl4->daddr = t->dst.u3.ip; | ||
54 | if (t->dst.protonum == IPPROTO_TCP || | ||
55 | t->dst.protonum == IPPROTO_UDP || | ||
56 | t->dst.protonum == IPPROTO_UDPLITE || | ||
57 | t->dst.protonum == IPPROTO_DCCP || | ||
58 | t->dst.protonum == IPPROTO_SCTP) | ||
59 | fl4->fl4_dport = t->dst.u.tcp.port; | ||
60 | } | ||
61 | 46 | ||
62 | statusbit ^= IPS_NAT_MASK; | 47 | static unsigned int nf_nat_rule_find(struct sk_buff *skb, unsigned int hooknum, |
48 | const struct net_device *in, | ||
49 | const struct net_device *out, | ||
50 | struct nf_conn *ct) | ||
51 | { | ||
52 | struct net *net = nf_ct_net(ct); | ||
53 | unsigned int ret; | ||
63 | 54 | ||
64 | if (ct->status & statusbit) { | 55 | ret = ipt_do_table(skb, hooknum, in, out, net->ipv4.nat_table); |
65 | fl4->saddr = t->src.u3.ip; | 56 | if (ret == NF_ACCEPT) { |
66 | if (t->dst.protonum == IPPROTO_TCP || | 57 | if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum))) |
67 | t->dst.protonum == IPPROTO_UDP || | 58 | ret = alloc_null_binding(ct, hooknum); |
68 | t->dst.protonum == IPPROTO_UDPLITE || | ||
69 | t->dst.protonum == IPPROTO_DCCP || | ||
70 | t->dst.protonum == IPPROTO_SCTP) | ||
71 | fl4->fl4_sport = t->src.u.tcp.port; | ||
72 | } | 59 | } |
60 | return ret; | ||
73 | } | 61 | } |
74 | #endif | ||
75 | 62 | ||
76 | static unsigned int | 63 | static unsigned int |
77 | nf_nat_fn(unsigned int hooknum, | 64 | nf_nat_ipv4_fn(unsigned int hooknum, |
78 | struct sk_buff *skb, | 65 | struct sk_buff *skb, |
79 | const struct net_device *in, | 66 | const struct net_device *in, |
80 | const struct net_device *out, | 67 | const struct net_device *out, |
81 | int (*okfn)(struct sk_buff *)) | 68 | int (*okfn)(struct sk_buff *)) |
82 | { | 69 | { |
83 | struct nf_conn *ct; | 70 | struct nf_conn *ct; |
84 | enum ip_conntrack_info ctinfo; | 71 | enum ip_conntrack_info ctinfo; |
@@ -87,14 +74,16 @@ nf_nat_fn(unsigned int hooknum, | |||
87 | enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum); | 74 | enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum); |
88 | 75 | ||
89 | /* We never see fragments: conntrack defrags on pre-routing | 76 | /* We never see fragments: conntrack defrags on pre-routing |
90 | and local-out, and nf_nat_out protects post-routing. */ | 77 | * and local-out, and nf_nat_out protects post-routing. |
78 | */ | ||
91 | NF_CT_ASSERT(!ip_is_fragment(ip_hdr(skb))); | 79 | NF_CT_ASSERT(!ip_is_fragment(ip_hdr(skb))); |
92 | 80 | ||
93 | ct = nf_ct_get(skb, &ctinfo); | 81 | ct = nf_ct_get(skb, &ctinfo); |
94 | /* Can't track? It's not due to stress, or conntrack would | 82 | /* Can't track? It's not due to stress, or conntrack would |
95 | have dropped it. Hence it's the user's responsibilty to | 83 | * have dropped it. Hence it's the user's responsibilty to |
96 | packet filter it out, or implement conntrack/NAT for that | 84 | * packet filter it out, or implement conntrack/NAT for that |
97 | protocol. 8) --RR */ | 85 | * protocol. 8) --RR |
86 | */ | ||
98 | if (!ct) | 87 | if (!ct) |
99 | return NF_ACCEPT; | 88 | return NF_ACCEPT; |
100 | 89 | ||
@@ -118,17 +107,17 @@ nf_nat_fn(unsigned int hooknum, | |||
118 | case IP_CT_RELATED: | 107 | case IP_CT_RELATED: |
119 | case IP_CT_RELATED_REPLY: | 108 | case IP_CT_RELATED_REPLY: |
120 | if (ip_hdr(skb)->protocol == IPPROTO_ICMP) { | 109 | if (ip_hdr(skb)->protocol == IPPROTO_ICMP) { |
121 | if (!nf_nat_icmp_reply_translation(ct, ctinfo, | 110 | if (!nf_nat_icmp_reply_translation(skb, ct, ctinfo, |
122 | hooknum, skb)) | 111 | hooknum)) |
123 | return NF_DROP; | 112 | return NF_DROP; |
124 | else | 113 | else |
125 | return NF_ACCEPT; | 114 | return NF_ACCEPT; |
126 | } | 115 | } |
127 | /* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */ | 116 | /* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */ |
128 | case IP_CT_NEW: | 117 | case IP_CT_NEW: |
129 | |||
130 | /* Seen it before? This can happen for loopback, retrans, | 118 | /* Seen it before? This can happen for loopback, retrans, |
131 | or local packets.. */ | 119 | * or local packets. |
120 | */ | ||
132 | if (!nf_nat_initialized(ct, maniptype)) { | 121 | if (!nf_nat_initialized(ct, maniptype)) { |
133 | unsigned int ret; | 122 | unsigned int ret; |
134 | 123 | ||
@@ -151,16 +140,16 @@ nf_nat_fn(unsigned int hooknum, | |||
151 | } | 140 | } |
152 | 141 | ||
153 | static unsigned int | 142 | static unsigned int |
154 | nf_nat_in(unsigned int hooknum, | 143 | nf_nat_ipv4_in(unsigned int hooknum, |
155 | struct sk_buff *skb, | 144 | struct sk_buff *skb, |
156 | const struct net_device *in, | 145 | const struct net_device *in, |
157 | const struct net_device *out, | 146 | const struct net_device *out, |
158 | int (*okfn)(struct sk_buff *)) | 147 | int (*okfn)(struct sk_buff *)) |
159 | { | 148 | { |
160 | unsigned int ret; | 149 | unsigned int ret; |
161 | __be32 daddr = ip_hdr(skb)->daddr; | 150 | __be32 daddr = ip_hdr(skb)->daddr; |
162 | 151 | ||
163 | ret = nf_nat_fn(hooknum, skb, in, out, okfn); | 152 | ret = nf_nat_ipv4_fn(hooknum, skb, in, out, okfn); |
164 | if (ret != NF_DROP && ret != NF_STOLEN && | 153 | if (ret != NF_DROP && ret != NF_STOLEN && |
165 | daddr != ip_hdr(skb)->daddr) | 154 | daddr != ip_hdr(skb)->daddr) |
166 | skb_dst_drop(skb); | 155 | skb_dst_drop(skb); |
@@ -169,11 +158,11 @@ nf_nat_in(unsigned int hooknum, | |||
169 | } | 158 | } |
170 | 159 | ||
171 | static unsigned int | 160 | static unsigned int |
172 | nf_nat_out(unsigned int hooknum, | 161 | nf_nat_ipv4_out(unsigned int hooknum, |
173 | struct sk_buff *skb, | 162 | struct sk_buff *skb, |
174 | const struct net_device *in, | 163 | const struct net_device *in, |
175 | const struct net_device *out, | 164 | const struct net_device *out, |
176 | int (*okfn)(struct sk_buff *)) | 165 | int (*okfn)(struct sk_buff *)) |
177 | { | 166 | { |
178 | #ifdef CONFIG_XFRM | 167 | #ifdef CONFIG_XFRM |
179 | const struct nf_conn *ct; | 168 | const struct nf_conn *ct; |
@@ -186,29 +175,30 @@ nf_nat_out(unsigned int hooknum, | |||
186 | ip_hdrlen(skb) < sizeof(struct iphdr)) | 175 | ip_hdrlen(skb) < sizeof(struct iphdr)) |
187 | return NF_ACCEPT; | 176 | return NF_ACCEPT; |
188 | 177 | ||
189 | ret = nf_nat_fn(hooknum, skb, in, out, okfn); | 178 | ret = nf_nat_ipv4_fn(hooknum, skb, in, out, okfn); |
190 | #ifdef CONFIG_XFRM | 179 | #ifdef CONFIG_XFRM |
191 | if (ret != NF_DROP && ret != NF_STOLEN && | 180 | if (ret != NF_DROP && ret != NF_STOLEN && |
181 | !(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) && | ||
192 | (ct = nf_ct_get(skb, &ctinfo)) != NULL) { | 182 | (ct = nf_ct_get(skb, &ctinfo)) != NULL) { |
193 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | 183 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); |
194 | 184 | ||
195 | if ((ct->tuplehash[dir].tuple.src.u3.ip != | 185 | if ((ct->tuplehash[dir].tuple.src.u3.ip != |
196 | ct->tuplehash[!dir].tuple.dst.u3.ip) || | 186 | ct->tuplehash[!dir].tuple.dst.u3.ip) || |
197 | (ct->tuplehash[dir].tuple.src.u.all != | 187 | (ct->tuplehash[dir].tuple.src.u.all != |
198 | ct->tuplehash[!dir].tuple.dst.u.all) | 188 | ct->tuplehash[!dir].tuple.dst.u.all)) |
199 | ) | 189 | if (nf_xfrm_me_harder(skb, AF_INET) < 0) |
200 | return ip_xfrm_me_harder(skb) == 0 ? ret : NF_DROP; | 190 | ret = NF_DROP; |
201 | } | 191 | } |
202 | #endif | 192 | #endif |
203 | return ret; | 193 | return ret; |
204 | } | 194 | } |
205 | 195 | ||
206 | static unsigned int | 196 | static unsigned int |
207 | nf_nat_local_fn(unsigned int hooknum, | 197 | nf_nat_ipv4_local_fn(unsigned int hooknum, |
208 | struct sk_buff *skb, | 198 | struct sk_buff *skb, |
209 | const struct net_device *in, | 199 | const struct net_device *in, |
210 | const struct net_device *out, | 200 | const struct net_device *out, |
211 | int (*okfn)(struct sk_buff *)) | 201 | int (*okfn)(struct sk_buff *)) |
212 | { | 202 | { |
213 | const struct nf_conn *ct; | 203 | const struct nf_conn *ct; |
214 | enum ip_conntrack_info ctinfo; | 204 | enum ip_conntrack_info ctinfo; |
@@ -219,7 +209,7 @@ nf_nat_local_fn(unsigned int hooknum, | |||
219 | ip_hdrlen(skb) < sizeof(struct iphdr)) | 209 | ip_hdrlen(skb) < sizeof(struct iphdr)) |
220 | return NF_ACCEPT; | 210 | return NF_ACCEPT; |
221 | 211 | ||
222 | ret = nf_nat_fn(hooknum, skb, in, out, okfn); | 212 | ret = nf_nat_ipv4_fn(hooknum, skb, in, out, okfn); |
223 | if (ret != NF_DROP && ret != NF_STOLEN && | 213 | if (ret != NF_DROP && ret != NF_STOLEN && |
224 | (ct = nf_ct_get(skb, &ctinfo)) != NULL) { | 214 | (ct = nf_ct_get(skb, &ctinfo)) != NULL) { |
225 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | 215 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); |
@@ -230,21 +220,20 @@ nf_nat_local_fn(unsigned int hooknum, | |||
230 | ret = NF_DROP; | 220 | ret = NF_DROP; |
231 | } | 221 | } |
232 | #ifdef CONFIG_XFRM | 222 | #ifdef CONFIG_XFRM |
233 | else if (ct->tuplehash[dir].tuple.dst.u.all != | 223 | else if (!(IPCB(skb)->flags & IPSKB_XFRM_TRANSFORMED) && |
224 | ct->tuplehash[dir].tuple.dst.u.all != | ||
234 | ct->tuplehash[!dir].tuple.src.u.all) | 225 | ct->tuplehash[!dir].tuple.src.u.all) |
235 | if (ip_xfrm_me_harder(skb)) | 226 | if (nf_xfrm_me_harder(skb, AF_INET) < 0) |
236 | ret = NF_DROP; | 227 | ret = NF_DROP; |
237 | #endif | 228 | #endif |
238 | } | 229 | } |
239 | return ret; | 230 | return ret; |
240 | } | 231 | } |
241 | 232 | ||
242 | /* We must be after connection tracking and before packet filtering. */ | 233 | static struct nf_hook_ops nf_nat_ipv4_ops[] __read_mostly = { |
243 | |||
244 | static struct nf_hook_ops nf_nat_ops[] __read_mostly = { | ||
245 | /* Before packet filtering, change destination */ | 234 | /* Before packet filtering, change destination */ |
246 | { | 235 | { |
247 | .hook = nf_nat_in, | 236 | .hook = nf_nat_ipv4_in, |
248 | .owner = THIS_MODULE, | 237 | .owner = THIS_MODULE, |
249 | .pf = NFPROTO_IPV4, | 238 | .pf = NFPROTO_IPV4, |
250 | .hooknum = NF_INET_PRE_ROUTING, | 239 | .hooknum = NF_INET_PRE_ROUTING, |
@@ -252,7 +241,7 @@ static struct nf_hook_ops nf_nat_ops[] __read_mostly = { | |||
252 | }, | 241 | }, |
253 | /* After packet filtering, change source */ | 242 | /* After packet filtering, change source */ |
254 | { | 243 | { |
255 | .hook = nf_nat_out, | 244 | .hook = nf_nat_ipv4_out, |
256 | .owner = THIS_MODULE, | 245 | .owner = THIS_MODULE, |
257 | .pf = NFPROTO_IPV4, | 246 | .pf = NFPROTO_IPV4, |
258 | .hooknum = NF_INET_POST_ROUTING, | 247 | .hooknum = NF_INET_POST_ROUTING, |
@@ -260,7 +249,7 @@ static struct nf_hook_ops nf_nat_ops[] __read_mostly = { | |||
260 | }, | 249 | }, |
261 | /* Before packet filtering, change destination */ | 250 | /* Before packet filtering, change destination */ |
262 | { | 251 | { |
263 | .hook = nf_nat_local_fn, | 252 | .hook = nf_nat_ipv4_local_fn, |
264 | .owner = THIS_MODULE, | 253 | .owner = THIS_MODULE, |
265 | .pf = NFPROTO_IPV4, | 254 | .pf = NFPROTO_IPV4, |
266 | .hooknum = NF_INET_LOCAL_OUT, | 255 | .hooknum = NF_INET_LOCAL_OUT, |
@@ -268,7 +257,7 @@ static struct nf_hook_ops nf_nat_ops[] __read_mostly = { | |||
268 | }, | 257 | }, |
269 | /* After packet filtering, change source */ | 258 | /* After packet filtering, change source */ |
270 | { | 259 | { |
271 | .hook = nf_nat_fn, | 260 | .hook = nf_nat_ipv4_fn, |
272 | .owner = THIS_MODULE, | 261 | .owner = THIS_MODULE, |
273 | .pf = NFPROTO_IPV4, | 262 | .pf = NFPROTO_IPV4, |
274 | .hooknum = NF_INET_LOCAL_IN, | 263 | .hooknum = NF_INET_LOCAL_IN, |
@@ -276,51 +265,56 @@ static struct nf_hook_ops nf_nat_ops[] __read_mostly = { | |||
276 | }, | 265 | }, |
277 | }; | 266 | }; |
278 | 267 | ||
279 | static int __init nf_nat_standalone_init(void) | 268 | static int __net_init iptable_nat_net_init(struct net *net) |
280 | { | 269 | { |
281 | int ret = 0; | 270 | struct ipt_replace *repl; |
271 | |||
272 | repl = ipt_alloc_initial_table(&nf_nat_ipv4_table); | ||
273 | if (repl == NULL) | ||
274 | return -ENOMEM; | ||
275 | net->ipv4.nat_table = ipt_register_table(net, &nf_nat_ipv4_table, repl); | ||
276 | kfree(repl); | ||
277 | if (IS_ERR(net->ipv4.nat_table)) | ||
278 | return PTR_ERR(net->ipv4.nat_table); | ||
279 | return 0; | ||
280 | } | ||
282 | 281 | ||
283 | need_ipv4_conntrack(); | 282 | static void __net_exit iptable_nat_net_exit(struct net *net) |
283 | { | ||
284 | ipt_unregister_table(net, net->ipv4.nat_table); | ||
285 | } | ||
284 | 286 | ||
285 | #ifdef CONFIG_XFRM | 287 | static struct pernet_operations iptable_nat_net_ops = { |
286 | BUG_ON(ip_nat_decode_session != NULL); | 288 | .init = iptable_nat_net_init, |
287 | RCU_INIT_POINTER(ip_nat_decode_session, nat_decode_session); | 289 | .exit = iptable_nat_net_exit, |
288 | #endif | 290 | }; |
289 | ret = nf_nat_rule_init(); | ||
290 | if (ret < 0) { | ||
291 | pr_err("nf_nat_init: can't setup rules.\n"); | ||
292 | goto cleanup_decode_session; | ||
293 | } | ||
294 | ret = nf_register_hooks(nf_nat_ops, ARRAY_SIZE(nf_nat_ops)); | ||
295 | if (ret < 0) { | ||
296 | pr_err("nf_nat_init: can't register hooks.\n"); | ||
297 | goto cleanup_rule_init; | ||
298 | } | ||
299 | return ret; | ||
300 | 291 | ||
301 | cleanup_rule_init: | 292 | static int __init iptable_nat_init(void) |
302 | nf_nat_rule_cleanup(); | 293 | { |
303 | cleanup_decode_session: | 294 | int err; |
304 | #ifdef CONFIG_XFRM | 295 | |
305 | RCU_INIT_POINTER(ip_nat_decode_session, NULL); | 296 | err = register_pernet_subsys(&iptable_nat_net_ops); |
306 | synchronize_net(); | 297 | if (err < 0) |
307 | #endif | 298 | goto err1; |
308 | return ret; | 299 | |
300 | err = nf_register_hooks(nf_nat_ipv4_ops, ARRAY_SIZE(nf_nat_ipv4_ops)); | ||
301 | if (err < 0) | ||
302 | goto err2; | ||
303 | return 0; | ||
304 | |||
305 | err2: | ||
306 | unregister_pernet_subsys(&iptable_nat_net_ops); | ||
307 | err1: | ||
308 | return err; | ||
309 | } | 309 | } |
310 | 310 | ||
311 | static void __exit nf_nat_standalone_fini(void) | 311 | static void __exit iptable_nat_exit(void) |
312 | { | 312 | { |
313 | nf_unregister_hooks(nf_nat_ops, ARRAY_SIZE(nf_nat_ops)); | 313 | nf_unregister_hooks(nf_nat_ipv4_ops, ARRAY_SIZE(nf_nat_ipv4_ops)); |
314 | nf_nat_rule_cleanup(); | 314 | unregister_pernet_subsys(&iptable_nat_net_ops); |
315 | #ifdef CONFIG_XFRM | ||
316 | RCU_INIT_POINTER(ip_nat_decode_session, NULL); | ||
317 | synchronize_net(); | ||
318 | #endif | ||
319 | /* Conntrack caches are unregistered in nf_conntrack_cleanup */ | ||
320 | } | 315 | } |
321 | 316 | ||
322 | module_init(nf_nat_standalone_init); | 317 | module_init(iptable_nat_init); |
323 | module_exit(nf_nat_standalone_fini); | 318 | module_exit(iptable_nat_exit); |
324 | 319 | ||
325 | MODULE_LICENSE("GPL"); | 320 | MODULE_LICENSE("GPL"); |
326 | MODULE_ALIAS("ip_nat"); | ||
diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c index 07fb710cd722..03d9696d3c6e 100644 --- a/net/ipv4/netfilter/iptable_raw.c +++ b/net/ipv4/netfilter/iptable_raw.c | |||
@@ -48,9 +48,7 @@ static int __net_init iptable_raw_net_init(struct net *net) | |||
48 | net->ipv4.iptable_raw = | 48 | net->ipv4.iptable_raw = |
49 | ipt_register_table(net, &packet_raw, repl); | 49 | ipt_register_table(net, &packet_raw, repl); |
50 | kfree(repl); | 50 | kfree(repl); |
51 | if (IS_ERR(net->ipv4.iptable_raw)) | 51 | return PTR_RET(net->ipv4.iptable_raw); |
52 | return PTR_ERR(net->ipv4.iptable_raw); | ||
53 | return 0; | ||
54 | } | 52 | } |
55 | 53 | ||
56 | static void __net_exit iptable_raw_net_exit(struct net *net) | 54 | static void __net_exit iptable_raw_net_exit(struct net *net) |
@@ -75,14 +73,10 @@ static int __init iptable_raw_init(void) | |||
75 | rawtable_ops = xt_hook_link(&packet_raw, iptable_raw_hook); | 73 | rawtable_ops = xt_hook_link(&packet_raw, iptable_raw_hook); |
76 | if (IS_ERR(rawtable_ops)) { | 74 | if (IS_ERR(rawtable_ops)) { |
77 | ret = PTR_ERR(rawtable_ops); | 75 | ret = PTR_ERR(rawtable_ops); |
78 | goto cleanup_table; | 76 | unregister_pernet_subsys(&iptable_raw_net_ops); |
79 | } | 77 | } |
80 | 78 | ||
81 | return ret; | 79 | return ret; |
82 | |||
83 | cleanup_table: | ||
84 | unregister_pernet_subsys(&iptable_raw_net_ops); | ||
85 | return ret; | ||
86 | } | 80 | } |
87 | 81 | ||
88 | static void __exit iptable_raw_fini(void) | 82 | static void __exit iptable_raw_fini(void) |
diff --git a/net/ipv4/netfilter/iptable_security.c b/net/ipv4/netfilter/iptable_security.c index be45bdc4c602..b283d8e2601a 100644 --- a/net/ipv4/netfilter/iptable_security.c +++ b/net/ipv4/netfilter/iptable_security.c | |||
@@ -66,10 +66,7 @@ static int __net_init iptable_security_net_init(struct net *net) | |||
66 | net->ipv4.iptable_security = | 66 | net->ipv4.iptable_security = |
67 | ipt_register_table(net, &security_table, repl); | 67 | ipt_register_table(net, &security_table, repl); |
68 | kfree(repl); | 68 | kfree(repl); |
69 | if (IS_ERR(net->ipv4.iptable_security)) | 69 | return PTR_RET(net->ipv4.iptable_security); |
70 | return PTR_ERR(net->ipv4.iptable_security); | ||
71 | |||
72 | return 0; | ||
73 | } | 70 | } |
74 | 71 | ||
75 | static void __net_exit iptable_security_net_exit(struct net *net) | 72 | static void __net_exit iptable_security_net_exit(struct net *net) |
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index e7ff2dcab6ce..fcdd0c2406e6 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | |||
@@ -29,11 +29,6 @@ | |||
29 | #include <net/netfilter/ipv4/nf_defrag_ipv4.h> | 29 | #include <net/netfilter/ipv4/nf_defrag_ipv4.h> |
30 | #include <net/netfilter/nf_log.h> | 30 | #include <net/netfilter/nf_log.h> |
31 | 31 | ||
32 | int (*nf_nat_seq_adjust_hook)(struct sk_buff *skb, | ||
33 | struct nf_conn *ct, | ||
34 | enum ip_conntrack_info ctinfo); | ||
35 | EXPORT_SYMBOL_GPL(nf_nat_seq_adjust_hook); | ||
36 | |||
37 | static bool ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, | 32 | static bool ipv4_pkt_to_tuple(const struct sk_buff *skb, unsigned int nhoff, |
38 | struct nf_conntrack_tuple *tuple) | 33 | struct nf_conntrack_tuple *tuple) |
39 | { | 34 | { |
@@ -149,7 +144,8 @@ static unsigned int ipv4_confirm(unsigned int hooknum, | |||
149 | typeof(nf_nat_seq_adjust_hook) seq_adjust; | 144 | typeof(nf_nat_seq_adjust_hook) seq_adjust; |
150 | 145 | ||
151 | seq_adjust = rcu_dereference(nf_nat_seq_adjust_hook); | 146 | seq_adjust = rcu_dereference(nf_nat_seq_adjust_hook); |
152 | if (!seq_adjust || !seq_adjust(skb, ct, ctinfo)) { | 147 | if (!seq_adjust || |
148 | !seq_adjust(skb, ct, ctinfo, ip_hdrlen(skb))) { | ||
153 | NF_CT_STAT_INC_ATOMIC(nf_ct_net(ct), drop); | 149 | NF_CT_STAT_INC_ATOMIC(nf_ct_net(ct), drop); |
154 | return NF_DROP; | 150 | return NF_DROP; |
155 | } | 151 | } |
diff --git a/net/ipv4/netfilter/nf_nat_h323.c b/net/ipv4/netfilter/nf_nat_h323.c index c6784a18c1c4..9c3db10b22d3 100644 --- a/net/ipv4/netfilter/nf_nat_h323.c +++ b/net/ipv4/netfilter/nf_nat_h323.c | |||
@@ -15,13 +15,12 @@ | |||
15 | 15 | ||
16 | #include <net/netfilter/nf_nat.h> | 16 | #include <net/netfilter/nf_nat.h> |
17 | #include <net/netfilter/nf_nat_helper.h> | 17 | #include <net/netfilter/nf_nat_helper.h> |
18 | #include <net/netfilter/nf_nat_rule.h> | ||
19 | #include <net/netfilter/nf_conntrack_helper.h> | 18 | #include <net/netfilter/nf_conntrack_helper.h> |
20 | #include <net/netfilter/nf_conntrack_expect.h> | 19 | #include <net/netfilter/nf_conntrack_expect.h> |
21 | #include <linux/netfilter/nf_conntrack_h323.h> | 20 | #include <linux/netfilter/nf_conntrack_h323.h> |
22 | 21 | ||
23 | /****************************************************************************/ | 22 | /****************************************************************************/ |
24 | static int set_addr(struct sk_buff *skb, | 23 | static int set_addr(struct sk_buff *skb, unsigned int protoff, |
25 | unsigned char **data, int dataoff, | 24 | unsigned char **data, int dataoff, |
26 | unsigned int addroff, __be32 ip, __be16 port) | 25 | unsigned int addroff, __be32 ip, __be16 port) |
27 | { | 26 | { |
@@ -40,7 +39,7 @@ static int set_addr(struct sk_buff *skb, | |||
40 | 39 | ||
41 | if (ip_hdr(skb)->protocol == IPPROTO_TCP) { | 40 | if (ip_hdr(skb)->protocol == IPPROTO_TCP) { |
42 | if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, | 41 | if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, |
43 | addroff, sizeof(buf), | 42 | protoff, addroff, sizeof(buf), |
44 | (char *) &buf, sizeof(buf))) { | 43 | (char *) &buf, sizeof(buf))) { |
45 | net_notice_ratelimited("nf_nat_h323: nf_nat_mangle_tcp_packet error\n"); | 44 | net_notice_ratelimited("nf_nat_h323: nf_nat_mangle_tcp_packet error\n"); |
46 | return -1; | 45 | return -1; |
@@ -54,7 +53,7 @@ static int set_addr(struct sk_buff *skb, | |||
54 | *data = skb->data + ip_hdrlen(skb) + th->doff * 4 + dataoff; | 53 | *data = skb->data + ip_hdrlen(skb) + th->doff * 4 + dataoff; |
55 | } else { | 54 | } else { |
56 | if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, | 55 | if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, |
57 | addroff, sizeof(buf), | 56 | protoff, addroff, sizeof(buf), |
58 | (char *) &buf, sizeof(buf))) { | 57 | (char *) &buf, sizeof(buf))) { |
59 | net_notice_ratelimited("nf_nat_h323: nf_nat_mangle_udp_packet error\n"); | 58 | net_notice_ratelimited("nf_nat_h323: nf_nat_mangle_udp_packet error\n"); |
60 | return -1; | 59 | return -1; |
@@ -69,22 +68,22 @@ static int set_addr(struct sk_buff *skb, | |||
69 | } | 68 | } |
70 | 69 | ||
71 | /****************************************************************************/ | 70 | /****************************************************************************/ |
72 | static int set_h225_addr(struct sk_buff *skb, | 71 | static int set_h225_addr(struct sk_buff *skb, unsigned int protoff, |
73 | unsigned char **data, int dataoff, | 72 | unsigned char **data, int dataoff, |
74 | TransportAddress *taddr, | 73 | TransportAddress *taddr, |
75 | union nf_inet_addr *addr, __be16 port) | 74 | union nf_inet_addr *addr, __be16 port) |
76 | { | 75 | { |
77 | return set_addr(skb, data, dataoff, taddr->ipAddress.ip, | 76 | return set_addr(skb, protoff, data, dataoff, taddr->ipAddress.ip, |
78 | addr->ip, port); | 77 | addr->ip, port); |
79 | } | 78 | } |
80 | 79 | ||
81 | /****************************************************************************/ | 80 | /****************************************************************************/ |
82 | static int set_h245_addr(struct sk_buff *skb, | 81 | static int set_h245_addr(struct sk_buff *skb, unsigned protoff, |
83 | unsigned char **data, int dataoff, | 82 | unsigned char **data, int dataoff, |
84 | H245_TransportAddress *taddr, | 83 | H245_TransportAddress *taddr, |
85 | union nf_inet_addr *addr, __be16 port) | 84 | union nf_inet_addr *addr, __be16 port) |
86 | { | 85 | { |
87 | return set_addr(skb, data, dataoff, | 86 | return set_addr(skb, protoff, data, dataoff, |
88 | taddr->unicastAddress.iPAddress.network, | 87 | taddr->unicastAddress.iPAddress.network, |
89 | addr->ip, port); | 88 | addr->ip, port); |
90 | } | 89 | } |
@@ -92,7 +91,7 @@ static int set_h245_addr(struct sk_buff *skb, | |||
92 | /****************************************************************************/ | 91 | /****************************************************************************/ |
93 | static int set_sig_addr(struct sk_buff *skb, struct nf_conn *ct, | 92 | static int set_sig_addr(struct sk_buff *skb, struct nf_conn *ct, |
94 | enum ip_conntrack_info ctinfo, | 93 | enum ip_conntrack_info ctinfo, |
95 | unsigned char **data, | 94 | unsigned int protoff, unsigned char **data, |
96 | TransportAddress *taddr, int count) | 95 | TransportAddress *taddr, int count) |
97 | { | 96 | { |
98 | const struct nf_ct_h323_master *info = nfct_help_data(ct); | 97 | const struct nf_ct_h323_master *info = nfct_help_data(ct); |
@@ -118,7 +117,8 @@ static int set_sig_addr(struct sk_buff *skb, struct nf_conn *ct, | |||
118 | &addr.ip, port, | 117 | &addr.ip, port, |
119 | &ct->tuplehash[!dir].tuple.dst.u3.ip, | 118 | &ct->tuplehash[!dir].tuple.dst.u3.ip, |
120 | info->sig_port[!dir]); | 119 | info->sig_port[!dir]); |
121 | return set_h225_addr(skb, data, 0, &taddr[i], | 120 | return set_h225_addr(skb, protoff, data, 0, |
121 | &taddr[i], | ||
122 | &ct->tuplehash[!dir]. | 122 | &ct->tuplehash[!dir]. |
123 | tuple.dst.u3, | 123 | tuple.dst.u3, |
124 | info->sig_port[!dir]); | 124 | info->sig_port[!dir]); |
@@ -129,7 +129,8 @@ static int set_sig_addr(struct sk_buff *skb, struct nf_conn *ct, | |||
129 | &addr.ip, port, | 129 | &addr.ip, port, |
130 | &ct->tuplehash[!dir].tuple.src.u3.ip, | 130 | &ct->tuplehash[!dir].tuple.src.u3.ip, |
131 | info->sig_port[!dir]); | 131 | info->sig_port[!dir]); |
132 | return set_h225_addr(skb, data, 0, &taddr[i], | 132 | return set_h225_addr(skb, protoff, data, 0, |
133 | &taddr[i], | ||
133 | &ct->tuplehash[!dir]. | 134 | &ct->tuplehash[!dir]. |
134 | tuple.src.u3, | 135 | tuple.src.u3, |
135 | info->sig_port[!dir]); | 136 | info->sig_port[!dir]); |
@@ -143,7 +144,7 @@ static int set_sig_addr(struct sk_buff *skb, struct nf_conn *ct, | |||
143 | /****************************************************************************/ | 144 | /****************************************************************************/ |
144 | static int set_ras_addr(struct sk_buff *skb, struct nf_conn *ct, | 145 | static int set_ras_addr(struct sk_buff *skb, struct nf_conn *ct, |
145 | enum ip_conntrack_info ctinfo, | 146 | enum ip_conntrack_info ctinfo, |
146 | unsigned char **data, | 147 | unsigned int protoff, unsigned char **data, |
147 | TransportAddress *taddr, int count) | 148 | TransportAddress *taddr, int count) |
148 | { | 149 | { |
149 | int dir = CTINFO2DIR(ctinfo); | 150 | int dir = CTINFO2DIR(ctinfo); |
@@ -159,7 +160,7 @@ static int set_ras_addr(struct sk_buff *skb, struct nf_conn *ct, | |||
159 | &addr.ip, ntohs(port), | 160 | &addr.ip, ntohs(port), |
160 | &ct->tuplehash[!dir].tuple.dst.u3.ip, | 161 | &ct->tuplehash[!dir].tuple.dst.u3.ip, |
161 | ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port)); | 162 | ntohs(ct->tuplehash[!dir].tuple.dst.u.udp.port)); |
162 | return set_h225_addr(skb, data, 0, &taddr[i], | 163 | return set_h225_addr(skb, protoff, data, 0, &taddr[i], |
163 | &ct->tuplehash[!dir].tuple.dst.u3, | 164 | &ct->tuplehash[!dir].tuple.dst.u3, |
164 | ct->tuplehash[!dir].tuple. | 165 | ct->tuplehash[!dir].tuple. |
165 | dst.u.udp.port); | 166 | dst.u.udp.port); |
@@ -172,7 +173,7 @@ static int set_ras_addr(struct sk_buff *skb, struct nf_conn *ct, | |||
172 | /****************************************************************************/ | 173 | /****************************************************************************/ |
173 | static int nat_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct, | 174 | static int nat_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct, |
174 | enum ip_conntrack_info ctinfo, | 175 | enum ip_conntrack_info ctinfo, |
175 | unsigned char **data, int dataoff, | 176 | unsigned int protoff, unsigned char **data, int dataoff, |
176 | H245_TransportAddress *taddr, | 177 | H245_TransportAddress *taddr, |
177 | __be16 port, __be16 rtp_port, | 178 | __be16 port, __be16 rtp_port, |
178 | struct nf_conntrack_expect *rtp_exp, | 179 | struct nf_conntrack_expect *rtp_exp, |
@@ -244,7 +245,7 @@ static int nat_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct, | |||
244 | } | 245 | } |
245 | 246 | ||
246 | /* Modify signal */ | 247 | /* Modify signal */ |
247 | if (set_h245_addr(skb, data, dataoff, taddr, | 248 | if (set_h245_addr(skb, protoff, data, dataoff, taddr, |
248 | &ct->tuplehash[!dir].tuple.dst.u3, | 249 | &ct->tuplehash[!dir].tuple.dst.u3, |
249 | htons((port & htons(1)) ? nated_port + 1 : | 250 | htons((port & htons(1)) ? nated_port + 1 : |
250 | nated_port)) == 0) { | 251 | nated_port)) == 0) { |
@@ -275,7 +276,7 @@ static int nat_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct, | |||
275 | /****************************************************************************/ | 276 | /****************************************************************************/ |
276 | static int nat_t120(struct sk_buff *skb, struct nf_conn *ct, | 277 | static int nat_t120(struct sk_buff *skb, struct nf_conn *ct, |
277 | enum ip_conntrack_info ctinfo, | 278 | enum ip_conntrack_info ctinfo, |
278 | unsigned char **data, int dataoff, | 279 | unsigned int protoff, unsigned char **data, int dataoff, |
279 | H245_TransportAddress *taddr, __be16 port, | 280 | H245_TransportAddress *taddr, __be16 port, |
280 | struct nf_conntrack_expect *exp) | 281 | struct nf_conntrack_expect *exp) |
281 | { | 282 | { |
@@ -307,7 +308,7 @@ static int nat_t120(struct sk_buff *skb, struct nf_conn *ct, | |||
307 | } | 308 | } |
308 | 309 | ||
309 | /* Modify signal */ | 310 | /* Modify signal */ |
310 | if (set_h245_addr(skb, data, dataoff, taddr, | 311 | if (set_h245_addr(skb, protoff, data, dataoff, taddr, |
311 | &ct->tuplehash[!dir].tuple.dst.u3, | 312 | &ct->tuplehash[!dir].tuple.dst.u3, |
312 | htons(nated_port)) < 0) { | 313 | htons(nated_port)) < 0) { |
313 | nf_ct_unexpect_related(exp); | 314 | nf_ct_unexpect_related(exp); |
@@ -326,7 +327,7 @@ static int nat_t120(struct sk_buff *skb, struct nf_conn *ct, | |||
326 | /****************************************************************************/ | 327 | /****************************************************************************/ |
327 | static int nat_h245(struct sk_buff *skb, struct nf_conn *ct, | 328 | static int nat_h245(struct sk_buff *skb, struct nf_conn *ct, |
328 | enum ip_conntrack_info ctinfo, | 329 | enum ip_conntrack_info ctinfo, |
329 | unsigned char **data, int dataoff, | 330 | unsigned int protoff, unsigned char **data, int dataoff, |
330 | TransportAddress *taddr, __be16 port, | 331 | TransportAddress *taddr, __be16 port, |
331 | struct nf_conntrack_expect *exp) | 332 | struct nf_conntrack_expect *exp) |
332 | { | 333 | { |
@@ -363,7 +364,7 @@ static int nat_h245(struct sk_buff *skb, struct nf_conn *ct, | |||
363 | } | 364 | } |
364 | 365 | ||
365 | /* Modify signal */ | 366 | /* Modify signal */ |
366 | if (set_h225_addr(skb, data, dataoff, taddr, | 367 | if (set_h225_addr(skb, protoff, data, dataoff, taddr, |
367 | &ct->tuplehash[!dir].tuple.dst.u3, | 368 | &ct->tuplehash[!dir].tuple.dst.u3, |
368 | htons(nated_port)) == 0) { | 369 | htons(nated_port)) == 0) { |
369 | /* Save ports */ | 370 | /* Save ports */ |
@@ -390,7 +391,7 @@ static int nat_h245(struct sk_buff *skb, struct nf_conn *ct, | |||
390 | static void ip_nat_q931_expect(struct nf_conn *new, | 391 | static void ip_nat_q931_expect(struct nf_conn *new, |
391 | struct nf_conntrack_expect *this) | 392 | struct nf_conntrack_expect *this) |
392 | { | 393 | { |
393 | struct nf_nat_ipv4_range range; | 394 | struct nf_nat_range range; |
394 | 395 | ||
395 | if (this->tuple.src.u3.ip != 0) { /* Only accept calls from GK */ | 396 | if (this->tuple.src.u3.ip != 0) { /* Only accept calls from GK */ |
396 | nf_nat_follow_master(new, this); | 397 | nf_nat_follow_master(new, this); |
@@ -402,21 +403,23 @@ static void ip_nat_q931_expect(struct nf_conn *new, | |||
402 | 403 | ||
403 | /* Change src to where master sends to */ | 404 | /* Change src to where master sends to */ |
404 | range.flags = NF_NAT_RANGE_MAP_IPS; | 405 | range.flags = NF_NAT_RANGE_MAP_IPS; |
405 | range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.u3.ip; | 406 | range.min_addr = range.max_addr = |
407 | new->tuplehash[!this->dir].tuple.src.u3; | ||
406 | nf_nat_setup_info(new, &range, NF_NAT_MANIP_SRC); | 408 | nf_nat_setup_info(new, &range, NF_NAT_MANIP_SRC); |
407 | 409 | ||
408 | /* For DST manip, map port here to where it's expected. */ | 410 | /* For DST manip, map port here to where it's expected. */ |
409 | range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED); | 411 | range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED); |
410 | range.min = range.max = this->saved_proto; | 412 | range.min_proto = range.max_proto = this->saved_proto; |
411 | range.min_ip = range.max_ip = | 413 | range.min_addr = range.max_addr = |
412 | new->master->tuplehash[!this->dir].tuple.src.u3.ip; | 414 | new->master->tuplehash[!this->dir].tuple.src.u3; |
413 | nf_nat_setup_info(new, &range, NF_NAT_MANIP_DST); | 415 | nf_nat_setup_info(new, &range, NF_NAT_MANIP_DST); |
414 | } | 416 | } |
415 | 417 | ||
416 | /****************************************************************************/ | 418 | /****************************************************************************/ |
417 | static int nat_q931(struct sk_buff *skb, struct nf_conn *ct, | 419 | static int nat_q931(struct sk_buff *skb, struct nf_conn *ct, |
418 | enum ip_conntrack_info ctinfo, | 420 | enum ip_conntrack_info ctinfo, |
419 | unsigned char **data, TransportAddress *taddr, int idx, | 421 | unsigned int protoff, unsigned char **data, |
422 | TransportAddress *taddr, int idx, | ||
420 | __be16 port, struct nf_conntrack_expect *exp) | 423 | __be16 port, struct nf_conntrack_expect *exp) |
421 | { | 424 | { |
422 | struct nf_ct_h323_master *info = nfct_help_data(ct); | 425 | struct nf_ct_h323_master *info = nfct_help_data(ct); |
@@ -453,7 +456,7 @@ static int nat_q931(struct sk_buff *skb, struct nf_conn *ct, | |||
453 | } | 456 | } |
454 | 457 | ||
455 | /* Modify signal */ | 458 | /* Modify signal */ |
456 | if (set_h225_addr(skb, data, 0, &taddr[idx], | 459 | if (set_h225_addr(skb, protoff, data, 0, &taddr[idx], |
457 | &ct->tuplehash[!dir].tuple.dst.u3, | 460 | &ct->tuplehash[!dir].tuple.dst.u3, |
458 | htons(nated_port)) == 0) { | 461 | htons(nated_port)) == 0) { |
459 | /* Save ports */ | 462 | /* Save ports */ |
@@ -464,7 +467,7 @@ static int nat_q931(struct sk_buff *skb, struct nf_conn *ct, | |||
464 | if (idx > 0 && | 467 | if (idx > 0 && |
465 | get_h225_addr(ct, *data, &taddr[0], &addr, &port) && | 468 | get_h225_addr(ct, *data, &taddr[0], &addr, &port) && |
466 | (ntohl(addr.ip) & 0xff000000) == 0x7f000000) { | 469 | (ntohl(addr.ip) & 0xff000000) == 0x7f000000) { |
467 | set_h225_addr(skb, data, 0, &taddr[0], | 470 | set_h225_addr(skb, protoff, data, 0, &taddr[0], |
468 | &ct->tuplehash[!dir].tuple.dst.u3, | 471 | &ct->tuplehash[!dir].tuple.dst.u3, |
469 | info->sig_port[!dir]); | 472 | info->sig_port[!dir]); |
470 | } | 473 | } |
@@ -487,26 +490,28 @@ static int nat_q931(struct sk_buff *skb, struct nf_conn *ct, | |||
487 | static void ip_nat_callforwarding_expect(struct nf_conn *new, | 490 | static void ip_nat_callforwarding_expect(struct nf_conn *new, |
488 | struct nf_conntrack_expect *this) | 491 | struct nf_conntrack_expect *this) |
489 | { | 492 | { |
490 | struct nf_nat_ipv4_range range; | 493 | struct nf_nat_range range; |
491 | 494 | ||
492 | /* This must be a fresh one. */ | 495 | /* This must be a fresh one. */ |
493 | BUG_ON(new->status & IPS_NAT_DONE_MASK); | 496 | BUG_ON(new->status & IPS_NAT_DONE_MASK); |
494 | 497 | ||
495 | /* Change src to where master sends to */ | 498 | /* Change src to where master sends to */ |
496 | range.flags = NF_NAT_RANGE_MAP_IPS; | 499 | range.flags = NF_NAT_RANGE_MAP_IPS; |
497 | range.min_ip = range.max_ip = new->tuplehash[!this->dir].tuple.src.u3.ip; | 500 | range.min_addr = range.max_addr = |
501 | new->tuplehash[!this->dir].tuple.src.u3; | ||
498 | nf_nat_setup_info(new, &range, NF_NAT_MANIP_SRC); | 502 | nf_nat_setup_info(new, &range, NF_NAT_MANIP_SRC); |
499 | 503 | ||
500 | /* For DST manip, map port here to where it's expected. */ | 504 | /* For DST manip, map port here to where it's expected. */ |
501 | range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED); | 505 | range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED); |
502 | range.min = range.max = this->saved_proto; | 506 | range.min_proto = range.max_proto = this->saved_proto; |
503 | range.min_ip = range.max_ip = this->saved_ip; | 507 | range.min_addr = range.max_addr = this->saved_addr; |
504 | nf_nat_setup_info(new, &range, NF_NAT_MANIP_DST); | 508 | nf_nat_setup_info(new, &range, NF_NAT_MANIP_DST); |
505 | } | 509 | } |
506 | 510 | ||
507 | /****************************************************************************/ | 511 | /****************************************************************************/ |
508 | static int nat_callforwarding(struct sk_buff *skb, struct nf_conn *ct, | 512 | static int nat_callforwarding(struct sk_buff *skb, struct nf_conn *ct, |
509 | enum ip_conntrack_info ctinfo, | 513 | enum ip_conntrack_info ctinfo, |
514 | unsigned int protoff, | ||
510 | unsigned char **data, int dataoff, | 515 | unsigned char **data, int dataoff, |
511 | TransportAddress *taddr, __be16 port, | 516 | TransportAddress *taddr, __be16 port, |
512 | struct nf_conntrack_expect *exp) | 517 | struct nf_conntrack_expect *exp) |
@@ -515,7 +520,7 @@ static int nat_callforwarding(struct sk_buff *skb, struct nf_conn *ct, | |||
515 | u_int16_t nated_port; | 520 | u_int16_t nated_port; |
516 | 521 | ||
517 | /* Set expectations for NAT */ | 522 | /* Set expectations for NAT */ |
518 | exp->saved_ip = exp->tuple.dst.u3.ip; | 523 | exp->saved_addr = exp->tuple.dst.u3; |
519 | exp->tuple.dst.u3.ip = ct->tuplehash[!dir].tuple.dst.u3.ip; | 524 | exp->tuple.dst.u3.ip = ct->tuplehash[!dir].tuple.dst.u3.ip; |
520 | exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port; | 525 | exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port; |
521 | exp->expectfn = ip_nat_callforwarding_expect; | 526 | exp->expectfn = ip_nat_callforwarding_expect; |
@@ -541,7 +546,7 @@ static int nat_callforwarding(struct sk_buff *skb, struct nf_conn *ct, | |||
541 | } | 546 | } |
542 | 547 | ||
543 | /* Modify signal */ | 548 | /* Modify signal */ |
544 | if (!set_h225_addr(skb, data, dataoff, taddr, | 549 | if (!set_h225_addr(skb, protoff, data, dataoff, taddr, |
545 | &ct->tuplehash[!dir].tuple.dst.u3, | 550 | &ct->tuplehash[!dir].tuple.dst.u3, |
546 | htons(nated_port)) == 0) { | 551 | htons(nated_port)) == 0) { |
547 | nf_ct_unexpect_related(exp); | 552 | nf_ct_unexpect_related(exp); |
diff --git a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c new file mode 100644 index 000000000000..d8b2e14efddc --- /dev/null +++ b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c | |||
@@ -0,0 +1,281 @@ | |||
1 | /* | ||
2 | * (C) 1999-2001 Paul `Rusty' Russell | ||
3 | * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org> | ||
4 | * (C) 2011 Patrick McHardy <kaber@trash.net> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/types.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/skbuff.h> | ||
14 | #include <linux/ip.h> | ||
15 | #include <linux/icmp.h> | ||
16 | #include <linux/netfilter.h> | ||
17 | #include <linux/netfilter_ipv4.h> | ||
18 | #include <net/secure_seq.h> | ||
19 | #include <net/checksum.h> | ||
20 | #include <net/route.h> | ||
21 | #include <net/ip.h> | ||
22 | |||
23 | #include <net/netfilter/nf_conntrack_core.h> | ||
24 | #include <net/netfilter/nf_conntrack.h> | ||
25 | #include <net/netfilter/nf_nat_core.h> | ||
26 | #include <net/netfilter/nf_nat_l3proto.h> | ||
27 | #include <net/netfilter/nf_nat_l4proto.h> | ||
28 | |||
29 | static const struct nf_nat_l3proto nf_nat_l3proto_ipv4; | ||
30 | |||
31 | #ifdef CONFIG_XFRM | ||
32 | static void nf_nat_ipv4_decode_session(struct sk_buff *skb, | ||
33 | const struct nf_conn *ct, | ||
34 | enum ip_conntrack_dir dir, | ||
35 | unsigned long statusbit, | ||
36 | struct flowi *fl) | ||
37 | { | ||
38 | const struct nf_conntrack_tuple *t = &ct->tuplehash[dir].tuple; | ||
39 | struct flowi4 *fl4 = &fl->u.ip4; | ||
40 | |||
41 | if (ct->status & statusbit) { | ||
42 | fl4->daddr = t->dst.u3.ip; | ||
43 | if (t->dst.protonum == IPPROTO_TCP || | ||
44 | t->dst.protonum == IPPROTO_UDP || | ||
45 | t->dst.protonum == IPPROTO_UDPLITE || | ||
46 | t->dst.protonum == IPPROTO_DCCP || | ||
47 | t->dst.protonum == IPPROTO_SCTP) | ||
48 | fl4->fl4_dport = t->dst.u.all; | ||
49 | } | ||
50 | |||
51 | statusbit ^= IPS_NAT_MASK; | ||
52 | |||
53 | if (ct->status & statusbit) { | ||
54 | fl4->saddr = t->src.u3.ip; | ||
55 | if (t->dst.protonum == IPPROTO_TCP || | ||
56 | t->dst.protonum == IPPROTO_UDP || | ||
57 | t->dst.protonum == IPPROTO_UDPLITE || | ||
58 | t->dst.protonum == IPPROTO_DCCP || | ||
59 | t->dst.protonum == IPPROTO_SCTP) | ||
60 | fl4->fl4_sport = t->src.u.all; | ||
61 | } | ||
62 | } | ||
63 | #endif /* CONFIG_XFRM */ | ||
64 | |||
65 | static bool nf_nat_ipv4_in_range(const struct nf_conntrack_tuple *t, | ||
66 | const struct nf_nat_range *range) | ||
67 | { | ||
68 | return ntohl(t->src.u3.ip) >= ntohl(range->min_addr.ip) && | ||
69 | ntohl(t->src.u3.ip) <= ntohl(range->max_addr.ip); | ||
70 | } | ||
71 | |||
72 | static u32 nf_nat_ipv4_secure_port(const struct nf_conntrack_tuple *t, | ||
73 | __be16 dport) | ||
74 | { | ||
75 | return secure_ipv4_port_ephemeral(t->src.u3.ip, t->dst.u3.ip, dport); | ||
76 | } | ||
77 | |||
78 | static bool nf_nat_ipv4_manip_pkt(struct sk_buff *skb, | ||
79 | unsigned int iphdroff, | ||
80 | const struct nf_nat_l4proto *l4proto, | ||
81 | const struct nf_conntrack_tuple *target, | ||
82 | enum nf_nat_manip_type maniptype) | ||
83 | { | ||
84 | struct iphdr *iph; | ||
85 | unsigned int hdroff; | ||
86 | |||
87 | if (!skb_make_writable(skb, iphdroff + sizeof(*iph))) | ||
88 | return false; | ||
89 | |||
90 | iph = (void *)skb->data + iphdroff; | ||
91 | hdroff = iphdroff + iph->ihl * 4; | ||
92 | |||
93 | if (!l4proto->manip_pkt(skb, &nf_nat_l3proto_ipv4, iphdroff, hdroff, | ||
94 | target, maniptype)) | ||
95 | return false; | ||
96 | iph = (void *)skb->data + iphdroff; | ||
97 | |||
98 | if (maniptype == NF_NAT_MANIP_SRC) { | ||
99 | csum_replace4(&iph->check, iph->saddr, target->src.u3.ip); | ||
100 | iph->saddr = target->src.u3.ip; | ||
101 | } else { | ||
102 | csum_replace4(&iph->check, iph->daddr, target->dst.u3.ip); | ||
103 | iph->daddr = target->dst.u3.ip; | ||
104 | } | ||
105 | return true; | ||
106 | } | ||
107 | |||
108 | static void nf_nat_ipv4_csum_update(struct sk_buff *skb, | ||
109 | unsigned int iphdroff, __sum16 *check, | ||
110 | const struct nf_conntrack_tuple *t, | ||
111 | enum nf_nat_manip_type maniptype) | ||
112 | { | ||
113 | struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff); | ||
114 | __be32 oldip, newip; | ||
115 | |||
116 | if (maniptype == NF_NAT_MANIP_SRC) { | ||
117 | oldip = iph->saddr; | ||
118 | newip = t->src.u3.ip; | ||
119 | } else { | ||
120 | oldip = iph->daddr; | ||
121 | newip = t->dst.u3.ip; | ||
122 | } | ||
123 | inet_proto_csum_replace4(check, skb, oldip, newip, 1); | ||
124 | } | ||
125 | |||
126 | static void nf_nat_ipv4_csum_recalc(struct sk_buff *skb, | ||
127 | u8 proto, void *data, __sum16 *check, | ||
128 | int datalen, int oldlen) | ||
129 | { | ||
130 | const struct iphdr *iph = ip_hdr(skb); | ||
131 | struct rtable *rt = skb_rtable(skb); | ||
132 | |||
133 | if (skb->ip_summed != CHECKSUM_PARTIAL) { | ||
134 | if (!(rt->rt_flags & RTCF_LOCAL) && | ||
135 | (!skb->dev || skb->dev->features & NETIF_F_V4_CSUM)) { | ||
136 | skb->ip_summed = CHECKSUM_PARTIAL; | ||
137 | skb->csum_start = skb_headroom(skb) + | ||
138 | skb_network_offset(skb) + | ||
139 | ip_hdrlen(skb); | ||
140 | skb->csum_offset = (void *)check - data; | ||
141 | *check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, | ||
142 | datalen, proto, 0); | ||
143 | } else { | ||
144 | *check = 0; | ||
145 | *check = csum_tcpudp_magic(iph->saddr, iph->daddr, | ||
146 | datalen, proto, | ||
147 | csum_partial(data, datalen, | ||
148 | 0)); | ||
149 | if (proto == IPPROTO_UDP && !*check) | ||
150 | *check = CSUM_MANGLED_0; | ||
151 | } | ||
152 | } else | ||
153 | inet_proto_csum_replace2(check, skb, | ||
154 | htons(oldlen), htons(datalen), 1); | ||
155 | } | ||
156 | |||
157 | static int nf_nat_ipv4_nlattr_to_range(struct nlattr *tb[], | ||
158 | struct nf_nat_range *range) | ||
159 | { | ||
160 | if (tb[CTA_NAT_V4_MINIP]) { | ||
161 | range->min_addr.ip = nla_get_be32(tb[CTA_NAT_V4_MINIP]); | ||
162 | range->flags |= NF_NAT_RANGE_MAP_IPS; | ||
163 | } | ||
164 | |||
165 | if (tb[CTA_NAT_V4_MAXIP]) | ||
166 | range->max_addr.ip = nla_get_be32(tb[CTA_NAT_V4_MAXIP]); | ||
167 | else | ||
168 | range->max_addr.ip = range->min_addr.ip; | ||
169 | |||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | static const struct nf_nat_l3proto nf_nat_l3proto_ipv4 = { | ||
174 | .l3proto = NFPROTO_IPV4, | ||
175 | .in_range = nf_nat_ipv4_in_range, | ||
176 | .secure_port = nf_nat_ipv4_secure_port, | ||
177 | .manip_pkt = nf_nat_ipv4_manip_pkt, | ||
178 | .csum_update = nf_nat_ipv4_csum_update, | ||
179 | .csum_recalc = nf_nat_ipv4_csum_recalc, | ||
180 | .nlattr_to_range = nf_nat_ipv4_nlattr_to_range, | ||
181 | #ifdef CONFIG_XFRM | ||
182 | .decode_session = nf_nat_ipv4_decode_session, | ||
183 | #endif | ||
184 | }; | ||
185 | |||
186 | int nf_nat_icmp_reply_translation(struct sk_buff *skb, | ||
187 | struct nf_conn *ct, | ||
188 | enum ip_conntrack_info ctinfo, | ||
189 | unsigned int hooknum) | ||
190 | { | ||
191 | struct { | ||
192 | struct icmphdr icmp; | ||
193 | struct iphdr ip; | ||
194 | } *inside; | ||
195 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | ||
196 | enum nf_nat_manip_type manip = HOOK2MANIP(hooknum); | ||
197 | unsigned int hdrlen = ip_hdrlen(skb); | ||
198 | const struct nf_nat_l4proto *l4proto; | ||
199 | struct nf_conntrack_tuple target; | ||
200 | unsigned long statusbit; | ||
201 | |||
202 | NF_CT_ASSERT(ctinfo == IP_CT_RELATED || ctinfo == IP_CT_RELATED_REPLY); | ||
203 | |||
204 | if (!skb_make_writable(skb, hdrlen + sizeof(*inside))) | ||
205 | return 0; | ||
206 | if (nf_ip_checksum(skb, hooknum, hdrlen, 0)) | ||
207 | return 0; | ||
208 | |||
209 | inside = (void *)skb->data + hdrlen; | ||
210 | if (inside->icmp.type == ICMP_REDIRECT) { | ||
211 | if ((ct->status & IPS_NAT_DONE_MASK) != IPS_NAT_DONE_MASK) | ||
212 | return 0; | ||
213 | if (ct->status & IPS_NAT_MASK) | ||
214 | return 0; | ||
215 | } | ||
216 | |||
217 | if (manip == NF_NAT_MANIP_SRC) | ||
218 | statusbit = IPS_SRC_NAT; | ||
219 | else | ||
220 | statusbit = IPS_DST_NAT; | ||
221 | |||
222 | /* Invert if this is reply direction */ | ||
223 | if (dir == IP_CT_DIR_REPLY) | ||
224 | statusbit ^= IPS_NAT_MASK; | ||
225 | |||
226 | if (!(ct->status & statusbit)) | ||
227 | return 1; | ||
228 | |||
229 | l4proto = __nf_nat_l4proto_find(NFPROTO_IPV4, inside->ip.protocol); | ||
230 | if (!nf_nat_ipv4_manip_pkt(skb, hdrlen + sizeof(inside->icmp), | ||
231 | l4proto, &ct->tuplehash[!dir].tuple, !manip)) | ||
232 | return 0; | ||
233 | |||
234 | if (skb->ip_summed != CHECKSUM_PARTIAL) { | ||
235 | /* Reloading "inside" here since manip_pkt may reallocate */ | ||
236 | inside = (void *)skb->data + hdrlen; | ||
237 | inside->icmp.checksum = 0; | ||
238 | inside->icmp.checksum = | ||
239 | csum_fold(skb_checksum(skb, hdrlen, | ||
240 | skb->len - hdrlen, 0)); | ||
241 | } | ||
242 | |||
243 | /* Change outer to look like the reply to an incoming packet */ | ||
244 | nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple); | ||
245 | l4proto = __nf_nat_l4proto_find(NFPROTO_IPV4, 0); | ||
246 | if (!nf_nat_ipv4_manip_pkt(skb, 0, l4proto, &target, manip)) | ||
247 | return 0; | ||
248 | |||
249 | return 1; | ||
250 | } | ||
251 | EXPORT_SYMBOL_GPL(nf_nat_icmp_reply_translation); | ||
252 | |||
253 | static int __init nf_nat_l3proto_ipv4_init(void) | ||
254 | { | ||
255 | int err; | ||
256 | |||
257 | err = nf_nat_l4proto_register(NFPROTO_IPV4, &nf_nat_l4proto_icmp); | ||
258 | if (err < 0) | ||
259 | goto err1; | ||
260 | err = nf_nat_l3proto_register(&nf_nat_l3proto_ipv4); | ||
261 | if (err < 0) | ||
262 | goto err2; | ||
263 | return err; | ||
264 | |||
265 | err2: | ||
266 | nf_nat_l4proto_unregister(NFPROTO_IPV4, &nf_nat_l4proto_icmp); | ||
267 | err1: | ||
268 | return err; | ||
269 | } | ||
270 | |||
271 | static void __exit nf_nat_l3proto_ipv4_exit(void) | ||
272 | { | ||
273 | nf_nat_l3proto_unregister(&nf_nat_l3proto_ipv4); | ||
274 | nf_nat_l4proto_unregister(NFPROTO_IPV4, &nf_nat_l4proto_icmp); | ||
275 | } | ||
276 | |||
277 | MODULE_LICENSE("GPL"); | ||
278 | MODULE_ALIAS("nf-nat-" __stringify(AF_INET)); | ||
279 | |||
280 | module_init(nf_nat_l3proto_ipv4_init); | ||
281 | module_exit(nf_nat_l3proto_ipv4_exit); | ||
diff --git a/net/ipv4/netfilter/nf_nat_pptp.c b/net/ipv4/netfilter/nf_nat_pptp.c index 388140881ebe..a06d7d74817d 100644 --- a/net/ipv4/netfilter/nf_nat_pptp.c +++ b/net/ipv4/netfilter/nf_nat_pptp.c | |||
@@ -22,7 +22,6 @@ | |||
22 | 22 | ||
23 | #include <net/netfilter/nf_nat.h> | 23 | #include <net/netfilter/nf_nat.h> |
24 | #include <net/netfilter/nf_nat_helper.h> | 24 | #include <net/netfilter/nf_nat_helper.h> |
25 | #include <net/netfilter/nf_nat_rule.h> | ||
26 | #include <net/netfilter/nf_conntrack_helper.h> | 25 | #include <net/netfilter/nf_conntrack_helper.h> |
27 | #include <net/netfilter/nf_conntrack_expect.h> | 26 | #include <net/netfilter/nf_conntrack_expect.h> |
28 | #include <net/netfilter/nf_conntrack_zones.h> | 27 | #include <net/netfilter/nf_conntrack_zones.h> |
@@ -47,7 +46,7 @@ static void pptp_nat_expected(struct nf_conn *ct, | |||
47 | struct nf_conntrack_tuple t; | 46 | struct nf_conntrack_tuple t; |
48 | const struct nf_ct_pptp_master *ct_pptp_info; | 47 | const struct nf_ct_pptp_master *ct_pptp_info; |
49 | const struct nf_nat_pptp *nat_pptp_info; | 48 | const struct nf_nat_pptp *nat_pptp_info; |
50 | struct nf_nat_ipv4_range range; | 49 | struct nf_nat_range range; |
51 | 50 | ||
52 | ct_pptp_info = nfct_help_data(master); | 51 | ct_pptp_info = nfct_help_data(master); |
53 | nat_pptp_info = &nfct_nat(master)->help.nat_pptp_info; | 52 | nat_pptp_info = &nfct_nat(master)->help.nat_pptp_info; |
@@ -89,21 +88,21 @@ static void pptp_nat_expected(struct nf_conn *ct, | |||
89 | 88 | ||
90 | /* Change src to where master sends to */ | 89 | /* Change src to where master sends to */ |
91 | range.flags = NF_NAT_RANGE_MAP_IPS; | 90 | range.flags = NF_NAT_RANGE_MAP_IPS; |
92 | range.min_ip = range.max_ip | 91 | range.min_addr = range.max_addr |
93 | = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip; | 92 | = ct->master->tuplehash[!exp->dir].tuple.dst.u3; |
94 | if (exp->dir == IP_CT_DIR_ORIGINAL) { | 93 | if (exp->dir == IP_CT_DIR_ORIGINAL) { |
95 | range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED; | 94 | range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED; |
96 | range.min = range.max = exp->saved_proto; | 95 | range.min_proto = range.max_proto = exp->saved_proto; |
97 | } | 96 | } |
98 | nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC); | 97 | nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC); |
99 | 98 | ||
100 | /* For DST manip, map port here to where it's expected. */ | 99 | /* For DST manip, map port here to where it's expected. */ |
101 | range.flags = NF_NAT_RANGE_MAP_IPS; | 100 | range.flags = NF_NAT_RANGE_MAP_IPS; |
102 | range.min_ip = range.max_ip | 101 | range.min_addr = range.max_addr |
103 | = ct->master->tuplehash[!exp->dir].tuple.src.u3.ip; | 102 | = ct->master->tuplehash[!exp->dir].tuple.src.u3; |
104 | if (exp->dir == IP_CT_DIR_REPLY) { | 103 | if (exp->dir == IP_CT_DIR_REPLY) { |
105 | range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED; | 104 | range.flags |= NF_NAT_RANGE_PROTO_SPECIFIED; |
106 | range.min = range.max = exp->saved_proto; | 105 | range.min_proto = range.max_proto = exp->saved_proto; |
107 | } | 106 | } |
108 | nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST); | 107 | nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST); |
109 | } | 108 | } |
@@ -113,6 +112,7 @@ static int | |||
113 | pptp_outbound_pkt(struct sk_buff *skb, | 112 | pptp_outbound_pkt(struct sk_buff *skb, |
114 | struct nf_conn *ct, | 113 | struct nf_conn *ct, |
115 | enum ip_conntrack_info ctinfo, | 114 | enum ip_conntrack_info ctinfo, |
115 | unsigned int protoff, | ||
116 | struct PptpControlHeader *ctlh, | 116 | struct PptpControlHeader *ctlh, |
117 | union pptp_ctrl_union *pptpReq) | 117 | union pptp_ctrl_union *pptpReq) |
118 | 118 | ||
@@ -175,7 +175,7 @@ pptp_outbound_pkt(struct sk_buff *skb, | |||
175 | ntohs(REQ_CID(pptpReq, cid_off)), ntohs(new_callid)); | 175 | ntohs(REQ_CID(pptpReq, cid_off)), ntohs(new_callid)); |
176 | 176 | ||
177 | /* mangle packet */ | 177 | /* mangle packet */ |
178 | if (nf_nat_mangle_tcp_packet(skb, ct, ctinfo, | 178 | if (nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff, |
179 | cid_off + sizeof(struct pptp_pkt_hdr) + | 179 | cid_off + sizeof(struct pptp_pkt_hdr) + |
180 | sizeof(struct PptpControlHeader), | 180 | sizeof(struct PptpControlHeader), |
181 | sizeof(new_callid), (char *)&new_callid, | 181 | sizeof(new_callid), (char *)&new_callid, |
@@ -216,6 +216,7 @@ static int | |||
216 | pptp_inbound_pkt(struct sk_buff *skb, | 216 | pptp_inbound_pkt(struct sk_buff *skb, |
217 | struct nf_conn *ct, | 217 | struct nf_conn *ct, |
218 | enum ip_conntrack_info ctinfo, | 218 | enum ip_conntrack_info ctinfo, |
219 | unsigned int protoff, | ||
219 | struct PptpControlHeader *ctlh, | 220 | struct PptpControlHeader *ctlh, |
220 | union pptp_ctrl_union *pptpReq) | 221 | union pptp_ctrl_union *pptpReq) |
221 | { | 222 | { |
@@ -268,7 +269,7 @@ pptp_inbound_pkt(struct sk_buff *skb, | |||
268 | pr_debug("altering peer call id from 0x%04x to 0x%04x\n", | 269 | pr_debug("altering peer call id from 0x%04x to 0x%04x\n", |
269 | ntohs(REQ_CID(pptpReq, pcid_off)), ntohs(new_pcid)); | 270 | ntohs(REQ_CID(pptpReq, pcid_off)), ntohs(new_pcid)); |
270 | 271 | ||
271 | if (nf_nat_mangle_tcp_packet(skb, ct, ctinfo, | 272 | if (nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff, |
272 | pcid_off + sizeof(struct pptp_pkt_hdr) + | 273 | pcid_off + sizeof(struct pptp_pkt_hdr) + |
273 | sizeof(struct PptpControlHeader), | 274 | sizeof(struct PptpControlHeader), |
274 | sizeof(new_pcid), (char *)&new_pcid, | 275 | sizeof(new_pcid), (char *)&new_pcid, |
diff --git a/net/ipv4/netfilter/nf_nat_proto_gre.c b/net/ipv4/netfilter/nf_nat_proto_gre.c index 46ba0b9ab985..ea44f02563b5 100644 --- a/net/ipv4/netfilter/nf_nat_proto_gre.c +++ b/net/ipv4/netfilter/nf_nat_proto_gre.c | |||
@@ -28,8 +28,7 @@ | |||
28 | #include <linux/ip.h> | 28 | #include <linux/ip.h> |
29 | 29 | ||
30 | #include <net/netfilter/nf_nat.h> | 30 | #include <net/netfilter/nf_nat.h> |
31 | #include <net/netfilter/nf_nat_rule.h> | 31 | #include <net/netfilter/nf_nat_l4proto.h> |
32 | #include <net/netfilter/nf_nat_protocol.h> | ||
33 | #include <linux/netfilter/nf_conntrack_proto_gre.h> | 32 | #include <linux/netfilter/nf_conntrack_proto_gre.h> |
34 | 33 | ||
35 | MODULE_LICENSE("GPL"); | 34 | MODULE_LICENSE("GPL"); |
@@ -38,8 +37,9 @@ MODULE_DESCRIPTION("Netfilter NAT protocol helper module for GRE"); | |||
38 | 37 | ||
39 | /* generate unique tuple ... */ | 38 | /* generate unique tuple ... */ |
40 | static void | 39 | static void |
41 | gre_unique_tuple(struct nf_conntrack_tuple *tuple, | 40 | gre_unique_tuple(const struct nf_nat_l3proto *l3proto, |
42 | const struct nf_nat_ipv4_range *range, | 41 | struct nf_conntrack_tuple *tuple, |
42 | const struct nf_nat_range *range, | ||
43 | enum nf_nat_manip_type maniptype, | 43 | enum nf_nat_manip_type maniptype, |
44 | const struct nf_conn *ct) | 44 | const struct nf_conn *ct) |
45 | { | 45 | { |
@@ -62,8 +62,8 @@ gre_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
62 | min = 1; | 62 | min = 1; |
63 | range_size = 0xffff; | 63 | range_size = 0xffff; |
64 | } else { | 64 | } else { |
65 | min = ntohs(range->min.gre.key); | 65 | min = ntohs(range->min_proto.gre.key); |
66 | range_size = ntohs(range->max.gre.key) - min + 1; | 66 | range_size = ntohs(range->max_proto.gre.key) - min + 1; |
67 | } | 67 | } |
68 | 68 | ||
69 | pr_debug("min = %u, range_size = %u\n", min, range_size); | 69 | pr_debug("min = %u, range_size = %u\n", min, range_size); |
@@ -80,14 +80,14 @@ gre_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
80 | 80 | ||
81 | /* manipulate a GRE packet according to maniptype */ | 81 | /* manipulate a GRE packet according to maniptype */ |
82 | static bool | 82 | static bool |
83 | gre_manip_pkt(struct sk_buff *skb, unsigned int iphdroff, | 83 | gre_manip_pkt(struct sk_buff *skb, |
84 | const struct nf_nat_l3proto *l3proto, | ||
85 | unsigned int iphdroff, unsigned int hdroff, | ||
84 | const struct nf_conntrack_tuple *tuple, | 86 | const struct nf_conntrack_tuple *tuple, |
85 | enum nf_nat_manip_type maniptype) | 87 | enum nf_nat_manip_type maniptype) |
86 | { | 88 | { |
87 | const struct gre_hdr *greh; | 89 | const struct gre_hdr *greh; |
88 | struct gre_hdr_pptp *pgreh; | 90 | struct gre_hdr_pptp *pgreh; |
89 | const struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff); | ||
90 | unsigned int hdroff = iphdroff + iph->ihl * 4; | ||
91 | 91 | ||
92 | /* pgreh includes two optional 32bit fields which are not required | 92 | /* pgreh includes two optional 32bit fields which are not required |
93 | * to be there. That's where the magic '8' comes from */ | 93 | * to be there. That's where the magic '8' comes from */ |
@@ -117,24 +117,24 @@ gre_manip_pkt(struct sk_buff *skb, unsigned int iphdroff, | |||
117 | return true; | 117 | return true; |
118 | } | 118 | } |
119 | 119 | ||
120 | static const struct nf_nat_protocol gre = { | 120 | static const struct nf_nat_l4proto gre = { |
121 | .protonum = IPPROTO_GRE, | 121 | .l4proto = IPPROTO_GRE, |
122 | .manip_pkt = gre_manip_pkt, | 122 | .manip_pkt = gre_manip_pkt, |
123 | .in_range = nf_nat_proto_in_range, | 123 | .in_range = nf_nat_l4proto_in_range, |
124 | .unique_tuple = gre_unique_tuple, | 124 | .unique_tuple = gre_unique_tuple, |
125 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 125 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
126 | .nlattr_to_range = nf_nat_proto_nlattr_to_range, | 126 | .nlattr_to_range = nf_nat_l4proto_nlattr_to_range, |
127 | #endif | 127 | #endif |
128 | }; | 128 | }; |
129 | 129 | ||
130 | static int __init nf_nat_proto_gre_init(void) | 130 | static int __init nf_nat_proto_gre_init(void) |
131 | { | 131 | { |
132 | return nf_nat_protocol_register(&gre); | 132 | return nf_nat_l4proto_register(NFPROTO_IPV4, &gre); |
133 | } | 133 | } |
134 | 134 | ||
135 | static void __exit nf_nat_proto_gre_fini(void) | 135 | static void __exit nf_nat_proto_gre_fini(void) |
136 | { | 136 | { |
137 | nf_nat_protocol_unregister(&gre); | 137 | nf_nat_l4proto_unregister(NFPROTO_IPV4, &gre); |
138 | } | 138 | } |
139 | 139 | ||
140 | module_init(nf_nat_proto_gre_init); | 140 | module_init(nf_nat_proto_gre_init); |
diff --git a/net/ipv4/netfilter/nf_nat_proto_icmp.c b/net/ipv4/netfilter/nf_nat_proto_icmp.c index b35172851bae..eb303471bcf6 100644 --- a/net/ipv4/netfilter/nf_nat_proto_icmp.c +++ b/net/ipv4/netfilter/nf_nat_proto_icmp.c | |||
@@ -15,8 +15,7 @@ | |||
15 | #include <linux/netfilter.h> | 15 | #include <linux/netfilter.h> |
16 | #include <net/netfilter/nf_nat.h> | 16 | #include <net/netfilter/nf_nat.h> |
17 | #include <net/netfilter/nf_nat_core.h> | 17 | #include <net/netfilter/nf_nat_core.h> |
18 | #include <net/netfilter/nf_nat_rule.h> | 18 | #include <net/netfilter/nf_nat_l4proto.h> |
19 | #include <net/netfilter/nf_nat_protocol.h> | ||
20 | 19 | ||
21 | static bool | 20 | static bool |
22 | icmp_in_range(const struct nf_conntrack_tuple *tuple, | 21 | icmp_in_range(const struct nf_conntrack_tuple *tuple, |
@@ -29,8 +28,9 @@ icmp_in_range(const struct nf_conntrack_tuple *tuple, | |||
29 | } | 28 | } |
30 | 29 | ||
31 | static void | 30 | static void |
32 | icmp_unique_tuple(struct nf_conntrack_tuple *tuple, | 31 | icmp_unique_tuple(const struct nf_nat_l3proto *l3proto, |
33 | const struct nf_nat_ipv4_range *range, | 32 | struct nf_conntrack_tuple *tuple, |
33 | const struct nf_nat_range *range, | ||
34 | enum nf_nat_manip_type maniptype, | 34 | enum nf_nat_manip_type maniptype, |
35 | const struct nf_conn *ct) | 35 | const struct nf_conn *ct) |
36 | { | 36 | { |
@@ -38,13 +38,14 @@ icmp_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
38 | unsigned int range_size; | 38 | unsigned int range_size; |
39 | unsigned int i; | 39 | unsigned int i; |
40 | 40 | ||
41 | range_size = ntohs(range->max.icmp.id) - ntohs(range->min.icmp.id) + 1; | 41 | range_size = ntohs(range->max_proto.icmp.id) - |
42 | ntohs(range->min_proto.icmp.id) + 1; | ||
42 | /* If no range specified... */ | 43 | /* If no range specified... */ |
43 | if (!(range->flags & NF_NAT_RANGE_PROTO_SPECIFIED)) | 44 | if (!(range->flags & NF_NAT_RANGE_PROTO_SPECIFIED)) |
44 | range_size = 0xFFFF; | 45 | range_size = 0xFFFF; |
45 | 46 | ||
46 | for (i = 0; ; ++id) { | 47 | for (i = 0; ; ++id) { |
47 | tuple->src.u.icmp.id = htons(ntohs(range->min.icmp.id) + | 48 | tuple->src.u.icmp.id = htons(ntohs(range->min_proto.icmp.id) + |
48 | (id % range_size)); | 49 | (id % range_size)); |
49 | if (++i == range_size || !nf_nat_used_tuple(tuple, ct)) | 50 | if (++i == range_size || !nf_nat_used_tuple(tuple, ct)) |
50 | return; | 51 | return; |
@@ -54,13 +55,12 @@ icmp_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
54 | 55 | ||
55 | static bool | 56 | static bool |
56 | icmp_manip_pkt(struct sk_buff *skb, | 57 | icmp_manip_pkt(struct sk_buff *skb, |
57 | unsigned int iphdroff, | 58 | const struct nf_nat_l3proto *l3proto, |
59 | unsigned int iphdroff, unsigned int hdroff, | ||
58 | const struct nf_conntrack_tuple *tuple, | 60 | const struct nf_conntrack_tuple *tuple, |
59 | enum nf_nat_manip_type maniptype) | 61 | enum nf_nat_manip_type maniptype) |
60 | { | 62 | { |
61 | const struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff); | ||
62 | struct icmphdr *hdr; | 63 | struct icmphdr *hdr; |
63 | unsigned int hdroff = iphdroff + iph->ihl*4; | ||
64 | 64 | ||
65 | if (!skb_make_writable(skb, hdroff + sizeof(*hdr))) | 65 | if (!skb_make_writable(skb, hdroff + sizeof(*hdr))) |
66 | return false; | 66 | return false; |
@@ -72,12 +72,12 @@ icmp_manip_pkt(struct sk_buff *skb, | |||
72 | return true; | 72 | return true; |
73 | } | 73 | } |
74 | 74 | ||
75 | const struct nf_nat_protocol nf_nat_protocol_icmp = { | 75 | const struct nf_nat_l4proto nf_nat_l4proto_icmp = { |
76 | .protonum = IPPROTO_ICMP, | 76 | .l4proto = IPPROTO_ICMP, |
77 | .manip_pkt = icmp_manip_pkt, | 77 | .manip_pkt = icmp_manip_pkt, |
78 | .in_range = icmp_in_range, | 78 | .in_range = icmp_in_range, |
79 | .unique_tuple = icmp_unique_tuple, | 79 | .unique_tuple = icmp_unique_tuple, |
80 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 80 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
81 | .nlattr_to_range = nf_nat_proto_nlattr_to_range, | 81 | .nlattr_to_range = nf_nat_l4proto_nlattr_to_range, |
82 | #endif | 82 | #endif |
83 | }; | 83 | }; |
diff --git a/net/ipv4/netfilter/nf_nat_rule.c b/net/ipv4/netfilter/nf_nat_rule.c deleted file mode 100644 index d2a9dc314e0e..000000000000 --- a/net/ipv4/netfilter/nf_nat_rule.c +++ /dev/null | |||
@@ -1,214 +0,0 @@ | |||
1 | /* (C) 1999-2001 Paul `Rusty' Russell | ||
2 | * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | /* Everything about the rules for NAT. */ | ||
10 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
11 | #include <linux/types.h> | ||
12 | #include <linux/ip.h> | ||
13 | #include <linux/netfilter.h> | ||
14 | #include <linux/netfilter_ipv4.h> | ||
15 | #include <linux/module.h> | ||
16 | #include <linux/kmod.h> | ||
17 | #include <linux/skbuff.h> | ||
18 | #include <linux/proc_fs.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <net/checksum.h> | ||
21 | #include <net/route.h> | ||
22 | #include <linux/bitops.h> | ||
23 | |||
24 | #include <linux/netfilter_ipv4/ip_tables.h> | ||
25 | #include <net/netfilter/nf_nat.h> | ||
26 | #include <net/netfilter/nf_nat_core.h> | ||
27 | #include <net/netfilter/nf_nat_rule.h> | ||
28 | |||
29 | #define NAT_VALID_HOOKS ((1 << NF_INET_PRE_ROUTING) | \ | ||
30 | (1 << NF_INET_POST_ROUTING) | \ | ||
31 | (1 << NF_INET_LOCAL_OUT) | \ | ||
32 | (1 << NF_INET_LOCAL_IN)) | ||
33 | |||
34 | static const struct xt_table nat_table = { | ||
35 | .name = "nat", | ||
36 | .valid_hooks = NAT_VALID_HOOKS, | ||
37 | .me = THIS_MODULE, | ||
38 | .af = NFPROTO_IPV4, | ||
39 | }; | ||
40 | |||
41 | /* Source NAT */ | ||
42 | static unsigned int | ||
43 | ipt_snat_target(struct sk_buff *skb, const struct xt_action_param *par) | ||
44 | { | ||
45 | struct nf_conn *ct; | ||
46 | enum ip_conntrack_info ctinfo; | ||
47 | const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; | ||
48 | |||
49 | NF_CT_ASSERT(par->hooknum == NF_INET_POST_ROUTING || | ||
50 | par->hooknum == NF_INET_LOCAL_IN); | ||
51 | |||
52 | ct = nf_ct_get(skb, &ctinfo); | ||
53 | |||
54 | /* Connection must be valid and new. */ | ||
55 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED || | ||
56 | ctinfo == IP_CT_RELATED_REPLY)); | ||
57 | NF_CT_ASSERT(par->out != NULL); | ||
58 | |||
59 | return nf_nat_setup_info(ct, &mr->range[0], NF_NAT_MANIP_SRC); | ||
60 | } | ||
61 | |||
62 | static unsigned int | ||
63 | ipt_dnat_target(struct sk_buff *skb, const struct xt_action_param *par) | ||
64 | { | ||
65 | struct nf_conn *ct; | ||
66 | enum ip_conntrack_info ctinfo; | ||
67 | const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; | ||
68 | |||
69 | NF_CT_ASSERT(par->hooknum == NF_INET_PRE_ROUTING || | ||
70 | par->hooknum == NF_INET_LOCAL_OUT); | ||
71 | |||
72 | ct = nf_ct_get(skb, &ctinfo); | ||
73 | |||
74 | /* Connection must be valid and new. */ | ||
75 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)); | ||
76 | |||
77 | return nf_nat_setup_info(ct, &mr->range[0], NF_NAT_MANIP_DST); | ||
78 | } | ||
79 | |||
80 | static int ipt_snat_checkentry(const struct xt_tgchk_param *par) | ||
81 | { | ||
82 | const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; | ||
83 | |||
84 | /* Must be a valid range */ | ||
85 | if (mr->rangesize != 1) { | ||
86 | pr_info("SNAT: multiple ranges no longer supported\n"); | ||
87 | return -EINVAL; | ||
88 | } | ||
89 | return 0; | ||
90 | } | ||
91 | |||
92 | static int ipt_dnat_checkentry(const struct xt_tgchk_param *par) | ||
93 | { | ||
94 | const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; | ||
95 | |||
96 | /* Must be a valid range */ | ||
97 | if (mr->rangesize != 1) { | ||
98 | pr_info("DNAT: multiple ranges no longer supported\n"); | ||
99 | return -EINVAL; | ||
100 | } | ||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | static unsigned int | ||
105 | alloc_null_binding(struct nf_conn *ct, unsigned int hooknum) | ||
106 | { | ||
107 | /* Force range to this IP; let proto decide mapping for | ||
108 | per-proto parts (hence not NF_NAT_RANGE_PROTO_SPECIFIED). | ||
109 | */ | ||
110 | struct nf_nat_ipv4_range range; | ||
111 | |||
112 | range.flags = 0; | ||
113 | pr_debug("Allocating NULL binding for %p (%pI4)\n", ct, | ||
114 | HOOK2MANIP(hooknum) == NF_NAT_MANIP_SRC ? | ||
115 | &ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip : | ||
116 | &ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip); | ||
117 | |||
118 | return nf_nat_setup_info(ct, &range, HOOK2MANIP(hooknum)); | ||
119 | } | ||
120 | |||
121 | int nf_nat_rule_find(struct sk_buff *skb, | ||
122 | unsigned int hooknum, | ||
123 | const struct net_device *in, | ||
124 | const struct net_device *out, | ||
125 | struct nf_conn *ct) | ||
126 | { | ||
127 | struct net *net = nf_ct_net(ct); | ||
128 | int ret; | ||
129 | |||
130 | ret = ipt_do_table(skb, hooknum, in, out, net->ipv4.nat_table); | ||
131 | |||
132 | if (ret == NF_ACCEPT) { | ||
133 | if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum))) | ||
134 | /* NUL mapping */ | ||
135 | ret = alloc_null_binding(ct, hooknum); | ||
136 | } | ||
137 | return ret; | ||
138 | } | ||
139 | |||
140 | static struct xt_target ipt_snat_reg __read_mostly = { | ||
141 | .name = "SNAT", | ||
142 | .target = ipt_snat_target, | ||
143 | .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat), | ||
144 | .table = "nat", | ||
145 | .hooks = (1 << NF_INET_POST_ROUTING) | (1 << NF_INET_LOCAL_IN), | ||
146 | .checkentry = ipt_snat_checkentry, | ||
147 | .family = AF_INET, | ||
148 | }; | ||
149 | |||
150 | static struct xt_target ipt_dnat_reg __read_mostly = { | ||
151 | .name = "DNAT", | ||
152 | .target = ipt_dnat_target, | ||
153 | .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat), | ||
154 | .table = "nat", | ||
155 | .hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT), | ||
156 | .checkentry = ipt_dnat_checkentry, | ||
157 | .family = AF_INET, | ||
158 | }; | ||
159 | |||
160 | static int __net_init nf_nat_rule_net_init(struct net *net) | ||
161 | { | ||
162 | struct ipt_replace *repl; | ||
163 | |||
164 | repl = ipt_alloc_initial_table(&nat_table); | ||
165 | if (repl == NULL) | ||
166 | return -ENOMEM; | ||
167 | net->ipv4.nat_table = ipt_register_table(net, &nat_table, repl); | ||
168 | kfree(repl); | ||
169 | if (IS_ERR(net->ipv4.nat_table)) | ||
170 | return PTR_ERR(net->ipv4.nat_table); | ||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static void __net_exit nf_nat_rule_net_exit(struct net *net) | ||
175 | { | ||
176 | ipt_unregister_table(net, net->ipv4.nat_table); | ||
177 | } | ||
178 | |||
179 | static struct pernet_operations nf_nat_rule_net_ops = { | ||
180 | .init = nf_nat_rule_net_init, | ||
181 | .exit = nf_nat_rule_net_exit, | ||
182 | }; | ||
183 | |||
184 | int __init nf_nat_rule_init(void) | ||
185 | { | ||
186 | int ret; | ||
187 | |||
188 | ret = register_pernet_subsys(&nf_nat_rule_net_ops); | ||
189 | if (ret != 0) | ||
190 | goto out; | ||
191 | ret = xt_register_target(&ipt_snat_reg); | ||
192 | if (ret != 0) | ||
193 | goto unregister_table; | ||
194 | |||
195 | ret = xt_register_target(&ipt_dnat_reg); | ||
196 | if (ret != 0) | ||
197 | goto unregister_snat; | ||
198 | |||
199 | return ret; | ||
200 | |||
201 | unregister_snat: | ||
202 | xt_unregister_target(&ipt_snat_reg); | ||
203 | unregister_table: | ||
204 | unregister_pernet_subsys(&nf_nat_rule_net_ops); | ||
205 | out: | ||
206 | return ret; | ||
207 | } | ||
208 | |||
209 | void nf_nat_rule_cleanup(void) | ||
210 | { | ||
211 | xt_unregister_target(&ipt_dnat_reg); | ||
212 | xt_unregister_target(&ipt_snat_reg); | ||
213 | unregister_pernet_subsys(&nf_nat_rule_net_ops); | ||
214 | } | ||
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 6232d476f37e..8f3d05424a3e 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c | |||
@@ -185,10 +185,10 @@ exit: | |||
185 | return sk; | 185 | return sk; |
186 | } | 186 | } |
187 | 187 | ||
188 | static void inet_get_ping_group_range_net(struct net *net, gid_t *low, | 188 | static void inet_get_ping_group_range_net(struct net *net, kgid_t *low, |
189 | gid_t *high) | 189 | kgid_t *high) |
190 | { | 190 | { |
191 | gid_t *data = net->ipv4.sysctl_ping_group_range; | 191 | kgid_t *data = net->ipv4.sysctl_ping_group_range; |
192 | unsigned int seq; | 192 | unsigned int seq; |
193 | 193 | ||
194 | do { | 194 | do { |
@@ -203,19 +203,13 @@ static void inet_get_ping_group_range_net(struct net *net, gid_t *low, | |||
203 | static int ping_init_sock(struct sock *sk) | 203 | static int ping_init_sock(struct sock *sk) |
204 | { | 204 | { |
205 | struct net *net = sock_net(sk); | 205 | struct net *net = sock_net(sk); |
206 | gid_t group = current_egid(); | 206 | kgid_t group = current_egid(); |
207 | gid_t range[2]; | ||
208 | struct group_info *group_info = get_current_groups(); | 207 | struct group_info *group_info = get_current_groups(); |
209 | int i, j, count = group_info->ngroups; | 208 | int i, j, count = group_info->ngroups; |
210 | kgid_t low, high; | 209 | kgid_t low, high; |
211 | 210 | ||
212 | inet_get_ping_group_range_net(net, range, range+1); | 211 | inet_get_ping_group_range_net(net, &low, &high); |
213 | low = make_kgid(&init_user_ns, range[0]); | 212 | if (gid_lte(low, group) && gid_lte(group, high)) |
214 | high = make_kgid(&init_user_ns, range[1]); | ||
215 | if (!gid_valid(low) || !gid_valid(high) || gid_lt(high, low)) | ||
216 | return -EACCES; | ||
217 | |||
218 | if (range[0] <= group && group <= range[1]) | ||
219 | return 0; | 213 | return 0; |
220 | 214 | ||
221 | for (i = 0; i < group_info->nblocks; i++) { | 215 | for (i = 0; i < group_info->nblocks; i++) { |
@@ -845,7 +839,9 @@ static void ping_format_sock(struct sock *sp, struct seq_file *f, | |||
845 | bucket, src, srcp, dest, destp, sp->sk_state, | 839 | bucket, src, srcp, dest, destp, sp->sk_state, |
846 | sk_wmem_alloc_get(sp), | 840 | sk_wmem_alloc_get(sp), |
847 | sk_rmem_alloc_get(sp), | 841 | sk_rmem_alloc_get(sp), |
848 | 0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp), | 842 | 0, 0L, 0, |
843 | from_kuid_munged(seq_user_ns(f), sock_i_uid(sp)), | ||
844 | 0, sock_i_ino(sp), | ||
849 | atomic_read(&sp->sk_refcnt), sp, | 845 | atomic_read(&sp->sk_refcnt), sp, |
850 | atomic_read(&sp->sk_drops), len); | 846 | atomic_read(&sp->sk_drops), len); |
851 | } | 847 | } |
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index 957acd12250b..8de53e1ddd54 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c | |||
@@ -263,6 +263,10 @@ static const struct snmp_mib snmp4_net_list[] = { | |||
263 | SNMP_MIB_ITEM("TCPChallengeACK", LINUX_MIB_TCPCHALLENGEACK), | 263 | SNMP_MIB_ITEM("TCPChallengeACK", LINUX_MIB_TCPCHALLENGEACK), |
264 | SNMP_MIB_ITEM("TCPSYNChallenge", LINUX_MIB_TCPSYNCHALLENGE), | 264 | SNMP_MIB_ITEM("TCPSYNChallenge", LINUX_MIB_TCPSYNCHALLENGE), |
265 | SNMP_MIB_ITEM("TCPFastOpenActive", LINUX_MIB_TCPFASTOPENACTIVE), | 265 | SNMP_MIB_ITEM("TCPFastOpenActive", LINUX_MIB_TCPFASTOPENACTIVE), |
266 | SNMP_MIB_ITEM("TCPFastOpenPassive", LINUX_MIB_TCPFASTOPENPASSIVE), | ||
267 | SNMP_MIB_ITEM("TCPFastOpenPassiveFail", LINUX_MIB_TCPFASTOPENPASSIVEFAIL), | ||
268 | SNMP_MIB_ITEM("TCPFastOpenListenOverflow", LINUX_MIB_TCPFASTOPENLISTENOVERFLOW), | ||
269 | SNMP_MIB_ITEM("TCPFastOpenCookieReqd", LINUX_MIB_TCPFASTOPENCOOKIEREQD), | ||
266 | SNMP_MIB_SENTINEL | 270 | SNMP_MIB_SENTINEL |
267 | }; | 271 | }; |
268 | 272 | ||
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index ff0f071969ea..f2425785d40a 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
@@ -992,7 +992,9 @@ static void raw_sock_seq_show(struct seq_file *seq, struct sock *sp, int i) | |||
992 | i, src, srcp, dest, destp, sp->sk_state, | 992 | i, src, srcp, dest, destp, sp->sk_state, |
993 | sk_wmem_alloc_get(sp), | 993 | sk_wmem_alloc_get(sp), |
994 | sk_rmem_alloc_get(sp), | 994 | sk_rmem_alloc_get(sp), |
995 | 0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp), | 995 | 0, 0L, 0, |
996 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)), | ||
997 | 0, sock_i_ino(sp), | ||
996 | atomic_read(&sp->sk_refcnt), sp, atomic_read(&sp->sk_drops)); | 998 | atomic_read(&sp->sk_refcnt), sp, atomic_read(&sp->sk_drops)); |
997 | } | 999 | } |
998 | 1000 | ||
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index c035251beb07..dc9549b5eb1c 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -70,7 +70,6 @@ | |||
70 | #include <linux/types.h> | 70 | #include <linux/types.h> |
71 | #include <linux/kernel.h> | 71 | #include <linux/kernel.h> |
72 | #include <linux/mm.h> | 72 | #include <linux/mm.h> |
73 | #include <linux/bootmem.h> | ||
74 | #include <linux/string.h> | 73 | #include <linux/string.h> |
75 | #include <linux/socket.h> | 74 | #include <linux/socket.h> |
76 | #include <linux/sockios.h> | 75 | #include <linux/sockios.h> |
@@ -80,7 +79,6 @@ | |||
80 | #include <linux/netdevice.h> | 79 | #include <linux/netdevice.h> |
81 | #include <linux/proc_fs.h> | 80 | #include <linux/proc_fs.h> |
82 | #include <linux/init.h> | 81 | #include <linux/init.h> |
83 | #include <linux/workqueue.h> | ||
84 | #include <linux/skbuff.h> | 82 | #include <linux/skbuff.h> |
85 | #include <linux/inetdevice.h> | 83 | #include <linux/inetdevice.h> |
86 | #include <linux/igmp.h> | 84 | #include <linux/igmp.h> |
@@ -88,11 +86,9 @@ | |||
88 | #include <linux/mroute.h> | 86 | #include <linux/mroute.h> |
89 | #include <linux/netfilter_ipv4.h> | 87 | #include <linux/netfilter_ipv4.h> |
90 | #include <linux/random.h> | 88 | #include <linux/random.h> |
91 | #include <linux/jhash.h> | ||
92 | #include <linux/rcupdate.h> | 89 | #include <linux/rcupdate.h> |
93 | #include <linux/times.h> | 90 | #include <linux/times.h> |
94 | #include <linux/slab.h> | 91 | #include <linux/slab.h> |
95 | #include <linux/prefetch.h> | ||
96 | #include <net/dst.h> | 92 | #include <net/dst.h> |
97 | #include <net/net_namespace.h> | 93 | #include <net/net_namespace.h> |
98 | #include <net/protocol.h> | 94 | #include <net/protocol.h> |
@@ -938,12 +934,14 @@ static u32 __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu) | |||
938 | if (mtu < ip_rt_min_pmtu) | 934 | if (mtu < ip_rt_min_pmtu) |
939 | mtu = ip_rt_min_pmtu; | 935 | mtu = ip_rt_min_pmtu; |
940 | 936 | ||
937 | rcu_read_lock(); | ||
941 | if (fib_lookup(dev_net(rt->dst.dev), fl4, &res) == 0) { | 938 | if (fib_lookup(dev_net(rt->dst.dev), fl4, &res) == 0) { |
942 | struct fib_nh *nh = &FIB_RES_NH(res); | 939 | struct fib_nh *nh = &FIB_RES_NH(res); |
943 | 940 | ||
944 | update_or_create_fnhe(nh, fl4->daddr, 0, mtu, | 941 | update_or_create_fnhe(nh, fl4->daddr, 0, mtu, |
945 | jiffies + ip_rt_mtu_expires); | 942 | jiffies + ip_rt_mtu_expires); |
946 | } | 943 | } |
944 | rcu_read_unlock(); | ||
947 | return mtu; | 945 | return mtu; |
948 | } | 946 | } |
949 | 947 | ||
@@ -960,7 +958,7 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, | |||
960 | dst->obsolete = DST_OBSOLETE_KILL; | 958 | dst->obsolete = DST_OBSOLETE_KILL; |
961 | } else { | 959 | } else { |
962 | rt->rt_pmtu = mtu; | 960 | rt->rt_pmtu = mtu; |
963 | dst_set_expires(&rt->dst, ip_rt_mtu_expires); | 961 | rt->dst.expires = max(1UL, jiffies + ip_rt_mtu_expires); |
964 | } | 962 | } |
965 | } | 963 | } |
966 | 964 | ||
@@ -1136,10 +1134,7 @@ static unsigned int ipv4_mtu(const struct dst_entry *dst) | |||
1136 | const struct rtable *rt = (const struct rtable *) dst; | 1134 | const struct rtable *rt = (const struct rtable *) dst; |
1137 | unsigned int mtu = rt->rt_pmtu; | 1135 | unsigned int mtu = rt->rt_pmtu; |
1138 | 1136 | ||
1139 | if (mtu && time_after_eq(jiffies, rt->dst.expires)) | 1137 | if (!mtu || time_after_eq(jiffies, rt->dst.expires)) |
1140 | mtu = 0; | ||
1141 | |||
1142 | if (!mtu) | ||
1143 | mtu = dst_metric_raw(dst, RTAX_MTU); | 1138 | mtu = dst_metric_raw(dst, RTAX_MTU); |
1144 | 1139 | ||
1145 | if (mtu && rt_is_output_route(rt)) | 1140 | if (mtu && rt_is_output_route(rt)) |
@@ -1267,7 +1262,7 @@ static void ipv4_dst_destroy(struct dst_entry *dst) | |||
1267 | { | 1262 | { |
1268 | struct rtable *rt = (struct rtable *) dst; | 1263 | struct rtable *rt = (struct rtable *) dst; |
1269 | 1264 | ||
1270 | if (dst->flags & DST_NOCACHE) { | 1265 | if (!list_empty(&rt->rt_uncached)) { |
1271 | spin_lock_bh(&rt_uncached_lock); | 1266 | spin_lock_bh(&rt_uncached_lock); |
1272 | list_del(&rt->rt_uncached); | 1267 | list_del(&rt->rt_uncached); |
1273 | spin_unlock_bh(&rt_uncached_lock); | 1268 | spin_unlock_bh(&rt_uncached_lock); |
@@ -1591,11 +1586,14 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
1591 | if (ipv4_is_zeronet(daddr)) | 1586 | if (ipv4_is_zeronet(daddr)) |
1592 | goto martian_destination; | 1587 | goto martian_destination; |
1593 | 1588 | ||
1594 | if (likely(!IN_DEV_ROUTE_LOCALNET(in_dev))) { | 1589 | /* Following code try to avoid calling IN_DEV_NET_ROUTE_LOCALNET(), |
1595 | if (ipv4_is_loopback(daddr)) | 1590 | * and call it once if daddr or/and saddr are loopback addresses |
1591 | */ | ||
1592 | if (ipv4_is_loopback(daddr)) { | ||
1593 | if (!IN_DEV_NET_ROUTE_LOCALNET(in_dev, net)) | ||
1596 | goto martian_destination; | 1594 | goto martian_destination; |
1597 | 1595 | } else if (ipv4_is_loopback(saddr)) { | |
1598 | if (ipv4_is_loopback(saddr)) | 1596 | if (!IN_DEV_NET_ROUTE_LOCALNET(in_dev, net)) |
1599 | goto martian_source; | 1597 | goto martian_source; |
1600 | } | 1598 | } |
1601 | 1599 | ||
@@ -1620,7 +1618,7 @@ static int ip_route_input_slow(struct sk_buff *skb, __be32 daddr, __be32 saddr, | |||
1620 | 1618 | ||
1621 | if (res.type == RTN_LOCAL) { | 1619 | if (res.type == RTN_LOCAL) { |
1622 | err = fib_validate_source(skb, saddr, daddr, tos, | 1620 | err = fib_validate_source(skb, saddr, daddr, tos, |
1623 | net->loopback_dev->ifindex, | 1621 | LOOPBACK_IFINDEX, |
1624 | dev, in_dev, &itag); | 1622 | dev, in_dev, &itag); |
1625 | if (err < 0) | 1623 | if (err < 0) |
1626 | goto martian_source_keep_err; | 1624 | goto martian_source_keep_err; |
@@ -1896,7 +1894,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4) | |||
1896 | 1894 | ||
1897 | orig_oif = fl4->flowi4_oif; | 1895 | orig_oif = fl4->flowi4_oif; |
1898 | 1896 | ||
1899 | fl4->flowi4_iif = net->loopback_dev->ifindex; | 1897 | fl4->flowi4_iif = LOOPBACK_IFINDEX; |
1900 | fl4->flowi4_tos = tos & IPTOS_RT_MASK; | 1898 | fl4->flowi4_tos = tos & IPTOS_RT_MASK; |
1901 | fl4->flowi4_scope = ((tos & RTO_ONLINK) ? | 1899 | fl4->flowi4_scope = ((tos & RTO_ONLINK) ? |
1902 | RT_SCOPE_LINK : RT_SCOPE_UNIVERSE); | 1900 | RT_SCOPE_LINK : RT_SCOPE_UNIVERSE); |
@@ -1985,7 +1983,7 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4) | |||
1985 | if (!fl4->daddr) | 1983 | if (!fl4->daddr) |
1986 | fl4->daddr = fl4->saddr = htonl(INADDR_LOOPBACK); | 1984 | fl4->daddr = fl4->saddr = htonl(INADDR_LOOPBACK); |
1987 | dev_out = net->loopback_dev; | 1985 | dev_out = net->loopback_dev; |
1988 | fl4->flowi4_oif = net->loopback_dev->ifindex; | 1986 | fl4->flowi4_oif = LOOPBACK_IFINDEX; |
1989 | res.type = RTN_LOCAL; | 1987 | res.type = RTN_LOCAL; |
1990 | flags |= RTCF_LOCAL; | 1988 | flags |= RTCF_LOCAL; |
1991 | goto make_route; | 1989 | goto make_route; |
@@ -2032,7 +2030,6 @@ struct rtable *__ip_route_output_key(struct net *net, struct flowi4 *fl4) | |||
2032 | } | 2030 | } |
2033 | dev_out = net->loopback_dev; | 2031 | dev_out = net->loopback_dev; |
2034 | fl4->flowi4_oif = dev_out->ifindex; | 2032 | fl4->flowi4_oif = dev_out->ifindex; |
2035 | res.fi = NULL; | ||
2036 | flags |= RTCF_LOCAL; | 2033 | flags |= RTCF_LOCAL; |
2037 | goto make_route; | 2034 | goto make_route; |
2038 | } | 2035 | } |
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index 650e1528e1e6..ba48e799b031 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c | |||
@@ -319,6 +319,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, | |||
319 | ireq->tstamp_ok = tcp_opt.saw_tstamp; | 319 | ireq->tstamp_ok = tcp_opt.saw_tstamp; |
320 | req->ts_recent = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsval : 0; | 320 | req->ts_recent = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsval : 0; |
321 | treq->snt_synack = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsecr : 0; | 321 | treq->snt_synack = tcp_opt.saw_tstamp ? tcp_opt.rcv_tsecr : 0; |
322 | treq->listener = NULL; | ||
322 | 323 | ||
323 | /* We throwed the options of the initial SYN away, so we hope | 324 | /* We throwed the options of the initial SYN away, so we hope |
324 | * the ACK carries the same options again (see RFC1122 4.2.3.8) | 325 | * the ACK carries the same options again (see RFC1122 4.2.3.8) |
diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index 1b5ce96707a3..9205e492dc9d 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c | |||
@@ -76,9 +76,9 @@ static int ipv4_local_port_range(ctl_table *table, int write, | |||
76 | } | 76 | } |
77 | 77 | ||
78 | 78 | ||
79 | static void inet_get_ping_group_range_table(struct ctl_table *table, gid_t *low, gid_t *high) | 79 | static void inet_get_ping_group_range_table(struct ctl_table *table, kgid_t *low, kgid_t *high) |
80 | { | 80 | { |
81 | gid_t *data = table->data; | 81 | kgid_t *data = table->data; |
82 | unsigned int seq; | 82 | unsigned int seq; |
83 | do { | 83 | do { |
84 | seq = read_seqbegin(&sysctl_local_ports.lock); | 84 | seq = read_seqbegin(&sysctl_local_ports.lock); |
@@ -89,12 +89,12 @@ static void inet_get_ping_group_range_table(struct ctl_table *table, gid_t *low, | |||
89 | } | 89 | } |
90 | 90 | ||
91 | /* Update system visible IP port range */ | 91 | /* Update system visible IP port range */ |
92 | static void set_ping_group_range(struct ctl_table *table, gid_t range[2]) | 92 | static void set_ping_group_range(struct ctl_table *table, kgid_t low, kgid_t high) |
93 | { | 93 | { |
94 | gid_t *data = table->data; | 94 | kgid_t *data = table->data; |
95 | write_seqlock(&sysctl_local_ports.lock); | 95 | write_seqlock(&sysctl_local_ports.lock); |
96 | data[0] = range[0]; | 96 | data[0] = low; |
97 | data[1] = range[1]; | 97 | data[1] = high; |
98 | write_sequnlock(&sysctl_local_ports.lock); | 98 | write_sequnlock(&sysctl_local_ports.lock); |
99 | } | 99 | } |
100 | 100 | ||
@@ -103,21 +103,33 @@ static int ipv4_ping_group_range(ctl_table *table, int write, | |||
103 | void __user *buffer, | 103 | void __user *buffer, |
104 | size_t *lenp, loff_t *ppos) | 104 | size_t *lenp, loff_t *ppos) |
105 | { | 105 | { |
106 | struct user_namespace *user_ns = current_user_ns(); | ||
106 | int ret; | 107 | int ret; |
107 | gid_t range[2]; | 108 | gid_t urange[2]; |
109 | kgid_t low, high; | ||
108 | ctl_table tmp = { | 110 | ctl_table tmp = { |
109 | .data = &range, | 111 | .data = &urange, |
110 | .maxlen = sizeof(range), | 112 | .maxlen = sizeof(urange), |
111 | .mode = table->mode, | 113 | .mode = table->mode, |
112 | .extra1 = &ip_ping_group_range_min, | 114 | .extra1 = &ip_ping_group_range_min, |
113 | .extra2 = &ip_ping_group_range_max, | 115 | .extra2 = &ip_ping_group_range_max, |
114 | }; | 116 | }; |
115 | 117 | ||
116 | inet_get_ping_group_range_table(table, range, range + 1); | 118 | inet_get_ping_group_range_table(table, &low, &high); |
119 | urange[0] = from_kgid_munged(user_ns, low); | ||
120 | urange[1] = from_kgid_munged(user_ns, high); | ||
117 | ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos); | 121 | ret = proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos); |
118 | 122 | ||
119 | if (write && ret == 0) | 123 | if (write && ret == 0) { |
120 | set_ping_group_range(table, range); | 124 | low = make_kgid(user_ns, urange[0]); |
125 | high = make_kgid(user_ns, urange[1]); | ||
126 | if (!gid_valid(low) || !gid_valid(high) || | ||
127 | (urange[1] < urange[0]) || gid_lt(high, low)) { | ||
128 | low = make_kgid(&init_user_ns, 1); | ||
129 | high = make_kgid(&init_user_ns, 0); | ||
130 | } | ||
131 | set_ping_group_range(table, low, high); | ||
132 | } | ||
121 | 133 | ||
122 | return ret; | 134 | return ret; |
123 | } | 135 | } |
@@ -220,6 +232,45 @@ static int ipv4_tcp_mem(ctl_table *ctl, int write, | |||
220 | return 0; | 232 | return 0; |
221 | } | 233 | } |
222 | 234 | ||
235 | int proc_tcp_fastopen_key(ctl_table *ctl, int write, void __user *buffer, | ||
236 | size_t *lenp, loff_t *ppos) | ||
237 | { | ||
238 | ctl_table tbl = { .maxlen = (TCP_FASTOPEN_KEY_LENGTH * 2 + 10) }; | ||
239 | struct tcp_fastopen_context *ctxt; | ||
240 | int ret; | ||
241 | u32 user_key[4]; /* 16 bytes, matching TCP_FASTOPEN_KEY_LENGTH */ | ||
242 | |||
243 | tbl.data = kmalloc(tbl.maxlen, GFP_KERNEL); | ||
244 | if (!tbl.data) | ||
245 | return -ENOMEM; | ||
246 | |||
247 | rcu_read_lock(); | ||
248 | ctxt = rcu_dereference(tcp_fastopen_ctx); | ||
249 | if (ctxt) | ||
250 | memcpy(user_key, ctxt->key, TCP_FASTOPEN_KEY_LENGTH); | ||
251 | rcu_read_unlock(); | ||
252 | |||
253 | snprintf(tbl.data, tbl.maxlen, "%08x-%08x-%08x-%08x", | ||
254 | user_key[0], user_key[1], user_key[2], user_key[3]); | ||
255 | ret = proc_dostring(&tbl, write, buffer, lenp, ppos); | ||
256 | |||
257 | if (write && ret == 0) { | ||
258 | if (sscanf(tbl.data, "%x-%x-%x-%x", user_key, user_key + 1, | ||
259 | user_key + 2, user_key + 3) != 4) { | ||
260 | ret = -EINVAL; | ||
261 | goto bad_key; | ||
262 | } | ||
263 | tcp_fastopen_reset_cipher(user_key, TCP_FASTOPEN_KEY_LENGTH); | ||
264 | } | ||
265 | |||
266 | bad_key: | ||
267 | pr_debug("proc FO key set 0x%x-%x-%x-%x <- 0x%s: %u\n", | ||
268 | user_key[0], user_key[1], user_key[2], user_key[3], | ||
269 | (char *)tbl.data, ret); | ||
270 | kfree(tbl.data); | ||
271 | return ret; | ||
272 | } | ||
273 | |||
223 | static struct ctl_table ipv4_table[] = { | 274 | static struct ctl_table ipv4_table[] = { |
224 | { | 275 | { |
225 | .procname = "tcp_timestamps", | 276 | .procname = "tcp_timestamps", |
@@ -374,6 +425,12 @@ static struct ctl_table ipv4_table[] = { | |||
374 | .proc_handler = proc_dointvec, | 425 | .proc_handler = proc_dointvec, |
375 | }, | 426 | }, |
376 | { | 427 | { |
428 | .procname = "tcp_fastopen_key", | ||
429 | .mode = 0600, | ||
430 | .maxlen = ((TCP_FASTOPEN_KEY_LENGTH * 2) + 10), | ||
431 | .proc_handler = proc_tcp_fastopen_key, | ||
432 | }, | ||
433 | { | ||
377 | .procname = "tcp_tw_recycle", | 434 | .procname = "tcp_tw_recycle", |
378 | .data = &tcp_death_row.sysctl_tw_recycle, | 435 | .data = &tcp_death_row.sysctl_tw_recycle, |
379 | .maxlen = sizeof(int), | 436 | .maxlen = sizeof(int), |
@@ -786,7 +843,7 @@ static struct ctl_table ipv4_net_table[] = { | |||
786 | { | 843 | { |
787 | .procname = "ping_group_range", | 844 | .procname = "ping_group_range", |
788 | .data = &init_net.ipv4.sysctl_ping_group_range, | 845 | .data = &init_net.ipv4.sysctl_ping_group_range, |
789 | .maxlen = sizeof(init_net.ipv4.sysctl_ping_group_range), | 846 | .maxlen = sizeof(gid_t)*2, |
790 | .mode = 0644, | 847 | .mode = 0644, |
791 | .proc_handler = ipv4_ping_group_range, | 848 | .proc_handler = ipv4_ping_group_range, |
792 | }, | 849 | }, |
@@ -830,8 +887,8 @@ static __net_init int ipv4_sysctl_init_net(struct net *net) | |||
830 | * Sane defaults - nobody may create ping sockets. | 887 | * Sane defaults - nobody may create ping sockets. |
831 | * Boot scripts should set this to distro-specific group. | 888 | * Boot scripts should set this to distro-specific group. |
832 | */ | 889 | */ |
833 | net->ipv4.sysctl_ping_group_range[0] = 1; | 890 | net->ipv4.sysctl_ping_group_range[0] = make_kgid(&init_user_ns, 1); |
834 | net->ipv4.sysctl_ping_group_range[1] = 0; | 891 | net->ipv4.sysctl_ping_group_range[1] = make_kgid(&init_user_ns, 0); |
835 | 892 | ||
836 | tcp_init_mem(net); | 893 | tcp_init_mem(net); |
837 | 894 | ||
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index e7e6eeae49c0..df83d744e380 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -486,8 +486,9 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait) | |||
486 | if (sk->sk_shutdown & RCV_SHUTDOWN) | 486 | if (sk->sk_shutdown & RCV_SHUTDOWN) |
487 | mask |= POLLIN | POLLRDNORM | POLLRDHUP; | 487 | mask |= POLLIN | POLLRDNORM | POLLRDHUP; |
488 | 488 | ||
489 | /* Connected? */ | 489 | /* Connected or passive Fast Open socket? */ |
490 | if ((1 << sk->sk_state) & ~(TCPF_SYN_SENT | TCPF_SYN_RECV)) { | 490 | if (sk->sk_state != TCP_SYN_SENT && |
491 | (sk->sk_state != TCP_SYN_RECV || tp->fastopen_rsk != NULL)) { | ||
491 | int target = sock_rcvlowat(sk, 0, INT_MAX); | 492 | int target = sock_rcvlowat(sk, 0, INT_MAX); |
492 | 493 | ||
493 | if (tp->urg_seq == tp->copied_seq && | 494 | if (tp->urg_seq == tp->copied_seq && |
@@ -811,7 +812,9 @@ static unsigned int tcp_xmit_size_goal(struct sock *sk, u32 mss_now, | |||
811 | old_size_goal + mss_now > xmit_size_goal)) { | 812 | old_size_goal + mss_now > xmit_size_goal)) { |
812 | xmit_size_goal = old_size_goal; | 813 | xmit_size_goal = old_size_goal; |
813 | } else { | 814 | } else { |
814 | tp->xmit_size_goal_segs = xmit_size_goal / mss_now; | 815 | tp->xmit_size_goal_segs = |
816 | min_t(u16, xmit_size_goal / mss_now, | ||
817 | sk->sk_gso_max_segs); | ||
815 | xmit_size_goal = tp->xmit_size_goal_segs * mss_now; | 818 | xmit_size_goal = tp->xmit_size_goal_segs * mss_now; |
816 | } | 819 | } |
817 | } | 820 | } |
@@ -838,10 +841,15 @@ static ssize_t do_tcp_sendpages(struct sock *sk, struct page **pages, int poffse | |||
838 | ssize_t copied; | 841 | ssize_t copied; |
839 | long timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT); | 842 | long timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT); |
840 | 843 | ||
841 | /* Wait for a connection to finish. */ | 844 | /* Wait for a connection to finish. One exception is TCP Fast Open |
842 | if ((1 << sk->sk_state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) | 845 | * (passive side) where data is allowed to be sent before a connection |
846 | * is fully established. | ||
847 | */ | ||
848 | if (((1 << sk->sk_state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) && | ||
849 | !tcp_passive_fastopen(sk)) { | ||
843 | if ((err = sk_stream_wait_connect(sk, &timeo)) != 0) | 850 | if ((err = sk_stream_wait_connect(sk, &timeo)) != 0) |
844 | goto out_err; | 851 | goto out_err; |
852 | } | ||
845 | 853 | ||
846 | clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); | 854 | clear_bit(SOCK_ASYNC_NOSPACE, &sk->sk_socket->flags); |
847 | 855 | ||
@@ -1040,10 +1048,15 @@ int tcp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
1040 | 1048 | ||
1041 | timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT); | 1049 | timeo = sock_sndtimeo(sk, flags & MSG_DONTWAIT); |
1042 | 1050 | ||
1043 | /* Wait for a connection to finish. */ | 1051 | /* Wait for a connection to finish. One exception is TCP Fast Open |
1044 | if ((1 << sk->sk_state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) | 1052 | * (passive side) where data is allowed to be sent before a connection |
1053 | * is fully established. | ||
1054 | */ | ||
1055 | if (((1 << sk->sk_state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) && | ||
1056 | !tcp_passive_fastopen(sk)) { | ||
1045 | if ((err = sk_stream_wait_connect(sk, &timeo)) != 0) | 1057 | if ((err = sk_stream_wait_connect(sk, &timeo)) != 0) |
1046 | goto do_error; | 1058 | goto do_error; |
1059 | } | ||
1047 | 1060 | ||
1048 | if (unlikely(tp->repair)) { | 1061 | if (unlikely(tp->repair)) { |
1049 | if (tp->repair_queue == TCP_RECV_QUEUE) { | 1062 | if (tp->repair_queue == TCP_RECV_QUEUE) { |
@@ -2142,6 +2155,10 @@ void tcp_close(struct sock *sk, long timeout) | |||
2142 | * they look as CLOSING or LAST_ACK for Linux) | 2155 | * they look as CLOSING or LAST_ACK for Linux) |
2143 | * Probably, I missed some more holelets. | 2156 | * Probably, I missed some more holelets. |
2144 | * --ANK | 2157 | * --ANK |
2158 | * XXX (TFO) - To start off we don't support SYN+ACK+FIN | ||
2159 | * in a single packet! (May consider it later but will | ||
2160 | * probably need API support or TCP_CORK SYN-ACK until | ||
2161 | * data is written and socket is closed.) | ||
2145 | */ | 2162 | */ |
2146 | tcp_send_fin(sk); | 2163 | tcp_send_fin(sk); |
2147 | } | 2164 | } |
@@ -2213,8 +2230,16 @@ adjudge_to_death: | |||
2213 | } | 2230 | } |
2214 | } | 2231 | } |
2215 | 2232 | ||
2216 | if (sk->sk_state == TCP_CLOSE) | 2233 | if (sk->sk_state == TCP_CLOSE) { |
2234 | struct request_sock *req = tcp_sk(sk)->fastopen_rsk; | ||
2235 | /* We could get here with a non-NULL req if the socket is | ||
2236 | * aborted (e.g., closed with unread data) before 3WHS | ||
2237 | * finishes. | ||
2238 | */ | ||
2239 | if (req != NULL) | ||
2240 | reqsk_fastopen_remove(sk, req, false); | ||
2217 | inet_csk_destroy_sock(sk); | 2241 | inet_csk_destroy_sock(sk); |
2242 | } | ||
2218 | /* Otherwise, socket is reprieved until protocol close. */ | 2243 | /* Otherwise, socket is reprieved until protocol close. */ |
2219 | 2244 | ||
2220 | out: | 2245 | out: |
@@ -2686,6 +2711,14 @@ static int do_tcp_setsockopt(struct sock *sk, int level, | |||
2686 | else | 2711 | else |
2687 | icsk->icsk_user_timeout = msecs_to_jiffies(val); | 2712 | icsk->icsk_user_timeout = msecs_to_jiffies(val); |
2688 | break; | 2713 | break; |
2714 | |||
2715 | case TCP_FASTOPEN: | ||
2716 | if (val >= 0 && ((1 << sk->sk_state) & (TCPF_CLOSE | | ||
2717 | TCPF_LISTEN))) | ||
2718 | err = fastopen_init_queue(sk, val); | ||
2719 | else | ||
2720 | err = -EINVAL; | ||
2721 | break; | ||
2689 | default: | 2722 | default: |
2690 | err = -ENOPROTOOPT; | 2723 | err = -ENOPROTOOPT; |
2691 | break; | 2724 | break; |
@@ -3499,11 +3532,15 @@ EXPORT_SYMBOL(tcp_cookie_generator); | |||
3499 | 3532 | ||
3500 | void tcp_done(struct sock *sk) | 3533 | void tcp_done(struct sock *sk) |
3501 | { | 3534 | { |
3535 | struct request_sock *req = tcp_sk(sk)->fastopen_rsk; | ||
3536 | |||
3502 | if (sk->sk_state == TCP_SYN_SENT || sk->sk_state == TCP_SYN_RECV) | 3537 | if (sk->sk_state == TCP_SYN_SENT || sk->sk_state == TCP_SYN_RECV) |
3503 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_ATTEMPTFAILS); | 3538 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_ATTEMPTFAILS); |
3504 | 3539 | ||
3505 | tcp_set_state(sk, TCP_CLOSE); | 3540 | tcp_set_state(sk, TCP_CLOSE); |
3506 | tcp_clear_xmit_timers(sk); | 3541 | tcp_clear_xmit_timers(sk); |
3542 | if (req != NULL) | ||
3543 | reqsk_fastopen_remove(sk, req, false); | ||
3507 | 3544 | ||
3508 | sk->sk_shutdown = SHUTDOWN_MASK; | 3545 | sk->sk_shutdown = SHUTDOWN_MASK; |
3509 | 3546 | ||
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index 4d4db16e336e..1432cdb0644c 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c | |||
@@ -291,7 +291,8 @@ bool tcp_is_cwnd_limited(const struct sock *sk, u32 in_flight) | |||
291 | left = tp->snd_cwnd - in_flight; | 291 | left = tp->snd_cwnd - in_flight; |
292 | if (sk_can_gso(sk) && | 292 | if (sk_can_gso(sk) && |
293 | left * sysctl_tcp_tso_win_divisor < tp->snd_cwnd && | 293 | left * sysctl_tcp_tso_win_divisor < tp->snd_cwnd && |
294 | left * tp->mss_cache < sk->sk_gso_max_size) | 294 | left * tp->mss_cache < sk->sk_gso_max_size && |
295 | left < sk->sk_gso_max_segs) | ||
295 | return true; | 296 | return true; |
296 | return left <= tcp_max_tso_deferred_mss(tp); | 297 | return left <= tcp_max_tso_deferred_mss(tp); |
297 | } | 298 | } |
diff --git a/net/ipv4/tcp_fastopen.c b/net/ipv4/tcp_fastopen.c index a7f729c409d7..8f7ef0ad80e5 100644 --- a/net/ipv4/tcp_fastopen.c +++ b/net/ipv4/tcp_fastopen.c | |||
@@ -1,10 +1,91 @@ | |||
1 | #include <linux/err.h> | ||
1 | #include <linux/init.h> | 2 | #include <linux/init.h> |
2 | #include <linux/kernel.h> | 3 | #include <linux/kernel.h> |
4 | #include <linux/list.h> | ||
5 | #include <linux/tcp.h> | ||
6 | #include <linux/rcupdate.h> | ||
7 | #include <linux/rculist.h> | ||
8 | #include <net/inetpeer.h> | ||
9 | #include <net/tcp.h> | ||
3 | 10 | ||
4 | int sysctl_tcp_fastopen; | 11 | int sysctl_tcp_fastopen __read_mostly; |
12 | |||
13 | struct tcp_fastopen_context __rcu *tcp_fastopen_ctx; | ||
14 | |||
15 | static DEFINE_SPINLOCK(tcp_fastopen_ctx_lock); | ||
16 | |||
17 | static void tcp_fastopen_ctx_free(struct rcu_head *head) | ||
18 | { | ||
19 | struct tcp_fastopen_context *ctx = | ||
20 | container_of(head, struct tcp_fastopen_context, rcu); | ||
21 | crypto_free_cipher(ctx->tfm); | ||
22 | kfree(ctx); | ||
23 | } | ||
24 | |||
25 | int tcp_fastopen_reset_cipher(void *key, unsigned int len) | ||
26 | { | ||
27 | int err; | ||
28 | struct tcp_fastopen_context *ctx, *octx; | ||
29 | |||
30 | ctx = kmalloc(sizeof(*ctx), GFP_KERNEL); | ||
31 | if (!ctx) | ||
32 | return -ENOMEM; | ||
33 | ctx->tfm = crypto_alloc_cipher("aes", 0, 0); | ||
34 | |||
35 | if (IS_ERR(ctx->tfm)) { | ||
36 | err = PTR_ERR(ctx->tfm); | ||
37 | error: kfree(ctx); | ||
38 | pr_err("TCP: TFO aes cipher alloc error: %d\n", err); | ||
39 | return err; | ||
40 | } | ||
41 | err = crypto_cipher_setkey(ctx->tfm, key, len); | ||
42 | if (err) { | ||
43 | pr_err("TCP: TFO cipher key error: %d\n", err); | ||
44 | crypto_free_cipher(ctx->tfm); | ||
45 | goto error; | ||
46 | } | ||
47 | memcpy(ctx->key, key, len); | ||
48 | |||
49 | spin_lock(&tcp_fastopen_ctx_lock); | ||
50 | |||
51 | octx = rcu_dereference_protected(tcp_fastopen_ctx, | ||
52 | lockdep_is_held(&tcp_fastopen_ctx_lock)); | ||
53 | rcu_assign_pointer(tcp_fastopen_ctx, ctx); | ||
54 | spin_unlock(&tcp_fastopen_ctx_lock); | ||
55 | |||
56 | if (octx) | ||
57 | call_rcu(&octx->rcu, tcp_fastopen_ctx_free); | ||
58 | return err; | ||
59 | } | ||
60 | |||
61 | /* Computes the fastopen cookie for the peer. | ||
62 | * The peer address is a 128 bits long (pad with zeros for IPv4). | ||
63 | * | ||
64 | * The caller must check foc->len to determine if a valid cookie | ||
65 | * has been generated successfully. | ||
66 | */ | ||
67 | void tcp_fastopen_cookie_gen(__be32 addr, struct tcp_fastopen_cookie *foc) | ||
68 | { | ||
69 | __be32 peer_addr[4] = { addr, 0, 0, 0 }; | ||
70 | struct tcp_fastopen_context *ctx; | ||
71 | |||
72 | rcu_read_lock(); | ||
73 | ctx = rcu_dereference(tcp_fastopen_ctx); | ||
74 | if (ctx) { | ||
75 | crypto_cipher_encrypt_one(ctx->tfm, | ||
76 | foc->val, | ||
77 | (__u8 *)peer_addr); | ||
78 | foc->len = TCP_FASTOPEN_COOKIE_SIZE; | ||
79 | } | ||
80 | rcu_read_unlock(); | ||
81 | } | ||
5 | 82 | ||
6 | static int __init tcp_fastopen_init(void) | 83 | static int __init tcp_fastopen_init(void) |
7 | { | 84 | { |
85 | __u8 key[TCP_FASTOPEN_KEY_LENGTH]; | ||
86 | |||
87 | get_random_bytes(key, sizeof(key)); | ||
88 | tcp_fastopen_reset_cipher(key, sizeof(key)); | ||
8 | return 0; | 89 | return 0; |
9 | } | 90 | } |
10 | 91 | ||
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 2fd2bc9e3c64..e2bec815ff23 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -237,7 +237,11 @@ static inline void TCP_ECN_check_ce(struct tcp_sock *tp, const struct sk_buff *s | |||
237 | tcp_enter_quickack_mode((struct sock *)tp); | 237 | tcp_enter_quickack_mode((struct sock *)tp); |
238 | break; | 238 | break; |
239 | case INET_ECN_CE: | 239 | case INET_ECN_CE: |
240 | tp->ecn_flags |= TCP_ECN_DEMAND_CWR; | 240 | if (!(tp->ecn_flags & TCP_ECN_DEMAND_CWR)) { |
241 | /* Better not delay acks, sender can have a very low cwnd */ | ||
242 | tcp_enter_quickack_mode((struct sock *)tp); | ||
243 | tp->ecn_flags |= TCP_ECN_DEMAND_CWR; | ||
244 | } | ||
241 | /* fallinto */ | 245 | /* fallinto */ |
242 | default: | 246 | default: |
243 | tp->ecn_flags |= TCP_ECN_SEEN; | 247 | tp->ecn_flags |= TCP_ECN_SEEN; |
@@ -374,7 +378,7 @@ static void tcp_fixup_rcvbuf(struct sock *sk) | |||
374 | /* 4. Try to fixup all. It is made immediately after connection enters | 378 | /* 4. Try to fixup all. It is made immediately after connection enters |
375 | * established state. | 379 | * established state. |
376 | */ | 380 | */ |
377 | static void tcp_init_buffer_space(struct sock *sk) | 381 | void tcp_init_buffer_space(struct sock *sk) |
378 | { | 382 | { |
379 | struct tcp_sock *tp = tcp_sk(sk); | 383 | struct tcp_sock *tp = tcp_sk(sk); |
380 | int maxwin; | 384 | int maxwin; |
@@ -739,29 +743,6 @@ __u32 tcp_init_cwnd(const struct tcp_sock *tp, const struct dst_entry *dst) | |||
739 | return min_t(__u32, cwnd, tp->snd_cwnd_clamp); | 743 | return min_t(__u32, cwnd, tp->snd_cwnd_clamp); |
740 | } | 744 | } |
741 | 745 | ||
742 | /* Set slow start threshold and cwnd not falling to slow start */ | ||
743 | void tcp_enter_cwr(struct sock *sk, const int set_ssthresh) | ||
744 | { | ||
745 | struct tcp_sock *tp = tcp_sk(sk); | ||
746 | const struct inet_connection_sock *icsk = inet_csk(sk); | ||
747 | |||
748 | tp->prior_ssthresh = 0; | ||
749 | tp->bytes_acked = 0; | ||
750 | if (icsk->icsk_ca_state < TCP_CA_CWR) { | ||
751 | tp->undo_marker = 0; | ||
752 | if (set_ssthresh) | ||
753 | tp->snd_ssthresh = icsk->icsk_ca_ops->ssthresh(sk); | ||
754 | tp->snd_cwnd = min(tp->snd_cwnd, | ||
755 | tcp_packets_in_flight(tp) + 1U); | ||
756 | tp->snd_cwnd_cnt = 0; | ||
757 | tp->high_seq = tp->snd_nxt; | ||
758 | tp->snd_cwnd_stamp = tcp_time_stamp; | ||
759 | TCP_ECN_queue_cwr(tp); | ||
760 | |||
761 | tcp_set_ca_state(sk, TCP_CA_CWR); | ||
762 | } | ||
763 | } | ||
764 | |||
765 | /* | 746 | /* |
766 | * Packet counting of FACK is based on in-order assumptions, therefore TCP | 747 | * Packet counting of FACK is based on in-order assumptions, therefore TCP |
767 | * disables it when reordering is detected | 748 | * disables it when reordering is detected |
@@ -2489,35 +2470,6 @@ static inline void tcp_moderate_cwnd(struct tcp_sock *tp) | |||
2489 | tp->snd_cwnd_stamp = tcp_time_stamp; | 2470 | tp->snd_cwnd_stamp = tcp_time_stamp; |
2490 | } | 2471 | } |
2491 | 2472 | ||
2492 | /* Lower bound on congestion window is slow start threshold | ||
2493 | * unless congestion avoidance choice decides to overide it. | ||
2494 | */ | ||
2495 | static inline u32 tcp_cwnd_min(const struct sock *sk) | ||
2496 | { | ||
2497 | const struct tcp_congestion_ops *ca_ops = inet_csk(sk)->icsk_ca_ops; | ||
2498 | |||
2499 | return ca_ops->min_cwnd ? ca_ops->min_cwnd(sk) : tcp_sk(sk)->snd_ssthresh; | ||
2500 | } | ||
2501 | |||
2502 | /* Decrease cwnd each second ack. */ | ||
2503 | static void tcp_cwnd_down(struct sock *sk, int flag) | ||
2504 | { | ||
2505 | struct tcp_sock *tp = tcp_sk(sk); | ||
2506 | int decr = tp->snd_cwnd_cnt + 1; | ||
2507 | |||
2508 | if ((flag & (FLAG_ANY_PROGRESS | FLAG_DSACKING_ACK)) || | ||
2509 | (tcp_is_reno(tp) && !(flag & FLAG_NOT_DUP))) { | ||
2510 | tp->snd_cwnd_cnt = decr & 1; | ||
2511 | decr >>= 1; | ||
2512 | |||
2513 | if (decr && tp->snd_cwnd > tcp_cwnd_min(sk)) | ||
2514 | tp->snd_cwnd -= decr; | ||
2515 | |||
2516 | tp->snd_cwnd = min(tp->snd_cwnd, tcp_packets_in_flight(tp) + 1); | ||
2517 | tp->snd_cwnd_stamp = tcp_time_stamp; | ||
2518 | } | ||
2519 | } | ||
2520 | |||
2521 | /* Nothing was retransmitted or returned timestamp is less | 2473 | /* Nothing was retransmitted or returned timestamp is less |
2522 | * than timestamp of the first retransmission. | 2474 | * than timestamp of the first retransmission. |
2523 | */ | 2475 | */ |
@@ -2719,24 +2671,80 @@ static bool tcp_try_undo_loss(struct sock *sk) | |||
2719 | return false; | 2671 | return false; |
2720 | } | 2672 | } |
2721 | 2673 | ||
2722 | static inline void tcp_complete_cwr(struct sock *sk) | 2674 | /* The cwnd reduction in CWR and Recovery use the PRR algorithm |
2675 | * https://datatracker.ietf.org/doc/draft-ietf-tcpm-proportional-rate-reduction/ | ||
2676 | * It computes the number of packets to send (sndcnt) based on packets newly | ||
2677 | * delivered: | ||
2678 | * 1) If the packets in flight is larger than ssthresh, PRR spreads the | ||
2679 | * cwnd reductions across a full RTT. | ||
2680 | * 2) If packets in flight is lower than ssthresh (such as due to excess | ||
2681 | * losses and/or application stalls), do not perform any further cwnd | ||
2682 | * reductions, but instead slow start up to ssthresh. | ||
2683 | */ | ||
2684 | static void tcp_init_cwnd_reduction(struct sock *sk, const bool set_ssthresh) | ||
2723 | { | 2685 | { |
2724 | struct tcp_sock *tp = tcp_sk(sk); | 2686 | struct tcp_sock *tp = tcp_sk(sk); |
2725 | 2687 | ||
2726 | /* Do not moderate cwnd if it's already undone in cwr or recovery. */ | 2688 | tp->high_seq = tp->snd_nxt; |
2727 | if (tp->undo_marker) { | 2689 | tp->bytes_acked = 0; |
2728 | if (inet_csk(sk)->icsk_ca_state == TCP_CA_CWR) { | 2690 | tp->snd_cwnd_cnt = 0; |
2729 | tp->snd_cwnd = min(tp->snd_cwnd, tp->snd_ssthresh); | 2691 | tp->prior_cwnd = tp->snd_cwnd; |
2730 | tp->snd_cwnd_stamp = tcp_time_stamp; | 2692 | tp->prr_delivered = 0; |
2731 | } else if (tp->snd_ssthresh < TCP_INFINITE_SSTHRESH) { | 2693 | tp->prr_out = 0; |
2732 | /* PRR algorithm. */ | 2694 | if (set_ssthresh) |
2733 | tp->snd_cwnd = tp->snd_ssthresh; | 2695 | tp->snd_ssthresh = inet_csk(sk)->icsk_ca_ops->ssthresh(sk); |
2734 | tp->snd_cwnd_stamp = tcp_time_stamp; | 2696 | TCP_ECN_queue_cwr(tp); |
2735 | } | 2697 | } |
2698 | |||
2699 | static void tcp_cwnd_reduction(struct sock *sk, int newly_acked_sacked, | ||
2700 | int fast_rexmit) | ||
2701 | { | ||
2702 | struct tcp_sock *tp = tcp_sk(sk); | ||
2703 | int sndcnt = 0; | ||
2704 | int delta = tp->snd_ssthresh - tcp_packets_in_flight(tp); | ||
2705 | |||
2706 | tp->prr_delivered += newly_acked_sacked; | ||
2707 | if (tcp_packets_in_flight(tp) > tp->snd_ssthresh) { | ||
2708 | u64 dividend = (u64)tp->snd_ssthresh * tp->prr_delivered + | ||
2709 | tp->prior_cwnd - 1; | ||
2710 | sndcnt = div_u64(dividend, tp->prior_cwnd) - tp->prr_out; | ||
2711 | } else { | ||
2712 | sndcnt = min_t(int, delta, | ||
2713 | max_t(int, tp->prr_delivered - tp->prr_out, | ||
2714 | newly_acked_sacked) + 1); | ||
2715 | } | ||
2716 | |||
2717 | sndcnt = max(sndcnt, (fast_rexmit ? 1 : 0)); | ||
2718 | tp->snd_cwnd = tcp_packets_in_flight(tp) + sndcnt; | ||
2719 | } | ||
2720 | |||
2721 | static inline void tcp_end_cwnd_reduction(struct sock *sk) | ||
2722 | { | ||
2723 | struct tcp_sock *tp = tcp_sk(sk); | ||
2724 | |||
2725 | /* Reset cwnd to ssthresh in CWR or Recovery (unless it's undone) */ | ||
2726 | if (inet_csk(sk)->icsk_ca_state == TCP_CA_CWR || | ||
2727 | (tp->undo_marker && tp->snd_ssthresh < TCP_INFINITE_SSTHRESH)) { | ||
2728 | tp->snd_cwnd = tp->snd_ssthresh; | ||
2729 | tp->snd_cwnd_stamp = tcp_time_stamp; | ||
2736 | } | 2730 | } |
2737 | tcp_ca_event(sk, CA_EVENT_COMPLETE_CWR); | 2731 | tcp_ca_event(sk, CA_EVENT_COMPLETE_CWR); |
2738 | } | 2732 | } |
2739 | 2733 | ||
2734 | /* Enter CWR state. Disable cwnd undo since congestion is proven with ECN */ | ||
2735 | void tcp_enter_cwr(struct sock *sk, const int set_ssthresh) | ||
2736 | { | ||
2737 | struct tcp_sock *tp = tcp_sk(sk); | ||
2738 | |||
2739 | tp->prior_ssthresh = 0; | ||
2740 | tp->bytes_acked = 0; | ||
2741 | if (inet_csk(sk)->icsk_ca_state < TCP_CA_CWR) { | ||
2742 | tp->undo_marker = 0; | ||
2743 | tcp_init_cwnd_reduction(sk, set_ssthresh); | ||
2744 | tcp_set_ca_state(sk, TCP_CA_CWR); | ||
2745 | } | ||
2746 | } | ||
2747 | |||
2740 | static void tcp_try_keep_open(struct sock *sk) | 2748 | static void tcp_try_keep_open(struct sock *sk) |
2741 | { | 2749 | { |
2742 | struct tcp_sock *tp = tcp_sk(sk); | 2750 | struct tcp_sock *tp = tcp_sk(sk); |
@@ -2751,7 +2759,7 @@ static void tcp_try_keep_open(struct sock *sk) | |||
2751 | } | 2759 | } |
2752 | } | 2760 | } |
2753 | 2761 | ||
2754 | static void tcp_try_to_open(struct sock *sk, int flag) | 2762 | static void tcp_try_to_open(struct sock *sk, int flag, int newly_acked_sacked) |
2755 | { | 2763 | { |
2756 | struct tcp_sock *tp = tcp_sk(sk); | 2764 | struct tcp_sock *tp = tcp_sk(sk); |
2757 | 2765 | ||
@@ -2768,7 +2776,7 @@ static void tcp_try_to_open(struct sock *sk, int flag) | |||
2768 | if (inet_csk(sk)->icsk_ca_state != TCP_CA_Open) | 2776 | if (inet_csk(sk)->icsk_ca_state != TCP_CA_Open) |
2769 | tcp_moderate_cwnd(tp); | 2777 | tcp_moderate_cwnd(tp); |
2770 | } else { | 2778 | } else { |
2771 | tcp_cwnd_down(sk, flag); | 2779 | tcp_cwnd_reduction(sk, newly_acked_sacked, 0); |
2772 | } | 2780 | } |
2773 | } | 2781 | } |
2774 | 2782 | ||
@@ -2850,38 +2858,6 @@ void tcp_simple_retransmit(struct sock *sk) | |||
2850 | } | 2858 | } |
2851 | EXPORT_SYMBOL(tcp_simple_retransmit); | 2859 | EXPORT_SYMBOL(tcp_simple_retransmit); |
2852 | 2860 | ||
2853 | /* This function implements the PRR algorithm, specifcally the PRR-SSRB | ||
2854 | * (proportional rate reduction with slow start reduction bound) as described in | ||
2855 | * http://www.ietf.org/id/draft-mathis-tcpm-proportional-rate-reduction-01.txt. | ||
2856 | * It computes the number of packets to send (sndcnt) based on packets newly | ||
2857 | * delivered: | ||
2858 | * 1) If the packets in flight is larger than ssthresh, PRR spreads the | ||
2859 | * cwnd reductions across a full RTT. | ||
2860 | * 2) If packets in flight is lower than ssthresh (such as due to excess | ||
2861 | * losses and/or application stalls), do not perform any further cwnd | ||
2862 | * reductions, but instead slow start up to ssthresh. | ||
2863 | */ | ||
2864 | static void tcp_update_cwnd_in_recovery(struct sock *sk, int newly_acked_sacked, | ||
2865 | int fast_rexmit, int flag) | ||
2866 | { | ||
2867 | struct tcp_sock *tp = tcp_sk(sk); | ||
2868 | int sndcnt = 0; | ||
2869 | int delta = tp->snd_ssthresh - tcp_packets_in_flight(tp); | ||
2870 | |||
2871 | if (tcp_packets_in_flight(tp) > tp->snd_ssthresh) { | ||
2872 | u64 dividend = (u64)tp->snd_ssthresh * tp->prr_delivered + | ||
2873 | tp->prior_cwnd - 1; | ||
2874 | sndcnt = div_u64(dividend, tp->prior_cwnd) - tp->prr_out; | ||
2875 | } else { | ||
2876 | sndcnt = min_t(int, delta, | ||
2877 | max_t(int, tp->prr_delivered - tp->prr_out, | ||
2878 | newly_acked_sacked) + 1); | ||
2879 | } | ||
2880 | |||
2881 | sndcnt = max(sndcnt, (fast_rexmit ? 1 : 0)); | ||
2882 | tp->snd_cwnd = tcp_packets_in_flight(tp) + sndcnt; | ||
2883 | } | ||
2884 | |||
2885 | static void tcp_enter_recovery(struct sock *sk, bool ece_ack) | 2861 | static void tcp_enter_recovery(struct sock *sk, bool ece_ack) |
2886 | { | 2862 | { |
2887 | struct tcp_sock *tp = tcp_sk(sk); | 2863 | struct tcp_sock *tp = tcp_sk(sk); |
@@ -2894,7 +2870,6 @@ static void tcp_enter_recovery(struct sock *sk, bool ece_ack) | |||
2894 | 2870 | ||
2895 | NET_INC_STATS_BH(sock_net(sk), mib_idx); | 2871 | NET_INC_STATS_BH(sock_net(sk), mib_idx); |
2896 | 2872 | ||
2897 | tp->high_seq = tp->snd_nxt; | ||
2898 | tp->prior_ssthresh = 0; | 2873 | tp->prior_ssthresh = 0; |
2899 | tp->undo_marker = tp->snd_una; | 2874 | tp->undo_marker = tp->snd_una; |
2900 | tp->undo_retrans = tp->retrans_out; | 2875 | tp->undo_retrans = tp->retrans_out; |
@@ -2902,15 +2877,8 @@ static void tcp_enter_recovery(struct sock *sk, bool ece_ack) | |||
2902 | if (inet_csk(sk)->icsk_ca_state < TCP_CA_CWR) { | 2877 | if (inet_csk(sk)->icsk_ca_state < TCP_CA_CWR) { |
2903 | if (!ece_ack) | 2878 | if (!ece_ack) |
2904 | tp->prior_ssthresh = tcp_current_ssthresh(sk); | 2879 | tp->prior_ssthresh = tcp_current_ssthresh(sk); |
2905 | tp->snd_ssthresh = inet_csk(sk)->icsk_ca_ops->ssthresh(sk); | 2880 | tcp_init_cwnd_reduction(sk, true); |
2906 | TCP_ECN_queue_cwr(tp); | ||
2907 | } | 2881 | } |
2908 | |||
2909 | tp->bytes_acked = 0; | ||
2910 | tp->snd_cwnd_cnt = 0; | ||
2911 | tp->prior_cwnd = tp->snd_cwnd; | ||
2912 | tp->prr_delivered = 0; | ||
2913 | tp->prr_out = 0; | ||
2914 | tcp_set_ca_state(sk, TCP_CA_Recovery); | 2882 | tcp_set_ca_state(sk, TCP_CA_Recovery); |
2915 | } | 2883 | } |
2916 | 2884 | ||
@@ -2926,13 +2894,14 @@ static void tcp_enter_recovery(struct sock *sk, bool ece_ack) | |||
2926 | * tcp_xmit_retransmit_queue(). | 2894 | * tcp_xmit_retransmit_queue(). |
2927 | */ | 2895 | */ |
2928 | static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, | 2896 | static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, |
2929 | int newly_acked_sacked, bool is_dupack, | 2897 | int prior_sacked, bool is_dupack, |
2930 | int flag) | 2898 | int flag) |
2931 | { | 2899 | { |
2932 | struct inet_connection_sock *icsk = inet_csk(sk); | 2900 | struct inet_connection_sock *icsk = inet_csk(sk); |
2933 | struct tcp_sock *tp = tcp_sk(sk); | 2901 | struct tcp_sock *tp = tcp_sk(sk); |
2934 | int do_lost = is_dupack || ((flag & FLAG_DATA_SACKED) && | 2902 | int do_lost = is_dupack || ((flag & FLAG_DATA_SACKED) && |
2935 | (tcp_fackets_out(tp) > tp->reordering)); | 2903 | (tcp_fackets_out(tp) > tp->reordering)); |
2904 | int newly_acked_sacked = 0; | ||
2936 | int fast_rexmit = 0; | 2905 | int fast_rexmit = 0; |
2937 | 2906 | ||
2938 | if (WARN_ON(!tp->packets_out && tp->sacked_out)) | 2907 | if (WARN_ON(!tp->packets_out && tp->sacked_out)) |
@@ -2969,7 +2938,7 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, | |||
2969 | /* CWR is to be held something *above* high_seq | 2938 | /* CWR is to be held something *above* high_seq |
2970 | * is ACKed for CWR bit to reach receiver. */ | 2939 | * is ACKed for CWR bit to reach receiver. */ |
2971 | if (tp->snd_una != tp->high_seq) { | 2940 | if (tp->snd_una != tp->high_seq) { |
2972 | tcp_complete_cwr(sk); | 2941 | tcp_end_cwnd_reduction(sk); |
2973 | tcp_set_ca_state(sk, TCP_CA_Open); | 2942 | tcp_set_ca_state(sk, TCP_CA_Open); |
2974 | } | 2943 | } |
2975 | break; | 2944 | break; |
@@ -2979,7 +2948,7 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, | |||
2979 | tcp_reset_reno_sack(tp); | 2948 | tcp_reset_reno_sack(tp); |
2980 | if (tcp_try_undo_recovery(sk)) | 2949 | if (tcp_try_undo_recovery(sk)) |
2981 | return; | 2950 | return; |
2982 | tcp_complete_cwr(sk); | 2951 | tcp_end_cwnd_reduction(sk); |
2983 | break; | 2952 | break; |
2984 | } | 2953 | } |
2985 | } | 2954 | } |
@@ -2992,6 +2961,7 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, | |||
2992 | tcp_add_reno_sack(sk); | 2961 | tcp_add_reno_sack(sk); |
2993 | } else | 2962 | } else |
2994 | do_lost = tcp_try_undo_partial(sk, pkts_acked); | 2963 | do_lost = tcp_try_undo_partial(sk, pkts_acked); |
2964 | newly_acked_sacked = pkts_acked + tp->sacked_out - prior_sacked; | ||
2995 | break; | 2965 | break; |
2996 | case TCP_CA_Loss: | 2966 | case TCP_CA_Loss: |
2997 | if (flag & FLAG_DATA_ACKED) | 2967 | if (flag & FLAG_DATA_ACKED) |
@@ -3013,12 +2983,13 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, | |||
3013 | if (is_dupack) | 2983 | if (is_dupack) |
3014 | tcp_add_reno_sack(sk); | 2984 | tcp_add_reno_sack(sk); |
3015 | } | 2985 | } |
2986 | newly_acked_sacked = pkts_acked + tp->sacked_out - prior_sacked; | ||
3016 | 2987 | ||
3017 | if (icsk->icsk_ca_state <= TCP_CA_Disorder) | 2988 | if (icsk->icsk_ca_state <= TCP_CA_Disorder) |
3018 | tcp_try_undo_dsack(sk); | 2989 | tcp_try_undo_dsack(sk); |
3019 | 2990 | ||
3020 | if (!tcp_time_to_recover(sk, flag)) { | 2991 | if (!tcp_time_to_recover(sk, flag)) { |
3021 | tcp_try_to_open(sk, flag); | 2992 | tcp_try_to_open(sk, flag, newly_acked_sacked); |
3022 | return; | 2993 | return; |
3023 | } | 2994 | } |
3024 | 2995 | ||
@@ -3040,8 +3011,7 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked, | |||
3040 | 3011 | ||
3041 | if (do_lost || (tcp_is_fack(tp) && tcp_head_timedout(sk))) | 3012 | if (do_lost || (tcp_is_fack(tp) && tcp_head_timedout(sk))) |
3042 | tcp_update_scoreboard(sk, fast_rexmit); | 3013 | tcp_update_scoreboard(sk, fast_rexmit); |
3043 | tp->prr_delivered += newly_acked_sacked; | 3014 | tcp_cwnd_reduction(sk, newly_acked_sacked, fast_rexmit); |
3044 | tcp_update_cwnd_in_recovery(sk, newly_acked_sacked, fast_rexmit, flag); | ||
3045 | tcp_xmit_retransmit_queue(sk); | 3015 | tcp_xmit_retransmit_queue(sk); |
3046 | } | 3016 | } |
3047 | 3017 | ||
@@ -3120,6 +3090,12 @@ void tcp_rearm_rto(struct sock *sk) | |||
3120 | { | 3090 | { |
3121 | struct tcp_sock *tp = tcp_sk(sk); | 3091 | struct tcp_sock *tp = tcp_sk(sk); |
3122 | 3092 | ||
3093 | /* If the retrans timer is currently being used by Fast Open | ||
3094 | * for SYN-ACK retrans purpose, stay put. | ||
3095 | */ | ||
3096 | if (tp->fastopen_rsk) | ||
3097 | return; | ||
3098 | |||
3123 | if (!tp->packets_out) { | 3099 | if (!tp->packets_out) { |
3124 | inet_csk_clear_xmit_timer(sk, ICSK_TIME_RETRANS); | 3100 | inet_csk_clear_xmit_timer(sk, ICSK_TIME_RETRANS); |
3125 | } else { | 3101 | } else { |
@@ -3381,7 +3357,7 @@ static inline bool tcp_may_raise_cwnd(const struct sock *sk, const int flag) | |||
3381 | { | 3357 | { |
3382 | const struct tcp_sock *tp = tcp_sk(sk); | 3358 | const struct tcp_sock *tp = tcp_sk(sk); |
3383 | return (!(flag & FLAG_ECE) || tp->snd_cwnd < tp->snd_ssthresh) && | 3359 | return (!(flag & FLAG_ECE) || tp->snd_cwnd < tp->snd_ssthresh) && |
3384 | !((1 << inet_csk(sk)->icsk_ca_state) & (TCPF_CA_Recovery | TCPF_CA_CWR)); | 3360 | !tcp_in_cwnd_reduction(sk); |
3385 | } | 3361 | } |
3386 | 3362 | ||
3387 | /* Check that window update is acceptable. | 3363 | /* Check that window update is acceptable. |
@@ -3449,9 +3425,9 @@ static void tcp_conservative_spur_to_response(struct tcp_sock *tp) | |||
3449 | } | 3425 | } |
3450 | 3426 | ||
3451 | /* A conservative spurious RTO response algorithm: reduce cwnd using | 3427 | /* A conservative spurious RTO response algorithm: reduce cwnd using |
3452 | * rate halving and continue in congestion avoidance. | 3428 | * PRR and continue in congestion avoidance. |
3453 | */ | 3429 | */ |
3454 | static void tcp_ratehalving_spur_to_response(struct sock *sk) | 3430 | static void tcp_cwr_spur_to_response(struct sock *sk) |
3455 | { | 3431 | { |
3456 | tcp_enter_cwr(sk, 0); | 3432 | tcp_enter_cwr(sk, 0); |
3457 | } | 3433 | } |
@@ -3459,7 +3435,7 @@ static void tcp_ratehalving_spur_to_response(struct sock *sk) | |||
3459 | static void tcp_undo_spur_to_response(struct sock *sk, int flag) | 3435 | static void tcp_undo_spur_to_response(struct sock *sk, int flag) |
3460 | { | 3436 | { |
3461 | if (flag & FLAG_ECE) | 3437 | if (flag & FLAG_ECE) |
3462 | tcp_ratehalving_spur_to_response(sk); | 3438 | tcp_cwr_spur_to_response(sk); |
3463 | else | 3439 | else |
3464 | tcp_undo_cwr(sk, true); | 3440 | tcp_undo_cwr(sk, true); |
3465 | } | 3441 | } |
@@ -3566,7 +3542,7 @@ static bool tcp_process_frto(struct sock *sk, int flag) | |||
3566 | tcp_conservative_spur_to_response(tp); | 3542 | tcp_conservative_spur_to_response(tp); |
3567 | break; | 3543 | break; |
3568 | default: | 3544 | default: |
3569 | tcp_ratehalving_spur_to_response(sk); | 3545 | tcp_cwr_spur_to_response(sk); |
3570 | break; | 3546 | break; |
3571 | } | 3547 | } |
3572 | tp->frto_counter = 0; | 3548 | tp->frto_counter = 0; |
@@ -3590,7 +3566,6 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) | |||
3590 | int prior_packets; | 3566 | int prior_packets; |
3591 | int prior_sacked = tp->sacked_out; | 3567 | int prior_sacked = tp->sacked_out; |
3592 | int pkts_acked = 0; | 3568 | int pkts_acked = 0; |
3593 | int newly_acked_sacked = 0; | ||
3594 | bool frto_cwnd = false; | 3569 | bool frto_cwnd = false; |
3595 | 3570 | ||
3596 | /* If the ack is older than previous acks | 3571 | /* If the ack is older than previous acks |
@@ -3666,8 +3641,6 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) | |||
3666 | flag |= tcp_clean_rtx_queue(sk, prior_fackets, prior_snd_una); | 3641 | flag |= tcp_clean_rtx_queue(sk, prior_fackets, prior_snd_una); |
3667 | 3642 | ||
3668 | pkts_acked = prior_packets - tp->packets_out; | 3643 | pkts_acked = prior_packets - tp->packets_out; |
3669 | newly_acked_sacked = (prior_packets - prior_sacked) - | ||
3670 | (tp->packets_out - tp->sacked_out); | ||
3671 | 3644 | ||
3672 | if (tp->frto_counter) | 3645 | if (tp->frto_counter) |
3673 | frto_cwnd = tcp_process_frto(sk, flag); | 3646 | frto_cwnd = tcp_process_frto(sk, flag); |
@@ -3681,7 +3654,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) | |||
3681 | tcp_may_raise_cwnd(sk, flag)) | 3654 | tcp_may_raise_cwnd(sk, flag)) |
3682 | tcp_cong_avoid(sk, ack, prior_in_flight); | 3655 | tcp_cong_avoid(sk, ack, prior_in_flight); |
3683 | is_dupack = !(flag & (FLAG_SND_UNA_ADVANCED | FLAG_NOT_DUP)); | 3656 | is_dupack = !(flag & (FLAG_SND_UNA_ADVANCED | FLAG_NOT_DUP)); |
3684 | tcp_fastretrans_alert(sk, pkts_acked, newly_acked_sacked, | 3657 | tcp_fastretrans_alert(sk, pkts_acked, prior_sacked, |
3685 | is_dupack, flag); | 3658 | is_dupack, flag); |
3686 | } else { | 3659 | } else { |
3687 | if ((flag & FLAG_DATA_ACKED) && !frto_cwnd) | 3660 | if ((flag & FLAG_DATA_ACKED) && !frto_cwnd) |
@@ -3698,7 +3671,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) | |||
3698 | no_queue: | 3671 | no_queue: |
3699 | /* If data was DSACKed, see if we can undo a cwnd reduction. */ | 3672 | /* If data was DSACKed, see if we can undo a cwnd reduction. */ |
3700 | if (flag & FLAG_DSACKING_ACK) | 3673 | if (flag & FLAG_DSACKING_ACK) |
3701 | tcp_fastretrans_alert(sk, pkts_acked, newly_acked_sacked, | 3674 | tcp_fastretrans_alert(sk, pkts_acked, prior_sacked, |
3702 | is_dupack, flag); | 3675 | is_dupack, flag); |
3703 | /* If this ack opens up a zero window, clear backoff. It was | 3676 | /* If this ack opens up a zero window, clear backoff. It was |
3704 | * being used to time the probes, and is probably far higher than | 3677 | * being used to time the probes, and is probably far higher than |
@@ -3718,8 +3691,7 @@ old_ack: | |||
3718 | */ | 3691 | */ |
3719 | if (TCP_SKB_CB(skb)->sacked) { | 3692 | if (TCP_SKB_CB(skb)->sacked) { |
3720 | flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una); | 3693 | flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una); |
3721 | newly_acked_sacked = tp->sacked_out - prior_sacked; | 3694 | tcp_fastretrans_alert(sk, pkts_acked, prior_sacked, |
3722 | tcp_fastretrans_alert(sk, pkts_acked, newly_acked_sacked, | ||
3723 | is_dupack, flag); | 3695 | is_dupack, flag); |
3724 | } | 3696 | } |
3725 | 3697 | ||
@@ -4035,7 +4007,7 @@ static inline bool tcp_sequence(const struct tcp_sock *tp, u32 seq, u32 end_seq) | |||
4035 | } | 4007 | } |
4036 | 4008 | ||
4037 | /* When we get a reset we do this. */ | 4009 | /* When we get a reset we do this. */ |
4038 | static void tcp_reset(struct sock *sk) | 4010 | void tcp_reset(struct sock *sk) |
4039 | { | 4011 | { |
4040 | /* We want the right error as BSD sees it (and indeed as we do). */ | 4012 | /* We want the right error as BSD sees it (and indeed as we do). */ |
4041 | switch (sk->sk_state) { | 4013 | switch (sk->sk_state) { |
@@ -5392,6 +5364,8 @@ int tcp_rcv_established(struct sock *sk, struct sk_buff *skb, | |||
5392 | { | 5364 | { |
5393 | struct tcp_sock *tp = tcp_sk(sk); | 5365 | struct tcp_sock *tp = tcp_sk(sk); |
5394 | 5366 | ||
5367 | if (unlikely(sk->sk_rx_dst == NULL)) | ||
5368 | inet_csk(sk)->icsk_af_ops->sk_rx_dst_set(sk, skb); | ||
5395 | /* | 5369 | /* |
5396 | * Header prediction. | 5370 | * Header prediction. |
5397 | * The code loosely follows the one in the famous | 5371 | * The code loosely follows the one in the famous |
@@ -5605,7 +5579,7 @@ void tcp_finish_connect(struct sock *sk, struct sk_buff *skb) | |||
5605 | tcp_set_state(sk, TCP_ESTABLISHED); | 5579 | tcp_set_state(sk, TCP_ESTABLISHED); |
5606 | 5580 | ||
5607 | if (skb != NULL) { | 5581 | if (skb != NULL) { |
5608 | inet_sk_rx_dst_set(sk, skb); | 5582 | icsk->icsk_af_ops->sk_rx_dst_set(sk, skb); |
5609 | security_inet_conn_established(sk, skb); | 5583 | security_inet_conn_established(sk, skb); |
5610 | } | 5584 | } |
5611 | 5585 | ||
@@ -5740,7 +5714,7 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, | |||
5740 | 5714 | ||
5741 | TCP_ECN_rcv_synack(tp, th); | 5715 | TCP_ECN_rcv_synack(tp, th); |
5742 | 5716 | ||
5743 | tp->snd_wl1 = TCP_SKB_CB(skb)->seq; | 5717 | tcp_init_wl(tp, TCP_SKB_CB(skb)->seq); |
5744 | tcp_ack(sk, skb, FLAG_SLOWPATH); | 5718 | tcp_ack(sk, skb, FLAG_SLOWPATH); |
5745 | 5719 | ||
5746 | /* Ok.. it's good. Set up sequence numbers and | 5720 | /* Ok.. it's good. Set up sequence numbers and |
@@ -5753,7 +5727,6 @@ static int tcp_rcv_synsent_state_process(struct sock *sk, struct sk_buff *skb, | |||
5753 | * never scaled. | 5727 | * never scaled. |
5754 | */ | 5728 | */ |
5755 | tp->snd_wnd = ntohs(th->window); | 5729 | tp->snd_wnd = ntohs(th->window); |
5756 | tcp_init_wl(tp, TCP_SKB_CB(skb)->seq); | ||
5757 | 5730 | ||
5758 | if (!tp->rx_opt.wscale_ok) { | 5731 | if (!tp->rx_opt.wscale_ok) { |
5759 | tp->rx_opt.snd_wscale = tp->rx_opt.rcv_wscale = 0; | 5732 | tp->rx_opt.snd_wscale = tp->rx_opt.rcv_wscale = 0; |
@@ -5891,7 +5864,9 @@ discard: | |||
5891 | tcp_send_synack(sk); | 5864 | tcp_send_synack(sk); |
5892 | #if 0 | 5865 | #if 0 |
5893 | /* Note, we could accept data and URG from this segment. | 5866 | /* Note, we could accept data and URG from this segment. |
5894 | * There are no obstacles to make this. | 5867 | * There are no obstacles to make this (except that we must |
5868 | * either change tcp_recvmsg() to prevent it from returning data | ||
5869 | * before 3WHS completes per RFC793, or employ TCP Fast Open). | ||
5895 | * | 5870 | * |
5896 | * However, if we ignore data in ACKless segments sometimes, | 5871 | * However, if we ignore data in ACKless segments sometimes, |
5897 | * we have no reasons to accept it sometimes. | 5872 | * we have no reasons to accept it sometimes. |
@@ -5931,6 +5906,7 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
5931 | { | 5906 | { |
5932 | struct tcp_sock *tp = tcp_sk(sk); | 5907 | struct tcp_sock *tp = tcp_sk(sk); |
5933 | struct inet_connection_sock *icsk = inet_csk(sk); | 5908 | struct inet_connection_sock *icsk = inet_csk(sk); |
5909 | struct request_sock *req; | ||
5934 | int queued = 0; | 5910 | int queued = 0; |
5935 | 5911 | ||
5936 | tp->rx_opt.saw_tstamp = 0; | 5912 | tp->rx_opt.saw_tstamp = 0; |
@@ -5986,7 +5962,14 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
5986 | return 0; | 5962 | return 0; |
5987 | } | 5963 | } |
5988 | 5964 | ||
5989 | if (!tcp_validate_incoming(sk, skb, th, 0)) | 5965 | req = tp->fastopen_rsk; |
5966 | if (req != NULL) { | ||
5967 | BUG_ON(sk->sk_state != TCP_SYN_RECV && | ||
5968 | sk->sk_state != TCP_FIN_WAIT1); | ||
5969 | |||
5970 | if (tcp_check_req(sk, skb, req, NULL, true) == NULL) | ||
5971 | goto discard; | ||
5972 | } else if (!tcp_validate_incoming(sk, skb, th, 0)) | ||
5990 | return 0; | 5973 | return 0; |
5991 | 5974 | ||
5992 | /* step 5: check the ACK field */ | 5975 | /* step 5: check the ACK field */ |
@@ -5996,7 +5979,22 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
5996 | switch (sk->sk_state) { | 5979 | switch (sk->sk_state) { |
5997 | case TCP_SYN_RECV: | 5980 | case TCP_SYN_RECV: |
5998 | if (acceptable) { | 5981 | if (acceptable) { |
5999 | tp->copied_seq = tp->rcv_nxt; | 5982 | /* Once we leave TCP_SYN_RECV, we no longer |
5983 | * need req so release it. | ||
5984 | */ | ||
5985 | if (req) { | ||
5986 | reqsk_fastopen_remove(sk, req, false); | ||
5987 | } else { | ||
5988 | /* Make sure socket is routed, for | ||
5989 | * correct metrics. | ||
5990 | */ | ||
5991 | icsk->icsk_af_ops->rebuild_header(sk); | ||
5992 | tcp_init_congestion_control(sk); | ||
5993 | |||
5994 | tcp_mtup_init(sk); | ||
5995 | tcp_init_buffer_space(sk); | ||
5996 | tp->copied_seq = tp->rcv_nxt; | ||
5997 | } | ||
6000 | smp_mb(); | 5998 | smp_mb(); |
6001 | tcp_set_state(sk, TCP_ESTABLISHED); | 5999 | tcp_set_state(sk, TCP_ESTABLISHED); |
6002 | sk->sk_state_change(sk); | 6000 | sk->sk_state_change(sk); |
@@ -6018,23 +6016,27 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
6018 | if (tp->rx_opt.tstamp_ok) | 6016 | if (tp->rx_opt.tstamp_ok) |
6019 | tp->advmss -= TCPOLEN_TSTAMP_ALIGNED; | 6017 | tp->advmss -= TCPOLEN_TSTAMP_ALIGNED; |
6020 | 6018 | ||
6021 | /* Make sure socket is routed, for | 6019 | if (req) { |
6022 | * correct metrics. | 6020 | /* Re-arm the timer because data may |
6023 | */ | 6021 | * have been sent out. This is similar |
6024 | icsk->icsk_af_ops->rebuild_header(sk); | 6022 | * to the regular data transmission case |
6025 | 6023 | * when new data has just been ack'ed. | |
6026 | tcp_init_metrics(sk); | 6024 | * |
6027 | 6025 | * (TFO) - we could try to be more | |
6028 | tcp_init_congestion_control(sk); | 6026 | * aggressive and retranmitting any data |
6027 | * sooner based on when they were sent | ||
6028 | * out. | ||
6029 | */ | ||
6030 | tcp_rearm_rto(sk); | ||
6031 | } else | ||
6032 | tcp_init_metrics(sk); | ||
6029 | 6033 | ||
6030 | /* Prevent spurious tcp_cwnd_restart() on | 6034 | /* Prevent spurious tcp_cwnd_restart() on |
6031 | * first data packet. | 6035 | * first data packet. |
6032 | */ | 6036 | */ |
6033 | tp->lsndtime = tcp_time_stamp; | 6037 | tp->lsndtime = tcp_time_stamp; |
6034 | 6038 | ||
6035 | tcp_mtup_init(sk); | ||
6036 | tcp_initialize_rcv_mss(sk); | 6039 | tcp_initialize_rcv_mss(sk); |
6037 | tcp_init_buffer_space(sk); | ||
6038 | tcp_fast_path_on(tp); | 6040 | tcp_fast_path_on(tp); |
6039 | } else { | 6041 | } else { |
6040 | return 1; | 6042 | return 1; |
@@ -6042,6 +6044,16 @@ int tcp_rcv_state_process(struct sock *sk, struct sk_buff *skb, | |||
6042 | break; | 6044 | break; |
6043 | 6045 | ||
6044 | case TCP_FIN_WAIT1: | 6046 | case TCP_FIN_WAIT1: |
6047 | /* If we enter the TCP_FIN_WAIT1 state and we are a | ||
6048 | * Fast Open socket and this is the first acceptable | ||
6049 | * ACK we have received, this would have acknowledged | ||
6050 | * our SYNACK so stop the SYNACK timer. | ||
6051 | */ | ||
6052 | if (acceptable && req != NULL) { | ||
6053 | /* We no longer need the request sock. */ | ||
6054 | reqsk_fastopen_remove(sk, req, false); | ||
6055 | tcp_rearm_rto(sk); | ||
6056 | } | ||
6045 | if (tp->snd_una == tp->write_seq) { | 6057 | if (tp->snd_una == tp->write_seq) { |
6046 | struct dst_entry *dst; | 6058 | struct dst_entry *dst; |
6047 | 6059 | ||
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 42b2a6a73092..e64abed249cc 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -352,6 +352,7 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) | |||
352 | const int code = icmp_hdr(icmp_skb)->code; | 352 | const int code = icmp_hdr(icmp_skb)->code; |
353 | struct sock *sk; | 353 | struct sock *sk; |
354 | struct sk_buff *skb; | 354 | struct sk_buff *skb; |
355 | struct request_sock *req; | ||
355 | __u32 seq; | 356 | __u32 seq; |
356 | __u32 remaining; | 357 | __u32 remaining; |
357 | int err; | 358 | int err; |
@@ -394,9 +395,12 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) | |||
394 | 395 | ||
395 | icsk = inet_csk(sk); | 396 | icsk = inet_csk(sk); |
396 | tp = tcp_sk(sk); | 397 | tp = tcp_sk(sk); |
398 | req = tp->fastopen_rsk; | ||
397 | seq = ntohl(th->seq); | 399 | seq = ntohl(th->seq); |
398 | if (sk->sk_state != TCP_LISTEN && | 400 | if (sk->sk_state != TCP_LISTEN && |
399 | !between(seq, tp->snd_una, tp->snd_nxt)) { | 401 | !between(seq, tp->snd_una, tp->snd_nxt) && |
402 | (req == NULL || seq != tcp_rsk(req)->snt_isn)) { | ||
403 | /* For a Fast Open socket, allow seq to be snt_isn. */ | ||
400 | NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS); | 404 | NET_INC_STATS_BH(net, LINUX_MIB_OUTOFWINDOWICMPS); |
401 | goto out; | 405 | goto out; |
402 | } | 406 | } |
@@ -417,10 +421,12 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) | |||
417 | 421 | ||
418 | if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */ | 422 | if (code == ICMP_FRAG_NEEDED) { /* PMTU discovery (RFC1191) */ |
419 | tp->mtu_info = info; | 423 | tp->mtu_info = info; |
420 | if (!sock_owned_by_user(sk)) | 424 | if (!sock_owned_by_user(sk)) { |
421 | tcp_v4_mtu_reduced(sk); | 425 | tcp_v4_mtu_reduced(sk); |
422 | else | 426 | } else { |
423 | set_bit(TCP_MTU_REDUCED_DEFERRED, &tp->tsq_flags); | 427 | if (!test_and_set_bit(TCP_MTU_REDUCED_DEFERRED, &tp->tsq_flags)) |
428 | sock_hold(sk); | ||
429 | } | ||
424 | goto out; | 430 | goto out; |
425 | } | 431 | } |
426 | 432 | ||
@@ -433,6 +439,8 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) | |||
433 | !icsk->icsk_backoff) | 439 | !icsk->icsk_backoff) |
434 | break; | 440 | break; |
435 | 441 | ||
442 | /* XXX (TFO) - revisit the following logic for TFO */ | ||
443 | |||
436 | if (sock_owned_by_user(sk)) | 444 | if (sock_owned_by_user(sk)) |
437 | break; | 445 | break; |
438 | 446 | ||
@@ -464,6 +472,14 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) | |||
464 | goto out; | 472 | goto out; |
465 | } | 473 | } |
466 | 474 | ||
475 | /* XXX (TFO) - if it's a TFO socket and has been accepted, rather | ||
476 | * than following the TCP_SYN_RECV case and closing the socket, | ||
477 | * we ignore the ICMP error and keep trying like a fully established | ||
478 | * socket. Is this the right thing to do? | ||
479 | */ | ||
480 | if (req && req->sk == NULL) | ||
481 | goto out; | ||
482 | |||
467 | switch (sk->sk_state) { | 483 | switch (sk->sk_state) { |
468 | struct request_sock *req, **prev; | 484 | struct request_sock *req, **prev; |
469 | case TCP_LISTEN: | 485 | case TCP_LISTEN: |
@@ -496,7 +512,8 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) | |||
496 | 512 | ||
497 | case TCP_SYN_SENT: | 513 | case TCP_SYN_SENT: |
498 | case TCP_SYN_RECV: /* Cannot happen. | 514 | case TCP_SYN_RECV: /* Cannot happen. |
499 | It can f.e. if SYNs crossed. | 515 | It can f.e. if SYNs crossed, |
516 | or Fast Open. | ||
500 | */ | 517 | */ |
501 | if (!sock_owned_by_user(sk)) { | 518 | if (!sock_owned_by_user(sk)) { |
502 | sk->sk_err = err; | 519 | sk->sk_err = err; |
@@ -807,8 +824,12 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb) | |||
807 | static void tcp_v4_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, | 824 | static void tcp_v4_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, |
808 | struct request_sock *req) | 825 | struct request_sock *req) |
809 | { | 826 | { |
810 | tcp_v4_send_ack(skb, tcp_rsk(req)->snt_isn + 1, | 827 | /* sk->sk_state == TCP_LISTEN -> for regular TCP_SYN_RECV |
811 | tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd, | 828 | * sk->sk_state == TCP_SYN_RECV -> for Fast Open. |
829 | */ | ||
830 | tcp_v4_send_ack(skb, (sk->sk_state == TCP_LISTEN) ? | ||
831 | tcp_rsk(req)->snt_isn + 1 : tcp_sk(sk)->snd_nxt, | ||
832 | tcp_rsk(req)->rcv_nxt, req->rcv_wnd, | ||
812 | req->ts_recent, | 833 | req->ts_recent, |
813 | 0, | 834 | 0, |
814 | tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&ip_hdr(skb)->daddr, | 835 | tcp_md5_do_lookup(sk, (union tcp_md5_addr *)&ip_hdr(skb)->daddr, |
@@ -837,7 +858,7 @@ static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst, | |||
837 | if (!dst && (dst = inet_csk_route_req(sk, &fl4, req)) == NULL) | 858 | if (!dst && (dst = inet_csk_route_req(sk, &fl4, req)) == NULL) |
838 | return -1; | 859 | return -1; |
839 | 860 | ||
840 | skb = tcp_make_synack(sk, dst, req, rvp); | 861 | skb = tcp_make_synack(sk, dst, req, rvp, NULL); |
841 | 862 | ||
842 | if (skb) { | 863 | if (skb) { |
843 | __tcp_v4_send_check(skb, ireq->loc_addr, ireq->rmt_addr); | 864 | __tcp_v4_send_check(skb, ireq->loc_addr, ireq->rmt_addr); |
@@ -1270,6 +1291,178 @@ static const struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = { | |||
1270 | }; | 1291 | }; |
1271 | #endif | 1292 | #endif |
1272 | 1293 | ||
1294 | static bool tcp_fastopen_check(struct sock *sk, struct sk_buff *skb, | ||
1295 | struct request_sock *req, | ||
1296 | struct tcp_fastopen_cookie *foc, | ||
1297 | struct tcp_fastopen_cookie *valid_foc) | ||
1298 | { | ||
1299 | bool skip_cookie = false; | ||
1300 | struct fastopen_queue *fastopenq; | ||
1301 | |||
1302 | if (likely(!fastopen_cookie_present(foc))) { | ||
1303 | /* See include/net/tcp.h for the meaning of these knobs */ | ||
1304 | if ((sysctl_tcp_fastopen & TFO_SERVER_ALWAYS) || | ||
1305 | ((sysctl_tcp_fastopen & TFO_SERVER_COOKIE_NOT_REQD) && | ||
1306 | (TCP_SKB_CB(skb)->end_seq != TCP_SKB_CB(skb)->seq + 1))) | ||
1307 | skip_cookie = true; /* no cookie to validate */ | ||
1308 | else | ||
1309 | return false; | ||
1310 | } | ||
1311 | fastopenq = inet_csk(sk)->icsk_accept_queue.fastopenq; | ||
1312 | /* A FO option is present; bump the counter. */ | ||
1313 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPFASTOPENPASSIVE); | ||
1314 | |||
1315 | /* Make sure the listener has enabled fastopen, and we don't | ||
1316 | * exceed the max # of pending TFO requests allowed before trying | ||
1317 | * to validating the cookie in order to avoid burning CPU cycles | ||
1318 | * unnecessarily. | ||
1319 | * | ||
1320 | * XXX (TFO) - The implication of checking the max_qlen before | ||
1321 | * processing a cookie request is that clients can't differentiate | ||
1322 | * between qlen overflow causing Fast Open to be disabled | ||
1323 | * temporarily vs a server not supporting Fast Open at all. | ||
1324 | */ | ||
1325 | if ((sysctl_tcp_fastopen & TFO_SERVER_ENABLE) == 0 || | ||
1326 | fastopenq == NULL || fastopenq->max_qlen == 0) | ||
1327 | return false; | ||
1328 | |||
1329 | if (fastopenq->qlen >= fastopenq->max_qlen) { | ||
1330 | struct request_sock *req1; | ||
1331 | spin_lock(&fastopenq->lock); | ||
1332 | req1 = fastopenq->rskq_rst_head; | ||
1333 | if ((req1 == NULL) || time_after(req1->expires, jiffies)) { | ||
1334 | spin_unlock(&fastopenq->lock); | ||
1335 | NET_INC_STATS_BH(sock_net(sk), | ||
1336 | LINUX_MIB_TCPFASTOPENLISTENOVERFLOW); | ||
1337 | /* Avoid bumping LINUX_MIB_TCPFASTOPENPASSIVEFAIL*/ | ||
1338 | foc->len = -1; | ||
1339 | return false; | ||
1340 | } | ||
1341 | fastopenq->rskq_rst_head = req1->dl_next; | ||
1342 | fastopenq->qlen--; | ||
1343 | spin_unlock(&fastopenq->lock); | ||
1344 | reqsk_free(req1); | ||
1345 | } | ||
1346 | if (skip_cookie) { | ||
1347 | tcp_rsk(req)->rcv_nxt = TCP_SKB_CB(skb)->end_seq; | ||
1348 | return true; | ||
1349 | } | ||
1350 | if (foc->len == TCP_FASTOPEN_COOKIE_SIZE) { | ||
1351 | if ((sysctl_tcp_fastopen & TFO_SERVER_COOKIE_NOT_CHKED) == 0) { | ||
1352 | tcp_fastopen_cookie_gen(ip_hdr(skb)->saddr, valid_foc); | ||
1353 | if ((valid_foc->len != TCP_FASTOPEN_COOKIE_SIZE) || | ||
1354 | memcmp(&foc->val[0], &valid_foc->val[0], | ||
1355 | TCP_FASTOPEN_COOKIE_SIZE) != 0) | ||
1356 | return false; | ||
1357 | valid_foc->len = -1; | ||
1358 | } | ||
1359 | /* Acknowledge the data received from the peer. */ | ||
1360 | tcp_rsk(req)->rcv_nxt = TCP_SKB_CB(skb)->end_seq; | ||
1361 | return true; | ||
1362 | } else if (foc->len == 0) { /* Client requesting a cookie */ | ||
1363 | tcp_fastopen_cookie_gen(ip_hdr(skb)->saddr, valid_foc); | ||
1364 | NET_INC_STATS_BH(sock_net(sk), | ||
1365 | LINUX_MIB_TCPFASTOPENCOOKIEREQD); | ||
1366 | } else { | ||
1367 | /* Client sent a cookie with wrong size. Treat it | ||
1368 | * the same as invalid and return a valid one. | ||
1369 | */ | ||
1370 | tcp_fastopen_cookie_gen(ip_hdr(skb)->saddr, valid_foc); | ||
1371 | } | ||
1372 | return false; | ||
1373 | } | ||
1374 | |||
1375 | static int tcp_v4_conn_req_fastopen(struct sock *sk, | ||
1376 | struct sk_buff *skb, | ||
1377 | struct sk_buff *skb_synack, | ||
1378 | struct request_sock *req, | ||
1379 | struct request_values *rvp) | ||
1380 | { | ||
1381 | struct tcp_sock *tp = tcp_sk(sk); | ||
1382 | struct request_sock_queue *queue = &inet_csk(sk)->icsk_accept_queue; | ||
1383 | const struct inet_request_sock *ireq = inet_rsk(req); | ||
1384 | struct sock *child; | ||
1385 | |||
1386 | req->retrans = 0; | ||
1387 | req->sk = NULL; | ||
1388 | |||
1389 | child = inet_csk(sk)->icsk_af_ops->syn_recv_sock(sk, skb, req, NULL); | ||
1390 | if (child == NULL) { | ||
1391 | NET_INC_STATS_BH(sock_net(sk), | ||
1392 | LINUX_MIB_TCPFASTOPENPASSIVEFAIL); | ||
1393 | kfree_skb(skb_synack); | ||
1394 | return -1; | ||
1395 | } | ||
1396 | ip_build_and_send_pkt(skb_synack, sk, ireq->loc_addr, | ||
1397 | ireq->rmt_addr, ireq->opt); | ||
1398 | /* XXX (TFO) - is it ok to ignore error and continue? */ | ||
1399 | |||
1400 | spin_lock(&queue->fastopenq->lock); | ||
1401 | queue->fastopenq->qlen++; | ||
1402 | spin_unlock(&queue->fastopenq->lock); | ||
1403 | |||
1404 | /* Initialize the child socket. Have to fix some values to take | ||
1405 | * into account the child is a Fast Open socket and is created | ||
1406 | * only out of the bits carried in the SYN packet. | ||
1407 | */ | ||
1408 | tp = tcp_sk(child); | ||
1409 | |||
1410 | tp->fastopen_rsk = req; | ||
1411 | /* Do a hold on the listner sk so that if the listener is being | ||
1412 | * closed, the child that has been accepted can live on and still | ||
1413 | * access listen_lock. | ||
1414 | */ | ||
1415 | sock_hold(sk); | ||
1416 | tcp_rsk(req)->listener = sk; | ||
1417 | |||
1418 | /* RFC1323: The window in SYN & SYN/ACK segments is never | ||
1419 | * scaled. So correct it appropriately. | ||
1420 | */ | ||
1421 | tp->snd_wnd = ntohs(tcp_hdr(skb)->window); | ||
1422 | |||
1423 | /* Activate the retrans timer so that SYNACK can be retransmitted. | ||
1424 | * The request socket is not added to the SYN table of the parent | ||
1425 | * because it's been added to the accept queue directly. | ||
1426 | */ | ||
1427 | inet_csk_reset_xmit_timer(child, ICSK_TIME_RETRANS, | ||
1428 | TCP_TIMEOUT_INIT, TCP_RTO_MAX); | ||
1429 | |||
1430 | /* Add the child socket directly into the accept queue */ | ||
1431 | inet_csk_reqsk_queue_add(sk, req, child); | ||
1432 | |||
1433 | /* Now finish processing the fastopen child socket. */ | ||
1434 | inet_csk(child)->icsk_af_ops->rebuild_header(child); | ||
1435 | tcp_init_congestion_control(child); | ||
1436 | tcp_mtup_init(child); | ||
1437 | tcp_init_buffer_space(child); | ||
1438 | tcp_init_metrics(child); | ||
1439 | |||
1440 | /* Queue the data carried in the SYN packet. We need to first | ||
1441 | * bump skb's refcnt because the caller will attempt to free it. | ||
1442 | * | ||
1443 | * XXX (TFO) - we honor a zero-payload TFO request for now. | ||
1444 | * (Any reason not to?) | ||
1445 | */ | ||
1446 | if (TCP_SKB_CB(skb)->end_seq == TCP_SKB_CB(skb)->seq + 1) { | ||
1447 | /* Don't queue the skb if there is no payload in SYN. | ||
1448 | * XXX (TFO) - How about SYN+FIN? | ||
1449 | */ | ||
1450 | tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq; | ||
1451 | } else { | ||
1452 | skb = skb_get(skb); | ||
1453 | skb_dst_drop(skb); | ||
1454 | __skb_pull(skb, tcp_hdr(skb)->doff * 4); | ||
1455 | skb_set_owner_r(skb, child); | ||
1456 | __skb_queue_tail(&child->sk_receive_queue, skb); | ||
1457 | tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq; | ||
1458 | } | ||
1459 | sk->sk_data_ready(sk, 0); | ||
1460 | bh_unlock_sock(child); | ||
1461 | sock_put(child); | ||
1462 | WARN_ON(req->sk == NULL); | ||
1463 | return 0; | ||
1464 | } | ||
1465 | |||
1273 | int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | 1466 | int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) |
1274 | { | 1467 | { |
1275 | struct tcp_extend_values tmp_ext; | 1468 | struct tcp_extend_values tmp_ext; |
@@ -1283,6 +1476,11 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1283 | __be32 daddr = ip_hdr(skb)->daddr; | 1476 | __be32 daddr = ip_hdr(skb)->daddr; |
1284 | __u32 isn = TCP_SKB_CB(skb)->when; | 1477 | __u32 isn = TCP_SKB_CB(skb)->when; |
1285 | bool want_cookie = false; | 1478 | bool want_cookie = false; |
1479 | struct flowi4 fl4; | ||
1480 | struct tcp_fastopen_cookie foc = { .len = -1 }; | ||
1481 | struct tcp_fastopen_cookie valid_foc = { .len = -1 }; | ||
1482 | struct sk_buff *skb_synack; | ||
1483 | int do_fastopen; | ||
1286 | 1484 | ||
1287 | /* Never answer to SYNs send to broadcast or multicast */ | 1485 | /* Never answer to SYNs send to broadcast or multicast */ |
1288 | if (skb_rtable(skb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) | 1486 | if (skb_rtable(skb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) |
@@ -1317,7 +1515,8 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1317 | tcp_clear_options(&tmp_opt); | 1515 | tcp_clear_options(&tmp_opt); |
1318 | tmp_opt.mss_clamp = TCP_MSS_DEFAULT; | 1516 | tmp_opt.mss_clamp = TCP_MSS_DEFAULT; |
1319 | tmp_opt.user_mss = tp->rx_opt.user_mss; | 1517 | tmp_opt.user_mss = tp->rx_opt.user_mss; |
1320 | tcp_parse_options(skb, &tmp_opt, &hash_location, 0, NULL); | 1518 | tcp_parse_options(skb, &tmp_opt, &hash_location, 0, |
1519 | want_cookie ? NULL : &foc); | ||
1321 | 1520 | ||
1322 | if (tmp_opt.cookie_plus > 0 && | 1521 | if (tmp_opt.cookie_plus > 0 && |
1323 | tmp_opt.saw_tstamp && | 1522 | tmp_opt.saw_tstamp && |
@@ -1375,8 +1574,6 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1375 | isn = cookie_v4_init_sequence(sk, skb, &req->mss); | 1574 | isn = cookie_v4_init_sequence(sk, skb, &req->mss); |
1376 | req->cookie_ts = tmp_opt.tstamp_ok; | 1575 | req->cookie_ts = tmp_opt.tstamp_ok; |
1377 | } else if (!isn) { | 1576 | } else if (!isn) { |
1378 | struct flowi4 fl4; | ||
1379 | |||
1380 | /* VJ's idea. We save last timestamp seen | 1577 | /* VJ's idea. We save last timestamp seen |
1381 | * from the destination in peer table, when entering | 1578 | * from the destination in peer table, when entering |
1382 | * state TIME-WAIT, and check against it before | 1579 | * state TIME-WAIT, and check against it before |
@@ -1417,14 +1614,52 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | |||
1417 | tcp_rsk(req)->snt_isn = isn; | 1614 | tcp_rsk(req)->snt_isn = isn; |
1418 | tcp_rsk(req)->snt_synack = tcp_time_stamp; | 1615 | tcp_rsk(req)->snt_synack = tcp_time_stamp; |
1419 | 1616 | ||
1420 | if (tcp_v4_send_synack(sk, dst, req, | 1617 | if (dst == NULL) { |
1421 | (struct request_values *)&tmp_ext, | 1618 | dst = inet_csk_route_req(sk, &fl4, req); |
1422 | skb_get_queue_mapping(skb), | 1619 | if (dst == NULL) |
1423 | want_cookie) || | 1620 | goto drop_and_free; |
1424 | want_cookie) | 1621 | } |
1622 | do_fastopen = tcp_fastopen_check(sk, skb, req, &foc, &valid_foc); | ||
1623 | |||
1624 | /* We don't call tcp_v4_send_synack() directly because we need | ||
1625 | * to make sure a child socket can be created successfully before | ||
1626 | * sending back synack! | ||
1627 | * | ||
1628 | * XXX (TFO) - Ideally one would simply call tcp_v4_send_synack() | ||
1629 | * (or better yet, call tcp_send_synack() in the child context | ||
1630 | * directly, but will have to fix bunch of other code first) | ||
1631 | * after syn_recv_sock() except one will need to first fix the | ||
1632 | * latter to remove its dependency on the current implementation | ||
1633 | * of tcp_v4_send_synack()->tcp_select_initial_window(). | ||
1634 | */ | ||
1635 | skb_synack = tcp_make_synack(sk, dst, req, | ||
1636 | (struct request_values *)&tmp_ext, | ||
1637 | fastopen_cookie_present(&valid_foc) ? &valid_foc : NULL); | ||
1638 | |||
1639 | if (skb_synack) { | ||
1640 | __tcp_v4_send_check(skb_synack, ireq->loc_addr, ireq->rmt_addr); | ||
1641 | skb_set_queue_mapping(skb_synack, skb_get_queue_mapping(skb)); | ||
1642 | } else | ||
1643 | goto drop_and_free; | ||
1644 | |||
1645 | if (likely(!do_fastopen)) { | ||
1646 | int err; | ||
1647 | err = ip_build_and_send_pkt(skb_synack, sk, ireq->loc_addr, | ||
1648 | ireq->rmt_addr, ireq->opt); | ||
1649 | err = net_xmit_eval(err); | ||
1650 | if (err || want_cookie) | ||
1651 | goto drop_and_free; | ||
1652 | |||
1653 | tcp_rsk(req)->listener = NULL; | ||
1654 | /* Add the request_sock to the SYN table */ | ||
1655 | inet_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); | ||
1656 | if (fastopen_cookie_present(&foc) && foc.len != 0) | ||
1657 | NET_INC_STATS_BH(sock_net(sk), | ||
1658 | LINUX_MIB_TCPFASTOPENPASSIVEFAIL); | ||
1659 | } else if (tcp_v4_conn_req_fastopen(sk, skb, skb_synack, req, | ||
1660 | (struct request_values *)&tmp_ext)) | ||
1425 | goto drop_and_free; | 1661 | goto drop_and_free; |
1426 | 1662 | ||
1427 | inet_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); | ||
1428 | return 0; | 1663 | return 0; |
1429 | 1664 | ||
1430 | drop_and_release: | 1665 | drop_and_release: |
@@ -1462,6 +1697,7 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1462 | goto exit_nonewsk; | 1697 | goto exit_nonewsk; |
1463 | 1698 | ||
1464 | newsk->sk_gso_type = SKB_GSO_TCPV4; | 1699 | newsk->sk_gso_type = SKB_GSO_TCPV4; |
1700 | inet_sk_rx_dst_set(newsk, skb); | ||
1465 | 1701 | ||
1466 | newtp = tcp_sk(newsk); | 1702 | newtp = tcp_sk(newsk); |
1467 | newinet = inet_sk(newsk); | 1703 | newinet = inet_sk(newsk); |
@@ -1551,7 +1787,7 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb) | |||
1551 | struct request_sock *req = inet_csk_search_req(sk, &prev, th->source, | 1787 | struct request_sock *req = inet_csk_search_req(sk, &prev, th->source, |
1552 | iph->saddr, iph->daddr); | 1788 | iph->saddr, iph->daddr); |
1553 | if (req) | 1789 | if (req) |
1554 | return tcp_check_req(sk, skb, req, prev); | 1790 | return tcp_check_req(sk, skb, req, prev, false); |
1555 | 1791 | ||
1556 | nsk = inet_lookup_established(sock_net(sk), &tcp_hashinfo, iph->saddr, | 1792 | nsk = inet_lookup_established(sock_net(sk), &tcp_hashinfo, iph->saddr, |
1557 | th->source, iph->daddr, th->dest, inet_iif(skb)); | 1793 | th->source, iph->daddr, th->dest, inet_iif(skb)); |
@@ -1627,9 +1863,6 @@ int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
1627 | sk->sk_rx_dst = NULL; | 1863 | sk->sk_rx_dst = NULL; |
1628 | } | 1864 | } |
1629 | } | 1865 | } |
1630 | if (unlikely(sk->sk_rx_dst == NULL)) | ||
1631 | inet_sk_rx_dst_set(sk, skb); | ||
1632 | |||
1633 | if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) { | 1866 | if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) { |
1634 | rsk = sk; | 1867 | rsk = sk; |
1635 | goto reset; | 1868 | goto reset; |
@@ -1872,10 +2105,21 @@ static struct timewait_sock_ops tcp_timewait_sock_ops = { | |||
1872 | .twsk_destructor= tcp_twsk_destructor, | 2105 | .twsk_destructor= tcp_twsk_destructor, |
1873 | }; | 2106 | }; |
1874 | 2107 | ||
2108 | void inet_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) | ||
2109 | { | ||
2110 | struct dst_entry *dst = skb_dst(skb); | ||
2111 | |||
2112 | dst_hold(dst); | ||
2113 | sk->sk_rx_dst = dst; | ||
2114 | inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; | ||
2115 | } | ||
2116 | EXPORT_SYMBOL(inet_sk_rx_dst_set); | ||
2117 | |||
1875 | const struct inet_connection_sock_af_ops ipv4_specific = { | 2118 | const struct inet_connection_sock_af_ops ipv4_specific = { |
1876 | .queue_xmit = ip_queue_xmit, | 2119 | .queue_xmit = ip_queue_xmit, |
1877 | .send_check = tcp_v4_send_check, | 2120 | .send_check = tcp_v4_send_check, |
1878 | .rebuild_header = inet_sk_rebuild_header, | 2121 | .rebuild_header = inet_sk_rebuild_header, |
2122 | .sk_rx_dst_set = inet_sk_rx_dst_set, | ||
1879 | .conn_request = tcp_v4_conn_request, | 2123 | .conn_request = tcp_v4_conn_request, |
1880 | .syn_recv_sock = tcp_v4_syn_recv_sock, | 2124 | .syn_recv_sock = tcp_v4_syn_recv_sock, |
1881 | .net_header_len = sizeof(struct iphdr), | 2125 | .net_header_len = sizeof(struct iphdr), |
@@ -1966,6 +2210,7 @@ void tcp_v4_destroy_sock(struct sock *sk) | |||
1966 | tcp_cookie_values_release); | 2210 | tcp_cookie_values_release); |
1967 | tp->cookie_values = NULL; | 2211 | tp->cookie_values = NULL; |
1968 | } | 2212 | } |
2213 | BUG_ON(tp->fastopen_rsk != NULL); | ||
1969 | 2214 | ||
1970 | /* If socket is aborted during connect operation */ | 2215 | /* If socket is aborted during connect operation */ |
1971 | tcp_free_fastopen_req(tp); | 2216 | tcp_free_fastopen_req(tp); |
@@ -2382,10 +2627,10 @@ void tcp_proc_unregister(struct net *net, struct tcp_seq_afinfo *afinfo) | |||
2382 | EXPORT_SYMBOL(tcp_proc_unregister); | 2627 | EXPORT_SYMBOL(tcp_proc_unregister); |
2383 | 2628 | ||
2384 | static void get_openreq4(const struct sock *sk, const struct request_sock *req, | 2629 | static void get_openreq4(const struct sock *sk, const struct request_sock *req, |
2385 | struct seq_file *f, int i, int uid, int *len) | 2630 | struct seq_file *f, int i, kuid_t uid, int *len) |
2386 | { | 2631 | { |
2387 | const struct inet_request_sock *ireq = inet_rsk(req); | 2632 | const struct inet_request_sock *ireq = inet_rsk(req); |
2388 | int ttd = req->expires - jiffies; | 2633 | long delta = req->expires - jiffies; |
2389 | 2634 | ||
2390 | seq_printf(f, "%4d: %08X:%04X %08X:%04X" | 2635 | seq_printf(f, "%4d: %08X:%04X %08X:%04X" |
2391 | " %02X %08X:%08X %02X:%08lX %08X %5d %8d %u %d %pK%n", | 2636 | " %02X %08X:%08X %02X:%08lX %08X %5d %8d %u %d %pK%n", |
@@ -2397,9 +2642,9 @@ static void get_openreq4(const struct sock *sk, const struct request_sock *req, | |||
2397 | TCP_SYN_RECV, | 2642 | TCP_SYN_RECV, |
2398 | 0, 0, /* could print option size, but that is af dependent. */ | 2643 | 0, 0, /* could print option size, but that is af dependent. */ |
2399 | 1, /* timers active (only the expire timer) */ | 2644 | 1, /* timers active (only the expire timer) */ |
2400 | jiffies_to_clock_t(ttd), | 2645 | jiffies_delta_to_clock_t(delta), |
2401 | req->retrans, | 2646 | req->retrans, |
2402 | uid, | 2647 | from_kuid_munged(seq_user_ns(f), uid), |
2403 | 0, /* non standard timer */ | 2648 | 0, /* non standard timer */ |
2404 | 0, /* open_requests have no inode */ | 2649 | 0, /* open_requests have no inode */ |
2405 | atomic_read(&sk->sk_refcnt), | 2650 | atomic_read(&sk->sk_refcnt), |
@@ -2414,6 +2659,7 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i, int *len) | |||
2414 | const struct tcp_sock *tp = tcp_sk(sk); | 2659 | const struct tcp_sock *tp = tcp_sk(sk); |
2415 | const struct inet_connection_sock *icsk = inet_csk(sk); | 2660 | const struct inet_connection_sock *icsk = inet_csk(sk); |
2416 | const struct inet_sock *inet = inet_sk(sk); | 2661 | const struct inet_sock *inet = inet_sk(sk); |
2662 | struct fastopen_queue *fastopenq = icsk->icsk_accept_queue.fastopenq; | ||
2417 | __be32 dest = inet->inet_daddr; | 2663 | __be32 dest = inet->inet_daddr; |
2418 | __be32 src = inet->inet_rcv_saddr; | 2664 | __be32 src = inet->inet_rcv_saddr; |
2419 | __u16 destp = ntohs(inet->inet_dport); | 2665 | __u16 destp = ntohs(inet->inet_dport); |
@@ -2448,9 +2694,9 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i, int *len) | |||
2448 | tp->write_seq - tp->snd_una, | 2694 | tp->write_seq - tp->snd_una, |
2449 | rx_queue, | 2695 | rx_queue, |
2450 | timer_active, | 2696 | timer_active, |
2451 | jiffies_to_clock_t(timer_expires - jiffies), | 2697 | jiffies_delta_to_clock_t(timer_expires - jiffies), |
2452 | icsk->icsk_retransmits, | 2698 | icsk->icsk_retransmits, |
2453 | sock_i_uid(sk), | 2699 | from_kuid_munged(seq_user_ns(f), sock_i_uid(sk)), |
2454 | icsk->icsk_probes_out, | 2700 | icsk->icsk_probes_out, |
2455 | sock_i_ino(sk), | 2701 | sock_i_ino(sk), |
2456 | atomic_read(&sk->sk_refcnt), sk, | 2702 | atomic_read(&sk->sk_refcnt), sk, |
@@ -2458,7 +2704,9 @@ static void get_tcp4_sock(struct sock *sk, struct seq_file *f, int i, int *len) | |||
2458 | jiffies_to_clock_t(icsk->icsk_ack.ato), | 2704 | jiffies_to_clock_t(icsk->icsk_ack.ato), |
2459 | (icsk->icsk_ack.quick << 1) | icsk->icsk_ack.pingpong, | 2705 | (icsk->icsk_ack.quick << 1) | icsk->icsk_ack.pingpong, |
2460 | tp->snd_cwnd, | 2706 | tp->snd_cwnd, |
2461 | tcp_in_initial_slowstart(tp) ? -1 : tp->snd_ssthresh, | 2707 | sk->sk_state == TCP_LISTEN ? |
2708 | (fastopenq ? fastopenq->max_qlen : 0) : | ||
2709 | (tcp_in_initial_slowstart(tp) ? -1 : tp->snd_ssthresh), | ||
2462 | len); | 2710 | len); |
2463 | } | 2711 | } |
2464 | 2712 | ||
@@ -2467,10 +2715,7 @@ static void get_timewait4_sock(const struct inet_timewait_sock *tw, | |||
2467 | { | 2715 | { |
2468 | __be32 dest, src; | 2716 | __be32 dest, src; |
2469 | __u16 destp, srcp; | 2717 | __u16 destp, srcp; |
2470 | int ttd = tw->tw_ttd - jiffies; | 2718 | long delta = tw->tw_ttd - jiffies; |
2471 | |||
2472 | if (ttd < 0) | ||
2473 | ttd = 0; | ||
2474 | 2719 | ||
2475 | dest = tw->tw_daddr; | 2720 | dest = tw->tw_daddr; |
2476 | src = tw->tw_rcv_saddr; | 2721 | src = tw->tw_rcv_saddr; |
@@ -2480,7 +2725,7 @@ static void get_timewait4_sock(const struct inet_timewait_sock *tw, | |||
2480 | seq_printf(f, "%4d: %08X:%04X %08X:%04X" | 2725 | seq_printf(f, "%4d: %08X:%04X %08X:%04X" |
2481 | " %02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %pK%n", | 2726 | " %02X %08X:%08X %02X:%08lX %08X %5d %8d %d %d %pK%n", |
2482 | i, src, srcp, dest, destp, tw->tw_substate, 0, 0, | 2727 | i, src, srcp, dest, destp, tw->tw_substate, 0, 0, |
2483 | 3, jiffies_to_clock_t(ttd), 0, 0, 0, 0, | 2728 | 3, jiffies_delta_to_clock_t(delta), 0, 0, 0, 0, |
2484 | atomic_read(&tw->tw_refcnt), tw, len); | 2729 | atomic_read(&tw->tw_refcnt), tw, len); |
2485 | } | 2730 | } |
2486 | 2731 | ||
diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c index 2288a6399e1e..0abe67bb4d3a 100644 --- a/net/ipv4/tcp_metrics.c +++ b/net/ipv4/tcp_metrics.c | |||
@@ -731,6 +731,18 @@ static int __net_init tcp_net_metrics_init(struct net *net) | |||
731 | 731 | ||
732 | static void __net_exit tcp_net_metrics_exit(struct net *net) | 732 | static void __net_exit tcp_net_metrics_exit(struct net *net) |
733 | { | 733 | { |
734 | unsigned int i; | ||
735 | |||
736 | for (i = 0; i < (1U << net->ipv4.tcp_metrics_hash_log) ; i++) { | ||
737 | struct tcp_metrics_block *tm, *next; | ||
738 | |||
739 | tm = rcu_dereference_protected(net->ipv4.tcp_metrics_hash[i].chain, 1); | ||
740 | while (tm) { | ||
741 | next = rcu_dereference_protected(tm->tcpm_next, 1); | ||
742 | kfree(tm); | ||
743 | tm = next; | ||
744 | } | ||
745 | } | ||
734 | kfree(net->ipv4.tcp_metrics_hash); | 746 | kfree(net->ipv4.tcp_metrics_hash); |
735 | } | 747 | } |
736 | 748 | ||
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 232a90c3ec86..e965319d610b 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c | |||
@@ -387,8 +387,6 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, | |||
387 | struct tcp_sock *oldtp = tcp_sk(sk); | 387 | struct tcp_sock *oldtp = tcp_sk(sk); |
388 | struct tcp_cookie_values *oldcvp = oldtp->cookie_values; | 388 | struct tcp_cookie_values *oldcvp = oldtp->cookie_values; |
389 | 389 | ||
390 | inet_sk_rx_dst_set(newsk, skb); | ||
391 | |||
392 | /* TCP Cookie Transactions require space for the cookie pair, | 390 | /* TCP Cookie Transactions require space for the cookie pair, |
393 | * as it differs for each connection. There is no need to | 391 | * as it differs for each connection. There is no need to |
394 | * copy any s_data_payload stored at the original socket. | 392 | * copy any s_data_payload stored at the original socket. |
@@ -509,6 +507,7 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, | |||
509 | newicsk->icsk_ack.last_seg_size = skb->len - newtp->tcp_header_len; | 507 | newicsk->icsk_ack.last_seg_size = skb->len - newtp->tcp_header_len; |
510 | newtp->rx_opt.mss_clamp = req->mss; | 508 | newtp->rx_opt.mss_clamp = req->mss; |
511 | TCP_ECN_openreq_child(newtp, req); | 509 | TCP_ECN_openreq_child(newtp, req); |
510 | newtp->fastopen_rsk = NULL; | ||
512 | 511 | ||
513 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_PASSIVEOPENS); | 512 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_PASSIVEOPENS); |
514 | } | 513 | } |
@@ -517,13 +516,18 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, | |||
517 | EXPORT_SYMBOL(tcp_create_openreq_child); | 516 | EXPORT_SYMBOL(tcp_create_openreq_child); |
518 | 517 | ||
519 | /* | 518 | /* |
520 | * Process an incoming packet for SYN_RECV sockets represented | 519 | * Process an incoming packet for SYN_RECV sockets represented as a |
521 | * as a request_sock. | 520 | * request_sock. Normally sk is the listener socket but for TFO it |
521 | * points to the child socket. | ||
522 | * | ||
523 | * XXX (TFO) - The current impl contains a special check for ack | ||
524 | * validation and inside tcp_v4_reqsk_send_ack(). Can we do better? | ||
522 | */ | 525 | */ |
523 | 526 | ||
524 | struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, | 527 | struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, |
525 | struct request_sock *req, | 528 | struct request_sock *req, |
526 | struct request_sock **prev) | 529 | struct request_sock **prev, |
530 | bool fastopen) | ||
527 | { | 531 | { |
528 | struct tcp_options_received tmp_opt; | 532 | struct tcp_options_received tmp_opt; |
529 | const u8 *hash_location; | 533 | const u8 *hash_location; |
@@ -532,6 +536,8 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, | |||
532 | __be32 flg = tcp_flag_word(th) & (TCP_FLAG_RST|TCP_FLAG_SYN|TCP_FLAG_ACK); | 536 | __be32 flg = tcp_flag_word(th) & (TCP_FLAG_RST|TCP_FLAG_SYN|TCP_FLAG_ACK); |
533 | bool paws_reject = false; | 537 | bool paws_reject = false; |
534 | 538 | ||
539 | BUG_ON(fastopen == (sk->sk_state == TCP_LISTEN)); | ||
540 | |||
535 | tmp_opt.saw_tstamp = 0; | 541 | tmp_opt.saw_tstamp = 0; |
536 | if (th->doff > (sizeof(struct tcphdr)>>2)) { | 542 | if (th->doff > (sizeof(struct tcphdr)>>2)) { |
537 | tcp_parse_options(skb, &tmp_opt, &hash_location, 0, NULL); | 543 | tcp_parse_options(skb, &tmp_opt, &hash_location, 0, NULL); |
@@ -567,6 +573,9 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, | |||
567 | * | 573 | * |
568 | * Enforce "SYN-ACK" according to figure 8, figure 6 | 574 | * Enforce "SYN-ACK" according to figure 8, figure 6 |
569 | * of RFC793, fixed by RFC1122. | 575 | * of RFC793, fixed by RFC1122. |
576 | * | ||
577 | * Note that even if there is new data in the SYN packet | ||
578 | * they will be thrown away too. | ||
570 | */ | 579 | */ |
571 | req->rsk_ops->rtx_syn_ack(sk, req, NULL); | 580 | req->rsk_ops->rtx_syn_ack(sk, req, NULL); |
572 | return NULL; | 581 | return NULL; |
@@ -624,9 +633,12 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, | |||
624 | * sent (the segment carries an unacceptable ACK) ... | 633 | * sent (the segment carries an unacceptable ACK) ... |
625 | * a reset is sent." | 634 | * a reset is sent." |
626 | * | 635 | * |
627 | * Invalid ACK: reset will be sent by listening socket | 636 | * Invalid ACK: reset will be sent by listening socket. |
637 | * Note that the ACK validity check for a Fast Open socket is done | ||
638 | * elsewhere and is checked directly against the child socket rather | ||
639 | * than req because user data may have been sent out. | ||
628 | */ | 640 | */ |
629 | if ((flg & TCP_FLAG_ACK) && | 641 | if ((flg & TCP_FLAG_ACK) && !fastopen && |
630 | (TCP_SKB_CB(skb)->ack_seq != | 642 | (TCP_SKB_CB(skb)->ack_seq != |
631 | tcp_rsk(req)->snt_isn + 1 + tcp_s_data_size(tcp_sk(sk)))) | 643 | tcp_rsk(req)->snt_isn + 1 + tcp_s_data_size(tcp_sk(sk)))) |
632 | return sk; | 644 | return sk; |
@@ -639,7 +651,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, | |||
639 | /* RFC793: "first check sequence number". */ | 651 | /* RFC793: "first check sequence number". */ |
640 | 652 | ||
641 | if (paws_reject || !tcp_in_window(TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq, | 653 | if (paws_reject || !tcp_in_window(TCP_SKB_CB(skb)->seq, TCP_SKB_CB(skb)->end_seq, |
642 | tcp_rsk(req)->rcv_isn + 1, tcp_rsk(req)->rcv_isn + 1 + req->rcv_wnd)) { | 654 | tcp_rsk(req)->rcv_nxt, tcp_rsk(req)->rcv_nxt + req->rcv_wnd)) { |
643 | /* Out of window: send ACK and drop. */ | 655 | /* Out of window: send ACK and drop. */ |
644 | if (!(flg & TCP_FLAG_RST)) | 656 | if (!(flg & TCP_FLAG_RST)) |
645 | req->rsk_ops->send_ack(sk, skb, req); | 657 | req->rsk_ops->send_ack(sk, skb, req); |
@@ -650,7 +662,7 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, | |||
650 | 662 | ||
651 | /* In sequence, PAWS is OK. */ | 663 | /* In sequence, PAWS is OK. */ |
652 | 664 | ||
653 | if (tmp_opt.saw_tstamp && !after(TCP_SKB_CB(skb)->seq, tcp_rsk(req)->rcv_isn + 1)) | 665 | if (tmp_opt.saw_tstamp && !after(TCP_SKB_CB(skb)->seq, tcp_rsk(req)->rcv_nxt)) |
654 | req->ts_recent = tmp_opt.rcv_tsval; | 666 | req->ts_recent = tmp_opt.rcv_tsval; |
655 | 667 | ||
656 | if (TCP_SKB_CB(skb)->seq == tcp_rsk(req)->rcv_isn) { | 668 | if (TCP_SKB_CB(skb)->seq == tcp_rsk(req)->rcv_isn) { |
@@ -669,10 +681,19 @@ struct sock *tcp_check_req(struct sock *sk, struct sk_buff *skb, | |||
669 | 681 | ||
670 | /* ACK sequence verified above, just make sure ACK is | 682 | /* ACK sequence verified above, just make sure ACK is |
671 | * set. If ACK not set, just silently drop the packet. | 683 | * set. If ACK not set, just silently drop the packet. |
684 | * | ||
685 | * XXX (TFO) - if we ever allow "data after SYN", the | ||
686 | * following check needs to be removed. | ||
672 | */ | 687 | */ |
673 | if (!(flg & TCP_FLAG_ACK)) | 688 | if (!(flg & TCP_FLAG_ACK)) |
674 | return NULL; | 689 | return NULL; |
675 | 690 | ||
691 | /* For Fast Open no more processing is needed (sk is the | ||
692 | * child socket). | ||
693 | */ | ||
694 | if (fastopen) | ||
695 | return sk; | ||
696 | |||
676 | /* While TCP_DEFER_ACCEPT is active, drop bare ACK. */ | 697 | /* While TCP_DEFER_ACCEPT is active, drop bare ACK. */ |
677 | if (req->retrans < inet_csk(sk)->icsk_accept_queue.rskq_defer_accept && | 698 | if (req->retrans < inet_csk(sk)->icsk_accept_queue.rskq_defer_accept && |
678 | TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) { | 699 | TCP_SKB_CB(skb)->end_seq == tcp_rsk(req)->rcv_isn + 1) { |
@@ -708,11 +729,21 @@ listen_overflow: | |||
708 | } | 729 | } |
709 | 730 | ||
710 | embryonic_reset: | 731 | embryonic_reset: |
711 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_EMBRYONICRSTS); | 732 | if (!(flg & TCP_FLAG_RST)) { |
712 | if (!(flg & TCP_FLAG_RST)) | 733 | /* Received a bad SYN pkt - for TFO We try not to reset |
734 | * the local connection unless it's really necessary to | ||
735 | * avoid becoming vulnerable to outside attack aiming at | ||
736 | * resetting legit local connections. | ||
737 | */ | ||
713 | req->rsk_ops->send_reset(sk, skb); | 738 | req->rsk_ops->send_reset(sk, skb); |
714 | 739 | } else if (fastopen) { /* received a valid RST pkt */ | |
715 | inet_csk_reqsk_queue_drop(sk, req, prev); | 740 | reqsk_fastopen_remove(sk, req, true); |
741 | tcp_reset(sk); | ||
742 | } | ||
743 | if (!fastopen) { | ||
744 | inet_csk_reqsk_queue_drop(sk, req, prev); | ||
745 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_EMBRYONICRSTS); | ||
746 | } | ||
716 | return NULL; | 747 | return NULL; |
717 | } | 748 | } |
718 | EXPORT_SYMBOL(tcp_check_req); | 749 | EXPORT_SYMBOL(tcp_check_req); |
@@ -721,6 +752,12 @@ EXPORT_SYMBOL(tcp_check_req); | |||
721 | * Queue segment on the new socket if the new socket is active, | 752 | * Queue segment on the new socket if the new socket is active, |
722 | * otherwise we just shortcircuit this and continue with | 753 | * otherwise we just shortcircuit this and continue with |
723 | * the new socket. | 754 | * the new socket. |
755 | * | ||
756 | * For the vast majority of cases child->sk_state will be TCP_SYN_RECV | ||
757 | * when entering. But other states are possible due to a race condition | ||
758 | * where after __inet_lookup_established() fails but before the listener | ||
759 | * locked is obtained, other packets cause the same connection to | ||
760 | * be created. | ||
724 | */ | 761 | */ |
725 | 762 | ||
726 | int tcp_child_process(struct sock *parent, struct sock *child, | 763 | int tcp_child_process(struct sock *parent, struct sock *child, |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 3f1bcff0b10b..cfe6ffe1c177 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -702,7 +702,8 @@ static unsigned int tcp_synack_options(struct sock *sk, | |||
702 | unsigned int mss, struct sk_buff *skb, | 702 | unsigned int mss, struct sk_buff *skb, |
703 | struct tcp_out_options *opts, | 703 | struct tcp_out_options *opts, |
704 | struct tcp_md5sig_key **md5, | 704 | struct tcp_md5sig_key **md5, |
705 | struct tcp_extend_values *xvp) | 705 | struct tcp_extend_values *xvp, |
706 | struct tcp_fastopen_cookie *foc) | ||
706 | { | 707 | { |
707 | struct inet_request_sock *ireq = inet_rsk(req); | 708 | struct inet_request_sock *ireq = inet_rsk(req); |
708 | unsigned int remaining = MAX_TCP_OPTION_SPACE; | 709 | unsigned int remaining = MAX_TCP_OPTION_SPACE; |
@@ -747,7 +748,15 @@ static unsigned int tcp_synack_options(struct sock *sk, | |||
747 | if (unlikely(!ireq->tstamp_ok)) | 748 | if (unlikely(!ireq->tstamp_ok)) |
748 | remaining -= TCPOLEN_SACKPERM_ALIGNED; | 749 | remaining -= TCPOLEN_SACKPERM_ALIGNED; |
749 | } | 750 | } |
750 | 751 | if (foc != NULL) { | |
752 | u32 need = TCPOLEN_EXP_FASTOPEN_BASE + foc->len; | ||
753 | need = (need + 3) & ~3U; /* Align to 32 bits */ | ||
754 | if (remaining >= need) { | ||
755 | opts->options |= OPTION_FAST_OPEN_COOKIE; | ||
756 | opts->fastopen_cookie = foc; | ||
757 | remaining -= need; | ||
758 | } | ||
759 | } | ||
751 | /* Similar rationale to tcp_syn_options() applies here, too. | 760 | /* Similar rationale to tcp_syn_options() applies here, too. |
752 | * If the <SYN> options fit, the same options should fit now! | 761 | * If the <SYN> options fit, the same options should fit now! |
753 | */ | 762 | */ |
@@ -910,14 +919,18 @@ void tcp_release_cb(struct sock *sk) | |||
910 | if (flags & (1UL << TCP_TSQ_DEFERRED)) | 919 | if (flags & (1UL << TCP_TSQ_DEFERRED)) |
911 | tcp_tsq_handler(sk); | 920 | tcp_tsq_handler(sk); |
912 | 921 | ||
913 | if (flags & (1UL << TCP_WRITE_TIMER_DEFERRED)) | 922 | if (flags & (1UL << TCP_WRITE_TIMER_DEFERRED)) { |
914 | tcp_write_timer_handler(sk); | 923 | tcp_write_timer_handler(sk); |
915 | 924 | __sock_put(sk); | |
916 | if (flags & (1UL << TCP_DELACK_TIMER_DEFERRED)) | 925 | } |
926 | if (flags & (1UL << TCP_DELACK_TIMER_DEFERRED)) { | ||
917 | tcp_delack_timer_handler(sk); | 927 | tcp_delack_timer_handler(sk); |
918 | 928 | __sock_put(sk); | |
919 | if (flags & (1UL << TCP_MTU_REDUCED_DEFERRED)) | 929 | } |
930 | if (flags & (1UL << TCP_MTU_REDUCED_DEFERRED)) { | ||
920 | sk->sk_prot->mtu_reduced(sk); | 931 | sk->sk_prot->mtu_reduced(sk); |
932 | __sock_put(sk); | ||
933 | } | ||
921 | } | 934 | } |
922 | EXPORT_SYMBOL(tcp_release_cb); | 935 | EXPORT_SYMBOL(tcp_release_cb); |
923 | 936 | ||
@@ -940,7 +953,7 @@ void __init tcp_tasklet_init(void) | |||
940 | * We cant xmit new skbs from this context, as we might already | 953 | * We cant xmit new skbs from this context, as we might already |
941 | * hold qdisc lock. | 954 | * hold qdisc lock. |
942 | */ | 955 | */ |
943 | void tcp_wfree(struct sk_buff *skb) | 956 | static void tcp_wfree(struct sk_buff *skb) |
944 | { | 957 | { |
945 | struct sock *sk = skb->sk; | 958 | struct sock *sk = skb->sk; |
946 | struct tcp_sock *tp = tcp_sk(sk); | 959 | struct tcp_sock *tp = tcp_sk(sk); |
@@ -1522,21 +1535,21 @@ static void tcp_cwnd_validate(struct sock *sk) | |||
1522 | * when we would be allowed to send the split-due-to-Nagle skb fully. | 1535 | * when we would be allowed to send the split-due-to-Nagle skb fully. |
1523 | */ | 1536 | */ |
1524 | static unsigned int tcp_mss_split_point(const struct sock *sk, const struct sk_buff *skb, | 1537 | static unsigned int tcp_mss_split_point(const struct sock *sk, const struct sk_buff *skb, |
1525 | unsigned int mss_now, unsigned int cwnd) | 1538 | unsigned int mss_now, unsigned int max_segs) |
1526 | { | 1539 | { |
1527 | const struct tcp_sock *tp = tcp_sk(sk); | 1540 | const struct tcp_sock *tp = tcp_sk(sk); |
1528 | u32 needed, window, cwnd_len; | 1541 | u32 needed, window, max_len; |
1529 | 1542 | ||
1530 | window = tcp_wnd_end(tp) - TCP_SKB_CB(skb)->seq; | 1543 | window = tcp_wnd_end(tp) - TCP_SKB_CB(skb)->seq; |
1531 | cwnd_len = mss_now * cwnd; | 1544 | max_len = mss_now * max_segs; |
1532 | 1545 | ||
1533 | if (likely(cwnd_len <= window && skb != tcp_write_queue_tail(sk))) | 1546 | if (likely(max_len <= window && skb != tcp_write_queue_tail(sk))) |
1534 | return cwnd_len; | 1547 | return max_len; |
1535 | 1548 | ||
1536 | needed = min(skb->len, window); | 1549 | needed = min(skb->len, window); |
1537 | 1550 | ||
1538 | if (cwnd_len <= needed) | 1551 | if (max_len <= needed) |
1539 | return cwnd_len; | 1552 | return max_len; |
1540 | 1553 | ||
1541 | return needed - needed % mss_now; | 1554 | return needed - needed % mss_now; |
1542 | } | 1555 | } |
@@ -1765,7 +1778,8 @@ static bool tcp_tso_should_defer(struct sock *sk, struct sk_buff *skb) | |||
1765 | limit = min(send_win, cong_win); | 1778 | limit = min(send_win, cong_win); |
1766 | 1779 | ||
1767 | /* If a full-sized TSO skb can be sent, do it. */ | 1780 | /* If a full-sized TSO skb can be sent, do it. */ |
1768 | if (limit >= sk->sk_gso_max_size) | 1781 | if (limit >= min_t(unsigned int, sk->sk_gso_max_size, |
1782 | sk->sk_gso_max_segs * tp->mss_cache)) | ||
1769 | goto send_now; | 1783 | goto send_now; |
1770 | 1784 | ||
1771 | /* Middle in queue won't get any more data, full sendable already? */ | 1785 | /* Middle in queue won't get any more data, full sendable already? */ |
@@ -1999,7 +2013,9 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, | |||
1999 | limit = mss_now; | 2013 | limit = mss_now; |
2000 | if (tso_segs > 1 && !tcp_urg_mode(tp)) | 2014 | if (tso_segs > 1 && !tcp_urg_mode(tp)) |
2001 | limit = tcp_mss_split_point(sk, skb, mss_now, | 2015 | limit = tcp_mss_split_point(sk, skb, mss_now, |
2002 | cwnd_quota); | 2016 | min_t(unsigned int, |
2017 | cwnd_quota, | ||
2018 | sk->sk_gso_max_segs)); | ||
2003 | 2019 | ||
2004 | if (skb->len > limit && | 2020 | if (skb->len > limit && |
2005 | unlikely(tso_fragment(sk, skb, limit, mss_now, gfp))) | 2021 | unlikely(tso_fragment(sk, skb, limit, mss_now, gfp))) |
@@ -2021,10 +2037,10 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, | |||
2021 | if (push_one) | 2037 | if (push_one) |
2022 | break; | 2038 | break; |
2023 | } | 2039 | } |
2024 | if (inet_csk(sk)->icsk_ca_state == TCP_CA_Recovery) | ||
2025 | tp->prr_out += sent_pkts; | ||
2026 | 2040 | ||
2027 | if (likely(sent_pkts)) { | 2041 | if (likely(sent_pkts)) { |
2042 | if (tcp_in_cwnd_reduction(sk)) | ||
2043 | tp->prr_out += sent_pkts; | ||
2028 | tcp_cwnd_validate(sk); | 2044 | tcp_cwnd_validate(sk); |
2029 | return false; | 2045 | return false; |
2030 | } | 2046 | } |
@@ -2526,7 +2542,7 @@ begin_fwd: | |||
2526 | } | 2542 | } |
2527 | NET_INC_STATS_BH(sock_net(sk), mib_idx); | 2543 | NET_INC_STATS_BH(sock_net(sk), mib_idx); |
2528 | 2544 | ||
2529 | if (inet_csk(sk)->icsk_ca_state == TCP_CA_Recovery) | 2545 | if (tcp_in_cwnd_reduction(sk)) |
2530 | tp->prr_out += tcp_skb_pcount(skb); | 2546 | tp->prr_out += tcp_skb_pcount(skb); |
2531 | 2547 | ||
2532 | if (skb == tcp_write_queue_head(sk)) | 2548 | if (skb == tcp_write_queue_head(sk)) |
@@ -2651,7 +2667,8 @@ int tcp_send_synack(struct sock *sk) | |||
2651 | */ | 2667 | */ |
2652 | struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | 2668 | struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, |
2653 | struct request_sock *req, | 2669 | struct request_sock *req, |
2654 | struct request_values *rvp) | 2670 | struct request_values *rvp, |
2671 | struct tcp_fastopen_cookie *foc) | ||
2655 | { | 2672 | { |
2656 | struct tcp_out_options opts; | 2673 | struct tcp_out_options opts; |
2657 | struct tcp_extend_values *xvp = tcp_xv(rvp); | 2674 | struct tcp_extend_values *xvp = tcp_xv(rvp); |
@@ -2711,7 +2728,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | |||
2711 | #endif | 2728 | #endif |
2712 | TCP_SKB_CB(skb)->when = tcp_time_stamp; | 2729 | TCP_SKB_CB(skb)->when = tcp_time_stamp; |
2713 | tcp_header_size = tcp_synack_options(sk, req, mss, | 2730 | tcp_header_size = tcp_synack_options(sk, req, mss, |
2714 | skb, &opts, &md5, xvp) | 2731 | skb, &opts, &md5, xvp, foc) |
2715 | + sizeof(*th); | 2732 | + sizeof(*th); |
2716 | 2733 | ||
2717 | skb_push(skb, tcp_header_size); | 2734 | skb_push(skb, tcp_header_size); |
@@ -2765,7 +2782,8 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | |||
2765 | } | 2782 | } |
2766 | 2783 | ||
2767 | th->seq = htonl(TCP_SKB_CB(skb)->seq); | 2784 | th->seq = htonl(TCP_SKB_CB(skb)->seq); |
2768 | th->ack_seq = htonl(tcp_rsk(req)->rcv_isn + 1); | 2785 | /* XXX data is queued and acked as is. No buffer/window check */ |
2786 | th->ack_seq = htonl(tcp_rsk(req)->rcv_nxt); | ||
2769 | 2787 | ||
2770 | /* RFC1323: The window in SYN & SYN/ACK segments is never scaled. */ | 2788 | /* RFC1323: The window in SYN & SYN/ACK segments is never scaled. */ |
2771 | th->window = htons(min(req->rcv_wnd, 65535U)); | 2789 | th->window = htons(min(req->rcv_wnd, 65535U)); |
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 6df36ad55a38..fc04711e80c8 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c | |||
@@ -252,7 +252,8 @@ static void tcp_delack_timer(unsigned long data) | |||
252 | inet_csk(sk)->icsk_ack.blocked = 1; | 252 | inet_csk(sk)->icsk_ack.blocked = 1; |
253 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_DELAYEDACKLOCKED); | 253 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_DELAYEDACKLOCKED); |
254 | /* deleguate our work to tcp_release_cb() */ | 254 | /* deleguate our work to tcp_release_cb() */ |
255 | set_bit(TCP_WRITE_TIMER_DEFERRED, &tcp_sk(sk)->tsq_flags); | 255 | if (!test_and_set_bit(TCP_DELACK_TIMER_DEFERRED, &tcp_sk(sk)->tsq_flags)) |
256 | sock_hold(sk); | ||
256 | } | 257 | } |
257 | bh_unlock_sock(sk); | 258 | bh_unlock_sock(sk); |
258 | sock_put(sk); | 259 | sock_put(sk); |
@@ -304,6 +305,35 @@ static void tcp_probe_timer(struct sock *sk) | |||
304 | } | 305 | } |
305 | 306 | ||
306 | /* | 307 | /* |
308 | * Timer for Fast Open socket to retransmit SYNACK. Note that the | ||
309 | * sk here is the child socket, not the parent (listener) socket. | ||
310 | */ | ||
311 | static void tcp_fastopen_synack_timer(struct sock *sk) | ||
312 | { | ||
313 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
314 | int max_retries = icsk->icsk_syn_retries ? : | ||
315 | sysctl_tcp_synack_retries + 1; /* add one more retry for fastopen */ | ||
316 | struct request_sock *req; | ||
317 | |||
318 | req = tcp_sk(sk)->fastopen_rsk; | ||
319 | req->rsk_ops->syn_ack_timeout(sk, req); | ||
320 | |||
321 | if (req->retrans >= max_retries) { | ||
322 | tcp_write_err(sk); | ||
323 | return; | ||
324 | } | ||
325 | /* XXX (TFO) - Unlike regular SYN-ACK retransmit, we ignore error | ||
326 | * returned from rtx_syn_ack() to make it more persistent like | ||
327 | * regular retransmit because if the child socket has been accepted | ||
328 | * it's not good to give up too easily. | ||
329 | */ | ||
330 | req->rsk_ops->rtx_syn_ack(sk, req, NULL); | ||
331 | req->retrans++; | ||
332 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, | ||
333 | TCP_TIMEOUT_INIT << req->retrans, TCP_RTO_MAX); | ||
334 | } | ||
335 | |||
336 | /* | ||
307 | * The TCP retransmit timer. | 337 | * The TCP retransmit timer. |
308 | */ | 338 | */ |
309 | 339 | ||
@@ -316,7 +346,15 @@ void tcp_retransmit_timer(struct sock *sk) | |||
316 | tcp_resume_early_retransmit(sk); | 346 | tcp_resume_early_retransmit(sk); |
317 | return; | 347 | return; |
318 | } | 348 | } |
319 | 349 | if (tp->fastopen_rsk) { | |
350 | BUG_ON(sk->sk_state != TCP_SYN_RECV && | ||
351 | sk->sk_state != TCP_FIN_WAIT1); | ||
352 | tcp_fastopen_synack_timer(sk); | ||
353 | /* Before we receive ACK to our SYN-ACK don't retransmit | ||
354 | * anything else (e.g., data or FIN segments). | ||
355 | */ | ||
356 | return; | ||
357 | } | ||
320 | if (!tp->packets_out) | 358 | if (!tp->packets_out) |
321 | goto out; | 359 | goto out; |
322 | 360 | ||
@@ -481,7 +519,8 @@ static void tcp_write_timer(unsigned long data) | |||
481 | tcp_write_timer_handler(sk); | 519 | tcp_write_timer_handler(sk); |
482 | } else { | 520 | } else { |
483 | /* deleguate our work to tcp_release_cb() */ | 521 | /* deleguate our work to tcp_release_cb() */ |
484 | set_bit(TCP_WRITE_TIMER_DEFERRED, &tcp_sk(sk)->tsq_flags); | 522 | if (!test_and_set_bit(TCP_WRITE_TIMER_DEFERRED, &tcp_sk(sk)->tsq_flags)) |
523 | sock_hold(sk); | ||
485 | } | 524 | } |
486 | bh_unlock_sock(sk); | 525 | bh_unlock_sock(sk); |
487 | sock_put(sk); | 526 | sock_put(sk); |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index b4c3582a991f..c4e64328d8ba 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -758,7 +758,7 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4) | |||
758 | uh->check = CSUM_MANGLED_0; | 758 | uh->check = CSUM_MANGLED_0; |
759 | 759 | ||
760 | send: | 760 | send: |
761 | err = ip_send_skb(skb); | 761 | err = ip_send_skb(sock_net(sk), skb); |
762 | if (err) { | 762 | if (err) { |
763 | if (err == -ENOBUFS && !inet->recverr) { | 763 | if (err == -ENOBUFS && !inet->recverr) { |
764 | UDP_INC_STATS_USER(sock_net(sk), | 764 | UDP_INC_STATS_USER(sock_net(sk), |
@@ -2110,7 +2110,9 @@ static void udp4_format_sock(struct sock *sp, struct seq_file *f, | |||
2110 | bucket, src, srcp, dest, destp, sp->sk_state, | 2110 | bucket, src, srcp, dest, destp, sp->sk_state, |
2111 | sk_wmem_alloc_get(sp), | 2111 | sk_wmem_alloc_get(sp), |
2112 | sk_rmem_alloc_get(sp), | 2112 | sk_rmem_alloc_get(sp), |
2113 | 0, 0L, 0, sock_i_uid(sp), 0, sock_i_ino(sp), | 2113 | 0, 0L, 0, |
2114 | from_kuid_munged(seq_user_ns(f), sock_i_uid(sp)), | ||
2115 | 0, sock_i_ino(sp), | ||
2114 | atomic_read(&sp->sk_refcnt), sp, | 2116 | atomic_read(&sp->sk_refcnt), sp, |
2115 | atomic_read(&sp->sk_drops), len); | 2117 | atomic_read(&sp->sk_drops), len); |
2116 | } | 2118 | } |
diff --git a/net/ipv4/udp_diag.c b/net/ipv4/udp_diag.c index 16d0960062be..d2f336ea82ca 100644 --- a/net/ipv4/udp_diag.c +++ b/net/ipv4/udp_diag.c | |||
@@ -24,7 +24,9 @@ static int sk_diag_dump(struct sock *sk, struct sk_buff *skb, | |||
24 | if (!inet_diag_bc_sk(bc, sk)) | 24 | if (!inet_diag_bc_sk(bc, sk)) |
25 | return 0; | 25 | return 0; |
26 | 26 | ||
27 | return inet_sk_diag_fill(sk, NULL, skb, req, NETLINK_CB(cb->skb).pid, | 27 | return inet_sk_diag_fill(sk, NULL, skb, req, |
28 | sk_user_ns(NETLINK_CB(cb->skb).ssk), | ||
29 | NETLINK_CB(cb->skb).pid, | ||
28 | cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); | 30 | cb->nlh->nlmsg_seq, NLM_F_MULTI, cb->nlh); |
29 | } | 31 | } |
30 | 32 | ||
@@ -69,6 +71,7 @@ static int udp_dump_one(struct udp_table *tbl, struct sk_buff *in_skb, | |||
69 | goto out; | 71 | goto out; |
70 | 72 | ||
71 | err = inet_sk_diag_fill(sk, NULL, rep, req, | 73 | err = inet_sk_diag_fill(sk, NULL, rep, req, |
74 | sk_user_ns(NETLINK_CB(in_skb).ssk), | ||
72 | NETLINK_CB(in_skb).pid, | 75 | NETLINK_CB(in_skb).pid, |
73 | nlh->nlmsg_seq, 0, nlh); | 76 | nlh->nlmsg_seq, 0, nlh); |
74 | if (err < 0) { | 77 | if (err < 0) { |
diff --git a/net/ipv6/Kconfig b/net/ipv6/Kconfig index 5728695b5449..4f7fe7270e37 100644 --- a/net/ipv6/Kconfig +++ b/net/ipv6/Kconfig | |||
@@ -201,6 +201,22 @@ config IPV6_TUNNEL | |||
201 | 201 | ||
202 | If unsure, say N. | 202 | If unsure, say N. |
203 | 203 | ||
204 | config IPV6_GRE | ||
205 | tristate "IPv6: GRE tunnel" | ||
206 | select IPV6_TUNNEL | ||
207 | ---help--- | ||
208 | Tunneling means encapsulating data of one protocol type within | ||
209 | another protocol and sending it over a channel that understands the | ||
210 | encapsulating protocol. This particular tunneling driver implements | ||
211 | GRE (Generic Routing Encapsulation) and at this time allows | ||
212 | encapsulating of IPv4 or IPv6 over existing IPv6 infrastructure. | ||
213 | This driver is useful if the other endpoint is a Cisco router: Cisco | ||
214 | likes GRE much better than the other Linux tunneling driver ("IP | ||
215 | tunneling" above). In addition, GRE allows multicast redistribution | ||
216 | through the tunnel. | ||
217 | |||
218 | Saying M here will produce a module called ip6_gre. If unsure, say N. | ||
219 | |||
204 | config IPV6_MULTIPLE_TABLES | 220 | config IPV6_MULTIPLE_TABLES |
205 | bool "IPv6: Multiple Routing Tables" | 221 | bool "IPv6: Multiple Routing Tables" |
206 | depends on EXPERIMENTAL | 222 | depends on EXPERIMENTAL |
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index 686934acfac1..b6d3f79151e2 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile | |||
@@ -36,6 +36,7 @@ obj-$(CONFIG_NETFILTER) += netfilter/ | |||
36 | 36 | ||
37 | obj-$(CONFIG_IPV6_SIT) += sit.o | 37 | obj-$(CONFIG_IPV6_SIT) += sit.o |
38 | obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o | 38 | obj-$(CONFIG_IPV6_TUNNEL) += ip6_tunnel.o |
39 | obj-$(CONFIG_IPV6_GRE) += ip6_gre.o | ||
39 | 40 | ||
40 | obj-y += addrconf_core.o exthdrs_core.o | 41 | obj-y += addrconf_core.o exthdrs_core.o |
41 | 42 | ||
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 79181819a24f..572cb660837b 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -127,8 +127,8 @@ static inline void addrconf_sysctl_unregister(struct inet6_dev *idev) | |||
127 | #endif | 127 | #endif |
128 | 128 | ||
129 | #ifdef CONFIG_IPV6_PRIVACY | 129 | #ifdef CONFIG_IPV6_PRIVACY |
130 | static int __ipv6_regen_rndid(struct inet6_dev *idev); | 130 | static void __ipv6_regen_rndid(struct inet6_dev *idev); |
131 | static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr); | 131 | static void __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr); |
132 | static void ipv6_regen_rndid(unsigned long data); | 132 | static void ipv6_regen_rndid(unsigned long data); |
133 | #endif | 133 | #endif |
134 | 134 | ||
@@ -494,8 +494,7 @@ static void addrconf_forward_change(struct net *net, __s32 newf) | |||
494 | struct net_device *dev; | 494 | struct net_device *dev; |
495 | struct inet6_dev *idev; | 495 | struct inet6_dev *idev; |
496 | 496 | ||
497 | rcu_read_lock(); | 497 | for_each_netdev(net, dev) { |
498 | for_each_netdev_rcu(net, dev) { | ||
499 | idev = __in6_dev_get(dev); | 498 | idev = __in6_dev_get(dev); |
500 | if (idev) { | 499 | if (idev) { |
501 | int changed = (!idev->cnf.forwarding) ^ (!newf); | 500 | int changed = (!idev->cnf.forwarding) ^ (!newf); |
@@ -504,7 +503,6 @@ static void addrconf_forward_change(struct net *net, __s32 newf) | |||
504 | dev_forward_change(idev); | 503 | dev_forward_change(idev); |
505 | } | 504 | } |
506 | } | 505 | } |
507 | rcu_read_unlock(); | ||
508 | } | 506 | } |
509 | 507 | ||
510 | static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf) | 508 | static int addrconf_fixup_forwarding(struct ctl_table *table, int *p, int newf) |
@@ -854,16 +852,7 @@ retry: | |||
854 | } | 852 | } |
855 | in6_ifa_hold(ifp); | 853 | in6_ifa_hold(ifp); |
856 | memcpy(addr.s6_addr, ifp->addr.s6_addr, 8); | 854 | memcpy(addr.s6_addr, ifp->addr.s6_addr, 8); |
857 | if (__ipv6_try_regen_rndid(idev, tmpaddr) < 0) { | 855 | __ipv6_try_regen_rndid(idev, tmpaddr); |
858 | spin_unlock_bh(&ifp->lock); | ||
859 | write_unlock(&idev->lock); | ||
860 | pr_warn("%s: regeneration of randomized interface id failed\n", | ||
861 | __func__); | ||
862 | in6_ifa_put(ifp); | ||
863 | in6_dev_put(idev); | ||
864 | ret = -1; | ||
865 | goto out; | ||
866 | } | ||
867 | memcpy(&addr.s6_addr[8], idev->rndid, 8); | 856 | memcpy(&addr.s6_addr[8], idev->rndid, 8); |
868 | age = (now - ifp->tstamp) / HZ; | 857 | age = (now - ifp->tstamp) / HZ; |
869 | tmp_valid_lft = min_t(__u32, | 858 | tmp_valid_lft = min_t(__u32, |
@@ -1095,7 +1084,7 @@ out: | |||
1095 | return ret; | 1084 | return ret; |
1096 | } | 1085 | } |
1097 | 1086 | ||
1098 | int ipv6_dev_get_saddr(struct net *net, struct net_device *dst_dev, | 1087 | int ipv6_dev_get_saddr(struct net *net, const struct net_device *dst_dev, |
1099 | const struct in6_addr *daddr, unsigned int prefs, | 1088 | const struct in6_addr *daddr, unsigned int prefs, |
1100 | struct in6_addr *saddr) | 1089 | struct in6_addr *saddr) |
1101 | { | 1090 | { |
@@ -1602,7 +1591,7 @@ static int ipv6_inherit_eui64(u8 *eui, struct inet6_dev *idev) | |||
1602 | 1591 | ||
1603 | #ifdef CONFIG_IPV6_PRIVACY | 1592 | #ifdef CONFIG_IPV6_PRIVACY |
1604 | /* (re)generation of randomized interface identifier (RFC 3041 3.2, 3.5) */ | 1593 | /* (re)generation of randomized interface identifier (RFC 3041 3.2, 3.5) */ |
1605 | static int __ipv6_regen_rndid(struct inet6_dev *idev) | 1594 | static void __ipv6_regen_rndid(struct inet6_dev *idev) |
1606 | { | 1595 | { |
1607 | regen: | 1596 | regen: |
1608 | get_random_bytes(idev->rndid, sizeof(idev->rndid)); | 1597 | get_random_bytes(idev->rndid, sizeof(idev->rndid)); |
@@ -1629,8 +1618,6 @@ regen: | |||
1629 | if ((idev->rndid[2]|idev->rndid[3]|idev->rndid[4]|idev->rndid[5]|idev->rndid[6]|idev->rndid[7]) == 0x00) | 1618 | if ((idev->rndid[2]|idev->rndid[3]|idev->rndid[4]|idev->rndid[5]|idev->rndid[6]|idev->rndid[7]) == 0x00) |
1630 | goto regen; | 1619 | goto regen; |
1631 | } | 1620 | } |
1632 | |||
1633 | return 0; | ||
1634 | } | 1621 | } |
1635 | 1622 | ||
1636 | static void ipv6_regen_rndid(unsigned long data) | 1623 | static void ipv6_regen_rndid(unsigned long data) |
@@ -1644,8 +1631,7 @@ static void ipv6_regen_rndid(unsigned long data) | |||
1644 | if (idev->dead) | 1631 | if (idev->dead) |
1645 | goto out; | 1632 | goto out; |
1646 | 1633 | ||
1647 | if (__ipv6_regen_rndid(idev) < 0) | 1634 | __ipv6_regen_rndid(idev); |
1648 | goto out; | ||
1649 | 1635 | ||
1650 | expires = jiffies + | 1636 | expires = jiffies + |
1651 | idev->cnf.temp_prefered_lft * HZ - | 1637 | idev->cnf.temp_prefered_lft * HZ - |
@@ -1666,13 +1652,10 @@ out: | |||
1666 | in6_dev_put(idev); | 1652 | in6_dev_put(idev); |
1667 | } | 1653 | } |
1668 | 1654 | ||
1669 | static int __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr) | 1655 | static void __ipv6_try_regen_rndid(struct inet6_dev *idev, struct in6_addr *tmpaddr) |
1670 | { | 1656 | { |
1671 | int ret = 0; | ||
1672 | |||
1673 | if (tmpaddr && memcmp(idev->rndid, &tmpaddr->s6_addr[8], 8) == 0) | 1657 | if (tmpaddr && memcmp(idev->rndid, &tmpaddr->s6_addr[8], 8) == 0) |
1674 | ret = __ipv6_regen_rndid(idev); | 1658 | __ipv6_regen_rndid(idev); |
1675 | return ret; | ||
1676 | } | 1659 | } |
1677 | #endif | 1660 | #endif |
1678 | 1661 | ||
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index 9772fbd8a3f5..90bbefb57943 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/seq_file.h> | 22 | #include <linux/seq_file.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/export.h> | 24 | #include <linux/export.h> |
25 | #include <linux/pid_namespace.h> | ||
25 | 26 | ||
26 | #include <net/net_namespace.h> | 27 | #include <net/net_namespace.h> |
27 | #include <net/sock.h> | 28 | #include <net/sock.h> |
@@ -91,6 +92,8 @@ static struct ip6_flowlabel *fl_lookup(struct net *net, __be32 label) | |||
91 | static void fl_free(struct ip6_flowlabel *fl) | 92 | static void fl_free(struct ip6_flowlabel *fl) |
92 | { | 93 | { |
93 | if (fl) { | 94 | if (fl) { |
95 | if (fl->share == IPV6_FL_S_PROCESS) | ||
96 | put_pid(fl->owner.pid); | ||
94 | release_net(fl->fl_net); | 97 | release_net(fl->fl_net); |
95 | kfree(fl->opt); | 98 | kfree(fl->opt); |
96 | } | 99 | } |
@@ -394,10 +397,10 @@ fl_create(struct net *net, struct sock *sk, struct in6_flowlabel_req *freq, | |||
394 | case IPV6_FL_S_ANY: | 397 | case IPV6_FL_S_ANY: |
395 | break; | 398 | break; |
396 | case IPV6_FL_S_PROCESS: | 399 | case IPV6_FL_S_PROCESS: |
397 | fl->owner = current->pid; | 400 | fl->owner.pid = get_task_pid(current, PIDTYPE_PID); |
398 | break; | 401 | break; |
399 | case IPV6_FL_S_USER: | 402 | case IPV6_FL_S_USER: |
400 | fl->owner = current_euid(); | 403 | fl->owner.uid = current_euid(); |
401 | break; | 404 | break; |
402 | default: | 405 | default: |
403 | err = -EINVAL; | 406 | err = -EINVAL; |
@@ -561,7 +564,10 @@ recheck: | |||
561 | err = -EPERM; | 564 | err = -EPERM; |
562 | if (fl1->share == IPV6_FL_S_EXCL || | 565 | if (fl1->share == IPV6_FL_S_EXCL || |
563 | fl1->share != fl->share || | 566 | fl1->share != fl->share || |
564 | fl1->owner != fl->owner) | 567 | ((fl1->share == IPV6_FL_S_PROCESS) && |
568 | (fl1->owner.pid == fl->owner.pid)) || | ||
569 | ((fl1->share == IPV6_FL_S_USER) && | ||
570 | uid_eq(fl1->owner.uid, fl->owner.uid))) | ||
565 | goto release; | 571 | goto release; |
566 | 572 | ||
567 | err = -EINVAL; | 573 | err = -EINVAL; |
@@ -621,6 +627,7 @@ done: | |||
621 | 627 | ||
622 | struct ip6fl_iter_state { | 628 | struct ip6fl_iter_state { |
623 | struct seq_net_private p; | 629 | struct seq_net_private p; |
630 | struct pid_namespace *pid_ns; | ||
624 | int bucket; | 631 | int bucket; |
625 | }; | 632 | }; |
626 | 633 | ||
@@ -699,6 +706,7 @@ static void ip6fl_seq_stop(struct seq_file *seq, void *v) | |||
699 | 706 | ||
700 | static int ip6fl_seq_show(struct seq_file *seq, void *v) | 707 | static int ip6fl_seq_show(struct seq_file *seq, void *v) |
701 | { | 708 | { |
709 | struct ip6fl_iter_state *state = ip6fl_seq_private(seq); | ||
702 | if (v == SEQ_START_TOKEN) | 710 | if (v == SEQ_START_TOKEN) |
703 | seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-32s %s\n", | 711 | seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-32s %s\n", |
704 | "Label", "S", "Owner", "Users", "Linger", "Expires", "Dst", "Opt"); | 712 | "Label", "S", "Owner", "Users", "Linger", "Expires", "Dst", "Opt"); |
@@ -708,7 +716,11 @@ static int ip6fl_seq_show(struct seq_file *seq, void *v) | |||
708 | "%05X %-1d %-6d %-6d %-6ld %-8ld %pi6 %-4d\n", | 716 | "%05X %-1d %-6d %-6d %-6ld %-8ld %pi6 %-4d\n", |
709 | (unsigned int)ntohl(fl->label), | 717 | (unsigned int)ntohl(fl->label), |
710 | fl->share, | 718 | fl->share, |
711 | (int)fl->owner, | 719 | ((fl->share == IPV6_FL_S_PROCESS) ? |
720 | pid_nr_ns(fl->owner.pid, state->pid_ns) : | ||
721 | ((fl->share == IPV6_FL_S_USER) ? | ||
722 | from_kuid_munged(seq_user_ns(seq), fl->owner.uid) : | ||
723 | 0)), | ||
712 | atomic_read(&fl->users), | 724 | atomic_read(&fl->users), |
713 | fl->linger/HZ, | 725 | fl->linger/HZ, |
714 | (long)(fl->expires - jiffies)/HZ, | 726 | (long)(fl->expires - jiffies)/HZ, |
@@ -727,8 +739,29 @@ static const struct seq_operations ip6fl_seq_ops = { | |||
727 | 739 | ||
728 | static int ip6fl_seq_open(struct inode *inode, struct file *file) | 740 | static int ip6fl_seq_open(struct inode *inode, struct file *file) |
729 | { | 741 | { |
730 | return seq_open_net(inode, file, &ip6fl_seq_ops, | 742 | struct seq_file *seq; |
731 | sizeof(struct ip6fl_iter_state)); | 743 | struct ip6fl_iter_state *state; |
744 | int err; | ||
745 | |||
746 | err = seq_open_net(inode, file, &ip6fl_seq_ops, | ||
747 | sizeof(struct ip6fl_iter_state)); | ||
748 | |||
749 | if (!err) { | ||
750 | seq = file->private_data; | ||
751 | state = ip6fl_seq_private(seq); | ||
752 | rcu_read_lock(); | ||
753 | state->pid_ns = get_pid_ns(task_active_pid_ns(current)); | ||
754 | rcu_read_unlock(); | ||
755 | } | ||
756 | return err; | ||
757 | } | ||
758 | |||
759 | static int ip6fl_seq_release(struct inode *inode, struct file *file) | ||
760 | { | ||
761 | struct seq_file *seq = file->private_data; | ||
762 | struct ip6fl_iter_state *state = ip6fl_seq_private(seq); | ||
763 | put_pid_ns(state->pid_ns); | ||
764 | return seq_release_net(inode, file); | ||
732 | } | 765 | } |
733 | 766 | ||
734 | static const struct file_operations ip6fl_seq_fops = { | 767 | static const struct file_operations ip6fl_seq_fops = { |
@@ -736,7 +769,7 @@ static const struct file_operations ip6fl_seq_fops = { | |||
736 | .open = ip6fl_seq_open, | 769 | .open = ip6fl_seq_open, |
737 | .read = seq_read, | 770 | .read = seq_read, |
738 | .llseek = seq_lseek, | 771 | .llseek = seq_lseek, |
739 | .release = seq_release_net, | 772 | .release = ip6fl_seq_release, |
740 | }; | 773 | }; |
741 | 774 | ||
742 | static int __net_init ip6_flowlabel_proc_init(struct net *net) | 775 | static int __net_init ip6_flowlabel_proc_init(struct net *net) |
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c new file mode 100644 index 000000000000..424d11a4e7ff --- /dev/null +++ b/net/ipv6/ip6_gre.c | |||
@@ -0,0 +1,1792 @@ | |||
1 | /* | ||
2 | * GRE over IPv6 protocol decoder. | ||
3 | * | ||
4 | * Authors: Dmitry Kozlov (xeb@mail.ru) | ||
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 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
14 | |||
15 | #include <linux/capability.h> | ||
16 | #include <linux/module.h> | ||
17 | #include <linux/types.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/uaccess.h> | ||
21 | #include <linux/skbuff.h> | ||
22 | #include <linux/netdevice.h> | ||
23 | #include <linux/in.h> | ||
24 | #include <linux/tcp.h> | ||
25 | #include <linux/udp.h> | ||
26 | #include <linux/if_arp.h> | ||
27 | #include <linux/mroute.h> | ||
28 | #include <linux/init.h> | ||
29 | #include <linux/in6.h> | ||
30 | #include <linux/inetdevice.h> | ||
31 | #include <linux/igmp.h> | ||
32 | #include <linux/netfilter_ipv4.h> | ||
33 | #include <linux/etherdevice.h> | ||
34 | #include <linux/if_ether.h> | ||
35 | #include <linux/hash.h> | ||
36 | #include <linux/if_tunnel.h> | ||
37 | #include <linux/ip6_tunnel.h> | ||
38 | |||
39 | #include <net/sock.h> | ||
40 | #include <net/ip.h> | ||
41 | #include <net/icmp.h> | ||
42 | #include <net/protocol.h> | ||
43 | #include <net/addrconf.h> | ||
44 | #include <net/arp.h> | ||
45 | #include <net/checksum.h> | ||
46 | #include <net/dsfield.h> | ||
47 | #include <net/inet_ecn.h> | ||
48 | #include <net/xfrm.h> | ||
49 | #include <net/net_namespace.h> | ||
50 | #include <net/netns/generic.h> | ||
51 | #include <net/rtnetlink.h> | ||
52 | |||
53 | #include <net/ipv6.h> | ||
54 | #include <net/ip6_fib.h> | ||
55 | #include <net/ip6_route.h> | ||
56 | #include <net/ip6_tunnel.h> | ||
57 | |||
58 | |||
59 | #define IPV6_TCLASS_MASK (IPV6_FLOWINFO_MASK & ~IPV6_FLOWLABEL_MASK) | ||
60 | #define IPV6_TCLASS_SHIFT 20 | ||
61 | |||
62 | #define HASH_SIZE_SHIFT 5 | ||
63 | #define HASH_SIZE (1 << HASH_SIZE_SHIFT) | ||
64 | |||
65 | static int ip6gre_net_id __read_mostly; | ||
66 | struct ip6gre_net { | ||
67 | struct ip6_tnl __rcu *tunnels[4][HASH_SIZE]; | ||
68 | |||
69 | struct net_device *fb_tunnel_dev; | ||
70 | }; | ||
71 | |||
72 | static struct rtnl_link_ops ip6gre_link_ops __read_mostly; | ||
73 | static int ip6gre_tunnel_init(struct net_device *dev); | ||
74 | static void ip6gre_tunnel_setup(struct net_device *dev); | ||
75 | static void ip6gre_tunnel_link(struct ip6gre_net *ign, struct ip6_tnl *t); | ||
76 | static void ip6gre_tnl_link_config(struct ip6_tnl *t, int set_mtu); | ||
77 | |||
78 | /* Tunnel hash table */ | ||
79 | |||
80 | /* | ||
81 | 4 hash tables: | ||
82 | |||
83 | 3: (remote,local) | ||
84 | 2: (remote,*) | ||
85 | 1: (*,local) | ||
86 | 0: (*,*) | ||
87 | |||
88 | We require exact key match i.e. if a key is present in packet | ||
89 | it will match only tunnel with the same key; if it is not present, | ||
90 | it will match only keyless tunnel. | ||
91 | |||
92 | All keysless packets, if not matched configured keyless tunnels | ||
93 | will match fallback tunnel. | ||
94 | */ | ||
95 | |||
96 | #define HASH_KEY(key) (((__force u32)key^((__force u32)key>>4))&(HASH_SIZE - 1)) | ||
97 | static u32 HASH_ADDR(const struct in6_addr *addr) | ||
98 | { | ||
99 | u32 hash = ipv6_addr_hash(addr); | ||
100 | |||
101 | return hash_32(hash, HASH_SIZE_SHIFT); | ||
102 | } | ||
103 | |||
104 | #define tunnels_r_l tunnels[3] | ||
105 | #define tunnels_r tunnels[2] | ||
106 | #define tunnels_l tunnels[1] | ||
107 | #define tunnels_wc tunnels[0] | ||
108 | /* | ||
109 | * Locking : hash tables are protected by RCU and RTNL | ||
110 | */ | ||
111 | |||
112 | #define for_each_ip_tunnel_rcu(start) \ | ||
113 | for (t = rcu_dereference(start); t; t = rcu_dereference(t->next)) | ||
114 | |||
115 | /* often modified stats are per cpu, other are shared (netdev->stats) */ | ||
116 | struct pcpu_tstats { | ||
117 | u64 rx_packets; | ||
118 | u64 rx_bytes; | ||
119 | u64 tx_packets; | ||
120 | u64 tx_bytes; | ||
121 | struct u64_stats_sync syncp; | ||
122 | }; | ||
123 | |||
124 | static struct rtnl_link_stats64 *ip6gre_get_stats64(struct net_device *dev, | ||
125 | struct rtnl_link_stats64 *tot) | ||
126 | { | ||
127 | int i; | ||
128 | |||
129 | for_each_possible_cpu(i) { | ||
130 | const struct pcpu_tstats *tstats = per_cpu_ptr(dev->tstats, i); | ||
131 | u64 rx_packets, rx_bytes, tx_packets, tx_bytes; | ||
132 | unsigned int start; | ||
133 | |||
134 | do { | ||
135 | start = u64_stats_fetch_begin_bh(&tstats->syncp); | ||
136 | rx_packets = tstats->rx_packets; | ||
137 | tx_packets = tstats->tx_packets; | ||
138 | rx_bytes = tstats->rx_bytes; | ||
139 | tx_bytes = tstats->tx_bytes; | ||
140 | } while (u64_stats_fetch_retry_bh(&tstats->syncp, start)); | ||
141 | |||
142 | tot->rx_packets += rx_packets; | ||
143 | tot->tx_packets += tx_packets; | ||
144 | tot->rx_bytes += rx_bytes; | ||
145 | tot->tx_bytes += tx_bytes; | ||
146 | } | ||
147 | |||
148 | tot->multicast = dev->stats.multicast; | ||
149 | tot->rx_crc_errors = dev->stats.rx_crc_errors; | ||
150 | tot->rx_fifo_errors = dev->stats.rx_fifo_errors; | ||
151 | tot->rx_length_errors = dev->stats.rx_length_errors; | ||
152 | tot->rx_errors = dev->stats.rx_errors; | ||
153 | tot->tx_fifo_errors = dev->stats.tx_fifo_errors; | ||
154 | tot->tx_carrier_errors = dev->stats.tx_carrier_errors; | ||
155 | tot->tx_dropped = dev->stats.tx_dropped; | ||
156 | tot->tx_aborted_errors = dev->stats.tx_aborted_errors; | ||
157 | tot->tx_errors = dev->stats.tx_errors; | ||
158 | |||
159 | return tot; | ||
160 | } | ||
161 | |||
162 | /* Given src, dst and key, find appropriate for input tunnel. */ | ||
163 | |||
164 | static struct ip6_tnl *ip6gre_tunnel_lookup(struct net_device *dev, | ||
165 | const struct in6_addr *remote, const struct in6_addr *local, | ||
166 | __be32 key, __be16 gre_proto) | ||
167 | { | ||
168 | struct net *net = dev_net(dev); | ||
169 | int link = dev->ifindex; | ||
170 | unsigned int h0 = HASH_ADDR(remote); | ||
171 | unsigned int h1 = HASH_KEY(key); | ||
172 | struct ip6_tnl *t, *cand = NULL; | ||
173 | struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); | ||
174 | int dev_type = (gre_proto == htons(ETH_P_TEB)) ? | ||
175 | ARPHRD_ETHER : ARPHRD_IP6GRE; | ||
176 | int score, cand_score = 4; | ||
177 | |||
178 | for_each_ip_tunnel_rcu(ign->tunnels_r_l[h0 ^ h1]) { | ||
179 | if (!ipv6_addr_equal(local, &t->parms.laddr) || | ||
180 | !ipv6_addr_equal(remote, &t->parms.raddr) || | ||
181 | key != t->parms.i_key || | ||
182 | !(t->dev->flags & IFF_UP)) | ||
183 | continue; | ||
184 | |||
185 | if (t->dev->type != ARPHRD_IP6GRE && | ||
186 | t->dev->type != dev_type) | ||
187 | continue; | ||
188 | |||
189 | score = 0; | ||
190 | if (t->parms.link != link) | ||
191 | score |= 1; | ||
192 | if (t->dev->type != dev_type) | ||
193 | score |= 2; | ||
194 | if (score == 0) | ||
195 | return t; | ||
196 | |||
197 | if (score < cand_score) { | ||
198 | cand = t; | ||
199 | cand_score = score; | ||
200 | } | ||
201 | } | ||
202 | |||
203 | for_each_ip_tunnel_rcu(ign->tunnels_r[h0 ^ h1]) { | ||
204 | if (!ipv6_addr_equal(remote, &t->parms.raddr) || | ||
205 | key != t->parms.i_key || | ||
206 | !(t->dev->flags & IFF_UP)) | ||
207 | continue; | ||
208 | |||
209 | if (t->dev->type != ARPHRD_IP6GRE && | ||
210 | t->dev->type != dev_type) | ||
211 | continue; | ||
212 | |||
213 | score = 0; | ||
214 | if (t->parms.link != link) | ||
215 | score |= 1; | ||
216 | if (t->dev->type != dev_type) | ||
217 | score |= 2; | ||
218 | if (score == 0) | ||
219 | return t; | ||
220 | |||
221 | if (score < cand_score) { | ||
222 | cand = t; | ||
223 | cand_score = score; | ||
224 | } | ||
225 | } | ||
226 | |||
227 | for_each_ip_tunnel_rcu(ign->tunnels_l[h1]) { | ||
228 | if ((!ipv6_addr_equal(local, &t->parms.laddr) && | ||
229 | (!ipv6_addr_equal(local, &t->parms.raddr) || | ||
230 | !ipv6_addr_is_multicast(local))) || | ||
231 | key != t->parms.i_key || | ||
232 | !(t->dev->flags & IFF_UP)) | ||
233 | continue; | ||
234 | |||
235 | if (t->dev->type != ARPHRD_IP6GRE && | ||
236 | t->dev->type != dev_type) | ||
237 | continue; | ||
238 | |||
239 | score = 0; | ||
240 | if (t->parms.link != link) | ||
241 | score |= 1; | ||
242 | if (t->dev->type != dev_type) | ||
243 | score |= 2; | ||
244 | if (score == 0) | ||
245 | return t; | ||
246 | |||
247 | if (score < cand_score) { | ||
248 | cand = t; | ||
249 | cand_score = score; | ||
250 | } | ||
251 | } | ||
252 | |||
253 | for_each_ip_tunnel_rcu(ign->tunnels_wc[h1]) { | ||
254 | if (t->parms.i_key != key || | ||
255 | !(t->dev->flags & IFF_UP)) | ||
256 | continue; | ||
257 | |||
258 | if (t->dev->type != ARPHRD_IP6GRE && | ||
259 | t->dev->type != dev_type) | ||
260 | continue; | ||
261 | |||
262 | score = 0; | ||
263 | if (t->parms.link != link) | ||
264 | score |= 1; | ||
265 | if (t->dev->type != dev_type) | ||
266 | score |= 2; | ||
267 | if (score == 0) | ||
268 | return t; | ||
269 | |||
270 | if (score < cand_score) { | ||
271 | cand = t; | ||
272 | cand_score = score; | ||
273 | } | ||
274 | } | ||
275 | |||
276 | if (cand != NULL) | ||
277 | return cand; | ||
278 | |||
279 | dev = ign->fb_tunnel_dev; | ||
280 | if (dev->flags & IFF_UP) | ||
281 | return netdev_priv(dev); | ||
282 | |||
283 | return NULL; | ||
284 | } | ||
285 | |||
286 | static struct ip6_tnl __rcu **__ip6gre_bucket(struct ip6gre_net *ign, | ||
287 | const struct __ip6_tnl_parm *p) | ||
288 | { | ||
289 | const struct in6_addr *remote = &p->raddr; | ||
290 | const struct in6_addr *local = &p->laddr; | ||
291 | unsigned int h = HASH_KEY(p->i_key); | ||
292 | int prio = 0; | ||
293 | |||
294 | if (!ipv6_addr_any(local)) | ||
295 | prio |= 1; | ||
296 | if (!ipv6_addr_any(remote) && !ipv6_addr_is_multicast(remote)) { | ||
297 | prio |= 2; | ||
298 | h ^= HASH_ADDR(remote); | ||
299 | } | ||
300 | |||
301 | return &ign->tunnels[prio][h]; | ||
302 | } | ||
303 | |||
304 | static inline struct ip6_tnl __rcu **ip6gre_bucket(struct ip6gre_net *ign, | ||
305 | const struct ip6_tnl *t) | ||
306 | { | ||
307 | return __ip6gre_bucket(ign, &t->parms); | ||
308 | } | ||
309 | |||
310 | static void ip6gre_tunnel_link(struct ip6gre_net *ign, struct ip6_tnl *t) | ||
311 | { | ||
312 | struct ip6_tnl __rcu **tp = ip6gre_bucket(ign, t); | ||
313 | |||
314 | rcu_assign_pointer(t->next, rtnl_dereference(*tp)); | ||
315 | rcu_assign_pointer(*tp, t); | ||
316 | } | ||
317 | |||
318 | static void ip6gre_tunnel_unlink(struct ip6gre_net *ign, struct ip6_tnl *t) | ||
319 | { | ||
320 | struct ip6_tnl __rcu **tp; | ||
321 | struct ip6_tnl *iter; | ||
322 | |||
323 | for (tp = ip6gre_bucket(ign, t); | ||
324 | (iter = rtnl_dereference(*tp)) != NULL; | ||
325 | tp = &iter->next) { | ||
326 | if (t == iter) { | ||
327 | rcu_assign_pointer(*tp, t->next); | ||
328 | break; | ||
329 | } | ||
330 | } | ||
331 | } | ||
332 | |||
333 | static struct ip6_tnl *ip6gre_tunnel_find(struct net *net, | ||
334 | const struct __ip6_tnl_parm *parms, | ||
335 | int type) | ||
336 | { | ||
337 | const struct in6_addr *remote = &parms->raddr; | ||
338 | const struct in6_addr *local = &parms->laddr; | ||
339 | __be32 key = parms->i_key; | ||
340 | int link = parms->link; | ||
341 | struct ip6_tnl *t; | ||
342 | struct ip6_tnl __rcu **tp; | ||
343 | struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); | ||
344 | |||
345 | for (tp = __ip6gre_bucket(ign, parms); | ||
346 | (t = rtnl_dereference(*tp)) != NULL; | ||
347 | tp = &t->next) | ||
348 | if (ipv6_addr_equal(local, &t->parms.laddr) && | ||
349 | ipv6_addr_equal(remote, &t->parms.raddr) && | ||
350 | key == t->parms.i_key && | ||
351 | link == t->parms.link && | ||
352 | type == t->dev->type) | ||
353 | break; | ||
354 | |||
355 | return t; | ||
356 | } | ||
357 | |||
358 | static struct ip6_tnl *ip6gre_tunnel_locate(struct net *net, | ||
359 | const struct __ip6_tnl_parm *parms, int create) | ||
360 | { | ||
361 | struct ip6_tnl *t, *nt; | ||
362 | struct net_device *dev; | ||
363 | char name[IFNAMSIZ]; | ||
364 | struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); | ||
365 | |||
366 | t = ip6gre_tunnel_find(net, parms, ARPHRD_IP6GRE); | ||
367 | if (t || !create) | ||
368 | return t; | ||
369 | |||
370 | if (parms->name[0]) | ||
371 | strlcpy(name, parms->name, IFNAMSIZ); | ||
372 | else | ||
373 | strcpy(name, "ip6gre%d"); | ||
374 | |||
375 | dev = alloc_netdev(sizeof(*t), name, ip6gre_tunnel_setup); | ||
376 | if (!dev) | ||
377 | return NULL; | ||
378 | |||
379 | dev_net_set(dev, net); | ||
380 | |||
381 | nt = netdev_priv(dev); | ||
382 | nt->parms = *parms; | ||
383 | dev->rtnl_link_ops = &ip6gre_link_ops; | ||
384 | |||
385 | nt->dev = dev; | ||
386 | ip6gre_tnl_link_config(nt, 1); | ||
387 | |||
388 | if (register_netdevice(dev) < 0) | ||
389 | goto failed_free; | ||
390 | |||
391 | /* Can use a lockless transmit, unless we generate output sequences */ | ||
392 | if (!(nt->parms.o_flags & GRE_SEQ)) | ||
393 | dev->features |= NETIF_F_LLTX; | ||
394 | |||
395 | dev_hold(dev); | ||
396 | ip6gre_tunnel_link(ign, nt); | ||
397 | return nt; | ||
398 | |||
399 | failed_free: | ||
400 | free_netdev(dev); | ||
401 | return NULL; | ||
402 | } | ||
403 | |||
404 | static void ip6gre_tunnel_uninit(struct net_device *dev) | ||
405 | { | ||
406 | struct net *net = dev_net(dev); | ||
407 | struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); | ||
408 | |||
409 | ip6gre_tunnel_unlink(ign, netdev_priv(dev)); | ||
410 | dev_put(dev); | ||
411 | } | ||
412 | |||
413 | |||
414 | static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | ||
415 | u8 type, u8 code, int offset, __be32 info) | ||
416 | { | ||
417 | const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)skb->data; | ||
418 | __be16 *p = (__be16 *)(skb->data + offset); | ||
419 | int grehlen = offset + 4; | ||
420 | struct ip6_tnl *t; | ||
421 | __be16 flags; | ||
422 | |||
423 | flags = p[0]; | ||
424 | if (flags&(GRE_CSUM|GRE_KEY|GRE_SEQ|GRE_ROUTING|GRE_VERSION)) { | ||
425 | if (flags&(GRE_VERSION|GRE_ROUTING)) | ||
426 | return; | ||
427 | if (flags&GRE_KEY) { | ||
428 | grehlen += 4; | ||
429 | if (flags&GRE_CSUM) | ||
430 | grehlen += 4; | ||
431 | } | ||
432 | } | ||
433 | |||
434 | /* If only 8 bytes returned, keyed message will be dropped here */ | ||
435 | if (!pskb_may_pull(skb, grehlen)) | ||
436 | return; | ||
437 | ipv6h = (const struct ipv6hdr *)skb->data; | ||
438 | p = (__be16 *)(skb->data + offset); | ||
439 | |||
440 | rcu_read_lock(); | ||
441 | |||
442 | t = ip6gre_tunnel_lookup(skb->dev, &ipv6h->daddr, &ipv6h->saddr, | ||
443 | flags & GRE_KEY ? | ||
444 | *(((__be32 *)p) + (grehlen / 4) - 1) : 0, | ||
445 | p[1]); | ||
446 | if (t == NULL) | ||
447 | goto out; | ||
448 | |||
449 | switch (type) { | ||
450 | __u32 teli; | ||
451 | struct ipv6_tlv_tnl_enc_lim *tel; | ||
452 | __u32 mtu; | ||
453 | case ICMPV6_DEST_UNREACH: | ||
454 | net_warn_ratelimited("%s: Path to destination invalid or inactive!\n", | ||
455 | t->parms.name); | ||
456 | break; | ||
457 | case ICMPV6_TIME_EXCEED: | ||
458 | if (code == ICMPV6_EXC_HOPLIMIT) { | ||
459 | net_warn_ratelimited("%s: Too small hop limit or routing loop in tunnel!\n", | ||
460 | t->parms.name); | ||
461 | } | ||
462 | break; | ||
463 | case ICMPV6_PARAMPROB: | ||
464 | teli = 0; | ||
465 | if (code == ICMPV6_HDR_FIELD) | ||
466 | teli = ip6_tnl_parse_tlv_enc_lim(skb, skb->data); | ||
467 | |||
468 | if (teli && teli == info - 2) { | ||
469 | tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->data[teli]; | ||
470 | if (tel->encap_limit == 0) { | ||
471 | net_warn_ratelimited("%s: Too small encapsulation limit or routing loop in tunnel!\n", | ||
472 | t->parms.name); | ||
473 | } | ||
474 | } else { | ||
475 | net_warn_ratelimited("%s: Recipient unable to parse tunneled packet!\n", | ||
476 | t->parms.name); | ||
477 | } | ||
478 | break; | ||
479 | case ICMPV6_PKT_TOOBIG: | ||
480 | mtu = info - offset; | ||
481 | if (mtu < IPV6_MIN_MTU) | ||
482 | mtu = IPV6_MIN_MTU; | ||
483 | t->dev->mtu = mtu; | ||
484 | break; | ||
485 | } | ||
486 | |||
487 | if (time_before(jiffies, t->err_time + IP6TUNNEL_ERR_TIMEO)) | ||
488 | t->err_count++; | ||
489 | else | ||
490 | t->err_count = 1; | ||
491 | t->err_time = jiffies; | ||
492 | out: | ||
493 | rcu_read_unlock(); | ||
494 | } | ||
495 | |||
496 | static inline void ip6gre_ecn_decapsulate_ipv4(const struct ip6_tnl *t, | ||
497 | const struct ipv6hdr *ipv6h, struct sk_buff *skb) | ||
498 | { | ||
499 | __u8 dsfield = ipv6_get_dsfield(ipv6h) & ~INET_ECN_MASK; | ||
500 | |||
501 | if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY) | ||
502 | ipv4_change_dsfield(ip_hdr(skb), INET_ECN_MASK, dsfield); | ||
503 | |||
504 | if (INET_ECN_is_ce(dsfield)) | ||
505 | IP_ECN_set_ce(ip_hdr(skb)); | ||
506 | } | ||
507 | |||
508 | static inline void ip6gre_ecn_decapsulate_ipv6(const struct ip6_tnl *t, | ||
509 | const struct ipv6hdr *ipv6h, struct sk_buff *skb) | ||
510 | { | ||
511 | if (t->parms.flags & IP6_TNL_F_RCV_DSCP_COPY) | ||
512 | ipv6_copy_dscp(ipv6_get_dsfield(ipv6h), ipv6_hdr(skb)); | ||
513 | |||
514 | if (INET_ECN_is_ce(ipv6_get_dsfield(ipv6h))) | ||
515 | IP6_ECN_set_ce(ipv6_hdr(skb)); | ||
516 | } | ||
517 | |||
518 | static int ip6gre_rcv(struct sk_buff *skb) | ||
519 | { | ||
520 | const struct ipv6hdr *ipv6h; | ||
521 | u8 *h; | ||
522 | __be16 flags; | ||
523 | __sum16 csum = 0; | ||
524 | __be32 key = 0; | ||
525 | u32 seqno = 0; | ||
526 | struct ip6_tnl *tunnel; | ||
527 | int offset = 4; | ||
528 | __be16 gre_proto; | ||
529 | |||
530 | if (!pskb_may_pull(skb, sizeof(struct in6_addr))) | ||
531 | goto drop_nolock; | ||
532 | |||
533 | ipv6h = ipv6_hdr(skb); | ||
534 | h = skb->data; | ||
535 | flags = *(__be16 *)h; | ||
536 | |||
537 | if (flags&(GRE_CSUM|GRE_KEY|GRE_ROUTING|GRE_SEQ|GRE_VERSION)) { | ||
538 | /* - Version must be 0. | ||
539 | - We do not support routing headers. | ||
540 | */ | ||
541 | if (flags&(GRE_VERSION|GRE_ROUTING)) | ||
542 | goto drop_nolock; | ||
543 | |||
544 | if (flags&GRE_CSUM) { | ||
545 | switch (skb->ip_summed) { | ||
546 | case CHECKSUM_COMPLETE: | ||
547 | csum = csum_fold(skb->csum); | ||
548 | if (!csum) | ||
549 | break; | ||
550 | /* fall through */ | ||
551 | case CHECKSUM_NONE: | ||
552 | skb->csum = 0; | ||
553 | csum = __skb_checksum_complete(skb); | ||
554 | skb->ip_summed = CHECKSUM_COMPLETE; | ||
555 | } | ||
556 | offset += 4; | ||
557 | } | ||
558 | if (flags&GRE_KEY) { | ||
559 | key = *(__be32 *)(h + offset); | ||
560 | offset += 4; | ||
561 | } | ||
562 | if (flags&GRE_SEQ) { | ||
563 | seqno = ntohl(*(__be32 *)(h + offset)); | ||
564 | offset += 4; | ||
565 | } | ||
566 | } | ||
567 | |||
568 | gre_proto = *(__be16 *)(h + 2); | ||
569 | |||
570 | rcu_read_lock(); | ||
571 | tunnel = ip6gre_tunnel_lookup(skb->dev, | ||
572 | &ipv6h->saddr, &ipv6h->daddr, key, | ||
573 | gre_proto); | ||
574 | if (tunnel) { | ||
575 | struct pcpu_tstats *tstats; | ||
576 | |||
577 | if (!xfrm6_policy_check(NULL, XFRM_POLICY_IN, skb)) | ||
578 | goto drop; | ||
579 | |||
580 | if (!ip6_tnl_rcv_ctl(tunnel, &ipv6h->daddr, &ipv6h->saddr)) { | ||
581 | tunnel->dev->stats.rx_dropped++; | ||
582 | goto drop; | ||
583 | } | ||
584 | |||
585 | secpath_reset(skb); | ||
586 | |||
587 | skb->protocol = gre_proto; | ||
588 | /* WCCP version 1 and 2 protocol decoding. | ||
589 | * - Change protocol to IP | ||
590 | * - When dealing with WCCPv2, Skip extra 4 bytes in GRE header | ||
591 | */ | ||
592 | if (flags == 0 && gre_proto == htons(ETH_P_WCCP)) { | ||
593 | skb->protocol = htons(ETH_P_IP); | ||
594 | if ((*(h + offset) & 0xF0) != 0x40) | ||
595 | offset += 4; | ||
596 | } | ||
597 | |||
598 | skb->mac_header = skb->network_header; | ||
599 | __pskb_pull(skb, offset); | ||
600 | skb_postpull_rcsum(skb, skb_transport_header(skb), offset); | ||
601 | skb->pkt_type = PACKET_HOST; | ||
602 | |||
603 | if (((flags&GRE_CSUM) && csum) || | ||
604 | (!(flags&GRE_CSUM) && tunnel->parms.i_flags&GRE_CSUM)) { | ||
605 | tunnel->dev->stats.rx_crc_errors++; | ||
606 | tunnel->dev->stats.rx_errors++; | ||
607 | goto drop; | ||
608 | } | ||
609 | if (tunnel->parms.i_flags&GRE_SEQ) { | ||
610 | if (!(flags&GRE_SEQ) || | ||
611 | (tunnel->i_seqno && | ||
612 | (s32)(seqno - tunnel->i_seqno) < 0)) { | ||
613 | tunnel->dev->stats.rx_fifo_errors++; | ||
614 | tunnel->dev->stats.rx_errors++; | ||
615 | goto drop; | ||
616 | } | ||
617 | tunnel->i_seqno = seqno + 1; | ||
618 | } | ||
619 | |||
620 | /* Warning: All skb pointers will be invalidated! */ | ||
621 | if (tunnel->dev->type == ARPHRD_ETHER) { | ||
622 | if (!pskb_may_pull(skb, ETH_HLEN)) { | ||
623 | tunnel->dev->stats.rx_length_errors++; | ||
624 | tunnel->dev->stats.rx_errors++; | ||
625 | goto drop; | ||
626 | } | ||
627 | |||
628 | ipv6h = ipv6_hdr(skb); | ||
629 | skb->protocol = eth_type_trans(skb, tunnel->dev); | ||
630 | skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN); | ||
631 | } | ||
632 | |||
633 | tstats = this_cpu_ptr(tunnel->dev->tstats); | ||
634 | u64_stats_update_begin(&tstats->syncp); | ||
635 | tstats->rx_packets++; | ||
636 | tstats->rx_bytes += skb->len; | ||
637 | u64_stats_update_end(&tstats->syncp); | ||
638 | |||
639 | __skb_tunnel_rx(skb, tunnel->dev); | ||
640 | |||
641 | skb_reset_network_header(skb); | ||
642 | if (skb->protocol == htons(ETH_P_IP)) | ||
643 | ip6gre_ecn_decapsulate_ipv4(tunnel, ipv6h, skb); | ||
644 | else if (skb->protocol == htons(ETH_P_IPV6)) | ||
645 | ip6gre_ecn_decapsulate_ipv6(tunnel, ipv6h, skb); | ||
646 | |||
647 | netif_rx(skb); | ||
648 | |||
649 | rcu_read_unlock(); | ||
650 | return 0; | ||
651 | } | ||
652 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); | ||
653 | |||
654 | drop: | ||
655 | rcu_read_unlock(); | ||
656 | drop_nolock: | ||
657 | kfree_skb(skb); | ||
658 | return 0; | ||
659 | } | ||
660 | |||
661 | struct ipv6_tel_txoption { | ||
662 | struct ipv6_txoptions ops; | ||
663 | __u8 dst_opt[8]; | ||
664 | }; | ||
665 | |||
666 | static void init_tel_txopt(struct ipv6_tel_txoption *opt, __u8 encap_limit) | ||
667 | { | ||
668 | memset(opt, 0, sizeof(struct ipv6_tel_txoption)); | ||
669 | |||
670 | opt->dst_opt[2] = IPV6_TLV_TNL_ENCAP_LIMIT; | ||
671 | opt->dst_opt[3] = 1; | ||
672 | opt->dst_opt[4] = encap_limit; | ||
673 | opt->dst_opt[5] = IPV6_TLV_PADN; | ||
674 | opt->dst_opt[6] = 1; | ||
675 | |||
676 | opt->ops.dst0opt = (struct ipv6_opt_hdr *) opt->dst_opt; | ||
677 | opt->ops.opt_nflen = 8; | ||
678 | } | ||
679 | |||
680 | static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb, | ||
681 | struct net_device *dev, | ||
682 | __u8 dsfield, | ||
683 | struct flowi6 *fl6, | ||
684 | int encap_limit, | ||
685 | __u32 *pmtu) | ||
686 | { | ||
687 | struct net *net = dev_net(dev); | ||
688 | struct ip6_tnl *tunnel = netdev_priv(dev); | ||
689 | struct net_device *tdev; /* Device to other host */ | ||
690 | struct ipv6hdr *ipv6h; /* Our new IP header */ | ||
691 | unsigned int max_headroom; /* The extra header space needed */ | ||
692 | int gre_hlen; | ||
693 | struct ipv6_tel_txoption opt; | ||
694 | int mtu; | ||
695 | struct dst_entry *dst = NULL, *ndst = NULL; | ||
696 | struct net_device_stats *stats = &tunnel->dev->stats; | ||
697 | int err = -1; | ||
698 | u8 proto; | ||
699 | int pkt_len; | ||
700 | struct sk_buff *new_skb; | ||
701 | |||
702 | if (dev->type == ARPHRD_ETHER) | ||
703 | IPCB(skb)->flags = 0; | ||
704 | |||
705 | if (dev->header_ops && dev->type == ARPHRD_IP6GRE) { | ||
706 | gre_hlen = 0; | ||
707 | ipv6h = (struct ipv6hdr *)skb->data; | ||
708 | fl6->daddr = ipv6h->daddr; | ||
709 | } else { | ||
710 | gre_hlen = tunnel->hlen; | ||
711 | fl6->daddr = tunnel->parms.raddr; | ||
712 | } | ||
713 | |||
714 | if (!fl6->flowi6_mark) | ||
715 | dst = ip6_tnl_dst_check(tunnel); | ||
716 | |||
717 | if (!dst) { | ||
718 | ndst = ip6_route_output(net, NULL, fl6); | ||
719 | |||
720 | if (ndst->error) | ||
721 | goto tx_err_link_failure; | ||
722 | ndst = xfrm_lookup(net, ndst, flowi6_to_flowi(fl6), NULL, 0); | ||
723 | if (IS_ERR(ndst)) { | ||
724 | err = PTR_ERR(ndst); | ||
725 | ndst = NULL; | ||
726 | goto tx_err_link_failure; | ||
727 | } | ||
728 | dst = ndst; | ||
729 | } | ||
730 | |||
731 | tdev = dst->dev; | ||
732 | |||
733 | if (tdev == dev) { | ||
734 | stats->collisions++; | ||
735 | net_warn_ratelimited("%s: Local routing loop detected!\n", | ||
736 | tunnel->parms.name); | ||
737 | goto tx_err_dst_release; | ||
738 | } | ||
739 | |||
740 | mtu = dst_mtu(dst) - sizeof(*ipv6h); | ||
741 | if (encap_limit >= 0) { | ||
742 | max_headroom += 8; | ||
743 | mtu -= 8; | ||
744 | } | ||
745 | if (mtu < IPV6_MIN_MTU) | ||
746 | mtu = IPV6_MIN_MTU; | ||
747 | if (skb_dst(skb)) | ||
748 | skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu); | ||
749 | if (skb->len > mtu) { | ||
750 | *pmtu = mtu; | ||
751 | err = -EMSGSIZE; | ||
752 | goto tx_err_dst_release; | ||
753 | } | ||
754 | |||
755 | if (tunnel->err_count > 0) { | ||
756 | if (time_before(jiffies, | ||
757 | tunnel->err_time + IP6TUNNEL_ERR_TIMEO)) { | ||
758 | tunnel->err_count--; | ||
759 | |||
760 | dst_link_failure(skb); | ||
761 | } else | ||
762 | tunnel->err_count = 0; | ||
763 | } | ||
764 | |||
765 | max_headroom = LL_RESERVED_SPACE(tdev) + gre_hlen + dst->header_len; | ||
766 | |||
767 | if (skb_headroom(skb) < max_headroom || skb_shared(skb) || | ||
768 | (skb_cloned(skb) && !skb_clone_writable(skb, 0))) { | ||
769 | new_skb = skb_realloc_headroom(skb, max_headroom); | ||
770 | if (max_headroom > dev->needed_headroom) | ||
771 | dev->needed_headroom = max_headroom; | ||
772 | if (!new_skb) | ||
773 | goto tx_err_dst_release; | ||
774 | |||
775 | if (skb->sk) | ||
776 | skb_set_owner_w(new_skb, skb->sk); | ||
777 | consume_skb(skb); | ||
778 | skb = new_skb; | ||
779 | } | ||
780 | |||
781 | skb_dst_drop(skb); | ||
782 | |||
783 | if (fl6->flowi6_mark) { | ||
784 | skb_dst_set(skb, dst); | ||
785 | ndst = NULL; | ||
786 | } else { | ||
787 | skb_dst_set_noref(skb, dst); | ||
788 | } | ||
789 | |||
790 | skb->transport_header = skb->network_header; | ||
791 | |||
792 | proto = NEXTHDR_GRE; | ||
793 | if (encap_limit >= 0) { | ||
794 | init_tel_txopt(&opt, encap_limit); | ||
795 | ipv6_push_nfrag_opts(skb, &opt.ops, &proto, NULL); | ||
796 | } | ||
797 | |||
798 | skb_push(skb, gre_hlen); | ||
799 | skb_reset_network_header(skb); | ||
800 | |||
801 | /* | ||
802 | * Push down and install the IP header. | ||
803 | */ | ||
804 | ipv6h = ipv6_hdr(skb); | ||
805 | *(__be32 *)ipv6h = fl6->flowlabel | htonl(0x60000000); | ||
806 | dsfield = INET_ECN_encapsulate(0, dsfield); | ||
807 | ipv6_change_dsfield(ipv6h, ~INET_ECN_MASK, dsfield); | ||
808 | ipv6h->hop_limit = tunnel->parms.hop_limit; | ||
809 | ipv6h->nexthdr = proto; | ||
810 | ipv6h->saddr = fl6->saddr; | ||
811 | ipv6h->daddr = fl6->daddr; | ||
812 | |||
813 | ((__be16 *)(ipv6h + 1))[0] = tunnel->parms.o_flags; | ||
814 | ((__be16 *)(ipv6h + 1))[1] = (dev->type == ARPHRD_ETHER) ? | ||
815 | htons(ETH_P_TEB) : skb->protocol; | ||
816 | |||
817 | if (tunnel->parms.o_flags&(GRE_KEY|GRE_CSUM|GRE_SEQ)) { | ||
818 | __be32 *ptr = (__be32 *)(((u8 *)ipv6h) + tunnel->hlen - 4); | ||
819 | |||
820 | if (tunnel->parms.o_flags&GRE_SEQ) { | ||
821 | ++tunnel->o_seqno; | ||
822 | *ptr = htonl(tunnel->o_seqno); | ||
823 | ptr--; | ||
824 | } | ||
825 | if (tunnel->parms.o_flags&GRE_KEY) { | ||
826 | *ptr = tunnel->parms.o_key; | ||
827 | ptr--; | ||
828 | } | ||
829 | if (tunnel->parms.o_flags&GRE_CSUM) { | ||
830 | *ptr = 0; | ||
831 | *(__sum16 *)ptr = ip_compute_csum((void *)(ipv6h+1), | ||
832 | skb->len - sizeof(struct ipv6hdr)); | ||
833 | } | ||
834 | } | ||
835 | |||
836 | nf_reset(skb); | ||
837 | pkt_len = skb->len; | ||
838 | err = ip6_local_out(skb); | ||
839 | |||
840 | if (net_xmit_eval(err) == 0) { | ||
841 | struct pcpu_tstats *tstats = this_cpu_ptr(tunnel->dev->tstats); | ||
842 | |||
843 | tstats->tx_bytes += pkt_len; | ||
844 | tstats->tx_packets++; | ||
845 | } else { | ||
846 | stats->tx_errors++; | ||
847 | stats->tx_aborted_errors++; | ||
848 | } | ||
849 | |||
850 | if (ndst) | ||
851 | ip6_tnl_dst_store(tunnel, ndst); | ||
852 | |||
853 | return 0; | ||
854 | tx_err_link_failure: | ||
855 | stats->tx_carrier_errors++; | ||
856 | dst_link_failure(skb); | ||
857 | tx_err_dst_release: | ||
858 | dst_release(ndst); | ||
859 | return err; | ||
860 | } | ||
861 | |||
862 | static inline int ip6gre_xmit_ipv4(struct sk_buff *skb, struct net_device *dev) | ||
863 | { | ||
864 | struct ip6_tnl *t = netdev_priv(dev); | ||
865 | const struct iphdr *iph = ip_hdr(skb); | ||
866 | int encap_limit = -1; | ||
867 | struct flowi6 fl6; | ||
868 | __u8 dsfield; | ||
869 | __u32 mtu; | ||
870 | int err; | ||
871 | |||
872 | if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) | ||
873 | encap_limit = t->parms.encap_limit; | ||
874 | |||
875 | memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6)); | ||
876 | fl6.flowi6_proto = IPPROTO_IPIP; | ||
877 | |||
878 | dsfield = ipv4_get_dsfield(iph); | ||
879 | |||
880 | if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS) | ||
881 | fl6.flowlabel |= htonl((__u32)iph->tos << IPV6_TCLASS_SHIFT) | ||
882 | & IPV6_TCLASS_MASK; | ||
883 | if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK) | ||
884 | fl6.flowi6_mark = skb->mark; | ||
885 | |||
886 | err = ip6gre_xmit2(skb, dev, dsfield, &fl6, encap_limit, &mtu); | ||
887 | if (err != 0) { | ||
888 | /* XXX: send ICMP error even if DF is not set. */ | ||
889 | if (err == -EMSGSIZE) | ||
890 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, | ||
891 | htonl(mtu)); | ||
892 | return -1; | ||
893 | } | ||
894 | |||
895 | return 0; | ||
896 | } | ||
897 | |||
898 | static inline int ip6gre_xmit_ipv6(struct sk_buff *skb, struct net_device *dev) | ||
899 | { | ||
900 | struct ip6_tnl *t = netdev_priv(dev); | ||
901 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); | ||
902 | int encap_limit = -1; | ||
903 | __u16 offset; | ||
904 | struct flowi6 fl6; | ||
905 | __u8 dsfield; | ||
906 | __u32 mtu; | ||
907 | int err; | ||
908 | |||
909 | if (ipv6_addr_equal(&t->parms.raddr, &ipv6h->saddr)) | ||
910 | return -1; | ||
911 | |||
912 | offset = ip6_tnl_parse_tlv_enc_lim(skb, skb_network_header(skb)); | ||
913 | if (offset > 0) { | ||
914 | struct ipv6_tlv_tnl_enc_lim *tel; | ||
915 | tel = (struct ipv6_tlv_tnl_enc_lim *)&skb_network_header(skb)[offset]; | ||
916 | if (tel->encap_limit == 0) { | ||
917 | icmpv6_send(skb, ICMPV6_PARAMPROB, | ||
918 | ICMPV6_HDR_FIELD, offset + 2); | ||
919 | return -1; | ||
920 | } | ||
921 | encap_limit = tel->encap_limit - 1; | ||
922 | } else if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) | ||
923 | encap_limit = t->parms.encap_limit; | ||
924 | |||
925 | memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6)); | ||
926 | fl6.flowi6_proto = IPPROTO_IPV6; | ||
927 | |||
928 | dsfield = ipv6_get_dsfield(ipv6h); | ||
929 | if (t->parms.flags & IP6_TNL_F_USE_ORIG_TCLASS) | ||
930 | fl6.flowlabel |= (*(__be32 *) ipv6h & IPV6_TCLASS_MASK); | ||
931 | if (t->parms.flags & IP6_TNL_F_USE_ORIG_FLOWLABEL) | ||
932 | fl6.flowlabel |= (*(__be32 *) ipv6h & IPV6_FLOWLABEL_MASK); | ||
933 | if (t->parms.flags & IP6_TNL_F_USE_ORIG_FWMARK) | ||
934 | fl6.flowi6_mark = skb->mark; | ||
935 | |||
936 | err = ip6gre_xmit2(skb, dev, dsfield, &fl6, encap_limit, &mtu); | ||
937 | if (err != 0) { | ||
938 | if (err == -EMSGSIZE) | ||
939 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); | ||
940 | return -1; | ||
941 | } | ||
942 | |||
943 | return 0; | ||
944 | } | ||
945 | |||
946 | /** | ||
947 | * ip6_tnl_addr_conflict - compare packet addresses to tunnel's own | ||
948 | * @t: the outgoing tunnel device | ||
949 | * @hdr: IPv6 header from the incoming packet | ||
950 | * | ||
951 | * Description: | ||
952 | * Avoid trivial tunneling loop by checking that tunnel exit-point | ||
953 | * doesn't match source of incoming packet. | ||
954 | * | ||
955 | * Return: | ||
956 | * 1 if conflict, | ||
957 | * 0 else | ||
958 | **/ | ||
959 | |||
960 | static inline bool ip6gre_tnl_addr_conflict(const struct ip6_tnl *t, | ||
961 | const struct ipv6hdr *hdr) | ||
962 | { | ||
963 | return ipv6_addr_equal(&t->parms.raddr, &hdr->saddr); | ||
964 | } | ||
965 | |||
966 | static int ip6gre_xmit_other(struct sk_buff *skb, struct net_device *dev) | ||
967 | { | ||
968 | struct ip6_tnl *t = netdev_priv(dev); | ||
969 | int encap_limit = -1; | ||
970 | struct flowi6 fl6; | ||
971 | __u32 mtu; | ||
972 | int err; | ||
973 | |||
974 | if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) | ||
975 | encap_limit = t->parms.encap_limit; | ||
976 | |||
977 | memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6)); | ||
978 | fl6.flowi6_proto = skb->protocol; | ||
979 | |||
980 | err = ip6gre_xmit2(skb, dev, 0, &fl6, encap_limit, &mtu); | ||
981 | |||
982 | return err; | ||
983 | } | ||
984 | |||
985 | static netdev_tx_t ip6gre_tunnel_xmit(struct sk_buff *skb, | ||
986 | struct net_device *dev) | ||
987 | { | ||
988 | struct ip6_tnl *t = netdev_priv(dev); | ||
989 | struct net_device_stats *stats = &t->dev->stats; | ||
990 | int ret; | ||
991 | |||
992 | if (!ip6_tnl_xmit_ctl(t)) | ||
993 | return -1; | ||
994 | |||
995 | switch (skb->protocol) { | ||
996 | case htons(ETH_P_IP): | ||
997 | ret = ip6gre_xmit_ipv4(skb, dev); | ||
998 | break; | ||
999 | case htons(ETH_P_IPV6): | ||
1000 | ret = ip6gre_xmit_ipv6(skb, dev); | ||
1001 | break; | ||
1002 | default: | ||
1003 | ret = ip6gre_xmit_other(skb, dev); | ||
1004 | break; | ||
1005 | } | ||
1006 | |||
1007 | if (ret < 0) | ||
1008 | goto tx_err; | ||
1009 | |||
1010 | return NETDEV_TX_OK; | ||
1011 | |||
1012 | tx_err: | ||
1013 | stats->tx_errors++; | ||
1014 | stats->tx_dropped++; | ||
1015 | kfree_skb(skb); | ||
1016 | return NETDEV_TX_OK; | ||
1017 | } | ||
1018 | |||
1019 | static void ip6gre_tnl_link_config(struct ip6_tnl *t, int set_mtu) | ||
1020 | { | ||
1021 | struct net_device *dev = t->dev; | ||
1022 | struct __ip6_tnl_parm *p = &t->parms; | ||
1023 | struct flowi6 *fl6 = &t->fl.u.ip6; | ||
1024 | int addend = sizeof(struct ipv6hdr) + 4; | ||
1025 | |||
1026 | if (dev->type != ARPHRD_ETHER) { | ||
1027 | memcpy(dev->dev_addr, &p->laddr, sizeof(struct in6_addr)); | ||
1028 | memcpy(dev->broadcast, &p->raddr, sizeof(struct in6_addr)); | ||
1029 | } | ||
1030 | |||
1031 | /* Set up flowi template */ | ||
1032 | fl6->saddr = p->laddr; | ||
1033 | fl6->daddr = p->raddr; | ||
1034 | fl6->flowi6_oif = p->link; | ||
1035 | fl6->flowlabel = 0; | ||
1036 | |||
1037 | if (!(p->flags&IP6_TNL_F_USE_ORIG_TCLASS)) | ||
1038 | fl6->flowlabel |= IPV6_TCLASS_MASK & p->flowinfo; | ||
1039 | if (!(p->flags&IP6_TNL_F_USE_ORIG_FLOWLABEL)) | ||
1040 | fl6->flowlabel |= IPV6_FLOWLABEL_MASK & p->flowinfo; | ||
1041 | |||
1042 | p->flags &= ~(IP6_TNL_F_CAP_XMIT|IP6_TNL_F_CAP_RCV|IP6_TNL_F_CAP_PER_PACKET); | ||
1043 | p->flags |= ip6_tnl_get_cap(t, &p->laddr, &p->raddr); | ||
1044 | |||
1045 | if (p->flags&IP6_TNL_F_CAP_XMIT && | ||
1046 | p->flags&IP6_TNL_F_CAP_RCV && dev->type != ARPHRD_ETHER) | ||
1047 | dev->flags |= IFF_POINTOPOINT; | ||
1048 | else | ||
1049 | dev->flags &= ~IFF_POINTOPOINT; | ||
1050 | |||
1051 | dev->iflink = p->link; | ||
1052 | |||
1053 | /* Precalculate GRE options length */ | ||
1054 | if (t->parms.o_flags&(GRE_CSUM|GRE_KEY|GRE_SEQ)) { | ||
1055 | if (t->parms.o_flags&GRE_CSUM) | ||
1056 | addend += 4; | ||
1057 | if (t->parms.o_flags&GRE_KEY) | ||
1058 | addend += 4; | ||
1059 | if (t->parms.o_flags&GRE_SEQ) | ||
1060 | addend += 4; | ||
1061 | } | ||
1062 | |||
1063 | if (p->flags & IP6_TNL_F_CAP_XMIT) { | ||
1064 | int strict = (ipv6_addr_type(&p->raddr) & | ||
1065 | (IPV6_ADDR_MULTICAST|IPV6_ADDR_LINKLOCAL)); | ||
1066 | |||
1067 | struct rt6_info *rt = rt6_lookup(dev_net(dev), | ||
1068 | &p->raddr, &p->laddr, | ||
1069 | p->link, strict); | ||
1070 | |||
1071 | if (rt == NULL) | ||
1072 | return; | ||
1073 | |||
1074 | if (rt->dst.dev) { | ||
1075 | dev->hard_header_len = rt->dst.dev->hard_header_len + addend; | ||
1076 | |||
1077 | if (set_mtu) { | ||
1078 | dev->mtu = rt->dst.dev->mtu - addend; | ||
1079 | if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) | ||
1080 | dev->mtu -= 8; | ||
1081 | |||
1082 | if (dev->mtu < IPV6_MIN_MTU) | ||
1083 | dev->mtu = IPV6_MIN_MTU; | ||
1084 | } | ||
1085 | } | ||
1086 | dst_release(&rt->dst); | ||
1087 | } | ||
1088 | |||
1089 | t->hlen = addend; | ||
1090 | } | ||
1091 | |||
1092 | static int ip6gre_tnl_change(struct ip6_tnl *t, | ||
1093 | const struct __ip6_tnl_parm *p, int set_mtu) | ||
1094 | { | ||
1095 | t->parms.laddr = p->laddr; | ||
1096 | t->parms.raddr = p->raddr; | ||
1097 | t->parms.flags = p->flags; | ||
1098 | t->parms.hop_limit = p->hop_limit; | ||
1099 | t->parms.encap_limit = p->encap_limit; | ||
1100 | t->parms.flowinfo = p->flowinfo; | ||
1101 | t->parms.link = p->link; | ||
1102 | t->parms.proto = p->proto; | ||
1103 | t->parms.i_key = p->i_key; | ||
1104 | t->parms.o_key = p->o_key; | ||
1105 | t->parms.i_flags = p->i_flags; | ||
1106 | t->parms.o_flags = p->o_flags; | ||
1107 | ip6_tnl_dst_reset(t); | ||
1108 | ip6gre_tnl_link_config(t, set_mtu); | ||
1109 | return 0; | ||
1110 | } | ||
1111 | |||
1112 | static void ip6gre_tnl_parm_from_user(struct __ip6_tnl_parm *p, | ||
1113 | const struct ip6_tnl_parm2 *u) | ||
1114 | { | ||
1115 | p->laddr = u->laddr; | ||
1116 | p->raddr = u->raddr; | ||
1117 | p->flags = u->flags; | ||
1118 | p->hop_limit = u->hop_limit; | ||
1119 | p->encap_limit = u->encap_limit; | ||
1120 | p->flowinfo = u->flowinfo; | ||
1121 | p->link = u->link; | ||
1122 | p->i_key = u->i_key; | ||
1123 | p->o_key = u->o_key; | ||
1124 | p->i_flags = u->i_flags; | ||
1125 | p->o_flags = u->o_flags; | ||
1126 | memcpy(p->name, u->name, sizeof(u->name)); | ||
1127 | } | ||
1128 | |||
1129 | static void ip6gre_tnl_parm_to_user(struct ip6_tnl_parm2 *u, | ||
1130 | const struct __ip6_tnl_parm *p) | ||
1131 | { | ||
1132 | u->proto = IPPROTO_GRE; | ||
1133 | u->laddr = p->laddr; | ||
1134 | u->raddr = p->raddr; | ||
1135 | u->flags = p->flags; | ||
1136 | u->hop_limit = p->hop_limit; | ||
1137 | u->encap_limit = p->encap_limit; | ||
1138 | u->flowinfo = p->flowinfo; | ||
1139 | u->link = p->link; | ||
1140 | u->i_key = p->i_key; | ||
1141 | u->o_key = p->o_key; | ||
1142 | u->i_flags = p->i_flags; | ||
1143 | u->o_flags = p->o_flags; | ||
1144 | memcpy(u->name, p->name, sizeof(u->name)); | ||
1145 | } | ||
1146 | |||
1147 | static int ip6gre_tunnel_ioctl(struct net_device *dev, | ||
1148 | struct ifreq *ifr, int cmd) | ||
1149 | { | ||
1150 | int err = 0; | ||
1151 | struct ip6_tnl_parm2 p; | ||
1152 | struct __ip6_tnl_parm p1; | ||
1153 | struct ip6_tnl *t; | ||
1154 | struct net *net = dev_net(dev); | ||
1155 | struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); | ||
1156 | |||
1157 | switch (cmd) { | ||
1158 | case SIOCGETTUNNEL: | ||
1159 | t = NULL; | ||
1160 | if (dev == ign->fb_tunnel_dev) { | ||
1161 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) { | ||
1162 | err = -EFAULT; | ||
1163 | break; | ||
1164 | } | ||
1165 | ip6gre_tnl_parm_from_user(&p1, &p); | ||
1166 | t = ip6gre_tunnel_locate(net, &p1, 0); | ||
1167 | } | ||
1168 | if (t == NULL) | ||
1169 | t = netdev_priv(dev); | ||
1170 | ip6gre_tnl_parm_to_user(&p, &t->parms); | ||
1171 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) | ||
1172 | err = -EFAULT; | ||
1173 | break; | ||
1174 | |||
1175 | case SIOCADDTUNNEL: | ||
1176 | case SIOCCHGTUNNEL: | ||
1177 | err = -EPERM; | ||
1178 | if (!capable(CAP_NET_ADMIN)) | ||
1179 | goto done; | ||
1180 | |||
1181 | err = -EFAULT; | ||
1182 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) | ||
1183 | goto done; | ||
1184 | |||
1185 | err = -EINVAL; | ||
1186 | if ((p.i_flags|p.o_flags)&(GRE_VERSION|GRE_ROUTING)) | ||
1187 | goto done; | ||
1188 | |||
1189 | if (!(p.i_flags&GRE_KEY)) | ||
1190 | p.i_key = 0; | ||
1191 | if (!(p.o_flags&GRE_KEY)) | ||
1192 | p.o_key = 0; | ||
1193 | |||
1194 | ip6gre_tnl_parm_from_user(&p1, &p); | ||
1195 | t = ip6gre_tunnel_locate(net, &p1, cmd == SIOCADDTUNNEL); | ||
1196 | |||
1197 | if (dev != ign->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { | ||
1198 | if (t != NULL) { | ||
1199 | if (t->dev != dev) { | ||
1200 | err = -EEXIST; | ||
1201 | break; | ||
1202 | } | ||
1203 | } else { | ||
1204 | t = netdev_priv(dev); | ||
1205 | |||
1206 | ip6gre_tunnel_unlink(ign, t); | ||
1207 | synchronize_net(); | ||
1208 | ip6gre_tnl_change(t, &p1, 1); | ||
1209 | ip6gre_tunnel_link(ign, t); | ||
1210 | netdev_state_change(dev); | ||
1211 | } | ||
1212 | } | ||
1213 | |||
1214 | if (t) { | ||
1215 | err = 0; | ||
1216 | |||
1217 | ip6gre_tnl_parm_to_user(&p, &t->parms); | ||
1218 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) | ||
1219 | err = -EFAULT; | ||
1220 | } else | ||
1221 | err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT); | ||
1222 | break; | ||
1223 | |||
1224 | case SIOCDELTUNNEL: | ||
1225 | err = -EPERM; | ||
1226 | if (!capable(CAP_NET_ADMIN)) | ||
1227 | goto done; | ||
1228 | |||
1229 | if (dev == ign->fb_tunnel_dev) { | ||
1230 | err = -EFAULT; | ||
1231 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof(p))) | ||
1232 | goto done; | ||
1233 | err = -ENOENT; | ||
1234 | ip6gre_tnl_parm_from_user(&p1, &p); | ||
1235 | t = ip6gre_tunnel_locate(net, &p1, 0); | ||
1236 | if (t == NULL) | ||
1237 | goto done; | ||
1238 | err = -EPERM; | ||
1239 | if (t == netdev_priv(ign->fb_tunnel_dev)) | ||
1240 | goto done; | ||
1241 | dev = t->dev; | ||
1242 | } | ||
1243 | unregister_netdevice(dev); | ||
1244 | err = 0; | ||
1245 | break; | ||
1246 | |||
1247 | default: | ||
1248 | err = -EINVAL; | ||
1249 | } | ||
1250 | |||
1251 | done: | ||
1252 | return err; | ||
1253 | } | ||
1254 | |||
1255 | static int ip6gre_tunnel_change_mtu(struct net_device *dev, int new_mtu) | ||
1256 | { | ||
1257 | struct ip6_tnl *tunnel = netdev_priv(dev); | ||
1258 | if (new_mtu < 68 || | ||
1259 | new_mtu > 0xFFF8 - dev->hard_header_len - tunnel->hlen) | ||
1260 | return -EINVAL; | ||
1261 | dev->mtu = new_mtu; | ||
1262 | return 0; | ||
1263 | } | ||
1264 | |||
1265 | static int ip6gre_header(struct sk_buff *skb, struct net_device *dev, | ||
1266 | unsigned short type, | ||
1267 | const void *daddr, const void *saddr, unsigned int len) | ||
1268 | { | ||
1269 | struct ip6_tnl *t = netdev_priv(dev); | ||
1270 | struct ipv6hdr *ipv6h = (struct ipv6hdr *)skb_push(skb, t->hlen); | ||
1271 | __be16 *p = (__be16 *)(ipv6h+1); | ||
1272 | |||
1273 | *(__be32 *)ipv6h = t->fl.u.ip6.flowlabel | htonl(0x60000000); | ||
1274 | ipv6h->hop_limit = t->parms.hop_limit; | ||
1275 | ipv6h->nexthdr = NEXTHDR_GRE; | ||
1276 | ipv6h->saddr = t->parms.laddr; | ||
1277 | ipv6h->daddr = t->parms.raddr; | ||
1278 | |||
1279 | p[0] = t->parms.o_flags; | ||
1280 | p[1] = htons(type); | ||
1281 | |||
1282 | /* | ||
1283 | * Set the source hardware address. | ||
1284 | */ | ||
1285 | |||
1286 | if (saddr) | ||
1287 | memcpy(&ipv6h->saddr, saddr, sizeof(struct in6_addr)); | ||
1288 | if (daddr) | ||
1289 | memcpy(&ipv6h->daddr, daddr, sizeof(struct in6_addr)); | ||
1290 | if (!ipv6_addr_any(&ipv6h->daddr)) | ||
1291 | return t->hlen; | ||
1292 | |||
1293 | return -t->hlen; | ||
1294 | } | ||
1295 | |||
1296 | static int ip6gre_header_parse(const struct sk_buff *skb, unsigned char *haddr) | ||
1297 | { | ||
1298 | const struct ipv6hdr *ipv6h = (const struct ipv6hdr *)skb_mac_header(skb); | ||
1299 | memcpy(haddr, &ipv6h->saddr, sizeof(struct in6_addr)); | ||
1300 | return sizeof(struct in6_addr); | ||
1301 | } | ||
1302 | |||
1303 | static const struct header_ops ip6gre_header_ops = { | ||
1304 | .create = ip6gre_header, | ||
1305 | .parse = ip6gre_header_parse, | ||
1306 | }; | ||
1307 | |||
1308 | static const struct net_device_ops ip6gre_netdev_ops = { | ||
1309 | .ndo_init = ip6gre_tunnel_init, | ||
1310 | .ndo_uninit = ip6gre_tunnel_uninit, | ||
1311 | .ndo_start_xmit = ip6gre_tunnel_xmit, | ||
1312 | .ndo_do_ioctl = ip6gre_tunnel_ioctl, | ||
1313 | .ndo_change_mtu = ip6gre_tunnel_change_mtu, | ||
1314 | .ndo_get_stats64 = ip6gre_get_stats64, | ||
1315 | }; | ||
1316 | |||
1317 | static void ip6gre_dev_free(struct net_device *dev) | ||
1318 | { | ||
1319 | free_percpu(dev->tstats); | ||
1320 | free_netdev(dev); | ||
1321 | } | ||
1322 | |||
1323 | static void ip6gre_tunnel_setup(struct net_device *dev) | ||
1324 | { | ||
1325 | struct ip6_tnl *t; | ||
1326 | |||
1327 | dev->netdev_ops = &ip6gre_netdev_ops; | ||
1328 | dev->destructor = ip6gre_dev_free; | ||
1329 | |||
1330 | dev->type = ARPHRD_IP6GRE; | ||
1331 | dev->hard_header_len = LL_MAX_HEADER + sizeof(struct ipv6hdr) + 4; | ||
1332 | dev->mtu = ETH_DATA_LEN - sizeof(struct ipv6hdr) - 4; | ||
1333 | t = netdev_priv(dev); | ||
1334 | if (!(t->parms.flags & IP6_TNL_F_IGN_ENCAP_LIMIT)) | ||
1335 | dev->mtu -= 8; | ||
1336 | dev->flags |= IFF_NOARP; | ||
1337 | dev->iflink = 0; | ||
1338 | dev->addr_len = sizeof(struct in6_addr); | ||
1339 | dev->features |= NETIF_F_NETNS_LOCAL; | ||
1340 | dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; | ||
1341 | } | ||
1342 | |||
1343 | static int ip6gre_tunnel_init(struct net_device *dev) | ||
1344 | { | ||
1345 | struct ip6_tnl *tunnel; | ||
1346 | |||
1347 | tunnel = netdev_priv(dev); | ||
1348 | |||
1349 | tunnel->dev = dev; | ||
1350 | strcpy(tunnel->parms.name, dev->name); | ||
1351 | |||
1352 | memcpy(dev->dev_addr, &tunnel->parms.laddr, sizeof(struct in6_addr)); | ||
1353 | memcpy(dev->broadcast, &tunnel->parms.raddr, sizeof(struct in6_addr)); | ||
1354 | |||
1355 | if (ipv6_addr_any(&tunnel->parms.raddr)) | ||
1356 | dev->header_ops = &ip6gre_header_ops; | ||
1357 | |||
1358 | dev->tstats = alloc_percpu(struct pcpu_tstats); | ||
1359 | if (!dev->tstats) | ||
1360 | return -ENOMEM; | ||
1361 | |||
1362 | return 0; | ||
1363 | } | ||
1364 | |||
1365 | static void ip6gre_fb_tunnel_init(struct net_device *dev) | ||
1366 | { | ||
1367 | struct ip6_tnl *tunnel = netdev_priv(dev); | ||
1368 | |||
1369 | tunnel->dev = dev; | ||
1370 | strcpy(tunnel->parms.name, dev->name); | ||
1371 | |||
1372 | tunnel->hlen = sizeof(struct ipv6hdr) + 4; | ||
1373 | |||
1374 | dev_hold(dev); | ||
1375 | } | ||
1376 | |||
1377 | |||
1378 | static struct inet6_protocol ip6gre_protocol __read_mostly = { | ||
1379 | .handler = ip6gre_rcv, | ||
1380 | .err_handler = ip6gre_err, | ||
1381 | .flags = INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL, | ||
1382 | }; | ||
1383 | |||
1384 | static void ip6gre_destroy_tunnels(struct ip6gre_net *ign, | ||
1385 | struct list_head *head) | ||
1386 | { | ||
1387 | int prio; | ||
1388 | |||
1389 | for (prio = 0; prio < 4; prio++) { | ||
1390 | int h; | ||
1391 | for (h = 0; h < HASH_SIZE; h++) { | ||
1392 | struct ip6_tnl *t; | ||
1393 | |||
1394 | t = rtnl_dereference(ign->tunnels[prio][h]); | ||
1395 | |||
1396 | while (t != NULL) { | ||
1397 | unregister_netdevice_queue(t->dev, head); | ||
1398 | t = rtnl_dereference(t->next); | ||
1399 | } | ||
1400 | } | ||
1401 | } | ||
1402 | } | ||
1403 | |||
1404 | static int __net_init ip6gre_init_net(struct net *net) | ||
1405 | { | ||
1406 | struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); | ||
1407 | int err; | ||
1408 | |||
1409 | ign->fb_tunnel_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6gre0", | ||
1410 | ip6gre_tunnel_setup); | ||
1411 | if (!ign->fb_tunnel_dev) { | ||
1412 | err = -ENOMEM; | ||
1413 | goto err_alloc_dev; | ||
1414 | } | ||
1415 | dev_net_set(ign->fb_tunnel_dev, net); | ||
1416 | |||
1417 | ip6gre_fb_tunnel_init(ign->fb_tunnel_dev); | ||
1418 | ign->fb_tunnel_dev->rtnl_link_ops = &ip6gre_link_ops; | ||
1419 | |||
1420 | err = register_netdev(ign->fb_tunnel_dev); | ||
1421 | if (err) | ||
1422 | goto err_reg_dev; | ||
1423 | |||
1424 | rcu_assign_pointer(ign->tunnels_wc[0], | ||
1425 | netdev_priv(ign->fb_tunnel_dev)); | ||
1426 | return 0; | ||
1427 | |||
1428 | err_reg_dev: | ||
1429 | ip6gre_dev_free(ign->fb_tunnel_dev); | ||
1430 | err_alloc_dev: | ||
1431 | return err; | ||
1432 | } | ||
1433 | |||
1434 | static void __net_exit ip6gre_exit_net(struct net *net) | ||
1435 | { | ||
1436 | struct ip6gre_net *ign; | ||
1437 | LIST_HEAD(list); | ||
1438 | |||
1439 | ign = net_generic(net, ip6gre_net_id); | ||
1440 | rtnl_lock(); | ||
1441 | ip6gre_destroy_tunnels(ign, &list); | ||
1442 | unregister_netdevice_many(&list); | ||
1443 | rtnl_unlock(); | ||
1444 | } | ||
1445 | |||
1446 | static struct pernet_operations ip6gre_net_ops = { | ||
1447 | .init = ip6gre_init_net, | ||
1448 | .exit = ip6gre_exit_net, | ||
1449 | .id = &ip6gre_net_id, | ||
1450 | .size = sizeof(struct ip6gre_net), | ||
1451 | }; | ||
1452 | |||
1453 | static int ip6gre_tunnel_validate(struct nlattr *tb[], struct nlattr *data[]) | ||
1454 | { | ||
1455 | __be16 flags; | ||
1456 | |||
1457 | if (!data) | ||
1458 | return 0; | ||
1459 | |||
1460 | flags = 0; | ||
1461 | if (data[IFLA_GRE_IFLAGS]) | ||
1462 | flags |= nla_get_be16(data[IFLA_GRE_IFLAGS]); | ||
1463 | if (data[IFLA_GRE_OFLAGS]) | ||
1464 | flags |= nla_get_be16(data[IFLA_GRE_OFLAGS]); | ||
1465 | if (flags & (GRE_VERSION|GRE_ROUTING)) | ||
1466 | return -EINVAL; | ||
1467 | |||
1468 | return 0; | ||
1469 | } | ||
1470 | |||
1471 | static int ip6gre_tap_validate(struct nlattr *tb[], struct nlattr *data[]) | ||
1472 | { | ||
1473 | struct in6_addr daddr; | ||
1474 | |||
1475 | if (tb[IFLA_ADDRESS]) { | ||
1476 | if (nla_len(tb[IFLA_ADDRESS]) != ETH_ALEN) | ||
1477 | return -EINVAL; | ||
1478 | if (!is_valid_ether_addr(nla_data(tb[IFLA_ADDRESS]))) | ||
1479 | return -EADDRNOTAVAIL; | ||
1480 | } | ||
1481 | |||
1482 | if (!data) | ||
1483 | goto out; | ||
1484 | |||
1485 | if (data[IFLA_GRE_REMOTE]) { | ||
1486 | nla_memcpy(&daddr, data[IFLA_GRE_REMOTE], sizeof(struct in6_addr)); | ||
1487 | if (ipv6_addr_any(&daddr)) | ||
1488 | return -EINVAL; | ||
1489 | } | ||
1490 | |||
1491 | out: | ||
1492 | return ip6gre_tunnel_validate(tb, data); | ||
1493 | } | ||
1494 | |||
1495 | |||
1496 | static void ip6gre_netlink_parms(struct nlattr *data[], | ||
1497 | struct __ip6_tnl_parm *parms) | ||
1498 | { | ||
1499 | memset(parms, 0, sizeof(*parms)); | ||
1500 | |||
1501 | if (!data) | ||
1502 | return; | ||
1503 | |||
1504 | if (data[IFLA_GRE_LINK]) | ||
1505 | parms->link = nla_get_u32(data[IFLA_GRE_LINK]); | ||
1506 | |||
1507 | if (data[IFLA_GRE_IFLAGS]) | ||
1508 | parms->i_flags = nla_get_be16(data[IFLA_GRE_IFLAGS]); | ||
1509 | |||
1510 | if (data[IFLA_GRE_OFLAGS]) | ||
1511 | parms->o_flags = nla_get_be16(data[IFLA_GRE_OFLAGS]); | ||
1512 | |||
1513 | if (data[IFLA_GRE_IKEY]) | ||
1514 | parms->i_key = nla_get_be32(data[IFLA_GRE_IKEY]); | ||
1515 | |||
1516 | if (data[IFLA_GRE_OKEY]) | ||
1517 | parms->o_key = nla_get_be32(data[IFLA_GRE_OKEY]); | ||
1518 | |||
1519 | if (data[IFLA_GRE_LOCAL]) | ||
1520 | nla_memcpy(&parms->laddr, data[IFLA_GRE_LOCAL], sizeof(struct in6_addr)); | ||
1521 | |||
1522 | if (data[IFLA_GRE_REMOTE]) | ||
1523 | nla_memcpy(&parms->raddr, data[IFLA_GRE_REMOTE], sizeof(struct in6_addr)); | ||
1524 | |||
1525 | if (data[IFLA_GRE_TTL]) | ||
1526 | parms->hop_limit = nla_get_u8(data[IFLA_GRE_TTL]); | ||
1527 | |||
1528 | if (data[IFLA_GRE_ENCAP_LIMIT]) | ||
1529 | parms->encap_limit = nla_get_u8(data[IFLA_GRE_ENCAP_LIMIT]); | ||
1530 | |||
1531 | if (data[IFLA_GRE_FLOWINFO]) | ||
1532 | parms->flowinfo = nla_get_u32(data[IFLA_GRE_FLOWINFO]); | ||
1533 | |||
1534 | if (data[IFLA_GRE_FLAGS]) | ||
1535 | parms->flags = nla_get_u32(data[IFLA_GRE_FLAGS]); | ||
1536 | } | ||
1537 | |||
1538 | static int ip6gre_tap_init(struct net_device *dev) | ||
1539 | { | ||
1540 | struct ip6_tnl *tunnel; | ||
1541 | |||
1542 | tunnel = netdev_priv(dev); | ||
1543 | |||
1544 | tunnel->dev = dev; | ||
1545 | strcpy(tunnel->parms.name, dev->name); | ||
1546 | |||
1547 | ip6gre_tnl_link_config(tunnel, 1); | ||
1548 | |||
1549 | dev->tstats = alloc_percpu(struct pcpu_tstats); | ||
1550 | if (!dev->tstats) | ||
1551 | return -ENOMEM; | ||
1552 | |||
1553 | return 0; | ||
1554 | } | ||
1555 | |||
1556 | static const struct net_device_ops ip6gre_tap_netdev_ops = { | ||
1557 | .ndo_init = ip6gre_tap_init, | ||
1558 | .ndo_uninit = ip6gre_tunnel_uninit, | ||
1559 | .ndo_start_xmit = ip6gre_tunnel_xmit, | ||
1560 | .ndo_set_mac_address = eth_mac_addr, | ||
1561 | .ndo_validate_addr = eth_validate_addr, | ||
1562 | .ndo_change_mtu = ip6gre_tunnel_change_mtu, | ||
1563 | .ndo_get_stats64 = ip6gre_get_stats64, | ||
1564 | }; | ||
1565 | |||
1566 | static void ip6gre_tap_setup(struct net_device *dev) | ||
1567 | { | ||
1568 | |||
1569 | ether_setup(dev); | ||
1570 | |||
1571 | dev->netdev_ops = &ip6gre_tap_netdev_ops; | ||
1572 | dev->destructor = ip6gre_dev_free; | ||
1573 | |||
1574 | dev->iflink = 0; | ||
1575 | dev->features |= NETIF_F_NETNS_LOCAL; | ||
1576 | } | ||
1577 | |||
1578 | static int ip6gre_newlink(struct net *src_net, struct net_device *dev, | ||
1579 | struct nlattr *tb[], struct nlattr *data[]) | ||
1580 | { | ||
1581 | struct ip6_tnl *nt; | ||
1582 | struct net *net = dev_net(dev); | ||
1583 | struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); | ||
1584 | int err; | ||
1585 | |||
1586 | nt = netdev_priv(dev); | ||
1587 | ip6gre_netlink_parms(data, &nt->parms); | ||
1588 | |||
1589 | if (ip6gre_tunnel_find(net, &nt->parms, dev->type)) | ||
1590 | return -EEXIST; | ||
1591 | |||
1592 | if (dev->type == ARPHRD_ETHER && !tb[IFLA_ADDRESS]) | ||
1593 | eth_hw_addr_random(dev); | ||
1594 | |||
1595 | nt->dev = dev; | ||
1596 | ip6gre_tnl_link_config(nt, !tb[IFLA_MTU]); | ||
1597 | |||
1598 | /* Can use a lockless transmit, unless we generate output sequences */ | ||
1599 | if (!(nt->parms.o_flags & GRE_SEQ)) | ||
1600 | dev->features |= NETIF_F_LLTX; | ||
1601 | |||
1602 | err = register_netdevice(dev); | ||
1603 | if (err) | ||
1604 | goto out; | ||
1605 | |||
1606 | dev_hold(dev); | ||
1607 | ip6gre_tunnel_link(ign, nt); | ||
1608 | |||
1609 | out: | ||
1610 | return err; | ||
1611 | } | ||
1612 | |||
1613 | static int ip6gre_changelink(struct net_device *dev, struct nlattr *tb[], | ||
1614 | struct nlattr *data[]) | ||
1615 | { | ||
1616 | struct ip6_tnl *t, *nt; | ||
1617 | struct net *net = dev_net(dev); | ||
1618 | struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); | ||
1619 | struct __ip6_tnl_parm p; | ||
1620 | |||
1621 | if (dev == ign->fb_tunnel_dev) | ||
1622 | return -EINVAL; | ||
1623 | |||
1624 | nt = netdev_priv(dev); | ||
1625 | ip6gre_netlink_parms(data, &p); | ||
1626 | |||
1627 | t = ip6gre_tunnel_locate(net, &p, 0); | ||
1628 | |||
1629 | if (t) { | ||
1630 | if (t->dev != dev) | ||
1631 | return -EEXIST; | ||
1632 | } else { | ||
1633 | t = nt; | ||
1634 | |||
1635 | ip6gre_tunnel_unlink(ign, t); | ||
1636 | ip6gre_tnl_change(t, &p, !tb[IFLA_MTU]); | ||
1637 | ip6gre_tunnel_link(ign, t); | ||
1638 | netdev_state_change(dev); | ||
1639 | } | ||
1640 | |||
1641 | return 0; | ||
1642 | } | ||
1643 | |||
1644 | static size_t ip6gre_get_size(const struct net_device *dev) | ||
1645 | { | ||
1646 | return | ||
1647 | /* IFLA_GRE_LINK */ | ||
1648 | nla_total_size(4) + | ||
1649 | /* IFLA_GRE_IFLAGS */ | ||
1650 | nla_total_size(2) + | ||
1651 | /* IFLA_GRE_OFLAGS */ | ||
1652 | nla_total_size(2) + | ||
1653 | /* IFLA_GRE_IKEY */ | ||
1654 | nla_total_size(4) + | ||
1655 | /* IFLA_GRE_OKEY */ | ||
1656 | nla_total_size(4) + | ||
1657 | /* IFLA_GRE_LOCAL */ | ||
1658 | nla_total_size(4) + | ||
1659 | /* IFLA_GRE_REMOTE */ | ||
1660 | nla_total_size(4) + | ||
1661 | /* IFLA_GRE_TTL */ | ||
1662 | nla_total_size(1) + | ||
1663 | /* IFLA_GRE_TOS */ | ||
1664 | nla_total_size(1) + | ||
1665 | /* IFLA_GRE_ENCAP_LIMIT */ | ||
1666 | nla_total_size(1) + | ||
1667 | /* IFLA_GRE_FLOWINFO */ | ||
1668 | nla_total_size(4) + | ||
1669 | /* IFLA_GRE_FLAGS */ | ||
1670 | nla_total_size(4) + | ||
1671 | 0; | ||
1672 | } | ||
1673 | |||
1674 | static int ip6gre_fill_info(struct sk_buff *skb, const struct net_device *dev) | ||
1675 | { | ||
1676 | struct ip6_tnl *t = netdev_priv(dev); | ||
1677 | struct __ip6_tnl_parm *p = &t->parms; | ||
1678 | |||
1679 | if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) || | ||
1680 | nla_put_be16(skb, IFLA_GRE_IFLAGS, p->i_flags) || | ||
1681 | nla_put_be16(skb, IFLA_GRE_OFLAGS, p->o_flags) || | ||
1682 | nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) || | ||
1683 | nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) || | ||
1684 | nla_put(skb, IFLA_GRE_LOCAL, sizeof(struct in6_addr), &p->raddr) || | ||
1685 | nla_put(skb, IFLA_GRE_REMOTE, sizeof(struct in6_addr), &p->laddr) || | ||
1686 | nla_put_u8(skb, IFLA_GRE_TTL, p->hop_limit) || | ||
1687 | /*nla_put_u8(skb, IFLA_GRE_TOS, t->priority) ||*/ | ||
1688 | nla_put_u8(skb, IFLA_GRE_ENCAP_LIMIT, p->encap_limit) || | ||
1689 | nla_put_be32(skb, IFLA_GRE_FLOWINFO, p->flowinfo) || | ||
1690 | nla_put_u32(skb, IFLA_GRE_FLAGS, p->flags)) | ||
1691 | goto nla_put_failure; | ||
1692 | return 0; | ||
1693 | |||
1694 | nla_put_failure: | ||
1695 | return -EMSGSIZE; | ||
1696 | } | ||
1697 | |||
1698 | static const struct nla_policy ip6gre_policy[IFLA_GRE_MAX + 1] = { | ||
1699 | [IFLA_GRE_LINK] = { .type = NLA_U32 }, | ||
1700 | [IFLA_GRE_IFLAGS] = { .type = NLA_U16 }, | ||
1701 | [IFLA_GRE_OFLAGS] = { .type = NLA_U16 }, | ||
1702 | [IFLA_GRE_IKEY] = { .type = NLA_U32 }, | ||
1703 | [IFLA_GRE_OKEY] = { .type = NLA_U32 }, | ||
1704 | [IFLA_GRE_LOCAL] = { .len = FIELD_SIZEOF(struct ipv6hdr, saddr) }, | ||
1705 | [IFLA_GRE_REMOTE] = { .len = FIELD_SIZEOF(struct ipv6hdr, daddr) }, | ||
1706 | [IFLA_GRE_TTL] = { .type = NLA_U8 }, | ||
1707 | [IFLA_GRE_ENCAP_LIMIT] = { .type = NLA_U8 }, | ||
1708 | [IFLA_GRE_FLOWINFO] = { .type = NLA_U32 }, | ||
1709 | [IFLA_GRE_FLAGS] = { .type = NLA_U32 }, | ||
1710 | }; | ||
1711 | |||
1712 | static struct rtnl_link_ops ip6gre_link_ops __read_mostly = { | ||
1713 | .kind = "ip6gre", | ||
1714 | .maxtype = IFLA_GRE_MAX, | ||
1715 | .policy = ip6gre_policy, | ||
1716 | .priv_size = sizeof(struct ip6_tnl), | ||
1717 | .setup = ip6gre_tunnel_setup, | ||
1718 | .validate = ip6gre_tunnel_validate, | ||
1719 | .newlink = ip6gre_newlink, | ||
1720 | .changelink = ip6gre_changelink, | ||
1721 | .get_size = ip6gre_get_size, | ||
1722 | .fill_info = ip6gre_fill_info, | ||
1723 | }; | ||
1724 | |||
1725 | static struct rtnl_link_ops ip6gre_tap_ops __read_mostly = { | ||
1726 | .kind = "ip6gretap", | ||
1727 | .maxtype = IFLA_GRE_MAX, | ||
1728 | .policy = ip6gre_policy, | ||
1729 | .priv_size = sizeof(struct ip6_tnl), | ||
1730 | .setup = ip6gre_tap_setup, | ||
1731 | .validate = ip6gre_tap_validate, | ||
1732 | .newlink = ip6gre_newlink, | ||
1733 | .changelink = ip6gre_changelink, | ||
1734 | .get_size = ip6gre_get_size, | ||
1735 | .fill_info = ip6gre_fill_info, | ||
1736 | }; | ||
1737 | |||
1738 | /* | ||
1739 | * And now the modules code and kernel interface. | ||
1740 | */ | ||
1741 | |||
1742 | static int __init ip6gre_init(void) | ||
1743 | { | ||
1744 | int err; | ||
1745 | |||
1746 | pr_info("GRE over IPv6 tunneling driver\n"); | ||
1747 | |||
1748 | err = register_pernet_device(&ip6gre_net_ops); | ||
1749 | if (err < 0) | ||
1750 | return err; | ||
1751 | |||
1752 | err = inet6_add_protocol(&ip6gre_protocol, IPPROTO_GRE); | ||
1753 | if (err < 0) { | ||
1754 | pr_info("%s: can't add protocol\n", __func__); | ||
1755 | goto add_proto_failed; | ||
1756 | } | ||
1757 | |||
1758 | err = rtnl_link_register(&ip6gre_link_ops); | ||
1759 | if (err < 0) | ||
1760 | goto rtnl_link_failed; | ||
1761 | |||
1762 | err = rtnl_link_register(&ip6gre_tap_ops); | ||
1763 | if (err < 0) | ||
1764 | goto tap_ops_failed; | ||
1765 | |||
1766 | out: | ||
1767 | return err; | ||
1768 | |||
1769 | tap_ops_failed: | ||
1770 | rtnl_link_unregister(&ip6gre_link_ops); | ||
1771 | rtnl_link_failed: | ||
1772 | inet6_del_protocol(&ip6gre_protocol, IPPROTO_GRE); | ||
1773 | add_proto_failed: | ||
1774 | unregister_pernet_device(&ip6gre_net_ops); | ||
1775 | goto out; | ||
1776 | } | ||
1777 | |||
1778 | static void __exit ip6gre_fini(void) | ||
1779 | { | ||
1780 | rtnl_link_unregister(&ip6gre_tap_ops); | ||
1781 | rtnl_link_unregister(&ip6gre_link_ops); | ||
1782 | inet6_del_protocol(&ip6gre_protocol, IPPROTO_GRE); | ||
1783 | unregister_pernet_device(&ip6gre_net_ops); | ||
1784 | } | ||
1785 | |||
1786 | module_init(ip6gre_init); | ||
1787 | module_exit(ip6gre_fini); | ||
1788 | MODULE_LICENSE("GPL"); | ||
1789 | MODULE_AUTHOR("D. Kozlov (xeb@mail.ru)"); | ||
1790 | MODULE_DESCRIPTION("GRE over IPv6 tunneling device"); | ||
1791 | MODULE_ALIAS_RTNL_LINK("ip6gre"); | ||
1792 | MODULE_ALIAS_NETDEV("ip6gre0"); | ||
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 5b2d63ed793e..a4f6263fddca 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -493,7 +493,8 @@ int ip6_forward(struct sk_buff *skb) | |||
493 | if (mtu < IPV6_MIN_MTU) | 493 | if (mtu < IPV6_MIN_MTU) |
494 | mtu = IPV6_MIN_MTU; | 494 | mtu = IPV6_MIN_MTU; |
495 | 495 | ||
496 | if (skb->len > mtu && !skb_is_gso(skb)) { | 496 | if ((!skb->local_df && skb->len > mtu && !skb_is_gso(skb)) || |
497 | (IP6CB(skb)->frag_max_size && IP6CB(skb)->frag_max_size > mtu)) { | ||
497 | /* Again, force OUTPUT device used as source address */ | 498 | /* Again, force OUTPUT device used as source address */ |
498 | skb->dev = dst->dev; | 499 | skb->dev = dst->dev; |
499 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); | 500 | icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); |
@@ -636,7 +637,9 @@ int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
636 | /* We must not fragment if the socket is set to force MTU discovery | 637 | /* We must not fragment if the socket is set to force MTU discovery |
637 | * or if the skb it not generated by a local socket. | 638 | * or if the skb it not generated by a local socket. |
638 | */ | 639 | */ |
639 | if (unlikely(!skb->local_df && skb->len > mtu)) { | 640 | if (unlikely(!skb->local_df && skb->len > mtu) || |
641 | (IP6CB(skb)->frag_max_size && | ||
642 | IP6CB(skb)->frag_max_size > mtu)) { | ||
640 | if (skb->sk && dst_allfrag(skb_dst(skb))) | 643 | if (skb->sk && dst_allfrag(skb_dst(skb))) |
641 | sk_nocaps_add(skb->sk, NETIF_F_GSO_MASK); | 644 | sk_nocaps_add(skb->sk, NETIF_F_GSO_MASK); |
642 | 645 | ||
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 9a1d5fe6aef8..cb7e2ded6f08 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -126,7 +126,7 @@ static struct net_device_stats *ip6_get_stats(struct net_device *dev) | |||
126 | * Locking : hash tables are protected by RCU and RTNL | 126 | * Locking : hash tables are protected by RCU and RTNL |
127 | */ | 127 | */ |
128 | 128 | ||
129 | static inline struct dst_entry *ip6_tnl_dst_check(struct ip6_tnl *t) | 129 | struct dst_entry *ip6_tnl_dst_check(struct ip6_tnl *t) |
130 | { | 130 | { |
131 | struct dst_entry *dst = t->dst_cache; | 131 | struct dst_entry *dst = t->dst_cache; |
132 | 132 | ||
@@ -139,20 +139,23 @@ static inline struct dst_entry *ip6_tnl_dst_check(struct ip6_tnl *t) | |||
139 | 139 | ||
140 | return dst; | 140 | return dst; |
141 | } | 141 | } |
142 | EXPORT_SYMBOL_GPL(ip6_tnl_dst_check); | ||
142 | 143 | ||
143 | static inline void ip6_tnl_dst_reset(struct ip6_tnl *t) | 144 | void ip6_tnl_dst_reset(struct ip6_tnl *t) |
144 | { | 145 | { |
145 | dst_release(t->dst_cache); | 146 | dst_release(t->dst_cache); |
146 | t->dst_cache = NULL; | 147 | t->dst_cache = NULL; |
147 | } | 148 | } |
149 | EXPORT_SYMBOL_GPL(ip6_tnl_dst_reset); | ||
148 | 150 | ||
149 | static inline void ip6_tnl_dst_store(struct ip6_tnl *t, struct dst_entry *dst) | 151 | void ip6_tnl_dst_store(struct ip6_tnl *t, struct dst_entry *dst) |
150 | { | 152 | { |
151 | struct rt6_info *rt = (struct rt6_info *) dst; | 153 | struct rt6_info *rt = (struct rt6_info *) dst; |
152 | t->dst_cookie = rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0; | 154 | t->dst_cookie = rt->rt6i_node ? rt->rt6i_node->fn_sernum : 0; |
153 | dst_release(t->dst_cache); | 155 | dst_release(t->dst_cache); |
154 | t->dst_cache = dst; | 156 | t->dst_cache = dst; |
155 | } | 157 | } |
158 | EXPORT_SYMBOL_GPL(ip6_tnl_dst_store); | ||
156 | 159 | ||
157 | /** | 160 | /** |
158 | * ip6_tnl_lookup - fetch tunnel matching the end-point addresses | 161 | * ip6_tnl_lookup - fetch tunnel matching the end-point addresses |
@@ -200,7 +203,7 @@ ip6_tnl_lookup(struct net *net, const struct in6_addr *remote, const struct in6_ | |||
200 | **/ | 203 | **/ |
201 | 204 | ||
202 | static struct ip6_tnl __rcu ** | 205 | static struct ip6_tnl __rcu ** |
203 | ip6_tnl_bucket(struct ip6_tnl_net *ip6n, const struct ip6_tnl_parm *p) | 206 | ip6_tnl_bucket(struct ip6_tnl_net *ip6n, const struct __ip6_tnl_parm *p) |
204 | { | 207 | { |
205 | const struct in6_addr *remote = &p->raddr; | 208 | const struct in6_addr *remote = &p->raddr; |
206 | const struct in6_addr *local = &p->laddr; | 209 | const struct in6_addr *local = &p->laddr; |
@@ -267,7 +270,7 @@ static void ip6_dev_free(struct net_device *dev) | |||
267 | * created tunnel or NULL | 270 | * created tunnel or NULL |
268 | **/ | 271 | **/ |
269 | 272 | ||
270 | static struct ip6_tnl *ip6_tnl_create(struct net *net, struct ip6_tnl_parm *p) | 273 | static struct ip6_tnl *ip6_tnl_create(struct net *net, struct __ip6_tnl_parm *p) |
271 | { | 274 | { |
272 | struct net_device *dev; | 275 | struct net_device *dev; |
273 | struct ip6_tnl *t; | 276 | struct ip6_tnl *t; |
@@ -322,7 +325,7 @@ failed: | |||
322 | **/ | 325 | **/ |
323 | 326 | ||
324 | static struct ip6_tnl *ip6_tnl_locate(struct net *net, | 327 | static struct ip6_tnl *ip6_tnl_locate(struct net *net, |
325 | struct ip6_tnl_parm *p, int create) | 328 | struct __ip6_tnl_parm *p, int create) |
326 | { | 329 | { |
327 | const struct in6_addr *remote = &p->raddr; | 330 | const struct in6_addr *remote = &p->raddr; |
328 | const struct in6_addr *local = &p->laddr; | 331 | const struct in6_addr *local = &p->laddr; |
@@ -374,8 +377,7 @@ ip6_tnl_dev_uninit(struct net_device *dev) | |||
374 | * else index to encapsulation limit | 377 | * else index to encapsulation limit |
375 | **/ | 378 | **/ |
376 | 379 | ||
377 | static __u16 | 380 | __u16 ip6_tnl_parse_tlv_enc_lim(struct sk_buff *skb, __u8 *raw) |
378 | parse_tlv_tnl_enc_lim(struct sk_buff *skb, __u8 * raw) | ||
379 | { | 381 | { |
380 | const struct ipv6hdr *ipv6h = (const struct ipv6hdr *) raw; | 382 | const struct ipv6hdr *ipv6h = (const struct ipv6hdr *) raw; |
381 | __u8 nexthdr = ipv6h->nexthdr; | 383 | __u8 nexthdr = ipv6h->nexthdr; |
@@ -425,6 +427,7 @@ parse_tlv_tnl_enc_lim(struct sk_buff *skb, __u8 * raw) | |||
425 | } | 427 | } |
426 | return 0; | 428 | return 0; |
427 | } | 429 | } |
430 | EXPORT_SYMBOL(ip6_tnl_parse_tlv_enc_lim); | ||
428 | 431 | ||
429 | /** | 432 | /** |
430 | * ip6_tnl_err - tunnel error handler | 433 | * ip6_tnl_err - tunnel error handler |
@@ -480,7 +483,7 @@ ip6_tnl_err(struct sk_buff *skb, __u8 ipproto, struct inet6_skb_parm *opt, | |||
480 | case ICMPV6_PARAMPROB: | 483 | case ICMPV6_PARAMPROB: |
481 | teli = 0; | 484 | teli = 0; |
482 | if ((*code) == ICMPV6_HDR_FIELD) | 485 | if ((*code) == ICMPV6_HDR_FIELD) |
483 | teli = parse_tlv_tnl_enc_lim(skb, skb->data); | 486 | teli = ip6_tnl_parse_tlv_enc_lim(skb, skb->data); |
484 | 487 | ||
485 | if (teli && teli == *info - 2) { | 488 | if (teli && teli == *info - 2) { |
486 | tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->data[teli]; | 489 | tel = (struct ipv6_tlv_tnl_enc_lim *) &skb->data[teli]; |
@@ -693,11 +696,11 @@ static void ip6ip6_dscp_ecn_decapsulate(const struct ip6_tnl *t, | |||
693 | IP6_ECN_set_ce(ipv6_hdr(skb)); | 696 | IP6_ECN_set_ce(ipv6_hdr(skb)); |
694 | } | 697 | } |
695 | 698 | ||
696 | static __u32 ip6_tnl_get_cap(struct ip6_tnl *t, | 699 | __u32 ip6_tnl_get_cap(struct ip6_tnl *t, |
697 | const struct in6_addr *laddr, | 700 | const struct in6_addr *laddr, |
698 | const struct in6_addr *raddr) | 701 | const struct in6_addr *raddr) |
699 | { | 702 | { |
700 | struct ip6_tnl_parm *p = &t->parms; | 703 | struct __ip6_tnl_parm *p = &t->parms; |
701 | int ltype = ipv6_addr_type(laddr); | 704 | int ltype = ipv6_addr_type(laddr); |
702 | int rtype = ipv6_addr_type(raddr); | 705 | int rtype = ipv6_addr_type(raddr); |
703 | __u32 flags = 0; | 706 | __u32 flags = 0; |
@@ -715,13 +718,14 @@ static __u32 ip6_tnl_get_cap(struct ip6_tnl *t, | |||
715 | } | 718 | } |
716 | return flags; | 719 | return flags; |
717 | } | 720 | } |
721 | EXPORT_SYMBOL(ip6_tnl_get_cap); | ||
718 | 722 | ||
719 | /* called with rcu_read_lock() */ | 723 | /* called with rcu_read_lock() */ |
720 | static inline int ip6_tnl_rcv_ctl(struct ip6_tnl *t, | 724 | int ip6_tnl_rcv_ctl(struct ip6_tnl *t, |
721 | const struct in6_addr *laddr, | 725 | const struct in6_addr *laddr, |
722 | const struct in6_addr *raddr) | 726 | const struct in6_addr *raddr) |
723 | { | 727 | { |
724 | struct ip6_tnl_parm *p = &t->parms; | 728 | struct __ip6_tnl_parm *p = &t->parms; |
725 | int ret = 0; | 729 | int ret = 0; |
726 | struct net *net = dev_net(t->dev); | 730 | struct net *net = dev_net(t->dev); |
727 | 731 | ||
@@ -740,6 +744,7 @@ static inline int ip6_tnl_rcv_ctl(struct ip6_tnl *t, | |||
740 | } | 744 | } |
741 | return ret; | 745 | return ret; |
742 | } | 746 | } |
747 | EXPORT_SYMBOL_GPL(ip6_tnl_rcv_ctl); | ||
743 | 748 | ||
744 | /** | 749 | /** |
745 | * ip6_tnl_rcv - decapsulate IPv6 packet and retransmit it locally | 750 | * ip6_tnl_rcv - decapsulate IPv6 packet and retransmit it locally |
@@ -859,9 +864,9 @@ ip6_tnl_addr_conflict(const struct ip6_tnl *t, const struct ipv6hdr *hdr) | |||
859 | return ipv6_addr_equal(&t->parms.raddr, &hdr->saddr); | 864 | return ipv6_addr_equal(&t->parms.raddr, &hdr->saddr); |
860 | } | 865 | } |
861 | 866 | ||
862 | static inline int ip6_tnl_xmit_ctl(struct ip6_tnl *t) | 867 | int ip6_tnl_xmit_ctl(struct ip6_tnl *t) |
863 | { | 868 | { |
864 | struct ip6_tnl_parm *p = &t->parms; | 869 | struct __ip6_tnl_parm *p = &t->parms; |
865 | int ret = 0; | 870 | int ret = 0; |
866 | struct net *net = dev_net(t->dev); | 871 | struct net *net = dev_net(t->dev); |
867 | 872 | ||
@@ -885,6 +890,8 @@ static inline int ip6_tnl_xmit_ctl(struct ip6_tnl *t) | |||
885 | } | 890 | } |
886 | return ret; | 891 | return ret; |
887 | } | 892 | } |
893 | EXPORT_SYMBOL_GPL(ip6_tnl_xmit_ctl); | ||
894 | |||
888 | /** | 895 | /** |
889 | * ip6_tnl_xmit2 - encapsulate packet and send | 896 | * ip6_tnl_xmit2 - encapsulate packet and send |
890 | * @skb: the outgoing socket buffer | 897 | * @skb: the outgoing socket buffer |
@@ -1085,7 +1092,7 @@ ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | |||
1085 | !ip6_tnl_xmit_ctl(t) || ip6_tnl_addr_conflict(t, ipv6h)) | 1092 | !ip6_tnl_xmit_ctl(t) || ip6_tnl_addr_conflict(t, ipv6h)) |
1086 | return -1; | 1093 | return -1; |
1087 | 1094 | ||
1088 | offset = parse_tlv_tnl_enc_lim(skb, skb_network_header(skb)); | 1095 | offset = ip6_tnl_parse_tlv_enc_lim(skb, skb_network_header(skb)); |
1089 | if (offset > 0) { | 1096 | if (offset > 0) { |
1090 | struct ipv6_tlv_tnl_enc_lim *tel; | 1097 | struct ipv6_tlv_tnl_enc_lim *tel; |
1091 | tel = (struct ipv6_tlv_tnl_enc_lim *)&skb_network_header(skb)[offset]; | 1098 | tel = (struct ipv6_tlv_tnl_enc_lim *)&skb_network_header(skb)[offset]; |
@@ -1152,7 +1159,7 @@ tx_err: | |||
1152 | static void ip6_tnl_link_config(struct ip6_tnl *t) | 1159 | static void ip6_tnl_link_config(struct ip6_tnl *t) |
1153 | { | 1160 | { |
1154 | struct net_device *dev = t->dev; | 1161 | struct net_device *dev = t->dev; |
1155 | struct ip6_tnl_parm *p = &t->parms; | 1162 | struct __ip6_tnl_parm *p = &t->parms; |
1156 | struct flowi6 *fl6 = &t->fl.u.ip6; | 1163 | struct flowi6 *fl6 = &t->fl.u.ip6; |
1157 | 1164 | ||
1158 | memcpy(dev->dev_addr, &p->laddr, sizeof(struct in6_addr)); | 1165 | memcpy(dev->dev_addr, &p->laddr, sizeof(struct in6_addr)); |
@@ -1215,7 +1222,7 @@ static void ip6_tnl_link_config(struct ip6_tnl *t) | |||
1215 | **/ | 1222 | **/ |
1216 | 1223 | ||
1217 | static int | 1224 | static int |
1218 | ip6_tnl_change(struct ip6_tnl *t, struct ip6_tnl_parm *p) | 1225 | ip6_tnl_change(struct ip6_tnl *t, const struct __ip6_tnl_parm *p) |
1219 | { | 1226 | { |
1220 | t->parms.laddr = p->laddr; | 1227 | t->parms.laddr = p->laddr; |
1221 | t->parms.raddr = p->raddr; | 1228 | t->parms.raddr = p->raddr; |
@@ -1230,6 +1237,34 @@ ip6_tnl_change(struct ip6_tnl *t, struct ip6_tnl_parm *p) | |||
1230 | return 0; | 1237 | return 0; |
1231 | } | 1238 | } |
1232 | 1239 | ||
1240 | static void | ||
1241 | ip6_tnl_parm_from_user(struct __ip6_tnl_parm *p, const struct ip6_tnl_parm *u) | ||
1242 | { | ||
1243 | p->laddr = u->laddr; | ||
1244 | p->raddr = u->raddr; | ||
1245 | p->flags = u->flags; | ||
1246 | p->hop_limit = u->hop_limit; | ||
1247 | p->encap_limit = u->encap_limit; | ||
1248 | p->flowinfo = u->flowinfo; | ||
1249 | p->link = u->link; | ||
1250 | p->proto = u->proto; | ||
1251 | memcpy(p->name, u->name, sizeof(u->name)); | ||
1252 | } | ||
1253 | |||
1254 | static void | ||
1255 | ip6_tnl_parm_to_user(struct ip6_tnl_parm *u, const struct __ip6_tnl_parm *p) | ||
1256 | { | ||
1257 | u->laddr = p->laddr; | ||
1258 | u->raddr = p->raddr; | ||
1259 | u->flags = p->flags; | ||
1260 | u->hop_limit = p->hop_limit; | ||
1261 | u->encap_limit = p->encap_limit; | ||
1262 | u->flowinfo = p->flowinfo; | ||
1263 | u->link = p->link; | ||
1264 | u->proto = p->proto; | ||
1265 | memcpy(u->name, p->name, sizeof(u->name)); | ||
1266 | } | ||
1267 | |||
1233 | /** | 1268 | /** |
1234 | * ip6_tnl_ioctl - configure ipv6 tunnels from userspace | 1269 | * ip6_tnl_ioctl - configure ipv6 tunnels from userspace |
1235 | * @dev: virtual device associated with tunnel | 1270 | * @dev: virtual device associated with tunnel |
@@ -1263,6 +1298,7 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
1263 | { | 1298 | { |
1264 | int err = 0; | 1299 | int err = 0; |
1265 | struct ip6_tnl_parm p; | 1300 | struct ip6_tnl_parm p; |
1301 | struct __ip6_tnl_parm p1; | ||
1266 | struct ip6_tnl *t = NULL; | 1302 | struct ip6_tnl *t = NULL; |
1267 | struct net *net = dev_net(dev); | 1303 | struct net *net = dev_net(dev); |
1268 | struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); | 1304 | struct ip6_tnl_net *ip6n = net_generic(net, ip6_tnl_net_id); |
@@ -1274,11 +1310,14 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
1274 | err = -EFAULT; | 1310 | err = -EFAULT; |
1275 | break; | 1311 | break; |
1276 | } | 1312 | } |
1277 | t = ip6_tnl_locate(net, &p, 0); | 1313 | ip6_tnl_parm_from_user(&p1, &p); |
1314 | t = ip6_tnl_locate(net, &p1, 0); | ||
1315 | } else { | ||
1316 | memset(&p, 0, sizeof(p)); | ||
1278 | } | 1317 | } |
1279 | if (t == NULL) | 1318 | if (t == NULL) |
1280 | t = netdev_priv(dev); | 1319 | t = netdev_priv(dev); |
1281 | memcpy(&p, &t->parms, sizeof (p)); | 1320 | ip6_tnl_parm_to_user(&p, &t->parms); |
1282 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof (p))) { | 1321 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof (p))) { |
1283 | err = -EFAULT; | 1322 | err = -EFAULT; |
1284 | } | 1323 | } |
@@ -1295,7 +1334,8 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
1295 | if (p.proto != IPPROTO_IPV6 && p.proto != IPPROTO_IPIP && | 1334 | if (p.proto != IPPROTO_IPV6 && p.proto != IPPROTO_IPIP && |
1296 | p.proto != 0) | 1335 | p.proto != 0) |
1297 | break; | 1336 | break; |
1298 | t = ip6_tnl_locate(net, &p, cmd == SIOCADDTUNNEL); | 1337 | ip6_tnl_parm_from_user(&p1, &p); |
1338 | t = ip6_tnl_locate(net, &p1, cmd == SIOCADDTUNNEL); | ||
1299 | if (dev != ip6n->fb_tnl_dev && cmd == SIOCCHGTUNNEL) { | 1339 | if (dev != ip6n->fb_tnl_dev && cmd == SIOCCHGTUNNEL) { |
1300 | if (t != NULL) { | 1340 | if (t != NULL) { |
1301 | if (t->dev != dev) { | 1341 | if (t->dev != dev) { |
@@ -1307,13 +1347,14 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
1307 | 1347 | ||
1308 | ip6_tnl_unlink(ip6n, t); | 1348 | ip6_tnl_unlink(ip6n, t); |
1309 | synchronize_net(); | 1349 | synchronize_net(); |
1310 | err = ip6_tnl_change(t, &p); | 1350 | err = ip6_tnl_change(t, &p1); |
1311 | ip6_tnl_link(ip6n, t); | 1351 | ip6_tnl_link(ip6n, t); |
1312 | netdev_state_change(dev); | 1352 | netdev_state_change(dev); |
1313 | } | 1353 | } |
1314 | if (t) { | 1354 | if (t) { |
1315 | err = 0; | 1355 | err = 0; |
1316 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &t->parms, sizeof (p))) | 1356 | ip6_tnl_parm_to_user(&p, &t->parms); |
1357 | if (copy_to_user(ifr->ifr_ifru.ifru_data, &p, sizeof(p))) | ||
1317 | err = -EFAULT; | 1358 | err = -EFAULT; |
1318 | 1359 | ||
1319 | } else | 1360 | } else |
@@ -1329,7 +1370,9 @@ ip6_tnl_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
1329 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) | 1370 | if (copy_from_user(&p, ifr->ifr_ifru.ifru_data, sizeof (p))) |
1330 | break; | 1371 | break; |
1331 | err = -ENOENT; | 1372 | err = -ENOENT; |
1332 | if ((t = ip6_tnl_locate(net, &p, 0)) == NULL) | 1373 | ip6_tnl_parm_from_user(&p1, &p); |
1374 | t = ip6_tnl_locate(net, &p1, 0); | ||
1375 | if (t == NULL) | ||
1333 | break; | 1376 | break; |
1334 | err = -EPERM; | 1377 | err = -EPERM; |
1335 | if (t->dev == ip6n->fb_tnl_dev) | 1378 | if (t->dev == ip6n->fb_tnl_dev) |
diff --git a/net/ipv6/netfilter.c b/net/ipv6/netfilter.c index db31561cc8df..429089cb073d 100644 --- a/net/ipv6/netfilter.c +++ b/net/ipv6/netfilter.c | |||
@@ -15,6 +15,7 @@ int ip6_route_me_harder(struct sk_buff *skb) | |||
15 | { | 15 | { |
16 | struct net *net = dev_net(skb_dst(skb)->dev); | 16 | struct net *net = dev_net(skb_dst(skb)->dev); |
17 | const struct ipv6hdr *iph = ipv6_hdr(skb); | 17 | const struct ipv6hdr *iph = ipv6_hdr(skb); |
18 | unsigned int hh_len; | ||
18 | struct dst_entry *dst; | 19 | struct dst_entry *dst; |
19 | struct flowi6 fl6 = { | 20 | struct flowi6 fl6 = { |
20 | .flowi6_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0, | 21 | .flowi6_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0, |
@@ -47,6 +48,13 @@ int ip6_route_me_harder(struct sk_buff *skb) | |||
47 | } | 48 | } |
48 | #endif | 49 | #endif |
49 | 50 | ||
51 | /* Change in oif may mean change in hh_len. */ | ||
52 | hh_len = skb_dst(skb)->dev->hard_header_len; | ||
53 | if (skb_headroom(skb) < hh_len && | ||
54 | pskb_expand_head(skb, HH_DATA_ALIGN(hh_len - skb_headroom(skb)), | ||
55 | 0, GFP_ATOMIC)) | ||
56 | return -1; | ||
57 | |||
50 | return 0; | 58 | return 0; |
51 | } | 59 | } |
52 | EXPORT_SYMBOL(ip6_route_me_harder); | 60 | EXPORT_SYMBOL(ip6_route_me_harder); |
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 10135342799e..3b73254d7bf1 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
@@ -25,6 +25,18 @@ config NF_CONNTRACK_IPV6 | |||
25 | 25 | ||
26 | To compile it as a module, choose M here. If unsure, say N. | 26 | To compile it as a module, choose M here. If unsure, say N. |
27 | 27 | ||
28 | config NF_NAT_IPV6 | ||
29 | tristate "IPv6 NAT" | ||
30 | depends on NF_CONNTRACK_IPV6 | ||
31 | depends on NETFILTER_ADVANCED | ||
32 | select NF_NAT | ||
33 | help | ||
34 | The IPv6 NAT option allows masquerading, port forwarding and other | ||
35 | forms of full Network Address Port Translation. It is controlled by | ||
36 | the `nat' table in ip6tables, see the man page for ip6tables(8). | ||
37 | |||
38 | To compile it as a module, choose M here. If unsure, say N. | ||
39 | |||
28 | config IP6_NF_IPTABLES | 40 | config IP6_NF_IPTABLES |
29 | tristate "IP6 tables support (required for filtering)" | 41 | tristate "IP6 tables support (required for filtering)" |
30 | depends on INET && IPV6 | 42 | depends on INET && IPV6 |
@@ -132,6 +144,48 @@ config IP6_NF_TARGET_HL | |||
132 | (e.g. when running oldconfig). It selects | 144 | (e.g. when running oldconfig). It selects |
133 | CONFIG_NETFILTER_XT_TARGET_HL. | 145 | CONFIG_NETFILTER_XT_TARGET_HL. |
134 | 146 | ||
147 | config IP6_NF_TARGET_MASQUERADE | ||
148 | tristate "MASQUERADE target support" | ||
149 | depends on NF_NAT_IPV6 | ||
150 | help | ||
151 | Masquerading is a special case of NAT: all outgoing connections are | ||
152 | changed to seem to come from a particular interface's address, and | ||
153 | if the interface goes down, those connections are lost. This is | ||
154 | only useful for dialup accounts with dynamic IP address (ie. your IP | ||
155 | address will be different on next dialup). | ||
156 | |||
157 | To compile it as a module, choose M here. If unsure, say N. | ||
158 | |||
159 | config IP6_NF_TARGET_NETMAP | ||
160 | tristate "NETMAP target support" | ||
161 | depends on NF_NAT_IPV6 | ||
162 | help | ||
163 | NETMAP is an implementation of static 1:1 NAT mapping of network | ||
164 | addresses. It maps the network address part, while keeping the host | ||
165 | address part intact. | ||
166 | |||
167 | To compile it as a module, choose M here. If unsure, say N. | ||
168 | |||
169 | config IP6_NF_TARGET_REDIRECT | ||
170 | tristate "REDIRECT target support" | ||
171 | depends on NF_NAT_IPV6 | ||
172 | help | ||
173 | REDIRECT is a special case of NAT: all incoming connections are | ||
174 | mapped onto the incoming interface's address, causing the packets to | ||
175 | come to the local machine instead of passing through. This is | ||
176 | useful for transparent proxies. | ||
177 | |||
178 | To compile it as a module, choose M here. If unsure, say N. | ||
179 | |||
180 | config IP6_NF_TARGET_NPT | ||
181 | tristate "NPT (Network Prefix translation) target support" | ||
182 | depends on NETFILTER_ADVANCED | ||
183 | help | ||
184 | This option adds the `SNPT' and `DNPT' target, which perform | ||
185 | stateless IPv6-to-IPv6 Network Prefix Translation per RFC 6296. | ||
186 | |||
187 | To compile it as a module, choose M here. If unsure, say N. | ||
188 | |||
135 | config IP6_NF_FILTER | 189 | config IP6_NF_FILTER |
136 | tristate "Packet filtering" | 190 | tristate "Packet filtering" |
137 | default m if NETFILTER_ADVANCED=n | 191 | default m if NETFILTER_ADVANCED=n |
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index 534d3f216f7b..5752132ca159 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile | |||
@@ -8,6 +8,7 @@ obj-$(CONFIG_IP6_NF_FILTER) += ip6table_filter.o | |||
8 | obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o | 8 | obj-$(CONFIG_IP6_NF_MANGLE) += ip6table_mangle.o |
9 | obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o | 9 | obj-$(CONFIG_IP6_NF_RAW) += ip6table_raw.o |
10 | obj-$(CONFIG_IP6_NF_SECURITY) += ip6table_security.o | 10 | obj-$(CONFIG_IP6_NF_SECURITY) += ip6table_security.o |
11 | obj-$(CONFIG_NF_NAT_IPV6) += ip6table_nat.o | ||
11 | 12 | ||
12 | # objects for l3 independent conntrack | 13 | # objects for l3 independent conntrack |
13 | nf_conntrack_ipv6-y := nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o | 14 | nf_conntrack_ipv6-y := nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o |
@@ -15,6 +16,9 @@ nf_conntrack_ipv6-y := nf_conntrack_l3proto_ipv6.o nf_conntrack_proto_icmpv6.o | |||
15 | # l3 independent conntrack | 16 | # l3 independent conntrack |
16 | obj-$(CONFIG_NF_CONNTRACK_IPV6) += nf_conntrack_ipv6.o nf_defrag_ipv6.o | 17 | obj-$(CONFIG_NF_CONNTRACK_IPV6) += nf_conntrack_ipv6.o nf_defrag_ipv6.o |
17 | 18 | ||
19 | nf_nat_ipv6-y := nf_nat_l3proto_ipv6.o nf_nat_proto_icmpv6.o | ||
20 | obj-$(CONFIG_NF_NAT_IPV6) += nf_nat_ipv6.o | ||
21 | |||
18 | # defrag | 22 | # defrag |
19 | nf_defrag_ipv6-y := nf_defrag_ipv6_hooks.o nf_conntrack_reasm.o | 23 | nf_defrag_ipv6-y := nf_defrag_ipv6_hooks.o nf_conntrack_reasm.o |
20 | obj-$(CONFIG_NF_DEFRAG_IPV6) += nf_defrag_ipv6.o | 24 | obj-$(CONFIG_NF_DEFRAG_IPV6) += nf_defrag_ipv6.o |
@@ -30,4 +34,8 @@ obj-$(CONFIG_IP6_NF_MATCH_RPFILTER) += ip6t_rpfilter.o | |||
30 | obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o | 34 | obj-$(CONFIG_IP6_NF_MATCH_RT) += ip6t_rt.o |
31 | 35 | ||
32 | # targets | 36 | # targets |
37 | obj-$(CONFIG_IP6_NF_TARGET_MASQUERADE) += ip6t_MASQUERADE.o | ||
38 | obj-$(CONFIG_IP6_NF_TARGET_NETMAP) += ip6t_NETMAP.o | ||
39 | obj-$(CONFIG_IP6_NF_TARGET_NPT) += ip6t_NPT.o | ||
40 | obj-$(CONFIG_IP6_NF_TARGET_REDIRECT) += ip6t_REDIRECT.o | ||
33 | obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o | 41 | obj-$(CONFIG_IP6_NF_TARGET_REJECT) += ip6t_REJECT.o |
diff --git a/net/ipv6/netfilter/ip6t_MASQUERADE.c b/net/ipv6/netfilter/ip6t_MASQUERADE.c new file mode 100644 index 000000000000..60e9053bab05 --- /dev/null +++ b/net/ipv6/netfilter/ip6t_MASQUERADE.c | |||
@@ -0,0 +1,135 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2011 Patrick McHardy <kaber@trash.net> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * Based on Rusty Russell's IPv6 MASQUERADE target. Development of IPv6 | ||
9 | * NAT funded by Astaro. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/netdevice.h> | ||
15 | #include <linux/ipv6.h> | ||
16 | #include <linux/netfilter.h> | ||
17 | #include <linux/netfilter_ipv6.h> | ||
18 | #include <linux/netfilter/x_tables.h> | ||
19 | #include <net/netfilter/nf_nat.h> | ||
20 | #include <net/addrconf.h> | ||
21 | #include <net/ipv6.h> | ||
22 | |||
23 | static unsigned int | ||
24 | masquerade_tg6(struct sk_buff *skb, const struct xt_action_param *par) | ||
25 | { | ||
26 | const struct nf_nat_range *range = par->targinfo; | ||
27 | enum ip_conntrack_info ctinfo; | ||
28 | struct in6_addr src; | ||
29 | struct nf_conn *ct; | ||
30 | struct nf_nat_range newrange; | ||
31 | |||
32 | ct = nf_ct_get(skb, &ctinfo); | ||
33 | NF_CT_ASSERT(ct && (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED || | ||
34 | ctinfo == IP_CT_RELATED_REPLY)); | ||
35 | |||
36 | if (ipv6_dev_get_saddr(dev_net(par->out), par->out, | ||
37 | &ipv6_hdr(skb)->daddr, 0, &src) < 0) | ||
38 | return NF_DROP; | ||
39 | |||
40 | nfct_nat(ct)->masq_index = par->out->ifindex; | ||
41 | |||
42 | newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS; | ||
43 | newrange.min_addr.in6 = src; | ||
44 | newrange.max_addr.in6 = src; | ||
45 | newrange.min_proto = range->min_proto; | ||
46 | newrange.max_proto = range->max_proto; | ||
47 | |||
48 | return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_SRC); | ||
49 | } | ||
50 | |||
51 | static int masquerade_tg6_checkentry(const struct xt_tgchk_param *par) | ||
52 | { | ||
53 | const struct nf_nat_range *range = par->targinfo; | ||
54 | |||
55 | if (range->flags & NF_NAT_RANGE_MAP_IPS) | ||
56 | return -EINVAL; | ||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | static int device_cmp(struct nf_conn *ct, void *ifindex) | ||
61 | { | ||
62 | const struct nf_conn_nat *nat = nfct_nat(ct); | ||
63 | |||
64 | if (!nat) | ||
65 | return 0; | ||
66 | if (nf_ct_l3num(ct) != NFPROTO_IPV6) | ||
67 | return 0; | ||
68 | return nat->masq_index == (int)(long)ifindex; | ||
69 | } | ||
70 | |||
71 | static int masq_device_event(struct notifier_block *this, | ||
72 | unsigned long event, void *ptr) | ||
73 | { | ||
74 | const struct net_device *dev = ptr; | ||
75 | struct net *net = dev_net(dev); | ||
76 | |||
77 | if (event == NETDEV_DOWN) | ||
78 | nf_ct_iterate_cleanup(net, device_cmp, | ||
79 | (void *)(long)dev->ifindex); | ||
80 | |||
81 | return NOTIFY_DONE; | ||
82 | } | ||
83 | |||
84 | static struct notifier_block masq_dev_notifier = { | ||
85 | .notifier_call = masq_device_event, | ||
86 | }; | ||
87 | |||
88 | static int masq_inet_event(struct notifier_block *this, | ||
89 | unsigned long event, void *ptr) | ||
90 | { | ||
91 | struct inet6_ifaddr *ifa = ptr; | ||
92 | |||
93 | return masq_device_event(this, event, ifa->idev->dev); | ||
94 | } | ||
95 | |||
96 | static struct notifier_block masq_inet_notifier = { | ||
97 | .notifier_call = masq_inet_event, | ||
98 | }; | ||
99 | |||
100 | static struct xt_target masquerade_tg6_reg __read_mostly = { | ||
101 | .name = "MASQUERADE", | ||
102 | .family = NFPROTO_IPV6, | ||
103 | .checkentry = masquerade_tg6_checkentry, | ||
104 | .target = masquerade_tg6, | ||
105 | .targetsize = sizeof(struct nf_nat_range), | ||
106 | .table = "nat", | ||
107 | .hooks = 1 << NF_INET_POST_ROUTING, | ||
108 | .me = THIS_MODULE, | ||
109 | }; | ||
110 | |||
111 | static int __init masquerade_tg6_init(void) | ||
112 | { | ||
113 | int err; | ||
114 | |||
115 | err = xt_register_target(&masquerade_tg6_reg); | ||
116 | if (err == 0) { | ||
117 | register_netdevice_notifier(&masq_dev_notifier); | ||
118 | register_inet6addr_notifier(&masq_inet_notifier); | ||
119 | } | ||
120 | |||
121 | return err; | ||
122 | } | ||
123 | static void __exit masquerade_tg6_exit(void) | ||
124 | { | ||
125 | unregister_inet6addr_notifier(&masq_inet_notifier); | ||
126 | unregister_netdevice_notifier(&masq_dev_notifier); | ||
127 | xt_unregister_target(&masquerade_tg6_reg); | ||
128 | } | ||
129 | |||
130 | module_init(masquerade_tg6_init); | ||
131 | module_exit(masquerade_tg6_exit); | ||
132 | |||
133 | MODULE_LICENSE("GPL"); | ||
134 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | ||
135 | MODULE_DESCRIPTION("Xtables: automatic address SNAT"); | ||
diff --git a/net/ipv6/netfilter/ip6t_NETMAP.c b/net/ipv6/netfilter/ip6t_NETMAP.c new file mode 100644 index 000000000000..4f3bf360e50f --- /dev/null +++ b/net/ipv6/netfilter/ip6t_NETMAP.c | |||
@@ -0,0 +1,94 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2011 Patrick McHardy <kaber@trash.net> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * Based on Svenning Soerensen's IPv4 NETMAP target. Development of IPv6 | ||
9 | * NAT funded by Astaro. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/ipv6.h> | ||
15 | #include <linux/netfilter.h> | ||
16 | #include <linux/netfilter_ipv6.h> | ||
17 | #include <linux/netfilter/x_tables.h> | ||
18 | #include <net/netfilter/nf_nat.h> | ||
19 | |||
20 | static unsigned int | ||
21 | netmap_tg6(struct sk_buff *skb, const struct xt_action_param *par) | ||
22 | { | ||
23 | const struct nf_nat_range *range = par->targinfo; | ||
24 | struct nf_nat_range newrange; | ||
25 | struct nf_conn *ct; | ||
26 | enum ip_conntrack_info ctinfo; | ||
27 | union nf_inet_addr new_addr, netmask; | ||
28 | unsigned int i; | ||
29 | |||
30 | ct = nf_ct_get(skb, &ctinfo); | ||
31 | for (i = 0; i < ARRAY_SIZE(range->min_addr.ip6); i++) | ||
32 | netmask.ip6[i] = ~(range->min_addr.ip6[i] ^ | ||
33 | range->max_addr.ip6[i]); | ||
34 | |||
35 | if (par->hooknum == NF_INET_PRE_ROUTING || | ||
36 | par->hooknum == NF_INET_LOCAL_OUT) | ||
37 | new_addr.in6 = ipv6_hdr(skb)->daddr; | ||
38 | else | ||
39 | new_addr.in6 = ipv6_hdr(skb)->saddr; | ||
40 | |||
41 | for (i = 0; i < ARRAY_SIZE(new_addr.ip6); i++) { | ||
42 | new_addr.ip6[i] &= ~netmask.ip6[i]; | ||
43 | new_addr.ip6[i] |= range->min_addr.ip6[i] & | ||
44 | netmask.ip6[i]; | ||
45 | } | ||
46 | |||
47 | newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS; | ||
48 | newrange.min_addr = new_addr; | ||
49 | newrange.max_addr = new_addr; | ||
50 | newrange.min_proto = range->min_proto; | ||
51 | newrange.max_proto = range->max_proto; | ||
52 | |||
53 | return nf_nat_setup_info(ct, &newrange, HOOK2MANIP(par->hooknum)); | ||
54 | } | ||
55 | |||
56 | static int netmap_tg6_checkentry(const struct xt_tgchk_param *par) | ||
57 | { | ||
58 | const struct nf_nat_range *range = par->targinfo; | ||
59 | |||
60 | if (!(range->flags & NF_NAT_RANGE_MAP_IPS)) | ||
61 | return -EINVAL; | ||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static struct xt_target netmap_tg6_reg __read_mostly = { | ||
66 | .name = "NETMAP", | ||
67 | .family = NFPROTO_IPV6, | ||
68 | .target = netmap_tg6, | ||
69 | .targetsize = sizeof(struct nf_nat_range), | ||
70 | .table = "nat", | ||
71 | .hooks = (1 << NF_INET_PRE_ROUTING) | | ||
72 | (1 << NF_INET_POST_ROUTING) | | ||
73 | (1 << NF_INET_LOCAL_OUT) | | ||
74 | (1 << NF_INET_LOCAL_IN), | ||
75 | .checkentry = netmap_tg6_checkentry, | ||
76 | .me = THIS_MODULE, | ||
77 | }; | ||
78 | |||
79 | static int __init netmap_tg6_init(void) | ||
80 | { | ||
81 | return xt_register_target(&netmap_tg6_reg); | ||
82 | } | ||
83 | |||
84 | static void netmap_tg6_exit(void) | ||
85 | { | ||
86 | xt_unregister_target(&netmap_tg6_reg); | ||
87 | } | ||
88 | |||
89 | module_init(netmap_tg6_init); | ||
90 | module_exit(netmap_tg6_exit); | ||
91 | |||
92 | MODULE_LICENSE("GPL"); | ||
93 | MODULE_DESCRIPTION("Xtables: 1:1 NAT mapping of IPv6 subnets"); | ||
94 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | ||
diff --git a/net/ipv6/netfilter/ip6t_NPT.c b/net/ipv6/netfilter/ip6t_NPT.c new file mode 100644 index 000000000000..e9486915eff6 --- /dev/null +++ b/net/ipv6/netfilter/ip6t_NPT.c | |||
@@ -0,0 +1,165 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2011, 2012 Patrick McHardy <kaber@trash.net> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | */ | ||
8 | |||
9 | #include <linux/module.h> | ||
10 | #include <linux/skbuff.h> | ||
11 | #include <linux/ipv6.h> | ||
12 | #include <linux/netfilter.h> | ||
13 | #include <linux/netfilter_ipv6.h> | ||
14 | #include <linux/netfilter_ipv6/ip6t_NPT.h> | ||
15 | #include <linux/netfilter/x_tables.h> | ||
16 | |||
17 | static __sum16 csum16_complement(__sum16 a) | ||
18 | { | ||
19 | return (__force __sum16)(0xffff - (__force u16)a); | ||
20 | } | ||
21 | |||
22 | static __sum16 csum16_add(__sum16 a, __sum16 b) | ||
23 | { | ||
24 | u16 sum; | ||
25 | |||
26 | sum = (__force u16)a + (__force u16)b; | ||
27 | sum += (__force u16)a < (__force u16)b; | ||
28 | return (__force __sum16)sum; | ||
29 | } | ||
30 | |||
31 | static __sum16 csum16_sub(__sum16 a, __sum16 b) | ||
32 | { | ||
33 | return csum16_add(a, csum16_complement(b)); | ||
34 | } | ||
35 | |||
36 | static int ip6t_npt_checkentry(const struct xt_tgchk_param *par) | ||
37 | { | ||
38 | struct ip6t_npt_tginfo *npt = par->targinfo; | ||
39 | __sum16 src_sum = 0, dst_sum = 0; | ||
40 | unsigned int i; | ||
41 | |||
42 | if (npt->src_pfx_len > 64 || npt->dst_pfx_len > 64) | ||
43 | return -EINVAL; | ||
44 | |||
45 | for (i = 0; i < ARRAY_SIZE(npt->src_pfx.in6.s6_addr16); i++) { | ||
46 | src_sum = csum16_add(src_sum, | ||
47 | (__force __sum16)npt->src_pfx.in6.s6_addr16[i]); | ||
48 | dst_sum = csum16_add(dst_sum, | ||
49 | (__force __sum16)npt->dst_pfx.in6.s6_addr16[i]); | ||
50 | } | ||
51 | |||
52 | npt->adjustment = csum16_sub(src_sum, dst_sum); | ||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | static bool ip6t_npt_map_pfx(const struct ip6t_npt_tginfo *npt, | ||
57 | struct in6_addr *addr) | ||
58 | { | ||
59 | unsigned int pfx_len; | ||
60 | unsigned int i, idx; | ||
61 | __be32 mask; | ||
62 | __sum16 sum; | ||
63 | |||
64 | pfx_len = max(npt->src_pfx_len, npt->dst_pfx_len); | ||
65 | for (i = 0; i < pfx_len; i += 32) { | ||
66 | if (pfx_len - i >= 32) | ||
67 | mask = 0; | ||
68 | else | ||
69 | mask = htonl(~((1 << (pfx_len - i)) - 1)); | ||
70 | |||
71 | idx = i / 32; | ||
72 | addr->s6_addr32[idx] &= mask; | ||
73 | addr->s6_addr32[idx] |= npt->dst_pfx.in6.s6_addr32[idx]; | ||
74 | } | ||
75 | |||
76 | if (pfx_len <= 48) | ||
77 | idx = 3; | ||
78 | else { | ||
79 | for (idx = 4; idx < ARRAY_SIZE(addr->s6_addr16); idx++) { | ||
80 | if ((__force __sum16)addr->s6_addr16[idx] != | ||
81 | CSUM_MANGLED_0) | ||
82 | break; | ||
83 | } | ||
84 | if (idx == ARRAY_SIZE(addr->s6_addr16)) | ||
85 | return false; | ||
86 | } | ||
87 | |||
88 | sum = csum16_add((__force __sum16)addr->s6_addr16[idx], | ||
89 | npt->adjustment); | ||
90 | if (sum == CSUM_MANGLED_0) | ||
91 | sum = 0; | ||
92 | *(__force __sum16 *)&addr->s6_addr16[idx] = sum; | ||
93 | |||
94 | return true; | ||
95 | } | ||
96 | |||
97 | static unsigned int | ||
98 | ip6t_snpt_tg(struct sk_buff *skb, const struct xt_action_param *par) | ||
99 | { | ||
100 | const struct ip6t_npt_tginfo *npt = par->targinfo; | ||
101 | |||
102 | if (!ip6t_npt_map_pfx(npt, &ipv6_hdr(skb)->saddr)) { | ||
103 | icmpv6_send(skb, ICMPV6_PARAMPROB, ICMPV6_HDR_FIELD, | ||
104 | offsetof(struct ipv6hdr, saddr)); | ||
105 | return NF_DROP; | ||
106 | } | ||
107 | return XT_CONTINUE; | ||
108 | } | ||
109 | |||
110 | static unsigned int | ||
111 | ip6t_dnpt_tg(struct sk_buff *skb, const struct xt_action_param *par) | ||
112 | { | ||
113 | const struct ip6t_npt_tginfo *npt = par->targinfo; | ||
114 | |||
115 | if (!ip6t_npt_map_pfx(npt, &ipv6_hdr(skb)->daddr)) { | ||
116 | icmpv6_send(skb, ICMPV6_PARAMPROB, ICMPV6_HDR_FIELD, | ||
117 | offsetof(struct ipv6hdr, daddr)); | ||
118 | return NF_DROP; | ||
119 | } | ||
120 | return XT_CONTINUE; | ||
121 | } | ||
122 | |||
123 | static struct xt_target ip6t_npt_target_reg[] __read_mostly = { | ||
124 | { | ||
125 | .name = "SNPT", | ||
126 | .target = ip6t_snpt_tg, | ||
127 | .targetsize = sizeof(struct ip6t_npt_tginfo), | ||
128 | .checkentry = ip6t_npt_checkentry, | ||
129 | .family = NFPROTO_IPV6, | ||
130 | .hooks = (1 << NF_INET_LOCAL_IN) | | ||
131 | (1 << NF_INET_POST_ROUTING), | ||
132 | .me = THIS_MODULE, | ||
133 | }, | ||
134 | { | ||
135 | .name = "DNPT", | ||
136 | .target = ip6t_dnpt_tg, | ||
137 | .targetsize = sizeof(struct ip6t_npt_tginfo), | ||
138 | .checkentry = ip6t_npt_checkentry, | ||
139 | .family = NFPROTO_IPV6, | ||
140 | .hooks = (1 << NF_INET_PRE_ROUTING) | | ||
141 | (1 << NF_INET_LOCAL_OUT), | ||
142 | .me = THIS_MODULE, | ||
143 | }, | ||
144 | }; | ||
145 | |||
146 | static int __init ip6t_npt_init(void) | ||
147 | { | ||
148 | return xt_register_targets(ip6t_npt_target_reg, | ||
149 | ARRAY_SIZE(ip6t_npt_target_reg)); | ||
150 | } | ||
151 | |||
152 | static void __exit ip6t_npt_exit(void) | ||
153 | { | ||
154 | xt_unregister_targets(ip6t_npt_target_reg, | ||
155 | ARRAY_SIZE(ip6t_npt_target_reg)); | ||
156 | } | ||
157 | |||
158 | module_init(ip6t_npt_init); | ||
159 | module_exit(ip6t_npt_exit); | ||
160 | |||
161 | MODULE_LICENSE("GPL"); | ||
162 | MODULE_DESCRIPTION("IPv6-to-IPv6 Network Prefix Translation (RFC 6296)"); | ||
163 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | ||
164 | MODULE_ALIAS("ip6t_SNPT"); | ||
165 | MODULE_ALIAS("ip6t_DNPT"); | ||
diff --git a/net/ipv6/netfilter/ip6t_REDIRECT.c b/net/ipv6/netfilter/ip6t_REDIRECT.c new file mode 100644 index 000000000000..60497a3c6004 --- /dev/null +++ b/net/ipv6/netfilter/ip6t_REDIRECT.c | |||
@@ -0,0 +1,98 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2011 Patrick McHardy <kaber@trash.net> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * Based on Rusty Russell's IPv4 REDIRECT target. Development of IPv6 | ||
9 | * NAT funded by Astaro. | ||
10 | */ | ||
11 | |||
12 | #include <linux/kernel.h> | ||
13 | #include <linux/module.h> | ||
14 | #include <linux/netfilter.h> | ||
15 | #include <linux/netfilter_ipv6.h> | ||
16 | #include <linux/netfilter/x_tables.h> | ||
17 | #include <net/addrconf.h> | ||
18 | #include <net/netfilter/nf_nat.h> | ||
19 | |||
20 | static const struct in6_addr loopback_addr = IN6ADDR_LOOPBACK_INIT; | ||
21 | |||
22 | static unsigned int | ||
23 | redirect_tg6(struct sk_buff *skb, const struct xt_action_param *par) | ||
24 | { | ||
25 | const struct nf_nat_range *range = par->targinfo; | ||
26 | struct nf_nat_range newrange; | ||
27 | struct in6_addr newdst; | ||
28 | enum ip_conntrack_info ctinfo; | ||
29 | struct nf_conn *ct; | ||
30 | |||
31 | ct = nf_ct_get(skb, &ctinfo); | ||
32 | if (par->hooknum == NF_INET_LOCAL_OUT) | ||
33 | newdst = loopback_addr; | ||
34 | else { | ||
35 | struct inet6_dev *idev; | ||
36 | struct inet6_ifaddr *ifa; | ||
37 | bool addr = false; | ||
38 | |||
39 | rcu_read_lock(); | ||
40 | idev = __in6_dev_get(skb->dev); | ||
41 | if (idev != NULL) { | ||
42 | list_for_each_entry(ifa, &idev->addr_list, if_list) { | ||
43 | newdst = ifa->addr; | ||
44 | addr = true; | ||
45 | break; | ||
46 | } | ||
47 | } | ||
48 | rcu_read_unlock(); | ||
49 | |||
50 | if (!addr) | ||
51 | return NF_DROP; | ||
52 | } | ||
53 | |||
54 | newrange.flags = range->flags | NF_NAT_RANGE_MAP_IPS; | ||
55 | newrange.min_addr.in6 = newdst; | ||
56 | newrange.max_addr.in6 = newdst; | ||
57 | newrange.min_proto = range->min_proto; | ||
58 | newrange.max_proto = range->max_proto; | ||
59 | |||
60 | return nf_nat_setup_info(ct, &newrange, NF_NAT_MANIP_DST); | ||
61 | } | ||
62 | |||
63 | static int redirect_tg6_checkentry(const struct xt_tgchk_param *par) | ||
64 | { | ||
65 | const struct nf_nat_range *range = par->targinfo; | ||
66 | |||
67 | if (range->flags & NF_NAT_RANGE_MAP_IPS) | ||
68 | return -EINVAL; | ||
69 | return 0; | ||
70 | } | ||
71 | |||
72 | static struct xt_target redirect_tg6_reg __read_mostly = { | ||
73 | .name = "REDIRECT", | ||
74 | .family = NFPROTO_IPV6, | ||
75 | .checkentry = redirect_tg6_checkentry, | ||
76 | .target = redirect_tg6, | ||
77 | .targetsize = sizeof(struct nf_nat_range), | ||
78 | .table = "nat", | ||
79 | .hooks = (1 << NF_INET_PRE_ROUTING) | (1 << NF_INET_LOCAL_OUT), | ||
80 | .me = THIS_MODULE, | ||
81 | }; | ||
82 | |||
83 | static int __init redirect_tg6_init(void) | ||
84 | { | ||
85 | return xt_register_target(&redirect_tg6_reg); | ||
86 | } | ||
87 | |||
88 | static void __exit redirect_tg6_exit(void) | ||
89 | { | ||
90 | xt_unregister_target(&redirect_tg6_reg); | ||
91 | } | ||
92 | |||
93 | module_init(redirect_tg6_init); | ||
94 | module_exit(redirect_tg6_exit); | ||
95 | |||
96 | MODULE_LICENSE("GPL"); | ||
97 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | ||
98 | MODULE_DESCRIPTION("Xtables: Connection redirection to localhost"); | ||
diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c index 325e59a0224f..beb5777d2043 100644 --- a/net/ipv6/netfilter/ip6table_filter.c +++ b/net/ipv6/netfilter/ip6table_filter.c | |||
@@ -61,9 +61,7 @@ static int __net_init ip6table_filter_net_init(struct net *net) | |||
61 | net->ipv6.ip6table_filter = | 61 | net->ipv6.ip6table_filter = |
62 | ip6t_register_table(net, &packet_filter, repl); | 62 | ip6t_register_table(net, &packet_filter, repl); |
63 | kfree(repl); | 63 | kfree(repl); |
64 | if (IS_ERR(net->ipv6.ip6table_filter)) | 64 | return PTR_RET(net->ipv6.ip6table_filter); |
65 | return PTR_ERR(net->ipv6.ip6table_filter); | ||
66 | return 0; | ||
67 | } | 65 | } |
68 | 66 | ||
69 | static void __net_exit ip6table_filter_net_exit(struct net *net) | 67 | static void __net_exit ip6table_filter_net_exit(struct net *net) |
diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c index 4d782405f125..7431121b87de 100644 --- a/net/ipv6/netfilter/ip6table_mangle.c +++ b/net/ipv6/netfilter/ip6table_mangle.c | |||
@@ -97,9 +97,7 @@ static int __net_init ip6table_mangle_net_init(struct net *net) | |||
97 | net->ipv6.ip6table_mangle = | 97 | net->ipv6.ip6table_mangle = |
98 | ip6t_register_table(net, &packet_mangler, repl); | 98 | ip6t_register_table(net, &packet_mangler, repl); |
99 | kfree(repl); | 99 | kfree(repl); |
100 | if (IS_ERR(net->ipv6.ip6table_mangle)) | 100 | return PTR_RET(net->ipv6.ip6table_mangle); |
101 | return PTR_ERR(net->ipv6.ip6table_mangle); | ||
102 | return 0; | ||
103 | } | 101 | } |
104 | 102 | ||
105 | static void __net_exit ip6table_mangle_net_exit(struct net *net) | 103 | static void __net_exit ip6table_mangle_net_exit(struct net *net) |
diff --git a/net/ipv6/netfilter/ip6table_nat.c b/net/ipv6/netfilter/ip6table_nat.c new file mode 100644 index 000000000000..e418bd6350a4 --- /dev/null +++ b/net/ipv6/netfilter/ip6table_nat.c | |||
@@ -0,0 +1,321 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2011 Patrick McHardy <kaber@trash.net> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * Based on Rusty Russell's IPv4 NAT code. Development of IPv6 NAT | ||
9 | * funded by Astaro. | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/netfilter.h> | ||
14 | #include <linux/netfilter_ipv6.h> | ||
15 | #include <linux/netfilter_ipv6/ip6_tables.h> | ||
16 | #include <linux/ipv6.h> | ||
17 | #include <net/ipv6.h> | ||
18 | |||
19 | #include <net/netfilter/nf_nat.h> | ||
20 | #include <net/netfilter/nf_nat_core.h> | ||
21 | #include <net/netfilter/nf_nat_l3proto.h> | ||
22 | |||
23 | static const struct xt_table nf_nat_ipv6_table = { | ||
24 | .name = "nat", | ||
25 | .valid_hooks = (1 << NF_INET_PRE_ROUTING) | | ||
26 | (1 << NF_INET_POST_ROUTING) | | ||
27 | (1 << NF_INET_LOCAL_OUT) | | ||
28 | (1 << NF_INET_LOCAL_IN), | ||
29 | .me = THIS_MODULE, | ||
30 | .af = NFPROTO_IPV6, | ||
31 | }; | ||
32 | |||
33 | static unsigned int alloc_null_binding(struct nf_conn *ct, unsigned int hooknum) | ||
34 | { | ||
35 | /* Force range to this IP; let proto decide mapping for | ||
36 | * per-proto parts (hence not IP_NAT_RANGE_PROTO_SPECIFIED). | ||
37 | */ | ||
38 | struct nf_nat_range range; | ||
39 | |||
40 | range.flags = 0; | ||
41 | pr_debug("Allocating NULL binding for %p (%pI6)\n", ct, | ||
42 | HOOK2MANIP(hooknum) == NF_NAT_MANIP_SRC ? | ||
43 | &ct->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip6 : | ||
44 | &ct->tuplehash[IP_CT_DIR_REPLY].tuple.src.u3.ip6); | ||
45 | |||
46 | return nf_nat_setup_info(ct, &range, HOOK2MANIP(hooknum)); | ||
47 | } | ||
48 | |||
49 | static unsigned int nf_nat_rule_find(struct sk_buff *skb, unsigned int hooknum, | ||
50 | const struct net_device *in, | ||
51 | const struct net_device *out, | ||
52 | struct nf_conn *ct) | ||
53 | { | ||
54 | struct net *net = nf_ct_net(ct); | ||
55 | unsigned int ret; | ||
56 | |||
57 | ret = ip6t_do_table(skb, hooknum, in, out, net->ipv6.ip6table_nat); | ||
58 | if (ret == NF_ACCEPT) { | ||
59 | if (!nf_nat_initialized(ct, HOOK2MANIP(hooknum))) | ||
60 | ret = alloc_null_binding(ct, hooknum); | ||
61 | } | ||
62 | return ret; | ||
63 | } | ||
64 | |||
65 | static unsigned int | ||
66 | nf_nat_ipv6_fn(unsigned int hooknum, | ||
67 | struct sk_buff *skb, | ||
68 | const struct net_device *in, | ||
69 | const struct net_device *out, | ||
70 | int (*okfn)(struct sk_buff *)) | ||
71 | { | ||
72 | struct nf_conn *ct; | ||
73 | enum ip_conntrack_info ctinfo; | ||
74 | struct nf_conn_nat *nat; | ||
75 | enum nf_nat_manip_type maniptype = HOOK2MANIP(hooknum); | ||
76 | __be16 frag_off; | ||
77 | int hdrlen; | ||
78 | u8 nexthdr; | ||
79 | |||
80 | ct = nf_ct_get(skb, &ctinfo); | ||
81 | /* Can't track? It's not due to stress, or conntrack would | ||
82 | * have dropped it. Hence it's the user's responsibilty to | ||
83 | * packet filter it out, or implement conntrack/NAT for that | ||
84 | * protocol. 8) --RR | ||
85 | */ | ||
86 | if (!ct) | ||
87 | return NF_ACCEPT; | ||
88 | |||
89 | /* Don't try to NAT if this packet is not conntracked */ | ||
90 | if (nf_ct_is_untracked(ct)) | ||
91 | return NF_ACCEPT; | ||
92 | |||
93 | nat = nfct_nat(ct); | ||
94 | if (!nat) { | ||
95 | /* NAT module was loaded late. */ | ||
96 | if (nf_ct_is_confirmed(ct)) | ||
97 | return NF_ACCEPT; | ||
98 | nat = nf_ct_ext_add(ct, NF_CT_EXT_NAT, GFP_ATOMIC); | ||
99 | if (nat == NULL) { | ||
100 | pr_debug("failed to add NAT extension\n"); | ||
101 | return NF_ACCEPT; | ||
102 | } | ||
103 | } | ||
104 | |||
105 | switch (ctinfo) { | ||
106 | case IP_CT_RELATED: | ||
107 | case IP_CT_RELATED_REPLY: | ||
108 | nexthdr = ipv6_hdr(skb)->nexthdr; | ||
109 | hdrlen = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), | ||
110 | &nexthdr, &frag_off); | ||
111 | |||
112 | if (hdrlen >= 0 && nexthdr == IPPROTO_ICMPV6) { | ||
113 | if (!nf_nat_icmpv6_reply_translation(skb, ct, ctinfo, | ||
114 | hooknum, hdrlen)) | ||
115 | return NF_DROP; | ||
116 | else | ||
117 | return NF_ACCEPT; | ||
118 | } | ||
119 | /* Fall thru... (Only ICMPs can be IP_CT_IS_REPLY) */ | ||
120 | case IP_CT_NEW: | ||
121 | /* Seen it before? This can happen for loopback, retrans, | ||
122 | * or local packets. | ||
123 | */ | ||
124 | if (!nf_nat_initialized(ct, maniptype)) { | ||
125 | unsigned int ret; | ||
126 | |||
127 | ret = nf_nat_rule_find(skb, hooknum, in, out, ct); | ||
128 | if (ret != NF_ACCEPT) | ||
129 | return ret; | ||
130 | } else | ||
131 | pr_debug("Already setup manip %s for ct %p\n", | ||
132 | maniptype == NF_NAT_MANIP_SRC ? "SRC" : "DST", | ||
133 | ct); | ||
134 | break; | ||
135 | |||
136 | default: | ||
137 | /* ESTABLISHED */ | ||
138 | NF_CT_ASSERT(ctinfo == IP_CT_ESTABLISHED || | ||
139 | ctinfo == IP_CT_ESTABLISHED_REPLY); | ||
140 | } | ||
141 | |||
142 | return nf_nat_packet(ct, ctinfo, hooknum, skb); | ||
143 | } | ||
144 | |||
145 | static unsigned int | ||
146 | nf_nat_ipv6_in(unsigned int hooknum, | ||
147 | struct sk_buff *skb, | ||
148 | const struct net_device *in, | ||
149 | const struct net_device *out, | ||
150 | int (*okfn)(struct sk_buff *)) | ||
151 | { | ||
152 | unsigned int ret; | ||
153 | struct in6_addr daddr = ipv6_hdr(skb)->daddr; | ||
154 | |||
155 | ret = nf_nat_ipv6_fn(hooknum, skb, in, out, okfn); | ||
156 | if (ret != NF_DROP && ret != NF_STOLEN && | ||
157 | ipv6_addr_cmp(&daddr, &ipv6_hdr(skb)->daddr)) | ||
158 | skb_dst_drop(skb); | ||
159 | |||
160 | return ret; | ||
161 | } | ||
162 | |||
163 | static unsigned int | ||
164 | nf_nat_ipv6_out(unsigned int hooknum, | ||
165 | struct sk_buff *skb, | ||
166 | const struct net_device *in, | ||
167 | const struct net_device *out, | ||
168 | int (*okfn)(struct sk_buff *)) | ||
169 | { | ||
170 | #ifdef CONFIG_XFRM | ||
171 | const struct nf_conn *ct; | ||
172 | enum ip_conntrack_info ctinfo; | ||
173 | #endif | ||
174 | unsigned int ret; | ||
175 | |||
176 | /* root is playing with raw sockets. */ | ||
177 | if (skb->len < sizeof(struct ipv6hdr)) | ||
178 | return NF_ACCEPT; | ||
179 | |||
180 | ret = nf_nat_ipv6_fn(hooknum, skb, in, out, okfn); | ||
181 | #ifdef CONFIG_XFRM | ||
182 | if (ret != NF_DROP && ret != NF_STOLEN && | ||
183 | !(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && | ||
184 | (ct = nf_ct_get(skb, &ctinfo)) != NULL) { | ||
185 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | ||
186 | |||
187 | if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3, | ||
188 | &ct->tuplehash[!dir].tuple.dst.u3) || | ||
189 | (ct->tuplehash[dir].tuple.src.u.all != | ||
190 | ct->tuplehash[!dir].tuple.dst.u.all)) | ||
191 | if (nf_xfrm_me_harder(skb, AF_INET6) < 0) | ||
192 | ret = NF_DROP; | ||
193 | } | ||
194 | #endif | ||
195 | return ret; | ||
196 | } | ||
197 | |||
198 | static unsigned int | ||
199 | nf_nat_ipv6_local_fn(unsigned int hooknum, | ||
200 | struct sk_buff *skb, | ||
201 | const struct net_device *in, | ||
202 | const struct net_device *out, | ||
203 | int (*okfn)(struct sk_buff *)) | ||
204 | { | ||
205 | const struct nf_conn *ct; | ||
206 | enum ip_conntrack_info ctinfo; | ||
207 | unsigned int ret; | ||
208 | |||
209 | /* root is playing with raw sockets. */ | ||
210 | if (skb->len < sizeof(struct ipv6hdr)) | ||
211 | return NF_ACCEPT; | ||
212 | |||
213 | ret = nf_nat_ipv6_fn(hooknum, skb, in, out, okfn); | ||
214 | if (ret != NF_DROP && ret != NF_STOLEN && | ||
215 | (ct = nf_ct_get(skb, &ctinfo)) != NULL) { | ||
216 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | ||
217 | |||
218 | if (!nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3, | ||
219 | &ct->tuplehash[!dir].tuple.src.u3)) { | ||
220 | if (ip6_route_me_harder(skb)) | ||
221 | ret = NF_DROP; | ||
222 | } | ||
223 | #ifdef CONFIG_XFRM | ||
224 | else if (!(IP6CB(skb)->flags & IP6SKB_XFRM_TRANSFORMED) && | ||
225 | ct->tuplehash[dir].tuple.dst.u.all != | ||
226 | ct->tuplehash[!dir].tuple.src.u.all) | ||
227 | if (nf_xfrm_me_harder(skb, AF_INET6)) | ||
228 | ret = NF_DROP; | ||
229 | #endif | ||
230 | } | ||
231 | return ret; | ||
232 | } | ||
233 | |||
234 | static struct nf_hook_ops nf_nat_ipv6_ops[] __read_mostly = { | ||
235 | /* Before packet filtering, change destination */ | ||
236 | { | ||
237 | .hook = nf_nat_ipv6_in, | ||
238 | .owner = THIS_MODULE, | ||
239 | .pf = NFPROTO_IPV6, | ||
240 | .hooknum = NF_INET_PRE_ROUTING, | ||
241 | .priority = NF_IP6_PRI_NAT_DST, | ||
242 | }, | ||
243 | /* After packet filtering, change source */ | ||
244 | { | ||
245 | .hook = nf_nat_ipv6_out, | ||
246 | .owner = THIS_MODULE, | ||
247 | .pf = NFPROTO_IPV6, | ||
248 | .hooknum = NF_INET_POST_ROUTING, | ||
249 | .priority = NF_IP6_PRI_NAT_SRC, | ||
250 | }, | ||
251 | /* Before packet filtering, change destination */ | ||
252 | { | ||
253 | .hook = nf_nat_ipv6_local_fn, | ||
254 | .owner = THIS_MODULE, | ||
255 | .pf = NFPROTO_IPV6, | ||
256 | .hooknum = NF_INET_LOCAL_OUT, | ||
257 | .priority = NF_IP6_PRI_NAT_DST, | ||
258 | }, | ||
259 | /* After packet filtering, change source */ | ||
260 | { | ||
261 | .hook = nf_nat_ipv6_fn, | ||
262 | .owner = THIS_MODULE, | ||
263 | .pf = NFPROTO_IPV6, | ||
264 | .hooknum = NF_INET_LOCAL_IN, | ||
265 | .priority = NF_IP6_PRI_NAT_SRC, | ||
266 | }, | ||
267 | }; | ||
268 | |||
269 | static int __net_init ip6table_nat_net_init(struct net *net) | ||
270 | { | ||
271 | struct ip6t_replace *repl; | ||
272 | |||
273 | repl = ip6t_alloc_initial_table(&nf_nat_ipv6_table); | ||
274 | if (repl == NULL) | ||
275 | return -ENOMEM; | ||
276 | net->ipv6.ip6table_nat = ip6t_register_table(net, &nf_nat_ipv6_table, repl); | ||
277 | kfree(repl); | ||
278 | if (IS_ERR(net->ipv6.ip6table_nat)) | ||
279 | return PTR_ERR(net->ipv6.ip6table_nat); | ||
280 | return 0; | ||
281 | } | ||
282 | |||
283 | static void __net_exit ip6table_nat_net_exit(struct net *net) | ||
284 | { | ||
285 | ip6t_unregister_table(net, net->ipv6.ip6table_nat); | ||
286 | } | ||
287 | |||
288 | static struct pernet_operations ip6table_nat_net_ops = { | ||
289 | .init = ip6table_nat_net_init, | ||
290 | .exit = ip6table_nat_net_exit, | ||
291 | }; | ||
292 | |||
293 | static int __init ip6table_nat_init(void) | ||
294 | { | ||
295 | int err; | ||
296 | |||
297 | err = register_pernet_subsys(&ip6table_nat_net_ops); | ||
298 | if (err < 0) | ||
299 | goto err1; | ||
300 | |||
301 | err = nf_register_hooks(nf_nat_ipv6_ops, ARRAY_SIZE(nf_nat_ipv6_ops)); | ||
302 | if (err < 0) | ||
303 | goto err2; | ||
304 | return 0; | ||
305 | |||
306 | err2: | ||
307 | unregister_pernet_subsys(&ip6table_nat_net_ops); | ||
308 | err1: | ||
309 | return err; | ||
310 | } | ||
311 | |||
312 | static void __exit ip6table_nat_exit(void) | ||
313 | { | ||
314 | nf_unregister_hooks(nf_nat_ipv6_ops, ARRAY_SIZE(nf_nat_ipv6_ops)); | ||
315 | unregister_pernet_subsys(&ip6table_nat_net_ops); | ||
316 | } | ||
317 | |||
318 | module_init(ip6table_nat_init); | ||
319 | module_exit(ip6table_nat_exit); | ||
320 | |||
321 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c index 5b9926a011bd..60d1bddff7a0 100644 --- a/net/ipv6/netfilter/ip6table_raw.c +++ b/net/ipv6/netfilter/ip6table_raw.c | |||
@@ -40,9 +40,7 @@ static int __net_init ip6table_raw_net_init(struct net *net) | |||
40 | net->ipv6.ip6table_raw = | 40 | net->ipv6.ip6table_raw = |
41 | ip6t_register_table(net, &packet_raw, repl); | 41 | ip6t_register_table(net, &packet_raw, repl); |
42 | kfree(repl); | 42 | kfree(repl); |
43 | if (IS_ERR(net->ipv6.ip6table_raw)) | 43 | return PTR_RET(net->ipv6.ip6table_raw); |
44 | return PTR_ERR(net->ipv6.ip6table_raw); | ||
45 | return 0; | ||
46 | } | 44 | } |
47 | 45 | ||
48 | static void __net_exit ip6table_raw_net_exit(struct net *net) | 46 | static void __net_exit ip6table_raw_net_exit(struct net *net) |
diff --git a/net/ipv6/netfilter/ip6table_security.c b/net/ipv6/netfilter/ip6table_security.c index 91aa2b4d83c9..db155351339c 100644 --- a/net/ipv6/netfilter/ip6table_security.c +++ b/net/ipv6/netfilter/ip6table_security.c | |||
@@ -58,10 +58,7 @@ static int __net_init ip6table_security_net_init(struct net *net) | |||
58 | net->ipv6.ip6table_security = | 58 | net->ipv6.ip6table_security = |
59 | ip6t_register_table(net, &security_table, repl); | 59 | ip6t_register_table(net, &security_table, repl); |
60 | kfree(repl); | 60 | kfree(repl); |
61 | if (IS_ERR(net->ipv6.ip6table_security)) | 61 | return PTR_RET(net->ipv6.ip6table_security); |
62 | return PTR_ERR(net->ipv6.ip6table_security); | ||
63 | |||
64 | return 0; | ||
65 | } | 62 | } |
66 | 63 | ||
67 | static void __net_exit ip6table_security_net_exit(struct net *net) | 64 | static void __net_exit ip6table_security_net_exit(struct net *net) |
diff --git a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c index 4794f96cf2e0..8860d23e61cf 100644 --- a/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_conntrack_l3proto_ipv6.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include <net/netfilter/nf_conntrack_core.h> | 28 | #include <net/netfilter/nf_conntrack_core.h> |
29 | #include <net/netfilter/nf_conntrack_zones.h> | 29 | #include <net/netfilter/nf_conntrack_zones.h> |
30 | #include <net/netfilter/ipv6/nf_conntrack_ipv6.h> | 30 | #include <net/netfilter/ipv6/nf_conntrack_ipv6.h> |
31 | #include <net/netfilter/nf_nat_helper.h> | ||
31 | #include <net/netfilter/ipv6/nf_defrag_ipv6.h> | 32 | #include <net/netfilter/ipv6/nf_defrag_ipv6.h> |
32 | #include <net/netfilter/nf_log.h> | 33 | #include <net/netfilter/nf_log.h> |
33 | 34 | ||
@@ -64,82 +65,31 @@ static int ipv6_print_tuple(struct seq_file *s, | |||
64 | tuple->src.u3.ip6, tuple->dst.u3.ip6); | 65 | tuple->src.u3.ip6, tuple->dst.u3.ip6); |
65 | } | 66 | } |
66 | 67 | ||
67 | /* | ||
68 | * Based on ipv6_skip_exthdr() in net/ipv6/exthdr.c | ||
69 | * | ||
70 | * This function parses (probably truncated) exthdr set "hdr" | ||
71 | * of length "len". "nexthdrp" initially points to some place, | ||
72 | * where type of the first header can be found. | ||
73 | * | ||
74 | * It skips all well-known exthdrs, and returns pointer to the start | ||
75 | * of unparsable area i.e. the first header with unknown type. | ||
76 | * if success, *nexthdr is updated by type/protocol of this header. | ||
77 | * | ||
78 | * NOTES: - it may return pointer pointing beyond end of packet, | ||
79 | * if the last recognized header is truncated in the middle. | ||
80 | * - if packet is truncated, so that all parsed headers are skipped, | ||
81 | * it returns -1. | ||
82 | * - if packet is fragmented, return pointer of the fragment header. | ||
83 | * - ESP is unparsable for now and considered like | ||
84 | * normal payload protocol. | ||
85 | * - Note also special handling of AUTH header. Thanks to IPsec wizards. | ||
86 | */ | ||
87 | |||
88 | static int nf_ct_ipv6_skip_exthdr(const struct sk_buff *skb, int start, | ||
89 | u8 *nexthdrp, int len) | ||
90 | { | ||
91 | u8 nexthdr = *nexthdrp; | ||
92 | |||
93 | while (ipv6_ext_hdr(nexthdr)) { | ||
94 | struct ipv6_opt_hdr hdr; | ||
95 | int hdrlen; | ||
96 | |||
97 | if (len < (int)sizeof(struct ipv6_opt_hdr)) | ||
98 | return -1; | ||
99 | if (nexthdr == NEXTHDR_NONE) | ||
100 | break; | ||
101 | if (nexthdr == NEXTHDR_FRAGMENT) | ||
102 | break; | ||
103 | if (skb_copy_bits(skb, start, &hdr, sizeof(hdr))) | ||
104 | BUG(); | ||
105 | if (nexthdr == NEXTHDR_AUTH) | ||
106 | hdrlen = (hdr.hdrlen+2)<<2; | ||
107 | else | ||
108 | hdrlen = ipv6_optlen(&hdr); | ||
109 | |||
110 | nexthdr = hdr.nexthdr; | ||
111 | len -= hdrlen; | ||
112 | start += hdrlen; | ||
113 | } | ||
114 | |||
115 | *nexthdrp = nexthdr; | ||
116 | return start; | ||
117 | } | ||
118 | |||
119 | static int ipv6_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, | 68 | static int ipv6_get_l4proto(const struct sk_buff *skb, unsigned int nhoff, |
120 | unsigned int *dataoff, u_int8_t *protonum) | 69 | unsigned int *dataoff, u_int8_t *protonum) |
121 | { | 70 | { |
122 | unsigned int extoff = nhoff + sizeof(struct ipv6hdr); | 71 | unsigned int extoff = nhoff + sizeof(struct ipv6hdr); |
123 | unsigned char pnum; | 72 | __be16 frag_off; |
124 | int protoff; | 73 | int protoff; |
74 | u8 nexthdr; | ||
125 | 75 | ||
126 | if (skb_copy_bits(skb, nhoff + offsetof(struct ipv6hdr, nexthdr), | 76 | if (skb_copy_bits(skb, nhoff + offsetof(struct ipv6hdr, nexthdr), |
127 | &pnum, sizeof(pnum)) != 0) { | 77 | &nexthdr, sizeof(nexthdr)) != 0) { |
128 | pr_debug("ip6_conntrack_core: can't get nexthdr\n"); | 78 | pr_debug("ip6_conntrack_core: can't get nexthdr\n"); |
129 | return -NF_ACCEPT; | 79 | return -NF_ACCEPT; |
130 | } | 80 | } |
131 | protoff = nf_ct_ipv6_skip_exthdr(skb, extoff, &pnum, skb->len - extoff); | 81 | protoff = ipv6_skip_exthdr(skb, extoff, &nexthdr, &frag_off); |
132 | /* | 82 | /* |
133 | * (protoff == skb->len) mean that the packet doesn't have no data | 83 | * (protoff == skb->len) mean that the packet doesn't have no data |
134 | * except of IPv6 & ext headers. but it's tracked anyway. - YK | 84 | * except of IPv6 & ext headers. but it's tracked anyway. - YK |
135 | */ | 85 | */ |
136 | if ((protoff < 0) || (protoff > skb->len)) { | 86 | if (protoff < 0 || (frag_off & htons(~0x7)) != 0) { |
137 | pr_debug("ip6_conntrack_core: can't find proto in pkt\n"); | 87 | pr_debug("ip6_conntrack_core: can't find proto in pkt\n"); |
138 | return -NF_ACCEPT; | 88 | return -NF_ACCEPT; |
139 | } | 89 | } |
140 | 90 | ||
141 | *dataoff = protoff; | 91 | *dataoff = protoff; |
142 | *protonum = pnum; | 92 | *protonum = nexthdr; |
143 | return NF_ACCEPT; | 93 | return NF_ACCEPT; |
144 | } | 94 | } |
145 | 95 | ||
@@ -153,10 +103,10 @@ static unsigned int ipv6_helper(unsigned int hooknum, | |||
153 | const struct nf_conn_help *help; | 103 | const struct nf_conn_help *help; |
154 | const struct nf_conntrack_helper *helper; | 104 | const struct nf_conntrack_helper *helper; |
155 | enum ip_conntrack_info ctinfo; | 105 | enum ip_conntrack_info ctinfo; |
156 | unsigned int ret, protoff; | 106 | unsigned int ret; |
157 | unsigned int extoff = (u8 *)(ipv6_hdr(skb) + 1) - skb->data; | 107 | __be16 frag_off; |
158 | unsigned char pnum = ipv6_hdr(skb)->nexthdr; | 108 | int protoff; |
159 | 109 | u8 nexthdr; | |
160 | 110 | ||
161 | /* This is where we call the helper: as the packet goes out. */ | 111 | /* This is where we call the helper: as the packet goes out. */ |
162 | ct = nf_ct_get(skb, &ctinfo); | 112 | ct = nf_ct_get(skb, &ctinfo); |
@@ -171,9 +121,10 @@ static unsigned int ipv6_helper(unsigned int hooknum, | |||
171 | if (!helper) | 121 | if (!helper) |
172 | return NF_ACCEPT; | 122 | return NF_ACCEPT; |
173 | 123 | ||
174 | protoff = nf_ct_ipv6_skip_exthdr(skb, extoff, &pnum, | 124 | nexthdr = ipv6_hdr(skb)->nexthdr; |
175 | skb->len - extoff); | 125 | protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &nexthdr, |
176 | if (protoff > skb->len || pnum == NEXTHDR_FRAGMENT) { | 126 | &frag_off); |
127 | if (protoff < 0 || (frag_off & htons(~0x7)) != 0) { | ||
177 | pr_debug("proto header not found\n"); | 128 | pr_debug("proto header not found\n"); |
178 | return NF_ACCEPT; | 129 | return NF_ACCEPT; |
179 | } | 130 | } |
@@ -192,6 +143,36 @@ static unsigned int ipv6_confirm(unsigned int hooknum, | |||
192 | const struct net_device *out, | 143 | const struct net_device *out, |
193 | int (*okfn)(struct sk_buff *)) | 144 | int (*okfn)(struct sk_buff *)) |
194 | { | 145 | { |
146 | struct nf_conn *ct; | ||
147 | enum ip_conntrack_info ctinfo; | ||
148 | unsigned char pnum = ipv6_hdr(skb)->nexthdr; | ||
149 | int protoff; | ||
150 | __be16 frag_off; | ||
151 | |||
152 | ct = nf_ct_get(skb, &ctinfo); | ||
153 | if (!ct || ctinfo == IP_CT_RELATED_REPLY) | ||
154 | goto out; | ||
155 | |||
156 | protoff = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), &pnum, | ||
157 | &frag_off); | ||
158 | if (protoff < 0 || (frag_off & htons(~0x7)) != 0) { | ||
159 | pr_debug("proto header not found\n"); | ||
160 | goto out; | ||
161 | } | ||
162 | |||
163 | /* adjust seqs for loopback traffic only in outgoing direction */ | ||
164 | if (test_bit(IPS_SEQ_ADJUST_BIT, &ct->status) && | ||
165 | !nf_is_loopback_packet(skb)) { | ||
166 | typeof(nf_nat_seq_adjust_hook) seq_adjust; | ||
167 | |||
168 | seq_adjust = rcu_dereference(nf_nat_seq_adjust_hook); | ||
169 | if (!seq_adjust || | ||
170 | !seq_adjust(skb, ct, ctinfo, protoff)) { | ||
171 | NF_CT_STAT_INC_ATOMIC(nf_ct_net(ct), drop); | ||
172 | return NF_DROP; | ||
173 | } | ||
174 | } | ||
175 | out: | ||
195 | /* We've seen it coming out the other side: confirm it */ | 176 | /* We've seen it coming out the other side: confirm it */ |
196 | return nf_conntrack_confirm(skb); | 177 | return nf_conntrack_confirm(skb); |
197 | } | 178 | } |
@@ -199,9 +180,14 @@ static unsigned int ipv6_confirm(unsigned int hooknum, | |||
199 | static unsigned int __ipv6_conntrack_in(struct net *net, | 180 | static unsigned int __ipv6_conntrack_in(struct net *net, |
200 | unsigned int hooknum, | 181 | unsigned int hooknum, |
201 | struct sk_buff *skb, | 182 | struct sk_buff *skb, |
183 | const struct net_device *in, | ||
184 | const struct net_device *out, | ||
202 | int (*okfn)(struct sk_buff *)) | 185 | int (*okfn)(struct sk_buff *)) |
203 | { | 186 | { |
204 | struct sk_buff *reasm = skb->nfct_reasm; | 187 | struct sk_buff *reasm = skb->nfct_reasm; |
188 | const struct nf_conn_help *help; | ||
189 | struct nf_conn *ct; | ||
190 | enum ip_conntrack_info ctinfo; | ||
205 | 191 | ||
206 | /* This packet is fragmented and has reassembled packet. */ | 192 | /* This packet is fragmented and has reassembled packet. */ |
207 | if (reasm) { | 193 | if (reasm) { |
@@ -213,6 +199,25 @@ static unsigned int __ipv6_conntrack_in(struct net *net, | |||
213 | if (ret != NF_ACCEPT) | 199 | if (ret != NF_ACCEPT) |
214 | return ret; | 200 | return ret; |
215 | } | 201 | } |
202 | |||
203 | /* Conntrack helpers need the entire reassembled packet in the | ||
204 | * POST_ROUTING hook. In case of unconfirmed connections NAT | ||
205 | * might reassign a helper, so the entire packet is also | ||
206 | * required. | ||
207 | */ | ||
208 | ct = nf_ct_get(reasm, &ctinfo); | ||
209 | if (ct != NULL && !nf_ct_is_untracked(ct)) { | ||
210 | help = nfct_help(ct); | ||
211 | if ((help && help->helper) || !nf_ct_is_confirmed(ct)) { | ||
212 | nf_conntrack_get_reasm(skb); | ||
213 | NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, reasm, | ||
214 | (struct net_device *)in, | ||
215 | (struct net_device *)out, | ||
216 | okfn, NF_IP6_PRI_CONNTRACK + 1); | ||
217 | return NF_DROP_ERR(-ECANCELED); | ||
218 | } | ||
219 | } | ||
220 | |||
216 | nf_conntrack_get(reasm->nfct); | 221 | nf_conntrack_get(reasm->nfct); |
217 | skb->nfct = reasm->nfct; | 222 | skb->nfct = reasm->nfct; |
218 | skb->nfctinfo = reasm->nfctinfo; | 223 | skb->nfctinfo = reasm->nfctinfo; |
@@ -228,7 +233,7 @@ static unsigned int ipv6_conntrack_in(unsigned int hooknum, | |||
228 | const struct net_device *out, | 233 | const struct net_device *out, |
229 | int (*okfn)(struct sk_buff *)) | 234 | int (*okfn)(struct sk_buff *)) |
230 | { | 235 | { |
231 | return __ipv6_conntrack_in(dev_net(in), hooknum, skb, okfn); | 236 | return __ipv6_conntrack_in(dev_net(in), hooknum, skb, in, out, okfn); |
232 | } | 237 | } |
233 | 238 | ||
234 | static unsigned int ipv6_conntrack_local(unsigned int hooknum, | 239 | static unsigned int ipv6_conntrack_local(unsigned int hooknum, |
@@ -242,7 +247,7 @@ static unsigned int ipv6_conntrack_local(unsigned int hooknum, | |||
242 | net_notice_ratelimited("ipv6_conntrack_local: packet too short\n"); | 247 | net_notice_ratelimited("ipv6_conntrack_local: packet too short\n"); |
243 | return NF_ACCEPT; | 248 | return NF_ACCEPT; |
244 | } | 249 | } |
245 | return __ipv6_conntrack_in(dev_net(out), hooknum, skb, okfn); | 250 | return __ipv6_conntrack_in(dev_net(out), hooknum, skb, in, out, okfn); |
246 | } | 251 | } |
247 | 252 | ||
248 | static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = { | 253 | static struct nf_hook_ops ipv6_conntrack_ops[] __read_mostly = { |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index c9c78c2e666b..f94fb3ac2a79 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -190,6 +190,7 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
190 | const struct frag_hdr *fhdr, int nhoff) | 190 | const struct frag_hdr *fhdr, int nhoff) |
191 | { | 191 | { |
192 | struct sk_buff *prev, *next; | 192 | struct sk_buff *prev, *next; |
193 | unsigned int payload_len; | ||
193 | int offset, end; | 194 | int offset, end; |
194 | 195 | ||
195 | if (fq->q.last_in & INET_FRAG_COMPLETE) { | 196 | if (fq->q.last_in & INET_FRAG_COMPLETE) { |
@@ -197,8 +198,10 @@ static int nf_ct_frag6_queue(struct nf_ct_frag6_queue *fq, struct sk_buff *skb, | |||
197 | goto err; | 198 | goto err; |
198 | } | 199 | } |
199 | 200 | ||
201 | payload_len = ntohs(ipv6_hdr(skb)->payload_len); | ||
202 | |||
200 | offset = ntohs(fhdr->frag_off) & ~0x7; | 203 | offset = ntohs(fhdr->frag_off) & ~0x7; |
201 | end = offset + (ntohs(ipv6_hdr(skb)->payload_len) - | 204 | end = offset + (payload_len - |
202 | ((u8 *)(fhdr + 1) - (u8 *)(ipv6_hdr(skb) + 1))); | 205 | ((u8 *)(fhdr + 1) - (u8 *)(ipv6_hdr(skb) + 1))); |
203 | 206 | ||
204 | if ((unsigned int)end > IPV6_MAXPLEN) { | 207 | if ((unsigned int)end > IPV6_MAXPLEN) { |
@@ -307,6 +310,8 @@ found: | |||
307 | skb->dev = NULL; | 310 | skb->dev = NULL; |
308 | fq->q.stamp = skb->tstamp; | 311 | fq->q.stamp = skb->tstamp; |
309 | fq->q.meat += skb->len; | 312 | fq->q.meat += skb->len; |
313 | if (payload_len > fq->q.max_size) | ||
314 | fq->q.max_size = payload_len; | ||
310 | atomic_add(skb->truesize, &nf_init_frags.mem); | 315 | atomic_add(skb->truesize, &nf_init_frags.mem); |
311 | 316 | ||
312 | /* The first fragment. | 317 | /* The first fragment. |
@@ -412,10 +417,12 @@ nf_ct_frag6_reasm(struct nf_ct_frag6_queue *fq, struct net_device *dev) | |||
412 | } | 417 | } |
413 | atomic_sub(head->truesize, &nf_init_frags.mem); | 418 | atomic_sub(head->truesize, &nf_init_frags.mem); |
414 | 419 | ||
420 | head->local_df = 1; | ||
415 | head->next = NULL; | 421 | head->next = NULL; |
416 | head->dev = dev; | 422 | head->dev = dev; |
417 | head->tstamp = fq->q.stamp; | 423 | head->tstamp = fq->q.stamp; |
418 | ipv6_hdr(head)->payload_len = htons(payload_len); | 424 | ipv6_hdr(head)->payload_len = htons(payload_len); |
425 | IP6CB(head)->frag_max_size = sizeof(struct ipv6hdr) + fq->q.max_size; | ||
419 | 426 | ||
420 | /* Yes, and fold redundant checksum back. 8) */ | 427 | /* Yes, and fold redundant checksum back. 8) */ |
421 | if (head->ip_summed == CHECKSUM_COMPLETE) | 428 | if (head->ip_summed == CHECKSUM_COMPLETE) |
@@ -592,6 +599,7 @@ void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb, | |||
592 | int (*okfn)(struct sk_buff *)) | 599 | int (*okfn)(struct sk_buff *)) |
593 | { | 600 | { |
594 | struct sk_buff *s, *s2; | 601 | struct sk_buff *s, *s2; |
602 | unsigned int ret = 0; | ||
595 | 603 | ||
596 | for (s = NFCT_FRAG6_CB(skb)->orig; s;) { | 604 | for (s = NFCT_FRAG6_CB(skb)->orig; s;) { |
597 | nf_conntrack_put_reasm(s->nfct_reasm); | 605 | nf_conntrack_put_reasm(s->nfct_reasm); |
@@ -601,8 +609,13 @@ void nf_ct_frag6_output(unsigned int hooknum, struct sk_buff *skb, | |||
601 | s2 = s->next; | 609 | s2 = s->next; |
602 | s->next = NULL; | 610 | s->next = NULL; |
603 | 611 | ||
604 | NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, s, in, out, okfn, | 612 | if (ret != -ECANCELED) |
605 | NF_IP6_PRI_CONNTRACK_DEFRAG + 1); | 613 | ret = NF_HOOK_THRESH(NFPROTO_IPV6, hooknum, s, |
614 | in, out, okfn, | ||
615 | NF_IP6_PRI_CONNTRACK_DEFRAG + 1); | ||
616 | else | ||
617 | kfree_skb(s); | ||
618 | |||
606 | s = s2; | 619 | s = s2; |
607 | } | 620 | } |
608 | nf_conntrack_put_reasm(skb); | 621 | nf_conntrack_put_reasm(skb); |
diff --git a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c new file mode 100644 index 000000000000..81a2d1c3da8e --- /dev/null +++ b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c | |||
@@ -0,0 +1,287 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2011 Patrick McHardy <kaber@trash.net> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * Development of IPv6 NAT funded by Astaro. | ||
9 | */ | ||
10 | #include <linux/types.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/skbuff.h> | ||
13 | #include <linux/ipv6.h> | ||
14 | #include <linux/netfilter.h> | ||
15 | #include <linux/netfilter_ipv6.h> | ||
16 | #include <net/secure_seq.h> | ||
17 | #include <net/checksum.h> | ||
18 | #include <net/ip6_route.h> | ||
19 | #include <net/ipv6.h> | ||
20 | |||
21 | #include <net/netfilter/nf_conntrack_core.h> | ||
22 | #include <net/netfilter/nf_conntrack.h> | ||
23 | #include <net/netfilter/nf_nat_core.h> | ||
24 | #include <net/netfilter/nf_nat_l3proto.h> | ||
25 | #include <net/netfilter/nf_nat_l4proto.h> | ||
26 | |||
27 | static const struct nf_nat_l3proto nf_nat_l3proto_ipv6; | ||
28 | |||
29 | #ifdef CONFIG_XFRM | ||
30 | static void nf_nat_ipv6_decode_session(struct sk_buff *skb, | ||
31 | const struct nf_conn *ct, | ||
32 | enum ip_conntrack_dir dir, | ||
33 | unsigned long statusbit, | ||
34 | struct flowi *fl) | ||
35 | { | ||
36 | const struct nf_conntrack_tuple *t = &ct->tuplehash[dir].tuple; | ||
37 | struct flowi6 *fl6 = &fl->u.ip6; | ||
38 | |||
39 | if (ct->status & statusbit) { | ||
40 | fl6->daddr = t->dst.u3.in6; | ||
41 | if (t->dst.protonum == IPPROTO_TCP || | ||
42 | t->dst.protonum == IPPROTO_UDP || | ||
43 | t->dst.protonum == IPPROTO_UDPLITE || | ||
44 | t->dst.protonum == IPPROTO_DCCP || | ||
45 | t->dst.protonum == IPPROTO_SCTP) | ||
46 | fl6->fl6_dport = t->dst.u.all; | ||
47 | } | ||
48 | |||
49 | statusbit ^= IPS_NAT_MASK; | ||
50 | |||
51 | if (ct->status & statusbit) { | ||
52 | fl6->saddr = t->src.u3.in6; | ||
53 | if (t->dst.protonum == IPPROTO_TCP || | ||
54 | t->dst.protonum == IPPROTO_UDP || | ||
55 | t->dst.protonum == IPPROTO_UDPLITE || | ||
56 | t->dst.protonum == IPPROTO_DCCP || | ||
57 | t->dst.protonum == IPPROTO_SCTP) | ||
58 | fl6->fl6_sport = t->src.u.all; | ||
59 | } | ||
60 | } | ||
61 | #endif | ||
62 | |||
63 | static bool nf_nat_ipv6_in_range(const struct nf_conntrack_tuple *t, | ||
64 | const struct nf_nat_range *range) | ||
65 | { | ||
66 | return ipv6_addr_cmp(&t->src.u3.in6, &range->min_addr.in6) >= 0 && | ||
67 | ipv6_addr_cmp(&t->src.u3.in6, &range->max_addr.in6) <= 0; | ||
68 | } | ||
69 | |||
70 | static u32 nf_nat_ipv6_secure_port(const struct nf_conntrack_tuple *t, | ||
71 | __be16 dport) | ||
72 | { | ||
73 | return secure_ipv6_port_ephemeral(t->src.u3.ip6, t->dst.u3.ip6, dport); | ||
74 | } | ||
75 | |||
76 | static bool nf_nat_ipv6_manip_pkt(struct sk_buff *skb, | ||
77 | unsigned int iphdroff, | ||
78 | const struct nf_nat_l4proto *l4proto, | ||
79 | const struct nf_conntrack_tuple *target, | ||
80 | enum nf_nat_manip_type maniptype) | ||
81 | { | ||
82 | struct ipv6hdr *ipv6h; | ||
83 | __be16 frag_off; | ||
84 | int hdroff; | ||
85 | u8 nexthdr; | ||
86 | |||
87 | if (!skb_make_writable(skb, iphdroff + sizeof(*ipv6h))) | ||
88 | return false; | ||
89 | |||
90 | ipv6h = (void *)skb->data + iphdroff; | ||
91 | nexthdr = ipv6h->nexthdr; | ||
92 | hdroff = ipv6_skip_exthdr(skb, iphdroff + sizeof(*ipv6h), | ||
93 | &nexthdr, &frag_off); | ||
94 | if (hdroff < 0) | ||
95 | goto manip_addr; | ||
96 | |||
97 | if ((frag_off & htons(~0x7)) == 0 && | ||
98 | !l4proto->manip_pkt(skb, &nf_nat_l3proto_ipv6, iphdroff, hdroff, | ||
99 | target, maniptype)) | ||
100 | return false; | ||
101 | manip_addr: | ||
102 | if (maniptype == NF_NAT_MANIP_SRC) | ||
103 | ipv6h->saddr = target->src.u3.in6; | ||
104 | else | ||
105 | ipv6h->daddr = target->dst.u3.in6; | ||
106 | |||
107 | return true; | ||
108 | } | ||
109 | |||
110 | static void nf_nat_ipv6_csum_update(struct sk_buff *skb, | ||
111 | unsigned int iphdroff, __sum16 *check, | ||
112 | const struct nf_conntrack_tuple *t, | ||
113 | enum nf_nat_manip_type maniptype) | ||
114 | { | ||
115 | const struct ipv6hdr *ipv6h = (struct ipv6hdr *)(skb->data + iphdroff); | ||
116 | const struct in6_addr *oldip, *newip; | ||
117 | |||
118 | if (maniptype == NF_NAT_MANIP_SRC) { | ||
119 | oldip = &ipv6h->saddr; | ||
120 | newip = &t->src.u3.in6; | ||
121 | } else { | ||
122 | oldip = &ipv6h->daddr; | ||
123 | newip = &t->dst.u3.in6; | ||
124 | } | ||
125 | inet_proto_csum_replace16(check, skb, oldip->s6_addr32, | ||
126 | newip->s6_addr32, 1); | ||
127 | } | ||
128 | |||
129 | static void nf_nat_ipv6_csum_recalc(struct sk_buff *skb, | ||
130 | u8 proto, void *data, __sum16 *check, | ||
131 | int datalen, int oldlen) | ||
132 | { | ||
133 | const struct ipv6hdr *ipv6h = ipv6_hdr(skb); | ||
134 | struct rt6_info *rt = (struct rt6_info *)skb_dst(skb); | ||
135 | |||
136 | if (skb->ip_summed != CHECKSUM_PARTIAL) { | ||
137 | if (!(rt->rt6i_flags & RTF_LOCAL) && | ||
138 | (!skb->dev || skb->dev->features & NETIF_F_V6_CSUM)) { | ||
139 | skb->ip_summed = CHECKSUM_PARTIAL; | ||
140 | skb->csum_start = skb_headroom(skb) + | ||
141 | skb_network_offset(skb) + | ||
142 | (data - (void *)skb->data); | ||
143 | skb->csum_offset = (void *)check - data; | ||
144 | *check = ~csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, | ||
145 | datalen, proto, 0); | ||
146 | } else { | ||
147 | *check = 0; | ||
148 | *check = csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, | ||
149 | datalen, proto, | ||
150 | csum_partial(data, datalen, | ||
151 | 0)); | ||
152 | if (proto == IPPROTO_UDP && !*check) | ||
153 | *check = CSUM_MANGLED_0; | ||
154 | } | ||
155 | } else | ||
156 | inet_proto_csum_replace2(check, skb, | ||
157 | htons(oldlen), htons(datalen), 1); | ||
158 | } | ||
159 | |||
160 | static int nf_nat_ipv6_nlattr_to_range(struct nlattr *tb[], | ||
161 | struct nf_nat_range *range) | ||
162 | { | ||
163 | if (tb[CTA_NAT_V6_MINIP]) { | ||
164 | nla_memcpy(&range->min_addr.ip6, tb[CTA_NAT_V6_MINIP], | ||
165 | sizeof(struct in6_addr)); | ||
166 | range->flags |= NF_NAT_RANGE_MAP_IPS; | ||
167 | } | ||
168 | |||
169 | if (tb[CTA_NAT_V6_MAXIP]) | ||
170 | nla_memcpy(&range->max_addr.ip6, tb[CTA_NAT_V6_MAXIP], | ||
171 | sizeof(struct in6_addr)); | ||
172 | else | ||
173 | range->max_addr = range->min_addr; | ||
174 | |||
175 | return 0; | ||
176 | } | ||
177 | |||
178 | static const struct nf_nat_l3proto nf_nat_l3proto_ipv6 = { | ||
179 | .l3proto = NFPROTO_IPV6, | ||
180 | .secure_port = nf_nat_ipv6_secure_port, | ||
181 | .in_range = nf_nat_ipv6_in_range, | ||
182 | .manip_pkt = nf_nat_ipv6_manip_pkt, | ||
183 | .csum_update = nf_nat_ipv6_csum_update, | ||
184 | .csum_recalc = nf_nat_ipv6_csum_recalc, | ||
185 | .nlattr_to_range = nf_nat_ipv6_nlattr_to_range, | ||
186 | #ifdef CONFIG_XFRM | ||
187 | .decode_session = nf_nat_ipv6_decode_session, | ||
188 | #endif | ||
189 | }; | ||
190 | |||
191 | int nf_nat_icmpv6_reply_translation(struct sk_buff *skb, | ||
192 | struct nf_conn *ct, | ||
193 | enum ip_conntrack_info ctinfo, | ||
194 | unsigned int hooknum, | ||
195 | unsigned int hdrlen) | ||
196 | { | ||
197 | struct { | ||
198 | struct icmp6hdr icmp6; | ||
199 | struct ipv6hdr ip6; | ||
200 | } *inside; | ||
201 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | ||
202 | enum nf_nat_manip_type manip = HOOK2MANIP(hooknum); | ||
203 | const struct nf_nat_l4proto *l4proto; | ||
204 | struct nf_conntrack_tuple target; | ||
205 | unsigned long statusbit; | ||
206 | |||
207 | NF_CT_ASSERT(ctinfo == IP_CT_RELATED || ctinfo == IP_CT_RELATED_REPLY); | ||
208 | |||
209 | if (!skb_make_writable(skb, hdrlen + sizeof(*inside))) | ||
210 | return 0; | ||
211 | if (nf_ip6_checksum(skb, hooknum, hdrlen, IPPROTO_ICMPV6)) | ||
212 | return 0; | ||
213 | |||
214 | inside = (void *)skb->data + hdrlen; | ||
215 | if (inside->icmp6.icmp6_type == NDISC_REDIRECT) { | ||
216 | if ((ct->status & IPS_NAT_DONE_MASK) != IPS_NAT_DONE_MASK) | ||
217 | return 0; | ||
218 | if (ct->status & IPS_NAT_MASK) | ||
219 | return 0; | ||
220 | } | ||
221 | |||
222 | if (manip == NF_NAT_MANIP_SRC) | ||
223 | statusbit = IPS_SRC_NAT; | ||
224 | else | ||
225 | statusbit = IPS_DST_NAT; | ||
226 | |||
227 | /* Invert if this is reply direction */ | ||
228 | if (dir == IP_CT_DIR_REPLY) | ||
229 | statusbit ^= IPS_NAT_MASK; | ||
230 | |||
231 | if (!(ct->status & statusbit)) | ||
232 | return 1; | ||
233 | |||
234 | l4proto = __nf_nat_l4proto_find(NFPROTO_IPV6, inside->ip6.nexthdr); | ||
235 | if (!nf_nat_ipv6_manip_pkt(skb, hdrlen + sizeof(inside->icmp6), | ||
236 | l4proto, &ct->tuplehash[!dir].tuple, !manip)) | ||
237 | return 0; | ||
238 | |||
239 | if (skb->ip_summed != CHECKSUM_PARTIAL) { | ||
240 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); | ||
241 | inside = (void *)skb->data + hdrlen; | ||
242 | inside->icmp6.icmp6_cksum = 0; | ||
243 | inside->icmp6.icmp6_cksum = | ||
244 | csum_ipv6_magic(&ipv6h->saddr, &ipv6h->daddr, | ||
245 | skb->len - hdrlen, IPPROTO_ICMPV6, | ||
246 | csum_partial(&inside->icmp6, | ||
247 | skb->len - hdrlen, 0)); | ||
248 | } | ||
249 | |||
250 | nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple); | ||
251 | l4proto = __nf_nat_l4proto_find(NFPROTO_IPV6, IPPROTO_ICMPV6); | ||
252 | if (!nf_nat_ipv6_manip_pkt(skb, 0, l4proto, &target, manip)) | ||
253 | return 0; | ||
254 | |||
255 | return 1; | ||
256 | } | ||
257 | EXPORT_SYMBOL_GPL(nf_nat_icmpv6_reply_translation); | ||
258 | |||
259 | static int __init nf_nat_l3proto_ipv6_init(void) | ||
260 | { | ||
261 | int err; | ||
262 | |||
263 | err = nf_nat_l4proto_register(NFPROTO_IPV6, &nf_nat_l4proto_icmpv6); | ||
264 | if (err < 0) | ||
265 | goto err1; | ||
266 | err = nf_nat_l3proto_register(&nf_nat_l3proto_ipv6); | ||
267 | if (err < 0) | ||
268 | goto err2; | ||
269 | return err; | ||
270 | |||
271 | err2: | ||
272 | nf_nat_l4proto_unregister(NFPROTO_IPV6, &nf_nat_l4proto_icmpv6); | ||
273 | err1: | ||
274 | return err; | ||
275 | } | ||
276 | |||
277 | static void __exit nf_nat_l3proto_ipv6_exit(void) | ||
278 | { | ||
279 | nf_nat_l3proto_unregister(&nf_nat_l3proto_ipv6); | ||
280 | nf_nat_l4proto_unregister(NFPROTO_IPV6, &nf_nat_l4proto_icmpv6); | ||
281 | } | ||
282 | |||
283 | MODULE_LICENSE("GPL"); | ||
284 | MODULE_ALIAS("nf-nat-" __stringify(AF_INET6)); | ||
285 | |||
286 | module_init(nf_nat_l3proto_ipv6_init); | ||
287 | module_exit(nf_nat_l3proto_ipv6_exit); | ||
diff --git a/net/ipv6/netfilter/nf_nat_proto_icmpv6.c b/net/ipv6/netfilter/nf_nat_proto_icmpv6.c new file mode 100644 index 000000000000..5d6da784305b --- /dev/null +++ b/net/ipv6/netfilter/nf_nat_proto_icmpv6.c | |||
@@ -0,0 +1,90 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2011 Patrick Mchardy <kaber@trash.net> | ||
3 | * | ||
4 | * This program is free software; you can redistribute it and/or modify | ||
5 | * it under the terms of the GNU General Public License version 2 as | ||
6 | * published by the Free Software Foundation. | ||
7 | * | ||
8 | * Based on Rusty Russell's IPv4 ICMP NAT code. Development of IPv6 | ||
9 | * NAT funded by Astaro. | ||
10 | */ | ||
11 | |||
12 | #include <linux/types.h> | ||
13 | #include <linux/init.h> | ||
14 | #include <linux/icmpv6.h> | ||
15 | |||
16 | #include <linux/netfilter.h> | ||
17 | #include <net/netfilter/nf_nat.h> | ||
18 | #include <net/netfilter/nf_nat_core.h> | ||
19 | #include <net/netfilter/nf_nat_l3proto.h> | ||
20 | #include <net/netfilter/nf_nat_l4proto.h> | ||
21 | |||
22 | static bool | ||
23 | icmpv6_in_range(const struct nf_conntrack_tuple *tuple, | ||
24 | enum nf_nat_manip_type maniptype, | ||
25 | const union nf_conntrack_man_proto *min, | ||
26 | const union nf_conntrack_man_proto *max) | ||
27 | { | ||
28 | return ntohs(tuple->src.u.icmp.id) >= ntohs(min->icmp.id) && | ||
29 | ntohs(tuple->src.u.icmp.id) <= ntohs(max->icmp.id); | ||
30 | } | ||
31 | |||
32 | static void | ||
33 | icmpv6_unique_tuple(const struct nf_nat_l3proto *l3proto, | ||
34 | struct nf_conntrack_tuple *tuple, | ||
35 | const struct nf_nat_range *range, | ||
36 | enum nf_nat_manip_type maniptype, | ||
37 | const struct nf_conn *ct) | ||
38 | { | ||
39 | static u16 id; | ||
40 | unsigned int range_size; | ||
41 | unsigned int i; | ||
42 | |||
43 | range_size = ntohs(range->max_proto.icmp.id) - | ||
44 | ntohs(range->min_proto.icmp.id) + 1; | ||
45 | |||
46 | if (!(range->flags & NF_NAT_RANGE_PROTO_SPECIFIED)) | ||
47 | range_size = 0xffff; | ||
48 | |||
49 | for (i = 0; ; ++id) { | ||
50 | tuple->src.u.icmp.id = htons(ntohs(range->min_proto.icmp.id) + | ||
51 | (id % range_size)); | ||
52 | if (++i == range_size || !nf_nat_used_tuple(tuple, ct)) | ||
53 | return; | ||
54 | } | ||
55 | } | ||
56 | |||
57 | static bool | ||
58 | icmpv6_manip_pkt(struct sk_buff *skb, | ||
59 | const struct nf_nat_l3proto *l3proto, | ||
60 | unsigned int iphdroff, unsigned int hdroff, | ||
61 | const struct nf_conntrack_tuple *tuple, | ||
62 | enum nf_nat_manip_type maniptype) | ||
63 | { | ||
64 | struct icmp6hdr *hdr; | ||
65 | |||
66 | if (!skb_make_writable(skb, hdroff + sizeof(*hdr))) | ||
67 | return false; | ||
68 | |||
69 | hdr = (struct icmp6hdr *)(skb->data + hdroff); | ||
70 | l3proto->csum_update(skb, iphdroff, &hdr->icmp6_cksum, | ||
71 | tuple, maniptype); | ||
72 | if (hdr->icmp6_code == ICMPV6_ECHO_REQUEST || | ||
73 | hdr->icmp6_code == ICMPV6_ECHO_REPLY) { | ||
74 | inet_proto_csum_replace2(&hdr->icmp6_cksum, skb, | ||
75 | hdr->icmp6_identifier, | ||
76 | tuple->src.u.icmp.id, 0); | ||
77 | hdr->icmp6_identifier = tuple->src.u.icmp.id; | ||
78 | } | ||
79 | return true; | ||
80 | } | ||
81 | |||
82 | const struct nf_nat_l4proto nf_nat_l4proto_icmpv6 = { | ||
83 | .l4proto = IPPROTO_ICMPV6, | ||
84 | .manip_pkt = icmpv6_manip_pkt, | ||
85 | .in_range = icmpv6_in_range, | ||
86 | .unique_tuple = icmpv6_unique_tuple, | ||
87 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | ||
88 | .nlattr_to_range = nf_nat_l4proto_nlattr_to_range, | ||
89 | #endif | ||
90 | }; | ||
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index da2e92d05c15..745a32042950 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c | |||
@@ -307,10 +307,10 @@ static int __net_init ipv6_proc_init_net(struct net *net) | |||
307 | goto proc_dev_snmp6_fail; | 307 | goto proc_dev_snmp6_fail; |
308 | return 0; | 308 | return 0; |
309 | 309 | ||
310 | proc_dev_snmp6_fail: | ||
311 | proc_net_remove(net, "snmp6"); | ||
310 | proc_snmp6_fail: | 312 | proc_snmp6_fail: |
311 | proc_net_remove(net, "sockstat6"); | 313 | proc_net_remove(net, "sockstat6"); |
312 | proc_dev_snmp6_fail: | ||
313 | proc_net_remove(net, "dev_snmp6"); | ||
314 | return -ENOMEM; | 314 | return -ENOMEM; |
315 | } | 315 | } |
316 | 316 | ||
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index ef0579d5bca6..7af88ef01657 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -1251,7 +1251,8 @@ static void raw6_sock_seq_show(struct seq_file *seq, struct sock *sp, int i) | |||
1251 | sk_wmem_alloc_get(sp), | 1251 | sk_wmem_alloc_get(sp), |
1252 | sk_rmem_alloc_get(sp), | 1252 | sk_rmem_alloc_get(sp), |
1253 | 0, 0L, 0, | 1253 | 0, 0L, 0, |
1254 | sock_i_uid(sp), 0, | 1254 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)), |
1255 | 0, | ||
1255 | sock_i_ino(sp), | 1256 | sock_i_ino(sp), |
1256 | atomic_read(&sp->sk_refcnt), sp, atomic_read(&sp->sk_drops)); | 1257 | atomic_read(&sp->sk_refcnt), sp, atomic_read(&sp->sk_drops)); |
1257 | } | 1258 | } |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 8e80fd279100..0ddf2d132e7f 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -965,7 +965,7 @@ struct dst_entry * ip6_route_output(struct net *net, const struct sock *sk, | |||
965 | { | 965 | { |
966 | int flags = 0; | 966 | int flags = 0; |
967 | 967 | ||
968 | fl6->flowi6_iif = net->loopback_dev->ifindex; | 968 | fl6->flowi6_iif = LOOPBACK_IFINDEX; |
969 | 969 | ||
970 | if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl6->daddr)) | 970 | if ((sk && sk->sk_bound_dev_if) || rt6_need_strict(&fl6->daddr)) |
971 | flags |= RT6_LOOKUP_F_IFACE; | 971 | flags |= RT6_LOOKUP_F_IFACE; |
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index bb46061c813a..182ab9a85d6c 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c | |||
@@ -190,6 +190,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
190 | ireq = inet_rsk(req); | 190 | ireq = inet_rsk(req); |
191 | ireq6 = inet6_rsk(req); | 191 | ireq6 = inet6_rsk(req); |
192 | treq = tcp_rsk(req); | 192 | treq = tcp_rsk(req); |
193 | treq->listener = NULL; | ||
193 | 194 | ||
194 | if (security_inet_conn_request(sk, skb, req)) | 195 | if (security_inet_conn_request(sk, skb, req)) |
195 | goto out_free; | 196 | goto out_free; |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index c66b90f71c9b..09078b9bc6f6 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -94,6 +94,18 @@ static struct tcp_md5sig_key *tcp_v6_md5_do_lookup(struct sock *sk, | |||
94 | } | 94 | } |
95 | #endif | 95 | #endif |
96 | 96 | ||
97 | static void inet6_sk_rx_dst_set(struct sock *sk, const struct sk_buff *skb) | ||
98 | { | ||
99 | struct dst_entry *dst = skb_dst(skb); | ||
100 | const struct rt6_info *rt = (const struct rt6_info *)dst; | ||
101 | |||
102 | dst_hold(dst); | ||
103 | sk->sk_rx_dst = dst; | ||
104 | inet_sk(sk)->rx_dst_ifindex = skb->skb_iif; | ||
105 | if (rt->rt6i_node) | ||
106 | inet6_sk(sk)->rx_dst_cookie = rt->rt6i_node->fn_sernum; | ||
107 | } | ||
108 | |||
97 | static void tcp_v6_hash(struct sock *sk) | 109 | static void tcp_v6_hash(struct sock *sk) |
98 | { | 110 | { |
99 | if (sk->sk_state != TCP_CLOSE) { | 111 | if (sk->sk_state != TCP_CLOSE) { |
@@ -463,7 +475,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct dst_entry *dst, | |||
463 | if (!dst && (dst = inet6_csk_route_req(sk, fl6, req)) == NULL) | 475 | if (!dst && (dst = inet6_csk_route_req(sk, fl6, req)) == NULL) |
464 | goto done; | 476 | goto done; |
465 | 477 | ||
466 | skb = tcp_make_synack(sk, dst, req, rvp); | 478 | skb = tcp_make_synack(sk, dst, req, rvp, NULL); |
467 | 479 | ||
468 | if (skb) { | 480 | if (skb) { |
469 | __tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr); | 481 | __tcp_v6_send_check(skb, &treq->loc_addr, &treq->rmt_addr); |
@@ -975,7 +987,7 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk,struct sk_buff *skb) | |||
975 | &ipv6_hdr(skb)->saddr, | 987 | &ipv6_hdr(skb)->saddr, |
976 | &ipv6_hdr(skb)->daddr, inet6_iif(skb)); | 988 | &ipv6_hdr(skb)->daddr, inet6_iif(skb)); |
977 | if (req) | 989 | if (req) |
978 | return tcp_check_req(sk, skb, req, prev); | 990 | return tcp_check_req(sk, skb, req, prev, false); |
979 | 991 | ||
980 | nsk = __inet6_lookup_established(sock_net(sk), &tcp_hashinfo, | 992 | nsk = __inet6_lookup_established(sock_net(sk), &tcp_hashinfo, |
981 | &ipv6_hdr(skb)->saddr, th->source, | 993 | &ipv6_hdr(skb)->saddr, th->source, |
@@ -1167,6 +1179,7 @@ have_isn: | |||
1167 | want_cookie) | 1179 | want_cookie) |
1168 | goto drop_and_free; | 1180 | goto drop_and_free; |
1169 | 1181 | ||
1182 | tcp_rsk(req)->listener = NULL; | ||
1170 | inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); | 1183 | inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); |
1171 | return 0; | 1184 | return 0; |
1172 | 1185 | ||
@@ -1270,6 +1283,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1270 | 1283 | ||
1271 | newsk->sk_gso_type = SKB_GSO_TCPV6; | 1284 | newsk->sk_gso_type = SKB_GSO_TCPV6; |
1272 | __ip6_dst_store(newsk, dst, NULL, NULL); | 1285 | __ip6_dst_store(newsk, dst, NULL, NULL); |
1286 | inet6_sk_rx_dst_set(newsk, skb); | ||
1273 | 1287 | ||
1274 | newtcp6sk = (struct tcp6_sock *)newsk; | 1288 | newtcp6sk = (struct tcp6_sock *)newsk; |
1275 | inet_sk(newsk)->pinet6 = &newtcp6sk->inet6; | 1289 | inet_sk(newsk)->pinet6 = &newtcp6sk->inet6; |
@@ -1447,7 +1461,17 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
1447 | opt_skb = skb_clone(skb, sk_gfp_atomic(sk, GFP_ATOMIC)); | 1461 | opt_skb = skb_clone(skb, sk_gfp_atomic(sk, GFP_ATOMIC)); |
1448 | 1462 | ||
1449 | if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ | 1463 | if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ |
1464 | struct dst_entry *dst = sk->sk_rx_dst; | ||
1465 | |||
1450 | sock_rps_save_rxhash(sk, skb); | 1466 | sock_rps_save_rxhash(sk, skb); |
1467 | if (dst) { | ||
1468 | if (inet_sk(sk)->rx_dst_ifindex != skb->skb_iif || | ||
1469 | dst->ops->check(dst, np->rx_dst_cookie) == NULL) { | ||
1470 | dst_release(dst); | ||
1471 | sk->sk_rx_dst = NULL; | ||
1472 | } | ||
1473 | } | ||
1474 | |||
1451 | if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) | 1475 | if (tcp_rcv_established(sk, skb, tcp_hdr(skb), skb->len)) |
1452 | goto reset; | 1476 | goto reset; |
1453 | if (opt_skb) | 1477 | if (opt_skb) |
@@ -1705,9 +1729,9 @@ static void tcp_v6_early_demux(struct sk_buff *skb) | |||
1705 | struct dst_entry *dst = sk->sk_rx_dst; | 1729 | struct dst_entry *dst = sk->sk_rx_dst; |
1706 | struct inet_sock *icsk = inet_sk(sk); | 1730 | struct inet_sock *icsk = inet_sk(sk); |
1707 | if (dst) | 1731 | if (dst) |
1708 | dst = dst_check(dst, 0); | 1732 | dst = dst_check(dst, inet6_sk(sk)->rx_dst_cookie); |
1709 | if (dst && | 1733 | if (dst && |
1710 | icsk->rx_dst_ifindex == inet6_iif(skb)) | 1734 | icsk->rx_dst_ifindex == skb->skb_iif) |
1711 | skb_dst_set_noref(skb, dst); | 1735 | skb_dst_set_noref(skb, dst); |
1712 | } | 1736 | } |
1713 | } | 1737 | } |
@@ -1723,6 +1747,7 @@ static const struct inet_connection_sock_af_ops ipv6_specific = { | |||
1723 | .queue_xmit = inet6_csk_xmit, | 1747 | .queue_xmit = inet6_csk_xmit, |
1724 | .send_check = tcp_v6_send_check, | 1748 | .send_check = tcp_v6_send_check, |
1725 | .rebuild_header = inet6_sk_rebuild_header, | 1749 | .rebuild_header = inet6_sk_rebuild_header, |
1750 | .sk_rx_dst_set = inet6_sk_rx_dst_set, | ||
1726 | .conn_request = tcp_v6_conn_request, | 1751 | .conn_request = tcp_v6_conn_request, |
1727 | .syn_recv_sock = tcp_v6_syn_recv_sock, | 1752 | .syn_recv_sock = tcp_v6_syn_recv_sock, |
1728 | .net_header_len = sizeof(struct ipv6hdr), | 1753 | .net_header_len = sizeof(struct ipv6hdr), |
@@ -1754,6 +1779,7 @@ static const struct inet_connection_sock_af_ops ipv6_mapped = { | |||
1754 | .queue_xmit = ip_queue_xmit, | 1779 | .queue_xmit = ip_queue_xmit, |
1755 | .send_check = tcp_v4_send_check, | 1780 | .send_check = tcp_v4_send_check, |
1756 | .rebuild_header = inet_sk_rebuild_header, | 1781 | .rebuild_header = inet_sk_rebuild_header, |
1782 | .sk_rx_dst_set = inet_sk_rx_dst_set, | ||
1757 | .conn_request = tcp_v6_conn_request, | 1783 | .conn_request = tcp_v6_conn_request, |
1758 | .syn_recv_sock = tcp_v6_syn_recv_sock, | 1784 | .syn_recv_sock = tcp_v6_syn_recv_sock, |
1759 | .net_header_len = sizeof(struct iphdr), | 1785 | .net_header_len = sizeof(struct iphdr), |
@@ -1803,7 +1829,7 @@ static void tcp_v6_destroy_sock(struct sock *sk) | |||
1803 | #ifdef CONFIG_PROC_FS | 1829 | #ifdef CONFIG_PROC_FS |
1804 | /* Proc filesystem TCPv6 sock list dumping. */ | 1830 | /* Proc filesystem TCPv6 sock list dumping. */ |
1805 | static void get_openreq6(struct seq_file *seq, | 1831 | static void get_openreq6(struct seq_file *seq, |
1806 | const struct sock *sk, struct request_sock *req, int i, int uid) | 1832 | const struct sock *sk, struct request_sock *req, int i, kuid_t uid) |
1807 | { | 1833 | { |
1808 | int ttd = req->expires - jiffies; | 1834 | int ttd = req->expires - jiffies; |
1809 | const struct in6_addr *src = &inet6_rsk(req)->loc_addr; | 1835 | const struct in6_addr *src = &inet6_rsk(req)->loc_addr; |
@@ -1827,7 +1853,7 @@ static void get_openreq6(struct seq_file *seq, | |||
1827 | 1, /* timers active (only the expire timer) */ | 1853 | 1, /* timers active (only the expire timer) */ |
1828 | jiffies_to_clock_t(ttd), | 1854 | jiffies_to_clock_t(ttd), |
1829 | req->retrans, | 1855 | req->retrans, |
1830 | uid, | 1856 | from_kuid_munged(seq_user_ns(seq), uid), |
1831 | 0, /* non standard timer */ | 1857 | 0, /* non standard timer */ |
1832 | 0, /* open_requests have no inode */ | 1858 | 0, /* open_requests have no inode */ |
1833 | 0, req); | 1859 | 0, req); |
@@ -1875,9 +1901,9 @@ static void get_tcp6_sock(struct seq_file *seq, struct sock *sp, int i) | |||
1875 | tp->write_seq-tp->snd_una, | 1901 | tp->write_seq-tp->snd_una, |
1876 | (sp->sk_state == TCP_LISTEN) ? sp->sk_ack_backlog : (tp->rcv_nxt - tp->copied_seq), | 1902 | (sp->sk_state == TCP_LISTEN) ? sp->sk_ack_backlog : (tp->rcv_nxt - tp->copied_seq), |
1877 | timer_active, | 1903 | timer_active, |
1878 | jiffies_to_clock_t(timer_expires - jiffies), | 1904 | jiffies_delta_to_clock_t(timer_expires - jiffies), |
1879 | icsk->icsk_retransmits, | 1905 | icsk->icsk_retransmits, |
1880 | sock_i_uid(sp), | 1906 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)), |
1881 | icsk->icsk_probes_out, | 1907 | icsk->icsk_probes_out, |
1882 | sock_i_ino(sp), | 1908 | sock_i_ino(sp), |
1883 | atomic_read(&sp->sk_refcnt), sp, | 1909 | atomic_read(&sp->sk_refcnt), sp, |
@@ -1895,10 +1921,7 @@ static void get_timewait6_sock(struct seq_file *seq, | |||
1895 | const struct in6_addr *dest, *src; | 1921 | const struct in6_addr *dest, *src; |
1896 | __u16 destp, srcp; | 1922 | __u16 destp, srcp; |
1897 | const struct inet6_timewait_sock *tw6 = inet6_twsk((struct sock *)tw); | 1923 | const struct inet6_timewait_sock *tw6 = inet6_twsk((struct sock *)tw); |
1898 | int ttd = tw->tw_ttd - jiffies; | 1924 | long delta = tw->tw_ttd - jiffies; |
1899 | |||
1900 | if (ttd < 0) | ||
1901 | ttd = 0; | ||
1902 | 1925 | ||
1903 | dest = &tw6->tw_v6_daddr; | 1926 | dest = &tw6->tw_v6_daddr; |
1904 | src = &tw6->tw_v6_rcv_saddr; | 1927 | src = &tw6->tw_v6_rcv_saddr; |
@@ -1914,7 +1937,7 @@ static void get_timewait6_sock(struct seq_file *seq, | |||
1914 | dest->s6_addr32[0], dest->s6_addr32[1], | 1937 | dest->s6_addr32[0], dest->s6_addr32[1], |
1915 | dest->s6_addr32[2], dest->s6_addr32[3], destp, | 1938 | dest->s6_addr32[2], dest->s6_addr32[3], destp, |
1916 | tw->tw_substate, 0, 0, | 1939 | tw->tw_substate, 0, 0, |
1917 | 3, jiffies_to_clock_t(ttd), 0, 0, 0, 0, | 1940 | 3, jiffies_delta_to_clock_t(delta), 0, 0, 0, 0, |
1918 | atomic_read(&tw->tw_refcnt), tw); | 1941 | atomic_read(&tw->tw_refcnt), tw); |
1919 | } | 1942 | } |
1920 | 1943 | ||
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 99d0077b56b8..bbdff07eebe1 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -1458,7 +1458,8 @@ static void udp6_sock_seq_show(struct seq_file *seq, struct sock *sp, int bucket | |||
1458 | sk_wmem_alloc_get(sp), | 1458 | sk_wmem_alloc_get(sp), |
1459 | sk_rmem_alloc_get(sp), | 1459 | sk_rmem_alloc_get(sp), |
1460 | 0, 0L, 0, | 1460 | 0, 0L, 0, |
1461 | sock_i_uid(sp), 0, | 1461 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(sp)), |
1462 | 0, | ||
1462 | sock_i_ino(sp), | 1463 | sock_i_ino(sp), |
1463 | atomic_read(&sp->sk_refcnt), sp, | 1464 | atomic_read(&sp->sk_refcnt), sp, |
1464 | atomic_read(&sp->sk_drops)); | 1465 | atomic_read(&sp->sk_drops)); |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index ef39812107b1..f8c4c08ffb60 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
@@ -73,6 +73,13 @@ static int xfrm6_get_tos(const struct flowi *fl) | |||
73 | return 0; | 73 | return 0; |
74 | } | 74 | } |
75 | 75 | ||
76 | static void xfrm6_init_dst(struct net *net, struct xfrm_dst *xdst) | ||
77 | { | ||
78 | struct rt6_info *rt = (struct rt6_info *)xdst; | ||
79 | |||
80 | rt6_init_peer(rt, net->ipv6.peers); | ||
81 | } | ||
82 | |||
76 | static int xfrm6_init_path(struct xfrm_dst *path, struct dst_entry *dst, | 83 | static int xfrm6_init_path(struct xfrm_dst *path, struct dst_entry *dst, |
77 | int nfheader_len) | 84 | int nfheader_len) |
78 | { | 85 | { |
@@ -286,6 +293,7 @@ static struct xfrm_policy_afinfo xfrm6_policy_afinfo = { | |||
286 | .get_saddr = xfrm6_get_saddr, | 293 | .get_saddr = xfrm6_get_saddr, |
287 | .decode_session = _decode_session6, | 294 | .decode_session = _decode_session6, |
288 | .get_tos = xfrm6_get_tos, | 295 | .get_tos = xfrm6_get_tos, |
296 | .init_dst = xfrm6_init_dst, | ||
289 | .init_path = xfrm6_init_path, | 297 | .init_path = xfrm6_init_path, |
290 | .fill_dst = xfrm6_fill_dst, | 298 | .fill_dst = xfrm6_fill_dst, |
291 | .blackhole_route = ip6_blackhole_route, | 299 | .blackhole_route = ip6_blackhole_route, |
diff --git a/net/ipx/ipx_proc.c b/net/ipx/ipx_proc.c index f8ba30dfecae..02ff7f2f60d4 100644 --- a/net/ipx/ipx_proc.c +++ b/net/ipx/ipx_proc.c | |||
@@ -217,7 +217,8 @@ static int ipx_seq_socket_show(struct seq_file *seq, void *v) | |||
217 | seq_printf(seq, "%08X %08X %02X %03d\n", | 217 | seq_printf(seq, "%08X %08X %02X %03d\n", |
218 | sk_wmem_alloc_get(s), | 218 | sk_wmem_alloc_get(s), |
219 | sk_rmem_alloc_get(s), | 219 | sk_rmem_alloc_get(s), |
220 | s->sk_state, SOCK_INODE(s->sk_socket)->i_uid); | 220 | s->sk_state, |
221 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(s))); | ||
221 | out: | 222 | out: |
222 | return 0; | 223 | return 0; |
223 | } | 224 | } |
diff --git a/net/key/af_key.c b/net/key/af_key.c index 34e418508a67..334f93b8cfcb 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
@@ -3024,7 +3024,7 @@ static u32 get_acqseq(void) | |||
3024 | return res; | 3024 | return res; |
3025 | } | 3025 | } |
3026 | 3026 | ||
3027 | static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *xp, int dir) | 3027 | static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *xp) |
3028 | { | 3028 | { |
3029 | struct sk_buff *skb; | 3029 | struct sk_buff *skb; |
3030 | struct sadb_msg *hdr; | 3030 | struct sadb_msg *hdr; |
@@ -3105,7 +3105,7 @@ static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct | |||
3105 | pol->sadb_x_policy_len = sizeof(struct sadb_x_policy)/sizeof(uint64_t); | 3105 | pol->sadb_x_policy_len = sizeof(struct sadb_x_policy)/sizeof(uint64_t); |
3106 | pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY; | 3106 | pol->sadb_x_policy_exttype = SADB_X_EXT_POLICY; |
3107 | pol->sadb_x_policy_type = IPSEC_POLICY_IPSEC; | 3107 | pol->sadb_x_policy_type = IPSEC_POLICY_IPSEC; |
3108 | pol->sadb_x_policy_dir = dir+1; | 3108 | pol->sadb_x_policy_dir = XFRM_POLICY_OUT + 1; |
3109 | pol->sadb_x_policy_id = xp->index; | 3109 | pol->sadb_x_policy_id = xp->index; |
3110 | 3110 | ||
3111 | /* Set sadb_comb's. */ | 3111 | /* Set sadb_comb's. */ |
@@ -3661,7 +3661,7 @@ static int pfkey_seq_show(struct seq_file *f, void *v) | |||
3661 | atomic_read(&s->sk_refcnt), | 3661 | atomic_read(&s->sk_refcnt), |
3662 | sk_rmem_alloc_get(s), | 3662 | sk_rmem_alloc_get(s), |
3663 | sk_wmem_alloc_get(s), | 3663 | sk_wmem_alloc_get(s), |
3664 | sock_i_uid(s), | 3664 | from_kuid_munged(seq_user_ns(f), sock_i_uid(s)), |
3665 | sock_i_ino(s) | 3665 | sock_i_ino(s) |
3666 | ); | 3666 | ); |
3667 | return 0; | 3667 | return 0; |
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index 393355d37b47..513cab08a986 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c | |||
@@ -1347,11 +1347,10 @@ static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel) | |||
1347 | /* Remove from tunnel list */ | 1347 | /* Remove from tunnel list */ |
1348 | spin_lock_bh(&pn->l2tp_tunnel_list_lock); | 1348 | spin_lock_bh(&pn->l2tp_tunnel_list_lock); |
1349 | list_del_rcu(&tunnel->list); | 1349 | list_del_rcu(&tunnel->list); |
1350 | kfree_rcu(tunnel, rcu); | ||
1350 | spin_unlock_bh(&pn->l2tp_tunnel_list_lock); | 1351 | spin_unlock_bh(&pn->l2tp_tunnel_list_lock); |
1351 | synchronize_rcu(); | ||
1352 | 1352 | ||
1353 | atomic_dec(&l2tp_tunnel_count); | 1353 | atomic_dec(&l2tp_tunnel_count); |
1354 | kfree(tunnel); | ||
1355 | } | 1354 | } |
1356 | 1355 | ||
1357 | /* Create a socket for the tunnel, if one isn't set up by | 1356 | /* Create a socket for the tunnel, if one isn't set up by |
diff --git a/net/l2tp/l2tp_core.h b/net/l2tp/l2tp_core.h index a38ec6cdeee1..56d583e083a7 100644 --- a/net/l2tp/l2tp_core.h +++ b/net/l2tp/l2tp_core.h | |||
@@ -163,6 +163,7 @@ struct l2tp_tunnel_cfg { | |||
163 | 163 | ||
164 | struct l2tp_tunnel { | 164 | struct l2tp_tunnel { |
165 | int magic; /* Should be L2TP_TUNNEL_MAGIC */ | 165 | int magic; /* Should be L2TP_TUNNEL_MAGIC */ |
166 | struct rcu_head rcu; | ||
166 | rwlock_t hlist_lock; /* protect session_hlist */ | 167 | rwlock_t hlist_lock; /* protect session_hlist */ |
167 | struct hlist_head session_hlist[L2TP_HASH_SIZE]; | 168 | struct hlist_head session_hlist[L2TP_HASH_SIZE]; |
168 | /* hashed list of sessions, | 169 | /* hashed list of sessions, |
diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c index 35e1e4bde587..927547171bc7 100644 --- a/net/l2tp/l2tp_ip6.c +++ b/net/l2tp/l2tp_ip6.c | |||
@@ -410,6 +410,7 @@ static int l2tp_ip6_getname(struct socket *sock, struct sockaddr *uaddr, | |||
410 | lsa->l2tp_family = AF_INET6; | 410 | lsa->l2tp_family = AF_INET6; |
411 | lsa->l2tp_flowinfo = 0; | 411 | lsa->l2tp_flowinfo = 0; |
412 | lsa->l2tp_scope_id = 0; | 412 | lsa->l2tp_scope_id = 0; |
413 | lsa->l2tp_unused = 0; | ||
413 | if (peer) { | 414 | if (peer) { |
414 | if (!lsk->peer_conn_id) | 415 | if (!lsk->peer_conn_id) |
415 | return -ENOTCONN; | 416 | return -ENOTCONN; |
diff --git a/net/llc/af_llc.c b/net/llc/af_llc.c index f6fe4d400502..c2190005a114 100644 --- a/net/llc/af_llc.c +++ b/net/llc/af_llc.c | |||
@@ -969,14 +969,13 @@ static int llc_ui_getname(struct socket *sock, struct sockaddr *uaddr, | |||
969 | struct sockaddr_llc sllc; | 969 | struct sockaddr_llc sllc; |
970 | struct sock *sk = sock->sk; | 970 | struct sock *sk = sock->sk; |
971 | struct llc_sock *llc = llc_sk(sk); | 971 | struct llc_sock *llc = llc_sk(sk); |
972 | int rc = 0; | 972 | int rc = -EBADF; |
973 | 973 | ||
974 | memset(&sllc, 0, sizeof(sllc)); | 974 | memset(&sllc, 0, sizeof(sllc)); |
975 | lock_sock(sk); | 975 | lock_sock(sk); |
976 | if (sock_flag(sk, SOCK_ZAPPED)) | 976 | if (sock_flag(sk, SOCK_ZAPPED)) |
977 | goto out; | 977 | goto out; |
978 | *uaddrlen = sizeof(sllc); | 978 | *uaddrlen = sizeof(sllc); |
979 | memset(uaddr, 0, *uaddrlen); | ||
980 | if (peer) { | 979 | if (peer) { |
981 | rc = -ENOTCONN; | 980 | rc = -ENOTCONN; |
982 | if (sk->sk_state != TCP_ESTABLISHED) | 981 | if (sk->sk_state != TCP_ESTABLISHED) |
@@ -1206,7 +1205,7 @@ static int __init llc2_init(void) | |||
1206 | rc = llc_proc_init(); | 1205 | rc = llc_proc_init(); |
1207 | if (rc != 0) { | 1206 | if (rc != 0) { |
1208 | printk(llc_proc_err_msg); | 1207 | printk(llc_proc_err_msg); |
1209 | goto out_unregister_llc_proto; | 1208 | goto out_station; |
1210 | } | 1209 | } |
1211 | rc = llc_sysctl_init(); | 1210 | rc = llc_sysctl_init(); |
1212 | if (rc) { | 1211 | if (rc) { |
@@ -1226,7 +1225,8 @@ out_sysctl: | |||
1226 | llc_sysctl_exit(); | 1225 | llc_sysctl_exit(); |
1227 | out_proc: | 1226 | out_proc: |
1228 | llc_proc_exit(); | 1227 | llc_proc_exit(); |
1229 | out_unregister_llc_proto: | 1228 | out_station: |
1229 | llc_station_exit(); | ||
1230 | proto_unregister(&llc_proto); | 1230 | proto_unregister(&llc_proto); |
1231 | goto out; | 1231 | goto out; |
1232 | } | 1232 | } |
diff --git a/net/llc/llc_input.c b/net/llc/llc_input.c index e32cab44ea95..dd3e83328ad5 100644 --- a/net/llc/llc_input.c +++ b/net/llc/llc_input.c | |||
@@ -42,6 +42,7 @@ static void (*llc_type_handlers[2])(struct llc_sap *sap, | |||
42 | void llc_add_pack(int type, void (*handler)(struct llc_sap *sap, | 42 | void llc_add_pack(int type, void (*handler)(struct llc_sap *sap, |
43 | struct sk_buff *skb)) | 43 | struct sk_buff *skb)) |
44 | { | 44 | { |
45 | smp_wmb(); /* ensure initialisation is complete before it's called */ | ||
45 | if (type == LLC_DEST_SAP || type == LLC_DEST_CONN) | 46 | if (type == LLC_DEST_SAP || type == LLC_DEST_CONN) |
46 | llc_type_handlers[type - 1] = handler; | 47 | llc_type_handlers[type - 1] = handler; |
47 | } | 48 | } |
@@ -50,11 +51,19 @@ void llc_remove_pack(int type) | |||
50 | { | 51 | { |
51 | if (type == LLC_DEST_SAP || type == LLC_DEST_CONN) | 52 | if (type == LLC_DEST_SAP || type == LLC_DEST_CONN) |
52 | llc_type_handlers[type - 1] = NULL; | 53 | llc_type_handlers[type - 1] = NULL; |
54 | synchronize_net(); | ||
53 | } | 55 | } |
54 | 56 | ||
55 | void llc_set_station_handler(void (*handler)(struct sk_buff *skb)) | 57 | void llc_set_station_handler(void (*handler)(struct sk_buff *skb)) |
56 | { | 58 | { |
59 | /* Ensure initialisation is complete before it's called */ | ||
60 | if (handler) | ||
61 | smp_wmb(); | ||
62 | |||
57 | llc_station_handler = handler; | 63 | llc_station_handler = handler; |
64 | |||
65 | if (!handler) | ||
66 | synchronize_net(); | ||
58 | } | 67 | } |
59 | 68 | ||
60 | /** | 69 | /** |
@@ -150,6 +159,8 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev, | |||
150 | int dest; | 159 | int dest; |
151 | int (*rcv)(struct sk_buff *, struct net_device *, | 160 | int (*rcv)(struct sk_buff *, struct net_device *, |
152 | struct packet_type *, struct net_device *); | 161 | struct packet_type *, struct net_device *); |
162 | void (*sta_handler)(struct sk_buff *skb); | ||
163 | void (*sap_handler)(struct llc_sap *sap, struct sk_buff *skb); | ||
153 | 164 | ||
154 | if (!net_eq(dev_net(dev), &init_net)) | 165 | if (!net_eq(dev_net(dev), &init_net)) |
155 | goto drop; | 166 | goto drop; |
@@ -182,7 +193,8 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev, | |||
182 | */ | 193 | */ |
183 | rcv = rcu_dereference(sap->rcv_func); | 194 | rcv = rcu_dereference(sap->rcv_func); |
184 | dest = llc_pdu_type(skb); | 195 | dest = llc_pdu_type(skb); |
185 | if (unlikely(!dest || !llc_type_handlers[dest - 1])) { | 196 | sap_handler = dest ? ACCESS_ONCE(llc_type_handlers[dest - 1]) : NULL; |
197 | if (unlikely(!sap_handler)) { | ||
186 | if (rcv) | 198 | if (rcv) |
187 | rcv(skb, dev, pt, orig_dev); | 199 | rcv(skb, dev, pt, orig_dev); |
188 | else | 200 | else |
@@ -193,7 +205,7 @@ int llc_rcv(struct sk_buff *skb, struct net_device *dev, | |||
193 | if (cskb) | 205 | if (cskb) |
194 | rcv(cskb, dev, pt, orig_dev); | 206 | rcv(cskb, dev, pt, orig_dev); |
195 | } | 207 | } |
196 | llc_type_handlers[dest - 1](sap, skb); | 208 | sap_handler(sap, skb); |
197 | } | 209 | } |
198 | llc_sap_put(sap); | 210 | llc_sap_put(sap); |
199 | out: | 211 | out: |
@@ -202,9 +214,10 @@ drop: | |||
202 | kfree_skb(skb); | 214 | kfree_skb(skb); |
203 | goto out; | 215 | goto out; |
204 | handle_station: | 216 | handle_station: |
205 | if (!llc_station_handler) | 217 | sta_handler = ACCESS_ONCE(llc_station_handler); |
218 | if (!sta_handler) | ||
206 | goto drop; | 219 | goto drop; |
207 | llc_station_handler(skb); | 220 | sta_handler(skb); |
208 | goto out; | 221 | goto out; |
209 | } | 222 | } |
210 | 223 | ||
diff --git a/net/llc/llc_proc.c b/net/llc/llc_proc.c index a1839c004357..7b4799cfbf8d 100644 --- a/net/llc/llc_proc.c +++ b/net/llc/llc_proc.c | |||
@@ -151,7 +151,7 @@ static int llc_seq_socket_show(struct seq_file *seq, void *v) | |||
151 | sk_wmem_alloc_get(sk), | 151 | sk_wmem_alloc_get(sk), |
152 | sk_rmem_alloc_get(sk) - llc->copied_seq, | 152 | sk_rmem_alloc_get(sk) - llc->copied_seq, |
153 | sk->sk_state, | 153 | sk->sk_state, |
154 | sk->sk_socket ? SOCK_INODE(sk->sk_socket)->i_uid : -1, | 154 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)), |
155 | llc->link); | 155 | llc->link); |
156 | out: | 156 | out: |
157 | return 0; | 157 | return 0; |
diff --git a/net/llc/llc_station.c b/net/llc/llc_station.c index 39a8d8924b9c..b2f2bac2c2a2 100644 --- a/net/llc/llc_station.c +++ b/net/llc/llc_station.c | |||
@@ -268,7 +268,7 @@ static int llc_station_ac_send_null_dsap_xid_c(struct sk_buff *skb) | |||
268 | out: | 268 | out: |
269 | return rc; | 269 | return rc; |
270 | free: | 270 | free: |
271 | kfree_skb(skb); | 271 | kfree_skb(nskb); |
272 | goto out; | 272 | goto out; |
273 | } | 273 | } |
274 | 274 | ||
@@ -293,7 +293,7 @@ static int llc_station_ac_send_xid_r(struct sk_buff *skb) | |||
293 | out: | 293 | out: |
294 | return rc; | 294 | return rc; |
295 | free: | 295 | free: |
296 | kfree_skb(skb); | 296 | kfree_skb(nskb); |
297 | goto out; | 297 | goto out; |
298 | } | 298 | } |
299 | 299 | ||
@@ -322,7 +322,7 @@ static int llc_station_ac_send_test_r(struct sk_buff *skb) | |||
322 | out: | 322 | out: |
323 | return rc; | 323 | return rc; |
324 | free: | 324 | free: |
325 | kfree_skb(skb); | 325 | kfree_skb(nskb); |
326 | goto out; | 326 | goto out; |
327 | } | 327 | } |
328 | 328 | ||
@@ -687,12 +687,8 @@ static void llc_station_rcv(struct sk_buff *skb) | |||
687 | llc_station_state_process(skb); | 687 | llc_station_state_process(skb); |
688 | } | 688 | } |
689 | 689 | ||
690 | int __init llc_station_init(void) | 690 | void __init llc_station_init(void) |
691 | { | 691 | { |
692 | int rc = -ENOBUFS; | ||
693 | struct sk_buff *skb; | ||
694 | struct llc_station_state_ev *ev; | ||
695 | |||
696 | skb_queue_head_init(&llc_main_station.mac_pdu_q); | 692 | skb_queue_head_init(&llc_main_station.mac_pdu_q); |
697 | skb_queue_head_init(&llc_main_station.ev_q.list); | 693 | skb_queue_head_init(&llc_main_station.ev_q.list); |
698 | spin_lock_init(&llc_main_station.ev_q.lock); | 694 | spin_lock_init(&llc_main_station.ev_q.lock); |
@@ -700,23 +696,12 @@ int __init llc_station_init(void) | |||
700 | (unsigned long)&llc_main_station); | 696 | (unsigned long)&llc_main_station); |
701 | llc_main_station.ack_timer.expires = jiffies + | 697 | llc_main_station.ack_timer.expires = jiffies + |
702 | sysctl_llc_station_ack_timeout; | 698 | sysctl_llc_station_ack_timeout; |
703 | skb = alloc_skb(0, GFP_ATOMIC); | ||
704 | if (!skb) | ||
705 | goto out; | ||
706 | rc = 0; | ||
707 | llc_set_station_handler(llc_station_rcv); | ||
708 | ev = llc_station_ev(skb); | ||
709 | memset(ev, 0, sizeof(*ev)); | ||
710 | llc_main_station.maximum_retry = 1; | 699 | llc_main_station.maximum_retry = 1; |
711 | llc_main_station.state = LLC_STATION_STATE_DOWN; | 700 | llc_main_station.state = LLC_STATION_STATE_UP; |
712 | ev->type = LLC_STATION_EV_TYPE_SIMPLE; | 701 | llc_set_station_handler(llc_station_rcv); |
713 | ev->prim_type = LLC_STATION_EV_ENABLE_WITHOUT_DUP_ADDR_CHECK; | ||
714 | rc = llc_station_next_state(skb); | ||
715 | out: | ||
716 | return rc; | ||
717 | } | 702 | } |
718 | 703 | ||
719 | void __exit llc_station_exit(void) | 704 | void llc_station_exit(void) |
720 | { | 705 | { |
721 | llc_set_station_handler(NULL); | 706 | llc_set_station_handler(NULL); |
722 | } | 707 | } |
diff --git a/net/mac80211/aes_cmac.c b/net/mac80211/aes_cmac.c index 8dfd70d8fcfb..a04752e91023 100644 --- a/net/mac80211/aes_cmac.c +++ b/net/mac80211/aes_cmac.c | |||
@@ -38,14 +38,10 @@ static void gf_mulx(u8 *pad) | |||
38 | static void aes_128_cmac_vector(struct crypto_cipher *tfm, size_t num_elem, | 38 | static void aes_128_cmac_vector(struct crypto_cipher *tfm, size_t num_elem, |
39 | const u8 *addr[], const size_t *len, u8 *mac) | 39 | const u8 *addr[], const size_t *len, u8 *mac) |
40 | { | 40 | { |
41 | u8 scratch[2 * AES_BLOCK_SIZE]; | 41 | u8 cbc[AES_BLOCK_SIZE], pad[AES_BLOCK_SIZE]; |
42 | u8 *cbc, *pad; | ||
43 | const u8 *pos, *end; | 42 | const u8 *pos, *end; |
44 | size_t i, e, left, total_len; | 43 | size_t i, e, left, total_len; |
45 | 44 | ||
46 | cbc = scratch; | ||
47 | pad = scratch + AES_BLOCK_SIZE; | ||
48 | |||
49 | memset(cbc, 0, AES_BLOCK_SIZE); | 45 | memset(cbc, 0, AES_BLOCK_SIZE); |
50 | 46 | ||
51 | total_len = 0; | 47 | total_len = 0; |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index d41974aacf51..929f897a8ded 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -102,6 +102,18 @@ static int ieee80211_change_iface(struct wiphy *wiphy, | |||
102 | return 0; | 102 | return 0; |
103 | } | 103 | } |
104 | 104 | ||
105 | static int ieee80211_start_p2p_device(struct wiphy *wiphy, | ||
106 | struct wireless_dev *wdev) | ||
107 | { | ||
108 | return ieee80211_do_open(wdev, true); | ||
109 | } | ||
110 | |||
111 | static void ieee80211_stop_p2p_device(struct wiphy *wiphy, | ||
112 | struct wireless_dev *wdev) | ||
113 | { | ||
114 | ieee80211_sdata_stop(IEEE80211_WDEV_TO_SUB_IF(wdev)); | ||
115 | } | ||
116 | |||
105 | static int ieee80211_set_noack_map(struct wiphy *wiphy, | 117 | static int ieee80211_set_noack_map(struct wiphy *wiphy, |
106 | struct net_device *dev, | 118 | struct net_device *dev, |
107 | u16 noack_map) | 119 | u16 noack_map) |
@@ -330,7 +342,7 @@ static void rate_idx_to_bitrate(struct rate_info *rate, struct sta_info *sta, in | |||
330 | if (!(rate->flags & RATE_INFO_FLAGS_MCS)) { | 342 | if (!(rate->flags & RATE_INFO_FLAGS_MCS)) { |
331 | struct ieee80211_supported_band *sband; | 343 | struct ieee80211_supported_band *sband; |
332 | sband = sta->local->hw.wiphy->bands[ | 344 | sband = sta->local->hw.wiphy->bands[ |
333 | sta->local->hw.conf.channel->band]; | 345 | sta->local->oper_channel->band]; |
334 | rate->legacy = sband->bitrates[idx].bitrate; | 346 | rate->legacy = sband->bitrates[idx].bitrate; |
335 | } else | 347 | } else |
336 | rate->mcs = idx; | 348 | rate->mcs = idx; |
@@ -725,25 +737,23 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy, | |||
725 | static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, | 737 | static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, |
726 | const u8 *resp, size_t resp_len) | 738 | const u8 *resp, size_t resp_len) |
727 | { | 739 | { |
728 | struct sk_buff *new, *old; | 740 | struct probe_resp *new, *old; |
729 | 741 | ||
730 | if (!resp || !resp_len) | 742 | if (!resp || !resp_len) |
731 | return 1; | 743 | return 1; |
732 | 744 | ||
733 | old = rtnl_dereference(sdata->u.ap.probe_resp); | 745 | old = rtnl_dereference(sdata->u.ap.probe_resp); |
734 | 746 | ||
735 | new = dev_alloc_skb(resp_len); | 747 | new = kzalloc(sizeof(struct probe_resp) + resp_len, GFP_KERNEL); |
736 | if (!new) | 748 | if (!new) |
737 | return -ENOMEM; | 749 | return -ENOMEM; |
738 | 750 | ||
739 | memcpy(skb_put(new, resp_len), resp, resp_len); | 751 | new->len = resp_len; |
752 | memcpy(new->data, resp, resp_len); | ||
740 | 753 | ||
741 | rcu_assign_pointer(sdata->u.ap.probe_resp, new); | 754 | rcu_assign_pointer(sdata->u.ap.probe_resp, new); |
742 | if (old) { | 755 | if (old) |
743 | /* TODO: use call_rcu() */ | 756 | kfree_rcu(old, rcu_head); |
744 | synchronize_rcu(); | ||
745 | dev_kfree_skb(old); | ||
746 | } | ||
747 | 757 | ||
748 | return 0; | 758 | return 0; |
749 | } | 759 | } |
@@ -950,7 +960,7 @@ static void ieee80211_send_layer2_update(struct sta_info *sta) | |||
950 | /* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID) | 960 | /* 802.2 Type 1 Logical Link Control (LLC) Exchange Identifier (XID) |
951 | * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */ | 961 | * Update response frame; IEEE Std 802.2-1998, 5.4.1.2.1 */ |
952 | 962 | ||
953 | memset(msg->da, 0xff, ETH_ALEN); | 963 | eth_broadcast_addr(msg->da); |
954 | memcpy(msg->sa, sta->sta.addr, ETH_ALEN); | 964 | memcpy(msg->sa, sta->sta.addr, ETH_ALEN); |
955 | msg->len = htons(6); | 965 | msg->len = htons(6); |
956 | msg->dsap = 0; | 966 | msg->dsap = 0; |
@@ -1285,9 +1295,10 @@ static int ieee80211_change_station(struct wiphy *wiphy, | |||
1285 | mutex_unlock(&local->sta_mtx); | 1295 | mutex_unlock(&local->sta_mtx); |
1286 | 1296 | ||
1287 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | 1297 | if (sdata->vif.type == NL80211_IFTYPE_STATION && |
1288 | params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) | 1298 | params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) { |
1289 | ieee80211_recalc_ps(local, -1); | 1299 | ieee80211_recalc_ps(local, -1); |
1290 | 1300 | ieee80211_recalc_ps_vif(sdata); | |
1301 | } | ||
1291 | return 0; | 1302 | return 0; |
1292 | } | 1303 | } |
1293 | 1304 | ||
@@ -1661,7 +1672,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy, | |||
1661 | } | 1672 | } |
1662 | 1673 | ||
1663 | if (!sdata->vif.bss_conf.use_short_slot && | 1674 | if (!sdata->vif.bss_conf.use_short_slot && |
1664 | sdata->local->hw.conf.channel->band == IEEE80211_BAND_5GHZ) { | 1675 | sdata->local->oper_channel->band == IEEE80211_BAND_5GHZ) { |
1665 | sdata->vif.bss_conf.use_short_slot = true; | 1676 | sdata->vif.bss_conf.use_short_slot = true; |
1666 | changed |= BSS_CHANGED_ERP_SLOT; | 1677 | changed |= BSS_CHANGED_ERP_SLOT; |
1667 | } | 1678 | } |
@@ -1775,6 +1786,7 @@ static int ieee80211_scan(struct wiphy *wiphy, | |||
1775 | case NL80211_IFTYPE_ADHOC: | 1786 | case NL80211_IFTYPE_ADHOC: |
1776 | case NL80211_IFTYPE_MESH_POINT: | 1787 | case NL80211_IFTYPE_MESH_POINT: |
1777 | case NL80211_IFTYPE_P2P_CLIENT: | 1788 | case NL80211_IFTYPE_P2P_CLIENT: |
1789 | case NL80211_IFTYPE_P2P_DEVICE: | ||
1778 | break; | 1790 | break; |
1779 | case NL80211_IFTYPE_P2P_GO: | 1791 | case NL80211_IFTYPE_P2P_GO: |
1780 | if (sdata->local->ops->hw_scan) | 1792 | if (sdata->local->ops->hw_scan) |
@@ -1927,7 +1939,7 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy, | |||
1927 | enum nl80211_tx_power_setting type, int mbm) | 1939 | enum nl80211_tx_power_setting type, int mbm) |
1928 | { | 1940 | { |
1929 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1941 | struct ieee80211_local *local = wiphy_priv(wiphy); |
1930 | struct ieee80211_channel *chan = local->hw.conf.channel; | 1942 | struct ieee80211_channel *chan = local->oper_channel; |
1931 | u32 changes = 0; | 1943 | u32 changes = 0; |
1932 | 1944 | ||
1933 | switch (type) { | 1945 | switch (type) { |
@@ -2079,6 +2091,7 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, | |||
2079 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | 2091 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); |
2080 | 2092 | ||
2081 | ieee80211_recalc_ps(local, -1); | 2093 | ieee80211_recalc_ps(local, -1); |
2094 | ieee80211_recalc_ps_vif(sdata); | ||
2082 | 2095 | ||
2083 | return 0; | 2096 | return 0; |
2084 | } | 2097 | } |
@@ -2461,6 +2474,9 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
2461 | if (!sdata->u.mgd.associated) | 2474 | if (!sdata->u.mgd.associated) |
2462 | need_offchan = true; | 2475 | need_offchan = true; |
2463 | break; | 2476 | break; |
2477 | case NL80211_IFTYPE_P2P_DEVICE: | ||
2478 | need_offchan = true; | ||
2479 | break; | ||
2464 | default: | 2480 | default: |
2465 | return -EOPNOTSUPP; | 2481 | return -EOPNOTSUPP; |
2466 | } | 2482 | } |
@@ -2653,6 +2669,7 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, | |||
2653 | u16 status_code, struct sk_buff *skb) | 2669 | u16 status_code, struct sk_buff *skb) |
2654 | { | 2670 | { |
2655 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2671 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
2672 | struct ieee80211_local *local = sdata->local; | ||
2656 | struct ieee80211_tdls_data *tf; | 2673 | struct ieee80211_tdls_data *tf; |
2657 | 2674 | ||
2658 | tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u)); | 2675 | tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u)); |
@@ -2672,8 +2689,10 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, | |||
2672 | tf->u.setup_req.capability = | 2689 | tf->u.setup_req.capability = |
2673 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | 2690 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); |
2674 | 2691 | ||
2675 | ieee80211_add_srates_ie(sdata, skb, false); | 2692 | ieee80211_add_srates_ie(sdata, skb, false, |
2676 | ieee80211_add_ext_srates_ie(sdata, skb, false); | 2693 | local->oper_channel->band); |
2694 | ieee80211_add_ext_srates_ie(sdata, skb, false, | ||
2695 | local->oper_channel->band); | ||
2677 | ieee80211_tdls_add_ext_capab(skb); | 2696 | ieee80211_tdls_add_ext_capab(skb); |
2678 | break; | 2697 | break; |
2679 | case WLAN_TDLS_SETUP_RESPONSE: | 2698 | case WLAN_TDLS_SETUP_RESPONSE: |
@@ -2686,8 +2705,10 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, | |||
2686 | tf->u.setup_resp.capability = | 2705 | tf->u.setup_resp.capability = |
2687 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | 2706 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); |
2688 | 2707 | ||
2689 | ieee80211_add_srates_ie(sdata, skb, false); | 2708 | ieee80211_add_srates_ie(sdata, skb, false, |
2690 | ieee80211_add_ext_srates_ie(sdata, skb, false); | 2709 | local->oper_channel->band); |
2710 | ieee80211_add_ext_srates_ie(sdata, skb, false, | ||
2711 | local->oper_channel->band); | ||
2691 | ieee80211_tdls_add_ext_capab(skb); | 2712 | ieee80211_tdls_add_ext_capab(skb); |
2692 | break; | 2713 | break; |
2693 | case WLAN_TDLS_SETUP_CONFIRM: | 2714 | case WLAN_TDLS_SETUP_CONFIRM: |
@@ -2725,6 +2746,7 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, | |||
2725 | u16 status_code, struct sk_buff *skb) | 2746 | u16 status_code, struct sk_buff *skb) |
2726 | { | 2747 | { |
2727 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2748 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
2749 | struct ieee80211_local *local = sdata->local; | ||
2728 | struct ieee80211_mgmt *mgmt; | 2750 | struct ieee80211_mgmt *mgmt; |
2729 | 2751 | ||
2730 | mgmt = (void *)skb_put(skb, 24); | 2752 | mgmt = (void *)skb_put(skb, 24); |
@@ -2747,8 +2769,10 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, | |||
2747 | mgmt->u.action.u.tdls_discover_resp.capability = | 2769 | mgmt->u.action.u.tdls_discover_resp.capability = |
2748 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | 2770 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); |
2749 | 2771 | ||
2750 | ieee80211_add_srates_ie(sdata, skb, false); | 2772 | ieee80211_add_srates_ie(sdata, skb, false, |
2751 | ieee80211_add_ext_srates_ie(sdata, skb, false); | 2773 | local->oper_channel->band); |
2774 | ieee80211_add_ext_srates_ie(sdata, skb, false, | ||
2775 | local->oper_channel->band); | ||
2752 | ieee80211_tdls_add_ext_capab(skb); | 2776 | ieee80211_tdls_add_ext_capab(skb); |
2753 | break; | 2777 | break; |
2754 | default: | 2778 | default: |
@@ -3005,6 +3029,8 @@ struct cfg80211_ops mac80211_config_ops = { | |||
3005 | .add_virtual_intf = ieee80211_add_iface, | 3029 | .add_virtual_intf = ieee80211_add_iface, |
3006 | .del_virtual_intf = ieee80211_del_iface, | 3030 | .del_virtual_intf = ieee80211_del_iface, |
3007 | .change_virtual_intf = ieee80211_change_iface, | 3031 | .change_virtual_intf = ieee80211_change_iface, |
3032 | .start_p2p_device = ieee80211_start_p2p_device, | ||
3033 | .stop_p2p_device = ieee80211_stop_p2p_device, | ||
3008 | .add_key = ieee80211_add_key, | 3034 | .add_key = ieee80211_add_key, |
3009 | .del_key = ieee80211_del_key, | 3035 | .del_key = ieee80211_del_key, |
3010 | .get_key = ieee80211_get_key, | 3036 | .get_key = ieee80211_get_key, |
diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c index b8dfb440c8ef..97173f8144d4 100644 --- a/net/mac80211/debugfs.c +++ b/net/mac80211/debugfs.c | |||
@@ -63,8 +63,6 @@ DEBUGFS_READONLY_FILE(user_power, "%d", | |||
63 | local->user_power_level); | 63 | local->user_power_level); |
64 | DEBUGFS_READONLY_FILE(power, "%d", | 64 | DEBUGFS_READONLY_FILE(power, "%d", |
65 | local->hw.conf.power_level); | 65 | local->hw.conf.power_level); |
66 | DEBUGFS_READONLY_FILE(frequency, "%d", | ||
67 | local->hw.conf.channel->center_freq); | ||
68 | DEBUGFS_READONLY_FILE(total_ps_buffered, "%d", | 66 | DEBUGFS_READONLY_FILE(total_ps_buffered, "%d", |
69 | local->total_ps_buffered); | 67 | local->total_ps_buffered); |
70 | DEBUGFS_READONLY_FILE(wep_iv, "%#08x", | 68 | DEBUGFS_READONLY_FILE(wep_iv, "%#08x", |
@@ -91,33 +89,6 @@ static const struct file_operations reset_ops = { | |||
91 | .llseek = noop_llseek, | 89 | .llseek = noop_llseek, |
92 | }; | 90 | }; |
93 | 91 | ||
94 | static ssize_t channel_type_read(struct file *file, char __user *user_buf, | ||
95 | size_t count, loff_t *ppos) | ||
96 | { | ||
97 | struct ieee80211_local *local = file->private_data; | ||
98 | const char *buf; | ||
99 | |||
100 | switch (local->hw.conf.channel_type) { | ||
101 | case NL80211_CHAN_NO_HT: | ||
102 | buf = "no ht\n"; | ||
103 | break; | ||
104 | case NL80211_CHAN_HT20: | ||
105 | buf = "ht20\n"; | ||
106 | break; | ||
107 | case NL80211_CHAN_HT40MINUS: | ||
108 | buf = "ht40-\n"; | ||
109 | break; | ||
110 | case NL80211_CHAN_HT40PLUS: | ||
111 | buf = "ht40+\n"; | ||
112 | break; | ||
113 | default: | ||
114 | buf = "???"; | ||
115 | break; | ||
116 | } | ||
117 | |||
118 | return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); | ||
119 | } | ||
120 | |||
121 | static ssize_t hwflags_read(struct file *file, char __user *user_buf, | 92 | static ssize_t hwflags_read(struct file *file, char __user *user_buf, |
122 | size_t count, loff_t *ppos) | 93 | size_t count, loff_t *ppos) |
123 | { | 94 | { |
@@ -205,7 +176,6 @@ static ssize_t queues_read(struct file *file, char __user *user_buf, | |||
205 | } | 176 | } |
206 | 177 | ||
207 | DEBUGFS_READONLY_FILE_OPS(hwflags); | 178 | DEBUGFS_READONLY_FILE_OPS(hwflags); |
208 | DEBUGFS_READONLY_FILE_OPS(channel_type); | ||
209 | DEBUGFS_READONLY_FILE_OPS(queues); | 179 | DEBUGFS_READONLY_FILE_OPS(queues); |
210 | 180 | ||
211 | /* statistics stuff */ | 181 | /* statistics stuff */ |
@@ -272,12 +242,10 @@ void debugfs_hw_add(struct ieee80211_local *local) | |||
272 | 242 | ||
273 | local->debugfs.keys = debugfs_create_dir("keys", phyd); | 243 | local->debugfs.keys = debugfs_create_dir("keys", phyd); |
274 | 244 | ||
275 | DEBUGFS_ADD(frequency); | ||
276 | DEBUGFS_ADD(total_ps_buffered); | 245 | DEBUGFS_ADD(total_ps_buffered); |
277 | DEBUGFS_ADD(wep_iv); | 246 | DEBUGFS_ADD(wep_iv); |
278 | DEBUGFS_ADD(queues); | 247 | DEBUGFS_ADD(queues); |
279 | DEBUGFS_ADD_MODE(reset, 0200); | 248 | DEBUGFS_ADD_MODE(reset, 0200); |
280 | DEBUGFS_ADD(channel_type); | ||
281 | DEBUGFS_ADD(hwflags); | 249 | DEBUGFS_ADD(hwflags); |
282 | DEBUGFS_ADD(user_power); | 250 | DEBUGFS_ADD(user_power); |
283 | DEBUGFS_ADD(power); | 251 | DEBUGFS_ADD(power); |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index df9203199102..da9003b20004 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -9,7 +9,7 @@ static inline void check_sdata_in_driver(struct ieee80211_sub_if_data *sdata) | |||
9 | { | 9 | { |
10 | WARN(!(sdata->flags & IEEE80211_SDATA_IN_DRIVER), | 10 | WARN(!(sdata->flags & IEEE80211_SDATA_IN_DRIVER), |
11 | "%s: Failed check-sdata-in-driver check, flags: 0x%x\n", | 11 | "%s: Failed check-sdata-in-driver check, flags: 0x%x\n", |
12 | sdata->dev->name, sdata->flags); | 12 | sdata->dev ? sdata->dev->name : sdata->name, sdata->flags); |
13 | } | 13 | } |
14 | 14 | ||
15 | static inline struct ieee80211_sub_if_data * | 15 | static inline struct ieee80211_sub_if_data * |
@@ -22,9 +22,11 @@ get_bss_sdata(struct ieee80211_sub_if_data *sdata) | |||
22 | return sdata; | 22 | return sdata; |
23 | } | 23 | } |
24 | 24 | ||
25 | static inline void drv_tx(struct ieee80211_local *local, struct sk_buff *skb) | 25 | static inline void drv_tx(struct ieee80211_local *local, |
26 | struct ieee80211_tx_control *control, | ||
27 | struct sk_buff *skb) | ||
26 | { | 28 | { |
27 | local->ops->tx(&local->hw, skb); | 29 | local->ops->tx(&local->hw, control, skb); |
28 | } | 30 | } |
29 | 31 | ||
30 | static inline void drv_get_et_strings(struct ieee80211_sub_if_data *sdata, | 32 | static inline void drv_get_et_strings(struct ieee80211_sub_if_data *sdata, |
@@ -526,6 +528,9 @@ static inline void drv_sta_rc_update(struct ieee80211_local *local, | |||
526 | sdata = get_bss_sdata(sdata); | 528 | sdata = get_bss_sdata(sdata); |
527 | check_sdata_in_driver(sdata); | 529 | check_sdata_in_driver(sdata); |
528 | 530 | ||
531 | WARN_ON(changed & IEEE80211_RC_SUPP_RATES_CHANGED && | ||
532 | sdata->vif.type != NL80211_IFTYPE_ADHOC); | ||
533 | |||
529 | trace_drv_sta_rc_update(local, sdata, sta, changed); | 534 | trace_drv_sta_rc_update(local, sdata, sta, changed); |
530 | if (local->ops->sta_rc_update) | 535 | if (local->ops->sta_rc_update) |
531 | local->ops->sta_rc_update(&local->hw, &sdata->vif, | 536 | local->ops->sta_rc_update(&local->hw, &sdata->vif, |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 5746d62faba1..a9d93285dba7 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -109,7 +109,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
109 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); | 109 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); |
110 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 110 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
111 | IEEE80211_STYPE_PROBE_RESP); | 111 | IEEE80211_STYPE_PROBE_RESP); |
112 | memset(mgmt->da, 0xff, ETH_ALEN); | 112 | eth_broadcast_addr(mgmt->da); |
113 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | 113 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
114 | memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN); | 114 | memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN); |
115 | mgmt->u.beacon.beacon_int = cpu_to_le16(beacon_int); | 115 | mgmt->u.beacon.beacon_int = cpu_to_le16(beacon_int); |
@@ -205,7 +205,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
205 | mod_timer(&ifibss->timer, | 205 | mod_timer(&ifibss->timer, |
206 | round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL)); | 206 | round_jiffies(jiffies + IEEE80211_IBSS_MERGE_INTERVAL)); |
207 | 207 | ||
208 | bss = cfg80211_inform_bss_frame(local->hw.wiphy, local->hw.conf.channel, | 208 | bss = cfg80211_inform_bss_frame(local->hw.wiphy, chan, |
209 | mgmt, skb->len, 0, GFP_KERNEL); | 209 | mgmt, skb->len, 0, GFP_KERNEL); |
210 | cfg80211_put_bss(bss); | 210 | cfg80211_put_bss(bss); |
211 | netif_carrier_on(sdata->dev); | 211 | netif_carrier_on(sdata->dev); |
@@ -294,7 +294,7 @@ ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | |||
294 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 294 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
295 | struct ieee80211_local *local = sdata->local; | 295 | struct ieee80211_local *local = sdata->local; |
296 | struct sta_info *sta; | 296 | struct sta_info *sta; |
297 | int band = local->hw.conf.channel->band; | 297 | int band = local->oper_channel->band; |
298 | 298 | ||
299 | /* | 299 | /* |
300 | * XXX: Consider removing the least recently used entry and | 300 | * XXX: Consider removing the least recently used entry and |
@@ -459,8 +459,11 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
459 | } | 459 | } |
460 | } | 460 | } |
461 | 461 | ||
462 | if (sta && rates_updated) | 462 | if (sta && rates_updated) { |
463 | drv_sta_rc_update(local, sdata, &sta->sta, | ||
464 | IEEE80211_RC_SUPP_RATES_CHANGED); | ||
463 | rate_control_rate_init(sta); | 465 | rate_control_rate_init(sta); |
466 | } | ||
464 | 467 | ||
465 | rcu_read_unlock(); | 468 | rcu_read_unlock(); |
466 | } | 469 | } |
@@ -561,7 +564,7 @@ void ieee80211_ibss_rx_no_sta(struct ieee80211_sub_if_data *sdata, | |||
561 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 564 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
562 | struct ieee80211_local *local = sdata->local; | 565 | struct ieee80211_local *local = sdata->local; |
563 | struct sta_info *sta; | 566 | struct sta_info *sta; |
564 | int band = local->hw.conf.channel->band; | 567 | int band = local->oper_channel->band; |
565 | 568 | ||
566 | /* | 569 | /* |
567 | * XXX: Consider removing the least recently used entry and | 570 | * XXX: Consider removing the least recently used entry and |
@@ -759,7 +762,7 @@ static void ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata) | |||
759 | return; | 762 | return; |
760 | } | 763 | } |
761 | sdata_info(sdata, "IBSS not allowed on %d MHz\n", | 764 | sdata_info(sdata, "IBSS not allowed on %d MHz\n", |
762 | local->hw.conf.channel->center_freq); | 765 | local->oper_channel->center_freq); |
763 | 766 | ||
764 | /* No IBSS found - decrease scan interval and continue | 767 | /* No IBSS found - decrease scan interval and continue |
765 | * scanning. */ | 768 | * scanning. */ |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index bb61f7718c4c..204bfedba306 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -193,8 +193,6 @@ struct ieee80211_tx_data { | |||
193 | struct sta_info *sta; | 193 | struct sta_info *sta; |
194 | struct ieee80211_key *key; | 194 | struct ieee80211_key *key; |
195 | 195 | ||
196 | struct ieee80211_channel *channel; | ||
197 | |||
198 | unsigned int flags; | 196 | unsigned int flags; |
199 | }; | 197 | }; |
200 | 198 | ||
@@ -274,9 +272,15 @@ struct beacon_data { | |||
274 | struct rcu_head rcu_head; | 272 | struct rcu_head rcu_head; |
275 | }; | 273 | }; |
276 | 274 | ||
275 | struct probe_resp { | ||
276 | struct rcu_head rcu_head; | ||
277 | int len; | ||
278 | u8 data[0]; | ||
279 | }; | ||
280 | |||
277 | struct ieee80211_if_ap { | 281 | struct ieee80211_if_ap { |
278 | struct beacon_data __rcu *beacon; | 282 | struct beacon_data __rcu *beacon; |
279 | struct sk_buff __rcu *probe_resp; | 283 | struct probe_resp __rcu *probe_resp; |
280 | 284 | ||
281 | struct list_head vlans; | 285 | struct list_head vlans; |
282 | 286 | ||
@@ -359,6 +363,7 @@ enum ieee80211_sta_flags { | |||
359 | IEEE80211_STA_NULLFUNC_ACKED = BIT(8), | 363 | IEEE80211_STA_NULLFUNC_ACKED = BIT(8), |
360 | IEEE80211_STA_RESET_SIGNAL_AVE = BIT(9), | 364 | IEEE80211_STA_RESET_SIGNAL_AVE = BIT(9), |
361 | IEEE80211_STA_DISABLE_40MHZ = BIT(10), | 365 | IEEE80211_STA_DISABLE_40MHZ = BIT(10), |
366 | IEEE80211_STA_DISABLE_VHT = BIT(11), | ||
362 | }; | 367 | }; |
363 | 368 | ||
364 | struct ieee80211_mgd_auth_data { | 369 | struct ieee80211_mgd_auth_data { |
@@ -1075,6 +1080,8 @@ struct ieee80211_local { | |||
1075 | struct idr ack_status_frames; | 1080 | struct idr ack_status_frames; |
1076 | spinlock_t ack_status_lock; | 1081 | spinlock_t ack_status_lock; |
1077 | 1082 | ||
1083 | struct ieee80211_sub_if_data __rcu *p2p_sdata; | ||
1084 | |||
1078 | /* dummy netdev for use w/ NAPI */ | 1085 | /* dummy netdev for use w/ NAPI */ |
1079 | struct net_device napi_dev; | 1086 | struct net_device napi_dev; |
1080 | 1087 | ||
@@ -1131,7 +1138,7 @@ struct ieee802_11_elems { | |||
1131 | u8 *prep; | 1138 | u8 *prep; |
1132 | u8 *perr; | 1139 | u8 *perr; |
1133 | struct ieee80211_rann_ie *rann; | 1140 | struct ieee80211_rann_ie *rann; |
1134 | u8 *ch_switch_elem; | 1141 | struct ieee80211_channel_sw_ie *ch_switch_ie; |
1135 | u8 *country_elem; | 1142 | u8 *country_elem; |
1136 | u8 *pwr_constr_elem; | 1143 | u8 *pwr_constr_elem; |
1137 | u8 *quiet_elem; /* first quite element */ | 1144 | u8 *quiet_elem; /* first quite element */ |
@@ -1157,7 +1164,6 @@ struct ieee802_11_elems { | |||
1157 | u8 preq_len; | 1164 | u8 preq_len; |
1158 | u8 prep_len; | 1165 | u8 prep_len; |
1159 | u8 perr_len; | 1166 | u8 perr_len; |
1160 | u8 ch_switch_elem_len; | ||
1161 | u8 country_elem_len; | 1167 | u8 country_elem_len; |
1162 | u8 pwr_constr_elem_len; | 1168 | u8 pwr_constr_elem_len; |
1163 | u8 quiet_elem_len; | 1169 | u8 quiet_elem_len; |
@@ -1202,6 +1208,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1202 | void ieee80211_send_pspoll(struct ieee80211_local *local, | 1208 | void ieee80211_send_pspoll(struct ieee80211_local *local, |
1203 | struct ieee80211_sub_if_data *sdata); | 1209 | struct ieee80211_sub_if_data *sdata); |
1204 | void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency); | 1210 | void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency); |
1211 | void ieee80211_recalc_ps_vif(struct ieee80211_sub_if_data *sdata); | ||
1205 | int ieee80211_max_network_latency(struct notifier_block *nb, | 1212 | int ieee80211_max_network_latency(struct notifier_block *nb, |
1206 | unsigned long data, void *dummy); | 1213 | unsigned long data, void *dummy); |
1207 | int ieee80211_set_arp_filter(struct ieee80211_sub_if_data *sdata); | 1214 | int ieee80211_set_arp_filter(struct ieee80211_sub_if_data *sdata); |
@@ -1291,6 +1298,8 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local); | |||
1291 | void ieee80211_recalc_idle(struct ieee80211_local *local); | 1298 | void ieee80211_recalc_idle(struct ieee80211_local *local); |
1292 | void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, | 1299 | void ieee80211_adjust_monitor_flags(struct ieee80211_sub_if_data *sdata, |
1293 | const int offset); | 1300 | const int offset); |
1301 | int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up); | ||
1302 | void ieee80211_sdata_stop(struct ieee80211_sub_if_data *sdata); | ||
1294 | 1303 | ||
1295 | static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata) | 1304 | static inline bool ieee80211_sdata_running(struct ieee80211_sub_if_data *sdata) |
1296 | { | 1305 | { |
@@ -1425,7 +1434,6 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | |||
1425 | struct ieee80211_hdr *hdr); | 1434 | struct ieee80211_hdr *hdr); |
1426 | void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, | 1435 | void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, |
1427 | struct ieee80211_hdr *hdr, bool ack); | 1436 | struct ieee80211_hdr *hdr, bool ack); |
1428 | void ieee80211_beacon_connection_loss_work(struct work_struct *work); | ||
1429 | 1437 | ||
1430 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, | 1438 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, |
1431 | enum queue_stop_reason reason); | 1439 | enum queue_stop_reason reason); |
@@ -1457,13 +1465,15 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1457 | u8 channel); | 1465 | u8 channel); |
1458 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | 1466 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, |
1459 | u8 *dst, u32 ratemask, | 1467 | u8 *dst, u32 ratemask, |
1468 | struct ieee80211_channel *chan, | ||
1460 | const u8 *ssid, size_t ssid_len, | 1469 | const u8 *ssid, size_t ssid_len, |
1461 | const u8 *ie, size_t ie_len, | 1470 | const u8 *ie, size_t ie_len, |
1462 | bool directed); | 1471 | bool directed); |
1463 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | 1472 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, |
1464 | const u8 *ssid, size_t ssid_len, | 1473 | const u8 *ssid, size_t ssid_len, |
1465 | const u8 *ie, size_t ie_len, | 1474 | const u8 *ie, size_t ie_len, |
1466 | u32 ratemask, bool directed, bool no_cck); | 1475 | u32 ratemask, bool directed, bool no_cck, |
1476 | struct ieee80211_channel *channel); | ||
1467 | 1477 | ||
1468 | void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, | 1478 | void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, |
1469 | const size_t supp_rates_len, | 1479 | const size_t supp_rates_len, |
@@ -1487,9 +1497,11 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap, | |||
1487 | u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, | 1497 | u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap, |
1488 | u32 cap); | 1498 | u32 cap); |
1489 | int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, | 1499 | int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, |
1490 | struct sk_buff *skb, bool need_basic); | 1500 | struct sk_buff *skb, bool need_basic, |
1501 | enum ieee80211_band band); | ||
1491 | int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, | 1502 | int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, |
1492 | struct sk_buff *skb, bool need_basic); | 1503 | struct sk_buff *skb, bool need_basic, |
1504 | enum ieee80211_band band); | ||
1493 | 1505 | ||
1494 | /* channel management */ | 1506 | /* channel management */ |
1495 | enum ieee80211_chan_mode { | 1507 | enum ieee80211_chan_mode { |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index bfb57dcc1538..59f8adc2aa5f 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -100,6 +100,10 @@ static u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
100 | sdata->vif.bss_conf.idle = true; | 100 | sdata->vif.bss_conf.idle = true; |
101 | continue; | 101 | continue; |
102 | } | 102 | } |
103 | |||
104 | if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) | ||
105 | continue; | ||
106 | |||
103 | /* count everything else */ | 107 | /* count everything else */ |
104 | sdata->vif.bss_conf.idle = false; | 108 | sdata->vif.bss_conf.idle = false; |
105 | count++; | 109 | count++; |
@@ -121,7 +125,8 @@ static u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | |||
121 | 125 | ||
122 | list_for_each_entry(sdata, &local->interfaces, list) { | 126 | list_for_each_entry(sdata, &local->interfaces, list) { |
123 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR || | 127 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR || |
124 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 128 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN || |
129 | sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) | ||
125 | continue; | 130 | continue; |
126 | if (sdata->old_idle == sdata->vif.bss_conf.idle) | 131 | if (sdata->old_idle == sdata->vif.bss_conf.idle) |
127 | continue; | 132 | continue; |
@@ -204,6 +209,8 @@ static inline int identical_mac_addr_allowed(int type1, int type2) | |||
204 | { | 209 | { |
205 | return type1 == NL80211_IFTYPE_MONITOR || | 210 | return type1 == NL80211_IFTYPE_MONITOR || |
206 | type2 == NL80211_IFTYPE_MONITOR || | 211 | type2 == NL80211_IFTYPE_MONITOR || |
212 | type1 == NL80211_IFTYPE_P2P_DEVICE || | ||
213 | type2 == NL80211_IFTYPE_P2P_DEVICE || | ||
207 | (type1 == NL80211_IFTYPE_AP && type2 == NL80211_IFTYPE_WDS) || | 214 | (type1 == NL80211_IFTYPE_AP && type2 == NL80211_IFTYPE_WDS) || |
208 | (type1 == NL80211_IFTYPE_WDS && | 215 | (type1 == NL80211_IFTYPE_WDS && |
209 | (type2 == NL80211_IFTYPE_WDS || | 216 | (type2 == NL80211_IFTYPE_WDS || |
@@ -406,9 +413,10 @@ static void ieee80211_del_virtual_monitor(struct ieee80211_local *local) | |||
406 | * an error on interface type changes that have been pre-checked, so most | 413 | * an error on interface type changes that have been pre-checked, so most |
407 | * checks should be in ieee80211_check_concurrent_iface. | 414 | * checks should be in ieee80211_check_concurrent_iface. |
408 | */ | 415 | */ |
409 | static int ieee80211_do_open(struct net_device *dev, bool coming_up) | 416 | int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) |
410 | { | 417 | { |
411 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 418 | struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev); |
419 | struct net_device *dev = wdev->netdev; | ||
412 | struct ieee80211_local *local = sdata->local; | 420 | struct ieee80211_local *local = sdata->local; |
413 | struct sta_info *sta; | 421 | struct sta_info *sta; |
414 | u32 changed = 0; | 422 | u32 changed = 0; |
@@ -443,6 +451,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
443 | case NL80211_IFTYPE_STATION: | 451 | case NL80211_IFTYPE_STATION: |
444 | case NL80211_IFTYPE_MONITOR: | 452 | case NL80211_IFTYPE_MONITOR: |
445 | case NL80211_IFTYPE_ADHOC: | 453 | case NL80211_IFTYPE_ADHOC: |
454 | case NL80211_IFTYPE_P2P_DEVICE: | ||
446 | /* no special treatment */ | 455 | /* no special treatment */ |
447 | break; | 456 | break; |
448 | case NL80211_IFTYPE_UNSPECIFIED: | 457 | case NL80211_IFTYPE_UNSPECIFIED: |
@@ -471,7 +480,7 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
471 | * Copy the hopefully now-present MAC address to | 480 | * Copy the hopefully now-present MAC address to |
472 | * this interface, if it has the special null one. | 481 | * this interface, if it has the special null one. |
473 | */ | 482 | */ |
474 | if (is_zero_ether_addr(dev->dev_addr)) { | 483 | if (dev && is_zero_ether_addr(dev->dev_addr)) { |
475 | memcpy(dev->dev_addr, | 484 | memcpy(dev->dev_addr, |
476 | local->hw.wiphy->perm_addr, | 485 | local->hw.wiphy->perm_addr, |
477 | ETH_ALEN); | 486 | ETH_ALEN); |
@@ -536,15 +545,23 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
536 | local->fif_probe_req++; | 545 | local->fif_probe_req++; |
537 | } | 546 | } |
538 | 547 | ||
539 | changed |= ieee80211_reset_erp_info(sdata); | 548 | if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE) |
549 | changed |= ieee80211_reset_erp_info(sdata); | ||
540 | ieee80211_bss_info_change_notify(sdata, changed); | 550 | ieee80211_bss_info_change_notify(sdata, changed); |
541 | 551 | ||
542 | if (sdata->vif.type == NL80211_IFTYPE_STATION || | 552 | switch (sdata->vif.type) { |
543 | sdata->vif.type == NL80211_IFTYPE_ADHOC || | 553 | case NL80211_IFTYPE_STATION: |
544 | sdata->vif.type == NL80211_IFTYPE_AP) | 554 | case NL80211_IFTYPE_ADHOC: |
555 | case NL80211_IFTYPE_AP: | ||
556 | case NL80211_IFTYPE_MESH_POINT: | ||
545 | netif_carrier_off(dev); | 557 | netif_carrier_off(dev); |
546 | else | 558 | break; |
559 | case NL80211_IFTYPE_WDS: | ||
560 | case NL80211_IFTYPE_P2P_DEVICE: | ||
561 | break; | ||
562 | default: | ||
547 | netif_carrier_on(dev); | 563 | netif_carrier_on(dev); |
564 | } | ||
548 | 565 | ||
549 | /* | 566 | /* |
550 | * set default queue parameters so drivers don't | 567 | * set default queue parameters so drivers don't |
@@ -576,6 +593,9 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
576 | } | 593 | } |
577 | 594 | ||
578 | rate_control_rate_init(sta); | 595 | rate_control_rate_init(sta); |
596 | netif_carrier_on(dev); | ||
597 | } else if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) { | ||
598 | rcu_assign_pointer(local->p2p_sdata, sdata); | ||
579 | } | 599 | } |
580 | 600 | ||
581 | /* | 601 | /* |
@@ -601,7 +621,8 @@ static int ieee80211_do_open(struct net_device *dev, bool coming_up) | |||
601 | 621 | ||
602 | ieee80211_recalc_ps(local, -1); | 622 | ieee80211_recalc_ps(local, -1); |
603 | 623 | ||
604 | netif_tx_start_all_queues(dev); | 624 | if (dev) |
625 | netif_tx_start_all_queues(dev); | ||
605 | 626 | ||
606 | return 0; | 627 | return 0; |
607 | err_del_interface: | 628 | err_del_interface: |
@@ -631,7 +652,7 @@ static int ieee80211_open(struct net_device *dev) | |||
631 | if (err) | 652 | if (err) |
632 | return err; | 653 | return err; |
633 | 654 | ||
634 | return ieee80211_do_open(dev, true); | 655 | return ieee80211_do_open(&sdata->wdev, true); |
635 | } | 656 | } |
636 | 657 | ||
637 | static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | 658 | static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, |
@@ -652,7 +673,8 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
652 | /* | 673 | /* |
653 | * Stop TX on this interface first. | 674 | * Stop TX on this interface first. |
654 | */ | 675 | */ |
655 | netif_tx_stop_all_queues(sdata->dev); | 676 | if (sdata->dev) |
677 | netif_tx_stop_all_queues(sdata->dev); | ||
656 | 678 | ||
657 | ieee80211_roc_purge(sdata); | 679 | ieee80211_roc_purge(sdata); |
658 | 680 | ||
@@ -691,14 +713,16 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
691 | local->fif_probe_req--; | 713 | local->fif_probe_req--; |
692 | } | 714 | } |
693 | 715 | ||
694 | netif_addr_lock_bh(sdata->dev); | 716 | if (sdata->dev) { |
695 | spin_lock_bh(&local->filter_lock); | 717 | netif_addr_lock_bh(sdata->dev); |
696 | __hw_addr_unsync(&local->mc_list, &sdata->dev->mc, | 718 | spin_lock_bh(&local->filter_lock); |
697 | sdata->dev->addr_len); | 719 | __hw_addr_unsync(&local->mc_list, &sdata->dev->mc, |
698 | spin_unlock_bh(&local->filter_lock); | 720 | sdata->dev->addr_len); |
699 | netif_addr_unlock_bh(sdata->dev); | 721 | spin_unlock_bh(&local->filter_lock); |
722 | netif_addr_unlock_bh(sdata->dev); | ||
700 | 723 | ||
701 | ieee80211_configure_filter(local); | 724 | ieee80211_configure_filter(local); |
725 | } | ||
702 | 726 | ||
703 | del_timer_sync(&local->dynamic_ps_timer); | 727 | del_timer_sync(&local->dynamic_ps_timer); |
704 | cancel_work_sync(&local->dynamic_ps_enable_work); | 728 | cancel_work_sync(&local->dynamic_ps_enable_work); |
@@ -708,7 +732,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
708 | struct ieee80211_sub_if_data *vlan, *tmpsdata; | 732 | struct ieee80211_sub_if_data *vlan, *tmpsdata; |
709 | struct beacon_data *old_beacon = | 733 | struct beacon_data *old_beacon = |
710 | rtnl_dereference(sdata->u.ap.beacon); | 734 | rtnl_dereference(sdata->u.ap.beacon); |
711 | struct sk_buff *old_probe_resp = | 735 | struct probe_resp *old_probe_resp = |
712 | rtnl_dereference(sdata->u.ap.probe_resp); | 736 | rtnl_dereference(sdata->u.ap.probe_resp); |
713 | 737 | ||
714 | /* sdata_running will return false, so this will disable */ | 738 | /* sdata_running will return false, so this will disable */ |
@@ -720,7 +744,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
720 | RCU_INIT_POINTER(sdata->u.ap.probe_resp, NULL); | 744 | RCU_INIT_POINTER(sdata->u.ap.probe_resp, NULL); |
721 | synchronize_rcu(); | 745 | synchronize_rcu(); |
722 | kfree(old_beacon); | 746 | kfree(old_beacon); |
723 | kfree_skb(old_probe_resp); | 747 | kfree(old_probe_resp); |
724 | 748 | ||
725 | /* down all dependent devices, that is VLANs */ | 749 | /* down all dependent devices, that is VLANs */ |
726 | list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, | 750 | list_for_each_entry_safe(vlan, tmpsdata, &sdata->u.ap.vlans, |
@@ -759,6 +783,10 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
759 | ieee80211_adjust_monitor_flags(sdata, -1); | 783 | ieee80211_adjust_monitor_flags(sdata, -1); |
760 | ieee80211_configure_filter(local); | 784 | ieee80211_configure_filter(local); |
761 | break; | 785 | break; |
786 | case NL80211_IFTYPE_P2P_DEVICE: | ||
787 | /* relies on synchronize_rcu() below */ | ||
788 | rcu_assign_pointer(local->p2p_sdata, NULL); | ||
789 | /* fall through */ | ||
762 | default: | 790 | default: |
763 | flush_work(&sdata->work); | 791 | flush_work(&sdata->work); |
764 | /* | 792 | /* |
@@ -771,14 +799,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
771 | skb_queue_purge(&sdata->skb_queue); | 799 | skb_queue_purge(&sdata->skb_queue); |
772 | 800 | ||
773 | /* | 801 | /* |
774 | * Disable beaconing here for mesh only, AP and IBSS | ||
775 | * are already taken care of. | ||
776 | */ | ||
777 | if (sdata->vif.type == NL80211_IFTYPE_MESH_POINT) | ||
778 | ieee80211_bss_info_change_notify(sdata, | ||
779 | BSS_CHANGED_BEACON_ENABLED); | ||
780 | |||
781 | /* | ||
782 | * Free all remaining keys, there shouldn't be any, | 802 | * Free all remaining keys, there shouldn't be any, |
783 | * except maybe group keys in AP more or WDS? | 803 | * except maybe group keys in AP more or WDS? |
784 | */ | 804 | */ |
@@ -877,9 +897,8 @@ static void ieee80211_set_multicast_list(struct net_device *dev) | |||
877 | * Called when the netdev is removed or, by the code below, before | 897 | * Called when the netdev is removed or, by the code below, before |
878 | * the interface type changes. | 898 | * the interface type changes. |
879 | */ | 899 | */ |
880 | static void ieee80211_teardown_sdata(struct net_device *dev) | 900 | static void ieee80211_teardown_sdata(struct ieee80211_sub_if_data *sdata) |
881 | { | 901 | { |
882 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
883 | struct ieee80211_local *local = sdata->local; | 902 | struct ieee80211_local *local = sdata->local; |
884 | int flushed; | 903 | int flushed; |
885 | int i; | 904 | int i; |
@@ -900,6 +919,11 @@ static void ieee80211_teardown_sdata(struct net_device *dev) | |||
900 | WARN_ON(flushed); | 919 | WARN_ON(flushed); |
901 | } | 920 | } |
902 | 921 | ||
922 | static void ieee80211_uninit(struct net_device *dev) | ||
923 | { | ||
924 | ieee80211_teardown_sdata(IEEE80211_DEV_TO_SUB_IF(dev)); | ||
925 | } | ||
926 | |||
903 | static u16 ieee80211_netdev_select_queue(struct net_device *dev, | 927 | static u16 ieee80211_netdev_select_queue(struct net_device *dev, |
904 | struct sk_buff *skb) | 928 | struct sk_buff *skb) |
905 | { | 929 | { |
@@ -909,7 +933,7 @@ static u16 ieee80211_netdev_select_queue(struct net_device *dev, | |||
909 | static const struct net_device_ops ieee80211_dataif_ops = { | 933 | static const struct net_device_ops ieee80211_dataif_ops = { |
910 | .ndo_open = ieee80211_open, | 934 | .ndo_open = ieee80211_open, |
911 | .ndo_stop = ieee80211_stop, | 935 | .ndo_stop = ieee80211_stop, |
912 | .ndo_uninit = ieee80211_teardown_sdata, | 936 | .ndo_uninit = ieee80211_uninit, |
913 | .ndo_start_xmit = ieee80211_subif_start_xmit, | 937 | .ndo_start_xmit = ieee80211_subif_start_xmit, |
914 | .ndo_set_rx_mode = ieee80211_set_multicast_list, | 938 | .ndo_set_rx_mode = ieee80211_set_multicast_list, |
915 | .ndo_change_mtu = ieee80211_change_mtu, | 939 | .ndo_change_mtu = ieee80211_change_mtu, |
@@ -940,7 +964,7 @@ static u16 ieee80211_monitor_select_queue(struct net_device *dev, | |||
940 | static const struct net_device_ops ieee80211_monitorif_ops = { | 964 | static const struct net_device_ops ieee80211_monitorif_ops = { |
941 | .ndo_open = ieee80211_open, | 965 | .ndo_open = ieee80211_open, |
942 | .ndo_stop = ieee80211_stop, | 966 | .ndo_stop = ieee80211_stop, |
943 | .ndo_uninit = ieee80211_teardown_sdata, | 967 | .ndo_uninit = ieee80211_uninit, |
944 | .ndo_start_xmit = ieee80211_monitor_start_xmit, | 968 | .ndo_start_xmit = ieee80211_monitor_start_xmit, |
945 | .ndo_set_rx_mode = ieee80211_set_multicast_list, | 969 | .ndo_set_rx_mode = ieee80211_set_multicast_list, |
946 | .ndo_change_mtu = ieee80211_change_mtu, | 970 | .ndo_change_mtu = ieee80211_change_mtu, |
@@ -1099,7 +1123,6 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
1099 | /* and set some type-dependent values */ | 1123 | /* and set some type-dependent values */ |
1100 | sdata->vif.type = type; | 1124 | sdata->vif.type = type; |
1101 | sdata->vif.p2p = false; | 1125 | sdata->vif.p2p = false; |
1102 | sdata->dev->netdev_ops = &ieee80211_dataif_ops; | ||
1103 | sdata->wdev.iftype = type; | 1126 | sdata->wdev.iftype = type; |
1104 | 1127 | ||
1105 | sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE); | 1128 | sdata->control_port_protocol = cpu_to_be16(ETH_P_PAE); |
@@ -1107,8 +1130,11 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
1107 | 1130 | ||
1108 | sdata->noack_map = 0; | 1131 | sdata->noack_map = 0; |
1109 | 1132 | ||
1110 | /* only monitor differs */ | 1133 | /* only monitor/p2p-device differ */ |
1111 | sdata->dev->type = ARPHRD_ETHER; | 1134 | if (sdata->dev) { |
1135 | sdata->dev->netdev_ops = &ieee80211_dataif_ops; | ||
1136 | sdata->dev->type = ARPHRD_ETHER; | ||
1137 | } | ||
1112 | 1138 | ||
1113 | skb_queue_head_init(&sdata->skb_queue); | 1139 | skb_queue_head_init(&sdata->skb_queue); |
1114 | INIT_WORK(&sdata->work, ieee80211_iface_work); | 1140 | INIT_WORK(&sdata->work, ieee80211_iface_work); |
@@ -1146,6 +1172,7 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
1146 | break; | 1172 | break; |
1147 | case NL80211_IFTYPE_WDS: | 1173 | case NL80211_IFTYPE_WDS: |
1148 | case NL80211_IFTYPE_AP_VLAN: | 1174 | case NL80211_IFTYPE_AP_VLAN: |
1175 | case NL80211_IFTYPE_P2P_DEVICE: | ||
1149 | break; | 1176 | break; |
1150 | case NL80211_IFTYPE_UNSPECIFIED: | 1177 | case NL80211_IFTYPE_UNSPECIFIED: |
1151 | case NUM_NL80211_IFTYPES: | 1178 | case NUM_NL80211_IFTYPES: |
@@ -1156,18 +1183,6 @@ static void ieee80211_setup_sdata(struct ieee80211_sub_if_data *sdata, | |||
1156 | ieee80211_debugfs_add_netdev(sdata); | 1183 | ieee80211_debugfs_add_netdev(sdata); |
1157 | } | 1184 | } |
1158 | 1185 | ||
1159 | static void ieee80211_clean_sdata(struct ieee80211_sub_if_data *sdata) | ||
1160 | { | ||
1161 | switch (sdata->vif.type) { | ||
1162 | case NL80211_IFTYPE_MESH_POINT: | ||
1163 | mesh_path_flush_by_iface(sdata); | ||
1164 | break; | ||
1165 | |||
1166 | default: | ||
1167 | break; | ||
1168 | } | ||
1169 | } | ||
1170 | |||
1171 | static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata, | 1186 | static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata, |
1172 | enum nl80211_iftype type) | 1187 | enum nl80211_iftype type) |
1173 | { | 1188 | { |
@@ -1225,7 +1240,7 @@ static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata, | |||
1225 | 1240 | ||
1226 | ieee80211_do_stop(sdata, false); | 1241 | ieee80211_do_stop(sdata, false); |
1227 | 1242 | ||
1228 | ieee80211_teardown_sdata(sdata->dev); | 1243 | ieee80211_teardown_sdata(sdata); |
1229 | 1244 | ||
1230 | ret = drv_change_interface(local, sdata, internal_type, p2p); | 1245 | ret = drv_change_interface(local, sdata, internal_type, p2p); |
1231 | if (ret) | 1246 | if (ret) |
@@ -1240,7 +1255,7 @@ static int ieee80211_runtime_change_iftype(struct ieee80211_sub_if_data *sdata, | |||
1240 | 1255 | ||
1241 | ieee80211_setup_sdata(sdata, type); | 1256 | ieee80211_setup_sdata(sdata, type); |
1242 | 1257 | ||
1243 | err = ieee80211_do_open(sdata->dev, false); | 1258 | err = ieee80211_do_open(&sdata->wdev, false); |
1244 | WARN(err, "type change: do_open returned %d", err); | 1259 | WARN(err, "type change: do_open returned %d", err); |
1245 | 1260 | ||
1246 | return ret; | 1261 | return ret; |
@@ -1267,14 +1282,14 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | |||
1267 | return ret; | 1282 | return ret; |
1268 | } else { | 1283 | } else { |
1269 | /* Purge and reset type-dependent state. */ | 1284 | /* Purge and reset type-dependent state. */ |
1270 | ieee80211_teardown_sdata(sdata->dev); | 1285 | ieee80211_teardown_sdata(sdata); |
1271 | ieee80211_setup_sdata(sdata, type); | 1286 | ieee80211_setup_sdata(sdata, type); |
1272 | } | 1287 | } |
1273 | 1288 | ||
1274 | /* reset some values that shouldn't be kept across type changes */ | 1289 | /* reset some values that shouldn't be kept across type changes */ |
1275 | sdata->vif.bss_conf.basic_rates = | 1290 | sdata->vif.bss_conf.basic_rates = |
1276 | ieee80211_mandatory_rates(sdata->local, | 1291 | ieee80211_mandatory_rates(sdata->local, |
1277 | sdata->local->hw.conf.channel->band); | 1292 | sdata->local->oper_channel->band); |
1278 | sdata->drop_unencrypted = 0; | 1293 | sdata->drop_unencrypted = 0; |
1279 | if (type == NL80211_IFTYPE_STATION) | 1294 | if (type == NL80211_IFTYPE_STATION) |
1280 | sdata->u.mgd.use_4addr = false; | 1295 | sdata->u.mgd.use_4addr = false; |
@@ -1283,8 +1298,7 @@ int ieee80211_if_change_type(struct ieee80211_sub_if_data *sdata, | |||
1283 | } | 1298 | } |
1284 | 1299 | ||
1285 | static void ieee80211_assign_perm_addr(struct ieee80211_local *local, | 1300 | static void ieee80211_assign_perm_addr(struct ieee80211_local *local, |
1286 | struct net_device *dev, | 1301 | u8 *perm_addr, enum nl80211_iftype type) |
1287 | enum nl80211_iftype type) | ||
1288 | { | 1302 | { |
1289 | struct ieee80211_sub_if_data *sdata; | 1303 | struct ieee80211_sub_if_data *sdata; |
1290 | u64 mask, start, addr, val, inc; | 1304 | u64 mask, start, addr, val, inc; |
@@ -1293,13 +1307,12 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, | |||
1293 | int i; | 1307 | int i; |
1294 | 1308 | ||
1295 | /* default ... something at least */ | 1309 | /* default ... something at least */ |
1296 | memcpy(dev->perm_addr, local->hw.wiphy->perm_addr, ETH_ALEN); | 1310 | memcpy(perm_addr, local->hw.wiphy->perm_addr, ETH_ALEN); |
1297 | 1311 | ||
1298 | if (is_zero_ether_addr(local->hw.wiphy->addr_mask) && | 1312 | if (is_zero_ether_addr(local->hw.wiphy->addr_mask) && |
1299 | local->hw.wiphy->n_addresses <= 1) | 1313 | local->hw.wiphy->n_addresses <= 1) |
1300 | return; | 1314 | return; |
1301 | 1315 | ||
1302 | |||
1303 | mutex_lock(&local->iflist_mtx); | 1316 | mutex_lock(&local->iflist_mtx); |
1304 | 1317 | ||
1305 | switch (type) { | 1318 | switch (type) { |
@@ -1312,11 +1325,24 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, | |||
1312 | list_for_each_entry(sdata, &local->interfaces, list) { | 1325 | list_for_each_entry(sdata, &local->interfaces, list) { |
1313 | if (sdata->vif.type != NL80211_IFTYPE_AP) | 1326 | if (sdata->vif.type != NL80211_IFTYPE_AP) |
1314 | continue; | 1327 | continue; |
1315 | memcpy(dev->perm_addr, sdata->vif.addr, ETH_ALEN); | 1328 | memcpy(perm_addr, sdata->vif.addr, ETH_ALEN); |
1316 | break; | 1329 | break; |
1317 | } | 1330 | } |
1318 | /* keep default if no AP interface present */ | 1331 | /* keep default if no AP interface present */ |
1319 | break; | 1332 | break; |
1333 | case NL80211_IFTYPE_P2P_CLIENT: | ||
1334 | case NL80211_IFTYPE_P2P_GO: | ||
1335 | if (local->hw.flags & IEEE80211_HW_P2P_DEV_ADDR_FOR_INTF) { | ||
1336 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
1337 | if (sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE) | ||
1338 | continue; | ||
1339 | if (!ieee80211_sdata_running(sdata)) | ||
1340 | continue; | ||
1341 | memcpy(perm_addr, sdata->vif.addr, ETH_ALEN); | ||
1342 | goto out_unlock; | ||
1343 | } | ||
1344 | } | ||
1345 | /* otherwise fall through */ | ||
1320 | default: | 1346 | default: |
1321 | /* assign a new address if possible -- try n_addresses first */ | 1347 | /* assign a new address if possible -- try n_addresses first */ |
1322 | for (i = 0; i < local->hw.wiphy->n_addresses; i++) { | 1348 | for (i = 0; i < local->hw.wiphy->n_addresses; i++) { |
@@ -1331,7 +1357,7 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, | |||
1331 | } | 1357 | } |
1332 | 1358 | ||
1333 | if (!used) { | 1359 | if (!used) { |
1334 | memcpy(dev->perm_addr, | 1360 | memcpy(perm_addr, |
1335 | local->hw.wiphy->addresses[i].addr, | 1361 | local->hw.wiphy->addresses[i].addr, |
1336 | ETH_ALEN); | 1362 | ETH_ALEN); |
1337 | break; | 1363 | break; |
@@ -1382,7 +1408,7 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, | |||
1382 | } | 1408 | } |
1383 | 1409 | ||
1384 | if (!used) { | 1410 | if (!used) { |
1385 | memcpy(dev->perm_addr, tmp_addr, ETH_ALEN); | 1411 | memcpy(perm_addr, tmp_addr, ETH_ALEN); |
1386 | break; | 1412 | break; |
1387 | } | 1413 | } |
1388 | addr = (start & ~mask) | (val & mask); | 1414 | addr = (start & ~mask) | (val & mask); |
@@ -1391,6 +1417,7 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, | |||
1391 | break; | 1417 | break; |
1392 | } | 1418 | } |
1393 | 1419 | ||
1420 | out_unlock: | ||
1394 | mutex_unlock(&local->iflist_mtx); | 1421 | mutex_unlock(&local->iflist_mtx); |
1395 | } | 1422 | } |
1396 | 1423 | ||
@@ -1398,49 +1425,68 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1398 | struct wireless_dev **new_wdev, enum nl80211_iftype type, | 1425 | struct wireless_dev **new_wdev, enum nl80211_iftype type, |
1399 | struct vif_params *params) | 1426 | struct vif_params *params) |
1400 | { | 1427 | { |
1401 | struct net_device *ndev; | 1428 | struct net_device *ndev = NULL; |
1402 | struct ieee80211_sub_if_data *sdata = NULL; | 1429 | struct ieee80211_sub_if_data *sdata = NULL; |
1403 | int ret, i; | 1430 | int ret, i; |
1404 | int txqs = 1; | 1431 | int txqs = 1; |
1405 | 1432 | ||
1406 | ASSERT_RTNL(); | 1433 | ASSERT_RTNL(); |
1407 | 1434 | ||
1408 | if (local->hw.queues >= IEEE80211_NUM_ACS) | 1435 | if (type == NL80211_IFTYPE_P2P_DEVICE) { |
1409 | txqs = IEEE80211_NUM_ACS; | 1436 | struct wireless_dev *wdev; |
1410 | 1437 | ||
1411 | ndev = alloc_netdev_mqs(sizeof(*sdata) + local->hw.vif_data_size, | 1438 | sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, |
1412 | name, ieee80211_if_setup, txqs, 1); | 1439 | GFP_KERNEL); |
1413 | if (!ndev) | 1440 | if (!sdata) |
1414 | return -ENOMEM; | 1441 | return -ENOMEM; |
1415 | dev_net_set(ndev, wiphy_net(local->hw.wiphy)); | 1442 | wdev = &sdata->wdev; |
1416 | 1443 | ||
1417 | ndev->needed_headroom = local->tx_headroom + | 1444 | sdata->dev = NULL; |
1418 | 4*6 /* four MAC addresses */ | 1445 | strlcpy(sdata->name, name, IFNAMSIZ); |
1419 | + 2 + 2 + 2 + 2 /* ctl, dur, seq, qos */ | 1446 | ieee80211_assign_perm_addr(local, wdev->address, type); |
1420 | + 6 /* mesh */ | 1447 | memcpy(sdata->vif.addr, wdev->address, ETH_ALEN); |
1421 | + 8 /* rfc1042/bridge tunnel */ | 1448 | } else { |
1422 | - ETH_HLEN /* ethernet hard_header_len */ | 1449 | if (local->hw.queues >= IEEE80211_NUM_ACS) |
1423 | + IEEE80211_ENCRYPT_HEADROOM; | 1450 | txqs = IEEE80211_NUM_ACS; |
1424 | ndev->needed_tailroom = IEEE80211_ENCRYPT_TAILROOM; | 1451 | |
1425 | 1452 | ndev = alloc_netdev_mqs(sizeof(*sdata) + | |
1426 | ret = dev_alloc_name(ndev, ndev->name); | 1453 | local->hw.vif_data_size, |
1427 | if (ret < 0) | 1454 | name, ieee80211_if_setup, txqs, 1); |
1428 | goto fail; | 1455 | if (!ndev) |
1429 | 1456 | return -ENOMEM; | |
1430 | ieee80211_assign_perm_addr(local, ndev, type); | 1457 | dev_net_set(ndev, wiphy_net(local->hw.wiphy)); |
1431 | memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN); | 1458 | |
1432 | SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); | 1459 | ndev->needed_headroom = local->tx_headroom + |
1433 | 1460 | 4*6 /* four MAC addresses */ | |
1434 | /* don't use IEEE80211_DEV_TO_SUB_IF because it checks too much */ | 1461 | + 2 + 2 + 2 + 2 /* ctl, dur, seq, qos */ |
1435 | sdata = netdev_priv(ndev); | 1462 | + 6 /* mesh */ |
1436 | ndev->ieee80211_ptr = &sdata->wdev; | 1463 | + 8 /* rfc1042/bridge tunnel */ |
1437 | memcpy(sdata->vif.addr, ndev->dev_addr, ETH_ALEN); | 1464 | - ETH_HLEN /* ethernet hard_header_len */ |
1438 | memcpy(sdata->name, ndev->name, IFNAMSIZ); | 1465 | + IEEE80211_ENCRYPT_HEADROOM; |
1466 | ndev->needed_tailroom = IEEE80211_ENCRYPT_TAILROOM; | ||
1467 | |||
1468 | ret = dev_alloc_name(ndev, ndev->name); | ||
1469 | if (ret < 0) { | ||
1470 | free_netdev(ndev); | ||
1471 | return ret; | ||
1472 | } | ||
1473 | |||
1474 | ieee80211_assign_perm_addr(local, ndev->perm_addr, type); | ||
1475 | memcpy(ndev->dev_addr, ndev->perm_addr, ETH_ALEN); | ||
1476 | SET_NETDEV_DEV(ndev, wiphy_dev(local->hw.wiphy)); | ||
1477 | |||
1478 | /* don't use IEEE80211_DEV_TO_SUB_IF -- it checks too much */ | ||
1479 | sdata = netdev_priv(ndev); | ||
1480 | ndev->ieee80211_ptr = &sdata->wdev; | ||
1481 | memcpy(sdata->vif.addr, ndev->dev_addr, ETH_ALEN); | ||
1482 | memcpy(sdata->name, ndev->name, IFNAMSIZ); | ||
1483 | |||
1484 | sdata->dev = ndev; | ||
1485 | } | ||
1439 | 1486 | ||
1440 | /* initialise type-independent data */ | 1487 | /* initialise type-independent data */ |
1441 | sdata->wdev.wiphy = local->hw.wiphy; | 1488 | sdata->wdev.wiphy = local->hw.wiphy; |
1442 | sdata->local = local; | 1489 | sdata->local = local; |
1443 | sdata->dev = ndev; | ||
1444 | #ifdef CONFIG_INET | 1490 | #ifdef CONFIG_INET |
1445 | sdata->arp_filter_state = true; | 1491 | sdata->arp_filter_state = true; |
1446 | #endif | 1492 | #endif |
@@ -1469,17 +1515,21 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1469 | /* setup type-dependent data */ | 1515 | /* setup type-dependent data */ |
1470 | ieee80211_setup_sdata(sdata, type); | 1516 | ieee80211_setup_sdata(sdata, type); |
1471 | 1517 | ||
1472 | if (params) { | 1518 | if (ndev) { |
1473 | ndev->ieee80211_ptr->use_4addr = params->use_4addr; | 1519 | if (params) { |
1474 | if (type == NL80211_IFTYPE_STATION) | 1520 | ndev->ieee80211_ptr->use_4addr = params->use_4addr; |
1475 | sdata->u.mgd.use_4addr = params->use_4addr; | 1521 | if (type == NL80211_IFTYPE_STATION) |
1476 | } | 1522 | sdata->u.mgd.use_4addr = params->use_4addr; |
1523 | } | ||
1477 | 1524 | ||
1478 | ndev->features |= local->hw.netdev_features; | 1525 | ndev->features |= local->hw.netdev_features; |
1479 | 1526 | ||
1480 | ret = register_netdevice(ndev); | 1527 | ret = register_netdevice(ndev); |
1481 | if (ret) | 1528 | if (ret) { |
1482 | goto fail; | 1529 | free_netdev(ndev); |
1530 | return ret; | ||
1531 | } | ||
1532 | } | ||
1483 | 1533 | ||
1484 | mutex_lock(&local->iflist_mtx); | 1534 | mutex_lock(&local->iflist_mtx); |
1485 | list_add_tail_rcu(&sdata->list, &local->interfaces); | 1535 | list_add_tail_rcu(&sdata->list, &local->interfaces); |
@@ -1489,10 +1539,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1489 | *new_wdev = &sdata->wdev; | 1539 | *new_wdev = &sdata->wdev; |
1490 | 1540 | ||
1491 | return 0; | 1541 | return 0; |
1492 | |||
1493 | fail: | ||
1494 | free_netdev(ndev); | ||
1495 | return ret; | ||
1496 | } | 1542 | } |
1497 | 1543 | ||
1498 | void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata) | 1544 | void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata) |
@@ -1503,11 +1549,22 @@ void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata) | |||
1503 | list_del_rcu(&sdata->list); | 1549 | list_del_rcu(&sdata->list); |
1504 | mutex_unlock(&sdata->local->iflist_mtx); | 1550 | mutex_unlock(&sdata->local->iflist_mtx); |
1505 | 1551 | ||
1506 | /* clean up type-dependent data */ | ||
1507 | ieee80211_clean_sdata(sdata); | ||
1508 | |||
1509 | synchronize_rcu(); | 1552 | synchronize_rcu(); |
1510 | unregister_netdevice(sdata->dev); | 1553 | |
1554 | if (sdata->dev) { | ||
1555 | unregister_netdevice(sdata->dev); | ||
1556 | } else { | ||
1557 | cfg80211_unregister_wdev(&sdata->wdev); | ||
1558 | kfree(sdata); | ||
1559 | } | ||
1560 | } | ||
1561 | |||
1562 | void ieee80211_sdata_stop(struct ieee80211_sub_if_data *sdata) | ||
1563 | { | ||
1564 | if (WARN_ON_ONCE(!test_bit(SDATA_STATE_RUNNING, &sdata->state))) | ||
1565 | return; | ||
1566 | ieee80211_do_stop(sdata, true); | ||
1567 | ieee80211_teardown_sdata(sdata); | ||
1511 | } | 1568 | } |
1512 | 1569 | ||
1513 | /* | 1570 | /* |
@@ -1518,6 +1575,7 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local) | |||
1518 | { | 1575 | { |
1519 | struct ieee80211_sub_if_data *sdata, *tmp; | 1576 | struct ieee80211_sub_if_data *sdata, *tmp; |
1520 | LIST_HEAD(unreg_list); | 1577 | LIST_HEAD(unreg_list); |
1578 | LIST_HEAD(wdev_list); | ||
1521 | 1579 | ||
1522 | ASSERT_RTNL(); | 1580 | ASSERT_RTNL(); |
1523 | 1581 | ||
@@ -1525,13 +1583,20 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local) | |||
1525 | list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { | 1583 | list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { |
1526 | list_del(&sdata->list); | 1584 | list_del(&sdata->list); |
1527 | 1585 | ||
1528 | ieee80211_clean_sdata(sdata); | 1586 | if (sdata->dev) |
1529 | 1587 | unregister_netdevice_queue(sdata->dev, &unreg_list); | |
1530 | unregister_netdevice_queue(sdata->dev, &unreg_list); | 1588 | else |
1589 | list_add(&sdata->list, &wdev_list); | ||
1531 | } | 1590 | } |
1532 | mutex_unlock(&local->iflist_mtx); | 1591 | mutex_unlock(&local->iflist_mtx); |
1533 | unregister_netdevice_many(&unreg_list); | 1592 | unregister_netdevice_many(&unreg_list); |
1534 | list_del(&unreg_list); | 1593 | list_del(&unreg_list); |
1594 | |||
1595 | list_for_each_entry_safe(sdata, tmp, &wdev_list, list) { | ||
1596 | list_del(&sdata->list); | ||
1597 | cfg80211_unregister_wdev(&sdata->wdev); | ||
1598 | kfree(sdata); | ||
1599 | } | ||
1535 | } | 1600 | } |
1536 | 1601 | ||
1537 | static int netdev_notify(struct notifier_block *nb, | 1602 | static int netdev_notify(struct notifier_block *nb, |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index c26e231c733a..bd7529363193 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -207,6 +207,10 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | |||
207 | sdata->vif.bss_conf.bssid = NULL; | 207 | sdata->vif.bss_conf.bssid = NULL; |
208 | else if (ieee80211_vif_is_mesh(&sdata->vif)) { | 208 | else if (ieee80211_vif_is_mesh(&sdata->vif)) { |
209 | sdata->vif.bss_conf.bssid = zero; | 209 | sdata->vif.bss_conf.bssid = zero; |
210 | } else if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) { | ||
211 | sdata->vif.bss_conf.bssid = sdata->vif.addr; | ||
212 | WARN_ONCE(changed & ~(BSS_CHANGED_IDLE), | ||
213 | "P2P Device BSS changed %#x", changed); | ||
210 | } else { | 214 | } else { |
211 | WARN_ON(1); | 215 | WARN_ON(1); |
212 | return; | 216 | return; |
@@ -514,6 +518,11 @@ ieee80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = { | |||
514 | BIT(IEEE80211_STYPE_AUTH >> 4) | | 518 | BIT(IEEE80211_STYPE_AUTH >> 4) | |
515 | BIT(IEEE80211_STYPE_DEAUTH >> 4), | 519 | BIT(IEEE80211_STYPE_DEAUTH >> 4), |
516 | }, | 520 | }, |
521 | [NL80211_IFTYPE_P2P_DEVICE] = { | ||
522 | .tx = 0xffff, | ||
523 | .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | | ||
524 | BIT(IEEE80211_STYPE_PROBE_REQ >> 4), | ||
525 | }, | ||
517 | }; | 526 | }; |
518 | 527 | ||
519 | static const struct ieee80211_ht_cap mac80211_ht_capa_mod_mask = { | 528 | static const struct ieee80211_ht_cap mac80211_ht_capa_mod_mask = { |
@@ -536,6 +545,11 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
536 | int priv_size, i; | 545 | int priv_size, i; |
537 | struct wiphy *wiphy; | 546 | struct wiphy *wiphy; |
538 | 547 | ||
548 | if (WARN_ON(!ops->tx || !ops->start || !ops->stop || !ops->config || | ||
549 | !ops->add_interface || !ops->remove_interface || | ||
550 | !ops->configure_filter)) | ||
551 | return NULL; | ||
552 | |||
539 | if (WARN_ON(ops->sta_state && (ops->sta_add || ops->sta_remove))) | 553 | if (WARN_ON(ops->sta_state && (ops->sta_add || ops->sta_remove))) |
540 | return NULL; | 554 | return NULL; |
541 | 555 | ||
@@ -588,13 +602,6 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
588 | 602 | ||
589 | local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN); | 603 | local->hw.priv = (char *)local + ALIGN(sizeof(*local), NETDEV_ALIGN); |
590 | 604 | ||
591 | BUG_ON(!ops->tx); | ||
592 | BUG_ON(!ops->start); | ||
593 | BUG_ON(!ops->stop); | ||
594 | BUG_ON(!ops->config); | ||
595 | BUG_ON(!ops->add_interface); | ||
596 | BUG_ON(!ops->remove_interface); | ||
597 | BUG_ON(!ops->configure_filter); | ||
598 | local->ops = ops; | 605 | local->ops = ops; |
599 | 606 | ||
600 | /* set up some defaults */ | 607 | /* set up some defaults */ |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 6fac18c0423f..ff0296c7bab8 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -109,11 +109,11 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata, | |||
109 | 109 | ||
110 | /* Disallow HT40+/- mismatch */ | 110 | /* Disallow HT40+/- mismatch */ |
111 | if (ie->ht_operation && | 111 | if (ie->ht_operation && |
112 | (local->_oper_channel_type == NL80211_CHAN_HT40MINUS || | 112 | (sdata->vif.bss_conf.channel_type == NL80211_CHAN_HT40MINUS || |
113 | local->_oper_channel_type == NL80211_CHAN_HT40PLUS) && | 113 | sdata->vif.bss_conf.channel_type == NL80211_CHAN_HT40PLUS) && |
114 | (sta_channel_type == NL80211_CHAN_HT40MINUS || | 114 | (sta_channel_type == NL80211_CHAN_HT40MINUS || |
115 | sta_channel_type == NL80211_CHAN_HT40PLUS) && | 115 | sta_channel_type == NL80211_CHAN_HT40PLUS) && |
116 | local->_oper_channel_type != sta_channel_type) | 116 | sdata->vif.bss_conf.channel_type != sta_channel_type) |
117 | goto mismatch; | 117 | goto mismatch; |
118 | 118 | ||
119 | return true; | 119 | return true; |
@@ -136,10 +136,13 @@ bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie) | |||
136 | * mesh_accept_plinks_update - update accepting_plink in local mesh beacons | 136 | * mesh_accept_plinks_update - update accepting_plink in local mesh beacons |
137 | * | 137 | * |
138 | * @sdata: mesh interface in which mesh beacons are going to be updated | 138 | * @sdata: mesh interface in which mesh beacons are going to be updated |
139 | * | ||
140 | * Returns: beacon changed flag if the beacon content changed. | ||
139 | */ | 141 | */ |
140 | void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata) | 142 | u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata) |
141 | { | 143 | { |
142 | bool free_plinks; | 144 | bool free_plinks; |
145 | u32 changed = 0; | ||
143 | 146 | ||
144 | /* In case mesh_plink_free_count > 0 and mesh_plinktbl_capacity == 0, | 147 | /* In case mesh_plink_free_count > 0 and mesh_plinktbl_capacity == 0, |
145 | * the mesh interface might be able to establish plinks with peers that | 148 | * the mesh interface might be able to establish plinks with peers that |
@@ -149,8 +152,12 @@ void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata) | |||
149 | */ | 152 | */ |
150 | free_plinks = mesh_plink_availables(sdata); | 153 | free_plinks = mesh_plink_availables(sdata); |
151 | 154 | ||
152 | if (free_plinks != sdata->u.mesh.accepting_plinks) | 155 | if (free_plinks != sdata->u.mesh.accepting_plinks) { |
153 | ieee80211_mesh_housekeeping_timer((unsigned long) sdata); | 156 | sdata->u.mesh.accepting_plinks = free_plinks; |
157 | changed = BSS_CHANGED_BEACON; | ||
158 | } | ||
159 | |||
160 | return changed; | ||
154 | } | 161 | } |
155 | 162 | ||
156 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) | 163 | int mesh_rmc_init(struct ieee80211_sub_if_data *sdata) |
@@ -262,7 +269,6 @@ mesh_add_meshconf_ie(struct sk_buff *skb, struct ieee80211_sub_if_data *sdata) | |||
262 | neighbors = (neighbors > 15) ? 15 : neighbors; | 269 | neighbors = (neighbors > 15) ? 15 : neighbors; |
263 | *pos++ = neighbors << 1; | 270 | *pos++ = neighbors << 1; |
264 | /* Mesh capability */ | 271 | /* Mesh capability */ |
265 | ifmsh->accepting_plinks = mesh_plink_availables(sdata); | ||
266 | *pos = MESHCONF_CAPAB_FORWARDING; | 272 | *pos = MESHCONF_CAPAB_FORWARDING; |
267 | *pos |= ifmsh->accepting_plinks ? | 273 | *pos |= ifmsh->accepting_plinks ? |
268 | MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; | 274 | MESHCONF_CAPAB_ACCEPT_PLINKS : 0x00; |
@@ -349,17 +355,18 @@ int mesh_add_ds_params_ie(struct sk_buff *skb, | |||
349 | { | 355 | { |
350 | struct ieee80211_local *local = sdata->local; | 356 | struct ieee80211_local *local = sdata->local; |
351 | struct ieee80211_supported_band *sband; | 357 | struct ieee80211_supported_band *sband; |
358 | struct ieee80211_channel *chan = local->oper_channel; | ||
352 | u8 *pos; | 359 | u8 *pos; |
353 | 360 | ||
354 | if (skb_tailroom(skb) < 3) | 361 | if (skb_tailroom(skb) < 3) |
355 | return -ENOMEM; | 362 | return -ENOMEM; |
356 | 363 | ||
357 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 364 | sband = local->hw.wiphy->bands[chan->band]; |
358 | if (sband->band == IEEE80211_BAND_2GHZ) { | 365 | if (sband->band == IEEE80211_BAND_2GHZ) { |
359 | pos = skb_put(skb, 2 + 1); | 366 | pos = skb_put(skb, 2 + 1); |
360 | *pos++ = WLAN_EID_DS_PARAMS; | 367 | *pos++ = WLAN_EID_DS_PARAMS; |
361 | *pos++ = 1; | 368 | *pos++ = 1; |
362 | *pos++ = ieee80211_frequency_to_channel(local->hw.conf.channel->center_freq); | 369 | *pos++ = ieee80211_frequency_to_channel(chan->center_freq); |
363 | } | 370 | } |
364 | 371 | ||
365 | return 0; | 372 | return 0; |
@@ -374,7 +381,7 @@ int mesh_add_ht_cap_ie(struct sk_buff *skb, | |||
374 | 381 | ||
375 | sband = local->hw.wiphy->bands[local->oper_channel->band]; | 382 | sband = local->hw.wiphy->bands[local->oper_channel->band]; |
376 | if (!sband->ht_cap.ht_supported || | 383 | if (!sband->ht_cap.ht_supported || |
377 | local->_oper_channel_type == NL80211_CHAN_NO_HT) | 384 | sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) |
378 | return 0; | 385 | return 0; |
379 | 386 | ||
380 | if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_cap)) | 387 | if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_cap)) |
@@ -391,7 +398,8 @@ int mesh_add_ht_oper_ie(struct sk_buff *skb, | |||
391 | { | 398 | { |
392 | struct ieee80211_local *local = sdata->local; | 399 | struct ieee80211_local *local = sdata->local; |
393 | struct ieee80211_channel *channel = local->oper_channel; | 400 | struct ieee80211_channel *channel = local->oper_channel; |
394 | enum nl80211_channel_type channel_type = local->_oper_channel_type; | 401 | enum nl80211_channel_type channel_type = |
402 | sdata->vif.bss_conf.channel_type; | ||
395 | struct ieee80211_supported_band *sband = | 403 | struct ieee80211_supported_band *sband = |
396 | local->hw.wiphy->bands[channel->band]; | 404 | local->hw.wiphy->bands[channel->band]; |
397 | struct ieee80211_sta_ht_cap *ht_cap = &sband->ht_cap; | 405 | struct ieee80211_sta_ht_cap *ht_cap = &sband->ht_cap; |
@@ -521,14 +529,13 @@ int ieee80211_new_mesh_header(struct ieee80211s_hdr *meshhdr, | |||
521 | static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, | 529 | static void ieee80211_mesh_housekeeping(struct ieee80211_sub_if_data *sdata, |
522 | struct ieee80211_if_mesh *ifmsh) | 530 | struct ieee80211_if_mesh *ifmsh) |
523 | { | 531 | { |
524 | bool free_plinks; | 532 | u32 changed; |
525 | 533 | ||
526 | ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); | 534 | ieee80211_sta_expire(sdata, IEEE80211_MESH_PEER_INACTIVITY_LIMIT); |
527 | mesh_path_expire(sdata); | 535 | mesh_path_expire(sdata); |
528 | 536 | ||
529 | free_plinks = mesh_plink_availables(sdata); | 537 | changed = mesh_accept_plinks_update(sdata); |
530 | if (free_plinks != sdata->u.mesh.accepting_plinks) | 538 | ieee80211_bss_info_change_notify(sdata, changed); |
531 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); | ||
532 | 539 | ||
533 | mod_timer(&ifmsh->housekeeping_timer, | 540 | mod_timer(&ifmsh->housekeeping_timer, |
534 | round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL)); | 541 | round_jiffies(jiffies + IEEE80211_MESH_HOUSEKEEPING_INTERVAL)); |
@@ -603,12 +610,14 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) | |||
603 | sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL; | 610 | sdata->vif.bss_conf.beacon_int = MESH_DEFAULT_BEACON_INTERVAL; |
604 | sdata->vif.bss_conf.basic_rates = | 611 | sdata->vif.bss_conf.basic_rates = |
605 | ieee80211_mandatory_rates(sdata->local, | 612 | ieee80211_mandatory_rates(sdata->local, |
606 | sdata->local->hw.conf.channel->band); | 613 | sdata->local->oper_channel->band); |
607 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | | 614 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON | |
608 | BSS_CHANGED_BEACON_ENABLED | | 615 | BSS_CHANGED_BEACON_ENABLED | |
609 | BSS_CHANGED_HT | | 616 | BSS_CHANGED_HT | |
610 | BSS_CHANGED_BASIC_RATES | | 617 | BSS_CHANGED_BASIC_RATES | |
611 | BSS_CHANGED_BEACON_INT); | 618 | BSS_CHANGED_BEACON_INT); |
619 | |||
620 | netif_carrier_on(sdata->dev); | ||
612 | } | 621 | } |
613 | 622 | ||
614 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) | 623 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) |
@@ -616,12 +625,19 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) | |||
616 | struct ieee80211_local *local = sdata->local; | 625 | struct ieee80211_local *local = sdata->local; |
617 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 626 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
618 | 627 | ||
628 | netif_carrier_off(sdata->dev); | ||
629 | |||
630 | /* stop the beacon */ | ||
619 | ifmsh->mesh_id_len = 0; | 631 | ifmsh->mesh_id_len = 0; |
620 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); | 632 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED); |
621 | sta_info_flush(local, NULL); | 633 | |
634 | /* flush STAs and mpaths on this iface */ | ||
635 | sta_info_flush(sdata->local, sdata); | ||
636 | mesh_path_flush_by_iface(sdata); | ||
622 | 637 | ||
623 | del_timer_sync(&sdata->u.mesh.housekeeping_timer); | 638 | del_timer_sync(&sdata->u.mesh.housekeeping_timer); |
624 | del_timer_sync(&sdata->u.mesh.mesh_path_root_timer); | 639 | del_timer_sync(&sdata->u.mesh.mesh_path_root_timer); |
640 | del_timer_sync(&sdata->u.mesh.mesh_path_timer); | ||
625 | /* | 641 | /* |
626 | * If the timer fired while we waited for it, it will have | 642 | * If the timer fired while we waited for it, it will have |
627 | * requeued the work. Now the work will be running again | 643 | * requeued the work. Now the work will be running again |
@@ -634,6 +650,8 @@ void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) | |||
634 | local->fif_other_bss--; | 650 | local->fif_other_bss--; |
635 | atomic_dec(&local->iff_allmultis); | 651 | atomic_dec(&local->iff_allmultis); |
636 | ieee80211_configure_filter(local); | 652 | ieee80211_configure_filter(local); |
653 | |||
654 | sdata->u.mesh.timers_running = 0; | ||
637 | } | 655 | } |
638 | 656 | ||
639 | static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | 657 | static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, |
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h index faaa39bcfd10..25d0f17dec71 100644 --- a/net/mac80211/mesh.h +++ b/net/mac80211/mesh.h | |||
@@ -215,6 +215,9 @@ struct mesh_rmc { | |||
215 | /* Maximum number of paths per interface */ | 215 | /* Maximum number of paths per interface */ |
216 | #define MESH_MAX_MPATHS 1024 | 216 | #define MESH_MAX_MPATHS 1024 |
217 | 217 | ||
218 | /* Number of frames buffered per destination for unresolved destinations */ | ||
219 | #define MESH_FRAME_QUEUE_LEN 10 | ||
220 | |||
218 | /* Public interfaces */ | 221 | /* Public interfaces */ |
219 | /* Various */ | 222 | /* Various */ |
220 | int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, | 223 | int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc, |
@@ -282,7 +285,7 @@ void mesh_neighbour_update(struct ieee80211_sub_if_data *sdata, | |||
282 | u8 *hw_addr, | 285 | u8 *hw_addr, |
283 | struct ieee802_11_elems *ie); | 286 | struct ieee802_11_elems *ie); |
284 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); | 287 | bool mesh_peer_accepts_plinks(struct ieee802_11_elems *ie); |
285 | void mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); | 288 | u32 mesh_accept_plinks_update(struct ieee80211_sub_if_data *sdata); |
286 | void mesh_plink_broken(struct sta_info *sta); | 289 | void mesh_plink_broken(struct sta_info *sta); |
287 | void mesh_plink_deactivate(struct sta_info *sta); | 290 | void mesh_plink_deactivate(struct sta_info *sta); |
288 | int mesh_plink_open(struct sta_info *sta); | 291 | int mesh_plink_open(struct sta_info *sta); |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 494bc39f61a4..47aeee2d8db1 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -17,8 +17,6 @@ | |||
17 | #define MAX_METRIC 0xffffffff | 17 | #define MAX_METRIC 0xffffffff |
18 | #define ARITH_SHIFT 8 | 18 | #define ARITH_SHIFT 8 |
19 | 19 | ||
20 | /* Number of frames buffered per destination for unresolved destinations */ | ||
21 | #define MESH_FRAME_QUEUE_LEN 10 | ||
22 | #define MAX_PREQ_QUEUE_LEN 64 | 20 | #define MAX_PREQ_QUEUE_LEN 64 |
23 | 21 | ||
24 | /* Destination only */ | 22 | /* Destination only */ |
diff --git a/net/mac80211/mesh_pathtbl.c b/net/mac80211/mesh_pathtbl.c index 075bc535c601..aa749818860e 100644 --- a/net/mac80211/mesh_pathtbl.c +++ b/net/mac80211/mesh_pathtbl.c | |||
@@ -203,23 +203,17 @@ void mesh_path_assign_nexthop(struct mesh_path *mpath, struct sta_info *sta) | |||
203 | { | 203 | { |
204 | struct sk_buff *skb; | 204 | struct sk_buff *skb; |
205 | struct ieee80211_hdr *hdr; | 205 | struct ieee80211_hdr *hdr; |
206 | struct sk_buff_head tmpq; | ||
207 | unsigned long flags; | 206 | unsigned long flags; |
208 | 207 | ||
209 | rcu_assign_pointer(mpath->next_hop, sta); | 208 | rcu_assign_pointer(mpath->next_hop, sta); |
210 | 209 | ||
211 | __skb_queue_head_init(&tmpq); | ||
212 | |||
213 | spin_lock_irqsave(&mpath->frame_queue.lock, flags); | 210 | spin_lock_irqsave(&mpath->frame_queue.lock, flags); |
214 | 211 | skb_queue_walk(&mpath->frame_queue, skb) { | |
215 | while ((skb = __skb_dequeue(&mpath->frame_queue)) != NULL) { | ||
216 | hdr = (struct ieee80211_hdr *) skb->data; | 212 | hdr = (struct ieee80211_hdr *) skb->data; |
217 | memcpy(hdr->addr1, sta->sta.addr, ETH_ALEN); | 213 | memcpy(hdr->addr1, sta->sta.addr, ETH_ALEN); |
218 | memcpy(hdr->addr2, mpath->sdata->vif.addr, ETH_ALEN); | 214 | memcpy(hdr->addr2, mpath->sdata->vif.addr, ETH_ALEN); |
219 | __skb_queue_tail(&tmpq, skb); | ||
220 | } | 215 | } |
221 | 216 | ||
222 | skb_queue_splice(&tmpq, &mpath->frame_queue); | ||
223 | spin_unlock_irqrestore(&mpath->frame_queue.lock, flags); | 217 | spin_unlock_irqrestore(&mpath->frame_queue.lock, flags); |
224 | } | 218 | } |
225 | 219 | ||
@@ -285,40 +279,42 @@ static void mesh_path_move_to_queue(struct mesh_path *gate_mpath, | |||
285 | struct mesh_path *from_mpath, | 279 | struct mesh_path *from_mpath, |
286 | bool copy) | 280 | bool copy) |
287 | { | 281 | { |
288 | struct sk_buff *skb, *cp_skb = NULL; | 282 | struct sk_buff *skb, *fskb, *tmp; |
289 | struct sk_buff_head gateq, failq; | 283 | struct sk_buff_head failq; |
290 | unsigned long flags; | 284 | unsigned long flags; |
291 | int num_skbs; | ||
292 | 285 | ||
293 | BUG_ON(gate_mpath == from_mpath); | 286 | BUG_ON(gate_mpath == from_mpath); |
294 | BUG_ON(!gate_mpath->next_hop); | 287 | BUG_ON(!gate_mpath->next_hop); |
295 | 288 | ||
296 | __skb_queue_head_init(&gateq); | ||
297 | __skb_queue_head_init(&failq); | 289 | __skb_queue_head_init(&failq); |
298 | 290 | ||
299 | spin_lock_irqsave(&from_mpath->frame_queue.lock, flags); | 291 | spin_lock_irqsave(&from_mpath->frame_queue.lock, flags); |
300 | skb_queue_splice_init(&from_mpath->frame_queue, &failq); | 292 | skb_queue_splice_init(&from_mpath->frame_queue, &failq); |
301 | spin_unlock_irqrestore(&from_mpath->frame_queue.lock, flags); | 293 | spin_unlock_irqrestore(&from_mpath->frame_queue.lock, flags); |
302 | 294 | ||
303 | num_skbs = skb_queue_len(&failq); | 295 | skb_queue_walk_safe(&failq, fskb, tmp) { |
304 | 296 | if (skb_queue_len(&gate_mpath->frame_queue) >= | |
305 | while (num_skbs--) { | 297 | MESH_FRAME_QUEUE_LEN) { |
306 | skb = __skb_dequeue(&failq); | 298 | mpath_dbg(gate_mpath->sdata, "mpath queue full!\n"); |
307 | if (copy) { | 299 | break; |
308 | cp_skb = skb_copy(skb, GFP_ATOMIC); | ||
309 | if (cp_skb) | ||
310 | __skb_queue_tail(&failq, cp_skb); | ||
311 | } | 300 | } |
312 | 301 | ||
302 | skb = skb_copy(fskb, GFP_ATOMIC); | ||
303 | if (WARN_ON(!skb)) | ||
304 | break; | ||
305 | |||
313 | prepare_for_gate(skb, gate_mpath->dst, gate_mpath); | 306 | prepare_for_gate(skb, gate_mpath->dst, gate_mpath); |
314 | __skb_queue_tail(&gateq, skb); | 307 | skb_queue_tail(&gate_mpath->frame_queue, skb); |
308 | |||
309 | if (copy) | ||
310 | continue; | ||
311 | |||
312 | __skb_unlink(fskb, &failq); | ||
313 | kfree_skb(fskb); | ||
315 | } | 314 | } |
316 | 315 | ||
317 | spin_lock_irqsave(&gate_mpath->frame_queue.lock, flags); | ||
318 | skb_queue_splice(&gateq, &gate_mpath->frame_queue); | ||
319 | mpath_dbg(gate_mpath->sdata, "Mpath queue for gate %pM has %d frames\n", | 316 | mpath_dbg(gate_mpath->sdata, "Mpath queue for gate %pM has %d frames\n", |
320 | gate_mpath->dst, skb_queue_len(&gate_mpath->frame_queue)); | 317 | gate_mpath->dst, skb_queue_len(&gate_mpath->frame_queue)); |
321 | spin_unlock_irqrestore(&gate_mpath->frame_queue.lock, flags); | ||
322 | 318 | ||
323 | if (!copy) | 319 | if (!copy) |
324 | return; | 320 | return; |
@@ -531,7 +527,7 @@ int mesh_path_add(u8 *dst, struct ieee80211_sub_if_data *sdata) | |||
531 | 527 | ||
532 | read_lock_bh(&pathtbl_resize_lock); | 528 | read_lock_bh(&pathtbl_resize_lock); |
533 | memcpy(new_mpath->dst, dst, ETH_ALEN); | 529 | memcpy(new_mpath->dst, dst, ETH_ALEN); |
534 | memset(new_mpath->rann_snd_addr, 0xff, ETH_ALEN); | 530 | eth_broadcast_addr(new_mpath->rann_snd_addr); |
535 | new_mpath->is_root = false; | 531 | new_mpath->is_root = false; |
536 | new_mpath->sdata = sdata; | 532 | new_mpath->sdata = sdata; |
537 | new_mpath->flags = 0; | 533 | new_mpath->flags = 0; |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index af671b984df3..9d7ad366ef09 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -48,17 +48,17 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
48 | u8 *da, __le16 llid, __le16 plid, __le16 reason); | 48 | u8 *da, __le16 llid, __le16 plid, __le16 reason); |
49 | 49 | ||
50 | static inline | 50 | static inline |
51 | void mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) | 51 | u32 mesh_plink_inc_estab_count(struct ieee80211_sub_if_data *sdata) |
52 | { | 52 | { |
53 | atomic_inc(&sdata->u.mesh.mshstats.estab_plinks); | 53 | atomic_inc(&sdata->u.mesh.mshstats.estab_plinks); |
54 | mesh_accept_plinks_update(sdata); | 54 | return mesh_accept_plinks_update(sdata); |
55 | } | 55 | } |
56 | 56 | ||
57 | static inline | 57 | static inline |
58 | void mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata) | 58 | u32 mesh_plink_dec_estab_count(struct ieee80211_sub_if_data *sdata) |
59 | { | 59 | { |
60 | atomic_dec(&sdata->u.mesh.mshstats.estab_plinks); | 60 | atomic_dec(&sdata->u.mesh.mshstats.estab_plinks); |
61 | mesh_accept_plinks_update(sdata); | 61 | return mesh_accept_plinks_update(sdata); |
62 | } | 62 | } |
63 | 63 | ||
64 | /** | 64 | /** |
@@ -117,7 +117,7 @@ static u32 mesh_set_ht_prot_mode(struct ieee80211_sub_if_data *sdata) | |||
117 | u16 ht_opmode; | 117 | u16 ht_opmode; |
118 | bool non_ht_sta = false, ht20_sta = false; | 118 | bool non_ht_sta = false, ht20_sta = false; |
119 | 119 | ||
120 | if (local->_oper_channel_type == NL80211_CHAN_NO_HT) | 120 | if (sdata->vif.bss_conf.channel_type == NL80211_CHAN_NO_HT) |
121 | return 0; | 121 | return 0; |
122 | 122 | ||
123 | rcu_read_lock(); | 123 | rcu_read_lock(); |
@@ -147,7 +147,8 @@ out: | |||
147 | 147 | ||
148 | if (non_ht_sta) | 148 | if (non_ht_sta) |
149 | ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED; | 149 | ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONHT_MIXED; |
150 | else if (ht20_sta && local->_oper_channel_type > NL80211_CHAN_HT20) | 150 | else if (ht20_sta && |
151 | sdata->vif.bss_conf.channel_type > NL80211_CHAN_HT20) | ||
151 | ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_20MHZ; | 152 | ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_20MHZ; |
152 | else | 153 | else |
153 | ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONE; | 154 | ht_opmode = IEEE80211_HT_OP_MODE_PROTECTION_NONE; |
@@ -170,22 +171,21 @@ out: | |||
170 | * @sta: mesh peer link to deactivate | 171 | * @sta: mesh peer link to deactivate |
171 | * | 172 | * |
172 | * All mesh paths with this peer as next hop will be flushed | 173 | * All mesh paths with this peer as next hop will be flushed |
174 | * Returns beacon changed flag if the beacon content changed. | ||
173 | * | 175 | * |
174 | * Locking: the caller must hold sta->lock | 176 | * Locking: the caller must hold sta->lock |
175 | */ | 177 | */ |
176 | static bool __mesh_plink_deactivate(struct sta_info *sta) | 178 | static u32 __mesh_plink_deactivate(struct sta_info *sta) |
177 | { | 179 | { |
178 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 180 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
179 | bool deactivated = false; | 181 | u32 changed = 0; |
180 | 182 | ||
181 | if (sta->plink_state == NL80211_PLINK_ESTAB) { | 183 | if (sta->plink_state == NL80211_PLINK_ESTAB) |
182 | mesh_plink_dec_estab_count(sdata); | 184 | changed = mesh_plink_dec_estab_count(sdata); |
183 | deactivated = true; | ||
184 | } | ||
185 | sta->plink_state = NL80211_PLINK_BLOCKED; | 185 | sta->plink_state = NL80211_PLINK_BLOCKED; |
186 | mesh_path_flush_by_nexthop(sta); | 186 | mesh_path_flush_by_nexthop(sta); |
187 | 187 | ||
188 | return deactivated; | 188 | return changed; |
189 | } | 189 | } |
190 | 190 | ||
191 | /** | 191 | /** |
@@ -198,18 +198,17 @@ static bool __mesh_plink_deactivate(struct sta_info *sta) | |||
198 | void mesh_plink_deactivate(struct sta_info *sta) | 198 | void mesh_plink_deactivate(struct sta_info *sta) |
199 | { | 199 | { |
200 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 200 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
201 | bool deactivated; | 201 | u32 changed; |
202 | 202 | ||
203 | spin_lock_bh(&sta->lock); | 203 | spin_lock_bh(&sta->lock); |
204 | deactivated = __mesh_plink_deactivate(sta); | 204 | changed = __mesh_plink_deactivate(sta); |
205 | sta->reason = cpu_to_le16(WLAN_REASON_MESH_PEER_CANCELED); | 205 | sta->reason = cpu_to_le16(WLAN_REASON_MESH_PEER_CANCELED); |
206 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, | 206 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, |
207 | sta->sta.addr, sta->llid, sta->plid, | 207 | sta->sta.addr, sta->llid, sta->plid, |
208 | sta->reason); | 208 | sta->reason); |
209 | spin_unlock_bh(&sta->lock); | 209 | spin_unlock_bh(&sta->lock); |
210 | 210 | ||
211 | if (deactivated) | 211 | ieee80211_bss_info_change_notify(sdata, changed); |
212 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); | ||
213 | } | 212 | } |
214 | 213 | ||
215 | static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | 214 | static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, |
@@ -217,12 +216,14 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
217 | u8 *da, __le16 llid, __le16 plid, __le16 reason) { | 216 | u8 *da, __le16 llid, __le16 plid, __le16 reason) { |
218 | struct ieee80211_local *local = sdata->local; | 217 | struct ieee80211_local *local = sdata->local; |
219 | struct sk_buff *skb; | 218 | struct sk_buff *skb; |
219 | struct ieee80211_tx_info *info; | ||
220 | struct ieee80211_mgmt *mgmt; | 220 | struct ieee80211_mgmt *mgmt; |
221 | bool include_plid = false; | 221 | bool include_plid = false; |
222 | u16 peering_proto = 0; | 222 | u16 peering_proto = 0; |
223 | u8 *pos, ie_len = 4; | 223 | u8 *pos, ie_len = 4; |
224 | int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.self_prot) + | 224 | int hdr_len = offsetof(struct ieee80211_mgmt, u.action.u.self_prot) + |
225 | sizeof(mgmt->u.action.u.self_prot); | 225 | sizeof(mgmt->u.action.u.self_prot); |
226 | int err = -ENOMEM; | ||
226 | 227 | ||
227 | skb = dev_alloc_skb(local->tx_headroom + | 228 | skb = dev_alloc_skb(local->tx_headroom + |
228 | hdr_len + | 229 | hdr_len + |
@@ -238,6 +239,7 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
238 | sdata->u.mesh.ie_len); | 239 | sdata->u.mesh.ie_len); |
239 | if (!skb) | 240 | if (!skb) |
240 | return -1; | 241 | return -1; |
242 | info = IEEE80211_SKB_CB(skb); | ||
241 | skb_reserve(skb, local->tx_headroom); | 243 | skb_reserve(skb, local->tx_headroom); |
242 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len); | 244 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len); |
243 | memset(mgmt, 0, hdr_len); | 245 | memset(mgmt, 0, hdr_len); |
@@ -258,15 +260,18 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
258 | pos = skb_put(skb, 2); | 260 | pos = skb_put(skb, 2); |
259 | memcpy(pos + 2, &plid, 2); | 261 | memcpy(pos + 2, &plid, 2); |
260 | } | 262 | } |
261 | if (ieee80211_add_srates_ie(sdata, skb, true) || | 263 | if (ieee80211_add_srates_ie(sdata, skb, true, |
262 | ieee80211_add_ext_srates_ie(sdata, skb, true) || | 264 | local->oper_channel->band) || |
265 | ieee80211_add_ext_srates_ie(sdata, skb, true, | ||
266 | local->oper_channel->band) || | ||
263 | mesh_add_rsn_ie(skb, sdata) || | 267 | mesh_add_rsn_ie(skb, sdata) || |
264 | mesh_add_meshid_ie(skb, sdata) || | 268 | mesh_add_meshid_ie(skb, sdata) || |
265 | mesh_add_meshconf_ie(skb, sdata)) | 269 | mesh_add_meshconf_ie(skb, sdata)) |
266 | return -1; | 270 | goto free; |
267 | } else { /* WLAN_SP_MESH_PEERING_CLOSE */ | 271 | } else { /* WLAN_SP_MESH_PEERING_CLOSE */ |
272 | info->flags |= IEEE80211_TX_CTL_NO_ACK; | ||
268 | if (mesh_add_meshid_ie(skb, sdata)) | 273 | if (mesh_add_meshid_ie(skb, sdata)) |
269 | return -1; | 274 | goto free; |
270 | } | 275 | } |
271 | 276 | ||
272 | /* Add Mesh Peering Management element */ | 277 | /* Add Mesh Peering Management element */ |
@@ -285,11 +290,12 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
285 | ie_len += 2; /* reason code */ | 290 | ie_len += 2; /* reason code */ |
286 | break; | 291 | break; |
287 | default: | 292 | default: |
288 | return -EINVAL; | 293 | err = -EINVAL; |
294 | goto free; | ||
289 | } | 295 | } |
290 | 296 | ||
291 | if (WARN_ON(skb_tailroom(skb) < 2 + ie_len)) | 297 | if (WARN_ON(skb_tailroom(skb) < 2 + ie_len)) |
292 | return -ENOMEM; | 298 | goto free; |
293 | 299 | ||
294 | pos = skb_put(skb, 2 + ie_len); | 300 | pos = skb_put(skb, 2 + ie_len); |
295 | *pos++ = WLAN_EID_PEER_MGMT; | 301 | *pos++ = WLAN_EID_PEER_MGMT; |
@@ -310,14 +316,17 @@ static int mesh_plink_frame_tx(struct ieee80211_sub_if_data *sdata, | |||
310 | if (action != WLAN_SP_MESH_PEERING_CLOSE) { | 316 | if (action != WLAN_SP_MESH_PEERING_CLOSE) { |
311 | if (mesh_add_ht_cap_ie(skb, sdata) || | 317 | if (mesh_add_ht_cap_ie(skb, sdata) || |
312 | mesh_add_ht_oper_ie(skb, sdata)) | 318 | mesh_add_ht_oper_ie(skb, sdata)) |
313 | return -1; | 319 | goto free; |
314 | } | 320 | } |
315 | 321 | ||
316 | if (mesh_add_vendor_ies(skb, sdata)) | 322 | if (mesh_add_vendor_ies(skb, sdata)) |
317 | return -1; | 323 | goto free; |
318 | 324 | ||
319 | ieee80211_tx_skb(sdata, skb); | 325 | ieee80211_tx_skb(sdata, skb); |
320 | return 0; | 326 | return 0; |
327 | free: | ||
328 | kfree_skb(skb); | ||
329 | return err; | ||
321 | } | 330 | } |
322 | 331 | ||
323 | /** | 332 | /** |
@@ -362,9 +371,14 @@ static struct sta_info *mesh_peer_init(struct ieee80211_sub_if_data *sdata, | |||
362 | 371 | ||
363 | spin_lock_bh(&sta->lock); | 372 | spin_lock_bh(&sta->lock); |
364 | sta->last_rx = jiffies; | 373 | sta->last_rx = jiffies; |
374 | if (sta->plink_state == NL80211_PLINK_ESTAB) { | ||
375 | spin_unlock_bh(&sta->lock); | ||
376 | return sta; | ||
377 | } | ||
378 | |||
365 | sta->sta.supp_rates[band] = rates; | 379 | sta->sta.supp_rates[band] = rates; |
366 | if (elems->ht_cap_elem && | 380 | if (elems->ht_cap_elem && |
367 | sdata->local->_oper_channel_type != NL80211_CHAN_NO_HT) | 381 | sdata->vif.bss_conf.channel_type != NL80211_CHAN_NO_HT) |
368 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, | 382 | ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband, |
369 | elems->ht_cap_elem, | 383 | elems->ht_cap_elem, |
370 | &sta->sta.ht_cap); | 384 | &sta->sta.ht_cap); |
@@ -541,15 +555,14 @@ int mesh_plink_open(struct sta_info *sta) | |||
541 | void mesh_plink_block(struct sta_info *sta) | 555 | void mesh_plink_block(struct sta_info *sta) |
542 | { | 556 | { |
543 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 557 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
544 | bool deactivated; | 558 | u32 changed; |
545 | 559 | ||
546 | spin_lock_bh(&sta->lock); | 560 | spin_lock_bh(&sta->lock); |
547 | deactivated = __mesh_plink_deactivate(sta); | 561 | changed = __mesh_plink_deactivate(sta); |
548 | sta->plink_state = NL80211_PLINK_BLOCKED; | 562 | sta->plink_state = NL80211_PLINK_BLOCKED; |
549 | spin_unlock_bh(&sta->lock); | 563 | spin_unlock_bh(&sta->lock); |
550 | 564 | ||
551 | if (deactivated) | 565 | ieee80211_bss_info_change_notify(sdata, changed); |
552 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); | ||
553 | } | 566 | } |
554 | 567 | ||
555 | 568 | ||
@@ -852,9 +865,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
852 | del_timer(&sta->plink_timer); | 865 | del_timer(&sta->plink_timer); |
853 | sta->plink_state = NL80211_PLINK_ESTAB; | 866 | sta->plink_state = NL80211_PLINK_ESTAB; |
854 | spin_unlock_bh(&sta->lock); | 867 | spin_unlock_bh(&sta->lock); |
855 | mesh_plink_inc_estab_count(sdata); | 868 | changed |= mesh_plink_inc_estab_count(sdata); |
856 | changed |= mesh_set_ht_prot_mode(sdata); | 869 | changed |= mesh_set_ht_prot_mode(sdata); |
857 | changed |= BSS_CHANGED_BEACON; | ||
858 | mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n", | 870 | mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n", |
859 | sta->sta.addr); | 871 | sta->sta.addr); |
860 | break; | 872 | break; |
@@ -888,9 +900,8 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
888 | del_timer(&sta->plink_timer); | 900 | del_timer(&sta->plink_timer); |
889 | sta->plink_state = NL80211_PLINK_ESTAB; | 901 | sta->plink_state = NL80211_PLINK_ESTAB; |
890 | spin_unlock_bh(&sta->lock); | 902 | spin_unlock_bh(&sta->lock); |
891 | mesh_plink_inc_estab_count(sdata); | 903 | changed |= mesh_plink_inc_estab_count(sdata); |
892 | changed |= mesh_set_ht_prot_mode(sdata); | 904 | changed |= mesh_set_ht_prot_mode(sdata); |
893 | changed |= BSS_CHANGED_BEACON; | ||
894 | mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n", | 905 | mpl_dbg(sdata, "Mesh plink with %pM ESTABLISHED\n", |
895 | sta->sta.addr); | 906 | sta->sta.addr); |
896 | mesh_plink_frame_tx(sdata, | 907 | mesh_plink_frame_tx(sdata, |
@@ -908,13 +919,12 @@ void mesh_rx_plink_frame(struct ieee80211_sub_if_data *sdata, struct ieee80211_m | |||
908 | case CLS_ACPT: | 919 | case CLS_ACPT: |
909 | reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE); | 920 | reason = cpu_to_le16(WLAN_REASON_MESH_CLOSE); |
910 | sta->reason = reason; | 921 | sta->reason = reason; |
911 | __mesh_plink_deactivate(sta); | 922 | changed |= __mesh_plink_deactivate(sta); |
912 | sta->plink_state = NL80211_PLINK_HOLDING; | 923 | sta->plink_state = NL80211_PLINK_HOLDING; |
913 | llid = sta->llid; | 924 | llid = sta->llid; |
914 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); | 925 | mod_plink_timer(sta, dot11MeshHoldingTimeout(sdata)); |
915 | spin_unlock_bh(&sta->lock); | 926 | spin_unlock_bh(&sta->lock); |
916 | changed |= mesh_set_ht_prot_mode(sdata); | 927 | changed |= mesh_set_ht_prot_mode(sdata); |
917 | changed |= BSS_CHANGED_BEACON; | ||
918 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, | 928 | mesh_plink_frame_tx(sdata, WLAN_SP_MESH_PEERING_CLOSE, |
919 | sta->sta.addr, llid, plid, reason); | 929 | sta->sta.addr, llid, plid, reason); |
920 | break; | 930 | break; |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index cef0c9e79aba..a8cf70bf1cba 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -146,6 +146,9 @@ void ieee80211_sta_reset_beacon_monitor(struct ieee80211_sub_if_data *sdata) | |||
146 | if (sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER) | 146 | if (sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER) |
147 | return; | 147 | return; |
148 | 148 | ||
149 | if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) | ||
150 | return; | ||
151 | |||
149 | mod_timer(&sdata->u.mgd.bcn_mon_timer, | 152 | mod_timer(&sdata->u.mgd.bcn_mon_timer, |
150 | round_jiffies_up(jiffies + sdata->u.mgd.beacon_timeout)); | 153 | round_jiffies_up(jiffies + sdata->u.mgd.beacon_timeout)); |
151 | } | 154 | } |
@@ -182,15 +185,15 @@ static u32 ieee80211_config_ht_tx(struct ieee80211_sub_if_data *sdata, | |||
182 | u16 ht_opmode; | 185 | u16 ht_opmode; |
183 | bool disable_40 = false; | 186 | bool disable_40 = false; |
184 | 187 | ||
185 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 188 | sband = local->hw.wiphy->bands[local->oper_channel->band]; |
186 | 189 | ||
187 | switch (sdata->vif.bss_conf.channel_type) { | 190 | switch (sdata->vif.bss_conf.channel_type) { |
188 | case NL80211_CHAN_HT40PLUS: | 191 | case NL80211_CHAN_HT40PLUS: |
189 | if (local->hw.conf.channel->flags & IEEE80211_CHAN_NO_HT40PLUS) | 192 | if (local->oper_channel->flags & IEEE80211_CHAN_NO_HT40PLUS) |
190 | disable_40 = true; | 193 | disable_40 = true; |
191 | break; | 194 | break; |
192 | case NL80211_CHAN_HT40MINUS: | 195 | case NL80211_CHAN_HT40MINUS: |
193 | if (local->hw.conf.channel->flags & IEEE80211_CHAN_NO_HT40MINUS) | 196 | if (local->oper_channel->flags & IEEE80211_CHAN_NO_HT40MINUS) |
194 | disable_40 = true; | 197 | disable_40 = true; |
195 | break; | 198 | break; |
196 | default: | 199 | default: |
@@ -326,6 +329,26 @@ static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata, | |||
326 | ieee80211_ie_build_ht_cap(pos, &ht_cap, cap); | 329 | ieee80211_ie_build_ht_cap(pos, &ht_cap, cap); |
327 | } | 330 | } |
328 | 331 | ||
332 | static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata, | ||
333 | struct sk_buff *skb, | ||
334 | struct ieee80211_supported_band *sband) | ||
335 | { | ||
336 | u8 *pos; | ||
337 | u32 cap; | ||
338 | struct ieee80211_sta_vht_cap vht_cap; | ||
339 | |||
340 | BUILD_BUG_ON(sizeof(vht_cap) != sizeof(sband->vht_cap)); | ||
341 | |||
342 | memcpy(&vht_cap, &sband->vht_cap, sizeof(vht_cap)); | ||
343 | |||
344 | /* determine capability flags */ | ||
345 | cap = vht_cap.cap; | ||
346 | |||
347 | /* reserve and fill IE */ | ||
348 | pos = skb_put(skb, sizeof(struct ieee80211_vht_capabilities) + 2); | ||
349 | ieee80211_ie_build_vht_cap(pos, &vht_cap, cap); | ||
350 | } | ||
351 | |||
329 | static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | 352 | static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) |
330 | { | 353 | { |
331 | struct ieee80211_local *local = sdata->local; | 354 | struct ieee80211_local *local = sdata->local; |
@@ -371,6 +394,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
371 | 4 + /* power capability */ | 394 | 4 + /* power capability */ |
372 | 2 + 2 * sband->n_channels + /* supported channels */ | 395 | 2 + 2 * sband->n_channels + /* supported channels */ |
373 | 2 + sizeof(struct ieee80211_ht_cap) + /* HT */ | 396 | 2 + sizeof(struct ieee80211_ht_cap) + /* HT */ |
397 | 2 + sizeof(struct ieee80211_vht_capabilities) + /* VHT */ | ||
374 | assoc_data->ie_len + /* extra IEs */ | 398 | assoc_data->ie_len + /* extra IEs */ |
375 | 9, /* WMM */ | 399 | 9, /* WMM */ |
376 | GFP_KERNEL); | 400 | GFP_KERNEL); |
@@ -503,6 +527,9 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
503 | ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param, | 527 | ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param, |
504 | sband, local->oper_channel, ifmgd->ap_smps); | 528 | sband, local->oper_channel, ifmgd->ap_smps); |
505 | 529 | ||
530 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) | ||
531 | ieee80211_add_vht_ie(sdata, skb, sband); | ||
532 | |||
506 | /* if present, add any custom non-vendor IEs that go after HT */ | 533 | /* if present, add any custom non-vendor IEs that go after HT */ |
507 | if (assoc_data->ie_len && assoc_data->ie) { | 534 | if (assoc_data->ie_len && assoc_data->ie) { |
508 | noffset = ieee80211_ie_split_vendor(assoc_data->ie, | 535 | noffset = ieee80211_ie_split_vendor(assoc_data->ie, |
@@ -583,8 +610,6 @@ static void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | |||
583 | IEEE80211_SKB_CB(skb)->flags |= | 610 | IEEE80211_SKB_CB(skb)->flags |= |
584 | IEEE80211_TX_INTFL_DONT_ENCRYPT; | 611 | IEEE80211_TX_INTFL_DONT_ENCRYPT; |
585 | 612 | ||
586 | drv_mgd_prepare_tx(local, sdata); | ||
587 | |||
588 | ieee80211_tx_skb(sdata, skb); | 613 | ieee80211_tx_skb(sdata, skb); |
589 | } | 614 | } |
590 | } | 615 | } |
@@ -687,6 +712,7 @@ static void ieee80211_chswitch_work(struct work_struct *work) | |||
687 | /* XXX: shouldn't really modify cfg80211-owned data! */ | 712 | /* XXX: shouldn't really modify cfg80211-owned data! */ |
688 | ifmgd->associated->channel = sdata->local->oper_channel; | 713 | ifmgd->associated->channel = sdata->local->oper_channel; |
689 | 714 | ||
715 | /* XXX: wait for a beacon first? */ | ||
690 | ieee80211_wake_queues_by_reason(&sdata->local->hw, | 716 | ieee80211_wake_queues_by_reason(&sdata->local->hw, |
691 | IEEE80211_QUEUE_STOP_REASON_CSA); | 717 | IEEE80211_QUEUE_STOP_REASON_CSA); |
692 | out: | 718 | out: |
@@ -763,36 +789,32 @@ void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
763 | 789 | ||
764 | sdata->local->csa_channel = new_ch; | 790 | sdata->local->csa_channel = new_ch; |
765 | 791 | ||
792 | ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED; | ||
793 | |||
794 | if (sw_elem->mode) | ||
795 | ieee80211_stop_queues_by_reason(&sdata->local->hw, | ||
796 | IEEE80211_QUEUE_STOP_REASON_CSA); | ||
797 | |||
766 | if (sdata->local->ops->channel_switch) { | 798 | if (sdata->local->ops->channel_switch) { |
767 | /* use driver's channel switch callback */ | 799 | /* use driver's channel switch callback */ |
768 | struct ieee80211_channel_switch ch_switch; | 800 | struct ieee80211_channel_switch ch_switch = { |
769 | memset(&ch_switch, 0, sizeof(ch_switch)); | 801 | .timestamp = timestamp, |
770 | ch_switch.timestamp = timestamp; | 802 | .block_tx = sw_elem->mode, |
771 | if (sw_elem->mode) { | 803 | .channel = new_ch, |
772 | ch_switch.block_tx = true; | 804 | .count = sw_elem->count, |
773 | ieee80211_stop_queues_by_reason(&sdata->local->hw, | 805 | }; |
774 | IEEE80211_QUEUE_STOP_REASON_CSA); | 806 | |
775 | } | ||
776 | ch_switch.channel = new_ch; | ||
777 | ch_switch.count = sw_elem->count; | ||
778 | ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED; | ||
779 | drv_channel_switch(sdata->local, &ch_switch); | 807 | drv_channel_switch(sdata->local, &ch_switch); |
780 | return; | 808 | return; |
781 | } | 809 | } |
782 | 810 | ||
783 | /* channel switch handled in software */ | 811 | /* channel switch handled in software */ |
784 | if (sw_elem->count <= 1) { | 812 | if (sw_elem->count <= 1) |
785 | ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work); | 813 | ieee80211_queue_work(&sdata->local->hw, &ifmgd->chswitch_work); |
786 | } else { | 814 | else |
787 | if (sw_elem->mode) | ||
788 | ieee80211_stop_queues_by_reason(&sdata->local->hw, | ||
789 | IEEE80211_QUEUE_STOP_REASON_CSA); | ||
790 | ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED; | ||
791 | mod_timer(&ifmgd->chswitch_timer, | 815 | mod_timer(&ifmgd->chswitch_timer, |
792 | jiffies + | 816 | TU_TO_EXP_TIME(sw_elem->count * |
793 | msecs_to_jiffies(sw_elem->count * | 817 | cbss->beacon_interval)); |
794 | cbss->beacon_interval)); | ||
795 | } | ||
796 | } | 818 | } |
797 | 819 | ||
798 | static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, | 820 | static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, |
@@ -1007,6 +1029,16 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
1007 | ieee80211_change_ps(local); | 1029 | ieee80211_change_ps(local); |
1008 | } | 1030 | } |
1009 | 1031 | ||
1032 | void ieee80211_recalc_ps_vif(struct ieee80211_sub_if_data *sdata) | ||
1033 | { | ||
1034 | bool ps_allowed = ieee80211_powersave_allowed(sdata); | ||
1035 | |||
1036 | if (sdata->vif.bss_conf.ps != ps_allowed) { | ||
1037 | sdata->vif.bss_conf.ps = ps_allowed; | ||
1038 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_PS); | ||
1039 | } | ||
1040 | } | ||
1041 | |||
1010 | void ieee80211_dynamic_ps_disable_work(struct work_struct *work) | 1042 | void ieee80211_dynamic_ps_disable_work(struct work_struct *work) |
1011 | { | 1043 | { |
1012 | struct ieee80211_local *local = | 1044 | struct ieee80211_local *local = |
@@ -1239,7 +1271,7 @@ static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, | |||
1239 | } | 1271 | } |
1240 | 1272 | ||
1241 | use_short_slot = !!(capab & WLAN_CAPABILITY_SHORT_SLOT_TIME); | 1273 | use_short_slot = !!(capab & WLAN_CAPABILITY_SHORT_SLOT_TIME); |
1242 | if (sdata->local->hw.conf.channel->band == IEEE80211_BAND_5GHZ) | 1274 | if (sdata->local->oper_channel->band == IEEE80211_BAND_5GHZ) |
1243 | use_short_slot = true; | 1275 | use_short_slot = true; |
1244 | 1276 | ||
1245 | if (use_protection != bss_conf->use_cts_prot) { | 1277 | if (use_protection != bss_conf->use_cts_prot) { |
@@ -1310,6 +1342,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
1310 | ieee80211_recalc_smps(local); | 1342 | ieee80211_recalc_smps(local); |
1311 | mutex_unlock(&local->iflist_mtx); | 1343 | mutex_unlock(&local->iflist_mtx); |
1312 | 1344 | ||
1345 | ieee80211_recalc_ps_vif(sdata); | ||
1346 | |||
1313 | netif_tx_start_all_queues(sdata->dev); | 1347 | netif_tx_start_all_queues(sdata->dev); |
1314 | netif_carrier_on(sdata->dev); | 1348 | netif_carrier_on(sdata->dev); |
1315 | } | 1349 | } |
@@ -1371,6 +1405,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1371 | } | 1405 | } |
1372 | local->ps_sdata = NULL; | 1406 | local->ps_sdata = NULL; |
1373 | 1407 | ||
1408 | /* disable per-vif ps */ | ||
1409 | ieee80211_recalc_ps_vif(sdata); | ||
1410 | |||
1374 | /* flush out any pending frame (e.g. DELBA) before deauth/disassoc */ | 1411 | /* flush out any pending frame (e.g. DELBA) before deauth/disassoc */ |
1375 | if (tx) | 1412 | if (tx) |
1376 | drv_flush(local, false); | 1413 | drv_flush(local, false); |
@@ -1430,6 +1467,8 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1430 | del_timer_sync(&sdata->u.mgd.bcn_mon_timer); | 1467 | del_timer_sync(&sdata->u.mgd.bcn_mon_timer); |
1431 | del_timer_sync(&sdata->u.mgd.timer); | 1468 | del_timer_sync(&sdata->u.mgd.timer); |
1432 | del_timer_sync(&sdata->u.mgd.chswitch_timer); | 1469 | del_timer_sync(&sdata->u.mgd.chswitch_timer); |
1470 | |||
1471 | sdata->u.mgd.timers_running = 0; | ||
1433 | } | 1472 | } |
1434 | 1473 | ||
1435 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, | 1474 | void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata, |
@@ -1540,7 +1579,8 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata) | |||
1540 | ssid_len = ssid[1]; | 1579 | ssid_len = ssid[1]; |
1541 | 1580 | ||
1542 | ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL, | 1581 | ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL, |
1543 | 0, (u32) -1, true, false); | 1582 | 0, (u32) -1, true, false, |
1583 | ifmgd->associated->channel); | ||
1544 | } | 1584 | } |
1545 | 1585 | ||
1546 | ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms); | 1586 | ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms); |
@@ -1643,7 +1683,9 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw, | |||
1643 | ssid_len = ssid[1]; | 1683 | ssid_len = ssid[1]; |
1644 | 1684 | ||
1645 | skb = ieee80211_build_probe_req(sdata, cbss->bssid, | 1685 | skb = ieee80211_build_probe_req(sdata, cbss->bssid, |
1646 | (u32) -1, ssid + 2, ssid_len, | 1686 | (u32) -1, |
1687 | sdata->local->oper_channel, | ||
1688 | ssid + 2, ssid_len, | ||
1647 | NULL, 0, true); | 1689 | NULL, 0, true); |
1648 | 1690 | ||
1649 | return skb; | 1691 | return skb; |
@@ -1654,7 +1696,6 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata) | |||
1654 | { | 1696 | { |
1655 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1697 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1656 | struct ieee80211_local *local = sdata->local; | 1698 | struct ieee80211_local *local = sdata->local; |
1657 | u8 bssid[ETH_ALEN]; | ||
1658 | u8 frame_buf[DEAUTH_DISASSOC_LEN]; | 1699 | u8 frame_buf[DEAUTH_DISASSOC_LEN]; |
1659 | 1700 | ||
1660 | mutex_lock(&ifmgd->mtx); | 1701 | mutex_lock(&ifmgd->mtx); |
@@ -1663,9 +1704,8 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata) | |||
1663 | return; | 1704 | return; |
1664 | } | 1705 | } |
1665 | 1706 | ||
1666 | memcpy(bssid, ifmgd->associated->bssid, ETH_ALEN); | 1707 | sdata_info(sdata, "Connection to AP %pM lost\n", |
1667 | 1708 | ifmgd->associated->bssid); | |
1668 | sdata_info(sdata, "Connection to AP %pM lost\n", bssid); | ||
1669 | 1709 | ||
1670 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, | 1710 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, |
1671 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, | 1711 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, |
@@ -1683,7 +1723,7 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata) | |||
1683 | mutex_unlock(&local->mtx); | 1723 | mutex_unlock(&local->mtx); |
1684 | } | 1724 | } |
1685 | 1725 | ||
1686 | void ieee80211_beacon_connection_loss_work(struct work_struct *work) | 1726 | static void ieee80211_beacon_connection_loss_work(struct work_struct *work) |
1687 | { | 1727 | { |
1688 | struct ieee80211_sub_if_data *sdata = | 1728 | struct ieee80211_sub_if_data *sdata = |
1689 | container_of(work, struct ieee80211_sub_if_data, | 1729 | container_of(work, struct ieee80211_sub_if_data, |
@@ -2230,14 +2270,10 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
2230 | mutex_unlock(&local->iflist_mtx); | 2270 | mutex_unlock(&local->iflist_mtx); |
2231 | } | 2271 | } |
2232 | 2272 | ||
2233 | if (elems->ch_switch_elem && (elems->ch_switch_elem_len == 3) && | 2273 | if (elems->ch_switch_ie && |
2234 | (memcmp(mgmt->bssid, sdata->u.mgd.associated->bssid, | 2274 | memcmp(mgmt->bssid, sdata->u.mgd.associated->bssid, ETH_ALEN) == 0) |
2235 | ETH_ALEN) == 0)) { | 2275 | ieee80211_sta_process_chanswitch(sdata, elems->ch_switch_ie, |
2236 | struct ieee80211_channel_sw_ie *sw_elem = | ||
2237 | (struct ieee80211_channel_sw_ie *)elems->ch_switch_elem; | ||
2238 | ieee80211_sta_process_chanswitch(sdata, sw_elem, | ||
2239 | bss, rx_status->mactime); | 2276 | bss, rx_status->mactime); |
2240 | } | ||
2241 | } | 2277 | } |
2242 | 2278 | ||
2243 | 2279 | ||
@@ -2324,7 +2360,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2324 | if (baselen > len) | 2360 | if (baselen > len) |
2325 | return; | 2361 | return; |
2326 | 2362 | ||
2327 | if (rx_status->freq != local->hw.conf.channel->center_freq) | 2363 | if (rx_status->freq != local->oper_channel->center_freq) |
2328 | return; | 2364 | return; |
2329 | 2365 | ||
2330 | if (ifmgd->assoc_data && !ifmgd->assoc_data->have_beacon && | 2366 | if (ifmgd->assoc_data && !ifmgd->assoc_data->have_beacon && |
@@ -2488,7 +2524,7 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
2488 | !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) { | 2524 | !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) { |
2489 | struct ieee80211_supported_band *sband; | 2525 | struct ieee80211_supported_band *sband; |
2490 | 2526 | ||
2491 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 2527 | sband = local->hw.wiphy->bands[local->oper_channel->band]; |
2492 | 2528 | ||
2493 | changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation, | 2529 | changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation, |
2494 | bssid, true); | 2530 | bssid, true); |
@@ -2671,7 +2707,8 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) | |||
2671 | * will not answer to direct packet in unassociated state. | 2707 | * will not answer to direct packet in unassociated state. |
2672 | */ | 2708 | */ |
2673 | ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1], | 2709 | ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1], |
2674 | NULL, 0, (u32) -1, true, false); | 2710 | NULL, 0, (u32) -1, true, false, |
2711 | auth_data->bss->channel); | ||
2675 | } | 2712 | } |
2676 | 2713 | ||
2677 | auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; | 2714 | auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; |
@@ -2998,41 +3035,17 @@ int ieee80211_max_network_latency(struct notifier_block *nb, | |||
2998 | return 0; | 3035 | return 0; |
2999 | } | 3036 | } |
3000 | 3037 | ||
3001 | static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | 3038 | static int ieee80211_prep_channel(struct ieee80211_sub_if_data *sdata, |
3002 | struct cfg80211_bss *cbss, bool assoc) | 3039 | struct cfg80211_bss *cbss) |
3003 | { | 3040 | { |
3004 | struct ieee80211_local *local = sdata->local; | 3041 | struct ieee80211_local *local = sdata->local; |
3005 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 3042 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
3006 | struct ieee80211_bss *bss = (void *)cbss->priv; | ||
3007 | struct sta_info *sta = NULL; | ||
3008 | bool have_sta = false; | ||
3009 | int err; | ||
3010 | int ht_cfreq; | 3043 | int ht_cfreq; |
3011 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | 3044 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; |
3012 | const u8 *ht_oper_ie; | 3045 | const u8 *ht_oper_ie; |
3013 | const struct ieee80211_ht_operation *ht_oper = NULL; | 3046 | const struct ieee80211_ht_operation *ht_oper = NULL; |
3014 | struct ieee80211_supported_band *sband; | 3047 | struct ieee80211_supported_band *sband; |
3015 | 3048 | ||
3016 | if (WARN_ON(!ifmgd->auth_data && !ifmgd->assoc_data)) | ||
3017 | return -EINVAL; | ||
3018 | |||
3019 | if (assoc) { | ||
3020 | rcu_read_lock(); | ||
3021 | have_sta = sta_info_get(sdata, cbss->bssid); | ||
3022 | rcu_read_unlock(); | ||
3023 | } | ||
3024 | |||
3025 | if (!have_sta) { | ||
3026 | sta = sta_info_alloc(sdata, cbss->bssid, GFP_KERNEL); | ||
3027 | if (!sta) | ||
3028 | return -ENOMEM; | ||
3029 | } | ||
3030 | |||
3031 | mutex_lock(&local->mtx); | ||
3032 | ieee80211_recalc_idle(sdata->local); | ||
3033 | mutex_unlock(&local->mtx); | ||
3034 | |||
3035 | /* switch to the right channel */ | ||
3036 | sband = local->hw.wiphy->bands[cbss->channel->band]; | 3049 | sband = local->hw.wiphy->bands[cbss->channel->band]; |
3037 | 3050 | ||
3038 | ifmgd->flags &= ~IEEE80211_STA_DISABLE_40MHZ; | 3051 | ifmgd->flags &= ~IEEE80211_STA_DISABLE_40MHZ; |
@@ -3095,10 +3108,51 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3095 | local->oper_channel = cbss->channel; | 3108 | local->oper_channel = cbss->channel; |
3096 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 3109 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); |
3097 | 3110 | ||
3098 | if (sta) { | 3111 | return 0; |
3112 | } | ||
3113 | |||
3114 | static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | ||
3115 | struct cfg80211_bss *cbss, bool assoc) | ||
3116 | { | ||
3117 | struct ieee80211_local *local = sdata->local; | ||
3118 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
3119 | struct ieee80211_bss *bss = (void *)cbss->priv; | ||
3120 | struct sta_info *new_sta = NULL; | ||
3121 | bool have_sta = false; | ||
3122 | int err; | ||
3123 | |||
3124 | if (WARN_ON(!ifmgd->auth_data && !ifmgd->assoc_data)) | ||
3125 | return -EINVAL; | ||
3126 | |||
3127 | if (assoc) { | ||
3128 | rcu_read_lock(); | ||
3129 | have_sta = sta_info_get(sdata, cbss->bssid); | ||
3130 | rcu_read_unlock(); | ||
3131 | } | ||
3132 | |||
3133 | if (!have_sta) { | ||
3134 | new_sta = sta_info_alloc(sdata, cbss->bssid, GFP_KERNEL); | ||
3135 | if (!new_sta) | ||
3136 | return -ENOMEM; | ||
3137 | } | ||
3138 | |||
3139 | mutex_lock(&local->mtx); | ||
3140 | ieee80211_recalc_idle(sdata->local); | ||
3141 | mutex_unlock(&local->mtx); | ||
3142 | |||
3143 | if (new_sta) { | ||
3099 | u32 rates = 0, basic_rates = 0; | 3144 | u32 rates = 0, basic_rates = 0; |
3100 | bool have_higher_than_11mbit; | 3145 | bool have_higher_than_11mbit; |
3101 | int min_rate = INT_MAX, min_rate_index = -1; | 3146 | int min_rate = INT_MAX, min_rate_index = -1; |
3147 | struct ieee80211_supported_band *sband; | ||
3148 | |||
3149 | sband = local->hw.wiphy->bands[cbss->channel->band]; | ||
3150 | |||
3151 | err = ieee80211_prep_channel(sdata, cbss); | ||
3152 | if (err) { | ||
3153 | sta_info_free(local, new_sta); | ||
3154 | return err; | ||
3155 | } | ||
3102 | 3156 | ||
3103 | ieee80211_get_rates(sband, bss->supp_rates, | 3157 | ieee80211_get_rates(sband, bss->supp_rates, |
3104 | bss->supp_rates_len, | 3158 | bss->supp_rates_len, |
@@ -3120,7 +3174,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3120 | basic_rates = BIT(min_rate_index); | 3174 | basic_rates = BIT(min_rate_index); |
3121 | } | 3175 | } |
3122 | 3176 | ||
3123 | sta->sta.supp_rates[cbss->channel->band] = rates; | 3177 | new_sta->sta.supp_rates[cbss->channel->band] = rates; |
3124 | sdata->vif.bss_conf.basic_rates = basic_rates; | 3178 | sdata->vif.bss_conf.basic_rates = basic_rates; |
3125 | 3179 | ||
3126 | /* cf. IEEE 802.11 9.2.12 */ | 3180 | /* cf. IEEE 802.11 9.2.12 */ |
@@ -3143,10 +3197,10 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata, | |||
3143 | BSS_CHANGED_BEACON_INT); | 3197 | BSS_CHANGED_BEACON_INT); |
3144 | 3198 | ||
3145 | if (assoc) | 3199 | if (assoc) |
3146 | sta_info_pre_move_state(sta, IEEE80211_STA_AUTH); | 3200 | sta_info_pre_move_state(new_sta, IEEE80211_STA_AUTH); |
3147 | 3201 | ||
3148 | err = sta_info_insert(sta); | 3202 | err = sta_info_insert(new_sta); |
3149 | sta = NULL; | 3203 | new_sta = NULL; |
3150 | if (err) { | 3204 | if (err) { |
3151 | sdata_info(sdata, | 3205 | sdata_info(sdata, |
3152 | "failed to insert STA entry for the AP (error %d)\n", | 3206 | "failed to insert STA entry for the AP (error %d)\n", |
@@ -3298,9 +3352,13 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3298 | } | 3352 | } |
3299 | 3353 | ||
3300 | /* prepare assoc data */ | 3354 | /* prepare assoc data */ |
3301 | 3355 | ||
3302 | ifmgd->flags &= ~IEEE80211_STA_DISABLE_11N; | 3356 | /* |
3303 | ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; | 3357 | * keep only the 40 MHz disable bit set as it might have |
3358 | * been set during authentication already, all other bits | ||
3359 | * should be reset for a new connection | ||
3360 | */ | ||
3361 | ifmgd->flags &= IEEE80211_STA_DISABLE_40MHZ; | ||
3304 | 3362 | ||
3305 | ifmgd->beacon_crc_valid = false; | 3363 | ifmgd->beacon_crc_valid = false; |
3306 | 3364 | ||
@@ -3316,21 +3374,34 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
3316 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP || | 3374 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_TKIP || |
3317 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) { | 3375 | req->crypto.ciphers_pairwise[i] == WLAN_CIPHER_SUITE_WEP104) { |
3318 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | 3376 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; |
3377 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; | ||
3319 | netdev_info(sdata->dev, | 3378 | netdev_info(sdata->dev, |
3320 | "disabling HT due to WEP/TKIP use\n"); | 3379 | "disabling HT/VHT due to WEP/TKIP use\n"); |
3321 | } | 3380 | } |
3322 | } | 3381 | } |
3323 | 3382 | ||
3324 | if (req->flags & ASSOC_REQ_DISABLE_HT) | 3383 | if (req->flags & ASSOC_REQ_DISABLE_HT) { |
3325 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | 3384 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; |
3385 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; | ||
3386 | } | ||
3326 | 3387 | ||
3327 | /* Also disable HT if we don't support it or the AP doesn't use WMM */ | 3388 | /* Also disable HT if we don't support it or the AP doesn't use WMM */ |
3328 | sband = local->hw.wiphy->bands[req->bss->channel->band]; | 3389 | sband = local->hw.wiphy->bands[req->bss->channel->band]; |
3329 | if (!sband->ht_cap.ht_supported || | 3390 | if (!sband->ht_cap.ht_supported || |
3330 | local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) { | 3391 | local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) { |
3331 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; | 3392 | ifmgd->flags |= IEEE80211_STA_DISABLE_11N; |
3332 | netdev_info(sdata->dev, | 3393 | if (!bss->wmm_used) |
3333 | "disabling HT as WMM/QoS is not supported\n"); | 3394 | netdev_info(sdata->dev, |
3395 | "disabling HT as WMM/QoS is not supported by the AP\n"); | ||
3396 | } | ||
3397 | |||
3398 | /* disable VHT if we don't support it or the AP doesn't use WMM */ | ||
3399 | if (!sband->vht_cap.vht_supported || | ||
3400 | local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used) { | ||
3401 | ifmgd->flags |= IEEE80211_STA_DISABLE_VHT; | ||
3402 | if (!bss->wmm_used) | ||
3403 | netdev_info(sdata->dev, | ||
3404 | "disabling VHT as WMM/QoS is not supported by the AP\n"); | ||
3334 | } | 3405 | } |
3335 | 3406 | ||
3336 | memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa)); | 3407 | memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa)); |
@@ -3465,14 +3536,17 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
3465 | req->bssid, req->reason_code); | 3536 | req->bssid, req->reason_code); |
3466 | 3537 | ||
3467 | if (ifmgd->associated && | 3538 | if (ifmgd->associated && |
3468 | ether_addr_equal(ifmgd->associated->bssid, req->bssid)) | 3539 | ether_addr_equal(ifmgd->associated->bssid, req->bssid)) { |
3469 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, | 3540 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, |
3470 | req->reason_code, true, frame_buf); | 3541 | req->reason_code, true, frame_buf); |
3471 | else | 3542 | } else { |
3543 | drv_mgd_prepare_tx(sdata->local, sdata); | ||
3472 | ieee80211_send_deauth_disassoc(sdata, req->bssid, | 3544 | ieee80211_send_deauth_disassoc(sdata, req->bssid, |
3473 | IEEE80211_STYPE_DEAUTH, | 3545 | IEEE80211_STYPE_DEAUTH, |
3474 | req->reason_code, true, | 3546 | req->reason_code, true, |
3475 | frame_buf); | 3547 | frame_buf); |
3548 | } | ||
3549 | |||
3476 | mutex_unlock(&ifmgd->mtx); | 3550 | mutex_unlock(&ifmgd->mtx); |
3477 | 3551 | ||
3478 | __cfg80211_send_deauth(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN); | 3552 | __cfg80211_send_deauth(sdata->dev, frame_buf, DEAUTH_DISASSOC_LEN); |
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index 635c3250c668..507121dad082 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -116,6 +116,9 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, | |||
116 | if (!ieee80211_sdata_running(sdata)) | 116 | if (!ieee80211_sdata_running(sdata)) |
117 | continue; | 117 | continue; |
118 | 118 | ||
119 | if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) | ||
120 | continue; | ||
121 | |||
119 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) | 122 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) |
120 | set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); | 123 | set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); |
121 | 124 | ||
@@ -144,6 +147,9 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, | |||
144 | 147 | ||
145 | mutex_lock(&local->iflist_mtx); | 148 | mutex_lock(&local->iflist_mtx); |
146 | list_for_each_entry(sdata, &local->interfaces, list) { | 149 | list_for_each_entry(sdata, &local->interfaces, list) { |
150 | if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) | ||
151 | continue; | ||
152 | |||
147 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) | 153 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) |
148 | clear_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); | 154 | clear_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); |
149 | 155 | ||
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index 6e4fd32c6617..10de668eb9f6 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h | |||
@@ -56,7 +56,7 @@ static inline void rate_control_rate_init(struct sta_info *sta) | |||
56 | if (!ref) | 56 | if (!ref) |
57 | return; | 57 | return; |
58 | 58 | ||
59 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 59 | sband = local->hw.wiphy->bands[local->oper_channel->band]; |
60 | 60 | ||
61 | ref->ops->rate_init(ref->priv, sband, ista, priv_sta); | 61 | ref->ops->rate_init(ref->priv, sband, ista, priv_sta); |
62 | set_sta_flag(sta, WLAN_STA_RATE_CONTROL); | 62 | set_sta_flag(sta, WLAN_STA_RATE_CONTROL); |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 0cb4edee6af5..b382605c5733 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -60,7 +60,9 @@ static inline int should_drop_frame(struct sk_buff *skb, | |||
60 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 60 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
61 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | 61 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; |
62 | 62 | ||
63 | if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC)) | 63 | if (status->flag & (RX_FLAG_FAILED_FCS_CRC | |
64 | RX_FLAG_FAILED_PLCP_CRC | | ||
65 | RX_FLAG_AMPDU_IS_ZEROLEN)) | ||
64 | return 1; | 66 | return 1; |
65 | if (unlikely(skb->len < 16 + present_fcs_len)) | 67 | if (unlikely(skb->len < 16 + present_fcs_len)) |
66 | return 1; | 68 | return 1; |
@@ -91,6 +93,13 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local, | |||
91 | if (status->flag & RX_FLAG_HT) /* HT info */ | 93 | if (status->flag & RX_FLAG_HT) /* HT info */ |
92 | len += 3; | 94 | len += 3; |
93 | 95 | ||
96 | if (status->flag & RX_FLAG_AMPDU_DETAILS) { | ||
97 | /* padding */ | ||
98 | while (len & 3) | ||
99 | len++; | ||
100 | len += 8; | ||
101 | } | ||
102 | |||
94 | return len; | 103 | return len; |
95 | } | 104 | } |
96 | 105 | ||
@@ -215,6 +224,37 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
215 | pos++; | 224 | pos++; |
216 | *pos++ = status->rate_idx; | 225 | *pos++ = status->rate_idx; |
217 | } | 226 | } |
227 | |||
228 | if (status->flag & RX_FLAG_AMPDU_DETAILS) { | ||
229 | u16 flags = 0; | ||
230 | |||
231 | /* ensure 4 byte alignment */ | ||
232 | while ((pos - (u8 *)rthdr) & 3) | ||
233 | pos++; | ||
234 | rthdr->it_present |= | ||
235 | cpu_to_le32(1 << IEEE80211_RADIOTAP_AMPDU_STATUS); | ||
236 | put_unaligned_le32(status->ampdu_reference, pos); | ||
237 | pos += 4; | ||
238 | if (status->flag & RX_FLAG_AMPDU_REPORT_ZEROLEN) | ||
239 | flags |= IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN; | ||
240 | if (status->flag & RX_FLAG_AMPDU_IS_ZEROLEN) | ||
241 | flags |= IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN; | ||
242 | if (status->flag & RX_FLAG_AMPDU_LAST_KNOWN) | ||
243 | flags |= IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN; | ||
244 | if (status->flag & RX_FLAG_AMPDU_IS_LAST) | ||
245 | flags |= IEEE80211_RADIOTAP_AMPDU_IS_LAST; | ||
246 | if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_ERROR) | ||
247 | flags |= IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_ERR; | ||
248 | if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_KNOWN) | ||
249 | flags |= IEEE80211_RADIOTAP_AMPDU_DELIM_CRC_KNOWN; | ||
250 | put_unaligned_le16(flags, pos); | ||
251 | pos += 2; | ||
252 | if (status->flag & RX_FLAG_AMPDU_DELIM_CRC_KNOWN) | ||
253 | *pos++ = status->ampdu_delimiter_crc; | ||
254 | else | ||
255 | *pos++ = 0; | ||
256 | *pos++ = 0; | ||
257 | } | ||
218 | } | 258 | } |
219 | 259 | ||
220 | /* | 260 | /* |
@@ -2268,7 +2308,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx) | |||
2268 | 2308 | ||
2269 | goto queue; | 2309 | goto queue; |
2270 | case WLAN_CATEGORY_SPECTRUM_MGMT: | 2310 | case WLAN_CATEGORY_SPECTRUM_MGMT: |
2271 | if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ) | 2311 | if (status->band != IEEE80211_BAND_5GHZ) |
2272 | break; | 2312 | break; |
2273 | 2313 | ||
2274 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 2314 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
@@ -2772,8 +2812,7 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
2772 | if (!bssid) { | 2812 | if (!bssid) { |
2773 | if (!ether_addr_equal(sdata->vif.addr, hdr->addr1)) | 2813 | if (!ether_addr_equal(sdata->vif.addr, hdr->addr1)) |
2774 | return 0; | 2814 | return 0; |
2775 | } else if (!ieee80211_bssid_match(bssid, | 2815 | } else if (!ieee80211_bssid_match(bssid, sdata->vif.addr)) { |
2776 | sdata->vif.addr)) { | ||
2777 | /* | 2816 | /* |
2778 | * Accept public action frames even when the | 2817 | * Accept public action frames even when the |
2779 | * BSSID doesn't match, this is used for P2P | 2818 | * BSSID doesn't match, this is used for P2P |
@@ -2793,9 +2832,18 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
2793 | if (!ether_addr_equal(sdata->u.wds.remote_addr, hdr->addr2)) | 2832 | if (!ether_addr_equal(sdata->u.wds.remote_addr, hdr->addr2)) |
2794 | return 0; | 2833 | return 0; |
2795 | break; | 2834 | break; |
2835 | case NL80211_IFTYPE_P2P_DEVICE: | ||
2836 | if (!ieee80211_is_public_action(hdr, skb->len) && | ||
2837 | !ieee80211_is_probe_req(hdr->frame_control) && | ||
2838 | !ieee80211_is_probe_resp(hdr->frame_control) && | ||
2839 | !ieee80211_is_beacon(hdr->frame_control)) | ||
2840 | return 0; | ||
2841 | if (!ether_addr_equal(sdata->vif.addr, hdr->addr1)) | ||
2842 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; | ||
2843 | break; | ||
2796 | default: | 2844 | default: |
2797 | /* should never get here */ | 2845 | /* should never get here */ |
2798 | WARN_ON(1); | 2846 | WARN_ON_ONCE(1); |
2799 | break; | 2847 | break; |
2800 | } | 2848 | } |
2801 | 2849 | ||
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index bcaee5d12839..740e414d44f4 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -299,7 +299,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, | |||
299 | if (local->scan_req != local->int_scan_req) | 299 | if (local->scan_req != local->int_scan_req) |
300 | cfg80211_scan_done(local->scan_req, aborted); | 300 | cfg80211_scan_done(local->scan_req, aborted); |
301 | local->scan_req = NULL; | 301 | local->scan_req = NULL; |
302 | local->scan_sdata = NULL; | 302 | rcu_assign_pointer(local->scan_sdata, NULL); |
303 | 303 | ||
304 | local->scanning = 0; | 304 | local->scanning = 0; |
305 | local->scan_channel = NULL; | 305 | local->scan_channel = NULL; |
@@ -416,7 +416,8 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, | |||
416 | local->scan_req->ssids[i].ssid_len, | 416 | local->scan_req->ssids[i].ssid_len, |
417 | local->scan_req->ie, local->scan_req->ie_len, | 417 | local->scan_req->ie, local->scan_req->ie_len, |
418 | local->scan_req->rates[band], false, | 418 | local->scan_req->rates[band], false, |
419 | local->scan_req->no_cck); | 419 | local->scan_req->no_cck, |
420 | local->hw.conf.channel); | ||
420 | 421 | ||
421 | /* | 422 | /* |
422 | * After sending probe requests, wait for probe responses | 423 | * After sending probe requests, wait for probe responses |
@@ -479,11 +480,10 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
479 | if (local->ops->hw_scan) { | 480 | if (local->ops->hw_scan) { |
480 | __set_bit(SCAN_HW_SCANNING, &local->scanning); | 481 | __set_bit(SCAN_HW_SCANNING, &local->scanning); |
481 | } else if ((req->n_channels == 1) && | 482 | } else if ((req->n_channels == 1) && |
482 | (req->channels[0]->center_freq == | 483 | (req->channels[0] == local->oper_channel)) { |
483 | local->hw.conf.channel->center_freq)) { | 484 | /* |
484 | 485 | * If we are scanning only on the operating channel | |
485 | /* If we are scanning only on the current channel, then | 486 | * then we do not need to stop normal activities |
486 | * we do not need to stop normal activities | ||
487 | */ | 487 | */ |
488 | unsigned long next_delay; | 488 | unsigned long next_delay; |
489 | 489 | ||
@@ -984,7 +984,6 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata) | |||
984 | kfree(local->sched_scan_ies.ie[i]); | 984 | kfree(local->sched_scan_ies.ie[i]); |
985 | 985 | ||
986 | drv_sched_scan_stop(local, sdata); | 986 | drv_sched_scan_stop(local, sdata); |
987 | rcu_assign_pointer(local->sched_scan_sdata, NULL); | ||
988 | } | 987 | } |
989 | out: | 988 | out: |
990 | mutex_unlock(&local->mtx); | 989 | mutex_unlock(&local->mtx); |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 8cd72914cdaf..b0801b7d572d 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -519,19 +519,27 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
519 | u64 cookie = (unsigned long)skb; | 519 | u64 cookie = (unsigned long)skb; |
520 | acked = info->flags & IEEE80211_TX_STAT_ACK; | 520 | acked = info->flags & IEEE80211_TX_STAT_ACK; |
521 | 521 | ||
522 | /* | ||
523 | * TODO: When we have non-netdev frame TX, | ||
524 | * we cannot use skb->dev->ieee80211_ptr | ||
525 | */ | ||
526 | |||
527 | if (ieee80211_is_nullfunc(hdr->frame_control) || | 522 | if (ieee80211_is_nullfunc(hdr->frame_control) || |
528 | ieee80211_is_qos_nullfunc(hdr->frame_control)) | 523 | ieee80211_is_qos_nullfunc(hdr->frame_control)) { |
529 | cfg80211_probe_status(skb->dev, hdr->addr1, | 524 | cfg80211_probe_status(skb->dev, hdr->addr1, |
530 | cookie, acked, GFP_ATOMIC); | 525 | cookie, acked, GFP_ATOMIC); |
531 | else | 526 | } else if (skb->dev) { |
532 | cfg80211_mgmt_tx_status( | 527 | cfg80211_mgmt_tx_status( |
533 | skb->dev->ieee80211_ptr, cookie, skb->data, | 528 | skb->dev->ieee80211_ptr, cookie, skb->data, |
534 | skb->len, acked, GFP_ATOMIC); | 529 | skb->len, acked, GFP_ATOMIC); |
530 | } else { | ||
531 | struct ieee80211_sub_if_data *p2p_sdata; | ||
532 | |||
533 | rcu_read_lock(); | ||
534 | |||
535 | p2p_sdata = rcu_dereference(local->p2p_sdata); | ||
536 | if (p2p_sdata) { | ||
537 | cfg80211_mgmt_tx_status( | ||
538 | &p2p_sdata->wdev, cookie, skb->data, | ||
539 | skb->len, acked, GFP_ATOMIC); | ||
540 | } | ||
541 | rcu_read_unlock(); | ||
542 | } | ||
535 | } | 543 | } |
536 | 544 | ||
537 | if (unlikely(info->ack_frame_id)) { | 545 | if (unlikely(info->ack_frame_id)) { |
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index c6d33b55b2df..18d9c8a52e9e 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -24,7 +24,7 @@ | |||
24 | __string(vif_name, sdata->dev ? sdata->dev->name : "<nodev>") | 24 | __string(vif_name, sdata->dev ? sdata->dev->name : "<nodev>") |
25 | #define VIF_ASSIGN __entry->vif_type = sdata->vif.type; __entry->sdata = sdata; \ | 25 | #define VIF_ASSIGN __entry->vif_type = sdata->vif.type; __entry->sdata = sdata; \ |
26 | __entry->p2p = sdata->vif.p2p; \ | 26 | __entry->p2p = sdata->vif.p2p; \ |
27 | __assign_str(vif_name, sdata->dev ? sdata->dev->name : "<nodev>") | 27 | __assign_str(vif_name, sdata->dev ? sdata->dev->name : sdata->name) |
28 | #define VIF_PR_FMT " vif:%s(%d%s)" | 28 | #define VIF_PR_FMT " vif:%s(%d%s)" |
29 | #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : "" | 29 | #define VIF_PR_ARG __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : "" |
30 | 30 | ||
@@ -274,9 +274,12 @@ TRACE_EVENT(drv_config, | |||
274 | __entry->dynamic_ps_timeout = local->hw.conf.dynamic_ps_timeout; | 274 | __entry->dynamic_ps_timeout = local->hw.conf.dynamic_ps_timeout; |
275 | __entry->max_sleep_period = local->hw.conf.max_sleep_period; | 275 | __entry->max_sleep_period = local->hw.conf.max_sleep_period; |
276 | __entry->listen_interval = local->hw.conf.listen_interval; | 276 | __entry->listen_interval = local->hw.conf.listen_interval; |
277 | __entry->long_frame_max_tx_count = local->hw.conf.long_frame_max_tx_count; | 277 | __entry->long_frame_max_tx_count = |
278 | __entry->short_frame_max_tx_count = local->hw.conf.short_frame_max_tx_count; | 278 | local->hw.conf.long_frame_max_tx_count; |
279 | __entry->center_freq = local->hw.conf.channel->center_freq; | 279 | __entry->short_frame_max_tx_count = |
280 | local->hw.conf.short_frame_max_tx_count; | ||
281 | __entry->center_freq = local->hw.conf.channel ? | ||
282 | local->hw.conf.channel->center_freq : 0; | ||
280 | __entry->channel_type = local->hw.conf.channel_type; | 283 | __entry->channel_type = local->hw.conf.channel_type; |
281 | __entry->smps = local->hw.conf.smps_mode; | 284 | __entry->smps = local->hw.conf.smps_mode; |
282 | ), | 285 | ), |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index acf712ffb5e6..29eb4e678235 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -55,7 +55,7 @@ static __le16 ieee80211_duration(struct ieee80211_tx_data *tx, | |||
55 | if (WARN_ON_ONCE(info->control.rates[0].idx < 0)) | 55 | if (WARN_ON_ONCE(info->control.rates[0].idx < 0)) |
56 | return 0; | 56 | return 0; |
57 | 57 | ||
58 | sband = local->hw.wiphy->bands[tx->channel->band]; | 58 | sband = local->hw.wiphy->bands[info->band]; |
59 | txrate = &sband->bitrates[info->control.rates[0].idx]; | 59 | txrate = &sband->bitrates[info->control.rates[0].idx]; |
60 | 60 | ||
61 | erp = txrate->flags & IEEE80211_RATE_ERP_G; | 61 | erp = txrate->flags & IEEE80211_RATE_ERP_G; |
@@ -615,7 +615,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
615 | 615 | ||
616 | memset(&txrc, 0, sizeof(txrc)); | 616 | memset(&txrc, 0, sizeof(txrc)); |
617 | 617 | ||
618 | sband = tx->local->hw.wiphy->bands[tx->channel->band]; | 618 | sband = tx->local->hw.wiphy->bands[info->band]; |
619 | 619 | ||
620 | len = min_t(u32, tx->skb->len + FCS_LEN, | 620 | len = min_t(u32, tx->skb->len + FCS_LEN, |
621 | tx->local->hw.wiphy->frag_threshold); | 621 | tx->local->hw.wiphy->frag_threshold); |
@@ -626,13 +626,13 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
626 | txrc.bss_conf = &tx->sdata->vif.bss_conf; | 626 | txrc.bss_conf = &tx->sdata->vif.bss_conf; |
627 | txrc.skb = tx->skb; | 627 | txrc.skb = tx->skb; |
628 | txrc.reported_rate.idx = -1; | 628 | txrc.reported_rate.idx = -1; |
629 | txrc.rate_idx_mask = tx->sdata->rc_rateidx_mask[tx->channel->band]; | 629 | txrc.rate_idx_mask = tx->sdata->rc_rateidx_mask[info->band]; |
630 | if (txrc.rate_idx_mask == (1 << sband->n_bitrates) - 1) | 630 | if (txrc.rate_idx_mask == (1 << sband->n_bitrates) - 1) |
631 | txrc.max_rate_idx = -1; | 631 | txrc.max_rate_idx = -1; |
632 | else | 632 | else |
633 | txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; | 633 | txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; |
634 | memcpy(txrc.rate_idx_mcs_mask, | 634 | memcpy(txrc.rate_idx_mcs_mask, |
635 | tx->sdata->rc_rateidx_mcs_mask[tx->channel->band], | 635 | tx->sdata->rc_rateidx_mcs_mask[info->band], |
636 | sizeof(txrc.rate_idx_mcs_mask)); | 636 | sizeof(txrc.rate_idx_mcs_mask)); |
637 | txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP || | 637 | txrc.bss = (tx->sdata->vif.type == NL80211_IFTYPE_AP || |
638 | tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT || | 638 | tx->sdata->vif.type == NL80211_IFTYPE_MESH_POINT || |
@@ -667,7 +667,7 @@ ieee80211_tx_h_rate_ctrl(struct ieee80211_tx_data *tx) | |||
667 | "scanning and associated. Target station: " | 667 | "scanning and associated. Target station: " |
668 | "%pM on %d GHz band\n", | 668 | "%pM on %d GHz band\n", |
669 | tx->sdata->name, hdr->addr1, | 669 | tx->sdata->name, hdr->addr1, |
670 | tx->channel->band ? 5 : 2)) | 670 | info->band ? 5 : 2)) |
671 | return TX_DROP; | 671 | return TX_DROP; |
672 | 672 | ||
673 | /* | 673 | /* |
@@ -1131,7 +1131,6 @@ ieee80211_tx_prepare(struct ieee80211_sub_if_data *sdata, | |||
1131 | tx->skb = skb; | 1131 | tx->skb = skb; |
1132 | tx->local = local; | 1132 | tx->local = local; |
1133 | tx->sdata = sdata; | 1133 | tx->sdata = sdata; |
1134 | tx->channel = local->hw.conf.channel; | ||
1135 | __skb_queue_head_init(&tx->skbs); | 1134 | __skb_queue_head_init(&tx->skbs); |
1136 | 1135 | ||
1137 | /* | 1136 | /* |
@@ -1204,6 +1203,7 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local, | |||
1204 | struct sk_buff_head *skbs, | 1203 | struct sk_buff_head *skbs, |
1205 | bool txpending) | 1204 | bool txpending) |
1206 | { | 1205 | { |
1206 | struct ieee80211_tx_control control; | ||
1207 | struct sk_buff *skb, *tmp; | 1207 | struct sk_buff *skb, *tmp; |
1208 | unsigned long flags; | 1208 | unsigned long flags; |
1209 | 1209 | ||
@@ -1240,10 +1240,10 @@ static bool ieee80211_tx_frags(struct ieee80211_local *local, | |||
1240 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 1240 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
1241 | 1241 | ||
1242 | info->control.vif = vif; | 1242 | info->control.vif = vif; |
1243 | info->control.sta = sta; | 1243 | control.sta = sta; |
1244 | 1244 | ||
1245 | __skb_unlink(skb, skbs); | 1245 | __skb_unlink(skb, skbs); |
1246 | drv_tx(local, skb); | 1246 | drv_tx(local, &control, skb); |
1247 | } | 1247 | } |
1248 | 1248 | ||
1249 | return true; | 1249 | return true; |
@@ -1399,8 +1399,7 @@ static bool ieee80211_tx(struct ieee80211_sub_if_data *sdata, | |||
1399 | goto out; | 1399 | goto out; |
1400 | } | 1400 | } |
1401 | 1401 | ||
1402 | tx.channel = local->hw.conf.channel; | 1402 | info->band = local->hw.conf.channel->band; |
1403 | info->band = tx.channel->band; | ||
1404 | 1403 | ||
1405 | /* set up hw_queue value early */ | 1404 | /* set up hw_queue value early */ |
1406 | if (!(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) || | 1405 | if (!(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN) || |
@@ -1720,7 +1719,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1720 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1719 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1721 | struct ieee80211_local *local = sdata->local; | 1720 | struct ieee80211_local *local = sdata->local; |
1722 | struct ieee80211_tx_info *info; | 1721 | struct ieee80211_tx_info *info; |
1723 | int ret = NETDEV_TX_BUSY, head_need; | 1722 | int head_need; |
1724 | u16 ethertype, hdrlen, meshhdrlen = 0; | 1723 | u16 ethertype, hdrlen, meshhdrlen = 0; |
1725 | __le16 fc; | 1724 | __le16 fc; |
1726 | struct ieee80211_hdr hdr; | 1725 | struct ieee80211_hdr hdr; |
@@ -1736,10 +1735,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1736 | u32 info_flags = 0; | 1735 | u32 info_flags = 0; |
1737 | u16 info_id = 0; | 1736 | u16 info_id = 0; |
1738 | 1737 | ||
1739 | if (unlikely(skb->len < ETH_HLEN)) { | 1738 | if (unlikely(skb->len < ETH_HLEN)) |
1740 | ret = NETDEV_TX_OK; | ||
1741 | goto fail; | 1739 | goto fail; |
1742 | } | ||
1743 | 1740 | ||
1744 | /* convert Ethernet header to proper 802.11 header (based on | 1741 | /* convert Ethernet header to proper 802.11 header (based on |
1745 | * operation mode) */ | 1742 | * operation mode) */ |
@@ -1787,7 +1784,6 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1787 | if (!sdata->u.mesh.mshcfg.dot11MeshTTL) { | 1784 | if (!sdata->u.mesh.mshcfg.dot11MeshTTL) { |
1788 | /* Do not send frames with mesh_ttl == 0 */ | 1785 | /* Do not send frames with mesh_ttl == 0 */ |
1789 | sdata->u.mesh.mshstats.dropped_frames_ttl++; | 1786 | sdata->u.mesh.mshstats.dropped_frames_ttl++; |
1790 | ret = NETDEV_TX_OK; | ||
1791 | goto fail; | 1787 | goto fail; |
1792 | } | 1788 | } |
1793 | rcu_read_lock(); | 1789 | rcu_read_lock(); |
@@ -1811,37 +1807,31 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1811 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, | 1807 | meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr, |
1812 | sdata, NULL, NULL); | 1808 | sdata, NULL, NULL); |
1813 | } else { | 1809 | } else { |
1814 | int is_mesh_mcast = 1; | 1810 | /* DS -> MBSS (802.11-2012 13.11.3.3). |
1815 | const u8 *mesh_da; | 1811 | * For unicast with unknown forwarding information, |
1812 | * destination might be in the MBSS or if that fails | ||
1813 | * forwarded to another mesh gate. In either case | ||
1814 | * resolution will be handled in ieee80211_xmit(), so | ||
1815 | * leave the original DA. This also works for mcast */ | ||
1816 | const u8 *mesh_da = skb->data; | ||
1817 | |||
1818 | if (mppath) | ||
1819 | mesh_da = mppath->mpp; | ||
1820 | else if (mpath) | ||
1821 | mesh_da = mpath->dst; | ||
1822 | rcu_read_unlock(); | ||
1816 | 1823 | ||
1817 | if (is_multicast_ether_addr(skb->data)) | ||
1818 | /* DA TA mSA AE:SA */ | ||
1819 | mesh_da = skb->data; | ||
1820 | else { | ||
1821 | static const u8 bcast[ETH_ALEN] = | ||
1822 | { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | ||
1823 | if (mppath) { | ||
1824 | /* RA TA mDA mSA AE:DA SA */ | ||
1825 | mesh_da = mppath->mpp; | ||
1826 | is_mesh_mcast = 0; | ||
1827 | } else if (mpath) { | ||
1828 | mesh_da = mpath->dst; | ||
1829 | is_mesh_mcast = 0; | ||
1830 | } else { | ||
1831 | /* DA TA mSA AE:SA */ | ||
1832 | mesh_da = bcast; | ||
1833 | } | ||
1834 | } | ||
1835 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, | 1824 | hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc, |
1836 | mesh_da, sdata->vif.addr); | 1825 | mesh_da, sdata->vif.addr); |
1837 | rcu_read_unlock(); | 1826 | if (is_multicast_ether_addr(mesh_da)) |
1838 | if (is_mesh_mcast) | 1827 | /* DA TA mSA AE:SA */ |
1839 | meshhdrlen = | 1828 | meshhdrlen = |
1840 | ieee80211_new_mesh_header(&mesh_hdr, | 1829 | ieee80211_new_mesh_header(&mesh_hdr, |
1841 | sdata, | 1830 | sdata, |
1842 | skb->data + ETH_ALEN, | 1831 | skb->data + ETH_ALEN, |
1843 | NULL); | 1832 | NULL); |
1844 | else | 1833 | else |
1834 | /* RA TA mDA mSA AE:DA SA */ | ||
1845 | meshhdrlen = | 1835 | meshhdrlen = |
1846 | ieee80211_new_mesh_header(&mesh_hdr, | 1836 | ieee80211_new_mesh_header(&mesh_hdr, |
1847 | sdata, | 1837 | sdata, |
@@ -1880,10 +1870,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1880 | 1870 | ||
1881 | if (tdls_direct) { | 1871 | if (tdls_direct) { |
1882 | /* link during setup - throw out frames to peer */ | 1872 | /* link during setup - throw out frames to peer */ |
1883 | if (!tdls_auth) { | 1873 | if (!tdls_auth) |
1884 | ret = NETDEV_TX_OK; | ||
1885 | goto fail; | 1874 | goto fail; |
1886 | } | ||
1887 | 1875 | ||
1888 | /* DA SA BSSID */ | 1876 | /* DA SA BSSID */ |
1889 | memcpy(hdr.addr1, skb->data, ETH_ALEN); | 1877 | memcpy(hdr.addr1, skb->data, ETH_ALEN); |
@@ -1917,7 +1905,6 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1917 | hdrlen = 24; | 1905 | hdrlen = 24; |
1918 | break; | 1906 | break; |
1919 | default: | 1907 | default: |
1920 | ret = NETDEV_TX_OK; | ||
1921 | goto fail; | 1908 | goto fail; |
1922 | } | 1909 | } |
1923 | 1910 | ||
@@ -1962,7 +1949,6 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1962 | 1949 | ||
1963 | I802_DEBUG_INC(local->tx_handlers_drop_unauth_port); | 1950 | I802_DEBUG_INC(local->tx_handlers_drop_unauth_port); |
1964 | 1951 | ||
1965 | ret = NETDEV_TX_OK; | ||
1966 | goto fail; | 1952 | goto fail; |
1967 | } | 1953 | } |
1968 | 1954 | ||
@@ -2017,10 +2003,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
2017 | skb = skb_clone(skb, GFP_ATOMIC); | 2003 | skb = skb_clone(skb, GFP_ATOMIC); |
2018 | kfree_skb(tmp_skb); | 2004 | kfree_skb(tmp_skb); |
2019 | 2005 | ||
2020 | if (!skb) { | 2006 | if (!skb) |
2021 | ret = NETDEV_TX_OK; | ||
2022 | goto fail; | 2007 | goto fail; |
2023 | } | ||
2024 | } | 2008 | } |
2025 | 2009 | ||
2026 | hdr.frame_control = fc; | 2010 | hdr.frame_control = fc; |
@@ -2123,10 +2107,8 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
2123 | return NETDEV_TX_OK; | 2107 | return NETDEV_TX_OK; |
2124 | 2108 | ||
2125 | fail: | 2109 | fail: |
2126 | if (ret == NETDEV_TX_OK) | 2110 | dev_kfree_skb(skb); |
2127 | dev_kfree_skb(skb); | 2111 | return NETDEV_TX_OK; |
2128 | |||
2129 | return ret; | ||
2130 | } | 2112 | } |
2131 | 2113 | ||
2132 | 2114 | ||
@@ -2301,12 +2283,9 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2301 | struct ieee80211_sub_if_data *sdata = NULL; | 2283 | struct ieee80211_sub_if_data *sdata = NULL; |
2302 | struct ieee80211_if_ap *ap = NULL; | 2284 | struct ieee80211_if_ap *ap = NULL; |
2303 | struct beacon_data *beacon; | 2285 | struct beacon_data *beacon; |
2304 | struct ieee80211_supported_band *sband; | 2286 | enum ieee80211_band band = local->oper_channel->band; |
2305 | enum ieee80211_band band = local->hw.conf.channel->band; | ||
2306 | struct ieee80211_tx_rate_control txrc; | 2287 | struct ieee80211_tx_rate_control txrc; |
2307 | 2288 | ||
2308 | sband = local->hw.wiphy->bands[band]; | ||
2309 | |||
2310 | rcu_read_lock(); | 2289 | rcu_read_lock(); |
2311 | 2290 | ||
2312 | sdata = vif_to_sdata(vif); | 2291 | sdata = vif_to_sdata(vif); |
@@ -2416,7 +2395,7 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2416 | memset(mgmt, 0, hdr_len); | 2395 | memset(mgmt, 0, hdr_len); |
2417 | mgmt->frame_control = | 2396 | mgmt->frame_control = |
2418 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); | 2397 | cpu_to_le16(IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON); |
2419 | memset(mgmt->da, 0xff, ETH_ALEN); | 2398 | eth_broadcast_addr(mgmt->da); |
2420 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); | 2399 | memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN); |
2421 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); | 2400 | memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN); |
2422 | mgmt->u.beacon.beacon_int = | 2401 | mgmt->u.beacon.beacon_int = |
@@ -2428,9 +2407,9 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2428 | *pos++ = WLAN_EID_SSID; | 2407 | *pos++ = WLAN_EID_SSID; |
2429 | *pos++ = 0x0; | 2408 | *pos++ = 0x0; |
2430 | 2409 | ||
2431 | if (ieee80211_add_srates_ie(sdata, skb, true) || | 2410 | if (ieee80211_add_srates_ie(sdata, skb, true, band) || |
2432 | mesh_add_ds_params_ie(skb, sdata) || | 2411 | mesh_add_ds_params_ie(skb, sdata) || |
2433 | ieee80211_add_ext_srates_ie(sdata, skb, true) || | 2412 | ieee80211_add_ext_srates_ie(sdata, skb, true, band) || |
2434 | mesh_add_rsn_ie(skb, sdata) || | 2413 | mesh_add_rsn_ie(skb, sdata) || |
2435 | mesh_add_ht_cap_ie(skb, sdata) || | 2414 | mesh_add_ht_cap_ie(skb, sdata) || |
2436 | mesh_add_ht_oper_ie(skb, sdata) || | 2415 | mesh_add_ht_oper_ie(skb, sdata) || |
@@ -2453,12 +2432,12 @@ struct sk_buff *ieee80211_beacon_get_tim(struct ieee80211_hw *hw, | |||
2453 | 2432 | ||
2454 | memset(&txrc, 0, sizeof(txrc)); | 2433 | memset(&txrc, 0, sizeof(txrc)); |
2455 | txrc.hw = hw; | 2434 | txrc.hw = hw; |
2456 | txrc.sband = sband; | 2435 | txrc.sband = local->hw.wiphy->bands[band]; |
2457 | txrc.bss_conf = &sdata->vif.bss_conf; | 2436 | txrc.bss_conf = &sdata->vif.bss_conf; |
2458 | txrc.skb = skb; | 2437 | txrc.skb = skb; |
2459 | txrc.reported_rate.idx = -1; | 2438 | txrc.reported_rate.idx = -1; |
2460 | txrc.rate_idx_mask = sdata->rc_rateidx_mask[band]; | 2439 | txrc.rate_idx_mask = sdata->rc_rateidx_mask[band]; |
2461 | if (txrc.rate_idx_mask == (1 << sband->n_bitrates) - 1) | 2440 | if (txrc.rate_idx_mask == (1 << txrc.sband->n_bitrates) - 1) |
2462 | txrc.max_rate_idx = -1; | 2441 | txrc.max_rate_idx = -1; |
2463 | else | 2442 | else |
2464 | txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; | 2443 | txrc.max_rate_idx = fls(txrc.rate_idx_mask) - 1; |
@@ -2482,7 +2461,8 @@ struct sk_buff *ieee80211_proberesp_get(struct ieee80211_hw *hw, | |||
2482 | struct ieee80211_vif *vif) | 2461 | struct ieee80211_vif *vif) |
2483 | { | 2462 | { |
2484 | struct ieee80211_if_ap *ap = NULL; | 2463 | struct ieee80211_if_ap *ap = NULL; |
2485 | struct sk_buff *presp = NULL, *skb = NULL; | 2464 | struct sk_buff *skb = NULL; |
2465 | struct probe_resp *presp = NULL; | ||
2486 | struct ieee80211_hdr *hdr; | 2466 | struct ieee80211_hdr *hdr; |
2487 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 2467 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
2488 | 2468 | ||
@@ -2496,10 +2476,12 @@ struct sk_buff *ieee80211_proberesp_get(struct ieee80211_hw *hw, | |||
2496 | if (!presp) | 2476 | if (!presp) |
2497 | goto out; | 2477 | goto out; |
2498 | 2478 | ||
2499 | skb = skb_copy(presp, GFP_ATOMIC); | 2479 | skb = dev_alloc_skb(presp->len); |
2500 | if (!skb) | 2480 | if (!skb) |
2501 | goto out; | 2481 | goto out; |
2502 | 2482 | ||
2483 | memcpy(skb_put(skb, presp->len), presp->data, presp->len); | ||
2484 | |||
2503 | hdr = (struct ieee80211_hdr *) skb->data; | 2485 | hdr = (struct ieee80211_hdr *) skb->data; |
2504 | memset(hdr->addr1, 0, sizeof(hdr->addr1)); | 2486 | memset(hdr->addr1, 0, sizeof(hdr->addr1)); |
2505 | 2487 | ||
@@ -2610,9 +2592,9 @@ struct sk_buff *ieee80211_probereq_get(struct ieee80211_hw *hw, | |||
2610 | memset(hdr, 0, sizeof(*hdr)); | 2592 | memset(hdr, 0, sizeof(*hdr)); |
2611 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 2593 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
2612 | IEEE80211_STYPE_PROBE_REQ); | 2594 | IEEE80211_STYPE_PROBE_REQ); |
2613 | memset(hdr->addr1, 0xff, ETH_ALEN); | 2595 | eth_broadcast_addr(hdr->addr1); |
2614 | memcpy(hdr->addr2, vif->addr, ETH_ALEN); | 2596 | memcpy(hdr->addr2, vif->addr, ETH_ALEN); |
2615 | memset(hdr->addr3, 0xff, ETH_ALEN); | 2597 | eth_broadcast_addr(hdr->addr3); |
2616 | 2598 | ||
2617 | pos = skb_put(skb, ie_ssid_len); | 2599 | pos = skb_put(skb, ie_ssid_len); |
2618 | *pos++ = WLAN_EID_SSID; | 2600 | *pos++ = WLAN_EID_SSID; |
@@ -2709,8 +2691,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
2709 | info = IEEE80211_SKB_CB(skb); | 2691 | info = IEEE80211_SKB_CB(skb); |
2710 | 2692 | ||
2711 | tx.flags |= IEEE80211_TX_PS_BUFFERED; | 2693 | tx.flags |= IEEE80211_TX_PS_BUFFERED; |
2712 | tx.channel = local->hw.conf.channel; | 2694 | info->band = local->oper_channel->band; |
2713 | info->band = tx.channel->band; | ||
2714 | 2695 | ||
2715 | if (invoke_tx_handlers(&tx)) | 2696 | if (invoke_tx_handlers(&tx)) |
2716 | skb = NULL; | 2697 | skb = NULL; |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 39b82fee4904..471fb0516c99 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -276,6 +276,9 @@ void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue) | |||
276 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 276 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
277 | int ac; | 277 | int ac; |
278 | 278 | ||
279 | if (!sdata->dev) | ||
280 | continue; | ||
281 | |||
279 | if (test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) | 282 | if (test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) |
280 | continue; | 283 | continue; |
281 | 284 | ||
@@ -364,6 +367,9 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue, | |||
364 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 367 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
365 | int ac; | 368 | int ac; |
366 | 369 | ||
370 | if (!sdata->dev) | ||
371 | continue; | ||
372 | |||
367 | for (ac = 0; ac < n_acs; ac++) { | 373 | for (ac = 0; ac < n_acs; ac++) { |
368 | if (sdata->vif.hw_queue[ac] == queue || | 374 | if (sdata->vif.hw_queue[ac] == queue || |
369 | sdata->vif.cab_queue == queue) | 375 | sdata->vif.cab_queue == queue) |
@@ -768,8 +774,11 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len, | |||
768 | elem_parse_failed = true; | 774 | elem_parse_failed = true; |
769 | break; | 775 | break; |
770 | case WLAN_EID_CHANNEL_SWITCH: | 776 | case WLAN_EID_CHANNEL_SWITCH: |
771 | elems->ch_switch_elem = pos; | 777 | if (elen != sizeof(struct ieee80211_channel_sw_ie)) { |
772 | elems->ch_switch_elem_len = elen; | 778 | elem_parse_failed = true; |
779 | break; | ||
780 | } | ||
781 | elems->ch_switch_ie = (void *)pos; | ||
773 | break; | 782 | break; |
774 | case WLAN_EID_QUIET: | 783 | case WLAN_EID_QUIET: |
775 | if (!elems->quiet_elem) { | 784 | if (!elems->quiet_elem) { |
@@ -832,7 +841,7 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | |||
832 | 841 | ||
833 | memset(&qparam, 0, sizeof(qparam)); | 842 | memset(&qparam, 0, sizeof(qparam)); |
834 | 843 | ||
835 | use_11b = (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) && | 844 | use_11b = (local->oper_channel->band == IEEE80211_BAND_2GHZ) && |
836 | !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE); | 845 | !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE); |
837 | 846 | ||
838 | /* | 847 | /* |
@@ -899,7 +908,8 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata, | |||
899 | drv_conf_tx(local, sdata, ac, &qparam); | 908 | drv_conf_tx(local, sdata, ac, &qparam); |
900 | } | 909 | } |
901 | 910 | ||
902 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { | 911 | if (sdata->vif.type != NL80211_IFTYPE_MONITOR && |
912 | sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE) { | ||
903 | sdata->vif.bss_conf.qos = enable_qos; | 913 | sdata->vif.bss_conf.qos = enable_qos; |
904 | if (bss_notify) | 914 | if (bss_notify) |
905 | ieee80211_bss_info_change_notify(sdata, | 915 | ieee80211_bss_info_change_notify(sdata, |
@@ -919,7 +929,7 @@ void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, | |||
919 | if ((supp_rates[i] & 0x7f) * 5 > 110) | 929 | if ((supp_rates[i] & 0x7f) * 5 > 110) |
920 | have_higher_than_11mbit = 1; | 930 | have_higher_than_11mbit = 1; |
921 | 931 | ||
922 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && | 932 | if (local->oper_channel->band == IEEE80211_BAND_2GHZ && |
923 | have_higher_than_11mbit) | 933 | have_higher_than_11mbit) |
924 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; | 934 | sdata->flags |= IEEE80211_SDATA_OPERATING_GMODE; |
925 | else | 935 | else |
@@ -1100,6 +1110,7 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1100 | 1110 | ||
1101 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | 1111 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, |
1102 | u8 *dst, u32 ratemask, | 1112 | u8 *dst, u32 ratemask, |
1113 | struct ieee80211_channel *chan, | ||
1103 | const u8 *ssid, size_t ssid_len, | 1114 | const u8 *ssid, size_t ssid_len, |
1104 | const u8 *ie, size_t ie_len, | 1115 | const u8 *ie, size_t ie_len, |
1105 | bool directed) | 1116 | bool directed) |
@@ -1109,7 +1120,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1109 | struct ieee80211_mgmt *mgmt; | 1120 | struct ieee80211_mgmt *mgmt; |
1110 | size_t buf_len; | 1121 | size_t buf_len; |
1111 | u8 *buf; | 1122 | u8 *buf; |
1112 | u8 chan; | 1123 | u8 chan_no; |
1113 | 1124 | ||
1114 | /* FIXME: come up with a proper value */ | 1125 | /* FIXME: come up with a proper value */ |
1115 | buf = kmalloc(200 + ie_len, GFP_KERNEL); | 1126 | buf = kmalloc(200 + ie_len, GFP_KERNEL); |
@@ -1122,14 +1133,12 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1122 | * badly-behaved APs don't respond when this parameter is included. | 1133 | * badly-behaved APs don't respond when this parameter is included. |
1123 | */ | 1134 | */ |
1124 | if (directed) | 1135 | if (directed) |
1125 | chan = 0; | 1136 | chan_no = 0; |
1126 | else | 1137 | else |
1127 | chan = ieee80211_frequency_to_channel( | 1138 | chan_no = ieee80211_frequency_to_channel(chan->center_freq); |
1128 | local->hw.conf.channel->center_freq); | ||
1129 | 1139 | ||
1130 | buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len, | 1140 | buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len, chan->band, |
1131 | local->hw.conf.channel->band, | 1141 | ratemask, chan_no); |
1132 | ratemask, chan); | ||
1133 | 1142 | ||
1134 | skb = ieee80211_probereq_get(&local->hw, &sdata->vif, | 1143 | skb = ieee80211_probereq_get(&local->hw, &sdata->vif, |
1135 | ssid, ssid_len, | 1144 | ssid, ssid_len, |
@@ -1154,11 +1163,13 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1154 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, | 1163 | void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, |
1155 | const u8 *ssid, size_t ssid_len, | 1164 | const u8 *ssid, size_t ssid_len, |
1156 | const u8 *ie, size_t ie_len, | 1165 | const u8 *ie, size_t ie_len, |
1157 | u32 ratemask, bool directed, bool no_cck) | 1166 | u32 ratemask, bool directed, bool no_cck, |
1167 | struct ieee80211_channel *channel) | ||
1158 | { | 1168 | { |
1159 | struct sk_buff *skb; | 1169 | struct sk_buff *skb; |
1160 | 1170 | ||
1161 | skb = ieee80211_build_probe_req(sdata, dst, ratemask, ssid, ssid_len, | 1171 | skb = ieee80211_build_probe_req(sdata, dst, ratemask, channel, |
1172 | ssid, ssid_len, | ||
1162 | ie, ie_len, directed); | 1173 | ie, ie_len, directed); |
1163 | if (skb) { | 1174 | if (skb) { |
1164 | if (no_cck) | 1175 | if (no_cck) |
@@ -1359,7 +1370,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1359 | switch (sdata->vif.type) { | 1370 | switch (sdata->vif.type) { |
1360 | case NL80211_IFTYPE_STATION: | 1371 | case NL80211_IFTYPE_STATION: |
1361 | changed |= BSS_CHANGED_ASSOC | | 1372 | changed |= BSS_CHANGED_ASSOC | |
1362 | BSS_CHANGED_ARP_FILTER; | 1373 | BSS_CHANGED_ARP_FILTER | |
1374 | BSS_CHANGED_PS; | ||
1363 | mutex_lock(&sdata->u.mgd.mtx); | 1375 | mutex_lock(&sdata->u.mgd.mtx); |
1364 | ieee80211_bss_info_change_notify(sdata, changed); | 1376 | ieee80211_bss_info_change_notify(sdata, changed); |
1365 | mutex_unlock(&sdata->u.mgd.mtx); | 1377 | mutex_unlock(&sdata->u.mgd.mtx); |
@@ -1385,6 +1397,9 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1385 | case NL80211_IFTYPE_MONITOR: | 1397 | case NL80211_IFTYPE_MONITOR: |
1386 | /* ignore virtual */ | 1398 | /* ignore virtual */ |
1387 | break; | 1399 | break; |
1400 | case NL80211_IFTYPE_P2P_DEVICE: | ||
1401 | changed = BSS_CHANGED_IDLE; | ||
1402 | break; | ||
1388 | case NL80211_IFTYPE_UNSPECIFIED: | 1403 | case NL80211_IFTYPE_UNSPECIFIED: |
1389 | case NUM_NL80211_IFTYPES: | 1404 | case NUM_NL80211_IFTYPES: |
1390 | case NL80211_IFTYPE_P2P_CLIENT: | 1405 | case NL80211_IFTYPE_P2P_CLIENT: |
@@ -1571,6 +1586,8 @@ void ieee80211_recalc_smps(struct ieee80211_local *local) | |||
1571 | list_for_each_entry(sdata, &local->interfaces, list) { | 1586 | list_for_each_entry(sdata, &local->interfaces, list) { |
1572 | if (!ieee80211_sdata_running(sdata)) | 1587 | if (!ieee80211_sdata_running(sdata)) |
1573 | continue; | 1588 | continue; |
1589 | if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) | ||
1590 | continue; | ||
1574 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 1591 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
1575 | goto set; | 1592 | goto set; |
1576 | 1593 | ||
@@ -1809,7 +1826,8 @@ ieee80211_ht_oper_to_channel_type(struct ieee80211_ht_operation *ht_oper) | |||
1809 | } | 1826 | } |
1810 | 1827 | ||
1811 | int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, | 1828 | int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, |
1812 | struct sk_buff *skb, bool need_basic) | 1829 | struct sk_buff *skb, bool need_basic, |
1830 | enum ieee80211_band band) | ||
1813 | { | 1831 | { |
1814 | struct ieee80211_local *local = sdata->local; | 1832 | struct ieee80211_local *local = sdata->local; |
1815 | struct ieee80211_supported_band *sband; | 1833 | struct ieee80211_supported_band *sband; |
@@ -1817,7 +1835,7 @@ int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, | |||
1817 | u8 i, rates, *pos; | 1835 | u8 i, rates, *pos; |
1818 | u32 basic_rates = sdata->vif.bss_conf.basic_rates; | 1836 | u32 basic_rates = sdata->vif.bss_conf.basic_rates; |
1819 | 1837 | ||
1820 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 1838 | sband = local->hw.wiphy->bands[band]; |
1821 | rates = sband->n_bitrates; | 1839 | rates = sband->n_bitrates; |
1822 | if (rates > 8) | 1840 | if (rates > 8) |
1823 | rates = 8; | 1841 | rates = 8; |
@@ -1840,7 +1858,8 @@ int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, | |||
1840 | } | 1858 | } |
1841 | 1859 | ||
1842 | int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, | 1860 | int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, |
1843 | struct sk_buff *skb, bool need_basic) | 1861 | struct sk_buff *skb, bool need_basic, |
1862 | enum ieee80211_band band) | ||
1844 | { | 1863 | { |
1845 | struct ieee80211_local *local = sdata->local; | 1864 | struct ieee80211_local *local = sdata->local; |
1846 | struct ieee80211_supported_band *sband; | 1865 | struct ieee80211_supported_band *sband; |
@@ -1848,7 +1867,7 @@ int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, | |||
1848 | u8 i, exrates, *pos; | 1867 | u8 i, exrates, *pos; |
1849 | u32 basic_rates = sdata->vif.bss_conf.basic_rates; | 1868 | u32 basic_rates = sdata->vif.bss_conf.basic_rates; |
1850 | 1869 | ||
1851 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 1870 | sband = local->hw.wiphy->bands[band]; |
1852 | exrates = sband->n_bitrates; | 1871 | exrates = sband->n_bitrates; |
1853 | if (exrates > 8) | 1872 | if (exrates > 8) |
1854 | exrates -= 8; | 1873 | exrates -= 8; |
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index c19b214ffd57..3f4b3b4a7762 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
@@ -356,6 +356,55 @@ config NETFILTER_NETLINK_QUEUE_CT | |||
356 | If this option is enabled, NFQUEUE can include Connection Tracking | 356 | If this option is enabled, NFQUEUE can include Connection Tracking |
357 | information together with the packet is the enqueued via NFNETLINK. | 357 | information together with the packet is the enqueued via NFNETLINK. |
358 | 358 | ||
359 | config NF_NAT | ||
360 | tristate | ||
361 | |||
362 | config NF_NAT_NEEDED | ||
363 | bool | ||
364 | depends on NF_NAT | ||
365 | default y | ||
366 | |||
367 | config NF_NAT_PROTO_DCCP | ||
368 | tristate | ||
369 | depends on NF_NAT && NF_CT_PROTO_DCCP | ||
370 | default NF_NAT && NF_CT_PROTO_DCCP | ||
371 | |||
372 | config NF_NAT_PROTO_UDPLITE | ||
373 | tristate | ||
374 | depends on NF_NAT && NF_CT_PROTO_UDPLITE | ||
375 | default NF_NAT && NF_CT_PROTO_UDPLITE | ||
376 | |||
377 | config NF_NAT_PROTO_SCTP | ||
378 | tristate | ||
379 | default NF_NAT && NF_CT_PROTO_SCTP | ||
380 | depends on NF_NAT && NF_CT_PROTO_SCTP | ||
381 | select LIBCRC32C | ||
382 | |||
383 | config NF_NAT_AMANDA | ||
384 | tristate | ||
385 | depends on NF_CONNTRACK && NF_NAT | ||
386 | default NF_NAT && NF_CONNTRACK_AMANDA | ||
387 | |||
388 | config NF_NAT_FTP | ||
389 | tristate | ||
390 | depends on NF_CONNTRACK && NF_NAT | ||
391 | default NF_NAT && NF_CONNTRACK_FTP | ||
392 | |||
393 | config NF_NAT_IRC | ||
394 | tristate | ||
395 | depends on NF_CONNTRACK && NF_NAT | ||
396 | default NF_NAT && NF_CONNTRACK_IRC | ||
397 | |||
398 | config NF_NAT_SIP | ||
399 | tristate | ||
400 | depends on NF_CONNTRACK && NF_NAT | ||
401 | default NF_NAT && NF_CONNTRACK_SIP | ||
402 | |||
403 | config NF_NAT_TFTP | ||
404 | tristate | ||
405 | depends on NF_CONNTRACK && NF_NAT | ||
406 | default NF_NAT && NF_CONNTRACK_TFTP | ||
407 | |||
359 | endif # NF_CONNTRACK | 408 | endif # NF_CONNTRACK |
360 | 409 | ||
361 | # transparent proxy support | 410 | # transparent proxy support |
@@ -621,19 +670,6 @@ config NETFILTER_XT_TARGET_NFQUEUE | |||
621 | 670 | ||
622 | To compile it as a module, choose M here. If unsure, say N. | 671 | To compile it as a module, choose M here. If unsure, say N. |
623 | 672 | ||
624 | config NETFILTER_XT_TARGET_NOTRACK | ||
625 | tristate '"NOTRACK" target support' | ||
626 | depends on IP_NF_RAW || IP6_NF_RAW | ||
627 | depends on NF_CONNTRACK | ||
628 | help | ||
629 | The NOTRACK target allows a select rule to specify | ||
630 | which packets *not* to enter the conntrack/NAT | ||
631 | subsystem with all the consequences (no ICMP error tracking, | ||
632 | no protocol helpers for the selected packets). | ||
633 | |||
634 | If you want to compile it as a module, say M here and read | ||
635 | <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. | ||
636 | |||
637 | config NETFILTER_XT_TARGET_RATEEST | 673 | config NETFILTER_XT_TARGET_RATEEST |
638 | tristate '"RATEEST" target support' | 674 | tristate '"RATEEST" target support' |
639 | depends on NETFILTER_ADVANCED | 675 | depends on NETFILTER_ADVANCED |
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 1c5160f2278e..98244d4c75f2 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile | |||
@@ -43,6 +43,24 @@ obj-$(CONFIG_NF_CONNTRACK_SANE) += nf_conntrack_sane.o | |||
43 | obj-$(CONFIG_NF_CONNTRACK_SIP) += nf_conntrack_sip.o | 43 | obj-$(CONFIG_NF_CONNTRACK_SIP) += nf_conntrack_sip.o |
44 | obj-$(CONFIG_NF_CONNTRACK_TFTP) += nf_conntrack_tftp.o | 44 | obj-$(CONFIG_NF_CONNTRACK_TFTP) += nf_conntrack_tftp.o |
45 | 45 | ||
46 | nf_nat-y := nf_nat_core.o nf_nat_proto_unknown.o nf_nat_proto_common.o \ | ||
47 | nf_nat_proto_udp.o nf_nat_proto_tcp.o nf_nat_helper.o | ||
48 | |||
49 | obj-$(CONFIG_NF_NAT) += nf_nat.o | ||
50 | obj-$(CONFIG_NF_NAT) += xt_nat.o | ||
51 | |||
52 | # NAT protocols (nf_nat) | ||
53 | obj-$(CONFIG_NF_NAT_PROTO_DCCP) += nf_nat_proto_dccp.o | ||
54 | obj-$(CONFIG_NF_NAT_PROTO_UDPLITE) += nf_nat_proto_udplite.o | ||
55 | obj-$(CONFIG_NF_NAT_PROTO_SCTP) += nf_nat_proto_sctp.o | ||
56 | |||
57 | # NAT helpers | ||
58 | obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o | ||
59 | obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o | ||
60 | obj-$(CONFIG_NF_NAT_IRC) += nf_nat_irc.o | ||
61 | obj-$(CONFIG_NF_NAT_SIP) += nf_nat_sip.o | ||
62 | obj-$(CONFIG_NF_NAT_TFTP) += nf_nat_tftp.o | ||
63 | |||
46 | # transparent proxy support | 64 | # transparent proxy support |
47 | obj-$(CONFIG_NETFILTER_TPROXY) += nf_tproxy_core.o | 65 | obj-$(CONFIG_NETFILTER_TPROXY) += nf_tproxy_core.o |
48 | 66 | ||
@@ -67,7 +85,6 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_LED) += xt_LED.o | |||
67 | obj-$(CONFIG_NETFILTER_XT_TARGET_LOG) += xt_LOG.o | 85 | obj-$(CONFIG_NETFILTER_XT_TARGET_LOG) += xt_LOG.o |
68 | obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o | 86 | obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o |
69 | obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o | 87 | obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o |
70 | obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o | ||
71 | obj-$(CONFIG_NETFILTER_XT_TARGET_RATEEST) += xt_RATEEST.o | 88 | obj-$(CONFIG_NETFILTER_XT_TARGET_RATEEST) += xt_RATEEST.o |
72 | obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o | 89 | obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o |
73 | obj-$(CONFIG_NETFILTER_XT_TARGET_TPROXY) += xt_TPROXY.o | 90 | obj-$(CONFIG_NETFILTER_XT_TARGET_TPROXY) += xt_TPROXY.o |
diff --git a/net/netfilter/core.c b/net/netfilter/core.c index 0bc6b60db4df..68912dadf13d 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c | |||
@@ -126,7 +126,7 @@ unsigned int nf_iterate(struct list_head *head, | |||
126 | unsigned int hook, | 126 | unsigned int hook, |
127 | const struct net_device *indev, | 127 | const struct net_device *indev, |
128 | const struct net_device *outdev, | 128 | const struct net_device *outdev, |
129 | struct list_head **i, | 129 | struct nf_hook_ops **elemp, |
130 | int (*okfn)(struct sk_buff *), | 130 | int (*okfn)(struct sk_buff *), |
131 | int hook_thresh) | 131 | int hook_thresh) |
132 | { | 132 | { |
@@ -136,22 +136,20 @@ unsigned int nf_iterate(struct list_head *head, | |||
136 | * The caller must not block between calls to this | 136 | * The caller must not block between calls to this |
137 | * function because of risk of continuing from deleted element. | 137 | * function because of risk of continuing from deleted element. |
138 | */ | 138 | */ |
139 | list_for_each_continue_rcu(*i, head) { | 139 | list_for_each_entry_continue_rcu((*elemp), head, list) { |
140 | struct nf_hook_ops *elem = (struct nf_hook_ops *)*i; | 140 | if (hook_thresh > (*elemp)->priority) |
141 | |||
142 | if (hook_thresh > elem->priority) | ||
143 | continue; | 141 | continue; |
144 | 142 | ||
145 | /* Optimization: we don't need to hold module | 143 | /* Optimization: we don't need to hold module |
146 | reference here, since function can't sleep. --RR */ | 144 | reference here, since function can't sleep. --RR */ |
147 | repeat: | 145 | repeat: |
148 | verdict = elem->hook(hook, skb, indev, outdev, okfn); | 146 | verdict = (*elemp)->hook(hook, skb, indev, outdev, okfn); |
149 | if (verdict != NF_ACCEPT) { | 147 | if (verdict != NF_ACCEPT) { |
150 | #ifdef CONFIG_NETFILTER_DEBUG | 148 | #ifdef CONFIG_NETFILTER_DEBUG |
151 | if (unlikely((verdict & NF_VERDICT_MASK) | 149 | if (unlikely((verdict & NF_VERDICT_MASK) |
152 | > NF_MAX_VERDICT)) { | 150 | > NF_MAX_VERDICT)) { |
153 | NFDEBUG("Evil return from %p(%u).\n", | 151 | NFDEBUG("Evil return from %p(%u).\n", |
154 | elem->hook, hook); | 152 | (*elemp)->hook, hook); |
155 | continue; | 153 | continue; |
156 | } | 154 | } |
157 | #endif | 155 | #endif |
@@ -172,14 +170,14 @@ int nf_hook_slow(u_int8_t pf, unsigned int hook, struct sk_buff *skb, | |||
172 | int (*okfn)(struct sk_buff *), | 170 | int (*okfn)(struct sk_buff *), |
173 | int hook_thresh) | 171 | int hook_thresh) |
174 | { | 172 | { |
175 | struct list_head *elem; | 173 | struct nf_hook_ops *elem; |
176 | unsigned int verdict; | 174 | unsigned int verdict; |
177 | int ret = 0; | 175 | int ret = 0; |
178 | 176 | ||
179 | /* We may already have this, but read-locks nest anyway */ | 177 | /* We may already have this, but read-locks nest anyway */ |
180 | rcu_read_lock(); | 178 | rcu_read_lock(); |
181 | 179 | ||
182 | elem = &nf_hooks[pf][hook]; | 180 | elem = list_entry_rcu(&nf_hooks[pf][hook], struct nf_hook_ops, list); |
183 | next_hook: | 181 | next_hook: |
184 | verdict = nf_iterate(&nf_hooks[pf][hook], skb, hook, indev, | 182 | verdict = nf_iterate(&nf_hooks[pf][hook], skb, hook, indev, |
185 | outdev, &elem, okfn, hook_thresh); | 183 | outdev, &elem, okfn, hook_thresh); |
@@ -273,6 +271,11 @@ EXPORT_SYMBOL_GPL(nfq_ct_nat_hook); | |||
273 | 271 | ||
274 | #endif /* CONFIG_NF_CONNTRACK */ | 272 | #endif /* CONFIG_NF_CONNTRACK */ |
275 | 273 | ||
274 | #ifdef CONFIG_NF_NAT_NEEDED | ||
275 | void (*nf_nat_decode_session_hook)(struct sk_buff *, struct flowi *); | ||
276 | EXPORT_SYMBOL(nf_nat_decode_session_hook); | ||
277 | #endif | ||
278 | |||
276 | #ifdef CONFIG_PROC_FS | 279 | #ifdef CONFIG_PROC_FS |
277 | struct proc_dir_entry *proc_net_netfilter; | 280 | struct proc_dir_entry *proc_net_netfilter; |
278 | EXPORT_SYMBOL(proc_net_netfilter); | 281 | EXPORT_SYMBOL(proc_net_netfilter); |
diff --git a/net/netfilter/ipvs/Kconfig b/net/netfilter/ipvs/Kconfig index f9871385a65e..8b2cffdfdd99 100644 --- a/net/netfilter/ipvs/Kconfig +++ b/net/netfilter/ipvs/Kconfig | |||
@@ -250,7 +250,8 @@ comment 'IPVS application helper' | |||
250 | 250 | ||
251 | config IP_VS_FTP | 251 | config IP_VS_FTP |
252 | tristate "FTP protocol helper" | 252 | tristate "FTP protocol helper" |
253 | depends on IP_VS_PROTO_TCP && NF_CONNTRACK && NF_NAT | 253 | depends on IP_VS_PROTO_TCP && NF_CONNTRACK && NF_NAT && \ |
254 | NF_CONNTRACK_FTP | ||
254 | select IP_VS_NFCT | 255 | select IP_VS_NFCT |
255 | ---help--- | 256 | ---help--- |
256 | FTP is a protocol that transfers IP address and/or port number in | 257 | FTP is a protocol that transfers IP address and/or port number in |
diff --git a/net/netfilter/ipvs/ip_vs_app.c b/net/netfilter/ipvs/ip_vs_app.c index 64f9e8f13207..9713e6e86d47 100644 --- a/net/netfilter/ipvs/ip_vs_app.c +++ b/net/netfilter/ipvs/ip_vs_app.c | |||
@@ -180,22 +180,38 @@ register_ip_vs_app_inc(struct net *net, struct ip_vs_app *app, __u16 proto, | |||
180 | } | 180 | } |
181 | 181 | ||
182 | 182 | ||
183 | /* | 183 | /* Register application for netns */ |
184 | * ip_vs_app registration routine | 184 | struct ip_vs_app *register_ip_vs_app(struct net *net, struct ip_vs_app *app) |
185 | */ | ||
186 | int register_ip_vs_app(struct net *net, struct ip_vs_app *app) | ||
187 | { | 185 | { |
188 | struct netns_ipvs *ipvs = net_ipvs(net); | 186 | struct netns_ipvs *ipvs = net_ipvs(net); |
189 | /* increase the module use count */ | 187 | struct ip_vs_app *a; |
190 | ip_vs_use_count_inc(); | 188 | int err = 0; |
189 | |||
190 | if (!ipvs) | ||
191 | return ERR_PTR(-ENOENT); | ||
191 | 192 | ||
192 | mutex_lock(&__ip_vs_app_mutex); | 193 | mutex_lock(&__ip_vs_app_mutex); |
193 | 194 | ||
194 | list_add(&app->a_list, &ipvs->app_list); | 195 | list_for_each_entry(a, &ipvs->app_list, a_list) { |
196 | if (!strcmp(app->name, a->name)) { | ||
197 | err = -EEXIST; | ||
198 | goto out_unlock; | ||
199 | } | ||
200 | } | ||
201 | a = kmemdup(app, sizeof(*app), GFP_KERNEL); | ||
202 | if (!a) { | ||
203 | err = -ENOMEM; | ||
204 | goto out_unlock; | ||
205 | } | ||
206 | INIT_LIST_HEAD(&a->incs_list); | ||
207 | list_add(&a->a_list, &ipvs->app_list); | ||
208 | /* increase the module use count */ | ||
209 | ip_vs_use_count_inc(); | ||
195 | 210 | ||
211 | out_unlock: | ||
196 | mutex_unlock(&__ip_vs_app_mutex); | 212 | mutex_unlock(&__ip_vs_app_mutex); |
197 | 213 | ||
198 | return 0; | 214 | return err ? ERR_PTR(err) : a; |
199 | } | 215 | } |
200 | 216 | ||
201 | 217 | ||
@@ -205,20 +221,29 @@ int register_ip_vs_app(struct net *net, struct ip_vs_app *app) | |||
205 | */ | 221 | */ |
206 | void unregister_ip_vs_app(struct net *net, struct ip_vs_app *app) | 222 | void unregister_ip_vs_app(struct net *net, struct ip_vs_app *app) |
207 | { | 223 | { |
208 | struct ip_vs_app *inc, *nxt; | 224 | struct netns_ipvs *ipvs = net_ipvs(net); |
225 | struct ip_vs_app *a, *anxt, *inc, *nxt; | ||
226 | |||
227 | if (!ipvs) | ||
228 | return; | ||
209 | 229 | ||
210 | mutex_lock(&__ip_vs_app_mutex); | 230 | mutex_lock(&__ip_vs_app_mutex); |
211 | 231 | ||
212 | list_for_each_entry_safe(inc, nxt, &app->incs_list, a_list) { | 232 | list_for_each_entry_safe(a, anxt, &ipvs->app_list, a_list) { |
213 | ip_vs_app_inc_release(net, inc); | 233 | if (app && strcmp(app->name, a->name)) |
214 | } | 234 | continue; |
235 | list_for_each_entry_safe(inc, nxt, &a->incs_list, a_list) { | ||
236 | ip_vs_app_inc_release(net, inc); | ||
237 | } | ||
215 | 238 | ||
216 | list_del(&app->a_list); | 239 | list_del(&a->a_list); |
240 | kfree(a); | ||
217 | 241 | ||
218 | mutex_unlock(&__ip_vs_app_mutex); | 242 | /* decrease the module use count */ |
243 | ip_vs_use_count_dec(); | ||
244 | } | ||
219 | 245 | ||
220 | /* decrease the module use count */ | 246 | mutex_unlock(&__ip_vs_app_mutex); |
221 | ip_vs_use_count_dec(); | ||
222 | } | 247 | } |
223 | 248 | ||
224 | 249 | ||
@@ -586,5 +611,6 @@ int __net_init ip_vs_app_net_init(struct net *net) | |||
586 | 611 | ||
587 | void __net_exit ip_vs_app_net_cleanup(struct net *net) | 612 | void __net_exit ip_vs_app_net_cleanup(struct net *net) |
588 | { | 613 | { |
614 | unregister_ip_vs_app(net, NULL /* all */); | ||
589 | proc_net_remove(net, "ip_vs_app"); | 615 | proc_net_remove(net, "ip_vs_app"); |
590 | } | 616 | } |
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index b54eccef40b5..58918e20f9d5 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c | |||
@@ -1303,7 +1303,8 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) | |||
1303 | struct ip_vs_conn *cp; | 1303 | struct ip_vs_conn *cp; |
1304 | struct ip_vs_protocol *pp; | 1304 | struct ip_vs_protocol *pp; |
1305 | struct ip_vs_proto_data *pd; | 1305 | struct ip_vs_proto_data *pd; |
1306 | unsigned int offset, ihl, verdict; | 1306 | unsigned int offset, offset2, ihl, verdict; |
1307 | bool ipip; | ||
1307 | 1308 | ||
1308 | *related = 1; | 1309 | *related = 1; |
1309 | 1310 | ||
@@ -1345,6 +1346,21 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) | |||
1345 | 1346 | ||
1346 | net = skb_net(skb); | 1347 | net = skb_net(skb); |
1347 | 1348 | ||
1349 | /* Special case for errors for IPIP packets */ | ||
1350 | ipip = false; | ||
1351 | if (cih->protocol == IPPROTO_IPIP) { | ||
1352 | if (unlikely(cih->frag_off & htons(IP_OFFSET))) | ||
1353 | return NF_ACCEPT; | ||
1354 | /* Error for our IPIP must arrive at LOCAL_IN */ | ||
1355 | if (!(skb_rtable(skb)->rt_flags & RTCF_LOCAL)) | ||
1356 | return NF_ACCEPT; | ||
1357 | offset += cih->ihl * 4; | ||
1358 | cih = skb_header_pointer(skb, offset, sizeof(_ciph), &_ciph); | ||
1359 | if (cih == NULL) | ||
1360 | return NF_ACCEPT; /* The packet looks wrong, ignore */ | ||
1361 | ipip = true; | ||
1362 | } | ||
1363 | |||
1348 | pd = ip_vs_proto_data_get(net, cih->protocol); | 1364 | pd = ip_vs_proto_data_get(net, cih->protocol); |
1349 | if (!pd) | 1365 | if (!pd) |
1350 | return NF_ACCEPT; | 1366 | return NF_ACCEPT; |
@@ -1358,11 +1374,14 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) | |||
1358 | IP_VS_DBG_PKT(11, AF_INET, pp, skb, offset, | 1374 | IP_VS_DBG_PKT(11, AF_INET, pp, skb, offset, |
1359 | "Checking incoming ICMP for"); | 1375 | "Checking incoming ICMP for"); |
1360 | 1376 | ||
1377 | offset2 = offset; | ||
1361 | offset += cih->ihl * 4; | 1378 | offset += cih->ihl * 4; |
1362 | 1379 | ||
1363 | ip_vs_fill_iphdr(AF_INET, cih, &ciph); | 1380 | ip_vs_fill_iphdr(AF_INET, cih, &ciph); |
1364 | /* The embedded headers contain source and dest in reverse order */ | 1381 | /* The embedded headers contain source and dest in reverse order. |
1365 | cp = pp->conn_in_get(AF_INET, skb, &ciph, offset, 1); | 1382 | * For IPIP this is error for request, not for reply. |
1383 | */ | ||
1384 | cp = pp->conn_in_get(AF_INET, skb, &ciph, offset, ipip ? 0 : 1); | ||
1366 | if (!cp) | 1385 | if (!cp) |
1367 | return NF_ACCEPT; | 1386 | return NF_ACCEPT; |
1368 | 1387 | ||
@@ -1376,6 +1395,57 @@ ip_vs_in_icmp(struct sk_buff *skb, int *related, unsigned int hooknum) | |||
1376 | goto out; | 1395 | goto out; |
1377 | } | 1396 | } |
1378 | 1397 | ||
1398 | if (ipip) { | ||
1399 | __be32 info = ic->un.gateway; | ||
1400 | |||
1401 | /* Update the MTU */ | ||
1402 | if (ic->type == ICMP_DEST_UNREACH && | ||
1403 | ic->code == ICMP_FRAG_NEEDED) { | ||
1404 | struct ip_vs_dest *dest = cp->dest; | ||
1405 | u32 mtu = ntohs(ic->un.frag.mtu); | ||
1406 | |||
1407 | /* Strip outer IP and ICMP, go to IPIP header */ | ||
1408 | __skb_pull(skb, ihl + sizeof(_icmph)); | ||
1409 | offset2 -= ihl + sizeof(_icmph); | ||
1410 | skb_reset_network_header(skb); | ||
1411 | IP_VS_DBG(12, "ICMP for IPIP %pI4->%pI4: mtu=%u\n", | ||
1412 | &ip_hdr(skb)->saddr, &ip_hdr(skb)->daddr, mtu); | ||
1413 | rcu_read_lock(); | ||
1414 | ipv4_update_pmtu(skb, dev_net(skb->dev), | ||
1415 | mtu, 0, 0, 0, 0); | ||
1416 | rcu_read_unlock(); | ||
1417 | /* Client uses PMTUD? */ | ||
1418 | if (!(cih->frag_off & htons(IP_DF))) | ||
1419 | goto ignore_ipip; | ||
1420 | /* Prefer the resulting PMTU */ | ||
1421 | if (dest) { | ||
1422 | spin_lock(&dest->dst_lock); | ||
1423 | if (dest->dst_cache) | ||
1424 | mtu = dst_mtu(dest->dst_cache); | ||
1425 | spin_unlock(&dest->dst_lock); | ||
1426 | } | ||
1427 | if (mtu > 68 + sizeof(struct iphdr)) | ||
1428 | mtu -= sizeof(struct iphdr); | ||
1429 | info = htonl(mtu); | ||
1430 | } | ||
1431 | /* Strip outer IP, ICMP and IPIP, go to IP header of | ||
1432 | * original request. | ||
1433 | */ | ||
1434 | __skb_pull(skb, offset2); | ||
1435 | skb_reset_network_header(skb); | ||
1436 | IP_VS_DBG(12, "Sending ICMP for %pI4->%pI4: t=%u, c=%u, i=%u\n", | ||
1437 | &ip_hdr(skb)->saddr, &ip_hdr(skb)->daddr, | ||
1438 | ic->type, ic->code, ntohl(info)); | ||
1439 | icmp_send(skb, ic->type, ic->code, info); | ||
1440 | /* ICMP can be shorter but anyways, account it */ | ||
1441 | ip_vs_out_stats(cp, skb); | ||
1442 | |||
1443 | ignore_ipip: | ||
1444 | consume_skb(skb); | ||
1445 | verdict = NF_STOLEN; | ||
1446 | goto out; | ||
1447 | } | ||
1448 | |||
1379 | /* do the statistics and put it back */ | 1449 | /* do the statistics and put it back */ |
1380 | ip_vs_in_stats(cp, skb); | 1450 | ip_vs_in_stats(cp, skb); |
1381 | if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol) | 1451 | if (IPPROTO_TCP == cih->protocol || IPPROTO_UDP == cih->protocol) |
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 84444dda194b..767cc12da0fe 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c | |||
@@ -1171,8 +1171,10 @@ ip_vs_add_service(struct net *net, struct ip_vs_service_user_kern *u, | |||
1171 | goto out_err; | 1171 | goto out_err; |
1172 | } | 1172 | } |
1173 | svc->stats.cpustats = alloc_percpu(struct ip_vs_cpu_stats); | 1173 | svc->stats.cpustats = alloc_percpu(struct ip_vs_cpu_stats); |
1174 | if (!svc->stats.cpustats) | 1174 | if (!svc->stats.cpustats) { |
1175 | ret = -ENOMEM; | ||
1175 | goto out_err; | 1176 | goto out_err; |
1177 | } | ||
1176 | 1178 | ||
1177 | /* I'm the first user of the service */ | 1179 | /* I'm the first user of the service */ |
1178 | atomic_set(&svc->usecnt, 0); | 1180 | atomic_set(&svc->usecnt, 0); |
@@ -1801,6 +1803,12 @@ static struct ctl_table vs_vars[] = { | |||
1801 | .mode = 0644, | 1803 | .mode = 0644, |
1802 | .proc_handler = proc_dointvec, | 1804 | .proc_handler = proc_dointvec, |
1803 | }, | 1805 | }, |
1806 | { | ||
1807 | .procname = "pmtu_disc", | ||
1808 | .maxlen = sizeof(int), | ||
1809 | .mode = 0644, | ||
1810 | .proc_handler = proc_dointvec, | ||
1811 | }, | ||
1804 | #ifdef CONFIG_IP_VS_DEBUG | 1812 | #ifdef CONFIG_IP_VS_DEBUG |
1805 | { | 1813 | { |
1806 | .procname = "debug_level", | 1814 | .procname = "debug_level", |
@@ -2759,6 +2767,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
2759 | { | 2767 | { |
2760 | struct ip_vs_timeout_user t; | 2768 | struct ip_vs_timeout_user t; |
2761 | 2769 | ||
2770 | memset(&t, 0, sizeof(t)); | ||
2762 | __ip_vs_get_timeouts(net, &t); | 2771 | __ip_vs_get_timeouts(net, &t); |
2763 | if (copy_to_user(user, &t, sizeof(t)) != 0) | 2772 | if (copy_to_user(user, &t, sizeof(t)) != 0) |
2764 | ret = -EFAULT; | 2773 | ret = -EFAULT; |
@@ -3675,7 +3684,7 @@ static void ip_vs_genl_unregister(void) | |||
3675 | * per netns intit/exit func. | 3684 | * per netns intit/exit func. |
3676 | */ | 3685 | */ |
3677 | #ifdef CONFIG_SYSCTL | 3686 | #ifdef CONFIG_SYSCTL |
3678 | int __net_init ip_vs_control_net_init_sysctl(struct net *net) | 3687 | static int __net_init ip_vs_control_net_init_sysctl(struct net *net) |
3679 | { | 3688 | { |
3680 | int idx; | 3689 | int idx; |
3681 | struct netns_ipvs *ipvs = net_ipvs(net); | 3690 | struct netns_ipvs *ipvs = net_ipvs(net); |
@@ -3726,6 +3735,8 @@ int __net_init ip_vs_control_net_init_sysctl(struct net *net) | |||
3726 | ipvs->sysctl_sync_retries = clamp_t(int, DEFAULT_SYNC_RETRIES, 0, 3); | 3735 | ipvs->sysctl_sync_retries = clamp_t(int, DEFAULT_SYNC_RETRIES, 0, 3); |
3727 | tbl[idx++].data = &ipvs->sysctl_sync_retries; | 3736 | tbl[idx++].data = &ipvs->sysctl_sync_retries; |
3728 | tbl[idx++].data = &ipvs->sysctl_nat_icmp_send; | 3737 | tbl[idx++].data = &ipvs->sysctl_nat_icmp_send; |
3738 | ipvs->sysctl_pmtu_disc = 1; | ||
3739 | tbl[idx++].data = &ipvs->sysctl_pmtu_disc; | ||
3729 | 3740 | ||
3730 | 3741 | ||
3731 | ipvs->sysctl_hdr = register_net_sysctl(net, "net/ipv4/vs", tbl); | 3742 | ipvs->sysctl_hdr = register_net_sysctl(net, "net/ipv4/vs", tbl); |
@@ -3743,7 +3754,7 @@ int __net_init ip_vs_control_net_init_sysctl(struct net *net) | |||
3743 | return 0; | 3754 | return 0; |
3744 | } | 3755 | } |
3745 | 3756 | ||
3746 | void __net_exit ip_vs_control_net_cleanup_sysctl(struct net *net) | 3757 | static void __net_exit ip_vs_control_net_cleanup_sysctl(struct net *net) |
3747 | { | 3758 | { |
3748 | struct netns_ipvs *ipvs = net_ipvs(net); | 3759 | struct netns_ipvs *ipvs = net_ipvs(net); |
3749 | 3760 | ||
@@ -3754,8 +3765,8 @@ void __net_exit ip_vs_control_net_cleanup_sysctl(struct net *net) | |||
3754 | 3765 | ||
3755 | #else | 3766 | #else |
3756 | 3767 | ||
3757 | int __net_init ip_vs_control_net_init_sysctl(struct net *net) { return 0; } | 3768 | static int __net_init ip_vs_control_net_init_sysctl(struct net *net) { return 0; } |
3758 | void __net_exit ip_vs_control_net_cleanup_sysctl(struct net *net) { } | 3769 | static void __net_exit ip_vs_control_net_cleanup_sysctl(struct net *net) { } |
3759 | 3770 | ||
3760 | #endif | 3771 | #endif |
3761 | 3772 | ||
diff --git a/net/netfilter/ipvs/ip_vs_ftp.c b/net/netfilter/ipvs/ip_vs_ftp.c index b20b29c903ef..4f53a5f04437 100644 --- a/net/netfilter/ipvs/ip_vs_ftp.c +++ b/net/netfilter/ipvs/ip_vs_ftp.c | |||
@@ -268,6 +268,7 @@ static int ip_vs_ftp_out(struct ip_vs_app *app, struct ip_vs_conn *cp, | |||
268 | * packet. | 268 | * packet. |
269 | */ | 269 | */ |
270 | ret = nf_nat_mangle_tcp_packet(skb, ct, ctinfo, | 270 | ret = nf_nat_mangle_tcp_packet(skb, ct, ctinfo, |
271 | iph->ihl * 4, | ||
271 | start-data, end-start, | 272 | start-data, end-start, |
272 | buf, buf_len); | 273 | buf, buf_len); |
273 | if (ret) { | 274 | if (ret) { |
@@ -441,16 +442,10 @@ static int __net_init __ip_vs_ftp_init(struct net *net) | |||
441 | 442 | ||
442 | if (!ipvs) | 443 | if (!ipvs) |
443 | return -ENOENT; | 444 | return -ENOENT; |
444 | app = kmemdup(&ip_vs_ftp, sizeof(struct ip_vs_app), GFP_KERNEL); | ||
445 | if (!app) | ||
446 | return -ENOMEM; | ||
447 | INIT_LIST_HEAD(&app->a_list); | ||
448 | INIT_LIST_HEAD(&app->incs_list); | ||
449 | ipvs->ftp_app = app; | ||
450 | 445 | ||
451 | ret = register_ip_vs_app(net, app); | 446 | app = register_ip_vs_app(net, &ip_vs_ftp); |
452 | if (ret) | 447 | if (IS_ERR(app)) |
453 | goto err_exit; | 448 | return PTR_ERR(app); |
454 | 449 | ||
455 | for (i = 0; i < ports_count; i++) { | 450 | for (i = 0; i < ports_count; i++) { |
456 | if (!ports[i]) | 451 | if (!ports[i]) |
@@ -464,9 +459,7 @@ static int __net_init __ip_vs_ftp_init(struct net *net) | |||
464 | return 0; | 459 | return 0; |
465 | 460 | ||
466 | err_unreg: | 461 | err_unreg: |
467 | unregister_ip_vs_app(net, app); | 462 | unregister_ip_vs_app(net, &ip_vs_ftp); |
468 | err_exit: | ||
469 | kfree(ipvs->ftp_app); | ||
470 | return ret; | 463 | return ret; |
471 | } | 464 | } |
472 | /* | 465 | /* |
@@ -474,10 +467,7 @@ err_exit: | |||
474 | */ | 467 | */ |
475 | static void __ip_vs_ftp_exit(struct net *net) | 468 | static void __ip_vs_ftp_exit(struct net *net) |
476 | { | 469 | { |
477 | struct netns_ipvs *ipvs = net_ipvs(net); | 470 | unregister_ip_vs_app(net, &ip_vs_ftp); |
478 | |||
479 | unregister_ip_vs_app(net, ipvs->ftp_app); | ||
480 | kfree(ipvs->ftp_app); | ||
481 | } | 471 | } |
482 | 472 | ||
483 | static struct pernet_operations ip_vs_ftp_ops = { | 473 | static struct pernet_operations ip_vs_ftp_ops = { |
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index 65b616ae1716..56f6d5d81a77 100644 --- a/net/netfilter/ipvs/ip_vs_xmit.c +++ b/net/netfilter/ipvs/ip_vs_xmit.c | |||
@@ -49,6 +49,7 @@ enum { | |||
49 | IP_VS_RT_MODE_RDR = 4, /* Allow redirect from remote daddr to | 49 | IP_VS_RT_MODE_RDR = 4, /* Allow redirect from remote daddr to |
50 | * local | 50 | * local |
51 | */ | 51 | */ |
52 | IP_VS_RT_MODE_CONNECT = 8, /* Always bind route to saddr */ | ||
52 | }; | 53 | }; |
53 | 54 | ||
54 | /* | 55 | /* |
@@ -84,6 +85,58 @@ __ip_vs_dst_check(struct ip_vs_dest *dest, u32 rtos) | |||
84 | return dst; | 85 | return dst; |
85 | } | 86 | } |
86 | 87 | ||
88 | static inline bool | ||
89 | __mtu_check_toobig_v6(const struct sk_buff *skb, u32 mtu) | ||
90 | { | ||
91 | if (IP6CB(skb)->frag_max_size) { | ||
92 | /* frag_max_size tell us that, this packet have been | ||
93 | * defragmented by netfilter IPv6 conntrack module. | ||
94 | */ | ||
95 | if (IP6CB(skb)->frag_max_size > mtu) | ||
96 | return true; /* largest fragment violate MTU */ | ||
97 | } | ||
98 | else if (skb->len > mtu && !skb_is_gso(skb)) { | ||
99 | return true; /* Packet size violate MTU size */ | ||
100 | } | ||
101 | return false; | ||
102 | } | ||
103 | |||
104 | /* Get route to daddr, update *saddr, optionally bind route to saddr */ | ||
105 | static struct rtable *do_output_route4(struct net *net, __be32 daddr, | ||
106 | u32 rtos, int rt_mode, __be32 *saddr) | ||
107 | { | ||
108 | struct flowi4 fl4; | ||
109 | struct rtable *rt; | ||
110 | int loop = 0; | ||
111 | |||
112 | memset(&fl4, 0, sizeof(fl4)); | ||
113 | fl4.daddr = daddr; | ||
114 | fl4.saddr = (rt_mode & IP_VS_RT_MODE_CONNECT) ? *saddr : 0; | ||
115 | fl4.flowi4_tos = rtos; | ||
116 | |||
117 | retry: | ||
118 | rt = ip_route_output_key(net, &fl4); | ||
119 | if (IS_ERR(rt)) { | ||
120 | /* Invalid saddr ? */ | ||
121 | if (PTR_ERR(rt) == -EINVAL && *saddr && | ||
122 | rt_mode & IP_VS_RT_MODE_CONNECT && !loop) { | ||
123 | *saddr = 0; | ||
124 | flowi4_update_output(&fl4, 0, rtos, daddr, 0); | ||
125 | goto retry; | ||
126 | } | ||
127 | IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n", &daddr); | ||
128 | return NULL; | ||
129 | } else if (!*saddr && rt_mode & IP_VS_RT_MODE_CONNECT && fl4.saddr) { | ||
130 | ip_rt_put(rt); | ||
131 | *saddr = fl4.saddr; | ||
132 | flowi4_update_output(&fl4, 0, rtos, daddr, fl4.saddr); | ||
133 | loop++; | ||
134 | goto retry; | ||
135 | } | ||
136 | *saddr = fl4.saddr; | ||
137 | return rt; | ||
138 | } | ||
139 | |||
87 | /* Get route to destination or remote server */ | 140 | /* Get route to destination or remote server */ |
88 | static struct rtable * | 141 | static struct rtable * |
89 | __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest, | 142 | __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest, |
@@ -98,20 +151,13 @@ __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest, | |||
98 | spin_lock(&dest->dst_lock); | 151 | spin_lock(&dest->dst_lock); |
99 | if (!(rt = (struct rtable *) | 152 | if (!(rt = (struct rtable *) |
100 | __ip_vs_dst_check(dest, rtos))) { | 153 | __ip_vs_dst_check(dest, rtos))) { |
101 | struct flowi4 fl4; | 154 | rt = do_output_route4(net, dest->addr.ip, rtos, |
102 | 155 | rt_mode, &dest->dst_saddr.ip); | |
103 | memset(&fl4, 0, sizeof(fl4)); | 156 | if (!rt) { |
104 | fl4.daddr = dest->addr.ip; | ||
105 | fl4.flowi4_tos = rtos; | ||
106 | rt = ip_route_output_key(net, &fl4); | ||
107 | if (IS_ERR(rt)) { | ||
108 | spin_unlock(&dest->dst_lock); | 157 | spin_unlock(&dest->dst_lock); |
109 | IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n", | ||
110 | &dest->addr.ip); | ||
111 | return NULL; | 158 | return NULL; |
112 | } | 159 | } |
113 | __ip_vs_dst_set(dest, rtos, dst_clone(&rt->dst), 0); | 160 | __ip_vs_dst_set(dest, rtos, dst_clone(&rt->dst), 0); |
114 | dest->dst_saddr.ip = fl4.saddr; | ||
115 | IP_VS_DBG(10, "new dst %pI4, src %pI4, refcnt=%d, " | 161 | IP_VS_DBG(10, "new dst %pI4, src %pI4, refcnt=%d, " |
116 | "rtos=%X\n", | 162 | "rtos=%X\n", |
117 | &dest->addr.ip, &dest->dst_saddr.ip, | 163 | &dest->addr.ip, &dest->dst_saddr.ip, |
@@ -122,19 +168,17 @@ __ip_vs_get_out_rt(struct sk_buff *skb, struct ip_vs_dest *dest, | |||
122 | *ret_saddr = dest->dst_saddr.ip; | 168 | *ret_saddr = dest->dst_saddr.ip; |
123 | spin_unlock(&dest->dst_lock); | 169 | spin_unlock(&dest->dst_lock); |
124 | } else { | 170 | } else { |
125 | struct flowi4 fl4; | 171 | __be32 saddr = htonl(INADDR_ANY); |
126 | 172 | ||
127 | memset(&fl4, 0, sizeof(fl4)); | 173 | /* For such unconfigured boxes avoid many route lookups |
128 | fl4.daddr = daddr; | 174 | * for performance reasons because we do not remember saddr |
129 | fl4.flowi4_tos = rtos; | 175 | */ |
130 | rt = ip_route_output_key(net, &fl4); | 176 | rt_mode &= ~IP_VS_RT_MODE_CONNECT; |
131 | if (IS_ERR(rt)) { | 177 | rt = do_output_route4(net, daddr, rtos, rt_mode, &saddr); |
132 | IP_VS_DBG_RL("ip_route_output error, dest: %pI4\n", | 178 | if (!rt) |
133 | &daddr); | ||
134 | return NULL; | 179 | return NULL; |
135 | } | ||
136 | if (ret_saddr) | 180 | if (ret_saddr) |
137 | *ret_saddr = fl4.saddr; | 181 | *ret_saddr = saddr; |
138 | } | 182 | } |
139 | 183 | ||
140 | local = rt->rt_flags & RTCF_LOCAL; | 184 | local = rt->rt_flags & RTCF_LOCAL; |
@@ -331,6 +375,7 @@ ip_vs_dst_reset(struct ip_vs_dest *dest) | |||
331 | old_dst = dest->dst_cache; | 375 | old_dst = dest->dst_cache; |
332 | dest->dst_cache = NULL; | 376 | dest->dst_cache = NULL; |
333 | dst_release(old_dst); | 377 | dst_release(old_dst); |
378 | dest->dst_saddr.ip = 0; | ||
334 | } | 379 | } |
335 | 380 | ||
336 | #define IP_VS_XMIT_TUNNEL(skb, cp) \ | 381 | #define IP_VS_XMIT_TUNNEL(skb, cp) \ |
@@ -462,7 +507,7 @@ ip_vs_bypass_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
462 | 507 | ||
463 | /* MTU checking */ | 508 | /* MTU checking */ |
464 | mtu = dst_mtu(&rt->dst); | 509 | mtu = dst_mtu(&rt->dst); |
465 | if (skb->len > mtu && !skb_is_gso(skb)) { | 510 | if (__mtu_check_toobig_v6(skb, mtu)) { |
466 | if (!skb->dev) { | 511 | if (!skb->dev) { |
467 | struct net *net = dev_net(skb_dst(skb)->dev); | 512 | struct net *net = dev_net(skb_dst(skb)->dev); |
468 | 513 | ||
@@ -683,7 +728,7 @@ ip_vs_nat_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
683 | 728 | ||
684 | /* MTU checking */ | 729 | /* MTU checking */ |
685 | mtu = dst_mtu(&rt->dst); | 730 | mtu = dst_mtu(&rt->dst); |
686 | if (skb->len > mtu && !skb_is_gso(skb)) { | 731 | if (__mtu_check_toobig_v6(skb, mtu)) { |
687 | if (!skb->dev) { | 732 | if (!skb->dev) { |
688 | struct net *net = dev_net(skb_dst(skb)->dev); | 733 | struct net *net = dev_net(skb_dst(skb)->dev); |
689 | 734 | ||
@@ -766,12 +811,13 @@ int | |||
766 | ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | 811 | ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, |
767 | struct ip_vs_protocol *pp) | 812 | struct ip_vs_protocol *pp) |
768 | { | 813 | { |
814 | struct netns_ipvs *ipvs = net_ipvs(skb_net(skb)); | ||
769 | struct rtable *rt; /* Route to the other host */ | 815 | struct rtable *rt; /* Route to the other host */ |
770 | __be32 saddr; /* Source for tunnel */ | 816 | __be32 saddr; /* Source for tunnel */ |
771 | struct net_device *tdev; /* Device to other host */ | 817 | struct net_device *tdev; /* Device to other host */ |
772 | struct iphdr *old_iph = ip_hdr(skb); | 818 | struct iphdr *old_iph = ip_hdr(skb); |
773 | u8 tos = old_iph->tos; | 819 | u8 tos = old_iph->tos; |
774 | __be16 df = old_iph->frag_off; | 820 | __be16 df; |
775 | struct iphdr *iph; /* Our new IP header */ | 821 | struct iphdr *iph; /* Our new IP header */ |
776 | unsigned int max_headroom; /* The extra header space needed */ | 822 | unsigned int max_headroom; /* The extra header space needed */ |
777 | int mtu; | 823 | int mtu; |
@@ -781,7 +827,8 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
781 | 827 | ||
782 | if (!(rt = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip, | 828 | if (!(rt = __ip_vs_get_out_rt(skb, cp->dest, cp->daddr.ip, |
783 | RT_TOS(tos), IP_VS_RT_MODE_LOCAL | | 829 | RT_TOS(tos), IP_VS_RT_MODE_LOCAL | |
784 | IP_VS_RT_MODE_NON_LOCAL, | 830 | IP_VS_RT_MODE_NON_LOCAL | |
831 | IP_VS_RT_MODE_CONNECT, | ||
785 | &saddr))) | 832 | &saddr))) |
786 | goto tx_error_icmp; | 833 | goto tx_error_icmp; |
787 | if (rt->rt_flags & RTCF_LOCAL) { | 834 | if (rt->rt_flags & RTCF_LOCAL) { |
@@ -796,13 +843,13 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
796 | IP_VS_DBG_RL("%s(): mtu less than 68\n", __func__); | 843 | IP_VS_DBG_RL("%s(): mtu less than 68\n", __func__); |
797 | goto tx_error_put; | 844 | goto tx_error_put; |
798 | } | 845 | } |
799 | if (skb_dst(skb)) | 846 | if (rt_is_output_route(skb_rtable(skb))) |
800 | skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu); | 847 | skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu); |
801 | 848 | ||
802 | df |= (old_iph->frag_off & htons(IP_DF)); | 849 | /* Copy DF, reset fragment offset and MF */ |
850 | df = sysctl_pmtu_disc(ipvs) ? old_iph->frag_off & htons(IP_DF) : 0; | ||
803 | 851 | ||
804 | if ((old_iph->frag_off & htons(IP_DF) && | 852 | if (df && mtu < ntohs(old_iph->tot_len) && !skb_is_gso(skb)) { |
805 | mtu < ntohs(old_iph->tot_len) && !skb_is_gso(skb))) { | ||
806 | icmp_send(skb, ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED, htonl(mtu)); | 853 | icmp_send(skb, ICMP_DEST_UNREACH,ICMP_FRAG_NEEDED, htonl(mtu)); |
807 | IP_VS_DBG_RL("%s(): frag needed\n", __func__); | 854 | IP_VS_DBG_RL("%s(): frag needed\n", __func__); |
808 | goto tx_error_put; | 855 | goto tx_error_put; |
@@ -915,8 +962,8 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
915 | if (skb_dst(skb)) | 962 | if (skb_dst(skb)) |
916 | skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu); | 963 | skb_dst(skb)->ops->update_pmtu(skb_dst(skb), NULL, skb, mtu); |
917 | 964 | ||
918 | if (mtu < ntohs(old_iph->payload_len) + sizeof(struct ipv6hdr) && | 965 | /* MTU checking: Notice that 'mtu' have been adjusted before hand */ |
919 | !skb_is_gso(skb)) { | 966 | if (__mtu_check_toobig_v6(skb, mtu)) { |
920 | if (!skb->dev) { | 967 | if (!skb->dev) { |
921 | struct net *net = dev_net(skb_dst(skb)->dev); | 968 | struct net *net = dev_net(skb_dst(skb)->dev); |
922 | 969 | ||
@@ -1082,7 +1129,7 @@ ip_vs_dr_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
1082 | 1129 | ||
1083 | /* MTU checking */ | 1130 | /* MTU checking */ |
1084 | mtu = dst_mtu(&rt->dst); | 1131 | mtu = dst_mtu(&rt->dst); |
1085 | if (skb->len > mtu) { | 1132 | if (__mtu_check_toobig_v6(skb, mtu)) { |
1086 | if (!skb->dev) { | 1133 | if (!skb->dev) { |
1087 | struct net *net = dev_net(skb_dst(skb)->dev); | 1134 | struct net *net = dev_net(skb_dst(skb)->dev); |
1088 | 1135 | ||
@@ -1318,7 +1365,7 @@ ip_vs_icmp_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
1318 | 1365 | ||
1319 | /* MTU checking */ | 1366 | /* MTU checking */ |
1320 | mtu = dst_mtu(&rt->dst); | 1367 | mtu = dst_mtu(&rt->dst); |
1321 | if (skb->len > mtu && !skb_is_gso(skb)) { | 1368 | if (__mtu_check_toobig_v6(skb, mtu)) { |
1322 | if (!skb->dev) { | 1369 | if (!skb->dev) { |
1323 | struct net *net = dev_net(skb_dst(skb)->dev); | 1370 | struct net *net = dev_net(skb_dst(skb)->dev); |
1324 | 1371 | ||
diff --git a/net/netfilter/nf_conntrack_amanda.c b/net/netfilter/nf_conntrack_amanda.c index f2de8c55ac50..c514fe6033d2 100644 --- a/net/netfilter/nf_conntrack_amanda.c +++ b/net/netfilter/nf_conntrack_amanda.c | |||
@@ -40,6 +40,7 @@ MODULE_PARM_DESC(ts_algo, "textsearch algorithm to use (default kmp)"); | |||
40 | 40 | ||
41 | unsigned int (*nf_nat_amanda_hook)(struct sk_buff *skb, | 41 | unsigned int (*nf_nat_amanda_hook)(struct sk_buff *skb, |
42 | enum ip_conntrack_info ctinfo, | 42 | enum ip_conntrack_info ctinfo, |
43 | unsigned int protoff, | ||
43 | unsigned int matchoff, | 44 | unsigned int matchoff, |
44 | unsigned int matchlen, | 45 | unsigned int matchlen, |
45 | struct nf_conntrack_expect *exp) | 46 | struct nf_conntrack_expect *exp) |
@@ -155,8 +156,8 @@ static int amanda_help(struct sk_buff *skb, | |||
155 | 156 | ||
156 | nf_nat_amanda = rcu_dereference(nf_nat_amanda_hook); | 157 | nf_nat_amanda = rcu_dereference(nf_nat_amanda_hook); |
157 | if (nf_nat_amanda && ct->status & IPS_NAT_MASK) | 158 | if (nf_nat_amanda && ct->status & IPS_NAT_MASK) |
158 | ret = nf_nat_amanda(skb, ctinfo, off - dataoff, | 159 | ret = nf_nat_amanda(skb, ctinfo, protoff, |
159 | len, exp); | 160 | off - dataoff, len, exp); |
160 | else if (nf_ct_expect_related(exp) != 0) | 161 | else if (nf_ct_expect_related(exp) != 0) |
161 | ret = NF_DROP; | 162 | ret = NF_DROP; |
162 | nf_ct_expect_put(exp); | 163 | nf_ct_expect_put(exp); |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index cf4875565d67..dcb27910ab3c 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -55,6 +55,12 @@ int (*nfnetlink_parse_nat_setup_hook)(struct nf_conn *ct, | |||
55 | const struct nlattr *attr) __read_mostly; | 55 | const struct nlattr *attr) __read_mostly; |
56 | EXPORT_SYMBOL_GPL(nfnetlink_parse_nat_setup_hook); | 56 | EXPORT_SYMBOL_GPL(nfnetlink_parse_nat_setup_hook); |
57 | 57 | ||
58 | int (*nf_nat_seq_adjust_hook)(struct sk_buff *skb, | ||
59 | struct nf_conn *ct, | ||
60 | enum ip_conntrack_info ctinfo, | ||
61 | unsigned int protoff); | ||
62 | EXPORT_SYMBOL_GPL(nf_nat_seq_adjust_hook); | ||
63 | |||
58 | DEFINE_SPINLOCK(nf_conntrack_lock); | 64 | DEFINE_SPINLOCK(nf_conntrack_lock); |
59 | EXPORT_SYMBOL_GPL(nf_conntrack_lock); | 65 | EXPORT_SYMBOL_GPL(nf_conntrack_lock); |
60 | 66 | ||
@@ -249,12 +255,15 @@ static void death_by_event(unsigned long ul_conntrack) | |||
249 | { | 255 | { |
250 | struct nf_conn *ct = (void *)ul_conntrack; | 256 | struct nf_conn *ct = (void *)ul_conntrack; |
251 | struct net *net = nf_ct_net(ct); | 257 | struct net *net = nf_ct_net(ct); |
258 | struct nf_conntrack_ecache *ecache = nf_ct_ecache_find(ct); | ||
259 | |||
260 | BUG_ON(ecache == NULL); | ||
252 | 261 | ||
253 | if (nf_conntrack_event(IPCT_DESTROY, ct) < 0) { | 262 | if (nf_conntrack_event(IPCT_DESTROY, ct) < 0) { |
254 | /* bad luck, let's retry again */ | 263 | /* bad luck, let's retry again */ |
255 | ct->timeout.expires = jiffies + | 264 | ecache->timeout.expires = jiffies + |
256 | (random32() % net->ct.sysctl_events_retry_timeout); | 265 | (random32() % net->ct.sysctl_events_retry_timeout); |
257 | add_timer(&ct->timeout); | 266 | add_timer(&ecache->timeout); |
258 | return; | 267 | return; |
259 | } | 268 | } |
260 | /* we've got the event delivered, now it's dying */ | 269 | /* we've got the event delivered, now it's dying */ |
@@ -268,6 +277,9 @@ static void death_by_event(unsigned long ul_conntrack) | |||
268 | void nf_ct_insert_dying_list(struct nf_conn *ct) | 277 | void nf_ct_insert_dying_list(struct nf_conn *ct) |
269 | { | 278 | { |
270 | struct net *net = nf_ct_net(ct); | 279 | struct net *net = nf_ct_net(ct); |
280 | struct nf_conntrack_ecache *ecache = nf_ct_ecache_find(ct); | ||
281 | |||
282 | BUG_ON(ecache == NULL); | ||
271 | 283 | ||
272 | /* add this conntrack to the dying list */ | 284 | /* add this conntrack to the dying list */ |
273 | spin_lock_bh(&nf_conntrack_lock); | 285 | spin_lock_bh(&nf_conntrack_lock); |
@@ -275,10 +287,10 @@ void nf_ct_insert_dying_list(struct nf_conn *ct) | |||
275 | &net->ct.dying); | 287 | &net->ct.dying); |
276 | spin_unlock_bh(&nf_conntrack_lock); | 288 | spin_unlock_bh(&nf_conntrack_lock); |
277 | /* set a new timer to retry event delivery */ | 289 | /* set a new timer to retry event delivery */ |
278 | setup_timer(&ct->timeout, death_by_event, (unsigned long)ct); | 290 | setup_timer(&ecache->timeout, death_by_event, (unsigned long)ct); |
279 | ct->timeout.expires = jiffies + | 291 | ecache->timeout.expires = jiffies + |
280 | (random32() % net->ct.sysctl_events_retry_timeout); | 292 | (random32() % net->ct.sysctl_events_retry_timeout); |
281 | add_timer(&ct->timeout); | 293 | add_timer(&ecache->timeout); |
282 | } | 294 | } |
283 | EXPORT_SYMBOL_GPL(nf_ct_insert_dying_list); | 295 | EXPORT_SYMBOL_GPL(nf_ct_insert_dying_list); |
284 | 296 | ||
@@ -924,7 +936,6 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, | |||
924 | enum ip_conntrack_info ctinfo; | 936 | enum ip_conntrack_info ctinfo; |
925 | struct nf_conntrack_l3proto *l3proto; | 937 | struct nf_conntrack_l3proto *l3proto; |
926 | struct nf_conntrack_l4proto *l4proto; | 938 | struct nf_conntrack_l4proto *l4proto; |
927 | struct nf_conn_timeout *timeout_ext; | ||
928 | unsigned int *timeouts; | 939 | unsigned int *timeouts; |
929 | unsigned int dataoff; | 940 | unsigned int dataoff; |
930 | u_int8_t protonum; | 941 | u_int8_t protonum; |
@@ -991,11 +1002,7 @@ nf_conntrack_in(struct net *net, u_int8_t pf, unsigned int hooknum, | |||
991 | NF_CT_ASSERT(skb->nfct); | 1002 | NF_CT_ASSERT(skb->nfct); |
992 | 1003 | ||
993 | /* Decide what timeout policy we want to apply to this flow. */ | 1004 | /* Decide what timeout policy we want to apply to this flow. */ |
994 | timeout_ext = nf_ct_timeout_find(ct); | 1005 | timeouts = nf_ct_timeout_lookup(net, ct, l4proto); |
995 | if (timeout_ext) | ||
996 | timeouts = NF_CT_TIMEOUT_EXT_DATA(timeout_ext); | ||
997 | else | ||
998 | timeouts = l4proto->get_timeouts(net); | ||
999 | 1006 | ||
1000 | ret = l4proto->packet(ct, skb, dataoff, ctinfo, pf, hooknum, timeouts); | 1007 | ret = l4proto->packet(ct, skb, dataoff, ctinfo, pf, hooknum, timeouts); |
1001 | if (ret <= 0) { | 1008 | if (ret <= 0) { |
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 45cf602a76bc..527651a53a45 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c | |||
@@ -361,23 +361,6 @@ static void evict_oldest_expect(struct nf_conn *master, | |||
361 | } | 361 | } |
362 | } | 362 | } |
363 | 363 | ||
364 | static inline int refresh_timer(struct nf_conntrack_expect *i) | ||
365 | { | ||
366 | struct nf_conn_help *master_help = nfct_help(i->master); | ||
367 | const struct nf_conntrack_expect_policy *p; | ||
368 | |||
369 | if (!del_timer(&i->timeout)) | ||
370 | return 0; | ||
371 | |||
372 | p = &rcu_dereference_protected( | ||
373 | master_help->helper, | ||
374 | lockdep_is_held(&nf_conntrack_lock) | ||
375 | )->expect_policy[i->class]; | ||
376 | i->timeout.expires = jiffies + p->timeout * HZ; | ||
377 | add_timer(&i->timeout); | ||
378 | return 1; | ||
379 | } | ||
380 | |||
381 | static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect) | 364 | static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect) |
382 | { | 365 | { |
383 | const struct nf_conntrack_expect_policy *p; | 366 | const struct nf_conntrack_expect_policy *p; |
@@ -386,7 +369,7 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect) | |||
386 | struct nf_conn_help *master_help = nfct_help(master); | 369 | struct nf_conn_help *master_help = nfct_help(master); |
387 | struct nf_conntrack_helper *helper; | 370 | struct nf_conntrack_helper *helper; |
388 | struct net *net = nf_ct_exp_net(expect); | 371 | struct net *net = nf_ct_exp_net(expect); |
389 | struct hlist_node *n; | 372 | struct hlist_node *n, *next; |
390 | unsigned int h; | 373 | unsigned int h; |
391 | int ret = 1; | 374 | int ret = 1; |
392 | 375 | ||
@@ -395,12 +378,12 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect) | |||
395 | goto out; | 378 | goto out; |
396 | } | 379 | } |
397 | h = nf_ct_expect_dst_hash(&expect->tuple); | 380 | h = nf_ct_expect_dst_hash(&expect->tuple); |
398 | hlist_for_each_entry(i, n, &net->ct.expect_hash[h], hnode) { | 381 | hlist_for_each_entry_safe(i, n, next, &net->ct.expect_hash[h], hnode) { |
399 | if (expect_matches(i, expect)) { | 382 | if (expect_matches(i, expect)) { |
400 | /* Refresh timer: if it's dying, ignore.. */ | 383 | if (del_timer(&i->timeout)) { |
401 | if (refresh_timer(i)) { | 384 | nf_ct_unlink_expect(i); |
402 | ret = 0; | 385 | nf_ct_expect_put(i); |
403 | goto out; | 386 | break; |
404 | } | 387 | } |
405 | } else if (expect_clash(i, expect)) { | 388 | } else if (expect_clash(i, expect)) { |
406 | ret = -EBUSY; | 389 | ret = -EBUSY; |
diff --git a/net/netfilter/nf_conntrack_ftp.c b/net/netfilter/nf_conntrack_ftp.c index 4bb771d1f57a..f8cc26ad4456 100644 --- a/net/netfilter/nf_conntrack_ftp.c +++ b/net/netfilter/nf_conntrack_ftp.c | |||
@@ -48,6 +48,7 @@ module_param(loose, bool, 0600); | |||
48 | unsigned int (*nf_nat_ftp_hook)(struct sk_buff *skb, | 48 | unsigned int (*nf_nat_ftp_hook)(struct sk_buff *skb, |
49 | enum ip_conntrack_info ctinfo, | 49 | enum ip_conntrack_info ctinfo, |
50 | enum nf_ct_ftp_type type, | 50 | enum nf_ct_ftp_type type, |
51 | unsigned int protoff, | ||
51 | unsigned int matchoff, | 52 | unsigned int matchoff, |
52 | unsigned int matchlen, | 53 | unsigned int matchlen, |
53 | struct nf_conntrack_expect *exp); | 54 | struct nf_conntrack_expect *exp); |
@@ -489,7 +490,7 @@ static int help(struct sk_buff *skb, | |||
489 | nf_nat_ftp = rcu_dereference(nf_nat_ftp_hook); | 490 | nf_nat_ftp = rcu_dereference(nf_nat_ftp_hook); |
490 | if (nf_nat_ftp && ct->status & IPS_NAT_MASK) | 491 | if (nf_nat_ftp && ct->status & IPS_NAT_MASK) |
491 | ret = nf_nat_ftp(skb, ctinfo, search[dir][i].ftptype, | 492 | ret = nf_nat_ftp(skb, ctinfo, search[dir][i].ftptype, |
492 | matchoff, matchlen, exp); | 493 | protoff, matchoff, matchlen, exp); |
493 | else { | 494 | else { |
494 | /* Can't expect this? Best to drop packet now. */ | 495 | /* Can't expect this? Best to drop packet now. */ |
495 | if (nf_ct_expect_related(exp) != 0) | 496 | if (nf_ct_expect_related(exp) != 0) |
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index 4283b207e63b..1b30b0dee708 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c | |||
@@ -49,12 +49,12 @@ MODULE_PARM_DESC(callforward_filter, "only create call forwarding expectations " | |||
49 | "(determined by routing information)"); | 49 | "(determined by routing information)"); |
50 | 50 | ||
51 | /* Hooks for NAT */ | 51 | /* Hooks for NAT */ |
52 | int (*set_h245_addr_hook) (struct sk_buff *skb, | 52 | int (*set_h245_addr_hook) (struct sk_buff *skb, unsigned int protoff, |
53 | unsigned char **data, int dataoff, | 53 | unsigned char **data, int dataoff, |
54 | H245_TransportAddress *taddr, | 54 | H245_TransportAddress *taddr, |
55 | union nf_inet_addr *addr, __be16 port) | 55 | union nf_inet_addr *addr, __be16 port) |
56 | __read_mostly; | 56 | __read_mostly; |
57 | int (*set_h225_addr_hook) (struct sk_buff *skb, | 57 | int (*set_h225_addr_hook) (struct sk_buff *skb, unsigned int protoff, |
58 | unsigned char **data, int dataoff, | 58 | unsigned char **data, int dataoff, |
59 | TransportAddress *taddr, | 59 | TransportAddress *taddr, |
60 | union nf_inet_addr *addr, __be16 port) | 60 | union nf_inet_addr *addr, __be16 port) |
@@ -62,16 +62,17 @@ int (*set_h225_addr_hook) (struct sk_buff *skb, | |||
62 | int (*set_sig_addr_hook) (struct sk_buff *skb, | 62 | int (*set_sig_addr_hook) (struct sk_buff *skb, |
63 | struct nf_conn *ct, | 63 | struct nf_conn *ct, |
64 | enum ip_conntrack_info ctinfo, | 64 | enum ip_conntrack_info ctinfo, |
65 | unsigned char **data, | 65 | unsigned int protoff, unsigned char **data, |
66 | TransportAddress *taddr, int count) __read_mostly; | 66 | TransportAddress *taddr, int count) __read_mostly; |
67 | int (*set_ras_addr_hook) (struct sk_buff *skb, | 67 | int (*set_ras_addr_hook) (struct sk_buff *skb, |
68 | struct nf_conn *ct, | 68 | struct nf_conn *ct, |
69 | enum ip_conntrack_info ctinfo, | 69 | enum ip_conntrack_info ctinfo, |
70 | unsigned char **data, | 70 | unsigned int protoff, unsigned char **data, |
71 | TransportAddress *taddr, int count) __read_mostly; | 71 | TransportAddress *taddr, int count) __read_mostly; |
72 | int (*nat_rtp_rtcp_hook) (struct sk_buff *skb, | 72 | int (*nat_rtp_rtcp_hook) (struct sk_buff *skb, |
73 | struct nf_conn *ct, | 73 | struct nf_conn *ct, |
74 | enum ip_conntrack_info ctinfo, | 74 | enum ip_conntrack_info ctinfo, |
75 | unsigned int protoff, | ||
75 | unsigned char **data, int dataoff, | 76 | unsigned char **data, int dataoff, |
76 | H245_TransportAddress *taddr, | 77 | H245_TransportAddress *taddr, |
77 | __be16 port, __be16 rtp_port, | 78 | __be16 port, __be16 rtp_port, |
@@ -80,24 +81,28 @@ int (*nat_rtp_rtcp_hook) (struct sk_buff *skb, | |||
80 | int (*nat_t120_hook) (struct sk_buff *skb, | 81 | int (*nat_t120_hook) (struct sk_buff *skb, |
81 | struct nf_conn *ct, | 82 | struct nf_conn *ct, |
82 | enum ip_conntrack_info ctinfo, | 83 | enum ip_conntrack_info ctinfo, |
84 | unsigned int protoff, | ||
83 | unsigned char **data, int dataoff, | 85 | unsigned char **data, int dataoff, |
84 | H245_TransportAddress *taddr, __be16 port, | 86 | H245_TransportAddress *taddr, __be16 port, |
85 | struct nf_conntrack_expect *exp) __read_mostly; | 87 | struct nf_conntrack_expect *exp) __read_mostly; |
86 | int (*nat_h245_hook) (struct sk_buff *skb, | 88 | int (*nat_h245_hook) (struct sk_buff *skb, |
87 | struct nf_conn *ct, | 89 | struct nf_conn *ct, |
88 | enum ip_conntrack_info ctinfo, | 90 | enum ip_conntrack_info ctinfo, |
91 | unsigned int protoff, | ||
89 | unsigned char **data, int dataoff, | 92 | unsigned char **data, int dataoff, |
90 | TransportAddress *taddr, __be16 port, | 93 | TransportAddress *taddr, __be16 port, |
91 | struct nf_conntrack_expect *exp) __read_mostly; | 94 | struct nf_conntrack_expect *exp) __read_mostly; |
92 | int (*nat_callforwarding_hook) (struct sk_buff *skb, | 95 | int (*nat_callforwarding_hook) (struct sk_buff *skb, |
93 | struct nf_conn *ct, | 96 | struct nf_conn *ct, |
94 | enum ip_conntrack_info ctinfo, | 97 | enum ip_conntrack_info ctinfo, |
98 | unsigned int protoff, | ||
95 | unsigned char **data, int dataoff, | 99 | unsigned char **data, int dataoff, |
96 | TransportAddress *taddr, __be16 port, | 100 | TransportAddress *taddr, __be16 port, |
97 | struct nf_conntrack_expect *exp) __read_mostly; | 101 | struct nf_conntrack_expect *exp) __read_mostly; |
98 | int (*nat_q931_hook) (struct sk_buff *skb, | 102 | int (*nat_q931_hook) (struct sk_buff *skb, |
99 | struct nf_conn *ct, | 103 | struct nf_conn *ct, |
100 | enum ip_conntrack_info ctinfo, | 104 | enum ip_conntrack_info ctinfo, |
105 | unsigned int protoff, | ||
101 | unsigned char **data, TransportAddress *taddr, int idx, | 106 | unsigned char **data, TransportAddress *taddr, int idx, |
102 | __be16 port, struct nf_conntrack_expect *exp) | 107 | __be16 port, struct nf_conntrack_expect *exp) |
103 | __read_mostly; | 108 | __read_mostly; |
@@ -251,6 +256,7 @@ static int get_h245_addr(struct nf_conn *ct, const unsigned char *data, | |||
251 | /****************************************************************************/ | 256 | /****************************************************************************/ |
252 | static int expect_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct, | 257 | static int expect_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct, |
253 | enum ip_conntrack_info ctinfo, | 258 | enum ip_conntrack_info ctinfo, |
259 | unsigned int protoff, | ||
254 | unsigned char **data, int dataoff, | 260 | unsigned char **data, int dataoff, |
255 | H245_TransportAddress *taddr) | 261 | H245_TransportAddress *taddr) |
256 | { | 262 | { |
@@ -295,9 +301,10 @@ static int expect_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct, | |||
295 | &ct->tuplehash[!dir].tuple.dst.u3, | 301 | &ct->tuplehash[!dir].tuple.dst.u3, |
296 | sizeof(ct->tuplehash[dir].tuple.src.u3)) && | 302 | sizeof(ct->tuplehash[dir].tuple.src.u3)) && |
297 | (nat_rtp_rtcp = rcu_dereference(nat_rtp_rtcp_hook)) && | 303 | (nat_rtp_rtcp = rcu_dereference(nat_rtp_rtcp_hook)) && |
304 | nf_ct_l3num(ct) == NFPROTO_IPV4 && | ||
298 | ct->status & IPS_NAT_MASK) { | 305 | ct->status & IPS_NAT_MASK) { |
299 | /* NAT needed */ | 306 | /* NAT needed */ |
300 | ret = nat_rtp_rtcp(skb, ct, ctinfo, data, dataoff, | 307 | ret = nat_rtp_rtcp(skb, ct, ctinfo, protoff, data, dataoff, |
301 | taddr, port, rtp_port, rtp_exp, rtcp_exp); | 308 | taddr, port, rtp_port, rtp_exp, rtcp_exp); |
302 | } else { /* Conntrack only */ | 309 | } else { /* Conntrack only */ |
303 | if (nf_ct_expect_related(rtp_exp) == 0) { | 310 | if (nf_ct_expect_related(rtp_exp) == 0) { |
@@ -324,6 +331,7 @@ static int expect_rtp_rtcp(struct sk_buff *skb, struct nf_conn *ct, | |||
324 | static int expect_t120(struct sk_buff *skb, | 331 | static int expect_t120(struct sk_buff *skb, |
325 | struct nf_conn *ct, | 332 | struct nf_conn *ct, |
326 | enum ip_conntrack_info ctinfo, | 333 | enum ip_conntrack_info ctinfo, |
334 | unsigned int protoff, | ||
327 | unsigned char **data, int dataoff, | 335 | unsigned char **data, int dataoff, |
328 | H245_TransportAddress *taddr) | 336 | H245_TransportAddress *taddr) |
329 | { | 337 | { |
@@ -353,9 +361,10 @@ static int expect_t120(struct sk_buff *skb, | |||
353 | &ct->tuplehash[!dir].tuple.dst.u3, | 361 | &ct->tuplehash[!dir].tuple.dst.u3, |
354 | sizeof(ct->tuplehash[dir].tuple.src.u3)) && | 362 | sizeof(ct->tuplehash[dir].tuple.src.u3)) && |
355 | (nat_t120 = rcu_dereference(nat_t120_hook)) && | 363 | (nat_t120 = rcu_dereference(nat_t120_hook)) && |
364 | nf_ct_l3num(ct) == NFPROTO_IPV4 && | ||
356 | ct->status & IPS_NAT_MASK) { | 365 | ct->status & IPS_NAT_MASK) { |
357 | /* NAT needed */ | 366 | /* NAT needed */ |
358 | ret = nat_t120(skb, ct, ctinfo, data, dataoff, taddr, | 367 | ret = nat_t120(skb, ct, ctinfo, protoff, data, dataoff, taddr, |
359 | port, exp); | 368 | port, exp); |
360 | } else { /* Conntrack only */ | 369 | } else { /* Conntrack only */ |
361 | if (nf_ct_expect_related(exp) == 0) { | 370 | if (nf_ct_expect_related(exp) == 0) { |
@@ -374,6 +383,7 @@ static int expect_t120(struct sk_buff *skb, | |||
374 | static int process_h245_channel(struct sk_buff *skb, | 383 | static int process_h245_channel(struct sk_buff *skb, |
375 | struct nf_conn *ct, | 384 | struct nf_conn *ct, |
376 | enum ip_conntrack_info ctinfo, | 385 | enum ip_conntrack_info ctinfo, |
386 | unsigned int protoff, | ||
377 | unsigned char **data, int dataoff, | 387 | unsigned char **data, int dataoff, |
378 | H2250LogicalChannelParameters *channel) | 388 | H2250LogicalChannelParameters *channel) |
379 | { | 389 | { |
@@ -381,7 +391,7 @@ static int process_h245_channel(struct sk_buff *skb, | |||
381 | 391 | ||
382 | if (channel->options & eH2250LogicalChannelParameters_mediaChannel) { | 392 | if (channel->options & eH2250LogicalChannelParameters_mediaChannel) { |
383 | /* RTP */ | 393 | /* RTP */ |
384 | ret = expect_rtp_rtcp(skb, ct, ctinfo, data, dataoff, | 394 | ret = expect_rtp_rtcp(skb, ct, ctinfo, protoff, data, dataoff, |
385 | &channel->mediaChannel); | 395 | &channel->mediaChannel); |
386 | if (ret < 0) | 396 | if (ret < 0) |
387 | return -1; | 397 | return -1; |
@@ -390,7 +400,7 @@ static int process_h245_channel(struct sk_buff *skb, | |||
390 | if (channel-> | 400 | if (channel-> |
391 | options & eH2250LogicalChannelParameters_mediaControlChannel) { | 401 | options & eH2250LogicalChannelParameters_mediaControlChannel) { |
392 | /* RTCP */ | 402 | /* RTCP */ |
393 | ret = expect_rtp_rtcp(skb, ct, ctinfo, data, dataoff, | 403 | ret = expect_rtp_rtcp(skb, ct, ctinfo, protoff, data, dataoff, |
394 | &channel->mediaControlChannel); | 404 | &channel->mediaControlChannel); |
395 | if (ret < 0) | 405 | if (ret < 0) |
396 | return -1; | 406 | return -1; |
@@ -402,6 +412,7 @@ static int process_h245_channel(struct sk_buff *skb, | |||
402 | /****************************************************************************/ | 412 | /****************************************************************************/ |
403 | static int process_olc(struct sk_buff *skb, struct nf_conn *ct, | 413 | static int process_olc(struct sk_buff *skb, struct nf_conn *ct, |
404 | enum ip_conntrack_info ctinfo, | 414 | enum ip_conntrack_info ctinfo, |
415 | unsigned int protoff, | ||
405 | unsigned char **data, int dataoff, | 416 | unsigned char **data, int dataoff, |
406 | OpenLogicalChannel *olc) | 417 | OpenLogicalChannel *olc) |
407 | { | 418 | { |
@@ -412,7 +423,8 @@ static int process_olc(struct sk_buff *skb, struct nf_conn *ct, | |||
412 | if (olc->forwardLogicalChannelParameters.multiplexParameters.choice == | 423 | if (olc->forwardLogicalChannelParameters.multiplexParameters.choice == |
413 | eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters) | 424 | eOpenLogicalChannel_forwardLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters) |
414 | { | 425 | { |
415 | ret = process_h245_channel(skb, ct, ctinfo, data, dataoff, | 426 | ret = process_h245_channel(skb, ct, ctinfo, |
427 | protoff, data, dataoff, | ||
416 | &olc-> | 428 | &olc-> |
417 | forwardLogicalChannelParameters. | 429 | forwardLogicalChannelParameters. |
418 | multiplexParameters. | 430 | multiplexParameters. |
@@ -430,7 +442,8 @@ static int process_olc(struct sk_buff *skb, struct nf_conn *ct, | |||
430 | eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)) | 442 | eOpenLogicalChannel_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)) |
431 | { | 443 | { |
432 | ret = | 444 | ret = |
433 | process_h245_channel(skb, ct, ctinfo, data, dataoff, | 445 | process_h245_channel(skb, ct, ctinfo, |
446 | protoff, data, dataoff, | ||
434 | &olc-> | 447 | &olc-> |
435 | reverseLogicalChannelParameters. | 448 | reverseLogicalChannelParameters. |
436 | multiplexParameters. | 449 | multiplexParameters. |
@@ -448,7 +461,7 @@ static int process_olc(struct sk_buff *skb, struct nf_conn *ct, | |||
448 | t120.choice == eDataProtocolCapability_separateLANStack && | 461 | t120.choice == eDataProtocolCapability_separateLANStack && |
449 | olc->separateStack.networkAddress.choice == | 462 | olc->separateStack.networkAddress.choice == |
450 | eNetworkAccessParameters_networkAddress_localAreaAddress) { | 463 | eNetworkAccessParameters_networkAddress_localAreaAddress) { |
451 | ret = expect_t120(skb, ct, ctinfo, data, dataoff, | 464 | ret = expect_t120(skb, ct, ctinfo, protoff, data, dataoff, |
452 | &olc->separateStack.networkAddress. | 465 | &olc->separateStack.networkAddress. |
453 | localAreaAddress); | 466 | localAreaAddress); |
454 | if (ret < 0) | 467 | if (ret < 0) |
@@ -461,7 +474,7 @@ static int process_olc(struct sk_buff *skb, struct nf_conn *ct, | |||
461 | /****************************************************************************/ | 474 | /****************************************************************************/ |
462 | static int process_olca(struct sk_buff *skb, struct nf_conn *ct, | 475 | static int process_olca(struct sk_buff *skb, struct nf_conn *ct, |
463 | enum ip_conntrack_info ctinfo, | 476 | enum ip_conntrack_info ctinfo, |
464 | unsigned char **data, int dataoff, | 477 | unsigned int protoff, unsigned char **data, int dataoff, |
465 | OpenLogicalChannelAck *olca) | 478 | OpenLogicalChannelAck *olca) |
466 | { | 479 | { |
467 | H2250LogicalChannelAckParameters *ack; | 480 | H2250LogicalChannelAckParameters *ack; |
@@ -477,7 +490,8 @@ static int process_olca(struct sk_buff *skb, struct nf_conn *ct, | |||
477 | choice == | 490 | choice == |
478 | eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)) | 491 | eOpenLogicalChannelAck_reverseLogicalChannelParameters_multiplexParameters_h2250LogicalChannelParameters)) |
479 | { | 492 | { |
480 | ret = process_h245_channel(skb, ct, ctinfo, data, dataoff, | 493 | ret = process_h245_channel(skb, ct, ctinfo, |
494 | protoff, data, dataoff, | ||
481 | &olca-> | 495 | &olca-> |
482 | reverseLogicalChannelParameters. | 496 | reverseLogicalChannelParameters. |
483 | multiplexParameters. | 497 | multiplexParameters. |
@@ -496,7 +510,8 @@ static int process_olca(struct sk_buff *skb, struct nf_conn *ct, | |||
496 | if (ack->options & | 510 | if (ack->options & |
497 | eH2250LogicalChannelAckParameters_mediaChannel) { | 511 | eH2250LogicalChannelAckParameters_mediaChannel) { |
498 | /* RTP */ | 512 | /* RTP */ |
499 | ret = expect_rtp_rtcp(skb, ct, ctinfo, data, dataoff, | 513 | ret = expect_rtp_rtcp(skb, ct, ctinfo, |
514 | protoff, data, dataoff, | ||
500 | &ack->mediaChannel); | 515 | &ack->mediaChannel); |
501 | if (ret < 0) | 516 | if (ret < 0) |
502 | return -1; | 517 | return -1; |
@@ -505,7 +520,8 @@ static int process_olca(struct sk_buff *skb, struct nf_conn *ct, | |||
505 | if (ack->options & | 520 | if (ack->options & |
506 | eH2250LogicalChannelAckParameters_mediaControlChannel) { | 521 | eH2250LogicalChannelAckParameters_mediaControlChannel) { |
507 | /* RTCP */ | 522 | /* RTCP */ |
508 | ret = expect_rtp_rtcp(skb, ct, ctinfo, data, dataoff, | 523 | ret = expect_rtp_rtcp(skb, ct, ctinfo, |
524 | protoff, data, dataoff, | ||
509 | &ack->mediaControlChannel); | 525 | &ack->mediaControlChannel); |
510 | if (ret < 0) | 526 | if (ret < 0) |
511 | return -1; | 527 | return -1; |
@@ -515,7 +531,7 @@ static int process_olca(struct sk_buff *skb, struct nf_conn *ct, | |||
515 | if ((olca->options & eOpenLogicalChannelAck_separateStack) && | 531 | if ((olca->options & eOpenLogicalChannelAck_separateStack) && |
516 | olca->separateStack.networkAddress.choice == | 532 | olca->separateStack.networkAddress.choice == |
517 | eNetworkAccessParameters_networkAddress_localAreaAddress) { | 533 | eNetworkAccessParameters_networkAddress_localAreaAddress) { |
518 | ret = expect_t120(skb, ct, ctinfo, data, dataoff, | 534 | ret = expect_t120(skb, ct, ctinfo, protoff, data, dataoff, |
519 | &olca->separateStack.networkAddress. | 535 | &olca->separateStack.networkAddress. |
520 | localAreaAddress); | 536 | localAreaAddress); |
521 | if (ret < 0) | 537 | if (ret < 0) |
@@ -528,14 +544,15 @@ static int process_olca(struct sk_buff *skb, struct nf_conn *ct, | |||
528 | /****************************************************************************/ | 544 | /****************************************************************************/ |
529 | static int process_h245(struct sk_buff *skb, struct nf_conn *ct, | 545 | static int process_h245(struct sk_buff *skb, struct nf_conn *ct, |
530 | enum ip_conntrack_info ctinfo, | 546 | enum ip_conntrack_info ctinfo, |
531 | unsigned char **data, int dataoff, | 547 | unsigned int protoff, unsigned char **data, int dataoff, |
532 | MultimediaSystemControlMessage *mscm) | 548 | MultimediaSystemControlMessage *mscm) |
533 | { | 549 | { |
534 | switch (mscm->choice) { | 550 | switch (mscm->choice) { |
535 | case eMultimediaSystemControlMessage_request: | 551 | case eMultimediaSystemControlMessage_request: |
536 | if (mscm->request.choice == | 552 | if (mscm->request.choice == |
537 | eRequestMessage_openLogicalChannel) { | 553 | eRequestMessage_openLogicalChannel) { |
538 | return process_olc(skb, ct, ctinfo, data, dataoff, | 554 | return process_olc(skb, ct, ctinfo, |
555 | protoff, data, dataoff, | ||
539 | &mscm->request.openLogicalChannel); | 556 | &mscm->request.openLogicalChannel); |
540 | } | 557 | } |
541 | pr_debug("nf_ct_h323: H.245 Request %d\n", | 558 | pr_debug("nf_ct_h323: H.245 Request %d\n", |
@@ -544,7 +561,8 @@ static int process_h245(struct sk_buff *skb, struct nf_conn *ct, | |||
544 | case eMultimediaSystemControlMessage_response: | 561 | case eMultimediaSystemControlMessage_response: |
545 | if (mscm->response.choice == | 562 | if (mscm->response.choice == |
546 | eResponseMessage_openLogicalChannelAck) { | 563 | eResponseMessage_openLogicalChannelAck) { |
547 | return process_olca(skb, ct, ctinfo, data, dataoff, | 564 | return process_olca(skb, ct, ctinfo, |
565 | protoff, data, dataoff, | ||
548 | &mscm->response. | 566 | &mscm->response. |
549 | openLogicalChannelAck); | 567 | openLogicalChannelAck); |
550 | } | 568 | } |
@@ -595,7 +613,8 @@ static int h245_help(struct sk_buff *skb, unsigned int protoff, | |||
595 | } | 613 | } |
596 | 614 | ||
597 | /* Process H.245 signal */ | 615 | /* Process H.245 signal */ |
598 | if (process_h245(skb, ct, ctinfo, &data, dataoff, &mscm) < 0) | 616 | if (process_h245(skb, ct, ctinfo, protoff, |
617 | &data, dataoff, &mscm) < 0) | ||
599 | goto drop; | 618 | goto drop; |
600 | } | 619 | } |
601 | 620 | ||
@@ -659,7 +678,7 @@ int get_h225_addr(struct nf_conn *ct, unsigned char *data, | |||
659 | /****************************************************************************/ | 678 | /****************************************************************************/ |
660 | static int expect_h245(struct sk_buff *skb, struct nf_conn *ct, | 679 | static int expect_h245(struct sk_buff *skb, struct nf_conn *ct, |
661 | enum ip_conntrack_info ctinfo, | 680 | enum ip_conntrack_info ctinfo, |
662 | unsigned char **data, int dataoff, | 681 | unsigned int protoff, unsigned char **data, int dataoff, |
663 | TransportAddress *taddr) | 682 | TransportAddress *taddr) |
664 | { | 683 | { |
665 | int dir = CTINFO2DIR(ctinfo); | 684 | int dir = CTINFO2DIR(ctinfo); |
@@ -688,9 +707,10 @@ static int expect_h245(struct sk_buff *skb, struct nf_conn *ct, | |||
688 | &ct->tuplehash[!dir].tuple.dst.u3, | 707 | &ct->tuplehash[!dir].tuple.dst.u3, |
689 | sizeof(ct->tuplehash[dir].tuple.src.u3)) && | 708 | sizeof(ct->tuplehash[dir].tuple.src.u3)) && |
690 | (nat_h245 = rcu_dereference(nat_h245_hook)) && | 709 | (nat_h245 = rcu_dereference(nat_h245_hook)) && |
710 | nf_ct_l3num(ct) == NFPROTO_IPV4 && | ||
691 | ct->status & IPS_NAT_MASK) { | 711 | ct->status & IPS_NAT_MASK) { |
692 | /* NAT needed */ | 712 | /* NAT needed */ |
693 | ret = nat_h245(skb, ct, ctinfo, data, dataoff, taddr, | 713 | ret = nat_h245(skb, ct, ctinfo, protoff, data, dataoff, taddr, |
694 | port, exp); | 714 | port, exp); |
695 | } else { /* Conntrack only */ | 715 | } else { /* Conntrack only */ |
696 | if (nf_ct_expect_related(exp) == 0) { | 716 | if (nf_ct_expect_related(exp) == 0) { |
@@ -776,6 +796,7 @@ static int callforward_do_filter(const union nf_inet_addr *src, | |||
776 | static int expect_callforwarding(struct sk_buff *skb, | 796 | static int expect_callforwarding(struct sk_buff *skb, |
777 | struct nf_conn *ct, | 797 | struct nf_conn *ct, |
778 | enum ip_conntrack_info ctinfo, | 798 | enum ip_conntrack_info ctinfo, |
799 | unsigned int protoff, | ||
779 | unsigned char **data, int dataoff, | 800 | unsigned char **data, int dataoff, |
780 | TransportAddress *taddr) | 801 | TransportAddress *taddr) |
781 | { | 802 | { |
@@ -811,9 +832,11 @@ static int expect_callforwarding(struct sk_buff *skb, | |||
811 | &ct->tuplehash[!dir].tuple.dst.u3, | 832 | &ct->tuplehash[!dir].tuple.dst.u3, |
812 | sizeof(ct->tuplehash[dir].tuple.src.u3)) && | 833 | sizeof(ct->tuplehash[dir].tuple.src.u3)) && |
813 | (nat_callforwarding = rcu_dereference(nat_callforwarding_hook)) && | 834 | (nat_callforwarding = rcu_dereference(nat_callforwarding_hook)) && |
835 | nf_ct_l3num(ct) == NFPROTO_IPV4 && | ||
814 | ct->status & IPS_NAT_MASK) { | 836 | ct->status & IPS_NAT_MASK) { |
815 | /* Need NAT */ | 837 | /* Need NAT */ |
816 | ret = nat_callforwarding(skb, ct, ctinfo, data, dataoff, | 838 | ret = nat_callforwarding(skb, ct, ctinfo, |
839 | protoff, data, dataoff, | ||
817 | taddr, port, exp); | 840 | taddr, port, exp); |
818 | } else { /* Conntrack only */ | 841 | } else { /* Conntrack only */ |
819 | if (nf_ct_expect_related(exp) == 0) { | 842 | if (nf_ct_expect_related(exp) == 0) { |
@@ -831,6 +854,7 @@ static int expect_callforwarding(struct sk_buff *skb, | |||
831 | /****************************************************************************/ | 854 | /****************************************************************************/ |
832 | static int process_setup(struct sk_buff *skb, struct nf_conn *ct, | 855 | static int process_setup(struct sk_buff *skb, struct nf_conn *ct, |
833 | enum ip_conntrack_info ctinfo, | 856 | enum ip_conntrack_info ctinfo, |
857 | unsigned int protoff, | ||
834 | unsigned char **data, int dataoff, | 858 | unsigned char **data, int dataoff, |
835 | Setup_UUIE *setup) | 859 | Setup_UUIE *setup) |
836 | { | 860 | { |
@@ -844,7 +868,7 @@ static int process_setup(struct sk_buff *skb, struct nf_conn *ct, | |||
844 | pr_debug("nf_ct_q931: Setup\n"); | 868 | pr_debug("nf_ct_q931: Setup\n"); |
845 | 869 | ||
846 | if (setup->options & eSetup_UUIE_h245Address) { | 870 | if (setup->options & eSetup_UUIE_h245Address) { |
847 | ret = expect_h245(skb, ct, ctinfo, data, dataoff, | 871 | ret = expect_h245(skb, ct, ctinfo, protoff, data, dataoff, |
848 | &setup->h245Address); | 872 | &setup->h245Address); |
849 | if (ret < 0) | 873 | if (ret < 0) |
850 | return -1; | 874 | return -1; |
@@ -852,14 +876,15 @@ static int process_setup(struct sk_buff *skb, struct nf_conn *ct, | |||
852 | 876 | ||
853 | set_h225_addr = rcu_dereference(set_h225_addr_hook); | 877 | set_h225_addr = rcu_dereference(set_h225_addr_hook); |
854 | if ((setup->options & eSetup_UUIE_destCallSignalAddress) && | 878 | if ((setup->options & eSetup_UUIE_destCallSignalAddress) && |
855 | (set_h225_addr) && ct->status & IPS_NAT_MASK && | 879 | (set_h225_addr) && nf_ct_l3num(ct) == NFPROTO_IPV4 && |
880 | ct->status & IPS_NAT_MASK && | ||
856 | get_h225_addr(ct, *data, &setup->destCallSignalAddress, | 881 | get_h225_addr(ct, *data, &setup->destCallSignalAddress, |
857 | &addr, &port) && | 882 | &addr, &port) && |
858 | memcmp(&addr, &ct->tuplehash[!dir].tuple.src.u3, sizeof(addr))) { | 883 | memcmp(&addr, &ct->tuplehash[!dir].tuple.src.u3, sizeof(addr))) { |
859 | pr_debug("nf_ct_q931: set destCallSignalAddress %pI6:%hu->%pI6:%hu\n", | 884 | pr_debug("nf_ct_q931: set destCallSignalAddress %pI6:%hu->%pI6:%hu\n", |
860 | &addr, ntohs(port), &ct->tuplehash[!dir].tuple.src.u3, | 885 | &addr, ntohs(port), &ct->tuplehash[!dir].tuple.src.u3, |
861 | ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port)); | 886 | ntohs(ct->tuplehash[!dir].tuple.src.u.tcp.port)); |
862 | ret = set_h225_addr(skb, data, dataoff, | 887 | ret = set_h225_addr(skb, protoff, data, dataoff, |
863 | &setup->destCallSignalAddress, | 888 | &setup->destCallSignalAddress, |
864 | &ct->tuplehash[!dir].tuple.src.u3, | 889 | &ct->tuplehash[!dir].tuple.src.u3, |
865 | ct->tuplehash[!dir].tuple.src.u.tcp.port); | 890 | ct->tuplehash[!dir].tuple.src.u.tcp.port); |
@@ -868,14 +893,15 @@ static int process_setup(struct sk_buff *skb, struct nf_conn *ct, | |||
868 | } | 893 | } |
869 | 894 | ||
870 | if ((setup->options & eSetup_UUIE_sourceCallSignalAddress) && | 895 | if ((setup->options & eSetup_UUIE_sourceCallSignalAddress) && |
871 | (set_h225_addr) && ct->status & IPS_NAT_MASK && | 896 | (set_h225_addr) && nf_ct_l3num(ct) == NFPROTO_IPV4 && |
897 | ct->status & IPS_NAT_MASK && | ||
872 | get_h225_addr(ct, *data, &setup->sourceCallSignalAddress, | 898 | get_h225_addr(ct, *data, &setup->sourceCallSignalAddress, |
873 | &addr, &port) && | 899 | &addr, &port) && |
874 | memcmp(&addr, &ct->tuplehash[!dir].tuple.dst.u3, sizeof(addr))) { | 900 | memcmp(&addr, &ct->tuplehash[!dir].tuple.dst.u3, sizeof(addr))) { |
875 | pr_debug("nf_ct_q931: set sourceCallSignalAddress %pI6:%hu->%pI6:%hu\n", | 901 | pr_debug("nf_ct_q931: set sourceCallSignalAddress %pI6:%hu->%pI6:%hu\n", |
876 | &addr, ntohs(port), &ct->tuplehash[!dir].tuple.dst.u3, | 902 | &addr, ntohs(port), &ct->tuplehash[!dir].tuple.dst.u3, |
877 | ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port)); | 903 | ntohs(ct->tuplehash[!dir].tuple.dst.u.tcp.port)); |
878 | ret = set_h225_addr(skb, data, dataoff, | 904 | ret = set_h225_addr(skb, protoff, data, dataoff, |
879 | &setup->sourceCallSignalAddress, | 905 | &setup->sourceCallSignalAddress, |
880 | &ct->tuplehash[!dir].tuple.dst.u3, | 906 | &ct->tuplehash[!dir].tuple.dst.u3, |
881 | ct->tuplehash[!dir].tuple.dst.u.tcp.port); | 907 | ct->tuplehash[!dir].tuple.dst.u.tcp.port); |
@@ -885,7 +911,8 @@ static int process_setup(struct sk_buff *skb, struct nf_conn *ct, | |||
885 | 911 | ||
886 | if (setup->options & eSetup_UUIE_fastStart) { | 912 | if (setup->options & eSetup_UUIE_fastStart) { |
887 | for (i = 0; i < setup->fastStart.count; i++) { | 913 | for (i = 0; i < setup->fastStart.count; i++) { |
888 | ret = process_olc(skb, ct, ctinfo, data, dataoff, | 914 | ret = process_olc(skb, ct, ctinfo, |
915 | protoff, data, dataoff, | ||
889 | &setup->fastStart.item[i]); | 916 | &setup->fastStart.item[i]); |
890 | if (ret < 0) | 917 | if (ret < 0) |
891 | return -1; | 918 | return -1; |
@@ -899,6 +926,7 @@ static int process_setup(struct sk_buff *skb, struct nf_conn *ct, | |||
899 | static int process_callproceeding(struct sk_buff *skb, | 926 | static int process_callproceeding(struct sk_buff *skb, |
900 | struct nf_conn *ct, | 927 | struct nf_conn *ct, |
901 | enum ip_conntrack_info ctinfo, | 928 | enum ip_conntrack_info ctinfo, |
929 | unsigned int protoff, | ||
902 | unsigned char **data, int dataoff, | 930 | unsigned char **data, int dataoff, |
903 | CallProceeding_UUIE *callproc) | 931 | CallProceeding_UUIE *callproc) |
904 | { | 932 | { |
@@ -908,7 +936,7 @@ static int process_callproceeding(struct sk_buff *skb, | |||
908 | pr_debug("nf_ct_q931: CallProceeding\n"); | 936 | pr_debug("nf_ct_q931: CallProceeding\n"); |
909 | 937 | ||
910 | if (callproc->options & eCallProceeding_UUIE_h245Address) { | 938 | if (callproc->options & eCallProceeding_UUIE_h245Address) { |
911 | ret = expect_h245(skb, ct, ctinfo, data, dataoff, | 939 | ret = expect_h245(skb, ct, ctinfo, protoff, data, dataoff, |
912 | &callproc->h245Address); | 940 | &callproc->h245Address); |
913 | if (ret < 0) | 941 | if (ret < 0) |
914 | return -1; | 942 | return -1; |
@@ -916,7 +944,8 @@ static int process_callproceeding(struct sk_buff *skb, | |||
916 | 944 | ||
917 | if (callproc->options & eCallProceeding_UUIE_fastStart) { | 945 | if (callproc->options & eCallProceeding_UUIE_fastStart) { |
918 | for (i = 0; i < callproc->fastStart.count; i++) { | 946 | for (i = 0; i < callproc->fastStart.count; i++) { |
919 | ret = process_olc(skb, ct, ctinfo, data, dataoff, | 947 | ret = process_olc(skb, ct, ctinfo, |
948 | protoff, data, dataoff, | ||
920 | &callproc->fastStart.item[i]); | 949 | &callproc->fastStart.item[i]); |
921 | if (ret < 0) | 950 | if (ret < 0) |
922 | return -1; | 951 | return -1; |
@@ -929,6 +958,7 @@ static int process_callproceeding(struct sk_buff *skb, | |||
929 | /****************************************************************************/ | 958 | /****************************************************************************/ |
930 | static int process_connect(struct sk_buff *skb, struct nf_conn *ct, | 959 | static int process_connect(struct sk_buff *skb, struct nf_conn *ct, |
931 | enum ip_conntrack_info ctinfo, | 960 | enum ip_conntrack_info ctinfo, |
961 | unsigned int protoff, | ||
932 | unsigned char **data, int dataoff, | 962 | unsigned char **data, int dataoff, |
933 | Connect_UUIE *connect) | 963 | Connect_UUIE *connect) |
934 | { | 964 | { |
@@ -938,7 +968,7 @@ static int process_connect(struct sk_buff *skb, struct nf_conn *ct, | |||
938 | pr_debug("nf_ct_q931: Connect\n"); | 968 | pr_debug("nf_ct_q931: Connect\n"); |
939 | 969 | ||
940 | if (connect->options & eConnect_UUIE_h245Address) { | 970 | if (connect->options & eConnect_UUIE_h245Address) { |
941 | ret = expect_h245(skb, ct, ctinfo, data, dataoff, | 971 | ret = expect_h245(skb, ct, ctinfo, protoff, data, dataoff, |
942 | &connect->h245Address); | 972 | &connect->h245Address); |
943 | if (ret < 0) | 973 | if (ret < 0) |
944 | return -1; | 974 | return -1; |
@@ -946,7 +976,8 @@ static int process_connect(struct sk_buff *skb, struct nf_conn *ct, | |||
946 | 976 | ||
947 | if (connect->options & eConnect_UUIE_fastStart) { | 977 | if (connect->options & eConnect_UUIE_fastStart) { |
948 | for (i = 0; i < connect->fastStart.count; i++) { | 978 | for (i = 0; i < connect->fastStart.count; i++) { |
949 | ret = process_olc(skb, ct, ctinfo, data, dataoff, | 979 | ret = process_olc(skb, ct, ctinfo, |
980 | protoff, data, dataoff, | ||
950 | &connect->fastStart.item[i]); | 981 | &connect->fastStart.item[i]); |
951 | if (ret < 0) | 982 | if (ret < 0) |
952 | return -1; | 983 | return -1; |
@@ -959,6 +990,7 @@ static int process_connect(struct sk_buff *skb, struct nf_conn *ct, | |||
959 | /****************************************************************************/ | 990 | /****************************************************************************/ |
960 | static int process_alerting(struct sk_buff *skb, struct nf_conn *ct, | 991 | static int process_alerting(struct sk_buff *skb, struct nf_conn *ct, |
961 | enum ip_conntrack_info ctinfo, | 992 | enum ip_conntrack_info ctinfo, |
993 | unsigned int protoff, | ||
962 | unsigned char **data, int dataoff, | 994 | unsigned char **data, int dataoff, |
963 | Alerting_UUIE *alert) | 995 | Alerting_UUIE *alert) |
964 | { | 996 | { |
@@ -968,7 +1000,7 @@ static int process_alerting(struct sk_buff *skb, struct nf_conn *ct, | |||
968 | pr_debug("nf_ct_q931: Alerting\n"); | 1000 | pr_debug("nf_ct_q931: Alerting\n"); |
969 | 1001 | ||
970 | if (alert->options & eAlerting_UUIE_h245Address) { | 1002 | if (alert->options & eAlerting_UUIE_h245Address) { |
971 | ret = expect_h245(skb, ct, ctinfo, data, dataoff, | 1003 | ret = expect_h245(skb, ct, ctinfo, protoff, data, dataoff, |
972 | &alert->h245Address); | 1004 | &alert->h245Address); |
973 | if (ret < 0) | 1005 | if (ret < 0) |
974 | return -1; | 1006 | return -1; |
@@ -976,7 +1008,8 @@ static int process_alerting(struct sk_buff *skb, struct nf_conn *ct, | |||
976 | 1008 | ||
977 | if (alert->options & eAlerting_UUIE_fastStart) { | 1009 | if (alert->options & eAlerting_UUIE_fastStart) { |
978 | for (i = 0; i < alert->fastStart.count; i++) { | 1010 | for (i = 0; i < alert->fastStart.count; i++) { |
979 | ret = process_olc(skb, ct, ctinfo, data, dataoff, | 1011 | ret = process_olc(skb, ct, ctinfo, |
1012 | protoff, data, dataoff, | ||
980 | &alert->fastStart.item[i]); | 1013 | &alert->fastStart.item[i]); |
981 | if (ret < 0) | 1014 | if (ret < 0) |
982 | return -1; | 1015 | return -1; |
@@ -989,6 +1022,7 @@ static int process_alerting(struct sk_buff *skb, struct nf_conn *ct, | |||
989 | /****************************************************************************/ | 1022 | /****************************************************************************/ |
990 | static int process_facility(struct sk_buff *skb, struct nf_conn *ct, | 1023 | static int process_facility(struct sk_buff *skb, struct nf_conn *ct, |
991 | enum ip_conntrack_info ctinfo, | 1024 | enum ip_conntrack_info ctinfo, |
1025 | unsigned int protoff, | ||
992 | unsigned char **data, int dataoff, | 1026 | unsigned char **data, int dataoff, |
993 | Facility_UUIE *facility) | 1027 | Facility_UUIE *facility) |
994 | { | 1028 | { |
@@ -999,15 +1033,15 @@ static int process_facility(struct sk_buff *skb, struct nf_conn *ct, | |||
999 | 1033 | ||
1000 | if (facility->reason.choice == eFacilityReason_callForwarded) { | 1034 | if (facility->reason.choice == eFacilityReason_callForwarded) { |
1001 | if (facility->options & eFacility_UUIE_alternativeAddress) | 1035 | if (facility->options & eFacility_UUIE_alternativeAddress) |
1002 | return expect_callforwarding(skb, ct, ctinfo, data, | 1036 | return expect_callforwarding(skb, ct, ctinfo, |
1003 | dataoff, | 1037 | protoff, data, dataoff, |
1004 | &facility-> | 1038 | &facility-> |
1005 | alternativeAddress); | 1039 | alternativeAddress); |
1006 | return 0; | 1040 | return 0; |
1007 | } | 1041 | } |
1008 | 1042 | ||
1009 | if (facility->options & eFacility_UUIE_h245Address) { | 1043 | if (facility->options & eFacility_UUIE_h245Address) { |
1010 | ret = expect_h245(skb, ct, ctinfo, data, dataoff, | 1044 | ret = expect_h245(skb, ct, ctinfo, protoff, data, dataoff, |
1011 | &facility->h245Address); | 1045 | &facility->h245Address); |
1012 | if (ret < 0) | 1046 | if (ret < 0) |
1013 | return -1; | 1047 | return -1; |
@@ -1015,7 +1049,8 @@ static int process_facility(struct sk_buff *skb, struct nf_conn *ct, | |||
1015 | 1049 | ||
1016 | if (facility->options & eFacility_UUIE_fastStart) { | 1050 | if (facility->options & eFacility_UUIE_fastStart) { |
1017 | for (i = 0; i < facility->fastStart.count; i++) { | 1051 | for (i = 0; i < facility->fastStart.count; i++) { |
1018 | ret = process_olc(skb, ct, ctinfo, data, dataoff, | 1052 | ret = process_olc(skb, ct, ctinfo, |
1053 | protoff, data, dataoff, | ||
1019 | &facility->fastStart.item[i]); | 1054 | &facility->fastStart.item[i]); |
1020 | if (ret < 0) | 1055 | if (ret < 0) |
1021 | return -1; | 1056 | return -1; |
@@ -1028,6 +1063,7 @@ static int process_facility(struct sk_buff *skb, struct nf_conn *ct, | |||
1028 | /****************************************************************************/ | 1063 | /****************************************************************************/ |
1029 | static int process_progress(struct sk_buff *skb, struct nf_conn *ct, | 1064 | static int process_progress(struct sk_buff *skb, struct nf_conn *ct, |
1030 | enum ip_conntrack_info ctinfo, | 1065 | enum ip_conntrack_info ctinfo, |
1066 | unsigned int protoff, | ||
1031 | unsigned char **data, int dataoff, | 1067 | unsigned char **data, int dataoff, |
1032 | Progress_UUIE *progress) | 1068 | Progress_UUIE *progress) |
1033 | { | 1069 | { |
@@ -1037,7 +1073,7 @@ static int process_progress(struct sk_buff *skb, struct nf_conn *ct, | |||
1037 | pr_debug("nf_ct_q931: Progress\n"); | 1073 | pr_debug("nf_ct_q931: Progress\n"); |
1038 | 1074 | ||
1039 | if (progress->options & eProgress_UUIE_h245Address) { | 1075 | if (progress->options & eProgress_UUIE_h245Address) { |
1040 | ret = expect_h245(skb, ct, ctinfo, data, dataoff, | 1076 | ret = expect_h245(skb, ct, ctinfo, protoff, data, dataoff, |
1041 | &progress->h245Address); | 1077 | &progress->h245Address); |
1042 | if (ret < 0) | 1078 | if (ret < 0) |
1043 | return -1; | 1079 | return -1; |
@@ -1045,7 +1081,8 @@ static int process_progress(struct sk_buff *skb, struct nf_conn *ct, | |||
1045 | 1081 | ||
1046 | if (progress->options & eProgress_UUIE_fastStart) { | 1082 | if (progress->options & eProgress_UUIE_fastStart) { |
1047 | for (i = 0; i < progress->fastStart.count; i++) { | 1083 | for (i = 0; i < progress->fastStart.count; i++) { |
1048 | ret = process_olc(skb, ct, ctinfo, data, dataoff, | 1084 | ret = process_olc(skb, ct, ctinfo, |
1085 | protoff, data, dataoff, | ||
1049 | &progress->fastStart.item[i]); | 1086 | &progress->fastStart.item[i]); |
1050 | if (ret < 0) | 1087 | if (ret < 0) |
1051 | return -1; | 1088 | return -1; |
@@ -1058,7 +1095,8 @@ static int process_progress(struct sk_buff *skb, struct nf_conn *ct, | |||
1058 | /****************************************************************************/ | 1095 | /****************************************************************************/ |
1059 | static int process_q931(struct sk_buff *skb, struct nf_conn *ct, | 1096 | static int process_q931(struct sk_buff *skb, struct nf_conn *ct, |
1060 | enum ip_conntrack_info ctinfo, | 1097 | enum ip_conntrack_info ctinfo, |
1061 | unsigned char **data, int dataoff, Q931 *q931) | 1098 | unsigned int protoff, unsigned char **data, int dataoff, |
1099 | Q931 *q931) | ||
1062 | { | 1100 | { |
1063 | H323_UU_PDU *pdu = &q931->UUIE.h323_uu_pdu; | 1101 | H323_UU_PDU *pdu = &q931->UUIE.h323_uu_pdu; |
1064 | int i; | 1102 | int i; |
@@ -1066,28 +1104,29 @@ static int process_q931(struct sk_buff *skb, struct nf_conn *ct, | |||
1066 | 1104 | ||
1067 | switch (pdu->h323_message_body.choice) { | 1105 | switch (pdu->h323_message_body.choice) { |
1068 | case eH323_UU_PDU_h323_message_body_setup: | 1106 | case eH323_UU_PDU_h323_message_body_setup: |
1069 | ret = process_setup(skb, ct, ctinfo, data, dataoff, | 1107 | ret = process_setup(skb, ct, ctinfo, protoff, data, dataoff, |
1070 | &pdu->h323_message_body.setup); | 1108 | &pdu->h323_message_body.setup); |
1071 | break; | 1109 | break; |
1072 | case eH323_UU_PDU_h323_message_body_callProceeding: | 1110 | case eH323_UU_PDU_h323_message_body_callProceeding: |
1073 | ret = process_callproceeding(skb, ct, ctinfo, data, dataoff, | 1111 | ret = process_callproceeding(skb, ct, ctinfo, |
1112 | protoff, data, dataoff, | ||
1074 | &pdu->h323_message_body. | 1113 | &pdu->h323_message_body. |
1075 | callProceeding); | 1114 | callProceeding); |
1076 | break; | 1115 | break; |
1077 | case eH323_UU_PDU_h323_message_body_connect: | 1116 | case eH323_UU_PDU_h323_message_body_connect: |
1078 | ret = process_connect(skb, ct, ctinfo, data, dataoff, | 1117 | ret = process_connect(skb, ct, ctinfo, protoff, data, dataoff, |
1079 | &pdu->h323_message_body.connect); | 1118 | &pdu->h323_message_body.connect); |
1080 | break; | 1119 | break; |
1081 | case eH323_UU_PDU_h323_message_body_alerting: | 1120 | case eH323_UU_PDU_h323_message_body_alerting: |
1082 | ret = process_alerting(skb, ct, ctinfo, data, dataoff, | 1121 | ret = process_alerting(skb, ct, ctinfo, protoff, data, dataoff, |
1083 | &pdu->h323_message_body.alerting); | 1122 | &pdu->h323_message_body.alerting); |
1084 | break; | 1123 | break; |
1085 | case eH323_UU_PDU_h323_message_body_facility: | 1124 | case eH323_UU_PDU_h323_message_body_facility: |
1086 | ret = process_facility(skb, ct, ctinfo, data, dataoff, | 1125 | ret = process_facility(skb, ct, ctinfo, protoff, data, dataoff, |
1087 | &pdu->h323_message_body.facility); | 1126 | &pdu->h323_message_body.facility); |
1088 | break; | 1127 | break; |
1089 | case eH323_UU_PDU_h323_message_body_progress: | 1128 | case eH323_UU_PDU_h323_message_body_progress: |
1090 | ret = process_progress(skb, ct, ctinfo, data, dataoff, | 1129 | ret = process_progress(skb, ct, ctinfo, protoff, data, dataoff, |
1091 | &pdu->h323_message_body.progress); | 1130 | &pdu->h323_message_body.progress); |
1092 | break; | 1131 | break; |
1093 | default: | 1132 | default: |
@@ -1101,7 +1140,8 @@ static int process_q931(struct sk_buff *skb, struct nf_conn *ct, | |||
1101 | 1140 | ||
1102 | if (pdu->options & eH323_UU_PDU_h245Control) { | 1141 | if (pdu->options & eH323_UU_PDU_h245Control) { |
1103 | for (i = 0; i < pdu->h245Control.count; i++) { | 1142 | for (i = 0; i < pdu->h245Control.count; i++) { |
1104 | ret = process_h245(skb, ct, ctinfo, data, dataoff, | 1143 | ret = process_h245(skb, ct, ctinfo, |
1144 | protoff, data, dataoff, | ||
1105 | &pdu->h245Control.item[i]); | 1145 | &pdu->h245Control.item[i]); |
1106 | if (ret < 0) | 1146 | if (ret < 0) |
1107 | return -1; | 1147 | return -1; |
@@ -1146,7 +1186,8 @@ static int q931_help(struct sk_buff *skb, unsigned int protoff, | |||
1146 | } | 1186 | } |
1147 | 1187 | ||
1148 | /* Process Q.931 signal */ | 1188 | /* Process Q.931 signal */ |
1149 | if (process_q931(skb, ct, ctinfo, &data, dataoff, &q931) < 0) | 1189 | if (process_q931(skb, ct, ctinfo, protoff, |
1190 | &data, dataoff, &q931) < 0) | ||
1150 | goto drop; | 1191 | goto drop; |
1151 | } | 1192 | } |
1152 | 1193 | ||
@@ -1243,7 +1284,7 @@ static int set_expect_timeout(struct nf_conntrack_expect *exp, | |||
1243 | /****************************************************************************/ | 1284 | /****************************************************************************/ |
1244 | static int expect_q931(struct sk_buff *skb, struct nf_conn *ct, | 1285 | static int expect_q931(struct sk_buff *skb, struct nf_conn *ct, |
1245 | enum ip_conntrack_info ctinfo, | 1286 | enum ip_conntrack_info ctinfo, |
1246 | unsigned char **data, | 1287 | unsigned int protoff, unsigned char **data, |
1247 | TransportAddress *taddr, int count) | 1288 | TransportAddress *taddr, int count) |
1248 | { | 1289 | { |
1249 | struct nf_ct_h323_master *info = nfct_help_data(ct); | 1290 | struct nf_ct_h323_master *info = nfct_help_data(ct); |
@@ -1278,8 +1319,10 @@ static int expect_q931(struct sk_buff *skb, struct nf_conn *ct, | |||
1278 | exp->flags = NF_CT_EXPECT_PERMANENT; /* Accept multiple calls */ | 1319 | exp->flags = NF_CT_EXPECT_PERMANENT; /* Accept multiple calls */ |
1279 | 1320 | ||
1280 | nat_q931 = rcu_dereference(nat_q931_hook); | 1321 | nat_q931 = rcu_dereference(nat_q931_hook); |
1281 | if (nat_q931 && ct->status & IPS_NAT_MASK) { /* Need NAT */ | 1322 | if (nat_q931 && nf_ct_l3num(ct) == NFPROTO_IPV4 && |
1282 | ret = nat_q931(skb, ct, ctinfo, data, taddr, i, port, exp); | 1323 | ct->status & IPS_NAT_MASK) { /* Need NAT */ |
1324 | ret = nat_q931(skb, ct, ctinfo, protoff, data, | ||
1325 | taddr, i, port, exp); | ||
1283 | } else { /* Conntrack only */ | 1326 | } else { /* Conntrack only */ |
1284 | if (nf_ct_expect_related(exp) == 0) { | 1327 | if (nf_ct_expect_related(exp) == 0) { |
1285 | pr_debug("nf_ct_ras: expect Q.931 "); | 1328 | pr_debug("nf_ct_ras: expect Q.931 "); |
@@ -1299,6 +1342,7 @@ static int expect_q931(struct sk_buff *skb, struct nf_conn *ct, | |||
1299 | /****************************************************************************/ | 1342 | /****************************************************************************/ |
1300 | static int process_grq(struct sk_buff *skb, struct nf_conn *ct, | 1343 | static int process_grq(struct sk_buff *skb, struct nf_conn *ct, |
1301 | enum ip_conntrack_info ctinfo, | 1344 | enum ip_conntrack_info ctinfo, |
1345 | unsigned int protoff, | ||
1302 | unsigned char **data, GatekeeperRequest *grq) | 1346 | unsigned char **data, GatekeeperRequest *grq) |
1303 | { | 1347 | { |
1304 | typeof(set_ras_addr_hook) set_ras_addr; | 1348 | typeof(set_ras_addr_hook) set_ras_addr; |
@@ -1306,8 +1350,9 @@ static int process_grq(struct sk_buff *skb, struct nf_conn *ct, | |||
1306 | pr_debug("nf_ct_ras: GRQ\n"); | 1350 | pr_debug("nf_ct_ras: GRQ\n"); |
1307 | 1351 | ||
1308 | set_ras_addr = rcu_dereference(set_ras_addr_hook); | 1352 | set_ras_addr = rcu_dereference(set_ras_addr_hook); |
1309 | if (set_ras_addr && ct->status & IPS_NAT_MASK) /* NATed */ | 1353 | if (set_ras_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 && |
1310 | return set_ras_addr(skb, ct, ctinfo, data, | 1354 | ct->status & IPS_NAT_MASK) /* NATed */ |
1355 | return set_ras_addr(skb, ct, ctinfo, protoff, data, | ||
1311 | &grq->rasAddress, 1); | 1356 | &grq->rasAddress, 1); |
1312 | return 0; | 1357 | return 0; |
1313 | } | 1358 | } |
@@ -1315,6 +1360,7 @@ static int process_grq(struct sk_buff *skb, struct nf_conn *ct, | |||
1315 | /****************************************************************************/ | 1360 | /****************************************************************************/ |
1316 | static int process_gcf(struct sk_buff *skb, struct nf_conn *ct, | 1361 | static int process_gcf(struct sk_buff *skb, struct nf_conn *ct, |
1317 | enum ip_conntrack_info ctinfo, | 1362 | enum ip_conntrack_info ctinfo, |
1363 | unsigned int protoff, | ||
1318 | unsigned char **data, GatekeeperConfirm *gcf) | 1364 | unsigned char **data, GatekeeperConfirm *gcf) |
1319 | { | 1365 | { |
1320 | int dir = CTINFO2DIR(ctinfo); | 1366 | int dir = CTINFO2DIR(ctinfo); |
@@ -1359,6 +1405,7 @@ static int process_gcf(struct sk_buff *skb, struct nf_conn *ct, | |||
1359 | /****************************************************************************/ | 1405 | /****************************************************************************/ |
1360 | static int process_rrq(struct sk_buff *skb, struct nf_conn *ct, | 1406 | static int process_rrq(struct sk_buff *skb, struct nf_conn *ct, |
1361 | enum ip_conntrack_info ctinfo, | 1407 | enum ip_conntrack_info ctinfo, |
1408 | unsigned int protoff, | ||
1362 | unsigned char **data, RegistrationRequest *rrq) | 1409 | unsigned char **data, RegistrationRequest *rrq) |
1363 | { | 1410 | { |
1364 | struct nf_ct_h323_master *info = nfct_help_data(ct); | 1411 | struct nf_ct_h323_master *info = nfct_help_data(ct); |
@@ -1367,15 +1414,16 @@ static int process_rrq(struct sk_buff *skb, struct nf_conn *ct, | |||
1367 | 1414 | ||
1368 | pr_debug("nf_ct_ras: RRQ\n"); | 1415 | pr_debug("nf_ct_ras: RRQ\n"); |
1369 | 1416 | ||
1370 | ret = expect_q931(skb, ct, ctinfo, data, | 1417 | ret = expect_q931(skb, ct, ctinfo, protoff, data, |
1371 | rrq->callSignalAddress.item, | 1418 | rrq->callSignalAddress.item, |
1372 | rrq->callSignalAddress.count); | 1419 | rrq->callSignalAddress.count); |
1373 | if (ret < 0) | 1420 | if (ret < 0) |
1374 | return -1; | 1421 | return -1; |
1375 | 1422 | ||
1376 | set_ras_addr = rcu_dereference(set_ras_addr_hook); | 1423 | set_ras_addr = rcu_dereference(set_ras_addr_hook); |
1377 | if (set_ras_addr && ct->status & IPS_NAT_MASK) { | 1424 | if (set_ras_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 && |
1378 | ret = set_ras_addr(skb, ct, ctinfo, data, | 1425 | ct->status & IPS_NAT_MASK) { |
1426 | ret = set_ras_addr(skb, ct, ctinfo, protoff, data, | ||
1379 | rrq->rasAddress.item, | 1427 | rrq->rasAddress.item, |
1380 | rrq->rasAddress.count); | 1428 | rrq->rasAddress.count); |
1381 | if (ret < 0) | 1429 | if (ret < 0) |
@@ -1394,6 +1442,7 @@ static int process_rrq(struct sk_buff *skb, struct nf_conn *ct, | |||
1394 | /****************************************************************************/ | 1442 | /****************************************************************************/ |
1395 | static int process_rcf(struct sk_buff *skb, struct nf_conn *ct, | 1443 | static int process_rcf(struct sk_buff *skb, struct nf_conn *ct, |
1396 | enum ip_conntrack_info ctinfo, | 1444 | enum ip_conntrack_info ctinfo, |
1445 | unsigned int protoff, | ||
1397 | unsigned char **data, RegistrationConfirm *rcf) | 1446 | unsigned char **data, RegistrationConfirm *rcf) |
1398 | { | 1447 | { |
1399 | struct nf_ct_h323_master *info = nfct_help_data(ct); | 1448 | struct nf_ct_h323_master *info = nfct_help_data(ct); |
@@ -1405,8 +1454,9 @@ static int process_rcf(struct sk_buff *skb, struct nf_conn *ct, | |||
1405 | pr_debug("nf_ct_ras: RCF\n"); | 1454 | pr_debug("nf_ct_ras: RCF\n"); |
1406 | 1455 | ||
1407 | set_sig_addr = rcu_dereference(set_sig_addr_hook); | 1456 | set_sig_addr = rcu_dereference(set_sig_addr_hook); |
1408 | if (set_sig_addr && ct->status & IPS_NAT_MASK) { | 1457 | if (set_sig_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 && |
1409 | ret = set_sig_addr(skb, ct, ctinfo, data, | 1458 | ct->status & IPS_NAT_MASK) { |
1459 | ret = set_sig_addr(skb, ct, ctinfo, protoff, data, | ||
1410 | rcf->callSignalAddress.item, | 1460 | rcf->callSignalAddress.item, |
1411 | rcf->callSignalAddress.count); | 1461 | rcf->callSignalAddress.count); |
1412 | if (ret < 0) | 1462 | if (ret < 0) |
@@ -1443,6 +1493,7 @@ static int process_rcf(struct sk_buff *skb, struct nf_conn *ct, | |||
1443 | /****************************************************************************/ | 1493 | /****************************************************************************/ |
1444 | static int process_urq(struct sk_buff *skb, struct nf_conn *ct, | 1494 | static int process_urq(struct sk_buff *skb, struct nf_conn *ct, |
1445 | enum ip_conntrack_info ctinfo, | 1495 | enum ip_conntrack_info ctinfo, |
1496 | unsigned int protoff, | ||
1446 | unsigned char **data, UnregistrationRequest *urq) | 1497 | unsigned char **data, UnregistrationRequest *urq) |
1447 | { | 1498 | { |
1448 | struct nf_ct_h323_master *info = nfct_help_data(ct); | 1499 | struct nf_ct_h323_master *info = nfct_help_data(ct); |
@@ -1453,8 +1504,9 @@ static int process_urq(struct sk_buff *skb, struct nf_conn *ct, | |||
1453 | pr_debug("nf_ct_ras: URQ\n"); | 1504 | pr_debug("nf_ct_ras: URQ\n"); |
1454 | 1505 | ||
1455 | set_sig_addr = rcu_dereference(set_sig_addr_hook); | 1506 | set_sig_addr = rcu_dereference(set_sig_addr_hook); |
1456 | if (set_sig_addr && ct->status & IPS_NAT_MASK) { | 1507 | if (set_sig_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 && |
1457 | ret = set_sig_addr(skb, ct, ctinfo, data, | 1508 | ct->status & IPS_NAT_MASK) { |
1509 | ret = set_sig_addr(skb, ct, ctinfo, protoff, data, | ||
1458 | urq->callSignalAddress.item, | 1510 | urq->callSignalAddress.item, |
1459 | urq->callSignalAddress.count); | 1511 | urq->callSignalAddress.count); |
1460 | if (ret < 0) | 1512 | if (ret < 0) |
@@ -1475,6 +1527,7 @@ static int process_urq(struct sk_buff *skb, struct nf_conn *ct, | |||
1475 | /****************************************************************************/ | 1527 | /****************************************************************************/ |
1476 | static int process_arq(struct sk_buff *skb, struct nf_conn *ct, | 1528 | static int process_arq(struct sk_buff *skb, struct nf_conn *ct, |
1477 | enum ip_conntrack_info ctinfo, | 1529 | enum ip_conntrack_info ctinfo, |
1530 | unsigned int protoff, | ||
1478 | unsigned char **data, AdmissionRequest *arq) | 1531 | unsigned char **data, AdmissionRequest *arq) |
1479 | { | 1532 | { |
1480 | const struct nf_ct_h323_master *info = nfct_help_data(ct); | 1533 | const struct nf_ct_h323_master *info = nfct_help_data(ct); |
@@ -1491,9 +1544,10 @@ static int process_arq(struct sk_buff *skb, struct nf_conn *ct, | |||
1491 | &addr, &port) && | 1544 | &addr, &port) && |
1492 | !memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) && | 1545 | !memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) && |
1493 | port == info->sig_port[dir] && | 1546 | port == info->sig_port[dir] && |
1547 | nf_ct_l3num(ct) == NFPROTO_IPV4 && | ||
1494 | set_h225_addr && ct->status & IPS_NAT_MASK) { | 1548 | set_h225_addr && ct->status & IPS_NAT_MASK) { |
1495 | /* Answering ARQ */ | 1549 | /* Answering ARQ */ |
1496 | return set_h225_addr(skb, data, 0, | 1550 | return set_h225_addr(skb, protoff, data, 0, |
1497 | &arq->destCallSignalAddress, | 1551 | &arq->destCallSignalAddress, |
1498 | &ct->tuplehash[!dir].tuple.dst.u3, | 1552 | &ct->tuplehash[!dir].tuple.dst.u3, |
1499 | info->sig_port[!dir]); | 1553 | info->sig_port[!dir]); |
@@ -1503,9 +1557,10 @@ static int process_arq(struct sk_buff *skb, struct nf_conn *ct, | |||
1503 | get_h225_addr(ct, *data, &arq->srcCallSignalAddress, | 1557 | get_h225_addr(ct, *data, &arq->srcCallSignalAddress, |
1504 | &addr, &port) && | 1558 | &addr, &port) && |
1505 | !memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) && | 1559 | !memcmp(&addr, &ct->tuplehash[dir].tuple.src.u3, sizeof(addr)) && |
1506 | set_h225_addr && ct->status & IPS_NAT_MASK) { | 1560 | set_h225_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 && |
1561 | ct->status & IPS_NAT_MASK) { | ||
1507 | /* Calling ARQ */ | 1562 | /* Calling ARQ */ |
1508 | return set_h225_addr(skb, data, 0, | 1563 | return set_h225_addr(skb, protoff, data, 0, |
1509 | &arq->srcCallSignalAddress, | 1564 | &arq->srcCallSignalAddress, |
1510 | &ct->tuplehash[!dir].tuple.dst.u3, | 1565 | &ct->tuplehash[!dir].tuple.dst.u3, |
1511 | port); | 1566 | port); |
@@ -1517,6 +1572,7 @@ static int process_arq(struct sk_buff *skb, struct nf_conn *ct, | |||
1517 | /****************************************************************************/ | 1572 | /****************************************************************************/ |
1518 | static int process_acf(struct sk_buff *skb, struct nf_conn *ct, | 1573 | static int process_acf(struct sk_buff *skb, struct nf_conn *ct, |
1519 | enum ip_conntrack_info ctinfo, | 1574 | enum ip_conntrack_info ctinfo, |
1575 | unsigned int protoff, | ||
1520 | unsigned char **data, AdmissionConfirm *acf) | 1576 | unsigned char **data, AdmissionConfirm *acf) |
1521 | { | 1577 | { |
1522 | int dir = CTINFO2DIR(ctinfo); | 1578 | int dir = CTINFO2DIR(ctinfo); |
@@ -1535,8 +1591,9 @@ static int process_acf(struct sk_buff *skb, struct nf_conn *ct, | |||
1535 | if (!memcmp(&addr, &ct->tuplehash[dir].tuple.dst.u3, sizeof(addr))) { | 1591 | if (!memcmp(&addr, &ct->tuplehash[dir].tuple.dst.u3, sizeof(addr))) { |
1536 | /* Answering ACF */ | 1592 | /* Answering ACF */ |
1537 | set_sig_addr = rcu_dereference(set_sig_addr_hook); | 1593 | set_sig_addr = rcu_dereference(set_sig_addr_hook); |
1538 | if (set_sig_addr && ct->status & IPS_NAT_MASK) | 1594 | if (set_sig_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 && |
1539 | return set_sig_addr(skb, ct, ctinfo, data, | 1595 | ct->status & IPS_NAT_MASK) |
1596 | return set_sig_addr(skb, ct, ctinfo, protoff, data, | ||
1540 | &acf->destCallSignalAddress, 1); | 1597 | &acf->destCallSignalAddress, 1); |
1541 | return 0; | 1598 | return 0; |
1542 | } | 1599 | } |
@@ -1564,6 +1621,7 @@ static int process_acf(struct sk_buff *skb, struct nf_conn *ct, | |||
1564 | /****************************************************************************/ | 1621 | /****************************************************************************/ |
1565 | static int process_lrq(struct sk_buff *skb, struct nf_conn *ct, | 1622 | static int process_lrq(struct sk_buff *skb, struct nf_conn *ct, |
1566 | enum ip_conntrack_info ctinfo, | 1623 | enum ip_conntrack_info ctinfo, |
1624 | unsigned int protoff, | ||
1567 | unsigned char **data, LocationRequest *lrq) | 1625 | unsigned char **data, LocationRequest *lrq) |
1568 | { | 1626 | { |
1569 | typeof(set_ras_addr_hook) set_ras_addr; | 1627 | typeof(set_ras_addr_hook) set_ras_addr; |
@@ -1571,8 +1629,9 @@ static int process_lrq(struct sk_buff *skb, struct nf_conn *ct, | |||
1571 | pr_debug("nf_ct_ras: LRQ\n"); | 1629 | pr_debug("nf_ct_ras: LRQ\n"); |
1572 | 1630 | ||
1573 | set_ras_addr = rcu_dereference(set_ras_addr_hook); | 1631 | set_ras_addr = rcu_dereference(set_ras_addr_hook); |
1574 | if (set_ras_addr && ct->status & IPS_NAT_MASK) | 1632 | if (set_ras_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 && |
1575 | return set_ras_addr(skb, ct, ctinfo, data, | 1633 | ct->status & IPS_NAT_MASK) |
1634 | return set_ras_addr(skb, ct, ctinfo, protoff, data, | ||
1576 | &lrq->replyAddress, 1); | 1635 | &lrq->replyAddress, 1); |
1577 | return 0; | 1636 | return 0; |
1578 | } | 1637 | } |
@@ -1580,6 +1639,7 @@ static int process_lrq(struct sk_buff *skb, struct nf_conn *ct, | |||
1580 | /****************************************************************************/ | 1639 | /****************************************************************************/ |
1581 | static int process_lcf(struct sk_buff *skb, struct nf_conn *ct, | 1640 | static int process_lcf(struct sk_buff *skb, struct nf_conn *ct, |
1582 | enum ip_conntrack_info ctinfo, | 1641 | enum ip_conntrack_info ctinfo, |
1642 | unsigned int protoff, | ||
1583 | unsigned char **data, LocationConfirm *lcf) | 1643 | unsigned char **data, LocationConfirm *lcf) |
1584 | { | 1644 | { |
1585 | int dir = CTINFO2DIR(ctinfo); | 1645 | int dir = CTINFO2DIR(ctinfo); |
@@ -1619,6 +1679,7 @@ static int process_lcf(struct sk_buff *skb, struct nf_conn *ct, | |||
1619 | /****************************************************************************/ | 1679 | /****************************************************************************/ |
1620 | static int process_irr(struct sk_buff *skb, struct nf_conn *ct, | 1680 | static int process_irr(struct sk_buff *skb, struct nf_conn *ct, |
1621 | enum ip_conntrack_info ctinfo, | 1681 | enum ip_conntrack_info ctinfo, |
1682 | unsigned int protoff, | ||
1622 | unsigned char **data, InfoRequestResponse *irr) | 1683 | unsigned char **data, InfoRequestResponse *irr) |
1623 | { | 1684 | { |
1624 | int ret; | 1685 | int ret; |
@@ -1628,16 +1689,18 @@ static int process_irr(struct sk_buff *skb, struct nf_conn *ct, | |||
1628 | pr_debug("nf_ct_ras: IRR\n"); | 1689 | pr_debug("nf_ct_ras: IRR\n"); |
1629 | 1690 | ||
1630 | set_ras_addr = rcu_dereference(set_ras_addr_hook); | 1691 | set_ras_addr = rcu_dereference(set_ras_addr_hook); |
1631 | if (set_ras_addr && ct->status & IPS_NAT_MASK) { | 1692 | if (set_ras_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 && |
1632 | ret = set_ras_addr(skb, ct, ctinfo, data, | 1693 | ct->status & IPS_NAT_MASK) { |
1694 | ret = set_ras_addr(skb, ct, ctinfo, protoff, data, | ||
1633 | &irr->rasAddress, 1); | 1695 | &irr->rasAddress, 1); |
1634 | if (ret < 0) | 1696 | if (ret < 0) |
1635 | return -1; | 1697 | return -1; |
1636 | } | 1698 | } |
1637 | 1699 | ||
1638 | set_sig_addr = rcu_dereference(set_sig_addr_hook); | 1700 | set_sig_addr = rcu_dereference(set_sig_addr_hook); |
1639 | if (set_sig_addr && ct->status & IPS_NAT_MASK) { | 1701 | if (set_sig_addr && nf_ct_l3num(ct) == NFPROTO_IPV4 && |
1640 | ret = set_sig_addr(skb, ct, ctinfo, data, | 1702 | ct->status & IPS_NAT_MASK) { |
1703 | ret = set_sig_addr(skb, ct, ctinfo, protoff, data, | ||
1641 | irr->callSignalAddress.item, | 1704 | irr->callSignalAddress.item, |
1642 | irr->callSignalAddress.count); | 1705 | irr->callSignalAddress.count); |
1643 | if (ret < 0) | 1706 | if (ret < 0) |
@@ -1650,38 +1713,39 @@ static int process_irr(struct sk_buff *skb, struct nf_conn *ct, | |||
1650 | /****************************************************************************/ | 1713 | /****************************************************************************/ |
1651 | static int process_ras(struct sk_buff *skb, struct nf_conn *ct, | 1714 | static int process_ras(struct sk_buff *skb, struct nf_conn *ct, |
1652 | enum ip_conntrack_info ctinfo, | 1715 | enum ip_conntrack_info ctinfo, |
1716 | unsigned int protoff, | ||
1653 | unsigned char **data, RasMessage *ras) | 1717 | unsigned char **data, RasMessage *ras) |
1654 | { | 1718 | { |
1655 | switch (ras->choice) { | 1719 | switch (ras->choice) { |
1656 | case eRasMessage_gatekeeperRequest: | 1720 | case eRasMessage_gatekeeperRequest: |
1657 | return process_grq(skb, ct, ctinfo, data, | 1721 | return process_grq(skb, ct, ctinfo, protoff, data, |
1658 | &ras->gatekeeperRequest); | 1722 | &ras->gatekeeperRequest); |
1659 | case eRasMessage_gatekeeperConfirm: | 1723 | case eRasMessage_gatekeeperConfirm: |
1660 | return process_gcf(skb, ct, ctinfo, data, | 1724 | return process_gcf(skb, ct, ctinfo, protoff, data, |
1661 | &ras->gatekeeperConfirm); | 1725 | &ras->gatekeeperConfirm); |
1662 | case eRasMessage_registrationRequest: | 1726 | case eRasMessage_registrationRequest: |
1663 | return process_rrq(skb, ct, ctinfo, data, | 1727 | return process_rrq(skb, ct, ctinfo, protoff, data, |
1664 | &ras->registrationRequest); | 1728 | &ras->registrationRequest); |
1665 | case eRasMessage_registrationConfirm: | 1729 | case eRasMessage_registrationConfirm: |
1666 | return process_rcf(skb, ct, ctinfo, data, | 1730 | return process_rcf(skb, ct, ctinfo, protoff, data, |
1667 | &ras->registrationConfirm); | 1731 | &ras->registrationConfirm); |
1668 | case eRasMessage_unregistrationRequest: | 1732 | case eRasMessage_unregistrationRequest: |
1669 | return process_urq(skb, ct, ctinfo, data, | 1733 | return process_urq(skb, ct, ctinfo, protoff, data, |
1670 | &ras->unregistrationRequest); | 1734 | &ras->unregistrationRequest); |
1671 | case eRasMessage_admissionRequest: | 1735 | case eRasMessage_admissionRequest: |
1672 | return process_arq(skb, ct, ctinfo, data, | 1736 | return process_arq(skb, ct, ctinfo, protoff, data, |
1673 | &ras->admissionRequest); | 1737 | &ras->admissionRequest); |
1674 | case eRasMessage_admissionConfirm: | 1738 | case eRasMessage_admissionConfirm: |
1675 | return process_acf(skb, ct, ctinfo, data, | 1739 | return process_acf(skb, ct, ctinfo, protoff, data, |
1676 | &ras->admissionConfirm); | 1740 | &ras->admissionConfirm); |
1677 | case eRasMessage_locationRequest: | 1741 | case eRasMessage_locationRequest: |
1678 | return process_lrq(skb, ct, ctinfo, data, | 1742 | return process_lrq(skb, ct, ctinfo, protoff, data, |
1679 | &ras->locationRequest); | 1743 | &ras->locationRequest); |
1680 | case eRasMessage_locationConfirm: | 1744 | case eRasMessage_locationConfirm: |
1681 | return process_lcf(skb, ct, ctinfo, data, | 1745 | return process_lcf(skb, ct, ctinfo, protoff, data, |
1682 | &ras->locationConfirm); | 1746 | &ras->locationConfirm); |
1683 | case eRasMessage_infoRequestResponse: | 1747 | case eRasMessage_infoRequestResponse: |
1684 | return process_irr(skb, ct, ctinfo, data, | 1748 | return process_irr(skb, ct, ctinfo, protoff, data, |
1685 | &ras->infoRequestResponse); | 1749 | &ras->infoRequestResponse); |
1686 | default: | 1750 | default: |
1687 | pr_debug("nf_ct_ras: RAS message %d\n", ras->choice); | 1751 | pr_debug("nf_ct_ras: RAS message %d\n", ras->choice); |
@@ -1721,7 +1785,7 @@ static int ras_help(struct sk_buff *skb, unsigned int protoff, | |||
1721 | } | 1785 | } |
1722 | 1786 | ||
1723 | /* Process RAS message */ | 1787 | /* Process RAS message */ |
1724 | if (process_ras(skb, ct, ctinfo, &data, &ras) < 0) | 1788 | if (process_ras(skb, ct, ctinfo, protoff, &data, &ras) < 0) |
1725 | goto drop; | 1789 | goto drop; |
1726 | 1790 | ||
1727 | accept: | 1791 | accept: |
diff --git a/net/netfilter/nf_conntrack_irc.c b/net/netfilter/nf_conntrack_irc.c index 009c52cfd1ec..3b20aa77cfc8 100644 --- a/net/netfilter/nf_conntrack_irc.c +++ b/net/netfilter/nf_conntrack_irc.c | |||
@@ -33,6 +33,7 @@ static DEFINE_SPINLOCK(irc_buffer_lock); | |||
33 | 33 | ||
34 | unsigned int (*nf_nat_irc_hook)(struct sk_buff *skb, | 34 | unsigned int (*nf_nat_irc_hook)(struct sk_buff *skb, |
35 | enum ip_conntrack_info ctinfo, | 35 | enum ip_conntrack_info ctinfo, |
36 | unsigned int protoff, | ||
36 | unsigned int matchoff, | 37 | unsigned int matchoff, |
37 | unsigned int matchlen, | 38 | unsigned int matchlen, |
38 | struct nf_conntrack_expect *exp) __read_mostly; | 39 | struct nf_conntrack_expect *exp) __read_mostly; |
@@ -205,7 +206,7 @@ static int help(struct sk_buff *skb, unsigned int protoff, | |||
205 | 206 | ||
206 | nf_nat_irc = rcu_dereference(nf_nat_irc_hook); | 207 | nf_nat_irc = rcu_dereference(nf_nat_irc_hook); |
207 | if (nf_nat_irc && ct->status & IPS_NAT_MASK) | 208 | if (nf_nat_irc && ct->status & IPS_NAT_MASK) |
208 | ret = nf_nat_irc(skb, ctinfo, | 209 | ret = nf_nat_irc(skb, ctinfo, protoff, |
209 | addr_beg_p - ib_ptr, | 210 | addr_beg_p - ib_ptr, |
210 | addr_end_p - addr_beg_p, | 211 | addr_end_p - addr_beg_p, |
211 | exp); | 212 | exp); |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 14f67a2cbcb5..a205bd6ce294 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -45,7 +45,7 @@ | |||
45 | #include <net/netfilter/nf_conntrack_timestamp.h> | 45 | #include <net/netfilter/nf_conntrack_timestamp.h> |
46 | #ifdef CONFIG_NF_NAT_NEEDED | 46 | #ifdef CONFIG_NF_NAT_NEEDED |
47 | #include <net/netfilter/nf_nat_core.h> | 47 | #include <net/netfilter/nf_nat_core.h> |
48 | #include <net/netfilter/nf_nat_protocol.h> | 48 | #include <net/netfilter/nf_nat_l4proto.h> |
49 | #include <net/netfilter/nf_nat_helper.h> | 49 | #include <net/netfilter/nf_nat_helper.h> |
50 | #endif | 50 | #endif |
51 | 51 | ||
@@ -1096,13 +1096,14 @@ ctnetlink_parse_nat_setup(struct nf_conn *ct, | |||
1096 | const struct nlattr *attr) | 1096 | const struct nlattr *attr) |
1097 | { | 1097 | { |
1098 | typeof(nfnetlink_parse_nat_setup_hook) parse_nat_setup; | 1098 | typeof(nfnetlink_parse_nat_setup_hook) parse_nat_setup; |
1099 | int err; | ||
1099 | 1100 | ||
1100 | parse_nat_setup = rcu_dereference(nfnetlink_parse_nat_setup_hook); | 1101 | parse_nat_setup = rcu_dereference(nfnetlink_parse_nat_setup_hook); |
1101 | if (!parse_nat_setup) { | 1102 | if (!parse_nat_setup) { |
1102 | #ifdef CONFIG_MODULES | 1103 | #ifdef CONFIG_MODULES |
1103 | rcu_read_unlock(); | 1104 | rcu_read_unlock(); |
1104 | nfnl_unlock(); | 1105 | nfnl_unlock(); |
1105 | if (request_module("nf-nat-ipv4") < 0) { | 1106 | if (request_module("nf-nat") < 0) { |
1106 | nfnl_lock(); | 1107 | nfnl_lock(); |
1107 | rcu_read_lock(); | 1108 | rcu_read_lock(); |
1108 | return -EOPNOTSUPP; | 1109 | return -EOPNOTSUPP; |
@@ -1115,7 +1116,26 @@ ctnetlink_parse_nat_setup(struct nf_conn *ct, | |||
1115 | return -EOPNOTSUPP; | 1116 | return -EOPNOTSUPP; |
1116 | } | 1117 | } |
1117 | 1118 | ||
1118 | return parse_nat_setup(ct, manip, attr); | 1119 | err = parse_nat_setup(ct, manip, attr); |
1120 | if (err == -EAGAIN) { | ||
1121 | #ifdef CONFIG_MODULES | ||
1122 | rcu_read_unlock(); | ||
1123 | spin_unlock_bh(&nf_conntrack_lock); | ||
1124 | nfnl_unlock(); | ||
1125 | if (request_module("nf-nat-%u", nf_ct_l3num(ct)) < 0) { | ||
1126 | nfnl_lock(); | ||
1127 | spin_lock_bh(&nf_conntrack_lock); | ||
1128 | rcu_read_lock(); | ||
1129 | return -EOPNOTSUPP; | ||
1130 | } | ||
1131 | nfnl_lock(); | ||
1132 | spin_lock_bh(&nf_conntrack_lock); | ||
1133 | rcu_read_lock(); | ||
1134 | #else | ||
1135 | err = -EOPNOTSUPP; | ||
1136 | #endif | ||
1137 | } | ||
1138 | return err; | ||
1119 | } | 1139 | } |
1120 | #endif | 1140 | #endif |
1121 | 1141 | ||
@@ -1896,10 +1916,15 @@ static int | |||
1896 | ctnetlink_nfqueue_parse(const struct nlattr *attr, struct nf_conn *ct) | 1916 | ctnetlink_nfqueue_parse(const struct nlattr *attr, struct nf_conn *ct) |
1897 | { | 1917 | { |
1898 | struct nlattr *cda[CTA_MAX+1]; | 1918 | struct nlattr *cda[CTA_MAX+1]; |
1919 | int ret; | ||
1899 | 1920 | ||
1900 | nla_parse_nested(cda, CTA_MAX, attr, ct_nla_policy); | 1921 | nla_parse_nested(cda, CTA_MAX, attr, ct_nla_policy); |
1901 | 1922 | ||
1902 | return ctnetlink_nfqueue_parse_ct((const struct nlattr **)cda, ct); | 1923 | spin_lock_bh(&nf_conntrack_lock); |
1924 | ret = ctnetlink_nfqueue_parse_ct((const struct nlattr **)cda, ct); | ||
1925 | spin_unlock_bh(&nf_conntrack_lock); | ||
1926 | |||
1927 | return ret; | ||
1903 | } | 1928 | } |
1904 | 1929 | ||
1905 | static struct nfq_ct_hook ctnetlink_nfqueue_hook = { | 1930 | static struct nfq_ct_hook ctnetlink_nfqueue_hook = { |
@@ -1974,6 +1999,8 @@ nla_put_failure: | |||
1974 | return -1; | 1999 | return -1; |
1975 | } | 2000 | } |
1976 | 2001 | ||
2002 | static const union nf_inet_addr any_addr; | ||
2003 | |||
1977 | static int | 2004 | static int |
1978 | ctnetlink_exp_dump_expect(struct sk_buff *skb, | 2005 | ctnetlink_exp_dump_expect(struct sk_buff *skb, |
1979 | const struct nf_conntrack_expect *exp) | 2006 | const struct nf_conntrack_expect *exp) |
@@ -2000,7 +2027,8 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb, | |||
2000 | goto nla_put_failure; | 2027 | goto nla_put_failure; |
2001 | 2028 | ||
2002 | #ifdef CONFIG_NF_NAT_NEEDED | 2029 | #ifdef CONFIG_NF_NAT_NEEDED |
2003 | if (exp->saved_ip || exp->saved_proto.all) { | 2030 | if (!nf_inet_addr_cmp(&exp->saved_addr, &any_addr) || |
2031 | exp->saved_proto.all) { | ||
2004 | nest_parms = nla_nest_start(skb, CTA_EXPECT_NAT | NLA_F_NESTED); | 2032 | nest_parms = nla_nest_start(skb, CTA_EXPECT_NAT | NLA_F_NESTED); |
2005 | if (!nest_parms) | 2033 | if (!nest_parms) |
2006 | goto nla_put_failure; | 2034 | goto nla_put_failure; |
@@ -2009,7 +2037,7 @@ ctnetlink_exp_dump_expect(struct sk_buff *skb, | |||
2009 | goto nla_put_failure; | 2037 | goto nla_put_failure; |
2010 | 2038 | ||
2011 | nat_tuple.src.l3num = nf_ct_l3num(master); | 2039 | nat_tuple.src.l3num = nf_ct_l3num(master); |
2012 | nat_tuple.src.u3.ip = exp->saved_ip; | 2040 | nat_tuple.src.u3 = exp->saved_addr; |
2013 | nat_tuple.dst.protonum = nf_ct_protonum(master); | 2041 | nat_tuple.dst.protonum = nf_ct_protonum(master); |
2014 | nat_tuple.src.u = exp->saved_proto; | 2042 | nat_tuple.src.u = exp->saved_proto; |
2015 | 2043 | ||
@@ -2405,7 +2433,7 @@ ctnetlink_parse_expect_nat(const struct nlattr *attr, | |||
2405 | if (err < 0) | 2433 | if (err < 0) |
2406 | return err; | 2434 | return err; |
2407 | 2435 | ||
2408 | exp->saved_ip = nat_tuple.src.u3.ip; | 2436 | exp->saved_addr = nat_tuple.src.u3; |
2409 | exp->saved_proto = nat_tuple.src.u; | 2437 | exp->saved_proto = nat_tuple.src.u; |
2410 | exp->dir = ntohl(nla_get_be32(tb[CTA_EXPECT_NAT_DIR])); | 2438 | exp->dir = ntohl(nla_get_be32(tb[CTA_EXPECT_NAT_DIR])); |
2411 | 2439 | ||
@@ -2785,7 +2813,8 @@ static int __init ctnetlink_init(void) | |||
2785 | goto err_unreg_subsys; | 2813 | goto err_unreg_subsys; |
2786 | } | 2814 | } |
2787 | 2815 | ||
2788 | if (register_pernet_subsys(&ctnetlink_net_ops)) { | 2816 | ret = register_pernet_subsys(&ctnetlink_net_ops); |
2817 | if (ret < 0) { | ||
2789 | pr_err("ctnetlink_init: cannot register pernet operations\n"); | 2818 | pr_err("ctnetlink_init: cannot register pernet operations\n"); |
2790 | goto err_unreg_exp_subsys; | 2819 | goto err_unreg_exp_subsys; |
2791 | } | 2820 | } |
diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c index 6fed9ec35248..cc7669ef0b95 100644 --- a/net/netfilter/nf_conntrack_pptp.c +++ b/net/netfilter/nf_conntrack_pptp.c | |||
@@ -45,14 +45,14 @@ static DEFINE_SPINLOCK(nf_pptp_lock); | |||
45 | int | 45 | int |
46 | (*nf_nat_pptp_hook_outbound)(struct sk_buff *skb, | 46 | (*nf_nat_pptp_hook_outbound)(struct sk_buff *skb, |
47 | struct nf_conn *ct, enum ip_conntrack_info ctinfo, | 47 | struct nf_conn *ct, enum ip_conntrack_info ctinfo, |
48 | struct PptpControlHeader *ctlh, | 48 | unsigned int protoff, struct PptpControlHeader *ctlh, |
49 | union pptp_ctrl_union *pptpReq) __read_mostly; | 49 | union pptp_ctrl_union *pptpReq) __read_mostly; |
50 | EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_outbound); | 50 | EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_outbound); |
51 | 51 | ||
52 | int | 52 | int |
53 | (*nf_nat_pptp_hook_inbound)(struct sk_buff *skb, | 53 | (*nf_nat_pptp_hook_inbound)(struct sk_buff *skb, |
54 | struct nf_conn *ct, enum ip_conntrack_info ctinfo, | 54 | struct nf_conn *ct, enum ip_conntrack_info ctinfo, |
55 | struct PptpControlHeader *ctlh, | 55 | unsigned int protoff, struct PptpControlHeader *ctlh, |
56 | union pptp_ctrl_union *pptpReq) __read_mostly; | 56 | union pptp_ctrl_union *pptpReq) __read_mostly; |
57 | EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_inbound); | 57 | EXPORT_SYMBOL_GPL(nf_nat_pptp_hook_inbound); |
58 | 58 | ||
@@ -262,7 +262,7 @@ out_unexpect_orig: | |||
262 | } | 262 | } |
263 | 263 | ||
264 | static inline int | 264 | static inline int |
265 | pptp_inbound_pkt(struct sk_buff *skb, | 265 | pptp_inbound_pkt(struct sk_buff *skb, unsigned int protoff, |
266 | struct PptpControlHeader *ctlh, | 266 | struct PptpControlHeader *ctlh, |
267 | union pptp_ctrl_union *pptpReq, | 267 | union pptp_ctrl_union *pptpReq, |
268 | unsigned int reqlen, | 268 | unsigned int reqlen, |
@@ -376,7 +376,8 @@ pptp_inbound_pkt(struct sk_buff *skb, | |||
376 | 376 | ||
377 | nf_nat_pptp_inbound = rcu_dereference(nf_nat_pptp_hook_inbound); | 377 | nf_nat_pptp_inbound = rcu_dereference(nf_nat_pptp_hook_inbound); |
378 | if (nf_nat_pptp_inbound && ct->status & IPS_NAT_MASK) | 378 | if (nf_nat_pptp_inbound && ct->status & IPS_NAT_MASK) |
379 | return nf_nat_pptp_inbound(skb, ct, ctinfo, ctlh, pptpReq); | 379 | return nf_nat_pptp_inbound(skb, ct, ctinfo, |
380 | protoff, ctlh, pptpReq); | ||
380 | return NF_ACCEPT; | 381 | return NF_ACCEPT; |
381 | 382 | ||
382 | invalid: | 383 | invalid: |
@@ -389,7 +390,7 @@ invalid: | |||
389 | } | 390 | } |
390 | 391 | ||
391 | static inline int | 392 | static inline int |
392 | pptp_outbound_pkt(struct sk_buff *skb, | 393 | pptp_outbound_pkt(struct sk_buff *skb, unsigned int protoff, |
393 | struct PptpControlHeader *ctlh, | 394 | struct PptpControlHeader *ctlh, |
394 | union pptp_ctrl_union *pptpReq, | 395 | union pptp_ctrl_union *pptpReq, |
395 | unsigned int reqlen, | 396 | unsigned int reqlen, |
@@ -471,7 +472,8 @@ pptp_outbound_pkt(struct sk_buff *skb, | |||
471 | 472 | ||
472 | nf_nat_pptp_outbound = rcu_dereference(nf_nat_pptp_hook_outbound); | 473 | nf_nat_pptp_outbound = rcu_dereference(nf_nat_pptp_hook_outbound); |
473 | if (nf_nat_pptp_outbound && ct->status & IPS_NAT_MASK) | 474 | if (nf_nat_pptp_outbound && ct->status & IPS_NAT_MASK) |
474 | return nf_nat_pptp_outbound(skb, ct, ctinfo, ctlh, pptpReq); | 475 | return nf_nat_pptp_outbound(skb, ct, ctinfo, |
476 | protoff, ctlh, pptpReq); | ||
475 | return NF_ACCEPT; | 477 | return NF_ACCEPT; |
476 | 478 | ||
477 | invalid: | 479 | invalid: |
@@ -570,11 +572,11 @@ conntrack_pptp_help(struct sk_buff *skb, unsigned int protoff, | |||
570 | * established from PNS->PAC. However, RFC makes no guarantee */ | 572 | * established from PNS->PAC. However, RFC makes no guarantee */ |
571 | if (dir == IP_CT_DIR_ORIGINAL) | 573 | if (dir == IP_CT_DIR_ORIGINAL) |
572 | /* client -> server (PNS -> PAC) */ | 574 | /* client -> server (PNS -> PAC) */ |
573 | ret = pptp_outbound_pkt(skb, ctlh, pptpReq, reqlen, ct, | 575 | ret = pptp_outbound_pkt(skb, protoff, ctlh, pptpReq, reqlen, ct, |
574 | ctinfo); | 576 | ctinfo); |
575 | else | 577 | else |
576 | /* server -> client (PAC -> PNS) */ | 578 | /* server -> client (PAC -> PNS) */ |
577 | ret = pptp_inbound_pkt(skb, ctlh, pptpReq, reqlen, ct, | 579 | ret = pptp_inbound_pkt(skb, protoff, ctlh, pptpReq, reqlen, ct, |
578 | ctinfo); | 580 | ctinfo); |
579 | pr_debug("sstate: %d->%d, cstate: %d->%d\n", | 581 | pr_debug("sstate: %d->%d, cstate: %d->%d\n", |
580 | oldsstate, info->sstate, oldcstate, info->cstate); | 582 | oldsstate, info->sstate, oldcstate, info->cstate); |
diff --git a/net/netfilter/nf_conntrack_proto.c b/net/netfilter/nf_conntrack_proto.c index 0dc63854390f..51e928db48c8 100644 --- a/net/netfilter/nf_conntrack_proto.c +++ b/net/netfilter/nf_conntrack_proto.c | |||
@@ -21,7 +21,6 @@ | |||
21 | #include <linux/notifier.h> | 21 | #include <linux/notifier.h> |
22 | #include <linux/kernel.h> | 22 | #include <linux/kernel.h> |
23 | #include <linux/netdevice.h> | 23 | #include <linux/netdevice.h> |
24 | #include <linux/rtnetlink.h> | ||
25 | 24 | ||
26 | #include <net/netfilter/nf_conntrack.h> | 25 | #include <net/netfilter/nf_conntrack.h> |
27 | #include <net/netfilter/nf_conntrack_l3proto.h> | 26 | #include <net/netfilter/nf_conntrack_l3proto.h> |
@@ -294,9 +293,7 @@ void nf_conntrack_l3proto_unregister(struct net *net, | |||
294 | nf_ct_l3proto_unregister_sysctl(net, proto); | 293 | nf_ct_l3proto_unregister_sysctl(net, proto); |
295 | 294 | ||
296 | /* Remove all contrack entries for this protocol */ | 295 | /* Remove all contrack entries for this protocol */ |
297 | rtnl_lock(); | ||
298 | nf_ct_iterate_cleanup(net, kill_l3proto, proto); | 296 | nf_ct_iterate_cleanup(net, kill_l3proto, proto); |
299 | rtnl_unlock(); | ||
300 | } | 297 | } |
301 | EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_unregister); | 298 | EXPORT_SYMBOL_GPL(nf_conntrack_l3proto_unregister); |
302 | 299 | ||
@@ -502,9 +499,7 @@ void nf_conntrack_l4proto_unregister(struct net *net, | |||
502 | nf_ct_l4proto_unregister_sysctl(net, pn, l4proto); | 499 | nf_ct_l4proto_unregister_sysctl(net, pn, l4proto); |
503 | 500 | ||
504 | /* Remove all contrack entries for this protocol */ | 501 | /* Remove all contrack entries for this protocol */ |
505 | rtnl_lock(); | ||
506 | nf_ct_iterate_cleanup(net, kill_l4proto, l4proto); | 502 | nf_ct_iterate_cleanup(net, kill_l4proto, l4proto); |
507 | rtnl_unlock(); | ||
508 | } | 503 | } |
509 | EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_unregister); | 504 | EXPORT_SYMBOL_GPL(nf_conntrack_l4proto_unregister); |
510 | 505 | ||
diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c index a5ac11ebef33..9c2cc716f4a5 100644 --- a/net/netfilter/nf_conntrack_proto_tcp.c +++ b/net/netfilter/nf_conntrack_proto_tcp.c | |||
@@ -505,10 +505,10 @@ static inline s16 nat_offset(const struct nf_conn *ct, | |||
505 | 505 | ||
506 | return get_offset != NULL ? get_offset(ct, dir, seq) : 0; | 506 | return get_offset != NULL ? get_offset(ct, dir, seq) : 0; |
507 | } | 507 | } |
508 | #define NAT_OFFSET(pf, ct, dir, seq) \ | 508 | #define NAT_OFFSET(ct, dir, seq) \ |
509 | (pf == NFPROTO_IPV4 ? nat_offset(ct, dir, seq) : 0) | 509 | (nat_offset(ct, dir, seq)) |
510 | #else | 510 | #else |
511 | #define NAT_OFFSET(pf, ct, dir, seq) 0 | 511 | #define NAT_OFFSET(ct, dir, seq) 0 |
512 | #endif | 512 | #endif |
513 | 513 | ||
514 | static bool tcp_in_window(const struct nf_conn *ct, | 514 | static bool tcp_in_window(const struct nf_conn *ct, |
@@ -541,7 +541,7 @@ static bool tcp_in_window(const struct nf_conn *ct, | |||
541 | tcp_sack(skb, dataoff, tcph, &sack); | 541 | tcp_sack(skb, dataoff, tcph, &sack); |
542 | 542 | ||
543 | /* Take into account NAT sequence number mangling */ | 543 | /* Take into account NAT sequence number mangling */ |
544 | receiver_offset = NAT_OFFSET(pf, ct, !dir, ack - 1); | 544 | receiver_offset = NAT_OFFSET(ct, !dir, ack - 1); |
545 | ack -= receiver_offset; | 545 | ack -= receiver_offset; |
546 | sack -= receiver_offset; | 546 | sack -= receiver_offset; |
547 | 547 | ||
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 758a1bacc126..df8f4f284481 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c | |||
@@ -52,15 +52,17 @@ module_param(sip_direct_media, int, 0600); | |||
52 | MODULE_PARM_DESC(sip_direct_media, "Expect Media streams between signalling " | 52 | MODULE_PARM_DESC(sip_direct_media, "Expect Media streams between signalling " |
53 | "endpoints only (default 1)"); | 53 | "endpoints only (default 1)"); |
54 | 54 | ||
55 | unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb, unsigned int dataoff, | 55 | unsigned int (*nf_nat_sip_hook)(struct sk_buff *skb, unsigned int protoff, |
56 | const char **dptr, | 56 | unsigned int dataoff, const char **dptr, |
57 | unsigned int *datalen) __read_mostly; | 57 | unsigned int *datalen) __read_mostly; |
58 | EXPORT_SYMBOL_GPL(nf_nat_sip_hook); | 58 | EXPORT_SYMBOL_GPL(nf_nat_sip_hook); |
59 | 59 | ||
60 | void (*nf_nat_sip_seq_adjust_hook)(struct sk_buff *skb, s16 off) __read_mostly; | 60 | void (*nf_nat_sip_seq_adjust_hook)(struct sk_buff *skb, unsigned int protoff, |
61 | s16 off) __read_mostly; | ||
61 | EXPORT_SYMBOL_GPL(nf_nat_sip_seq_adjust_hook); | 62 | EXPORT_SYMBOL_GPL(nf_nat_sip_seq_adjust_hook); |
62 | 63 | ||
63 | unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb, | 64 | unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb, |
65 | unsigned int protoff, | ||
64 | unsigned int dataoff, | 66 | unsigned int dataoff, |
65 | const char **dptr, | 67 | const char **dptr, |
66 | unsigned int *datalen, | 68 | unsigned int *datalen, |
@@ -69,7 +71,8 @@ unsigned int (*nf_nat_sip_expect_hook)(struct sk_buff *skb, | |||
69 | unsigned int matchlen) __read_mostly; | 71 | unsigned int matchlen) __read_mostly; |
70 | EXPORT_SYMBOL_GPL(nf_nat_sip_expect_hook); | 72 | EXPORT_SYMBOL_GPL(nf_nat_sip_expect_hook); |
71 | 73 | ||
72 | unsigned int (*nf_nat_sdp_addr_hook)(struct sk_buff *skb, unsigned int dataoff, | 74 | unsigned int (*nf_nat_sdp_addr_hook)(struct sk_buff *skb, unsigned int protoff, |
75 | unsigned int dataoff, | ||
73 | const char **dptr, | 76 | const char **dptr, |
74 | unsigned int *datalen, | 77 | unsigned int *datalen, |
75 | unsigned int sdpoff, | 78 | unsigned int sdpoff, |
@@ -79,7 +82,8 @@ unsigned int (*nf_nat_sdp_addr_hook)(struct sk_buff *skb, unsigned int dataoff, | |||
79 | __read_mostly; | 82 | __read_mostly; |
80 | EXPORT_SYMBOL_GPL(nf_nat_sdp_addr_hook); | 83 | EXPORT_SYMBOL_GPL(nf_nat_sdp_addr_hook); |
81 | 84 | ||
82 | unsigned int (*nf_nat_sdp_port_hook)(struct sk_buff *skb, unsigned int dataoff, | 85 | unsigned int (*nf_nat_sdp_port_hook)(struct sk_buff *skb, unsigned int protoff, |
86 | unsigned int dataoff, | ||
83 | const char **dptr, | 87 | const char **dptr, |
84 | unsigned int *datalen, | 88 | unsigned int *datalen, |
85 | unsigned int matchoff, | 89 | unsigned int matchoff, |
@@ -88,6 +92,7 @@ unsigned int (*nf_nat_sdp_port_hook)(struct sk_buff *skb, unsigned int dataoff, | |||
88 | EXPORT_SYMBOL_GPL(nf_nat_sdp_port_hook); | 92 | EXPORT_SYMBOL_GPL(nf_nat_sdp_port_hook); |
89 | 93 | ||
90 | unsigned int (*nf_nat_sdp_session_hook)(struct sk_buff *skb, | 94 | unsigned int (*nf_nat_sdp_session_hook)(struct sk_buff *skb, |
95 | unsigned int protoff, | ||
91 | unsigned int dataoff, | 96 | unsigned int dataoff, |
92 | const char **dptr, | 97 | const char **dptr, |
93 | unsigned int *datalen, | 98 | unsigned int *datalen, |
@@ -96,7 +101,8 @@ unsigned int (*nf_nat_sdp_session_hook)(struct sk_buff *skb, | |||
96 | __read_mostly; | 101 | __read_mostly; |
97 | EXPORT_SYMBOL_GPL(nf_nat_sdp_session_hook); | 102 | EXPORT_SYMBOL_GPL(nf_nat_sdp_session_hook); |
98 | 103 | ||
99 | unsigned int (*nf_nat_sdp_media_hook)(struct sk_buff *skb, unsigned int dataoff, | 104 | unsigned int (*nf_nat_sdp_media_hook)(struct sk_buff *skb, unsigned int protoff, |
105 | unsigned int dataoff, | ||
100 | const char **dptr, | 106 | const char **dptr, |
101 | unsigned int *datalen, | 107 | unsigned int *datalen, |
102 | struct nf_conntrack_expect *rtp_exp, | 108 | struct nf_conntrack_expect *rtp_exp, |
@@ -183,12 +189,12 @@ static int media_len(const struct nf_conn *ct, const char *dptr, | |||
183 | return len + digits_len(ct, dptr, limit, shift); | 189 | return len + digits_len(ct, dptr, limit, shift); |
184 | } | 190 | } |
185 | 191 | ||
186 | static int parse_addr(const struct nf_conn *ct, const char *cp, | 192 | static int sip_parse_addr(const struct nf_conn *ct, const char *cp, |
187 | const char **endp, union nf_inet_addr *addr, | 193 | const char **endp, union nf_inet_addr *addr, |
188 | const char *limit) | 194 | const char *limit, bool delim) |
189 | { | 195 | { |
190 | const char *end; | 196 | const char *end; |
191 | int ret = 0; | 197 | int ret; |
192 | 198 | ||
193 | if (!ct) | 199 | if (!ct) |
194 | return 0; | 200 | return 0; |
@@ -197,16 +203,28 @@ static int parse_addr(const struct nf_conn *ct, const char *cp, | |||
197 | switch (nf_ct_l3num(ct)) { | 203 | switch (nf_ct_l3num(ct)) { |
198 | case AF_INET: | 204 | case AF_INET: |
199 | ret = in4_pton(cp, limit - cp, (u8 *)&addr->ip, -1, &end); | 205 | ret = in4_pton(cp, limit - cp, (u8 *)&addr->ip, -1, &end); |
206 | if (ret == 0) | ||
207 | return 0; | ||
200 | break; | 208 | break; |
201 | case AF_INET6: | 209 | case AF_INET6: |
210 | if (cp < limit && *cp == '[') | ||
211 | cp++; | ||
212 | else if (delim) | ||
213 | return 0; | ||
214 | |||
202 | ret = in6_pton(cp, limit - cp, (u8 *)&addr->ip6, -1, &end); | 215 | ret = in6_pton(cp, limit - cp, (u8 *)&addr->ip6, -1, &end); |
216 | if (ret == 0) | ||
217 | return 0; | ||
218 | |||
219 | if (end < limit && *end == ']') | ||
220 | end++; | ||
221 | else if (delim) | ||
222 | return 0; | ||
203 | break; | 223 | break; |
204 | default: | 224 | default: |
205 | BUG(); | 225 | BUG(); |
206 | } | 226 | } |
207 | 227 | ||
208 | if (ret == 0 || end == cp) | ||
209 | return 0; | ||
210 | if (endp) | 228 | if (endp) |
211 | *endp = end; | 229 | *endp = end; |
212 | return 1; | 230 | return 1; |
@@ -219,7 +237,7 @@ static int epaddr_len(const struct nf_conn *ct, const char *dptr, | |||
219 | union nf_inet_addr addr; | 237 | union nf_inet_addr addr; |
220 | const char *aux = dptr; | 238 | const char *aux = dptr; |
221 | 239 | ||
222 | if (!parse_addr(ct, dptr, &dptr, &addr, limit)) { | 240 | if (!sip_parse_addr(ct, dptr, &dptr, &addr, limit, true)) { |
223 | pr_debug("ip: %s parse failed.!\n", dptr); | 241 | pr_debug("ip: %s parse failed.!\n", dptr); |
224 | return 0; | 242 | return 0; |
225 | } | 243 | } |
@@ -296,7 +314,7 @@ int ct_sip_parse_request(const struct nf_conn *ct, | |||
296 | return 0; | 314 | return 0; |
297 | dptr += shift; | 315 | dptr += shift; |
298 | 316 | ||
299 | if (!parse_addr(ct, dptr, &end, addr, limit)) | 317 | if (!sip_parse_addr(ct, dptr, &end, addr, limit, true)) |
300 | return -1; | 318 | return -1; |
301 | if (end < limit && *end == ':') { | 319 | if (end < limit && *end == ':') { |
302 | end++; | 320 | end++; |
@@ -550,7 +568,7 @@ int ct_sip_parse_header_uri(const struct nf_conn *ct, const char *dptr, | |||
550 | if (ret == 0) | 568 | if (ret == 0) |
551 | return ret; | 569 | return ret; |
552 | 570 | ||
553 | if (!parse_addr(ct, dptr + *matchoff, &c, addr, limit)) | 571 | if (!sip_parse_addr(ct, dptr + *matchoff, &c, addr, limit, true)) |
554 | return -1; | 572 | return -1; |
555 | if (*c == ':') { | 573 | if (*c == ':') { |
556 | c++; | 574 | c++; |
@@ -599,7 +617,7 @@ int ct_sip_parse_address_param(const struct nf_conn *ct, const char *dptr, | |||
599 | unsigned int dataoff, unsigned int datalen, | 617 | unsigned int dataoff, unsigned int datalen, |
600 | const char *name, | 618 | const char *name, |
601 | unsigned int *matchoff, unsigned int *matchlen, | 619 | unsigned int *matchoff, unsigned int *matchlen, |
602 | union nf_inet_addr *addr) | 620 | union nf_inet_addr *addr, bool delim) |
603 | { | 621 | { |
604 | const char *limit = dptr + datalen; | 622 | const char *limit = dptr + datalen; |
605 | const char *start, *end; | 623 | const char *start, *end; |
@@ -613,7 +631,7 @@ int ct_sip_parse_address_param(const struct nf_conn *ct, const char *dptr, | |||
613 | return 0; | 631 | return 0; |
614 | 632 | ||
615 | start += strlen(name); | 633 | start += strlen(name); |
616 | if (!parse_addr(ct, start, &end, addr, limit)) | 634 | if (!sip_parse_addr(ct, start, &end, addr, limit, delim)) |
617 | return 0; | 635 | return 0; |
618 | *matchoff = start - dptr; | 636 | *matchoff = start - dptr; |
619 | *matchlen = end - start; | 637 | *matchlen = end - start; |
@@ -675,6 +693,47 @@ static int ct_sip_parse_transport(struct nf_conn *ct, const char *dptr, | |||
675 | return 1; | 693 | return 1; |
676 | } | 694 | } |
677 | 695 | ||
696 | static int sdp_parse_addr(const struct nf_conn *ct, const char *cp, | ||
697 | const char **endp, union nf_inet_addr *addr, | ||
698 | const char *limit) | ||
699 | { | ||
700 | const char *end; | ||
701 | int ret; | ||
702 | |||
703 | memset(addr, 0, sizeof(*addr)); | ||
704 | switch (nf_ct_l3num(ct)) { | ||
705 | case AF_INET: | ||
706 | ret = in4_pton(cp, limit - cp, (u8 *)&addr->ip, -1, &end); | ||
707 | break; | ||
708 | case AF_INET6: | ||
709 | ret = in6_pton(cp, limit - cp, (u8 *)&addr->ip6, -1, &end); | ||
710 | break; | ||
711 | default: | ||
712 | BUG(); | ||
713 | } | ||
714 | |||
715 | if (ret == 0) | ||
716 | return 0; | ||
717 | if (endp) | ||
718 | *endp = end; | ||
719 | return 1; | ||
720 | } | ||
721 | |||
722 | /* skip ip address. returns its length. */ | ||
723 | static int sdp_addr_len(const struct nf_conn *ct, const char *dptr, | ||
724 | const char *limit, int *shift) | ||
725 | { | ||
726 | union nf_inet_addr addr; | ||
727 | const char *aux = dptr; | ||
728 | |||
729 | if (!sdp_parse_addr(ct, dptr, &dptr, &addr, limit)) { | ||
730 | pr_debug("ip: %s parse failed.!\n", dptr); | ||
731 | return 0; | ||
732 | } | ||
733 | |||
734 | return dptr - aux; | ||
735 | } | ||
736 | |||
678 | /* SDP header parsing: a SDP session description contains an ordered set of | 737 | /* SDP header parsing: a SDP session description contains an ordered set of |
679 | * headers, starting with a section containing general session parameters, | 738 | * headers, starting with a section containing general session parameters, |
680 | * optionally followed by multiple media descriptions. | 739 | * optionally followed by multiple media descriptions. |
@@ -684,13 +743,18 @@ static int ct_sip_parse_transport(struct nf_conn *ct, const char *dptr, | |||
684 | * be tolerant and also accept records terminated with a single newline | 743 | * be tolerant and also accept records terminated with a single newline |
685 | * character". We handle both cases. | 744 | * character". We handle both cases. |
686 | */ | 745 | */ |
687 | static const struct sip_header ct_sdp_hdrs[] = { | 746 | static const struct sip_header ct_sdp_hdrs_v4[] = { |
688 | [SDP_HDR_VERSION] = SDP_HDR("v=", NULL, digits_len), | 747 | [SDP_HDR_VERSION] = SDP_HDR("v=", NULL, digits_len), |
689 | [SDP_HDR_OWNER_IP4] = SDP_HDR("o=", "IN IP4 ", epaddr_len), | 748 | [SDP_HDR_OWNER] = SDP_HDR("o=", "IN IP4 ", sdp_addr_len), |
690 | [SDP_HDR_CONNECTION_IP4] = SDP_HDR("c=", "IN IP4 ", epaddr_len), | 749 | [SDP_HDR_CONNECTION] = SDP_HDR("c=", "IN IP4 ", sdp_addr_len), |
691 | [SDP_HDR_OWNER_IP6] = SDP_HDR("o=", "IN IP6 ", epaddr_len), | 750 | [SDP_HDR_MEDIA] = SDP_HDR("m=", NULL, media_len), |
692 | [SDP_HDR_CONNECTION_IP6] = SDP_HDR("c=", "IN IP6 ", epaddr_len), | 751 | }; |
693 | [SDP_HDR_MEDIA] = SDP_HDR("m=", NULL, media_len), | 752 | |
753 | static const struct sip_header ct_sdp_hdrs_v6[] = { | ||
754 | [SDP_HDR_VERSION] = SDP_HDR("v=", NULL, digits_len), | ||
755 | [SDP_HDR_OWNER] = SDP_HDR("o=", "IN IP6 ", sdp_addr_len), | ||
756 | [SDP_HDR_CONNECTION] = SDP_HDR("c=", "IN IP6 ", sdp_addr_len), | ||
757 | [SDP_HDR_MEDIA] = SDP_HDR("m=", NULL, media_len), | ||
694 | }; | 758 | }; |
695 | 759 | ||
696 | /* Linear string search within SDP header values */ | 760 | /* Linear string search within SDP header values */ |
@@ -716,11 +780,14 @@ int ct_sip_get_sdp_header(const struct nf_conn *ct, const char *dptr, | |||
716 | enum sdp_header_types term, | 780 | enum sdp_header_types term, |
717 | unsigned int *matchoff, unsigned int *matchlen) | 781 | unsigned int *matchoff, unsigned int *matchlen) |
718 | { | 782 | { |
719 | const struct sip_header *hdr = &ct_sdp_hdrs[type]; | 783 | const struct sip_header *hdrs, *hdr, *thdr; |
720 | const struct sip_header *thdr = &ct_sdp_hdrs[term]; | ||
721 | const char *start = dptr, *limit = dptr + datalen; | 784 | const char *start = dptr, *limit = dptr + datalen; |
722 | int shift = 0; | 785 | int shift = 0; |
723 | 786 | ||
787 | hdrs = nf_ct_l3num(ct) == NFPROTO_IPV4 ? ct_sdp_hdrs_v4 : ct_sdp_hdrs_v6; | ||
788 | hdr = &hdrs[type]; | ||
789 | thdr = &hdrs[term]; | ||
790 | |||
724 | for (dptr += dataoff; dptr < limit; dptr++) { | 791 | for (dptr += dataoff; dptr < limit; dptr++) { |
725 | /* Find beginning of line */ | 792 | /* Find beginning of line */ |
726 | if (*dptr != '\r' && *dptr != '\n') | 793 | if (*dptr != '\r' && *dptr != '\n') |
@@ -775,8 +842,8 @@ static int ct_sip_parse_sdp_addr(const struct nf_conn *ct, const char *dptr, | |||
775 | if (ret <= 0) | 842 | if (ret <= 0) |
776 | return ret; | 843 | return ret; |
777 | 844 | ||
778 | if (!parse_addr(ct, dptr + *matchoff, NULL, addr, | 845 | if (!sdp_parse_addr(ct, dptr + *matchoff, NULL, addr, |
779 | dptr + *matchoff + *matchlen)) | 846 | dptr + *matchoff + *matchlen)) |
780 | return -1; | 847 | return -1; |
781 | return 1; | 848 | return 1; |
782 | } | 849 | } |
@@ -830,7 +897,8 @@ static void flush_expectations(struct nf_conn *ct, bool media) | |||
830 | spin_unlock_bh(&nf_conntrack_lock); | 897 | spin_unlock_bh(&nf_conntrack_lock); |
831 | } | 898 | } |
832 | 899 | ||
833 | static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int dataoff, | 900 | static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int protoff, |
901 | unsigned int dataoff, | ||
834 | const char **dptr, unsigned int *datalen, | 902 | const char **dptr, unsigned int *datalen, |
835 | union nf_inet_addr *daddr, __be16 port, | 903 | union nf_inet_addr *daddr, __be16 port, |
836 | enum sip_expectation_classes class, | 904 | enum sip_expectation_classes class, |
@@ -886,12 +954,12 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int dataoff, | |||
886 | exp->class != class) | 954 | exp->class != class) |
887 | break; | 955 | break; |
888 | #ifdef CONFIG_NF_NAT_NEEDED | 956 | #ifdef CONFIG_NF_NAT_NEEDED |
889 | if (exp->tuple.src.l3num == AF_INET && !direct_rtp && | 957 | if (!direct_rtp && |
890 | (exp->saved_ip != exp->tuple.dst.u3.ip || | 958 | (!nf_inet_addr_cmp(&exp->saved_addr, &exp->tuple.dst.u3) || |
891 | exp->saved_proto.udp.port != exp->tuple.dst.u.udp.port) && | 959 | exp->saved_proto.udp.port != exp->tuple.dst.u.udp.port) && |
892 | ct->status & IPS_NAT_MASK) { | 960 | ct->status & IPS_NAT_MASK) { |
893 | daddr->ip = exp->saved_ip; | 961 | *daddr = exp->saved_addr; |
894 | tuple.dst.u3.ip = exp->saved_ip; | 962 | tuple.dst.u3 = exp->saved_addr; |
895 | tuple.dst.u.udp.port = exp->saved_proto.udp.port; | 963 | tuple.dst.u.udp.port = exp->saved_proto.udp.port; |
896 | direct_rtp = 1; | 964 | direct_rtp = 1; |
897 | } else | 965 | } else |
@@ -907,7 +975,7 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int dataoff, | |||
907 | if (direct_rtp) { | 975 | if (direct_rtp) { |
908 | nf_nat_sdp_port = rcu_dereference(nf_nat_sdp_port_hook); | 976 | nf_nat_sdp_port = rcu_dereference(nf_nat_sdp_port_hook); |
909 | if (nf_nat_sdp_port && | 977 | if (nf_nat_sdp_port && |
910 | !nf_nat_sdp_port(skb, dataoff, dptr, datalen, | 978 | !nf_nat_sdp_port(skb, protoff, dataoff, dptr, datalen, |
911 | mediaoff, medialen, ntohs(rtp_port))) | 979 | mediaoff, medialen, ntohs(rtp_port))) |
912 | goto err1; | 980 | goto err1; |
913 | } | 981 | } |
@@ -929,7 +997,7 @@ static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int dataoff, | |||
929 | 997 | ||
930 | nf_nat_sdp_media = rcu_dereference(nf_nat_sdp_media_hook); | 998 | nf_nat_sdp_media = rcu_dereference(nf_nat_sdp_media_hook); |
931 | if (nf_nat_sdp_media && ct->status & IPS_NAT_MASK && !direct_rtp) | 999 | if (nf_nat_sdp_media && ct->status & IPS_NAT_MASK && !direct_rtp) |
932 | ret = nf_nat_sdp_media(skb, dataoff, dptr, datalen, | 1000 | ret = nf_nat_sdp_media(skb, protoff, dataoff, dptr, datalen, |
933 | rtp_exp, rtcp_exp, | 1001 | rtp_exp, rtcp_exp, |
934 | mediaoff, medialen, daddr); | 1002 | mediaoff, medialen, daddr); |
935 | else { | 1003 | else { |
@@ -970,7 +1038,8 @@ static const struct sdp_media_type *sdp_media_type(const char *dptr, | |||
970 | return NULL; | 1038 | return NULL; |
971 | } | 1039 | } |
972 | 1040 | ||
973 | static int process_sdp(struct sk_buff *skb, unsigned int dataoff, | 1041 | static int process_sdp(struct sk_buff *skb, unsigned int protoff, |
1042 | unsigned int dataoff, | ||
974 | const char **dptr, unsigned int *datalen, | 1043 | const char **dptr, unsigned int *datalen, |
975 | unsigned int cseq) | 1044 | unsigned int cseq) |
976 | { | 1045 | { |
@@ -983,15 +1052,12 @@ static int process_sdp(struct sk_buff *skb, unsigned int dataoff, | |||
983 | unsigned int i; | 1052 | unsigned int i; |
984 | union nf_inet_addr caddr, maddr, rtp_addr; | 1053 | union nf_inet_addr caddr, maddr, rtp_addr; |
985 | unsigned int port; | 1054 | unsigned int port; |
986 | enum sdp_header_types c_hdr; | ||
987 | const struct sdp_media_type *t; | 1055 | const struct sdp_media_type *t; |
988 | int ret = NF_ACCEPT; | 1056 | int ret = NF_ACCEPT; |
989 | typeof(nf_nat_sdp_addr_hook) nf_nat_sdp_addr; | 1057 | typeof(nf_nat_sdp_addr_hook) nf_nat_sdp_addr; |
990 | typeof(nf_nat_sdp_session_hook) nf_nat_sdp_session; | 1058 | typeof(nf_nat_sdp_session_hook) nf_nat_sdp_session; |
991 | 1059 | ||
992 | nf_nat_sdp_addr = rcu_dereference(nf_nat_sdp_addr_hook); | 1060 | nf_nat_sdp_addr = rcu_dereference(nf_nat_sdp_addr_hook); |
993 | c_hdr = nf_ct_l3num(ct) == AF_INET ? SDP_HDR_CONNECTION_IP4 : | ||
994 | SDP_HDR_CONNECTION_IP6; | ||
995 | 1061 | ||
996 | /* Find beginning of session description */ | 1062 | /* Find beginning of session description */ |
997 | if (ct_sip_get_sdp_header(ct, *dptr, 0, *datalen, | 1063 | if (ct_sip_get_sdp_header(ct, *dptr, 0, *datalen, |
@@ -1005,7 +1071,7 @@ static int process_sdp(struct sk_buff *skb, unsigned int dataoff, | |||
1005 | * the end of the session description. */ | 1071 | * the end of the session description. */ |
1006 | caddr_len = 0; | 1072 | caddr_len = 0; |
1007 | if (ct_sip_parse_sdp_addr(ct, *dptr, sdpoff, *datalen, | 1073 | if (ct_sip_parse_sdp_addr(ct, *dptr, sdpoff, *datalen, |
1008 | c_hdr, SDP_HDR_MEDIA, | 1074 | SDP_HDR_CONNECTION, SDP_HDR_MEDIA, |
1009 | &matchoff, &matchlen, &caddr) > 0) | 1075 | &matchoff, &matchlen, &caddr) > 0) |
1010 | caddr_len = matchlen; | 1076 | caddr_len = matchlen; |
1011 | 1077 | ||
@@ -1035,7 +1101,7 @@ static int process_sdp(struct sk_buff *skb, unsigned int dataoff, | |||
1035 | /* The media description overrides the session description. */ | 1101 | /* The media description overrides the session description. */ |
1036 | maddr_len = 0; | 1102 | maddr_len = 0; |
1037 | if (ct_sip_parse_sdp_addr(ct, *dptr, mediaoff, *datalen, | 1103 | if (ct_sip_parse_sdp_addr(ct, *dptr, mediaoff, *datalen, |
1038 | c_hdr, SDP_HDR_MEDIA, | 1104 | SDP_HDR_CONNECTION, SDP_HDR_MEDIA, |
1039 | &matchoff, &matchlen, &maddr) > 0) { | 1105 | &matchoff, &matchlen, &maddr) > 0) { |
1040 | maddr_len = matchlen; | 1106 | maddr_len = matchlen; |
1041 | memcpy(&rtp_addr, &maddr, sizeof(rtp_addr)); | 1107 | memcpy(&rtp_addr, &maddr, sizeof(rtp_addr)); |
@@ -1044,7 +1110,8 @@ static int process_sdp(struct sk_buff *skb, unsigned int dataoff, | |||
1044 | else | 1110 | else |
1045 | return NF_DROP; | 1111 | return NF_DROP; |
1046 | 1112 | ||
1047 | ret = set_expected_rtp_rtcp(skb, dataoff, dptr, datalen, | 1113 | ret = set_expected_rtp_rtcp(skb, protoff, dataoff, |
1114 | dptr, datalen, | ||
1048 | &rtp_addr, htons(port), t->class, | 1115 | &rtp_addr, htons(port), t->class, |
1049 | mediaoff, medialen); | 1116 | mediaoff, medialen); |
1050 | if (ret != NF_ACCEPT) | 1117 | if (ret != NF_ACCEPT) |
@@ -1052,8 +1119,9 @@ static int process_sdp(struct sk_buff *skb, unsigned int dataoff, | |||
1052 | 1119 | ||
1053 | /* Update media connection address if present */ | 1120 | /* Update media connection address if present */ |
1054 | if (maddr_len && nf_nat_sdp_addr && ct->status & IPS_NAT_MASK) { | 1121 | if (maddr_len && nf_nat_sdp_addr && ct->status & IPS_NAT_MASK) { |
1055 | ret = nf_nat_sdp_addr(skb, dataoff, dptr, datalen, | 1122 | ret = nf_nat_sdp_addr(skb, protoff, dataoff, |
1056 | mediaoff, c_hdr, SDP_HDR_MEDIA, | 1123 | dptr, datalen, mediaoff, |
1124 | SDP_HDR_CONNECTION, SDP_HDR_MEDIA, | ||
1057 | &rtp_addr); | 1125 | &rtp_addr); |
1058 | if (ret != NF_ACCEPT) | 1126 | if (ret != NF_ACCEPT) |
1059 | return ret; | 1127 | return ret; |
@@ -1064,12 +1132,13 @@ static int process_sdp(struct sk_buff *skb, unsigned int dataoff, | |||
1064 | /* Update session connection and owner addresses */ | 1132 | /* Update session connection and owner addresses */ |
1065 | nf_nat_sdp_session = rcu_dereference(nf_nat_sdp_session_hook); | 1133 | nf_nat_sdp_session = rcu_dereference(nf_nat_sdp_session_hook); |
1066 | if (nf_nat_sdp_session && ct->status & IPS_NAT_MASK) | 1134 | if (nf_nat_sdp_session && ct->status & IPS_NAT_MASK) |
1067 | ret = nf_nat_sdp_session(skb, dataoff, dptr, datalen, sdpoff, | 1135 | ret = nf_nat_sdp_session(skb, protoff, dataoff, |
1068 | &rtp_addr); | 1136 | dptr, datalen, sdpoff, &rtp_addr); |
1069 | 1137 | ||
1070 | return ret; | 1138 | return ret; |
1071 | } | 1139 | } |
1072 | static int process_invite_response(struct sk_buff *skb, unsigned int dataoff, | 1140 | static int process_invite_response(struct sk_buff *skb, unsigned int protoff, |
1141 | unsigned int dataoff, | ||
1073 | const char **dptr, unsigned int *datalen, | 1142 | const char **dptr, unsigned int *datalen, |
1074 | unsigned int cseq, unsigned int code) | 1143 | unsigned int cseq, unsigned int code) |
1075 | { | 1144 | { |
@@ -1079,13 +1148,14 @@ static int process_invite_response(struct sk_buff *skb, unsigned int dataoff, | |||
1079 | 1148 | ||
1080 | if ((code >= 100 && code <= 199) || | 1149 | if ((code >= 100 && code <= 199) || |
1081 | (code >= 200 && code <= 299)) | 1150 | (code >= 200 && code <= 299)) |
1082 | return process_sdp(skb, dataoff, dptr, datalen, cseq); | 1151 | return process_sdp(skb, protoff, dataoff, dptr, datalen, cseq); |
1083 | else if (ct_sip_info->invite_cseq == cseq) | 1152 | else if (ct_sip_info->invite_cseq == cseq) |
1084 | flush_expectations(ct, true); | 1153 | flush_expectations(ct, true); |
1085 | return NF_ACCEPT; | 1154 | return NF_ACCEPT; |
1086 | } | 1155 | } |
1087 | 1156 | ||
1088 | static int process_update_response(struct sk_buff *skb, unsigned int dataoff, | 1157 | static int process_update_response(struct sk_buff *skb, unsigned int protoff, |
1158 | unsigned int dataoff, | ||
1089 | const char **dptr, unsigned int *datalen, | 1159 | const char **dptr, unsigned int *datalen, |
1090 | unsigned int cseq, unsigned int code) | 1160 | unsigned int cseq, unsigned int code) |
1091 | { | 1161 | { |
@@ -1095,13 +1165,14 @@ static int process_update_response(struct sk_buff *skb, unsigned int dataoff, | |||
1095 | 1165 | ||
1096 | if ((code >= 100 && code <= 199) || | 1166 | if ((code >= 100 && code <= 199) || |
1097 | (code >= 200 && code <= 299)) | 1167 | (code >= 200 && code <= 299)) |
1098 | return process_sdp(skb, dataoff, dptr, datalen, cseq); | 1168 | return process_sdp(skb, protoff, dataoff, dptr, datalen, cseq); |
1099 | else if (ct_sip_info->invite_cseq == cseq) | 1169 | else if (ct_sip_info->invite_cseq == cseq) |
1100 | flush_expectations(ct, true); | 1170 | flush_expectations(ct, true); |
1101 | return NF_ACCEPT; | 1171 | return NF_ACCEPT; |
1102 | } | 1172 | } |
1103 | 1173 | ||
1104 | static int process_prack_response(struct sk_buff *skb, unsigned int dataoff, | 1174 | static int process_prack_response(struct sk_buff *skb, unsigned int protoff, |
1175 | unsigned int dataoff, | ||
1105 | const char **dptr, unsigned int *datalen, | 1176 | const char **dptr, unsigned int *datalen, |
1106 | unsigned int cseq, unsigned int code) | 1177 | unsigned int cseq, unsigned int code) |
1107 | { | 1178 | { |
@@ -1111,13 +1182,14 @@ static int process_prack_response(struct sk_buff *skb, unsigned int dataoff, | |||
1111 | 1182 | ||
1112 | if ((code >= 100 && code <= 199) || | 1183 | if ((code >= 100 && code <= 199) || |
1113 | (code >= 200 && code <= 299)) | 1184 | (code >= 200 && code <= 299)) |
1114 | return process_sdp(skb, dataoff, dptr, datalen, cseq); | 1185 | return process_sdp(skb, protoff, dataoff, dptr, datalen, cseq); |
1115 | else if (ct_sip_info->invite_cseq == cseq) | 1186 | else if (ct_sip_info->invite_cseq == cseq) |
1116 | flush_expectations(ct, true); | 1187 | flush_expectations(ct, true); |
1117 | return NF_ACCEPT; | 1188 | return NF_ACCEPT; |
1118 | } | 1189 | } |
1119 | 1190 | ||
1120 | static int process_invite_request(struct sk_buff *skb, unsigned int dataoff, | 1191 | static int process_invite_request(struct sk_buff *skb, unsigned int protoff, |
1192 | unsigned int dataoff, | ||
1121 | const char **dptr, unsigned int *datalen, | 1193 | const char **dptr, unsigned int *datalen, |
1122 | unsigned int cseq) | 1194 | unsigned int cseq) |
1123 | { | 1195 | { |
@@ -1127,13 +1199,14 @@ static int process_invite_request(struct sk_buff *skb, unsigned int dataoff, | |||
1127 | unsigned int ret; | 1199 | unsigned int ret; |
1128 | 1200 | ||
1129 | flush_expectations(ct, true); | 1201 | flush_expectations(ct, true); |
1130 | ret = process_sdp(skb, dataoff, dptr, datalen, cseq); | 1202 | ret = process_sdp(skb, protoff, dataoff, dptr, datalen, cseq); |
1131 | if (ret == NF_ACCEPT) | 1203 | if (ret == NF_ACCEPT) |
1132 | ct_sip_info->invite_cseq = cseq; | 1204 | ct_sip_info->invite_cseq = cseq; |
1133 | return ret; | 1205 | return ret; |
1134 | } | 1206 | } |
1135 | 1207 | ||
1136 | static int process_bye_request(struct sk_buff *skb, unsigned int dataoff, | 1208 | static int process_bye_request(struct sk_buff *skb, unsigned int protoff, |
1209 | unsigned int dataoff, | ||
1137 | const char **dptr, unsigned int *datalen, | 1210 | const char **dptr, unsigned int *datalen, |
1138 | unsigned int cseq) | 1211 | unsigned int cseq) |
1139 | { | 1212 | { |
@@ -1148,7 +1221,8 @@ static int process_bye_request(struct sk_buff *skb, unsigned int dataoff, | |||
1148 | * signalling connections. The expectation is marked inactive and is activated | 1221 | * signalling connections. The expectation is marked inactive and is activated |
1149 | * when receiving a response indicating success from the registrar. | 1222 | * when receiving a response indicating success from the registrar. |
1150 | */ | 1223 | */ |
1151 | static int process_register_request(struct sk_buff *skb, unsigned int dataoff, | 1224 | static int process_register_request(struct sk_buff *skb, unsigned int protoff, |
1225 | unsigned int dataoff, | ||
1152 | const char **dptr, unsigned int *datalen, | 1226 | const char **dptr, unsigned int *datalen, |
1153 | unsigned int cseq) | 1227 | unsigned int cseq) |
1154 | { | 1228 | { |
@@ -1223,8 +1297,8 @@ static int process_register_request(struct sk_buff *skb, unsigned int dataoff, | |||
1223 | 1297 | ||
1224 | nf_nat_sip_expect = rcu_dereference(nf_nat_sip_expect_hook); | 1298 | nf_nat_sip_expect = rcu_dereference(nf_nat_sip_expect_hook); |
1225 | if (nf_nat_sip_expect && ct->status & IPS_NAT_MASK) | 1299 | if (nf_nat_sip_expect && ct->status & IPS_NAT_MASK) |
1226 | ret = nf_nat_sip_expect(skb, dataoff, dptr, datalen, exp, | 1300 | ret = nf_nat_sip_expect(skb, protoff, dataoff, dptr, datalen, |
1227 | matchoff, matchlen); | 1301 | exp, matchoff, matchlen); |
1228 | else { | 1302 | else { |
1229 | if (nf_ct_expect_related(exp) != 0) | 1303 | if (nf_ct_expect_related(exp) != 0) |
1230 | ret = NF_DROP; | 1304 | ret = NF_DROP; |
@@ -1239,7 +1313,8 @@ store_cseq: | |||
1239 | return ret; | 1313 | return ret; |
1240 | } | 1314 | } |
1241 | 1315 | ||
1242 | static int process_register_response(struct sk_buff *skb, unsigned int dataoff, | 1316 | static int process_register_response(struct sk_buff *skb, unsigned int protoff, |
1317 | unsigned int dataoff, | ||
1243 | const char **dptr, unsigned int *datalen, | 1318 | const char **dptr, unsigned int *datalen, |
1244 | unsigned int cseq, unsigned int code) | 1319 | unsigned int cseq, unsigned int code) |
1245 | { | 1320 | { |
@@ -1321,7 +1396,8 @@ static const struct sip_handler sip_handlers[] = { | |||
1321 | SIP_HANDLER("REGISTER", process_register_request, process_register_response), | 1396 | SIP_HANDLER("REGISTER", process_register_request, process_register_response), |
1322 | }; | 1397 | }; |
1323 | 1398 | ||
1324 | static int process_sip_response(struct sk_buff *skb, unsigned int dataoff, | 1399 | static int process_sip_response(struct sk_buff *skb, unsigned int protoff, |
1400 | unsigned int dataoff, | ||
1325 | const char **dptr, unsigned int *datalen) | 1401 | const char **dptr, unsigned int *datalen) |
1326 | { | 1402 | { |
1327 | enum ip_conntrack_info ctinfo; | 1403 | enum ip_conntrack_info ctinfo; |
@@ -1352,13 +1428,14 @@ static int process_sip_response(struct sk_buff *skb, unsigned int dataoff, | |||
1352 | if (*datalen < matchend + handler->len || | 1428 | if (*datalen < matchend + handler->len || |
1353 | strnicmp(*dptr + matchend, handler->method, handler->len)) | 1429 | strnicmp(*dptr + matchend, handler->method, handler->len)) |
1354 | continue; | 1430 | continue; |
1355 | return handler->response(skb, dataoff, dptr, datalen, | 1431 | return handler->response(skb, protoff, dataoff, dptr, datalen, |
1356 | cseq, code); | 1432 | cseq, code); |
1357 | } | 1433 | } |
1358 | return NF_ACCEPT; | 1434 | return NF_ACCEPT; |
1359 | } | 1435 | } |
1360 | 1436 | ||
1361 | static int process_sip_request(struct sk_buff *skb, unsigned int dataoff, | 1437 | static int process_sip_request(struct sk_buff *skb, unsigned int protoff, |
1438 | unsigned int dataoff, | ||
1362 | const char **dptr, unsigned int *datalen) | 1439 | const char **dptr, unsigned int *datalen) |
1363 | { | 1440 | { |
1364 | enum ip_conntrack_info ctinfo; | 1441 | enum ip_conntrack_info ctinfo; |
@@ -1383,26 +1460,28 @@ static int process_sip_request(struct sk_buff *skb, unsigned int dataoff, | |||
1383 | if (!cseq) | 1460 | if (!cseq) |
1384 | return NF_DROP; | 1461 | return NF_DROP; |
1385 | 1462 | ||
1386 | return handler->request(skb, dataoff, dptr, datalen, cseq); | 1463 | return handler->request(skb, protoff, dataoff, dptr, datalen, |
1464 | cseq); | ||
1387 | } | 1465 | } |
1388 | return NF_ACCEPT; | 1466 | return NF_ACCEPT; |
1389 | } | 1467 | } |
1390 | 1468 | ||
1391 | static int process_sip_msg(struct sk_buff *skb, struct nf_conn *ct, | 1469 | static int process_sip_msg(struct sk_buff *skb, struct nf_conn *ct, |
1392 | unsigned int dataoff, const char **dptr, | 1470 | unsigned int protoff, unsigned int dataoff, |
1393 | unsigned int *datalen) | 1471 | const char **dptr, unsigned int *datalen) |
1394 | { | 1472 | { |
1395 | typeof(nf_nat_sip_hook) nf_nat_sip; | 1473 | typeof(nf_nat_sip_hook) nf_nat_sip; |
1396 | int ret; | 1474 | int ret; |
1397 | 1475 | ||
1398 | if (strnicmp(*dptr, "SIP/2.0 ", strlen("SIP/2.0 ")) != 0) | 1476 | if (strnicmp(*dptr, "SIP/2.0 ", strlen("SIP/2.0 ")) != 0) |
1399 | ret = process_sip_request(skb, dataoff, dptr, datalen); | 1477 | ret = process_sip_request(skb, protoff, dataoff, dptr, datalen); |
1400 | else | 1478 | else |
1401 | ret = process_sip_response(skb, dataoff, dptr, datalen); | 1479 | ret = process_sip_response(skb, protoff, dataoff, dptr, datalen); |
1402 | 1480 | ||
1403 | if (ret == NF_ACCEPT && ct->status & IPS_NAT_MASK) { | 1481 | if (ret == NF_ACCEPT && ct->status & IPS_NAT_MASK) { |
1404 | nf_nat_sip = rcu_dereference(nf_nat_sip_hook); | 1482 | nf_nat_sip = rcu_dereference(nf_nat_sip_hook); |
1405 | if (nf_nat_sip && !nf_nat_sip(skb, dataoff, dptr, datalen)) | 1483 | if (nf_nat_sip && !nf_nat_sip(skb, protoff, dataoff, |
1484 | dptr, datalen)) | ||
1406 | ret = NF_DROP; | 1485 | ret = NF_DROP; |
1407 | } | 1486 | } |
1408 | 1487 | ||
@@ -1470,7 +1549,8 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff, | |||
1470 | if (msglen > datalen) | 1549 | if (msglen > datalen) |
1471 | return NF_DROP; | 1550 | return NF_DROP; |
1472 | 1551 | ||
1473 | ret = process_sip_msg(skb, ct, dataoff, &dptr, &msglen); | 1552 | ret = process_sip_msg(skb, ct, protoff, dataoff, |
1553 | &dptr, &msglen); | ||
1474 | if (ret != NF_ACCEPT) | 1554 | if (ret != NF_ACCEPT) |
1475 | break; | 1555 | break; |
1476 | diff = msglen - origlen; | 1556 | diff = msglen - origlen; |
@@ -1484,7 +1564,7 @@ static int sip_help_tcp(struct sk_buff *skb, unsigned int protoff, | |||
1484 | if (ret == NF_ACCEPT && ct->status & IPS_NAT_MASK) { | 1564 | if (ret == NF_ACCEPT && ct->status & IPS_NAT_MASK) { |
1485 | nf_nat_sip_seq_adjust = rcu_dereference(nf_nat_sip_seq_adjust_hook); | 1565 | nf_nat_sip_seq_adjust = rcu_dereference(nf_nat_sip_seq_adjust_hook); |
1486 | if (nf_nat_sip_seq_adjust) | 1566 | if (nf_nat_sip_seq_adjust) |
1487 | nf_nat_sip_seq_adjust(skb, tdiff); | 1567 | nf_nat_sip_seq_adjust(skb, protoff, tdiff); |
1488 | } | 1568 | } |
1489 | 1569 | ||
1490 | return ret; | 1570 | return ret; |
@@ -1511,11 +1591,10 @@ static int sip_help_udp(struct sk_buff *skb, unsigned int protoff, | |||
1511 | if (datalen < strlen("SIP/2.0 200")) | 1591 | if (datalen < strlen("SIP/2.0 200")) |
1512 | return NF_ACCEPT; | 1592 | return NF_ACCEPT; |
1513 | 1593 | ||
1514 | return process_sip_msg(skb, ct, dataoff, &dptr, &datalen); | 1594 | return process_sip_msg(skb, ct, protoff, dataoff, &dptr, &datalen); |
1515 | } | 1595 | } |
1516 | 1596 | ||
1517 | static struct nf_conntrack_helper sip[MAX_PORTS][4] __read_mostly; | 1597 | static struct nf_conntrack_helper sip[MAX_PORTS][4] __read_mostly; |
1518 | static char sip_names[MAX_PORTS][4][sizeof("sip-65535")] __read_mostly; | ||
1519 | 1598 | ||
1520 | static const struct nf_conntrack_expect_policy sip_exp_policy[SIP_EXPECT_MAX + 1] = { | 1599 | static const struct nf_conntrack_expect_policy sip_exp_policy[SIP_EXPECT_MAX + 1] = { |
1521 | [SIP_EXPECT_SIGNALLING] = { | 1600 | [SIP_EXPECT_SIGNALLING] = { |
@@ -1585,9 +1664,9 @@ static int __init nf_conntrack_sip_init(void) | |||
1585 | sip[i][j].me = THIS_MODULE; | 1664 | sip[i][j].me = THIS_MODULE; |
1586 | 1665 | ||
1587 | if (ports[i] == SIP_PORT) | 1666 | if (ports[i] == SIP_PORT) |
1588 | sprintf(sip_names[i][j], "sip"); | 1667 | sprintf(sip[i][j].name, "sip"); |
1589 | else | 1668 | else |
1590 | sprintf(sip_names[i][j], "sip-%u", i); | 1669 | sprintf(sip[i][j].name, "sip-%u", i); |
1591 | 1670 | ||
1592 | pr_debug("port #%u: %u\n", i, ports[i]); | 1671 | pr_debug("port #%u: %u\n", i, ports[i]); |
1593 | 1672 | ||
diff --git a/net/netfilter/nf_internals.h b/net/netfilter/nf_internals.h index 770f76432ad0..3deec997be89 100644 --- a/net/netfilter/nf_internals.h +++ b/net/netfilter/nf_internals.h | |||
@@ -18,13 +18,13 @@ extern unsigned int nf_iterate(struct list_head *head, | |||
18 | unsigned int hook, | 18 | unsigned int hook, |
19 | const struct net_device *indev, | 19 | const struct net_device *indev, |
20 | const struct net_device *outdev, | 20 | const struct net_device *outdev, |
21 | struct list_head **i, | 21 | struct nf_hook_ops **elemp, |
22 | int (*okfn)(struct sk_buff *), | 22 | int (*okfn)(struct sk_buff *), |
23 | int hook_thresh); | 23 | int hook_thresh); |
24 | 24 | ||
25 | /* nf_queue.c */ | 25 | /* nf_queue.c */ |
26 | extern int nf_queue(struct sk_buff *skb, | 26 | extern int nf_queue(struct sk_buff *skb, |
27 | struct list_head *elem, | 27 | struct nf_hook_ops *elem, |
28 | u_int8_t pf, unsigned int hook, | 28 | u_int8_t pf, unsigned int hook, |
29 | struct net_device *indev, | 29 | struct net_device *indev, |
30 | struct net_device *outdev, | 30 | struct net_device *outdev, |
diff --git a/net/ipv4/netfilter/nf_nat_amanda.c b/net/netfilter/nf_nat_amanda.c index 3c04d24e2976..42d337881171 100644 --- a/net/ipv4/netfilter/nf_nat_amanda.c +++ b/net/netfilter/nf_nat_amanda.c | |||
@@ -16,7 +16,6 @@ | |||
16 | #include <net/netfilter/nf_conntrack_helper.h> | 16 | #include <net/netfilter/nf_conntrack_helper.h> |
17 | #include <net/netfilter/nf_conntrack_expect.h> | 17 | #include <net/netfilter/nf_conntrack_expect.h> |
18 | #include <net/netfilter/nf_nat_helper.h> | 18 | #include <net/netfilter/nf_nat_helper.h> |
19 | #include <net/netfilter/nf_nat_rule.h> | ||
20 | #include <linux/netfilter/nf_conntrack_amanda.h> | 19 | #include <linux/netfilter/nf_conntrack_amanda.h> |
21 | 20 | ||
22 | MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>"); | 21 | MODULE_AUTHOR("Brian J. Murrell <netfilter@interlinx.bc.ca>"); |
@@ -26,6 +25,7 @@ MODULE_ALIAS("ip_nat_amanda"); | |||
26 | 25 | ||
27 | static unsigned int help(struct sk_buff *skb, | 26 | static unsigned int help(struct sk_buff *skb, |
28 | enum ip_conntrack_info ctinfo, | 27 | enum ip_conntrack_info ctinfo, |
28 | unsigned int protoff, | ||
29 | unsigned int matchoff, | 29 | unsigned int matchoff, |
30 | unsigned int matchlen, | 30 | unsigned int matchlen, |
31 | struct nf_conntrack_expect *exp) | 31 | struct nf_conntrack_expect *exp) |
@@ -61,7 +61,7 @@ static unsigned int help(struct sk_buff *skb, | |||
61 | 61 | ||
62 | sprintf(buffer, "%u", port); | 62 | sprintf(buffer, "%u", port); |
63 | ret = nf_nat_mangle_udp_packet(skb, exp->master, ctinfo, | 63 | ret = nf_nat_mangle_udp_packet(skb, exp->master, ctinfo, |
64 | matchoff, matchlen, | 64 | protoff, matchoff, matchlen, |
65 | buffer, strlen(buffer)); | 65 | buffer, strlen(buffer)); |
66 | if (ret != NF_ACCEPT) | 66 | if (ret != NF_ACCEPT) |
67 | nf_ct_unexpect_related(exp); | 67 | nf_ct_unexpect_related(exp); |
diff --git a/net/ipv4/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c index 44b082fd48ab..29d445235199 100644 --- a/net/ipv4/netfilter/nf_nat_core.c +++ b/net/netfilter/nf_nat_core.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* NAT for netfilter; shared with compatibility layer. */ | 1 | /* |
2 | 2 | * (C) 1999-2001 Paul `Rusty' Russell | |
3 | /* (C) 1999-2001 Paul `Rusty' Russell | ||
4 | * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org> | 3 | * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org> |
4 | * (C) 2011 Patrick McHardy <kaber@trash.net> | ||
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License version 2 as | 7 | * it under the terms of the GNU General Public License version 2 as |
@@ -13,39 +13,106 @@ | |||
13 | #include <linux/timer.h> | 13 | #include <linux/timer.h> |
14 | #include <linux/skbuff.h> | 14 | #include <linux/skbuff.h> |
15 | #include <linux/gfp.h> | 15 | #include <linux/gfp.h> |
16 | #include <net/checksum.h> | 16 | #include <net/xfrm.h> |
17 | #include <net/icmp.h> | ||
18 | #include <net/ip.h> | ||
19 | #include <net/tcp.h> /* For tcp_prot in getorigdst */ | ||
20 | #include <linux/icmp.h> | ||
21 | #include <linux/udp.h> | ||
22 | #include <linux/jhash.h> | 17 | #include <linux/jhash.h> |
18 | #include <linux/rtnetlink.h> | ||
23 | 19 | ||
24 | #include <linux/netfilter_ipv4.h> | ||
25 | #include <net/netfilter/nf_conntrack.h> | 20 | #include <net/netfilter/nf_conntrack.h> |
26 | #include <net/netfilter/nf_conntrack_core.h> | 21 | #include <net/netfilter/nf_conntrack_core.h> |
27 | #include <net/netfilter/nf_nat.h> | 22 | #include <net/netfilter/nf_nat.h> |
28 | #include <net/netfilter/nf_nat_protocol.h> | 23 | #include <net/netfilter/nf_nat_l3proto.h> |
24 | #include <net/netfilter/nf_nat_l4proto.h> | ||
29 | #include <net/netfilter/nf_nat_core.h> | 25 | #include <net/netfilter/nf_nat_core.h> |
30 | #include <net/netfilter/nf_nat_helper.h> | 26 | #include <net/netfilter/nf_nat_helper.h> |
31 | #include <net/netfilter/nf_conntrack_helper.h> | 27 | #include <net/netfilter/nf_conntrack_helper.h> |
32 | #include <net/netfilter/nf_conntrack_l3proto.h> | 28 | #include <net/netfilter/nf_conntrack_l3proto.h> |
33 | #include <net/netfilter/nf_conntrack_zones.h> | 29 | #include <net/netfilter/nf_conntrack_zones.h> |
30 | #include <linux/netfilter/nf_nat.h> | ||
34 | 31 | ||
35 | static DEFINE_SPINLOCK(nf_nat_lock); | 32 | static DEFINE_SPINLOCK(nf_nat_lock); |
36 | 33 | ||
37 | static struct nf_conntrack_l3proto *l3proto __read_mostly; | 34 | static DEFINE_MUTEX(nf_nat_proto_mutex); |
38 | 35 | static const struct nf_nat_l3proto __rcu *nf_nat_l3protos[NFPROTO_NUMPROTO] | |
39 | #define MAX_IP_NAT_PROTO 256 | 36 | __read_mostly; |
40 | static const struct nf_nat_protocol __rcu *nf_nat_protos[MAX_IP_NAT_PROTO] | 37 | static const struct nf_nat_l4proto __rcu **nf_nat_l4protos[NFPROTO_NUMPROTO] |
41 | __read_mostly; | 38 | __read_mostly; |
42 | 39 | ||
43 | static inline const struct nf_nat_protocol * | 40 | |
44 | __nf_nat_proto_find(u_int8_t protonum) | 41 | inline const struct nf_nat_l3proto * |
42 | __nf_nat_l3proto_find(u8 family) | ||
45 | { | 43 | { |
46 | return rcu_dereference(nf_nat_protos[protonum]); | 44 | return rcu_dereference(nf_nat_l3protos[family]); |
47 | } | 45 | } |
48 | 46 | ||
47 | inline const struct nf_nat_l4proto * | ||
48 | __nf_nat_l4proto_find(u8 family, u8 protonum) | ||
49 | { | ||
50 | return rcu_dereference(nf_nat_l4protos[family][protonum]); | ||
51 | } | ||
52 | EXPORT_SYMBOL_GPL(__nf_nat_l4proto_find); | ||
53 | |||
54 | #ifdef CONFIG_XFRM | ||
55 | static void __nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl) | ||
56 | { | ||
57 | const struct nf_nat_l3proto *l3proto; | ||
58 | const struct nf_conn *ct; | ||
59 | enum ip_conntrack_info ctinfo; | ||
60 | enum ip_conntrack_dir dir; | ||
61 | unsigned long statusbit; | ||
62 | u8 family; | ||
63 | |||
64 | ct = nf_ct_get(skb, &ctinfo); | ||
65 | if (ct == NULL) | ||
66 | return; | ||
67 | |||
68 | family = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.l3num; | ||
69 | rcu_read_lock(); | ||
70 | l3proto = __nf_nat_l3proto_find(family); | ||
71 | if (l3proto == NULL) | ||
72 | goto out; | ||
73 | |||
74 | dir = CTINFO2DIR(ctinfo); | ||
75 | if (dir == IP_CT_DIR_ORIGINAL) | ||
76 | statusbit = IPS_DST_NAT; | ||
77 | else | ||
78 | statusbit = IPS_SRC_NAT; | ||
79 | |||
80 | l3proto->decode_session(skb, ct, dir, statusbit, fl); | ||
81 | out: | ||
82 | rcu_read_unlock(); | ||
83 | } | ||
84 | |||
85 | int nf_xfrm_me_harder(struct sk_buff *skb, unsigned int family) | ||
86 | { | ||
87 | struct flowi fl; | ||
88 | unsigned int hh_len; | ||
89 | struct dst_entry *dst; | ||
90 | |||
91 | if (xfrm_decode_session(skb, &fl, family) < 0) | ||
92 | return -1; | ||
93 | |||
94 | dst = skb_dst(skb); | ||
95 | if (dst->xfrm) | ||
96 | dst = ((struct xfrm_dst *)dst)->route; | ||
97 | dst_hold(dst); | ||
98 | |||
99 | dst = xfrm_lookup(dev_net(dst->dev), dst, &fl, skb->sk, 0); | ||
100 | if (IS_ERR(dst)) | ||
101 | return -1; | ||
102 | |||
103 | skb_dst_drop(skb); | ||
104 | skb_dst_set(skb, dst); | ||
105 | |||
106 | /* Change in oif may mean change in hh_len. */ | ||
107 | hh_len = skb_dst(skb)->dev->hard_header_len; | ||
108 | if (skb_headroom(skb) < hh_len && | ||
109 | pskb_expand_head(skb, hh_len - skb_headroom(skb), 0, GFP_ATOMIC)) | ||
110 | return -1; | ||
111 | return 0; | ||
112 | } | ||
113 | EXPORT_SYMBOL(nf_xfrm_me_harder); | ||
114 | #endif /* CONFIG_XFRM */ | ||
115 | |||
49 | /* We keep an extra hash for each conntrack, for fast searching. */ | 116 | /* We keep an extra hash for each conntrack, for fast searching. */ |
50 | static inline unsigned int | 117 | static inline unsigned int |
51 | hash_by_src(const struct net *net, u16 zone, | 118 | hash_by_src(const struct net *net, u16 zone, |
@@ -54,10 +121,9 @@ hash_by_src(const struct net *net, u16 zone, | |||
54 | unsigned int hash; | 121 | unsigned int hash; |
55 | 122 | ||
56 | /* Original src, to ensure we map it consistently if poss. */ | 123 | /* Original src, to ensure we map it consistently if poss. */ |
57 | hash = jhash_3words((__force u32)tuple->src.u3.ip, | 124 | hash = jhash2((u32 *)&tuple->src, sizeof(tuple->src) / sizeof(u32), |
58 | (__force u32)tuple->src.u.all ^ zone, | 125 | tuple->dst.protonum ^ zone ^ nf_conntrack_hash_rnd); |
59 | tuple->dst.protonum, nf_conntrack_hash_rnd); | 126 | return ((u64)hash * net->ct.nat_htable_size) >> 32; |
60 | return ((u64)hash * net->ipv4.nat_htable_size) >> 32; | ||
61 | } | 127 | } |
62 | 128 | ||
63 | /* Is this tuple already taken? (not by us) */ | 129 | /* Is this tuple already taken? (not by us) */ |
@@ -66,10 +132,11 @@ nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple, | |||
66 | const struct nf_conn *ignored_conntrack) | 132 | const struct nf_conn *ignored_conntrack) |
67 | { | 133 | { |
68 | /* Conntrack tracking doesn't keep track of outgoing tuples; only | 134 | /* Conntrack tracking doesn't keep track of outgoing tuples; only |
69 | incoming ones. NAT means they don't have a fixed mapping, | 135 | * incoming ones. NAT means they don't have a fixed mapping, |
70 | so we invert the tuple and look for the incoming reply. | 136 | * so we invert the tuple and look for the incoming reply. |
71 | 137 | * | |
72 | We could keep a separate hash if this proves too slow. */ | 138 | * We could keep a separate hash if this proves too slow. |
139 | */ | ||
73 | struct nf_conntrack_tuple reply; | 140 | struct nf_conntrack_tuple reply; |
74 | 141 | ||
75 | nf_ct_invert_tuplepr(&reply, tuple); | 142 | nf_ct_invert_tuplepr(&reply, tuple); |
@@ -78,31 +145,26 @@ nf_nat_used_tuple(const struct nf_conntrack_tuple *tuple, | |||
78 | EXPORT_SYMBOL(nf_nat_used_tuple); | 145 | EXPORT_SYMBOL(nf_nat_used_tuple); |
79 | 146 | ||
80 | /* If we source map this tuple so reply looks like reply_tuple, will | 147 | /* If we source map this tuple so reply looks like reply_tuple, will |
81 | * that meet the constraints of range. */ | 148 | * that meet the constraints of range. |
82 | static int | 149 | */ |
83 | in_range(const struct nf_conntrack_tuple *tuple, | 150 | static int in_range(const struct nf_nat_l3proto *l3proto, |
84 | const struct nf_nat_ipv4_range *range) | 151 | const struct nf_nat_l4proto *l4proto, |
152 | const struct nf_conntrack_tuple *tuple, | ||
153 | const struct nf_nat_range *range) | ||
85 | { | 154 | { |
86 | const struct nf_nat_protocol *proto; | ||
87 | int ret = 0; | ||
88 | |||
89 | /* If we are supposed to map IPs, then we must be in the | 155 | /* If we are supposed to map IPs, then we must be in the |
90 | range specified, otherwise let this drag us onto a new src IP. */ | 156 | * range specified, otherwise let this drag us onto a new src IP. |
91 | if (range->flags & NF_NAT_RANGE_MAP_IPS) { | 157 | */ |
92 | if (ntohl(tuple->src.u3.ip) < ntohl(range->min_ip) || | 158 | if (range->flags & NF_NAT_RANGE_MAP_IPS && |
93 | ntohl(tuple->src.u3.ip) > ntohl(range->max_ip)) | 159 | !l3proto->in_range(tuple, range)) |
94 | return 0; | 160 | return 0; |
95 | } | ||
96 | 161 | ||
97 | rcu_read_lock(); | ||
98 | proto = __nf_nat_proto_find(tuple->dst.protonum); | ||
99 | if (!(range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) || | 162 | if (!(range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) || |
100 | proto->in_range(tuple, NF_NAT_MANIP_SRC, | 163 | l4proto->in_range(tuple, NF_NAT_MANIP_SRC, |
101 | &range->min, &range->max)) | 164 | &range->min_proto, &range->max_proto)) |
102 | ret = 1; | 165 | return 1; |
103 | rcu_read_unlock(); | ||
104 | 166 | ||
105 | return ret; | 167 | return 0; |
106 | } | 168 | } |
107 | 169 | ||
108 | static inline int | 170 | static inline int |
@@ -113,24 +175,25 @@ same_src(const struct nf_conn *ct, | |||
113 | 175 | ||
114 | t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; | 176 | t = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple; |
115 | return (t->dst.protonum == tuple->dst.protonum && | 177 | return (t->dst.protonum == tuple->dst.protonum && |
116 | t->src.u3.ip == tuple->src.u3.ip && | 178 | nf_inet_addr_cmp(&t->src.u3, &tuple->src.u3) && |
117 | t->src.u.all == tuple->src.u.all); | 179 | t->src.u.all == tuple->src.u.all); |
118 | } | 180 | } |
119 | 181 | ||
120 | /* Only called for SRC manip */ | 182 | /* Only called for SRC manip */ |
121 | static int | 183 | static int |
122 | find_appropriate_src(struct net *net, u16 zone, | 184 | find_appropriate_src(struct net *net, u16 zone, |
185 | const struct nf_nat_l3proto *l3proto, | ||
186 | const struct nf_nat_l4proto *l4proto, | ||
123 | const struct nf_conntrack_tuple *tuple, | 187 | const struct nf_conntrack_tuple *tuple, |
124 | struct nf_conntrack_tuple *result, | 188 | struct nf_conntrack_tuple *result, |
125 | const struct nf_nat_ipv4_range *range) | 189 | const struct nf_nat_range *range) |
126 | { | 190 | { |
127 | unsigned int h = hash_by_src(net, zone, tuple); | 191 | unsigned int h = hash_by_src(net, zone, tuple); |
128 | const struct nf_conn_nat *nat; | 192 | const struct nf_conn_nat *nat; |
129 | const struct nf_conn *ct; | 193 | const struct nf_conn *ct; |
130 | const struct hlist_node *n; | 194 | const struct hlist_node *n; |
131 | 195 | ||
132 | rcu_read_lock(); | 196 | hlist_for_each_entry_rcu(nat, n, &net->ct.nat_bysource[h], bysource) { |
133 | hlist_for_each_entry_rcu(nat, n, &net->ipv4.nat_bysource[h], bysource) { | ||
134 | ct = nat->ct; | 197 | ct = nat->ct; |
135 | if (same_src(ct, tuple) && nf_ct_zone(ct) == zone) { | 198 | if (same_src(ct, tuple) && nf_ct_zone(ct) == zone) { |
136 | /* Copy source part from reply tuple. */ | 199 | /* Copy source part from reply tuple. */ |
@@ -138,119 +201,150 @@ find_appropriate_src(struct net *net, u16 zone, | |||
138 | &ct->tuplehash[IP_CT_DIR_REPLY].tuple); | 201 | &ct->tuplehash[IP_CT_DIR_REPLY].tuple); |
139 | result->dst = tuple->dst; | 202 | result->dst = tuple->dst; |
140 | 203 | ||
141 | if (in_range(result, range)) { | 204 | if (in_range(l3proto, l4proto, result, range)) { |
142 | rcu_read_unlock(); | 205 | rcu_read_unlock(); |
143 | return 1; | 206 | return 1; |
144 | } | 207 | } |
145 | } | 208 | } |
146 | } | 209 | } |
147 | rcu_read_unlock(); | ||
148 | return 0; | 210 | return 0; |
149 | } | 211 | } |
150 | 212 | ||
151 | /* For [FUTURE] fragmentation handling, we want the least-used | 213 | /* For [FUTURE] fragmentation handling, we want the least-used |
152 | src-ip/dst-ip/proto triple. Fairness doesn't come into it. Thus | 214 | * src-ip/dst-ip/proto triple. Fairness doesn't come into it. Thus |
153 | if the range specifies 1.2.3.4 ports 10000-10005 and 1.2.3.5 ports | 215 | * if the range specifies 1.2.3.4 ports 10000-10005 and 1.2.3.5 ports |
154 | 1-65535, we don't do pro-rata allocation based on ports; we choose | 216 | * 1-65535, we don't do pro-rata allocation based on ports; we choose |
155 | the ip with the lowest src-ip/dst-ip/proto usage. | 217 | * the ip with the lowest src-ip/dst-ip/proto usage. |
156 | */ | 218 | */ |
157 | static void | 219 | static void |
158 | find_best_ips_proto(u16 zone, struct nf_conntrack_tuple *tuple, | 220 | find_best_ips_proto(u16 zone, struct nf_conntrack_tuple *tuple, |
159 | const struct nf_nat_ipv4_range *range, | 221 | const struct nf_nat_range *range, |
160 | const struct nf_conn *ct, | 222 | const struct nf_conn *ct, |
161 | enum nf_nat_manip_type maniptype) | 223 | enum nf_nat_manip_type maniptype) |
162 | { | 224 | { |
163 | __be32 *var_ipp; | 225 | union nf_inet_addr *var_ipp; |
226 | unsigned int i, max; | ||
164 | /* Host order */ | 227 | /* Host order */ |
165 | u_int32_t minip, maxip, j; | 228 | u32 minip, maxip, j, dist; |
229 | bool full_range; | ||
166 | 230 | ||
167 | /* No IP mapping? Do nothing. */ | 231 | /* No IP mapping? Do nothing. */ |
168 | if (!(range->flags & NF_NAT_RANGE_MAP_IPS)) | 232 | if (!(range->flags & NF_NAT_RANGE_MAP_IPS)) |
169 | return; | 233 | return; |
170 | 234 | ||
171 | if (maniptype == NF_NAT_MANIP_SRC) | 235 | if (maniptype == NF_NAT_MANIP_SRC) |
172 | var_ipp = &tuple->src.u3.ip; | 236 | var_ipp = &tuple->src.u3; |
173 | else | 237 | else |
174 | var_ipp = &tuple->dst.u3.ip; | 238 | var_ipp = &tuple->dst.u3; |
175 | 239 | ||
176 | /* Fast path: only one choice. */ | 240 | /* Fast path: only one choice. */ |
177 | if (range->min_ip == range->max_ip) { | 241 | if (nf_inet_addr_cmp(&range->min_addr, &range->max_addr)) { |
178 | *var_ipp = range->min_ip; | 242 | *var_ipp = range->min_addr; |
179 | return; | 243 | return; |
180 | } | 244 | } |
181 | 245 | ||
246 | if (nf_ct_l3num(ct) == NFPROTO_IPV4) | ||
247 | max = sizeof(var_ipp->ip) / sizeof(u32) - 1; | ||
248 | else | ||
249 | max = sizeof(var_ipp->ip6) / sizeof(u32) - 1; | ||
250 | |||
182 | /* Hashing source and destination IPs gives a fairly even | 251 | /* Hashing source and destination IPs gives a fairly even |
183 | * spread in practice (if there are a small number of IPs | 252 | * spread in practice (if there are a small number of IPs |
184 | * involved, there usually aren't that many connections | 253 | * involved, there usually aren't that many connections |
185 | * anyway). The consistency means that servers see the same | 254 | * anyway). The consistency means that servers see the same |
186 | * client coming from the same IP (some Internet Banking sites | 255 | * client coming from the same IP (some Internet Banking sites |
187 | * like this), even across reboots. */ | 256 | * like this), even across reboots. |
188 | minip = ntohl(range->min_ip); | 257 | */ |
189 | maxip = ntohl(range->max_ip); | 258 | j = jhash2((u32 *)&tuple->src.u3, sizeof(tuple->src.u3), |
190 | j = jhash_2words((__force u32)tuple->src.u3.ip, | 259 | range->flags & NF_NAT_RANGE_PERSISTENT ? |
191 | range->flags & NF_NAT_RANGE_PERSISTENT ? | 260 | 0 : (__force u32)tuple->dst.u3.all[max] ^ zone); |
192 | 0 : (__force u32)tuple->dst.u3.ip ^ zone, 0); | 261 | |
193 | j = ((u64)j * (maxip - minip + 1)) >> 32; | 262 | full_range = false; |
194 | *var_ipp = htonl(minip + j); | 263 | for (i = 0; i <= max; i++) { |
264 | /* If first bytes of the address are at the maximum, use the | ||
265 | * distance. Otherwise use the full range. | ||
266 | */ | ||
267 | if (!full_range) { | ||
268 | minip = ntohl((__force __be32)range->min_addr.all[i]); | ||
269 | maxip = ntohl((__force __be32)range->max_addr.all[i]); | ||
270 | dist = maxip - minip + 1; | ||
271 | } else { | ||
272 | minip = 0; | ||
273 | dist = ~0; | ||
274 | } | ||
275 | |||
276 | var_ipp->all[i] = (__force __u32) | ||
277 | htonl(minip + (((u64)j * dist) >> 32)); | ||
278 | if (var_ipp->all[i] != range->max_addr.all[i]) | ||
279 | full_range = true; | ||
280 | |||
281 | if (!(range->flags & NF_NAT_RANGE_PERSISTENT)) | ||
282 | j ^= (__force u32)tuple->dst.u3.all[i]; | ||
283 | } | ||
195 | } | 284 | } |
196 | 285 | ||
197 | /* Manipulate the tuple into the range given. For NF_INET_POST_ROUTING, | 286 | /* Manipulate the tuple into the range given. For NF_INET_POST_ROUTING, |
198 | * we change the source to map into the range. For NF_INET_PRE_ROUTING | 287 | * we change the source to map into the range. For NF_INET_PRE_ROUTING |
199 | * and NF_INET_LOCAL_OUT, we change the destination to map into the | 288 | * and NF_INET_LOCAL_OUT, we change the destination to map into the |
200 | * range. It might not be possible to get a unique tuple, but we try. | 289 | * range. It might not be possible to get a unique tuple, but we try. |
201 | * At worst (or if we race), we will end up with a final duplicate in | 290 | * At worst (or if we race), we will end up with a final duplicate in |
202 | * __ip_conntrack_confirm and drop the packet. */ | 291 | * __ip_conntrack_confirm and drop the packet. */ |
203 | static void | 292 | static void |
204 | get_unique_tuple(struct nf_conntrack_tuple *tuple, | 293 | get_unique_tuple(struct nf_conntrack_tuple *tuple, |
205 | const struct nf_conntrack_tuple *orig_tuple, | 294 | const struct nf_conntrack_tuple *orig_tuple, |
206 | const struct nf_nat_ipv4_range *range, | 295 | const struct nf_nat_range *range, |
207 | struct nf_conn *ct, | 296 | struct nf_conn *ct, |
208 | enum nf_nat_manip_type maniptype) | 297 | enum nf_nat_manip_type maniptype) |
209 | { | 298 | { |
299 | const struct nf_nat_l3proto *l3proto; | ||
300 | const struct nf_nat_l4proto *l4proto; | ||
210 | struct net *net = nf_ct_net(ct); | 301 | struct net *net = nf_ct_net(ct); |
211 | const struct nf_nat_protocol *proto; | ||
212 | u16 zone = nf_ct_zone(ct); | 302 | u16 zone = nf_ct_zone(ct); |
213 | 303 | ||
214 | /* 1) If this srcip/proto/src-proto-part is currently mapped, | 304 | rcu_read_lock(); |
215 | and that same mapping gives a unique tuple within the given | 305 | l3proto = __nf_nat_l3proto_find(orig_tuple->src.l3num); |
216 | range, use that. | 306 | l4proto = __nf_nat_l4proto_find(orig_tuple->src.l3num, |
307 | orig_tuple->dst.protonum); | ||
217 | 308 | ||
218 | This is only required for source (ie. NAT/masq) mappings. | 309 | /* 1) If this srcip/proto/src-proto-part is currently mapped, |
219 | So far, we don't do local source mappings, so multiple | 310 | * and that same mapping gives a unique tuple within the given |
220 | manips not an issue. */ | 311 | * range, use that. |
312 | * | ||
313 | * This is only required for source (ie. NAT/masq) mappings. | ||
314 | * So far, we don't do local source mappings, so multiple | ||
315 | * manips not an issue. | ||
316 | */ | ||
221 | if (maniptype == NF_NAT_MANIP_SRC && | 317 | if (maniptype == NF_NAT_MANIP_SRC && |
222 | !(range->flags & NF_NAT_RANGE_PROTO_RANDOM)) { | 318 | !(range->flags & NF_NAT_RANGE_PROTO_RANDOM)) { |
223 | /* try the original tuple first */ | 319 | /* try the original tuple first */ |
224 | if (in_range(orig_tuple, range)) { | 320 | if (in_range(l3proto, l4proto, orig_tuple, range)) { |
225 | if (!nf_nat_used_tuple(orig_tuple, ct)) { | 321 | if (!nf_nat_used_tuple(orig_tuple, ct)) { |
226 | *tuple = *orig_tuple; | 322 | *tuple = *orig_tuple; |
227 | return; | 323 | goto out; |
228 | } | 324 | } |
229 | } else if (find_appropriate_src(net, zone, orig_tuple, tuple, | 325 | } else if (find_appropriate_src(net, zone, l3proto, l4proto, |
230 | range)) { | 326 | orig_tuple, tuple, range)) { |
231 | pr_debug("get_unique_tuple: Found current src map\n"); | 327 | pr_debug("get_unique_tuple: Found current src map\n"); |
232 | if (!nf_nat_used_tuple(tuple, ct)) | 328 | if (!nf_nat_used_tuple(tuple, ct)) |
233 | return; | 329 | goto out; |
234 | } | 330 | } |
235 | } | 331 | } |
236 | 332 | ||
237 | /* 2) Select the least-used IP/proto combination in the given | 333 | /* 2) Select the least-used IP/proto combination in the given range */ |
238 | range. */ | ||
239 | *tuple = *orig_tuple; | 334 | *tuple = *orig_tuple; |
240 | find_best_ips_proto(zone, tuple, range, ct, maniptype); | 335 | find_best_ips_proto(zone, tuple, range, ct, maniptype); |
241 | 336 | ||
242 | /* 3) The per-protocol part of the manip is made to map into | 337 | /* 3) The per-protocol part of the manip is made to map into |
243 | the range to make a unique tuple. */ | 338 | * the range to make a unique tuple. |
244 | 339 | */ | |
245 | rcu_read_lock(); | ||
246 | proto = __nf_nat_proto_find(orig_tuple->dst.protonum); | ||
247 | 340 | ||
248 | /* Only bother mapping if it's not already in range and unique */ | 341 | /* Only bother mapping if it's not already in range and unique */ |
249 | if (!(range->flags & NF_NAT_RANGE_PROTO_RANDOM)) { | 342 | if (!(range->flags & NF_NAT_RANGE_PROTO_RANDOM)) { |
250 | if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) { | 343 | if (range->flags & NF_NAT_RANGE_PROTO_SPECIFIED) { |
251 | if (proto->in_range(tuple, maniptype, &range->min, | 344 | if (l4proto->in_range(tuple, maniptype, |
252 | &range->max) && | 345 | &range->min_proto, |
253 | (range->min.all == range->max.all || | 346 | &range->max_proto) && |
347 | (range->min_proto.all == range->max_proto.all || | ||
254 | !nf_nat_used_tuple(tuple, ct))) | 348 | !nf_nat_used_tuple(tuple, ct))) |
255 | goto out; | 349 | goto out; |
256 | } else if (!nf_nat_used_tuple(tuple, ct)) { | 350 | } else if (!nf_nat_used_tuple(tuple, ct)) { |
@@ -259,14 +353,14 @@ get_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
259 | } | 353 | } |
260 | 354 | ||
261 | /* Last change: get protocol to try to obtain unique tuple. */ | 355 | /* Last change: get protocol to try to obtain unique tuple. */ |
262 | proto->unique_tuple(tuple, range, maniptype, ct); | 356 | l4proto->unique_tuple(l3proto, tuple, range, maniptype, ct); |
263 | out: | 357 | out: |
264 | rcu_read_unlock(); | 358 | rcu_read_unlock(); |
265 | } | 359 | } |
266 | 360 | ||
267 | unsigned int | 361 | unsigned int |
268 | nf_nat_setup_info(struct nf_conn *ct, | 362 | nf_nat_setup_info(struct nf_conn *ct, |
269 | const struct nf_nat_ipv4_range *range, | 363 | const struct nf_nat_range *range, |
270 | enum nf_nat_manip_type maniptype) | 364 | enum nf_nat_manip_type maniptype) |
271 | { | 365 | { |
272 | struct net *net = nf_ct_net(ct); | 366 | struct net *net = nf_ct_net(ct); |
@@ -288,10 +382,10 @@ nf_nat_setup_info(struct nf_conn *ct, | |||
288 | BUG_ON(nf_nat_initialized(ct, maniptype)); | 382 | BUG_ON(nf_nat_initialized(ct, maniptype)); |
289 | 383 | ||
290 | /* What we've got will look like inverse of reply. Normally | 384 | /* What we've got will look like inverse of reply. Normally |
291 | this is what is in the conntrack, except for prior | 385 | * this is what is in the conntrack, except for prior |
292 | manipulations (future optimization: if num_manips == 0, | 386 | * manipulations (future optimization: if num_manips == 0, |
293 | orig_tp = | 387 | * orig_tp = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple) |
294 | conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple) */ | 388 | */ |
295 | nf_ct_invert_tuplepr(&curr_tuple, | 389 | nf_ct_invert_tuplepr(&curr_tuple, |
296 | &ct->tuplehash[IP_CT_DIR_REPLY].tuple); | 390 | &ct->tuplehash[IP_CT_DIR_REPLY].tuple); |
297 | 391 | ||
@@ -317,11 +411,11 @@ nf_nat_setup_info(struct nf_conn *ct, | |||
317 | srchash = hash_by_src(net, nf_ct_zone(ct), | 411 | srchash = hash_by_src(net, nf_ct_zone(ct), |
318 | &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); | 412 | &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); |
319 | spin_lock_bh(&nf_nat_lock); | 413 | spin_lock_bh(&nf_nat_lock); |
320 | /* nf_conntrack_alter_reply might re-allocate extension area */ | 414 | /* nf_conntrack_alter_reply might re-allocate extension aera */ |
321 | nat = nfct_nat(ct); | 415 | nat = nfct_nat(ct); |
322 | nat->ct = ct; | 416 | nat->ct = ct; |
323 | hlist_add_head_rcu(&nat->bysource, | 417 | hlist_add_head_rcu(&nat->bysource, |
324 | &net->ipv4.nat_bysource[srchash]); | 418 | &net->ct.nat_bysource[srchash]); |
325 | spin_unlock_bh(&nf_nat_lock); | 419 | spin_unlock_bh(&nf_nat_lock); |
326 | } | 420 | } |
327 | 421 | ||
@@ -335,47 +429,14 @@ nf_nat_setup_info(struct nf_conn *ct, | |||
335 | } | 429 | } |
336 | EXPORT_SYMBOL(nf_nat_setup_info); | 430 | EXPORT_SYMBOL(nf_nat_setup_info); |
337 | 431 | ||
338 | /* Returns true if succeeded. */ | ||
339 | static bool | ||
340 | manip_pkt(u_int16_t proto, | ||
341 | struct sk_buff *skb, | ||
342 | unsigned int iphdroff, | ||
343 | const struct nf_conntrack_tuple *target, | ||
344 | enum nf_nat_manip_type maniptype) | ||
345 | { | ||
346 | struct iphdr *iph; | ||
347 | const struct nf_nat_protocol *p; | ||
348 | |||
349 | if (!skb_make_writable(skb, iphdroff + sizeof(*iph))) | ||
350 | return false; | ||
351 | |||
352 | iph = (void *)skb->data + iphdroff; | ||
353 | |||
354 | /* Manipulate protcol part. */ | ||
355 | |||
356 | /* rcu_read_lock()ed by nf_hook_slow */ | ||
357 | p = __nf_nat_proto_find(proto); | ||
358 | if (!p->manip_pkt(skb, iphdroff, target, maniptype)) | ||
359 | return false; | ||
360 | |||
361 | iph = (void *)skb->data + iphdroff; | ||
362 | |||
363 | if (maniptype == NF_NAT_MANIP_SRC) { | ||
364 | csum_replace4(&iph->check, iph->saddr, target->src.u3.ip); | ||
365 | iph->saddr = target->src.u3.ip; | ||
366 | } else { | ||
367 | csum_replace4(&iph->check, iph->daddr, target->dst.u3.ip); | ||
368 | iph->daddr = target->dst.u3.ip; | ||
369 | } | ||
370 | return true; | ||
371 | } | ||
372 | |||
373 | /* Do packet manipulations according to nf_nat_setup_info. */ | 432 | /* Do packet manipulations according to nf_nat_setup_info. */ |
374 | unsigned int nf_nat_packet(struct nf_conn *ct, | 433 | unsigned int nf_nat_packet(struct nf_conn *ct, |
375 | enum ip_conntrack_info ctinfo, | 434 | enum ip_conntrack_info ctinfo, |
376 | unsigned int hooknum, | 435 | unsigned int hooknum, |
377 | struct sk_buff *skb) | 436 | struct sk_buff *skb) |
378 | { | 437 | { |
438 | const struct nf_nat_l3proto *l3proto; | ||
439 | const struct nf_nat_l4proto *l4proto; | ||
379 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | 440 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); |
380 | unsigned long statusbit; | 441 | unsigned long statusbit; |
381 | enum nf_nat_manip_type mtype = HOOK2MANIP(hooknum); | 442 | enum nf_nat_manip_type mtype = HOOK2MANIP(hooknum); |
@@ -396,129 +457,174 @@ unsigned int nf_nat_packet(struct nf_conn *ct, | |||
396 | /* We are aiming to look like inverse of other direction. */ | 457 | /* We are aiming to look like inverse of other direction. */ |
397 | nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple); | 458 | nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple); |
398 | 459 | ||
399 | if (!manip_pkt(target.dst.protonum, skb, 0, &target, mtype)) | 460 | l3proto = __nf_nat_l3proto_find(target.src.l3num); |
461 | l4proto = __nf_nat_l4proto_find(target.src.l3num, | ||
462 | target.dst.protonum); | ||
463 | if (!l3proto->manip_pkt(skb, 0, l4proto, &target, mtype)) | ||
400 | return NF_DROP; | 464 | return NF_DROP; |
401 | } | 465 | } |
402 | return NF_ACCEPT; | 466 | return NF_ACCEPT; |
403 | } | 467 | } |
404 | EXPORT_SYMBOL_GPL(nf_nat_packet); | 468 | EXPORT_SYMBOL_GPL(nf_nat_packet); |
405 | 469 | ||
406 | /* Dir is direction ICMP is coming from (opposite to packet it contains) */ | 470 | struct nf_nat_proto_clean { |
407 | int nf_nat_icmp_reply_translation(struct nf_conn *ct, | 471 | u8 l3proto; |
408 | enum ip_conntrack_info ctinfo, | 472 | u8 l4proto; |
409 | unsigned int hooknum, | 473 | bool hash; |
410 | struct sk_buff *skb) | 474 | }; |
475 | |||
476 | /* Clear NAT section of all conntracks, in case we're loaded again. */ | ||
477 | static int nf_nat_proto_clean(struct nf_conn *i, void *data) | ||
411 | { | 478 | { |
412 | struct { | 479 | const struct nf_nat_proto_clean *clean = data; |
413 | struct icmphdr icmp; | 480 | struct nf_conn_nat *nat = nfct_nat(i); |
414 | struct iphdr ip; | ||
415 | } *inside; | ||
416 | struct nf_conntrack_tuple target; | ||
417 | int hdrlen = ip_hdrlen(skb); | ||
418 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | ||
419 | unsigned long statusbit; | ||
420 | enum nf_nat_manip_type manip = HOOK2MANIP(hooknum); | ||
421 | 481 | ||
422 | if (!skb_make_writable(skb, hdrlen + sizeof(*inside))) | 482 | if (!nat) |
423 | return 0; | 483 | return 0; |
424 | 484 | if ((clean->l3proto && nf_ct_l3num(i) != clean->l3proto) || | |
425 | inside = (void *)skb->data + hdrlen; | 485 | (clean->l4proto && nf_ct_protonum(i) != clean->l4proto)) |
426 | |||
427 | /* We're actually going to mangle it beyond trivial checksum | ||
428 | adjustment, so make sure the current checksum is correct. */ | ||
429 | if (nf_ip_checksum(skb, hooknum, hdrlen, 0)) | ||
430 | return 0; | 486 | return 0; |
431 | 487 | ||
432 | /* Must be RELATED */ | 488 | if (clean->hash) { |
433 | NF_CT_ASSERT(skb->nfctinfo == IP_CT_RELATED || | 489 | spin_lock_bh(&nf_nat_lock); |
434 | skb->nfctinfo == IP_CT_RELATED_REPLY); | 490 | hlist_del_rcu(&nat->bysource); |
435 | 491 | spin_unlock_bh(&nf_nat_lock); | |
436 | /* Redirects on non-null nats must be dropped, else they'll | 492 | } else { |
437 | start talking to each other without our translation, and be | 493 | memset(nat, 0, sizeof(*nat)); |
438 | confused... --RR */ | 494 | i->status &= ~(IPS_NAT_MASK | IPS_NAT_DONE_MASK | |
439 | if (inside->icmp.type == ICMP_REDIRECT) { | 495 | IPS_SEQ_ADJUST); |
440 | /* If NAT isn't finished, assume it and drop. */ | ||
441 | if ((ct->status & IPS_NAT_DONE_MASK) != IPS_NAT_DONE_MASK) | ||
442 | return 0; | ||
443 | |||
444 | if (ct->status & IPS_NAT_MASK) | ||
445 | return 0; | ||
446 | } | 496 | } |
497 | return 0; | ||
498 | } | ||
447 | 499 | ||
448 | if (manip == NF_NAT_MANIP_SRC) | 500 | static void nf_nat_l4proto_clean(u8 l3proto, u8 l4proto) |
449 | statusbit = IPS_SRC_NAT; | 501 | { |
450 | else | 502 | struct nf_nat_proto_clean clean = { |
451 | statusbit = IPS_DST_NAT; | 503 | .l3proto = l3proto, |
452 | 504 | .l4proto = l4proto, | |
453 | /* Invert if this is reply dir. */ | 505 | }; |
454 | if (dir == IP_CT_DIR_REPLY) | 506 | struct net *net; |
455 | statusbit ^= IPS_NAT_MASK; | 507 | |
456 | 508 | rtnl_lock(); | |
457 | if (!(ct->status & statusbit)) | 509 | /* Step 1 - remove from bysource hash */ |
458 | return 1; | 510 | clean.hash = true; |
459 | 511 | for_each_net(net) | |
460 | pr_debug("icmp_reply_translation: translating error %p manip %u " | 512 | nf_ct_iterate_cleanup(net, nf_nat_proto_clean, &clean); |
461 | "dir %s\n", skb, manip, | 513 | synchronize_rcu(); |
462 | dir == IP_CT_DIR_ORIGINAL ? "ORIG" : "REPLY"); | ||
463 | |||
464 | /* Change inner back to look like incoming packet. We do the | ||
465 | opposite manip on this hook to normal, because it might not | ||
466 | pass all hooks (locally-generated ICMP). Consider incoming | ||
467 | packet: PREROUTING (DST manip), routing produces ICMP, goes | ||
468 | through POSTROUTING (which must correct the DST manip). */ | ||
469 | if (!manip_pkt(inside->ip.protocol, skb, hdrlen + sizeof(inside->icmp), | ||
470 | &ct->tuplehash[!dir].tuple, !manip)) | ||
471 | return 0; | ||
472 | 514 | ||
473 | if (skb->ip_summed != CHECKSUM_PARTIAL) { | 515 | /* Step 2 - clean NAT section */ |
474 | /* Reloading "inside" here since manip_pkt inner. */ | 516 | clean.hash = false; |
475 | inside = (void *)skb->data + hdrlen; | 517 | for_each_net(net) |
476 | inside->icmp.checksum = 0; | 518 | nf_ct_iterate_cleanup(net, nf_nat_proto_clean, &clean); |
477 | inside->icmp.checksum = | 519 | rtnl_unlock(); |
478 | csum_fold(skb_checksum(skb, hdrlen, | 520 | } |
479 | skb->len - hdrlen, 0)); | ||
480 | } | ||
481 | 521 | ||
482 | /* Change outer to look the reply to an incoming packet | 522 | static void nf_nat_l3proto_clean(u8 l3proto) |
483 | * (proto 0 means don't invert per-proto part). */ | 523 | { |
484 | nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple); | 524 | struct nf_nat_proto_clean clean = { |
485 | if (!manip_pkt(0, skb, 0, &target, manip)) | 525 | .l3proto = l3proto, |
486 | return 0; | 526 | }; |
527 | struct net *net; | ||
528 | |||
529 | rtnl_lock(); | ||
530 | /* Step 1 - remove from bysource hash */ | ||
531 | clean.hash = true; | ||
532 | for_each_net(net) | ||
533 | nf_ct_iterate_cleanup(net, nf_nat_proto_clean, &clean); | ||
534 | synchronize_rcu(); | ||
487 | 535 | ||
488 | return 1; | 536 | /* Step 2 - clean NAT section */ |
537 | clean.hash = false; | ||
538 | for_each_net(net) | ||
539 | nf_ct_iterate_cleanup(net, nf_nat_proto_clean, &clean); | ||
540 | rtnl_unlock(); | ||
489 | } | 541 | } |
490 | EXPORT_SYMBOL_GPL(nf_nat_icmp_reply_translation); | ||
491 | 542 | ||
492 | /* Protocol registration. */ | 543 | /* Protocol registration. */ |
493 | int nf_nat_protocol_register(const struct nf_nat_protocol *proto) | 544 | int nf_nat_l4proto_register(u8 l3proto, const struct nf_nat_l4proto *l4proto) |
494 | { | 545 | { |
546 | const struct nf_nat_l4proto **l4protos; | ||
547 | unsigned int i; | ||
495 | int ret = 0; | 548 | int ret = 0; |
496 | 549 | ||
497 | spin_lock_bh(&nf_nat_lock); | 550 | mutex_lock(&nf_nat_proto_mutex); |
551 | if (nf_nat_l4protos[l3proto] == NULL) { | ||
552 | l4protos = kmalloc(IPPROTO_MAX * sizeof(struct nf_nat_l4proto *), | ||
553 | GFP_KERNEL); | ||
554 | if (l4protos == NULL) { | ||
555 | ret = -ENOMEM; | ||
556 | goto out; | ||
557 | } | ||
558 | |||
559 | for (i = 0; i < IPPROTO_MAX; i++) | ||
560 | RCU_INIT_POINTER(l4protos[i], &nf_nat_l4proto_unknown); | ||
561 | |||
562 | /* Before making proto_array visible to lockless readers, | ||
563 | * we must make sure its content is committed to memory. | ||
564 | */ | ||
565 | smp_wmb(); | ||
566 | |||
567 | nf_nat_l4protos[l3proto] = l4protos; | ||
568 | } | ||
569 | |||
498 | if (rcu_dereference_protected( | 570 | if (rcu_dereference_protected( |
499 | nf_nat_protos[proto->protonum], | 571 | nf_nat_l4protos[l3proto][l4proto->l4proto], |
500 | lockdep_is_held(&nf_nat_lock) | 572 | lockdep_is_held(&nf_nat_proto_mutex) |
501 | ) != &nf_nat_unknown_protocol) { | 573 | ) != &nf_nat_l4proto_unknown) { |
502 | ret = -EBUSY; | 574 | ret = -EBUSY; |
503 | goto out; | 575 | goto out; |
504 | } | 576 | } |
505 | RCU_INIT_POINTER(nf_nat_protos[proto->protonum], proto); | 577 | RCU_INIT_POINTER(nf_nat_l4protos[l3proto][l4proto->l4proto], l4proto); |
506 | out: | 578 | out: |
507 | spin_unlock_bh(&nf_nat_lock); | 579 | mutex_unlock(&nf_nat_proto_mutex); |
508 | return ret; | 580 | return ret; |
509 | } | 581 | } |
510 | EXPORT_SYMBOL(nf_nat_protocol_register); | 582 | EXPORT_SYMBOL_GPL(nf_nat_l4proto_register); |
511 | 583 | ||
512 | /* No one stores the protocol anywhere; simply delete it. */ | 584 | /* No one stores the protocol anywhere; simply delete it. */ |
513 | void nf_nat_protocol_unregister(const struct nf_nat_protocol *proto) | 585 | void nf_nat_l4proto_unregister(u8 l3proto, const struct nf_nat_l4proto *l4proto) |
514 | { | 586 | { |
515 | spin_lock_bh(&nf_nat_lock); | 587 | mutex_lock(&nf_nat_proto_mutex); |
516 | RCU_INIT_POINTER(nf_nat_protos[proto->protonum], | 588 | RCU_INIT_POINTER(nf_nat_l4protos[l3proto][l4proto->l4proto], |
517 | &nf_nat_unknown_protocol); | 589 | &nf_nat_l4proto_unknown); |
518 | spin_unlock_bh(&nf_nat_lock); | 590 | mutex_unlock(&nf_nat_proto_mutex); |
519 | synchronize_rcu(); | 591 | synchronize_rcu(); |
592 | |||
593 | nf_nat_l4proto_clean(l3proto, l4proto->l4proto); | ||
520 | } | 594 | } |
521 | EXPORT_SYMBOL(nf_nat_protocol_unregister); | 595 | EXPORT_SYMBOL_GPL(nf_nat_l4proto_unregister); |
596 | |||
597 | int nf_nat_l3proto_register(const struct nf_nat_l3proto *l3proto) | ||
598 | { | ||
599 | int err; | ||
600 | |||
601 | err = nf_ct_l3proto_try_module_get(l3proto->l3proto); | ||
602 | if (err < 0) | ||
603 | return err; | ||
604 | |||
605 | mutex_lock(&nf_nat_proto_mutex); | ||
606 | RCU_INIT_POINTER(nf_nat_l4protos[l3proto->l3proto][IPPROTO_TCP], | ||
607 | &nf_nat_l4proto_tcp); | ||
608 | RCU_INIT_POINTER(nf_nat_l4protos[l3proto->l3proto][IPPROTO_UDP], | ||
609 | &nf_nat_l4proto_udp); | ||
610 | mutex_unlock(&nf_nat_proto_mutex); | ||
611 | |||
612 | RCU_INIT_POINTER(nf_nat_l3protos[l3proto->l3proto], l3proto); | ||
613 | return 0; | ||
614 | } | ||
615 | EXPORT_SYMBOL_GPL(nf_nat_l3proto_register); | ||
616 | |||
617 | void nf_nat_l3proto_unregister(const struct nf_nat_l3proto *l3proto) | ||
618 | { | ||
619 | mutex_lock(&nf_nat_proto_mutex); | ||
620 | RCU_INIT_POINTER(nf_nat_l3protos[l3proto->l3proto], NULL); | ||
621 | mutex_unlock(&nf_nat_proto_mutex); | ||
622 | synchronize_rcu(); | ||
623 | |||
624 | nf_nat_l3proto_clean(l3proto->l3proto); | ||
625 | nf_ct_l3proto_module_put(l3proto->l3proto); | ||
626 | } | ||
627 | EXPORT_SYMBOL_GPL(nf_nat_l3proto_unregister); | ||
522 | 628 | ||
523 | /* No one using conntrack by the time this called. */ | 629 | /* No one using conntrack by the time this called. */ |
524 | static void nf_nat_cleanup_conntrack(struct nf_conn *ct) | 630 | static void nf_nat_cleanup_conntrack(struct nf_conn *ct) |
@@ -570,34 +676,36 @@ static const struct nla_policy protonat_nla_policy[CTA_PROTONAT_MAX+1] = { | |||
570 | 676 | ||
571 | static int nfnetlink_parse_nat_proto(struct nlattr *attr, | 677 | static int nfnetlink_parse_nat_proto(struct nlattr *attr, |
572 | const struct nf_conn *ct, | 678 | const struct nf_conn *ct, |
573 | struct nf_nat_ipv4_range *range) | 679 | struct nf_nat_range *range) |
574 | { | 680 | { |
575 | struct nlattr *tb[CTA_PROTONAT_MAX+1]; | 681 | struct nlattr *tb[CTA_PROTONAT_MAX+1]; |
576 | const struct nf_nat_protocol *npt; | 682 | const struct nf_nat_l4proto *l4proto; |
577 | int err; | 683 | int err; |
578 | 684 | ||
579 | err = nla_parse_nested(tb, CTA_PROTONAT_MAX, attr, protonat_nla_policy); | 685 | err = nla_parse_nested(tb, CTA_PROTONAT_MAX, attr, protonat_nla_policy); |
580 | if (err < 0) | 686 | if (err < 0) |
581 | return err; | 687 | return err; |
582 | 688 | ||
583 | rcu_read_lock(); | 689 | l4proto = __nf_nat_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct)); |
584 | npt = __nf_nat_proto_find(nf_ct_protonum(ct)); | 690 | if (l4proto->nlattr_to_range) |
585 | if (npt->nlattr_to_range) | 691 | err = l4proto->nlattr_to_range(tb, range); |
586 | err = npt->nlattr_to_range(tb, range); | 692 | |
587 | rcu_read_unlock(); | ||
588 | return err; | 693 | return err; |
589 | } | 694 | } |
590 | 695 | ||
591 | static const struct nla_policy nat_nla_policy[CTA_NAT_MAX+1] = { | 696 | static const struct nla_policy nat_nla_policy[CTA_NAT_MAX+1] = { |
592 | [CTA_NAT_MINIP] = { .type = NLA_U32 }, | 697 | [CTA_NAT_V4_MINIP] = { .type = NLA_U32 }, |
593 | [CTA_NAT_MAXIP] = { .type = NLA_U32 }, | 698 | [CTA_NAT_V4_MAXIP] = { .type = NLA_U32 }, |
699 | [CTA_NAT_V6_MINIP] = { .len = sizeof(struct in6_addr) }, | ||
700 | [CTA_NAT_V6_MAXIP] = { .len = sizeof(struct in6_addr) }, | ||
594 | [CTA_NAT_PROTO] = { .type = NLA_NESTED }, | 701 | [CTA_NAT_PROTO] = { .type = NLA_NESTED }, |
595 | }; | 702 | }; |
596 | 703 | ||
597 | static int | 704 | static int |
598 | nfnetlink_parse_nat(const struct nlattr *nat, | 705 | nfnetlink_parse_nat(const struct nlattr *nat, |
599 | const struct nf_conn *ct, struct nf_nat_ipv4_range *range) | 706 | const struct nf_conn *ct, struct nf_nat_range *range) |
600 | { | 707 | { |
708 | const struct nf_nat_l3proto *l3proto; | ||
601 | struct nlattr *tb[CTA_NAT_MAX+1]; | 709 | struct nlattr *tb[CTA_NAT_MAX+1]; |
602 | int err; | 710 | int err; |
603 | 711 | ||
@@ -607,25 +715,23 @@ nfnetlink_parse_nat(const struct nlattr *nat, | |||
607 | if (err < 0) | 715 | if (err < 0) |
608 | return err; | 716 | return err; |
609 | 717 | ||
610 | if (tb[CTA_NAT_MINIP]) | 718 | rcu_read_lock(); |
611 | range->min_ip = nla_get_be32(tb[CTA_NAT_MINIP]); | 719 | l3proto = __nf_nat_l3proto_find(nf_ct_l3num(ct)); |
612 | 720 | if (l3proto == NULL) { | |
613 | if (!tb[CTA_NAT_MAXIP]) | 721 | err = -EAGAIN; |
614 | range->max_ip = range->min_ip; | 722 | goto out; |
615 | else | 723 | } |
616 | range->max_ip = nla_get_be32(tb[CTA_NAT_MAXIP]); | 724 | err = l3proto->nlattr_to_range(tb, range); |
617 | 725 | if (err < 0) | |
618 | if (range->min_ip) | 726 | goto out; |
619 | range->flags |= NF_NAT_RANGE_MAP_IPS; | ||
620 | 727 | ||
621 | if (!tb[CTA_NAT_PROTO]) | 728 | if (!tb[CTA_NAT_PROTO]) |
622 | return 0; | 729 | goto out; |
623 | 730 | ||
624 | err = nfnetlink_parse_nat_proto(tb[CTA_NAT_PROTO], ct, range); | 731 | err = nfnetlink_parse_nat_proto(tb[CTA_NAT_PROTO], ct, range); |
625 | if (err < 0) | 732 | out: |
626 | return err; | 733 | rcu_read_unlock(); |
627 | 734 | return err; | |
628 | return 0; | ||
629 | } | 735 | } |
630 | 736 | ||
631 | static int | 737 | static int |
@@ -633,10 +739,12 @@ nfnetlink_parse_nat_setup(struct nf_conn *ct, | |||
633 | enum nf_nat_manip_type manip, | 739 | enum nf_nat_manip_type manip, |
634 | const struct nlattr *attr) | 740 | const struct nlattr *attr) |
635 | { | 741 | { |
636 | struct nf_nat_ipv4_range range; | 742 | struct nf_nat_range range; |
743 | int err; | ||
637 | 744 | ||
638 | if (nfnetlink_parse_nat(attr, ct, &range) < 0) | 745 | err = nfnetlink_parse_nat(attr, ct, &range); |
639 | return -EINVAL; | 746 | if (err < 0) |
747 | return err; | ||
640 | if (nf_nat_initialized(ct, manip)) | 748 | if (nf_nat_initialized(ct, manip)) |
641 | return -EEXIST; | 749 | return -EEXIST; |
642 | 750 | ||
@@ -655,30 +763,20 @@ nfnetlink_parse_nat_setup(struct nf_conn *ct, | |||
655 | static int __net_init nf_nat_net_init(struct net *net) | 763 | static int __net_init nf_nat_net_init(struct net *net) |
656 | { | 764 | { |
657 | /* Leave them the same for the moment. */ | 765 | /* Leave them the same for the moment. */ |
658 | net->ipv4.nat_htable_size = net->ct.htable_size; | 766 | net->ct.nat_htable_size = net->ct.htable_size; |
659 | net->ipv4.nat_bysource = nf_ct_alloc_hashtable(&net->ipv4.nat_htable_size, 0); | 767 | net->ct.nat_bysource = nf_ct_alloc_hashtable(&net->ct.nat_htable_size, 0); |
660 | if (!net->ipv4.nat_bysource) | 768 | if (!net->ct.nat_bysource) |
661 | return -ENOMEM; | 769 | return -ENOMEM; |
662 | return 0; | 770 | return 0; |
663 | } | 771 | } |
664 | 772 | ||
665 | /* Clear NAT section of all conntracks, in case we're loaded again. */ | ||
666 | static int clean_nat(struct nf_conn *i, void *data) | ||
667 | { | ||
668 | struct nf_conn_nat *nat = nfct_nat(i); | ||
669 | |||
670 | if (!nat) | ||
671 | return 0; | ||
672 | memset(nat, 0, sizeof(*nat)); | ||
673 | i->status &= ~(IPS_NAT_MASK | IPS_NAT_DONE_MASK | IPS_SEQ_ADJUST); | ||
674 | return 0; | ||
675 | } | ||
676 | |||
677 | static void __net_exit nf_nat_net_exit(struct net *net) | 773 | static void __net_exit nf_nat_net_exit(struct net *net) |
678 | { | 774 | { |
679 | nf_ct_iterate_cleanup(net, &clean_nat, NULL); | 775 | struct nf_nat_proto_clean clean = {}; |
776 | |||
777 | nf_ct_iterate_cleanup(net, &nf_nat_proto_clean, &clean); | ||
680 | synchronize_rcu(); | 778 | synchronize_rcu(); |
681 | nf_ct_free_hashtable(net->ipv4.nat_bysource, net->ipv4.nat_htable_size); | 779 | nf_ct_free_hashtable(net->ct.nat_bysource, net->ct.nat_htable_size); |
682 | } | 780 | } |
683 | 781 | ||
684 | static struct pernet_operations nf_nat_net_ops = { | 782 | static struct pernet_operations nf_nat_net_ops = { |
@@ -697,11 +795,8 @@ static struct nfq_ct_nat_hook nfq_ct_nat = { | |||
697 | 795 | ||
698 | static int __init nf_nat_init(void) | 796 | static int __init nf_nat_init(void) |
699 | { | 797 | { |
700 | size_t i; | ||
701 | int ret; | 798 | int ret; |
702 | 799 | ||
703 | need_ipv4_conntrack(); | ||
704 | |||
705 | ret = nf_ct_extend_register(&nat_extend); | 800 | ret = nf_ct_extend_register(&nat_extend); |
706 | if (ret < 0) { | 801 | if (ret < 0) { |
707 | printk(KERN_ERR "nf_nat_core: Unable to register extension\n"); | 802 | printk(KERN_ERR "nf_nat_core: Unable to register extension\n"); |
@@ -712,22 +807,11 @@ static int __init nf_nat_init(void) | |||
712 | if (ret < 0) | 807 | if (ret < 0) |
713 | goto cleanup_extend; | 808 | goto cleanup_extend; |
714 | 809 | ||
715 | /* Sew in builtin protocols. */ | 810 | nf_ct_helper_expectfn_register(&follow_master_nat); |
716 | spin_lock_bh(&nf_nat_lock); | ||
717 | for (i = 0; i < MAX_IP_NAT_PROTO; i++) | ||
718 | RCU_INIT_POINTER(nf_nat_protos[i], &nf_nat_unknown_protocol); | ||
719 | RCU_INIT_POINTER(nf_nat_protos[IPPROTO_TCP], &nf_nat_protocol_tcp); | ||
720 | RCU_INIT_POINTER(nf_nat_protos[IPPROTO_UDP], &nf_nat_protocol_udp); | ||
721 | RCU_INIT_POINTER(nf_nat_protos[IPPROTO_ICMP], &nf_nat_protocol_icmp); | ||
722 | spin_unlock_bh(&nf_nat_lock); | ||
723 | 811 | ||
724 | /* Initialize fake conntrack so that NAT will skip it */ | 812 | /* Initialize fake conntrack so that NAT will skip it */ |
725 | nf_ct_untracked_status_or(IPS_NAT_DONE_MASK); | 813 | nf_ct_untracked_status_or(IPS_NAT_DONE_MASK); |
726 | 814 | ||
727 | l3proto = nf_ct_l3proto_find_get((u_int16_t)AF_INET); | ||
728 | |||
729 | nf_ct_helper_expectfn_register(&follow_master_nat); | ||
730 | |||
731 | BUG_ON(nf_nat_seq_adjust_hook != NULL); | 815 | BUG_ON(nf_nat_seq_adjust_hook != NULL); |
732 | RCU_INIT_POINTER(nf_nat_seq_adjust_hook, nf_nat_seq_adjust); | 816 | RCU_INIT_POINTER(nf_nat_seq_adjust_hook, nf_nat_seq_adjust); |
733 | BUG_ON(nfnetlink_parse_nat_setup_hook != NULL); | 817 | BUG_ON(nfnetlink_parse_nat_setup_hook != NULL); |
@@ -736,6 +820,10 @@ static int __init nf_nat_init(void) | |||
736 | BUG_ON(nf_ct_nat_offset != NULL); | 820 | BUG_ON(nf_ct_nat_offset != NULL); |
737 | RCU_INIT_POINTER(nf_ct_nat_offset, nf_nat_get_offset); | 821 | RCU_INIT_POINTER(nf_ct_nat_offset, nf_nat_get_offset); |
738 | RCU_INIT_POINTER(nfq_ct_nat_hook, &nfq_ct_nat); | 822 | RCU_INIT_POINTER(nfq_ct_nat_hook, &nfq_ct_nat); |
823 | #ifdef CONFIG_XFRM | ||
824 | BUG_ON(nf_nat_decode_session_hook != NULL); | ||
825 | RCU_INIT_POINTER(nf_nat_decode_session_hook, __nf_nat_decode_session); | ||
826 | #endif | ||
739 | return 0; | 827 | return 0; |
740 | 828 | ||
741 | cleanup_extend: | 829 | cleanup_extend: |
@@ -745,19 +833,24 @@ static int __init nf_nat_init(void) | |||
745 | 833 | ||
746 | static void __exit nf_nat_cleanup(void) | 834 | static void __exit nf_nat_cleanup(void) |
747 | { | 835 | { |
836 | unsigned int i; | ||
837 | |||
748 | unregister_pernet_subsys(&nf_nat_net_ops); | 838 | unregister_pernet_subsys(&nf_nat_net_ops); |
749 | nf_ct_l3proto_put(l3proto); | ||
750 | nf_ct_extend_unregister(&nat_extend); | 839 | nf_ct_extend_unregister(&nat_extend); |
751 | nf_ct_helper_expectfn_unregister(&follow_master_nat); | 840 | nf_ct_helper_expectfn_unregister(&follow_master_nat); |
752 | RCU_INIT_POINTER(nf_nat_seq_adjust_hook, NULL); | 841 | RCU_INIT_POINTER(nf_nat_seq_adjust_hook, NULL); |
753 | RCU_INIT_POINTER(nfnetlink_parse_nat_setup_hook, NULL); | 842 | RCU_INIT_POINTER(nfnetlink_parse_nat_setup_hook, NULL); |
754 | RCU_INIT_POINTER(nf_ct_nat_offset, NULL); | 843 | RCU_INIT_POINTER(nf_ct_nat_offset, NULL); |
755 | RCU_INIT_POINTER(nfq_ct_nat_hook, NULL); | 844 | RCU_INIT_POINTER(nfq_ct_nat_hook, NULL); |
845 | #ifdef CONFIG_XFRM | ||
846 | RCU_INIT_POINTER(nf_nat_decode_session_hook, NULL); | ||
847 | #endif | ||
848 | for (i = 0; i < NFPROTO_NUMPROTO; i++) | ||
849 | kfree(nf_nat_l4protos[i]); | ||
756 | synchronize_net(); | 850 | synchronize_net(); |
757 | } | 851 | } |
758 | 852 | ||
759 | MODULE_LICENSE("GPL"); | 853 | MODULE_LICENSE("GPL"); |
760 | MODULE_ALIAS("nf-nat-ipv4"); | ||
761 | 854 | ||
762 | module_init(nf_nat_init); | 855 | module_init(nf_nat_init); |
763 | module_exit(nf_nat_cleanup); | 856 | module_exit(nf_nat_cleanup); |
diff --git a/net/ipv4/netfilter/nf_nat_ftp.c b/net/netfilter/nf_nat_ftp.c index e462a957d080..e839b97b2863 100644 --- a/net/ipv4/netfilter/nf_nat_ftp.c +++ b/net/netfilter/nf_nat_ftp.c | |||
@@ -10,12 +10,11 @@ | |||
10 | 10 | ||
11 | #include <linux/module.h> | 11 | #include <linux/module.h> |
12 | #include <linux/moduleparam.h> | 12 | #include <linux/moduleparam.h> |
13 | #include <linux/ip.h> | 13 | #include <linux/inet.h> |
14 | #include <linux/tcp.h> | 14 | #include <linux/tcp.h> |
15 | #include <linux/netfilter_ipv4.h> | 15 | #include <linux/netfilter_ipv4.h> |
16 | #include <net/netfilter/nf_nat.h> | 16 | #include <net/netfilter/nf_nat.h> |
17 | #include <net/netfilter/nf_nat_helper.h> | 17 | #include <net/netfilter/nf_nat_helper.h> |
18 | #include <net/netfilter/nf_nat_rule.h> | ||
19 | #include <net/netfilter/nf_conntrack_helper.h> | 18 | #include <net/netfilter/nf_conntrack_helper.h> |
20 | #include <net/netfilter/nf_conntrack_expect.h> | 19 | #include <net/netfilter/nf_conntrack_expect.h> |
21 | #include <linux/netfilter/nf_conntrack_ftp.h> | 20 | #include <linux/netfilter/nf_conntrack_ftp.h> |
@@ -27,22 +26,27 @@ MODULE_ALIAS("ip_nat_ftp"); | |||
27 | 26 | ||
28 | /* FIXME: Time out? --RR */ | 27 | /* FIXME: Time out? --RR */ |
29 | 28 | ||
30 | static int nf_nat_ftp_fmt_cmd(enum nf_ct_ftp_type type, | 29 | static int nf_nat_ftp_fmt_cmd(struct nf_conn *ct, enum nf_ct_ftp_type type, |
31 | char *buffer, size_t buflen, | 30 | char *buffer, size_t buflen, |
32 | __be32 addr, u16 port) | 31 | union nf_inet_addr *addr, u16 port) |
33 | { | 32 | { |
34 | switch (type) { | 33 | switch (type) { |
35 | case NF_CT_FTP_PORT: | 34 | case NF_CT_FTP_PORT: |
36 | case NF_CT_FTP_PASV: | 35 | case NF_CT_FTP_PASV: |
37 | return snprintf(buffer, buflen, "%u,%u,%u,%u,%u,%u", | 36 | return snprintf(buffer, buflen, "%u,%u,%u,%u,%u,%u", |
38 | ((unsigned char *)&addr)[0], | 37 | ((unsigned char *)&addr->ip)[0], |
39 | ((unsigned char *)&addr)[1], | 38 | ((unsigned char *)&addr->ip)[1], |
40 | ((unsigned char *)&addr)[2], | 39 | ((unsigned char *)&addr->ip)[2], |
41 | ((unsigned char *)&addr)[3], | 40 | ((unsigned char *)&addr->ip)[3], |
42 | port >> 8, | 41 | port >> 8, |
43 | port & 0xFF); | 42 | port & 0xFF); |
44 | case NF_CT_FTP_EPRT: | 43 | case NF_CT_FTP_EPRT: |
45 | return snprintf(buffer, buflen, "|1|%pI4|%u|", &addr, port); | 44 | if (nf_ct_l3num(ct) == NFPROTO_IPV4) |
45 | return snprintf(buffer, buflen, "|1|%pI4|%u|", | ||
46 | &addr->ip, port); | ||
47 | else | ||
48 | return snprintf(buffer, buflen, "|2|%pI6|%u|", | ||
49 | &addr->ip6, port); | ||
46 | case NF_CT_FTP_EPSV: | 50 | case NF_CT_FTP_EPSV: |
47 | return snprintf(buffer, buflen, "|||%u|", port); | 51 | return snprintf(buffer, buflen, "|||%u|", port); |
48 | } | 52 | } |
@@ -55,21 +59,22 @@ static int nf_nat_ftp_fmt_cmd(enum nf_ct_ftp_type type, | |||
55 | static unsigned int nf_nat_ftp(struct sk_buff *skb, | 59 | static unsigned int nf_nat_ftp(struct sk_buff *skb, |
56 | enum ip_conntrack_info ctinfo, | 60 | enum ip_conntrack_info ctinfo, |
57 | enum nf_ct_ftp_type type, | 61 | enum nf_ct_ftp_type type, |
62 | unsigned int protoff, | ||
58 | unsigned int matchoff, | 63 | unsigned int matchoff, |
59 | unsigned int matchlen, | 64 | unsigned int matchlen, |
60 | struct nf_conntrack_expect *exp) | 65 | struct nf_conntrack_expect *exp) |
61 | { | 66 | { |
62 | __be32 newip; | 67 | union nf_inet_addr newaddr; |
63 | u_int16_t port; | 68 | u_int16_t port; |
64 | int dir = CTINFO2DIR(ctinfo); | 69 | int dir = CTINFO2DIR(ctinfo); |
65 | struct nf_conn *ct = exp->master; | 70 | struct nf_conn *ct = exp->master; |
66 | char buffer[sizeof("|1|255.255.255.255|65535|")]; | 71 | char buffer[sizeof("|1||65535|") + INET6_ADDRSTRLEN]; |
67 | unsigned int buflen; | 72 | unsigned int buflen; |
68 | 73 | ||
69 | pr_debug("FTP_NAT: type %i, off %u len %u\n", type, matchoff, matchlen); | 74 | pr_debug("FTP_NAT: type %i, off %u len %u\n", type, matchoff, matchlen); |
70 | 75 | ||
71 | /* Connection will come from wherever this packet goes, hence !dir */ | 76 | /* Connection will come from wherever this packet goes, hence !dir */ |
72 | newip = ct->tuplehash[!dir].tuple.dst.u3.ip; | 77 | newaddr = ct->tuplehash[!dir].tuple.dst.u3; |
73 | exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port; | 78 | exp->saved_proto.tcp.port = exp->tuple.dst.u.tcp.port; |
74 | exp->dir = !dir; | 79 | exp->dir = !dir; |
75 | 80 | ||
@@ -94,13 +99,14 @@ static unsigned int nf_nat_ftp(struct sk_buff *skb, | |||
94 | if (port == 0) | 99 | if (port == 0) |
95 | return NF_DROP; | 100 | return NF_DROP; |
96 | 101 | ||
97 | buflen = nf_nat_ftp_fmt_cmd(type, buffer, sizeof(buffer), newip, port); | 102 | buflen = nf_nat_ftp_fmt_cmd(ct, type, buffer, sizeof(buffer), |
103 | &newaddr, port); | ||
98 | if (!buflen) | 104 | if (!buflen) |
99 | goto out; | 105 | goto out; |
100 | 106 | ||
101 | pr_debug("calling nf_nat_mangle_tcp_packet\n"); | 107 | pr_debug("calling nf_nat_mangle_tcp_packet\n"); |
102 | 108 | ||
103 | if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, matchoff, | 109 | if (!nf_nat_mangle_tcp_packet(skb, ct, ctinfo, protoff, matchoff, |
104 | matchlen, buffer, buflen)) | 110 | matchlen, buffer, buflen)) |
105 | goto out; | 111 | goto out; |
106 | 112 | ||
diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/netfilter/nf_nat_helper.c index 2e59ad0b90ca..23c2b38676a6 100644 --- a/net/ipv4/netfilter/nf_nat_helper.c +++ b/net/netfilter/nf_nat_helper.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* ip_nat_helper.c - generic support functions for NAT helpers | 1 | /* nf_nat_helper.c - generic support functions for NAT helpers |
2 | * | 2 | * |
3 | * (C) 2000-2002 Harald Welte <laforge@netfilter.org> | 3 | * (C) 2000-2002 Harald Welte <laforge@netfilter.org> |
4 | * (C) 2003-2006 Netfilter Core Team <coreteam@netfilter.org> | 4 | * (C) 2003-2006 Netfilter Core Team <coreteam@netfilter.org> |
@@ -9,23 +9,19 @@ | |||
9 | */ | 9 | */ |
10 | #include <linux/module.h> | 10 | #include <linux/module.h> |
11 | #include <linux/gfp.h> | 11 | #include <linux/gfp.h> |
12 | #include <linux/kmod.h> | ||
13 | #include <linux/types.h> | 12 | #include <linux/types.h> |
14 | #include <linux/timer.h> | ||
15 | #include <linux/skbuff.h> | 13 | #include <linux/skbuff.h> |
16 | #include <linux/tcp.h> | 14 | #include <linux/tcp.h> |
17 | #include <linux/udp.h> | 15 | #include <linux/udp.h> |
18 | #include <net/checksum.h> | ||
19 | #include <net/tcp.h> | 16 | #include <net/tcp.h> |
20 | #include <net/route.h> | ||
21 | 17 | ||
22 | #include <linux/netfilter_ipv4.h> | ||
23 | #include <net/netfilter/nf_conntrack.h> | 18 | #include <net/netfilter/nf_conntrack.h> |
24 | #include <net/netfilter/nf_conntrack_helper.h> | 19 | #include <net/netfilter/nf_conntrack_helper.h> |
25 | #include <net/netfilter/nf_conntrack_ecache.h> | 20 | #include <net/netfilter/nf_conntrack_ecache.h> |
26 | #include <net/netfilter/nf_conntrack_expect.h> | 21 | #include <net/netfilter/nf_conntrack_expect.h> |
27 | #include <net/netfilter/nf_nat.h> | 22 | #include <net/netfilter/nf_nat.h> |
28 | #include <net/netfilter/nf_nat_protocol.h> | 23 | #include <net/netfilter/nf_nat_l3proto.h> |
24 | #include <net/netfilter/nf_nat_l4proto.h> | ||
29 | #include <net/netfilter/nf_nat_core.h> | 25 | #include <net/netfilter/nf_nat_core.h> |
30 | #include <net/netfilter/nf_nat_helper.h> | 26 | #include <net/netfilter/nf_nat_helper.h> |
31 | 27 | ||
@@ -90,7 +86,6 @@ s16 nf_nat_get_offset(const struct nf_conn *ct, | |||
90 | 86 | ||
91 | return offset; | 87 | return offset; |
92 | } | 88 | } |
93 | EXPORT_SYMBOL_GPL(nf_nat_get_offset); | ||
94 | 89 | ||
95 | /* Frobs data inside this packet, which is linear. */ | 90 | /* Frobs data inside this packet, which is linear. */ |
96 | static void mangle_contents(struct sk_buff *skb, | 91 | static void mangle_contents(struct sk_buff *skb, |
@@ -125,9 +120,13 @@ static void mangle_contents(struct sk_buff *skb, | |||
125 | __skb_trim(skb, skb->len + rep_len - match_len); | 120 | __skb_trim(skb, skb->len + rep_len - match_len); |
126 | } | 121 | } |
127 | 122 | ||
128 | /* fix IP hdr checksum information */ | 123 | if (nf_ct_l3num((struct nf_conn *)skb->nfct) == NFPROTO_IPV4) { |
129 | ip_hdr(skb)->tot_len = htons(skb->len); | 124 | /* fix IP hdr checksum information */ |
130 | ip_send_check(ip_hdr(skb)); | 125 | ip_hdr(skb)->tot_len = htons(skb->len); |
126 | ip_send_check(ip_hdr(skb)); | ||
127 | } else | ||
128 | ipv6_hdr(skb)->payload_len = | ||
129 | htons(skb->len - sizeof(struct ipv6hdr)); | ||
131 | } | 130 | } |
132 | 131 | ||
133 | /* Unusual, but possible case. */ | 132 | /* Unusual, but possible case. */ |
@@ -166,35 +165,6 @@ void nf_nat_tcp_seq_adjust(struct sk_buff *skb, struct nf_conn *ct, | |||
166 | } | 165 | } |
167 | EXPORT_SYMBOL_GPL(nf_nat_tcp_seq_adjust); | 166 | EXPORT_SYMBOL_GPL(nf_nat_tcp_seq_adjust); |
168 | 167 | ||
169 | static void nf_nat_csum(struct sk_buff *skb, const struct iphdr *iph, void *data, | ||
170 | int datalen, __sum16 *check, int oldlen) | ||
171 | { | ||
172 | struct rtable *rt = skb_rtable(skb); | ||
173 | |||
174 | if (skb->ip_summed != CHECKSUM_PARTIAL) { | ||
175 | if (!(rt->rt_flags & RTCF_LOCAL) && | ||
176 | (!skb->dev || skb->dev->features & NETIF_F_V4_CSUM)) { | ||
177 | skb->ip_summed = CHECKSUM_PARTIAL; | ||
178 | skb->csum_start = skb_headroom(skb) + | ||
179 | skb_network_offset(skb) + | ||
180 | iph->ihl * 4; | ||
181 | skb->csum_offset = (void *)check - data; | ||
182 | *check = ~csum_tcpudp_magic(iph->saddr, iph->daddr, | ||
183 | datalen, iph->protocol, 0); | ||
184 | } else { | ||
185 | *check = 0; | ||
186 | *check = csum_tcpudp_magic(iph->saddr, iph->daddr, | ||
187 | datalen, iph->protocol, | ||
188 | csum_partial(data, datalen, | ||
189 | 0)); | ||
190 | if (iph->protocol == IPPROTO_UDP && !*check) | ||
191 | *check = CSUM_MANGLED_0; | ||
192 | } | ||
193 | } else | ||
194 | inet_proto_csum_replace2(check, skb, | ||
195 | htons(oldlen), htons(datalen), 1); | ||
196 | } | ||
197 | |||
198 | /* Generic function for mangling variable-length address changes inside | 168 | /* Generic function for mangling variable-length address changes inside |
199 | * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX | 169 | * NATed TCP connections (like the PORT XXX,XXX,XXX,XXX,XXX,XXX |
200 | * command in FTP). | 170 | * command in FTP). |
@@ -206,12 +176,13 @@ static void nf_nat_csum(struct sk_buff *skb, const struct iphdr *iph, void *data | |||
206 | int __nf_nat_mangle_tcp_packet(struct sk_buff *skb, | 176 | int __nf_nat_mangle_tcp_packet(struct sk_buff *skb, |
207 | struct nf_conn *ct, | 177 | struct nf_conn *ct, |
208 | enum ip_conntrack_info ctinfo, | 178 | enum ip_conntrack_info ctinfo, |
179 | unsigned int protoff, | ||
209 | unsigned int match_offset, | 180 | unsigned int match_offset, |
210 | unsigned int match_len, | 181 | unsigned int match_len, |
211 | const char *rep_buffer, | 182 | const char *rep_buffer, |
212 | unsigned int rep_len, bool adjust) | 183 | unsigned int rep_len, bool adjust) |
213 | { | 184 | { |
214 | struct iphdr *iph; | 185 | const struct nf_nat_l3proto *l3proto; |
215 | struct tcphdr *tcph; | 186 | struct tcphdr *tcph; |
216 | int oldlen, datalen; | 187 | int oldlen, datalen; |
217 | 188 | ||
@@ -225,15 +196,17 @@ int __nf_nat_mangle_tcp_packet(struct sk_buff *skb, | |||
225 | 196 | ||
226 | SKB_LINEAR_ASSERT(skb); | 197 | SKB_LINEAR_ASSERT(skb); |
227 | 198 | ||
228 | iph = ip_hdr(skb); | 199 | tcph = (void *)skb->data + protoff; |
229 | tcph = (void *)iph + iph->ihl*4; | ||
230 | 200 | ||
231 | oldlen = skb->len - iph->ihl*4; | 201 | oldlen = skb->len - protoff; |
232 | mangle_contents(skb, iph->ihl*4 + tcph->doff*4, | 202 | mangle_contents(skb, protoff + tcph->doff*4, |
233 | match_offset, match_len, rep_buffer, rep_len); | 203 | match_offset, match_len, rep_buffer, rep_len); |
234 | 204 | ||
235 | datalen = skb->len - iph->ihl*4; | 205 | datalen = skb->len - protoff; |
236 | nf_nat_csum(skb, iph, tcph, datalen, &tcph->check, oldlen); | 206 | |
207 | l3proto = __nf_nat_l3proto_find(nf_ct_l3num(ct)); | ||
208 | l3proto->csum_recalc(skb, IPPROTO_TCP, tcph, &tcph->check, | ||
209 | datalen, oldlen); | ||
237 | 210 | ||
238 | if (adjust && rep_len != match_len) | 211 | if (adjust && rep_len != match_len) |
239 | nf_nat_set_seq_adjust(ct, ctinfo, tcph->seq, | 212 | nf_nat_set_seq_adjust(ct, ctinfo, tcph->seq, |
@@ -257,12 +230,13 @@ int | |||
257 | nf_nat_mangle_udp_packet(struct sk_buff *skb, | 230 | nf_nat_mangle_udp_packet(struct sk_buff *skb, |
258 | struct nf_conn *ct, | 231 | struct nf_conn *ct, |
259 | enum ip_conntrack_info ctinfo, | 232 | enum ip_conntrack_info ctinfo, |
233 | unsigned int protoff, | ||
260 | unsigned int match_offset, | 234 | unsigned int match_offset, |
261 | unsigned int match_len, | 235 | unsigned int match_len, |
262 | const char *rep_buffer, | 236 | const char *rep_buffer, |
263 | unsigned int rep_len) | 237 | unsigned int rep_len) |
264 | { | 238 | { |
265 | struct iphdr *iph; | 239 | const struct nf_nat_l3proto *l3proto; |
266 | struct udphdr *udph; | 240 | struct udphdr *udph; |
267 | int datalen, oldlen; | 241 | int datalen, oldlen; |
268 | 242 | ||
@@ -274,22 +248,23 @@ nf_nat_mangle_udp_packet(struct sk_buff *skb, | |||
274 | !enlarge_skb(skb, rep_len - match_len)) | 248 | !enlarge_skb(skb, rep_len - match_len)) |
275 | return 0; | 249 | return 0; |
276 | 250 | ||
277 | iph = ip_hdr(skb); | 251 | udph = (void *)skb->data + protoff; |
278 | udph = (void *)iph + iph->ihl*4; | ||
279 | 252 | ||
280 | oldlen = skb->len - iph->ihl*4; | 253 | oldlen = skb->len - protoff; |
281 | mangle_contents(skb, iph->ihl*4 + sizeof(*udph), | 254 | mangle_contents(skb, protoff + sizeof(*udph), |
282 | match_offset, match_len, rep_buffer, rep_len); | 255 | match_offset, match_len, rep_buffer, rep_len); |
283 | 256 | ||
284 | /* update the length of the UDP packet */ | 257 | /* update the length of the UDP packet */ |
285 | datalen = skb->len - iph->ihl*4; | 258 | datalen = skb->len - protoff; |
286 | udph->len = htons(datalen); | 259 | udph->len = htons(datalen); |
287 | 260 | ||
288 | /* fix udp checksum if udp checksum was previously calculated */ | 261 | /* fix udp checksum if udp checksum was previously calculated */ |
289 | if (!udph->check && skb->ip_summed != CHECKSUM_PARTIAL) | 262 | if (!udph->check && skb->ip_summed != CHECKSUM_PARTIAL) |
290 | return 1; | 263 | return 1; |
291 | 264 | ||
292 | nf_nat_csum(skb, iph, udph, datalen, &udph->check, oldlen); | 265 | l3proto = __nf_nat_l3proto_find(nf_ct_l3num(ct)); |
266 | l3proto->csum_recalc(skb, IPPROTO_UDP, udph, &udph->check, | ||
267 | datalen, oldlen); | ||
293 | 268 | ||
294 | return 1; | 269 | return 1; |
295 | } | 270 | } |
@@ -341,6 +316,7 @@ sack_adjust(struct sk_buff *skb, | |||
341 | /* TCP SACK sequence number adjustment */ | 316 | /* TCP SACK sequence number adjustment */ |
342 | static inline unsigned int | 317 | static inline unsigned int |
343 | nf_nat_sack_adjust(struct sk_buff *skb, | 318 | nf_nat_sack_adjust(struct sk_buff *skb, |
319 | unsigned int protoff, | ||
344 | struct tcphdr *tcph, | 320 | struct tcphdr *tcph, |
345 | struct nf_conn *ct, | 321 | struct nf_conn *ct, |
346 | enum ip_conntrack_info ctinfo) | 322 | enum ip_conntrack_info ctinfo) |
@@ -348,8 +324,8 @@ nf_nat_sack_adjust(struct sk_buff *skb, | |||
348 | unsigned int dir, optoff, optend; | 324 | unsigned int dir, optoff, optend; |
349 | struct nf_conn_nat *nat = nfct_nat(ct); | 325 | struct nf_conn_nat *nat = nfct_nat(ct); |
350 | 326 | ||
351 | optoff = ip_hdrlen(skb) + sizeof(struct tcphdr); | 327 | optoff = protoff + sizeof(struct tcphdr); |
352 | optend = ip_hdrlen(skb) + tcph->doff * 4; | 328 | optend = protoff + tcph->doff * 4; |
353 | 329 | ||
354 | if (!skb_make_writable(skb, optend)) | 330 | if (!skb_make_writable(skb, optend)) |
355 | return 0; | 331 | return 0; |
@@ -387,7 +363,8 @@ nf_nat_sack_adjust(struct sk_buff *skb, | |||
387 | int | 363 | int |
388 | nf_nat_seq_adjust(struct sk_buff *skb, | 364 | nf_nat_seq_adjust(struct sk_buff *skb, |
389 | struct nf_conn *ct, | 365 | struct nf_conn *ct, |
390 | enum ip_conntrack_info ctinfo) | 366 | enum ip_conntrack_info ctinfo, |
367 | unsigned int protoff) | ||
391 | { | 368 | { |
392 | struct tcphdr *tcph; | 369 | struct tcphdr *tcph; |
393 | int dir; | 370 | int dir; |
@@ -401,10 +378,10 @@ nf_nat_seq_adjust(struct sk_buff *skb, | |||
401 | this_way = &nat->seq[dir]; | 378 | this_way = &nat->seq[dir]; |
402 | other_way = &nat->seq[!dir]; | 379 | other_way = &nat->seq[!dir]; |
403 | 380 | ||
404 | if (!skb_make_writable(skb, ip_hdrlen(skb) + sizeof(*tcph))) | 381 | if (!skb_make_writable(skb, protoff + sizeof(*tcph))) |
405 | return 0; | 382 | return 0; |
406 | 383 | ||
407 | tcph = (void *)skb->data + ip_hdrlen(skb); | 384 | tcph = (void *)skb->data + protoff; |
408 | if (after(ntohl(tcph->seq), this_way->correction_pos)) | 385 | if (after(ntohl(tcph->seq), this_way->correction_pos)) |
409 | seqoff = this_way->offset_after; | 386 | seqoff = this_way->offset_after; |
410 | else | 387 | else |
@@ -429,7 +406,7 @@ nf_nat_seq_adjust(struct sk_buff *skb, | |||
429 | tcph->seq = newseq; | 406 | tcph->seq = newseq; |
430 | tcph->ack_seq = newack; | 407 | tcph->ack_seq = newack; |
431 | 408 | ||
432 | return nf_nat_sack_adjust(skb, tcph, ct, ctinfo); | 409 | return nf_nat_sack_adjust(skb, protoff, tcph, ct, ctinfo); |
433 | } | 410 | } |
434 | 411 | ||
435 | /* Setup NAT on this expected conntrack so it follows master. */ | 412 | /* Setup NAT on this expected conntrack so it follows master. */ |
@@ -437,22 +414,22 @@ nf_nat_seq_adjust(struct sk_buff *skb, | |||
437 | void nf_nat_follow_master(struct nf_conn *ct, | 414 | void nf_nat_follow_master(struct nf_conn *ct, |
438 | struct nf_conntrack_expect *exp) | 415 | struct nf_conntrack_expect *exp) |
439 | { | 416 | { |
440 | struct nf_nat_ipv4_range range; | 417 | struct nf_nat_range range; |
441 | 418 | ||
442 | /* This must be a fresh one. */ | 419 | /* This must be a fresh one. */ |
443 | BUG_ON(ct->status & IPS_NAT_DONE_MASK); | 420 | BUG_ON(ct->status & IPS_NAT_DONE_MASK); |
444 | 421 | ||
445 | /* Change src to where master sends to */ | 422 | /* Change src to where master sends to */ |
446 | range.flags = NF_NAT_RANGE_MAP_IPS; | 423 | range.flags = NF_NAT_RANGE_MAP_IPS; |
447 | range.min_ip = range.max_ip | 424 | range.min_addr = range.max_addr |
448 | = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip; | 425 | = ct->master->tuplehash[!exp->dir].tuple.dst.u3; |
449 | nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC); | 426 | nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC); |
450 | 427 | ||
451 | /* For DST manip, map port here to where it's expected. */ | 428 | /* For DST manip, map port here to where it's expected. */ |
452 | range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED); | 429 | range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED); |
453 | range.min = range.max = exp->saved_proto; | 430 | range.min_proto = range.max_proto = exp->saved_proto; |
454 | range.min_ip = range.max_ip | 431 | range.min_addr = range.max_addr |
455 | = ct->master->tuplehash[!exp->dir].tuple.src.u3.ip; | 432 | = ct->master->tuplehash[!exp->dir].tuple.src.u3; |
456 | nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST); | 433 | nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST); |
457 | } | 434 | } |
458 | EXPORT_SYMBOL(nf_nat_follow_master); | 435 | EXPORT_SYMBOL(nf_nat_follow_master); |
diff --git a/net/ipv4/netfilter/nf_nat_irc.c b/net/netfilter/nf_nat_irc.c index 979ae165f4ef..1fedee6e7fb6 100644 --- a/net/ipv4/netfilter/nf_nat_irc.c +++ b/net/netfilter/nf_nat_irc.c | |||
@@ -17,7 +17,6 @@ | |||
17 | 17 | ||
18 | #include <net/netfilter/nf_nat.h> | 18 | #include <net/netfilter/nf_nat.h> |
19 | #include <net/netfilter/nf_nat_helper.h> | 19 | #include <net/netfilter/nf_nat_helper.h> |
20 | #include <net/netfilter/nf_nat_rule.h> | ||
21 | #include <net/netfilter/nf_conntrack_helper.h> | 20 | #include <net/netfilter/nf_conntrack_helper.h> |
22 | #include <net/netfilter/nf_conntrack_expect.h> | 21 | #include <net/netfilter/nf_conntrack_expect.h> |
23 | #include <linux/netfilter/nf_conntrack_irc.h> | 22 | #include <linux/netfilter/nf_conntrack_irc.h> |
@@ -29,12 +28,12 @@ MODULE_ALIAS("ip_nat_irc"); | |||
29 | 28 | ||
30 | static unsigned int help(struct sk_buff *skb, | 29 | static unsigned int help(struct sk_buff *skb, |
31 | enum ip_conntrack_info ctinfo, | 30 | enum ip_conntrack_info ctinfo, |
31 | unsigned int protoff, | ||
32 | unsigned int matchoff, | 32 | unsigned int matchoff, |
33 | unsigned int matchlen, | 33 | unsigned int matchlen, |
34 | struct nf_conntrack_expect *exp) | 34 | struct nf_conntrack_expect *exp) |
35 | { | 35 | { |
36 | char buffer[sizeof("4294967296 65635")]; | 36 | char buffer[sizeof("4294967296 65635")]; |
37 | u_int32_t ip; | ||
38 | u_int16_t port; | 37 | u_int16_t port; |
39 | unsigned int ret; | 38 | unsigned int ret; |
40 | 39 | ||
@@ -60,13 +59,8 @@ static unsigned int help(struct sk_buff *skb, | |||
60 | if (port == 0) | 59 | if (port == 0) |
61 | return NF_DROP; | 60 | return NF_DROP; |
62 | 61 | ||
63 | ip = ntohl(exp->master->tuplehash[IP_CT_DIR_REPLY].tuple.dst.u3.ip); | ||
64 | sprintf(buffer, "%u %u", ip, port); | ||
65 | pr_debug("nf_nat_irc: inserting '%s' == %pI4, port %u\n", | ||
66 | buffer, &ip, port); | ||
67 | |||
68 | ret = nf_nat_mangle_tcp_packet(skb, exp->master, ctinfo, | 62 | ret = nf_nat_mangle_tcp_packet(skb, exp->master, ctinfo, |
69 | matchoff, matchlen, buffer, | 63 | protoff, matchoff, matchlen, buffer, |
70 | strlen(buffer)); | 64 | strlen(buffer)); |
71 | if (ret != NF_ACCEPT) | 65 | if (ret != NF_ACCEPT) |
72 | nf_ct_unexpect_related(exp); | 66 | nf_ct_unexpect_related(exp); |
diff --git a/net/ipv4/netfilter/nf_nat_proto_common.c b/net/netfilter/nf_nat_proto_common.c index 9993bc93e102..9baaf734c142 100644 --- a/net/ipv4/netfilter/nf_nat_proto_common.c +++ b/net/netfilter/nf_nat_proto_common.c | |||
@@ -9,20 +9,18 @@ | |||
9 | 9 | ||
10 | #include <linux/types.h> | 10 | #include <linux/types.h> |
11 | #include <linux/random.h> | 11 | #include <linux/random.h> |
12 | #include <linux/ip.h> | ||
13 | |||
14 | #include <linux/netfilter.h> | 12 | #include <linux/netfilter.h> |
15 | #include <linux/export.h> | 13 | #include <linux/export.h> |
16 | #include <net/secure_seq.h> | 14 | |
17 | #include <net/netfilter/nf_nat.h> | 15 | #include <net/netfilter/nf_nat.h> |
18 | #include <net/netfilter/nf_nat_core.h> | 16 | #include <net/netfilter/nf_nat_core.h> |
19 | #include <net/netfilter/nf_nat_rule.h> | 17 | #include <net/netfilter/nf_nat_l3proto.h> |
20 | #include <net/netfilter/nf_nat_protocol.h> | 18 | #include <net/netfilter/nf_nat_l4proto.h> |
21 | 19 | ||
22 | bool nf_nat_proto_in_range(const struct nf_conntrack_tuple *tuple, | 20 | bool nf_nat_l4proto_in_range(const struct nf_conntrack_tuple *tuple, |
23 | enum nf_nat_manip_type maniptype, | 21 | enum nf_nat_manip_type maniptype, |
24 | const union nf_conntrack_man_proto *min, | 22 | const union nf_conntrack_man_proto *min, |
25 | const union nf_conntrack_man_proto *max) | 23 | const union nf_conntrack_man_proto *max) |
26 | { | 24 | { |
27 | __be16 port; | 25 | __be16 port; |
28 | 26 | ||
@@ -34,13 +32,14 @@ bool nf_nat_proto_in_range(const struct nf_conntrack_tuple *tuple, | |||
34 | return ntohs(port) >= ntohs(min->all) && | 32 | return ntohs(port) >= ntohs(min->all) && |
35 | ntohs(port) <= ntohs(max->all); | 33 | ntohs(port) <= ntohs(max->all); |
36 | } | 34 | } |
37 | EXPORT_SYMBOL_GPL(nf_nat_proto_in_range); | 35 | EXPORT_SYMBOL_GPL(nf_nat_l4proto_in_range); |
38 | 36 | ||
39 | void nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple, | 37 | void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto, |
40 | const struct nf_nat_ipv4_range *range, | 38 | struct nf_conntrack_tuple *tuple, |
41 | enum nf_nat_manip_type maniptype, | 39 | const struct nf_nat_range *range, |
42 | const struct nf_conn *ct, | 40 | enum nf_nat_manip_type maniptype, |
43 | u_int16_t *rover) | 41 | const struct nf_conn *ct, |
42 | u16 *rover) | ||
44 | { | 43 | { |
45 | unsigned int range_size, min, i; | 44 | unsigned int range_size, min, i; |
46 | __be16 *portptr; | 45 | __be16 *portptr; |
@@ -71,15 +70,14 @@ void nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
71 | range_size = 65535 - 1024 + 1; | 70 | range_size = 65535 - 1024 + 1; |
72 | } | 71 | } |
73 | } else { | 72 | } else { |
74 | min = ntohs(range->min.all); | 73 | min = ntohs(range->min_proto.all); |
75 | range_size = ntohs(range->max.all) - min + 1; | 74 | range_size = ntohs(range->max_proto.all) - min + 1; |
76 | } | 75 | } |
77 | 76 | ||
78 | if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) | 77 | if (range->flags & NF_NAT_RANGE_PROTO_RANDOM) |
79 | off = secure_ipv4_port_ephemeral(tuple->src.u3.ip, tuple->dst.u3.ip, | 78 | off = l3proto->secure_port(tuple, maniptype == NF_NAT_MANIP_SRC |
80 | maniptype == NF_NAT_MANIP_SRC | 79 | ? tuple->dst.u.all |
81 | ? tuple->dst.u.all | 80 | : tuple->src.u.all); |
82 | : tuple->src.u.all); | ||
83 | else | 81 | else |
84 | off = *rover; | 82 | off = *rover; |
85 | 83 | ||
@@ -93,22 +91,22 @@ void nf_nat_proto_unique_tuple(struct nf_conntrack_tuple *tuple, | |||
93 | } | 91 | } |
94 | return; | 92 | return; |
95 | } | 93 | } |
96 | EXPORT_SYMBOL_GPL(nf_nat_proto_unique_tuple); | 94 | EXPORT_SYMBOL_GPL(nf_nat_l4proto_unique_tuple); |
97 | 95 | ||
98 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 96 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
99 | int nf_nat_proto_nlattr_to_range(struct nlattr *tb[], | 97 | int nf_nat_l4proto_nlattr_to_range(struct nlattr *tb[], |
100 | struct nf_nat_ipv4_range *range) | 98 | struct nf_nat_range *range) |
101 | { | 99 | { |
102 | if (tb[CTA_PROTONAT_PORT_MIN]) { | 100 | if (tb[CTA_PROTONAT_PORT_MIN]) { |
103 | range->min.all = nla_get_be16(tb[CTA_PROTONAT_PORT_MIN]); | 101 | range->min_proto.all = nla_get_be16(tb[CTA_PROTONAT_PORT_MIN]); |
104 | range->max.all = range->min.tcp.port; | 102 | range->max_proto.all = range->min_proto.all; |
105 | range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED; | 103 | range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED; |
106 | } | 104 | } |
107 | if (tb[CTA_PROTONAT_PORT_MAX]) { | 105 | if (tb[CTA_PROTONAT_PORT_MAX]) { |
108 | range->max.all = nla_get_be16(tb[CTA_PROTONAT_PORT_MAX]); | 106 | range->max_proto.all = nla_get_be16(tb[CTA_PROTONAT_PORT_MAX]); |
109 | range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED; | 107 | range->flags |= NF_NAT_RANGE_PROTO_SPECIFIED; |
110 | } | 108 | } |
111 | return 0; | 109 | return 0; |
112 | } | 110 | } |
113 | EXPORT_SYMBOL_GPL(nf_nat_proto_nlattr_to_range); | 111 | EXPORT_SYMBOL_GPL(nf_nat_l4proto_nlattr_to_range); |
114 | #endif | 112 | #endif |
diff --git a/net/ipv4/netfilter/nf_nat_proto_dccp.c b/net/netfilter/nf_nat_proto_dccp.c index 3f67138d187c..c8be2cdac0bf 100644 --- a/net/ipv4/netfilter/nf_nat_proto_dccp.c +++ b/net/netfilter/nf_nat_proto_dccp.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * DCCP NAT protocol helper | 2 | * DCCP NAT protocol helper |
3 | * | 3 | * |
4 | * Copyright (c) 2005, 2006. 2008 Patrick McHardy <kaber@trash.net> | 4 | * Copyright (c) 2005, 2006, 2008 Patrick McHardy <kaber@trash.net> |
5 | * | 5 | * |
6 | * This program is free software; you can redistribute it and/or modify | 6 | * This program is free software; you can redistribute it and/or modify |
7 | * it under the terms of the GNU General Public License version 2 as | 7 | * it under the terms of the GNU General Public License version 2 as |
@@ -13,35 +13,34 @@ | |||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/skbuff.h> | 15 | #include <linux/skbuff.h> |
16 | #include <linux/ip.h> | ||
17 | #include <linux/dccp.h> | 16 | #include <linux/dccp.h> |
18 | 17 | ||
19 | #include <net/netfilter/nf_conntrack.h> | 18 | #include <net/netfilter/nf_conntrack.h> |
20 | #include <net/netfilter/nf_nat.h> | 19 | #include <net/netfilter/nf_nat.h> |
21 | #include <net/netfilter/nf_nat_protocol.h> | 20 | #include <net/netfilter/nf_nat_l3proto.h> |
21 | #include <net/netfilter/nf_nat_l4proto.h> | ||
22 | 22 | ||
23 | static u_int16_t dccp_port_rover; | 23 | static u_int16_t dccp_port_rover; |
24 | 24 | ||
25 | static void | 25 | static void |
26 | dccp_unique_tuple(struct nf_conntrack_tuple *tuple, | 26 | dccp_unique_tuple(const struct nf_nat_l3proto *l3proto, |
27 | const struct nf_nat_ipv4_range *range, | 27 | struct nf_conntrack_tuple *tuple, |
28 | const struct nf_nat_range *range, | ||
28 | enum nf_nat_manip_type maniptype, | 29 | enum nf_nat_manip_type maniptype, |
29 | const struct nf_conn *ct) | 30 | const struct nf_conn *ct) |
30 | { | 31 | { |
31 | nf_nat_proto_unique_tuple(tuple, range, maniptype, ct, | 32 | nf_nat_l4proto_unique_tuple(l3proto, tuple, range, maniptype, ct, |
32 | &dccp_port_rover); | 33 | &dccp_port_rover); |
33 | } | 34 | } |
34 | 35 | ||
35 | static bool | 36 | static bool |
36 | dccp_manip_pkt(struct sk_buff *skb, | 37 | dccp_manip_pkt(struct sk_buff *skb, |
37 | unsigned int iphdroff, | 38 | const struct nf_nat_l3proto *l3proto, |
39 | unsigned int iphdroff, unsigned int hdroff, | ||
38 | const struct nf_conntrack_tuple *tuple, | 40 | const struct nf_conntrack_tuple *tuple, |
39 | enum nf_nat_manip_type maniptype) | 41 | enum nf_nat_manip_type maniptype) |
40 | { | 42 | { |
41 | const struct iphdr *iph = (const void *)(skb->data + iphdroff); | ||
42 | struct dccp_hdr *hdr; | 43 | struct dccp_hdr *hdr; |
43 | unsigned int hdroff = iphdroff + iph->ihl * 4; | ||
44 | __be32 oldip, newip; | ||
45 | __be16 *portptr, oldport, newport; | 44 | __be16 *portptr, oldport, newport; |
46 | int hdrsize = 8; /* DCCP connection tracking guarantees this much */ | 45 | int hdrsize = 8; /* DCCP connection tracking guarantees this much */ |
47 | 46 | ||
@@ -51,17 +50,12 @@ dccp_manip_pkt(struct sk_buff *skb, | |||
51 | if (!skb_make_writable(skb, hdroff + hdrsize)) | 50 | if (!skb_make_writable(skb, hdroff + hdrsize)) |
52 | return false; | 51 | return false; |
53 | 52 | ||
54 | iph = (struct iphdr *)(skb->data + iphdroff); | ||
55 | hdr = (struct dccp_hdr *)(skb->data + hdroff); | 53 | hdr = (struct dccp_hdr *)(skb->data + hdroff); |
56 | 54 | ||
57 | if (maniptype == NF_NAT_MANIP_SRC) { | 55 | if (maniptype == NF_NAT_MANIP_SRC) { |
58 | oldip = iph->saddr; | ||
59 | newip = tuple->src.u3.ip; | ||
60 | newport = tuple->src.u.dccp.port; | 56 | newport = tuple->src.u.dccp.port; |
61 | portptr = &hdr->dccph_sport; | 57 | portptr = &hdr->dccph_sport; |
62 | } else { | 58 | } else { |
63 | oldip = iph->daddr; | ||
64 | newip = tuple->dst.u3.ip; | ||
65 | newport = tuple->dst.u.dccp.port; | 59 | newport = tuple->dst.u.dccp.port; |
66 | portptr = &hdr->dccph_dport; | 60 | portptr = &hdr->dccph_dport; |
67 | } | 61 | } |
@@ -72,30 +66,46 @@ dccp_manip_pkt(struct sk_buff *skb, | |||
72 | if (hdrsize < sizeof(*hdr)) | 66 | if (hdrsize < sizeof(*hdr)) |
73 | return true; | 67 | return true; |
74 | 68 | ||
75 | inet_proto_csum_replace4(&hdr->dccph_checksum, skb, oldip, newip, 1); | 69 | l3proto->csum_update(skb, iphdroff, &hdr->dccph_checksum, |
70 | tuple, maniptype); | ||
76 | inet_proto_csum_replace2(&hdr->dccph_checksum, skb, oldport, newport, | 71 | inet_proto_csum_replace2(&hdr->dccph_checksum, skb, oldport, newport, |
77 | 0); | 72 | 0); |
78 | return true; | 73 | return true; |
79 | } | 74 | } |
80 | 75 | ||
81 | static const struct nf_nat_protocol nf_nat_protocol_dccp = { | 76 | static const struct nf_nat_l4proto nf_nat_l4proto_dccp = { |
82 | .protonum = IPPROTO_DCCP, | 77 | .l4proto = IPPROTO_DCCP, |
83 | .manip_pkt = dccp_manip_pkt, | 78 | .manip_pkt = dccp_manip_pkt, |
84 | .in_range = nf_nat_proto_in_range, | 79 | .in_range = nf_nat_l4proto_in_range, |
85 | .unique_tuple = dccp_unique_tuple, | 80 | .unique_tuple = dccp_unique_tuple, |
86 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 81 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
87 | .nlattr_to_range = nf_nat_proto_nlattr_to_range, | 82 | .nlattr_to_range = nf_nat_l4proto_nlattr_to_range, |
88 | #endif | 83 | #endif |
89 | }; | 84 | }; |
90 | 85 | ||
91 | static int __init nf_nat_proto_dccp_init(void) | 86 | static int __init nf_nat_proto_dccp_init(void) |
92 | { | 87 | { |
93 | return nf_nat_protocol_register(&nf_nat_protocol_dccp); | 88 | int err; |
89 | |||
90 | err = nf_nat_l4proto_register(NFPROTO_IPV4, &nf_nat_l4proto_dccp); | ||
91 | if (err < 0) | ||
92 | goto err1; | ||
93 | err = nf_nat_l4proto_register(NFPROTO_IPV6, &nf_nat_l4proto_dccp); | ||
94 | if (err < 0) | ||
95 | goto err2; | ||
96 | return 0; | ||
97 | |||
98 | err2: | ||
99 | nf_nat_l4proto_unregister(NFPROTO_IPV4, &nf_nat_l4proto_dccp); | ||
100 | err1: | ||
101 | return err; | ||
94 | } | 102 | } |
95 | 103 | ||
96 | static void __exit nf_nat_proto_dccp_fini(void) | 104 | static void __exit nf_nat_proto_dccp_fini(void) |
97 | { | 105 | { |
98 | nf_nat_protocol_unregister(&nf_nat_protocol_dccp); | 106 | nf_nat_l4proto_unregister(NFPROTO_IPV6, &nf_nat_l4proto_dccp); |
107 | nf_nat_l4proto_unregister(NFPROTO_IPV4, &nf_nat_l4proto_dccp); | ||
108 | |||
99 | } | 109 | } |
100 | 110 | ||
101 | module_init(nf_nat_proto_dccp_init); | 111 | module_init(nf_nat_proto_dccp_init); |
diff --git a/net/ipv4/netfilter/nf_nat_proto_sctp.c b/net/netfilter/nf_nat_proto_sctp.c index 3cce9b6c1c29..e64faa5ca893 100644 --- a/net/ipv4/netfilter/nf_nat_proto_sctp.c +++ b/net/netfilter/nf_nat_proto_sctp.c | |||
@@ -8,53 +8,46 @@ | |||
8 | 8 | ||
9 | #include <linux/types.h> | 9 | #include <linux/types.h> |
10 | #include <linux/init.h> | 10 | #include <linux/init.h> |
11 | #include <linux/ip.h> | ||
12 | #include <linux/sctp.h> | 11 | #include <linux/sctp.h> |
13 | #include <linux/module.h> | 12 | #include <linux/module.h> |
14 | #include <net/sctp/checksum.h> | 13 | #include <net/sctp/checksum.h> |
15 | 14 | ||
16 | #include <net/netfilter/nf_nat_protocol.h> | 15 | #include <net/netfilter/nf_nat_l4proto.h> |
17 | 16 | ||
18 | static u_int16_t nf_sctp_port_rover; | 17 | static u_int16_t nf_sctp_port_rover; |
19 | 18 | ||
20 | static void | 19 | static void |
21 | sctp_unique_tuple(struct nf_conntrack_tuple *tuple, | 20 | sctp_unique_tuple(const struct nf_nat_l3proto *l3proto, |
22 | const struct nf_nat_ipv4_range *range, | 21 | struct nf_conntrack_tuple *tuple, |
22 | const struct nf_nat_range *range, | ||
23 | enum nf_nat_manip_type maniptype, | 23 | enum nf_nat_manip_type maniptype, |
24 | const struct nf_conn *ct) | 24 | const struct nf_conn *ct) |
25 | { | 25 | { |
26 | nf_nat_proto_unique_tuple(tuple, range, maniptype, ct, | 26 | nf_nat_l4proto_unique_tuple(l3proto, tuple, range, maniptype, ct, |
27 | &nf_sctp_port_rover); | 27 | &nf_sctp_port_rover); |
28 | } | 28 | } |
29 | 29 | ||
30 | static bool | 30 | static bool |
31 | sctp_manip_pkt(struct sk_buff *skb, | 31 | sctp_manip_pkt(struct sk_buff *skb, |
32 | unsigned int iphdroff, | 32 | const struct nf_nat_l3proto *l3proto, |
33 | unsigned int iphdroff, unsigned int hdroff, | ||
33 | const struct nf_conntrack_tuple *tuple, | 34 | const struct nf_conntrack_tuple *tuple, |
34 | enum nf_nat_manip_type maniptype) | 35 | enum nf_nat_manip_type maniptype) |
35 | { | 36 | { |
36 | const struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff); | ||
37 | struct sk_buff *frag; | 37 | struct sk_buff *frag; |
38 | sctp_sctphdr_t *hdr; | 38 | sctp_sctphdr_t *hdr; |
39 | unsigned int hdroff = iphdroff + iph->ihl*4; | ||
40 | __be32 oldip, newip; | ||
41 | __be32 crc32; | 39 | __be32 crc32; |
42 | 40 | ||
43 | if (!skb_make_writable(skb, hdroff + sizeof(*hdr))) | 41 | if (!skb_make_writable(skb, hdroff + sizeof(*hdr))) |
44 | return false; | 42 | return false; |
45 | 43 | ||
46 | iph = (struct iphdr *)(skb->data + iphdroff); | ||
47 | hdr = (struct sctphdr *)(skb->data + hdroff); | 44 | hdr = (struct sctphdr *)(skb->data + hdroff); |
48 | 45 | ||
49 | if (maniptype == NF_NAT_MANIP_SRC) { | 46 | if (maniptype == NF_NAT_MANIP_SRC) { |
50 | /* Get rid of src ip and src pt */ | 47 | /* Get rid of src port */ |
51 | oldip = iph->saddr; | ||
52 | newip = tuple->src.u3.ip; | ||
53 | hdr->source = tuple->src.u.sctp.port; | 48 | hdr->source = tuple->src.u.sctp.port; |
54 | } else { | 49 | } else { |
55 | /* Get rid of dst ip and dst pt */ | 50 | /* Get rid of dst port */ |
56 | oldip = iph->daddr; | ||
57 | newip = tuple->dst.u3.ip; | ||
58 | hdr->dest = tuple->dst.u.sctp.port; | 51 | hdr->dest = tuple->dst.u.sctp.port; |
59 | } | 52 | } |
60 | 53 | ||
@@ -68,24 +61,38 @@ sctp_manip_pkt(struct sk_buff *skb, | |||
68 | return true; | 61 | return true; |
69 | } | 62 | } |
70 | 63 | ||
71 | static const struct nf_nat_protocol nf_nat_protocol_sctp = { | 64 | static const struct nf_nat_l4proto nf_nat_l4proto_sctp = { |
72 | .protonum = IPPROTO_SCTP, | 65 | .l4proto = IPPROTO_SCTP, |
73 | .manip_pkt = sctp_manip_pkt, | 66 | .manip_pkt = sctp_manip_pkt, |
74 | .in_range = nf_nat_proto_in_range, | 67 | .in_range = nf_nat_l4proto_in_range, |
75 | .unique_tuple = sctp_unique_tuple, | 68 | .unique_tuple = sctp_unique_tuple, |
76 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 69 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
77 | .nlattr_to_range = nf_nat_proto_nlattr_to_range, | 70 | .nlattr_to_range = nf_nat_l4proto_nlattr_to_range, |
78 | #endif | 71 | #endif |
79 | }; | 72 | }; |
80 | 73 | ||
81 | static int __init nf_nat_proto_sctp_init(void) | 74 | static int __init nf_nat_proto_sctp_init(void) |
82 | { | 75 | { |
83 | return nf_nat_protocol_register(&nf_nat_protocol_sctp); | 76 | int err; |
77 | |||
78 | err = nf_nat_l4proto_register(NFPROTO_IPV4, &nf_nat_l4proto_sctp); | ||
79 | if (err < 0) | ||
80 | goto err1; | ||
81 | err = nf_nat_l4proto_register(NFPROTO_IPV6, &nf_nat_l4proto_sctp); | ||
82 | if (err < 0) | ||
83 | goto err2; | ||
84 | return 0; | ||
85 | |||
86 | err2: | ||
87 | nf_nat_l4proto_unregister(NFPROTO_IPV4, &nf_nat_l4proto_sctp); | ||
88 | err1: | ||
89 | return err; | ||
84 | } | 90 | } |
85 | 91 | ||
86 | static void __exit nf_nat_proto_sctp_exit(void) | 92 | static void __exit nf_nat_proto_sctp_exit(void) |
87 | { | 93 | { |
88 | nf_nat_protocol_unregister(&nf_nat_protocol_sctp); | 94 | nf_nat_l4proto_unregister(NFPROTO_IPV6, &nf_nat_l4proto_sctp); |
95 | nf_nat_l4proto_unregister(NFPROTO_IPV4, &nf_nat_l4proto_sctp); | ||
89 | } | 96 | } |
90 | 97 | ||
91 | module_init(nf_nat_proto_sctp_init); | 98 | module_init(nf_nat_proto_sctp_init); |
diff --git a/net/ipv4/netfilter/nf_nat_proto_tcp.c b/net/netfilter/nf_nat_proto_tcp.c index 9fb4b4e72bbf..83ec8a6e4c36 100644 --- a/net/ipv4/netfilter/nf_nat_proto_tcp.c +++ b/net/netfilter/nf_nat_proto_tcp.c | |||
@@ -9,37 +9,36 @@ | |||
9 | #include <linux/types.h> | 9 | #include <linux/types.h> |
10 | #include <linux/init.h> | 10 | #include <linux/init.h> |
11 | #include <linux/export.h> | 11 | #include <linux/export.h> |
12 | #include <linux/ip.h> | ||
13 | #include <linux/tcp.h> | 12 | #include <linux/tcp.h> |
14 | 13 | ||
15 | #include <linux/netfilter.h> | 14 | #include <linux/netfilter.h> |
16 | #include <linux/netfilter/nfnetlink_conntrack.h> | 15 | #include <linux/netfilter/nfnetlink_conntrack.h> |
17 | #include <net/netfilter/nf_nat.h> | 16 | #include <net/netfilter/nf_nat.h> |
18 | #include <net/netfilter/nf_nat_rule.h> | 17 | #include <net/netfilter/nf_nat_l3proto.h> |
19 | #include <net/netfilter/nf_nat_protocol.h> | 18 | #include <net/netfilter/nf_nat_l4proto.h> |
20 | #include <net/netfilter/nf_nat_core.h> | 19 | #include <net/netfilter/nf_nat_core.h> |
21 | 20 | ||
22 | static u_int16_t tcp_port_rover; | 21 | static u16 tcp_port_rover; |
23 | 22 | ||
24 | static void | 23 | static void |
25 | tcp_unique_tuple(struct nf_conntrack_tuple *tuple, | 24 | tcp_unique_tuple(const struct nf_nat_l3proto *l3proto, |
26 | const struct nf_nat_ipv4_range *range, | 25 | struct nf_conntrack_tuple *tuple, |
26 | const struct nf_nat_range *range, | ||
27 | enum nf_nat_manip_type maniptype, | 27 | enum nf_nat_manip_type maniptype, |
28 | const struct nf_conn *ct) | 28 | const struct nf_conn *ct) |
29 | { | 29 | { |
30 | nf_nat_proto_unique_tuple(tuple, range, maniptype, ct, &tcp_port_rover); | 30 | nf_nat_l4proto_unique_tuple(l3proto, tuple, range, maniptype, ct, |
31 | &tcp_port_rover); | ||
31 | } | 32 | } |
32 | 33 | ||
33 | static bool | 34 | static bool |
34 | tcp_manip_pkt(struct sk_buff *skb, | 35 | tcp_manip_pkt(struct sk_buff *skb, |
35 | unsigned int iphdroff, | 36 | const struct nf_nat_l3proto *l3proto, |
37 | unsigned int iphdroff, unsigned int hdroff, | ||
36 | const struct nf_conntrack_tuple *tuple, | 38 | const struct nf_conntrack_tuple *tuple, |
37 | enum nf_nat_manip_type maniptype) | 39 | enum nf_nat_manip_type maniptype) |
38 | { | 40 | { |
39 | const struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff); | ||
40 | struct tcphdr *hdr; | 41 | struct tcphdr *hdr; |
41 | unsigned int hdroff = iphdroff + iph->ihl*4; | ||
42 | __be32 oldip, newip; | ||
43 | __be16 *portptr, newport, oldport; | 42 | __be16 *portptr, newport, oldport; |
44 | int hdrsize = 8; /* TCP connection tracking guarantees this much */ | 43 | int hdrsize = 8; /* TCP connection tracking guarantees this much */ |
45 | 44 | ||
@@ -52,19 +51,14 @@ tcp_manip_pkt(struct sk_buff *skb, | |||
52 | if (!skb_make_writable(skb, hdroff + hdrsize)) | 51 | if (!skb_make_writable(skb, hdroff + hdrsize)) |
53 | return false; | 52 | return false; |
54 | 53 | ||
55 | iph = (struct iphdr *)(skb->data + iphdroff); | ||
56 | hdr = (struct tcphdr *)(skb->data + hdroff); | 54 | hdr = (struct tcphdr *)(skb->data + hdroff); |
57 | 55 | ||
58 | if (maniptype == NF_NAT_MANIP_SRC) { | 56 | if (maniptype == NF_NAT_MANIP_SRC) { |
59 | /* Get rid of src ip and src pt */ | 57 | /* Get rid of src port */ |
60 | oldip = iph->saddr; | ||
61 | newip = tuple->src.u3.ip; | ||
62 | newport = tuple->src.u.tcp.port; | 58 | newport = tuple->src.u.tcp.port; |
63 | portptr = &hdr->source; | 59 | portptr = &hdr->source; |
64 | } else { | 60 | } else { |
65 | /* Get rid of dst ip and dst pt */ | 61 | /* Get rid of dst port */ |
66 | oldip = iph->daddr; | ||
67 | newip = tuple->dst.u3.ip; | ||
68 | newport = tuple->dst.u.tcp.port; | 62 | newport = tuple->dst.u.tcp.port; |
69 | portptr = &hdr->dest; | 63 | portptr = &hdr->dest; |
70 | } | 64 | } |
@@ -75,17 +69,17 @@ tcp_manip_pkt(struct sk_buff *skb, | |||
75 | if (hdrsize < sizeof(*hdr)) | 69 | if (hdrsize < sizeof(*hdr)) |
76 | return true; | 70 | return true; |
77 | 71 | ||
78 | inet_proto_csum_replace4(&hdr->check, skb, oldip, newip, 1); | 72 | l3proto->csum_update(skb, iphdroff, &hdr->check, tuple, maniptype); |
79 | inet_proto_csum_replace2(&hdr->check, skb, oldport, newport, 0); | 73 | inet_proto_csum_replace2(&hdr->check, skb, oldport, newport, 0); |
80 | return true; | 74 | return true; |
81 | } | 75 | } |
82 | 76 | ||
83 | const struct nf_nat_protocol nf_nat_protocol_tcp = { | 77 | const struct nf_nat_l4proto nf_nat_l4proto_tcp = { |
84 | .protonum = IPPROTO_TCP, | 78 | .l4proto = IPPROTO_TCP, |
85 | .manip_pkt = tcp_manip_pkt, | 79 | .manip_pkt = tcp_manip_pkt, |
86 | .in_range = nf_nat_proto_in_range, | 80 | .in_range = nf_nat_l4proto_in_range, |
87 | .unique_tuple = tcp_unique_tuple, | 81 | .unique_tuple = tcp_unique_tuple, |
88 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 82 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
89 | .nlattr_to_range = nf_nat_proto_nlattr_to_range, | 83 | .nlattr_to_range = nf_nat_l4proto_nlattr_to_range, |
90 | #endif | 84 | #endif |
91 | }; | 85 | }; |
diff --git a/net/ipv4/netfilter/nf_nat_proto_udp.c b/net/netfilter/nf_nat_proto_udp.c index 9883336e628f..7df613fb34a2 100644 --- a/net/ipv4/netfilter/nf_nat_proto_udp.c +++ b/net/netfilter/nf_nat_proto_udp.c | |||
@@ -9,59 +9,53 @@ | |||
9 | #include <linux/types.h> | 9 | #include <linux/types.h> |
10 | #include <linux/export.h> | 10 | #include <linux/export.h> |
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/ip.h> | ||
13 | #include <linux/udp.h> | 12 | #include <linux/udp.h> |
14 | 13 | ||
15 | #include <linux/netfilter.h> | 14 | #include <linux/netfilter.h> |
16 | #include <net/netfilter/nf_nat.h> | 15 | #include <net/netfilter/nf_nat.h> |
17 | #include <net/netfilter/nf_nat_core.h> | 16 | #include <net/netfilter/nf_nat_core.h> |
18 | #include <net/netfilter/nf_nat_rule.h> | 17 | #include <net/netfilter/nf_nat_l3proto.h> |
19 | #include <net/netfilter/nf_nat_protocol.h> | 18 | #include <net/netfilter/nf_nat_l4proto.h> |
20 | 19 | ||
21 | static u_int16_t udp_port_rover; | 20 | static u16 udp_port_rover; |
22 | 21 | ||
23 | static void | 22 | static void |
24 | udp_unique_tuple(struct nf_conntrack_tuple *tuple, | 23 | udp_unique_tuple(const struct nf_nat_l3proto *l3proto, |
25 | const struct nf_nat_ipv4_range *range, | 24 | struct nf_conntrack_tuple *tuple, |
25 | const struct nf_nat_range *range, | ||
26 | enum nf_nat_manip_type maniptype, | 26 | enum nf_nat_manip_type maniptype, |
27 | const struct nf_conn *ct) | 27 | const struct nf_conn *ct) |
28 | { | 28 | { |
29 | nf_nat_proto_unique_tuple(tuple, range, maniptype, ct, &udp_port_rover); | 29 | nf_nat_l4proto_unique_tuple(l3proto, tuple, range, maniptype, ct, |
30 | &udp_port_rover); | ||
30 | } | 31 | } |
31 | 32 | ||
32 | static bool | 33 | static bool |
33 | udp_manip_pkt(struct sk_buff *skb, | 34 | udp_manip_pkt(struct sk_buff *skb, |
34 | unsigned int iphdroff, | 35 | const struct nf_nat_l3proto *l3proto, |
36 | unsigned int iphdroff, unsigned int hdroff, | ||
35 | const struct nf_conntrack_tuple *tuple, | 37 | const struct nf_conntrack_tuple *tuple, |
36 | enum nf_nat_manip_type maniptype) | 38 | enum nf_nat_manip_type maniptype) |
37 | { | 39 | { |
38 | const struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff); | ||
39 | struct udphdr *hdr; | 40 | struct udphdr *hdr; |
40 | unsigned int hdroff = iphdroff + iph->ihl*4; | ||
41 | __be32 oldip, newip; | ||
42 | __be16 *portptr, newport; | 41 | __be16 *portptr, newport; |
43 | 42 | ||
44 | if (!skb_make_writable(skb, hdroff + sizeof(*hdr))) | 43 | if (!skb_make_writable(skb, hdroff + sizeof(*hdr))) |
45 | return false; | 44 | return false; |
46 | |||
47 | iph = (struct iphdr *)(skb->data + iphdroff); | ||
48 | hdr = (struct udphdr *)(skb->data + hdroff); | 45 | hdr = (struct udphdr *)(skb->data + hdroff); |
49 | 46 | ||
50 | if (maniptype == NF_NAT_MANIP_SRC) { | 47 | if (maniptype == NF_NAT_MANIP_SRC) { |
51 | /* Get rid of src ip and src pt */ | 48 | /* Get rid of src port */ |
52 | oldip = iph->saddr; | ||
53 | newip = tuple->src.u3.ip; | ||
54 | newport = tuple->src.u.udp.port; | 49 | newport = tuple->src.u.udp.port; |
55 | portptr = &hdr->source; | 50 | portptr = &hdr->source; |
56 | } else { | 51 | } else { |
57 | /* Get rid of dst ip and dst pt */ | 52 | /* Get rid of dst port */ |
58 | oldip = iph->daddr; | ||
59 | newip = tuple->dst.u3.ip; | ||
60 | newport = tuple->dst.u.udp.port; | 53 | newport = tuple->dst.u.udp.port; |
61 | portptr = &hdr->dest; | 54 | portptr = &hdr->dest; |
62 | } | 55 | } |
63 | if (hdr->check || skb->ip_summed == CHECKSUM_PARTIAL) { | 56 | if (hdr->check || skb->ip_summed == CHECKSUM_PARTIAL) { |
64 | inet_proto_csum_replace4(&hdr->check, skb, oldip, newip, 1); | 57 | l3proto->csum_update(skb, iphdroff, &hdr->check, |
58 | tuple, maniptype); | ||
65 | inet_proto_csum_replace2(&hdr->check, skb, *portptr, newport, | 59 | inet_proto_csum_replace2(&hdr->check, skb, *portptr, newport, |
66 | 0); | 60 | 0); |
67 | if (!hdr->check) | 61 | if (!hdr->check) |
@@ -71,12 +65,12 @@ udp_manip_pkt(struct sk_buff *skb, | |||
71 | return true; | 65 | return true; |
72 | } | 66 | } |
73 | 67 | ||
74 | const struct nf_nat_protocol nf_nat_protocol_udp = { | 68 | const struct nf_nat_l4proto nf_nat_l4proto_udp = { |
75 | .protonum = IPPROTO_UDP, | 69 | .l4proto = IPPROTO_UDP, |
76 | .manip_pkt = udp_manip_pkt, | 70 | .manip_pkt = udp_manip_pkt, |
77 | .in_range = nf_nat_proto_in_range, | 71 | .in_range = nf_nat_l4proto_in_range, |
78 | .unique_tuple = udp_unique_tuple, | 72 | .unique_tuple = udp_unique_tuple, |
79 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 73 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
80 | .nlattr_to_range = nf_nat_proto_nlattr_to_range, | 74 | .nlattr_to_range = nf_nat_l4proto_nlattr_to_range, |
81 | #endif | 75 | #endif |
82 | }; | 76 | }; |
diff --git a/net/ipv4/netfilter/nf_nat_proto_udplite.c b/net/netfilter/nf_nat_proto_udplite.c index d24d10a7beb2..776a0d1317b1 100644 --- a/net/ipv4/netfilter/nf_nat_proto_udplite.c +++ b/net/netfilter/nf_nat_proto_udplite.c | |||
@@ -9,59 +9,53 @@ | |||
9 | 9 | ||
10 | #include <linux/types.h> | 10 | #include <linux/types.h> |
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/ip.h> | ||
13 | #include <linux/udp.h> | 12 | #include <linux/udp.h> |
14 | 13 | ||
15 | #include <linux/netfilter.h> | 14 | #include <linux/netfilter.h> |
16 | #include <linux/module.h> | 15 | #include <linux/module.h> |
17 | #include <net/netfilter/nf_nat.h> | 16 | #include <net/netfilter/nf_nat.h> |
18 | #include <net/netfilter/nf_nat_protocol.h> | 17 | #include <net/netfilter/nf_nat_l3proto.h> |
18 | #include <net/netfilter/nf_nat_l4proto.h> | ||
19 | 19 | ||
20 | static u_int16_t udplite_port_rover; | 20 | static u16 udplite_port_rover; |
21 | 21 | ||
22 | static void | 22 | static void |
23 | udplite_unique_tuple(struct nf_conntrack_tuple *tuple, | 23 | udplite_unique_tuple(const struct nf_nat_l3proto *l3proto, |
24 | const struct nf_nat_ipv4_range *range, | 24 | struct nf_conntrack_tuple *tuple, |
25 | const struct nf_nat_range *range, | ||
25 | enum nf_nat_manip_type maniptype, | 26 | enum nf_nat_manip_type maniptype, |
26 | const struct nf_conn *ct) | 27 | const struct nf_conn *ct) |
27 | { | 28 | { |
28 | nf_nat_proto_unique_tuple(tuple, range, maniptype, ct, | 29 | nf_nat_l4proto_unique_tuple(l3proto, tuple, range, maniptype, ct, |
29 | &udplite_port_rover); | 30 | &udplite_port_rover); |
30 | } | 31 | } |
31 | 32 | ||
32 | static bool | 33 | static bool |
33 | udplite_manip_pkt(struct sk_buff *skb, | 34 | udplite_manip_pkt(struct sk_buff *skb, |
34 | unsigned int iphdroff, | 35 | const struct nf_nat_l3proto *l3proto, |
36 | unsigned int iphdroff, unsigned int hdroff, | ||
35 | const struct nf_conntrack_tuple *tuple, | 37 | const struct nf_conntrack_tuple *tuple, |
36 | enum nf_nat_manip_type maniptype) | 38 | enum nf_nat_manip_type maniptype) |
37 | { | 39 | { |
38 | const struct iphdr *iph = (struct iphdr *)(skb->data + iphdroff); | ||
39 | struct udphdr *hdr; | 40 | struct udphdr *hdr; |
40 | unsigned int hdroff = iphdroff + iph->ihl*4; | ||
41 | __be32 oldip, newip; | ||
42 | __be16 *portptr, newport; | 41 | __be16 *portptr, newport; |
43 | 42 | ||
44 | if (!skb_make_writable(skb, hdroff + sizeof(*hdr))) | 43 | if (!skb_make_writable(skb, hdroff + sizeof(*hdr))) |
45 | return false; | 44 | return false; |
46 | 45 | ||
47 | iph = (struct iphdr *)(skb->data + iphdroff); | ||
48 | hdr = (struct udphdr *)(skb->data + hdroff); | 46 | hdr = (struct udphdr *)(skb->data + hdroff); |
49 | 47 | ||
50 | if (maniptype == NF_NAT_MANIP_SRC) { | 48 | if (maniptype == NF_NAT_MANIP_SRC) { |
51 | /* Get rid of src ip and src pt */ | 49 | /* Get rid of source port */ |
52 | oldip = iph->saddr; | ||
53 | newip = tuple->src.u3.ip; | ||
54 | newport = tuple->src.u.udp.port; | 50 | newport = tuple->src.u.udp.port; |
55 | portptr = &hdr->source; | 51 | portptr = &hdr->source; |
56 | } else { | 52 | } else { |
57 | /* Get rid of dst ip and dst pt */ | 53 | /* Get rid of dst port */ |
58 | oldip = iph->daddr; | ||
59 | newip = tuple->dst.u3.ip; | ||
60 | newport = tuple->dst.u.udp.port; | 54 | newport = tuple->dst.u.udp.port; |
61 | portptr = &hdr->dest; | 55 | portptr = &hdr->dest; |
62 | } | 56 | } |
63 | 57 | ||
64 | inet_proto_csum_replace4(&hdr->check, skb, oldip, newip, 1); | 58 | l3proto->csum_update(skb, iphdroff, &hdr->check, tuple, maniptype); |
65 | inet_proto_csum_replace2(&hdr->check, skb, *portptr, newport, 0); | 59 | inet_proto_csum_replace2(&hdr->check, skb, *portptr, newport, 0); |
66 | if (!hdr->check) | 60 | if (!hdr->check) |
67 | hdr->check = CSUM_MANGLED_0; | 61 | hdr->check = CSUM_MANGLED_0; |
@@ -70,24 +64,38 @@ udplite_manip_pkt(struct sk_buff *skb, | |||
70 | return true; | 64 | return true; |
71 | } | 65 | } |
72 | 66 | ||
73 | static const struct nf_nat_protocol nf_nat_protocol_udplite = { | 67 | static const struct nf_nat_l4proto nf_nat_l4proto_udplite = { |
74 | .protonum = IPPROTO_UDPLITE, | 68 | .l4proto = IPPROTO_UDPLITE, |
75 | .manip_pkt = udplite_manip_pkt, | 69 | .manip_pkt = udplite_manip_pkt, |
76 | .in_range = nf_nat_proto_in_range, | 70 | .in_range = nf_nat_l4proto_in_range, |
77 | .unique_tuple = udplite_unique_tuple, | 71 | .unique_tuple = udplite_unique_tuple, |
78 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 72 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) |
79 | .nlattr_to_range = nf_nat_proto_nlattr_to_range, | 73 | .nlattr_to_range = nf_nat_l4proto_nlattr_to_range, |
80 | #endif | 74 | #endif |
81 | }; | 75 | }; |
82 | 76 | ||
83 | static int __init nf_nat_proto_udplite_init(void) | 77 | static int __init nf_nat_proto_udplite_init(void) |
84 | { | 78 | { |
85 | return nf_nat_protocol_register(&nf_nat_protocol_udplite); | 79 | int err; |
80 | |||
81 | err = nf_nat_l4proto_register(NFPROTO_IPV4, &nf_nat_l4proto_udplite); | ||
82 | if (err < 0) | ||
83 | goto err1; | ||
84 | err = nf_nat_l4proto_register(NFPROTO_IPV6, &nf_nat_l4proto_udplite); | ||
85 | if (err < 0) | ||
86 | goto err2; | ||
87 | return 0; | ||
88 | |||
89 | err2: | ||
90 | nf_nat_l4proto_unregister(NFPROTO_IPV4, &nf_nat_l4proto_udplite); | ||
91 | err1: | ||
92 | return err; | ||
86 | } | 93 | } |
87 | 94 | ||
88 | static void __exit nf_nat_proto_udplite_fini(void) | 95 | static void __exit nf_nat_proto_udplite_fini(void) |
89 | { | 96 | { |
90 | nf_nat_protocol_unregister(&nf_nat_protocol_udplite); | 97 | nf_nat_l4proto_unregister(NFPROTO_IPV6, &nf_nat_l4proto_udplite); |
98 | nf_nat_l4proto_unregister(NFPROTO_IPV4, &nf_nat_l4proto_udplite); | ||
91 | } | 99 | } |
92 | 100 | ||
93 | module_init(nf_nat_proto_udplite_init); | 101 | module_init(nf_nat_proto_udplite_init); |
diff --git a/net/ipv4/netfilter/nf_nat_proto_unknown.c b/net/netfilter/nf_nat_proto_unknown.c index e0afe8112b1c..6e494d584412 100644 --- a/net/ipv4/netfilter/nf_nat_proto_unknown.c +++ b/net/netfilter/nf_nat_proto_unknown.c | |||
@@ -15,8 +15,7 @@ | |||
15 | 15 | ||
16 | #include <linux/netfilter.h> | 16 | #include <linux/netfilter.h> |
17 | #include <net/netfilter/nf_nat.h> | 17 | #include <net/netfilter/nf_nat.h> |
18 | #include <net/netfilter/nf_nat_rule.h> | 18 | #include <net/netfilter/nf_nat_l4proto.h> |
19 | #include <net/netfilter/nf_nat_protocol.h> | ||
20 | 19 | ||
21 | static bool unknown_in_range(const struct nf_conntrack_tuple *tuple, | 20 | static bool unknown_in_range(const struct nf_conntrack_tuple *tuple, |
22 | enum nf_nat_manip_type manip_type, | 21 | enum nf_nat_manip_type manip_type, |
@@ -26,26 +25,29 @@ static bool unknown_in_range(const struct nf_conntrack_tuple *tuple, | |||
26 | return true; | 25 | return true; |
27 | } | 26 | } |
28 | 27 | ||
29 | static void unknown_unique_tuple(struct nf_conntrack_tuple *tuple, | 28 | static void unknown_unique_tuple(const struct nf_nat_l3proto *l3proto, |
30 | const struct nf_nat_ipv4_range *range, | 29 | struct nf_conntrack_tuple *tuple, |
30 | const struct nf_nat_range *range, | ||
31 | enum nf_nat_manip_type maniptype, | 31 | enum nf_nat_manip_type maniptype, |
32 | const struct nf_conn *ct) | 32 | const struct nf_conn *ct) |
33 | { | 33 | { |
34 | /* Sorry: we can't help you; if it's not unique, we can't frob | 34 | /* Sorry: we can't help you; if it's not unique, we can't frob |
35 | anything. */ | 35 | * anything. |
36 | */ | ||
36 | return; | 37 | return; |
37 | } | 38 | } |
38 | 39 | ||
39 | static bool | 40 | static bool |
40 | unknown_manip_pkt(struct sk_buff *skb, | 41 | unknown_manip_pkt(struct sk_buff *skb, |
41 | unsigned int iphdroff, | 42 | const struct nf_nat_l3proto *l3proto, |
43 | unsigned int iphdroff, unsigned int hdroff, | ||
42 | const struct nf_conntrack_tuple *tuple, | 44 | const struct nf_conntrack_tuple *tuple, |
43 | enum nf_nat_manip_type maniptype) | 45 | enum nf_nat_manip_type maniptype) |
44 | { | 46 | { |
45 | return true; | 47 | return true; |
46 | } | 48 | } |
47 | 49 | ||
48 | const struct nf_nat_protocol nf_nat_unknown_protocol = { | 50 | const struct nf_nat_l4proto nf_nat_l4proto_unknown = { |
49 | .manip_pkt = unknown_manip_pkt, | 51 | .manip_pkt = unknown_manip_pkt, |
50 | .in_range = unknown_in_range, | 52 | .in_range = unknown_in_range, |
51 | .unique_tuple = unknown_unique_tuple, | 53 | .unique_tuple = unknown_unique_tuple, |
diff --git a/net/ipv4/netfilter/nf_nat_sip.c b/net/netfilter/nf_nat_sip.c index ea4a23813d26..16303c752213 100644 --- a/net/ipv4/netfilter/nf_nat_sip.c +++ b/net/netfilter/nf_nat_sip.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * (C) 2005 by Christian Hentschel <chentschel@arnet.com.ar> | 3 | * (C) 2005 by Christian Hentschel <chentschel@arnet.com.ar> |
4 | * based on RR's ip_nat_ftp.c and other modules. | 4 | * based on RR's ip_nat_ftp.c and other modules. |
5 | * (C) 2007 United Security Providers | 5 | * (C) 2007 United Security Providers |
6 | * (C) 2007, 2008 Patrick McHardy <kaber@trash.net> | 6 | * (C) 2007, 2008, 2011, 2012 Patrick McHardy <kaber@trash.net> |
7 | * | 7 | * |
8 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License version 2 as | 9 | * it under the terms of the GNU General Public License version 2 as |
@@ -12,14 +12,12 @@ | |||
12 | 12 | ||
13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
14 | #include <linux/skbuff.h> | 14 | #include <linux/skbuff.h> |
15 | #include <linux/ip.h> | 15 | #include <linux/inet.h> |
16 | #include <net/ip.h> | ||
17 | #include <linux/udp.h> | 16 | #include <linux/udp.h> |
18 | #include <linux/tcp.h> | 17 | #include <linux/tcp.h> |
19 | 18 | ||
20 | #include <net/netfilter/nf_nat.h> | 19 | #include <net/netfilter/nf_nat.h> |
21 | #include <net/netfilter/nf_nat_helper.h> | 20 | #include <net/netfilter/nf_nat_helper.h> |
22 | #include <net/netfilter/nf_nat_rule.h> | ||
23 | #include <net/netfilter/nf_conntrack_helper.h> | 21 | #include <net/netfilter/nf_conntrack_helper.h> |
24 | #include <net/netfilter/nf_conntrack_expect.h> | 22 | #include <net/netfilter/nf_conntrack_expect.h> |
25 | #include <linux/netfilter/nf_conntrack_sip.h> | 23 | #include <linux/netfilter/nf_conntrack_sip.h> |
@@ -30,7 +28,8 @@ MODULE_DESCRIPTION("SIP NAT helper"); | |||
30 | MODULE_ALIAS("ip_nat_sip"); | 28 | MODULE_ALIAS("ip_nat_sip"); |
31 | 29 | ||
32 | 30 | ||
33 | static unsigned int mangle_packet(struct sk_buff *skb, unsigned int dataoff, | 31 | static unsigned int mangle_packet(struct sk_buff *skb, unsigned int protoff, |
32 | unsigned int dataoff, | ||
34 | const char **dptr, unsigned int *datalen, | 33 | const char **dptr, unsigned int *datalen, |
35 | unsigned int matchoff, unsigned int matchlen, | 34 | unsigned int matchoff, unsigned int matchlen, |
36 | const char *buffer, unsigned int buflen) | 35 | const char *buffer, unsigned int buflen) |
@@ -41,20 +40,20 @@ static unsigned int mangle_packet(struct sk_buff *skb, unsigned int dataoff, | |||
41 | unsigned int baseoff; | 40 | unsigned int baseoff; |
42 | 41 | ||
43 | if (nf_ct_protonum(ct) == IPPROTO_TCP) { | 42 | if (nf_ct_protonum(ct) == IPPROTO_TCP) { |
44 | th = (struct tcphdr *)(skb->data + ip_hdrlen(skb)); | 43 | th = (struct tcphdr *)(skb->data + protoff); |
45 | baseoff = ip_hdrlen(skb) + th->doff * 4; | 44 | baseoff = protoff + th->doff * 4; |
46 | matchoff += dataoff - baseoff; | 45 | matchoff += dataoff - baseoff; |
47 | 46 | ||
48 | if (!__nf_nat_mangle_tcp_packet(skb, ct, ctinfo, | 47 | if (!__nf_nat_mangle_tcp_packet(skb, ct, ctinfo, |
49 | matchoff, matchlen, | 48 | protoff, matchoff, matchlen, |
50 | buffer, buflen, false)) | 49 | buffer, buflen, false)) |
51 | return 0; | 50 | return 0; |
52 | } else { | 51 | } else { |
53 | baseoff = ip_hdrlen(skb) + sizeof(struct udphdr); | 52 | baseoff = protoff + sizeof(struct udphdr); |
54 | matchoff += dataoff - baseoff; | 53 | matchoff += dataoff - baseoff; |
55 | 54 | ||
56 | if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, | 55 | if (!nf_nat_mangle_udp_packet(skb, ct, ctinfo, |
57 | matchoff, matchlen, | 56 | protoff, matchoff, matchlen, |
58 | buffer, buflen)) | 57 | buffer, buflen)) |
59 | return 0; | 58 | return 0; |
60 | } | 59 | } |
@@ -65,7 +64,30 @@ static unsigned int mangle_packet(struct sk_buff *skb, unsigned int dataoff, | |||
65 | return 1; | 64 | return 1; |
66 | } | 65 | } |
67 | 66 | ||
68 | static int map_addr(struct sk_buff *skb, unsigned int dataoff, | 67 | static int sip_sprintf_addr(const struct nf_conn *ct, char *buffer, |
68 | const union nf_inet_addr *addr, bool delim) | ||
69 | { | ||
70 | if (nf_ct_l3num(ct) == NFPROTO_IPV4) | ||
71 | return sprintf(buffer, "%pI4", &addr->ip); | ||
72 | else { | ||
73 | if (delim) | ||
74 | return sprintf(buffer, "[%pI6c]", &addr->ip6); | ||
75 | else | ||
76 | return sprintf(buffer, "%pI6c", &addr->ip6); | ||
77 | } | ||
78 | } | ||
79 | |||
80 | static int sip_sprintf_addr_port(const struct nf_conn *ct, char *buffer, | ||
81 | const union nf_inet_addr *addr, u16 port) | ||
82 | { | ||
83 | if (nf_ct_l3num(ct) == NFPROTO_IPV4) | ||
84 | return sprintf(buffer, "%pI4:%u", &addr->ip, port); | ||
85 | else | ||
86 | return sprintf(buffer, "[%pI6c]:%u", &addr->ip6, port); | ||
87 | } | ||
88 | |||
89 | static int map_addr(struct sk_buff *skb, unsigned int protoff, | ||
90 | unsigned int dataoff, | ||
69 | const char **dptr, unsigned int *datalen, | 91 | const char **dptr, unsigned int *datalen, |
70 | unsigned int matchoff, unsigned int matchlen, | 92 | unsigned int matchoff, unsigned int matchlen, |
71 | union nf_inet_addr *addr, __be16 port) | 93 | union nf_inet_addr *addr, __be16 port) |
@@ -73,32 +95,32 @@ static int map_addr(struct sk_buff *skb, unsigned int dataoff, | |||
73 | enum ip_conntrack_info ctinfo; | 95 | enum ip_conntrack_info ctinfo; |
74 | struct nf_conn *ct = nf_ct_get(skb, &ctinfo); | 96 | struct nf_conn *ct = nf_ct_get(skb, &ctinfo); |
75 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | 97 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); |
76 | char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")]; | 98 | char buffer[INET6_ADDRSTRLEN + sizeof("[]:nnnnn")]; |
77 | unsigned int buflen; | 99 | unsigned int buflen; |
78 | __be32 newaddr; | 100 | union nf_inet_addr newaddr; |
79 | __be16 newport; | 101 | __be16 newport; |
80 | 102 | ||
81 | if (ct->tuplehash[dir].tuple.src.u3.ip == addr->ip && | 103 | if (nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3, addr) && |
82 | ct->tuplehash[dir].tuple.src.u.udp.port == port) { | 104 | ct->tuplehash[dir].tuple.src.u.udp.port == port) { |
83 | newaddr = ct->tuplehash[!dir].tuple.dst.u3.ip; | 105 | newaddr = ct->tuplehash[!dir].tuple.dst.u3; |
84 | newport = ct->tuplehash[!dir].tuple.dst.u.udp.port; | 106 | newport = ct->tuplehash[!dir].tuple.dst.u.udp.port; |
85 | } else if (ct->tuplehash[dir].tuple.dst.u3.ip == addr->ip && | 107 | } else if (nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.dst.u3, addr) && |
86 | ct->tuplehash[dir].tuple.dst.u.udp.port == port) { | 108 | ct->tuplehash[dir].tuple.dst.u.udp.port == port) { |
87 | newaddr = ct->tuplehash[!dir].tuple.src.u3.ip; | 109 | newaddr = ct->tuplehash[!dir].tuple.src.u3; |
88 | newport = ct->tuplehash[!dir].tuple.src.u.udp.port; | 110 | newport = ct->tuplehash[!dir].tuple.src.u.udp.port; |
89 | } else | 111 | } else |
90 | return 1; | 112 | return 1; |
91 | 113 | ||
92 | if (newaddr == addr->ip && newport == port) | 114 | if (nf_inet_addr_cmp(&newaddr, addr) && newport == port) |
93 | return 1; | 115 | return 1; |
94 | 116 | ||
95 | buflen = sprintf(buffer, "%pI4:%u", &newaddr, ntohs(newport)); | 117 | buflen = sip_sprintf_addr_port(ct, buffer, &newaddr, ntohs(newport)); |
96 | 118 | return mangle_packet(skb, protoff, dataoff, dptr, datalen, | |
97 | return mangle_packet(skb, dataoff, dptr, datalen, matchoff, matchlen, | 119 | matchoff, matchlen, buffer, buflen); |
98 | buffer, buflen); | ||
99 | } | 120 | } |
100 | 121 | ||
101 | static int map_sip_addr(struct sk_buff *skb, unsigned int dataoff, | 122 | static int map_sip_addr(struct sk_buff *skb, unsigned int protoff, |
123 | unsigned int dataoff, | ||
102 | const char **dptr, unsigned int *datalen, | 124 | const char **dptr, unsigned int *datalen, |
103 | enum sip_header_types type) | 125 | enum sip_header_types type) |
104 | { | 126 | { |
@@ -111,11 +133,12 @@ static int map_sip_addr(struct sk_buff *skb, unsigned int dataoff, | |||
111 | if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, type, NULL, | 133 | if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, type, NULL, |
112 | &matchoff, &matchlen, &addr, &port) <= 0) | 134 | &matchoff, &matchlen, &addr, &port) <= 0) |
113 | return 1; | 135 | return 1; |
114 | return map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen, | 136 | return map_addr(skb, protoff, dataoff, dptr, datalen, |
115 | &addr, port); | 137 | matchoff, matchlen, &addr, port); |
116 | } | 138 | } |
117 | 139 | ||
118 | static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff, | 140 | static unsigned int nf_nat_sip(struct sk_buff *skb, unsigned int protoff, |
141 | unsigned int dataoff, | ||
119 | const char **dptr, unsigned int *datalen) | 142 | const char **dptr, unsigned int *datalen) |
120 | { | 143 | { |
121 | enum ip_conntrack_info ctinfo; | 144 | enum ip_conntrack_info ctinfo; |
@@ -132,8 +155,8 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff, | |||
132 | if (ct_sip_parse_request(ct, *dptr, *datalen, | 155 | if (ct_sip_parse_request(ct, *dptr, *datalen, |
133 | &matchoff, &matchlen, | 156 | &matchoff, &matchlen, |
134 | &addr, &port) > 0 && | 157 | &addr, &port) > 0 && |
135 | !map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen, | 158 | !map_addr(skb, protoff, dataoff, dptr, datalen, |
136 | &addr, port)) | 159 | matchoff, matchlen, &addr, port)) |
137 | return NF_DROP; | 160 | return NF_DROP; |
138 | request = 1; | 161 | request = 1; |
139 | } else | 162 | } else |
@@ -148,37 +171,41 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff, | |||
148 | if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, | 171 | if (ct_sip_parse_header_uri(ct, *dptr, NULL, *datalen, |
149 | hdr, NULL, &matchoff, &matchlen, | 172 | hdr, NULL, &matchoff, &matchlen, |
150 | &addr, &port) > 0) { | 173 | &addr, &port) > 0) { |
151 | unsigned int matchend, poff, plen, buflen, n; | 174 | unsigned int olen, matchend, poff, plen, buflen, n; |
152 | char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")]; | 175 | char buffer[INET6_ADDRSTRLEN + sizeof("[]:nnnnn")]; |
153 | 176 | ||
154 | /* We're only interested in headers related to this | 177 | /* We're only interested in headers related to this |
155 | * connection */ | 178 | * connection */ |
156 | if (request) { | 179 | if (request) { |
157 | if (addr.ip != ct->tuplehash[dir].tuple.src.u3.ip || | 180 | if (!nf_inet_addr_cmp(&addr, |
181 | &ct->tuplehash[dir].tuple.src.u3) || | ||
158 | port != ct->tuplehash[dir].tuple.src.u.udp.port) | 182 | port != ct->tuplehash[dir].tuple.src.u.udp.port) |
159 | goto next; | 183 | goto next; |
160 | } else { | 184 | } else { |
161 | if (addr.ip != ct->tuplehash[dir].tuple.dst.u3.ip || | 185 | if (!nf_inet_addr_cmp(&addr, |
186 | &ct->tuplehash[dir].tuple.dst.u3) || | ||
162 | port != ct->tuplehash[dir].tuple.dst.u.udp.port) | 187 | port != ct->tuplehash[dir].tuple.dst.u.udp.port) |
163 | goto next; | 188 | goto next; |
164 | } | 189 | } |
165 | 190 | ||
166 | if (!map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen, | 191 | olen = *datalen; |
167 | &addr, port)) | 192 | if (!map_addr(skb, protoff, dataoff, dptr, datalen, |
193 | matchoff, matchlen, &addr, port)) | ||
168 | return NF_DROP; | 194 | return NF_DROP; |
169 | 195 | ||
170 | matchend = matchoff + matchlen; | 196 | matchend = matchoff + matchlen + *datalen - olen; |
171 | 197 | ||
172 | /* The maddr= parameter (RFC 2361) specifies where to send | 198 | /* The maddr= parameter (RFC 2361) specifies where to send |
173 | * the reply. */ | 199 | * the reply. */ |
174 | if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen, | 200 | if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen, |
175 | "maddr=", &poff, &plen, | 201 | "maddr=", &poff, &plen, |
176 | &addr) > 0 && | 202 | &addr, true) > 0 && |
177 | addr.ip == ct->tuplehash[dir].tuple.src.u3.ip && | 203 | nf_inet_addr_cmp(&addr, &ct->tuplehash[dir].tuple.src.u3) && |
178 | addr.ip != ct->tuplehash[!dir].tuple.dst.u3.ip) { | 204 | !nf_inet_addr_cmp(&addr, &ct->tuplehash[!dir].tuple.dst.u3)) { |
179 | buflen = sprintf(buffer, "%pI4", | 205 | buflen = sip_sprintf_addr(ct, buffer, |
180 | &ct->tuplehash[!dir].tuple.dst.u3.ip); | 206 | &ct->tuplehash[!dir].tuple.dst.u3, |
181 | if (!mangle_packet(skb, dataoff, dptr, datalen, | 207 | true); |
208 | if (!mangle_packet(skb, protoff, dataoff, dptr, datalen, | ||
182 | poff, plen, buffer, buflen)) | 209 | poff, plen, buffer, buflen)) |
183 | return NF_DROP; | 210 | return NF_DROP; |
184 | } | 211 | } |
@@ -187,12 +214,13 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff, | |||
187 | * from which the server received the request. */ | 214 | * from which the server received the request. */ |
188 | if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen, | 215 | if (ct_sip_parse_address_param(ct, *dptr, matchend, *datalen, |
189 | "received=", &poff, &plen, | 216 | "received=", &poff, &plen, |
190 | &addr) > 0 && | 217 | &addr, false) > 0 && |
191 | addr.ip == ct->tuplehash[dir].tuple.dst.u3.ip && | 218 | nf_inet_addr_cmp(&addr, &ct->tuplehash[dir].tuple.dst.u3) && |
192 | addr.ip != ct->tuplehash[!dir].tuple.src.u3.ip) { | 219 | !nf_inet_addr_cmp(&addr, &ct->tuplehash[!dir].tuple.src.u3)) { |
193 | buflen = sprintf(buffer, "%pI4", | 220 | buflen = sip_sprintf_addr(ct, buffer, |
194 | &ct->tuplehash[!dir].tuple.src.u3.ip); | 221 | &ct->tuplehash[!dir].tuple.src.u3, |
195 | if (!mangle_packet(skb, dataoff, dptr, datalen, | 222 | false); |
223 | if (!mangle_packet(skb, protoff, dataoff, dptr, datalen, | ||
196 | poff, plen, buffer, buflen)) | 224 | poff, plen, buffer, buflen)) |
197 | return NF_DROP; | 225 | return NF_DROP; |
198 | } | 226 | } |
@@ -206,7 +234,7 @@ static unsigned int ip_nat_sip(struct sk_buff *skb, unsigned int dataoff, | |||
206 | htons(n) != ct->tuplehash[!dir].tuple.src.u.udp.port) { | 234 | htons(n) != ct->tuplehash[!dir].tuple.src.u.udp.port) { |
207 | __be16 p = ct->tuplehash[!dir].tuple.src.u.udp.port; | 235 | __be16 p = ct->tuplehash[!dir].tuple.src.u.udp.port; |
208 | buflen = sprintf(buffer, "%u", ntohs(p)); | 236 | buflen = sprintf(buffer, "%u", ntohs(p)); |
209 | if (!mangle_packet(skb, dataoff, dptr, datalen, | 237 | if (!mangle_packet(skb, protoff, dataoff, dptr, datalen, |
210 | poff, plen, buffer, buflen)) | 238 | poff, plen, buffer, buflen)) |
211 | return NF_DROP; | 239 | return NF_DROP; |
212 | } | 240 | } |
@@ -220,19 +248,21 @@ next: | |||
220 | SIP_HDR_CONTACT, &in_header, | 248 | SIP_HDR_CONTACT, &in_header, |
221 | &matchoff, &matchlen, | 249 | &matchoff, &matchlen, |
222 | &addr, &port) > 0) { | 250 | &addr, &port) > 0) { |
223 | if (!map_addr(skb, dataoff, dptr, datalen, matchoff, matchlen, | 251 | if (!map_addr(skb, protoff, dataoff, dptr, datalen, |
252 | matchoff, matchlen, | ||
224 | &addr, port)) | 253 | &addr, port)) |
225 | return NF_DROP; | 254 | return NF_DROP; |
226 | } | 255 | } |
227 | 256 | ||
228 | if (!map_sip_addr(skb, dataoff, dptr, datalen, SIP_HDR_FROM) || | 257 | if (!map_sip_addr(skb, protoff, dataoff, dptr, datalen, SIP_HDR_FROM) || |
229 | !map_sip_addr(skb, dataoff, dptr, datalen, SIP_HDR_TO)) | 258 | !map_sip_addr(skb, protoff, dataoff, dptr, datalen, SIP_HDR_TO)) |
230 | return NF_DROP; | 259 | return NF_DROP; |
231 | 260 | ||
232 | return NF_ACCEPT; | 261 | return NF_ACCEPT; |
233 | } | 262 | } |
234 | 263 | ||
235 | static void ip_nat_sip_seq_adjust(struct sk_buff *skb, s16 off) | 264 | static void nf_nat_sip_seq_adjust(struct sk_buff *skb, unsigned int protoff, |
265 | s16 off) | ||
236 | { | 266 | { |
237 | enum ip_conntrack_info ctinfo; | 267 | enum ip_conntrack_info ctinfo; |
238 | struct nf_conn *ct = nf_ct_get(skb, &ctinfo); | 268 | struct nf_conn *ct = nf_ct_get(skb, &ctinfo); |
@@ -241,37 +271,38 @@ static void ip_nat_sip_seq_adjust(struct sk_buff *skb, s16 off) | |||
241 | if (nf_ct_protonum(ct) != IPPROTO_TCP || off == 0) | 271 | if (nf_ct_protonum(ct) != IPPROTO_TCP || off == 0) |
242 | return; | 272 | return; |
243 | 273 | ||
244 | th = (struct tcphdr *)(skb->data + ip_hdrlen(skb)); | 274 | th = (struct tcphdr *)(skb->data + protoff); |
245 | nf_nat_set_seq_adjust(ct, ctinfo, th->seq, off); | 275 | nf_nat_set_seq_adjust(ct, ctinfo, th->seq, off); |
246 | } | 276 | } |
247 | 277 | ||
248 | /* Handles expected signalling connections and media streams */ | 278 | /* Handles expected signalling connections and media streams */ |
249 | static void ip_nat_sip_expected(struct nf_conn *ct, | 279 | static void nf_nat_sip_expected(struct nf_conn *ct, |
250 | struct nf_conntrack_expect *exp) | 280 | struct nf_conntrack_expect *exp) |
251 | { | 281 | { |
252 | struct nf_nat_ipv4_range range; | 282 | struct nf_nat_range range; |
253 | 283 | ||
254 | /* This must be a fresh one. */ | 284 | /* This must be a fresh one. */ |
255 | BUG_ON(ct->status & IPS_NAT_DONE_MASK); | 285 | BUG_ON(ct->status & IPS_NAT_DONE_MASK); |
256 | 286 | ||
257 | /* For DST manip, map port here to where it's expected. */ | 287 | /* For DST manip, map port here to where it's expected. */ |
258 | range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED); | 288 | range.flags = (NF_NAT_RANGE_MAP_IPS | NF_NAT_RANGE_PROTO_SPECIFIED); |
259 | range.min = range.max = exp->saved_proto; | 289 | range.min_proto = range.max_proto = exp->saved_proto; |
260 | range.min_ip = range.max_ip = exp->saved_ip; | 290 | range.min_addr = range.max_addr = exp->saved_addr; |
261 | nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST); | 291 | nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST); |
262 | 292 | ||
263 | /* Change src to where master sends to, but only if the connection | 293 | /* Change src to where master sends to, but only if the connection |
264 | * actually came from the same source. */ | 294 | * actually came from the same source. */ |
265 | if (ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip == | 295 | if (nf_inet_addr_cmp(&ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3, |
266 | ct->master->tuplehash[exp->dir].tuple.src.u3.ip) { | 296 | &ct->master->tuplehash[exp->dir].tuple.src.u3)) { |
267 | range.flags = NF_NAT_RANGE_MAP_IPS; | 297 | range.flags = NF_NAT_RANGE_MAP_IPS; |
268 | range.min_ip = range.max_ip | 298 | range.min_addr = range.max_addr |
269 | = ct->master->tuplehash[!exp->dir].tuple.dst.u3.ip; | 299 | = ct->master->tuplehash[!exp->dir].tuple.dst.u3; |
270 | nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC); | 300 | nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC); |
271 | } | 301 | } |
272 | } | 302 | } |
273 | 303 | ||
274 | static unsigned int ip_nat_sip_expect(struct sk_buff *skb, unsigned int dataoff, | 304 | static unsigned int nf_nat_sip_expect(struct sk_buff *skb, unsigned int protoff, |
305 | unsigned int dataoff, | ||
275 | const char **dptr, unsigned int *datalen, | 306 | const char **dptr, unsigned int *datalen, |
276 | struct nf_conntrack_expect *exp, | 307 | struct nf_conntrack_expect *exp, |
277 | unsigned int matchoff, | 308 | unsigned int matchoff, |
@@ -280,16 +311,17 @@ static unsigned int ip_nat_sip_expect(struct sk_buff *skb, unsigned int dataoff, | |||
280 | enum ip_conntrack_info ctinfo; | 311 | enum ip_conntrack_info ctinfo; |
281 | struct nf_conn *ct = nf_ct_get(skb, &ctinfo); | 312 | struct nf_conn *ct = nf_ct_get(skb, &ctinfo); |
282 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); | 313 | enum ip_conntrack_dir dir = CTINFO2DIR(ctinfo); |
283 | __be32 newip; | 314 | union nf_inet_addr newaddr; |
284 | u_int16_t port; | 315 | u_int16_t port; |
285 | char buffer[sizeof("nnn.nnn.nnn.nnn:nnnnn")]; | 316 | char buffer[INET6_ADDRSTRLEN + sizeof("[]:nnnnn")]; |
286 | unsigned int buflen; | 317 | unsigned int buflen; |
287 | 318 | ||
288 | /* Connection will come from reply */ | 319 | /* Connection will come from reply */ |
289 | if (ct->tuplehash[dir].tuple.src.u3.ip == ct->tuplehash[!dir].tuple.dst.u3.ip) | 320 | if (nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3, |
290 | newip = exp->tuple.dst.u3.ip; | 321 | &ct->tuplehash[!dir].tuple.dst.u3)) |
322 | newaddr = exp->tuple.dst.u3; | ||
291 | else | 323 | else |
292 | newip = ct->tuplehash[!dir].tuple.dst.u3.ip; | 324 | newaddr = ct->tuplehash[!dir].tuple.dst.u3; |
293 | 325 | ||
294 | /* If the signalling port matches the connection's source port in the | 326 | /* If the signalling port matches the connection's source port in the |
295 | * original direction, try to use the destination port in the opposite | 327 | * original direction, try to use the destination port in the opposite |
@@ -300,11 +332,11 @@ static unsigned int ip_nat_sip_expect(struct sk_buff *skb, unsigned int dataoff, | |||
300 | else | 332 | else |
301 | port = ntohs(exp->tuple.dst.u.udp.port); | 333 | port = ntohs(exp->tuple.dst.u.udp.port); |
302 | 334 | ||
303 | exp->saved_ip = exp->tuple.dst.u3.ip; | 335 | exp->saved_addr = exp->tuple.dst.u3; |
304 | exp->tuple.dst.u3.ip = newip; | 336 | exp->tuple.dst.u3 = newaddr; |
305 | exp->saved_proto.udp.port = exp->tuple.dst.u.udp.port; | 337 | exp->saved_proto.udp.port = exp->tuple.dst.u.udp.port; |
306 | exp->dir = !dir; | 338 | exp->dir = !dir; |
307 | exp->expectfn = ip_nat_sip_expected; | 339 | exp->expectfn = nf_nat_sip_expected; |
308 | 340 | ||
309 | for (; port != 0; port++) { | 341 | for (; port != 0; port++) { |
310 | int ret; | 342 | int ret; |
@@ -322,10 +354,10 @@ static unsigned int ip_nat_sip_expect(struct sk_buff *skb, unsigned int dataoff, | |||
322 | if (port == 0) | 354 | if (port == 0) |
323 | return NF_DROP; | 355 | return NF_DROP; |
324 | 356 | ||
325 | if (exp->tuple.dst.u3.ip != exp->saved_ip || | 357 | if (!nf_inet_addr_cmp(&exp->tuple.dst.u3, &exp->saved_addr) || |
326 | exp->tuple.dst.u.udp.port != exp->saved_proto.udp.port) { | 358 | exp->tuple.dst.u.udp.port != exp->saved_proto.udp.port) { |
327 | buflen = sprintf(buffer, "%pI4:%u", &newip, port); | 359 | buflen = sip_sprintf_addr_port(ct, buffer, &newaddr, port); |
328 | if (!mangle_packet(skb, dataoff, dptr, datalen, | 360 | if (!mangle_packet(skb, protoff, dataoff, dptr, datalen, |
329 | matchoff, matchlen, buffer, buflen)) | 361 | matchoff, matchlen, buffer, buflen)) |
330 | goto err; | 362 | goto err; |
331 | } | 363 | } |
@@ -336,7 +368,8 @@ err: | |||
336 | return NF_DROP; | 368 | return NF_DROP; |
337 | } | 369 | } |
338 | 370 | ||
339 | static int mangle_content_len(struct sk_buff *skb, unsigned int dataoff, | 371 | static int mangle_content_len(struct sk_buff *skb, unsigned int protoff, |
372 | unsigned int dataoff, | ||
340 | const char **dptr, unsigned int *datalen) | 373 | const char **dptr, unsigned int *datalen) |
341 | { | 374 | { |
342 | enum ip_conntrack_info ctinfo; | 375 | enum ip_conntrack_info ctinfo; |
@@ -358,11 +391,12 @@ static int mangle_content_len(struct sk_buff *skb, unsigned int dataoff, | |||
358 | return 0; | 391 | return 0; |
359 | 392 | ||
360 | buflen = sprintf(buffer, "%u", c_len); | 393 | buflen = sprintf(buffer, "%u", c_len); |
361 | return mangle_packet(skb, dataoff, dptr, datalen, matchoff, matchlen, | 394 | return mangle_packet(skb, protoff, dataoff, dptr, datalen, |
362 | buffer, buflen); | 395 | matchoff, matchlen, buffer, buflen); |
363 | } | 396 | } |
364 | 397 | ||
365 | static int mangle_sdp_packet(struct sk_buff *skb, unsigned int dataoff, | 398 | static int mangle_sdp_packet(struct sk_buff *skb, unsigned int protoff, |
399 | unsigned int dataoff, | ||
366 | const char **dptr, unsigned int *datalen, | 400 | const char **dptr, unsigned int *datalen, |
367 | unsigned int sdpoff, | 401 | unsigned int sdpoff, |
368 | enum sdp_header_types type, | 402 | enum sdp_header_types type, |
@@ -376,29 +410,33 @@ static int mangle_sdp_packet(struct sk_buff *skb, unsigned int dataoff, | |||
376 | if (ct_sip_get_sdp_header(ct, *dptr, sdpoff, *datalen, type, term, | 410 | if (ct_sip_get_sdp_header(ct, *dptr, sdpoff, *datalen, type, term, |
377 | &matchoff, &matchlen) <= 0) | 411 | &matchoff, &matchlen) <= 0) |
378 | return -ENOENT; | 412 | return -ENOENT; |
379 | return mangle_packet(skb, dataoff, dptr, datalen, matchoff, matchlen, | 413 | return mangle_packet(skb, protoff, dataoff, dptr, datalen, |
380 | buffer, buflen) ? 0 : -EINVAL; | 414 | matchoff, matchlen, buffer, buflen) ? 0 : -EINVAL; |
381 | } | 415 | } |
382 | 416 | ||
383 | static unsigned int ip_nat_sdp_addr(struct sk_buff *skb, unsigned int dataoff, | 417 | static unsigned int nf_nat_sdp_addr(struct sk_buff *skb, unsigned int protoff, |
418 | unsigned int dataoff, | ||
384 | const char **dptr, unsigned int *datalen, | 419 | const char **dptr, unsigned int *datalen, |
385 | unsigned int sdpoff, | 420 | unsigned int sdpoff, |
386 | enum sdp_header_types type, | 421 | enum sdp_header_types type, |
387 | enum sdp_header_types term, | 422 | enum sdp_header_types term, |
388 | const union nf_inet_addr *addr) | 423 | const union nf_inet_addr *addr) |
389 | { | 424 | { |
390 | char buffer[sizeof("nnn.nnn.nnn.nnn")]; | 425 | enum ip_conntrack_info ctinfo; |
426 | struct nf_conn *ct = nf_ct_get(skb, &ctinfo); | ||
427 | char buffer[INET6_ADDRSTRLEN]; | ||
391 | unsigned int buflen; | 428 | unsigned int buflen; |
392 | 429 | ||
393 | buflen = sprintf(buffer, "%pI4", &addr->ip); | 430 | buflen = sip_sprintf_addr(ct, buffer, addr, false); |
394 | if (mangle_sdp_packet(skb, dataoff, dptr, datalen, sdpoff, type, term, | 431 | if (mangle_sdp_packet(skb, protoff, dataoff, dptr, datalen, |
395 | buffer, buflen)) | 432 | sdpoff, type, term, buffer, buflen)) |
396 | return 0; | 433 | return 0; |
397 | 434 | ||
398 | return mangle_content_len(skb, dataoff, dptr, datalen); | 435 | return mangle_content_len(skb, protoff, dataoff, dptr, datalen); |
399 | } | 436 | } |
400 | 437 | ||
401 | static unsigned int ip_nat_sdp_port(struct sk_buff *skb, unsigned int dataoff, | 438 | static unsigned int nf_nat_sdp_port(struct sk_buff *skb, unsigned int protoff, |
439 | unsigned int dataoff, | ||
402 | const char **dptr, unsigned int *datalen, | 440 | const char **dptr, unsigned int *datalen, |
403 | unsigned int matchoff, | 441 | unsigned int matchoff, |
404 | unsigned int matchlen, | 442 | unsigned int matchlen, |
@@ -408,30 +446,32 @@ static unsigned int ip_nat_sdp_port(struct sk_buff *skb, unsigned int dataoff, | |||
408 | unsigned int buflen; | 446 | unsigned int buflen; |
409 | 447 | ||
410 | buflen = sprintf(buffer, "%u", port); | 448 | buflen = sprintf(buffer, "%u", port); |
411 | if (!mangle_packet(skb, dataoff, dptr, datalen, matchoff, matchlen, | 449 | if (!mangle_packet(skb, protoff, dataoff, dptr, datalen, |
412 | buffer, buflen)) | 450 | matchoff, matchlen, buffer, buflen)) |
413 | return 0; | 451 | return 0; |
414 | 452 | ||
415 | return mangle_content_len(skb, dataoff, dptr, datalen); | 453 | return mangle_content_len(skb, protoff, dataoff, dptr, datalen); |
416 | } | 454 | } |
417 | 455 | ||
418 | static unsigned int ip_nat_sdp_session(struct sk_buff *skb, unsigned int dataoff, | 456 | static unsigned int nf_nat_sdp_session(struct sk_buff *skb, unsigned int protoff, |
457 | unsigned int dataoff, | ||
419 | const char **dptr, unsigned int *datalen, | 458 | const char **dptr, unsigned int *datalen, |
420 | unsigned int sdpoff, | 459 | unsigned int sdpoff, |
421 | const union nf_inet_addr *addr) | 460 | const union nf_inet_addr *addr) |
422 | { | 461 | { |
423 | char buffer[sizeof("nnn.nnn.nnn.nnn")]; | 462 | enum ip_conntrack_info ctinfo; |
463 | struct nf_conn *ct = nf_ct_get(skb, &ctinfo); | ||
464 | char buffer[INET6_ADDRSTRLEN]; | ||
424 | unsigned int buflen; | 465 | unsigned int buflen; |
425 | 466 | ||
426 | /* Mangle session description owner and contact addresses */ | 467 | /* Mangle session description owner and contact addresses */ |
427 | buflen = sprintf(buffer, "%pI4", &addr->ip); | 468 | buflen = sip_sprintf_addr(ct, buffer, addr, false); |
428 | if (mangle_sdp_packet(skb, dataoff, dptr, datalen, sdpoff, | 469 | if (mangle_sdp_packet(skb, protoff, dataoff, dptr, datalen, sdpoff, |
429 | SDP_HDR_OWNER_IP4, SDP_HDR_MEDIA, | 470 | SDP_HDR_OWNER, SDP_HDR_MEDIA, buffer, buflen)) |
430 | buffer, buflen)) | ||
431 | return 0; | 471 | return 0; |
432 | 472 | ||
433 | switch (mangle_sdp_packet(skb, dataoff, dptr, datalen, sdpoff, | 473 | switch (mangle_sdp_packet(skb, protoff, dataoff, dptr, datalen, sdpoff, |
434 | SDP_HDR_CONNECTION_IP4, SDP_HDR_MEDIA, | 474 | SDP_HDR_CONNECTION, SDP_HDR_MEDIA, |
435 | buffer, buflen)) { | 475 | buffer, buflen)) { |
436 | case 0: | 476 | case 0: |
437 | /* | 477 | /* |
@@ -447,12 +487,13 @@ static unsigned int ip_nat_sdp_session(struct sk_buff *skb, unsigned int dataoff | |||
447 | return 0; | 487 | return 0; |
448 | } | 488 | } |
449 | 489 | ||
450 | return mangle_content_len(skb, dataoff, dptr, datalen); | 490 | return mangle_content_len(skb, protoff, dataoff, dptr, datalen); |
451 | } | 491 | } |
452 | 492 | ||
453 | /* So, this packet has hit the connection tracking matching code. | 493 | /* So, this packet has hit the connection tracking matching code. |
454 | Mangle it, and change the expectation to match the new version. */ | 494 | Mangle it, and change the expectation to match the new version. */ |
455 | static unsigned int ip_nat_sdp_media(struct sk_buff *skb, unsigned int dataoff, | 495 | static unsigned int nf_nat_sdp_media(struct sk_buff *skb, unsigned int protoff, |
496 | unsigned int dataoff, | ||
456 | const char **dptr, unsigned int *datalen, | 497 | const char **dptr, unsigned int *datalen, |
457 | struct nf_conntrack_expect *rtp_exp, | 498 | struct nf_conntrack_expect *rtp_exp, |
458 | struct nf_conntrack_expect *rtcp_exp, | 499 | struct nf_conntrack_expect *rtcp_exp, |
@@ -466,23 +507,23 @@ static unsigned int ip_nat_sdp_media(struct sk_buff *skb, unsigned int dataoff, | |||
466 | u_int16_t port; | 507 | u_int16_t port; |
467 | 508 | ||
468 | /* Connection will come from reply */ | 509 | /* Connection will come from reply */ |
469 | if (ct->tuplehash[dir].tuple.src.u3.ip == | 510 | if (nf_inet_addr_cmp(&ct->tuplehash[dir].tuple.src.u3, |
470 | ct->tuplehash[!dir].tuple.dst.u3.ip) | 511 | &ct->tuplehash[!dir].tuple.dst.u3)) |
471 | rtp_addr->ip = rtp_exp->tuple.dst.u3.ip; | 512 | *rtp_addr = rtp_exp->tuple.dst.u3; |
472 | else | 513 | else |
473 | rtp_addr->ip = ct->tuplehash[!dir].tuple.dst.u3.ip; | 514 | *rtp_addr = ct->tuplehash[!dir].tuple.dst.u3; |
474 | 515 | ||
475 | rtp_exp->saved_ip = rtp_exp->tuple.dst.u3.ip; | 516 | rtp_exp->saved_addr = rtp_exp->tuple.dst.u3; |
476 | rtp_exp->tuple.dst.u3.ip = rtp_addr->ip; | 517 | rtp_exp->tuple.dst.u3 = *rtp_addr; |
477 | rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port; | 518 | rtp_exp->saved_proto.udp.port = rtp_exp->tuple.dst.u.udp.port; |
478 | rtp_exp->dir = !dir; | 519 | rtp_exp->dir = !dir; |
479 | rtp_exp->expectfn = ip_nat_sip_expected; | 520 | rtp_exp->expectfn = nf_nat_sip_expected; |
480 | 521 | ||
481 | rtcp_exp->saved_ip = rtcp_exp->tuple.dst.u3.ip; | 522 | rtcp_exp->saved_addr = rtcp_exp->tuple.dst.u3; |
482 | rtcp_exp->tuple.dst.u3.ip = rtp_addr->ip; | 523 | rtcp_exp->tuple.dst.u3 = *rtp_addr; |
483 | rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port; | 524 | rtcp_exp->saved_proto.udp.port = rtcp_exp->tuple.dst.u.udp.port; |
484 | rtcp_exp->dir = !dir; | 525 | rtcp_exp->dir = !dir; |
485 | rtcp_exp->expectfn = ip_nat_sip_expected; | 526 | rtcp_exp->expectfn = nf_nat_sip_expected; |
486 | 527 | ||
487 | /* Try to get same pair of ports: if not, try to change them. */ | 528 | /* Try to get same pair of ports: if not, try to change them. */ |
488 | for (port = ntohs(rtp_exp->tuple.dst.u.udp.port); | 529 | for (port = ntohs(rtp_exp->tuple.dst.u.udp.port); |
@@ -501,7 +542,10 @@ static unsigned int ip_nat_sdp_media(struct sk_buff *skb, unsigned int dataoff, | |||
501 | ret = nf_ct_expect_related(rtcp_exp); | 542 | ret = nf_ct_expect_related(rtcp_exp); |
502 | if (ret == 0) | 543 | if (ret == 0) |
503 | break; | 544 | break; |
504 | else if (ret != -EBUSY) { | 545 | else if (ret == -EBUSY) { |
546 | nf_ct_unexpect_related(rtp_exp); | ||
547 | continue; | ||
548 | } else if (ret < 0) { | ||
505 | nf_ct_unexpect_related(rtp_exp); | 549 | nf_ct_unexpect_related(rtp_exp); |
506 | port = 0; | 550 | port = 0; |
507 | break; | 551 | break; |
@@ -513,7 +557,7 @@ static unsigned int ip_nat_sdp_media(struct sk_buff *skb, unsigned int dataoff, | |||
513 | 557 | ||
514 | /* Update media port. */ | 558 | /* Update media port. */ |
515 | if (rtp_exp->tuple.dst.u.udp.port != rtp_exp->saved_proto.udp.port && | 559 | if (rtp_exp->tuple.dst.u.udp.port != rtp_exp->saved_proto.udp.port && |
516 | !ip_nat_sdp_port(skb, dataoff, dptr, datalen, | 560 | !nf_nat_sdp_port(skb, protoff, dataoff, dptr, datalen, |
517 | mediaoff, medialen, port)) | 561 | mediaoff, medialen, port)) |
518 | goto err2; | 562 | goto err2; |
519 | 563 | ||
@@ -527,8 +571,8 @@ err1: | |||
527 | } | 571 | } |
528 | 572 | ||
529 | static struct nf_ct_helper_expectfn sip_nat = { | 573 | static struct nf_ct_helper_expectfn sip_nat = { |
530 | .name = "sip", | 574 | .name = "sip", |
531 | .expectfn = ip_nat_sip_expected, | 575 | .expectfn = nf_nat_sip_expected, |
532 | }; | 576 | }; |
533 | 577 | ||
534 | static void __exit nf_nat_sip_fini(void) | 578 | static void __exit nf_nat_sip_fini(void) |
@@ -553,13 +597,13 @@ static int __init nf_nat_sip_init(void) | |||
553 | BUG_ON(nf_nat_sdp_port_hook != NULL); | 597 | BUG_ON(nf_nat_sdp_port_hook != NULL); |
554 | BUG_ON(nf_nat_sdp_session_hook != NULL); | 598 | BUG_ON(nf_nat_sdp_session_hook != NULL); |
555 | BUG_ON(nf_nat_sdp_media_hook != NULL); | 599 | BUG_ON(nf_nat_sdp_media_hook != NULL); |
556 | RCU_INIT_POINTER(nf_nat_sip_hook, ip_nat_sip); | 600 | RCU_INIT_POINTER(nf_nat_sip_hook, nf_nat_sip); |
557 | RCU_INIT_POINTER(nf_nat_sip_seq_adjust_hook, ip_nat_sip_seq_adjust); | 601 | RCU_INIT_POINTER(nf_nat_sip_seq_adjust_hook, nf_nat_sip_seq_adjust); |
558 | RCU_INIT_POINTER(nf_nat_sip_expect_hook, ip_nat_sip_expect); | 602 | RCU_INIT_POINTER(nf_nat_sip_expect_hook, nf_nat_sip_expect); |
559 | RCU_INIT_POINTER(nf_nat_sdp_addr_hook, ip_nat_sdp_addr); | 603 | RCU_INIT_POINTER(nf_nat_sdp_addr_hook, nf_nat_sdp_addr); |
560 | RCU_INIT_POINTER(nf_nat_sdp_port_hook, ip_nat_sdp_port); | 604 | RCU_INIT_POINTER(nf_nat_sdp_port_hook, nf_nat_sdp_port); |
561 | RCU_INIT_POINTER(nf_nat_sdp_session_hook, ip_nat_sdp_session); | 605 | RCU_INIT_POINTER(nf_nat_sdp_session_hook, nf_nat_sdp_session); |
562 | RCU_INIT_POINTER(nf_nat_sdp_media_hook, ip_nat_sdp_media); | 606 | RCU_INIT_POINTER(nf_nat_sdp_media_hook, nf_nat_sdp_media); |
563 | nf_ct_helper_expectfn_register(&sip_nat); | 607 | nf_ct_helper_expectfn_register(&sip_nat); |
564 | return 0; | 608 | return 0; |
565 | } | 609 | } |
diff --git a/net/ipv4/netfilter/nf_nat_tftp.c b/net/netfilter/nf_nat_tftp.c index 9dbb8d284f99..ccabbda71a3e 100644 --- a/net/ipv4/netfilter/nf_nat_tftp.c +++ b/net/netfilter/nf_nat_tftp.c | |||
@@ -11,7 +11,6 @@ | |||
11 | #include <net/netfilter/nf_conntrack_helper.h> | 11 | #include <net/netfilter/nf_conntrack_helper.h> |
12 | #include <net/netfilter/nf_conntrack_expect.h> | 12 | #include <net/netfilter/nf_conntrack_expect.h> |
13 | #include <net/netfilter/nf_nat_helper.h> | 13 | #include <net/netfilter/nf_nat_helper.h> |
14 | #include <net/netfilter/nf_nat_rule.h> | ||
15 | #include <linux/netfilter/nf_conntrack_tftp.h> | 14 | #include <linux/netfilter/nf_conntrack_tftp.h> |
16 | 15 | ||
17 | MODULE_AUTHOR("Magnus Boden <mb@ozaba.mine.nu>"); | 16 | MODULE_AUTHOR("Magnus Boden <mb@ozaba.mine.nu>"); |
diff --git a/net/netfilter/nf_queue.c b/net/netfilter/nf_queue.c index ce60cf0f6c11..8d2cf9ec37a8 100644 --- a/net/netfilter/nf_queue.c +++ b/net/netfilter/nf_queue.c | |||
@@ -118,7 +118,7 @@ static void nf_queue_entry_release_refs(struct nf_queue_entry *entry) | |||
118 | * through nf_reinject(). | 118 | * through nf_reinject(). |
119 | */ | 119 | */ |
120 | static int __nf_queue(struct sk_buff *skb, | 120 | static int __nf_queue(struct sk_buff *skb, |
121 | struct list_head *elem, | 121 | struct nf_hook_ops *elem, |
122 | u_int8_t pf, unsigned int hook, | 122 | u_int8_t pf, unsigned int hook, |
123 | struct net_device *indev, | 123 | struct net_device *indev, |
124 | struct net_device *outdev, | 124 | struct net_device *outdev, |
@@ -155,7 +155,7 @@ static int __nf_queue(struct sk_buff *skb, | |||
155 | 155 | ||
156 | *entry = (struct nf_queue_entry) { | 156 | *entry = (struct nf_queue_entry) { |
157 | .skb = skb, | 157 | .skb = skb, |
158 | .elem = list_entry(elem, struct nf_hook_ops, list), | 158 | .elem = elem, |
159 | .pf = pf, | 159 | .pf = pf, |
160 | .hook = hook, | 160 | .hook = hook, |
161 | .indev = indev, | 161 | .indev = indev, |
@@ -225,7 +225,7 @@ static void nf_bridge_adjust_segmented_data(struct sk_buff *skb) | |||
225 | #endif | 225 | #endif |
226 | 226 | ||
227 | int nf_queue(struct sk_buff *skb, | 227 | int nf_queue(struct sk_buff *skb, |
228 | struct list_head *elem, | 228 | struct nf_hook_ops *elem, |
229 | u_int8_t pf, unsigned int hook, | 229 | u_int8_t pf, unsigned int hook, |
230 | struct net_device *indev, | 230 | struct net_device *indev, |
231 | struct net_device *outdev, | 231 | struct net_device *outdev, |
@@ -287,7 +287,7 @@ int nf_queue(struct sk_buff *skb, | |||
287 | void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict) | 287 | void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict) |
288 | { | 288 | { |
289 | struct sk_buff *skb = entry->skb; | 289 | struct sk_buff *skb = entry->skb; |
290 | struct list_head *elem = &entry->elem->list; | 290 | struct nf_hook_ops *elem = entry->elem; |
291 | const struct nf_afinfo *afinfo; | 291 | const struct nf_afinfo *afinfo; |
292 | int err; | 292 | int err; |
293 | 293 | ||
@@ -297,7 +297,7 @@ void nf_reinject(struct nf_queue_entry *entry, unsigned int verdict) | |||
297 | 297 | ||
298 | /* Continue traversal iff userspace said ok... */ | 298 | /* Continue traversal iff userspace said ok... */ |
299 | if (verdict == NF_REPEAT) { | 299 | if (verdict == NF_REPEAT) { |
300 | elem = elem->prev; | 300 | elem = list_entry(elem->list.prev, struct nf_hook_ops, list); |
301 | verdict = NF_ACCEPT; | 301 | verdict = NF_ACCEPT; |
302 | } | 302 | } |
303 | 303 | ||
diff --git a/net/netfilter/nfnetlink_acct.c b/net/netfilter/nfnetlink_acct.c index b2e7310ca0b8..d7ec92879071 100644 --- a/net/netfilter/nfnetlink_acct.c +++ b/net/netfilter/nfnetlink_acct.c | |||
@@ -79,11 +79,11 @@ nfnl_acct_new(struct sock *nfnl, struct sk_buff *skb, | |||
79 | 79 | ||
80 | if (tb[NFACCT_BYTES]) { | 80 | if (tb[NFACCT_BYTES]) { |
81 | atomic64_set(&nfacct->bytes, | 81 | atomic64_set(&nfacct->bytes, |
82 | be64_to_cpu(nla_get_u64(tb[NFACCT_BYTES]))); | 82 | be64_to_cpu(nla_get_be64(tb[NFACCT_BYTES]))); |
83 | } | 83 | } |
84 | if (tb[NFACCT_PKTS]) { | 84 | if (tb[NFACCT_PKTS]) { |
85 | atomic64_set(&nfacct->pkts, | 85 | atomic64_set(&nfacct->pkts, |
86 | be64_to_cpu(nla_get_u64(tb[NFACCT_PKTS]))); | 86 | be64_to_cpu(nla_get_be64(tb[NFACCT_PKTS]))); |
87 | } | 87 | } |
88 | atomic_set(&nfacct->refcnt, 1); | 88 | atomic_set(&nfacct->refcnt, 1); |
89 | list_add_tail_rcu(&nfacct->head, &nfnl_acct_list); | 89 | list_add_tail_rcu(&nfacct->head, &nfnl_acct_list); |
diff --git a/net/netfilter/nfnetlink_cthelper.c b/net/netfilter/nfnetlink_cthelper.c index d6836193d479..32a1ba3f3e27 100644 --- a/net/netfilter/nfnetlink_cthelper.c +++ b/net/netfilter/nfnetlink_cthelper.c | |||
@@ -74,7 +74,7 @@ nfnl_cthelper_parse_tuple(struct nf_conntrack_tuple *tuple, | |||
74 | if (!tb[NFCTH_TUPLE_L3PROTONUM] || !tb[NFCTH_TUPLE_L4PROTONUM]) | 74 | if (!tb[NFCTH_TUPLE_L3PROTONUM] || !tb[NFCTH_TUPLE_L4PROTONUM]) |
75 | return -EINVAL; | 75 | return -EINVAL; |
76 | 76 | ||
77 | tuple->src.l3num = ntohs(nla_get_u16(tb[NFCTH_TUPLE_L3PROTONUM])); | 77 | tuple->src.l3num = ntohs(nla_get_be16(tb[NFCTH_TUPLE_L3PROTONUM])); |
78 | tuple->dst.protonum = nla_get_u8(tb[NFCTH_TUPLE_L4PROTONUM]); | 78 | tuple->dst.protonum = nla_get_u8(tb[NFCTH_TUPLE_L4PROTONUM]); |
79 | 79 | ||
80 | return 0; | 80 | return 0; |
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index 169ab59ed9d4..be194b144297 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c | |||
@@ -55,6 +55,7 @@ struct nfulnl_instance { | |||
55 | unsigned int qlen; /* number of nlmsgs in skb */ | 55 | unsigned int qlen; /* number of nlmsgs in skb */ |
56 | struct sk_buff *skb; /* pre-allocatd skb */ | 56 | struct sk_buff *skb; /* pre-allocatd skb */ |
57 | struct timer_list timer; | 57 | struct timer_list timer; |
58 | struct user_namespace *peer_user_ns; /* User namespace of the peer process */ | ||
58 | int peer_pid; /* PID of the peer process */ | 59 | int peer_pid; /* PID of the peer process */ |
59 | 60 | ||
60 | /* configurable parameters */ | 61 | /* configurable parameters */ |
@@ -132,7 +133,7 @@ instance_put(struct nfulnl_instance *inst) | |||
132 | static void nfulnl_timer(unsigned long data); | 133 | static void nfulnl_timer(unsigned long data); |
133 | 134 | ||
134 | static struct nfulnl_instance * | 135 | static struct nfulnl_instance * |
135 | instance_create(u_int16_t group_num, int pid) | 136 | instance_create(u_int16_t group_num, int pid, struct user_namespace *user_ns) |
136 | { | 137 | { |
137 | struct nfulnl_instance *inst; | 138 | struct nfulnl_instance *inst; |
138 | int err; | 139 | int err; |
@@ -162,6 +163,7 @@ instance_create(u_int16_t group_num, int pid) | |||
162 | 163 | ||
163 | setup_timer(&inst->timer, nfulnl_timer, (unsigned long)inst); | 164 | setup_timer(&inst->timer, nfulnl_timer, (unsigned long)inst); |
164 | 165 | ||
166 | inst->peer_user_ns = user_ns; | ||
165 | inst->peer_pid = pid; | 167 | inst->peer_pid = pid; |
166 | inst->group_num = group_num; | 168 | inst->group_num = group_num; |
167 | 169 | ||
@@ -480,7 +482,7 @@ __build_packet_message(struct nfulnl_instance *inst, | |||
480 | } | 482 | } |
481 | 483 | ||
482 | if (indev && skb_mac_header_was_set(skb)) { | 484 | if (indev && skb_mac_header_was_set(skb)) { |
483 | if (nla_put_be32(inst->skb, NFULA_HWTYPE, htons(skb->dev->type)) || | 485 | if (nla_put_be16(inst->skb, NFULA_HWTYPE, htons(skb->dev->type)) || |
484 | nla_put_be16(inst->skb, NFULA_HWLEN, | 486 | nla_put_be16(inst->skb, NFULA_HWLEN, |
485 | htons(skb->dev->hard_header_len)) || | 487 | htons(skb->dev->hard_header_len)) || |
486 | nla_put(inst->skb, NFULA_HWHEADER, skb->dev->hard_header_len, | 488 | nla_put(inst->skb, NFULA_HWHEADER, skb->dev->hard_header_len, |
@@ -503,8 +505,11 @@ __build_packet_message(struct nfulnl_instance *inst, | |||
503 | read_lock_bh(&skb->sk->sk_callback_lock); | 505 | read_lock_bh(&skb->sk->sk_callback_lock); |
504 | if (skb->sk->sk_socket && skb->sk->sk_socket->file) { | 506 | if (skb->sk->sk_socket && skb->sk->sk_socket->file) { |
505 | struct file *file = skb->sk->sk_socket->file; | 507 | struct file *file = skb->sk->sk_socket->file; |
506 | __be32 uid = htonl(file->f_cred->fsuid); | 508 | __be32 uid = htonl(from_kuid_munged(inst->peer_user_ns, |
507 | __be32 gid = htonl(file->f_cred->fsgid); | 509 | file->f_cred->fsuid)); |
510 | __be32 gid = htonl(from_kgid_munged(inst->peer_user_ns, | ||
511 | file->f_cred->fsgid)); | ||
512 | /* need to unlock here since NLA_PUT may goto */ | ||
508 | read_unlock_bh(&skb->sk->sk_callback_lock); | 513 | read_unlock_bh(&skb->sk->sk_callback_lock); |
509 | if (nla_put_be32(inst->skb, NFULA_UID, uid) || | 514 | if (nla_put_be32(inst->skb, NFULA_UID, uid) || |
510 | nla_put_be32(inst->skb, NFULA_GID, gid)) | 515 | nla_put_be32(inst->skb, NFULA_GID, gid)) |
@@ -783,7 +788,8 @@ nfulnl_recv_config(struct sock *ctnl, struct sk_buff *skb, | |||
783 | } | 788 | } |
784 | 789 | ||
785 | inst = instance_create(group_num, | 790 | inst = instance_create(group_num, |
786 | NETLINK_CB(skb).pid); | 791 | NETLINK_CB(skb).pid, |
792 | sk_user_ns(NETLINK_CB(skb).ssk)); | ||
787 | if (IS_ERR(inst)) { | 793 | if (IS_ERR(inst)) { |
788 | ret = PTR_ERR(inst); | 794 | ret = PTR_ERR(inst); |
789 | goto out; | 795 | goto out; |
@@ -996,8 +1002,10 @@ static int __init nfnetlink_log_init(void) | |||
996 | 1002 | ||
997 | #ifdef CONFIG_PROC_FS | 1003 | #ifdef CONFIG_PROC_FS |
998 | if (!proc_create("nfnetlink_log", 0440, | 1004 | if (!proc_create("nfnetlink_log", 0440, |
999 | proc_net_netfilter, &nful_file_ops)) | 1005 | proc_net_netfilter, &nful_file_ops)) { |
1006 | status = -ENOMEM; | ||
1000 | goto cleanup_logger; | 1007 | goto cleanup_logger; |
1008 | } | ||
1001 | #endif | 1009 | #endif |
1002 | return status; | 1010 | return status; |
1003 | 1011 | ||
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c index 116018560c60..16c712563860 100644 --- a/net/netfilter/xt_CT.c +++ b/net/netfilter/xt_CT.c | |||
@@ -72,14 +72,44 @@ static u8 xt_ct_find_proto(const struct xt_tgchk_param *par) | |||
72 | return 0; | 72 | return 0; |
73 | } | 73 | } |
74 | 74 | ||
75 | static int | ||
76 | xt_ct_set_helper(struct nf_conn *ct, const char *helper_name, | ||
77 | const struct xt_tgchk_param *par) | ||
78 | { | ||
79 | struct nf_conntrack_helper *helper; | ||
80 | struct nf_conn_help *help; | ||
81 | u8 proto; | ||
82 | |||
83 | proto = xt_ct_find_proto(par); | ||
84 | if (!proto) { | ||
85 | pr_info("You must specify a L4 protocol, and not use " | ||
86 | "inversions on it.\n"); | ||
87 | return -ENOENT; | ||
88 | } | ||
89 | |||
90 | helper = nf_conntrack_helper_try_module_get(helper_name, par->family, | ||
91 | proto); | ||
92 | if (helper == NULL) { | ||
93 | pr_info("No such helper \"%s\"\n", helper_name); | ||
94 | return -ENOENT; | ||
95 | } | ||
96 | |||
97 | help = nf_ct_helper_ext_add(ct, helper, GFP_KERNEL); | ||
98 | if (help == NULL) { | ||
99 | module_put(helper->me); | ||
100 | return -ENOMEM; | ||
101 | } | ||
102 | |||
103 | help->helper = helper; | ||
104 | return 0; | ||
105 | } | ||
106 | |||
75 | static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par) | 107 | static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par) |
76 | { | 108 | { |
77 | struct xt_ct_target_info *info = par->targinfo; | 109 | struct xt_ct_target_info *info = par->targinfo; |
78 | struct nf_conntrack_tuple t; | 110 | struct nf_conntrack_tuple t; |
79 | struct nf_conn_help *help; | ||
80 | struct nf_conn *ct; | 111 | struct nf_conn *ct; |
81 | int ret = 0; | 112 | int ret; |
82 | u8 proto; | ||
83 | 113 | ||
84 | if (info->flags & ~XT_CT_NOTRACK) | 114 | if (info->flags & ~XT_CT_NOTRACK) |
85 | return -EINVAL; | 115 | return -EINVAL; |
@@ -112,31 +142,9 @@ static int xt_ct_tg_check_v0(const struct xt_tgchk_param *par) | |||
112 | goto err3; | 142 | goto err3; |
113 | 143 | ||
114 | if (info->helper[0]) { | 144 | if (info->helper[0]) { |
115 | struct nf_conntrack_helper *helper; | 145 | ret = xt_ct_set_helper(ct, info->helper, par); |
116 | 146 | if (ret < 0) | |
117 | ret = -ENOENT; | ||
118 | proto = xt_ct_find_proto(par); | ||
119 | if (!proto) { | ||
120 | pr_info("You must specify a L4 protocol, " | ||
121 | "and not use inversions on it.\n"); | ||
122 | goto err3; | ||
123 | } | ||
124 | |||
125 | ret = -ENOENT; | ||
126 | helper = nf_conntrack_helper_try_module_get(info->helper, | ||
127 | par->family, | ||
128 | proto); | ||
129 | if (helper == NULL) { | ||
130 | pr_info("No such helper \"%s\"\n", info->helper); | ||
131 | goto err3; | ||
132 | } | ||
133 | |||
134 | ret = -ENOMEM; | ||
135 | help = nf_ct_helper_ext_add(ct, helper, GFP_KERNEL); | ||
136 | if (help == NULL) | ||
137 | goto err3; | 147 | goto err3; |
138 | |||
139 | help->helper = helper; | ||
140 | } | 148 | } |
141 | 149 | ||
142 | __set_bit(IPS_TEMPLATE_BIT, &ct->status); | 150 | __set_bit(IPS_TEMPLATE_BIT, &ct->status); |
@@ -164,17 +172,77 @@ static void __xt_ct_tg_timeout_put(struct ctnl_timeout *timeout) | |||
164 | } | 172 | } |
165 | #endif | 173 | #endif |
166 | 174 | ||
175 | static int | ||
176 | xt_ct_set_timeout(struct nf_conn *ct, const struct xt_tgchk_param *par, | ||
177 | const char *timeout_name) | ||
178 | { | ||
179 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT | ||
180 | typeof(nf_ct_timeout_find_get_hook) timeout_find_get; | ||
181 | struct ctnl_timeout *timeout; | ||
182 | struct nf_conn_timeout *timeout_ext; | ||
183 | const struct ipt_entry *e = par->entryinfo; | ||
184 | struct nf_conntrack_l4proto *l4proto; | ||
185 | int ret = 0; | ||
186 | |||
187 | rcu_read_lock(); | ||
188 | timeout_find_get = rcu_dereference(nf_ct_timeout_find_get_hook); | ||
189 | if (timeout_find_get == NULL) { | ||
190 | ret = -ENOENT; | ||
191 | pr_info("Timeout policy base is empty\n"); | ||
192 | goto out; | ||
193 | } | ||
194 | |||
195 | if (e->ip.invflags & IPT_INV_PROTO) { | ||
196 | ret = -EINVAL; | ||
197 | pr_info("You cannot use inversion on L4 protocol\n"); | ||
198 | goto out; | ||
199 | } | ||
200 | |||
201 | timeout = timeout_find_get(timeout_name); | ||
202 | if (timeout == NULL) { | ||
203 | ret = -ENOENT; | ||
204 | pr_info("No such timeout policy \"%s\"\n", timeout_name); | ||
205 | goto out; | ||
206 | } | ||
207 | |||
208 | if (timeout->l3num != par->family) { | ||
209 | ret = -EINVAL; | ||
210 | pr_info("Timeout policy `%s' can only be used by L3 protocol " | ||
211 | "number %d\n", timeout_name, timeout->l3num); | ||
212 | goto err_put_timeout; | ||
213 | } | ||
214 | /* Make sure the timeout policy matches any existing protocol tracker, | ||
215 | * otherwise default to generic. | ||
216 | */ | ||
217 | l4proto = __nf_ct_l4proto_find(par->family, e->ip.proto); | ||
218 | if (timeout->l4proto->l4proto != l4proto->l4proto) { | ||
219 | ret = -EINVAL; | ||
220 | pr_info("Timeout policy `%s' can only be used by L4 protocol " | ||
221 | "number %d\n", | ||
222 | timeout_name, timeout->l4proto->l4proto); | ||
223 | goto err_put_timeout; | ||
224 | } | ||
225 | timeout_ext = nf_ct_timeout_ext_add(ct, timeout, GFP_ATOMIC); | ||
226 | if (timeout_ext == NULL) | ||
227 | ret = -ENOMEM; | ||
228 | |||
229 | err_put_timeout: | ||
230 | __xt_ct_tg_timeout_put(timeout); | ||
231 | out: | ||
232 | rcu_read_unlock(); | ||
233 | return ret; | ||
234 | #else | ||
235 | return -EOPNOTSUPP; | ||
236 | #endif | ||
237 | } | ||
238 | |||
167 | static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) | 239 | static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) |
168 | { | 240 | { |
169 | struct xt_ct_target_info_v1 *info = par->targinfo; | 241 | struct xt_ct_target_info_v1 *info = par->targinfo; |
170 | struct nf_conntrack_tuple t; | 242 | struct nf_conntrack_tuple t; |
171 | struct nf_conn_help *help; | ||
172 | struct nf_conn *ct; | 243 | struct nf_conn *ct; |
173 | int ret = 0; | 244 | int ret; |
174 | u8 proto; | 245 | |
175 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT | ||
176 | struct ctnl_timeout *timeout; | ||
177 | #endif | ||
178 | if (info->flags & ~XT_CT_NOTRACK) | 246 | if (info->flags & ~XT_CT_NOTRACK) |
179 | return -EINVAL; | 247 | return -EINVAL; |
180 | 248 | ||
@@ -206,93 +274,16 @@ static int xt_ct_tg_check_v1(const struct xt_tgchk_param *par) | |||
206 | goto err3; | 274 | goto err3; |
207 | 275 | ||
208 | if (info->helper[0]) { | 276 | if (info->helper[0]) { |
209 | struct nf_conntrack_helper *helper; | 277 | ret = xt_ct_set_helper(ct, info->helper, par); |
210 | 278 | if (ret < 0) | |
211 | ret = -ENOENT; | ||
212 | proto = xt_ct_find_proto(par); | ||
213 | if (!proto) { | ||
214 | pr_info("You must specify a L4 protocol, " | ||
215 | "and not use inversions on it.\n"); | ||
216 | goto err3; | ||
217 | } | ||
218 | |||
219 | ret = -ENOENT; | ||
220 | helper = nf_conntrack_helper_try_module_get(info->helper, | ||
221 | par->family, | ||
222 | proto); | ||
223 | if (helper == NULL) { | ||
224 | pr_info("No such helper \"%s\"\n", info->helper); | ||
225 | goto err3; | ||
226 | } | ||
227 | |||
228 | ret = -ENOMEM; | ||
229 | help = nf_ct_helper_ext_add(ct, helper, GFP_KERNEL); | ||
230 | if (help == NULL) | ||
231 | goto err3; | 279 | goto err3; |
232 | |||
233 | help->helper = helper; | ||
234 | } | 280 | } |
235 | 281 | ||
236 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT | ||
237 | if (info->timeout[0]) { | 282 | if (info->timeout[0]) { |
238 | typeof(nf_ct_timeout_find_get_hook) timeout_find_get; | 283 | ret = xt_ct_set_timeout(ct, par, info->timeout); |
239 | struct nf_conn_timeout *timeout_ext; | 284 | if (ret < 0) |
240 | 285 | goto err3; | |
241 | rcu_read_lock(); | ||
242 | timeout_find_get = | ||
243 | rcu_dereference(nf_ct_timeout_find_get_hook); | ||
244 | |||
245 | if (timeout_find_get) { | ||
246 | const struct ipt_entry *e = par->entryinfo; | ||
247 | struct nf_conntrack_l4proto *l4proto; | ||
248 | |||
249 | if (e->ip.invflags & IPT_INV_PROTO) { | ||
250 | ret = -EINVAL; | ||
251 | pr_info("You cannot use inversion on " | ||
252 | "L4 protocol\n"); | ||
253 | goto err4; | ||
254 | } | ||
255 | timeout = timeout_find_get(info->timeout); | ||
256 | if (timeout == NULL) { | ||
257 | ret = -ENOENT; | ||
258 | pr_info("No such timeout policy \"%s\"\n", | ||
259 | info->timeout); | ||
260 | goto err4; | ||
261 | } | ||
262 | if (timeout->l3num != par->family) { | ||
263 | ret = -EINVAL; | ||
264 | pr_info("Timeout policy `%s' can only be " | ||
265 | "used by L3 protocol number %d\n", | ||
266 | info->timeout, timeout->l3num); | ||
267 | goto err5; | ||
268 | } | ||
269 | /* Make sure the timeout policy matches any existing | ||
270 | * protocol tracker, otherwise default to generic. | ||
271 | */ | ||
272 | l4proto = __nf_ct_l4proto_find(par->family, | ||
273 | e->ip.proto); | ||
274 | if (timeout->l4proto->l4proto != l4proto->l4proto) { | ||
275 | ret = -EINVAL; | ||
276 | pr_info("Timeout policy `%s' can only be " | ||
277 | "used by L4 protocol number %d\n", | ||
278 | info->timeout, | ||
279 | timeout->l4proto->l4proto); | ||
280 | goto err5; | ||
281 | } | ||
282 | timeout_ext = nf_ct_timeout_ext_add(ct, timeout, | ||
283 | GFP_ATOMIC); | ||
284 | if (timeout_ext == NULL) { | ||
285 | ret = -ENOMEM; | ||
286 | goto err5; | ||
287 | } | ||
288 | } else { | ||
289 | ret = -ENOENT; | ||
290 | pr_info("Timeout policy base is empty\n"); | ||
291 | goto err4; | ||
292 | } | ||
293 | rcu_read_unlock(); | ||
294 | } | 286 | } |
295 | #endif | ||
296 | 287 | ||
297 | __set_bit(IPS_TEMPLATE_BIT, &ct->status); | 288 | __set_bit(IPS_TEMPLATE_BIT, &ct->status); |
298 | __set_bit(IPS_CONFIRMED_BIT, &ct->status); | 289 | __set_bit(IPS_CONFIRMED_BIT, &ct->status); |
@@ -300,12 +291,6 @@ out: | |||
300 | info->ct = ct; | 291 | info->ct = ct; |
301 | return 0; | 292 | return 0; |
302 | 293 | ||
303 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT | ||
304 | err5: | ||
305 | __xt_ct_tg_timeout_put(timeout); | ||
306 | err4: | ||
307 | rcu_read_unlock(); | ||
308 | #endif | ||
309 | err3: | 294 | err3: |
310 | nf_conntrack_free(ct); | 295 | nf_conntrack_free(ct); |
311 | err2: | 296 | err2: |
@@ -330,15 +315,30 @@ static void xt_ct_tg_destroy_v0(const struct xt_tgdtor_param *par) | |||
330 | nf_ct_put(info->ct); | 315 | nf_ct_put(info->ct); |
331 | } | 316 | } |
332 | 317 | ||
333 | static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par) | 318 | static void xt_ct_destroy_timeout(struct nf_conn *ct) |
334 | { | 319 | { |
335 | struct xt_ct_target_info_v1 *info = par->targinfo; | ||
336 | struct nf_conn *ct = info->ct; | ||
337 | struct nf_conn_help *help; | ||
338 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT | 320 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT |
339 | struct nf_conn_timeout *timeout_ext; | 321 | struct nf_conn_timeout *timeout_ext; |
340 | typeof(nf_ct_timeout_put_hook) timeout_put; | 322 | typeof(nf_ct_timeout_put_hook) timeout_put; |
323 | |||
324 | rcu_read_lock(); | ||
325 | timeout_put = rcu_dereference(nf_ct_timeout_put_hook); | ||
326 | |||
327 | if (timeout_put) { | ||
328 | timeout_ext = nf_ct_timeout_find(ct); | ||
329 | if (timeout_ext) | ||
330 | timeout_put(timeout_ext->timeout); | ||
331 | } | ||
332 | rcu_read_unlock(); | ||
341 | #endif | 333 | #endif |
334 | } | ||
335 | |||
336 | static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par) | ||
337 | { | ||
338 | struct xt_ct_target_info_v1 *info = par->targinfo; | ||
339 | struct nf_conn *ct = info->ct; | ||
340 | struct nf_conn_help *help; | ||
341 | |||
342 | if (!nf_ct_is_untracked(ct)) { | 342 | if (!nf_ct_is_untracked(ct)) { |
343 | help = nfct_help(ct); | 343 | help = nfct_help(ct); |
344 | if (help) | 344 | if (help) |
@@ -346,17 +346,7 @@ static void xt_ct_tg_destroy_v1(const struct xt_tgdtor_param *par) | |||
346 | 346 | ||
347 | nf_ct_l3proto_module_put(par->family); | 347 | nf_ct_l3proto_module_put(par->family); |
348 | 348 | ||
349 | #ifdef CONFIG_NF_CONNTRACK_TIMEOUT | 349 | xt_ct_destroy_timeout(ct); |
350 | rcu_read_lock(); | ||
351 | timeout_put = rcu_dereference(nf_ct_timeout_put_hook); | ||
352 | |||
353 | if (timeout_put) { | ||
354 | timeout_ext = nf_ct_timeout_find(ct); | ||
355 | if (timeout_ext) | ||
356 | timeout_put(timeout_ext->timeout); | ||
357 | } | ||
358 | rcu_read_unlock(); | ||
359 | #endif | ||
360 | } | 350 | } |
361 | nf_ct_put(info->ct); | 351 | nf_ct_put(info->ct); |
362 | } | 352 | } |
diff --git a/net/netfilter/xt_LOG.c b/net/netfilter/xt_LOG.c index ff5f75fddb15..02a2bf49dcbd 100644 --- a/net/netfilter/xt_LOG.c +++ b/net/netfilter/xt_LOG.c | |||
@@ -363,10 +363,12 @@ static void dump_ipv4_packet(struct sbuff *m, | |||
363 | /* Max length: 15 "UID=4294967295 " */ | 363 | /* Max length: 15 "UID=4294967295 " */ |
364 | if ((logflags & XT_LOG_UID) && !iphoff && skb->sk) { | 364 | if ((logflags & XT_LOG_UID) && !iphoff && skb->sk) { |
365 | read_lock_bh(&skb->sk->sk_callback_lock); | 365 | read_lock_bh(&skb->sk->sk_callback_lock); |
366 | if (skb->sk->sk_socket && skb->sk->sk_socket->file) | 366 | if (skb->sk->sk_socket && skb->sk->sk_socket->file) { |
367 | const struct cred *cred = skb->sk->sk_socket->file->f_cred; | ||
367 | sb_add(m, "UID=%u GID=%u ", | 368 | sb_add(m, "UID=%u GID=%u ", |
368 | skb->sk->sk_socket->file->f_cred->fsuid, | 369 | from_kuid_munged(&init_user_ns, cred->fsuid), |
369 | skb->sk->sk_socket->file->f_cred->fsgid); | 370 | from_kgid_munged(&init_user_ns, cred->fsgid)); |
371 | } | ||
370 | read_unlock_bh(&skb->sk->sk_callback_lock); | 372 | read_unlock_bh(&skb->sk->sk_callback_lock); |
371 | } | 373 | } |
372 | 374 | ||
@@ -719,10 +721,12 @@ static void dump_ipv6_packet(struct sbuff *m, | |||
719 | /* Max length: 15 "UID=4294967295 " */ | 721 | /* Max length: 15 "UID=4294967295 " */ |
720 | if ((logflags & XT_LOG_UID) && recurse && skb->sk) { | 722 | if ((logflags & XT_LOG_UID) && recurse && skb->sk) { |
721 | read_lock_bh(&skb->sk->sk_callback_lock); | 723 | read_lock_bh(&skb->sk->sk_callback_lock); |
722 | if (skb->sk->sk_socket && skb->sk->sk_socket->file) | 724 | if (skb->sk->sk_socket && skb->sk->sk_socket->file) { |
725 | const struct cred *cred = skb->sk->sk_socket->file->f_cred; | ||
723 | sb_add(m, "UID=%u GID=%u ", | 726 | sb_add(m, "UID=%u GID=%u ", |
724 | skb->sk->sk_socket->file->f_cred->fsuid, | 727 | from_kuid_munged(&init_user_ns, cred->fsuid), |
725 | skb->sk->sk_socket->file->f_cred->fsgid); | 728 | from_kgid_munged(&init_user_ns, cred->fsgid)); |
729 | } | ||
726 | read_unlock_bh(&skb->sk->sk_callback_lock); | 730 | read_unlock_bh(&skb->sk->sk_callback_lock); |
727 | } | 731 | } |
728 | 732 | ||
diff --git a/net/netfilter/xt_NFQUEUE.c b/net/netfilter/xt_NFQUEUE.c index 7babe7d68716..817f9e9f2b16 100644 --- a/net/netfilter/xt_NFQUEUE.c +++ b/net/netfilter/xt_NFQUEUE.c | |||
@@ -43,7 +43,7 @@ static u32 hash_v4(const struct sk_buff *skb) | |||
43 | const struct iphdr *iph = ip_hdr(skb); | 43 | const struct iphdr *iph = ip_hdr(skb); |
44 | 44 | ||
45 | /* packets in either direction go into same queue */ | 45 | /* packets in either direction go into same queue */ |
46 | if (iph->saddr < iph->daddr) | 46 | if ((__force u32)iph->saddr < (__force u32)iph->daddr) |
47 | return jhash_3words((__force u32)iph->saddr, | 47 | return jhash_3words((__force u32)iph->saddr, |
48 | (__force u32)iph->daddr, iph->protocol, jhash_initval); | 48 | (__force u32)iph->daddr, iph->protocol, jhash_initval); |
49 | 49 | ||
@@ -57,7 +57,8 @@ static u32 hash_v6(const struct sk_buff *skb) | |||
57 | const struct ipv6hdr *ip6h = ipv6_hdr(skb); | 57 | const struct ipv6hdr *ip6h = ipv6_hdr(skb); |
58 | u32 a, b, c; | 58 | u32 a, b, c; |
59 | 59 | ||
60 | if (ip6h->saddr.s6_addr32[3] < ip6h->daddr.s6_addr32[3]) { | 60 | if ((__force u32)ip6h->saddr.s6_addr32[3] < |
61 | (__force u32)ip6h->daddr.s6_addr32[3]) { | ||
61 | a = (__force u32) ip6h->saddr.s6_addr32[3]; | 62 | a = (__force u32) ip6h->saddr.s6_addr32[3]; |
62 | b = (__force u32) ip6h->daddr.s6_addr32[3]; | 63 | b = (__force u32) ip6h->daddr.s6_addr32[3]; |
63 | } else { | 64 | } else { |
@@ -65,7 +66,8 @@ static u32 hash_v6(const struct sk_buff *skb) | |||
65 | a = (__force u32) ip6h->daddr.s6_addr32[3]; | 66 | a = (__force u32) ip6h->daddr.s6_addr32[3]; |
66 | } | 67 | } |
67 | 68 | ||
68 | if (ip6h->saddr.s6_addr32[1] < ip6h->daddr.s6_addr32[1]) | 69 | if ((__force u32)ip6h->saddr.s6_addr32[1] < |
70 | (__force u32)ip6h->daddr.s6_addr32[1]) | ||
69 | c = (__force u32) ip6h->saddr.s6_addr32[1]; | 71 | c = (__force u32) ip6h->saddr.s6_addr32[1]; |
70 | else | 72 | else |
71 | c = (__force u32) ip6h->daddr.s6_addr32[1]; | 73 | c = (__force u32) ip6h->daddr.s6_addr32[1]; |
diff --git a/net/netfilter/xt_NOTRACK.c b/net/netfilter/xt_NOTRACK.c deleted file mode 100644 index 9d782181b6c8..000000000000 --- a/net/netfilter/xt_NOTRACK.c +++ /dev/null | |||
@@ -1,53 +0,0 @@ | |||
1 | /* This is a module which is used for setting up fake conntracks | ||
2 | * on packets so that they are not seen by the conntrack/NAT code. | ||
3 | */ | ||
4 | #include <linux/module.h> | ||
5 | #include <linux/skbuff.h> | ||
6 | |||
7 | #include <linux/netfilter/x_tables.h> | ||
8 | #include <net/netfilter/nf_conntrack.h> | ||
9 | |||
10 | MODULE_DESCRIPTION("Xtables: Disabling connection tracking for packets"); | ||
11 | MODULE_LICENSE("GPL"); | ||
12 | MODULE_ALIAS("ipt_NOTRACK"); | ||
13 | MODULE_ALIAS("ip6t_NOTRACK"); | ||
14 | |||
15 | static unsigned int | ||
16 | notrack_tg(struct sk_buff *skb, const struct xt_action_param *par) | ||
17 | { | ||
18 | /* Previously seen (loopback)? Ignore. */ | ||
19 | if (skb->nfct != NULL) | ||
20 | return XT_CONTINUE; | ||
21 | |||
22 | /* Attach fake conntrack entry. | ||
23 | If there is a real ct entry correspondig to this packet, | ||
24 | it'll hang aroun till timing out. We don't deal with it | ||
25 | for performance reasons. JK */ | ||
26 | skb->nfct = &nf_ct_untracked_get()->ct_general; | ||
27 | skb->nfctinfo = IP_CT_NEW; | ||
28 | nf_conntrack_get(skb->nfct); | ||
29 | |||
30 | return XT_CONTINUE; | ||
31 | } | ||
32 | |||
33 | static struct xt_target notrack_tg_reg __read_mostly = { | ||
34 | .name = "NOTRACK", | ||
35 | .revision = 0, | ||
36 | .family = NFPROTO_UNSPEC, | ||
37 | .target = notrack_tg, | ||
38 | .table = "raw", | ||
39 | .me = THIS_MODULE, | ||
40 | }; | ||
41 | |||
42 | static int __init notrack_tg_init(void) | ||
43 | { | ||
44 | return xt_register_target(¬rack_tg_reg); | ||
45 | } | ||
46 | |||
47 | static void __exit notrack_tg_exit(void) | ||
48 | { | ||
49 | xt_unregister_target(¬rack_tg_reg); | ||
50 | } | ||
51 | |||
52 | module_init(notrack_tg_init); | ||
53 | module_exit(notrack_tg_exit); | ||
diff --git a/net/netfilter/xt_nat.c b/net/netfilter/xt_nat.c new file mode 100644 index 000000000000..81aafa8e4fef --- /dev/null +++ b/net/netfilter/xt_nat.c | |||
@@ -0,0 +1,170 @@ | |||
1 | /* | ||
2 | * (C) 1999-2001 Paul `Rusty' Russell | ||
3 | * (C) 2002-2006 Netfilter Core Team <coreteam@netfilter.org> | ||
4 | * (C) 2011 Patrick McHardy <kaber@trash.net> | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License version 2 as | ||
8 | * published by the Free Software Foundation. | ||
9 | */ | ||
10 | |||
11 | #include <linux/module.h> | ||
12 | #include <linux/skbuff.h> | ||
13 | #include <linux/netfilter.h> | ||
14 | #include <linux/netfilter/x_tables.h> | ||
15 | #include <net/netfilter/nf_nat_core.h> | ||
16 | |||
17 | static int xt_nat_checkentry_v0(const struct xt_tgchk_param *par) | ||
18 | { | ||
19 | const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; | ||
20 | |||
21 | if (mr->rangesize != 1) { | ||
22 | pr_info("%s: multiple ranges no longer supported\n", | ||
23 | par->target->name); | ||
24 | return -EINVAL; | ||
25 | } | ||
26 | return 0; | ||
27 | } | ||
28 | |||
29 | static void xt_nat_convert_range(struct nf_nat_range *dst, | ||
30 | const struct nf_nat_ipv4_range *src) | ||
31 | { | ||
32 | memset(&dst->min_addr, 0, sizeof(dst->min_addr)); | ||
33 | memset(&dst->max_addr, 0, sizeof(dst->max_addr)); | ||
34 | |||
35 | dst->flags = src->flags; | ||
36 | dst->min_addr.ip = src->min_ip; | ||
37 | dst->max_addr.ip = src->max_ip; | ||
38 | dst->min_proto = src->min; | ||
39 | dst->max_proto = src->max; | ||
40 | } | ||
41 | |||
42 | static unsigned int | ||
43 | xt_snat_target_v0(struct sk_buff *skb, const struct xt_action_param *par) | ||
44 | { | ||
45 | const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; | ||
46 | struct nf_nat_range range; | ||
47 | enum ip_conntrack_info ctinfo; | ||
48 | struct nf_conn *ct; | ||
49 | |||
50 | ct = nf_ct_get(skb, &ctinfo); | ||
51 | NF_CT_ASSERT(ct != NULL && | ||
52 | (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED || | ||
53 | ctinfo == IP_CT_RELATED_REPLY)); | ||
54 | |||
55 | xt_nat_convert_range(&range, &mr->range[0]); | ||
56 | return nf_nat_setup_info(ct, &range, NF_NAT_MANIP_SRC); | ||
57 | } | ||
58 | |||
59 | static unsigned int | ||
60 | xt_dnat_target_v0(struct sk_buff *skb, const struct xt_action_param *par) | ||
61 | { | ||
62 | const struct nf_nat_ipv4_multi_range_compat *mr = par->targinfo; | ||
63 | struct nf_nat_range range; | ||
64 | enum ip_conntrack_info ctinfo; | ||
65 | struct nf_conn *ct; | ||
66 | |||
67 | ct = nf_ct_get(skb, &ctinfo); | ||
68 | NF_CT_ASSERT(ct != NULL && | ||
69 | (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)); | ||
70 | |||
71 | xt_nat_convert_range(&range, &mr->range[0]); | ||
72 | return nf_nat_setup_info(ct, &range, NF_NAT_MANIP_DST); | ||
73 | } | ||
74 | |||
75 | static unsigned int | ||
76 | xt_snat_target_v1(struct sk_buff *skb, const struct xt_action_param *par) | ||
77 | { | ||
78 | const struct nf_nat_range *range = par->targinfo; | ||
79 | enum ip_conntrack_info ctinfo; | ||
80 | struct nf_conn *ct; | ||
81 | |||
82 | ct = nf_ct_get(skb, &ctinfo); | ||
83 | NF_CT_ASSERT(ct != NULL && | ||
84 | (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED || | ||
85 | ctinfo == IP_CT_RELATED_REPLY)); | ||
86 | |||
87 | return nf_nat_setup_info(ct, range, NF_NAT_MANIP_SRC); | ||
88 | } | ||
89 | |||
90 | static unsigned int | ||
91 | xt_dnat_target_v1(struct sk_buff *skb, const struct xt_action_param *par) | ||
92 | { | ||
93 | const struct nf_nat_range *range = par->targinfo; | ||
94 | enum ip_conntrack_info ctinfo; | ||
95 | struct nf_conn *ct; | ||
96 | |||
97 | ct = nf_ct_get(skb, &ctinfo); | ||
98 | NF_CT_ASSERT(ct != NULL && | ||
99 | (ctinfo == IP_CT_NEW || ctinfo == IP_CT_RELATED)); | ||
100 | |||
101 | return nf_nat_setup_info(ct, range, NF_NAT_MANIP_DST); | ||
102 | } | ||
103 | |||
104 | static struct xt_target xt_nat_target_reg[] __read_mostly = { | ||
105 | { | ||
106 | .name = "SNAT", | ||
107 | .revision = 0, | ||
108 | .checkentry = xt_nat_checkentry_v0, | ||
109 | .target = xt_snat_target_v0, | ||
110 | .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat), | ||
111 | .family = NFPROTO_IPV4, | ||
112 | .table = "nat", | ||
113 | .hooks = (1 << NF_INET_POST_ROUTING) | | ||
114 | (1 << NF_INET_LOCAL_OUT), | ||
115 | .me = THIS_MODULE, | ||
116 | }, | ||
117 | { | ||
118 | .name = "DNAT", | ||
119 | .revision = 0, | ||
120 | .checkentry = xt_nat_checkentry_v0, | ||
121 | .target = xt_dnat_target_v0, | ||
122 | .targetsize = sizeof(struct nf_nat_ipv4_multi_range_compat), | ||
123 | .family = NFPROTO_IPV4, | ||
124 | .table = "nat", | ||
125 | .hooks = (1 << NF_INET_PRE_ROUTING) | | ||
126 | (1 << NF_INET_LOCAL_IN), | ||
127 | .me = THIS_MODULE, | ||
128 | }, | ||
129 | { | ||
130 | .name = "SNAT", | ||
131 | .revision = 1, | ||
132 | .target = xt_snat_target_v1, | ||
133 | .targetsize = sizeof(struct nf_nat_range), | ||
134 | .table = "nat", | ||
135 | .hooks = (1 << NF_INET_POST_ROUTING) | | ||
136 | (1 << NF_INET_LOCAL_OUT), | ||
137 | .me = THIS_MODULE, | ||
138 | }, | ||
139 | { | ||
140 | .name = "DNAT", | ||
141 | .revision = 1, | ||
142 | .target = xt_dnat_target_v1, | ||
143 | .targetsize = sizeof(struct nf_nat_range), | ||
144 | .table = "nat", | ||
145 | .hooks = (1 << NF_INET_PRE_ROUTING) | | ||
146 | (1 << NF_INET_LOCAL_IN), | ||
147 | .me = THIS_MODULE, | ||
148 | }, | ||
149 | }; | ||
150 | |||
151 | static int __init xt_nat_init(void) | ||
152 | { | ||
153 | return xt_register_targets(xt_nat_target_reg, | ||
154 | ARRAY_SIZE(xt_nat_target_reg)); | ||
155 | } | ||
156 | |||
157 | static void __exit xt_nat_exit(void) | ||
158 | { | ||
159 | xt_unregister_targets(xt_nat_target_reg, ARRAY_SIZE(xt_nat_target_reg)); | ||
160 | } | ||
161 | |||
162 | module_init(xt_nat_init); | ||
163 | module_exit(xt_nat_exit); | ||
164 | |||
165 | MODULE_LICENSE("GPL"); | ||
166 | MODULE_AUTHOR("Patrick McHardy <kaber@trash.net>"); | ||
167 | MODULE_ALIAS("ipt_SNAT"); | ||
168 | MODULE_ALIAS("ipt_DNAT"); | ||
169 | MODULE_ALIAS("ip6t_SNAT"); | ||
170 | MODULE_ALIAS("ip6t_DNAT"); | ||
diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c index 846f895cb656..a5e673d32bda 100644 --- a/net/netfilter/xt_osf.c +++ b/net/netfilter/xt_osf.c | |||
@@ -269,7 +269,7 @@ xt_osf_match_packet(const struct sk_buff *skb, struct xt_action_param *p) | |||
269 | mss <<= 8; | 269 | mss <<= 8; |
270 | mss |= optp[2]; | 270 | mss |= optp[2]; |
271 | 271 | ||
272 | mss = ntohs(mss); | 272 | mss = ntohs((__force __be16)mss); |
273 | break; | 273 | break; |
274 | case OSFOPT_TS: | 274 | case OSFOPT_TS: |
275 | loop_cont = 1; | 275 | loop_cont = 1; |
diff --git a/net/netfilter/xt_owner.c b/net/netfilter/xt_owner.c index 772d7389b337..ca2e577ed8ac 100644 --- a/net/netfilter/xt_owner.c +++ b/net/netfilter/xt_owner.c | |||
@@ -17,6 +17,17 @@ | |||
17 | #include <linux/netfilter/x_tables.h> | 17 | #include <linux/netfilter/x_tables.h> |
18 | #include <linux/netfilter/xt_owner.h> | 18 | #include <linux/netfilter/xt_owner.h> |
19 | 19 | ||
20 | static int owner_check(const struct xt_mtchk_param *par) | ||
21 | { | ||
22 | struct xt_owner_match_info *info = par->matchinfo; | ||
23 | |||
24 | /* For now only allow adding matches from the initial user namespace */ | ||
25 | if ((info->match & (XT_OWNER_UID|XT_OWNER_GID)) && | ||
26 | (current_user_ns() != &init_user_ns)) | ||
27 | return -EINVAL; | ||
28 | return 0; | ||
29 | } | ||
30 | |||
20 | static bool | 31 | static bool |
21 | owner_mt(const struct sk_buff *skb, struct xt_action_param *par) | 32 | owner_mt(const struct sk_buff *skb, struct xt_action_param *par) |
22 | { | 33 | { |
@@ -37,17 +48,23 @@ owner_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
37 | return ((info->match ^ info->invert) & | 48 | return ((info->match ^ info->invert) & |
38 | (XT_OWNER_UID | XT_OWNER_GID)) == 0; | 49 | (XT_OWNER_UID | XT_OWNER_GID)) == 0; |
39 | 50 | ||
40 | if (info->match & XT_OWNER_UID) | 51 | if (info->match & XT_OWNER_UID) { |
41 | if ((filp->f_cred->fsuid >= info->uid_min && | 52 | kuid_t uid_min = make_kuid(&init_user_ns, info->uid_min); |
42 | filp->f_cred->fsuid <= info->uid_max) ^ | 53 | kuid_t uid_max = make_kuid(&init_user_ns, info->uid_max); |
54 | if ((uid_gte(filp->f_cred->fsuid, uid_min) && | ||
55 | uid_lte(filp->f_cred->fsuid, uid_max)) ^ | ||
43 | !(info->invert & XT_OWNER_UID)) | 56 | !(info->invert & XT_OWNER_UID)) |
44 | return false; | 57 | return false; |
58 | } | ||
45 | 59 | ||
46 | if (info->match & XT_OWNER_GID) | 60 | if (info->match & XT_OWNER_GID) { |
47 | if ((filp->f_cred->fsgid >= info->gid_min && | 61 | kgid_t gid_min = make_kgid(&init_user_ns, info->gid_min); |
48 | filp->f_cred->fsgid <= info->gid_max) ^ | 62 | kgid_t gid_max = make_kgid(&init_user_ns, info->gid_max); |
63 | if ((gid_gte(filp->f_cred->fsgid, gid_min) && | ||
64 | gid_lte(filp->f_cred->fsgid, gid_max)) ^ | ||
49 | !(info->invert & XT_OWNER_GID)) | 65 | !(info->invert & XT_OWNER_GID)) |
50 | return false; | 66 | return false; |
67 | } | ||
51 | 68 | ||
52 | return true; | 69 | return true; |
53 | } | 70 | } |
@@ -56,6 +73,7 @@ static struct xt_match owner_mt_reg __read_mostly = { | |||
56 | .name = "owner", | 73 | .name = "owner", |
57 | .revision = 1, | 74 | .revision = 1, |
58 | .family = NFPROTO_UNSPEC, | 75 | .family = NFPROTO_UNSPEC, |
76 | .checkentry = owner_check, | ||
59 | .match = owner_mt, | 77 | .match = owner_mt, |
60 | .matchsize = sizeof(struct xt_owner_match_info), | 78 | .matchsize = sizeof(struct xt_owner_match_info), |
61 | .hooks = (1 << NF_INET_LOCAL_OUT) | | 79 | .hooks = (1 << NF_INET_LOCAL_OUT) | |
diff --git a/net/netfilter/xt_recent.c b/net/netfilter/xt_recent.c index ae2ad1eec8d0..4635c9b00459 100644 --- a/net/netfilter/xt_recent.c +++ b/net/netfilter/xt_recent.c | |||
@@ -317,6 +317,8 @@ static int recent_mt_check(const struct xt_mtchk_param *par, | |||
317 | struct recent_table *t; | 317 | struct recent_table *t; |
318 | #ifdef CONFIG_PROC_FS | 318 | #ifdef CONFIG_PROC_FS |
319 | struct proc_dir_entry *pde; | 319 | struct proc_dir_entry *pde; |
320 | kuid_t uid; | ||
321 | kgid_t gid; | ||
320 | #endif | 322 | #endif |
321 | unsigned int i; | 323 | unsigned int i; |
322 | int ret = -EINVAL; | 324 | int ret = -EINVAL; |
@@ -372,6 +374,13 @@ static int recent_mt_check(const struct xt_mtchk_param *par, | |||
372 | for (i = 0; i < ip_list_hash_size; i++) | 374 | for (i = 0; i < ip_list_hash_size; i++) |
373 | INIT_LIST_HEAD(&t->iphash[i]); | 375 | INIT_LIST_HEAD(&t->iphash[i]); |
374 | #ifdef CONFIG_PROC_FS | 376 | #ifdef CONFIG_PROC_FS |
377 | uid = make_kuid(&init_user_ns, ip_list_uid); | ||
378 | gid = make_kgid(&init_user_ns, ip_list_gid); | ||
379 | if (!uid_valid(uid) || !gid_valid(gid)) { | ||
380 | kfree(t); | ||
381 | ret = -EINVAL; | ||
382 | goto out; | ||
383 | } | ||
375 | pde = proc_create_data(t->name, ip_list_perms, recent_net->xt_recent, | 384 | pde = proc_create_data(t->name, ip_list_perms, recent_net->xt_recent, |
376 | &recent_mt_fops, t); | 385 | &recent_mt_fops, t); |
377 | if (pde == NULL) { | 386 | if (pde == NULL) { |
@@ -379,8 +388,8 @@ static int recent_mt_check(const struct xt_mtchk_param *par, | |||
379 | ret = -ENOMEM; | 388 | ret = -ENOMEM; |
380 | goto out; | 389 | goto out; |
381 | } | 390 | } |
382 | pde->uid = ip_list_uid; | 391 | pde->uid = uid; |
383 | pde->gid = ip_list_gid; | 392 | pde->gid = gid; |
384 | #endif | 393 | #endif |
385 | spin_lock_bh(&recent_lock); | 394 | spin_lock_bh(&recent_lock); |
386 | list_add_tail(&t->list, &recent_net->tables); | 395 | list_add_tail(&t->list, &recent_net->tables); |
diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c index 9ea482d08cf7..63b2bdb59e95 100644 --- a/net/netfilter/xt_socket.c +++ b/net/netfilter/xt_socket.c | |||
@@ -108,9 +108,9 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par, | |||
108 | const struct iphdr *iph = ip_hdr(skb); | 108 | const struct iphdr *iph = ip_hdr(skb); |
109 | struct udphdr _hdr, *hp = NULL; | 109 | struct udphdr _hdr, *hp = NULL; |
110 | struct sock *sk; | 110 | struct sock *sk; |
111 | __be32 daddr, saddr; | 111 | __be32 uninitialized_var(daddr), uninitialized_var(saddr); |
112 | __be16 dport, sport; | 112 | __be16 uninitialized_var(dport), uninitialized_var(sport); |
113 | u8 protocol; | 113 | u8 uninitialized_var(protocol); |
114 | #ifdef XT_SOCKET_HAVE_CONNTRACK | 114 | #ifdef XT_SOCKET_HAVE_CONNTRACK |
115 | struct nf_conn const *ct; | 115 | struct nf_conn const *ct; |
116 | enum ip_conntrack_info ctinfo; | 116 | enum ip_conntrack_info ctinfo; |
@@ -261,9 +261,9 @@ socket_mt6_v1(const struct sk_buff *skb, struct xt_action_param *par) | |||
261 | struct ipv6hdr *iph = ipv6_hdr(skb); | 261 | struct ipv6hdr *iph = ipv6_hdr(skb); |
262 | struct udphdr _hdr, *hp = NULL; | 262 | struct udphdr _hdr, *hp = NULL; |
263 | struct sock *sk; | 263 | struct sock *sk; |
264 | struct in6_addr *daddr, *saddr; | 264 | struct in6_addr *daddr = NULL, *saddr = NULL; |
265 | __be16 dport, sport; | 265 | __be16 uninitialized_var(dport), uninitialized_var(sport); |
266 | int thoff = 0, tproto; | 266 | int thoff = 0, uninitialized_var(tproto); |
267 | const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo; | 267 | const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo; |
268 | 268 | ||
269 | tproto = ipv6_find_hdr(skb, &thoff, -1, NULL, NULL); | 269 | tproto = ipv6_find_hdr(skb, &thoff, -1, NULL, NULL); |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 5463969da45b..382119917166 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -912,7 +912,8 @@ static void netlink_rcv_wake(struct sock *sk) | |||
912 | wake_up_interruptible(&nlk->wait); | 912 | wake_up_interruptible(&nlk->wait); |
913 | } | 913 | } |
914 | 914 | ||
915 | static int netlink_unicast_kernel(struct sock *sk, struct sk_buff *skb) | 915 | static int netlink_unicast_kernel(struct sock *sk, struct sk_buff *skb, |
916 | struct sock *ssk) | ||
916 | { | 917 | { |
917 | int ret; | 918 | int ret; |
918 | struct netlink_sock *nlk = nlk_sk(sk); | 919 | struct netlink_sock *nlk = nlk_sk(sk); |
@@ -921,6 +922,7 @@ static int netlink_unicast_kernel(struct sock *sk, struct sk_buff *skb) | |||
921 | if (nlk->netlink_rcv != NULL) { | 922 | if (nlk->netlink_rcv != NULL) { |
922 | ret = skb->len; | 923 | ret = skb->len; |
923 | skb_set_owner_r(skb, sk); | 924 | skb_set_owner_r(skb, sk); |
925 | NETLINK_CB(skb).ssk = ssk; | ||
924 | nlk->netlink_rcv(skb); | 926 | nlk->netlink_rcv(skb); |
925 | consume_skb(skb); | 927 | consume_skb(skb); |
926 | } else { | 928 | } else { |
@@ -947,7 +949,7 @@ retry: | |||
947 | return PTR_ERR(sk); | 949 | return PTR_ERR(sk); |
948 | } | 950 | } |
949 | if (netlink_is_kernel(sk)) | 951 | if (netlink_is_kernel(sk)) |
950 | return netlink_unicast_kernel(sk, skb); | 952 | return netlink_unicast_kernel(sk, skb, ssk); |
951 | 953 | ||
952 | if (sk_filter(sk, skb)) { | 954 | if (sk_filter(sk, skb)) { |
953 | err = skb->len; | 955 | err = skb->len; |
@@ -1362,7 +1364,7 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1362 | if (NULL == siocb->scm) | 1364 | if (NULL == siocb->scm) |
1363 | siocb->scm = &scm; | 1365 | siocb->scm = &scm; |
1364 | 1366 | ||
1365 | err = scm_send(sock, msg, siocb->scm); | 1367 | err = scm_send(sock, msg, siocb->scm, true); |
1366 | if (err < 0) | 1368 | if (err < 0) |
1367 | return err; | 1369 | return err; |
1368 | 1370 | ||
@@ -1373,7 +1375,8 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1373 | dst_pid = addr->nl_pid; | 1375 | dst_pid = addr->nl_pid; |
1374 | dst_group = ffs(addr->nl_groups); | 1376 | dst_group = ffs(addr->nl_groups); |
1375 | err = -EPERM; | 1377 | err = -EPERM; |
1376 | if (dst_group && !netlink_capable(sock, NL_NONROOT_SEND)) | 1378 | if ((dst_group || dst_pid) && |
1379 | !netlink_capable(sock, NL_NONROOT_SEND)) | ||
1377 | goto out; | 1380 | goto out; |
1378 | } else { | 1381 | } else { |
1379 | dst_pid = nlk->dst_pid; | 1382 | dst_pid = nlk->dst_pid; |
@@ -2147,6 +2150,7 @@ static void __init netlink_add_usersock_entry(void) | |||
2147 | rcu_assign_pointer(nl_table[NETLINK_USERSOCK].listeners, listeners); | 2150 | rcu_assign_pointer(nl_table[NETLINK_USERSOCK].listeners, listeners); |
2148 | nl_table[NETLINK_USERSOCK].module = THIS_MODULE; | 2151 | nl_table[NETLINK_USERSOCK].module = THIS_MODULE; |
2149 | nl_table[NETLINK_USERSOCK].registered = 1; | 2152 | nl_table[NETLINK_USERSOCK].registered = 1; |
2153 | nl_table[NETLINK_USERSOCK].nl_nonroot = NL_NONROOT_SEND; | ||
2150 | 2154 | ||
2151 | netlink_table_ungrab(); | 2155 | netlink_table_ungrab(); |
2152 | } | 2156 | } |
diff --git a/net/openvswitch/flow.c b/net/openvswitch/flow.c index f9f211d95ebe..98c70630ad06 100644 --- a/net/openvswitch/flow.c +++ b/net/openvswitch/flow.c | |||
@@ -424,19 +424,11 @@ void ovs_flow_deferred_free(struct sw_flow *flow) | |||
424 | call_rcu(&flow->rcu, rcu_free_flow_callback); | 424 | call_rcu(&flow->rcu, rcu_free_flow_callback); |
425 | } | 425 | } |
426 | 426 | ||
427 | /* RCU callback used by ovs_flow_deferred_free_acts. */ | ||
428 | static void rcu_free_acts_callback(struct rcu_head *rcu) | ||
429 | { | ||
430 | struct sw_flow_actions *sf_acts = container_of(rcu, | ||
431 | struct sw_flow_actions, rcu); | ||
432 | kfree(sf_acts); | ||
433 | } | ||
434 | |||
435 | /* Schedules 'sf_acts' to be freed after the next RCU grace period. | 427 | /* Schedules 'sf_acts' to be freed after the next RCU grace period. |
436 | * The caller must hold rcu_read_lock for this to be sensible. */ | 428 | * The caller must hold rcu_read_lock for this to be sensible. */ |
437 | void ovs_flow_deferred_free_acts(struct sw_flow_actions *sf_acts) | 429 | void ovs_flow_deferred_free_acts(struct sw_flow_actions *sf_acts) |
438 | { | 430 | { |
439 | call_rcu(&sf_acts->rcu, rcu_free_acts_callback); | 431 | kfree_rcu(sf_acts, rcu); |
440 | } | 432 | } |
441 | 433 | ||
442 | static int parse_vlan(struct sk_buff *skb, struct sw_flow_key *key) | 434 | static int parse_vlan(struct sk_buff *skb, struct sw_flow_key *key) |
diff --git a/net/packet/Kconfig b/net/packet/Kconfig index 0060e3b396b7..cc55b35f80e5 100644 --- a/net/packet/Kconfig +++ b/net/packet/Kconfig | |||
@@ -14,3 +14,11 @@ config PACKET | |||
14 | be called af_packet. | 14 | be called af_packet. |
15 | 15 | ||
16 | If unsure, say Y. | 16 | If unsure, say Y. |
17 | |||
18 | config PACKET_DIAG | ||
19 | tristate "Packet: sockets monitoring interface" | ||
20 | depends on PACKET | ||
21 | default n | ||
22 | ---help--- | ||
23 | Support for PF_PACKET sockets monitoring interface used by the ss tool. | ||
24 | If unsure, say Y. | ||
diff --git a/net/packet/Makefile b/net/packet/Makefile index 81183eabfdec..9df61347a3c3 100644 --- a/net/packet/Makefile +++ b/net/packet/Makefile | |||
@@ -3,3 +3,5 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | obj-$(CONFIG_PACKET) += af_packet.o | 5 | obj-$(CONFIG_PACKET) += af_packet.o |
6 | obj-$(CONFIG_PACKET_DIAG) += af_packet_diag.o | ||
7 | af_packet_diag-y += diag.o | ||
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index ceaca7c134a0..94060edbbd70 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -93,6 +93,8 @@ | |||
93 | #include <net/inet_common.h> | 93 | #include <net/inet_common.h> |
94 | #endif | 94 | #endif |
95 | 95 | ||
96 | #include "internal.h" | ||
97 | |||
96 | /* | 98 | /* |
97 | Assumptions: | 99 | Assumptions: |
98 | - if device has no dev->hard_header routine, it adds and removes ll header | 100 | - if device has no dev->hard_header routine, it adds and removes ll header |
@@ -146,14 +148,6 @@ dev->hard_header == NULL (ll header is added by device, we cannot control it) | |||
146 | 148 | ||
147 | /* Private packet socket structures. */ | 149 | /* Private packet socket structures. */ |
148 | 150 | ||
149 | struct packet_mclist { | ||
150 | struct packet_mclist *next; | ||
151 | int ifindex; | ||
152 | int count; | ||
153 | unsigned short type; | ||
154 | unsigned short alen; | ||
155 | unsigned char addr[MAX_ADDR_LEN]; | ||
156 | }; | ||
157 | /* identical to struct packet_mreq except it has | 151 | /* identical to struct packet_mreq except it has |
158 | * a longer address field. | 152 | * a longer address field. |
159 | */ | 153 | */ |
@@ -175,63 +169,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, | |||
175 | #define BLK_PLUS_PRIV(sz_of_priv) \ | 169 | #define BLK_PLUS_PRIV(sz_of_priv) \ |
176 | (BLK_HDR_LEN + ALIGN((sz_of_priv), V3_ALIGNMENT)) | 170 | (BLK_HDR_LEN + ALIGN((sz_of_priv), V3_ALIGNMENT)) |
177 | 171 | ||
178 | /* kbdq - kernel block descriptor queue */ | ||
179 | struct tpacket_kbdq_core { | ||
180 | struct pgv *pkbdq; | ||
181 | unsigned int feature_req_word; | ||
182 | unsigned int hdrlen; | ||
183 | unsigned char reset_pending_on_curr_blk; | ||
184 | unsigned char delete_blk_timer; | ||
185 | unsigned short kactive_blk_num; | ||
186 | unsigned short blk_sizeof_priv; | ||
187 | |||
188 | /* last_kactive_blk_num: | ||
189 | * trick to see if user-space has caught up | ||
190 | * in order to avoid refreshing timer when every single pkt arrives. | ||
191 | */ | ||
192 | unsigned short last_kactive_blk_num; | ||
193 | |||
194 | char *pkblk_start; | ||
195 | char *pkblk_end; | ||
196 | int kblk_size; | ||
197 | unsigned int knum_blocks; | ||
198 | uint64_t knxt_seq_num; | ||
199 | char *prev; | ||
200 | char *nxt_offset; | ||
201 | struct sk_buff *skb; | ||
202 | |||
203 | atomic_t blk_fill_in_prog; | ||
204 | |||
205 | /* Default is set to 8ms */ | ||
206 | #define DEFAULT_PRB_RETIRE_TOV (8) | ||
207 | |||
208 | unsigned short retire_blk_tov; | ||
209 | unsigned short version; | ||
210 | unsigned long tov_in_jiffies; | ||
211 | |||
212 | /* timer to retire an outstanding block */ | ||
213 | struct timer_list retire_blk_timer; | ||
214 | }; | ||
215 | |||
216 | #define PGV_FROM_VMALLOC 1 | 172 | #define PGV_FROM_VMALLOC 1 |
217 | struct pgv { | ||
218 | char *buffer; | ||
219 | }; | ||
220 | |||
221 | struct packet_ring_buffer { | ||
222 | struct pgv *pg_vec; | ||
223 | unsigned int head; | ||
224 | unsigned int frames_per_block; | ||
225 | unsigned int frame_size; | ||
226 | unsigned int frame_max; | ||
227 | |||
228 | unsigned int pg_vec_order; | ||
229 | unsigned int pg_vec_pages; | ||
230 | unsigned int pg_vec_len; | ||
231 | |||
232 | struct tpacket_kbdq_core prb_bdqc; | ||
233 | atomic_t pending; | ||
234 | }; | ||
235 | 173 | ||
236 | #define BLOCK_STATUS(x) ((x)->hdr.bh1.block_status) | 174 | #define BLOCK_STATUS(x) ((x)->hdr.bh1.block_status) |
237 | #define BLOCK_NUM_PKTS(x) ((x)->hdr.bh1.num_pkts) | 175 | #define BLOCK_NUM_PKTS(x) ((x)->hdr.bh1.num_pkts) |
@@ -269,52 +207,6 @@ static void prb_fill_vlan_info(struct tpacket_kbdq_core *, | |||
269 | struct tpacket3_hdr *); | 207 | struct tpacket3_hdr *); |
270 | static void packet_flush_mclist(struct sock *sk); | 208 | static void packet_flush_mclist(struct sock *sk); |
271 | 209 | ||
272 | struct packet_fanout; | ||
273 | struct packet_sock { | ||
274 | /* struct sock has to be the first member of packet_sock */ | ||
275 | struct sock sk; | ||
276 | struct packet_fanout *fanout; | ||
277 | struct tpacket_stats stats; | ||
278 | union tpacket_stats_u stats_u; | ||
279 | struct packet_ring_buffer rx_ring; | ||
280 | struct packet_ring_buffer tx_ring; | ||
281 | int copy_thresh; | ||
282 | spinlock_t bind_lock; | ||
283 | struct mutex pg_vec_lock; | ||
284 | unsigned int running:1, /* prot_hook is attached*/ | ||
285 | auxdata:1, | ||
286 | origdev:1, | ||
287 | has_vnet_hdr:1; | ||
288 | int ifindex; /* bound device */ | ||
289 | __be16 num; | ||
290 | struct packet_mclist *mclist; | ||
291 | atomic_t mapped; | ||
292 | enum tpacket_versions tp_version; | ||
293 | unsigned int tp_hdrlen; | ||
294 | unsigned int tp_reserve; | ||
295 | unsigned int tp_loss:1; | ||
296 | unsigned int tp_tstamp; | ||
297 | struct packet_type prot_hook ____cacheline_aligned_in_smp; | ||
298 | }; | ||
299 | |||
300 | #define PACKET_FANOUT_MAX 256 | ||
301 | |||
302 | struct packet_fanout { | ||
303 | #ifdef CONFIG_NET_NS | ||
304 | struct net *net; | ||
305 | #endif | ||
306 | unsigned int num_members; | ||
307 | u16 id; | ||
308 | u8 type; | ||
309 | u8 defrag; | ||
310 | atomic_t rr_cur; | ||
311 | struct list_head list; | ||
312 | struct sock *arr[PACKET_FANOUT_MAX]; | ||
313 | spinlock_t lock; | ||
314 | atomic_t sk_ref; | ||
315 | struct packet_type prot_hook ____cacheline_aligned_in_smp; | ||
316 | }; | ||
317 | |||
318 | struct packet_skb_cb { | 210 | struct packet_skb_cb { |
319 | unsigned int origlen; | 211 | unsigned int origlen; |
320 | union { | 212 | union { |
@@ -334,11 +226,6 @@ struct packet_skb_cb { | |||
334 | (((x)->kactive_blk_num < ((x)->knum_blocks-1)) ? \ | 226 | (((x)->kactive_blk_num < ((x)->knum_blocks-1)) ? \ |
335 | ((x)->kactive_blk_num+1) : 0) | 227 | ((x)->kactive_blk_num+1) : 0) |
336 | 228 | ||
337 | static struct packet_sock *pkt_sk(struct sock *sk) | ||
338 | { | ||
339 | return (struct packet_sock *)sk; | ||
340 | } | ||
341 | |||
342 | static void __fanout_unlink(struct sock *sk, struct packet_sock *po); | 229 | static void __fanout_unlink(struct sock *sk, struct packet_sock *po); |
343 | static void __fanout_link(struct sock *sk, struct packet_sock *po); | 230 | static void __fanout_link(struct sock *sk, struct packet_sock *po); |
344 | 231 | ||
@@ -968,7 +855,8 @@ static void prb_fill_vlan_info(struct tpacket_kbdq_core *pkc, | |||
968 | ppd->hv1.tp_vlan_tci = vlan_tx_tag_get(pkc->skb); | 855 | ppd->hv1.tp_vlan_tci = vlan_tx_tag_get(pkc->skb); |
969 | ppd->tp_status = TP_STATUS_VLAN_VALID; | 856 | ppd->tp_status = TP_STATUS_VLAN_VALID; |
970 | } else { | 857 | } else { |
971 | ppd->hv1.tp_vlan_tci = ppd->tp_status = 0; | 858 | ppd->hv1.tp_vlan_tci = 0; |
859 | ppd->tp_status = TP_STATUS_AVAILABLE; | ||
972 | } | 860 | } |
973 | } | 861 | } |
974 | 862 | ||
@@ -1079,7 +967,7 @@ static void *packet_current_rx_frame(struct packet_sock *po, | |||
1079 | default: | 967 | default: |
1080 | WARN(1, "TPACKET version not supported\n"); | 968 | WARN(1, "TPACKET version not supported\n"); |
1081 | BUG(); | 969 | BUG(); |
1082 | return 0; | 970 | return NULL; |
1083 | } | 971 | } |
1084 | } | 972 | } |
1085 | 973 | ||
@@ -1243,7 +1131,8 @@ static int packet_rcv_fanout(struct sk_buff *skb, struct net_device *dev, | |||
1243 | return po->prot_hook.func(skb, dev, &po->prot_hook, orig_dev); | 1131 | return po->prot_hook.func(skb, dev, &po->prot_hook, orig_dev); |
1244 | } | 1132 | } |
1245 | 1133 | ||
1246 | static DEFINE_MUTEX(fanout_mutex); | 1134 | DEFINE_MUTEX(fanout_mutex); |
1135 | EXPORT_SYMBOL_GPL(fanout_mutex); | ||
1247 | static LIST_HEAD(fanout_list); | 1136 | static LIST_HEAD(fanout_list); |
1248 | 1137 | ||
1249 | static void __fanout_link(struct sock *sk, struct packet_sock *po) | 1138 | static void __fanout_link(struct sock *sk, struct packet_sock *po) |
@@ -1273,6 +1162,14 @@ static void __fanout_unlink(struct sock *sk, struct packet_sock *po) | |||
1273 | spin_unlock(&f->lock); | 1162 | spin_unlock(&f->lock); |
1274 | } | 1163 | } |
1275 | 1164 | ||
1165 | static bool match_fanout_group(struct packet_type *ptype, struct sock * sk) | ||
1166 | { | ||
1167 | if (ptype->af_packet_priv == (void*)((struct packet_sock *)sk)->fanout) | ||
1168 | return true; | ||
1169 | |||
1170 | return false; | ||
1171 | } | ||
1172 | |||
1276 | static int fanout_add(struct sock *sk, u16 id, u16 type_flags) | 1173 | static int fanout_add(struct sock *sk, u16 id, u16 type_flags) |
1277 | { | 1174 | { |
1278 | struct packet_sock *po = pkt_sk(sk); | 1175 | struct packet_sock *po = pkt_sk(sk); |
@@ -1325,6 +1222,7 @@ static int fanout_add(struct sock *sk, u16 id, u16 type_flags) | |||
1325 | match->prot_hook.dev = po->prot_hook.dev; | 1222 | match->prot_hook.dev = po->prot_hook.dev; |
1326 | match->prot_hook.func = packet_rcv_fanout; | 1223 | match->prot_hook.func = packet_rcv_fanout; |
1327 | match->prot_hook.af_packet_priv = match; | 1224 | match->prot_hook.af_packet_priv = match; |
1225 | match->prot_hook.id_match = match_fanout_group; | ||
1328 | dev_add_pack(&match->prot_hook); | 1226 | dev_add_pack(&match->prot_hook); |
1329 | list_add(&match->list, &fanout_list); | 1227 | list_add(&match->list, &fanout_list); |
1330 | } | 1228 | } |
@@ -1355,9 +1253,9 @@ static void fanout_release(struct sock *sk) | |||
1355 | if (!f) | 1253 | if (!f) |
1356 | return; | 1254 | return; |
1357 | 1255 | ||
1256 | mutex_lock(&fanout_mutex); | ||
1358 | po->fanout = NULL; | 1257 | po->fanout = NULL; |
1359 | 1258 | ||
1360 | mutex_lock(&fanout_mutex); | ||
1361 | if (atomic_dec_and_test(&f->sk_ref)) { | 1259 | if (atomic_dec_and_test(&f->sk_ref)) { |
1362 | list_del(&f->list); | 1260 | list_del(&f->list); |
1363 | dev_remove_pack(&f->prot_hook); | 1261 | dev_remove_pack(&f->prot_hook); |
@@ -1936,7 +1834,6 @@ static void tpacket_destruct_skb(struct sk_buff *skb) | |||
1936 | 1834 | ||
1937 | if (likely(po->tx_ring.pg_vec)) { | 1835 | if (likely(po->tx_ring.pg_vec)) { |
1938 | ph = skb_shinfo(skb)->destructor_arg; | 1836 | ph = skb_shinfo(skb)->destructor_arg; |
1939 | BUG_ON(__packet_get_status(po, ph) != TP_STATUS_SENDING); | ||
1940 | BUG_ON(atomic_read(&po->tx_ring.pending) == 0); | 1837 | BUG_ON(atomic_read(&po->tx_ring.pending) == 0); |
1941 | atomic_dec(&po->tx_ring.pending); | 1838 | atomic_dec(&po->tx_ring.pending); |
1942 | __packet_set_status(po, ph, TP_STATUS_AVAILABLE); | 1839 | __packet_set_status(po, ph, TP_STATUS_AVAILABLE); |
@@ -2055,7 +1952,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) | |||
2055 | int tp_len, size_max; | 1952 | int tp_len, size_max; |
2056 | unsigned char *addr; | 1953 | unsigned char *addr; |
2057 | int len_sum = 0; | 1954 | int len_sum = 0; |
2058 | int status = 0; | 1955 | int status = TP_STATUS_AVAILABLE; |
2059 | int hlen, tlen; | 1956 | int hlen, tlen; |
2060 | 1957 | ||
2061 | mutex_lock(&po->pg_vec_lock); | 1958 | mutex_lock(&po->pg_vec_lock); |
@@ -2420,10 +2317,13 @@ static int packet_release(struct socket *sock) | |||
2420 | net = sock_net(sk); | 2317 | net = sock_net(sk); |
2421 | po = pkt_sk(sk); | 2318 | po = pkt_sk(sk); |
2422 | 2319 | ||
2423 | spin_lock_bh(&net->packet.sklist_lock); | 2320 | mutex_lock(&net->packet.sklist_lock); |
2424 | sk_del_node_init_rcu(sk); | 2321 | sk_del_node_init_rcu(sk); |
2322 | mutex_unlock(&net->packet.sklist_lock); | ||
2323 | |||
2324 | preempt_disable(); | ||
2425 | sock_prot_inuse_add(net, sk->sk_prot, -1); | 2325 | sock_prot_inuse_add(net, sk->sk_prot, -1); |
2426 | spin_unlock_bh(&net->packet.sklist_lock); | 2326 | preempt_enable(); |
2427 | 2327 | ||
2428 | spin_lock(&po->bind_lock); | 2328 | spin_lock(&po->bind_lock); |
2429 | unregister_prot_hook(sk, false); | 2329 | unregister_prot_hook(sk, false); |
@@ -2622,10 +2522,13 @@ static int packet_create(struct net *net, struct socket *sock, int protocol, | |||
2622 | register_prot_hook(sk); | 2522 | register_prot_hook(sk); |
2623 | } | 2523 | } |
2624 | 2524 | ||
2625 | spin_lock_bh(&net->packet.sklist_lock); | 2525 | mutex_lock(&net->packet.sklist_lock); |
2626 | sk_add_node_rcu(sk, &net->packet.sklist); | 2526 | sk_add_node_rcu(sk, &net->packet.sklist); |
2527 | mutex_unlock(&net->packet.sklist_lock); | ||
2528 | |||
2529 | preempt_disable(); | ||
2627 | sock_prot_inuse_add(net, &packet_proto, 1); | 2530 | sock_prot_inuse_add(net, &packet_proto, 1); |
2628 | spin_unlock_bh(&net->packet.sklist_lock); | 2531 | preempt_enable(); |
2629 | 2532 | ||
2630 | return 0; | 2533 | return 0; |
2631 | out: | 2534 | out: |
@@ -3846,7 +3749,7 @@ static int packet_seq_show(struct seq_file *seq, void *v) | |||
3846 | po->ifindex, | 3749 | po->ifindex, |
3847 | po->running, | 3750 | po->running, |
3848 | atomic_read(&s->sk_rmem_alloc), | 3751 | atomic_read(&s->sk_rmem_alloc), |
3849 | sock_i_uid(s), | 3752 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(s)), |
3850 | sock_i_ino(s)); | 3753 | sock_i_ino(s)); |
3851 | } | 3754 | } |
3852 | 3755 | ||
@@ -3878,7 +3781,7 @@ static const struct file_operations packet_seq_fops = { | |||
3878 | 3781 | ||
3879 | static int __net_init packet_net_init(struct net *net) | 3782 | static int __net_init packet_net_init(struct net *net) |
3880 | { | 3783 | { |
3881 | spin_lock_init(&net->packet.sklist_lock); | 3784 | mutex_init(&net->packet.sklist_lock); |
3882 | INIT_HLIST_HEAD(&net->packet.sklist); | 3785 | INIT_HLIST_HEAD(&net->packet.sklist); |
3883 | 3786 | ||
3884 | if (!proc_net_fops_create(net, "packet", 0, &packet_seq_fops)) | 3787 | if (!proc_net_fops_create(net, "packet", 0, &packet_seq_fops)) |
diff --git a/net/packet/diag.c b/net/packet/diag.c new file mode 100644 index 000000000000..39bce0d50df9 --- /dev/null +++ b/net/packet/diag.c | |||
@@ -0,0 +1,242 @@ | |||
1 | #include <linux/module.h> | ||
2 | #include <linux/sock_diag.h> | ||
3 | #include <linux/net.h> | ||
4 | #include <linux/netdevice.h> | ||
5 | #include <linux/packet_diag.h> | ||
6 | #include <net/net_namespace.h> | ||
7 | #include <net/sock.h> | ||
8 | |||
9 | #include "internal.h" | ||
10 | |||
11 | static int pdiag_put_info(const struct packet_sock *po, struct sk_buff *nlskb) | ||
12 | { | ||
13 | struct packet_diag_info pinfo; | ||
14 | |||
15 | pinfo.pdi_index = po->ifindex; | ||
16 | pinfo.pdi_version = po->tp_version; | ||
17 | pinfo.pdi_reserve = po->tp_reserve; | ||
18 | pinfo.pdi_copy_thresh = po->copy_thresh; | ||
19 | pinfo.pdi_tstamp = po->tp_tstamp; | ||
20 | |||
21 | pinfo.pdi_flags = 0; | ||
22 | if (po->running) | ||
23 | pinfo.pdi_flags |= PDI_RUNNING; | ||
24 | if (po->auxdata) | ||
25 | pinfo.pdi_flags |= PDI_AUXDATA; | ||
26 | if (po->origdev) | ||
27 | pinfo.pdi_flags |= PDI_ORIGDEV; | ||
28 | if (po->has_vnet_hdr) | ||
29 | pinfo.pdi_flags |= PDI_VNETHDR; | ||
30 | if (po->tp_loss) | ||
31 | pinfo.pdi_flags |= PDI_LOSS; | ||
32 | |||
33 | return nla_put(nlskb, PACKET_DIAG_INFO, sizeof(pinfo), &pinfo); | ||
34 | } | ||
35 | |||
36 | static int pdiag_put_mclist(const struct packet_sock *po, struct sk_buff *nlskb) | ||
37 | { | ||
38 | struct nlattr *mca; | ||
39 | struct packet_mclist *ml; | ||
40 | |||
41 | mca = nla_nest_start(nlskb, PACKET_DIAG_MCLIST); | ||
42 | if (!mca) | ||
43 | return -EMSGSIZE; | ||
44 | |||
45 | rtnl_lock(); | ||
46 | for (ml = po->mclist; ml; ml = ml->next) { | ||
47 | struct packet_diag_mclist *dml; | ||
48 | |||
49 | dml = nla_reserve_nohdr(nlskb, sizeof(*dml)); | ||
50 | if (!dml) { | ||
51 | rtnl_unlock(); | ||
52 | nla_nest_cancel(nlskb, mca); | ||
53 | return -EMSGSIZE; | ||
54 | } | ||
55 | |||
56 | dml->pdmc_index = ml->ifindex; | ||
57 | dml->pdmc_type = ml->type; | ||
58 | dml->pdmc_alen = ml->alen; | ||
59 | dml->pdmc_count = ml->count; | ||
60 | BUILD_BUG_ON(sizeof(dml->pdmc_addr) != sizeof(ml->addr)); | ||
61 | memcpy(dml->pdmc_addr, ml->addr, sizeof(ml->addr)); | ||
62 | } | ||
63 | |||
64 | rtnl_unlock(); | ||
65 | nla_nest_end(nlskb, mca); | ||
66 | |||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | static int pdiag_put_ring(struct packet_ring_buffer *ring, int ver, int nl_type, | ||
71 | struct sk_buff *nlskb) | ||
72 | { | ||
73 | struct packet_diag_ring pdr; | ||
74 | |||
75 | if (!ring->pg_vec || ((ver > TPACKET_V2) && | ||
76 | (nl_type == PACKET_DIAG_TX_RING))) | ||
77 | return 0; | ||
78 | |||
79 | pdr.pdr_block_size = ring->pg_vec_pages << PAGE_SHIFT; | ||
80 | pdr.pdr_block_nr = ring->pg_vec_len; | ||
81 | pdr.pdr_frame_size = ring->frame_size; | ||
82 | pdr.pdr_frame_nr = ring->frame_max + 1; | ||
83 | |||
84 | if (ver > TPACKET_V2) { | ||
85 | pdr.pdr_retire_tmo = ring->prb_bdqc.retire_blk_tov; | ||
86 | pdr.pdr_sizeof_priv = ring->prb_bdqc.blk_sizeof_priv; | ||
87 | pdr.pdr_features = ring->prb_bdqc.feature_req_word; | ||
88 | } else { | ||
89 | pdr.pdr_retire_tmo = 0; | ||
90 | pdr.pdr_sizeof_priv = 0; | ||
91 | pdr.pdr_features = 0; | ||
92 | } | ||
93 | |||
94 | return nla_put(nlskb, nl_type, sizeof(pdr), &pdr); | ||
95 | } | ||
96 | |||
97 | static int pdiag_put_rings_cfg(struct packet_sock *po, struct sk_buff *skb) | ||
98 | { | ||
99 | int ret; | ||
100 | |||
101 | mutex_lock(&po->pg_vec_lock); | ||
102 | ret = pdiag_put_ring(&po->rx_ring, po->tp_version, | ||
103 | PACKET_DIAG_RX_RING, skb); | ||
104 | if (!ret) | ||
105 | ret = pdiag_put_ring(&po->tx_ring, po->tp_version, | ||
106 | PACKET_DIAG_TX_RING, skb); | ||
107 | mutex_unlock(&po->pg_vec_lock); | ||
108 | |||
109 | return ret; | ||
110 | } | ||
111 | |||
112 | static int pdiag_put_fanout(struct packet_sock *po, struct sk_buff *nlskb) | ||
113 | { | ||
114 | int ret = 0; | ||
115 | |||
116 | mutex_lock(&fanout_mutex); | ||
117 | if (po->fanout) { | ||
118 | u32 val; | ||
119 | |||
120 | val = (u32)po->fanout->id | ((u32)po->fanout->type << 16); | ||
121 | ret = nla_put_u32(nlskb, PACKET_DIAG_FANOUT, val); | ||
122 | } | ||
123 | mutex_unlock(&fanout_mutex); | ||
124 | |||
125 | return ret; | ||
126 | } | ||
127 | |||
128 | static int sk_diag_fill(struct sock *sk, struct sk_buff *skb, struct packet_diag_req *req, | ||
129 | u32 pid, u32 seq, u32 flags, int sk_ino) | ||
130 | { | ||
131 | struct nlmsghdr *nlh; | ||
132 | struct packet_diag_msg *rp; | ||
133 | struct packet_sock *po = pkt_sk(sk); | ||
134 | |||
135 | nlh = nlmsg_put(skb, pid, seq, SOCK_DIAG_BY_FAMILY, sizeof(*rp), flags); | ||
136 | if (!nlh) | ||
137 | return -EMSGSIZE; | ||
138 | |||
139 | rp = nlmsg_data(nlh); | ||
140 | rp->pdiag_family = AF_PACKET; | ||
141 | rp->pdiag_type = sk->sk_type; | ||
142 | rp->pdiag_num = ntohs(po->num); | ||
143 | rp->pdiag_ino = sk_ino; | ||
144 | sock_diag_save_cookie(sk, rp->pdiag_cookie); | ||
145 | |||
146 | if ((req->pdiag_show & PACKET_SHOW_INFO) && | ||
147 | pdiag_put_info(po, skb)) | ||
148 | goto out_nlmsg_trim; | ||
149 | |||
150 | if ((req->pdiag_show & PACKET_SHOW_MCLIST) && | ||
151 | pdiag_put_mclist(po, skb)) | ||
152 | goto out_nlmsg_trim; | ||
153 | |||
154 | if ((req->pdiag_show & PACKET_SHOW_RING_CFG) && | ||
155 | pdiag_put_rings_cfg(po, skb)) | ||
156 | goto out_nlmsg_trim; | ||
157 | |||
158 | if ((req->pdiag_show & PACKET_SHOW_FANOUT) && | ||
159 | pdiag_put_fanout(po, skb)) | ||
160 | goto out_nlmsg_trim; | ||
161 | |||
162 | return nlmsg_end(skb, nlh); | ||
163 | |||
164 | out_nlmsg_trim: | ||
165 | nlmsg_cancel(skb, nlh); | ||
166 | return -EMSGSIZE; | ||
167 | } | ||
168 | |||
169 | static int packet_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) | ||
170 | { | ||
171 | int num = 0, s_num = cb->args[0]; | ||
172 | struct packet_diag_req *req; | ||
173 | struct net *net; | ||
174 | struct sock *sk; | ||
175 | struct hlist_node *node; | ||
176 | |||
177 | net = sock_net(skb->sk); | ||
178 | req = nlmsg_data(cb->nlh); | ||
179 | |||
180 | mutex_lock(&net->packet.sklist_lock); | ||
181 | sk_for_each(sk, node, &net->packet.sklist) { | ||
182 | if (!net_eq(sock_net(sk), net)) | ||
183 | continue; | ||
184 | if (num < s_num) | ||
185 | goto next; | ||
186 | |||
187 | if (sk_diag_fill(sk, skb, req, NETLINK_CB(cb->skb).pid, | ||
188 | cb->nlh->nlmsg_seq, NLM_F_MULTI, | ||
189 | sock_i_ino(sk)) < 0) | ||
190 | goto done; | ||
191 | next: | ||
192 | num++; | ||
193 | } | ||
194 | done: | ||
195 | mutex_unlock(&net->packet.sklist_lock); | ||
196 | cb->args[0] = num; | ||
197 | |||
198 | return skb->len; | ||
199 | } | ||
200 | |||
201 | static int packet_diag_handler_dump(struct sk_buff *skb, struct nlmsghdr *h) | ||
202 | { | ||
203 | int hdrlen = sizeof(struct packet_diag_req); | ||
204 | struct net *net = sock_net(skb->sk); | ||
205 | struct packet_diag_req *req; | ||
206 | |||
207 | if (nlmsg_len(h) < hdrlen) | ||
208 | return -EINVAL; | ||
209 | |||
210 | req = nlmsg_data(h); | ||
211 | /* Make it possible to support protocol filtering later */ | ||
212 | if (req->sdiag_protocol) | ||
213 | return -EINVAL; | ||
214 | |||
215 | if (h->nlmsg_flags & NLM_F_DUMP) { | ||
216 | struct netlink_dump_control c = { | ||
217 | .dump = packet_diag_dump, | ||
218 | }; | ||
219 | return netlink_dump_start(net->diag_nlsk, skb, h, &c); | ||
220 | } else | ||
221 | return -EOPNOTSUPP; | ||
222 | } | ||
223 | |||
224 | static const struct sock_diag_handler packet_diag_handler = { | ||
225 | .family = AF_PACKET, | ||
226 | .dump = packet_diag_handler_dump, | ||
227 | }; | ||
228 | |||
229 | static int __init packet_diag_init(void) | ||
230 | { | ||
231 | return sock_diag_register(&packet_diag_handler); | ||
232 | } | ||
233 | |||
234 | static void __exit packet_diag_exit(void) | ||
235 | { | ||
236 | sock_diag_unregister(&packet_diag_handler); | ||
237 | } | ||
238 | |||
239 | module_init(packet_diag_init); | ||
240 | module_exit(packet_diag_exit); | ||
241 | MODULE_LICENSE("GPL"); | ||
242 | MODULE_ALIAS_NET_PF_PROTO_TYPE(PF_NETLINK, NETLINK_SOCK_DIAG, 17 /* AF_PACKET */); | ||
diff --git a/net/packet/internal.h b/net/packet/internal.h new file mode 100644 index 000000000000..44945f6b7252 --- /dev/null +++ b/net/packet/internal.h | |||
@@ -0,0 +1,121 @@ | |||
1 | #ifndef __PACKET_INTERNAL_H__ | ||
2 | #define __PACKET_INTERNAL_H__ | ||
3 | |||
4 | struct packet_mclist { | ||
5 | struct packet_mclist *next; | ||
6 | int ifindex; | ||
7 | int count; | ||
8 | unsigned short type; | ||
9 | unsigned short alen; | ||
10 | unsigned char addr[MAX_ADDR_LEN]; | ||
11 | }; | ||
12 | |||
13 | /* kbdq - kernel block descriptor queue */ | ||
14 | struct tpacket_kbdq_core { | ||
15 | struct pgv *pkbdq; | ||
16 | unsigned int feature_req_word; | ||
17 | unsigned int hdrlen; | ||
18 | unsigned char reset_pending_on_curr_blk; | ||
19 | unsigned char delete_blk_timer; | ||
20 | unsigned short kactive_blk_num; | ||
21 | unsigned short blk_sizeof_priv; | ||
22 | |||
23 | /* last_kactive_blk_num: | ||
24 | * trick to see if user-space has caught up | ||
25 | * in order to avoid refreshing timer when every single pkt arrives. | ||
26 | */ | ||
27 | unsigned short last_kactive_blk_num; | ||
28 | |||
29 | char *pkblk_start; | ||
30 | char *pkblk_end; | ||
31 | int kblk_size; | ||
32 | unsigned int knum_blocks; | ||
33 | uint64_t knxt_seq_num; | ||
34 | char *prev; | ||
35 | char *nxt_offset; | ||
36 | struct sk_buff *skb; | ||
37 | |||
38 | atomic_t blk_fill_in_prog; | ||
39 | |||
40 | /* Default is set to 8ms */ | ||
41 | #define DEFAULT_PRB_RETIRE_TOV (8) | ||
42 | |||
43 | unsigned short retire_blk_tov; | ||
44 | unsigned short version; | ||
45 | unsigned long tov_in_jiffies; | ||
46 | |||
47 | /* timer to retire an outstanding block */ | ||
48 | struct timer_list retire_blk_timer; | ||
49 | }; | ||
50 | |||
51 | struct pgv { | ||
52 | char *buffer; | ||
53 | }; | ||
54 | |||
55 | struct packet_ring_buffer { | ||
56 | struct pgv *pg_vec; | ||
57 | unsigned int head; | ||
58 | unsigned int frames_per_block; | ||
59 | unsigned int frame_size; | ||
60 | unsigned int frame_max; | ||
61 | |||
62 | unsigned int pg_vec_order; | ||
63 | unsigned int pg_vec_pages; | ||
64 | unsigned int pg_vec_len; | ||
65 | |||
66 | struct tpacket_kbdq_core prb_bdqc; | ||
67 | atomic_t pending; | ||
68 | }; | ||
69 | |||
70 | extern struct mutex fanout_mutex; | ||
71 | #define PACKET_FANOUT_MAX 256 | ||
72 | |||
73 | struct packet_fanout { | ||
74 | #ifdef CONFIG_NET_NS | ||
75 | struct net *net; | ||
76 | #endif | ||
77 | unsigned int num_members; | ||
78 | u16 id; | ||
79 | u8 type; | ||
80 | u8 defrag; | ||
81 | atomic_t rr_cur; | ||
82 | struct list_head list; | ||
83 | struct sock *arr[PACKET_FANOUT_MAX]; | ||
84 | spinlock_t lock; | ||
85 | atomic_t sk_ref; | ||
86 | struct packet_type prot_hook ____cacheline_aligned_in_smp; | ||
87 | }; | ||
88 | |||
89 | struct packet_sock { | ||
90 | /* struct sock has to be the first member of packet_sock */ | ||
91 | struct sock sk; | ||
92 | struct packet_fanout *fanout; | ||
93 | struct tpacket_stats stats; | ||
94 | union tpacket_stats_u stats_u; | ||
95 | struct packet_ring_buffer rx_ring; | ||
96 | struct packet_ring_buffer tx_ring; | ||
97 | int copy_thresh; | ||
98 | spinlock_t bind_lock; | ||
99 | struct mutex pg_vec_lock; | ||
100 | unsigned int running:1, /* prot_hook is attached*/ | ||
101 | auxdata:1, | ||
102 | origdev:1, | ||
103 | has_vnet_hdr:1; | ||
104 | int ifindex; /* bound device */ | ||
105 | __be16 num; | ||
106 | struct packet_mclist *mclist; | ||
107 | atomic_t mapped; | ||
108 | enum tpacket_versions tp_version; | ||
109 | unsigned int tp_hdrlen; | ||
110 | unsigned int tp_reserve; | ||
111 | unsigned int tp_loss:1; | ||
112 | unsigned int tp_tstamp; | ||
113 | struct packet_type prot_hook ____cacheline_aligned_in_smp; | ||
114 | }; | ||
115 | |||
116 | static struct packet_sock *pkt_sk(struct sock *sk) | ||
117 | { | ||
118 | return (struct packet_sock *)sk; | ||
119 | } | ||
120 | |||
121 | #endif | ||
diff --git a/net/phonet/socket.c b/net/phonet/socket.c index 0acc943f713a..b7e982782255 100644 --- a/net/phonet/socket.c +++ b/net/phonet/socket.c | |||
@@ -612,7 +612,8 @@ static int pn_sock_seq_show(struct seq_file *seq, void *v) | |||
612 | sk->sk_protocol, pn->sobject, pn->dobject, | 612 | sk->sk_protocol, pn->sobject, pn->dobject, |
613 | pn->resource, sk->sk_state, | 613 | pn->resource, sk->sk_state, |
614 | sk_wmem_alloc_get(sk), sk_rmem_alloc_get(sk), | 614 | sk_wmem_alloc_get(sk), sk_rmem_alloc_get(sk), |
615 | sock_i_uid(sk), sock_i_ino(sk), | 615 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)), |
616 | sock_i_ino(sk), | ||
616 | atomic_read(&sk->sk_refcnt), sk, | 617 | atomic_read(&sk->sk_refcnt), sk, |
617 | atomic_read(&sk->sk_drops), &len); | 618 | atomic_read(&sk->sk_drops), &len); |
618 | } | 619 | } |
@@ -796,7 +797,8 @@ static int pn_res_seq_show(struct seq_file *seq, void *v) | |||
796 | struct sock *sk = *psk; | 797 | struct sock *sk = *psk; |
797 | 798 | ||
798 | seq_printf(seq, "%02X %5d %lu%n", | 799 | seq_printf(seq, "%02X %5d %lu%n", |
799 | (int) (psk - pnres.sk), sock_i_uid(sk), | 800 | (int) (psk - pnres.sk), |
801 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)), | ||
800 | sock_i_ino(sk), &len); | 802 | sock_i_ino(sk), &len); |
801 | } | 803 | } |
802 | seq_printf(seq, "%*s\n", 63 - len, ""); | 804 | seq_printf(seq, "%*s\n", 63 - len, ""); |
diff --git a/net/rds/tcp_connect.c b/net/rds/tcp_connect.c index af95c8e058fc..a65ee78db0c5 100644 --- a/net/rds/tcp_connect.c +++ b/net/rds/tcp_connect.c | |||
@@ -43,7 +43,7 @@ void rds_tcp_state_change(struct sock *sk) | |||
43 | struct rds_connection *conn; | 43 | struct rds_connection *conn; |
44 | struct rds_tcp_connection *tc; | 44 | struct rds_tcp_connection *tc; |
45 | 45 | ||
46 | read_lock_bh(&sk->sk_callback_lock); | 46 | read_lock(&sk->sk_callback_lock); |
47 | conn = sk->sk_user_data; | 47 | conn = sk->sk_user_data; |
48 | if (!conn) { | 48 | if (!conn) { |
49 | state_change = sk->sk_state_change; | 49 | state_change = sk->sk_state_change; |
@@ -68,7 +68,7 @@ void rds_tcp_state_change(struct sock *sk) | |||
68 | break; | 68 | break; |
69 | } | 69 | } |
70 | out: | 70 | out: |
71 | read_unlock_bh(&sk->sk_callback_lock); | 71 | read_unlock(&sk->sk_callback_lock); |
72 | state_change(sk); | 72 | state_change(sk); |
73 | } | 73 | } |
74 | 74 | ||
diff --git a/net/rds/tcp_listen.c b/net/rds/tcp_listen.c index 72981375f47c..7787537e9c2e 100644 --- a/net/rds/tcp_listen.c +++ b/net/rds/tcp_listen.c | |||
@@ -114,7 +114,7 @@ void rds_tcp_listen_data_ready(struct sock *sk, int bytes) | |||
114 | 114 | ||
115 | rdsdebug("listen data ready sk %p\n", sk); | 115 | rdsdebug("listen data ready sk %p\n", sk); |
116 | 116 | ||
117 | read_lock_bh(&sk->sk_callback_lock); | 117 | read_lock(&sk->sk_callback_lock); |
118 | ready = sk->sk_user_data; | 118 | ready = sk->sk_user_data; |
119 | if (!ready) { /* check for teardown race */ | 119 | if (!ready) { /* check for teardown race */ |
120 | ready = sk->sk_data_ready; | 120 | ready = sk->sk_data_ready; |
@@ -131,7 +131,7 @@ void rds_tcp_listen_data_ready(struct sock *sk, int bytes) | |||
131 | queue_work(rds_wq, &rds_tcp_listen_work); | 131 | queue_work(rds_wq, &rds_tcp_listen_work); |
132 | 132 | ||
133 | out: | 133 | out: |
134 | read_unlock_bh(&sk->sk_callback_lock); | 134 | read_unlock(&sk->sk_callback_lock); |
135 | ready(sk, bytes); | 135 | ready(sk, bytes); |
136 | } | 136 | } |
137 | 137 | ||
diff --git a/net/rds/tcp_recv.c b/net/rds/tcp_recv.c index 6243258f840f..4fac4f2bb9dc 100644 --- a/net/rds/tcp_recv.c +++ b/net/rds/tcp_recv.c | |||
@@ -322,7 +322,7 @@ void rds_tcp_data_ready(struct sock *sk, int bytes) | |||
322 | 322 | ||
323 | rdsdebug("data ready sk %p bytes %d\n", sk, bytes); | 323 | rdsdebug("data ready sk %p bytes %d\n", sk, bytes); |
324 | 324 | ||
325 | read_lock_bh(&sk->sk_callback_lock); | 325 | read_lock(&sk->sk_callback_lock); |
326 | conn = sk->sk_user_data; | 326 | conn = sk->sk_user_data; |
327 | if (!conn) { /* check for teardown race */ | 327 | if (!conn) { /* check for teardown race */ |
328 | ready = sk->sk_data_ready; | 328 | ready = sk->sk_data_ready; |
@@ -336,7 +336,7 @@ void rds_tcp_data_ready(struct sock *sk, int bytes) | |||
336 | if (rds_tcp_read_sock(conn, GFP_ATOMIC) == -ENOMEM) | 336 | if (rds_tcp_read_sock(conn, GFP_ATOMIC) == -ENOMEM) |
337 | queue_delayed_work(rds_wq, &conn->c_recv_w, 0); | 337 | queue_delayed_work(rds_wq, &conn->c_recv_w, 0); |
338 | out: | 338 | out: |
339 | read_unlock_bh(&sk->sk_callback_lock); | 339 | read_unlock(&sk->sk_callback_lock); |
340 | ready(sk, bytes); | 340 | ready(sk, bytes); |
341 | } | 341 | } |
342 | 342 | ||
diff --git a/net/rds/tcp_send.c b/net/rds/tcp_send.c index 1b4fd68f0c7c..81cf5a4c5e40 100644 --- a/net/rds/tcp_send.c +++ b/net/rds/tcp_send.c | |||
@@ -174,7 +174,7 @@ void rds_tcp_write_space(struct sock *sk) | |||
174 | struct rds_connection *conn; | 174 | struct rds_connection *conn; |
175 | struct rds_tcp_connection *tc; | 175 | struct rds_tcp_connection *tc; |
176 | 176 | ||
177 | read_lock_bh(&sk->sk_callback_lock); | 177 | read_lock(&sk->sk_callback_lock); |
178 | conn = sk->sk_user_data; | 178 | conn = sk->sk_user_data; |
179 | if (!conn) { | 179 | if (!conn) { |
180 | write_space = sk->sk_write_space; | 180 | write_space = sk->sk_write_space; |
@@ -194,7 +194,7 @@ void rds_tcp_write_space(struct sock *sk) | |||
194 | queue_delayed_work(rds_wq, &conn->c_send_w, 0); | 194 | queue_delayed_work(rds_wq, &conn->c_send_w, 0); |
195 | 195 | ||
196 | out: | 196 | out: |
197 | read_unlock_bh(&sk->sk_callback_lock); | 197 | read_unlock(&sk->sk_callback_lock); |
198 | 198 | ||
199 | /* | 199 | /* |
200 | * write_space is only called when data leaves tcp's send queue if | 200 | * write_space is only called when data leaves tcp's send queue if |
diff --git a/net/rfkill/core.c b/net/rfkill/core.c index 752b72360ebc..c275bad12068 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c | |||
@@ -150,6 +150,20 @@ static void rfkill_led_trigger_activate(struct led_classdev *led) | |||
150 | rfkill_led_trigger_event(rfkill); | 150 | rfkill_led_trigger_event(rfkill); |
151 | } | 151 | } |
152 | 152 | ||
153 | const char *rfkill_get_led_trigger_name(struct rfkill *rfkill) | ||
154 | { | ||
155 | return rfkill->led_trigger.name; | ||
156 | } | ||
157 | EXPORT_SYMBOL(rfkill_get_led_trigger_name); | ||
158 | |||
159 | void rfkill_set_led_trigger_name(struct rfkill *rfkill, const char *name) | ||
160 | { | ||
161 | BUG_ON(!rfkill); | ||
162 | |||
163 | rfkill->ledtrigname = name; | ||
164 | } | ||
165 | EXPORT_SYMBOL(rfkill_set_led_trigger_name); | ||
166 | |||
153 | static int rfkill_led_trigger_register(struct rfkill *rfkill) | 167 | static int rfkill_led_trigger_register(struct rfkill *rfkill) |
154 | { | 168 | { |
155 | rfkill->led_trigger.name = rfkill->ledtrigname | 169 | rfkill->led_trigger.name = rfkill->ledtrigname |
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c index f10fb8256442..05d60859d8e3 100644 --- a/net/sched/act_gact.c +++ b/net/sched/act_gact.c | |||
@@ -67,6 +67,9 @@ static int tcf_gact_init(struct nlattr *nla, struct nlattr *est, | |||
67 | struct tcf_common *pc; | 67 | struct tcf_common *pc; |
68 | int ret = 0; | 68 | int ret = 0; |
69 | int err; | 69 | int err; |
70 | #ifdef CONFIG_GACT_PROB | ||
71 | struct tc_gact_p *p_parm = NULL; | ||
72 | #endif | ||
70 | 73 | ||
71 | if (nla == NULL) | 74 | if (nla == NULL) |
72 | return -EINVAL; | 75 | return -EINVAL; |
@@ -82,6 +85,12 @@ static int tcf_gact_init(struct nlattr *nla, struct nlattr *est, | |||
82 | #ifndef CONFIG_GACT_PROB | 85 | #ifndef CONFIG_GACT_PROB |
83 | if (tb[TCA_GACT_PROB] != NULL) | 86 | if (tb[TCA_GACT_PROB] != NULL) |
84 | return -EOPNOTSUPP; | 87 | return -EOPNOTSUPP; |
88 | #else | ||
89 | if (tb[TCA_GACT_PROB]) { | ||
90 | p_parm = nla_data(tb[TCA_GACT_PROB]); | ||
91 | if (p_parm->ptype >= MAX_RAND) | ||
92 | return -EINVAL; | ||
93 | } | ||
85 | #endif | 94 | #endif |
86 | 95 | ||
87 | pc = tcf_hash_check(parm->index, a, bind, &gact_hash_info); | 96 | pc = tcf_hash_check(parm->index, a, bind, &gact_hash_info); |
@@ -103,8 +112,7 @@ static int tcf_gact_init(struct nlattr *nla, struct nlattr *est, | |||
103 | spin_lock_bh(&gact->tcf_lock); | 112 | spin_lock_bh(&gact->tcf_lock); |
104 | gact->tcf_action = parm->action; | 113 | gact->tcf_action = parm->action; |
105 | #ifdef CONFIG_GACT_PROB | 114 | #ifdef CONFIG_GACT_PROB |
106 | if (tb[TCA_GACT_PROB] != NULL) { | 115 | if (p_parm) { |
107 | struct tc_gact_p *p_parm = nla_data(tb[TCA_GACT_PROB]); | ||
108 | gact->tcfg_paction = p_parm->paction; | 116 | gact->tcfg_paction = p_parm->paction; |
109 | gact->tcfg_pval = p_parm->pval; | 117 | gact->tcfg_pval = p_parm->pval; |
110 | gact->tcfg_ptype = p_parm->ptype; | 118 | gact->tcfg_ptype = p_parm->ptype; |
@@ -133,7 +141,7 @@ static int tcf_gact(struct sk_buff *skb, const struct tc_action *a, | |||
133 | 141 | ||
134 | spin_lock(&gact->tcf_lock); | 142 | spin_lock(&gact->tcf_lock); |
135 | #ifdef CONFIG_GACT_PROB | 143 | #ifdef CONFIG_GACT_PROB |
136 | if (gact->tcfg_ptype && gact_rand[gact->tcfg_ptype] != NULL) | 144 | if (gact->tcfg_ptype) |
137 | action = gact_rand[gact->tcfg_ptype](gact); | 145 | action = gact_rand[gact->tcfg_ptype](gact); |
138 | else | 146 | else |
139 | action = gact->tcf_action; | 147 | action = gact->tcf_action; |
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index 60e281ad0f07..58fb3c7aab9e 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c | |||
@@ -185,7 +185,12 @@ err3: | |||
185 | err2: | 185 | err2: |
186 | kfree(tname); | 186 | kfree(tname); |
187 | err1: | 187 | err1: |
188 | kfree(pc); | 188 | if (ret == ACT_P_CREATED) { |
189 | if (est) | ||
190 | gen_kill_estimator(&pc->tcfc_bstats, | ||
191 | &pc->tcfc_rate_est); | ||
192 | kfree_rcu(pc, tcfc_rcu); | ||
193 | } | ||
189 | return err; | 194 | return err; |
190 | } | 195 | } |
191 | 196 | ||
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c index fe81cc18e9e0..9c0fd0c78814 100644 --- a/net/sched/act_mirred.c +++ b/net/sched/act_mirred.c | |||
@@ -200,13 +200,12 @@ static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a, | |||
200 | out: | 200 | out: |
201 | if (err) { | 201 | if (err) { |
202 | m->tcf_qstats.overlimits++; | 202 | m->tcf_qstats.overlimits++; |
203 | /* should we be asking for packet to be dropped? | 203 | if (m->tcfm_eaction != TCA_EGRESS_MIRROR) |
204 | * may make sense for redirect case only | 204 | retval = TC_ACT_SHOT; |
205 | */ | 205 | else |
206 | retval = TC_ACT_SHOT; | 206 | retval = m->tcf_action; |
207 | } else { | 207 | } else |
208 | retval = m->tcf_action; | 208 | retval = m->tcf_action; |
209 | } | ||
210 | spin_unlock(&m->tcf_lock); | 209 | spin_unlock(&m->tcf_lock); |
211 | 210 | ||
212 | return retval; | 211 | return retval; |
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c index 26aa2f6ce257..45c53ab067a6 100644 --- a/net/sched/act_pedit.c +++ b/net/sched/act_pedit.c | |||
@@ -74,7 +74,10 @@ static int tcf_pedit_init(struct nlattr *nla, struct nlattr *est, | |||
74 | p = to_pedit(pc); | 74 | p = to_pedit(pc); |
75 | keys = kmalloc(ksize, GFP_KERNEL); | 75 | keys = kmalloc(ksize, GFP_KERNEL); |
76 | if (keys == NULL) { | 76 | if (keys == NULL) { |
77 | kfree(pc); | 77 | if (est) |
78 | gen_kill_estimator(&pc->tcfc_bstats, | ||
79 | &pc->tcfc_rate_est); | ||
80 | kfree_rcu(pc, tcfc_rcu); | ||
78 | return -ENOMEM; | 81 | return -ENOMEM; |
79 | } | 82 | } |
80 | ret = ACT_P_CREATED; | 83 | ret = ACT_P_CREATED; |
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c index 3922f2a2821b..3714f60f0b3c 100644 --- a/net/sched/act_simple.c +++ b/net/sched/act_simple.c | |||
@@ -131,7 +131,10 @@ static int tcf_simp_init(struct nlattr *nla, struct nlattr *est, | |||
131 | d = to_defact(pc); | 131 | d = to_defact(pc); |
132 | ret = alloc_defdata(d, defdata); | 132 | ret = alloc_defdata(d, defdata); |
133 | if (ret < 0) { | 133 | if (ret < 0) { |
134 | kfree(pc); | 134 | if (est) |
135 | gen_kill_estimator(&pc->tcfc_bstats, | ||
136 | &pc->tcfc_rate_est); | ||
137 | kfree_rcu(pc, tcfc_rcu); | ||
135 | return ret; | 138 | return ret; |
136 | } | 139 | } |
137 | d->tcf_action = parm->action; | 140 | d->tcf_action = parm->action; |
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 6dd1131f2ec1..dc3ef5aef355 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c | |||
@@ -319,7 +319,7 @@ replay: | |||
319 | } | 319 | } |
320 | } | 320 | } |
321 | 321 | ||
322 | err = tp->ops->change(tp, cl, t->tcm_handle, tca, &fh); | 322 | err = tp->ops->change(skb, tp, cl, t->tcm_handle, tca, &fh); |
323 | if (err == 0) { | 323 | if (err == 0) { |
324 | if (tp_created) { | 324 | if (tp_created) { |
325 | spin_lock_bh(root_lock); | 325 | spin_lock_bh(root_lock); |
diff --git a/net/sched/cls_basic.c b/net/sched/cls_basic.c index 590960a22a77..344a11b342e5 100644 --- a/net/sched/cls_basic.c +++ b/net/sched/cls_basic.c | |||
@@ -162,7 +162,8 @@ errout: | |||
162 | return err; | 162 | return err; |
163 | } | 163 | } |
164 | 164 | ||
165 | static int basic_change(struct tcf_proto *tp, unsigned long base, u32 handle, | 165 | static int basic_change(struct sk_buff *in_skb, |
166 | struct tcf_proto *tp, unsigned long base, u32 handle, | ||
166 | struct nlattr **tca, unsigned long *arg) | 167 | struct nlattr **tca, unsigned long *arg) |
167 | { | 168 | { |
168 | int err; | 169 | int err; |
diff --git a/net/sched/cls_cgroup.c b/net/sched/cls_cgroup.c index 7743ea8d1d38..91de66695b4a 100644 --- a/net/sched/cls_cgroup.c +++ b/net/sched/cls_cgroup.c | |||
@@ -151,7 +151,8 @@ static const struct nla_policy cgroup_policy[TCA_CGROUP_MAX + 1] = { | |||
151 | [TCA_CGROUP_EMATCHES] = { .type = NLA_NESTED }, | 151 | [TCA_CGROUP_EMATCHES] = { .type = NLA_NESTED }, |
152 | }; | 152 | }; |
153 | 153 | ||
154 | static int cls_cgroup_change(struct tcf_proto *tp, unsigned long base, | 154 | static int cls_cgroup_change(struct sk_buff *in_skb, |
155 | struct tcf_proto *tp, unsigned long base, | ||
155 | u32 handle, struct nlattr **tca, | 156 | u32 handle, struct nlattr **tca, |
156 | unsigned long *arg) | 157 | unsigned long *arg) |
157 | { | 158 | { |
diff --git a/net/sched/cls_flow.c b/net/sched/cls_flow.c index ccd08c8dc6a7..ce82d0cb1b47 100644 --- a/net/sched/cls_flow.c +++ b/net/sched/cls_flow.c | |||
@@ -193,15 +193,19 @@ static u32 flow_get_rtclassid(const struct sk_buff *skb) | |||
193 | 193 | ||
194 | static u32 flow_get_skuid(const struct sk_buff *skb) | 194 | static u32 flow_get_skuid(const struct sk_buff *skb) |
195 | { | 195 | { |
196 | if (skb->sk && skb->sk->sk_socket && skb->sk->sk_socket->file) | 196 | if (skb->sk && skb->sk->sk_socket && skb->sk->sk_socket->file) { |
197 | return skb->sk->sk_socket->file->f_cred->fsuid; | 197 | kuid_t skuid = skb->sk->sk_socket->file->f_cred->fsuid; |
198 | return from_kuid(&init_user_ns, skuid); | ||
199 | } | ||
198 | return 0; | 200 | return 0; |
199 | } | 201 | } |
200 | 202 | ||
201 | static u32 flow_get_skgid(const struct sk_buff *skb) | 203 | static u32 flow_get_skgid(const struct sk_buff *skb) |
202 | { | 204 | { |
203 | if (skb->sk && skb->sk->sk_socket && skb->sk->sk_socket->file) | 205 | if (skb->sk && skb->sk->sk_socket && skb->sk->sk_socket->file) { |
204 | return skb->sk->sk_socket->file->f_cred->fsgid; | 206 | kgid_t skgid = skb->sk->sk_socket->file->f_cred->fsgid; |
207 | return from_kgid(&init_user_ns, skgid); | ||
208 | } | ||
205 | return 0; | 209 | return 0; |
206 | } | 210 | } |
207 | 211 | ||
@@ -347,7 +351,8 @@ static const struct nla_policy flow_policy[TCA_FLOW_MAX + 1] = { | |||
347 | [TCA_FLOW_PERTURB] = { .type = NLA_U32 }, | 351 | [TCA_FLOW_PERTURB] = { .type = NLA_U32 }, |
348 | }; | 352 | }; |
349 | 353 | ||
350 | static int flow_change(struct tcf_proto *tp, unsigned long base, | 354 | static int flow_change(struct sk_buff *in_skb, |
355 | struct tcf_proto *tp, unsigned long base, | ||
351 | u32 handle, struct nlattr **tca, | 356 | u32 handle, struct nlattr **tca, |
352 | unsigned long *arg) | 357 | unsigned long *arg) |
353 | { | 358 | { |
@@ -386,6 +391,10 @@ static int flow_change(struct tcf_proto *tp, unsigned long base, | |||
386 | 391 | ||
387 | if (fls(keymask) - 1 > FLOW_KEY_MAX) | 392 | if (fls(keymask) - 1 > FLOW_KEY_MAX) |
388 | return -EOPNOTSUPP; | 393 | return -EOPNOTSUPP; |
394 | |||
395 | if ((keymask & (FLOW_KEY_SKUID|FLOW_KEY_SKGID)) && | ||
396 | sk_user_ns(NETLINK_CB(in_skb).ssk) != &init_user_ns) | ||
397 | return -EOPNOTSUPP; | ||
389 | } | 398 | } |
390 | 399 | ||
391 | err = tcf_exts_validate(tp, tb, tca[TCA_RATE], &e, &flow_ext_map); | 400 | err = tcf_exts_validate(tp, tb, tca[TCA_RATE], &e, &flow_ext_map); |
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c index 8384a4797240..4075a0aef2aa 100644 --- a/net/sched/cls_fw.c +++ b/net/sched/cls_fw.c | |||
@@ -233,7 +233,8 @@ errout: | |||
233 | return err; | 233 | return err; |
234 | } | 234 | } |
235 | 235 | ||
236 | static int fw_change(struct tcf_proto *tp, unsigned long base, | 236 | static int fw_change(struct sk_buff *in_skb, |
237 | struct tcf_proto *tp, unsigned long base, | ||
237 | u32 handle, | 238 | u32 handle, |
238 | struct nlattr **tca, | 239 | struct nlattr **tca, |
239 | unsigned long *arg) | 240 | unsigned long *arg) |
diff --git a/net/sched/cls_route.c b/net/sched/cls_route.c index 44f405cb9aaf..c10d57bf98f2 100644 --- a/net/sched/cls_route.c +++ b/net/sched/cls_route.c | |||
@@ -427,7 +427,8 @@ errout: | |||
427 | return err; | 427 | return err; |
428 | } | 428 | } |
429 | 429 | ||
430 | static int route4_change(struct tcf_proto *tp, unsigned long base, | 430 | static int route4_change(struct sk_buff *in_skb, |
431 | struct tcf_proto *tp, unsigned long base, | ||
431 | u32 handle, | 432 | u32 handle, |
432 | struct nlattr **tca, | 433 | struct nlattr **tca, |
433 | unsigned long *arg) | 434 | unsigned long *arg) |
diff --git a/net/sched/cls_rsvp.h b/net/sched/cls_rsvp.h index 18ab93ec8d7e..494bbb90924a 100644 --- a/net/sched/cls_rsvp.h +++ b/net/sched/cls_rsvp.h | |||
@@ -416,7 +416,8 @@ static const struct nla_policy rsvp_policy[TCA_RSVP_MAX + 1] = { | |||
416 | [TCA_RSVP_PINFO] = { .len = sizeof(struct tc_rsvp_pinfo) }, | 416 | [TCA_RSVP_PINFO] = { .len = sizeof(struct tc_rsvp_pinfo) }, |
417 | }; | 417 | }; |
418 | 418 | ||
419 | static int rsvp_change(struct tcf_proto *tp, unsigned long base, | 419 | static int rsvp_change(struct sk_buff *in_skb, |
420 | struct tcf_proto *tp, unsigned long base, | ||
420 | u32 handle, | 421 | u32 handle, |
421 | struct nlattr **tca, | 422 | struct nlattr **tca, |
422 | unsigned long *arg) | 423 | unsigned long *arg) |
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c index fe29420d0b0e..a1293b4ab7a1 100644 --- a/net/sched/cls_tcindex.c +++ b/net/sched/cls_tcindex.c | |||
@@ -332,7 +332,8 @@ errout: | |||
332 | } | 332 | } |
333 | 333 | ||
334 | static int | 334 | static int |
335 | tcindex_change(struct tcf_proto *tp, unsigned long base, u32 handle, | 335 | tcindex_change(struct sk_buff *in_skb, |
336 | struct tcf_proto *tp, unsigned long base, u32 handle, | ||
336 | struct nlattr **tca, unsigned long *arg) | 337 | struct nlattr **tca, unsigned long *arg) |
337 | { | 338 | { |
338 | struct nlattr *opt = tca[TCA_OPTIONS]; | 339 | struct nlattr *opt = tca[TCA_OPTIONS]; |
diff --git a/net/sched/cls_u32.c b/net/sched/cls_u32.c index d45373fb00b9..c7c27bc91b5a 100644 --- a/net/sched/cls_u32.c +++ b/net/sched/cls_u32.c | |||
@@ -544,7 +544,8 @@ errout: | |||
544 | return err; | 544 | return err; |
545 | } | 545 | } |
546 | 546 | ||
547 | static int u32_change(struct tcf_proto *tp, unsigned long base, u32 handle, | 547 | static int u32_change(struct sk_buff *in_skb, |
548 | struct tcf_proto *tp, unsigned long base, u32 handle, | ||
548 | struct nlattr **tca, | 549 | struct nlattr **tca, |
549 | unsigned long *arg) | 550 | unsigned long *arg) |
550 | { | 551 | { |
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index 511323e89cec..6c4d5fe53ce8 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
@@ -324,24 +324,6 @@ void netif_carrier_off(struct net_device *dev) | |||
324 | } | 324 | } |
325 | EXPORT_SYMBOL(netif_carrier_off); | 325 | EXPORT_SYMBOL(netif_carrier_off); |
326 | 326 | ||
327 | /** | ||
328 | * netif_notify_peers - notify network peers about existence of @dev | ||
329 | * @dev: network device | ||
330 | * | ||
331 | * Generate traffic such that interested network peers are aware of | ||
332 | * @dev, such as by generating a gratuitous ARP. This may be used when | ||
333 | * a device wants to inform the rest of the network about some sort of | ||
334 | * reconfiguration such as a failover event or virtual machine | ||
335 | * migration. | ||
336 | */ | ||
337 | void netif_notify_peers(struct net_device *dev) | ||
338 | { | ||
339 | rtnl_lock(); | ||
340 | call_netdevice_notifiers(NETDEV_NOTIFY_PEERS, dev); | ||
341 | rtnl_unlock(); | ||
342 | } | ||
343 | EXPORT_SYMBOL(netif_notify_peers); | ||
344 | |||
345 | /* "NOOP" scheduler: the best scheduler, recommended for all interfaces | 327 | /* "NOOP" scheduler: the best scheduler, recommended for all interfaces |
346 | under all circumstances. It is difficult to invent anything faster or | 328 | under all circumstances. It is difficult to invent anything faster or |
347 | cheaper. | 329 | cheaper. |
diff --git a/net/sched/sch_qfq.c b/net/sched/sch_qfq.c index 9af01f3df18c..e4723d31fdd5 100644 --- a/net/sched/sch_qfq.c +++ b/net/sched/sch_qfq.c | |||
@@ -203,6 +203,34 @@ out: | |||
203 | return index; | 203 | return index; |
204 | } | 204 | } |
205 | 205 | ||
206 | /* Length of the next packet (0 if the queue is empty). */ | ||
207 | static unsigned int qdisc_peek_len(struct Qdisc *sch) | ||
208 | { | ||
209 | struct sk_buff *skb; | ||
210 | |||
211 | skb = sch->ops->peek(sch); | ||
212 | return skb ? qdisc_pkt_len(skb) : 0; | ||
213 | } | ||
214 | |||
215 | static void qfq_deactivate_class(struct qfq_sched *, struct qfq_class *); | ||
216 | static void qfq_activate_class(struct qfq_sched *q, struct qfq_class *cl, | ||
217 | unsigned int len); | ||
218 | |||
219 | static void qfq_update_class_params(struct qfq_sched *q, struct qfq_class *cl, | ||
220 | u32 lmax, u32 inv_w, int delta_w) | ||
221 | { | ||
222 | int i; | ||
223 | |||
224 | /* update qfq-specific data */ | ||
225 | cl->lmax = lmax; | ||
226 | cl->inv_w = inv_w; | ||
227 | i = qfq_calc_index(cl->inv_w, cl->lmax); | ||
228 | |||
229 | cl->grp = &q->groups[i]; | ||
230 | |||
231 | q->wsum += delta_w; | ||
232 | } | ||
233 | |||
206 | static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, | 234 | static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, |
207 | struct nlattr **tca, unsigned long *arg) | 235 | struct nlattr **tca, unsigned long *arg) |
208 | { | 236 | { |
@@ -250,6 +278,8 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, | |||
250 | lmax = 1UL << QFQ_MTU_SHIFT; | 278 | lmax = 1UL << QFQ_MTU_SHIFT; |
251 | 279 | ||
252 | if (cl != NULL) { | 280 | if (cl != NULL) { |
281 | bool need_reactivation = false; | ||
282 | |||
253 | if (tca[TCA_RATE]) { | 283 | if (tca[TCA_RATE]) { |
254 | err = gen_replace_estimator(&cl->bstats, &cl->rate_est, | 284 | err = gen_replace_estimator(&cl->bstats, &cl->rate_est, |
255 | qdisc_root_sleeping_lock(sch), | 285 | qdisc_root_sleeping_lock(sch), |
@@ -258,12 +288,29 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, | |||
258 | return err; | 288 | return err; |
259 | } | 289 | } |
260 | 290 | ||
261 | if (inv_w != cl->inv_w) { | 291 | if (lmax == cl->lmax && inv_w == cl->inv_w) |
262 | sch_tree_lock(sch); | 292 | return 0; /* nothing to update */ |
263 | q->wsum += delta_w; | 293 | |
264 | cl->inv_w = inv_w; | 294 | i = qfq_calc_index(inv_w, lmax); |
265 | sch_tree_unlock(sch); | 295 | sch_tree_lock(sch); |
296 | if (&q->groups[i] != cl->grp && cl->qdisc->q.qlen > 0) { | ||
297 | /* | ||
298 | * shift cl->F back, to not charge the | ||
299 | * class for the not-yet-served head | ||
300 | * packet | ||
301 | */ | ||
302 | cl->F = cl->S; | ||
303 | /* remove class from its slot in the old group */ | ||
304 | qfq_deactivate_class(q, cl); | ||
305 | need_reactivation = true; | ||
266 | } | 306 | } |
307 | |||
308 | qfq_update_class_params(q, cl, lmax, inv_w, delta_w); | ||
309 | |||
310 | if (need_reactivation) /* activate in new group */ | ||
311 | qfq_activate_class(q, cl, qdisc_peek_len(cl->qdisc)); | ||
312 | sch_tree_unlock(sch); | ||
313 | |||
267 | return 0; | 314 | return 0; |
268 | } | 315 | } |
269 | 316 | ||
@@ -273,11 +320,8 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, | |||
273 | 320 | ||
274 | cl->refcnt = 1; | 321 | cl->refcnt = 1; |
275 | cl->common.classid = classid; | 322 | cl->common.classid = classid; |
276 | cl->lmax = lmax; | ||
277 | cl->inv_w = inv_w; | ||
278 | i = qfq_calc_index(cl->inv_w, cl->lmax); | ||
279 | 323 | ||
280 | cl->grp = &q->groups[i]; | 324 | qfq_update_class_params(q, cl, lmax, inv_w, delta_w); |
281 | 325 | ||
282 | cl->qdisc = qdisc_create_dflt(sch->dev_queue, | 326 | cl->qdisc = qdisc_create_dflt(sch->dev_queue, |
283 | &pfifo_qdisc_ops, classid); | 327 | &pfifo_qdisc_ops, classid); |
@@ -294,7 +338,6 @@ static int qfq_change_class(struct Qdisc *sch, u32 classid, u32 parentid, | |||
294 | return err; | 338 | return err; |
295 | } | 339 | } |
296 | } | 340 | } |
297 | q->wsum += weight; | ||
298 | 341 | ||
299 | sch_tree_lock(sch); | 342 | sch_tree_lock(sch); |
300 | qdisc_class_hash_insert(&q->clhash, &cl->common); | 343 | qdisc_class_hash_insert(&q->clhash, &cl->common); |
@@ -711,15 +754,6 @@ static void qfq_update_eligible(struct qfq_sched *q, u64 old_V) | |||
711 | } | 754 | } |
712 | } | 755 | } |
713 | 756 | ||
714 | /* What is length of next packet in queue (0 if queue is empty) */ | ||
715 | static unsigned int qdisc_peek_len(struct Qdisc *sch) | ||
716 | { | ||
717 | struct sk_buff *skb; | ||
718 | |||
719 | skb = sch->ops->peek(sch); | ||
720 | return skb ? qdisc_pkt_len(skb) : 0; | ||
721 | } | ||
722 | |||
723 | /* | 757 | /* |
724 | * Updates the class, returns true if also the group needs to be updated. | 758 | * Updates the class, returns true if also the group needs to be updated. |
725 | */ | 759 | */ |
@@ -843,11 +877,8 @@ static void qfq_update_start(struct qfq_sched *q, struct qfq_class *cl) | |||
843 | static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch) | 877 | static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch) |
844 | { | 878 | { |
845 | struct qfq_sched *q = qdisc_priv(sch); | 879 | struct qfq_sched *q = qdisc_priv(sch); |
846 | struct qfq_group *grp; | ||
847 | struct qfq_class *cl; | 880 | struct qfq_class *cl; |
848 | int err; | 881 | int err; |
849 | u64 roundedS; | ||
850 | int s; | ||
851 | 882 | ||
852 | cl = qfq_classify(skb, sch, &err); | 883 | cl = qfq_classify(skb, sch, &err); |
853 | if (cl == NULL) { | 884 | if (cl == NULL) { |
@@ -876,11 +907,25 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
876 | return err; | 907 | return err; |
877 | 908 | ||
878 | /* If reach this point, queue q was idle */ | 909 | /* If reach this point, queue q was idle */ |
879 | grp = cl->grp; | 910 | qfq_activate_class(q, cl, qdisc_pkt_len(skb)); |
911 | |||
912 | return err; | ||
913 | } | ||
914 | |||
915 | /* | ||
916 | * Handle class switch from idle to backlogged. | ||
917 | */ | ||
918 | static void qfq_activate_class(struct qfq_sched *q, struct qfq_class *cl, | ||
919 | unsigned int pkt_len) | ||
920 | { | ||
921 | struct qfq_group *grp = cl->grp; | ||
922 | u64 roundedS; | ||
923 | int s; | ||
924 | |||
880 | qfq_update_start(q, cl); | 925 | qfq_update_start(q, cl); |
881 | 926 | ||
882 | /* compute new finish time and rounded start. */ | 927 | /* compute new finish time and rounded start. */ |
883 | cl->F = cl->S + (u64)qdisc_pkt_len(skb) * cl->inv_w; | 928 | cl->F = cl->S + (u64)pkt_len * cl->inv_w; |
884 | roundedS = qfq_round_down(cl->S, grp->slot_shift); | 929 | roundedS = qfq_round_down(cl->S, grp->slot_shift); |
885 | 930 | ||
886 | /* | 931 | /* |
@@ -917,8 +962,6 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch) | |||
917 | 962 | ||
918 | skip_update: | 963 | skip_update: |
919 | qfq_slot_insert(grp, cl, roundedS); | 964 | qfq_slot_insert(grp, cl, roundedS); |
920 | |||
921 | return err; | ||
922 | } | 965 | } |
923 | 966 | ||
924 | 967 | ||
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index ebaef3ed6065..b1ef3bc301a5 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -82,6 +82,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
82 | sctp_scope_t scope, | 82 | sctp_scope_t scope, |
83 | gfp_t gfp) | 83 | gfp_t gfp) |
84 | { | 84 | { |
85 | struct net *net = sock_net(sk); | ||
85 | struct sctp_sock *sp; | 86 | struct sctp_sock *sp; |
86 | int i; | 87 | int i; |
87 | sctp_paramhdr_t *p; | 88 | sctp_paramhdr_t *p; |
@@ -124,7 +125,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
124 | * socket values. | 125 | * socket values. |
125 | */ | 126 | */ |
126 | asoc->max_retrans = sp->assocparams.sasoc_asocmaxrxt; | 127 | asoc->max_retrans = sp->assocparams.sasoc_asocmaxrxt; |
127 | asoc->pf_retrans = sctp_pf_retrans; | 128 | asoc->pf_retrans = net->sctp.pf_retrans; |
128 | 129 | ||
129 | asoc->rto_initial = msecs_to_jiffies(sp->rtoinfo.srto_initial); | 130 | asoc->rto_initial = msecs_to_jiffies(sp->rtoinfo.srto_initial); |
130 | asoc->rto_max = msecs_to_jiffies(sp->rtoinfo.srto_max); | 131 | asoc->rto_max = msecs_to_jiffies(sp->rtoinfo.srto_max); |
@@ -175,7 +176,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
175 | asoc->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = 0; | 176 | asoc->timeouts[SCTP_EVENT_TIMEOUT_HEARTBEAT] = 0; |
176 | asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay; | 177 | asoc->timeouts[SCTP_EVENT_TIMEOUT_SACK] = asoc->sackdelay; |
177 | asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] = | 178 | asoc->timeouts[SCTP_EVENT_TIMEOUT_AUTOCLOSE] = |
178 | min_t(unsigned long, sp->autoclose, sctp_max_autoclose) * HZ; | 179 | min_t(unsigned long, sp->autoclose, net->sctp.max_autoclose) * HZ; |
179 | 180 | ||
180 | /* Initializes the timers */ | 181 | /* Initializes the timers */ |
181 | for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i) | 182 | for (i = SCTP_EVENT_TIMEOUT_NONE; i < SCTP_NUM_TIMEOUT_TYPES; ++i) |
@@ -281,7 +282,7 @@ static struct sctp_association *sctp_association_init(struct sctp_association *a | |||
281 | * and will revert old behavior. | 282 | * and will revert old behavior. |
282 | */ | 283 | */ |
283 | asoc->peer.asconf_capable = 0; | 284 | asoc->peer.asconf_capable = 0; |
284 | if (sctp_addip_noauth) | 285 | if (net->sctp.addip_noauth) |
285 | asoc->peer.asconf_capable = 1; | 286 | asoc->peer.asconf_capable = 1; |
286 | asoc->asconf_addr_del_pending = NULL; | 287 | asoc->asconf_addr_del_pending = NULL; |
287 | asoc->src_out_of_asoc_ok = 0; | 288 | asoc->src_out_of_asoc_ok = 0; |
@@ -641,6 +642,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | |||
641 | const gfp_t gfp, | 642 | const gfp_t gfp, |
642 | const int peer_state) | 643 | const int peer_state) |
643 | { | 644 | { |
645 | struct net *net = sock_net(asoc->base.sk); | ||
644 | struct sctp_transport *peer; | 646 | struct sctp_transport *peer; |
645 | struct sctp_sock *sp; | 647 | struct sctp_sock *sp; |
646 | unsigned short port; | 648 | unsigned short port; |
@@ -674,7 +676,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc, | |||
674 | return peer; | 676 | return peer; |
675 | } | 677 | } |
676 | 678 | ||
677 | peer = sctp_transport_new(addr, gfp); | 679 | peer = sctp_transport_new(net, addr, gfp); |
678 | if (!peer) | 680 | if (!peer) |
679 | return NULL; | 681 | return NULL; |
680 | 682 | ||
@@ -1089,13 +1091,15 @@ out: | |||
1089 | 1091 | ||
1090 | /* Is this the association we are looking for? */ | 1092 | /* Is this the association we are looking for? */ |
1091 | struct sctp_transport *sctp_assoc_is_match(struct sctp_association *asoc, | 1093 | struct sctp_transport *sctp_assoc_is_match(struct sctp_association *asoc, |
1094 | struct net *net, | ||
1092 | const union sctp_addr *laddr, | 1095 | const union sctp_addr *laddr, |
1093 | const union sctp_addr *paddr) | 1096 | const union sctp_addr *paddr) |
1094 | { | 1097 | { |
1095 | struct sctp_transport *transport; | 1098 | struct sctp_transport *transport; |
1096 | 1099 | ||
1097 | if ((htons(asoc->base.bind_addr.port) == laddr->v4.sin_port) && | 1100 | if ((htons(asoc->base.bind_addr.port) == laddr->v4.sin_port) && |
1098 | (htons(asoc->peer.port) == paddr->v4.sin_port)) { | 1101 | (htons(asoc->peer.port) == paddr->v4.sin_port) && |
1102 | net_eq(sock_net(asoc->base.sk), net)) { | ||
1099 | transport = sctp_assoc_lookup_paddr(asoc, paddr); | 1103 | transport = sctp_assoc_lookup_paddr(asoc, paddr); |
1100 | if (!transport) | 1104 | if (!transport) |
1101 | goto out; | 1105 | goto out; |
@@ -1116,6 +1120,7 @@ static void sctp_assoc_bh_rcv(struct work_struct *work) | |||
1116 | struct sctp_association *asoc = | 1120 | struct sctp_association *asoc = |
1117 | container_of(work, struct sctp_association, | 1121 | container_of(work, struct sctp_association, |
1118 | base.inqueue.immediate); | 1122 | base.inqueue.immediate); |
1123 | struct net *net = sock_net(asoc->base.sk); | ||
1119 | struct sctp_endpoint *ep; | 1124 | struct sctp_endpoint *ep; |
1120 | struct sctp_chunk *chunk; | 1125 | struct sctp_chunk *chunk; |
1121 | struct sctp_inq *inqueue; | 1126 | struct sctp_inq *inqueue; |
@@ -1148,13 +1153,13 @@ static void sctp_assoc_bh_rcv(struct work_struct *work) | |||
1148 | if (sctp_chunk_is_data(chunk)) | 1153 | if (sctp_chunk_is_data(chunk)) |
1149 | asoc->peer.last_data_from = chunk->transport; | 1154 | asoc->peer.last_data_from = chunk->transport; |
1150 | else | 1155 | else |
1151 | SCTP_INC_STATS(SCTP_MIB_INCTRLCHUNKS); | 1156 | SCTP_INC_STATS(net, SCTP_MIB_INCTRLCHUNKS); |
1152 | 1157 | ||
1153 | if (chunk->transport) | 1158 | if (chunk->transport) |
1154 | chunk->transport->last_time_heard = jiffies; | 1159 | chunk->transport->last_time_heard = jiffies; |
1155 | 1160 | ||
1156 | /* Run through the state machine. */ | 1161 | /* Run through the state machine. */ |
1157 | error = sctp_do_sm(SCTP_EVENT_T_CHUNK, subtype, | 1162 | error = sctp_do_sm(net, SCTP_EVENT_T_CHUNK, subtype, |
1158 | state, ep, asoc, chunk, GFP_ATOMIC); | 1163 | state, ep, asoc, chunk, GFP_ATOMIC); |
1159 | 1164 | ||
1160 | /* Check to see if the association is freed in response to | 1165 | /* Check to see if the association is freed in response to |
@@ -1414,6 +1419,7 @@ void sctp_assoc_sync_pmtu(struct sock *sk, struct sctp_association *asoc) | |||
1414 | /* Should we send a SACK to update our peer? */ | 1419 | /* Should we send a SACK to update our peer? */ |
1415 | static inline int sctp_peer_needs_update(struct sctp_association *asoc) | 1420 | static inline int sctp_peer_needs_update(struct sctp_association *asoc) |
1416 | { | 1421 | { |
1422 | struct net *net = sock_net(asoc->base.sk); | ||
1417 | switch (asoc->state) { | 1423 | switch (asoc->state) { |
1418 | case SCTP_STATE_ESTABLISHED: | 1424 | case SCTP_STATE_ESTABLISHED: |
1419 | case SCTP_STATE_SHUTDOWN_PENDING: | 1425 | case SCTP_STATE_SHUTDOWN_PENDING: |
@@ -1421,7 +1427,7 @@ static inline int sctp_peer_needs_update(struct sctp_association *asoc) | |||
1421 | case SCTP_STATE_SHUTDOWN_SENT: | 1427 | case SCTP_STATE_SHUTDOWN_SENT: |
1422 | if ((asoc->rwnd > asoc->a_rwnd) && | 1428 | if ((asoc->rwnd > asoc->a_rwnd) && |
1423 | ((asoc->rwnd - asoc->a_rwnd) >= max_t(__u32, | 1429 | ((asoc->rwnd - asoc->a_rwnd) >= max_t(__u32, |
1424 | (asoc->base.sk->sk_rcvbuf >> sctp_rwnd_upd_shift), | 1430 | (asoc->base.sk->sk_rcvbuf >> net->sctp.rwnd_upd_shift), |
1425 | asoc->pathmtu))) | 1431 | asoc->pathmtu))) |
1426 | return 1; | 1432 | return 1; |
1427 | break; | 1433 | break; |
@@ -1542,7 +1548,8 @@ int sctp_assoc_set_bind_addr_from_ep(struct sctp_association *asoc, | |||
1542 | if (asoc->peer.ipv6_address) | 1548 | if (asoc->peer.ipv6_address) |
1543 | flags |= SCTP_ADDR6_PEERSUPP; | 1549 | flags |= SCTP_ADDR6_PEERSUPP; |
1544 | 1550 | ||
1545 | return sctp_bind_addr_copy(&asoc->base.bind_addr, | 1551 | return sctp_bind_addr_copy(sock_net(asoc->base.sk), |
1552 | &asoc->base.bind_addr, | ||
1546 | &asoc->ep->base.bind_addr, | 1553 | &asoc->ep->base.bind_addr, |
1547 | scope, gfp, flags); | 1554 | scope, gfp, flags); |
1548 | } | 1555 | } |
diff --git a/net/sctp/auth.c b/net/sctp/auth.c index bf812048cf6f..159b9bc5d633 100644 --- a/net/sctp/auth.c +++ b/net/sctp/auth.c | |||
@@ -392,13 +392,14 @@ nomem: | |||
392 | */ | 392 | */ |
393 | int sctp_auth_asoc_init_active_key(struct sctp_association *asoc, gfp_t gfp) | 393 | int sctp_auth_asoc_init_active_key(struct sctp_association *asoc, gfp_t gfp) |
394 | { | 394 | { |
395 | struct net *net = sock_net(asoc->base.sk); | ||
395 | struct sctp_auth_bytes *secret; | 396 | struct sctp_auth_bytes *secret; |
396 | struct sctp_shared_key *ep_key; | 397 | struct sctp_shared_key *ep_key; |
397 | 398 | ||
398 | /* If we don't support AUTH, or peer is not capable | 399 | /* If we don't support AUTH, or peer is not capable |
399 | * we don't need to do anything. | 400 | * we don't need to do anything. |
400 | */ | 401 | */ |
401 | if (!sctp_auth_enable || !asoc->peer.auth_capable) | 402 | if (!net->sctp.auth_enable || !asoc->peer.auth_capable) |
402 | return 0; | 403 | return 0; |
403 | 404 | ||
404 | /* If the key_id is non-zero and we couldn't find an | 405 | /* If the key_id is non-zero and we couldn't find an |
@@ -445,11 +446,12 @@ struct sctp_shared_key *sctp_auth_get_shkey( | |||
445 | */ | 446 | */ |
446 | int sctp_auth_init_hmacs(struct sctp_endpoint *ep, gfp_t gfp) | 447 | int sctp_auth_init_hmacs(struct sctp_endpoint *ep, gfp_t gfp) |
447 | { | 448 | { |
449 | struct net *net = sock_net(ep->base.sk); | ||
448 | struct crypto_hash *tfm = NULL; | 450 | struct crypto_hash *tfm = NULL; |
449 | __u16 id; | 451 | __u16 id; |
450 | 452 | ||
451 | /* if the transforms are already allocted, we are done */ | 453 | /* if the transforms are already allocted, we are done */ |
452 | if (!sctp_auth_enable) { | 454 | if (!net->sctp.auth_enable) { |
453 | ep->auth_hmacs = NULL; | 455 | ep->auth_hmacs = NULL; |
454 | return 0; | 456 | return 0; |
455 | } | 457 | } |
@@ -674,7 +676,12 @@ static int __sctp_auth_cid(sctp_cid_t chunk, struct sctp_chunks_param *param) | |||
674 | /* Check if peer requested that this chunk is authenticated */ | 676 | /* Check if peer requested that this chunk is authenticated */ |
675 | int sctp_auth_send_cid(sctp_cid_t chunk, const struct sctp_association *asoc) | 677 | int sctp_auth_send_cid(sctp_cid_t chunk, const struct sctp_association *asoc) |
676 | { | 678 | { |
677 | if (!sctp_auth_enable || !asoc || !asoc->peer.auth_capable) | 679 | struct net *net; |
680 | if (!asoc) | ||
681 | return 0; | ||
682 | |||
683 | net = sock_net(asoc->base.sk); | ||
684 | if (!net->sctp.auth_enable || !asoc->peer.auth_capable) | ||
678 | return 0; | 685 | return 0; |
679 | 686 | ||
680 | return __sctp_auth_cid(chunk, asoc->peer.peer_chunks); | 687 | return __sctp_auth_cid(chunk, asoc->peer.peer_chunks); |
@@ -683,7 +690,12 @@ int sctp_auth_send_cid(sctp_cid_t chunk, const struct sctp_association *asoc) | |||
683 | /* Check if we requested that peer authenticate this chunk. */ | 690 | /* Check if we requested that peer authenticate this chunk. */ |
684 | int sctp_auth_recv_cid(sctp_cid_t chunk, const struct sctp_association *asoc) | 691 | int sctp_auth_recv_cid(sctp_cid_t chunk, const struct sctp_association *asoc) |
685 | { | 692 | { |
686 | if (!sctp_auth_enable || !asoc) | 693 | struct net *net; |
694 | if (!asoc) | ||
695 | return 0; | ||
696 | |||
697 | net = sock_net(asoc->base.sk); | ||
698 | if (!net->sctp.auth_enable) | ||
687 | return 0; | 699 | return 0; |
688 | 700 | ||
689 | return __sctp_auth_cid(chunk, | 701 | return __sctp_auth_cid(chunk, |
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c index 4ece451c8d27..d886b3bf84f5 100644 --- a/net/sctp/bind_addr.c +++ b/net/sctp/bind_addr.c | |||
@@ -52,8 +52,8 @@ | |||
52 | #include <net/sctp/sm.h> | 52 | #include <net/sctp/sm.h> |
53 | 53 | ||
54 | /* Forward declarations for internal helpers. */ | 54 | /* Forward declarations for internal helpers. */ |
55 | static int sctp_copy_one_addr(struct sctp_bind_addr *, union sctp_addr *, | 55 | static int sctp_copy_one_addr(struct net *, struct sctp_bind_addr *, |
56 | sctp_scope_t scope, gfp_t gfp, | 56 | union sctp_addr *, sctp_scope_t scope, gfp_t gfp, |
57 | int flags); | 57 | int flags); |
58 | static void sctp_bind_addr_clean(struct sctp_bind_addr *); | 58 | static void sctp_bind_addr_clean(struct sctp_bind_addr *); |
59 | 59 | ||
@@ -62,7 +62,7 @@ static void sctp_bind_addr_clean(struct sctp_bind_addr *); | |||
62 | /* Copy 'src' to 'dest' taking 'scope' into account. Omit addresses | 62 | /* Copy 'src' to 'dest' taking 'scope' into account. Omit addresses |
63 | * in 'src' which have a broader scope than 'scope'. | 63 | * in 'src' which have a broader scope than 'scope'. |
64 | */ | 64 | */ |
65 | int sctp_bind_addr_copy(struct sctp_bind_addr *dest, | 65 | int sctp_bind_addr_copy(struct net *net, struct sctp_bind_addr *dest, |
66 | const struct sctp_bind_addr *src, | 66 | const struct sctp_bind_addr *src, |
67 | sctp_scope_t scope, gfp_t gfp, | 67 | sctp_scope_t scope, gfp_t gfp, |
68 | int flags) | 68 | int flags) |
@@ -75,7 +75,7 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest, | |||
75 | 75 | ||
76 | /* Extract the addresses which are relevant for this scope. */ | 76 | /* Extract the addresses which are relevant for this scope. */ |
77 | list_for_each_entry(addr, &src->address_list, list) { | 77 | list_for_each_entry(addr, &src->address_list, list) { |
78 | error = sctp_copy_one_addr(dest, &addr->a, scope, | 78 | error = sctp_copy_one_addr(net, dest, &addr->a, scope, |
79 | gfp, flags); | 79 | gfp, flags); |
80 | if (error < 0) | 80 | if (error < 0) |
81 | goto out; | 81 | goto out; |
@@ -87,7 +87,7 @@ int sctp_bind_addr_copy(struct sctp_bind_addr *dest, | |||
87 | */ | 87 | */ |
88 | if (list_empty(&dest->address_list) && (SCTP_SCOPE_GLOBAL == scope)) { | 88 | if (list_empty(&dest->address_list) && (SCTP_SCOPE_GLOBAL == scope)) { |
89 | list_for_each_entry(addr, &src->address_list, list) { | 89 | list_for_each_entry(addr, &src->address_list, list) { |
90 | error = sctp_copy_one_addr(dest, &addr->a, | 90 | error = sctp_copy_one_addr(net, dest, &addr->a, |
91 | SCTP_SCOPE_LINK, gfp, | 91 | SCTP_SCOPE_LINK, gfp, |
92 | flags); | 92 | flags); |
93 | if (error < 0) | 93 | if (error < 0) |
@@ -448,7 +448,7 @@ union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr *bp, | |||
448 | } | 448 | } |
449 | 449 | ||
450 | /* Copy out addresses from the global local address list. */ | 450 | /* Copy out addresses from the global local address list. */ |
451 | static int sctp_copy_one_addr(struct sctp_bind_addr *dest, | 451 | static int sctp_copy_one_addr(struct net *net, struct sctp_bind_addr *dest, |
452 | union sctp_addr *addr, | 452 | union sctp_addr *addr, |
453 | sctp_scope_t scope, gfp_t gfp, | 453 | sctp_scope_t scope, gfp_t gfp, |
454 | int flags) | 454 | int flags) |
@@ -456,8 +456,8 @@ static int sctp_copy_one_addr(struct sctp_bind_addr *dest, | |||
456 | int error = 0; | 456 | int error = 0; |
457 | 457 | ||
458 | if (sctp_is_any(NULL, addr)) { | 458 | if (sctp_is_any(NULL, addr)) { |
459 | error = sctp_copy_local_addr_list(dest, scope, gfp, flags); | 459 | error = sctp_copy_local_addr_list(net, dest, scope, gfp, flags); |
460 | } else if (sctp_in_scope(addr, scope)) { | 460 | } else if (sctp_in_scope(net, addr, scope)) { |
461 | /* Now that the address is in scope, check to see if | 461 | /* Now that the address is in scope, check to see if |
462 | * the address type is supported by local sock as | 462 | * the address type is supported by local sock as |
463 | * well as the remote peer. | 463 | * well as the remote peer. |
@@ -494,7 +494,7 @@ int sctp_is_any(struct sock *sk, const union sctp_addr *addr) | |||
494 | } | 494 | } |
495 | 495 | ||
496 | /* Is 'addr' valid for 'scope'? */ | 496 | /* Is 'addr' valid for 'scope'? */ |
497 | int sctp_in_scope(const union sctp_addr *addr, sctp_scope_t scope) | 497 | int sctp_in_scope(struct net *net, const union sctp_addr *addr, sctp_scope_t scope) |
498 | { | 498 | { |
499 | sctp_scope_t addr_scope = sctp_scope(addr); | 499 | sctp_scope_t addr_scope = sctp_scope(addr); |
500 | 500 | ||
@@ -512,7 +512,7 @@ int sctp_in_scope(const union sctp_addr *addr, sctp_scope_t scope) | |||
512 | * Address scoping can be selectively controlled via sysctl | 512 | * Address scoping can be selectively controlled via sysctl |
513 | * option | 513 | * option |
514 | */ | 514 | */ |
515 | switch (sctp_scope_policy) { | 515 | switch (net->sctp.scope_policy) { |
516 | case SCTP_SCOPE_POLICY_DISABLE: | 516 | case SCTP_SCOPE_POLICY_DISABLE: |
517 | return 1; | 517 | return 1; |
518 | case SCTP_SCOPE_POLICY_ENABLE: | 518 | case SCTP_SCOPE_POLICY_ENABLE: |
diff --git a/net/sctp/chunk.c b/net/sctp/chunk.c index 6c8556459a75..7c2df9c33df3 100644 --- a/net/sctp/chunk.c +++ b/net/sctp/chunk.c | |||
@@ -257,7 +257,7 @@ struct sctp_datamsg *sctp_datamsg_from_user(struct sctp_association *asoc, | |||
257 | offset = 0; | 257 | offset = 0; |
258 | 258 | ||
259 | if ((whole > 1) || (whole && over)) | 259 | if ((whole > 1) || (whole && over)) |
260 | SCTP_INC_STATS_USER(SCTP_MIB_FRAGUSRMSGS); | 260 | SCTP_INC_STATS_USER(sock_net(asoc->base.sk), SCTP_MIB_FRAGUSRMSGS); |
261 | 261 | ||
262 | /* Create chunks for all the full sized DATA chunks. */ | 262 | /* Create chunks for all the full sized DATA chunks. */ |
263 | for (i=0, len=first_len; i < whole; i++) { | 263 | for (i=0, len=first_len; i < whole; i++) { |
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c index 68a385d7c3bd..1859e2bc83d1 100644 --- a/net/sctp/endpointola.c +++ b/net/sctp/endpointola.c | |||
@@ -65,6 +65,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, | |||
65 | struct sock *sk, | 65 | struct sock *sk, |
66 | gfp_t gfp) | 66 | gfp_t gfp) |
67 | { | 67 | { |
68 | struct net *net = sock_net(sk); | ||
68 | struct sctp_hmac_algo_param *auth_hmacs = NULL; | 69 | struct sctp_hmac_algo_param *auth_hmacs = NULL; |
69 | struct sctp_chunks_param *auth_chunks = NULL; | 70 | struct sctp_chunks_param *auth_chunks = NULL; |
70 | struct sctp_shared_key *null_key; | 71 | struct sctp_shared_key *null_key; |
@@ -74,7 +75,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, | |||
74 | if (!ep->digest) | 75 | if (!ep->digest) |
75 | return NULL; | 76 | return NULL; |
76 | 77 | ||
77 | if (sctp_auth_enable) { | 78 | if (net->sctp.auth_enable) { |
78 | /* Allocate space for HMACS and CHUNKS authentication | 79 | /* Allocate space for HMACS and CHUNKS authentication |
79 | * variables. There are arrays that we encode directly | 80 | * variables. There are arrays that we encode directly |
80 | * into parameters to make the rest of the operations easier. | 81 | * into parameters to make the rest of the operations easier. |
@@ -106,7 +107,7 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, | |||
106 | /* If the Add-IP functionality is enabled, we must | 107 | /* If the Add-IP functionality is enabled, we must |
107 | * authenticate, ASCONF and ASCONF-ACK chunks | 108 | * authenticate, ASCONF and ASCONF-ACK chunks |
108 | */ | 109 | */ |
109 | if (sctp_addip_enable) { | 110 | if (net->sctp.addip_enable) { |
110 | auth_chunks->chunks[0] = SCTP_CID_ASCONF; | 111 | auth_chunks->chunks[0] = SCTP_CID_ASCONF; |
111 | auth_chunks->chunks[1] = SCTP_CID_ASCONF_ACK; | 112 | auth_chunks->chunks[1] = SCTP_CID_ASCONF_ACK; |
112 | auth_chunks->param_hdr.length = | 113 | auth_chunks->param_hdr.length = |
@@ -140,14 +141,14 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep, | |||
140 | INIT_LIST_HEAD(&ep->asocs); | 141 | INIT_LIST_HEAD(&ep->asocs); |
141 | 142 | ||
142 | /* Use SCTP specific send buffer space queues. */ | 143 | /* Use SCTP specific send buffer space queues. */ |
143 | ep->sndbuf_policy = sctp_sndbuf_policy; | 144 | ep->sndbuf_policy = net->sctp.sndbuf_policy; |
144 | 145 | ||
145 | sk->sk_data_ready = sctp_data_ready; | 146 | sk->sk_data_ready = sctp_data_ready; |
146 | sk->sk_write_space = sctp_write_space; | 147 | sk->sk_write_space = sctp_write_space; |
147 | sock_set_flag(sk, SOCK_USE_WRITE_QUEUE); | 148 | sock_set_flag(sk, SOCK_USE_WRITE_QUEUE); |
148 | 149 | ||
149 | /* Get the receive buffer policy for this endpoint */ | 150 | /* Get the receive buffer policy for this endpoint */ |
150 | ep->rcvbuf_policy = sctp_rcvbuf_policy; | 151 | ep->rcvbuf_policy = net->sctp.rcvbuf_policy; |
151 | 152 | ||
152 | /* Initialize the secret key used with cookie. */ | 153 | /* Initialize the secret key used with cookie. */ |
153 | get_random_bytes(&ep->secret_key[0], SCTP_SECRET_SIZE); | 154 | get_random_bytes(&ep->secret_key[0], SCTP_SECRET_SIZE); |
@@ -302,11 +303,13 @@ void sctp_endpoint_put(struct sctp_endpoint *ep) | |||
302 | 303 | ||
303 | /* Is this the endpoint we are looking for? */ | 304 | /* Is this the endpoint we are looking for? */ |
304 | struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *ep, | 305 | struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *ep, |
306 | struct net *net, | ||
305 | const union sctp_addr *laddr) | 307 | const union sctp_addr *laddr) |
306 | { | 308 | { |
307 | struct sctp_endpoint *retval = NULL; | 309 | struct sctp_endpoint *retval = NULL; |
308 | 310 | ||
309 | if (htons(ep->base.bind_addr.port) == laddr->v4.sin_port) { | 311 | if ((htons(ep->base.bind_addr.port) == laddr->v4.sin_port) && |
312 | net_eq(sock_net(ep->base.sk), net)) { | ||
310 | if (sctp_bind_addr_match(&ep->base.bind_addr, laddr, | 313 | if (sctp_bind_addr_match(&ep->base.bind_addr, laddr, |
311 | sctp_sk(ep->base.sk))) | 314 | sctp_sk(ep->base.sk))) |
312 | retval = ep; | 315 | retval = ep; |
@@ -343,7 +346,8 @@ static struct sctp_association *__sctp_endpoint_lookup_assoc( | |||
343 | 346 | ||
344 | rport = ntohs(paddr->v4.sin_port); | 347 | rport = ntohs(paddr->v4.sin_port); |
345 | 348 | ||
346 | hash = sctp_assoc_hashfn(ep->base.bind_addr.port, rport); | 349 | hash = sctp_assoc_hashfn(sock_net(ep->base.sk), ep->base.bind_addr.port, |
350 | rport); | ||
347 | head = &sctp_assoc_hashtable[hash]; | 351 | head = &sctp_assoc_hashtable[hash]; |
348 | read_lock(&head->lock); | 352 | read_lock(&head->lock); |
349 | sctp_for_each_hentry(epb, node, &head->chain) { | 353 | sctp_for_each_hentry(epb, node, &head->chain) { |
@@ -386,13 +390,14 @@ int sctp_endpoint_is_peeled_off(struct sctp_endpoint *ep, | |||
386 | { | 390 | { |
387 | struct sctp_sockaddr_entry *addr; | 391 | struct sctp_sockaddr_entry *addr; |
388 | struct sctp_bind_addr *bp; | 392 | struct sctp_bind_addr *bp; |
393 | struct net *net = sock_net(ep->base.sk); | ||
389 | 394 | ||
390 | bp = &ep->base.bind_addr; | 395 | bp = &ep->base.bind_addr; |
391 | /* This function is called with the socket lock held, | 396 | /* This function is called with the socket lock held, |
392 | * so the address_list can not change. | 397 | * so the address_list can not change. |
393 | */ | 398 | */ |
394 | list_for_each_entry(addr, &bp->address_list, list) { | 399 | list_for_each_entry(addr, &bp->address_list, list) { |
395 | if (sctp_has_association(&addr->a, paddr)) | 400 | if (sctp_has_association(net, &addr->a, paddr)) |
396 | return 1; | 401 | return 1; |
397 | } | 402 | } |
398 | 403 | ||
@@ -409,6 +414,7 @@ static void sctp_endpoint_bh_rcv(struct work_struct *work) | |||
409 | base.inqueue.immediate); | 414 | base.inqueue.immediate); |
410 | struct sctp_association *asoc; | 415 | struct sctp_association *asoc; |
411 | struct sock *sk; | 416 | struct sock *sk; |
417 | struct net *net; | ||
412 | struct sctp_transport *transport; | 418 | struct sctp_transport *transport; |
413 | struct sctp_chunk *chunk; | 419 | struct sctp_chunk *chunk; |
414 | struct sctp_inq *inqueue; | 420 | struct sctp_inq *inqueue; |
@@ -423,6 +429,7 @@ static void sctp_endpoint_bh_rcv(struct work_struct *work) | |||
423 | asoc = NULL; | 429 | asoc = NULL; |
424 | inqueue = &ep->base.inqueue; | 430 | inqueue = &ep->base.inqueue; |
425 | sk = ep->base.sk; | 431 | sk = ep->base.sk; |
432 | net = sock_net(sk); | ||
426 | 433 | ||
427 | while (NULL != (chunk = sctp_inq_pop(inqueue))) { | 434 | while (NULL != (chunk = sctp_inq_pop(inqueue))) { |
428 | subtype = SCTP_ST_CHUNK(chunk->chunk_hdr->type); | 435 | subtype = SCTP_ST_CHUNK(chunk->chunk_hdr->type); |
@@ -474,12 +481,12 @@ normal: | |||
474 | if (asoc && sctp_chunk_is_data(chunk)) | 481 | if (asoc && sctp_chunk_is_data(chunk)) |
475 | asoc->peer.last_data_from = chunk->transport; | 482 | asoc->peer.last_data_from = chunk->transport; |
476 | else | 483 | else |
477 | SCTP_INC_STATS(SCTP_MIB_INCTRLCHUNKS); | 484 | SCTP_INC_STATS(sock_net(ep->base.sk), SCTP_MIB_INCTRLCHUNKS); |
478 | 485 | ||
479 | if (chunk->transport) | 486 | if (chunk->transport) |
480 | chunk->transport->last_time_heard = jiffies; | 487 | chunk->transport->last_time_heard = jiffies; |
481 | 488 | ||
482 | error = sctp_do_sm(SCTP_EVENT_T_CHUNK, subtype, state, | 489 | error = sctp_do_sm(net, SCTP_EVENT_T_CHUNK, subtype, state, |
483 | ep, asoc, chunk, GFP_ATOMIC); | 490 | ep, asoc, chunk, GFP_ATOMIC); |
484 | 491 | ||
485 | if (error && chunk) | 492 | if (error && chunk) |
diff --git a/net/sctp/input.c b/net/sctp/input.c index e64d5210ed13..25dfe7380479 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
@@ -66,12 +66,15 @@ | |||
66 | 66 | ||
67 | /* Forward declarations for internal helpers. */ | 67 | /* Forward declarations for internal helpers. */ |
68 | static int sctp_rcv_ootb(struct sk_buff *); | 68 | static int sctp_rcv_ootb(struct sk_buff *); |
69 | static struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb, | 69 | static struct sctp_association *__sctp_rcv_lookup(struct net *net, |
70 | struct sk_buff *skb, | ||
70 | const union sctp_addr *laddr, | 71 | const union sctp_addr *laddr, |
71 | const union sctp_addr *paddr, | 72 | const union sctp_addr *paddr, |
72 | struct sctp_transport **transportp); | 73 | struct sctp_transport **transportp); |
73 | static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr); | 74 | static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(struct net *net, |
75 | const union sctp_addr *laddr); | ||
74 | static struct sctp_association *__sctp_lookup_association( | 76 | static struct sctp_association *__sctp_lookup_association( |
77 | struct net *net, | ||
75 | const union sctp_addr *local, | 78 | const union sctp_addr *local, |
76 | const union sctp_addr *peer, | 79 | const union sctp_addr *peer, |
77 | struct sctp_transport **pt); | 80 | struct sctp_transport **pt); |
@@ -80,7 +83,7 @@ static int sctp_add_backlog(struct sock *sk, struct sk_buff *skb); | |||
80 | 83 | ||
81 | 84 | ||
82 | /* Calculate the SCTP checksum of an SCTP packet. */ | 85 | /* Calculate the SCTP checksum of an SCTP packet. */ |
83 | static inline int sctp_rcv_checksum(struct sk_buff *skb) | 86 | static inline int sctp_rcv_checksum(struct net *net, struct sk_buff *skb) |
84 | { | 87 | { |
85 | struct sctphdr *sh = sctp_hdr(skb); | 88 | struct sctphdr *sh = sctp_hdr(skb); |
86 | __le32 cmp = sh->checksum; | 89 | __le32 cmp = sh->checksum; |
@@ -96,7 +99,7 @@ static inline int sctp_rcv_checksum(struct sk_buff *skb) | |||
96 | 99 | ||
97 | if (val != cmp) { | 100 | if (val != cmp) { |
98 | /* CRC failure, dump it. */ | 101 | /* CRC failure, dump it. */ |
99 | SCTP_INC_STATS_BH(SCTP_MIB_CHECKSUMERRORS); | 102 | SCTP_INC_STATS_BH(net, SCTP_MIB_CHECKSUMERRORS); |
100 | return -1; | 103 | return -1; |
101 | } | 104 | } |
102 | return 0; | 105 | return 0; |
@@ -129,11 +132,12 @@ int sctp_rcv(struct sk_buff *skb) | |||
129 | union sctp_addr dest; | 132 | union sctp_addr dest; |
130 | int family; | 133 | int family; |
131 | struct sctp_af *af; | 134 | struct sctp_af *af; |
135 | struct net *net = dev_net(skb->dev); | ||
132 | 136 | ||
133 | if (skb->pkt_type!=PACKET_HOST) | 137 | if (skb->pkt_type!=PACKET_HOST) |
134 | goto discard_it; | 138 | goto discard_it; |
135 | 139 | ||
136 | SCTP_INC_STATS_BH(SCTP_MIB_INSCTPPACKS); | 140 | SCTP_INC_STATS_BH(net, SCTP_MIB_INSCTPPACKS); |
137 | 141 | ||
138 | if (skb_linearize(skb)) | 142 | if (skb_linearize(skb)) |
139 | goto discard_it; | 143 | goto discard_it; |
@@ -145,7 +149,7 @@ int sctp_rcv(struct sk_buff *skb) | |||
145 | if (skb->len < sizeof(struct sctphdr)) | 149 | if (skb->len < sizeof(struct sctphdr)) |
146 | goto discard_it; | 150 | goto discard_it; |
147 | if (!sctp_checksum_disable && !skb_csum_unnecessary(skb) && | 151 | if (!sctp_checksum_disable && !skb_csum_unnecessary(skb) && |
148 | sctp_rcv_checksum(skb) < 0) | 152 | sctp_rcv_checksum(net, skb) < 0) |
149 | goto discard_it; | 153 | goto discard_it; |
150 | 154 | ||
151 | skb_pull(skb, sizeof(struct sctphdr)); | 155 | skb_pull(skb, sizeof(struct sctphdr)); |
@@ -178,10 +182,10 @@ int sctp_rcv(struct sk_buff *skb) | |||
178 | !af->addr_valid(&dest, NULL, skb)) | 182 | !af->addr_valid(&dest, NULL, skb)) |
179 | goto discard_it; | 183 | goto discard_it; |
180 | 184 | ||
181 | asoc = __sctp_rcv_lookup(skb, &src, &dest, &transport); | 185 | asoc = __sctp_rcv_lookup(net, skb, &src, &dest, &transport); |
182 | 186 | ||
183 | if (!asoc) | 187 | if (!asoc) |
184 | ep = __sctp_rcv_lookup_endpoint(&dest); | 188 | ep = __sctp_rcv_lookup_endpoint(net, &dest); |
185 | 189 | ||
186 | /* Retrieve the common input handling substructure. */ | 190 | /* Retrieve the common input handling substructure. */ |
187 | rcvr = asoc ? &asoc->base : &ep->base; | 191 | rcvr = asoc ? &asoc->base : &ep->base; |
@@ -200,7 +204,7 @@ int sctp_rcv(struct sk_buff *skb) | |||
200 | sctp_endpoint_put(ep); | 204 | sctp_endpoint_put(ep); |
201 | ep = NULL; | 205 | ep = NULL; |
202 | } | 206 | } |
203 | sk = sctp_get_ctl_sock(); | 207 | sk = net->sctp.ctl_sock; |
204 | ep = sctp_sk(sk)->ep; | 208 | ep = sctp_sk(sk)->ep; |
205 | sctp_endpoint_hold(ep); | 209 | sctp_endpoint_hold(ep); |
206 | rcvr = &ep->base; | 210 | rcvr = &ep->base; |
@@ -216,7 +220,7 @@ int sctp_rcv(struct sk_buff *skb) | |||
216 | */ | 220 | */ |
217 | if (!asoc) { | 221 | if (!asoc) { |
218 | if (sctp_rcv_ootb(skb)) { | 222 | if (sctp_rcv_ootb(skb)) { |
219 | SCTP_INC_STATS_BH(SCTP_MIB_OUTOFBLUES); | 223 | SCTP_INC_STATS_BH(net, SCTP_MIB_OUTOFBLUES); |
220 | goto discard_release; | 224 | goto discard_release; |
221 | } | 225 | } |
222 | } | 226 | } |
@@ -272,9 +276,9 @@ int sctp_rcv(struct sk_buff *skb) | |||
272 | skb = NULL; /* sctp_chunk_free already freed the skb */ | 276 | skb = NULL; /* sctp_chunk_free already freed the skb */ |
273 | goto discard_release; | 277 | goto discard_release; |
274 | } | 278 | } |
275 | SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_BACKLOG); | 279 | SCTP_INC_STATS_BH(net, SCTP_MIB_IN_PKT_BACKLOG); |
276 | } else { | 280 | } else { |
277 | SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_SOFTIRQ); | 281 | SCTP_INC_STATS_BH(net, SCTP_MIB_IN_PKT_SOFTIRQ); |
278 | sctp_inq_push(&chunk->rcvr->inqueue, chunk); | 282 | sctp_inq_push(&chunk->rcvr->inqueue, chunk); |
279 | } | 283 | } |
280 | 284 | ||
@@ -289,7 +293,7 @@ int sctp_rcv(struct sk_buff *skb) | |||
289 | return 0; | 293 | return 0; |
290 | 294 | ||
291 | discard_it: | 295 | discard_it: |
292 | SCTP_INC_STATS_BH(SCTP_MIB_IN_PKT_DISCARDS); | 296 | SCTP_INC_STATS_BH(net, SCTP_MIB_IN_PKT_DISCARDS); |
293 | kfree_skb(skb); | 297 | kfree_skb(skb); |
294 | return 0; | 298 | return 0; |
295 | 299 | ||
@@ -462,11 +466,13 @@ void sctp_icmp_proto_unreachable(struct sock *sk, | |||
462 | } | 466 | } |
463 | 467 | ||
464 | } else { | 468 | } else { |
469 | struct net *net = sock_net(sk); | ||
470 | |||
465 | if (timer_pending(&t->proto_unreach_timer) && | 471 | if (timer_pending(&t->proto_unreach_timer) && |
466 | del_timer(&t->proto_unreach_timer)) | 472 | del_timer(&t->proto_unreach_timer)) |
467 | sctp_association_put(asoc); | 473 | sctp_association_put(asoc); |
468 | 474 | ||
469 | sctp_do_sm(SCTP_EVENT_T_OTHER, | 475 | sctp_do_sm(net, SCTP_EVENT_T_OTHER, |
470 | SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH), | 476 | SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH), |
471 | asoc->state, asoc->ep, asoc, t, | 477 | asoc->state, asoc->ep, asoc, t, |
472 | GFP_ATOMIC); | 478 | GFP_ATOMIC); |
@@ -474,7 +480,7 @@ void sctp_icmp_proto_unreachable(struct sock *sk, | |||
474 | } | 480 | } |
475 | 481 | ||
476 | /* Common lookup code for icmp/icmpv6 error handler. */ | 482 | /* Common lookup code for icmp/icmpv6 error handler. */ |
477 | struct sock *sctp_err_lookup(int family, struct sk_buff *skb, | 483 | struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb, |
478 | struct sctphdr *sctphdr, | 484 | struct sctphdr *sctphdr, |
479 | struct sctp_association **app, | 485 | struct sctp_association **app, |
480 | struct sctp_transport **tpp) | 486 | struct sctp_transport **tpp) |
@@ -503,7 +509,7 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb, | |||
503 | /* Look for an association that matches the incoming ICMP error | 509 | /* Look for an association that matches the incoming ICMP error |
504 | * packet. | 510 | * packet. |
505 | */ | 511 | */ |
506 | asoc = __sctp_lookup_association(&saddr, &daddr, &transport); | 512 | asoc = __sctp_lookup_association(net, &saddr, &daddr, &transport); |
507 | if (!asoc) | 513 | if (!asoc) |
508 | return NULL; | 514 | return NULL; |
509 | 515 | ||
@@ -539,7 +545,7 @@ struct sock *sctp_err_lookup(int family, struct sk_buff *skb, | |||
539 | * servers this needs to be solved differently. | 545 | * servers this needs to be solved differently. |
540 | */ | 546 | */ |
541 | if (sock_owned_by_user(sk)) | 547 | if (sock_owned_by_user(sk)) |
542 | NET_INC_STATS_BH(&init_net, LINUX_MIB_LOCKDROPPEDICMPS); | 548 | NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS); |
543 | 549 | ||
544 | *app = asoc; | 550 | *app = asoc; |
545 | *tpp = transport; | 551 | *tpp = transport; |
@@ -586,9 +592,10 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info) | |||
586 | struct inet_sock *inet; | 592 | struct inet_sock *inet; |
587 | sk_buff_data_t saveip, savesctp; | 593 | sk_buff_data_t saveip, savesctp; |
588 | int err; | 594 | int err; |
595 | struct net *net = dev_net(skb->dev); | ||
589 | 596 | ||
590 | if (skb->len < ihlen + 8) { | 597 | if (skb->len < ihlen + 8) { |
591 | ICMP_INC_STATS_BH(&init_net, ICMP_MIB_INERRORS); | 598 | ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); |
592 | return; | 599 | return; |
593 | } | 600 | } |
594 | 601 | ||
@@ -597,12 +604,12 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info) | |||
597 | savesctp = skb->transport_header; | 604 | savesctp = skb->transport_header; |
598 | skb_reset_network_header(skb); | 605 | skb_reset_network_header(skb); |
599 | skb_set_transport_header(skb, ihlen); | 606 | skb_set_transport_header(skb, ihlen); |
600 | sk = sctp_err_lookup(AF_INET, skb, sctp_hdr(skb), &asoc, &transport); | 607 | sk = sctp_err_lookup(net, AF_INET, skb, sctp_hdr(skb), &asoc, &transport); |
601 | /* Put back, the original values. */ | 608 | /* Put back, the original values. */ |
602 | skb->network_header = saveip; | 609 | skb->network_header = saveip; |
603 | skb->transport_header = savesctp; | 610 | skb->transport_header = savesctp; |
604 | if (!sk) { | 611 | if (!sk) { |
605 | ICMP_INC_STATS_BH(&init_net, ICMP_MIB_INERRORS); | 612 | ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); |
606 | return; | 613 | return; |
607 | } | 614 | } |
608 | /* Warning: The sock lock is held. Remember to call | 615 | /* Warning: The sock lock is held. Remember to call |
@@ -723,12 +730,13 @@ discard: | |||
723 | /* Insert endpoint into the hash table. */ | 730 | /* Insert endpoint into the hash table. */ |
724 | static void __sctp_hash_endpoint(struct sctp_endpoint *ep) | 731 | static void __sctp_hash_endpoint(struct sctp_endpoint *ep) |
725 | { | 732 | { |
733 | struct net *net = sock_net(ep->base.sk); | ||
726 | struct sctp_ep_common *epb; | 734 | struct sctp_ep_common *epb; |
727 | struct sctp_hashbucket *head; | 735 | struct sctp_hashbucket *head; |
728 | 736 | ||
729 | epb = &ep->base; | 737 | epb = &ep->base; |
730 | 738 | ||
731 | epb->hashent = sctp_ep_hashfn(epb->bind_addr.port); | 739 | epb->hashent = sctp_ep_hashfn(net, epb->bind_addr.port); |
732 | head = &sctp_ep_hashtable[epb->hashent]; | 740 | head = &sctp_ep_hashtable[epb->hashent]; |
733 | 741 | ||
734 | sctp_write_lock(&head->lock); | 742 | sctp_write_lock(&head->lock); |
@@ -747,12 +755,13 @@ void sctp_hash_endpoint(struct sctp_endpoint *ep) | |||
747 | /* Remove endpoint from the hash table. */ | 755 | /* Remove endpoint from the hash table. */ |
748 | static void __sctp_unhash_endpoint(struct sctp_endpoint *ep) | 756 | static void __sctp_unhash_endpoint(struct sctp_endpoint *ep) |
749 | { | 757 | { |
758 | struct net *net = sock_net(ep->base.sk); | ||
750 | struct sctp_hashbucket *head; | 759 | struct sctp_hashbucket *head; |
751 | struct sctp_ep_common *epb; | 760 | struct sctp_ep_common *epb; |
752 | 761 | ||
753 | epb = &ep->base; | 762 | epb = &ep->base; |
754 | 763 | ||
755 | epb->hashent = sctp_ep_hashfn(epb->bind_addr.port); | 764 | epb->hashent = sctp_ep_hashfn(net, epb->bind_addr.port); |
756 | 765 | ||
757 | head = &sctp_ep_hashtable[epb->hashent]; | 766 | head = &sctp_ep_hashtable[epb->hashent]; |
758 | 767 | ||
@@ -770,7 +779,8 @@ void sctp_unhash_endpoint(struct sctp_endpoint *ep) | |||
770 | } | 779 | } |
771 | 780 | ||
772 | /* Look up an endpoint. */ | 781 | /* Look up an endpoint. */ |
773 | static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *laddr) | 782 | static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(struct net *net, |
783 | const union sctp_addr *laddr) | ||
774 | { | 784 | { |
775 | struct sctp_hashbucket *head; | 785 | struct sctp_hashbucket *head; |
776 | struct sctp_ep_common *epb; | 786 | struct sctp_ep_common *epb; |
@@ -778,16 +788,16 @@ static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(const union sctp_addr *l | |||
778 | struct hlist_node *node; | 788 | struct hlist_node *node; |
779 | int hash; | 789 | int hash; |
780 | 790 | ||
781 | hash = sctp_ep_hashfn(ntohs(laddr->v4.sin_port)); | 791 | hash = sctp_ep_hashfn(net, ntohs(laddr->v4.sin_port)); |
782 | head = &sctp_ep_hashtable[hash]; | 792 | head = &sctp_ep_hashtable[hash]; |
783 | read_lock(&head->lock); | 793 | read_lock(&head->lock); |
784 | sctp_for_each_hentry(epb, node, &head->chain) { | 794 | sctp_for_each_hentry(epb, node, &head->chain) { |
785 | ep = sctp_ep(epb); | 795 | ep = sctp_ep(epb); |
786 | if (sctp_endpoint_is_match(ep, laddr)) | 796 | if (sctp_endpoint_is_match(ep, net, laddr)) |
787 | goto hit; | 797 | goto hit; |
788 | } | 798 | } |
789 | 799 | ||
790 | ep = sctp_sk((sctp_get_ctl_sock()))->ep; | 800 | ep = sctp_sk(net->sctp.ctl_sock)->ep; |
791 | 801 | ||
792 | hit: | 802 | hit: |
793 | sctp_endpoint_hold(ep); | 803 | sctp_endpoint_hold(ep); |
@@ -798,13 +808,15 @@ hit: | |||
798 | /* Insert association into the hash table. */ | 808 | /* Insert association into the hash table. */ |
799 | static void __sctp_hash_established(struct sctp_association *asoc) | 809 | static void __sctp_hash_established(struct sctp_association *asoc) |
800 | { | 810 | { |
811 | struct net *net = sock_net(asoc->base.sk); | ||
801 | struct sctp_ep_common *epb; | 812 | struct sctp_ep_common *epb; |
802 | struct sctp_hashbucket *head; | 813 | struct sctp_hashbucket *head; |
803 | 814 | ||
804 | epb = &asoc->base; | 815 | epb = &asoc->base; |
805 | 816 | ||
806 | /* Calculate which chain this entry will belong to. */ | 817 | /* Calculate which chain this entry will belong to. */ |
807 | epb->hashent = sctp_assoc_hashfn(epb->bind_addr.port, asoc->peer.port); | 818 | epb->hashent = sctp_assoc_hashfn(net, epb->bind_addr.port, |
819 | asoc->peer.port); | ||
808 | 820 | ||
809 | head = &sctp_assoc_hashtable[epb->hashent]; | 821 | head = &sctp_assoc_hashtable[epb->hashent]; |
810 | 822 | ||
@@ -827,12 +839,13 @@ void sctp_hash_established(struct sctp_association *asoc) | |||
827 | /* Remove association from the hash table. */ | 839 | /* Remove association from the hash table. */ |
828 | static void __sctp_unhash_established(struct sctp_association *asoc) | 840 | static void __sctp_unhash_established(struct sctp_association *asoc) |
829 | { | 841 | { |
842 | struct net *net = sock_net(asoc->base.sk); | ||
830 | struct sctp_hashbucket *head; | 843 | struct sctp_hashbucket *head; |
831 | struct sctp_ep_common *epb; | 844 | struct sctp_ep_common *epb; |
832 | 845 | ||
833 | epb = &asoc->base; | 846 | epb = &asoc->base; |
834 | 847 | ||
835 | epb->hashent = sctp_assoc_hashfn(epb->bind_addr.port, | 848 | epb->hashent = sctp_assoc_hashfn(net, epb->bind_addr.port, |
836 | asoc->peer.port); | 849 | asoc->peer.port); |
837 | 850 | ||
838 | head = &sctp_assoc_hashtable[epb->hashent]; | 851 | head = &sctp_assoc_hashtable[epb->hashent]; |
@@ -855,6 +868,7 @@ void sctp_unhash_established(struct sctp_association *asoc) | |||
855 | 868 | ||
856 | /* Look up an association. */ | 869 | /* Look up an association. */ |
857 | static struct sctp_association *__sctp_lookup_association( | 870 | static struct sctp_association *__sctp_lookup_association( |
871 | struct net *net, | ||
858 | const union sctp_addr *local, | 872 | const union sctp_addr *local, |
859 | const union sctp_addr *peer, | 873 | const union sctp_addr *peer, |
860 | struct sctp_transport **pt) | 874 | struct sctp_transport **pt) |
@@ -869,12 +883,13 @@ static struct sctp_association *__sctp_lookup_association( | |||
869 | /* Optimize here for direct hit, only listening connections can | 883 | /* Optimize here for direct hit, only listening connections can |
870 | * have wildcards anyways. | 884 | * have wildcards anyways. |
871 | */ | 885 | */ |
872 | hash = sctp_assoc_hashfn(ntohs(local->v4.sin_port), ntohs(peer->v4.sin_port)); | 886 | hash = sctp_assoc_hashfn(net, ntohs(local->v4.sin_port), |
887 | ntohs(peer->v4.sin_port)); | ||
873 | head = &sctp_assoc_hashtable[hash]; | 888 | head = &sctp_assoc_hashtable[hash]; |
874 | read_lock(&head->lock); | 889 | read_lock(&head->lock); |
875 | sctp_for_each_hentry(epb, node, &head->chain) { | 890 | sctp_for_each_hentry(epb, node, &head->chain) { |
876 | asoc = sctp_assoc(epb); | 891 | asoc = sctp_assoc(epb); |
877 | transport = sctp_assoc_is_match(asoc, local, peer); | 892 | transport = sctp_assoc_is_match(asoc, net, local, peer); |
878 | if (transport) | 893 | if (transport) |
879 | goto hit; | 894 | goto hit; |
880 | } | 895 | } |
@@ -892,27 +907,29 @@ hit: | |||
892 | 907 | ||
893 | /* Look up an association. BH-safe. */ | 908 | /* Look up an association. BH-safe. */ |
894 | SCTP_STATIC | 909 | SCTP_STATIC |
895 | struct sctp_association *sctp_lookup_association(const union sctp_addr *laddr, | 910 | struct sctp_association *sctp_lookup_association(struct net *net, |
911 | const union sctp_addr *laddr, | ||
896 | const union sctp_addr *paddr, | 912 | const union sctp_addr *paddr, |
897 | struct sctp_transport **transportp) | 913 | struct sctp_transport **transportp) |
898 | { | 914 | { |
899 | struct sctp_association *asoc; | 915 | struct sctp_association *asoc; |
900 | 916 | ||
901 | sctp_local_bh_disable(); | 917 | sctp_local_bh_disable(); |
902 | asoc = __sctp_lookup_association(laddr, paddr, transportp); | 918 | asoc = __sctp_lookup_association(net, laddr, paddr, transportp); |
903 | sctp_local_bh_enable(); | 919 | sctp_local_bh_enable(); |
904 | 920 | ||
905 | return asoc; | 921 | return asoc; |
906 | } | 922 | } |
907 | 923 | ||
908 | /* Is there an association matching the given local and peer addresses? */ | 924 | /* Is there an association matching the given local and peer addresses? */ |
909 | int sctp_has_association(const union sctp_addr *laddr, | 925 | int sctp_has_association(struct net *net, |
926 | const union sctp_addr *laddr, | ||
910 | const union sctp_addr *paddr) | 927 | const union sctp_addr *paddr) |
911 | { | 928 | { |
912 | struct sctp_association *asoc; | 929 | struct sctp_association *asoc; |
913 | struct sctp_transport *transport; | 930 | struct sctp_transport *transport; |
914 | 931 | ||
915 | if ((asoc = sctp_lookup_association(laddr, paddr, &transport))) { | 932 | if ((asoc = sctp_lookup_association(net, laddr, paddr, &transport))) { |
916 | sctp_association_put(asoc); | 933 | sctp_association_put(asoc); |
917 | return 1; | 934 | return 1; |
918 | } | 935 | } |
@@ -938,7 +955,8 @@ int sctp_has_association(const union sctp_addr *laddr, | |||
938 | * in certain circumstances. | 955 | * in certain circumstances. |
939 | * | 956 | * |
940 | */ | 957 | */ |
941 | static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb, | 958 | static struct sctp_association *__sctp_rcv_init_lookup(struct net *net, |
959 | struct sk_buff *skb, | ||
942 | const union sctp_addr *laddr, struct sctp_transport **transportp) | 960 | const union sctp_addr *laddr, struct sctp_transport **transportp) |
943 | { | 961 | { |
944 | struct sctp_association *asoc; | 962 | struct sctp_association *asoc; |
@@ -978,7 +996,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb, | |||
978 | 996 | ||
979 | af->from_addr_param(paddr, params.addr, sh->source, 0); | 997 | af->from_addr_param(paddr, params.addr, sh->source, 0); |
980 | 998 | ||
981 | asoc = __sctp_lookup_association(laddr, paddr, &transport); | 999 | asoc = __sctp_lookup_association(net, laddr, paddr, &transport); |
982 | if (asoc) | 1000 | if (asoc) |
983 | return asoc; | 1001 | return asoc; |
984 | } | 1002 | } |
@@ -1001,6 +1019,7 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct sk_buff *skb, | |||
1001 | * subsequent ASCONF Chunks. If found, proceed to rule D4. | 1019 | * subsequent ASCONF Chunks. If found, proceed to rule D4. |
1002 | */ | 1020 | */ |
1003 | static struct sctp_association *__sctp_rcv_asconf_lookup( | 1021 | static struct sctp_association *__sctp_rcv_asconf_lookup( |
1022 | struct net *net, | ||
1004 | sctp_chunkhdr_t *ch, | 1023 | sctp_chunkhdr_t *ch, |
1005 | const union sctp_addr *laddr, | 1024 | const union sctp_addr *laddr, |
1006 | __be16 peer_port, | 1025 | __be16 peer_port, |
@@ -1020,7 +1039,7 @@ static struct sctp_association *__sctp_rcv_asconf_lookup( | |||
1020 | 1039 | ||
1021 | af->from_addr_param(&paddr, param, peer_port, 0); | 1040 | af->from_addr_param(&paddr, param, peer_port, 0); |
1022 | 1041 | ||
1023 | return __sctp_lookup_association(laddr, &paddr, transportp); | 1042 | return __sctp_lookup_association(net, laddr, &paddr, transportp); |
1024 | } | 1043 | } |
1025 | 1044 | ||
1026 | 1045 | ||
@@ -1033,7 +1052,8 @@ static struct sctp_association *__sctp_rcv_asconf_lookup( | |||
1033 | * This means that any chunks that can help us identify the association need | 1052 | * This means that any chunks that can help us identify the association need |
1034 | * to be looked at to find this association. | 1053 | * to be looked at to find this association. |
1035 | */ | 1054 | */ |
1036 | static struct sctp_association *__sctp_rcv_walk_lookup(struct sk_buff *skb, | 1055 | static struct sctp_association *__sctp_rcv_walk_lookup(struct net *net, |
1056 | struct sk_buff *skb, | ||
1037 | const union sctp_addr *laddr, | 1057 | const union sctp_addr *laddr, |
1038 | struct sctp_transport **transportp) | 1058 | struct sctp_transport **transportp) |
1039 | { | 1059 | { |
@@ -1074,8 +1094,9 @@ static struct sctp_association *__sctp_rcv_walk_lookup(struct sk_buff *skb, | |||
1074 | break; | 1094 | break; |
1075 | 1095 | ||
1076 | case SCTP_CID_ASCONF: | 1096 | case SCTP_CID_ASCONF: |
1077 | if (have_auth || sctp_addip_noauth) | 1097 | if (have_auth || net->sctp.addip_noauth) |
1078 | asoc = __sctp_rcv_asconf_lookup(ch, laddr, | 1098 | asoc = __sctp_rcv_asconf_lookup( |
1099 | net, ch, laddr, | ||
1079 | sctp_hdr(skb)->source, | 1100 | sctp_hdr(skb)->source, |
1080 | transportp); | 1101 | transportp); |
1081 | default: | 1102 | default: |
@@ -1098,7 +1119,8 @@ static struct sctp_association *__sctp_rcv_walk_lookup(struct sk_buff *skb, | |||
1098 | * include looking inside of INIT/INIT-ACK chunks or after the AUTH | 1119 | * include looking inside of INIT/INIT-ACK chunks or after the AUTH |
1099 | * chunks. | 1120 | * chunks. |
1100 | */ | 1121 | */ |
1101 | static struct sctp_association *__sctp_rcv_lookup_harder(struct sk_buff *skb, | 1122 | static struct sctp_association *__sctp_rcv_lookup_harder(struct net *net, |
1123 | struct sk_buff *skb, | ||
1102 | const union sctp_addr *laddr, | 1124 | const union sctp_addr *laddr, |
1103 | struct sctp_transport **transportp) | 1125 | struct sctp_transport **transportp) |
1104 | { | 1126 | { |
@@ -1118,11 +1140,11 @@ static struct sctp_association *__sctp_rcv_lookup_harder(struct sk_buff *skb, | |||
1118 | switch (ch->type) { | 1140 | switch (ch->type) { |
1119 | case SCTP_CID_INIT: | 1141 | case SCTP_CID_INIT: |
1120 | case SCTP_CID_INIT_ACK: | 1142 | case SCTP_CID_INIT_ACK: |
1121 | return __sctp_rcv_init_lookup(skb, laddr, transportp); | 1143 | return __sctp_rcv_init_lookup(net, skb, laddr, transportp); |
1122 | break; | 1144 | break; |
1123 | 1145 | ||
1124 | default: | 1146 | default: |
1125 | return __sctp_rcv_walk_lookup(skb, laddr, transportp); | 1147 | return __sctp_rcv_walk_lookup(net, skb, laddr, transportp); |
1126 | break; | 1148 | break; |
1127 | } | 1149 | } |
1128 | 1150 | ||
@@ -1131,21 +1153,22 @@ static struct sctp_association *__sctp_rcv_lookup_harder(struct sk_buff *skb, | |||
1131 | } | 1153 | } |
1132 | 1154 | ||
1133 | /* Lookup an association for an inbound skb. */ | 1155 | /* Lookup an association for an inbound skb. */ |
1134 | static struct sctp_association *__sctp_rcv_lookup(struct sk_buff *skb, | 1156 | static struct sctp_association *__sctp_rcv_lookup(struct net *net, |
1157 | struct sk_buff *skb, | ||
1135 | const union sctp_addr *paddr, | 1158 | const union sctp_addr *paddr, |
1136 | const union sctp_addr *laddr, | 1159 | const union sctp_addr *laddr, |
1137 | struct sctp_transport **transportp) | 1160 | struct sctp_transport **transportp) |
1138 | { | 1161 | { |
1139 | struct sctp_association *asoc; | 1162 | struct sctp_association *asoc; |
1140 | 1163 | ||
1141 | asoc = __sctp_lookup_association(laddr, paddr, transportp); | 1164 | asoc = __sctp_lookup_association(net, laddr, paddr, transportp); |
1142 | 1165 | ||
1143 | /* Further lookup for INIT/INIT-ACK packets. | 1166 | /* Further lookup for INIT/INIT-ACK packets. |
1144 | * SCTP Implementors Guide, 2.18 Handling of address | 1167 | * SCTP Implementors Guide, 2.18 Handling of address |
1145 | * parameters within the INIT or INIT-ACK. | 1168 | * parameters within the INIT or INIT-ACK. |
1146 | */ | 1169 | */ |
1147 | if (!asoc) | 1170 | if (!asoc) |
1148 | asoc = __sctp_rcv_lookup_harder(skb, laddr, transportp); | 1171 | asoc = __sctp_rcv_lookup_harder(net, skb, laddr, transportp); |
1149 | 1172 | ||
1150 | return asoc; | 1173 | return asoc; |
1151 | } | 1174 | } |
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index ed7139ea7978..ea14cb445295 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -99,6 +99,7 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev, | |||
99 | struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr; | 99 | struct inet6_ifaddr *ifa = (struct inet6_ifaddr *)ptr; |
100 | struct sctp_sockaddr_entry *addr = NULL; | 100 | struct sctp_sockaddr_entry *addr = NULL; |
101 | struct sctp_sockaddr_entry *temp; | 101 | struct sctp_sockaddr_entry *temp; |
102 | struct net *net = dev_net(ifa->idev->dev); | ||
102 | int found = 0; | 103 | int found = 0; |
103 | 104 | ||
104 | switch (ev) { | 105 | switch (ev) { |
@@ -110,27 +111,27 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev, | |||
110 | addr->a.v6.sin6_addr = ifa->addr; | 111 | addr->a.v6.sin6_addr = ifa->addr; |
111 | addr->a.v6.sin6_scope_id = ifa->idev->dev->ifindex; | 112 | addr->a.v6.sin6_scope_id = ifa->idev->dev->ifindex; |
112 | addr->valid = 1; | 113 | addr->valid = 1; |
113 | spin_lock_bh(&sctp_local_addr_lock); | 114 | spin_lock_bh(&net->sctp.local_addr_lock); |
114 | list_add_tail_rcu(&addr->list, &sctp_local_addr_list); | 115 | list_add_tail_rcu(&addr->list, &net->sctp.local_addr_list); |
115 | sctp_addr_wq_mgmt(addr, SCTP_ADDR_NEW); | 116 | sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_NEW); |
116 | spin_unlock_bh(&sctp_local_addr_lock); | 117 | spin_unlock_bh(&net->sctp.local_addr_lock); |
117 | } | 118 | } |
118 | break; | 119 | break; |
119 | case NETDEV_DOWN: | 120 | case NETDEV_DOWN: |
120 | spin_lock_bh(&sctp_local_addr_lock); | 121 | spin_lock_bh(&net->sctp.local_addr_lock); |
121 | list_for_each_entry_safe(addr, temp, | 122 | list_for_each_entry_safe(addr, temp, |
122 | &sctp_local_addr_list, list) { | 123 | &net->sctp.local_addr_list, list) { |
123 | if (addr->a.sa.sa_family == AF_INET6 && | 124 | if (addr->a.sa.sa_family == AF_INET6 && |
124 | ipv6_addr_equal(&addr->a.v6.sin6_addr, | 125 | ipv6_addr_equal(&addr->a.v6.sin6_addr, |
125 | &ifa->addr)) { | 126 | &ifa->addr)) { |
126 | sctp_addr_wq_mgmt(addr, SCTP_ADDR_DEL); | 127 | sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_DEL); |
127 | found = 1; | 128 | found = 1; |
128 | addr->valid = 0; | 129 | addr->valid = 0; |
129 | list_del_rcu(&addr->list); | 130 | list_del_rcu(&addr->list); |
130 | break; | 131 | break; |
131 | } | 132 | } |
132 | } | 133 | } |
133 | spin_unlock_bh(&sctp_local_addr_lock); | 134 | spin_unlock_bh(&net->sctp.local_addr_lock); |
134 | if (found) | 135 | if (found) |
135 | kfree_rcu(addr, rcu); | 136 | kfree_rcu(addr, rcu); |
136 | break; | 137 | break; |
@@ -154,6 +155,7 @@ SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
154 | struct ipv6_pinfo *np; | 155 | struct ipv6_pinfo *np; |
155 | sk_buff_data_t saveip, savesctp; | 156 | sk_buff_data_t saveip, savesctp; |
156 | int err; | 157 | int err; |
158 | struct net *net = dev_net(skb->dev); | ||
157 | 159 | ||
158 | idev = in6_dev_get(skb->dev); | 160 | idev = in6_dev_get(skb->dev); |
159 | 161 | ||
@@ -162,12 +164,12 @@ SCTP_STATIC void sctp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
162 | savesctp = skb->transport_header; | 164 | savesctp = skb->transport_header; |
163 | skb_reset_network_header(skb); | 165 | skb_reset_network_header(skb); |
164 | skb_set_transport_header(skb, offset); | 166 | skb_set_transport_header(skb, offset); |
165 | sk = sctp_err_lookup(AF_INET6, skb, sctp_hdr(skb), &asoc, &transport); | 167 | sk = sctp_err_lookup(net, AF_INET6, skb, sctp_hdr(skb), &asoc, &transport); |
166 | /* Put back, the original pointers. */ | 168 | /* Put back, the original pointers. */ |
167 | skb->network_header = saveip; | 169 | skb->network_header = saveip; |
168 | skb->transport_header = savesctp; | 170 | skb->transport_header = savesctp; |
169 | if (!sk) { | 171 | if (!sk) { |
170 | ICMP6_INC_STATS_BH(dev_net(skb->dev), idev, ICMP6_MIB_INERRORS); | 172 | ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_INERRORS); |
171 | goto out; | 173 | goto out; |
172 | } | 174 | } |
173 | 175 | ||
@@ -241,7 +243,7 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport) | |||
241 | __func__, skb, skb->len, | 243 | __func__, skb, skb->len, |
242 | &fl6.saddr, &fl6.daddr); | 244 | &fl6.saddr, &fl6.daddr); |
243 | 245 | ||
244 | SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS); | 246 | SCTP_INC_STATS(sock_net(sk), SCTP_MIB_OUTSCTPPACKS); |
245 | 247 | ||
246 | if (!(transport->param_flags & SPP_PMTUD_ENABLE)) | 248 | if (!(transport->param_flags & SPP_PMTUD_ENABLE)) |
247 | skb->local_df = 1; | 249 | skb->local_df = 1; |
@@ -580,7 +582,7 @@ static int sctp_v6_available(union sctp_addr *addr, struct sctp_sock *sp) | |||
580 | if (!(type & IPV6_ADDR_UNICAST)) | 582 | if (!(type & IPV6_ADDR_UNICAST)) |
581 | return 0; | 583 | return 0; |
582 | 584 | ||
583 | return ipv6_chk_addr(&init_net, in6, NULL, 0); | 585 | return ipv6_chk_addr(sock_net(&sp->inet.sk), in6, NULL, 0); |
584 | } | 586 | } |
585 | 587 | ||
586 | /* This function checks if the address is a valid address to be used for | 588 | /* This function checks if the address is a valid address to be used for |
@@ -857,14 +859,14 @@ static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr) | |||
857 | struct net_device *dev; | 859 | struct net_device *dev; |
858 | 860 | ||
859 | if (type & IPV6_ADDR_LINKLOCAL) { | 861 | if (type & IPV6_ADDR_LINKLOCAL) { |
862 | struct net *net; | ||
860 | if (!addr->v6.sin6_scope_id) | 863 | if (!addr->v6.sin6_scope_id) |
861 | return 0; | 864 | return 0; |
865 | net = sock_net(&opt->inet.sk); | ||
862 | rcu_read_lock(); | 866 | rcu_read_lock(); |
863 | dev = dev_get_by_index_rcu(&init_net, | 867 | dev = dev_get_by_index_rcu(net, addr->v6.sin6_scope_id); |
864 | addr->v6.sin6_scope_id); | ||
865 | if (!dev || | 868 | if (!dev || |
866 | !ipv6_chk_addr(&init_net, &addr->v6.sin6_addr, | 869 | !ipv6_chk_addr(net, &addr->v6.sin6_addr, dev, 0)) { |
867 | dev, 0)) { | ||
868 | rcu_read_unlock(); | 870 | rcu_read_unlock(); |
869 | return 0; | 871 | return 0; |
870 | } | 872 | } |
@@ -897,7 +899,7 @@ static int sctp_inet6_send_verify(struct sctp_sock *opt, union sctp_addr *addr) | |||
897 | if (!addr->v6.sin6_scope_id) | 899 | if (!addr->v6.sin6_scope_id) |
898 | return 0; | 900 | return 0; |
899 | rcu_read_lock(); | 901 | rcu_read_lock(); |
900 | dev = dev_get_by_index_rcu(&init_net, | 902 | dev = dev_get_by_index_rcu(sock_net(&opt->inet.sk), |
901 | addr->v6.sin6_scope_id); | 903 | addr->v6.sin6_scope_id); |
902 | rcu_read_unlock(); | 904 | rcu_read_unlock(); |
903 | if (!dev) | 905 | if (!dev) |
diff --git a/net/sctp/objcnt.c b/net/sctp/objcnt.c index 8ef8e7d9eb61..fe012c44f8df 100644 --- a/net/sctp/objcnt.c +++ b/net/sctp/objcnt.c | |||
@@ -129,20 +129,20 @@ static const struct file_operations sctp_objcnt_ops = { | |||
129 | }; | 129 | }; |
130 | 130 | ||
131 | /* Initialize the objcount in the proc filesystem. */ | 131 | /* Initialize the objcount in the proc filesystem. */ |
132 | void sctp_dbg_objcnt_init(void) | 132 | void sctp_dbg_objcnt_init(struct net *net) |
133 | { | 133 | { |
134 | struct proc_dir_entry *ent; | 134 | struct proc_dir_entry *ent; |
135 | 135 | ||
136 | ent = proc_create("sctp_dbg_objcnt", 0, | 136 | ent = proc_create("sctp_dbg_objcnt", 0, |
137 | proc_net_sctp, &sctp_objcnt_ops); | 137 | net->sctp.proc_net_sctp, &sctp_objcnt_ops); |
138 | if (!ent) | 138 | if (!ent) |
139 | pr_warn("sctp_dbg_objcnt: Unable to create /proc entry.\n"); | 139 | pr_warn("sctp_dbg_objcnt: Unable to create /proc entry.\n"); |
140 | } | 140 | } |
141 | 141 | ||
142 | /* Cleanup the objcount entry in the proc filesystem. */ | 142 | /* Cleanup the objcount entry in the proc filesystem. */ |
143 | void sctp_dbg_objcnt_exit(void) | 143 | void sctp_dbg_objcnt_exit(struct net *net) |
144 | { | 144 | { |
145 | remove_proc_entry("sctp_dbg_objcnt", proc_net_sctp); | 145 | remove_proc_entry("sctp_dbg_objcnt", net->sctp.proc_net_sctp); |
146 | } | 146 | } |
147 | 147 | ||
148 | 148 | ||
diff --git a/net/sctp/output.c b/net/sctp/output.c index 838e18b4d7ea..0c6359bb973c 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c | |||
@@ -597,7 +597,7 @@ out: | |||
597 | return err; | 597 | return err; |
598 | no_route: | 598 | no_route: |
599 | kfree_skb(nskb); | 599 | kfree_skb(nskb); |
600 | IP_INC_STATS_BH(&init_net, IPSTATS_MIB_OUTNOROUTES); | 600 | IP_INC_STATS_BH(sock_net(asoc->base.sk), IPSTATS_MIB_OUTNOROUTES); |
601 | 601 | ||
602 | /* FIXME: Returning the 'err' will effect all the associations | 602 | /* FIXME: Returning the 'err' will effect all the associations |
603 | * associated with a socket, although only one of the paths of the | 603 | * associated with a socket, although only one of the paths of the |
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index e7aa177c9522..d16632e1503a 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
@@ -299,6 +299,7 @@ void sctp_outq_free(struct sctp_outq *q) | |||
299 | /* Put a new chunk in an sctp_outq. */ | 299 | /* Put a new chunk in an sctp_outq. */ |
300 | int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk) | 300 | int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk) |
301 | { | 301 | { |
302 | struct net *net = sock_net(q->asoc->base.sk); | ||
302 | int error = 0; | 303 | int error = 0; |
303 | 304 | ||
304 | SCTP_DEBUG_PRINTK("sctp_outq_tail(%p, %p[%s])\n", | 305 | SCTP_DEBUG_PRINTK("sctp_outq_tail(%p, %p[%s])\n", |
@@ -337,15 +338,15 @@ int sctp_outq_tail(struct sctp_outq *q, struct sctp_chunk *chunk) | |||
337 | 338 | ||
338 | sctp_outq_tail_data(q, chunk); | 339 | sctp_outq_tail_data(q, chunk); |
339 | if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) | 340 | if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) |
340 | SCTP_INC_STATS(SCTP_MIB_OUTUNORDERCHUNKS); | 341 | SCTP_INC_STATS(net, SCTP_MIB_OUTUNORDERCHUNKS); |
341 | else | 342 | else |
342 | SCTP_INC_STATS(SCTP_MIB_OUTORDERCHUNKS); | 343 | SCTP_INC_STATS(net, SCTP_MIB_OUTORDERCHUNKS); |
343 | q->empty = 0; | 344 | q->empty = 0; |
344 | break; | 345 | break; |
345 | } | 346 | } |
346 | } else { | 347 | } else { |
347 | list_add_tail(&chunk->list, &q->control_chunk_list); | 348 | list_add_tail(&chunk->list, &q->control_chunk_list); |
348 | SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); | 349 | SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); |
349 | } | 350 | } |
350 | 351 | ||
351 | if (error < 0) | 352 | if (error < 0) |
@@ -478,11 +479,12 @@ void sctp_retransmit_mark(struct sctp_outq *q, | |||
478 | void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport, | 479 | void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport, |
479 | sctp_retransmit_reason_t reason) | 480 | sctp_retransmit_reason_t reason) |
480 | { | 481 | { |
482 | struct net *net = sock_net(q->asoc->base.sk); | ||
481 | int error = 0; | 483 | int error = 0; |
482 | 484 | ||
483 | switch(reason) { | 485 | switch(reason) { |
484 | case SCTP_RTXR_T3_RTX: | 486 | case SCTP_RTXR_T3_RTX: |
485 | SCTP_INC_STATS(SCTP_MIB_T3_RETRANSMITS); | 487 | SCTP_INC_STATS(net, SCTP_MIB_T3_RETRANSMITS); |
486 | sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_T3_RTX); | 488 | sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_T3_RTX); |
487 | /* Update the retran path if the T3-rtx timer has expired for | 489 | /* Update the retran path if the T3-rtx timer has expired for |
488 | * the current retran path. | 490 | * the current retran path. |
@@ -493,15 +495,15 @@ void sctp_retransmit(struct sctp_outq *q, struct sctp_transport *transport, | |||
493 | transport->asoc->unack_data; | 495 | transport->asoc->unack_data; |
494 | break; | 496 | break; |
495 | case SCTP_RTXR_FAST_RTX: | 497 | case SCTP_RTXR_FAST_RTX: |
496 | SCTP_INC_STATS(SCTP_MIB_FAST_RETRANSMITS); | 498 | SCTP_INC_STATS(net, SCTP_MIB_FAST_RETRANSMITS); |
497 | sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_FAST_RTX); | 499 | sctp_transport_lower_cwnd(transport, SCTP_LOWER_CWND_FAST_RTX); |
498 | q->fast_rtx = 1; | 500 | q->fast_rtx = 1; |
499 | break; | 501 | break; |
500 | case SCTP_RTXR_PMTUD: | 502 | case SCTP_RTXR_PMTUD: |
501 | SCTP_INC_STATS(SCTP_MIB_PMTUD_RETRANSMITS); | 503 | SCTP_INC_STATS(net, SCTP_MIB_PMTUD_RETRANSMITS); |
502 | break; | 504 | break; |
503 | case SCTP_RTXR_T1_RTX: | 505 | case SCTP_RTXR_T1_RTX: |
504 | SCTP_INC_STATS(SCTP_MIB_T1_RETRANSMITS); | 506 | SCTP_INC_STATS(net, SCTP_MIB_T1_RETRANSMITS); |
505 | transport->asoc->init_retries++; | 507 | transport->asoc->init_retries++; |
506 | break; | 508 | break; |
507 | default: | 509 | default: |
@@ -589,9 +591,8 @@ static int sctp_outq_flush_rtx(struct sctp_outq *q, struct sctp_packet *pkt, | |||
589 | * next chunk. | 591 | * next chunk. |
590 | */ | 592 | */ |
591 | if (chunk->tsn_gap_acked) { | 593 | if (chunk->tsn_gap_acked) { |
592 | list_del(&chunk->transmitted_list); | 594 | list_move_tail(&chunk->transmitted_list, |
593 | list_add_tail(&chunk->transmitted_list, | 595 | &transport->transmitted); |
594 | &transport->transmitted); | ||
595 | continue; | 596 | continue; |
596 | } | 597 | } |
597 | 598 | ||
@@ -655,9 +656,8 @@ redo: | |||
655 | /* The append was successful, so add this chunk to | 656 | /* The append was successful, so add this chunk to |
656 | * the transmitted list. | 657 | * the transmitted list. |
657 | */ | 658 | */ |
658 | list_del(&chunk->transmitted_list); | 659 | list_move_tail(&chunk->transmitted_list, |
659 | list_add_tail(&chunk->transmitted_list, | 660 | &transport->transmitted); |
660 | &transport->transmitted); | ||
661 | 661 | ||
662 | /* Mark the chunk as ineligible for fast retransmit | 662 | /* Mark the chunk as ineligible for fast retransmit |
663 | * after it is retransmitted. | 663 | * after it is retransmitted. |
@@ -1914,6 +1914,6 @@ static void sctp_generate_fwdtsn(struct sctp_outq *q, __u32 ctsn) | |||
1914 | 1914 | ||
1915 | if (ftsn_chunk) { | 1915 | if (ftsn_chunk) { |
1916 | list_add_tail(&ftsn_chunk->list, &q->control_chunk_list); | 1916 | list_add_tail(&ftsn_chunk->list, &q->control_chunk_list); |
1917 | SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); | 1917 | SCTP_INC_STATS(sock_net(asoc->base.sk), SCTP_MIB_OUTCTRLCHUNKS); |
1918 | } | 1918 | } |
1919 | } | 1919 | } |
diff --git a/net/sctp/primitive.c b/net/sctp/primitive.c index 534c7eae9d15..794bb14decde 100644 --- a/net/sctp/primitive.c +++ b/net/sctp/primitive.c | |||
@@ -57,7 +57,7 @@ | |||
57 | 57 | ||
58 | #define DECLARE_PRIMITIVE(name) \ | 58 | #define DECLARE_PRIMITIVE(name) \ |
59 | /* This is called in the code as sctp_primitive_ ## name. */ \ | 59 | /* This is called in the code as sctp_primitive_ ## name. */ \ |
60 | int sctp_primitive_ ## name(struct sctp_association *asoc, \ | 60 | int sctp_primitive_ ## name(struct net *net, struct sctp_association *asoc, \ |
61 | void *arg) { \ | 61 | void *arg) { \ |
62 | int error = 0; \ | 62 | int error = 0; \ |
63 | sctp_event_t event_type; sctp_subtype_t subtype; \ | 63 | sctp_event_t event_type; sctp_subtype_t subtype; \ |
@@ -69,7 +69,7 @@ int sctp_primitive_ ## name(struct sctp_association *asoc, \ | |||
69 | state = asoc ? asoc->state : SCTP_STATE_CLOSED; \ | 69 | state = asoc ? asoc->state : SCTP_STATE_CLOSED; \ |
70 | ep = asoc ? asoc->ep : NULL; \ | 70 | ep = asoc ? asoc->ep : NULL; \ |
71 | \ | 71 | \ |
72 | error = sctp_do_sm(event_type, subtype, state, ep, asoc, \ | 72 | error = sctp_do_sm(net, event_type, subtype, state, ep, asoc, \ |
73 | arg, GFP_KERNEL); \ | 73 | arg, GFP_KERNEL); \ |
74 | return error; \ | 74 | return error; \ |
75 | } | 75 | } |
diff --git a/net/sctp/proc.c b/net/sctp/proc.c index 1e2eee88c3ea..c3bea269faf4 100644 --- a/net/sctp/proc.c +++ b/net/sctp/proc.c | |||
@@ -80,11 +80,12 @@ static const struct snmp_mib sctp_snmp_list[] = { | |||
80 | /* Display sctp snmp mib statistics(/proc/net/sctp/snmp). */ | 80 | /* Display sctp snmp mib statistics(/proc/net/sctp/snmp). */ |
81 | static int sctp_snmp_seq_show(struct seq_file *seq, void *v) | 81 | static int sctp_snmp_seq_show(struct seq_file *seq, void *v) |
82 | { | 82 | { |
83 | struct net *net = seq->private; | ||
83 | int i; | 84 | int i; |
84 | 85 | ||
85 | for (i = 0; sctp_snmp_list[i].name != NULL; i++) | 86 | for (i = 0; sctp_snmp_list[i].name != NULL; i++) |
86 | seq_printf(seq, "%-32s\t%ld\n", sctp_snmp_list[i].name, | 87 | seq_printf(seq, "%-32s\t%ld\n", sctp_snmp_list[i].name, |
87 | snmp_fold_field((void __percpu **)sctp_statistics, | 88 | snmp_fold_field((void __percpu **)net->sctp.sctp_statistics, |
88 | sctp_snmp_list[i].entry)); | 89 | sctp_snmp_list[i].entry)); |
89 | 90 | ||
90 | return 0; | 91 | return 0; |
@@ -93,7 +94,7 @@ static int sctp_snmp_seq_show(struct seq_file *seq, void *v) | |||
93 | /* Initialize the seq file operations for 'snmp' object. */ | 94 | /* Initialize the seq file operations for 'snmp' object. */ |
94 | static int sctp_snmp_seq_open(struct inode *inode, struct file *file) | 95 | static int sctp_snmp_seq_open(struct inode *inode, struct file *file) |
95 | { | 96 | { |
96 | return single_open(file, sctp_snmp_seq_show, NULL); | 97 | return single_open_net(inode, file, sctp_snmp_seq_show); |
97 | } | 98 | } |
98 | 99 | ||
99 | static const struct file_operations sctp_snmp_seq_fops = { | 100 | static const struct file_operations sctp_snmp_seq_fops = { |
@@ -105,11 +106,12 @@ static const struct file_operations sctp_snmp_seq_fops = { | |||
105 | }; | 106 | }; |
106 | 107 | ||
107 | /* Set up the proc fs entry for 'snmp' object. */ | 108 | /* Set up the proc fs entry for 'snmp' object. */ |
108 | int __init sctp_snmp_proc_init(void) | 109 | int __net_init sctp_snmp_proc_init(struct net *net) |
109 | { | 110 | { |
110 | struct proc_dir_entry *p; | 111 | struct proc_dir_entry *p; |
111 | 112 | ||
112 | p = proc_create("snmp", S_IRUGO, proc_net_sctp, &sctp_snmp_seq_fops); | 113 | p = proc_create("snmp", S_IRUGO, net->sctp.proc_net_sctp, |
114 | &sctp_snmp_seq_fops); | ||
113 | if (!p) | 115 | if (!p) |
114 | return -ENOMEM; | 116 | return -ENOMEM; |
115 | 117 | ||
@@ -117,9 +119,9 @@ int __init sctp_snmp_proc_init(void) | |||
117 | } | 119 | } |
118 | 120 | ||
119 | /* Cleanup the proc fs entry for 'snmp' object. */ | 121 | /* Cleanup the proc fs entry for 'snmp' object. */ |
120 | void sctp_snmp_proc_exit(void) | 122 | void sctp_snmp_proc_exit(struct net *net) |
121 | { | 123 | { |
122 | remove_proc_entry("snmp", proc_net_sctp); | 124 | remove_proc_entry("snmp", net->sctp.proc_net_sctp); |
123 | } | 125 | } |
124 | 126 | ||
125 | /* Dump local addresses of an association/endpoint. */ | 127 | /* Dump local addresses of an association/endpoint. */ |
@@ -213,10 +215,13 @@ static int sctp_eps_seq_show(struct seq_file *seq, void *v) | |||
213 | sctp_for_each_hentry(epb, node, &head->chain) { | 215 | sctp_for_each_hentry(epb, node, &head->chain) { |
214 | ep = sctp_ep(epb); | 216 | ep = sctp_ep(epb); |
215 | sk = epb->sk; | 217 | sk = epb->sk; |
218 | if (!net_eq(sock_net(sk), seq_file_net(seq))) | ||
219 | continue; | ||
216 | seq_printf(seq, "%8pK %8pK %-3d %-3d %-4d %-5d %5d %5lu ", ep, sk, | 220 | seq_printf(seq, "%8pK %8pK %-3d %-3d %-4d %-5d %5d %5lu ", ep, sk, |
217 | sctp_sk(sk)->type, sk->sk_state, hash, | 221 | sctp_sk(sk)->type, sk->sk_state, hash, |
218 | epb->bind_addr.port, | 222 | epb->bind_addr.port, |
219 | sock_i_uid(sk), sock_i_ino(sk)); | 223 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)), |
224 | sock_i_ino(sk)); | ||
220 | 225 | ||
221 | sctp_seq_dump_local_addrs(seq, epb); | 226 | sctp_seq_dump_local_addrs(seq, epb); |
222 | seq_printf(seq, "\n"); | 227 | seq_printf(seq, "\n"); |
@@ -238,7 +243,8 @@ static const struct seq_operations sctp_eps_ops = { | |||
238 | /* Initialize the seq file operations for 'eps' object. */ | 243 | /* Initialize the seq file operations for 'eps' object. */ |
239 | static int sctp_eps_seq_open(struct inode *inode, struct file *file) | 244 | static int sctp_eps_seq_open(struct inode *inode, struct file *file) |
240 | { | 245 | { |
241 | return seq_open(file, &sctp_eps_ops); | 246 | return seq_open_net(inode, file, &sctp_eps_ops, |
247 | sizeof(struct seq_net_private)); | ||
242 | } | 248 | } |
243 | 249 | ||
244 | static const struct file_operations sctp_eps_seq_fops = { | 250 | static const struct file_operations sctp_eps_seq_fops = { |
@@ -249,11 +255,12 @@ static const struct file_operations sctp_eps_seq_fops = { | |||
249 | }; | 255 | }; |
250 | 256 | ||
251 | /* Set up the proc fs entry for 'eps' object. */ | 257 | /* Set up the proc fs entry for 'eps' object. */ |
252 | int __init sctp_eps_proc_init(void) | 258 | int __net_init sctp_eps_proc_init(struct net *net) |
253 | { | 259 | { |
254 | struct proc_dir_entry *p; | 260 | struct proc_dir_entry *p; |
255 | 261 | ||
256 | p = proc_create("eps", S_IRUGO, proc_net_sctp, &sctp_eps_seq_fops); | 262 | p = proc_create("eps", S_IRUGO, net->sctp.proc_net_sctp, |
263 | &sctp_eps_seq_fops); | ||
257 | if (!p) | 264 | if (!p) |
258 | return -ENOMEM; | 265 | return -ENOMEM; |
259 | 266 | ||
@@ -261,9 +268,9 @@ int __init sctp_eps_proc_init(void) | |||
261 | } | 268 | } |
262 | 269 | ||
263 | /* Cleanup the proc fs entry for 'eps' object. */ | 270 | /* Cleanup the proc fs entry for 'eps' object. */ |
264 | void sctp_eps_proc_exit(void) | 271 | void sctp_eps_proc_exit(struct net *net) |
265 | { | 272 | { |
266 | remove_proc_entry("eps", proc_net_sctp); | 273 | remove_proc_entry("eps", net->sctp.proc_net_sctp); |
267 | } | 274 | } |
268 | 275 | ||
269 | 276 | ||
@@ -316,6 +323,8 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v) | |||
316 | sctp_for_each_hentry(epb, node, &head->chain) { | 323 | sctp_for_each_hentry(epb, node, &head->chain) { |
317 | assoc = sctp_assoc(epb); | 324 | assoc = sctp_assoc(epb); |
318 | sk = epb->sk; | 325 | sk = epb->sk; |
326 | if (!net_eq(sock_net(sk), seq_file_net(seq))) | ||
327 | continue; | ||
319 | seq_printf(seq, | 328 | seq_printf(seq, |
320 | "%8pK %8pK %-3d %-3d %-2d %-4d " | 329 | "%8pK %8pK %-3d %-3d %-2d %-4d " |
321 | "%4d %8d %8d %7d %5lu %-5d %5d ", | 330 | "%4d %8d %8d %7d %5lu %-5d %5d ", |
@@ -324,7 +333,8 @@ static int sctp_assocs_seq_show(struct seq_file *seq, void *v) | |||
324 | assoc->assoc_id, | 333 | assoc->assoc_id, |
325 | assoc->sndbuf_used, | 334 | assoc->sndbuf_used, |
326 | atomic_read(&assoc->rmem_alloc), | 335 | atomic_read(&assoc->rmem_alloc), |
327 | sock_i_uid(sk), sock_i_ino(sk), | 336 | from_kuid_munged(seq_user_ns(seq), sock_i_uid(sk)), |
337 | sock_i_ino(sk), | ||
328 | epb->bind_addr.port, | 338 | epb->bind_addr.port, |
329 | assoc->peer.port); | 339 | assoc->peer.port); |
330 | seq_printf(seq, " "); | 340 | seq_printf(seq, " "); |
@@ -354,7 +364,8 @@ static const struct seq_operations sctp_assoc_ops = { | |||
354 | /* Initialize the seq file operations for 'assocs' object. */ | 364 | /* Initialize the seq file operations for 'assocs' object. */ |
355 | static int sctp_assocs_seq_open(struct inode *inode, struct file *file) | 365 | static int sctp_assocs_seq_open(struct inode *inode, struct file *file) |
356 | { | 366 | { |
357 | return seq_open(file, &sctp_assoc_ops); | 367 | return seq_open_net(inode, file, &sctp_assoc_ops, |
368 | sizeof(struct seq_net_private)); | ||
358 | } | 369 | } |
359 | 370 | ||
360 | static const struct file_operations sctp_assocs_seq_fops = { | 371 | static const struct file_operations sctp_assocs_seq_fops = { |
@@ -365,11 +376,11 @@ static const struct file_operations sctp_assocs_seq_fops = { | |||
365 | }; | 376 | }; |
366 | 377 | ||
367 | /* Set up the proc fs entry for 'assocs' object. */ | 378 | /* Set up the proc fs entry for 'assocs' object. */ |
368 | int __init sctp_assocs_proc_init(void) | 379 | int __net_init sctp_assocs_proc_init(struct net *net) |
369 | { | 380 | { |
370 | struct proc_dir_entry *p; | 381 | struct proc_dir_entry *p; |
371 | 382 | ||
372 | p = proc_create("assocs", S_IRUGO, proc_net_sctp, | 383 | p = proc_create("assocs", S_IRUGO, net->sctp.proc_net_sctp, |
373 | &sctp_assocs_seq_fops); | 384 | &sctp_assocs_seq_fops); |
374 | if (!p) | 385 | if (!p) |
375 | return -ENOMEM; | 386 | return -ENOMEM; |
@@ -378,9 +389,9 @@ int __init sctp_assocs_proc_init(void) | |||
378 | } | 389 | } |
379 | 390 | ||
380 | /* Cleanup the proc fs entry for 'assocs' object. */ | 391 | /* Cleanup the proc fs entry for 'assocs' object. */ |
381 | void sctp_assocs_proc_exit(void) | 392 | void sctp_assocs_proc_exit(struct net *net) |
382 | { | 393 | { |
383 | remove_proc_entry("assocs", proc_net_sctp); | 394 | remove_proc_entry("assocs", net->sctp.proc_net_sctp); |
384 | } | 395 | } |
385 | 396 | ||
386 | static void *sctp_remaddr_seq_start(struct seq_file *seq, loff_t *pos) | 397 | static void *sctp_remaddr_seq_start(struct seq_file *seq, loff_t *pos) |
@@ -426,6 +437,8 @@ static int sctp_remaddr_seq_show(struct seq_file *seq, void *v) | |||
426 | sctp_local_bh_disable(); | 437 | sctp_local_bh_disable(); |
427 | read_lock(&head->lock); | 438 | read_lock(&head->lock); |
428 | sctp_for_each_hentry(epb, node, &head->chain) { | 439 | sctp_for_each_hentry(epb, node, &head->chain) { |
440 | if (!net_eq(sock_net(epb->sk), seq_file_net(seq))) | ||
441 | continue; | ||
429 | assoc = sctp_assoc(epb); | 442 | assoc = sctp_assoc(epb); |
430 | list_for_each_entry(tsp, &assoc->peer.transport_addr_list, | 443 | list_for_each_entry(tsp, &assoc->peer.transport_addr_list, |
431 | transports) { | 444 | transports) { |
@@ -489,14 +502,15 @@ static const struct seq_operations sctp_remaddr_ops = { | |||
489 | }; | 502 | }; |
490 | 503 | ||
491 | /* Cleanup the proc fs entry for 'remaddr' object. */ | 504 | /* Cleanup the proc fs entry for 'remaddr' object. */ |
492 | void sctp_remaddr_proc_exit(void) | 505 | void sctp_remaddr_proc_exit(struct net *net) |
493 | { | 506 | { |
494 | remove_proc_entry("remaddr", proc_net_sctp); | 507 | remove_proc_entry("remaddr", net->sctp.proc_net_sctp); |
495 | } | 508 | } |
496 | 509 | ||
497 | static int sctp_remaddr_seq_open(struct inode *inode, struct file *file) | 510 | static int sctp_remaddr_seq_open(struct inode *inode, struct file *file) |
498 | { | 511 | { |
499 | return seq_open(file, &sctp_remaddr_ops); | 512 | return seq_open_net(inode, file, &sctp_remaddr_ops, |
513 | sizeof(struct seq_net_private)); | ||
500 | } | 514 | } |
501 | 515 | ||
502 | static const struct file_operations sctp_remaddr_seq_fops = { | 516 | static const struct file_operations sctp_remaddr_seq_fops = { |
@@ -506,11 +520,12 @@ static const struct file_operations sctp_remaddr_seq_fops = { | |||
506 | .release = seq_release, | 520 | .release = seq_release, |
507 | }; | 521 | }; |
508 | 522 | ||
509 | int __init sctp_remaddr_proc_init(void) | 523 | int __net_init sctp_remaddr_proc_init(struct net *net) |
510 | { | 524 | { |
511 | struct proc_dir_entry *p; | 525 | struct proc_dir_entry *p; |
512 | 526 | ||
513 | p = proc_create("remaddr", S_IRUGO, proc_net_sctp, &sctp_remaddr_seq_fops); | 527 | p = proc_create("remaddr", S_IRUGO, net->sctp.proc_net_sctp, |
528 | &sctp_remaddr_seq_fops); | ||
514 | if (!p) | 529 | if (!p) |
515 | return -ENOMEM; | 530 | return -ENOMEM; |
516 | return 0; | 531 | return 0; |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 1f89c4e69645..2d518425d598 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -69,21 +69,10 @@ | |||
69 | 69 | ||
70 | /* Global data structures. */ | 70 | /* Global data structures. */ |
71 | struct sctp_globals sctp_globals __read_mostly; | 71 | struct sctp_globals sctp_globals __read_mostly; |
72 | DEFINE_SNMP_STAT(struct sctp_mib, sctp_statistics) __read_mostly; | ||
73 | |||
74 | #ifdef CONFIG_PROC_FS | ||
75 | struct proc_dir_entry *proc_net_sctp; | ||
76 | #endif | ||
77 | 72 | ||
78 | struct idr sctp_assocs_id; | 73 | struct idr sctp_assocs_id; |
79 | DEFINE_SPINLOCK(sctp_assocs_id_lock); | 74 | DEFINE_SPINLOCK(sctp_assocs_id_lock); |
80 | 75 | ||
81 | /* This is the global socket data structure used for responding to | ||
82 | * the Out-of-the-blue (OOTB) packets. A control sock will be created | ||
83 | * for this socket at the initialization time. | ||
84 | */ | ||
85 | static struct sock *sctp_ctl_sock; | ||
86 | |||
87 | static struct sctp_pf *sctp_pf_inet6_specific; | 76 | static struct sctp_pf *sctp_pf_inet6_specific; |
88 | static struct sctp_pf *sctp_pf_inet_specific; | 77 | static struct sctp_pf *sctp_pf_inet_specific; |
89 | static struct sctp_af *sctp_af_v4_specific; | 78 | static struct sctp_af *sctp_af_v4_specific; |
@@ -96,74 +85,54 @@ long sysctl_sctp_mem[3]; | |||
96 | int sysctl_sctp_rmem[3]; | 85 | int sysctl_sctp_rmem[3]; |
97 | int sysctl_sctp_wmem[3]; | 86 | int sysctl_sctp_wmem[3]; |
98 | 87 | ||
99 | /* Return the address of the control sock. */ | ||
100 | struct sock *sctp_get_ctl_sock(void) | ||
101 | { | ||
102 | return sctp_ctl_sock; | ||
103 | } | ||
104 | |||
105 | /* Set up the proc fs entry for the SCTP protocol. */ | 88 | /* Set up the proc fs entry for the SCTP protocol. */ |
106 | static __init int sctp_proc_init(void) | 89 | static __net_init int sctp_proc_init(struct net *net) |
107 | { | 90 | { |
108 | if (percpu_counter_init(&sctp_sockets_allocated, 0)) | ||
109 | goto out_nomem; | ||
110 | #ifdef CONFIG_PROC_FS | 91 | #ifdef CONFIG_PROC_FS |
111 | if (!proc_net_sctp) { | 92 | net->sctp.proc_net_sctp = proc_net_mkdir(net, "sctp", net->proc_net); |
112 | proc_net_sctp = proc_mkdir("sctp", init_net.proc_net); | 93 | if (!net->sctp.proc_net_sctp) |
113 | if (!proc_net_sctp) | 94 | goto out_proc_net_sctp; |
114 | goto out_free_percpu; | 95 | if (sctp_snmp_proc_init(net)) |
115 | } | ||
116 | |||
117 | if (sctp_snmp_proc_init()) | ||
118 | goto out_snmp_proc_init; | 96 | goto out_snmp_proc_init; |
119 | if (sctp_eps_proc_init()) | 97 | if (sctp_eps_proc_init(net)) |
120 | goto out_eps_proc_init; | 98 | goto out_eps_proc_init; |
121 | if (sctp_assocs_proc_init()) | 99 | if (sctp_assocs_proc_init(net)) |
122 | goto out_assocs_proc_init; | 100 | goto out_assocs_proc_init; |
123 | if (sctp_remaddr_proc_init()) | 101 | if (sctp_remaddr_proc_init(net)) |
124 | goto out_remaddr_proc_init; | 102 | goto out_remaddr_proc_init; |
125 | 103 | ||
126 | return 0; | 104 | return 0; |
127 | 105 | ||
128 | out_remaddr_proc_init: | 106 | out_remaddr_proc_init: |
129 | sctp_assocs_proc_exit(); | 107 | sctp_assocs_proc_exit(net); |
130 | out_assocs_proc_init: | 108 | out_assocs_proc_init: |
131 | sctp_eps_proc_exit(); | 109 | sctp_eps_proc_exit(net); |
132 | out_eps_proc_init: | 110 | out_eps_proc_init: |
133 | sctp_snmp_proc_exit(); | 111 | sctp_snmp_proc_exit(net); |
134 | out_snmp_proc_init: | 112 | out_snmp_proc_init: |
135 | if (proc_net_sctp) { | 113 | remove_proc_entry("sctp", net->proc_net); |
136 | proc_net_sctp = NULL; | 114 | net->sctp.proc_net_sctp = NULL; |
137 | remove_proc_entry("sctp", init_net.proc_net); | 115 | out_proc_net_sctp: |
138 | } | ||
139 | out_free_percpu: | ||
140 | percpu_counter_destroy(&sctp_sockets_allocated); | ||
141 | #else | ||
142 | return 0; | ||
143 | #endif /* CONFIG_PROC_FS */ | ||
144 | |||
145 | out_nomem: | ||
146 | return -ENOMEM; | 116 | return -ENOMEM; |
117 | #endif /* CONFIG_PROC_FS */ | ||
118 | return 0; | ||
147 | } | 119 | } |
148 | 120 | ||
149 | /* Clean up the proc fs entry for the SCTP protocol. | 121 | /* Clean up the proc fs entry for the SCTP protocol. |
150 | * Note: Do not make this __exit as it is used in the init error | 122 | * Note: Do not make this __exit as it is used in the init error |
151 | * path. | 123 | * path. |
152 | */ | 124 | */ |
153 | static void sctp_proc_exit(void) | 125 | static void sctp_proc_exit(struct net *net) |
154 | { | 126 | { |
155 | #ifdef CONFIG_PROC_FS | 127 | #ifdef CONFIG_PROC_FS |
156 | sctp_snmp_proc_exit(); | 128 | sctp_snmp_proc_exit(net); |
157 | sctp_eps_proc_exit(); | 129 | sctp_eps_proc_exit(net); |
158 | sctp_assocs_proc_exit(); | 130 | sctp_assocs_proc_exit(net); |
159 | sctp_remaddr_proc_exit(); | 131 | sctp_remaddr_proc_exit(net); |
160 | 132 | ||
161 | if (proc_net_sctp) { | 133 | remove_proc_entry("sctp", net->proc_net); |
162 | proc_net_sctp = NULL; | 134 | net->sctp.proc_net_sctp = NULL; |
163 | remove_proc_entry("sctp", init_net.proc_net); | ||
164 | } | ||
165 | #endif | 135 | #endif |
166 | percpu_counter_destroy(&sctp_sockets_allocated); | ||
167 | } | 136 | } |
168 | 137 | ||
169 | /* Private helper to extract ipv4 address and stash them in | 138 | /* Private helper to extract ipv4 address and stash them in |
@@ -201,29 +170,29 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist, | |||
201 | /* Extract our IP addresses from the system and stash them in the | 170 | /* Extract our IP addresses from the system and stash them in the |
202 | * protocol structure. | 171 | * protocol structure. |
203 | */ | 172 | */ |
204 | static void sctp_get_local_addr_list(void) | 173 | static void sctp_get_local_addr_list(struct net *net) |
205 | { | 174 | { |
206 | struct net_device *dev; | 175 | struct net_device *dev; |
207 | struct list_head *pos; | 176 | struct list_head *pos; |
208 | struct sctp_af *af; | 177 | struct sctp_af *af; |
209 | 178 | ||
210 | rcu_read_lock(); | 179 | rcu_read_lock(); |
211 | for_each_netdev_rcu(&init_net, dev) { | 180 | for_each_netdev_rcu(net, dev) { |
212 | __list_for_each(pos, &sctp_address_families) { | 181 | __list_for_each(pos, &sctp_address_families) { |
213 | af = list_entry(pos, struct sctp_af, list); | 182 | af = list_entry(pos, struct sctp_af, list); |
214 | af->copy_addrlist(&sctp_local_addr_list, dev); | 183 | af->copy_addrlist(&net->sctp.local_addr_list, dev); |
215 | } | 184 | } |
216 | } | 185 | } |
217 | rcu_read_unlock(); | 186 | rcu_read_unlock(); |
218 | } | 187 | } |
219 | 188 | ||
220 | /* Free the existing local addresses. */ | 189 | /* Free the existing local addresses. */ |
221 | static void sctp_free_local_addr_list(void) | 190 | static void sctp_free_local_addr_list(struct net *net) |
222 | { | 191 | { |
223 | struct sctp_sockaddr_entry *addr; | 192 | struct sctp_sockaddr_entry *addr; |
224 | struct list_head *pos, *temp; | 193 | struct list_head *pos, *temp; |
225 | 194 | ||
226 | list_for_each_safe(pos, temp, &sctp_local_addr_list) { | 195 | list_for_each_safe(pos, temp, &net->sctp.local_addr_list) { |
227 | addr = list_entry(pos, struct sctp_sockaddr_entry, list); | 196 | addr = list_entry(pos, struct sctp_sockaddr_entry, list); |
228 | list_del(pos); | 197 | list_del(pos); |
229 | kfree(addr); | 198 | kfree(addr); |
@@ -231,17 +200,17 @@ static void sctp_free_local_addr_list(void) | |||
231 | } | 200 | } |
232 | 201 | ||
233 | /* Copy the local addresses which are valid for 'scope' into 'bp'. */ | 202 | /* Copy the local addresses which are valid for 'scope' into 'bp'. */ |
234 | int sctp_copy_local_addr_list(struct sctp_bind_addr *bp, sctp_scope_t scope, | 203 | int sctp_copy_local_addr_list(struct net *net, struct sctp_bind_addr *bp, |
235 | gfp_t gfp, int copy_flags) | 204 | sctp_scope_t scope, gfp_t gfp, int copy_flags) |
236 | { | 205 | { |
237 | struct sctp_sockaddr_entry *addr; | 206 | struct sctp_sockaddr_entry *addr; |
238 | int error = 0; | 207 | int error = 0; |
239 | 208 | ||
240 | rcu_read_lock(); | 209 | rcu_read_lock(); |
241 | list_for_each_entry_rcu(addr, &sctp_local_addr_list, list) { | 210 | list_for_each_entry_rcu(addr, &net->sctp.local_addr_list, list) { |
242 | if (!addr->valid) | 211 | if (!addr->valid) |
243 | continue; | 212 | continue; |
244 | if (sctp_in_scope(&addr->a, scope)) { | 213 | if (sctp_in_scope(net, &addr->a, scope)) { |
245 | /* Now that the address is in scope, check to see if | 214 | /* Now that the address is in scope, check to see if |
246 | * the address type is really supported by the local | 215 | * the address type is really supported by the local |
247 | * sock as well as the remote peer. | 216 | * sock as well as the remote peer. |
@@ -397,7 +366,8 @@ static int sctp_v4_addr_valid(union sctp_addr *addr, | |||
397 | /* Should this be available for binding? */ | 366 | /* Should this be available for binding? */ |
398 | static int sctp_v4_available(union sctp_addr *addr, struct sctp_sock *sp) | 367 | static int sctp_v4_available(union sctp_addr *addr, struct sctp_sock *sp) |
399 | { | 368 | { |
400 | int ret = inet_addr_type(&init_net, addr->v4.sin_addr.s_addr); | 369 | struct net *net = sock_net(&sp->inet.sk); |
370 | int ret = inet_addr_type(net, addr->v4.sin_addr.s_addr); | ||
401 | 371 | ||
402 | 372 | ||
403 | if (addr->v4.sin_addr.s_addr != htonl(INADDR_ANY) && | 373 | if (addr->v4.sin_addr.s_addr != htonl(INADDR_ANY) && |
@@ -484,7 +454,7 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr, | |||
484 | SCTP_DEBUG_PRINTK("%s: DST:%pI4, SRC:%pI4 - ", | 454 | SCTP_DEBUG_PRINTK("%s: DST:%pI4, SRC:%pI4 - ", |
485 | __func__, &fl4->daddr, &fl4->saddr); | 455 | __func__, &fl4->daddr, &fl4->saddr); |
486 | 456 | ||
487 | rt = ip_route_output_key(&init_net, fl4); | 457 | rt = ip_route_output_key(sock_net(sk), fl4); |
488 | if (!IS_ERR(rt)) | 458 | if (!IS_ERR(rt)) |
489 | dst = &rt->dst; | 459 | dst = &rt->dst; |
490 | 460 | ||
@@ -530,7 +500,7 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr, | |||
530 | (AF_INET == laddr->a.sa.sa_family)) { | 500 | (AF_INET == laddr->a.sa.sa_family)) { |
531 | fl4->saddr = laddr->a.v4.sin_addr.s_addr; | 501 | fl4->saddr = laddr->a.v4.sin_addr.s_addr; |
532 | fl4->fl4_sport = laddr->a.v4.sin_port; | 502 | fl4->fl4_sport = laddr->a.v4.sin_port; |
533 | rt = ip_route_output_key(&init_net, fl4); | 503 | rt = ip_route_output_key(sock_net(sk), fl4); |
534 | if (!IS_ERR(rt)) { | 504 | if (!IS_ERR(rt)) { |
535 | dst = &rt->dst; | 505 | dst = &rt->dst; |
536 | goto out_unlock; | 506 | goto out_unlock; |
@@ -627,14 +597,15 @@ static void sctp_v4_ecn_capable(struct sock *sk) | |||
627 | 597 | ||
628 | void sctp_addr_wq_timeout_handler(unsigned long arg) | 598 | void sctp_addr_wq_timeout_handler(unsigned long arg) |
629 | { | 599 | { |
600 | struct net *net = (struct net *)arg; | ||
630 | struct sctp_sockaddr_entry *addrw, *temp; | 601 | struct sctp_sockaddr_entry *addrw, *temp; |
631 | struct sctp_sock *sp; | 602 | struct sctp_sock *sp; |
632 | 603 | ||
633 | spin_lock_bh(&sctp_addr_wq_lock); | 604 | spin_lock_bh(&net->sctp.addr_wq_lock); |
634 | 605 | ||
635 | list_for_each_entry_safe(addrw, temp, &sctp_addr_waitq, list) { | 606 | list_for_each_entry_safe(addrw, temp, &net->sctp.addr_waitq, list) { |
636 | SCTP_DEBUG_PRINTK_IPADDR("sctp_addrwq_timo_handler: the first ent in wq %p is ", | 607 | SCTP_DEBUG_PRINTK_IPADDR("sctp_addrwq_timo_handler: the first ent in wq %p is ", |
637 | " for cmd %d at entry %p\n", &sctp_addr_waitq, &addrw->a, addrw->state, | 608 | " for cmd %d at entry %p\n", &net->sctp.addr_waitq, &addrw->a, addrw->state, |
638 | addrw); | 609 | addrw); |
639 | 610 | ||
640 | #if IS_ENABLED(CONFIG_IPV6) | 611 | #if IS_ENABLED(CONFIG_IPV6) |
@@ -648,7 +619,7 @@ void sctp_addr_wq_timeout_handler(unsigned long arg) | |||
648 | goto free_next; | 619 | goto free_next; |
649 | 620 | ||
650 | in6 = (struct in6_addr *)&addrw->a.v6.sin6_addr; | 621 | in6 = (struct in6_addr *)&addrw->a.v6.sin6_addr; |
651 | if (ipv6_chk_addr(&init_net, in6, NULL, 0) == 0 && | 622 | if (ipv6_chk_addr(net, in6, NULL, 0) == 0 && |
652 | addrw->state == SCTP_ADDR_NEW) { | 623 | addrw->state == SCTP_ADDR_NEW) { |
653 | unsigned long timeo_val; | 624 | unsigned long timeo_val; |
654 | 625 | ||
@@ -656,12 +627,12 @@ void sctp_addr_wq_timeout_handler(unsigned long arg) | |||
656 | SCTP_ADDRESS_TICK_DELAY); | 627 | SCTP_ADDRESS_TICK_DELAY); |
657 | timeo_val = jiffies; | 628 | timeo_val = jiffies; |
658 | timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY); | 629 | timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY); |
659 | mod_timer(&sctp_addr_wq_timer, timeo_val); | 630 | mod_timer(&net->sctp.addr_wq_timer, timeo_val); |
660 | break; | 631 | break; |
661 | } | 632 | } |
662 | } | 633 | } |
663 | #endif | 634 | #endif |
664 | list_for_each_entry(sp, &sctp_auto_asconf_splist, auto_asconf_list) { | 635 | list_for_each_entry(sp, &net->sctp.auto_asconf_splist, auto_asconf_list) { |
665 | struct sock *sk; | 636 | struct sock *sk; |
666 | 637 | ||
667 | sk = sctp_opt2sk(sp); | 638 | sk = sctp_opt2sk(sp); |
@@ -679,31 +650,32 @@ free_next: | |||
679 | list_del(&addrw->list); | 650 | list_del(&addrw->list); |
680 | kfree(addrw); | 651 | kfree(addrw); |
681 | } | 652 | } |
682 | spin_unlock_bh(&sctp_addr_wq_lock); | 653 | spin_unlock_bh(&net->sctp.addr_wq_lock); |
683 | } | 654 | } |
684 | 655 | ||
685 | static void sctp_free_addr_wq(void) | 656 | static void sctp_free_addr_wq(struct net *net) |
686 | { | 657 | { |
687 | struct sctp_sockaddr_entry *addrw; | 658 | struct sctp_sockaddr_entry *addrw; |
688 | struct sctp_sockaddr_entry *temp; | 659 | struct sctp_sockaddr_entry *temp; |
689 | 660 | ||
690 | spin_lock_bh(&sctp_addr_wq_lock); | 661 | spin_lock_bh(&net->sctp.addr_wq_lock); |
691 | del_timer(&sctp_addr_wq_timer); | 662 | del_timer(&net->sctp.addr_wq_timer); |
692 | list_for_each_entry_safe(addrw, temp, &sctp_addr_waitq, list) { | 663 | list_for_each_entry_safe(addrw, temp, &net->sctp.addr_waitq, list) { |
693 | list_del(&addrw->list); | 664 | list_del(&addrw->list); |
694 | kfree(addrw); | 665 | kfree(addrw); |
695 | } | 666 | } |
696 | spin_unlock_bh(&sctp_addr_wq_lock); | 667 | spin_unlock_bh(&net->sctp.addr_wq_lock); |
697 | } | 668 | } |
698 | 669 | ||
699 | /* lookup the entry for the same address in the addr_waitq | 670 | /* lookup the entry for the same address in the addr_waitq |
700 | * sctp_addr_wq MUST be locked | 671 | * sctp_addr_wq MUST be locked |
701 | */ | 672 | */ |
702 | static struct sctp_sockaddr_entry *sctp_addr_wq_lookup(struct sctp_sockaddr_entry *addr) | 673 | static struct sctp_sockaddr_entry *sctp_addr_wq_lookup(struct net *net, |
674 | struct sctp_sockaddr_entry *addr) | ||
703 | { | 675 | { |
704 | struct sctp_sockaddr_entry *addrw; | 676 | struct sctp_sockaddr_entry *addrw; |
705 | 677 | ||
706 | list_for_each_entry(addrw, &sctp_addr_waitq, list) { | 678 | list_for_each_entry(addrw, &net->sctp.addr_waitq, list) { |
707 | if (addrw->a.sa.sa_family != addr->a.sa.sa_family) | 679 | if (addrw->a.sa.sa_family != addr->a.sa.sa_family) |
708 | continue; | 680 | continue; |
709 | if (addrw->a.sa.sa_family == AF_INET) { | 681 | if (addrw->a.sa.sa_family == AF_INET) { |
@@ -719,7 +691,7 @@ static struct sctp_sockaddr_entry *sctp_addr_wq_lookup(struct sctp_sockaddr_entr | |||
719 | return NULL; | 691 | return NULL; |
720 | } | 692 | } |
721 | 693 | ||
722 | void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *addr, int cmd) | 694 | void sctp_addr_wq_mgmt(struct net *net, struct sctp_sockaddr_entry *addr, int cmd) |
723 | { | 695 | { |
724 | struct sctp_sockaddr_entry *addrw; | 696 | struct sctp_sockaddr_entry *addrw; |
725 | unsigned long timeo_val; | 697 | unsigned long timeo_val; |
@@ -730,38 +702,38 @@ void sctp_addr_wq_mgmt(struct sctp_sockaddr_entry *addr, int cmd) | |||
730 | * new address after a couple of addition and deletion of that address | 702 | * new address after a couple of addition and deletion of that address |
731 | */ | 703 | */ |
732 | 704 | ||
733 | spin_lock_bh(&sctp_addr_wq_lock); | 705 | spin_lock_bh(&net->sctp.addr_wq_lock); |
734 | /* Offsets existing events in addr_wq */ | 706 | /* Offsets existing events in addr_wq */ |
735 | addrw = sctp_addr_wq_lookup(addr); | 707 | addrw = sctp_addr_wq_lookup(net, addr); |
736 | if (addrw) { | 708 | if (addrw) { |
737 | if (addrw->state != cmd) { | 709 | if (addrw->state != cmd) { |
738 | SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt offsets existing entry for %d ", | 710 | SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt offsets existing entry for %d ", |
739 | " in wq %p\n", addrw->state, &addrw->a, | 711 | " in wq %p\n", addrw->state, &addrw->a, |
740 | &sctp_addr_waitq); | 712 | &net->sctp.addr_waitq); |
741 | list_del(&addrw->list); | 713 | list_del(&addrw->list); |
742 | kfree(addrw); | 714 | kfree(addrw); |
743 | } | 715 | } |
744 | spin_unlock_bh(&sctp_addr_wq_lock); | 716 | spin_unlock_bh(&net->sctp.addr_wq_lock); |
745 | return; | 717 | return; |
746 | } | 718 | } |
747 | 719 | ||
748 | /* OK, we have to add the new address to the wait queue */ | 720 | /* OK, we have to add the new address to the wait queue */ |
749 | addrw = kmemdup(addr, sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC); | 721 | addrw = kmemdup(addr, sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC); |
750 | if (addrw == NULL) { | 722 | if (addrw == NULL) { |
751 | spin_unlock_bh(&sctp_addr_wq_lock); | 723 | spin_unlock_bh(&net->sctp.addr_wq_lock); |
752 | return; | 724 | return; |
753 | } | 725 | } |
754 | addrw->state = cmd; | 726 | addrw->state = cmd; |
755 | list_add_tail(&addrw->list, &sctp_addr_waitq); | 727 | list_add_tail(&addrw->list, &net->sctp.addr_waitq); |
756 | SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt add new entry for cmd:%d ", | 728 | SCTP_DEBUG_PRINTK_IPADDR("sctp_addr_wq_mgmt add new entry for cmd:%d ", |
757 | " in wq %p\n", addrw->state, &addrw->a, &sctp_addr_waitq); | 729 | " in wq %p\n", addrw->state, &addrw->a, &net->sctp.addr_waitq); |
758 | 730 | ||
759 | if (!timer_pending(&sctp_addr_wq_timer)) { | 731 | if (!timer_pending(&net->sctp.addr_wq_timer)) { |
760 | timeo_val = jiffies; | 732 | timeo_val = jiffies; |
761 | timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY); | 733 | timeo_val += msecs_to_jiffies(SCTP_ADDRESS_TICK_DELAY); |
762 | mod_timer(&sctp_addr_wq_timer, timeo_val); | 734 | mod_timer(&net->sctp.addr_wq_timer, timeo_val); |
763 | } | 735 | } |
764 | spin_unlock_bh(&sctp_addr_wq_lock); | 736 | spin_unlock_bh(&net->sctp.addr_wq_lock); |
765 | } | 737 | } |
766 | 738 | ||
767 | /* Event handler for inet address addition/deletion events. | 739 | /* Event handler for inet address addition/deletion events. |
@@ -776,11 +748,9 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev, | |||
776 | struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; | 748 | struct in_ifaddr *ifa = (struct in_ifaddr *)ptr; |
777 | struct sctp_sockaddr_entry *addr = NULL; | 749 | struct sctp_sockaddr_entry *addr = NULL; |
778 | struct sctp_sockaddr_entry *temp; | 750 | struct sctp_sockaddr_entry *temp; |
751 | struct net *net = dev_net(ifa->ifa_dev->dev); | ||
779 | int found = 0; | 752 | int found = 0; |
780 | 753 | ||
781 | if (!net_eq(dev_net(ifa->ifa_dev->dev), &init_net)) | ||
782 | return NOTIFY_DONE; | ||
783 | |||
784 | switch (ev) { | 754 | switch (ev) { |
785 | case NETDEV_UP: | 755 | case NETDEV_UP: |
786 | addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC); | 756 | addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC); |
@@ -789,27 +759,27 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev, | |||
789 | addr->a.v4.sin_port = 0; | 759 | addr->a.v4.sin_port = 0; |
790 | addr->a.v4.sin_addr.s_addr = ifa->ifa_local; | 760 | addr->a.v4.sin_addr.s_addr = ifa->ifa_local; |
791 | addr->valid = 1; | 761 | addr->valid = 1; |
792 | spin_lock_bh(&sctp_local_addr_lock); | 762 | spin_lock_bh(&net->sctp.local_addr_lock); |
793 | list_add_tail_rcu(&addr->list, &sctp_local_addr_list); | 763 | list_add_tail_rcu(&addr->list, &net->sctp.local_addr_list); |
794 | sctp_addr_wq_mgmt(addr, SCTP_ADDR_NEW); | 764 | sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_NEW); |
795 | spin_unlock_bh(&sctp_local_addr_lock); | 765 | spin_unlock_bh(&net->sctp.local_addr_lock); |
796 | } | 766 | } |
797 | break; | 767 | break; |
798 | case NETDEV_DOWN: | 768 | case NETDEV_DOWN: |
799 | spin_lock_bh(&sctp_local_addr_lock); | 769 | spin_lock_bh(&net->sctp.local_addr_lock); |
800 | list_for_each_entry_safe(addr, temp, | 770 | list_for_each_entry_safe(addr, temp, |
801 | &sctp_local_addr_list, list) { | 771 | &net->sctp.local_addr_list, list) { |
802 | if (addr->a.sa.sa_family == AF_INET && | 772 | if (addr->a.sa.sa_family == AF_INET && |
803 | addr->a.v4.sin_addr.s_addr == | 773 | addr->a.v4.sin_addr.s_addr == |
804 | ifa->ifa_local) { | 774 | ifa->ifa_local) { |
805 | sctp_addr_wq_mgmt(addr, SCTP_ADDR_DEL); | 775 | sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_DEL); |
806 | found = 1; | 776 | found = 1; |
807 | addr->valid = 0; | 777 | addr->valid = 0; |
808 | list_del_rcu(&addr->list); | 778 | list_del_rcu(&addr->list); |
809 | break; | 779 | break; |
810 | } | 780 | } |
811 | } | 781 | } |
812 | spin_unlock_bh(&sctp_local_addr_lock); | 782 | spin_unlock_bh(&net->sctp.local_addr_lock); |
813 | if (found) | 783 | if (found) |
814 | kfree_rcu(addr, rcu); | 784 | kfree_rcu(addr, rcu); |
815 | break; | 785 | break; |
@@ -822,7 +792,7 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev, | |||
822 | * Initialize the control inode/socket with a control endpoint data | 792 | * Initialize the control inode/socket with a control endpoint data |
823 | * structure. This endpoint is reserved exclusively for the OOTB processing. | 793 | * structure. This endpoint is reserved exclusively for the OOTB processing. |
824 | */ | 794 | */ |
825 | static int sctp_ctl_sock_init(void) | 795 | static int sctp_ctl_sock_init(struct net *net) |
826 | { | 796 | { |
827 | int err; | 797 | int err; |
828 | sa_family_t family = PF_INET; | 798 | sa_family_t family = PF_INET; |
@@ -830,14 +800,14 @@ static int sctp_ctl_sock_init(void) | |||
830 | if (sctp_get_pf_specific(PF_INET6)) | 800 | if (sctp_get_pf_specific(PF_INET6)) |
831 | family = PF_INET6; | 801 | family = PF_INET6; |
832 | 802 | ||
833 | err = inet_ctl_sock_create(&sctp_ctl_sock, family, | 803 | err = inet_ctl_sock_create(&net->sctp.ctl_sock, family, |
834 | SOCK_SEQPACKET, IPPROTO_SCTP, &init_net); | 804 | SOCK_SEQPACKET, IPPROTO_SCTP, net); |
835 | 805 | ||
836 | /* If IPv6 socket could not be created, try the IPv4 socket */ | 806 | /* If IPv6 socket could not be created, try the IPv4 socket */ |
837 | if (err < 0 && family == PF_INET6) | 807 | if (err < 0 && family == PF_INET6) |
838 | err = inet_ctl_sock_create(&sctp_ctl_sock, AF_INET, | 808 | err = inet_ctl_sock_create(&net->sctp.ctl_sock, AF_INET, |
839 | SOCK_SEQPACKET, IPPROTO_SCTP, | 809 | SOCK_SEQPACKET, IPPROTO_SCTP, |
840 | &init_net); | 810 | net); |
841 | 811 | ||
842 | if (err < 0) { | 812 | if (err < 0) { |
843 | pr_err("Failed to create the SCTP control socket\n"); | 813 | pr_err("Failed to create the SCTP control socket\n"); |
@@ -990,7 +960,7 @@ static inline int sctp_v4_xmit(struct sk_buff *skb, | |||
990 | inet->pmtudisc = transport->param_flags & SPP_PMTUD_ENABLE ? | 960 | inet->pmtudisc = transport->param_flags & SPP_PMTUD_ENABLE ? |
991 | IP_PMTUDISC_DO : IP_PMTUDISC_DONT; | 961 | IP_PMTUDISC_DO : IP_PMTUDISC_DONT; |
992 | 962 | ||
993 | SCTP_INC_STATS(SCTP_MIB_OUTSCTPPACKS); | 963 | SCTP_INC_STATS(sock_net(&inet->sk), SCTP_MIB_OUTSCTPPACKS); |
994 | return ip_queue_xmit(skb, &transport->fl); | 964 | return ip_queue_xmit(skb, &transport->fl); |
995 | } | 965 | } |
996 | 966 | ||
@@ -1063,6 +1033,7 @@ static const struct net_protocol sctp_protocol = { | |||
1063 | .handler = sctp_rcv, | 1033 | .handler = sctp_rcv, |
1064 | .err_handler = sctp_v4_err, | 1034 | .err_handler = sctp_v4_err, |
1065 | .no_policy = 1, | 1035 | .no_policy = 1, |
1036 | .netns_ok = 1, | ||
1066 | }; | 1037 | }; |
1067 | 1038 | ||
1068 | /* IPv4 address related functions. */ | 1039 | /* IPv4 address related functions. */ |
@@ -1130,16 +1101,16 @@ int sctp_register_pf(struct sctp_pf *pf, sa_family_t family) | |||
1130 | return 1; | 1101 | return 1; |
1131 | } | 1102 | } |
1132 | 1103 | ||
1133 | static inline int init_sctp_mibs(void) | 1104 | static inline int init_sctp_mibs(struct net *net) |
1134 | { | 1105 | { |
1135 | return snmp_mib_init((void __percpu **)sctp_statistics, | 1106 | return snmp_mib_init((void __percpu **)net->sctp.sctp_statistics, |
1136 | sizeof(struct sctp_mib), | 1107 | sizeof(struct sctp_mib), |
1137 | __alignof__(struct sctp_mib)); | 1108 | __alignof__(struct sctp_mib)); |
1138 | } | 1109 | } |
1139 | 1110 | ||
1140 | static inline void cleanup_sctp_mibs(void) | 1111 | static inline void cleanup_sctp_mibs(struct net *net) |
1141 | { | 1112 | { |
1142 | snmp_mib_free((void __percpu **)sctp_statistics); | 1113 | snmp_mib_free((void __percpu **)net->sctp.sctp_statistics); |
1143 | } | 1114 | } |
1144 | 1115 | ||
1145 | static void sctp_v4_pf_init(void) | 1116 | static void sctp_v4_pf_init(void) |
@@ -1194,6 +1165,143 @@ static void sctp_v4_del_protocol(void) | |||
1194 | unregister_inetaddr_notifier(&sctp_inetaddr_notifier); | 1165 | unregister_inetaddr_notifier(&sctp_inetaddr_notifier); |
1195 | } | 1166 | } |
1196 | 1167 | ||
1168 | static int sctp_net_init(struct net *net) | ||
1169 | { | ||
1170 | int status; | ||
1171 | |||
1172 | /* | ||
1173 | * 14. Suggested SCTP Protocol Parameter Values | ||
1174 | */ | ||
1175 | /* The following protocol parameters are RECOMMENDED: */ | ||
1176 | /* RTO.Initial - 3 seconds */ | ||
1177 | net->sctp.rto_initial = SCTP_RTO_INITIAL; | ||
1178 | /* RTO.Min - 1 second */ | ||
1179 | net->sctp.rto_min = SCTP_RTO_MIN; | ||
1180 | /* RTO.Max - 60 seconds */ | ||
1181 | net->sctp.rto_max = SCTP_RTO_MAX; | ||
1182 | /* RTO.Alpha - 1/8 */ | ||
1183 | net->sctp.rto_alpha = SCTP_RTO_ALPHA; | ||
1184 | /* RTO.Beta - 1/4 */ | ||
1185 | net->sctp.rto_beta = SCTP_RTO_BETA; | ||
1186 | |||
1187 | /* Valid.Cookie.Life - 60 seconds */ | ||
1188 | net->sctp.valid_cookie_life = SCTP_DEFAULT_COOKIE_LIFE; | ||
1189 | |||
1190 | /* Whether Cookie Preservative is enabled(1) or not(0) */ | ||
1191 | net->sctp.cookie_preserve_enable = 1; | ||
1192 | |||
1193 | /* Max.Burst - 4 */ | ||
1194 | net->sctp.max_burst = SCTP_DEFAULT_MAX_BURST; | ||
1195 | |||
1196 | /* Association.Max.Retrans - 10 attempts | ||
1197 | * Path.Max.Retrans - 5 attempts (per destination address) | ||
1198 | * Max.Init.Retransmits - 8 attempts | ||
1199 | */ | ||
1200 | net->sctp.max_retrans_association = 10; | ||
1201 | net->sctp.max_retrans_path = 5; | ||
1202 | net->sctp.max_retrans_init = 8; | ||
1203 | |||
1204 | /* Sendbuffer growth - do per-socket accounting */ | ||
1205 | net->sctp.sndbuf_policy = 0; | ||
1206 | |||
1207 | /* Rcvbuffer growth - do per-socket accounting */ | ||
1208 | net->sctp.rcvbuf_policy = 0; | ||
1209 | |||
1210 | /* HB.interval - 30 seconds */ | ||
1211 | net->sctp.hb_interval = SCTP_DEFAULT_TIMEOUT_HEARTBEAT; | ||
1212 | |||
1213 | /* delayed SACK timeout */ | ||
1214 | net->sctp.sack_timeout = SCTP_DEFAULT_TIMEOUT_SACK; | ||
1215 | |||
1216 | /* Disable ADDIP by default. */ | ||
1217 | net->sctp.addip_enable = 0; | ||
1218 | net->sctp.addip_noauth = 0; | ||
1219 | net->sctp.default_auto_asconf = 0; | ||
1220 | |||
1221 | /* Enable PR-SCTP by default. */ | ||
1222 | net->sctp.prsctp_enable = 1; | ||
1223 | |||
1224 | /* Disable AUTH by default. */ | ||
1225 | net->sctp.auth_enable = 0; | ||
1226 | |||
1227 | /* Set SCOPE policy to enabled */ | ||
1228 | net->sctp.scope_policy = SCTP_SCOPE_POLICY_ENABLE; | ||
1229 | |||
1230 | /* Set the default rwnd update threshold */ | ||
1231 | net->sctp.rwnd_upd_shift = SCTP_DEFAULT_RWND_SHIFT; | ||
1232 | |||
1233 | /* Initialize maximum autoclose timeout. */ | ||
1234 | net->sctp.max_autoclose = INT_MAX / HZ; | ||
1235 | |||
1236 | status = sctp_sysctl_net_register(net); | ||
1237 | if (status) | ||
1238 | goto err_sysctl_register; | ||
1239 | |||
1240 | /* Allocate and initialise sctp mibs. */ | ||
1241 | status = init_sctp_mibs(net); | ||
1242 | if (status) | ||
1243 | goto err_init_mibs; | ||
1244 | |||
1245 | /* Initialize proc fs directory. */ | ||
1246 | status = sctp_proc_init(net); | ||
1247 | if (status) | ||
1248 | goto err_init_proc; | ||
1249 | |||
1250 | sctp_dbg_objcnt_init(net); | ||
1251 | |||
1252 | /* Initialize the control inode/socket for handling OOTB packets. */ | ||
1253 | if ((status = sctp_ctl_sock_init(net))) { | ||
1254 | pr_err("Failed to initialize the SCTP control sock\n"); | ||
1255 | goto err_ctl_sock_init; | ||
1256 | } | ||
1257 | |||
1258 | /* Initialize the local address list. */ | ||
1259 | INIT_LIST_HEAD(&net->sctp.local_addr_list); | ||
1260 | spin_lock_init(&net->sctp.local_addr_lock); | ||
1261 | sctp_get_local_addr_list(net); | ||
1262 | |||
1263 | /* Initialize the address event list */ | ||
1264 | INIT_LIST_HEAD(&net->sctp.addr_waitq); | ||
1265 | INIT_LIST_HEAD(&net->sctp.auto_asconf_splist); | ||
1266 | spin_lock_init(&net->sctp.addr_wq_lock); | ||
1267 | net->sctp.addr_wq_timer.expires = 0; | ||
1268 | setup_timer(&net->sctp.addr_wq_timer, sctp_addr_wq_timeout_handler, | ||
1269 | (unsigned long)net); | ||
1270 | |||
1271 | return 0; | ||
1272 | |||
1273 | err_ctl_sock_init: | ||
1274 | sctp_dbg_objcnt_exit(net); | ||
1275 | sctp_proc_exit(net); | ||
1276 | err_init_proc: | ||
1277 | cleanup_sctp_mibs(net); | ||
1278 | err_init_mibs: | ||
1279 | sctp_sysctl_net_unregister(net); | ||
1280 | err_sysctl_register: | ||
1281 | return status; | ||
1282 | } | ||
1283 | |||
1284 | static void sctp_net_exit(struct net *net) | ||
1285 | { | ||
1286 | /* Free the local address list */ | ||
1287 | sctp_free_addr_wq(net); | ||
1288 | sctp_free_local_addr_list(net); | ||
1289 | |||
1290 | /* Free the control endpoint. */ | ||
1291 | inet_ctl_sock_destroy(net->sctp.ctl_sock); | ||
1292 | |||
1293 | sctp_dbg_objcnt_exit(net); | ||
1294 | |||
1295 | sctp_proc_exit(net); | ||
1296 | cleanup_sctp_mibs(net); | ||
1297 | sctp_sysctl_net_unregister(net); | ||
1298 | } | ||
1299 | |||
1300 | static struct pernet_operations sctp_net_ops = { | ||
1301 | .init = sctp_net_init, | ||
1302 | .exit = sctp_net_exit, | ||
1303 | }; | ||
1304 | |||
1197 | /* Initialize the universe into something sensible. */ | 1305 | /* Initialize the universe into something sensible. */ |
1198 | SCTP_STATIC __init int sctp_init(void) | 1306 | SCTP_STATIC __init int sctp_init(void) |
1199 | { | 1307 | { |
@@ -1224,62 +1332,9 @@ SCTP_STATIC __init int sctp_init(void) | |||
1224 | if (!sctp_chunk_cachep) | 1332 | if (!sctp_chunk_cachep) |
1225 | goto err_chunk_cachep; | 1333 | goto err_chunk_cachep; |
1226 | 1334 | ||
1227 | /* Allocate and initialise sctp mibs. */ | 1335 | status = percpu_counter_init(&sctp_sockets_allocated, 0); |
1228 | status = init_sctp_mibs(); | ||
1229 | if (status) | 1336 | if (status) |
1230 | goto err_init_mibs; | 1337 | goto err_percpu_counter_init; |
1231 | |||
1232 | /* Initialize proc fs directory. */ | ||
1233 | status = sctp_proc_init(); | ||
1234 | if (status) | ||
1235 | goto err_init_proc; | ||
1236 | |||
1237 | /* Initialize object count debugging. */ | ||
1238 | sctp_dbg_objcnt_init(); | ||
1239 | |||
1240 | /* | ||
1241 | * 14. Suggested SCTP Protocol Parameter Values | ||
1242 | */ | ||
1243 | /* The following protocol parameters are RECOMMENDED: */ | ||
1244 | /* RTO.Initial - 3 seconds */ | ||
1245 | sctp_rto_initial = SCTP_RTO_INITIAL; | ||
1246 | /* RTO.Min - 1 second */ | ||
1247 | sctp_rto_min = SCTP_RTO_MIN; | ||
1248 | /* RTO.Max - 60 seconds */ | ||
1249 | sctp_rto_max = SCTP_RTO_MAX; | ||
1250 | /* RTO.Alpha - 1/8 */ | ||
1251 | sctp_rto_alpha = SCTP_RTO_ALPHA; | ||
1252 | /* RTO.Beta - 1/4 */ | ||
1253 | sctp_rto_beta = SCTP_RTO_BETA; | ||
1254 | |||
1255 | /* Valid.Cookie.Life - 60 seconds */ | ||
1256 | sctp_valid_cookie_life = SCTP_DEFAULT_COOKIE_LIFE; | ||
1257 | |||
1258 | /* Whether Cookie Preservative is enabled(1) or not(0) */ | ||
1259 | sctp_cookie_preserve_enable = 1; | ||
1260 | |||
1261 | /* Max.Burst - 4 */ | ||
1262 | sctp_max_burst = SCTP_DEFAULT_MAX_BURST; | ||
1263 | |||
1264 | /* Association.Max.Retrans - 10 attempts | ||
1265 | * Path.Max.Retrans - 5 attempts (per destination address) | ||
1266 | * Max.Init.Retransmits - 8 attempts | ||
1267 | */ | ||
1268 | sctp_max_retrans_association = 10; | ||
1269 | sctp_max_retrans_path = 5; | ||
1270 | sctp_max_retrans_init = 8; | ||
1271 | |||
1272 | /* Sendbuffer growth - do per-socket accounting */ | ||
1273 | sctp_sndbuf_policy = 0; | ||
1274 | |||
1275 | /* Rcvbuffer growth - do per-socket accounting */ | ||
1276 | sctp_rcvbuf_policy = 0; | ||
1277 | |||
1278 | /* HB.interval - 30 seconds */ | ||
1279 | sctp_hb_interval = SCTP_DEFAULT_TIMEOUT_HEARTBEAT; | ||
1280 | |||
1281 | /* delayed SACK timeout */ | ||
1282 | sctp_sack_timeout = SCTP_DEFAULT_TIMEOUT_SACK; | ||
1283 | 1338 | ||
1284 | /* Implementation specific variables. */ | 1339 | /* Implementation specific variables. */ |
1285 | 1340 | ||
@@ -1287,9 +1342,6 @@ SCTP_STATIC __init int sctp_init(void) | |||
1287 | sctp_max_instreams = SCTP_DEFAULT_INSTREAMS; | 1342 | sctp_max_instreams = SCTP_DEFAULT_INSTREAMS; |
1288 | sctp_max_outstreams = SCTP_DEFAULT_OUTSTREAMS; | 1343 | sctp_max_outstreams = SCTP_DEFAULT_OUTSTREAMS; |
1289 | 1344 | ||
1290 | /* Initialize maximum autoclose timeout. */ | ||
1291 | sctp_max_autoclose = INT_MAX / HZ; | ||
1292 | |||
1293 | /* Initialize handle used for association ids. */ | 1345 | /* Initialize handle used for association ids. */ |
1294 | idr_init(&sctp_assocs_id); | 1346 | idr_init(&sctp_assocs_id); |
1295 | 1347 | ||
@@ -1376,41 +1428,12 @@ SCTP_STATIC __init int sctp_init(void) | |||
1376 | pr_info("Hash tables configured (established %d bind %d)\n", | 1428 | pr_info("Hash tables configured (established %d bind %d)\n", |
1377 | sctp_assoc_hashsize, sctp_port_hashsize); | 1429 | sctp_assoc_hashsize, sctp_port_hashsize); |
1378 | 1430 | ||
1379 | /* Disable ADDIP by default. */ | ||
1380 | sctp_addip_enable = 0; | ||
1381 | sctp_addip_noauth = 0; | ||
1382 | sctp_default_auto_asconf = 0; | ||
1383 | |||
1384 | /* Enable PR-SCTP by default. */ | ||
1385 | sctp_prsctp_enable = 1; | ||
1386 | |||
1387 | /* Disable AUTH by default. */ | ||
1388 | sctp_auth_enable = 0; | ||
1389 | |||
1390 | /* Set SCOPE policy to enabled */ | ||
1391 | sctp_scope_policy = SCTP_SCOPE_POLICY_ENABLE; | ||
1392 | |||
1393 | /* Set the default rwnd update threshold */ | ||
1394 | sctp_rwnd_upd_shift = SCTP_DEFAULT_RWND_SHIFT; | ||
1395 | |||
1396 | sctp_sysctl_register(); | 1431 | sctp_sysctl_register(); |
1397 | 1432 | ||
1398 | INIT_LIST_HEAD(&sctp_address_families); | 1433 | INIT_LIST_HEAD(&sctp_address_families); |
1399 | sctp_v4_pf_init(); | 1434 | sctp_v4_pf_init(); |
1400 | sctp_v6_pf_init(); | 1435 | sctp_v6_pf_init(); |
1401 | 1436 | ||
1402 | /* Initialize the local address list. */ | ||
1403 | INIT_LIST_HEAD(&sctp_local_addr_list); | ||
1404 | spin_lock_init(&sctp_local_addr_lock); | ||
1405 | sctp_get_local_addr_list(); | ||
1406 | |||
1407 | /* Initialize the address event list */ | ||
1408 | INIT_LIST_HEAD(&sctp_addr_waitq); | ||
1409 | INIT_LIST_HEAD(&sctp_auto_asconf_splist); | ||
1410 | spin_lock_init(&sctp_addr_wq_lock); | ||
1411 | sctp_addr_wq_timer.expires = 0; | ||
1412 | setup_timer(&sctp_addr_wq_timer, sctp_addr_wq_timeout_handler, 0); | ||
1413 | |||
1414 | status = sctp_v4_protosw_init(); | 1437 | status = sctp_v4_protosw_init(); |
1415 | 1438 | ||
1416 | if (status) | 1439 | if (status) |
@@ -1420,11 +1443,9 @@ SCTP_STATIC __init int sctp_init(void) | |||
1420 | if (status) | 1443 | if (status) |
1421 | goto err_v6_protosw_init; | 1444 | goto err_v6_protosw_init; |
1422 | 1445 | ||
1423 | /* Initialize the control inode/socket for handling OOTB packets. */ | 1446 | status = register_pernet_subsys(&sctp_net_ops); |
1424 | if ((status = sctp_ctl_sock_init())) { | 1447 | if (status) |
1425 | pr_err("Failed to initialize the SCTP control sock\n"); | 1448 | goto err_register_pernet_subsys; |
1426 | goto err_ctl_sock_init; | ||
1427 | } | ||
1428 | 1449 | ||
1429 | status = sctp_v4_add_protocol(); | 1450 | status = sctp_v4_add_protocol(); |
1430 | if (status) | 1451 | if (status) |
@@ -1441,13 +1462,12 @@ out: | |||
1441 | err_v6_add_protocol: | 1462 | err_v6_add_protocol: |
1442 | sctp_v4_del_protocol(); | 1463 | sctp_v4_del_protocol(); |
1443 | err_add_protocol: | 1464 | err_add_protocol: |
1444 | inet_ctl_sock_destroy(sctp_ctl_sock); | 1465 | unregister_pernet_subsys(&sctp_net_ops); |
1445 | err_ctl_sock_init: | 1466 | err_register_pernet_subsys: |
1446 | sctp_v6_protosw_exit(); | 1467 | sctp_v6_protosw_exit(); |
1447 | err_v6_protosw_init: | 1468 | err_v6_protosw_init: |
1448 | sctp_v4_protosw_exit(); | 1469 | sctp_v4_protosw_exit(); |
1449 | err_protosw_init: | 1470 | err_protosw_init: |
1450 | sctp_free_local_addr_list(); | ||
1451 | sctp_v4_pf_exit(); | 1471 | sctp_v4_pf_exit(); |
1452 | sctp_v6_pf_exit(); | 1472 | sctp_v6_pf_exit(); |
1453 | sctp_sysctl_unregister(); | 1473 | sctp_sysctl_unregister(); |
@@ -1461,11 +1481,8 @@ err_ehash_alloc: | |||
1461 | get_order(sctp_assoc_hashsize * | 1481 | get_order(sctp_assoc_hashsize * |
1462 | sizeof(struct sctp_hashbucket))); | 1482 | sizeof(struct sctp_hashbucket))); |
1463 | err_ahash_alloc: | 1483 | err_ahash_alloc: |
1464 | sctp_dbg_objcnt_exit(); | 1484 | percpu_counter_destroy(&sctp_sockets_allocated); |
1465 | sctp_proc_exit(); | 1485 | err_percpu_counter_init: |
1466 | err_init_proc: | ||
1467 | cleanup_sctp_mibs(); | ||
1468 | err_init_mibs: | ||
1469 | kmem_cache_destroy(sctp_chunk_cachep); | 1486 | kmem_cache_destroy(sctp_chunk_cachep); |
1470 | err_chunk_cachep: | 1487 | err_chunk_cachep: |
1471 | kmem_cache_destroy(sctp_bucket_cachep); | 1488 | kmem_cache_destroy(sctp_bucket_cachep); |
@@ -1482,18 +1499,13 @@ SCTP_STATIC __exit void sctp_exit(void) | |||
1482 | /* Unregister with inet6/inet layers. */ | 1499 | /* Unregister with inet6/inet layers. */ |
1483 | sctp_v6_del_protocol(); | 1500 | sctp_v6_del_protocol(); |
1484 | sctp_v4_del_protocol(); | 1501 | sctp_v4_del_protocol(); |
1485 | sctp_free_addr_wq(); | ||
1486 | 1502 | ||
1487 | /* Free the control endpoint. */ | 1503 | unregister_pernet_subsys(&sctp_net_ops); |
1488 | inet_ctl_sock_destroy(sctp_ctl_sock); | ||
1489 | 1504 | ||
1490 | /* Free protosw registrations */ | 1505 | /* Free protosw registrations */ |
1491 | sctp_v6_protosw_exit(); | 1506 | sctp_v6_protosw_exit(); |
1492 | sctp_v4_protosw_exit(); | 1507 | sctp_v4_protosw_exit(); |
1493 | 1508 | ||
1494 | /* Free the local address list. */ | ||
1495 | sctp_free_local_addr_list(); | ||
1496 | |||
1497 | /* Unregister with socket layer. */ | 1509 | /* Unregister with socket layer. */ |
1498 | sctp_v6_pf_exit(); | 1510 | sctp_v6_pf_exit(); |
1499 | sctp_v4_pf_exit(); | 1511 | sctp_v4_pf_exit(); |
@@ -1508,9 +1520,7 @@ SCTP_STATIC __exit void sctp_exit(void) | |||
1508 | get_order(sctp_port_hashsize * | 1520 | get_order(sctp_port_hashsize * |
1509 | sizeof(struct sctp_bind_hashbucket))); | 1521 | sizeof(struct sctp_bind_hashbucket))); |
1510 | 1522 | ||
1511 | sctp_dbg_objcnt_exit(); | 1523 | percpu_counter_destroy(&sctp_sockets_allocated); |
1512 | sctp_proc_exit(); | ||
1513 | cleanup_sctp_mibs(); | ||
1514 | 1524 | ||
1515 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ | 1525 | rcu_barrier(); /* Wait for completion of call_rcu()'s */ |
1516 | 1526 | ||
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c index 479a70ef6ff8..fbe1636309a7 100644 --- a/net/sctp/sm_make_chunk.c +++ b/net/sctp/sm_make_chunk.c | |||
@@ -198,6 +198,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, | |||
198 | const struct sctp_bind_addr *bp, | 198 | const struct sctp_bind_addr *bp, |
199 | gfp_t gfp, int vparam_len) | 199 | gfp_t gfp, int vparam_len) |
200 | { | 200 | { |
201 | struct net *net = sock_net(asoc->base.sk); | ||
201 | sctp_inithdr_t init; | 202 | sctp_inithdr_t init; |
202 | union sctp_params addrs; | 203 | union sctp_params addrs; |
203 | size_t chunksize; | 204 | size_t chunksize; |
@@ -237,7 +238,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, | |||
237 | chunksize += WORD_ROUND(SCTP_SAT_LEN(num_types)); | 238 | chunksize += WORD_ROUND(SCTP_SAT_LEN(num_types)); |
238 | chunksize += sizeof(ecap_param); | 239 | chunksize += sizeof(ecap_param); |
239 | 240 | ||
240 | if (sctp_prsctp_enable) | 241 | if (net->sctp.prsctp_enable) |
241 | chunksize += sizeof(prsctp_param); | 242 | chunksize += sizeof(prsctp_param); |
242 | 243 | ||
243 | /* ADDIP: Section 4.2.7: | 244 | /* ADDIP: Section 4.2.7: |
@@ -245,7 +246,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, | |||
245 | * the ASCONF,the ASCONF-ACK, and the AUTH chunks in its INIT and | 246 | * the ASCONF,the ASCONF-ACK, and the AUTH chunks in its INIT and |
246 | * INIT-ACK parameters. | 247 | * INIT-ACK parameters. |
247 | */ | 248 | */ |
248 | if (sctp_addip_enable) { | 249 | if (net->sctp.addip_enable) { |
249 | extensions[num_ext] = SCTP_CID_ASCONF; | 250 | extensions[num_ext] = SCTP_CID_ASCONF; |
250 | extensions[num_ext+1] = SCTP_CID_ASCONF_ACK; | 251 | extensions[num_ext+1] = SCTP_CID_ASCONF_ACK; |
251 | num_ext += 2; | 252 | num_ext += 2; |
@@ -257,7 +258,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, | |||
257 | chunksize += vparam_len; | 258 | chunksize += vparam_len; |
258 | 259 | ||
259 | /* Account for AUTH related parameters */ | 260 | /* Account for AUTH related parameters */ |
260 | if (sctp_auth_enable) { | 261 | if (net->sctp.auth_enable) { |
261 | /* Add random parameter length*/ | 262 | /* Add random parameter length*/ |
262 | chunksize += sizeof(asoc->c.auth_random); | 263 | chunksize += sizeof(asoc->c.auth_random); |
263 | 264 | ||
@@ -331,7 +332,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, | |||
331 | sctp_addto_param(retval, num_ext, extensions); | 332 | sctp_addto_param(retval, num_ext, extensions); |
332 | } | 333 | } |
333 | 334 | ||
334 | if (sctp_prsctp_enable) | 335 | if (net->sctp.prsctp_enable) |
335 | sctp_addto_chunk(retval, sizeof(prsctp_param), &prsctp_param); | 336 | sctp_addto_chunk(retval, sizeof(prsctp_param), &prsctp_param); |
336 | 337 | ||
337 | if (sp->adaptation_ind) { | 338 | if (sp->adaptation_ind) { |
@@ -342,7 +343,7 @@ struct sctp_chunk *sctp_make_init(const struct sctp_association *asoc, | |||
342 | } | 343 | } |
343 | 344 | ||
344 | /* Add SCTP-AUTH chunks to the parameter list */ | 345 | /* Add SCTP-AUTH chunks to the parameter list */ |
345 | if (sctp_auth_enable) { | 346 | if (net->sctp.auth_enable) { |
346 | sctp_addto_chunk(retval, sizeof(asoc->c.auth_random), | 347 | sctp_addto_chunk(retval, sizeof(asoc->c.auth_random), |
347 | asoc->c.auth_random); | 348 | asoc->c.auth_random); |
348 | if (auth_hmacs) | 349 | if (auth_hmacs) |
@@ -1940,7 +1941,7 @@ static int sctp_process_hn_param(const struct sctp_association *asoc, | |||
1940 | return 0; | 1941 | return 0; |
1941 | } | 1942 | } |
1942 | 1943 | ||
1943 | static int sctp_verify_ext_param(union sctp_params param) | 1944 | static int sctp_verify_ext_param(struct net *net, union sctp_params param) |
1944 | { | 1945 | { |
1945 | __u16 num_ext = ntohs(param.p->length) - sizeof(sctp_paramhdr_t); | 1946 | __u16 num_ext = ntohs(param.p->length) - sizeof(sctp_paramhdr_t); |
1946 | int have_auth = 0; | 1947 | int have_auth = 0; |
@@ -1964,10 +1965,10 @@ static int sctp_verify_ext_param(union sctp_params param) | |||
1964 | * only if ADD-IP is turned on and we are not backward-compatible | 1965 | * only if ADD-IP is turned on and we are not backward-compatible |
1965 | * mode. | 1966 | * mode. |
1966 | */ | 1967 | */ |
1967 | if (sctp_addip_noauth) | 1968 | if (net->sctp.addip_noauth) |
1968 | return 1; | 1969 | return 1; |
1969 | 1970 | ||
1970 | if (sctp_addip_enable && !have_auth && have_asconf) | 1971 | if (net->sctp.addip_enable && !have_auth && have_asconf) |
1971 | return 0; | 1972 | return 0; |
1972 | 1973 | ||
1973 | return 1; | 1974 | return 1; |
@@ -1976,13 +1977,14 @@ static int sctp_verify_ext_param(union sctp_params param) | |||
1976 | static void sctp_process_ext_param(struct sctp_association *asoc, | 1977 | static void sctp_process_ext_param(struct sctp_association *asoc, |
1977 | union sctp_params param) | 1978 | union sctp_params param) |
1978 | { | 1979 | { |
1980 | struct net *net = sock_net(asoc->base.sk); | ||
1979 | __u16 num_ext = ntohs(param.p->length) - sizeof(sctp_paramhdr_t); | 1981 | __u16 num_ext = ntohs(param.p->length) - sizeof(sctp_paramhdr_t); |
1980 | int i; | 1982 | int i; |
1981 | 1983 | ||
1982 | for (i = 0; i < num_ext; i++) { | 1984 | for (i = 0; i < num_ext; i++) { |
1983 | switch (param.ext->chunks[i]) { | 1985 | switch (param.ext->chunks[i]) { |
1984 | case SCTP_CID_FWD_TSN: | 1986 | case SCTP_CID_FWD_TSN: |
1985 | if (sctp_prsctp_enable && | 1987 | if (net->sctp.prsctp_enable && |
1986 | !asoc->peer.prsctp_capable) | 1988 | !asoc->peer.prsctp_capable) |
1987 | asoc->peer.prsctp_capable = 1; | 1989 | asoc->peer.prsctp_capable = 1; |
1988 | break; | 1990 | break; |
@@ -1990,12 +1992,12 @@ static void sctp_process_ext_param(struct sctp_association *asoc, | |||
1990 | /* if the peer reports AUTH, assume that he | 1992 | /* if the peer reports AUTH, assume that he |
1991 | * supports AUTH. | 1993 | * supports AUTH. |
1992 | */ | 1994 | */ |
1993 | if (sctp_auth_enable) | 1995 | if (net->sctp.auth_enable) |
1994 | asoc->peer.auth_capable = 1; | 1996 | asoc->peer.auth_capable = 1; |
1995 | break; | 1997 | break; |
1996 | case SCTP_CID_ASCONF: | 1998 | case SCTP_CID_ASCONF: |
1997 | case SCTP_CID_ASCONF_ACK: | 1999 | case SCTP_CID_ASCONF_ACK: |
1998 | if (sctp_addip_enable) | 2000 | if (net->sctp.addip_enable) |
1999 | asoc->peer.asconf_capable = 1; | 2001 | asoc->peer.asconf_capable = 1; |
2000 | break; | 2002 | break; |
2001 | default: | 2003 | default: |
@@ -2081,7 +2083,8 @@ static sctp_ierror_t sctp_process_unk_param(const struct sctp_association *asoc, | |||
2081 | * SCTP_IERROR_ERROR - stop processing, trigger an ERROR | 2083 | * SCTP_IERROR_ERROR - stop processing, trigger an ERROR |
2082 | * SCTP_IERROR_NO_ERROR - continue with the chunk | 2084 | * SCTP_IERROR_NO_ERROR - continue with the chunk |
2083 | */ | 2085 | */ |
2084 | static sctp_ierror_t sctp_verify_param(const struct sctp_association *asoc, | 2086 | static sctp_ierror_t sctp_verify_param(struct net *net, |
2087 | const struct sctp_association *asoc, | ||
2085 | union sctp_params param, | 2088 | union sctp_params param, |
2086 | sctp_cid_t cid, | 2089 | sctp_cid_t cid, |
2087 | struct sctp_chunk *chunk, | 2090 | struct sctp_chunk *chunk, |
@@ -2110,12 +2113,12 @@ static sctp_ierror_t sctp_verify_param(const struct sctp_association *asoc, | |||
2110 | break; | 2113 | break; |
2111 | 2114 | ||
2112 | case SCTP_PARAM_SUPPORTED_EXT: | 2115 | case SCTP_PARAM_SUPPORTED_EXT: |
2113 | if (!sctp_verify_ext_param(param)) | 2116 | if (!sctp_verify_ext_param(net, param)) |
2114 | return SCTP_IERROR_ABORT; | 2117 | return SCTP_IERROR_ABORT; |
2115 | break; | 2118 | break; |
2116 | 2119 | ||
2117 | case SCTP_PARAM_SET_PRIMARY: | 2120 | case SCTP_PARAM_SET_PRIMARY: |
2118 | if (sctp_addip_enable) | 2121 | if (net->sctp.addip_enable) |
2119 | break; | 2122 | break; |
2120 | goto fallthrough; | 2123 | goto fallthrough; |
2121 | 2124 | ||
@@ -2126,12 +2129,12 @@ static sctp_ierror_t sctp_verify_param(const struct sctp_association *asoc, | |||
2126 | break; | 2129 | break; |
2127 | 2130 | ||
2128 | case SCTP_PARAM_FWD_TSN_SUPPORT: | 2131 | case SCTP_PARAM_FWD_TSN_SUPPORT: |
2129 | if (sctp_prsctp_enable) | 2132 | if (net->sctp.prsctp_enable) |
2130 | break; | 2133 | break; |
2131 | goto fallthrough; | 2134 | goto fallthrough; |
2132 | 2135 | ||
2133 | case SCTP_PARAM_RANDOM: | 2136 | case SCTP_PARAM_RANDOM: |
2134 | if (!sctp_auth_enable) | 2137 | if (!net->sctp.auth_enable) |
2135 | goto fallthrough; | 2138 | goto fallthrough; |
2136 | 2139 | ||
2137 | /* SCTP-AUTH: Secion 6.1 | 2140 | /* SCTP-AUTH: Secion 6.1 |
@@ -2148,7 +2151,7 @@ static sctp_ierror_t sctp_verify_param(const struct sctp_association *asoc, | |||
2148 | break; | 2151 | break; |
2149 | 2152 | ||
2150 | case SCTP_PARAM_CHUNKS: | 2153 | case SCTP_PARAM_CHUNKS: |
2151 | if (!sctp_auth_enable) | 2154 | if (!net->sctp.auth_enable) |
2152 | goto fallthrough; | 2155 | goto fallthrough; |
2153 | 2156 | ||
2154 | /* SCTP-AUTH: Section 3.2 | 2157 | /* SCTP-AUTH: Section 3.2 |
@@ -2164,7 +2167,7 @@ static sctp_ierror_t sctp_verify_param(const struct sctp_association *asoc, | |||
2164 | break; | 2167 | break; |
2165 | 2168 | ||
2166 | case SCTP_PARAM_HMAC_ALGO: | 2169 | case SCTP_PARAM_HMAC_ALGO: |
2167 | if (!sctp_auth_enable) | 2170 | if (!net->sctp.auth_enable) |
2168 | goto fallthrough; | 2171 | goto fallthrough; |
2169 | 2172 | ||
2170 | hmacs = (struct sctp_hmac_algo_param *)param.p; | 2173 | hmacs = (struct sctp_hmac_algo_param *)param.p; |
@@ -2198,7 +2201,7 @@ fallthrough: | |||
2198 | } | 2201 | } |
2199 | 2202 | ||
2200 | /* Verify the INIT packet before we process it. */ | 2203 | /* Verify the INIT packet before we process it. */ |
2201 | int sctp_verify_init(const struct sctp_association *asoc, | 2204 | int sctp_verify_init(struct net *net, const struct sctp_association *asoc, |
2202 | sctp_cid_t cid, | 2205 | sctp_cid_t cid, |
2203 | sctp_init_chunk_t *peer_init, | 2206 | sctp_init_chunk_t *peer_init, |
2204 | struct sctp_chunk *chunk, | 2207 | struct sctp_chunk *chunk, |
@@ -2245,7 +2248,7 @@ int sctp_verify_init(const struct sctp_association *asoc, | |||
2245 | /* Verify all the variable length parameters */ | 2248 | /* Verify all the variable length parameters */ |
2246 | sctp_walk_params(param, peer_init, init_hdr.params) { | 2249 | sctp_walk_params(param, peer_init, init_hdr.params) { |
2247 | 2250 | ||
2248 | result = sctp_verify_param(asoc, param, cid, chunk, errp); | 2251 | result = sctp_verify_param(net, asoc, param, cid, chunk, errp); |
2249 | switch (result) { | 2252 | switch (result) { |
2250 | case SCTP_IERROR_ABORT: | 2253 | case SCTP_IERROR_ABORT: |
2251 | case SCTP_IERROR_NOMEM: | 2254 | case SCTP_IERROR_NOMEM: |
@@ -2270,6 +2273,7 @@ int sctp_process_init(struct sctp_association *asoc, struct sctp_chunk *chunk, | |||
2270 | const union sctp_addr *peer_addr, | 2273 | const union sctp_addr *peer_addr, |
2271 | sctp_init_chunk_t *peer_init, gfp_t gfp) | 2274 | sctp_init_chunk_t *peer_init, gfp_t gfp) |
2272 | { | 2275 | { |
2276 | struct net *net = sock_net(asoc->base.sk); | ||
2273 | union sctp_params param; | 2277 | union sctp_params param; |
2274 | struct sctp_transport *transport; | 2278 | struct sctp_transport *transport; |
2275 | struct list_head *pos, *temp; | 2279 | struct list_head *pos, *temp; |
@@ -2326,7 +2330,7 @@ int sctp_process_init(struct sctp_association *asoc, struct sctp_chunk *chunk, | |||
2326 | * also give us an option to silently ignore the packet, which | 2330 | * also give us an option to silently ignore the packet, which |
2327 | * is what we'll do here. | 2331 | * is what we'll do here. |
2328 | */ | 2332 | */ |
2329 | if (!sctp_addip_noauth && | 2333 | if (!net->sctp.addip_noauth && |
2330 | (asoc->peer.asconf_capable && !asoc->peer.auth_capable)) { | 2334 | (asoc->peer.asconf_capable && !asoc->peer.auth_capable)) { |
2331 | asoc->peer.addip_disabled_mask |= (SCTP_PARAM_ADD_IP | | 2335 | asoc->peer.addip_disabled_mask |= (SCTP_PARAM_ADD_IP | |
2332 | SCTP_PARAM_DEL_IP | | 2336 | SCTP_PARAM_DEL_IP | |
@@ -2466,6 +2470,7 @@ static int sctp_process_param(struct sctp_association *asoc, | |||
2466 | const union sctp_addr *peer_addr, | 2470 | const union sctp_addr *peer_addr, |
2467 | gfp_t gfp) | 2471 | gfp_t gfp) |
2468 | { | 2472 | { |
2473 | struct net *net = sock_net(asoc->base.sk); | ||
2469 | union sctp_addr addr; | 2474 | union sctp_addr addr; |
2470 | int i; | 2475 | int i; |
2471 | __u16 sat; | 2476 | __u16 sat; |
@@ -2494,13 +2499,13 @@ do_addr_param: | |||
2494 | af = sctp_get_af_specific(param_type2af(param.p->type)); | 2499 | af = sctp_get_af_specific(param_type2af(param.p->type)); |
2495 | af->from_addr_param(&addr, param.addr, htons(asoc->peer.port), 0); | 2500 | af->from_addr_param(&addr, param.addr, htons(asoc->peer.port), 0); |
2496 | scope = sctp_scope(peer_addr); | 2501 | scope = sctp_scope(peer_addr); |
2497 | if (sctp_in_scope(&addr, scope)) | 2502 | if (sctp_in_scope(net, &addr, scope)) |
2498 | if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_UNCONFIRMED)) | 2503 | if (!sctp_assoc_add_peer(asoc, &addr, gfp, SCTP_UNCONFIRMED)) |
2499 | return 0; | 2504 | return 0; |
2500 | break; | 2505 | break; |
2501 | 2506 | ||
2502 | case SCTP_PARAM_COOKIE_PRESERVATIVE: | 2507 | case SCTP_PARAM_COOKIE_PRESERVATIVE: |
2503 | if (!sctp_cookie_preserve_enable) | 2508 | if (!net->sctp.cookie_preserve_enable) |
2504 | break; | 2509 | break; |
2505 | 2510 | ||
2506 | stale = ntohl(param.life->lifespan_increment); | 2511 | stale = ntohl(param.life->lifespan_increment); |
@@ -2580,7 +2585,7 @@ do_addr_param: | |||
2580 | break; | 2585 | break; |
2581 | 2586 | ||
2582 | case SCTP_PARAM_SET_PRIMARY: | 2587 | case SCTP_PARAM_SET_PRIMARY: |
2583 | if (!sctp_addip_enable) | 2588 | if (!net->sctp.addip_enable) |
2584 | goto fall_through; | 2589 | goto fall_through; |
2585 | 2590 | ||
2586 | addr_param = param.v + sizeof(sctp_addip_param_t); | 2591 | addr_param = param.v + sizeof(sctp_addip_param_t); |
@@ -2607,7 +2612,7 @@ do_addr_param: | |||
2607 | break; | 2612 | break; |
2608 | 2613 | ||
2609 | case SCTP_PARAM_FWD_TSN_SUPPORT: | 2614 | case SCTP_PARAM_FWD_TSN_SUPPORT: |
2610 | if (sctp_prsctp_enable) { | 2615 | if (net->sctp.prsctp_enable) { |
2611 | asoc->peer.prsctp_capable = 1; | 2616 | asoc->peer.prsctp_capable = 1; |
2612 | break; | 2617 | break; |
2613 | } | 2618 | } |
@@ -2615,7 +2620,7 @@ do_addr_param: | |||
2615 | goto fall_through; | 2620 | goto fall_through; |
2616 | 2621 | ||
2617 | case SCTP_PARAM_RANDOM: | 2622 | case SCTP_PARAM_RANDOM: |
2618 | if (!sctp_auth_enable) | 2623 | if (!net->sctp.auth_enable) |
2619 | goto fall_through; | 2624 | goto fall_through; |
2620 | 2625 | ||
2621 | /* Save peer's random parameter */ | 2626 | /* Save peer's random parameter */ |
@@ -2628,7 +2633,7 @@ do_addr_param: | |||
2628 | break; | 2633 | break; |
2629 | 2634 | ||
2630 | case SCTP_PARAM_HMAC_ALGO: | 2635 | case SCTP_PARAM_HMAC_ALGO: |
2631 | if (!sctp_auth_enable) | 2636 | if (!net->sctp.auth_enable) |
2632 | goto fall_through; | 2637 | goto fall_through; |
2633 | 2638 | ||
2634 | /* Save peer's HMAC list */ | 2639 | /* Save peer's HMAC list */ |
@@ -2644,7 +2649,7 @@ do_addr_param: | |||
2644 | break; | 2649 | break; |
2645 | 2650 | ||
2646 | case SCTP_PARAM_CHUNKS: | 2651 | case SCTP_PARAM_CHUNKS: |
2647 | if (!sctp_auth_enable) | 2652 | if (!net->sctp.auth_enable) |
2648 | goto fall_through; | 2653 | goto fall_through; |
2649 | 2654 | ||
2650 | asoc->peer.peer_chunks = kmemdup(param.p, | 2655 | asoc->peer.peer_chunks = kmemdup(param.p, |
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c index fe99628e1257..bcfebb91559d 100644 --- a/net/sctp/sm_sideeffect.c +++ b/net/sctp/sm_sideeffect.c | |||
@@ -251,6 +251,7 @@ void sctp_generate_t3_rtx_event(unsigned long peer) | |||
251 | int error; | 251 | int error; |
252 | struct sctp_transport *transport = (struct sctp_transport *) peer; | 252 | struct sctp_transport *transport = (struct sctp_transport *) peer; |
253 | struct sctp_association *asoc = transport->asoc; | 253 | struct sctp_association *asoc = transport->asoc; |
254 | struct net *net = sock_net(asoc->base.sk); | ||
254 | 255 | ||
255 | /* Check whether a task is in the sock. */ | 256 | /* Check whether a task is in the sock. */ |
256 | 257 | ||
@@ -271,7 +272,7 @@ void sctp_generate_t3_rtx_event(unsigned long peer) | |||
271 | goto out_unlock; | 272 | goto out_unlock; |
272 | 273 | ||
273 | /* Run through the state machine. */ | 274 | /* Run through the state machine. */ |
274 | error = sctp_do_sm(SCTP_EVENT_T_TIMEOUT, | 275 | error = sctp_do_sm(net, SCTP_EVENT_T_TIMEOUT, |
275 | SCTP_ST_TIMEOUT(SCTP_EVENT_TIMEOUT_T3_RTX), | 276 | SCTP_ST_TIMEOUT(SCTP_EVENT_TIMEOUT_T3_RTX), |
276 | asoc->state, | 277 | asoc->state, |
277 | asoc->ep, asoc, | 278 | asoc->ep, asoc, |
@@ -291,6 +292,7 @@ out_unlock: | |||
291 | static void sctp_generate_timeout_event(struct sctp_association *asoc, | 292 | static void sctp_generate_timeout_event(struct sctp_association *asoc, |
292 | sctp_event_timeout_t timeout_type) | 293 | sctp_event_timeout_t timeout_type) |
293 | { | 294 | { |
295 | struct net *net = sock_net(asoc->base.sk); | ||
294 | int error = 0; | 296 | int error = 0; |
295 | 297 | ||
296 | sctp_bh_lock_sock(asoc->base.sk); | 298 | sctp_bh_lock_sock(asoc->base.sk); |
@@ -312,7 +314,7 @@ static void sctp_generate_timeout_event(struct sctp_association *asoc, | |||
312 | goto out_unlock; | 314 | goto out_unlock; |
313 | 315 | ||
314 | /* Run through the state machine. */ | 316 | /* Run through the state machine. */ |
315 | error = sctp_do_sm(SCTP_EVENT_T_TIMEOUT, | 317 | error = sctp_do_sm(net, SCTP_EVENT_T_TIMEOUT, |
316 | SCTP_ST_TIMEOUT(timeout_type), | 318 | SCTP_ST_TIMEOUT(timeout_type), |
317 | asoc->state, asoc->ep, asoc, | 319 | asoc->state, asoc->ep, asoc, |
318 | (void *)timeout_type, GFP_ATOMIC); | 320 | (void *)timeout_type, GFP_ATOMIC); |
@@ -371,6 +373,7 @@ void sctp_generate_heartbeat_event(unsigned long data) | |||
371 | int error = 0; | 373 | int error = 0; |
372 | struct sctp_transport *transport = (struct sctp_transport *) data; | 374 | struct sctp_transport *transport = (struct sctp_transport *) data; |
373 | struct sctp_association *asoc = transport->asoc; | 375 | struct sctp_association *asoc = transport->asoc; |
376 | struct net *net = sock_net(asoc->base.sk); | ||
374 | 377 | ||
375 | sctp_bh_lock_sock(asoc->base.sk); | 378 | sctp_bh_lock_sock(asoc->base.sk); |
376 | if (sock_owned_by_user(asoc->base.sk)) { | 379 | if (sock_owned_by_user(asoc->base.sk)) { |
@@ -388,7 +391,7 @@ void sctp_generate_heartbeat_event(unsigned long data) | |||
388 | if (transport->dead) | 391 | if (transport->dead) |
389 | goto out_unlock; | 392 | goto out_unlock; |
390 | 393 | ||
391 | error = sctp_do_sm(SCTP_EVENT_T_TIMEOUT, | 394 | error = sctp_do_sm(net, SCTP_EVENT_T_TIMEOUT, |
392 | SCTP_ST_TIMEOUT(SCTP_EVENT_TIMEOUT_HEARTBEAT), | 395 | SCTP_ST_TIMEOUT(SCTP_EVENT_TIMEOUT_HEARTBEAT), |
393 | asoc->state, asoc->ep, asoc, | 396 | asoc->state, asoc->ep, asoc, |
394 | transport, GFP_ATOMIC); | 397 | transport, GFP_ATOMIC); |
@@ -408,6 +411,7 @@ void sctp_generate_proto_unreach_event(unsigned long data) | |||
408 | { | 411 | { |
409 | struct sctp_transport *transport = (struct sctp_transport *) data; | 412 | struct sctp_transport *transport = (struct sctp_transport *) data; |
410 | struct sctp_association *asoc = transport->asoc; | 413 | struct sctp_association *asoc = transport->asoc; |
414 | struct net *net = sock_net(asoc->base.sk); | ||
411 | 415 | ||
412 | sctp_bh_lock_sock(asoc->base.sk); | 416 | sctp_bh_lock_sock(asoc->base.sk); |
413 | if (sock_owned_by_user(asoc->base.sk)) { | 417 | if (sock_owned_by_user(asoc->base.sk)) { |
@@ -426,7 +430,7 @@ void sctp_generate_proto_unreach_event(unsigned long data) | |||
426 | if (asoc->base.dead) | 430 | if (asoc->base.dead) |
427 | goto out_unlock; | 431 | goto out_unlock; |
428 | 432 | ||
429 | sctp_do_sm(SCTP_EVENT_T_OTHER, | 433 | sctp_do_sm(net, SCTP_EVENT_T_OTHER, |
430 | SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH), | 434 | SCTP_ST_OTHER(SCTP_EVENT_ICMP_PROTO_UNREACH), |
431 | asoc->state, asoc->ep, asoc, transport, GFP_ATOMIC); | 435 | asoc->state, asoc->ep, asoc, transport, GFP_ATOMIC); |
432 | 436 | ||
@@ -753,8 +757,10 @@ static int sctp_cmd_process_sack(sctp_cmd_seq_t *cmds, | |||
753 | int err = 0; | 757 | int err = 0; |
754 | 758 | ||
755 | if (sctp_outq_sack(&asoc->outqueue, sackh)) { | 759 | if (sctp_outq_sack(&asoc->outqueue, sackh)) { |
760 | struct net *net = sock_net(asoc->base.sk); | ||
761 | |||
756 | /* There are no more TSNs awaiting SACK. */ | 762 | /* There are no more TSNs awaiting SACK. */ |
757 | err = sctp_do_sm(SCTP_EVENT_T_OTHER, | 763 | err = sctp_do_sm(net, SCTP_EVENT_T_OTHER, |
758 | SCTP_ST_OTHER(SCTP_EVENT_NO_PENDING_TSN), | 764 | SCTP_ST_OTHER(SCTP_EVENT_NO_PENDING_TSN), |
759 | asoc->state, asoc->ep, asoc, NULL, | 765 | asoc->state, asoc->ep, asoc, NULL, |
760 | GFP_ATOMIC); | 766 | GFP_ATOMIC); |
@@ -1042,6 +1048,8 @@ static int sctp_cmd_send_msg(struct sctp_association *asoc, | |||
1042 | */ | 1048 | */ |
1043 | static void sctp_cmd_send_asconf(struct sctp_association *asoc) | 1049 | static void sctp_cmd_send_asconf(struct sctp_association *asoc) |
1044 | { | 1050 | { |
1051 | struct net *net = sock_net(asoc->base.sk); | ||
1052 | |||
1045 | /* Send the next asconf chunk from the addip chunk | 1053 | /* Send the next asconf chunk from the addip chunk |
1046 | * queue. | 1054 | * queue. |
1047 | */ | 1055 | */ |
@@ -1053,7 +1061,7 @@ static void sctp_cmd_send_asconf(struct sctp_association *asoc) | |||
1053 | 1061 | ||
1054 | /* Hold the chunk until an ASCONF_ACK is received. */ | 1062 | /* Hold the chunk until an ASCONF_ACK is received. */ |
1055 | sctp_chunk_hold(asconf); | 1063 | sctp_chunk_hold(asconf); |
1056 | if (sctp_primitive_ASCONF(asoc, asconf)) | 1064 | if (sctp_primitive_ASCONF(net, asoc, asconf)) |
1057 | sctp_chunk_free(asconf); | 1065 | sctp_chunk_free(asconf); |
1058 | else | 1066 | else |
1059 | asoc->addip_last_asconf = asconf; | 1067 | asoc->addip_last_asconf = asconf; |
@@ -1089,7 +1097,7 @@ static void sctp_cmd_send_asconf(struct sctp_association *asoc) | |||
1089 | * If you want to understand all of lksctp, this is a | 1097 | * If you want to understand all of lksctp, this is a |
1090 | * good place to start. | 1098 | * good place to start. |
1091 | */ | 1099 | */ |
1092 | int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype, | 1100 | int sctp_do_sm(struct net *net, sctp_event_t event_type, sctp_subtype_t subtype, |
1093 | sctp_state_t state, | 1101 | sctp_state_t state, |
1094 | struct sctp_endpoint *ep, | 1102 | struct sctp_endpoint *ep, |
1095 | struct sctp_association *asoc, | 1103 | struct sctp_association *asoc, |
@@ -1110,12 +1118,12 @@ int sctp_do_sm(sctp_event_t event_type, sctp_subtype_t subtype, | |||
1110 | /* Look up the state function, run it, and then process the | 1118 | /* Look up the state function, run it, and then process the |
1111 | * side effects. These three steps are the heart of lksctp. | 1119 | * side effects. These three steps are the heart of lksctp. |
1112 | */ | 1120 | */ |
1113 | state_fn = sctp_sm_lookup_event(event_type, state, subtype); | 1121 | state_fn = sctp_sm_lookup_event(net, event_type, state, subtype); |
1114 | 1122 | ||
1115 | sctp_init_cmd_seq(&commands); | 1123 | sctp_init_cmd_seq(&commands); |
1116 | 1124 | ||
1117 | DEBUG_PRE; | 1125 | DEBUG_PRE; |
1118 | status = (*state_fn->fn)(ep, asoc, subtype, event_arg, &commands); | 1126 | status = (*state_fn->fn)(net, ep, asoc, subtype, event_arg, &commands); |
1119 | DEBUG_POST; | 1127 | DEBUG_POST; |
1120 | 1128 | ||
1121 | error = sctp_side_effects(event_type, subtype, state, | 1129 | error = sctp_side_effects(event_type, subtype, state, |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 9fca10357350..094813b6c3c3 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -66,7 +66,8 @@ | |||
66 | #include <net/sctp/sm.h> | 66 | #include <net/sctp/sm.h> |
67 | #include <net/sctp/structs.h> | 67 | #include <net/sctp/structs.h> |
68 | 68 | ||
69 | static struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *ep, | 69 | static struct sctp_packet *sctp_abort_pkt_new(struct net *net, |
70 | const struct sctp_endpoint *ep, | ||
70 | const struct sctp_association *asoc, | 71 | const struct sctp_association *asoc, |
71 | struct sctp_chunk *chunk, | 72 | struct sctp_chunk *chunk, |
72 | const void *payload, | 73 | const void *payload, |
@@ -74,36 +75,43 @@ static struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *ep, | |||
74 | static int sctp_eat_data(const struct sctp_association *asoc, | 75 | static int sctp_eat_data(const struct sctp_association *asoc, |
75 | struct sctp_chunk *chunk, | 76 | struct sctp_chunk *chunk, |
76 | sctp_cmd_seq_t *commands); | 77 | sctp_cmd_seq_t *commands); |
77 | static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc, | 78 | static struct sctp_packet *sctp_ootb_pkt_new(struct net *net, |
79 | const struct sctp_association *asoc, | ||
78 | const struct sctp_chunk *chunk); | 80 | const struct sctp_chunk *chunk); |
79 | static void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep, | 81 | static void sctp_send_stale_cookie_err(struct net *net, |
82 | const struct sctp_endpoint *ep, | ||
80 | const struct sctp_association *asoc, | 83 | const struct sctp_association *asoc, |
81 | const struct sctp_chunk *chunk, | 84 | const struct sctp_chunk *chunk, |
82 | sctp_cmd_seq_t *commands, | 85 | sctp_cmd_seq_t *commands, |
83 | struct sctp_chunk *err_chunk); | 86 | struct sctp_chunk *err_chunk); |
84 | static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep, | 87 | static sctp_disposition_t sctp_sf_do_5_2_6_stale(struct net *net, |
88 | const struct sctp_endpoint *ep, | ||
85 | const struct sctp_association *asoc, | 89 | const struct sctp_association *asoc, |
86 | const sctp_subtype_t type, | 90 | const sctp_subtype_t type, |
87 | void *arg, | 91 | void *arg, |
88 | sctp_cmd_seq_t *commands); | 92 | sctp_cmd_seq_t *commands); |
89 | static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep, | 93 | static sctp_disposition_t sctp_sf_shut_8_4_5(struct net *net, |
94 | const struct sctp_endpoint *ep, | ||
90 | const struct sctp_association *asoc, | 95 | const struct sctp_association *asoc, |
91 | const sctp_subtype_t type, | 96 | const sctp_subtype_t type, |
92 | void *arg, | 97 | void *arg, |
93 | sctp_cmd_seq_t *commands); | 98 | sctp_cmd_seq_t *commands); |
94 | static sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep, | 99 | static sctp_disposition_t sctp_sf_tabort_8_4_8(struct net *net, |
100 | const struct sctp_endpoint *ep, | ||
95 | const struct sctp_association *asoc, | 101 | const struct sctp_association *asoc, |
96 | const sctp_subtype_t type, | 102 | const sctp_subtype_t type, |
97 | void *arg, | 103 | void *arg, |
98 | sctp_cmd_seq_t *commands); | 104 | sctp_cmd_seq_t *commands); |
99 | static struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk); | 105 | static struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk); |
100 | 106 | ||
101 | static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, | 107 | static sctp_disposition_t sctp_stop_t1_and_abort(struct net *net, |
108 | sctp_cmd_seq_t *commands, | ||
102 | __be16 error, int sk_err, | 109 | __be16 error, int sk_err, |
103 | const struct sctp_association *asoc, | 110 | const struct sctp_association *asoc, |
104 | struct sctp_transport *transport); | 111 | struct sctp_transport *transport); |
105 | 112 | ||
106 | static sctp_disposition_t sctp_sf_abort_violation( | 113 | static sctp_disposition_t sctp_sf_abort_violation( |
114 | struct net *net, | ||
107 | const struct sctp_endpoint *ep, | 115 | const struct sctp_endpoint *ep, |
108 | const struct sctp_association *asoc, | 116 | const struct sctp_association *asoc, |
109 | void *arg, | 117 | void *arg, |
@@ -112,6 +120,7 @@ static sctp_disposition_t sctp_sf_abort_violation( | |||
112 | const size_t paylen); | 120 | const size_t paylen); |
113 | 121 | ||
114 | static sctp_disposition_t sctp_sf_violation_chunklen( | 122 | static sctp_disposition_t sctp_sf_violation_chunklen( |
123 | struct net *net, | ||
115 | const struct sctp_endpoint *ep, | 124 | const struct sctp_endpoint *ep, |
116 | const struct sctp_association *asoc, | 125 | const struct sctp_association *asoc, |
117 | const sctp_subtype_t type, | 126 | const sctp_subtype_t type, |
@@ -119,6 +128,7 @@ static sctp_disposition_t sctp_sf_violation_chunklen( | |||
119 | sctp_cmd_seq_t *commands); | 128 | sctp_cmd_seq_t *commands); |
120 | 129 | ||
121 | static sctp_disposition_t sctp_sf_violation_paramlen( | 130 | static sctp_disposition_t sctp_sf_violation_paramlen( |
131 | struct net *net, | ||
122 | const struct sctp_endpoint *ep, | 132 | const struct sctp_endpoint *ep, |
123 | const struct sctp_association *asoc, | 133 | const struct sctp_association *asoc, |
124 | const sctp_subtype_t type, | 134 | const sctp_subtype_t type, |
@@ -126,6 +136,7 @@ static sctp_disposition_t sctp_sf_violation_paramlen( | |||
126 | sctp_cmd_seq_t *commands); | 136 | sctp_cmd_seq_t *commands); |
127 | 137 | ||
128 | static sctp_disposition_t sctp_sf_violation_ctsn( | 138 | static sctp_disposition_t sctp_sf_violation_ctsn( |
139 | struct net *net, | ||
129 | const struct sctp_endpoint *ep, | 140 | const struct sctp_endpoint *ep, |
130 | const struct sctp_association *asoc, | 141 | const struct sctp_association *asoc, |
131 | const sctp_subtype_t type, | 142 | const sctp_subtype_t type, |
@@ -133,18 +144,21 @@ static sctp_disposition_t sctp_sf_violation_ctsn( | |||
133 | sctp_cmd_seq_t *commands); | 144 | sctp_cmd_seq_t *commands); |
134 | 145 | ||
135 | static sctp_disposition_t sctp_sf_violation_chunk( | 146 | static sctp_disposition_t sctp_sf_violation_chunk( |
147 | struct net *net, | ||
136 | const struct sctp_endpoint *ep, | 148 | const struct sctp_endpoint *ep, |
137 | const struct sctp_association *asoc, | 149 | const struct sctp_association *asoc, |
138 | const sctp_subtype_t type, | 150 | const sctp_subtype_t type, |
139 | void *arg, | 151 | void *arg, |
140 | sctp_cmd_seq_t *commands); | 152 | sctp_cmd_seq_t *commands); |
141 | 153 | ||
142 | static sctp_ierror_t sctp_sf_authenticate(const struct sctp_endpoint *ep, | 154 | static sctp_ierror_t sctp_sf_authenticate(struct net *net, |
155 | const struct sctp_endpoint *ep, | ||
143 | const struct sctp_association *asoc, | 156 | const struct sctp_association *asoc, |
144 | const sctp_subtype_t type, | 157 | const sctp_subtype_t type, |
145 | struct sctp_chunk *chunk); | 158 | struct sctp_chunk *chunk); |
146 | 159 | ||
147 | static sctp_disposition_t __sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep, | 160 | static sctp_disposition_t __sctp_sf_do_9_1_abort(struct net *net, |
161 | const struct sctp_endpoint *ep, | ||
148 | const struct sctp_association *asoc, | 162 | const struct sctp_association *asoc, |
149 | const sctp_subtype_t type, | 163 | const sctp_subtype_t type, |
150 | void *arg, | 164 | void *arg, |
@@ -204,7 +218,8 @@ sctp_chunk_length_valid(struct sctp_chunk *chunk, | |||
204 | * | 218 | * |
205 | * The return value is the disposition of the chunk. | 219 | * The return value is the disposition of the chunk. |
206 | */ | 220 | */ |
207 | sctp_disposition_t sctp_sf_do_4_C(const struct sctp_endpoint *ep, | 221 | sctp_disposition_t sctp_sf_do_4_C(struct net *net, |
222 | const struct sctp_endpoint *ep, | ||
208 | const struct sctp_association *asoc, | 223 | const struct sctp_association *asoc, |
209 | const sctp_subtype_t type, | 224 | const sctp_subtype_t type, |
210 | void *arg, | 225 | void *arg, |
@@ -214,7 +229,7 @@ sctp_disposition_t sctp_sf_do_4_C(const struct sctp_endpoint *ep, | |||
214 | struct sctp_ulpevent *ev; | 229 | struct sctp_ulpevent *ev; |
215 | 230 | ||
216 | if (!sctp_vtag_verify_either(chunk, asoc)) | 231 | if (!sctp_vtag_verify_either(chunk, asoc)) |
217 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 232 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
218 | 233 | ||
219 | /* RFC 2960 6.10 Bundling | 234 | /* RFC 2960 6.10 Bundling |
220 | * | 235 | * |
@@ -222,11 +237,11 @@ sctp_disposition_t sctp_sf_do_4_C(const struct sctp_endpoint *ep, | |||
222 | * SHUTDOWN COMPLETE with any other chunks. | 237 | * SHUTDOWN COMPLETE with any other chunks. |
223 | */ | 238 | */ |
224 | if (!chunk->singleton) | 239 | if (!chunk->singleton) |
225 | return sctp_sf_violation_chunk(ep, asoc, type, arg, commands); | 240 | return sctp_sf_violation_chunk(net, ep, asoc, type, arg, commands); |
226 | 241 | ||
227 | /* Make sure that the SHUTDOWN_COMPLETE chunk has a valid length. */ | 242 | /* Make sure that the SHUTDOWN_COMPLETE chunk has a valid length. */ |
228 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t))) | 243 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t))) |
229 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 244 | return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
230 | commands); | 245 | commands); |
231 | 246 | ||
232 | /* RFC 2960 10.2 SCTP-to-ULP | 247 | /* RFC 2960 10.2 SCTP-to-ULP |
@@ -259,8 +274,8 @@ sctp_disposition_t sctp_sf_do_4_C(const struct sctp_endpoint *ep, | |||
259 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | 274 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, |
260 | SCTP_STATE(SCTP_STATE_CLOSED)); | 275 | SCTP_STATE(SCTP_STATE_CLOSED)); |
261 | 276 | ||
262 | SCTP_INC_STATS(SCTP_MIB_SHUTDOWNS); | 277 | SCTP_INC_STATS(net, SCTP_MIB_SHUTDOWNS); |
263 | SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); | 278 | SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); |
264 | 279 | ||
265 | sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); | 280 | sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); |
266 | 281 | ||
@@ -289,7 +304,8 @@ sctp_disposition_t sctp_sf_do_4_C(const struct sctp_endpoint *ep, | |||
289 | * | 304 | * |
290 | * The return value is the disposition of the chunk. | 305 | * The return value is the disposition of the chunk. |
291 | */ | 306 | */ |
292 | sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep, | 307 | sctp_disposition_t sctp_sf_do_5_1B_init(struct net *net, |
308 | const struct sctp_endpoint *ep, | ||
293 | const struct sctp_association *asoc, | 309 | const struct sctp_association *asoc, |
294 | const sctp_subtype_t type, | 310 | const sctp_subtype_t type, |
295 | void *arg, | 311 | void *arg, |
@@ -313,21 +329,21 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep, | |||
313 | * with an INIT chunk that is bundled with other chunks. | 329 | * with an INIT chunk that is bundled with other chunks. |
314 | */ | 330 | */ |
315 | if (!chunk->singleton) | 331 | if (!chunk->singleton) |
316 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 332 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
317 | 333 | ||
318 | /* If the packet is an OOTB packet which is temporarily on the | 334 | /* If the packet is an OOTB packet which is temporarily on the |
319 | * control endpoint, respond with an ABORT. | 335 | * control endpoint, respond with an ABORT. |
320 | */ | 336 | */ |
321 | if (ep == sctp_sk((sctp_get_ctl_sock()))->ep) { | 337 | if (ep == sctp_sk(net->sctp.ctl_sock)->ep) { |
322 | SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES); | 338 | SCTP_INC_STATS(net, SCTP_MIB_OUTOFBLUES); |
323 | return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands); | 339 | return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands); |
324 | } | 340 | } |
325 | 341 | ||
326 | /* 3.1 A packet containing an INIT chunk MUST have a zero Verification | 342 | /* 3.1 A packet containing an INIT chunk MUST have a zero Verification |
327 | * Tag. | 343 | * Tag. |
328 | */ | 344 | */ |
329 | if (chunk->sctp_hdr->vtag != 0) | 345 | if (chunk->sctp_hdr->vtag != 0) |
330 | return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands); | 346 | return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands); |
331 | 347 | ||
332 | /* Make sure that the INIT chunk has a valid length. | 348 | /* Make sure that the INIT chunk has a valid length. |
333 | * Normally, this would cause an ABORT with a Protocol Violation | 349 | * Normally, this would cause an ABORT with a Protocol Violation |
@@ -335,7 +351,7 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep, | |||
335 | * just discard the packet. | 351 | * just discard the packet. |
336 | */ | 352 | */ |
337 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_init_chunk_t))) | 353 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_init_chunk_t))) |
338 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 354 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
339 | 355 | ||
340 | /* If the INIT is coming toward a closing socket, we'll send back | 356 | /* If the INIT is coming toward a closing socket, we'll send back |
341 | * and ABORT. Essentially, this catches the race of INIT being | 357 | * and ABORT. Essentially, this catches the race of INIT being |
@@ -344,18 +360,18 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep, | |||
344 | * can treat this OOTB | 360 | * can treat this OOTB |
345 | */ | 361 | */ |
346 | if (sctp_sstate(ep->base.sk, CLOSING)) | 362 | if (sctp_sstate(ep->base.sk, CLOSING)) |
347 | return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands); | 363 | return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands); |
348 | 364 | ||
349 | /* Verify the INIT chunk before processing it. */ | 365 | /* Verify the INIT chunk before processing it. */ |
350 | err_chunk = NULL; | 366 | err_chunk = NULL; |
351 | if (!sctp_verify_init(asoc, chunk->chunk_hdr->type, | 367 | if (!sctp_verify_init(net, asoc, chunk->chunk_hdr->type, |
352 | (sctp_init_chunk_t *)chunk->chunk_hdr, chunk, | 368 | (sctp_init_chunk_t *)chunk->chunk_hdr, chunk, |
353 | &err_chunk)) { | 369 | &err_chunk)) { |
354 | /* This chunk contains fatal error. It is to be discarded. | 370 | /* This chunk contains fatal error. It is to be discarded. |
355 | * Send an ABORT, with causes if there is any. | 371 | * Send an ABORT, with causes if there is any. |
356 | */ | 372 | */ |
357 | if (err_chunk) { | 373 | if (err_chunk) { |
358 | packet = sctp_abort_pkt_new(ep, asoc, arg, | 374 | packet = sctp_abort_pkt_new(net, ep, asoc, arg, |
359 | (__u8 *)(err_chunk->chunk_hdr) + | 375 | (__u8 *)(err_chunk->chunk_hdr) + |
360 | sizeof(sctp_chunkhdr_t), | 376 | sizeof(sctp_chunkhdr_t), |
361 | ntohs(err_chunk->chunk_hdr->length) - | 377 | ntohs(err_chunk->chunk_hdr->length) - |
@@ -366,13 +382,13 @@ sctp_disposition_t sctp_sf_do_5_1B_init(const struct sctp_endpoint *ep, | |||
366 | if (packet) { | 382 | if (packet) { |
367 | sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, | 383 | sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, |
368 | SCTP_PACKET(packet)); | 384 | SCTP_PACKET(packet)); |
369 | SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); | 385 | SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); |
370 | return SCTP_DISPOSITION_CONSUME; | 386 | return SCTP_DISPOSITION_CONSUME; |
371 | } else { | 387 | } else { |
372 | return SCTP_DISPOSITION_NOMEM; | 388 | return SCTP_DISPOSITION_NOMEM; |
373 | } | 389 | } |
374 | } else { | 390 | } else { |
375 | return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, | 391 | return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, |
376 | commands); | 392 | commands); |
377 | } | 393 | } |
378 | } | 394 | } |
@@ -484,7 +500,8 @@ nomem: | |||
484 | * | 500 | * |
485 | * The return value is the disposition of the chunk. | 501 | * The return value is the disposition of the chunk. |
486 | */ | 502 | */ |
487 | sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep, | 503 | sctp_disposition_t sctp_sf_do_5_1C_ack(struct net *net, |
504 | const struct sctp_endpoint *ep, | ||
488 | const struct sctp_association *asoc, | 505 | const struct sctp_association *asoc, |
489 | const sctp_subtype_t type, | 506 | const sctp_subtype_t type, |
490 | void *arg, | 507 | void *arg, |
@@ -496,25 +513,25 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep, | |||
496 | struct sctp_packet *packet; | 513 | struct sctp_packet *packet; |
497 | 514 | ||
498 | if (!sctp_vtag_verify(chunk, asoc)) | 515 | if (!sctp_vtag_verify(chunk, asoc)) |
499 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 516 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
500 | 517 | ||
501 | /* 6.10 Bundling | 518 | /* 6.10 Bundling |
502 | * An endpoint MUST NOT bundle INIT, INIT ACK or | 519 | * An endpoint MUST NOT bundle INIT, INIT ACK or |
503 | * SHUTDOWN COMPLETE with any other chunks. | 520 | * SHUTDOWN COMPLETE with any other chunks. |
504 | */ | 521 | */ |
505 | if (!chunk->singleton) | 522 | if (!chunk->singleton) |
506 | return sctp_sf_violation_chunk(ep, asoc, type, arg, commands); | 523 | return sctp_sf_violation_chunk(net, ep, asoc, type, arg, commands); |
507 | 524 | ||
508 | /* Make sure that the INIT-ACK chunk has a valid length */ | 525 | /* Make sure that the INIT-ACK chunk has a valid length */ |
509 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_initack_chunk_t))) | 526 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_initack_chunk_t))) |
510 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 527 | return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
511 | commands); | 528 | commands); |
512 | /* Grab the INIT header. */ | 529 | /* Grab the INIT header. */ |
513 | chunk->subh.init_hdr = (sctp_inithdr_t *) chunk->skb->data; | 530 | chunk->subh.init_hdr = (sctp_inithdr_t *) chunk->skb->data; |
514 | 531 | ||
515 | /* Verify the INIT chunk before processing it. */ | 532 | /* Verify the INIT chunk before processing it. */ |
516 | err_chunk = NULL; | 533 | err_chunk = NULL; |
517 | if (!sctp_verify_init(asoc, chunk->chunk_hdr->type, | 534 | if (!sctp_verify_init(net, asoc, chunk->chunk_hdr->type, |
518 | (sctp_init_chunk_t *)chunk->chunk_hdr, chunk, | 535 | (sctp_init_chunk_t *)chunk->chunk_hdr, chunk, |
519 | &err_chunk)) { | 536 | &err_chunk)) { |
520 | 537 | ||
@@ -526,7 +543,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep, | |||
526 | * the association. | 543 | * the association. |
527 | */ | 544 | */ |
528 | if (err_chunk) { | 545 | if (err_chunk) { |
529 | packet = sctp_abort_pkt_new(ep, asoc, arg, | 546 | packet = sctp_abort_pkt_new(net, ep, asoc, arg, |
530 | (__u8 *)(err_chunk->chunk_hdr) + | 547 | (__u8 *)(err_chunk->chunk_hdr) + |
531 | sizeof(sctp_chunkhdr_t), | 548 | sizeof(sctp_chunkhdr_t), |
532 | ntohs(err_chunk->chunk_hdr->length) - | 549 | ntohs(err_chunk->chunk_hdr->length) - |
@@ -537,7 +554,7 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep, | |||
537 | if (packet) { | 554 | if (packet) { |
538 | sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, | 555 | sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, |
539 | SCTP_PACKET(packet)); | 556 | SCTP_PACKET(packet)); |
540 | SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); | 557 | SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); |
541 | error = SCTP_ERROR_INV_PARAM; | 558 | error = SCTP_ERROR_INV_PARAM; |
542 | } | 559 | } |
543 | } | 560 | } |
@@ -554,10 +571,10 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep, | |||
554 | * was malformed. | 571 | * was malformed. |
555 | */ | 572 | */ |
556 | if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) | 573 | if (sctp_auth_recv_cid(SCTP_CID_ABORT, asoc)) |
557 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 574 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
558 | 575 | ||
559 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 576 | SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); |
560 | return sctp_stop_t1_and_abort(commands, error, ECONNREFUSED, | 577 | return sctp_stop_t1_and_abort(net, commands, error, ECONNREFUSED, |
561 | asoc, chunk->transport); | 578 | asoc, chunk->transport); |
562 | } | 579 | } |
563 | 580 | ||
@@ -633,7 +650,8 @@ sctp_disposition_t sctp_sf_do_5_1C_ack(const struct sctp_endpoint *ep, | |||
633 | * | 650 | * |
634 | * The return value is the disposition of the chunk. | 651 | * The return value is the disposition of the chunk. |
635 | */ | 652 | */ |
636 | sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, | 653 | sctp_disposition_t sctp_sf_do_5_1D_ce(struct net *net, |
654 | const struct sctp_endpoint *ep, | ||
637 | const struct sctp_association *asoc, | 655 | const struct sctp_association *asoc, |
638 | const sctp_subtype_t type, void *arg, | 656 | const sctp_subtype_t type, void *arg, |
639 | sctp_cmd_seq_t *commands) | 657 | sctp_cmd_seq_t *commands) |
@@ -650,9 +668,9 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, | |||
650 | /* If the packet is an OOTB packet which is temporarily on the | 668 | /* If the packet is an OOTB packet which is temporarily on the |
651 | * control endpoint, respond with an ABORT. | 669 | * control endpoint, respond with an ABORT. |
652 | */ | 670 | */ |
653 | if (ep == sctp_sk((sctp_get_ctl_sock()))->ep) { | 671 | if (ep == sctp_sk(net->sctp.ctl_sock)->ep) { |
654 | SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES); | 672 | SCTP_INC_STATS(net, SCTP_MIB_OUTOFBLUES); |
655 | return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands); | 673 | return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands); |
656 | } | 674 | } |
657 | 675 | ||
658 | /* Make sure that the COOKIE_ECHO chunk has a valid length. | 676 | /* Make sure that the COOKIE_ECHO chunk has a valid length. |
@@ -661,7 +679,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, | |||
661 | * in sctp_unpack_cookie(). | 679 | * in sctp_unpack_cookie(). |
662 | */ | 680 | */ |
663 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t))) | 681 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t))) |
664 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 682 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
665 | 683 | ||
666 | /* If the endpoint is not listening or if the number of associations | 684 | /* If the endpoint is not listening or if the number of associations |
667 | * on the TCP-style socket exceed the max backlog, respond with an | 685 | * on the TCP-style socket exceed the max backlog, respond with an |
@@ -670,7 +688,7 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, | |||
670 | sk = ep->base.sk; | 688 | sk = ep->base.sk; |
671 | if (!sctp_sstate(sk, LISTENING) || | 689 | if (!sctp_sstate(sk, LISTENING) || |
672 | (sctp_style(sk, TCP) && sk_acceptq_is_full(sk))) | 690 | (sctp_style(sk, TCP) && sk_acceptq_is_full(sk))) |
673 | return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands); | 691 | return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands); |
674 | 692 | ||
675 | /* "Decode" the chunk. We have no optional parameters so we | 693 | /* "Decode" the chunk. We have no optional parameters so we |
676 | * are in good shape. | 694 | * are in good shape. |
@@ -703,13 +721,13 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, | |||
703 | goto nomem; | 721 | goto nomem; |
704 | 722 | ||
705 | case -SCTP_IERROR_STALE_COOKIE: | 723 | case -SCTP_IERROR_STALE_COOKIE: |
706 | sctp_send_stale_cookie_err(ep, asoc, chunk, commands, | 724 | sctp_send_stale_cookie_err(net, ep, asoc, chunk, commands, |
707 | err_chk_p); | 725 | err_chk_p); |
708 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 726 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
709 | 727 | ||
710 | case -SCTP_IERROR_BAD_SIG: | 728 | case -SCTP_IERROR_BAD_SIG: |
711 | default: | 729 | default: |
712 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 730 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
713 | } | 731 | } |
714 | } | 732 | } |
715 | 733 | ||
@@ -756,14 +774,14 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, | |||
756 | skb_pull(chunk->auth_chunk, sizeof(sctp_chunkhdr_t)); | 774 | skb_pull(chunk->auth_chunk, sizeof(sctp_chunkhdr_t)); |
757 | auth.transport = chunk->transport; | 775 | auth.transport = chunk->transport; |
758 | 776 | ||
759 | ret = sctp_sf_authenticate(ep, new_asoc, type, &auth); | 777 | ret = sctp_sf_authenticate(net, ep, new_asoc, type, &auth); |
760 | 778 | ||
761 | /* We can now safely free the auth_chunk clone */ | 779 | /* We can now safely free the auth_chunk clone */ |
762 | kfree_skb(chunk->auth_chunk); | 780 | kfree_skb(chunk->auth_chunk); |
763 | 781 | ||
764 | if (ret != SCTP_IERROR_NO_ERROR) { | 782 | if (ret != SCTP_IERROR_NO_ERROR) { |
765 | sctp_association_free(new_asoc); | 783 | sctp_association_free(new_asoc); |
766 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 784 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
767 | } | 785 | } |
768 | } | 786 | } |
769 | 787 | ||
@@ -804,8 +822,8 @@ sctp_disposition_t sctp_sf_do_5_1D_ce(const struct sctp_endpoint *ep, | |||
804 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc)); | 822 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_ASOC, SCTP_ASOC(new_asoc)); |
805 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | 823 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, |
806 | SCTP_STATE(SCTP_STATE_ESTABLISHED)); | 824 | SCTP_STATE(SCTP_STATE_ESTABLISHED)); |
807 | SCTP_INC_STATS(SCTP_MIB_CURRESTAB); | 825 | SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB); |
808 | SCTP_INC_STATS(SCTP_MIB_PASSIVEESTABS); | 826 | SCTP_INC_STATS(net, SCTP_MIB_PASSIVEESTABS); |
809 | sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL()); | 827 | sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL()); |
810 | 828 | ||
811 | if (new_asoc->autoclose) | 829 | if (new_asoc->autoclose) |
@@ -856,7 +874,8 @@ nomem: | |||
856 | * | 874 | * |
857 | * The return value is the disposition of the chunk. | 875 | * The return value is the disposition of the chunk. |
858 | */ | 876 | */ |
859 | sctp_disposition_t sctp_sf_do_5_1E_ca(const struct sctp_endpoint *ep, | 877 | sctp_disposition_t sctp_sf_do_5_1E_ca(struct net *net, |
878 | const struct sctp_endpoint *ep, | ||
860 | const struct sctp_association *asoc, | 879 | const struct sctp_association *asoc, |
861 | const sctp_subtype_t type, void *arg, | 880 | const sctp_subtype_t type, void *arg, |
862 | sctp_cmd_seq_t *commands) | 881 | sctp_cmd_seq_t *commands) |
@@ -865,13 +884,13 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const struct sctp_endpoint *ep, | |||
865 | struct sctp_ulpevent *ev; | 884 | struct sctp_ulpevent *ev; |
866 | 885 | ||
867 | if (!sctp_vtag_verify(chunk, asoc)) | 886 | if (!sctp_vtag_verify(chunk, asoc)) |
868 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 887 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
869 | 888 | ||
870 | /* Verify that the chunk length for the COOKIE-ACK is OK. | 889 | /* Verify that the chunk length for the COOKIE-ACK is OK. |
871 | * If we don't do this, any bundled chunks may be junked. | 890 | * If we don't do this, any bundled chunks may be junked. |
872 | */ | 891 | */ |
873 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t))) | 892 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t))) |
874 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 893 | return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
875 | commands); | 894 | commands); |
876 | 895 | ||
877 | /* Reset init error count upon receipt of COOKIE-ACK, | 896 | /* Reset init error count upon receipt of COOKIE-ACK, |
@@ -892,8 +911,8 @@ sctp_disposition_t sctp_sf_do_5_1E_ca(const struct sctp_endpoint *ep, | |||
892 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); | 911 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); |
893 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | 912 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, |
894 | SCTP_STATE(SCTP_STATE_ESTABLISHED)); | 913 | SCTP_STATE(SCTP_STATE_ESTABLISHED)); |
895 | SCTP_INC_STATS(SCTP_MIB_CURRESTAB); | 914 | SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB); |
896 | SCTP_INC_STATS(SCTP_MIB_ACTIVEESTABS); | 915 | SCTP_INC_STATS(net, SCTP_MIB_ACTIVEESTABS); |
897 | sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL()); | 916 | sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL()); |
898 | if (asoc->autoclose) | 917 | if (asoc->autoclose) |
899 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, | 918 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_START, |
@@ -958,7 +977,8 @@ static sctp_disposition_t sctp_sf_heartbeat(const struct sctp_endpoint *ep, | |||
958 | } | 977 | } |
959 | 978 | ||
960 | /* Generate a HEARTBEAT packet on the given transport. */ | 979 | /* Generate a HEARTBEAT packet on the given transport. */ |
961 | sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep, | 980 | sctp_disposition_t sctp_sf_sendbeat_8_3(struct net *net, |
981 | const struct sctp_endpoint *ep, | ||
962 | const struct sctp_association *asoc, | 982 | const struct sctp_association *asoc, |
963 | const sctp_subtype_t type, | 983 | const sctp_subtype_t type, |
964 | void *arg, | 984 | void *arg, |
@@ -972,8 +992,8 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep, | |||
972 | /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ | 992 | /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ |
973 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 993 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
974 | SCTP_PERR(SCTP_ERROR_NO_ERROR)); | 994 | SCTP_PERR(SCTP_ERROR_NO_ERROR)); |
975 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 995 | SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); |
976 | SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); | 996 | SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); |
977 | return SCTP_DISPOSITION_DELETE_TCB; | 997 | return SCTP_DISPOSITION_DELETE_TCB; |
978 | } | 998 | } |
979 | 999 | ||
@@ -1028,7 +1048,8 @@ sctp_disposition_t sctp_sf_sendbeat_8_3(const struct sctp_endpoint *ep, | |||
1028 | * | 1048 | * |
1029 | * The return value is the disposition of the chunk. | 1049 | * The return value is the disposition of the chunk. |
1030 | */ | 1050 | */ |
1031 | sctp_disposition_t sctp_sf_beat_8_3(const struct sctp_endpoint *ep, | 1051 | sctp_disposition_t sctp_sf_beat_8_3(struct net *net, |
1052 | const struct sctp_endpoint *ep, | ||
1032 | const struct sctp_association *asoc, | 1053 | const struct sctp_association *asoc, |
1033 | const sctp_subtype_t type, | 1054 | const sctp_subtype_t type, |
1034 | void *arg, | 1055 | void *arg, |
@@ -1039,11 +1060,11 @@ sctp_disposition_t sctp_sf_beat_8_3(const struct sctp_endpoint *ep, | |||
1039 | size_t paylen = 0; | 1060 | size_t paylen = 0; |
1040 | 1061 | ||
1041 | if (!sctp_vtag_verify(chunk, asoc)) | 1062 | if (!sctp_vtag_verify(chunk, asoc)) |
1042 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 1063 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
1043 | 1064 | ||
1044 | /* Make sure that the HEARTBEAT chunk has a valid length. */ | 1065 | /* Make sure that the HEARTBEAT chunk has a valid length. */ |
1045 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_heartbeat_chunk_t))) | 1066 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_heartbeat_chunk_t))) |
1046 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 1067 | return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
1047 | commands); | 1068 | commands); |
1048 | 1069 | ||
1049 | /* 8.3 The receiver of the HEARTBEAT should immediately | 1070 | /* 8.3 The receiver of the HEARTBEAT should immediately |
@@ -1095,7 +1116,8 @@ nomem: | |||
1095 | * | 1116 | * |
1096 | * The return value is the disposition of the chunk. | 1117 | * The return value is the disposition of the chunk. |
1097 | */ | 1118 | */ |
1098 | sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep, | 1119 | sctp_disposition_t sctp_sf_backbeat_8_3(struct net *net, |
1120 | const struct sctp_endpoint *ep, | ||
1099 | const struct sctp_association *asoc, | 1121 | const struct sctp_association *asoc, |
1100 | const sctp_subtype_t type, | 1122 | const sctp_subtype_t type, |
1101 | void *arg, | 1123 | void *arg, |
@@ -1108,12 +1130,12 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep, | |||
1108 | unsigned long max_interval; | 1130 | unsigned long max_interval; |
1109 | 1131 | ||
1110 | if (!sctp_vtag_verify(chunk, asoc)) | 1132 | if (!sctp_vtag_verify(chunk, asoc)) |
1111 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 1133 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
1112 | 1134 | ||
1113 | /* Make sure that the HEARTBEAT-ACK chunk has a valid length. */ | 1135 | /* Make sure that the HEARTBEAT-ACK chunk has a valid length. */ |
1114 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t) + | 1136 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t) + |
1115 | sizeof(sctp_sender_hb_info_t))) | 1137 | sizeof(sctp_sender_hb_info_t))) |
1116 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 1138 | return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
1117 | commands); | 1139 | commands); |
1118 | 1140 | ||
1119 | hbinfo = (sctp_sender_hb_info_t *) chunk->skb->data; | 1141 | hbinfo = (sctp_sender_hb_info_t *) chunk->skb->data; |
@@ -1171,7 +1193,7 @@ sctp_disposition_t sctp_sf_backbeat_8_3(const struct sctp_endpoint *ep, | |||
1171 | /* Helper function to send out an abort for the restart | 1193 | /* Helper function to send out an abort for the restart |
1172 | * condition. | 1194 | * condition. |
1173 | */ | 1195 | */ |
1174 | static int sctp_sf_send_restart_abort(union sctp_addr *ssa, | 1196 | static int sctp_sf_send_restart_abort(struct net *net, union sctp_addr *ssa, |
1175 | struct sctp_chunk *init, | 1197 | struct sctp_chunk *init, |
1176 | sctp_cmd_seq_t *commands) | 1198 | sctp_cmd_seq_t *commands) |
1177 | { | 1199 | { |
@@ -1197,18 +1219,18 @@ static int sctp_sf_send_restart_abort(union sctp_addr *ssa, | |||
1197 | errhdr->length = htons(len); | 1219 | errhdr->length = htons(len); |
1198 | 1220 | ||
1199 | /* Assign to the control socket. */ | 1221 | /* Assign to the control socket. */ |
1200 | ep = sctp_sk((sctp_get_ctl_sock()))->ep; | 1222 | ep = sctp_sk(net->sctp.ctl_sock)->ep; |
1201 | 1223 | ||
1202 | /* Association is NULL since this may be a restart attack and we | 1224 | /* Association is NULL since this may be a restart attack and we |
1203 | * want to send back the attacker's vtag. | 1225 | * want to send back the attacker's vtag. |
1204 | */ | 1226 | */ |
1205 | pkt = sctp_abort_pkt_new(ep, NULL, init, errhdr, len); | 1227 | pkt = sctp_abort_pkt_new(net, ep, NULL, init, errhdr, len); |
1206 | 1228 | ||
1207 | if (!pkt) | 1229 | if (!pkt) |
1208 | goto out; | 1230 | goto out; |
1209 | sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, SCTP_PACKET(pkt)); | 1231 | sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, SCTP_PACKET(pkt)); |
1210 | 1232 | ||
1211 | SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); | 1233 | SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); |
1212 | 1234 | ||
1213 | /* Discard the rest of the inbound packet. */ | 1235 | /* Discard the rest of the inbound packet. */ |
1214 | sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL()); | 1236 | sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL()); |
@@ -1240,6 +1262,7 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc, | |||
1240 | struct sctp_chunk *init, | 1262 | struct sctp_chunk *init, |
1241 | sctp_cmd_seq_t *commands) | 1263 | sctp_cmd_seq_t *commands) |
1242 | { | 1264 | { |
1265 | struct net *net = sock_net(new_asoc->base.sk); | ||
1243 | struct sctp_transport *new_addr; | 1266 | struct sctp_transport *new_addr; |
1244 | int ret = 1; | 1267 | int ret = 1; |
1245 | 1268 | ||
@@ -1258,7 +1281,7 @@ static int sctp_sf_check_restart_addrs(const struct sctp_association *new_asoc, | |||
1258 | transports) { | 1281 | transports) { |
1259 | if (!list_has_sctp_addr(&asoc->peer.transport_addr_list, | 1282 | if (!list_has_sctp_addr(&asoc->peer.transport_addr_list, |
1260 | &new_addr->ipaddr)) { | 1283 | &new_addr->ipaddr)) { |
1261 | sctp_sf_send_restart_abort(&new_addr->ipaddr, init, | 1284 | sctp_sf_send_restart_abort(net, &new_addr->ipaddr, init, |
1262 | commands); | 1285 | commands); |
1263 | ret = 0; | 1286 | ret = 0; |
1264 | break; | 1287 | break; |
@@ -1358,6 +1381,7 @@ static char sctp_tietags_compare(struct sctp_association *new_asoc, | |||
1358 | * chunk handling. | 1381 | * chunk handling. |
1359 | */ | 1382 | */ |
1360 | static sctp_disposition_t sctp_sf_do_unexpected_init( | 1383 | static sctp_disposition_t sctp_sf_do_unexpected_init( |
1384 | struct net *net, | ||
1361 | const struct sctp_endpoint *ep, | 1385 | const struct sctp_endpoint *ep, |
1362 | const struct sctp_association *asoc, | 1386 | const struct sctp_association *asoc, |
1363 | const sctp_subtype_t type, | 1387 | const sctp_subtype_t type, |
@@ -1382,20 +1406,20 @@ static sctp_disposition_t sctp_sf_do_unexpected_init( | |||
1382 | * with an INIT chunk that is bundled with other chunks. | 1406 | * with an INIT chunk that is bundled with other chunks. |
1383 | */ | 1407 | */ |
1384 | if (!chunk->singleton) | 1408 | if (!chunk->singleton) |
1385 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 1409 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
1386 | 1410 | ||
1387 | /* 3.1 A packet containing an INIT chunk MUST have a zero Verification | 1411 | /* 3.1 A packet containing an INIT chunk MUST have a zero Verification |
1388 | * Tag. | 1412 | * Tag. |
1389 | */ | 1413 | */ |
1390 | if (chunk->sctp_hdr->vtag != 0) | 1414 | if (chunk->sctp_hdr->vtag != 0) |
1391 | return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands); | 1415 | return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands); |
1392 | 1416 | ||
1393 | /* Make sure that the INIT chunk has a valid length. | 1417 | /* Make sure that the INIT chunk has a valid length. |
1394 | * In this case, we generate a protocol violation since we have | 1418 | * In this case, we generate a protocol violation since we have |
1395 | * an association established. | 1419 | * an association established. |
1396 | */ | 1420 | */ |
1397 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_init_chunk_t))) | 1421 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_init_chunk_t))) |
1398 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 1422 | return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
1399 | commands); | 1423 | commands); |
1400 | /* Grab the INIT header. */ | 1424 | /* Grab the INIT header. */ |
1401 | chunk->subh.init_hdr = (sctp_inithdr_t *) chunk->skb->data; | 1425 | chunk->subh.init_hdr = (sctp_inithdr_t *) chunk->skb->data; |
@@ -1405,14 +1429,14 @@ static sctp_disposition_t sctp_sf_do_unexpected_init( | |||
1405 | 1429 | ||
1406 | /* Verify the INIT chunk before processing it. */ | 1430 | /* Verify the INIT chunk before processing it. */ |
1407 | err_chunk = NULL; | 1431 | err_chunk = NULL; |
1408 | if (!sctp_verify_init(asoc, chunk->chunk_hdr->type, | 1432 | if (!sctp_verify_init(net, asoc, chunk->chunk_hdr->type, |
1409 | (sctp_init_chunk_t *)chunk->chunk_hdr, chunk, | 1433 | (sctp_init_chunk_t *)chunk->chunk_hdr, chunk, |
1410 | &err_chunk)) { | 1434 | &err_chunk)) { |
1411 | /* This chunk contains fatal error. It is to be discarded. | 1435 | /* This chunk contains fatal error. It is to be discarded. |
1412 | * Send an ABORT, with causes if there is any. | 1436 | * Send an ABORT, with causes if there is any. |
1413 | */ | 1437 | */ |
1414 | if (err_chunk) { | 1438 | if (err_chunk) { |
1415 | packet = sctp_abort_pkt_new(ep, asoc, arg, | 1439 | packet = sctp_abort_pkt_new(net, ep, asoc, arg, |
1416 | (__u8 *)(err_chunk->chunk_hdr) + | 1440 | (__u8 *)(err_chunk->chunk_hdr) + |
1417 | sizeof(sctp_chunkhdr_t), | 1441 | sizeof(sctp_chunkhdr_t), |
1418 | ntohs(err_chunk->chunk_hdr->length) - | 1442 | ntohs(err_chunk->chunk_hdr->length) - |
@@ -1421,14 +1445,14 @@ static sctp_disposition_t sctp_sf_do_unexpected_init( | |||
1421 | if (packet) { | 1445 | if (packet) { |
1422 | sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, | 1446 | sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, |
1423 | SCTP_PACKET(packet)); | 1447 | SCTP_PACKET(packet)); |
1424 | SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); | 1448 | SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); |
1425 | retval = SCTP_DISPOSITION_CONSUME; | 1449 | retval = SCTP_DISPOSITION_CONSUME; |
1426 | } else { | 1450 | } else { |
1427 | retval = SCTP_DISPOSITION_NOMEM; | 1451 | retval = SCTP_DISPOSITION_NOMEM; |
1428 | } | 1452 | } |
1429 | goto cleanup; | 1453 | goto cleanup; |
1430 | } else { | 1454 | } else { |
1431 | return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, | 1455 | return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, |
1432 | commands); | 1456 | commands); |
1433 | } | 1457 | } |
1434 | } | 1458 | } |
@@ -1570,7 +1594,8 @@ cleanup: | |||
1570 | * | 1594 | * |
1571 | * The return value is the disposition of the chunk. | 1595 | * The return value is the disposition of the chunk. |
1572 | */ | 1596 | */ |
1573 | sctp_disposition_t sctp_sf_do_5_2_1_siminit(const struct sctp_endpoint *ep, | 1597 | sctp_disposition_t sctp_sf_do_5_2_1_siminit(struct net *net, |
1598 | const struct sctp_endpoint *ep, | ||
1574 | const struct sctp_association *asoc, | 1599 | const struct sctp_association *asoc, |
1575 | const sctp_subtype_t type, | 1600 | const sctp_subtype_t type, |
1576 | void *arg, | 1601 | void *arg, |
@@ -1579,7 +1604,7 @@ sctp_disposition_t sctp_sf_do_5_2_1_siminit(const struct sctp_endpoint *ep, | |||
1579 | /* Call helper to do the real work for both simulataneous and | 1604 | /* Call helper to do the real work for both simulataneous and |
1580 | * duplicate INIT chunk handling. | 1605 | * duplicate INIT chunk handling. |
1581 | */ | 1606 | */ |
1582 | return sctp_sf_do_unexpected_init(ep, asoc, type, arg, commands); | 1607 | return sctp_sf_do_unexpected_init(net, ep, asoc, type, arg, commands); |
1583 | } | 1608 | } |
1584 | 1609 | ||
1585 | /* | 1610 | /* |
@@ -1623,7 +1648,8 @@ sctp_disposition_t sctp_sf_do_5_2_1_siminit(const struct sctp_endpoint *ep, | |||
1623 | * | 1648 | * |
1624 | * The return value is the disposition of the chunk. | 1649 | * The return value is the disposition of the chunk. |
1625 | */ | 1650 | */ |
1626 | sctp_disposition_t sctp_sf_do_5_2_2_dupinit(const struct sctp_endpoint *ep, | 1651 | sctp_disposition_t sctp_sf_do_5_2_2_dupinit(struct net *net, |
1652 | const struct sctp_endpoint *ep, | ||
1627 | const struct sctp_association *asoc, | 1653 | const struct sctp_association *asoc, |
1628 | const sctp_subtype_t type, | 1654 | const sctp_subtype_t type, |
1629 | void *arg, | 1655 | void *arg, |
@@ -1632,7 +1658,7 @@ sctp_disposition_t sctp_sf_do_5_2_2_dupinit(const struct sctp_endpoint *ep, | |||
1632 | /* Call helper to do the real work for both simulataneous and | 1658 | /* Call helper to do the real work for both simulataneous and |
1633 | * duplicate INIT chunk handling. | 1659 | * duplicate INIT chunk handling. |
1634 | */ | 1660 | */ |
1635 | return sctp_sf_do_unexpected_init(ep, asoc, type, arg, commands); | 1661 | return sctp_sf_do_unexpected_init(net, ep, asoc, type, arg, commands); |
1636 | } | 1662 | } |
1637 | 1663 | ||
1638 | 1664 | ||
@@ -1645,7 +1671,8 @@ sctp_disposition_t sctp_sf_do_5_2_2_dupinit(const struct sctp_endpoint *ep, | |||
1645 | * An unexpected INIT ACK usually indicates the processing of an old or | 1671 | * An unexpected INIT ACK usually indicates the processing of an old or |
1646 | * duplicated INIT chunk. | 1672 | * duplicated INIT chunk. |
1647 | */ | 1673 | */ |
1648 | sctp_disposition_t sctp_sf_do_5_2_3_initack(const struct sctp_endpoint *ep, | 1674 | sctp_disposition_t sctp_sf_do_5_2_3_initack(struct net *net, |
1675 | const struct sctp_endpoint *ep, | ||
1649 | const struct sctp_association *asoc, | 1676 | const struct sctp_association *asoc, |
1650 | const sctp_subtype_t type, | 1677 | const sctp_subtype_t type, |
1651 | void *arg, sctp_cmd_seq_t *commands) | 1678 | void *arg, sctp_cmd_seq_t *commands) |
@@ -1653,10 +1680,10 @@ sctp_disposition_t sctp_sf_do_5_2_3_initack(const struct sctp_endpoint *ep, | |||
1653 | /* Per the above section, we'll discard the chunk if we have an | 1680 | /* Per the above section, we'll discard the chunk if we have an |
1654 | * endpoint. If this is an OOTB INIT-ACK, treat it as such. | 1681 | * endpoint. If this is an OOTB INIT-ACK, treat it as such. |
1655 | */ | 1682 | */ |
1656 | if (ep == sctp_sk((sctp_get_ctl_sock()))->ep) | 1683 | if (ep == sctp_sk(net->sctp.ctl_sock)->ep) |
1657 | return sctp_sf_ootb(ep, asoc, type, arg, commands); | 1684 | return sctp_sf_ootb(net, ep, asoc, type, arg, commands); |
1658 | else | 1685 | else |
1659 | return sctp_sf_discard_chunk(ep, asoc, type, arg, commands); | 1686 | return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands); |
1660 | } | 1687 | } |
1661 | 1688 | ||
1662 | /* Unexpected COOKIE-ECHO handler for peer restart (Table 2, action 'A') | 1689 | /* Unexpected COOKIE-ECHO handler for peer restart (Table 2, action 'A') |
@@ -1664,7 +1691,8 @@ sctp_disposition_t sctp_sf_do_5_2_3_initack(const struct sctp_endpoint *ep, | |||
1664 | * Section 5.2.4 | 1691 | * Section 5.2.4 |
1665 | * A) In this case, the peer may have restarted. | 1692 | * A) In this case, the peer may have restarted. |
1666 | */ | 1693 | */ |
1667 | static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep, | 1694 | static sctp_disposition_t sctp_sf_do_dupcook_a(struct net *net, |
1695 | const struct sctp_endpoint *ep, | ||
1668 | const struct sctp_association *asoc, | 1696 | const struct sctp_association *asoc, |
1669 | struct sctp_chunk *chunk, | 1697 | struct sctp_chunk *chunk, |
1670 | sctp_cmd_seq_t *commands, | 1698 | sctp_cmd_seq_t *commands, |
@@ -1700,7 +1728,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_a(const struct sctp_endpoint *ep, | |||
1700 | * its peer. | 1728 | * its peer. |
1701 | */ | 1729 | */ |
1702 | if (sctp_state(asoc, SHUTDOWN_ACK_SENT)) { | 1730 | if (sctp_state(asoc, SHUTDOWN_ACK_SENT)) { |
1703 | disposition = sctp_sf_do_9_2_reshutack(ep, asoc, | 1731 | disposition = sctp_sf_do_9_2_reshutack(net, ep, asoc, |
1704 | SCTP_ST_CHUNK(chunk->chunk_hdr->type), | 1732 | SCTP_ST_CHUNK(chunk->chunk_hdr->type), |
1705 | chunk, commands); | 1733 | chunk, commands); |
1706 | if (SCTP_DISPOSITION_NOMEM == disposition) | 1734 | if (SCTP_DISPOSITION_NOMEM == disposition) |
@@ -1763,7 +1791,8 @@ nomem: | |||
1763 | * after responding to the local endpoint's INIT | 1791 | * after responding to the local endpoint's INIT |
1764 | */ | 1792 | */ |
1765 | /* This case represents an initialization collision. */ | 1793 | /* This case represents an initialization collision. */ |
1766 | static sctp_disposition_t sctp_sf_do_dupcook_b(const struct sctp_endpoint *ep, | 1794 | static sctp_disposition_t sctp_sf_do_dupcook_b(struct net *net, |
1795 | const struct sctp_endpoint *ep, | ||
1767 | const struct sctp_association *asoc, | 1796 | const struct sctp_association *asoc, |
1768 | struct sctp_chunk *chunk, | 1797 | struct sctp_chunk *chunk, |
1769 | sctp_cmd_seq_t *commands, | 1798 | sctp_cmd_seq_t *commands, |
@@ -1784,7 +1813,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_b(const struct sctp_endpoint *ep, | |||
1784 | sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc)); | 1813 | sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc)); |
1785 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | 1814 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, |
1786 | SCTP_STATE(SCTP_STATE_ESTABLISHED)); | 1815 | SCTP_STATE(SCTP_STATE_ESTABLISHED)); |
1787 | SCTP_INC_STATS(SCTP_MIB_CURRESTAB); | 1816 | SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB); |
1788 | sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL()); | 1817 | sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, SCTP_NULL()); |
1789 | 1818 | ||
1790 | repl = sctp_make_cookie_ack(new_asoc, chunk); | 1819 | repl = sctp_make_cookie_ack(new_asoc, chunk); |
@@ -1833,7 +1862,8 @@ nomem: | |||
1833 | * but a new tag of its own. | 1862 | * but a new tag of its own. |
1834 | */ | 1863 | */ |
1835 | /* This case represents an initialization collision. */ | 1864 | /* This case represents an initialization collision. */ |
1836 | static sctp_disposition_t sctp_sf_do_dupcook_c(const struct sctp_endpoint *ep, | 1865 | static sctp_disposition_t sctp_sf_do_dupcook_c(struct net *net, |
1866 | const struct sctp_endpoint *ep, | ||
1837 | const struct sctp_association *asoc, | 1867 | const struct sctp_association *asoc, |
1838 | struct sctp_chunk *chunk, | 1868 | struct sctp_chunk *chunk, |
1839 | sctp_cmd_seq_t *commands, | 1869 | sctp_cmd_seq_t *commands, |
@@ -1854,7 +1884,8 @@ static sctp_disposition_t sctp_sf_do_dupcook_c(const struct sctp_endpoint *ep, | |||
1854 | * enter the ESTABLISHED state, if it has not already done so. | 1884 | * enter the ESTABLISHED state, if it has not already done so. |
1855 | */ | 1885 | */ |
1856 | /* This case represents an initialization collision. */ | 1886 | /* This case represents an initialization collision. */ |
1857 | static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep, | 1887 | static sctp_disposition_t sctp_sf_do_dupcook_d(struct net *net, |
1888 | const struct sctp_endpoint *ep, | ||
1858 | const struct sctp_association *asoc, | 1889 | const struct sctp_association *asoc, |
1859 | struct sctp_chunk *chunk, | 1890 | struct sctp_chunk *chunk, |
1860 | sctp_cmd_seq_t *commands, | 1891 | sctp_cmd_seq_t *commands, |
@@ -1876,7 +1907,7 @@ static sctp_disposition_t sctp_sf_do_dupcook_d(const struct sctp_endpoint *ep, | |||
1876 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); | 1907 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_COOKIE)); |
1877 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | 1908 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, |
1878 | SCTP_STATE(SCTP_STATE_ESTABLISHED)); | 1909 | SCTP_STATE(SCTP_STATE_ESTABLISHED)); |
1879 | SCTP_INC_STATS(SCTP_MIB_CURRESTAB); | 1910 | SCTP_INC_STATS(net, SCTP_MIB_CURRESTAB); |
1880 | sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, | 1911 | sctp_add_cmd_sf(commands, SCTP_CMD_HB_TIMERS_START, |
1881 | SCTP_NULL()); | 1912 | SCTP_NULL()); |
1882 | 1913 | ||
@@ -1948,7 +1979,8 @@ nomem: | |||
1948 | * | 1979 | * |
1949 | * The return value is the disposition of the chunk. | 1980 | * The return value is the disposition of the chunk. |
1950 | */ | 1981 | */ |
1951 | sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const struct sctp_endpoint *ep, | 1982 | sctp_disposition_t sctp_sf_do_5_2_4_dupcook(struct net *net, |
1983 | const struct sctp_endpoint *ep, | ||
1952 | const struct sctp_association *asoc, | 1984 | const struct sctp_association *asoc, |
1953 | const sctp_subtype_t type, | 1985 | const sctp_subtype_t type, |
1954 | void *arg, | 1986 | void *arg, |
@@ -1967,7 +1999,7 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const struct sctp_endpoint *ep, | |||
1967 | * done later. | 1999 | * done later. |
1968 | */ | 2000 | */ |
1969 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t))) | 2001 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t))) |
1970 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 2002 | return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
1971 | commands); | 2003 | commands); |
1972 | 2004 | ||
1973 | /* "Decode" the chunk. We have no optional parameters so we | 2005 | /* "Decode" the chunk. We have no optional parameters so we |
@@ -2001,12 +2033,12 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const struct sctp_endpoint *ep, | |||
2001 | goto nomem; | 2033 | goto nomem; |
2002 | 2034 | ||
2003 | case -SCTP_IERROR_STALE_COOKIE: | 2035 | case -SCTP_IERROR_STALE_COOKIE: |
2004 | sctp_send_stale_cookie_err(ep, asoc, chunk, commands, | 2036 | sctp_send_stale_cookie_err(net, ep, asoc, chunk, commands, |
2005 | err_chk_p); | 2037 | err_chk_p); |
2006 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 2038 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
2007 | case -SCTP_IERROR_BAD_SIG: | 2039 | case -SCTP_IERROR_BAD_SIG: |
2008 | default: | 2040 | default: |
2009 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 2041 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
2010 | } | 2042 | } |
2011 | } | 2043 | } |
2012 | 2044 | ||
@@ -2017,27 +2049,27 @@ sctp_disposition_t sctp_sf_do_5_2_4_dupcook(const struct sctp_endpoint *ep, | |||
2017 | 2049 | ||
2018 | switch (action) { | 2050 | switch (action) { |
2019 | case 'A': /* Association restart. */ | 2051 | case 'A': /* Association restart. */ |
2020 | retval = sctp_sf_do_dupcook_a(ep, asoc, chunk, commands, | 2052 | retval = sctp_sf_do_dupcook_a(net, ep, asoc, chunk, commands, |
2021 | new_asoc); | 2053 | new_asoc); |
2022 | break; | 2054 | break; |
2023 | 2055 | ||
2024 | case 'B': /* Collision case B. */ | 2056 | case 'B': /* Collision case B. */ |
2025 | retval = sctp_sf_do_dupcook_b(ep, asoc, chunk, commands, | 2057 | retval = sctp_sf_do_dupcook_b(net, ep, asoc, chunk, commands, |
2026 | new_asoc); | 2058 | new_asoc); |
2027 | break; | 2059 | break; |
2028 | 2060 | ||
2029 | case 'C': /* Collision case C. */ | 2061 | case 'C': /* Collision case C. */ |
2030 | retval = sctp_sf_do_dupcook_c(ep, asoc, chunk, commands, | 2062 | retval = sctp_sf_do_dupcook_c(net, ep, asoc, chunk, commands, |
2031 | new_asoc); | 2063 | new_asoc); |
2032 | break; | 2064 | break; |
2033 | 2065 | ||
2034 | case 'D': /* Collision case D. */ | 2066 | case 'D': /* Collision case D. */ |
2035 | retval = sctp_sf_do_dupcook_d(ep, asoc, chunk, commands, | 2067 | retval = sctp_sf_do_dupcook_d(net, ep, asoc, chunk, commands, |
2036 | new_asoc); | 2068 | new_asoc); |
2037 | break; | 2069 | break; |
2038 | 2070 | ||
2039 | default: /* Discard packet for all others. */ | 2071 | default: /* Discard packet for all others. */ |
2040 | retval = sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 2072 | retval = sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
2041 | break; | 2073 | break; |
2042 | } | 2074 | } |
2043 | 2075 | ||
@@ -2063,6 +2095,7 @@ nomem: | |||
2063 | * See sctp_sf_do_9_1_abort(). | 2095 | * See sctp_sf_do_9_1_abort(). |
2064 | */ | 2096 | */ |
2065 | sctp_disposition_t sctp_sf_shutdown_pending_abort( | 2097 | sctp_disposition_t sctp_sf_shutdown_pending_abort( |
2098 | struct net *net, | ||
2066 | const struct sctp_endpoint *ep, | 2099 | const struct sctp_endpoint *ep, |
2067 | const struct sctp_association *asoc, | 2100 | const struct sctp_association *asoc, |
2068 | const sctp_subtype_t type, | 2101 | const sctp_subtype_t type, |
@@ -2072,7 +2105,7 @@ sctp_disposition_t sctp_sf_shutdown_pending_abort( | |||
2072 | struct sctp_chunk *chunk = arg; | 2105 | struct sctp_chunk *chunk = arg; |
2073 | 2106 | ||
2074 | if (!sctp_vtag_verify_either(chunk, asoc)) | 2107 | if (!sctp_vtag_verify_either(chunk, asoc)) |
2075 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 2108 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
2076 | 2109 | ||
2077 | /* Make sure that the ABORT chunk has a valid length. | 2110 | /* Make sure that the ABORT chunk has a valid length. |
2078 | * Since this is an ABORT chunk, we have to discard it | 2111 | * Since this is an ABORT chunk, we have to discard it |
@@ -2085,7 +2118,7 @@ sctp_disposition_t sctp_sf_shutdown_pending_abort( | |||
2085 | * packet. | 2118 | * packet. |
2086 | */ | 2119 | */ |
2087 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_abort_chunk_t))) | 2120 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_abort_chunk_t))) |
2088 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 2121 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
2089 | 2122 | ||
2090 | /* ADD-IP: Special case for ABORT chunks | 2123 | /* ADD-IP: Special case for ABORT chunks |
2091 | * F4) One special consideration is that ABORT Chunks arriving | 2124 | * F4) One special consideration is that ABORT Chunks arriving |
@@ -2094,9 +2127,9 @@ sctp_disposition_t sctp_sf_shutdown_pending_abort( | |||
2094 | */ | 2127 | */ |
2095 | if (SCTP_ADDR_DEL == | 2128 | if (SCTP_ADDR_DEL == |
2096 | sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest)) | 2129 | sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest)) |
2097 | return sctp_sf_discard_chunk(ep, asoc, type, arg, commands); | 2130 | return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands); |
2098 | 2131 | ||
2099 | return __sctp_sf_do_9_1_abort(ep, asoc, type, arg, commands); | 2132 | return __sctp_sf_do_9_1_abort(net, ep, asoc, type, arg, commands); |
2100 | } | 2133 | } |
2101 | 2134 | ||
2102 | /* | 2135 | /* |
@@ -2104,7 +2137,8 @@ sctp_disposition_t sctp_sf_shutdown_pending_abort( | |||
2104 | * | 2137 | * |
2105 | * See sctp_sf_do_9_1_abort(). | 2138 | * See sctp_sf_do_9_1_abort(). |
2106 | */ | 2139 | */ |
2107 | sctp_disposition_t sctp_sf_shutdown_sent_abort(const struct sctp_endpoint *ep, | 2140 | sctp_disposition_t sctp_sf_shutdown_sent_abort(struct net *net, |
2141 | const struct sctp_endpoint *ep, | ||
2108 | const struct sctp_association *asoc, | 2142 | const struct sctp_association *asoc, |
2109 | const sctp_subtype_t type, | 2143 | const sctp_subtype_t type, |
2110 | void *arg, | 2144 | void *arg, |
@@ -2113,7 +2147,7 @@ sctp_disposition_t sctp_sf_shutdown_sent_abort(const struct sctp_endpoint *ep, | |||
2113 | struct sctp_chunk *chunk = arg; | 2147 | struct sctp_chunk *chunk = arg; |
2114 | 2148 | ||
2115 | if (!sctp_vtag_verify_either(chunk, asoc)) | 2149 | if (!sctp_vtag_verify_either(chunk, asoc)) |
2116 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 2150 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
2117 | 2151 | ||
2118 | /* Make sure that the ABORT chunk has a valid length. | 2152 | /* Make sure that the ABORT chunk has a valid length. |
2119 | * Since this is an ABORT chunk, we have to discard it | 2153 | * Since this is an ABORT chunk, we have to discard it |
@@ -2126,7 +2160,7 @@ sctp_disposition_t sctp_sf_shutdown_sent_abort(const struct sctp_endpoint *ep, | |||
2126 | * packet. | 2160 | * packet. |
2127 | */ | 2161 | */ |
2128 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_abort_chunk_t))) | 2162 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_abort_chunk_t))) |
2129 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 2163 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
2130 | 2164 | ||
2131 | /* ADD-IP: Special case for ABORT chunks | 2165 | /* ADD-IP: Special case for ABORT chunks |
2132 | * F4) One special consideration is that ABORT Chunks arriving | 2166 | * F4) One special consideration is that ABORT Chunks arriving |
@@ -2135,7 +2169,7 @@ sctp_disposition_t sctp_sf_shutdown_sent_abort(const struct sctp_endpoint *ep, | |||
2135 | */ | 2169 | */ |
2136 | if (SCTP_ADDR_DEL == | 2170 | if (SCTP_ADDR_DEL == |
2137 | sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest)) | 2171 | sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest)) |
2138 | return sctp_sf_discard_chunk(ep, asoc, type, arg, commands); | 2172 | return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands); |
2139 | 2173 | ||
2140 | /* Stop the T2-shutdown timer. */ | 2174 | /* Stop the T2-shutdown timer. */ |
2141 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 2175 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
@@ -2145,7 +2179,7 @@ sctp_disposition_t sctp_sf_shutdown_sent_abort(const struct sctp_endpoint *ep, | |||
2145 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 2179 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
2146 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); | 2180 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); |
2147 | 2181 | ||
2148 | return __sctp_sf_do_9_1_abort(ep, asoc, type, arg, commands); | 2182 | return __sctp_sf_do_9_1_abort(net, ep, asoc, type, arg, commands); |
2149 | } | 2183 | } |
2150 | 2184 | ||
2151 | /* | 2185 | /* |
@@ -2154,6 +2188,7 @@ sctp_disposition_t sctp_sf_shutdown_sent_abort(const struct sctp_endpoint *ep, | |||
2154 | * See sctp_sf_do_9_1_abort(). | 2188 | * See sctp_sf_do_9_1_abort(). |
2155 | */ | 2189 | */ |
2156 | sctp_disposition_t sctp_sf_shutdown_ack_sent_abort( | 2190 | sctp_disposition_t sctp_sf_shutdown_ack_sent_abort( |
2191 | struct net *net, | ||
2157 | const struct sctp_endpoint *ep, | 2192 | const struct sctp_endpoint *ep, |
2158 | const struct sctp_association *asoc, | 2193 | const struct sctp_association *asoc, |
2159 | const sctp_subtype_t type, | 2194 | const sctp_subtype_t type, |
@@ -2163,7 +2198,7 @@ sctp_disposition_t sctp_sf_shutdown_ack_sent_abort( | |||
2163 | /* The same T2 timer, so we should be able to use | 2198 | /* The same T2 timer, so we should be able to use |
2164 | * common function with the SHUTDOWN-SENT state. | 2199 | * common function with the SHUTDOWN-SENT state. |
2165 | */ | 2200 | */ |
2166 | return sctp_sf_shutdown_sent_abort(ep, asoc, type, arg, commands); | 2201 | return sctp_sf_shutdown_sent_abort(net, ep, asoc, type, arg, commands); |
2167 | } | 2202 | } |
2168 | 2203 | ||
2169 | /* | 2204 | /* |
@@ -2180,7 +2215,8 @@ sctp_disposition_t sctp_sf_shutdown_ack_sent_abort( | |||
2180 | * | 2215 | * |
2181 | * The return value is the disposition of the chunk. | 2216 | * The return value is the disposition of the chunk. |
2182 | */ | 2217 | */ |
2183 | sctp_disposition_t sctp_sf_cookie_echoed_err(const struct sctp_endpoint *ep, | 2218 | sctp_disposition_t sctp_sf_cookie_echoed_err(struct net *net, |
2219 | const struct sctp_endpoint *ep, | ||
2184 | const struct sctp_association *asoc, | 2220 | const struct sctp_association *asoc, |
2185 | const sctp_subtype_t type, | 2221 | const sctp_subtype_t type, |
2186 | void *arg, | 2222 | void *arg, |
@@ -2190,13 +2226,13 @@ sctp_disposition_t sctp_sf_cookie_echoed_err(const struct sctp_endpoint *ep, | |||
2190 | sctp_errhdr_t *err; | 2226 | sctp_errhdr_t *err; |
2191 | 2227 | ||
2192 | if (!sctp_vtag_verify(chunk, asoc)) | 2228 | if (!sctp_vtag_verify(chunk, asoc)) |
2193 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 2229 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
2194 | 2230 | ||
2195 | /* Make sure that the ERROR chunk has a valid length. | 2231 | /* Make sure that the ERROR chunk has a valid length. |
2196 | * The parameter walking depends on this as well. | 2232 | * The parameter walking depends on this as well. |
2197 | */ | 2233 | */ |
2198 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_operr_chunk_t))) | 2234 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_operr_chunk_t))) |
2199 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 2235 | return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
2200 | commands); | 2236 | commands); |
2201 | 2237 | ||
2202 | /* Process the error here */ | 2238 | /* Process the error here */ |
@@ -2206,7 +2242,7 @@ sctp_disposition_t sctp_sf_cookie_echoed_err(const struct sctp_endpoint *ep, | |||
2206 | */ | 2242 | */ |
2207 | sctp_walk_errors(err, chunk->chunk_hdr) { | 2243 | sctp_walk_errors(err, chunk->chunk_hdr) { |
2208 | if (SCTP_ERROR_STALE_COOKIE == err->cause) | 2244 | if (SCTP_ERROR_STALE_COOKIE == err->cause) |
2209 | return sctp_sf_do_5_2_6_stale(ep, asoc, type, | 2245 | return sctp_sf_do_5_2_6_stale(net, ep, asoc, type, |
2210 | arg, commands); | 2246 | arg, commands); |
2211 | } | 2247 | } |
2212 | 2248 | ||
@@ -2215,7 +2251,7 @@ sctp_disposition_t sctp_sf_cookie_echoed_err(const struct sctp_endpoint *ep, | |||
2215 | * we are discarding the packet, there should be no adverse | 2251 | * we are discarding the packet, there should be no adverse |
2216 | * affects. | 2252 | * affects. |
2217 | */ | 2253 | */ |
2218 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 2254 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
2219 | } | 2255 | } |
2220 | 2256 | ||
2221 | /* | 2257 | /* |
@@ -2243,7 +2279,8 @@ sctp_disposition_t sctp_sf_cookie_echoed_err(const struct sctp_endpoint *ep, | |||
2243 | * | 2279 | * |
2244 | * The return value is the disposition of the chunk. | 2280 | * The return value is the disposition of the chunk. |
2245 | */ | 2281 | */ |
2246 | static sctp_disposition_t sctp_sf_do_5_2_6_stale(const struct sctp_endpoint *ep, | 2282 | static sctp_disposition_t sctp_sf_do_5_2_6_stale(struct net *net, |
2283 | const struct sctp_endpoint *ep, | ||
2247 | const struct sctp_association *asoc, | 2284 | const struct sctp_association *asoc, |
2248 | const sctp_subtype_t type, | 2285 | const sctp_subtype_t type, |
2249 | void *arg, | 2286 | void *arg, |
@@ -2365,7 +2402,8 @@ nomem: | |||
2365 | * | 2402 | * |
2366 | * The return value is the disposition of the chunk. | 2403 | * The return value is the disposition of the chunk. |
2367 | */ | 2404 | */ |
2368 | sctp_disposition_t sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep, | 2405 | sctp_disposition_t sctp_sf_do_9_1_abort(struct net *net, |
2406 | const struct sctp_endpoint *ep, | ||
2369 | const struct sctp_association *asoc, | 2407 | const struct sctp_association *asoc, |
2370 | const sctp_subtype_t type, | 2408 | const sctp_subtype_t type, |
2371 | void *arg, | 2409 | void *arg, |
@@ -2374,7 +2412,7 @@ sctp_disposition_t sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep, | |||
2374 | struct sctp_chunk *chunk = arg; | 2412 | struct sctp_chunk *chunk = arg; |
2375 | 2413 | ||
2376 | if (!sctp_vtag_verify_either(chunk, asoc)) | 2414 | if (!sctp_vtag_verify_either(chunk, asoc)) |
2377 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 2415 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
2378 | 2416 | ||
2379 | /* Make sure that the ABORT chunk has a valid length. | 2417 | /* Make sure that the ABORT chunk has a valid length. |
2380 | * Since this is an ABORT chunk, we have to discard it | 2418 | * Since this is an ABORT chunk, we have to discard it |
@@ -2387,7 +2425,7 @@ sctp_disposition_t sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep, | |||
2387 | * packet. | 2425 | * packet. |
2388 | */ | 2426 | */ |
2389 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_abort_chunk_t))) | 2427 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_abort_chunk_t))) |
2390 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 2428 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
2391 | 2429 | ||
2392 | /* ADD-IP: Special case for ABORT chunks | 2430 | /* ADD-IP: Special case for ABORT chunks |
2393 | * F4) One special consideration is that ABORT Chunks arriving | 2431 | * F4) One special consideration is that ABORT Chunks arriving |
@@ -2396,12 +2434,13 @@ sctp_disposition_t sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep, | |||
2396 | */ | 2434 | */ |
2397 | if (SCTP_ADDR_DEL == | 2435 | if (SCTP_ADDR_DEL == |
2398 | sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest)) | 2436 | sctp_bind_addr_state(&asoc->base.bind_addr, &chunk->dest)) |
2399 | return sctp_sf_discard_chunk(ep, asoc, type, arg, commands); | 2437 | return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands); |
2400 | 2438 | ||
2401 | return __sctp_sf_do_9_1_abort(ep, asoc, type, arg, commands); | 2439 | return __sctp_sf_do_9_1_abort(net, ep, asoc, type, arg, commands); |
2402 | } | 2440 | } |
2403 | 2441 | ||
2404 | static sctp_disposition_t __sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep, | 2442 | static sctp_disposition_t __sctp_sf_do_9_1_abort(struct net *net, |
2443 | const struct sctp_endpoint *ep, | ||
2405 | const struct sctp_association *asoc, | 2444 | const struct sctp_association *asoc, |
2406 | const sctp_subtype_t type, | 2445 | const sctp_subtype_t type, |
2407 | void *arg, | 2446 | void *arg, |
@@ -2418,7 +2457,7 @@ static sctp_disposition_t __sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep, | |||
2418 | sctp_errhdr_t *err; | 2457 | sctp_errhdr_t *err; |
2419 | sctp_walk_errors(err, chunk->chunk_hdr); | 2458 | sctp_walk_errors(err, chunk->chunk_hdr); |
2420 | if ((void *)err != (void *)chunk->chunk_end) | 2459 | if ((void *)err != (void *)chunk->chunk_end) |
2421 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 2460 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
2422 | 2461 | ||
2423 | error = ((sctp_errhdr_t *)chunk->skb->data)->cause; | 2462 | error = ((sctp_errhdr_t *)chunk->skb->data)->cause; |
2424 | } | 2463 | } |
@@ -2426,8 +2465,8 @@ static sctp_disposition_t __sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep, | |||
2426 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNRESET)); | 2465 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(ECONNRESET)); |
2427 | /* ASSOC_FAILED will DELETE_TCB. */ | 2466 | /* ASSOC_FAILED will DELETE_TCB. */ |
2428 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_PERR(error)); | 2467 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, SCTP_PERR(error)); |
2429 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 2468 | SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); |
2430 | SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); | 2469 | SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); |
2431 | 2470 | ||
2432 | return SCTP_DISPOSITION_ABORT; | 2471 | return SCTP_DISPOSITION_ABORT; |
2433 | } | 2472 | } |
@@ -2437,7 +2476,8 @@ static sctp_disposition_t __sctp_sf_do_9_1_abort(const struct sctp_endpoint *ep, | |||
2437 | * | 2476 | * |
2438 | * See sctp_sf_do_9_1_abort() above. | 2477 | * See sctp_sf_do_9_1_abort() above. |
2439 | */ | 2478 | */ |
2440 | sctp_disposition_t sctp_sf_cookie_wait_abort(const struct sctp_endpoint *ep, | 2479 | sctp_disposition_t sctp_sf_cookie_wait_abort(struct net *net, |
2480 | const struct sctp_endpoint *ep, | ||
2441 | const struct sctp_association *asoc, | 2481 | const struct sctp_association *asoc, |
2442 | const sctp_subtype_t type, | 2482 | const sctp_subtype_t type, |
2443 | void *arg, | 2483 | void *arg, |
@@ -2448,7 +2488,7 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const struct sctp_endpoint *ep, | |||
2448 | __be16 error = SCTP_ERROR_NO_ERROR; | 2488 | __be16 error = SCTP_ERROR_NO_ERROR; |
2449 | 2489 | ||
2450 | if (!sctp_vtag_verify_either(chunk, asoc)) | 2490 | if (!sctp_vtag_verify_either(chunk, asoc)) |
2451 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 2491 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
2452 | 2492 | ||
2453 | /* Make sure that the ABORT chunk has a valid length. | 2493 | /* Make sure that the ABORT chunk has a valid length. |
2454 | * Since this is an ABORT chunk, we have to discard it | 2494 | * Since this is an ABORT chunk, we have to discard it |
@@ -2461,27 +2501,28 @@ sctp_disposition_t sctp_sf_cookie_wait_abort(const struct sctp_endpoint *ep, | |||
2461 | * packet. | 2501 | * packet. |
2462 | */ | 2502 | */ |
2463 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_abort_chunk_t))) | 2503 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_abort_chunk_t))) |
2464 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 2504 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
2465 | 2505 | ||
2466 | /* See if we have an error cause code in the chunk. */ | 2506 | /* See if we have an error cause code in the chunk. */ |
2467 | len = ntohs(chunk->chunk_hdr->length); | 2507 | len = ntohs(chunk->chunk_hdr->length); |
2468 | if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) | 2508 | if (len >= sizeof(struct sctp_chunkhdr) + sizeof(struct sctp_errhdr)) |
2469 | error = ((sctp_errhdr_t *)chunk->skb->data)->cause; | 2509 | error = ((sctp_errhdr_t *)chunk->skb->data)->cause; |
2470 | 2510 | ||
2471 | return sctp_stop_t1_and_abort(commands, error, ECONNREFUSED, asoc, | 2511 | return sctp_stop_t1_and_abort(net, commands, error, ECONNREFUSED, asoc, |
2472 | chunk->transport); | 2512 | chunk->transport); |
2473 | } | 2513 | } |
2474 | 2514 | ||
2475 | /* | 2515 | /* |
2476 | * Process an incoming ICMP as an ABORT. (COOKIE-WAIT state) | 2516 | * Process an incoming ICMP as an ABORT. (COOKIE-WAIT state) |
2477 | */ | 2517 | */ |
2478 | sctp_disposition_t sctp_sf_cookie_wait_icmp_abort(const struct sctp_endpoint *ep, | 2518 | sctp_disposition_t sctp_sf_cookie_wait_icmp_abort(struct net *net, |
2519 | const struct sctp_endpoint *ep, | ||
2479 | const struct sctp_association *asoc, | 2520 | const struct sctp_association *asoc, |
2480 | const sctp_subtype_t type, | 2521 | const sctp_subtype_t type, |
2481 | void *arg, | 2522 | void *arg, |
2482 | sctp_cmd_seq_t *commands) | 2523 | sctp_cmd_seq_t *commands) |
2483 | { | 2524 | { |
2484 | return sctp_stop_t1_and_abort(commands, SCTP_ERROR_NO_ERROR, | 2525 | return sctp_stop_t1_and_abort(net, commands, SCTP_ERROR_NO_ERROR, |
2485 | ENOPROTOOPT, asoc, | 2526 | ENOPROTOOPT, asoc, |
2486 | (struct sctp_transport *)arg); | 2527 | (struct sctp_transport *)arg); |
2487 | } | 2528 | } |
@@ -2489,7 +2530,8 @@ sctp_disposition_t sctp_sf_cookie_wait_icmp_abort(const struct sctp_endpoint *ep | |||
2489 | /* | 2530 | /* |
2490 | * Process an ABORT. (COOKIE-ECHOED state) | 2531 | * Process an ABORT. (COOKIE-ECHOED state) |
2491 | */ | 2532 | */ |
2492 | sctp_disposition_t sctp_sf_cookie_echoed_abort(const struct sctp_endpoint *ep, | 2533 | sctp_disposition_t sctp_sf_cookie_echoed_abort(struct net *net, |
2534 | const struct sctp_endpoint *ep, | ||
2493 | const struct sctp_association *asoc, | 2535 | const struct sctp_association *asoc, |
2494 | const sctp_subtype_t type, | 2536 | const sctp_subtype_t type, |
2495 | void *arg, | 2537 | void *arg, |
@@ -2498,7 +2540,7 @@ sctp_disposition_t sctp_sf_cookie_echoed_abort(const struct sctp_endpoint *ep, | |||
2498 | /* There is a single T1 timer, so we should be able to use | 2540 | /* There is a single T1 timer, so we should be able to use |
2499 | * common function with the COOKIE-WAIT state. | 2541 | * common function with the COOKIE-WAIT state. |
2500 | */ | 2542 | */ |
2501 | return sctp_sf_cookie_wait_abort(ep, asoc, type, arg, commands); | 2543 | return sctp_sf_cookie_wait_abort(net, ep, asoc, type, arg, commands); |
2502 | } | 2544 | } |
2503 | 2545 | ||
2504 | /* | 2546 | /* |
@@ -2506,7 +2548,8 @@ sctp_disposition_t sctp_sf_cookie_echoed_abort(const struct sctp_endpoint *ep, | |||
2506 | * | 2548 | * |
2507 | * This is common code called by several sctp_sf_*_abort() functions above. | 2549 | * This is common code called by several sctp_sf_*_abort() functions above. |
2508 | */ | 2550 | */ |
2509 | static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, | 2551 | static sctp_disposition_t sctp_stop_t1_and_abort(struct net *net, |
2552 | sctp_cmd_seq_t *commands, | ||
2510 | __be16 error, int sk_err, | 2553 | __be16 error, int sk_err, |
2511 | const struct sctp_association *asoc, | 2554 | const struct sctp_association *asoc, |
2512 | struct sctp_transport *transport) | 2555 | struct sctp_transport *transport) |
@@ -2514,7 +2557,7 @@ static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, | |||
2514 | SCTP_DEBUG_PRINTK("ABORT received (INIT).\n"); | 2557 | SCTP_DEBUG_PRINTK("ABORT received (INIT).\n"); |
2515 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | 2558 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, |
2516 | SCTP_STATE(SCTP_STATE_CLOSED)); | 2559 | SCTP_STATE(SCTP_STATE_CLOSED)); |
2517 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 2560 | SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); |
2518 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 2561 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
2519 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); | 2562 | SCTP_TO(SCTP_EVENT_TIMEOUT_T1_INIT)); |
2520 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(sk_err)); | 2563 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, SCTP_ERROR(sk_err)); |
@@ -2557,7 +2600,8 @@ static sctp_disposition_t sctp_stop_t1_and_abort(sctp_cmd_seq_t *commands, | |||
2557 | * | 2600 | * |
2558 | * The return value is the disposition of the chunk. | 2601 | * The return value is the disposition of the chunk. |
2559 | */ | 2602 | */ |
2560 | sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep, | 2603 | sctp_disposition_t sctp_sf_do_9_2_shutdown(struct net *net, |
2604 | const struct sctp_endpoint *ep, | ||
2561 | const struct sctp_association *asoc, | 2605 | const struct sctp_association *asoc, |
2562 | const sctp_subtype_t type, | 2606 | const sctp_subtype_t type, |
2563 | void *arg, | 2607 | void *arg, |
@@ -2570,12 +2614,12 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep, | |||
2570 | __u32 ctsn; | 2614 | __u32 ctsn; |
2571 | 2615 | ||
2572 | if (!sctp_vtag_verify(chunk, asoc)) | 2616 | if (!sctp_vtag_verify(chunk, asoc)) |
2573 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 2617 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
2574 | 2618 | ||
2575 | /* Make sure that the SHUTDOWN chunk has a valid length. */ | 2619 | /* Make sure that the SHUTDOWN chunk has a valid length. */ |
2576 | if (!sctp_chunk_length_valid(chunk, | 2620 | if (!sctp_chunk_length_valid(chunk, |
2577 | sizeof(struct sctp_shutdown_chunk_t))) | 2621 | sizeof(struct sctp_shutdown_chunk_t))) |
2578 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 2622 | return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
2579 | commands); | 2623 | commands); |
2580 | 2624 | ||
2581 | /* Convert the elaborate header. */ | 2625 | /* Convert the elaborate header. */ |
@@ -2595,7 +2639,7 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep, | |||
2595 | * sender with an ABORT. | 2639 | * sender with an ABORT. |
2596 | */ | 2640 | */ |
2597 | if (!TSN_lt(ctsn, asoc->next_tsn)) | 2641 | if (!TSN_lt(ctsn, asoc->next_tsn)) |
2598 | return sctp_sf_violation_ctsn(ep, asoc, type, arg, commands); | 2642 | return sctp_sf_violation_ctsn(net, ep, asoc, type, arg, commands); |
2599 | 2643 | ||
2600 | /* API 5.3.1.5 SCTP_SHUTDOWN_EVENT | 2644 | /* API 5.3.1.5 SCTP_SHUTDOWN_EVENT |
2601 | * When a peer sends a SHUTDOWN, SCTP delivers this notification to | 2645 | * When a peer sends a SHUTDOWN, SCTP delivers this notification to |
@@ -2619,7 +2663,7 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown(const struct sctp_endpoint *ep, | |||
2619 | disposition = SCTP_DISPOSITION_CONSUME; | 2663 | disposition = SCTP_DISPOSITION_CONSUME; |
2620 | 2664 | ||
2621 | if (sctp_outq_is_empty(&asoc->outqueue)) { | 2665 | if (sctp_outq_is_empty(&asoc->outqueue)) { |
2622 | disposition = sctp_sf_do_9_2_shutdown_ack(ep, asoc, type, | 2666 | disposition = sctp_sf_do_9_2_shutdown_ack(net, ep, asoc, type, |
2623 | arg, commands); | 2667 | arg, commands); |
2624 | } | 2668 | } |
2625 | 2669 | ||
@@ -2645,7 +2689,8 @@ out: | |||
2645 | * The Cumulative TSN Ack of the received SHUTDOWN chunk | 2689 | * The Cumulative TSN Ack of the received SHUTDOWN chunk |
2646 | * MUST be processed. | 2690 | * MUST be processed. |
2647 | */ | 2691 | */ |
2648 | sctp_disposition_t sctp_sf_do_9_2_shut_ctsn(const struct sctp_endpoint *ep, | 2692 | sctp_disposition_t sctp_sf_do_9_2_shut_ctsn(struct net *net, |
2693 | const struct sctp_endpoint *ep, | ||
2649 | const struct sctp_association *asoc, | 2694 | const struct sctp_association *asoc, |
2650 | const sctp_subtype_t type, | 2695 | const sctp_subtype_t type, |
2651 | void *arg, | 2696 | void *arg, |
@@ -2656,12 +2701,12 @@ sctp_disposition_t sctp_sf_do_9_2_shut_ctsn(const struct sctp_endpoint *ep, | |||
2656 | __u32 ctsn; | 2701 | __u32 ctsn; |
2657 | 2702 | ||
2658 | if (!sctp_vtag_verify(chunk, asoc)) | 2703 | if (!sctp_vtag_verify(chunk, asoc)) |
2659 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 2704 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
2660 | 2705 | ||
2661 | /* Make sure that the SHUTDOWN chunk has a valid length. */ | 2706 | /* Make sure that the SHUTDOWN chunk has a valid length. */ |
2662 | if (!sctp_chunk_length_valid(chunk, | 2707 | if (!sctp_chunk_length_valid(chunk, |
2663 | sizeof(struct sctp_shutdown_chunk_t))) | 2708 | sizeof(struct sctp_shutdown_chunk_t))) |
2664 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 2709 | return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
2665 | commands); | 2710 | commands); |
2666 | 2711 | ||
2667 | sdh = (sctp_shutdownhdr_t *)chunk->skb->data; | 2712 | sdh = (sctp_shutdownhdr_t *)chunk->skb->data; |
@@ -2678,7 +2723,7 @@ sctp_disposition_t sctp_sf_do_9_2_shut_ctsn(const struct sctp_endpoint *ep, | |||
2678 | * sender with an ABORT. | 2723 | * sender with an ABORT. |
2679 | */ | 2724 | */ |
2680 | if (!TSN_lt(ctsn, asoc->next_tsn)) | 2725 | if (!TSN_lt(ctsn, asoc->next_tsn)) |
2681 | return sctp_sf_violation_ctsn(ep, asoc, type, arg, commands); | 2726 | return sctp_sf_violation_ctsn(net, ep, asoc, type, arg, commands); |
2682 | 2727 | ||
2683 | /* verify, by checking the Cumulative TSN Ack field of the | 2728 | /* verify, by checking the Cumulative TSN Ack field of the |
2684 | * chunk, that all its outstanding DATA chunks have been | 2729 | * chunk, that all its outstanding DATA chunks have been |
@@ -2697,7 +2742,8 @@ sctp_disposition_t sctp_sf_do_9_2_shut_ctsn(const struct sctp_endpoint *ep, | |||
2697 | * that belong to this association, it should discard the INIT chunk and | 2742 | * that belong to this association, it should discard the INIT chunk and |
2698 | * retransmit the SHUTDOWN ACK chunk. | 2743 | * retransmit the SHUTDOWN ACK chunk. |
2699 | */ | 2744 | */ |
2700 | sctp_disposition_t sctp_sf_do_9_2_reshutack(const struct sctp_endpoint *ep, | 2745 | sctp_disposition_t sctp_sf_do_9_2_reshutack(struct net *net, |
2746 | const struct sctp_endpoint *ep, | ||
2701 | const struct sctp_association *asoc, | 2747 | const struct sctp_association *asoc, |
2702 | const sctp_subtype_t type, | 2748 | const sctp_subtype_t type, |
2703 | void *arg, | 2749 | void *arg, |
@@ -2708,7 +2754,7 @@ sctp_disposition_t sctp_sf_do_9_2_reshutack(const struct sctp_endpoint *ep, | |||
2708 | 2754 | ||
2709 | /* Make sure that the chunk has a valid length */ | 2755 | /* Make sure that the chunk has a valid length */ |
2710 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t))) | 2756 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t))) |
2711 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 2757 | return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
2712 | commands); | 2758 | commands); |
2713 | 2759 | ||
2714 | /* Since we are not going to really process this INIT, there | 2760 | /* Since we are not going to really process this INIT, there |
@@ -2760,7 +2806,8 @@ nomem: | |||
2760 | * | 2806 | * |
2761 | * The return value is the disposition of the chunk. | 2807 | * The return value is the disposition of the chunk. |
2762 | */ | 2808 | */ |
2763 | sctp_disposition_t sctp_sf_do_ecn_cwr(const struct sctp_endpoint *ep, | 2809 | sctp_disposition_t sctp_sf_do_ecn_cwr(struct net *net, |
2810 | const struct sctp_endpoint *ep, | ||
2764 | const struct sctp_association *asoc, | 2811 | const struct sctp_association *asoc, |
2765 | const sctp_subtype_t type, | 2812 | const sctp_subtype_t type, |
2766 | void *arg, | 2813 | void *arg, |
@@ -2771,10 +2818,10 @@ sctp_disposition_t sctp_sf_do_ecn_cwr(const struct sctp_endpoint *ep, | |||
2771 | u32 lowest_tsn; | 2818 | u32 lowest_tsn; |
2772 | 2819 | ||
2773 | if (!sctp_vtag_verify(chunk, asoc)) | 2820 | if (!sctp_vtag_verify(chunk, asoc)) |
2774 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 2821 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
2775 | 2822 | ||
2776 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_ecne_chunk_t))) | 2823 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_ecne_chunk_t))) |
2777 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 2824 | return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
2778 | commands); | 2825 | commands); |
2779 | 2826 | ||
2780 | cwr = (sctp_cwrhdr_t *) chunk->skb->data; | 2827 | cwr = (sctp_cwrhdr_t *) chunk->skb->data; |
@@ -2815,7 +2862,8 @@ sctp_disposition_t sctp_sf_do_ecn_cwr(const struct sctp_endpoint *ep, | |||
2815 | * | 2862 | * |
2816 | * The return value is the disposition of the chunk. | 2863 | * The return value is the disposition of the chunk. |
2817 | */ | 2864 | */ |
2818 | sctp_disposition_t sctp_sf_do_ecne(const struct sctp_endpoint *ep, | 2865 | sctp_disposition_t sctp_sf_do_ecne(struct net *net, |
2866 | const struct sctp_endpoint *ep, | ||
2819 | const struct sctp_association *asoc, | 2867 | const struct sctp_association *asoc, |
2820 | const sctp_subtype_t type, | 2868 | const sctp_subtype_t type, |
2821 | void *arg, | 2869 | void *arg, |
@@ -2825,10 +2873,10 @@ sctp_disposition_t sctp_sf_do_ecne(const struct sctp_endpoint *ep, | |||
2825 | struct sctp_chunk *chunk = arg; | 2873 | struct sctp_chunk *chunk = arg; |
2826 | 2874 | ||
2827 | if (!sctp_vtag_verify(chunk, asoc)) | 2875 | if (!sctp_vtag_verify(chunk, asoc)) |
2828 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 2876 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
2829 | 2877 | ||
2830 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_ecne_chunk_t))) | 2878 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_ecne_chunk_t))) |
2831 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 2879 | return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
2832 | commands); | 2880 | commands); |
2833 | 2881 | ||
2834 | ecne = (sctp_ecnehdr_t *) chunk->skb->data; | 2882 | ecne = (sctp_ecnehdr_t *) chunk->skb->data; |
@@ -2871,7 +2919,8 @@ sctp_disposition_t sctp_sf_do_ecne(const struct sctp_endpoint *ep, | |||
2871 | * | 2919 | * |
2872 | * The return value is the disposition of the chunk. | 2920 | * The return value is the disposition of the chunk. |
2873 | */ | 2921 | */ |
2874 | sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep, | 2922 | sctp_disposition_t sctp_sf_eat_data_6_2(struct net *net, |
2923 | const struct sctp_endpoint *ep, | ||
2875 | const struct sctp_association *asoc, | 2924 | const struct sctp_association *asoc, |
2876 | const sctp_subtype_t type, | 2925 | const sctp_subtype_t type, |
2877 | void *arg, | 2926 | void *arg, |
@@ -2884,11 +2933,11 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep, | |||
2884 | if (!sctp_vtag_verify(chunk, asoc)) { | 2933 | if (!sctp_vtag_verify(chunk, asoc)) { |
2885 | sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, | 2934 | sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, |
2886 | SCTP_NULL()); | 2935 | SCTP_NULL()); |
2887 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 2936 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
2888 | } | 2937 | } |
2889 | 2938 | ||
2890 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_data_chunk_t))) | 2939 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_data_chunk_t))) |
2891 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 2940 | return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
2892 | commands); | 2941 | commands); |
2893 | 2942 | ||
2894 | error = sctp_eat_data(asoc, chunk, commands ); | 2943 | error = sctp_eat_data(asoc, chunk, commands ); |
@@ -2897,16 +2946,16 @@ sctp_disposition_t sctp_sf_eat_data_6_2(const struct sctp_endpoint *ep, | |||
2897 | break; | 2946 | break; |
2898 | case SCTP_IERROR_HIGH_TSN: | 2947 | case SCTP_IERROR_HIGH_TSN: |
2899 | case SCTP_IERROR_BAD_STREAM: | 2948 | case SCTP_IERROR_BAD_STREAM: |
2900 | SCTP_INC_STATS(SCTP_MIB_IN_DATA_CHUNK_DISCARDS); | 2949 | SCTP_INC_STATS(net, SCTP_MIB_IN_DATA_CHUNK_DISCARDS); |
2901 | goto discard_noforce; | 2950 | goto discard_noforce; |
2902 | case SCTP_IERROR_DUP_TSN: | 2951 | case SCTP_IERROR_DUP_TSN: |
2903 | case SCTP_IERROR_IGNORE_TSN: | 2952 | case SCTP_IERROR_IGNORE_TSN: |
2904 | SCTP_INC_STATS(SCTP_MIB_IN_DATA_CHUNK_DISCARDS); | 2953 | SCTP_INC_STATS(net, SCTP_MIB_IN_DATA_CHUNK_DISCARDS); |
2905 | goto discard_force; | 2954 | goto discard_force; |
2906 | case SCTP_IERROR_NO_DATA: | 2955 | case SCTP_IERROR_NO_DATA: |
2907 | goto consume; | 2956 | goto consume; |
2908 | case SCTP_IERROR_PROTO_VIOLATION: | 2957 | case SCTP_IERROR_PROTO_VIOLATION: |
2909 | return sctp_sf_abort_violation(ep, asoc, chunk, commands, | 2958 | return sctp_sf_abort_violation(net, ep, asoc, chunk, commands, |
2910 | (u8 *)chunk->subh.data_hdr, sizeof(sctp_datahdr_t)); | 2959 | (u8 *)chunk->subh.data_hdr, sizeof(sctp_datahdr_t)); |
2911 | default: | 2960 | default: |
2912 | BUG(); | 2961 | BUG(); |
@@ -2992,7 +3041,8 @@ consume: | |||
2992 | * | 3041 | * |
2993 | * The return value is the disposition of the chunk. | 3042 | * The return value is the disposition of the chunk. |
2994 | */ | 3043 | */ |
2995 | sctp_disposition_t sctp_sf_eat_data_fast_4_4(const struct sctp_endpoint *ep, | 3044 | sctp_disposition_t sctp_sf_eat_data_fast_4_4(struct net *net, |
3045 | const struct sctp_endpoint *ep, | ||
2996 | const struct sctp_association *asoc, | 3046 | const struct sctp_association *asoc, |
2997 | const sctp_subtype_t type, | 3047 | const sctp_subtype_t type, |
2998 | void *arg, | 3048 | void *arg, |
@@ -3004,11 +3054,11 @@ sctp_disposition_t sctp_sf_eat_data_fast_4_4(const struct sctp_endpoint *ep, | |||
3004 | if (!sctp_vtag_verify(chunk, asoc)) { | 3054 | if (!sctp_vtag_verify(chunk, asoc)) { |
3005 | sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, | 3055 | sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, |
3006 | SCTP_NULL()); | 3056 | SCTP_NULL()); |
3007 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 3057 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
3008 | } | 3058 | } |
3009 | 3059 | ||
3010 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_data_chunk_t))) | 3060 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_data_chunk_t))) |
3011 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 3061 | return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
3012 | commands); | 3062 | commands); |
3013 | 3063 | ||
3014 | error = sctp_eat_data(asoc, chunk, commands ); | 3064 | error = sctp_eat_data(asoc, chunk, commands ); |
@@ -3022,7 +3072,7 @@ sctp_disposition_t sctp_sf_eat_data_fast_4_4(const struct sctp_endpoint *ep, | |||
3022 | case SCTP_IERROR_NO_DATA: | 3072 | case SCTP_IERROR_NO_DATA: |
3023 | goto consume; | 3073 | goto consume; |
3024 | case SCTP_IERROR_PROTO_VIOLATION: | 3074 | case SCTP_IERROR_PROTO_VIOLATION: |
3025 | return sctp_sf_abort_violation(ep, asoc, chunk, commands, | 3075 | return sctp_sf_abort_violation(net, ep, asoc, chunk, commands, |
3026 | (u8 *)chunk->subh.data_hdr, sizeof(sctp_datahdr_t)); | 3076 | (u8 *)chunk->subh.data_hdr, sizeof(sctp_datahdr_t)); |
3027 | default: | 3077 | default: |
3028 | BUG(); | 3078 | BUG(); |
@@ -3082,7 +3132,8 @@ consume: | |||
3082 | * | 3132 | * |
3083 | * The return value is the disposition of the chunk. | 3133 | * The return value is the disposition of the chunk. |
3084 | */ | 3134 | */ |
3085 | sctp_disposition_t sctp_sf_eat_sack_6_2(const struct sctp_endpoint *ep, | 3135 | sctp_disposition_t sctp_sf_eat_sack_6_2(struct net *net, |
3136 | const struct sctp_endpoint *ep, | ||
3086 | const struct sctp_association *asoc, | 3137 | const struct sctp_association *asoc, |
3087 | const sctp_subtype_t type, | 3138 | const sctp_subtype_t type, |
3088 | void *arg, | 3139 | void *arg, |
@@ -3093,18 +3144,18 @@ sctp_disposition_t sctp_sf_eat_sack_6_2(const struct sctp_endpoint *ep, | |||
3093 | __u32 ctsn; | 3144 | __u32 ctsn; |
3094 | 3145 | ||
3095 | if (!sctp_vtag_verify(chunk, asoc)) | 3146 | if (!sctp_vtag_verify(chunk, asoc)) |
3096 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 3147 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
3097 | 3148 | ||
3098 | /* Make sure that the SACK chunk has a valid length. */ | 3149 | /* Make sure that the SACK chunk has a valid length. */ |
3099 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_sack_chunk_t))) | 3150 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_sack_chunk_t))) |
3100 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 3151 | return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
3101 | commands); | 3152 | commands); |
3102 | 3153 | ||
3103 | /* Pull the SACK chunk from the data buffer */ | 3154 | /* Pull the SACK chunk from the data buffer */ |
3104 | sackh = sctp_sm_pull_sack(chunk); | 3155 | sackh = sctp_sm_pull_sack(chunk); |
3105 | /* Was this a bogus SACK? */ | 3156 | /* Was this a bogus SACK? */ |
3106 | if (!sackh) | 3157 | if (!sackh) |
3107 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 3158 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
3108 | chunk->subh.sack_hdr = sackh; | 3159 | chunk->subh.sack_hdr = sackh; |
3109 | ctsn = ntohl(sackh->cum_tsn_ack); | 3160 | ctsn = ntohl(sackh->cum_tsn_ack); |
3110 | 3161 | ||
@@ -3125,7 +3176,7 @@ sctp_disposition_t sctp_sf_eat_sack_6_2(const struct sctp_endpoint *ep, | |||
3125 | * sender with an ABORT. | 3176 | * sender with an ABORT. |
3126 | */ | 3177 | */ |
3127 | if (!TSN_lt(ctsn, asoc->next_tsn)) | 3178 | if (!TSN_lt(ctsn, asoc->next_tsn)) |
3128 | return sctp_sf_violation_ctsn(ep, asoc, type, arg, commands); | 3179 | return sctp_sf_violation_ctsn(net, ep, asoc, type, arg, commands); |
3129 | 3180 | ||
3130 | /* Return this SACK for further processing. */ | 3181 | /* Return this SACK for further processing. */ |
3131 | sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, SCTP_SACKH(sackh)); | 3182 | sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_SACK, SCTP_SACKH(sackh)); |
@@ -3154,7 +3205,8 @@ sctp_disposition_t sctp_sf_eat_sack_6_2(const struct sctp_endpoint *ep, | |||
3154 | * | 3205 | * |
3155 | * The return value is the disposition of the chunk. | 3206 | * The return value is the disposition of the chunk. |
3156 | */ | 3207 | */ |
3157 | static sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep, | 3208 | static sctp_disposition_t sctp_sf_tabort_8_4_8(struct net *net, |
3209 | const struct sctp_endpoint *ep, | ||
3158 | const struct sctp_association *asoc, | 3210 | const struct sctp_association *asoc, |
3159 | const sctp_subtype_t type, | 3211 | const sctp_subtype_t type, |
3160 | void *arg, | 3212 | void *arg, |
@@ -3164,7 +3216,7 @@ static sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep, | |||
3164 | struct sctp_chunk *chunk = arg; | 3216 | struct sctp_chunk *chunk = arg; |
3165 | struct sctp_chunk *abort; | 3217 | struct sctp_chunk *abort; |
3166 | 3218 | ||
3167 | packet = sctp_ootb_pkt_new(asoc, chunk); | 3219 | packet = sctp_ootb_pkt_new(net, asoc, chunk); |
3168 | 3220 | ||
3169 | if (packet) { | 3221 | if (packet) { |
3170 | /* Make an ABORT. The T bit will be set if the asoc | 3222 | /* Make an ABORT. The T bit will be set if the asoc |
@@ -3188,9 +3240,9 @@ static sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep, | |||
3188 | sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, | 3240 | sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, |
3189 | SCTP_PACKET(packet)); | 3241 | SCTP_PACKET(packet)); |
3190 | 3242 | ||
3191 | SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); | 3243 | SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); |
3192 | 3244 | ||
3193 | sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 3245 | sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
3194 | return SCTP_DISPOSITION_CONSUME; | 3246 | return SCTP_DISPOSITION_CONSUME; |
3195 | } | 3247 | } |
3196 | 3248 | ||
@@ -3205,7 +3257,8 @@ static sctp_disposition_t sctp_sf_tabort_8_4_8(const struct sctp_endpoint *ep, | |||
3205 | * | 3257 | * |
3206 | * The return value is the disposition of the chunk. | 3258 | * The return value is the disposition of the chunk. |
3207 | */ | 3259 | */ |
3208 | sctp_disposition_t sctp_sf_operr_notify(const struct sctp_endpoint *ep, | 3260 | sctp_disposition_t sctp_sf_operr_notify(struct net *net, |
3261 | const struct sctp_endpoint *ep, | ||
3209 | const struct sctp_association *asoc, | 3262 | const struct sctp_association *asoc, |
3210 | const sctp_subtype_t type, | 3263 | const sctp_subtype_t type, |
3211 | void *arg, | 3264 | void *arg, |
@@ -3215,15 +3268,15 @@ sctp_disposition_t sctp_sf_operr_notify(const struct sctp_endpoint *ep, | |||
3215 | sctp_errhdr_t *err; | 3268 | sctp_errhdr_t *err; |
3216 | 3269 | ||
3217 | if (!sctp_vtag_verify(chunk, asoc)) | 3270 | if (!sctp_vtag_verify(chunk, asoc)) |
3218 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 3271 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
3219 | 3272 | ||
3220 | /* Make sure that the ERROR chunk has a valid length. */ | 3273 | /* Make sure that the ERROR chunk has a valid length. */ |
3221 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_operr_chunk_t))) | 3274 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_operr_chunk_t))) |
3222 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 3275 | return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
3223 | commands); | 3276 | commands); |
3224 | sctp_walk_errors(err, chunk->chunk_hdr); | 3277 | sctp_walk_errors(err, chunk->chunk_hdr); |
3225 | if ((void *)err != (void *)chunk->chunk_end) | 3278 | if ((void *)err != (void *)chunk->chunk_end) |
3226 | return sctp_sf_violation_paramlen(ep, asoc, type, arg, | 3279 | return sctp_sf_violation_paramlen(net, ep, asoc, type, arg, |
3227 | (void *)err, commands); | 3280 | (void *)err, commands); |
3228 | 3281 | ||
3229 | sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_OPERR, | 3282 | sctp_add_cmd_sf(commands, SCTP_CMD_PROCESS_OPERR, |
@@ -3242,7 +3295,8 @@ sctp_disposition_t sctp_sf_operr_notify(const struct sctp_endpoint *ep, | |||
3242 | * | 3295 | * |
3243 | * The return value is the disposition. | 3296 | * The return value is the disposition. |
3244 | */ | 3297 | */ |
3245 | sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep, | 3298 | sctp_disposition_t sctp_sf_do_9_2_final(struct net *net, |
3299 | const struct sctp_endpoint *ep, | ||
3246 | const struct sctp_association *asoc, | 3300 | const struct sctp_association *asoc, |
3247 | const sctp_subtype_t type, | 3301 | const sctp_subtype_t type, |
3248 | void *arg, | 3302 | void *arg, |
@@ -3253,11 +3307,11 @@ sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep, | |||
3253 | struct sctp_ulpevent *ev; | 3307 | struct sctp_ulpevent *ev; |
3254 | 3308 | ||
3255 | if (!sctp_vtag_verify(chunk, asoc)) | 3309 | if (!sctp_vtag_verify(chunk, asoc)) |
3256 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 3310 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
3257 | 3311 | ||
3258 | /* Make sure that the SHUTDOWN_ACK chunk has a valid length. */ | 3312 | /* Make sure that the SHUTDOWN_ACK chunk has a valid length. */ |
3259 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t))) | 3313 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t))) |
3260 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 3314 | return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
3261 | commands); | 3315 | commands); |
3262 | /* 10.2 H) SHUTDOWN COMPLETE notification | 3316 | /* 10.2 H) SHUTDOWN COMPLETE notification |
3263 | * | 3317 | * |
@@ -3290,8 +3344,8 @@ sctp_disposition_t sctp_sf_do_9_2_final(const struct sctp_endpoint *ep, | |||
3290 | 3344 | ||
3291 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | 3345 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, |
3292 | SCTP_STATE(SCTP_STATE_CLOSED)); | 3346 | SCTP_STATE(SCTP_STATE_CLOSED)); |
3293 | SCTP_INC_STATS(SCTP_MIB_SHUTDOWNS); | 3347 | SCTP_INC_STATS(net, SCTP_MIB_SHUTDOWNS); |
3294 | SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); | 3348 | SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); |
3295 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); | 3349 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(reply)); |
3296 | 3350 | ||
3297 | /* ...and remove all record of the association. */ | 3351 | /* ...and remove all record of the association. */ |
@@ -3324,7 +3378,8 @@ nomem: | |||
3324 | * receiver of the OOTB packet shall discard the OOTB packet and take | 3378 | * receiver of the OOTB packet shall discard the OOTB packet and take |
3325 | * no further action. | 3379 | * no further action. |
3326 | */ | 3380 | */ |
3327 | sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep, | 3381 | sctp_disposition_t sctp_sf_ootb(struct net *net, |
3382 | const struct sctp_endpoint *ep, | ||
3328 | const struct sctp_association *asoc, | 3383 | const struct sctp_association *asoc, |
3329 | const sctp_subtype_t type, | 3384 | const sctp_subtype_t type, |
3330 | void *arg, | 3385 | void *arg, |
@@ -3338,13 +3393,13 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep, | |||
3338 | int ootb_shut_ack = 0; | 3393 | int ootb_shut_ack = 0; |
3339 | int ootb_cookie_ack = 0; | 3394 | int ootb_cookie_ack = 0; |
3340 | 3395 | ||
3341 | SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES); | 3396 | SCTP_INC_STATS(net, SCTP_MIB_OUTOFBLUES); |
3342 | 3397 | ||
3343 | ch = (sctp_chunkhdr_t *) chunk->chunk_hdr; | 3398 | ch = (sctp_chunkhdr_t *) chunk->chunk_hdr; |
3344 | do { | 3399 | do { |
3345 | /* Report violation if the chunk is less then minimal */ | 3400 | /* Report violation if the chunk is less then minimal */ |
3346 | if (ntohs(ch->length) < sizeof(sctp_chunkhdr_t)) | 3401 | if (ntohs(ch->length) < sizeof(sctp_chunkhdr_t)) |
3347 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 3402 | return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
3348 | commands); | 3403 | commands); |
3349 | 3404 | ||
3350 | /* Now that we know we at least have a chunk header, | 3405 | /* Now that we know we at least have a chunk header, |
@@ -3359,7 +3414,7 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep, | |||
3359 | * sending an ABORT of its own. | 3414 | * sending an ABORT of its own. |
3360 | */ | 3415 | */ |
3361 | if (SCTP_CID_ABORT == ch->type) | 3416 | if (SCTP_CID_ABORT == ch->type) |
3362 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 3417 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
3363 | 3418 | ||
3364 | /* RFC 8.4, 7) If the packet contains a "Stale cookie" ERROR | 3419 | /* RFC 8.4, 7) If the packet contains a "Stale cookie" ERROR |
3365 | * or a COOKIE ACK the SCTP Packet should be silently | 3420 | * or a COOKIE ACK the SCTP Packet should be silently |
@@ -3381,18 +3436,18 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep, | |||
3381 | /* Report violation if chunk len overflows */ | 3436 | /* Report violation if chunk len overflows */ |
3382 | ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length)); | 3437 | ch_end = ((__u8 *)ch) + WORD_ROUND(ntohs(ch->length)); |
3383 | if (ch_end > skb_tail_pointer(skb)) | 3438 | if (ch_end > skb_tail_pointer(skb)) |
3384 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 3439 | return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
3385 | commands); | 3440 | commands); |
3386 | 3441 | ||
3387 | ch = (sctp_chunkhdr_t *) ch_end; | 3442 | ch = (sctp_chunkhdr_t *) ch_end; |
3388 | } while (ch_end < skb_tail_pointer(skb)); | 3443 | } while (ch_end < skb_tail_pointer(skb)); |
3389 | 3444 | ||
3390 | if (ootb_shut_ack) | 3445 | if (ootb_shut_ack) |
3391 | return sctp_sf_shut_8_4_5(ep, asoc, type, arg, commands); | 3446 | return sctp_sf_shut_8_4_5(net, ep, asoc, type, arg, commands); |
3392 | else if (ootb_cookie_ack) | 3447 | else if (ootb_cookie_ack) |
3393 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 3448 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
3394 | else | 3449 | else |
3395 | return sctp_sf_tabort_8_4_8(ep, asoc, type, arg, commands); | 3450 | return sctp_sf_tabort_8_4_8(net, ep, asoc, type, arg, commands); |
3396 | } | 3451 | } |
3397 | 3452 | ||
3398 | /* | 3453 | /* |
@@ -3416,7 +3471,8 @@ sctp_disposition_t sctp_sf_ootb(const struct sctp_endpoint *ep, | |||
3416 | * | 3471 | * |
3417 | * The return value is the disposition of the chunk. | 3472 | * The return value is the disposition of the chunk. |
3418 | */ | 3473 | */ |
3419 | static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep, | 3474 | static sctp_disposition_t sctp_sf_shut_8_4_5(struct net *net, |
3475 | const struct sctp_endpoint *ep, | ||
3420 | const struct sctp_association *asoc, | 3476 | const struct sctp_association *asoc, |
3421 | const sctp_subtype_t type, | 3477 | const sctp_subtype_t type, |
3422 | void *arg, | 3478 | void *arg, |
@@ -3426,7 +3482,7 @@ static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep, | |||
3426 | struct sctp_chunk *chunk = arg; | 3482 | struct sctp_chunk *chunk = arg; |
3427 | struct sctp_chunk *shut; | 3483 | struct sctp_chunk *shut; |
3428 | 3484 | ||
3429 | packet = sctp_ootb_pkt_new(asoc, chunk); | 3485 | packet = sctp_ootb_pkt_new(net, asoc, chunk); |
3430 | 3486 | ||
3431 | if (packet) { | 3487 | if (packet) { |
3432 | /* Make an SHUTDOWN_COMPLETE. | 3488 | /* Make an SHUTDOWN_COMPLETE. |
@@ -3450,19 +3506,19 @@ static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep, | |||
3450 | sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, | 3506 | sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, |
3451 | SCTP_PACKET(packet)); | 3507 | SCTP_PACKET(packet)); |
3452 | 3508 | ||
3453 | SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); | 3509 | SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); |
3454 | 3510 | ||
3455 | /* If the chunk length is invalid, we don't want to process | 3511 | /* If the chunk length is invalid, we don't want to process |
3456 | * the reset of the packet. | 3512 | * the reset of the packet. |
3457 | */ | 3513 | */ |
3458 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t))) | 3514 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t))) |
3459 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 3515 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
3460 | 3516 | ||
3461 | /* We need to discard the rest of the packet to prevent | 3517 | /* We need to discard the rest of the packet to prevent |
3462 | * potential bomming attacks from additional bundled chunks. | 3518 | * potential bomming attacks from additional bundled chunks. |
3463 | * This is documented in SCTP Threats ID. | 3519 | * This is documented in SCTP Threats ID. |
3464 | */ | 3520 | */ |
3465 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 3521 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
3466 | } | 3522 | } |
3467 | 3523 | ||
3468 | return SCTP_DISPOSITION_NOMEM; | 3524 | return SCTP_DISPOSITION_NOMEM; |
@@ -3479,7 +3535,8 @@ static sctp_disposition_t sctp_sf_shut_8_4_5(const struct sctp_endpoint *ep, | |||
3479 | * chunks. --piggy ] | 3535 | * chunks. --piggy ] |
3480 | * | 3536 | * |
3481 | */ | 3537 | */ |
3482 | sctp_disposition_t sctp_sf_do_8_5_1_E_sa(const struct sctp_endpoint *ep, | 3538 | sctp_disposition_t sctp_sf_do_8_5_1_E_sa(struct net *net, |
3539 | const struct sctp_endpoint *ep, | ||
3483 | const struct sctp_association *asoc, | 3540 | const struct sctp_association *asoc, |
3484 | const sctp_subtype_t type, | 3541 | const sctp_subtype_t type, |
3485 | void *arg, | 3542 | void *arg, |
@@ -3489,7 +3546,7 @@ sctp_disposition_t sctp_sf_do_8_5_1_E_sa(const struct sctp_endpoint *ep, | |||
3489 | 3546 | ||
3490 | /* Make sure that the SHUTDOWN_ACK chunk has a valid length. */ | 3547 | /* Make sure that the SHUTDOWN_ACK chunk has a valid length. */ |
3491 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t))) | 3548 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t))) |
3492 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 3549 | return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
3493 | commands); | 3550 | commands); |
3494 | 3551 | ||
3495 | /* Although we do have an association in this case, it corresponds | 3552 | /* Although we do have an association in this case, it corresponds |
@@ -3497,13 +3554,14 @@ sctp_disposition_t sctp_sf_do_8_5_1_E_sa(const struct sctp_endpoint *ep, | |||
3497 | * packet and the state function that handles OOTB SHUTDOWN_ACK is | 3554 | * packet and the state function that handles OOTB SHUTDOWN_ACK is |
3498 | * called with a NULL association. | 3555 | * called with a NULL association. |
3499 | */ | 3556 | */ |
3500 | SCTP_INC_STATS(SCTP_MIB_OUTOFBLUES); | 3557 | SCTP_INC_STATS(net, SCTP_MIB_OUTOFBLUES); |
3501 | 3558 | ||
3502 | return sctp_sf_shut_8_4_5(ep, NULL, type, arg, commands); | 3559 | return sctp_sf_shut_8_4_5(net, ep, NULL, type, arg, commands); |
3503 | } | 3560 | } |
3504 | 3561 | ||
3505 | /* ADDIP Section 4.2 Upon reception of an ASCONF Chunk. */ | 3562 | /* ADDIP Section 4.2 Upon reception of an ASCONF Chunk. */ |
3506 | sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep, | 3563 | sctp_disposition_t sctp_sf_do_asconf(struct net *net, |
3564 | const struct sctp_endpoint *ep, | ||
3507 | const struct sctp_association *asoc, | 3565 | const struct sctp_association *asoc, |
3508 | const sctp_subtype_t type, void *arg, | 3566 | const sctp_subtype_t type, void *arg, |
3509 | sctp_cmd_seq_t *commands) | 3567 | sctp_cmd_seq_t *commands) |
@@ -3519,7 +3577,7 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep, | |||
3519 | if (!sctp_vtag_verify(chunk, asoc)) { | 3577 | if (!sctp_vtag_verify(chunk, asoc)) { |
3520 | sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, | 3578 | sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, |
3521 | SCTP_NULL()); | 3579 | SCTP_NULL()); |
3522 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 3580 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
3523 | } | 3581 | } |
3524 | 3582 | ||
3525 | /* ADD-IP: Section 4.1.1 | 3583 | /* ADD-IP: Section 4.1.1 |
@@ -3528,12 +3586,12 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep, | |||
3528 | * is received unauthenticated it MUST be silently discarded as | 3586 | * is received unauthenticated it MUST be silently discarded as |
3529 | * described in [I-D.ietf-tsvwg-sctp-auth]. | 3587 | * described in [I-D.ietf-tsvwg-sctp-auth]. |
3530 | */ | 3588 | */ |
3531 | if (!sctp_addip_noauth && !chunk->auth) | 3589 | if (!net->sctp.addip_noauth && !chunk->auth) |
3532 | return sctp_sf_discard_chunk(ep, asoc, type, arg, commands); | 3590 | return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands); |
3533 | 3591 | ||
3534 | /* Make sure that the ASCONF ADDIP chunk has a valid length. */ | 3592 | /* Make sure that the ASCONF ADDIP chunk has a valid length. */ |
3535 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_addip_chunk_t))) | 3593 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_addip_chunk_t))) |
3536 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 3594 | return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
3537 | commands); | 3595 | commands); |
3538 | 3596 | ||
3539 | hdr = (sctp_addiphdr_t *)chunk->skb->data; | 3597 | hdr = (sctp_addiphdr_t *)chunk->skb->data; |
@@ -3542,7 +3600,7 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep, | |||
3542 | addr_param = (union sctp_addr_param *)hdr->params; | 3600 | addr_param = (union sctp_addr_param *)hdr->params; |
3543 | length = ntohs(addr_param->p.length); | 3601 | length = ntohs(addr_param->p.length); |
3544 | if (length < sizeof(sctp_paramhdr_t)) | 3602 | if (length < sizeof(sctp_paramhdr_t)) |
3545 | return sctp_sf_violation_paramlen(ep, asoc, type, arg, | 3603 | return sctp_sf_violation_paramlen(net, ep, asoc, type, arg, |
3546 | (void *)addr_param, commands); | 3604 | (void *)addr_param, commands); |
3547 | 3605 | ||
3548 | /* Verify the ASCONF chunk before processing it. */ | 3606 | /* Verify the ASCONF chunk before processing it. */ |
@@ -3550,7 +3608,7 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep, | |||
3550 | (sctp_paramhdr_t *)((void *)addr_param + length), | 3608 | (sctp_paramhdr_t *)((void *)addr_param + length), |
3551 | (void *)chunk->chunk_end, | 3609 | (void *)chunk->chunk_end, |
3552 | &err_param)) | 3610 | &err_param)) |
3553 | return sctp_sf_violation_paramlen(ep, asoc, type, arg, | 3611 | return sctp_sf_violation_paramlen(net, ep, asoc, type, arg, |
3554 | (void *)err_param, commands); | 3612 | (void *)err_param, commands); |
3555 | 3613 | ||
3556 | /* ADDIP 5.2 E1) Compare the value of the serial number to the value | 3614 | /* ADDIP 5.2 E1) Compare the value of the serial number to the value |
@@ -3630,7 +3688,8 @@ sctp_disposition_t sctp_sf_do_asconf(const struct sctp_endpoint *ep, | |||
3630 | * When building TLV parameters for the ASCONF Chunk that will add or | 3688 | * When building TLV parameters for the ASCONF Chunk that will add or |
3631 | * delete IP addresses the D0 to D13 rules should be applied: | 3689 | * delete IP addresses the D0 to D13 rules should be applied: |
3632 | */ | 3690 | */ |
3633 | sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep, | 3691 | sctp_disposition_t sctp_sf_do_asconf_ack(struct net *net, |
3692 | const struct sctp_endpoint *ep, | ||
3634 | const struct sctp_association *asoc, | 3693 | const struct sctp_association *asoc, |
3635 | const sctp_subtype_t type, void *arg, | 3694 | const sctp_subtype_t type, void *arg, |
3636 | sctp_cmd_seq_t *commands) | 3695 | sctp_cmd_seq_t *commands) |
@@ -3645,7 +3704,7 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep, | |||
3645 | if (!sctp_vtag_verify(asconf_ack, asoc)) { | 3704 | if (!sctp_vtag_verify(asconf_ack, asoc)) { |
3646 | sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, | 3705 | sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, |
3647 | SCTP_NULL()); | 3706 | SCTP_NULL()); |
3648 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 3707 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
3649 | } | 3708 | } |
3650 | 3709 | ||
3651 | /* ADD-IP, Section 4.1.2: | 3710 | /* ADD-IP, Section 4.1.2: |
@@ -3654,12 +3713,12 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep, | |||
3654 | * is received unauthenticated it MUST be silently discarded as | 3713 | * is received unauthenticated it MUST be silently discarded as |
3655 | * described in [I-D.ietf-tsvwg-sctp-auth]. | 3714 | * described in [I-D.ietf-tsvwg-sctp-auth]. |
3656 | */ | 3715 | */ |
3657 | if (!sctp_addip_noauth && !asconf_ack->auth) | 3716 | if (!net->sctp.addip_noauth && !asconf_ack->auth) |
3658 | return sctp_sf_discard_chunk(ep, asoc, type, arg, commands); | 3717 | return sctp_sf_discard_chunk(net, ep, asoc, type, arg, commands); |
3659 | 3718 | ||
3660 | /* Make sure that the ADDIP chunk has a valid length. */ | 3719 | /* Make sure that the ADDIP chunk has a valid length. */ |
3661 | if (!sctp_chunk_length_valid(asconf_ack, sizeof(sctp_addip_chunk_t))) | 3720 | if (!sctp_chunk_length_valid(asconf_ack, sizeof(sctp_addip_chunk_t))) |
3662 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 3721 | return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
3663 | commands); | 3722 | commands); |
3664 | 3723 | ||
3665 | addip_hdr = (sctp_addiphdr_t *)asconf_ack->skb->data; | 3724 | addip_hdr = (sctp_addiphdr_t *)asconf_ack->skb->data; |
@@ -3670,7 +3729,7 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep, | |||
3670 | (sctp_paramhdr_t *)addip_hdr->params, | 3729 | (sctp_paramhdr_t *)addip_hdr->params, |
3671 | (void *)asconf_ack->chunk_end, | 3730 | (void *)asconf_ack->chunk_end, |
3672 | &err_param)) | 3731 | &err_param)) |
3673 | return sctp_sf_violation_paramlen(ep, asoc, type, arg, | 3732 | return sctp_sf_violation_paramlen(net, ep, asoc, type, arg, |
3674 | (void *)err_param, commands); | 3733 | (void *)err_param, commands); |
3675 | 3734 | ||
3676 | if (last_asconf) { | 3735 | if (last_asconf) { |
@@ -3705,8 +3764,8 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep, | |||
3705 | SCTP_ERROR(ECONNABORTED)); | 3764 | SCTP_ERROR(ECONNABORTED)); |
3706 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 3765 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
3707 | SCTP_PERR(SCTP_ERROR_ASCONF_ACK)); | 3766 | SCTP_PERR(SCTP_ERROR_ASCONF_ACK)); |
3708 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 3767 | SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); |
3709 | SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); | 3768 | SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); |
3710 | return SCTP_DISPOSITION_ABORT; | 3769 | return SCTP_DISPOSITION_ABORT; |
3711 | } | 3770 | } |
3712 | 3771 | ||
@@ -3739,8 +3798,8 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep, | |||
3739 | SCTP_ERROR(ECONNABORTED)); | 3798 | SCTP_ERROR(ECONNABORTED)); |
3740 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 3799 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
3741 | SCTP_PERR(SCTP_ERROR_ASCONF_ACK)); | 3800 | SCTP_PERR(SCTP_ERROR_ASCONF_ACK)); |
3742 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 3801 | SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); |
3743 | SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); | 3802 | SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); |
3744 | return SCTP_DISPOSITION_ABORT; | 3803 | return SCTP_DISPOSITION_ABORT; |
3745 | } | 3804 | } |
3746 | 3805 | ||
@@ -3761,7 +3820,8 @@ sctp_disposition_t sctp_sf_do_asconf_ack(const struct sctp_endpoint *ep, | |||
3761 | * | 3820 | * |
3762 | * The return value is the disposition of the chunk. | 3821 | * The return value is the disposition of the chunk. |
3763 | */ | 3822 | */ |
3764 | sctp_disposition_t sctp_sf_eat_fwd_tsn(const struct sctp_endpoint *ep, | 3823 | sctp_disposition_t sctp_sf_eat_fwd_tsn(struct net *net, |
3824 | const struct sctp_endpoint *ep, | ||
3765 | const struct sctp_association *asoc, | 3825 | const struct sctp_association *asoc, |
3766 | const sctp_subtype_t type, | 3826 | const sctp_subtype_t type, |
3767 | void *arg, | 3827 | void *arg, |
@@ -3776,12 +3836,12 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn(const struct sctp_endpoint *ep, | |||
3776 | if (!sctp_vtag_verify(chunk, asoc)) { | 3836 | if (!sctp_vtag_verify(chunk, asoc)) { |
3777 | sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, | 3837 | sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, |
3778 | SCTP_NULL()); | 3838 | SCTP_NULL()); |
3779 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 3839 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
3780 | } | 3840 | } |
3781 | 3841 | ||
3782 | /* Make sure that the FORWARD_TSN chunk has valid length. */ | 3842 | /* Make sure that the FORWARD_TSN chunk has valid length. */ |
3783 | if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_fwdtsn_chunk))) | 3843 | if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_fwdtsn_chunk))) |
3784 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 3844 | return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
3785 | commands); | 3845 | commands); |
3786 | 3846 | ||
3787 | fwdtsn_hdr = (struct sctp_fwdtsn_hdr *)chunk->skb->data; | 3847 | fwdtsn_hdr = (struct sctp_fwdtsn_hdr *)chunk->skb->data; |
@@ -3828,6 +3888,7 @@ discard_noforce: | |||
3828 | } | 3888 | } |
3829 | 3889 | ||
3830 | sctp_disposition_t sctp_sf_eat_fwd_tsn_fast( | 3890 | sctp_disposition_t sctp_sf_eat_fwd_tsn_fast( |
3891 | struct net *net, | ||
3831 | const struct sctp_endpoint *ep, | 3892 | const struct sctp_endpoint *ep, |
3832 | const struct sctp_association *asoc, | 3893 | const struct sctp_association *asoc, |
3833 | const sctp_subtype_t type, | 3894 | const sctp_subtype_t type, |
@@ -3843,12 +3904,12 @@ sctp_disposition_t sctp_sf_eat_fwd_tsn_fast( | |||
3843 | if (!sctp_vtag_verify(chunk, asoc)) { | 3904 | if (!sctp_vtag_verify(chunk, asoc)) { |
3844 | sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, | 3905 | sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, |
3845 | SCTP_NULL()); | 3906 | SCTP_NULL()); |
3846 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 3907 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
3847 | } | 3908 | } |
3848 | 3909 | ||
3849 | /* Make sure that the FORWARD_TSN chunk has a valid length. */ | 3910 | /* Make sure that the FORWARD_TSN chunk has a valid length. */ |
3850 | if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_fwdtsn_chunk))) | 3911 | if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_fwdtsn_chunk))) |
3851 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 3912 | return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
3852 | commands); | 3913 | commands); |
3853 | 3914 | ||
3854 | fwdtsn_hdr = (struct sctp_fwdtsn_hdr *)chunk->skb->data; | 3915 | fwdtsn_hdr = (struct sctp_fwdtsn_hdr *)chunk->skb->data; |
@@ -3915,7 +3976,8 @@ gen_shutdown: | |||
3915 | * | 3976 | * |
3916 | * The return value is the disposition of the chunk. | 3977 | * The return value is the disposition of the chunk. |
3917 | */ | 3978 | */ |
3918 | static sctp_ierror_t sctp_sf_authenticate(const struct sctp_endpoint *ep, | 3979 | static sctp_ierror_t sctp_sf_authenticate(struct net *net, |
3980 | const struct sctp_endpoint *ep, | ||
3919 | const struct sctp_association *asoc, | 3981 | const struct sctp_association *asoc, |
3920 | const sctp_subtype_t type, | 3982 | const sctp_subtype_t type, |
3921 | struct sctp_chunk *chunk) | 3983 | struct sctp_chunk *chunk) |
@@ -3988,7 +4050,8 @@ nomem: | |||
3988 | return SCTP_IERROR_NOMEM; | 4050 | return SCTP_IERROR_NOMEM; |
3989 | } | 4051 | } |
3990 | 4052 | ||
3991 | sctp_disposition_t sctp_sf_eat_auth(const struct sctp_endpoint *ep, | 4053 | sctp_disposition_t sctp_sf_eat_auth(struct net *net, |
4054 | const struct sctp_endpoint *ep, | ||
3992 | const struct sctp_association *asoc, | 4055 | const struct sctp_association *asoc, |
3993 | const sctp_subtype_t type, | 4056 | const sctp_subtype_t type, |
3994 | void *arg, | 4057 | void *arg, |
@@ -4001,21 +4064,21 @@ sctp_disposition_t sctp_sf_eat_auth(const struct sctp_endpoint *ep, | |||
4001 | 4064 | ||
4002 | /* Make sure that the peer has AUTH capable */ | 4065 | /* Make sure that the peer has AUTH capable */ |
4003 | if (!asoc->peer.auth_capable) | 4066 | if (!asoc->peer.auth_capable) |
4004 | return sctp_sf_unk_chunk(ep, asoc, type, arg, commands); | 4067 | return sctp_sf_unk_chunk(net, ep, asoc, type, arg, commands); |
4005 | 4068 | ||
4006 | if (!sctp_vtag_verify(chunk, asoc)) { | 4069 | if (!sctp_vtag_verify(chunk, asoc)) { |
4007 | sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, | 4070 | sctp_add_cmd_sf(commands, SCTP_CMD_REPORT_BAD_TAG, |
4008 | SCTP_NULL()); | 4071 | SCTP_NULL()); |
4009 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 4072 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
4010 | } | 4073 | } |
4011 | 4074 | ||
4012 | /* Make sure that the AUTH chunk has valid length. */ | 4075 | /* Make sure that the AUTH chunk has valid length. */ |
4013 | if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_auth_chunk))) | 4076 | if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_auth_chunk))) |
4014 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 4077 | return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
4015 | commands); | 4078 | commands); |
4016 | 4079 | ||
4017 | auth_hdr = (struct sctp_authhdr *)chunk->skb->data; | 4080 | auth_hdr = (struct sctp_authhdr *)chunk->skb->data; |
4018 | error = sctp_sf_authenticate(ep, asoc, type, chunk); | 4081 | error = sctp_sf_authenticate(net, ep, asoc, type, chunk); |
4019 | switch (error) { | 4082 | switch (error) { |
4020 | case SCTP_IERROR_AUTH_BAD_HMAC: | 4083 | case SCTP_IERROR_AUTH_BAD_HMAC: |
4021 | /* Generate the ERROR chunk and discard the rest | 4084 | /* Generate the ERROR chunk and discard the rest |
@@ -4032,10 +4095,10 @@ sctp_disposition_t sctp_sf_eat_auth(const struct sctp_endpoint *ep, | |||
4032 | /* Fall Through */ | 4095 | /* Fall Through */ |
4033 | case SCTP_IERROR_AUTH_BAD_KEYID: | 4096 | case SCTP_IERROR_AUTH_BAD_KEYID: |
4034 | case SCTP_IERROR_BAD_SIG: | 4097 | case SCTP_IERROR_BAD_SIG: |
4035 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 4098 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
4036 | 4099 | ||
4037 | case SCTP_IERROR_PROTO_VIOLATION: | 4100 | case SCTP_IERROR_PROTO_VIOLATION: |
4038 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 4101 | return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
4039 | commands); | 4102 | commands); |
4040 | 4103 | ||
4041 | case SCTP_IERROR_NOMEM: | 4104 | case SCTP_IERROR_NOMEM: |
@@ -4084,7 +4147,8 @@ sctp_disposition_t sctp_sf_eat_auth(const struct sctp_endpoint *ep, | |||
4084 | * | 4147 | * |
4085 | * The return value is the disposition of the chunk. | 4148 | * The return value is the disposition of the chunk. |
4086 | */ | 4149 | */ |
4087 | sctp_disposition_t sctp_sf_unk_chunk(const struct sctp_endpoint *ep, | 4150 | sctp_disposition_t sctp_sf_unk_chunk(struct net *net, |
4151 | const struct sctp_endpoint *ep, | ||
4088 | const struct sctp_association *asoc, | 4152 | const struct sctp_association *asoc, |
4089 | const sctp_subtype_t type, | 4153 | const sctp_subtype_t type, |
4090 | void *arg, | 4154 | void *arg, |
@@ -4097,20 +4161,20 @@ sctp_disposition_t sctp_sf_unk_chunk(const struct sctp_endpoint *ep, | |||
4097 | SCTP_DEBUG_PRINTK("Processing the unknown chunk id %d.\n", type.chunk); | 4161 | SCTP_DEBUG_PRINTK("Processing the unknown chunk id %d.\n", type.chunk); |
4098 | 4162 | ||
4099 | if (!sctp_vtag_verify(unk_chunk, asoc)) | 4163 | if (!sctp_vtag_verify(unk_chunk, asoc)) |
4100 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 4164 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
4101 | 4165 | ||
4102 | /* Make sure that the chunk has a valid length. | 4166 | /* Make sure that the chunk has a valid length. |
4103 | * Since we don't know the chunk type, we use a general | 4167 | * Since we don't know the chunk type, we use a general |
4104 | * chunkhdr structure to make a comparison. | 4168 | * chunkhdr structure to make a comparison. |
4105 | */ | 4169 | */ |
4106 | if (!sctp_chunk_length_valid(unk_chunk, sizeof(sctp_chunkhdr_t))) | 4170 | if (!sctp_chunk_length_valid(unk_chunk, sizeof(sctp_chunkhdr_t))) |
4107 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 4171 | return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
4108 | commands); | 4172 | commands); |
4109 | 4173 | ||
4110 | switch (type.chunk & SCTP_CID_ACTION_MASK) { | 4174 | switch (type.chunk & SCTP_CID_ACTION_MASK) { |
4111 | case SCTP_CID_ACTION_DISCARD: | 4175 | case SCTP_CID_ACTION_DISCARD: |
4112 | /* Discard the packet. */ | 4176 | /* Discard the packet. */ |
4113 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 4177 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
4114 | break; | 4178 | break; |
4115 | case SCTP_CID_ACTION_DISCARD_ERR: | 4179 | case SCTP_CID_ACTION_DISCARD_ERR: |
4116 | /* Generate an ERROR chunk as response. */ | 4180 | /* Generate an ERROR chunk as response. */ |
@@ -4125,7 +4189,7 @@ sctp_disposition_t sctp_sf_unk_chunk(const struct sctp_endpoint *ep, | |||
4125 | } | 4189 | } |
4126 | 4190 | ||
4127 | /* Discard the packet. */ | 4191 | /* Discard the packet. */ |
4128 | sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 4192 | sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
4129 | return SCTP_DISPOSITION_CONSUME; | 4193 | return SCTP_DISPOSITION_CONSUME; |
4130 | break; | 4194 | break; |
4131 | case SCTP_CID_ACTION_SKIP: | 4195 | case SCTP_CID_ACTION_SKIP: |
@@ -4167,7 +4231,8 @@ sctp_disposition_t sctp_sf_unk_chunk(const struct sctp_endpoint *ep, | |||
4167 | * | 4231 | * |
4168 | * The return value is the disposition of the chunk. | 4232 | * The return value is the disposition of the chunk. |
4169 | */ | 4233 | */ |
4170 | sctp_disposition_t sctp_sf_discard_chunk(const struct sctp_endpoint *ep, | 4234 | sctp_disposition_t sctp_sf_discard_chunk(struct net *net, |
4235 | const struct sctp_endpoint *ep, | ||
4171 | const struct sctp_association *asoc, | 4236 | const struct sctp_association *asoc, |
4172 | const sctp_subtype_t type, | 4237 | const sctp_subtype_t type, |
4173 | void *arg, | 4238 | void *arg, |
@@ -4180,7 +4245,7 @@ sctp_disposition_t sctp_sf_discard_chunk(const struct sctp_endpoint *ep, | |||
4180 | * chunkhdr structure to make a comparison. | 4245 | * chunkhdr structure to make a comparison. |
4181 | */ | 4246 | */ |
4182 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t))) | 4247 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t))) |
4183 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 4248 | return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
4184 | commands); | 4249 | commands); |
4185 | 4250 | ||
4186 | SCTP_DEBUG_PRINTK("Chunk %d is discarded\n", type.chunk); | 4251 | SCTP_DEBUG_PRINTK("Chunk %d is discarded\n", type.chunk); |
@@ -4205,13 +4270,14 @@ sctp_disposition_t sctp_sf_discard_chunk(const struct sctp_endpoint *ep, | |||
4205 | * | 4270 | * |
4206 | * The return value is the disposition of the chunk. | 4271 | * The return value is the disposition of the chunk. |
4207 | */ | 4272 | */ |
4208 | sctp_disposition_t sctp_sf_pdiscard(const struct sctp_endpoint *ep, | 4273 | sctp_disposition_t sctp_sf_pdiscard(struct net *net, |
4274 | const struct sctp_endpoint *ep, | ||
4209 | const struct sctp_association *asoc, | 4275 | const struct sctp_association *asoc, |
4210 | const sctp_subtype_t type, | 4276 | const sctp_subtype_t type, |
4211 | void *arg, | 4277 | void *arg, |
4212 | sctp_cmd_seq_t *commands) | 4278 | sctp_cmd_seq_t *commands) |
4213 | { | 4279 | { |
4214 | SCTP_INC_STATS(SCTP_MIB_IN_PKT_DISCARDS); | 4280 | SCTP_INC_STATS(net, SCTP_MIB_IN_PKT_DISCARDS); |
4215 | sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL()); | 4281 | sctp_add_cmd_sf(commands, SCTP_CMD_DISCARD_PACKET, SCTP_NULL()); |
4216 | 4282 | ||
4217 | return SCTP_DISPOSITION_CONSUME; | 4283 | return SCTP_DISPOSITION_CONSUME; |
@@ -4232,7 +4298,8 @@ sctp_disposition_t sctp_sf_pdiscard(const struct sctp_endpoint *ep, | |||
4232 | * We simply tag the chunk as a violation. The state machine will log | 4298 | * We simply tag the chunk as a violation. The state machine will log |
4233 | * the violation and continue. | 4299 | * the violation and continue. |
4234 | */ | 4300 | */ |
4235 | sctp_disposition_t sctp_sf_violation(const struct sctp_endpoint *ep, | 4301 | sctp_disposition_t sctp_sf_violation(struct net *net, |
4302 | const struct sctp_endpoint *ep, | ||
4236 | const struct sctp_association *asoc, | 4303 | const struct sctp_association *asoc, |
4237 | const sctp_subtype_t type, | 4304 | const sctp_subtype_t type, |
4238 | void *arg, | 4305 | void *arg, |
@@ -4242,7 +4309,7 @@ sctp_disposition_t sctp_sf_violation(const struct sctp_endpoint *ep, | |||
4242 | 4309 | ||
4243 | /* Make sure that the chunk has a valid length. */ | 4310 | /* Make sure that the chunk has a valid length. */ |
4244 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t))) | 4311 | if (!sctp_chunk_length_valid(chunk, sizeof(sctp_chunkhdr_t))) |
4245 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 4312 | return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
4246 | commands); | 4313 | commands); |
4247 | 4314 | ||
4248 | return SCTP_DISPOSITION_VIOLATION; | 4315 | return SCTP_DISPOSITION_VIOLATION; |
@@ -4252,6 +4319,7 @@ sctp_disposition_t sctp_sf_violation(const struct sctp_endpoint *ep, | |||
4252 | * Common function to handle a protocol violation. | 4319 | * Common function to handle a protocol violation. |
4253 | */ | 4320 | */ |
4254 | static sctp_disposition_t sctp_sf_abort_violation( | 4321 | static sctp_disposition_t sctp_sf_abort_violation( |
4322 | struct net *net, | ||
4255 | const struct sctp_endpoint *ep, | 4323 | const struct sctp_endpoint *ep, |
4256 | const struct sctp_association *asoc, | 4324 | const struct sctp_association *asoc, |
4257 | void *arg, | 4325 | void *arg, |
@@ -4302,7 +4370,7 @@ static sctp_disposition_t sctp_sf_abort_violation( | |||
4302 | } | 4370 | } |
4303 | 4371 | ||
4304 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); | 4372 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); |
4305 | SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); | 4373 | SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); |
4306 | 4374 | ||
4307 | if (asoc->state <= SCTP_STATE_COOKIE_ECHOED) { | 4375 | if (asoc->state <= SCTP_STATE_COOKIE_ECHOED) { |
4308 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 4376 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
@@ -4316,10 +4384,10 @@ static sctp_disposition_t sctp_sf_abort_violation( | |||
4316 | SCTP_ERROR(ECONNABORTED)); | 4384 | SCTP_ERROR(ECONNABORTED)); |
4317 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 4385 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
4318 | SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION)); | 4386 | SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION)); |
4319 | SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); | 4387 | SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); |
4320 | } | 4388 | } |
4321 | } else { | 4389 | } else { |
4322 | packet = sctp_ootb_pkt_new(asoc, chunk); | 4390 | packet = sctp_ootb_pkt_new(net, asoc, chunk); |
4323 | 4391 | ||
4324 | if (!packet) | 4392 | if (!packet) |
4325 | goto nomem_pkt; | 4393 | goto nomem_pkt; |
@@ -4334,13 +4402,13 @@ static sctp_disposition_t sctp_sf_abort_violation( | |||
4334 | sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, | 4402 | sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, |
4335 | SCTP_PACKET(packet)); | 4403 | SCTP_PACKET(packet)); |
4336 | 4404 | ||
4337 | SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); | 4405 | SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); |
4338 | } | 4406 | } |
4339 | 4407 | ||
4340 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 4408 | SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); |
4341 | 4409 | ||
4342 | discard: | 4410 | discard: |
4343 | sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands); | 4411 | sctp_sf_pdiscard(net, ep, asoc, SCTP_ST_CHUNK(0), arg, commands); |
4344 | return SCTP_DISPOSITION_ABORT; | 4412 | return SCTP_DISPOSITION_ABORT; |
4345 | 4413 | ||
4346 | nomem_pkt: | 4414 | nomem_pkt: |
@@ -4369,6 +4437,7 @@ nomem: | |||
4369 | * Generate an ABORT chunk and terminate the association. | 4437 | * Generate an ABORT chunk and terminate the association. |
4370 | */ | 4438 | */ |
4371 | static sctp_disposition_t sctp_sf_violation_chunklen( | 4439 | static sctp_disposition_t sctp_sf_violation_chunklen( |
4440 | struct net *net, | ||
4372 | const struct sctp_endpoint *ep, | 4441 | const struct sctp_endpoint *ep, |
4373 | const struct sctp_association *asoc, | 4442 | const struct sctp_association *asoc, |
4374 | const sctp_subtype_t type, | 4443 | const sctp_subtype_t type, |
@@ -4377,7 +4446,7 @@ static sctp_disposition_t sctp_sf_violation_chunklen( | |||
4377 | { | 4446 | { |
4378 | static const char err_str[]="The following chunk had invalid length:"; | 4447 | static const char err_str[]="The following chunk had invalid length:"; |
4379 | 4448 | ||
4380 | return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str, | 4449 | return sctp_sf_abort_violation(net, ep, asoc, arg, commands, err_str, |
4381 | sizeof(err_str)); | 4450 | sizeof(err_str)); |
4382 | } | 4451 | } |
4383 | 4452 | ||
@@ -4388,6 +4457,7 @@ static sctp_disposition_t sctp_sf_violation_chunklen( | |||
4388 | * the length is considered as invalid. | 4457 | * the length is considered as invalid. |
4389 | */ | 4458 | */ |
4390 | static sctp_disposition_t sctp_sf_violation_paramlen( | 4459 | static sctp_disposition_t sctp_sf_violation_paramlen( |
4460 | struct net *net, | ||
4391 | const struct sctp_endpoint *ep, | 4461 | const struct sctp_endpoint *ep, |
4392 | const struct sctp_association *asoc, | 4462 | const struct sctp_association *asoc, |
4393 | const sctp_subtype_t type, | 4463 | const sctp_subtype_t type, |
@@ -4407,17 +4477,17 @@ static sctp_disposition_t sctp_sf_violation_paramlen( | |||
4407 | goto nomem; | 4477 | goto nomem; |
4408 | 4478 | ||
4409 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); | 4479 | sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(abort)); |
4410 | SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); | 4480 | SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); |
4411 | 4481 | ||
4412 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, | 4482 | sctp_add_cmd_sf(commands, SCTP_CMD_SET_SK_ERR, |
4413 | SCTP_ERROR(ECONNABORTED)); | 4483 | SCTP_ERROR(ECONNABORTED)); |
4414 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 4484 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
4415 | SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION)); | 4485 | SCTP_PERR(SCTP_ERROR_PROTO_VIOLATION)); |
4416 | SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); | 4486 | SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); |
4417 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 4487 | SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); |
4418 | 4488 | ||
4419 | discard: | 4489 | discard: |
4420 | sctp_sf_pdiscard(ep, asoc, SCTP_ST_CHUNK(0), arg, commands); | 4490 | sctp_sf_pdiscard(net, ep, asoc, SCTP_ST_CHUNK(0), arg, commands); |
4421 | return SCTP_DISPOSITION_ABORT; | 4491 | return SCTP_DISPOSITION_ABORT; |
4422 | nomem: | 4492 | nomem: |
4423 | return SCTP_DISPOSITION_NOMEM; | 4493 | return SCTP_DISPOSITION_NOMEM; |
@@ -4430,6 +4500,7 @@ nomem: | |||
4430 | * error code. | 4500 | * error code. |
4431 | */ | 4501 | */ |
4432 | static sctp_disposition_t sctp_sf_violation_ctsn( | 4502 | static sctp_disposition_t sctp_sf_violation_ctsn( |
4503 | struct net *net, | ||
4433 | const struct sctp_endpoint *ep, | 4504 | const struct sctp_endpoint *ep, |
4434 | const struct sctp_association *asoc, | 4505 | const struct sctp_association *asoc, |
4435 | const sctp_subtype_t type, | 4506 | const sctp_subtype_t type, |
@@ -4438,7 +4509,7 @@ static sctp_disposition_t sctp_sf_violation_ctsn( | |||
4438 | { | 4509 | { |
4439 | static const char err_str[]="The cumulative tsn ack beyond the max tsn currently sent:"; | 4510 | static const char err_str[]="The cumulative tsn ack beyond the max tsn currently sent:"; |
4440 | 4511 | ||
4441 | return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str, | 4512 | return sctp_sf_abort_violation(net, ep, asoc, arg, commands, err_str, |
4442 | sizeof(err_str)); | 4513 | sizeof(err_str)); |
4443 | } | 4514 | } |
4444 | 4515 | ||
@@ -4449,6 +4520,7 @@ static sctp_disposition_t sctp_sf_violation_ctsn( | |||
4449 | * on the path and we may not want to continue this communication. | 4520 | * on the path and we may not want to continue this communication. |
4450 | */ | 4521 | */ |
4451 | static sctp_disposition_t sctp_sf_violation_chunk( | 4522 | static sctp_disposition_t sctp_sf_violation_chunk( |
4523 | struct net *net, | ||
4452 | const struct sctp_endpoint *ep, | 4524 | const struct sctp_endpoint *ep, |
4453 | const struct sctp_association *asoc, | 4525 | const struct sctp_association *asoc, |
4454 | const sctp_subtype_t type, | 4526 | const sctp_subtype_t type, |
@@ -4458,9 +4530,9 @@ static sctp_disposition_t sctp_sf_violation_chunk( | |||
4458 | static const char err_str[]="The following chunk violates protocol:"; | 4530 | static const char err_str[]="The following chunk violates protocol:"; |
4459 | 4531 | ||
4460 | if (!asoc) | 4532 | if (!asoc) |
4461 | return sctp_sf_violation(ep, asoc, type, arg, commands); | 4533 | return sctp_sf_violation(net, ep, asoc, type, arg, commands); |
4462 | 4534 | ||
4463 | return sctp_sf_abort_violation(ep, asoc, arg, commands, err_str, | 4535 | return sctp_sf_abort_violation(net, ep, asoc, arg, commands, err_str, |
4464 | sizeof(err_str)); | 4536 | sizeof(err_str)); |
4465 | } | 4537 | } |
4466 | /*************************************************************************** | 4538 | /*************************************************************************** |
@@ -4523,7 +4595,8 @@ static sctp_disposition_t sctp_sf_violation_chunk( | |||
4523 | * | 4595 | * |
4524 | * The return value is a disposition. | 4596 | * The return value is a disposition. |
4525 | */ | 4597 | */ |
4526 | sctp_disposition_t sctp_sf_do_prm_asoc(const struct sctp_endpoint *ep, | 4598 | sctp_disposition_t sctp_sf_do_prm_asoc(struct net *net, |
4599 | const struct sctp_endpoint *ep, | ||
4527 | const struct sctp_association *asoc, | 4600 | const struct sctp_association *asoc, |
4528 | const sctp_subtype_t type, | 4601 | const sctp_subtype_t type, |
4529 | void *arg, | 4602 | void *arg, |
@@ -4634,7 +4707,8 @@ nomem: | |||
4634 | * | 4707 | * |
4635 | * The return value is the disposition. | 4708 | * The return value is the disposition. |
4636 | */ | 4709 | */ |
4637 | sctp_disposition_t sctp_sf_do_prm_send(const struct sctp_endpoint *ep, | 4710 | sctp_disposition_t sctp_sf_do_prm_send(struct net *net, |
4711 | const struct sctp_endpoint *ep, | ||
4638 | const struct sctp_association *asoc, | 4712 | const struct sctp_association *asoc, |
4639 | const sctp_subtype_t type, | 4713 | const sctp_subtype_t type, |
4640 | void *arg, | 4714 | void *arg, |
@@ -4673,6 +4747,7 @@ sctp_disposition_t sctp_sf_do_prm_send(const struct sctp_endpoint *ep, | |||
4673 | * The return value is the disposition. | 4747 | * The return value is the disposition. |
4674 | */ | 4748 | */ |
4675 | sctp_disposition_t sctp_sf_do_9_2_prm_shutdown( | 4749 | sctp_disposition_t sctp_sf_do_9_2_prm_shutdown( |
4750 | struct net *net, | ||
4676 | const struct sctp_endpoint *ep, | 4751 | const struct sctp_endpoint *ep, |
4677 | const struct sctp_association *asoc, | 4752 | const struct sctp_association *asoc, |
4678 | const sctp_subtype_t type, | 4753 | const sctp_subtype_t type, |
@@ -4694,7 +4769,7 @@ sctp_disposition_t sctp_sf_do_9_2_prm_shutdown( | |||
4694 | 4769 | ||
4695 | disposition = SCTP_DISPOSITION_CONSUME; | 4770 | disposition = SCTP_DISPOSITION_CONSUME; |
4696 | if (sctp_outq_is_empty(&asoc->outqueue)) { | 4771 | if (sctp_outq_is_empty(&asoc->outqueue)) { |
4697 | disposition = sctp_sf_do_9_2_start_shutdown(ep, asoc, type, | 4772 | disposition = sctp_sf_do_9_2_start_shutdown(net, ep, asoc, type, |
4698 | arg, commands); | 4773 | arg, commands); |
4699 | } | 4774 | } |
4700 | return disposition; | 4775 | return disposition; |
@@ -4728,6 +4803,7 @@ sctp_disposition_t sctp_sf_do_9_2_prm_shutdown( | |||
4728 | * The return value is the disposition. | 4803 | * The return value is the disposition. |
4729 | */ | 4804 | */ |
4730 | sctp_disposition_t sctp_sf_do_9_1_prm_abort( | 4805 | sctp_disposition_t sctp_sf_do_9_1_prm_abort( |
4806 | struct net *net, | ||
4731 | const struct sctp_endpoint *ep, | 4807 | const struct sctp_endpoint *ep, |
4732 | const struct sctp_association *asoc, | 4808 | const struct sctp_association *asoc, |
4733 | const sctp_subtype_t type, | 4809 | const sctp_subtype_t type, |
@@ -4759,14 +4835,15 @@ sctp_disposition_t sctp_sf_do_9_1_prm_abort( | |||
4759 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 4835 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
4760 | SCTP_PERR(SCTP_ERROR_USER_ABORT)); | 4836 | SCTP_PERR(SCTP_ERROR_USER_ABORT)); |
4761 | 4837 | ||
4762 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 4838 | SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); |
4763 | SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); | 4839 | SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); |
4764 | 4840 | ||
4765 | return retval; | 4841 | return retval; |
4766 | } | 4842 | } |
4767 | 4843 | ||
4768 | /* We tried an illegal operation on an association which is closed. */ | 4844 | /* We tried an illegal operation on an association which is closed. */ |
4769 | sctp_disposition_t sctp_sf_error_closed(const struct sctp_endpoint *ep, | 4845 | sctp_disposition_t sctp_sf_error_closed(struct net *net, |
4846 | const struct sctp_endpoint *ep, | ||
4770 | const struct sctp_association *asoc, | 4847 | const struct sctp_association *asoc, |
4771 | const sctp_subtype_t type, | 4848 | const sctp_subtype_t type, |
4772 | void *arg, | 4849 | void *arg, |
@@ -4779,7 +4856,8 @@ sctp_disposition_t sctp_sf_error_closed(const struct sctp_endpoint *ep, | |||
4779 | /* We tried an illegal operation on an association which is shutting | 4856 | /* We tried an illegal operation on an association which is shutting |
4780 | * down. | 4857 | * down. |
4781 | */ | 4858 | */ |
4782 | sctp_disposition_t sctp_sf_error_shutdown(const struct sctp_endpoint *ep, | 4859 | sctp_disposition_t sctp_sf_error_shutdown(struct net *net, |
4860 | const struct sctp_endpoint *ep, | ||
4783 | const struct sctp_association *asoc, | 4861 | const struct sctp_association *asoc, |
4784 | const sctp_subtype_t type, | 4862 | const sctp_subtype_t type, |
4785 | void *arg, | 4863 | void *arg, |
@@ -4805,6 +4883,7 @@ sctp_disposition_t sctp_sf_error_shutdown(const struct sctp_endpoint *ep, | |||
4805 | * (timers) | 4883 | * (timers) |
4806 | */ | 4884 | */ |
4807 | sctp_disposition_t sctp_sf_cookie_wait_prm_shutdown( | 4885 | sctp_disposition_t sctp_sf_cookie_wait_prm_shutdown( |
4886 | struct net *net, | ||
4808 | const struct sctp_endpoint *ep, | 4887 | const struct sctp_endpoint *ep, |
4809 | const struct sctp_association *asoc, | 4888 | const struct sctp_association *asoc, |
4810 | const sctp_subtype_t type, | 4889 | const sctp_subtype_t type, |
@@ -4817,7 +4896,7 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_shutdown( | |||
4817 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | 4896 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, |
4818 | SCTP_STATE(SCTP_STATE_CLOSED)); | 4897 | SCTP_STATE(SCTP_STATE_CLOSED)); |
4819 | 4898 | ||
4820 | SCTP_INC_STATS(SCTP_MIB_SHUTDOWNS); | 4899 | SCTP_INC_STATS(net, SCTP_MIB_SHUTDOWNS); |
4821 | 4900 | ||
4822 | sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); | 4901 | sctp_add_cmd_sf(commands, SCTP_CMD_DELETE_TCB, SCTP_NULL()); |
4823 | 4902 | ||
@@ -4839,6 +4918,7 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_shutdown( | |||
4839 | * (timers) | 4918 | * (timers) |
4840 | */ | 4919 | */ |
4841 | sctp_disposition_t sctp_sf_cookie_echoed_prm_shutdown( | 4920 | sctp_disposition_t sctp_sf_cookie_echoed_prm_shutdown( |
4921 | struct net *net, | ||
4842 | const struct sctp_endpoint *ep, | 4922 | const struct sctp_endpoint *ep, |
4843 | const struct sctp_association *asoc, | 4923 | const struct sctp_association *asoc, |
4844 | const sctp_subtype_t type, | 4924 | const sctp_subtype_t type, |
@@ -4847,7 +4927,7 @@ sctp_disposition_t sctp_sf_cookie_echoed_prm_shutdown( | |||
4847 | /* There is a single T1 timer, so we should be able to use | 4927 | /* There is a single T1 timer, so we should be able to use |
4848 | * common function with the COOKIE-WAIT state. | 4928 | * common function with the COOKIE-WAIT state. |
4849 | */ | 4929 | */ |
4850 | return sctp_sf_cookie_wait_prm_shutdown(ep, asoc, type, arg, commands); | 4930 | return sctp_sf_cookie_wait_prm_shutdown(net, ep, asoc, type, arg, commands); |
4851 | } | 4931 | } |
4852 | 4932 | ||
4853 | /* | 4933 | /* |
@@ -4865,6 +4945,7 @@ sctp_disposition_t sctp_sf_cookie_echoed_prm_shutdown( | |||
4865 | * (timers) | 4945 | * (timers) |
4866 | */ | 4946 | */ |
4867 | sctp_disposition_t sctp_sf_cookie_wait_prm_abort( | 4947 | sctp_disposition_t sctp_sf_cookie_wait_prm_abort( |
4948 | struct net *net, | ||
4868 | const struct sctp_endpoint *ep, | 4949 | const struct sctp_endpoint *ep, |
4869 | const struct sctp_association *asoc, | 4950 | const struct sctp_association *asoc, |
4870 | const sctp_subtype_t type, | 4951 | const sctp_subtype_t type, |
@@ -4884,7 +4965,7 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort( | |||
4884 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, | 4965 | sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE, |
4885 | SCTP_STATE(SCTP_STATE_CLOSED)); | 4966 | SCTP_STATE(SCTP_STATE_CLOSED)); |
4886 | 4967 | ||
4887 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 4968 | SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); |
4888 | 4969 | ||
4889 | /* Even if we can't send the ABORT due to low memory delete the | 4970 | /* Even if we can't send the ABORT due to low memory delete the |
4890 | * TCB. This is a departure from our typical NOMEM handling. | 4971 | * TCB. This is a departure from our typical NOMEM handling. |
@@ -4914,6 +4995,7 @@ sctp_disposition_t sctp_sf_cookie_wait_prm_abort( | |||
4914 | * (timers) | 4995 | * (timers) |
4915 | */ | 4996 | */ |
4916 | sctp_disposition_t sctp_sf_cookie_echoed_prm_abort( | 4997 | sctp_disposition_t sctp_sf_cookie_echoed_prm_abort( |
4998 | struct net *net, | ||
4917 | const struct sctp_endpoint *ep, | 4999 | const struct sctp_endpoint *ep, |
4918 | const struct sctp_association *asoc, | 5000 | const struct sctp_association *asoc, |
4919 | const sctp_subtype_t type, | 5001 | const sctp_subtype_t type, |
@@ -4923,7 +5005,7 @@ sctp_disposition_t sctp_sf_cookie_echoed_prm_abort( | |||
4923 | /* There is a single T1 timer, so we should be able to use | 5005 | /* There is a single T1 timer, so we should be able to use |
4924 | * common function with the COOKIE-WAIT state. | 5006 | * common function with the COOKIE-WAIT state. |
4925 | */ | 5007 | */ |
4926 | return sctp_sf_cookie_wait_prm_abort(ep, asoc, type, arg, commands); | 5008 | return sctp_sf_cookie_wait_prm_abort(net, ep, asoc, type, arg, commands); |
4927 | } | 5009 | } |
4928 | 5010 | ||
4929 | /* | 5011 | /* |
@@ -4939,6 +5021,7 @@ sctp_disposition_t sctp_sf_cookie_echoed_prm_abort( | |||
4939 | * (timers) | 5021 | * (timers) |
4940 | */ | 5022 | */ |
4941 | sctp_disposition_t sctp_sf_shutdown_pending_prm_abort( | 5023 | sctp_disposition_t sctp_sf_shutdown_pending_prm_abort( |
5024 | struct net *net, | ||
4942 | const struct sctp_endpoint *ep, | 5025 | const struct sctp_endpoint *ep, |
4943 | const struct sctp_association *asoc, | 5026 | const struct sctp_association *asoc, |
4944 | const sctp_subtype_t type, | 5027 | const sctp_subtype_t type, |
@@ -4949,7 +5032,7 @@ sctp_disposition_t sctp_sf_shutdown_pending_prm_abort( | |||
4949 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 5032 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
4950 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); | 5033 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); |
4951 | 5034 | ||
4952 | return sctp_sf_do_9_1_prm_abort(ep, asoc, type, arg, commands); | 5035 | return sctp_sf_do_9_1_prm_abort(net, ep, asoc, type, arg, commands); |
4953 | } | 5036 | } |
4954 | 5037 | ||
4955 | /* | 5038 | /* |
@@ -4965,6 +5048,7 @@ sctp_disposition_t sctp_sf_shutdown_pending_prm_abort( | |||
4965 | * (timers) | 5048 | * (timers) |
4966 | */ | 5049 | */ |
4967 | sctp_disposition_t sctp_sf_shutdown_sent_prm_abort( | 5050 | sctp_disposition_t sctp_sf_shutdown_sent_prm_abort( |
5051 | struct net *net, | ||
4968 | const struct sctp_endpoint *ep, | 5052 | const struct sctp_endpoint *ep, |
4969 | const struct sctp_association *asoc, | 5053 | const struct sctp_association *asoc, |
4970 | const sctp_subtype_t type, | 5054 | const sctp_subtype_t type, |
@@ -4979,7 +5063,7 @@ sctp_disposition_t sctp_sf_shutdown_sent_prm_abort( | |||
4979 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, | 5063 | sctp_add_cmd_sf(commands, SCTP_CMD_TIMER_STOP, |
4980 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); | 5064 | SCTP_TO(SCTP_EVENT_TIMEOUT_T5_SHUTDOWN_GUARD)); |
4981 | 5065 | ||
4982 | return sctp_sf_do_9_1_prm_abort(ep, asoc, type, arg, commands); | 5066 | return sctp_sf_do_9_1_prm_abort(net, ep, asoc, type, arg, commands); |
4983 | } | 5067 | } |
4984 | 5068 | ||
4985 | /* | 5069 | /* |
@@ -4995,6 +5079,7 @@ sctp_disposition_t sctp_sf_shutdown_sent_prm_abort( | |||
4995 | * (timers) | 5079 | * (timers) |
4996 | */ | 5080 | */ |
4997 | sctp_disposition_t sctp_sf_shutdown_ack_sent_prm_abort( | 5081 | sctp_disposition_t sctp_sf_shutdown_ack_sent_prm_abort( |
5082 | struct net *net, | ||
4998 | const struct sctp_endpoint *ep, | 5083 | const struct sctp_endpoint *ep, |
4999 | const struct sctp_association *asoc, | 5084 | const struct sctp_association *asoc, |
5000 | const sctp_subtype_t type, | 5085 | const sctp_subtype_t type, |
@@ -5004,7 +5089,7 @@ sctp_disposition_t sctp_sf_shutdown_ack_sent_prm_abort( | |||
5004 | /* The same T2 timer, so we should be able to use | 5089 | /* The same T2 timer, so we should be able to use |
5005 | * common function with the SHUTDOWN-SENT state. | 5090 | * common function with the SHUTDOWN-SENT state. |
5006 | */ | 5091 | */ |
5007 | return sctp_sf_shutdown_sent_prm_abort(ep, asoc, type, arg, commands); | 5092 | return sctp_sf_shutdown_sent_prm_abort(net, ep, asoc, type, arg, commands); |
5008 | } | 5093 | } |
5009 | 5094 | ||
5010 | /* | 5095 | /* |
@@ -5030,6 +5115,7 @@ sctp_disposition_t sctp_sf_shutdown_ack_sent_prm_abort( | |||
5030 | * association on which a heartbeat should be issued. | 5115 | * association on which a heartbeat should be issued. |
5031 | */ | 5116 | */ |
5032 | sctp_disposition_t sctp_sf_do_prm_requestheartbeat( | 5117 | sctp_disposition_t sctp_sf_do_prm_requestheartbeat( |
5118 | struct net *net, | ||
5033 | const struct sctp_endpoint *ep, | 5119 | const struct sctp_endpoint *ep, |
5034 | const struct sctp_association *asoc, | 5120 | const struct sctp_association *asoc, |
5035 | const sctp_subtype_t type, | 5121 | const sctp_subtype_t type, |
@@ -5061,7 +5147,8 @@ sctp_disposition_t sctp_sf_do_prm_requestheartbeat( | |||
5061 | * When an endpoint has an ASCONF signaled change to be sent to the | 5147 | * When an endpoint has an ASCONF signaled change to be sent to the |
5062 | * remote endpoint it should do A1 to A9 | 5148 | * remote endpoint it should do A1 to A9 |
5063 | */ | 5149 | */ |
5064 | sctp_disposition_t sctp_sf_do_prm_asconf(const struct sctp_endpoint *ep, | 5150 | sctp_disposition_t sctp_sf_do_prm_asconf(struct net *net, |
5151 | const struct sctp_endpoint *ep, | ||
5065 | const struct sctp_association *asoc, | 5152 | const struct sctp_association *asoc, |
5066 | const sctp_subtype_t type, | 5153 | const sctp_subtype_t type, |
5067 | void *arg, | 5154 | void *arg, |
@@ -5082,6 +5169,7 @@ sctp_disposition_t sctp_sf_do_prm_asconf(const struct sctp_endpoint *ep, | |||
5082 | * The return value is the disposition of the primitive. | 5169 | * The return value is the disposition of the primitive. |
5083 | */ | 5170 | */ |
5084 | sctp_disposition_t sctp_sf_ignore_primitive( | 5171 | sctp_disposition_t sctp_sf_ignore_primitive( |
5172 | struct net *net, | ||
5085 | const struct sctp_endpoint *ep, | 5173 | const struct sctp_endpoint *ep, |
5086 | const struct sctp_association *asoc, | 5174 | const struct sctp_association *asoc, |
5087 | const sctp_subtype_t type, | 5175 | const sctp_subtype_t type, |
@@ -5103,6 +5191,7 @@ sctp_disposition_t sctp_sf_ignore_primitive( | |||
5103 | * retransmit, the stack will immediately send up this notification. | 5191 | * retransmit, the stack will immediately send up this notification. |
5104 | */ | 5192 | */ |
5105 | sctp_disposition_t sctp_sf_do_no_pending_tsn( | 5193 | sctp_disposition_t sctp_sf_do_no_pending_tsn( |
5194 | struct net *net, | ||
5106 | const struct sctp_endpoint *ep, | 5195 | const struct sctp_endpoint *ep, |
5107 | const struct sctp_association *asoc, | 5196 | const struct sctp_association *asoc, |
5108 | const sctp_subtype_t type, | 5197 | const sctp_subtype_t type, |
@@ -5134,6 +5223,7 @@ sctp_disposition_t sctp_sf_do_no_pending_tsn( | |||
5134 | * The return value is the disposition. | 5223 | * The return value is the disposition. |
5135 | */ | 5224 | */ |
5136 | sctp_disposition_t sctp_sf_do_9_2_start_shutdown( | 5225 | sctp_disposition_t sctp_sf_do_9_2_start_shutdown( |
5226 | struct net *net, | ||
5137 | const struct sctp_endpoint *ep, | 5227 | const struct sctp_endpoint *ep, |
5138 | const struct sctp_association *asoc, | 5228 | const struct sctp_association *asoc, |
5139 | const sctp_subtype_t type, | 5229 | const sctp_subtype_t type, |
@@ -5203,6 +5293,7 @@ nomem: | |||
5203 | * The return value is the disposition. | 5293 | * The return value is the disposition. |
5204 | */ | 5294 | */ |
5205 | sctp_disposition_t sctp_sf_do_9_2_shutdown_ack( | 5295 | sctp_disposition_t sctp_sf_do_9_2_shutdown_ack( |
5296 | struct net *net, | ||
5206 | const struct sctp_endpoint *ep, | 5297 | const struct sctp_endpoint *ep, |
5207 | const struct sctp_association *asoc, | 5298 | const struct sctp_association *asoc, |
5208 | const sctp_subtype_t type, | 5299 | const sctp_subtype_t type, |
@@ -5221,11 +5312,11 @@ sctp_disposition_t sctp_sf_do_9_2_shutdown_ack( | |||
5221 | */ | 5312 | */ |
5222 | if (chunk) { | 5313 | if (chunk) { |
5223 | if (!sctp_vtag_verify(chunk, asoc)) | 5314 | if (!sctp_vtag_verify(chunk, asoc)) |
5224 | return sctp_sf_pdiscard(ep, asoc, type, arg, commands); | 5315 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
5225 | 5316 | ||
5226 | /* Make sure that the SHUTDOWN chunk has a valid length. */ | 5317 | /* Make sure that the SHUTDOWN chunk has a valid length. */ |
5227 | if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_shutdown_chunk_t))) | 5318 | if (!sctp_chunk_length_valid(chunk, sizeof(struct sctp_shutdown_chunk_t))) |
5228 | return sctp_sf_violation_chunklen(ep, asoc, type, arg, | 5319 | return sctp_sf_violation_chunklen(net, ep, asoc, type, arg, |
5229 | commands); | 5320 | commands); |
5230 | } | 5321 | } |
5231 | 5322 | ||
@@ -5273,7 +5364,8 @@ nomem: | |||
5273 | * | 5364 | * |
5274 | * The return value is the disposition of the event. | 5365 | * The return value is the disposition of the event. |
5275 | */ | 5366 | */ |
5276 | sctp_disposition_t sctp_sf_ignore_other(const struct sctp_endpoint *ep, | 5367 | sctp_disposition_t sctp_sf_ignore_other(struct net *net, |
5368 | const struct sctp_endpoint *ep, | ||
5277 | const struct sctp_association *asoc, | 5369 | const struct sctp_association *asoc, |
5278 | const sctp_subtype_t type, | 5370 | const sctp_subtype_t type, |
5279 | void *arg, | 5371 | void *arg, |
@@ -5298,7 +5390,8 @@ sctp_disposition_t sctp_sf_ignore_other(const struct sctp_endpoint *ep, | |||
5298 | * | 5390 | * |
5299 | * The return value is the disposition of the chunk. | 5391 | * The return value is the disposition of the chunk. |
5300 | */ | 5392 | */ |
5301 | sctp_disposition_t sctp_sf_do_6_3_3_rtx(const struct sctp_endpoint *ep, | 5393 | sctp_disposition_t sctp_sf_do_6_3_3_rtx(struct net *net, |
5394 | const struct sctp_endpoint *ep, | ||
5302 | const struct sctp_association *asoc, | 5395 | const struct sctp_association *asoc, |
5303 | const sctp_subtype_t type, | 5396 | const sctp_subtype_t type, |
5304 | void *arg, | 5397 | void *arg, |
@@ -5306,7 +5399,7 @@ sctp_disposition_t sctp_sf_do_6_3_3_rtx(const struct sctp_endpoint *ep, | |||
5306 | { | 5399 | { |
5307 | struct sctp_transport *transport = arg; | 5400 | struct sctp_transport *transport = arg; |
5308 | 5401 | ||
5309 | SCTP_INC_STATS(SCTP_MIB_T3_RTX_EXPIREDS); | 5402 | SCTP_INC_STATS(net, SCTP_MIB_T3_RTX_EXPIREDS); |
5310 | 5403 | ||
5311 | if (asoc->overall_error_count >= asoc->max_retrans) { | 5404 | if (asoc->overall_error_count >= asoc->max_retrans) { |
5312 | if (asoc->state == SCTP_STATE_SHUTDOWN_PENDING) { | 5405 | if (asoc->state == SCTP_STATE_SHUTDOWN_PENDING) { |
@@ -5327,8 +5420,8 @@ sctp_disposition_t sctp_sf_do_6_3_3_rtx(const struct sctp_endpoint *ep, | |||
5327 | /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ | 5420 | /* CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ |
5328 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 5421 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
5329 | SCTP_PERR(SCTP_ERROR_NO_ERROR)); | 5422 | SCTP_PERR(SCTP_ERROR_NO_ERROR)); |
5330 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 5423 | SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); |
5331 | SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); | 5424 | SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); |
5332 | return SCTP_DISPOSITION_DELETE_TCB; | 5425 | return SCTP_DISPOSITION_DELETE_TCB; |
5333 | } | 5426 | } |
5334 | } | 5427 | } |
@@ -5384,13 +5477,14 @@ sctp_disposition_t sctp_sf_do_6_3_3_rtx(const struct sctp_endpoint *ep, | |||
5384 | * allow. However, an SCTP transmitter MUST NOT be more aggressive than | 5477 | * allow. However, an SCTP transmitter MUST NOT be more aggressive than |
5385 | * the following algorithms allow. | 5478 | * the following algorithms allow. |
5386 | */ | 5479 | */ |
5387 | sctp_disposition_t sctp_sf_do_6_2_sack(const struct sctp_endpoint *ep, | 5480 | sctp_disposition_t sctp_sf_do_6_2_sack(struct net *net, |
5481 | const struct sctp_endpoint *ep, | ||
5388 | const struct sctp_association *asoc, | 5482 | const struct sctp_association *asoc, |
5389 | const sctp_subtype_t type, | 5483 | const sctp_subtype_t type, |
5390 | void *arg, | 5484 | void *arg, |
5391 | sctp_cmd_seq_t *commands) | 5485 | sctp_cmd_seq_t *commands) |
5392 | { | 5486 | { |
5393 | SCTP_INC_STATS(SCTP_MIB_DELAY_SACK_EXPIREDS); | 5487 | SCTP_INC_STATS(net, SCTP_MIB_DELAY_SACK_EXPIREDS); |
5394 | sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_FORCE()); | 5488 | sctp_add_cmd_sf(commands, SCTP_CMD_GEN_SACK, SCTP_FORCE()); |
5395 | return SCTP_DISPOSITION_CONSUME; | 5489 | return SCTP_DISPOSITION_CONSUME; |
5396 | } | 5490 | } |
@@ -5414,7 +5508,8 @@ sctp_disposition_t sctp_sf_do_6_2_sack(const struct sctp_endpoint *ep, | |||
5414 | * (timers, events) | 5508 | * (timers, events) |
5415 | * | 5509 | * |
5416 | */ | 5510 | */ |
5417 | sctp_disposition_t sctp_sf_t1_init_timer_expire(const struct sctp_endpoint *ep, | 5511 | sctp_disposition_t sctp_sf_t1_init_timer_expire(struct net *net, |
5512 | const struct sctp_endpoint *ep, | ||
5418 | const struct sctp_association *asoc, | 5513 | const struct sctp_association *asoc, |
5419 | const sctp_subtype_t type, | 5514 | const sctp_subtype_t type, |
5420 | void *arg, | 5515 | void *arg, |
@@ -5425,7 +5520,7 @@ sctp_disposition_t sctp_sf_t1_init_timer_expire(const struct sctp_endpoint *ep, | |||
5425 | int attempts = asoc->init_err_counter + 1; | 5520 | int attempts = asoc->init_err_counter + 1; |
5426 | 5521 | ||
5427 | SCTP_DEBUG_PRINTK("Timer T1 expired (INIT).\n"); | 5522 | SCTP_DEBUG_PRINTK("Timer T1 expired (INIT).\n"); |
5428 | SCTP_INC_STATS(SCTP_MIB_T1_INIT_EXPIREDS); | 5523 | SCTP_INC_STATS(net, SCTP_MIB_T1_INIT_EXPIREDS); |
5429 | 5524 | ||
5430 | if (attempts <= asoc->max_init_attempts) { | 5525 | if (attempts <= asoc->max_init_attempts) { |
5431 | bp = (struct sctp_bind_addr *) &asoc->base.bind_addr; | 5526 | bp = (struct sctp_bind_addr *) &asoc->base.bind_addr; |
@@ -5475,7 +5570,8 @@ sctp_disposition_t sctp_sf_t1_init_timer_expire(const struct sctp_endpoint *ep, | |||
5475 | * (timers, events) | 5570 | * (timers, events) |
5476 | * | 5571 | * |
5477 | */ | 5572 | */ |
5478 | sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep, | 5573 | sctp_disposition_t sctp_sf_t1_cookie_timer_expire(struct net *net, |
5574 | const struct sctp_endpoint *ep, | ||
5479 | const struct sctp_association *asoc, | 5575 | const struct sctp_association *asoc, |
5480 | const sctp_subtype_t type, | 5576 | const sctp_subtype_t type, |
5481 | void *arg, | 5577 | void *arg, |
@@ -5485,7 +5581,7 @@ sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep | |||
5485 | int attempts = asoc->init_err_counter + 1; | 5581 | int attempts = asoc->init_err_counter + 1; |
5486 | 5582 | ||
5487 | SCTP_DEBUG_PRINTK("Timer T1 expired (COOKIE-ECHO).\n"); | 5583 | SCTP_DEBUG_PRINTK("Timer T1 expired (COOKIE-ECHO).\n"); |
5488 | SCTP_INC_STATS(SCTP_MIB_T1_COOKIE_EXPIREDS); | 5584 | SCTP_INC_STATS(net, SCTP_MIB_T1_COOKIE_EXPIREDS); |
5489 | 5585 | ||
5490 | if (attempts <= asoc->max_init_attempts) { | 5586 | if (attempts <= asoc->max_init_attempts) { |
5491 | repl = sctp_make_cookie_echo(asoc, NULL); | 5587 | repl = sctp_make_cookie_echo(asoc, NULL); |
@@ -5523,7 +5619,8 @@ sctp_disposition_t sctp_sf_t1_cookie_timer_expire(const struct sctp_endpoint *ep | |||
5523 | * the T2-Shutdown timer, giving its peer ample opportunity to transmit | 5619 | * the T2-Shutdown timer, giving its peer ample opportunity to transmit |
5524 | * all of its queued DATA chunks that have not yet been sent. | 5620 | * all of its queued DATA chunks that have not yet been sent. |
5525 | */ | 5621 | */ |
5526 | sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep, | 5622 | sctp_disposition_t sctp_sf_t2_timer_expire(struct net *net, |
5623 | const struct sctp_endpoint *ep, | ||
5527 | const struct sctp_association *asoc, | 5624 | const struct sctp_association *asoc, |
5528 | const sctp_subtype_t type, | 5625 | const sctp_subtype_t type, |
5529 | void *arg, | 5626 | void *arg, |
@@ -5532,7 +5629,7 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep, | |||
5532 | struct sctp_chunk *reply = NULL; | 5629 | struct sctp_chunk *reply = NULL; |
5533 | 5630 | ||
5534 | SCTP_DEBUG_PRINTK("Timer T2 expired.\n"); | 5631 | SCTP_DEBUG_PRINTK("Timer T2 expired.\n"); |
5535 | SCTP_INC_STATS(SCTP_MIB_T2_SHUTDOWN_EXPIREDS); | 5632 | SCTP_INC_STATS(net, SCTP_MIB_T2_SHUTDOWN_EXPIREDS); |
5536 | 5633 | ||
5537 | ((struct sctp_association *)asoc)->shutdown_retries++; | 5634 | ((struct sctp_association *)asoc)->shutdown_retries++; |
5538 | 5635 | ||
@@ -5542,8 +5639,8 @@ sctp_disposition_t sctp_sf_t2_timer_expire(const struct sctp_endpoint *ep, | |||
5542 | /* Note: CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ | 5639 | /* Note: CMD_ASSOC_FAILED calls CMD_DELETE_TCB. */ |
5543 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 5640 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
5544 | SCTP_PERR(SCTP_ERROR_NO_ERROR)); | 5641 | SCTP_PERR(SCTP_ERROR_NO_ERROR)); |
5545 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 5642 | SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); |
5546 | SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); | 5643 | SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); |
5547 | return SCTP_DISPOSITION_DELETE_TCB; | 5644 | return SCTP_DISPOSITION_DELETE_TCB; |
5548 | } | 5645 | } |
5549 | 5646 | ||
@@ -5592,6 +5689,7 @@ nomem: | |||
5592 | * If the T4 RTO timer expires the endpoint should do B1 to B5 | 5689 | * If the T4 RTO timer expires the endpoint should do B1 to B5 |
5593 | */ | 5690 | */ |
5594 | sctp_disposition_t sctp_sf_t4_timer_expire( | 5691 | sctp_disposition_t sctp_sf_t4_timer_expire( |
5692 | struct net *net, | ||
5595 | const struct sctp_endpoint *ep, | 5693 | const struct sctp_endpoint *ep, |
5596 | const struct sctp_association *asoc, | 5694 | const struct sctp_association *asoc, |
5597 | const sctp_subtype_t type, | 5695 | const sctp_subtype_t type, |
@@ -5601,7 +5699,7 @@ sctp_disposition_t sctp_sf_t4_timer_expire( | |||
5601 | struct sctp_chunk *chunk = asoc->addip_last_asconf; | 5699 | struct sctp_chunk *chunk = asoc->addip_last_asconf; |
5602 | struct sctp_transport *transport = chunk->transport; | 5700 | struct sctp_transport *transport = chunk->transport; |
5603 | 5701 | ||
5604 | SCTP_INC_STATS(SCTP_MIB_T4_RTO_EXPIREDS); | 5702 | SCTP_INC_STATS(net, SCTP_MIB_T4_RTO_EXPIREDS); |
5605 | 5703 | ||
5606 | /* ADDIP 4.1 B1) Increment the error counters and perform path failure | 5704 | /* ADDIP 4.1 B1) Increment the error counters and perform path failure |
5607 | * detection on the appropriate destination address as defined in | 5705 | * detection on the appropriate destination address as defined in |
@@ -5626,8 +5724,8 @@ sctp_disposition_t sctp_sf_t4_timer_expire( | |||
5626 | SCTP_ERROR(ETIMEDOUT)); | 5724 | SCTP_ERROR(ETIMEDOUT)); |
5627 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 5725 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
5628 | SCTP_PERR(SCTP_ERROR_NO_ERROR)); | 5726 | SCTP_PERR(SCTP_ERROR_NO_ERROR)); |
5629 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 5727 | SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); |
5630 | SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); | 5728 | SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); |
5631 | return SCTP_DISPOSITION_ABORT; | 5729 | return SCTP_DISPOSITION_ABORT; |
5632 | } | 5730 | } |
5633 | 5731 | ||
@@ -5662,7 +5760,8 @@ sctp_disposition_t sctp_sf_t4_timer_expire( | |||
5662 | * At the expiration of this timer the sender SHOULD abort the association | 5760 | * At the expiration of this timer the sender SHOULD abort the association |
5663 | * by sending an ABORT chunk. | 5761 | * by sending an ABORT chunk. |
5664 | */ | 5762 | */ |
5665 | sctp_disposition_t sctp_sf_t5_timer_expire(const struct sctp_endpoint *ep, | 5763 | sctp_disposition_t sctp_sf_t5_timer_expire(struct net *net, |
5764 | const struct sctp_endpoint *ep, | ||
5666 | const struct sctp_association *asoc, | 5765 | const struct sctp_association *asoc, |
5667 | const sctp_subtype_t type, | 5766 | const sctp_subtype_t type, |
5668 | void *arg, | 5767 | void *arg, |
@@ -5671,7 +5770,7 @@ sctp_disposition_t sctp_sf_t5_timer_expire(const struct sctp_endpoint *ep, | |||
5671 | struct sctp_chunk *reply = NULL; | 5770 | struct sctp_chunk *reply = NULL; |
5672 | 5771 | ||
5673 | SCTP_DEBUG_PRINTK("Timer T5 expired.\n"); | 5772 | SCTP_DEBUG_PRINTK("Timer T5 expired.\n"); |
5674 | SCTP_INC_STATS(SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS); | 5773 | SCTP_INC_STATS(net, SCTP_MIB_T5_SHUTDOWN_GUARD_EXPIREDS); |
5675 | 5774 | ||
5676 | reply = sctp_make_abort(asoc, NULL, 0); | 5775 | reply = sctp_make_abort(asoc, NULL, 0); |
5677 | if (!reply) | 5776 | if (!reply) |
@@ -5683,8 +5782,8 @@ sctp_disposition_t sctp_sf_t5_timer_expire(const struct sctp_endpoint *ep, | |||
5683 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 5782 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
5684 | SCTP_PERR(SCTP_ERROR_NO_ERROR)); | 5783 | SCTP_PERR(SCTP_ERROR_NO_ERROR)); |
5685 | 5784 | ||
5686 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 5785 | SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); |
5687 | SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); | 5786 | SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); |
5688 | 5787 | ||
5689 | return SCTP_DISPOSITION_DELETE_TCB; | 5788 | return SCTP_DISPOSITION_DELETE_TCB; |
5690 | nomem: | 5789 | nomem: |
@@ -5697,6 +5796,7 @@ nomem: | |||
5697 | * the user. So this routine looks same as sctp_sf_do_9_2_prm_shutdown(). | 5796 | * the user. So this routine looks same as sctp_sf_do_9_2_prm_shutdown(). |
5698 | */ | 5797 | */ |
5699 | sctp_disposition_t sctp_sf_autoclose_timer_expire( | 5798 | sctp_disposition_t sctp_sf_autoclose_timer_expire( |
5799 | struct net *net, | ||
5700 | const struct sctp_endpoint *ep, | 5800 | const struct sctp_endpoint *ep, |
5701 | const struct sctp_association *asoc, | 5801 | const struct sctp_association *asoc, |
5702 | const sctp_subtype_t type, | 5802 | const sctp_subtype_t type, |
@@ -5705,7 +5805,7 @@ sctp_disposition_t sctp_sf_autoclose_timer_expire( | |||
5705 | { | 5805 | { |
5706 | int disposition; | 5806 | int disposition; |
5707 | 5807 | ||
5708 | SCTP_INC_STATS(SCTP_MIB_AUTOCLOSE_EXPIREDS); | 5808 | SCTP_INC_STATS(net, SCTP_MIB_AUTOCLOSE_EXPIREDS); |
5709 | 5809 | ||
5710 | /* From 9.2 Shutdown of an Association | 5810 | /* From 9.2 Shutdown of an Association |
5711 | * Upon receipt of the SHUTDOWN primitive from its upper | 5811 | * Upon receipt of the SHUTDOWN primitive from its upper |
@@ -5720,7 +5820,7 @@ sctp_disposition_t sctp_sf_autoclose_timer_expire( | |||
5720 | 5820 | ||
5721 | disposition = SCTP_DISPOSITION_CONSUME; | 5821 | disposition = SCTP_DISPOSITION_CONSUME; |
5722 | if (sctp_outq_is_empty(&asoc->outqueue)) { | 5822 | if (sctp_outq_is_empty(&asoc->outqueue)) { |
5723 | disposition = sctp_sf_do_9_2_start_shutdown(ep, asoc, type, | 5823 | disposition = sctp_sf_do_9_2_start_shutdown(net, ep, asoc, type, |
5724 | arg, commands); | 5824 | arg, commands); |
5725 | } | 5825 | } |
5726 | return disposition; | 5826 | return disposition; |
@@ -5738,7 +5838,8 @@ sctp_disposition_t sctp_sf_autoclose_timer_expire( | |||
5738 | * | 5838 | * |
5739 | * The return value is the disposition of the chunk. | 5839 | * The return value is the disposition of the chunk. |
5740 | */ | 5840 | */ |
5741 | sctp_disposition_t sctp_sf_not_impl(const struct sctp_endpoint *ep, | 5841 | sctp_disposition_t sctp_sf_not_impl(struct net *net, |
5842 | const struct sctp_endpoint *ep, | ||
5742 | const struct sctp_association *asoc, | 5843 | const struct sctp_association *asoc, |
5743 | const sctp_subtype_t type, | 5844 | const sctp_subtype_t type, |
5744 | void *arg, | 5845 | void *arg, |
@@ -5755,7 +5856,8 @@ sctp_disposition_t sctp_sf_not_impl(const struct sctp_endpoint *ep, | |||
5755 | * | 5856 | * |
5756 | * The return value is the disposition of the chunk. | 5857 | * The return value is the disposition of the chunk. |
5757 | */ | 5858 | */ |
5758 | sctp_disposition_t sctp_sf_bug(const struct sctp_endpoint *ep, | 5859 | sctp_disposition_t sctp_sf_bug(struct net *net, |
5860 | const struct sctp_endpoint *ep, | ||
5759 | const struct sctp_association *asoc, | 5861 | const struct sctp_association *asoc, |
5760 | const sctp_subtype_t type, | 5862 | const sctp_subtype_t type, |
5761 | void *arg, | 5863 | void *arg, |
@@ -5775,7 +5877,8 @@ sctp_disposition_t sctp_sf_bug(const struct sctp_endpoint *ep, | |||
5775 | * | 5877 | * |
5776 | * The return value is the disposition of the chunk. | 5878 | * The return value is the disposition of the chunk. |
5777 | */ | 5879 | */ |
5778 | sctp_disposition_t sctp_sf_timer_ignore(const struct sctp_endpoint *ep, | 5880 | sctp_disposition_t sctp_sf_timer_ignore(struct net *net, |
5881 | const struct sctp_endpoint *ep, | ||
5779 | const struct sctp_association *asoc, | 5882 | const struct sctp_association *asoc, |
5780 | const sctp_subtype_t type, | 5883 | const sctp_subtype_t type, |
5781 | void *arg, | 5884 | void *arg, |
@@ -5817,7 +5920,8 @@ static struct sctp_sackhdr *sctp_sm_pull_sack(struct sctp_chunk *chunk) | |||
5817 | /* Create an ABORT packet to be sent as a response, with the specified | 5920 | /* Create an ABORT packet to be sent as a response, with the specified |
5818 | * error causes. | 5921 | * error causes. |
5819 | */ | 5922 | */ |
5820 | static struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *ep, | 5923 | static struct sctp_packet *sctp_abort_pkt_new(struct net *net, |
5924 | const struct sctp_endpoint *ep, | ||
5821 | const struct sctp_association *asoc, | 5925 | const struct sctp_association *asoc, |
5822 | struct sctp_chunk *chunk, | 5926 | struct sctp_chunk *chunk, |
5823 | const void *payload, | 5927 | const void *payload, |
@@ -5826,7 +5930,7 @@ static struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *ep, | |||
5826 | struct sctp_packet *packet; | 5930 | struct sctp_packet *packet; |
5827 | struct sctp_chunk *abort; | 5931 | struct sctp_chunk *abort; |
5828 | 5932 | ||
5829 | packet = sctp_ootb_pkt_new(asoc, chunk); | 5933 | packet = sctp_ootb_pkt_new(net, asoc, chunk); |
5830 | 5934 | ||
5831 | if (packet) { | 5935 | if (packet) { |
5832 | /* Make an ABORT. | 5936 | /* Make an ABORT. |
@@ -5858,7 +5962,8 @@ static struct sctp_packet *sctp_abort_pkt_new(const struct sctp_endpoint *ep, | |||
5858 | } | 5962 | } |
5859 | 5963 | ||
5860 | /* Allocate a packet for responding in the OOTB conditions. */ | 5964 | /* Allocate a packet for responding in the OOTB conditions. */ |
5861 | static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc, | 5965 | static struct sctp_packet *sctp_ootb_pkt_new(struct net *net, |
5966 | const struct sctp_association *asoc, | ||
5862 | const struct sctp_chunk *chunk) | 5967 | const struct sctp_chunk *chunk) |
5863 | { | 5968 | { |
5864 | struct sctp_packet *packet; | 5969 | struct sctp_packet *packet; |
@@ -5911,7 +6016,7 @@ static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc | |||
5911 | } | 6016 | } |
5912 | 6017 | ||
5913 | /* Make a transport for the bucket, Eliza... */ | 6018 | /* Make a transport for the bucket, Eliza... */ |
5914 | transport = sctp_transport_new(sctp_source(chunk), GFP_ATOMIC); | 6019 | transport = sctp_transport_new(net, sctp_source(chunk), GFP_ATOMIC); |
5915 | if (!transport) | 6020 | if (!transport) |
5916 | goto nomem; | 6021 | goto nomem; |
5917 | 6022 | ||
@@ -5919,7 +6024,7 @@ static struct sctp_packet *sctp_ootb_pkt_new(const struct sctp_association *asoc | |||
5919 | * the source address. | 6024 | * the source address. |
5920 | */ | 6025 | */ |
5921 | sctp_transport_route(transport, (union sctp_addr *)&chunk->dest, | 6026 | sctp_transport_route(transport, (union sctp_addr *)&chunk->dest, |
5922 | sctp_sk(sctp_get_ctl_sock())); | 6027 | sctp_sk(net->sctp.ctl_sock)); |
5923 | 6028 | ||
5924 | packet = sctp_packet_init(&transport->packet, transport, sport, dport); | 6029 | packet = sctp_packet_init(&transport->packet, transport, sport, dport); |
5925 | packet = sctp_packet_config(packet, vtag, 0); | 6030 | packet = sctp_packet_config(packet, vtag, 0); |
@@ -5937,7 +6042,8 @@ void sctp_ootb_pkt_free(struct sctp_packet *packet) | |||
5937 | } | 6042 | } |
5938 | 6043 | ||
5939 | /* Send a stale cookie error when a invalid COOKIE ECHO chunk is found */ | 6044 | /* Send a stale cookie error when a invalid COOKIE ECHO chunk is found */ |
5940 | static void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep, | 6045 | static void sctp_send_stale_cookie_err(struct net *net, |
6046 | const struct sctp_endpoint *ep, | ||
5941 | const struct sctp_association *asoc, | 6047 | const struct sctp_association *asoc, |
5942 | const struct sctp_chunk *chunk, | 6048 | const struct sctp_chunk *chunk, |
5943 | sctp_cmd_seq_t *commands, | 6049 | sctp_cmd_seq_t *commands, |
@@ -5946,7 +6052,7 @@ static void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep, | |||
5946 | struct sctp_packet *packet; | 6052 | struct sctp_packet *packet; |
5947 | 6053 | ||
5948 | if (err_chunk) { | 6054 | if (err_chunk) { |
5949 | packet = sctp_ootb_pkt_new(asoc, chunk); | 6055 | packet = sctp_ootb_pkt_new(net, asoc, chunk); |
5950 | if (packet) { | 6056 | if (packet) { |
5951 | struct sctp_signed_cookie *cookie; | 6057 | struct sctp_signed_cookie *cookie; |
5952 | 6058 | ||
@@ -5959,7 +6065,7 @@ static void sctp_send_stale_cookie_err(const struct sctp_endpoint *ep, | |||
5959 | sctp_packet_append_chunk(packet, err_chunk); | 6065 | sctp_packet_append_chunk(packet, err_chunk); |
5960 | sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, | 6066 | sctp_add_cmd_sf(commands, SCTP_CMD_SEND_PKT, |
5961 | SCTP_PACKET(packet)); | 6067 | SCTP_PACKET(packet)); |
5962 | SCTP_INC_STATS(SCTP_MIB_OUTCTRLCHUNKS); | 6068 | SCTP_INC_STATS(net, SCTP_MIB_OUTCTRLCHUNKS); |
5963 | } else | 6069 | } else |
5964 | sctp_chunk_free (err_chunk); | 6070 | sctp_chunk_free (err_chunk); |
5965 | } | 6071 | } |
@@ -5979,6 +6085,7 @@ static int sctp_eat_data(const struct sctp_association *asoc, | |||
5979 | __u32 tsn; | 6085 | __u32 tsn; |
5980 | struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map; | 6086 | struct sctp_tsnmap *map = (struct sctp_tsnmap *)&asoc->peer.tsn_map; |
5981 | struct sock *sk = asoc->base.sk; | 6087 | struct sock *sk = asoc->base.sk; |
6088 | struct net *net = sock_net(sk); | ||
5982 | u16 ssn; | 6089 | u16 ssn; |
5983 | u16 sid; | 6090 | u16 sid; |
5984 | u8 ordered = 0; | 6091 | u8 ordered = 0; |
@@ -6109,8 +6216,8 @@ static int sctp_eat_data(const struct sctp_association *asoc, | |||
6109 | SCTP_ERROR(ECONNABORTED)); | 6216 | SCTP_ERROR(ECONNABORTED)); |
6110 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, | 6217 | sctp_add_cmd_sf(commands, SCTP_CMD_ASSOC_FAILED, |
6111 | SCTP_PERR(SCTP_ERROR_NO_DATA)); | 6218 | SCTP_PERR(SCTP_ERROR_NO_DATA)); |
6112 | SCTP_INC_STATS(SCTP_MIB_ABORTEDS); | 6219 | SCTP_INC_STATS(net, SCTP_MIB_ABORTEDS); |
6113 | SCTP_DEC_STATS(SCTP_MIB_CURRESTAB); | 6220 | SCTP_DEC_STATS(net, SCTP_MIB_CURRESTAB); |
6114 | return SCTP_IERROR_NO_DATA; | 6221 | return SCTP_IERROR_NO_DATA; |
6115 | } | 6222 | } |
6116 | 6223 | ||
@@ -6120,9 +6227,9 @@ static int sctp_eat_data(const struct sctp_association *asoc, | |||
6120 | * if we renege and the chunk arrives again. | 6227 | * if we renege and the chunk arrives again. |
6121 | */ | 6228 | */ |
6122 | if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) | 6229 | if (chunk->chunk_hdr->flags & SCTP_DATA_UNORDERED) |
6123 | SCTP_INC_STATS(SCTP_MIB_INUNORDERCHUNKS); | 6230 | SCTP_INC_STATS(net, SCTP_MIB_INUNORDERCHUNKS); |
6124 | else { | 6231 | else { |
6125 | SCTP_INC_STATS(SCTP_MIB_INORDERCHUNKS); | 6232 | SCTP_INC_STATS(net, SCTP_MIB_INORDERCHUNKS); |
6126 | ordered = 1; | 6233 | ordered = 1; |
6127 | } | 6234 | } |
6128 | 6235 | ||
diff --git a/net/sctp/sm_statetable.c b/net/sctp/sm_statetable.c index 7c211a7f90f4..84d98d8a5a74 100644 --- a/net/sctp/sm_statetable.c +++ b/net/sctp/sm_statetable.c | |||
@@ -59,7 +59,8 @@ other_event_table[SCTP_NUM_OTHER_TYPES][SCTP_STATE_NUM_STATES]; | |||
59 | static const sctp_sm_table_entry_t | 59 | static const sctp_sm_table_entry_t |
60 | timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][SCTP_STATE_NUM_STATES]; | 60 | timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][SCTP_STATE_NUM_STATES]; |
61 | 61 | ||
62 | static const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t cid, | 62 | static const sctp_sm_table_entry_t *sctp_chunk_event_lookup(struct net *net, |
63 | sctp_cid_t cid, | ||
63 | sctp_state_t state); | 64 | sctp_state_t state); |
64 | 65 | ||
65 | 66 | ||
@@ -82,13 +83,14 @@ static const sctp_sm_table_entry_t bug = { | |||
82 | rtn; \ | 83 | rtn; \ |
83 | }) | 84 | }) |
84 | 85 | ||
85 | const sctp_sm_table_entry_t *sctp_sm_lookup_event(sctp_event_t event_type, | 86 | const sctp_sm_table_entry_t *sctp_sm_lookup_event(struct net *net, |
87 | sctp_event_t event_type, | ||
86 | sctp_state_t state, | 88 | sctp_state_t state, |
87 | sctp_subtype_t event_subtype) | 89 | sctp_subtype_t event_subtype) |
88 | { | 90 | { |
89 | switch (event_type) { | 91 | switch (event_type) { |
90 | case SCTP_EVENT_T_CHUNK: | 92 | case SCTP_EVENT_T_CHUNK: |
91 | return sctp_chunk_event_lookup(event_subtype.chunk, state); | 93 | return sctp_chunk_event_lookup(net, event_subtype.chunk, state); |
92 | case SCTP_EVENT_T_TIMEOUT: | 94 | case SCTP_EVENT_T_TIMEOUT: |
93 | return DO_LOOKUP(SCTP_EVENT_TIMEOUT_MAX, timeout, | 95 | return DO_LOOKUP(SCTP_EVENT_TIMEOUT_MAX, timeout, |
94 | timeout_event_table); | 96 | timeout_event_table); |
@@ -906,7 +908,8 @@ static const sctp_sm_table_entry_t timeout_event_table[SCTP_NUM_TIMEOUT_TYPES][S | |||
906 | TYPE_SCTP_EVENT_TIMEOUT_AUTOCLOSE, | 908 | TYPE_SCTP_EVENT_TIMEOUT_AUTOCLOSE, |
907 | }; | 909 | }; |
908 | 910 | ||
909 | static const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t cid, | 911 | static const sctp_sm_table_entry_t *sctp_chunk_event_lookup(struct net *net, |
912 | sctp_cid_t cid, | ||
910 | sctp_state_t state) | 913 | sctp_state_t state) |
911 | { | 914 | { |
912 | if (state > SCTP_STATE_MAX) | 915 | if (state > SCTP_STATE_MAX) |
@@ -915,12 +918,12 @@ static const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t cid, | |||
915 | if (cid <= SCTP_CID_BASE_MAX) | 918 | if (cid <= SCTP_CID_BASE_MAX) |
916 | return &chunk_event_table[cid][state]; | 919 | return &chunk_event_table[cid][state]; |
917 | 920 | ||
918 | if (sctp_prsctp_enable) { | 921 | if (net->sctp.prsctp_enable) { |
919 | if (cid == SCTP_CID_FWD_TSN) | 922 | if (cid == SCTP_CID_FWD_TSN) |
920 | return &prsctp_chunk_event_table[0][state]; | 923 | return &prsctp_chunk_event_table[0][state]; |
921 | } | 924 | } |
922 | 925 | ||
923 | if (sctp_addip_enable) { | 926 | if (net->sctp.addip_enable) { |
924 | if (cid == SCTP_CID_ASCONF) | 927 | if (cid == SCTP_CID_ASCONF) |
925 | return &addip_chunk_event_table[0][state]; | 928 | return &addip_chunk_event_table[0][state]; |
926 | 929 | ||
@@ -928,7 +931,7 @@ static const sctp_sm_table_entry_t *sctp_chunk_event_lookup(sctp_cid_t cid, | |||
928 | return &addip_chunk_event_table[1][state]; | 931 | return &addip_chunk_event_table[1][state]; |
929 | } | 932 | } |
930 | 933 | ||
931 | if (sctp_auth_enable) { | 934 | if (net->sctp.auth_enable) { |
932 | if (cid == SCTP_CID_AUTH) | 935 | if (cid == SCTP_CID_AUTH) |
933 | return &auth_chunk_event_table[0][state]; | 936 | return &auth_chunk_event_table[0][state]; |
934 | } | 937 | } |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 5e259817a7f3..d37d24ff197f 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -427,6 +427,7 @@ SCTP_STATIC int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) | |||
427 | static int sctp_send_asconf(struct sctp_association *asoc, | 427 | static int sctp_send_asconf(struct sctp_association *asoc, |
428 | struct sctp_chunk *chunk) | 428 | struct sctp_chunk *chunk) |
429 | { | 429 | { |
430 | struct net *net = sock_net(asoc->base.sk); | ||
430 | int retval = 0; | 431 | int retval = 0; |
431 | 432 | ||
432 | /* If there is an outstanding ASCONF chunk, queue it for later | 433 | /* If there is an outstanding ASCONF chunk, queue it for later |
@@ -439,7 +440,7 @@ static int sctp_send_asconf(struct sctp_association *asoc, | |||
439 | 440 | ||
440 | /* Hold the chunk until an ASCONF_ACK is received. */ | 441 | /* Hold the chunk until an ASCONF_ACK is received. */ |
441 | sctp_chunk_hold(chunk); | 442 | sctp_chunk_hold(chunk); |
442 | retval = sctp_primitive_ASCONF(asoc, chunk); | 443 | retval = sctp_primitive_ASCONF(net, asoc, chunk); |
443 | if (retval) | 444 | if (retval) |
444 | sctp_chunk_free(chunk); | 445 | sctp_chunk_free(chunk); |
445 | else | 446 | else |
@@ -515,6 +516,7 @@ static int sctp_send_asconf_add_ip(struct sock *sk, | |||
515 | struct sockaddr *addrs, | 516 | struct sockaddr *addrs, |
516 | int addrcnt) | 517 | int addrcnt) |
517 | { | 518 | { |
519 | struct net *net = sock_net(sk); | ||
518 | struct sctp_sock *sp; | 520 | struct sctp_sock *sp; |
519 | struct sctp_endpoint *ep; | 521 | struct sctp_endpoint *ep; |
520 | struct sctp_association *asoc; | 522 | struct sctp_association *asoc; |
@@ -529,7 +531,7 @@ static int sctp_send_asconf_add_ip(struct sock *sk, | |||
529 | int i; | 531 | int i; |
530 | int retval = 0; | 532 | int retval = 0; |
531 | 533 | ||
532 | if (!sctp_addip_enable) | 534 | if (!net->sctp.addip_enable) |
533 | return retval; | 535 | return retval; |
534 | 536 | ||
535 | sp = sctp_sk(sk); | 537 | sp = sctp_sk(sk); |
@@ -717,6 +719,7 @@ static int sctp_send_asconf_del_ip(struct sock *sk, | |||
717 | struct sockaddr *addrs, | 719 | struct sockaddr *addrs, |
718 | int addrcnt) | 720 | int addrcnt) |
719 | { | 721 | { |
722 | struct net *net = sock_net(sk); | ||
720 | struct sctp_sock *sp; | 723 | struct sctp_sock *sp; |
721 | struct sctp_endpoint *ep; | 724 | struct sctp_endpoint *ep; |
722 | struct sctp_association *asoc; | 725 | struct sctp_association *asoc; |
@@ -732,7 +735,7 @@ static int sctp_send_asconf_del_ip(struct sock *sk, | |||
732 | int stored = 0; | 735 | int stored = 0; |
733 | 736 | ||
734 | chunk = NULL; | 737 | chunk = NULL; |
735 | if (!sctp_addip_enable) | 738 | if (!net->sctp.addip_enable) |
736 | return retval; | 739 | return retval; |
737 | 740 | ||
738 | sp = sctp_sk(sk); | 741 | sp = sctp_sk(sk); |
@@ -1050,6 +1053,7 @@ static int __sctp_connect(struct sock* sk, | |||
1050 | int addrs_size, | 1053 | int addrs_size, |
1051 | sctp_assoc_t *assoc_id) | 1054 | sctp_assoc_t *assoc_id) |
1052 | { | 1055 | { |
1056 | struct net *net = sock_net(sk); | ||
1053 | struct sctp_sock *sp; | 1057 | struct sctp_sock *sp; |
1054 | struct sctp_endpoint *ep; | 1058 | struct sctp_endpoint *ep; |
1055 | struct sctp_association *asoc = NULL; | 1059 | struct sctp_association *asoc = NULL; |
@@ -1200,7 +1204,7 @@ static int __sctp_connect(struct sock* sk, | |||
1200 | goto out_free; | 1204 | goto out_free; |
1201 | } | 1205 | } |
1202 | 1206 | ||
1203 | err = sctp_primitive_ASSOCIATE(asoc, NULL); | 1207 | err = sctp_primitive_ASSOCIATE(net, asoc, NULL); |
1204 | if (err < 0) { | 1208 | if (err < 0) { |
1205 | goto out_free; | 1209 | goto out_free; |
1206 | } | 1210 | } |
@@ -1458,6 +1462,7 @@ SCTP_STATIC int sctp_getsockopt_connectx3(struct sock* sk, int len, | |||
1458 | */ | 1462 | */ |
1459 | SCTP_STATIC void sctp_close(struct sock *sk, long timeout) | 1463 | SCTP_STATIC void sctp_close(struct sock *sk, long timeout) |
1460 | { | 1464 | { |
1465 | struct net *net = sock_net(sk); | ||
1461 | struct sctp_endpoint *ep; | 1466 | struct sctp_endpoint *ep; |
1462 | struct sctp_association *asoc; | 1467 | struct sctp_association *asoc; |
1463 | struct list_head *pos, *temp; | 1468 | struct list_head *pos, *temp; |
@@ -1499,9 +1504,9 @@ SCTP_STATIC void sctp_close(struct sock *sk, long timeout) | |||
1499 | 1504 | ||
1500 | chunk = sctp_make_abort_user(asoc, NULL, 0); | 1505 | chunk = sctp_make_abort_user(asoc, NULL, 0); |
1501 | if (chunk) | 1506 | if (chunk) |
1502 | sctp_primitive_ABORT(asoc, chunk); | 1507 | sctp_primitive_ABORT(net, asoc, chunk); |
1503 | } else | 1508 | } else |
1504 | sctp_primitive_SHUTDOWN(asoc, NULL); | 1509 | sctp_primitive_SHUTDOWN(net, asoc, NULL); |
1505 | } | 1510 | } |
1506 | 1511 | ||
1507 | /* On a TCP-style socket, block for at most linger_time if set. */ | 1512 | /* On a TCP-style socket, block for at most linger_time if set. */ |
@@ -1569,6 +1574,7 @@ SCTP_STATIC int sctp_msghdr_parse(const struct msghdr *, sctp_cmsgs_t *); | |||
1569 | SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | 1574 | SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, |
1570 | struct msghdr *msg, size_t msg_len) | 1575 | struct msghdr *msg, size_t msg_len) |
1571 | { | 1576 | { |
1577 | struct net *net = sock_net(sk); | ||
1572 | struct sctp_sock *sp; | 1578 | struct sctp_sock *sp; |
1573 | struct sctp_endpoint *ep; | 1579 | struct sctp_endpoint *ep; |
1574 | struct sctp_association *new_asoc=NULL, *asoc=NULL; | 1580 | struct sctp_association *new_asoc=NULL, *asoc=NULL; |
@@ -1714,7 +1720,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1714 | if (sinfo_flags & SCTP_EOF) { | 1720 | if (sinfo_flags & SCTP_EOF) { |
1715 | SCTP_DEBUG_PRINTK("Shutting down association: %p\n", | 1721 | SCTP_DEBUG_PRINTK("Shutting down association: %p\n", |
1716 | asoc); | 1722 | asoc); |
1717 | sctp_primitive_SHUTDOWN(asoc, NULL); | 1723 | sctp_primitive_SHUTDOWN(net, asoc, NULL); |
1718 | err = 0; | 1724 | err = 0; |
1719 | goto out_unlock; | 1725 | goto out_unlock; |
1720 | } | 1726 | } |
@@ -1727,7 +1733,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1727 | } | 1733 | } |
1728 | 1734 | ||
1729 | SCTP_DEBUG_PRINTK("Aborting association: %p\n", asoc); | 1735 | SCTP_DEBUG_PRINTK("Aborting association: %p\n", asoc); |
1730 | sctp_primitive_ABORT(asoc, chunk); | 1736 | sctp_primitive_ABORT(net, asoc, chunk); |
1731 | err = 0; | 1737 | err = 0; |
1732 | goto out_unlock; | 1738 | goto out_unlock; |
1733 | } | 1739 | } |
@@ -1900,7 +1906,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1900 | 1906 | ||
1901 | /* Auto-connect, if we aren't connected already. */ | 1907 | /* Auto-connect, if we aren't connected already. */ |
1902 | if (sctp_state(asoc, CLOSED)) { | 1908 | if (sctp_state(asoc, CLOSED)) { |
1903 | err = sctp_primitive_ASSOCIATE(asoc, NULL); | 1909 | err = sctp_primitive_ASSOCIATE(net, asoc, NULL); |
1904 | if (err < 0) | 1910 | if (err < 0) |
1905 | goto out_free; | 1911 | goto out_free; |
1906 | SCTP_DEBUG_PRINTK("We associated primitively.\n"); | 1912 | SCTP_DEBUG_PRINTK("We associated primitively.\n"); |
@@ -1928,7 +1934,7 @@ SCTP_STATIC int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1928 | * works that way today. Keep it that way or this | 1934 | * works that way today. Keep it that way or this |
1929 | * breaks. | 1935 | * breaks. |
1930 | */ | 1936 | */ |
1931 | err = sctp_primitive_SEND(asoc, datamsg); | 1937 | err = sctp_primitive_SEND(net, asoc, datamsg); |
1932 | /* Did the lower layer accept the chunk? */ | 1938 | /* Did the lower layer accept the chunk? */ |
1933 | if (err) | 1939 | if (err) |
1934 | sctp_datamsg_free(datamsg); | 1940 | sctp_datamsg_free(datamsg); |
@@ -2320,7 +2326,9 @@ static int sctp_apply_peer_addr_params(struct sctp_paddrparams *params, | |||
2320 | int error; | 2326 | int error; |
2321 | 2327 | ||
2322 | if (params->spp_flags & SPP_HB_DEMAND && trans) { | 2328 | if (params->spp_flags & SPP_HB_DEMAND && trans) { |
2323 | error = sctp_primitive_REQUESTHEARTBEAT (trans->asoc, trans); | 2329 | struct net *net = sock_net(trans->asoc->base.sk); |
2330 | |||
2331 | error = sctp_primitive_REQUESTHEARTBEAT(net, trans->asoc, trans); | ||
2324 | if (error) | 2332 | if (error) |
2325 | return error; | 2333 | return error; |
2326 | } | 2334 | } |
@@ -3033,6 +3041,7 @@ static int sctp_setsockopt_maxseg(struct sock *sk, char __user *optval, unsigned | |||
3033 | static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optval, | 3041 | static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optval, |
3034 | unsigned int optlen) | 3042 | unsigned int optlen) |
3035 | { | 3043 | { |
3044 | struct net *net = sock_net(sk); | ||
3036 | struct sctp_sock *sp; | 3045 | struct sctp_sock *sp; |
3037 | struct sctp_association *asoc = NULL; | 3046 | struct sctp_association *asoc = NULL; |
3038 | struct sctp_setpeerprim prim; | 3047 | struct sctp_setpeerprim prim; |
@@ -3042,7 +3051,7 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optva | |||
3042 | 3051 | ||
3043 | sp = sctp_sk(sk); | 3052 | sp = sctp_sk(sk); |
3044 | 3053 | ||
3045 | if (!sctp_addip_enable) | 3054 | if (!net->sctp.addip_enable) |
3046 | return -EPERM; | 3055 | return -EPERM; |
3047 | 3056 | ||
3048 | if (optlen != sizeof(struct sctp_setpeerprim)) | 3057 | if (optlen != sizeof(struct sctp_setpeerprim)) |
@@ -3279,9 +3288,10 @@ static int sctp_setsockopt_auth_chunk(struct sock *sk, | |||
3279 | char __user *optval, | 3288 | char __user *optval, |
3280 | unsigned int optlen) | 3289 | unsigned int optlen) |
3281 | { | 3290 | { |
3291 | struct net *net = sock_net(sk); | ||
3282 | struct sctp_authchunk val; | 3292 | struct sctp_authchunk val; |
3283 | 3293 | ||
3284 | if (!sctp_auth_enable) | 3294 | if (!net->sctp.auth_enable) |
3285 | return -EACCES; | 3295 | return -EACCES; |
3286 | 3296 | ||
3287 | if (optlen != sizeof(struct sctp_authchunk)) | 3297 | if (optlen != sizeof(struct sctp_authchunk)) |
@@ -3311,11 +3321,12 @@ static int sctp_setsockopt_hmac_ident(struct sock *sk, | |||
3311 | char __user *optval, | 3321 | char __user *optval, |
3312 | unsigned int optlen) | 3322 | unsigned int optlen) |
3313 | { | 3323 | { |
3324 | struct net *net = sock_net(sk); | ||
3314 | struct sctp_hmacalgo *hmacs; | 3325 | struct sctp_hmacalgo *hmacs; |
3315 | u32 idents; | 3326 | u32 idents; |
3316 | int err; | 3327 | int err; |
3317 | 3328 | ||
3318 | if (!sctp_auth_enable) | 3329 | if (!net->sctp.auth_enable) |
3319 | return -EACCES; | 3330 | return -EACCES; |
3320 | 3331 | ||
3321 | if (optlen < sizeof(struct sctp_hmacalgo)) | 3332 | if (optlen < sizeof(struct sctp_hmacalgo)) |
@@ -3348,11 +3359,12 @@ static int sctp_setsockopt_auth_key(struct sock *sk, | |||
3348 | char __user *optval, | 3359 | char __user *optval, |
3349 | unsigned int optlen) | 3360 | unsigned int optlen) |
3350 | { | 3361 | { |
3362 | struct net *net = sock_net(sk); | ||
3351 | struct sctp_authkey *authkey; | 3363 | struct sctp_authkey *authkey; |
3352 | struct sctp_association *asoc; | 3364 | struct sctp_association *asoc; |
3353 | int ret; | 3365 | int ret; |
3354 | 3366 | ||
3355 | if (!sctp_auth_enable) | 3367 | if (!net->sctp.auth_enable) |
3356 | return -EACCES; | 3368 | return -EACCES; |
3357 | 3369 | ||
3358 | if (optlen <= sizeof(struct sctp_authkey)) | 3370 | if (optlen <= sizeof(struct sctp_authkey)) |
@@ -3389,10 +3401,11 @@ static int sctp_setsockopt_active_key(struct sock *sk, | |||
3389 | char __user *optval, | 3401 | char __user *optval, |
3390 | unsigned int optlen) | 3402 | unsigned int optlen) |
3391 | { | 3403 | { |
3404 | struct net *net = sock_net(sk); | ||
3392 | struct sctp_authkeyid val; | 3405 | struct sctp_authkeyid val; |
3393 | struct sctp_association *asoc; | 3406 | struct sctp_association *asoc; |
3394 | 3407 | ||
3395 | if (!sctp_auth_enable) | 3408 | if (!net->sctp.auth_enable) |
3396 | return -EACCES; | 3409 | return -EACCES; |
3397 | 3410 | ||
3398 | if (optlen != sizeof(struct sctp_authkeyid)) | 3411 | if (optlen != sizeof(struct sctp_authkeyid)) |
@@ -3417,10 +3430,11 @@ static int sctp_setsockopt_del_key(struct sock *sk, | |||
3417 | char __user *optval, | 3430 | char __user *optval, |
3418 | unsigned int optlen) | 3431 | unsigned int optlen) |
3419 | { | 3432 | { |
3433 | struct net *net = sock_net(sk); | ||
3420 | struct sctp_authkeyid val; | 3434 | struct sctp_authkeyid val; |
3421 | struct sctp_association *asoc; | 3435 | struct sctp_association *asoc; |
3422 | 3436 | ||
3423 | if (!sctp_auth_enable) | 3437 | if (!net->sctp.auth_enable) |
3424 | return -EACCES; | 3438 | return -EACCES; |
3425 | 3439 | ||
3426 | if (optlen != sizeof(struct sctp_authkeyid)) | 3440 | if (optlen != sizeof(struct sctp_authkeyid)) |
@@ -3471,7 +3485,7 @@ static int sctp_setsockopt_auto_asconf(struct sock *sk, char __user *optval, | |||
3471 | sp->do_auto_asconf = 0; | 3485 | sp->do_auto_asconf = 0; |
3472 | } else if (val && !sp->do_auto_asconf) { | 3486 | } else if (val && !sp->do_auto_asconf) { |
3473 | list_add_tail(&sp->auto_asconf_list, | 3487 | list_add_tail(&sp->auto_asconf_list, |
3474 | &sctp_auto_asconf_splist); | 3488 | &sock_net(sk)->sctp.auto_asconf_splist); |
3475 | sp->do_auto_asconf = 1; | 3489 | sp->do_auto_asconf = 1; |
3476 | } | 3490 | } |
3477 | return 0; | 3491 | return 0; |
@@ -3843,6 +3857,7 @@ out: | |||
3843 | */ | 3857 | */ |
3844 | SCTP_STATIC int sctp_init_sock(struct sock *sk) | 3858 | SCTP_STATIC int sctp_init_sock(struct sock *sk) |
3845 | { | 3859 | { |
3860 | struct net *net = sock_net(sk); | ||
3846 | struct sctp_endpoint *ep; | 3861 | struct sctp_endpoint *ep; |
3847 | struct sctp_sock *sp; | 3862 | struct sctp_sock *sp; |
3848 | 3863 | ||
@@ -3872,7 +3887,7 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) | |||
3872 | sp->default_timetolive = 0; | 3887 | sp->default_timetolive = 0; |
3873 | 3888 | ||
3874 | sp->default_rcv_context = 0; | 3889 | sp->default_rcv_context = 0; |
3875 | sp->max_burst = sctp_max_burst; | 3890 | sp->max_burst = net->sctp.max_burst; |
3876 | 3891 | ||
3877 | /* Initialize default setup parameters. These parameters | 3892 | /* Initialize default setup parameters. These parameters |
3878 | * can be modified with the SCTP_INITMSG socket option or | 3893 | * can be modified with the SCTP_INITMSG socket option or |
@@ -3880,24 +3895,24 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) | |||
3880 | */ | 3895 | */ |
3881 | sp->initmsg.sinit_num_ostreams = sctp_max_outstreams; | 3896 | sp->initmsg.sinit_num_ostreams = sctp_max_outstreams; |
3882 | sp->initmsg.sinit_max_instreams = sctp_max_instreams; | 3897 | sp->initmsg.sinit_max_instreams = sctp_max_instreams; |
3883 | sp->initmsg.sinit_max_attempts = sctp_max_retrans_init; | 3898 | sp->initmsg.sinit_max_attempts = net->sctp.max_retrans_init; |
3884 | sp->initmsg.sinit_max_init_timeo = sctp_rto_max; | 3899 | sp->initmsg.sinit_max_init_timeo = net->sctp.rto_max; |
3885 | 3900 | ||
3886 | /* Initialize default RTO related parameters. These parameters can | 3901 | /* Initialize default RTO related parameters. These parameters can |
3887 | * be modified for with the SCTP_RTOINFO socket option. | 3902 | * be modified for with the SCTP_RTOINFO socket option. |
3888 | */ | 3903 | */ |
3889 | sp->rtoinfo.srto_initial = sctp_rto_initial; | 3904 | sp->rtoinfo.srto_initial = net->sctp.rto_initial; |
3890 | sp->rtoinfo.srto_max = sctp_rto_max; | 3905 | sp->rtoinfo.srto_max = net->sctp.rto_max; |
3891 | sp->rtoinfo.srto_min = sctp_rto_min; | 3906 | sp->rtoinfo.srto_min = net->sctp.rto_min; |
3892 | 3907 | ||
3893 | /* Initialize default association related parameters. These parameters | 3908 | /* Initialize default association related parameters. These parameters |
3894 | * can be modified with the SCTP_ASSOCINFO socket option. | 3909 | * can be modified with the SCTP_ASSOCINFO socket option. |
3895 | */ | 3910 | */ |
3896 | sp->assocparams.sasoc_asocmaxrxt = sctp_max_retrans_association; | 3911 | sp->assocparams.sasoc_asocmaxrxt = net->sctp.max_retrans_association; |
3897 | sp->assocparams.sasoc_number_peer_destinations = 0; | 3912 | sp->assocparams.sasoc_number_peer_destinations = 0; |
3898 | sp->assocparams.sasoc_peer_rwnd = 0; | 3913 | sp->assocparams.sasoc_peer_rwnd = 0; |
3899 | sp->assocparams.sasoc_local_rwnd = 0; | 3914 | sp->assocparams.sasoc_local_rwnd = 0; |
3900 | sp->assocparams.sasoc_cookie_life = sctp_valid_cookie_life; | 3915 | sp->assocparams.sasoc_cookie_life = net->sctp.valid_cookie_life; |
3901 | 3916 | ||
3902 | /* Initialize default event subscriptions. By default, all the | 3917 | /* Initialize default event subscriptions. By default, all the |
3903 | * options are off. | 3918 | * options are off. |
@@ -3907,10 +3922,10 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) | |||
3907 | /* Default Peer Address Parameters. These defaults can | 3922 | /* Default Peer Address Parameters. These defaults can |
3908 | * be modified via SCTP_PEER_ADDR_PARAMS | 3923 | * be modified via SCTP_PEER_ADDR_PARAMS |
3909 | */ | 3924 | */ |
3910 | sp->hbinterval = sctp_hb_interval; | 3925 | sp->hbinterval = net->sctp.hb_interval; |
3911 | sp->pathmaxrxt = sctp_max_retrans_path; | 3926 | sp->pathmaxrxt = net->sctp.max_retrans_path; |
3912 | sp->pathmtu = 0; // allow default discovery | 3927 | sp->pathmtu = 0; // allow default discovery |
3913 | sp->sackdelay = sctp_sack_timeout; | 3928 | sp->sackdelay = net->sctp.sack_timeout; |
3914 | sp->sackfreq = 2; | 3929 | sp->sackfreq = 2; |
3915 | sp->param_flags = SPP_HB_ENABLE | | 3930 | sp->param_flags = SPP_HB_ENABLE | |
3916 | SPP_PMTUD_ENABLE | | 3931 | SPP_PMTUD_ENABLE | |
@@ -3961,10 +3976,10 @@ SCTP_STATIC int sctp_init_sock(struct sock *sk) | |||
3961 | 3976 | ||
3962 | local_bh_disable(); | 3977 | local_bh_disable(); |
3963 | percpu_counter_inc(&sctp_sockets_allocated); | 3978 | percpu_counter_inc(&sctp_sockets_allocated); |
3964 | sock_prot_inuse_add(sock_net(sk), sk->sk_prot, 1); | 3979 | sock_prot_inuse_add(net, sk->sk_prot, 1); |
3965 | if (sctp_default_auto_asconf) { | 3980 | if (net->sctp.default_auto_asconf) { |
3966 | list_add_tail(&sp->auto_asconf_list, | 3981 | list_add_tail(&sp->auto_asconf_list, |
3967 | &sctp_auto_asconf_splist); | 3982 | &net->sctp.auto_asconf_splist); |
3968 | sp->do_auto_asconf = 1; | 3983 | sp->do_auto_asconf = 1; |
3969 | } else | 3984 | } else |
3970 | sp->do_auto_asconf = 0; | 3985 | sp->do_auto_asconf = 0; |
@@ -4011,6 +4026,7 @@ SCTP_STATIC void sctp_destroy_sock(struct sock *sk) | |||
4011 | */ | 4026 | */ |
4012 | SCTP_STATIC void sctp_shutdown(struct sock *sk, int how) | 4027 | SCTP_STATIC void sctp_shutdown(struct sock *sk, int how) |
4013 | { | 4028 | { |
4029 | struct net *net = sock_net(sk); | ||
4014 | struct sctp_endpoint *ep; | 4030 | struct sctp_endpoint *ep; |
4015 | struct sctp_association *asoc; | 4031 | struct sctp_association *asoc; |
4016 | 4032 | ||
@@ -4022,7 +4038,7 @@ SCTP_STATIC void sctp_shutdown(struct sock *sk, int how) | |||
4022 | if (!list_empty(&ep->asocs)) { | 4038 | if (!list_empty(&ep->asocs)) { |
4023 | asoc = list_entry(ep->asocs.next, | 4039 | asoc = list_entry(ep->asocs.next, |
4024 | struct sctp_association, asocs); | 4040 | struct sctp_association, asocs); |
4025 | sctp_primitive_SHUTDOWN(asoc, NULL); | 4041 | sctp_primitive_SHUTDOWN(net, asoc, NULL); |
4026 | } | 4042 | } |
4027 | } | 4043 | } |
4028 | } | 4044 | } |
@@ -4653,9 +4669,10 @@ static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to, | |||
4653 | union sctp_addr temp; | 4669 | union sctp_addr temp; |
4654 | int cnt = 0; | 4670 | int cnt = 0; |
4655 | int addrlen; | 4671 | int addrlen; |
4672 | struct net *net = sock_net(sk); | ||
4656 | 4673 | ||
4657 | rcu_read_lock(); | 4674 | rcu_read_lock(); |
4658 | list_for_each_entry_rcu(addr, &sctp_local_addr_list, list) { | 4675 | list_for_each_entry_rcu(addr, &net->sctp.local_addr_list, list) { |
4659 | if (!addr->valid) | 4676 | if (!addr->valid) |
4660 | continue; | 4677 | continue; |
4661 | 4678 | ||
@@ -5299,12 +5316,13 @@ static int sctp_getsockopt_maxburst(struct sock *sk, int len, | |||
5299 | static int sctp_getsockopt_hmac_ident(struct sock *sk, int len, | 5316 | static int sctp_getsockopt_hmac_ident(struct sock *sk, int len, |
5300 | char __user *optval, int __user *optlen) | 5317 | char __user *optval, int __user *optlen) |
5301 | { | 5318 | { |
5319 | struct net *net = sock_net(sk); | ||
5302 | struct sctp_hmacalgo __user *p = (void __user *)optval; | 5320 | struct sctp_hmacalgo __user *p = (void __user *)optval; |
5303 | struct sctp_hmac_algo_param *hmacs; | 5321 | struct sctp_hmac_algo_param *hmacs; |
5304 | __u16 data_len = 0; | 5322 | __u16 data_len = 0; |
5305 | u32 num_idents; | 5323 | u32 num_idents; |
5306 | 5324 | ||
5307 | if (!sctp_auth_enable) | 5325 | if (!net->sctp.auth_enable) |
5308 | return -EACCES; | 5326 | return -EACCES; |
5309 | 5327 | ||
5310 | hmacs = sctp_sk(sk)->ep->auth_hmacs_list; | 5328 | hmacs = sctp_sk(sk)->ep->auth_hmacs_list; |
@@ -5328,10 +5346,11 @@ static int sctp_getsockopt_hmac_ident(struct sock *sk, int len, | |||
5328 | static int sctp_getsockopt_active_key(struct sock *sk, int len, | 5346 | static int sctp_getsockopt_active_key(struct sock *sk, int len, |
5329 | char __user *optval, int __user *optlen) | 5347 | char __user *optval, int __user *optlen) |
5330 | { | 5348 | { |
5349 | struct net *net = sock_net(sk); | ||
5331 | struct sctp_authkeyid val; | 5350 | struct sctp_authkeyid val; |
5332 | struct sctp_association *asoc; | 5351 | struct sctp_association *asoc; |
5333 | 5352 | ||
5334 | if (!sctp_auth_enable) | 5353 | if (!net->sctp.auth_enable) |
5335 | return -EACCES; | 5354 | return -EACCES; |
5336 | 5355 | ||
5337 | if (len < sizeof(struct sctp_authkeyid)) | 5356 | if (len < sizeof(struct sctp_authkeyid)) |
@@ -5360,6 +5379,7 @@ static int sctp_getsockopt_active_key(struct sock *sk, int len, | |||
5360 | static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len, | 5379 | static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len, |
5361 | char __user *optval, int __user *optlen) | 5380 | char __user *optval, int __user *optlen) |
5362 | { | 5381 | { |
5382 | struct net *net = sock_net(sk); | ||
5363 | struct sctp_authchunks __user *p = (void __user *)optval; | 5383 | struct sctp_authchunks __user *p = (void __user *)optval; |
5364 | struct sctp_authchunks val; | 5384 | struct sctp_authchunks val; |
5365 | struct sctp_association *asoc; | 5385 | struct sctp_association *asoc; |
@@ -5367,7 +5387,7 @@ static int sctp_getsockopt_peer_auth_chunks(struct sock *sk, int len, | |||
5367 | u32 num_chunks = 0; | 5387 | u32 num_chunks = 0; |
5368 | char __user *to; | 5388 | char __user *to; |
5369 | 5389 | ||
5370 | if (!sctp_auth_enable) | 5390 | if (!net->sctp.auth_enable) |
5371 | return -EACCES; | 5391 | return -EACCES; |
5372 | 5392 | ||
5373 | if (len < sizeof(struct sctp_authchunks)) | 5393 | if (len < sizeof(struct sctp_authchunks)) |
@@ -5403,6 +5423,7 @@ num: | |||
5403 | static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len, | 5423 | static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len, |
5404 | char __user *optval, int __user *optlen) | 5424 | char __user *optval, int __user *optlen) |
5405 | { | 5425 | { |
5426 | struct net *net = sock_net(sk); | ||
5406 | struct sctp_authchunks __user *p = (void __user *)optval; | 5427 | struct sctp_authchunks __user *p = (void __user *)optval; |
5407 | struct sctp_authchunks val; | 5428 | struct sctp_authchunks val; |
5408 | struct sctp_association *asoc; | 5429 | struct sctp_association *asoc; |
@@ -5410,7 +5431,7 @@ static int sctp_getsockopt_local_auth_chunks(struct sock *sk, int len, | |||
5410 | u32 num_chunks = 0; | 5431 | u32 num_chunks = 0; |
5411 | char __user *to; | 5432 | char __user *to; |
5412 | 5433 | ||
5413 | if (!sctp_auth_enable) | 5434 | if (!net->sctp.auth_enable) |
5414 | return -EACCES; | 5435 | return -EACCES; |
5415 | 5436 | ||
5416 | if (len < sizeof(struct sctp_authchunks)) | 5437 | if (len < sizeof(struct sctp_authchunks)) |
@@ -5769,7 +5790,7 @@ static void sctp_unhash(struct sock *sk) | |||
5769 | * a fastreuse flag (FIXME: NPI ipg). | 5790 | * a fastreuse flag (FIXME: NPI ipg). |
5770 | */ | 5791 | */ |
5771 | static struct sctp_bind_bucket *sctp_bucket_create( | 5792 | static struct sctp_bind_bucket *sctp_bucket_create( |
5772 | struct sctp_bind_hashbucket *head, unsigned short snum); | 5793 | struct sctp_bind_hashbucket *head, struct net *, unsigned short snum); |
5773 | 5794 | ||
5774 | static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) | 5795 | static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) |
5775 | { | 5796 | { |
@@ -5799,11 +5820,12 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) | |||
5799 | rover = low; | 5820 | rover = low; |
5800 | if (inet_is_reserved_local_port(rover)) | 5821 | if (inet_is_reserved_local_port(rover)) |
5801 | continue; | 5822 | continue; |
5802 | index = sctp_phashfn(rover); | 5823 | index = sctp_phashfn(sock_net(sk), rover); |
5803 | head = &sctp_port_hashtable[index]; | 5824 | head = &sctp_port_hashtable[index]; |
5804 | sctp_spin_lock(&head->lock); | 5825 | sctp_spin_lock(&head->lock); |
5805 | sctp_for_each_hentry(pp, node, &head->chain) | 5826 | sctp_for_each_hentry(pp, node, &head->chain) |
5806 | if (pp->port == rover) | 5827 | if ((pp->port == rover) && |
5828 | net_eq(sock_net(sk), pp->net)) | ||
5807 | goto next; | 5829 | goto next; |
5808 | break; | 5830 | break; |
5809 | next: | 5831 | next: |
@@ -5827,10 +5849,10 @@ static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr) | |||
5827 | * to the port number (snum) - we detect that with the | 5849 | * to the port number (snum) - we detect that with the |
5828 | * port iterator, pp being NULL. | 5850 | * port iterator, pp being NULL. |
5829 | */ | 5851 | */ |
5830 | head = &sctp_port_hashtable[sctp_phashfn(snum)]; | 5852 | head = &sctp_port_hashtable[sctp_phashfn(sock_net(sk), snum)]; |
5831 | sctp_spin_lock(&head->lock); | 5853 | sctp_spin_lock(&head->lock); |
5832 | sctp_for_each_hentry(pp, node, &head->chain) { | 5854 | sctp_for_each_hentry(pp, node, &head->chain) { |
5833 | if (pp->port == snum) | 5855 | if ((pp->port == snum) && net_eq(pp->net, sock_net(sk))) |
5834 | goto pp_found; | 5856 | goto pp_found; |
5835 | } | 5857 | } |
5836 | } | 5858 | } |
@@ -5881,7 +5903,7 @@ pp_found: | |||
5881 | pp_not_found: | 5903 | pp_not_found: |
5882 | /* If there was a hash table miss, create a new port. */ | 5904 | /* If there was a hash table miss, create a new port. */ |
5883 | ret = 1; | 5905 | ret = 1; |
5884 | if (!pp && !(pp = sctp_bucket_create(head, snum))) | 5906 | if (!pp && !(pp = sctp_bucket_create(head, sock_net(sk), snum))) |
5885 | goto fail_unlock; | 5907 | goto fail_unlock; |
5886 | 5908 | ||
5887 | /* In either case (hit or miss), make sure fastreuse is 1 only | 5909 | /* In either case (hit or miss), make sure fastreuse is 1 only |
@@ -6113,7 +6135,7 @@ unsigned int sctp_poll(struct file *file, struct socket *sock, poll_table *wait) | |||
6113 | ********************************************************************/ | 6135 | ********************************************************************/ |
6114 | 6136 | ||
6115 | static struct sctp_bind_bucket *sctp_bucket_create( | 6137 | static struct sctp_bind_bucket *sctp_bucket_create( |
6116 | struct sctp_bind_hashbucket *head, unsigned short snum) | 6138 | struct sctp_bind_hashbucket *head, struct net *net, unsigned short snum) |
6117 | { | 6139 | { |
6118 | struct sctp_bind_bucket *pp; | 6140 | struct sctp_bind_bucket *pp; |
6119 | 6141 | ||
@@ -6123,6 +6145,7 @@ static struct sctp_bind_bucket *sctp_bucket_create( | |||
6123 | pp->port = snum; | 6145 | pp->port = snum; |
6124 | pp->fastreuse = 0; | 6146 | pp->fastreuse = 0; |
6125 | INIT_HLIST_HEAD(&pp->owner); | 6147 | INIT_HLIST_HEAD(&pp->owner); |
6148 | pp->net = net; | ||
6126 | hlist_add_head(&pp->node, &head->chain); | 6149 | hlist_add_head(&pp->node, &head->chain); |
6127 | } | 6150 | } |
6128 | return pp; | 6151 | return pp; |
@@ -6142,7 +6165,8 @@ static void sctp_bucket_destroy(struct sctp_bind_bucket *pp) | |||
6142 | static inline void __sctp_put_port(struct sock *sk) | 6165 | static inline void __sctp_put_port(struct sock *sk) |
6143 | { | 6166 | { |
6144 | struct sctp_bind_hashbucket *head = | 6167 | struct sctp_bind_hashbucket *head = |
6145 | &sctp_port_hashtable[sctp_phashfn(inet_sk(sk)->inet_num)]; | 6168 | &sctp_port_hashtable[sctp_phashfn(sock_net(sk), |
6169 | inet_sk(sk)->inet_num)]; | ||
6146 | struct sctp_bind_bucket *pp; | 6170 | struct sctp_bind_bucket *pp; |
6147 | 6171 | ||
6148 | sctp_spin_lock(&head->lock); | 6172 | sctp_spin_lock(&head->lock); |
@@ -6809,7 +6833,8 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk, | |||
6809 | newsp->hmac = NULL; | 6833 | newsp->hmac = NULL; |
6810 | 6834 | ||
6811 | /* Hook this new socket in to the bind_hash list. */ | 6835 | /* Hook this new socket in to the bind_hash list. */ |
6812 | head = &sctp_port_hashtable[sctp_phashfn(inet_sk(oldsk)->inet_num)]; | 6836 | head = &sctp_port_hashtable[sctp_phashfn(sock_net(oldsk), |
6837 | inet_sk(oldsk)->inet_num)]; | ||
6813 | sctp_local_bh_disable(); | 6838 | sctp_local_bh_disable(); |
6814 | sctp_spin_lock(&head->lock); | 6839 | sctp_spin_lock(&head->lock); |
6815 | pp = sctp_sk(oldsk)->bind_hash; | 6840 | pp = sctp_sk(oldsk)->bind_hash; |
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index 2b2bfe933ff1..70e3ba5cb50b 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c | |||
@@ -64,8 +64,34 @@ extern int sysctl_sctp_wmem[3]; | |||
64 | 64 | ||
65 | static ctl_table sctp_table[] = { | 65 | static ctl_table sctp_table[] = { |
66 | { | 66 | { |
67 | .procname = "sctp_mem", | ||
68 | .data = &sysctl_sctp_mem, | ||
69 | .maxlen = sizeof(sysctl_sctp_mem), | ||
70 | .mode = 0644, | ||
71 | .proc_handler = proc_doulongvec_minmax | ||
72 | }, | ||
73 | { | ||
74 | .procname = "sctp_rmem", | ||
75 | .data = &sysctl_sctp_rmem, | ||
76 | .maxlen = sizeof(sysctl_sctp_rmem), | ||
77 | .mode = 0644, | ||
78 | .proc_handler = proc_dointvec, | ||
79 | }, | ||
80 | { | ||
81 | .procname = "sctp_wmem", | ||
82 | .data = &sysctl_sctp_wmem, | ||
83 | .maxlen = sizeof(sysctl_sctp_wmem), | ||
84 | .mode = 0644, | ||
85 | .proc_handler = proc_dointvec, | ||
86 | }, | ||
87 | |||
88 | { /* sentinel */ } | ||
89 | }; | ||
90 | |||
91 | static ctl_table sctp_net_table[] = { | ||
92 | { | ||
67 | .procname = "rto_initial", | 93 | .procname = "rto_initial", |
68 | .data = &sctp_rto_initial, | 94 | .data = &init_net.sctp.rto_initial, |
69 | .maxlen = sizeof(unsigned int), | 95 | .maxlen = sizeof(unsigned int), |
70 | .mode = 0644, | 96 | .mode = 0644, |
71 | .proc_handler = proc_dointvec_minmax, | 97 | .proc_handler = proc_dointvec_minmax, |
@@ -74,7 +100,7 @@ static ctl_table sctp_table[] = { | |||
74 | }, | 100 | }, |
75 | { | 101 | { |
76 | .procname = "rto_min", | 102 | .procname = "rto_min", |
77 | .data = &sctp_rto_min, | 103 | .data = &init_net.sctp.rto_min, |
78 | .maxlen = sizeof(unsigned int), | 104 | .maxlen = sizeof(unsigned int), |
79 | .mode = 0644, | 105 | .mode = 0644, |
80 | .proc_handler = proc_dointvec_minmax, | 106 | .proc_handler = proc_dointvec_minmax, |
@@ -83,7 +109,7 @@ static ctl_table sctp_table[] = { | |||
83 | }, | 109 | }, |
84 | { | 110 | { |
85 | .procname = "rto_max", | 111 | .procname = "rto_max", |
86 | .data = &sctp_rto_max, | 112 | .data = &init_net.sctp.rto_max, |
87 | .maxlen = sizeof(unsigned int), | 113 | .maxlen = sizeof(unsigned int), |
88 | .mode = 0644, | 114 | .mode = 0644, |
89 | .proc_handler = proc_dointvec_minmax, | 115 | .proc_handler = proc_dointvec_minmax, |
@@ -91,17 +117,22 @@ static ctl_table sctp_table[] = { | |||
91 | .extra2 = &timer_max | 117 | .extra2 = &timer_max |
92 | }, | 118 | }, |
93 | { | 119 | { |
94 | .procname = "valid_cookie_life", | 120 | .procname = "rto_alpha_exp_divisor", |
95 | .data = &sctp_valid_cookie_life, | 121 | .data = &init_net.sctp.rto_alpha, |
96 | .maxlen = sizeof(unsigned int), | 122 | .maxlen = sizeof(int), |
97 | .mode = 0644, | 123 | .mode = 0444, |
98 | .proc_handler = proc_dointvec_minmax, | 124 | .proc_handler = proc_dointvec, |
99 | .extra1 = &one, | 125 | }, |
100 | .extra2 = &timer_max | 126 | { |
127 | .procname = "rto_beta_exp_divisor", | ||
128 | .data = &init_net.sctp.rto_beta, | ||
129 | .maxlen = sizeof(int), | ||
130 | .mode = 0444, | ||
131 | .proc_handler = proc_dointvec, | ||
101 | }, | 132 | }, |
102 | { | 133 | { |
103 | .procname = "max_burst", | 134 | .procname = "max_burst", |
104 | .data = &sctp_max_burst, | 135 | .data = &init_net.sctp.max_burst, |
105 | .maxlen = sizeof(int), | 136 | .maxlen = sizeof(int), |
106 | .mode = 0644, | 137 | .mode = 0644, |
107 | .proc_handler = proc_dointvec_minmax, | 138 | .proc_handler = proc_dointvec_minmax, |
@@ -109,31 +140,42 @@ static ctl_table sctp_table[] = { | |||
109 | .extra2 = &int_max | 140 | .extra2 = &int_max |
110 | }, | 141 | }, |
111 | { | 142 | { |
112 | .procname = "association_max_retrans", | 143 | .procname = "cookie_preserve_enable", |
113 | .data = &sctp_max_retrans_association, | 144 | .data = &init_net.sctp.cookie_preserve_enable, |
114 | .maxlen = sizeof(int), | 145 | .maxlen = sizeof(int), |
115 | .mode = 0644, | 146 | .mode = 0644, |
147 | .proc_handler = proc_dointvec, | ||
148 | }, | ||
149 | { | ||
150 | .procname = "valid_cookie_life", | ||
151 | .data = &init_net.sctp.valid_cookie_life, | ||
152 | .maxlen = sizeof(unsigned int), | ||
153 | .mode = 0644, | ||
116 | .proc_handler = proc_dointvec_minmax, | 154 | .proc_handler = proc_dointvec_minmax, |
117 | .extra1 = &one, | 155 | .extra1 = &one, |
118 | .extra2 = &int_max | 156 | .extra2 = &timer_max |
119 | }, | 157 | }, |
120 | { | 158 | { |
121 | .procname = "sndbuf_policy", | 159 | .procname = "sack_timeout", |
122 | .data = &sctp_sndbuf_policy, | 160 | .data = &init_net.sctp.sack_timeout, |
123 | .maxlen = sizeof(int), | 161 | .maxlen = sizeof(int), |
124 | .mode = 0644, | 162 | .mode = 0644, |
125 | .proc_handler = proc_dointvec, | 163 | .proc_handler = proc_dointvec_minmax, |
164 | .extra1 = &sack_timer_min, | ||
165 | .extra2 = &sack_timer_max, | ||
126 | }, | 166 | }, |
127 | { | 167 | { |
128 | .procname = "rcvbuf_policy", | 168 | .procname = "hb_interval", |
129 | .data = &sctp_rcvbuf_policy, | 169 | .data = &init_net.sctp.hb_interval, |
130 | .maxlen = sizeof(int), | 170 | .maxlen = sizeof(unsigned int), |
131 | .mode = 0644, | 171 | .mode = 0644, |
132 | .proc_handler = proc_dointvec, | 172 | .proc_handler = proc_dointvec_minmax, |
173 | .extra1 = &one, | ||
174 | .extra2 = &timer_max | ||
133 | }, | 175 | }, |
134 | { | 176 | { |
135 | .procname = "path_max_retrans", | 177 | .procname = "association_max_retrans", |
136 | .data = &sctp_max_retrans_path, | 178 | .data = &init_net.sctp.max_retrans_association, |
137 | .maxlen = sizeof(int), | 179 | .maxlen = sizeof(int), |
138 | .mode = 0644, | 180 | .mode = 0644, |
139 | .proc_handler = proc_dointvec_minmax, | 181 | .proc_handler = proc_dointvec_minmax, |
@@ -141,17 +183,17 @@ static ctl_table sctp_table[] = { | |||
141 | .extra2 = &int_max | 183 | .extra2 = &int_max |
142 | }, | 184 | }, |
143 | { | 185 | { |
144 | .procname = "pf_retrans", | 186 | .procname = "path_max_retrans", |
145 | .data = &sctp_pf_retrans, | 187 | .data = &init_net.sctp.max_retrans_path, |
146 | .maxlen = sizeof(int), | 188 | .maxlen = sizeof(int), |
147 | .mode = 0644, | 189 | .mode = 0644, |
148 | .proc_handler = proc_dointvec_minmax, | 190 | .proc_handler = proc_dointvec_minmax, |
149 | .extra1 = &zero, | 191 | .extra1 = &one, |
150 | .extra2 = &int_max | 192 | .extra2 = &int_max |
151 | }, | 193 | }, |
152 | { | 194 | { |
153 | .procname = "max_init_retransmits", | 195 | .procname = "max_init_retransmits", |
154 | .data = &sctp_max_retrans_init, | 196 | .data = &init_net.sctp.max_retrans_init, |
155 | .maxlen = sizeof(int), | 197 | .maxlen = sizeof(int), |
156 | .mode = 0644, | 198 | .mode = 0644, |
157 | .proc_handler = proc_dointvec_minmax, | 199 | .proc_handler = proc_dointvec_minmax, |
@@ -159,103 +201,66 @@ static ctl_table sctp_table[] = { | |||
159 | .extra2 = &int_max | 201 | .extra2 = &int_max |
160 | }, | 202 | }, |
161 | { | 203 | { |
162 | .procname = "hb_interval", | 204 | .procname = "pf_retrans", |
163 | .data = &sctp_hb_interval, | 205 | .data = &init_net.sctp.pf_retrans, |
164 | .maxlen = sizeof(unsigned int), | 206 | .maxlen = sizeof(int), |
165 | .mode = 0644, | 207 | .mode = 0644, |
166 | .proc_handler = proc_dointvec_minmax, | 208 | .proc_handler = proc_dointvec_minmax, |
167 | .extra1 = &one, | 209 | .extra1 = &zero, |
168 | .extra2 = &timer_max | 210 | .extra2 = &int_max |
169 | }, | 211 | }, |
170 | { | 212 | { |
171 | .procname = "cookie_preserve_enable", | 213 | .procname = "sndbuf_policy", |
172 | .data = &sctp_cookie_preserve_enable, | 214 | .data = &init_net.sctp.sndbuf_policy, |
173 | .maxlen = sizeof(int), | 215 | .maxlen = sizeof(int), |
174 | .mode = 0644, | 216 | .mode = 0644, |
175 | .proc_handler = proc_dointvec, | 217 | .proc_handler = proc_dointvec, |
176 | }, | 218 | }, |
177 | { | 219 | { |
178 | .procname = "rto_alpha_exp_divisor", | 220 | .procname = "rcvbuf_policy", |
179 | .data = &sctp_rto_alpha, | 221 | .data = &init_net.sctp.rcvbuf_policy, |
180 | .maxlen = sizeof(int), | ||
181 | .mode = 0444, | ||
182 | .proc_handler = proc_dointvec, | ||
183 | }, | ||
184 | { | ||
185 | .procname = "rto_beta_exp_divisor", | ||
186 | .data = &sctp_rto_beta, | ||
187 | .maxlen = sizeof(int), | ||
188 | .mode = 0444, | ||
189 | .proc_handler = proc_dointvec, | ||
190 | }, | ||
191 | { | ||
192 | .procname = "addip_enable", | ||
193 | .data = &sctp_addip_enable, | ||
194 | .maxlen = sizeof(int), | 222 | .maxlen = sizeof(int), |
195 | .mode = 0644, | 223 | .mode = 0644, |
196 | .proc_handler = proc_dointvec, | 224 | .proc_handler = proc_dointvec, |
197 | }, | 225 | }, |
198 | { | 226 | { |
199 | .procname = "default_auto_asconf", | 227 | .procname = "default_auto_asconf", |
200 | .data = &sctp_default_auto_asconf, | 228 | .data = &init_net.sctp.default_auto_asconf, |
201 | .maxlen = sizeof(int), | 229 | .maxlen = sizeof(int), |
202 | .mode = 0644, | 230 | .mode = 0644, |
203 | .proc_handler = proc_dointvec, | 231 | .proc_handler = proc_dointvec, |
204 | }, | 232 | }, |
205 | { | 233 | { |
206 | .procname = "prsctp_enable", | 234 | .procname = "addip_enable", |
207 | .data = &sctp_prsctp_enable, | 235 | .data = &init_net.sctp.addip_enable, |
208 | .maxlen = sizeof(int), | 236 | .maxlen = sizeof(int), |
209 | .mode = 0644, | 237 | .mode = 0644, |
210 | .proc_handler = proc_dointvec, | 238 | .proc_handler = proc_dointvec, |
211 | }, | 239 | }, |
212 | { | 240 | { |
213 | .procname = "sack_timeout", | 241 | .procname = "addip_noauth_enable", |
214 | .data = &sctp_sack_timeout, | 242 | .data = &init_net.sctp.addip_noauth, |
215 | .maxlen = sizeof(int), | 243 | .maxlen = sizeof(int), |
216 | .mode = 0644, | 244 | .mode = 0644, |
217 | .proc_handler = proc_dointvec_minmax, | ||
218 | .extra1 = &sack_timer_min, | ||
219 | .extra2 = &sack_timer_max, | ||
220 | }, | ||
221 | { | ||
222 | .procname = "sctp_mem", | ||
223 | .data = &sysctl_sctp_mem, | ||
224 | .maxlen = sizeof(sysctl_sctp_mem), | ||
225 | .mode = 0644, | ||
226 | .proc_handler = proc_doulongvec_minmax | ||
227 | }, | ||
228 | { | ||
229 | .procname = "sctp_rmem", | ||
230 | .data = &sysctl_sctp_rmem, | ||
231 | .maxlen = sizeof(sysctl_sctp_rmem), | ||
232 | .mode = 0644, | ||
233 | .proc_handler = proc_dointvec, | ||
234 | }, | ||
235 | { | ||
236 | .procname = "sctp_wmem", | ||
237 | .data = &sysctl_sctp_wmem, | ||
238 | .maxlen = sizeof(sysctl_sctp_wmem), | ||
239 | .mode = 0644, | ||
240 | .proc_handler = proc_dointvec, | 245 | .proc_handler = proc_dointvec, |
241 | }, | 246 | }, |
242 | { | 247 | { |
243 | .procname = "auth_enable", | 248 | .procname = "prsctp_enable", |
244 | .data = &sctp_auth_enable, | 249 | .data = &init_net.sctp.prsctp_enable, |
245 | .maxlen = sizeof(int), | 250 | .maxlen = sizeof(int), |
246 | .mode = 0644, | 251 | .mode = 0644, |
247 | .proc_handler = proc_dointvec, | 252 | .proc_handler = proc_dointvec, |
248 | }, | 253 | }, |
249 | { | 254 | { |
250 | .procname = "addip_noauth_enable", | 255 | .procname = "auth_enable", |
251 | .data = &sctp_addip_noauth, | 256 | .data = &init_net.sctp.auth_enable, |
252 | .maxlen = sizeof(int), | 257 | .maxlen = sizeof(int), |
253 | .mode = 0644, | 258 | .mode = 0644, |
254 | .proc_handler = proc_dointvec, | 259 | .proc_handler = proc_dointvec, |
255 | }, | 260 | }, |
256 | { | 261 | { |
257 | .procname = "addr_scope_policy", | 262 | .procname = "addr_scope_policy", |
258 | .data = &sctp_scope_policy, | 263 | .data = &init_net.sctp.scope_policy, |
259 | .maxlen = sizeof(int), | 264 | .maxlen = sizeof(int), |
260 | .mode = 0644, | 265 | .mode = 0644, |
261 | .proc_handler = proc_dointvec_minmax, | 266 | .proc_handler = proc_dointvec_minmax, |
@@ -264,7 +269,7 @@ static ctl_table sctp_table[] = { | |||
264 | }, | 269 | }, |
265 | { | 270 | { |
266 | .procname = "rwnd_update_shift", | 271 | .procname = "rwnd_update_shift", |
267 | .data = &sctp_rwnd_upd_shift, | 272 | .data = &init_net.sctp.rwnd_upd_shift, |
268 | .maxlen = sizeof(int), | 273 | .maxlen = sizeof(int), |
269 | .mode = 0644, | 274 | .mode = 0644, |
270 | .proc_handler = &proc_dointvec_minmax, | 275 | .proc_handler = &proc_dointvec_minmax, |
@@ -273,7 +278,7 @@ static ctl_table sctp_table[] = { | |||
273 | }, | 278 | }, |
274 | { | 279 | { |
275 | .procname = "max_autoclose", | 280 | .procname = "max_autoclose", |
276 | .data = &sctp_max_autoclose, | 281 | .data = &init_net.sctp.max_autoclose, |
277 | .maxlen = sizeof(unsigned long), | 282 | .maxlen = sizeof(unsigned long), |
278 | .mode = 0644, | 283 | .mode = 0644, |
279 | .proc_handler = &proc_doulongvec_minmax, | 284 | .proc_handler = &proc_doulongvec_minmax, |
@@ -284,6 +289,27 @@ static ctl_table sctp_table[] = { | |||
284 | { /* sentinel */ } | 289 | { /* sentinel */ } |
285 | }; | 290 | }; |
286 | 291 | ||
292 | int sctp_sysctl_net_register(struct net *net) | ||
293 | { | ||
294 | struct ctl_table *table; | ||
295 | int i; | ||
296 | |||
297 | table = kmemdup(sctp_net_table, sizeof(sctp_net_table), GFP_KERNEL); | ||
298 | if (!table) | ||
299 | return -ENOMEM; | ||
300 | |||
301 | for (i = 0; table[i].data; i++) | ||
302 | table[i].data += (char *)(&net->sctp) - (char *)&init_net.sctp; | ||
303 | |||
304 | net->sctp.sysctl_header = register_net_sysctl(net, "net/sctp", table); | ||
305 | return 0; | ||
306 | } | ||
307 | |||
308 | void sctp_sysctl_net_unregister(struct net *net) | ||
309 | { | ||
310 | unregister_net_sysctl_table(net->sctp.sysctl_header); | ||
311 | } | ||
312 | |||
287 | static struct ctl_table_header * sctp_sysctl_header; | 313 | static struct ctl_table_header * sctp_sysctl_header; |
288 | 314 | ||
289 | /* Sysctl registration. */ | 315 | /* Sysctl registration. */ |
diff --git a/net/sctp/transport.c b/net/sctp/transport.c index c97472b248a2..953c21e4af97 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c | |||
@@ -59,7 +59,8 @@ | |||
59 | /* 1st Level Abstractions. */ | 59 | /* 1st Level Abstractions. */ |
60 | 60 | ||
61 | /* Initialize a new transport from provided memory. */ | 61 | /* Initialize a new transport from provided memory. */ |
62 | static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, | 62 | static struct sctp_transport *sctp_transport_init(struct net *net, |
63 | struct sctp_transport *peer, | ||
63 | const union sctp_addr *addr, | 64 | const union sctp_addr *addr, |
64 | gfp_t gfp) | 65 | gfp_t gfp) |
65 | { | 66 | { |
@@ -76,7 +77,7 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, | |||
76 | * given destination transport address, set RTO to the protocol | 77 | * given destination transport address, set RTO to the protocol |
77 | * parameter 'RTO.Initial'. | 78 | * parameter 'RTO.Initial'. |
78 | */ | 79 | */ |
79 | peer->rto = msecs_to_jiffies(sctp_rto_initial); | 80 | peer->rto = msecs_to_jiffies(net->sctp.rto_initial); |
80 | 81 | ||
81 | peer->last_time_heard = jiffies; | 82 | peer->last_time_heard = jiffies; |
82 | peer->last_time_ecne_reduced = jiffies; | 83 | peer->last_time_ecne_reduced = jiffies; |
@@ -86,8 +87,8 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, | |||
86 | SPP_SACKDELAY_ENABLE; | 87 | SPP_SACKDELAY_ENABLE; |
87 | 88 | ||
88 | /* Initialize the default path max_retrans. */ | 89 | /* Initialize the default path max_retrans. */ |
89 | peer->pathmaxrxt = sctp_max_retrans_path; | 90 | peer->pathmaxrxt = net->sctp.max_retrans_path; |
90 | peer->pf_retrans = sctp_pf_retrans; | 91 | peer->pf_retrans = net->sctp.pf_retrans; |
91 | 92 | ||
92 | INIT_LIST_HEAD(&peer->transmitted); | 93 | INIT_LIST_HEAD(&peer->transmitted); |
93 | INIT_LIST_HEAD(&peer->send_ready); | 94 | INIT_LIST_HEAD(&peer->send_ready); |
@@ -109,7 +110,8 @@ static struct sctp_transport *sctp_transport_init(struct sctp_transport *peer, | |||
109 | } | 110 | } |
110 | 111 | ||
111 | /* Allocate and initialize a new transport. */ | 112 | /* Allocate and initialize a new transport. */ |
112 | struct sctp_transport *sctp_transport_new(const union sctp_addr *addr, | 113 | struct sctp_transport *sctp_transport_new(struct net *net, |
114 | const union sctp_addr *addr, | ||
113 | gfp_t gfp) | 115 | gfp_t gfp) |
114 | { | 116 | { |
115 | struct sctp_transport *transport; | 117 | struct sctp_transport *transport; |
@@ -118,7 +120,7 @@ struct sctp_transport *sctp_transport_new(const union sctp_addr *addr, | |||
118 | if (!transport) | 120 | if (!transport) |
119 | goto fail; | 121 | goto fail; |
120 | 122 | ||
121 | if (!sctp_transport_init(transport, addr, gfp)) | 123 | if (!sctp_transport_init(net, transport, addr, gfp)) |
122 | goto fail_init; | 124 | goto fail_init; |
123 | 125 | ||
124 | transport->malloced = 1; | 126 | transport->malloced = 1; |
@@ -316,6 +318,7 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt) | |||
316 | SCTP_ASSERT(tp->rto_pending, "rto_pending not set", return); | 318 | SCTP_ASSERT(tp->rto_pending, "rto_pending not set", return); |
317 | 319 | ||
318 | if (tp->rttvar || tp->srtt) { | 320 | if (tp->rttvar || tp->srtt) { |
321 | struct net *net = sock_net(tp->asoc->base.sk); | ||
319 | /* 6.3.1 C3) When a new RTT measurement R' is made, set | 322 | /* 6.3.1 C3) When a new RTT measurement R' is made, set |
320 | * RTTVAR <- (1 - RTO.Beta) * RTTVAR + RTO.Beta * |SRTT - R'| | 323 | * RTTVAR <- (1 - RTO.Beta) * RTTVAR + RTO.Beta * |SRTT - R'| |
321 | * SRTT <- (1 - RTO.Alpha) * SRTT + RTO.Alpha * R' | 324 | * SRTT <- (1 - RTO.Alpha) * SRTT + RTO.Alpha * R' |
@@ -327,10 +330,10 @@ void sctp_transport_update_rto(struct sctp_transport *tp, __u32 rtt) | |||
327 | * For example, assuming the default value of RTO.Alpha of | 330 | * For example, assuming the default value of RTO.Alpha of |
328 | * 1/8, rto_alpha would be expressed as 3. | 331 | * 1/8, rto_alpha would be expressed as 3. |
329 | */ | 332 | */ |
330 | tp->rttvar = tp->rttvar - (tp->rttvar >> sctp_rto_beta) | 333 | tp->rttvar = tp->rttvar - (tp->rttvar >> net->sctp.rto_beta) |
331 | + ((abs(tp->srtt - rtt)) >> sctp_rto_beta); | 334 | + ((abs(tp->srtt - rtt)) >> net->sctp.rto_beta); |
332 | tp->srtt = tp->srtt - (tp->srtt >> sctp_rto_alpha) | 335 | tp->srtt = tp->srtt - (tp->srtt >> net->sctp.rto_alpha) |
333 | + (rtt >> sctp_rto_alpha); | 336 | + (rtt >> net->sctp.rto_alpha); |
334 | } else { | 337 | } else { |
335 | /* 6.3.1 C2) When the first RTT measurement R is made, set | 338 | /* 6.3.1 C2) When the first RTT measurement R is made, set |
336 | * SRTT <- R, RTTVAR <- R/2. | 339 | * SRTT <- R, RTTVAR <- R/2. |
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index f5a6a4f4faf7..360d8697b95c 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c | |||
@@ -326,7 +326,9 @@ static void sctp_ulpq_store_reasm(struct sctp_ulpq *ulpq, | |||
326 | * payload was fragmented on the way and ip had to reassemble them. | 326 | * payload was fragmented on the way and ip had to reassemble them. |
327 | * We add the rest of skb's to the first skb's fraglist. | 327 | * We add the rest of skb's to the first skb's fraglist. |
328 | */ | 328 | */ |
329 | static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff_head *queue, struct sk_buff *f_frag, struct sk_buff *l_frag) | 329 | static struct sctp_ulpevent *sctp_make_reassembled_event(struct net *net, |
330 | struct sk_buff_head *queue, struct sk_buff *f_frag, | ||
331 | struct sk_buff *l_frag) | ||
330 | { | 332 | { |
331 | struct sk_buff *pos; | 333 | struct sk_buff *pos; |
332 | struct sk_buff *new = NULL; | 334 | struct sk_buff *new = NULL; |
@@ -394,7 +396,7 @@ static struct sctp_ulpevent *sctp_make_reassembled_event(struct sk_buff_head *qu | |||
394 | } | 396 | } |
395 | 397 | ||
396 | event = sctp_skb2event(f_frag); | 398 | event = sctp_skb2event(f_frag); |
397 | SCTP_INC_STATS(SCTP_MIB_REASMUSRMSGS); | 399 | SCTP_INC_STATS(net, SCTP_MIB_REASMUSRMSGS); |
398 | 400 | ||
399 | return event; | 401 | return event; |
400 | } | 402 | } |
@@ -493,7 +495,8 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_reassembled(struct sctp_ulpq *ul | |||
493 | cevent = sctp_skb2event(pd_first); | 495 | cevent = sctp_skb2event(pd_first); |
494 | pd_point = sctp_sk(asoc->base.sk)->pd_point; | 496 | pd_point = sctp_sk(asoc->base.sk)->pd_point; |
495 | if (pd_point && pd_point <= pd_len) { | 497 | if (pd_point && pd_point <= pd_len) { |
496 | retval = sctp_make_reassembled_event(&ulpq->reasm, | 498 | retval = sctp_make_reassembled_event(sock_net(asoc->base.sk), |
499 | &ulpq->reasm, | ||
497 | pd_first, | 500 | pd_first, |
498 | pd_last); | 501 | pd_last); |
499 | if (retval) | 502 | if (retval) |
@@ -503,7 +506,8 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_reassembled(struct sctp_ulpq *ul | |||
503 | done: | 506 | done: |
504 | return retval; | 507 | return retval; |
505 | found: | 508 | found: |
506 | retval = sctp_make_reassembled_event(&ulpq->reasm, first_frag, pos); | 509 | retval = sctp_make_reassembled_event(sock_net(ulpq->asoc->base.sk), |
510 | &ulpq->reasm, first_frag, pos); | ||
507 | if (retval) | 511 | if (retval) |
508 | retval->msg_flags |= MSG_EOR; | 512 | retval->msg_flags |= MSG_EOR; |
509 | goto done; | 513 | goto done; |
@@ -563,7 +567,8 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_partial(struct sctp_ulpq *ulpq) | |||
563 | * further. | 567 | * further. |
564 | */ | 568 | */ |
565 | done: | 569 | done: |
566 | retval = sctp_make_reassembled_event(&ulpq->reasm, first_frag, last_frag); | 570 | retval = sctp_make_reassembled_event(sock_net(ulpq->asoc->base.sk), |
571 | &ulpq->reasm, first_frag, last_frag); | ||
567 | if (retval && is_last) | 572 | if (retval && is_last) |
568 | retval->msg_flags |= MSG_EOR; | 573 | retval->msg_flags |= MSG_EOR; |
569 | 574 | ||
@@ -655,7 +660,8 @@ static struct sctp_ulpevent *sctp_ulpq_retrieve_first(struct sctp_ulpq *ulpq) | |||
655 | * further. | 660 | * further. |
656 | */ | 661 | */ |
657 | done: | 662 | done: |
658 | retval = sctp_make_reassembled_event(&ulpq->reasm, first_frag, last_frag); | 663 | retval = sctp_make_reassembled_event(sock_net(ulpq->asoc->base.sk), |
664 | &ulpq->reasm, first_frag, last_frag); | ||
659 | return retval; | 665 | return retval; |
660 | } | 666 | } |
661 | 667 | ||
diff --git a/net/socket.c b/net/socket.c index dfe5b66c97e0..a5471f804d99 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -2657,6 +2657,7 @@ static int dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32) | |||
2657 | if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf))) | 2657 | if (copy_from_user(&ifc32, uifc32, sizeof(struct compat_ifconf))) |
2658 | return -EFAULT; | 2658 | return -EFAULT; |
2659 | 2659 | ||
2660 | memset(&ifc, 0, sizeof(ifc)); | ||
2660 | if (ifc32.ifcbuf == 0) { | 2661 | if (ifc32.ifcbuf == 0) { |
2661 | ifc32.ifc_len = 0; | 2662 | ifc32.ifc_len = 0; |
2662 | ifc.ifc_len = 0; | 2663 | ifc.ifc_len = 0; |
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 09e71241265d..4ec5c80e8a7c 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c | |||
@@ -49,21 +49,6 @@ struct tipc_bearer tipc_bearers[MAX_BEARERS]; | |||
49 | static void bearer_disable(struct tipc_bearer *b_ptr); | 49 | static void bearer_disable(struct tipc_bearer *b_ptr); |
50 | 50 | ||
51 | /** | 51 | /** |
52 | * media_name_valid - validate media name | ||
53 | * | ||
54 | * Returns 1 if media name is valid, otherwise 0. | ||
55 | */ | ||
56 | static int media_name_valid(const char *name) | ||
57 | { | ||
58 | u32 len; | ||
59 | |||
60 | len = strlen(name); | ||
61 | if ((len + 1) > TIPC_MAX_MEDIA_NAME) | ||
62 | return 0; | ||
63 | return strspn(name, tipc_alphabet) == len; | ||
64 | } | ||
65 | |||
66 | /** | ||
67 | * tipc_media_find - locates specified media object by name | 52 | * tipc_media_find - locates specified media object by name |
68 | */ | 53 | */ |
69 | struct tipc_media *tipc_media_find(const char *name) | 54 | struct tipc_media *tipc_media_find(const char *name) |
@@ -102,7 +87,7 @@ int tipc_register_media(struct tipc_media *m_ptr) | |||
102 | 87 | ||
103 | write_lock_bh(&tipc_net_lock); | 88 | write_lock_bh(&tipc_net_lock); |
104 | 89 | ||
105 | if (!media_name_valid(m_ptr->name)) | 90 | if ((strlen(m_ptr->name) + 1) > TIPC_MAX_MEDIA_NAME) |
106 | goto exit; | 91 | goto exit; |
107 | if ((m_ptr->bcast_addr.media_id != m_ptr->type_id) || | 92 | if ((m_ptr->bcast_addr.media_id != m_ptr->type_id) || |
108 | !m_ptr->bcast_addr.broadcast) | 93 | !m_ptr->bcast_addr.broadcast) |
@@ -206,9 +191,7 @@ static int bearer_name_validate(const char *name, | |||
206 | 191 | ||
207 | /* validate component parts of bearer name */ | 192 | /* validate component parts of bearer name */ |
208 | if ((media_len <= 1) || (media_len > TIPC_MAX_MEDIA_NAME) || | 193 | if ((media_len <= 1) || (media_len > TIPC_MAX_MEDIA_NAME) || |
209 | (if_len <= 1) || (if_len > TIPC_MAX_IF_NAME) || | 194 | (if_len <= 1) || (if_len > TIPC_MAX_IF_NAME)) |
210 | (strspn(media_name, tipc_alphabet) != (media_len - 1)) || | ||
211 | (strspn(if_name, tipc_alphabet) != (if_len - 1))) | ||
212 | return 0; | 195 | return 0; |
213 | 196 | ||
214 | /* return bearer name components, if necessary */ | 197 | /* return bearer name components, if necessary */ |
diff --git a/net/tipc/config.c b/net/tipc/config.c index a056a3852f71..f67866c765dd 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c | |||
@@ -2,7 +2,7 @@ | |||
2 | * net/tipc/config.c: TIPC configuration management code | 2 | * net/tipc/config.c: TIPC configuration management code |
3 | * | 3 | * |
4 | * Copyright (c) 2002-2006, Ericsson AB | 4 | * Copyright (c) 2002-2006, Ericsson AB |
5 | * Copyright (c) 2004-2007, 2010-2011, Wind River Systems | 5 | * Copyright (c) 2004-2007, 2010-2012, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
@@ -208,36 +208,6 @@ static struct sk_buff *cfg_set_remote_mng(void) | |||
208 | return tipc_cfg_reply_none(); | 208 | return tipc_cfg_reply_none(); |
209 | } | 209 | } |
210 | 210 | ||
211 | static struct sk_buff *cfg_set_max_publications(void) | ||
212 | { | ||
213 | u32 value; | ||
214 | |||
215 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | ||
216 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
217 | |||
218 | value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); | ||
219 | if (value < 1 || value > 65535) | ||
220 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | ||
221 | " (max publications must be 1-65535)"); | ||
222 | tipc_max_publications = value; | ||
223 | return tipc_cfg_reply_none(); | ||
224 | } | ||
225 | |||
226 | static struct sk_buff *cfg_set_max_subscriptions(void) | ||
227 | { | ||
228 | u32 value; | ||
229 | |||
230 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | ||
231 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
232 | |||
233 | value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); | ||
234 | if (value < 1 || value > 65535) | ||
235 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | ||
236 | " (max subscriptions must be 1-65535"); | ||
237 | tipc_max_subscriptions = value; | ||
238 | return tipc_cfg_reply_none(); | ||
239 | } | ||
240 | |||
241 | static struct sk_buff *cfg_set_max_ports(void) | 211 | static struct sk_buff *cfg_set_max_ports(void) |
242 | { | 212 | { |
243 | u32 value; | 213 | u32 value; |
@@ -357,12 +327,6 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area | |||
357 | case TIPC_CMD_SET_MAX_PORTS: | 327 | case TIPC_CMD_SET_MAX_PORTS: |
358 | rep_tlv_buf = cfg_set_max_ports(); | 328 | rep_tlv_buf = cfg_set_max_ports(); |
359 | break; | 329 | break; |
360 | case TIPC_CMD_SET_MAX_PUBL: | ||
361 | rep_tlv_buf = cfg_set_max_publications(); | ||
362 | break; | ||
363 | case TIPC_CMD_SET_MAX_SUBSCR: | ||
364 | rep_tlv_buf = cfg_set_max_subscriptions(); | ||
365 | break; | ||
366 | case TIPC_CMD_SET_NETID: | 330 | case TIPC_CMD_SET_NETID: |
367 | rep_tlv_buf = cfg_set_netid(); | 331 | rep_tlv_buf = cfg_set_netid(); |
368 | break; | 332 | break; |
@@ -372,12 +336,6 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area | |||
372 | case TIPC_CMD_GET_MAX_PORTS: | 336 | case TIPC_CMD_GET_MAX_PORTS: |
373 | rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_ports); | 337 | rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_ports); |
374 | break; | 338 | break; |
375 | case TIPC_CMD_GET_MAX_PUBL: | ||
376 | rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_publications); | ||
377 | break; | ||
378 | case TIPC_CMD_GET_MAX_SUBSCR: | ||
379 | rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_subscriptions); | ||
380 | break; | ||
381 | case TIPC_CMD_GET_NETID: | 339 | case TIPC_CMD_GET_NETID: |
382 | rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_net_id); | 340 | rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_net_id); |
383 | break; | 341 | break; |
@@ -393,6 +351,10 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area | |||
393 | case TIPC_CMD_GET_MAX_CLUSTERS: | 351 | case TIPC_CMD_GET_MAX_CLUSTERS: |
394 | case TIPC_CMD_SET_MAX_NODES: | 352 | case TIPC_CMD_SET_MAX_NODES: |
395 | case TIPC_CMD_GET_MAX_NODES: | 353 | case TIPC_CMD_GET_MAX_NODES: |
354 | case TIPC_CMD_SET_MAX_SUBSCR: | ||
355 | case TIPC_CMD_GET_MAX_SUBSCR: | ||
356 | case TIPC_CMD_SET_MAX_PUBL: | ||
357 | case TIPC_CMD_GET_MAX_PUBL: | ||
396 | case TIPC_CMD_SET_LOG_SIZE: | 358 | case TIPC_CMD_SET_LOG_SIZE: |
397 | case TIPC_CMD_DUMP_LOG: | 359 | case TIPC_CMD_DUMP_LOG: |
398 | rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 360 | rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
diff --git a/net/tipc/core.c b/net/tipc/core.c index 6586eac6a50e..bfe8af88469a 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c | |||
@@ -48,18 +48,13 @@ | |||
48 | 48 | ||
49 | 49 | ||
50 | /* global variables used by multiple sub-systems within TIPC */ | 50 | /* global variables used by multiple sub-systems within TIPC */ |
51 | int tipc_random; | 51 | int tipc_random __read_mostly; |
52 | |||
53 | const char tipc_alphabet[] = | ||
54 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_."; | ||
55 | 52 | ||
56 | /* configurable TIPC parameters */ | 53 | /* configurable TIPC parameters */ |
57 | u32 tipc_own_addr; | 54 | u32 tipc_own_addr __read_mostly; |
58 | int tipc_max_ports; | 55 | int tipc_max_ports __read_mostly; |
59 | int tipc_max_subscriptions; | 56 | int tipc_net_id __read_mostly; |
60 | int tipc_max_publications; | 57 | int tipc_remote_management __read_mostly; |
61 | int tipc_net_id; | ||
62 | int tipc_remote_management; | ||
63 | 58 | ||
64 | 59 | ||
65 | /** | 60 | /** |
@@ -101,9 +96,8 @@ int tipc_core_start_net(unsigned long addr) | |||
101 | { | 96 | { |
102 | int res; | 97 | int res; |
103 | 98 | ||
104 | res = tipc_net_start(addr); | 99 | tipc_net_start(addr); |
105 | if (!res) | 100 | res = tipc_eth_media_start(); |
106 | res = tipc_eth_media_start(); | ||
107 | if (res) | 101 | if (res) |
108 | tipc_core_stop_net(); | 102 | tipc_core_stop_net(); |
109 | return res; | 103 | return res; |
@@ -160,8 +154,6 @@ static int __init tipc_init(void) | |||
160 | 154 | ||
161 | tipc_own_addr = 0; | 155 | tipc_own_addr = 0; |
162 | tipc_remote_management = 1; | 156 | tipc_remote_management = 1; |
163 | tipc_max_publications = 10000; | ||
164 | tipc_max_subscriptions = 2000; | ||
165 | tipc_max_ports = CONFIG_TIPC_PORTS; | 157 | tipc_max_ports = CONFIG_TIPC_PORTS; |
166 | tipc_net_id = 4711; | 158 | tipc_net_id = 4711; |
167 | 159 | ||
diff --git a/net/tipc/core.h b/net/tipc/core.h index fd42e106c185..0207db04179a 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h | |||
@@ -60,7 +60,9 @@ | |||
60 | 60 | ||
61 | #define TIPC_MOD_VER "2.0.0" | 61 | #define TIPC_MOD_VER "2.0.0" |
62 | 62 | ||
63 | #define ULTRA_STRING_MAX_LEN 32768 | 63 | #define ULTRA_STRING_MAX_LEN 32768 |
64 | #define TIPC_MAX_SUBSCRIPTIONS 65535 | ||
65 | #define TIPC_MAX_PUBLICATIONS 65535 | ||
64 | 66 | ||
65 | struct tipc_msg; /* msg.h */ | 67 | struct tipc_msg; /* msg.h */ |
66 | 68 | ||
@@ -74,19 +76,15 @@ int tipc_snprintf(char *buf, int len, const char *fmt, ...); | |||
74 | /* | 76 | /* |
75 | * Global configuration variables | 77 | * Global configuration variables |
76 | */ | 78 | */ |
77 | extern u32 tipc_own_addr; | 79 | extern u32 tipc_own_addr __read_mostly; |
78 | extern int tipc_max_ports; | 80 | extern int tipc_max_ports __read_mostly; |
79 | extern int tipc_max_subscriptions; | 81 | extern int tipc_net_id __read_mostly; |
80 | extern int tipc_max_publications; | 82 | extern int tipc_remote_management __read_mostly; |
81 | extern int tipc_net_id; | ||
82 | extern int tipc_remote_management; | ||
83 | 83 | ||
84 | /* | 84 | /* |
85 | * Other global variables | 85 | * Other global variables |
86 | */ | 86 | */ |
87 | extern int tipc_random; | 87 | extern int tipc_random __read_mostly; |
88 | extern const char tipc_alphabet[]; | ||
89 | |||
90 | 88 | ||
91 | /* | 89 | /* |
92 | * Routines available to privileged subsystems | 90 | * Routines available to privileged subsystems |
diff --git a/net/tipc/eth_media.c b/net/tipc/eth_media.c index 90ac9bfa7abb..2132c1ef2951 100644 --- a/net/tipc/eth_media.c +++ b/net/tipc/eth_media.c | |||
@@ -46,19 +46,30 @@ | |||
46 | * @bearer: ptr to associated "generic" bearer structure | 46 | * @bearer: ptr to associated "generic" bearer structure |
47 | * @dev: ptr to associated Ethernet network device | 47 | * @dev: ptr to associated Ethernet network device |
48 | * @tipc_packet_type: used in binding TIPC to Ethernet driver | 48 | * @tipc_packet_type: used in binding TIPC to Ethernet driver |
49 | * @setup: work item used when enabling bearer | ||
49 | * @cleanup: work item used when disabling bearer | 50 | * @cleanup: work item used when disabling bearer |
50 | */ | 51 | */ |
51 | struct eth_bearer { | 52 | struct eth_bearer { |
52 | struct tipc_bearer *bearer; | 53 | struct tipc_bearer *bearer; |
53 | struct net_device *dev; | 54 | struct net_device *dev; |
54 | struct packet_type tipc_packet_type; | 55 | struct packet_type tipc_packet_type; |
56 | struct work_struct setup; | ||
55 | struct work_struct cleanup; | 57 | struct work_struct cleanup; |
56 | }; | 58 | }; |
57 | 59 | ||
58 | static struct tipc_media eth_media_info; | 60 | static struct tipc_media eth_media_info; |
59 | static struct eth_bearer eth_bearers[MAX_ETH_BEARERS]; | 61 | static struct eth_bearer eth_bearers[MAX_ETH_BEARERS]; |
60 | static int eth_started; | 62 | static int eth_started; |
61 | static struct notifier_block notifier; | 63 | |
64 | static int recv_notification(struct notifier_block *nb, unsigned long evt, | ||
65 | void *dv); | ||
66 | /* | ||
67 | * Network device notifier info | ||
68 | */ | ||
69 | static struct notifier_block notifier = { | ||
70 | .notifier_call = recv_notification, | ||
71 | .priority = 0 | ||
72 | }; | ||
62 | 73 | ||
63 | /** | 74 | /** |
64 | * eth_media_addr_set - initialize Ethernet media address structure | 75 | * eth_media_addr_set - initialize Ethernet media address structure |
@@ -134,6 +145,17 @@ static int recv_msg(struct sk_buff *buf, struct net_device *dev, | |||
134 | } | 145 | } |
135 | 146 | ||
136 | /** | 147 | /** |
148 | * setup_bearer - setup association between Ethernet bearer and interface | ||
149 | */ | ||
150 | static void setup_bearer(struct work_struct *work) | ||
151 | { | ||
152 | struct eth_bearer *eb_ptr = | ||
153 | container_of(work, struct eth_bearer, setup); | ||
154 | |||
155 | dev_add_pack(&eb_ptr->tipc_packet_type); | ||
156 | } | ||
157 | |||
158 | /** | ||
137 | * enable_bearer - attach TIPC bearer to an Ethernet interface | 159 | * enable_bearer - attach TIPC bearer to an Ethernet interface |
138 | */ | 160 | */ |
139 | static int enable_bearer(struct tipc_bearer *tb_ptr) | 161 | static int enable_bearer(struct tipc_bearer *tb_ptr) |
@@ -173,7 +195,8 @@ static int enable_bearer(struct tipc_bearer *tb_ptr) | |||
173 | eb_ptr->tipc_packet_type.func = recv_msg; | 195 | eb_ptr->tipc_packet_type.func = recv_msg; |
174 | eb_ptr->tipc_packet_type.af_packet_priv = eb_ptr; | 196 | eb_ptr->tipc_packet_type.af_packet_priv = eb_ptr; |
175 | INIT_LIST_HEAD(&(eb_ptr->tipc_packet_type.list)); | 197 | INIT_LIST_HEAD(&(eb_ptr->tipc_packet_type.list)); |
176 | dev_add_pack(&eb_ptr->tipc_packet_type); | 198 | INIT_WORK(&eb_ptr->setup, setup_bearer); |
199 | schedule_work(&eb_ptr->setup); | ||
177 | 200 | ||
178 | /* Associate TIPC bearer with Ethernet bearer */ | 201 | /* Associate TIPC bearer with Ethernet bearer */ |
179 | eb_ptr->bearer = tb_ptr; | 202 | eb_ptr->bearer = tb_ptr; |
@@ -357,8 +380,6 @@ int tipc_eth_media_start(void) | |||
357 | if (res) | 380 | if (res) |
358 | return res; | 381 | return res; |
359 | 382 | ||
360 | notifier.notifier_call = &recv_notification; | ||
361 | notifier.priority = 0; | ||
362 | res = register_netdevice_notifier(¬ifier); | 383 | res = register_netdevice_notifier(¬ifier); |
363 | if (!res) | 384 | if (!res) |
364 | eth_started = 1; | 385 | eth_started = 1; |
diff --git a/net/tipc/handler.c b/net/tipc/handler.c index 7a52d3922f3c..111ff8300ae5 100644 --- a/net/tipc/handler.c +++ b/net/tipc/handler.c | |||
@@ -45,7 +45,7 @@ struct queue_item { | |||
45 | static struct kmem_cache *tipc_queue_item_cache; | 45 | static struct kmem_cache *tipc_queue_item_cache; |
46 | static struct list_head signal_queue_head; | 46 | static struct list_head signal_queue_head; |
47 | static DEFINE_SPINLOCK(qitem_lock); | 47 | static DEFINE_SPINLOCK(qitem_lock); |
48 | static int handler_enabled; | 48 | static int handler_enabled __read_mostly; |
49 | 49 | ||
50 | static void process_signal_queue(unsigned long dummy); | 50 | static void process_signal_queue(unsigned long dummy); |
51 | 51 | ||
diff --git a/net/tipc/link.c b/net/tipc/link.c index 1c1e6151875e..a79c755cb417 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
@@ -210,9 +210,7 @@ static int link_name_validate(const char *name, | |||
210 | (z_local > 255) || (c_local > 4095) || (n_local > 4095) || | 210 | (z_local > 255) || (c_local > 4095) || (n_local > 4095) || |
211 | (z_peer > 255) || (c_peer > 4095) || (n_peer > 4095) || | 211 | (z_peer > 255) || (c_peer > 4095) || (n_peer > 4095) || |
212 | (if_local_len <= 1) || (if_local_len > TIPC_MAX_IF_NAME) || | 212 | (if_local_len <= 1) || (if_local_len > TIPC_MAX_IF_NAME) || |
213 | (if_peer_len <= 1) || (if_peer_len > TIPC_MAX_IF_NAME) || | 213 | (if_peer_len <= 1) || (if_peer_len > TIPC_MAX_IF_NAME)) |
214 | (strspn(if_local, tipc_alphabet) != (if_local_len - 1)) || | ||
215 | (strspn(if_peer, tipc_alphabet) != (if_peer_len - 1))) | ||
216 | return 0; | 214 | return 0; |
217 | 215 | ||
218 | /* return link name components, if necessary */ | 216 | /* return link name components, if necessary */ |
diff --git a/net/tipc/name_table.c b/net/tipc/name_table.c index 360c478b0b53..98975e80bb51 100644 --- a/net/tipc/name_table.c +++ b/net/tipc/name_table.c | |||
@@ -41,7 +41,7 @@ | |||
41 | #include "subscr.h" | 41 | #include "subscr.h" |
42 | #include "port.h" | 42 | #include "port.h" |
43 | 43 | ||
44 | static int tipc_nametbl_size = 1024; /* must be a power of 2 */ | 44 | #define TIPC_NAMETBL_SIZE 1024 /* must be a power of 2 */ |
45 | 45 | ||
46 | /** | 46 | /** |
47 | * struct name_info - name sequence publication info | 47 | * struct name_info - name sequence publication info |
@@ -114,7 +114,7 @@ DEFINE_RWLOCK(tipc_nametbl_lock); | |||
114 | 114 | ||
115 | static int hash(int x) | 115 | static int hash(int x) |
116 | { | 116 | { |
117 | return x & (tipc_nametbl_size - 1); | 117 | return x & (TIPC_NAMETBL_SIZE - 1); |
118 | } | 118 | } |
119 | 119 | ||
120 | /** | 120 | /** |
@@ -667,9 +667,9 @@ struct publication *tipc_nametbl_publish(u32 type, u32 lower, u32 upper, | |||
667 | { | 667 | { |
668 | struct publication *publ; | 668 | struct publication *publ; |
669 | 669 | ||
670 | if (table.local_publ_count >= tipc_max_publications) { | 670 | if (table.local_publ_count >= TIPC_MAX_PUBLICATIONS) { |
671 | pr_warn("Publication failed, local publication limit reached (%u)\n", | 671 | pr_warn("Publication failed, local publication limit reached (%u)\n", |
672 | tipc_max_publications); | 672 | TIPC_MAX_PUBLICATIONS); |
673 | return NULL; | 673 | return NULL; |
674 | } | 674 | } |
675 | 675 | ||
@@ -871,7 +871,7 @@ static int nametbl_list(char *buf, int len, u32 depth_info, | |||
871 | ret += nametbl_header(buf, len, depth); | 871 | ret += nametbl_header(buf, len, depth); |
872 | lowbound = 0; | 872 | lowbound = 0; |
873 | upbound = ~0; | 873 | upbound = ~0; |
874 | for (i = 0; i < tipc_nametbl_size; i++) { | 874 | for (i = 0; i < TIPC_NAMETBL_SIZE; i++) { |
875 | seq_head = &table.types[i]; | 875 | seq_head = &table.types[i]; |
876 | hlist_for_each_entry(seq, seq_node, seq_head, ns_list) { | 876 | hlist_for_each_entry(seq, seq_node, seq_head, ns_list) { |
877 | ret += nameseq_list(seq, buf + ret, len - ret, | 877 | ret += nameseq_list(seq, buf + ret, len - ret, |
@@ -935,7 +935,7 @@ struct sk_buff *tipc_nametbl_get(const void *req_tlv_area, int req_tlv_space) | |||
935 | 935 | ||
936 | int tipc_nametbl_init(void) | 936 | int tipc_nametbl_init(void) |
937 | { | 937 | { |
938 | table.types = kcalloc(tipc_nametbl_size, sizeof(struct hlist_head), | 938 | table.types = kcalloc(TIPC_NAMETBL_SIZE, sizeof(struct hlist_head), |
939 | GFP_ATOMIC); | 939 | GFP_ATOMIC); |
940 | if (!table.types) | 940 | if (!table.types) |
941 | return -ENOMEM; | 941 | return -ENOMEM; |
@@ -953,7 +953,7 @@ void tipc_nametbl_stop(void) | |||
953 | 953 | ||
954 | /* Verify name table is empty, then release it */ | 954 | /* Verify name table is empty, then release it */ |
955 | write_lock_bh(&tipc_nametbl_lock); | 955 | write_lock_bh(&tipc_nametbl_lock); |
956 | for (i = 0; i < tipc_nametbl_size; i++) { | 956 | for (i = 0; i < TIPC_NAMETBL_SIZE; i++) { |
957 | if (hlist_empty(&table.types[i])) | 957 | if (hlist_empty(&table.types[i])) |
958 | continue; | 958 | continue; |
959 | pr_err("nametbl_stop(): orphaned hash chain detected\n"); | 959 | pr_err("nametbl_stop(): orphaned hash chain detected\n"); |
diff --git a/net/tipc/net.c b/net/tipc/net.c index 5b5cea259caf..7d305ecc09c2 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c | |||
@@ -171,7 +171,7 @@ void tipc_net_route_msg(struct sk_buff *buf) | |||
171 | tipc_link_send(buf, dnode, msg_link_selector(msg)); | 171 | tipc_link_send(buf, dnode, msg_link_selector(msg)); |
172 | } | 172 | } |
173 | 173 | ||
174 | int tipc_net_start(u32 addr) | 174 | void tipc_net_start(u32 addr) |
175 | { | 175 | { |
176 | char addr_string[16]; | 176 | char addr_string[16]; |
177 | 177 | ||
@@ -187,7 +187,6 @@ int tipc_net_start(u32 addr) | |||
187 | pr_info("Started in network mode\n"); | 187 | pr_info("Started in network mode\n"); |
188 | pr_info("Own node address %s, network identity %u\n", | 188 | pr_info("Own node address %s, network identity %u\n", |
189 | tipc_addr_string_fill(addr_string, tipc_own_addr), tipc_net_id); | 189 | tipc_addr_string_fill(addr_string, tipc_own_addr), tipc_net_id); |
190 | return 0; | ||
191 | } | 190 | } |
192 | 191 | ||
193 | void tipc_net_stop(void) | 192 | void tipc_net_stop(void) |
diff --git a/net/tipc/net.h b/net/tipc/net.h index 9eb4b9e220eb..079daadb3f72 100644 --- a/net/tipc/net.h +++ b/net/tipc/net.h | |||
@@ -41,7 +41,7 @@ extern rwlock_t tipc_net_lock; | |||
41 | 41 | ||
42 | void tipc_net_route_msg(struct sk_buff *buf); | 42 | void tipc_net_route_msg(struct sk_buff *buf); |
43 | 43 | ||
44 | int tipc_net_start(u32 addr); | 44 | void tipc_net_start(u32 addr); |
45 | void tipc_net_stop(void); | 45 | void tipc_net_stop(void); |
46 | 46 | ||
47 | #endif | 47 | #endif |
diff --git a/net/tipc/subscr.c b/net/tipc/subscr.c index 5ed5965eb0be..0f7d0d007e22 100644 --- a/net/tipc/subscr.c +++ b/net/tipc/subscr.c | |||
@@ -304,9 +304,9 @@ static struct tipc_subscription *subscr_subscribe(struct tipc_subscr *s, | |||
304 | } | 304 | } |
305 | 305 | ||
306 | /* Refuse subscription if global limit exceeded */ | 306 | /* Refuse subscription if global limit exceeded */ |
307 | if (atomic_read(&topsrv.subscription_count) >= tipc_max_subscriptions) { | 307 | if (atomic_read(&topsrv.subscription_count) >= TIPC_MAX_SUBSCRIPTIONS) { |
308 | pr_warn("Subscription rejected, limit reached (%u)\n", | 308 | pr_warn("Subscription rejected, limit reached (%u)\n", |
309 | tipc_max_subscriptions); | 309 | TIPC_MAX_SUBSCRIPTIONS); |
310 | subscr_terminate(subscriber); | 310 | subscr_terminate(subscriber); |
311 | return NULL; | 311 | return NULL; |
312 | } | 312 | } |
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index e4768c180da2..8a84ab64cafd 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
@@ -1450,7 +1450,7 @@ static int unix_dgram_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1450 | if (NULL == siocb->scm) | 1450 | if (NULL == siocb->scm) |
1451 | siocb->scm = &tmp_scm; | 1451 | siocb->scm = &tmp_scm; |
1452 | wait_for_unix_gc(); | 1452 | wait_for_unix_gc(); |
1453 | err = scm_send(sock, msg, siocb->scm); | 1453 | err = scm_send(sock, msg, siocb->scm, false); |
1454 | if (err < 0) | 1454 | if (err < 0) |
1455 | return err; | 1455 | return err; |
1456 | 1456 | ||
@@ -1619,7 +1619,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
1619 | if (NULL == siocb->scm) | 1619 | if (NULL == siocb->scm) |
1620 | siocb->scm = &tmp_scm; | 1620 | siocb->scm = &tmp_scm; |
1621 | wait_for_unix_gc(); | 1621 | wait_for_unix_gc(); |
1622 | err = scm_send(sock, msg, siocb->scm); | 1622 | err = scm_send(sock, msg, siocb->scm, false); |
1623 | if (err < 0) | 1623 | if (err < 0) |
1624 | return err; | 1624 | return err; |
1625 | 1625 | ||
@@ -2060,10 +2060,14 @@ static int unix_shutdown(struct socket *sock, int mode) | |||
2060 | struct sock *sk = sock->sk; | 2060 | struct sock *sk = sock->sk; |
2061 | struct sock *other; | 2061 | struct sock *other; |
2062 | 2062 | ||
2063 | mode = (mode+1)&(RCV_SHUTDOWN|SEND_SHUTDOWN); | 2063 | if (mode < SHUT_RD || mode > SHUT_RDWR) |
2064 | 2064 | return -EINVAL; | |
2065 | if (!mode) | 2065 | /* This maps: |
2066 | return 0; | 2066 | * SHUT_RD (0) -> RCV_SHUTDOWN (1) |
2067 | * SHUT_WR (1) -> SEND_SHUTDOWN (2) | ||
2068 | * SHUT_RDWR (2) -> SHUTDOWN_MASK (3) | ||
2069 | */ | ||
2070 | ++mode; | ||
2067 | 2071 | ||
2068 | unix_state_lock(sk); | 2072 | unix_state_lock(sk); |
2069 | sk->sk_shutdown |= mode; | 2073 | sk->sk_shutdown |= mode; |
diff --git a/net/wireless/chan.c b/net/wireless/chan.c index d355f67d0cdd..2f876b9ee344 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c | |||
@@ -105,7 +105,7 @@ cfg80211_get_chan_state(struct wireless_dev *wdev, | |||
105 | 105 | ||
106 | ASSERT_WDEV_LOCK(wdev); | 106 | ASSERT_WDEV_LOCK(wdev); |
107 | 107 | ||
108 | if (!netif_running(wdev->netdev)) | 108 | if (wdev->netdev && !netif_running(wdev->netdev)) |
109 | return; | 109 | return; |
110 | 110 | ||
111 | switch (wdev->iftype) { | 111 | switch (wdev->iftype) { |
@@ -143,6 +143,11 @@ cfg80211_get_chan_state(struct wireless_dev *wdev, | |||
143 | case NL80211_IFTYPE_WDS: | 143 | case NL80211_IFTYPE_WDS: |
144 | /* these interface types don't really have a channel */ | 144 | /* these interface types don't really have a channel */ |
145 | return; | 145 | return; |
146 | case NL80211_IFTYPE_P2P_DEVICE: | ||
147 | if (wdev->wiphy->features & | ||
148 | NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL) | ||
149 | *chanmode = CHAN_MODE_EXCLUSIVE; | ||
150 | return; | ||
146 | case NL80211_IFTYPE_UNSPECIFIED: | 151 | case NL80211_IFTYPE_UNSPECIFIED: |
147 | case NUM_NL80211_IFTYPES: | 152 | case NUM_NL80211_IFTYPES: |
148 | WARN_ON(1); | 153 | WARN_ON(1); |
diff --git a/net/wireless/core.c b/net/wireless/core.c index 31b40cc4a9c3..443d4d7deea2 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -230,9 +230,24 @@ static int cfg80211_rfkill_set_block(void *data, bool blocked) | |||
230 | rtnl_lock(); | 230 | rtnl_lock(); |
231 | mutex_lock(&rdev->devlist_mtx); | 231 | mutex_lock(&rdev->devlist_mtx); |
232 | 232 | ||
233 | list_for_each_entry(wdev, &rdev->wdev_list, list) | 233 | list_for_each_entry(wdev, &rdev->wdev_list, list) { |
234 | if (wdev->netdev) | 234 | if (wdev->netdev) { |
235 | dev_close(wdev->netdev); | 235 | dev_close(wdev->netdev); |
236 | continue; | ||
237 | } | ||
238 | /* otherwise, check iftype */ | ||
239 | switch (wdev->iftype) { | ||
240 | case NL80211_IFTYPE_P2P_DEVICE: | ||
241 | if (!wdev->p2p_started) | ||
242 | break; | ||
243 | rdev->ops->stop_p2p_device(&rdev->wiphy, wdev); | ||
244 | wdev->p2p_started = false; | ||
245 | rdev->opencount--; | ||
246 | break; | ||
247 | default: | ||
248 | break; | ||
249 | } | ||
250 | } | ||
236 | 251 | ||
237 | mutex_unlock(&rdev->devlist_mtx); | 252 | mutex_unlock(&rdev->devlist_mtx); |
238 | rtnl_unlock(); | 253 | rtnl_unlock(); |
@@ -407,6 +422,11 @@ static int wiphy_verify_combinations(struct wiphy *wiphy) | |||
407 | if (WARN_ON(wiphy->software_iftypes & types)) | 422 | if (WARN_ON(wiphy->software_iftypes & types)) |
408 | return -EINVAL; | 423 | return -EINVAL; |
409 | 424 | ||
425 | /* Only a single P2P_DEVICE can be allowed */ | ||
426 | if (WARN_ON(types & BIT(NL80211_IFTYPE_P2P_DEVICE) && | ||
427 | c->limits[j].max > 1)) | ||
428 | return -EINVAL; | ||
429 | |||
410 | cnt += c->limits[j].max; | 430 | cnt += c->limits[j].max; |
411 | /* | 431 | /* |
412 | * Don't advertise an unsupported type | 432 | * Don't advertise an unsupported type |
@@ -734,6 +754,35 @@ static void wdev_cleanup_work(struct work_struct *work) | |||
734 | dev_put(wdev->netdev); | 754 | dev_put(wdev->netdev); |
735 | } | 755 | } |
736 | 756 | ||
757 | void cfg80211_unregister_wdev(struct wireless_dev *wdev) | ||
758 | { | ||
759 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | ||
760 | |||
761 | ASSERT_RTNL(); | ||
762 | |||
763 | if (WARN_ON(wdev->netdev)) | ||
764 | return; | ||
765 | |||
766 | mutex_lock(&rdev->devlist_mtx); | ||
767 | list_del_rcu(&wdev->list); | ||
768 | rdev->devlist_generation++; | ||
769 | |||
770 | switch (wdev->iftype) { | ||
771 | case NL80211_IFTYPE_P2P_DEVICE: | ||
772 | if (!wdev->p2p_started) | ||
773 | break; | ||
774 | rdev->ops->stop_p2p_device(&rdev->wiphy, wdev); | ||
775 | wdev->p2p_started = false; | ||
776 | rdev->opencount--; | ||
777 | break; | ||
778 | default: | ||
779 | WARN_ON_ONCE(1); | ||
780 | break; | ||
781 | } | ||
782 | mutex_unlock(&rdev->devlist_mtx); | ||
783 | } | ||
784 | EXPORT_SYMBOL(cfg80211_unregister_wdev); | ||
785 | |||
737 | static struct device_type wiphy_type = { | 786 | static struct device_type wiphy_type = { |
738 | .name = "wlan", | 787 | .name = "wlan", |
739 | }; | 788 | }; |
@@ -952,6 +1001,11 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | |||
952 | */ | 1001 | */ |
953 | synchronize_rcu(); | 1002 | synchronize_rcu(); |
954 | INIT_LIST_HEAD(&wdev->list); | 1003 | INIT_LIST_HEAD(&wdev->list); |
1004 | /* | ||
1005 | * Ensure that all events have been processed and | ||
1006 | * freed. | ||
1007 | */ | ||
1008 | cfg80211_process_wdev_events(wdev); | ||
955 | break; | 1009 | break; |
956 | case NETDEV_PRE_UP: | 1010 | case NETDEV_PRE_UP: |
957 | if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype))) | 1011 | if (!(wdev->wiphy->interface_modes & BIT(wdev->iftype))) |
diff --git a/net/wireless/core.h b/net/wireless/core.h index 5206c6844fd7..bc7430b54771 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -426,6 +426,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | |||
426 | struct net_device *dev, enum nl80211_iftype ntype, | 426 | struct net_device *dev, enum nl80211_iftype ntype, |
427 | u32 *flags, struct vif_params *params); | 427 | u32 *flags, struct vif_params *params); |
428 | void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev); | 428 | void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev); |
429 | void cfg80211_process_wdev_events(struct wireless_dev *wdev); | ||
429 | 430 | ||
430 | int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | 431 | int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, |
431 | struct wireless_dev *wdev, | 432 | struct wireless_dev *wdev, |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 1cdb1d5e6b0f..8fd0242ee169 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -736,7 +736,6 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, | |||
736 | const u8 *buf, size_t len, bool no_cck, | 736 | const u8 *buf, size_t len, bool no_cck, |
737 | bool dont_wait_for_ack, u64 *cookie) | 737 | bool dont_wait_for_ack, u64 *cookie) |
738 | { | 738 | { |
739 | struct net_device *dev = wdev->netdev; | ||
740 | const struct ieee80211_mgmt *mgmt; | 739 | const struct ieee80211_mgmt *mgmt; |
741 | u16 stype; | 740 | u16 stype; |
742 | 741 | ||
@@ -796,7 +795,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, | |||
796 | case NL80211_IFTYPE_AP: | 795 | case NL80211_IFTYPE_AP: |
797 | case NL80211_IFTYPE_P2P_GO: | 796 | case NL80211_IFTYPE_P2P_GO: |
798 | case NL80211_IFTYPE_AP_VLAN: | 797 | case NL80211_IFTYPE_AP_VLAN: |
799 | if (!ether_addr_equal(mgmt->bssid, dev->dev_addr)) | 798 | if (!ether_addr_equal(mgmt->bssid, wdev_address(wdev))) |
800 | err = -EINVAL; | 799 | err = -EINVAL; |
801 | break; | 800 | break; |
802 | case NL80211_IFTYPE_MESH_POINT: | 801 | case NL80211_IFTYPE_MESH_POINT: |
@@ -809,6 +808,11 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, | |||
809 | * cfg80211 doesn't track the stations | 808 | * cfg80211 doesn't track the stations |
810 | */ | 809 | */ |
811 | break; | 810 | break; |
811 | case NL80211_IFTYPE_P2P_DEVICE: | ||
812 | /* | ||
813 | * fall through, P2P device only supports | ||
814 | * public action frames | ||
815 | */ | ||
812 | default: | 816 | default: |
813 | err = -EOPNOTSUPP; | 817 | err = -EOPNOTSUPP; |
814 | break; | 818 | break; |
@@ -819,7 +823,7 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, | |||
819 | return err; | 823 | return err; |
820 | } | 824 | } |
821 | 825 | ||
822 | if (!ether_addr_equal(mgmt->sa, dev->dev_addr)) | 826 | if (!ether_addr_equal(mgmt->sa, wdev_address(wdev))) |
823 | return -EINVAL; | 827 | return -EINVAL; |
824 | 828 | ||
825 | /* Transmit the Action frame as requested by user space */ | 829 | /* Transmit the Action frame as requested by user space */ |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 97026f3b215a..787aeaa902fe 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -1100,6 +1100,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
1100 | if (nla_put_u32(msg, i, NL80211_CMD_REGISTER_BEACONS)) | 1100 | if (nla_put_u32(msg, i, NL80211_CMD_REGISTER_BEACONS)) |
1101 | goto nla_put_failure; | 1101 | goto nla_put_failure; |
1102 | } | 1102 | } |
1103 | CMD(start_p2p_device, START_P2P_DEVICE); | ||
1103 | 1104 | ||
1104 | #ifdef CONFIG_NL80211_TESTMODE | 1105 | #ifdef CONFIG_NL80211_TESTMODE |
1105 | CMD(testmode_cmd, TESTMODE); | 1106 | CMD(testmode_cmd, TESTMODE); |
@@ -1748,13 +1749,13 @@ static int nl80211_send_iface(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
1748 | 1749 | ||
1749 | if (dev && | 1750 | if (dev && |
1750 | (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || | 1751 | (nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) || |
1751 | nla_put_string(msg, NL80211_ATTR_IFNAME, dev->name) || | 1752 | nla_put_string(msg, NL80211_ATTR_IFNAME, dev->name))) |
1752 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, dev->dev_addr))) | ||
1753 | goto nla_put_failure; | 1753 | goto nla_put_failure; |
1754 | 1754 | ||
1755 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | 1755 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || |
1756 | nla_put_u32(msg, NL80211_ATTR_IFTYPE, wdev->iftype) || | 1756 | nla_put_u32(msg, NL80211_ATTR_IFTYPE, wdev->iftype) || |
1757 | nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) || | 1757 | nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) || |
1758 | nla_put(msg, NL80211_ATTR_MAC, ETH_ALEN, wdev_address(wdev)) || | ||
1758 | nla_put_u32(msg, NL80211_ATTR_GENERATION, | 1759 | nla_put_u32(msg, NL80211_ATTR_GENERATION, |
1759 | rdev->devlist_generation ^ | 1760 | rdev->devlist_generation ^ |
1760 | (cfg80211_rdev_list_generation << 2))) | 1761 | (cfg80211_rdev_list_generation << 2))) |
@@ -2021,8 +2022,10 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) | |||
2021 | return PTR_ERR(wdev); | 2022 | return PTR_ERR(wdev); |
2022 | } | 2023 | } |
2023 | 2024 | ||
2024 | if (type == NL80211_IFTYPE_MESH_POINT && | 2025 | switch (type) { |
2025 | info->attrs[NL80211_ATTR_MESH_ID]) { | 2026 | case NL80211_IFTYPE_MESH_POINT: |
2027 | if (!info->attrs[NL80211_ATTR_MESH_ID]) | ||
2028 | break; | ||
2026 | wdev_lock(wdev); | 2029 | wdev_lock(wdev); |
2027 | BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN != | 2030 | BUILD_BUG_ON(IEEE80211_MAX_SSID_LEN != |
2028 | IEEE80211_MAX_MESH_ID_LEN); | 2031 | IEEE80211_MAX_MESH_ID_LEN); |
@@ -2031,6 +2034,26 @@ static int nl80211_new_interface(struct sk_buff *skb, struct genl_info *info) | |||
2031 | memcpy(wdev->ssid, nla_data(info->attrs[NL80211_ATTR_MESH_ID]), | 2034 | memcpy(wdev->ssid, nla_data(info->attrs[NL80211_ATTR_MESH_ID]), |
2032 | wdev->mesh_id_up_len); | 2035 | wdev->mesh_id_up_len); |
2033 | wdev_unlock(wdev); | 2036 | wdev_unlock(wdev); |
2037 | break; | ||
2038 | case NL80211_IFTYPE_P2P_DEVICE: | ||
2039 | /* | ||
2040 | * P2P Device doesn't have a netdev, so doesn't go | ||
2041 | * through the netdev notifier and must be added here | ||
2042 | */ | ||
2043 | mutex_init(&wdev->mtx); | ||
2044 | INIT_LIST_HEAD(&wdev->event_list); | ||
2045 | spin_lock_init(&wdev->event_lock); | ||
2046 | INIT_LIST_HEAD(&wdev->mgmt_registrations); | ||
2047 | spin_lock_init(&wdev->mgmt_registrations_lock); | ||
2048 | |||
2049 | mutex_lock(&rdev->devlist_mtx); | ||
2050 | wdev->identifier = ++rdev->wdev_id; | ||
2051 | list_add_rcu(&wdev->list, &rdev->wdev_list); | ||
2052 | rdev->devlist_generation++; | ||
2053 | mutex_unlock(&rdev->devlist_mtx); | ||
2054 | break; | ||
2055 | default: | ||
2056 | break; | ||
2034 | } | 2057 | } |
2035 | 2058 | ||
2036 | if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0, | 2059 | if (nl80211_send_iface(msg, info->snd_pid, info->snd_seq, 0, |
@@ -6053,6 +6076,7 @@ static int nl80211_register_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
6053 | case NL80211_IFTYPE_AP_VLAN: | 6076 | case NL80211_IFTYPE_AP_VLAN: |
6054 | case NL80211_IFTYPE_MESH_POINT: | 6077 | case NL80211_IFTYPE_MESH_POINT: |
6055 | case NL80211_IFTYPE_P2P_GO: | 6078 | case NL80211_IFTYPE_P2P_GO: |
6079 | case NL80211_IFTYPE_P2P_DEVICE: | ||
6056 | break; | 6080 | break; |
6057 | default: | 6081 | default: |
6058 | return -EOPNOTSUPP; | 6082 | return -EOPNOTSUPP; |
@@ -6099,6 +6123,7 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
6099 | case NL80211_IFTYPE_AP_VLAN: | 6123 | case NL80211_IFTYPE_AP_VLAN: |
6100 | case NL80211_IFTYPE_MESH_POINT: | 6124 | case NL80211_IFTYPE_MESH_POINT: |
6101 | case NL80211_IFTYPE_P2P_GO: | 6125 | case NL80211_IFTYPE_P2P_GO: |
6126 | case NL80211_IFTYPE_P2P_DEVICE: | ||
6102 | break; | 6127 | break; |
6103 | default: | 6128 | default: |
6104 | return -EOPNOTSUPP; | 6129 | return -EOPNOTSUPP; |
@@ -6195,6 +6220,7 @@ static int nl80211_tx_mgmt_cancel_wait(struct sk_buff *skb, struct genl_info *in | |||
6195 | case NL80211_IFTYPE_AP: | 6220 | case NL80211_IFTYPE_AP: |
6196 | case NL80211_IFTYPE_AP_VLAN: | 6221 | case NL80211_IFTYPE_AP_VLAN: |
6197 | case NL80211_IFTYPE_P2P_GO: | 6222 | case NL80211_IFTYPE_P2P_GO: |
6223 | case NL80211_IFTYPE_P2P_DEVICE: | ||
6198 | break; | 6224 | break; |
6199 | default: | 6225 | default: |
6200 | return -EOPNOTSUPP; | 6226 | return -EOPNOTSUPP; |
@@ -6810,6 +6836,68 @@ static int nl80211_register_beacons(struct sk_buff *skb, struct genl_info *info) | |||
6810 | return 0; | 6836 | return 0; |
6811 | } | 6837 | } |
6812 | 6838 | ||
6839 | static int nl80211_start_p2p_device(struct sk_buff *skb, struct genl_info *info) | ||
6840 | { | ||
6841 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
6842 | struct wireless_dev *wdev = info->user_ptr[1]; | ||
6843 | int err; | ||
6844 | |||
6845 | if (!rdev->ops->start_p2p_device) | ||
6846 | return -EOPNOTSUPP; | ||
6847 | |||
6848 | if (wdev->iftype != NL80211_IFTYPE_P2P_DEVICE) | ||
6849 | return -EOPNOTSUPP; | ||
6850 | |||
6851 | if (wdev->p2p_started) | ||
6852 | return 0; | ||
6853 | |||
6854 | mutex_lock(&rdev->devlist_mtx); | ||
6855 | err = cfg80211_can_add_interface(rdev, wdev->iftype); | ||
6856 | mutex_unlock(&rdev->devlist_mtx); | ||
6857 | if (err) | ||
6858 | return err; | ||
6859 | |||
6860 | err = rdev->ops->start_p2p_device(&rdev->wiphy, wdev); | ||
6861 | if (err) | ||
6862 | return err; | ||
6863 | |||
6864 | wdev->p2p_started = true; | ||
6865 | mutex_lock(&rdev->devlist_mtx); | ||
6866 | rdev->opencount++; | ||
6867 | mutex_unlock(&rdev->devlist_mtx); | ||
6868 | |||
6869 | return 0; | ||
6870 | } | ||
6871 | |||
6872 | static int nl80211_stop_p2p_device(struct sk_buff *skb, struct genl_info *info) | ||
6873 | { | ||
6874 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
6875 | struct wireless_dev *wdev = info->user_ptr[1]; | ||
6876 | |||
6877 | if (wdev->iftype != NL80211_IFTYPE_P2P_DEVICE) | ||
6878 | return -EOPNOTSUPP; | ||
6879 | |||
6880 | if (!rdev->ops->stop_p2p_device) | ||
6881 | return -EOPNOTSUPP; | ||
6882 | |||
6883 | if (!wdev->p2p_started) | ||
6884 | return 0; | ||
6885 | |||
6886 | rdev->ops->stop_p2p_device(&rdev->wiphy, wdev); | ||
6887 | wdev->p2p_started = false; | ||
6888 | |||
6889 | mutex_lock(&rdev->devlist_mtx); | ||
6890 | rdev->opencount--; | ||
6891 | mutex_unlock(&rdev->devlist_mtx); | ||
6892 | |||
6893 | if (WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev)) { | ||
6894 | rdev->scan_req->aborted = true; | ||
6895 | ___cfg80211_scan_done(rdev, true); | ||
6896 | } | ||
6897 | |||
6898 | return 0; | ||
6899 | } | ||
6900 | |||
6813 | #define NL80211_FLAG_NEED_WIPHY 0x01 | 6901 | #define NL80211_FLAG_NEED_WIPHY 0x01 |
6814 | #define NL80211_FLAG_NEED_NETDEV 0x02 | 6902 | #define NL80211_FLAG_NEED_NETDEV 0x02 |
6815 | #define NL80211_FLAG_NEED_RTNL 0x04 | 6903 | #define NL80211_FLAG_NEED_RTNL 0x04 |
@@ -6817,7 +6905,7 @@ static int nl80211_register_beacons(struct sk_buff *skb, struct genl_info *info) | |||
6817 | #define NL80211_FLAG_NEED_NETDEV_UP (NL80211_FLAG_NEED_NETDEV |\ | 6905 | #define NL80211_FLAG_NEED_NETDEV_UP (NL80211_FLAG_NEED_NETDEV |\ |
6818 | NL80211_FLAG_CHECK_NETDEV_UP) | 6906 | NL80211_FLAG_CHECK_NETDEV_UP) |
6819 | #define NL80211_FLAG_NEED_WDEV 0x10 | 6907 | #define NL80211_FLAG_NEED_WDEV 0x10 |
6820 | /* If a netdev is associated, it must be UP */ | 6908 | /* If a netdev is associated, it must be UP, P2P must be started */ |
6821 | #define NL80211_FLAG_NEED_WDEV_UP (NL80211_FLAG_NEED_WDEV |\ | 6909 | #define NL80211_FLAG_NEED_WDEV_UP (NL80211_FLAG_NEED_WDEV |\ |
6822 | NL80211_FLAG_CHECK_NETDEV_UP) | 6910 | NL80211_FLAG_CHECK_NETDEV_UP) |
6823 | 6911 | ||
@@ -6878,6 +6966,13 @@ static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb, | |||
6878 | } | 6966 | } |
6879 | 6967 | ||
6880 | dev_hold(dev); | 6968 | dev_hold(dev); |
6969 | } else if (ops->internal_flags & NL80211_FLAG_CHECK_NETDEV_UP) { | ||
6970 | if (!wdev->p2p_started) { | ||
6971 | mutex_unlock(&cfg80211_mutex); | ||
6972 | if (rtnl) | ||
6973 | rtnl_unlock(); | ||
6974 | return -ENETDOWN; | ||
6975 | } | ||
6881 | } | 6976 | } |
6882 | 6977 | ||
6883 | cfg80211_lock_rdev(rdev); | 6978 | cfg80211_lock_rdev(rdev); |
@@ -7439,7 +7534,22 @@ static struct genl_ops nl80211_ops[] = { | |||
7439 | .internal_flags = NL80211_FLAG_NEED_NETDEV | | 7534 | .internal_flags = NL80211_FLAG_NEED_NETDEV | |
7440 | NL80211_FLAG_NEED_RTNL, | 7535 | NL80211_FLAG_NEED_RTNL, |
7441 | }, | 7536 | }, |
7442 | 7537 | { | |
7538 | .cmd = NL80211_CMD_START_P2P_DEVICE, | ||
7539 | .doit = nl80211_start_p2p_device, | ||
7540 | .policy = nl80211_policy, | ||
7541 | .flags = GENL_ADMIN_PERM, | ||
7542 | .internal_flags = NL80211_FLAG_NEED_WDEV | | ||
7543 | NL80211_FLAG_NEED_RTNL, | ||
7544 | }, | ||
7545 | { | ||
7546 | .cmd = NL80211_CMD_STOP_P2P_DEVICE, | ||
7547 | .doit = nl80211_stop_p2p_device, | ||
7548 | .policy = nl80211_policy, | ||
7549 | .flags = GENL_ADMIN_PERM, | ||
7550 | .internal_flags = NL80211_FLAG_NEED_WDEV_UP | | ||
7551 | NL80211_FLAG_NEED_RTNL, | ||
7552 | }, | ||
7443 | }; | 7553 | }; |
7444 | 7554 | ||
7445 | static struct genl_multicast_group nl80211_mlme_mcgrp = { | 7555 | static struct genl_multicast_group nl80211_mlme_mcgrp = { |
diff --git a/net/wireless/radiotap.c b/net/wireless/radiotap.c index c4ad7958af52..7d604c06c3dc 100644 --- a/net/wireless/radiotap.c +++ b/net/wireless/radiotap.c | |||
@@ -41,6 +41,8 @@ static const struct radiotap_align_size rtap_namespace_sizes[] = { | |||
41 | [IEEE80211_RADIOTAP_TX_FLAGS] = { .align = 2, .size = 2, }, | 41 | [IEEE80211_RADIOTAP_TX_FLAGS] = { .align = 2, .size = 2, }, |
42 | [IEEE80211_RADIOTAP_RTS_RETRIES] = { .align = 1, .size = 1, }, | 42 | [IEEE80211_RADIOTAP_RTS_RETRIES] = { .align = 1, .size = 1, }, |
43 | [IEEE80211_RADIOTAP_DATA_RETRIES] = { .align = 1, .size = 1, }, | 43 | [IEEE80211_RADIOTAP_DATA_RETRIES] = { .align = 1, .size = 1, }, |
44 | [IEEE80211_RADIOTAP_MCS] = { .align = 1, .size = 3, }, | ||
45 | [IEEE80211_RADIOTAP_AMPDU_STATUS] = { .align = 4, .size = 8, }, | ||
44 | /* | 46 | /* |
45 | * add more here as they are defined in radiotap.h | 47 | * add more here as they are defined in radiotap.h |
46 | */ | 48 | */ |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 2303ee73b50a..2ded3c7fad06 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
@@ -680,6 +680,8 @@ static u32 map_regdom_flags(u32 rd_flags) | |||
680 | channel_flags |= IEEE80211_CHAN_NO_IBSS; | 680 | channel_flags |= IEEE80211_CHAN_NO_IBSS; |
681 | if (rd_flags & NL80211_RRF_DFS) | 681 | if (rd_flags & NL80211_RRF_DFS) |
682 | channel_flags |= IEEE80211_CHAN_RADAR; | 682 | channel_flags |= IEEE80211_CHAN_RADAR; |
683 | if (rd_flags & NL80211_RRF_NO_OFDM) | ||
684 | channel_flags |= IEEE80211_CHAN_NO_OFDM; | ||
683 | return channel_flags; | 685 | return channel_flags; |
684 | } | 686 | } |
685 | 687 | ||
@@ -901,7 +903,21 @@ static void handle_channel(struct wiphy *wiphy, | |||
901 | chan->max_antenna_gain = min(chan->orig_mag, | 903 | chan->max_antenna_gain = min(chan->orig_mag, |
902 | (int) MBI_TO_DBI(power_rule->max_antenna_gain)); | 904 | (int) MBI_TO_DBI(power_rule->max_antenna_gain)); |
903 | chan->max_reg_power = (int) MBM_TO_DBM(power_rule->max_eirp); | 905 | chan->max_reg_power = (int) MBM_TO_DBM(power_rule->max_eirp); |
904 | chan->max_power = min(chan->max_power, chan->max_reg_power); | 906 | if (chan->orig_mpwr) { |
907 | /* | ||
908 | * Devices that have their own custom regulatory domain | ||
909 | * but also use WIPHY_FLAG_STRICT_REGULATORY will follow the | ||
910 | * passed country IE power settings. | ||
911 | */ | ||
912 | if (initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE && | ||
913 | wiphy->flags & WIPHY_FLAG_CUSTOM_REGULATORY && | ||
914 | wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) | ||
915 | chan->max_power = chan->max_reg_power; | ||
916 | else | ||
917 | chan->max_power = min(chan->orig_mpwr, | ||
918 | chan->max_reg_power); | ||
919 | } else | ||
920 | chan->max_power = chan->max_reg_power; | ||
905 | } | 921 | } |
906 | 922 | ||
907 | static void handle_band(struct wiphy *wiphy, | 923 | static void handle_band(struct wiphy *wiphy, |
@@ -1885,6 +1901,7 @@ static void restore_custom_reg_settings(struct wiphy *wiphy) | |||
1885 | chan->flags = chan->orig_flags; | 1901 | chan->flags = chan->orig_flags; |
1886 | chan->max_antenna_gain = chan->orig_mag; | 1902 | chan->max_antenna_gain = chan->orig_mag; |
1887 | chan->max_power = chan->orig_mpwr; | 1903 | chan->max_power = chan->orig_mpwr; |
1904 | chan->beacon_found = false; | ||
1888 | } | 1905 | } |
1889 | } | 1906 | } |
1890 | } | 1907 | } |
diff --git a/net/wireless/util.c b/net/wireless/util.c index 26f8cd30f712..ef35f4ef2aa6 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
@@ -684,22 +684,10 @@ EXPORT_SYMBOL(cfg80211_classify8021d); | |||
684 | 684 | ||
685 | const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie) | 685 | const u8 *ieee80211_bss_get_ie(struct cfg80211_bss *bss, u8 ie) |
686 | { | 686 | { |
687 | u8 *end, *pos; | 687 | if (bss->information_elements == NULL) |
688 | |||
689 | pos = bss->information_elements; | ||
690 | if (pos == NULL) | ||
691 | return NULL; | 688 | return NULL; |
692 | end = pos + bss->len_information_elements; | 689 | return cfg80211_find_ie(ie, bss->information_elements, |
693 | 690 | bss->len_information_elements); | |
694 | while (pos + 1 < end) { | ||
695 | if (pos + 2 + pos[1] > end) | ||
696 | break; | ||
697 | if (pos[0] == ie) | ||
698 | return pos; | ||
699 | pos += 2 + pos[1]; | ||
700 | } | ||
701 | |||
702 | return NULL; | ||
703 | } | 691 | } |
704 | EXPORT_SYMBOL(ieee80211_bss_get_ie); | 692 | EXPORT_SYMBOL(ieee80211_bss_get_ie); |
705 | 693 | ||
@@ -735,7 +723,7 @@ void cfg80211_upload_connect_keys(struct wireless_dev *wdev) | |||
735 | wdev->connect_keys = NULL; | 723 | wdev->connect_keys = NULL; |
736 | } | 724 | } |
737 | 725 | ||
738 | static void cfg80211_process_wdev_events(struct wireless_dev *wdev) | 726 | void cfg80211_process_wdev_events(struct wireless_dev *wdev) |
739 | { | 727 | { |
740 | struct cfg80211_event *ev; | 728 | struct cfg80211_event *ev; |
741 | unsigned long flags; | 729 | unsigned long flags; |
@@ -812,6 +800,10 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | |||
812 | if (otype == NL80211_IFTYPE_AP_VLAN) | 800 | if (otype == NL80211_IFTYPE_AP_VLAN) |
813 | return -EOPNOTSUPP; | 801 | return -EOPNOTSUPP; |
814 | 802 | ||
803 | /* cannot change into P2P device type */ | ||
804 | if (ntype == NL80211_IFTYPE_P2P_DEVICE) | ||
805 | return -EOPNOTSUPP; | ||
806 | |||
815 | if (!rdev->ops->change_virtual_intf || | 807 | if (!rdev->ops->change_virtual_intf || |
816 | !(rdev->wiphy.interface_modes & (1 << ntype))) | 808 | !(rdev->wiphy.interface_modes & (1 << ntype))) |
817 | return -EOPNOTSUPP; | 809 | return -EOPNOTSUPP; |
@@ -889,6 +881,9 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | |||
889 | case NUM_NL80211_IFTYPES: | 881 | case NUM_NL80211_IFTYPES: |
890 | /* not happening */ | 882 | /* not happening */ |
891 | break; | 883 | break; |
884 | case NL80211_IFTYPE_P2P_DEVICE: | ||
885 | WARN_ON(1); | ||
886 | break; | ||
892 | } | 887 | } |
893 | } | 888 | } |
894 | 889 | ||
@@ -1053,8 +1048,15 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | |||
1053 | list_for_each_entry(wdev_iter, &rdev->wdev_list, list) { | 1048 | list_for_each_entry(wdev_iter, &rdev->wdev_list, list) { |
1054 | if (wdev_iter == wdev) | 1049 | if (wdev_iter == wdev) |
1055 | continue; | 1050 | continue; |
1056 | if (!netif_running(wdev_iter->netdev)) | 1051 | if (wdev_iter->netdev) { |
1057 | continue; | 1052 | if (!netif_running(wdev_iter->netdev)) |
1053 | continue; | ||
1054 | } else if (wdev_iter->iftype == NL80211_IFTYPE_P2P_DEVICE) { | ||
1055 | if (!wdev_iter->p2p_started) | ||
1056 | continue; | ||
1057 | } else { | ||
1058 | WARN_ON(1); | ||
1059 | } | ||
1058 | 1060 | ||
1059 | if (rdev->wiphy.software_iftypes & BIT(wdev_iter->iftype)) | 1061 | if (rdev->wiphy.software_iftypes & BIT(wdev_iter->iftype)) |
1060 | continue; | 1062 | continue; |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index c5a5165a5927..741a32aa512e 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -42,13 +42,12 @@ static DEFINE_SPINLOCK(xfrm_policy_sk_bundle_lock); | |||
42 | static struct dst_entry *xfrm_policy_sk_bundles; | 42 | static struct dst_entry *xfrm_policy_sk_bundles; |
43 | static DEFINE_RWLOCK(xfrm_policy_lock); | 43 | static DEFINE_RWLOCK(xfrm_policy_lock); |
44 | 44 | ||
45 | static DEFINE_RWLOCK(xfrm_policy_afinfo_lock); | 45 | static DEFINE_SPINLOCK(xfrm_policy_afinfo_lock); |
46 | static struct xfrm_policy_afinfo *xfrm_policy_afinfo[NPROTO]; | 46 | static struct xfrm_policy_afinfo __rcu *xfrm_policy_afinfo[NPROTO] |
47 | __read_mostly; | ||
47 | 48 | ||
48 | static struct kmem_cache *xfrm_dst_cache __read_mostly; | 49 | static struct kmem_cache *xfrm_dst_cache __read_mostly; |
49 | 50 | ||
50 | static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family); | ||
51 | static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo); | ||
52 | static void xfrm_init_pmtu(struct dst_entry *dst); | 51 | static void xfrm_init_pmtu(struct dst_entry *dst); |
53 | static int stale_bundle(struct dst_entry *dst); | 52 | static int stale_bundle(struct dst_entry *dst); |
54 | static int xfrm_bundle_ok(struct xfrm_dst *xdst); | 53 | static int xfrm_bundle_ok(struct xfrm_dst *xdst); |
@@ -95,6 +94,24 @@ bool xfrm_selector_match(const struct xfrm_selector *sel, const struct flowi *fl | |||
95 | return false; | 94 | return false; |
96 | } | 95 | } |
97 | 96 | ||
97 | static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family) | ||
98 | { | ||
99 | struct xfrm_policy_afinfo *afinfo; | ||
100 | |||
101 | if (unlikely(family >= NPROTO)) | ||
102 | return NULL; | ||
103 | rcu_read_lock(); | ||
104 | afinfo = rcu_dereference(xfrm_policy_afinfo[family]); | ||
105 | if (unlikely(!afinfo)) | ||
106 | rcu_read_unlock(); | ||
107 | return afinfo; | ||
108 | } | ||
109 | |||
110 | static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo) | ||
111 | { | ||
112 | rcu_read_unlock(); | ||
113 | } | ||
114 | |||
98 | static inline struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos, | 115 | static inline struct dst_entry *__xfrm_dst_lookup(struct net *net, int tos, |
99 | const xfrm_address_t *saddr, | 116 | const xfrm_address_t *saddr, |
100 | const xfrm_address_t *daddr, | 117 | const xfrm_address_t *daddr, |
@@ -1357,6 +1374,8 @@ static inline struct xfrm_dst *xfrm_alloc_dst(struct net *net, int family) | |||
1357 | 1374 | ||
1358 | memset(dst + 1, 0, sizeof(*xdst) - sizeof(*dst)); | 1375 | memset(dst + 1, 0, sizeof(*xdst) - sizeof(*dst)); |
1359 | xdst->flo.ops = &xfrm_bundle_fc_ops; | 1376 | xdst->flo.ops = &xfrm_bundle_fc_ops; |
1377 | if (afinfo->init_dst) | ||
1378 | afinfo->init_dst(net, xdst); | ||
1360 | } else | 1379 | } else |
1361 | xdst = ERR_PTR(-ENOBUFS); | 1380 | xdst = ERR_PTR(-ENOBUFS); |
1362 | 1381 | ||
@@ -2418,7 +2437,7 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) | |||
2418 | return -EINVAL; | 2437 | return -EINVAL; |
2419 | if (unlikely(afinfo->family >= NPROTO)) | 2438 | if (unlikely(afinfo->family >= NPROTO)) |
2420 | return -EAFNOSUPPORT; | 2439 | return -EAFNOSUPPORT; |
2421 | write_lock_bh(&xfrm_policy_afinfo_lock); | 2440 | spin_lock(&xfrm_policy_afinfo_lock); |
2422 | if (unlikely(xfrm_policy_afinfo[afinfo->family] != NULL)) | 2441 | if (unlikely(xfrm_policy_afinfo[afinfo->family] != NULL)) |
2423 | err = -ENOBUFS; | 2442 | err = -ENOBUFS; |
2424 | else { | 2443 | else { |
@@ -2439,9 +2458,9 @@ int xfrm_policy_register_afinfo(struct xfrm_policy_afinfo *afinfo) | |||
2439 | dst_ops->neigh_lookup = xfrm_neigh_lookup; | 2458 | dst_ops->neigh_lookup = xfrm_neigh_lookup; |
2440 | if (likely(afinfo->garbage_collect == NULL)) | 2459 | if (likely(afinfo->garbage_collect == NULL)) |
2441 | afinfo->garbage_collect = xfrm_garbage_collect_deferred; | 2460 | afinfo->garbage_collect = xfrm_garbage_collect_deferred; |
2442 | xfrm_policy_afinfo[afinfo->family] = afinfo; | 2461 | rcu_assign_pointer(xfrm_policy_afinfo[afinfo->family], afinfo); |
2443 | } | 2462 | } |
2444 | write_unlock_bh(&xfrm_policy_afinfo_lock); | 2463 | spin_unlock(&xfrm_policy_afinfo_lock); |
2445 | 2464 | ||
2446 | rtnl_lock(); | 2465 | rtnl_lock(); |
2447 | for_each_net(net) { | 2466 | for_each_net(net) { |
@@ -2474,21 +2493,26 @@ int xfrm_policy_unregister_afinfo(struct xfrm_policy_afinfo *afinfo) | |||
2474 | return -EINVAL; | 2493 | return -EINVAL; |
2475 | if (unlikely(afinfo->family >= NPROTO)) | 2494 | if (unlikely(afinfo->family >= NPROTO)) |
2476 | return -EAFNOSUPPORT; | 2495 | return -EAFNOSUPPORT; |
2477 | write_lock_bh(&xfrm_policy_afinfo_lock); | 2496 | spin_lock(&xfrm_policy_afinfo_lock); |
2478 | if (likely(xfrm_policy_afinfo[afinfo->family] != NULL)) { | 2497 | if (likely(xfrm_policy_afinfo[afinfo->family] != NULL)) { |
2479 | if (unlikely(xfrm_policy_afinfo[afinfo->family] != afinfo)) | 2498 | if (unlikely(xfrm_policy_afinfo[afinfo->family] != afinfo)) |
2480 | err = -EINVAL; | 2499 | err = -EINVAL; |
2481 | else { | 2500 | else |
2482 | struct dst_ops *dst_ops = afinfo->dst_ops; | 2501 | RCU_INIT_POINTER(xfrm_policy_afinfo[afinfo->family], |
2483 | xfrm_policy_afinfo[afinfo->family] = NULL; | 2502 | NULL); |
2484 | dst_ops->kmem_cachep = NULL; | 2503 | } |
2485 | dst_ops->check = NULL; | 2504 | spin_unlock(&xfrm_policy_afinfo_lock); |
2486 | dst_ops->negative_advice = NULL; | 2505 | if (!err) { |
2487 | dst_ops->link_failure = NULL; | 2506 | struct dst_ops *dst_ops = afinfo->dst_ops; |
2488 | afinfo->garbage_collect = NULL; | 2507 | |
2489 | } | 2508 | synchronize_rcu(); |
2509 | |||
2510 | dst_ops->kmem_cachep = NULL; | ||
2511 | dst_ops->check = NULL; | ||
2512 | dst_ops->negative_advice = NULL; | ||
2513 | dst_ops->link_failure = NULL; | ||
2514 | afinfo->garbage_collect = NULL; | ||
2490 | } | 2515 | } |
2491 | write_unlock_bh(&xfrm_policy_afinfo_lock); | ||
2492 | return err; | 2516 | return err; |
2493 | } | 2517 | } |
2494 | EXPORT_SYMBOL(xfrm_policy_unregister_afinfo); | 2518 | EXPORT_SYMBOL(xfrm_policy_unregister_afinfo); |
@@ -2497,33 +2521,16 @@ static void __net_init xfrm_dst_ops_init(struct net *net) | |||
2497 | { | 2521 | { |
2498 | struct xfrm_policy_afinfo *afinfo; | 2522 | struct xfrm_policy_afinfo *afinfo; |
2499 | 2523 | ||
2500 | read_lock_bh(&xfrm_policy_afinfo_lock); | 2524 | rcu_read_lock(); |
2501 | afinfo = xfrm_policy_afinfo[AF_INET]; | 2525 | afinfo = rcu_dereference(xfrm_policy_afinfo[AF_INET]); |
2502 | if (afinfo) | 2526 | if (afinfo) |
2503 | net->xfrm.xfrm4_dst_ops = *afinfo->dst_ops; | 2527 | net->xfrm.xfrm4_dst_ops = *afinfo->dst_ops; |
2504 | #if IS_ENABLED(CONFIG_IPV6) | 2528 | #if IS_ENABLED(CONFIG_IPV6) |
2505 | afinfo = xfrm_policy_afinfo[AF_INET6]; | 2529 | afinfo = rcu_dereference(xfrm_policy_afinfo[AF_INET6]); |
2506 | if (afinfo) | 2530 | if (afinfo) |
2507 | net->xfrm.xfrm6_dst_ops = *afinfo->dst_ops; | 2531 | net->xfrm.xfrm6_dst_ops = *afinfo->dst_ops; |
2508 | #endif | 2532 | #endif |
2509 | read_unlock_bh(&xfrm_policy_afinfo_lock); | 2533 | rcu_read_unlock(); |
2510 | } | ||
2511 | |||
2512 | static struct xfrm_policy_afinfo *xfrm_policy_get_afinfo(unsigned short family) | ||
2513 | { | ||
2514 | struct xfrm_policy_afinfo *afinfo; | ||
2515 | if (unlikely(family >= NPROTO)) | ||
2516 | return NULL; | ||
2517 | read_lock(&xfrm_policy_afinfo_lock); | ||
2518 | afinfo = xfrm_policy_afinfo[family]; | ||
2519 | if (unlikely(!afinfo)) | ||
2520 | read_unlock(&xfrm_policy_afinfo_lock); | ||
2521 | return afinfo; | ||
2522 | } | ||
2523 | |||
2524 | static void xfrm_policy_put_afinfo(struct xfrm_policy_afinfo *afinfo) | ||
2525 | { | ||
2526 | read_unlock(&xfrm_policy_afinfo_lock); | ||
2527 | } | 2534 | } |
2528 | 2535 | ||
2529 | static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr) | 2536 | static int xfrm_dev_event(struct notifier_block *this, unsigned long event, void *ptr) |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 5b228f97d4b3..7856c33898fa 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
@@ -415,8 +415,17 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer * me) | |||
415 | if (x->lft.hard_add_expires_seconds) { | 415 | if (x->lft.hard_add_expires_seconds) { |
416 | long tmo = x->lft.hard_add_expires_seconds + | 416 | long tmo = x->lft.hard_add_expires_seconds + |
417 | x->curlft.add_time - now; | 417 | x->curlft.add_time - now; |
418 | if (tmo <= 0) | 418 | if (tmo <= 0) { |
419 | goto expired; | 419 | if (x->xflags & XFRM_SOFT_EXPIRE) { |
420 | /* enter hard expire without soft expire first?! | ||
421 | * setting a new date could trigger this. | ||
422 | * workarbound: fix x->curflt.add_time by below: | ||
423 | */ | ||
424 | x->curlft.add_time = now - x->saved_tmo - 1; | ||
425 | tmo = x->lft.hard_add_expires_seconds - x->saved_tmo; | ||
426 | } else | ||
427 | goto expired; | ||
428 | } | ||
420 | if (tmo < next) | 429 | if (tmo < next) |
421 | next = tmo; | 430 | next = tmo; |
422 | } | 431 | } |
@@ -433,10 +442,14 @@ static enum hrtimer_restart xfrm_timer_handler(struct hrtimer * me) | |||
433 | if (x->lft.soft_add_expires_seconds) { | 442 | if (x->lft.soft_add_expires_seconds) { |
434 | long tmo = x->lft.soft_add_expires_seconds + | 443 | long tmo = x->lft.soft_add_expires_seconds + |
435 | x->curlft.add_time - now; | 444 | x->curlft.add_time - now; |
436 | if (tmo <= 0) | 445 | if (tmo <= 0) { |
437 | warn = 1; | 446 | warn = 1; |
438 | else if (tmo < next) | 447 | x->xflags &= ~XFRM_SOFT_EXPIRE; |
448 | } else if (tmo < next) { | ||
439 | next = tmo; | 449 | next = tmo; |
450 | x->xflags |= XFRM_SOFT_EXPIRE; | ||
451 | x->saved_tmo = tmo; | ||
452 | } | ||
440 | } | 453 | } |
441 | if (x->lft.soft_use_expires_seconds) { | 454 | if (x->lft.soft_use_expires_seconds) { |
442 | long tmo = x->lft.soft_use_expires_seconds + | 455 | long tmo = x->lft.soft_use_expires_seconds + |
@@ -1687,7 +1700,7 @@ int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol) | |||
1687 | 1700 | ||
1688 | read_lock(&xfrm_km_lock); | 1701 | read_lock(&xfrm_km_lock); |
1689 | list_for_each_entry(km, &xfrm_km_list, list) { | 1702 | list_for_each_entry(km, &xfrm_km_list, list) { |
1690 | acqret = km->acquire(x, t, pol, XFRM_POLICY_OUT); | 1703 | acqret = km->acquire(x, t, pol); |
1691 | if (!acqret) | 1704 | if (!acqret) |
1692 | err = acqret; | 1705 | err = acqret; |
1693 | } | 1706 | } |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index e75d8e47f35c..ab58034c42d6 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -2567,8 +2567,7 @@ static inline size_t xfrm_acquire_msgsize(struct xfrm_state *x, | |||
2567 | } | 2567 | } |
2568 | 2568 | ||
2569 | static int build_acquire(struct sk_buff *skb, struct xfrm_state *x, | 2569 | static int build_acquire(struct sk_buff *skb, struct xfrm_state *x, |
2570 | struct xfrm_tmpl *xt, struct xfrm_policy *xp, | 2570 | struct xfrm_tmpl *xt, struct xfrm_policy *xp) |
2571 | int dir) | ||
2572 | { | 2571 | { |
2573 | __u32 seq = xfrm_get_acqseq(); | 2572 | __u32 seq = xfrm_get_acqseq(); |
2574 | struct xfrm_user_acquire *ua; | 2573 | struct xfrm_user_acquire *ua; |
@@ -2583,7 +2582,7 @@ static int build_acquire(struct sk_buff *skb, struct xfrm_state *x, | |||
2583 | memcpy(&ua->id, &x->id, sizeof(ua->id)); | 2582 | memcpy(&ua->id, &x->id, sizeof(ua->id)); |
2584 | memcpy(&ua->saddr, &x->props.saddr, sizeof(ua->saddr)); | 2583 | memcpy(&ua->saddr, &x->props.saddr, sizeof(ua->saddr)); |
2585 | memcpy(&ua->sel, &x->sel, sizeof(ua->sel)); | 2584 | memcpy(&ua->sel, &x->sel, sizeof(ua->sel)); |
2586 | copy_to_user_policy(xp, &ua->policy, dir); | 2585 | copy_to_user_policy(xp, &ua->policy, XFRM_POLICY_OUT); |
2587 | ua->aalgos = xt->aalgos; | 2586 | ua->aalgos = xt->aalgos; |
2588 | ua->ealgos = xt->ealgos; | 2587 | ua->ealgos = xt->ealgos; |
2589 | ua->calgos = xt->calgos; | 2588 | ua->calgos = xt->calgos; |
@@ -2605,7 +2604,7 @@ static int build_acquire(struct sk_buff *skb, struct xfrm_state *x, | |||
2605 | } | 2604 | } |
2606 | 2605 | ||
2607 | static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt, | 2606 | static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt, |
2608 | struct xfrm_policy *xp, int dir) | 2607 | struct xfrm_policy *xp) |
2609 | { | 2608 | { |
2610 | struct net *net = xs_net(x); | 2609 | struct net *net = xs_net(x); |
2611 | struct sk_buff *skb; | 2610 | struct sk_buff *skb; |
@@ -2614,7 +2613,7 @@ static int xfrm_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *xt, | |||
2614 | if (skb == NULL) | 2613 | if (skb == NULL) |
2615 | return -ENOMEM; | 2614 | return -ENOMEM; |
2616 | 2615 | ||
2617 | if (build_acquire(skb, x, xt, xp, dir) < 0) | 2616 | if (build_acquire(skb, x, xt, xp) < 0) |
2618 | BUG(); | 2617 | BUG(); |
2619 | 2618 | ||
2620 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_ACQUIRE, GFP_ATOMIC); | 2619 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_ACQUIRE, GFP_ATOMIC); |