diff options
author | James Morris <james.l.morris@oracle.com> | 2014-11-19 05:32:12 -0500 |
---|---|---|
committer | James Morris <james.l.morris@oracle.com> | 2014-11-19 05:32:12 -0500 |
commit | b10778a00d40b3d9fdaaf5891e802794781ff71c (patch) | |
tree | 6ba4cbac86eecedc3f30650e7f764ecf00c83898 /net | |
parent | 594081ee7145cc30a3977cb4e218f81213b63dc5 (diff) | |
parent | bfe01a5ba2490f299e1d2d5508cbbbadd897bbe9 (diff) |
Merge commit 'v3.17' into next
Diffstat (limited to 'net')
387 files changed, 16043 insertions, 12909 deletions
diff --git a/net/6lowpan/Kconfig b/net/6lowpan/Kconfig new file mode 100644 index 000000000000..e4a02ef55102 --- /dev/null +++ b/net/6lowpan/Kconfig | |||
@@ -0,0 +1,6 @@ | |||
1 | config 6LOWPAN | ||
2 | tristate "6LoWPAN Support" | ||
3 | depends on IPV6 | ||
4 | ---help--- | ||
5 | This enables IPv6 over Low power Wireless Personal Area Network - | ||
6 | "6LoWPAN" which is supported by IEEE 802.15.4 or Bluetooth stacks. | ||
diff --git a/net/6lowpan/Makefile b/net/6lowpan/Makefile new file mode 100644 index 000000000000..415886bb456a --- /dev/null +++ b/net/6lowpan/Makefile | |||
@@ -0,0 +1,3 @@ | |||
1 | obj-$(CONFIG_6LOWPAN) := 6lowpan.o | ||
2 | |||
3 | 6lowpan-y := iphc.o | ||
diff --git a/net/ieee802154/6lowpan_iphc.c b/net/6lowpan/iphc.c index 211b5686d719..142eef55c9e2 100644 --- a/net/ieee802154/6lowpan_iphc.c +++ b/net/6lowpan/iphc.c | |||
@@ -3,8 +3,7 @@ | |||
3 | * written by Alexander Smirnov <alex.bluesman.smirnov@gmail.com> | 3 | * written by Alexander Smirnov <alex.bluesman.smirnov@gmail.com> |
4 | */ | 4 | */ |
5 | 5 | ||
6 | /* | 6 | /* Based on patches from Jon Smirl <jonsmirl@gmail.com> |
7 | * Based on patches from Jon Smirl <jonsmirl@gmail.com> | ||
8 | * Copyright (c) 2011 Jon Smirl <jonsmirl@gmail.com> | 7 | * Copyright (c) 2011 Jon Smirl <jonsmirl@gmail.com> |
9 | * | 8 | * |
10 | * This program is free software; you can redistribute it and/or modify | 9 | * This program is free software; you can redistribute it and/or modify |
@@ -58,16 +57,15 @@ | |||
58 | #include <net/ipv6.h> | 57 | #include <net/ipv6.h> |
59 | #include <net/af_ieee802154.h> | 58 | #include <net/af_ieee802154.h> |
60 | 59 | ||
61 | /* | 60 | /* Uncompress address function for source and |
62 | * Uncompress address function for source and | ||
63 | * destination address(non-multicast). | 61 | * destination address(non-multicast). |
64 | * | 62 | * |
65 | * address_mode is sam value or dam value. | 63 | * address_mode is sam value or dam value. |
66 | */ | 64 | */ |
67 | static int uncompress_addr(struct sk_buff *skb, | 65 | static int uncompress_addr(struct sk_buff *skb, |
68 | struct in6_addr *ipaddr, const u8 address_mode, | 66 | struct in6_addr *ipaddr, const u8 address_mode, |
69 | const u8 *lladdr, const u8 addr_type, | 67 | const u8 *lladdr, const u8 addr_type, |
70 | const u8 addr_len) | 68 | const u8 addr_len) |
71 | { | 69 | { |
72 | bool fail; | 70 | bool fail; |
73 | 71 | ||
@@ -140,13 +138,12 @@ static int uncompress_addr(struct sk_buff *skb, | |||
140 | return 0; | 138 | return 0; |
141 | } | 139 | } |
142 | 140 | ||
143 | /* | 141 | /* Uncompress address function for source context |
144 | * Uncompress address function for source context | ||
145 | * based address(non-multicast). | 142 | * based address(non-multicast). |
146 | */ | 143 | */ |
147 | static int uncompress_context_based_src_addr(struct sk_buff *skb, | 144 | static int uncompress_context_based_src_addr(struct sk_buff *skb, |
148 | struct in6_addr *ipaddr, | 145 | struct in6_addr *ipaddr, |
149 | const u8 sam) | 146 | const u8 sam) |
150 | { | 147 | { |
151 | switch (sam) { | 148 | switch (sam) { |
152 | case LOWPAN_IPHC_ADDR_00: | 149 | case LOWPAN_IPHC_ADDR_00: |
@@ -175,13 +172,13 @@ static int uncompress_context_based_src_addr(struct sk_buff *skb, | |||
175 | } | 172 | } |
176 | 173 | ||
177 | static int skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr, | 174 | static int skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr, |
178 | struct net_device *dev, skb_delivery_cb deliver_skb) | 175 | struct net_device *dev, skb_delivery_cb deliver_skb) |
179 | { | 176 | { |
180 | struct sk_buff *new; | 177 | struct sk_buff *new; |
181 | int stat; | 178 | int stat; |
182 | 179 | ||
183 | new = skb_copy_expand(skb, sizeof(struct ipv6hdr), skb_tailroom(skb), | 180 | new = skb_copy_expand(skb, sizeof(struct ipv6hdr), skb_tailroom(skb), |
184 | GFP_ATOMIC); | 181 | GFP_ATOMIC); |
185 | kfree_skb(skb); | 182 | kfree_skb(skb); |
186 | 183 | ||
187 | if (!new) | 184 | if (!new) |
@@ -196,7 +193,7 @@ static int skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr, | |||
196 | new->dev = dev; | 193 | new->dev = dev; |
197 | 194 | ||
198 | raw_dump_table(__func__, "raw skb data dump before receiving", | 195 | raw_dump_table(__func__, "raw skb data dump before receiving", |
199 | new->data, new->len); | 196 | new->data, new->len); |
200 | 197 | ||
201 | stat = deliver_skb(new, dev); | 198 | stat = deliver_skb(new, dev); |
202 | 199 | ||
@@ -208,10 +205,9 @@ static int skb_deliver(struct sk_buff *skb, struct ipv6hdr *hdr, | |||
208 | /* Uncompress function for multicast destination address, | 205 | /* Uncompress function for multicast destination address, |
209 | * when M bit is set. | 206 | * when M bit is set. |
210 | */ | 207 | */ |
211 | static int | 208 | static int lowpan_uncompress_multicast_daddr(struct sk_buff *skb, |
212 | lowpan_uncompress_multicast_daddr(struct sk_buff *skb, | 209 | struct in6_addr *ipaddr, |
213 | struct in6_addr *ipaddr, | 210 | const u8 dam) |
214 | const u8 dam) | ||
215 | { | 211 | { |
216 | bool fail; | 212 | bool fail; |
217 | 213 | ||
@@ -257,41 +253,41 @@ lowpan_uncompress_multicast_daddr(struct sk_buff *skb, | |||
257 | } | 253 | } |
258 | 254 | ||
259 | raw_dump_inline(NULL, "Reconstructed ipv6 multicast addr is", | 255 | raw_dump_inline(NULL, "Reconstructed ipv6 multicast addr is", |
260 | ipaddr->s6_addr, 16); | 256 | ipaddr->s6_addr, 16); |
261 | 257 | ||
262 | return 0; | 258 | return 0; |
263 | } | 259 | } |
264 | 260 | ||
265 | static int | 261 | static int uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh) |
266 | uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh) | ||
267 | { | 262 | { |
268 | bool fail; | 263 | bool fail; |
269 | u8 tmp = 0, val = 0; | 264 | u8 tmp = 0, val = 0; |
270 | 265 | ||
271 | if (!uh) | 266 | fail = lowpan_fetch_skb(skb, &tmp, sizeof(tmp)); |
272 | goto err; | ||
273 | |||
274 | fail = lowpan_fetch_skb(skb, &tmp, 1); | ||
275 | 267 | ||
276 | if ((tmp & LOWPAN_NHC_UDP_MASK) == LOWPAN_NHC_UDP_ID) { | 268 | if ((tmp & LOWPAN_NHC_UDP_MASK) == LOWPAN_NHC_UDP_ID) { |
277 | pr_debug("UDP header uncompression\n"); | 269 | pr_debug("UDP header uncompression\n"); |
278 | switch (tmp & LOWPAN_NHC_UDP_CS_P_11) { | 270 | switch (tmp & LOWPAN_NHC_UDP_CS_P_11) { |
279 | case LOWPAN_NHC_UDP_CS_P_00: | 271 | case LOWPAN_NHC_UDP_CS_P_00: |
280 | fail |= lowpan_fetch_skb(skb, &uh->source, 2); | 272 | fail |= lowpan_fetch_skb(skb, &uh->source, |
281 | fail |= lowpan_fetch_skb(skb, &uh->dest, 2); | 273 | sizeof(uh->source)); |
274 | fail |= lowpan_fetch_skb(skb, &uh->dest, | ||
275 | sizeof(uh->dest)); | ||
282 | break; | 276 | break; |
283 | case LOWPAN_NHC_UDP_CS_P_01: | 277 | case LOWPAN_NHC_UDP_CS_P_01: |
284 | fail |= lowpan_fetch_skb(skb, &uh->source, 2); | 278 | fail |= lowpan_fetch_skb(skb, &uh->source, |
285 | fail |= lowpan_fetch_skb(skb, &val, 1); | 279 | sizeof(uh->source)); |
280 | fail |= lowpan_fetch_skb(skb, &val, sizeof(val)); | ||
286 | uh->dest = htons(val + LOWPAN_NHC_UDP_8BIT_PORT); | 281 | uh->dest = htons(val + LOWPAN_NHC_UDP_8BIT_PORT); |
287 | break; | 282 | break; |
288 | case LOWPAN_NHC_UDP_CS_P_10: | 283 | case LOWPAN_NHC_UDP_CS_P_10: |
289 | fail |= lowpan_fetch_skb(skb, &val, 1); | 284 | fail |= lowpan_fetch_skb(skb, &val, sizeof(val)); |
290 | uh->source = htons(val + LOWPAN_NHC_UDP_8BIT_PORT); | 285 | uh->source = htons(val + LOWPAN_NHC_UDP_8BIT_PORT); |
291 | fail |= lowpan_fetch_skb(skb, &uh->dest, 2); | 286 | fail |= lowpan_fetch_skb(skb, &uh->dest, |
287 | sizeof(uh->dest)); | ||
292 | break; | 288 | break; |
293 | case LOWPAN_NHC_UDP_CS_P_11: | 289 | case LOWPAN_NHC_UDP_CS_P_11: |
294 | fail |= lowpan_fetch_skb(skb, &val, 1); | 290 | fail |= lowpan_fetch_skb(skb, &val, sizeof(val)); |
295 | uh->source = htons(LOWPAN_NHC_UDP_4BIT_PORT + | 291 | uh->source = htons(LOWPAN_NHC_UDP_4BIT_PORT + |
296 | (val >> 4)); | 292 | (val >> 4)); |
297 | uh->dest = htons(LOWPAN_NHC_UDP_4BIT_PORT + | 293 | uh->dest = htons(LOWPAN_NHC_UDP_4BIT_PORT + |
@@ -300,7 +296,6 @@ uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh) | |||
300 | default: | 296 | default: |
301 | pr_debug("ERROR: unknown UDP format\n"); | 297 | pr_debug("ERROR: unknown UDP format\n"); |
302 | goto err; | 298 | goto err; |
303 | break; | ||
304 | } | 299 | } |
305 | 300 | ||
306 | pr_debug("uncompressed UDP ports: src = %d, dst = %d\n", | 301 | pr_debug("uncompressed UDP ports: src = %d, dst = %d\n", |
@@ -311,11 +306,11 @@ uncompress_udp_header(struct sk_buff *skb, struct udphdr *uh) | |||
311 | pr_debug_ratelimited("checksum elided currently not supported\n"); | 306 | pr_debug_ratelimited("checksum elided currently not supported\n"); |
312 | goto err; | 307 | goto err; |
313 | } else { | 308 | } else { |
314 | fail |= lowpan_fetch_skb(skb, &uh->check, 2); | 309 | fail |= lowpan_fetch_skb(skb, &uh->check, |
310 | sizeof(uh->check)); | ||
315 | } | 311 | } |
316 | 312 | ||
317 | /* | 313 | /* UDP length needs to be infered from the lower layers |
318 | * UDP lenght needs to be infered from the lower layers | ||
319 | * here, we obtain the hint from the remaining size of the | 314 | * here, we obtain the hint from the remaining size of the |
320 | * frame | 315 | * frame |
321 | */ | 316 | */ |
@@ -338,21 +333,21 @@ err: | |||
338 | static const u8 lowpan_ttl_values[] = { 0, 1, 64, 255 }; | 333 | static const u8 lowpan_ttl_values[] = { 0, 1, 64, 255 }; |
339 | 334 | ||
340 | int lowpan_process_data(struct sk_buff *skb, struct net_device *dev, | 335 | int lowpan_process_data(struct sk_buff *skb, struct net_device *dev, |
341 | const u8 *saddr, const u8 saddr_type, const u8 saddr_len, | 336 | const u8 *saddr, const u8 saddr_type, const u8 saddr_len, |
342 | const u8 *daddr, const u8 daddr_type, const u8 daddr_len, | 337 | const u8 *daddr, const u8 daddr_type, const u8 daddr_len, |
343 | u8 iphc0, u8 iphc1, skb_delivery_cb deliver_skb) | 338 | u8 iphc0, u8 iphc1, skb_delivery_cb deliver_skb) |
344 | { | 339 | { |
345 | struct ipv6hdr hdr = {}; | 340 | struct ipv6hdr hdr = {}; |
346 | u8 tmp, num_context = 0; | 341 | u8 tmp, num_context = 0; |
347 | int err; | 342 | int err; |
348 | 343 | ||
349 | raw_dump_table(__func__, "raw skb data dump uncompressed", | 344 | raw_dump_table(__func__, "raw skb data dump uncompressed", |
350 | skb->data, skb->len); | 345 | skb->data, skb->len); |
351 | 346 | ||
352 | /* another if the CID flag is set */ | 347 | /* another if the CID flag is set */ |
353 | if (iphc1 & LOWPAN_IPHC_CID) { | 348 | if (iphc1 & LOWPAN_IPHC_CID) { |
354 | pr_debug("CID flag is set, increase header with one\n"); | 349 | pr_debug("CID flag is set, increase header with one\n"); |
355 | if (lowpan_fetch_skb_u8(skb, &num_context)) | 350 | if (lowpan_fetch_skb(skb, &num_context, sizeof(num_context))) |
356 | goto drop; | 351 | goto drop; |
357 | } | 352 | } |
358 | 353 | ||
@@ -360,12 +355,11 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev, | |||
360 | 355 | ||
361 | /* Traffic Class and Flow Label */ | 356 | /* Traffic Class and Flow Label */ |
362 | switch ((iphc0 & LOWPAN_IPHC_TF) >> 3) { | 357 | switch ((iphc0 & LOWPAN_IPHC_TF) >> 3) { |
363 | /* | 358 | /* Traffic Class and FLow Label carried in-line |
364 | * Traffic Class and FLow Label carried in-line | ||
365 | * ECN + DSCP + 4-bit Pad + Flow Label (4 bytes) | 359 | * ECN + DSCP + 4-bit Pad + Flow Label (4 bytes) |
366 | */ | 360 | */ |
367 | case 0: /* 00b */ | 361 | case 0: /* 00b */ |
368 | if (lowpan_fetch_skb_u8(skb, &tmp)) | 362 | if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp))) |
369 | goto drop; | 363 | goto drop; |
370 | 364 | ||
371 | memcpy(&hdr.flow_lbl, &skb->data[0], 3); | 365 | memcpy(&hdr.flow_lbl, &skb->data[0], 3); |
@@ -374,23 +368,21 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev, | |||
374 | hdr.flow_lbl[0] = ((tmp >> 2) & 0x30) | (tmp << 6) | | 368 | hdr.flow_lbl[0] = ((tmp >> 2) & 0x30) | (tmp << 6) | |
375 | (hdr.flow_lbl[0] & 0x0f); | 369 | (hdr.flow_lbl[0] & 0x0f); |
376 | break; | 370 | break; |
377 | /* | 371 | /* Traffic class carried in-line |
378 | * Traffic class carried in-line | ||
379 | * ECN + DSCP (1 byte), Flow Label is elided | 372 | * ECN + DSCP (1 byte), Flow Label is elided |
380 | */ | 373 | */ |
381 | case 2: /* 10b */ | 374 | case 2: /* 10b */ |
382 | if (lowpan_fetch_skb_u8(skb, &tmp)) | 375 | if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp))) |
383 | goto drop; | 376 | goto drop; |
384 | 377 | ||
385 | hdr.priority = ((tmp >> 2) & 0x0f); | 378 | hdr.priority = ((tmp >> 2) & 0x0f); |
386 | hdr.flow_lbl[0] = ((tmp << 6) & 0xC0) | ((tmp >> 2) & 0x30); | 379 | hdr.flow_lbl[0] = ((tmp << 6) & 0xC0) | ((tmp >> 2) & 0x30); |
387 | break; | 380 | break; |
388 | /* | 381 | /* Flow Label carried in-line |
389 | * Flow Label carried in-line | ||
390 | * ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided | 382 | * ECN + 2-bit Pad + Flow Label (3 bytes), DSCP is elided |
391 | */ | 383 | */ |
392 | case 1: /* 01b */ | 384 | case 1: /* 01b */ |
393 | if (lowpan_fetch_skb_u8(skb, &tmp)) | 385 | if (lowpan_fetch_skb(skb, &tmp, sizeof(tmp))) |
394 | goto drop; | 386 | goto drop; |
395 | 387 | ||
396 | hdr.flow_lbl[0] = (skb->data[0] & 0x0F) | ((tmp >> 2) & 0x30); | 388 | hdr.flow_lbl[0] = (skb->data[0] & 0x0F) | ((tmp >> 2) & 0x30); |
@@ -407,7 +399,7 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev, | |||
407 | /* Next Header */ | 399 | /* Next Header */ |
408 | if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) { | 400 | if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) { |
409 | /* Next header is carried inline */ | 401 | /* Next header is carried inline */ |
410 | if (lowpan_fetch_skb_u8(skb, &(hdr.nexthdr))) | 402 | if (lowpan_fetch_skb(skb, &hdr.nexthdr, sizeof(hdr.nexthdr))) |
411 | goto drop; | 403 | goto drop; |
412 | 404 | ||
413 | pr_debug("NH flag is set, next header carried inline: %02x\n", | 405 | pr_debug("NH flag is set, next header carried inline: %02x\n", |
@@ -415,10 +407,11 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev, | |||
415 | } | 407 | } |
416 | 408 | ||
417 | /* Hop Limit */ | 409 | /* Hop Limit */ |
418 | if ((iphc0 & 0x03) != LOWPAN_IPHC_TTL_I) | 410 | if ((iphc0 & 0x03) != LOWPAN_IPHC_TTL_I) { |
419 | hdr.hop_limit = lowpan_ttl_values[iphc0 & 0x03]; | 411 | hdr.hop_limit = lowpan_ttl_values[iphc0 & 0x03]; |
420 | else { | 412 | } else { |
421 | if (lowpan_fetch_skb_u8(skb, &(hdr.hop_limit))) | 413 | if (lowpan_fetch_skb(skb, &hdr.hop_limit, |
414 | sizeof(hdr.hop_limit))) | ||
422 | goto drop; | 415 | goto drop; |
423 | } | 416 | } |
424 | 417 | ||
@@ -428,13 +421,12 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev, | |||
428 | if (iphc1 & LOWPAN_IPHC_SAC) { | 421 | if (iphc1 & LOWPAN_IPHC_SAC) { |
429 | /* Source address context based uncompression */ | 422 | /* Source address context based uncompression */ |
430 | pr_debug("SAC bit is set. Handle context based source address.\n"); | 423 | pr_debug("SAC bit is set. Handle context based source address.\n"); |
431 | err = uncompress_context_based_src_addr( | 424 | err = uncompress_context_based_src_addr(skb, &hdr.saddr, tmp); |
432 | skb, &hdr.saddr, tmp); | ||
433 | } else { | 425 | } else { |
434 | /* Source address uncompression */ | 426 | /* Source address uncompression */ |
435 | pr_debug("source address stateless compression\n"); | 427 | pr_debug("source address stateless compression\n"); |
436 | err = uncompress_addr(skb, &hdr.saddr, tmp, saddr, | 428 | err = uncompress_addr(skb, &hdr.saddr, tmp, saddr, |
437 | saddr_type, saddr_len); | 429 | saddr_type, saddr_len); |
438 | } | 430 | } |
439 | 431 | ||
440 | /* Check on error of previous branch */ | 432 | /* Check on error of previous branch */ |
@@ -450,16 +442,17 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev, | |||
450 | pr_debug("dest: context-based mcast compression\n"); | 442 | pr_debug("dest: context-based mcast compression\n"); |
451 | /* TODO: implement this */ | 443 | /* TODO: implement this */ |
452 | } else { | 444 | } else { |
453 | err = lowpan_uncompress_multicast_daddr( | 445 | err = lowpan_uncompress_multicast_daddr(skb, &hdr.daddr, |
454 | skb, &hdr.daddr, tmp); | 446 | tmp); |
447 | |||
455 | if (err) | 448 | if (err) |
456 | goto drop; | 449 | goto drop; |
457 | } | 450 | } |
458 | } else { | 451 | } else { |
459 | err = uncompress_addr(skb, &hdr.daddr, tmp, daddr, | 452 | err = uncompress_addr(skb, &hdr.daddr, tmp, daddr, |
460 | daddr_type, daddr_len); | 453 | daddr_type, daddr_len); |
461 | pr_debug("dest: stateless compression mode %d dest %pI6c\n", | 454 | pr_debug("dest: stateless compression mode %d dest %pI6c\n", |
462 | tmp, &hdr.daddr); | 455 | tmp, &hdr.daddr); |
463 | if (err) | 456 | if (err) |
464 | goto drop; | 457 | goto drop; |
465 | } | 458 | } |
@@ -468,11 +461,11 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev, | |||
468 | if (iphc0 & LOWPAN_IPHC_NH_C) { | 461 | if (iphc0 & LOWPAN_IPHC_NH_C) { |
469 | struct udphdr uh; | 462 | struct udphdr uh; |
470 | struct sk_buff *new; | 463 | struct sk_buff *new; |
464 | |||
471 | if (uncompress_udp_header(skb, &uh)) | 465 | if (uncompress_udp_header(skb, &uh)) |
472 | goto drop; | 466 | goto drop; |
473 | 467 | ||
474 | /* | 468 | /* replace the compressed UDP head by the uncompressed UDP |
475 | * replace the compressed UDP head by the uncompressed UDP | ||
476 | * header | 469 | * header |
477 | */ | 470 | */ |
478 | new = skb_copy_expand(skb, sizeof(struct udphdr), | 471 | new = skb_copy_expand(skb, sizeof(struct udphdr), |
@@ -489,7 +482,7 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev, | |||
489 | skb_copy_to_linear_data(skb, &uh, sizeof(struct udphdr)); | 482 | skb_copy_to_linear_data(skb, &uh, sizeof(struct udphdr)); |
490 | 483 | ||
491 | raw_dump_table(__func__, "raw UDP header dump", | 484 | raw_dump_table(__func__, "raw UDP header dump", |
492 | (u8 *)&uh, sizeof(uh)); | 485 | (u8 *)&uh, sizeof(uh)); |
493 | 486 | ||
494 | hdr.nexthdr = UIP_PROTO_UDP; | 487 | hdr.nexthdr = UIP_PROTO_UDP; |
495 | } | 488 | } |
@@ -504,8 +497,7 @@ int lowpan_process_data(struct sk_buff *skb, struct net_device *dev, | |||
504 | hdr.version, ntohs(hdr.payload_len), hdr.nexthdr, | 497 | hdr.version, ntohs(hdr.payload_len), hdr.nexthdr, |
505 | hdr.hop_limit, &hdr.daddr); | 498 | hdr.hop_limit, &hdr.daddr); |
506 | 499 | ||
507 | raw_dump_table(__func__, "raw header dump", (u8 *)&hdr, | 500 | raw_dump_table(__func__, "raw header dump", (u8 *)&hdr, sizeof(hdr)); |
508 | sizeof(hdr)); | ||
509 | 501 | ||
510 | return skb_deliver(skb, &hdr, dev, deliver_skb); | 502 | return skb_deliver(skb, &hdr, dev, deliver_skb); |
511 | 503 | ||
@@ -515,9 +507,9 @@ drop: | |||
515 | } | 507 | } |
516 | EXPORT_SYMBOL_GPL(lowpan_process_data); | 508 | EXPORT_SYMBOL_GPL(lowpan_process_data); |
517 | 509 | ||
518 | static u8 lowpan_compress_addr_64(u8 **hc06_ptr, u8 shift, | 510 | static u8 lowpan_compress_addr_64(u8 **hc_ptr, u8 shift, |
519 | const struct in6_addr *ipaddr, | 511 | const struct in6_addr *ipaddr, |
520 | const unsigned char *lladdr) | 512 | const unsigned char *lladdr) |
521 | { | 513 | { |
522 | u8 val = 0; | 514 | u8 val = 0; |
523 | 515 | ||
@@ -526,24 +518,22 @@ static u8 lowpan_compress_addr_64(u8 **hc06_ptr, u8 shift, | |||
526 | pr_debug("address compression 0 bits\n"); | 518 | pr_debug("address compression 0 bits\n"); |
527 | } else if (lowpan_is_iid_16_bit_compressable(ipaddr)) { | 519 | } else if (lowpan_is_iid_16_bit_compressable(ipaddr)) { |
528 | /* compress IID to 16 bits xxxx::XXXX */ | 520 | /* compress IID to 16 bits xxxx::XXXX */ |
529 | memcpy(*hc06_ptr, &ipaddr->s6_addr16[7], 2); | 521 | lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr16[7], 2); |
530 | *hc06_ptr += 2; | ||
531 | val = 2; /* 16-bits */ | 522 | val = 2; /* 16-bits */ |
532 | raw_dump_inline(NULL, "Compressed ipv6 addr is (16 bits)", | 523 | raw_dump_inline(NULL, "Compressed ipv6 addr is (16 bits)", |
533 | *hc06_ptr - 2, 2); | 524 | *hc_ptr - 2, 2); |
534 | } else { | 525 | } else { |
535 | /* do not compress IID => xxxx::IID */ | 526 | /* do not compress IID => xxxx::IID */ |
536 | memcpy(*hc06_ptr, &ipaddr->s6_addr16[4], 8); | 527 | lowpan_push_hc_data(hc_ptr, &ipaddr->s6_addr16[4], 8); |
537 | *hc06_ptr += 8; | ||
538 | val = 1; /* 64-bits */ | 528 | val = 1; /* 64-bits */ |
539 | raw_dump_inline(NULL, "Compressed ipv6 addr is (64 bits)", | 529 | raw_dump_inline(NULL, "Compressed ipv6 addr is (64 bits)", |
540 | *hc06_ptr - 8, 8); | 530 | *hc_ptr - 8, 8); |
541 | } | 531 | } |
542 | 532 | ||
543 | return rol8(val, shift); | 533 | return rol8(val, shift); |
544 | } | 534 | } |
545 | 535 | ||
546 | static void compress_udp_header(u8 **hc06_ptr, struct sk_buff *skb) | 536 | static void compress_udp_header(u8 **hc_ptr, struct sk_buff *skb) |
547 | { | 537 | { |
548 | struct udphdr *uh = udp_hdr(skb); | 538 | struct udphdr *uh = udp_hdr(skb); |
549 | u8 tmp; | 539 | u8 tmp; |
@@ -555,75 +545,75 @@ static void compress_udp_header(u8 **hc06_ptr, struct sk_buff *skb) | |||
555 | pr_debug("UDP header: both ports compression to 4 bits\n"); | 545 | pr_debug("UDP header: both ports compression to 4 bits\n"); |
556 | /* compression value */ | 546 | /* compression value */ |
557 | tmp = LOWPAN_NHC_UDP_CS_P_11; | 547 | tmp = LOWPAN_NHC_UDP_CS_P_11; |
558 | lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp)); | 548 | lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp)); |
559 | /* source and destination port */ | 549 | /* source and destination port */ |
560 | tmp = ntohs(uh->dest) - LOWPAN_NHC_UDP_4BIT_PORT + | 550 | tmp = ntohs(uh->dest) - LOWPAN_NHC_UDP_4BIT_PORT + |
561 | ((ntohs(uh->source) - LOWPAN_NHC_UDP_4BIT_PORT) << 4); | 551 | ((ntohs(uh->source) - LOWPAN_NHC_UDP_4BIT_PORT) << 4); |
562 | lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp)); | 552 | lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp)); |
563 | } else if ((ntohs(uh->dest) & LOWPAN_NHC_UDP_8BIT_MASK) == | 553 | } else if ((ntohs(uh->dest) & LOWPAN_NHC_UDP_8BIT_MASK) == |
564 | LOWPAN_NHC_UDP_8BIT_PORT) { | 554 | LOWPAN_NHC_UDP_8BIT_PORT) { |
565 | pr_debug("UDP header: remove 8 bits of dest\n"); | 555 | pr_debug("UDP header: remove 8 bits of dest\n"); |
566 | /* compression value */ | 556 | /* compression value */ |
567 | tmp = LOWPAN_NHC_UDP_CS_P_01; | 557 | tmp = LOWPAN_NHC_UDP_CS_P_01; |
568 | lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp)); | 558 | lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp)); |
569 | /* source port */ | 559 | /* source port */ |
570 | lowpan_push_hc_data(hc06_ptr, &uh->source, sizeof(uh->source)); | 560 | lowpan_push_hc_data(hc_ptr, &uh->source, sizeof(uh->source)); |
571 | /* destination port */ | 561 | /* destination port */ |
572 | tmp = ntohs(uh->dest) - LOWPAN_NHC_UDP_8BIT_PORT; | 562 | tmp = ntohs(uh->dest) - LOWPAN_NHC_UDP_8BIT_PORT; |
573 | lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp)); | 563 | lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp)); |
574 | } else if ((ntohs(uh->source) & LOWPAN_NHC_UDP_8BIT_MASK) == | 564 | } else if ((ntohs(uh->source) & LOWPAN_NHC_UDP_8BIT_MASK) == |
575 | LOWPAN_NHC_UDP_8BIT_PORT) { | 565 | LOWPAN_NHC_UDP_8BIT_PORT) { |
576 | pr_debug("UDP header: remove 8 bits of source\n"); | 566 | pr_debug("UDP header: remove 8 bits of source\n"); |
577 | /* compression value */ | 567 | /* compression value */ |
578 | tmp = LOWPAN_NHC_UDP_CS_P_10; | 568 | tmp = LOWPAN_NHC_UDP_CS_P_10; |
579 | lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp)); | 569 | lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp)); |
580 | /* source port */ | 570 | /* source port */ |
581 | tmp = ntohs(uh->source) - LOWPAN_NHC_UDP_8BIT_PORT; | 571 | tmp = ntohs(uh->source) - LOWPAN_NHC_UDP_8BIT_PORT; |
582 | lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp)); | 572 | lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp)); |
583 | /* destination port */ | 573 | /* destination port */ |
584 | lowpan_push_hc_data(hc06_ptr, &uh->dest, sizeof(uh->dest)); | 574 | lowpan_push_hc_data(hc_ptr, &uh->dest, sizeof(uh->dest)); |
585 | } else { | 575 | } else { |
586 | pr_debug("UDP header: can't compress\n"); | 576 | pr_debug("UDP header: can't compress\n"); |
587 | /* compression value */ | 577 | /* compression value */ |
588 | tmp = LOWPAN_NHC_UDP_CS_P_00; | 578 | tmp = LOWPAN_NHC_UDP_CS_P_00; |
589 | lowpan_push_hc_data(hc06_ptr, &tmp, sizeof(tmp)); | 579 | lowpan_push_hc_data(hc_ptr, &tmp, sizeof(tmp)); |
590 | /* source port */ | 580 | /* source port */ |
591 | lowpan_push_hc_data(hc06_ptr, &uh->source, sizeof(uh->source)); | 581 | lowpan_push_hc_data(hc_ptr, &uh->source, sizeof(uh->source)); |
592 | /* destination port */ | 582 | /* destination port */ |
593 | lowpan_push_hc_data(hc06_ptr, &uh->dest, sizeof(uh->dest)); | 583 | lowpan_push_hc_data(hc_ptr, &uh->dest, sizeof(uh->dest)); |
594 | } | 584 | } |
595 | 585 | ||
596 | /* checksum is always inline */ | 586 | /* checksum is always inline */ |
597 | lowpan_push_hc_data(hc06_ptr, &uh->check, sizeof(uh->check)); | 587 | lowpan_push_hc_data(hc_ptr, &uh->check, sizeof(uh->check)); |
598 | 588 | ||
599 | /* skip the UDP header */ | 589 | /* skip the UDP header */ |
600 | skb_pull(skb, sizeof(struct udphdr)); | 590 | skb_pull(skb, sizeof(struct udphdr)); |
601 | } | 591 | } |
602 | 592 | ||
603 | int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev, | 593 | int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev, |
604 | unsigned short type, const void *_daddr, | 594 | unsigned short type, const void *_daddr, |
605 | const void *_saddr, unsigned int len) | 595 | const void *_saddr, unsigned int len) |
606 | { | 596 | { |
607 | u8 tmp, iphc0, iphc1, *hc06_ptr; | 597 | u8 tmp, iphc0, iphc1, *hc_ptr; |
608 | struct ipv6hdr *hdr; | 598 | struct ipv6hdr *hdr; |
609 | u8 head[100] = {}; | 599 | u8 head[100] = {}; |
600 | int addr_type; | ||
610 | 601 | ||
611 | if (type != ETH_P_IPV6) | 602 | if (type != ETH_P_IPV6) |
612 | return -EINVAL; | 603 | return -EINVAL; |
613 | 604 | ||
614 | hdr = ipv6_hdr(skb); | 605 | hdr = ipv6_hdr(skb); |
615 | hc06_ptr = head + 2; | 606 | hc_ptr = head + 2; |
616 | 607 | ||
617 | pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n" | 608 | pr_debug("IPv6 header dump:\n\tversion = %d\n\tlength = %d\n" |
618 | "\tnexthdr = 0x%02x\n\thop_lim = %d\n\tdest = %pI6c\n", | 609 | "\tnexthdr = 0x%02x\n\thop_lim = %d\n\tdest = %pI6c\n", |
619 | hdr->version, ntohs(hdr->payload_len), hdr->nexthdr, | 610 | hdr->version, ntohs(hdr->payload_len), hdr->nexthdr, |
620 | hdr->hop_limit, &hdr->daddr); | 611 | hdr->hop_limit, &hdr->daddr); |
621 | 612 | ||
622 | raw_dump_table(__func__, "raw skb network header dump", | 613 | raw_dump_table(__func__, "raw skb network header dump", |
623 | skb_network_header(skb), sizeof(struct ipv6hdr)); | 614 | skb_network_header(skb), sizeof(struct ipv6hdr)); |
624 | 615 | ||
625 | /* | 616 | /* As we copy some bit-length fields, in the IPHC encoding bytes, |
626 | * As we copy some bit-length fields, in the IPHC encoding bytes, | ||
627 | * we sometimes use |= | 617 | * we sometimes use |= |
628 | * If the field is 0, and the current bit value in memory is 1, | 618 | * If the field is 0, and the current bit value in memory is 1, |
629 | * this does not work. We therefore reset the IPHC encoding here | 619 | * this does not work. We therefore reset the IPHC encoding here |
@@ -638,49 +628,47 @@ int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev, | |||
638 | raw_dump_inline(__func__, "daddr", | 628 | raw_dump_inline(__func__, "daddr", |
639 | (unsigned char *)_daddr, IEEE802154_ADDR_LEN); | 629 | (unsigned char *)_daddr, IEEE802154_ADDR_LEN); |
640 | 630 | ||
641 | raw_dump_table(__func__, | 631 | raw_dump_table(__func__, "sending raw skb network uncompressed packet", |
642 | "sending raw skb network uncompressed packet", | 632 | skb->data, skb->len); |
643 | skb->data, skb->len); | ||
644 | 633 | ||
645 | /* | 634 | /* Traffic class, flow label |
646 | * Traffic class, flow label | ||
647 | * If flow label is 0, compress it. If traffic class is 0, compress it | 635 | * If flow label is 0, compress it. If traffic class is 0, compress it |
648 | * We have to process both in the same time as the offset of traffic | 636 | * We have to process both in the same time as the offset of traffic |
649 | * class depends on the presence of version and flow label | 637 | * class depends on the presence of version and flow label |
650 | */ | 638 | */ |
651 | 639 | ||
652 | /* hc06 format of TC is ECN | DSCP , original one is DSCP | ECN */ | 640 | /* hc format of TC is ECN | DSCP , original one is DSCP | ECN */ |
653 | tmp = (hdr->priority << 4) | (hdr->flow_lbl[0] >> 4); | 641 | tmp = (hdr->priority << 4) | (hdr->flow_lbl[0] >> 4); |
654 | tmp = ((tmp & 0x03) << 6) | (tmp >> 2); | 642 | tmp = ((tmp & 0x03) << 6) | (tmp >> 2); |
655 | 643 | ||
656 | if (((hdr->flow_lbl[0] & 0x0F) == 0) && | 644 | if (((hdr->flow_lbl[0] & 0x0F) == 0) && |
657 | (hdr->flow_lbl[1] == 0) && (hdr->flow_lbl[2] == 0)) { | 645 | (hdr->flow_lbl[1] == 0) && (hdr->flow_lbl[2] == 0)) { |
658 | /* flow label can be compressed */ | 646 | /* flow label can be compressed */ |
659 | iphc0 |= LOWPAN_IPHC_FL_C; | 647 | iphc0 |= LOWPAN_IPHC_FL_C; |
660 | if ((hdr->priority == 0) && | 648 | if ((hdr->priority == 0) && |
661 | ((hdr->flow_lbl[0] & 0xF0) == 0)) { | 649 | ((hdr->flow_lbl[0] & 0xF0) == 0)) { |
662 | /* compress (elide) all */ | 650 | /* compress (elide) all */ |
663 | iphc0 |= LOWPAN_IPHC_TC_C; | 651 | iphc0 |= LOWPAN_IPHC_TC_C; |
664 | } else { | 652 | } else { |
665 | /* compress only the flow label */ | 653 | /* compress only the flow label */ |
666 | *hc06_ptr = tmp; | 654 | *hc_ptr = tmp; |
667 | hc06_ptr += 1; | 655 | hc_ptr += 1; |
668 | } | 656 | } |
669 | } else { | 657 | } else { |
670 | /* Flow label cannot be compressed */ | 658 | /* Flow label cannot be compressed */ |
671 | if ((hdr->priority == 0) && | 659 | if ((hdr->priority == 0) && |
672 | ((hdr->flow_lbl[0] & 0xF0) == 0)) { | 660 | ((hdr->flow_lbl[0] & 0xF0) == 0)) { |
673 | /* compress only traffic class */ | 661 | /* compress only traffic class */ |
674 | iphc0 |= LOWPAN_IPHC_TC_C; | 662 | iphc0 |= LOWPAN_IPHC_TC_C; |
675 | *hc06_ptr = (tmp & 0xc0) | (hdr->flow_lbl[0] & 0x0F); | 663 | *hc_ptr = (tmp & 0xc0) | (hdr->flow_lbl[0] & 0x0F); |
676 | memcpy(hc06_ptr + 1, &hdr->flow_lbl[1], 2); | 664 | memcpy(hc_ptr + 1, &hdr->flow_lbl[1], 2); |
677 | hc06_ptr += 3; | 665 | hc_ptr += 3; |
678 | } else { | 666 | } else { |
679 | /* compress nothing */ | 667 | /* compress nothing */ |
680 | memcpy(hc06_ptr, hdr, 4); | 668 | memcpy(hc_ptr, hdr, 4); |
681 | /* replace the top byte with new ECN | DSCP format */ | 669 | /* replace the top byte with new ECN | DSCP format */ |
682 | *hc06_ptr = tmp; | 670 | *hc_ptr = tmp; |
683 | hc06_ptr += 4; | 671 | hc_ptr += 4; |
684 | } | 672 | } |
685 | } | 673 | } |
686 | 674 | ||
@@ -690,13 +678,11 @@ int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev, | |||
690 | if (hdr->nexthdr == UIP_PROTO_UDP) | 678 | if (hdr->nexthdr == UIP_PROTO_UDP) |
691 | iphc0 |= LOWPAN_IPHC_NH_C; | 679 | iphc0 |= LOWPAN_IPHC_NH_C; |
692 | 680 | ||
693 | if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) { | 681 | if ((iphc0 & LOWPAN_IPHC_NH_C) == 0) |
694 | *hc06_ptr = hdr->nexthdr; | 682 | lowpan_push_hc_data(&hc_ptr, &hdr->nexthdr, |
695 | hc06_ptr += 1; | 683 | sizeof(hdr->nexthdr)); |
696 | } | ||
697 | 684 | ||
698 | /* | 685 | /* Hop limit |
699 | * Hop limit | ||
700 | * if 1: compress, encoding is 01 | 686 | * if 1: compress, encoding is 01 |
701 | * if 64: compress, encoding is 10 | 687 | * if 64: compress, encoding is 10 |
702 | * if 255: compress, encoding is 11 | 688 | * if 255: compress, encoding is 11 |
@@ -713,87 +699,89 @@ int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev, | |||
713 | iphc0 |= LOWPAN_IPHC_TTL_255; | 699 | iphc0 |= LOWPAN_IPHC_TTL_255; |
714 | break; | 700 | break; |
715 | default: | 701 | default: |
716 | *hc06_ptr = hdr->hop_limit; | 702 | lowpan_push_hc_data(&hc_ptr, &hdr->hop_limit, |
717 | hc06_ptr += 1; | 703 | sizeof(hdr->hop_limit)); |
718 | break; | ||
719 | } | 704 | } |
720 | 705 | ||
706 | addr_type = ipv6_addr_type(&hdr->saddr); | ||
721 | /* source address compression */ | 707 | /* source address compression */ |
722 | if (is_addr_unspecified(&hdr->saddr)) { | 708 | if (addr_type == IPV6_ADDR_ANY) { |
723 | pr_debug("source address is unspecified, setting SAC\n"); | 709 | pr_debug("source address is unspecified, setting SAC\n"); |
724 | iphc1 |= LOWPAN_IPHC_SAC; | 710 | iphc1 |= LOWPAN_IPHC_SAC; |
725 | /* TODO: context lookup */ | ||
726 | } else if (is_addr_link_local(&hdr->saddr)) { | ||
727 | iphc1 |= lowpan_compress_addr_64(&hc06_ptr, | ||
728 | LOWPAN_IPHC_SAM_BIT, &hdr->saddr, _saddr); | ||
729 | pr_debug("source address unicast link-local %pI6c " | ||
730 | "iphc1 0x%02x\n", &hdr->saddr, iphc1); | ||
731 | } else { | 711 | } else { |
732 | pr_debug("send the full source address\n"); | 712 | if (addr_type & IPV6_ADDR_LINKLOCAL) { |
733 | memcpy(hc06_ptr, &hdr->saddr.s6_addr16[0], 16); | 713 | iphc1 |= lowpan_compress_addr_64(&hc_ptr, |
734 | hc06_ptr += 16; | 714 | LOWPAN_IPHC_SAM_BIT, |
715 | &hdr->saddr, _saddr); | ||
716 | pr_debug("source address unicast link-local %pI6c iphc1 0x%02x\n", | ||
717 | &hdr->saddr, iphc1); | ||
718 | } else { | ||
719 | pr_debug("send the full source address\n"); | ||
720 | lowpan_push_hc_data(&hc_ptr, hdr->saddr.s6_addr, 16); | ||
721 | } | ||
735 | } | 722 | } |
736 | 723 | ||
724 | addr_type = ipv6_addr_type(&hdr->daddr); | ||
737 | /* destination address compression */ | 725 | /* destination address compression */ |
738 | if (is_addr_mcast(&hdr->daddr)) { | 726 | if (addr_type & IPV6_ADDR_MULTICAST) { |
739 | pr_debug("destination address is multicast: "); | 727 | pr_debug("destination address is multicast: "); |
740 | iphc1 |= LOWPAN_IPHC_M; | 728 | iphc1 |= LOWPAN_IPHC_M; |
741 | if (lowpan_is_mcast_addr_compressable8(&hdr->daddr)) { | 729 | if (lowpan_is_mcast_addr_compressable8(&hdr->daddr)) { |
742 | pr_debug("compressed to 1 octet\n"); | 730 | pr_debug("compressed to 1 octet\n"); |
743 | iphc1 |= LOWPAN_IPHC_DAM_11; | 731 | iphc1 |= LOWPAN_IPHC_DAM_11; |
744 | /* use last byte */ | 732 | /* use last byte */ |
745 | *hc06_ptr = hdr->daddr.s6_addr[15]; | 733 | lowpan_push_hc_data(&hc_ptr, |
746 | hc06_ptr += 1; | 734 | &hdr->daddr.s6_addr[15], 1); |
747 | } else if (lowpan_is_mcast_addr_compressable32(&hdr->daddr)) { | 735 | } else if (lowpan_is_mcast_addr_compressable32(&hdr->daddr)) { |
748 | pr_debug("compressed to 4 octets\n"); | 736 | pr_debug("compressed to 4 octets\n"); |
749 | iphc1 |= LOWPAN_IPHC_DAM_10; | 737 | iphc1 |= LOWPAN_IPHC_DAM_10; |
750 | /* second byte + the last three */ | 738 | /* second byte + the last three */ |
751 | *hc06_ptr = hdr->daddr.s6_addr[1]; | 739 | lowpan_push_hc_data(&hc_ptr, |
752 | memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[13], 3); | 740 | &hdr->daddr.s6_addr[1], 1); |
753 | hc06_ptr += 4; | 741 | lowpan_push_hc_data(&hc_ptr, |
742 | &hdr->daddr.s6_addr[13], 3); | ||
754 | } else if (lowpan_is_mcast_addr_compressable48(&hdr->daddr)) { | 743 | } else if (lowpan_is_mcast_addr_compressable48(&hdr->daddr)) { |
755 | pr_debug("compressed to 6 octets\n"); | 744 | pr_debug("compressed to 6 octets\n"); |
756 | iphc1 |= LOWPAN_IPHC_DAM_01; | 745 | iphc1 |= LOWPAN_IPHC_DAM_01; |
757 | /* second byte + the last five */ | 746 | /* second byte + the last five */ |
758 | *hc06_ptr = hdr->daddr.s6_addr[1]; | 747 | lowpan_push_hc_data(&hc_ptr, |
759 | memcpy(hc06_ptr + 1, &hdr->daddr.s6_addr[11], 5); | 748 | &hdr->daddr.s6_addr[1], 1); |
760 | hc06_ptr += 6; | 749 | lowpan_push_hc_data(&hc_ptr, |
750 | &hdr->daddr.s6_addr[11], 5); | ||
761 | } else { | 751 | } else { |
762 | pr_debug("using full address\n"); | 752 | pr_debug("using full address\n"); |
763 | iphc1 |= LOWPAN_IPHC_DAM_00; | 753 | iphc1 |= LOWPAN_IPHC_DAM_00; |
764 | memcpy(hc06_ptr, &hdr->daddr.s6_addr[0], 16); | 754 | lowpan_push_hc_data(&hc_ptr, hdr->daddr.s6_addr, 16); |
765 | hc06_ptr += 16; | ||
766 | } | 755 | } |
767 | } else { | 756 | } else { |
768 | /* TODO: context lookup */ | 757 | if (addr_type & IPV6_ADDR_LINKLOCAL) { |
769 | if (is_addr_link_local(&hdr->daddr)) { | 758 | /* TODO: context lookup */ |
770 | iphc1 |= lowpan_compress_addr_64(&hc06_ptr, | 759 | iphc1 |= lowpan_compress_addr_64(&hc_ptr, |
771 | LOWPAN_IPHC_DAM_BIT, &hdr->daddr, _daddr); | 760 | LOWPAN_IPHC_DAM_BIT, &hdr->daddr, _daddr); |
772 | pr_debug("dest address unicast link-local %pI6c " | 761 | pr_debug("dest address unicast link-local %pI6c " |
773 | "iphc1 0x%02x\n", &hdr->daddr, iphc1); | 762 | "iphc1 0x%02x\n", &hdr->daddr, iphc1); |
774 | } else { | 763 | } else { |
775 | pr_debug("dest address unicast %pI6c\n", &hdr->daddr); | 764 | pr_debug("dest address unicast %pI6c\n", &hdr->daddr); |
776 | memcpy(hc06_ptr, &hdr->daddr.s6_addr16[0], 16); | 765 | lowpan_push_hc_data(&hc_ptr, hdr->daddr.s6_addr, 16); |
777 | hc06_ptr += 16; | ||
778 | } | 766 | } |
779 | } | 767 | } |
780 | 768 | ||
781 | /* UDP header compression */ | 769 | /* UDP header compression */ |
782 | if (hdr->nexthdr == UIP_PROTO_UDP) | 770 | if (hdr->nexthdr == UIP_PROTO_UDP) |
783 | compress_udp_header(&hc06_ptr, skb); | 771 | compress_udp_header(&hc_ptr, skb); |
784 | 772 | ||
785 | head[0] = iphc0; | 773 | head[0] = iphc0; |
786 | head[1] = iphc1; | 774 | head[1] = iphc1; |
787 | 775 | ||
788 | skb_pull(skb, sizeof(struct ipv6hdr)); | 776 | skb_pull(skb, sizeof(struct ipv6hdr)); |
789 | skb_reset_transport_header(skb); | 777 | skb_reset_transport_header(skb); |
790 | memcpy(skb_push(skb, hc06_ptr - head), head, hc06_ptr - head); | 778 | memcpy(skb_push(skb, hc_ptr - head), head, hc_ptr - head); |
791 | skb_reset_network_header(skb); | 779 | skb_reset_network_header(skb); |
792 | 780 | ||
793 | pr_debug("header len %d skb %u\n", (int)(hc06_ptr - head), skb->len); | 781 | pr_debug("header len %d skb %u\n", (int)(hc_ptr - head), skb->len); |
794 | 782 | ||
795 | raw_dump_table(__func__, "raw skb data dump compressed", | 783 | raw_dump_table(__func__, "raw skb data dump compressed", |
796 | skb->data, skb->len); | 784 | skb->data, skb->len); |
797 | return 0; | 785 | return 0; |
798 | } | 786 | } |
799 | EXPORT_SYMBOL_GPL(lowpan_header_compress); | 787 | EXPORT_SYMBOL_GPL(lowpan_header_compress); |
diff --git a/net/802/fc.c b/net/802/fc.c index 05eea6b98bb8..7c174b6750cd 100644 --- a/net/802/fc.c +++ b/net/802/fc.c | |||
@@ -126,6 +126,6 @@ static void fc_setup(struct net_device *dev) | |||
126 | */ | 126 | */ |
127 | struct net_device *alloc_fcdev(int sizeof_priv) | 127 | struct net_device *alloc_fcdev(int sizeof_priv) |
128 | { | 128 | { |
129 | return alloc_netdev(sizeof_priv, "fc%d", fc_setup); | 129 | return alloc_netdev(sizeof_priv, "fc%d", NET_NAME_UNKNOWN, fc_setup); |
130 | } | 130 | } |
131 | EXPORT_SYMBOL(alloc_fcdev); | 131 | EXPORT_SYMBOL(alloc_fcdev); |
diff --git a/net/802/fddi.c b/net/802/fddi.c index 9cda40661e0d..59e7346f1193 100644 --- a/net/802/fddi.c +++ b/net/802/fddi.c | |||
@@ -207,7 +207,8 @@ static void fddi_setup(struct net_device *dev) | |||
207 | */ | 207 | */ |
208 | struct net_device *alloc_fddidev(int sizeof_priv) | 208 | struct net_device *alloc_fddidev(int sizeof_priv) |
209 | { | 209 | { |
210 | return alloc_netdev(sizeof_priv, "fddi%d", fddi_setup); | 210 | return alloc_netdev(sizeof_priv, "fddi%d", NET_NAME_UNKNOWN, |
211 | fddi_setup); | ||
211 | } | 212 | } |
212 | EXPORT_SYMBOL(alloc_fddidev); | 213 | EXPORT_SYMBOL(alloc_fddidev); |
213 | 214 | ||
diff --git a/net/802/hippi.c b/net/802/hippi.c index 5ff2a718ddca..2e03f8259dd5 100644 --- a/net/802/hippi.c +++ b/net/802/hippi.c | |||
@@ -228,7 +228,8 @@ static void hippi_setup(struct net_device *dev) | |||
228 | 228 | ||
229 | struct net_device *alloc_hippi_dev(int sizeof_priv) | 229 | struct net_device *alloc_hippi_dev(int sizeof_priv) |
230 | { | 230 | { |
231 | return alloc_netdev(sizeof_priv, "hip%d", hippi_setup); | 231 | return alloc_netdev(sizeof_priv, "hip%d", NET_NAME_UNKNOWN, |
232 | hippi_setup); | ||
232 | } | 233 | } |
233 | 234 | ||
234 | EXPORT_SYMBOL(alloc_hippi_dev); | 235 | EXPORT_SYMBOL(alloc_hippi_dev); |
diff --git a/net/8021q/vlan.c b/net/8021q/vlan.c index 44ebd5c2cd4a..64c6bed4a3d3 100644 --- a/net/8021q/vlan.c +++ b/net/8021q/vlan.c | |||
@@ -250,7 +250,8 @@ static int register_vlan_device(struct net_device *real_dev, u16 vlan_id) | |||
250 | snprintf(name, IFNAMSIZ, "vlan%.4i", vlan_id); | 250 | snprintf(name, IFNAMSIZ, "vlan%.4i", vlan_id); |
251 | } | 251 | } |
252 | 252 | ||
253 | new_dev = alloc_netdev(sizeof(struct vlan_dev_priv), name, vlan_setup); | 253 | new_dev = alloc_netdev(sizeof(struct vlan_dev_priv), name, |
254 | NET_NAME_UNKNOWN, vlan_setup); | ||
254 | 255 | ||
255 | if (new_dev == NULL) | 256 | if (new_dev == NULL) |
256 | return -ENOBUFS; | 257 | return -ENOBUFS; |
@@ -324,23 +325,24 @@ static void vlan_transfer_features(struct net_device *dev, | |||
324 | netdev_update_features(vlandev); | 325 | netdev_update_features(vlandev); |
325 | } | 326 | } |
326 | 327 | ||
327 | static void __vlan_device_event(struct net_device *dev, unsigned long event) | 328 | static int __vlan_device_event(struct net_device *dev, unsigned long event) |
328 | { | 329 | { |
330 | int err = 0; | ||
331 | |||
329 | switch (event) { | 332 | switch (event) { |
330 | case NETDEV_CHANGENAME: | 333 | case NETDEV_CHANGENAME: |
331 | vlan_proc_rem_dev(dev); | 334 | vlan_proc_rem_dev(dev); |
332 | if (vlan_proc_add_dev(dev) < 0) | 335 | err = vlan_proc_add_dev(dev); |
333 | pr_warn("failed to change proc name for %s\n", | ||
334 | dev->name); | ||
335 | break; | 336 | break; |
336 | case NETDEV_REGISTER: | 337 | case NETDEV_REGISTER: |
337 | if (vlan_proc_add_dev(dev) < 0) | 338 | err = vlan_proc_add_dev(dev); |
338 | pr_warn("failed to add proc entry for %s\n", dev->name); | ||
339 | break; | 339 | break; |
340 | case NETDEV_UNREGISTER: | 340 | case NETDEV_UNREGISTER: |
341 | vlan_proc_rem_dev(dev); | 341 | vlan_proc_rem_dev(dev); |
342 | break; | 342 | break; |
343 | } | 343 | } |
344 | |||
345 | return err; | ||
344 | } | 346 | } |
345 | 347 | ||
346 | static int vlan_device_event(struct notifier_block *unused, unsigned long event, | 348 | static int vlan_device_event(struct notifier_block *unused, unsigned long event, |
@@ -355,8 +357,12 @@ static int vlan_device_event(struct notifier_block *unused, unsigned long event, | |||
355 | bool last = false; | 357 | bool last = false; |
356 | LIST_HEAD(list); | 358 | LIST_HEAD(list); |
357 | 359 | ||
358 | if (is_vlan_dev(dev)) | 360 | if (is_vlan_dev(dev)) { |
359 | __vlan_device_event(dev, event); | 361 | int err = __vlan_device_event(dev, event); |
362 | |||
363 | if (err) | ||
364 | return notifier_from_errno(err); | ||
365 | } | ||
360 | 366 | ||
361 | if ((event == NETDEV_UP) && | 367 | if ((event == NETDEV_UP) && |
362 | (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) { | 368 | (dev->features & NETIF_F_HW_VLAN_CTAG_FILTER)) { |
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index 75d427763992..90cc2bdd4064 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c | |||
@@ -112,59 +112,6 @@ __be16 vlan_dev_vlan_proto(const struct net_device *dev) | |||
112 | } | 112 | } |
113 | EXPORT_SYMBOL(vlan_dev_vlan_proto); | 113 | EXPORT_SYMBOL(vlan_dev_vlan_proto); |
114 | 114 | ||
115 | static struct sk_buff *vlan_reorder_header(struct sk_buff *skb) | ||
116 | { | ||
117 | if (skb_cow(skb, skb_headroom(skb)) < 0) { | ||
118 | kfree_skb(skb); | ||
119 | return NULL; | ||
120 | } | ||
121 | |||
122 | memmove(skb->data - ETH_HLEN, skb->data - VLAN_ETH_HLEN, 2 * ETH_ALEN); | ||
123 | skb->mac_header += VLAN_HLEN; | ||
124 | return skb; | ||
125 | } | ||
126 | |||
127 | struct sk_buff *vlan_untag(struct sk_buff *skb) | ||
128 | { | ||
129 | struct vlan_hdr *vhdr; | ||
130 | u16 vlan_tci; | ||
131 | |||
132 | if (unlikely(vlan_tx_tag_present(skb))) { | ||
133 | /* vlan_tci is already set-up so leave this for another time */ | ||
134 | return skb; | ||
135 | } | ||
136 | |||
137 | skb = skb_share_check(skb, GFP_ATOMIC); | ||
138 | if (unlikely(!skb)) | ||
139 | goto err_free; | ||
140 | |||
141 | if (unlikely(!pskb_may_pull(skb, VLAN_HLEN))) | ||
142 | goto err_free; | ||
143 | |||
144 | vhdr = (struct vlan_hdr *) skb->data; | ||
145 | vlan_tci = ntohs(vhdr->h_vlan_TCI); | ||
146 | __vlan_hwaccel_put_tag(skb, skb->protocol, vlan_tci); | ||
147 | |||
148 | skb_pull_rcsum(skb, VLAN_HLEN); | ||
149 | vlan_set_encap_proto(skb, vhdr); | ||
150 | |||
151 | skb = vlan_reorder_header(skb); | ||
152 | if (unlikely(!skb)) | ||
153 | goto err_free; | ||
154 | |||
155 | skb_reset_network_header(skb); | ||
156 | skb_reset_transport_header(skb); | ||
157 | skb_reset_mac_len(skb); | ||
158 | |||
159 | return skb; | ||
160 | |||
161 | err_free: | ||
162 | kfree_skb(skb); | ||
163 | return NULL; | ||
164 | } | ||
165 | EXPORT_SYMBOL(vlan_untag); | ||
166 | |||
167 | |||
168 | /* | 115 | /* |
169 | * vlan info and vid list | 116 | * vlan info and vid list |
170 | */ | 117 | */ |
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index dd11f612e03e..35a6b6b15e8a 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
@@ -385,6 +385,8 @@ static int vlan_dev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
385 | case SIOCGMIIPHY: | 385 | case SIOCGMIIPHY: |
386 | case SIOCGMIIREG: | 386 | case SIOCGMIIREG: |
387 | case SIOCSMIIREG: | 387 | case SIOCSMIIREG: |
388 | case SIOCSHWTSTAMP: | ||
389 | case SIOCGHWTSTAMP: | ||
388 | if (netif_device_present(real_dev) && ops->ndo_do_ioctl) | 390 | if (netif_device_present(real_dev) && ops->ndo_do_ioctl) |
389 | err = ops->ndo_do_ioctl(real_dev, &ifrr, cmd); | 391 | err = ops->ndo_do_ioctl(real_dev, &ifrr, cmd); |
390 | break; | 392 | break; |
diff --git a/net/8021q/vlanproc.c b/net/8021q/vlanproc.c index 1d0e89213a28..ae63cf72a953 100644 --- a/net/8021q/vlanproc.c +++ b/net/8021q/vlanproc.c | |||
@@ -171,6 +171,8 @@ int vlan_proc_add_dev(struct net_device *vlandev) | |||
171 | struct vlan_dev_priv *vlan = vlan_dev_priv(vlandev); | 171 | struct vlan_dev_priv *vlan = vlan_dev_priv(vlandev); |
172 | struct vlan_net *vn = net_generic(dev_net(vlandev), vlan_net_id); | 172 | struct vlan_net *vn = net_generic(dev_net(vlandev), vlan_net_id); |
173 | 173 | ||
174 | if (!strcmp(vlandev->name, name_conf)) | ||
175 | return -EINVAL; | ||
174 | vlan->dent = | 176 | vlan->dent = |
175 | proc_create_data(vlandev->name, S_IFREG|S_IRUSR|S_IWUSR, | 177 | proc_create_data(vlandev->name, S_IFREG|S_IRUSR|S_IWUSR, |
176 | vn->proc_vlan_dir, &vlandev_fops, vlandev); | 178 | vn->proc_vlan_dir, &vlandev_fops, vlandev); |
diff --git a/net/9p/client.c b/net/9p/client.c index 0004cbaac4a4..e86a9bea1d16 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
@@ -959,7 +959,6 @@ static int p9_client_version(struct p9_client *c) | |||
959 | break; | 959 | break; |
960 | default: | 960 | default: |
961 | return -EINVAL; | 961 | return -EINVAL; |
962 | break; | ||
963 | } | 962 | } |
964 | 963 | ||
965 | if (IS_ERR(req)) | 964 | if (IS_ERR(req)) |
diff --git a/net/Kconfig b/net/Kconfig index d92afe4204d9..4051fdfa4367 100644 --- a/net/Kconfig +++ b/net/Kconfig | |||
@@ -214,6 +214,7 @@ source "drivers/net/appletalk/Kconfig" | |||
214 | source "net/x25/Kconfig" | 214 | source "net/x25/Kconfig" |
215 | source "net/lapb/Kconfig" | 215 | source "net/lapb/Kconfig" |
216 | source "net/phonet/Kconfig" | 216 | source "net/phonet/Kconfig" |
217 | source "net/6lowpan/Kconfig" | ||
217 | source "net/ieee802154/Kconfig" | 218 | source "net/ieee802154/Kconfig" |
218 | source "net/mac802154/Kconfig" | 219 | source "net/mac802154/Kconfig" |
219 | source "net/sched/Kconfig" | 220 | source "net/sched/Kconfig" |
diff --git a/net/Makefile b/net/Makefile index cbbbe6d657ca..7ed1970074b0 100644 --- a/net/Makefile +++ b/net/Makefile | |||
@@ -57,7 +57,8 @@ obj-$(CONFIG_CAIF) += caif/ | |||
57 | ifneq ($(CONFIG_DCB),) | 57 | ifneq ($(CONFIG_DCB),) |
58 | obj-y += dcb/ | 58 | obj-y += dcb/ |
59 | endif | 59 | endif |
60 | obj-y += ieee802154/ | 60 | obj-$(CONFIG_6LOWPAN) += 6lowpan/ |
61 | obj-$(CONFIG_IEEE802154) += ieee802154/ | ||
61 | obj-$(CONFIG_MAC802154) += mac802154/ | 62 | obj-$(CONFIG_MAC802154) += mac802154/ |
62 | 63 | ||
63 | ifeq ($(CONFIG_NET),y) | 64 | ifeq ($(CONFIG_NET),y) |
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index bfcf6be1d665..c00897f65a31 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c | |||
@@ -1805,7 +1805,7 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
1805 | long amount = 0; | 1805 | long amount = 0; |
1806 | 1806 | ||
1807 | if (skb) | 1807 | if (skb) |
1808 | amount = skb->len - sizeof(struct ddpehdr); | 1808 | amount = skb->len - sizeof(struct ddpehdr); |
1809 | rc = put_user(amount, (int __user *)argp); | 1809 | rc = put_user(amount, (int __user *)argp); |
1810 | break; | 1810 | break; |
1811 | } | 1811 | } |
diff --git a/net/appletalk/dev.c b/net/appletalk/dev.c index 6c8016f61866..e4158b8b926d 100644 --- a/net/appletalk/dev.c +++ b/net/appletalk/dev.c | |||
@@ -39,6 +39,7 @@ static void ltalk_setup(struct net_device *dev) | |||
39 | 39 | ||
40 | struct net_device *alloc_ltalkdev(int sizeof_priv) | 40 | struct net_device *alloc_ltalkdev(int sizeof_priv) |
41 | { | 41 | { |
42 | return alloc_netdev(sizeof_priv, "lt%d", ltalk_setup); | 42 | return alloc_netdev(sizeof_priv, "lt%d", NET_NAME_UNKNOWN, |
43 | ltalk_setup); | ||
43 | } | 44 | } |
44 | EXPORT_SYMBOL(alloc_ltalkdev); | 45 | EXPORT_SYMBOL(alloc_ltalkdev); |
diff --git a/net/atm/br2684.c b/net/atm/br2684.c index 403e71fa88fe..cc78538d163b 100644 --- a/net/atm/br2684.c +++ b/net/atm/br2684.c | |||
@@ -682,8 +682,8 @@ static int br2684_create(void __user *arg) | |||
682 | 682 | ||
683 | netdev = alloc_netdev(sizeof(struct br2684_dev), | 683 | netdev = alloc_netdev(sizeof(struct br2684_dev), |
684 | ni.ifname[0] ? ni.ifname : "nas%d", | 684 | ni.ifname[0] ? ni.ifname : "nas%d", |
685 | (payload == p_routed) ? | 685 | NET_NAME_UNKNOWN, |
686 | br2684_setup_routed : br2684_setup); | 686 | (payload == p_routed) ? br2684_setup_routed : br2684_setup); |
687 | if (!netdev) | 687 | if (!netdev) |
688 | return -ENOMEM; | 688 | return -ENOMEM; |
689 | 689 | ||
diff --git a/net/atm/clip.c b/net/atm/clip.c index ba291ce4bdff..46339040fef0 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c | |||
@@ -520,7 +520,8 @@ static int clip_create(int number) | |||
520 | if (PRIV(dev)->number >= number) | 520 | if (PRIV(dev)->number >= number) |
521 | number = PRIV(dev)->number + 1; | 521 | number = PRIV(dev)->number + 1; |
522 | } | 522 | } |
523 | dev = alloc_netdev(sizeof(struct clip_priv), "", clip_setup); | 523 | dev = alloc_netdev(sizeof(struct clip_priv), "", NET_NAME_UNKNOWN, |
524 | clip_setup); | ||
524 | if (!dev) | 525 | if (!dev) |
525 | return -ENOMEM; | 526 | return -ENOMEM; |
526 | clip_priv = PRIV(dev); | 527 | clip_priv = PRIV(dev); |
diff --git a/net/atm/lec.c b/net/atm/lec.c index 4c5b8ba0f84f..4b98f897044a 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c | |||
@@ -410,9 +410,11 @@ static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) | |||
410 | priv->lane2_ops = NULL; | 410 | priv->lane2_ops = NULL; |
411 | if (priv->lane_version > 1) | 411 | if (priv->lane_version > 1) |
412 | priv->lane2_ops = &lane2_ops; | 412 | priv->lane2_ops = &lane2_ops; |
413 | rtnl_lock(); | ||
413 | if (dev_set_mtu(dev, mesg->content.config.mtu)) | 414 | if (dev_set_mtu(dev, mesg->content.config.mtu)) |
414 | pr_info("%s: change_mtu to %d failed\n", | 415 | pr_info("%s: change_mtu to %d failed\n", |
415 | dev->name, mesg->content.config.mtu); | 416 | dev->name, mesg->content.config.mtu); |
417 | rtnl_unlock(); | ||
416 | priv->is_proxy = mesg->content.config.is_proxy; | 418 | priv->is_proxy = mesg->content.config.is_proxy; |
417 | break; | 419 | break; |
418 | case l_flush_tran_id: | 420 | case l_flush_tran_id: |
@@ -833,7 +835,6 @@ static void *lec_tbl_walk(struct lec_state *state, struct hlist_head *tbl, | |||
833 | loff_t *l) | 835 | loff_t *l) |
834 | { | 836 | { |
835 | struct hlist_node *e = state->node; | 837 | struct hlist_node *e = state->node; |
836 | struct lec_arp_table *tmp; | ||
837 | 838 | ||
838 | if (!e) | 839 | if (!e) |
839 | e = tbl->first; | 840 | e = tbl->first; |
@@ -842,9 +843,7 @@ static void *lec_tbl_walk(struct lec_state *state, struct hlist_head *tbl, | |||
842 | --*l; | 843 | --*l; |
843 | } | 844 | } |
844 | 845 | ||
845 | tmp = container_of(e, struct lec_arp_table, next); | 846 | for (; e; e = e->next) { |
846 | |||
847 | hlist_for_each_entry_from(tmp, next) { | ||
848 | if (--*l < 0) | 847 | if (--*l < 0) |
849 | break; | 848 | break; |
850 | } | 849 | } |
diff --git a/net/atm/svc.c b/net/atm/svc.c index d8e5d0c2ebbc..1ba23f5018e7 100644 --- a/net/atm/svc.c +++ b/net/atm/svc.c | |||
@@ -50,12 +50,12 @@ static void svc_disconnect(struct atm_vcc *vcc) | |||
50 | 50 | ||
51 | pr_debug("%p\n", vcc); | 51 | pr_debug("%p\n", vcc); |
52 | if (test_bit(ATM_VF_REGIS, &vcc->flags)) { | 52 | if (test_bit(ATM_VF_REGIS, &vcc->flags)) { |
53 | prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); | ||
54 | sigd_enq(vcc, as_close, NULL, NULL, NULL); | 53 | sigd_enq(vcc, as_close, NULL, NULL, NULL); |
55 | while (!test_bit(ATM_VF_RELEASED, &vcc->flags) && sigd) { | 54 | for (;;) { |
55 | prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); | ||
56 | if (test_bit(ATM_VF_RELEASED, &vcc->flags) || !sigd) | ||
57 | break; | ||
56 | schedule(); | 58 | schedule(); |
57 | prepare_to_wait(sk_sleep(sk), &wait, | ||
58 | TASK_UNINTERRUPTIBLE); | ||
59 | } | 59 | } |
60 | finish_wait(sk_sleep(sk), &wait); | 60 | finish_wait(sk_sleep(sk), &wait); |
61 | } | 61 | } |
@@ -126,11 +126,12 @@ static int svc_bind(struct socket *sock, struct sockaddr *sockaddr, | |||
126 | } | 126 | } |
127 | vcc->local = *addr; | 127 | vcc->local = *addr; |
128 | set_bit(ATM_VF_WAITING, &vcc->flags); | 128 | set_bit(ATM_VF_WAITING, &vcc->flags); |
129 | prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); | ||
130 | sigd_enq(vcc, as_bind, NULL, NULL, &vcc->local); | 129 | sigd_enq(vcc, as_bind, NULL, NULL, &vcc->local); |
131 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { | 130 | for (;;) { |
132 | schedule(); | ||
133 | prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); | 131 | prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); |
132 | if (!test_bit(ATM_VF_WAITING, &vcc->flags) || !sigd) | ||
133 | break; | ||
134 | schedule(); | ||
134 | } | 135 | } |
135 | finish_wait(sk_sleep(sk), &wait); | 136 | finish_wait(sk_sleep(sk), &wait); |
136 | clear_bit(ATM_VF_REGIS, &vcc->flags); /* doesn't count */ | 137 | clear_bit(ATM_VF_REGIS, &vcc->flags); /* doesn't count */ |
@@ -202,15 +203,14 @@ static int svc_connect(struct socket *sock, struct sockaddr *sockaddr, | |||
202 | } | 203 | } |
203 | vcc->remote = *addr; | 204 | vcc->remote = *addr; |
204 | set_bit(ATM_VF_WAITING, &vcc->flags); | 205 | set_bit(ATM_VF_WAITING, &vcc->flags); |
205 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | ||
206 | sigd_enq(vcc, as_connect, NULL, NULL, &vcc->remote); | 206 | sigd_enq(vcc, as_connect, NULL, NULL, &vcc->remote); |
207 | if (flags & O_NONBLOCK) { | 207 | if (flags & O_NONBLOCK) { |
208 | finish_wait(sk_sleep(sk), &wait); | ||
209 | sock->state = SS_CONNECTING; | 208 | sock->state = SS_CONNECTING; |
210 | error = -EINPROGRESS; | 209 | error = -EINPROGRESS; |
211 | goto out; | 210 | goto out; |
212 | } | 211 | } |
213 | error = 0; | 212 | error = 0; |
213 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | ||
214 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { | 214 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { |
215 | schedule(); | 215 | schedule(); |
216 | if (!signal_pending(current)) { | 216 | if (!signal_pending(current)) { |
@@ -297,11 +297,12 @@ static int svc_listen(struct socket *sock, int backlog) | |||
297 | goto out; | 297 | goto out; |
298 | } | 298 | } |
299 | set_bit(ATM_VF_WAITING, &vcc->flags); | 299 | set_bit(ATM_VF_WAITING, &vcc->flags); |
300 | prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); | ||
301 | sigd_enq(vcc, as_listen, NULL, NULL, &vcc->local); | 300 | sigd_enq(vcc, as_listen, NULL, NULL, &vcc->local); |
302 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { | 301 | for (;;) { |
303 | schedule(); | ||
304 | prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); | 302 | prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); |
303 | if (!test_bit(ATM_VF_WAITING, &vcc->flags) || !sigd) | ||
304 | break; | ||
305 | schedule(); | ||
305 | } | 306 | } |
306 | finish_wait(sk_sleep(sk), &wait); | 307 | finish_wait(sk_sleep(sk), &wait); |
307 | if (!sigd) { | 308 | if (!sigd) { |
@@ -387,15 +388,15 @@ static int svc_accept(struct socket *sock, struct socket *newsock, int flags) | |||
387 | } | 388 | } |
388 | /* wait should be short, so we ignore the non-blocking flag */ | 389 | /* wait should be short, so we ignore the non-blocking flag */ |
389 | set_bit(ATM_VF_WAITING, &new_vcc->flags); | 390 | set_bit(ATM_VF_WAITING, &new_vcc->flags); |
390 | prepare_to_wait(sk_sleep(sk_atm(new_vcc)), &wait, | ||
391 | TASK_UNINTERRUPTIBLE); | ||
392 | sigd_enq(new_vcc, as_accept, old_vcc, NULL, NULL); | 391 | sigd_enq(new_vcc, as_accept, old_vcc, NULL, NULL); |
393 | while (test_bit(ATM_VF_WAITING, &new_vcc->flags) && sigd) { | 392 | for (;;) { |
393 | prepare_to_wait(sk_sleep(sk_atm(new_vcc)), &wait, | ||
394 | TASK_UNINTERRUPTIBLE); | ||
395 | if (!test_bit(ATM_VF_WAITING, &new_vcc->flags) || !sigd) | ||
396 | break; | ||
394 | release_sock(sk); | 397 | release_sock(sk); |
395 | schedule(); | 398 | schedule(); |
396 | lock_sock(sk); | 399 | lock_sock(sk); |
397 | prepare_to_wait(sk_sleep(sk_atm(new_vcc)), &wait, | ||
398 | TASK_UNINTERRUPTIBLE); | ||
399 | } | 400 | } |
400 | finish_wait(sk_sleep(sk_atm(new_vcc)), &wait); | 401 | finish_wait(sk_sleep(sk_atm(new_vcc)), &wait); |
401 | if (!sigd) { | 402 | if (!sigd) { |
@@ -433,12 +434,14 @@ int svc_change_qos(struct atm_vcc *vcc, struct atm_qos *qos) | |||
433 | DEFINE_WAIT(wait); | 434 | DEFINE_WAIT(wait); |
434 | 435 | ||
435 | set_bit(ATM_VF_WAITING, &vcc->flags); | 436 | set_bit(ATM_VF_WAITING, &vcc->flags); |
436 | prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); | ||
437 | sigd_enq2(vcc, as_modify, NULL, NULL, &vcc->local, qos, 0); | 437 | sigd_enq2(vcc, as_modify, NULL, NULL, &vcc->local, qos, 0); |
438 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && | 438 | for (;;) { |
439 | !test_bit(ATM_VF_RELEASED, &vcc->flags) && sigd) { | ||
440 | schedule(); | ||
441 | prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); | 439 | prepare_to_wait(sk_sleep(sk), &wait, TASK_UNINTERRUPTIBLE); |
440 | if (!test_bit(ATM_VF_WAITING, &vcc->flags) || | ||
441 | test_bit(ATM_VF_RELEASED, &vcc->flags) || !sigd) { | ||
442 | break; | ||
443 | } | ||
444 | schedule(); | ||
442 | } | 445 | } |
443 | finish_wait(sk_sleep(sk), &wait); | 446 | finish_wait(sk_sleep(sk), &wait); |
444 | if (!sigd) | 447 | if (!sigd) |
@@ -529,18 +532,18 @@ static int svc_addparty(struct socket *sock, struct sockaddr *sockaddr, | |||
529 | 532 | ||
530 | lock_sock(sk); | 533 | lock_sock(sk); |
531 | set_bit(ATM_VF_WAITING, &vcc->flags); | 534 | set_bit(ATM_VF_WAITING, &vcc->flags); |
532 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | ||
533 | sigd_enq(vcc, as_addparty, NULL, NULL, | 535 | sigd_enq(vcc, as_addparty, NULL, NULL, |
534 | (struct sockaddr_atmsvc *) sockaddr); | 536 | (struct sockaddr_atmsvc *) sockaddr); |
535 | if (flags & O_NONBLOCK) { | 537 | if (flags & O_NONBLOCK) { |
536 | finish_wait(sk_sleep(sk), &wait); | ||
537 | error = -EINPROGRESS; | 538 | error = -EINPROGRESS; |
538 | goto out; | 539 | goto out; |
539 | } | 540 | } |
540 | pr_debug("added wait queue\n"); | 541 | pr_debug("added wait queue\n"); |
541 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { | 542 | for (;;) { |
542 | schedule(); | ||
543 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | 543 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
544 | if (!test_bit(ATM_VF_WAITING, &vcc->flags) || !sigd) | ||
545 | break; | ||
546 | schedule(); | ||
544 | } | 547 | } |
545 | finish_wait(sk_sleep(sk), &wait); | 548 | finish_wait(sk_sleep(sk), &wait); |
546 | error = xchg(&sk->sk_err_soft, 0); | 549 | error = xchg(&sk->sk_err_soft, 0); |
@@ -558,11 +561,12 @@ static int svc_dropparty(struct socket *sock, int ep_ref) | |||
558 | 561 | ||
559 | lock_sock(sk); | 562 | lock_sock(sk); |
560 | set_bit(ATM_VF_WAITING, &vcc->flags); | 563 | set_bit(ATM_VF_WAITING, &vcc->flags); |
561 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | ||
562 | sigd_enq2(vcc, as_dropparty, NULL, NULL, NULL, NULL, ep_ref); | 564 | sigd_enq2(vcc, as_dropparty, NULL, NULL, NULL, NULL, ep_ref); |
563 | while (test_bit(ATM_VF_WAITING, &vcc->flags) && sigd) { | 565 | for (;;) { |
564 | schedule(); | ||
565 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | 566 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
567 | if (!test_bit(ATM_VF_WAITING, &vcc->flags) || !sigd) | ||
568 | break; | ||
569 | schedule(); | ||
566 | } | 570 | } |
567 | finish_wait(sk_sleep(sk), &wait); | 571 | finish_wait(sk_sleep(sk), &wait); |
568 | if (!sigd) { | 572 | if (!sigd) { |
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index f04224c32005..1e8053976e83 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c | |||
@@ -108,14 +108,15 @@ static int batadv_iv_ogm_orig_add_if(struct batadv_orig_node *orig_node, | |||
108 | int max_if_num) | 108 | int max_if_num) |
109 | { | 109 | { |
110 | void *data_ptr; | 110 | void *data_ptr; |
111 | size_t data_size, old_size; | 111 | size_t old_size; |
112 | int ret = -ENOMEM; | 112 | int ret = -ENOMEM; |
113 | 113 | ||
114 | spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock); | 114 | spin_lock_bh(&orig_node->bat_iv.ogm_cnt_lock); |
115 | 115 | ||
116 | data_size = max_if_num * sizeof(unsigned long) * BATADV_NUM_WORDS; | ||
117 | old_size = (max_if_num - 1) * sizeof(unsigned long) * BATADV_NUM_WORDS; | 116 | old_size = (max_if_num - 1) * sizeof(unsigned long) * BATADV_NUM_WORDS; |
118 | data_ptr = kmalloc(data_size, GFP_ATOMIC); | 117 | data_ptr = kmalloc_array(max_if_num, |
118 | BATADV_NUM_WORDS * sizeof(unsigned long), | ||
119 | GFP_ATOMIC); | ||
119 | if (!data_ptr) | 120 | if (!data_ptr) |
120 | goto unlock; | 121 | goto unlock; |
121 | 122 | ||
@@ -123,7 +124,7 @@ static int batadv_iv_ogm_orig_add_if(struct batadv_orig_node *orig_node, | |||
123 | kfree(orig_node->bat_iv.bcast_own); | 124 | kfree(orig_node->bat_iv.bcast_own); |
124 | orig_node->bat_iv.bcast_own = data_ptr; | 125 | orig_node->bat_iv.bcast_own = data_ptr; |
125 | 126 | ||
126 | data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC); | 127 | data_ptr = kmalloc_array(max_if_num, sizeof(uint8_t), GFP_ATOMIC); |
127 | if (!data_ptr) { | 128 | if (!data_ptr) { |
128 | kfree(orig_node->bat_iv.bcast_own); | 129 | kfree(orig_node->bat_iv.bcast_own); |
129 | goto unlock; | 130 | goto unlock; |
@@ -164,7 +165,7 @@ static int batadv_iv_ogm_orig_del_if(struct batadv_orig_node *orig_node, | |||
164 | goto free_bcast_own; | 165 | goto free_bcast_own; |
165 | 166 | ||
166 | chunk_size = sizeof(unsigned long) * BATADV_NUM_WORDS; | 167 | chunk_size = sizeof(unsigned long) * BATADV_NUM_WORDS; |
167 | data_ptr = kmalloc(max_if_num * chunk_size, GFP_ATOMIC); | 168 | data_ptr = kmalloc_array(max_if_num, chunk_size, GFP_ATOMIC); |
168 | if (!data_ptr) | 169 | if (!data_ptr) |
169 | goto unlock; | 170 | goto unlock; |
170 | 171 | ||
@@ -183,7 +184,7 @@ free_bcast_own: | |||
183 | if (max_if_num == 0) | 184 | if (max_if_num == 0) |
184 | goto free_own_sum; | 185 | goto free_own_sum; |
185 | 186 | ||
186 | data_ptr = kmalloc(max_if_num * sizeof(uint8_t), GFP_ATOMIC); | 187 | data_ptr = kmalloc_array(max_if_num, sizeof(uint8_t), GFP_ATOMIC); |
187 | if (!data_ptr) { | 188 | if (!data_ptr) { |
188 | kfree(orig_node->bat_iv.bcast_own); | 189 | kfree(orig_node->bat_iv.bcast_own); |
189 | goto unlock; | 190 | goto unlock; |
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index f2c066b21716..b5981113c9a7 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c | |||
@@ -537,7 +537,8 @@ batadv_dat_select_candidates(struct batadv_priv *bat_priv, __be32 ip_dst) | |||
537 | if (!bat_priv->orig_hash) | 537 | if (!bat_priv->orig_hash) |
538 | return NULL; | 538 | return NULL; |
539 | 539 | ||
540 | res = kmalloc(BATADV_DAT_CANDIDATES_NUM * sizeof(*res), GFP_ATOMIC); | 540 | res = kmalloc_array(BATADV_DAT_CANDIDATES_NUM, sizeof(*res), |
541 | GFP_ATOMIC); | ||
541 | if (!res) | 542 | if (!res) |
542 | return NULL; | 543 | return NULL; |
543 | 544 | ||
diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c index f14e54a05691..fc1835c6bb40 100644 --- a/net/batman-adv/fragmentation.c +++ b/net/batman-adv/fragmentation.c | |||
@@ -128,6 +128,7 @@ static bool batadv_frag_insert_packet(struct batadv_orig_node *orig_node, | |||
128 | { | 128 | { |
129 | struct batadv_frag_table_entry *chain; | 129 | struct batadv_frag_table_entry *chain; |
130 | struct batadv_frag_list_entry *frag_entry_new = NULL, *frag_entry_curr; | 130 | struct batadv_frag_list_entry *frag_entry_new = NULL, *frag_entry_curr; |
131 | struct batadv_frag_list_entry *frag_entry_last = NULL; | ||
131 | struct batadv_frag_packet *frag_packet; | 132 | struct batadv_frag_packet *frag_packet; |
132 | uint8_t bucket; | 133 | uint8_t bucket; |
133 | uint16_t seqno, hdr_size = sizeof(struct batadv_frag_packet); | 134 | uint16_t seqno, hdr_size = sizeof(struct batadv_frag_packet); |
@@ -180,11 +181,14 @@ static bool batadv_frag_insert_packet(struct batadv_orig_node *orig_node, | |||
180 | ret = true; | 181 | ret = true; |
181 | goto out; | 182 | goto out; |
182 | } | 183 | } |
184 | |||
185 | /* store current entry because it could be the last in list */ | ||
186 | frag_entry_last = frag_entry_curr; | ||
183 | } | 187 | } |
184 | 188 | ||
185 | /* Reached the end of the list, so insert after 'frag_entry_curr'. */ | 189 | /* Reached the end of the list, so insert after 'frag_entry_last'. */ |
186 | if (likely(frag_entry_curr)) { | 190 | if (likely(frag_entry_last)) { |
187 | hlist_add_after(&frag_entry_curr->list, &frag_entry_new->list); | 191 | hlist_add_behind(&frag_entry_new->list, &frag_entry_last->list); |
188 | chain->size += skb->len - hdr_size; | 192 | chain->size += skb->len - hdr_size; |
189 | chain->timestamp = jiffies; | 193 | chain->timestamp = jiffies; |
190 | ret = true; | 194 | ret = true; |
diff --git a/net/batman-adv/hash.c b/net/batman-adv/hash.c index 63bdf7e94f1e..7c1c63080e20 100644 --- a/net/batman-adv/hash.c +++ b/net/batman-adv/hash.c | |||
@@ -46,12 +46,12 @@ struct batadv_hashtable *batadv_hash_new(uint32_t size) | |||
46 | if (!hash) | 46 | if (!hash) |
47 | return NULL; | 47 | return NULL; |
48 | 48 | ||
49 | hash->table = kmalloc(sizeof(*hash->table) * size, GFP_ATOMIC); | 49 | hash->table = kmalloc_array(size, sizeof(*hash->table), GFP_ATOMIC); |
50 | if (!hash->table) | 50 | if (!hash->table) |
51 | goto free_hash; | 51 | goto free_hash; |
52 | 52 | ||
53 | hash->list_locks = kmalloc(sizeof(*hash->list_locks) * size, | 53 | hash->list_locks = kmalloc_array(size, sizeof(*hash->list_locks), |
54 | GFP_ATOMIC); | 54 | GFP_ATOMIC); |
55 | if (!hash->list_locks) | 55 | if (!hash->list_locks) |
56 | goto free_table; | 56 | goto free_table; |
57 | 57 | ||
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index 118b990bae25..a1fcd884f0b1 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h | |||
@@ -24,7 +24,7 @@ | |||
24 | #define BATADV_DRIVER_DEVICE "batman-adv" | 24 | #define BATADV_DRIVER_DEVICE "batman-adv" |
25 | 25 | ||
26 | #ifndef BATADV_SOURCE_VERSION | 26 | #ifndef BATADV_SOURCE_VERSION |
27 | #define BATADV_SOURCE_VERSION "2014.3.0" | 27 | #define BATADV_SOURCE_VERSION "2014.4.0" |
28 | #endif | 28 | #endif |
29 | 29 | ||
30 | /* B.A.T.M.A.N. parameters */ | 30 | /* B.A.T.M.A.N. parameters */ |
@@ -238,21 +238,29 @@ enum batadv_dbg_level { | |||
238 | int batadv_debug_log(struct batadv_priv *bat_priv, const char *fmt, ...) | 238 | int batadv_debug_log(struct batadv_priv *bat_priv, const char *fmt, ...) |
239 | __printf(2, 3); | 239 | __printf(2, 3); |
240 | 240 | ||
241 | #define batadv_dbg(type, bat_priv, fmt, arg...) \ | 241 | /* possibly ratelimited debug output */ |
242 | #define _batadv_dbg(type, bat_priv, ratelimited, fmt, arg...) \ | ||
242 | do { \ | 243 | do { \ |
243 | if (atomic_read(&bat_priv->log_level) & type) \ | 244 | if (atomic_read(&bat_priv->log_level) & type && \ |
245 | (!ratelimited || net_ratelimit())) \ | ||
244 | batadv_debug_log(bat_priv, fmt, ## arg);\ | 246 | batadv_debug_log(bat_priv, fmt, ## arg);\ |
245 | } \ | 247 | } \ |
246 | while (0) | 248 | while (0) |
247 | #else /* !CONFIG_BATMAN_ADV_DEBUG */ | 249 | #else /* !CONFIG_BATMAN_ADV_DEBUG */ |
248 | __printf(3, 4) | 250 | __printf(4, 5) |
249 | static inline void batadv_dbg(int type __always_unused, | 251 | static inline void _batadv_dbg(int type __always_unused, |
250 | struct batadv_priv *bat_priv __always_unused, | 252 | struct batadv_priv *bat_priv __always_unused, |
251 | const char *fmt __always_unused, ...) | 253 | int ratelimited __always_unused, |
254 | const char *fmt __always_unused, ...) | ||
252 | { | 255 | { |
253 | } | 256 | } |
254 | #endif | 257 | #endif |
255 | 258 | ||
259 | #define batadv_dbg(type, bat_priv, arg...) \ | ||
260 | _batadv_dbg(type, bat_priv, 0, ## arg) | ||
261 | #define batadv_dbg_ratelimited(type, bat_priv, arg...) \ | ||
262 | _batadv_dbg(type, bat_priv, 1, ## arg) | ||
263 | |||
256 | #define batadv_info(net_dev, fmt, arg...) \ | 264 | #define batadv_info(net_dev, fmt, arg...) \ |
257 | do { \ | 265 | do { \ |
258 | struct net_device *_netdev = (net_dev); \ | 266 | struct net_device *_netdev = (net_dev); \ |
diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c index 96b66fd30f96..ab6bb2af1d45 100644 --- a/net/batman-adv/multicast.c +++ b/net/batman-adv/multicast.c | |||
@@ -20,7 +20,6 @@ | |||
20 | #include "originator.h" | 20 | #include "originator.h" |
21 | #include "hard-interface.h" | 21 | #include "hard-interface.h" |
22 | #include "translation-table.h" | 22 | #include "translation-table.h" |
23 | #include "multicast.h" | ||
24 | 23 | ||
25 | /** | 24 | /** |
26 | * batadv_mcast_mla_softif_get - get softif multicast listeners | 25 | * batadv_mcast_mla_softif_get - get softif multicast listeners |
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 35141534938e..35f76f2f7824 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c | |||
@@ -706,11 +706,11 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv, | |||
706 | if (batadv_tt_local_client_is_roaming(bat_priv, ethhdr->h_dest, vid)) { | 706 | if (batadv_tt_local_client_is_roaming(bat_priv, ethhdr->h_dest, vid)) { |
707 | if (batadv_reroute_unicast_packet(bat_priv, unicast_packet, | 707 | if (batadv_reroute_unicast_packet(bat_priv, unicast_packet, |
708 | ethhdr->h_dest, vid)) | 708 | ethhdr->h_dest, vid)) |
709 | net_ratelimited_function(batadv_dbg, BATADV_DBG_TT, | 709 | batadv_dbg_ratelimited(BATADV_DBG_TT, |
710 | bat_priv, | 710 | bat_priv, |
711 | "Rerouting unicast packet to %pM (dst=%pM): Local Roaming\n", | 711 | "Rerouting unicast packet to %pM (dst=%pM): Local Roaming\n", |
712 | unicast_packet->dest, | 712 | unicast_packet->dest, |
713 | ethhdr->h_dest); | 713 | ethhdr->h_dest); |
714 | /* at this point the mesh destination should have been | 714 | /* at this point the mesh destination should have been |
715 | * substituted with the originator address found in the global | 715 | * substituted with the originator address found in the global |
716 | * table. If not, let the packet go untouched anyway because | 716 | * table. If not, let the packet go untouched anyway because |
@@ -752,10 +752,10 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv, | |||
752 | */ | 752 | */ |
753 | if (batadv_reroute_unicast_packet(bat_priv, unicast_packet, | 753 | if (batadv_reroute_unicast_packet(bat_priv, unicast_packet, |
754 | ethhdr->h_dest, vid)) { | 754 | ethhdr->h_dest, vid)) { |
755 | net_ratelimited_function(batadv_dbg, BATADV_DBG_TT, bat_priv, | 755 | batadv_dbg_ratelimited(BATADV_DBG_TT, bat_priv, |
756 | "Rerouting unicast packet to %pM (dst=%pM): TTVN mismatch old_ttvn=%u new_ttvn=%u\n", | 756 | "Rerouting unicast packet to %pM (dst=%pM): TTVN mismatch old_ttvn=%u new_ttvn=%u\n", |
757 | unicast_packet->dest, ethhdr->h_dest, | 757 | unicast_packet->dest, ethhdr->h_dest, |
758 | old_ttvn, curr_ttvn); | 758 | old_ttvn, curr_ttvn); |
759 | return 1; | 759 | return 1; |
760 | } | 760 | } |
761 | 761 | ||
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index cbd677f48c00..5467955eb27c 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c | |||
@@ -751,7 +751,7 @@ static int batadv_softif_init_late(struct net_device *dev) | |||
751 | atomic_set(&bat_priv->gw.bandwidth_down, 100); | 751 | atomic_set(&bat_priv->gw.bandwidth_down, 100); |
752 | atomic_set(&bat_priv->gw.bandwidth_up, 20); | 752 | atomic_set(&bat_priv->gw.bandwidth_up, 20); |
753 | atomic_set(&bat_priv->orig_interval, 1000); | 753 | atomic_set(&bat_priv->orig_interval, 1000); |
754 | atomic_set(&bat_priv->hop_penalty, 15); | 754 | atomic_set(&bat_priv->hop_penalty, 30); |
755 | #ifdef CONFIG_BATMAN_ADV_DEBUG | 755 | #ifdef CONFIG_BATMAN_ADV_DEBUG |
756 | atomic_set(&bat_priv->log_level, 0); | 756 | atomic_set(&bat_priv->log_level, 0); |
757 | #endif | 757 | #endif |
@@ -927,7 +927,7 @@ struct net_device *batadv_softif_create(const char *name) | |||
927 | int ret; | 927 | int ret; |
928 | 928 | ||
929 | soft_iface = alloc_netdev(sizeof(struct batadv_priv), name, | 929 | soft_iface = alloc_netdev(sizeof(struct batadv_priv), name, |
930 | batadv_softif_init_early); | 930 | NET_NAME_UNKNOWN, batadv_softif_init_early); |
931 | if (!soft_iface) | 931 | if (!soft_iface) |
932 | return NULL; | 932 | return NULL; |
933 | 933 | ||
diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c index fc47baa888c5..f40cb0436eba 100644 --- a/net/batman-adv/sysfs.c +++ b/net/batman-adv/sysfs.c | |||
@@ -900,32 +900,24 @@ int batadv_throw_uevent(struct batadv_priv *bat_priv, enum batadv_uev_type type, | |||
900 | 900 | ||
901 | bat_kobj = &bat_priv->soft_iface->dev.kobj; | 901 | bat_kobj = &bat_priv->soft_iface->dev.kobj; |
902 | 902 | ||
903 | uevent_env[0] = kmalloc(strlen(BATADV_UEV_TYPE_VAR) + | 903 | uevent_env[0] = kasprintf(GFP_ATOMIC, |
904 | strlen(batadv_uev_type_str[type]) + 1, | 904 | "%s%s", BATADV_UEV_TYPE_VAR, |
905 | GFP_ATOMIC); | 905 | batadv_uev_type_str[type]); |
906 | if (!uevent_env[0]) | 906 | if (!uevent_env[0]) |
907 | goto out; | 907 | goto out; |
908 | 908 | ||
909 | sprintf(uevent_env[0], "%s%s", BATADV_UEV_TYPE_VAR, | 909 | uevent_env[1] = kasprintf(GFP_ATOMIC, |
910 | batadv_uev_type_str[type]); | 910 | "%s%s", BATADV_UEV_ACTION_VAR, |
911 | 911 | batadv_uev_action_str[action]); | |
912 | uevent_env[1] = kmalloc(strlen(BATADV_UEV_ACTION_VAR) + | ||
913 | strlen(batadv_uev_action_str[action]) + 1, | ||
914 | GFP_ATOMIC); | ||
915 | if (!uevent_env[1]) | 912 | if (!uevent_env[1]) |
916 | goto out; | 913 | goto out; |
917 | 914 | ||
918 | sprintf(uevent_env[1], "%s%s", BATADV_UEV_ACTION_VAR, | ||
919 | batadv_uev_action_str[action]); | ||
920 | |||
921 | /* If the event is DEL, ignore the data field */ | 915 | /* If the event is DEL, ignore the data field */ |
922 | if (action != BATADV_UEV_DEL) { | 916 | if (action != BATADV_UEV_DEL) { |
923 | uevent_env[2] = kmalloc(strlen(BATADV_UEV_DATA_VAR) + | 917 | uevent_env[2] = kasprintf(GFP_ATOMIC, |
924 | strlen(data) + 1, GFP_ATOMIC); | 918 | "%s%s", BATADV_UEV_DATA_VAR, data); |
925 | if (!uevent_env[2]) | 919 | if (!uevent_env[2]) |
926 | goto out; | 920 | goto out; |
927 | |||
928 | sprintf(uevent_env[2], "%s%s", BATADV_UEV_DATA_VAR, data); | ||
929 | } | 921 | } |
930 | 922 | ||
931 | ret = kobject_uevent_env(bat_kobj, KOBJ_CHANGE, uevent_env); | 923 | ret = kobject_uevent_env(bat_kobj, KOBJ_CHANGE, uevent_env); |
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c index 8796ffa08b43..206b65ccd5b8 100644 --- a/net/bluetooth/6lowpan.c +++ b/net/bluetooth/6lowpan.c | |||
@@ -1,5 +1,5 @@ | |||
1 | /* | 1 | /* |
2 | Copyright (c) 2013 Intel Corp. | 2 | Copyright (c) 2013-2014 Intel Corp. |
3 | 3 | ||
4 | This program is free software; you can redistribute it and/or modify | 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 and | 5 | it under the terms of the GNU General Public License version 2 and |
@@ -14,6 +14,8 @@ | |||
14 | #include <linux/if_arp.h> | 14 | #include <linux/if_arp.h> |
15 | #include <linux/netdevice.h> | 15 | #include <linux/netdevice.h> |
16 | #include <linux/etherdevice.h> | 16 | #include <linux/etherdevice.h> |
17 | #include <linux/module.h> | ||
18 | #include <linux/debugfs.h> | ||
17 | 19 | ||
18 | #include <net/ipv6.h> | 20 | #include <net/ipv6.h> |
19 | #include <net/ip6_route.h> | 21 | #include <net/ip6_route.h> |
@@ -25,16 +27,20 @@ | |||
25 | #include <net/bluetooth/hci_core.h> | 27 | #include <net/bluetooth/hci_core.h> |
26 | #include <net/bluetooth/l2cap.h> | 28 | #include <net/bluetooth/l2cap.h> |
27 | 29 | ||
28 | #include "6lowpan.h" | ||
29 | |||
30 | #include <net/6lowpan.h> /* for the compression support */ | 30 | #include <net/6lowpan.h> /* for the compression support */ |
31 | 31 | ||
32 | #define VERSION "0.1" | ||
33 | |||
34 | static struct dentry *lowpan_psm_debugfs; | ||
35 | static struct dentry *lowpan_control_debugfs; | ||
36 | |||
32 | #define IFACE_NAME_TEMPLATE "bt%d" | 37 | #define IFACE_NAME_TEMPLATE "bt%d" |
33 | #define EUI64_ADDR_LEN 8 | 38 | #define EUI64_ADDR_LEN 8 |
34 | 39 | ||
35 | struct skb_cb { | 40 | struct skb_cb { |
36 | struct in6_addr addr; | 41 | struct in6_addr addr; |
37 | struct l2cap_conn *conn; | 42 | struct l2cap_chan *chan; |
43 | int status; | ||
38 | }; | 44 | }; |
39 | #define lowpan_cb(skb) ((struct skb_cb *)((skb)->cb)) | 45 | #define lowpan_cb(skb) ((struct skb_cb *)((skb)->cb)) |
40 | 46 | ||
@@ -48,9 +54,19 @@ struct skb_cb { | |||
48 | static LIST_HEAD(bt_6lowpan_devices); | 54 | static LIST_HEAD(bt_6lowpan_devices); |
49 | static DEFINE_RWLOCK(devices_lock); | 55 | static DEFINE_RWLOCK(devices_lock); |
50 | 56 | ||
57 | /* If psm is set to 0 (default value), then 6lowpan is disabled. | ||
58 | * Other values are used to indicate a Protocol Service Multiplexer | ||
59 | * value for 6lowpan. | ||
60 | */ | ||
61 | static u16 psm_6lowpan; | ||
62 | |||
63 | /* We are listening incoming connections via this channel | ||
64 | */ | ||
65 | static struct l2cap_chan *listen_chan; | ||
66 | |||
51 | struct lowpan_peer { | 67 | struct lowpan_peer { |
52 | struct list_head list; | 68 | struct list_head list; |
53 | struct l2cap_conn *conn; | 69 | struct l2cap_chan *chan; |
54 | 70 | ||
55 | /* peer addresses in various formats */ | 71 | /* peer addresses in various formats */ |
56 | unsigned char eui64_addr[EUI64_ADDR_LEN]; | 72 | unsigned char eui64_addr[EUI64_ADDR_LEN]; |
@@ -84,6 +100,8 @@ static inline bool peer_del(struct lowpan_dev *dev, struct lowpan_peer *peer) | |||
84 | { | 100 | { |
85 | list_del(&peer->list); | 101 | list_del(&peer->list); |
86 | 102 | ||
103 | module_put(THIS_MODULE); | ||
104 | |||
87 | if (atomic_dec_and_test(&dev->peer_count)) { | 105 | if (atomic_dec_and_test(&dev->peer_count)) { |
88 | BT_DBG("last peer"); | 106 | BT_DBG("last peer"); |
89 | return true; | 107 | return true; |
@@ -101,13 +119,26 @@ static inline struct lowpan_peer *peer_lookup_ba(struct lowpan_dev *dev, | |||
101 | ba, type); | 119 | ba, type); |
102 | 120 | ||
103 | list_for_each_entry_safe(peer, tmp, &dev->peers, list) { | 121 | list_for_each_entry_safe(peer, tmp, &dev->peers, list) { |
104 | BT_DBG("addr %pMR type %d", | 122 | BT_DBG("dst addr %pMR dst type %d", |
105 | &peer->conn->hcon->dst, peer->conn->hcon->dst_type); | 123 | &peer->chan->dst, peer->chan->dst_type); |
106 | 124 | ||
107 | if (bacmp(&peer->conn->hcon->dst, ba)) | 125 | if (bacmp(&peer->chan->dst, ba)) |
108 | continue; | 126 | continue; |
109 | 127 | ||
110 | if (type == peer->conn->hcon->dst_type) | 128 | if (type == peer->chan->dst_type) |
129 | return peer; | ||
130 | } | ||
131 | |||
132 | return NULL; | ||
133 | } | ||
134 | |||
135 | static inline struct lowpan_peer *peer_lookup_chan(struct lowpan_dev *dev, | ||
136 | struct l2cap_chan *chan) | ||
137 | { | ||
138 | struct lowpan_peer *peer, *tmp; | ||
139 | |||
140 | list_for_each_entry_safe(peer, tmp, &dev->peers, list) { | ||
141 | if (peer->chan == chan) | ||
111 | return peer; | 142 | return peer; |
112 | } | 143 | } |
113 | 144 | ||
@@ -120,7 +151,7 @@ static inline struct lowpan_peer *peer_lookup_conn(struct lowpan_dev *dev, | |||
120 | struct lowpan_peer *peer, *tmp; | 151 | struct lowpan_peer *peer, *tmp; |
121 | 152 | ||
122 | list_for_each_entry_safe(peer, tmp, &dev->peers, list) { | 153 | list_for_each_entry_safe(peer, tmp, &dev->peers, list) { |
123 | if (peer->conn == conn) | 154 | if (peer->chan->conn == conn) |
124 | return peer; | 155 | return peer; |
125 | } | 156 | } |
126 | 157 | ||
@@ -176,16 +207,16 @@ static int give_skb_to_upper(struct sk_buff *skb, struct net_device *dev) | |||
176 | return -ENOMEM; | 207 | return -ENOMEM; |
177 | 208 | ||
178 | ret = netif_rx(skb_cp); | 209 | ret = netif_rx(skb_cp); |
179 | 210 | if (ret < 0) { | |
180 | BT_DBG("receive skb %d", ret); | 211 | BT_DBG("receive skb %d", ret); |
181 | if (ret < 0) | ||
182 | return NET_RX_DROP; | 212 | return NET_RX_DROP; |
213 | } | ||
183 | 214 | ||
184 | return ret; | 215 | return ret; |
185 | } | 216 | } |
186 | 217 | ||
187 | static int process_data(struct sk_buff *skb, struct net_device *netdev, | 218 | static int process_data(struct sk_buff *skb, struct net_device *netdev, |
188 | struct l2cap_conn *conn) | 219 | struct l2cap_chan *chan) |
189 | { | 220 | { |
190 | const u8 *saddr, *daddr; | 221 | const u8 *saddr, *daddr; |
191 | u8 iphc0, iphc1; | 222 | u8 iphc0, iphc1; |
@@ -196,7 +227,7 @@ static int process_data(struct sk_buff *skb, struct net_device *netdev, | |||
196 | dev = lowpan_dev(netdev); | 227 | dev = lowpan_dev(netdev); |
197 | 228 | ||
198 | read_lock_irqsave(&devices_lock, flags); | 229 | read_lock_irqsave(&devices_lock, flags); |
199 | peer = peer_lookup_conn(dev, conn); | 230 | peer = peer_lookup_chan(dev, chan); |
200 | read_unlock_irqrestore(&devices_lock, flags); | 231 | read_unlock_irqrestore(&devices_lock, flags); |
201 | if (!peer) | 232 | if (!peer) |
202 | goto drop; | 233 | goto drop; |
@@ -225,7 +256,7 @@ drop: | |||
225 | } | 256 | } |
226 | 257 | ||
227 | static int recv_pkt(struct sk_buff *skb, struct net_device *dev, | 258 | static int recv_pkt(struct sk_buff *skb, struct net_device *dev, |
228 | struct l2cap_conn *conn) | 259 | struct l2cap_chan *chan) |
229 | { | 260 | { |
230 | struct sk_buff *local_skb; | 261 | struct sk_buff *local_skb; |
231 | int ret; | 262 | int ret; |
@@ -269,7 +300,7 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev, | |||
269 | if (!local_skb) | 300 | if (!local_skb) |
270 | goto drop; | 301 | goto drop; |
271 | 302 | ||
272 | ret = process_data(local_skb, dev, conn); | 303 | ret = process_data(local_skb, dev, chan); |
273 | if (ret != NET_RX_SUCCESS) | 304 | if (ret != NET_RX_SUCCESS) |
274 | goto drop; | 305 | goto drop; |
275 | 306 | ||
@@ -286,147 +317,39 @@ static int recv_pkt(struct sk_buff *skb, struct net_device *dev, | |||
286 | return NET_RX_SUCCESS; | 317 | return NET_RX_SUCCESS; |
287 | 318 | ||
288 | drop: | 319 | drop: |
320 | dev->stats.rx_dropped++; | ||
289 | kfree_skb(skb); | 321 | kfree_skb(skb); |
290 | return NET_RX_DROP; | 322 | return NET_RX_DROP; |
291 | } | 323 | } |
292 | 324 | ||
293 | /* Packet from BT LE device */ | 325 | /* Packet from BT LE device */ |
294 | int bt_6lowpan_recv(struct l2cap_conn *conn, struct sk_buff *skb) | 326 | static int chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) |
295 | { | 327 | { |
296 | struct lowpan_dev *dev; | 328 | struct lowpan_dev *dev; |
297 | struct lowpan_peer *peer; | 329 | struct lowpan_peer *peer; |
298 | int err; | 330 | int err; |
299 | 331 | ||
300 | peer = lookup_peer(conn); | 332 | peer = lookup_peer(chan->conn); |
301 | if (!peer) | 333 | if (!peer) |
302 | return -ENOENT; | 334 | return -ENOENT; |
303 | 335 | ||
304 | dev = lookup_dev(conn); | 336 | dev = lookup_dev(chan->conn); |
305 | if (!dev || !dev->netdev) | 337 | if (!dev || !dev->netdev) |
306 | return -ENOENT; | 338 | return -ENOENT; |
307 | 339 | ||
308 | err = recv_pkt(skb, dev->netdev, conn); | 340 | err = recv_pkt(skb, dev->netdev, chan); |
309 | BT_DBG("recv pkt %d", err); | 341 | if (err) { |
310 | 342 | BT_DBG("recv pkt %d", err); | |
311 | return err; | 343 | err = -EAGAIN; |
312 | } | ||
313 | |||
314 | static inline int skbuff_copy(void *msg, int len, int count, int mtu, | ||
315 | struct sk_buff *skb, struct net_device *dev) | ||
316 | { | ||
317 | struct sk_buff **frag; | ||
318 | int sent = 0; | ||
319 | |||
320 | memcpy(skb_put(skb, count), msg, count); | ||
321 | |||
322 | sent += count; | ||
323 | msg += count; | ||
324 | len -= count; | ||
325 | |||
326 | dev->stats.tx_bytes += count; | ||
327 | dev->stats.tx_packets++; | ||
328 | |||
329 | raw_dump_table(__func__, "Sending", skb->data, skb->len); | ||
330 | |||
331 | /* Continuation fragments (no L2CAP header) */ | ||
332 | frag = &skb_shinfo(skb)->frag_list; | ||
333 | while (len > 0) { | ||
334 | struct sk_buff *tmp; | ||
335 | |||
336 | count = min_t(unsigned int, mtu, len); | ||
337 | |||
338 | tmp = bt_skb_alloc(count, GFP_ATOMIC); | ||
339 | if (!tmp) | ||
340 | return -ENOMEM; | ||
341 | |||
342 | *frag = tmp; | ||
343 | |||
344 | memcpy(skb_put(*frag, count), msg, count); | ||
345 | |||
346 | raw_dump_table(__func__, "Sending fragment", | ||
347 | (*frag)->data, count); | ||
348 | |||
349 | (*frag)->priority = skb->priority; | ||
350 | |||
351 | sent += count; | ||
352 | msg += count; | ||
353 | len -= count; | ||
354 | |||
355 | skb->len += (*frag)->len; | ||
356 | skb->data_len += (*frag)->len; | ||
357 | |||
358 | frag = &(*frag)->next; | ||
359 | |||
360 | dev->stats.tx_bytes += count; | ||
361 | dev->stats.tx_packets++; | ||
362 | } | 344 | } |
363 | 345 | ||
364 | return sent; | 346 | return err; |
365 | } | ||
366 | |||
367 | static struct sk_buff *create_pdu(struct l2cap_conn *conn, void *msg, | ||
368 | size_t len, u32 priority, | ||
369 | struct net_device *dev) | ||
370 | { | ||
371 | struct sk_buff *skb; | ||
372 | int err, count; | ||
373 | struct l2cap_hdr *lh; | ||
374 | |||
375 | /* FIXME: This mtu check should be not needed and atm is only used for | ||
376 | * testing purposes | ||
377 | */ | ||
378 | if (conn->mtu > (L2CAP_LE_MIN_MTU + L2CAP_HDR_SIZE)) | ||
379 | conn->mtu = L2CAP_LE_MIN_MTU + L2CAP_HDR_SIZE; | ||
380 | |||
381 | count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len); | ||
382 | |||
383 | BT_DBG("conn %p len %zu mtu %d count %d", conn, len, conn->mtu, count); | ||
384 | |||
385 | skb = bt_skb_alloc(count + L2CAP_HDR_SIZE, GFP_ATOMIC); | ||
386 | if (!skb) | ||
387 | return ERR_PTR(-ENOMEM); | ||
388 | |||
389 | skb->priority = priority; | ||
390 | |||
391 | lh = (struct l2cap_hdr *)skb_put(skb, L2CAP_HDR_SIZE); | ||
392 | lh->cid = cpu_to_le16(L2CAP_FC_6LOWPAN); | ||
393 | lh->len = cpu_to_le16(len); | ||
394 | |||
395 | err = skbuff_copy(msg, len, count, conn->mtu, skb, dev); | ||
396 | if (unlikely(err < 0)) { | ||
397 | kfree_skb(skb); | ||
398 | BT_DBG("skbuff copy %d failed", err); | ||
399 | return ERR_PTR(err); | ||
400 | } | ||
401 | |||
402 | return skb; | ||
403 | } | ||
404 | |||
405 | static int conn_send(struct l2cap_conn *conn, | ||
406 | void *msg, size_t len, u32 priority, | ||
407 | struct net_device *dev) | ||
408 | { | ||
409 | struct sk_buff *skb; | ||
410 | |||
411 | skb = create_pdu(conn, msg, len, priority, dev); | ||
412 | if (IS_ERR(skb)) | ||
413 | return -EINVAL; | ||
414 | |||
415 | BT_DBG("conn %p skb %p len %d priority %u", conn, skb, skb->len, | ||
416 | skb->priority); | ||
417 | |||
418 | hci_send_acl(conn->hchan, skb, ACL_START); | ||
419 | |||
420 | return 0; | ||
421 | } | 347 | } |
422 | 348 | ||
423 | static u8 get_addr_type_from_eui64(u8 byte) | 349 | static u8 get_addr_type_from_eui64(u8 byte) |
424 | { | 350 | { |
425 | /* Is universal(0) or local(1) bit, */ | 351 | /* Is universal(0) or local(1) bit */ |
426 | if (byte & 0x02) | 352 | return ((byte & 0x02) ? BDADDR_LE_RANDOM : BDADDR_LE_PUBLIC); |
427 | return ADDR_LE_DEV_RANDOM; | ||
428 | |||
429 | return ADDR_LE_DEV_PUBLIC; | ||
430 | } | 353 | } |
431 | 354 | ||
432 | static void copy_to_bdaddr(struct in6_addr *ip6_daddr, bdaddr_t *addr) | 355 | static void copy_to_bdaddr(struct in6_addr *ip6_daddr, bdaddr_t *addr) |
@@ -475,7 +398,7 @@ static int header_create(struct sk_buff *skb, struct net_device *netdev, | |||
475 | if (ipv6_addr_is_multicast(&hdr->daddr)) { | 398 | if (ipv6_addr_is_multicast(&hdr->daddr)) { |
476 | memcpy(&lowpan_cb(skb)->addr, &hdr->daddr, | 399 | memcpy(&lowpan_cb(skb)->addr, &hdr->daddr, |
477 | sizeof(struct in6_addr)); | 400 | sizeof(struct in6_addr)); |
478 | lowpan_cb(skb)->conn = NULL; | 401 | lowpan_cb(skb)->chan = NULL; |
479 | } else { | 402 | } else { |
480 | unsigned long flags; | 403 | unsigned long flags; |
481 | 404 | ||
@@ -484,9 +407,8 @@ static int header_create(struct sk_buff *skb, struct net_device *netdev, | |||
484 | */ | 407 | */ |
485 | convert_dest_bdaddr(&hdr->daddr, &addr, &addr_type); | 408 | convert_dest_bdaddr(&hdr->daddr, &addr, &addr_type); |
486 | 409 | ||
487 | BT_DBG("dest addr %pMR type %s IP %pI6c", &addr, | 410 | BT_DBG("dest addr %pMR type %d IP %pI6c", &addr, |
488 | addr_type == ADDR_LE_DEV_PUBLIC ? "PUBLIC" : "RANDOM", | 411 | addr_type, &hdr->daddr); |
489 | &hdr->daddr); | ||
490 | 412 | ||
491 | read_lock_irqsave(&devices_lock, flags); | 413 | read_lock_irqsave(&devices_lock, flags); |
492 | peer = peer_lookup_ba(dev, &addr, addr_type); | 414 | peer = peer_lookup_ba(dev, &addr, addr_type); |
@@ -501,7 +423,7 @@ static int header_create(struct sk_buff *skb, struct net_device *netdev, | |||
501 | 423 | ||
502 | memcpy(&lowpan_cb(skb)->addr, &hdr->daddr, | 424 | memcpy(&lowpan_cb(skb)->addr, &hdr->daddr, |
503 | sizeof(struct in6_addr)); | 425 | sizeof(struct in6_addr)); |
504 | lowpan_cb(skb)->conn = peer->conn; | 426 | lowpan_cb(skb)->chan = peer->chan; |
505 | } | 427 | } |
506 | 428 | ||
507 | saddr = dev->netdev->dev_addr; | 429 | saddr = dev->netdev->dev_addr; |
@@ -510,14 +432,42 @@ static int header_create(struct sk_buff *skb, struct net_device *netdev, | |||
510 | } | 432 | } |
511 | 433 | ||
512 | /* Packet to BT LE device */ | 434 | /* Packet to BT LE device */ |
513 | static int send_pkt(struct l2cap_conn *conn, const void *saddr, | 435 | static int send_pkt(struct l2cap_chan *chan, struct sk_buff *skb, |
514 | const void *daddr, struct sk_buff *skb, | ||
515 | struct net_device *netdev) | 436 | struct net_device *netdev) |
516 | { | 437 | { |
517 | raw_dump_table(__func__, "raw skb data dump before fragmentation", | 438 | struct msghdr msg; |
518 | skb->data, skb->len); | 439 | struct kvec iv; |
440 | int err; | ||
441 | |||
442 | /* Remember the skb so that we can send EAGAIN to the caller if | ||
443 | * we run out of credits. | ||
444 | */ | ||
445 | chan->data = skb; | ||
446 | |||
447 | memset(&msg, 0, sizeof(msg)); | ||
448 | msg.msg_iov = (struct iovec *) &iv; | ||
449 | msg.msg_iovlen = 1; | ||
450 | iv.iov_base = skb->data; | ||
451 | iv.iov_len = skb->len; | ||
452 | |||
453 | err = l2cap_chan_send(chan, &msg, skb->len); | ||
454 | if (err > 0) { | ||
455 | netdev->stats.tx_bytes += err; | ||
456 | netdev->stats.tx_packets++; | ||
457 | return 0; | ||
458 | } | ||
459 | |||
460 | if (!err) | ||
461 | err = lowpan_cb(skb)->status; | ||
519 | 462 | ||
520 | return conn_send(conn, skb->data, skb->len, 0, netdev); | 463 | if (err < 0) { |
464 | if (err == -EAGAIN) | ||
465 | netdev->stats.tx_dropped++; | ||
466 | else | ||
467 | netdev->stats.tx_errors++; | ||
468 | } | ||
469 | |||
470 | return err; | ||
521 | } | 471 | } |
522 | 472 | ||
523 | static void send_mcast_pkt(struct sk_buff *skb, struct net_device *netdev) | 473 | static void send_mcast_pkt(struct sk_buff *skb, struct net_device *netdev) |
@@ -540,8 +490,7 @@ static void send_mcast_pkt(struct sk_buff *skb, struct net_device *netdev) | |||
540 | list_for_each_entry_safe(pentry, ptmp, &dev->peers, list) { | 490 | list_for_each_entry_safe(pentry, ptmp, &dev->peers, list) { |
541 | local_skb = skb_clone(skb, GFP_ATOMIC); | 491 | local_skb = skb_clone(skb, GFP_ATOMIC); |
542 | 492 | ||
543 | send_pkt(pentry->conn, netdev->dev_addr, | 493 | send_pkt(pentry->chan, local_skb, netdev); |
544 | pentry->eui64_addr, local_skb, netdev); | ||
545 | 494 | ||
546 | kfree_skb(local_skb); | 495 | kfree_skb(local_skb); |
547 | } | 496 | } |
@@ -553,7 +502,6 @@ static void send_mcast_pkt(struct sk_buff *skb, struct net_device *netdev) | |||
553 | static netdev_tx_t bt_xmit(struct sk_buff *skb, struct net_device *netdev) | 502 | static netdev_tx_t bt_xmit(struct sk_buff *skb, struct net_device *netdev) |
554 | { | 503 | { |
555 | int err = 0; | 504 | int err = 0; |
556 | unsigned char *eui64_addr; | ||
557 | struct lowpan_dev *dev; | 505 | struct lowpan_dev *dev; |
558 | struct lowpan_peer *peer; | 506 | struct lowpan_peer *peer; |
559 | bdaddr_t addr; | 507 | bdaddr_t addr; |
@@ -568,21 +516,20 @@ static netdev_tx_t bt_xmit(struct sk_buff *skb, struct net_device *netdev) | |||
568 | unsigned long flags; | 516 | unsigned long flags; |
569 | 517 | ||
570 | convert_dest_bdaddr(&lowpan_cb(skb)->addr, &addr, &addr_type); | 518 | convert_dest_bdaddr(&lowpan_cb(skb)->addr, &addr, &addr_type); |
571 | eui64_addr = lowpan_cb(skb)->addr.s6_addr + 8; | ||
572 | dev = lowpan_dev(netdev); | 519 | dev = lowpan_dev(netdev); |
573 | 520 | ||
574 | read_lock_irqsave(&devices_lock, flags); | 521 | read_lock_irqsave(&devices_lock, flags); |
575 | peer = peer_lookup_ba(dev, &addr, addr_type); | 522 | peer = peer_lookup_ba(dev, &addr, addr_type); |
576 | read_unlock_irqrestore(&devices_lock, flags); | 523 | read_unlock_irqrestore(&devices_lock, flags); |
577 | 524 | ||
578 | BT_DBG("xmit %s to %pMR type %s IP %pI6c peer %p", | 525 | BT_DBG("xmit %s to %pMR type %d IP %pI6c peer %p", |
579 | netdev->name, &addr, | 526 | netdev->name, &addr, addr_type, |
580 | addr_type == ADDR_LE_DEV_PUBLIC ? "PUBLIC" : "RANDOM", | ||
581 | &lowpan_cb(skb)->addr, peer); | 527 | &lowpan_cb(skb)->addr, peer); |
582 | 528 | ||
583 | if (peer && peer->conn) | 529 | if (peer && peer->chan) |
584 | err = send_pkt(peer->conn, netdev->dev_addr, | 530 | err = send_pkt(peer->chan, skb, netdev); |
585 | eui64_addr, skb, netdev); | 531 | else |
532 | err = -ENOENT; | ||
586 | } | 533 | } |
587 | dev_kfree_skb(skb); | 534 | dev_kfree_skb(skb); |
588 | 535 | ||
@@ -634,7 +581,7 @@ static void set_addr(u8 *eui, u8 *addr, u8 addr_type) | |||
634 | eui[7] = addr[0]; | 581 | eui[7] = addr[0]; |
635 | 582 | ||
636 | /* Universal/local bit set, BT 6lowpan draft ch. 3.2.1 */ | 583 | /* Universal/local bit set, BT 6lowpan draft ch. 3.2.1 */ |
637 | if (addr_type == ADDR_LE_DEV_PUBLIC) | 584 | if (addr_type == BDADDR_LE_PUBLIC) |
638 | eui[0] &= ~0x02; | 585 | eui[0] &= ~0x02; |
639 | else | 586 | else |
640 | eui[0] |= 0x02; | 587 | eui[0] |= 0x02; |
@@ -660,6 +607,17 @@ static void ifup(struct net_device *netdev) | |||
660 | rtnl_unlock(); | 607 | rtnl_unlock(); |
661 | } | 608 | } |
662 | 609 | ||
610 | static void ifdown(struct net_device *netdev) | ||
611 | { | ||
612 | int err; | ||
613 | |||
614 | rtnl_lock(); | ||
615 | err = dev_close(netdev); | ||
616 | if (err < 0) | ||
617 | BT_INFO("iface %s cannot be closed (%d)", netdev->name, err); | ||
618 | rtnl_unlock(); | ||
619 | } | ||
620 | |||
663 | static void do_notify_peers(struct work_struct *work) | 621 | static void do_notify_peers(struct work_struct *work) |
664 | { | 622 | { |
665 | struct lowpan_dev *dev = container_of(work, struct lowpan_dev, | 623 | struct lowpan_dev *dev = container_of(work, struct lowpan_dev, |
@@ -673,26 +631,64 @@ static bool is_bt_6lowpan(struct hci_conn *hcon) | |||
673 | if (hcon->type != LE_LINK) | 631 | if (hcon->type != LE_LINK) |
674 | return false; | 632 | return false; |
675 | 633 | ||
676 | return test_bit(HCI_CONN_6LOWPAN, &hcon->flags); | 634 | if (!psm_6lowpan) |
635 | return false; | ||
636 | |||
637 | return true; | ||
638 | } | ||
639 | |||
640 | static struct l2cap_chan *chan_create(void) | ||
641 | { | ||
642 | struct l2cap_chan *chan; | ||
643 | |||
644 | chan = l2cap_chan_create(); | ||
645 | if (!chan) | ||
646 | return NULL; | ||
647 | |||
648 | l2cap_chan_set_defaults(chan); | ||
649 | |||
650 | chan->chan_type = L2CAP_CHAN_CONN_ORIENTED; | ||
651 | chan->mode = L2CAP_MODE_LE_FLOWCTL; | ||
652 | chan->omtu = 65535; | ||
653 | chan->imtu = chan->omtu; | ||
654 | |||
655 | return chan; | ||
677 | } | 656 | } |
678 | 657 | ||
679 | static int add_peer_conn(struct l2cap_conn *conn, struct lowpan_dev *dev) | 658 | static struct l2cap_chan *chan_open(struct l2cap_chan *pchan) |
659 | { | ||
660 | struct l2cap_chan *chan; | ||
661 | |||
662 | chan = chan_create(); | ||
663 | if (!chan) | ||
664 | return NULL; | ||
665 | |||
666 | chan->remote_mps = chan->omtu; | ||
667 | chan->mps = chan->omtu; | ||
668 | |||
669 | chan->state = BT_CONNECTED; | ||
670 | |||
671 | return chan; | ||
672 | } | ||
673 | |||
674 | static struct l2cap_chan *add_peer_chan(struct l2cap_chan *chan, | ||
675 | struct lowpan_dev *dev) | ||
680 | { | 676 | { |
681 | struct lowpan_peer *peer; | 677 | struct lowpan_peer *peer; |
682 | unsigned long flags; | 678 | unsigned long flags; |
683 | 679 | ||
684 | peer = kzalloc(sizeof(*peer), GFP_ATOMIC); | 680 | peer = kzalloc(sizeof(*peer), GFP_ATOMIC); |
685 | if (!peer) | 681 | if (!peer) |
686 | return -ENOMEM; | 682 | return NULL; |
687 | 683 | ||
688 | peer->conn = conn; | 684 | peer->chan = chan; |
689 | memset(&peer->peer_addr, 0, sizeof(struct in6_addr)); | 685 | memset(&peer->peer_addr, 0, sizeof(struct in6_addr)); |
690 | 686 | ||
691 | /* RFC 2464 ch. 5 */ | 687 | /* RFC 2464 ch. 5 */ |
692 | peer->peer_addr.s6_addr[0] = 0xFE; | 688 | peer->peer_addr.s6_addr[0] = 0xFE; |
693 | peer->peer_addr.s6_addr[1] = 0x80; | 689 | peer->peer_addr.s6_addr[1] = 0x80; |
694 | set_addr((u8 *)&peer->peer_addr.s6_addr + 8, conn->hcon->dst.b, | 690 | set_addr((u8 *)&peer->peer_addr.s6_addr + 8, chan->dst.b, |
695 | conn->hcon->dst_type); | 691 | chan->dst_type); |
696 | 692 | ||
697 | memcpy(&peer->eui64_addr, (u8 *)&peer->peer_addr.s6_addr + 8, | 693 | memcpy(&peer->eui64_addr, (u8 *)&peer->peer_addr.s6_addr + 8, |
698 | EUI64_ADDR_LEN); | 694 | EUI64_ADDR_LEN); |
@@ -706,40 +702,24 @@ static int add_peer_conn(struct l2cap_conn *conn, struct lowpan_dev *dev) | |||
706 | INIT_DELAYED_WORK(&dev->notify_peers, do_notify_peers); | 702 | INIT_DELAYED_WORK(&dev->notify_peers, do_notify_peers); |
707 | schedule_delayed_work(&dev->notify_peers, msecs_to_jiffies(100)); | 703 | schedule_delayed_work(&dev->notify_peers, msecs_to_jiffies(100)); |
708 | 704 | ||
709 | return 0; | 705 | return peer->chan; |
710 | } | 706 | } |
711 | 707 | ||
712 | /* This gets called when BT LE 6LoWPAN device is connected. We then | 708 | static int setup_netdev(struct l2cap_chan *chan, struct lowpan_dev **dev) |
713 | * create network device that acts as a proxy between BT LE device | ||
714 | * and kernel network stack. | ||
715 | */ | ||
716 | int bt_6lowpan_add_conn(struct l2cap_conn *conn) | ||
717 | { | 709 | { |
718 | struct lowpan_peer *peer = NULL; | ||
719 | struct lowpan_dev *dev; | ||
720 | struct net_device *netdev; | 710 | struct net_device *netdev; |
721 | int err = 0; | 711 | int err = 0; |
722 | unsigned long flags; | 712 | unsigned long flags; |
723 | 713 | ||
724 | if (!is_bt_6lowpan(conn->hcon)) | 714 | netdev = alloc_netdev(sizeof(struct lowpan_dev), IFACE_NAME_TEMPLATE, |
725 | return 0; | 715 | NET_NAME_UNKNOWN, netdev_setup); |
726 | |||
727 | peer = lookup_peer(conn); | ||
728 | if (peer) | ||
729 | return -EEXIST; | ||
730 | |||
731 | dev = lookup_dev(conn); | ||
732 | if (dev) | ||
733 | return add_peer_conn(conn, dev); | ||
734 | |||
735 | netdev = alloc_netdev(sizeof(*dev), IFACE_NAME_TEMPLATE, netdev_setup); | ||
736 | if (!netdev) | 716 | if (!netdev) |
737 | return -ENOMEM; | 717 | return -ENOMEM; |
738 | 718 | ||
739 | set_dev_addr(netdev, &conn->hcon->src, conn->hcon->src_type); | 719 | set_dev_addr(netdev, &chan->src, chan->src_type); |
740 | 720 | ||
741 | netdev->netdev_ops = &netdev_ops; | 721 | netdev->netdev_ops = &netdev_ops; |
742 | SET_NETDEV_DEV(netdev, &conn->hcon->dev); | 722 | SET_NETDEV_DEV(netdev, &chan->conn->hcon->dev); |
743 | SET_NETDEV_DEVTYPE(netdev, &bt_type); | 723 | SET_NETDEV_DEVTYPE(netdev, &bt_type); |
744 | 724 | ||
745 | err = register_netdev(netdev); | 725 | err = register_netdev(netdev); |
@@ -749,28 +729,61 @@ int bt_6lowpan_add_conn(struct l2cap_conn *conn) | |||
749 | goto out; | 729 | goto out; |
750 | } | 730 | } |
751 | 731 | ||
752 | BT_DBG("ifindex %d peer bdaddr %pMR my addr %pMR", | 732 | BT_DBG("ifindex %d peer bdaddr %pMR type %d my addr %pMR type %d", |
753 | netdev->ifindex, &conn->hcon->dst, &conn->hcon->src); | 733 | netdev->ifindex, &chan->dst, chan->dst_type, |
734 | &chan->src, chan->src_type); | ||
754 | set_bit(__LINK_STATE_PRESENT, &netdev->state); | 735 | set_bit(__LINK_STATE_PRESENT, &netdev->state); |
755 | 736 | ||
756 | dev = netdev_priv(netdev); | 737 | *dev = netdev_priv(netdev); |
757 | dev->netdev = netdev; | 738 | (*dev)->netdev = netdev; |
758 | dev->hdev = conn->hcon->hdev; | 739 | (*dev)->hdev = chan->conn->hcon->hdev; |
759 | INIT_LIST_HEAD(&dev->peers); | 740 | INIT_LIST_HEAD(&(*dev)->peers); |
760 | 741 | ||
761 | write_lock_irqsave(&devices_lock, flags); | 742 | write_lock_irqsave(&devices_lock, flags); |
762 | INIT_LIST_HEAD(&dev->list); | 743 | INIT_LIST_HEAD(&(*dev)->list); |
763 | list_add(&dev->list, &bt_6lowpan_devices); | 744 | list_add(&(*dev)->list, &bt_6lowpan_devices); |
764 | write_unlock_irqrestore(&devices_lock, flags); | 745 | write_unlock_irqrestore(&devices_lock, flags); |
765 | 746 | ||
766 | ifup(netdev); | 747 | return 0; |
767 | |||
768 | return add_peer_conn(conn, dev); | ||
769 | 748 | ||
770 | out: | 749 | out: |
771 | return err; | 750 | return err; |
772 | } | 751 | } |
773 | 752 | ||
753 | static inline void chan_ready_cb(struct l2cap_chan *chan) | ||
754 | { | ||
755 | struct lowpan_dev *dev; | ||
756 | |||
757 | dev = lookup_dev(chan->conn); | ||
758 | |||
759 | BT_DBG("chan %p conn %p dev %p", chan, chan->conn, dev); | ||
760 | |||
761 | if (!dev) { | ||
762 | if (setup_netdev(chan, &dev) < 0) { | ||
763 | l2cap_chan_del(chan, -ENOENT); | ||
764 | return; | ||
765 | } | ||
766 | } | ||
767 | |||
768 | if (!try_module_get(THIS_MODULE)) | ||
769 | return; | ||
770 | |||
771 | add_peer_chan(chan, dev); | ||
772 | ifup(dev->netdev); | ||
773 | } | ||
774 | |||
775 | static inline struct l2cap_chan *chan_new_conn_cb(struct l2cap_chan *chan) | ||
776 | { | ||
777 | struct l2cap_chan *pchan; | ||
778 | |||
779 | pchan = chan_open(chan); | ||
780 | pchan->ops = chan->ops; | ||
781 | |||
782 | BT_DBG("chan %p pchan %p", chan, pchan); | ||
783 | |||
784 | return pchan; | ||
785 | } | ||
786 | |||
774 | static void delete_netdev(struct work_struct *work) | 787 | static void delete_netdev(struct work_struct *work) |
775 | { | 788 | { |
776 | struct lowpan_dev *entry = container_of(work, struct lowpan_dev, | 789 | struct lowpan_dev *entry = container_of(work, struct lowpan_dev, |
@@ -781,26 +794,43 @@ static void delete_netdev(struct work_struct *work) | |||
781 | /* The entry pointer is deleted in device_event() */ | 794 | /* The entry pointer is deleted in device_event() */ |
782 | } | 795 | } |
783 | 796 | ||
784 | int bt_6lowpan_del_conn(struct l2cap_conn *conn) | 797 | static void chan_close_cb(struct l2cap_chan *chan) |
785 | { | 798 | { |
786 | struct lowpan_dev *entry, *tmp; | 799 | struct lowpan_dev *entry, *tmp; |
787 | struct lowpan_dev *dev = NULL; | 800 | struct lowpan_dev *dev = NULL; |
788 | struct lowpan_peer *peer; | 801 | struct lowpan_peer *peer; |
789 | int err = -ENOENT; | 802 | int err = -ENOENT; |
790 | unsigned long flags; | 803 | unsigned long flags; |
791 | bool last = false; | 804 | bool last = false, removed = true; |
792 | 805 | ||
793 | if (!conn || !is_bt_6lowpan(conn->hcon)) | 806 | BT_DBG("chan %p conn %p", chan, chan->conn); |
794 | return 0; | 807 | |
808 | if (chan->conn && chan->conn->hcon) { | ||
809 | if (!is_bt_6lowpan(chan->conn->hcon)) | ||
810 | return; | ||
811 | |||
812 | /* If conn is set, then the netdev is also there and we should | ||
813 | * not remove it. | ||
814 | */ | ||
815 | removed = false; | ||
816 | } | ||
795 | 817 | ||
796 | write_lock_irqsave(&devices_lock, flags); | 818 | write_lock_irqsave(&devices_lock, flags); |
797 | 819 | ||
798 | list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) { | 820 | list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) { |
799 | dev = lowpan_dev(entry->netdev); | 821 | dev = lowpan_dev(entry->netdev); |
800 | peer = peer_lookup_conn(dev, conn); | 822 | peer = peer_lookup_chan(dev, chan); |
801 | if (peer) { | 823 | if (peer) { |
802 | last = peer_del(dev, peer); | 824 | last = peer_del(dev, peer); |
803 | err = 0; | 825 | err = 0; |
826 | |||
827 | BT_DBG("dev %p removing %speer %p", dev, | ||
828 | last ? "last " : "1 ", peer); | ||
829 | BT_DBG("chan %p orig refcnt %d", chan, | ||
830 | atomic_read(&chan->kref.refcount)); | ||
831 | |||
832 | l2cap_chan_put(chan); | ||
833 | kfree(peer); | ||
804 | break; | 834 | break; |
805 | } | 835 | } |
806 | } | 836 | } |
@@ -810,18 +840,402 @@ int bt_6lowpan_del_conn(struct l2cap_conn *conn) | |||
810 | 840 | ||
811 | cancel_delayed_work_sync(&dev->notify_peers); | 841 | cancel_delayed_work_sync(&dev->notify_peers); |
812 | 842 | ||
813 | /* bt_6lowpan_del_conn() is called with hci dev lock held which | 843 | ifdown(dev->netdev); |
814 | * means that we must delete the netdevice in worker thread. | 844 | |
815 | */ | 845 | if (!removed) { |
816 | INIT_WORK(&entry->delete_netdev, delete_netdev); | 846 | INIT_WORK(&entry->delete_netdev, delete_netdev); |
817 | schedule_work(&entry->delete_netdev); | 847 | schedule_work(&entry->delete_netdev); |
848 | } | ||
818 | } else { | 849 | } else { |
819 | write_unlock_irqrestore(&devices_lock, flags); | 850 | write_unlock_irqrestore(&devices_lock, flags); |
820 | } | 851 | } |
821 | 852 | ||
853 | return; | ||
854 | } | ||
855 | |||
856 | static void chan_state_change_cb(struct l2cap_chan *chan, int state, int err) | ||
857 | { | ||
858 | BT_DBG("chan %p conn %p state %s err %d", chan, chan->conn, | ||
859 | state_to_string(state), err); | ||
860 | } | ||
861 | |||
862 | static struct sk_buff *chan_alloc_skb_cb(struct l2cap_chan *chan, | ||
863 | unsigned long hdr_len, | ||
864 | unsigned long len, int nb) | ||
865 | { | ||
866 | /* Note that we must allocate using GFP_ATOMIC here as | ||
867 | * this function is called originally from netdev hard xmit | ||
868 | * function in atomic context. | ||
869 | */ | ||
870 | return bt_skb_alloc(hdr_len + len, GFP_ATOMIC); | ||
871 | } | ||
872 | |||
873 | static void chan_suspend_cb(struct l2cap_chan *chan) | ||
874 | { | ||
875 | struct sk_buff *skb = chan->data; | ||
876 | |||
877 | BT_DBG("chan %p conn %p skb %p", chan, chan->conn, skb); | ||
878 | |||
879 | lowpan_cb(skb)->status = -EAGAIN; | ||
880 | } | ||
881 | |||
882 | static void chan_resume_cb(struct l2cap_chan *chan) | ||
883 | { | ||
884 | struct sk_buff *skb = chan->data; | ||
885 | |||
886 | BT_DBG("chan %p conn %p skb %p", chan, chan->conn, skb); | ||
887 | |||
888 | lowpan_cb(skb)->status = 0; | ||
889 | } | ||
890 | |||
891 | static long chan_get_sndtimeo_cb(struct l2cap_chan *chan) | ||
892 | { | ||
893 | return msecs_to_jiffies(1000); | ||
894 | } | ||
895 | |||
896 | static const struct l2cap_ops bt_6lowpan_chan_ops = { | ||
897 | .name = "L2CAP 6LoWPAN channel", | ||
898 | .new_connection = chan_new_conn_cb, | ||
899 | .recv = chan_recv_cb, | ||
900 | .close = chan_close_cb, | ||
901 | .state_change = chan_state_change_cb, | ||
902 | .ready = chan_ready_cb, | ||
903 | .resume = chan_resume_cb, | ||
904 | .suspend = chan_suspend_cb, | ||
905 | .get_sndtimeo = chan_get_sndtimeo_cb, | ||
906 | .alloc_skb = chan_alloc_skb_cb, | ||
907 | .memcpy_fromiovec = l2cap_chan_no_memcpy_fromiovec, | ||
908 | |||
909 | .teardown = l2cap_chan_no_teardown, | ||
910 | .defer = l2cap_chan_no_defer, | ||
911 | .set_shutdown = l2cap_chan_no_set_shutdown, | ||
912 | }; | ||
913 | |||
914 | static inline __u8 bdaddr_type(__u8 type) | ||
915 | { | ||
916 | if (type == ADDR_LE_DEV_PUBLIC) | ||
917 | return BDADDR_LE_PUBLIC; | ||
918 | else | ||
919 | return BDADDR_LE_RANDOM; | ||
920 | } | ||
921 | |||
922 | static struct l2cap_chan *chan_get(void) | ||
923 | { | ||
924 | struct l2cap_chan *pchan; | ||
925 | |||
926 | pchan = chan_create(); | ||
927 | if (!pchan) | ||
928 | return NULL; | ||
929 | |||
930 | pchan->ops = &bt_6lowpan_chan_ops; | ||
931 | |||
932 | return pchan; | ||
933 | } | ||
934 | |||
935 | static int bt_6lowpan_connect(bdaddr_t *addr, u8 dst_type) | ||
936 | { | ||
937 | struct l2cap_chan *pchan; | ||
938 | int err; | ||
939 | |||
940 | pchan = chan_get(); | ||
941 | if (!pchan) | ||
942 | return -EINVAL; | ||
943 | |||
944 | err = l2cap_chan_connect(pchan, cpu_to_le16(psm_6lowpan), 0, | ||
945 | addr, dst_type); | ||
946 | |||
947 | BT_DBG("chan %p err %d", pchan, err); | ||
948 | if (err < 0) | ||
949 | l2cap_chan_put(pchan); | ||
950 | |||
822 | return err; | 951 | return err; |
823 | } | 952 | } |
824 | 953 | ||
954 | static int bt_6lowpan_disconnect(struct l2cap_conn *conn, u8 dst_type) | ||
955 | { | ||
956 | struct lowpan_peer *peer; | ||
957 | |||
958 | BT_DBG("conn %p dst type %d", conn, dst_type); | ||
959 | |||
960 | peer = lookup_peer(conn); | ||
961 | if (!peer) | ||
962 | return -ENOENT; | ||
963 | |||
964 | BT_DBG("peer %p chan %p", peer, peer->chan); | ||
965 | |||
966 | l2cap_chan_close(peer->chan, ENOENT); | ||
967 | |||
968 | return 0; | ||
969 | } | ||
970 | |||
971 | static struct l2cap_chan *bt_6lowpan_listen(void) | ||
972 | { | ||
973 | bdaddr_t *addr = BDADDR_ANY; | ||
974 | struct l2cap_chan *pchan; | ||
975 | int err; | ||
976 | |||
977 | if (psm_6lowpan == 0) | ||
978 | return NULL; | ||
979 | |||
980 | pchan = chan_get(); | ||
981 | if (!pchan) | ||
982 | return NULL; | ||
983 | |||
984 | pchan->state = BT_LISTEN; | ||
985 | pchan->src_type = BDADDR_LE_PUBLIC; | ||
986 | |||
987 | BT_DBG("psm 0x%04x chan %p src type %d", psm_6lowpan, pchan, | ||
988 | pchan->src_type); | ||
989 | |||
990 | err = l2cap_add_psm(pchan, addr, cpu_to_le16(psm_6lowpan)); | ||
991 | if (err) { | ||
992 | l2cap_chan_put(pchan); | ||
993 | BT_ERR("psm cannot be added err %d", err); | ||
994 | return NULL; | ||
995 | } | ||
996 | |||
997 | return pchan; | ||
998 | } | ||
999 | |||
1000 | static int get_l2cap_conn(char *buf, bdaddr_t *addr, u8 *addr_type, | ||
1001 | struct l2cap_conn **conn) | ||
1002 | { | ||
1003 | struct hci_conn *hcon; | ||
1004 | struct hci_dev *hdev; | ||
1005 | bdaddr_t *src = BDADDR_ANY; | ||
1006 | int n; | ||
1007 | |||
1008 | n = sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %hhu", | ||
1009 | &addr->b[5], &addr->b[4], &addr->b[3], | ||
1010 | &addr->b[2], &addr->b[1], &addr->b[0], | ||
1011 | addr_type); | ||
1012 | |||
1013 | if (n < 7) | ||
1014 | return -EINVAL; | ||
1015 | |||
1016 | hdev = hci_get_route(addr, src); | ||
1017 | if (!hdev) | ||
1018 | return -ENOENT; | ||
1019 | |||
1020 | hci_dev_lock(hdev); | ||
1021 | hcon = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr); | ||
1022 | hci_dev_unlock(hdev); | ||
1023 | |||
1024 | if (!hcon) | ||
1025 | return -ENOENT; | ||
1026 | |||
1027 | *conn = (struct l2cap_conn *)hcon->l2cap_data; | ||
1028 | |||
1029 | BT_DBG("conn %p dst %pMR type %d", *conn, &hcon->dst, hcon->dst_type); | ||
1030 | |||
1031 | return 0; | ||
1032 | } | ||
1033 | |||
1034 | static void disconnect_all_peers(void) | ||
1035 | { | ||
1036 | struct lowpan_dev *entry, *tmp_dev; | ||
1037 | struct lowpan_peer *peer, *tmp_peer, *new_peer; | ||
1038 | struct list_head peers; | ||
1039 | unsigned long flags; | ||
1040 | |||
1041 | INIT_LIST_HEAD(&peers); | ||
1042 | |||
1043 | /* We make a separate list of peers as the close_cb() will | ||
1044 | * modify the device peers list so it is better not to mess | ||
1045 | * with the same list at the same time. | ||
1046 | */ | ||
1047 | |||
1048 | read_lock_irqsave(&devices_lock, flags); | ||
1049 | |||
1050 | list_for_each_entry_safe(entry, tmp_dev, &bt_6lowpan_devices, list) { | ||
1051 | list_for_each_entry_safe(peer, tmp_peer, &entry->peers, list) { | ||
1052 | new_peer = kmalloc(sizeof(*new_peer), GFP_ATOMIC); | ||
1053 | if (!new_peer) | ||
1054 | break; | ||
1055 | |||
1056 | new_peer->chan = peer->chan; | ||
1057 | INIT_LIST_HEAD(&new_peer->list); | ||
1058 | |||
1059 | list_add(&new_peer->list, &peers); | ||
1060 | } | ||
1061 | } | ||
1062 | |||
1063 | read_unlock_irqrestore(&devices_lock, flags); | ||
1064 | |||
1065 | list_for_each_entry_safe(peer, tmp_peer, &peers, list) { | ||
1066 | l2cap_chan_close(peer->chan, ENOENT); | ||
1067 | kfree(peer); | ||
1068 | } | ||
1069 | } | ||
1070 | |||
1071 | static int lowpan_psm_set(void *data, u64 val) | ||
1072 | { | ||
1073 | u16 psm; | ||
1074 | |||
1075 | psm = val; | ||
1076 | if (psm == 0 || psm_6lowpan != psm) | ||
1077 | /* Disconnect existing connections if 6lowpan is | ||
1078 | * disabled (psm = 0), or if psm changes. | ||
1079 | */ | ||
1080 | disconnect_all_peers(); | ||
1081 | |||
1082 | psm_6lowpan = psm; | ||
1083 | |||
1084 | if (listen_chan) { | ||
1085 | l2cap_chan_close(listen_chan, 0); | ||
1086 | l2cap_chan_put(listen_chan); | ||
1087 | } | ||
1088 | |||
1089 | listen_chan = bt_6lowpan_listen(); | ||
1090 | |||
1091 | return 0; | ||
1092 | } | ||
1093 | |||
1094 | static int lowpan_psm_get(void *data, u64 *val) | ||
1095 | { | ||
1096 | *val = psm_6lowpan; | ||
1097 | return 0; | ||
1098 | } | ||
1099 | |||
1100 | DEFINE_SIMPLE_ATTRIBUTE(lowpan_psm_fops, lowpan_psm_get, | ||
1101 | lowpan_psm_set, "%llu\n"); | ||
1102 | |||
1103 | static ssize_t lowpan_control_write(struct file *fp, | ||
1104 | const char __user *user_buffer, | ||
1105 | size_t count, | ||
1106 | loff_t *position) | ||
1107 | { | ||
1108 | char buf[32]; | ||
1109 | size_t buf_size = min(count, sizeof(buf) - 1); | ||
1110 | int ret; | ||
1111 | bdaddr_t addr; | ||
1112 | u8 addr_type; | ||
1113 | struct l2cap_conn *conn = NULL; | ||
1114 | |||
1115 | if (copy_from_user(buf, user_buffer, buf_size)) | ||
1116 | return -EFAULT; | ||
1117 | |||
1118 | buf[buf_size] = '\0'; | ||
1119 | |||
1120 | if (memcmp(buf, "connect ", 8) == 0) { | ||
1121 | ret = get_l2cap_conn(&buf[8], &addr, &addr_type, &conn); | ||
1122 | if (ret == -EINVAL) | ||
1123 | return ret; | ||
1124 | |||
1125 | if (listen_chan) { | ||
1126 | l2cap_chan_close(listen_chan, 0); | ||
1127 | l2cap_chan_put(listen_chan); | ||
1128 | listen_chan = NULL; | ||
1129 | } | ||
1130 | |||
1131 | if (conn) { | ||
1132 | struct lowpan_peer *peer; | ||
1133 | |||
1134 | if (!is_bt_6lowpan(conn->hcon)) | ||
1135 | return -EINVAL; | ||
1136 | |||
1137 | peer = lookup_peer(conn); | ||
1138 | if (peer) { | ||
1139 | BT_DBG("6LoWPAN connection already exists"); | ||
1140 | return -EALREADY; | ||
1141 | } | ||
1142 | |||
1143 | BT_DBG("conn %p dst %pMR type %d user %d", conn, | ||
1144 | &conn->hcon->dst, conn->hcon->dst_type, | ||
1145 | addr_type); | ||
1146 | } | ||
1147 | |||
1148 | ret = bt_6lowpan_connect(&addr, addr_type); | ||
1149 | if (ret < 0) | ||
1150 | return ret; | ||
1151 | |||
1152 | return count; | ||
1153 | } | ||
1154 | |||
1155 | if (memcmp(buf, "disconnect ", 11) == 0) { | ||
1156 | ret = get_l2cap_conn(&buf[11], &addr, &addr_type, &conn); | ||
1157 | if (ret < 0) | ||
1158 | return ret; | ||
1159 | |||
1160 | ret = bt_6lowpan_disconnect(conn, addr_type); | ||
1161 | if (ret < 0) | ||
1162 | return ret; | ||
1163 | |||
1164 | return count; | ||
1165 | } | ||
1166 | |||
1167 | return count; | ||
1168 | } | ||
1169 | |||
1170 | static int lowpan_control_show(struct seq_file *f, void *ptr) | ||
1171 | { | ||
1172 | struct lowpan_dev *entry, *tmp_dev; | ||
1173 | struct lowpan_peer *peer, *tmp_peer; | ||
1174 | unsigned long flags; | ||
1175 | |||
1176 | read_lock_irqsave(&devices_lock, flags); | ||
1177 | |||
1178 | list_for_each_entry_safe(entry, tmp_dev, &bt_6lowpan_devices, list) { | ||
1179 | list_for_each_entry_safe(peer, tmp_peer, &entry->peers, list) | ||
1180 | seq_printf(f, "%pMR (type %u)\n", | ||
1181 | &peer->chan->dst, peer->chan->dst_type); | ||
1182 | } | ||
1183 | |||
1184 | read_unlock_irqrestore(&devices_lock, flags); | ||
1185 | |||
1186 | return 0; | ||
1187 | } | ||
1188 | |||
1189 | static int lowpan_control_open(struct inode *inode, struct file *file) | ||
1190 | { | ||
1191 | return single_open(file, lowpan_control_show, inode->i_private); | ||
1192 | } | ||
1193 | |||
1194 | static const struct file_operations lowpan_control_fops = { | ||
1195 | .open = lowpan_control_open, | ||
1196 | .read = seq_read, | ||
1197 | .write = lowpan_control_write, | ||
1198 | .llseek = seq_lseek, | ||
1199 | .release = single_release, | ||
1200 | }; | ||
1201 | |||
1202 | static void disconnect_devices(void) | ||
1203 | { | ||
1204 | struct lowpan_dev *entry, *tmp, *new_dev; | ||
1205 | struct list_head devices; | ||
1206 | unsigned long flags; | ||
1207 | |||
1208 | INIT_LIST_HEAD(&devices); | ||
1209 | |||
1210 | /* We make a separate list of devices because the unregister_netdev() | ||
1211 | * will call device_event() which will also want to modify the same | ||
1212 | * devices list. | ||
1213 | */ | ||
1214 | |||
1215 | read_lock_irqsave(&devices_lock, flags); | ||
1216 | |||
1217 | list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, list) { | ||
1218 | new_dev = kmalloc(sizeof(*new_dev), GFP_ATOMIC); | ||
1219 | if (!new_dev) | ||
1220 | break; | ||
1221 | |||
1222 | new_dev->netdev = entry->netdev; | ||
1223 | INIT_LIST_HEAD(&new_dev->list); | ||
1224 | |||
1225 | list_add(&new_dev->list, &devices); | ||
1226 | } | ||
1227 | |||
1228 | read_unlock_irqrestore(&devices_lock, flags); | ||
1229 | |||
1230 | list_for_each_entry_safe(entry, tmp, &devices, list) { | ||
1231 | ifdown(entry->netdev); | ||
1232 | BT_DBG("Unregistering netdev %s %p", | ||
1233 | entry->netdev->name, entry->netdev); | ||
1234 | unregister_netdev(entry->netdev); | ||
1235 | kfree(entry); | ||
1236 | } | ||
1237 | } | ||
1238 | |||
825 | static int device_event(struct notifier_block *unused, | 1239 | static int device_event(struct notifier_block *unused, |
826 | unsigned long event, void *ptr) | 1240 | unsigned long event, void *ptr) |
827 | { | 1241 | { |
@@ -838,6 +1252,8 @@ static int device_event(struct notifier_block *unused, | |||
838 | list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, | 1252 | list_for_each_entry_safe(entry, tmp, &bt_6lowpan_devices, |
839 | list) { | 1253 | list) { |
840 | if (entry->netdev == netdev) { | 1254 | if (entry->netdev == netdev) { |
1255 | BT_DBG("Unregistered netdev %s %p", | ||
1256 | netdev->name, netdev); | ||
841 | list_del(&entry->list); | 1257 | list_del(&entry->list); |
842 | kfree(entry); | 1258 | kfree(entry); |
843 | break; | 1259 | break; |
@@ -854,12 +1270,37 @@ static struct notifier_block bt_6lowpan_dev_notifier = { | |||
854 | .notifier_call = device_event, | 1270 | .notifier_call = device_event, |
855 | }; | 1271 | }; |
856 | 1272 | ||
857 | int bt_6lowpan_init(void) | 1273 | static int __init bt_6lowpan_init(void) |
858 | { | 1274 | { |
1275 | lowpan_psm_debugfs = debugfs_create_file("6lowpan_psm", 0644, | ||
1276 | bt_debugfs, NULL, | ||
1277 | &lowpan_psm_fops); | ||
1278 | lowpan_control_debugfs = debugfs_create_file("6lowpan_control", 0644, | ||
1279 | bt_debugfs, NULL, | ||
1280 | &lowpan_control_fops); | ||
1281 | |||
859 | return register_netdevice_notifier(&bt_6lowpan_dev_notifier); | 1282 | return register_netdevice_notifier(&bt_6lowpan_dev_notifier); |
860 | } | 1283 | } |
861 | 1284 | ||
862 | void bt_6lowpan_cleanup(void) | 1285 | static void __exit bt_6lowpan_exit(void) |
863 | { | 1286 | { |
1287 | debugfs_remove(lowpan_psm_debugfs); | ||
1288 | debugfs_remove(lowpan_control_debugfs); | ||
1289 | |||
1290 | if (listen_chan) { | ||
1291 | l2cap_chan_close(listen_chan, 0); | ||
1292 | l2cap_chan_put(listen_chan); | ||
1293 | } | ||
1294 | |||
1295 | disconnect_devices(); | ||
1296 | |||
864 | unregister_netdevice_notifier(&bt_6lowpan_dev_notifier); | 1297 | unregister_netdevice_notifier(&bt_6lowpan_dev_notifier); |
865 | } | 1298 | } |
1299 | |||
1300 | module_init(bt_6lowpan_init); | ||
1301 | module_exit(bt_6lowpan_exit); | ||
1302 | |||
1303 | MODULE_AUTHOR("Jukka Rissanen <jukka.rissanen@linux.intel.com>"); | ||
1304 | MODULE_DESCRIPTION("Bluetooth 6LoWPAN"); | ||
1305 | MODULE_VERSION(VERSION); | ||
1306 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/bluetooth/6lowpan.h b/net/bluetooth/6lowpan.h deleted file mode 100644 index 5d281f1eaf55..000000000000 --- a/net/bluetooth/6lowpan.h +++ /dev/null | |||
@@ -1,47 +0,0 @@ | |||
1 | /* | ||
2 | Copyright (c) 2013 Intel Corp. | ||
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 and | ||
6 | only version 2 as published by the Free Software Foundation. | ||
7 | |||
8 | This program is distributed in the hope that it will be useful, | ||
9 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
11 | GNU General Public License for more details. | ||
12 | */ | ||
13 | |||
14 | #ifndef __6LOWPAN_H | ||
15 | #define __6LOWPAN_H | ||
16 | |||
17 | #include <linux/errno.h> | ||
18 | #include <linux/skbuff.h> | ||
19 | #include <net/bluetooth/l2cap.h> | ||
20 | |||
21 | #if IS_ENABLED(CONFIG_BT_6LOWPAN) | ||
22 | int bt_6lowpan_recv(struct l2cap_conn *conn, struct sk_buff *skb); | ||
23 | int bt_6lowpan_add_conn(struct l2cap_conn *conn); | ||
24 | int bt_6lowpan_del_conn(struct l2cap_conn *conn); | ||
25 | int bt_6lowpan_init(void); | ||
26 | void bt_6lowpan_cleanup(void); | ||
27 | #else | ||
28 | static int bt_6lowpan_recv(struct l2cap_conn *conn, struct sk_buff *skb) | ||
29 | { | ||
30 | return -EOPNOTSUPP; | ||
31 | } | ||
32 | static int bt_6lowpan_add_conn(struct l2cap_conn *conn) | ||
33 | { | ||
34 | return -EOPNOTSUPP; | ||
35 | } | ||
36 | int bt_6lowpan_del_conn(struct l2cap_conn *conn) | ||
37 | { | ||
38 | return -EOPNOTSUPP; | ||
39 | } | ||
40 | static int bt_6lowpan_init(void) | ||
41 | { | ||
42 | return -EOPNOTSUPP; | ||
43 | } | ||
44 | static void bt_6lowpan_cleanup(void) { } | ||
45 | #endif | ||
46 | |||
47 | #endif /* __6LOWPAN_H */ | ||
diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig index 06ec14499ca1..600fb29288f4 100644 --- a/net/bluetooth/Kconfig +++ b/net/bluetooth/Kconfig | |||
@@ -6,7 +6,6 @@ menuconfig BT | |||
6 | tristate "Bluetooth subsystem support" | 6 | tristate "Bluetooth subsystem support" |
7 | depends on NET && !S390 | 7 | depends on NET && !S390 |
8 | depends on RFKILL || !RFKILL | 8 | depends on RFKILL || !RFKILL |
9 | select 6LOWPAN_IPHC if BT_6LOWPAN | ||
10 | select CRC16 | 9 | select CRC16 |
11 | select CRYPTO | 10 | select CRYPTO |
12 | select CRYPTO_BLKCIPHER | 11 | select CRYPTO_BLKCIPHER |
@@ -41,10 +40,10 @@ menuconfig BT | |||
41 | more information, see <http://www.bluez.org/>. | 40 | more information, see <http://www.bluez.org/>. |
42 | 41 | ||
43 | config BT_6LOWPAN | 42 | config BT_6LOWPAN |
44 | bool "Bluetooth 6LoWPAN support" | 43 | tristate "Bluetooth 6LoWPAN support" |
45 | depends on BT && IPV6 | 44 | depends on BT && 6LOWPAN |
46 | help | 45 | help |
47 | IPv6 compression over Bluetooth. | 46 | IPv6 compression over Bluetooth Low Energy. |
48 | 47 | ||
49 | source "net/bluetooth/rfcomm/Kconfig" | 48 | source "net/bluetooth/rfcomm/Kconfig" |
50 | 49 | ||
diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile index ca51246b1016..886e9aa3ecf1 100644 --- a/net/bluetooth/Makefile +++ b/net/bluetooth/Makefile | |||
@@ -7,10 +7,12 @@ obj-$(CONFIG_BT_RFCOMM) += rfcomm/ | |||
7 | obj-$(CONFIG_BT_BNEP) += bnep/ | 7 | obj-$(CONFIG_BT_BNEP) += bnep/ |
8 | obj-$(CONFIG_BT_CMTP) += cmtp/ | 8 | obj-$(CONFIG_BT_CMTP) += cmtp/ |
9 | obj-$(CONFIG_BT_HIDP) += hidp/ | 9 | obj-$(CONFIG_BT_HIDP) += hidp/ |
10 | obj-$(CONFIG_BT_6LOWPAN) += bluetooth_6lowpan.o | ||
11 | |||
12 | bluetooth_6lowpan-y := 6lowpan.o | ||
10 | 13 | ||
11 | bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \ | 14 | bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \ |
12 | hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o \ | 15 | hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o \ |
13 | a2mp.o amp.o | 16 | a2mp.o amp.o |
14 | bluetooth-$(CONFIG_BT_6LOWPAN) += 6lowpan.o | ||
15 | 17 | ||
16 | subdir-ccflags-y += -D__CHECK_ENDIAN__ | 18 | subdir-ccflags-y += -D__CHECK_ENDIAN__ |
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index 9514cc9e850c..5dcade511fdb 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c | |||
@@ -63,7 +63,7 @@ void a2mp_send(struct amp_mgr *mgr, u8 code, u8 ident, u16 len, void *data) | |||
63 | msg.msg_iov = (struct iovec *) &iv; | 63 | msg.msg_iov = (struct iovec *) &iv; |
64 | msg.msg_iovlen = 1; | 64 | msg.msg_iovlen = 1; |
65 | 65 | ||
66 | l2cap_chan_send(chan, &msg, total_len, 0); | 66 | l2cap_chan_send(chan, &msg, total_len); |
67 | 67 | ||
68 | kfree(cmd); | 68 | kfree(cmd); |
69 | } | 69 | } |
@@ -693,18 +693,19 @@ static void a2mp_chan_state_change_cb(struct l2cap_chan *chan, int state, | |||
693 | } | 693 | } |
694 | 694 | ||
695 | static struct sk_buff *a2mp_chan_alloc_skb_cb(struct l2cap_chan *chan, | 695 | static struct sk_buff *a2mp_chan_alloc_skb_cb(struct l2cap_chan *chan, |
696 | unsigned long hdr_len, | ||
696 | unsigned long len, int nb) | 697 | unsigned long len, int nb) |
697 | { | 698 | { |
698 | struct sk_buff *skb; | 699 | struct sk_buff *skb; |
699 | 700 | ||
700 | skb = bt_skb_alloc(len, GFP_KERNEL); | 701 | skb = bt_skb_alloc(hdr_len + len, GFP_KERNEL); |
701 | if (!skb) | 702 | if (!skb) |
702 | return ERR_PTR(-ENOMEM); | 703 | return ERR_PTR(-ENOMEM); |
703 | 704 | ||
704 | return skb; | 705 | return skb; |
705 | } | 706 | } |
706 | 707 | ||
707 | static struct l2cap_ops a2mp_chan_ops = { | 708 | static const struct l2cap_ops a2mp_chan_ops = { |
708 | .name = "L2CAP A2MP channel", | 709 | .name = "L2CAP A2MP channel", |
709 | .recv = a2mp_chan_recv_cb, | 710 | .recv = a2mp_chan_recv_cb, |
710 | .close = a2mp_chan_close_cb, | 711 | .close = a2mp_chan_close_cb, |
@@ -719,6 +720,7 @@ static struct l2cap_ops a2mp_chan_ops = { | |||
719 | .resume = l2cap_chan_no_resume, | 720 | .resume = l2cap_chan_no_resume, |
720 | .set_shutdown = l2cap_chan_no_set_shutdown, | 721 | .set_shutdown = l2cap_chan_no_set_shutdown, |
721 | .get_sndtimeo = l2cap_chan_no_get_sndtimeo, | 722 | .get_sndtimeo = l2cap_chan_no_get_sndtimeo, |
723 | .memcpy_fromiovec = l2cap_chan_no_memcpy_fromiovec, | ||
722 | }; | 724 | }; |
723 | 725 | ||
724 | static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked) | 726 | static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked) |
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 2021c481cdb6..4dca0299ed96 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c | |||
@@ -639,7 +639,7 @@ static int bt_seq_show(struct seq_file *seq, void *v) | |||
639 | return 0; | 639 | return 0; |
640 | } | 640 | } |
641 | 641 | ||
642 | static struct seq_operations bt_seq_ops = { | 642 | static const struct seq_operations bt_seq_ops = { |
643 | .start = bt_seq_start, | 643 | .start = bt_seq_start, |
644 | .next = bt_seq_next, | 644 | .next = bt_seq_next, |
645 | .stop = bt_seq_stop, | 645 | .stop = bt_seq_stop, |
diff --git a/net/bluetooth/amp.c b/net/bluetooth/amp.c index bb39509b3f06..016cdb66df6c 100644 --- a/net/bluetooth/amp.c +++ b/net/bluetooth/amp.c | |||
@@ -113,8 +113,9 @@ struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr, | |||
113 | { | 113 | { |
114 | bdaddr_t *dst = &mgr->l2cap_conn->hcon->dst; | 114 | bdaddr_t *dst = &mgr->l2cap_conn->hcon->dst; |
115 | struct hci_conn *hcon; | 115 | struct hci_conn *hcon; |
116 | u8 role = out ? HCI_ROLE_MASTER : HCI_ROLE_SLAVE; | ||
116 | 117 | ||
117 | hcon = hci_conn_add(hdev, AMP_LINK, dst); | 118 | hcon = hci_conn_add(hdev, AMP_LINK, dst, role); |
118 | if (!hcon) | 119 | if (!hcon) |
119 | return NULL; | 120 | return NULL; |
120 | 121 | ||
@@ -125,7 +126,6 @@ struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr, | |||
125 | hcon->handle = __next_handle(mgr); | 126 | hcon->handle = __next_handle(mgr); |
126 | hcon->remote_id = remote_id; | 127 | hcon->remote_id = remote_id; |
127 | hcon->amp_mgr = amp_mgr_get(mgr); | 128 | hcon->amp_mgr = amp_mgr_get(mgr); |
128 | hcon->out = out; | ||
129 | 129 | ||
130 | return hcon; | 130 | return hcon; |
131 | } | 131 | } |
@@ -133,8 +133,8 @@ struct hci_conn *phylink_add(struct hci_dev *hdev, struct amp_mgr *mgr, | |||
133 | /* AMP crypto key generation interface */ | 133 | /* AMP crypto key generation interface */ |
134 | static int hmac_sha256(u8 *key, u8 ksize, char *plaintext, u8 psize, u8 *output) | 134 | static int hmac_sha256(u8 *key, u8 ksize, char *plaintext, u8 psize, u8 *output) |
135 | { | 135 | { |
136 | int ret = 0; | ||
137 | struct crypto_shash *tfm; | 136 | struct crypto_shash *tfm; |
137 | int ret; | ||
138 | 138 | ||
139 | if (!ksize) | 139 | if (!ksize) |
140 | return -EINVAL; | 140 | return -EINVAL; |
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index a841d3e776c5..85bcc21e84d2 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c | |||
@@ -538,8 +538,9 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) | |||
538 | 538 | ||
539 | /* session struct allocated as private part of net_device */ | 539 | /* session struct allocated as private part of net_device */ |
540 | dev = alloc_netdev(sizeof(struct bnep_session), | 540 | dev = alloc_netdev(sizeof(struct bnep_session), |
541 | (*req->device) ? req->device : "bnep%d", | 541 | (*req->device) ? req->device : "bnep%d", |
542 | bnep_net_setup); | 542 | NET_NAME_UNKNOWN, |
543 | bnep_net_setup); | ||
543 | if (!dev) | 544 | if (!dev) |
544 | return -ENOMEM; | 545 | return -ENOMEM; |
545 | 546 | ||
diff --git a/net/bluetooth/cmtp/capi.c b/net/bluetooth/cmtp/capi.c index cd75e4d64b90..1ca8a87a0787 100644 --- a/net/bluetooth/cmtp/capi.c +++ b/net/bluetooth/cmtp/capi.c | |||
@@ -362,12 +362,6 @@ void cmtp_recv_capimsg(struct cmtp_session *session, struct sk_buff *skb) | |||
362 | CAPIMSG_SETCONTROL(skb->data, contr); | 362 | CAPIMSG_SETCONTROL(skb->data, contr); |
363 | } | 363 | } |
364 | 364 | ||
365 | if (!ctrl) { | ||
366 | BT_ERR("Can't find controller %d for message", session->num); | ||
367 | kfree_skb(skb); | ||
368 | return; | ||
369 | } | ||
370 | |||
371 | capi_ctr_handle_message(ctrl, appl, skb); | 365 | capi_ctr_handle_message(ctrl, appl, skb); |
372 | } | 366 | } |
373 | 367 | ||
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index a7a27bc2c0b1..faff6247ac8f 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -66,8 +66,7 @@ static void hci_acl_create_connection(struct hci_conn *conn) | |||
66 | 66 | ||
67 | conn->state = BT_CONNECT; | 67 | conn->state = BT_CONNECT; |
68 | conn->out = true; | 68 | conn->out = true; |
69 | 69 | conn->role = HCI_ROLE_MASTER; | |
70 | conn->link_mode = HCI_LM_MASTER; | ||
71 | 70 | ||
72 | conn->attempt++; | 71 | conn->attempt++; |
73 | 72 | ||
@@ -136,7 +135,7 @@ void hci_disconnect(struct hci_conn *conn, __u8 reason) | |||
136 | hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp); | 135 | hci_send_cmd(conn->hdev, HCI_OP_DISCONNECT, sizeof(cp), &cp); |
137 | } | 136 | } |
138 | 137 | ||
139 | static void hci_amp_disconn(struct hci_conn *conn, __u8 reason) | 138 | static void hci_amp_disconn(struct hci_conn *conn) |
140 | { | 139 | { |
141 | struct hci_cp_disconn_phy_link cp; | 140 | struct hci_cp_disconn_phy_link cp; |
142 | 141 | ||
@@ -145,7 +144,7 @@ static void hci_amp_disconn(struct hci_conn *conn, __u8 reason) | |||
145 | conn->state = BT_DISCONN; | 144 | conn->state = BT_DISCONN; |
146 | 145 | ||
147 | cp.phy_handle = HCI_PHY_HANDLE(conn->handle); | 146 | cp.phy_handle = HCI_PHY_HANDLE(conn->handle); |
148 | cp.reason = reason; | 147 | cp.reason = hci_proto_disconn_ind(conn); |
149 | hci_send_cmd(conn->hdev, HCI_OP_DISCONN_PHY_LINK, | 148 | hci_send_cmd(conn->hdev, HCI_OP_DISCONN_PHY_LINK, |
150 | sizeof(cp), &cp); | 149 | sizeof(cp), &cp); |
151 | } | 150 | } |
@@ -213,14 +212,26 @@ bool hci_setup_sync(struct hci_conn *conn, __u16 handle) | |||
213 | return true; | 212 | return true; |
214 | } | 213 | } |
215 | 214 | ||
216 | void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, | 215 | u8 hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, u16 latency, |
217 | u16 latency, u16 to_multiplier) | 216 | u16 to_multiplier) |
218 | { | 217 | { |
219 | struct hci_cp_le_conn_update cp; | ||
220 | struct hci_dev *hdev = conn->hdev; | 218 | struct hci_dev *hdev = conn->hdev; |
219 | struct hci_conn_params *params; | ||
220 | struct hci_cp_le_conn_update cp; | ||
221 | 221 | ||
222 | memset(&cp, 0, sizeof(cp)); | 222 | hci_dev_lock(hdev); |
223 | 223 | ||
224 | params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type); | ||
225 | if (params) { | ||
226 | params->conn_min_interval = min; | ||
227 | params->conn_max_interval = max; | ||
228 | params->conn_latency = latency; | ||
229 | params->supervision_timeout = to_multiplier; | ||
230 | } | ||
231 | |||
232 | hci_dev_unlock(hdev); | ||
233 | |||
234 | memset(&cp, 0, sizeof(cp)); | ||
224 | cp.handle = cpu_to_le16(conn->handle); | 235 | cp.handle = cpu_to_le16(conn->handle); |
225 | cp.conn_interval_min = cpu_to_le16(min); | 236 | cp.conn_interval_min = cpu_to_le16(min); |
226 | cp.conn_interval_max = cpu_to_le16(max); | 237 | cp.conn_interval_max = cpu_to_le16(max); |
@@ -230,6 +241,11 @@ void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, | |||
230 | cp.max_ce_len = cpu_to_le16(0x0000); | 241 | cp.max_ce_len = cpu_to_le16(0x0000); |
231 | 242 | ||
232 | hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp); | 243 | hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp); |
244 | |||
245 | if (params) | ||
246 | return 0x01; | ||
247 | |||
248 | return 0x00; | ||
233 | } | 249 | } |
234 | 250 | ||
235 | void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __le64 rand, | 251 | void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __le64 rand, |
@@ -271,20 +287,6 @@ void hci_sco_setup(struct hci_conn *conn, __u8 status) | |||
271 | } | 287 | } |
272 | } | 288 | } |
273 | 289 | ||
274 | static void hci_conn_disconnect(struct hci_conn *conn) | ||
275 | { | ||
276 | __u8 reason = hci_proto_disconn_ind(conn); | ||
277 | |||
278 | switch (conn->type) { | ||
279 | case AMP_LINK: | ||
280 | hci_amp_disconn(conn, reason); | ||
281 | break; | ||
282 | default: | ||
283 | hci_disconnect(conn, reason); | ||
284 | break; | ||
285 | } | ||
286 | } | ||
287 | |||
288 | static void hci_conn_timeout(struct work_struct *work) | 290 | static void hci_conn_timeout(struct work_struct *work) |
289 | { | 291 | { |
290 | struct hci_conn *conn = container_of(work, struct hci_conn, | 292 | struct hci_conn *conn = container_of(work, struct hci_conn, |
@@ -319,7 +321,31 @@ static void hci_conn_timeout(struct work_struct *work) | |||
319 | break; | 321 | break; |
320 | case BT_CONFIG: | 322 | case BT_CONFIG: |
321 | case BT_CONNECTED: | 323 | case BT_CONNECTED: |
322 | hci_conn_disconnect(conn); | 324 | if (conn->type == AMP_LINK) { |
325 | hci_amp_disconn(conn); | ||
326 | } else { | ||
327 | __u8 reason = hci_proto_disconn_ind(conn); | ||
328 | |||
329 | /* When we are master of an established connection | ||
330 | * and it enters the disconnect timeout, then go | ||
331 | * ahead and try to read the current clock offset. | ||
332 | * | ||
333 | * Processing of the result is done within the | ||
334 | * event handling and hci_clock_offset_evt function. | ||
335 | */ | ||
336 | if (conn->type == ACL_LINK && | ||
337 | conn->role == HCI_ROLE_MASTER) { | ||
338 | struct hci_dev *hdev = conn->hdev; | ||
339 | struct hci_cp_read_clock_offset cp; | ||
340 | |||
341 | cp.handle = cpu_to_le16(conn->handle); | ||
342 | |||
343 | hci_send_cmd(hdev, HCI_OP_READ_CLOCK_OFFSET, | ||
344 | sizeof(cp), &cp); | ||
345 | } | ||
346 | |||
347 | hci_disconnect(conn, reason); | ||
348 | } | ||
323 | break; | 349 | break; |
324 | default: | 350 | default: |
325 | conn->state = BT_CLOSED; | 351 | conn->state = BT_CLOSED; |
@@ -336,9 +362,6 @@ static void hci_conn_idle(struct work_struct *work) | |||
336 | 362 | ||
337 | BT_DBG("hcon %p mode %d", conn, conn->mode); | 363 | BT_DBG("hcon %p mode %d", conn, conn->mode); |
338 | 364 | ||
339 | if (test_bit(HCI_RAW, &hdev->flags)) | ||
340 | return; | ||
341 | |||
342 | if (!lmp_sniff_capable(hdev) || !lmp_sniff_capable(conn)) | 365 | if (!lmp_sniff_capable(hdev) || !lmp_sniff_capable(conn)) |
343 | return; | 366 | return; |
344 | 367 | ||
@@ -398,13 +421,14 @@ static void le_conn_timeout(struct work_struct *work) | |||
398 | hci_le_create_connection_cancel(conn); | 421 | hci_le_create_connection_cancel(conn); |
399 | } | 422 | } |
400 | 423 | ||
401 | struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) | 424 | struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst, |
425 | u8 role) | ||
402 | { | 426 | { |
403 | struct hci_conn *conn; | 427 | struct hci_conn *conn; |
404 | 428 | ||
405 | BT_DBG("%s dst %pMR", hdev->name, dst); | 429 | BT_DBG("%s dst %pMR", hdev->name, dst); |
406 | 430 | ||
407 | conn = kzalloc(sizeof(struct hci_conn), GFP_KERNEL); | 431 | conn = kzalloc(sizeof(*conn), GFP_KERNEL); |
408 | if (!conn) | 432 | if (!conn) |
409 | return NULL; | 433 | return NULL; |
410 | 434 | ||
@@ -412,6 +436,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) | |||
412 | bacpy(&conn->src, &hdev->bdaddr); | 436 | bacpy(&conn->src, &hdev->bdaddr); |
413 | conn->hdev = hdev; | 437 | conn->hdev = hdev; |
414 | conn->type = type; | 438 | conn->type = type; |
439 | conn->role = role; | ||
415 | conn->mode = HCI_CM_ACTIVE; | 440 | conn->mode = HCI_CM_ACTIVE; |
416 | conn->state = BT_OPEN; | 441 | conn->state = BT_OPEN; |
417 | conn->auth_type = HCI_AT_GENERAL_BONDING; | 442 | conn->auth_type = HCI_AT_GENERAL_BONDING; |
@@ -424,6 +449,9 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) | |||
424 | set_bit(HCI_CONN_POWER_SAVE, &conn->flags); | 449 | set_bit(HCI_CONN_POWER_SAVE, &conn->flags); |
425 | conn->disc_timeout = HCI_DISCONN_TIMEOUT; | 450 | conn->disc_timeout = HCI_DISCONN_TIMEOUT; |
426 | 451 | ||
452 | if (conn->role == HCI_ROLE_MASTER) | ||
453 | conn->out = true; | ||
454 | |||
427 | switch (type) { | 455 | switch (type) { |
428 | case ACL_LINK: | 456 | case ACL_LINK: |
429 | conn->pkt_type = hdev->pkt_type & ACL_PTYPE_MASK; | 457 | conn->pkt_type = hdev->pkt_type & ACL_PTYPE_MASK; |
@@ -529,7 +557,6 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src) | |||
529 | 557 | ||
530 | list_for_each_entry(d, &hci_dev_list, list) { | 558 | list_for_each_entry(d, &hci_dev_list, list) { |
531 | if (!test_bit(HCI_UP, &d->flags) || | 559 | if (!test_bit(HCI_UP, &d->flags) || |
532 | test_bit(HCI_RAW, &d->flags) || | ||
533 | test_bit(HCI_USER_CHANNEL, &d->dev_flags) || | 560 | test_bit(HCI_USER_CHANNEL, &d->dev_flags) || |
534 | d->dev_type != HCI_BREDR) | 561 | d->dev_type != HCI_BREDR) |
535 | continue; | 562 | continue; |
@@ -562,6 +589,14 @@ EXPORT_SYMBOL(hci_get_route); | |||
562 | void hci_le_conn_failed(struct hci_conn *conn, u8 status) | 589 | void hci_le_conn_failed(struct hci_conn *conn, u8 status) |
563 | { | 590 | { |
564 | struct hci_dev *hdev = conn->hdev; | 591 | struct hci_dev *hdev = conn->hdev; |
592 | struct hci_conn_params *params; | ||
593 | |||
594 | params = hci_pend_le_action_lookup(&hdev->pend_le_conns, &conn->dst, | ||
595 | conn->dst_type); | ||
596 | if (params && params->conn) { | ||
597 | hci_conn_drop(params->conn); | ||
598 | params->conn = NULL; | ||
599 | } | ||
565 | 600 | ||
566 | conn->state = BT_CLOSED; | 601 | conn->state = BT_CLOSED; |
567 | 602 | ||
@@ -627,7 +662,8 @@ static void hci_req_add_le_create_conn(struct hci_request *req, | |||
627 | cp.own_address_type = own_addr_type; | 662 | cp.own_address_type = own_addr_type; |
628 | cp.conn_interval_min = cpu_to_le16(conn->le_conn_min_interval); | 663 | cp.conn_interval_min = cpu_to_le16(conn->le_conn_min_interval); |
629 | cp.conn_interval_max = cpu_to_le16(conn->le_conn_max_interval); | 664 | cp.conn_interval_max = cpu_to_le16(conn->le_conn_max_interval); |
630 | cp.supervision_timeout = cpu_to_le16(0x002a); | 665 | cp.conn_latency = cpu_to_le16(conn->le_conn_latency); |
666 | cp.supervision_timeout = cpu_to_le16(conn->le_supv_timeout); | ||
631 | cp.min_ce_len = cpu_to_le16(0x0000); | 667 | cp.min_ce_len = cpu_to_le16(0x0000); |
632 | cp.max_ce_len = cpu_to_le16(0x0000); | 668 | cp.max_ce_len = cpu_to_le16(0x0000); |
633 | 669 | ||
@@ -644,15 +680,12 @@ static void hci_req_directed_advertising(struct hci_request *req, | |||
644 | u8 own_addr_type; | 680 | u8 own_addr_type; |
645 | u8 enable; | 681 | u8 enable; |
646 | 682 | ||
647 | enable = 0x00; | 683 | /* Clear the HCI_LE_ADV bit temporarily so that the |
648 | hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable); | ||
649 | |||
650 | /* Clear the HCI_ADVERTISING bit temporarily so that the | ||
651 | * hci_update_random_address knows that it's safe to go ahead | 684 | * hci_update_random_address knows that it's safe to go ahead |
652 | * and write a new random address. The flag will be set back on | 685 | * and write a new random address. The flag will be set back on |
653 | * as soon as the SET_ADV_ENABLE HCI command completes. | 686 | * as soon as the SET_ADV_ENABLE HCI command completes. |
654 | */ | 687 | */ |
655 | clear_bit(HCI_ADVERTISING, &hdev->dev_flags); | 688 | clear_bit(HCI_LE_ADV, &hdev->dev_flags); |
656 | 689 | ||
657 | /* Set require_privacy to false so that the remote device has a | 690 | /* Set require_privacy to false so that the remote device has a |
658 | * chance of identifying us. | 691 | * chance of identifying us. |
@@ -676,7 +709,8 @@ static void hci_req_directed_advertising(struct hci_request *req, | |||
676 | } | 709 | } |
677 | 710 | ||
678 | struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, | 711 | struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, |
679 | u8 dst_type, u8 sec_level, u8 auth_type) | 712 | u8 dst_type, u8 sec_level, u16 conn_timeout, |
713 | u8 role) | ||
680 | { | 714 | { |
681 | struct hci_conn_params *params; | 715 | struct hci_conn_params *params; |
682 | struct hci_conn *conn; | 716 | struct hci_conn *conn; |
@@ -696,7 +730,6 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, | |||
696 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst); | 730 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, dst); |
697 | if (conn) { | 731 | if (conn) { |
698 | conn->pending_sec_level = sec_level; | 732 | conn->pending_sec_level = sec_level; |
699 | conn->auth_type = auth_type; | ||
700 | goto done; | 733 | goto done; |
701 | } | 734 | } |
702 | 735 | ||
@@ -726,32 +759,56 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, | |||
726 | dst_type = ADDR_LE_DEV_RANDOM; | 759 | dst_type = ADDR_LE_DEV_RANDOM; |
727 | } | 760 | } |
728 | 761 | ||
729 | conn = hci_conn_add(hdev, LE_LINK, dst); | 762 | conn = hci_conn_add(hdev, LE_LINK, dst, role); |
730 | if (!conn) | 763 | if (!conn) |
731 | return ERR_PTR(-ENOMEM); | 764 | return ERR_PTR(-ENOMEM); |
732 | 765 | ||
733 | conn->dst_type = dst_type; | 766 | conn->dst_type = dst_type; |
734 | conn->sec_level = BT_SECURITY_LOW; | 767 | conn->sec_level = BT_SECURITY_LOW; |
735 | conn->pending_sec_level = sec_level; | 768 | conn->pending_sec_level = sec_level; |
736 | conn->auth_type = auth_type; | 769 | conn->conn_timeout = conn_timeout; |
737 | 770 | ||
738 | hci_req_init(&req, hdev); | 771 | hci_req_init(&req, hdev); |
739 | 772 | ||
740 | if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) { | 773 | /* Disable advertising if we're active. For master role |
774 | * connections most controllers will refuse to connect if | ||
775 | * advertising is enabled, and for slave role connections we | ||
776 | * anyway have to disable it in order to start directed | ||
777 | * advertising. | ||
778 | */ | ||
779 | if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) { | ||
780 | u8 enable = 0x00; | ||
781 | hci_req_add(&req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), | ||
782 | &enable); | ||
783 | } | ||
784 | |||
785 | /* If requested to connect as slave use directed advertising */ | ||
786 | if (conn->role == HCI_ROLE_SLAVE) { | ||
787 | /* If we're active scanning most controllers are unable | ||
788 | * to initiate advertising. Simply reject the attempt. | ||
789 | */ | ||
790 | if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) && | ||
791 | hdev->le_scan_type == LE_SCAN_ACTIVE) { | ||
792 | skb_queue_purge(&req.cmd_q); | ||
793 | hci_conn_del(conn); | ||
794 | return ERR_PTR(-EBUSY); | ||
795 | } | ||
796 | |||
741 | hci_req_directed_advertising(&req, conn); | 797 | hci_req_directed_advertising(&req, conn); |
742 | goto create_conn; | 798 | goto create_conn; |
743 | } | 799 | } |
744 | 800 | ||
745 | conn->out = true; | ||
746 | conn->link_mode |= HCI_LM_MASTER; | ||
747 | |||
748 | params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type); | 801 | params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type); |
749 | if (params) { | 802 | if (params) { |
750 | conn->le_conn_min_interval = params->conn_min_interval; | 803 | conn->le_conn_min_interval = params->conn_min_interval; |
751 | conn->le_conn_max_interval = params->conn_max_interval; | 804 | conn->le_conn_max_interval = params->conn_max_interval; |
805 | conn->le_conn_latency = params->conn_latency; | ||
806 | conn->le_supv_timeout = params->supervision_timeout; | ||
752 | } else { | 807 | } else { |
753 | conn->le_conn_min_interval = hdev->le_conn_min_interval; | 808 | conn->le_conn_min_interval = hdev->le_conn_min_interval; |
754 | conn->le_conn_max_interval = hdev->le_conn_max_interval; | 809 | conn->le_conn_max_interval = hdev->le_conn_max_interval; |
810 | conn->le_conn_latency = hdev->le_conn_latency; | ||
811 | conn->le_supv_timeout = hdev->le_supv_timeout; | ||
755 | } | 812 | } |
756 | 813 | ||
757 | /* If controller is scanning, we stop it since some controllers are | 814 | /* If controller is scanning, we stop it since some controllers are |
@@ -785,11 +842,11 @@ struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, | |||
785 | struct hci_conn *acl; | 842 | struct hci_conn *acl; |
786 | 843 | ||
787 | if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) | 844 | if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) |
788 | return ERR_PTR(-ENOTSUPP); | 845 | return ERR_PTR(-EOPNOTSUPP); |
789 | 846 | ||
790 | acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst); | 847 | acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst); |
791 | if (!acl) { | 848 | if (!acl) { |
792 | acl = hci_conn_add(hdev, ACL_LINK, dst); | 849 | acl = hci_conn_add(hdev, ACL_LINK, dst, HCI_ROLE_MASTER); |
793 | if (!acl) | 850 | if (!acl) |
794 | return ERR_PTR(-ENOMEM); | 851 | return ERR_PTR(-ENOMEM); |
795 | } | 852 | } |
@@ -818,7 +875,7 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst, | |||
818 | 875 | ||
819 | sco = hci_conn_hash_lookup_ba(hdev, type, dst); | 876 | sco = hci_conn_hash_lookup_ba(hdev, type, dst); |
820 | if (!sco) { | 877 | if (!sco) { |
821 | sco = hci_conn_add(hdev, type, dst); | 878 | sco = hci_conn_add(hdev, type, dst, HCI_ROLE_MASTER); |
822 | if (!sco) { | 879 | if (!sco) { |
823 | hci_conn_drop(acl); | 880 | hci_conn_drop(acl); |
824 | return ERR_PTR(-ENOMEM); | 881 | return ERR_PTR(-ENOMEM); |
@@ -865,7 +922,8 @@ int hci_conn_check_link_mode(struct hci_conn *conn) | |||
865 | return 0; | 922 | return 0; |
866 | } | 923 | } |
867 | 924 | ||
868 | if (hci_conn_ssp_enabled(conn) && !(conn->link_mode & HCI_LM_ENCRYPT)) | 925 | if (hci_conn_ssp_enabled(conn) && |
926 | !test_bit(HCI_CONN_ENCRYPT, &conn->flags)) | ||
869 | return 0; | 927 | return 0; |
870 | 928 | ||
871 | return 1; | 929 | return 1; |
@@ -881,7 +939,7 @@ static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) | |||
881 | 939 | ||
882 | if (sec_level > conn->sec_level) | 940 | if (sec_level > conn->sec_level) |
883 | conn->pending_sec_level = sec_level; | 941 | conn->pending_sec_level = sec_level; |
884 | else if (conn->link_mode & HCI_LM_AUTH) | 942 | else if (test_bit(HCI_CONN_AUTH, &conn->flags)) |
885 | return 1; | 943 | return 1; |
886 | 944 | ||
887 | /* Make sure we preserve an existing MITM requirement*/ | 945 | /* Make sure we preserve an existing MITM requirement*/ |
@@ -899,7 +957,7 @@ static int hci_conn_auth(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) | |||
899 | /* If we're already encrypted set the REAUTH_PEND flag, | 957 | /* If we're already encrypted set the REAUTH_PEND flag, |
900 | * otherwise set the ENCRYPT_PEND. | 958 | * otherwise set the ENCRYPT_PEND. |
901 | */ | 959 | */ |
902 | if (conn->link_mode & HCI_LM_ENCRYPT) | 960 | if (test_bit(HCI_CONN_ENCRYPT, &conn->flags)) |
903 | set_bit(HCI_CONN_REAUTH_PEND, &conn->flags); | 961 | set_bit(HCI_CONN_REAUTH_PEND, &conn->flags); |
904 | else | 962 | else |
905 | set_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); | 963 | set_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); |
@@ -923,7 +981,8 @@ static void hci_conn_encrypt(struct hci_conn *conn) | |||
923 | } | 981 | } |
924 | 982 | ||
925 | /* Enable security */ | 983 | /* Enable security */ |
926 | int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) | 984 | int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type, |
985 | bool initiator) | ||
927 | { | 986 | { |
928 | BT_DBG("hcon %p", conn); | 987 | BT_DBG("hcon %p", conn); |
929 | 988 | ||
@@ -940,7 +999,7 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) | |||
940 | return 1; | 999 | return 1; |
941 | 1000 | ||
942 | /* For other security levels we need the link key. */ | 1001 | /* For other security levels we need the link key. */ |
943 | if (!(conn->link_mode & HCI_LM_AUTH)) | 1002 | if (!test_bit(HCI_CONN_AUTH, &conn->flags)) |
944 | goto auth; | 1003 | goto auth; |
945 | 1004 | ||
946 | /* An authenticated FIPS approved combination key has sufficient | 1005 | /* An authenticated FIPS approved combination key has sufficient |
@@ -976,11 +1035,14 @@ auth: | |||
976 | if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) | 1035 | if (test_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags)) |
977 | return 0; | 1036 | return 0; |
978 | 1037 | ||
1038 | if (initiator) | ||
1039 | set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags); | ||
1040 | |||
979 | if (!hci_conn_auth(conn, sec_level, auth_type)) | 1041 | if (!hci_conn_auth(conn, sec_level, auth_type)) |
980 | return 0; | 1042 | return 0; |
981 | 1043 | ||
982 | encrypt: | 1044 | encrypt: |
983 | if (conn->link_mode & HCI_LM_ENCRYPT) | 1045 | if (test_bit(HCI_CONN_ENCRYPT, &conn->flags)) |
984 | return 1; | 1046 | return 1; |
985 | 1047 | ||
986 | hci_conn_encrypt(conn); | 1048 | hci_conn_encrypt(conn); |
@@ -1027,7 +1089,7 @@ int hci_conn_switch_role(struct hci_conn *conn, __u8 role) | |||
1027 | { | 1089 | { |
1028 | BT_DBG("hcon %p", conn); | 1090 | BT_DBG("hcon %p", conn); |
1029 | 1091 | ||
1030 | if (!role && conn->link_mode & HCI_LM_MASTER) | 1092 | if (role == conn->role) |
1031 | return 1; | 1093 | return 1; |
1032 | 1094 | ||
1033 | if (!test_and_set_bit(HCI_CONN_RSWITCH_PEND, &conn->flags)) { | 1095 | if (!test_and_set_bit(HCI_CONN_RSWITCH_PEND, &conn->flags)) { |
@@ -1048,9 +1110,6 @@ void hci_conn_enter_active_mode(struct hci_conn *conn, __u8 force_active) | |||
1048 | 1110 | ||
1049 | BT_DBG("hcon %p mode %d", conn, conn->mode); | 1111 | BT_DBG("hcon %p mode %d", conn, conn->mode); |
1050 | 1112 | ||
1051 | if (test_bit(HCI_RAW, &hdev->flags)) | ||
1052 | return; | ||
1053 | |||
1054 | if (conn->mode != HCI_CM_SNIFF) | 1113 | if (conn->mode != HCI_CM_SNIFF) |
1055 | goto timer; | 1114 | goto timer; |
1056 | 1115 | ||
@@ -1101,6 +1160,28 @@ void hci_conn_check_pending(struct hci_dev *hdev) | |||
1101 | hci_dev_unlock(hdev); | 1160 | hci_dev_unlock(hdev); |
1102 | } | 1161 | } |
1103 | 1162 | ||
1163 | static u32 get_link_mode(struct hci_conn *conn) | ||
1164 | { | ||
1165 | u32 link_mode = 0; | ||
1166 | |||
1167 | if (conn->role == HCI_ROLE_MASTER) | ||
1168 | link_mode |= HCI_LM_MASTER; | ||
1169 | |||
1170 | if (test_bit(HCI_CONN_ENCRYPT, &conn->flags)) | ||
1171 | link_mode |= HCI_LM_ENCRYPT; | ||
1172 | |||
1173 | if (test_bit(HCI_CONN_AUTH, &conn->flags)) | ||
1174 | link_mode |= HCI_LM_AUTH; | ||
1175 | |||
1176 | if (test_bit(HCI_CONN_SECURE, &conn->flags)) | ||
1177 | link_mode |= HCI_LM_SECURE; | ||
1178 | |||
1179 | if (test_bit(HCI_CONN_FIPS, &conn->flags)) | ||
1180 | link_mode |= HCI_LM_FIPS; | ||
1181 | |||
1182 | return link_mode; | ||
1183 | } | ||
1184 | |||
1104 | int hci_get_conn_list(void __user *arg) | 1185 | int hci_get_conn_list(void __user *arg) |
1105 | { | 1186 | { |
1106 | struct hci_conn *c; | 1187 | struct hci_conn *c; |
@@ -1136,7 +1217,7 @@ int hci_get_conn_list(void __user *arg) | |||
1136 | (ci + n)->type = c->type; | 1217 | (ci + n)->type = c->type; |
1137 | (ci + n)->out = c->out; | 1218 | (ci + n)->out = c->out; |
1138 | (ci + n)->state = c->state; | 1219 | (ci + n)->state = c->state; |
1139 | (ci + n)->link_mode = c->link_mode; | 1220 | (ci + n)->link_mode = get_link_mode(c); |
1140 | if (++n >= req.conn_num) | 1221 | if (++n >= req.conn_num) |
1141 | break; | 1222 | break; |
1142 | } | 1223 | } |
@@ -1172,7 +1253,7 @@ int hci_get_conn_info(struct hci_dev *hdev, void __user *arg) | |||
1172 | ci.type = conn->type; | 1253 | ci.type = conn->type; |
1173 | ci.out = conn->out; | 1254 | ci.out = conn->out; |
1174 | ci.state = conn->state; | 1255 | ci.state = conn->state; |
1175 | ci.link_mode = conn->link_mode; | 1256 | ci.link_mode = get_link_mode(conn); |
1176 | } | 1257 | } |
1177 | hci_dev_unlock(hdev); | 1258 | hci_dev_unlock(hdev); |
1178 | 1259 | ||
@@ -1209,7 +1290,7 @@ struct hci_chan *hci_chan_create(struct hci_conn *conn) | |||
1209 | 1290 | ||
1210 | BT_DBG("%s hcon %p", hdev->name, conn); | 1291 | BT_DBG("%s hcon %p", hdev->name, conn); |
1211 | 1292 | ||
1212 | chan = kzalloc(sizeof(struct hci_chan), GFP_KERNEL); | 1293 | chan = kzalloc(sizeof(*chan), GFP_KERNEL); |
1213 | if (!chan) | 1294 | if (!chan) |
1214 | return NULL; | 1295 | return NULL; |
1215 | 1296 | ||
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 0a43cce9a914..1d9c29a00568 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -35,6 +35,7 @@ | |||
35 | #include <net/bluetooth/bluetooth.h> | 35 | #include <net/bluetooth/bluetooth.h> |
36 | #include <net/bluetooth/hci_core.h> | 36 | #include <net/bluetooth/hci_core.h> |
37 | #include <net/bluetooth/l2cap.h> | 37 | #include <net/bluetooth/l2cap.h> |
38 | #include <net/bluetooth/mgmt.h> | ||
38 | 39 | ||
39 | #include "smp.h" | 40 | #include "smp.h" |
40 | 41 | ||
@@ -53,6 +54,15 @@ DEFINE_RWLOCK(hci_cb_list_lock); | |||
53 | /* HCI ID Numbering */ | 54 | /* HCI ID Numbering */ |
54 | static DEFINE_IDA(hci_index_ida); | 55 | static DEFINE_IDA(hci_index_ida); |
55 | 56 | ||
57 | /* ----- HCI requests ----- */ | ||
58 | |||
59 | #define HCI_REQ_DONE 0 | ||
60 | #define HCI_REQ_PEND 1 | ||
61 | #define HCI_REQ_CANCELED 2 | ||
62 | |||
63 | #define hci_req_lock(d) mutex_lock(&d->req_lock) | ||
64 | #define hci_req_unlock(d) mutex_unlock(&d->req_lock) | ||
65 | |||
56 | /* ---- HCI notifications ---- */ | 66 | /* ---- HCI notifications ---- */ |
57 | 67 | ||
58 | static void hci_notify(struct hci_dev *hdev, int event) | 68 | static void hci_notify(struct hci_dev *hdev, int event) |
@@ -68,7 +78,7 @@ static ssize_t dut_mode_read(struct file *file, char __user *user_buf, | |||
68 | struct hci_dev *hdev = file->private_data; | 78 | struct hci_dev *hdev = file->private_data; |
69 | char buf[3]; | 79 | char buf[3]; |
70 | 80 | ||
71 | buf[0] = test_bit(HCI_DUT_MODE, &hdev->dev_flags) ? 'Y': 'N'; | 81 | buf[0] = test_bit(HCI_DUT_MODE, &hdev->dbg_flags) ? 'Y': 'N'; |
72 | buf[1] = '\n'; | 82 | buf[1] = '\n'; |
73 | buf[2] = '\0'; | 83 | buf[2] = '\0'; |
74 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); | 84 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); |
@@ -94,7 +104,7 @@ static ssize_t dut_mode_write(struct file *file, const char __user *user_buf, | |||
94 | if (strtobool(buf, &enable)) | 104 | if (strtobool(buf, &enable)) |
95 | return -EINVAL; | 105 | return -EINVAL; |
96 | 106 | ||
97 | if (enable == test_bit(HCI_DUT_MODE, &hdev->dev_flags)) | 107 | if (enable == test_bit(HCI_DUT_MODE, &hdev->dbg_flags)) |
98 | return -EALREADY; | 108 | return -EALREADY; |
99 | 109 | ||
100 | hci_req_lock(hdev); | 110 | hci_req_lock(hdev); |
@@ -115,7 +125,7 @@ static ssize_t dut_mode_write(struct file *file, const char __user *user_buf, | |||
115 | if (err < 0) | 125 | if (err < 0) |
116 | return err; | 126 | return err; |
117 | 127 | ||
118 | change_bit(HCI_DUT_MODE, &hdev->dev_flags); | 128 | change_bit(HCI_DUT_MODE, &hdev->dbg_flags); |
119 | 129 | ||
120 | return count; | 130 | return count; |
121 | } | 131 | } |
@@ -190,6 +200,31 @@ static const struct file_operations blacklist_fops = { | |||
190 | .release = single_release, | 200 | .release = single_release, |
191 | }; | 201 | }; |
192 | 202 | ||
203 | static int whitelist_show(struct seq_file *f, void *p) | ||
204 | { | ||
205 | struct hci_dev *hdev = f->private; | ||
206 | struct bdaddr_list *b; | ||
207 | |||
208 | hci_dev_lock(hdev); | ||
209 | list_for_each_entry(b, &hdev->whitelist, list) | ||
210 | seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type); | ||
211 | hci_dev_unlock(hdev); | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static int whitelist_open(struct inode *inode, struct file *file) | ||
217 | { | ||
218 | return single_open(file, whitelist_show, inode->i_private); | ||
219 | } | ||
220 | |||
221 | static const struct file_operations whitelist_fops = { | ||
222 | .open = whitelist_open, | ||
223 | .read = seq_read, | ||
224 | .llseek = seq_lseek, | ||
225 | .release = single_release, | ||
226 | }; | ||
227 | |||
193 | static int uuids_show(struct seq_file *f, void *p) | 228 | static int uuids_show(struct seq_file *f, void *p) |
194 | { | 229 | { |
195 | struct hci_dev *hdev = f->private; | 230 | struct hci_dev *hdev = f->private; |
@@ -352,62 +387,13 @@ static int auto_accept_delay_get(void *data, u64 *val) | |||
352 | DEFINE_SIMPLE_ATTRIBUTE(auto_accept_delay_fops, auto_accept_delay_get, | 387 | DEFINE_SIMPLE_ATTRIBUTE(auto_accept_delay_fops, auto_accept_delay_get, |
353 | auto_accept_delay_set, "%llu\n"); | 388 | auto_accept_delay_set, "%llu\n"); |
354 | 389 | ||
355 | static int ssp_debug_mode_set(void *data, u64 val) | ||
356 | { | ||
357 | struct hci_dev *hdev = data; | ||
358 | struct sk_buff *skb; | ||
359 | __u8 mode; | ||
360 | int err; | ||
361 | |||
362 | if (val != 0 && val != 1) | ||
363 | return -EINVAL; | ||
364 | |||
365 | if (!test_bit(HCI_UP, &hdev->flags)) | ||
366 | return -ENETDOWN; | ||
367 | |||
368 | hci_req_lock(hdev); | ||
369 | mode = val; | ||
370 | skb = __hci_cmd_sync(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE, sizeof(mode), | ||
371 | &mode, HCI_CMD_TIMEOUT); | ||
372 | hci_req_unlock(hdev); | ||
373 | |||
374 | if (IS_ERR(skb)) | ||
375 | return PTR_ERR(skb); | ||
376 | |||
377 | err = -bt_to_errno(skb->data[0]); | ||
378 | kfree_skb(skb); | ||
379 | |||
380 | if (err < 0) | ||
381 | return err; | ||
382 | |||
383 | hci_dev_lock(hdev); | ||
384 | hdev->ssp_debug_mode = val; | ||
385 | hci_dev_unlock(hdev); | ||
386 | |||
387 | return 0; | ||
388 | } | ||
389 | |||
390 | static int ssp_debug_mode_get(void *data, u64 *val) | ||
391 | { | ||
392 | struct hci_dev *hdev = data; | ||
393 | |||
394 | hci_dev_lock(hdev); | ||
395 | *val = hdev->ssp_debug_mode; | ||
396 | hci_dev_unlock(hdev); | ||
397 | |||
398 | return 0; | ||
399 | } | ||
400 | |||
401 | DEFINE_SIMPLE_ATTRIBUTE(ssp_debug_mode_fops, ssp_debug_mode_get, | ||
402 | ssp_debug_mode_set, "%llu\n"); | ||
403 | |||
404 | static ssize_t force_sc_support_read(struct file *file, char __user *user_buf, | 390 | static ssize_t force_sc_support_read(struct file *file, char __user *user_buf, |
405 | size_t count, loff_t *ppos) | 391 | size_t count, loff_t *ppos) |
406 | { | 392 | { |
407 | struct hci_dev *hdev = file->private_data; | 393 | struct hci_dev *hdev = file->private_data; |
408 | char buf[3]; | 394 | char buf[3]; |
409 | 395 | ||
410 | buf[0] = test_bit(HCI_FORCE_SC, &hdev->dev_flags) ? 'Y': 'N'; | 396 | buf[0] = test_bit(HCI_FORCE_SC, &hdev->dbg_flags) ? 'Y': 'N'; |
411 | buf[1] = '\n'; | 397 | buf[1] = '\n'; |
412 | buf[2] = '\0'; | 398 | buf[2] = '\0'; |
413 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); | 399 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); |
@@ -432,10 +418,10 @@ static ssize_t force_sc_support_write(struct file *file, | |||
432 | if (strtobool(buf, &enable)) | 418 | if (strtobool(buf, &enable)) |
433 | return -EINVAL; | 419 | return -EINVAL; |
434 | 420 | ||
435 | if (enable == test_bit(HCI_FORCE_SC, &hdev->dev_flags)) | 421 | if (enable == test_bit(HCI_FORCE_SC, &hdev->dbg_flags)) |
436 | return -EALREADY; | 422 | return -EALREADY; |
437 | 423 | ||
438 | change_bit(HCI_FORCE_SC, &hdev->dev_flags); | 424 | change_bit(HCI_FORCE_SC, &hdev->dbg_flags); |
439 | 425 | ||
440 | return count; | 426 | return count; |
441 | } | 427 | } |
@@ -719,7 +705,7 @@ static ssize_t force_static_address_read(struct file *file, | |||
719 | struct hci_dev *hdev = file->private_data; | 705 | struct hci_dev *hdev = file->private_data; |
720 | char buf[3]; | 706 | char buf[3]; |
721 | 707 | ||
722 | buf[0] = test_bit(HCI_FORCE_STATIC_ADDR, &hdev->dev_flags) ? 'Y': 'N'; | 708 | buf[0] = test_bit(HCI_FORCE_STATIC_ADDR, &hdev->dbg_flags) ? 'Y': 'N'; |
723 | buf[1] = '\n'; | 709 | buf[1] = '\n'; |
724 | buf[2] = '\0'; | 710 | buf[2] = '\0'; |
725 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); | 711 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); |
@@ -744,10 +730,10 @@ static ssize_t force_static_address_write(struct file *file, | |||
744 | if (strtobool(buf, &enable)) | 730 | if (strtobool(buf, &enable)) |
745 | return -EINVAL; | 731 | return -EINVAL; |
746 | 732 | ||
747 | if (enable == test_bit(HCI_FORCE_STATIC_ADDR, &hdev->dev_flags)) | 733 | if (enable == test_bit(HCI_FORCE_STATIC_ADDR, &hdev->dbg_flags)) |
748 | return -EALREADY; | 734 | return -EALREADY; |
749 | 735 | ||
750 | change_bit(HCI_FORCE_STATIC_ADDR, &hdev->dev_flags); | 736 | change_bit(HCI_FORCE_STATIC_ADDR, &hdev->dbg_flags); |
751 | 737 | ||
752 | return count; | 738 | return count; |
753 | } | 739 | } |
@@ -900,177 +886,169 @@ static int conn_max_interval_get(void *data, u64 *val) | |||
900 | DEFINE_SIMPLE_ATTRIBUTE(conn_max_interval_fops, conn_max_interval_get, | 886 | DEFINE_SIMPLE_ATTRIBUTE(conn_max_interval_fops, conn_max_interval_get, |
901 | conn_max_interval_set, "%llu\n"); | 887 | conn_max_interval_set, "%llu\n"); |
902 | 888 | ||
903 | static int adv_channel_map_set(void *data, u64 val) | 889 | static int conn_latency_set(void *data, u64 val) |
904 | { | 890 | { |
905 | struct hci_dev *hdev = data; | 891 | struct hci_dev *hdev = data; |
906 | 892 | ||
907 | if (val < 0x01 || val > 0x07) | 893 | if (val > 0x01f3) |
908 | return -EINVAL; | 894 | return -EINVAL; |
909 | 895 | ||
910 | hci_dev_lock(hdev); | 896 | hci_dev_lock(hdev); |
911 | hdev->le_adv_channel_map = val; | 897 | hdev->le_conn_latency = val; |
912 | hci_dev_unlock(hdev); | 898 | hci_dev_unlock(hdev); |
913 | 899 | ||
914 | return 0; | 900 | return 0; |
915 | } | 901 | } |
916 | 902 | ||
917 | static int adv_channel_map_get(void *data, u64 *val) | 903 | static int conn_latency_get(void *data, u64 *val) |
918 | { | 904 | { |
919 | struct hci_dev *hdev = data; | 905 | struct hci_dev *hdev = data; |
920 | 906 | ||
921 | hci_dev_lock(hdev); | 907 | hci_dev_lock(hdev); |
922 | *val = hdev->le_adv_channel_map; | 908 | *val = hdev->le_conn_latency; |
923 | hci_dev_unlock(hdev); | 909 | hci_dev_unlock(hdev); |
924 | 910 | ||
925 | return 0; | 911 | return 0; |
926 | } | 912 | } |
927 | 913 | ||
928 | DEFINE_SIMPLE_ATTRIBUTE(adv_channel_map_fops, adv_channel_map_get, | 914 | DEFINE_SIMPLE_ATTRIBUTE(conn_latency_fops, conn_latency_get, |
929 | adv_channel_map_set, "%llu\n"); | 915 | conn_latency_set, "%llu\n"); |
930 | 916 | ||
931 | static ssize_t lowpan_read(struct file *file, char __user *user_buf, | 917 | static int supervision_timeout_set(void *data, u64 val) |
932 | size_t count, loff_t *ppos) | ||
933 | { | 918 | { |
934 | struct hci_dev *hdev = file->private_data; | 919 | struct hci_dev *hdev = data; |
935 | char buf[3]; | ||
936 | 920 | ||
937 | buf[0] = test_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags) ? 'Y' : 'N'; | 921 | if (val < 0x000a || val > 0x0c80) |
938 | buf[1] = '\n'; | 922 | return -EINVAL; |
939 | buf[2] = '\0'; | 923 | |
940 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); | 924 | hci_dev_lock(hdev); |
925 | hdev->le_supv_timeout = val; | ||
926 | hci_dev_unlock(hdev); | ||
927 | |||
928 | return 0; | ||
941 | } | 929 | } |
942 | 930 | ||
943 | static ssize_t lowpan_write(struct file *fp, const char __user *user_buffer, | 931 | static int supervision_timeout_get(void *data, u64 *val) |
944 | size_t count, loff_t *position) | ||
945 | { | 932 | { |
946 | struct hci_dev *hdev = fp->private_data; | 933 | struct hci_dev *hdev = data; |
947 | bool enable; | ||
948 | char buf[32]; | ||
949 | size_t buf_size = min(count, (sizeof(buf)-1)); | ||
950 | 934 | ||
951 | if (copy_from_user(buf, user_buffer, buf_size)) | 935 | hci_dev_lock(hdev); |
952 | return -EFAULT; | 936 | *val = hdev->le_supv_timeout; |
937 | hci_dev_unlock(hdev); | ||
953 | 938 | ||
954 | buf[buf_size] = '\0'; | 939 | return 0; |
940 | } | ||
955 | 941 | ||
956 | if (strtobool(buf, &enable) < 0) | 942 | DEFINE_SIMPLE_ATTRIBUTE(supervision_timeout_fops, supervision_timeout_get, |
957 | return -EINVAL; | 943 | supervision_timeout_set, "%llu\n"); |
958 | 944 | ||
959 | if (enable == test_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags)) | 945 | static int adv_channel_map_set(void *data, u64 val) |
960 | return -EALREADY; | 946 | { |
947 | struct hci_dev *hdev = data; | ||
961 | 948 | ||
962 | change_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags); | 949 | if (val < 0x01 || val > 0x07) |
950 | return -EINVAL; | ||
963 | 951 | ||
964 | return count; | 952 | hci_dev_lock(hdev); |
965 | } | 953 | hdev->le_adv_channel_map = val; |
954 | hci_dev_unlock(hdev); | ||
966 | 955 | ||
967 | static const struct file_operations lowpan_debugfs_fops = { | 956 | return 0; |
968 | .open = simple_open, | 957 | } |
969 | .read = lowpan_read, | ||
970 | .write = lowpan_write, | ||
971 | .llseek = default_llseek, | ||
972 | }; | ||
973 | 958 | ||
974 | static int le_auto_conn_show(struct seq_file *sf, void *ptr) | 959 | static int adv_channel_map_get(void *data, u64 *val) |
975 | { | 960 | { |
976 | struct hci_dev *hdev = sf->private; | 961 | struct hci_dev *hdev = data; |
977 | struct hci_conn_params *p; | ||
978 | 962 | ||
979 | hci_dev_lock(hdev); | 963 | hci_dev_lock(hdev); |
964 | *val = hdev->le_adv_channel_map; | ||
965 | hci_dev_unlock(hdev); | ||
980 | 966 | ||
981 | list_for_each_entry(p, &hdev->le_conn_params, list) { | 967 | return 0; |
982 | seq_printf(sf, "%pMR %u %u\n", &p->addr, p->addr_type, | 968 | } |
983 | p->auto_connect); | 969 | |
984 | } | 970 | DEFINE_SIMPLE_ATTRIBUTE(adv_channel_map_fops, adv_channel_map_get, |
971 | adv_channel_map_set, "%llu\n"); | ||
985 | 972 | ||
973 | static int adv_min_interval_set(void *data, u64 val) | ||
974 | { | ||
975 | struct hci_dev *hdev = data; | ||
976 | |||
977 | if (val < 0x0020 || val > 0x4000 || val > hdev->le_adv_max_interval) | ||
978 | return -EINVAL; | ||
979 | |||
980 | hci_dev_lock(hdev); | ||
981 | hdev->le_adv_min_interval = val; | ||
986 | hci_dev_unlock(hdev); | 982 | hci_dev_unlock(hdev); |
987 | 983 | ||
988 | return 0; | 984 | return 0; |
989 | } | 985 | } |
990 | 986 | ||
991 | static int le_auto_conn_open(struct inode *inode, struct file *file) | 987 | static int adv_min_interval_get(void *data, u64 *val) |
992 | { | 988 | { |
993 | return single_open(file, le_auto_conn_show, inode->i_private); | 989 | struct hci_dev *hdev = data; |
990 | |||
991 | hci_dev_lock(hdev); | ||
992 | *val = hdev->le_adv_min_interval; | ||
993 | hci_dev_unlock(hdev); | ||
994 | |||
995 | return 0; | ||
994 | } | 996 | } |
995 | 997 | ||
996 | static ssize_t le_auto_conn_write(struct file *file, const char __user *data, | 998 | DEFINE_SIMPLE_ATTRIBUTE(adv_min_interval_fops, adv_min_interval_get, |
997 | size_t count, loff_t *offset) | 999 | adv_min_interval_set, "%llu\n"); |
1000 | |||
1001 | static int adv_max_interval_set(void *data, u64 val) | ||
998 | { | 1002 | { |
999 | struct seq_file *sf = file->private_data; | 1003 | struct hci_dev *hdev = data; |
1000 | struct hci_dev *hdev = sf->private; | ||
1001 | u8 auto_connect = 0; | ||
1002 | bdaddr_t addr; | ||
1003 | u8 addr_type; | ||
1004 | char *buf; | ||
1005 | int err = 0; | ||
1006 | int n; | ||
1007 | 1004 | ||
1008 | /* Don't allow partial write */ | 1005 | if (val < 0x0020 || val > 0x4000 || val < hdev->le_adv_min_interval) |
1009 | if (*offset != 0) | ||
1010 | return -EINVAL; | 1006 | return -EINVAL; |
1011 | 1007 | ||
1012 | if (count < 3) | 1008 | hci_dev_lock(hdev); |
1013 | return -EINVAL; | 1009 | hdev->le_adv_max_interval = val; |
1010 | hci_dev_unlock(hdev); | ||
1014 | 1011 | ||
1015 | buf = memdup_user(data, count); | 1012 | return 0; |
1016 | if (IS_ERR(buf)) | 1013 | } |
1017 | return PTR_ERR(buf); | ||
1018 | 1014 | ||
1019 | if (memcmp(buf, "add", 3) == 0) { | 1015 | static int adv_max_interval_get(void *data, u64 *val) |
1020 | n = sscanf(&buf[4], "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %hhu %hhu", | 1016 | { |
1021 | &addr.b[5], &addr.b[4], &addr.b[3], &addr.b[2], | 1017 | struct hci_dev *hdev = data; |
1022 | &addr.b[1], &addr.b[0], &addr_type, | ||
1023 | &auto_connect); | ||
1024 | 1018 | ||
1025 | if (n < 7) { | 1019 | hci_dev_lock(hdev); |
1026 | err = -EINVAL; | 1020 | *val = hdev->le_adv_max_interval; |
1027 | goto done; | 1021 | hci_dev_unlock(hdev); |
1028 | } | ||
1029 | 1022 | ||
1030 | hci_dev_lock(hdev); | 1023 | return 0; |
1031 | err = hci_conn_params_add(hdev, &addr, addr_type, auto_connect, | 1024 | } |
1032 | hdev->le_conn_min_interval, | ||
1033 | hdev->le_conn_max_interval); | ||
1034 | hci_dev_unlock(hdev); | ||
1035 | 1025 | ||
1036 | if (err) | 1026 | DEFINE_SIMPLE_ATTRIBUTE(adv_max_interval_fops, adv_max_interval_get, |
1037 | goto done; | 1027 | adv_max_interval_set, "%llu\n"); |
1038 | } else if (memcmp(buf, "del", 3) == 0) { | ||
1039 | n = sscanf(&buf[4], "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %hhu", | ||
1040 | &addr.b[5], &addr.b[4], &addr.b[3], &addr.b[2], | ||
1041 | &addr.b[1], &addr.b[0], &addr_type); | ||
1042 | 1028 | ||
1043 | if (n < 7) { | 1029 | static int device_list_show(struct seq_file *f, void *ptr) |
1044 | err = -EINVAL; | 1030 | { |
1045 | goto done; | 1031 | struct hci_dev *hdev = f->private; |
1046 | } | 1032 | struct hci_conn_params *p; |
1047 | 1033 | ||
1048 | hci_dev_lock(hdev); | 1034 | hci_dev_lock(hdev); |
1049 | hci_conn_params_del(hdev, &addr, addr_type); | 1035 | list_for_each_entry(p, &hdev->le_conn_params, list) { |
1050 | hci_dev_unlock(hdev); | 1036 | seq_printf(f, "%pMR %u %u\n", &p->addr, p->addr_type, |
1051 | } else if (memcmp(buf, "clr", 3) == 0) { | 1037 | p->auto_connect); |
1052 | hci_dev_lock(hdev); | ||
1053 | hci_conn_params_clear(hdev); | ||
1054 | hci_pend_le_conns_clear(hdev); | ||
1055 | hci_update_background_scan(hdev); | ||
1056 | hci_dev_unlock(hdev); | ||
1057 | } else { | ||
1058 | err = -EINVAL; | ||
1059 | } | 1038 | } |
1039 | hci_dev_unlock(hdev); | ||
1060 | 1040 | ||
1061 | done: | 1041 | return 0; |
1062 | kfree(buf); | 1042 | } |
1063 | 1043 | ||
1064 | if (err) | 1044 | static int device_list_open(struct inode *inode, struct file *file) |
1065 | return err; | 1045 | { |
1066 | else | 1046 | return single_open(file, device_list_show, inode->i_private); |
1067 | return count; | ||
1068 | } | 1047 | } |
1069 | 1048 | ||
1070 | static const struct file_operations le_auto_conn_fops = { | 1049 | static const struct file_operations device_list_fops = { |
1071 | .open = le_auto_conn_open, | 1050 | .open = device_list_open, |
1072 | .read = seq_read, | 1051 | .read = seq_read, |
1073 | .write = le_auto_conn_write, | ||
1074 | .llseek = seq_lseek, | 1052 | .llseek = seq_lseek, |
1075 | .release = single_release, | 1053 | .release = single_release, |
1076 | }; | 1054 | }; |
@@ -1426,9 +1404,6 @@ static void le_setup(struct hci_request *req) | |||
1426 | /* Read LE Supported States */ | 1404 | /* Read LE Supported States */ |
1427 | hci_req_add(req, HCI_OP_LE_READ_SUPPORTED_STATES, 0, NULL); | 1405 | hci_req_add(req, HCI_OP_LE_READ_SUPPORTED_STATES, 0, NULL); |
1428 | 1406 | ||
1429 | /* Read LE Advertising Channel TX Power */ | ||
1430 | hci_req_add(req, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL); | ||
1431 | |||
1432 | /* Read LE White List Size */ | 1407 | /* Read LE White List Size */ |
1433 | hci_req_add(req, HCI_OP_LE_READ_WHITE_LIST_SIZE, 0, NULL); | 1408 | hci_req_add(req, HCI_OP_LE_READ_WHITE_LIST_SIZE, 0, NULL); |
1434 | 1409 | ||
@@ -1503,14 +1478,17 @@ static void hci_setup_event_mask(struct hci_request *req) | |||
1503 | /* Use a different default for LE-only devices */ | 1478 | /* Use a different default for LE-only devices */ |
1504 | memset(events, 0, sizeof(events)); | 1479 | memset(events, 0, sizeof(events)); |
1505 | events[0] |= 0x10; /* Disconnection Complete */ | 1480 | events[0] |= 0x10; /* Disconnection Complete */ |
1506 | events[0] |= 0x80; /* Encryption Change */ | ||
1507 | events[1] |= 0x08; /* Read Remote Version Information Complete */ | 1481 | events[1] |= 0x08; /* Read Remote Version Information Complete */ |
1508 | events[1] |= 0x20; /* Command Complete */ | 1482 | events[1] |= 0x20; /* Command Complete */ |
1509 | events[1] |= 0x40; /* Command Status */ | 1483 | events[1] |= 0x40; /* Command Status */ |
1510 | events[1] |= 0x80; /* Hardware Error */ | 1484 | events[1] |= 0x80; /* Hardware Error */ |
1511 | events[2] |= 0x04; /* Number of Completed Packets */ | 1485 | events[2] |= 0x04; /* Number of Completed Packets */ |
1512 | events[3] |= 0x02; /* Data Buffer Overflow */ | 1486 | events[3] |= 0x02; /* Data Buffer Overflow */ |
1513 | events[5] |= 0x80; /* Encryption Key Refresh Complete */ | 1487 | |
1488 | if (hdev->le_features[0] & HCI_LE_ENCRYPTION) { | ||
1489 | events[0] |= 0x80; /* Encryption Change */ | ||
1490 | events[5] |= 0x80; /* Encryption Key Refresh Complete */ | ||
1491 | } | ||
1514 | } | 1492 | } |
1515 | 1493 | ||
1516 | if (lmp_inq_rssi_capable(hdev)) | 1494 | if (lmp_inq_rssi_capable(hdev)) |
@@ -1549,13 +1527,6 @@ static void hci_setup_event_mask(struct hci_request *req) | |||
1549 | events[7] |= 0x20; /* LE Meta-Event */ | 1527 | events[7] |= 0x20; /* LE Meta-Event */ |
1550 | 1528 | ||
1551 | hci_req_add(req, HCI_OP_SET_EVENT_MASK, sizeof(events), events); | 1529 | hci_req_add(req, HCI_OP_SET_EVENT_MASK, sizeof(events), events); |
1552 | |||
1553 | if (lmp_le_capable(hdev)) { | ||
1554 | memset(events, 0, sizeof(events)); | ||
1555 | events[0] = 0x1f; | ||
1556 | hci_req_add(req, HCI_OP_LE_SET_EVENT_MASK, | ||
1557 | sizeof(events), events); | ||
1558 | } | ||
1559 | } | 1530 | } |
1560 | 1531 | ||
1561 | static void hci_init2_req(struct hci_request *req, unsigned long opt) | 1532 | static void hci_init2_req(struct hci_request *req, unsigned long opt) |
@@ -1570,8 +1541,6 @@ static void hci_init2_req(struct hci_request *req, unsigned long opt) | |||
1570 | if (lmp_le_capable(hdev)) | 1541 | if (lmp_le_capable(hdev)) |
1571 | le_setup(req); | 1542 | le_setup(req); |
1572 | 1543 | ||
1573 | hci_setup_event_mask(req); | ||
1574 | |||
1575 | /* AVM Berlin (31), aka "BlueFRITZ!", doesn't support the read | 1544 | /* AVM Berlin (31), aka "BlueFRITZ!", doesn't support the read |
1576 | * local supported commands HCI command. | 1545 | * local supported commands HCI command. |
1577 | */ | 1546 | */ |
@@ -1654,7 +1623,7 @@ static void hci_set_le_support(struct hci_request *req) | |||
1654 | 1623 | ||
1655 | if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { | 1624 | if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) { |
1656 | cp.le = 0x01; | 1625 | cp.le = 0x01; |
1657 | cp.simul = lmp_le_br_capable(hdev); | 1626 | cp.simul = 0x00; |
1658 | } | 1627 | } |
1659 | 1628 | ||
1660 | if (cp.le != lmp_host_le_capable(hdev)) | 1629 | if (cp.le != lmp_host_le_capable(hdev)) |
@@ -1688,7 +1657,7 @@ static void hci_set_event_mask_page_2(struct hci_request *req) | |||
1688 | } | 1657 | } |
1689 | 1658 | ||
1690 | /* Enable Authenticated Payload Timeout Expired event if supported */ | 1659 | /* Enable Authenticated Payload Timeout Expired event if supported */ |
1691 | if (lmp_ping_capable(hdev)) | 1660 | if (lmp_ping_capable(hdev) || hdev->le_features[0] & HCI_LE_PING) |
1692 | events[2] |= 0x80; | 1661 | events[2] |= 0x80; |
1693 | 1662 | ||
1694 | hci_req_add(req, HCI_OP_SET_EVENT_MASK_PAGE_2, sizeof(events), events); | 1663 | hci_req_add(req, HCI_OP_SET_EVENT_MASK_PAGE_2, sizeof(events), events); |
@@ -1699,6 +1668,8 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt) | |||
1699 | struct hci_dev *hdev = req->hdev; | 1668 | struct hci_dev *hdev = req->hdev; |
1700 | u8 p; | 1669 | u8 p; |
1701 | 1670 | ||
1671 | hci_setup_event_mask(req); | ||
1672 | |||
1702 | /* Some Broadcom based Bluetooth controllers do not support the | 1673 | /* Some Broadcom based Bluetooth controllers do not support the |
1703 | * Delete Stored Link Key command. They are clearly indicating its | 1674 | * Delete Stored Link Key command. They are clearly indicating its |
1704 | * absence in the bit mask of supported commands. | 1675 | * absence in the bit mask of supported commands. |
@@ -1725,8 +1696,33 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt) | |||
1725 | if (hdev->commands[5] & 0x10) | 1696 | if (hdev->commands[5] & 0x10) |
1726 | hci_setup_link_policy(req); | 1697 | hci_setup_link_policy(req); |
1727 | 1698 | ||
1728 | if (lmp_le_capable(hdev)) | 1699 | if (lmp_le_capable(hdev)) { |
1700 | u8 events[8]; | ||
1701 | |||
1702 | memset(events, 0, sizeof(events)); | ||
1703 | events[0] = 0x0f; | ||
1704 | |||
1705 | if (hdev->le_features[0] & HCI_LE_ENCRYPTION) | ||
1706 | events[0] |= 0x10; /* LE Long Term Key Request */ | ||
1707 | |||
1708 | /* If controller supports the Connection Parameters Request | ||
1709 | * Link Layer Procedure, enable the corresponding event. | ||
1710 | */ | ||
1711 | if (hdev->le_features[0] & HCI_LE_CONN_PARAM_REQ_PROC) | ||
1712 | events[0] |= 0x20; /* LE Remote Connection | ||
1713 | * Parameter Request | ||
1714 | */ | ||
1715 | |||
1716 | hci_req_add(req, HCI_OP_LE_SET_EVENT_MASK, sizeof(events), | ||
1717 | events); | ||
1718 | |||
1719 | if (hdev->commands[25] & 0x40) { | ||
1720 | /* Read LE Advertising Channel TX Power */ | ||
1721 | hci_req_add(req, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL); | ||
1722 | } | ||
1723 | |||
1729 | hci_set_le_support(req); | 1724 | hci_set_le_support(req); |
1725 | } | ||
1730 | 1726 | ||
1731 | /* Read features beyond page 1 if available */ | 1727 | /* Read features beyond page 1 if available */ |
1732 | for (p = 2; p < HCI_MAX_PAGES && p <= hdev->max_page; p++) { | 1728 | for (p = 2; p < HCI_MAX_PAGES && p <= hdev->max_page; p++) { |
@@ -1746,13 +1742,21 @@ static void hci_init4_req(struct hci_request *req, unsigned long opt) | |||
1746 | if (hdev->commands[22] & 0x04) | 1742 | if (hdev->commands[22] & 0x04) |
1747 | hci_set_event_mask_page_2(req); | 1743 | hci_set_event_mask_page_2(req); |
1748 | 1744 | ||
1745 | /* Read local codec list if the HCI command is supported */ | ||
1746 | if (hdev->commands[29] & 0x20) | ||
1747 | hci_req_add(req, HCI_OP_READ_LOCAL_CODECS, 0, NULL); | ||
1748 | |||
1749 | /* Get MWS transport configuration if the HCI command is supported */ | ||
1750 | if (hdev->commands[30] & 0x08) | ||
1751 | hci_req_add(req, HCI_OP_GET_MWS_TRANSPORT_CONFIG, 0, NULL); | ||
1752 | |||
1749 | /* Check for Synchronization Train support */ | 1753 | /* Check for Synchronization Train support */ |
1750 | if (lmp_sync_train_capable(hdev)) | 1754 | if (lmp_sync_train_capable(hdev)) |
1751 | hci_req_add(req, HCI_OP_READ_SYNC_TRAIN_PARAMS, 0, NULL); | 1755 | hci_req_add(req, HCI_OP_READ_SYNC_TRAIN_PARAMS, 0, NULL); |
1752 | 1756 | ||
1753 | /* Enable Secure Connections if supported and configured */ | 1757 | /* Enable Secure Connections if supported and configured */ |
1754 | if ((lmp_sc_capable(hdev) || | 1758 | if ((lmp_sc_capable(hdev) || |
1755 | test_bit(HCI_FORCE_SC, &hdev->dev_flags)) && | 1759 | test_bit(HCI_FORCE_SC, &hdev->dbg_flags)) && |
1756 | test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) { | 1760 | test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) { |
1757 | u8 support = 0x01; | 1761 | u8 support = 0x01; |
1758 | hci_req_add(req, HCI_OP_WRITE_SC_SUPPORT, | 1762 | hci_req_add(req, HCI_OP_WRITE_SC_SUPPORT, |
@@ -1809,6 +1813,8 @@ static int __hci_init(struct hci_dev *hdev) | |||
1809 | debugfs_create_u16("hci_revision", 0444, hdev->debugfs, &hdev->hci_rev); | 1813 | debugfs_create_u16("hci_revision", 0444, hdev->debugfs, &hdev->hci_rev); |
1810 | debugfs_create_file("blacklist", 0444, hdev->debugfs, hdev, | 1814 | debugfs_create_file("blacklist", 0444, hdev->debugfs, hdev, |
1811 | &blacklist_fops); | 1815 | &blacklist_fops); |
1816 | debugfs_create_file("whitelist", 0444, hdev->debugfs, hdev, | ||
1817 | &whitelist_fops); | ||
1812 | debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops); | 1818 | debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops); |
1813 | 1819 | ||
1814 | debugfs_create_file("conn_info_min_age", 0644, hdev->debugfs, hdev, | 1820 | debugfs_create_file("conn_info_min_age", 0644, hdev->debugfs, hdev, |
@@ -1830,8 +1836,6 @@ static int __hci_init(struct hci_dev *hdev) | |||
1830 | if (lmp_ssp_capable(hdev)) { | 1836 | if (lmp_ssp_capable(hdev)) { |
1831 | debugfs_create_file("auto_accept_delay", 0644, hdev->debugfs, | 1837 | debugfs_create_file("auto_accept_delay", 0644, hdev->debugfs, |
1832 | hdev, &auto_accept_delay_fops); | 1838 | hdev, &auto_accept_delay_fops); |
1833 | debugfs_create_file("ssp_debug_mode", 0644, hdev->debugfs, | ||
1834 | hdev, &ssp_debug_mode_fops); | ||
1835 | debugfs_create_file("force_sc_support", 0644, hdev->debugfs, | 1839 | debugfs_create_file("force_sc_support", 0644, hdev->debugfs, |
1836 | hdev, &force_sc_support_fops); | 1840 | hdev, &force_sc_support_fops); |
1837 | debugfs_create_file("sc_only_mode", 0444, hdev->debugfs, | 1841 | debugfs_create_file("sc_only_mode", 0444, hdev->debugfs, |
@@ -1879,12 +1883,18 @@ static int __hci_init(struct hci_dev *hdev) | |||
1879 | hdev, &conn_min_interval_fops); | 1883 | hdev, &conn_min_interval_fops); |
1880 | debugfs_create_file("conn_max_interval", 0644, hdev->debugfs, | 1884 | debugfs_create_file("conn_max_interval", 0644, hdev->debugfs, |
1881 | hdev, &conn_max_interval_fops); | 1885 | hdev, &conn_max_interval_fops); |
1886 | debugfs_create_file("conn_latency", 0644, hdev->debugfs, | ||
1887 | hdev, &conn_latency_fops); | ||
1888 | debugfs_create_file("supervision_timeout", 0644, hdev->debugfs, | ||
1889 | hdev, &supervision_timeout_fops); | ||
1882 | debugfs_create_file("adv_channel_map", 0644, hdev->debugfs, | 1890 | debugfs_create_file("adv_channel_map", 0644, hdev->debugfs, |
1883 | hdev, &adv_channel_map_fops); | 1891 | hdev, &adv_channel_map_fops); |
1884 | debugfs_create_file("6lowpan", 0644, hdev->debugfs, hdev, | 1892 | debugfs_create_file("adv_min_interval", 0644, hdev->debugfs, |
1885 | &lowpan_debugfs_fops); | 1893 | hdev, &adv_min_interval_fops); |
1886 | debugfs_create_file("le_auto_conn", 0644, hdev->debugfs, hdev, | 1894 | debugfs_create_file("adv_max_interval", 0644, hdev->debugfs, |
1887 | &le_auto_conn_fops); | 1895 | hdev, &adv_max_interval_fops); |
1896 | debugfs_create_file("device_list", 0444, hdev->debugfs, hdev, | ||
1897 | &device_list_fops); | ||
1888 | debugfs_create_u16("discov_interleaved_timeout", 0644, | 1898 | debugfs_create_u16("discov_interleaved_timeout", 0644, |
1889 | hdev->debugfs, | 1899 | hdev->debugfs, |
1890 | &hdev->discov_interleaved_timeout); | 1900 | &hdev->discov_interleaved_timeout); |
@@ -1893,6 +1903,38 @@ static int __hci_init(struct hci_dev *hdev) | |||
1893 | return 0; | 1903 | return 0; |
1894 | } | 1904 | } |
1895 | 1905 | ||
1906 | static void hci_init0_req(struct hci_request *req, unsigned long opt) | ||
1907 | { | ||
1908 | struct hci_dev *hdev = req->hdev; | ||
1909 | |||
1910 | BT_DBG("%s %ld", hdev->name, opt); | ||
1911 | |||
1912 | /* Reset */ | ||
1913 | if (!test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks)) | ||
1914 | hci_reset_req(req, 0); | ||
1915 | |||
1916 | /* Read Local Version */ | ||
1917 | hci_req_add(req, HCI_OP_READ_LOCAL_VERSION, 0, NULL); | ||
1918 | |||
1919 | /* Read BD Address */ | ||
1920 | if (hdev->set_bdaddr) | ||
1921 | hci_req_add(req, HCI_OP_READ_BD_ADDR, 0, NULL); | ||
1922 | } | ||
1923 | |||
1924 | static int __hci_unconf_init(struct hci_dev *hdev) | ||
1925 | { | ||
1926 | int err; | ||
1927 | |||
1928 | if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) | ||
1929 | return 0; | ||
1930 | |||
1931 | err = __hci_req_sync(hdev, hci_init0_req, 0, HCI_INIT_TIMEOUT); | ||
1932 | if (err < 0) | ||
1933 | return err; | ||
1934 | |||
1935 | return 0; | ||
1936 | } | ||
1937 | |||
1896 | static void hci_scan_req(struct hci_request *req, unsigned long opt) | 1938 | static void hci_scan_req(struct hci_request *req, unsigned long opt) |
1897 | { | 1939 | { |
1898 | __u8 scan = opt; | 1940 | __u8 scan = opt; |
@@ -1973,16 +2015,20 @@ bool hci_discovery_active(struct hci_dev *hdev) | |||
1973 | 2015 | ||
1974 | void hci_discovery_set_state(struct hci_dev *hdev, int state) | 2016 | void hci_discovery_set_state(struct hci_dev *hdev, int state) |
1975 | { | 2017 | { |
2018 | int old_state = hdev->discovery.state; | ||
2019 | |||
1976 | BT_DBG("%s state %u -> %u", hdev->name, hdev->discovery.state, state); | 2020 | BT_DBG("%s state %u -> %u", hdev->name, hdev->discovery.state, state); |
1977 | 2021 | ||
1978 | if (hdev->discovery.state == state) | 2022 | if (old_state == state) |
1979 | return; | 2023 | return; |
1980 | 2024 | ||
2025 | hdev->discovery.state = state; | ||
2026 | |||
1981 | switch (state) { | 2027 | switch (state) { |
1982 | case DISCOVERY_STOPPED: | 2028 | case DISCOVERY_STOPPED: |
1983 | hci_update_background_scan(hdev); | 2029 | hci_update_background_scan(hdev); |
1984 | 2030 | ||
1985 | if (hdev->discovery.state != DISCOVERY_STARTING) | 2031 | if (old_state != DISCOVERY_STARTING) |
1986 | mgmt_discovering(hdev, 0); | 2032 | mgmt_discovering(hdev, 0); |
1987 | break; | 2033 | break; |
1988 | case DISCOVERY_STARTING: | 2034 | case DISCOVERY_STARTING: |
@@ -1995,8 +2041,6 @@ void hci_discovery_set_state(struct hci_dev *hdev, int state) | |||
1995 | case DISCOVERY_STOPPING: | 2041 | case DISCOVERY_STOPPING: |
1996 | break; | 2042 | break; |
1997 | } | 2043 | } |
1998 | |||
1999 | hdev->discovery.state = state; | ||
2000 | } | 2044 | } |
2001 | 2045 | ||
2002 | void hci_inquiry_cache_flush(struct hci_dev *hdev) | 2046 | void hci_inquiry_cache_flush(struct hci_dev *hdev) |
@@ -2083,22 +2127,24 @@ void hci_inquiry_cache_update_resolve(struct hci_dev *hdev, | |||
2083 | list_add(&ie->list, pos); | 2127 | list_add(&ie->list, pos); |
2084 | } | 2128 | } |
2085 | 2129 | ||
2086 | bool hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data, | 2130 | u32 hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data, |
2087 | bool name_known, bool *ssp) | 2131 | bool name_known) |
2088 | { | 2132 | { |
2089 | struct discovery_state *cache = &hdev->discovery; | 2133 | struct discovery_state *cache = &hdev->discovery; |
2090 | struct inquiry_entry *ie; | 2134 | struct inquiry_entry *ie; |
2135 | u32 flags = 0; | ||
2091 | 2136 | ||
2092 | BT_DBG("cache %p, %pMR", cache, &data->bdaddr); | 2137 | BT_DBG("cache %p, %pMR", cache, &data->bdaddr); |
2093 | 2138 | ||
2094 | hci_remove_remote_oob_data(hdev, &data->bdaddr); | 2139 | hci_remove_remote_oob_data(hdev, &data->bdaddr); |
2095 | 2140 | ||
2096 | *ssp = data->ssp_mode; | 2141 | if (!data->ssp_mode) |
2142 | flags |= MGMT_DEV_FOUND_LEGACY_PAIRING; | ||
2097 | 2143 | ||
2098 | ie = hci_inquiry_cache_lookup(hdev, &data->bdaddr); | 2144 | ie = hci_inquiry_cache_lookup(hdev, &data->bdaddr); |
2099 | if (ie) { | 2145 | if (ie) { |
2100 | if (ie->data.ssp_mode) | 2146 | if (!ie->data.ssp_mode) |
2101 | *ssp = true; | 2147 | flags |= MGMT_DEV_FOUND_LEGACY_PAIRING; |
2102 | 2148 | ||
2103 | if (ie->name_state == NAME_NEEDED && | 2149 | if (ie->name_state == NAME_NEEDED && |
2104 | data->rssi != ie->data.rssi) { | 2150 | data->rssi != ie->data.rssi) { |
@@ -2110,9 +2156,11 @@ bool hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data, | |||
2110 | } | 2156 | } |
2111 | 2157 | ||
2112 | /* Entry not in the cache. Add new one. */ | 2158 | /* Entry not in the cache. Add new one. */ |
2113 | ie = kzalloc(sizeof(struct inquiry_entry), GFP_ATOMIC); | 2159 | ie = kzalloc(sizeof(*ie), GFP_KERNEL); |
2114 | if (!ie) | 2160 | if (!ie) { |
2115 | return false; | 2161 | flags |= MGMT_DEV_FOUND_CONFIRM_NAME; |
2162 | goto done; | ||
2163 | } | ||
2116 | 2164 | ||
2117 | list_add(&ie->all, &cache->all); | 2165 | list_add(&ie->all, &cache->all); |
2118 | 2166 | ||
@@ -2135,9 +2183,10 @@ update: | |||
2135 | cache->timestamp = jiffies; | 2183 | cache->timestamp = jiffies; |
2136 | 2184 | ||
2137 | if (ie->name_state == NAME_NOT_KNOWN) | 2185 | if (ie->name_state == NAME_NOT_KNOWN) |
2138 | return false; | 2186 | flags |= MGMT_DEV_FOUND_CONFIRM_NAME; |
2139 | 2187 | ||
2140 | return true; | 2188 | done: |
2189 | return flags; | ||
2141 | } | 2190 | } |
2142 | 2191 | ||
2143 | static int inquiry_cache_dump(struct hci_dev *hdev, int num, __u8 *buf) | 2192 | static int inquiry_cache_dump(struct hci_dev *hdev, int num, __u8 *buf) |
@@ -2186,12 +2235,6 @@ static void hci_inq_req(struct hci_request *req, unsigned long opt) | |||
2186 | hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp); | 2235 | hci_req_add(req, HCI_OP_INQUIRY, sizeof(cp), &cp); |
2187 | } | 2236 | } |
2188 | 2237 | ||
2189 | static int wait_inquiry(void *word) | ||
2190 | { | ||
2191 | schedule(); | ||
2192 | return signal_pending(current); | ||
2193 | } | ||
2194 | |||
2195 | int hci_inquiry(void __user *arg) | 2238 | int hci_inquiry(void __user *arg) |
2196 | { | 2239 | { |
2197 | __u8 __user *ptr = arg; | 2240 | __u8 __user *ptr = arg; |
@@ -2213,6 +2256,11 @@ int hci_inquiry(void __user *arg) | |||
2213 | goto done; | 2256 | goto done; |
2214 | } | 2257 | } |
2215 | 2258 | ||
2259 | if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) { | ||
2260 | err = -EOPNOTSUPP; | ||
2261 | goto done; | ||
2262 | } | ||
2263 | |||
2216 | if (hdev->dev_type != HCI_BREDR) { | 2264 | if (hdev->dev_type != HCI_BREDR) { |
2217 | err = -EOPNOTSUPP; | 2265 | err = -EOPNOTSUPP; |
2218 | goto done; | 2266 | goto done; |
@@ -2242,7 +2290,7 @@ int hci_inquiry(void __user *arg) | |||
2242 | /* Wait until Inquiry procedure finishes (HCI_INQUIRY flag is | 2290 | /* Wait until Inquiry procedure finishes (HCI_INQUIRY flag is |
2243 | * cleared). If it is interrupted by a signal, return -EINTR. | 2291 | * cleared). If it is interrupted by a signal, return -EINTR. |
2244 | */ | 2292 | */ |
2245 | if (wait_on_bit(&hdev->flags, HCI_INQUIRY, wait_inquiry, | 2293 | if (wait_on_bit(&hdev->flags, HCI_INQUIRY, |
2246 | TASK_INTERRUPTIBLE)) | 2294 | TASK_INTERRUPTIBLE)) |
2247 | return -EINTR; | 2295 | return -EINTR; |
2248 | } | 2296 | } |
@@ -2295,7 +2343,8 @@ static int hci_dev_do_open(struct hci_dev *hdev) | |||
2295 | goto done; | 2343 | goto done; |
2296 | } | 2344 | } |
2297 | 2345 | ||
2298 | if (!test_bit(HCI_SETUP, &hdev->dev_flags)) { | 2346 | if (!test_bit(HCI_SETUP, &hdev->dev_flags) && |
2347 | !test_bit(HCI_CONFIG, &hdev->dev_flags)) { | ||
2299 | /* Check for rfkill but allow the HCI setup stage to | 2348 | /* Check for rfkill but allow the HCI setup stage to |
2300 | * proceed (which in itself doesn't cause any RF activity). | 2349 | * proceed (which in itself doesn't cause any RF activity). |
2301 | */ | 2350 | */ |
@@ -2338,14 +2387,47 @@ static int hci_dev_do_open(struct hci_dev *hdev) | |||
2338 | atomic_set(&hdev->cmd_cnt, 1); | 2387 | atomic_set(&hdev->cmd_cnt, 1); |
2339 | set_bit(HCI_INIT, &hdev->flags); | 2388 | set_bit(HCI_INIT, &hdev->flags); |
2340 | 2389 | ||
2341 | if (hdev->setup && test_bit(HCI_SETUP, &hdev->dev_flags)) | 2390 | if (test_bit(HCI_SETUP, &hdev->dev_flags)) { |
2342 | ret = hdev->setup(hdev); | 2391 | if (hdev->setup) |
2392 | ret = hdev->setup(hdev); | ||
2343 | 2393 | ||
2344 | if (!ret) { | 2394 | /* The transport driver can set these quirks before |
2345 | if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) | 2395 | * creating the HCI device or in its setup callback. |
2346 | set_bit(HCI_RAW, &hdev->flags); | 2396 | * |
2397 | * In case any of them is set, the controller has to | ||
2398 | * start up as unconfigured. | ||
2399 | */ | ||
2400 | if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) || | ||
2401 | test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks)) | ||
2402 | set_bit(HCI_UNCONFIGURED, &hdev->dev_flags); | ||
2347 | 2403 | ||
2348 | if (!test_bit(HCI_RAW, &hdev->flags) && | 2404 | /* For an unconfigured controller it is required to |
2405 | * read at least the version information provided by | ||
2406 | * the Read Local Version Information command. | ||
2407 | * | ||
2408 | * If the set_bdaddr driver callback is provided, then | ||
2409 | * also the original Bluetooth public device address | ||
2410 | * will be read using the Read BD Address command. | ||
2411 | */ | ||
2412 | if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) | ||
2413 | ret = __hci_unconf_init(hdev); | ||
2414 | } | ||
2415 | |||
2416 | if (test_bit(HCI_CONFIG, &hdev->dev_flags)) { | ||
2417 | /* If public address change is configured, ensure that | ||
2418 | * the address gets programmed. If the driver does not | ||
2419 | * support changing the public address, fail the power | ||
2420 | * on procedure. | ||
2421 | */ | ||
2422 | if (bacmp(&hdev->public_addr, BDADDR_ANY) && | ||
2423 | hdev->set_bdaddr) | ||
2424 | ret = hdev->set_bdaddr(hdev, &hdev->public_addr); | ||
2425 | else | ||
2426 | ret = -EADDRNOTAVAIL; | ||
2427 | } | ||
2428 | |||
2429 | if (!ret) { | ||
2430 | if (!test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) && | ||
2349 | !test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) | 2431 | !test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) |
2350 | ret = __hci_init(hdev); | 2432 | ret = __hci_init(hdev); |
2351 | } | 2433 | } |
@@ -2358,6 +2440,8 @@ static int hci_dev_do_open(struct hci_dev *hdev) | |||
2358 | set_bit(HCI_UP, &hdev->flags); | 2440 | set_bit(HCI_UP, &hdev->flags); |
2359 | hci_notify(hdev, HCI_DEV_UP); | 2441 | hci_notify(hdev, HCI_DEV_UP); |
2360 | if (!test_bit(HCI_SETUP, &hdev->dev_flags) && | 2442 | if (!test_bit(HCI_SETUP, &hdev->dev_flags) && |
2443 | !test_bit(HCI_CONFIG, &hdev->dev_flags) && | ||
2444 | !test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) && | ||
2361 | !test_bit(HCI_USER_CHANNEL, &hdev->dev_flags) && | 2445 | !test_bit(HCI_USER_CHANNEL, &hdev->dev_flags) && |
2362 | hdev->dev_type == HCI_BREDR) { | 2446 | hdev->dev_type == HCI_BREDR) { |
2363 | hci_dev_lock(hdev); | 2447 | hci_dev_lock(hdev); |
@@ -2382,7 +2466,7 @@ static int hci_dev_do_open(struct hci_dev *hdev) | |||
2382 | } | 2466 | } |
2383 | 2467 | ||
2384 | hdev->close(hdev); | 2468 | hdev->close(hdev); |
2385 | hdev->flags = 0; | 2469 | hdev->flags &= BIT(HCI_RAW); |
2386 | } | 2470 | } |
2387 | 2471 | ||
2388 | done: | 2472 | done: |
@@ -2401,6 +2485,21 @@ int hci_dev_open(__u16 dev) | |||
2401 | if (!hdev) | 2485 | if (!hdev) |
2402 | return -ENODEV; | 2486 | return -ENODEV; |
2403 | 2487 | ||
2488 | /* Devices that are marked as unconfigured can only be powered | ||
2489 | * up as user channel. Trying to bring them up as normal devices | ||
2490 | * will result into a failure. Only user channel operation is | ||
2491 | * possible. | ||
2492 | * | ||
2493 | * When this function is called for a user channel, the flag | ||
2494 | * HCI_USER_CHANNEL will be set first before attempting to | ||
2495 | * open the device. | ||
2496 | */ | ||
2497 | if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) && | ||
2498 | !test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) { | ||
2499 | err = -EOPNOTSUPP; | ||
2500 | goto done; | ||
2501 | } | ||
2502 | |||
2404 | /* We need to ensure that no other power on/off work is pending | 2503 | /* We need to ensure that no other power on/off work is pending |
2405 | * before proceeding to call hci_dev_do_open. This is | 2504 | * before proceeding to call hci_dev_do_open. This is |
2406 | * particularly important if the setup procedure has not yet | 2505 | * particularly important if the setup procedure has not yet |
@@ -2415,13 +2514,39 @@ int hci_dev_open(__u16 dev) | |||
2415 | */ | 2514 | */ |
2416 | flush_workqueue(hdev->req_workqueue); | 2515 | flush_workqueue(hdev->req_workqueue); |
2417 | 2516 | ||
2517 | /* For controllers not using the management interface and that | ||
2518 | * are brought up using legacy ioctl, set the HCI_BONDABLE bit | ||
2519 | * so that pairing works for them. Once the management interface | ||
2520 | * is in use this bit will be cleared again and userspace has | ||
2521 | * to explicitly enable it. | ||
2522 | */ | ||
2523 | if (!test_bit(HCI_USER_CHANNEL, &hdev->dev_flags) && | ||
2524 | !test_bit(HCI_MGMT, &hdev->dev_flags)) | ||
2525 | set_bit(HCI_BONDABLE, &hdev->dev_flags); | ||
2526 | |||
2418 | err = hci_dev_do_open(hdev); | 2527 | err = hci_dev_do_open(hdev); |
2419 | 2528 | ||
2529 | done: | ||
2420 | hci_dev_put(hdev); | 2530 | hci_dev_put(hdev); |
2421 | |||
2422 | return err; | 2531 | return err; |
2423 | } | 2532 | } |
2424 | 2533 | ||
2534 | /* This function requires the caller holds hdev->lock */ | ||
2535 | static void hci_pend_le_actions_clear(struct hci_dev *hdev) | ||
2536 | { | ||
2537 | struct hci_conn_params *p; | ||
2538 | |||
2539 | list_for_each_entry(p, &hdev->le_conn_params, list) { | ||
2540 | if (p->conn) { | ||
2541 | hci_conn_drop(p->conn); | ||
2542 | p->conn = NULL; | ||
2543 | } | ||
2544 | list_del_init(&p->action); | ||
2545 | } | ||
2546 | |||
2547 | BT_DBG("All LE pending actions cleared"); | ||
2548 | } | ||
2549 | |||
2425 | static int hci_dev_do_close(struct hci_dev *hdev) | 2550 | static int hci_dev_do_close(struct hci_dev *hdev) |
2426 | { | 2551 | { |
2427 | BT_DBG("%s %p", hdev->name, hdev); | 2552 | BT_DBG("%s %p", hdev->name, hdev); |
@@ -2432,7 +2557,7 @@ static int hci_dev_do_close(struct hci_dev *hdev) | |||
2432 | hci_req_lock(hdev); | 2557 | hci_req_lock(hdev); |
2433 | 2558 | ||
2434 | if (!test_and_clear_bit(HCI_UP, &hdev->flags)) { | 2559 | if (!test_and_clear_bit(HCI_UP, &hdev->flags)) { |
2435 | del_timer_sync(&hdev->cmd_timer); | 2560 | cancel_delayed_work_sync(&hdev->cmd_timer); |
2436 | hci_req_unlock(hdev); | 2561 | hci_req_unlock(hdev); |
2437 | return 0; | 2562 | return 0; |
2438 | } | 2563 | } |
@@ -2458,8 +2583,8 @@ static int hci_dev_do_close(struct hci_dev *hdev) | |||
2458 | 2583 | ||
2459 | hci_dev_lock(hdev); | 2584 | hci_dev_lock(hdev); |
2460 | hci_inquiry_cache_flush(hdev); | 2585 | hci_inquiry_cache_flush(hdev); |
2586 | hci_pend_le_actions_clear(hdev); | ||
2461 | hci_conn_hash_flush(hdev); | 2587 | hci_conn_hash_flush(hdev); |
2462 | hci_pend_le_conns_clear(hdev); | ||
2463 | hci_dev_unlock(hdev); | 2588 | hci_dev_unlock(hdev); |
2464 | 2589 | ||
2465 | hci_notify(hdev, HCI_DEV_DOWN); | 2590 | hci_notify(hdev, HCI_DEV_DOWN); |
@@ -2470,8 +2595,8 @@ static int hci_dev_do_close(struct hci_dev *hdev) | |||
2470 | /* Reset device */ | 2595 | /* Reset device */ |
2471 | skb_queue_purge(&hdev->cmd_q); | 2596 | skb_queue_purge(&hdev->cmd_q); |
2472 | atomic_set(&hdev->cmd_cnt, 1); | 2597 | atomic_set(&hdev->cmd_cnt, 1); |
2473 | if (!test_bit(HCI_RAW, &hdev->flags) && | 2598 | if (!test_bit(HCI_AUTO_OFF, &hdev->dev_flags) && |
2474 | !test_bit(HCI_AUTO_OFF, &hdev->dev_flags) && | 2599 | !test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) && |
2475 | test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks)) { | 2600 | test_bit(HCI_QUIRK_RESET_ON_CLOSE, &hdev->quirks)) { |
2476 | set_bit(HCI_INIT, &hdev->flags); | 2601 | set_bit(HCI_INIT, &hdev->flags); |
2477 | __hci_req_sync(hdev, hci_reset_req, 0, HCI_CMD_TIMEOUT); | 2602 | __hci_req_sync(hdev, hci_reset_req, 0, HCI_CMD_TIMEOUT); |
@@ -2488,7 +2613,7 @@ static int hci_dev_do_close(struct hci_dev *hdev) | |||
2488 | 2613 | ||
2489 | /* Drop last sent command */ | 2614 | /* Drop last sent command */ |
2490 | if (hdev->sent_cmd) { | 2615 | if (hdev->sent_cmd) { |
2491 | del_timer_sync(&hdev->cmd_timer); | 2616 | cancel_delayed_work_sync(&hdev->cmd_timer); |
2492 | kfree_skb(hdev->sent_cmd); | 2617 | kfree_skb(hdev->sent_cmd); |
2493 | hdev->sent_cmd = NULL; | 2618 | hdev->sent_cmd = NULL; |
2494 | } | 2619 | } |
@@ -2501,7 +2626,7 @@ static int hci_dev_do_close(struct hci_dev *hdev) | |||
2501 | hdev->close(hdev); | 2626 | hdev->close(hdev); |
2502 | 2627 | ||
2503 | /* Clear flags */ | 2628 | /* Clear flags */ |
2504 | hdev->flags = 0; | 2629 | hdev->flags &= BIT(HCI_RAW); |
2505 | hdev->dev_flags &= ~HCI_PERSISTENT_MASK; | 2630 | hdev->dev_flags &= ~HCI_PERSISTENT_MASK; |
2506 | 2631 | ||
2507 | if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) { | 2632 | if (!test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) { |
@@ -2570,6 +2695,11 @@ int hci_dev_reset(__u16 dev) | |||
2570 | goto done; | 2695 | goto done; |
2571 | } | 2696 | } |
2572 | 2697 | ||
2698 | if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) { | ||
2699 | ret = -EOPNOTSUPP; | ||
2700 | goto done; | ||
2701 | } | ||
2702 | |||
2573 | /* Drop queues */ | 2703 | /* Drop queues */ |
2574 | skb_queue_purge(&hdev->rx_q); | 2704 | skb_queue_purge(&hdev->rx_q); |
2575 | skb_queue_purge(&hdev->cmd_q); | 2705 | skb_queue_purge(&hdev->cmd_q); |
@@ -2585,8 +2715,7 @@ int hci_dev_reset(__u16 dev) | |||
2585 | atomic_set(&hdev->cmd_cnt, 1); | 2715 | atomic_set(&hdev->cmd_cnt, 1); |
2586 | hdev->acl_cnt = 0; hdev->sco_cnt = 0; hdev->le_cnt = 0; | 2716 | hdev->acl_cnt = 0; hdev->sco_cnt = 0; hdev->le_cnt = 0; |
2587 | 2717 | ||
2588 | if (!test_bit(HCI_RAW, &hdev->flags)) | 2718 | ret = __hci_req_sync(hdev, hci_reset_req, 0, HCI_INIT_TIMEOUT); |
2589 | ret = __hci_req_sync(hdev, hci_reset_req, 0, HCI_INIT_TIMEOUT); | ||
2590 | 2719 | ||
2591 | done: | 2720 | done: |
2592 | hci_req_unlock(hdev); | 2721 | hci_req_unlock(hdev); |
@@ -2608,6 +2737,11 @@ int hci_dev_reset_stat(__u16 dev) | |||
2608 | goto done; | 2737 | goto done; |
2609 | } | 2738 | } |
2610 | 2739 | ||
2740 | if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) { | ||
2741 | ret = -EOPNOTSUPP; | ||
2742 | goto done; | ||
2743 | } | ||
2744 | |||
2611 | memset(&hdev->stat, 0, sizeof(struct hci_dev_stats)); | 2745 | memset(&hdev->stat, 0, sizeof(struct hci_dev_stats)); |
2612 | 2746 | ||
2613 | done: | 2747 | done: |
@@ -2615,6 +2749,42 @@ done: | |||
2615 | return ret; | 2749 | return ret; |
2616 | } | 2750 | } |
2617 | 2751 | ||
2752 | static void hci_update_scan_state(struct hci_dev *hdev, u8 scan) | ||
2753 | { | ||
2754 | bool conn_changed, discov_changed; | ||
2755 | |||
2756 | BT_DBG("%s scan 0x%02x", hdev->name, scan); | ||
2757 | |||
2758 | if ((scan & SCAN_PAGE)) | ||
2759 | conn_changed = !test_and_set_bit(HCI_CONNECTABLE, | ||
2760 | &hdev->dev_flags); | ||
2761 | else | ||
2762 | conn_changed = test_and_clear_bit(HCI_CONNECTABLE, | ||
2763 | &hdev->dev_flags); | ||
2764 | |||
2765 | if ((scan & SCAN_INQUIRY)) { | ||
2766 | discov_changed = !test_and_set_bit(HCI_DISCOVERABLE, | ||
2767 | &hdev->dev_flags); | ||
2768 | } else { | ||
2769 | clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags); | ||
2770 | discov_changed = test_and_clear_bit(HCI_DISCOVERABLE, | ||
2771 | &hdev->dev_flags); | ||
2772 | } | ||
2773 | |||
2774 | if (!test_bit(HCI_MGMT, &hdev->dev_flags)) | ||
2775 | return; | ||
2776 | |||
2777 | if (conn_changed || discov_changed) { | ||
2778 | /* In case this was disabled through mgmt */ | ||
2779 | set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags); | ||
2780 | |||
2781 | if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) | ||
2782 | mgmt_update_adv_data(hdev); | ||
2783 | |||
2784 | mgmt_new_settings(hdev); | ||
2785 | } | ||
2786 | } | ||
2787 | |||
2618 | int hci_dev_cmd(unsigned int cmd, void __user *arg) | 2788 | int hci_dev_cmd(unsigned int cmd, void __user *arg) |
2619 | { | 2789 | { |
2620 | struct hci_dev *hdev; | 2790 | struct hci_dev *hdev; |
@@ -2633,6 +2803,11 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg) | |||
2633 | goto done; | 2803 | goto done; |
2634 | } | 2804 | } |
2635 | 2805 | ||
2806 | if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) { | ||
2807 | err = -EOPNOTSUPP; | ||
2808 | goto done; | ||
2809 | } | ||
2810 | |||
2636 | if (hdev->dev_type != HCI_BREDR) { | 2811 | if (hdev->dev_type != HCI_BREDR) { |
2637 | err = -EOPNOTSUPP; | 2812 | err = -EOPNOTSUPP; |
2638 | goto done; | 2813 | goto done; |
@@ -2670,6 +2845,12 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg) | |||
2670 | case HCISETSCAN: | 2845 | case HCISETSCAN: |
2671 | err = hci_req_sync(hdev, hci_scan_req, dr.dev_opt, | 2846 | err = hci_req_sync(hdev, hci_scan_req, dr.dev_opt, |
2672 | HCI_INIT_TIMEOUT); | 2847 | HCI_INIT_TIMEOUT); |
2848 | |||
2849 | /* Ensure that the connectable and discoverable states | ||
2850 | * get correctly modified as this was a non-mgmt change. | ||
2851 | */ | ||
2852 | if (!err) | ||
2853 | hci_update_scan_state(hdev, dr.dev_opt); | ||
2673 | break; | 2854 | break; |
2674 | 2855 | ||
2675 | case HCISETLINKPOL: | 2856 | case HCISETLINKPOL: |
@@ -2730,14 +2911,17 @@ int hci_get_dev_list(void __user *arg) | |||
2730 | 2911 | ||
2731 | read_lock(&hci_dev_list_lock); | 2912 | read_lock(&hci_dev_list_lock); |
2732 | list_for_each_entry(hdev, &hci_dev_list, list) { | 2913 | list_for_each_entry(hdev, &hci_dev_list, list) { |
2733 | if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) | 2914 | unsigned long flags = hdev->flags; |
2734 | cancel_delayed_work(&hdev->power_off); | ||
2735 | 2915 | ||
2736 | if (!test_bit(HCI_MGMT, &hdev->dev_flags)) | 2916 | /* When the auto-off is configured it means the transport |
2737 | set_bit(HCI_PAIRABLE, &hdev->dev_flags); | 2917 | * is running, but in that case still indicate that the |
2918 | * device is actually down. | ||
2919 | */ | ||
2920 | if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags)) | ||
2921 | flags &= ~BIT(HCI_UP); | ||
2738 | 2922 | ||
2739 | (dr + n)->dev_id = hdev->id; | 2923 | (dr + n)->dev_id = hdev->id; |
2740 | (dr + n)->dev_opt = hdev->flags; | 2924 | (dr + n)->dev_opt = flags; |
2741 | 2925 | ||
2742 | if (++n >= dev_num) | 2926 | if (++n >= dev_num) |
2743 | break; | 2927 | break; |
@@ -2757,6 +2941,7 @@ int hci_get_dev_info(void __user *arg) | |||
2757 | { | 2941 | { |
2758 | struct hci_dev *hdev; | 2942 | struct hci_dev *hdev; |
2759 | struct hci_dev_info di; | 2943 | struct hci_dev_info di; |
2944 | unsigned long flags; | ||
2760 | int err = 0; | 2945 | int err = 0; |
2761 | 2946 | ||
2762 | if (copy_from_user(&di, arg, sizeof(di))) | 2947 | if (copy_from_user(&di, arg, sizeof(di))) |
@@ -2766,16 +2951,19 @@ int hci_get_dev_info(void __user *arg) | |||
2766 | if (!hdev) | 2951 | if (!hdev) |
2767 | return -ENODEV; | 2952 | return -ENODEV; |
2768 | 2953 | ||
2769 | if (test_and_clear_bit(HCI_AUTO_OFF, &hdev->dev_flags)) | 2954 | /* When the auto-off is configured it means the transport |
2770 | cancel_delayed_work_sync(&hdev->power_off); | 2955 | * is running, but in that case still indicate that the |
2771 | 2956 | * device is actually down. | |
2772 | if (!test_bit(HCI_MGMT, &hdev->dev_flags)) | 2957 | */ |
2773 | set_bit(HCI_PAIRABLE, &hdev->dev_flags); | 2958 | if (test_bit(HCI_AUTO_OFF, &hdev->dev_flags)) |
2959 | flags = hdev->flags & ~BIT(HCI_UP); | ||
2960 | else | ||
2961 | flags = hdev->flags; | ||
2774 | 2962 | ||
2775 | strcpy(di.name, hdev->name); | 2963 | strcpy(di.name, hdev->name); |
2776 | di.bdaddr = hdev->bdaddr; | 2964 | di.bdaddr = hdev->bdaddr; |
2777 | di.type = (hdev->bus & 0x0f) | ((hdev->dev_type & 0x03) << 4); | 2965 | di.type = (hdev->bus & 0x0f) | ((hdev->dev_type & 0x03) << 4); |
2778 | di.flags = hdev->flags; | 2966 | di.flags = flags; |
2779 | di.pkt_type = hdev->pkt_type; | 2967 | di.pkt_type = hdev->pkt_type; |
2780 | if (lmp_bredr_capable(hdev)) { | 2968 | if (lmp_bredr_capable(hdev)) { |
2781 | di.acl_mtu = hdev->acl_mtu; | 2969 | di.acl_mtu = hdev->acl_mtu; |
@@ -2815,7 +3003,8 @@ static int hci_rfkill_set_block(void *data, bool blocked) | |||
2815 | 3003 | ||
2816 | if (blocked) { | 3004 | if (blocked) { |
2817 | set_bit(HCI_RFKILLED, &hdev->dev_flags); | 3005 | set_bit(HCI_RFKILLED, &hdev->dev_flags); |
2818 | if (!test_bit(HCI_SETUP, &hdev->dev_flags)) | 3006 | if (!test_bit(HCI_SETUP, &hdev->dev_flags) && |
3007 | !test_bit(HCI_CONFIG, &hdev->dev_flags)) | ||
2819 | hci_dev_do_close(hdev); | 3008 | hci_dev_do_close(hdev); |
2820 | } else { | 3009 | } else { |
2821 | clear_bit(HCI_RFKILLED, &hdev->dev_flags); | 3010 | clear_bit(HCI_RFKILLED, &hdev->dev_flags); |
@@ -2846,6 +3035,7 @@ static void hci_power_on(struct work_struct *work) | |||
2846 | * valid, it is important to turn the device back off. | 3035 | * valid, it is important to turn the device back off. |
2847 | */ | 3036 | */ |
2848 | if (test_bit(HCI_RFKILLED, &hdev->dev_flags) || | 3037 | if (test_bit(HCI_RFKILLED, &hdev->dev_flags) || |
3038 | test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) || | ||
2849 | (hdev->dev_type == HCI_BREDR && | 3039 | (hdev->dev_type == HCI_BREDR && |
2850 | !bacmp(&hdev->bdaddr, BDADDR_ANY) && | 3040 | !bacmp(&hdev->bdaddr, BDADDR_ANY) && |
2851 | !bacmp(&hdev->static_addr, BDADDR_ANY))) { | 3041 | !bacmp(&hdev->static_addr, BDADDR_ANY))) { |
@@ -2856,8 +3046,34 @@ static void hci_power_on(struct work_struct *work) | |||
2856 | HCI_AUTO_OFF_TIMEOUT); | 3046 | HCI_AUTO_OFF_TIMEOUT); |
2857 | } | 3047 | } |
2858 | 3048 | ||
2859 | if (test_and_clear_bit(HCI_SETUP, &hdev->dev_flags)) | 3049 | if (test_and_clear_bit(HCI_SETUP, &hdev->dev_flags)) { |
3050 | /* For unconfigured devices, set the HCI_RAW flag | ||
3051 | * so that userspace can easily identify them. | ||
3052 | */ | ||
3053 | if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) | ||
3054 | set_bit(HCI_RAW, &hdev->flags); | ||
3055 | |||
3056 | /* For fully configured devices, this will send | ||
3057 | * the Index Added event. For unconfigured devices, | ||
3058 | * it will send Unconfigued Index Added event. | ||
3059 | * | ||
3060 | * Devices with HCI_QUIRK_RAW_DEVICE are ignored | ||
3061 | * and no event will be send. | ||
3062 | */ | ||
2860 | mgmt_index_added(hdev); | 3063 | mgmt_index_added(hdev); |
3064 | } else if (test_and_clear_bit(HCI_CONFIG, &hdev->dev_flags)) { | ||
3065 | /* When the controller is now configured, then it | ||
3066 | * is important to clear the HCI_RAW flag. | ||
3067 | */ | ||
3068 | if (!test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) | ||
3069 | clear_bit(HCI_RAW, &hdev->flags); | ||
3070 | |||
3071 | /* Powering on the controller with HCI_CONFIG set only | ||
3072 | * happens with the transition from unconfigured to | ||
3073 | * configured. This will send the Index Added event. | ||
3074 | */ | ||
3075 | mgmt_index_added(hdev); | ||
3076 | } | ||
2861 | } | 3077 | } |
2862 | 3078 | ||
2863 | static void hci_power_off(struct work_struct *work) | 3079 | static void hci_power_off(struct work_struct *work) |
@@ -2972,16 +3188,16 @@ static bool hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn, | |||
2972 | return false; | 3188 | return false; |
2973 | } | 3189 | } |
2974 | 3190 | ||
2975 | static bool ltk_type_master(u8 type) | 3191 | static u8 ltk_role(u8 type) |
2976 | { | 3192 | { |
2977 | if (type == HCI_SMP_STK || type == HCI_SMP_LTK) | 3193 | if (type == SMP_LTK) |
2978 | return true; | 3194 | return HCI_ROLE_MASTER; |
2979 | 3195 | ||
2980 | return false; | 3196 | return HCI_ROLE_SLAVE; |
2981 | } | 3197 | } |
2982 | 3198 | ||
2983 | struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, __le64 rand, | 3199 | struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, __le64 rand, |
2984 | bool master) | 3200 | u8 role) |
2985 | { | 3201 | { |
2986 | struct smp_ltk *k; | 3202 | struct smp_ltk *k; |
2987 | 3203 | ||
@@ -2989,7 +3205,7 @@ struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, __le64 rand, | |||
2989 | if (k->ediv != ediv || k->rand != rand) | 3205 | if (k->ediv != ediv || k->rand != rand) |
2990 | continue; | 3206 | continue; |
2991 | 3207 | ||
2992 | if (ltk_type_master(k->type) != master) | 3208 | if (ltk_role(k->type) != role) |
2993 | continue; | 3209 | continue; |
2994 | 3210 | ||
2995 | return k; | 3211 | return k; |
@@ -2999,14 +3215,14 @@ struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, __le64 rand, | |||
2999 | } | 3215 | } |
3000 | 3216 | ||
3001 | struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr, | 3217 | struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr, |
3002 | u8 addr_type, bool master) | 3218 | u8 addr_type, u8 role) |
3003 | { | 3219 | { |
3004 | struct smp_ltk *k; | 3220 | struct smp_ltk *k; |
3005 | 3221 | ||
3006 | list_for_each_entry(k, &hdev->long_term_keys, list) | 3222 | list_for_each_entry(k, &hdev->long_term_keys, list) |
3007 | if (addr_type == k->bdaddr_type && | 3223 | if (addr_type == k->bdaddr_type && |
3008 | bacmp(bdaddr, &k->bdaddr) == 0 && | 3224 | bacmp(bdaddr, &k->bdaddr) == 0 && |
3009 | ltk_type_master(k->type) == master) | 3225 | ltk_role(k->type) == role) |
3010 | return k; | 3226 | return k; |
3011 | 3227 | ||
3012 | return NULL; | 3228 | return NULL; |
@@ -3049,12 +3265,12 @@ struct smp_irk *hci_find_irk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
3049 | return NULL; | 3265 | return NULL; |
3050 | } | 3266 | } |
3051 | 3267 | ||
3052 | int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, | 3268 | struct link_key *hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, |
3053 | bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len) | 3269 | bdaddr_t *bdaddr, u8 *val, u8 type, |
3270 | u8 pin_len, bool *persistent) | ||
3054 | { | 3271 | { |
3055 | struct link_key *key, *old_key; | 3272 | struct link_key *key, *old_key; |
3056 | u8 old_key_type; | 3273 | u8 old_key_type; |
3057 | bool persistent; | ||
3058 | 3274 | ||
3059 | old_key = hci_find_link_key(hdev, bdaddr); | 3275 | old_key = hci_find_link_key(hdev, bdaddr); |
3060 | if (old_key) { | 3276 | if (old_key) { |
@@ -3064,7 +3280,7 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, | |||
3064 | old_key_type = conn ? conn->key_type : 0xff; | 3280 | old_key_type = conn ? conn->key_type : 0xff; |
3065 | key = kzalloc(sizeof(*key), GFP_KERNEL); | 3281 | key = kzalloc(sizeof(*key), GFP_KERNEL); |
3066 | if (!key) | 3282 | if (!key) |
3067 | return -ENOMEM; | 3283 | return NULL; |
3068 | list_add(&key->list, &hdev->link_keys); | 3284 | list_add(&key->list, &hdev->link_keys); |
3069 | } | 3285 | } |
3070 | 3286 | ||
@@ -3089,17 +3305,11 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, | |||
3089 | else | 3305 | else |
3090 | key->type = type; | 3306 | key->type = type; |
3091 | 3307 | ||
3092 | if (!new_key) | 3308 | if (persistent) |
3093 | return 0; | 3309 | *persistent = hci_persistent_key(hdev, conn, type, |
3094 | 3310 | old_key_type); | |
3095 | persistent = hci_persistent_key(hdev, conn, type, old_key_type); | ||
3096 | 3311 | ||
3097 | mgmt_new_link_key(hdev, key, persistent); | 3312 | return key; |
3098 | |||
3099 | if (conn) | ||
3100 | conn->flush_key = !persistent; | ||
3101 | |||
3102 | return 0; | ||
3103 | } | 3313 | } |
3104 | 3314 | ||
3105 | struct smp_ltk *hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, | 3315 | struct smp_ltk *hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, |
@@ -3107,9 +3317,9 @@ struct smp_ltk *hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
3107 | u8 tk[16], u8 enc_size, __le16 ediv, __le64 rand) | 3317 | u8 tk[16], u8 enc_size, __le16 ediv, __le64 rand) |
3108 | { | 3318 | { |
3109 | struct smp_ltk *key, *old_key; | 3319 | struct smp_ltk *key, *old_key; |
3110 | bool master = ltk_type_master(type); | 3320 | u8 role = ltk_role(type); |
3111 | 3321 | ||
3112 | old_key = hci_find_ltk_by_addr(hdev, bdaddr, addr_type, master); | 3322 | old_key = hci_find_ltk_by_addr(hdev, bdaddr, addr_type, role); |
3113 | if (old_key) | 3323 | if (old_key) |
3114 | key = old_key; | 3324 | key = old_key; |
3115 | else { | 3325 | else { |
@@ -3205,9 +3415,10 @@ void hci_remove_irk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type) | |||
3205 | } | 3415 | } |
3206 | 3416 | ||
3207 | /* HCI command timer function */ | 3417 | /* HCI command timer function */ |
3208 | static void hci_cmd_timeout(unsigned long arg) | 3418 | static void hci_cmd_timeout(struct work_struct *work) |
3209 | { | 3419 | { |
3210 | struct hci_dev *hdev = (void *) arg; | 3420 | struct hci_dev *hdev = container_of(work, struct hci_dev, |
3421 | cmd_timer.work); | ||
3211 | 3422 | ||
3212 | if (hdev->sent_cmd) { | 3423 | if (hdev->sent_cmd) { |
3213 | struct hci_command_hdr *sent = (void *) hdev->sent_cmd->data; | 3424 | struct hci_command_hdr *sent = (void *) hdev->sent_cmd->data; |
@@ -3313,12 +3524,12 @@ int hci_add_remote_oob_ext_data(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
3313 | return 0; | 3524 | return 0; |
3314 | } | 3525 | } |
3315 | 3526 | ||
3316 | struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, | 3527 | struct bdaddr_list *hci_bdaddr_list_lookup(struct list_head *bdaddr_list, |
3317 | bdaddr_t *bdaddr, u8 type) | 3528 | bdaddr_t *bdaddr, u8 type) |
3318 | { | 3529 | { |
3319 | struct bdaddr_list *b; | 3530 | struct bdaddr_list *b; |
3320 | 3531 | ||
3321 | list_for_each_entry(b, &hdev->blacklist, list) { | 3532 | list_for_each_entry(b, bdaddr_list, list) { |
3322 | if (!bacmp(&b->bdaddr, bdaddr) && b->bdaddr_type == type) | 3533 | if (!bacmp(&b->bdaddr, bdaddr) && b->bdaddr_type == type) |
3323 | return b; | 3534 | return b; |
3324 | } | 3535 | } |
@@ -3326,11 +3537,11 @@ struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, | |||
3326 | return NULL; | 3537 | return NULL; |
3327 | } | 3538 | } |
3328 | 3539 | ||
3329 | static void hci_blacklist_clear(struct hci_dev *hdev) | 3540 | void hci_bdaddr_list_clear(struct list_head *bdaddr_list) |
3330 | { | 3541 | { |
3331 | struct list_head *p, *n; | 3542 | struct list_head *p, *n; |
3332 | 3543 | ||
3333 | list_for_each_safe(p, n, &hdev->blacklist) { | 3544 | list_for_each_safe(p, n, bdaddr_list) { |
3334 | struct bdaddr_list *b = list_entry(p, struct bdaddr_list, list); | 3545 | struct bdaddr_list *b = list_entry(p, struct bdaddr_list, list); |
3335 | 3546 | ||
3336 | list_del(p); | 3547 | list_del(p); |
@@ -3338,99 +3549,38 @@ static void hci_blacklist_clear(struct hci_dev *hdev) | |||
3338 | } | 3549 | } |
3339 | } | 3550 | } |
3340 | 3551 | ||
3341 | int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) | 3552 | int hci_bdaddr_list_add(struct list_head *list, bdaddr_t *bdaddr, u8 type) |
3342 | { | 3553 | { |
3343 | struct bdaddr_list *entry; | 3554 | struct bdaddr_list *entry; |
3344 | 3555 | ||
3345 | if (!bacmp(bdaddr, BDADDR_ANY)) | 3556 | if (!bacmp(bdaddr, BDADDR_ANY)) |
3346 | return -EBADF; | 3557 | return -EBADF; |
3347 | 3558 | ||
3348 | if (hci_blacklist_lookup(hdev, bdaddr, type)) | 3559 | if (hci_bdaddr_list_lookup(list, bdaddr, type)) |
3349 | return -EEXIST; | 3560 | return -EEXIST; |
3350 | 3561 | ||
3351 | entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL); | 3562 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); |
3352 | if (!entry) | 3563 | if (!entry) |
3353 | return -ENOMEM; | 3564 | return -ENOMEM; |
3354 | 3565 | ||
3355 | bacpy(&entry->bdaddr, bdaddr); | 3566 | bacpy(&entry->bdaddr, bdaddr); |
3356 | entry->bdaddr_type = type; | 3567 | entry->bdaddr_type = type; |
3357 | 3568 | ||
3358 | list_add(&entry->list, &hdev->blacklist); | 3569 | list_add(&entry->list, list); |
3359 | 3570 | ||
3360 | return mgmt_device_blocked(hdev, bdaddr, type); | 3571 | return 0; |
3361 | } | 3572 | } |
3362 | 3573 | ||
3363 | int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) | 3574 | int hci_bdaddr_list_del(struct list_head *list, bdaddr_t *bdaddr, u8 type) |
3364 | { | 3575 | { |
3365 | struct bdaddr_list *entry; | 3576 | struct bdaddr_list *entry; |
3366 | 3577 | ||
3367 | if (!bacmp(bdaddr, BDADDR_ANY)) { | 3578 | if (!bacmp(bdaddr, BDADDR_ANY)) { |
3368 | hci_blacklist_clear(hdev); | 3579 | hci_bdaddr_list_clear(list); |
3369 | return 0; | 3580 | return 0; |
3370 | } | 3581 | } |
3371 | 3582 | ||
3372 | entry = hci_blacklist_lookup(hdev, bdaddr, type); | 3583 | entry = hci_bdaddr_list_lookup(list, bdaddr, type); |
3373 | if (!entry) | ||
3374 | return -ENOENT; | ||
3375 | |||
3376 | list_del(&entry->list); | ||
3377 | kfree(entry); | ||
3378 | |||
3379 | return mgmt_device_unblocked(hdev, bdaddr, type); | ||
3380 | } | ||
3381 | |||
3382 | struct bdaddr_list *hci_white_list_lookup(struct hci_dev *hdev, | ||
3383 | bdaddr_t *bdaddr, u8 type) | ||
3384 | { | ||
3385 | struct bdaddr_list *b; | ||
3386 | |||
3387 | list_for_each_entry(b, &hdev->le_white_list, list) { | ||
3388 | if (!bacmp(&b->bdaddr, bdaddr) && b->bdaddr_type == type) | ||
3389 | return b; | ||
3390 | } | ||
3391 | |||
3392 | return NULL; | ||
3393 | } | ||
3394 | |||
3395 | void hci_white_list_clear(struct hci_dev *hdev) | ||
3396 | { | ||
3397 | struct list_head *p, *n; | ||
3398 | |||
3399 | list_for_each_safe(p, n, &hdev->le_white_list) { | ||
3400 | struct bdaddr_list *b = list_entry(p, struct bdaddr_list, list); | ||
3401 | |||
3402 | list_del(p); | ||
3403 | kfree(b); | ||
3404 | } | ||
3405 | } | ||
3406 | |||
3407 | int hci_white_list_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) | ||
3408 | { | ||
3409 | struct bdaddr_list *entry; | ||
3410 | |||
3411 | if (!bacmp(bdaddr, BDADDR_ANY)) | ||
3412 | return -EBADF; | ||
3413 | |||
3414 | entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL); | ||
3415 | if (!entry) | ||
3416 | return -ENOMEM; | ||
3417 | |||
3418 | bacpy(&entry->bdaddr, bdaddr); | ||
3419 | entry->bdaddr_type = type; | ||
3420 | |||
3421 | list_add(&entry->list, &hdev->le_white_list); | ||
3422 | |||
3423 | return 0; | ||
3424 | } | ||
3425 | |||
3426 | int hci_white_list_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) | ||
3427 | { | ||
3428 | struct bdaddr_list *entry; | ||
3429 | |||
3430 | if (!bacmp(bdaddr, BDADDR_ANY)) | ||
3431 | return -EBADF; | ||
3432 | |||
3433 | entry = hci_white_list_lookup(hdev, bdaddr, type); | ||
3434 | if (!entry) | 3584 | if (!entry) |
3435 | return -ENOENT; | 3585 | return -ENOENT; |
3436 | 3586 | ||
@@ -3446,6 +3596,10 @@ struct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev, | |||
3446 | { | 3596 | { |
3447 | struct hci_conn_params *params; | 3597 | struct hci_conn_params *params; |
3448 | 3598 | ||
3599 | /* The conn params list only contains identity addresses */ | ||
3600 | if (!hci_is_identity_address(addr, addr_type)) | ||
3601 | return NULL; | ||
3602 | |||
3449 | list_for_each_entry(params, &hdev->le_conn_params, list) { | 3603 | list_for_each_entry(params, &hdev->le_conn_params, list) { |
3450 | if (bacmp(¶ms->addr, addr) == 0 && | 3604 | if (bacmp(¶ms->addr, addr) == 0 && |
3451 | params->addr_type == addr_type) { | 3605 | params->addr_type == addr_type) { |
@@ -3473,62 +3627,98 @@ static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type) | |||
3473 | return true; | 3627 | return true; |
3474 | } | 3628 | } |
3475 | 3629 | ||
3476 | static bool is_identity_address(bdaddr_t *addr, u8 addr_type) | 3630 | /* This function requires the caller holds hdev->lock */ |
3631 | struct hci_conn_params *hci_pend_le_action_lookup(struct list_head *list, | ||
3632 | bdaddr_t *addr, u8 addr_type) | ||
3477 | { | 3633 | { |
3478 | if (addr_type == ADDR_LE_DEV_PUBLIC) | 3634 | struct hci_conn_params *param; |
3479 | return true; | ||
3480 | 3635 | ||
3481 | /* Check for Random Static address type */ | 3636 | /* The list only contains identity addresses */ |
3482 | if ((addr->b[5] & 0xc0) == 0xc0) | 3637 | if (!hci_is_identity_address(addr, addr_type)) |
3483 | return true; | 3638 | return NULL; |
3484 | 3639 | ||
3485 | return false; | 3640 | list_for_each_entry(param, list, action) { |
3641 | if (bacmp(¶m->addr, addr) == 0 && | ||
3642 | param->addr_type == addr_type) | ||
3643 | return param; | ||
3644 | } | ||
3645 | |||
3646 | return NULL; | ||
3486 | } | 3647 | } |
3487 | 3648 | ||
3488 | /* This function requires the caller holds hdev->lock */ | 3649 | /* This function requires the caller holds hdev->lock */ |
3489 | int hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type, | 3650 | struct hci_conn_params *hci_conn_params_add(struct hci_dev *hdev, |
3490 | u8 auto_connect, u16 conn_min_interval, | 3651 | bdaddr_t *addr, u8 addr_type) |
3491 | u16 conn_max_interval) | ||
3492 | { | 3652 | { |
3493 | struct hci_conn_params *params; | 3653 | struct hci_conn_params *params; |
3494 | 3654 | ||
3495 | if (!is_identity_address(addr, addr_type)) | 3655 | if (!hci_is_identity_address(addr, addr_type)) |
3496 | return -EINVAL; | 3656 | return NULL; |
3497 | 3657 | ||
3498 | params = hci_conn_params_lookup(hdev, addr, addr_type); | 3658 | params = hci_conn_params_lookup(hdev, addr, addr_type); |
3499 | if (params) | 3659 | if (params) |
3500 | goto update; | 3660 | return params; |
3501 | 3661 | ||
3502 | params = kzalloc(sizeof(*params), GFP_KERNEL); | 3662 | params = kzalloc(sizeof(*params), GFP_KERNEL); |
3503 | if (!params) { | 3663 | if (!params) { |
3504 | BT_ERR("Out of memory"); | 3664 | BT_ERR("Out of memory"); |
3505 | return -ENOMEM; | 3665 | return NULL; |
3506 | } | 3666 | } |
3507 | 3667 | ||
3508 | bacpy(¶ms->addr, addr); | 3668 | bacpy(¶ms->addr, addr); |
3509 | params->addr_type = addr_type; | 3669 | params->addr_type = addr_type; |
3510 | 3670 | ||
3511 | list_add(¶ms->list, &hdev->le_conn_params); | 3671 | list_add(¶ms->list, &hdev->le_conn_params); |
3672 | INIT_LIST_HEAD(¶ms->action); | ||
3512 | 3673 | ||
3513 | update: | 3674 | params->conn_min_interval = hdev->le_conn_min_interval; |
3514 | params->conn_min_interval = conn_min_interval; | 3675 | params->conn_max_interval = hdev->le_conn_max_interval; |
3515 | params->conn_max_interval = conn_max_interval; | 3676 | params->conn_latency = hdev->le_conn_latency; |
3516 | params->auto_connect = auto_connect; | 3677 | params->supervision_timeout = hdev->le_supv_timeout; |
3678 | params->auto_connect = HCI_AUTO_CONN_DISABLED; | ||
3679 | |||
3680 | BT_DBG("addr %pMR (type %u)", addr, addr_type); | ||
3681 | |||
3682 | return params; | ||
3683 | } | ||
3684 | |||
3685 | /* This function requires the caller holds hdev->lock */ | ||
3686 | int hci_conn_params_set(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type, | ||
3687 | u8 auto_connect) | ||
3688 | { | ||
3689 | struct hci_conn_params *params; | ||
3690 | |||
3691 | params = hci_conn_params_add(hdev, addr, addr_type); | ||
3692 | if (!params) | ||
3693 | return -EIO; | ||
3694 | |||
3695 | if (params->auto_connect == auto_connect) | ||
3696 | return 0; | ||
3697 | |||
3698 | list_del_init(¶ms->action); | ||
3517 | 3699 | ||
3518 | switch (auto_connect) { | 3700 | switch (auto_connect) { |
3519 | case HCI_AUTO_CONN_DISABLED: | 3701 | case HCI_AUTO_CONN_DISABLED: |
3520 | case HCI_AUTO_CONN_LINK_LOSS: | 3702 | case HCI_AUTO_CONN_LINK_LOSS: |
3521 | hci_pend_le_conn_del(hdev, addr, addr_type); | 3703 | hci_update_background_scan(hdev); |
3522 | break; | 3704 | break; |
3705 | case HCI_AUTO_CONN_REPORT: | ||
3706 | list_add(¶ms->action, &hdev->pend_le_reports); | ||
3707 | hci_update_background_scan(hdev); | ||
3708 | break; | ||
3709 | case HCI_AUTO_CONN_DIRECT: | ||
3523 | case HCI_AUTO_CONN_ALWAYS: | 3710 | case HCI_AUTO_CONN_ALWAYS: |
3524 | if (!is_connected(hdev, addr, addr_type)) | 3711 | if (!is_connected(hdev, addr, addr_type)) { |
3525 | hci_pend_le_conn_add(hdev, addr, addr_type); | 3712 | list_add(¶ms->action, &hdev->pend_le_conns); |
3713 | hci_update_background_scan(hdev); | ||
3714 | } | ||
3526 | break; | 3715 | break; |
3527 | } | 3716 | } |
3528 | 3717 | ||
3529 | BT_DBG("addr %pMR (type %u) auto_connect %u conn_min_interval 0x%.4x " | 3718 | params->auto_connect = auto_connect; |
3530 | "conn_max_interval 0x%.4x", addr, addr_type, auto_connect, | 3719 | |
3531 | conn_min_interval, conn_max_interval); | 3720 | BT_DBG("addr %pMR (type %u) auto_connect %u", addr, addr_type, |
3721 | auto_connect); | ||
3532 | 3722 | ||
3533 | return 0; | 3723 | return 0; |
3534 | } | 3724 | } |
@@ -3542,97 +3732,49 @@ void hci_conn_params_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type) | |||
3542 | if (!params) | 3732 | if (!params) |
3543 | return; | 3733 | return; |
3544 | 3734 | ||
3545 | hci_pend_le_conn_del(hdev, addr, addr_type); | 3735 | if (params->conn) |
3736 | hci_conn_drop(params->conn); | ||
3546 | 3737 | ||
3738 | list_del(¶ms->action); | ||
3547 | list_del(¶ms->list); | 3739 | list_del(¶ms->list); |
3548 | kfree(params); | 3740 | kfree(params); |
3549 | 3741 | ||
3742 | hci_update_background_scan(hdev); | ||
3743 | |||
3550 | BT_DBG("addr %pMR (type %u)", addr, addr_type); | 3744 | BT_DBG("addr %pMR (type %u)", addr, addr_type); |
3551 | } | 3745 | } |
3552 | 3746 | ||
3553 | /* This function requires the caller holds hdev->lock */ | 3747 | /* This function requires the caller holds hdev->lock */ |
3554 | void hci_conn_params_clear(struct hci_dev *hdev) | 3748 | void hci_conn_params_clear_disabled(struct hci_dev *hdev) |
3555 | { | 3749 | { |
3556 | struct hci_conn_params *params, *tmp; | 3750 | struct hci_conn_params *params, *tmp; |
3557 | 3751 | ||
3558 | list_for_each_entry_safe(params, tmp, &hdev->le_conn_params, list) { | 3752 | list_for_each_entry_safe(params, tmp, &hdev->le_conn_params, list) { |
3753 | if (params->auto_connect != HCI_AUTO_CONN_DISABLED) | ||
3754 | continue; | ||
3559 | list_del(¶ms->list); | 3755 | list_del(¶ms->list); |
3560 | kfree(params); | 3756 | kfree(params); |
3561 | } | 3757 | } |
3562 | 3758 | ||
3563 | BT_DBG("All LE connection parameters were removed"); | 3759 | BT_DBG("All LE disabled connection parameters were removed"); |
3564 | } | ||
3565 | |||
3566 | /* This function requires the caller holds hdev->lock */ | ||
3567 | struct bdaddr_list *hci_pend_le_conn_lookup(struct hci_dev *hdev, | ||
3568 | bdaddr_t *addr, u8 addr_type) | ||
3569 | { | ||
3570 | struct bdaddr_list *entry; | ||
3571 | |||
3572 | list_for_each_entry(entry, &hdev->pend_le_conns, list) { | ||
3573 | if (bacmp(&entry->bdaddr, addr) == 0 && | ||
3574 | entry->bdaddr_type == addr_type) | ||
3575 | return entry; | ||
3576 | } | ||
3577 | |||
3578 | return NULL; | ||
3579 | } | 3760 | } |
3580 | 3761 | ||
3581 | /* This function requires the caller holds hdev->lock */ | 3762 | /* This function requires the caller holds hdev->lock */ |
3582 | void hci_pend_le_conn_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type) | 3763 | void hci_conn_params_clear_all(struct hci_dev *hdev) |
3583 | { | 3764 | { |
3584 | struct bdaddr_list *entry; | 3765 | struct hci_conn_params *params, *tmp; |
3585 | |||
3586 | entry = hci_pend_le_conn_lookup(hdev, addr, addr_type); | ||
3587 | if (entry) | ||
3588 | goto done; | ||
3589 | 3766 | ||
3590 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); | 3767 | list_for_each_entry_safe(params, tmp, &hdev->le_conn_params, list) { |
3591 | if (!entry) { | 3768 | if (params->conn) |
3592 | BT_ERR("Out of memory"); | 3769 | hci_conn_drop(params->conn); |
3593 | return; | 3770 | list_del(¶ms->action); |
3771 | list_del(¶ms->list); | ||
3772 | kfree(params); | ||
3594 | } | 3773 | } |
3595 | 3774 | ||
3596 | bacpy(&entry->bdaddr, addr); | ||
3597 | entry->bdaddr_type = addr_type; | ||
3598 | |||
3599 | list_add(&entry->list, &hdev->pend_le_conns); | ||
3600 | |||
3601 | BT_DBG("addr %pMR (type %u)", addr, addr_type); | ||
3602 | |||
3603 | done: | ||
3604 | hci_update_background_scan(hdev); | 3775 | hci_update_background_scan(hdev); |
3605 | } | ||
3606 | 3776 | ||
3607 | /* This function requires the caller holds hdev->lock */ | 3777 | BT_DBG("All LE connection parameters were removed"); |
3608 | void hci_pend_le_conn_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type) | ||
3609 | { | ||
3610 | struct bdaddr_list *entry; | ||
3611 | |||
3612 | entry = hci_pend_le_conn_lookup(hdev, addr, addr_type); | ||
3613 | if (!entry) | ||
3614 | goto done; | ||
3615 | |||
3616 | list_del(&entry->list); | ||
3617 | kfree(entry); | ||
3618 | |||
3619 | BT_DBG("addr %pMR (type %u)", addr, addr_type); | ||
3620 | |||
3621 | done: | ||
3622 | hci_update_background_scan(hdev); | ||
3623 | } | ||
3624 | |||
3625 | /* This function requires the caller holds hdev->lock */ | ||
3626 | void hci_pend_le_conns_clear(struct hci_dev *hdev) | ||
3627 | { | ||
3628 | struct bdaddr_list *entry, *tmp; | ||
3629 | |||
3630 | list_for_each_entry_safe(entry, tmp, &hdev->pend_le_conns, list) { | ||
3631 | list_del(&entry->list); | ||
3632 | kfree(entry); | ||
3633 | } | ||
3634 | |||
3635 | BT_DBG("All LE pending connections cleared"); | ||
3636 | } | 3778 | } |
3637 | 3779 | ||
3638 | static void inquiry_complete(struct hci_dev *hdev, u8 status) | 3780 | static void inquiry_complete(struct hci_dev *hdev, u8 status) |
@@ -3722,7 +3864,7 @@ static void set_random_addr(struct hci_request *req, bdaddr_t *rpa) | |||
3722 | * In this kind of scenario skip the update and let the random | 3864 | * In this kind of scenario skip the update and let the random |
3723 | * address be updated at the next cycle. | 3865 | * address be updated at the next cycle. |
3724 | */ | 3866 | */ |
3725 | if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) || | 3867 | if (test_bit(HCI_LE_ADV, &hdev->dev_flags) || |
3726 | hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT)) { | 3868 | hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT)) { |
3727 | BT_DBG("Deferring random address update"); | 3869 | BT_DBG("Deferring random address update"); |
3728 | return; | 3870 | return; |
@@ -3784,7 +3926,7 @@ int hci_update_random_address(struct hci_request *req, bool require_privacy, | |||
3784 | * the HCI command if the current random address is already the | 3926 | * the HCI command if the current random address is already the |
3785 | * static one. | 3927 | * static one. |
3786 | */ | 3928 | */ |
3787 | if (test_bit(HCI_FORCE_STATIC_ADDR, &hdev->dev_flags) || | 3929 | if (test_bit(HCI_FORCE_STATIC_ADDR, &hdev->dbg_flags) || |
3788 | !bacmp(&hdev->bdaddr, BDADDR_ANY)) { | 3930 | !bacmp(&hdev->bdaddr, BDADDR_ANY)) { |
3789 | *own_addr_type = ADDR_LE_DEV_RANDOM; | 3931 | *own_addr_type = ADDR_LE_DEV_RANDOM; |
3790 | if (bacmp(&hdev->static_addr, &hdev->random_addr)) | 3932 | if (bacmp(&hdev->static_addr, &hdev->random_addr)) |
@@ -3813,7 +3955,7 @@ int hci_update_random_address(struct hci_request *req, bool require_privacy, | |||
3813 | void hci_copy_identity_address(struct hci_dev *hdev, bdaddr_t *bdaddr, | 3955 | void hci_copy_identity_address(struct hci_dev *hdev, bdaddr_t *bdaddr, |
3814 | u8 *bdaddr_type) | 3956 | u8 *bdaddr_type) |
3815 | { | 3957 | { |
3816 | if (test_bit(HCI_FORCE_STATIC_ADDR, &hdev->dev_flags) || | 3958 | if (test_bit(HCI_FORCE_STATIC_ADDR, &hdev->dbg_flags) || |
3817 | !bacmp(&hdev->bdaddr, BDADDR_ANY)) { | 3959 | !bacmp(&hdev->bdaddr, BDADDR_ANY)) { |
3818 | bacpy(bdaddr, &hdev->static_addr); | 3960 | bacpy(bdaddr, &hdev->static_addr); |
3819 | *bdaddr_type = ADDR_LE_DEV_RANDOM; | 3961 | *bdaddr_type = ADDR_LE_DEV_RANDOM; |
@@ -3828,7 +3970,7 @@ struct hci_dev *hci_alloc_dev(void) | |||
3828 | { | 3970 | { |
3829 | struct hci_dev *hdev; | 3971 | struct hci_dev *hdev; |
3830 | 3972 | ||
3831 | hdev = kzalloc(sizeof(struct hci_dev), GFP_KERNEL); | 3973 | hdev = kzalloc(sizeof(*hdev), GFP_KERNEL); |
3832 | if (!hdev) | 3974 | if (!hdev) |
3833 | return NULL; | 3975 | return NULL; |
3834 | 3976 | ||
@@ -3837,6 +3979,7 @@ struct hci_dev *hci_alloc_dev(void) | |||
3837 | hdev->link_mode = (HCI_LM_ACCEPT); | 3979 | hdev->link_mode = (HCI_LM_ACCEPT); |
3838 | hdev->num_iac = 0x01; /* One IAC support is mandatory */ | 3980 | hdev->num_iac = 0x01; /* One IAC support is mandatory */ |
3839 | hdev->io_capability = 0x03; /* No Input No Output */ | 3981 | hdev->io_capability = 0x03; /* No Input No Output */ |
3982 | hdev->manufacturer = 0xffff; /* Default to internal use */ | ||
3840 | hdev->inq_tx_power = HCI_TX_POWER_INVALID; | 3983 | hdev->inq_tx_power = HCI_TX_POWER_INVALID; |
3841 | hdev->adv_tx_power = HCI_TX_POWER_INVALID; | 3984 | hdev->adv_tx_power = HCI_TX_POWER_INVALID; |
3842 | 3985 | ||
@@ -3844,10 +3987,14 @@ struct hci_dev *hci_alloc_dev(void) | |||
3844 | hdev->sniff_min_interval = 80; | 3987 | hdev->sniff_min_interval = 80; |
3845 | 3988 | ||
3846 | hdev->le_adv_channel_map = 0x07; | 3989 | hdev->le_adv_channel_map = 0x07; |
3990 | hdev->le_adv_min_interval = 0x0800; | ||
3991 | hdev->le_adv_max_interval = 0x0800; | ||
3847 | hdev->le_scan_interval = 0x0060; | 3992 | hdev->le_scan_interval = 0x0060; |
3848 | hdev->le_scan_window = 0x0030; | 3993 | hdev->le_scan_window = 0x0030; |
3849 | hdev->le_conn_min_interval = 0x0028; | 3994 | hdev->le_conn_min_interval = 0x0028; |
3850 | hdev->le_conn_max_interval = 0x0038; | 3995 | hdev->le_conn_max_interval = 0x0038; |
3996 | hdev->le_conn_latency = 0x0000; | ||
3997 | hdev->le_supv_timeout = 0x002a; | ||
3851 | 3998 | ||
3852 | hdev->rpa_timeout = HCI_DEFAULT_RPA_TIMEOUT; | 3999 | hdev->rpa_timeout = HCI_DEFAULT_RPA_TIMEOUT; |
3853 | hdev->discov_interleaved_timeout = DISCOV_INTERLEAVED_TIMEOUT; | 4000 | hdev->discov_interleaved_timeout = DISCOV_INTERLEAVED_TIMEOUT; |
@@ -3859,6 +4006,7 @@ struct hci_dev *hci_alloc_dev(void) | |||
3859 | 4006 | ||
3860 | INIT_LIST_HEAD(&hdev->mgmt_pending); | 4007 | INIT_LIST_HEAD(&hdev->mgmt_pending); |
3861 | INIT_LIST_HEAD(&hdev->blacklist); | 4008 | INIT_LIST_HEAD(&hdev->blacklist); |
4009 | INIT_LIST_HEAD(&hdev->whitelist); | ||
3862 | INIT_LIST_HEAD(&hdev->uuids); | 4010 | INIT_LIST_HEAD(&hdev->uuids); |
3863 | INIT_LIST_HEAD(&hdev->link_keys); | 4011 | INIT_LIST_HEAD(&hdev->link_keys); |
3864 | INIT_LIST_HEAD(&hdev->long_term_keys); | 4012 | INIT_LIST_HEAD(&hdev->long_term_keys); |
@@ -3867,6 +4015,7 @@ struct hci_dev *hci_alloc_dev(void) | |||
3867 | INIT_LIST_HEAD(&hdev->le_white_list); | 4015 | INIT_LIST_HEAD(&hdev->le_white_list); |
3868 | INIT_LIST_HEAD(&hdev->le_conn_params); | 4016 | INIT_LIST_HEAD(&hdev->le_conn_params); |
3869 | INIT_LIST_HEAD(&hdev->pend_le_conns); | 4017 | INIT_LIST_HEAD(&hdev->pend_le_conns); |
4018 | INIT_LIST_HEAD(&hdev->pend_le_reports); | ||
3870 | INIT_LIST_HEAD(&hdev->conn_hash.list); | 4019 | INIT_LIST_HEAD(&hdev->conn_hash.list); |
3871 | 4020 | ||
3872 | INIT_WORK(&hdev->rx_work, hci_rx_work); | 4021 | INIT_WORK(&hdev->rx_work, hci_rx_work); |
@@ -3884,7 +4033,7 @@ struct hci_dev *hci_alloc_dev(void) | |||
3884 | 4033 | ||
3885 | init_waitqueue_head(&hdev->req_wait_q); | 4034 | init_waitqueue_head(&hdev->req_wait_q); |
3886 | 4035 | ||
3887 | setup_timer(&hdev->cmd_timer, hci_cmd_timeout, (unsigned long) hdev); | 4036 | INIT_DELAYED_WORK(&hdev->cmd_timer, hci_cmd_timeout); |
3888 | 4037 | ||
3889 | hci_init_sysfs(hdev); | 4038 | hci_init_sysfs(hdev); |
3890 | discovery_init(hdev); | 4039 | discovery_init(hdev); |
@@ -3906,7 +4055,7 @@ int hci_register_dev(struct hci_dev *hdev) | |||
3906 | { | 4055 | { |
3907 | int id, error; | 4056 | int id, error; |
3908 | 4057 | ||
3909 | if (!hdev->open || !hdev->close) | 4058 | if (!hdev->open || !hdev->close || !hdev->send) |
3910 | return -EINVAL; | 4059 | return -EINVAL; |
3911 | 4060 | ||
3912 | /* Do not allow HCI_AMP devices to register at index 0, | 4061 | /* Do not allow HCI_AMP devices to register at index 0, |
@@ -3991,6 +4140,12 @@ int hci_register_dev(struct hci_dev *hdev) | |||
3991 | list_add(&hdev->list, &hci_dev_list); | 4140 | list_add(&hdev->list, &hci_dev_list); |
3992 | write_unlock(&hci_dev_list_lock); | 4141 | write_unlock(&hci_dev_list_lock); |
3993 | 4142 | ||
4143 | /* Devices that are marked for raw-only usage are unconfigured | ||
4144 | * and should not be included in normal operation. | ||
4145 | */ | ||
4146 | if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) | ||
4147 | set_bit(HCI_UNCONFIGURED, &hdev->dev_flags); | ||
4148 | |||
3994 | hci_notify(hdev, HCI_DEV_REG); | 4149 | hci_notify(hdev, HCI_DEV_REG); |
3995 | hci_dev_hold(hdev); | 4150 | hci_dev_hold(hdev); |
3996 | 4151 | ||
@@ -4033,7 +4188,8 @@ void hci_unregister_dev(struct hci_dev *hdev) | |||
4033 | cancel_work_sync(&hdev->power_on); | 4188 | cancel_work_sync(&hdev->power_on); |
4034 | 4189 | ||
4035 | if (!test_bit(HCI_INIT, &hdev->flags) && | 4190 | if (!test_bit(HCI_INIT, &hdev->flags) && |
4036 | !test_bit(HCI_SETUP, &hdev->dev_flags)) { | 4191 | !test_bit(HCI_SETUP, &hdev->dev_flags) && |
4192 | !test_bit(HCI_CONFIG, &hdev->dev_flags)) { | ||
4037 | hci_dev_lock(hdev); | 4193 | hci_dev_lock(hdev); |
4038 | mgmt_index_removed(hdev); | 4194 | mgmt_index_removed(hdev); |
4039 | hci_dev_unlock(hdev); | 4195 | hci_dev_unlock(hdev); |
@@ -4061,15 +4217,15 @@ void hci_unregister_dev(struct hci_dev *hdev) | |||
4061 | destroy_workqueue(hdev->req_workqueue); | 4217 | destroy_workqueue(hdev->req_workqueue); |
4062 | 4218 | ||
4063 | hci_dev_lock(hdev); | 4219 | hci_dev_lock(hdev); |
4064 | hci_blacklist_clear(hdev); | 4220 | hci_bdaddr_list_clear(&hdev->blacklist); |
4221 | hci_bdaddr_list_clear(&hdev->whitelist); | ||
4065 | hci_uuids_clear(hdev); | 4222 | hci_uuids_clear(hdev); |
4066 | hci_link_keys_clear(hdev); | 4223 | hci_link_keys_clear(hdev); |
4067 | hci_smp_ltks_clear(hdev); | 4224 | hci_smp_ltks_clear(hdev); |
4068 | hci_smp_irks_clear(hdev); | 4225 | hci_smp_irks_clear(hdev); |
4069 | hci_remote_oob_data_clear(hdev); | 4226 | hci_remote_oob_data_clear(hdev); |
4070 | hci_white_list_clear(hdev); | 4227 | hci_bdaddr_list_clear(&hdev->le_white_list); |
4071 | hci_conn_params_clear(hdev); | 4228 | hci_conn_params_clear_all(hdev); |
4072 | hci_pend_le_conns_clear(hdev); | ||
4073 | hci_dev_unlock(hdev); | 4229 | hci_dev_unlock(hdev); |
4074 | 4230 | ||
4075 | hci_dev_put(hdev); | 4231 | hci_dev_put(hdev); |
@@ -4307,6 +4463,8 @@ EXPORT_SYMBOL(hci_unregister_cb); | |||
4307 | 4463 | ||
4308 | static void hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) | 4464 | static void hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) |
4309 | { | 4465 | { |
4466 | int err; | ||
4467 | |||
4310 | BT_DBG("%s type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len); | 4468 | BT_DBG("%s type %d len %d", hdev->name, bt_cb(skb)->pkt_type, skb->len); |
4311 | 4469 | ||
4312 | /* Time stamp */ | 4470 | /* Time stamp */ |
@@ -4323,8 +4481,11 @@ static void hci_send_frame(struct hci_dev *hdev, struct sk_buff *skb) | |||
4323 | /* Get rid of skb owner, prior to sending to the driver. */ | 4481 | /* Get rid of skb owner, prior to sending to the driver. */ |
4324 | skb_orphan(skb); | 4482 | skb_orphan(skb); |
4325 | 4483 | ||
4326 | if (hdev->send(hdev, skb) < 0) | 4484 | err = hdev->send(hdev, skb); |
4327 | BT_ERR("%s sending frame failed", hdev->name); | 4485 | if (err < 0) { |
4486 | BT_ERR("%s sending frame failed (%d)", hdev->name, err); | ||
4487 | kfree_skb(skb); | ||
4488 | } | ||
4328 | } | 4489 | } |
4329 | 4490 | ||
4330 | void hci_req_init(struct hci_request *req, struct hci_dev *hdev) | 4491 | void hci_req_init(struct hci_request *req, struct hci_dev *hdev) |
@@ -4366,6 +4527,11 @@ int hci_req_run(struct hci_request *req, hci_req_complete_t complete) | |||
4366 | return 0; | 4527 | return 0; |
4367 | } | 4528 | } |
4368 | 4529 | ||
4530 | bool hci_req_pending(struct hci_dev *hdev) | ||
4531 | { | ||
4532 | return (hdev->req_status == HCI_REQ_PEND); | ||
4533 | } | ||
4534 | |||
4369 | static struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, | 4535 | static struct sk_buff *hci_prepare_cmd(struct hci_dev *hdev, u16 opcode, |
4370 | u32 plen, const void *param) | 4536 | u32 plen, const void *param) |
4371 | { | 4537 | { |
@@ -4798,7 +4964,7 @@ static inline int __get_blocks(struct hci_dev *hdev, struct sk_buff *skb) | |||
4798 | 4964 | ||
4799 | static void __check_timeout(struct hci_dev *hdev, unsigned int cnt) | 4965 | static void __check_timeout(struct hci_dev *hdev, unsigned int cnt) |
4800 | { | 4966 | { |
4801 | if (!test_bit(HCI_RAW, &hdev->flags)) { | 4967 | if (!test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) { |
4802 | /* ACL tx timeout must be longer than maximum | 4968 | /* ACL tx timeout must be longer than maximum |
4803 | * link supervision timeout (40.9 seconds) */ | 4969 | * link supervision timeout (40.9 seconds) */ |
4804 | if (!cnt && time_after(jiffies, hdev->acl_last_tx + | 4970 | if (!cnt && time_after(jiffies, hdev->acl_last_tx + |
@@ -4981,7 +5147,7 @@ static void hci_sched_le(struct hci_dev *hdev) | |||
4981 | if (!hci_conn_num(hdev, LE_LINK)) | 5147 | if (!hci_conn_num(hdev, LE_LINK)) |
4982 | return; | 5148 | return; |
4983 | 5149 | ||
4984 | if (!test_bit(HCI_RAW, &hdev->flags)) { | 5150 | if (!test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) { |
4985 | /* LE tx timeout must be longer than maximum | 5151 | /* LE tx timeout must be longer than maximum |
4986 | * link supervision timeout (40.9 seconds) */ | 5152 | * link supervision timeout (40.9 seconds) */ |
4987 | if (!hdev->le_cnt && hdev->le_pkts && | 5153 | if (!hdev->le_cnt && hdev->le_pkts && |
@@ -5226,8 +5392,7 @@ static void hci_rx_work(struct work_struct *work) | |||
5226 | hci_send_to_sock(hdev, skb); | 5392 | hci_send_to_sock(hdev, skb); |
5227 | } | 5393 | } |
5228 | 5394 | ||
5229 | if (test_bit(HCI_RAW, &hdev->flags) || | 5395 | if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) { |
5230 | test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) { | ||
5231 | kfree_skb(skb); | 5396 | kfree_skb(skb); |
5232 | continue; | 5397 | continue; |
5233 | } | 5398 | } |
@@ -5287,10 +5452,10 @@ static void hci_cmd_work(struct work_struct *work) | |||
5287 | atomic_dec(&hdev->cmd_cnt); | 5452 | atomic_dec(&hdev->cmd_cnt); |
5288 | hci_send_frame(hdev, skb); | 5453 | hci_send_frame(hdev, skb); |
5289 | if (test_bit(HCI_RESET, &hdev->flags)) | 5454 | if (test_bit(HCI_RESET, &hdev->flags)) |
5290 | del_timer(&hdev->cmd_timer); | 5455 | cancel_delayed_work(&hdev->cmd_timer); |
5291 | else | 5456 | else |
5292 | mod_timer(&hdev->cmd_timer, | 5457 | schedule_delayed_work(&hdev->cmd_timer, |
5293 | jiffies + HCI_CMD_TIMEOUT); | 5458 | HCI_CMD_TIMEOUT); |
5294 | } else { | 5459 | } else { |
5295 | skb_queue_head(&hdev->cmd_q, skb); | 5460 | skb_queue_head(&hdev->cmd_q, skb); |
5296 | queue_work(hdev->workqueue, &hdev->cmd_work); | 5461 | queue_work(hdev->workqueue, &hdev->cmd_work); |
@@ -5307,26 +5472,135 @@ void hci_req_add_le_scan_disable(struct hci_request *req) | |||
5307 | hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp); | 5472 | hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp); |
5308 | } | 5473 | } |
5309 | 5474 | ||
5475 | static void add_to_white_list(struct hci_request *req, | ||
5476 | struct hci_conn_params *params) | ||
5477 | { | ||
5478 | struct hci_cp_le_add_to_white_list cp; | ||
5479 | |||
5480 | cp.bdaddr_type = params->addr_type; | ||
5481 | bacpy(&cp.bdaddr, ¶ms->addr); | ||
5482 | |||
5483 | hci_req_add(req, HCI_OP_LE_ADD_TO_WHITE_LIST, sizeof(cp), &cp); | ||
5484 | } | ||
5485 | |||
5486 | static u8 update_white_list(struct hci_request *req) | ||
5487 | { | ||
5488 | struct hci_dev *hdev = req->hdev; | ||
5489 | struct hci_conn_params *params; | ||
5490 | struct bdaddr_list *b; | ||
5491 | uint8_t white_list_entries = 0; | ||
5492 | |||
5493 | /* Go through the current white list programmed into the | ||
5494 | * controller one by one and check if that address is still | ||
5495 | * in the list of pending connections or list of devices to | ||
5496 | * report. If not present in either list, then queue the | ||
5497 | * command to remove it from the controller. | ||
5498 | */ | ||
5499 | list_for_each_entry(b, &hdev->le_white_list, list) { | ||
5500 | struct hci_cp_le_del_from_white_list cp; | ||
5501 | |||
5502 | if (hci_pend_le_action_lookup(&hdev->pend_le_conns, | ||
5503 | &b->bdaddr, b->bdaddr_type) || | ||
5504 | hci_pend_le_action_lookup(&hdev->pend_le_reports, | ||
5505 | &b->bdaddr, b->bdaddr_type)) { | ||
5506 | white_list_entries++; | ||
5507 | continue; | ||
5508 | } | ||
5509 | |||
5510 | cp.bdaddr_type = b->bdaddr_type; | ||
5511 | bacpy(&cp.bdaddr, &b->bdaddr); | ||
5512 | |||
5513 | hci_req_add(req, HCI_OP_LE_DEL_FROM_WHITE_LIST, | ||
5514 | sizeof(cp), &cp); | ||
5515 | } | ||
5516 | |||
5517 | /* Since all no longer valid white list entries have been | ||
5518 | * removed, walk through the list of pending connections | ||
5519 | * and ensure that any new device gets programmed into | ||
5520 | * the controller. | ||
5521 | * | ||
5522 | * If the list of the devices is larger than the list of | ||
5523 | * available white list entries in the controller, then | ||
5524 | * just abort and return filer policy value to not use the | ||
5525 | * white list. | ||
5526 | */ | ||
5527 | list_for_each_entry(params, &hdev->pend_le_conns, action) { | ||
5528 | if (hci_bdaddr_list_lookup(&hdev->le_white_list, | ||
5529 | ¶ms->addr, params->addr_type)) | ||
5530 | continue; | ||
5531 | |||
5532 | if (white_list_entries >= hdev->le_white_list_size) { | ||
5533 | /* Select filter policy to accept all advertising */ | ||
5534 | return 0x00; | ||
5535 | } | ||
5536 | |||
5537 | if (hci_find_irk_by_addr(hdev, ¶ms->addr, | ||
5538 | params->addr_type)) { | ||
5539 | /* White list can not be used with RPAs */ | ||
5540 | return 0x00; | ||
5541 | } | ||
5542 | |||
5543 | white_list_entries++; | ||
5544 | add_to_white_list(req, params); | ||
5545 | } | ||
5546 | |||
5547 | /* After adding all new pending connections, walk through | ||
5548 | * the list of pending reports and also add these to the | ||
5549 | * white list if there is still space. | ||
5550 | */ | ||
5551 | list_for_each_entry(params, &hdev->pend_le_reports, action) { | ||
5552 | if (hci_bdaddr_list_lookup(&hdev->le_white_list, | ||
5553 | ¶ms->addr, params->addr_type)) | ||
5554 | continue; | ||
5555 | |||
5556 | if (white_list_entries >= hdev->le_white_list_size) { | ||
5557 | /* Select filter policy to accept all advertising */ | ||
5558 | return 0x00; | ||
5559 | } | ||
5560 | |||
5561 | if (hci_find_irk_by_addr(hdev, ¶ms->addr, | ||
5562 | params->addr_type)) { | ||
5563 | /* White list can not be used with RPAs */ | ||
5564 | return 0x00; | ||
5565 | } | ||
5566 | |||
5567 | white_list_entries++; | ||
5568 | add_to_white_list(req, params); | ||
5569 | } | ||
5570 | |||
5571 | /* Select filter policy to use white list */ | ||
5572 | return 0x01; | ||
5573 | } | ||
5574 | |||
5310 | void hci_req_add_le_passive_scan(struct hci_request *req) | 5575 | void hci_req_add_le_passive_scan(struct hci_request *req) |
5311 | { | 5576 | { |
5312 | struct hci_cp_le_set_scan_param param_cp; | 5577 | struct hci_cp_le_set_scan_param param_cp; |
5313 | struct hci_cp_le_set_scan_enable enable_cp; | 5578 | struct hci_cp_le_set_scan_enable enable_cp; |
5314 | struct hci_dev *hdev = req->hdev; | 5579 | struct hci_dev *hdev = req->hdev; |
5315 | u8 own_addr_type; | 5580 | u8 own_addr_type; |
5581 | u8 filter_policy; | ||
5316 | 5582 | ||
5317 | /* Set require_privacy to true to avoid identification from | 5583 | /* Set require_privacy to false since no SCAN_REQ are send |
5318 | * unknown peer devices. Since this is passive scanning, no | 5584 | * during passive scanning. Not using an unresolvable address |
5319 | * SCAN_REQ using the local identity should be sent. Mandating | 5585 | * here is important so that peer devices using direct |
5320 | * privacy is just an extra precaution. | 5586 | * advertising with our address will be correctly reported |
5587 | * by the controller. | ||
5321 | */ | 5588 | */ |
5322 | if (hci_update_random_address(req, true, &own_addr_type)) | 5589 | if (hci_update_random_address(req, false, &own_addr_type)) |
5323 | return; | 5590 | return; |
5324 | 5591 | ||
5592 | /* Adding or removing entries from the white list must | ||
5593 | * happen before enabling scanning. The controller does | ||
5594 | * not allow white list modification while scanning. | ||
5595 | */ | ||
5596 | filter_policy = update_white_list(req); | ||
5597 | |||
5325 | memset(¶m_cp, 0, sizeof(param_cp)); | 5598 | memset(¶m_cp, 0, sizeof(param_cp)); |
5326 | param_cp.type = LE_SCAN_PASSIVE; | 5599 | param_cp.type = LE_SCAN_PASSIVE; |
5327 | param_cp.interval = cpu_to_le16(hdev->le_scan_interval); | 5600 | param_cp.interval = cpu_to_le16(hdev->le_scan_interval); |
5328 | param_cp.window = cpu_to_le16(hdev->le_scan_window); | 5601 | param_cp.window = cpu_to_le16(hdev->le_scan_window); |
5329 | param_cp.own_address_type = own_addr_type; | 5602 | param_cp.own_address_type = own_addr_type; |
5603 | param_cp.filter_policy = filter_policy; | ||
5330 | hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp), | 5604 | hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp), |
5331 | ¶m_cp); | 5605 | ¶m_cp); |
5332 | 5606 | ||
@@ -5356,11 +5630,29 @@ void hci_update_background_scan(struct hci_dev *hdev) | |||
5356 | struct hci_conn *conn; | 5630 | struct hci_conn *conn; |
5357 | int err; | 5631 | int err; |
5358 | 5632 | ||
5633 | if (!test_bit(HCI_UP, &hdev->flags) || | ||
5634 | test_bit(HCI_INIT, &hdev->flags) || | ||
5635 | test_bit(HCI_SETUP, &hdev->dev_flags) || | ||
5636 | test_bit(HCI_CONFIG, &hdev->dev_flags) || | ||
5637 | test_bit(HCI_AUTO_OFF, &hdev->dev_flags) || | ||
5638 | test_bit(HCI_UNREGISTER, &hdev->dev_flags)) | ||
5639 | return; | ||
5640 | |||
5641 | /* No point in doing scanning if LE support hasn't been enabled */ | ||
5642 | if (!test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) | ||
5643 | return; | ||
5644 | |||
5645 | /* If discovery is active don't interfere with it */ | ||
5646 | if (hdev->discovery.state != DISCOVERY_STOPPED) | ||
5647 | return; | ||
5648 | |||
5359 | hci_req_init(&req, hdev); | 5649 | hci_req_init(&req, hdev); |
5360 | 5650 | ||
5361 | if (list_empty(&hdev->pend_le_conns)) { | 5651 | if (list_empty(&hdev->pend_le_conns) && |
5362 | /* If there is no pending LE connections, we should stop | 5652 | list_empty(&hdev->pend_le_reports)) { |
5363 | * the background scanning. | 5653 | /* If there is no pending LE connections or devices |
5654 | * to be scanned for, we should stop the background | ||
5655 | * scanning. | ||
5364 | */ | 5656 | */ |
5365 | 5657 | ||
5366 | /* If controller is not scanning we are done. */ | 5658 | /* If controller is not scanning we are done. */ |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 640c54ec1bd2..a6000823f0ff 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -32,6 +32,7 @@ | |||
32 | 32 | ||
33 | #include "a2mp.h" | 33 | #include "a2mp.h" |
34 | #include "amp.h" | 34 | #include "amp.h" |
35 | #include "smp.h" | ||
35 | 36 | ||
36 | /* Handle HCI Event packets */ | 37 | /* Handle HCI Event packets */ |
37 | 38 | ||
@@ -100,12 +101,8 @@ static void hci_cc_role_discovery(struct hci_dev *hdev, struct sk_buff *skb) | |||
100 | hci_dev_lock(hdev); | 101 | hci_dev_lock(hdev); |
101 | 102 | ||
102 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); | 103 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); |
103 | if (conn) { | 104 | if (conn) |
104 | if (rp->role) | 105 | conn->role = rp->role; |
105 | conn->link_mode &= ~HCI_LM_MASTER; | ||
106 | else | ||
107 | conn->link_mode |= HCI_LM_MASTER; | ||
108 | } | ||
109 | 106 | ||
110 | hci_dev_unlock(hdev); | 107 | hci_dev_unlock(hdev); |
111 | } | 108 | } |
@@ -174,12 +171,14 @@ static void hci_cc_write_def_link_policy(struct hci_dev *hdev, | |||
174 | 171 | ||
175 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | 172 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
176 | 173 | ||
174 | if (status) | ||
175 | return; | ||
176 | |||
177 | sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY); | 177 | sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_DEF_LINK_POLICY); |
178 | if (!sent) | 178 | if (!sent) |
179 | return; | 179 | return; |
180 | 180 | ||
181 | if (!status) | 181 | hdev->link_policy = get_unaligned_le16(sent); |
182 | hdev->link_policy = get_unaligned_le16(sent); | ||
183 | } | 182 | } |
184 | 183 | ||
185 | static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) | 184 | static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -269,28 +268,30 @@ static void hci_cc_write_auth_enable(struct hci_dev *hdev, struct sk_buff *skb) | |||
269 | static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) | 268 | static void hci_cc_write_encrypt_mode(struct hci_dev *hdev, struct sk_buff *skb) |
270 | { | 269 | { |
271 | __u8 status = *((__u8 *) skb->data); | 270 | __u8 status = *((__u8 *) skb->data); |
271 | __u8 param; | ||
272 | void *sent; | 272 | void *sent; |
273 | 273 | ||
274 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | 274 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
275 | 275 | ||
276 | if (status) | ||
277 | return; | ||
278 | |||
276 | sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); | 279 | sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_ENCRYPT_MODE); |
277 | if (!sent) | 280 | if (!sent) |
278 | return; | 281 | return; |
279 | 282 | ||
280 | if (!status) { | 283 | param = *((__u8 *) sent); |
281 | __u8 param = *((__u8 *) sent); | ||
282 | 284 | ||
283 | if (param) | 285 | if (param) |
284 | set_bit(HCI_ENCRYPT, &hdev->flags); | 286 | set_bit(HCI_ENCRYPT, &hdev->flags); |
285 | else | 287 | else |
286 | clear_bit(HCI_ENCRYPT, &hdev->flags); | 288 | clear_bit(HCI_ENCRYPT, &hdev->flags); |
287 | } | ||
288 | } | 289 | } |
289 | 290 | ||
290 | static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) | 291 | static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) |
291 | { | 292 | { |
292 | __u8 param, status = *((__u8 *) skb->data); | 293 | __u8 status = *((__u8 *) skb->data); |
293 | int old_pscan, old_iscan; | 294 | __u8 param; |
294 | void *sent; | 295 | void *sent; |
295 | 296 | ||
296 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | 297 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
@@ -304,32 +305,19 @@ static void hci_cc_write_scan_enable(struct hci_dev *hdev, struct sk_buff *skb) | |||
304 | hci_dev_lock(hdev); | 305 | hci_dev_lock(hdev); |
305 | 306 | ||
306 | if (status) { | 307 | if (status) { |
307 | mgmt_write_scan_failed(hdev, param, status); | ||
308 | hdev->discov_timeout = 0; | 308 | hdev->discov_timeout = 0; |
309 | goto done; | 309 | goto done; |
310 | } | 310 | } |
311 | 311 | ||
312 | /* We need to ensure that we set this back on if someone changed | 312 | if (param & SCAN_INQUIRY) |
313 | * the scan mode through a raw HCI socket. | ||
314 | */ | ||
315 | set_bit(HCI_BREDR_ENABLED, &hdev->dev_flags); | ||
316 | |||
317 | old_pscan = test_and_clear_bit(HCI_PSCAN, &hdev->flags); | ||
318 | old_iscan = test_and_clear_bit(HCI_ISCAN, &hdev->flags); | ||
319 | |||
320 | if (param & SCAN_INQUIRY) { | ||
321 | set_bit(HCI_ISCAN, &hdev->flags); | 313 | set_bit(HCI_ISCAN, &hdev->flags); |
322 | if (!old_iscan) | 314 | else |
323 | mgmt_discoverable(hdev, 1); | 315 | clear_bit(HCI_ISCAN, &hdev->flags); |
324 | } else if (old_iscan) | ||
325 | mgmt_discoverable(hdev, 0); | ||
326 | 316 | ||
327 | if (param & SCAN_PAGE) { | 317 | if (param & SCAN_PAGE) |
328 | set_bit(HCI_PSCAN, &hdev->flags); | 318 | set_bit(HCI_PSCAN, &hdev->flags); |
329 | if (!old_pscan) | 319 | else |
330 | mgmt_connectable(hdev, 1); | 320 | clear_bit(HCI_PSCAN, &hdev->flags); |
331 | } else if (old_pscan) | ||
332 | mgmt_connectable(hdev, 0); | ||
333 | 321 | ||
334 | done: | 322 | done: |
335 | hci_dev_unlock(hdev); | 323 | hci_dev_unlock(hdev); |
@@ -601,8 +589,10 @@ static void hci_cc_read_flow_control_mode(struct hci_dev *hdev, | |||
601 | 589 | ||
602 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | 590 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); |
603 | 591 | ||
604 | if (!rp->status) | 592 | if (rp->status) |
605 | hdev->flow_ctl_mode = rp->mode; | 593 | return; |
594 | |||
595 | hdev->flow_ctl_mode = rp->mode; | ||
606 | } | 596 | } |
607 | 597 | ||
608 | static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) | 598 | static void hci_cc_read_buffer_size(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -637,8 +627,14 @@ static void hci_cc_read_bd_addr(struct hci_dev *hdev, struct sk_buff *skb) | |||
637 | 627 | ||
638 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | 628 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); |
639 | 629 | ||
640 | if (!rp->status) | 630 | if (rp->status) |
631 | return; | ||
632 | |||
633 | if (test_bit(HCI_INIT, &hdev->flags)) | ||
641 | bacpy(&hdev->bdaddr, &rp->bdaddr); | 634 | bacpy(&hdev->bdaddr, &rp->bdaddr); |
635 | |||
636 | if (test_bit(HCI_SETUP, &hdev->dev_flags)) | ||
637 | bacpy(&hdev->setup_addr, &rp->bdaddr); | ||
642 | } | 638 | } |
643 | 639 | ||
644 | static void hci_cc_read_page_scan_activity(struct hci_dev *hdev, | 640 | static void hci_cc_read_page_scan_activity(struct hci_dev *hdev, |
@@ -648,7 +644,10 @@ static void hci_cc_read_page_scan_activity(struct hci_dev *hdev, | |||
648 | 644 | ||
649 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | 645 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); |
650 | 646 | ||
651 | if (test_bit(HCI_INIT, &hdev->flags) && !rp->status) { | 647 | if (rp->status) |
648 | return; | ||
649 | |||
650 | if (test_bit(HCI_INIT, &hdev->flags)) { | ||
652 | hdev->page_scan_interval = __le16_to_cpu(rp->interval); | 651 | hdev->page_scan_interval = __le16_to_cpu(rp->interval); |
653 | hdev->page_scan_window = __le16_to_cpu(rp->window); | 652 | hdev->page_scan_window = __le16_to_cpu(rp->window); |
654 | } | 653 | } |
@@ -680,7 +679,10 @@ static void hci_cc_read_page_scan_type(struct hci_dev *hdev, | |||
680 | 679 | ||
681 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | 680 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); |
682 | 681 | ||
683 | if (test_bit(HCI_INIT, &hdev->flags) && !rp->status) | 682 | if (rp->status) |
683 | return; | ||
684 | |||
685 | if (test_bit(HCI_INIT, &hdev->flags)) | ||
684 | hdev->page_scan_type = rp->type; | 686 | hdev->page_scan_type = rp->type; |
685 | } | 687 | } |
686 | 688 | ||
@@ -720,6 +722,41 @@ static void hci_cc_read_data_block_size(struct hci_dev *hdev, | |||
720 | hdev->block_cnt, hdev->block_len); | 722 | hdev->block_cnt, hdev->block_len); |
721 | } | 723 | } |
722 | 724 | ||
725 | static void hci_cc_read_clock(struct hci_dev *hdev, struct sk_buff *skb) | ||
726 | { | ||
727 | struct hci_rp_read_clock *rp = (void *) skb->data; | ||
728 | struct hci_cp_read_clock *cp; | ||
729 | struct hci_conn *conn; | ||
730 | |||
731 | BT_DBG("%s", hdev->name); | ||
732 | |||
733 | if (skb->len < sizeof(*rp)) | ||
734 | return; | ||
735 | |||
736 | if (rp->status) | ||
737 | return; | ||
738 | |||
739 | hci_dev_lock(hdev); | ||
740 | |||
741 | cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK); | ||
742 | if (!cp) | ||
743 | goto unlock; | ||
744 | |||
745 | if (cp->which == 0x00) { | ||
746 | hdev->clock = le32_to_cpu(rp->clock); | ||
747 | goto unlock; | ||
748 | } | ||
749 | |||
750 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(rp->handle)); | ||
751 | if (conn) { | ||
752 | conn->clock = le32_to_cpu(rp->clock); | ||
753 | conn->clock_accuracy = le16_to_cpu(rp->accuracy); | ||
754 | } | ||
755 | |||
756 | unlock: | ||
757 | hci_dev_unlock(hdev); | ||
758 | } | ||
759 | |||
723 | static void hci_cc_read_local_amp_info(struct hci_dev *hdev, | 760 | static void hci_cc_read_local_amp_info(struct hci_dev *hdev, |
724 | struct sk_buff *skb) | 761 | struct sk_buff *skb) |
725 | { | 762 | { |
@@ -789,8 +826,10 @@ static void hci_cc_read_inq_rsp_tx_power(struct hci_dev *hdev, | |||
789 | 826 | ||
790 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | 827 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); |
791 | 828 | ||
792 | if (!rp->status) | 829 | if (rp->status) |
793 | hdev->inq_tx_power = rp->tx_power; | 830 | return; |
831 | |||
832 | hdev->inq_tx_power = rp->tx_power; | ||
794 | } | 833 | } |
795 | 834 | ||
796 | static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) | 835 | static void hci_cc_pin_code_reply(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -861,8 +900,10 @@ static void hci_cc_le_read_local_features(struct hci_dev *hdev, | |||
861 | 900 | ||
862 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | 901 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); |
863 | 902 | ||
864 | if (!rp->status) | 903 | if (rp->status) |
865 | memcpy(hdev->le_features, rp->features, 8); | 904 | return; |
905 | |||
906 | memcpy(hdev->le_features, rp->features, 8); | ||
866 | } | 907 | } |
867 | 908 | ||
868 | static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, | 909 | static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, |
@@ -872,8 +913,10 @@ static void hci_cc_le_read_adv_tx_power(struct hci_dev *hdev, | |||
872 | 913 | ||
873 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | 914 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); |
874 | 915 | ||
875 | if (!rp->status) | 916 | if (rp->status) |
876 | hdev->adv_tx_power = rp->tx_power; | 917 | return; |
918 | |||
919 | hdev->adv_tx_power = rp->tx_power; | ||
877 | } | 920 | } |
878 | 921 | ||
879 | static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) | 922 | static void hci_cc_user_confirm_reply(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -973,14 +1016,16 @@ static void hci_cc_le_set_random_addr(struct hci_dev *hdev, struct sk_buff *skb) | |||
973 | 1016 | ||
974 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | 1017 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
975 | 1018 | ||
1019 | if (status) | ||
1020 | return; | ||
1021 | |||
976 | sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_RANDOM_ADDR); | 1022 | sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_RANDOM_ADDR); |
977 | if (!sent) | 1023 | if (!sent) |
978 | return; | 1024 | return; |
979 | 1025 | ||
980 | hci_dev_lock(hdev); | 1026 | hci_dev_lock(hdev); |
981 | 1027 | ||
982 | if (!status) | 1028 | bacpy(&hdev->random_addr, sent); |
983 | bacpy(&hdev->random_addr, sent); | ||
984 | 1029 | ||
985 | hci_dev_unlock(hdev); | 1030 | hci_dev_unlock(hdev); |
986 | } | 1031 | } |
@@ -991,11 +1036,11 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb) | |||
991 | 1036 | ||
992 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | 1037 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
993 | 1038 | ||
994 | sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE); | 1039 | if (status) |
995 | if (!sent) | ||
996 | return; | 1040 | return; |
997 | 1041 | ||
998 | if (status) | 1042 | sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_ENABLE); |
1043 | if (!sent) | ||
999 | return; | 1044 | return; |
1000 | 1045 | ||
1001 | hci_dev_lock(hdev); | 1046 | hci_dev_lock(hdev); |
@@ -1006,15 +1051,17 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb) | |||
1006 | if (*sent) { | 1051 | if (*sent) { |
1007 | struct hci_conn *conn; | 1052 | struct hci_conn *conn; |
1008 | 1053 | ||
1054 | set_bit(HCI_LE_ADV, &hdev->dev_flags); | ||
1055 | |||
1009 | conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); | 1056 | conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); |
1010 | if (conn) | 1057 | if (conn) |
1011 | queue_delayed_work(hdev->workqueue, | 1058 | queue_delayed_work(hdev->workqueue, |
1012 | &conn->le_conn_timeout, | 1059 | &conn->le_conn_timeout, |
1013 | HCI_LE_CONN_TIMEOUT); | 1060 | conn->conn_timeout); |
1061 | } else { | ||
1062 | clear_bit(HCI_LE_ADV, &hdev->dev_flags); | ||
1014 | } | 1063 | } |
1015 | 1064 | ||
1016 | mgmt_advertising(hdev, *sent); | ||
1017 | |||
1018 | hci_dev_unlock(hdev); | 1065 | hci_dev_unlock(hdev); |
1019 | } | 1066 | } |
1020 | 1067 | ||
@@ -1025,14 +1072,16 @@ static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) | |||
1025 | 1072 | ||
1026 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | 1073 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
1027 | 1074 | ||
1075 | if (status) | ||
1076 | return; | ||
1077 | |||
1028 | cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_PARAM); | 1078 | cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_PARAM); |
1029 | if (!cp) | 1079 | if (!cp) |
1030 | return; | 1080 | return; |
1031 | 1081 | ||
1032 | hci_dev_lock(hdev); | 1082 | hci_dev_lock(hdev); |
1033 | 1083 | ||
1034 | if (!status) | 1084 | hdev->le_scan_type = cp->type; |
1035 | hdev->le_scan_type = cp->type; | ||
1036 | 1085 | ||
1037 | hci_dev_unlock(hdev); | 1086 | hci_dev_unlock(hdev); |
1038 | } | 1087 | } |
@@ -1053,13 +1102,15 @@ static void clear_pending_adv_report(struct hci_dev *hdev) | |||
1053 | } | 1102 | } |
1054 | 1103 | ||
1055 | static void store_pending_adv_report(struct hci_dev *hdev, bdaddr_t *bdaddr, | 1104 | static void store_pending_adv_report(struct hci_dev *hdev, bdaddr_t *bdaddr, |
1056 | u8 bdaddr_type, s8 rssi, u8 *data, u8 len) | 1105 | u8 bdaddr_type, s8 rssi, u32 flags, |
1106 | u8 *data, u8 len) | ||
1057 | { | 1107 | { |
1058 | struct discovery_state *d = &hdev->discovery; | 1108 | struct discovery_state *d = &hdev->discovery; |
1059 | 1109 | ||
1060 | bacpy(&d->last_adv_addr, bdaddr); | 1110 | bacpy(&d->last_adv_addr, bdaddr); |
1061 | d->last_adv_addr_type = bdaddr_type; | 1111 | d->last_adv_addr_type = bdaddr_type; |
1062 | d->last_adv_rssi = rssi; | 1112 | d->last_adv_rssi = rssi; |
1113 | d->last_adv_flags = flags; | ||
1063 | memcpy(d->last_adv_data, data, len); | 1114 | memcpy(d->last_adv_data, data, len); |
1064 | d->last_adv_data_len = len; | 1115 | d->last_adv_data_len = len; |
1065 | } | 1116 | } |
@@ -1072,11 +1123,11 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, | |||
1072 | 1123 | ||
1073 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | 1124 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
1074 | 1125 | ||
1075 | cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE); | 1126 | if (status) |
1076 | if (!cp) | ||
1077 | return; | 1127 | return; |
1078 | 1128 | ||
1079 | if (status) | 1129 | cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_ENABLE); |
1130 | if (!cp) | ||
1080 | return; | 1131 | return; |
1081 | 1132 | ||
1082 | switch (cp->enable) { | 1133 | switch (cp->enable) { |
@@ -1096,7 +1147,7 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, | |||
1096 | 1147 | ||
1097 | mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK, | 1148 | mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK, |
1098 | d->last_adv_addr_type, NULL, | 1149 | d->last_adv_addr_type, NULL, |
1099 | d->last_adv_rssi, 0, 1, | 1150 | d->last_adv_rssi, d->last_adv_flags, |
1100 | d->last_adv_data, | 1151 | d->last_adv_data, |
1101 | d->last_adv_data_len, NULL, 0); | 1152 | d->last_adv_data_len, NULL, 0); |
1102 | } | 1153 | } |
@@ -1107,13 +1158,21 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, | |||
1107 | cancel_delayed_work(&hdev->le_scan_disable); | 1158 | cancel_delayed_work(&hdev->le_scan_disable); |
1108 | 1159 | ||
1109 | clear_bit(HCI_LE_SCAN, &hdev->dev_flags); | 1160 | clear_bit(HCI_LE_SCAN, &hdev->dev_flags); |
1161 | |||
1110 | /* The HCI_LE_SCAN_INTERRUPTED flag indicates that we | 1162 | /* The HCI_LE_SCAN_INTERRUPTED flag indicates that we |
1111 | * interrupted scanning due to a connect request. Mark | 1163 | * interrupted scanning due to a connect request. Mark |
1112 | * therefore discovery as stopped. | 1164 | * therefore discovery as stopped. If this was not |
1165 | * because of a connect request advertising might have | ||
1166 | * been disabled because of active scanning, so | ||
1167 | * re-enable it again if necessary. | ||
1113 | */ | 1168 | */ |
1114 | if (test_and_clear_bit(HCI_LE_SCAN_INTERRUPTED, | 1169 | if (test_and_clear_bit(HCI_LE_SCAN_INTERRUPTED, |
1115 | &hdev->dev_flags)) | 1170 | &hdev->dev_flags)) |
1116 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); | 1171 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); |
1172 | else if (!test_bit(HCI_LE_ADV, &hdev->dev_flags) && | ||
1173 | hdev->discovery.state == DISCOVERY_FINDING) | ||
1174 | mgmt_reenable_advertising(hdev); | ||
1175 | |||
1117 | break; | 1176 | break; |
1118 | 1177 | ||
1119 | default: | 1178 | default: |
@@ -1129,8 +1188,10 @@ static void hci_cc_le_read_white_list_size(struct hci_dev *hdev, | |||
1129 | 1188 | ||
1130 | BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size); | 1189 | BT_DBG("%s status 0x%2.2x size %u", hdev->name, rp->status, rp->size); |
1131 | 1190 | ||
1132 | if (!rp->status) | 1191 | if (rp->status) |
1133 | hdev->le_white_list_size = rp->size; | 1192 | return; |
1193 | |||
1194 | hdev->le_white_list_size = rp->size; | ||
1134 | } | 1195 | } |
1135 | 1196 | ||
1136 | static void hci_cc_le_clear_white_list(struct hci_dev *hdev, | 1197 | static void hci_cc_le_clear_white_list(struct hci_dev *hdev, |
@@ -1140,8 +1201,10 @@ static void hci_cc_le_clear_white_list(struct hci_dev *hdev, | |||
1140 | 1201 | ||
1141 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | 1202 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
1142 | 1203 | ||
1143 | if (!status) | 1204 | if (status) |
1144 | hci_white_list_clear(hdev); | 1205 | return; |
1206 | |||
1207 | hci_bdaddr_list_clear(&hdev->le_white_list); | ||
1145 | } | 1208 | } |
1146 | 1209 | ||
1147 | static void hci_cc_le_add_to_white_list(struct hci_dev *hdev, | 1210 | static void hci_cc_le_add_to_white_list(struct hci_dev *hdev, |
@@ -1152,12 +1215,15 @@ static void hci_cc_le_add_to_white_list(struct hci_dev *hdev, | |||
1152 | 1215 | ||
1153 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | 1216 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
1154 | 1217 | ||
1218 | if (status) | ||
1219 | return; | ||
1220 | |||
1155 | sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_WHITE_LIST); | 1221 | sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_WHITE_LIST); |
1156 | if (!sent) | 1222 | if (!sent) |
1157 | return; | 1223 | return; |
1158 | 1224 | ||
1159 | if (!status) | 1225 | hci_bdaddr_list_add(&hdev->le_white_list, &sent->bdaddr, |
1160 | hci_white_list_add(hdev, &sent->bdaddr, sent->bdaddr_type); | 1226 | sent->bdaddr_type); |
1161 | } | 1227 | } |
1162 | 1228 | ||
1163 | static void hci_cc_le_del_from_white_list(struct hci_dev *hdev, | 1229 | static void hci_cc_le_del_from_white_list(struct hci_dev *hdev, |
@@ -1168,12 +1234,15 @@ static void hci_cc_le_del_from_white_list(struct hci_dev *hdev, | |||
1168 | 1234 | ||
1169 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | 1235 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
1170 | 1236 | ||
1237 | if (status) | ||
1238 | return; | ||
1239 | |||
1171 | sent = hci_sent_cmd_data(hdev, HCI_OP_LE_DEL_FROM_WHITE_LIST); | 1240 | sent = hci_sent_cmd_data(hdev, HCI_OP_LE_DEL_FROM_WHITE_LIST); |
1172 | if (!sent) | 1241 | if (!sent) |
1173 | return; | 1242 | return; |
1174 | 1243 | ||
1175 | if (!status) | 1244 | hci_bdaddr_list_del(&hdev->le_white_list, &sent->bdaddr, |
1176 | hci_white_list_del(hdev, &sent->bdaddr, sent->bdaddr_type); | 1245 | sent->bdaddr_type); |
1177 | } | 1246 | } |
1178 | 1247 | ||
1179 | static void hci_cc_le_read_supported_states(struct hci_dev *hdev, | 1248 | static void hci_cc_le_read_supported_states(struct hci_dev *hdev, |
@@ -1183,8 +1252,10 @@ static void hci_cc_le_read_supported_states(struct hci_dev *hdev, | |||
1183 | 1252 | ||
1184 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | 1253 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); |
1185 | 1254 | ||
1186 | if (!rp->status) | 1255 | if (rp->status) |
1187 | memcpy(hdev->le_states, rp->le_states, 8); | 1256 | return; |
1257 | |||
1258 | memcpy(hdev->le_states, rp->le_states, 8); | ||
1188 | } | 1259 | } |
1189 | 1260 | ||
1190 | static void hci_cc_write_le_host_supported(struct hci_dev *hdev, | 1261 | static void hci_cc_write_le_host_supported(struct hci_dev *hdev, |
@@ -1195,25 +1266,26 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev, | |||
1195 | 1266 | ||
1196 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | 1267 | BT_DBG("%s status 0x%2.2x", hdev->name, status); |
1197 | 1268 | ||
1269 | if (status) | ||
1270 | return; | ||
1271 | |||
1198 | sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED); | 1272 | sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED); |
1199 | if (!sent) | 1273 | if (!sent) |
1200 | return; | 1274 | return; |
1201 | 1275 | ||
1202 | if (!status) { | 1276 | if (sent->le) { |
1203 | if (sent->le) { | 1277 | hdev->features[1][0] |= LMP_HOST_LE; |
1204 | hdev->features[1][0] |= LMP_HOST_LE; | 1278 | set_bit(HCI_LE_ENABLED, &hdev->dev_flags); |
1205 | set_bit(HCI_LE_ENABLED, &hdev->dev_flags); | 1279 | } else { |
1206 | } else { | 1280 | hdev->features[1][0] &= ~LMP_HOST_LE; |
1207 | hdev->features[1][0] &= ~LMP_HOST_LE; | 1281 | clear_bit(HCI_LE_ENABLED, &hdev->dev_flags); |
1208 | clear_bit(HCI_LE_ENABLED, &hdev->dev_flags); | 1282 | clear_bit(HCI_ADVERTISING, &hdev->dev_flags); |
1209 | clear_bit(HCI_ADVERTISING, &hdev->dev_flags); | ||
1210 | } | ||
1211 | |||
1212 | if (sent->simul) | ||
1213 | hdev->features[1][0] |= LMP_HOST_LE_BREDR; | ||
1214 | else | ||
1215 | hdev->features[1][0] &= ~LMP_HOST_LE_BREDR; | ||
1216 | } | 1283 | } |
1284 | |||
1285 | if (sent->simul) | ||
1286 | hdev->features[1][0] |= LMP_HOST_LE_BREDR; | ||
1287 | else | ||
1288 | hdev->features[1][0] &= ~LMP_HOST_LE_BREDR; | ||
1217 | } | 1289 | } |
1218 | 1290 | ||
1219 | static void hci_cc_set_adv_param(struct hci_dev *hdev, struct sk_buff *skb) | 1291 | static void hci_cc_set_adv_param(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -1342,11 +1414,9 @@ static void hci_cs_create_conn(struct hci_dev *hdev, __u8 status) | |||
1342 | } | 1414 | } |
1343 | } else { | 1415 | } else { |
1344 | if (!conn) { | 1416 | if (!conn) { |
1345 | conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr); | 1417 | conn = hci_conn_add(hdev, ACL_LINK, &cp->bdaddr, |
1346 | if (conn) { | 1418 | HCI_ROLE_MASTER); |
1347 | conn->out = true; | 1419 | if (!conn) |
1348 | conn->link_mode |= HCI_LM_MASTER; | ||
1349 | } else | ||
1350 | BT_ERR("No memory for new connection"); | 1420 | BT_ERR("No memory for new connection"); |
1351 | } | 1421 | } |
1352 | } | 1422 | } |
@@ -1575,6 +1645,8 @@ static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) | |||
1575 | if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { | 1645 | if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { |
1576 | struct hci_cp_auth_requested auth_cp; | 1646 | struct hci_cp_auth_requested auth_cp; |
1577 | 1647 | ||
1648 | set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags); | ||
1649 | |||
1578 | auth_cp.handle = __cpu_to_le16(conn->handle); | 1650 | auth_cp.handle = __cpu_to_le16(conn->handle); |
1579 | hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, | 1651 | hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, |
1580 | sizeof(auth_cp), &auth_cp); | 1652 | sizeof(auth_cp), &auth_cp); |
@@ -1835,7 +1907,7 @@ static void hci_cs_le_create_conn(struct hci_dev *hdev, u8 status) | |||
1835 | if (cp->filter_policy == HCI_LE_USE_PEER_ADDR) | 1907 | if (cp->filter_policy == HCI_LE_USE_PEER_ADDR) |
1836 | queue_delayed_work(conn->hdev->workqueue, | 1908 | queue_delayed_work(conn->hdev->workqueue, |
1837 | &conn->le_conn_timeout, | 1909 | &conn->le_conn_timeout, |
1838 | HCI_LE_CONN_TIMEOUT); | 1910 | conn->conn_timeout); |
1839 | 1911 | ||
1840 | unlock: | 1912 | unlock: |
1841 | hci_dev_unlock(hdev); | 1913 | hci_dev_unlock(hdev); |
@@ -1929,7 +2001,7 @@ static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
1929 | hci_dev_lock(hdev); | 2001 | hci_dev_lock(hdev); |
1930 | 2002 | ||
1931 | for (; num_rsp; num_rsp--, info++) { | 2003 | for (; num_rsp; num_rsp--, info++) { |
1932 | bool name_known, ssp; | 2004 | u32 flags; |
1933 | 2005 | ||
1934 | bacpy(&data.bdaddr, &info->bdaddr); | 2006 | bacpy(&data.bdaddr, &info->bdaddr); |
1935 | data.pscan_rep_mode = info->pscan_rep_mode; | 2007 | data.pscan_rep_mode = info->pscan_rep_mode; |
@@ -1940,10 +2012,10 @@ static void hci_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
1940 | data.rssi = 0x00; | 2012 | data.rssi = 0x00; |
1941 | data.ssp_mode = 0x00; | 2013 | data.ssp_mode = 0x00; |
1942 | 2014 | ||
1943 | name_known = hci_inquiry_cache_update(hdev, &data, false, &ssp); | 2015 | flags = hci_inquiry_cache_update(hdev, &data, false); |
2016 | |||
1944 | mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, | 2017 | mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, |
1945 | info->dev_class, 0, !name_known, ssp, NULL, | 2018 | info->dev_class, 0, flags, NULL, 0, NULL, 0); |
1946 | 0, NULL, 0); | ||
1947 | } | 2019 | } |
1948 | 2020 | ||
1949 | hci_dev_unlock(hdev); | 2021 | hci_dev_unlock(hdev); |
@@ -1988,10 +2060,10 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
1988 | hci_conn_add_sysfs(conn); | 2060 | hci_conn_add_sysfs(conn); |
1989 | 2061 | ||
1990 | if (test_bit(HCI_AUTH, &hdev->flags)) | 2062 | if (test_bit(HCI_AUTH, &hdev->flags)) |
1991 | conn->link_mode |= HCI_LM_AUTH; | 2063 | set_bit(HCI_CONN_AUTH, &conn->flags); |
1992 | 2064 | ||
1993 | if (test_bit(HCI_ENCRYPT, &hdev->flags)) | 2065 | if (test_bit(HCI_ENCRYPT, &hdev->flags)) |
1994 | conn->link_mode |= HCI_LM_ENCRYPT; | 2066 | set_bit(HCI_CONN_ENCRYPT, &conn->flags); |
1995 | 2067 | ||
1996 | /* Get remote features */ | 2068 | /* Get remote features */ |
1997 | if (conn->type == ACL_LINK) { | 2069 | if (conn->type == ACL_LINK) { |
@@ -2031,10 +2103,21 @@ unlock: | |||
2031 | hci_conn_check_pending(hdev); | 2103 | hci_conn_check_pending(hdev); |
2032 | } | 2104 | } |
2033 | 2105 | ||
2106 | static void hci_reject_conn(struct hci_dev *hdev, bdaddr_t *bdaddr) | ||
2107 | { | ||
2108 | struct hci_cp_reject_conn_req cp; | ||
2109 | |||
2110 | bacpy(&cp.bdaddr, bdaddr); | ||
2111 | cp.reason = HCI_ERROR_REJ_BAD_ADDR; | ||
2112 | hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); | ||
2113 | } | ||
2114 | |||
2034 | static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | 2115 | static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) |
2035 | { | 2116 | { |
2036 | struct hci_ev_conn_request *ev = (void *) skb->data; | 2117 | struct hci_ev_conn_request *ev = (void *) skb->data; |
2037 | int mask = hdev->link_mode; | 2118 | int mask = hdev->link_mode; |
2119 | struct inquiry_entry *ie; | ||
2120 | struct hci_conn *conn; | ||
2038 | __u8 flags = 0; | 2121 | __u8 flags = 0; |
2039 | 2122 | ||
2040 | BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr, | 2123 | BT_DBG("%s bdaddr %pMR type 0x%x", hdev->name, &ev->bdaddr, |
@@ -2043,73 +2126,79 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2043 | mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type, | 2126 | mask |= hci_proto_connect_ind(hdev, &ev->bdaddr, ev->link_type, |
2044 | &flags); | 2127 | &flags); |
2045 | 2128 | ||
2046 | if ((mask & HCI_LM_ACCEPT) && | 2129 | if (!(mask & HCI_LM_ACCEPT)) { |
2047 | !hci_blacklist_lookup(hdev, &ev->bdaddr, BDADDR_BREDR)) { | 2130 | hci_reject_conn(hdev, &ev->bdaddr); |
2048 | /* Connection accepted */ | 2131 | return; |
2049 | struct inquiry_entry *ie; | 2132 | } |
2050 | struct hci_conn *conn; | ||
2051 | 2133 | ||
2052 | hci_dev_lock(hdev); | 2134 | if (hci_bdaddr_list_lookup(&hdev->blacklist, &ev->bdaddr, |
2135 | BDADDR_BREDR)) { | ||
2136 | hci_reject_conn(hdev, &ev->bdaddr); | ||
2137 | return; | ||
2138 | } | ||
2053 | 2139 | ||
2054 | ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); | 2140 | if (!test_bit(HCI_CONNECTABLE, &hdev->dev_flags) && |
2055 | if (ie) | 2141 | !hci_bdaddr_list_lookup(&hdev->whitelist, &ev->bdaddr, |
2056 | memcpy(ie->data.dev_class, ev->dev_class, 3); | 2142 | BDADDR_BREDR)) { |
2143 | hci_reject_conn(hdev, &ev->bdaddr); | ||
2144 | return; | ||
2145 | } | ||
2057 | 2146 | ||
2058 | conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, | 2147 | /* Connection accepted */ |
2059 | &ev->bdaddr); | 2148 | |
2149 | hci_dev_lock(hdev); | ||
2150 | |||
2151 | ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); | ||
2152 | if (ie) | ||
2153 | memcpy(ie->data.dev_class, ev->dev_class, 3); | ||
2154 | |||
2155 | conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, | ||
2156 | &ev->bdaddr); | ||
2157 | if (!conn) { | ||
2158 | conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr, | ||
2159 | HCI_ROLE_SLAVE); | ||
2060 | if (!conn) { | 2160 | if (!conn) { |
2061 | conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); | 2161 | BT_ERR("No memory for new connection"); |
2062 | if (!conn) { | 2162 | hci_dev_unlock(hdev); |
2063 | BT_ERR("No memory for new connection"); | 2163 | return; |
2064 | hci_dev_unlock(hdev); | ||
2065 | return; | ||
2066 | } | ||
2067 | } | 2164 | } |
2165 | } | ||
2068 | 2166 | ||
2069 | memcpy(conn->dev_class, ev->dev_class, 3); | 2167 | memcpy(conn->dev_class, ev->dev_class, 3); |
2070 | 2168 | ||
2071 | hci_dev_unlock(hdev); | 2169 | hci_dev_unlock(hdev); |
2072 | 2170 | ||
2073 | if (ev->link_type == ACL_LINK || | 2171 | if (ev->link_type == ACL_LINK || |
2074 | (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) { | 2172 | (!(flags & HCI_PROTO_DEFER) && !lmp_esco_capable(hdev))) { |
2075 | struct hci_cp_accept_conn_req cp; | 2173 | struct hci_cp_accept_conn_req cp; |
2076 | conn->state = BT_CONNECT; | 2174 | conn->state = BT_CONNECT; |
2077 | 2175 | ||
2078 | bacpy(&cp.bdaddr, &ev->bdaddr); | 2176 | bacpy(&cp.bdaddr, &ev->bdaddr); |
2079 | 2177 | ||
2080 | if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) | 2178 | if (lmp_rswitch_capable(hdev) && (mask & HCI_LM_MASTER)) |
2081 | cp.role = 0x00; /* Become master */ | 2179 | cp.role = 0x00; /* Become master */ |
2082 | else | 2180 | else |
2083 | cp.role = 0x01; /* Remain slave */ | 2181 | cp.role = 0x01; /* Remain slave */ |
2084 | 2182 | ||
2085 | hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), | 2183 | hci_send_cmd(hdev, HCI_OP_ACCEPT_CONN_REQ, sizeof(cp), &cp); |
2086 | &cp); | 2184 | } else if (!(flags & HCI_PROTO_DEFER)) { |
2087 | } else if (!(flags & HCI_PROTO_DEFER)) { | 2185 | struct hci_cp_accept_sync_conn_req cp; |
2088 | struct hci_cp_accept_sync_conn_req cp; | 2186 | conn->state = BT_CONNECT; |
2089 | conn->state = BT_CONNECT; | ||
2090 | 2187 | ||
2091 | bacpy(&cp.bdaddr, &ev->bdaddr); | 2188 | bacpy(&cp.bdaddr, &ev->bdaddr); |
2092 | cp.pkt_type = cpu_to_le16(conn->pkt_type); | 2189 | cp.pkt_type = cpu_to_le16(conn->pkt_type); |
2093 | 2190 | ||
2094 | cp.tx_bandwidth = cpu_to_le32(0x00001f40); | 2191 | cp.tx_bandwidth = cpu_to_le32(0x00001f40); |
2095 | cp.rx_bandwidth = cpu_to_le32(0x00001f40); | 2192 | cp.rx_bandwidth = cpu_to_le32(0x00001f40); |
2096 | cp.max_latency = cpu_to_le16(0xffff); | 2193 | cp.max_latency = cpu_to_le16(0xffff); |
2097 | cp.content_format = cpu_to_le16(hdev->voice_setting); | 2194 | cp.content_format = cpu_to_le16(hdev->voice_setting); |
2098 | cp.retrans_effort = 0xff; | 2195 | cp.retrans_effort = 0xff; |
2099 | 2196 | ||
2100 | hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, | 2197 | hci_send_cmd(hdev, HCI_OP_ACCEPT_SYNC_CONN_REQ, sizeof(cp), |
2101 | sizeof(cp), &cp); | 2198 | &cp); |
2102 | } else { | ||
2103 | conn->state = BT_CONNECT2; | ||
2104 | hci_proto_connect_cfm(conn, 0); | ||
2105 | } | ||
2106 | } else { | 2199 | } else { |
2107 | /* Connection rejected */ | 2200 | conn->state = BT_CONNECT2; |
2108 | struct hci_cp_reject_conn_req cp; | 2201 | hci_proto_connect_cfm(conn, 0); |
2109 | |||
2110 | bacpy(&cp.bdaddr, &ev->bdaddr); | ||
2111 | cp.reason = HCI_ERROR_REJ_BAD_ADDR; | ||
2112 | hci_send_cmd(hdev, HCI_OP_REJECT_CONN_REQ, sizeof(cp), &cp); | ||
2113 | } | 2202 | } |
2114 | } | 2203 | } |
2115 | 2204 | ||
@@ -2158,7 +2247,8 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2158 | mgmt_device_disconnected(hdev, &conn->dst, conn->type, conn->dst_type, | 2247 | mgmt_device_disconnected(hdev, &conn->dst, conn->type, conn->dst_type, |
2159 | reason, mgmt_connected); | 2248 | reason, mgmt_connected); |
2160 | 2249 | ||
2161 | if (conn->type == ACL_LINK && conn->flush_key) | 2250 | if (conn->type == ACL_LINK && |
2251 | test_bit(HCI_CONN_FLUSH_KEY, &conn->flags)) | ||
2162 | hci_remove_link_key(hdev, &conn->dst); | 2252 | hci_remove_link_key(hdev, &conn->dst); |
2163 | 2253 | ||
2164 | params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type); | 2254 | params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type); |
@@ -2169,8 +2259,11 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2169 | break; | 2259 | break; |
2170 | /* Fall through */ | 2260 | /* Fall through */ |
2171 | 2261 | ||
2262 | case HCI_AUTO_CONN_DIRECT: | ||
2172 | case HCI_AUTO_CONN_ALWAYS: | 2263 | case HCI_AUTO_CONN_ALWAYS: |
2173 | hci_pend_le_conn_add(hdev, &conn->dst, conn->dst_type); | 2264 | list_del_init(¶ms->action); |
2265 | list_add(¶ms->action, &hdev->pend_le_conns); | ||
2266 | hci_update_background_scan(hdev); | ||
2174 | break; | 2267 | break; |
2175 | 2268 | ||
2176 | default: | 2269 | default: |
@@ -2218,7 +2311,7 @@ static void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2218 | test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) { | 2311 | test_bit(HCI_CONN_REAUTH_PEND, &conn->flags)) { |
2219 | BT_INFO("re-auth of legacy device is not possible."); | 2312 | BT_INFO("re-auth of legacy device is not possible."); |
2220 | } else { | 2313 | } else { |
2221 | conn->link_mode |= HCI_LM_AUTH; | 2314 | set_bit(HCI_CONN_AUTH, &conn->flags); |
2222 | conn->sec_level = conn->pending_sec_level; | 2315 | conn->sec_level = conn->pending_sec_level; |
2223 | } | 2316 | } |
2224 | } else { | 2317 | } else { |
@@ -2297,6 +2390,9 @@ check_auth: | |||
2297 | 2390 | ||
2298 | if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { | 2391 | if (!test_and_set_bit(HCI_CONN_AUTH_PEND, &conn->flags)) { |
2299 | struct hci_cp_auth_requested cp; | 2392 | struct hci_cp_auth_requested cp; |
2393 | |||
2394 | set_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags); | ||
2395 | |||
2300 | cp.handle = __cpu_to_le16(conn->handle); | 2396 | cp.handle = __cpu_to_le16(conn->handle); |
2301 | hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); | 2397 | hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); |
2302 | } | 2398 | } |
@@ -2321,19 +2417,19 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2321 | if (!ev->status) { | 2417 | if (!ev->status) { |
2322 | if (ev->encrypt) { | 2418 | if (ev->encrypt) { |
2323 | /* Encryption implies authentication */ | 2419 | /* Encryption implies authentication */ |
2324 | conn->link_mode |= HCI_LM_AUTH; | 2420 | set_bit(HCI_CONN_AUTH, &conn->flags); |
2325 | conn->link_mode |= HCI_LM_ENCRYPT; | 2421 | set_bit(HCI_CONN_ENCRYPT, &conn->flags); |
2326 | conn->sec_level = conn->pending_sec_level; | 2422 | conn->sec_level = conn->pending_sec_level; |
2327 | 2423 | ||
2328 | /* P-256 authentication key implies FIPS */ | 2424 | /* P-256 authentication key implies FIPS */ |
2329 | if (conn->key_type == HCI_LK_AUTH_COMBINATION_P256) | 2425 | if (conn->key_type == HCI_LK_AUTH_COMBINATION_P256) |
2330 | conn->link_mode |= HCI_LM_FIPS; | 2426 | set_bit(HCI_CONN_FIPS, &conn->flags); |
2331 | 2427 | ||
2332 | if ((conn->type == ACL_LINK && ev->encrypt == 0x02) || | 2428 | if ((conn->type == ACL_LINK && ev->encrypt == 0x02) || |
2333 | conn->type == LE_LINK) | 2429 | conn->type == LE_LINK) |
2334 | set_bit(HCI_CONN_AES_CCM, &conn->flags); | 2430 | set_bit(HCI_CONN_AES_CCM, &conn->flags); |
2335 | } else { | 2431 | } else { |
2336 | conn->link_mode &= ~HCI_LM_ENCRYPT; | 2432 | clear_bit(HCI_CONN_ENCRYPT, &conn->flags); |
2337 | clear_bit(HCI_CONN_AES_CCM, &conn->flags); | 2433 | clear_bit(HCI_CONN_AES_CCM, &conn->flags); |
2338 | } | 2434 | } |
2339 | } | 2435 | } |
@@ -2384,7 +2480,7 @@ static void hci_change_link_key_complete_evt(struct hci_dev *hdev, | |||
2384 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); | 2480 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); |
2385 | if (conn) { | 2481 | if (conn) { |
2386 | if (!ev->status) | 2482 | if (!ev->status) |
2387 | conn->link_mode |= HCI_LM_SECURE; | 2483 | set_bit(HCI_CONN_SECURE, &conn->flags); |
2388 | 2484 | ||
2389 | clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); | 2485 | clear_bit(HCI_CONN_AUTH_PEND, &conn->flags); |
2390 | 2486 | ||
@@ -2595,6 +2691,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2595 | hci_cc_read_local_amp_info(hdev, skb); | 2691 | hci_cc_read_local_amp_info(hdev, skb); |
2596 | break; | 2692 | break; |
2597 | 2693 | ||
2694 | case HCI_OP_READ_CLOCK: | ||
2695 | hci_cc_read_clock(hdev, skb); | ||
2696 | break; | ||
2697 | |||
2598 | case HCI_OP_READ_LOCAL_AMP_ASSOC: | 2698 | case HCI_OP_READ_LOCAL_AMP_ASSOC: |
2599 | hci_cc_read_local_amp_assoc(hdev, skb); | 2699 | hci_cc_read_local_amp_assoc(hdev, skb); |
2600 | break; | 2700 | break; |
@@ -2709,7 +2809,7 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2709 | } | 2809 | } |
2710 | 2810 | ||
2711 | if (opcode != HCI_OP_NOP) | 2811 | if (opcode != HCI_OP_NOP) |
2712 | del_timer(&hdev->cmd_timer); | 2812 | cancel_delayed_work(&hdev->cmd_timer); |
2713 | 2813 | ||
2714 | hci_req_cmd_complete(hdev, opcode, status); | 2814 | hci_req_cmd_complete(hdev, opcode, status); |
2715 | 2815 | ||
@@ -2800,7 +2900,7 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2800 | } | 2900 | } |
2801 | 2901 | ||
2802 | if (opcode != HCI_OP_NOP) | 2902 | if (opcode != HCI_OP_NOP) |
2803 | del_timer(&hdev->cmd_timer); | 2903 | cancel_delayed_work(&hdev->cmd_timer); |
2804 | 2904 | ||
2805 | if (ev->status || | 2905 | if (ev->status || |
2806 | (hdev->sent_cmd && !bt_cb(hdev->sent_cmd)->req.event)) | 2906 | (hdev->sent_cmd && !bt_cb(hdev->sent_cmd)->req.event)) |
@@ -2824,12 +2924,8 @@ static void hci_role_change_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
2824 | 2924 | ||
2825 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); | 2925 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); |
2826 | if (conn) { | 2926 | if (conn) { |
2827 | if (!ev->status) { | 2927 | if (!ev->status) |
2828 | if (ev->role) | 2928 | conn->role = ev->role; |
2829 | conn->link_mode &= ~HCI_LM_MASTER; | ||
2830 | else | ||
2831 | conn->link_mode |= HCI_LM_MASTER; | ||
2832 | } | ||
2833 | 2929 | ||
2834 | clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); | 2930 | clear_bit(HCI_CONN_RSWITCH_PEND, &conn->flags); |
2835 | 2931 | ||
@@ -3023,10 +3119,11 @@ static void hci_pin_code_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
3023 | hci_conn_drop(conn); | 3119 | hci_conn_drop(conn); |
3024 | } | 3120 | } |
3025 | 3121 | ||
3026 | if (!test_bit(HCI_PAIRABLE, &hdev->dev_flags)) | 3122 | if (!test_bit(HCI_BONDABLE, &hdev->dev_flags) && |
3123 | !test_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags)) { | ||
3027 | hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, | 3124 | hci_send_cmd(hdev, HCI_OP_PIN_CODE_NEG_REPLY, |
3028 | sizeof(ev->bdaddr), &ev->bdaddr); | 3125 | sizeof(ev->bdaddr), &ev->bdaddr); |
3029 | else if (test_bit(HCI_MGMT, &hdev->dev_flags)) { | 3126 | } else if (test_bit(HCI_MGMT, &hdev->dev_flags)) { |
3030 | u8 secure; | 3127 | u8 secure; |
3031 | 3128 | ||
3032 | if (conn->pending_sec_level == BT_SECURITY_HIGH) | 3129 | if (conn->pending_sec_level == BT_SECURITY_HIGH) |
@@ -3065,12 +3162,6 @@ static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
3065 | BT_DBG("%s found key type %u for %pMR", hdev->name, key->type, | 3162 | BT_DBG("%s found key type %u for %pMR", hdev->name, key->type, |
3066 | &ev->bdaddr); | 3163 | &ev->bdaddr); |
3067 | 3164 | ||
3068 | if (!test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) && | ||
3069 | key->type == HCI_LK_DEBUG_COMBINATION) { | ||
3070 | BT_DBG("%s ignoring debug key", hdev->name); | ||
3071 | goto not_found; | ||
3072 | } | ||
3073 | |||
3074 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); | 3165 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); |
3075 | if (conn) { | 3166 | if (conn) { |
3076 | if ((key->type == HCI_LK_UNAUTH_COMBINATION_P192 || | 3167 | if ((key->type == HCI_LK_UNAUTH_COMBINATION_P192 || |
@@ -3110,6 +3201,8 @@ static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
3110 | { | 3201 | { |
3111 | struct hci_ev_link_key_notify *ev = (void *) skb->data; | 3202 | struct hci_ev_link_key_notify *ev = (void *) skb->data; |
3112 | struct hci_conn *conn; | 3203 | struct hci_conn *conn; |
3204 | struct link_key *key; | ||
3205 | bool persistent; | ||
3113 | u8 pin_len = 0; | 3206 | u8 pin_len = 0; |
3114 | 3207 | ||
3115 | BT_DBG("%s", hdev->name); | 3208 | BT_DBG("%s", hdev->name); |
@@ -3128,10 +3221,33 @@ static void hci_link_key_notify_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
3128 | hci_conn_drop(conn); | 3221 | hci_conn_drop(conn); |
3129 | } | 3222 | } |
3130 | 3223 | ||
3131 | if (test_bit(HCI_MGMT, &hdev->dev_flags)) | 3224 | if (!test_bit(HCI_MGMT, &hdev->dev_flags)) |
3132 | hci_add_link_key(hdev, conn, 1, &ev->bdaddr, ev->link_key, | 3225 | goto unlock; |
3133 | ev->key_type, pin_len); | 3226 | |
3227 | key = hci_add_link_key(hdev, conn, &ev->bdaddr, ev->link_key, | ||
3228 | ev->key_type, pin_len, &persistent); | ||
3229 | if (!key) | ||
3230 | goto unlock; | ||
3134 | 3231 | ||
3232 | mgmt_new_link_key(hdev, key, persistent); | ||
3233 | |||
3234 | /* Keep debug keys around only if the HCI_KEEP_DEBUG_KEYS flag | ||
3235 | * is set. If it's not set simply remove the key from the kernel | ||
3236 | * list (we've still notified user space about it but with | ||
3237 | * store_hint being 0). | ||
3238 | */ | ||
3239 | if (key->type == HCI_LK_DEBUG_COMBINATION && | ||
3240 | !test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags)) { | ||
3241 | list_del(&key->list); | ||
3242 | kfree(key); | ||
3243 | } else if (conn) { | ||
3244 | if (persistent) | ||
3245 | clear_bit(HCI_CONN_FLUSH_KEY, &conn->flags); | ||
3246 | else | ||
3247 | set_bit(HCI_CONN_FLUSH_KEY, &conn->flags); | ||
3248 | } | ||
3249 | |||
3250 | unlock: | ||
3135 | hci_dev_unlock(hdev); | 3251 | hci_dev_unlock(hdev); |
3136 | } | 3252 | } |
3137 | 3253 | ||
@@ -3197,7 +3313,6 @@ static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, | |||
3197 | { | 3313 | { |
3198 | struct inquiry_data data; | 3314 | struct inquiry_data data; |
3199 | int num_rsp = *((__u8 *) skb->data); | 3315 | int num_rsp = *((__u8 *) skb->data); |
3200 | bool name_known, ssp; | ||
3201 | 3316 | ||
3202 | BT_DBG("%s num_rsp %d", hdev->name, num_rsp); | 3317 | BT_DBG("%s num_rsp %d", hdev->name, num_rsp); |
3203 | 3318 | ||
@@ -3214,6 +3329,8 @@ static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, | |||
3214 | info = (void *) (skb->data + 1); | 3329 | info = (void *) (skb->data + 1); |
3215 | 3330 | ||
3216 | for (; num_rsp; num_rsp--, info++) { | 3331 | for (; num_rsp; num_rsp--, info++) { |
3332 | u32 flags; | ||
3333 | |||
3217 | bacpy(&data.bdaddr, &info->bdaddr); | 3334 | bacpy(&data.bdaddr, &info->bdaddr); |
3218 | data.pscan_rep_mode = info->pscan_rep_mode; | 3335 | data.pscan_rep_mode = info->pscan_rep_mode; |
3219 | data.pscan_period_mode = info->pscan_period_mode; | 3336 | data.pscan_period_mode = info->pscan_period_mode; |
@@ -3223,16 +3340,18 @@ static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, | |||
3223 | data.rssi = info->rssi; | 3340 | data.rssi = info->rssi; |
3224 | data.ssp_mode = 0x00; | 3341 | data.ssp_mode = 0x00; |
3225 | 3342 | ||
3226 | name_known = hci_inquiry_cache_update(hdev, &data, | 3343 | flags = hci_inquiry_cache_update(hdev, &data, false); |
3227 | false, &ssp); | 3344 | |
3228 | mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, | 3345 | mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, |
3229 | info->dev_class, info->rssi, | 3346 | info->dev_class, info->rssi, |
3230 | !name_known, ssp, NULL, 0, NULL, 0); | 3347 | flags, NULL, 0, NULL, 0); |
3231 | } | 3348 | } |
3232 | } else { | 3349 | } else { |
3233 | struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); | 3350 | struct inquiry_info_with_rssi *info = (void *) (skb->data + 1); |
3234 | 3351 | ||
3235 | for (; num_rsp; num_rsp--, info++) { | 3352 | for (; num_rsp; num_rsp--, info++) { |
3353 | u32 flags; | ||
3354 | |||
3236 | bacpy(&data.bdaddr, &info->bdaddr); | 3355 | bacpy(&data.bdaddr, &info->bdaddr); |
3237 | data.pscan_rep_mode = info->pscan_rep_mode; | 3356 | data.pscan_rep_mode = info->pscan_rep_mode; |
3238 | data.pscan_period_mode = info->pscan_period_mode; | 3357 | data.pscan_period_mode = info->pscan_period_mode; |
@@ -3241,11 +3360,12 @@ static void hci_inquiry_result_with_rssi_evt(struct hci_dev *hdev, | |||
3241 | data.clock_offset = info->clock_offset; | 3360 | data.clock_offset = info->clock_offset; |
3242 | data.rssi = info->rssi; | 3361 | data.rssi = info->rssi; |
3243 | data.ssp_mode = 0x00; | 3362 | data.ssp_mode = 0x00; |
3244 | name_known = hci_inquiry_cache_update(hdev, &data, | 3363 | |
3245 | false, &ssp); | 3364 | flags = hci_inquiry_cache_update(hdev, &data, false); |
3365 | |||
3246 | mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, | 3366 | mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, |
3247 | info->dev_class, info->rssi, | 3367 | info->dev_class, info->rssi, |
3248 | !name_known, ssp, NULL, 0, NULL, 0); | 3368 | flags, NULL, 0, NULL, 0); |
3249 | } | 3369 | } |
3250 | } | 3370 | } |
3251 | 3371 | ||
@@ -3348,6 +3468,7 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev, | |||
3348 | hci_conn_add_sysfs(conn); | 3468 | hci_conn_add_sysfs(conn); |
3349 | break; | 3469 | break; |
3350 | 3470 | ||
3471 | case 0x10: /* Connection Accept Timeout */ | ||
3351 | case 0x0d: /* Connection Rejected due to Limited Resources */ | 3472 | case 0x0d: /* Connection Rejected due to Limited Resources */ |
3352 | case 0x11: /* Unsupported Feature or Parameter Value */ | 3473 | case 0x11: /* Unsupported Feature or Parameter Value */ |
3353 | case 0x1c: /* SCO interval rejected */ | 3474 | case 0x1c: /* SCO interval rejected */ |
@@ -3411,7 +3532,8 @@ static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, | |||
3411 | hci_dev_lock(hdev); | 3532 | hci_dev_lock(hdev); |
3412 | 3533 | ||
3413 | for (; num_rsp; num_rsp--, info++) { | 3534 | for (; num_rsp; num_rsp--, info++) { |
3414 | bool name_known, ssp; | 3535 | u32 flags; |
3536 | bool name_known; | ||
3415 | 3537 | ||
3416 | bacpy(&data.bdaddr, &info->bdaddr); | 3538 | bacpy(&data.bdaddr, &info->bdaddr); |
3417 | data.pscan_rep_mode = info->pscan_rep_mode; | 3539 | data.pscan_rep_mode = info->pscan_rep_mode; |
@@ -3429,12 +3551,13 @@ static void hci_extended_inquiry_result_evt(struct hci_dev *hdev, | |||
3429 | else | 3551 | else |
3430 | name_known = true; | 3552 | name_known = true; |
3431 | 3553 | ||
3432 | name_known = hci_inquiry_cache_update(hdev, &data, name_known, | 3554 | flags = hci_inquiry_cache_update(hdev, &data, name_known); |
3433 | &ssp); | 3555 | |
3434 | eir_len = eir_get_length(info->data, sizeof(info->data)); | 3556 | eir_len = eir_get_length(info->data, sizeof(info->data)); |
3557 | |||
3435 | mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, | 3558 | mgmt_device_found(hdev, &info->bdaddr, ACL_LINK, 0x00, |
3436 | info->dev_class, info->rssi, !name_known, | 3559 | info->dev_class, info->rssi, |
3437 | ssp, info->data, eir_len, NULL, 0); | 3560 | flags, info->data, eir_len, NULL, 0); |
3438 | } | 3561 | } |
3439 | 3562 | ||
3440 | hci_dev_unlock(hdev); | 3563 | hci_dev_unlock(hdev); |
@@ -3526,7 +3649,11 @@ static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
3526 | if (!test_bit(HCI_MGMT, &hdev->dev_flags)) | 3649 | if (!test_bit(HCI_MGMT, &hdev->dev_flags)) |
3527 | goto unlock; | 3650 | goto unlock; |
3528 | 3651 | ||
3529 | if (test_bit(HCI_PAIRABLE, &hdev->dev_flags) || | 3652 | /* Allow pairing if we're pairable, the initiators of the |
3653 | * pairing or if the remote is not requesting bonding. | ||
3654 | */ | ||
3655 | if (test_bit(HCI_BONDABLE, &hdev->dev_flags) || | ||
3656 | test_bit(HCI_CONN_AUTH_INITIATOR, &conn->flags) || | ||
3530 | (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { | 3657 | (conn->remote_auth & ~0x01) == HCI_AT_NO_BONDING) { |
3531 | struct hci_cp_io_capability_reply cp; | 3658 | struct hci_cp_io_capability_reply cp; |
3532 | 3659 | ||
@@ -3538,23 +3665,24 @@ static void hci_io_capa_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
3538 | 3665 | ||
3539 | /* If we are initiators, there is no remote information yet */ | 3666 | /* If we are initiators, there is no remote information yet */ |
3540 | if (conn->remote_auth == 0xff) { | 3667 | if (conn->remote_auth == 0xff) { |
3541 | cp.authentication = conn->auth_type; | ||
3542 | |||
3543 | /* Request MITM protection if our IO caps allow it | 3668 | /* Request MITM protection if our IO caps allow it |
3544 | * except for the no-bonding case. | 3669 | * except for the no-bonding case. |
3545 | * conn->auth_type is not updated here since | ||
3546 | * that might cause the user confirmation to be | ||
3547 | * rejected in case the remote doesn't have the | ||
3548 | * IO capabilities for MITM. | ||
3549 | */ | 3670 | */ |
3550 | if (conn->io_capability != HCI_IO_NO_INPUT_OUTPUT && | 3671 | if (conn->io_capability != HCI_IO_NO_INPUT_OUTPUT && |
3551 | cp.authentication != HCI_AT_NO_BONDING) | 3672 | conn->auth_type != HCI_AT_NO_BONDING) |
3552 | cp.authentication |= 0x01; | 3673 | conn->auth_type |= 0x01; |
3553 | } else { | 3674 | } else { |
3554 | conn->auth_type = hci_get_auth_req(conn); | 3675 | conn->auth_type = hci_get_auth_req(conn); |
3555 | cp.authentication = conn->auth_type; | ||
3556 | } | 3676 | } |
3557 | 3677 | ||
3678 | /* If we're not bondable, force one of the non-bondable | ||
3679 | * authentication requirement values. | ||
3680 | */ | ||
3681 | if (!test_bit(HCI_BONDABLE, &hdev->dev_flags)) | ||
3682 | conn->auth_type &= HCI_AT_NO_BONDING_MITM; | ||
3683 | |||
3684 | cp.authentication = conn->auth_type; | ||
3685 | |||
3558 | if (hci_find_remote_oob_data(hdev, &conn->dst) && | 3686 | if (hci_find_remote_oob_data(hdev, &conn->dst) && |
3559 | (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags))) | 3687 | (conn->out || test_bit(HCI_CONN_REMOTE_OOB, &conn->flags))) |
3560 | cp.oob_data = 0x01; | 3688 | cp.oob_data = 0x01; |
@@ -3621,9 +3749,12 @@ static void hci_user_confirm_request_evt(struct hci_dev *hdev, | |||
3621 | rem_mitm = (conn->remote_auth & 0x01); | 3749 | rem_mitm = (conn->remote_auth & 0x01); |
3622 | 3750 | ||
3623 | /* If we require MITM but the remote device can't provide that | 3751 | /* If we require MITM but the remote device can't provide that |
3624 | * (it has NoInputNoOutput) then reject the confirmation request | 3752 | * (it has NoInputNoOutput) then reject the confirmation |
3753 | * request. We check the security level here since it doesn't | ||
3754 | * necessarily match conn->auth_type. | ||
3625 | */ | 3755 | */ |
3626 | if (loc_mitm && conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) { | 3756 | if (conn->pending_sec_level > BT_SECURITY_MEDIUM && |
3757 | conn->remote_cap == HCI_IO_NO_INPUT_OUTPUT) { | ||
3627 | BT_DBG("Rejecting request: remote device can't provide MITM"); | 3758 | BT_DBG("Rejecting request: remote device can't provide MITM"); |
3628 | hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, | 3759 | hci_send_cmd(hdev, HCI_OP_USER_CONFIRM_NEG_REPLY, |
3629 | sizeof(ev->bdaddr), &ev->bdaddr); | 3760 | sizeof(ev->bdaddr), &ev->bdaddr); |
@@ -3637,9 +3768,11 @@ static void hci_user_confirm_request_evt(struct hci_dev *hdev, | |||
3637 | /* If we're not the initiators request authorization to | 3768 | /* If we're not the initiators request authorization to |
3638 | * proceed from user space (mgmt_user_confirm with | 3769 | * proceed from user space (mgmt_user_confirm with |
3639 | * confirm_hint set to 1). The exception is if neither | 3770 | * confirm_hint set to 1). The exception is if neither |
3640 | * side had MITM in which case we do auto-accept. | 3771 | * side had MITM or if the local IO capability is |
3772 | * NoInputNoOutput, in which case we do auto-accept | ||
3641 | */ | 3773 | */ |
3642 | if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && | 3774 | if (!test_bit(HCI_CONN_AUTH_PEND, &conn->flags) && |
3775 | conn->io_capability != HCI_IO_NO_INPUT_OUTPUT && | ||
3643 | (loc_mitm || rem_mitm)) { | 3776 | (loc_mitm || rem_mitm)) { |
3644 | BT_DBG("Confirming auto-accept as acceptor"); | 3777 | BT_DBG("Confirming auto-accept as acceptor"); |
3645 | confirm_hint = 1; | 3778 | confirm_hint = 1; |
@@ -3753,6 +3886,9 @@ static void hci_simple_pair_complete_evt(struct hci_dev *hdev, | |||
3753 | if (!conn) | 3886 | if (!conn) |
3754 | goto unlock; | 3887 | goto unlock; |
3755 | 3888 | ||
3889 | /* Reset the authentication requirement to unknown */ | ||
3890 | conn->remote_auth = 0xff; | ||
3891 | |||
3756 | /* To avoid duplicate auth_failed events to user space we check | 3892 | /* To avoid duplicate auth_failed events to user space we check |
3757 | * the HCI_CONN_AUTH_PEND flag which will be set if we | 3893 | * the HCI_CONN_AUTH_PEND flag which will be set if we |
3758 | * initiated the authentication. A traditional auth_complete | 3894 | * initiated the authentication. A traditional auth_complete |
@@ -3967,16 +4103,23 @@ static void hci_disconn_phylink_complete_evt(struct hci_dev *hdev, | |||
3967 | static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | 4103 | static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
3968 | { | 4104 | { |
3969 | struct hci_ev_le_conn_complete *ev = (void *) skb->data; | 4105 | struct hci_ev_le_conn_complete *ev = (void *) skb->data; |
4106 | struct hci_conn_params *params; | ||
3970 | struct hci_conn *conn; | 4107 | struct hci_conn *conn; |
3971 | struct smp_irk *irk; | 4108 | struct smp_irk *irk; |
4109 | u8 addr_type; | ||
3972 | 4110 | ||
3973 | BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); | 4111 | BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); |
3974 | 4112 | ||
3975 | hci_dev_lock(hdev); | 4113 | hci_dev_lock(hdev); |
3976 | 4114 | ||
4115 | /* All controllers implicitly stop advertising in the event of a | ||
4116 | * connection, so ensure that the state bit is cleared. | ||
4117 | */ | ||
4118 | clear_bit(HCI_LE_ADV, &hdev->dev_flags); | ||
4119 | |||
3977 | conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); | 4120 | conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); |
3978 | if (!conn) { | 4121 | if (!conn) { |
3979 | conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr); | 4122 | conn = hci_conn_add(hdev, LE_LINK, &ev->bdaddr, ev->role); |
3980 | if (!conn) { | 4123 | if (!conn) { |
3981 | BT_ERR("No memory for new connection"); | 4124 | BT_ERR("No memory for new connection"); |
3982 | goto unlock; | 4125 | goto unlock; |
@@ -3984,11 +4127,6 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
3984 | 4127 | ||
3985 | conn->dst_type = ev->bdaddr_type; | 4128 | conn->dst_type = ev->bdaddr_type; |
3986 | 4129 | ||
3987 | if (ev->role == LE_CONN_ROLE_MASTER) { | ||
3988 | conn->out = true; | ||
3989 | conn->link_mode |= HCI_LM_MASTER; | ||
3990 | } | ||
3991 | |||
3992 | /* If we didn't have a hci_conn object previously | 4130 | /* If we didn't have a hci_conn object previously |
3993 | * but we're in master role this must be something | 4131 | * but we're in master role this must be something |
3994 | * initiated using a white list. Since white list based | 4132 | * initiated using a white list. Since white list based |
@@ -4025,6 +4163,14 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
4025 | 4163 | ||
4026 | conn->init_addr_type = ev->bdaddr_type; | 4164 | conn->init_addr_type = ev->bdaddr_type; |
4027 | bacpy(&conn->init_addr, &ev->bdaddr); | 4165 | bacpy(&conn->init_addr, &ev->bdaddr); |
4166 | |||
4167 | /* For incoming connections, set the default minimum | ||
4168 | * and maximum connection interval. They will be used | ||
4169 | * to check if the parameters are in range and if not | ||
4170 | * trigger the connection update procedure. | ||
4171 | */ | ||
4172 | conn->le_conn_min_interval = hdev->le_conn_min_interval; | ||
4173 | conn->le_conn_max_interval = hdev->le_conn_max_interval; | ||
4028 | } | 4174 | } |
4029 | 4175 | ||
4030 | /* Lookup the identity address from the stored connection | 4176 | /* Lookup the identity address from the stored connection |
@@ -4042,11 +4188,22 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
4042 | conn->dst_type = irk->addr_type; | 4188 | conn->dst_type = irk->addr_type; |
4043 | } | 4189 | } |
4044 | 4190 | ||
4191 | if (conn->dst_type == ADDR_LE_DEV_PUBLIC) | ||
4192 | addr_type = BDADDR_LE_PUBLIC; | ||
4193 | else | ||
4194 | addr_type = BDADDR_LE_RANDOM; | ||
4195 | |||
4045 | if (ev->status) { | 4196 | if (ev->status) { |
4046 | hci_le_conn_failed(conn, ev->status); | 4197 | hci_le_conn_failed(conn, ev->status); |
4047 | goto unlock; | 4198 | goto unlock; |
4048 | } | 4199 | } |
4049 | 4200 | ||
4201 | /* Drop the connection if the device is blocked */ | ||
4202 | if (hci_bdaddr_list_lookup(&hdev->blacklist, &conn->dst, addr_type)) { | ||
4203 | hci_conn_drop(conn); | ||
4204 | goto unlock; | ||
4205 | } | ||
4206 | |||
4050 | if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) | 4207 | if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) |
4051 | mgmt_device_connected(hdev, &conn->dst, conn->type, | 4208 | mgmt_device_connected(hdev, &conn->dst, conn->type, |
4052 | conn->dst_type, 0, NULL, 0, NULL); | 4209 | conn->dst_type, 0, NULL, 0, NULL); |
@@ -4055,42 +4212,113 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
4055 | conn->handle = __le16_to_cpu(ev->handle); | 4212 | conn->handle = __le16_to_cpu(ev->handle); |
4056 | conn->state = BT_CONNECTED; | 4213 | conn->state = BT_CONNECTED; |
4057 | 4214 | ||
4058 | if (test_bit(HCI_6LOWPAN_ENABLED, &hdev->dev_flags)) | 4215 | conn->le_conn_interval = le16_to_cpu(ev->interval); |
4059 | set_bit(HCI_CONN_6LOWPAN, &conn->flags); | 4216 | conn->le_conn_latency = le16_to_cpu(ev->latency); |
4217 | conn->le_supv_timeout = le16_to_cpu(ev->supervision_timeout); | ||
4060 | 4218 | ||
4061 | hci_conn_add_sysfs(conn); | 4219 | hci_conn_add_sysfs(conn); |
4062 | 4220 | ||
4063 | hci_proto_connect_cfm(conn, ev->status); | 4221 | hci_proto_connect_cfm(conn, ev->status); |
4064 | 4222 | ||
4065 | hci_pend_le_conn_del(hdev, &conn->dst, conn->dst_type); | 4223 | params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type); |
4224 | if (params) { | ||
4225 | list_del_init(¶ms->action); | ||
4226 | if (params->conn) { | ||
4227 | hci_conn_drop(params->conn); | ||
4228 | params->conn = NULL; | ||
4229 | } | ||
4230 | } | ||
4066 | 4231 | ||
4067 | unlock: | 4232 | unlock: |
4233 | hci_update_background_scan(hdev); | ||
4234 | hci_dev_unlock(hdev); | ||
4235 | } | ||
4236 | |||
4237 | static void hci_le_conn_update_complete_evt(struct hci_dev *hdev, | ||
4238 | struct sk_buff *skb) | ||
4239 | { | ||
4240 | struct hci_ev_le_conn_update_complete *ev = (void *) skb->data; | ||
4241 | struct hci_conn *conn; | ||
4242 | |||
4243 | BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); | ||
4244 | |||
4245 | if (ev->status) | ||
4246 | return; | ||
4247 | |||
4248 | hci_dev_lock(hdev); | ||
4249 | |||
4250 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); | ||
4251 | if (conn) { | ||
4252 | conn->le_conn_interval = le16_to_cpu(ev->interval); | ||
4253 | conn->le_conn_latency = le16_to_cpu(ev->latency); | ||
4254 | conn->le_supv_timeout = le16_to_cpu(ev->supervision_timeout); | ||
4255 | } | ||
4256 | |||
4068 | hci_dev_unlock(hdev); | 4257 | hci_dev_unlock(hdev); |
4069 | } | 4258 | } |
4070 | 4259 | ||
4071 | /* This function requires the caller holds hdev->lock */ | 4260 | /* This function requires the caller holds hdev->lock */ |
4072 | static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr, | 4261 | static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr, |
4073 | u8 addr_type) | 4262 | u8 addr_type, u8 adv_type) |
4074 | { | 4263 | { |
4075 | struct hci_conn *conn; | 4264 | struct hci_conn *conn; |
4076 | struct smp_irk *irk; | 4265 | struct hci_conn_params *params; |
4266 | |||
4267 | /* If the event is not connectable don't proceed further */ | ||
4268 | if (adv_type != LE_ADV_IND && adv_type != LE_ADV_DIRECT_IND) | ||
4269 | return; | ||
4270 | |||
4271 | /* Ignore if the device is blocked */ | ||
4272 | if (hci_bdaddr_list_lookup(&hdev->blacklist, addr, addr_type)) | ||
4273 | return; | ||
4077 | 4274 | ||
4078 | /* If this is a resolvable address, we should resolve it and then | 4275 | /* Most controller will fail if we try to create new connections |
4079 | * update address and address type variables. | 4276 | * while we have an existing one in slave role. |
4080 | */ | 4277 | */ |
4081 | irk = hci_get_irk(hdev, addr, addr_type); | 4278 | if (hdev->conn_hash.le_num_slave > 0) |
4082 | if (irk) { | 4279 | return; |
4083 | addr = &irk->bdaddr; | ||
4084 | addr_type = irk->addr_type; | ||
4085 | } | ||
4086 | 4280 | ||
4087 | if (!hci_pend_le_conn_lookup(hdev, addr, addr_type)) | 4281 | /* If we're not connectable only connect devices that we have in |
4282 | * our pend_le_conns list. | ||
4283 | */ | ||
4284 | params = hci_pend_le_action_lookup(&hdev->pend_le_conns, | ||
4285 | addr, addr_type); | ||
4286 | if (!params) | ||
4088 | return; | 4287 | return; |
4089 | 4288 | ||
4289 | switch (params->auto_connect) { | ||
4290 | case HCI_AUTO_CONN_DIRECT: | ||
4291 | /* Only devices advertising with ADV_DIRECT_IND are | ||
4292 | * triggering a connection attempt. This is allowing | ||
4293 | * incoming connections from slave devices. | ||
4294 | */ | ||
4295 | if (adv_type != LE_ADV_DIRECT_IND) | ||
4296 | return; | ||
4297 | break; | ||
4298 | case HCI_AUTO_CONN_ALWAYS: | ||
4299 | /* Devices advertising with ADV_IND or ADV_DIRECT_IND | ||
4300 | * are triggering a connection attempt. This means | ||
4301 | * that incoming connectioms from slave device are | ||
4302 | * accepted and also outgoing connections to slave | ||
4303 | * devices are established when found. | ||
4304 | */ | ||
4305 | break; | ||
4306 | default: | ||
4307 | return; | ||
4308 | } | ||
4309 | |||
4090 | conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW, | 4310 | conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW, |
4091 | HCI_AT_NO_BONDING); | 4311 | HCI_LE_AUTOCONN_TIMEOUT, HCI_ROLE_MASTER); |
4092 | if (!IS_ERR(conn)) | 4312 | if (!IS_ERR(conn)) { |
4313 | /* Store the pointer since we don't really have any | ||
4314 | * other owner of the object besides the params that | ||
4315 | * triggered it. This way we can abort the connection if | ||
4316 | * the parameters get removed and keep the reference | ||
4317 | * count consistent once the connection is established. | ||
4318 | */ | ||
4319 | params->conn = conn; | ||
4093 | return; | 4320 | return; |
4321 | } | ||
4094 | 4322 | ||
4095 | switch (PTR_ERR(conn)) { | 4323 | switch (PTR_ERR(conn)) { |
4096 | case -EBUSY: | 4324 | case -EBUSY: |
@@ -4109,15 +4337,62 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, | |||
4109 | u8 bdaddr_type, s8 rssi, u8 *data, u8 len) | 4337 | u8 bdaddr_type, s8 rssi, u8 *data, u8 len) |
4110 | { | 4338 | { |
4111 | struct discovery_state *d = &hdev->discovery; | 4339 | struct discovery_state *d = &hdev->discovery; |
4340 | struct smp_irk *irk; | ||
4112 | bool match; | 4341 | bool match; |
4342 | u32 flags; | ||
4343 | |||
4344 | /* Check if we need to convert to identity address */ | ||
4345 | irk = hci_get_irk(hdev, bdaddr, bdaddr_type); | ||
4346 | if (irk) { | ||
4347 | bdaddr = &irk->bdaddr; | ||
4348 | bdaddr_type = irk->addr_type; | ||
4349 | } | ||
4113 | 4350 | ||
4114 | /* Passive scanning shouldn't trigger any device found events */ | 4351 | /* Check if we have been requested to connect to this device */ |
4352 | check_pending_le_conn(hdev, bdaddr, bdaddr_type, type); | ||
4353 | |||
4354 | /* Passive scanning shouldn't trigger any device found events, | ||
4355 | * except for devices marked as CONN_REPORT for which we do send | ||
4356 | * device found events. | ||
4357 | */ | ||
4115 | if (hdev->le_scan_type == LE_SCAN_PASSIVE) { | 4358 | if (hdev->le_scan_type == LE_SCAN_PASSIVE) { |
4116 | if (type == LE_ADV_IND || type == LE_ADV_DIRECT_IND) | 4359 | if (type == LE_ADV_DIRECT_IND) |
4117 | check_pending_le_conn(hdev, bdaddr, bdaddr_type); | 4360 | return; |
4361 | |||
4362 | if (!hci_pend_le_action_lookup(&hdev->pend_le_reports, | ||
4363 | bdaddr, bdaddr_type)) | ||
4364 | return; | ||
4365 | |||
4366 | if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND) | ||
4367 | flags = MGMT_DEV_FOUND_NOT_CONNECTABLE; | ||
4368 | else | ||
4369 | flags = 0; | ||
4370 | mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL, | ||
4371 | rssi, flags, data, len, NULL, 0); | ||
4118 | return; | 4372 | return; |
4119 | } | 4373 | } |
4120 | 4374 | ||
4375 | /* When receiving non-connectable or scannable undirected | ||
4376 | * advertising reports, this means that the remote device is | ||
4377 | * not connectable and then clearly indicate this in the | ||
4378 | * device found event. | ||
4379 | * | ||
4380 | * When receiving a scan response, then there is no way to | ||
4381 | * know if the remote device is connectable or not. However | ||
4382 | * since scan responses are merged with a previously seen | ||
4383 | * advertising report, the flags field from that report | ||
4384 | * will be used. | ||
4385 | * | ||
4386 | * In the really unlikely case that a controller get confused | ||
4387 | * and just sends a scan response event, then it is marked as | ||
4388 | * not connectable as well. | ||
4389 | */ | ||
4390 | if (type == LE_ADV_NONCONN_IND || type == LE_ADV_SCAN_IND || | ||
4391 | type == LE_ADV_SCAN_RSP) | ||
4392 | flags = MGMT_DEV_FOUND_NOT_CONNECTABLE; | ||
4393 | else | ||
4394 | flags = 0; | ||
4395 | |||
4121 | /* If there's nothing pending either store the data from this | 4396 | /* If there's nothing pending either store the data from this |
4122 | * event or send an immediate device found event if the data | 4397 | * event or send an immediate device found event if the data |
4123 | * should not be stored for later. | 4398 | * should not be stored for later. |
@@ -4128,12 +4403,12 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, | |||
4128 | */ | 4403 | */ |
4129 | if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) { | 4404 | if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) { |
4130 | store_pending_adv_report(hdev, bdaddr, bdaddr_type, | 4405 | store_pending_adv_report(hdev, bdaddr, bdaddr_type, |
4131 | rssi, data, len); | 4406 | rssi, flags, data, len); |
4132 | return; | 4407 | return; |
4133 | } | 4408 | } |
4134 | 4409 | ||
4135 | mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL, | 4410 | mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL, |
4136 | rssi, 0, 1, data, len, NULL, 0); | 4411 | rssi, flags, data, len, NULL, 0); |
4137 | return; | 4412 | return; |
4138 | } | 4413 | } |
4139 | 4414 | ||
@@ -4150,7 +4425,7 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, | |||
4150 | if (!match) | 4425 | if (!match) |
4151 | mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK, | 4426 | mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK, |
4152 | d->last_adv_addr_type, NULL, | 4427 | d->last_adv_addr_type, NULL, |
4153 | d->last_adv_rssi, 0, 1, | 4428 | d->last_adv_rssi, d->last_adv_flags, |
4154 | d->last_adv_data, | 4429 | d->last_adv_data, |
4155 | d->last_adv_data_len, NULL, 0); | 4430 | d->last_adv_data_len, NULL, 0); |
4156 | 4431 | ||
@@ -4159,7 +4434,7 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, | |||
4159 | */ | 4434 | */ |
4160 | if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) { | 4435 | if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) { |
4161 | store_pending_adv_report(hdev, bdaddr, bdaddr_type, | 4436 | store_pending_adv_report(hdev, bdaddr, bdaddr_type, |
4162 | rssi, data, len); | 4437 | rssi, flags, data, len); |
4163 | return; | 4438 | return; |
4164 | } | 4439 | } |
4165 | 4440 | ||
@@ -4168,7 +4443,7 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, | |||
4168 | */ | 4443 | */ |
4169 | clear_pending_adv_report(hdev); | 4444 | clear_pending_adv_report(hdev); |
4170 | mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL, | 4445 | mgmt_device_found(hdev, bdaddr, LE_LINK, bdaddr_type, NULL, |
4171 | rssi, 0, 1, data, len, NULL, 0); | 4446 | rssi, flags, data, len, NULL, 0); |
4172 | return; | 4447 | return; |
4173 | } | 4448 | } |
4174 | 4449 | ||
@@ -4177,8 +4452,8 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, | |||
4177 | * sending a merged device found event. | 4452 | * sending a merged device found event. |
4178 | */ | 4453 | */ |
4179 | mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK, | 4454 | mgmt_device_found(hdev, &d->last_adv_addr, LE_LINK, |
4180 | d->last_adv_addr_type, NULL, rssi, 0, 1, data, len, | 4455 | d->last_adv_addr_type, NULL, rssi, d->last_adv_flags, |
4181 | d->last_adv_data, d->last_adv_data_len); | 4456 | d->last_adv_data, d->last_adv_data_len, data, len); |
4182 | clear_pending_adv_report(hdev); | 4457 | clear_pending_adv_report(hdev); |
4183 | } | 4458 | } |
4184 | 4459 | ||
@@ -4219,7 +4494,7 @@ static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
4219 | if (conn == NULL) | 4494 | if (conn == NULL) |
4220 | goto not_found; | 4495 | goto not_found; |
4221 | 4496 | ||
4222 | ltk = hci_find_ltk(hdev, ev->ediv, ev->rand, conn->out); | 4497 | ltk = hci_find_ltk(hdev, ev->ediv, ev->rand, conn->role); |
4223 | if (ltk == NULL) | 4498 | if (ltk == NULL) |
4224 | goto not_found; | 4499 | goto not_found; |
4225 | 4500 | ||
@@ -4241,9 +4516,12 @@ static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
4241 | * distribute the keys. Later, security can be re-established | 4516 | * distribute the keys. Later, security can be re-established |
4242 | * using a distributed LTK. | 4517 | * using a distributed LTK. |
4243 | */ | 4518 | */ |
4244 | if (ltk->type == HCI_SMP_STK_SLAVE) { | 4519 | if (ltk->type == SMP_STK) { |
4520 | set_bit(HCI_CONN_STK_ENCRYPT, &conn->flags); | ||
4245 | list_del(<k->list); | 4521 | list_del(<k->list); |
4246 | kfree(ltk); | 4522 | kfree(ltk); |
4523 | } else { | ||
4524 | clear_bit(HCI_CONN_STK_ENCRYPT, &conn->flags); | ||
4247 | } | 4525 | } |
4248 | 4526 | ||
4249 | hci_dev_unlock(hdev); | 4527 | hci_dev_unlock(hdev); |
@@ -4256,6 +4534,76 @@ not_found: | |||
4256 | hci_dev_unlock(hdev); | 4534 | hci_dev_unlock(hdev); |
4257 | } | 4535 | } |
4258 | 4536 | ||
4537 | static void send_conn_param_neg_reply(struct hci_dev *hdev, u16 handle, | ||
4538 | u8 reason) | ||
4539 | { | ||
4540 | struct hci_cp_le_conn_param_req_neg_reply cp; | ||
4541 | |||
4542 | cp.handle = cpu_to_le16(handle); | ||
4543 | cp.reason = reason; | ||
4544 | |||
4545 | hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_NEG_REPLY, sizeof(cp), | ||
4546 | &cp); | ||
4547 | } | ||
4548 | |||
4549 | static void hci_le_remote_conn_param_req_evt(struct hci_dev *hdev, | ||
4550 | struct sk_buff *skb) | ||
4551 | { | ||
4552 | struct hci_ev_le_remote_conn_param_req *ev = (void *) skb->data; | ||
4553 | struct hci_cp_le_conn_param_req_reply cp; | ||
4554 | struct hci_conn *hcon; | ||
4555 | u16 handle, min, max, latency, timeout; | ||
4556 | |||
4557 | handle = le16_to_cpu(ev->handle); | ||
4558 | min = le16_to_cpu(ev->interval_min); | ||
4559 | max = le16_to_cpu(ev->interval_max); | ||
4560 | latency = le16_to_cpu(ev->latency); | ||
4561 | timeout = le16_to_cpu(ev->timeout); | ||
4562 | |||
4563 | hcon = hci_conn_hash_lookup_handle(hdev, handle); | ||
4564 | if (!hcon || hcon->state != BT_CONNECTED) | ||
4565 | return send_conn_param_neg_reply(hdev, handle, | ||
4566 | HCI_ERROR_UNKNOWN_CONN_ID); | ||
4567 | |||
4568 | if (hci_check_conn_params(min, max, latency, timeout)) | ||
4569 | return send_conn_param_neg_reply(hdev, handle, | ||
4570 | HCI_ERROR_INVALID_LL_PARAMS); | ||
4571 | |||
4572 | if (hcon->role == HCI_ROLE_MASTER) { | ||
4573 | struct hci_conn_params *params; | ||
4574 | u8 store_hint; | ||
4575 | |||
4576 | hci_dev_lock(hdev); | ||
4577 | |||
4578 | params = hci_conn_params_lookup(hdev, &hcon->dst, | ||
4579 | hcon->dst_type); | ||
4580 | if (params) { | ||
4581 | params->conn_min_interval = min; | ||
4582 | params->conn_max_interval = max; | ||
4583 | params->conn_latency = latency; | ||
4584 | params->supervision_timeout = timeout; | ||
4585 | store_hint = 0x01; | ||
4586 | } else{ | ||
4587 | store_hint = 0x00; | ||
4588 | } | ||
4589 | |||
4590 | hci_dev_unlock(hdev); | ||
4591 | |||
4592 | mgmt_new_conn_param(hdev, &hcon->dst, hcon->dst_type, | ||
4593 | store_hint, min, max, latency, timeout); | ||
4594 | } | ||
4595 | |||
4596 | cp.handle = ev->handle; | ||
4597 | cp.interval_min = ev->interval_min; | ||
4598 | cp.interval_max = ev->interval_max; | ||
4599 | cp.latency = ev->latency; | ||
4600 | cp.timeout = ev->timeout; | ||
4601 | cp.min_ce_len = 0; | ||
4602 | cp.max_ce_len = 0; | ||
4603 | |||
4604 | hci_send_cmd(hdev, HCI_OP_LE_CONN_PARAM_REQ_REPLY, sizeof(cp), &cp); | ||
4605 | } | ||
4606 | |||
4259 | static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) | 4607 | static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) |
4260 | { | 4608 | { |
4261 | struct hci_ev_le_meta *le_ev = (void *) skb->data; | 4609 | struct hci_ev_le_meta *le_ev = (void *) skb->data; |
@@ -4267,6 +4615,10 @@ static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
4267 | hci_le_conn_complete_evt(hdev, skb); | 4615 | hci_le_conn_complete_evt(hdev, skb); |
4268 | break; | 4616 | break; |
4269 | 4617 | ||
4618 | case HCI_EV_LE_CONN_UPDATE_COMPLETE: | ||
4619 | hci_le_conn_update_complete_evt(hdev, skb); | ||
4620 | break; | ||
4621 | |||
4270 | case HCI_EV_LE_ADVERTISING_REPORT: | 4622 | case HCI_EV_LE_ADVERTISING_REPORT: |
4271 | hci_le_adv_report_evt(hdev, skb); | 4623 | hci_le_adv_report_evt(hdev, skb); |
4272 | break; | 4624 | break; |
@@ -4275,6 +4627,10 @@ static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
4275 | hci_le_ltk_request_evt(hdev, skb); | 4627 | hci_le_ltk_request_evt(hdev, skb); |
4276 | break; | 4628 | break; |
4277 | 4629 | ||
4630 | case HCI_EV_LE_REMOTE_CONN_PARAM_REQ: | ||
4631 | hci_le_remote_conn_param_req_evt(hdev, skb); | ||
4632 | break; | ||
4633 | |||
4278 | default: | 4634 | default: |
4279 | break; | 4635 | break; |
4280 | } | 4636 | } |
@@ -4306,7 +4662,7 @@ void hci_event_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
4306 | /* Received events are (currently) only needed when a request is | 4662 | /* Received events are (currently) only needed when a request is |
4307 | * ongoing so avoid unnecessary memory allocation. | 4663 | * ongoing so avoid unnecessary memory allocation. |
4308 | */ | 4664 | */ |
4309 | if (hdev->req_status == HCI_REQ_PEND) { | 4665 | if (hci_req_pending(hdev)) { |
4310 | kfree_skb(hdev->recv_evt); | 4666 | kfree_skb(hdev->recv_evt); |
4311 | hdev->recv_evt = skb_clone(skb, GFP_KERNEL); | 4667 | hdev->recv_evt = skb_clone(skb, GFP_KERNEL); |
4312 | } | 4668 | } |
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 80d25c150a65..115f149362ba 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c | |||
@@ -35,13 +35,32 @@ static atomic_t monitor_promisc = ATOMIC_INIT(0); | |||
35 | 35 | ||
36 | /* ----- HCI socket interface ----- */ | 36 | /* ----- HCI socket interface ----- */ |
37 | 37 | ||
38 | /* Socket info */ | ||
39 | #define hci_pi(sk) ((struct hci_pinfo *) sk) | ||
40 | |||
41 | struct hci_pinfo { | ||
42 | struct bt_sock bt; | ||
43 | struct hci_dev *hdev; | ||
44 | struct hci_filter filter; | ||
45 | __u32 cmsg_mask; | ||
46 | unsigned short channel; | ||
47 | }; | ||
48 | |||
38 | static inline int hci_test_bit(int nr, void *addr) | 49 | static inline int hci_test_bit(int nr, void *addr) |
39 | { | 50 | { |
40 | return *((__u32 *) addr + (nr >> 5)) & ((__u32) 1 << (nr & 31)); | 51 | return *((__u32 *) addr + (nr >> 5)) & ((__u32) 1 << (nr & 31)); |
41 | } | 52 | } |
42 | 53 | ||
43 | /* Security filter */ | 54 | /* Security filter */ |
44 | static struct hci_sec_filter hci_sec_filter = { | 55 | #define HCI_SFLT_MAX_OGF 5 |
56 | |||
57 | struct hci_sec_filter { | ||
58 | __u32 type_mask; | ||
59 | __u32 event_mask[2]; | ||
60 | __u32 ocf_mask[HCI_SFLT_MAX_OGF + 1][4]; | ||
61 | }; | ||
62 | |||
63 | static const struct hci_sec_filter hci_sec_filter = { | ||
45 | /* Packet types */ | 64 | /* Packet types */ |
46 | 0x10, | 65 | 0x10, |
47 | /* Events */ | 66 | /* Events */ |
@@ -481,7 +500,7 @@ static int hci_sock_blacklist_add(struct hci_dev *hdev, void __user *arg) | |||
481 | 500 | ||
482 | hci_dev_lock(hdev); | 501 | hci_dev_lock(hdev); |
483 | 502 | ||
484 | err = hci_blacklist_add(hdev, &bdaddr, BDADDR_BREDR); | 503 | err = hci_bdaddr_list_add(&hdev->blacklist, &bdaddr, BDADDR_BREDR); |
485 | 504 | ||
486 | hci_dev_unlock(hdev); | 505 | hci_dev_unlock(hdev); |
487 | 506 | ||
@@ -498,7 +517,7 @@ static int hci_sock_blacklist_del(struct hci_dev *hdev, void __user *arg) | |||
498 | 517 | ||
499 | hci_dev_lock(hdev); | 518 | hci_dev_lock(hdev); |
500 | 519 | ||
501 | err = hci_blacklist_del(hdev, &bdaddr, BDADDR_BREDR); | 520 | err = hci_bdaddr_list_del(&hdev->blacklist, &bdaddr, BDADDR_BREDR); |
502 | 521 | ||
503 | hci_dev_unlock(hdev); | 522 | hci_dev_unlock(hdev); |
504 | 523 | ||
@@ -517,6 +536,9 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd, | |||
517 | if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) | 536 | if (test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) |
518 | return -EBUSY; | 537 | return -EBUSY; |
519 | 538 | ||
539 | if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) | ||
540 | return -EOPNOTSUPP; | ||
541 | |||
520 | if (hdev->dev_type != HCI_BREDR) | 542 | if (hdev->dev_type != HCI_BREDR) |
521 | return -EOPNOTSUPP; | 543 | return -EOPNOTSUPP; |
522 | 544 | ||
@@ -690,7 +712,8 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, | |||
690 | 712 | ||
691 | if (test_bit(HCI_UP, &hdev->flags) || | 713 | if (test_bit(HCI_UP, &hdev->flags) || |
692 | test_bit(HCI_INIT, &hdev->flags) || | 714 | test_bit(HCI_INIT, &hdev->flags) || |
693 | test_bit(HCI_SETUP, &hdev->dev_flags)) { | 715 | test_bit(HCI_SETUP, &hdev->dev_flags) || |
716 | test_bit(HCI_CONFIG, &hdev->dev_flags)) { | ||
694 | err = -EBUSY; | 717 | err = -EBUSY; |
695 | hci_dev_put(hdev); | 718 | hci_dev_put(hdev); |
696 | goto done; | 719 | goto done; |
@@ -960,7 +983,7 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
960 | goto drop; | 983 | goto drop; |
961 | } | 984 | } |
962 | 985 | ||
963 | if (test_bit(HCI_RAW, &hdev->flags) || (ogf == 0x3f)) { | 986 | if (ogf == 0x3f) { |
964 | skb_queue_tail(&hdev->raw_q, skb); | 987 | skb_queue_tail(&hdev->raw_q, skb); |
965 | queue_work(hdev->workqueue, &hdev->tx_work); | 988 | queue_work(hdev->workqueue, &hdev->tx_work); |
966 | } else { | 989 | } else { |
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index 8181ea4bc2f2..6c7ecf116e74 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
@@ -154,7 +154,7 @@ static int hidp_input_event(struct input_dev *dev, unsigned int type, | |||
154 | (!!test_bit(LED_COMPOSE, dev->led) << 3) | | 154 | (!!test_bit(LED_COMPOSE, dev->led) << 3) | |
155 | (!!test_bit(LED_SCROLLL, dev->led) << 2) | | 155 | (!!test_bit(LED_SCROLLL, dev->led) << 2) | |
156 | (!!test_bit(LED_CAPSL, dev->led) << 1) | | 156 | (!!test_bit(LED_CAPSL, dev->led) << 1) | |
157 | (!!test_bit(LED_NUML, dev->led)); | 157 | (!!test_bit(LED_NUML, dev->led) << 0); |
158 | 158 | ||
159 | if (session->leds == newleds) | 159 | if (session->leds == newleds) |
160 | return 0; | 160 | return 0; |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index 323f23cd2c37..46547b920f88 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
@@ -40,14 +40,13 @@ | |||
40 | #include "smp.h" | 40 | #include "smp.h" |
41 | #include "a2mp.h" | 41 | #include "a2mp.h" |
42 | #include "amp.h" | 42 | #include "amp.h" |
43 | #include "6lowpan.h" | ||
44 | 43 | ||
45 | #define LE_FLOWCTL_MAX_CREDITS 65535 | 44 | #define LE_FLOWCTL_MAX_CREDITS 65535 |
46 | 45 | ||
47 | bool disable_ertm; | 46 | bool disable_ertm; |
48 | 47 | ||
49 | static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN | L2CAP_FEAT_UCD; | 48 | static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN | L2CAP_FEAT_UCD; |
50 | static u8 l2cap_fixed_chan[8] = { L2CAP_FC_L2CAP | L2CAP_FC_CONNLESS, }; | 49 | static u8 l2cap_fixed_chan[8] = { L2CAP_FC_SIG_BREDR | L2CAP_FC_CONNLESS, }; |
51 | 50 | ||
52 | static LIST_HEAD(chan_list); | 51 | static LIST_HEAD(chan_list); |
53 | static DEFINE_RWLOCK(chan_list_lock); | 52 | static DEFINE_RWLOCK(chan_list_lock); |
@@ -205,6 +204,7 @@ done: | |||
205 | write_unlock(&chan_list_lock); | 204 | write_unlock(&chan_list_lock); |
206 | return err; | 205 | return err; |
207 | } | 206 | } |
207 | EXPORT_SYMBOL_GPL(l2cap_add_psm); | ||
208 | 208 | ||
209 | int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid) | 209 | int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid) |
210 | { | 210 | { |
@@ -437,6 +437,7 @@ struct l2cap_chan *l2cap_chan_create(void) | |||
437 | 437 | ||
438 | return chan; | 438 | return chan; |
439 | } | 439 | } |
440 | EXPORT_SYMBOL_GPL(l2cap_chan_create); | ||
440 | 441 | ||
441 | static void l2cap_chan_destroy(struct kref *kref) | 442 | static void l2cap_chan_destroy(struct kref *kref) |
442 | { | 443 | { |
@@ -464,6 +465,7 @@ void l2cap_chan_put(struct l2cap_chan *c) | |||
464 | 465 | ||
465 | kref_put(&c->kref, l2cap_chan_destroy); | 466 | kref_put(&c->kref, l2cap_chan_destroy); |
466 | } | 467 | } |
468 | EXPORT_SYMBOL_GPL(l2cap_chan_put); | ||
467 | 469 | ||
468 | void l2cap_chan_set_defaults(struct l2cap_chan *chan) | 470 | void l2cap_chan_set_defaults(struct l2cap_chan *chan) |
469 | { | 471 | { |
@@ -482,6 +484,7 @@ void l2cap_chan_set_defaults(struct l2cap_chan *chan) | |||
482 | 484 | ||
483 | set_bit(FLAG_FORCE_ACTIVE, &chan->flags); | 485 | set_bit(FLAG_FORCE_ACTIVE, &chan->flags); |
484 | } | 486 | } |
487 | EXPORT_SYMBOL_GPL(l2cap_chan_set_defaults); | ||
485 | 488 | ||
486 | static void l2cap_le_flowctl_init(struct l2cap_chan *chan) | 489 | static void l2cap_le_flowctl_init(struct l2cap_chan *chan) |
487 | { | 490 | { |
@@ -614,6 +617,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) | |||
614 | 617 | ||
615 | return; | 618 | return; |
616 | } | 619 | } |
620 | EXPORT_SYMBOL_GPL(l2cap_chan_del); | ||
617 | 621 | ||
618 | void l2cap_conn_update_id_addr(struct hci_conn *hcon) | 622 | void l2cap_conn_update_id_addr(struct hci_conn *hcon) |
619 | { | 623 | { |
@@ -717,6 +721,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) | |||
717 | break; | 721 | break; |
718 | } | 722 | } |
719 | } | 723 | } |
724 | EXPORT_SYMBOL(l2cap_chan_close); | ||
720 | 725 | ||
721 | static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) | 726 | static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) |
722 | { | 727 | { |
@@ -770,7 +775,7 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) | |||
770 | } | 775 | } |
771 | 776 | ||
772 | /* Service level security */ | 777 | /* Service level security */ |
773 | int l2cap_chan_check_security(struct l2cap_chan *chan) | 778 | int l2cap_chan_check_security(struct l2cap_chan *chan, bool initiator) |
774 | { | 779 | { |
775 | struct l2cap_conn *conn = chan->conn; | 780 | struct l2cap_conn *conn = chan->conn; |
776 | __u8 auth_type; | 781 | __u8 auth_type; |
@@ -780,7 +785,8 @@ int l2cap_chan_check_security(struct l2cap_chan *chan) | |||
780 | 785 | ||
781 | auth_type = l2cap_get_auth_type(chan); | 786 | auth_type = l2cap_get_auth_type(chan); |
782 | 787 | ||
783 | return hci_conn_security(conn->hcon, chan->sec_level, auth_type); | 788 | return hci_conn_security(conn->hcon, chan->sec_level, auth_type, |
789 | initiator); | ||
784 | } | 790 | } |
785 | 791 | ||
786 | static u8 l2cap_get_ident(struct l2cap_conn *conn) | 792 | static u8 l2cap_get_ident(struct l2cap_conn *conn) |
@@ -793,14 +799,14 @@ static u8 l2cap_get_ident(struct l2cap_conn *conn) | |||
793 | * 200 - 254 are used by utilities like l2ping, etc. | 799 | * 200 - 254 are used by utilities like l2ping, etc. |
794 | */ | 800 | */ |
795 | 801 | ||
796 | spin_lock(&conn->lock); | 802 | mutex_lock(&conn->ident_lock); |
797 | 803 | ||
798 | if (++conn->tx_ident > 128) | 804 | if (++conn->tx_ident > 128) |
799 | conn->tx_ident = 1; | 805 | conn->tx_ident = 1; |
800 | 806 | ||
801 | id = conn->tx_ident; | 807 | id = conn->tx_ident; |
802 | 808 | ||
803 | spin_unlock(&conn->lock); | 809 | mutex_unlock(&conn->ident_lock); |
804 | 810 | ||
805 | return id; | 811 | return id; |
806 | } | 812 | } |
@@ -1273,7 +1279,7 @@ static void l2cap_do_start(struct l2cap_chan *chan) | |||
1273 | if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) | 1279 | if (!(conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE)) |
1274 | return; | 1280 | return; |
1275 | 1281 | ||
1276 | if (l2cap_chan_check_security(chan) && | 1282 | if (l2cap_chan_check_security(chan, true) && |
1277 | __l2cap_no_conn_pending(chan)) { | 1283 | __l2cap_no_conn_pending(chan)) { |
1278 | l2cap_start_connection(chan); | 1284 | l2cap_start_connection(chan); |
1279 | } | 1285 | } |
@@ -1352,7 +1358,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) | |||
1352 | } | 1358 | } |
1353 | 1359 | ||
1354 | if (chan->state == BT_CONNECT) { | 1360 | if (chan->state == BT_CONNECT) { |
1355 | if (!l2cap_chan_check_security(chan) || | 1361 | if (!l2cap_chan_check_security(chan, true) || |
1356 | !__l2cap_no_conn_pending(chan)) { | 1362 | !__l2cap_no_conn_pending(chan)) { |
1357 | l2cap_chan_unlock(chan); | 1363 | l2cap_chan_unlock(chan); |
1358 | continue; | 1364 | continue; |
@@ -1374,7 +1380,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) | |||
1374 | rsp.scid = cpu_to_le16(chan->dcid); | 1380 | rsp.scid = cpu_to_le16(chan->dcid); |
1375 | rsp.dcid = cpu_to_le16(chan->scid); | 1381 | rsp.dcid = cpu_to_le16(chan->scid); |
1376 | 1382 | ||
1377 | if (l2cap_chan_check_security(chan)) { | 1383 | if (l2cap_chan_check_security(chan, false)) { |
1378 | if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { | 1384 | if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { |
1379 | rsp.result = cpu_to_le16(L2CAP_CR_PEND); | 1385 | rsp.result = cpu_to_le16(L2CAP_CR_PEND); |
1380 | rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND); | 1386 | rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND); |
@@ -1455,13 +1461,12 @@ static struct l2cap_chan *l2cap_global_chan_by_scid(int state, u16 cid, | |||
1455 | static void l2cap_le_conn_ready(struct l2cap_conn *conn) | 1461 | static void l2cap_le_conn_ready(struct l2cap_conn *conn) |
1456 | { | 1462 | { |
1457 | struct hci_conn *hcon = conn->hcon; | 1463 | struct hci_conn *hcon = conn->hcon; |
1464 | struct hci_dev *hdev = hcon->hdev; | ||
1458 | struct l2cap_chan *chan, *pchan; | 1465 | struct l2cap_chan *chan, *pchan; |
1459 | u8 dst_type; | 1466 | u8 dst_type; |
1460 | 1467 | ||
1461 | BT_DBG(""); | 1468 | BT_DBG(""); |
1462 | 1469 | ||
1463 | bt_6lowpan_add_conn(conn); | ||
1464 | |||
1465 | /* Check if we have socket listening on cid */ | 1470 | /* Check if we have socket listening on cid */ |
1466 | pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_ATT, | 1471 | pchan = l2cap_global_chan_by_scid(BT_LISTEN, L2CAP_CID_ATT, |
1467 | &hcon->src, &hcon->dst); | 1472 | &hcon->src, &hcon->dst); |
@@ -1475,9 +1480,28 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) | |||
1475 | dst_type = bdaddr_type(hcon, hcon->dst_type); | 1480 | dst_type = bdaddr_type(hcon, hcon->dst_type); |
1476 | 1481 | ||
1477 | /* If device is blocked, do not create a channel for it */ | 1482 | /* If device is blocked, do not create a channel for it */ |
1478 | if (hci_blacklist_lookup(hcon->hdev, &hcon->dst, dst_type)) | 1483 | if (hci_bdaddr_list_lookup(&hdev->blacklist, &hcon->dst, dst_type)) |
1479 | return; | 1484 | return; |
1480 | 1485 | ||
1486 | /* For LE slave connections, make sure the connection interval | ||
1487 | * is in the range of the minium and maximum interval that has | ||
1488 | * been configured for this connection. If not, then trigger | ||
1489 | * the connection update procedure. | ||
1490 | */ | ||
1491 | if (hcon->role == HCI_ROLE_SLAVE && | ||
1492 | (hcon->le_conn_interval < hcon->le_conn_min_interval || | ||
1493 | hcon->le_conn_interval > hcon->le_conn_max_interval)) { | ||
1494 | struct l2cap_conn_param_update_req req; | ||
1495 | |||
1496 | req.min = cpu_to_le16(hcon->le_conn_min_interval); | ||
1497 | req.max = cpu_to_le16(hcon->le_conn_max_interval); | ||
1498 | req.latency = cpu_to_le16(hcon->le_conn_latency); | ||
1499 | req.to_multiplier = cpu_to_le16(hcon->le_supv_timeout); | ||
1500 | |||
1501 | l2cap_send_cmd(conn, l2cap_get_ident(conn), | ||
1502 | L2CAP_CONN_PARAM_UPDATE_REQ, sizeof(req), &req); | ||
1503 | } | ||
1504 | |||
1481 | l2cap_chan_lock(pchan); | 1505 | l2cap_chan_lock(pchan); |
1482 | 1506 | ||
1483 | chan = pchan->ops->new_connection(pchan); | 1507 | chan = pchan->ops->new_connection(pchan); |
@@ -2118,7 +2142,8 @@ static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, | |||
2118 | struct sk_buff **frag; | 2142 | struct sk_buff **frag; |
2119 | int sent = 0; | 2143 | int sent = 0; |
2120 | 2144 | ||
2121 | if (memcpy_fromiovec(skb_put(skb, count), msg->msg_iov, count)) | 2145 | if (chan->ops->memcpy_fromiovec(chan, skb_put(skb, count), |
2146 | msg->msg_iov, count)) | ||
2122 | return -EFAULT; | 2147 | return -EFAULT; |
2123 | 2148 | ||
2124 | sent += count; | 2149 | sent += count; |
@@ -2131,18 +2156,17 @@ static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, | |||
2131 | 2156 | ||
2132 | count = min_t(unsigned int, conn->mtu, len); | 2157 | count = min_t(unsigned int, conn->mtu, len); |
2133 | 2158 | ||
2134 | tmp = chan->ops->alloc_skb(chan, count, | 2159 | tmp = chan->ops->alloc_skb(chan, 0, count, |
2135 | msg->msg_flags & MSG_DONTWAIT); | 2160 | msg->msg_flags & MSG_DONTWAIT); |
2136 | if (IS_ERR(tmp)) | 2161 | if (IS_ERR(tmp)) |
2137 | return PTR_ERR(tmp); | 2162 | return PTR_ERR(tmp); |
2138 | 2163 | ||
2139 | *frag = tmp; | 2164 | *frag = tmp; |
2140 | 2165 | ||
2141 | if (memcpy_fromiovec(skb_put(*frag, count), msg->msg_iov, count)) | 2166 | if (chan->ops->memcpy_fromiovec(chan, skb_put(*frag, count), |
2167 | msg->msg_iov, count)) | ||
2142 | return -EFAULT; | 2168 | return -EFAULT; |
2143 | 2169 | ||
2144 | (*frag)->priority = skb->priority; | ||
2145 | |||
2146 | sent += count; | 2170 | sent += count; |
2147 | len -= count; | 2171 | len -= count; |
2148 | 2172 | ||
@@ -2156,26 +2180,23 @@ static inline int l2cap_skbuff_fromiovec(struct l2cap_chan *chan, | |||
2156 | } | 2180 | } |
2157 | 2181 | ||
2158 | static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, | 2182 | static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, |
2159 | struct msghdr *msg, size_t len, | 2183 | struct msghdr *msg, size_t len) |
2160 | u32 priority) | ||
2161 | { | 2184 | { |
2162 | struct l2cap_conn *conn = chan->conn; | 2185 | struct l2cap_conn *conn = chan->conn; |
2163 | struct sk_buff *skb; | 2186 | struct sk_buff *skb; |
2164 | int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE; | 2187 | int err, count, hlen = L2CAP_HDR_SIZE + L2CAP_PSMLEN_SIZE; |
2165 | struct l2cap_hdr *lh; | 2188 | struct l2cap_hdr *lh; |
2166 | 2189 | ||
2167 | BT_DBG("chan %p psm 0x%2.2x len %zu priority %u", chan, | 2190 | BT_DBG("chan %p psm 0x%2.2x len %zu", chan, |
2168 | __le16_to_cpu(chan->psm), len, priority); | 2191 | __le16_to_cpu(chan->psm), len); |
2169 | 2192 | ||
2170 | count = min_t(unsigned int, (conn->mtu - hlen), len); | 2193 | count = min_t(unsigned int, (conn->mtu - hlen), len); |
2171 | 2194 | ||
2172 | skb = chan->ops->alloc_skb(chan, count + hlen, | 2195 | skb = chan->ops->alloc_skb(chan, hlen, count, |
2173 | msg->msg_flags & MSG_DONTWAIT); | 2196 | msg->msg_flags & MSG_DONTWAIT); |
2174 | if (IS_ERR(skb)) | 2197 | if (IS_ERR(skb)) |
2175 | return skb; | 2198 | return skb; |
2176 | 2199 | ||
2177 | skb->priority = priority; | ||
2178 | |||
2179 | /* Create L2CAP header */ | 2200 | /* Create L2CAP header */ |
2180 | lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); | 2201 | lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); |
2181 | lh->cid = cpu_to_le16(chan->dcid); | 2202 | lh->cid = cpu_to_le16(chan->dcid); |
@@ -2191,8 +2212,7 @@ static struct sk_buff *l2cap_create_connless_pdu(struct l2cap_chan *chan, | |||
2191 | } | 2212 | } |
2192 | 2213 | ||
2193 | static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, | 2214 | static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, |
2194 | struct msghdr *msg, size_t len, | 2215 | struct msghdr *msg, size_t len) |
2195 | u32 priority) | ||
2196 | { | 2216 | { |
2197 | struct l2cap_conn *conn = chan->conn; | 2217 | struct l2cap_conn *conn = chan->conn; |
2198 | struct sk_buff *skb; | 2218 | struct sk_buff *skb; |
@@ -2203,13 +2223,11 @@ static struct sk_buff *l2cap_create_basic_pdu(struct l2cap_chan *chan, | |||
2203 | 2223 | ||
2204 | count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len); | 2224 | count = min_t(unsigned int, (conn->mtu - L2CAP_HDR_SIZE), len); |
2205 | 2225 | ||
2206 | skb = chan->ops->alloc_skb(chan, count + L2CAP_HDR_SIZE, | 2226 | skb = chan->ops->alloc_skb(chan, L2CAP_HDR_SIZE, count, |
2207 | msg->msg_flags & MSG_DONTWAIT); | 2227 | msg->msg_flags & MSG_DONTWAIT); |
2208 | if (IS_ERR(skb)) | 2228 | if (IS_ERR(skb)) |
2209 | return skb; | 2229 | return skb; |
2210 | 2230 | ||
2211 | skb->priority = priority; | ||
2212 | |||
2213 | /* Create L2CAP header */ | 2231 | /* Create L2CAP header */ |
2214 | lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); | 2232 | lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); |
2215 | lh->cid = cpu_to_le16(chan->dcid); | 2233 | lh->cid = cpu_to_le16(chan->dcid); |
@@ -2247,7 +2265,7 @@ static struct sk_buff *l2cap_create_iframe_pdu(struct l2cap_chan *chan, | |||
2247 | 2265 | ||
2248 | count = min_t(unsigned int, (conn->mtu - hlen), len); | 2266 | count = min_t(unsigned int, (conn->mtu - hlen), len); |
2249 | 2267 | ||
2250 | skb = chan->ops->alloc_skb(chan, count + hlen, | 2268 | skb = chan->ops->alloc_skb(chan, hlen, count, |
2251 | msg->msg_flags & MSG_DONTWAIT); | 2269 | msg->msg_flags & MSG_DONTWAIT); |
2252 | if (IS_ERR(skb)) | 2270 | if (IS_ERR(skb)) |
2253 | return skb; | 2271 | return skb; |
@@ -2368,7 +2386,7 @@ static struct sk_buff *l2cap_create_le_flowctl_pdu(struct l2cap_chan *chan, | |||
2368 | 2386 | ||
2369 | count = min_t(unsigned int, (conn->mtu - hlen), len); | 2387 | count = min_t(unsigned int, (conn->mtu - hlen), len); |
2370 | 2388 | ||
2371 | skb = chan->ops->alloc_skb(chan, count + hlen, | 2389 | skb = chan->ops->alloc_skb(chan, hlen, count, |
2372 | msg->msg_flags & MSG_DONTWAIT); | 2390 | msg->msg_flags & MSG_DONTWAIT); |
2373 | if (IS_ERR(skb)) | 2391 | if (IS_ERR(skb)) |
2374 | return skb; | 2392 | return skb; |
@@ -2430,8 +2448,7 @@ static int l2cap_segment_le_sdu(struct l2cap_chan *chan, | |||
2430 | return 0; | 2448 | return 0; |
2431 | } | 2449 | } |
2432 | 2450 | ||
2433 | int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, | 2451 | int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len) |
2434 | u32 priority) | ||
2435 | { | 2452 | { |
2436 | struct sk_buff *skb; | 2453 | struct sk_buff *skb; |
2437 | int err; | 2454 | int err; |
@@ -2442,7 +2459,7 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, | |||
2442 | 2459 | ||
2443 | /* Connectionless channel */ | 2460 | /* Connectionless channel */ |
2444 | if (chan->chan_type == L2CAP_CHAN_CONN_LESS) { | 2461 | if (chan->chan_type == L2CAP_CHAN_CONN_LESS) { |
2445 | skb = l2cap_create_connless_pdu(chan, msg, len, priority); | 2462 | skb = l2cap_create_connless_pdu(chan, msg, len); |
2446 | if (IS_ERR(skb)) | 2463 | if (IS_ERR(skb)) |
2447 | return PTR_ERR(skb); | 2464 | return PTR_ERR(skb); |
2448 | 2465 | ||
@@ -2499,7 +2516,7 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, | |||
2499 | return -EMSGSIZE; | 2516 | return -EMSGSIZE; |
2500 | 2517 | ||
2501 | /* Create a basic PDU */ | 2518 | /* Create a basic PDU */ |
2502 | skb = l2cap_create_basic_pdu(chan, msg, len, priority); | 2519 | skb = l2cap_create_basic_pdu(chan, msg, len); |
2503 | if (IS_ERR(skb)) | 2520 | if (IS_ERR(skb)) |
2504 | return PTR_ERR(skb); | 2521 | return PTR_ERR(skb); |
2505 | 2522 | ||
@@ -2562,6 +2579,7 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, | |||
2562 | 2579 | ||
2563 | return err; | 2580 | return err; |
2564 | } | 2581 | } |
2582 | EXPORT_SYMBOL_GPL(l2cap_chan_send); | ||
2565 | 2583 | ||
2566 | static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq) | 2584 | static void l2cap_send_srej(struct l2cap_chan *chan, u16 txseq) |
2567 | { | 2585 | { |
@@ -3217,6 +3235,9 @@ done: | |||
3217 | 3235 | ||
3218 | switch (chan->mode) { | 3236 | switch (chan->mode) { |
3219 | case L2CAP_MODE_BASIC: | 3237 | case L2CAP_MODE_BASIC: |
3238 | if (disable_ertm) | ||
3239 | break; | ||
3240 | |||
3220 | if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) && | 3241 | if (!(chan->conn->feat_mask & L2CAP_FEAT_ERTM) && |
3221 | !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING)) | 3242 | !(chan->conn->feat_mask & L2CAP_FEAT_STREAMING)) |
3222 | break; | 3243 | break; |
@@ -3829,7 +3850,7 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, | |||
3829 | chan->ident = cmd->ident; | 3850 | chan->ident = cmd->ident; |
3830 | 3851 | ||
3831 | if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { | 3852 | if (conn->info_state & L2CAP_INFO_FEAT_MASK_REQ_DONE) { |
3832 | if (l2cap_chan_check_security(chan)) { | 3853 | if (l2cap_chan_check_security(chan, false)) { |
3833 | if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { | 3854 | if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { |
3834 | l2cap_state_change(chan, BT_CONNECT2); | 3855 | l2cap_state_change(chan, BT_CONNECT2); |
3835 | result = L2CAP_CR_PEND; | 3856 | result = L2CAP_CR_PEND; |
@@ -5197,27 +5218,6 @@ static inline int l2cap_move_channel_confirm_rsp(struct l2cap_conn *conn, | |||
5197 | return 0; | 5218 | return 0; |
5198 | } | 5219 | } |
5199 | 5220 | ||
5200 | static inline int l2cap_check_conn_param(u16 min, u16 max, u16 latency, | ||
5201 | u16 to_multiplier) | ||
5202 | { | ||
5203 | u16 max_latency; | ||
5204 | |||
5205 | if (min > max || min < 6 || max > 3200) | ||
5206 | return -EINVAL; | ||
5207 | |||
5208 | if (to_multiplier < 10 || to_multiplier > 3200) | ||
5209 | return -EINVAL; | ||
5210 | |||
5211 | if (max >= to_multiplier * 8) | ||
5212 | return -EINVAL; | ||
5213 | |||
5214 | max_latency = (to_multiplier * 8 / max) - 1; | ||
5215 | if (latency > 499 || latency > max_latency) | ||
5216 | return -EINVAL; | ||
5217 | |||
5218 | return 0; | ||
5219 | } | ||
5220 | |||
5221 | static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, | 5221 | static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, |
5222 | struct l2cap_cmd_hdr *cmd, | 5222 | struct l2cap_cmd_hdr *cmd, |
5223 | u16 cmd_len, u8 *data) | 5223 | u16 cmd_len, u8 *data) |
@@ -5228,7 +5228,7 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, | |||
5228 | u16 min, max, latency, to_multiplier; | 5228 | u16 min, max, latency, to_multiplier; |
5229 | int err; | 5229 | int err; |
5230 | 5230 | ||
5231 | if (!(hcon->link_mode & HCI_LM_MASTER)) | 5231 | if (hcon->role != HCI_ROLE_MASTER) |
5232 | return -EINVAL; | 5232 | return -EINVAL; |
5233 | 5233 | ||
5234 | if (cmd_len != sizeof(struct l2cap_conn_param_update_req)) | 5234 | if (cmd_len != sizeof(struct l2cap_conn_param_update_req)) |
@@ -5245,7 +5245,7 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, | |||
5245 | 5245 | ||
5246 | memset(&rsp, 0, sizeof(rsp)); | 5246 | memset(&rsp, 0, sizeof(rsp)); |
5247 | 5247 | ||
5248 | err = l2cap_check_conn_param(min, max, latency, to_multiplier); | 5248 | err = hci_check_conn_params(min, max, latency, to_multiplier); |
5249 | if (err) | 5249 | if (err) |
5250 | rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); | 5250 | rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); |
5251 | else | 5251 | else |
@@ -5254,8 +5254,16 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, | |||
5254 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, | 5254 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, |
5255 | sizeof(rsp), &rsp); | 5255 | sizeof(rsp), &rsp); |
5256 | 5256 | ||
5257 | if (!err) | 5257 | if (!err) { |
5258 | hci_le_conn_update(hcon, min, max, latency, to_multiplier); | 5258 | u8 store_hint; |
5259 | |||
5260 | store_hint = hci_le_conn_update(hcon, min, max, latency, | ||
5261 | to_multiplier); | ||
5262 | mgmt_new_conn_param(hcon->hdev, &hcon->dst, hcon->dst_type, | ||
5263 | store_hint, min, max, latency, | ||
5264 | to_multiplier); | ||
5265 | |||
5266 | } | ||
5259 | 5267 | ||
5260 | return 0; | 5268 | return 0; |
5261 | } | 5269 | } |
@@ -6879,9 +6887,6 @@ static void l2cap_att_channel(struct l2cap_conn *conn, | |||
6879 | 6887 | ||
6880 | BT_DBG("chan %p, len %d", chan, skb->len); | 6888 | BT_DBG("chan %p, len %d", chan, skb->len); |
6881 | 6889 | ||
6882 | if (hci_blacklist_lookup(hcon->hdev, &hcon->dst, hcon->dst_type)) | ||
6883 | goto drop; | ||
6884 | |||
6885 | if (chan->imtu < skb->len) | 6890 | if (chan->imtu < skb->len) |
6886 | goto drop; | 6891 | goto drop; |
6887 | 6892 | ||
@@ -6914,6 +6919,16 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) | |||
6914 | return; | 6919 | return; |
6915 | } | 6920 | } |
6916 | 6921 | ||
6922 | /* Since we can't actively block incoming LE connections we must | ||
6923 | * at least ensure that we ignore incoming data from them. | ||
6924 | */ | ||
6925 | if (hcon->type == LE_LINK && | ||
6926 | hci_bdaddr_list_lookup(&hcon->hdev->blacklist, &hcon->dst, | ||
6927 | bdaddr_type(hcon, hcon->dst_type))) { | ||
6928 | kfree_skb(skb); | ||
6929 | return; | ||
6930 | } | ||
6931 | |||
6917 | BT_DBG("len %d, cid 0x%4.4x", len, cid); | 6932 | BT_DBG("len %d, cid 0x%4.4x", len, cid); |
6918 | 6933 | ||
6919 | switch (cid) { | 6934 | switch (cid) { |
@@ -6940,10 +6955,6 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) | |||
6940 | l2cap_conn_del(conn->hcon, EACCES); | 6955 | l2cap_conn_del(conn->hcon, EACCES); |
6941 | break; | 6956 | break; |
6942 | 6957 | ||
6943 | case L2CAP_FC_6LOWPAN: | ||
6944 | bt_6lowpan_recv(conn, skb); | ||
6945 | break; | ||
6946 | |||
6947 | default: | 6958 | default: |
6948 | l2cap_data_channel(conn, cid, skb); | 6959 | l2cap_data_channel(conn, cid, skb); |
6949 | break; | 6960 | break; |
@@ -6974,7 +6985,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) | |||
6974 | if (!hchan) | 6985 | if (!hchan) |
6975 | return NULL; | 6986 | return NULL; |
6976 | 6987 | ||
6977 | conn = kzalloc(sizeof(struct l2cap_conn), GFP_KERNEL); | 6988 | conn = kzalloc(sizeof(*conn), GFP_KERNEL); |
6978 | if (!conn) { | 6989 | if (!conn) { |
6979 | hci_chan_del(hchan); | 6990 | hci_chan_del(hchan); |
6980 | return NULL; | 6991 | return NULL; |
@@ -7006,7 +7017,7 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) | |||
7006 | conn->hs_enabled = test_bit(HCI_HS_ENABLED, | 7017 | conn->hs_enabled = test_bit(HCI_HS_ENABLED, |
7007 | &hcon->hdev->dev_flags); | 7018 | &hcon->hdev->dev_flags); |
7008 | 7019 | ||
7009 | spin_lock_init(&conn->lock); | 7020 | mutex_init(&conn->ident_lock); |
7010 | mutex_init(&conn->chan_lock); | 7021 | mutex_init(&conn->chan_lock); |
7011 | 7022 | ||
7012 | INIT_LIST_HEAD(&conn->chan_l); | 7023 | INIT_LIST_HEAD(&conn->chan_l); |
@@ -7042,7 +7053,6 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | |||
7042 | struct l2cap_conn *conn; | 7053 | struct l2cap_conn *conn; |
7043 | struct hci_conn *hcon; | 7054 | struct hci_conn *hcon; |
7044 | struct hci_dev *hdev; | 7055 | struct hci_dev *hdev; |
7045 | __u8 auth_type; | ||
7046 | int err; | 7056 | int err; |
7047 | 7057 | ||
7048 | BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", &chan->src, dst, | 7058 | BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", &chan->src, dst, |
@@ -7084,7 +7094,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | |||
7084 | break; | 7094 | break; |
7085 | /* fall through */ | 7095 | /* fall through */ |
7086 | default: | 7096 | default: |
7087 | err = -ENOTSUPP; | 7097 | err = -EOPNOTSUPP; |
7088 | goto done; | 7098 | goto done; |
7089 | } | 7099 | } |
7090 | 7100 | ||
@@ -7118,9 +7128,9 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | |||
7118 | chan->psm = psm; | 7128 | chan->psm = psm; |
7119 | chan->dcid = cid; | 7129 | chan->dcid = cid; |
7120 | 7130 | ||
7121 | auth_type = l2cap_get_auth_type(chan); | ||
7122 | |||
7123 | if (bdaddr_type_is_le(dst_type)) { | 7131 | if (bdaddr_type_is_le(dst_type)) { |
7132 | u8 role; | ||
7133 | |||
7124 | /* Convert from L2CAP channel address type to HCI address type | 7134 | /* Convert from L2CAP channel address type to HCI address type |
7125 | */ | 7135 | */ |
7126 | if (dst_type == BDADDR_LE_PUBLIC) | 7136 | if (dst_type == BDADDR_LE_PUBLIC) |
@@ -7128,9 +7138,15 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | |||
7128 | else | 7138 | else |
7129 | dst_type = ADDR_LE_DEV_RANDOM; | 7139 | dst_type = ADDR_LE_DEV_RANDOM; |
7130 | 7140 | ||
7141 | if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) | ||
7142 | role = HCI_ROLE_SLAVE; | ||
7143 | else | ||
7144 | role = HCI_ROLE_MASTER; | ||
7145 | |||
7131 | hcon = hci_connect_le(hdev, dst, dst_type, chan->sec_level, | 7146 | hcon = hci_connect_le(hdev, dst, dst_type, chan->sec_level, |
7132 | auth_type); | 7147 | HCI_LE_CONN_TIMEOUT, role); |
7133 | } else { | 7148 | } else { |
7149 | u8 auth_type = l2cap_get_auth_type(chan); | ||
7134 | hcon = hci_connect_acl(hdev, dst, chan->sec_level, auth_type); | 7150 | hcon = hci_connect_acl(hdev, dst, chan->sec_level, auth_type); |
7135 | } | 7151 | } |
7136 | 7152 | ||
@@ -7176,7 +7192,7 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | |||
7176 | if (hcon->state == BT_CONNECTED) { | 7192 | if (hcon->state == BT_CONNECTED) { |
7177 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { | 7193 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { |
7178 | __clear_chan_timer(chan); | 7194 | __clear_chan_timer(chan); |
7179 | if (l2cap_chan_check_security(chan)) | 7195 | if (l2cap_chan_check_security(chan, true)) |
7180 | l2cap_state_change(chan, BT_CONNECTED); | 7196 | l2cap_state_change(chan, BT_CONNECTED); |
7181 | } else | 7197 | } else |
7182 | l2cap_do_start(chan); | 7198 | l2cap_do_start(chan); |
@@ -7190,6 +7206,7 @@ done: | |||
7190 | hci_dev_put(hdev); | 7206 | hci_dev_put(hdev); |
7191 | return err; | 7207 | return err; |
7192 | } | 7208 | } |
7209 | EXPORT_SYMBOL_GPL(l2cap_chan_connect); | ||
7193 | 7210 | ||
7194 | /* ---- L2CAP interface with lower layer (HCI) ---- */ | 7211 | /* ---- L2CAP interface with lower layer (HCI) ---- */ |
7195 | 7212 | ||
@@ -7252,8 +7269,6 @@ void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) | |||
7252 | { | 7269 | { |
7253 | BT_DBG("hcon %p reason %d", hcon, reason); | 7270 | BT_DBG("hcon %p reason %d", hcon, reason); |
7254 | 7271 | ||
7255 | bt_6lowpan_del_conn(hcon->l2cap_data); | ||
7256 | |||
7257 | l2cap_conn_del(hcon, bt_to_errno(reason)); | 7272 | l2cap_conn_del(hcon, bt_to_errno(reason)); |
7258 | } | 7273 | } |
7259 | 7274 | ||
@@ -7536,14 +7551,11 @@ int __init l2cap_init(void) | |||
7536 | debugfs_create_u16("l2cap_le_default_mps", 0644, bt_debugfs, | 7551 | debugfs_create_u16("l2cap_le_default_mps", 0644, bt_debugfs, |
7537 | &le_default_mps); | 7552 | &le_default_mps); |
7538 | 7553 | ||
7539 | bt_6lowpan_init(); | ||
7540 | |||
7541 | return 0; | 7554 | return 0; |
7542 | } | 7555 | } |
7543 | 7556 | ||
7544 | void l2cap_exit(void) | 7557 | void l2cap_exit(void) |
7545 | { | 7558 | { |
7546 | bt_6lowpan_cleanup(); | ||
7547 | debugfs_remove(l2cap_debugfs); | 7559 | debugfs_remove(l2cap_debugfs); |
7548 | l2cap_cleanup_sockets(); | 7560 | l2cap_cleanup_sockets(); |
7549 | } | 7561 | } |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index e1378693cc90..1884f72083c2 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -279,7 +279,7 @@ static int l2cap_sock_listen(struct socket *sock, int backlog) | |||
279 | break; | 279 | break; |
280 | /* fall through */ | 280 | /* fall through */ |
281 | default: | 281 | default: |
282 | err = -ENOTSUPP; | 282 | err = -EOPNOTSUPP; |
283 | goto done; | 283 | goto done; |
284 | } | 284 | } |
285 | 285 | ||
@@ -361,7 +361,8 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, | |||
361 | BT_DBG("sock %p, sk %p", sock, sk); | 361 | BT_DBG("sock %p, sk %p", sock, sk); |
362 | 362 | ||
363 | if (peer && sk->sk_state != BT_CONNECTED && | 363 | if (peer && sk->sk_state != BT_CONNECTED && |
364 | sk->sk_state != BT_CONNECT && sk->sk_state != BT_CONNECT2) | 364 | sk->sk_state != BT_CONNECT && sk->sk_state != BT_CONNECT2 && |
365 | sk->sk_state != BT_CONFIG) | ||
365 | return -ENOTCONN; | 366 | return -ENOTCONN; |
366 | 367 | ||
367 | memset(la, 0, sizeof(struct sockaddr_l2)); | 368 | memset(la, 0, sizeof(struct sockaddr_l2)); |
@@ -796,7 +797,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, | |||
796 | } else if ((sk->sk_state == BT_CONNECT2 && | 797 | } else if ((sk->sk_state == BT_CONNECT2 && |
797 | test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) || | 798 | test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) || |
798 | sk->sk_state == BT_CONNECTED) { | 799 | sk->sk_state == BT_CONNECTED) { |
799 | if (!l2cap_chan_check_security(chan)) | 800 | if (!l2cap_chan_check_security(chan, true)) |
800 | set_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags); | 801 | set_bit(BT_SK_SUSPEND, &bt_sk(sk)->flags); |
801 | else | 802 | else |
802 | sk->sk_state_change(sk); | 803 | sk->sk_state_change(sk); |
@@ -964,7 +965,7 @@ static int l2cap_sock_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
964 | return err; | 965 | return err; |
965 | 966 | ||
966 | l2cap_chan_lock(chan); | 967 | l2cap_chan_lock(chan); |
967 | err = l2cap_chan_send(chan, msg, len, sk->sk_priority); | 968 | err = l2cap_chan_send(chan, msg, len); |
968 | l2cap_chan_unlock(chan); | 969 | l2cap_chan_unlock(chan); |
969 | 970 | ||
970 | return err; | 971 | return err; |
@@ -1111,7 +1112,8 @@ static int l2cap_sock_shutdown(struct socket *sock, int how) | |||
1111 | l2cap_chan_close(chan, 0); | 1112 | l2cap_chan_close(chan, 0); |
1112 | lock_sock(sk); | 1113 | lock_sock(sk); |
1113 | 1114 | ||
1114 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) | 1115 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime && |
1116 | !(current->flags & PF_EXITING)) | ||
1115 | err = bt_sock_wait_state(sk, BT_CLOSED, | 1117 | err = bt_sock_wait_state(sk, BT_CLOSED, |
1116 | sk->sk_lingertime); | 1118 | sk->sk_lingertime); |
1117 | } | 1119 | } |
@@ -1292,6 +1294,7 @@ static void l2cap_sock_state_change_cb(struct l2cap_chan *chan, int state, | |||
1292 | } | 1294 | } |
1293 | 1295 | ||
1294 | static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan, | 1296 | static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan, |
1297 | unsigned long hdr_len, | ||
1295 | unsigned long len, int nb) | 1298 | unsigned long len, int nb) |
1296 | { | 1299 | { |
1297 | struct sock *sk = chan->data; | 1300 | struct sock *sk = chan->data; |
@@ -1299,17 +1302,26 @@ static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan, | |||
1299 | int err; | 1302 | int err; |
1300 | 1303 | ||
1301 | l2cap_chan_unlock(chan); | 1304 | l2cap_chan_unlock(chan); |
1302 | skb = bt_skb_send_alloc(sk, len, nb, &err); | 1305 | skb = bt_skb_send_alloc(sk, hdr_len + len, nb, &err); |
1303 | l2cap_chan_lock(chan); | 1306 | l2cap_chan_lock(chan); |
1304 | 1307 | ||
1305 | if (!skb) | 1308 | if (!skb) |
1306 | return ERR_PTR(err); | 1309 | return ERR_PTR(err); |
1307 | 1310 | ||
1311 | skb->priority = sk->sk_priority; | ||
1312 | |||
1308 | bt_cb(skb)->chan = chan; | 1313 | bt_cb(skb)->chan = chan; |
1309 | 1314 | ||
1310 | return skb; | 1315 | return skb; |
1311 | } | 1316 | } |
1312 | 1317 | ||
1318 | static int l2cap_sock_memcpy_fromiovec_cb(struct l2cap_chan *chan, | ||
1319 | unsigned char *kdata, | ||
1320 | struct iovec *iov, int len) | ||
1321 | { | ||
1322 | return memcpy_fromiovec(kdata, iov, len); | ||
1323 | } | ||
1324 | |||
1313 | static void l2cap_sock_ready_cb(struct l2cap_chan *chan) | 1325 | static void l2cap_sock_ready_cb(struct l2cap_chan *chan) |
1314 | { | 1326 | { |
1315 | struct sock *sk = chan->data; | 1327 | struct sock *sk = chan->data; |
@@ -1375,20 +1387,21 @@ static void l2cap_sock_suspend_cb(struct l2cap_chan *chan) | |||
1375 | sk->sk_state_change(sk); | 1387 | sk->sk_state_change(sk); |
1376 | } | 1388 | } |
1377 | 1389 | ||
1378 | static struct l2cap_ops l2cap_chan_ops = { | 1390 | static const struct l2cap_ops l2cap_chan_ops = { |
1379 | .name = "L2CAP Socket Interface", | 1391 | .name = "L2CAP Socket Interface", |
1380 | .new_connection = l2cap_sock_new_connection_cb, | 1392 | .new_connection = l2cap_sock_new_connection_cb, |
1381 | .recv = l2cap_sock_recv_cb, | 1393 | .recv = l2cap_sock_recv_cb, |
1382 | .close = l2cap_sock_close_cb, | 1394 | .close = l2cap_sock_close_cb, |
1383 | .teardown = l2cap_sock_teardown_cb, | 1395 | .teardown = l2cap_sock_teardown_cb, |
1384 | .state_change = l2cap_sock_state_change_cb, | 1396 | .state_change = l2cap_sock_state_change_cb, |
1385 | .ready = l2cap_sock_ready_cb, | 1397 | .ready = l2cap_sock_ready_cb, |
1386 | .defer = l2cap_sock_defer_cb, | 1398 | .defer = l2cap_sock_defer_cb, |
1387 | .resume = l2cap_sock_resume_cb, | 1399 | .resume = l2cap_sock_resume_cb, |
1388 | .suspend = l2cap_sock_suspend_cb, | 1400 | .suspend = l2cap_sock_suspend_cb, |
1389 | .set_shutdown = l2cap_sock_set_shutdown_cb, | 1401 | .set_shutdown = l2cap_sock_set_shutdown_cb, |
1390 | .get_sndtimeo = l2cap_sock_get_sndtimeo_cb, | 1402 | .get_sndtimeo = l2cap_sock_get_sndtimeo_cb, |
1391 | .alloc_skb = l2cap_sock_alloc_skb_cb, | 1403 | .alloc_skb = l2cap_sock_alloc_skb_cb, |
1404 | .memcpy_fromiovec = l2cap_sock_memcpy_fromiovec_cb, | ||
1392 | }; | 1405 | }; |
1393 | 1406 | ||
1394 | static void l2cap_sock_destruct(struct sock *sk) | 1407 | static void l2cap_sock_destruct(struct sock *sk) |
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index af8e0a6243b7..b8554d429d88 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
@@ -35,7 +35,7 @@ | |||
35 | #include "smp.h" | 35 | #include "smp.h" |
36 | 36 | ||
37 | #define MGMT_VERSION 1 | 37 | #define MGMT_VERSION 1 |
38 | #define MGMT_REVISION 6 | 38 | #define MGMT_REVISION 7 |
39 | 39 | ||
40 | static const u16 mgmt_commands[] = { | 40 | static const u16 mgmt_commands[] = { |
41 | MGMT_OP_READ_INDEX_LIST, | 41 | MGMT_OP_READ_INDEX_LIST, |
@@ -44,7 +44,7 @@ static const u16 mgmt_commands[] = { | |||
44 | MGMT_OP_SET_DISCOVERABLE, | 44 | MGMT_OP_SET_DISCOVERABLE, |
45 | MGMT_OP_SET_CONNECTABLE, | 45 | MGMT_OP_SET_CONNECTABLE, |
46 | MGMT_OP_SET_FAST_CONNECTABLE, | 46 | MGMT_OP_SET_FAST_CONNECTABLE, |
47 | MGMT_OP_SET_PAIRABLE, | 47 | MGMT_OP_SET_BONDABLE, |
48 | MGMT_OP_SET_LINK_SECURITY, | 48 | MGMT_OP_SET_LINK_SECURITY, |
49 | MGMT_OP_SET_SSP, | 49 | MGMT_OP_SET_SSP, |
50 | MGMT_OP_SET_HS, | 50 | MGMT_OP_SET_HS, |
@@ -85,6 +85,14 @@ static const u16 mgmt_commands[] = { | |||
85 | MGMT_OP_SET_PRIVACY, | 85 | MGMT_OP_SET_PRIVACY, |
86 | MGMT_OP_LOAD_IRKS, | 86 | MGMT_OP_LOAD_IRKS, |
87 | MGMT_OP_GET_CONN_INFO, | 87 | MGMT_OP_GET_CONN_INFO, |
88 | MGMT_OP_GET_CLOCK_INFO, | ||
89 | MGMT_OP_ADD_DEVICE, | ||
90 | MGMT_OP_REMOVE_DEVICE, | ||
91 | MGMT_OP_LOAD_CONN_PARAM, | ||
92 | MGMT_OP_READ_UNCONF_INDEX_LIST, | ||
93 | MGMT_OP_READ_CONFIG_INFO, | ||
94 | MGMT_OP_SET_EXTERNAL_CONFIG, | ||
95 | MGMT_OP_SET_PUBLIC_ADDRESS, | ||
88 | }; | 96 | }; |
89 | 97 | ||
90 | static const u16 mgmt_events[] = { | 98 | static const u16 mgmt_events[] = { |
@@ -111,6 +119,12 @@ static const u16 mgmt_events[] = { | |||
111 | MGMT_EV_PASSKEY_NOTIFY, | 119 | MGMT_EV_PASSKEY_NOTIFY, |
112 | MGMT_EV_NEW_IRK, | 120 | MGMT_EV_NEW_IRK, |
113 | MGMT_EV_NEW_CSRK, | 121 | MGMT_EV_NEW_CSRK, |
122 | MGMT_EV_DEVICE_ADDED, | ||
123 | MGMT_EV_DEVICE_REMOVED, | ||
124 | MGMT_EV_NEW_CONN_PARAM, | ||
125 | MGMT_EV_UNCONF_INDEX_ADDED, | ||
126 | MGMT_EV_UNCONF_INDEX_REMOVED, | ||
127 | MGMT_EV_NEW_CONFIG_OPTIONS, | ||
114 | }; | 128 | }; |
115 | 129 | ||
116 | #define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000) | 130 | #define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000) |
@@ -200,6 +214,36 @@ static u8 mgmt_status(u8 hci_status) | |||
200 | return MGMT_STATUS_FAILED; | 214 | return MGMT_STATUS_FAILED; |
201 | } | 215 | } |
202 | 216 | ||
217 | static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len, | ||
218 | struct sock *skip_sk) | ||
219 | { | ||
220 | struct sk_buff *skb; | ||
221 | struct mgmt_hdr *hdr; | ||
222 | |||
223 | skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL); | ||
224 | if (!skb) | ||
225 | return -ENOMEM; | ||
226 | |||
227 | hdr = (void *) skb_put(skb, sizeof(*hdr)); | ||
228 | hdr->opcode = cpu_to_le16(event); | ||
229 | if (hdev) | ||
230 | hdr->index = cpu_to_le16(hdev->id); | ||
231 | else | ||
232 | hdr->index = cpu_to_le16(MGMT_INDEX_NONE); | ||
233 | hdr->len = cpu_to_le16(data_len); | ||
234 | |||
235 | if (data) | ||
236 | memcpy(skb_put(skb, data_len), data, data_len); | ||
237 | |||
238 | /* Time stamp */ | ||
239 | __net_timestamp(skb); | ||
240 | |||
241 | hci_send_to_control(skb, skip_sk); | ||
242 | kfree_skb(skb); | ||
243 | |||
244 | return 0; | ||
245 | } | ||
246 | |||
203 | static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status) | 247 | static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status) |
204 | { | 248 | { |
205 | struct sk_buff *skb; | 249 | struct sk_buff *skb; |
@@ -327,7 +371,8 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, | |||
327 | 371 | ||
328 | count = 0; | 372 | count = 0; |
329 | list_for_each_entry(d, &hci_dev_list, list) { | 373 | list_for_each_entry(d, &hci_dev_list, list) { |
330 | if (d->dev_type == HCI_BREDR) | 374 | if (d->dev_type == HCI_BREDR && |
375 | !test_bit(HCI_UNCONFIGURED, &d->dev_flags)) | ||
331 | count++; | 376 | count++; |
332 | } | 377 | } |
333 | 378 | ||
@@ -340,13 +385,19 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, | |||
340 | 385 | ||
341 | count = 0; | 386 | count = 0; |
342 | list_for_each_entry(d, &hci_dev_list, list) { | 387 | list_for_each_entry(d, &hci_dev_list, list) { |
343 | if (test_bit(HCI_SETUP, &d->dev_flags)) | 388 | if (test_bit(HCI_SETUP, &d->dev_flags) || |
389 | test_bit(HCI_CONFIG, &d->dev_flags) || | ||
390 | test_bit(HCI_USER_CHANNEL, &d->dev_flags)) | ||
344 | continue; | 391 | continue; |
345 | 392 | ||
346 | if (test_bit(HCI_USER_CHANNEL, &d->dev_flags)) | 393 | /* Devices marked as raw-only are neither configured |
394 | * nor unconfigured controllers. | ||
395 | */ | ||
396 | if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks)) | ||
347 | continue; | 397 | continue; |
348 | 398 | ||
349 | if (d->dev_type == HCI_BREDR) { | 399 | if (d->dev_type == HCI_BREDR && |
400 | !test_bit(HCI_UNCONFIGURED, &d->dev_flags)) { | ||
350 | rp->index[count++] = cpu_to_le16(d->id); | 401 | rp->index[count++] = cpu_to_le16(d->id); |
351 | BT_DBG("Added hci%u", d->id); | 402 | BT_DBG("Added hci%u", d->id); |
352 | } | 403 | } |
@@ -365,19 +416,151 @@ static int read_index_list(struct sock *sk, struct hci_dev *hdev, void *data, | |||
365 | return err; | 416 | return err; |
366 | } | 417 | } |
367 | 418 | ||
419 | static int read_unconf_index_list(struct sock *sk, struct hci_dev *hdev, | ||
420 | void *data, u16 data_len) | ||
421 | { | ||
422 | struct mgmt_rp_read_unconf_index_list *rp; | ||
423 | struct hci_dev *d; | ||
424 | size_t rp_len; | ||
425 | u16 count; | ||
426 | int err; | ||
427 | |||
428 | BT_DBG("sock %p", sk); | ||
429 | |||
430 | read_lock(&hci_dev_list_lock); | ||
431 | |||
432 | count = 0; | ||
433 | list_for_each_entry(d, &hci_dev_list, list) { | ||
434 | if (d->dev_type == HCI_BREDR && | ||
435 | test_bit(HCI_UNCONFIGURED, &d->dev_flags)) | ||
436 | count++; | ||
437 | } | ||
438 | |||
439 | rp_len = sizeof(*rp) + (2 * count); | ||
440 | rp = kmalloc(rp_len, GFP_ATOMIC); | ||
441 | if (!rp) { | ||
442 | read_unlock(&hci_dev_list_lock); | ||
443 | return -ENOMEM; | ||
444 | } | ||
445 | |||
446 | count = 0; | ||
447 | list_for_each_entry(d, &hci_dev_list, list) { | ||
448 | if (test_bit(HCI_SETUP, &d->dev_flags) || | ||
449 | test_bit(HCI_CONFIG, &d->dev_flags) || | ||
450 | test_bit(HCI_USER_CHANNEL, &d->dev_flags)) | ||
451 | continue; | ||
452 | |||
453 | /* Devices marked as raw-only are neither configured | ||
454 | * nor unconfigured controllers. | ||
455 | */ | ||
456 | if (test_bit(HCI_QUIRK_RAW_DEVICE, &d->quirks)) | ||
457 | continue; | ||
458 | |||
459 | if (d->dev_type == HCI_BREDR && | ||
460 | test_bit(HCI_UNCONFIGURED, &d->dev_flags)) { | ||
461 | rp->index[count++] = cpu_to_le16(d->id); | ||
462 | BT_DBG("Added hci%u", d->id); | ||
463 | } | ||
464 | } | ||
465 | |||
466 | rp->num_controllers = cpu_to_le16(count); | ||
467 | rp_len = sizeof(*rp) + (2 * count); | ||
468 | |||
469 | read_unlock(&hci_dev_list_lock); | ||
470 | |||
471 | err = cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_UNCONF_INDEX_LIST, | ||
472 | 0, rp, rp_len); | ||
473 | |||
474 | kfree(rp); | ||
475 | |||
476 | return err; | ||
477 | } | ||
478 | |||
479 | static bool is_configured(struct hci_dev *hdev) | ||
480 | { | ||
481 | if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) && | ||
482 | !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags)) | ||
483 | return false; | ||
484 | |||
485 | if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) && | ||
486 | !bacmp(&hdev->public_addr, BDADDR_ANY)) | ||
487 | return false; | ||
488 | |||
489 | return true; | ||
490 | } | ||
491 | |||
492 | static __le32 get_missing_options(struct hci_dev *hdev) | ||
493 | { | ||
494 | u32 options = 0; | ||
495 | |||
496 | if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) && | ||
497 | !test_bit(HCI_EXT_CONFIGURED, &hdev->dev_flags)) | ||
498 | options |= MGMT_OPTION_EXTERNAL_CONFIG; | ||
499 | |||
500 | if (test_bit(HCI_QUIRK_INVALID_BDADDR, &hdev->quirks) && | ||
501 | !bacmp(&hdev->public_addr, BDADDR_ANY)) | ||
502 | options |= MGMT_OPTION_PUBLIC_ADDRESS; | ||
503 | |||
504 | return cpu_to_le32(options); | ||
505 | } | ||
506 | |||
507 | static int new_options(struct hci_dev *hdev, struct sock *skip) | ||
508 | { | ||
509 | __le32 options = get_missing_options(hdev); | ||
510 | |||
511 | return mgmt_event(MGMT_EV_NEW_CONFIG_OPTIONS, hdev, &options, | ||
512 | sizeof(options), skip); | ||
513 | } | ||
514 | |||
515 | static int send_options_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev) | ||
516 | { | ||
517 | __le32 options = get_missing_options(hdev); | ||
518 | |||
519 | return cmd_complete(sk, hdev->id, opcode, 0, &options, | ||
520 | sizeof(options)); | ||
521 | } | ||
522 | |||
523 | static int read_config_info(struct sock *sk, struct hci_dev *hdev, | ||
524 | void *data, u16 data_len) | ||
525 | { | ||
526 | struct mgmt_rp_read_config_info rp; | ||
527 | u32 options = 0; | ||
528 | |||
529 | BT_DBG("sock %p %s", sk, hdev->name); | ||
530 | |||
531 | hci_dev_lock(hdev); | ||
532 | |||
533 | memset(&rp, 0, sizeof(rp)); | ||
534 | rp.manufacturer = cpu_to_le16(hdev->manufacturer); | ||
535 | |||
536 | if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks)) | ||
537 | options |= MGMT_OPTION_EXTERNAL_CONFIG; | ||
538 | |||
539 | if (hdev->set_bdaddr) | ||
540 | options |= MGMT_OPTION_PUBLIC_ADDRESS; | ||
541 | |||
542 | rp.supported_options = cpu_to_le32(options); | ||
543 | rp.missing_options = get_missing_options(hdev); | ||
544 | |||
545 | hci_dev_unlock(hdev); | ||
546 | |||
547 | return cmd_complete(sk, hdev->id, MGMT_OP_READ_CONFIG_INFO, 0, &rp, | ||
548 | sizeof(rp)); | ||
549 | } | ||
550 | |||
368 | static u32 get_supported_settings(struct hci_dev *hdev) | 551 | static u32 get_supported_settings(struct hci_dev *hdev) |
369 | { | 552 | { |
370 | u32 settings = 0; | 553 | u32 settings = 0; |
371 | 554 | ||
372 | settings |= MGMT_SETTING_POWERED; | 555 | settings |= MGMT_SETTING_POWERED; |
373 | settings |= MGMT_SETTING_PAIRABLE; | 556 | settings |= MGMT_SETTING_BONDABLE; |
374 | settings |= MGMT_SETTING_DEBUG_KEYS; | 557 | settings |= MGMT_SETTING_DEBUG_KEYS; |
558 | settings |= MGMT_SETTING_CONNECTABLE; | ||
559 | settings |= MGMT_SETTING_DISCOVERABLE; | ||
375 | 560 | ||
376 | if (lmp_bredr_capable(hdev)) { | 561 | if (lmp_bredr_capable(hdev)) { |
377 | settings |= MGMT_SETTING_CONNECTABLE; | ||
378 | if (hdev->hci_ver >= BLUETOOTH_VER_1_2) | 562 | if (hdev->hci_ver >= BLUETOOTH_VER_1_2) |
379 | settings |= MGMT_SETTING_FAST_CONNECTABLE; | 563 | settings |= MGMT_SETTING_FAST_CONNECTABLE; |
380 | settings |= MGMT_SETTING_DISCOVERABLE; | ||
381 | settings |= MGMT_SETTING_BREDR; | 564 | settings |= MGMT_SETTING_BREDR; |
382 | settings |= MGMT_SETTING_LINK_SECURITY; | 565 | settings |= MGMT_SETTING_LINK_SECURITY; |
383 | 566 | ||
@@ -387,7 +570,7 @@ static u32 get_supported_settings(struct hci_dev *hdev) | |||
387 | } | 570 | } |
388 | 571 | ||
389 | if (lmp_sc_capable(hdev) || | 572 | if (lmp_sc_capable(hdev) || |
390 | test_bit(HCI_FORCE_SC, &hdev->dev_flags)) | 573 | test_bit(HCI_FORCE_SC, &hdev->dbg_flags)) |
391 | settings |= MGMT_SETTING_SECURE_CONN; | 574 | settings |= MGMT_SETTING_SECURE_CONN; |
392 | } | 575 | } |
393 | 576 | ||
@@ -397,6 +580,10 @@ static u32 get_supported_settings(struct hci_dev *hdev) | |||
397 | settings |= MGMT_SETTING_PRIVACY; | 580 | settings |= MGMT_SETTING_PRIVACY; |
398 | } | 581 | } |
399 | 582 | ||
583 | if (test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks) || | ||
584 | hdev->set_bdaddr) | ||
585 | settings |= MGMT_SETTING_CONFIGURATION; | ||
586 | |||
400 | return settings; | 587 | return settings; |
401 | } | 588 | } |
402 | 589 | ||
@@ -416,8 +603,8 @@ static u32 get_current_settings(struct hci_dev *hdev) | |||
416 | if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) | 603 | if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) |
417 | settings |= MGMT_SETTING_DISCOVERABLE; | 604 | settings |= MGMT_SETTING_DISCOVERABLE; |
418 | 605 | ||
419 | if (test_bit(HCI_PAIRABLE, &hdev->dev_flags)) | 606 | if (test_bit(HCI_BONDABLE, &hdev->dev_flags)) |
420 | settings |= MGMT_SETTING_PAIRABLE; | 607 | settings |= MGMT_SETTING_BONDABLE; |
421 | 608 | ||
422 | if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) | 609 | if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) |
423 | settings |= MGMT_SETTING_BREDR; | 610 | settings |= MGMT_SETTING_BREDR; |
@@ -440,7 +627,7 @@ static u32 get_current_settings(struct hci_dev *hdev) | |||
440 | if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) | 627 | if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) |
441 | settings |= MGMT_SETTING_SECURE_CONN; | 628 | settings |= MGMT_SETTING_SECURE_CONN; |
442 | 629 | ||
443 | if (test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags)) | 630 | if (test_bit(HCI_KEEP_DEBUG_KEYS, &hdev->dev_flags)) |
444 | settings |= MGMT_SETTING_DEBUG_KEYS; | 631 | settings |= MGMT_SETTING_DEBUG_KEYS; |
445 | 632 | ||
446 | if (test_bit(HCI_PRIVACY, &hdev->dev_flags)) | 633 | if (test_bit(HCI_PRIVACY, &hdev->dev_flags)) |
@@ -571,6 +758,22 @@ static struct pending_cmd *mgmt_pending_find(u16 opcode, struct hci_dev *hdev) | |||
571 | return NULL; | 758 | return NULL; |
572 | } | 759 | } |
573 | 760 | ||
761 | static struct pending_cmd *mgmt_pending_find_data(u16 opcode, | ||
762 | struct hci_dev *hdev, | ||
763 | const void *data) | ||
764 | { | ||
765 | struct pending_cmd *cmd; | ||
766 | |||
767 | list_for_each_entry(cmd, &hdev->mgmt_pending, list) { | ||
768 | if (cmd->user_data != data) | ||
769 | continue; | ||
770 | if (cmd->opcode == opcode) | ||
771 | return cmd; | ||
772 | } | ||
773 | |||
774 | return NULL; | ||
775 | } | ||
776 | |||
574 | static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr) | 777 | static u8 create_scan_rsp_data(struct hci_dev *hdev, u8 *ptr) |
575 | { | 778 | { |
576 | u8 ad_len = 0; | 779 | u8 ad_len = 0; |
@@ -703,6 +906,16 @@ static void update_adv_data(struct hci_request *req) | |||
703 | hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp); | 906 | hci_req_add(req, HCI_OP_LE_SET_ADV_DATA, sizeof(cp), &cp); |
704 | } | 907 | } |
705 | 908 | ||
909 | int mgmt_update_adv_data(struct hci_dev *hdev) | ||
910 | { | ||
911 | struct hci_request req; | ||
912 | |||
913 | hci_req_init(&req, hdev); | ||
914 | update_adv_data(&req); | ||
915 | |||
916 | return hci_req_run(&req, NULL); | ||
917 | } | ||
918 | |||
706 | static void create_eir(struct hci_dev *hdev, u8 *data) | 919 | static void create_eir(struct hci_dev *hdev, u8 *data) |
707 | { | 920 | { |
708 | u8 *ptr = data; | 921 | u8 *ptr = data; |
@@ -836,6 +1049,13 @@ static bool get_connectable(struct hci_dev *hdev) | |||
836 | return test_bit(HCI_CONNECTABLE, &hdev->dev_flags); | 1049 | return test_bit(HCI_CONNECTABLE, &hdev->dev_flags); |
837 | } | 1050 | } |
838 | 1051 | ||
1052 | static void disable_advertising(struct hci_request *req) | ||
1053 | { | ||
1054 | u8 enable = 0x00; | ||
1055 | |||
1056 | hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable); | ||
1057 | } | ||
1058 | |||
839 | static void enable_advertising(struct hci_request *req) | 1059 | static void enable_advertising(struct hci_request *req) |
840 | { | 1060 | { |
841 | struct hci_dev *hdev = req->hdev; | 1061 | struct hci_dev *hdev = req->hdev; |
@@ -843,12 +1063,18 @@ static void enable_advertising(struct hci_request *req) | |||
843 | u8 own_addr_type, enable = 0x01; | 1063 | u8 own_addr_type, enable = 0x01; |
844 | bool connectable; | 1064 | bool connectable; |
845 | 1065 | ||
846 | /* Clear the HCI_ADVERTISING bit temporarily so that the | 1066 | if (hci_conn_num(hdev, LE_LINK) > 0) |
1067 | return; | ||
1068 | |||
1069 | if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) | ||
1070 | disable_advertising(req); | ||
1071 | |||
1072 | /* Clear the HCI_LE_ADV bit temporarily so that the | ||
847 | * hci_update_random_address knows that it's safe to go ahead | 1073 | * hci_update_random_address knows that it's safe to go ahead |
848 | * and write a new random address. The flag will be set back on | 1074 | * and write a new random address. The flag will be set back on |
849 | * as soon as the SET_ADV_ENABLE HCI command completes. | 1075 | * as soon as the SET_ADV_ENABLE HCI command completes. |
850 | */ | 1076 | */ |
851 | clear_bit(HCI_ADVERTISING, &hdev->dev_flags); | 1077 | clear_bit(HCI_LE_ADV, &hdev->dev_flags); |
852 | 1078 | ||
853 | connectable = get_connectable(hdev); | 1079 | connectable = get_connectable(hdev); |
854 | 1080 | ||
@@ -860,8 +1086,8 @@ static void enable_advertising(struct hci_request *req) | |||
860 | return; | 1086 | return; |
861 | 1087 | ||
862 | memset(&cp, 0, sizeof(cp)); | 1088 | memset(&cp, 0, sizeof(cp)); |
863 | cp.min_interval = cpu_to_le16(0x0800); | 1089 | cp.min_interval = cpu_to_le16(hdev->le_adv_min_interval); |
864 | cp.max_interval = cpu_to_le16(0x0800); | 1090 | cp.max_interval = cpu_to_le16(hdev->le_adv_max_interval); |
865 | cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND; | 1091 | cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND; |
866 | cp.own_address_type = own_addr_type; | 1092 | cp.own_address_type = own_addr_type; |
867 | cp.channel_map = hdev->le_adv_channel_map; | 1093 | cp.channel_map = hdev->le_adv_channel_map; |
@@ -871,13 +1097,6 @@ static void enable_advertising(struct hci_request *req) | |||
871 | hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable); | 1097 | hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable); |
872 | } | 1098 | } |
873 | 1099 | ||
874 | static void disable_advertising(struct hci_request *req) | ||
875 | { | ||
876 | u8 enable = 0x00; | ||
877 | |||
878 | hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable); | ||
879 | } | ||
880 | |||
881 | static void service_cache_off(struct work_struct *work) | 1100 | static void service_cache_off(struct work_struct *work) |
882 | { | 1101 | { |
883 | struct hci_dev *hdev = container_of(work, struct hci_dev, | 1102 | struct hci_dev *hdev = container_of(work, struct hci_dev, |
@@ -909,19 +1128,14 @@ static void rpa_expired(struct work_struct *work) | |||
909 | 1128 | ||
910 | set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags); | 1129 | set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags); |
911 | 1130 | ||
912 | if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags) || | 1131 | if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags)) |
913 | hci_conn_num(hdev, LE_LINK) > 0) | ||
914 | return; | 1132 | return; |
915 | 1133 | ||
916 | /* The generation of a new RPA and programming it into the | 1134 | /* The generation of a new RPA and programming it into the |
917 | * controller happens in the enable_advertising() function. | 1135 | * controller happens in the enable_advertising() function. |
918 | */ | 1136 | */ |
919 | |||
920 | hci_req_init(&req, hdev); | 1137 | hci_req_init(&req, hdev); |
921 | |||
922 | disable_advertising(&req); | ||
923 | enable_advertising(&req); | 1138 | enable_advertising(&req); |
924 | |||
925 | hci_req_run(&req, NULL); | 1139 | hci_req_run(&req, NULL); |
926 | } | 1140 | } |
927 | 1141 | ||
@@ -938,7 +1152,7 @@ static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev) | |||
938 | * for mgmt we require user-space to explicitly enable | 1152 | * for mgmt we require user-space to explicitly enable |
939 | * it | 1153 | * it |
940 | */ | 1154 | */ |
941 | clear_bit(HCI_PAIRABLE, &hdev->dev_flags); | 1155 | clear_bit(HCI_BONDABLE, &hdev->dev_flags); |
942 | } | 1156 | } |
943 | 1157 | ||
944 | static int read_controller_info(struct sock *sk, struct hci_dev *hdev, | 1158 | static int read_controller_info(struct sock *sk, struct hci_dev *hdev, |
@@ -984,7 +1198,7 @@ static struct pending_cmd *mgmt_pending_add(struct sock *sk, u16 opcode, | |||
984 | { | 1198 | { |
985 | struct pending_cmd *cmd; | 1199 | struct pending_cmd *cmd; |
986 | 1200 | ||
987 | cmd = kmalloc(sizeof(*cmd), GFP_KERNEL); | 1201 | cmd = kzalloc(sizeof(*cmd), GFP_KERNEL); |
988 | if (!cmd) | 1202 | if (!cmd) |
989 | return NULL; | 1203 | return NULL; |
990 | 1204 | ||
@@ -1047,7 +1261,7 @@ static void clean_up_hci_complete(struct hci_dev *hdev, u8 status) | |||
1047 | } | 1261 | } |
1048 | } | 1262 | } |
1049 | 1263 | ||
1050 | static void hci_stop_discovery(struct hci_request *req) | 1264 | static bool hci_stop_discovery(struct hci_request *req) |
1051 | { | 1265 | { |
1052 | struct hci_dev *hdev = req->hdev; | 1266 | struct hci_dev *hdev = req->hdev; |
1053 | struct hci_cp_remote_name_req_cancel cp; | 1267 | struct hci_cp_remote_name_req_cancel cp; |
@@ -1062,32 +1276,39 @@ static void hci_stop_discovery(struct hci_request *req) | |||
1062 | hci_req_add_le_scan_disable(req); | 1276 | hci_req_add_le_scan_disable(req); |
1063 | } | 1277 | } |
1064 | 1278 | ||
1065 | break; | 1279 | return true; |
1066 | 1280 | ||
1067 | case DISCOVERY_RESOLVING: | 1281 | case DISCOVERY_RESOLVING: |
1068 | e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, | 1282 | e = hci_inquiry_cache_lookup_resolve(hdev, BDADDR_ANY, |
1069 | NAME_PENDING); | 1283 | NAME_PENDING); |
1070 | if (!e) | 1284 | if (!e) |
1071 | return; | 1285 | break; |
1072 | 1286 | ||
1073 | bacpy(&cp.bdaddr, &e->data.bdaddr); | 1287 | bacpy(&cp.bdaddr, &e->data.bdaddr); |
1074 | hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp), | 1288 | hci_req_add(req, HCI_OP_REMOTE_NAME_REQ_CANCEL, sizeof(cp), |
1075 | &cp); | 1289 | &cp); |
1076 | 1290 | ||
1077 | break; | 1291 | return true; |
1078 | 1292 | ||
1079 | default: | 1293 | default: |
1080 | /* Passive scanning */ | 1294 | /* Passive scanning */ |
1081 | if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) | 1295 | if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) { |
1082 | hci_req_add_le_scan_disable(req); | 1296 | hci_req_add_le_scan_disable(req); |
1297 | return true; | ||
1298 | } | ||
1299 | |||
1083 | break; | 1300 | break; |
1084 | } | 1301 | } |
1302 | |||
1303 | return false; | ||
1085 | } | 1304 | } |
1086 | 1305 | ||
1087 | static int clean_up_hci_state(struct hci_dev *hdev) | 1306 | static int clean_up_hci_state(struct hci_dev *hdev) |
1088 | { | 1307 | { |
1089 | struct hci_request req; | 1308 | struct hci_request req; |
1090 | struct hci_conn *conn; | 1309 | struct hci_conn *conn; |
1310 | bool discov_stopped; | ||
1311 | int err; | ||
1091 | 1312 | ||
1092 | hci_req_init(&req, hdev); | 1313 | hci_req_init(&req, hdev); |
1093 | 1314 | ||
@@ -1097,10 +1318,10 @@ static int clean_up_hci_state(struct hci_dev *hdev) | |||
1097 | hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | 1318 | hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); |
1098 | } | 1319 | } |
1099 | 1320 | ||
1100 | if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) | 1321 | if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) |
1101 | disable_advertising(&req); | 1322 | disable_advertising(&req); |
1102 | 1323 | ||
1103 | hci_stop_discovery(&req); | 1324 | discov_stopped = hci_stop_discovery(&req); |
1104 | 1325 | ||
1105 | list_for_each_entry(conn, &hdev->conn_hash.list, list) { | 1326 | list_for_each_entry(conn, &hdev->conn_hash.list, list) { |
1106 | struct hci_cp_disconnect dc; | 1327 | struct hci_cp_disconnect dc; |
@@ -1134,7 +1355,11 @@ static int clean_up_hci_state(struct hci_dev *hdev) | |||
1134 | } | 1355 | } |
1135 | } | 1356 | } |
1136 | 1357 | ||
1137 | return hci_req_run(&req, clean_up_hci_complete); | 1358 | err = hci_req_run(&req, clean_up_hci_complete); |
1359 | if (!err && discov_stopped) | ||
1360 | hci_discovery_set_state(hdev, DISCOVERY_STOPPING); | ||
1361 | |||
1362 | return err; | ||
1138 | } | 1363 | } |
1139 | 1364 | ||
1140 | static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data, | 1365 | static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data, |
@@ -1203,36 +1428,6 @@ failed: | |||
1203 | return err; | 1428 | return err; |
1204 | } | 1429 | } |
1205 | 1430 | ||
1206 | static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len, | ||
1207 | struct sock *skip_sk) | ||
1208 | { | ||
1209 | struct sk_buff *skb; | ||
1210 | struct mgmt_hdr *hdr; | ||
1211 | |||
1212 | skb = alloc_skb(sizeof(*hdr) + data_len, GFP_KERNEL); | ||
1213 | if (!skb) | ||
1214 | return -ENOMEM; | ||
1215 | |||
1216 | hdr = (void *) skb_put(skb, sizeof(*hdr)); | ||
1217 | hdr->opcode = cpu_to_le16(event); | ||
1218 | if (hdev) | ||
1219 | hdr->index = cpu_to_le16(hdev->id); | ||
1220 | else | ||
1221 | hdr->index = cpu_to_le16(MGMT_INDEX_NONE); | ||
1222 | hdr->len = cpu_to_le16(data_len); | ||
1223 | |||
1224 | if (data) | ||
1225 | memcpy(skb_put(skb, data_len), data, data_len); | ||
1226 | |||
1227 | /* Time stamp */ | ||
1228 | __net_timestamp(skb); | ||
1229 | |||
1230 | hci_send_to_control(skb, skip_sk); | ||
1231 | kfree_skb(skb); | ||
1232 | |||
1233 | return 0; | ||
1234 | } | ||
1235 | |||
1236 | static int new_settings(struct hci_dev *hdev, struct sock *skip) | 1431 | static int new_settings(struct hci_dev *hdev, struct sock *skip) |
1237 | { | 1432 | { |
1238 | __le32 ev; | 1433 | __le32 ev; |
@@ -1242,6 +1437,11 @@ static int new_settings(struct hci_dev *hdev, struct sock *skip) | |||
1242 | return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip); | 1437 | return mgmt_event(MGMT_EV_NEW_SETTINGS, hdev, &ev, sizeof(ev), skip); |
1243 | } | 1438 | } |
1244 | 1439 | ||
1440 | int mgmt_new_settings(struct hci_dev *hdev) | ||
1441 | { | ||
1442 | return new_settings(hdev, NULL); | ||
1443 | } | ||
1444 | |||
1245 | struct cmd_lookup { | 1445 | struct cmd_lookup { |
1246 | struct sock *sk; | 1446 | struct sock *sk; |
1247 | struct hci_dev *hdev; | 1447 | struct hci_dev *hdev; |
@@ -1553,7 +1753,7 @@ static void set_connectable_complete(struct hci_dev *hdev, u8 status) | |||
1553 | { | 1753 | { |
1554 | struct pending_cmd *cmd; | 1754 | struct pending_cmd *cmd; |
1555 | struct mgmt_mode *cp; | 1755 | struct mgmt_mode *cp; |
1556 | bool changed; | 1756 | bool conn_changed, discov_changed; |
1557 | 1757 | ||
1558 | BT_DBG("status 0x%02x", status); | 1758 | BT_DBG("status 0x%02x", status); |
1559 | 1759 | ||
@@ -1570,15 +1770,25 @@ static void set_connectable_complete(struct hci_dev *hdev, u8 status) | |||
1570 | } | 1770 | } |
1571 | 1771 | ||
1572 | cp = cmd->param; | 1772 | cp = cmd->param; |
1573 | if (cp->val) | 1773 | if (cp->val) { |
1574 | changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags); | 1774 | conn_changed = !test_and_set_bit(HCI_CONNECTABLE, |
1575 | else | 1775 | &hdev->dev_flags); |
1576 | changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags); | 1776 | discov_changed = false; |
1777 | } else { | ||
1778 | conn_changed = test_and_clear_bit(HCI_CONNECTABLE, | ||
1779 | &hdev->dev_flags); | ||
1780 | discov_changed = test_and_clear_bit(HCI_DISCOVERABLE, | ||
1781 | &hdev->dev_flags); | ||
1782 | } | ||
1577 | 1783 | ||
1578 | send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev); | 1784 | send_settings_rsp(cmd->sk, MGMT_OP_SET_CONNECTABLE, hdev); |
1579 | 1785 | ||
1580 | if (changed) | 1786 | if (conn_changed || discov_changed) { |
1581 | new_settings(hdev, cmd->sk); | 1787 | new_settings(hdev, cmd->sk); |
1788 | if (discov_changed) | ||
1789 | mgmt_update_adv_data(hdev); | ||
1790 | hci_update_background_scan(hdev); | ||
1791 | } | ||
1582 | 1792 | ||
1583 | remove_cmd: | 1793 | remove_cmd: |
1584 | mgmt_pending_remove(cmd); | 1794 | mgmt_pending_remove(cmd); |
@@ -1607,8 +1817,10 @@ static int set_connectable_update_settings(struct hci_dev *hdev, | |||
1607 | if (err < 0) | 1817 | if (err < 0) |
1608 | return err; | 1818 | return err; |
1609 | 1819 | ||
1610 | if (changed) | 1820 | if (changed) { |
1821 | hci_update_background_scan(hdev); | ||
1611 | return new_settings(hdev, sk); | 1822 | return new_settings(hdev, sk); |
1823 | } | ||
1612 | 1824 | ||
1613 | return 0; | 1825 | return 0; |
1614 | } | 1826 | } |
@@ -1669,7 +1881,18 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1669 | if (cp->val) { | 1881 | if (cp->val) { |
1670 | scan = SCAN_PAGE; | 1882 | scan = SCAN_PAGE; |
1671 | } else { | 1883 | } else { |
1672 | scan = 0; | 1884 | /* If we don't have any whitelist entries just |
1885 | * disable all scanning. If there are entries | ||
1886 | * and we had both page and inquiry scanning | ||
1887 | * enabled then fall back to only page scanning. | ||
1888 | * Otherwise no changes are needed. | ||
1889 | */ | ||
1890 | if (list_empty(&hdev->whitelist)) | ||
1891 | scan = SCAN_DISABLED; | ||
1892 | else if (test_bit(HCI_ISCAN, &hdev->flags)) | ||
1893 | scan = SCAN_PAGE; | ||
1894 | else | ||
1895 | goto no_scan_update; | ||
1673 | 1896 | ||
1674 | if (test_bit(HCI_ISCAN, &hdev->flags) && | 1897 | if (test_bit(HCI_ISCAN, &hdev->flags) && |
1675 | hdev->discov_timeout > 0) | 1898 | hdev->discov_timeout > 0) |
@@ -1679,6 +1902,7 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1679 | hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | 1902 | hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); |
1680 | } | 1903 | } |
1681 | 1904 | ||
1905 | no_scan_update: | ||
1682 | /* If we're going from non-connectable to connectable or | 1906 | /* If we're going from non-connectable to connectable or |
1683 | * vice-versa when fast connectable is enabled ensure that fast | 1907 | * vice-versa when fast connectable is enabled ensure that fast |
1684 | * connectable gets disabled. write_fast_connectable won't do | 1908 | * connectable gets disabled. write_fast_connectable won't do |
@@ -1688,11 +1912,9 @@ static int set_connectable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1688 | if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) | 1912 | if (cp->val || test_bit(HCI_FAST_CONNECTABLE, &hdev->dev_flags)) |
1689 | write_fast_connectable(&req, false); | 1913 | write_fast_connectable(&req, false); |
1690 | 1914 | ||
1691 | if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) && | 1915 | /* Update the advertising parameters if necessary */ |
1692 | hci_conn_num(hdev, LE_LINK) == 0) { | 1916 | if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) |
1693 | disable_advertising(&req); | ||
1694 | enable_advertising(&req); | 1917 | enable_advertising(&req); |
1695 | } | ||
1696 | 1918 | ||
1697 | err = hci_req_run(&req, set_connectable_complete); | 1919 | err = hci_req_run(&req, set_connectable_complete); |
1698 | if (err < 0) { | 1920 | if (err < 0) { |
@@ -1708,7 +1930,7 @@ failed: | |||
1708 | return err; | 1930 | return err; |
1709 | } | 1931 | } |
1710 | 1932 | ||
1711 | static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data, | 1933 | static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data, |
1712 | u16 len) | 1934 | u16 len) |
1713 | { | 1935 | { |
1714 | struct mgmt_mode *cp = data; | 1936 | struct mgmt_mode *cp = data; |
@@ -1718,17 +1940,17 @@ static int set_pairable(struct sock *sk, struct hci_dev *hdev, void *data, | |||
1718 | BT_DBG("request for %s", hdev->name); | 1940 | BT_DBG("request for %s", hdev->name); |
1719 | 1941 | ||
1720 | if (cp->val != 0x00 && cp->val != 0x01) | 1942 | if (cp->val != 0x00 && cp->val != 0x01) |
1721 | return cmd_status(sk, hdev->id, MGMT_OP_SET_PAIRABLE, | 1943 | return cmd_status(sk, hdev->id, MGMT_OP_SET_BONDABLE, |
1722 | MGMT_STATUS_INVALID_PARAMS); | 1944 | MGMT_STATUS_INVALID_PARAMS); |
1723 | 1945 | ||
1724 | hci_dev_lock(hdev); | 1946 | hci_dev_lock(hdev); |
1725 | 1947 | ||
1726 | if (cp->val) | 1948 | if (cp->val) |
1727 | changed = !test_and_set_bit(HCI_PAIRABLE, &hdev->dev_flags); | 1949 | changed = !test_and_set_bit(HCI_BONDABLE, &hdev->dev_flags); |
1728 | else | 1950 | else |
1729 | changed = test_and_clear_bit(HCI_PAIRABLE, &hdev->dev_flags); | 1951 | changed = test_and_clear_bit(HCI_BONDABLE, &hdev->dev_flags); |
1730 | 1952 | ||
1731 | err = send_settings_rsp(sk, MGMT_OP_SET_PAIRABLE, hdev); | 1953 | err = send_settings_rsp(sk, MGMT_OP_SET_BONDABLE, hdev); |
1732 | if (err < 0) | 1954 | if (err < 0) |
1733 | goto unlock; | 1955 | goto unlock; |
1734 | 1956 | ||
@@ -1877,6 +2099,10 @@ static int set_ssp(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
1877 | goto failed; | 2099 | goto failed; |
1878 | } | 2100 | } |
1879 | 2101 | ||
2102 | if (!cp->val && test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags)) | ||
2103 | hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE, | ||
2104 | sizeof(cp->val), &cp->val); | ||
2105 | |||
1880 | err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val); | 2106 | err = hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &cp->val); |
1881 | if (err < 0) { | 2107 | if (err < 0) { |
1882 | mgmt_pending_remove(cmd); | 2108 | mgmt_pending_remove(cmd); |
@@ -1973,6 +2199,8 @@ static void le_enable_complete(struct hci_dev *hdev, u8 status) | |||
1973 | update_scan_rsp_data(&req); | 2199 | update_scan_rsp_data(&req); |
1974 | hci_req_run(&req, NULL); | 2200 | hci_req_run(&req, NULL); |
1975 | 2201 | ||
2202 | hci_update_background_scan(hdev); | ||
2203 | |||
1976 | hci_dev_unlock(hdev); | 2204 | hci_dev_unlock(hdev); |
1977 | } | 2205 | } |
1978 | } | 2206 | } |
@@ -2048,9 +2276,9 @@ static int set_le(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
2048 | 2276 | ||
2049 | if (val) { | 2277 | if (val) { |
2050 | hci_cp.le = val; | 2278 | hci_cp.le = val; |
2051 | hci_cp.simul = lmp_le_br_capable(hdev); | 2279 | hci_cp.simul = 0x00; |
2052 | } else { | 2280 | } else { |
2053 | if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) | 2281 | if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) |
2054 | disable_advertising(&req); | 2282 | disable_advertising(&req); |
2055 | } | 2283 | } |
2056 | 2284 | ||
@@ -2373,6 +2601,8 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2373 | u16 len) | 2601 | u16 len) |
2374 | { | 2602 | { |
2375 | struct mgmt_cp_load_link_keys *cp = data; | 2603 | struct mgmt_cp_load_link_keys *cp = data; |
2604 | const u16 max_key_count = ((U16_MAX - sizeof(*cp)) / | ||
2605 | sizeof(struct mgmt_link_key_info)); | ||
2376 | u16 key_count, expected_len; | 2606 | u16 key_count, expected_len; |
2377 | bool changed; | 2607 | bool changed; |
2378 | int i; | 2608 | int i; |
@@ -2384,6 +2614,12 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2384 | MGMT_STATUS_NOT_SUPPORTED); | 2614 | MGMT_STATUS_NOT_SUPPORTED); |
2385 | 2615 | ||
2386 | key_count = __le16_to_cpu(cp->key_count); | 2616 | key_count = __le16_to_cpu(cp->key_count); |
2617 | if (key_count > max_key_count) { | ||
2618 | BT_ERR("load_link_keys: too big key_count value %u", | ||
2619 | key_count); | ||
2620 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, | ||
2621 | MGMT_STATUS_INVALID_PARAMS); | ||
2622 | } | ||
2387 | 2623 | ||
2388 | expected_len = sizeof(*cp) + key_count * | 2624 | expected_len = sizeof(*cp) + key_count * |
2389 | sizeof(struct mgmt_link_key_info); | 2625 | sizeof(struct mgmt_link_key_info); |
@@ -2414,9 +2650,11 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2414 | hci_link_keys_clear(hdev); | 2650 | hci_link_keys_clear(hdev); |
2415 | 2651 | ||
2416 | if (cp->debug_keys) | 2652 | if (cp->debug_keys) |
2417 | changed = !test_and_set_bit(HCI_DEBUG_KEYS, &hdev->dev_flags); | 2653 | changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS, |
2654 | &hdev->dev_flags); | ||
2418 | else | 2655 | else |
2419 | changed = test_and_clear_bit(HCI_DEBUG_KEYS, &hdev->dev_flags); | 2656 | changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS, |
2657 | &hdev->dev_flags); | ||
2420 | 2658 | ||
2421 | if (changed) | 2659 | if (changed) |
2422 | new_settings(hdev, NULL); | 2660 | new_settings(hdev, NULL); |
@@ -2424,8 +2662,14 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2424 | for (i = 0; i < key_count; i++) { | 2662 | for (i = 0; i < key_count; i++) { |
2425 | struct mgmt_link_key_info *key = &cp->keys[i]; | 2663 | struct mgmt_link_key_info *key = &cp->keys[i]; |
2426 | 2664 | ||
2427 | hci_add_link_key(hdev, NULL, 0, &key->addr.bdaddr, key->val, | 2665 | /* Always ignore debug keys and require a new pairing if |
2428 | key->type, key->pin_len); | 2666 | * the user wants to use them. |
2667 | */ | ||
2668 | if (key->type == HCI_LK_DEBUG_COMBINATION) | ||
2669 | continue; | ||
2670 | |||
2671 | hci_add_link_key(hdev, NULL, &key->addr.bdaddr, key->val, | ||
2672 | key->type, key->pin_len, NULL); | ||
2429 | } | 2673 | } |
2430 | 2674 | ||
2431 | cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0); | 2675 | cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, 0, NULL, 0); |
@@ -2766,6 +3010,10 @@ static int set_io_capability(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2766 | 3010 | ||
2767 | BT_DBG(""); | 3011 | BT_DBG(""); |
2768 | 3012 | ||
3013 | if (cp->io_capability > SMP_IO_KEYBOARD_DISPLAY) | ||
3014 | return cmd_complete(sk, hdev->id, MGMT_OP_SET_IO_CAPABILITY, | ||
3015 | MGMT_STATUS_INVALID_PARAMS, NULL, 0); | ||
3016 | |||
2769 | hci_dev_lock(hdev); | 3017 | hci_dev_lock(hdev); |
2770 | 3018 | ||
2771 | hdev->io_capability = cp->io_capability; | 3019 | hdev->io_capability = cp->io_capability; |
@@ -2878,6 +3126,11 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2878 | MGMT_STATUS_INVALID_PARAMS, | 3126 | MGMT_STATUS_INVALID_PARAMS, |
2879 | &rp, sizeof(rp)); | 3127 | &rp, sizeof(rp)); |
2880 | 3128 | ||
3129 | if (cp->io_cap > SMP_IO_KEYBOARD_DISPLAY) | ||
3130 | return cmd_complete(sk, hdev->id, MGMT_OP_PAIR_DEVICE, | ||
3131 | MGMT_STATUS_INVALID_PARAMS, | ||
3132 | &rp, sizeof(rp)); | ||
3133 | |||
2881 | hci_dev_lock(hdev); | 3134 | hci_dev_lock(hdev); |
2882 | 3135 | ||
2883 | if (!hdev_is_powered(hdev)) { | 3136 | if (!hdev_is_powered(hdev)) { |
@@ -2902,8 +3155,20 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2902 | else | 3155 | else |
2903 | addr_type = ADDR_LE_DEV_RANDOM; | 3156 | addr_type = ADDR_LE_DEV_RANDOM; |
2904 | 3157 | ||
3158 | /* When pairing a new device, it is expected to remember | ||
3159 | * this device for future connections. Adding the connection | ||
3160 | * parameter information ahead of time allows tracking | ||
3161 | * of the slave preferred values and will speed up any | ||
3162 | * further connection establishment. | ||
3163 | * | ||
3164 | * If connection parameters already exist, then they | ||
3165 | * will be kept and this function does nothing. | ||
3166 | */ | ||
3167 | hci_conn_params_add(hdev, &cp->addr.bdaddr, addr_type); | ||
3168 | |||
2905 | conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type, | 3169 | conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type, |
2906 | sec_level, auth_type); | 3170 | sec_level, HCI_LE_CONN_TIMEOUT, |
3171 | HCI_ROLE_MASTER); | ||
2907 | } | 3172 | } |
2908 | 3173 | ||
2909 | if (IS_ERR(conn)) { | 3174 | if (IS_ERR(conn)) { |
@@ -2948,8 +3213,8 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, | |||
2948 | conn->io_capability = cp->io_cap; | 3213 | conn->io_capability = cp->io_cap; |
2949 | cmd->user_data = conn; | 3214 | cmd->user_data = conn; |
2950 | 3215 | ||
2951 | if (conn->state == BT_CONNECTED && | 3216 | if ((conn->state == BT_CONNECTED || conn->state == BT_CONFIG) && |
2952 | hci_conn_security(conn, sec_level, auth_type)) | 3217 | hci_conn_security(conn, sec_level, auth_type, true)) |
2953 | pairing_complete(cmd, 0); | 3218 | pairing_complete(cmd, 0); |
2954 | 3219 | ||
2955 | err = 0; | 3220 | err = 0; |
@@ -3031,14 +3296,7 @@ static int user_pairing_resp(struct sock *sk, struct hci_dev *hdev, | |||
3031 | } | 3296 | } |
3032 | 3297 | ||
3033 | if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) { | 3298 | if (addr->type == BDADDR_LE_PUBLIC || addr->type == BDADDR_LE_RANDOM) { |
3034 | /* Continue with pairing via SMP. The hdev lock must be | ||
3035 | * released as SMP may try to recquire it for crypto | ||
3036 | * purposes. | ||
3037 | */ | ||
3038 | hci_dev_unlock(hdev); | ||
3039 | err = smp_user_confirm_reply(conn, mgmt_op, passkey); | 3299 | err = smp_user_confirm_reply(conn, mgmt_op, passkey); |
3040 | hci_dev_lock(hdev); | ||
3041 | |||
3042 | if (!err) | 3300 | if (!err) |
3043 | err = cmd_complete(sk, hdev->id, mgmt_op, | 3301 | err = cmd_complete(sk, hdev->id, mgmt_op, |
3044 | MGMT_STATUS_SUCCESS, addr, | 3302 | MGMT_STATUS_SUCCESS, addr, |
@@ -3516,11 +3774,21 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, | |||
3516 | goto failed; | 3774 | goto failed; |
3517 | } | 3775 | } |
3518 | 3776 | ||
3519 | if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) { | 3777 | if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) { |
3520 | err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, | 3778 | /* Don't let discovery abort an outgoing |
3521 | MGMT_STATUS_REJECTED); | 3779 | * connection attempt that's using directed |
3522 | mgmt_pending_remove(cmd); | 3780 | * advertising. |
3523 | goto failed; | 3781 | */ |
3782 | if (hci_conn_hash_lookup_state(hdev, LE_LINK, | ||
3783 | BT_CONNECT)) { | ||
3784 | err = cmd_status(sk, hdev->id, | ||
3785 | MGMT_OP_START_DISCOVERY, | ||
3786 | MGMT_STATUS_REJECTED); | ||
3787 | mgmt_pending_remove(cmd); | ||
3788 | goto failed; | ||
3789 | } | ||
3790 | |||
3791 | disable_advertising(&req); | ||
3524 | } | 3792 | } |
3525 | 3793 | ||
3526 | /* If controller is scanning, it means the background scanning | 3794 | /* If controller is scanning, it means the background scanning |
@@ -3723,12 +3991,18 @@ static int block_device(struct sock *sk, struct hci_dev *hdev, void *data, | |||
3723 | 3991 | ||
3724 | hci_dev_lock(hdev); | 3992 | hci_dev_lock(hdev); |
3725 | 3993 | ||
3726 | err = hci_blacklist_add(hdev, &cp->addr.bdaddr, cp->addr.type); | 3994 | err = hci_bdaddr_list_add(&hdev->blacklist, &cp->addr.bdaddr, |
3727 | if (err < 0) | 3995 | cp->addr.type); |
3996 | if (err < 0) { | ||
3728 | status = MGMT_STATUS_FAILED; | 3997 | status = MGMT_STATUS_FAILED; |
3729 | else | 3998 | goto done; |
3730 | status = MGMT_STATUS_SUCCESS; | 3999 | } |
4000 | |||
4001 | mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &cp->addr, sizeof(cp->addr), | ||
4002 | sk); | ||
4003 | status = MGMT_STATUS_SUCCESS; | ||
3731 | 4004 | ||
4005 | done: | ||
3732 | err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status, | 4006 | err = cmd_complete(sk, hdev->id, MGMT_OP_BLOCK_DEVICE, status, |
3733 | &cp->addr, sizeof(cp->addr)); | 4007 | &cp->addr, sizeof(cp->addr)); |
3734 | 4008 | ||
@@ -3753,12 +4027,18 @@ static int unblock_device(struct sock *sk, struct hci_dev *hdev, void *data, | |||
3753 | 4027 | ||
3754 | hci_dev_lock(hdev); | 4028 | hci_dev_lock(hdev); |
3755 | 4029 | ||
3756 | err = hci_blacklist_del(hdev, &cp->addr.bdaddr, cp->addr.type); | 4030 | err = hci_bdaddr_list_del(&hdev->blacklist, &cp->addr.bdaddr, |
3757 | if (err < 0) | 4031 | cp->addr.type); |
4032 | if (err < 0) { | ||
3758 | status = MGMT_STATUS_INVALID_PARAMS; | 4033 | status = MGMT_STATUS_INVALID_PARAMS; |
3759 | else | 4034 | goto done; |
3760 | status = MGMT_STATUS_SUCCESS; | 4035 | } |
4036 | |||
4037 | mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &cp->addr, sizeof(cp->addr), | ||
4038 | sk); | ||
4039 | status = MGMT_STATUS_SUCCESS; | ||
3761 | 4040 | ||
4041 | done: | ||
3762 | err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status, | 4042 | err = cmd_complete(sk, hdev->id, MGMT_OP_UNBLOCK_DEVICE, status, |
3763 | &cp->addr, sizeof(cp->addr)); | 4043 | &cp->addr, sizeof(cp->addr)); |
3764 | 4044 | ||
@@ -3813,6 +4093,11 @@ static void set_advertising_complete(struct hci_dev *hdev, u8 status) | |||
3813 | return; | 4093 | return; |
3814 | } | 4094 | } |
3815 | 4095 | ||
4096 | if (test_bit(HCI_LE_ADV, &hdev->dev_flags)) | ||
4097 | set_bit(HCI_ADVERTISING, &hdev->dev_flags); | ||
4098 | else | ||
4099 | clear_bit(HCI_ADVERTISING, &hdev->dev_flags); | ||
4100 | |||
3816 | mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp, | 4101 | mgmt_pending_foreach(MGMT_OP_SET_ADVERTISING, hdev, settings_rsp, |
3817 | &match); | 4102 | &match); |
3818 | 4103 | ||
@@ -3853,7 +4138,9 @@ static int set_advertising(struct sock *sk, struct hci_dev *hdev, void *data, | |||
3853 | * necessary). | 4138 | * necessary). |
3854 | */ | 4139 | */ |
3855 | if (!hdev_is_powered(hdev) || val == enabled || | 4140 | if (!hdev_is_powered(hdev) || val == enabled || |
3856 | hci_conn_num(hdev, LE_LINK) > 0) { | 4141 | hci_conn_num(hdev, LE_LINK) > 0 || |
4142 | (test_bit(HCI_LE_SCAN, &hdev->dev_flags) && | ||
4143 | hdev->le_scan_type == LE_SCAN_ACTIVE)) { | ||
3857 | bool changed = false; | 4144 | bool changed = false; |
3858 | 4145 | ||
3859 | if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) { | 4146 | if (val != test_bit(HCI_ADVERTISING, &hdev->dev_flags)) { |
@@ -4105,7 +4392,8 @@ static void set_bredr_scan(struct hci_request *req) | |||
4105 | */ | 4392 | */ |
4106 | write_fast_connectable(req, false); | 4393 | write_fast_connectable(req, false); |
4107 | 4394 | ||
4108 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) | 4395 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags) || |
4396 | !list_empty(&hdev->whitelist)) | ||
4109 | scan |= SCAN_PAGE; | 4397 | scan |= SCAN_PAGE; |
4110 | if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) | 4398 | if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) |
4111 | scan |= SCAN_INQUIRY; | 4399 | scan |= SCAN_INQUIRY; |
@@ -4219,7 +4507,8 @@ static int set_bredr(struct sock *sk, struct hci_dev *hdev, void *data, u16 len) | |||
4219 | 4507 | ||
4220 | hci_req_init(&req, hdev); | 4508 | hci_req_init(&req, hdev); |
4221 | 4509 | ||
4222 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) | 4510 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags) || |
4511 | !list_empty(&hdev->whitelist)) | ||
4223 | set_bredr_scan(&req); | 4512 | set_bredr_scan(&req); |
4224 | 4513 | ||
4225 | /* Since only the advertising data flags will change, there | 4514 | /* Since only the advertising data flags will change, there |
@@ -4252,7 +4541,7 @@ static int set_secure_conn(struct sock *sk, struct hci_dev *hdev, | |||
4252 | status); | 4541 | status); |
4253 | 4542 | ||
4254 | if (!lmp_sc_capable(hdev) && | 4543 | if (!lmp_sc_capable(hdev) && |
4255 | !test_bit(HCI_FORCE_SC, &hdev->dev_flags)) | 4544 | !test_bit(HCI_FORCE_SC, &hdev->dbg_flags)) |
4256 | return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN, | 4545 | return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN, |
4257 | MGMT_STATUS_NOT_SUPPORTED); | 4546 | MGMT_STATUS_NOT_SUPPORTED); |
4258 | 4547 | ||
@@ -4328,21 +4617,37 @@ static int set_debug_keys(struct sock *sk, struct hci_dev *hdev, | |||
4328 | void *data, u16 len) | 4617 | void *data, u16 len) |
4329 | { | 4618 | { |
4330 | struct mgmt_mode *cp = data; | 4619 | struct mgmt_mode *cp = data; |
4331 | bool changed; | 4620 | bool changed, use_changed; |
4332 | int err; | 4621 | int err; |
4333 | 4622 | ||
4334 | BT_DBG("request for %s", hdev->name); | 4623 | BT_DBG("request for %s", hdev->name); |
4335 | 4624 | ||
4336 | if (cp->val != 0x00 && cp->val != 0x01) | 4625 | if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02) |
4337 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS, | 4626 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS, |
4338 | MGMT_STATUS_INVALID_PARAMS); | 4627 | MGMT_STATUS_INVALID_PARAMS); |
4339 | 4628 | ||
4340 | hci_dev_lock(hdev); | 4629 | hci_dev_lock(hdev); |
4341 | 4630 | ||
4342 | if (cp->val) | 4631 | if (cp->val) |
4343 | changed = !test_and_set_bit(HCI_DEBUG_KEYS, &hdev->dev_flags); | 4632 | changed = !test_and_set_bit(HCI_KEEP_DEBUG_KEYS, |
4633 | &hdev->dev_flags); | ||
4634 | else | ||
4635 | changed = test_and_clear_bit(HCI_KEEP_DEBUG_KEYS, | ||
4636 | &hdev->dev_flags); | ||
4637 | |||
4638 | if (cp->val == 0x02) | ||
4639 | use_changed = !test_and_set_bit(HCI_USE_DEBUG_KEYS, | ||
4640 | &hdev->dev_flags); | ||
4344 | else | 4641 | else |
4345 | changed = test_and_clear_bit(HCI_DEBUG_KEYS, &hdev->dev_flags); | 4642 | use_changed = test_and_clear_bit(HCI_USE_DEBUG_KEYS, |
4643 | &hdev->dev_flags); | ||
4644 | |||
4645 | if (hdev_is_powered(hdev) && use_changed && | ||
4646 | test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { | ||
4647 | u8 mode = (cp->val == 0x02) ? 0x01 : 0x00; | ||
4648 | hci_send_cmd(hdev, HCI_OP_WRITE_SSP_DEBUG_MODE, | ||
4649 | sizeof(mode), &mode); | ||
4650 | } | ||
4346 | 4651 | ||
4347 | err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev); | 4652 | err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev); |
4348 | if (err < 0) | 4653 | if (err < 0) |
@@ -4426,6 +4731,8 @@ static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data, | |||
4426 | u16 len) | 4731 | u16 len) |
4427 | { | 4732 | { |
4428 | struct mgmt_cp_load_irks *cp = cp_data; | 4733 | struct mgmt_cp_load_irks *cp = cp_data; |
4734 | const u16 max_irk_count = ((U16_MAX - sizeof(*cp)) / | ||
4735 | sizeof(struct mgmt_irk_info)); | ||
4429 | u16 irk_count, expected_len; | 4736 | u16 irk_count, expected_len; |
4430 | int i, err; | 4737 | int i, err; |
4431 | 4738 | ||
@@ -4436,6 +4743,11 @@ static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data, | |||
4436 | MGMT_STATUS_NOT_SUPPORTED); | 4743 | MGMT_STATUS_NOT_SUPPORTED); |
4437 | 4744 | ||
4438 | irk_count = __le16_to_cpu(cp->irk_count); | 4745 | irk_count = __le16_to_cpu(cp->irk_count); |
4746 | if (irk_count > max_irk_count) { | ||
4747 | BT_ERR("load_irks: too big irk_count value %u", irk_count); | ||
4748 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS, | ||
4749 | MGMT_STATUS_INVALID_PARAMS); | ||
4750 | } | ||
4439 | 4751 | ||
4440 | expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info); | 4752 | expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info); |
4441 | if (expected_len != len) { | 4753 | if (expected_len != len) { |
@@ -4505,6 +4817,8 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev, | |||
4505 | void *cp_data, u16 len) | 4817 | void *cp_data, u16 len) |
4506 | { | 4818 | { |
4507 | struct mgmt_cp_load_long_term_keys *cp = cp_data; | 4819 | struct mgmt_cp_load_long_term_keys *cp = cp_data; |
4820 | const u16 max_key_count = ((U16_MAX - sizeof(*cp)) / | ||
4821 | sizeof(struct mgmt_ltk_info)); | ||
4508 | u16 key_count, expected_len; | 4822 | u16 key_count, expected_len; |
4509 | int i, err; | 4823 | int i, err; |
4510 | 4824 | ||
@@ -4515,6 +4829,11 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev, | |||
4515 | MGMT_STATUS_NOT_SUPPORTED); | 4829 | MGMT_STATUS_NOT_SUPPORTED); |
4516 | 4830 | ||
4517 | key_count = __le16_to_cpu(cp->key_count); | 4831 | key_count = __le16_to_cpu(cp->key_count); |
4832 | if (key_count > max_key_count) { | ||
4833 | BT_ERR("load_ltks: too big key_count value %u", key_count); | ||
4834 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, | ||
4835 | MGMT_STATUS_INVALID_PARAMS); | ||
4836 | } | ||
4518 | 4837 | ||
4519 | expected_len = sizeof(*cp) + key_count * | 4838 | expected_len = sizeof(*cp) + key_count * |
4520 | sizeof(struct mgmt_ltk_info); | 4839 | sizeof(struct mgmt_ltk_info); |
@@ -4550,9 +4869,9 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev, | |||
4550 | addr_type = ADDR_LE_DEV_RANDOM; | 4869 | addr_type = ADDR_LE_DEV_RANDOM; |
4551 | 4870 | ||
4552 | if (key->master) | 4871 | if (key->master) |
4553 | type = HCI_SMP_LTK; | 4872 | type = SMP_LTK; |
4554 | else | 4873 | else |
4555 | type = HCI_SMP_LTK_SLAVE; | 4874 | type = SMP_LTK_SLAVE; |
4556 | 4875 | ||
4557 | switch (key->type) { | 4876 | switch (key->type) { |
4558 | case MGMT_LTK_UNAUTHENTICATED: | 4877 | case MGMT_LTK_UNAUTHENTICATED: |
@@ -4790,6 +5109,561 @@ unlock: | |||
4790 | return err; | 5109 | return err; |
4791 | } | 5110 | } |
4792 | 5111 | ||
5112 | static void get_clock_info_complete(struct hci_dev *hdev, u8 status) | ||
5113 | { | ||
5114 | struct mgmt_cp_get_clock_info *cp; | ||
5115 | struct mgmt_rp_get_clock_info rp; | ||
5116 | struct hci_cp_read_clock *hci_cp; | ||
5117 | struct pending_cmd *cmd; | ||
5118 | struct hci_conn *conn; | ||
5119 | |||
5120 | BT_DBG("%s status %u", hdev->name, status); | ||
5121 | |||
5122 | hci_dev_lock(hdev); | ||
5123 | |||
5124 | hci_cp = hci_sent_cmd_data(hdev, HCI_OP_READ_CLOCK); | ||
5125 | if (!hci_cp) | ||
5126 | goto unlock; | ||
5127 | |||
5128 | if (hci_cp->which) { | ||
5129 | u16 handle = __le16_to_cpu(hci_cp->handle); | ||
5130 | conn = hci_conn_hash_lookup_handle(hdev, handle); | ||
5131 | } else { | ||
5132 | conn = NULL; | ||
5133 | } | ||
5134 | |||
5135 | cmd = mgmt_pending_find_data(MGMT_OP_GET_CLOCK_INFO, hdev, conn); | ||
5136 | if (!cmd) | ||
5137 | goto unlock; | ||
5138 | |||
5139 | cp = cmd->param; | ||
5140 | |||
5141 | memset(&rp, 0, sizeof(rp)); | ||
5142 | memcpy(&rp.addr, &cp->addr, sizeof(rp.addr)); | ||
5143 | |||
5144 | if (status) | ||
5145 | goto send_rsp; | ||
5146 | |||
5147 | rp.local_clock = cpu_to_le32(hdev->clock); | ||
5148 | |||
5149 | if (conn) { | ||
5150 | rp.piconet_clock = cpu_to_le32(conn->clock); | ||
5151 | rp.accuracy = cpu_to_le16(conn->clock_accuracy); | ||
5152 | } | ||
5153 | |||
5154 | send_rsp: | ||
5155 | cmd_complete(cmd->sk, cmd->index, cmd->opcode, mgmt_status(status), | ||
5156 | &rp, sizeof(rp)); | ||
5157 | mgmt_pending_remove(cmd); | ||
5158 | if (conn) | ||
5159 | hci_conn_drop(conn); | ||
5160 | |||
5161 | unlock: | ||
5162 | hci_dev_unlock(hdev); | ||
5163 | } | ||
5164 | |||
5165 | static int get_clock_info(struct sock *sk, struct hci_dev *hdev, void *data, | ||
5166 | u16 len) | ||
5167 | { | ||
5168 | struct mgmt_cp_get_clock_info *cp = data; | ||
5169 | struct mgmt_rp_get_clock_info rp; | ||
5170 | struct hci_cp_read_clock hci_cp; | ||
5171 | struct pending_cmd *cmd; | ||
5172 | struct hci_request req; | ||
5173 | struct hci_conn *conn; | ||
5174 | int err; | ||
5175 | |||
5176 | BT_DBG("%s", hdev->name); | ||
5177 | |||
5178 | memset(&rp, 0, sizeof(rp)); | ||
5179 | bacpy(&rp.addr.bdaddr, &cp->addr.bdaddr); | ||
5180 | rp.addr.type = cp->addr.type; | ||
5181 | |||
5182 | if (cp->addr.type != BDADDR_BREDR) | ||
5183 | return cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO, | ||
5184 | MGMT_STATUS_INVALID_PARAMS, | ||
5185 | &rp, sizeof(rp)); | ||
5186 | |||
5187 | hci_dev_lock(hdev); | ||
5188 | |||
5189 | if (!hdev_is_powered(hdev)) { | ||
5190 | err = cmd_complete(sk, hdev->id, MGMT_OP_GET_CLOCK_INFO, | ||
5191 | MGMT_STATUS_NOT_POWERED, &rp, sizeof(rp)); | ||
5192 | goto unlock; | ||
5193 | } | ||
5194 | |||
5195 | if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) { | ||
5196 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, | ||
5197 | &cp->addr.bdaddr); | ||
5198 | if (!conn || conn->state != BT_CONNECTED) { | ||
5199 | err = cmd_complete(sk, hdev->id, | ||
5200 | MGMT_OP_GET_CLOCK_INFO, | ||
5201 | MGMT_STATUS_NOT_CONNECTED, | ||
5202 | &rp, sizeof(rp)); | ||
5203 | goto unlock; | ||
5204 | } | ||
5205 | } else { | ||
5206 | conn = NULL; | ||
5207 | } | ||
5208 | |||
5209 | cmd = mgmt_pending_add(sk, MGMT_OP_GET_CLOCK_INFO, hdev, data, len); | ||
5210 | if (!cmd) { | ||
5211 | err = -ENOMEM; | ||
5212 | goto unlock; | ||
5213 | } | ||
5214 | |||
5215 | hci_req_init(&req, hdev); | ||
5216 | |||
5217 | memset(&hci_cp, 0, sizeof(hci_cp)); | ||
5218 | hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp); | ||
5219 | |||
5220 | if (conn) { | ||
5221 | hci_conn_hold(conn); | ||
5222 | cmd->user_data = conn; | ||
5223 | |||
5224 | hci_cp.handle = cpu_to_le16(conn->handle); | ||
5225 | hci_cp.which = 0x01; /* Piconet clock */ | ||
5226 | hci_req_add(&req, HCI_OP_READ_CLOCK, sizeof(hci_cp), &hci_cp); | ||
5227 | } | ||
5228 | |||
5229 | err = hci_req_run(&req, get_clock_info_complete); | ||
5230 | if (err < 0) | ||
5231 | mgmt_pending_remove(cmd); | ||
5232 | |||
5233 | unlock: | ||
5234 | hci_dev_unlock(hdev); | ||
5235 | return err; | ||
5236 | } | ||
5237 | |||
5238 | /* Helper for Add/Remove Device commands */ | ||
5239 | static void update_page_scan(struct hci_dev *hdev, u8 scan) | ||
5240 | { | ||
5241 | if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) | ||
5242 | return; | ||
5243 | |||
5244 | if (!hdev_is_powered(hdev)) | ||
5245 | return; | ||
5246 | |||
5247 | /* If HCI_CONNECTABLE is set then Add/Remove Device should not | ||
5248 | * make any changes to page scanning. | ||
5249 | */ | ||
5250 | if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags)) | ||
5251 | return; | ||
5252 | |||
5253 | if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags)) | ||
5254 | scan |= SCAN_INQUIRY; | ||
5255 | |||
5256 | hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | ||
5257 | } | ||
5258 | |||
5259 | static void device_added(struct sock *sk, struct hci_dev *hdev, | ||
5260 | bdaddr_t *bdaddr, u8 type, u8 action) | ||
5261 | { | ||
5262 | struct mgmt_ev_device_added ev; | ||
5263 | |||
5264 | bacpy(&ev.addr.bdaddr, bdaddr); | ||
5265 | ev.addr.type = type; | ||
5266 | ev.action = action; | ||
5267 | |||
5268 | mgmt_event(MGMT_EV_DEVICE_ADDED, hdev, &ev, sizeof(ev), sk); | ||
5269 | } | ||
5270 | |||
5271 | static int add_device(struct sock *sk, struct hci_dev *hdev, | ||
5272 | void *data, u16 len) | ||
5273 | { | ||
5274 | struct mgmt_cp_add_device *cp = data; | ||
5275 | u8 auto_conn, addr_type; | ||
5276 | int err; | ||
5277 | |||
5278 | BT_DBG("%s", hdev->name); | ||
5279 | |||
5280 | if (!bdaddr_type_is_valid(cp->addr.type) || | ||
5281 | !bacmp(&cp->addr.bdaddr, BDADDR_ANY)) | ||
5282 | return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE, | ||
5283 | MGMT_STATUS_INVALID_PARAMS, | ||
5284 | &cp->addr, sizeof(cp->addr)); | ||
5285 | |||
5286 | if (cp->action != 0x00 && cp->action != 0x01 && cp->action != 0x02) | ||
5287 | return cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE, | ||
5288 | MGMT_STATUS_INVALID_PARAMS, | ||
5289 | &cp->addr, sizeof(cp->addr)); | ||
5290 | |||
5291 | hci_dev_lock(hdev); | ||
5292 | |||
5293 | if (cp->addr.type == BDADDR_BREDR) { | ||
5294 | bool update_scan; | ||
5295 | |||
5296 | /* Only incoming connections action is supported for now */ | ||
5297 | if (cp->action != 0x01) { | ||
5298 | err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE, | ||
5299 | MGMT_STATUS_INVALID_PARAMS, | ||
5300 | &cp->addr, sizeof(cp->addr)); | ||
5301 | goto unlock; | ||
5302 | } | ||
5303 | |||
5304 | update_scan = list_empty(&hdev->whitelist); | ||
5305 | |||
5306 | err = hci_bdaddr_list_add(&hdev->whitelist, &cp->addr.bdaddr, | ||
5307 | cp->addr.type); | ||
5308 | if (err) | ||
5309 | goto unlock; | ||
5310 | |||
5311 | if (update_scan) | ||
5312 | update_page_scan(hdev, SCAN_PAGE); | ||
5313 | |||
5314 | goto added; | ||
5315 | } | ||
5316 | |||
5317 | if (cp->addr.type == BDADDR_LE_PUBLIC) | ||
5318 | addr_type = ADDR_LE_DEV_PUBLIC; | ||
5319 | else | ||
5320 | addr_type = ADDR_LE_DEV_RANDOM; | ||
5321 | |||
5322 | if (cp->action == 0x02) | ||
5323 | auto_conn = HCI_AUTO_CONN_ALWAYS; | ||
5324 | else if (cp->action == 0x01) | ||
5325 | auto_conn = HCI_AUTO_CONN_DIRECT; | ||
5326 | else | ||
5327 | auto_conn = HCI_AUTO_CONN_REPORT; | ||
5328 | |||
5329 | /* If the connection parameters don't exist for this device, | ||
5330 | * they will be created and configured with defaults. | ||
5331 | */ | ||
5332 | if (hci_conn_params_set(hdev, &cp->addr.bdaddr, addr_type, | ||
5333 | auto_conn) < 0) { | ||
5334 | err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE, | ||
5335 | MGMT_STATUS_FAILED, | ||
5336 | &cp->addr, sizeof(cp->addr)); | ||
5337 | goto unlock; | ||
5338 | } | ||
5339 | |||
5340 | added: | ||
5341 | device_added(sk, hdev, &cp->addr.bdaddr, cp->addr.type, cp->action); | ||
5342 | |||
5343 | err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_DEVICE, | ||
5344 | MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr)); | ||
5345 | |||
5346 | unlock: | ||
5347 | hci_dev_unlock(hdev); | ||
5348 | return err; | ||
5349 | } | ||
5350 | |||
5351 | static void device_removed(struct sock *sk, struct hci_dev *hdev, | ||
5352 | bdaddr_t *bdaddr, u8 type) | ||
5353 | { | ||
5354 | struct mgmt_ev_device_removed ev; | ||
5355 | |||
5356 | bacpy(&ev.addr.bdaddr, bdaddr); | ||
5357 | ev.addr.type = type; | ||
5358 | |||
5359 | mgmt_event(MGMT_EV_DEVICE_REMOVED, hdev, &ev, sizeof(ev), sk); | ||
5360 | } | ||
5361 | |||
5362 | static int remove_device(struct sock *sk, struct hci_dev *hdev, | ||
5363 | void *data, u16 len) | ||
5364 | { | ||
5365 | struct mgmt_cp_remove_device *cp = data; | ||
5366 | int err; | ||
5367 | |||
5368 | BT_DBG("%s", hdev->name); | ||
5369 | |||
5370 | hci_dev_lock(hdev); | ||
5371 | |||
5372 | if (bacmp(&cp->addr.bdaddr, BDADDR_ANY)) { | ||
5373 | struct hci_conn_params *params; | ||
5374 | u8 addr_type; | ||
5375 | |||
5376 | if (!bdaddr_type_is_valid(cp->addr.type)) { | ||
5377 | err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE, | ||
5378 | MGMT_STATUS_INVALID_PARAMS, | ||
5379 | &cp->addr, sizeof(cp->addr)); | ||
5380 | goto unlock; | ||
5381 | } | ||
5382 | |||
5383 | if (cp->addr.type == BDADDR_BREDR) { | ||
5384 | err = hci_bdaddr_list_del(&hdev->whitelist, | ||
5385 | &cp->addr.bdaddr, | ||
5386 | cp->addr.type); | ||
5387 | if (err) { | ||
5388 | err = cmd_complete(sk, hdev->id, | ||
5389 | MGMT_OP_REMOVE_DEVICE, | ||
5390 | MGMT_STATUS_INVALID_PARAMS, | ||
5391 | &cp->addr, sizeof(cp->addr)); | ||
5392 | goto unlock; | ||
5393 | } | ||
5394 | |||
5395 | if (list_empty(&hdev->whitelist)) | ||
5396 | update_page_scan(hdev, SCAN_DISABLED); | ||
5397 | |||
5398 | device_removed(sk, hdev, &cp->addr.bdaddr, | ||
5399 | cp->addr.type); | ||
5400 | goto complete; | ||
5401 | } | ||
5402 | |||
5403 | if (cp->addr.type == BDADDR_LE_PUBLIC) | ||
5404 | addr_type = ADDR_LE_DEV_PUBLIC; | ||
5405 | else | ||
5406 | addr_type = ADDR_LE_DEV_RANDOM; | ||
5407 | |||
5408 | params = hci_conn_params_lookup(hdev, &cp->addr.bdaddr, | ||
5409 | addr_type); | ||
5410 | if (!params) { | ||
5411 | err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE, | ||
5412 | MGMT_STATUS_INVALID_PARAMS, | ||
5413 | &cp->addr, sizeof(cp->addr)); | ||
5414 | goto unlock; | ||
5415 | } | ||
5416 | |||
5417 | if (params->auto_connect == HCI_AUTO_CONN_DISABLED) { | ||
5418 | err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE, | ||
5419 | MGMT_STATUS_INVALID_PARAMS, | ||
5420 | &cp->addr, sizeof(cp->addr)); | ||
5421 | goto unlock; | ||
5422 | } | ||
5423 | |||
5424 | list_del(¶ms->action); | ||
5425 | list_del(¶ms->list); | ||
5426 | kfree(params); | ||
5427 | hci_update_background_scan(hdev); | ||
5428 | |||
5429 | device_removed(sk, hdev, &cp->addr.bdaddr, cp->addr.type); | ||
5430 | } else { | ||
5431 | struct hci_conn_params *p, *tmp; | ||
5432 | struct bdaddr_list *b, *btmp; | ||
5433 | |||
5434 | if (cp->addr.type) { | ||
5435 | err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE, | ||
5436 | MGMT_STATUS_INVALID_PARAMS, | ||
5437 | &cp->addr, sizeof(cp->addr)); | ||
5438 | goto unlock; | ||
5439 | } | ||
5440 | |||
5441 | list_for_each_entry_safe(b, btmp, &hdev->whitelist, list) { | ||
5442 | device_removed(sk, hdev, &b->bdaddr, b->bdaddr_type); | ||
5443 | list_del(&b->list); | ||
5444 | kfree(b); | ||
5445 | } | ||
5446 | |||
5447 | update_page_scan(hdev, SCAN_DISABLED); | ||
5448 | |||
5449 | list_for_each_entry_safe(p, tmp, &hdev->le_conn_params, list) { | ||
5450 | if (p->auto_connect == HCI_AUTO_CONN_DISABLED) | ||
5451 | continue; | ||
5452 | device_removed(sk, hdev, &p->addr, p->addr_type); | ||
5453 | list_del(&p->action); | ||
5454 | list_del(&p->list); | ||
5455 | kfree(p); | ||
5456 | } | ||
5457 | |||
5458 | BT_DBG("All LE connection parameters were removed"); | ||
5459 | |||
5460 | hci_update_background_scan(hdev); | ||
5461 | } | ||
5462 | |||
5463 | complete: | ||
5464 | err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_DEVICE, | ||
5465 | MGMT_STATUS_SUCCESS, &cp->addr, sizeof(cp->addr)); | ||
5466 | |||
5467 | unlock: | ||
5468 | hci_dev_unlock(hdev); | ||
5469 | return err; | ||
5470 | } | ||
5471 | |||
5472 | static int load_conn_param(struct sock *sk, struct hci_dev *hdev, void *data, | ||
5473 | u16 len) | ||
5474 | { | ||
5475 | struct mgmt_cp_load_conn_param *cp = data; | ||
5476 | const u16 max_param_count = ((U16_MAX - sizeof(*cp)) / | ||
5477 | sizeof(struct mgmt_conn_param)); | ||
5478 | u16 param_count, expected_len; | ||
5479 | int i; | ||
5480 | |||
5481 | if (!lmp_le_capable(hdev)) | ||
5482 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, | ||
5483 | MGMT_STATUS_NOT_SUPPORTED); | ||
5484 | |||
5485 | param_count = __le16_to_cpu(cp->param_count); | ||
5486 | if (param_count > max_param_count) { | ||
5487 | BT_ERR("load_conn_param: too big param_count value %u", | ||
5488 | param_count); | ||
5489 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, | ||
5490 | MGMT_STATUS_INVALID_PARAMS); | ||
5491 | } | ||
5492 | |||
5493 | expected_len = sizeof(*cp) + param_count * | ||
5494 | sizeof(struct mgmt_conn_param); | ||
5495 | if (expected_len != len) { | ||
5496 | BT_ERR("load_conn_param: expected %u bytes, got %u bytes", | ||
5497 | expected_len, len); | ||
5498 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, | ||
5499 | MGMT_STATUS_INVALID_PARAMS); | ||
5500 | } | ||
5501 | |||
5502 | BT_DBG("%s param_count %u", hdev->name, param_count); | ||
5503 | |||
5504 | hci_dev_lock(hdev); | ||
5505 | |||
5506 | hci_conn_params_clear_disabled(hdev); | ||
5507 | |||
5508 | for (i = 0; i < param_count; i++) { | ||
5509 | struct mgmt_conn_param *param = &cp->params[i]; | ||
5510 | struct hci_conn_params *hci_param; | ||
5511 | u16 min, max, latency, timeout; | ||
5512 | u8 addr_type; | ||
5513 | |||
5514 | BT_DBG("Adding %pMR (type %u)", ¶m->addr.bdaddr, | ||
5515 | param->addr.type); | ||
5516 | |||
5517 | if (param->addr.type == BDADDR_LE_PUBLIC) { | ||
5518 | addr_type = ADDR_LE_DEV_PUBLIC; | ||
5519 | } else if (param->addr.type == BDADDR_LE_RANDOM) { | ||
5520 | addr_type = ADDR_LE_DEV_RANDOM; | ||
5521 | } else { | ||
5522 | BT_ERR("Ignoring invalid connection parameters"); | ||
5523 | continue; | ||
5524 | } | ||
5525 | |||
5526 | min = le16_to_cpu(param->min_interval); | ||
5527 | max = le16_to_cpu(param->max_interval); | ||
5528 | latency = le16_to_cpu(param->latency); | ||
5529 | timeout = le16_to_cpu(param->timeout); | ||
5530 | |||
5531 | BT_DBG("min 0x%04x max 0x%04x latency 0x%04x timeout 0x%04x", | ||
5532 | min, max, latency, timeout); | ||
5533 | |||
5534 | if (hci_check_conn_params(min, max, latency, timeout) < 0) { | ||
5535 | BT_ERR("Ignoring invalid connection parameters"); | ||
5536 | continue; | ||
5537 | } | ||
5538 | |||
5539 | hci_param = hci_conn_params_add(hdev, ¶m->addr.bdaddr, | ||
5540 | addr_type); | ||
5541 | if (!hci_param) { | ||
5542 | BT_ERR("Failed to add connection parameters"); | ||
5543 | continue; | ||
5544 | } | ||
5545 | |||
5546 | hci_param->conn_min_interval = min; | ||
5547 | hci_param->conn_max_interval = max; | ||
5548 | hci_param->conn_latency = latency; | ||
5549 | hci_param->supervision_timeout = timeout; | ||
5550 | } | ||
5551 | |||
5552 | hci_dev_unlock(hdev); | ||
5553 | |||
5554 | return cmd_complete(sk, hdev->id, MGMT_OP_LOAD_CONN_PARAM, 0, NULL, 0); | ||
5555 | } | ||
5556 | |||
5557 | static int set_external_config(struct sock *sk, struct hci_dev *hdev, | ||
5558 | void *data, u16 len) | ||
5559 | { | ||
5560 | struct mgmt_cp_set_external_config *cp = data; | ||
5561 | bool changed; | ||
5562 | int err; | ||
5563 | |||
5564 | BT_DBG("%s", hdev->name); | ||
5565 | |||
5566 | if (hdev_is_powered(hdev)) | ||
5567 | return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG, | ||
5568 | MGMT_STATUS_REJECTED); | ||
5569 | |||
5570 | if (cp->config != 0x00 && cp->config != 0x01) | ||
5571 | return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG, | ||
5572 | MGMT_STATUS_INVALID_PARAMS); | ||
5573 | |||
5574 | if (!test_bit(HCI_QUIRK_EXTERNAL_CONFIG, &hdev->quirks)) | ||
5575 | return cmd_status(sk, hdev->id, MGMT_OP_SET_EXTERNAL_CONFIG, | ||
5576 | MGMT_STATUS_NOT_SUPPORTED); | ||
5577 | |||
5578 | hci_dev_lock(hdev); | ||
5579 | |||
5580 | if (cp->config) | ||
5581 | changed = !test_and_set_bit(HCI_EXT_CONFIGURED, | ||
5582 | &hdev->dev_flags); | ||
5583 | else | ||
5584 | changed = test_and_clear_bit(HCI_EXT_CONFIGURED, | ||
5585 | &hdev->dev_flags); | ||
5586 | |||
5587 | err = send_options_rsp(sk, MGMT_OP_SET_EXTERNAL_CONFIG, hdev); | ||
5588 | if (err < 0) | ||
5589 | goto unlock; | ||
5590 | |||
5591 | if (!changed) | ||
5592 | goto unlock; | ||
5593 | |||
5594 | err = new_options(hdev, sk); | ||
5595 | |||
5596 | if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) == is_configured(hdev)) { | ||
5597 | mgmt_index_removed(hdev); | ||
5598 | |||
5599 | if (test_and_change_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) { | ||
5600 | set_bit(HCI_CONFIG, &hdev->dev_flags); | ||
5601 | set_bit(HCI_AUTO_OFF, &hdev->dev_flags); | ||
5602 | |||
5603 | queue_work(hdev->req_workqueue, &hdev->power_on); | ||
5604 | } else { | ||
5605 | set_bit(HCI_RAW, &hdev->flags); | ||
5606 | mgmt_index_added(hdev); | ||
5607 | } | ||
5608 | } | ||
5609 | |||
5610 | unlock: | ||
5611 | hci_dev_unlock(hdev); | ||
5612 | return err; | ||
5613 | } | ||
5614 | |||
5615 | static int set_public_address(struct sock *sk, struct hci_dev *hdev, | ||
5616 | void *data, u16 len) | ||
5617 | { | ||
5618 | struct mgmt_cp_set_public_address *cp = data; | ||
5619 | bool changed; | ||
5620 | int err; | ||
5621 | |||
5622 | BT_DBG("%s", hdev->name); | ||
5623 | |||
5624 | if (hdev_is_powered(hdev)) | ||
5625 | return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS, | ||
5626 | MGMT_STATUS_REJECTED); | ||
5627 | |||
5628 | if (!bacmp(&cp->bdaddr, BDADDR_ANY)) | ||
5629 | return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS, | ||
5630 | MGMT_STATUS_INVALID_PARAMS); | ||
5631 | |||
5632 | if (!hdev->set_bdaddr) | ||
5633 | return cmd_status(sk, hdev->id, MGMT_OP_SET_PUBLIC_ADDRESS, | ||
5634 | MGMT_STATUS_NOT_SUPPORTED); | ||
5635 | |||
5636 | hci_dev_lock(hdev); | ||
5637 | |||
5638 | changed = !!bacmp(&hdev->public_addr, &cp->bdaddr); | ||
5639 | bacpy(&hdev->public_addr, &cp->bdaddr); | ||
5640 | |||
5641 | err = send_options_rsp(sk, MGMT_OP_SET_PUBLIC_ADDRESS, hdev); | ||
5642 | if (err < 0) | ||
5643 | goto unlock; | ||
5644 | |||
5645 | if (!changed) | ||
5646 | goto unlock; | ||
5647 | |||
5648 | if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) | ||
5649 | err = new_options(hdev, sk); | ||
5650 | |||
5651 | if (is_configured(hdev)) { | ||
5652 | mgmt_index_removed(hdev); | ||
5653 | |||
5654 | clear_bit(HCI_UNCONFIGURED, &hdev->dev_flags); | ||
5655 | |||
5656 | set_bit(HCI_CONFIG, &hdev->dev_flags); | ||
5657 | set_bit(HCI_AUTO_OFF, &hdev->dev_flags); | ||
5658 | |||
5659 | queue_work(hdev->req_workqueue, &hdev->power_on); | ||
5660 | } | ||
5661 | |||
5662 | unlock: | ||
5663 | hci_dev_unlock(hdev); | ||
5664 | return err; | ||
5665 | } | ||
5666 | |||
4793 | static const struct mgmt_handler { | 5667 | static const struct mgmt_handler { |
4794 | int (*func) (struct sock *sk, struct hci_dev *hdev, void *data, | 5668 | int (*func) (struct sock *sk, struct hci_dev *hdev, void *data, |
4795 | u16 data_len); | 5669 | u16 data_len); |
@@ -4805,7 +5679,7 @@ static const struct mgmt_handler { | |||
4805 | { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE }, | 5679 | { set_discoverable, false, MGMT_SET_DISCOVERABLE_SIZE }, |
4806 | { set_connectable, false, MGMT_SETTING_SIZE }, | 5680 | { set_connectable, false, MGMT_SETTING_SIZE }, |
4807 | { set_fast_connectable, false, MGMT_SETTING_SIZE }, | 5681 | { set_fast_connectable, false, MGMT_SETTING_SIZE }, |
4808 | { set_pairable, false, MGMT_SETTING_SIZE }, | 5682 | { set_bondable, false, MGMT_SETTING_SIZE }, |
4809 | { set_link_security, false, MGMT_SETTING_SIZE }, | 5683 | { set_link_security, false, MGMT_SETTING_SIZE }, |
4810 | { set_ssp, false, MGMT_SETTING_SIZE }, | 5684 | { set_ssp, false, MGMT_SETTING_SIZE }, |
4811 | { set_hs, false, MGMT_SETTING_SIZE }, | 5685 | { set_hs, false, MGMT_SETTING_SIZE }, |
@@ -4846,9 +5720,16 @@ static const struct mgmt_handler { | |||
4846 | { set_privacy, false, MGMT_SET_PRIVACY_SIZE }, | 5720 | { set_privacy, false, MGMT_SET_PRIVACY_SIZE }, |
4847 | { load_irks, true, MGMT_LOAD_IRKS_SIZE }, | 5721 | { load_irks, true, MGMT_LOAD_IRKS_SIZE }, |
4848 | { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE }, | 5722 | { get_conn_info, false, MGMT_GET_CONN_INFO_SIZE }, |
5723 | { get_clock_info, false, MGMT_GET_CLOCK_INFO_SIZE }, | ||
5724 | { add_device, false, MGMT_ADD_DEVICE_SIZE }, | ||
5725 | { remove_device, false, MGMT_REMOVE_DEVICE_SIZE }, | ||
5726 | { load_conn_param, true, MGMT_LOAD_CONN_PARAM_SIZE }, | ||
5727 | { read_unconf_index_list, false, MGMT_READ_UNCONF_INDEX_LIST_SIZE }, | ||
5728 | { read_config_info, false, MGMT_READ_CONFIG_INFO_SIZE }, | ||
5729 | { set_external_config, false, MGMT_SET_EXTERNAL_CONFIG_SIZE }, | ||
5730 | { set_public_address, false, MGMT_SET_PUBLIC_ADDRESS_SIZE }, | ||
4849 | }; | 5731 | }; |
4850 | 5732 | ||
4851 | |||
4852 | int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) | 5733 | int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) |
4853 | { | 5734 | { |
4854 | void *buf; | 5735 | void *buf; |
@@ -4892,11 +5773,21 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) | |||
4892 | } | 5773 | } |
4893 | 5774 | ||
4894 | if (test_bit(HCI_SETUP, &hdev->dev_flags) || | 5775 | if (test_bit(HCI_SETUP, &hdev->dev_flags) || |
5776 | test_bit(HCI_CONFIG, &hdev->dev_flags) || | ||
4895 | test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) { | 5777 | test_bit(HCI_USER_CHANNEL, &hdev->dev_flags)) { |
4896 | err = cmd_status(sk, index, opcode, | 5778 | err = cmd_status(sk, index, opcode, |
4897 | MGMT_STATUS_INVALID_INDEX); | 5779 | MGMT_STATUS_INVALID_INDEX); |
4898 | goto done; | 5780 | goto done; |
4899 | } | 5781 | } |
5782 | |||
5783 | if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags) && | ||
5784 | opcode != MGMT_OP_READ_CONFIG_INFO && | ||
5785 | opcode != MGMT_OP_SET_EXTERNAL_CONFIG && | ||
5786 | opcode != MGMT_OP_SET_PUBLIC_ADDRESS) { | ||
5787 | err = cmd_status(sk, index, opcode, | ||
5788 | MGMT_STATUS_INVALID_INDEX); | ||
5789 | goto done; | ||
5790 | } | ||
4900 | } | 5791 | } |
4901 | 5792 | ||
4902 | if (opcode >= ARRAY_SIZE(mgmt_handlers) || | 5793 | if (opcode >= ARRAY_SIZE(mgmt_handlers) || |
@@ -4907,8 +5798,15 @@ int mgmt_control(struct sock *sk, struct msghdr *msg, size_t msglen) | |||
4907 | goto done; | 5798 | goto done; |
4908 | } | 5799 | } |
4909 | 5800 | ||
4910 | if ((hdev && opcode < MGMT_OP_READ_INFO) || | 5801 | if (hdev && (opcode <= MGMT_OP_READ_INDEX_LIST || |
4911 | (!hdev && opcode >= MGMT_OP_READ_INFO)) { | 5802 | opcode == MGMT_OP_READ_UNCONF_INDEX_LIST)) { |
5803 | err = cmd_status(sk, index, opcode, | ||
5804 | MGMT_STATUS_INVALID_INDEX); | ||
5805 | goto done; | ||
5806 | } | ||
5807 | |||
5808 | if (!hdev && (opcode > MGMT_OP_READ_INDEX_LIST && | ||
5809 | opcode != MGMT_OP_READ_UNCONF_INDEX_LIST)) { | ||
4912 | err = cmd_status(sk, index, opcode, | 5810 | err = cmd_status(sk, index, opcode, |
4913 | MGMT_STATUS_INVALID_INDEX); | 5811 | MGMT_STATUS_INVALID_INDEX); |
4914 | goto done; | 5812 | goto done; |
@@ -4947,7 +5845,13 @@ void mgmt_index_added(struct hci_dev *hdev) | |||
4947 | if (hdev->dev_type != HCI_BREDR) | 5845 | if (hdev->dev_type != HCI_BREDR) |
4948 | return; | 5846 | return; |
4949 | 5847 | ||
4950 | mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL); | 5848 | if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) |
5849 | return; | ||
5850 | |||
5851 | if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) | ||
5852 | mgmt_event(MGMT_EV_UNCONF_INDEX_ADDED, hdev, NULL, 0, NULL); | ||
5853 | else | ||
5854 | mgmt_event(MGMT_EV_INDEX_ADDED, hdev, NULL, 0, NULL); | ||
4951 | } | 5855 | } |
4952 | 5856 | ||
4953 | void mgmt_index_removed(struct hci_dev *hdev) | 5857 | void mgmt_index_removed(struct hci_dev *hdev) |
@@ -4957,20 +5861,42 @@ void mgmt_index_removed(struct hci_dev *hdev) | |||
4957 | if (hdev->dev_type != HCI_BREDR) | 5861 | if (hdev->dev_type != HCI_BREDR) |
4958 | return; | 5862 | return; |
4959 | 5863 | ||
5864 | if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks)) | ||
5865 | return; | ||
5866 | |||
4960 | mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); | 5867 | mgmt_pending_foreach(0, hdev, cmd_status_rsp, &status); |
4961 | 5868 | ||
4962 | mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL); | 5869 | if (test_bit(HCI_UNCONFIGURED, &hdev->dev_flags)) |
5870 | mgmt_event(MGMT_EV_UNCONF_INDEX_REMOVED, hdev, NULL, 0, NULL); | ||
5871 | else | ||
5872 | mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL); | ||
4963 | } | 5873 | } |
4964 | 5874 | ||
4965 | /* This function requires the caller holds hdev->lock */ | 5875 | /* This function requires the caller holds hdev->lock */ |
4966 | static void restart_le_auto_conns(struct hci_dev *hdev) | 5876 | static void restart_le_actions(struct hci_dev *hdev) |
4967 | { | 5877 | { |
4968 | struct hci_conn_params *p; | 5878 | struct hci_conn_params *p; |
4969 | 5879 | ||
4970 | list_for_each_entry(p, &hdev->le_conn_params, list) { | 5880 | list_for_each_entry(p, &hdev->le_conn_params, list) { |
4971 | if (p->auto_connect == HCI_AUTO_CONN_ALWAYS) | 5881 | /* Needed for AUTO_OFF case where might not "really" |
4972 | hci_pend_le_conn_add(hdev, &p->addr, p->addr_type); | 5882 | * have been powered off. |
5883 | */ | ||
5884 | list_del_init(&p->action); | ||
5885 | |||
5886 | switch (p->auto_connect) { | ||
5887 | case HCI_AUTO_CONN_DIRECT: | ||
5888 | case HCI_AUTO_CONN_ALWAYS: | ||
5889 | list_add(&p->action, &hdev->pend_le_conns); | ||
5890 | break; | ||
5891 | case HCI_AUTO_CONN_REPORT: | ||
5892 | list_add(&p->action, &hdev->pend_le_reports); | ||
5893 | break; | ||
5894 | default: | ||
5895 | break; | ||
5896 | } | ||
4973 | } | 5897 | } |
5898 | |||
5899 | hci_update_background_scan(hdev); | ||
4974 | } | 5900 | } |
4975 | 5901 | ||
4976 | static void powered_complete(struct hci_dev *hdev, u8 status) | 5902 | static void powered_complete(struct hci_dev *hdev, u8 status) |
@@ -4981,7 +5907,7 @@ static void powered_complete(struct hci_dev *hdev, u8 status) | |||
4981 | 5907 | ||
4982 | hci_dev_lock(hdev); | 5908 | hci_dev_lock(hdev); |
4983 | 5909 | ||
4984 | restart_le_auto_conns(hdev); | 5910 | restart_le_actions(hdev); |
4985 | 5911 | ||
4986 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); | 5912 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); |
4987 | 5913 | ||
@@ -5011,8 +5937,8 @@ static int powered_update_hci(struct hci_dev *hdev) | |||
5011 | lmp_bredr_capable(hdev)) { | 5937 | lmp_bredr_capable(hdev)) { |
5012 | struct hci_cp_write_le_host_supported cp; | 5938 | struct hci_cp_write_le_host_supported cp; |
5013 | 5939 | ||
5014 | cp.le = 1; | 5940 | cp.le = 0x01; |
5015 | cp.simul = lmp_le_br_capable(hdev); | 5941 | cp.simul = 0x00; |
5016 | 5942 | ||
5017 | /* Check first if we already have the right | 5943 | /* Check first if we already have the right |
5018 | * host state (host features set) | 5944 | * host state (host features set) |
@@ -5138,92 +6064,6 @@ void mgmt_discoverable_timeout(struct hci_dev *hdev) | |||
5138 | hci_dev_unlock(hdev); | 6064 | hci_dev_unlock(hdev); |
5139 | } | 6065 | } |
5140 | 6066 | ||
5141 | void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable) | ||
5142 | { | ||
5143 | bool changed; | ||
5144 | |||
5145 | /* Nothing needed here if there's a pending command since that | ||
5146 | * commands request completion callback takes care of everything | ||
5147 | * necessary. | ||
5148 | */ | ||
5149 | if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev)) | ||
5150 | return; | ||
5151 | |||
5152 | /* Powering off may clear the scan mode - don't let that interfere */ | ||
5153 | if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) | ||
5154 | return; | ||
5155 | |||
5156 | if (discoverable) { | ||
5157 | changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags); | ||
5158 | } else { | ||
5159 | clear_bit(HCI_LIMITED_DISCOVERABLE, &hdev->dev_flags); | ||
5160 | changed = test_and_clear_bit(HCI_DISCOVERABLE, &hdev->dev_flags); | ||
5161 | } | ||
5162 | |||
5163 | if (changed) { | ||
5164 | struct hci_request req; | ||
5165 | |||
5166 | /* In case this change in discoverable was triggered by | ||
5167 | * a disabling of connectable there could be a need to | ||
5168 | * update the advertising flags. | ||
5169 | */ | ||
5170 | hci_req_init(&req, hdev); | ||
5171 | update_adv_data(&req); | ||
5172 | hci_req_run(&req, NULL); | ||
5173 | |||
5174 | new_settings(hdev, NULL); | ||
5175 | } | ||
5176 | } | ||
5177 | |||
5178 | void mgmt_connectable(struct hci_dev *hdev, u8 connectable) | ||
5179 | { | ||
5180 | bool changed; | ||
5181 | |||
5182 | /* Nothing needed here if there's a pending command since that | ||
5183 | * commands request completion callback takes care of everything | ||
5184 | * necessary. | ||
5185 | */ | ||
5186 | if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) | ||
5187 | return; | ||
5188 | |||
5189 | /* Powering off may clear the scan mode - don't let that interfere */ | ||
5190 | if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) | ||
5191 | return; | ||
5192 | |||
5193 | if (connectable) | ||
5194 | changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags); | ||
5195 | else | ||
5196 | changed = test_and_clear_bit(HCI_CONNECTABLE, &hdev->dev_flags); | ||
5197 | |||
5198 | if (changed) | ||
5199 | new_settings(hdev, NULL); | ||
5200 | } | ||
5201 | |||
5202 | void mgmt_advertising(struct hci_dev *hdev, u8 advertising) | ||
5203 | { | ||
5204 | /* Powering off may stop advertising - don't let that interfere */ | ||
5205 | if (!advertising && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) | ||
5206 | return; | ||
5207 | |||
5208 | if (advertising) | ||
5209 | set_bit(HCI_ADVERTISING, &hdev->dev_flags); | ||
5210 | else | ||
5211 | clear_bit(HCI_ADVERTISING, &hdev->dev_flags); | ||
5212 | } | ||
5213 | |||
5214 | void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status) | ||
5215 | { | ||
5216 | u8 mgmt_err = mgmt_status(status); | ||
5217 | |||
5218 | if (scan & SCAN_PAGE) | ||
5219 | mgmt_pending_foreach(MGMT_OP_SET_CONNECTABLE, hdev, | ||
5220 | cmd_status_rsp, &mgmt_err); | ||
5221 | |||
5222 | if (scan & SCAN_INQUIRY) | ||
5223 | mgmt_pending_foreach(MGMT_OP_SET_DISCOVERABLE, hdev, | ||
5224 | cmd_status_rsp, &mgmt_err); | ||
5225 | } | ||
5226 | |||
5227 | void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, | 6067 | void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, |
5228 | bool persistent) | 6068 | bool persistent) |
5229 | { | 6069 | { |
@@ -5279,7 +6119,7 @@ void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent) | |||
5279 | ev.key.ediv = key->ediv; | 6119 | ev.key.ediv = key->ediv; |
5280 | ev.key.rand = key->rand; | 6120 | ev.key.rand = key->rand; |
5281 | 6121 | ||
5282 | if (key->type == HCI_SMP_LTK) | 6122 | if (key->type == SMP_LTK) |
5283 | ev.key.master = 1; | 6123 | ev.key.master = 1; |
5284 | 6124 | ||
5285 | memcpy(ev.key.val, key->val, sizeof(key->val)); | 6125 | memcpy(ev.key.val, key->val, sizeof(key->val)); |
@@ -5347,6 +6187,27 @@ void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk, | |||
5347 | mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL); | 6187 | mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL); |
5348 | } | 6188 | } |
5349 | 6189 | ||
6190 | void mgmt_new_conn_param(struct hci_dev *hdev, bdaddr_t *bdaddr, | ||
6191 | u8 bdaddr_type, u8 store_hint, u16 min_interval, | ||
6192 | u16 max_interval, u16 latency, u16 timeout) | ||
6193 | { | ||
6194 | struct mgmt_ev_new_conn_param ev; | ||
6195 | |||
6196 | if (!hci_is_identity_address(bdaddr, bdaddr_type)) | ||
6197 | return; | ||
6198 | |||
6199 | memset(&ev, 0, sizeof(ev)); | ||
6200 | bacpy(&ev.addr.bdaddr, bdaddr); | ||
6201 | ev.addr.type = link_to_bdaddr(LE_LINK, bdaddr_type); | ||
6202 | ev.store_hint = store_hint; | ||
6203 | ev.min_interval = cpu_to_le16(min_interval); | ||
6204 | ev.max_interval = cpu_to_le16(max_interval); | ||
6205 | ev.latency = cpu_to_le16(latency); | ||
6206 | ev.timeout = cpu_to_le16(timeout); | ||
6207 | |||
6208 | mgmt_event(MGMT_EV_NEW_CONN_PARAM, hdev, &ev, sizeof(ev), NULL); | ||
6209 | } | ||
6210 | |||
5350 | static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data, | 6211 | static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data, |
5351 | u8 data_len) | 6212 | u8 data_len) |
5352 | { | 6213 | { |
@@ -5765,10 +6626,14 @@ void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) | |||
5765 | 6626 | ||
5766 | hci_req_init(&req, hdev); | 6627 | hci_req_init(&req, hdev); |
5767 | 6628 | ||
5768 | if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) | 6629 | if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) { |
6630 | if (test_bit(HCI_USE_DEBUG_KEYS, &hdev->dev_flags)) | ||
6631 | hci_req_add(&req, HCI_OP_WRITE_SSP_DEBUG_MODE, | ||
6632 | sizeof(enable), &enable); | ||
5769 | update_eir(&req); | 6633 | update_eir(&req); |
5770 | else | 6634 | } else { |
5771 | clear_eir(&req); | 6635 | clear_eir(&req); |
6636 | } | ||
5772 | 6637 | ||
5773 | hci_req_run(&req, NULL); | 6638 | hci_req_run(&req, NULL); |
5774 | } | 6639 | } |
@@ -5912,17 +6777,23 @@ void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192, | |||
5912 | } | 6777 | } |
5913 | 6778 | ||
5914 | void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | 6779 | void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, |
5915 | u8 addr_type, u8 *dev_class, s8 rssi, u8 cfm_name, | 6780 | u8 addr_type, u8 *dev_class, s8 rssi, u32 flags, |
5916 | u8 ssp, u8 *eir, u16 eir_len, u8 *scan_rsp, | 6781 | u8 *eir, u16 eir_len, u8 *scan_rsp, u8 scan_rsp_len) |
5917 | u8 scan_rsp_len) | ||
5918 | { | 6782 | { |
5919 | char buf[512]; | 6783 | char buf[512]; |
5920 | struct mgmt_ev_device_found *ev = (void *) buf; | 6784 | struct mgmt_ev_device_found *ev = (void *) buf; |
5921 | struct smp_irk *irk; | ||
5922 | size_t ev_size; | 6785 | size_t ev_size; |
5923 | 6786 | ||
5924 | if (!hci_discovery_active(hdev)) | 6787 | /* Don't send events for a non-kernel initiated discovery. With |
5925 | return; | 6788 | * LE one exception is if we have pend_le_reports > 0 in which |
6789 | * case we're doing passive scanning and want these events. | ||
6790 | */ | ||
6791 | if (!hci_discovery_active(hdev)) { | ||
6792 | if (link_type == ACL_LINK) | ||
6793 | return; | ||
6794 | if (link_type == LE_LINK && list_empty(&hdev->pend_le_reports)) | ||
6795 | return; | ||
6796 | } | ||
5926 | 6797 | ||
5927 | /* Make sure that the buffer is big enough. The 5 extra bytes | 6798 | /* Make sure that the buffer is big enough. The 5 extra bytes |
5928 | * are for the potential CoD field. | 6799 | * are for the potential CoD field. |
@@ -5932,20 +6803,10 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | |||
5932 | 6803 | ||
5933 | memset(buf, 0, sizeof(buf)); | 6804 | memset(buf, 0, sizeof(buf)); |
5934 | 6805 | ||
5935 | irk = hci_get_irk(hdev, bdaddr, addr_type); | 6806 | bacpy(&ev->addr.bdaddr, bdaddr); |
5936 | if (irk) { | 6807 | ev->addr.type = link_to_bdaddr(link_type, addr_type); |
5937 | bacpy(&ev->addr.bdaddr, &irk->bdaddr); | ||
5938 | ev->addr.type = link_to_bdaddr(link_type, irk->addr_type); | ||
5939 | } else { | ||
5940 | bacpy(&ev->addr.bdaddr, bdaddr); | ||
5941 | ev->addr.type = link_to_bdaddr(link_type, addr_type); | ||
5942 | } | ||
5943 | |||
5944 | ev->rssi = rssi; | 6808 | ev->rssi = rssi; |
5945 | if (cfm_name) | 6809 | ev->flags = cpu_to_le32(flags); |
5946 | ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME); | ||
5947 | if (!ssp) | ||
5948 | ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_LEGACY_PAIRING); | ||
5949 | 6810 | ||
5950 | if (eir_len > 0) | 6811 | if (eir_len > 0) |
5951 | memcpy(ev->eir, eir, eir_len); | 6812 | memcpy(ev->eir, eir, eir_len); |
@@ -6013,63 +6874,19 @@ void mgmt_discovering(struct hci_dev *hdev, u8 discovering) | |||
6013 | mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL); | 6874 | mgmt_event(MGMT_EV_DISCOVERING, hdev, &ev, sizeof(ev), NULL); |
6014 | } | 6875 | } |
6015 | 6876 | ||
6016 | int mgmt_device_blocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) | ||
6017 | { | ||
6018 | struct pending_cmd *cmd; | ||
6019 | struct mgmt_ev_device_blocked ev; | ||
6020 | |||
6021 | cmd = mgmt_pending_find(MGMT_OP_BLOCK_DEVICE, hdev); | ||
6022 | |||
6023 | bacpy(&ev.addr.bdaddr, bdaddr); | ||
6024 | ev.addr.type = type; | ||
6025 | |||
6026 | return mgmt_event(MGMT_EV_DEVICE_BLOCKED, hdev, &ev, sizeof(ev), | ||
6027 | cmd ? cmd->sk : NULL); | ||
6028 | } | ||
6029 | |||
6030 | int mgmt_device_unblocked(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) | ||
6031 | { | ||
6032 | struct pending_cmd *cmd; | ||
6033 | struct mgmt_ev_device_unblocked ev; | ||
6034 | |||
6035 | cmd = mgmt_pending_find(MGMT_OP_UNBLOCK_DEVICE, hdev); | ||
6036 | |||
6037 | bacpy(&ev.addr.bdaddr, bdaddr); | ||
6038 | ev.addr.type = type; | ||
6039 | |||
6040 | return mgmt_event(MGMT_EV_DEVICE_UNBLOCKED, hdev, &ev, sizeof(ev), | ||
6041 | cmd ? cmd->sk : NULL); | ||
6042 | } | ||
6043 | |||
6044 | static void adv_enable_complete(struct hci_dev *hdev, u8 status) | 6877 | static void adv_enable_complete(struct hci_dev *hdev, u8 status) |
6045 | { | 6878 | { |
6046 | BT_DBG("%s status %u", hdev->name, status); | 6879 | BT_DBG("%s status %u", hdev->name, status); |
6047 | |||
6048 | /* Clear the advertising mgmt setting if we failed to re-enable it */ | ||
6049 | if (status) { | ||
6050 | clear_bit(HCI_ADVERTISING, &hdev->dev_flags); | ||
6051 | new_settings(hdev, NULL); | ||
6052 | } | ||
6053 | } | 6880 | } |
6054 | 6881 | ||
6055 | void mgmt_reenable_advertising(struct hci_dev *hdev) | 6882 | void mgmt_reenable_advertising(struct hci_dev *hdev) |
6056 | { | 6883 | { |
6057 | struct hci_request req; | 6884 | struct hci_request req; |
6058 | 6885 | ||
6059 | if (hci_conn_num(hdev, LE_LINK) > 0) | ||
6060 | return; | ||
6061 | |||
6062 | if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags)) | 6886 | if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags)) |
6063 | return; | 6887 | return; |
6064 | 6888 | ||
6065 | hci_req_init(&req, hdev); | 6889 | hci_req_init(&req, hdev); |
6066 | enable_advertising(&req); | 6890 | enable_advertising(&req); |
6067 | 6891 | hci_req_run(&req, adv_enable_complete); | |
6068 | /* If this fails we have no option but to let user space know | ||
6069 | * that we've disabled advertising. | ||
6070 | */ | ||
6071 | if (hci_req_run(&req, adv_enable_complete) < 0) { | ||
6072 | clear_bit(HCI_ADVERTISING, &hdev->dev_flags); | ||
6073 | new_settings(hdev, NULL); | ||
6074 | } | ||
6075 | } | 6892 | } |
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 754b6fe4f742..af73bc3acb40 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
@@ -227,7 +227,8 @@ static int rfcomm_check_security(struct rfcomm_dlc *d) | |||
227 | break; | 227 | break; |
228 | } | 228 | } |
229 | 229 | ||
230 | return hci_conn_security(conn->hcon, d->sec_level, auth_type); | 230 | return hci_conn_security(conn->hcon, d->sec_level, auth_type, |
231 | d->out); | ||
231 | } | 232 | } |
232 | 233 | ||
233 | static void rfcomm_session_timeout(unsigned long arg) | 234 | static void rfcomm_session_timeout(unsigned long arg) |
@@ -1909,10 +1910,13 @@ static struct rfcomm_session *rfcomm_process_rx(struct rfcomm_session *s) | |||
1909 | /* Get data directly from socket receive queue without copying it. */ | 1910 | /* Get data directly from socket receive queue without copying it. */ |
1910 | while ((skb = skb_dequeue(&sk->sk_receive_queue))) { | 1911 | while ((skb = skb_dequeue(&sk->sk_receive_queue))) { |
1911 | skb_orphan(skb); | 1912 | skb_orphan(skb); |
1912 | if (!skb_linearize(skb)) | 1913 | if (!skb_linearize(skb)) { |
1913 | s = rfcomm_recv_frame(s, skb); | 1914 | s = rfcomm_recv_frame(s, skb); |
1914 | else | 1915 | if (!s) |
1916 | break; | ||
1917 | } else { | ||
1915 | kfree_skb(skb); | 1918 | kfree_skb(skb); |
1919 | } | ||
1916 | } | 1920 | } |
1917 | 1921 | ||
1918 | if (s && (sk->sk_state == BT_CLOSED)) | 1922 | if (s && (sk->sk_state == BT_CLOSED)) |
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index c603a5eb4720..8bbbb5ec468c 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c | |||
@@ -918,7 +918,8 @@ static int rfcomm_sock_shutdown(struct socket *sock, int how) | |||
918 | sk->sk_shutdown = SHUTDOWN_MASK; | 918 | sk->sk_shutdown = SHUTDOWN_MASK; |
919 | __rfcomm_sock_close(sk); | 919 | __rfcomm_sock_close(sk); |
920 | 920 | ||
921 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) | 921 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime && |
922 | !(current->flags & PF_EXITING)) | ||
922 | err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime); | 923 | err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime); |
923 | } | 924 | } |
924 | release_sock(sk); | 925 | release_sock(sk); |
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index c06dbd3938e8..7ee9e4ab00f8 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
@@ -40,13 +40,38 @@ static struct bt_sock_list sco_sk_list = { | |||
40 | .lock = __RW_LOCK_UNLOCKED(sco_sk_list.lock) | 40 | .lock = __RW_LOCK_UNLOCKED(sco_sk_list.lock) |
41 | }; | 41 | }; |
42 | 42 | ||
43 | static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent); | 43 | /* ---- SCO connections ---- */ |
44 | static void sco_chan_del(struct sock *sk, int err); | 44 | struct sco_conn { |
45 | struct hci_conn *hcon; | ||
46 | |||
47 | spinlock_t lock; | ||
48 | struct sock *sk; | ||
49 | |||
50 | unsigned int mtu; | ||
51 | }; | ||
52 | |||
53 | #define sco_conn_lock(c) spin_lock(&c->lock); | ||
54 | #define sco_conn_unlock(c) spin_unlock(&c->lock); | ||
45 | 55 | ||
46 | static void sco_sock_close(struct sock *sk); | 56 | static void sco_sock_close(struct sock *sk); |
47 | static void sco_sock_kill(struct sock *sk); | 57 | static void sco_sock_kill(struct sock *sk); |
48 | 58 | ||
59 | /* ----- SCO socket info ----- */ | ||
60 | #define sco_pi(sk) ((struct sco_pinfo *) sk) | ||
61 | |||
62 | struct sco_pinfo { | ||
63 | struct bt_sock bt; | ||
64 | bdaddr_t src; | ||
65 | bdaddr_t dst; | ||
66 | __u32 flags; | ||
67 | __u16 setting; | ||
68 | struct sco_conn *conn; | ||
69 | }; | ||
70 | |||
49 | /* ---- SCO timers ---- */ | 71 | /* ---- SCO timers ---- */ |
72 | #define SCO_CONN_TIMEOUT (HZ * 40) | ||
73 | #define SCO_DISCONN_TIMEOUT (HZ * 2) | ||
74 | |||
50 | static void sco_sock_timeout(unsigned long arg) | 75 | static void sco_sock_timeout(unsigned long arg) |
51 | { | 76 | { |
52 | struct sock *sk = (struct sock *) arg; | 77 | struct sock *sk = (struct sock *) arg; |
@@ -102,13 +127,31 @@ static struct sco_conn *sco_conn_add(struct hci_conn *hcon) | |||
102 | return conn; | 127 | return conn; |
103 | } | 128 | } |
104 | 129 | ||
105 | static struct sock *sco_chan_get(struct sco_conn *conn) | 130 | /* Delete channel. |
131 | * Must be called on the locked socket. */ | ||
132 | static void sco_chan_del(struct sock *sk, int err) | ||
106 | { | 133 | { |
107 | struct sock *sk = NULL; | 134 | struct sco_conn *conn; |
108 | sco_conn_lock(conn); | 135 | |
109 | sk = conn->sk; | 136 | conn = sco_pi(sk)->conn; |
110 | sco_conn_unlock(conn); | 137 | |
111 | return sk; | 138 | BT_DBG("sk %p, conn %p, err %d", sk, conn, err); |
139 | |||
140 | if (conn) { | ||
141 | sco_conn_lock(conn); | ||
142 | conn->sk = NULL; | ||
143 | sco_pi(sk)->conn = NULL; | ||
144 | sco_conn_unlock(conn); | ||
145 | |||
146 | if (conn->hcon) | ||
147 | hci_conn_drop(conn->hcon); | ||
148 | } | ||
149 | |||
150 | sk->sk_state = BT_CLOSED; | ||
151 | sk->sk_err = err; | ||
152 | sk->sk_state_change(sk); | ||
153 | |||
154 | sock_set_flag(sk, SOCK_ZAPPED); | ||
112 | } | 155 | } |
113 | 156 | ||
114 | static int sco_conn_del(struct hci_conn *hcon, int err) | 157 | static int sco_conn_del(struct hci_conn *hcon, int err) |
@@ -122,7 +165,10 @@ static int sco_conn_del(struct hci_conn *hcon, int err) | |||
122 | BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); | 165 | BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); |
123 | 166 | ||
124 | /* Kill socket */ | 167 | /* Kill socket */ |
125 | sk = sco_chan_get(conn); | 168 | sco_conn_lock(conn); |
169 | sk = conn->sk; | ||
170 | sco_conn_unlock(conn); | ||
171 | |||
126 | if (sk) { | 172 | if (sk) { |
127 | bh_lock_sock(sk); | 173 | bh_lock_sock(sk); |
128 | sco_sock_clear_timer(sk); | 174 | sco_sock_clear_timer(sk); |
@@ -136,6 +182,17 @@ static int sco_conn_del(struct hci_conn *hcon, int err) | |||
136 | return 0; | 182 | return 0; |
137 | } | 183 | } |
138 | 184 | ||
185 | static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent) | ||
186 | { | ||
187 | BT_DBG("conn %p", conn); | ||
188 | |||
189 | sco_pi(sk)->conn = conn; | ||
190 | conn->sk = sk; | ||
191 | |||
192 | if (parent) | ||
193 | bt_accept_enqueue(parent, sk); | ||
194 | } | ||
195 | |||
139 | static int sco_chan_add(struct sco_conn *conn, struct sock *sk, | 196 | static int sco_chan_add(struct sco_conn *conn, struct sock *sk, |
140 | struct sock *parent) | 197 | struct sock *parent) |
141 | { | 198 | { |
@@ -240,7 +297,11 @@ static int sco_send_frame(struct sock *sk, struct msghdr *msg, int len) | |||
240 | 297 | ||
241 | static void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb) | 298 | static void sco_recv_frame(struct sco_conn *conn, struct sk_buff *skb) |
242 | { | 299 | { |
243 | struct sock *sk = sco_chan_get(conn); | 300 | struct sock *sk; |
301 | |||
302 | sco_conn_lock(conn); | ||
303 | sk = conn->sk; | ||
304 | sco_conn_unlock(conn); | ||
244 | 305 | ||
245 | if (!sk) | 306 | if (!sk) |
246 | goto drop; | 307 | goto drop; |
@@ -909,7 +970,8 @@ static int sco_sock_shutdown(struct socket *sock, int how) | |||
909 | sco_sock_clear_timer(sk); | 970 | sco_sock_clear_timer(sk); |
910 | __sco_sock_close(sk); | 971 | __sco_sock_close(sk); |
911 | 972 | ||
912 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) | 973 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime && |
974 | !(current->flags & PF_EXITING)) | ||
913 | err = bt_sock_wait_state(sk, BT_CLOSED, | 975 | err = bt_sock_wait_state(sk, BT_CLOSED, |
914 | sk->sk_lingertime); | 976 | sk->sk_lingertime); |
915 | } | 977 | } |
@@ -929,7 +991,8 @@ static int sco_sock_release(struct socket *sock) | |||
929 | 991 | ||
930 | sco_sock_close(sk); | 992 | sco_sock_close(sk); |
931 | 993 | ||
932 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime) { | 994 | if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime && |
995 | !(current->flags & PF_EXITING)) { | ||
933 | lock_sock(sk); | 996 | lock_sock(sk); |
934 | err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime); | 997 | err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime); |
935 | release_sock(sk); | 998 | release_sock(sk); |
@@ -940,44 +1003,6 @@ static int sco_sock_release(struct socket *sock) | |||
940 | return err; | 1003 | return err; |
941 | } | 1004 | } |
942 | 1005 | ||
943 | static void __sco_chan_add(struct sco_conn *conn, struct sock *sk, struct sock *parent) | ||
944 | { | ||
945 | BT_DBG("conn %p", conn); | ||
946 | |||
947 | sco_pi(sk)->conn = conn; | ||
948 | conn->sk = sk; | ||
949 | |||
950 | if (parent) | ||
951 | bt_accept_enqueue(parent, sk); | ||
952 | } | ||
953 | |||
954 | /* Delete channel. | ||
955 | * Must be called on the locked socket. */ | ||
956 | static void sco_chan_del(struct sock *sk, int err) | ||
957 | { | ||
958 | struct sco_conn *conn; | ||
959 | |||
960 | conn = sco_pi(sk)->conn; | ||
961 | |||
962 | BT_DBG("sk %p, conn %p, err %d", sk, conn, err); | ||
963 | |||
964 | if (conn) { | ||
965 | sco_conn_lock(conn); | ||
966 | conn->sk = NULL; | ||
967 | sco_pi(sk)->conn = NULL; | ||
968 | sco_conn_unlock(conn); | ||
969 | |||
970 | if (conn->hcon) | ||
971 | hci_conn_drop(conn->hcon); | ||
972 | } | ||
973 | |||
974 | sk->sk_state = BT_CLOSED; | ||
975 | sk->sk_err = err; | ||
976 | sk->sk_state_change(sk); | ||
977 | |||
978 | sock_set_flag(sk, SOCK_ZAPPED); | ||
979 | } | ||
980 | |||
981 | static void sco_conn_ready(struct sco_conn *conn) | 1006 | static void sco_conn_ready(struct sco_conn *conn) |
982 | { | 1007 | { |
983 | struct sock *parent; | 1008 | struct sock *parent; |
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index e33a982161c1..fd3294300803 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
@@ -35,11 +35,13 @@ | |||
35 | 35 | ||
36 | #define AUTH_REQ_MASK 0x07 | 36 | #define AUTH_REQ_MASK 0x07 |
37 | 37 | ||
38 | #define SMP_FLAG_TK_VALID 1 | 38 | enum { |
39 | #define SMP_FLAG_CFM_PENDING 2 | 39 | SMP_FLAG_TK_VALID, |
40 | #define SMP_FLAG_MITM_AUTH 3 | 40 | SMP_FLAG_CFM_PENDING, |
41 | #define SMP_FLAG_COMPLETE 4 | 41 | SMP_FLAG_MITM_AUTH, |
42 | #define SMP_FLAG_INITIATOR 5 | 42 | SMP_FLAG_COMPLETE, |
43 | SMP_FLAG_INITIATOR, | ||
44 | }; | ||
43 | 45 | ||
44 | struct smp_chan { | 46 | struct smp_chan { |
45 | struct l2cap_conn *conn; | 47 | struct l2cap_conn *conn; |
@@ -60,20 +62,16 @@ struct smp_chan { | |||
60 | struct smp_ltk *slave_ltk; | 62 | struct smp_ltk *slave_ltk; |
61 | struct smp_irk *remote_irk; | 63 | struct smp_irk *remote_irk; |
62 | unsigned long flags; | 64 | unsigned long flags; |
65 | |||
66 | struct crypto_blkcipher *tfm_aes; | ||
63 | }; | 67 | }; |
64 | 68 | ||
65 | static inline void swap128(const u8 src[16], u8 dst[16]) | 69 | static inline void swap_buf(const u8 *src, u8 *dst, size_t len) |
66 | { | 70 | { |
67 | int i; | 71 | size_t i; |
68 | for (i = 0; i < 16; i++) | ||
69 | dst[15 - i] = src[i]; | ||
70 | } | ||
71 | 72 | ||
72 | static inline void swap56(const u8 src[7], u8 dst[7]) | 73 | for (i = 0; i < len; i++) |
73 | { | 74 | dst[len - 1 - i] = src[i]; |
74 | int i; | ||
75 | for (i = 0; i < 7; i++) | ||
76 | dst[6 - i] = src[i]; | ||
77 | } | 75 | } |
78 | 76 | ||
79 | static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r) | 77 | static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r) |
@@ -92,7 +90,7 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r) | |||
92 | desc.flags = 0; | 90 | desc.flags = 0; |
93 | 91 | ||
94 | /* The most significant octet of key corresponds to k[0] */ | 92 | /* The most significant octet of key corresponds to k[0] */ |
95 | swap128(k, tmp); | 93 | swap_buf(k, tmp, 16); |
96 | 94 | ||
97 | err = crypto_blkcipher_setkey(tfm, tmp, 16); | 95 | err = crypto_blkcipher_setkey(tfm, tmp, 16); |
98 | if (err) { | 96 | if (err) { |
@@ -101,7 +99,7 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r) | |||
101 | } | 99 | } |
102 | 100 | ||
103 | /* Most significant octet of plaintextData corresponds to data[0] */ | 101 | /* Most significant octet of plaintextData corresponds to data[0] */ |
104 | swap128(r, data); | 102 | swap_buf(r, data, 16); |
105 | 103 | ||
106 | sg_init_one(&sg, data, 16); | 104 | sg_init_one(&sg, data, 16); |
107 | 105 | ||
@@ -110,7 +108,7 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r) | |||
110 | BT_ERR("Encrypt data error %d", err); | 108 | BT_ERR("Encrypt data error %d", err); |
111 | 109 | ||
112 | /* Most significant octet of encryptedData corresponds to data[0] */ | 110 | /* Most significant octet of encryptedData corresponds to data[0] */ |
113 | swap128(data, r); | 111 | swap_buf(data, r, 16); |
114 | 112 | ||
115 | return err; | 113 | return err; |
116 | } | 114 | } |
@@ -174,13 +172,16 @@ int smp_generate_rpa(struct crypto_blkcipher *tfm, u8 irk[16], bdaddr_t *rpa) | |||
174 | return 0; | 172 | return 0; |
175 | } | 173 | } |
176 | 174 | ||
177 | static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16], | 175 | static int smp_c1(struct smp_chan *smp, u8 k[16], u8 r[16], u8 preq[7], |
178 | u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia, | 176 | u8 pres[7], u8 _iat, bdaddr_t *ia, u8 _rat, bdaddr_t *ra, |
179 | u8 _rat, bdaddr_t *ra, u8 res[16]) | 177 | u8 res[16]) |
180 | { | 178 | { |
179 | struct hci_dev *hdev = smp->conn->hcon->hdev; | ||
181 | u8 p1[16], p2[16]; | 180 | u8 p1[16], p2[16]; |
182 | int err; | 181 | int err; |
183 | 182 | ||
183 | BT_DBG("%s", hdev->name); | ||
184 | |||
184 | memset(p1, 0, 16); | 185 | memset(p1, 0, 16); |
185 | 186 | ||
186 | /* p1 = pres || preq || _rat || _iat */ | 187 | /* p1 = pres || preq || _rat || _iat */ |
@@ -198,7 +199,7 @@ static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16], | |||
198 | u128_xor((u128 *) res, (u128 *) r, (u128 *) p1); | 199 | u128_xor((u128 *) res, (u128 *) r, (u128 *) p1); |
199 | 200 | ||
200 | /* res = e(k, res) */ | 201 | /* res = e(k, res) */ |
201 | err = smp_e(tfm, k, res); | 202 | err = smp_e(smp->tfm_aes, k, res); |
202 | if (err) { | 203 | if (err) { |
203 | BT_ERR("Encrypt data error"); | 204 | BT_ERR("Encrypt data error"); |
204 | return err; | 205 | return err; |
@@ -208,23 +209,26 @@ static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16], | |||
208 | u128_xor((u128 *) res, (u128 *) res, (u128 *) p2); | 209 | u128_xor((u128 *) res, (u128 *) res, (u128 *) p2); |
209 | 210 | ||
210 | /* res = e(k, res) */ | 211 | /* res = e(k, res) */ |
211 | err = smp_e(tfm, k, res); | 212 | err = smp_e(smp->tfm_aes, k, res); |
212 | if (err) | 213 | if (err) |
213 | BT_ERR("Encrypt data error"); | 214 | BT_ERR("Encrypt data error"); |
214 | 215 | ||
215 | return err; | 216 | return err; |
216 | } | 217 | } |
217 | 218 | ||
218 | static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16], u8 r1[16], | 219 | static int smp_s1(struct smp_chan *smp, u8 k[16], u8 r1[16], u8 r2[16], |
219 | u8 r2[16], u8 _r[16]) | 220 | u8 _r[16]) |
220 | { | 221 | { |
222 | struct hci_dev *hdev = smp->conn->hcon->hdev; | ||
221 | int err; | 223 | int err; |
222 | 224 | ||
225 | BT_DBG("%s", hdev->name); | ||
226 | |||
223 | /* Just least significant octets from r1 and r2 are considered */ | 227 | /* Just least significant octets from r1 and r2 are considered */ |
224 | memcpy(_r, r2, 8); | 228 | memcpy(_r, r2, 8); |
225 | memcpy(_r + 8, r1, 8); | 229 | memcpy(_r + 8, r1, 8); |
226 | 230 | ||
227 | err = smp_e(tfm, k, _r); | 231 | err = smp_e(smp->tfm_aes, k, _r); |
228 | if (err) | 232 | if (err) |
229 | BT_ERR("Encrypt data error"); | 233 | BT_ERR("Encrypt data error"); |
230 | 234 | ||
@@ -303,7 +307,7 @@ static void build_pairing_cmd(struct l2cap_conn *conn, | |||
303 | struct hci_dev *hdev = hcon->hdev; | 307 | struct hci_dev *hdev = hcon->hdev; |
304 | u8 local_dist = 0, remote_dist = 0; | 308 | u8 local_dist = 0, remote_dist = 0; |
305 | 309 | ||
306 | if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->dev_flags)) { | 310 | if (test_bit(HCI_BONDABLE, &conn->hcon->hdev->dev_flags)) { |
307 | local_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN; | 311 | local_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN; |
308 | remote_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN; | 312 | remote_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN; |
309 | authreq |= SMP_AUTH_BONDING; | 313 | authreq |= SMP_AUTH_BONDING; |
@@ -387,10 +391,12 @@ static const u8 gen_method[5][5] = { | |||
387 | 391 | ||
388 | static u8 get_auth_method(struct smp_chan *smp, u8 local_io, u8 remote_io) | 392 | static u8 get_auth_method(struct smp_chan *smp, u8 local_io, u8 remote_io) |
389 | { | 393 | { |
390 | /* If either side has unknown io_caps, use JUST WORKS */ | 394 | /* If either side has unknown io_caps, use JUST_CFM (which gets |
395 | * converted later to JUST_WORKS if we're initiators. | ||
396 | */ | ||
391 | if (local_io > SMP_IO_KEYBOARD_DISPLAY || | 397 | if (local_io > SMP_IO_KEYBOARD_DISPLAY || |
392 | remote_io > SMP_IO_KEYBOARD_DISPLAY) | 398 | remote_io > SMP_IO_KEYBOARD_DISPLAY) |
393 | return JUST_WORKS; | 399 | return JUST_CFM; |
394 | 400 | ||
395 | return gen_method[remote_io][local_io]; | 401 | return gen_method[remote_io][local_io]; |
396 | } | 402 | } |
@@ -410,21 +416,25 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth, | |||
410 | 416 | ||
411 | BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io); | 417 | BT_DBG("tk_request: auth:%d lcl:%d rem:%d", auth, local_io, remote_io); |
412 | 418 | ||
413 | /* If neither side wants MITM, use JUST WORKS */ | 419 | /* If neither side wants MITM, either "just" confirm an incoming |
414 | /* Otherwise, look up method from the table */ | 420 | * request or use just-works for outgoing ones. The JUST_CFM |
421 | * will be converted to JUST_WORKS if necessary later in this | ||
422 | * function. If either side has MITM look up the method from the | ||
423 | * table. | ||
424 | */ | ||
415 | if (!(auth & SMP_AUTH_MITM)) | 425 | if (!(auth & SMP_AUTH_MITM)) |
416 | method = JUST_WORKS; | 426 | method = JUST_CFM; |
417 | else | 427 | else |
418 | method = get_auth_method(smp, local_io, remote_io); | 428 | method = get_auth_method(smp, local_io, remote_io); |
419 | 429 | ||
420 | /* If not bonding, don't ask user to confirm a Zero TK */ | ||
421 | if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM) | ||
422 | method = JUST_WORKS; | ||
423 | |||
424 | /* Don't confirm locally initiated pairing attempts */ | 430 | /* Don't confirm locally initiated pairing attempts */ |
425 | if (method == JUST_CFM && test_bit(SMP_FLAG_INITIATOR, &smp->flags)) | 431 | if (method == JUST_CFM && test_bit(SMP_FLAG_INITIATOR, &smp->flags)) |
426 | method = JUST_WORKS; | 432 | method = JUST_WORKS; |
427 | 433 | ||
434 | /* Don't bother user space with no IO capabilities */ | ||
435 | if (method == JUST_CFM && hcon->io_capability == HCI_IO_NO_INPUT_OUTPUT) | ||
436 | method = JUST_WORKS; | ||
437 | |||
428 | /* If Just Works, Continue with Zero TK */ | 438 | /* If Just Works, Continue with Zero TK */ |
429 | if (method == JUST_WORKS) { | 439 | if (method == JUST_WORKS) { |
430 | set_bit(SMP_FLAG_TK_VALID, &smp->flags); | 440 | set_bit(SMP_FLAG_TK_VALID, &smp->flags); |
@@ -439,7 +449,7 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth, | |||
439 | * Confirms and the slave Enters the passkey. | 449 | * Confirms and the slave Enters the passkey. |
440 | */ | 450 | */ |
441 | if (method == OVERLAP) { | 451 | if (method == OVERLAP) { |
442 | if (hcon->link_mode & HCI_LM_MASTER) | 452 | if (hcon->role == HCI_ROLE_MASTER) |
443 | method = CFM_PASSKEY; | 453 | method = CFM_PASSKEY; |
444 | else | 454 | else |
445 | method = REQ_PASSKEY; | 455 | method = REQ_PASSKEY; |
@@ -477,23 +487,15 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth, | |||
477 | static u8 smp_confirm(struct smp_chan *smp) | 487 | static u8 smp_confirm(struct smp_chan *smp) |
478 | { | 488 | { |
479 | struct l2cap_conn *conn = smp->conn; | 489 | struct l2cap_conn *conn = smp->conn; |
480 | struct hci_dev *hdev = conn->hcon->hdev; | ||
481 | struct crypto_blkcipher *tfm = hdev->tfm_aes; | ||
482 | struct smp_cmd_pairing_confirm cp; | 490 | struct smp_cmd_pairing_confirm cp; |
483 | int ret; | 491 | int ret; |
484 | 492 | ||
485 | BT_DBG("conn %p", conn); | 493 | BT_DBG("conn %p", conn); |
486 | 494 | ||
487 | /* Prevent mutual access to hdev->tfm_aes */ | 495 | ret = smp_c1(smp, smp->tk, smp->prnd, smp->preq, smp->prsp, |
488 | hci_dev_lock(hdev); | ||
489 | |||
490 | ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, | ||
491 | conn->hcon->init_addr_type, &conn->hcon->init_addr, | 496 | conn->hcon->init_addr_type, &conn->hcon->init_addr, |
492 | conn->hcon->resp_addr_type, &conn->hcon->resp_addr, | 497 | conn->hcon->resp_addr_type, &conn->hcon->resp_addr, |
493 | cp.confirm_val); | 498 | cp.confirm_val); |
494 | |||
495 | hci_dev_unlock(hdev); | ||
496 | |||
497 | if (ret) | 499 | if (ret) |
498 | return SMP_UNSPECIFIED; | 500 | return SMP_UNSPECIFIED; |
499 | 501 | ||
@@ -508,25 +510,17 @@ static u8 smp_random(struct smp_chan *smp) | |||
508 | { | 510 | { |
509 | struct l2cap_conn *conn = smp->conn; | 511 | struct l2cap_conn *conn = smp->conn; |
510 | struct hci_conn *hcon = conn->hcon; | 512 | struct hci_conn *hcon = conn->hcon; |
511 | struct hci_dev *hdev = hcon->hdev; | ||
512 | struct crypto_blkcipher *tfm = hdev->tfm_aes; | ||
513 | u8 confirm[16]; | 513 | u8 confirm[16]; |
514 | int ret; | 514 | int ret; |
515 | 515 | ||
516 | if (IS_ERR_OR_NULL(tfm)) | 516 | if (IS_ERR_OR_NULL(smp->tfm_aes)) |
517 | return SMP_UNSPECIFIED; | 517 | return SMP_UNSPECIFIED; |
518 | 518 | ||
519 | BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); | 519 | BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); |
520 | 520 | ||
521 | /* Prevent mutual access to hdev->tfm_aes */ | 521 | ret = smp_c1(smp, smp->tk, smp->rrnd, smp->preq, smp->prsp, |
522 | hci_dev_lock(hdev); | ||
523 | |||
524 | ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, | ||
525 | hcon->init_addr_type, &hcon->init_addr, | 522 | hcon->init_addr_type, &hcon->init_addr, |
526 | hcon->resp_addr_type, &hcon->resp_addr, confirm); | 523 | hcon->resp_addr_type, &hcon->resp_addr, confirm); |
527 | |||
528 | hci_dev_unlock(hdev); | ||
529 | |||
530 | if (ret) | 524 | if (ret) |
531 | return SMP_UNSPECIFIED; | 525 | return SMP_UNSPECIFIED; |
532 | 526 | ||
@@ -540,7 +534,7 @@ static u8 smp_random(struct smp_chan *smp) | |||
540 | __le64 rand = 0; | 534 | __le64 rand = 0; |
541 | __le16 ediv = 0; | 535 | __le16 ediv = 0; |
542 | 536 | ||
543 | smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, stk); | 537 | smp_s1(smp, smp->tk, smp->rrnd, smp->prnd, stk); |
544 | 538 | ||
545 | memset(stk + smp->enc_key_size, 0, | 539 | memset(stk + smp->enc_key_size, 0, |
546 | SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size); | 540 | SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size); |
@@ -550,6 +544,7 @@ static u8 smp_random(struct smp_chan *smp) | |||
550 | 544 | ||
551 | hci_le_start_enc(hcon, ediv, rand, stk); | 545 | hci_le_start_enc(hcon, ediv, rand, stk); |
552 | hcon->enc_key_size = smp->enc_key_size; | 546 | hcon->enc_key_size = smp->enc_key_size; |
547 | set_bit(HCI_CONN_STK_ENCRYPT, &hcon->flags); | ||
553 | } else { | 548 | } else { |
554 | u8 stk[16], auth; | 549 | u8 stk[16], auth; |
555 | __le64 rand = 0; | 550 | __le64 rand = 0; |
@@ -558,7 +553,7 @@ static u8 smp_random(struct smp_chan *smp) | |||
558 | smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd), | 553 | smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd), |
559 | smp->prnd); | 554 | smp->prnd); |
560 | 555 | ||
561 | smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, stk); | 556 | smp_s1(smp, smp->tk, smp->prnd, smp->rrnd, stk); |
562 | 557 | ||
563 | memset(stk + smp->enc_key_size, 0, | 558 | memset(stk + smp->enc_key_size, 0, |
564 | SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size); | 559 | SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size); |
@@ -568,9 +563,12 @@ static u8 smp_random(struct smp_chan *smp) | |||
568 | else | 563 | else |
569 | auth = 0; | 564 | auth = 0; |
570 | 565 | ||
566 | /* Even though there's no _SLAVE suffix this is the | ||
567 | * slave STK we're adding for later lookup (the master | ||
568 | * STK never needs to be stored). | ||
569 | */ | ||
571 | hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, | 570 | hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, |
572 | HCI_SMP_STK_SLAVE, auth, stk, smp->enc_key_size, | 571 | SMP_STK, auth, stk, smp->enc_key_size, ediv, rand); |
573 | ediv, rand); | ||
574 | } | 572 | } |
575 | 573 | ||
576 | return 0; | 574 | return 0; |
@@ -581,12 +579,21 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn) | |||
581 | struct smp_chan *smp; | 579 | struct smp_chan *smp; |
582 | 580 | ||
583 | smp = kzalloc(sizeof(*smp), GFP_ATOMIC); | 581 | smp = kzalloc(sizeof(*smp), GFP_ATOMIC); |
584 | if (!smp) | 582 | if (!smp) { |
583 | clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags); | ||
585 | return NULL; | 584 | return NULL; |
585 | } | ||
586 | |||
587 | smp->tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC); | ||
588 | if (IS_ERR(smp->tfm_aes)) { | ||
589 | BT_ERR("Unable to create ECB crypto context"); | ||
590 | kfree(smp); | ||
591 | clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags); | ||
592 | return NULL; | ||
593 | } | ||
586 | 594 | ||
587 | smp->conn = conn; | 595 | smp->conn = conn; |
588 | conn->smp_chan = smp; | 596 | conn->smp_chan = smp; |
589 | conn->hcon->smp_conn = conn; | ||
590 | 597 | ||
591 | hci_conn_hold(conn->hcon); | 598 | hci_conn_hold(conn->hcon); |
592 | 599 | ||
@@ -606,6 +613,8 @@ void smp_chan_destroy(struct l2cap_conn *conn) | |||
606 | kfree(smp->csrk); | 613 | kfree(smp->csrk); |
607 | kfree(smp->slave_csrk); | 614 | kfree(smp->slave_csrk); |
608 | 615 | ||
616 | crypto_free_blkcipher(smp->tfm_aes); | ||
617 | |||
609 | /* If pairing failed clean up any keys we might have */ | 618 | /* If pairing failed clean up any keys we might have */ |
610 | if (!complete) { | 619 | if (!complete) { |
611 | if (smp->ltk) { | 620 | if (smp->ltk) { |
@@ -626,19 +635,18 @@ void smp_chan_destroy(struct l2cap_conn *conn) | |||
626 | 635 | ||
627 | kfree(smp); | 636 | kfree(smp); |
628 | conn->smp_chan = NULL; | 637 | conn->smp_chan = NULL; |
629 | conn->hcon->smp_conn = NULL; | ||
630 | hci_conn_drop(conn->hcon); | 638 | hci_conn_drop(conn->hcon); |
631 | } | 639 | } |
632 | 640 | ||
633 | int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey) | 641 | int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey) |
634 | { | 642 | { |
635 | struct l2cap_conn *conn = hcon->smp_conn; | 643 | struct l2cap_conn *conn = hcon->l2cap_data; |
636 | struct smp_chan *smp; | 644 | struct smp_chan *smp; |
637 | u32 value; | 645 | u32 value; |
638 | 646 | ||
639 | BT_DBG(""); | 647 | BT_DBG(""); |
640 | 648 | ||
641 | if (!conn) | 649 | if (!conn || !test_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) |
642 | return -ENOTCONN; | 650 | return -ENOTCONN; |
643 | 651 | ||
644 | smp = conn->smp_chan; | 652 | smp = conn->smp_chan; |
@@ -675,6 +683,7 @@ int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey) | |||
675 | static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) | 683 | static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) |
676 | { | 684 | { |
677 | struct smp_cmd_pairing rsp, *req = (void *) skb->data; | 685 | struct smp_cmd_pairing rsp, *req = (void *) skb->data; |
686 | struct hci_dev *hdev = conn->hcon->hdev; | ||
678 | struct smp_chan *smp; | 687 | struct smp_chan *smp; |
679 | u8 key_size, auth, sec_level; | 688 | u8 key_size, auth, sec_level; |
680 | int ret; | 689 | int ret; |
@@ -684,7 +693,7 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
684 | if (skb->len < sizeof(*req)) | 693 | if (skb->len < sizeof(*req)) |
685 | return SMP_INVALID_PARAMS; | 694 | return SMP_INVALID_PARAMS; |
686 | 695 | ||
687 | if (conn->hcon->link_mode & HCI_LM_MASTER) | 696 | if (conn->hcon->role != HCI_ROLE_SLAVE) |
688 | return SMP_CMD_NOTSUPP; | 697 | return SMP_CMD_NOTSUPP; |
689 | 698 | ||
690 | if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) | 699 | if (!test_and_set_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) |
@@ -695,6 +704,10 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
695 | if (!smp) | 704 | if (!smp) |
696 | return SMP_UNSPECIFIED; | 705 | return SMP_UNSPECIFIED; |
697 | 706 | ||
707 | if (!test_bit(HCI_BONDABLE, &hdev->dev_flags) && | ||
708 | (req->auth_req & SMP_AUTH_BONDING)) | ||
709 | return SMP_PAIRING_NOTSUPP; | ||
710 | |||
698 | smp->preq[0] = SMP_CMD_PAIRING_REQ; | 711 | smp->preq[0] = SMP_CMD_PAIRING_REQ; |
699 | memcpy(&smp->preq[1], req, sizeof(*req)); | 712 | memcpy(&smp->preq[1], req, sizeof(*req)); |
700 | skb_pull(skb, sizeof(*req)); | 713 | skb_pull(skb, sizeof(*req)); |
@@ -734,8 +747,6 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
734 | if (ret) | 747 | if (ret) |
735 | return SMP_UNSPECIFIED; | 748 | return SMP_UNSPECIFIED; |
736 | 749 | ||
737 | clear_bit(SMP_FLAG_INITIATOR, &smp->flags); | ||
738 | |||
739 | return 0; | 750 | return 0; |
740 | } | 751 | } |
741 | 752 | ||
@@ -751,7 +762,7 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) | |||
751 | if (skb->len < sizeof(*rsp)) | 762 | if (skb->len < sizeof(*rsp)) |
752 | return SMP_INVALID_PARAMS; | 763 | return SMP_INVALID_PARAMS; |
753 | 764 | ||
754 | if (!(conn->hcon->link_mode & HCI_LM_MASTER)) | 765 | if (conn->hcon->role != HCI_ROLE_MASTER) |
755 | return SMP_CMD_NOTSUPP; | 766 | return SMP_CMD_NOTSUPP; |
756 | 767 | ||
757 | skb_pull(skb, sizeof(*rsp)); | 768 | skb_pull(skb, sizeof(*rsp)); |
@@ -839,26 +850,51 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) | |||
839 | return smp_random(smp); | 850 | return smp_random(smp); |
840 | } | 851 | } |
841 | 852 | ||
842 | static u8 smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level) | 853 | static bool smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level) |
843 | { | 854 | { |
844 | struct smp_ltk *key; | 855 | struct smp_ltk *key; |
845 | struct hci_conn *hcon = conn->hcon; | 856 | struct hci_conn *hcon = conn->hcon; |
846 | 857 | ||
847 | key = hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type, | 858 | key = hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type, |
848 | hcon->out); | 859 | hcon->role); |
849 | if (!key) | 860 | if (!key) |
850 | return 0; | 861 | return false; |
851 | 862 | ||
852 | if (sec_level > BT_SECURITY_MEDIUM && !key->authenticated) | 863 | if (sec_level > BT_SECURITY_MEDIUM && !key->authenticated) |
853 | return 0; | 864 | return false; |
854 | 865 | ||
855 | if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) | 866 | if (test_and_set_bit(HCI_CONN_ENCRYPT_PEND, &hcon->flags)) |
856 | return 1; | 867 | return true; |
857 | 868 | ||
858 | hci_le_start_enc(hcon, key->ediv, key->rand, key->val); | 869 | hci_le_start_enc(hcon, key->ediv, key->rand, key->val); |
859 | hcon->enc_key_size = key->enc_size; | 870 | hcon->enc_key_size = key->enc_size; |
860 | 871 | ||
861 | return 1; | 872 | /* We never store STKs for master role, so clear this flag */ |
873 | clear_bit(HCI_CONN_STK_ENCRYPT, &hcon->flags); | ||
874 | |||
875 | return true; | ||
876 | } | ||
877 | |||
878 | bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level) | ||
879 | { | ||
880 | if (sec_level == BT_SECURITY_LOW) | ||
881 | return true; | ||
882 | |||
883 | /* If we're encrypted with an STK always claim insufficient | ||
884 | * security. This way we allow the connection to be re-encrypted | ||
885 | * with an LTK, even if the LTK provides the same level of | ||
886 | * security. Only exception is if we don't have an LTK (e.g. | ||
887 | * because of key distribution bits). | ||
888 | */ | ||
889 | if (test_bit(HCI_CONN_STK_ENCRYPT, &hcon->flags) && | ||
890 | hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type, | ||
891 | hcon->role)) | ||
892 | return false; | ||
893 | |||
894 | if (hcon->sec_level >= sec_level) | ||
895 | return true; | ||
896 | |||
897 | return false; | ||
862 | } | 898 | } |
863 | 899 | ||
864 | static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) | 900 | static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) |
@@ -874,10 +910,13 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
874 | if (skb->len < sizeof(*rp)) | 910 | if (skb->len < sizeof(*rp)) |
875 | return SMP_INVALID_PARAMS; | 911 | return SMP_INVALID_PARAMS; |
876 | 912 | ||
877 | if (!(conn->hcon->link_mode & HCI_LM_MASTER)) | 913 | if (hcon->role != HCI_ROLE_MASTER) |
878 | return SMP_CMD_NOTSUPP; | 914 | return SMP_CMD_NOTSUPP; |
879 | 915 | ||
880 | sec_level = authreq_to_seclevel(rp->auth_req); | 916 | sec_level = authreq_to_seclevel(rp->auth_req); |
917 | if (smp_sufficient_security(hcon, sec_level)) | ||
918 | return 0; | ||
919 | |||
881 | if (sec_level > hcon->pending_sec_level) | 920 | if (sec_level > hcon->pending_sec_level) |
882 | hcon->pending_sec_level = sec_level; | 921 | hcon->pending_sec_level = sec_level; |
883 | 922 | ||
@@ -888,6 +927,12 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
888 | return 0; | 927 | return 0; |
889 | 928 | ||
890 | smp = smp_chan_create(conn); | 929 | smp = smp_chan_create(conn); |
930 | if (!smp) | ||
931 | return SMP_UNSPECIFIED; | ||
932 | |||
933 | if (!test_bit(HCI_BONDABLE, &hcon->hdev->dev_flags) && | ||
934 | (rp->auth_req & SMP_AUTH_BONDING)) | ||
935 | return SMP_PAIRING_NOTSUPP; | ||
891 | 936 | ||
892 | skb_pull(skb, sizeof(*rp)); | 937 | skb_pull(skb, sizeof(*rp)); |
893 | 938 | ||
@@ -899,22 +944,9 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
899 | 944 | ||
900 | smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); | 945 | smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); |
901 | 946 | ||
902 | clear_bit(SMP_FLAG_INITIATOR, &smp->flags); | ||
903 | |||
904 | return 0; | 947 | return 0; |
905 | } | 948 | } |
906 | 949 | ||
907 | bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level) | ||
908 | { | ||
909 | if (sec_level == BT_SECURITY_LOW) | ||
910 | return true; | ||
911 | |||
912 | if (hcon->sec_level >= sec_level) | ||
913 | return true; | ||
914 | |||
915 | return false; | ||
916 | } | ||
917 | |||
918 | int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) | 950 | int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) |
919 | { | 951 | { |
920 | struct l2cap_conn *conn = hcon->l2cap_data; | 952 | struct l2cap_conn *conn = hcon->l2cap_data; |
@@ -936,7 +968,7 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) | |||
936 | if (sec_level > hcon->pending_sec_level) | 968 | if (sec_level > hcon->pending_sec_level) |
937 | hcon->pending_sec_level = sec_level; | 969 | hcon->pending_sec_level = sec_level; |
938 | 970 | ||
939 | if (hcon->link_mode & HCI_LM_MASTER) | 971 | if (hcon->role == HCI_ROLE_MASTER) |
940 | if (smp_ltk_encrypt(conn, hcon->pending_sec_level)) | 972 | if (smp_ltk_encrypt(conn, hcon->pending_sec_level)) |
941 | return 0; | 973 | return 0; |
942 | 974 | ||
@@ -956,7 +988,7 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) | |||
956 | hcon->pending_sec_level > BT_SECURITY_MEDIUM) | 988 | hcon->pending_sec_level > BT_SECURITY_MEDIUM) |
957 | authreq |= SMP_AUTH_MITM; | 989 | authreq |= SMP_AUTH_MITM; |
958 | 990 | ||
959 | if (hcon->link_mode & HCI_LM_MASTER) { | 991 | if (hcon->role == HCI_ROLE_MASTER) { |
960 | struct smp_cmd_pairing cp; | 992 | struct smp_cmd_pairing cp; |
961 | 993 | ||
962 | build_pairing_cmd(conn, &cp, NULL, authreq); | 994 | build_pairing_cmd(conn, &cp, NULL, authreq); |
@@ -1021,7 +1053,7 @@ static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb) | |||
1021 | 1053 | ||
1022 | hci_dev_lock(hdev); | 1054 | hci_dev_lock(hdev); |
1023 | authenticated = (hcon->sec_level == BT_SECURITY_HIGH); | 1055 | authenticated = (hcon->sec_level == BT_SECURITY_HIGH); |
1024 | ltk = hci_add_ltk(hdev, &hcon->dst, hcon->dst_type, HCI_SMP_LTK, | 1056 | ltk = hci_add_ltk(hdev, &hcon->dst, hcon->dst_type, SMP_LTK, |
1025 | authenticated, smp->tk, smp->enc_key_size, | 1057 | authenticated, smp->tk, smp->enc_key_size, |
1026 | rp->ediv, rp->rand); | 1058 | rp->ediv, rp->rand); |
1027 | smp->ltk = ltk; | 1059 | smp->ltk = ltk; |
@@ -1075,6 +1107,8 @@ static int smp_cmd_ident_addr_info(struct l2cap_conn *conn, | |||
1075 | 1107 | ||
1076 | skb_pull(skb, sizeof(*info)); | 1108 | skb_pull(skb, sizeof(*info)); |
1077 | 1109 | ||
1110 | hci_dev_lock(hcon->hdev); | ||
1111 | |||
1078 | /* Strictly speaking the Core Specification (4.1) allows sending | 1112 | /* Strictly speaking the Core Specification (4.1) allows sending |
1079 | * an empty address which would force us to rely on just the IRK | 1113 | * an empty address which would force us to rely on just the IRK |
1080 | * as "identity information". However, since such | 1114 | * as "identity information". However, since such |
@@ -1084,8 +1118,7 @@ static int smp_cmd_ident_addr_info(struct l2cap_conn *conn, | |||
1084 | */ | 1118 | */ |
1085 | if (!bacmp(&info->bdaddr, BDADDR_ANY)) { | 1119 | if (!bacmp(&info->bdaddr, BDADDR_ANY)) { |
1086 | BT_ERR("Ignoring IRK with no identity address"); | 1120 | BT_ERR("Ignoring IRK with no identity address"); |
1087 | smp_distribute_keys(conn); | 1121 | goto distribute; |
1088 | return 0; | ||
1089 | } | 1122 | } |
1090 | 1123 | ||
1091 | bacpy(&smp->id_addr, &info->bdaddr); | 1124 | bacpy(&smp->id_addr, &info->bdaddr); |
@@ -1099,8 +1132,11 @@ static int smp_cmd_ident_addr_info(struct l2cap_conn *conn, | |||
1099 | smp->remote_irk = hci_add_irk(conn->hcon->hdev, &smp->id_addr, | 1132 | smp->remote_irk = hci_add_irk(conn->hcon->hdev, &smp->id_addr, |
1100 | smp->id_addr_type, smp->irk, &rpa); | 1133 | smp->id_addr_type, smp->irk, &rpa); |
1101 | 1134 | ||
1135 | distribute: | ||
1102 | smp_distribute_keys(conn); | 1136 | smp_distribute_keys(conn); |
1103 | 1137 | ||
1138 | hci_dev_unlock(hcon->hdev); | ||
1139 | |||
1104 | return 0; | 1140 | return 0; |
1105 | } | 1141 | } |
1106 | 1142 | ||
@@ -1156,7 +1192,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) | |||
1156 | } | 1192 | } |
1157 | 1193 | ||
1158 | if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) { | 1194 | if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) { |
1159 | err = -ENOTSUPP; | 1195 | err = -EOPNOTSUPP; |
1160 | reason = SMP_PAIRING_NOTSUPP; | 1196 | reason = SMP_PAIRING_NOTSUPP; |
1161 | goto done; | 1197 | goto done; |
1162 | } | 1198 | } |
@@ -1174,7 +1210,7 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) | |||
1174 | !conn->smp_chan) { | 1210 | !conn->smp_chan) { |
1175 | BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code); | 1211 | BT_ERR("Unexpected SMP command 0x%02x. Disconnecting.", code); |
1176 | kfree_skb(skb); | 1212 | kfree_skb(skb); |
1177 | return -ENOTSUPP; | 1213 | return -EOPNOTSUPP; |
1178 | } | 1214 | } |
1179 | 1215 | ||
1180 | switch (code) { | 1216 | switch (code) { |
@@ -1258,6 +1294,22 @@ static void smp_notify_keys(struct l2cap_conn *conn) | |||
1258 | bacpy(&hcon->dst, &smp->remote_irk->bdaddr); | 1294 | bacpy(&hcon->dst, &smp->remote_irk->bdaddr); |
1259 | hcon->dst_type = smp->remote_irk->addr_type; | 1295 | hcon->dst_type = smp->remote_irk->addr_type; |
1260 | l2cap_conn_update_id_addr(hcon); | 1296 | l2cap_conn_update_id_addr(hcon); |
1297 | |||
1298 | /* When receiving an indentity resolving key for | ||
1299 | * a remote device that does not use a resolvable | ||
1300 | * private address, just remove the key so that | ||
1301 | * it is possible to use the controller white | ||
1302 | * list for scanning. | ||
1303 | * | ||
1304 | * Userspace will have been told to not store | ||
1305 | * this key at this point. So it is safe to | ||
1306 | * just remove it. | ||
1307 | */ | ||
1308 | if (!bacmp(&smp->remote_irk->rpa, BDADDR_ANY)) { | ||
1309 | list_del(&smp->remote_irk->list); | ||
1310 | kfree(smp->remote_irk); | ||
1311 | smp->remote_irk = NULL; | ||
1312 | } | ||
1261 | } | 1313 | } |
1262 | 1314 | ||
1263 | /* The LTKs and CSRKs should be persistent only if both sides | 1315 | /* The LTKs and CSRKs should be persistent only if both sides |
@@ -1337,7 +1389,7 @@ int smp_distribute_keys(struct l2cap_conn *conn) | |||
1337 | 1389 | ||
1338 | authenticated = hcon->sec_level == BT_SECURITY_HIGH; | 1390 | authenticated = hcon->sec_level == BT_SECURITY_HIGH; |
1339 | ltk = hci_add_ltk(hdev, &hcon->dst, hcon->dst_type, | 1391 | ltk = hci_add_ltk(hdev, &hcon->dst, hcon->dst_type, |
1340 | HCI_SMP_LTK_SLAVE, authenticated, enc.ltk, | 1392 | SMP_LTK_SLAVE, authenticated, enc.ltk, |
1341 | smp->enc_key_size, ediv, rand); | 1393 | smp->enc_key_size, ediv, rand); |
1342 | smp->slave_ltk = ltk; | 1394 | smp->slave_ltk = ltk; |
1343 | 1395 | ||
diff --git a/net/bluetooth/smp.h b/net/bluetooth/smp.h index 5a8dc36460a1..796f4f45f92f 100644 --- a/net/bluetooth/smp.h +++ b/net/bluetooth/smp.h | |||
@@ -116,6 +116,13 @@ struct smp_cmd_security_req { | |||
116 | #define SMP_MIN_ENC_KEY_SIZE 7 | 116 | #define SMP_MIN_ENC_KEY_SIZE 7 |
117 | #define SMP_MAX_ENC_KEY_SIZE 16 | 117 | #define SMP_MAX_ENC_KEY_SIZE 16 |
118 | 118 | ||
119 | /* LTK types used in internal storage (struct smp_ltk) */ | ||
120 | enum { | ||
121 | SMP_STK, | ||
122 | SMP_LTK, | ||
123 | SMP_LTK_SLAVE, | ||
124 | }; | ||
125 | |||
119 | /* SMP Commands */ | 126 | /* SMP Commands */ |
120 | bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level); | 127 | bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level); |
121 | int smp_conn_security(struct hci_conn *hcon, __u8 sec_level); | 128 | int smp_conn_security(struct hci_conn *hcon, __u8 sec_level); |
diff --git a/net/bridge/br_fdb.c b/net/bridge/br_fdb.c index b524c36c1273..6f6c95cfe8f2 100644 --- a/net/bridge/br_fdb.c +++ b/net/bridge/br_fdb.c | |||
@@ -93,7 +93,7 @@ static void fdb_rcu_free(struct rcu_head *head) | |||
93 | static void fdb_add_hw(struct net_bridge *br, const unsigned char *addr) | 93 | static void fdb_add_hw(struct net_bridge *br, const unsigned char *addr) |
94 | { | 94 | { |
95 | int err; | 95 | int err; |
96 | struct net_bridge_port *p, *tmp; | 96 | struct net_bridge_port *p; |
97 | 97 | ||
98 | ASSERT_RTNL(); | 98 | ASSERT_RTNL(); |
99 | 99 | ||
@@ -107,11 +107,9 @@ static void fdb_add_hw(struct net_bridge *br, const unsigned char *addr) | |||
107 | 107 | ||
108 | return; | 108 | return; |
109 | undo: | 109 | undo: |
110 | list_for_each_entry(tmp, &br->port_list, list) { | 110 | list_for_each_entry_continue_reverse(p, &br->port_list, list) { |
111 | if (tmp == p) | 111 | if (!br_promisc_port(p)) |
112 | break; | 112 | dev_uc_del(p->dev, addr); |
113 | if (!br_promisc_port(tmp)) | ||
114 | dev_uc_del(tmp->dev, addr); | ||
115 | } | 113 | } |
116 | } | 114 | } |
117 | 115 | ||
@@ -631,7 +629,7 @@ static int fdb_fill_info(struct sk_buff *skb, const struct net_bridge *br, | |||
631 | if (nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci)) | 629 | if (nla_put(skb, NDA_CACHEINFO, sizeof(ci), &ci)) |
632 | goto nla_put_failure; | 630 | goto nla_put_failure; |
633 | 631 | ||
634 | if (nla_put(skb, NDA_VLAN, sizeof(u16), &fdb->vlan_id)) | 632 | if (fdb->vlan_id && nla_put(skb, NDA_VLAN, sizeof(u16), &fdb->vlan_id)) |
635 | goto nla_put_failure; | 633 | goto nla_put_failure; |
636 | 634 | ||
637 | return nlmsg_end(skb, nlh); | 635 | return nlmsg_end(skb, nlh); |
@@ -678,6 +676,7 @@ errout: | |||
678 | int br_fdb_dump(struct sk_buff *skb, | 676 | int br_fdb_dump(struct sk_buff *skb, |
679 | struct netlink_callback *cb, | 677 | struct netlink_callback *cb, |
680 | struct net_device *dev, | 678 | struct net_device *dev, |
679 | struct net_device *filter_dev, | ||
681 | int idx) | 680 | int idx) |
682 | { | 681 | { |
683 | struct net_bridge *br = netdev_priv(dev); | 682 | struct net_bridge *br = netdev_priv(dev); |
@@ -693,6 +692,19 @@ int br_fdb_dump(struct sk_buff *skb, | |||
693 | if (idx < cb->args[0]) | 692 | if (idx < cb->args[0]) |
694 | goto skip; | 693 | goto skip; |
695 | 694 | ||
695 | if (filter_dev && | ||
696 | (!f->dst || f->dst->dev != filter_dev)) { | ||
697 | if (filter_dev != dev) | ||
698 | goto skip; | ||
699 | /* !f->dst is a speacial case for bridge | ||
700 | * It means the MAC belongs to the bridge | ||
701 | * Therefore need a little more filtering | ||
702 | * we only want to dump the !f->dst case | ||
703 | */ | ||
704 | if (f->dst) | ||
705 | goto skip; | ||
706 | } | ||
707 | |||
696 | if (fdb_fill_info(skb, br, f, | 708 | if (fdb_fill_info(skb, br, f, |
697 | NETLINK_CB(cb->skb).portid, | 709 | NETLINK_CB(cb->skb).portid, |
698 | cb->nlh->nlmsg_seq, | 710 | cb->nlh->nlmsg_seq, |
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 3eca3fdf8fe1..078d336a1f37 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
@@ -344,7 +344,7 @@ int br_add_bridge(struct net *net, const char *name) | |||
344 | struct net_device *dev; | 344 | struct net_device *dev; |
345 | int res; | 345 | int res; |
346 | 346 | ||
347 | dev = alloc_netdev(sizeof(struct net_bridge), name, | 347 | dev = alloc_netdev(sizeof(struct net_bridge), name, NET_NAME_UNKNOWN, |
348 | br_dev_setup); | 348 | br_dev_setup); |
349 | 349 | ||
350 | if (!dev) | 350 | if (!dev) |
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index abfa0b65a111..7751c92c8c57 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
@@ -1174,7 +1174,7 @@ static void br_multicast_add_router(struct net_bridge *br, | |||
1174 | } | 1174 | } |
1175 | 1175 | ||
1176 | if (slot) | 1176 | if (slot) |
1177 | hlist_add_after_rcu(slot, &port->rlist); | 1177 | hlist_add_behind_rcu(&port->rlist, slot); |
1178 | else | 1178 | else |
1179 | hlist_add_head_rcu(&port->rlist, &br->router_list); | 1179 | hlist_add_head_rcu(&port->rlist, &br->router_list); |
1180 | } | 1180 | } |
@@ -2216,6 +2216,43 @@ unlock: | |||
2216 | EXPORT_SYMBOL_GPL(br_multicast_list_adjacent); | 2216 | EXPORT_SYMBOL_GPL(br_multicast_list_adjacent); |
2217 | 2217 | ||
2218 | /** | 2218 | /** |
2219 | * br_multicast_has_querier_anywhere - Checks for a querier on a bridge | ||
2220 | * @dev: The bridge port providing the bridge on which to check for a querier | ||
2221 | * @proto: The protocol family to check for: IGMP -> ETH_P_IP, MLD -> ETH_P_IPV6 | ||
2222 | * | ||
2223 | * Checks whether the given interface has a bridge on top and if so returns | ||
2224 | * true if a valid querier exists anywhere on the bridged link layer. | ||
2225 | * Otherwise returns false. | ||
2226 | */ | ||
2227 | bool br_multicast_has_querier_anywhere(struct net_device *dev, int proto) | ||
2228 | { | ||
2229 | struct net_bridge *br; | ||
2230 | struct net_bridge_port *port; | ||
2231 | struct ethhdr eth; | ||
2232 | bool ret = false; | ||
2233 | |||
2234 | rcu_read_lock(); | ||
2235 | if (!br_port_exists(dev)) | ||
2236 | goto unlock; | ||
2237 | |||
2238 | port = br_port_get_rcu(dev); | ||
2239 | if (!port || !port->br) | ||
2240 | goto unlock; | ||
2241 | |||
2242 | br = port->br; | ||
2243 | |||
2244 | memset(ð, 0, sizeof(eth)); | ||
2245 | eth.h_proto = htons(proto); | ||
2246 | |||
2247 | ret = br_multicast_querier_exists(br, ð); | ||
2248 | |||
2249 | unlock: | ||
2250 | rcu_read_unlock(); | ||
2251 | return ret; | ||
2252 | } | ||
2253 | EXPORT_SYMBOL_GPL(br_multicast_has_querier_anywhere); | ||
2254 | |||
2255 | /** | ||
2219 | * br_multicast_has_querier_adjacent - Checks for a querier behind a bridge port | 2256 | * br_multicast_has_querier_adjacent - Checks for a querier behind a bridge port |
2220 | * @dev: The bridge port adjacent to which to check for a querier | 2257 | * @dev: The bridge port adjacent to which to check for a querier |
2221 | * @proto: The protocol family to check for: IGMP -> ETH_P_IP, MLD -> ETH_P_IPV6 | 2258 | * @proto: The protocol family to check for: IGMP -> ETH_P_IP, MLD -> ETH_P_IPV6 |
diff --git a/net/bridge/br_netlink.c b/net/bridge/br_netlink.c index 26edb518b839..cb5fcf62f663 100644 --- a/net/bridge/br_netlink.c +++ b/net/bridge/br_netlink.c | |||
@@ -208,7 +208,6 @@ int br_getlink(struct sk_buff *skb, u32 pid, u32 seq, | |||
208 | int err = 0; | 208 | int err = 0; |
209 | struct net_bridge_port *port = br_port_get_rtnl(dev); | 209 | struct net_bridge_port *port = br_port_get_rtnl(dev); |
210 | 210 | ||
211 | /* not a bridge port and */ | ||
212 | if (!port && !(filter_mask & RTEXT_FILTER_BRVLAN)) | 211 | if (!port && !(filter_mask & RTEXT_FILTER_BRVLAN)) |
213 | goto out; | 212 | goto out; |
214 | 213 | ||
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 23caf5b0309e..b6c04cbcfdc5 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
@@ -309,6 +309,9 @@ struct br_input_skb_cb { | |||
309 | int igmp; | 309 | int igmp; |
310 | int mrouters_only; | 310 | int mrouters_only; |
311 | #endif | 311 | #endif |
312 | #ifdef CONFIG_BRIDGE_VLAN_FILTERING | ||
313 | bool vlan_filtered; | ||
314 | #endif | ||
312 | }; | 315 | }; |
313 | 316 | ||
314 | #define BR_INPUT_SKB_CB(__skb) ((struct br_input_skb_cb *)(__skb)->cb) | 317 | #define BR_INPUT_SKB_CB(__skb) ((struct br_input_skb_cb *)(__skb)->cb) |
@@ -399,7 +402,7 @@ int br_fdb_delete(struct ndmsg *ndm, struct nlattr *tb[], | |||
399 | int br_fdb_add(struct ndmsg *nlh, struct nlattr *tb[], struct net_device *dev, | 402 | int br_fdb_add(struct ndmsg *nlh, struct nlattr *tb[], struct net_device *dev, |
400 | const unsigned char *addr, u16 nlh_flags); | 403 | const unsigned char *addr, u16 nlh_flags); |
401 | int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, | 404 | int br_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb, |
402 | struct net_device *dev, int idx); | 405 | struct net_device *dev, struct net_device *fdev, int idx); |
403 | int br_fdb_sync_static(struct net_bridge *br, struct net_bridge_port *p); | 406 | int br_fdb_sync_static(struct net_bridge *br, struct net_bridge_port *p); |
404 | void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p); | 407 | void br_fdb_unsync_static(struct net_bridge *br, struct net_bridge_port *p); |
405 | 408 | ||
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index 2b2774fe0703..3ba57fcdcd13 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c | |||
@@ -27,9 +27,13 @@ static void __vlan_add_flags(struct net_port_vlans *v, u16 vid, u16 flags) | |||
27 | { | 27 | { |
28 | if (flags & BRIDGE_VLAN_INFO_PVID) | 28 | if (flags & BRIDGE_VLAN_INFO_PVID) |
29 | __vlan_add_pvid(v, vid); | 29 | __vlan_add_pvid(v, vid); |
30 | else | ||
31 | __vlan_delete_pvid(v, vid); | ||
30 | 32 | ||
31 | if (flags & BRIDGE_VLAN_INFO_UNTAGGED) | 33 | if (flags & BRIDGE_VLAN_INFO_UNTAGGED) |
32 | set_bit(vid, v->untagged_bitmap); | 34 | set_bit(vid, v->untagged_bitmap); |
35 | else | ||
36 | clear_bit(vid, v->untagged_bitmap); | ||
33 | } | 37 | } |
34 | 38 | ||
35 | static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags) | 39 | static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags) |
@@ -55,10 +59,8 @@ static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags) | |||
55 | 59 | ||
56 | if (p) { | 60 | if (p) { |
57 | /* Add VLAN to the device filter if it is supported. | 61 | /* Add VLAN to the device filter if it is supported. |
58 | * Stricly speaking, this is not necessary now, since | 62 | * This ensures tagged traffic enters the bridge when |
59 | * devices are made promiscuous by the bridge, but if | 63 | * promiscuous mode is disabled by br_manage_promisc(). |
60 | * that ever changes this code will allow tagged | ||
61 | * traffic to enter the bridge. | ||
62 | */ | 64 | */ |
63 | err = vlan_vid_add(dev, br->vlan_proto, vid); | 65 | err = vlan_vid_add(dev, br->vlan_proto, vid); |
64 | if (err) | 66 | if (err) |
@@ -127,7 +129,8 @@ struct sk_buff *br_handle_vlan(struct net_bridge *br, | |||
127 | { | 129 | { |
128 | u16 vid; | 130 | u16 vid; |
129 | 131 | ||
130 | if (!br->vlan_enabled) | 132 | /* If this packet was not filtered at input, let it pass */ |
133 | if (!BR_INPUT_SKB_CB(skb)->vlan_filtered) | ||
131 | goto out; | 134 | goto out; |
132 | 135 | ||
133 | /* Vlan filter table must be configured at this point. The | 136 | /* Vlan filter table must be configured at this point. The |
@@ -166,8 +169,10 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, | |||
166 | /* If VLAN filtering is disabled on the bridge, all packets are | 169 | /* If VLAN filtering is disabled on the bridge, all packets are |
167 | * permitted. | 170 | * permitted. |
168 | */ | 171 | */ |
169 | if (!br->vlan_enabled) | 172 | if (!br->vlan_enabled) { |
173 | BR_INPUT_SKB_CB(skb)->vlan_filtered = false; | ||
170 | return true; | 174 | return true; |
175 | } | ||
171 | 176 | ||
172 | /* If there are no vlan in the permitted list, all packets are | 177 | /* If there are no vlan in the permitted list, all packets are |
173 | * rejected. | 178 | * rejected. |
@@ -175,6 +180,7 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, | |||
175 | if (!v) | 180 | if (!v) |
176 | goto drop; | 181 | goto drop; |
177 | 182 | ||
183 | BR_INPUT_SKB_CB(skb)->vlan_filtered = true; | ||
178 | proto = br->vlan_proto; | 184 | proto = br->vlan_proto; |
179 | 185 | ||
180 | /* If vlan tx offload is disabled on bridge device and frame was | 186 | /* If vlan tx offload is disabled on bridge device and frame was |
@@ -183,7 +189,7 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, | |||
183 | */ | 189 | */ |
184 | if (unlikely(!vlan_tx_tag_present(skb) && | 190 | if (unlikely(!vlan_tx_tag_present(skb) && |
185 | skb->protocol == proto)) { | 191 | skb->protocol == proto)) { |
186 | skb = vlan_untag(skb); | 192 | skb = skb_vlan_untag(skb); |
187 | if (unlikely(!skb)) | 193 | if (unlikely(!skb)) |
188 | return false; | 194 | return false; |
189 | } | 195 | } |
@@ -253,7 +259,8 @@ bool br_allowed_egress(struct net_bridge *br, | |||
253 | { | 259 | { |
254 | u16 vid; | 260 | u16 vid; |
255 | 261 | ||
256 | if (!br->vlan_enabled) | 262 | /* If this packet was not filtered at input, let it pass */ |
263 | if (!BR_INPUT_SKB_CB(skb)->vlan_filtered) | ||
257 | return true; | 264 | return true; |
258 | 265 | ||
259 | if (!v) | 266 | if (!v) |
@@ -272,6 +279,7 @@ bool br_should_learn(struct net_bridge_port *p, struct sk_buff *skb, u16 *vid) | |||
272 | struct net_bridge *br = p->br; | 279 | struct net_bridge *br = p->br; |
273 | struct net_port_vlans *v; | 280 | struct net_port_vlans *v; |
274 | 281 | ||
282 | /* If filtering was disabled at input, let it pass. */ | ||
275 | if (!br->vlan_enabled) | 283 | if (!br->vlan_enabled) |
276 | return true; | 284 | return true; |
277 | 285 | ||
diff --git a/net/bridge/netfilter/Kconfig b/net/bridge/netfilter/Kconfig index 629dc77874a9..9cebf47ac840 100644 --- a/net/bridge/netfilter/Kconfig +++ b/net/bridge/netfilter/Kconfig | |||
@@ -14,6 +14,15 @@ config NFT_BRIDGE_META | |||
14 | help | 14 | help |
15 | Add support for bridge dedicated meta key. | 15 | Add support for bridge dedicated meta key. |
16 | 16 | ||
17 | config NFT_BRIDGE_REJECT | ||
18 | tristate "Netfilter nf_tables bridge reject support" | ||
19 | depends on NFT_REJECT && NFT_REJECT_IPV4 && NFT_REJECT_IPV6 | ||
20 | help | ||
21 | Add support to reject packets. | ||
22 | |||
23 | config NF_LOG_BRIDGE | ||
24 | tristate "Bridge packet logging" | ||
25 | |||
17 | endif # NF_TABLES_BRIDGE | 26 | endif # NF_TABLES_BRIDGE |
18 | 27 | ||
19 | menuconfig BRIDGE_NF_EBTABLES | 28 | menuconfig BRIDGE_NF_EBTABLES |
@@ -202,22 +211,6 @@ config BRIDGE_EBT_LOG | |||
202 | 211 | ||
203 | To compile it as a module, choose M here. If unsure, say N. | 212 | To compile it as a module, choose M here. If unsure, say N. |
204 | 213 | ||
205 | config BRIDGE_EBT_ULOG | ||
206 | tristate "ebt: ulog support (OBSOLETE)" | ||
207 | help | ||
208 | This option enables the old bridge-specific "ebt_ulog" implementation | ||
209 | which has been obsoleted by the new "nfnetlink_log" code (see | ||
210 | CONFIG_NETFILTER_NETLINK_LOG). | ||
211 | |||
212 | This option adds the ulog watcher, that you can use in any rule | ||
213 | in any ebtables table. The packet is passed to a userspace | ||
214 | logging daemon using netlink multicast sockets. This differs | ||
215 | from the log watcher in the sense that the complete packet is | ||
216 | sent to userspace instead of a descriptive text and that | ||
217 | netlink multicast sockets are used instead of the syslog. | ||
218 | |||
219 | To compile it as a module, choose M here. If unsure, say N. | ||
220 | |||
221 | config BRIDGE_EBT_NFLOG | 214 | config BRIDGE_EBT_NFLOG |
222 | tristate "ebt: nflog support" | 215 | tristate "ebt: nflog support" |
223 | help | 216 | help |
diff --git a/net/bridge/netfilter/Makefile b/net/bridge/netfilter/Makefile index 6f2f3943d66f..be4d0cea78ce 100644 --- a/net/bridge/netfilter/Makefile +++ b/net/bridge/netfilter/Makefile | |||
@@ -4,6 +4,10 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_NF_TABLES_BRIDGE) += nf_tables_bridge.o | 5 | obj-$(CONFIG_NF_TABLES_BRIDGE) += nf_tables_bridge.o |
6 | obj-$(CONFIG_NFT_BRIDGE_META) += nft_meta_bridge.o | 6 | obj-$(CONFIG_NFT_BRIDGE_META) += nft_meta_bridge.o |
7 | obj-$(CONFIG_NFT_BRIDGE_REJECT) += nft_reject_bridge.o | ||
8 | |||
9 | # packet logging | ||
10 | obj-$(CONFIG_NF_LOG_BRIDGE) += nf_log_bridge.o | ||
7 | 11 | ||
8 | obj-$(CONFIG_BRIDGE_NF_EBTABLES) += ebtables.o | 12 | obj-$(CONFIG_BRIDGE_NF_EBTABLES) += ebtables.o |
9 | 13 | ||
@@ -33,5 +37,4 @@ obj-$(CONFIG_BRIDGE_EBT_SNAT) += ebt_snat.o | |||
33 | 37 | ||
34 | # watchers | 38 | # watchers |
35 | obj-$(CONFIG_BRIDGE_EBT_LOG) += ebt_log.o | 39 | obj-$(CONFIG_BRIDGE_EBT_LOG) += ebt_log.o |
36 | obj-$(CONFIG_BRIDGE_EBT_ULOG) += ebt_ulog.o | ||
37 | obj-$(CONFIG_BRIDGE_EBT_NFLOG) += ebt_nflog.o | 40 | obj-$(CONFIG_BRIDGE_EBT_NFLOG) += ebt_nflog.o |
diff --git a/net/bridge/netfilter/ebt_log.c b/net/bridge/netfilter/ebt_log.c index 5322a36867a3..17f2e4bc2a29 100644 --- a/net/bridge/netfilter/ebt_log.c +++ b/net/bridge/netfilter/ebt_log.c | |||
@@ -186,6 +186,10 @@ ebt_log_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
186 | li.u.log.level = info->loglevel; | 186 | li.u.log.level = info->loglevel; |
187 | li.u.log.logflags = info->bitmask; | 187 | li.u.log.logflags = info->bitmask; |
188 | 188 | ||
189 | /* Remember that we have to use ebt_log_packet() not to break backward | ||
190 | * compatibility. We cannot use the default bridge packet logger via | ||
191 | * nf_log_packet() with NFT_LOG_TYPE_LOG here. --Pablo | ||
192 | */ | ||
189 | if (info->bitmask & EBT_LOG_NFLOG) | 193 | if (info->bitmask & EBT_LOG_NFLOG) |
190 | nf_log_packet(net, NFPROTO_BRIDGE, par->hooknum, skb, | 194 | nf_log_packet(net, NFPROTO_BRIDGE, par->hooknum, skb, |
191 | par->in, par->out, &li, "%s", info->prefix); | 195 | par->in, par->out, &li, "%s", info->prefix); |
@@ -205,54 +209,13 @@ static struct xt_target ebt_log_tg_reg __read_mostly = { | |||
205 | .me = THIS_MODULE, | 209 | .me = THIS_MODULE, |
206 | }; | 210 | }; |
207 | 211 | ||
208 | static struct nf_logger ebt_log_logger __read_mostly = { | ||
209 | .name = "ebt_log", | ||
210 | .logfn = &ebt_log_packet, | ||
211 | .me = THIS_MODULE, | ||
212 | }; | ||
213 | |||
214 | static int __net_init ebt_log_net_init(struct net *net) | ||
215 | { | ||
216 | nf_log_set(net, NFPROTO_BRIDGE, &ebt_log_logger); | ||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | static void __net_exit ebt_log_net_fini(struct net *net) | ||
221 | { | ||
222 | nf_log_unset(net, &ebt_log_logger); | ||
223 | } | ||
224 | |||
225 | static struct pernet_operations ebt_log_net_ops = { | ||
226 | .init = ebt_log_net_init, | ||
227 | .exit = ebt_log_net_fini, | ||
228 | }; | ||
229 | |||
230 | static int __init ebt_log_init(void) | 212 | static int __init ebt_log_init(void) |
231 | { | 213 | { |
232 | int ret; | 214 | return xt_register_target(&ebt_log_tg_reg); |
233 | |||
234 | ret = register_pernet_subsys(&ebt_log_net_ops); | ||
235 | if (ret < 0) | ||
236 | goto err_pernet; | ||
237 | |||
238 | ret = xt_register_target(&ebt_log_tg_reg); | ||
239 | if (ret < 0) | ||
240 | goto err_target; | ||
241 | |||
242 | nf_log_register(NFPROTO_BRIDGE, &ebt_log_logger); | ||
243 | |||
244 | return ret; | ||
245 | |||
246 | err_target: | ||
247 | unregister_pernet_subsys(&ebt_log_net_ops); | ||
248 | err_pernet: | ||
249 | return ret; | ||
250 | } | 215 | } |
251 | 216 | ||
252 | static void __exit ebt_log_fini(void) | 217 | static void __exit ebt_log_fini(void) |
253 | { | 218 | { |
254 | unregister_pernet_subsys(&ebt_log_net_ops); | ||
255 | nf_log_unregister(&ebt_log_logger); | ||
256 | xt_unregister_target(&ebt_log_tg_reg); | 219 | xt_unregister_target(&ebt_log_tg_reg); |
257 | } | 220 | } |
258 | 221 | ||
diff --git a/net/bridge/netfilter/ebt_ulog.c b/net/bridge/netfilter/ebt_ulog.c deleted file mode 100644 index 7c470c371e14..000000000000 --- a/net/bridge/netfilter/ebt_ulog.c +++ /dev/null | |||
@@ -1,393 +0,0 @@ | |||
1 | /* | ||
2 | * netfilter module for userspace bridged Ethernet frames logging daemons | ||
3 | * | ||
4 | * Authors: | ||
5 | * Bart De Schuymer <bdschuym@pandora.be> | ||
6 | * Harald Welte <laforge@netfilter.org> | ||
7 | * | ||
8 | * November, 2004 | ||
9 | * | ||
10 | * Based on ipt_ULOG.c, which is | ||
11 | * (C) 2000-2002 by Harald Welte <laforge@netfilter.org> | ||
12 | * | ||
13 | * This module accepts two parameters: | ||
14 | * | ||
15 | * nlbufsiz: | ||
16 | * The parameter specifies how big the buffer for each netlink multicast | ||
17 | * group is. e.g. If you say nlbufsiz=8192, up to eight kb of packets will | ||
18 | * get accumulated in the kernel until they are sent to userspace. It is | ||
19 | * NOT possible to allocate more than 128kB, and it is strongly discouraged, | ||
20 | * because atomically allocating 128kB inside the network rx softirq is not | ||
21 | * reliable. Please also keep in mind that this buffer size is allocated for | ||
22 | * each nlgroup you are using, so the total kernel memory usage increases | ||
23 | * by that factor. | ||
24 | * | ||
25 | * flushtimeout: | ||
26 | * Specify, after how many hundredths of a second the queue should be | ||
27 | * flushed even if it is not full yet. | ||
28 | * | ||
29 | */ | ||
30 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
31 | #include <linux/module.h> | ||
32 | #include <linux/slab.h> | ||
33 | #include <linux/spinlock.h> | ||
34 | #include <linux/socket.h> | ||
35 | #include <linux/skbuff.h> | ||
36 | #include <linux/kernel.h> | ||
37 | #include <linux/timer.h> | ||
38 | #include <net/netlink.h> | ||
39 | #include <linux/netdevice.h> | ||
40 | #include <linux/netfilter/x_tables.h> | ||
41 | #include <linux/netfilter_bridge/ebtables.h> | ||
42 | #include <linux/netfilter_bridge/ebt_ulog.h> | ||
43 | #include <net/netfilter/nf_log.h> | ||
44 | #include <net/netns/generic.h> | ||
45 | #include <net/sock.h> | ||
46 | #include "../br_private.h" | ||
47 | |||
48 | static unsigned int nlbufsiz = NLMSG_GOODSIZE; | ||
49 | module_param(nlbufsiz, uint, 0600); | ||
50 | MODULE_PARM_DESC(nlbufsiz, "netlink buffer size (number of bytes) " | ||
51 | "(defaults to 4096)"); | ||
52 | |||
53 | static unsigned int flushtimeout = 10; | ||
54 | module_param(flushtimeout, uint, 0600); | ||
55 | MODULE_PARM_DESC(flushtimeout, "buffer flush timeout (hundredths ofa second) " | ||
56 | "(defaults to 10)"); | ||
57 | |||
58 | typedef struct { | ||
59 | unsigned int qlen; /* number of nlmsgs' in the skb */ | ||
60 | struct nlmsghdr *lastnlh; /* netlink header of last msg in skb */ | ||
61 | struct sk_buff *skb; /* the pre-allocated skb */ | ||
62 | struct timer_list timer; /* the timer function */ | ||
63 | spinlock_t lock; /* the per-queue lock */ | ||
64 | } ebt_ulog_buff_t; | ||
65 | |||
66 | static int ebt_ulog_net_id __read_mostly; | ||
67 | struct ebt_ulog_net { | ||
68 | unsigned int nlgroup[EBT_ULOG_MAXNLGROUPS]; | ||
69 | ebt_ulog_buff_t ulog_buffers[EBT_ULOG_MAXNLGROUPS]; | ||
70 | struct sock *ebtulognl; | ||
71 | }; | ||
72 | |||
73 | static struct ebt_ulog_net *ebt_ulog_pernet(struct net *net) | ||
74 | { | ||
75 | return net_generic(net, ebt_ulog_net_id); | ||
76 | } | ||
77 | |||
78 | /* send one ulog_buff_t to userspace */ | ||
79 | static void ulog_send(struct ebt_ulog_net *ebt, unsigned int nlgroup) | ||
80 | { | ||
81 | ebt_ulog_buff_t *ub = &ebt->ulog_buffers[nlgroup]; | ||
82 | |||
83 | del_timer(&ub->timer); | ||
84 | |||
85 | if (!ub->skb) | ||
86 | return; | ||
87 | |||
88 | /* last nlmsg needs NLMSG_DONE */ | ||
89 | if (ub->qlen > 1) | ||
90 | ub->lastnlh->nlmsg_type = NLMSG_DONE; | ||
91 | |||
92 | NETLINK_CB(ub->skb).dst_group = nlgroup + 1; | ||
93 | netlink_broadcast(ebt->ebtulognl, ub->skb, 0, nlgroup + 1, GFP_ATOMIC); | ||
94 | |||
95 | ub->qlen = 0; | ||
96 | ub->skb = NULL; | ||
97 | } | ||
98 | |||
99 | /* timer function to flush queue in flushtimeout time */ | ||
100 | static void ulog_timer(unsigned long data) | ||
101 | { | ||
102 | struct ebt_ulog_net *ebt = container_of((void *)data, | ||
103 | struct ebt_ulog_net, | ||
104 | nlgroup[*(unsigned int *)data]); | ||
105 | |||
106 | ebt_ulog_buff_t *ub = &ebt->ulog_buffers[*(unsigned int *)data]; | ||
107 | spin_lock_bh(&ub->lock); | ||
108 | if (ub->skb) | ||
109 | ulog_send(ebt, *(unsigned int *)data); | ||
110 | spin_unlock_bh(&ub->lock); | ||
111 | } | ||
112 | |||
113 | static struct sk_buff *ulog_alloc_skb(unsigned int size) | ||
114 | { | ||
115 | struct sk_buff *skb; | ||
116 | unsigned int n; | ||
117 | |||
118 | n = max(size, nlbufsiz); | ||
119 | skb = alloc_skb(n, GFP_ATOMIC | __GFP_NOWARN); | ||
120 | if (!skb) { | ||
121 | if (n > size) { | ||
122 | /* try to allocate only as much as we need for | ||
123 | * current packet */ | ||
124 | skb = alloc_skb(size, GFP_ATOMIC); | ||
125 | if (!skb) | ||
126 | pr_debug("cannot even allocate buffer of size %ub\n", | ||
127 | size); | ||
128 | } | ||
129 | } | ||
130 | |||
131 | return skb; | ||
132 | } | ||
133 | |||
134 | static void ebt_ulog_packet(struct net *net, unsigned int hooknr, | ||
135 | const struct sk_buff *skb, | ||
136 | const struct net_device *in, | ||
137 | const struct net_device *out, | ||
138 | const struct ebt_ulog_info *uloginfo, | ||
139 | const char *prefix) | ||
140 | { | ||
141 | ebt_ulog_packet_msg_t *pm; | ||
142 | size_t size, copy_len; | ||
143 | struct nlmsghdr *nlh; | ||
144 | struct ebt_ulog_net *ebt = ebt_ulog_pernet(net); | ||
145 | unsigned int group = uloginfo->nlgroup; | ||
146 | ebt_ulog_buff_t *ub = &ebt->ulog_buffers[group]; | ||
147 | spinlock_t *lock = &ub->lock; | ||
148 | ktime_t kt; | ||
149 | |||
150 | if ((uloginfo->cprange == 0) || | ||
151 | (uloginfo->cprange > skb->len + ETH_HLEN)) | ||
152 | copy_len = skb->len + ETH_HLEN; | ||
153 | else | ||
154 | copy_len = uloginfo->cprange; | ||
155 | |||
156 | size = nlmsg_total_size(sizeof(*pm) + copy_len); | ||
157 | if (size > nlbufsiz) { | ||
158 | pr_debug("Size %Zd needed, but nlbufsiz=%d\n", size, nlbufsiz); | ||
159 | return; | ||
160 | } | ||
161 | |||
162 | spin_lock_bh(lock); | ||
163 | |||
164 | if (!ub->skb) { | ||
165 | if (!(ub->skb = ulog_alloc_skb(size))) | ||
166 | goto unlock; | ||
167 | } else if (size > skb_tailroom(ub->skb)) { | ||
168 | ulog_send(ebt, group); | ||
169 | |||
170 | if (!(ub->skb = ulog_alloc_skb(size))) | ||
171 | goto unlock; | ||
172 | } | ||
173 | |||
174 | nlh = nlmsg_put(ub->skb, 0, ub->qlen, 0, | ||
175 | size - NLMSG_ALIGN(sizeof(*nlh)), 0); | ||
176 | if (!nlh) { | ||
177 | kfree_skb(ub->skb); | ||
178 | ub->skb = NULL; | ||
179 | goto unlock; | ||
180 | } | ||
181 | ub->qlen++; | ||
182 | |||
183 | pm = nlmsg_data(nlh); | ||
184 | memset(pm, 0, sizeof(*pm)); | ||
185 | |||
186 | /* Fill in the ulog data */ | ||
187 | pm->version = EBT_ULOG_VERSION; | ||
188 | kt = ktime_get_real(); | ||
189 | pm->stamp = ktime_to_timeval(kt); | ||
190 | if (ub->qlen == 1) | ||
191 | ub->skb->tstamp = kt; | ||
192 | pm->data_len = copy_len; | ||
193 | pm->mark = skb->mark; | ||
194 | pm->hook = hooknr; | ||
195 | if (uloginfo->prefix != NULL) | ||
196 | strcpy(pm->prefix, uloginfo->prefix); | ||
197 | |||
198 | if (in) { | ||
199 | strcpy(pm->physindev, in->name); | ||
200 | /* If in isn't a bridge, then physindev==indev */ | ||
201 | if (br_port_exists(in)) | ||
202 | /* rcu_read_lock()ed by nf_hook_slow */ | ||
203 | strcpy(pm->indev, br_port_get_rcu(in)->br->dev->name); | ||
204 | else | ||
205 | strcpy(pm->indev, in->name); | ||
206 | } | ||
207 | |||
208 | if (out) { | ||
209 | /* If out exists, then out is a bridge port */ | ||
210 | strcpy(pm->physoutdev, out->name); | ||
211 | /* rcu_read_lock()ed by nf_hook_slow */ | ||
212 | strcpy(pm->outdev, br_port_get_rcu(out)->br->dev->name); | ||
213 | } | ||
214 | |||
215 | if (skb_copy_bits(skb, -ETH_HLEN, pm->data, copy_len) < 0) | ||
216 | BUG(); | ||
217 | |||
218 | if (ub->qlen > 1) | ||
219 | ub->lastnlh->nlmsg_flags |= NLM_F_MULTI; | ||
220 | |||
221 | ub->lastnlh = nlh; | ||
222 | |||
223 | if (ub->qlen >= uloginfo->qthreshold) | ||
224 | ulog_send(ebt, group); | ||
225 | else if (!timer_pending(&ub->timer)) { | ||
226 | ub->timer.expires = jiffies + flushtimeout * HZ / 100; | ||
227 | add_timer(&ub->timer); | ||
228 | } | ||
229 | |||
230 | unlock: | ||
231 | spin_unlock_bh(lock); | ||
232 | } | ||
233 | |||
234 | /* this function is registered with the netfilter core */ | ||
235 | static void ebt_log_packet(struct net *net, u_int8_t pf, unsigned int hooknum, | ||
236 | const struct sk_buff *skb, const struct net_device *in, | ||
237 | const struct net_device *out, const struct nf_loginfo *li, | ||
238 | const char *prefix) | ||
239 | { | ||
240 | struct ebt_ulog_info loginfo; | ||
241 | |||
242 | if (!li || li->type != NF_LOG_TYPE_ULOG) { | ||
243 | loginfo.nlgroup = EBT_ULOG_DEFAULT_NLGROUP; | ||
244 | loginfo.cprange = 0; | ||
245 | loginfo.qthreshold = EBT_ULOG_DEFAULT_QTHRESHOLD; | ||
246 | loginfo.prefix[0] = '\0'; | ||
247 | } else { | ||
248 | loginfo.nlgroup = li->u.ulog.group; | ||
249 | loginfo.cprange = li->u.ulog.copy_len; | ||
250 | loginfo.qthreshold = li->u.ulog.qthreshold; | ||
251 | strlcpy(loginfo.prefix, prefix, sizeof(loginfo.prefix)); | ||
252 | } | ||
253 | |||
254 | ebt_ulog_packet(net, hooknum, skb, in, out, &loginfo, prefix); | ||
255 | } | ||
256 | |||
257 | static unsigned int | ||
258 | ebt_ulog_tg(struct sk_buff *skb, const struct xt_action_param *par) | ||
259 | { | ||
260 | struct net *net = dev_net(par->in ? par->in : par->out); | ||
261 | |||
262 | ebt_ulog_packet(net, par->hooknum, skb, par->in, par->out, | ||
263 | par->targinfo, NULL); | ||
264 | return EBT_CONTINUE; | ||
265 | } | ||
266 | |||
267 | static int ebt_ulog_tg_check(const struct xt_tgchk_param *par) | ||
268 | { | ||
269 | struct ebt_ulog_info *uloginfo = par->targinfo; | ||
270 | |||
271 | if (!par->net->xt.ebt_ulog_warn_deprecated) { | ||
272 | pr_info("ebt_ulog is deprecated and it will be removed soon, " | ||
273 | "use ebt_nflog instead\n"); | ||
274 | par->net->xt.ebt_ulog_warn_deprecated = true; | ||
275 | } | ||
276 | |||
277 | if (uloginfo->nlgroup > 31) | ||
278 | return -EINVAL; | ||
279 | |||
280 | uloginfo->prefix[EBT_ULOG_PREFIX_LEN - 1] = '\0'; | ||
281 | |||
282 | if (uloginfo->qthreshold > EBT_ULOG_MAX_QLEN) | ||
283 | uloginfo->qthreshold = EBT_ULOG_MAX_QLEN; | ||
284 | |||
285 | return 0; | ||
286 | } | ||
287 | |||
288 | static struct xt_target ebt_ulog_tg_reg __read_mostly = { | ||
289 | .name = "ulog", | ||
290 | .revision = 0, | ||
291 | .family = NFPROTO_BRIDGE, | ||
292 | .target = ebt_ulog_tg, | ||
293 | .checkentry = ebt_ulog_tg_check, | ||
294 | .targetsize = sizeof(struct ebt_ulog_info), | ||
295 | .me = THIS_MODULE, | ||
296 | }; | ||
297 | |||
298 | static struct nf_logger ebt_ulog_logger __read_mostly = { | ||
299 | .name = "ebt_ulog", | ||
300 | .logfn = &ebt_log_packet, | ||
301 | .me = THIS_MODULE, | ||
302 | }; | ||
303 | |||
304 | static int __net_init ebt_ulog_net_init(struct net *net) | ||
305 | { | ||
306 | int i; | ||
307 | struct ebt_ulog_net *ebt = ebt_ulog_pernet(net); | ||
308 | |||
309 | struct netlink_kernel_cfg cfg = { | ||
310 | .groups = EBT_ULOG_MAXNLGROUPS, | ||
311 | }; | ||
312 | |||
313 | /* initialize ulog_buffers */ | ||
314 | for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) { | ||
315 | ebt->nlgroup[i] = i; | ||
316 | setup_timer(&ebt->ulog_buffers[i].timer, ulog_timer, | ||
317 | (unsigned long)&ebt->nlgroup[i]); | ||
318 | spin_lock_init(&ebt->ulog_buffers[i].lock); | ||
319 | } | ||
320 | |||
321 | ebt->ebtulognl = netlink_kernel_create(net, NETLINK_NFLOG, &cfg); | ||
322 | if (!ebt->ebtulognl) | ||
323 | return -ENOMEM; | ||
324 | |||
325 | nf_log_set(net, NFPROTO_BRIDGE, &ebt_ulog_logger); | ||
326 | return 0; | ||
327 | } | ||
328 | |||
329 | static void __net_exit ebt_ulog_net_fini(struct net *net) | ||
330 | { | ||
331 | int i; | ||
332 | struct ebt_ulog_net *ebt = ebt_ulog_pernet(net); | ||
333 | |||
334 | nf_log_unset(net, &ebt_ulog_logger); | ||
335 | for (i = 0; i < EBT_ULOG_MAXNLGROUPS; i++) { | ||
336 | ebt_ulog_buff_t *ub = &ebt->ulog_buffers[i]; | ||
337 | del_timer(&ub->timer); | ||
338 | |||
339 | if (ub->skb) { | ||
340 | kfree_skb(ub->skb); | ||
341 | ub->skb = NULL; | ||
342 | } | ||
343 | } | ||
344 | netlink_kernel_release(ebt->ebtulognl); | ||
345 | } | ||
346 | |||
347 | static struct pernet_operations ebt_ulog_net_ops = { | ||
348 | .init = ebt_ulog_net_init, | ||
349 | .exit = ebt_ulog_net_fini, | ||
350 | .id = &ebt_ulog_net_id, | ||
351 | .size = sizeof(struct ebt_ulog_net), | ||
352 | }; | ||
353 | |||
354 | static int __init ebt_ulog_init(void) | ||
355 | { | ||
356 | int ret; | ||
357 | |||
358 | if (nlbufsiz >= 128*1024) { | ||
359 | pr_warn("Netlink buffer has to be <= 128kB," | ||
360 | "please try a smaller nlbufsiz parameter.\n"); | ||
361 | return -EINVAL; | ||
362 | } | ||
363 | |||
364 | ret = register_pernet_subsys(&ebt_ulog_net_ops); | ||
365 | if (ret) | ||
366 | goto out_pernet; | ||
367 | |||
368 | ret = xt_register_target(&ebt_ulog_tg_reg); | ||
369 | if (ret) | ||
370 | goto out_target; | ||
371 | |||
372 | nf_log_register(NFPROTO_BRIDGE, &ebt_ulog_logger); | ||
373 | |||
374 | return 0; | ||
375 | |||
376 | out_target: | ||
377 | unregister_pernet_subsys(&ebt_ulog_net_ops); | ||
378 | out_pernet: | ||
379 | return ret; | ||
380 | } | ||
381 | |||
382 | static void __exit ebt_ulog_fini(void) | ||
383 | { | ||
384 | nf_log_unregister(&ebt_ulog_logger); | ||
385 | xt_unregister_target(&ebt_ulog_tg_reg); | ||
386 | unregister_pernet_subsys(&ebt_ulog_net_ops); | ||
387 | } | ||
388 | |||
389 | module_init(ebt_ulog_init); | ||
390 | module_exit(ebt_ulog_fini); | ||
391 | MODULE_LICENSE("GPL"); | ||
392 | MODULE_AUTHOR("Bart De Schuymer <bdschuym@pandora.be>"); | ||
393 | MODULE_DESCRIPTION("Ebtables: Packet logging to netlink using ULOG"); | ||
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 1059ed3bc255..6d69631b9f4d 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c | |||
@@ -327,10 +327,7 @@ find_inlist_lock_noload(struct list_head *head, const char *name, int *error, | |||
327 | char name[EBT_FUNCTION_MAXNAMELEN]; | 327 | char name[EBT_FUNCTION_MAXNAMELEN]; |
328 | } *e; | 328 | } *e; |
329 | 329 | ||
330 | *error = mutex_lock_interruptible(mutex); | 330 | mutex_lock(mutex); |
331 | if (*error != 0) | ||
332 | return NULL; | ||
333 | |||
334 | list_for_each_entry(e, head, list) { | 331 | list_for_each_entry(e, head, list) { |
335 | if (strcmp(e->name, name) == 0) | 332 | if (strcmp(e->name, name) == 0) |
336 | return e; | 333 | return e; |
@@ -1203,10 +1200,7 @@ ebt_register_table(struct net *net, const struct ebt_table *input_table) | |||
1203 | 1200 | ||
1204 | table->private = newinfo; | 1201 | table->private = newinfo; |
1205 | rwlock_init(&table->lock); | 1202 | rwlock_init(&table->lock); |
1206 | ret = mutex_lock_interruptible(&ebt_mutex); | 1203 | mutex_lock(&ebt_mutex); |
1207 | if (ret != 0) | ||
1208 | goto free_chainstack; | ||
1209 | |||
1210 | list_for_each_entry(t, &net->xt.tables[NFPROTO_BRIDGE], list) { | 1204 | list_for_each_entry(t, &net->xt.tables[NFPROTO_BRIDGE], list) { |
1211 | if (strcmp(t->name, table->name) == 0) { | 1205 | if (strcmp(t->name, table->name) == 0) { |
1212 | ret = -EEXIST; | 1206 | ret = -EEXIST; |
diff --git a/net/bridge/netfilter/nf_log_bridge.c b/net/bridge/netfilter/nf_log_bridge.c new file mode 100644 index 000000000000..5d9953a90929 --- /dev/null +++ b/net/bridge/netfilter/nf_log_bridge.c | |||
@@ -0,0 +1,96 @@ | |||
1 | /* | ||
2 | * (C) 2014 by Pablo Neira Ayuso <pablo@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 | #include <linux/module.h> | ||
10 | #include <linux/spinlock.h> | ||
11 | #include <linux/skbuff.h> | ||
12 | #include <linux/if_bridge.h> | ||
13 | #include <linux/ip.h> | ||
14 | #include <net/route.h> | ||
15 | |||
16 | #include <linux/netfilter.h> | ||
17 | #include <net/netfilter/nf_log.h> | ||
18 | |||
19 | static void nf_log_bridge_packet(struct net *net, u_int8_t pf, | ||
20 | unsigned int hooknum, | ||
21 | const struct sk_buff *skb, | ||
22 | const struct net_device *in, | ||
23 | const struct net_device *out, | ||
24 | const struct nf_loginfo *loginfo, | ||
25 | const char *prefix) | ||
26 | { | ||
27 | switch (eth_hdr(skb)->h_proto) { | ||
28 | case htons(ETH_P_IP): | ||
29 | nf_log_packet(net, NFPROTO_IPV4, hooknum, skb, in, out, | ||
30 | loginfo, "%s", prefix); | ||
31 | break; | ||
32 | case htons(ETH_P_IPV6): | ||
33 | nf_log_packet(net, NFPROTO_IPV6, hooknum, skb, in, out, | ||
34 | loginfo, "%s", prefix); | ||
35 | break; | ||
36 | case htons(ETH_P_ARP): | ||
37 | case htons(ETH_P_RARP): | ||
38 | nf_log_packet(net, NFPROTO_ARP, hooknum, skb, in, out, | ||
39 | loginfo, "%s", prefix); | ||
40 | break; | ||
41 | } | ||
42 | } | ||
43 | |||
44 | static struct nf_logger nf_bridge_logger __read_mostly = { | ||
45 | .name = "nf_log_bridge", | ||
46 | .type = NF_LOG_TYPE_LOG, | ||
47 | .logfn = nf_log_bridge_packet, | ||
48 | .me = THIS_MODULE, | ||
49 | }; | ||
50 | |||
51 | static int __net_init nf_log_bridge_net_init(struct net *net) | ||
52 | { | ||
53 | nf_log_set(net, NFPROTO_BRIDGE, &nf_bridge_logger); | ||
54 | return 0; | ||
55 | } | ||
56 | |||
57 | static void __net_exit nf_log_bridge_net_exit(struct net *net) | ||
58 | { | ||
59 | nf_log_unset(net, &nf_bridge_logger); | ||
60 | } | ||
61 | |||
62 | static struct pernet_operations nf_log_bridge_net_ops = { | ||
63 | .init = nf_log_bridge_net_init, | ||
64 | .exit = nf_log_bridge_net_exit, | ||
65 | }; | ||
66 | |||
67 | static int __init nf_log_bridge_init(void) | ||
68 | { | ||
69 | int ret; | ||
70 | |||
71 | /* Request to load the real packet loggers. */ | ||
72 | nf_logger_request_module(NFPROTO_IPV4, NF_LOG_TYPE_LOG); | ||
73 | nf_logger_request_module(NFPROTO_IPV6, NF_LOG_TYPE_LOG); | ||
74 | nf_logger_request_module(NFPROTO_ARP, NF_LOG_TYPE_LOG); | ||
75 | |||
76 | ret = register_pernet_subsys(&nf_log_bridge_net_ops); | ||
77 | if (ret < 0) | ||
78 | return ret; | ||
79 | |||
80 | nf_log_register(NFPROTO_BRIDGE, &nf_bridge_logger); | ||
81 | return 0; | ||
82 | } | ||
83 | |||
84 | static void __exit nf_log_bridge_exit(void) | ||
85 | { | ||
86 | unregister_pernet_subsys(&nf_log_bridge_net_ops); | ||
87 | nf_log_unregister(&nf_bridge_logger); | ||
88 | } | ||
89 | |||
90 | module_init(nf_log_bridge_init); | ||
91 | module_exit(nf_log_bridge_exit); | ||
92 | |||
93 | MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); | ||
94 | MODULE_DESCRIPTION("Netfilter bridge packet logging"); | ||
95 | MODULE_LICENSE("GPL"); | ||
96 | MODULE_ALIAS_NF_LOGGER(AF_BRIDGE, 0); | ||
diff --git a/net/bridge/netfilter/nft_reject_bridge.c b/net/bridge/netfilter/nft_reject_bridge.c new file mode 100644 index 000000000000..ee3ffe93e14e --- /dev/null +++ b/net/bridge/netfilter/nft_reject_bridge.c | |||
@@ -0,0 +1,67 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2014 Pablo Neira Ayuso <pablo@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 | #include <linux/kernel.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <linux/module.h> | ||
12 | #include <linux/netlink.h> | ||
13 | #include <linux/netfilter.h> | ||
14 | #include <linux/netfilter/nf_tables.h> | ||
15 | #include <net/netfilter/nf_tables.h> | ||
16 | #include <net/netfilter/nft_reject.h> | ||
17 | |||
18 | static void nft_reject_bridge_eval(const struct nft_expr *expr, | ||
19 | struct nft_data data[NFT_REG_MAX + 1], | ||
20 | const struct nft_pktinfo *pkt) | ||
21 | { | ||
22 | switch (eth_hdr(pkt->skb)->h_proto) { | ||
23 | case htons(ETH_P_IP): | ||
24 | return nft_reject_ipv4_eval(expr, data, pkt); | ||
25 | case htons(ETH_P_IPV6): | ||
26 | return nft_reject_ipv6_eval(expr, data, pkt); | ||
27 | default: | ||
28 | /* No explicit way to reject this protocol, drop it. */ | ||
29 | data[NFT_REG_VERDICT].verdict = NF_DROP; | ||
30 | break; | ||
31 | } | ||
32 | } | ||
33 | |||
34 | static struct nft_expr_type nft_reject_bridge_type; | ||
35 | static const struct nft_expr_ops nft_reject_bridge_ops = { | ||
36 | .type = &nft_reject_bridge_type, | ||
37 | .size = NFT_EXPR_SIZE(sizeof(struct nft_reject)), | ||
38 | .eval = nft_reject_bridge_eval, | ||
39 | .init = nft_reject_init, | ||
40 | .dump = nft_reject_dump, | ||
41 | }; | ||
42 | |||
43 | static struct nft_expr_type nft_reject_bridge_type __read_mostly = { | ||
44 | .family = NFPROTO_BRIDGE, | ||
45 | .name = "reject", | ||
46 | .ops = &nft_reject_bridge_ops, | ||
47 | .policy = nft_reject_policy, | ||
48 | .maxattr = NFTA_REJECT_MAX, | ||
49 | .owner = THIS_MODULE, | ||
50 | }; | ||
51 | |||
52 | static int __init nft_reject_bridge_module_init(void) | ||
53 | { | ||
54 | return nft_register_expr(&nft_reject_bridge_type); | ||
55 | } | ||
56 | |||
57 | static void __exit nft_reject_bridge_module_exit(void) | ||
58 | { | ||
59 | nft_unregister_expr(&nft_reject_bridge_type); | ||
60 | } | ||
61 | |||
62 | module_init(nft_reject_bridge_module_init); | ||
63 | module_exit(nft_reject_bridge_module_exit); | ||
64 | |||
65 | MODULE_LICENSE("GPL"); | ||
66 | MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); | ||
67 | MODULE_ALIAS_NFT_AF_EXPR(AF_BRIDGE, "reject"); | ||
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index e8437094d15f..43f750e88e19 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c | |||
@@ -908,8 +908,7 @@ static int caif_release(struct socket *sock) | |||
908 | sock->sk = NULL; | 908 | sock->sk = NULL; |
909 | 909 | ||
910 | WARN_ON(IS_ERR(cf_sk->debugfs_socket_dir)); | 910 | WARN_ON(IS_ERR(cf_sk->debugfs_socket_dir)); |
911 | if (cf_sk->debugfs_socket_dir != NULL) | 911 | debugfs_remove_recursive(cf_sk->debugfs_socket_dir); |
912 | debugfs_remove_recursive(cf_sk->debugfs_socket_dir); | ||
913 | 912 | ||
914 | lock_sock(&(cf_sk->sk)); | 913 | lock_sock(&(cf_sk->sk)); |
915 | sk->sk_state = CAIF_DISCONNECTED; | 914 | sk->sk_state = CAIF_DISCONNECTED; |
diff --git a/net/caif/cfctrl.c b/net/caif/cfctrl.c index 0f455227da83..f5afda1abc76 100644 --- a/net/caif/cfctrl.c +++ b/net/caif/cfctrl.c | |||
@@ -547,7 +547,6 @@ static int cfctrl_recv(struct cflayer *layer, struct cfpkt *pkt) | |||
547 | default: | 547 | default: |
548 | pr_err("Unrecognized Control Frame\n"); | 548 | pr_err("Unrecognized Control Frame\n"); |
549 | goto error; | 549 | goto error; |
550 | break; | ||
551 | } | 550 | } |
552 | ret = 0; | 551 | ret = 0; |
553 | error: | 552 | error: |
diff --git a/net/ceph/auth_x.c b/net/ceph/auth_x.c index 96238ba95f2b..de6662b14e1f 100644 --- a/net/ceph/auth_x.c +++ b/net/ceph/auth_x.c | |||
@@ -13,8 +13,6 @@ | |||
13 | #include "auth_x.h" | 13 | #include "auth_x.h" |
14 | #include "auth_x_protocol.h" | 14 | #include "auth_x_protocol.h" |
15 | 15 | ||
16 | #define TEMP_TICKET_BUF_LEN 256 | ||
17 | |||
18 | static void ceph_x_validate_tickets(struct ceph_auth_client *ac, int *pneed); | 16 | static void ceph_x_validate_tickets(struct ceph_auth_client *ac, int *pneed); |
19 | 17 | ||
20 | static int ceph_x_is_authenticated(struct ceph_auth_client *ac) | 18 | static int ceph_x_is_authenticated(struct ceph_auth_client *ac) |
@@ -64,7 +62,7 @@ static int ceph_x_encrypt(struct ceph_crypto_key *secret, | |||
64 | } | 62 | } |
65 | 63 | ||
66 | static int ceph_x_decrypt(struct ceph_crypto_key *secret, | 64 | static int ceph_x_decrypt(struct ceph_crypto_key *secret, |
67 | void **p, void *end, void *obuf, size_t olen) | 65 | void **p, void *end, void **obuf, size_t olen) |
68 | { | 66 | { |
69 | struct ceph_x_encrypt_header head; | 67 | struct ceph_x_encrypt_header head; |
70 | size_t head_len = sizeof(head); | 68 | size_t head_len = sizeof(head); |
@@ -75,8 +73,14 @@ static int ceph_x_decrypt(struct ceph_crypto_key *secret, | |||
75 | return -EINVAL; | 73 | return -EINVAL; |
76 | 74 | ||
77 | dout("ceph_x_decrypt len %d\n", len); | 75 | dout("ceph_x_decrypt len %d\n", len); |
78 | ret = ceph_decrypt2(secret, &head, &head_len, obuf, &olen, | 76 | if (*obuf == NULL) { |
79 | *p, len); | 77 | *obuf = kmalloc(len, GFP_NOFS); |
78 | if (!*obuf) | ||
79 | return -ENOMEM; | ||
80 | olen = len; | ||
81 | } | ||
82 | |||
83 | ret = ceph_decrypt2(secret, &head, &head_len, *obuf, &olen, *p, len); | ||
80 | if (ret) | 84 | if (ret) |
81 | return ret; | 85 | return ret; |
82 | if (head.struct_v != 1 || le64_to_cpu(head.magic) != CEPHX_ENC_MAGIC) | 86 | if (head.struct_v != 1 || le64_to_cpu(head.magic) != CEPHX_ENC_MAGIC) |
@@ -129,139 +133,120 @@ static void remove_ticket_handler(struct ceph_auth_client *ac, | |||
129 | kfree(th); | 133 | kfree(th); |
130 | } | 134 | } |
131 | 135 | ||
132 | static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac, | 136 | static int process_one_ticket(struct ceph_auth_client *ac, |
133 | struct ceph_crypto_key *secret, | 137 | struct ceph_crypto_key *secret, |
134 | void *buf, void *end) | 138 | void **p, void *end) |
135 | { | 139 | { |
136 | struct ceph_x_info *xi = ac->private; | 140 | struct ceph_x_info *xi = ac->private; |
137 | int num; | 141 | int type; |
138 | void *p = buf; | 142 | u8 tkt_struct_v, blob_struct_v; |
143 | struct ceph_x_ticket_handler *th; | ||
144 | void *dbuf = NULL; | ||
145 | void *dp, *dend; | ||
146 | int dlen; | ||
147 | char is_enc; | ||
148 | struct timespec validity; | ||
149 | struct ceph_crypto_key old_key; | ||
150 | void *ticket_buf = NULL; | ||
151 | void *tp, *tpend; | ||
152 | struct ceph_timespec new_validity; | ||
153 | struct ceph_crypto_key new_session_key; | ||
154 | struct ceph_buffer *new_ticket_blob; | ||
155 | unsigned long new_expires, new_renew_after; | ||
156 | u64 new_secret_id; | ||
139 | int ret; | 157 | int ret; |
140 | char *dbuf; | ||
141 | char *ticket_buf; | ||
142 | u8 reply_struct_v; | ||
143 | 158 | ||
144 | dbuf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS); | 159 | ceph_decode_need(p, end, sizeof(u32) + 1, bad); |
145 | if (!dbuf) | ||
146 | return -ENOMEM; | ||
147 | 160 | ||
148 | ret = -ENOMEM; | 161 | type = ceph_decode_32(p); |
149 | ticket_buf = kmalloc(TEMP_TICKET_BUF_LEN, GFP_NOFS); | 162 | dout(" ticket type %d %s\n", type, ceph_entity_type_name(type)); |
150 | if (!ticket_buf) | ||
151 | goto out_dbuf; | ||
152 | 163 | ||
153 | ceph_decode_need(&p, end, 1 + sizeof(u32), bad); | 164 | tkt_struct_v = ceph_decode_8(p); |
154 | reply_struct_v = ceph_decode_8(&p); | 165 | if (tkt_struct_v != 1) |
155 | if (reply_struct_v != 1) | ||
156 | goto bad; | 166 | goto bad; |
157 | num = ceph_decode_32(&p); | ||
158 | dout("%d tickets\n", num); | ||
159 | while (num--) { | ||
160 | int type; | ||
161 | u8 tkt_struct_v, blob_struct_v; | ||
162 | struct ceph_x_ticket_handler *th; | ||
163 | void *dp, *dend; | ||
164 | int dlen; | ||
165 | char is_enc; | ||
166 | struct timespec validity; | ||
167 | struct ceph_crypto_key old_key; | ||
168 | void *tp, *tpend; | ||
169 | struct ceph_timespec new_validity; | ||
170 | struct ceph_crypto_key new_session_key; | ||
171 | struct ceph_buffer *new_ticket_blob; | ||
172 | unsigned long new_expires, new_renew_after; | ||
173 | u64 new_secret_id; | ||
174 | |||
175 | ceph_decode_need(&p, end, sizeof(u32) + 1, bad); | ||
176 | |||
177 | type = ceph_decode_32(&p); | ||
178 | dout(" ticket type %d %s\n", type, ceph_entity_type_name(type)); | ||
179 | |||
180 | tkt_struct_v = ceph_decode_8(&p); | ||
181 | if (tkt_struct_v != 1) | ||
182 | goto bad; | ||
183 | |||
184 | th = get_ticket_handler(ac, type); | ||
185 | if (IS_ERR(th)) { | ||
186 | ret = PTR_ERR(th); | ||
187 | goto out; | ||
188 | } | ||
189 | 167 | ||
190 | /* blob for me */ | 168 | th = get_ticket_handler(ac, type); |
191 | dlen = ceph_x_decrypt(secret, &p, end, dbuf, | 169 | if (IS_ERR(th)) { |
192 | TEMP_TICKET_BUF_LEN); | 170 | ret = PTR_ERR(th); |
193 | if (dlen <= 0) { | 171 | goto out; |
194 | ret = dlen; | 172 | } |
195 | goto out; | ||
196 | } | ||
197 | dout(" decrypted %d bytes\n", dlen); | ||
198 | dend = dbuf + dlen; | ||
199 | dp = dbuf; | ||
200 | 173 | ||
201 | tkt_struct_v = ceph_decode_8(&dp); | 174 | /* blob for me */ |
202 | if (tkt_struct_v != 1) | 175 | dlen = ceph_x_decrypt(secret, p, end, &dbuf, 0); |
203 | goto bad; | 176 | if (dlen <= 0) { |
177 | ret = dlen; | ||
178 | goto out; | ||
179 | } | ||
180 | dout(" decrypted %d bytes\n", dlen); | ||
181 | dp = dbuf; | ||
182 | dend = dp + dlen; | ||
204 | 183 | ||
205 | memcpy(&old_key, &th->session_key, sizeof(old_key)); | 184 | tkt_struct_v = ceph_decode_8(&dp); |
206 | ret = ceph_crypto_key_decode(&new_session_key, &dp, dend); | 185 | if (tkt_struct_v != 1) |
207 | if (ret) | 186 | goto bad; |
208 | goto out; | ||
209 | 187 | ||
210 | ceph_decode_copy(&dp, &new_validity, sizeof(new_validity)); | 188 | memcpy(&old_key, &th->session_key, sizeof(old_key)); |
211 | ceph_decode_timespec(&validity, &new_validity); | 189 | ret = ceph_crypto_key_decode(&new_session_key, &dp, dend); |
212 | new_expires = get_seconds() + validity.tv_sec; | 190 | if (ret) |
213 | new_renew_after = new_expires - (validity.tv_sec / 4); | 191 | goto out; |
214 | dout(" expires=%lu renew_after=%lu\n", new_expires, | ||
215 | new_renew_after); | ||
216 | 192 | ||
217 | /* ticket blob for service */ | 193 | ceph_decode_copy(&dp, &new_validity, sizeof(new_validity)); |
218 | ceph_decode_8_safe(&p, end, is_enc, bad); | 194 | ceph_decode_timespec(&validity, &new_validity); |
219 | tp = ticket_buf; | 195 | new_expires = get_seconds() + validity.tv_sec; |
220 | if (is_enc) { | 196 | new_renew_after = new_expires - (validity.tv_sec / 4); |
221 | /* encrypted */ | 197 | dout(" expires=%lu renew_after=%lu\n", new_expires, |
222 | dout(" encrypted ticket\n"); | 198 | new_renew_after); |
223 | dlen = ceph_x_decrypt(&old_key, &p, end, ticket_buf, | 199 | |
224 | TEMP_TICKET_BUF_LEN); | 200 | /* ticket blob for service */ |
225 | if (dlen < 0) { | 201 | ceph_decode_8_safe(p, end, is_enc, bad); |
226 | ret = dlen; | 202 | if (is_enc) { |
227 | goto out; | 203 | /* encrypted */ |
228 | } | 204 | dout(" encrypted ticket\n"); |
229 | dlen = ceph_decode_32(&tp); | 205 | dlen = ceph_x_decrypt(&old_key, p, end, &ticket_buf, 0); |
230 | } else { | 206 | if (dlen < 0) { |
231 | /* unencrypted */ | 207 | ret = dlen; |
232 | ceph_decode_32_safe(&p, end, dlen, bad); | 208 | goto out; |
233 | ceph_decode_need(&p, end, dlen, bad); | ||
234 | ceph_decode_copy(&p, ticket_buf, dlen); | ||
235 | } | 209 | } |
236 | tpend = tp + dlen; | 210 | tp = ticket_buf; |
237 | dout(" ticket blob is %d bytes\n", dlen); | 211 | dlen = ceph_decode_32(&tp); |
238 | ceph_decode_need(&tp, tpend, 1 + sizeof(u64), bad); | 212 | } else { |
239 | blob_struct_v = ceph_decode_8(&tp); | 213 | /* unencrypted */ |
240 | new_secret_id = ceph_decode_64(&tp); | 214 | ceph_decode_32_safe(p, end, dlen, bad); |
241 | ret = ceph_decode_buffer(&new_ticket_blob, &tp, tpend); | 215 | ticket_buf = kmalloc(dlen, GFP_NOFS); |
242 | if (ret) | 216 | if (!ticket_buf) { |
217 | ret = -ENOMEM; | ||
243 | goto out; | 218 | goto out; |
244 | 219 | } | |
245 | /* all is well, update our ticket */ | 220 | tp = ticket_buf; |
246 | ceph_crypto_key_destroy(&th->session_key); | 221 | ceph_decode_need(p, end, dlen, bad); |
247 | if (th->ticket_blob) | 222 | ceph_decode_copy(p, ticket_buf, dlen); |
248 | ceph_buffer_put(th->ticket_blob); | ||
249 | th->session_key = new_session_key; | ||
250 | th->ticket_blob = new_ticket_blob; | ||
251 | th->validity = new_validity; | ||
252 | th->secret_id = new_secret_id; | ||
253 | th->expires = new_expires; | ||
254 | th->renew_after = new_renew_after; | ||
255 | dout(" got ticket service %d (%s) secret_id %lld len %d\n", | ||
256 | type, ceph_entity_type_name(type), th->secret_id, | ||
257 | (int)th->ticket_blob->vec.iov_len); | ||
258 | xi->have_keys |= th->service; | ||
259 | } | 223 | } |
224 | tpend = tp + dlen; | ||
225 | dout(" ticket blob is %d bytes\n", dlen); | ||
226 | ceph_decode_need(&tp, tpend, 1 + sizeof(u64), bad); | ||
227 | blob_struct_v = ceph_decode_8(&tp); | ||
228 | new_secret_id = ceph_decode_64(&tp); | ||
229 | ret = ceph_decode_buffer(&new_ticket_blob, &tp, tpend); | ||
230 | if (ret) | ||
231 | goto out; | ||
232 | |||
233 | /* all is well, update our ticket */ | ||
234 | ceph_crypto_key_destroy(&th->session_key); | ||
235 | if (th->ticket_blob) | ||
236 | ceph_buffer_put(th->ticket_blob); | ||
237 | th->session_key = new_session_key; | ||
238 | th->ticket_blob = new_ticket_blob; | ||
239 | th->validity = new_validity; | ||
240 | th->secret_id = new_secret_id; | ||
241 | th->expires = new_expires; | ||
242 | th->renew_after = new_renew_after; | ||
243 | dout(" got ticket service %d (%s) secret_id %lld len %d\n", | ||
244 | type, ceph_entity_type_name(type), th->secret_id, | ||
245 | (int)th->ticket_blob->vec.iov_len); | ||
246 | xi->have_keys |= th->service; | ||
260 | 247 | ||
261 | ret = 0; | ||
262 | out: | 248 | out: |
263 | kfree(ticket_buf); | 249 | kfree(ticket_buf); |
264 | out_dbuf: | ||
265 | kfree(dbuf); | 250 | kfree(dbuf); |
266 | return ret; | 251 | return ret; |
267 | 252 | ||
@@ -270,6 +255,34 @@ bad: | |||
270 | goto out; | 255 | goto out; |
271 | } | 256 | } |
272 | 257 | ||
258 | static int ceph_x_proc_ticket_reply(struct ceph_auth_client *ac, | ||
259 | struct ceph_crypto_key *secret, | ||
260 | void *buf, void *end) | ||
261 | { | ||
262 | void *p = buf; | ||
263 | u8 reply_struct_v; | ||
264 | u32 num; | ||
265 | int ret; | ||
266 | |||
267 | ceph_decode_8_safe(&p, end, reply_struct_v, bad); | ||
268 | if (reply_struct_v != 1) | ||
269 | return -EINVAL; | ||
270 | |||
271 | ceph_decode_32_safe(&p, end, num, bad); | ||
272 | dout("%d tickets\n", num); | ||
273 | |||
274 | while (num--) { | ||
275 | ret = process_one_ticket(ac, secret, &p, end); | ||
276 | if (ret) | ||
277 | return ret; | ||
278 | } | ||
279 | |||
280 | return 0; | ||
281 | |||
282 | bad: | ||
283 | return -EINVAL; | ||
284 | } | ||
285 | |||
273 | static int ceph_x_build_authorizer(struct ceph_auth_client *ac, | 286 | static int ceph_x_build_authorizer(struct ceph_auth_client *ac, |
274 | struct ceph_x_ticket_handler *th, | 287 | struct ceph_x_ticket_handler *th, |
275 | struct ceph_x_authorizer *au) | 288 | struct ceph_x_authorizer *au) |
@@ -583,13 +596,14 @@ static int ceph_x_verify_authorizer_reply(struct ceph_auth_client *ac, | |||
583 | struct ceph_x_ticket_handler *th; | 596 | struct ceph_x_ticket_handler *th; |
584 | int ret = 0; | 597 | int ret = 0; |
585 | struct ceph_x_authorize_reply reply; | 598 | struct ceph_x_authorize_reply reply; |
599 | void *preply = &reply; | ||
586 | void *p = au->reply_buf; | 600 | void *p = au->reply_buf; |
587 | void *end = p + sizeof(au->reply_buf); | 601 | void *end = p + sizeof(au->reply_buf); |
588 | 602 | ||
589 | th = get_ticket_handler(ac, au->service); | 603 | th = get_ticket_handler(ac, au->service); |
590 | if (IS_ERR(th)) | 604 | if (IS_ERR(th)) |
591 | return PTR_ERR(th); | 605 | return PTR_ERR(th); |
592 | ret = ceph_x_decrypt(&th->session_key, &p, end, &reply, sizeof(reply)); | 606 | ret = ceph_x_decrypt(&th->session_key, &p, end, &preply, sizeof(reply)); |
593 | if (ret < 0) | 607 | if (ret < 0) |
594 | return ret; | 608 | return ret; |
595 | if (ret != sizeof(reply)) | 609 | if (ret != sizeof(reply)) |
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 1948d592aa54..b2f571dd933d 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c | |||
@@ -174,6 +174,7 @@ static struct lock_class_key socket_class; | |||
174 | #define SKIP_BUF_SIZE 1024 | 174 | #define SKIP_BUF_SIZE 1024 |
175 | 175 | ||
176 | static void queue_con(struct ceph_connection *con); | 176 | static void queue_con(struct ceph_connection *con); |
177 | static void cancel_con(struct ceph_connection *con); | ||
177 | static void con_work(struct work_struct *); | 178 | static void con_work(struct work_struct *); |
178 | static void con_fault(struct ceph_connection *con); | 179 | static void con_fault(struct ceph_connection *con); |
179 | 180 | ||
@@ -680,7 +681,7 @@ void ceph_con_close(struct ceph_connection *con) | |||
680 | 681 | ||
681 | reset_connection(con); | 682 | reset_connection(con); |
682 | con->peer_global_seq = 0; | 683 | con->peer_global_seq = 0; |
683 | cancel_delayed_work(&con->work); | 684 | cancel_con(con); |
684 | con_close_socket(con); | 685 | con_close_socket(con); |
685 | mutex_unlock(&con->mutex); | 686 | mutex_unlock(&con->mutex); |
686 | } | 687 | } |
@@ -900,7 +901,7 @@ static void ceph_msg_data_pages_cursor_init(struct ceph_msg_data_cursor *cursor, | |||
900 | BUG_ON(page_count > (int)USHRT_MAX); | 901 | BUG_ON(page_count > (int)USHRT_MAX); |
901 | cursor->page_count = (unsigned short)page_count; | 902 | cursor->page_count = (unsigned short)page_count; |
902 | BUG_ON(length > SIZE_MAX - cursor->page_offset); | 903 | BUG_ON(length > SIZE_MAX - cursor->page_offset); |
903 | cursor->last_piece = (size_t)cursor->page_offset + length <= PAGE_SIZE; | 904 | cursor->last_piece = cursor->page_offset + cursor->resid <= PAGE_SIZE; |
904 | } | 905 | } |
905 | 906 | ||
906 | static struct page * | 907 | static struct page * |
@@ -2667,19 +2668,16 @@ static int queue_con_delay(struct ceph_connection *con, unsigned long delay) | |||
2667 | { | 2668 | { |
2668 | if (!con->ops->get(con)) { | 2669 | if (!con->ops->get(con)) { |
2669 | dout("%s %p ref count 0\n", __func__, con); | 2670 | dout("%s %p ref count 0\n", __func__, con); |
2670 | |||
2671 | return -ENOENT; | 2671 | return -ENOENT; |
2672 | } | 2672 | } |
2673 | 2673 | ||
2674 | if (!queue_delayed_work(ceph_msgr_wq, &con->work, delay)) { | 2674 | if (!queue_delayed_work(ceph_msgr_wq, &con->work, delay)) { |
2675 | dout("%s %p - already queued\n", __func__, con); | 2675 | dout("%s %p - already queued\n", __func__, con); |
2676 | con->ops->put(con); | 2676 | con->ops->put(con); |
2677 | |||
2678 | return -EBUSY; | 2677 | return -EBUSY; |
2679 | } | 2678 | } |
2680 | 2679 | ||
2681 | dout("%s %p %lu\n", __func__, con, delay); | 2680 | dout("%s %p %lu\n", __func__, con, delay); |
2682 | |||
2683 | return 0; | 2681 | return 0; |
2684 | } | 2682 | } |
2685 | 2683 | ||
@@ -2688,6 +2686,14 @@ static void queue_con(struct ceph_connection *con) | |||
2688 | (void) queue_con_delay(con, 0); | 2686 | (void) queue_con_delay(con, 0); |
2689 | } | 2687 | } |
2690 | 2688 | ||
2689 | static void cancel_con(struct ceph_connection *con) | ||
2690 | { | ||
2691 | if (cancel_delayed_work(&con->work)) { | ||
2692 | dout("%s %p\n", __func__, con); | ||
2693 | con->ops->put(con); | ||
2694 | } | ||
2695 | } | ||
2696 | |||
2691 | static bool con_sock_closed(struct ceph_connection *con) | 2697 | static bool con_sock_closed(struct ceph_connection *con) |
2692 | { | 2698 | { |
2693 | if (!con_flag_test_and_clear(con, CON_FLAG_SOCK_CLOSED)) | 2699 | if (!con_flag_test_and_clear(con, CON_FLAG_SOCK_CLOSED)) |
@@ -3269,24 +3275,21 @@ static int ceph_con_in_msg_alloc(struct ceph_connection *con, int *skip) | |||
3269 | /* | 3275 | /* |
3270 | * Free a generically kmalloc'd message. | 3276 | * Free a generically kmalloc'd message. |
3271 | */ | 3277 | */ |
3272 | void ceph_msg_kfree(struct ceph_msg *m) | 3278 | static void ceph_msg_free(struct ceph_msg *m) |
3273 | { | 3279 | { |
3274 | dout("msg_kfree %p\n", m); | 3280 | dout("%s %p\n", __func__, m); |
3275 | ceph_kvfree(m->front.iov_base); | 3281 | ceph_kvfree(m->front.iov_base); |
3276 | kmem_cache_free(ceph_msg_cache, m); | 3282 | kmem_cache_free(ceph_msg_cache, m); |
3277 | } | 3283 | } |
3278 | 3284 | ||
3279 | /* | 3285 | static void ceph_msg_release(struct kref *kref) |
3280 | * Drop a msg ref. Destroy as needed. | ||
3281 | */ | ||
3282 | void ceph_msg_last_put(struct kref *kref) | ||
3283 | { | 3286 | { |
3284 | struct ceph_msg *m = container_of(kref, struct ceph_msg, kref); | 3287 | struct ceph_msg *m = container_of(kref, struct ceph_msg, kref); |
3285 | LIST_HEAD(data); | 3288 | LIST_HEAD(data); |
3286 | struct list_head *links; | 3289 | struct list_head *links; |
3287 | struct list_head *next; | 3290 | struct list_head *next; |
3288 | 3291 | ||
3289 | dout("ceph_msg_put last one on %p\n", m); | 3292 | dout("%s %p\n", __func__, m); |
3290 | WARN_ON(!list_empty(&m->list_head)); | 3293 | WARN_ON(!list_empty(&m->list_head)); |
3291 | 3294 | ||
3292 | /* drop middle, data, if any */ | 3295 | /* drop middle, data, if any */ |
@@ -3308,9 +3311,25 @@ void ceph_msg_last_put(struct kref *kref) | |||
3308 | if (m->pool) | 3311 | if (m->pool) |
3309 | ceph_msgpool_put(m->pool, m); | 3312 | ceph_msgpool_put(m->pool, m); |
3310 | else | 3313 | else |
3311 | ceph_msg_kfree(m); | 3314 | ceph_msg_free(m); |
3315 | } | ||
3316 | |||
3317 | struct ceph_msg *ceph_msg_get(struct ceph_msg *msg) | ||
3318 | { | ||
3319 | dout("%s %p (was %d)\n", __func__, msg, | ||
3320 | atomic_read(&msg->kref.refcount)); | ||
3321 | kref_get(&msg->kref); | ||
3322 | return msg; | ||
3323 | } | ||
3324 | EXPORT_SYMBOL(ceph_msg_get); | ||
3325 | |||
3326 | void ceph_msg_put(struct ceph_msg *msg) | ||
3327 | { | ||
3328 | dout("%s %p (was %d)\n", __func__, msg, | ||
3329 | atomic_read(&msg->kref.refcount)); | ||
3330 | kref_put(&msg->kref, ceph_msg_release); | ||
3312 | } | 3331 | } |
3313 | EXPORT_SYMBOL(ceph_msg_last_put); | 3332 | EXPORT_SYMBOL(ceph_msg_put); |
3314 | 3333 | ||
3315 | void ceph_msg_dump(struct ceph_msg *msg) | 3334 | void ceph_msg_dump(struct ceph_msg *msg) |
3316 | { | 3335 | { |
diff --git a/net/ceph/mon_client.c b/net/ceph/mon_client.c index 067d3af2eaf6..61fcfc304f68 100644 --- a/net/ceph/mon_client.c +++ b/net/ceph/mon_client.c | |||
@@ -1181,7 +1181,15 @@ static struct ceph_msg *mon_alloc_msg(struct ceph_connection *con, | |||
1181 | if (!m) { | 1181 | if (!m) { |
1182 | pr_info("alloc_msg unknown type %d\n", type); | 1182 | pr_info("alloc_msg unknown type %d\n", type); |
1183 | *skip = 1; | 1183 | *skip = 1; |
1184 | } else if (front_len > m->front_alloc_len) { | ||
1185 | pr_warning("mon_alloc_msg front %d > prealloc %d (%u#%llu)\n", | ||
1186 | front_len, m->front_alloc_len, | ||
1187 | (unsigned int)con->peer_name.type, | ||
1188 | le64_to_cpu(con->peer_name.num)); | ||
1189 | ceph_msg_put(m); | ||
1190 | m = ceph_msg_new(type, front_len, GFP_NOFS, false); | ||
1184 | } | 1191 | } |
1192 | |||
1185 | return m; | 1193 | return m; |
1186 | } | 1194 | } |
1187 | 1195 | ||
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 05be0c181695..30f6faf3584f 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c | |||
@@ -297,12 +297,21 @@ static void osd_req_op_data_release(struct ceph_osd_request *osd_req, | |||
297 | /* | 297 | /* |
298 | * requests | 298 | * requests |
299 | */ | 299 | */ |
300 | void ceph_osdc_release_request(struct kref *kref) | 300 | static void ceph_osdc_release_request(struct kref *kref) |
301 | { | 301 | { |
302 | struct ceph_osd_request *req; | 302 | struct ceph_osd_request *req = container_of(kref, |
303 | struct ceph_osd_request, r_kref); | ||
303 | unsigned int which; | 304 | unsigned int which; |
304 | 305 | ||
305 | req = container_of(kref, struct ceph_osd_request, r_kref); | 306 | dout("%s %p (r_request %p r_reply %p)\n", __func__, req, |
307 | req->r_request, req->r_reply); | ||
308 | WARN_ON(!RB_EMPTY_NODE(&req->r_node)); | ||
309 | WARN_ON(!list_empty(&req->r_req_lru_item)); | ||
310 | WARN_ON(!list_empty(&req->r_osd_item)); | ||
311 | WARN_ON(!list_empty(&req->r_linger_item)); | ||
312 | WARN_ON(!list_empty(&req->r_linger_osd_item)); | ||
313 | WARN_ON(req->r_osd); | ||
314 | |||
306 | if (req->r_request) | 315 | if (req->r_request) |
307 | ceph_msg_put(req->r_request); | 316 | ceph_msg_put(req->r_request); |
308 | if (req->r_reply) { | 317 | if (req->r_reply) { |
@@ -320,7 +329,22 @@ void ceph_osdc_release_request(struct kref *kref) | |||
320 | kmem_cache_free(ceph_osd_request_cache, req); | 329 | kmem_cache_free(ceph_osd_request_cache, req); |
321 | 330 | ||
322 | } | 331 | } |
323 | EXPORT_SYMBOL(ceph_osdc_release_request); | 332 | |
333 | void ceph_osdc_get_request(struct ceph_osd_request *req) | ||
334 | { | ||
335 | dout("%s %p (was %d)\n", __func__, req, | ||
336 | atomic_read(&req->r_kref.refcount)); | ||
337 | kref_get(&req->r_kref); | ||
338 | } | ||
339 | EXPORT_SYMBOL(ceph_osdc_get_request); | ||
340 | |||
341 | void ceph_osdc_put_request(struct ceph_osd_request *req) | ||
342 | { | ||
343 | dout("%s %p (was %d)\n", __func__, req, | ||
344 | atomic_read(&req->r_kref.refcount)); | ||
345 | kref_put(&req->r_kref, ceph_osdc_release_request); | ||
346 | } | ||
347 | EXPORT_SYMBOL(ceph_osdc_put_request); | ||
324 | 348 | ||
325 | struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc, | 349 | struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc, |
326 | struct ceph_snap_context *snapc, | 350 | struct ceph_snap_context *snapc, |
@@ -364,7 +388,7 @@ struct ceph_osd_request *ceph_osdc_alloc_request(struct ceph_osd_client *osdc, | |||
364 | RB_CLEAR_NODE(&req->r_node); | 388 | RB_CLEAR_NODE(&req->r_node); |
365 | INIT_LIST_HEAD(&req->r_unsafe_item); | 389 | INIT_LIST_HEAD(&req->r_unsafe_item); |
366 | INIT_LIST_HEAD(&req->r_linger_item); | 390 | INIT_LIST_HEAD(&req->r_linger_item); |
367 | INIT_LIST_HEAD(&req->r_linger_osd); | 391 | INIT_LIST_HEAD(&req->r_linger_osd_item); |
368 | INIT_LIST_HEAD(&req->r_req_lru_item); | 392 | INIT_LIST_HEAD(&req->r_req_lru_item); |
369 | INIT_LIST_HEAD(&req->r_osd_item); | 393 | INIT_LIST_HEAD(&req->r_osd_item); |
370 | 394 | ||
@@ -916,7 +940,7 @@ static void __kick_osd_requests(struct ceph_osd_client *osdc, | |||
916 | * list at the end to keep things in tid order. | 940 | * list at the end to keep things in tid order. |
917 | */ | 941 | */ |
918 | list_for_each_entry_safe(req, nreq, &osd->o_linger_requests, | 942 | list_for_each_entry_safe(req, nreq, &osd->o_linger_requests, |
919 | r_linger_osd) { | 943 | r_linger_osd_item) { |
920 | /* | 944 | /* |
921 | * reregister request prior to unregistering linger so | 945 | * reregister request prior to unregistering linger so |
922 | * that r_osd is preserved. | 946 | * that r_osd is preserved. |
@@ -1008,6 +1032,8 @@ static void __remove_osd(struct ceph_osd_client *osdc, struct ceph_osd *osd) | |||
1008 | { | 1032 | { |
1009 | dout("__remove_osd %p\n", osd); | 1033 | dout("__remove_osd %p\n", osd); |
1010 | BUG_ON(!list_empty(&osd->o_requests)); | 1034 | BUG_ON(!list_empty(&osd->o_requests)); |
1035 | BUG_ON(!list_empty(&osd->o_linger_requests)); | ||
1036 | |||
1011 | rb_erase(&osd->o_node, &osdc->osds); | 1037 | rb_erase(&osd->o_node, &osdc->osds); |
1012 | list_del_init(&osd->o_osd_lru); | 1038 | list_del_init(&osd->o_osd_lru); |
1013 | ceph_con_close(&osd->o_con); | 1039 | ceph_con_close(&osd->o_con); |
@@ -1029,12 +1055,23 @@ static void remove_all_osds(struct ceph_osd_client *osdc) | |||
1029 | static void __move_osd_to_lru(struct ceph_osd_client *osdc, | 1055 | static void __move_osd_to_lru(struct ceph_osd_client *osdc, |
1030 | struct ceph_osd *osd) | 1056 | struct ceph_osd *osd) |
1031 | { | 1057 | { |
1032 | dout("__move_osd_to_lru %p\n", osd); | 1058 | dout("%s %p\n", __func__, osd); |
1033 | BUG_ON(!list_empty(&osd->o_osd_lru)); | 1059 | BUG_ON(!list_empty(&osd->o_osd_lru)); |
1060 | |||
1034 | list_add_tail(&osd->o_osd_lru, &osdc->osd_lru); | 1061 | list_add_tail(&osd->o_osd_lru, &osdc->osd_lru); |
1035 | osd->lru_ttl = jiffies + osdc->client->options->osd_idle_ttl * HZ; | 1062 | osd->lru_ttl = jiffies + osdc->client->options->osd_idle_ttl * HZ; |
1036 | } | 1063 | } |
1037 | 1064 | ||
1065 | static void maybe_move_osd_to_lru(struct ceph_osd_client *osdc, | ||
1066 | struct ceph_osd *osd) | ||
1067 | { | ||
1068 | dout("%s %p\n", __func__, osd); | ||
1069 | |||
1070 | if (list_empty(&osd->o_requests) && | ||
1071 | list_empty(&osd->o_linger_requests)) | ||
1072 | __move_osd_to_lru(osdc, osd); | ||
1073 | } | ||
1074 | |||
1038 | static void __remove_osd_from_lru(struct ceph_osd *osd) | 1075 | static void __remove_osd_from_lru(struct ceph_osd *osd) |
1039 | { | 1076 | { |
1040 | dout("__remove_osd_from_lru %p\n", osd); | 1077 | dout("__remove_osd_from_lru %p\n", osd); |
@@ -1175,6 +1212,7 @@ static void __unregister_request(struct ceph_osd_client *osdc, | |||
1175 | 1212 | ||
1176 | dout("__unregister_request %p tid %lld\n", req, req->r_tid); | 1213 | dout("__unregister_request %p tid %lld\n", req, req->r_tid); |
1177 | rb_erase(&req->r_node, &osdc->requests); | 1214 | rb_erase(&req->r_node, &osdc->requests); |
1215 | RB_CLEAR_NODE(&req->r_node); | ||
1178 | osdc->num_requests--; | 1216 | osdc->num_requests--; |
1179 | 1217 | ||
1180 | if (req->r_osd) { | 1218 | if (req->r_osd) { |
@@ -1182,12 +1220,8 @@ static void __unregister_request(struct ceph_osd_client *osdc, | |||
1182 | ceph_msg_revoke(req->r_request); | 1220 | ceph_msg_revoke(req->r_request); |
1183 | 1221 | ||
1184 | list_del_init(&req->r_osd_item); | 1222 | list_del_init(&req->r_osd_item); |
1185 | if (list_empty(&req->r_osd->o_requests) && | 1223 | maybe_move_osd_to_lru(osdc, req->r_osd); |
1186 | list_empty(&req->r_osd->o_linger_requests)) { | 1224 | if (list_empty(&req->r_linger_osd_item)) |
1187 | dout("moving osd to %p lru\n", req->r_osd); | ||
1188 | __move_osd_to_lru(osdc, req->r_osd); | ||
1189 | } | ||
1190 | if (list_empty(&req->r_linger_item)) | ||
1191 | req->r_osd = NULL; | 1225 | req->r_osd = NULL; |
1192 | } | 1226 | } |
1193 | 1227 | ||
@@ -1214,45 +1248,39 @@ static void __cancel_request(struct ceph_osd_request *req) | |||
1214 | static void __register_linger_request(struct ceph_osd_client *osdc, | 1248 | static void __register_linger_request(struct ceph_osd_client *osdc, |
1215 | struct ceph_osd_request *req) | 1249 | struct ceph_osd_request *req) |
1216 | { | 1250 | { |
1217 | dout("__register_linger_request %p\n", req); | 1251 | dout("%s %p tid %llu\n", __func__, req, req->r_tid); |
1252 | WARN_ON(!req->r_linger); | ||
1253 | |||
1218 | ceph_osdc_get_request(req); | 1254 | ceph_osdc_get_request(req); |
1219 | list_add_tail(&req->r_linger_item, &osdc->req_linger); | 1255 | list_add_tail(&req->r_linger_item, &osdc->req_linger); |
1220 | if (req->r_osd) | 1256 | if (req->r_osd) |
1221 | list_add_tail(&req->r_linger_osd, | 1257 | list_add_tail(&req->r_linger_osd_item, |
1222 | &req->r_osd->o_linger_requests); | 1258 | &req->r_osd->o_linger_requests); |
1223 | } | 1259 | } |
1224 | 1260 | ||
1225 | static void __unregister_linger_request(struct ceph_osd_client *osdc, | 1261 | static void __unregister_linger_request(struct ceph_osd_client *osdc, |
1226 | struct ceph_osd_request *req) | 1262 | struct ceph_osd_request *req) |
1227 | { | 1263 | { |
1228 | dout("__unregister_linger_request %p\n", req); | 1264 | WARN_ON(!req->r_linger); |
1265 | |||
1266 | if (list_empty(&req->r_linger_item)) { | ||
1267 | dout("%s %p tid %llu not registered\n", __func__, req, | ||
1268 | req->r_tid); | ||
1269 | return; | ||
1270 | } | ||
1271 | |||
1272 | dout("%s %p tid %llu\n", __func__, req, req->r_tid); | ||
1229 | list_del_init(&req->r_linger_item); | 1273 | list_del_init(&req->r_linger_item); |
1230 | if (req->r_osd) { | ||
1231 | list_del_init(&req->r_linger_osd); | ||
1232 | 1274 | ||
1233 | if (list_empty(&req->r_osd->o_requests) && | 1275 | if (req->r_osd) { |
1234 | list_empty(&req->r_osd->o_linger_requests)) { | 1276 | list_del_init(&req->r_linger_osd_item); |
1235 | dout("moving osd to %p lru\n", req->r_osd); | 1277 | maybe_move_osd_to_lru(osdc, req->r_osd); |
1236 | __move_osd_to_lru(osdc, req->r_osd); | ||
1237 | } | ||
1238 | if (list_empty(&req->r_osd_item)) | 1278 | if (list_empty(&req->r_osd_item)) |
1239 | req->r_osd = NULL; | 1279 | req->r_osd = NULL; |
1240 | } | 1280 | } |
1241 | ceph_osdc_put_request(req); | 1281 | ceph_osdc_put_request(req); |
1242 | } | 1282 | } |
1243 | 1283 | ||
1244 | void ceph_osdc_unregister_linger_request(struct ceph_osd_client *osdc, | ||
1245 | struct ceph_osd_request *req) | ||
1246 | { | ||
1247 | mutex_lock(&osdc->request_mutex); | ||
1248 | if (req->r_linger) { | ||
1249 | req->r_linger = 0; | ||
1250 | __unregister_linger_request(osdc, req); | ||
1251 | } | ||
1252 | mutex_unlock(&osdc->request_mutex); | ||
1253 | } | ||
1254 | EXPORT_SYMBOL(ceph_osdc_unregister_linger_request); | ||
1255 | |||
1256 | void ceph_osdc_set_request_linger(struct ceph_osd_client *osdc, | 1284 | void ceph_osdc_set_request_linger(struct ceph_osd_client *osdc, |
1257 | struct ceph_osd_request *req) | 1285 | struct ceph_osd_request *req) |
1258 | { | 1286 | { |
@@ -2430,6 +2458,25 @@ int ceph_osdc_start_request(struct ceph_osd_client *osdc, | |||
2430 | EXPORT_SYMBOL(ceph_osdc_start_request); | 2458 | EXPORT_SYMBOL(ceph_osdc_start_request); |
2431 | 2459 | ||
2432 | /* | 2460 | /* |
2461 | * Unregister a registered request. The request is not completed (i.e. | ||
2462 | * no callbacks or wakeups) - higher layers are supposed to know what | ||
2463 | * they are canceling. | ||
2464 | */ | ||
2465 | void ceph_osdc_cancel_request(struct ceph_osd_request *req) | ||
2466 | { | ||
2467 | struct ceph_osd_client *osdc = req->r_osdc; | ||
2468 | |||
2469 | mutex_lock(&osdc->request_mutex); | ||
2470 | if (req->r_linger) | ||
2471 | __unregister_linger_request(osdc, req); | ||
2472 | __unregister_request(osdc, req); | ||
2473 | mutex_unlock(&osdc->request_mutex); | ||
2474 | |||
2475 | dout("%s %p tid %llu canceled\n", __func__, req, req->r_tid); | ||
2476 | } | ||
2477 | EXPORT_SYMBOL(ceph_osdc_cancel_request); | ||
2478 | |||
2479 | /* | ||
2433 | * wait for a request to complete | 2480 | * wait for a request to complete |
2434 | */ | 2481 | */ |
2435 | int ceph_osdc_wait_request(struct ceph_osd_client *osdc, | 2482 | int ceph_osdc_wait_request(struct ceph_osd_client *osdc, |
@@ -2437,18 +2484,18 @@ int ceph_osdc_wait_request(struct ceph_osd_client *osdc, | |||
2437 | { | 2484 | { |
2438 | int rc; | 2485 | int rc; |
2439 | 2486 | ||
2487 | dout("%s %p tid %llu\n", __func__, req, req->r_tid); | ||
2488 | |||
2440 | rc = wait_for_completion_interruptible(&req->r_completion); | 2489 | rc = wait_for_completion_interruptible(&req->r_completion); |
2441 | if (rc < 0) { | 2490 | if (rc < 0) { |
2442 | mutex_lock(&osdc->request_mutex); | 2491 | dout("%s %p tid %llu interrupted\n", __func__, req, req->r_tid); |
2443 | __cancel_request(req); | 2492 | ceph_osdc_cancel_request(req); |
2444 | __unregister_request(osdc, req); | ||
2445 | mutex_unlock(&osdc->request_mutex); | ||
2446 | complete_request(req); | 2493 | complete_request(req); |
2447 | dout("wait_request tid %llu canceled/timed out\n", req->r_tid); | ||
2448 | return rc; | 2494 | return rc; |
2449 | } | 2495 | } |
2450 | 2496 | ||
2451 | dout("wait_request tid %llu result %d\n", req->r_tid, req->r_result); | 2497 | dout("%s %p tid %llu result %d\n", __func__, req, req->r_tid, |
2498 | req->r_result); | ||
2452 | return req->r_result; | 2499 | return req->r_result; |
2453 | } | 2500 | } |
2454 | EXPORT_SYMBOL(ceph_osdc_wait_request); | 2501 | EXPORT_SYMBOL(ceph_osdc_wait_request); |
diff --git a/net/core/datagram.c b/net/core/datagram.c index 488dd1a825c0..fdbc9a81d4c2 100644 --- a/net/core/datagram.c +++ b/net/core/datagram.c | |||
@@ -775,7 +775,7 @@ __sum16 __skb_checksum_complete(struct sk_buff *skb) | |||
775 | EXPORT_SYMBOL(__skb_checksum_complete); | 775 | EXPORT_SYMBOL(__skb_checksum_complete); |
776 | 776 | ||
777 | /** | 777 | /** |
778 | * skb_copy_and_csum_datagram_iovec - Copy and checkum skb to user iovec. | 778 | * skb_copy_and_csum_datagram_iovec - Copy and checksum skb to user iovec. |
779 | * @skb: skbuff | 779 | * @skb: skbuff |
780 | * @hlen: hardware length | 780 | * @hlen: hardware length |
781 | * @iov: io vector | 781 | * @iov: io vector |
diff --git a/net/core/dev.c b/net/core/dev.c index 367a586d0c8a..cf8a95f48cff 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
@@ -132,6 +132,7 @@ | |||
132 | #include <linux/hashtable.h> | 132 | #include <linux/hashtable.h> |
133 | #include <linux/vmalloc.h> | 133 | #include <linux/vmalloc.h> |
134 | #include <linux/if_macvlan.h> | 134 | #include <linux/if_macvlan.h> |
135 | #include <linux/errqueue.h> | ||
135 | 136 | ||
136 | #include "net-sysfs.h" | 137 | #include "net-sysfs.h" |
137 | 138 | ||
@@ -1085,6 +1086,7 @@ static int dev_get_valid_name(struct net *net, | |||
1085 | */ | 1086 | */ |
1086 | int dev_change_name(struct net_device *dev, const char *newname) | 1087 | int dev_change_name(struct net_device *dev, const char *newname) |
1087 | { | 1088 | { |
1089 | unsigned char old_assign_type; | ||
1088 | char oldname[IFNAMSIZ]; | 1090 | char oldname[IFNAMSIZ]; |
1089 | int err = 0; | 1091 | int err = 0; |
1090 | int ret; | 1092 | int ret; |
@@ -1112,10 +1114,17 @@ int dev_change_name(struct net_device *dev, const char *newname) | |||
1112 | return err; | 1114 | return err; |
1113 | } | 1115 | } |
1114 | 1116 | ||
1117 | if (oldname[0] && !strchr(oldname, '%')) | ||
1118 | netdev_info(dev, "renamed from %s\n", oldname); | ||
1119 | |||
1120 | old_assign_type = dev->name_assign_type; | ||
1121 | dev->name_assign_type = NET_NAME_RENAMED; | ||
1122 | |||
1115 | rollback: | 1123 | rollback: |
1116 | ret = device_rename(&dev->dev, dev->name); | 1124 | ret = device_rename(&dev->dev, dev->name); |
1117 | if (ret) { | 1125 | if (ret) { |
1118 | memcpy(dev->name, oldname, IFNAMSIZ); | 1126 | memcpy(dev->name, oldname, IFNAMSIZ); |
1127 | dev->name_assign_type = old_assign_type; | ||
1119 | write_seqcount_end(&devnet_rename_seq); | 1128 | write_seqcount_end(&devnet_rename_seq); |
1120 | return ret; | 1129 | return ret; |
1121 | } | 1130 | } |
@@ -1144,6 +1153,8 @@ rollback: | |||
1144 | write_seqcount_begin(&devnet_rename_seq); | 1153 | write_seqcount_begin(&devnet_rename_seq); |
1145 | memcpy(dev->name, oldname, IFNAMSIZ); | 1154 | memcpy(dev->name, oldname, IFNAMSIZ); |
1146 | memcpy(oldname, newname, IFNAMSIZ); | 1155 | memcpy(oldname, newname, IFNAMSIZ); |
1156 | dev->name_assign_type = old_assign_type; | ||
1157 | old_assign_type = NET_NAME_RENAMED; | ||
1147 | goto rollback; | 1158 | goto rollback; |
1148 | } else { | 1159 | } else { |
1149 | pr_err("%s: name change rollback failed: %d\n", | 1160 | pr_err("%s: name change rollback failed: %d\n", |
@@ -2316,7 +2327,7 @@ __be16 skb_network_protocol(struct sk_buff *skb, int *depth) | |||
2316 | */ | 2327 | */ |
2317 | if (type == htons(ETH_P_8021Q) || type == htons(ETH_P_8021AD)) { | 2328 | if (type == htons(ETH_P_8021Q) || type == htons(ETH_P_8021AD)) { |
2318 | if (vlan_depth) { | 2329 | if (vlan_depth) { |
2319 | if (unlikely(WARN_ON(vlan_depth < VLAN_HLEN))) | 2330 | if (WARN_ON(vlan_depth < VLAN_HLEN)) |
2320 | return 0; | 2331 | return 0; |
2321 | vlan_depth -= VLAN_HLEN; | 2332 | vlan_depth -= VLAN_HLEN; |
2322 | } else { | 2333 | } else { |
@@ -2414,8 +2425,8 @@ struct sk_buff *__skb_gso_segment(struct sk_buff *skb, | |||
2414 | 2425 | ||
2415 | skb_warn_bad_offload(skb); | 2426 | skb_warn_bad_offload(skb); |
2416 | 2427 | ||
2417 | if (skb_header_cloned(skb) && | 2428 | err = skb_cow_head(skb, 0); |
2418 | (err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC))) | 2429 | if (err < 0) |
2419 | return ERR_PTR(err); | 2430 | return ERR_PTR(err); |
2420 | } | 2431 | } |
2421 | 2432 | ||
@@ -2576,13 +2587,19 @@ netdev_features_t netif_skb_features(struct sk_buff *skb) | |||
2576 | return harmonize_features(skb, features); | 2587 | return harmonize_features(skb, features); |
2577 | } | 2588 | } |
2578 | 2589 | ||
2579 | features &= (skb->dev->vlan_features | NETIF_F_HW_VLAN_CTAG_TX | | 2590 | features = netdev_intersect_features(features, |
2580 | NETIF_F_HW_VLAN_STAG_TX); | 2591 | skb->dev->vlan_features | |
2592 | NETIF_F_HW_VLAN_CTAG_TX | | ||
2593 | NETIF_F_HW_VLAN_STAG_TX); | ||
2581 | 2594 | ||
2582 | if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD)) | 2595 | if (protocol == htons(ETH_P_8021Q) || protocol == htons(ETH_P_8021AD)) |
2583 | features &= NETIF_F_SG | NETIF_F_HIGHDMA | NETIF_F_FRAGLIST | | 2596 | features = netdev_intersect_features(features, |
2584 | NETIF_F_GEN_CSUM | NETIF_F_HW_VLAN_CTAG_TX | | 2597 | NETIF_F_SG | |
2585 | NETIF_F_HW_VLAN_STAG_TX; | 2598 | NETIF_F_HIGHDMA | |
2599 | NETIF_F_FRAGLIST | | ||
2600 | NETIF_F_GEN_CSUM | | ||
2601 | NETIF_F_HW_VLAN_CTAG_TX | | ||
2602 | NETIF_F_HW_VLAN_STAG_TX); | ||
2586 | 2603 | ||
2587 | return harmonize_features(skb, features); | 2604 | return harmonize_features(skb, features); |
2588 | } | 2605 | } |
@@ -2745,8 +2762,8 @@ static inline int __dev_xmit_skb(struct sk_buff *skb, struct Qdisc *q, | |||
2745 | /* | 2762 | /* |
2746 | * Heuristic to force contended enqueues to serialize on a | 2763 | * Heuristic to force contended enqueues to serialize on a |
2747 | * separate lock before trying to get qdisc main lock. | 2764 | * separate lock before trying to get qdisc main lock. |
2748 | * This permits __QDISC_STATE_RUNNING owner to get the lock more often | 2765 | * This permits __QDISC___STATE_RUNNING owner to get the lock more |
2749 | * and dequeue packets faster. | 2766 | * often and dequeue packets faster. |
2750 | */ | 2767 | */ |
2751 | contended = qdisc_is_running(q); | 2768 | contended = qdisc_is_running(q); |
2752 | if (unlikely(contended)) | 2769 | if (unlikely(contended)) |
@@ -2866,6 +2883,9 @@ static int __dev_queue_xmit(struct sk_buff *skb, void *accel_priv) | |||
2866 | 2883 | ||
2867 | skb_reset_mac_header(skb); | 2884 | skb_reset_mac_header(skb); |
2868 | 2885 | ||
2886 | if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_SCHED_TSTAMP)) | ||
2887 | __skb_tstamp_tx(skb, NULL, skb->sk, SCM_TSTAMP_SCHED); | ||
2888 | |||
2869 | /* Disable soft irqs for various locks below. Also | 2889 | /* Disable soft irqs for various locks below. Also |
2870 | * stops preemption for RCU. | 2890 | * stops preemption for RCU. |
2871 | */ | 2891 | */ |
@@ -3588,7 +3608,7 @@ another_round: | |||
3588 | 3608 | ||
3589 | if (skb->protocol == cpu_to_be16(ETH_P_8021Q) || | 3609 | if (skb->protocol == cpu_to_be16(ETH_P_8021Q) || |
3590 | skb->protocol == cpu_to_be16(ETH_P_8021AD)) { | 3610 | skb->protocol == cpu_to_be16(ETH_P_8021AD)) { |
3591 | skb = vlan_untag(skb); | 3611 | skb = skb_vlan_untag(skb); |
3592 | if (unlikely(!skb)) | 3612 | if (unlikely(!skb)) |
3593 | goto unlock; | 3613 | goto unlock; |
3594 | } | 3614 | } |
@@ -4789,9 +4809,14 @@ static void netdev_adjacent_sysfs_del(struct net_device *dev, | |||
4789 | sysfs_remove_link(&(dev->dev.kobj), linkname); | 4809 | sysfs_remove_link(&(dev->dev.kobj), linkname); |
4790 | } | 4810 | } |
4791 | 4811 | ||
4792 | #define netdev_adjacent_is_neigh_list(dev, dev_list) \ | 4812 | static inline bool netdev_adjacent_is_neigh_list(struct net_device *dev, |
4793 | (dev_list == &dev->adj_list.upper || \ | 4813 | struct net_device *adj_dev, |
4794 | dev_list == &dev->adj_list.lower) | 4814 | struct list_head *dev_list) |
4815 | { | ||
4816 | return (dev_list == &dev->adj_list.upper || | ||
4817 | dev_list == &dev->adj_list.lower) && | ||
4818 | net_eq(dev_net(dev), dev_net(adj_dev)); | ||
4819 | } | ||
4795 | 4820 | ||
4796 | static int __netdev_adjacent_dev_insert(struct net_device *dev, | 4821 | static int __netdev_adjacent_dev_insert(struct net_device *dev, |
4797 | struct net_device *adj_dev, | 4822 | struct net_device *adj_dev, |
@@ -4821,7 +4846,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev, | |||
4821 | pr_debug("dev_hold for %s, because of link added from %s to %s\n", | 4846 | pr_debug("dev_hold for %s, because of link added from %s to %s\n", |
4822 | adj_dev->name, dev->name, adj_dev->name); | 4847 | adj_dev->name, dev->name, adj_dev->name); |
4823 | 4848 | ||
4824 | if (netdev_adjacent_is_neigh_list(dev, dev_list)) { | 4849 | if (netdev_adjacent_is_neigh_list(dev, adj_dev, dev_list)) { |
4825 | ret = netdev_adjacent_sysfs_add(dev, adj_dev, dev_list); | 4850 | ret = netdev_adjacent_sysfs_add(dev, adj_dev, dev_list); |
4826 | if (ret) | 4851 | if (ret) |
4827 | goto free_adj; | 4852 | goto free_adj; |
@@ -4842,7 +4867,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev, | |||
4842 | return 0; | 4867 | return 0; |
4843 | 4868 | ||
4844 | remove_symlinks: | 4869 | remove_symlinks: |
4845 | if (netdev_adjacent_is_neigh_list(dev, dev_list)) | 4870 | if (netdev_adjacent_is_neigh_list(dev, adj_dev, dev_list)) |
4846 | netdev_adjacent_sysfs_del(dev, adj_dev->name, dev_list); | 4871 | netdev_adjacent_sysfs_del(dev, adj_dev->name, dev_list); |
4847 | free_adj: | 4872 | free_adj: |
4848 | kfree(adj); | 4873 | kfree(adj); |
@@ -4875,7 +4900,7 @@ static void __netdev_adjacent_dev_remove(struct net_device *dev, | |||
4875 | if (adj->master) | 4900 | if (adj->master) |
4876 | sysfs_remove_link(&(dev->dev.kobj), "master"); | 4901 | sysfs_remove_link(&(dev->dev.kobj), "master"); |
4877 | 4902 | ||
4878 | if (netdev_adjacent_is_neigh_list(dev, dev_list)) | 4903 | if (netdev_adjacent_is_neigh_list(dev, adj_dev, dev_list)) |
4879 | netdev_adjacent_sysfs_del(dev, adj_dev->name, dev_list); | 4904 | netdev_adjacent_sysfs_del(dev, adj_dev->name, dev_list); |
4880 | 4905 | ||
4881 | list_del_rcu(&adj->list); | 4906 | list_del_rcu(&adj->list); |
@@ -5145,11 +5170,65 @@ void netdev_upper_dev_unlink(struct net_device *dev, | |||
5145 | } | 5170 | } |
5146 | EXPORT_SYMBOL(netdev_upper_dev_unlink); | 5171 | EXPORT_SYMBOL(netdev_upper_dev_unlink); |
5147 | 5172 | ||
5173 | void netdev_adjacent_add_links(struct net_device *dev) | ||
5174 | { | ||
5175 | struct netdev_adjacent *iter; | ||
5176 | |||
5177 | struct net *net = dev_net(dev); | ||
5178 | |||
5179 | list_for_each_entry(iter, &dev->adj_list.upper, list) { | ||
5180 | if (!net_eq(net,dev_net(iter->dev))) | ||
5181 | continue; | ||
5182 | netdev_adjacent_sysfs_add(iter->dev, dev, | ||
5183 | &iter->dev->adj_list.lower); | ||
5184 | netdev_adjacent_sysfs_add(dev, iter->dev, | ||
5185 | &dev->adj_list.upper); | ||
5186 | } | ||
5187 | |||
5188 | list_for_each_entry(iter, &dev->adj_list.lower, list) { | ||
5189 | if (!net_eq(net,dev_net(iter->dev))) | ||
5190 | continue; | ||
5191 | netdev_adjacent_sysfs_add(iter->dev, dev, | ||
5192 | &iter->dev->adj_list.upper); | ||
5193 | netdev_adjacent_sysfs_add(dev, iter->dev, | ||
5194 | &dev->adj_list.lower); | ||
5195 | } | ||
5196 | } | ||
5197 | |||
5198 | void netdev_adjacent_del_links(struct net_device *dev) | ||
5199 | { | ||
5200 | struct netdev_adjacent *iter; | ||
5201 | |||
5202 | struct net *net = dev_net(dev); | ||
5203 | |||
5204 | list_for_each_entry(iter, &dev->adj_list.upper, list) { | ||
5205 | if (!net_eq(net,dev_net(iter->dev))) | ||
5206 | continue; | ||
5207 | netdev_adjacent_sysfs_del(iter->dev, dev->name, | ||
5208 | &iter->dev->adj_list.lower); | ||
5209 | netdev_adjacent_sysfs_del(dev, iter->dev->name, | ||
5210 | &dev->adj_list.upper); | ||
5211 | } | ||
5212 | |||
5213 | list_for_each_entry(iter, &dev->adj_list.lower, list) { | ||
5214 | if (!net_eq(net,dev_net(iter->dev))) | ||
5215 | continue; | ||
5216 | netdev_adjacent_sysfs_del(iter->dev, dev->name, | ||
5217 | &iter->dev->adj_list.upper); | ||
5218 | netdev_adjacent_sysfs_del(dev, iter->dev->name, | ||
5219 | &dev->adj_list.lower); | ||
5220 | } | ||
5221 | } | ||
5222 | |||
5148 | void netdev_adjacent_rename_links(struct net_device *dev, char *oldname) | 5223 | void netdev_adjacent_rename_links(struct net_device *dev, char *oldname) |
5149 | { | 5224 | { |
5150 | struct netdev_adjacent *iter; | 5225 | struct netdev_adjacent *iter; |
5151 | 5226 | ||
5227 | struct net *net = dev_net(dev); | ||
5228 | |||
5152 | list_for_each_entry(iter, &dev->adj_list.upper, list) { | 5229 | list_for_each_entry(iter, &dev->adj_list.upper, list) { |
5230 | if (!net_eq(net,dev_net(iter->dev))) | ||
5231 | continue; | ||
5153 | netdev_adjacent_sysfs_del(iter->dev, oldname, | 5232 | netdev_adjacent_sysfs_del(iter->dev, oldname, |
5154 | &iter->dev->adj_list.lower); | 5233 | &iter->dev->adj_list.lower); |
5155 | netdev_adjacent_sysfs_add(iter->dev, dev, | 5234 | netdev_adjacent_sysfs_add(iter->dev, dev, |
@@ -5157,6 +5236,8 @@ void netdev_adjacent_rename_links(struct net_device *dev, char *oldname) | |||
5157 | } | 5236 | } |
5158 | 5237 | ||
5159 | list_for_each_entry(iter, &dev->adj_list.lower, list) { | 5238 | list_for_each_entry(iter, &dev->adj_list.lower, list) { |
5239 | if (!net_eq(net,dev_net(iter->dev))) | ||
5240 | continue; | ||
5160 | netdev_adjacent_sysfs_del(iter->dev, oldname, | 5241 | netdev_adjacent_sysfs_del(iter->dev, oldname, |
5161 | &iter->dev->adj_list.upper); | 5242 | &iter->dev->adj_list.upper); |
5162 | netdev_adjacent_sysfs_add(iter->dev, dev, | 5243 | netdev_adjacent_sysfs_add(iter->dev, dev, |
@@ -5440,13 +5521,9 @@ int __dev_change_flags(struct net_device *dev, unsigned int flags) | |||
5440 | */ | 5521 | */ |
5441 | 5522 | ||
5442 | ret = 0; | 5523 | ret = 0; |
5443 | if ((old_flags ^ flags) & IFF_UP) { /* Bit is different ? */ | 5524 | if ((old_flags ^ flags) & IFF_UP) |
5444 | ret = ((old_flags & IFF_UP) ? __dev_close : __dev_open)(dev); | 5525 | ret = ((old_flags & IFF_UP) ? __dev_close : __dev_open)(dev); |
5445 | 5526 | ||
5446 | if (!ret) | ||
5447 | dev_set_rx_mode(dev); | ||
5448 | } | ||
5449 | |||
5450 | if ((flags ^ dev->gflags) & IFF_PROMISC) { | 5527 | if ((flags ^ dev->gflags) & IFF_PROMISC) { |
5451 | int inc = (flags & IFF_PROMISC) ? 1 : -1; | 5528 | int inc = (flags & IFF_PROMISC) ? 1 : -1; |
5452 | unsigned int old_flags = dev->flags; | 5529 | unsigned int old_flags = dev->flags; |
@@ -6446,17 +6523,19 @@ void netdev_freemem(struct net_device *dev) | |||
6446 | 6523 | ||
6447 | /** | 6524 | /** |
6448 | * alloc_netdev_mqs - allocate network device | 6525 | * alloc_netdev_mqs - allocate network device |
6449 | * @sizeof_priv: size of private data to allocate space for | 6526 | * @sizeof_priv: size of private data to allocate space for |
6450 | * @name: device name format string | 6527 | * @name: device name format string |
6451 | * @setup: callback to initialize device | 6528 | * @name_assign_type: origin of device name |
6452 | * @txqs: the number of TX subqueues to allocate | 6529 | * @setup: callback to initialize device |
6453 | * @rxqs: the number of RX subqueues to allocate | 6530 | * @txqs: the number of TX subqueues to allocate |
6531 | * @rxqs: the number of RX subqueues to allocate | ||
6454 | * | 6532 | * |
6455 | * Allocates a struct net_device with private data area for driver use | 6533 | * Allocates a struct net_device with private data area for driver use |
6456 | * and performs basic initialization. Also allocates subqueue structs | 6534 | * and performs basic initialization. Also allocates subqueue structs |
6457 | * for each queue on the device. | 6535 | * for each queue on the device. |
6458 | */ | 6536 | */ |
6459 | struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, | 6537 | struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, |
6538 | unsigned char name_assign_type, | ||
6460 | void (*setup)(struct net_device *), | 6539 | void (*setup)(struct net_device *), |
6461 | unsigned int txqs, unsigned int rxqs) | 6540 | unsigned int txqs, unsigned int rxqs) |
6462 | { | 6541 | { |
@@ -6535,6 +6614,7 @@ struct net_device *alloc_netdev_mqs(int sizeof_priv, const char *name, | |||
6535 | #endif | 6614 | #endif |
6536 | 6615 | ||
6537 | strcpy(dev->name, name); | 6616 | strcpy(dev->name, name); |
6617 | dev->name_assign_type = name_assign_type; | ||
6538 | dev->group = INIT_NETDEV_GROUP; | 6618 | dev->group = INIT_NETDEV_GROUP; |
6539 | if (!dev->ethtool_ops) | 6619 | if (!dev->ethtool_ops) |
6540 | dev->ethtool_ops = &default_ethtool_ops; | 6620 | dev->ethtool_ops = &default_ethtool_ops; |
@@ -6760,6 +6840,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char | |||
6760 | 6840 | ||
6761 | /* Send a netdev-removed uevent to the old namespace */ | 6841 | /* Send a netdev-removed uevent to the old namespace */ |
6762 | kobject_uevent(&dev->dev.kobj, KOBJ_REMOVE); | 6842 | kobject_uevent(&dev->dev.kobj, KOBJ_REMOVE); |
6843 | netdev_adjacent_del_links(dev); | ||
6763 | 6844 | ||
6764 | /* Actually switch the network namespace */ | 6845 | /* Actually switch the network namespace */ |
6765 | dev_net_set(dev, net); | 6846 | dev_net_set(dev, net); |
@@ -6774,6 +6855,7 @@ int dev_change_net_namespace(struct net_device *dev, struct net *net, const char | |||
6774 | 6855 | ||
6775 | /* Send a netdev-add uevent to the new namespace */ | 6856 | /* Send a netdev-add uevent to the new namespace */ |
6776 | kobject_uevent(&dev->dev.kobj, KOBJ_ADD); | 6857 | kobject_uevent(&dev->dev.kobj, KOBJ_ADD); |
6858 | netdev_adjacent_add_links(dev); | ||
6777 | 6859 | ||
6778 | /* Fixup kobjects */ | 6860 | /* Fixup kobjects */ |
6779 | err = device_rename(&dev->dev, dev->name); | 6861 | err = device_rename(&dev->dev, dev->name); |
@@ -6946,12 +7028,14 @@ static int __netdev_printk(const char *level, const struct net_device *dev, | |||
6946 | if (dev && dev->dev.parent) { | 7028 | if (dev && dev->dev.parent) { |
6947 | r = dev_printk_emit(level[1] - '0', | 7029 | r = dev_printk_emit(level[1] - '0', |
6948 | dev->dev.parent, | 7030 | dev->dev.parent, |
6949 | "%s %s %s: %pV", | 7031 | "%s %s %s%s: %pV", |
6950 | dev_driver_string(dev->dev.parent), | 7032 | dev_driver_string(dev->dev.parent), |
6951 | dev_name(dev->dev.parent), | 7033 | dev_name(dev->dev.parent), |
6952 | netdev_name(dev), vaf); | 7034 | netdev_name(dev), netdev_reg_state(dev), |
7035 | vaf); | ||
6953 | } else if (dev) { | 7036 | } else if (dev) { |
6954 | r = printk("%s%s: %pV", level, netdev_name(dev), vaf); | 7037 | r = printk("%s%s%s: %pV", level, netdev_name(dev), |
7038 | netdev_reg_state(dev), vaf); | ||
6955 | } else { | 7039 | } else { |
6956 | r = printk("%s(NULL net_device): %pV", level, vaf); | 7040 | r = printk("%s(NULL net_device): %pV", level, vaf); |
6957 | } | 7041 | } |
@@ -7103,7 +7187,7 @@ static void __net_exit default_device_exit_batch(struct list_head *net_list) | |||
7103 | rtnl_lock_unregistering(net_list); | 7187 | rtnl_lock_unregistering(net_list); |
7104 | list_for_each_entry(net, net_list, exit_list) { | 7188 | list_for_each_entry(net, net_list, exit_list) { |
7105 | for_each_netdev_reverse(net, dev) { | 7189 | for_each_netdev_reverse(net, dev) { |
7106 | if (dev->rtnl_link_ops) | 7190 | if (dev->rtnl_link_ops && dev->rtnl_link_ops->dellink) |
7107 | dev->rtnl_link_ops->dellink(dev, &dev_kill_list); | 7191 | dev->rtnl_link_ops->dellink(dev, &dev_kill_list); |
7108 | else | 7192 | else |
7109 | unregister_netdevice_queue(dev, &dev_kill_list); | 7193 | unregister_netdevice_queue(dev, &dev_kill_list); |
diff --git a/net/core/drop_monitor.c b/net/core/drop_monitor.c index e70301eb7a4a..50f9a9db5792 100644 --- a/net/core/drop_monitor.c +++ b/net/core/drop_monitor.c | |||
@@ -289,10 +289,8 @@ static int net_dm_cmd_trace(struct sk_buff *skb, | |||
289 | switch (info->genlhdr->cmd) { | 289 | switch (info->genlhdr->cmd) { |
290 | case NET_DM_CMD_START: | 290 | case NET_DM_CMD_START: |
291 | return set_all_monitor_traces(TRACE_ON); | 291 | return set_all_monitor_traces(TRACE_ON); |
292 | break; | ||
293 | case NET_DM_CMD_STOP: | 292 | case NET_DM_CMD_STOP: |
294 | return set_all_monitor_traces(TRACE_OFF); | 293 | return set_all_monitor_traces(TRACE_OFF); |
295 | break; | ||
296 | } | 294 | } |
297 | 295 | ||
298 | return -ENOTSUPP; | 296 | return -ENOTSUPP; |
diff --git a/net/core/filter.c b/net/core/filter.c index 1dbf6462f766..d814b8a89d0f 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
@@ -18,7 +18,7 @@ | |||
18 | * 2 of the License, or (at your option) any later version. | 18 | * 2 of the License, or (at your option) any later version. |
19 | * | 19 | * |
20 | * Andi Kleen - Fix a few bad bugs and races. | 20 | * Andi Kleen - Fix a few bad bugs and races. |
21 | * Kris Katterjohn - Added many additional checks in sk_chk_filter() | 21 | * Kris Katterjohn - Added many additional checks in bpf_check_classic() |
22 | */ | 22 | */ |
23 | 23 | ||
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
@@ -45,54 +45,6 @@ | |||
45 | #include <linux/seccomp.h> | 45 | #include <linux/seccomp.h> |
46 | #include <linux/if_vlan.h> | 46 | #include <linux/if_vlan.h> |
47 | 47 | ||
48 | /* Registers */ | ||
49 | #define BPF_R0 regs[BPF_REG_0] | ||
50 | #define BPF_R1 regs[BPF_REG_1] | ||
51 | #define BPF_R2 regs[BPF_REG_2] | ||
52 | #define BPF_R3 regs[BPF_REG_3] | ||
53 | #define BPF_R4 regs[BPF_REG_4] | ||
54 | #define BPF_R5 regs[BPF_REG_5] | ||
55 | #define BPF_R6 regs[BPF_REG_6] | ||
56 | #define BPF_R7 regs[BPF_REG_7] | ||
57 | #define BPF_R8 regs[BPF_REG_8] | ||
58 | #define BPF_R9 regs[BPF_REG_9] | ||
59 | #define BPF_R10 regs[BPF_REG_10] | ||
60 | |||
61 | /* Named registers */ | ||
62 | #define DST regs[insn->dst_reg] | ||
63 | #define SRC regs[insn->src_reg] | ||
64 | #define FP regs[BPF_REG_FP] | ||
65 | #define ARG1 regs[BPF_REG_ARG1] | ||
66 | #define CTX regs[BPF_REG_CTX] | ||
67 | #define IMM insn->imm | ||
68 | |||
69 | /* No hurry in this branch | ||
70 | * | ||
71 | * Exported for the bpf jit load helper. | ||
72 | */ | ||
73 | void *bpf_internal_load_pointer_neg_helper(const struct sk_buff *skb, int k, unsigned int size) | ||
74 | { | ||
75 | u8 *ptr = NULL; | ||
76 | |||
77 | if (k >= SKF_NET_OFF) | ||
78 | ptr = skb_network_header(skb) + k - SKF_NET_OFF; | ||
79 | else if (k >= SKF_LL_OFF) | ||
80 | ptr = skb_mac_header(skb) + k - SKF_LL_OFF; | ||
81 | if (ptr >= skb->head && ptr + size <= skb_tail_pointer(skb)) | ||
82 | return ptr; | ||
83 | |||
84 | return NULL; | ||
85 | } | ||
86 | |||
87 | static inline void *load_pointer(const struct sk_buff *skb, int k, | ||
88 | unsigned int size, void *buffer) | ||
89 | { | ||
90 | if (k >= 0) | ||
91 | return skb_header_pointer(skb, k, size, buffer); | ||
92 | |||
93 | return bpf_internal_load_pointer_neg_helper(skb, k, size); | ||
94 | } | ||
95 | |||
96 | /** | 48 | /** |
97 | * sk_filter - run a packet through a socket filter | 49 | * sk_filter - run a packet through a socket filter |
98 | * @sk: sock associated with &sk_buff | 50 | * @sk: sock associated with &sk_buff |
@@ -135,451 +87,6 @@ int sk_filter(struct sock *sk, struct sk_buff *skb) | |||
135 | } | 87 | } |
136 | EXPORT_SYMBOL(sk_filter); | 88 | EXPORT_SYMBOL(sk_filter); |
137 | 89 | ||
138 | /* Base function for offset calculation. Needs to go into .text section, | ||
139 | * therefore keeping it non-static as well; will also be used by JITs | ||
140 | * anyway later on, so do not let the compiler omit it. | ||
141 | */ | ||
142 | noinline u64 __bpf_call_base(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5) | ||
143 | { | ||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | /** | ||
148 | * __sk_run_filter - run a filter on a given context | ||
149 | * @ctx: buffer to run the filter on | ||
150 | * @insn: filter to apply | ||
151 | * | ||
152 | * Decode and apply filter instructions to the skb->data. Return length to | ||
153 | * keep, 0 for none. @ctx is the data we are operating on, @insn is the | ||
154 | * array of filter instructions. | ||
155 | */ | ||
156 | static unsigned int __sk_run_filter(void *ctx, const struct sock_filter_int *insn) | ||
157 | { | ||
158 | u64 stack[MAX_BPF_STACK / sizeof(u64)]; | ||
159 | u64 regs[MAX_BPF_REG], tmp; | ||
160 | static const void *jumptable[256] = { | ||
161 | [0 ... 255] = &&default_label, | ||
162 | /* Now overwrite non-defaults ... */ | ||
163 | /* 32 bit ALU operations */ | ||
164 | [BPF_ALU | BPF_ADD | BPF_X] = &&ALU_ADD_X, | ||
165 | [BPF_ALU | BPF_ADD | BPF_K] = &&ALU_ADD_K, | ||
166 | [BPF_ALU | BPF_SUB | BPF_X] = &&ALU_SUB_X, | ||
167 | [BPF_ALU | BPF_SUB | BPF_K] = &&ALU_SUB_K, | ||
168 | [BPF_ALU | BPF_AND | BPF_X] = &&ALU_AND_X, | ||
169 | [BPF_ALU | BPF_AND | BPF_K] = &&ALU_AND_K, | ||
170 | [BPF_ALU | BPF_OR | BPF_X] = &&ALU_OR_X, | ||
171 | [BPF_ALU | BPF_OR | BPF_K] = &&ALU_OR_K, | ||
172 | [BPF_ALU | BPF_LSH | BPF_X] = &&ALU_LSH_X, | ||
173 | [BPF_ALU | BPF_LSH | BPF_K] = &&ALU_LSH_K, | ||
174 | [BPF_ALU | BPF_RSH | BPF_X] = &&ALU_RSH_X, | ||
175 | [BPF_ALU | BPF_RSH | BPF_K] = &&ALU_RSH_K, | ||
176 | [BPF_ALU | BPF_XOR | BPF_X] = &&ALU_XOR_X, | ||
177 | [BPF_ALU | BPF_XOR | BPF_K] = &&ALU_XOR_K, | ||
178 | [BPF_ALU | BPF_MUL | BPF_X] = &&ALU_MUL_X, | ||
179 | [BPF_ALU | BPF_MUL | BPF_K] = &&ALU_MUL_K, | ||
180 | [BPF_ALU | BPF_MOV | BPF_X] = &&ALU_MOV_X, | ||
181 | [BPF_ALU | BPF_MOV | BPF_K] = &&ALU_MOV_K, | ||
182 | [BPF_ALU | BPF_DIV | BPF_X] = &&ALU_DIV_X, | ||
183 | [BPF_ALU | BPF_DIV | BPF_K] = &&ALU_DIV_K, | ||
184 | [BPF_ALU | BPF_MOD | BPF_X] = &&ALU_MOD_X, | ||
185 | [BPF_ALU | BPF_MOD | BPF_K] = &&ALU_MOD_K, | ||
186 | [BPF_ALU | BPF_NEG] = &&ALU_NEG, | ||
187 | [BPF_ALU | BPF_END | BPF_TO_BE] = &&ALU_END_TO_BE, | ||
188 | [BPF_ALU | BPF_END | BPF_TO_LE] = &&ALU_END_TO_LE, | ||
189 | /* 64 bit ALU operations */ | ||
190 | [BPF_ALU64 | BPF_ADD | BPF_X] = &&ALU64_ADD_X, | ||
191 | [BPF_ALU64 | BPF_ADD | BPF_K] = &&ALU64_ADD_K, | ||
192 | [BPF_ALU64 | BPF_SUB | BPF_X] = &&ALU64_SUB_X, | ||
193 | [BPF_ALU64 | BPF_SUB | BPF_K] = &&ALU64_SUB_K, | ||
194 | [BPF_ALU64 | BPF_AND | BPF_X] = &&ALU64_AND_X, | ||
195 | [BPF_ALU64 | BPF_AND | BPF_K] = &&ALU64_AND_K, | ||
196 | [BPF_ALU64 | BPF_OR | BPF_X] = &&ALU64_OR_X, | ||
197 | [BPF_ALU64 | BPF_OR | BPF_K] = &&ALU64_OR_K, | ||
198 | [BPF_ALU64 | BPF_LSH | BPF_X] = &&ALU64_LSH_X, | ||
199 | [BPF_ALU64 | BPF_LSH | BPF_K] = &&ALU64_LSH_K, | ||
200 | [BPF_ALU64 | BPF_RSH | BPF_X] = &&ALU64_RSH_X, | ||
201 | [BPF_ALU64 | BPF_RSH | BPF_K] = &&ALU64_RSH_K, | ||
202 | [BPF_ALU64 | BPF_XOR | BPF_X] = &&ALU64_XOR_X, | ||
203 | [BPF_ALU64 | BPF_XOR | BPF_K] = &&ALU64_XOR_K, | ||
204 | [BPF_ALU64 | BPF_MUL | BPF_X] = &&ALU64_MUL_X, | ||
205 | [BPF_ALU64 | BPF_MUL | BPF_K] = &&ALU64_MUL_K, | ||
206 | [BPF_ALU64 | BPF_MOV | BPF_X] = &&ALU64_MOV_X, | ||
207 | [BPF_ALU64 | BPF_MOV | BPF_K] = &&ALU64_MOV_K, | ||
208 | [BPF_ALU64 | BPF_ARSH | BPF_X] = &&ALU64_ARSH_X, | ||
209 | [BPF_ALU64 | BPF_ARSH | BPF_K] = &&ALU64_ARSH_K, | ||
210 | [BPF_ALU64 | BPF_DIV | BPF_X] = &&ALU64_DIV_X, | ||
211 | [BPF_ALU64 | BPF_DIV | BPF_K] = &&ALU64_DIV_K, | ||
212 | [BPF_ALU64 | BPF_MOD | BPF_X] = &&ALU64_MOD_X, | ||
213 | [BPF_ALU64 | BPF_MOD | BPF_K] = &&ALU64_MOD_K, | ||
214 | [BPF_ALU64 | BPF_NEG] = &&ALU64_NEG, | ||
215 | /* Call instruction */ | ||
216 | [BPF_JMP | BPF_CALL] = &&JMP_CALL, | ||
217 | /* Jumps */ | ||
218 | [BPF_JMP | BPF_JA] = &&JMP_JA, | ||
219 | [BPF_JMP | BPF_JEQ | BPF_X] = &&JMP_JEQ_X, | ||
220 | [BPF_JMP | BPF_JEQ | BPF_K] = &&JMP_JEQ_K, | ||
221 | [BPF_JMP | BPF_JNE | BPF_X] = &&JMP_JNE_X, | ||
222 | [BPF_JMP | BPF_JNE | BPF_K] = &&JMP_JNE_K, | ||
223 | [BPF_JMP | BPF_JGT | BPF_X] = &&JMP_JGT_X, | ||
224 | [BPF_JMP | BPF_JGT | BPF_K] = &&JMP_JGT_K, | ||
225 | [BPF_JMP | BPF_JGE | BPF_X] = &&JMP_JGE_X, | ||
226 | [BPF_JMP | BPF_JGE | BPF_K] = &&JMP_JGE_K, | ||
227 | [BPF_JMP | BPF_JSGT | BPF_X] = &&JMP_JSGT_X, | ||
228 | [BPF_JMP | BPF_JSGT | BPF_K] = &&JMP_JSGT_K, | ||
229 | [BPF_JMP | BPF_JSGE | BPF_X] = &&JMP_JSGE_X, | ||
230 | [BPF_JMP | BPF_JSGE | BPF_K] = &&JMP_JSGE_K, | ||
231 | [BPF_JMP | BPF_JSET | BPF_X] = &&JMP_JSET_X, | ||
232 | [BPF_JMP | BPF_JSET | BPF_K] = &&JMP_JSET_K, | ||
233 | /* Program return */ | ||
234 | [BPF_JMP | BPF_EXIT] = &&JMP_EXIT, | ||
235 | /* Store instructions */ | ||
236 | [BPF_STX | BPF_MEM | BPF_B] = &&STX_MEM_B, | ||
237 | [BPF_STX | BPF_MEM | BPF_H] = &&STX_MEM_H, | ||
238 | [BPF_STX | BPF_MEM | BPF_W] = &&STX_MEM_W, | ||
239 | [BPF_STX | BPF_MEM | BPF_DW] = &&STX_MEM_DW, | ||
240 | [BPF_STX | BPF_XADD | BPF_W] = &&STX_XADD_W, | ||
241 | [BPF_STX | BPF_XADD | BPF_DW] = &&STX_XADD_DW, | ||
242 | [BPF_ST | BPF_MEM | BPF_B] = &&ST_MEM_B, | ||
243 | [BPF_ST | BPF_MEM | BPF_H] = &&ST_MEM_H, | ||
244 | [BPF_ST | BPF_MEM | BPF_W] = &&ST_MEM_W, | ||
245 | [BPF_ST | BPF_MEM | BPF_DW] = &&ST_MEM_DW, | ||
246 | /* Load instructions */ | ||
247 | [BPF_LDX | BPF_MEM | BPF_B] = &&LDX_MEM_B, | ||
248 | [BPF_LDX | BPF_MEM | BPF_H] = &&LDX_MEM_H, | ||
249 | [BPF_LDX | BPF_MEM | BPF_W] = &&LDX_MEM_W, | ||
250 | [BPF_LDX | BPF_MEM | BPF_DW] = &&LDX_MEM_DW, | ||
251 | [BPF_LD | BPF_ABS | BPF_W] = &&LD_ABS_W, | ||
252 | [BPF_LD | BPF_ABS | BPF_H] = &&LD_ABS_H, | ||
253 | [BPF_LD | BPF_ABS | BPF_B] = &&LD_ABS_B, | ||
254 | [BPF_LD | BPF_IND | BPF_W] = &&LD_IND_W, | ||
255 | [BPF_LD | BPF_IND | BPF_H] = &&LD_IND_H, | ||
256 | [BPF_LD | BPF_IND | BPF_B] = &&LD_IND_B, | ||
257 | }; | ||
258 | void *ptr; | ||
259 | int off; | ||
260 | |||
261 | #define CONT ({ insn++; goto select_insn; }) | ||
262 | #define CONT_JMP ({ insn++; goto select_insn; }) | ||
263 | |||
264 | FP = (u64) (unsigned long) &stack[ARRAY_SIZE(stack)]; | ||
265 | ARG1 = (u64) (unsigned long) ctx; | ||
266 | |||
267 | /* Registers used in classic BPF programs need to be reset first. */ | ||
268 | regs[BPF_REG_A] = 0; | ||
269 | regs[BPF_REG_X] = 0; | ||
270 | |||
271 | select_insn: | ||
272 | goto *jumptable[insn->code]; | ||
273 | |||
274 | /* ALU */ | ||
275 | #define ALU(OPCODE, OP) \ | ||
276 | ALU64_##OPCODE##_X: \ | ||
277 | DST = DST OP SRC; \ | ||
278 | CONT; \ | ||
279 | ALU_##OPCODE##_X: \ | ||
280 | DST = (u32) DST OP (u32) SRC; \ | ||
281 | CONT; \ | ||
282 | ALU64_##OPCODE##_K: \ | ||
283 | DST = DST OP IMM; \ | ||
284 | CONT; \ | ||
285 | ALU_##OPCODE##_K: \ | ||
286 | DST = (u32) DST OP (u32) IMM; \ | ||
287 | CONT; | ||
288 | |||
289 | ALU(ADD, +) | ||
290 | ALU(SUB, -) | ||
291 | ALU(AND, &) | ||
292 | ALU(OR, |) | ||
293 | ALU(LSH, <<) | ||
294 | ALU(RSH, >>) | ||
295 | ALU(XOR, ^) | ||
296 | ALU(MUL, *) | ||
297 | #undef ALU | ||
298 | ALU_NEG: | ||
299 | DST = (u32) -DST; | ||
300 | CONT; | ||
301 | ALU64_NEG: | ||
302 | DST = -DST; | ||
303 | CONT; | ||
304 | ALU_MOV_X: | ||
305 | DST = (u32) SRC; | ||
306 | CONT; | ||
307 | ALU_MOV_K: | ||
308 | DST = (u32) IMM; | ||
309 | CONT; | ||
310 | ALU64_MOV_X: | ||
311 | DST = SRC; | ||
312 | CONT; | ||
313 | ALU64_MOV_K: | ||
314 | DST = IMM; | ||
315 | CONT; | ||
316 | ALU64_ARSH_X: | ||
317 | (*(s64 *) &DST) >>= SRC; | ||
318 | CONT; | ||
319 | ALU64_ARSH_K: | ||
320 | (*(s64 *) &DST) >>= IMM; | ||
321 | CONT; | ||
322 | ALU64_MOD_X: | ||
323 | if (unlikely(SRC == 0)) | ||
324 | return 0; | ||
325 | tmp = DST; | ||
326 | DST = do_div(tmp, SRC); | ||
327 | CONT; | ||
328 | ALU_MOD_X: | ||
329 | if (unlikely(SRC == 0)) | ||
330 | return 0; | ||
331 | tmp = (u32) DST; | ||
332 | DST = do_div(tmp, (u32) SRC); | ||
333 | CONT; | ||
334 | ALU64_MOD_K: | ||
335 | tmp = DST; | ||
336 | DST = do_div(tmp, IMM); | ||
337 | CONT; | ||
338 | ALU_MOD_K: | ||
339 | tmp = (u32) DST; | ||
340 | DST = do_div(tmp, (u32) IMM); | ||
341 | CONT; | ||
342 | ALU64_DIV_X: | ||
343 | if (unlikely(SRC == 0)) | ||
344 | return 0; | ||
345 | do_div(DST, SRC); | ||
346 | CONT; | ||
347 | ALU_DIV_X: | ||
348 | if (unlikely(SRC == 0)) | ||
349 | return 0; | ||
350 | tmp = (u32) DST; | ||
351 | do_div(tmp, (u32) SRC); | ||
352 | DST = (u32) tmp; | ||
353 | CONT; | ||
354 | ALU64_DIV_K: | ||
355 | do_div(DST, IMM); | ||
356 | CONT; | ||
357 | ALU_DIV_K: | ||
358 | tmp = (u32) DST; | ||
359 | do_div(tmp, (u32) IMM); | ||
360 | DST = (u32) tmp; | ||
361 | CONT; | ||
362 | ALU_END_TO_BE: | ||
363 | switch (IMM) { | ||
364 | case 16: | ||
365 | DST = (__force u16) cpu_to_be16(DST); | ||
366 | break; | ||
367 | case 32: | ||
368 | DST = (__force u32) cpu_to_be32(DST); | ||
369 | break; | ||
370 | case 64: | ||
371 | DST = (__force u64) cpu_to_be64(DST); | ||
372 | break; | ||
373 | } | ||
374 | CONT; | ||
375 | ALU_END_TO_LE: | ||
376 | switch (IMM) { | ||
377 | case 16: | ||
378 | DST = (__force u16) cpu_to_le16(DST); | ||
379 | break; | ||
380 | case 32: | ||
381 | DST = (__force u32) cpu_to_le32(DST); | ||
382 | break; | ||
383 | case 64: | ||
384 | DST = (__force u64) cpu_to_le64(DST); | ||
385 | break; | ||
386 | } | ||
387 | CONT; | ||
388 | |||
389 | /* CALL */ | ||
390 | JMP_CALL: | ||
391 | /* Function call scratches BPF_R1-BPF_R5 registers, | ||
392 | * preserves BPF_R6-BPF_R9, and stores return value | ||
393 | * into BPF_R0. | ||
394 | */ | ||
395 | BPF_R0 = (__bpf_call_base + insn->imm)(BPF_R1, BPF_R2, BPF_R3, | ||
396 | BPF_R4, BPF_R5); | ||
397 | CONT; | ||
398 | |||
399 | /* JMP */ | ||
400 | JMP_JA: | ||
401 | insn += insn->off; | ||
402 | CONT; | ||
403 | JMP_JEQ_X: | ||
404 | if (DST == SRC) { | ||
405 | insn += insn->off; | ||
406 | CONT_JMP; | ||
407 | } | ||
408 | CONT; | ||
409 | JMP_JEQ_K: | ||
410 | if (DST == IMM) { | ||
411 | insn += insn->off; | ||
412 | CONT_JMP; | ||
413 | } | ||
414 | CONT; | ||
415 | JMP_JNE_X: | ||
416 | if (DST != SRC) { | ||
417 | insn += insn->off; | ||
418 | CONT_JMP; | ||
419 | } | ||
420 | CONT; | ||
421 | JMP_JNE_K: | ||
422 | if (DST != IMM) { | ||
423 | insn += insn->off; | ||
424 | CONT_JMP; | ||
425 | } | ||
426 | CONT; | ||
427 | JMP_JGT_X: | ||
428 | if (DST > SRC) { | ||
429 | insn += insn->off; | ||
430 | CONT_JMP; | ||
431 | } | ||
432 | CONT; | ||
433 | JMP_JGT_K: | ||
434 | if (DST > IMM) { | ||
435 | insn += insn->off; | ||
436 | CONT_JMP; | ||
437 | } | ||
438 | CONT; | ||
439 | JMP_JGE_X: | ||
440 | if (DST >= SRC) { | ||
441 | insn += insn->off; | ||
442 | CONT_JMP; | ||
443 | } | ||
444 | CONT; | ||
445 | JMP_JGE_K: | ||
446 | if (DST >= IMM) { | ||
447 | insn += insn->off; | ||
448 | CONT_JMP; | ||
449 | } | ||
450 | CONT; | ||
451 | JMP_JSGT_X: | ||
452 | if (((s64) DST) > ((s64) SRC)) { | ||
453 | insn += insn->off; | ||
454 | CONT_JMP; | ||
455 | } | ||
456 | CONT; | ||
457 | JMP_JSGT_K: | ||
458 | if (((s64) DST) > ((s64) IMM)) { | ||
459 | insn += insn->off; | ||
460 | CONT_JMP; | ||
461 | } | ||
462 | CONT; | ||
463 | JMP_JSGE_X: | ||
464 | if (((s64) DST) >= ((s64) SRC)) { | ||
465 | insn += insn->off; | ||
466 | CONT_JMP; | ||
467 | } | ||
468 | CONT; | ||
469 | JMP_JSGE_K: | ||
470 | if (((s64) DST) >= ((s64) IMM)) { | ||
471 | insn += insn->off; | ||
472 | CONT_JMP; | ||
473 | } | ||
474 | CONT; | ||
475 | JMP_JSET_X: | ||
476 | if (DST & SRC) { | ||
477 | insn += insn->off; | ||
478 | CONT_JMP; | ||
479 | } | ||
480 | CONT; | ||
481 | JMP_JSET_K: | ||
482 | if (DST & IMM) { | ||
483 | insn += insn->off; | ||
484 | CONT_JMP; | ||
485 | } | ||
486 | CONT; | ||
487 | JMP_EXIT: | ||
488 | return BPF_R0; | ||
489 | |||
490 | /* STX and ST and LDX*/ | ||
491 | #define LDST(SIZEOP, SIZE) \ | ||
492 | STX_MEM_##SIZEOP: \ | ||
493 | *(SIZE *)(unsigned long) (DST + insn->off) = SRC; \ | ||
494 | CONT; \ | ||
495 | ST_MEM_##SIZEOP: \ | ||
496 | *(SIZE *)(unsigned long) (DST + insn->off) = IMM; \ | ||
497 | CONT; \ | ||
498 | LDX_MEM_##SIZEOP: \ | ||
499 | DST = *(SIZE *)(unsigned long) (SRC + insn->off); \ | ||
500 | CONT; | ||
501 | |||
502 | LDST(B, u8) | ||
503 | LDST(H, u16) | ||
504 | LDST(W, u32) | ||
505 | LDST(DW, u64) | ||
506 | #undef LDST | ||
507 | STX_XADD_W: /* lock xadd *(u32 *)(dst_reg + off16) += src_reg */ | ||
508 | atomic_add((u32) SRC, (atomic_t *)(unsigned long) | ||
509 | (DST + insn->off)); | ||
510 | CONT; | ||
511 | STX_XADD_DW: /* lock xadd *(u64 *)(dst_reg + off16) += src_reg */ | ||
512 | atomic64_add((u64) SRC, (atomic64_t *)(unsigned long) | ||
513 | (DST + insn->off)); | ||
514 | CONT; | ||
515 | LD_ABS_W: /* BPF_R0 = ntohl(*(u32 *) (skb->data + imm32)) */ | ||
516 | off = IMM; | ||
517 | load_word: | ||
518 | /* BPF_LD + BPD_ABS and BPF_LD + BPF_IND insns are | ||
519 | * only appearing in the programs where ctx == | ||
520 | * skb. All programs keep 'ctx' in regs[BPF_REG_CTX] | ||
521 | * == BPF_R6, sk_convert_filter() saves it in BPF_R6, | ||
522 | * internal BPF verifier will check that BPF_R6 == | ||
523 | * ctx. | ||
524 | * | ||
525 | * BPF_ABS and BPF_IND are wrappers of function calls, | ||
526 | * so they scratch BPF_R1-BPF_R5 registers, preserve | ||
527 | * BPF_R6-BPF_R9, and store return value into BPF_R0. | ||
528 | * | ||
529 | * Implicit input: | ||
530 | * ctx == skb == BPF_R6 == CTX | ||
531 | * | ||
532 | * Explicit input: | ||
533 | * SRC == any register | ||
534 | * IMM == 32-bit immediate | ||
535 | * | ||
536 | * Output: | ||
537 | * BPF_R0 - 8/16/32-bit skb data converted to cpu endianness | ||
538 | */ | ||
539 | |||
540 | ptr = load_pointer((struct sk_buff *) (unsigned long) CTX, off, 4, &tmp); | ||
541 | if (likely(ptr != NULL)) { | ||
542 | BPF_R0 = get_unaligned_be32(ptr); | ||
543 | CONT; | ||
544 | } | ||
545 | |||
546 | return 0; | ||
547 | LD_ABS_H: /* BPF_R0 = ntohs(*(u16 *) (skb->data + imm32)) */ | ||
548 | off = IMM; | ||
549 | load_half: | ||
550 | ptr = load_pointer((struct sk_buff *) (unsigned long) CTX, off, 2, &tmp); | ||
551 | if (likely(ptr != NULL)) { | ||
552 | BPF_R0 = get_unaligned_be16(ptr); | ||
553 | CONT; | ||
554 | } | ||
555 | |||
556 | return 0; | ||
557 | LD_ABS_B: /* BPF_R0 = *(u8 *) (skb->data + imm32) */ | ||
558 | off = IMM; | ||
559 | load_byte: | ||
560 | ptr = load_pointer((struct sk_buff *) (unsigned long) CTX, off, 1, &tmp); | ||
561 | if (likely(ptr != NULL)) { | ||
562 | BPF_R0 = *(u8 *)ptr; | ||
563 | CONT; | ||
564 | } | ||
565 | |||
566 | return 0; | ||
567 | LD_IND_W: /* BPF_R0 = ntohl(*(u32 *) (skb->data + src_reg + imm32)) */ | ||
568 | off = IMM + SRC; | ||
569 | goto load_word; | ||
570 | LD_IND_H: /* BPF_R0 = ntohs(*(u16 *) (skb->data + src_reg + imm32)) */ | ||
571 | off = IMM + SRC; | ||
572 | goto load_half; | ||
573 | LD_IND_B: /* BPF_R0 = *(u8 *) (skb->data + src_reg + imm32) */ | ||
574 | off = IMM + SRC; | ||
575 | goto load_byte; | ||
576 | |||
577 | default_label: | ||
578 | /* If we ever reach this, we have a bug somewhere. */ | ||
579 | WARN_RATELIMIT(1, "unknown opcode %02x\n", insn->code); | ||
580 | return 0; | ||
581 | } | ||
582 | |||
583 | /* Helper to find the offset of pkt_type in sk_buff structure. We want | 90 | /* Helper to find the offset of pkt_type in sk_buff structure. We want |
584 | * to make sure its still a 3bit field starting at a byte boundary; | 91 | * to make sure its still a 3bit field starting at a byte boundary; |
585 | * taken from arch/x86/net/bpf_jit_comp.c. | 92 | * taken from arch/x86/net/bpf_jit_comp.c. |
@@ -667,9 +174,9 @@ static u64 __get_random_u32(u64 ctx, u64 a, u64 x, u64 r4, u64 r5) | |||
667 | } | 174 | } |
668 | 175 | ||
669 | static bool convert_bpf_extensions(struct sock_filter *fp, | 176 | static bool convert_bpf_extensions(struct sock_filter *fp, |
670 | struct sock_filter_int **insnp) | 177 | struct bpf_insn **insnp) |
671 | { | 178 | { |
672 | struct sock_filter_int *insn = *insnp; | 179 | struct bpf_insn *insn = *insnp; |
673 | 180 | ||
674 | switch (fp->k) { | 181 | switch (fp->k) { |
675 | case SKF_AD_OFF + SKF_AD_PROTOCOL: | 182 | case SKF_AD_OFF + SKF_AD_PROTOCOL: |
@@ -805,7 +312,7 @@ static bool convert_bpf_extensions(struct sock_filter *fp, | |||
805 | } | 312 | } |
806 | 313 | ||
807 | /** | 314 | /** |
808 | * sk_convert_filter - convert filter program | 315 | * bpf_convert_filter - convert filter program |
809 | * @prog: the user passed filter program | 316 | * @prog: the user passed filter program |
810 | * @len: the length of the user passed filter program | 317 | * @len: the length of the user passed filter program |
811 | * @new_prog: buffer where converted program will be stored | 318 | * @new_prog: buffer where converted program will be stored |
@@ -815,12 +322,12 @@ static bool convert_bpf_extensions(struct sock_filter *fp, | |||
815 | * Conversion workflow: | 322 | * Conversion workflow: |
816 | * | 323 | * |
817 | * 1) First pass for calculating the new program length: | 324 | * 1) First pass for calculating the new program length: |
818 | * sk_convert_filter(old_prog, old_len, NULL, &new_len) | 325 | * bpf_convert_filter(old_prog, old_len, NULL, &new_len) |
819 | * | 326 | * |
820 | * 2) 2nd pass to remap in two passes: 1st pass finds new | 327 | * 2) 2nd pass to remap in two passes: 1st pass finds new |
821 | * jump offsets, 2nd pass remapping: | 328 | * jump offsets, 2nd pass remapping: |
822 | * new_prog = kmalloc(sizeof(struct sock_filter_int) * new_len); | 329 | * new_prog = kmalloc(sizeof(struct bpf_insn) * new_len); |
823 | * sk_convert_filter(old_prog, old_len, new_prog, &new_len); | 330 | * bpf_convert_filter(old_prog, old_len, new_prog, &new_len); |
824 | * | 331 | * |
825 | * User BPF's register A is mapped to our BPF register 6, user BPF | 332 | * User BPF's register A is mapped to our BPF register 6, user BPF |
826 | * register X is mapped to BPF register 7; frame pointer is always | 333 | * register X is mapped to BPF register 7; frame pointer is always |
@@ -828,11 +335,11 @@ static bool convert_bpf_extensions(struct sock_filter *fp, | |||
828 | * for socket filters: ctx == 'struct sk_buff *', for seccomp: | 335 | * for socket filters: ctx == 'struct sk_buff *', for seccomp: |
829 | * ctx == 'struct seccomp_data *'. | 336 | * ctx == 'struct seccomp_data *'. |
830 | */ | 337 | */ |
831 | int sk_convert_filter(struct sock_filter *prog, int len, | 338 | int bpf_convert_filter(struct sock_filter *prog, int len, |
832 | struct sock_filter_int *new_prog, int *new_len) | 339 | struct bpf_insn *new_prog, int *new_len) |
833 | { | 340 | { |
834 | int new_flen = 0, pass = 0, target, i; | 341 | int new_flen = 0, pass = 0, target, i; |
835 | struct sock_filter_int *new_insn; | 342 | struct bpf_insn *new_insn; |
836 | struct sock_filter *fp; | 343 | struct sock_filter *fp; |
837 | int *addrs = NULL; | 344 | int *addrs = NULL; |
838 | u8 bpf_src; | 345 | u8 bpf_src; |
@@ -858,8 +365,8 @@ do_pass: | |||
858 | new_insn++; | 365 | new_insn++; |
859 | 366 | ||
860 | for (i = 0; i < len; fp++, i++) { | 367 | for (i = 0; i < len; fp++, i++) { |
861 | struct sock_filter_int tmp_insns[6] = { }; | 368 | struct bpf_insn tmp_insns[6] = { }; |
862 | struct sock_filter_int *insn = tmp_insns; | 369 | struct bpf_insn *insn = tmp_insns; |
863 | 370 | ||
864 | if (addrs) | 371 | if (addrs) |
865 | addrs[i] = new_insn - new_prog; | 372 | addrs[i] = new_insn - new_prog; |
@@ -1094,7 +601,7 @@ err: | |||
1094 | * a cell if not previously written, and we check all branches to be sure | 601 | * a cell if not previously written, and we check all branches to be sure |
1095 | * a malicious user doesn't try to abuse us. | 602 | * a malicious user doesn't try to abuse us. |
1096 | */ | 603 | */ |
1097 | static int check_load_and_stores(struct sock_filter *filter, int flen) | 604 | static int check_load_and_stores(const struct sock_filter *filter, int flen) |
1098 | { | 605 | { |
1099 | u16 *masks, memvalid = 0; /* One bit per cell, 16 cells */ | 606 | u16 *masks, memvalid = 0; /* One bit per cell, 16 cells */ |
1100 | int pc, ret = 0; | 607 | int pc, ret = 0; |
@@ -1214,7 +721,7 @@ static bool chk_code_allowed(u16 code_to_probe) | |||
1214 | } | 721 | } |
1215 | 722 | ||
1216 | /** | 723 | /** |
1217 | * sk_chk_filter - verify socket filter code | 724 | * bpf_check_classic - verify socket filter code |
1218 | * @filter: filter to verify | 725 | * @filter: filter to verify |
1219 | * @flen: length of filter | 726 | * @flen: length of filter |
1220 | * | 727 | * |
@@ -1227,7 +734,7 @@ static bool chk_code_allowed(u16 code_to_probe) | |||
1227 | * | 734 | * |
1228 | * Returns 0 if the rule set is legal or -EINVAL if not. | 735 | * Returns 0 if the rule set is legal or -EINVAL if not. |
1229 | */ | 736 | */ |
1230 | int sk_chk_filter(struct sock_filter *filter, unsigned int flen) | 737 | int bpf_check_classic(const struct sock_filter *filter, unsigned int flen) |
1231 | { | 738 | { |
1232 | bool anc_found; | 739 | bool anc_found; |
1233 | int pc; | 740 | int pc; |
@@ -1237,7 +744,7 @@ int sk_chk_filter(struct sock_filter *filter, unsigned int flen) | |||
1237 | 744 | ||
1238 | /* Check the filter code now */ | 745 | /* Check the filter code now */ |
1239 | for (pc = 0; pc < flen; pc++) { | 746 | for (pc = 0; pc < flen; pc++) { |
1240 | struct sock_filter *ftest = &filter[pc]; | 747 | const struct sock_filter *ftest = &filter[pc]; |
1241 | 748 | ||
1242 | /* May we actually operate on this code? */ | 749 | /* May we actually operate on this code? */ |
1243 | if (!chk_code_allowed(ftest->code)) | 750 | if (!chk_code_allowed(ftest->code)) |
@@ -1301,12 +808,12 @@ int sk_chk_filter(struct sock_filter *filter, unsigned int flen) | |||
1301 | 808 | ||
1302 | return -EINVAL; | 809 | return -EINVAL; |
1303 | } | 810 | } |
1304 | EXPORT_SYMBOL(sk_chk_filter); | 811 | EXPORT_SYMBOL(bpf_check_classic); |
1305 | 812 | ||
1306 | static int sk_store_orig_filter(struct sk_filter *fp, | 813 | static int bpf_prog_store_orig_filter(struct bpf_prog *fp, |
1307 | const struct sock_fprog *fprog) | 814 | const struct sock_fprog *fprog) |
1308 | { | 815 | { |
1309 | unsigned int fsize = sk_filter_proglen(fprog); | 816 | unsigned int fsize = bpf_classic_proglen(fprog); |
1310 | struct sock_fprog_kern *fkprog; | 817 | struct sock_fprog_kern *fkprog; |
1311 | 818 | ||
1312 | fp->orig_prog = kmalloc(sizeof(*fkprog), GFP_KERNEL); | 819 | fp->orig_prog = kmalloc(sizeof(*fkprog), GFP_KERNEL); |
@@ -1324,7 +831,7 @@ static int sk_store_orig_filter(struct sk_filter *fp, | |||
1324 | return 0; | 831 | return 0; |
1325 | } | 832 | } |
1326 | 833 | ||
1327 | static void sk_release_orig_filter(struct sk_filter *fp) | 834 | static void bpf_release_orig_filter(struct bpf_prog *fp) |
1328 | { | 835 | { |
1329 | struct sock_fprog_kern *fprog = fp->orig_prog; | 836 | struct sock_fprog_kern *fprog = fp->orig_prog; |
1330 | 837 | ||
@@ -1334,6 +841,18 @@ static void sk_release_orig_filter(struct sk_filter *fp) | |||
1334 | } | 841 | } |
1335 | } | 842 | } |
1336 | 843 | ||
844 | static void __bpf_prog_release(struct bpf_prog *prog) | ||
845 | { | ||
846 | bpf_release_orig_filter(prog); | ||
847 | bpf_prog_free(prog); | ||
848 | } | ||
849 | |||
850 | static void __sk_filter_release(struct sk_filter *fp) | ||
851 | { | ||
852 | __bpf_prog_release(fp->prog); | ||
853 | kfree(fp); | ||
854 | } | ||
855 | |||
1337 | /** | 856 | /** |
1338 | * sk_filter_release_rcu - Release a socket filter by rcu_head | 857 | * sk_filter_release_rcu - Release a socket filter by rcu_head |
1339 | * @rcu: rcu_head that contains the sk_filter to free | 858 | * @rcu: rcu_head that contains the sk_filter to free |
@@ -1342,8 +861,7 @@ static void sk_filter_release_rcu(struct rcu_head *rcu) | |||
1342 | { | 861 | { |
1343 | struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu); | 862 | struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu); |
1344 | 863 | ||
1345 | sk_release_orig_filter(fp); | 864 | __sk_filter_release(fp); |
1346 | sk_filter_free(fp); | ||
1347 | } | 865 | } |
1348 | 866 | ||
1349 | /** | 867 | /** |
@@ -1360,44 +878,33 @@ static void sk_filter_release(struct sk_filter *fp) | |||
1360 | 878 | ||
1361 | void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp) | 879 | void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp) |
1362 | { | 880 | { |
1363 | atomic_sub(sk_filter_size(fp->len), &sk->sk_omem_alloc); | 881 | u32 filter_size = bpf_prog_size(fp->prog->len); |
1364 | sk_filter_release(fp); | ||
1365 | } | ||
1366 | 882 | ||
1367 | void sk_filter_charge(struct sock *sk, struct sk_filter *fp) | 883 | atomic_sub(filter_size, &sk->sk_omem_alloc); |
1368 | { | 884 | sk_filter_release(fp); |
1369 | atomic_inc(&fp->refcnt); | ||
1370 | atomic_add(sk_filter_size(fp->len), &sk->sk_omem_alloc); | ||
1371 | } | 885 | } |
1372 | 886 | ||
1373 | static struct sk_filter *__sk_migrate_realloc(struct sk_filter *fp, | 887 | /* try to charge the socket memory if there is space available |
1374 | struct sock *sk, | 888 | * return true on success |
1375 | unsigned int len) | 889 | */ |
890 | bool sk_filter_charge(struct sock *sk, struct sk_filter *fp) | ||
1376 | { | 891 | { |
1377 | struct sk_filter *fp_new; | 892 | u32 filter_size = bpf_prog_size(fp->prog->len); |
1378 | 893 | ||
1379 | if (sk == NULL) | 894 | /* same check as in sock_kmalloc() */ |
1380 | return krealloc(fp, len, GFP_KERNEL); | 895 | if (filter_size <= sysctl_optmem_max && |
1381 | 896 | atomic_read(&sk->sk_omem_alloc) + filter_size < sysctl_optmem_max) { | |
1382 | fp_new = sock_kmalloc(sk, len, GFP_KERNEL); | 897 | atomic_inc(&fp->refcnt); |
1383 | if (fp_new) { | 898 | atomic_add(filter_size, &sk->sk_omem_alloc); |
1384 | *fp_new = *fp; | 899 | return true; |
1385 | /* As we're keeping orig_prog in fp_new along, | ||
1386 | * we need to make sure we're not evicting it | ||
1387 | * from the old fp. | ||
1388 | */ | ||
1389 | fp->orig_prog = NULL; | ||
1390 | sk_filter_uncharge(sk, fp); | ||
1391 | } | 900 | } |
1392 | 901 | return false; | |
1393 | return fp_new; | ||
1394 | } | 902 | } |
1395 | 903 | ||
1396 | static struct sk_filter *__sk_migrate_filter(struct sk_filter *fp, | 904 | static struct bpf_prog *bpf_migrate_filter(struct bpf_prog *fp) |
1397 | struct sock *sk) | ||
1398 | { | 905 | { |
1399 | struct sock_filter *old_prog; | 906 | struct sock_filter *old_prog; |
1400 | struct sk_filter *old_fp; | 907 | struct bpf_prog *old_fp; |
1401 | int err, new_len, old_len = fp->len; | 908 | int err, new_len, old_len = fp->len; |
1402 | 909 | ||
1403 | /* We are free to overwrite insns et al right here as it | 910 | /* We are free to overwrite insns et al right here as it |
@@ -1406,7 +913,7 @@ static struct sk_filter *__sk_migrate_filter(struct sk_filter *fp, | |||
1406 | * representation. | 913 | * representation. |
1407 | */ | 914 | */ |
1408 | BUILD_BUG_ON(sizeof(struct sock_filter) != | 915 | BUILD_BUG_ON(sizeof(struct sock_filter) != |
1409 | sizeof(struct sock_filter_int)); | 916 | sizeof(struct bpf_insn)); |
1410 | 917 | ||
1411 | /* Conversion cannot happen on overlapping memory areas, | 918 | /* Conversion cannot happen on overlapping memory areas, |
1412 | * so we need to keep the user BPF around until the 2nd | 919 | * so we need to keep the user BPF around until the 2nd |
@@ -1420,13 +927,13 @@ static struct sk_filter *__sk_migrate_filter(struct sk_filter *fp, | |||
1420 | } | 927 | } |
1421 | 928 | ||
1422 | /* 1st pass: calculate the new program length. */ | 929 | /* 1st pass: calculate the new program length. */ |
1423 | err = sk_convert_filter(old_prog, old_len, NULL, &new_len); | 930 | err = bpf_convert_filter(old_prog, old_len, NULL, &new_len); |
1424 | if (err) | 931 | if (err) |
1425 | goto out_err_free; | 932 | goto out_err_free; |
1426 | 933 | ||
1427 | /* Expand fp for appending the new filter representation. */ | 934 | /* Expand fp for appending the new filter representation. */ |
1428 | old_fp = fp; | 935 | old_fp = fp; |
1429 | fp = __sk_migrate_realloc(old_fp, sk, sk_filter_size(new_len)); | 936 | fp = krealloc(old_fp, bpf_prog_size(new_len), GFP_KERNEL); |
1430 | if (!fp) { | 937 | if (!fp) { |
1431 | /* The old_fp is still around in case we couldn't | 938 | /* The old_fp is still around in case we couldn't |
1432 | * allocate new memory, so uncharge on that one. | 939 | * allocate new memory, so uncharge on that one. |
@@ -1438,17 +945,17 @@ static struct sk_filter *__sk_migrate_filter(struct sk_filter *fp, | |||
1438 | 945 | ||
1439 | fp->len = new_len; | 946 | fp->len = new_len; |
1440 | 947 | ||
1441 | /* 2nd pass: remap sock_filter insns into sock_filter_int insns. */ | 948 | /* 2nd pass: remap sock_filter insns into bpf_insn insns. */ |
1442 | err = sk_convert_filter(old_prog, old_len, fp->insnsi, &new_len); | 949 | err = bpf_convert_filter(old_prog, old_len, fp->insnsi, &new_len); |
1443 | if (err) | 950 | if (err) |
1444 | /* 2nd sk_convert_filter() can fail only if it fails | 951 | /* 2nd bpf_convert_filter() can fail only if it fails |
1445 | * to allocate memory, remapping must succeed. Note, | 952 | * to allocate memory, remapping must succeed. Note, |
1446 | * that at this time old_fp has already been released | 953 | * that at this time old_fp has already been released |
1447 | * by __sk_migrate_realloc(). | 954 | * by krealloc(). |
1448 | */ | 955 | */ |
1449 | goto out_err_free; | 956 | goto out_err_free; |
1450 | 957 | ||
1451 | sk_filter_select_runtime(fp); | 958 | bpf_prog_select_runtime(fp); |
1452 | 959 | ||
1453 | kfree(old_prog); | 960 | kfree(old_prog); |
1454 | return fp; | 961 | return fp; |
@@ -1456,55 +963,20 @@ static struct sk_filter *__sk_migrate_filter(struct sk_filter *fp, | |||
1456 | out_err_free: | 963 | out_err_free: |
1457 | kfree(old_prog); | 964 | kfree(old_prog); |
1458 | out_err: | 965 | out_err: |
1459 | /* Rollback filter setup. */ | 966 | __bpf_prog_release(fp); |
1460 | if (sk != NULL) | ||
1461 | sk_filter_uncharge(sk, fp); | ||
1462 | else | ||
1463 | kfree(fp); | ||
1464 | return ERR_PTR(err); | 967 | return ERR_PTR(err); |
1465 | } | 968 | } |
1466 | 969 | ||
1467 | void __weak bpf_int_jit_compile(struct sk_filter *prog) | 970 | static struct bpf_prog *bpf_prepare_filter(struct bpf_prog *fp) |
1468 | { | ||
1469 | } | ||
1470 | |||
1471 | /** | ||
1472 | * sk_filter_select_runtime - select execution runtime for BPF program | ||
1473 | * @fp: sk_filter populated with internal BPF program | ||
1474 | * | ||
1475 | * try to JIT internal BPF program, if JIT is not available select interpreter | ||
1476 | * BPF program will be executed via SK_RUN_FILTER() macro | ||
1477 | */ | ||
1478 | void sk_filter_select_runtime(struct sk_filter *fp) | ||
1479 | { | ||
1480 | fp->bpf_func = (void *) __sk_run_filter; | ||
1481 | |||
1482 | /* Probe if internal BPF can be JITed */ | ||
1483 | bpf_int_jit_compile(fp); | ||
1484 | } | ||
1485 | EXPORT_SYMBOL_GPL(sk_filter_select_runtime); | ||
1486 | |||
1487 | /* free internal BPF program */ | ||
1488 | void sk_filter_free(struct sk_filter *fp) | ||
1489 | { | ||
1490 | bpf_jit_free(fp); | ||
1491 | } | ||
1492 | EXPORT_SYMBOL_GPL(sk_filter_free); | ||
1493 | |||
1494 | static struct sk_filter *__sk_prepare_filter(struct sk_filter *fp, | ||
1495 | struct sock *sk) | ||
1496 | { | 971 | { |
1497 | int err; | 972 | int err; |
1498 | 973 | ||
1499 | fp->bpf_func = NULL; | 974 | fp->bpf_func = NULL; |
1500 | fp->jited = 0; | 975 | fp->jited = 0; |
1501 | 976 | ||
1502 | err = sk_chk_filter(fp->insns, fp->len); | 977 | err = bpf_check_classic(fp->insns, fp->len); |
1503 | if (err) { | 978 | if (err) { |
1504 | if (sk != NULL) | 979 | __bpf_prog_release(fp); |
1505 | sk_filter_uncharge(sk, fp); | ||
1506 | else | ||
1507 | kfree(fp); | ||
1508 | return ERR_PTR(err); | 980 | return ERR_PTR(err); |
1509 | } | 981 | } |
1510 | 982 | ||
@@ -1517,13 +989,13 @@ static struct sk_filter *__sk_prepare_filter(struct sk_filter *fp, | |||
1517 | * internal BPF translation for the optimized interpreter. | 989 | * internal BPF translation for the optimized interpreter. |
1518 | */ | 990 | */ |
1519 | if (!fp->jited) | 991 | if (!fp->jited) |
1520 | fp = __sk_migrate_filter(fp, sk); | 992 | fp = bpf_migrate_filter(fp); |
1521 | 993 | ||
1522 | return fp; | 994 | return fp; |
1523 | } | 995 | } |
1524 | 996 | ||
1525 | /** | 997 | /** |
1526 | * sk_unattached_filter_create - create an unattached filter | 998 | * bpf_prog_create - create an unattached filter |
1527 | * @pfp: the unattached filter that is created | 999 | * @pfp: the unattached filter that is created |
1528 | * @fprog: the filter program | 1000 | * @fprog: the filter program |
1529 | * | 1001 | * |
@@ -1532,23 +1004,21 @@ static struct sk_filter *__sk_prepare_filter(struct sk_filter *fp, | |||
1532 | * If an error occurs or there is insufficient memory for the filter | 1004 | * If an error occurs or there is insufficient memory for the filter |
1533 | * a negative errno code is returned. On success the return is zero. | 1005 | * a negative errno code is returned. On success the return is zero. |
1534 | */ | 1006 | */ |
1535 | int sk_unattached_filter_create(struct sk_filter **pfp, | 1007 | int bpf_prog_create(struct bpf_prog **pfp, struct sock_fprog_kern *fprog) |
1536 | struct sock_fprog_kern *fprog) | ||
1537 | { | 1008 | { |
1538 | unsigned int fsize = sk_filter_proglen(fprog); | 1009 | unsigned int fsize = bpf_classic_proglen(fprog); |
1539 | struct sk_filter *fp; | 1010 | struct bpf_prog *fp; |
1540 | 1011 | ||
1541 | /* Make sure new filter is there and in the right amounts. */ | 1012 | /* Make sure new filter is there and in the right amounts. */ |
1542 | if (fprog->filter == NULL) | 1013 | if (fprog->filter == NULL) |
1543 | return -EINVAL; | 1014 | return -EINVAL; |
1544 | 1015 | ||
1545 | fp = kmalloc(sk_filter_size(fprog->len), GFP_KERNEL); | 1016 | fp = kmalloc(bpf_prog_size(fprog->len), GFP_KERNEL); |
1546 | if (!fp) | 1017 | if (!fp) |
1547 | return -ENOMEM; | 1018 | return -ENOMEM; |
1548 | 1019 | ||
1549 | memcpy(fp->insns, fprog->filter, fsize); | 1020 | memcpy(fp->insns, fprog->filter, fsize); |
1550 | 1021 | ||
1551 | atomic_set(&fp->refcnt, 1); | ||
1552 | fp->len = fprog->len; | 1022 | fp->len = fprog->len; |
1553 | /* Since unattached filters are not copied back to user | 1023 | /* Since unattached filters are not copied back to user |
1554 | * space through sk_get_filter(), we do not need to hold | 1024 | * space through sk_get_filter(), we do not need to hold |
@@ -1556,23 +1026,23 @@ int sk_unattached_filter_create(struct sk_filter **pfp, | |||
1556 | */ | 1026 | */ |
1557 | fp->orig_prog = NULL; | 1027 | fp->orig_prog = NULL; |
1558 | 1028 | ||
1559 | /* __sk_prepare_filter() already takes care of uncharging | 1029 | /* bpf_prepare_filter() already takes care of freeing |
1560 | * memory in case something goes wrong. | 1030 | * memory in case something goes wrong. |
1561 | */ | 1031 | */ |
1562 | fp = __sk_prepare_filter(fp, NULL); | 1032 | fp = bpf_prepare_filter(fp); |
1563 | if (IS_ERR(fp)) | 1033 | if (IS_ERR(fp)) |
1564 | return PTR_ERR(fp); | 1034 | return PTR_ERR(fp); |
1565 | 1035 | ||
1566 | *pfp = fp; | 1036 | *pfp = fp; |
1567 | return 0; | 1037 | return 0; |
1568 | } | 1038 | } |
1569 | EXPORT_SYMBOL_GPL(sk_unattached_filter_create); | 1039 | EXPORT_SYMBOL_GPL(bpf_prog_create); |
1570 | 1040 | ||
1571 | void sk_unattached_filter_destroy(struct sk_filter *fp) | 1041 | void bpf_prog_destroy(struct bpf_prog *fp) |
1572 | { | 1042 | { |
1573 | sk_filter_release(fp); | 1043 | __bpf_prog_release(fp); |
1574 | } | 1044 | } |
1575 | EXPORT_SYMBOL_GPL(sk_unattached_filter_destroy); | 1045 | EXPORT_SYMBOL_GPL(bpf_prog_destroy); |
1576 | 1046 | ||
1577 | /** | 1047 | /** |
1578 | * sk_attach_filter - attach a socket filter | 1048 | * sk_attach_filter - attach a socket filter |
@@ -1587,8 +1057,9 @@ EXPORT_SYMBOL_GPL(sk_unattached_filter_destroy); | |||
1587 | int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) | 1057 | int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) |
1588 | { | 1058 | { |
1589 | struct sk_filter *fp, *old_fp; | 1059 | struct sk_filter *fp, *old_fp; |
1590 | unsigned int fsize = sk_filter_proglen(fprog); | 1060 | unsigned int fsize = bpf_classic_proglen(fprog); |
1591 | unsigned int sk_fsize = sk_filter_size(fprog->len); | 1061 | unsigned int bpf_fsize = bpf_prog_size(fprog->len); |
1062 | struct bpf_prog *prog; | ||
1592 | int err; | 1063 | int err; |
1593 | 1064 | ||
1594 | if (sock_flag(sk, SOCK_FILTER_LOCKED)) | 1065 | if (sock_flag(sk, SOCK_FILTER_LOCKED)) |
@@ -1598,30 +1069,43 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) | |||
1598 | if (fprog->filter == NULL) | 1069 | if (fprog->filter == NULL) |
1599 | return -EINVAL; | 1070 | return -EINVAL; |
1600 | 1071 | ||
1601 | fp = sock_kmalloc(sk, sk_fsize, GFP_KERNEL); | 1072 | prog = kmalloc(bpf_fsize, GFP_KERNEL); |
1602 | if (!fp) | 1073 | if (!prog) |
1603 | return -ENOMEM; | 1074 | return -ENOMEM; |
1604 | 1075 | ||
1605 | if (copy_from_user(fp->insns, fprog->filter, fsize)) { | 1076 | if (copy_from_user(prog->insns, fprog->filter, fsize)) { |
1606 | sock_kfree_s(sk, fp, sk_fsize); | 1077 | kfree(prog); |
1607 | return -EFAULT; | 1078 | return -EFAULT; |
1608 | } | 1079 | } |
1609 | 1080 | ||
1610 | atomic_set(&fp->refcnt, 1); | 1081 | prog->len = fprog->len; |
1611 | fp->len = fprog->len; | ||
1612 | 1082 | ||
1613 | err = sk_store_orig_filter(fp, fprog); | 1083 | err = bpf_prog_store_orig_filter(prog, fprog); |
1614 | if (err) { | 1084 | if (err) { |
1615 | sk_filter_uncharge(sk, fp); | 1085 | kfree(prog); |
1616 | return -ENOMEM; | 1086 | return -ENOMEM; |
1617 | } | 1087 | } |
1618 | 1088 | ||
1619 | /* __sk_prepare_filter() already takes care of uncharging | 1089 | /* bpf_prepare_filter() already takes care of freeing |
1620 | * memory in case something goes wrong. | 1090 | * memory in case something goes wrong. |
1621 | */ | 1091 | */ |
1622 | fp = __sk_prepare_filter(fp, sk); | 1092 | prog = bpf_prepare_filter(prog); |
1623 | if (IS_ERR(fp)) | 1093 | if (IS_ERR(prog)) |
1624 | return PTR_ERR(fp); | 1094 | return PTR_ERR(prog); |
1095 | |||
1096 | fp = kmalloc(sizeof(*fp), GFP_KERNEL); | ||
1097 | if (!fp) { | ||
1098 | __bpf_prog_release(prog); | ||
1099 | return -ENOMEM; | ||
1100 | } | ||
1101 | fp->prog = prog; | ||
1102 | |||
1103 | atomic_set(&fp->refcnt, 0); | ||
1104 | |||
1105 | if (!sk_filter_charge(sk, fp)) { | ||
1106 | __sk_filter_release(fp); | ||
1107 | return -ENOMEM; | ||
1108 | } | ||
1625 | 1109 | ||
1626 | old_fp = rcu_dereference_protected(sk->sk_filter, | 1110 | old_fp = rcu_dereference_protected(sk->sk_filter, |
1627 | sock_owned_by_user(sk)); | 1111 | sock_owned_by_user(sk)); |
@@ -1670,7 +1154,7 @@ int sk_get_filter(struct sock *sk, struct sock_filter __user *ubuf, | |||
1670 | /* We're copying the filter that has been originally attached, | 1154 | /* We're copying the filter that has been originally attached, |
1671 | * so no conversion/decode needed anymore. | 1155 | * so no conversion/decode needed anymore. |
1672 | */ | 1156 | */ |
1673 | fprog = filter->orig_prog; | 1157 | fprog = filter->prog->orig_prog; |
1674 | 1158 | ||
1675 | ret = fprog->len; | 1159 | ret = fprog->len; |
1676 | if (!len) | 1160 | if (!len) |
@@ -1682,7 +1166,7 @@ int sk_get_filter(struct sock *sk, struct sock_filter __user *ubuf, | |||
1682 | goto out; | 1166 | goto out; |
1683 | 1167 | ||
1684 | ret = -EFAULT; | 1168 | ret = -EFAULT; |
1685 | if (copy_to_user(ubuf, fprog->filter, sk_filter_proglen(fprog))) | 1169 | if (copy_to_user(ubuf, fprog->filter, bpf_classic_proglen(fprog))) |
1686 | goto out; | 1170 | goto out; |
1687 | 1171 | ||
1688 | /* Instead of bytes, the API requests to return the number | 1172 | /* Instead of bytes, the API requests to return the number |
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index 107ed12a5323..5f362c1d0332 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c | |||
@@ -80,6 +80,8 @@ ip: | |||
80 | case htons(ETH_P_IPV6): { | 80 | case htons(ETH_P_IPV6): { |
81 | const struct ipv6hdr *iph; | 81 | const struct ipv6hdr *iph; |
82 | struct ipv6hdr _iph; | 82 | struct ipv6hdr _iph; |
83 | __be32 flow_label; | ||
84 | |||
83 | ipv6: | 85 | ipv6: |
84 | iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph); | 86 | iph = skb_header_pointer(skb, nhoff, sizeof(_iph), &_iph); |
85 | if (!iph) | 87 | if (!iph) |
@@ -89,6 +91,21 @@ ipv6: | |||
89 | flow->src = (__force __be32)ipv6_addr_hash(&iph->saddr); | 91 | flow->src = (__force __be32)ipv6_addr_hash(&iph->saddr); |
90 | flow->dst = (__force __be32)ipv6_addr_hash(&iph->daddr); | 92 | flow->dst = (__force __be32)ipv6_addr_hash(&iph->daddr); |
91 | nhoff += sizeof(struct ipv6hdr); | 93 | nhoff += sizeof(struct ipv6hdr); |
94 | |||
95 | flow_label = ip6_flowlabel(iph); | ||
96 | if (flow_label) { | ||
97 | /* Awesome, IPv6 packet has a flow label so we can | ||
98 | * use that to represent the ports without any | ||
99 | * further dissection. | ||
100 | */ | ||
101 | flow->n_proto = proto; | ||
102 | flow->ip_proto = ip_proto; | ||
103 | flow->ports = flow_label; | ||
104 | flow->thoff = (u16)nhoff; | ||
105 | |||
106 | return true; | ||
107 | } | ||
108 | |||
92 | break; | 109 | break; |
93 | } | 110 | } |
94 | case htons(ETH_P_8021AD): | 111 | case htons(ETH_P_8021AD): |
@@ -175,6 +192,7 @@ ipv6: | |||
175 | break; | 192 | break; |
176 | } | 193 | } |
177 | 194 | ||
195 | flow->n_proto = proto; | ||
178 | flow->ip_proto = ip_proto; | 196 | flow->ip_proto = ip_proto; |
179 | flow->ports = skb_flow_get_ports(skb, nhoff, ip_proto); | 197 | flow->ports = skb_flow_get_ports(skb, nhoff, ip_proto); |
180 | flow->thoff = (u16) nhoff; | 198 | flow->thoff = (u16) nhoff; |
@@ -195,12 +213,33 @@ static __always_inline u32 __flow_hash_3words(u32 a, u32 b, u32 c) | |||
195 | return jhash_3words(a, b, c, hashrnd); | 213 | return jhash_3words(a, b, c, hashrnd); |
196 | } | 214 | } |
197 | 215 | ||
198 | static __always_inline u32 __flow_hash_1word(u32 a) | 216 | static inline u32 __flow_hash_from_keys(struct flow_keys *keys) |
199 | { | 217 | { |
200 | __flow_hash_secret_init(); | 218 | u32 hash; |
201 | return jhash_1word(a, hashrnd); | 219 | |
220 | /* get a consistent hash (same value on both flow directions) */ | ||
221 | if (((__force u32)keys->dst < (__force u32)keys->src) || | ||
222 | (((__force u32)keys->dst == (__force u32)keys->src) && | ||
223 | ((__force u16)keys->port16[1] < (__force u16)keys->port16[0]))) { | ||
224 | swap(keys->dst, keys->src); | ||
225 | swap(keys->port16[0], keys->port16[1]); | ||
226 | } | ||
227 | |||
228 | hash = __flow_hash_3words((__force u32)keys->dst, | ||
229 | (__force u32)keys->src, | ||
230 | (__force u32)keys->ports); | ||
231 | if (!hash) | ||
232 | hash = 1; | ||
233 | |||
234 | return hash; | ||
202 | } | 235 | } |
203 | 236 | ||
237 | u32 flow_hash_from_keys(struct flow_keys *keys) | ||
238 | { | ||
239 | return __flow_hash_from_keys(keys); | ||
240 | } | ||
241 | EXPORT_SYMBOL(flow_hash_from_keys); | ||
242 | |||
204 | /* | 243 | /* |
205 | * __skb_get_hash: calculate a flow hash based on src/dst addresses | 244 | * __skb_get_hash: calculate a flow hash based on src/dst addresses |
206 | * and src/dst port numbers. Sets hash in skb to non-zero hash value | 245 | * and src/dst port numbers. Sets hash in skb to non-zero hash value |
@@ -210,7 +249,6 @@ static __always_inline u32 __flow_hash_1word(u32 a) | |||
210 | void __skb_get_hash(struct sk_buff *skb) | 249 | void __skb_get_hash(struct sk_buff *skb) |
211 | { | 250 | { |
212 | struct flow_keys keys; | 251 | struct flow_keys keys; |
213 | u32 hash; | ||
214 | 252 | ||
215 | if (!skb_flow_dissect(skb, &keys)) | 253 | if (!skb_flow_dissect(skb, &keys)) |
216 | return; | 254 | return; |
@@ -218,21 +256,9 @@ void __skb_get_hash(struct sk_buff *skb) | |||
218 | if (keys.ports) | 256 | if (keys.ports) |
219 | skb->l4_hash = 1; | 257 | skb->l4_hash = 1; |
220 | 258 | ||
221 | /* get a consistent hash (same value on both flow directions) */ | 259 | skb->sw_hash = 1; |
222 | if (((__force u32)keys.dst < (__force u32)keys.src) || | ||
223 | (((__force u32)keys.dst == (__force u32)keys.src) && | ||
224 | ((__force u16)keys.port16[1] < (__force u16)keys.port16[0]))) { | ||
225 | swap(keys.dst, keys.src); | ||
226 | swap(keys.port16[0], keys.port16[1]); | ||
227 | } | ||
228 | |||
229 | hash = __flow_hash_3words((__force u32)keys.dst, | ||
230 | (__force u32)keys.src, | ||
231 | (__force u32)keys.ports); | ||
232 | if (!hash) | ||
233 | hash = 1; | ||
234 | 260 | ||
235 | skb->hash = hash; | 261 | skb->hash = __flow_hash_from_keys(&keys); |
236 | } | 262 | } |
237 | EXPORT_SYMBOL(__skb_get_hash); | 263 | EXPORT_SYMBOL(__skb_get_hash); |
238 | 264 | ||
@@ -240,7 +266,7 @@ EXPORT_SYMBOL(__skb_get_hash); | |||
240 | * Returns a Tx hash based on the given packet descriptor a Tx queues' number | 266 | * Returns a Tx hash based on the given packet descriptor a Tx queues' number |
241 | * to be used as a distribution range. | 267 | * to be used as a distribution range. |
242 | */ | 268 | */ |
243 | u16 __skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb, | 269 | u16 __skb_tx_hash(const struct net_device *dev, struct sk_buff *skb, |
244 | unsigned int num_tx_queues) | 270 | unsigned int num_tx_queues) |
245 | { | 271 | { |
246 | u32 hash; | 272 | u32 hash; |
@@ -260,13 +286,7 @@ u16 __skb_tx_hash(const struct net_device *dev, const struct sk_buff *skb, | |||
260 | qcount = dev->tc_to_txq[tc].count; | 286 | qcount = dev->tc_to_txq[tc].count; |
261 | } | 287 | } |
262 | 288 | ||
263 | if (skb->sk && skb->sk->sk_hash) | 289 | return (u16) (((u64)skb_get_hash(skb) * qcount) >> 32) + qoffset; |
264 | hash = skb->sk->sk_hash; | ||
265 | else | ||
266 | hash = (__force u16) skb->protocol; | ||
267 | hash = __flow_hash_1word(hash); | ||
268 | |||
269 | return (u16) (((u64) hash * qcount) >> 32) + qoffset; | ||
270 | } | 290 | } |
271 | EXPORT_SYMBOL(__skb_tx_hash); | 291 | EXPORT_SYMBOL(__skb_tx_hash); |
272 | 292 | ||
@@ -338,17 +358,10 @@ static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb) | |||
338 | if (map) { | 358 | if (map) { |
339 | if (map->len == 1) | 359 | if (map->len == 1) |
340 | queue_index = map->queues[0]; | 360 | queue_index = map->queues[0]; |
341 | else { | 361 | else |
342 | u32 hash; | ||
343 | if (skb->sk && skb->sk->sk_hash) | ||
344 | hash = skb->sk->sk_hash; | ||
345 | else | ||
346 | hash = (__force u16) skb->protocol ^ | ||
347 | skb->hash; | ||
348 | hash = __flow_hash_1word(hash); | ||
349 | queue_index = map->queues[ | 362 | queue_index = map->queues[ |
350 | ((u64)hash * map->len) >> 32]; | 363 | ((u64)skb_get_hash(skb) * map->len) >> 32]; |
351 | } | 364 | |
352 | if (unlikely(queue_index >= dev->real_num_tx_queues)) | 365 | if (unlikely(queue_index >= dev->real_num_tx_queues)) |
353 | queue_index = -1; | 366 | queue_index = -1; |
354 | } | 367 | } |
diff --git a/net/core/gen_estimator.c b/net/core/gen_estimator.c index 6b5b6e7013ca..9d33dfffca19 100644 --- a/net/core/gen_estimator.c +++ b/net/core/gen_estimator.c | |||
@@ -197,7 +197,7 @@ struct gen_estimator *gen_find_node(const struct gnet_stats_basic_packed *bstats | |||
197 | * as destination. A new timer with the interval specified in the | 197 | * as destination. A new timer with the interval specified in the |
198 | * configuration TLV is created. Upon each interval, the latest statistics | 198 | * configuration TLV is created. Upon each interval, the latest statistics |
199 | * will be read from &bstats and the estimated rate will be stored in | 199 | * will be read from &bstats and the estimated rate will be stored in |
200 | * &rate_est with the statistics lock grabed during this period. | 200 | * &rate_est with the statistics lock grabbed during this period. |
201 | * | 201 | * |
202 | * Returns 0 on success or a negative error code. | 202 | * Returns 0 on success or a negative error code. |
203 | * | 203 | * |
diff --git a/net/core/gen_stats.c b/net/core/gen_stats.c index 9d3d9e78397b..2ddbce4cce14 100644 --- a/net/core/gen_stats.c +++ b/net/core/gen_stats.c | |||
@@ -206,7 +206,7 @@ EXPORT_SYMBOL(gnet_stats_copy_queue); | |||
206 | * @st: application specific statistics data | 206 | * @st: application specific statistics data |
207 | * @len: length of data | 207 | * @len: length of data |
208 | * | 208 | * |
209 | * Appends the application sepecific statistics to the top level TLV created by | 209 | * Appends the application specific statistics to the top level TLV created by |
210 | * gnet_stats_start_copy() and remembers the data for XSTATS if the dumping | 210 | * gnet_stats_start_copy() and remembers the data for XSTATS if the dumping |
211 | * handle is in backward compatibility mode. | 211 | * handle is in backward compatibility mode. |
212 | * | 212 | * |
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 1cac29ebb05b..9dd06699b09c 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
@@ -43,12 +43,12 @@ static ssize_t netdev_show(const struct device *dev, | |||
43 | struct device_attribute *attr, char *buf, | 43 | struct device_attribute *attr, char *buf, |
44 | ssize_t (*format)(const struct net_device *, char *)) | 44 | ssize_t (*format)(const struct net_device *, char *)) |
45 | { | 45 | { |
46 | struct net_device *net = to_net_dev(dev); | 46 | struct net_device *ndev = to_net_dev(dev); |
47 | ssize_t ret = -EINVAL; | 47 | ssize_t ret = -EINVAL; |
48 | 48 | ||
49 | read_lock(&dev_base_lock); | 49 | read_lock(&dev_base_lock); |
50 | if (dev_isalive(net)) | 50 | if (dev_isalive(ndev)) |
51 | ret = (*format)(net, buf); | 51 | ret = (*format)(ndev, buf); |
52 | read_unlock(&dev_base_lock); | 52 | read_unlock(&dev_base_lock); |
53 | 53 | ||
54 | return ret; | 54 | return ret; |
@@ -56,9 +56,9 @@ static ssize_t netdev_show(const struct device *dev, | |||
56 | 56 | ||
57 | /* generate a show function for simple field */ | 57 | /* generate a show function for simple field */ |
58 | #define NETDEVICE_SHOW(field, format_string) \ | 58 | #define NETDEVICE_SHOW(field, format_string) \ |
59 | static ssize_t format_##field(const struct net_device *net, char *buf) \ | 59 | static ssize_t format_##field(const struct net_device *dev, char *buf) \ |
60 | { \ | 60 | { \ |
61 | return sprintf(buf, format_string, net->field); \ | 61 | return sprintf(buf, format_string, dev->field); \ |
62 | } \ | 62 | } \ |
63 | static ssize_t field##_show(struct device *dev, \ | 63 | static ssize_t field##_show(struct device *dev, \ |
64 | struct device_attribute *attr, char *buf) \ | 64 | struct device_attribute *attr, char *buf) \ |
@@ -112,16 +112,35 @@ NETDEVICE_SHOW_RO(ifindex, fmt_dec); | |||
112 | NETDEVICE_SHOW_RO(type, fmt_dec); | 112 | NETDEVICE_SHOW_RO(type, fmt_dec); |
113 | NETDEVICE_SHOW_RO(link_mode, fmt_dec); | 113 | NETDEVICE_SHOW_RO(link_mode, fmt_dec); |
114 | 114 | ||
115 | static ssize_t format_name_assign_type(const struct net_device *dev, char *buf) | ||
116 | { | ||
117 | return sprintf(buf, fmt_dec, dev->name_assign_type); | ||
118 | } | ||
119 | |||
120 | static ssize_t name_assign_type_show(struct device *dev, | ||
121 | struct device_attribute *attr, | ||
122 | char *buf) | ||
123 | { | ||
124 | struct net_device *ndev = to_net_dev(dev); | ||
125 | ssize_t ret = -EINVAL; | ||
126 | |||
127 | if (ndev->name_assign_type != NET_NAME_UNKNOWN) | ||
128 | ret = netdev_show(dev, attr, buf, format_name_assign_type); | ||
129 | |||
130 | return ret; | ||
131 | } | ||
132 | static DEVICE_ATTR_RO(name_assign_type); | ||
133 | |||
115 | /* use same locking rules as GIFHWADDR ioctl's */ | 134 | /* use same locking rules as GIFHWADDR ioctl's */ |
116 | static ssize_t address_show(struct device *dev, struct device_attribute *attr, | 135 | static ssize_t address_show(struct device *dev, struct device_attribute *attr, |
117 | char *buf) | 136 | char *buf) |
118 | { | 137 | { |
119 | struct net_device *net = to_net_dev(dev); | 138 | struct net_device *ndev = to_net_dev(dev); |
120 | ssize_t ret = -EINVAL; | 139 | ssize_t ret = -EINVAL; |
121 | 140 | ||
122 | read_lock(&dev_base_lock); | 141 | read_lock(&dev_base_lock); |
123 | if (dev_isalive(net)) | 142 | if (dev_isalive(ndev)) |
124 | ret = sysfs_format_mac(buf, net->dev_addr, net->addr_len); | 143 | ret = sysfs_format_mac(buf, ndev->dev_addr, ndev->addr_len); |
125 | read_unlock(&dev_base_lock); | 144 | read_unlock(&dev_base_lock); |
126 | return ret; | 145 | return ret; |
127 | } | 146 | } |
@@ -130,18 +149,18 @@ static DEVICE_ATTR_RO(address); | |||
130 | static ssize_t broadcast_show(struct device *dev, | 149 | static ssize_t broadcast_show(struct device *dev, |
131 | struct device_attribute *attr, char *buf) | 150 | struct device_attribute *attr, char *buf) |
132 | { | 151 | { |
133 | struct net_device *net = to_net_dev(dev); | 152 | struct net_device *ndev = to_net_dev(dev); |
134 | if (dev_isalive(net)) | 153 | if (dev_isalive(ndev)) |
135 | return sysfs_format_mac(buf, net->broadcast, net->addr_len); | 154 | return sysfs_format_mac(buf, ndev->broadcast, ndev->addr_len); |
136 | return -EINVAL; | 155 | return -EINVAL; |
137 | } | 156 | } |
138 | static DEVICE_ATTR_RO(broadcast); | 157 | static DEVICE_ATTR_RO(broadcast); |
139 | 158 | ||
140 | static int change_carrier(struct net_device *net, unsigned long new_carrier) | 159 | static int change_carrier(struct net_device *dev, unsigned long new_carrier) |
141 | { | 160 | { |
142 | if (!netif_running(net)) | 161 | if (!netif_running(dev)) |
143 | return -EINVAL; | 162 | return -EINVAL; |
144 | return dev_change_carrier(net, (bool) new_carrier); | 163 | return dev_change_carrier(dev, (bool) new_carrier); |
145 | } | 164 | } |
146 | 165 | ||
147 | static ssize_t carrier_store(struct device *dev, struct device_attribute *attr, | 166 | static ssize_t carrier_store(struct device *dev, struct device_attribute *attr, |
@@ -265,9 +284,9 @@ static DEVICE_ATTR_RO(carrier_changes); | |||
265 | 284 | ||
266 | /* read-write attributes */ | 285 | /* read-write attributes */ |
267 | 286 | ||
268 | static int change_mtu(struct net_device *net, unsigned long new_mtu) | 287 | static int change_mtu(struct net_device *dev, unsigned long new_mtu) |
269 | { | 288 | { |
270 | return dev_set_mtu(net, (int) new_mtu); | 289 | return dev_set_mtu(dev, (int) new_mtu); |
271 | } | 290 | } |
272 | 291 | ||
273 | static ssize_t mtu_store(struct device *dev, struct device_attribute *attr, | 292 | static ssize_t mtu_store(struct device *dev, struct device_attribute *attr, |
@@ -277,9 +296,9 @@ static ssize_t mtu_store(struct device *dev, struct device_attribute *attr, | |||
277 | } | 296 | } |
278 | NETDEVICE_SHOW_RW(mtu, fmt_dec); | 297 | NETDEVICE_SHOW_RW(mtu, fmt_dec); |
279 | 298 | ||
280 | static int change_flags(struct net_device *net, unsigned long new_flags) | 299 | static int change_flags(struct net_device *dev, unsigned long new_flags) |
281 | { | 300 | { |
282 | return dev_change_flags(net, (unsigned int) new_flags); | 301 | return dev_change_flags(dev, (unsigned int) new_flags); |
283 | } | 302 | } |
284 | 303 | ||
285 | static ssize_t flags_store(struct device *dev, struct device_attribute *attr, | 304 | static ssize_t flags_store(struct device *dev, struct device_attribute *attr, |
@@ -289,9 +308,9 @@ static ssize_t flags_store(struct device *dev, struct device_attribute *attr, | |||
289 | } | 308 | } |
290 | NETDEVICE_SHOW_RW(flags, fmt_hex); | 309 | NETDEVICE_SHOW_RW(flags, fmt_hex); |
291 | 310 | ||
292 | static int change_tx_queue_len(struct net_device *net, unsigned long new_len) | 311 | static int change_tx_queue_len(struct net_device *dev, unsigned long new_len) |
293 | { | 312 | { |
294 | net->tx_queue_len = new_len; | 313 | dev->tx_queue_len = new_len; |
295 | return 0; | 314 | return 0; |
296 | } | 315 | } |
297 | 316 | ||
@@ -344,9 +363,9 @@ static ssize_t ifalias_show(struct device *dev, | |||
344 | } | 363 | } |
345 | static DEVICE_ATTR_RW(ifalias); | 364 | static DEVICE_ATTR_RW(ifalias); |
346 | 365 | ||
347 | static int change_group(struct net_device *net, unsigned long new_group) | 366 | static int change_group(struct net_device *dev, unsigned long new_group) |
348 | { | 367 | { |
349 | dev_set_group(net, (int) new_group); | 368 | dev_set_group(dev, (int) new_group); |
350 | return 0; | 369 | return 0; |
351 | } | 370 | } |
352 | 371 | ||
@@ -387,6 +406,7 @@ static struct attribute *net_class_attrs[] = { | |||
387 | &dev_attr_dev_port.attr, | 406 | &dev_attr_dev_port.attr, |
388 | &dev_attr_iflink.attr, | 407 | &dev_attr_iflink.attr, |
389 | &dev_attr_ifindex.attr, | 408 | &dev_attr_ifindex.attr, |
409 | &dev_attr_name_assign_type.attr, | ||
390 | &dev_attr_addr_assign_type.attr, | 410 | &dev_attr_addr_assign_type.attr, |
391 | &dev_attr_addr_len.attr, | 411 | &dev_attr_addr_len.attr, |
392 | &dev_attr_link_mode.attr, | 412 | &dev_attr_link_mode.attr, |
@@ -776,20 +796,20 @@ static struct kobj_type rx_queue_ktype = { | |||
776 | .namespace = rx_queue_namespace | 796 | .namespace = rx_queue_namespace |
777 | }; | 797 | }; |
778 | 798 | ||
779 | static int rx_queue_add_kobject(struct net_device *net, int index) | 799 | static int rx_queue_add_kobject(struct net_device *dev, int index) |
780 | { | 800 | { |
781 | struct netdev_rx_queue *queue = net->_rx + index; | 801 | struct netdev_rx_queue *queue = dev->_rx + index; |
782 | struct kobject *kobj = &queue->kobj; | 802 | struct kobject *kobj = &queue->kobj; |
783 | int error = 0; | 803 | int error = 0; |
784 | 804 | ||
785 | kobj->kset = net->queues_kset; | 805 | kobj->kset = dev->queues_kset; |
786 | error = kobject_init_and_add(kobj, &rx_queue_ktype, NULL, | 806 | error = kobject_init_and_add(kobj, &rx_queue_ktype, NULL, |
787 | "rx-%u", index); | 807 | "rx-%u", index); |
788 | if (error) | 808 | if (error) |
789 | goto exit; | 809 | goto exit; |
790 | 810 | ||
791 | if (net->sysfs_rx_queue_group) { | 811 | if (dev->sysfs_rx_queue_group) { |
792 | error = sysfs_create_group(kobj, net->sysfs_rx_queue_group); | 812 | error = sysfs_create_group(kobj, dev->sysfs_rx_queue_group); |
793 | if (error) | 813 | if (error) |
794 | goto exit; | 814 | goto exit; |
795 | } | 815 | } |
@@ -805,18 +825,18 @@ exit: | |||
805 | #endif /* CONFIG_SYSFS */ | 825 | #endif /* CONFIG_SYSFS */ |
806 | 826 | ||
807 | int | 827 | int |
808 | net_rx_queue_update_kobjects(struct net_device *net, int old_num, int new_num) | 828 | net_rx_queue_update_kobjects(struct net_device *dev, int old_num, int new_num) |
809 | { | 829 | { |
810 | #ifdef CONFIG_SYSFS | 830 | #ifdef CONFIG_SYSFS |
811 | int i; | 831 | int i; |
812 | int error = 0; | 832 | int error = 0; |
813 | 833 | ||
814 | #ifndef CONFIG_RPS | 834 | #ifndef CONFIG_RPS |
815 | if (!net->sysfs_rx_queue_group) | 835 | if (!dev->sysfs_rx_queue_group) |
816 | return 0; | 836 | return 0; |
817 | #endif | 837 | #endif |
818 | for (i = old_num; i < new_num; i++) { | 838 | for (i = old_num; i < new_num; i++) { |
819 | error = rx_queue_add_kobject(net, i); | 839 | error = rx_queue_add_kobject(dev, i); |
820 | if (error) { | 840 | if (error) { |
821 | new_num = old_num; | 841 | new_num = old_num; |
822 | break; | 842 | break; |
@@ -824,10 +844,10 @@ net_rx_queue_update_kobjects(struct net_device *net, int old_num, int new_num) | |||
824 | } | 844 | } |
825 | 845 | ||
826 | while (--i >= new_num) { | 846 | while (--i >= new_num) { |
827 | if (net->sysfs_rx_queue_group) | 847 | if (dev->sysfs_rx_queue_group) |
828 | sysfs_remove_group(&net->_rx[i].kobj, | 848 | sysfs_remove_group(&dev->_rx[i].kobj, |
829 | net->sysfs_rx_queue_group); | 849 | dev->sysfs_rx_queue_group); |
830 | kobject_put(&net->_rx[i].kobj); | 850 | kobject_put(&dev->_rx[i].kobj); |
831 | } | 851 | } |
832 | 852 | ||
833 | return error; | 853 | return error; |
@@ -1135,13 +1155,13 @@ static struct kobj_type netdev_queue_ktype = { | |||
1135 | .namespace = netdev_queue_namespace, | 1155 | .namespace = netdev_queue_namespace, |
1136 | }; | 1156 | }; |
1137 | 1157 | ||
1138 | static int netdev_queue_add_kobject(struct net_device *net, int index) | 1158 | static int netdev_queue_add_kobject(struct net_device *dev, int index) |
1139 | { | 1159 | { |
1140 | struct netdev_queue *queue = net->_tx + index; | 1160 | struct netdev_queue *queue = dev->_tx + index; |
1141 | struct kobject *kobj = &queue->kobj; | 1161 | struct kobject *kobj = &queue->kobj; |
1142 | int error = 0; | 1162 | int error = 0; |
1143 | 1163 | ||
1144 | kobj->kset = net->queues_kset; | 1164 | kobj->kset = dev->queues_kset; |
1145 | error = kobject_init_and_add(kobj, &netdev_queue_ktype, NULL, | 1165 | error = kobject_init_and_add(kobj, &netdev_queue_ktype, NULL, |
1146 | "tx-%u", index); | 1166 | "tx-%u", index); |
1147 | if (error) | 1167 | if (error) |
@@ -1164,14 +1184,14 @@ exit: | |||
1164 | #endif /* CONFIG_SYSFS */ | 1184 | #endif /* CONFIG_SYSFS */ |
1165 | 1185 | ||
1166 | int | 1186 | int |
1167 | netdev_queue_update_kobjects(struct net_device *net, int old_num, int new_num) | 1187 | netdev_queue_update_kobjects(struct net_device *dev, int old_num, int new_num) |
1168 | { | 1188 | { |
1169 | #ifdef CONFIG_SYSFS | 1189 | #ifdef CONFIG_SYSFS |
1170 | int i; | 1190 | int i; |
1171 | int error = 0; | 1191 | int error = 0; |
1172 | 1192 | ||
1173 | for (i = old_num; i < new_num; i++) { | 1193 | for (i = old_num; i < new_num; i++) { |
1174 | error = netdev_queue_add_kobject(net, i); | 1194 | error = netdev_queue_add_kobject(dev, i); |
1175 | if (error) { | 1195 | if (error) { |
1176 | new_num = old_num; | 1196 | new_num = old_num; |
1177 | break; | 1197 | break; |
@@ -1179,7 +1199,7 @@ netdev_queue_update_kobjects(struct net_device *net, int old_num, int new_num) | |||
1179 | } | 1199 | } |
1180 | 1200 | ||
1181 | while (--i >= new_num) { | 1201 | while (--i >= new_num) { |
1182 | struct netdev_queue *queue = net->_tx + i; | 1202 | struct netdev_queue *queue = dev->_tx + i; |
1183 | 1203 | ||
1184 | #ifdef CONFIG_BQL | 1204 | #ifdef CONFIG_BQL |
1185 | sysfs_remove_group(&queue->kobj, &dql_group); | 1205 | sysfs_remove_group(&queue->kobj, &dql_group); |
@@ -1193,25 +1213,25 @@ netdev_queue_update_kobjects(struct net_device *net, int old_num, int new_num) | |||
1193 | #endif /* CONFIG_SYSFS */ | 1213 | #endif /* CONFIG_SYSFS */ |
1194 | } | 1214 | } |
1195 | 1215 | ||
1196 | static int register_queue_kobjects(struct net_device *net) | 1216 | static int register_queue_kobjects(struct net_device *dev) |
1197 | { | 1217 | { |
1198 | int error = 0, txq = 0, rxq = 0, real_rx = 0, real_tx = 0; | 1218 | int error = 0, txq = 0, rxq = 0, real_rx = 0, real_tx = 0; |
1199 | 1219 | ||
1200 | #ifdef CONFIG_SYSFS | 1220 | #ifdef CONFIG_SYSFS |
1201 | net->queues_kset = kset_create_and_add("queues", | 1221 | dev->queues_kset = kset_create_and_add("queues", |
1202 | NULL, &net->dev.kobj); | 1222 | NULL, &dev->dev.kobj); |
1203 | if (!net->queues_kset) | 1223 | if (!dev->queues_kset) |
1204 | return -ENOMEM; | 1224 | return -ENOMEM; |
1205 | real_rx = net->real_num_rx_queues; | 1225 | real_rx = dev->real_num_rx_queues; |
1206 | #endif | 1226 | #endif |
1207 | real_tx = net->real_num_tx_queues; | 1227 | real_tx = dev->real_num_tx_queues; |
1208 | 1228 | ||
1209 | error = net_rx_queue_update_kobjects(net, 0, real_rx); | 1229 | error = net_rx_queue_update_kobjects(dev, 0, real_rx); |
1210 | if (error) | 1230 | if (error) |
1211 | goto error; | 1231 | goto error; |
1212 | rxq = real_rx; | 1232 | rxq = real_rx; |
1213 | 1233 | ||
1214 | error = netdev_queue_update_kobjects(net, 0, real_tx); | 1234 | error = netdev_queue_update_kobjects(dev, 0, real_tx); |
1215 | if (error) | 1235 | if (error) |
1216 | goto error; | 1236 | goto error; |
1217 | txq = real_tx; | 1237 | txq = real_tx; |
@@ -1219,24 +1239,24 @@ static int register_queue_kobjects(struct net_device *net) | |||
1219 | return 0; | 1239 | return 0; |
1220 | 1240 | ||
1221 | error: | 1241 | error: |
1222 | netdev_queue_update_kobjects(net, txq, 0); | 1242 | netdev_queue_update_kobjects(dev, txq, 0); |
1223 | net_rx_queue_update_kobjects(net, rxq, 0); | 1243 | net_rx_queue_update_kobjects(dev, rxq, 0); |
1224 | return error; | 1244 | return error; |
1225 | } | 1245 | } |
1226 | 1246 | ||
1227 | static void remove_queue_kobjects(struct net_device *net) | 1247 | static void remove_queue_kobjects(struct net_device *dev) |
1228 | { | 1248 | { |
1229 | int real_rx = 0, real_tx = 0; | 1249 | int real_rx = 0, real_tx = 0; |
1230 | 1250 | ||
1231 | #ifdef CONFIG_SYSFS | 1251 | #ifdef CONFIG_SYSFS |
1232 | real_rx = net->real_num_rx_queues; | 1252 | real_rx = dev->real_num_rx_queues; |
1233 | #endif | 1253 | #endif |
1234 | real_tx = net->real_num_tx_queues; | 1254 | real_tx = dev->real_num_tx_queues; |
1235 | 1255 | ||
1236 | net_rx_queue_update_kobjects(net, real_rx, 0); | 1256 | net_rx_queue_update_kobjects(dev, real_rx, 0); |
1237 | netdev_queue_update_kobjects(net, real_tx, 0); | 1257 | netdev_queue_update_kobjects(dev, real_tx, 0); |
1238 | #ifdef CONFIG_SYSFS | 1258 | #ifdef CONFIG_SYSFS |
1239 | kset_unregister(net->queues_kset); | 1259 | kset_unregister(dev->queues_kset); |
1240 | #endif | 1260 | #endif |
1241 | } | 1261 | } |
1242 | 1262 | ||
@@ -1329,13 +1349,13 @@ static struct class net_class = { | |||
1329 | /* Delete sysfs entries but hold kobject reference until after all | 1349 | /* Delete sysfs entries but hold kobject reference until after all |
1330 | * netdev references are gone. | 1350 | * netdev references are gone. |
1331 | */ | 1351 | */ |
1332 | void netdev_unregister_kobject(struct net_device * net) | 1352 | void netdev_unregister_kobject(struct net_device *ndev) |
1333 | { | 1353 | { |
1334 | struct device *dev = &(net->dev); | 1354 | struct device *dev = &(ndev->dev); |
1335 | 1355 | ||
1336 | kobject_get(&dev->kobj); | 1356 | kobject_get(&dev->kobj); |
1337 | 1357 | ||
1338 | remove_queue_kobjects(net); | 1358 | remove_queue_kobjects(ndev); |
1339 | 1359 | ||
1340 | pm_runtime_set_memalloc_noio(dev, false); | 1360 | pm_runtime_set_memalloc_noio(dev, false); |
1341 | 1361 | ||
@@ -1343,18 +1363,18 @@ void netdev_unregister_kobject(struct net_device * net) | |||
1343 | } | 1363 | } |
1344 | 1364 | ||
1345 | /* Create sysfs entries for network device. */ | 1365 | /* Create sysfs entries for network device. */ |
1346 | int netdev_register_kobject(struct net_device *net) | 1366 | int netdev_register_kobject(struct net_device *ndev) |
1347 | { | 1367 | { |
1348 | struct device *dev = &(net->dev); | 1368 | struct device *dev = &(ndev->dev); |
1349 | const struct attribute_group **groups = net->sysfs_groups; | 1369 | const struct attribute_group **groups = ndev->sysfs_groups; |
1350 | int error = 0; | 1370 | int error = 0; |
1351 | 1371 | ||
1352 | device_initialize(dev); | 1372 | device_initialize(dev); |
1353 | dev->class = &net_class; | 1373 | dev->class = &net_class; |
1354 | dev->platform_data = net; | 1374 | dev->platform_data = ndev; |
1355 | dev->groups = groups; | 1375 | dev->groups = groups; |
1356 | 1376 | ||
1357 | dev_set_name(dev, "%s", net->name); | 1377 | dev_set_name(dev, "%s", ndev->name); |
1358 | 1378 | ||
1359 | #ifdef CONFIG_SYSFS | 1379 | #ifdef CONFIG_SYSFS |
1360 | /* Allow for a device specific group */ | 1380 | /* Allow for a device specific group */ |
@@ -1364,10 +1384,10 @@ int netdev_register_kobject(struct net_device *net) | |||
1364 | *groups++ = &netstat_group; | 1384 | *groups++ = &netstat_group; |
1365 | 1385 | ||
1366 | #if IS_ENABLED(CONFIG_WIRELESS_EXT) || IS_ENABLED(CONFIG_CFG80211) | 1386 | #if IS_ENABLED(CONFIG_WIRELESS_EXT) || IS_ENABLED(CONFIG_CFG80211) |
1367 | if (net->ieee80211_ptr) | 1387 | if (ndev->ieee80211_ptr) |
1368 | *groups++ = &wireless_group; | 1388 | *groups++ = &wireless_group; |
1369 | #if IS_ENABLED(CONFIG_WIRELESS_EXT) | 1389 | #if IS_ENABLED(CONFIG_WIRELESS_EXT) |
1370 | else if (net->wireless_handlers) | 1390 | else if (ndev->wireless_handlers) |
1371 | *groups++ = &wireless_group; | 1391 | *groups++ = &wireless_group; |
1372 | #endif | 1392 | #endif |
1373 | #endif | 1393 | #endif |
@@ -1377,7 +1397,7 @@ int netdev_register_kobject(struct net_device *net) | |||
1377 | if (error) | 1397 | if (error) |
1378 | return error; | 1398 | return error; |
1379 | 1399 | ||
1380 | error = register_queue_kobjects(net); | 1400 | error = register_queue_kobjects(ndev); |
1381 | if (error) { | 1401 | if (error) { |
1382 | device_del(dev); | 1402 | device_del(dev); |
1383 | return error; | 1403 | return error; |
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c index 85b62691f4f2..7c6b51a58968 100644 --- a/net/core/net_namespace.c +++ b/net/core/net_namespace.c | |||
@@ -373,9 +373,11 @@ struct net *get_net_ns_by_pid(pid_t pid) | |||
373 | tsk = find_task_by_vpid(pid); | 373 | tsk = find_task_by_vpid(pid); |
374 | if (tsk) { | 374 | if (tsk) { |
375 | struct nsproxy *nsproxy; | 375 | struct nsproxy *nsproxy; |
376 | nsproxy = task_nsproxy(tsk); | 376 | task_lock(tsk); |
377 | nsproxy = tsk->nsproxy; | ||
377 | if (nsproxy) | 378 | if (nsproxy) |
378 | net = get_net(nsproxy->net_ns); | 379 | net = get_net(nsproxy->net_ns); |
380 | task_unlock(tsk); | ||
379 | } | 381 | } |
380 | rcu_read_unlock(); | 382 | rcu_read_unlock(); |
381 | return net; | 383 | return net; |
@@ -632,11 +634,11 @@ static void *netns_get(struct task_struct *task) | |||
632 | struct net *net = NULL; | 634 | struct net *net = NULL; |
633 | struct nsproxy *nsproxy; | 635 | struct nsproxy *nsproxy; |
634 | 636 | ||
635 | rcu_read_lock(); | 637 | task_lock(task); |
636 | nsproxy = task_nsproxy(task); | 638 | nsproxy = task->nsproxy; |
637 | if (nsproxy) | 639 | if (nsproxy) |
638 | net = get_net(nsproxy->net_ns); | 640 | net = get_net(nsproxy->net_ns); |
639 | rcu_read_unlock(); | 641 | task_unlock(task); |
640 | 642 | ||
641 | return net; | 643 | return net; |
642 | } | 644 | } |
diff --git a/net/core/netclassid_cgroup.c b/net/core/netclassid_cgroup.c index 30d903b19c62..1f2a126f4ffa 100644 --- a/net/core/netclassid_cgroup.c +++ b/net/core/netclassid_cgroup.c | |||
@@ -107,5 +107,5 @@ struct cgroup_subsys net_cls_cgrp_subsys = { | |||
107 | .css_online = cgrp_css_online, | 107 | .css_online = cgrp_css_online, |
108 | .css_free = cgrp_css_free, | 108 | .css_free = cgrp_css_free, |
109 | .attach = cgrp_attach, | 109 | .attach = cgrp_attach, |
110 | .base_cftypes = ss_files, | 110 | .legacy_cftypes = ss_files, |
111 | }; | 111 | }; |
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index e33937fb32a0..907fb5e36c02 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
@@ -822,7 +822,8 @@ void __netpoll_cleanup(struct netpoll *np) | |||
822 | 822 | ||
823 | RCU_INIT_POINTER(np->dev->npinfo, NULL); | 823 | RCU_INIT_POINTER(np->dev->npinfo, NULL); |
824 | call_rcu_bh(&npinfo->rcu, rcu_cleanup_netpoll_info); | 824 | call_rcu_bh(&npinfo->rcu, rcu_cleanup_netpoll_info); |
825 | } | 825 | } else |
826 | RCU_INIT_POINTER(np->dev->npinfo, NULL); | ||
826 | } | 827 | } |
827 | EXPORT_SYMBOL_GPL(__netpoll_cleanup); | 828 | EXPORT_SYMBOL_GPL(__netpoll_cleanup); |
828 | 829 | ||
diff --git a/net/core/netprio_cgroup.c b/net/core/netprio_cgroup.c index 2f385b9bccc0..cbd0a199bf52 100644 --- a/net/core/netprio_cgroup.c +++ b/net/core/netprio_cgroup.c | |||
@@ -249,7 +249,7 @@ struct cgroup_subsys net_prio_cgrp_subsys = { | |||
249 | .css_online = cgrp_css_online, | 249 | .css_online = cgrp_css_online, |
250 | .css_free = cgrp_css_free, | 250 | .css_free = cgrp_css_free, |
251 | .attach = net_prio_attach, | 251 | .attach = net_prio_attach, |
252 | .base_cftypes = ss_files, | 252 | .legacy_cftypes = ss_files, |
253 | }; | 253 | }; |
254 | 254 | ||
255 | static int netprio_device_event(struct notifier_block *unused, | 255 | static int netprio_device_event(struct notifier_block *unused, |
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index fc17a9d309ac..8b849ddfef2e 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c | |||
@@ -69,8 +69,9 @@ | |||
69 | * for running devices in the if_list and sends packets until count is 0 it | 69 | * for running devices in the if_list and sends packets until count is 0 it |
70 | * also the thread checks the thread->control which is used for inter-process | 70 | * also the thread checks the thread->control which is used for inter-process |
71 | * communication. controlling process "posts" operations to the threads this | 71 | * communication. controlling process "posts" operations to the threads this |
72 | * way. The if_lock should be possible to remove when add/rem_device is merged | 72 | * way. |
73 | * into this too. | 73 | * The if_list is RCU protected, and the if_lock remains to protect updating |
74 | * of if_list, from "add_device" as it invoked from userspace (via proc write). | ||
74 | * | 75 | * |
75 | * By design there should only be *one* "controlling" process. In practice | 76 | * By design there should only be *one* "controlling" process. In practice |
76 | * multiple write accesses gives unpredictable result. Understood by "write" | 77 | * multiple write accesses gives unpredictable result. Understood by "write" |
@@ -208,7 +209,7 @@ | |||
208 | #define T_REMDEVALL (1<<2) /* Remove all devs */ | 209 | #define T_REMDEVALL (1<<2) /* Remove all devs */ |
209 | #define T_REMDEV (1<<3) /* Remove one dev */ | 210 | #define T_REMDEV (1<<3) /* Remove one dev */ |
210 | 211 | ||
211 | /* If lock -- can be removed after some work */ | 212 | /* If lock -- protects updating of if_list */ |
212 | #define if_lock(t) spin_lock(&(t->if_lock)); | 213 | #define if_lock(t) spin_lock(&(t->if_lock)); |
213 | #define if_unlock(t) spin_unlock(&(t->if_lock)); | 214 | #define if_unlock(t) spin_unlock(&(t->if_lock)); |
214 | 215 | ||
@@ -241,6 +242,7 @@ struct pktgen_dev { | |||
241 | struct proc_dir_entry *entry; /* proc file */ | 242 | struct proc_dir_entry *entry; /* proc file */ |
242 | struct pktgen_thread *pg_thread;/* the owner */ | 243 | struct pktgen_thread *pg_thread;/* the owner */ |
243 | struct list_head list; /* chaining in the thread's run-queue */ | 244 | struct list_head list; /* chaining in the thread's run-queue */ |
245 | struct rcu_head rcu; /* freed by RCU */ | ||
244 | 246 | ||
245 | int running; /* if false, the test will stop */ | 247 | int running; /* if false, the test will stop */ |
246 | 248 | ||
@@ -802,7 +804,6 @@ static int strn_len(const char __user * user_buffer, unsigned int maxlen) | |||
802 | case '\t': | 804 | case '\t': |
803 | case ' ': | 805 | case ' ': |
804 | goto done_str; | 806 | goto done_str; |
805 | break; | ||
806 | default: | 807 | default: |
807 | break; | 808 | break; |
808 | } | 809 | } |
@@ -1737,14 +1738,14 @@ static int pktgen_thread_show(struct seq_file *seq, void *v) | |||
1737 | 1738 | ||
1738 | seq_puts(seq, "Running: "); | 1739 | seq_puts(seq, "Running: "); |
1739 | 1740 | ||
1740 | if_lock(t); | 1741 | rcu_read_lock(); |
1741 | list_for_each_entry(pkt_dev, &t->if_list, list) | 1742 | list_for_each_entry_rcu(pkt_dev, &t->if_list, list) |
1742 | if (pkt_dev->running) | 1743 | if (pkt_dev->running) |
1743 | seq_printf(seq, "%s ", pkt_dev->odevname); | 1744 | seq_printf(seq, "%s ", pkt_dev->odevname); |
1744 | 1745 | ||
1745 | seq_puts(seq, "\nStopped: "); | 1746 | seq_puts(seq, "\nStopped: "); |
1746 | 1747 | ||
1747 | list_for_each_entry(pkt_dev, &t->if_list, list) | 1748 | list_for_each_entry_rcu(pkt_dev, &t->if_list, list) |
1748 | if (!pkt_dev->running) | 1749 | if (!pkt_dev->running) |
1749 | seq_printf(seq, "%s ", pkt_dev->odevname); | 1750 | seq_printf(seq, "%s ", pkt_dev->odevname); |
1750 | 1751 | ||
@@ -1753,7 +1754,7 @@ static int pktgen_thread_show(struct seq_file *seq, void *v) | |||
1753 | else | 1754 | else |
1754 | seq_puts(seq, "\nResult: NA\n"); | 1755 | seq_puts(seq, "\nResult: NA\n"); |
1755 | 1756 | ||
1756 | if_unlock(t); | 1757 | rcu_read_unlock(); |
1757 | 1758 | ||
1758 | return 0; | 1759 | return 0; |
1759 | } | 1760 | } |
@@ -1878,10 +1879,8 @@ static struct pktgen_dev *__pktgen_NN_threads(const struct pktgen_net *pn, | |||
1878 | pkt_dev = pktgen_find_dev(t, ifname, exact); | 1879 | pkt_dev = pktgen_find_dev(t, ifname, exact); |
1879 | if (pkt_dev) { | 1880 | if (pkt_dev) { |
1880 | if (remove) { | 1881 | if (remove) { |
1881 | if_lock(t); | ||
1882 | pkt_dev->removal_mark = 1; | 1882 | pkt_dev->removal_mark = 1; |
1883 | t->control |= T_REMDEV; | 1883 | t->control |= T_REMDEV; |
1884 | if_unlock(t); | ||
1885 | } | 1884 | } |
1886 | break; | 1885 | break; |
1887 | } | 1886 | } |
@@ -1931,7 +1930,8 @@ static void pktgen_change_name(const struct pktgen_net *pn, struct net_device *d | |||
1931 | list_for_each_entry(t, &pn->pktgen_threads, th_list) { | 1930 | list_for_each_entry(t, &pn->pktgen_threads, th_list) { |
1932 | struct pktgen_dev *pkt_dev; | 1931 | struct pktgen_dev *pkt_dev; |
1933 | 1932 | ||
1934 | list_for_each_entry(pkt_dev, &t->if_list, list) { | 1933 | rcu_read_lock(); |
1934 | list_for_each_entry_rcu(pkt_dev, &t->if_list, list) { | ||
1935 | if (pkt_dev->odev != dev) | 1935 | if (pkt_dev->odev != dev) |
1936 | continue; | 1936 | continue; |
1937 | 1937 | ||
@@ -1946,6 +1946,7 @@ static void pktgen_change_name(const struct pktgen_net *pn, struct net_device *d | |||
1946 | dev->name); | 1946 | dev->name); |
1947 | break; | 1947 | break; |
1948 | } | 1948 | } |
1949 | rcu_read_unlock(); | ||
1949 | } | 1950 | } |
1950 | } | 1951 | } |
1951 | 1952 | ||
@@ -2997,8 +2998,8 @@ static void pktgen_run(struct pktgen_thread *t) | |||
2997 | 2998 | ||
2998 | func_enter(); | 2999 | func_enter(); |
2999 | 3000 | ||
3000 | if_lock(t); | 3001 | rcu_read_lock(); |
3001 | list_for_each_entry(pkt_dev, &t->if_list, list) { | 3002 | list_for_each_entry_rcu(pkt_dev, &t->if_list, list) { |
3002 | 3003 | ||
3003 | /* | 3004 | /* |
3004 | * setup odev and create initial packet. | 3005 | * setup odev and create initial packet. |
@@ -3007,18 +3008,18 @@ static void pktgen_run(struct pktgen_thread *t) | |||
3007 | 3008 | ||
3008 | if (pkt_dev->odev) { | 3009 | if (pkt_dev->odev) { |
3009 | pktgen_clear_counters(pkt_dev); | 3010 | pktgen_clear_counters(pkt_dev); |
3010 | pkt_dev->running = 1; /* Cranke yeself! */ | ||
3011 | pkt_dev->skb = NULL; | 3011 | pkt_dev->skb = NULL; |
3012 | pkt_dev->started_at = pkt_dev->next_tx = ktime_get(); | 3012 | pkt_dev->started_at = pkt_dev->next_tx = ktime_get(); |
3013 | 3013 | ||
3014 | set_pkt_overhead(pkt_dev); | 3014 | set_pkt_overhead(pkt_dev); |
3015 | 3015 | ||
3016 | strcpy(pkt_dev->result, "Starting"); | 3016 | strcpy(pkt_dev->result, "Starting"); |
3017 | pkt_dev->running = 1; /* Cranke yeself! */ | ||
3017 | started++; | 3018 | started++; |
3018 | } else | 3019 | } else |
3019 | strcpy(pkt_dev->result, "Error starting"); | 3020 | strcpy(pkt_dev->result, "Error starting"); |
3020 | } | 3021 | } |
3021 | if_unlock(t); | 3022 | rcu_read_unlock(); |
3022 | if (started) | 3023 | if (started) |
3023 | t->control &= ~(T_STOP); | 3024 | t->control &= ~(T_STOP); |
3024 | } | 3025 | } |
@@ -3041,27 +3042,25 @@ static int thread_is_running(const struct pktgen_thread *t) | |||
3041 | { | 3042 | { |
3042 | const struct pktgen_dev *pkt_dev; | 3043 | const struct pktgen_dev *pkt_dev; |
3043 | 3044 | ||
3044 | list_for_each_entry(pkt_dev, &t->if_list, list) | 3045 | rcu_read_lock(); |
3045 | if (pkt_dev->running) | 3046 | list_for_each_entry_rcu(pkt_dev, &t->if_list, list) |
3047 | if (pkt_dev->running) { | ||
3048 | rcu_read_unlock(); | ||
3046 | return 1; | 3049 | return 1; |
3050 | } | ||
3051 | rcu_read_unlock(); | ||
3047 | return 0; | 3052 | return 0; |
3048 | } | 3053 | } |
3049 | 3054 | ||
3050 | static int pktgen_wait_thread_run(struct pktgen_thread *t) | 3055 | static int pktgen_wait_thread_run(struct pktgen_thread *t) |
3051 | { | 3056 | { |
3052 | if_lock(t); | ||
3053 | |||
3054 | while (thread_is_running(t)) { | 3057 | while (thread_is_running(t)) { |
3055 | 3058 | ||
3056 | if_unlock(t); | ||
3057 | |||
3058 | msleep_interruptible(100); | 3059 | msleep_interruptible(100); |
3059 | 3060 | ||
3060 | if (signal_pending(current)) | 3061 | if (signal_pending(current)) |
3061 | goto signal; | 3062 | goto signal; |
3062 | if_lock(t); | ||
3063 | } | 3063 | } |
3064 | if_unlock(t); | ||
3065 | return 1; | 3064 | return 1; |
3066 | signal: | 3065 | signal: |
3067 | return 0; | 3066 | return 0; |
@@ -3166,10 +3165,10 @@ static int pktgen_stop_device(struct pktgen_dev *pkt_dev) | |||
3166 | return -EINVAL; | 3165 | return -EINVAL; |
3167 | } | 3166 | } |
3168 | 3167 | ||
3168 | pkt_dev->running = 0; | ||
3169 | kfree_skb(pkt_dev->skb); | 3169 | kfree_skb(pkt_dev->skb); |
3170 | pkt_dev->skb = NULL; | 3170 | pkt_dev->skb = NULL; |
3171 | pkt_dev->stopped_at = ktime_get(); | 3171 | pkt_dev->stopped_at = ktime_get(); |
3172 | pkt_dev->running = 0; | ||
3173 | 3172 | ||
3174 | show_results(pkt_dev, nr_frags); | 3173 | show_results(pkt_dev, nr_frags); |
3175 | 3174 | ||
@@ -3180,9 +3179,8 @@ static struct pktgen_dev *next_to_run(struct pktgen_thread *t) | |||
3180 | { | 3179 | { |
3181 | struct pktgen_dev *pkt_dev, *best = NULL; | 3180 | struct pktgen_dev *pkt_dev, *best = NULL; |
3182 | 3181 | ||
3183 | if_lock(t); | 3182 | rcu_read_lock(); |
3184 | 3183 | list_for_each_entry_rcu(pkt_dev, &t->if_list, list) { | |
3185 | list_for_each_entry(pkt_dev, &t->if_list, list) { | ||
3186 | if (!pkt_dev->running) | 3184 | if (!pkt_dev->running) |
3187 | continue; | 3185 | continue; |
3188 | if (best == NULL) | 3186 | if (best == NULL) |
@@ -3190,7 +3188,8 @@ static struct pktgen_dev *next_to_run(struct pktgen_thread *t) | |||
3190 | else if (ktime_compare(pkt_dev->next_tx, best->next_tx) < 0) | 3188 | else if (ktime_compare(pkt_dev->next_tx, best->next_tx) < 0) |
3191 | best = pkt_dev; | 3189 | best = pkt_dev; |
3192 | } | 3190 | } |
3193 | if_unlock(t); | 3191 | rcu_read_unlock(); |
3192 | |||
3194 | return best; | 3193 | return best; |
3195 | } | 3194 | } |
3196 | 3195 | ||
@@ -3200,13 +3199,13 @@ static void pktgen_stop(struct pktgen_thread *t) | |||
3200 | 3199 | ||
3201 | func_enter(); | 3200 | func_enter(); |
3202 | 3201 | ||
3203 | if_lock(t); | 3202 | rcu_read_lock(); |
3204 | 3203 | ||
3205 | list_for_each_entry(pkt_dev, &t->if_list, list) { | 3204 | list_for_each_entry_rcu(pkt_dev, &t->if_list, list) { |
3206 | pktgen_stop_device(pkt_dev); | 3205 | pktgen_stop_device(pkt_dev); |
3207 | } | 3206 | } |
3208 | 3207 | ||
3209 | if_unlock(t); | 3208 | rcu_read_unlock(); |
3210 | } | 3209 | } |
3211 | 3210 | ||
3212 | /* | 3211 | /* |
@@ -3220,8 +3219,6 @@ static void pktgen_rem_one_if(struct pktgen_thread *t) | |||
3220 | 3219 | ||
3221 | func_enter(); | 3220 | func_enter(); |
3222 | 3221 | ||
3223 | if_lock(t); | ||
3224 | |||
3225 | list_for_each_safe(q, n, &t->if_list) { | 3222 | list_for_each_safe(q, n, &t->if_list) { |
3226 | cur = list_entry(q, struct pktgen_dev, list); | 3223 | cur = list_entry(q, struct pktgen_dev, list); |
3227 | 3224 | ||
@@ -3235,8 +3232,6 @@ static void pktgen_rem_one_if(struct pktgen_thread *t) | |||
3235 | 3232 | ||
3236 | break; | 3233 | break; |
3237 | } | 3234 | } |
3238 | |||
3239 | if_unlock(t); | ||
3240 | } | 3235 | } |
3241 | 3236 | ||
3242 | static void pktgen_rem_all_ifs(struct pktgen_thread *t) | 3237 | static void pktgen_rem_all_ifs(struct pktgen_thread *t) |
@@ -3248,8 +3243,6 @@ static void pktgen_rem_all_ifs(struct pktgen_thread *t) | |||
3248 | 3243 | ||
3249 | /* Remove all devices, free mem */ | 3244 | /* Remove all devices, free mem */ |
3250 | 3245 | ||
3251 | if_lock(t); | ||
3252 | |||
3253 | list_for_each_safe(q, n, &t->if_list) { | 3246 | list_for_each_safe(q, n, &t->if_list) { |
3254 | cur = list_entry(q, struct pktgen_dev, list); | 3247 | cur = list_entry(q, struct pktgen_dev, list); |
3255 | 3248 | ||
@@ -3258,8 +3251,6 @@ static void pktgen_rem_all_ifs(struct pktgen_thread *t) | |||
3258 | 3251 | ||
3259 | pktgen_remove_device(t, cur); | 3252 | pktgen_remove_device(t, cur); |
3260 | } | 3253 | } |
3261 | |||
3262 | if_unlock(t); | ||
3263 | } | 3254 | } |
3264 | 3255 | ||
3265 | static void pktgen_rem_thread(struct pktgen_thread *t) | 3256 | static void pktgen_rem_thread(struct pktgen_thread *t) |
@@ -3407,10 +3398,10 @@ static int pktgen_thread_worker(void *arg) | |||
3407 | 3398 | ||
3408 | pr_debug("starting pktgen/%d: pid=%d\n", cpu, task_pid_nr(current)); | 3399 | pr_debug("starting pktgen/%d: pid=%d\n", cpu, task_pid_nr(current)); |
3409 | 3400 | ||
3410 | set_current_state(TASK_INTERRUPTIBLE); | ||
3411 | |||
3412 | set_freezable(); | 3401 | set_freezable(); |
3413 | 3402 | ||
3403 | __set_current_state(TASK_RUNNING); | ||
3404 | |||
3414 | while (!kthread_should_stop()) { | 3405 | while (!kthread_should_stop()) { |
3415 | pkt_dev = next_to_run(t); | 3406 | pkt_dev = next_to_run(t); |
3416 | 3407 | ||
@@ -3424,8 +3415,6 @@ static int pktgen_thread_worker(void *arg) | |||
3424 | continue; | 3415 | continue; |
3425 | } | 3416 | } |
3426 | 3417 | ||
3427 | __set_current_state(TASK_RUNNING); | ||
3428 | |||
3429 | if (likely(pkt_dev)) { | 3418 | if (likely(pkt_dev)) { |
3430 | pktgen_xmit(pkt_dev); | 3419 | pktgen_xmit(pkt_dev); |
3431 | 3420 | ||
@@ -3456,9 +3445,8 @@ static int pktgen_thread_worker(void *arg) | |||
3456 | } | 3445 | } |
3457 | 3446 | ||
3458 | try_to_freeze(); | 3447 | try_to_freeze(); |
3459 | |||
3460 | set_current_state(TASK_INTERRUPTIBLE); | ||
3461 | } | 3448 | } |
3449 | set_current_state(TASK_INTERRUPTIBLE); | ||
3462 | 3450 | ||
3463 | pr_debug("%s stopping all device\n", t->tsk->comm); | 3451 | pr_debug("%s stopping all device\n", t->tsk->comm); |
3464 | pktgen_stop(t); | 3452 | pktgen_stop(t); |
@@ -3485,8 +3473,8 @@ static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread *t, | |||
3485 | struct pktgen_dev *p, *pkt_dev = NULL; | 3473 | struct pktgen_dev *p, *pkt_dev = NULL; |
3486 | size_t len = strlen(ifname); | 3474 | size_t len = strlen(ifname); |
3487 | 3475 | ||
3488 | if_lock(t); | 3476 | rcu_read_lock(); |
3489 | list_for_each_entry(p, &t->if_list, list) | 3477 | list_for_each_entry_rcu(p, &t->if_list, list) |
3490 | if (strncmp(p->odevname, ifname, len) == 0) { | 3478 | if (strncmp(p->odevname, ifname, len) == 0) { |
3491 | if (p->odevname[len]) { | 3479 | if (p->odevname[len]) { |
3492 | if (exact || p->odevname[len] != '@') | 3480 | if (exact || p->odevname[len] != '@') |
@@ -3496,7 +3484,7 @@ static struct pktgen_dev *pktgen_find_dev(struct pktgen_thread *t, | |||
3496 | break; | 3484 | break; |
3497 | } | 3485 | } |
3498 | 3486 | ||
3499 | if_unlock(t); | 3487 | rcu_read_unlock(); |
3500 | pr_debug("find_dev(%s) returning %p\n", ifname, pkt_dev); | 3488 | pr_debug("find_dev(%s) returning %p\n", ifname, pkt_dev); |
3501 | return pkt_dev; | 3489 | return pkt_dev; |
3502 | } | 3490 | } |
@@ -3510,6 +3498,12 @@ static int add_dev_to_thread(struct pktgen_thread *t, | |||
3510 | { | 3498 | { |
3511 | int rv = 0; | 3499 | int rv = 0; |
3512 | 3500 | ||
3501 | /* This function cannot be called concurrently, as its called | ||
3502 | * under pktgen_thread_lock mutex, but it can run from | ||
3503 | * userspace on another CPU than the kthread. The if_lock() | ||
3504 | * is used here to sync with concurrent instances of | ||
3505 | * _rem_dev_from_if_list() invoked via kthread, which is also | ||
3506 | * updating the if_list */ | ||
3513 | if_lock(t); | 3507 | if_lock(t); |
3514 | 3508 | ||
3515 | if (pkt_dev->pg_thread) { | 3509 | if (pkt_dev->pg_thread) { |
@@ -3518,9 +3512,9 @@ static int add_dev_to_thread(struct pktgen_thread *t, | |||
3518 | goto out; | 3512 | goto out; |
3519 | } | 3513 | } |
3520 | 3514 | ||
3521 | list_add(&pkt_dev->list, &t->if_list); | ||
3522 | pkt_dev->pg_thread = t; | ||
3523 | pkt_dev->running = 0; | 3515 | pkt_dev->running = 0; |
3516 | pkt_dev->pg_thread = t; | ||
3517 | list_add_rcu(&pkt_dev->list, &t->if_list); | ||
3524 | 3518 | ||
3525 | out: | 3519 | out: |
3526 | if_unlock(t); | 3520 | if_unlock(t); |
@@ -3675,11 +3669,13 @@ static void _rem_dev_from_if_list(struct pktgen_thread *t, | |||
3675 | struct list_head *q, *n; | 3669 | struct list_head *q, *n; |
3676 | struct pktgen_dev *p; | 3670 | struct pktgen_dev *p; |
3677 | 3671 | ||
3672 | if_lock(t); | ||
3678 | list_for_each_safe(q, n, &t->if_list) { | 3673 | list_for_each_safe(q, n, &t->if_list) { |
3679 | p = list_entry(q, struct pktgen_dev, list); | 3674 | p = list_entry(q, struct pktgen_dev, list); |
3680 | if (p == pkt_dev) | 3675 | if (p == pkt_dev) |
3681 | list_del(&p->list); | 3676 | list_del_rcu(&p->list); |
3682 | } | 3677 | } |
3678 | if_unlock(t); | ||
3683 | } | 3679 | } |
3684 | 3680 | ||
3685 | static int pktgen_remove_device(struct pktgen_thread *t, | 3681 | static int pktgen_remove_device(struct pktgen_thread *t, |
@@ -3699,20 +3695,22 @@ static int pktgen_remove_device(struct pktgen_thread *t, | |||
3699 | pkt_dev->odev = NULL; | 3695 | pkt_dev->odev = NULL; |
3700 | } | 3696 | } |
3701 | 3697 | ||
3702 | /* And update the thread if_list */ | 3698 | /* Remove proc before if_list entry, because add_device uses |
3703 | 3699 | * list to determine if interface already exist, avoid race | |
3704 | _rem_dev_from_if_list(t, pkt_dev); | 3700 | * with proc_create_data() */ |
3705 | |||
3706 | if (pkt_dev->entry) | 3701 | if (pkt_dev->entry) |
3707 | proc_remove(pkt_dev->entry); | 3702 | proc_remove(pkt_dev->entry); |
3708 | 3703 | ||
3704 | /* And update the thread if_list */ | ||
3705 | _rem_dev_from_if_list(t, pkt_dev); | ||
3706 | |||
3709 | #ifdef CONFIG_XFRM | 3707 | #ifdef CONFIG_XFRM |
3710 | free_SAs(pkt_dev); | 3708 | free_SAs(pkt_dev); |
3711 | #endif | 3709 | #endif |
3712 | vfree(pkt_dev->flows); | 3710 | vfree(pkt_dev->flows); |
3713 | if (pkt_dev->page) | 3711 | if (pkt_dev->page) |
3714 | put_page(pkt_dev->page); | 3712 | put_page(pkt_dev->page); |
3715 | kfree(pkt_dev); | 3713 | kfree_rcu(pkt_dev, rcu); |
3716 | return 0; | 3714 | return 0; |
3717 | } | 3715 | } |
3718 | 3716 | ||
@@ -3812,6 +3810,7 @@ static void __exit pg_cleanup(void) | |||
3812 | { | 3810 | { |
3813 | unregister_netdevice_notifier(&pktgen_notifier_block); | 3811 | unregister_netdevice_notifier(&pktgen_notifier_block); |
3814 | unregister_pernet_subsys(&pg_net_ops); | 3812 | unregister_pernet_subsys(&pg_net_ops); |
3813 | /* Don't need rcu_barrier() due to use of kfree_rcu() */ | ||
3815 | } | 3814 | } |
3816 | 3815 | ||
3817 | module_init(pg_init); | 3816 | module_init(pg_init); |
diff --git a/net/core/ptp_classifier.c b/net/core/ptp_classifier.c index d3027a73fd4b..4eab4a94a59d 100644 --- a/net/core/ptp_classifier.c +++ b/net/core/ptp_classifier.c | |||
@@ -52,14 +52,43 @@ | |||
52 | * test_8021q: | 52 | * test_8021q: |
53 | * jneq #0x8100, test_ieee1588 ; ETH_P_8021Q ? | 53 | * jneq #0x8100, test_ieee1588 ; ETH_P_8021Q ? |
54 | * ldh [16] ; load inner type | 54 | * ldh [16] ; load inner type |
55 | * jneq #0x88f7, drop_ieee1588 ; ETH_P_1588 ? | 55 | * jneq #0x88f7, test_8021q_ipv4 ; ETH_P_1588 ? |
56 | * ldb [18] ; load payload | 56 | * ldb [18] ; load payload |
57 | * and #0x8 ; as we don't have ports here, test | 57 | * and #0x8 ; as we don't have ports here, test |
58 | * jneq #0x0, drop_ieee1588 ; for PTP_GEN_BIT and drop these | 58 | * jneq #0x0, drop_ieee1588 ; for PTP_GEN_BIT and drop these |
59 | * ldh [18] ; reload payload | 59 | * ldh [18] ; reload payload |
60 | * and #0xf ; mask PTP_CLASS_VMASK | 60 | * and #0xf ; mask PTP_CLASS_VMASK |
61 | * or #0x40 ; PTP_CLASS_V2_VLAN | 61 | * or #0x70 ; PTP_CLASS_VLAN|PTP_CLASS_L2 |
62 | * ret a ; return PTP class | ||
63 | * | ||
64 | * ; PTP over UDP over IPv4 over 802.1Q over Ethernet | ||
65 | * test_8021q_ipv4: | ||
66 | * jneq #0x800, test_8021q_ipv6 ; ETH_P_IP ? | ||
67 | * ldb [27] ; load proto | ||
68 | * jneq #17, drop_8021q_ipv4 ; IPPROTO_UDP ? | ||
69 | * ldh [24] ; load frag offset field | ||
70 | * jset #0x1fff, drop_8021q_ipv4; don't allow fragments | ||
71 | * ldxb 4*([18]&0xf) ; load IP header len | ||
72 | * ldh [x + 20] ; load UDP dst port | ||
73 | * jneq #319, drop_8021q_ipv4 ; is port PTP_EV_PORT ? | ||
74 | * ldh [x + 26] ; load payload | ||
75 | * and #0xf ; mask PTP_CLASS_VMASK | ||
76 | * or #0x50 ; PTP_CLASS_VLAN|PTP_CLASS_IPV4 | ||
77 | * ret a ; return PTP class | ||
78 | * drop_8021q_ipv4: ret #0x0 ; PTP_CLASS_NONE | ||
79 | * | ||
80 | * ; PTP over UDP over IPv6 over 802.1Q over Ethernet | ||
81 | * test_8021q_ipv6: | ||
82 | * jneq #0x86dd, drop_8021q_ipv6 ; ETH_P_IPV6 ? | ||
83 | * ldb [24] ; load proto | ||
84 | * jneq #17, drop_8021q_ipv6 ; IPPROTO_UDP ? | ||
85 | * ldh [60] ; load UDP dst port | ||
86 | * jneq #319, drop_8021q_ipv6 ; is port PTP_EV_PORT ? | ||
87 | * ldh [66] ; load payload | ||
88 | * and #0xf ; mask PTP_CLASS_VMASK | ||
89 | * or #0x60 ; PTP_CLASS_VLAN|PTP_CLASS_IPV6 | ||
62 | * ret a ; return PTP class | 90 | * ret a ; return PTP class |
91 | * drop_8021q_ipv6: ret #0x0 ; PTP_CLASS_NONE | ||
63 | * | 92 | * |
64 | * ; PTP over Ethernet | 93 | * ; PTP over Ethernet |
65 | * test_ieee1588: | 94 | * test_ieee1588: |
@@ -78,11 +107,11 @@ | |||
78 | #include <linux/filter.h> | 107 | #include <linux/filter.h> |
79 | #include <linux/ptp_classify.h> | 108 | #include <linux/ptp_classify.h> |
80 | 109 | ||
81 | static struct sk_filter *ptp_insns __read_mostly; | 110 | static struct bpf_prog *ptp_insns __read_mostly; |
82 | 111 | ||
83 | unsigned int ptp_classify_raw(const struct sk_buff *skb) | 112 | unsigned int ptp_classify_raw(const struct sk_buff *skb) |
84 | { | 113 | { |
85 | return SK_RUN_FILTER(ptp_insns, skb); | 114 | return BPF_PROG_RUN(ptp_insns, skb); |
86 | } | 115 | } |
87 | EXPORT_SYMBOL_GPL(ptp_classify_raw); | 116 | EXPORT_SYMBOL_GPL(ptp_classify_raw); |
88 | 117 | ||
@@ -113,16 +142,39 @@ void __init ptp_classifier_init(void) | |||
113 | { 0x44, 0, 0, 0x00000020 }, | 142 | { 0x44, 0, 0, 0x00000020 }, |
114 | { 0x16, 0, 0, 0x00000000 }, | 143 | { 0x16, 0, 0, 0x00000000 }, |
115 | { 0x06, 0, 0, 0x00000000 }, | 144 | { 0x06, 0, 0, 0x00000000 }, |
116 | { 0x15, 0, 9, 0x00008100 }, | 145 | { 0x15, 0, 32, 0x00008100 }, |
117 | { 0x28, 0, 0, 0x00000010 }, | 146 | { 0x28, 0, 0, 0x00000010 }, |
118 | { 0x15, 0, 15, 0x000088f7 }, | 147 | { 0x15, 0, 7, 0x000088f7 }, |
119 | { 0x30, 0, 0, 0x00000012 }, | 148 | { 0x30, 0, 0, 0x00000012 }, |
120 | { 0x54, 0, 0, 0x00000008 }, | 149 | { 0x54, 0, 0, 0x00000008 }, |
121 | { 0x15, 0, 12, 0x00000000 }, | 150 | { 0x15, 0, 35, 0x00000000 }, |
122 | { 0x28, 0, 0, 0x00000012 }, | 151 | { 0x28, 0, 0, 0x00000012 }, |
123 | { 0x54, 0, 0, 0x0000000f }, | 152 | { 0x54, 0, 0, 0x0000000f }, |
124 | { 0x44, 0, 0, 0x00000040 }, | 153 | { 0x44, 0, 0, 0x00000070 }, |
154 | { 0x16, 0, 0, 0x00000000 }, | ||
155 | { 0x15, 0, 12, 0x00000800 }, | ||
156 | { 0x30, 0, 0, 0x0000001b }, | ||
157 | { 0x15, 0, 9, 0x00000011 }, | ||
158 | { 0x28, 0, 0, 0x00000018 }, | ||
159 | { 0x45, 7, 0, 0x00001fff }, | ||
160 | { 0xb1, 0, 0, 0x00000012 }, | ||
161 | { 0x48, 0, 0, 0x00000014 }, | ||
162 | { 0x15, 0, 4, 0x0000013f }, | ||
163 | { 0x48, 0, 0, 0x0000001a }, | ||
164 | { 0x54, 0, 0, 0x0000000f }, | ||
165 | { 0x44, 0, 0, 0x00000050 }, | ||
166 | { 0x16, 0, 0, 0x00000000 }, | ||
167 | { 0x06, 0, 0, 0x00000000 }, | ||
168 | { 0x15, 0, 8, 0x000086dd }, | ||
169 | { 0x30, 0, 0, 0x00000018 }, | ||
170 | { 0x15, 0, 6, 0x00000011 }, | ||
171 | { 0x28, 0, 0, 0x0000003c }, | ||
172 | { 0x15, 0, 4, 0x0000013f }, | ||
173 | { 0x28, 0, 0, 0x00000042 }, | ||
174 | { 0x54, 0, 0, 0x0000000f }, | ||
175 | { 0x44, 0, 0, 0x00000060 }, | ||
125 | { 0x16, 0, 0, 0x00000000 }, | 176 | { 0x16, 0, 0, 0x00000000 }, |
177 | { 0x06, 0, 0, 0x00000000 }, | ||
126 | { 0x15, 0, 7, 0x000088f7 }, | 178 | { 0x15, 0, 7, 0x000088f7 }, |
127 | { 0x30, 0, 0, 0x0000000e }, | 179 | { 0x30, 0, 0, 0x0000000e }, |
128 | { 0x54, 0, 0, 0x00000008 }, | 180 | { 0x54, 0, 0, 0x00000008 }, |
@@ -137,5 +189,5 @@ void __init ptp_classifier_init(void) | |||
137 | .len = ARRAY_SIZE(ptp_filter), .filter = ptp_filter, | 189 | .len = ARRAY_SIZE(ptp_filter), .filter = ptp_filter, |
138 | }; | 190 | }; |
139 | 191 | ||
140 | BUG_ON(sk_unattached_filter_create(&ptp_insns, &ptp_prog)); | 192 | BUG_ON(bpf_prog_create(&ptp_insns, &ptp_prog)); |
141 | } | 193 | } |
diff --git a/net/core/request_sock.c b/net/core/request_sock.c index 467f326126e0..04db318e6218 100644 --- a/net/core/request_sock.c +++ b/net/core/request_sock.c | |||
@@ -41,27 +41,27 @@ int reqsk_queue_alloc(struct request_sock_queue *queue, | |||
41 | unsigned int nr_table_entries) | 41 | unsigned int nr_table_entries) |
42 | { | 42 | { |
43 | size_t lopt_size = sizeof(struct listen_sock); | 43 | size_t lopt_size = sizeof(struct listen_sock); |
44 | struct listen_sock *lopt; | 44 | struct listen_sock *lopt = NULL; |
45 | 45 | ||
46 | nr_table_entries = min_t(u32, nr_table_entries, sysctl_max_syn_backlog); | 46 | nr_table_entries = min_t(u32, nr_table_entries, sysctl_max_syn_backlog); |
47 | nr_table_entries = max_t(u32, nr_table_entries, 8); | 47 | nr_table_entries = max_t(u32, nr_table_entries, 8); |
48 | nr_table_entries = roundup_pow_of_two(nr_table_entries + 1); | 48 | nr_table_entries = roundup_pow_of_two(nr_table_entries + 1); |
49 | lopt_size += nr_table_entries * sizeof(struct request_sock *); | 49 | lopt_size += nr_table_entries * sizeof(struct request_sock *); |
50 | if (lopt_size > PAGE_SIZE) | 50 | |
51 | if (lopt_size <= (PAGE_SIZE << PAGE_ALLOC_COSTLY_ORDER)) | ||
52 | lopt = kzalloc(lopt_size, GFP_KERNEL | | ||
53 | __GFP_NOWARN | | ||
54 | __GFP_NORETRY); | ||
55 | if (!lopt) | ||
51 | lopt = vzalloc(lopt_size); | 56 | lopt = vzalloc(lopt_size); |
52 | else | 57 | if (!lopt) |
53 | lopt = kzalloc(lopt_size, GFP_KERNEL); | ||
54 | if (lopt == NULL) | ||
55 | return -ENOMEM; | 58 | return -ENOMEM; |
56 | 59 | ||
57 | for (lopt->max_qlen_log = 3; | ||
58 | (1 << lopt->max_qlen_log) < nr_table_entries; | ||
59 | lopt->max_qlen_log++); | ||
60 | |||
61 | get_random_bytes(&lopt->hash_rnd, sizeof(lopt->hash_rnd)); | 60 | get_random_bytes(&lopt->hash_rnd, sizeof(lopt->hash_rnd)); |
62 | rwlock_init(&queue->syn_wait_lock); | 61 | rwlock_init(&queue->syn_wait_lock); |
63 | queue->rskq_accept_head = NULL; | 62 | queue->rskq_accept_head = NULL; |
64 | lopt->nr_table_entries = nr_table_entries; | 63 | lopt->nr_table_entries = nr_table_entries; |
64 | lopt->max_qlen_log = ilog2(nr_table_entries); | ||
65 | 65 | ||
66 | write_lock_bh(&queue->syn_wait_lock); | 66 | write_lock_bh(&queue->syn_wait_lock); |
67 | queue->listen_opt = lopt; | 67 | queue->listen_opt = lopt; |
@@ -72,22 +72,8 @@ int reqsk_queue_alloc(struct request_sock_queue *queue, | |||
72 | 72 | ||
73 | void __reqsk_queue_destroy(struct request_sock_queue *queue) | 73 | void __reqsk_queue_destroy(struct request_sock_queue *queue) |
74 | { | 74 | { |
75 | struct listen_sock *lopt; | 75 | /* This is an error recovery path only, no locking needed */ |
76 | size_t lopt_size; | 76 | kvfree(queue->listen_opt); |
77 | |||
78 | /* | ||
79 | * this is an error recovery path only | ||
80 | * no locking needed and the lopt is not NULL | ||
81 | */ | ||
82 | |||
83 | lopt = queue->listen_opt; | ||
84 | lopt_size = sizeof(struct listen_sock) + | ||
85 | lopt->nr_table_entries * sizeof(struct request_sock *); | ||
86 | |||
87 | if (lopt_size > PAGE_SIZE) | ||
88 | vfree(lopt); | ||
89 | else | ||
90 | kfree(lopt); | ||
91 | } | 77 | } |
92 | 78 | ||
93 | static inline struct listen_sock *reqsk_queue_yank_listen_sk( | 79 | static inline struct listen_sock *reqsk_queue_yank_listen_sk( |
@@ -107,8 +93,6 @@ void reqsk_queue_destroy(struct request_sock_queue *queue) | |||
107 | { | 93 | { |
108 | /* make all the listen_opt local to us */ | 94 | /* make all the listen_opt local to us */ |
109 | struct listen_sock *lopt = reqsk_queue_yank_listen_sk(queue); | 95 | struct listen_sock *lopt = reqsk_queue_yank_listen_sk(queue); |
110 | size_t lopt_size = sizeof(struct listen_sock) + | ||
111 | lopt->nr_table_entries * sizeof(struct request_sock *); | ||
112 | 96 | ||
113 | if (lopt->qlen != 0) { | 97 | if (lopt->qlen != 0) { |
114 | unsigned int i; | 98 | unsigned int i; |
@@ -125,10 +109,7 @@ void reqsk_queue_destroy(struct request_sock_queue *queue) | |||
125 | } | 109 | } |
126 | 110 | ||
127 | WARN_ON(lopt->qlen != 0); | 111 | WARN_ON(lopt->qlen != 0); |
128 | if (lopt_size > PAGE_SIZE) | 112 | kvfree(lopt); |
129 | vfree(lopt); | ||
130 | else | ||
131 | kfree(lopt); | ||
132 | } | 113 | } |
133 | 114 | ||
134 | /* | 115 | /* |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 1063996f8317..f0493e3b7471 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
@@ -299,7 +299,12 @@ int __rtnl_link_register(struct rtnl_link_ops *ops) | |||
299 | if (rtnl_link_ops_get(ops->kind)) | 299 | if (rtnl_link_ops_get(ops->kind)) |
300 | return -EEXIST; | 300 | return -EEXIST; |
301 | 301 | ||
302 | if (!ops->dellink) | 302 | /* The check for setup is here because if ops |
303 | * does not have that filled up, it is not possible | ||
304 | * to use the ops for creating device. So do not | ||
305 | * fill up dellink as well. That disables rtnl_dellink. | ||
306 | */ | ||
307 | if (ops->setup && !ops->dellink) | ||
303 | ops->dellink = unregister_netdevice_queue; | 308 | ops->dellink = unregister_netdevice_queue; |
304 | 309 | ||
305 | list_add_tail(&ops->list, &link_ops); | 310 | list_add_tail(&ops->list, &link_ops); |
@@ -799,7 +804,8 @@ static inline int rtnl_vfinfo_size(const struct net_device *dev, | |||
799 | (nla_total_size(sizeof(struct ifla_vf_mac)) + | 804 | (nla_total_size(sizeof(struct ifla_vf_mac)) + |
800 | nla_total_size(sizeof(struct ifla_vf_vlan)) + | 805 | nla_total_size(sizeof(struct ifla_vf_vlan)) + |
801 | nla_total_size(sizeof(struct ifla_vf_spoofchk)) + | 806 | nla_total_size(sizeof(struct ifla_vf_spoofchk)) + |
802 | nla_total_size(sizeof(struct ifla_vf_rate))); | 807 | nla_total_size(sizeof(struct ifla_vf_rate)) + |
808 | nla_total_size(sizeof(struct ifla_vf_link_state))); | ||
803 | return size; | 809 | return size; |
804 | } else | 810 | } else |
805 | return 0; | 811 | return 0; |
@@ -1777,7 +1783,7 @@ static int rtnl_dellink(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
1777 | return -ENODEV; | 1783 | return -ENODEV; |
1778 | 1784 | ||
1779 | ops = dev->rtnl_link_ops; | 1785 | ops = dev->rtnl_link_ops; |
1780 | if (!ops) | 1786 | if (!ops || !ops->dellink) |
1781 | return -EOPNOTSUPP; | 1787 | return -EOPNOTSUPP; |
1782 | 1788 | ||
1783 | ops->dellink(dev, &list_kill); | 1789 | ops->dellink(dev, &list_kill); |
@@ -1805,7 +1811,8 @@ int rtnl_configure_link(struct net_device *dev, const struct ifinfomsg *ifm) | |||
1805 | EXPORT_SYMBOL(rtnl_configure_link); | 1811 | EXPORT_SYMBOL(rtnl_configure_link); |
1806 | 1812 | ||
1807 | struct net_device *rtnl_create_link(struct net *net, | 1813 | struct net_device *rtnl_create_link(struct net *net, |
1808 | char *ifname, const struct rtnl_link_ops *ops, struct nlattr *tb[]) | 1814 | char *ifname, unsigned char name_assign_type, |
1815 | const struct rtnl_link_ops *ops, struct nlattr *tb[]) | ||
1809 | { | 1816 | { |
1810 | int err; | 1817 | int err; |
1811 | struct net_device *dev; | 1818 | struct net_device *dev; |
@@ -1823,8 +1830,8 @@ struct net_device *rtnl_create_link(struct net *net, | |||
1823 | num_rx_queues = ops->get_num_rx_queues(); | 1830 | num_rx_queues = ops->get_num_rx_queues(); |
1824 | 1831 | ||
1825 | err = -ENOMEM; | 1832 | err = -ENOMEM; |
1826 | dev = alloc_netdev_mqs(ops->priv_size, ifname, ops->setup, | 1833 | dev = alloc_netdev_mqs(ops->priv_size, ifname, name_assign_type, |
1827 | num_tx_queues, num_rx_queues); | 1834 | ops->setup, num_tx_queues, num_rx_queues); |
1828 | if (!dev) | 1835 | if (!dev) |
1829 | goto err; | 1836 | goto err; |
1830 | 1837 | ||
@@ -1889,6 +1896,7 @@ static int rtnl_newlink(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
1889 | char ifname[IFNAMSIZ]; | 1896 | char ifname[IFNAMSIZ]; |
1890 | struct nlattr *tb[IFLA_MAX+1]; | 1897 | struct nlattr *tb[IFLA_MAX+1]; |
1891 | struct nlattr *linkinfo[IFLA_INFO_MAX+1]; | 1898 | struct nlattr *linkinfo[IFLA_INFO_MAX+1]; |
1899 | unsigned char name_assign_type = NET_NAME_USER; | ||
1892 | int err; | 1900 | int err; |
1893 | 1901 | ||
1894 | #ifdef CONFIG_MODULES | 1902 | #ifdef CONFIG_MODULES |
@@ -2038,14 +2046,19 @@ replay: | |||
2038 | return -EOPNOTSUPP; | 2046 | return -EOPNOTSUPP; |
2039 | } | 2047 | } |
2040 | 2048 | ||
2041 | if (!ifname[0]) | 2049 | if (!ops->setup) |
2050 | return -EOPNOTSUPP; | ||
2051 | |||
2052 | if (!ifname[0]) { | ||
2042 | snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind); | 2053 | snprintf(ifname, IFNAMSIZ, "%s%%d", ops->kind); |
2054 | name_assign_type = NET_NAME_ENUM; | ||
2055 | } | ||
2043 | 2056 | ||
2044 | dest_net = rtnl_link_get_net(net, tb); | 2057 | dest_net = rtnl_link_get_net(net, tb); |
2045 | if (IS_ERR(dest_net)) | 2058 | if (IS_ERR(dest_net)) |
2046 | return PTR_ERR(dest_net); | 2059 | return PTR_ERR(dest_net); |
2047 | 2060 | ||
2048 | dev = rtnl_create_link(dest_net, ifname, ops, tb); | 2061 | dev = rtnl_create_link(dest_net, ifname, name_assign_type, ops, tb); |
2049 | if (IS_ERR(dev)) { | 2062 | if (IS_ERR(dev)) { |
2050 | err = PTR_ERR(dev); | 2063 | err = PTR_ERR(dev); |
2051 | goto out; | 2064 | goto out; |
@@ -2380,22 +2393,20 @@ int ndo_dflt_fdb_del(struct ndmsg *ndm, | |||
2380 | struct net_device *dev, | 2393 | struct net_device *dev, |
2381 | const unsigned char *addr) | 2394 | const unsigned char *addr) |
2382 | { | 2395 | { |
2383 | int err = -EOPNOTSUPP; | 2396 | int err = -EINVAL; |
2384 | 2397 | ||
2385 | /* If aging addresses are supported device will need to | 2398 | /* If aging addresses are supported device will need to |
2386 | * implement its own handler for this. | 2399 | * implement its own handler for this. |
2387 | */ | 2400 | */ |
2388 | if (!(ndm->ndm_state & NUD_PERMANENT)) { | 2401 | if (!(ndm->ndm_state & NUD_PERMANENT)) { |
2389 | pr_info("%s: FDB only supports static addresses\n", dev->name); | 2402 | pr_info("%s: FDB only supports static addresses\n", dev->name); |
2390 | return -EINVAL; | 2403 | return err; |
2391 | } | 2404 | } |
2392 | 2405 | ||
2393 | if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr)) | 2406 | if (is_unicast_ether_addr(addr) || is_link_local_ether_addr(addr)) |
2394 | err = dev_uc_del(dev, addr); | 2407 | err = dev_uc_del(dev, addr); |
2395 | else if (is_multicast_ether_addr(addr)) | 2408 | else if (is_multicast_ether_addr(addr)) |
2396 | err = dev_mc_del(dev, addr); | 2409 | err = dev_mc_del(dev, addr); |
2397 | else | ||
2398 | err = -EINVAL; | ||
2399 | 2410 | ||
2400 | return err; | 2411 | return err; |
2401 | } | 2412 | } |
@@ -2509,6 +2520,7 @@ skip: | |||
2509 | int ndo_dflt_fdb_dump(struct sk_buff *skb, | 2520 | int ndo_dflt_fdb_dump(struct sk_buff *skb, |
2510 | struct netlink_callback *cb, | 2521 | struct netlink_callback *cb, |
2511 | struct net_device *dev, | 2522 | struct net_device *dev, |
2523 | struct net_device *filter_dev, | ||
2512 | int idx) | 2524 | int idx) |
2513 | { | 2525 | { |
2514 | int err; | 2526 | int err; |
@@ -2526,28 +2538,72 @@ EXPORT_SYMBOL(ndo_dflt_fdb_dump); | |||
2526 | 2538 | ||
2527 | static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb) | 2539 | static int rtnl_fdb_dump(struct sk_buff *skb, struct netlink_callback *cb) |
2528 | { | 2540 | { |
2529 | int idx = 0; | ||
2530 | struct net *net = sock_net(skb->sk); | ||
2531 | struct net_device *dev; | 2541 | struct net_device *dev; |
2542 | struct nlattr *tb[IFLA_MAX+1]; | ||
2543 | struct net_device *bdev = NULL; | ||
2544 | struct net_device *br_dev = NULL; | ||
2545 | const struct net_device_ops *ops = NULL; | ||
2546 | const struct net_device_ops *cops = NULL; | ||
2547 | struct ifinfomsg *ifm = nlmsg_data(cb->nlh); | ||
2548 | struct net *net = sock_net(skb->sk); | ||
2549 | int brport_idx = 0; | ||
2550 | int br_idx = 0; | ||
2551 | int idx = 0; | ||
2532 | 2552 | ||
2533 | rcu_read_lock(); | 2553 | if (nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX, |
2534 | for_each_netdev_rcu(net, dev) { | 2554 | ifla_policy) == 0) { |
2535 | if (dev->priv_flags & IFF_BRIDGE_PORT) { | 2555 | if (tb[IFLA_MASTER]) |
2536 | struct net_device *br_dev; | 2556 | br_idx = nla_get_u32(tb[IFLA_MASTER]); |
2537 | const struct net_device_ops *ops; | 2557 | } |
2558 | |||
2559 | brport_idx = ifm->ifi_index; | ||
2538 | 2560 | ||
2539 | br_dev = netdev_master_upper_dev_get(dev); | 2561 | if (br_idx) { |
2540 | ops = br_dev->netdev_ops; | 2562 | br_dev = __dev_get_by_index(net, br_idx); |
2541 | if (ops->ndo_fdb_dump) | 2563 | if (!br_dev) |
2542 | idx = ops->ndo_fdb_dump(skb, cb, dev, idx); | 2564 | return -ENODEV; |
2565 | |||
2566 | ops = br_dev->netdev_ops; | ||
2567 | bdev = br_dev; | ||
2568 | } | ||
2569 | |||
2570 | for_each_netdev(net, dev) { | ||
2571 | if (brport_idx && (dev->ifindex != brport_idx)) | ||
2572 | continue; | ||
2573 | |||
2574 | if (!br_idx) { /* user did not specify a specific bridge */ | ||
2575 | if (dev->priv_flags & IFF_BRIDGE_PORT) { | ||
2576 | br_dev = netdev_master_upper_dev_get(dev); | ||
2577 | cops = br_dev->netdev_ops; | ||
2578 | } | ||
2579 | |||
2580 | bdev = dev; | ||
2581 | } else { | ||
2582 | if (dev != br_dev && | ||
2583 | !(dev->priv_flags & IFF_BRIDGE_PORT)) | ||
2584 | continue; | ||
2585 | |||
2586 | if (br_dev != netdev_master_upper_dev_get(dev) && | ||
2587 | !(dev->priv_flags & IFF_EBRIDGE)) | ||
2588 | continue; | ||
2589 | |||
2590 | bdev = br_dev; | ||
2591 | cops = ops; | ||
2592 | } | ||
2593 | |||
2594 | if (dev->priv_flags & IFF_BRIDGE_PORT) { | ||
2595 | if (cops && cops->ndo_fdb_dump) | ||
2596 | idx = cops->ndo_fdb_dump(skb, cb, br_dev, dev, | ||
2597 | idx); | ||
2543 | } | 2598 | } |
2544 | 2599 | ||
2600 | idx = ndo_dflt_fdb_dump(skb, cb, dev, NULL, idx); | ||
2545 | if (dev->netdev_ops->ndo_fdb_dump) | 2601 | if (dev->netdev_ops->ndo_fdb_dump) |
2546 | idx = dev->netdev_ops->ndo_fdb_dump(skb, cb, dev, idx); | 2602 | idx = dev->netdev_ops->ndo_fdb_dump(skb, cb, bdev, dev, |
2547 | else | 2603 | idx); |
2548 | idx = ndo_dflt_fdb_dump(skb, cb, dev, idx); | 2604 | |
2605 | cops = NULL; | ||
2549 | } | 2606 | } |
2550 | rcu_read_unlock(); | ||
2551 | 2607 | ||
2552 | cb->args[0] = idx; | 2608 | cb->args[0] = idx; |
2553 | return skb->len; | 2609 | return skb->len; |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index c1a33033cbe2..8d289697cc7a 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
@@ -62,6 +62,7 @@ | |||
62 | #include <linux/scatterlist.h> | 62 | #include <linux/scatterlist.h> |
63 | #include <linux/errqueue.h> | 63 | #include <linux/errqueue.h> |
64 | #include <linux/prefetch.h> | 64 | #include <linux/prefetch.h> |
65 | #include <linux/if_vlan.h> | ||
65 | 66 | ||
66 | #include <net/protocol.h> | 67 | #include <net/protocol.h> |
67 | #include <net/dst.h> | 68 | #include <net/dst.h> |
@@ -2646,7 +2647,7 @@ EXPORT_SYMBOL(skb_prepare_seq_read); | |||
2646 | * skb_seq_read() will return the remaining part of the block. | 2647 | * skb_seq_read() will return the remaining part of the block. |
2647 | * | 2648 | * |
2648 | * Note 1: The size of each block of data returned can be arbitrary, | 2649 | * Note 1: The size of each block of data returned can be arbitrary, |
2649 | * this limitation is the cost for zerocopy seqeuental | 2650 | * this limitation is the cost for zerocopy sequential |
2650 | * reads of potentially non linear data. | 2651 | * reads of potentially non linear data. |
2651 | * | 2652 | * |
2652 | * Note 2: Fragment lists within fragments are not implemented | 2653 | * Note 2: Fragment lists within fragments are not implemented |
@@ -2780,7 +2781,7 @@ EXPORT_SYMBOL(skb_find_text); | |||
2780 | /** | 2781 | /** |
2781 | * skb_append_datato_frags - append the user data to a skb | 2782 | * skb_append_datato_frags - append the user data to a skb |
2782 | * @sk: sock structure | 2783 | * @sk: sock structure |
2783 | * @skb: skb structure to be appened with user data. | 2784 | * @skb: skb structure to be appended with user data. |
2784 | * @getfrag: call back function to be used for getting the user data | 2785 | * @getfrag: call back function to be used for getting the user data |
2785 | * @from: pointer to user message iov | 2786 | * @from: pointer to user message iov |
2786 | * @length: length of the iov message | 2787 | * @length: length of the iov message |
@@ -2976,9 +2977,9 @@ struct sk_buff *skb_segment(struct sk_buff *head_skb, | |||
2976 | tail = nskb; | 2977 | tail = nskb; |
2977 | 2978 | ||
2978 | __copy_skb_header(nskb, head_skb); | 2979 | __copy_skb_header(nskb, head_skb); |
2979 | nskb->mac_len = head_skb->mac_len; | ||
2980 | 2980 | ||
2981 | skb_headers_offset_update(nskb, skb_headroom(nskb) - headroom); | 2981 | skb_headers_offset_update(nskb, skb_headroom(nskb) - headroom); |
2982 | skb_reset_mac_len(nskb); | ||
2982 | 2983 | ||
2983 | skb_copy_from_linear_data_offset(head_skb, -tnl_hlen, | 2984 | skb_copy_from_linear_data_offset(head_skb, -tnl_hlen, |
2984 | nskb->data - tnl_hlen, | 2985 | nskb->data - tnl_hlen, |
@@ -3151,6 +3152,9 @@ int skb_gro_receive(struct sk_buff **head, struct sk_buff *skb) | |||
3151 | NAPI_GRO_CB(skb)->free = NAPI_GRO_FREE_STOLEN_HEAD; | 3152 | NAPI_GRO_CB(skb)->free = NAPI_GRO_FREE_STOLEN_HEAD; |
3152 | goto done; | 3153 | goto done; |
3153 | } | 3154 | } |
3155 | /* switch back to head shinfo */ | ||
3156 | pinfo = skb_shinfo(p); | ||
3157 | |||
3154 | if (pinfo->frag_list) | 3158 | if (pinfo->frag_list) |
3155 | goto merge; | 3159 | goto merge; |
3156 | if (skb_gro_len(p) != pinfo->gso_size) | 3160 | if (skb_gro_len(p) != pinfo->gso_size) |
@@ -3490,10 +3494,10 @@ int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb) | |||
3490 | } | 3494 | } |
3491 | EXPORT_SYMBOL(sock_queue_err_skb); | 3495 | EXPORT_SYMBOL(sock_queue_err_skb); |
3492 | 3496 | ||
3493 | void skb_tstamp_tx(struct sk_buff *orig_skb, | 3497 | void __skb_tstamp_tx(struct sk_buff *orig_skb, |
3494 | struct skb_shared_hwtstamps *hwtstamps) | 3498 | struct skb_shared_hwtstamps *hwtstamps, |
3499 | struct sock *sk, int tstype) | ||
3495 | { | 3500 | { |
3496 | struct sock *sk = orig_skb->sk; | ||
3497 | struct sock_exterr_skb *serr; | 3501 | struct sock_exterr_skb *serr; |
3498 | struct sk_buff *skb; | 3502 | struct sk_buff *skb; |
3499 | int err; | 3503 | int err; |
@@ -3521,12 +3525,26 @@ void skb_tstamp_tx(struct sk_buff *orig_skb, | |||
3521 | memset(serr, 0, sizeof(*serr)); | 3525 | memset(serr, 0, sizeof(*serr)); |
3522 | serr->ee.ee_errno = ENOMSG; | 3526 | serr->ee.ee_errno = ENOMSG; |
3523 | serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING; | 3527 | serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING; |
3528 | serr->ee.ee_info = tstype; | ||
3529 | if (sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) { | ||
3530 | serr->ee.ee_data = skb_shinfo(skb)->tskey; | ||
3531 | if (sk->sk_protocol == IPPROTO_TCP) | ||
3532 | serr->ee.ee_data -= sk->sk_tskey; | ||
3533 | } | ||
3524 | 3534 | ||
3525 | err = sock_queue_err_skb(sk, skb); | 3535 | err = sock_queue_err_skb(sk, skb); |
3526 | 3536 | ||
3527 | if (err) | 3537 | if (err) |
3528 | kfree_skb(skb); | 3538 | kfree_skb(skb); |
3529 | } | 3539 | } |
3540 | EXPORT_SYMBOL_GPL(__skb_tstamp_tx); | ||
3541 | |||
3542 | void skb_tstamp_tx(struct sk_buff *orig_skb, | ||
3543 | struct skb_shared_hwtstamps *hwtstamps) | ||
3544 | { | ||
3545 | return __skb_tstamp_tx(orig_skb, hwtstamps, orig_skb->sk, | ||
3546 | SCM_TSTAMP_SND); | ||
3547 | } | ||
3530 | EXPORT_SYMBOL_GPL(skb_tstamp_tx); | 3548 | EXPORT_SYMBOL_GPL(skb_tstamp_tx); |
3531 | 3549 | ||
3532 | void skb_complete_wifi_ack(struct sk_buff *skb, bool acked) | 3550 | void skb_complete_wifi_ack(struct sk_buff *skb, bool acked) |
@@ -3959,3 +3977,55 @@ unsigned int skb_gso_transport_seglen(const struct sk_buff *skb) | |||
3959 | return shinfo->gso_size; | 3977 | return shinfo->gso_size; |
3960 | } | 3978 | } |
3961 | EXPORT_SYMBOL_GPL(skb_gso_transport_seglen); | 3979 | EXPORT_SYMBOL_GPL(skb_gso_transport_seglen); |
3980 | |||
3981 | static struct sk_buff *skb_reorder_vlan_header(struct sk_buff *skb) | ||
3982 | { | ||
3983 | if (skb_cow(skb, skb_headroom(skb)) < 0) { | ||
3984 | kfree_skb(skb); | ||
3985 | return NULL; | ||
3986 | } | ||
3987 | |||
3988 | memmove(skb->data - ETH_HLEN, skb->data - VLAN_ETH_HLEN, 2 * ETH_ALEN); | ||
3989 | skb->mac_header += VLAN_HLEN; | ||
3990 | return skb; | ||
3991 | } | ||
3992 | |||
3993 | struct sk_buff *skb_vlan_untag(struct sk_buff *skb) | ||
3994 | { | ||
3995 | struct vlan_hdr *vhdr; | ||
3996 | u16 vlan_tci; | ||
3997 | |||
3998 | if (unlikely(vlan_tx_tag_present(skb))) { | ||
3999 | /* vlan_tci is already set-up so leave this for another time */ | ||
4000 | return skb; | ||
4001 | } | ||
4002 | |||
4003 | skb = skb_share_check(skb, GFP_ATOMIC); | ||
4004 | if (unlikely(!skb)) | ||
4005 | goto err_free; | ||
4006 | |||
4007 | if (unlikely(!pskb_may_pull(skb, VLAN_HLEN))) | ||
4008 | goto err_free; | ||
4009 | |||
4010 | vhdr = (struct vlan_hdr *)skb->data; | ||
4011 | vlan_tci = ntohs(vhdr->h_vlan_TCI); | ||
4012 | __vlan_hwaccel_put_tag(skb, skb->protocol, vlan_tci); | ||
4013 | |||
4014 | skb_pull_rcsum(skb, VLAN_HLEN); | ||
4015 | vlan_set_encap_proto(skb, vhdr); | ||
4016 | |||
4017 | skb = skb_reorder_vlan_header(skb); | ||
4018 | if (unlikely(!skb)) | ||
4019 | goto err_free; | ||
4020 | |||
4021 | skb_reset_network_header(skb); | ||
4022 | skb_reset_transport_header(skb); | ||
4023 | skb_reset_mac_len(skb); | ||
4024 | |||
4025 | return skb; | ||
4026 | |||
4027 | err_free: | ||
4028 | kfree_skb(skb); | ||
4029 | return NULL; | ||
4030 | } | ||
4031 | EXPORT_SYMBOL(skb_vlan_untag); | ||
diff --git a/net/core/sock.c b/net/core/sock.c index 026e01f70274..9c3f823e76a9 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -166,7 +166,7 @@ EXPORT_SYMBOL(sk_ns_capable); | |||
166 | /** | 166 | /** |
167 | * sk_capable - Socket global capability test | 167 | * sk_capable - Socket global capability test |
168 | * @sk: Socket to use a capability on or through | 168 | * @sk: Socket to use a capability on or through |
169 | * @cap: The global capbility to use | 169 | * @cap: The global capability to use |
170 | * | 170 | * |
171 | * Test to see if the opener of the socket had when the socket was | 171 | * Test to see if the opener of the socket had when the socket was |
172 | * created and the current process has the capability @cap in all user | 172 | * created and the current process has the capability @cap in all user |
@@ -183,7 +183,7 @@ EXPORT_SYMBOL(sk_capable); | |||
183 | * @sk: Socket to use a capability on or through | 183 | * @sk: Socket to use a capability on or through |
184 | * @cap: The capability to use | 184 | * @cap: The capability to use |
185 | * | 185 | * |
186 | * Test to see if the opener of the socket had when the socke was created | 186 | * Test to see if the opener of the socket had when the socket was created |
187 | * and the current process has the capability @cap over the network namespace | 187 | * and the current process has the capability @cap over the network namespace |
188 | * the socket is a member of. | 188 | * the socket is a member of. |
189 | */ | 189 | */ |
@@ -491,7 +491,7 @@ int sk_receive_skb(struct sock *sk, struct sk_buff *skb, const int nested) | |||
491 | 491 | ||
492 | skb->dev = NULL; | 492 | skb->dev = NULL; |
493 | 493 | ||
494 | if (sk_rcvqueues_full(sk, skb, sk->sk_rcvbuf)) { | 494 | if (sk_rcvqueues_full(sk, sk->sk_rcvbuf)) { |
495 | atomic_inc(&sk->sk_drops); | 495 | atomic_inc(&sk->sk_drops); |
496 | goto discard_and_relse; | 496 | goto discard_and_relse; |
497 | } | 497 | } |
@@ -848,24 +848,25 @@ set_rcvbuf: | |||
848 | ret = -EINVAL; | 848 | ret = -EINVAL; |
849 | break; | 849 | break; |
850 | } | 850 | } |
851 | sock_valbool_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE, | 851 | if (val & SOF_TIMESTAMPING_OPT_ID && |
852 | val & SOF_TIMESTAMPING_TX_HARDWARE); | 852 | !(sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID)) { |
853 | sock_valbool_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE, | 853 | if (sk->sk_protocol == IPPROTO_TCP) { |
854 | val & SOF_TIMESTAMPING_TX_SOFTWARE); | 854 | if (sk->sk_state != TCP_ESTABLISHED) { |
855 | sock_valbool_flag(sk, SOCK_TIMESTAMPING_RX_HARDWARE, | 855 | ret = -EINVAL; |
856 | val & SOF_TIMESTAMPING_RX_HARDWARE); | 856 | break; |
857 | } | ||
858 | sk->sk_tskey = tcp_sk(sk)->snd_una; | ||
859 | } else { | ||
860 | sk->sk_tskey = 0; | ||
861 | } | ||
862 | } | ||
863 | sk->sk_tsflags = val; | ||
857 | if (val & SOF_TIMESTAMPING_RX_SOFTWARE) | 864 | if (val & SOF_TIMESTAMPING_RX_SOFTWARE) |
858 | sock_enable_timestamp(sk, | 865 | sock_enable_timestamp(sk, |
859 | SOCK_TIMESTAMPING_RX_SOFTWARE); | 866 | SOCK_TIMESTAMPING_RX_SOFTWARE); |
860 | else | 867 | else |
861 | sock_disable_timestamp(sk, | 868 | sock_disable_timestamp(sk, |
862 | (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE)); | 869 | (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE)); |
863 | sock_valbool_flag(sk, SOCK_TIMESTAMPING_SOFTWARE, | ||
864 | val & SOF_TIMESTAMPING_SOFTWARE); | ||
865 | sock_valbool_flag(sk, SOCK_TIMESTAMPING_SYS_HARDWARE, | ||
866 | val & SOF_TIMESTAMPING_SYS_HARDWARE); | ||
867 | sock_valbool_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE, | ||
868 | val & SOF_TIMESTAMPING_RAW_HARDWARE); | ||
869 | break; | 870 | break; |
870 | 871 | ||
871 | case SO_RCVLOWAT: | 872 | case SO_RCVLOWAT: |
@@ -1091,21 +1092,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname, | |||
1091 | break; | 1092 | break; |
1092 | 1093 | ||
1093 | case SO_TIMESTAMPING: | 1094 | case SO_TIMESTAMPING: |
1094 | v.val = 0; | 1095 | v.val = sk->sk_tsflags; |
1095 | if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE)) | ||
1096 | v.val |= SOF_TIMESTAMPING_TX_HARDWARE; | ||
1097 | if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE)) | ||
1098 | v.val |= SOF_TIMESTAMPING_TX_SOFTWARE; | ||
1099 | if (sock_flag(sk, SOCK_TIMESTAMPING_RX_HARDWARE)) | ||
1100 | v.val |= SOF_TIMESTAMPING_RX_HARDWARE; | ||
1101 | if (sock_flag(sk, SOCK_TIMESTAMPING_RX_SOFTWARE)) | ||
1102 | v.val |= SOF_TIMESTAMPING_RX_SOFTWARE; | ||
1103 | if (sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE)) | ||
1104 | v.val |= SOF_TIMESTAMPING_SOFTWARE; | ||
1105 | if (sock_flag(sk, SOCK_TIMESTAMPING_SYS_HARDWARE)) | ||
1106 | v.val |= SOF_TIMESTAMPING_SYS_HARDWARE; | ||
1107 | if (sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE)) | ||
1108 | v.val |= SOF_TIMESTAMPING_RAW_HARDWARE; | ||
1109 | break; | 1096 | break; |
1110 | 1097 | ||
1111 | case SO_RCVTIMEO: | 1098 | case SO_RCVTIMEO: |
@@ -1478,6 +1465,7 @@ static void sk_update_clone(const struct sock *sk, struct sock *newsk) | |||
1478 | struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) | 1465 | struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) |
1479 | { | 1466 | { |
1480 | struct sock *newsk; | 1467 | struct sock *newsk; |
1468 | bool is_charged = true; | ||
1481 | 1469 | ||
1482 | newsk = sk_prot_alloc(sk->sk_prot, priority, sk->sk_family); | 1470 | newsk = sk_prot_alloc(sk->sk_prot, priority, sk->sk_family); |
1483 | if (newsk != NULL) { | 1471 | if (newsk != NULL) { |
@@ -1522,9 +1510,13 @@ struct sock *sk_clone_lock(const struct sock *sk, const gfp_t priority) | |||
1522 | 1510 | ||
1523 | filter = rcu_dereference_protected(newsk->sk_filter, 1); | 1511 | filter = rcu_dereference_protected(newsk->sk_filter, 1); |
1524 | if (filter != NULL) | 1512 | if (filter != NULL) |
1525 | sk_filter_charge(newsk, filter); | 1513 | /* though it's an empty new sock, the charging may fail |
1514 | * if sysctl_optmem_max was changed between creation of | ||
1515 | * original socket and cloning | ||
1516 | */ | ||
1517 | is_charged = sk_filter_charge(newsk, filter); | ||
1526 | 1518 | ||
1527 | if (unlikely(xfrm_sk_clone_policy(newsk))) { | 1519 | if (unlikely(!is_charged || xfrm_sk_clone_policy(newsk))) { |
1528 | /* It is still raw copy of parent, so invalidate | 1520 | /* It is still raw copy of parent, so invalidate |
1529 | * destructor and make plain sk_free() */ | 1521 | * destructor and make plain sk_free() */ |
1530 | newsk->sk_destruct = NULL; | 1522 | newsk->sk_destruct = NULL; |
@@ -1830,6 +1822,9 @@ struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len, | |||
1830 | order); | 1822 | order); |
1831 | if (page) | 1823 | if (page) |
1832 | goto fill_page; | 1824 | goto fill_page; |
1825 | /* Do not retry other high order allocations */ | ||
1826 | order = 1; | ||
1827 | max_page_order = 0; | ||
1833 | } | 1828 | } |
1834 | order--; | 1829 | order--; |
1835 | } | 1830 | } |
@@ -1871,16 +1866,14 @@ EXPORT_SYMBOL(sock_alloc_send_skb); | |||
1871 | * skb_page_frag_refill - check that a page_frag contains enough room | 1866 | * skb_page_frag_refill - check that a page_frag contains enough room |
1872 | * @sz: minimum size of the fragment we want to get | 1867 | * @sz: minimum size of the fragment we want to get |
1873 | * @pfrag: pointer to page_frag | 1868 | * @pfrag: pointer to page_frag |
1874 | * @prio: priority for memory allocation | 1869 | * @gfp: priority for memory allocation |
1875 | * | 1870 | * |
1876 | * Note: While this allocator tries to use high order pages, there is | 1871 | * Note: While this allocator tries to use high order pages, there is |
1877 | * no guarantee that allocations succeed. Therefore, @sz MUST be | 1872 | * no guarantee that allocations succeed. Therefore, @sz MUST be |
1878 | * less or equal than PAGE_SIZE. | 1873 | * less or equal than PAGE_SIZE. |
1879 | */ | 1874 | */ |
1880 | bool skb_page_frag_refill(unsigned int sz, struct page_frag *pfrag, gfp_t prio) | 1875 | bool skb_page_frag_refill(unsigned int sz, struct page_frag *pfrag, gfp_t gfp) |
1881 | { | 1876 | { |
1882 | int order; | ||
1883 | |||
1884 | if (pfrag->page) { | 1877 | if (pfrag->page) { |
1885 | if (atomic_read(&pfrag->page->_count) == 1) { | 1878 | if (atomic_read(&pfrag->page->_count) == 1) { |
1886 | pfrag->offset = 0; | 1879 | pfrag->offset = 0; |
@@ -1891,20 +1884,21 @@ bool skb_page_frag_refill(unsigned int sz, struct page_frag *pfrag, gfp_t prio) | |||
1891 | put_page(pfrag->page); | 1884 | put_page(pfrag->page); |
1892 | } | 1885 | } |
1893 | 1886 | ||
1894 | order = SKB_FRAG_PAGE_ORDER; | 1887 | pfrag->offset = 0; |
1895 | do { | 1888 | if (SKB_FRAG_PAGE_ORDER) { |
1896 | gfp_t gfp = prio; | 1889 | pfrag->page = alloc_pages(gfp | __GFP_COMP | |
1897 | 1890 | __GFP_NOWARN | __GFP_NORETRY, | |
1898 | if (order) | 1891 | SKB_FRAG_PAGE_ORDER); |
1899 | gfp |= __GFP_COMP | __GFP_NOWARN | __GFP_NORETRY; | ||
1900 | pfrag->page = alloc_pages(gfp, order); | ||
1901 | if (likely(pfrag->page)) { | 1892 | if (likely(pfrag->page)) { |
1902 | pfrag->offset = 0; | 1893 | pfrag->size = PAGE_SIZE << SKB_FRAG_PAGE_ORDER; |
1903 | pfrag->size = PAGE_SIZE << order; | ||
1904 | return true; | 1894 | return true; |
1905 | } | 1895 | } |
1906 | } while (--order >= 0); | 1896 | } |
1907 | 1897 | pfrag->page = alloc_page(gfp); | |
1898 | if (likely(pfrag->page)) { | ||
1899 | pfrag->size = PAGE_SIZE; | ||
1900 | return true; | ||
1901 | } | ||
1908 | return false; | 1902 | return false; |
1909 | } | 1903 | } |
1910 | EXPORT_SYMBOL(skb_page_frag_refill); | 1904 | EXPORT_SYMBOL(skb_page_frag_refill); |
diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c index a4216a4c9572..ad704c757bb4 100644 --- a/net/core/sock_diag.c +++ b/net/core/sock_diag.c | |||
@@ -68,8 +68,8 @@ int sock_diag_put_filterinfo(bool may_report_filterinfo, struct sock *sk, | |||
68 | if (!filter) | 68 | if (!filter) |
69 | goto out; | 69 | goto out; |
70 | 70 | ||
71 | fprog = filter->orig_prog; | 71 | fprog = filter->prog->orig_prog; |
72 | flen = sk_filter_proglen(fprog); | 72 | flen = bpf_classic_proglen(fprog); |
73 | 73 | ||
74 | attr = nla_reserve(skb, attrtype, flen); | 74 | attr = nla_reserve(skb, attrtype, flen); |
75 | if (attr == NULL) { | 75 | if (attr == NULL) { |
diff --git a/net/core/timestamping.c b/net/core/timestamping.c index 6521dfd8b7c8..a8770391ea5b 100644 --- a/net/core/timestamping.c +++ b/net/core/timestamping.c | |||
@@ -43,31 +43,22 @@ void skb_clone_tx_timestamp(struct sk_buff *skb) | |||
43 | return; | 43 | return; |
44 | 44 | ||
45 | type = classify(skb); | 45 | type = classify(skb); |
46 | if (type == PTP_CLASS_NONE) | ||
47 | return; | ||
48 | |||
49 | phydev = skb->dev->phydev; | ||
50 | if (likely(phydev->drv->txtstamp)) { | ||
51 | if (!atomic_inc_not_zero(&sk->sk_refcnt)) | ||
52 | return; | ||
46 | 53 | ||
47 | switch (type) { | 54 | clone = skb_clone(skb, GFP_ATOMIC); |
48 | case PTP_CLASS_V1_IPV4: | 55 | if (!clone) { |
49 | case PTP_CLASS_V1_IPV6: | 56 | sock_put(sk); |
50 | case PTP_CLASS_V2_IPV4: | 57 | return; |
51 | case PTP_CLASS_V2_IPV6: | ||
52 | case PTP_CLASS_V2_L2: | ||
53 | case PTP_CLASS_V2_VLAN: | ||
54 | phydev = skb->dev->phydev; | ||
55 | if (likely(phydev->drv->txtstamp)) { | ||
56 | if (!atomic_inc_not_zero(&sk->sk_refcnt)) | ||
57 | return; | ||
58 | |||
59 | clone = skb_clone(skb, GFP_ATOMIC); | ||
60 | if (!clone) { | ||
61 | sock_put(sk); | ||
62 | return; | ||
63 | } | ||
64 | |||
65 | clone->sk = sk; | ||
66 | phydev->drv->txtstamp(phydev, clone, type); | ||
67 | } | 58 | } |
68 | break; | 59 | |
69 | default: | 60 | clone->sk = sk; |
70 | break; | 61 | phydev->drv->txtstamp(phydev, clone, type); |
71 | } | 62 | } |
72 | } | 63 | } |
73 | EXPORT_SYMBOL_GPL(skb_clone_tx_timestamp); | 64 | EXPORT_SYMBOL_GPL(skb_clone_tx_timestamp); |
@@ -114,20 +105,12 @@ bool skb_defer_rx_timestamp(struct sk_buff *skb) | |||
114 | 105 | ||
115 | __skb_pull(skb, ETH_HLEN); | 106 | __skb_pull(skb, ETH_HLEN); |
116 | 107 | ||
117 | switch (type) { | 108 | if (type == PTP_CLASS_NONE) |
118 | case PTP_CLASS_V1_IPV4: | 109 | return false; |
119 | case PTP_CLASS_V1_IPV6: | 110 | |
120 | case PTP_CLASS_V2_IPV4: | 111 | phydev = skb->dev->phydev; |
121 | case PTP_CLASS_V2_IPV6: | 112 | if (likely(phydev->drv->rxtstamp)) |
122 | case PTP_CLASS_V2_L2: | 113 | return phydev->drv->rxtstamp(phydev, skb, type); |
123 | case PTP_CLASS_V2_VLAN: | ||
124 | phydev = skb->dev->phydev; | ||
125 | if (likely(phydev->drv->rxtstamp)) | ||
126 | return phydev->drv->rxtstamp(phydev, skb, type); | ||
127 | break; | ||
128 | default: | ||
129 | break; | ||
130 | } | ||
131 | 114 | ||
132 | return false; | 115 | return false; |
133 | } | 116 | } |
diff --git a/net/dcb/dcbnl.c b/net/dcb/dcbnl.c index f8b98d89c285..ca11d283bbeb 100644 --- a/net/dcb/dcbnl.c +++ b/net/dcb/dcbnl.c | |||
@@ -471,7 +471,11 @@ static int dcbnl_getapp(struct net_device *netdev, struct nlmsghdr *nlh, | |||
471 | id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]); | 471 | id = nla_get_u16(app_tb[DCB_APP_ATTR_ID]); |
472 | 472 | ||
473 | if (netdev->dcbnl_ops->getapp) { | 473 | if (netdev->dcbnl_ops->getapp) { |
474 | up = netdev->dcbnl_ops->getapp(netdev, idtype, id); | 474 | ret = netdev->dcbnl_ops->getapp(netdev, idtype, id); |
475 | if (ret < 0) | ||
476 | return ret; | ||
477 | else | ||
478 | up = ret; | ||
475 | } else { | 479 | } else { |
476 | struct dcb_app app = { | 480 | struct dcb_app app = { |
477 | .selector = idtype, | 481 | .selector = idtype, |
@@ -538,6 +542,8 @@ static int dcbnl_setapp(struct net_device *netdev, struct nlmsghdr *nlh, | |||
538 | 542 | ||
539 | if (netdev->dcbnl_ops->setapp) { | 543 | if (netdev->dcbnl_ops->setapp) { |
540 | ret = netdev->dcbnl_ops->setapp(netdev, idtype, id, up); | 544 | ret = netdev->dcbnl_ops->setapp(netdev, idtype, id, up); |
545 | if (ret < 0) | ||
546 | return ret; | ||
541 | } else { | 547 | } else { |
542 | struct dcb_app app; | 548 | struct dcb_app app; |
543 | app.selector = idtype; | 549 | app.selector = idtype; |
@@ -1770,7 +1776,7 @@ EXPORT_SYMBOL(dcb_getapp); | |||
1770 | * | 1776 | * |
1771 | * Priority 0 is an invalid priority in CEE spec. This routine | 1777 | * Priority 0 is an invalid priority in CEE spec. This routine |
1772 | * removes applications from the app list if the priority is | 1778 | * removes applications from the app list if the priority is |
1773 | * set to zero. | 1779 | * set to zero. Priority is expected to be 8-bit 802.1p user priority bitmap |
1774 | */ | 1780 | */ |
1775 | int dcb_setapp(struct net_device *dev, struct dcb_app *new) | 1781 | int dcb_setapp(struct net_device *dev, struct dcb_app *new) |
1776 | { | 1782 | { |
@@ -1831,7 +1837,8 @@ EXPORT_SYMBOL(dcb_ieee_getapp_mask); | |||
1831 | * | 1837 | * |
1832 | * This adds Application data to the list. Multiple application | 1838 | * This adds Application data to the list. Multiple application |
1833 | * entries may exists for the same selector and protocol as long | 1839 | * entries may exists for the same selector and protocol as long |
1834 | * as the priorities are different. | 1840 | * as the priorities are different. Priority is expected to be a |
1841 | * 3-bit unsigned integer | ||
1835 | */ | 1842 | */ |
1836 | int dcb_ieee_setapp(struct net_device *dev, struct dcb_app *new) | 1843 | int dcb_ieee_setapp(struct net_device *dev, struct dcb_app *new) |
1837 | { | 1844 | { |
diff --git a/net/dccp/ipv6.c b/net/dccp/ipv6.c index 4db3c2a1679c..04cb17d4b0ce 100644 --- a/net/dccp/ipv6.c +++ b/net/dccp/ipv6.c | |||
@@ -386,7 +386,7 @@ static int dccp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | |||
386 | if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) | 386 | if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) |
387 | goto drop; | 387 | goto drop; |
388 | 388 | ||
389 | req = inet6_reqsk_alloc(&dccp6_request_sock_ops); | 389 | req = inet_reqsk_alloc(&dccp6_request_sock_ops); |
390 | if (req == NULL) | 390 | if (req == NULL) |
391 | goto drop; | 391 | goto drop; |
392 | 392 | ||
diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index c69eb9c4fbb8..b50dc436db1f 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c | |||
@@ -55,11 +55,9 @@ void dccp_time_wait(struct sock *sk, int state, int timeo) | |||
55 | const int rto = (icsk->icsk_rto << 2) - (icsk->icsk_rto >> 1); | 55 | const int rto = (icsk->icsk_rto << 2) - (icsk->icsk_rto >> 1); |
56 | #if IS_ENABLED(CONFIG_IPV6) | 56 | #if IS_ENABLED(CONFIG_IPV6) |
57 | if (tw->tw_family == PF_INET6) { | 57 | if (tw->tw_family == PF_INET6) { |
58 | const struct ipv6_pinfo *np = inet6_sk(sk); | ||
59 | |||
60 | tw->tw_v6_daddr = sk->sk_v6_daddr; | 58 | tw->tw_v6_daddr = sk->sk_v6_daddr; |
61 | tw->tw_v6_rcv_saddr = sk->sk_v6_rcv_saddr; | 59 | tw->tw_v6_rcv_saddr = sk->sk_v6_rcv_saddr; |
62 | tw->tw_ipv6only = np->ipv6only; | 60 | tw->tw_ipv6only = sk->sk_ipv6only; |
63 | } | 61 | } |
64 | #endif | 62 | #endif |
65 | /* Linkage updates. */ | 63 | /* Linkage updates. */ |
diff --git a/net/dsa/dsa.c b/net/dsa/dsa.c index 5db37cef50a9..0a49632fac47 100644 --- a/net/dsa/dsa.c +++ b/net/dsa/dsa.c | |||
@@ -351,8 +351,7 @@ static void dsa_of_free_platform_data(struct dsa_platform_data *pd) | |||
351 | for (i = 0; i < pd->nr_chips; i++) { | 351 | for (i = 0; i < pd->nr_chips; i++) { |
352 | port_index = 0; | 352 | port_index = 0; |
353 | while (port_index < DSA_MAX_PORTS) { | 353 | while (port_index < DSA_MAX_PORTS) { |
354 | if (pd->chip[i].port_names[port_index]) | 354 | kfree(pd->chip[i].port_names[port_index]); |
355 | kfree(pd->chip[i].port_names[port_index]); | ||
356 | port_index++; | 355 | port_index++; |
357 | } | 356 | } |
358 | kfree(pd->chip[i].rtable); | 357 | kfree(pd->chip[i].rtable); |
diff --git a/net/dsa/slave.c b/net/dsa/slave.c index 64c5af0a10dd..45a1e34c89e0 100644 --- a/net/dsa/slave.c +++ b/net/dsa/slave.c | |||
@@ -340,8 +340,8 @@ dsa_slave_create(struct dsa_switch *ds, struct device *parent, | |||
340 | struct dsa_slave_priv *p; | 340 | struct dsa_slave_priv *p; |
341 | int ret; | 341 | int ret; |
342 | 342 | ||
343 | slave_dev = alloc_netdev(sizeof(struct dsa_slave_priv), | 343 | slave_dev = alloc_netdev(sizeof(struct dsa_slave_priv), name, |
344 | name, ether_setup); | 344 | NET_NAME_UNKNOWN, ether_setup); |
345 | if (slave_dev == NULL) | 345 | if (slave_dev == NULL) |
346 | return slave_dev; | 346 | return slave_dev; |
347 | 347 | ||
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c index 5dc638cad2e1..f405e0592407 100644 --- a/net/ethernet/eth.c +++ b/net/ethernet/eth.c | |||
@@ -390,7 +390,8 @@ EXPORT_SYMBOL(ether_setup); | |||
390 | struct net_device *alloc_etherdev_mqs(int sizeof_priv, unsigned int txqs, | 390 | struct net_device *alloc_etherdev_mqs(int sizeof_priv, unsigned int txqs, |
391 | unsigned int rxqs) | 391 | unsigned int rxqs) |
392 | { | 392 | { |
393 | return alloc_netdev_mqs(sizeof_priv, "eth%d", ether_setup, txqs, rxqs); | 393 | return alloc_netdev_mqs(sizeof_priv, "eth%d", NET_NAME_UNKNOWN, |
394 | ether_setup, txqs, rxqs); | ||
394 | } | 395 | } |
395 | EXPORT_SYMBOL(alloc_etherdev_mqs); | 396 | EXPORT_SYMBOL(alloc_etherdev_mqs); |
396 | 397 | ||
diff --git a/net/hsr/Makefile b/net/hsr/Makefile index b68359f181cc..9ae972a820f4 100644 --- a/net/hsr/Makefile +++ b/net/hsr/Makefile | |||
@@ -4,4 +4,5 @@ | |||
4 | 4 | ||
5 | obj-$(CONFIG_HSR) += hsr.o | 5 | obj-$(CONFIG_HSR) += hsr.o |
6 | 6 | ||
7 | hsr-y := hsr_main.o hsr_framereg.o hsr_device.o hsr_netlink.o | 7 | hsr-y := hsr_main.o hsr_framereg.o hsr_device.o \ |
8 | hsr_netlink.o hsr_slave.o hsr_forward.o | ||
diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c index e5302b7f7ca9..a138d75751df 100644 --- a/net/hsr/hsr_device.c +++ b/net/hsr/hsr_device.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Copyright 2011-2013 Autronica Fire and Security AS | 1 | /* Copyright 2011-2014 Autronica Fire and Security AS |
2 | * | 2 | * |
3 | * This program is free software; you can redistribute it and/or modify it | 3 | * This program is free software; you can redistribute it and/or modify it |
4 | * under the terms of the GNU General Public License as published by the Free | 4 | * under the terms of the GNU General Public License as published by the Free |
@@ -6,7 +6,7 @@ | |||
6 | * any later version. | 6 | * any later version. |
7 | * | 7 | * |
8 | * Author(s): | 8 | * Author(s): |
9 | * 2011-2013 Arvid Brodin, arvid.brodin@xdin.com | 9 | * 2011-2014 Arvid Brodin, arvid.brodin@alten.se |
10 | * | 10 | * |
11 | * This file contains device methods for creating, using and destroying | 11 | * This file contains device methods for creating, using and destroying |
12 | * virtual HSR devices. | 12 | * virtual HSR devices. |
@@ -15,12 +15,13 @@ | |||
15 | #include <linux/netdevice.h> | 15 | #include <linux/netdevice.h> |
16 | #include <linux/skbuff.h> | 16 | #include <linux/skbuff.h> |
17 | #include <linux/etherdevice.h> | 17 | #include <linux/etherdevice.h> |
18 | #include <linux/if_arp.h> | ||
19 | #include <linux/rtnetlink.h> | 18 | #include <linux/rtnetlink.h> |
20 | #include <linux/pkt_sched.h> | 19 | #include <linux/pkt_sched.h> |
21 | #include "hsr_device.h" | 20 | #include "hsr_device.h" |
21 | #include "hsr_slave.h" | ||
22 | #include "hsr_framereg.h" | 22 | #include "hsr_framereg.h" |
23 | #include "hsr_main.h" | 23 | #include "hsr_main.h" |
24 | #include "hsr_forward.h" | ||
24 | 25 | ||
25 | 26 | ||
26 | static bool is_admin_up(struct net_device *dev) | 27 | static bool is_admin_up(struct net_device *dev) |
@@ -45,75 +46,108 @@ static void __hsr_set_operstate(struct net_device *dev, int transition) | |||
45 | } | 46 | } |
46 | } | 47 | } |
47 | 48 | ||
48 | void hsr_set_operstate(struct net_device *hsr_dev, struct net_device *slave1, | 49 | static void hsr_set_operstate(struct hsr_port *master, bool has_carrier) |
49 | struct net_device *slave2) | ||
50 | { | 50 | { |
51 | if (!is_admin_up(hsr_dev)) { | 51 | if (!is_admin_up(master->dev)) { |
52 | __hsr_set_operstate(hsr_dev, IF_OPER_DOWN); | 52 | __hsr_set_operstate(master->dev, IF_OPER_DOWN); |
53 | return; | 53 | return; |
54 | } | 54 | } |
55 | 55 | ||
56 | if (is_slave_up(slave1) || is_slave_up(slave2)) | 56 | if (has_carrier) |
57 | __hsr_set_operstate(hsr_dev, IF_OPER_UP); | 57 | __hsr_set_operstate(master->dev, IF_OPER_UP); |
58 | else | 58 | else |
59 | __hsr_set_operstate(hsr_dev, IF_OPER_LOWERLAYERDOWN); | 59 | __hsr_set_operstate(master->dev, IF_OPER_LOWERLAYERDOWN); |
60 | } | 60 | } |
61 | 61 | ||
62 | void hsr_set_carrier(struct net_device *hsr_dev, struct net_device *slave1, | 62 | static bool hsr_check_carrier(struct hsr_port *master) |
63 | struct net_device *slave2) | ||
64 | { | 63 | { |
65 | if (is_slave_up(slave1) || is_slave_up(slave2)) | 64 | struct hsr_port *port; |
66 | netif_carrier_on(hsr_dev); | 65 | bool has_carrier; |
66 | |||
67 | has_carrier = false; | ||
68 | |||
69 | rcu_read_lock(); | ||
70 | hsr_for_each_port(master->hsr, port) | ||
71 | if ((port->type != HSR_PT_MASTER) && is_slave_up(port->dev)) { | ||
72 | has_carrier = true; | ||
73 | break; | ||
74 | } | ||
75 | rcu_read_unlock(); | ||
76 | |||
77 | if (has_carrier) | ||
78 | netif_carrier_on(master->dev); | ||
67 | else | 79 | else |
68 | netif_carrier_off(hsr_dev); | 80 | netif_carrier_off(master->dev); |
81 | |||
82 | return has_carrier; | ||
69 | } | 83 | } |
70 | 84 | ||
71 | 85 | ||
72 | void hsr_check_announce(struct net_device *hsr_dev, int old_operstate) | 86 | static void hsr_check_announce(struct net_device *hsr_dev, |
87 | unsigned char old_operstate) | ||
73 | { | 88 | { |
74 | struct hsr_priv *hsr_priv; | 89 | struct hsr_priv *hsr; |
75 | 90 | ||
76 | hsr_priv = netdev_priv(hsr_dev); | 91 | hsr = netdev_priv(hsr_dev); |
77 | 92 | ||
78 | if ((hsr_dev->operstate == IF_OPER_UP) && (old_operstate != IF_OPER_UP)) { | 93 | if ((hsr_dev->operstate == IF_OPER_UP) && (old_operstate != IF_OPER_UP)) { |
79 | /* Went up */ | 94 | /* Went up */ |
80 | hsr_priv->announce_count = 0; | 95 | hsr->announce_count = 0; |
81 | hsr_priv->announce_timer.expires = jiffies + | 96 | hsr->announce_timer.expires = jiffies + |
82 | msecs_to_jiffies(HSR_ANNOUNCE_INTERVAL); | 97 | msecs_to_jiffies(HSR_ANNOUNCE_INTERVAL); |
83 | add_timer(&hsr_priv->announce_timer); | 98 | add_timer(&hsr->announce_timer); |
84 | } | 99 | } |
85 | 100 | ||
86 | if ((hsr_dev->operstate != IF_OPER_UP) && (old_operstate == IF_OPER_UP)) | 101 | if ((hsr_dev->operstate != IF_OPER_UP) && (old_operstate == IF_OPER_UP)) |
87 | /* Went down */ | 102 | /* Went down */ |
88 | del_timer(&hsr_priv->announce_timer); | 103 | del_timer(&hsr->announce_timer); |
89 | } | 104 | } |
90 | 105 | ||
91 | 106 | void hsr_check_carrier_and_operstate(struct hsr_priv *hsr) | |
92 | int hsr_get_max_mtu(struct hsr_priv *hsr_priv) | ||
93 | { | 107 | { |
94 | int mtu_max; | 108 | struct hsr_port *master; |
95 | 109 | unsigned char old_operstate; | |
96 | if (hsr_priv->slave[0] && hsr_priv->slave[1]) | 110 | bool has_carrier; |
97 | mtu_max = min(hsr_priv->slave[0]->mtu, hsr_priv->slave[1]->mtu); | ||
98 | else if (hsr_priv->slave[0]) | ||
99 | mtu_max = hsr_priv->slave[0]->mtu; | ||
100 | else if (hsr_priv->slave[1]) | ||
101 | mtu_max = hsr_priv->slave[1]->mtu; | ||
102 | else | ||
103 | mtu_max = HSR_TAGLEN; | ||
104 | 111 | ||
105 | return mtu_max - HSR_TAGLEN; | 112 | master = hsr_port_get_hsr(hsr, HSR_PT_MASTER); |
113 | /* netif_stacked_transfer_operstate() cannot be used here since | ||
114 | * it doesn't set IF_OPER_LOWERLAYERDOWN (?) | ||
115 | */ | ||
116 | old_operstate = master->dev->operstate; | ||
117 | has_carrier = hsr_check_carrier(master); | ||
118 | hsr_set_operstate(master, has_carrier); | ||
119 | hsr_check_announce(master->dev, old_operstate); | ||
106 | } | 120 | } |
107 | 121 | ||
122 | int hsr_get_max_mtu(struct hsr_priv *hsr) | ||
123 | { | ||
124 | unsigned int mtu_max; | ||
125 | struct hsr_port *port; | ||
126 | |||
127 | mtu_max = ETH_DATA_LEN; | ||
128 | rcu_read_lock(); | ||
129 | hsr_for_each_port(hsr, port) | ||
130 | if (port->type != HSR_PT_MASTER) | ||
131 | mtu_max = min(port->dev->mtu, mtu_max); | ||
132 | rcu_read_unlock(); | ||
133 | |||
134 | if (mtu_max < HSR_HLEN) | ||
135 | return 0; | ||
136 | return mtu_max - HSR_HLEN; | ||
137 | } | ||
138 | |||
139 | |||
108 | static int hsr_dev_change_mtu(struct net_device *dev, int new_mtu) | 140 | static int hsr_dev_change_mtu(struct net_device *dev, int new_mtu) |
109 | { | 141 | { |
110 | struct hsr_priv *hsr_priv; | 142 | struct hsr_priv *hsr; |
143 | struct hsr_port *master; | ||
111 | 144 | ||
112 | hsr_priv = netdev_priv(dev); | 145 | hsr = netdev_priv(dev); |
146 | master = hsr_port_get_hsr(hsr, HSR_PT_MASTER); | ||
113 | 147 | ||
114 | if (new_mtu > hsr_get_max_mtu(hsr_priv)) { | 148 | if (new_mtu > hsr_get_max_mtu(hsr)) { |
115 | netdev_info(hsr_priv->dev, "A HSR master's MTU cannot be greater than the smallest MTU of its slaves minus the HSR Tag length (%d octets).\n", | 149 | netdev_info(master->dev, "A HSR master's MTU cannot be greater than the smallest MTU of its slaves minus the HSR Tag length (%d octets).\n", |
116 | HSR_TAGLEN); | 150 | HSR_HLEN); |
117 | return -EINVAL; | 151 | return -EINVAL; |
118 | } | 152 | } |
119 | 153 | ||
@@ -124,164 +158,95 @@ static int hsr_dev_change_mtu(struct net_device *dev, int new_mtu) | |||
124 | 158 | ||
125 | static int hsr_dev_open(struct net_device *dev) | 159 | static int hsr_dev_open(struct net_device *dev) |
126 | { | 160 | { |
127 | struct hsr_priv *hsr_priv; | 161 | struct hsr_priv *hsr; |
128 | int i; | 162 | struct hsr_port *port; |
129 | char *slave_name; | 163 | char designation; |
130 | 164 | ||
131 | hsr_priv = netdev_priv(dev); | 165 | hsr = netdev_priv(dev); |
166 | designation = '\0'; | ||
132 | 167 | ||
133 | for (i = 0; i < HSR_MAX_SLAVE; i++) { | 168 | rcu_read_lock(); |
134 | if (hsr_priv->slave[i]) | 169 | hsr_for_each_port(hsr, port) { |
135 | slave_name = hsr_priv->slave[i]->name; | 170 | if (port->type == HSR_PT_MASTER) |
136 | else | 171 | continue; |
137 | slave_name = "null"; | 172 | switch (port->type) { |
138 | 173 | case HSR_PT_SLAVE_A: | |
139 | if (!is_slave_up(hsr_priv->slave[i])) | 174 | designation = 'A'; |
140 | netdev_warn(dev, "Slave %c (%s) is not up; please bring it up to get a working HSR network\n", | 175 | break; |
141 | 'A' + i, slave_name); | 176 | case HSR_PT_SLAVE_B: |
177 | designation = 'B'; | ||
178 | break; | ||
179 | default: | ||
180 | designation = '?'; | ||
181 | } | ||
182 | if (!is_slave_up(port->dev)) | ||
183 | netdev_warn(dev, "Slave %c (%s) is not up; please bring it up to get a fully working HSR network\n", | ||
184 | designation, port->dev->name); | ||
142 | } | 185 | } |
186 | rcu_read_unlock(); | ||
187 | |||
188 | if (designation == '\0') | ||
189 | netdev_warn(dev, "No slave devices configured\n"); | ||
143 | 190 | ||
144 | return 0; | 191 | return 0; |
145 | } | 192 | } |
146 | 193 | ||
194 | |||
147 | static int hsr_dev_close(struct net_device *dev) | 195 | static int hsr_dev_close(struct net_device *dev) |
148 | { | 196 | { |
149 | /* Nothing to do here. We could try to restore the state of the slaves | 197 | /* Nothing to do here. */ |
150 | * to what they were before being changed by the hsr master dev's state, | ||
151 | * but they might have been changed manually in the mean time too, so | ||
152 | * taking them up or down here might be confusing and is probably not a | ||
153 | * good idea. | ||
154 | */ | ||
155 | return 0; | 198 | return 0; |
156 | } | 199 | } |
157 | 200 | ||
158 | 201 | ||
159 | static void hsr_fill_tag(struct hsr_ethhdr *hsr_ethhdr, struct hsr_priv *hsr_priv) | 202 | static netdev_features_t hsr_features_recompute(struct hsr_priv *hsr, |
203 | netdev_features_t features) | ||
160 | { | 204 | { |
161 | unsigned long irqflags; | 205 | netdev_features_t mask; |
206 | struct hsr_port *port; | ||
162 | 207 | ||
163 | /* IEC 62439-1:2010, p 48, says the 4-bit "path" field can take values | 208 | mask = features; |
164 | * between 0001-1001 ("ring identifier", for regular HSR frames), | ||
165 | * or 1111 ("HSR management", supervision frames). Unfortunately, the | ||
166 | * spec writers forgot to explain what a "ring identifier" is, or | ||
167 | * how it is used. So we just set this to 0001 for regular frames, | ||
168 | * and 1111 for supervision frames. | ||
169 | */ | ||
170 | set_hsr_tag_path(&hsr_ethhdr->hsr_tag, 0x1); | ||
171 | 209 | ||
172 | /* IEC 62439-1:2010, p 12: "The link service data unit in an Ethernet | 210 | /* Mask out all features that, if supported by one device, should be |
173 | * frame is the content of the frame located between the Length/Type | 211 | * enabled for all devices (see NETIF_F_ONE_FOR_ALL). |
174 | * field and the Frame Check Sequence." | ||
175 | * | 212 | * |
176 | * IEC 62439-3, p 48, specifies the "original LPDU" to include the | 213 | * Anything that's off in mask will not be enabled - so only things |
177 | * original "LT" field (what "LT" means is not explained anywhere as | 214 | * that were in features originally, and also is in NETIF_F_ONE_FOR_ALL, |
178 | * far as I can see - perhaps "Length/Type"?). So LSDU_size might | 215 | * may become enabled. |
179 | * equal original length + 2. | ||
180 | * Also, the fact that this field is not used anywhere (might be used | ||
181 | * by a RedBox connecting HSR and PRP nets?) means I cannot test its | ||
182 | * correctness. Instead of guessing, I set this to 0 here, to make any | ||
183 | * problems immediately apparent. Anyone using this driver with PRP/HSR | ||
184 | * RedBoxes might need to fix this... | ||
185 | */ | 216 | */ |
186 | set_hsr_tag_LSDU_size(&hsr_ethhdr->hsr_tag, 0); | 217 | features &= ~NETIF_F_ONE_FOR_ALL; |
187 | 218 | hsr_for_each_port(hsr, port) | |
188 | spin_lock_irqsave(&hsr_priv->seqnr_lock, irqflags); | 219 | features = netdev_increment_features(features, |
189 | hsr_ethhdr->hsr_tag.sequence_nr = htons(hsr_priv->sequence_nr); | 220 | port->dev->features, |
190 | hsr_priv->sequence_nr++; | 221 | mask); |
191 | spin_unlock_irqrestore(&hsr_priv->seqnr_lock, irqflags); | ||
192 | 222 | ||
193 | hsr_ethhdr->hsr_tag.encap_proto = hsr_ethhdr->ethhdr.h_proto; | 223 | return features; |
194 | |||
195 | hsr_ethhdr->ethhdr.h_proto = htons(ETH_P_PRP); | ||
196 | } | 224 | } |
197 | 225 | ||
198 | static int slave_xmit(struct sk_buff *skb, struct hsr_priv *hsr_priv, | 226 | static netdev_features_t hsr_fix_features(struct net_device *dev, |
199 | enum hsr_dev_idx dev_idx) | 227 | netdev_features_t features) |
200 | { | 228 | { |
201 | struct hsr_ethhdr *hsr_ethhdr; | 229 | struct hsr_priv *hsr = netdev_priv(dev); |
202 | |||
203 | hsr_ethhdr = (struct hsr_ethhdr *) skb->data; | ||
204 | 230 | ||
205 | skb->dev = hsr_priv->slave[dev_idx]; | 231 | return hsr_features_recompute(hsr, features); |
206 | |||
207 | hsr_addr_subst_dest(hsr_priv, &hsr_ethhdr->ethhdr, dev_idx); | ||
208 | |||
209 | /* Address substitution (IEC62439-3 pp 26, 50): replace mac | ||
210 | * address of outgoing frame with that of the outgoing slave's. | ||
211 | */ | ||
212 | ether_addr_copy(hsr_ethhdr->ethhdr.h_source, skb->dev->dev_addr); | ||
213 | |||
214 | return dev_queue_xmit(skb); | ||
215 | } | 232 | } |
216 | 233 | ||
217 | 234 | ||
218 | static int hsr_dev_xmit(struct sk_buff *skb, struct net_device *dev) | 235 | static int hsr_dev_xmit(struct sk_buff *skb, struct net_device *dev) |
219 | { | 236 | { |
220 | struct hsr_priv *hsr_priv; | 237 | struct hsr_priv *hsr = netdev_priv(dev); |
221 | struct hsr_ethhdr *hsr_ethhdr; | 238 | struct hsr_port *master; |
222 | struct sk_buff *skb2; | ||
223 | int res1, res2; | ||
224 | |||
225 | hsr_priv = netdev_priv(dev); | ||
226 | hsr_ethhdr = (struct hsr_ethhdr *) skb->data; | ||
227 | |||
228 | if ((skb->protocol != htons(ETH_P_PRP)) || | ||
229 | (hsr_ethhdr->ethhdr.h_proto != htons(ETH_P_PRP))) { | ||
230 | hsr_fill_tag(hsr_ethhdr, hsr_priv); | ||
231 | skb->protocol = htons(ETH_P_PRP); | ||
232 | } | ||
233 | |||
234 | skb2 = pskb_copy(skb, GFP_ATOMIC); | ||
235 | |||
236 | res1 = NET_XMIT_DROP; | ||
237 | if (likely(hsr_priv->slave[HSR_DEV_SLAVE_A])) | ||
238 | res1 = slave_xmit(skb, hsr_priv, HSR_DEV_SLAVE_A); | ||
239 | 239 | ||
240 | res2 = NET_XMIT_DROP; | 240 | master = hsr_port_get_hsr(hsr, HSR_PT_MASTER); |
241 | if (likely(skb2 && hsr_priv->slave[HSR_DEV_SLAVE_B])) | 241 | skb->dev = master->dev; |
242 | res2 = slave_xmit(skb2, hsr_priv, HSR_DEV_SLAVE_B); | 242 | hsr_forward_skb(skb, master); |
243 | |||
244 | if (likely(res1 == NET_XMIT_SUCCESS || res1 == NET_XMIT_CN || | ||
245 | res2 == NET_XMIT_SUCCESS || res2 == NET_XMIT_CN)) { | ||
246 | hsr_priv->dev->stats.tx_packets++; | ||
247 | hsr_priv->dev->stats.tx_bytes += skb->len; | ||
248 | } else { | ||
249 | hsr_priv->dev->stats.tx_dropped++; | ||
250 | } | ||
251 | 243 | ||
252 | return NETDEV_TX_OK; | 244 | return NETDEV_TX_OK; |
253 | } | 245 | } |
254 | 246 | ||
255 | 247 | ||
256 | static int hsr_header_create(struct sk_buff *skb, struct net_device *dev, | ||
257 | unsigned short type, const void *daddr, | ||
258 | const void *saddr, unsigned int len) | ||
259 | { | ||
260 | int res; | ||
261 | |||
262 | /* Make room for the HSR tag now. We will fill it in later (in | ||
263 | * hsr_dev_xmit) | ||
264 | */ | ||
265 | if (skb_headroom(skb) < HSR_TAGLEN + ETH_HLEN) | ||
266 | return -ENOBUFS; | ||
267 | skb_push(skb, HSR_TAGLEN); | ||
268 | |||
269 | /* To allow VLAN/HSR combos we should probably use | ||
270 | * res = dev_hard_header(skb, dev, type, daddr, saddr, len + HSR_TAGLEN); | ||
271 | * here instead. It would require other changes too, though - e.g. | ||
272 | * separate headers for each slave etc... | ||
273 | */ | ||
274 | res = eth_header(skb, dev, type, daddr, saddr, len + HSR_TAGLEN); | ||
275 | if (res <= 0) | ||
276 | return res; | ||
277 | skb_reset_mac_header(skb); | ||
278 | |||
279 | return res + HSR_TAGLEN; | ||
280 | } | ||
281 | |||
282 | |||
283 | static const struct header_ops hsr_header_ops = { | 248 | static const struct header_ops hsr_header_ops = { |
284 | .create = hsr_header_create, | 249 | .create = eth_header, |
285 | .parse = eth_header_parse, | 250 | .parse = eth_header_parse, |
286 | }; | 251 | }; |
287 | 252 | ||
@@ -291,67 +256,63 @@ static const struct header_ops hsr_header_ops = { | |||
291 | */ | 256 | */ |
292 | static int hsr_pad(int size) | 257 | static int hsr_pad(int size) |
293 | { | 258 | { |
294 | const int min_size = ETH_ZLEN - HSR_TAGLEN - ETH_HLEN; | 259 | const int min_size = ETH_ZLEN - HSR_HLEN - ETH_HLEN; |
295 | 260 | ||
296 | if (size >= min_size) | 261 | if (size >= min_size) |
297 | return size; | 262 | return size; |
298 | return min_size; | 263 | return min_size; |
299 | } | 264 | } |
300 | 265 | ||
301 | static void send_hsr_supervision_frame(struct net_device *hsr_dev, u8 type) | 266 | static void send_hsr_supervision_frame(struct hsr_port *master, u8 type) |
302 | { | 267 | { |
303 | struct hsr_priv *hsr_priv; | ||
304 | struct sk_buff *skb; | 268 | struct sk_buff *skb; |
305 | int hlen, tlen; | 269 | int hlen, tlen; |
306 | struct hsr_sup_tag *hsr_stag; | 270 | struct hsr_sup_tag *hsr_stag; |
307 | struct hsr_sup_payload *hsr_sp; | 271 | struct hsr_sup_payload *hsr_sp; |
308 | unsigned long irqflags; | 272 | unsigned long irqflags; |
309 | 273 | ||
310 | hlen = LL_RESERVED_SPACE(hsr_dev); | 274 | hlen = LL_RESERVED_SPACE(master->dev); |
311 | tlen = hsr_dev->needed_tailroom; | 275 | tlen = master->dev->needed_tailroom; |
312 | skb = alloc_skb(hsr_pad(sizeof(struct hsr_sup_payload)) + hlen + tlen, | 276 | skb = alloc_skb(hsr_pad(sizeof(struct hsr_sup_payload)) + hlen + tlen, |
313 | GFP_ATOMIC); | 277 | GFP_ATOMIC); |
314 | 278 | ||
315 | if (skb == NULL) | 279 | if (skb == NULL) |
316 | return; | 280 | return; |
317 | 281 | ||
318 | hsr_priv = netdev_priv(hsr_dev); | ||
319 | |||
320 | skb_reserve(skb, hlen); | 282 | skb_reserve(skb, hlen); |
321 | 283 | ||
322 | skb->dev = hsr_dev; | 284 | skb->dev = master->dev; |
323 | skb->protocol = htons(ETH_P_PRP); | 285 | skb->protocol = htons(ETH_P_PRP); |
324 | skb->priority = TC_PRIO_CONTROL; | 286 | skb->priority = TC_PRIO_CONTROL; |
325 | 287 | ||
326 | if (dev_hard_header(skb, skb->dev, ETH_P_PRP, | 288 | if (dev_hard_header(skb, skb->dev, ETH_P_PRP, |
327 | hsr_priv->sup_multicast_addr, | 289 | master->hsr->sup_multicast_addr, |
328 | skb->dev->dev_addr, skb->len) < 0) | 290 | skb->dev->dev_addr, skb->len) <= 0) |
329 | goto out; | 291 | goto out; |
292 | skb_reset_mac_header(skb); | ||
330 | 293 | ||
331 | skb_pull(skb, sizeof(struct ethhdr)); | 294 | hsr_stag = (typeof(hsr_stag)) skb_put(skb, sizeof(*hsr_stag)); |
332 | hsr_stag = (typeof(hsr_stag)) skb->data; | ||
333 | 295 | ||
334 | set_hsr_stag_path(hsr_stag, 0xf); | 296 | set_hsr_stag_path(hsr_stag, 0xf); |
335 | set_hsr_stag_HSR_Ver(hsr_stag, 0); | 297 | set_hsr_stag_HSR_Ver(hsr_stag, 0); |
336 | 298 | ||
337 | spin_lock_irqsave(&hsr_priv->seqnr_lock, irqflags); | 299 | spin_lock_irqsave(&master->hsr->seqnr_lock, irqflags); |
338 | hsr_stag->sequence_nr = htons(hsr_priv->sequence_nr); | 300 | hsr_stag->sequence_nr = htons(master->hsr->sequence_nr); |
339 | hsr_priv->sequence_nr++; | 301 | master->hsr->sequence_nr++; |
340 | spin_unlock_irqrestore(&hsr_priv->seqnr_lock, irqflags); | 302 | spin_unlock_irqrestore(&master->hsr->seqnr_lock, irqflags); |
341 | 303 | ||
342 | hsr_stag->HSR_TLV_Type = type; | 304 | hsr_stag->HSR_TLV_Type = type; |
343 | hsr_stag->HSR_TLV_Length = 12; | 305 | hsr_stag->HSR_TLV_Length = 12; |
344 | 306 | ||
345 | skb_push(skb, sizeof(struct ethhdr)); | ||
346 | |||
347 | /* Payload: MacAddressA */ | 307 | /* Payload: MacAddressA */ |
348 | hsr_sp = (typeof(hsr_sp)) skb_put(skb, sizeof(*hsr_sp)); | 308 | hsr_sp = (typeof(hsr_sp)) skb_put(skb, sizeof(*hsr_sp)); |
349 | ether_addr_copy(hsr_sp->MacAddressA, hsr_dev->dev_addr); | 309 | ether_addr_copy(hsr_sp->MacAddressA, master->dev->dev_addr); |
350 | 310 | ||
351 | dev_queue_xmit(skb); | 311 | hsr_forward_skb(skb, master); |
352 | return; | 312 | return; |
353 | 313 | ||
354 | out: | 314 | out: |
315 | WARN_ON_ONCE("HSR: Could not send supervision frame\n"); | ||
355 | kfree_skb(skb); | 316 | kfree_skb(skb); |
356 | } | 317 | } |
357 | 318 | ||
@@ -360,59 +321,32 @@ out: | |||
360 | */ | 321 | */ |
361 | static void hsr_announce(unsigned long data) | 322 | static void hsr_announce(unsigned long data) |
362 | { | 323 | { |
363 | struct hsr_priv *hsr_priv; | 324 | struct hsr_priv *hsr; |
325 | struct hsr_port *master; | ||
364 | 326 | ||
365 | hsr_priv = (struct hsr_priv *) data; | 327 | hsr = (struct hsr_priv *) data; |
366 | 328 | ||
367 | if (hsr_priv->announce_count < 3) { | 329 | rcu_read_lock(); |
368 | send_hsr_supervision_frame(hsr_priv->dev, HSR_TLV_ANNOUNCE); | 330 | master = hsr_port_get_hsr(hsr, HSR_PT_MASTER); |
369 | hsr_priv->announce_count++; | 331 | |
332 | if (hsr->announce_count < 3) { | ||
333 | send_hsr_supervision_frame(master, HSR_TLV_ANNOUNCE); | ||
334 | hsr->announce_count++; | ||
370 | } else { | 335 | } else { |
371 | send_hsr_supervision_frame(hsr_priv->dev, HSR_TLV_LIFE_CHECK); | 336 | send_hsr_supervision_frame(master, HSR_TLV_LIFE_CHECK); |
372 | } | 337 | } |
373 | 338 | ||
374 | if (hsr_priv->announce_count < 3) | 339 | if (hsr->announce_count < 3) |
375 | hsr_priv->announce_timer.expires = jiffies + | 340 | hsr->announce_timer.expires = jiffies + |
376 | msecs_to_jiffies(HSR_ANNOUNCE_INTERVAL); | 341 | msecs_to_jiffies(HSR_ANNOUNCE_INTERVAL); |
377 | else | 342 | else |
378 | hsr_priv->announce_timer.expires = jiffies + | 343 | hsr->announce_timer.expires = jiffies + |
379 | msecs_to_jiffies(HSR_LIFE_CHECK_INTERVAL); | 344 | msecs_to_jiffies(HSR_LIFE_CHECK_INTERVAL); |
380 | 345 | ||
381 | if (is_admin_up(hsr_priv->dev)) | 346 | if (is_admin_up(master->dev)) |
382 | add_timer(&hsr_priv->announce_timer); | 347 | add_timer(&hsr->announce_timer); |
383 | } | ||
384 | |||
385 | |||
386 | static void restore_slaves(struct net_device *hsr_dev) | ||
387 | { | ||
388 | struct hsr_priv *hsr_priv; | ||
389 | int i; | ||
390 | int res; | ||
391 | |||
392 | hsr_priv = netdev_priv(hsr_dev); | ||
393 | |||
394 | rtnl_lock(); | ||
395 | |||
396 | /* Restore promiscuity */ | ||
397 | for (i = 0; i < HSR_MAX_SLAVE; i++) { | ||
398 | if (!hsr_priv->slave[i]) | ||
399 | continue; | ||
400 | res = dev_set_promiscuity(hsr_priv->slave[i], -1); | ||
401 | if (res) | ||
402 | netdev_info(hsr_dev, | ||
403 | "Cannot restore slave promiscuity (%s, %d)\n", | ||
404 | hsr_priv->slave[i]->name, res); | ||
405 | } | ||
406 | |||
407 | rtnl_unlock(); | ||
408 | } | ||
409 | |||
410 | static void reclaim_hsr_dev(struct rcu_head *rh) | ||
411 | { | ||
412 | struct hsr_priv *hsr_priv; | ||
413 | 348 | ||
414 | hsr_priv = container_of(rh, struct hsr_priv, rcu_head); | 349 | rcu_read_unlock(); |
415 | free_netdev(hsr_priv->dev); | ||
416 | } | 350 | } |
417 | 351 | ||
418 | 352 | ||
@@ -421,14 +355,18 @@ static void reclaim_hsr_dev(struct rcu_head *rh) | |||
421 | */ | 355 | */ |
422 | static void hsr_dev_destroy(struct net_device *hsr_dev) | 356 | static void hsr_dev_destroy(struct net_device *hsr_dev) |
423 | { | 357 | { |
424 | struct hsr_priv *hsr_priv; | 358 | struct hsr_priv *hsr; |
359 | struct hsr_port *port; | ||
425 | 360 | ||
426 | hsr_priv = netdev_priv(hsr_dev); | 361 | hsr = netdev_priv(hsr_dev); |
362 | hsr_for_each_port(hsr, port) | ||
363 | hsr_del_port(port); | ||
427 | 364 | ||
428 | del_timer(&hsr_priv->announce_timer); | 365 | del_timer_sync(&hsr->prune_timer); |
429 | unregister_hsr_master(hsr_priv); /* calls list_del_rcu on hsr_priv */ | 366 | del_timer_sync(&hsr->announce_timer); |
430 | restore_slaves(hsr_dev); | 367 | |
431 | call_rcu(&hsr_priv->rcu_head, reclaim_hsr_dev); /* reclaim hsr_priv */ | 368 | synchronize_rcu(); |
369 | free_netdev(hsr_dev); | ||
432 | } | 370 | } |
433 | 371 | ||
434 | static const struct net_device_ops hsr_device_ops = { | 372 | static const struct net_device_ops hsr_device_ops = { |
@@ -436,62 +374,51 @@ static const struct net_device_ops hsr_device_ops = { | |||
436 | .ndo_open = hsr_dev_open, | 374 | .ndo_open = hsr_dev_open, |
437 | .ndo_stop = hsr_dev_close, | 375 | .ndo_stop = hsr_dev_close, |
438 | .ndo_start_xmit = hsr_dev_xmit, | 376 | .ndo_start_xmit = hsr_dev_xmit, |
377 | .ndo_fix_features = hsr_fix_features, | ||
439 | }; | 378 | }; |
440 | 379 | ||
380 | static struct device_type hsr_type = { | ||
381 | .name = "hsr", | ||
382 | }; | ||
441 | 383 | ||
442 | void hsr_dev_setup(struct net_device *dev) | 384 | void hsr_dev_setup(struct net_device *dev) |
443 | { | 385 | { |
444 | random_ether_addr(dev->dev_addr); | 386 | random_ether_addr(dev->dev_addr); |
445 | 387 | ||
446 | ether_setup(dev); | 388 | ether_setup(dev); |
447 | dev->header_ops = &hsr_header_ops; | 389 | dev->header_ops = &hsr_header_ops; |
448 | dev->netdev_ops = &hsr_device_ops; | 390 | dev->netdev_ops = &hsr_device_ops; |
449 | dev->tx_queue_len = 0; | 391 | SET_NETDEV_DEVTYPE(dev, &hsr_type); |
392 | dev->tx_queue_len = 0; | ||
450 | 393 | ||
451 | dev->destructor = hsr_dev_destroy; | 394 | dev->destructor = hsr_dev_destroy; |
395 | |||
396 | dev->hw_features = NETIF_F_SG | NETIF_F_FRAGLIST | NETIF_F_HIGHDMA | | ||
397 | NETIF_F_GSO_MASK | NETIF_F_HW_CSUM | | ||
398 | NETIF_F_HW_VLAN_CTAG_TX; | ||
399 | |||
400 | dev->features = dev->hw_features; | ||
401 | |||
402 | /* Prevent recursive tx locking */ | ||
403 | dev->features |= NETIF_F_LLTX; | ||
404 | /* VLAN on top of HSR needs testing and probably some work on | ||
405 | * hsr_header_create() etc. | ||
406 | */ | ||
407 | dev->features |= NETIF_F_VLAN_CHALLENGED; | ||
408 | /* Not sure about this. Taken from bridge code. netdev_features.h says | ||
409 | * it means "Does not change network namespaces". | ||
410 | */ | ||
411 | dev->features |= NETIF_F_NETNS_LOCAL; | ||
452 | } | 412 | } |
453 | 413 | ||
454 | 414 | ||
455 | /* Return true if dev is a HSR master; return false otherwise. | 415 | /* Return true if dev is a HSR master; return false otherwise. |
456 | */ | 416 | */ |
457 | bool is_hsr_master(struct net_device *dev) | 417 | inline bool is_hsr_master(struct net_device *dev) |
458 | { | 418 | { |
459 | return (dev->netdev_ops->ndo_start_xmit == hsr_dev_xmit); | 419 | return (dev->netdev_ops->ndo_start_xmit == hsr_dev_xmit); |
460 | } | 420 | } |
461 | 421 | ||
462 | static int check_slave_ok(struct net_device *dev) | ||
463 | { | ||
464 | /* Don't allow HSR on non-ethernet like devices */ | ||
465 | if ((dev->flags & IFF_LOOPBACK) || (dev->type != ARPHRD_ETHER) || | ||
466 | (dev->addr_len != ETH_ALEN)) { | ||
467 | netdev_info(dev, "Cannot use loopback or non-ethernet device as HSR slave.\n"); | ||
468 | return -EINVAL; | ||
469 | } | ||
470 | |||
471 | /* Don't allow enslaving hsr devices */ | ||
472 | if (is_hsr_master(dev)) { | ||
473 | netdev_info(dev, "Cannot create trees of HSR devices.\n"); | ||
474 | return -EINVAL; | ||
475 | } | ||
476 | |||
477 | if (is_hsr_slave(dev)) { | ||
478 | netdev_info(dev, "This device is already a HSR slave.\n"); | ||
479 | return -EINVAL; | ||
480 | } | ||
481 | |||
482 | if (dev->priv_flags & IFF_802_1Q_VLAN) { | ||
483 | netdev_info(dev, "HSR on top of VLAN is not yet supported in this driver.\n"); | ||
484 | return -EINVAL; | ||
485 | } | ||
486 | |||
487 | /* HSR over bonded devices has not been tested, but I'm not sure it | ||
488 | * won't work... | ||
489 | */ | ||
490 | |||
491 | return 0; | ||
492 | } | ||
493 | |||
494 | |||
495 | /* Default multicast address for HSR Supervision frames */ | 422 | /* Default multicast address for HSR Supervision frames */ |
496 | static const unsigned char def_multicast_addr[ETH_ALEN] __aligned(2) = { | 423 | static const unsigned char def_multicast_addr[ETH_ALEN] __aligned(2) = { |
497 | 0x01, 0x15, 0x4e, 0x00, 0x01, 0x00 | 424 | 0x01, 0x15, 0x4e, 0x00, 0x01, 0x00 |
@@ -500,97 +427,74 @@ static const unsigned char def_multicast_addr[ETH_ALEN] __aligned(2) = { | |||
500 | int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2], | 427 | int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2], |
501 | unsigned char multicast_spec) | 428 | unsigned char multicast_spec) |
502 | { | 429 | { |
503 | struct hsr_priv *hsr_priv; | 430 | struct hsr_priv *hsr; |
504 | int i; | 431 | struct hsr_port *port; |
505 | int res; | 432 | int res; |
506 | 433 | ||
507 | hsr_priv = netdev_priv(hsr_dev); | 434 | hsr = netdev_priv(hsr_dev); |
508 | hsr_priv->dev = hsr_dev; | 435 | INIT_LIST_HEAD(&hsr->ports); |
509 | INIT_LIST_HEAD(&hsr_priv->node_db); | 436 | INIT_LIST_HEAD(&hsr->node_db); |
510 | INIT_LIST_HEAD(&hsr_priv->self_node_db); | 437 | INIT_LIST_HEAD(&hsr->self_node_db); |
511 | for (i = 0; i < HSR_MAX_SLAVE; i++) | ||
512 | hsr_priv->slave[i] = slave[i]; | ||
513 | |||
514 | spin_lock_init(&hsr_priv->seqnr_lock); | ||
515 | /* Overflow soon to find bugs easier: */ | ||
516 | hsr_priv->sequence_nr = USHRT_MAX - 1024; | ||
517 | |||
518 | init_timer(&hsr_priv->announce_timer); | ||
519 | hsr_priv->announce_timer.function = hsr_announce; | ||
520 | hsr_priv->announce_timer.data = (unsigned long) hsr_priv; | ||
521 | 438 | ||
522 | ether_addr_copy(hsr_priv->sup_multicast_addr, def_multicast_addr); | 439 | ether_addr_copy(hsr_dev->dev_addr, slave[0]->dev_addr); |
523 | hsr_priv->sup_multicast_addr[ETH_ALEN - 1] = multicast_spec; | ||
524 | 440 | ||
525 | /* FIXME: should I modify the value of these? | 441 | /* Make sure we recognize frames from ourselves in hsr_rcv() */ |
526 | * | 442 | res = hsr_create_self_node(&hsr->self_node_db, hsr_dev->dev_addr, |
527 | * - hsr_dev->flags - i.e. | 443 | slave[1]->dev_addr); |
528 | * IFF_MASTER/SLAVE? | 444 | if (res < 0) |
529 | * - hsr_dev->priv_flags - i.e. | 445 | return res; |
530 | * IFF_EBRIDGE? | ||
531 | * IFF_TX_SKB_SHARING? | ||
532 | * IFF_HSR_MASTER/SLAVE? | ||
533 | */ | ||
534 | 446 | ||
535 | for (i = 0; i < HSR_MAX_SLAVE; i++) { | 447 | spin_lock_init(&hsr->seqnr_lock); |
536 | res = check_slave_ok(slave[i]); | 448 | /* Overflow soon to find bugs easier: */ |
537 | if (res) | 449 | hsr->sequence_nr = HSR_SEQNR_START; |
538 | return res; | ||
539 | } | ||
540 | 450 | ||
541 | hsr_dev->features = slave[0]->features & slave[1]->features; | 451 | init_timer(&hsr->announce_timer); |
542 | /* Prevent recursive tx locking */ | 452 | hsr->announce_timer.function = hsr_announce; |
543 | hsr_dev->features |= NETIF_F_LLTX; | 453 | hsr->announce_timer.data = (unsigned long) hsr; |
544 | /* VLAN on top of HSR needs testing and probably some work on | ||
545 | * hsr_header_create() etc. | ||
546 | */ | ||
547 | hsr_dev->features |= NETIF_F_VLAN_CHALLENGED; | ||
548 | 454 | ||
549 | /* Set hsr_dev's MAC address to that of mac_slave1 */ | 455 | init_timer(&hsr->prune_timer); |
550 | ether_addr_copy(hsr_dev->dev_addr, hsr_priv->slave[0]->dev_addr); | 456 | hsr->prune_timer.function = hsr_prune_nodes; |
457 | hsr->prune_timer.data = (unsigned long) hsr; | ||
551 | 458 | ||
552 | /* Set required header length */ | 459 | ether_addr_copy(hsr->sup_multicast_addr, def_multicast_addr); |
553 | for (i = 0; i < HSR_MAX_SLAVE; i++) { | 460 | hsr->sup_multicast_addr[ETH_ALEN - 1] = multicast_spec; |
554 | if (slave[i]->hard_header_len + HSR_TAGLEN > | ||
555 | hsr_dev->hard_header_len) | ||
556 | hsr_dev->hard_header_len = | ||
557 | slave[i]->hard_header_len + HSR_TAGLEN; | ||
558 | } | ||
559 | 461 | ||
560 | /* MTU */ | 462 | /* FIXME: should I modify the value of these? |
561 | for (i = 0; i < HSR_MAX_SLAVE; i++) | 463 | * |
562 | if (slave[i]->mtu - HSR_TAGLEN < hsr_dev->mtu) | 464 | * - hsr_dev->flags - i.e. |
563 | hsr_dev->mtu = slave[i]->mtu - HSR_TAGLEN; | 465 | * IFF_MASTER/SLAVE? |
466 | * - hsr_dev->priv_flags - i.e. | ||
467 | * IFF_EBRIDGE? | ||
468 | * IFF_TX_SKB_SHARING? | ||
469 | * IFF_HSR_MASTER/SLAVE? | ||
470 | */ | ||
564 | 471 | ||
565 | /* Make sure the 1st call to netif_carrier_on() gets through */ | 472 | /* Make sure the 1st call to netif_carrier_on() gets through */ |
566 | netif_carrier_off(hsr_dev); | 473 | netif_carrier_off(hsr_dev); |
567 | 474 | ||
568 | /* Promiscuity */ | 475 | res = hsr_add_port(hsr, hsr_dev, HSR_PT_MASTER); |
569 | for (i = 0; i < HSR_MAX_SLAVE; i++) { | 476 | if (res) |
570 | res = dev_set_promiscuity(slave[i], 1); | 477 | return res; |
571 | if (res) { | ||
572 | netdev_info(hsr_dev, "Cannot set slave promiscuity (%s, %d)\n", | ||
573 | slave[i]->name, res); | ||
574 | goto fail; | ||
575 | } | ||
576 | } | ||
577 | 478 | ||
578 | /* Make sure we recognize frames from ourselves in hsr_rcv() */ | 479 | res = register_netdevice(hsr_dev); |
579 | res = hsr_create_self_node(&hsr_priv->self_node_db, | 480 | if (res) |
580 | hsr_dev->dev_addr, | ||
581 | hsr_priv->slave[1]->dev_addr); | ||
582 | if (res < 0) | ||
583 | goto fail; | 481 | goto fail; |
584 | 482 | ||
585 | res = register_netdevice(hsr_dev); | 483 | res = hsr_add_port(hsr, slave[0], HSR_PT_SLAVE_A); |
484 | if (res) | ||
485 | goto fail; | ||
486 | res = hsr_add_port(hsr, slave[1], HSR_PT_SLAVE_B); | ||
586 | if (res) | 487 | if (res) |
587 | goto fail; | 488 | goto fail; |
588 | 489 | ||
589 | register_hsr_master(hsr_priv); | 490 | hsr->prune_timer.expires = jiffies + msecs_to_jiffies(PRUNE_PERIOD); |
491 | add_timer(&hsr->prune_timer); | ||
590 | 492 | ||
591 | return 0; | 493 | return 0; |
592 | 494 | ||
593 | fail: | 495 | fail: |
594 | restore_slaves(hsr_dev); | 496 | hsr_for_each_port(hsr, port) |
497 | hsr_del_port(port); | ||
498 | |||
595 | return res; | 499 | return res; |
596 | } | 500 | } |
diff --git a/net/hsr/hsr_device.h b/net/hsr/hsr_device.h index 2c7148e73914..108a5d59d2a6 100644 --- a/net/hsr/hsr_device.h +++ b/net/hsr/hsr_device.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Copyright 2011-2013 Autronica Fire and Security AS | 1 | /* Copyright 2011-2014 Autronica Fire and Security AS |
2 | * | 2 | * |
3 | * This program is free software; you can redistribute it and/or modify it | 3 | * This program is free software; you can redistribute it and/or modify it |
4 | * under the terms of the GNU General Public License as published by the Free | 4 | * under the terms of the GNU General Public License as published by the Free |
@@ -6,7 +6,7 @@ | |||
6 | * any later version. | 6 | * any later version. |
7 | * | 7 | * |
8 | * Author(s): | 8 | * Author(s): |
9 | * 2011-2013 Arvid Brodin, arvid.brodin@xdin.com | 9 | * 2011-2014 Arvid Brodin, arvid.brodin@alten.se |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #ifndef __HSR_DEVICE_H | 12 | #ifndef __HSR_DEVICE_H |
@@ -18,12 +18,8 @@ | |||
18 | void hsr_dev_setup(struct net_device *dev); | 18 | void hsr_dev_setup(struct net_device *dev); |
19 | int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2], | 19 | int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2], |
20 | unsigned char multicast_spec); | 20 | unsigned char multicast_spec); |
21 | void hsr_set_operstate(struct net_device *hsr_dev, struct net_device *slave1, | 21 | void hsr_check_carrier_and_operstate(struct hsr_priv *hsr); |
22 | struct net_device *slave2); | ||
23 | void hsr_set_carrier(struct net_device *hsr_dev, struct net_device *slave1, | ||
24 | struct net_device *slave2); | ||
25 | void hsr_check_announce(struct net_device *hsr_dev, int old_operstate); | ||
26 | bool is_hsr_master(struct net_device *dev); | 22 | bool is_hsr_master(struct net_device *dev); |
27 | int hsr_get_max_mtu(struct hsr_priv *hsr_priv); | 23 | int hsr_get_max_mtu(struct hsr_priv *hsr); |
28 | 24 | ||
29 | #endif /* __HSR_DEVICE_H */ | 25 | #endif /* __HSR_DEVICE_H */ |
diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c new file mode 100644 index 000000000000..7871ed6d3825 --- /dev/null +++ b/net/hsr/hsr_forward.c | |||
@@ -0,0 +1,368 @@ | |||
1 | /* Copyright 2011-2014 Autronica Fire and Security AS | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify it | ||
4 | * under the terms of the GNU General Public License as published by the Free | ||
5 | * Software Foundation; either version 2 of the License, or (at your option) | ||
6 | * any later version. | ||
7 | * | ||
8 | * Author(s): | ||
9 | * 2011-2014 Arvid Brodin, arvid.brodin@alten.se | ||
10 | */ | ||
11 | |||
12 | #include "hsr_forward.h" | ||
13 | #include <linux/types.h> | ||
14 | #include <linux/skbuff.h> | ||
15 | #include <linux/etherdevice.h> | ||
16 | #include <linux/if_vlan.h> | ||
17 | #include "hsr_main.h" | ||
18 | #include "hsr_framereg.h" | ||
19 | |||
20 | |||
21 | struct hsr_node; | ||
22 | |||
23 | struct hsr_frame_info { | ||
24 | struct sk_buff *skb_std; | ||
25 | struct sk_buff *skb_hsr; | ||
26 | struct hsr_port *port_rcv; | ||
27 | struct hsr_node *node_src; | ||
28 | u16 sequence_nr; | ||
29 | bool is_supervision; | ||
30 | bool is_vlan; | ||
31 | bool is_local_dest; | ||
32 | bool is_local_exclusive; | ||
33 | }; | ||
34 | |||
35 | |||
36 | /* The uses I can see for these HSR supervision frames are: | ||
37 | * 1) Use the frames that are sent after node initialization ("HSR_TLV.Type = | ||
38 | * 22") to reset any sequence_nr counters belonging to that node. Useful if | ||
39 | * the other node's counter has been reset for some reason. | ||
40 | * -- | ||
41 | * Or not - resetting the counter and bridging the frame would create a | ||
42 | * loop, unfortunately. | ||
43 | * | ||
44 | * 2) Use the LifeCheck frames to detect ring breaks. I.e. if no LifeCheck | ||
45 | * frame is received from a particular node, we know something is wrong. | ||
46 | * We just register these (as with normal frames) and throw them away. | ||
47 | * | ||
48 | * 3) Allow different MAC addresses for the two slave interfaces, using the | ||
49 | * MacAddressA field. | ||
50 | */ | ||
51 | static bool is_supervision_frame(struct hsr_priv *hsr, struct sk_buff *skb) | ||
52 | { | ||
53 | struct hsr_ethhdr_sp *hdr; | ||
54 | |||
55 | WARN_ON_ONCE(!skb_mac_header_was_set(skb)); | ||
56 | hdr = (struct hsr_ethhdr_sp *) skb_mac_header(skb); | ||
57 | |||
58 | if (!ether_addr_equal(hdr->ethhdr.h_dest, | ||
59 | hsr->sup_multicast_addr)) | ||
60 | return false; | ||
61 | |||
62 | if (get_hsr_stag_path(&hdr->hsr_sup) != 0x0f) | ||
63 | return false; | ||
64 | if ((hdr->hsr_sup.HSR_TLV_Type != HSR_TLV_ANNOUNCE) && | ||
65 | (hdr->hsr_sup.HSR_TLV_Type != HSR_TLV_LIFE_CHECK)) | ||
66 | return false; | ||
67 | if (hdr->hsr_sup.HSR_TLV_Length != 12) | ||
68 | return false; | ||
69 | |||
70 | return true; | ||
71 | } | ||
72 | |||
73 | |||
74 | static struct sk_buff *create_stripped_skb(struct sk_buff *skb_in, | ||
75 | struct hsr_frame_info *frame) | ||
76 | { | ||
77 | struct sk_buff *skb; | ||
78 | int copylen; | ||
79 | unsigned char *dst, *src; | ||
80 | |||
81 | skb_pull(skb_in, HSR_HLEN); | ||
82 | skb = __pskb_copy(skb_in, skb_headroom(skb_in) - HSR_HLEN, GFP_ATOMIC); | ||
83 | skb_push(skb_in, HSR_HLEN); | ||
84 | if (skb == NULL) | ||
85 | return NULL; | ||
86 | |||
87 | skb_reset_mac_header(skb); | ||
88 | |||
89 | if (skb->ip_summed == CHECKSUM_PARTIAL) | ||
90 | skb->csum_start -= HSR_HLEN; | ||
91 | |||
92 | copylen = 2*ETH_ALEN; | ||
93 | if (frame->is_vlan) | ||
94 | copylen += VLAN_HLEN; | ||
95 | src = skb_mac_header(skb_in); | ||
96 | dst = skb_mac_header(skb); | ||
97 | memcpy(dst, src, copylen); | ||
98 | |||
99 | skb->protocol = eth_hdr(skb)->h_proto; | ||
100 | return skb; | ||
101 | } | ||
102 | |||
103 | static struct sk_buff *frame_get_stripped_skb(struct hsr_frame_info *frame, | ||
104 | struct hsr_port *port) | ||
105 | { | ||
106 | if (!frame->skb_std) | ||
107 | frame->skb_std = create_stripped_skb(frame->skb_hsr, frame); | ||
108 | return skb_clone(frame->skb_std, GFP_ATOMIC); | ||
109 | } | ||
110 | |||
111 | |||
112 | static void hsr_fill_tag(struct sk_buff *skb, struct hsr_frame_info *frame, | ||
113 | struct hsr_port *port) | ||
114 | { | ||
115 | struct hsr_ethhdr *hsr_ethhdr; | ||
116 | int lane_id; | ||
117 | int lsdu_size; | ||
118 | |||
119 | if (port->type == HSR_PT_SLAVE_A) | ||
120 | lane_id = 0; | ||
121 | else | ||
122 | lane_id = 1; | ||
123 | |||
124 | lsdu_size = skb->len - 14; | ||
125 | if (frame->is_vlan) | ||
126 | lsdu_size -= 4; | ||
127 | |||
128 | hsr_ethhdr = (struct hsr_ethhdr *) skb_mac_header(skb); | ||
129 | |||
130 | set_hsr_tag_path(&hsr_ethhdr->hsr_tag, lane_id); | ||
131 | set_hsr_tag_LSDU_size(&hsr_ethhdr->hsr_tag, lsdu_size); | ||
132 | hsr_ethhdr->hsr_tag.sequence_nr = htons(frame->sequence_nr); | ||
133 | hsr_ethhdr->hsr_tag.encap_proto = hsr_ethhdr->ethhdr.h_proto; | ||
134 | hsr_ethhdr->ethhdr.h_proto = htons(ETH_P_PRP); | ||
135 | } | ||
136 | |||
137 | static struct sk_buff *create_tagged_skb(struct sk_buff *skb_o, | ||
138 | struct hsr_frame_info *frame, | ||
139 | struct hsr_port *port) | ||
140 | { | ||
141 | int movelen; | ||
142 | unsigned char *dst, *src; | ||
143 | struct sk_buff *skb; | ||
144 | |||
145 | /* Create the new skb with enough headroom to fit the HSR tag */ | ||
146 | skb = __pskb_copy(skb_o, skb_headroom(skb_o) + HSR_HLEN, GFP_ATOMIC); | ||
147 | if (skb == NULL) | ||
148 | return NULL; | ||
149 | skb_reset_mac_header(skb); | ||
150 | |||
151 | if (skb->ip_summed == CHECKSUM_PARTIAL) | ||
152 | skb->csum_start += HSR_HLEN; | ||
153 | |||
154 | movelen = ETH_HLEN; | ||
155 | if (frame->is_vlan) | ||
156 | movelen += VLAN_HLEN; | ||
157 | |||
158 | src = skb_mac_header(skb); | ||
159 | dst = skb_push(skb, HSR_HLEN); | ||
160 | memmove(dst, src, movelen); | ||
161 | skb_reset_mac_header(skb); | ||
162 | |||
163 | hsr_fill_tag(skb, frame, port); | ||
164 | |||
165 | return skb; | ||
166 | } | ||
167 | |||
168 | /* If the original frame was an HSR tagged frame, just clone it to be sent | ||
169 | * unchanged. Otherwise, create a private frame especially tagged for 'port'. | ||
170 | */ | ||
171 | static struct sk_buff *frame_get_tagged_skb(struct hsr_frame_info *frame, | ||
172 | struct hsr_port *port) | ||
173 | { | ||
174 | if (frame->skb_hsr) | ||
175 | return skb_clone(frame->skb_hsr, GFP_ATOMIC); | ||
176 | |||
177 | if ((port->type != HSR_PT_SLAVE_A) && (port->type != HSR_PT_SLAVE_B)) { | ||
178 | WARN_ONCE(1, "HSR: Bug: trying to create a tagged frame for a non-ring port"); | ||
179 | return NULL; | ||
180 | } | ||
181 | |||
182 | return create_tagged_skb(frame->skb_std, frame, port); | ||
183 | } | ||
184 | |||
185 | |||
186 | static void hsr_deliver_master(struct sk_buff *skb, struct net_device *dev, | ||
187 | struct hsr_node *node_src) | ||
188 | { | ||
189 | bool was_multicast_frame; | ||
190 | int res; | ||
191 | |||
192 | was_multicast_frame = (skb->pkt_type == PACKET_MULTICAST); | ||
193 | hsr_addr_subst_source(node_src, skb); | ||
194 | skb_pull(skb, ETH_HLEN); | ||
195 | res = netif_rx(skb); | ||
196 | if (res == NET_RX_DROP) { | ||
197 | dev->stats.rx_dropped++; | ||
198 | } else { | ||
199 | dev->stats.rx_packets++; | ||
200 | dev->stats.rx_bytes += skb->len; | ||
201 | if (was_multicast_frame) | ||
202 | dev->stats.multicast++; | ||
203 | } | ||
204 | } | ||
205 | |||
206 | static int hsr_xmit(struct sk_buff *skb, struct hsr_port *port, | ||
207 | struct hsr_frame_info *frame) | ||
208 | { | ||
209 | if (frame->port_rcv->type == HSR_PT_MASTER) { | ||
210 | hsr_addr_subst_dest(frame->node_src, skb, port); | ||
211 | |||
212 | /* Address substitution (IEC62439-3 pp 26, 50): replace mac | ||
213 | * address of outgoing frame with that of the outgoing slave's. | ||
214 | */ | ||
215 | ether_addr_copy(eth_hdr(skb)->h_source, port->dev->dev_addr); | ||
216 | } | ||
217 | return dev_queue_xmit(skb); | ||
218 | } | ||
219 | |||
220 | |||
221 | /* Forward the frame through all devices except: | ||
222 | * - Back through the receiving device | ||
223 | * - If it's a HSR frame: through a device where it has passed before | ||
224 | * - To the local HSR master only if the frame is directly addressed to it, or | ||
225 | * a non-supervision multicast or broadcast frame. | ||
226 | * | ||
227 | * HSR slave devices should insert a HSR tag into the frame, or forward the | ||
228 | * frame unchanged if it's already tagged. Interlink devices should strip HSR | ||
229 | * tags if they're of the non-HSR type (but only after duplicate discard). The | ||
230 | * master device always strips HSR tags. | ||
231 | */ | ||
232 | static void hsr_forward_do(struct hsr_frame_info *frame) | ||
233 | { | ||
234 | struct hsr_port *port; | ||
235 | struct sk_buff *skb; | ||
236 | |||
237 | hsr_for_each_port(frame->port_rcv->hsr, port) { | ||
238 | /* Don't send frame back the way it came */ | ||
239 | if (port == frame->port_rcv) | ||
240 | continue; | ||
241 | |||
242 | /* Don't deliver locally unless we should */ | ||
243 | if ((port->type == HSR_PT_MASTER) && !frame->is_local_dest) | ||
244 | continue; | ||
245 | |||
246 | /* Deliver frames directly addressed to us to master only */ | ||
247 | if ((port->type != HSR_PT_MASTER) && frame->is_local_exclusive) | ||
248 | continue; | ||
249 | |||
250 | /* Don't send frame over port where it has been sent before */ | ||
251 | if (hsr_register_frame_out(port, frame->node_src, | ||
252 | frame->sequence_nr)) | ||
253 | continue; | ||
254 | |||
255 | if (frame->is_supervision && (port->type == HSR_PT_MASTER)) { | ||
256 | hsr_handle_sup_frame(frame->skb_hsr, | ||
257 | frame->node_src, | ||
258 | frame->port_rcv); | ||
259 | continue; | ||
260 | } | ||
261 | |||
262 | if (port->type != HSR_PT_MASTER) | ||
263 | skb = frame_get_tagged_skb(frame, port); | ||
264 | else | ||
265 | skb = frame_get_stripped_skb(frame, port); | ||
266 | if (skb == NULL) { | ||
267 | /* FIXME: Record the dropped frame? */ | ||
268 | continue; | ||
269 | } | ||
270 | |||
271 | skb->dev = port->dev; | ||
272 | if (port->type == HSR_PT_MASTER) | ||
273 | hsr_deliver_master(skb, port->dev, frame->node_src); | ||
274 | else | ||
275 | hsr_xmit(skb, port, frame); | ||
276 | } | ||
277 | } | ||
278 | |||
279 | |||
280 | static void check_local_dest(struct hsr_priv *hsr, struct sk_buff *skb, | ||
281 | struct hsr_frame_info *frame) | ||
282 | { | ||
283 | struct net_device *master_dev; | ||
284 | |||
285 | master_dev = hsr_port_get_hsr(hsr, HSR_PT_MASTER)->dev; | ||
286 | |||
287 | if (hsr_addr_is_self(hsr, eth_hdr(skb)->h_dest)) { | ||
288 | frame->is_local_exclusive = true; | ||
289 | skb->pkt_type = PACKET_HOST; | ||
290 | } else { | ||
291 | frame->is_local_exclusive = false; | ||
292 | } | ||
293 | |||
294 | if ((skb->pkt_type == PACKET_HOST) || | ||
295 | (skb->pkt_type == PACKET_MULTICAST) || | ||
296 | (skb->pkt_type == PACKET_BROADCAST)) { | ||
297 | frame->is_local_dest = true; | ||
298 | } else { | ||
299 | frame->is_local_dest = false; | ||
300 | } | ||
301 | } | ||
302 | |||
303 | |||
304 | static int hsr_fill_frame_info(struct hsr_frame_info *frame, | ||
305 | struct sk_buff *skb, struct hsr_port *port) | ||
306 | { | ||
307 | struct ethhdr *ethhdr; | ||
308 | unsigned long irqflags; | ||
309 | |||
310 | frame->is_supervision = is_supervision_frame(port->hsr, skb); | ||
311 | frame->node_src = hsr_get_node(&port->hsr->node_db, skb, | ||
312 | frame->is_supervision); | ||
313 | if (frame->node_src == NULL) | ||
314 | return -1; /* Unknown node and !is_supervision, or no mem */ | ||
315 | |||
316 | ethhdr = (struct ethhdr *) skb_mac_header(skb); | ||
317 | frame->is_vlan = false; | ||
318 | if (ethhdr->h_proto == htons(ETH_P_8021Q)) { | ||
319 | frame->is_vlan = true; | ||
320 | /* FIXME: */ | ||
321 | WARN_ONCE(1, "HSR: VLAN not yet supported"); | ||
322 | } | ||
323 | if (ethhdr->h_proto == htons(ETH_P_PRP)) { | ||
324 | frame->skb_std = NULL; | ||
325 | frame->skb_hsr = skb; | ||
326 | frame->sequence_nr = hsr_get_skb_sequence_nr(skb); | ||
327 | } else { | ||
328 | frame->skb_std = skb; | ||
329 | frame->skb_hsr = NULL; | ||
330 | /* Sequence nr for the master node */ | ||
331 | spin_lock_irqsave(&port->hsr->seqnr_lock, irqflags); | ||
332 | frame->sequence_nr = port->hsr->sequence_nr; | ||
333 | port->hsr->sequence_nr++; | ||
334 | spin_unlock_irqrestore(&port->hsr->seqnr_lock, irqflags); | ||
335 | } | ||
336 | |||
337 | frame->port_rcv = port; | ||
338 | check_local_dest(port->hsr, skb, frame); | ||
339 | |||
340 | return 0; | ||
341 | } | ||
342 | |||
343 | /* Must be called holding rcu read lock (because of the port parameter) */ | ||
344 | void hsr_forward_skb(struct sk_buff *skb, struct hsr_port *port) | ||
345 | { | ||
346 | struct hsr_frame_info frame; | ||
347 | |||
348 | if (skb_mac_header(skb) != skb->data) { | ||
349 | WARN_ONCE(1, "%s:%d: Malformed frame (port_src %s)\n", | ||
350 | __FILE__, __LINE__, port->dev->name); | ||
351 | goto out_drop; | ||
352 | } | ||
353 | |||
354 | if (hsr_fill_frame_info(&frame, skb, port) < 0) | ||
355 | goto out_drop; | ||
356 | hsr_register_frame_in(frame.node_src, port, frame.sequence_nr); | ||
357 | hsr_forward_do(&frame); | ||
358 | |||
359 | if (frame.skb_hsr != NULL) | ||
360 | kfree_skb(frame.skb_hsr); | ||
361 | if (frame.skb_std != NULL) | ||
362 | kfree_skb(frame.skb_std); | ||
363 | return; | ||
364 | |||
365 | out_drop: | ||
366 | port->dev->stats.tx_dropped++; | ||
367 | kfree_skb(skb); | ||
368 | } | ||
diff --git a/net/hsr/hsr_forward.h b/net/hsr/hsr_forward.h new file mode 100644 index 000000000000..5c5bc4b6b75f --- /dev/null +++ b/net/hsr/hsr_forward.h | |||
@@ -0,0 +1,20 @@ | |||
1 | /* Copyright 2011-2014 Autronica Fire and Security AS | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify it | ||
4 | * under the terms of the GNU General Public License as published by the Free | ||
5 | * Software Foundation; either version 2 of the License, or (at your option) | ||
6 | * any later version. | ||
7 | * | ||
8 | * Author(s): | ||
9 | * 2011-2014 Arvid Brodin, arvid.brodin@alten.se | ||
10 | */ | ||
11 | |||
12 | #ifndef __HSR_FORWARD_H | ||
13 | #define __HSR_FORWARD_H | ||
14 | |||
15 | #include <linux/netdevice.h> | ||
16 | #include "hsr_main.h" | ||
17 | |||
18 | void hsr_forward_skb(struct sk_buff *skb, struct hsr_port *port); | ||
19 | |||
20 | #endif /* __HSR_FORWARD_H */ | ||
diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c index 83e58449366a..bace124d14ef 100644 --- a/net/hsr/hsr_framereg.c +++ b/net/hsr/hsr_framereg.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Copyright 2011-2013 Autronica Fire and Security AS | 1 | /* Copyright 2011-2014 Autronica Fire and Security AS |
2 | * | 2 | * |
3 | * This program is free software; you can redistribute it and/or modify it | 3 | * This program is free software; you can redistribute it and/or modify it |
4 | * under the terms of the GNU General Public License as published by the Free | 4 | * under the terms of the GNU General Public License as published by the Free |
@@ -6,7 +6,7 @@ | |||
6 | * any later version. | 6 | * any later version. |
7 | * | 7 | * |
8 | * Author(s): | 8 | * Author(s): |
9 | * 2011-2013 Arvid Brodin, arvid.brodin@xdin.com | 9 | * 2011-2014 Arvid Brodin, arvid.brodin@alten.se |
10 | * | 10 | * |
11 | * The HSR spec says never to forward the same frame twice on the same | 11 | * The HSR spec says never to forward the same frame twice on the same |
12 | * interface. A frame is identified by its source MAC address and its HSR | 12 | * interface. A frame is identified by its source MAC address and its HSR |
@@ -23,71 +23,68 @@ | |||
23 | #include "hsr_netlink.h" | 23 | #include "hsr_netlink.h" |
24 | 24 | ||
25 | 25 | ||
26 | struct node_entry { | 26 | struct hsr_node { |
27 | struct list_head mac_list; | 27 | struct list_head mac_list; |
28 | unsigned char MacAddressA[ETH_ALEN]; | 28 | unsigned char MacAddressA[ETH_ALEN]; |
29 | unsigned char MacAddressB[ETH_ALEN]; | 29 | unsigned char MacAddressB[ETH_ALEN]; |
30 | enum hsr_dev_idx AddrB_if; /* The local slave through which AddrB | 30 | /* Local slave through which AddrB frames are received from this node */ |
31 | * frames are received from this node | 31 | enum hsr_port_type AddrB_port; |
32 | */ | 32 | unsigned long time_in[HSR_PT_PORTS]; |
33 | unsigned long time_in[HSR_MAX_SLAVE]; | 33 | bool time_in_stale[HSR_PT_PORTS]; |
34 | bool time_in_stale[HSR_MAX_SLAVE]; | 34 | u16 seq_out[HSR_PT_PORTS]; |
35 | u16 seq_out[HSR_MAX_DEV]; | 35 | struct rcu_head rcu_head; |
36 | struct rcu_head rcu_head; | ||
37 | }; | 36 | }; |
38 | 37 | ||
39 | /* TODO: use hash lists for mac addresses (linux/jhash.h)? */ | ||
40 | 38 | ||
39 | /* TODO: use hash lists for mac addresses (linux/jhash.h)? */ | ||
41 | 40 | ||
42 | 41 | ||
43 | /* Search for mac entry. Caller must hold rcu read lock. | 42 | /* seq_nr_after(a, b) - return true if a is after (higher in sequence than) b, |
43 | * false otherwise. | ||
44 | */ | 44 | */ |
45 | static struct node_entry *find_node_by_AddrA(struct list_head *node_db, | 45 | static bool seq_nr_after(u16 a, u16 b) |
46 | const unsigned char addr[ETH_ALEN]) | ||
47 | { | 46 | { |
48 | struct node_entry *node; | 47 | /* Remove inconsistency where |
49 | 48 | * seq_nr_after(a, b) == seq_nr_before(a, b) | |
50 | list_for_each_entry_rcu(node, node_db, mac_list) { | 49 | */ |
51 | if (ether_addr_equal(node->MacAddressA, addr)) | 50 | if ((int) b - a == 32768) |
52 | return node; | 51 | return false; |
53 | } | ||
54 | 52 | ||
55 | return NULL; | 53 | return (((s16) (b - a)) < 0); |
56 | } | 54 | } |
55 | #define seq_nr_before(a, b) seq_nr_after((b), (a)) | ||
56 | #define seq_nr_after_or_eq(a, b) (!seq_nr_before((a), (b))) | ||
57 | #define seq_nr_before_or_eq(a, b) (!seq_nr_after((a), (b))) | ||
57 | 58 | ||
58 | 59 | ||
59 | /* Search for mac entry. Caller must hold rcu read lock. | 60 | bool hsr_addr_is_self(struct hsr_priv *hsr, unsigned char *addr) |
60 | */ | ||
61 | static struct node_entry *find_node_by_AddrB(struct list_head *node_db, | ||
62 | const unsigned char addr[ETH_ALEN]) | ||
63 | { | 61 | { |
64 | struct node_entry *node; | 62 | struct hsr_node *node; |
65 | 63 | ||
66 | list_for_each_entry_rcu(node, node_db, mac_list) { | 64 | node = list_first_or_null_rcu(&hsr->self_node_db, struct hsr_node, |
67 | if (ether_addr_equal(node->MacAddressB, addr)) | 65 | mac_list); |
68 | return node; | 66 | if (!node) { |
67 | WARN_ONCE(1, "HSR: No self node\n"); | ||
68 | return false; | ||
69 | } | 69 | } |
70 | 70 | ||
71 | return NULL; | 71 | if (ether_addr_equal(addr, node->MacAddressA)) |
72 | } | 72 | return true; |
73 | if (ether_addr_equal(addr, node->MacAddressB)) | ||
74 | return true; | ||
73 | 75 | ||
76 | return false; | ||
77 | } | ||
74 | 78 | ||
75 | /* Search for mac entry. Caller must hold rcu read lock. | 79 | /* Search for mac entry. Caller must hold rcu read lock. |
76 | */ | 80 | */ |
77 | struct node_entry *hsr_find_node(struct list_head *node_db, struct sk_buff *skb) | 81 | static struct hsr_node *find_node_by_AddrA(struct list_head *node_db, |
82 | const unsigned char addr[ETH_ALEN]) | ||
78 | { | 83 | { |
79 | struct node_entry *node; | 84 | struct hsr_node *node; |
80 | struct ethhdr *ethhdr; | ||
81 | |||
82 | if (!skb_mac_header_was_set(skb)) | ||
83 | return NULL; | ||
84 | |||
85 | ethhdr = (struct ethhdr *) skb_mac_header(skb); | ||
86 | 85 | ||
87 | list_for_each_entry_rcu(node, node_db, mac_list) { | 86 | list_for_each_entry_rcu(node, node_db, mac_list) { |
88 | if (ether_addr_equal(node->MacAddressA, ethhdr->h_source)) | 87 | if (ether_addr_equal(node->MacAddressA, addr)) |
89 | return node; | ||
90 | if (ether_addr_equal(node->MacAddressB, ethhdr->h_source)) | ||
91 | return node; | 88 | return node; |
92 | } | 89 | } |
93 | 90 | ||
@@ -102,7 +99,7 @@ int hsr_create_self_node(struct list_head *self_node_db, | |||
102 | unsigned char addr_a[ETH_ALEN], | 99 | unsigned char addr_a[ETH_ALEN], |
103 | unsigned char addr_b[ETH_ALEN]) | 100 | unsigned char addr_b[ETH_ALEN]) |
104 | { | 101 | { |
105 | struct node_entry *node, *oldnode; | 102 | struct hsr_node *node, *oldnode; |
106 | 103 | ||
107 | node = kmalloc(sizeof(*node), GFP_KERNEL); | 104 | node = kmalloc(sizeof(*node), GFP_KERNEL); |
108 | if (!node) | 105 | if (!node) |
@@ -113,7 +110,7 @@ int hsr_create_self_node(struct list_head *self_node_db, | |||
113 | 110 | ||
114 | rcu_read_lock(); | 111 | rcu_read_lock(); |
115 | oldnode = list_first_or_null_rcu(self_node_db, | 112 | oldnode = list_first_or_null_rcu(self_node_db, |
116 | struct node_entry, mac_list); | 113 | struct hsr_node, mac_list); |
117 | if (oldnode) { | 114 | if (oldnode) { |
118 | list_replace_rcu(&oldnode->mac_list, &node->mac_list); | 115 | list_replace_rcu(&oldnode->mac_list, &node->mac_list); |
119 | rcu_read_unlock(); | 116 | rcu_read_unlock(); |
@@ -128,135 +125,144 @@ int hsr_create_self_node(struct list_head *self_node_db, | |||
128 | } | 125 | } |
129 | 126 | ||
130 | 127 | ||
131 | /* Add/merge node to the database of nodes. 'skb' must contain an HSR | 128 | /* Allocate an hsr_node and add it to node_db. 'addr' is the node's AddressA; |
132 | * supervision frame. | 129 | * seq_out is used to initialize filtering of outgoing duplicate frames |
133 | * - If the supervision header's MacAddressA field is not yet in the database, | 130 | * originating from the newly added node. |
134 | * this frame is from an hitherto unknown node - add it to the database. | ||
135 | * - If the sender's MAC address is not the same as its MacAddressA address, | ||
136 | * the node is using PICS_SUBS (address substitution). Record the sender's | ||
137 | * address as the node's MacAddressB. | ||
138 | * | ||
139 | * This function needs to work even if the sender node has changed one of its | ||
140 | * slaves' MAC addresses. In this case, there are four different cases described | ||
141 | * by (Addr-changed, received-from) pairs as follows. Note that changing the | ||
142 | * SlaveA address is equal to changing the node's own address: | ||
143 | * | ||
144 | * - (AddrB, SlaveB): The new AddrB will be recorded by PICS_SUBS code since | ||
145 | * node == NULL. | ||
146 | * - (AddrB, SlaveA): Will work as usual (the AddrB change won't be detected | ||
147 | * from this frame). | ||
148 | * | ||
149 | * - (AddrA, SlaveB): The old node will be found. We need to detect this and | ||
150 | * remove the node. | ||
151 | * - (AddrA, SlaveA): A new node will be registered (non-PICS_SUBS at first). | ||
152 | * The old one will be pruned after HSR_NODE_FORGET_TIME. | ||
153 | * | ||
154 | * We also need to detect if the sender's SlaveA and SlaveB cables have been | ||
155 | * swapped. | ||
156 | */ | 131 | */ |
157 | struct node_entry *hsr_merge_node(struct hsr_priv *hsr_priv, | 132 | struct hsr_node *hsr_add_node(struct list_head *node_db, unsigned char addr[], |
158 | struct node_entry *node, | 133 | u16 seq_out) |
159 | struct sk_buff *skb, | ||
160 | enum hsr_dev_idx dev_idx) | ||
161 | { | 134 | { |
162 | struct hsr_sup_payload *hsr_sp; | 135 | struct hsr_node *node; |
163 | struct hsr_ethhdr_sp *hsr_ethsup; | ||
164 | int i; | ||
165 | unsigned long now; | 136 | unsigned long now; |
166 | 137 | int i; | |
167 | hsr_ethsup = (struct hsr_ethhdr_sp *) skb_mac_header(skb); | ||
168 | hsr_sp = (struct hsr_sup_payload *) skb->data; | ||
169 | |||
170 | if (node && !ether_addr_equal(node->MacAddressA, hsr_sp->MacAddressA)) { | ||
171 | /* Node has changed its AddrA, frame was received from SlaveB */ | ||
172 | list_del_rcu(&node->mac_list); | ||
173 | kfree_rcu(node, rcu_head); | ||
174 | node = NULL; | ||
175 | } | ||
176 | |||
177 | if (node && (dev_idx == node->AddrB_if) && | ||
178 | !ether_addr_equal(node->MacAddressB, hsr_ethsup->ethhdr.h_source)) { | ||
179 | /* Cables have been swapped */ | ||
180 | list_del_rcu(&node->mac_list); | ||
181 | kfree_rcu(node, rcu_head); | ||
182 | node = NULL; | ||
183 | } | ||
184 | |||
185 | if (node && (dev_idx != node->AddrB_if) && | ||
186 | (node->AddrB_if != HSR_DEV_NONE) && | ||
187 | !ether_addr_equal(node->MacAddressA, hsr_ethsup->ethhdr.h_source)) { | ||
188 | /* Cables have been swapped */ | ||
189 | list_del_rcu(&node->mac_list); | ||
190 | kfree_rcu(node, rcu_head); | ||
191 | node = NULL; | ||
192 | } | ||
193 | |||
194 | if (node) | ||
195 | return node; | ||
196 | |||
197 | node = find_node_by_AddrA(&hsr_priv->node_db, hsr_sp->MacAddressA); | ||
198 | if (node) { | ||
199 | /* Node is known, but frame was received from an unknown | ||
200 | * address. Node is PICS_SUBS capable; merge its AddrB. | ||
201 | */ | ||
202 | ether_addr_copy(node->MacAddressB, hsr_ethsup->ethhdr.h_source); | ||
203 | node->AddrB_if = dev_idx; | ||
204 | return node; | ||
205 | } | ||
206 | 138 | ||
207 | node = kzalloc(sizeof(*node), GFP_ATOMIC); | 139 | node = kzalloc(sizeof(*node), GFP_ATOMIC); |
208 | if (!node) | 140 | if (!node) |
209 | return NULL; | 141 | return NULL; |
210 | 142 | ||
211 | ether_addr_copy(node->MacAddressA, hsr_sp->MacAddressA); | 143 | ether_addr_copy(node->MacAddressA, addr); |
212 | ether_addr_copy(node->MacAddressB, hsr_ethsup->ethhdr.h_source); | ||
213 | if (!ether_addr_equal(hsr_sp->MacAddressA, hsr_ethsup->ethhdr.h_source)) | ||
214 | node->AddrB_if = dev_idx; | ||
215 | else | ||
216 | node->AddrB_if = HSR_DEV_NONE; | ||
217 | 144 | ||
218 | /* We are only interested in time diffs here, so use current jiffies | 145 | /* We are only interested in time diffs here, so use current jiffies |
219 | * as initialization. (0 could trigger an spurious ring error warning). | 146 | * as initialization. (0 could trigger an spurious ring error warning). |
220 | */ | 147 | */ |
221 | now = jiffies; | 148 | now = jiffies; |
222 | for (i = 0; i < HSR_MAX_SLAVE; i++) | 149 | for (i = 0; i < HSR_PT_PORTS; i++) |
223 | node->time_in[i] = now; | 150 | node->time_in[i] = now; |
224 | for (i = 0; i < HSR_MAX_DEV; i++) | 151 | for (i = 0; i < HSR_PT_PORTS; i++) |
225 | node->seq_out[i] = ntohs(hsr_ethsup->hsr_sup.sequence_nr) - 1; | 152 | node->seq_out[i] = seq_out; |
226 | 153 | ||
227 | list_add_tail_rcu(&node->mac_list, &hsr_priv->node_db); | 154 | list_add_tail_rcu(&node->mac_list, node_db); |
228 | 155 | ||
229 | return node; | 156 | return node; |
230 | } | 157 | } |
231 | 158 | ||
159 | /* Get the hsr_node from which 'skb' was sent. | ||
160 | */ | ||
161 | struct hsr_node *hsr_get_node(struct list_head *node_db, struct sk_buff *skb, | ||
162 | bool is_sup) | ||
163 | { | ||
164 | struct hsr_node *node; | ||
165 | struct ethhdr *ethhdr; | ||
166 | u16 seq_out; | ||
167 | |||
168 | if (!skb_mac_header_was_set(skb)) | ||
169 | return NULL; | ||
170 | |||
171 | ethhdr = (struct ethhdr *) skb_mac_header(skb); | ||
172 | |||
173 | list_for_each_entry_rcu(node, node_db, mac_list) { | ||
174 | if (ether_addr_equal(node->MacAddressA, ethhdr->h_source)) | ||
175 | return node; | ||
176 | if (ether_addr_equal(node->MacAddressB, ethhdr->h_source)) | ||
177 | return node; | ||
178 | } | ||
179 | |||
180 | if (!is_sup) | ||
181 | return NULL; /* Only supervision frame may create node entry */ | ||
182 | |||
183 | if (ethhdr->h_proto == htons(ETH_P_PRP)) { | ||
184 | /* Use the existing sequence_nr from the tag as starting point | ||
185 | * for filtering duplicate frames. | ||
186 | */ | ||
187 | seq_out = hsr_get_skb_sequence_nr(skb) - 1; | ||
188 | } else { | ||
189 | WARN_ONCE(1, "%s: Non-HSR frame\n", __func__); | ||
190 | seq_out = 0; | ||
191 | } | ||
192 | |||
193 | return hsr_add_node(node_db, ethhdr->h_source, seq_out); | ||
194 | } | ||
195 | |||
196 | /* Use the Supervision frame's info about an eventual MacAddressB for merging | ||
197 | * nodes that has previously had their MacAddressB registered as a separate | ||
198 | * node. | ||
199 | */ | ||
200 | void hsr_handle_sup_frame(struct sk_buff *skb, struct hsr_node *node_curr, | ||
201 | struct hsr_port *port_rcv) | ||
202 | { | ||
203 | struct hsr_node *node_real; | ||
204 | struct hsr_sup_payload *hsr_sp; | ||
205 | struct list_head *node_db; | ||
206 | int i; | ||
207 | |||
208 | skb_pull(skb, sizeof(struct hsr_ethhdr_sp)); | ||
209 | hsr_sp = (struct hsr_sup_payload *) skb->data; | ||
210 | |||
211 | if (ether_addr_equal(eth_hdr(skb)->h_source, hsr_sp->MacAddressA)) | ||
212 | /* Not sent from MacAddressB of a PICS_SUBS capable node */ | ||
213 | goto done; | ||
214 | |||
215 | /* Merge node_curr (registered on MacAddressB) into node_real */ | ||
216 | node_db = &port_rcv->hsr->node_db; | ||
217 | node_real = find_node_by_AddrA(node_db, hsr_sp->MacAddressA); | ||
218 | if (!node_real) | ||
219 | /* No frame received from AddrA of this node yet */ | ||
220 | node_real = hsr_add_node(node_db, hsr_sp->MacAddressA, | ||
221 | HSR_SEQNR_START - 1); | ||
222 | if (!node_real) | ||
223 | goto done; /* No mem */ | ||
224 | if (node_real == node_curr) | ||
225 | /* Node has already been merged */ | ||
226 | goto done; | ||
227 | |||
228 | ether_addr_copy(node_real->MacAddressB, eth_hdr(skb)->h_source); | ||
229 | for (i = 0; i < HSR_PT_PORTS; i++) { | ||
230 | if (!node_curr->time_in_stale[i] && | ||
231 | time_after(node_curr->time_in[i], node_real->time_in[i])) { | ||
232 | node_real->time_in[i] = node_curr->time_in[i]; | ||
233 | node_real->time_in_stale[i] = node_curr->time_in_stale[i]; | ||
234 | } | ||
235 | if (seq_nr_after(node_curr->seq_out[i], node_real->seq_out[i])) | ||
236 | node_real->seq_out[i] = node_curr->seq_out[i]; | ||
237 | } | ||
238 | node_real->AddrB_port = port_rcv->type; | ||
239 | |||
240 | list_del_rcu(&node_curr->mac_list); | ||
241 | kfree_rcu(node_curr, rcu_head); | ||
242 | |||
243 | done: | ||
244 | skb_push(skb, sizeof(struct hsr_ethhdr_sp)); | ||
245 | } | ||
246 | |||
232 | 247 | ||
233 | /* 'skb' is a frame meant for this host, that is to be passed to upper layers. | 248 | /* 'skb' is a frame meant for this host, that is to be passed to upper layers. |
234 | * | 249 | * |
235 | * If the frame was sent by a node's B interface, replace the sender | 250 | * If the frame was sent by a node's B interface, replace the source |
236 | * address with that node's "official" address (MacAddressA) so that upper | 251 | * address with that node's "official" address (MacAddressA) so that upper |
237 | * layers recognize where it came from. | 252 | * layers recognize where it came from. |
238 | */ | 253 | */ |
239 | void hsr_addr_subst_source(struct hsr_priv *hsr_priv, struct sk_buff *skb) | 254 | void hsr_addr_subst_source(struct hsr_node *node, struct sk_buff *skb) |
240 | { | 255 | { |
241 | struct ethhdr *ethhdr; | ||
242 | struct node_entry *node; | ||
243 | |||
244 | if (!skb_mac_header_was_set(skb)) { | 256 | if (!skb_mac_header_was_set(skb)) { |
245 | WARN_ONCE(1, "%s: Mac header not set\n", __func__); | 257 | WARN_ONCE(1, "%s: Mac header not set\n", __func__); |
246 | return; | 258 | return; |
247 | } | 259 | } |
248 | ethhdr = (struct ethhdr *) skb_mac_header(skb); | ||
249 | 260 | ||
250 | rcu_read_lock(); | 261 | memcpy(ð_hdr(skb)->h_source, node->MacAddressA, ETH_ALEN); |
251 | node = find_node_by_AddrB(&hsr_priv->node_db, ethhdr->h_source); | ||
252 | if (node) | ||
253 | ether_addr_copy(ethhdr->h_source, node->MacAddressA); | ||
254 | rcu_read_unlock(); | ||
255 | } | 262 | } |
256 | 263 | ||
257 | |||
258 | /* 'skb' is a frame meant for another host. | 264 | /* 'skb' is a frame meant for another host. |
259 | * 'hsr_dev_idx' is the HSR index of the outgoing device | 265 | * 'port' is the outgoing interface |
260 | * | 266 | * |
261 | * Substitute the target (dest) MAC address if necessary, so the it matches the | 267 | * Substitute the target (dest) MAC address if necessary, so the it matches the |
262 | * recipient interface MAC address, regardless of whether that is the | 268 | * recipient interface MAC address, regardless of whether that is the |
@@ -264,47 +270,44 @@ void hsr_addr_subst_source(struct hsr_priv *hsr_priv, struct sk_buff *skb) | |||
264 | * This is needed to keep the packets flowing through switches that learn on | 270 | * This is needed to keep the packets flowing through switches that learn on |
265 | * which "side" the different interfaces are. | 271 | * which "side" the different interfaces are. |
266 | */ | 272 | */ |
267 | void hsr_addr_subst_dest(struct hsr_priv *hsr_priv, struct ethhdr *ethhdr, | 273 | void hsr_addr_subst_dest(struct hsr_node *node_src, struct sk_buff *skb, |
268 | enum hsr_dev_idx dev_idx) | 274 | struct hsr_port *port) |
269 | { | 275 | { |
270 | struct node_entry *node; | 276 | struct hsr_node *node_dst; |
271 | 277 | ||
272 | rcu_read_lock(); | 278 | if (!skb_mac_header_was_set(skb)) { |
273 | node = find_node_by_AddrA(&hsr_priv->node_db, ethhdr->h_dest); | 279 | WARN_ONCE(1, "%s: Mac header not set\n", __func__); |
274 | if (node && (node->AddrB_if == dev_idx)) | 280 | return; |
275 | ether_addr_copy(ethhdr->h_dest, node->MacAddressB); | 281 | } |
276 | rcu_read_unlock(); | ||
277 | } | ||
278 | 282 | ||
283 | if (!is_unicast_ether_addr(eth_hdr(skb)->h_dest)) | ||
284 | return; | ||
279 | 285 | ||
280 | /* seq_nr_after(a, b) - return true if a is after (higher in sequence than) b, | 286 | node_dst = find_node_by_AddrA(&port->hsr->node_db, eth_hdr(skb)->h_dest); |
281 | * false otherwise. | 287 | if (!node_dst) { |
282 | */ | 288 | WARN_ONCE(1, "%s: Unknown node\n", __func__); |
283 | static bool seq_nr_after(u16 a, u16 b) | 289 | return; |
284 | { | 290 | } |
285 | /* Remove inconsistency where | 291 | if (port->type != node_dst->AddrB_port) |
286 | * seq_nr_after(a, b) == seq_nr_before(a, b) | 292 | return; |
287 | */ | ||
288 | if ((int) b - a == 32768) | ||
289 | return false; | ||
290 | 293 | ||
291 | return (((s16) (b - a)) < 0); | 294 | ether_addr_copy(eth_hdr(skb)->h_dest, node_dst->MacAddressB); |
292 | } | 295 | } |
293 | #define seq_nr_before(a, b) seq_nr_after((b), (a)) | ||
294 | #define seq_nr_after_or_eq(a, b) (!seq_nr_before((a), (b))) | ||
295 | #define seq_nr_before_or_eq(a, b) (!seq_nr_after((a), (b))) | ||
296 | 296 | ||
297 | 297 | ||
298 | void hsr_register_frame_in(struct node_entry *node, enum hsr_dev_idx dev_idx) | 298 | void hsr_register_frame_in(struct hsr_node *node, struct hsr_port *port, |
299 | u16 sequence_nr) | ||
299 | { | 300 | { |
300 | if ((dev_idx < 0) || (dev_idx >= HSR_MAX_SLAVE)) { | 301 | /* Don't register incoming frames without a valid sequence number. This |
301 | WARN_ONCE(1, "%s: Invalid dev_idx (%d)\n", __func__, dev_idx); | 302 | * ensures entries of restarted nodes gets pruned so that they can |
303 | * re-register and resume communications. | ||
304 | */ | ||
305 | if (seq_nr_before(sequence_nr, node->seq_out[port->type])) | ||
302 | return; | 306 | return; |
303 | } | ||
304 | node->time_in[dev_idx] = jiffies; | ||
305 | node->time_in_stale[dev_idx] = false; | ||
306 | } | ||
307 | 307 | ||
308 | node->time_in[port->type] = jiffies; | ||
309 | node->time_in_stale[port->type] = false; | ||
310 | } | ||
308 | 311 | ||
309 | /* 'skb' is a HSR Ethernet frame (with a HSR tag inserted), with a valid | 312 | /* 'skb' is a HSR Ethernet frame (with a HSR tag inserted), with a valid |
310 | * ethhdr->h_source address and skb->mac_header set. | 313 | * ethhdr->h_source address and skb->mac_header set. |
@@ -314,102 +317,87 @@ void hsr_register_frame_in(struct node_entry *node, enum hsr_dev_idx dev_idx) | |||
314 | * 0 otherwise, or | 317 | * 0 otherwise, or |
315 | * negative error code on error | 318 | * negative error code on error |
316 | */ | 319 | */ |
317 | int hsr_register_frame_out(struct node_entry *node, enum hsr_dev_idx dev_idx, | 320 | int hsr_register_frame_out(struct hsr_port *port, struct hsr_node *node, |
318 | struct sk_buff *skb) | 321 | u16 sequence_nr) |
319 | { | 322 | { |
320 | struct hsr_ethhdr *hsr_ethhdr; | 323 | if (seq_nr_before_or_eq(sequence_nr, node->seq_out[port->type])) |
321 | u16 sequence_nr; | ||
322 | |||
323 | if ((dev_idx < 0) || (dev_idx >= HSR_MAX_DEV)) { | ||
324 | WARN_ONCE(1, "%s: Invalid dev_idx (%d)\n", __func__, dev_idx); | ||
325 | return -EINVAL; | ||
326 | } | ||
327 | if (!skb_mac_header_was_set(skb)) { | ||
328 | WARN_ONCE(1, "%s: Mac header not set\n", __func__); | ||
329 | return -EINVAL; | ||
330 | } | ||
331 | hsr_ethhdr = (struct hsr_ethhdr *) skb_mac_header(skb); | ||
332 | |||
333 | sequence_nr = ntohs(hsr_ethhdr->hsr_tag.sequence_nr); | ||
334 | if (seq_nr_before_or_eq(sequence_nr, node->seq_out[dev_idx])) | ||
335 | return 1; | 324 | return 1; |
336 | 325 | ||
337 | node->seq_out[dev_idx] = sequence_nr; | 326 | node->seq_out[port->type] = sequence_nr; |
338 | return 0; | 327 | return 0; |
339 | } | 328 | } |
340 | 329 | ||
341 | 330 | ||
342 | 331 | static struct hsr_port *get_late_port(struct hsr_priv *hsr, | |
343 | static bool is_late(struct node_entry *node, enum hsr_dev_idx dev_idx) | 332 | struct hsr_node *node) |
344 | { | 333 | { |
345 | enum hsr_dev_idx other; | 334 | if (node->time_in_stale[HSR_PT_SLAVE_A]) |
346 | 335 | return hsr_port_get_hsr(hsr, HSR_PT_SLAVE_A); | |
347 | if (node->time_in_stale[dev_idx]) | 336 | if (node->time_in_stale[HSR_PT_SLAVE_B]) |
348 | return true; | 337 | return hsr_port_get_hsr(hsr, HSR_PT_SLAVE_B); |
349 | 338 | ||
350 | if (dev_idx == HSR_DEV_SLAVE_A) | 339 | if (time_after(node->time_in[HSR_PT_SLAVE_B], |
351 | other = HSR_DEV_SLAVE_B; | 340 | node->time_in[HSR_PT_SLAVE_A] + |
352 | else | 341 | msecs_to_jiffies(MAX_SLAVE_DIFF))) |
353 | other = HSR_DEV_SLAVE_A; | 342 | return hsr_port_get_hsr(hsr, HSR_PT_SLAVE_A); |
354 | 343 | if (time_after(node->time_in[HSR_PT_SLAVE_A], | |
355 | if (node->time_in_stale[other]) | 344 | node->time_in[HSR_PT_SLAVE_B] + |
356 | return false; | 345 | msecs_to_jiffies(MAX_SLAVE_DIFF))) |
346 | return hsr_port_get_hsr(hsr, HSR_PT_SLAVE_B); | ||
357 | 347 | ||
358 | if (time_after(node->time_in[other], node->time_in[dev_idx] + | 348 | return NULL; |
359 | msecs_to_jiffies(MAX_SLAVE_DIFF))) | ||
360 | return true; | ||
361 | |||
362 | return false; | ||
363 | } | 349 | } |
364 | 350 | ||
365 | 351 | ||
366 | /* Remove stale sequence_nr records. Called by timer every | 352 | /* Remove stale sequence_nr records. Called by timer every |
367 | * HSR_LIFE_CHECK_INTERVAL (two seconds or so). | 353 | * HSR_LIFE_CHECK_INTERVAL (two seconds or so). |
368 | */ | 354 | */ |
369 | void hsr_prune_nodes(struct hsr_priv *hsr_priv) | 355 | void hsr_prune_nodes(unsigned long data) |
370 | { | 356 | { |
371 | struct node_entry *node; | 357 | struct hsr_priv *hsr; |
358 | struct hsr_node *node; | ||
359 | struct hsr_port *port; | ||
372 | unsigned long timestamp; | 360 | unsigned long timestamp; |
373 | unsigned long time_a, time_b; | 361 | unsigned long time_a, time_b; |
374 | 362 | ||
363 | hsr = (struct hsr_priv *) data; | ||
364 | |||
375 | rcu_read_lock(); | 365 | rcu_read_lock(); |
376 | list_for_each_entry_rcu(node, &hsr_priv->node_db, mac_list) { | 366 | list_for_each_entry_rcu(node, &hsr->node_db, mac_list) { |
377 | /* Shorthand */ | 367 | /* Shorthand */ |
378 | time_a = node->time_in[HSR_DEV_SLAVE_A]; | 368 | time_a = node->time_in[HSR_PT_SLAVE_A]; |
379 | time_b = node->time_in[HSR_DEV_SLAVE_B]; | 369 | time_b = node->time_in[HSR_PT_SLAVE_B]; |
380 | 370 | ||
381 | /* Check for timestamps old enough to risk wrap-around */ | 371 | /* Check for timestamps old enough to risk wrap-around */ |
382 | if (time_after(jiffies, time_a + MAX_JIFFY_OFFSET/2)) | 372 | if (time_after(jiffies, time_a + MAX_JIFFY_OFFSET/2)) |
383 | node->time_in_stale[HSR_DEV_SLAVE_A] = true; | 373 | node->time_in_stale[HSR_PT_SLAVE_A] = true; |
384 | if (time_after(jiffies, time_b + MAX_JIFFY_OFFSET/2)) | 374 | if (time_after(jiffies, time_b + MAX_JIFFY_OFFSET/2)) |
385 | node->time_in_stale[HSR_DEV_SLAVE_B] = true; | 375 | node->time_in_stale[HSR_PT_SLAVE_B] = true; |
386 | 376 | ||
387 | /* Get age of newest frame from node. | 377 | /* Get age of newest frame from node. |
388 | * At least one time_in is OK here; nodes get pruned long | 378 | * At least one time_in is OK here; nodes get pruned long |
389 | * before both time_ins can get stale | 379 | * before both time_ins can get stale |
390 | */ | 380 | */ |
391 | timestamp = time_a; | 381 | timestamp = time_a; |
392 | if (node->time_in_stale[HSR_DEV_SLAVE_A] || | 382 | if (node->time_in_stale[HSR_PT_SLAVE_A] || |
393 | (!node->time_in_stale[HSR_DEV_SLAVE_B] && | 383 | (!node->time_in_stale[HSR_PT_SLAVE_B] && |
394 | time_after(time_b, time_a))) | 384 | time_after(time_b, time_a))) |
395 | timestamp = time_b; | 385 | timestamp = time_b; |
396 | 386 | ||
397 | /* Warn of ring error only as long as we get frames at all */ | 387 | /* Warn of ring error only as long as we get frames at all */ |
398 | if (time_is_after_jiffies(timestamp + | 388 | if (time_is_after_jiffies(timestamp + |
399 | msecs_to_jiffies(1.5*MAX_SLAVE_DIFF))) { | 389 | msecs_to_jiffies(1.5*MAX_SLAVE_DIFF))) { |
400 | 390 | rcu_read_lock(); | |
401 | if (is_late(node, HSR_DEV_SLAVE_A)) | 391 | port = get_late_port(hsr, node); |
402 | hsr_nl_ringerror(hsr_priv, node->MacAddressA, | 392 | if (port != NULL) |
403 | HSR_DEV_SLAVE_A); | 393 | hsr_nl_ringerror(hsr, node->MacAddressA, port); |
404 | else if (is_late(node, HSR_DEV_SLAVE_B)) | 394 | rcu_read_unlock(); |
405 | hsr_nl_ringerror(hsr_priv, node->MacAddressA, | ||
406 | HSR_DEV_SLAVE_B); | ||
407 | } | 395 | } |
408 | 396 | ||
409 | /* Prune old entries */ | 397 | /* Prune old entries */ |
410 | if (time_is_before_jiffies(timestamp + | 398 | if (time_is_before_jiffies(timestamp + |
411 | msecs_to_jiffies(HSR_NODE_FORGET_TIME))) { | 399 | msecs_to_jiffies(HSR_NODE_FORGET_TIME))) { |
412 | hsr_nl_nodedown(hsr_priv, node->MacAddressA); | 400 | hsr_nl_nodedown(hsr, node->MacAddressA); |
413 | list_del_rcu(&node->mac_list); | 401 | list_del_rcu(&node->mac_list); |
414 | /* Note that we need to free this entry later: */ | 402 | /* Note that we need to free this entry later: */ |
415 | kfree_rcu(node, rcu_head); | 403 | kfree_rcu(node, rcu_head); |
@@ -419,21 +407,21 @@ void hsr_prune_nodes(struct hsr_priv *hsr_priv) | |||
419 | } | 407 | } |
420 | 408 | ||
421 | 409 | ||
422 | void *hsr_get_next_node(struct hsr_priv *hsr_priv, void *_pos, | 410 | void *hsr_get_next_node(struct hsr_priv *hsr, void *_pos, |
423 | unsigned char addr[ETH_ALEN]) | 411 | unsigned char addr[ETH_ALEN]) |
424 | { | 412 | { |
425 | struct node_entry *node; | 413 | struct hsr_node *node; |
426 | 414 | ||
427 | if (!_pos) { | 415 | if (!_pos) { |
428 | node = list_first_or_null_rcu(&hsr_priv->node_db, | 416 | node = list_first_or_null_rcu(&hsr->node_db, |
429 | struct node_entry, mac_list); | 417 | struct hsr_node, mac_list); |
430 | if (node) | 418 | if (node) |
431 | ether_addr_copy(addr, node->MacAddressA); | 419 | ether_addr_copy(addr, node->MacAddressA); |
432 | return node; | 420 | return node; |
433 | } | 421 | } |
434 | 422 | ||
435 | node = _pos; | 423 | node = _pos; |
436 | list_for_each_entry_continue_rcu(node, &hsr_priv->node_db, mac_list) { | 424 | list_for_each_entry_continue_rcu(node, &hsr->node_db, mac_list) { |
437 | ether_addr_copy(addr, node->MacAddressA); | 425 | ether_addr_copy(addr, node->MacAddressA); |
438 | return node; | 426 | return node; |
439 | } | 427 | } |
@@ -442,7 +430,7 @@ void *hsr_get_next_node(struct hsr_priv *hsr_priv, void *_pos, | |||
442 | } | 430 | } |
443 | 431 | ||
444 | 432 | ||
445 | int hsr_get_node_data(struct hsr_priv *hsr_priv, | 433 | int hsr_get_node_data(struct hsr_priv *hsr, |
446 | const unsigned char *addr, | 434 | const unsigned char *addr, |
447 | unsigned char addr_b[ETH_ALEN], | 435 | unsigned char addr_b[ETH_ALEN], |
448 | unsigned int *addr_b_ifindex, | 436 | unsigned int *addr_b_ifindex, |
@@ -451,12 +439,13 @@ int hsr_get_node_data(struct hsr_priv *hsr_priv, | |||
451 | int *if2_age, | 439 | int *if2_age, |
452 | u16 *if2_seq) | 440 | u16 *if2_seq) |
453 | { | 441 | { |
454 | struct node_entry *node; | 442 | struct hsr_node *node; |
443 | struct hsr_port *port; | ||
455 | unsigned long tdiff; | 444 | unsigned long tdiff; |
456 | 445 | ||
457 | 446 | ||
458 | rcu_read_lock(); | 447 | rcu_read_lock(); |
459 | node = find_node_by_AddrA(&hsr_priv->node_db, addr); | 448 | node = find_node_by_AddrA(&hsr->node_db, addr); |
460 | if (!node) { | 449 | if (!node) { |
461 | rcu_read_unlock(); | 450 | rcu_read_unlock(); |
462 | return -ENOENT; /* No such entry */ | 451 | return -ENOENT; /* No such entry */ |
@@ -464,8 +453,8 @@ int hsr_get_node_data(struct hsr_priv *hsr_priv, | |||
464 | 453 | ||
465 | ether_addr_copy(addr_b, node->MacAddressB); | 454 | ether_addr_copy(addr_b, node->MacAddressB); |
466 | 455 | ||
467 | tdiff = jiffies - node->time_in[HSR_DEV_SLAVE_A]; | 456 | tdiff = jiffies - node->time_in[HSR_PT_SLAVE_A]; |
468 | if (node->time_in_stale[HSR_DEV_SLAVE_A]) | 457 | if (node->time_in_stale[HSR_PT_SLAVE_A]) |
469 | *if1_age = INT_MAX; | 458 | *if1_age = INT_MAX; |
470 | #if HZ <= MSEC_PER_SEC | 459 | #if HZ <= MSEC_PER_SEC |
471 | else if (tdiff > msecs_to_jiffies(INT_MAX)) | 460 | else if (tdiff > msecs_to_jiffies(INT_MAX)) |
@@ -474,8 +463,8 @@ int hsr_get_node_data(struct hsr_priv *hsr_priv, | |||
474 | else | 463 | else |
475 | *if1_age = jiffies_to_msecs(tdiff); | 464 | *if1_age = jiffies_to_msecs(tdiff); |
476 | 465 | ||
477 | tdiff = jiffies - node->time_in[HSR_DEV_SLAVE_B]; | 466 | tdiff = jiffies - node->time_in[HSR_PT_SLAVE_B]; |
478 | if (node->time_in_stale[HSR_DEV_SLAVE_B]) | 467 | if (node->time_in_stale[HSR_PT_SLAVE_B]) |
479 | *if2_age = INT_MAX; | 468 | *if2_age = INT_MAX; |
480 | #if HZ <= MSEC_PER_SEC | 469 | #if HZ <= MSEC_PER_SEC |
481 | else if (tdiff > msecs_to_jiffies(INT_MAX)) | 470 | else if (tdiff > msecs_to_jiffies(INT_MAX)) |
@@ -485,13 +474,15 @@ int hsr_get_node_data(struct hsr_priv *hsr_priv, | |||
485 | *if2_age = jiffies_to_msecs(tdiff); | 474 | *if2_age = jiffies_to_msecs(tdiff); |
486 | 475 | ||
487 | /* Present sequence numbers as if they were incoming on interface */ | 476 | /* Present sequence numbers as if they were incoming on interface */ |
488 | *if1_seq = node->seq_out[HSR_DEV_SLAVE_B]; | 477 | *if1_seq = node->seq_out[HSR_PT_SLAVE_B]; |
489 | *if2_seq = node->seq_out[HSR_DEV_SLAVE_A]; | 478 | *if2_seq = node->seq_out[HSR_PT_SLAVE_A]; |
490 | 479 | ||
491 | if ((node->AddrB_if != HSR_DEV_NONE) && hsr_priv->slave[node->AddrB_if]) | 480 | if (node->AddrB_port != HSR_PT_NONE) { |
492 | *addr_b_ifindex = hsr_priv->slave[node->AddrB_if]->ifindex; | 481 | port = hsr_port_get_hsr(hsr, node->AddrB_port); |
493 | else | 482 | *addr_b_ifindex = port->dev->ifindex; |
483 | } else { | ||
494 | *addr_b_ifindex = -1; | 484 | *addr_b_ifindex = -1; |
485 | } | ||
495 | 486 | ||
496 | rcu_read_unlock(); | 487 | rcu_read_unlock(); |
497 | 488 | ||
diff --git a/net/hsr/hsr_framereg.h b/net/hsr/hsr_framereg.h index e6c4022030ad..438b40f98f5a 100644 --- a/net/hsr/hsr_framereg.h +++ b/net/hsr/hsr_framereg.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Copyright 2011-2013 Autronica Fire and Security AS | 1 | /* Copyright 2011-2014 Autronica Fire and Security AS |
2 | * | 2 | * |
3 | * This program is free software; you can redistribute it and/or modify it | 3 | * This program is free software; you can redistribute it and/or modify it |
4 | * under the terms of the GNU General Public License as published by the Free | 4 | * under the terms of the GNU General Public License as published by the Free |
@@ -6,42 +6,43 @@ | |||
6 | * any later version. | 6 | * any later version. |
7 | * | 7 | * |
8 | * Author(s): | 8 | * Author(s): |
9 | * 2011-2013 Arvid Brodin, arvid.brodin@xdin.com | 9 | * 2011-2014 Arvid Brodin, arvid.brodin@alten.se |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #ifndef _HSR_FRAMEREG_H | 12 | #ifndef __HSR_FRAMEREG_H |
13 | #define _HSR_FRAMEREG_H | 13 | #define __HSR_FRAMEREG_H |
14 | 14 | ||
15 | #include "hsr_main.h" | 15 | #include "hsr_main.h" |
16 | 16 | ||
17 | struct node_entry; | 17 | struct hsr_node; |
18 | 18 | ||
19 | struct node_entry *hsr_find_node(struct list_head *node_db, struct sk_buff *skb); | 19 | struct hsr_node *hsr_add_node(struct list_head *node_db, unsigned char addr[], |
20 | u16 seq_out); | ||
21 | struct hsr_node *hsr_get_node(struct list_head *node_db, struct sk_buff *skb, | ||
22 | bool is_sup); | ||
23 | void hsr_handle_sup_frame(struct sk_buff *skb, struct hsr_node *node_curr, | ||
24 | struct hsr_port *port); | ||
25 | bool hsr_addr_is_self(struct hsr_priv *hsr, unsigned char *addr); | ||
20 | 26 | ||
21 | struct node_entry *hsr_merge_node(struct hsr_priv *hsr_priv, | 27 | void hsr_addr_subst_source(struct hsr_node *node, struct sk_buff *skb); |
22 | struct node_entry *node, | 28 | void hsr_addr_subst_dest(struct hsr_node *node_src, struct sk_buff *skb, |
23 | struct sk_buff *skb, | 29 | struct hsr_port *port); |
24 | enum hsr_dev_idx dev_idx); | ||
25 | 30 | ||
26 | void hsr_addr_subst_source(struct hsr_priv *hsr_priv, struct sk_buff *skb); | 31 | void hsr_register_frame_in(struct hsr_node *node, struct hsr_port *port, |
27 | void hsr_addr_subst_dest(struct hsr_priv *hsr_priv, struct ethhdr *ethhdr, | 32 | u16 sequence_nr); |
28 | enum hsr_dev_idx dev_idx); | 33 | int hsr_register_frame_out(struct hsr_port *port, struct hsr_node *node, |
34 | u16 sequence_nr); | ||
29 | 35 | ||
30 | void hsr_register_frame_in(struct node_entry *node, enum hsr_dev_idx dev_idx); | 36 | void hsr_prune_nodes(unsigned long data); |
31 | |||
32 | int hsr_register_frame_out(struct node_entry *node, enum hsr_dev_idx dev_idx, | ||
33 | struct sk_buff *skb); | ||
34 | |||
35 | void hsr_prune_nodes(struct hsr_priv *hsr_priv); | ||
36 | 37 | ||
37 | int hsr_create_self_node(struct list_head *self_node_db, | 38 | int hsr_create_self_node(struct list_head *self_node_db, |
38 | unsigned char addr_a[ETH_ALEN], | 39 | unsigned char addr_a[ETH_ALEN], |
39 | unsigned char addr_b[ETH_ALEN]); | 40 | unsigned char addr_b[ETH_ALEN]); |
40 | 41 | ||
41 | void *hsr_get_next_node(struct hsr_priv *hsr_priv, void *_pos, | 42 | void *hsr_get_next_node(struct hsr_priv *hsr, void *_pos, |
42 | unsigned char addr[ETH_ALEN]); | 43 | unsigned char addr[ETH_ALEN]); |
43 | 44 | ||
44 | int hsr_get_node_data(struct hsr_priv *hsr_priv, | 45 | int hsr_get_node_data(struct hsr_priv *hsr, |
45 | const unsigned char *addr, | 46 | const unsigned char *addr, |
46 | unsigned char addr_b[ETH_ALEN], | 47 | unsigned char addr_b[ETH_ALEN], |
47 | unsigned int *addr_b_ifindex, | 48 | unsigned int *addr_b_ifindex, |
@@ -50,4 +51,4 @@ int hsr_get_node_data(struct hsr_priv *hsr_priv, | |||
50 | int *if2_age, | 51 | int *if2_age, |
51 | u16 *if2_seq); | 52 | u16 *if2_seq); |
52 | 53 | ||
53 | #endif /* _HSR_FRAMEREG_H */ | 54 | #endif /* __HSR_FRAMEREG_H */ |
diff --git a/net/hsr/hsr_main.c b/net/hsr/hsr_main.c index 3fee5218a691..779d28b65417 100644 --- a/net/hsr/hsr_main.c +++ b/net/hsr/hsr_main.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Copyright 2011-2013 Autronica Fire and Security AS | 1 | /* Copyright 2011-2014 Autronica Fire and Security AS |
2 | * | 2 | * |
3 | * This program is free software; you can redistribute it and/or modify it | 3 | * This program is free software; you can redistribute it and/or modify it |
4 | * under the terms of the GNU General Public License as published by the Free | 4 | * under the terms of the GNU General Public License as published by the Free |
@@ -6,11 +6,7 @@ | |||
6 | * any later version. | 6 | * any later version. |
7 | * | 7 | * |
8 | * Author(s): | 8 | * Author(s): |
9 | * 2011-2013 Arvid Brodin, arvid.brodin@xdin.com | 9 | * 2011-2014 Arvid Brodin, arvid.brodin@alten.se |
10 | * | ||
11 | * In addition to routines for registering and unregistering HSR support, this | ||
12 | * file also contains the receive routine that handles all incoming frames with | ||
13 | * Ethertype (protocol) ETH_P_PRP (HSRv0), and network device event handling. | ||
14 | */ | 10 | */ |
15 | 11 | ||
16 | #include <linux/netdevice.h> | 12 | #include <linux/netdevice.h> |
@@ -21,154 +17,71 @@ | |||
21 | #include "hsr_device.h" | 17 | #include "hsr_device.h" |
22 | #include "hsr_netlink.h" | 18 | #include "hsr_netlink.h" |
23 | #include "hsr_framereg.h" | 19 | #include "hsr_framereg.h" |
24 | 20 | #include "hsr_slave.h" | |
25 | |||
26 | /* List of all registered virtual HSR devices */ | ||
27 | static LIST_HEAD(hsr_list); | ||
28 | |||
29 | void register_hsr_master(struct hsr_priv *hsr_priv) | ||
30 | { | ||
31 | list_add_tail_rcu(&hsr_priv->hsr_list, &hsr_list); | ||
32 | } | ||
33 | |||
34 | void unregister_hsr_master(struct hsr_priv *hsr_priv) | ||
35 | { | ||
36 | struct hsr_priv *hsr_priv_it; | ||
37 | |||
38 | list_for_each_entry(hsr_priv_it, &hsr_list, hsr_list) | ||
39 | if (hsr_priv_it == hsr_priv) { | ||
40 | list_del_rcu(&hsr_priv_it->hsr_list); | ||
41 | return; | ||
42 | } | ||
43 | } | ||
44 | |||
45 | bool is_hsr_slave(struct net_device *dev) | ||
46 | { | ||
47 | struct hsr_priv *hsr_priv_it; | ||
48 | |||
49 | list_for_each_entry_rcu(hsr_priv_it, &hsr_list, hsr_list) { | ||
50 | if (dev == hsr_priv_it->slave[0]) | ||
51 | return true; | ||
52 | if (dev == hsr_priv_it->slave[1]) | ||
53 | return true; | ||
54 | } | ||
55 | |||
56 | return false; | ||
57 | } | ||
58 | |||
59 | |||
60 | /* If dev is a HSR slave device, return the virtual master device. Return NULL | ||
61 | * otherwise. | ||
62 | */ | ||
63 | static struct hsr_priv *get_hsr_master(struct net_device *dev) | ||
64 | { | ||
65 | struct hsr_priv *hsr_priv; | ||
66 | |||
67 | rcu_read_lock(); | ||
68 | list_for_each_entry_rcu(hsr_priv, &hsr_list, hsr_list) | ||
69 | if ((dev == hsr_priv->slave[0]) || | ||
70 | (dev == hsr_priv->slave[1])) { | ||
71 | rcu_read_unlock(); | ||
72 | return hsr_priv; | ||
73 | } | ||
74 | |||
75 | rcu_read_unlock(); | ||
76 | return NULL; | ||
77 | } | ||
78 | |||
79 | |||
80 | /* If dev is a HSR slave device, return the other slave device. Return NULL | ||
81 | * otherwise. | ||
82 | */ | ||
83 | static struct net_device *get_other_slave(struct hsr_priv *hsr_priv, | ||
84 | struct net_device *dev) | ||
85 | { | ||
86 | if (dev == hsr_priv->slave[0]) | ||
87 | return hsr_priv->slave[1]; | ||
88 | if (dev == hsr_priv->slave[1]) | ||
89 | return hsr_priv->slave[0]; | ||
90 | |||
91 | return NULL; | ||
92 | } | ||
93 | 21 | ||
94 | 22 | ||
95 | static int hsr_netdev_notify(struct notifier_block *nb, unsigned long event, | 23 | static int hsr_netdev_notify(struct notifier_block *nb, unsigned long event, |
96 | void *ptr) | 24 | void *ptr) |
97 | { | 25 | { |
98 | struct net_device *slave, *other_slave; | 26 | struct net_device *dev; |
99 | struct hsr_priv *hsr_priv; | 27 | struct hsr_port *port, *master; |
100 | int old_operstate; | 28 | struct hsr_priv *hsr; |
101 | int mtu_max; | 29 | int mtu_max; |
102 | int res; | 30 | int res; |
103 | struct net_device *dev; | ||
104 | 31 | ||
105 | dev = netdev_notifier_info_to_dev(ptr); | 32 | dev = netdev_notifier_info_to_dev(ptr); |
106 | 33 | port = hsr_port_get_rtnl(dev); | |
107 | hsr_priv = get_hsr_master(dev); | 34 | if (port == NULL) { |
108 | if (hsr_priv) { | ||
109 | /* dev is a slave device */ | ||
110 | slave = dev; | ||
111 | other_slave = get_other_slave(hsr_priv, slave); | ||
112 | } else { | ||
113 | if (!is_hsr_master(dev)) | 35 | if (!is_hsr_master(dev)) |
114 | return NOTIFY_DONE; | 36 | return NOTIFY_DONE; /* Not an HSR device */ |
115 | hsr_priv = netdev_priv(dev); | 37 | hsr = netdev_priv(dev); |
116 | slave = hsr_priv->slave[0]; | 38 | port = hsr_port_get_hsr(hsr, HSR_PT_MASTER); |
117 | other_slave = hsr_priv->slave[1]; | 39 | } else { |
40 | hsr = port->hsr; | ||
118 | } | 41 | } |
119 | 42 | ||
120 | switch (event) { | 43 | switch (event) { |
121 | case NETDEV_UP: /* Administrative state DOWN */ | 44 | case NETDEV_UP: /* Administrative state DOWN */ |
122 | case NETDEV_DOWN: /* Administrative state UP */ | 45 | case NETDEV_DOWN: /* Administrative state UP */ |
123 | case NETDEV_CHANGE: /* Link (carrier) state changes */ | 46 | case NETDEV_CHANGE: /* Link (carrier) state changes */ |
124 | old_operstate = hsr_priv->dev->operstate; | 47 | hsr_check_carrier_and_operstate(hsr); |
125 | hsr_set_carrier(hsr_priv->dev, slave, other_slave); | ||
126 | /* netif_stacked_transfer_operstate() cannot be used here since | ||
127 | * it doesn't set IF_OPER_LOWERLAYERDOWN (?) | ||
128 | */ | ||
129 | hsr_set_operstate(hsr_priv->dev, slave, other_slave); | ||
130 | hsr_check_announce(hsr_priv->dev, old_operstate); | ||
131 | break; | 48 | break; |
132 | case NETDEV_CHANGEADDR: | 49 | case NETDEV_CHANGEADDR: |
133 | 50 | if (port->type == HSR_PT_MASTER) { | |
134 | /* This should not happen since there's no ndo_set_mac_address() | 51 | /* This should not happen since there's no |
135 | * for HSR devices - i.e. not supported. | 52 | * ndo_set_mac_address() for HSR devices - i.e. not |
136 | */ | 53 | * supported. |
137 | if (dev == hsr_priv->dev) | 54 | */ |
138 | break; | 55 | break; |
56 | } | ||
139 | 57 | ||
140 | if (dev == hsr_priv->slave[0]) | 58 | master = hsr_port_get_hsr(hsr, HSR_PT_MASTER); |
141 | ether_addr_copy(hsr_priv->dev->dev_addr, | 59 | |
142 | hsr_priv->slave[0]->dev_addr); | 60 | if (port->type == HSR_PT_SLAVE_A) { |
61 | ether_addr_copy(master->dev->dev_addr, dev->dev_addr); | ||
62 | call_netdevice_notifiers(NETDEV_CHANGEADDR, master->dev); | ||
63 | } | ||
143 | 64 | ||
144 | /* Make sure we recognize frames from ourselves in hsr_rcv() */ | 65 | /* Make sure we recognize frames from ourselves in hsr_rcv() */ |
145 | res = hsr_create_self_node(&hsr_priv->self_node_db, | 66 | port = hsr_port_get_hsr(hsr, HSR_PT_SLAVE_B); |
146 | hsr_priv->dev->dev_addr, | 67 | res = hsr_create_self_node(&hsr->self_node_db, |
147 | hsr_priv->slave[1] ? | 68 | master->dev->dev_addr, |
148 | hsr_priv->slave[1]->dev_addr : | 69 | port ? |
149 | hsr_priv->dev->dev_addr); | 70 | port->dev->dev_addr : |
71 | master->dev->dev_addr); | ||
150 | if (res) | 72 | if (res) |
151 | netdev_warn(hsr_priv->dev, | 73 | netdev_warn(master->dev, |
152 | "Could not update HSR node address.\n"); | 74 | "Could not update HSR node address.\n"); |
153 | |||
154 | if (dev == hsr_priv->slave[0]) | ||
155 | call_netdevice_notifiers(NETDEV_CHANGEADDR, hsr_priv->dev); | ||
156 | break; | 75 | break; |
157 | case NETDEV_CHANGEMTU: | 76 | case NETDEV_CHANGEMTU: |
158 | if (dev == hsr_priv->dev) | 77 | if (port->type == HSR_PT_MASTER) |
159 | break; /* Handled in ndo_change_mtu() */ | 78 | break; /* Handled in ndo_change_mtu() */ |
160 | mtu_max = hsr_get_max_mtu(hsr_priv); | 79 | mtu_max = hsr_get_max_mtu(port->hsr); |
161 | if (hsr_priv->dev->mtu > mtu_max) | 80 | master = hsr_port_get_hsr(port->hsr, HSR_PT_MASTER); |
162 | dev_set_mtu(hsr_priv->dev, mtu_max); | 81 | master->dev->mtu = mtu_max; |
163 | break; | 82 | break; |
164 | case NETDEV_UNREGISTER: | 83 | case NETDEV_UNREGISTER: |
165 | if (dev == hsr_priv->slave[0]) | 84 | hsr_del_port(port); |
166 | hsr_priv->slave[0] = NULL; | ||
167 | if (dev == hsr_priv->slave[1]) | ||
168 | hsr_priv->slave[1] = NULL; | ||
169 | |||
170 | /* There should really be a way to set a new slave device... */ | ||
171 | |||
172 | break; | 85 | break; |
173 | case NETDEV_PRE_TYPE_CHANGE: | 86 | case NETDEV_PRE_TYPE_CHANGE: |
174 | /* HSR works only on Ethernet devices. Refuse slave to change | 87 | /* HSR works only on Ethernet devices. Refuse slave to change |
@@ -181,255 +94,16 @@ static int hsr_netdev_notify(struct notifier_block *nb, unsigned long event, | |||
181 | } | 94 | } |
182 | 95 | ||
183 | 96 | ||
184 | static struct timer_list prune_timer; | 97 | struct hsr_port *hsr_port_get_hsr(struct hsr_priv *hsr, enum hsr_port_type pt) |
185 | |||
186 | static void prune_nodes_all(unsigned long data) | ||
187 | { | ||
188 | struct hsr_priv *hsr_priv; | ||
189 | |||
190 | rcu_read_lock(); | ||
191 | list_for_each_entry_rcu(hsr_priv, &hsr_list, hsr_list) | ||
192 | hsr_prune_nodes(hsr_priv); | ||
193 | rcu_read_unlock(); | ||
194 | |||
195 | prune_timer.expires = jiffies + msecs_to_jiffies(PRUNE_PERIOD); | ||
196 | add_timer(&prune_timer); | ||
197 | } | ||
198 | |||
199 | |||
200 | static struct sk_buff *hsr_pull_tag(struct sk_buff *skb) | ||
201 | { | 98 | { |
202 | struct hsr_tag *hsr_tag; | 99 | struct hsr_port *port; |
203 | struct sk_buff *skb2; | ||
204 | |||
205 | skb2 = skb_share_check(skb, GFP_ATOMIC); | ||
206 | if (unlikely(!skb2)) | ||
207 | goto err_free; | ||
208 | skb = skb2; | ||
209 | |||
210 | if (unlikely(!pskb_may_pull(skb, HSR_TAGLEN))) | ||
211 | goto err_free; | ||
212 | 100 | ||
213 | hsr_tag = (struct hsr_tag *) skb->data; | 101 | hsr_for_each_port(hsr, port) |
214 | skb->protocol = hsr_tag->encap_proto; | 102 | if (port->type == pt) |
215 | skb_pull(skb, HSR_TAGLEN); | 103 | return port; |
216 | |||
217 | return skb; | ||
218 | |||
219 | err_free: | ||
220 | kfree_skb(skb); | ||
221 | return NULL; | 104 | return NULL; |
222 | } | 105 | } |
223 | 106 | ||
224 | |||
225 | /* The uses I can see for these HSR supervision frames are: | ||
226 | * 1) Use the frames that are sent after node initialization ("HSR_TLV.Type = | ||
227 | * 22") to reset any sequence_nr counters belonging to that node. Useful if | ||
228 | * the other node's counter has been reset for some reason. | ||
229 | * -- | ||
230 | * Or not - resetting the counter and bridging the frame would create a | ||
231 | * loop, unfortunately. | ||
232 | * | ||
233 | * 2) Use the LifeCheck frames to detect ring breaks. I.e. if no LifeCheck | ||
234 | * frame is received from a particular node, we know something is wrong. | ||
235 | * We just register these (as with normal frames) and throw them away. | ||
236 | * | ||
237 | * 3) Allow different MAC addresses for the two slave interfaces, using the | ||
238 | * MacAddressA field. | ||
239 | */ | ||
240 | static bool is_supervision_frame(struct hsr_priv *hsr_priv, struct sk_buff *skb) | ||
241 | { | ||
242 | struct hsr_sup_tag *hsr_stag; | ||
243 | |||
244 | if (!ether_addr_equal(eth_hdr(skb)->h_dest, | ||
245 | hsr_priv->sup_multicast_addr)) | ||
246 | return false; | ||
247 | |||
248 | hsr_stag = (struct hsr_sup_tag *) skb->data; | ||
249 | if (get_hsr_stag_path(hsr_stag) != 0x0f) | ||
250 | return false; | ||
251 | if ((hsr_stag->HSR_TLV_Type != HSR_TLV_ANNOUNCE) && | ||
252 | (hsr_stag->HSR_TLV_Type != HSR_TLV_LIFE_CHECK)) | ||
253 | return false; | ||
254 | if (hsr_stag->HSR_TLV_Length != 12) | ||
255 | return false; | ||
256 | |||
257 | return true; | ||
258 | } | ||
259 | |||
260 | |||
261 | /* Implementation somewhat according to IEC-62439-3, p. 43 | ||
262 | */ | ||
263 | static int hsr_rcv(struct sk_buff *skb, struct net_device *dev, | ||
264 | struct packet_type *pt, struct net_device *orig_dev) | ||
265 | { | ||
266 | struct hsr_priv *hsr_priv; | ||
267 | struct net_device *other_slave; | ||
268 | struct node_entry *node; | ||
269 | bool deliver_to_self; | ||
270 | struct sk_buff *skb_deliver; | ||
271 | enum hsr_dev_idx dev_in_idx, dev_other_idx; | ||
272 | bool dup_out; | ||
273 | int ret; | ||
274 | |||
275 | hsr_priv = get_hsr_master(dev); | ||
276 | |||
277 | if (!hsr_priv) { | ||
278 | /* Non-HSR-slave device 'dev' is connected to a HSR network */ | ||
279 | kfree_skb(skb); | ||
280 | dev->stats.rx_errors++; | ||
281 | return NET_RX_SUCCESS; | ||
282 | } | ||
283 | |||
284 | if (dev == hsr_priv->slave[0]) { | ||
285 | dev_in_idx = HSR_DEV_SLAVE_A; | ||
286 | dev_other_idx = HSR_DEV_SLAVE_B; | ||
287 | } else { | ||
288 | dev_in_idx = HSR_DEV_SLAVE_B; | ||
289 | dev_other_idx = HSR_DEV_SLAVE_A; | ||
290 | } | ||
291 | |||
292 | node = hsr_find_node(&hsr_priv->self_node_db, skb); | ||
293 | if (node) { | ||
294 | /* Always kill frames sent by ourselves */ | ||
295 | kfree_skb(skb); | ||
296 | return NET_RX_SUCCESS; | ||
297 | } | ||
298 | |||
299 | /* Is this frame a candidate for local reception? */ | ||
300 | deliver_to_self = false; | ||
301 | if ((skb->pkt_type == PACKET_HOST) || | ||
302 | (skb->pkt_type == PACKET_MULTICAST) || | ||
303 | (skb->pkt_type == PACKET_BROADCAST)) | ||
304 | deliver_to_self = true; | ||
305 | else if (ether_addr_equal(eth_hdr(skb)->h_dest, | ||
306 | hsr_priv->dev->dev_addr)) { | ||
307 | skb->pkt_type = PACKET_HOST; | ||
308 | deliver_to_self = true; | ||
309 | } | ||
310 | |||
311 | |||
312 | rcu_read_lock(); /* node_db */ | ||
313 | node = hsr_find_node(&hsr_priv->node_db, skb); | ||
314 | |||
315 | if (is_supervision_frame(hsr_priv, skb)) { | ||
316 | skb_pull(skb, sizeof(struct hsr_sup_tag)); | ||
317 | node = hsr_merge_node(hsr_priv, node, skb, dev_in_idx); | ||
318 | if (!node) { | ||
319 | rcu_read_unlock(); /* node_db */ | ||
320 | kfree_skb(skb); | ||
321 | hsr_priv->dev->stats.rx_dropped++; | ||
322 | return NET_RX_DROP; | ||
323 | } | ||
324 | skb_push(skb, sizeof(struct hsr_sup_tag)); | ||
325 | deliver_to_self = false; | ||
326 | } | ||
327 | |||
328 | if (!node) { | ||
329 | /* Source node unknown; this might be a HSR frame from | ||
330 | * another net (different multicast address). Ignore it. | ||
331 | */ | ||
332 | rcu_read_unlock(); /* node_db */ | ||
333 | kfree_skb(skb); | ||
334 | return NET_RX_SUCCESS; | ||
335 | } | ||
336 | |||
337 | /* Register ALL incoming frames as outgoing through the other interface. | ||
338 | * This allows us to register frames as incoming only if they are valid | ||
339 | * for the receiving interface, without using a specific counter for | ||
340 | * incoming frames. | ||
341 | */ | ||
342 | dup_out = hsr_register_frame_out(node, dev_other_idx, skb); | ||
343 | if (!dup_out) | ||
344 | hsr_register_frame_in(node, dev_in_idx); | ||
345 | |||
346 | /* Forward this frame? */ | ||
347 | if (!dup_out && (skb->pkt_type != PACKET_HOST)) | ||
348 | other_slave = get_other_slave(hsr_priv, dev); | ||
349 | else | ||
350 | other_slave = NULL; | ||
351 | |||
352 | if (hsr_register_frame_out(node, HSR_DEV_MASTER, skb)) | ||
353 | deliver_to_self = false; | ||
354 | |||
355 | rcu_read_unlock(); /* node_db */ | ||
356 | |||
357 | if (!deliver_to_self && !other_slave) { | ||
358 | kfree_skb(skb); | ||
359 | /* Circulated frame; silently remove it. */ | ||
360 | return NET_RX_SUCCESS; | ||
361 | } | ||
362 | |||
363 | skb_deliver = skb; | ||
364 | if (deliver_to_self && other_slave) { | ||
365 | /* skb_clone() is not enough since we will strip the hsr tag | ||
366 | * and do address substitution below | ||
367 | */ | ||
368 | skb_deliver = pskb_copy(skb, GFP_ATOMIC); | ||
369 | if (!skb_deliver) { | ||
370 | deliver_to_self = false; | ||
371 | hsr_priv->dev->stats.rx_dropped++; | ||
372 | } | ||
373 | } | ||
374 | |||
375 | if (deliver_to_self) { | ||
376 | bool multicast_frame; | ||
377 | |||
378 | skb_deliver = hsr_pull_tag(skb_deliver); | ||
379 | if (!skb_deliver) { | ||
380 | hsr_priv->dev->stats.rx_dropped++; | ||
381 | goto forward; | ||
382 | } | ||
383 | #if !defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) | ||
384 | /* Move everything in the header that is after the HSR tag, | ||
385 | * to work around alignment problems caused by the 6-byte HSR | ||
386 | * tag. In practice, this removes/overwrites the HSR tag in | ||
387 | * the header and restores a "standard" packet. | ||
388 | */ | ||
389 | memmove(skb_deliver->data - HSR_TAGLEN, skb_deliver->data, | ||
390 | skb_headlen(skb_deliver)); | ||
391 | |||
392 | /* Adjust skb members so they correspond with the move above. | ||
393 | * This cannot possibly underflow skb->data since hsr_pull_tag() | ||
394 | * above succeeded. | ||
395 | * At this point in the protocol stack, the transport and | ||
396 | * network headers have not been set yet, and we haven't touched | ||
397 | * the mac header nor the head. So we only need to adjust data | ||
398 | * and tail: | ||
399 | */ | ||
400 | skb_deliver->data -= HSR_TAGLEN; | ||
401 | skb_deliver->tail -= HSR_TAGLEN; | ||
402 | #endif | ||
403 | skb_deliver->dev = hsr_priv->dev; | ||
404 | hsr_addr_subst_source(hsr_priv, skb_deliver); | ||
405 | multicast_frame = (skb_deliver->pkt_type == PACKET_MULTICAST); | ||
406 | ret = netif_rx(skb_deliver); | ||
407 | if (ret == NET_RX_DROP) { | ||
408 | hsr_priv->dev->stats.rx_dropped++; | ||
409 | } else { | ||
410 | hsr_priv->dev->stats.rx_packets++; | ||
411 | hsr_priv->dev->stats.rx_bytes += skb->len; | ||
412 | if (multicast_frame) | ||
413 | hsr_priv->dev->stats.multicast++; | ||
414 | } | ||
415 | } | ||
416 | |||
417 | forward: | ||
418 | if (other_slave) { | ||
419 | skb_push(skb, ETH_HLEN); | ||
420 | skb->dev = other_slave; | ||
421 | dev_queue_xmit(skb); | ||
422 | } | ||
423 | |||
424 | return NET_RX_SUCCESS; | ||
425 | } | ||
426 | |||
427 | |||
428 | static struct packet_type hsr_pt __read_mostly = { | ||
429 | .type = htons(ETH_P_PRP), | ||
430 | .func = hsr_rcv, | ||
431 | }; | ||
432 | |||
433 | static struct notifier_block hsr_nb = { | 107 | static struct notifier_block hsr_nb = { |
434 | .notifier_call = hsr_netdev_notify, /* Slave event notifications */ | 108 | .notifier_call = hsr_netdev_notify, /* Slave event notifications */ |
435 | }; | 109 | }; |
@@ -439,18 +113,9 @@ static int __init hsr_init(void) | |||
439 | { | 113 | { |
440 | int res; | 114 | int res; |
441 | 115 | ||
442 | BUILD_BUG_ON(sizeof(struct hsr_tag) != HSR_TAGLEN); | 116 | BUILD_BUG_ON(sizeof(struct hsr_tag) != HSR_HLEN); |
443 | |||
444 | dev_add_pack(&hsr_pt); | ||
445 | |||
446 | init_timer(&prune_timer); | ||
447 | prune_timer.function = prune_nodes_all; | ||
448 | prune_timer.data = 0; | ||
449 | prune_timer.expires = jiffies + msecs_to_jiffies(PRUNE_PERIOD); | ||
450 | add_timer(&prune_timer); | ||
451 | 117 | ||
452 | register_netdevice_notifier(&hsr_nb); | 118 | register_netdevice_notifier(&hsr_nb); |
453 | |||
454 | res = hsr_netlink_init(); | 119 | res = hsr_netlink_init(); |
455 | 120 | ||
456 | return res; | 121 | return res; |
@@ -459,9 +124,7 @@ static int __init hsr_init(void) | |||
459 | static void __exit hsr_exit(void) | 124 | static void __exit hsr_exit(void) |
460 | { | 125 | { |
461 | unregister_netdevice_notifier(&hsr_nb); | 126 | unregister_netdevice_notifier(&hsr_nb); |
462 | del_timer_sync(&prune_timer); | ||
463 | hsr_netlink_exit(); | 127 | hsr_netlink_exit(); |
464 | dev_remove_pack(&hsr_pt); | ||
465 | } | 128 | } |
466 | 129 | ||
467 | module_init(hsr_init); | 130 | module_init(hsr_init); |
diff --git a/net/hsr/hsr_main.h b/net/hsr/hsr_main.h index 56fe060c0ab1..5a9c69962ded 100644 --- a/net/hsr/hsr_main.h +++ b/net/hsr/hsr_main.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Copyright 2011-2013 Autronica Fire and Security AS | 1 | /* Copyright 2011-2014 Autronica Fire and Security AS |
2 | * | 2 | * |
3 | * This program is free software; you can redistribute it and/or modify it | 3 | * This program is free software; you can redistribute it and/or modify it |
4 | * under the terms of the GNU General Public License as published by the Free | 4 | * under the terms of the GNU General Public License as published by the Free |
@@ -6,11 +6,11 @@ | |||
6 | * any later version. | 6 | * any later version. |
7 | * | 7 | * |
8 | * Author(s): | 8 | * Author(s): |
9 | * 2011-2013 Arvid Brodin, arvid.brodin@xdin.com | 9 | * 2011-2014 Arvid Brodin, arvid.brodin@alten.se |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #ifndef _HSR_PRIVATE_H | 12 | #ifndef __HSR_PRIVATE_H |
13 | #define _HSR_PRIVATE_H | 13 | #define __HSR_PRIVATE_H |
14 | 14 | ||
15 | #include <linux/netdevice.h> | 15 | #include <linux/netdevice.h> |
16 | #include <linux/list.h> | 16 | #include <linux/list.h> |
@@ -29,6 +29,7 @@ | |||
29 | * each node differ before we notify of communication problem? | 29 | * each node differ before we notify of communication problem? |
30 | */ | 30 | */ |
31 | #define MAX_SLAVE_DIFF 3000 /* ms */ | 31 | #define MAX_SLAVE_DIFF 3000 /* ms */ |
32 | #define HSR_SEQNR_START (USHRT_MAX - 1024) | ||
32 | 33 | ||
33 | 34 | ||
34 | /* How often shall we check for broken ring and remove node entries older than | 35 | /* How often shall we check for broken ring and remove node entries older than |
@@ -46,16 +47,16 @@ | |||
46 | * path, LSDU_size, sequence Nr }. But we let eth_header() create { h_dest, | 47 | * path, LSDU_size, sequence Nr }. But we let eth_header() create { h_dest, |
47 | * h_source, h_proto = 0x88FB }, and add { path, LSDU_size, sequence Nr, | 48 | * h_source, h_proto = 0x88FB }, and add { path, LSDU_size, sequence Nr, |
48 | * encapsulated protocol } instead. | 49 | * encapsulated protocol } instead. |
50 | * | ||
51 | * Field names as defined in the IEC:2010 standard for HSR. | ||
49 | */ | 52 | */ |
50 | #define HSR_TAGLEN 6 | ||
51 | |||
52 | /* Field names below as defined in the IEC:2010 standard for HSR. */ | ||
53 | struct hsr_tag { | 53 | struct hsr_tag { |
54 | __be16 path_and_LSDU_size; | 54 | __be16 path_and_LSDU_size; |
55 | __be16 sequence_nr; | 55 | __be16 sequence_nr; |
56 | __be16 encap_proto; | 56 | __be16 encap_proto; |
57 | } __packed; | 57 | } __packed; |
58 | 58 | ||
59 | #define HSR_HLEN 6 | ||
59 | 60 | ||
60 | /* The helper functions below assumes that 'path' occupies the 4 most | 61 | /* The helper functions below assumes that 'path' occupies the 4 most |
61 | * significant bits of the 16-bit field shared by 'path' and 'LSDU_size' (or | 62 | * significant bits of the 16-bit field shared by 'path' and 'LSDU_size' (or |
@@ -136,31 +137,47 @@ struct hsr_ethhdr_sp { | |||
136 | } __packed; | 137 | } __packed; |
137 | 138 | ||
138 | 139 | ||
139 | enum hsr_dev_idx { | 140 | enum hsr_port_type { |
140 | HSR_DEV_NONE = -1, | 141 | HSR_PT_NONE = 0, /* Must be 0, used by framereg */ |
141 | HSR_DEV_SLAVE_A = 0, | 142 | HSR_PT_SLAVE_A, |
142 | HSR_DEV_SLAVE_B, | 143 | HSR_PT_SLAVE_B, |
143 | HSR_DEV_MASTER, | 144 | HSR_PT_INTERLINK, |
145 | HSR_PT_MASTER, | ||
146 | HSR_PT_PORTS, /* This must be the last item in the enum */ | ||
147 | }; | ||
148 | |||
149 | struct hsr_port { | ||
150 | struct list_head port_list; | ||
151 | struct net_device *dev; | ||
152 | struct hsr_priv *hsr; | ||
153 | enum hsr_port_type type; | ||
144 | }; | 154 | }; |
145 | #define HSR_MAX_SLAVE (HSR_DEV_SLAVE_B + 1) | ||
146 | #define HSR_MAX_DEV (HSR_DEV_MASTER + 1) | ||
147 | 155 | ||
148 | struct hsr_priv { | 156 | struct hsr_priv { |
149 | struct list_head hsr_list; /* List of hsr devices */ | ||
150 | struct rcu_head rcu_head; | 157 | struct rcu_head rcu_head; |
151 | struct net_device *dev; | 158 | struct list_head ports; |
152 | struct net_device *slave[HSR_MAX_SLAVE]; | 159 | struct list_head node_db; /* Known HSR nodes */ |
153 | struct list_head node_db; /* Other HSR nodes */ | ||
154 | struct list_head self_node_db; /* MACs of slaves */ | 160 | struct list_head self_node_db; /* MACs of slaves */ |
155 | struct timer_list announce_timer; /* Supervision frame dispatch */ | 161 | struct timer_list announce_timer; /* Supervision frame dispatch */ |
162 | struct timer_list prune_timer; | ||
156 | int announce_count; | 163 | int announce_count; |
157 | u16 sequence_nr; | 164 | u16 sequence_nr; |
158 | spinlock_t seqnr_lock; /* locking for sequence_nr */ | 165 | spinlock_t seqnr_lock; /* locking for sequence_nr */ |
159 | unsigned char sup_multicast_addr[ETH_ALEN]; | 166 | unsigned char sup_multicast_addr[ETH_ALEN]; |
160 | }; | 167 | }; |
161 | 168 | ||
162 | void register_hsr_master(struct hsr_priv *hsr_priv); | 169 | #define hsr_for_each_port(hsr, port) \ |
163 | void unregister_hsr_master(struct hsr_priv *hsr_priv); | 170 | list_for_each_entry_rcu((port), &(hsr)->ports, port_list) |
164 | bool is_hsr_slave(struct net_device *dev); | 171 | |
172 | struct hsr_port *hsr_port_get_hsr(struct hsr_priv *hsr, enum hsr_port_type pt); | ||
173 | |||
174 | /* Caller must ensure skb is a valid HSR frame */ | ||
175 | static inline u16 hsr_get_skb_sequence_nr(struct sk_buff *skb) | ||
176 | { | ||
177 | struct hsr_ethhdr *hsr_ethhdr; | ||
178 | |||
179 | hsr_ethhdr = (struct hsr_ethhdr *) skb_mac_header(skb); | ||
180 | return ntohs(hsr_ethhdr->hsr_tag.sequence_nr); | ||
181 | } | ||
165 | 182 | ||
166 | #endif /* _HSR_PRIVATE_H */ | 183 | #endif /* __HSR_PRIVATE_H */ |
diff --git a/net/hsr/hsr_netlink.c b/net/hsr/hsr_netlink.c index 01a5261ac7a5..a2c7e4c0ac1e 100644 --- a/net/hsr/hsr_netlink.c +++ b/net/hsr/hsr_netlink.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Copyright 2011-2013 Autronica Fire and Security AS | 1 | /* Copyright 2011-2014 Autronica Fire and Security AS |
2 | * | 2 | * |
3 | * This program is free software; you can redistribute it and/or modify it | 3 | * This program is free software; you can redistribute it and/or modify it |
4 | * under the terms of the GNU General Public License as published by the Free | 4 | * under the terms of the GNU General Public License as published by the Free |
@@ -6,7 +6,7 @@ | |||
6 | * any later version. | 6 | * any later version. |
7 | * | 7 | * |
8 | * Author(s): | 8 | * Author(s): |
9 | * 2011-2013 Arvid Brodin, arvid.brodin@xdin.com | 9 | * 2011-2014 Arvid Brodin, arvid.brodin@alten.se |
10 | * | 10 | * |
11 | * Routines for handling Netlink messages for HSR. | 11 | * Routines for handling Netlink messages for HSR. |
12 | */ | 12 | */ |
@@ -37,13 +37,17 @@ static int hsr_newlink(struct net *src_net, struct net_device *dev, | |||
37 | struct net_device *link[2]; | 37 | struct net_device *link[2]; |
38 | unsigned char multicast_spec; | 38 | unsigned char multicast_spec; |
39 | 39 | ||
40 | if (!data) { | ||
41 | netdev_info(dev, "HSR: No slave devices specified\n"); | ||
42 | return -EINVAL; | ||
43 | } | ||
40 | if (!data[IFLA_HSR_SLAVE1]) { | 44 | if (!data[IFLA_HSR_SLAVE1]) { |
41 | netdev_info(dev, "IFLA_HSR_SLAVE1 missing!\n"); | 45 | netdev_info(dev, "HSR: Slave1 device not specified\n"); |
42 | return -EINVAL; | 46 | return -EINVAL; |
43 | } | 47 | } |
44 | link[0] = __dev_get_by_index(src_net, nla_get_u32(data[IFLA_HSR_SLAVE1])); | 48 | link[0] = __dev_get_by_index(src_net, nla_get_u32(data[IFLA_HSR_SLAVE1])); |
45 | if (!data[IFLA_HSR_SLAVE2]) { | 49 | if (!data[IFLA_HSR_SLAVE2]) { |
46 | netdev_info(dev, "IFLA_HSR_SLAVE2 missing!\n"); | 50 | netdev_info(dev, "HSR: Slave2 device not specified\n"); |
47 | return -EINVAL; | 51 | return -EINVAL; |
48 | } | 52 | } |
49 | link[1] = __dev_get_by_index(src_net, nla_get_u32(data[IFLA_HSR_SLAVE2])); | 53 | link[1] = __dev_get_by_index(src_net, nla_get_u32(data[IFLA_HSR_SLAVE2])); |
@@ -63,21 +67,33 @@ static int hsr_newlink(struct net *src_net, struct net_device *dev, | |||
63 | 67 | ||
64 | static int hsr_fill_info(struct sk_buff *skb, const struct net_device *dev) | 68 | static int hsr_fill_info(struct sk_buff *skb, const struct net_device *dev) |
65 | { | 69 | { |
66 | struct hsr_priv *hsr_priv; | 70 | struct hsr_priv *hsr; |
71 | struct hsr_port *port; | ||
72 | int res; | ||
67 | 73 | ||
68 | hsr_priv = netdev_priv(dev); | 74 | hsr = netdev_priv(dev); |
69 | 75 | ||
70 | if (hsr_priv->slave[0]) | 76 | res = 0; |
71 | if (nla_put_u32(skb, IFLA_HSR_SLAVE1, hsr_priv->slave[0]->ifindex)) | ||
72 | goto nla_put_failure; | ||
73 | 77 | ||
74 | if (hsr_priv->slave[1]) | 78 | rcu_read_lock(); |
75 | if (nla_put_u32(skb, IFLA_HSR_SLAVE2, hsr_priv->slave[1]->ifindex)) | 79 | port = hsr_port_get_hsr(hsr, HSR_PT_SLAVE_A); |
76 | goto nla_put_failure; | 80 | if (port) |
81 | res = nla_put_u32(skb, IFLA_HSR_SLAVE1, port->dev->ifindex); | ||
82 | rcu_read_unlock(); | ||
83 | if (res) | ||
84 | goto nla_put_failure; | ||
85 | |||
86 | rcu_read_lock(); | ||
87 | port = hsr_port_get_hsr(hsr, HSR_PT_SLAVE_B); | ||
88 | if (port) | ||
89 | res = nla_put_u32(skb, IFLA_HSR_SLAVE2, port->dev->ifindex); | ||
90 | rcu_read_unlock(); | ||
91 | if (res) | ||
92 | goto nla_put_failure; | ||
77 | 93 | ||
78 | if (nla_put(skb, IFLA_HSR_SUPERVISION_ADDR, ETH_ALEN, | 94 | if (nla_put(skb, IFLA_HSR_SUPERVISION_ADDR, ETH_ALEN, |
79 | hsr_priv->sup_multicast_addr) || | 95 | hsr->sup_multicast_addr) || |
80 | nla_put_u16(skb, IFLA_HSR_SEQ_NR, hsr_priv->sequence_nr)) | 96 | nla_put_u16(skb, IFLA_HSR_SEQ_NR, hsr->sequence_nr)) |
81 | goto nla_put_failure; | 97 | goto nla_put_failure; |
82 | 98 | ||
83 | return 0; | 99 | return 0; |
@@ -128,13 +144,13 @@ static const struct genl_multicast_group hsr_mcgrps[] = { | |||
128 | * over one of the slave interfaces. This would indicate an open network ring | 144 | * over one of the slave interfaces. This would indicate an open network ring |
129 | * (i.e. a link has failed somewhere). | 145 | * (i.e. a link has failed somewhere). |
130 | */ | 146 | */ |
131 | void hsr_nl_ringerror(struct hsr_priv *hsr_priv, unsigned char addr[ETH_ALEN], | 147 | void hsr_nl_ringerror(struct hsr_priv *hsr, unsigned char addr[ETH_ALEN], |
132 | enum hsr_dev_idx dev_idx) | 148 | struct hsr_port *port) |
133 | { | 149 | { |
134 | struct sk_buff *skb; | 150 | struct sk_buff *skb; |
135 | void *msg_head; | 151 | void *msg_head; |
152 | struct hsr_port *master; | ||
136 | int res; | 153 | int res; |
137 | int ifindex; | ||
138 | 154 | ||
139 | skb = genlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); | 155 | skb = genlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); |
140 | if (!skb) | 156 | if (!skb) |
@@ -148,11 +164,7 @@ void hsr_nl_ringerror(struct hsr_priv *hsr_priv, unsigned char addr[ETH_ALEN], | |||
148 | if (res < 0) | 164 | if (res < 0) |
149 | goto nla_put_failure; | 165 | goto nla_put_failure; |
150 | 166 | ||
151 | if (hsr_priv->slave[dev_idx]) | 167 | res = nla_put_u32(skb, HSR_A_IFINDEX, port->dev->ifindex); |
152 | ifindex = hsr_priv->slave[dev_idx]->ifindex; | ||
153 | else | ||
154 | ifindex = -1; | ||
155 | res = nla_put_u32(skb, HSR_A_IFINDEX, ifindex); | ||
156 | if (res < 0) | 168 | if (res < 0) |
157 | goto nla_put_failure; | 169 | goto nla_put_failure; |
158 | 170 | ||
@@ -165,16 +177,20 @@ nla_put_failure: | |||
165 | kfree_skb(skb); | 177 | kfree_skb(skb); |
166 | 178 | ||
167 | fail: | 179 | fail: |
168 | netdev_warn(hsr_priv->dev, "Could not send HSR ring error message\n"); | 180 | rcu_read_lock(); |
181 | master = hsr_port_get_hsr(hsr, HSR_PT_MASTER); | ||
182 | netdev_warn(master->dev, "Could not send HSR ring error message\n"); | ||
183 | rcu_read_unlock(); | ||
169 | } | 184 | } |
170 | 185 | ||
171 | /* This is called when we haven't heard from the node with MAC address addr for | 186 | /* This is called when we haven't heard from the node with MAC address addr for |
172 | * some time (just before the node is removed from the node table/list). | 187 | * some time (just before the node is removed from the node table/list). |
173 | */ | 188 | */ |
174 | void hsr_nl_nodedown(struct hsr_priv *hsr_priv, unsigned char addr[ETH_ALEN]) | 189 | void hsr_nl_nodedown(struct hsr_priv *hsr, unsigned char addr[ETH_ALEN]) |
175 | { | 190 | { |
176 | struct sk_buff *skb; | 191 | struct sk_buff *skb; |
177 | void *msg_head; | 192 | void *msg_head; |
193 | struct hsr_port *master; | ||
178 | int res; | 194 | int res; |
179 | 195 | ||
180 | skb = genlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); | 196 | skb = genlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC); |
@@ -199,7 +215,10 @@ nla_put_failure: | |||
199 | kfree_skb(skb); | 215 | kfree_skb(skb); |
200 | 216 | ||
201 | fail: | 217 | fail: |
202 | netdev_warn(hsr_priv->dev, "Could not send HSR node down\n"); | 218 | rcu_read_lock(); |
219 | master = hsr_port_get_hsr(hsr, HSR_PT_MASTER); | ||
220 | netdev_warn(master->dev, "Could not send HSR node down\n"); | ||
221 | rcu_read_unlock(); | ||
203 | } | 222 | } |
204 | 223 | ||
205 | 224 | ||
@@ -220,7 +239,8 @@ static int hsr_get_node_status(struct sk_buff *skb_in, struct genl_info *info) | |||
220 | /* For sending */ | 239 | /* For sending */ |
221 | struct sk_buff *skb_out; | 240 | struct sk_buff *skb_out; |
222 | void *msg_head; | 241 | void *msg_head; |
223 | struct hsr_priv *hsr_priv; | 242 | struct hsr_priv *hsr; |
243 | struct hsr_port *port; | ||
224 | unsigned char hsr_node_addr_b[ETH_ALEN]; | 244 | unsigned char hsr_node_addr_b[ETH_ALEN]; |
225 | int hsr_node_if1_age; | 245 | int hsr_node_if1_age; |
226 | u16 hsr_node_if1_seq; | 246 | u16 hsr_node_if1_seq; |
@@ -267,8 +287,8 @@ static int hsr_get_node_status(struct sk_buff *skb_in, struct genl_info *info) | |||
267 | if (res < 0) | 287 | if (res < 0) |
268 | goto nla_put_failure; | 288 | goto nla_put_failure; |
269 | 289 | ||
270 | hsr_priv = netdev_priv(hsr_dev); | 290 | hsr = netdev_priv(hsr_dev); |
271 | res = hsr_get_node_data(hsr_priv, | 291 | res = hsr_get_node_data(hsr, |
272 | (unsigned char *) nla_data(info->attrs[HSR_A_NODE_ADDR]), | 292 | (unsigned char *) nla_data(info->attrs[HSR_A_NODE_ADDR]), |
273 | hsr_node_addr_b, | 293 | hsr_node_addr_b, |
274 | &addr_b_ifindex, | 294 | &addr_b_ifindex, |
@@ -301,9 +321,12 @@ static int hsr_get_node_status(struct sk_buff *skb_in, struct genl_info *info) | |||
301 | res = nla_put_u16(skb_out, HSR_A_IF1_SEQ, hsr_node_if1_seq); | 321 | res = nla_put_u16(skb_out, HSR_A_IF1_SEQ, hsr_node_if1_seq); |
302 | if (res < 0) | 322 | if (res < 0) |
303 | goto nla_put_failure; | 323 | goto nla_put_failure; |
304 | if (hsr_priv->slave[0]) | 324 | rcu_read_lock(); |
325 | port = hsr_port_get_hsr(hsr, HSR_PT_SLAVE_A); | ||
326 | if (port) | ||
305 | res = nla_put_u32(skb_out, HSR_A_IF1_IFINDEX, | 327 | res = nla_put_u32(skb_out, HSR_A_IF1_IFINDEX, |
306 | hsr_priv->slave[0]->ifindex); | 328 | port->dev->ifindex); |
329 | rcu_read_unlock(); | ||
307 | if (res < 0) | 330 | if (res < 0) |
308 | goto nla_put_failure; | 331 | goto nla_put_failure; |
309 | 332 | ||
@@ -313,9 +336,14 @@ static int hsr_get_node_status(struct sk_buff *skb_in, struct genl_info *info) | |||
313 | res = nla_put_u16(skb_out, HSR_A_IF2_SEQ, hsr_node_if2_seq); | 336 | res = nla_put_u16(skb_out, HSR_A_IF2_SEQ, hsr_node_if2_seq); |
314 | if (res < 0) | 337 | if (res < 0) |
315 | goto nla_put_failure; | 338 | goto nla_put_failure; |
316 | if (hsr_priv->slave[1]) | 339 | rcu_read_lock(); |
340 | port = hsr_port_get_hsr(hsr, HSR_PT_SLAVE_B); | ||
341 | if (port) | ||
317 | res = nla_put_u32(skb_out, HSR_A_IF2_IFINDEX, | 342 | res = nla_put_u32(skb_out, HSR_A_IF2_IFINDEX, |
318 | hsr_priv->slave[1]->ifindex); | 343 | port->dev->ifindex); |
344 | rcu_read_unlock(); | ||
345 | if (res < 0) | ||
346 | goto nla_put_failure; | ||
319 | 347 | ||
320 | genlmsg_end(skb_out, msg_head); | 348 | genlmsg_end(skb_out, msg_head); |
321 | genlmsg_unicast(genl_info_net(info), skb_out, info->snd_portid); | 349 | genlmsg_unicast(genl_info_net(info), skb_out, info->snd_portid); |
@@ -334,7 +362,7 @@ fail: | |||
334 | return res; | 362 | return res; |
335 | } | 363 | } |
336 | 364 | ||
337 | /* Get a list of MacAddressA of all nodes known to this node (other than self). | 365 | /* Get a list of MacAddressA of all nodes known to this node (including self). |
338 | */ | 366 | */ |
339 | static int hsr_get_node_list(struct sk_buff *skb_in, struct genl_info *info) | 367 | static int hsr_get_node_list(struct sk_buff *skb_in, struct genl_info *info) |
340 | { | 368 | { |
@@ -345,7 +373,7 @@ static int hsr_get_node_list(struct sk_buff *skb_in, struct genl_info *info) | |||
345 | /* For sending */ | 373 | /* For sending */ |
346 | struct sk_buff *skb_out; | 374 | struct sk_buff *skb_out; |
347 | void *msg_head; | 375 | void *msg_head; |
348 | struct hsr_priv *hsr_priv; | 376 | struct hsr_priv *hsr; |
349 | void *pos; | 377 | void *pos; |
350 | unsigned char addr[ETH_ALEN]; | 378 | unsigned char addr[ETH_ALEN]; |
351 | int res; | 379 | int res; |
@@ -385,17 +413,17 @@ static int hsr_get_node_list(struct sk_buff *skb_in, struct genl_info *info) | |||
385 | if (res < 0) | 413 | if (res < 0) |
386 | goto nla_put_failure; | 414 | goto nla_put_failure; |
387 | 415 | ||
388 | hsr_priv = netdev_priv(hsr_dev); | 416 | hsr = netdev_priv(hsr_dev); |
389 | 417 | ||
390 | rcu_read_lock(); | 418 | rcu_read_lock(); |
391 | pos = hsr_get_next_node(hsr_priv, NULL, addr); | 419 | pos = hsr_get_next_node(hsr, NULL, addr); |
392 | while (pos) { | 420 | while (pos) { |
393 | res = nla_put(skb_out, HSR_A_NODE_ADDR, ETH_ALEN, addr); | 421 | res = nla_put(skb_out, HSR_A_NODE_ADDR, ETH_ALEN, addr); |
394 | if (res < 0) { | 422 | if (res < 0) { |
395 | rcu_read_unlock(); | 423 | rcu_read_unlock(); |
396 | goto nla_put_failure; | 424 | goto nla_put_failure; |
397 | } | 425 | } |
398 | pos = hsr_get_next_node(hsr_priv, pos, addr); | 426 | pos = hsr_get_next_node(hsr, pos, addr); |
399 | } | 427 | } |
400 | rcu_read_unlock(); | 428 | rcu_read_unlock(); |
401 | 429 | ||
diff --git a/net/hsr/hsr_netlink.h b/net/hsr/hsr_netlink.h index d4579dcc3c7d..3f6b95b5b6b8 100644 --- a/net/hsr/hsr_netlink.h +++ b/net/hsr/hsr_netlink.h | |||
@@ -1,4 +1,4 @@ | |||
1 | /* Copyright 2011-2013 Autronica Fire and Security AS | 1 | /* Copyright 2011-2014 Autronica Fire and Security AS |
2 | * | 2 | * |
3 | * This program is free software; you can redistribute it and/or modify it | 3 | * This program is free software; you can redistribute it and/or modify it |
4 | * under the terms of the GNU General Public License as published by the Free | 4 | * under the terms of the GNU General Public License as published by the Free |
@@ -6,7 +6,7 @@ | |||
6 | * any later version. | 6 | * any later version. |
7 | * | 7 | * |
8 | * Author(s): | 8 | * Author(s): |
9 | * 2011-2013 Arvid Brodin, arvid.brodin@xdin.com | 9 | * 2011-2014 Arvid Brodin, arvid.brodin@alten.se |
10 | */ | 10 | */ |
11 | 11 | ||
12 | #ifndef __HSR_NETLINK_H | 12 | #ifndef __HSR_NETLINK_H |
@@ -17,13 +17,14 @@ | |||
17 | #include <uapi/linux/hsr_netlink.h> | 17 | #include <uapi/linux/hsr_netlink.h> |
18 | 18 | ||
19 | struct hsr_priv; | 19 | struct hsr_priv; |
20 | struct hsr_port; | ||
20 | 21 | ||
21 | int __init hsr_netlink_init(void); | 22 | int __init hsr_netlink_init(void); |
22 | void __exit hsr_netlink_exit(void); | 23 | void __exit hsr_netlink_exit(void); |
23 | 24 | ||
24 | void hsr_nl_ringerror(struct hsr_priv *hsr_priv, unsigned char addr[ETH_ALEN], | 25 | void hsr_nl_ringerror(struct hsr_priv *hsr, unsigned char addr[ETH_ALEN], |
25 | int dev_idx); | 26 | struct hsr_port *port); |
26 | void hsr_nl_nodedown(struct hsr_priv *hsr_priv, unsigned char addr[ETH_ALEN]); | 27 | void hsr_nl_nodedown(struct hsr_priv *hsr, unsigned char addr[ETH_ALEN]); |
27 | void hsr_nl_framedrop(int dropcount, int dev_idx); | 28 | void hsr_nl_framedrop(int dropcount, int dev_idx); |
28 | void hsr_nl_linkdown(int dev_idx); | 29 | void hsr_nl_linkdown(int dev_idx); |
29 | 30 | ||
diff --git a/net/hsr/hsr_slave.c b/net/hsr/hsr_slave.c new file mode 100644 index 000000000000..a348dcbcd683 --- /dev/null +++ b/net/hsr/hsr_slave.c | |||
@@ -0,0 +1,196 @@ | |||
1 | /* Copyright 2011-2014 Autronica Fire and Security AS | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify it | ||
4 | * under the terms of the GNU General Public License as published by the Free | ||
5 | * Software Foundation; either version 2 of the License, or (at your option) | ||
6 | * any later version. | ||
7 | * | ||
8 | * Author(s): | ||
9 | * 2011-2014 Arvid Brodin, arvid.brodin@alten.se | ||
10 | */ | ||
11 | |||
12 | #include "hsr_slave.h" | ||
13 | #include <linux/etherdevice.h> | ||
14 | #include <linux/if_arp.h> | ||
15 | #include "hsr_main.h" | ||
16 | #include "hsr_device.h" | ||
17 | #include "hsr_forward.h" | ||
18 | #include "hsr_framereg.h" | ||
19 | |||
20 | |||
21 | static rx_handler_result_t hsr_handle_frame(struct sk_buff **pskb) | ||
22 | { | ||
23 | struct sk_buff *skb = *pskb; | ||
24 | struct hsr_port *port; | ||
25 | |||
26 | if (!skb_mac_header_was_set(skb)) { | ||
27 | WARN_ONCE(1, "%s: skb invalid", __func__); | ||
28 | return RX_HANDLER_PASS; | ||
29 | } | ||
30 | |||
31 | rcu_read_lock(); /* hsr->node_db, hsr->ports */ | ||
32 | port = hsr_port_get_rcu(skb->dev); | ||
33 | |||
34 | if (hsr_addr_is_self(port->hsr, eth_hdr(skb)->h_source)) { | ||
35 | /* Directly kill frames sent by ourselves */ | ||
36 | kfree_skb(skb); | ||
37 | goto finish_consume; | ||
38 | } | ||
39 | |||
40 | if (eth_hdr(skb)->h_proto != htons(ETH_P_PRP)) | ||
41 | goto finish_pass; | ||
42 | |||
43 | skb_push(skb, ETH_HLEN); | ||
44 | |||
45 | hsr_forward_skb(skb, port); | ||
46 | |||
47 | finish_consume: | ||
48 | rcu_read_unlock(); /* hsr->node_db, hsr->ports */ | ||
49 | return RX_HANDLER_CONSUMED; | ||
50 | |||
51 | finish_pass: | ||
52 | rcu_read_unlock(); /* hsr->node_db, hsr->ports */ | ||
53 | return RX_HANDLER_PASS; | ||
54 | } | ||
55 | |||
56 | bool hsr_port_exists(const struct net_device *dev) | ||
57 | { | ||
58 | return rcu_access_pointer(dev->rx_handler) == hsr_handle_frame; | ||
59 | } | ||
60 | |||
61 | |||
62 | static int hsr_check_dev_ok(struct net_device *dev) | ||
63 | { | ||
64 | /* Don't allow HSR on non-ethernet like devices */ | ||
65 | if ((dev->flags & IFF_LOOPBACK) || (dev->type != ARPHRD_ETHER) || | ||
66 | (dev->addr_len != ETH_ALEN)) { | ||
67 | netdev_info(dev, "Cannot use loopback or non-ethernet device as HSR slave.\n"); | ||
68 | return -EINVAL; | ||
69 | } | ||
70 | |||
71 | /* Don't allow enslaving hsr devices */ | ||
72 | if (is_hsr_master(dev)) { | ||
73 | netdev_info(dev, "Cannot create trees of HSR devices.\n"); | ||
74 | return -EINVAL; | ||
75 | } | ||
76 | |||
77 | if (hsr_port_exists(dev)) { | ||
78 | netdev_info(dev, "This device is already a HSR slave.\n"); | ||
79 | return -EINVAL; | ||
80 | } | ||
81 | |||
82 | if (dev->priv_flags & IFF_802_1Q_VLAN) { | ||
83 | netdev_info(dev, "HSR on top of VLAN is not yet supported in this driver.\n"); | ||
84 | return -EINVAL; | ||
85 | } | ||
86 | |||
87 | if (dev->priv_flags & IFF_DONT_BRIDGE) { | ||
88 | netdev_info(dev, "This device does not support bridging.\n"); | ||
89 | return -EOPNOTSUPP; | ||
90 | } | ||
91 | |||
92 | /* HSR over bonded devices has not been tested, but I'm not sure it | ||
93 | * won't work... | ||
94 | */ | ||
95 | |||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | |||
100 | /* Setup device to be added to the HSR bridge. */ | ||
101 | static int hsr_portdev_setup(struct net_device *dev, struct hsr_port *port) | ||
102 | { | ||
103 | int res; | ||
104 | |||
105 | dev_hold(dev); | ||
106 | res = dev_set_promiscuity(dev, 1); | ||
107 | if (res) | ||
108 | goto fail_promiscuity; | ||
109 | |||
110 | /* FIXME: | ||
111 | * What does net device "adjacency" mean? Should we do | ||
112 | * res = netdev_master_upper_dev_link(port->dev, port->hsr->dev); ? | ||
113 | */ | ||
114 | |||
115 | res = netdev_rx_handler_register(dev, hsr_handle_frame, port); | ||
116 | if (res) | ||
117 | goto fail_rx_handler; | ||
118 | dev_disable_lro(dev); | ||
119 | |||
120 | return 0; | ||
121 | |||
122 | fail_rx_handler: | ||
123 | dev_set_promiscuity(dev, -1); | ||
124 | fail_promiscuity: | ||
125 | dev_put(dev); | ||
126 | |||
127 | return res; | ||
128 | } | ||
129 | |||
130 | int hsr_add_port(struct hsr_priv *hsr, struct net_device *dev, | ||
131 | enum hsr_port_type type) | ||
132 | { | ||
133 | struct hsr_port *port, *master; | ||
134 | int res; | ||
135 | |||
136 | if (type != HSR_PT_MASTER) { | ||
137 | res = hsr_check_dev_ok(dev); | ||
138 | if (res) | ||
139 | return res; | ||
140 | } | ||
141 | |||
142 | port = hsr_port_get_hsr(hsr, type); | ||
143 | if (port != NULL) | ||
144 | return -EBUSY; /* This port already exists */ | ||
145 | |||
146 | port = kzalloc(sizeof(*port), GFP_KERNEL); | ||
147 | if (port == NULL) | ||
148 | return -ENOMEM; | ||
149 | |||
150 | if (type != HSR_PT_MASTER) { | ||
151 | res = hsr_portdev_setup(dev, port); | ||
152 | if (res) | ||
153 | goto fail_dev_setup; | ||
154 | } | ||
155 | |||
156 | port->hsr = hsr; | ||
157 | port->dev = dev; | ||
158 | port->type = type; | ||
159 | |||
160 | list_add_tail_rcu(&port->port_list, &hsr->ports); | ||
161 | synchronize_rcu(); | ||
162 | |||
163 | master = hsr_port_get_hsr(hsr, HSR_PT_MASTER); | ||
164 | netdev_update_features(master->dev); | ||
165 | dev_set_mtu(master->dev, hsr_get_max_mtu(hsr)); | ||
166 | |||
167 | return 0; | ||
168 | |||
169 | fail_dev_setup: | ||
170 | kfree(port); | ||
171 | return res; | ||
172 | } | ||
173 | |||
174 | void hsr_del_port(struct hsr_port *port) | ||
175 | { | ||
176 | struct hsr_priv *hsr; | ||
177 | struct hsr_port *master; | ||
178 | |||
179 | hsr = port->hsr; | ||
180 | master = hsr_port_get_hsr(hsr, HSR_PT_MASTER); | ||
181 | list_del_rcu(&port->port_list); | ||
182 | |||
183 | if (port != master) { | ||
184 | netdev_update_features(master->dev); | ||
185 | dev_set_mtu(master->dev, hsr_get_max_mtu(hsr)); | ||
186 | netdev_rx_handler_unregister(port->dev); | ||
187 | dev_set_promiscuity(port->dev, -1); | ||
188 | } | ||
189 | |||
190 | /* FIXME? | ||
191 | * netdev_upper_dev_unlink(port->dev, port->hsr->dev); | ||
192 | */ | ||
193 | |||
194 | synchronize_rcu(); | ||
195 | dev_put(port->dev); | ||
196 | } | ||
diff --git a/net/hsr/hsr_slave.h b/net/hsr/hsr_slave.h new file mode 100644 index 000000000000..3ccfbf71c92e --- /dev/null +++ b/net/hsr/hsr_slave.h | |||
@@ -0,0 +1,38 @@ | |||
1 | /* Copyright 2011-2014 Autronica Fire and Security AS | ||
2 | * | ||
3 | * This program is free software; you can redistribute it and/or modify it | ||
4 | * under the terms of the GNU General Public License as published by the Free | ||
5 | * Software Foundation; either version 2 of the License, or (at your option) | ||
6 | * any later version. | ||
7 | * | ||
8 | * Author(s): | ||
9 | * 2011-2014 Arvid Brodin, arvid.brodin@alten.se | ||
10 | */ | ||
11 | |||
12 | #ifndef __HSR_SLAVE_H | ||
13 | #define __HSR_SLAVE_H | ||
14 | |||
15 | #include <linux/skbuff.h> | ||
16 | #include <linux/netdevice.h> | ||
17 | #include <linux/rtnetlink.h> | ||
18 | #include "hsr_main.h" | ||
19 | |||
20 | int hsr_add_port(struct hsr_priv *hsr, struct net_device *dev, | ||
21 | enum hsr_port_type pt); | ||
22 | void hsr_del_port(struct hsr_port *port); | ||
23 | bool hsr_port_exists(const struct net_device *dev); | ||
24 | |||
25 | static inline struct hsr_port *hsr_port_get_rtnl(const struct net_device *dev) | ||
26 | { | ||
27 | ASSERT_RTNL(); | ||
28 | return hsr_port_exists(dev) ? | ||
29 | rtnl_dereference(dev->rx_handler_data) : NULL; | ||
30 | } | ||
31 | |||
32 | static inline struct hsr_port *hsr_port_get_rcu(const struct net_device *dev) | ||
33 | { | ||
34 | return hsr_port_exists(dev) ? | ||
35 | rcu_dereference(dev->rx_handler_data) : NULL; | ||
36 | } | ||
37 | |||
38 | #endif /* __HSR_SLAVE_H */ | ||
diff --git a/net/ieee802154/6lowpan_rtnl.c b/net/ieee802154/6lowpan_rtnl.c index fe6bd7a71081..6591d27e53a4 100644 --- a/net/ieee802154/6lowpan_rtnl.c +++ b/net/ieee802154/6lowpan_rtnl.c | |||
@@ -80,14 +80,14 @@ lowpan_dev_info *lowpan_dev_info(const struct net_device *dev) | |||
80 | static inline void lowpan_address_flip(u8 *src, u8 *dest) | 80 | static inline void lowpan_address_flip(u8 *src, u8 *dest) |
81 | { | 81 | { |
82 | int i; | 82 | int i; |
83 | |||
83 | for (i = 0; i < IEEE802154_ADDR_LEN; i++) | 84 | for (i = 0; i < IEEE802154_ADDR_LEN; i++) |
84 | (dest)[IEEE802154_ADDR_LEN - i - 1] = (src)[i]; | 85 | (dest)[IEEE802154_ADDR_LEN - i - 1] = (src)[i]; |
85 | } | 86 | } |
86 | 87 | ||
87 | static int lowpan_header_create(struct sk_buff *skb, | 88 | static int lowpan_header_create(struct sk_buff *skb, struct net_device *dev, |
88 | struct net_device *dev, | 89 | unsigned short type, const void *_daddr, |
89 | unsigned short type, const void *_daddr, | 90 | const void *_saddr, unsigned int len) |
90 | const void *_saddr, unsigned int len) | ||
91 | { | 91 | { |
92 | const u8 *saddr = _saddr; | 92 | const u8 *saddr = _saddr; |
93 | const u8 *daddr = _daddr; | 93 | const u8 *daddr = _daddr; |
@@ -144,7 +144,7 @@ static int lowpan_header_create(struct sk_buff *skb, | |||
144 | } | 144 | } |
145 | 145 | ||
146 | static int lowpan_give_skb_to_devices(struct sk_buff *skb, | 146 | static int lowpan_give_skb_to_devices(struct sk_buff *skb, |
147 | struct net_device *dev) | 147 | struct net_device *dev) |
148 | { | 148 | { |
149 | struct lowpan_dev_record *entry; | 149 | struct lowpan_dev_record *entry; |
150 | struct sk_buff *skb_cp; | 150 | struct sk_buff *skb_cp; |
@@ -246,7 +246,7 @@ lowpan_alloc_frag(struct sk_buff *skb, int size, | |||
246 | return ERR_PTR(-rc); | 246 | return ERR_PTR(-rc); |
247 | } | 247 | } |
248 | } else { | 248 | } else { |
249 | frag = ERR_PTR(ENOMEM); | 249 | frag = ERR_PTR(-ENOMEM); |
250 | } | 250 | } |
251 | 251 | ||
252 | return frag; | 252 | return frag; |
@@ -368,24 +368,28 @@ static netdev_tx_t lowpan_xmit(struct sk_buff *skb, struct net_device *dev) | |||
368 | static struct wpan_phy *lowpan_get_phy(const struct net_device *dev) | 368 | static struct wpan_phy *lowpan_get_phy(const struct net_device *dev) |
369 | { | 369 | { |
370 | struct net_device *real_dev = lowpan_dev_info(dev)->real_dev; | 370 | struct net_device *real_dev = lowpan_dev_info(dev)->real_dev; |
371 | |||
371 | return ieee802154_mlme_ops(real_dev)->get_phy(real_dev); | 372 | return ieee802154_mlme_ops(real_dev)->get_phy(real_dev); |
372 | } | 373 | } |
373 | 374 | ||
374 | static __le16 lowpan_get_pan_id(const struct net_device *dev) | 375 | static __le16 lowpan_get_pan_id(const struct net_device *dev) |
375 | { | 376 | { |
376 | struct net_device *real_dev = lowpan_dev_info(dev)->real_dev; | 377 | struct net_device *real_dev = lowpan_dev_info(dev)->real_dev; |
378 | |||
377 | return ieee802154_mlme_ops(real_dev)->get_pan_id(real_dev); | 379 | return ieee802154_mlme_ops(real_dev)->get_pan_id(real_dev); |
378 | } | 380 | } |
379 | 381 | ||
380 | static __le16 lowpan_get_short_addr(const struct net_device *dev) | 382 | static __le16 lowpan_get_short_addr(const struct net_device *dev) |
381 | { | 383 | { |
382 | struct net_device *real_dev = lowpan_dev_info(dev)->real_dev; | 384 | struct net_device *real_dev = lowpan_dev_info(dev)->real_dev; |
385 | |||
383 | return ieee802154_mlme_ops(real_dev)->get_short_addr(real_dev); | 386 | return ieee802154_mlme_ops(real_dev)->get_short_addr(real_dev); |
384 | } | 387 | } |
385 | 388 | ||
386 | static u8 lowpan_get_dsn(const struct net_device *dev) | 389 | static u8 lowpan_get_dsn(const struct net_device *dev) |
387 | { | 390 | { |
388 | struct net_device *real_dev = lowpan_dev_info(dev)->real_dev; | 391 | struct net_device *real_dev = lowpan_dev_info(dev)->real_dev; |
392 | |||
389 | return ieee802154_mlme_ops(real_dev)->get_dsn(real_dev); | 393 | return ieee802154_mlme_ops(real_dev)->get_dsn(real_dev); |
390 | } | 394 | } |
391 | 395 | ||
@@ -433,7 +437,7 @@ static void lowpan_setup(struct net_device *dev) | |||
433 | /* Frame Control + Sequence Number + Address fields + Security Header */ | 437 | /* Frame Control + Sequence Number + Address fields + Security Header */ |
434 | dev->hard_header_len = 2 + 1 + 20 + 14; | 438 | dev->hard_header_len = 2 + 1 + 20 + 14; |
435 | dev->needed_tailroom = 2; /* FCS */ | 439 | dev->needed_tailroom = 2; /* FCS */ |
436 | dev->mtu = 1281; | 440 | dev->mtu = IPV6_MIN_MTU; |
437 | dev->tx_queue_len = 0; | 441 | dev->tx_queue_len = 0; |
438 | dev->flags = IFF_BROADCAST | IFF_MULTICAST; | 442 | dev->flags = IFF_BROADCAST | IFF_MULTICAST; |
439 | dev->watchdog_timeo = 0; | 443 | dev->watchdog_timeo = 0; |
@@ -454,7 +458,7 @@ static int lowpan_validate(struct nlattr *tb[], struct nlattr *data[]) | |||
454 | } | 458 | } |
455 | 459 | ||
456 | static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev, | 460 | static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev, |
457 | struct packet_type *pt, struct net_device *orig_dev) | 461 | struct packet_type *pt, struct net_device *orig_dev) |
458 | { | 462 | { |
459 | struct ieee802154_hdr hdr; | 463 | struct ieee802154_hdr hdr; |
460 | int ret; | 464 | int ret; |
diff --git a/net/ieee802154/Kconfig b/net/ieee802154/Kconfig index 8af1330b3137..c0d4154d144f 100644 --- a/net/ieee802154/Kconfig +++ b/net/ieee802154/Kconfig | |||
@@ -12,13 +12,6 @@ config IEEE802154 | |||
12 | 12 | ||
13 | config IEEE802154_6LOWPAN | 13 | config IEEE802154_6LOWPAN |
14 | tristate "6lowpan support over IEEE 802.15.4" | 14 | tristate "6lowpan support over IEEE 802.15.4" |
15 | depends on IEEE802154 && IPV6 | 15 | depends on IEEE802154 && 6LOWPAN |
16 | select 6LOWPAN_IPHC | ||
17 | ---help--- | 16 | ---help--- |
18 | IPv6 compression over IEEE 802.15.4. | 17 | IPv6 compression over IEEE 802.15.4. |
19 | |||
20 | config 6LOWPAN_IPHC | ||
21 | tristate | ||
22 | ---help--- | ||
23 | 6lowpan compression code which is shared between IEEE 802.15.4 and Bluetooth | ||
24 | stacks. | ||
diff --git a/net/ieee802154/Makefile b/net/ieee802154/Makefile index bf1b51497a41..3914b1ed4274 100644 --- a/net/ieee802154/Makefile +++ b/net/ieee802154/Makefile | |||
@@ -1,8 +1,7 @@ | |||
1 | obj-$(CONFIG_IEEE802154) += ieee802154.o af_802154.o | 1 | obj-$(CONFIG_IEEE802154) += ieee802154.o af_802154.o |
2 | obj-$(CONFIG_IEEE802154_6LOWPAN) += 6lowpan.o | 2 | obj-$(CONFIG_IEEE802154_6LOWPAN) += ieee802154_6lowpan.o |
3 | obj-$(CONFIG_6LOWPAN_IPHC) += 6lowpan_iphc.o | ||
4 | 3 | ||
5 | 6lowpan-y := 6lowpan_rtnl.o reassembly.o | 4 | ieee802154_6lowpan-y := 6lowpan_rtnl.o reassembly.o |
6 | ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o \ | 5 | ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o \ |
7 | header_ops.o | 6 | header_ops.o |
8 | af_802154-y := af_ieee802154.o raw.o dgram.o | 7 | af_802154-y := af_ieee802154.o raw.o dgram.o |
diff --git a/net/ieee802154/af_ieee802154.c b/net/ieee802154/af_ieee802154.c index 351d9a94ec2f..29e0de63001b 100644 --- a/net/ieee802154/af_ieee802154.c +++ b/net/ieee802154/af_ieee802154.c | |||
@@ -40,9 +40,7 @@ | |||
40 | 40 | ||
41 | #include "af802154.h" | 41 | #include "af802154.h" |
42 | 42 | ||
43 | /* | 43 | /* Utility function for families */ |
44 | * Utility function for families | ||
45 | */ | ||
46 | struct net_device* | 44 | struct net_device* |
47 | ieee802154_get_dev(struct net *net, const struct ieee802154_addr *addr) | 45 | ieee802154_get_dev(struct net *net, const struct ieee802154_addr *addr) |
48 | { | 46 | { |
@@ -87,8 +85,8 @@ ieee802154_get_dev(struct net *net, const struct ieee802154_addr *addr) | |||
87 | rtnl_unlock(); | 85 | rtnl_unlock(); |
88 | break; | 86 | break; |
89 | default: | 87 | default: |
90 | pr_warning("Unsupported ieee802154 address type: %d\n", | 88 | pr_warn("Unsupported ieee802154 address type: %d\n", |
91 | addr->mode); | 89 | addr->mode); |
92 | break; | 90 | break; |
93 | } | 91 | } |
94 | 92 | ||
@@ -106,7 +104,7 @@ static int ieee802154_sock_release(struct socket *sock) | |||
106 | return 0; | 104 | return 0; |
107 | } | 105 | } |
108 | static int ieee802154_sock_sendmsg(struct kiocb *iocb, struct socket *sock, | 106 | static int ieee802154_sock_sendmsg(struct kiocb *iocb, struct socket *sock, |
109 | struct msghdr *msg, size_t len) | 107 | struct msghdr *msg, size_t len) |
110 | { | 108 | { |
111 | struct sock *sk = sock->sk; | 109 | struct sock *sk = sock->sk; |
112 | 110 | ||
@@ -114,7 +112,7 @@ static int ieee802154_sock_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
114 | } | 112 | } |
115 | 113 | ||
116 | static int ieee802154_sock_bind(struct socket *sock, struct sockaddr *uaddr, | 114 | static int ieee802154_sock_bind(struct socket *sock, struct sockaddr *uaddr, |
117 | int addr_len) | 115 | int addr_len) |
118 | { | 116 | { |
119 | struct sock *sk = sock->sk; | 117 | struct sock *sk = sock->sk; |
120 | 118 | ||
@@ -125,7 +123,7 @@ static int ieee802154_sock_bind(struct socket *sock, struct sockaddr *uaddr, | |||
125 | } | 123 | } |
126 | 124 | ||
127 | static int ieee802154_sock_connect(struct socket *sock, struct sockaddr *uaddr, | 125 | static int ieee802154_sock_connect(struct socket *sock, struct sockaddr *uaddr, |
128 | int addr_len, int flags) | 126 | int addr_len, int flags) |
129 | { | 127 | { |
130 | struct sock *sk = sock->sk; | 128 | struct sock *sk = sock->sk; |
131 | 129 | ||
@@ -139,7 +137,7 @@ static int ieee802154_sock_connect(struct socket *sock, struct sockaddr *uaddr, | |||
139 | } | 137 | } |
140 | 138 | ||
141 | static int ieee802154_dev_ioctl(struct sock *sk, struct ifreq __user *arg, | 139 | static int ieee802154_dev_ioctl(struct sock *sk, struct ifreq __user *arg, |
142 | unsigned int cmd) | 140 | unsigned int cmd) |
143 | { | 141 | { |
144 | struct ifreq ifr; | 142 | struct ifreq ifr; |
145 | int ret = -ENOIOCTLCMD; | 143 | int ret = -ENOIOCTLCMD; |
@@ -167,7 +165,7 @@ static int ieee802154_dev_ioctl(struct sock *sk, struct ifreq __user *arg, | |||
167 | } | 165 | } |
168 | 166 | ||
169 | static int ieee802154_sock_ioctl(struct socket *sock, unsigned int cmd, | 167 | static int ieee802154_sock_ioctl(struct socket *sock, unsigned int cmd, |
170 | unsigned long arg) | 168 | unsigned long arg) |
171 | { | 169 | { |
172 | struct sock *sk = sock->sk; | 170 | struct sock *sk = sock->sk; |
173 | 171 | ||
@@ -238,8 +236,7 @@ static const struct proto_ops ieee802154_dgram_ops = { | |||
238 | }; | 236 | }; |
239 | 237 | ||
240 | 238 | ||
241 | /* | 239 | /* Create a socket. Initialise the socket, blank the addresses |
242 | * Create a socket. Initialise the socket, blank the addresses | ||
243 | * set the state. | 240 | * set the state. |
244 | */ | 241 | */ |
245 | static int ieee802154_create(struct net *net, struct socket *sock, | 242 | static int ieee802154_create(struct net *net, struct socket *sock, |
@@ -301,13 +298,14 @@ static const struct net_proto_family ieee802154_family_ops = { | |||
301 | }; | 298 | }; |
302 | 299 | ||
303 | static int ieee802154_rcv(struct sk_buff *skb, struct net_device *dev, | 300 | static int ieee802154_rcv(struct sk_buff *skb, struct net_device *dev, |
304 | struct packet_type *pt, struct net_device *orig_dev) | 301 | struct packet_type *pt, struct net_device *orig_dev) |
305 | { | 302 | { |
306 | if (!netif_running(dev)) | 303 | if (!netif_running(dev)) |
307 | goto drop; | 304 | goto drop; |
308 | pr_debug("got frame, type %d, dev %p\n", dev->type, dev); | 305 | pr_debug("got frame, type %d, dev %p\n", dev->type, dev); |
309 | #ifdef DEBUG | 306 | #ifdef DEBUG |
310 | print_hex_dump_bytes("ieee802154_rcv ", DUMP_PREFIX_NONE, skb->data, skb->len); | 307 | print_hex_dump_bytes("ieee802154_rcv ", |
308 | DUMP_PREFIX_NONE, skb->data, skb->len); | ||
311 | #endif | 309 | #endif |
312 | 310 | ||
313 | if (!net_eq(dev_net(dev), &init_net)) | 311 | if (!net_eq(dev_net(dev), &init_net)) |
diff --git a/net/ieee802154/dgram.c b/net/ieee802154/dgram.c index 4f0ed8780194..ef2ad8aaef13 100644 --- a/net/ieee802154/dgram.c +++ b/net/ieee802154/dgram.c | |||
@@ -149,8 +149,7 @@ static int dgram_ioctl(struct sock *sk, int cmd, unsigned long arg) | |||
149 | spin_lock_bh(&sk->sk_receive_queue.lock); | 149 | spin_lock_bh(&sk->sk_receive_queue.lock); |
150 | skb = skb_peek(&sk->sk_receive_queue); | 150 | skb = skb_peek(&sk->sk_receive_queue); |
151 | if (skb != NULL) { | 151 | if (skb != NULL) { |
152 | /* | 152 | /* We will only return the amount |
153 | * We will only return the amount | ||
154 | * of this packet since that is all | 153 | * of this packet since that is all |
155 | * that will be read. | 154 | * that will be read. |
156 | */ | 155 | */ |
@@ -161,12 +160,13 @@ static int dgram_ioctl(struct sock *sk, int cmd, unsigned long arg) | |||
161 | } | 160 | } |
162 | 161 | ||
163 | } | 162 | } |
163 | |||
164 | return -ENOIOCTLCMD; | 164 | return -ENOIOCTLCMD; |
165 | } | 165 | } |
166 | 166 | ||
167 | /* FIXME: autobind */ | 167 | /* FIXME: autobind */ |
168 | static int dgram_connect(struct sock *sk, struct sockaddr *uaddr, | 168 | static int dgram_connect(struct sock *sk, struct sockaddr *uaddr, |
169 | int len) | 169 | int len) |
170 | { | 170 | { |
171 | struct sockaddr_ieee802154 *addr = (struct sockaddr_ieee802154 *)uaddr; | 171 | struct sockaddr_ieee802154 *addr = (struct sockaddr_ieee802154 *)uaddr; |
172 | struct dgram_sock *ro = dgram_sk(sk); | 172 | struct dgram_sock *ro = dgram_sk(sk); |
@@ -205,7 +205,7 @@ static int dgram_disconnect(struct sock *sk, int flags) | |||
205 | } | 205 | } |
206 | 206 | ||
207 | static int dgram_sendmsg(struct kiocb *iocb, struct sock *sk, | 207 | static int dgram_sendmsg(struct kiocb *iocb, struct sock *sk, |
208 | struct msghdr *msg, size_t size) | 208 | struct msghdr *msg, size_t size) |
209 | { | 209 | { |
210 | struct net_device *dev; | 210 | struct net_device *dev; |
211 | unsigned int mtu; | 211 | unsigned int mtu; |
@@ -248,8 +248,8 @@ static int dgram_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
248 | hlen = LL_RESERVED_SPACE(dev); | 248 | hlen = LL_RESERVED_SPACE(dev); |
249 | tlen = dev->needed_tailroom; | 249 | tlen = dev->needed_tailroom; |
250 | skb = sock_alloc_send_skb(sk, hlen + tlen + size, | 250 | skb = sock_alloc_send_skb(sk, hlen + tlen + size, |
251 | msg->msg_flags & MSG_DONTWAIT, | 251 | msg->msg_flags & MSG_DONTWAIT, |
252 | &err); | 252 | &err); |
253 | if (!skb) | 253 | if (!skb) |
254 | goto out_dev; | 254 | goto out_dev; |
255 | 255 | ||
@@ -262,7 +262,8 @@ static int dgram_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
262 | cb->ackreq = ro->want_ack; | 262 | cb->ackreq = ro->want_ack; |
263 | 263 | ||
264 | if (msg->msg_name) { | 264 | if (msg->msg_name) { |
265 | DECLARE_SOCKADDR(struct sockaddr_ieee802154*, daddr, msg->msg_name); | 265 | DECLARE_SOCKADDR(struct sockaddr_ieee802154*, |
266 | daddr, msg->msg_name); | ||
266 | 267 | ||
267 | ieee802154_addr_from_sa(&dst_addr, &daddr->addr); | 268 | ieee802154_addr_from_sa(&dst_addr, &daddr->addr); |
268 | } else { | 269 | } else { |
@@ -304,8 +305,8 @@ out: | |||
304 | } | 305 | } |
305 | 306 | ||
306 | static int dgram_recvmsg(struct kiocb *iocb, struct sock *sk, | 307 | static int dgram_recvmsg(struct kiocb *iocb, struct sock *sk, |
307 | struct msghdr *msg, size_t len, int noblock, int flags, | 308 | struct msghdr *msg, size_t len, int noblock, |
308 | int *addr_len) | 309 | int flags, int *addr_len) |
309 | { | 310 | { |
310 | size_t copied = 0; | 311 | size_t copied = 0; |
311 | int err = -EOPNOTSUPP; | 312 | int err = -EOPNOTSUPP; |
@@ -398,6 +399,7 @@ int ieee802154_dgram_deliver(struct net_device *dev, struct sk_buff *skb) | |||
398 | dgram_sk(sk))) { | 399 | dgram_sk(sk))) { |
399 | if (prev) { | 400 | if (prev) { |
400 | struct sk_buff *clone; | 401 | struct sk_buff *clone; |
402 | |||
401 | clone = skb_clone(skb, GFP_ATOMIC); | 403 | clone = skb_clone(skb, GFP_ATOMIC); |
402 | if (clone) | 404 | if (clone) |
403 | dgram_rcv_skb(prev, clone); | 405 | dgram_rcv_skb(prev, clone); |
@@ -407,9 +409,9 @@ int ieee802154_dgram_deliver(struct net_device *dev, struct sk_buff *skb) | |||
407 | } | 409 | } |
408 | } | 410 | } |
409 | 411 | ||
410 | if (prev) | 412 | if (prev) { |
411 | dgram_rcv_skb(prev, skb); | 413 | dgram_rcv_skb(prev, skb); |
412 | else { | 414 | } else { |
413 | kfree_skb(skb); | 415 | kfree_skb(skb); |
414 | ret = NET_RX_DROP; | 416 | ret = NET_RX_DROP; |
415 | } | 417 | } |
@@ -419,7 +421,7 @@ int ieee802154_dgram_deliver(struct net_device *dev, struct sk_buff *skb) | |||
419 | } | 421 | } |
420 | 422 | ||
421 | static int dgram_getsockopt(struct sock *sk, int level, int optname, | 423 | static int dgram_getsockopt(struct sock *sk, int level, int optname, |
422 | char __user *optval, int __user *optlen) | 424 | char __user *optval, int __user *optlen) |
423 | { | 425 | { |
424 | struct dgram_sock *ro = dgram_sk(sk); | 426 | struct dgram_sock *ro = dgram_sk(sk); |
425 | 427 | ||
@@ -463,7 +465,7 @@ static int dgram_getsockopt(struct sock *sk, int level, int optname, | |||
463 | } | 465 | } |
464 | 466 | ||
465 | static int dgram_setsockopt(struct sock *sk, int level, int optname, | 467 | static int dgram_setsockopt(struct sock *sk, int level, int optname, |
466 | char __user *optval, unsigned int optlen) | 468 | char __user *optval, unsigned int optlen) |
467 | { | 469 | { |
468 | struct dgram_sock *ro = dgram_sk(sk); | 470 | struct dgram_sock *ro = dgram_sk(sk); |
469 | struct net *net = sock_net(sk); | 471 | struct net *net = sock_net(sk); |
diff --git a/net/ieee802154/ieee802154.h b/net/ieee802154/ieee802154.h index 8b83a231299e..5d352f86979e 100644 --- a/net/ieee802154/ieee802154.h +++ b/net/ieee802154/ieee802154.h | |||
@@ -43,7 +43,7 @@ struct genl_info; | |||
43 | struct sk_buff *ieee802154_nl_create(int flags, u8 req); | 43 | struct sk_buff *ieee802154_nl_create(int flags, u8 req); |
44 | int ieee802154_nl_mcast(struct sk_buff *msg, unsigned int group); | 44 | int ieee802154_nl_mcast(struct sk_buff *msg, unsigned int group); |
45 | struct sk_buff *ieee802154_nl_new_reply(struct genl_info *info, | 45 | struct sk_buff *ieee802154_nl_new_reply(struct genl_info *info, |
46 | int flags, u8 req); | 46 | int flags, u8 req); |
47 | int ieee802154_nl_reply(struct sk_buff *msg, struct genl_info *info); | 47 | int ieee802154_nl_reply(struct sk_buff *msg, struct genl_info *info); |
48 | 48 | ||
49 | extern struct genl_family nl802154_family; | 49 | extern struct genl_family nl802154_family; |
diff --git a/net/ieee802154/netlink.c b/net/ieee802154/netlink.c index 26efcf4fd2ff..9222966f5e6d 100644 --- a/net/ieee802154/netlink.c +++ b/net/ieee802154/netlink.c | |||
@@ -52,7 +52,7 @@ struct sk_buff *ieee802154_nl_create(int flags, u8 req) | |||
52 | 52 | ||
53 | spin_lock_irqsave(&ieee802154_seq_lock, f); | 53 | spin_lock_irqsave(&ieee802154_seq_lock, f); |
54 | hdr = genlmsg_put(msg, 0, ieee802154_seq_num++, | 54 | hdr = genlmsg_put(msg, 0, ieee802154_seq_num++, |
55 | &nl802154_family, flags, req); | 55 | &nl802154_family, flags, req); |
56 | spin_unlock_irqrestore(&ieee802154_seq_lock, f); | 56 | spin_unlock_irqrestore(&ieee802154_seq_lock, f); |
57 | if (!hdr) { | 57 | if (!hdr) { |
58 | nlmsg_free(msg); | 58 | nlmsg_free(msg); |
@@ -86,7 +86,7 @@ struct sk_buff *ieee802154_nl_new_reply(struct genl_info *info, | |||
86 | return NULL; | 86 | return NULL; |
87 | 87 | ||
88 | hdr = genlmsg_put_reply(msg, info, | 88 | hdr = genlmsg_put_reply(msg, info, |
89 | &nl802154_family, flags, req); | 89 | &nl802154_family, flags, req); |
90 | if (!hdr) { | 90 | if (!hdr) { |
91 | nlmsg_free(msg); | 91 | nlmsg_free(msg); |
92 | return NULL; | 92 | return NULL; |
diff --git a/net/ieee802154/nl-mac.c b/net/ieee802154/nl-mac.c index a3281b8bfd5b..c6bfe22bfa5e 100644 --- a/net/ieee802154/nl-mac.c +++ b/net/ieee802154/nl-mac.c | |||
@@ -60,7 +60,8 @@ static __le16 nla_get_shortaddr(const struct nlattr *nla) | |||
60 | } | 60 | } |
61 | 61 | ||
62 | int ieee802154_nl_assoc_indic(struct net_device *dev, | 62 | int ieee802154_nl_assoc_indic(struct net_device *dev, |
63 | struct ieee802154_addr *addr, u8 cap) | 63 | struct ieee802154_addr *addr, |
64 | u8 cap) | ||
64 | { | 65 | { |
65 | struct sk_buff *msg; | 66 | struct sk_buff *msg; |
66 | 67 | ||
@@ -93,7 +94,7 @@ nla_put_failure: | |||
93 | EXPORT_SYMBOL(ieee802154_nl_assoc_indic); | 94 | EXPORT_SYMBOL(ieee802154_nl_assoc_indic); |
94 | 95 | ||
95 | int ieee802154_nl_assoc_confirm(struct net_device *dev, __le16 short_addr, | 96 | int ieee802154_nl_assoc_confirm(struct net_device *dev, __le16 short_addr, |
96 | u8 status) | 97 | u8 status) |
97 | { | 98 | { |
98 | struct sk_buff *msg; | 99 | struct sk_buff *msg; |
99 | 100 | ||
@@ -119,7 +120,8 @@ nla_put_failure: | |||
119 | EXPORT_SYMBOL(ieee802154_nl_assoc_confirm); | 120 | EXPORT_SYMBOL(ieee802154_nl_assoc_confirm); |
120 | 121 | ||
121 | int ieee802154_nl_disassoc_indic(struct net_device *dev, | 122 | int ieee802154_nl_disassoc_indic(struct net_device *dev, |
122 | struct ieee802154_addr *addr, u8 reason) | 123 | struct ieee802154_addr *addr, |
124 | u8 reason) | ||
123 | { | 125 | { |
124 | struct sk_buff *msg; | 126 | struct sk_buff *msg; |
125 | 127 | ||
@@ -205,8 +207,9 @@ nla_put_failure: | |||
205 | EXPORT_SYMBOL(ieee802154_nl_beacon_indic); | 207 | EXPORT_SYMBOL(ieee802154_nl_beacon_indic); |
206 | 208 | ||
207 | int ieee802154_nl_scan_confirm(struct net_device *dev, | 209 | int ieee802154_nl_scan_confirm(struct net_device *dev, |
208 | u8 status, u8 scan_type, u32 unscanned, u8 page, | 210 | u8 status, u8 scan_type, |
209 | u8 *edl/* , struct list_head *pan_desc_list */) | 211 | u32 unscanned, u8 page, |
212 | u8 *edl/* , struct list_head *pan_desc_list */) | ||
210 | { | 213 | { |
211 | struct sk_buff *msg; | 214 | struct sk_buff *msg; |
212 | 215 | ||
@@ -260,7 +263,7 @@ nla_put_failure: | |||
260 | EXPORT_SYMBOL(ieee802154_nl_start_confirm); | 263 | EXPORT_SYMBOL(ieee802154_nl_start_confirm); |
261 | 264 | ||
262 | static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 portid, | 265 | static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 portid, |
263 | u32 seq, int flags, struct net_device *dev) | 266 | u32 seq, int flags, struct net_device *dev) |
264 | { | 267 | { |
265 | void *hdr; | 268 | void *hdr; |
266 | struct wpan_phy *phy; | 269 | struct wpan_phy *phy; |
@@ -270,7 +273,7 @@ static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 portid, | |||
270 | pr_debug("%s\n", __func__); | 273 | pr_debug("%s\n", __func__); |
271 | 274 | ||
272 | hdr = genlmsg_put(msg, 0, seq, &nl802154_family, flags, | 275 | hdr = genlmsg_put(msg, 0, seq, &nl802154_family, flags, |
273 | IEEE802154_LIST_IFACE); | 276 | IEEE802154_LIST_IFACE); |
274 | if (!hdr) | 277 | if (!hdr) |
275 | goto out; | 278 | goto out; |
276 | 279 | ||
@@ -330,14 +333,16 @@ static struct net_device *ieee802154_nl_get_dev(struct genl_info *info) | |||
330 | 333 | ||
331 | if (info->attrs[IEEE802154_ATTR_DEV_NAME]) { | 334 | if (info->attrs[IEEE802154_ATTR_DEV_NAME]) { |
332 | char name[IFNAMSIZ + 1]; | 335 | char name[IFNAMSIZ + 1]; |
336 | |||
333 | nla_strlcpy(name, info->attrs[IEEE802154_ATTR_DEV_NAME], | 337 | nla_strlcpy(name, info->attrs[IEEE802154_ATTR_DEV_NAME], |
334 | sizeof(name)); | 338 | sizeof(name)); |
335 | dev = dev_get_by_name(&init_net, name); | 339 | dev = dev_get_by_name(&init_net, name); |
336 | } else if (info->attrs[IEEE802154_ATTR_DEV_INDEX]) | 340 | } else if (info->attrs[IEEE802154_ATTR_DEV_INDEX]) { |
337 | dev = dev_get_by_index(&init_net, | 341 | dev = dev_get_by_index(&init_net, |
338 | nla_get_u32(info->attrs[IEEE802154_ATTR_DEV_INDEX])); | 342 | nla_get_u32(info->attrs[IEEE802154_ATTR_DEV_INDEX])); |
339 | else | 343 | } else { |
340 | return NULL; | 344 | return NULL; |
345 | } | ||
341 | 346 | ||
342 | if (!dev) | 347 | if (!dev) |
343 | return NULL; | 348 | return NULL; |
@@ -435,7 +440,7 @@ int ieee802154_disassociate_req(struct sk_buff *skb, struct genl_info *info) | |||
435 | int ret = -EOPNOTSUPP; | 440 | int ret = -EOPNOTSUPP; |
436 | 441 | ||
437 | if ((!info->attrs[IEEE802154_ATTR_DEST_HW_ADDR] && | 442 | if ((!info->attrs[IEEE802154_ATTR_DEST_HW_ADDR] && |
438 | !info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]) || | 443 | !info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]) || |
439 | !info->attrs[IEEE802154_ATTR_REASON]) | 444 | !info->attrs[IEEE802154_ATTR_REASON]) |
440 | return -EINVAL; | 445 | return -EINVAL; |
441 | 446 | ||
@@ -464,8 +469,7 @@ out: | |||
464 | return ret; | 469 | return ret; |
465 | } | 470 | } |
466 | 471 | ||
467 | /* | 472 | /* PANid, channel, beacon_order = 15, superframe_order = 15, |
468 | * PANid, channel, beacon_order = 15, superframe_order = 15, | ||
469 | * PAN_coordinator, battery_life_extension = 0, | 473 | * PAN_coordinator, battery_life_extension = 0, |
470 | * coord_realignment = 0, security_enable = 0 | 474 | * coord_realignment = 0, security_enable = 0 |
471 | */ | 475 | */ |
@@ -559,8 +563,8 @@ int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info) | |||
559 | page = 0; | 563 | page = 0; |
560 | 564 | ||
561 | 565 | ||
562 | ret = ieee802154_mlme_ops(dev)->scan_req(dev, type, channels, page, | 566 | ret = ieee802154_mlme_ops(dev)->scan_req(dev, type, channels, |
563 | duration); | 567 | page, duration); |
564 | 568 | ||
565 | out: | 569 | out: |
566 | dev_put(dev); | 570 | dev_put(dev); |
@@ -570,7 +574,8 @@ out: | |||
570 | int ieee802154_list_iface(struct sk_buff *skb, struct genl_info *info) | 574 | int ieee802154_list_iface(struct sk_buff *skb, struct genl_info *info) |
571 | { | 575 | { |
572 | /* Request for interface name, index, type, IEEE address, | 576 | /* Request for interface name, index, type, IEEE address, |
573 | PAN Id, short address */ | 577 | * PAN Id, short address |
578 | */ | ||
574 | struct sk_buff *msg; | 579 | struct sk_buff *msg; |
575 | struct net_device *dev = NULL; | 580 | struct net_device *dev = NULL; |
576 | int rc = -ENOBUFS; | 581 | int rc = -ENOBUFS; |
@@ -586,7 +591,7 @@ int ieee802154_list_iface(struct sk_buff *skb, struct genl_info *info) | |||
586 | goto out_dev; | 591 | goto out_dev; |
587 | 592 | ||
588 | rc = ieee802154_nl_fill_iface(msg, info->snd_portid, info->snd_seq, | 593 | rc = ieee802154_nl_fill_iface(msg, info->snd_portid, info->snd_seq, |
589 | 0, dev); | 594 | 0, dev); |
590 | if (rc < 0) | 595 | if (rc < 0) |
591 | goto out_free; | 596 | goto out_free; |
592 | 597 | ||
@@ -598,7 +603,6 @@ out_free: | |||
598 | out_dev: | 603 | out_dev: |
599 | dev_put(dev); | 604 | dev_put(dev); |
600 | return rc; | 605 | return rc; |
601 | |||
602 | } | 606 | } |
603 | 607 | ||
604 | int ieee802154_dump_iface(struct sk_buff *skb, struct netlink_callback *cb) | 608 | int ieee802154_dump_iface(struct sk_buff *skb, struct netlink_callback *cb) |
@@ -616,7 +620,8 @@ int ieee802154_dump_iface(struct sk_buff *skb, struct netlink_callback *cb) | |||
616 | goto cont; | 620 | goto cont; |
617 | 621 | ||
618 | if (ieee802154_nl_fill_iface(skb, NETLINK_CB(cb->skb).portid, | 622 | if (ieee802154_nl_fill_iface(skb, NETLINK_CB(cb->skb).portid, |
619 | cb->nlh->nlmsg_seq, NLM_F_MULTI, dev) < 0) | 623 | cb->nlh->nlmsg_seq, |
624 | NLM_F_MULTI, dev) < 0) | ||
620 | break; | 625 | break; |
621 | cont: | 626 | cont: |
622 | idx++; | 627 | idx++; |
@@ -765,6 +770,7 @@ ieee802154_llsec_parse_key_id(struct genl_info *info, | |||
765 | case IEEE802154_SCF_KEY_SHORT_INDEX: | 770 | case IEEE802154_SCF_KEY_SHORT_INDEX: |
766 | { | 771 | { |
767 | u32 source = nla_get_u32(info->attrs[IEEE802154_ATTR_LLSEC_KEY_SOURCE_SHORT]); | 772 | u32 source = nla_get_u32(info->attrs[IEEE802154_ATTR_LLSEC_KEY_SOURCE_SHORT]); |
773 | |||
768 | desc->short_source = cpu_to_le32(source); | 774 | desc->short_source = cpu_to_le32(source); |
769 | break; | 775 | break; |
770 | } | 776 | } |
@@ -842,7 +848,7 @@ int ieee802154_llsec_getparams(struct sk_buff *skb, struct genl_info *info) | |||
842 | goto out_dev; | 848 | goto out_dev; |
843 | 849 | ||
844 | hdr = genlmsg_put(msg, 0, info->snd_seq, &nl802154_family, 0, | 850 | hdr = genlmsg_put(msg, 0, info->snd_seq, &nl802154_family, 0, |
845 | IEEE802154_LLSEC_GETPARAMS); | 851 | IEEE802154_LLSEC_GETPARAMS); |
846 | if (!hdr) | 852 | if (!hdr) |
847 | goto out_free; | 853 | goto out_free; |
848 | 854 | ||
@@ -946,7 +952,7 @@ struct llsec_dump_data { | |||
946 | 952 | ||
947 | static int | 953 | static int |
948 | ieee802154_llsec_dump_table(struct sk_buff *skb, struct netlink_callback *cb, | 954 | ieee802154_llsec_dump_table(struct sk_buff *skb, struct netlink_callback *cb, |
949 | int (*step)(struct llsec_dump_data*)) | 955 | int (*step)(struct llsec_dump_data *)) |
950 | { | 956 | { |
951 | struct net *net = sock_net(skb->sk); | 957 | struct net *net = sock_net(skb->sk); |
952 | struct net_device *dev; | 958 | struct net_device *dev; |
diff --git a/net/ieee802154/nl-phy.c b/net/ieee802154/nl-phy.c index 89b265aea151..972baf83411a 100644 --- a/net/ieee802154/nl-phy.c +++ b/net/ieee802154/nl-phy.c | |||
@@ -36,7 +36,7 @@ | |||
36 | #include "ieee802154.h" | 36 | #include "ieee802154.h" |
37 | 37 | ||
38 | static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 portid, | 38 | static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 portid, |
39 | u32 seq, int flags, struct wpan_phy *phy) | 39 | u32 seq, int flags, struct wpan_phy *phy) |
40 | { | 40 | { |
41 | void *hdr; | 41 | void *hdr; |
42 | int i, pages = 0; | 42 | int i, pages = 0; |
@@ -48,7 +48,7 @@ static int ieee802154_nl_fill_phy(struct sk_buff *msg, u32 portid, | |||
48 | return -EMSGSIZE; | 48 | return -EMSGSIZE; |
49 | 49 | ||
50 | hdr = genlmsg_put(msg, 0, seq, &nl802154_family, flags, | 50 | hdr = genlmsg_put(msg, 0, seq, &nl802154_family, flags, |
51 | IEEE802154_LIST_PHY); | 51 | IEEE802154_LIST_PHY); |
52 | if (!hdr) | 52 | if (!hdr) |
53 | goto out; | 53 | goto out; |
54 | 54 | ||
@@ -80,7 +80,8 @@ out: | |||
80 | int ieee802154_list_phy(struct sk_buff *skb, struct genl_info *info) | 80 | int ieee802154_list_phy(struct sk_buff *skb, struct genl_info *info) |
81 | { | 81 | { |
82 | /* Request for interface name, index, type, IEEE address, | 82 | /* Request for interface name, index, type, IEEE address, |
83 | PAN Id, short address */ | 83 | * PAN Id, short address |
84 | */ | ||
84 | struct sk_buff *msg; | 85 | struct sk_buff *msg; |
85 | struct wpan_phy *phy; | 86 | struct wpan_phy *phy; |
86 | const char *name; | 87 | const char *name; |
@@ -105,7 +106,7 @@ int ieee802154_list_phy(struct sk_buff *skb, struct genl_info *info) | |||
105 | goto out_dev; | 106 | goto out_dev; |
106 | 107 | ||
107 | rc = ieee802154_nl_fill_phy(msg, info->snd_portid, info->snd_seq, | 108 | rc = ieee802154_nl_fill_phy(msg, info->snd_portid, info->snd_seq, |
108 | 0, phy); | 109 | 0, phy); |
109 | if (rc < 0) | 110 | if (rc < 0) |
110 | goto out_free; | 111 | goto out_free; |
111 | 112 | ||
@@ -117,7 +118,6 @@ out_free: | |||
117 | out_dev: | 118 | out_dev: |
118 | wpan_phy_put(phy); | 119 | wpan_phy_put(phy); |
119 | return rc; | 120 | return rc; |
120 | |||
121 | } | 121 | } |
122 | 122 | ||
123 | struct dump_phy_data { | 123 | struct dump_phy_data { |
@@ -137,10 +137,10 @@ static int ieee802154_dump_phy_iter(struct wpan_phy *phy, void *_data) | |||
137 | return 0; | 137 | return 0; |
138 | 138 | ||
139 | rc = ieee802154_nl_fill_phy(data->skb, | 139 | rc = ieee802154_nl_fill_phy(data->skb, |
140 | NETLINK_CB(data->cb->skb).portid, | 140 | NETLINK_CB(data->cb->skb).portid, |
141 | data->cb->nlh->nlmsg_seq, | 141 | data->cb->nlh->nlmsg_seq, |
142 | NLM_F_MULTI, | 142 | NLM_F_MULTI, |
143 | phy); | 143 | phy); |
144 | 144 | ||
145 | if (rc < 0) { | 145 | if (rc < 0) { |
146 | data->idx--; | 146 | data->idx--; |
@@ -238,10 +238,9 @@ int ieee802154_add_iface(struct sk_buff *skb, struct genl_info *info) | |||
238 | 238 | ||
239 | addr.sa_family = ARPHRD_IEEE802154; | 239 | addr.sa_family = ARPHRD_IEEE802154; |
240 | nla_memcpy(&addr.sa_data, info->attrs[IEEE802154_ATTR_HW_ADDR], | 240 | nla_memcpy(&addr.sa_data, info->attrs[IEEE802154_ATTR_HW_ADDR], |
241 | IEEE802154_ADDR_LEN); | 241 | IEEE802154_ADDR_LEN); |
242 | 242 | ||
243 | /* | 243 | /* strangely enough, some callbacks (inetdev_event) from |
244 | * strangely enough, some callbacks (inetdev_event) from | ||
245 | * dev_set_mac_address require RTNL_LOCK | 244 | * dev_set_mac_address require RTNL_LOCK |
246 | */ | 245 | */ |
247 | rtnl_lock(); | 246 | rtnl_lock(); |
diff --git a/net/ieee802154/raw.c b/net/ieee802154/raw.c index 74d54fae33d7..9d1f64806f02 100644 --- a/net/ieee802154/raw.c +++ b/net/ieee802154/raw.c | |||
@@ -96,7 +96,7 @@ out: | |||
96 | } | 96 | } |
97 | 97 | ||
98 | static int raw_connect(struct sock *sk, struct sockaddr *uaddr, | 98 | static int raw_connect(struct sock *sk, struct sockaddr *uaddr, |
99 | int addr_len) | 99 | int addr_len) |
100 | { | 100 | { |
101 | return -ENOTSUPP; | 101 | return -ENOTSUPP; |
102 | } | 102 | } |
@@ -106,8 +106,8 @@ static int raw_disconnect(struct sock *sk, int flags) | |||
106 | return 0; | 106 | return 0; |
107 | } | 107 | } |
108 | 108 | ||
109 | static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | 109 | static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, |
110 | size_t size) | 110 | struct msghdr *msg, size_t size) |
111 | { | 111 | { |
112 | struct net_device *dev; | 112 | struct net_device *dev; |
113 | unsigned int mtu; | 113 | unsigned int mtu; |
@@ -145,7 +145,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
145 | hlen = LL_RESERVED_SPACE(dev); | 145 | hlen = LL_RESERVED_SPACE(dev); |
146 | tlen = dev->needed_tailroom; | 146 | tlen = dev->needed_tailroom; |
147 | skb = sock_alloc_send_skb(sk, hlen + tlen + size, | 147 | skb = sock_alloc_send_skb(sk, hlen + tlen + size, |
148 | msg->msg_flags & MSG_DONTWAIT, &err); | 148 | msg->msg_flags & MSG_DONTWAIT, &err); |
149 | if (!skb) | 149 | if (!skb) |
150 | goto out_dev; | 150 | goto out_dev; |
151 | 151 | ||
@@ -235,7 +235,6 @@ void ieee802154_raw_deliver(struct net_device *dev, struct sk_buff *skb) | |||
235 | bh_lock_sock(sk); | 235 | bh_lock_sock(sk); |
236 | if (!sk->sk_bound_dev_if || | 236 | if (!sk->sk_bound_dev_if || |
237 | sk->sk_bound_dev_if == dev->ifindex) { | 237 | sk->sk_bound_dev_if == dev->ifindex) { |
238 | |||
239 | struct sk_buff *clone; | 238 | struct sk_buff *clone; |
240 | 239 | ||
241 | clone = skb_clone(skb, GFP_ATOMIC); | 240 | clone = skb_clone(skb, GFP_ATOMIC); |
@@ -248,13 +247,13 @@ void ieee802154_raw_deliver(struct net_device *dev, struct sk_buff *skb) | |||
248 | } | 247 | } |
249 | 248 | ||
250 | static int raw_getsockopt(struct sock *sk, int level, int optname, | 249 | static int raw_getsockopt(struct sock *sk, int level, int optname, |
251 | char __user *optval, int __user *optlen) | 250 | char __user *optval, int __user *optlen) |
252 | { | 251 | { |
253 | return -EOPNOTSUPP; | 252 | return -EOPNOTSUPP; |
254 | } | 253 | } |
255 | 254 | ||
256 | static int raw_setsockopt(struct sock *sk, int level, int optname, | 255 | static int raw_setsockopt(struct sock *sk, int level, int optname, |
257 | char __user *optval, unsigned int optlen) | 256 | char __user *optval, unsigned int optlen) |
258 | { | 257 | { |
259 | return -EOPNOTSUPP; | 258 | return -EOPNOTSUPP; |
260 | } | 259 | } |
@@ -274,4 +273,3 @@ struct proto ieee802154_raw_prot = { | |||
274 | .getsockopt = raw_getsockopt, | 273 | .getsockopt = raw_getsockopt, |
275 | .setsockopt = raw_setsockopt, | 274 | .setsockopt = raw_setsockopt, |
276 | }; | 275 | }; |
277 | |||
diff --git a/net/ieee802154/reassembly.c b/net/ieee802154/reassembly.c index 6f1428c4870b..32755cb7e64e 100644 --- a/net/ieee802154/reassembly.c +++ b/net/ieee802154/reassembly.c | |||
@@ -30,6 +30,8 @@ | |||
30 | 30 | ||
31 | #include "reassembly.h" | 31 | #include "reassembly.h" |
32 | 32 | ||
33 | static const char lowpan_frags_cache_name[] = "lowpan-frags"; | ||
34 | |||
33 | struct lowpan_frag_info { | 35 | struct lowpan_frag_info { |
34 | __be16 d_tag; | 36 | __be16 d_tag; |
35 | u16 d_size; | 37 | u16 d_size; |
@@ -50,29 +52,25 @@ static unsigned int lowpan_hash_frag(__be16 tag, u16 d_size, | |||
50 | const struct ieee802154_addr *saddr, | 52 | const struct ieee802154_addr *saddr, |
51 | const struct ieee802154_addr *daddr) | 53 | const struct ieee802154_addr *daddr) |
52 | { | 54 | { |
53 | u32 c; | ||
54 | |||
55 | net_get_random_once(&lowpan_frags.rnd, sizeof(lowpan_frags.rnd)); | 55 | net_get_random_once(&lowpan_frags.rnd, sizeof(lowpan_frags.rnd)); |
56 | c = jhash_3words(ieee802154_addr_hash(saddr), | 56 | return jhash_3words(ieee802154_addr_hash(saddr), |
57 | ieee802154_addr_hash(daddr), | 57 | ieee802154_addr_hash(daddr), |
58 | (__force u32)(tag + (d_size << 16)), | 58 | (__force u32)(tag + (d_size << 16)), |
59 | lowpan_frags.rnd); | 59 | lowpan_frags.rnd); |
60 | |||
61 | return c & (INETFRAGS_HASHSZ - 1); | ||
62 | } | 60 | } |
63 | 61 | ||
64 | static unsigned int lowpan_hashfn(struct inet_frag_queue *q) | 62 | static unsigned int lowpan_hashfn(const struct inet_frag_queue *q) |
65 | { | 63 | { |
66 | struct lowpan_frag_queue *fq; | 64 | const struct lowpan_frag_queue *fq; |
67 | 65 | ||
68 | fq = container_of(q, struct lowpan_frag_queue, q); | 66 | fq = container_of(q, struct lowpan_frag_queue, q); |
69 | return lowpan_hash_frag(fq->tag, fq->d_size, &fq->saddr, &fq->daddr); | 67 | return lowpan_hash_frag(fq->tag, fq->d_size, &fq->saddr, &fq->daddr); |
70 | } | 68 | } |
71 | 69 | ||
72 | static bool lowpan_frag_match(struct inet_frag_queue *q, void *a) | 70 | static bool lowpan_frag_match(const struct inet_frag_queue *q, const void *a) |
73 | { | 71 | { |
74 | struct lowpan_frag_queue *fq; | 72 | const struct lowpan_frag_queue *fq; |
75 | struct lowpan_create_arg *arg = a; | 73 | const struct lowpan_create_arg *arg = a; |
76 | 74 | ||
77 | fq = container_of(q, struct lowpan_frag_queue, q); | 75 | fq = container_of(q, struct lowpan_frag_queue, q); |
78 | return fq->tag == arg->tag && fq->d_size == arg->d_size && | 76 | return fq->tag == arg->tag && fq->d_size == arg->d_size && |
@@ -80,10 +78,10 @@ static bool lowpan_frag_match(struct inet_frag_queue *q, void *a) | |||
80 | ieee802154_addr_equal(&fq->daddr, arg->dst); | 78 | ieee802154_addr_equal(&fq->daddr, arg->dst); |
81 | } | 79 | } |
82 | 80 | ||
83 | static void lowpan_frag_init(struct inet_frag_queue *q, void *a) | 81 | static void lowpan_frag_init(struct inet_frag_queue *q, const void *a) |
84 | { | 82 | { |
83 | const struct lowpan_create_arg *arg = a; | ||
85 | struct lowpan_frag_queue *fq; | 84 | struct lowpan_frag_queue *fq; |
86 | struct lowpan_create_arg *arg = a; | ||
87 | 85 | ||
88 | fq = container_of(q, struct lowpan_frag_queue, q); | 86 | fq = container_of(q, struct lowpan_frag_queue, q); |
89 | 87 | ||
@@ -103,7 +101,7 @@ static void lowpan_frag_expire(unsigned long data) | |||
103 | 101 | ||
104 | spin_lock(&fq->q.lock); | 102 | spin_lock(&fq->q.lock); |
105 | 103 | ||
106 | if (fq->q.last_in & INET_FRAG_COMPLETE) | 104 | if (fq->q.flags & INET_FRAG_COMPLETE) |
107 | goto out; | 105 | goto out; |
108 | 106 | ||
109 | inet_frag_kill(&fq->q, &lowpan_frags); | 107 | inet_frag_kill(&fq->q, &lowpan_frags); |
@@ -128,7 +126,6 @@ fq_find(struct net *net, const struct lowpan_frag_info *frag_info, | |||
128 | arg.src = src; | 126 | arg.src = src; |
129 | arg.dst = dst; | 127 | arg.dst = dst; |
130 | 128 | ||
131 | read_lock(&lowpan_frags.lock); | ||
132 | hash = lowpan_hash_frag(frag_info->d_tag, frag_info->d_size, src, dst); | 129 | hash = lowpan_hash_frag(frag_info->d_tag, frag_info->d_size, src, dst); |
133 | 130 | ||
134 | q = inet_frag_find(&ieee802154_lowpan->frags, | 131 | q = inet_frag_find(&ieee802154_lowpan->frags, |
@@ -147,7 +144,7 @@ static int lowpan_frag_queue(struct lowpan_frag_queue *fq, | |||
147 | struct net_device *dev; | 144 | struct net_device *dev; |
148 | int end, offset; | 145 | int end, offset; |
149 | 146 | ||
150 | if (fq->q.last_in & INET_FRAG_COMPLETE) | 147 | if (fq->q.flags & INET_FRAG_COMPLETE) |
151 | goto err; | 148 | goto err; |
152 | 149 | ||
153 | offset = lowpan_cb(skb)->d_offset << 3; | 150 | offset = lowpan_cb(skb)->d_offset << 3; |
@@ -159,14 +156,14 @@ static int lowpan_frag_queue(struct lowpan_frag_queue *fq, | |||
159 | * or have different end, the segment is corrupted. | 156 | * or have different end, the segment is corrupted. |
160 | */ | 157 | */ |
161 | if (end < fq->q.len || | 158 | if (end < fq->q.len || |
162 | ((fq->q.last_in & INET_FRAG_LAST_IN) && end != fq->q.len)) | 159 | ((fq->q.flags & INET_FRAG_LAST_IN) && end != fq->q.len)) |
163 | goto err; | 160 | goto err; |
164 | fq->q.last_in |= INET_FRAG_LAST_IN; | 161 | fq->q.flags |= INET_FRAG_LAST_IN; |
165 | fq->q.len = end; | 162 | fq->q.len = end; |
166 | } else { | 163 | } else { |
167 | if (end > fq->q.len) { | 164 | if (end > fq->q.len) { |
168 | /* Some bits beyond end -> corruption. */ | 165 | /* Some bits beyond end -> corruption. */ |
169 | if (fq->q.last_in & INET_FRAG_LAST_IN) | 166 | if (fq->q.flags & INET_FRAG_LAST_IN) |
170 | goto err; | 167 | goto err; |
171 | fq->q.len = end; | 168 | fq->q.len = end; |
172 | } | 169 | } |
@@ -206,13 +203,13 @@ found: | |||
206 | if (frag_type == LOWPAN_DISPATCH_FRAG1) { | 203 | if (frag_type == LOWPAN_DISPATCH_FRAG1) { |
207 | /* Calculate uncomp. 6lowpan header to estimate full size */ | 204 | /* Calculate uncomp. 6lowpan header to estimate full size */ |
208 | fq->q.meat += lowpan_uncompress_size(skb, NULL); | 205 | fq->q.meat += lowpan_uncompress_size(skb, NULL); |
209 | fq->q.last_in |= INET_FRAG_FIRST_IN; | 206 | fq->q.flags |= INET_FRAG_FIRST_IN; |
210 | } else { | 207 | } else { |
211 | fq->q.meat += skb->len; | 208 | fq->q.meat += skb->len; |
212 | } | 209 | } |
213 | add_frag_mem_limit(&fq->q, skb->truesize); | 210 | add_frag_mem_limit(&fq->q, skb->truesize); |
214 | 211 | ||
215 | if (fq->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && | 212 | if (fq->q.flags == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && |
216 | fq->q.meat == fq->q.len) { | 213 | fq->q.meat == fq->q.len) { |
217 | int res; | 214 | int res; |
218 | unsigned long orefdst = skb->_skb_refdst; | 215 | unsigned long orefdst = skb->_skb_refdst; |
@@ -223,7 +220,6 @@ found: | |||
223 | return res; | 220 | return res; |
224 | } | 221 | } |
225 | 222 | ||
226 | inet_frag_lru_move(&fq->q); | ||
227 | return -1; | 223 | return -1; |
228 | err: | 224 | err: |
229 | kfree_skb(skb); | 225 | kfree_skb(skb); |
@@ -359,8 +355,6 @@ int lowpan_frag_rcv(struct sk_buff *skb, const u8 frag_type) | |||
359 | struct net *net = dev_net(skb->dev); | 355 | struct net *net = dev_net(skb->dev); |
360 | struct lowpan_frag_info *frag_info = lowpan_cb(skb); | 356 | struct lowpan_frag_info *frag_info = lowpan_cb(skb); |
361 | struct ieee802154_addr source, dest; | 357 | struct ieee802154_addr source, dest; |
362 | struct netns_ieee802154_lowpan *ieee802154_lowpan = | ||
363 | net_ieee802154_lowpan(net); | ||
364 | int err; | 358 | int err; |
365 | 359 | ||
366 | source = mac_cb(skb)->source; | 360 | source = mac_cb(skb)->source; |
@@ -370,14 +364,15 @@ int lowpan_frag_rcv(struct sk_buff *skb, const u8 frag_type) | |||
370 | if (err < 0) | 364 | if (err < 0) |
371 | goto err; | 365 | goto err; |
372 | 366 | ||
373 | if (frag_info->d_size > ieee802154_lowpan->max_dsize) | 367 | if (frag_info->d_size > IPV6_MIN_MTU) { |
368 | net_warn_ratelimited("lowpan_frag_rcv: datagram size exceeds MTU\n"); | ||
374 | goto err; | 369 | goto err; |
375 | 370 | } | |
376 | inet_frag_evictor(&ieee802154_lowpan->frags, &lowpan_frags, false); | ||
377 | 371 | ||
378 | fq = fq_find(net, frag_info, &source, &dest); | 372 | fq = fq_find(net, frag_info, &source, &dest); |
379 | if (fq != NULL) { | 373 | if (fq != NULL) { |
380 | int ret; | 374 | int ret; |
375 | |||
381 | spin_lock(&fq->q.lock); | 376 | spin_lock(&fq->q.lock); |
382 | ret = lowpan_frag_queue(fq, skb, frag_type); | 377 | ret = lowpan_frag_queue(fq, skb, frag_type); |
383 | spin_unlock(&fq->q.lock); | 378 | spin_unlock(&fq->q.lock); |
@@ -393,20 +388,25 @@ err: | |||
393 | EXPORT_SYMBOL(lowpan_frag_rcv); | 388 | EXPORT_SYMBOL(lowpan_frag_rcv); |
394 | 389 | ||
395 | #ifdef CONFIG_SYSCTL | 390 | #ifdef CONFIG_SYSCTL |
391 | static int zero; | ||
392 | |||
396 | static struct ctl_table lowpan_frags_ns_ctl_table[] = { | 393 | static struct ctl_table lowpan_frags_ns_ctl_table[] = { |
397 | { | 394 | { |
398 | .procname = "6lowpanfrag_high_thresh", | 395 | .procname = "6lowpanfrag_high_thresh", |
399 | .data = &init_net.ieee802154_lowpan.frags.high_thresh, | 396 | .data = &init_net.ieee802154_lowpan.frags.high_thresh, |
400 | .maxlen = sizeof(int), | 397 | .maxlen = sizeof(int), |
401 | .mode = 0644, | 398 | .mode = 0644, |
402 | .proc_handler = proc_dointvec | 399 | .proc_handler = proc_dointvec_minmax, |
400 | .extra1 = &init_net.ieee802154_lowpan.frags.low_thresh | ||
403 | }, | 401 | }, |
404 | { | 402 | { |
405 | .procname = "6lowpanfrag_low_thresh", | 403 | .procname = "6lowpanfrag_low_thresh", |
406 | .data = &init_net.ieee802154_lowpan.frags.low_thresh, | 404 | .data = &init_net.ieee802154_lowpan.frags.low_thresh, |
407 | .maxlen = sizeof(int), | 405 | .maxlen = sizeof(int), |
408 | .mode = 0644, | 406 | .mode = 0644, |
409 | .proc_handler = proc_dointvec | 407 | .proc_handler = proc_dointvec_minmax, |
408 | .extra1 = &zero, | ||
409 | .extra2 = &init_net.ieee802154_lowpan.frags.high_thresh | ||
410 | }, | 410 | }, |
411 | { | 411 | { |
412 | .procname = "6lowpanfrag_time", | 412 | .procname = "6lowpanfrag_time", |
@@ -415,20 +415,15 @@ static struct ctl_table lowpan_frags_ns_ctl_table[] = { | |||
415 | .mode = 0644, | 415 | .mode = 0644, |
416 | .proc_handler = proc_dointvec_jiffies, | 416 | .proc_handler = proc_dointvec_jiffies, |
417 | }, | 417 | }, |
418 | { | ||
419 | .procname = "6lowpanfrag_max_datagram_size", | ||
420 | .data = &init_net.ieee802154_lowpan.max_dsize, | ||
421 | .maxlen = sizeof(int), | ||
422 | .mode = 0644, | ||
423 | .proc_handler = proc_dointvec | ||
424 | }, | ||
425 | { } | 418 | { } |
426 | }; | 419 | }; |
427 | 420 | ||
421 | /* secret interval has been deprecated */ | ||
422 | static int lowpan_frags_secret_interval_unused; | ||
428 | static struct ctl_table lowpan_frags_ctl_table[] = { | 423 | static struct ctl_table lowpan_frags_ctl_table[] = { |
429 | { | 424 | { |
430 | .procname = "6lowpanfrag_secret_interval", | 425 | .procname = "6lowpanfrag_secret_interval", |
431 | .data = &lowpan_frags.secret_interval, | 426 | .data = &lowpan_frags_secret_interval_unused, |
432 | .maxlen = sizeof(int), | 427 | .maxlen = sizeof(int), |
433 | .mode = 0644, | 428 | .mode = 0644, |
434 | .proc_handler = proc_dointvec_jiffies, | 429 | .proc_handler = proc_dointvec_jiffies, |
@@ -451,9 +446,11 @@ static int __net_init lowpan_frags_ns_sysctl_register(struct net *net) | |||
451 | goto err_alloc; | 446 | goto err_alloc; |
452 | 447 | ||
453 | table[0].data = &ieee802154_lowpan->frags.high_thresh; | 448 | table[0].data = &ieee802154_lowpan->frags.high_thresh; |
449 | table[0].extra1 = &ieee802154_lowpan->frags.low_thresh; | ||
450 | table[0].extra2 = &init_net.ieee802154_lowpan.frags.high_thresh; | ||
454 | table[1].data = &ieee802154_lowpan->frags.low_thresh; | 451 | table[1].data = &ieee802154_lowpan->frags.low_thresh; |
452 | table[1].extra2 = &ieee802154_lowpan->frags.high_thresh; | ||
455 | table[2].data = &ieee802154_lowpan->frags.timeout; | 453 | table[2].data = &ieee802154_lowpan->frags.timeout; |
456 | table[3].data = &ieee802154_lowpan->max_dsize; | ||
457 | 454 | ||
458 | /* Don't export sysctls to unprivileged users */ | 455 | /* Don't export sysctls to unprivileged users */ |
459 | if (net->user_ns != &init_user_ns) | 456 | if (net->user_ns != &init_user_ns) |
@@ -528,7 +525,6 @@ static int __net_init lowpan_frags_init_net(struct net *net) | |||
528 | ieee802154_lowpan->frags.high_thresh = IPV6_FRAG_HIGH_THRESH; | 525 | ieee802154_lowpan->frags.high_thresh = IPV6_FRAG_HIGH_THRESH; |
529 | ieee802154_lowpan->frags.low_thresh = IPV6_FRAG_LOW_THRESH; | 526 | ieee802154_lowpan->frags.low_thresh = IPV6_FRAG_LOW_THRESH; |
530 | ieee802154_lowpan->frags.timeout = IPV6_FRAG_TIMEOUT; | 527 | ieee802154_lowpan->frags.timeout = IPV6_FRAG_TIMEOUT; |
531 | ieee802154_lowpan->max_dsize = 0xFFFF; | ||
532 | 528 | ||
533 | inet_frags_init_net(&ieee802154_lowpan->frags); | 529 | inet_frags_init_net(&ieee802154_lowpan->frags); |
534 | 530 | ||
@@ -568,8 +564,10 @@ int __init lowpan_net_frag_init(void) | |||
568 | lowpan_frags.qsize = sizeof(struct frag_queue); | 564 | lowpan_frags.qsize = sizeof(struct frag_queue); |
569 | lowpan_frags.match = lowpan_frag_match; | 565 | lowpan_frags.match = lowpan_frag_match; |
570 | lowpan_frags.frag_expire = lowpan_frag_expire; | 566 | lowpan_frags.frag_expire = lowpan_frag_expire; |
571 | lowpan_frags.secret_interval = 10 * 60 * HZ; | 567 | lowpan_frags.frags_cache_name = lowpan_frags_cache_name; |
572 | inet_frags_init(&lowpan_frags); | 568 | ret = inet_frags_init(&lowpan_frags); |
569 | if (ret) | ||
570 | goto err_pernet; | ||
573 | 571 | ||
574 | return ret; | 572 | return ret; |
575 | err_pernet: | 573 | err_pernet: |
diff --git a/net/ieee802154/wpan-class.c b/net/ieee802154/wpan-class.c index 8d6f6704da84..4955e0fe5883 100644 --- a/net/ieee802154/wpan-class.c +++ b/net/ieee802154/wpan-class.c | |||
@@ -48,7 +48,8 @@ MASTER_SHOW(transmit_power, "%d +- 1 dB"); | |||
48 | MASTER_SHOW(cca_mode, "%d"); | 48 | MASTER_SHOW(cca_mode, "%d"); |
49 | 49 | ||
50 | static ssize_t channels_supported_show(struct device *dev, | 50 | static ssize_t channels_supported_show(struct device *dev, |
51 | struct device_attribute *attr, char *buf) | 51 | struct device_attribute *attr, |
52 | char *buf) | ||
52 | { | 53 | { |
53 | struct wpan_phy *phy = container_of(dev, struct wpan_phy, dev); | 54 | struct wpan_phy *phy = container_of(dev, struct wpan_phy, dev); |
54 | int ret; | 55 | int ret; |
@@ -57,7 +58,7 @@ static ssize_t channels_supported_show(struct device *dev, | |||
57 | mutex_lock(&phy->pib_lock); | 58 | mutex_lock(&phy->pib_lock); |
58 | for (i = 0; i < 32; i++) { | 59 | for (i = 0; i < 32; i++) { |
59 | ret = snprintf(buf + len, PAGE_SIZE - len, | 60 | ret = snprintf(buf + len, PAGE_SIZE - len, |
60 | "%#09x\n", phy->channels_supported[i]); | 61 | "%#09x\n", phy->channels_supported[i]); |
61 | if (ret < 0) | 62 | if (ret < 0) |
62 | break; | 63 | break; |
63 | len += ret; | 64 | len += ret; |
@@ -80,6 +81,7 @@ ATTRIBUTE_GROUPS(pmib); | |||
80 | static void wpan_phy_release(struct device *d) | 81 | static void wpan_phy_release(struct device *d) |
81 | { | 82 | { |
82 | struct wpan_phy *phy = container_of(d, struct wpan_phy, dev); | 83 | struct wpan_phy *phy = container_of(d, struct wpan_phy, dev); |
84 | |||
83 | kfree(phy); | 85 | kfree(phy); |
84 | } | 86 | } |
85 | 87 | ||
@@ -121,11 +123,12 @@ static int wpan_phy_iter(struct device *dev, void *_data) | |||
121 | { | 123 | { |
122 | struct wpan_phy_iter_data *wpid = _data; | 124 | struct wpan_phy_iter_data *wpid = _data; |
123 | struct wpan_phy *phy = container_of(dev, struct wpan_phy, dev); | 125 | struct wpan_phy *phy = container_of(dev, struct wpan_phy, dev); |
126 | |||
124 | return wpid->fn(phy, wpid->data); | 127 | return wpid->fn(phy, wpid->data); |
125 | } | 128 | } |
126 | 129 | ||
127 | int wpan_phy_for_each(int (*fn)(struct wpan_phy *phy, void *data), | 130 | int wpan_phy_for_each(int (*fn)(struct wpan_phy *phy, void *data), |
128 | void *data) | 131 | void *data) |
129 | { | 132 | { |
130 | struct wpan_phy_iter_data wpid = { | 133 | struct wpan_phy_iter_data wpid = { |
131 | .fn = fn, | 134 | .fn = fn, |
@@ -197,6 +200,7 @@ EXPORT_SYMBOL(wpan_phy_free); | |||
197 | static int __init wpan_phy_class_init(void) | 200 | static int __init wpan_phy_class_init(void) |
198 | { | 201 | { |
199 | int rc; | 202 | int rc; |
203 | |||
200 | rc = class_register(&wpan_phy_class); | 204 | rc = class_register(&wpan_phy_class); |
201 | if (rc) | 205 | if (rc) |
202 | goto err; | 206 | goto err; |
diff --git a/net/ipv4/Kconfig b/net/ipv4/Kconfig index 05c57f0fcabe..dbc10d84161f 100644 --- a/net/ipv4/Kconfig +++ b/net/ipv4/Kconfig | |||
@@ -307,6 +307,10 @@ config NET_IPVTI | |||
307 | the notion of a secure tunnel for IPSEC and then use routing protocol | 307 | the notion of a secure tunnel for IPSEC and then use routing protocol |
308 | on top. | 308 | on top. |
309 | 309 | ||
310 | config NET_UDP_TUNNEL | ||
311 | tristate | ||
312 | default n | ||
313 | |||
310 | config INET_AH | 314 | config INET_AH |
311 | tristate "IP: AH transformation" | 315 | tristate "IP: AH transformation" |
312 | select XFRM_ALGO | 316 | select XFRM_ALGO |
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile index f032688d20d3..8ee1cd4053ee 100644 --- a/net/ipv4/Makefile +++ b/net/ipv4/Makefile | |||
@@ -22,6 +22,7 @@ obj-$(CONFIG_NET_IPIP) += ipip.o | |||
22 | gre-y := gre_demux.o | 22 | gre-y := gre_demux.o |
23 | obj-$(CONFIG_NET_IPGRE_DEMUX) += gre.o | 23 | obj-$(CONFIG_NET_IPGRE_DEMUX) += gre.o |
24 | obj-$(CONFIG_NET_IPGRE) += ip_gre.o | 24 | obj-$(CONFIG_NET_IPGRE) += ip_gre.o |
25 | obj-$(CONFIG_NET_UDP_TUNNEL) += udp_tunnel.o | ||
25 | obj-$(CONFIG_NET_IPVTI) += ip_vti.o | 26 | obj-$(CONFIG_NET_IPVTI) += ip_vti.o |
26 | obj-$(CONFIG_SYN_COOKIES) += syncookies.o | 27 | obj-$(CONFIG_SYN_COOKIES) += syncookies.o |
27 | obj-$(CONFIG_INET_AH) += ah4.o | 28 | obj-$(CONFIG_INET_AH) += ah4.o |
diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c index a3095fdefbed..90c0e8386116 100644 --- a/net/ipv4/datagram.c +++ b/net/ipv4/datagram.c | |||
@@ -76,6 +76,7 @@ int ip4_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
76 | inet->inet_daddr = fl4->daddr; | 76 | inet->inet_daddr = fl4->daddr; |
77 | inet->inet_dport = usin->sin_port; | 77 | inet->inet_dport = usin->sin_port; |
78 | sk->sk_state = TCP_ESTABLISHED; | 78 | sk->sk_state = TCP_ESTABLISHED; |
79 | inet_set_txhash(sk); | ||
79 | inet->inet_id = jiffies; | 80 | inet->inet_id = jiffies; |
80 | 81 | ||
81 | sk_dst_set(sk, &rt->dst); | 82 | sk_dst_set(sk, &rt->dst); |
diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index e9449376b58e..214882e7d6de 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c | |||
@@ -180,11 +180,12 @@ static BLOCKING_NOTIFIER_HEAD(inetaddr_chain); | |||
180 | static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, | 180 | static void inet_del_ifa(struct in_device *in_dev, struct in_ifaddr **ifap, |
181 | int destroy); | 181 | int destroy); |
182 | #ifdef CONFIG_SYSCTL | 182 | #ifdef CONFIG_SYSCTL |
183 | static void devinet_sysctl_register(struct in_device *idev); | 183 | static int devinet_sysctl_register(struct in_device *idev); |
184 | static void devinet_sysctl_unregister(struct in_device *idev); | 184 | static void devinet_sysctl_unregister(struct in_device *idev); |
185 | #else | 185 | #else |
186 | static void devinet_sysctl_register(struct in_device *idev) | 186 | static int devinet_sysctl_register(struct in_device *idev) |
187 | { | 187 | { |
188 | return 0; | ||
188 | } | 189 | } |
189 | static void devinet_sysctl_unregister(struct in_device *idev) | 190 | static void devinet_sysctl_unregister(struct in_device *idev) |
190 | { | 191 | { |
@@ -232,6 +233,7 @@ EXPORT_SYMBOL(in_dev_finish_destroy); | |||
232 | static struct in_device *inetdev_init(struct net_device *dev) | 233 | static struct in_device *inetdev_init(struct net_device *dev) |
233 | { | 234 | { |
234 | struct in_device *in_dev; | 235 | struct in_device *in_dev; |
236 | int err = -ENOMEM; | ||
235 | 237 | ||
236 | ASSERT_RTNL(); | 238 | ASSERT_RTNL(); |
237 | 239 | ||
@@ -252,7 +254,13 @@ static struct in_device *inetdev_init(struct net_device *dev) | |||
252 | /* Account for reference dev->ip_ptr (below) */ | 254 | /* Account for reference dev->ip_ptr (below) */ |
253 | in_dev_hold(in_dev); | 255 | in_dev_hold(in_dev); |
254 | 256 | ||
255 | devinet_sysctl_register(in_dev); | 257 | err = devinet_sysctl_register(in_dev); |
258 | if (err) { | ||
259 | in_dev->dead = 1; | ||
260 | in_dev_put(in_dev); | ||
261 | in_dev = NULL; | ||
262 | goto out; | ||
263 | } | ||
256 | ip_mc_init_dev(in_dev); | 264 | ip_mc_init_dev(in_dev); |
257 | if (dev->flags & IFF_UP) | 265 | if (dev->flags & IFF_UP) |
258 | ip_mc_up(in_dev); | 266 | ip_mc_up(in_dev); |
@@ -260,7 +268,7 @@ static struct in_device *inetdev_init(struct net_device *dev) | |||
260 | /* we can receive as soon as ip_ptr is set -- do this last */ | 268 | /* we can receive as soon as ip_ptr is set -- do this last */ |
261 | rcu_assign_pointer(dev->ip_ptr, in_dev); | 269 | rcu_assign_pointer(dev->ip_ptr, in_dev); |
262 | out: | 270 | out: |
263 | return in_dev; | 271 | return in_dev ?: ERR_PTR(err); |
264 | out_kfree: | 272 | out_kfree: |
265 | kfree(in_dev); | 273 | kfree(in_dev); |
266 | in_dev = NULL; | 274 | in_dev = NULL; |
@@ -1347,8 +1355,8 @@ static int inetdev_event(struct notifier_block *this, unsigned long event, | |||
1347 | if (!in_dev) { | 1355 | if (!in_dev) { |
1348 | if (event == NETDEV_REGISTER) { | 1356 | if (event == NETDEV_REGISTER) { |
1349 | in_dev = inetdev_init(dev); | 1357 | in_dev = inetdev_init(dev); |
1350 | if (!in_dev) | 1358 | if (IS_ERR(in_dev)) |
1351 | return notifier_from_errno(-ENOMEM); | 1359 | return notifier_from_errno(PTR_ERR(in_dev)); |
1352 | if (dev->flags & IFF_LOOPBACK) { | 1360 | if (dev->flags & IFF_LOOPBACK) { |
1353 | IN_DEV_CONF_SET(in_dev, NOXFRM, 1); | 1361 | IN_DEV_CONF_SET(in_dev, NOXFRM, 1); |
1354 | IN_DEV_CONF_SET(in_dev, NOPOLICY, 1); | 1362 | IN_DEV_CONF_SET(in_dev, NOPOLICY, 1); |
@@ -2182,11 +2190,21 @@ static void __devinet_sysctl_unregister(struct ipv4_devconf *cnf) | |||
2182 | kfree(t); | 2190 | kfree(t); |
2183 | } | 2191 | } |
2184 | 2192 | ||
2185 | static void devinet_sysctl_register(struct in_device *idev) | 2193 | static int devinet_sysctl_register(struct in_device *idev) |
2186 | { | 2194 | { |
2187 | neigh_sysctl_register(idev->dev, idev->arp_parms, NULL); | 2195 | int err; |
2188 | __devinet_sysctl_register(dev_net(idev->dev), idev->dev->name, | 2196 | |
2197 | if (!sysctl_dev_name_is_allowed(idev->dev->name)) | ||
2198 | return -EINVAL; | ||
2199 | |||
2200 | err = neigh_sysctl_register(idev->dev, idev->arp_parms, NULL); | ||
2201 | if (err) | ||
2202 | return err; | ||
2203 | err = __devinet_sysctl_register(dev_net(idev->dev), idev->dev->name, | ||
2189 | &idev->cnf); | 2204 | &idev->cnf); |
2205 | if (err) | ||
2206 | neigh_sysctl_unregister(idev->arp_parms); | ||
2207 | return err; | ||
2190 | } | 2208 | } |
2191 | 2209 | ||
2192 | static void devinet_sysctl_unregister(struct in_device *idev) | 2210 | static void devinet_sysctl_unregister(struct in_device *idev) |
diff --git a/net/ipv4/fib_trie.c b/net/ipv4/fib_trie.c index 5afeb5aa4c7c..e9cb2588e416 100644 --- a/net/ipv4/fib_trie.c +++ b/net/ipv4/fib_trie.c | |||
@@ -940,7 +940,7 @@ static void insert_leaf_info(struct hlist_head *head, struct leaf_info *new) | |||
940 | last = li; | 940 | last = li; |
941 | } | 941 | } |
942 | if (last) | 942 | if (last) |
943 | hlist_add_after_rcu(&last->hlist, &new->hlist); | 943 | hlist_add_behind_rcu(&new->hlist, &last->hlist); |
944 | else | 944 | else |
945 | hlist_add_before_rcu(&new->hlist, &li->hlist); | 945 | hlist_add_before_rcu(&new->hlist, &li->hlist); |
946 | } | 946 | } |
diff --git a/net/ipv4/gre_offload.c b/net/ipv4/gre_offload.c index f0bdd47bbbcb..6556263c8fa5 100644 --- a/net/ipv4/gre_offload.c +++ b/net/ipv4/gre_offload.c | |||
@@ -74,7 +74,7 @@ static struct sk_buff *gre_gso_segment(struct sk_buff *skb, | |||
74 | /* segment inner packet. */ | 74 | /* segment inner packet. */ |
75 | enc_features = skb->dev->hw_enc_features & netif_skb_features(skb); | 75 | enc_features = skb->dev->hw_enc_features & netif_skb_features(skb); |
76 | segs = skb_mac_gso_segment(skb, enc_features); | 76 | segs = skb_mac_gso_segment(skb, enc_features); |
77 | if (!segs || IS_ERR(segs)) { | 77 | if (IS_ERR_OR_NULL(segs)) { |
78 | skb_gso_error_unwind(skb, protocol, ghl, mac_offset, mac_len); | 78 | skb_gso_error_unwind(skb, protocol, ghl, mac_offset, mac_len); |
79 | goto out; | 79 | goto out; |
80 | } | 80 | } |
diff --git a/net/ipv4/icmp.c b/net/ipv4/icmp.c index 42b7bcf8045b..ea7d4afe8205 100644 --- a/net/ipv4/icmp.c +++ b/net/ipv4/icmp.c | |||
@@ -663,16 +663,16 @@ static void icmp_socket_deliver(struct sk_buff *skb, u32 info) | |||
663 | /* Checkin full IP header plus 8 bytes of protocol to | 663 | /* Checkin full IP header plus 8 bytes of protocol to |
664 | * avoid additional coding at protocol handlers. | 664 | * avoid additional coding at protocol handlers. |
665 | */ | 665 | */ |
666 | if (!pskb_may_pull(skb, iph->ihl * 4 + 8)) | 666 | if (!pskb_may_pull(skb, iph->ihl * 4 + 8)) { |
667 | ICMP_INC_STATS_BH(dev_net(skb->dev), ICMP_MIB_INERRORS); | ||
667 | return; | 668 | return; |
669 | } | ||
668 | 670 | ||
669 | raw_icmp_error(skb, protocol, info); | 671 | raw_icmp_error(skb, protocol, info); |
670 | 672 | ||
671 | rcu_read_lock(); | ||
672 | ipprot = rcu_dereference(inet_protos[protocol]); | 673 | ipprot = rcu_dereference(inet_protos[protocol]); |
673 | if (ipprot && ipprot->err_handler) | 674 | if (ipprot && ipprot->err_handler) |
674 | ipprot->err_handler(skb, info); | 675 | ipprot->err_handler(skb, info); |
675 | rcu_read_unlock(); | ||
676 | } | 676 | } |
677 | 677 | ||
678 | static bool icmp_tag_validation(int proto) | 678 | static bool icmp_tag_validation(int proto) |
diff --git a/net/ipv4/igmp.c b/net/ipv4/igmp.c index db710b059bab..f10eab462282 100644 --- a/net/ipv4/igmp.c +++ b/net/ipv4/igmp.c | |||
@@ -1321,7 +1321,7 @@ void ip_mc_inc_group(struct in_device *in_dev, __be32 addr) | |||
1321 | atomic_set(&im->refcnt, 1); | 1321 | atomic_set(&im->refcnt, 1); |
1322 | spin_lock_init(&im->lock); | 1322 | spin_lock_init(&im->lock); |
1323 | #ifdef CONFIG_IP_MULTICAST | 1323 | #ifdef CONFIG_IP_MULTICAST |
1324 | setup_timer(&im->timer, &igmp_timer_expire, (unsigned long)im); | 1324 | setup_timer(&im->timer, igmp_timer_expire, (unsigned long)im); |
1325 | im->unsolicit_count = IGMP_Unsolicited_Report_Count; | 1325 | im->unsolicit_count = IGMP_Unsolicited_Report_Count; |
1326 | #endif | 1326 | #endif |
1327 | 1327 | ||
diff --git a/net/ipv4/inet_fragment.c b/net/ipv4/inet_fragment.c index 3b01959bf4bb..9eb89f3f0ee4 100644 --- a/net/ipv4/inet_fragment.c +++ b/net/ipv4/inet_fragment.c | |||
@@ -25,6 +25,12 @@ | |||
25 | #include <net/inet_frag.h> | 25 | #include <net/inet_frag.h> |
26 | #include <net/inet_ecn.h> | 26 | #include <net/inet_ecn.h> |
27 | 27 | ||
28 | #define INETFRAGS_EVICT_BUCKETS 128 | ||
29 | #define INETFRAGS_EVICT_MAX 512 | ||
30 | |||
31 | /* don't rebuild inetfrag table with new secret more often than this */ | ||
32 | #define INETFRAGS_MIN_REBUILD_INTERVAL (5 * HZ) | ||
33 | |||
28 | /* Given the OR values of all fragments, apply RFC 3168 5.3 requirements | 34 | /* Given the OR values of all fragments, apply RFC 3168 5.3 requirements |
29 | * Value : 0xff if frame should be dropped. | 35 | * Value : 0xff if frame should be dropped. |
30 | * 0 or INET_ECN_CE value, to be ORed in to final iph->tos field | 36 | * 0 or INET_ECN_CE value, to be ORed in to final iph->tos field |
@@ -46,24 +52,39 @@ const u8 ip_frag_ecn_table[16] = { | |||
46 | }; | 52 | }; |
47 | EXPORT_SYMBOL(ip_frag_ecn_table); | 53 | EXPORT_SYMBOL(ip_frag_ecn_table); |
48 | 54 | ||
49 | static void inet_frag_secret_rebuild(unsigned long dummy) | 55 | static unsigned int |
56 | inet_frag_hashfn(const struct inet_frags *f, const struct inet_frag_queue *q) | ||
57 | { | ||
58 | return f->hashfn(q) & (INETFRAGS_HASHSZ - 1); | ||
59 | } | ||
60 | |||
61 | static bool inet_frag_may_rebuild(struct inet_frags *f) | ||
62 | { | ||
63 | return time_after(jiffies, | ||
64 | f->last_rebuild_jiffies + INETFRAGS_MIN_REBUILD_INTERVAL); | ||
65 | } | ||
66 | |||
67 | static void inet_frag_secret_rebuild(struct inet_frags *f) | ||
50 | { | 68 | { |
51 | struct inet_frags *f = (struct inet_frags *)dummy; | ||
52 | unsigned long now = jiffies; | ||
53 | int i; | 69 | int i; |
54 | 70 | ||
55 | /* Per bucket lock NOT needed here, due to write lock protection */ | 71 | write_seqlock_bh(&f->rnd_seqlock); |
56 | write_lock(&f->lock); | 72 | |
73 | if (!inet_frag_may_rebuild(f)) | ||
74 | goto out; | ||
57 | 75 | ||
58 | get_random_bytes(&f->rnd, sizeof(u32)); | 76 | get_random_bytes(&f->rnd, sizeof(u32)); |
77 | |||
59 | for (i = 0; i < INETFRAGS_HASHSZ; i++) { | 78 | for (i = 0; i < INETFRAGS_HASHSZ; i++) { |
60 | struct inet_frag_bucket *hb; | 79 | struct inet_frag_bucket *hb; |
61 | struct inet_frag_queue *q; | 80 | struct inet_frag_queue *q; |
62 | struct hlist_node *n; | 81 | struct hlist_node *n; |
63 | 82 | ||
64 | hb = &f->hash[i]; | 83 | hb = &f->hash[i]; |
84 | spin_lock(&hb->chain_lock); | ||
85 | |||
65 | hlist_for_each_entry_safe(q, n, &hb->chain, list) { | 86 | hlist_for_each_entry_safe(q, n, &hb->chain, list) { |
66 | unsigned int hval = f->hashfn(q); | 87 | unsigned int hval = inet_frag_hashfn(f, q); |
67 | 88 | ||
68 | if (hval != i) { | 89 | if (hval != i) { |
69 | struct inet_frag_bucket *hb_dest; | 90 | struct inet_frag_bucket *hb_dest; |
@@ -72,76 +93,200 @@ static void inet_frag_secret_rebuild(unsigned long dummy) | |||
72 | 93 | ||
73 | /* Relink to new hash chain. */ | 94 | /* Relink to new hash chain. */ |
74 | hb_dest = &f->hash[hval]; | 95 | hb_dest = &f->hash[hval]; |
96 | |||
97 | /* This is the only place where we take | ||
98 | * another chain_lock while already holding | ||
99 | * one. As this will not run concurrently, | ||
100 | * we cannot deadlock on hb_dest lock below, if its | ||
101 | * already locked it will be released soon since | ||
102 | * other caller cannot be waiting for hb lock | ||
103 | * that we've taken above. | ||
104 | */ | ||
105 | spin_lock_nested(&hb_dest->chain_lock, | ||
106 | SINGLE_DEPTH_NESTING); | ||
75 | hlist_add_head(&q->list, &hb_dest->chain); | 107 | hlist_add_head(&q->list, &hb_dest->chain); |
108 | spin_unlock(&hb_dest->chain_lock); | ||
76 | } | 109 | } |
77 | } | 110 | } |
111 | spin_unlock(&hb->chain_lock); | ||
112 | } | ||
113 | |||
114 | f->rebuild = false; | ||
115 | f->last_rebuild_jiffies = jiffies; | ||
116 | out: | ||
117 | write_sequnlock_bh(&f->rnd_seqlock); | ||
118 | } | ||
119 | |||
120 | static bool inet_fragq_should_evict(const struct inet_frag_queue *q) | ||
121 | { | ||
122 | return q->net->low_thresh == 0 || | ||
123 | frag_mem_limit(q->net) >= q->net->low_thresh; | ||
124 | } | ||
125 | |||
126 | static unsigned int | ||
127 | inet_evict_bucket(struct inet_frags *f, struct inet_frag_bucket *hb) | ||
128 | { | ||
129 | struct inet_frag_queue *fq; | ||
130 | struct hlist_node *n; | ||
131 | unsigned int evicted = 0; | ||
132 | HLIST_HEAD(expired); | ||
133 | |||
134 | evict_again: | ||
135 | spin_lock(&hb->chain_lock); | ||
136 | |||
137 | hlist_for_each_entry_safe(fq, n, &hb->chain, list) { | ||
138 | if (!inet_fragq_should_evict(fq)) | ||
139 | continue; | ||
140 | |||
141 | if (!del_timer(&fq->timer)) { | ||
142 | /* q expiring right now thus increment its refcount so | ||
143 | * it won't be freed under us and wait until the timer | ||
144 | * has finished executing then destroy it | ||
145 | */ | ||
146 | atomic_inc(&fq->refcnt); | ||
147 | spin_unlock(&hb->chain_lock); | ||
148 | del_timer_sync(&fq->timer); | ||
149 | WARN_ON(atomic_read(&fq->refcnt) != 1); | ||
150 | inet_frag_put(fq, f); | ||
151 | goto evict_again; | ||
152 | } | ||
153 | |||
154 | fq->flags |= INET_FRAG_EVICTED; | ||
155 | hlist_del(&fq->list); | ||
156 | hlist_add_head(&fq->list, &expired); | ||
157 | ++evicted; | ||
78 | } | 158 | } |
79 | write_unlock(&f->lock); | ||
80 | 159 | ||
81 | mod_timer(&f->secret_timer, now + f->secret_interval); | 160 | spin_unlock(&hb->chain_lock); |
161 | |||
162 | hlist_for_each_entry_safe(fq, n, &expired, list) | ||
163 | f->frag_expire((unsigned long) fq); | ||
164 | |||
165 | return evicted; | ||
82 | } | 166 | } |
83 | 167 | ||
84 | void inet_frags_init(struct inet_frags *f) | 168 | static void inet_frag_worker(struct work_struct *work) |
169 | { | ||
170 | unsigned int budget = INETFRAGS_EVICT_BUCKETS; | ||
171 | unsigned int i, evicted = 0; | ||
172 | struct inet_frags *f; | ||
173 | |||
174 | f = container_of(work, struct inet_frags, frags_work); | ||
175 | |||
176 | BUILD_BUG_ON(INETFRAGS_EVICT_BUCKETS >= INETFRAGS_HASHSZ); | ||
177 | |||
178 | local_bh_disable(); | ||
179 | |||
180 | for (i = ACCESS_ONCE(f->next_bucket); budget; --budget) { | ||
181 | evicted += inet_evict_bucket(f, &f->hash[i]); | ||
182 | i = (i + 1) & (INETFRAGS_HASHSZ - 1); | ||
183 | if (evicted > INETFRAGS_EVICT_MAX) | ||
184 | break; | ||
185 | } | ||
186 | |||
187 | f->next_bucket = i; | ||
188 | |||
189 | local_bh_enable(); | ||
190 | |||
191 | if (f->rebuild && inet_frag_may_rebuild(f)) | ||
192 | inet_frag_secret_rebuild(f); | ||
193 | } | ||
194 | |||
195 | static void inet_frag_schedule_worker(struct inet_frags *f) | ||
196 | { | ||
197 | if (unlikely(!work_pending(&f->frags_work))) | ||
198 | schedule_work(&f->frags_work); | ||
199 | } | ||
200 | |||
201 | int inet_frags_init(struct inet_frags *f) | ||
85 | { | 202 | { |
86 | int i; | 203 | int i; |
87 | 204 | ||
205 | INIT_WORK(&f->frags_work, inet_frag_worker); | ||
206 | |||
88 | for (i = 0; i < INETFRAGS_HASHSZ; i++) { | 207 | for (i = 0; i < INETFRAGS_HASHSZ; i++) { |
89 | struct inet_frag_bucket *hb = &f->hash[i]; | 208 | struct inet_frag_bucket *hb = &f->hash[i]; |
90 | 209 | ||
91 | spin_lock_init(&hb->chain_lock); | 210 | spin_lock_init(&hb->chain_lock); |
92 | INIT_HLIST_HEAD(&hb->chain); | 211 | INIT_HLIST_HEAD(&hb->chain); |
93 | } | 212 | } |
94 | rwlock_init(&f->lock); | ||
95 | 213 | ||
96 | setup_timer(&f->secret_timer, inet_frag_secret_rebuild, | 214 | seqlock_init(&f->rnd_seqlock); |
97 | (unsigned long)f); | 215 | f->last_rebuild_jiffies = 0; |
98 | f->secret_timer.expires = jiffies + f->secret_interval; | 216 | f->frags_cachep = kmem_cache_create(f->frags_cache_name, f->qsize, 0, 0, |
99 | add_timer(&f->secret_timer); | 217 | NULL); |
218 | if (!f->frags_cachep) | ||
219 | return -ENOMEM; | ||
220 | |||
221 | return 0; | ||
100 | } | 222 | } |
101 | EXPORT_SYMBOL(inet_frags_init); | 223 | EXPORT_SYMBOL(inet_frags_init); |
102 | 224 | ||
103 | void inet_frags_init_net(struct netns_frags *nf) | 225 | void inet_frags_init_net(struct netns_frags *nf) |
104 | { | 226 | { |
105 | nf->nqueues = 0; | ||
106 | init_frag_mem_limit(nf); | 227 | init_frag_mem_limit(nf); |
107 | INIT_LIST_HEAD(&nf->lru_list); | ||
108 | spin_lock_init(&nf->lru_lock); | ||
109 | } | 228 | } |
110 | EXPORT_SYMBOL(inet_frags_init_net); | 229 | EXPORT_SYMBOL(inet_frags_init_net); |
111 | 230 | ||
112 | void inet_frags_fini(struct inet_frags *f) | 231 | void inet_frags_fini(struct inet_frags *f) |
113 | { | 232 | { |
114 | del_timer(&f->secret_timer); | 233 | cancel_work_sync(&f->frags_work); |
234 | kmem_cache_destroy(f->frags_cachep); | ||
115 | } | 235 | } |
116 | EXPORT_SYMBOL(inet_frags_fini); | 236 | EXPORT_SYMBOL(inet_frags_fini); |
117 | 237 | ||
118 | void inet_frags_exit_net(struct netns_frags *nf, struct inet_frags *f) | 238 | void inet_frags_exit_net(struct netns_frags *nf, struct inet_frags *f) |
119 | { | 239 | { |
120 | nf->low_thresh = 0; | 240 | unsigned int seq; |
241 | int i; | ||
121 | 242 | ||
243 | nf->low_thresh = 0; | ||
122 | local_bh_disable(); | 244 | local_bh_disable(); |
123 | inet_frag_evictor(nf, f, true); | 245 | |
246 | evict_again: | ||
247 | seq = read_seqbegin(&f->rnd_seqlock); | ||
248 | |||
249 | for (i = 0; i < INETFRAGS_HASHSZ ; i++) | ||
250 | inet_evict_bucket(f, &f->hash[i]); | ||
251 | |||
252 | if (read_seqretry(&f->rnd_seqlock, seq)) | ||
253 | goto evict_again; | ||
254 | |||
124 | local_bh_enable(); | 255 | local_bh_enable(); |
125 | 256 | ||
126 | percpu_counter_destroy(&nf->mem); | 257 | percpu_counter_destroy(&nf->mem); |
127 | } | 258 | } |
128 | EXPORT_SYMBOL(inet_frags_exit_net); | 259 | EXPORT_SYMBOL(inet_frags_exit_net); |
129 | 260 | ||
130 | static inline void fq_unlink(struct inet_frag_queue *fq, struct inet_frags *f) | 261 | static struct inet_frag_bucket * |
262 | get_frag_bucket_locked(struct inet_frag_queue *fq, struct inet_frags *f) | ||
263 | __acquires(hb->chain_lock) | ||
131 | { | 264 | { |
132 | struct inet_frag_bucket *hb; | 265 | struct inet_frag_bucket *hb; |
133 | unsigned int hash; | 266 | unsigned int seq, hash; |
267 | |||
268 | restart: | ||
269 | seq = read_seqbegin(&f->rnd_seqlock); | ||
134 | 270 | ||
135 | read_lock(&f->lock); | 271 | hash = inet_frag_hashfn(f, fq); |
136 | hash = f->hashfn(fq); | ||
137 | hb = &f->hash[hash]; | 272 | hb = &f->hash[hash]; |
138 | 273 | ||
139 | spin_lock(&hb->chain_lock); | 274 | spin_lock(&hb->chain_lock); |
275 | if (read_seqretry(&f->rnd_seqlock, seq)) { | ||
276 | spin_unlock(&hb->chain_lock); | ||
277 | goto restart; | ||
278 | } | ||
279 | |||
280 | return hb; | ||
281 | } | ||
282 | |||
283 | static inline void fq_unlink(struct inet_frag_queue *fq, struct inet_frags *f) | ||
284 | { | ||
285 | struct inet_frag_bucket *hb; | ||
286 | |||
287 | hb = get_frag_bucket_locked(fq, f); | ||
140 | hlist_del(&fq->list); | 288 | hlist_del(&fq->list); |
141 | spin_unlock(&hb->chain_lock); | 289 | spin_unlock(&hb->chain_lock); |
142 | |||
143 | read_unlock(&f->lock); | ||
144 | inet_frag_lru_del(fq); | ||
145 | } | 290 | } |
146 | 291 | ||
147 | void inet_frag_kill(struct inet_frag_queue *fq, struct inet_frags *f) | 292 | void inet_frag_kill(struct inet_frag_queue *fq, struct inet_frags *f) |
@@ -149,30 +294,29 @@ void inet_frag_kill(struct inet_frag_queue *fq, struct inet_frags *f) | |||
149 | if (del_timer(&fq->timer)) | 294 | if (del_timer(&fq->timer)) |
150 | atomic_dec(&fq->refcnt); | 295 | atomic_dec(&fq->refcnt); |
151 | 296 | ||
152 | if (!(fq->last_in & INET_FRAG_COMPLETE)) { | 297 | if (!(fq->flags & INET_FRAG_COMPLETE)) { |
153 | fq_unlink(fq, f); | 298 | fq_unlink(fq, f); |
154 | atomic_dec(&fq->refcnt); | 299 | atomic_dec(&fq->refcnt); |
155 | fq->last_in |= INET_FRAG_COMPLETE; | 300 | fq->flags |= INET_FRAG_COMPLETE; |
156 | } | 301 | } |
157 | } | 302 | } |
158 | EXPORT_SYMBOL(inet_frag_kill); | 303 | EXPORT_SYMBOL(inet_frag_kill); |
159 | 304 | ||
160 | static inline void frag_kfree_skb(struct netns_frags *nf, struct inet_frags *f, | 305 | static inline void frag_kfree_skb(struct netns_frags *nf, struct inet_frags *f, |
161 | struct sk_buff *skb) | 306 | struct sk_buff *skb) |
162 | { | 307 | { |
163 | if (f->skb_free) | 308 | if (f->skb_free) |
164 | f->skb_free(skb); | 309 | f->skb_free(skb); |
165 | kfree_skb(skb); | 310 | kfree_skb(skb); |
166 | } | 311 | } |
167 | 312 | ||
168 | void inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f, | 313 | void inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f) |
169 | int *work) | ||
170 | { | 314 | { |
171 | struct sk_buff *fp; | 315 | struct sk_buff *fp; |
172 | struct netns_frags *nf; | 316 | struct netns_frags *nf; |
173 | unsigned int sum, sum_truesize = 0; | 317 | unsigned int sum, sum_truesize = 0; |
174 | 318 | ||
175 | WARN_ON(!(q->last_in & INET_FRAG_COMPLETE)); | 319 | WARN_ON(!(q->flags & INET_FRAG_COMPLETE)); |
176 | WARN_ON(del_timer(&q->timer) != 0); | 320 | WARN_ON(del_timer(&q->timer) != 0); |
177 | 321 | ||
178 | /* Release all fragment data. */ | 322 | /* Release all fragment data. */ |
@@ -186,87 +330,32 @@ void inet_frag_destroy(struct inet_frag_queue *q, struct inet_frags *f, | |||
186 | fp = xp; | 330 | fp = xp; |
187 | } | 331 | } |
188 | sum = sum_truesize + f->qsize; | 332 | sum = sum_truesize + f->qsize; |
189 | if (work) | ||
190 | *work -= sum; | ||
191 | sub_frag_mem_limit(q, sum); | 333 | sub_frag_mem_limit(q, sum); |
192 | 334 | ||
193 | if (f->destructor) | 335 | if (f->destructor) |
194 | f->destructor(q); | 336 | f->destructor(q); |
195 | kfree(q); | 337 | kmem_cache_free(f->frags_cachep, q); |
196 | |||
197 | } | 338 | } |
198 | EXPORT_SYMBOL(inet_frag_destroy); | 339 | EXPORT_SYMBOL(inet_frag_destroy); |
199 | 340 | ||
200 | int inet_frag_evictor(struct netns_frags *nf, struct inet_frags *f, bool force) | ||
201 | { | ||
202 | struct inet_frag_queue *q; | ||
203 | int work, evicted = 0; | ||
204 | |||
205 | if (!force) { | ||
206 | if (frag_mem_limit(nf) <= nf->high_thresh) | ||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | work = frag_mem_limit(nf) - nf->low_thresh; | ||
211 | while (work > 0 || force) { | ||
212 | spin_lock(&nf->lru_lock); | ||
213 | |||
214 | if (list_empty(&nf->lru_list)) { | ||
215 | spin_unlock(&nf->lru_lock); | ||
216 | break; | ||
217 | } | ||
218 | |||
219 | q = list_first_entry(&nf->lru_list, | ||
220 | struct inet_frag_queue, lru_list); | ||
221 | atomic_inc(&q->refcnt); | ||
222 | /* Remove q from list to avoid several CPUs grabbing it */ | ||
223 | list_del_init(&q->lru_list); | ||
224 | |||
225 | spin_unlock(&nf->lru_lock); | ||
226 | |||
227 | spin_lock(&q->lock); | ||
228 | if (!(q->last_in & INET_FRAG_COMPLETE)) | ||
229 | inet_frag_kill(q, f); | ||
230 | spin_unlock(&q->lock); | ||
231 | |||
232 | if (atomic_dec_and_test(&q->refcnt)) | ||
233 | inet_frag_destroy(q, f, &work); | ||
234 | evicted++; | ||
235 | } | ||
236 | |||
237 | return evicted; | ||
238 | } | ||
239 | EXPORT_SYMBOL(inet_frag_evictor); | ||
240 | |||
241 | static struct inet_frag_queue *inet_frag_intern(struct netns_frags *nf, | 341 | static struct inet_frag_queue *inet_frag_intern(struct netns_frags *nf, |
242 | struct inet_frag_queue *qp_in, struct inet_frags *f, | 342 | struct inet_frag_queue *qp_in, |
243 | void *arg) | 343 | struct inet_frags *f, |
344 | void *arg) | ||
244 | { | 345 | { |
245 | struct inet_frag_bucket *hb; | 346 | struct inet_frag_bucket *hb = get_frag_bucket_locked(qp_in, f); |
246 | struct inet_frag_queue *qp; | 347 | struct inet_frag_queue *qp; |
247 | unsigned int hash; | ||
248 | |||
249 | read_lock(&f->lock); /* Protects against hash rebuild */ | ||
250 | /* | ||
251 | * While we stayed w/o the lock other CPU could update | ||
252 | * the rnd seed, so we need to re-calculate the hash | ||
253 | * chain. Fortunatelly the qp_in can be used to get one. | ||
254 | */ | ||
255 | hash = f->hashfn(qp_in); | ||
256 | hb = &f->hash[hash]; | ||
257 | spin_lock(&hb->chain_lock); | ||
258 | 348 | ||
259 | #ifdef CONFIG_SMP | 349 | #ifdef CONFIG_SMP |
260 | /* With SMP race we have to recheck hash table, because | 350 | /* With SMP race we have to recheck hash table, because |
261 | * such entry could be created on other cpu, while we | 351 | * such entry could have been created on other cpu before |
262 | * released the hash bucket lock. | 352 | * we acquired hash bucket lock. |
263 | */ | 353 | */ |
264 | hlist_for_each_entry(qp, &hb->chain, list) { | 354 | hlist_for_each_entry(qp, &hb->chain, list) { |
265 | if (qp->net == nf && f->match(qp, arg)) { | 355 | if (qp->net == nf && f->match(qp, arg)) { |
266 | atomic_inc(&qp->refcnt); | 356 | atomic_inc(&qp->refcnt); |
267 | spin_unlock(&hb->chain_lock); | 357 | spin_unlock(&hb->chain_lock); |
268 | read_unlock(&f->lock); | 358 | qp_in->flags |= INET_FRAG_COMPLETE; |
269 | qp_in->last_in |= INET_FRAG_COMPLETE; | ||
270 | inet_frag_put(qp_in, f); | 359 | inet_frag_put(qp_in, f); |
271 | return qp; | 360 | return qp; |
272 | } | 361 | } |
@@ -278,19 +367,24 @@ static struct inet_frag_queue *inet_frag_intern(struct netns_frags *nf, | |||
278 | 367 | ||
279 | atomic_inc(&qp->refcnt); | 368 | atomic_inc(&qp->refcnt); |
280 | hlist_add_head(&qp->list, &hb->chain); | 369 | hlist_add_head(&qp->list, &hb->chain); |
281 | inet_frag_lru_add(nf, qp); | 370 | |
282 | spin_unlock(&hb->chain_lock); | 371 | spin_unlock(&hb->chain_lock); |
283 | read_unlock(&f->lock); | ||
284 | 372 | ||
285 | return qp; | 373 | return qp; |
286 | } | 374 | } |
287 | 375 | ||
288 | static struct inet_frag_queue *inet_frag_alloc(struct netns_frags *nf, | 376 | static struct inet_frag_queue *inet_frag_alloc(struct netns_frags *nf, |
289 | struct inet_frags *f, void *arg) | 377 | struct inet_frags *f, |
378 | void *arg) | ||
290 | { | 379 | { |
291 | struct inet_frag_queue *q; | 380 | struct inet_frag_queue *q; |
292 | 381 | ||
293 | q = kzalloc(f->qsize, GFP_ATOMIC); | 382 | if (frag_mem_limit(nf) > nf->high_thresh) { |
383 | inet_frag_schedule_worker(f); | ||
384 | return NULL; | ||
385 | } | ||
386 | |||
387 | q = kmem_cache_zalloc(f->frags_cachep, GFP_ATOMIC); | ||
294 | if (q == NULL) | 388 | if (q == NULL) |
295 | return NULL; | 389 | return NULL; |
296 | 390 | ||
@@ -301,13 +395,13 @@ static struct inet_frag_queue *inet_frag_alloc(struct netns_frags *nf, | |||
301 | setup_timer(&q->timer, f->frag_expire, (unsigned long)q); | 395 | setup_timer(&q->timer, f->frag_expire, (unsigned long)q); |
302 | spin_lock_init(&q->lock); | 396 | spin_lock_init(&q->lock); |
303 | atomic_set(&q->refcnt, 1); | 397 | atomic_set(&q->refcnt, 1); |
304 | INIT_LIST_HEAD(&q->lru_list); | ||
305 | 398 | ||
306 | return q; | 399 | return q; |
307 | } | 400 | } |
308 | 401 | ||
309 | static struct inet_frag_queue *inet_frag_create(struct netns_frags *nf, | 402 | static struct inet_frag_queue *inet_frag_create(struct netns_frags *nf, |
310 | struct inet_frags *f, void *arg) | 403 | struct inet_frags *f, |
404 | void *arg) | ||
311 | { | 405 | { |
312 | struct inet_frag_queue *q; | 406 | struct inet_frag_queue *q; |
313 | 407 | ||
@@ -319,13 +413,17 @@ static struct inet_frag_queue *inet_frag_create(struct netns_frags *nf, | |||
319 | } | 413 | } |
320 | 414 | ||
321 | struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, | 415 | struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, |
322 | struct inet_frags *f, void *key, unsigned int hash) | 416 | struct inet_frags *f, void *key, |
323 | __releases(&f->lock) | 417 | unsigned int hash) |
324 | { | 418 | { |
325 | struct inet_frag_bucket *hb; | 419 | struct inet_frag_bucket *hb; |
326 | struct inet_frag_queue *q; | 420 | struct inet_frag_queue *q; |
327 | int depth = 0; | 421 | int depth = 0; |
328 | 422 | ||
423 | if (frag_mem_limit(nf) > nf->low_thresh) | ||
424 | inet_frag_schedule_worker(f); | ||
425 | |||
426 | hash &= (INETFRAGS_HASHSZ - 1); | ||
329 | hb = &f->hash[hash]; | 427 | hb = &f->hash[hash]; |
330 | 428 | ||
331 | spin_lock(&hb->chain_lock); | 429 | spin_lock(&hb->chain_lock); |
@@ -333,18 +431,22 @@ struct inet_frag_queue *inet_frag_find(struct netns_frags *nf, | |||
333 | if (q->net == nf && f->match(q, key)) { | 431 | if (q->net == nf && f->match(q, key)) { |
334 | atomic_inc(&q->refcnt); | 432 | atomic_inc(&q->refcnt); |
335 | spin_unlock(&hb->chain_lock); | 433 | spin_unlock(&hb->chain_lock); |
336 | read_unlock(&f->lock); | ||
337 | return q; | 434 | return q; |
338 | } | 435 | } |
339 | depth++; | 436 | depth++; |
340 | } | 437 | } |
341 | spin_unlock(&hb->chain_lock); | 438 | spin_unlock(&hb->chain_lock); |
342 | read_unlock(&f->lock); | ||
343 | 439 | ||
344 | if (depth <= INETFRAGS_MAXDEPTH) | 440 | if (depth <= INETFRAGS_MAXDEPTH) |
345 | return inet_frag_create(nf, f, key); | 441 | return inet_frag_create(nf, f, key); |
346 | else | 442 | |
347 | return ERR_PTR(-ENOBUFS); | 443 | if (inet_frag_may_rebuild(f)) { |
444 | if (!f->rebuild) | ||
445 | f->rebuild = true; | ||
446 | inet_frag_schedule_worker(f); | ||
447 | } | ||
448 | |||
449 | return ERR_PTR(-ENOBUFS); | ||
348 | } | 450 | } |
349 | EXPORT_SYMBOL(inet_frag_find); | 451 | EXPORT_SYMBOL(inet_frag_find); |
350 | 452 | ||
diff --git a/net/ipv4/ip_fragment.c b/net/ipv4/ip_fragment.c index ed32313e307c..15f0e2bad7ad 100644 --- a/net/ipv4/ip_fragment.c +++ b/net/ipv4/ip_fragment.c | |||
@@ -55,6 +55,7 @@ | |||
55 | */ | 55 | */ |
56 | 56 | ||
57 | static int sysctl_ipfrag_max_dist __read_mostly = 64; | 57 | static int sysctl_ipfrag_max_dist __read_mostly = 64; |
58 | static const char ip_frag_cache_name[] = "ip4-frags"; | ||
58 | 59 | ||
59 | struct ipfrag_skb_cb | 60 | struct ipfrag_skb_cb |
60 | { | 61 | { |
@@ -86,11 +87,6 @@ static inline u8 ip4_frag_ecn(u8 tos) | |||
86 | 87 | ||
87 | static struct inet_frags ip4_frags; | 88 | static struct inet_frags ip4_frags; |
88 | 89 | ||
89 | int ip_frag_nqueues(struct net *net) | ||
90 | { | ||
91 | return net->ipv4.frags.nqueues; | ||
92 | } | ||
93 | |||
94 | int ip_frag_mem(struct net *net) | 90 | int ip_frag_mem(struct net *net) |
95 | { | 91 | { |
96 | return sum_frag_mem_limit(&net->ipv4.frags); | 92 | return sum_frag_mem_limit(&net->ipv4.frags); |
@@ -109,21 +105,21 @@ static unsigned int ipqhashfn(__be16 id, __be32 saddr, __be32 daddr, u8 prot) | |||
109 | net_get_random_once(&ip4_frags.rnd, sizeof(ip4_frags.rnd)); | 105 | net_get_random_once(&ip4_frags.rnd, sizeof(ip4_frags.rnd)); |
110 | return jhash_3words((__force u32)id << 16 | prot, | 106 | return jhash_3words((__force u32)id << 16 | prot, |
111 | (__force u32)saddr, (__force u32)daddr, | 107 | (__force u32)saddr, (__force u32)daddr, |
112 | ip4_frags.rnd) & (INETFRAGS_HASHSZ - 1); | 108 | ip4_frags.rnd); |
113 | } | 109 | } |
114 | 110 | ||
115 | static unsigned int ip4_hashfn(struct inet_frag_queue *q) | 111 | static unsigned int ip4_hashfn(const struct inet_frag_queue *q) |
116 | { | 112 | { |
117 | struct ipq *ipq; | 113 | const struct ipq *ipq; |
118 | 114 | ||
119 | ipq = container_of(q, struct ipq, q); | 115 | ipq = container_of(q, struct ipq, q); |
120 | return ipqhashfn(ipq->id, ipq->saddr, ipq->daddr, ipq->protocol); | 116 | return ipqhashfn(ipq->id, ipq->saddr, ipq->daddr, ipq->protocol); |
121 | } | 117 | } |
122 | 118 | ||
123 | static bool ip4_frag_match(struct inet_frag_queue *q, void *a) | 119 | static bool ip4_frag_match(const struct inet_frag_queue *q, const void *a) |
124 | { | 120 | { |
125 | struct ipq *qp; | 121 | const struct ipq *qp; |
126 | struct ip4_create_arg *arg = a; | 122 | const struct ip4_create_arg *arg = a; |
127 | 123 | ||
128 | qp = container_of(q, struct ipq, q); | 124 | qp = container_of(q, struct ipq, q); |
129 | return qp->id == arg->iph->id && | 125 | return qp->id == arg->iph->id && |
@@ -133,14 +129,14 @@ static bool ip4_frag_match(struct inet_frag_queue *q, void *a) | |||
133 | qp->user == arg->user; | 129 | qp->user == arg->user; |
134 | } | 130 | } |
135 | 131 | ||
136 | static void ip4_frag_init(struct inet_frag_queue *q, void *a) | 132 | static void ip4_frag_init(struct inet_frag_queue *q, const void *a) |
137 | { | 133 | { |
138 | struct ipq *qp = container_of(q, struct ipq, q); | 134 | struct ipq *qp = container_of(q, struct ipq, q); |
139 | struct netns_ipv4 *ipv4 = container_of(q->net, struct netns_ipv4, | 135 | struct netns_ipv4 *ipv4 = container_of(q->net, struct netns_ipv4, |
140 | frags); | 136 | frags); |
141 | struct net *net = container_of(ipv4, struct net, ipv4); | 137 | struct net *net = container_of(ipv4, struct net, ipv4); |
142 | 138 | ||
143 | struct ip4_create_arg *arg = a; | 139 | const struct ip4_create_arg *arg = a; |
144 | 140 | ||
145 | qp->protocol = arg->iph->protocol; | 141 | qp->protocol = arg->iph->protocol; |
146 | qp->id = arg->iph->id; | 142 | qp->id = arg->iph->id; |
@@ -177,18 +173,6 @@ static void ipq_kill(struct ipq *ipq) | |||
177 | inet_frag_kill(&ipq->q, &ip4_frags); | 173 | inet_frag_kill(&ipq->q, &ip4_frags); |
178 | } | 174 | } |
179 | 175 | ||
180 | /* Memory limiting on fragments. Evictor trashes the oldest | ||
181 | * fragment queue until we are back under the threshold. | ||
182 | */ | ||
183 | static void ip_evictor(struct net *net) | ||
184 | { | ||
185 | int evicted; | ||
186 | |||
187 | evicted = inet_frag_evictor(&net->ipv4.frags, &ip4_frags, false); | ||
188 | if (evicted) | ||
189 | IP_ADD_STATS_BH(net, IPSTATS_MIB_REASMFAILS, evicted); | ||
190 | } | ||
191 | |||
192 | /* | 176 | /* |
193 | * Oops, a fragment queue timed out. Kill it and send an ICMP reply. | 177 | * Oops, a fragment queue timed out. Kill it and send an ICMP reply. |
194 | */ | 178 | */ |
@@ -202,19 +186,22 @@ static void ip_expire(unsigned long arg) | |||
202 | 186 | ||
203 | spin_lock(&qp->q.lock); | 187 | spin_lock(&qp->q.lock); |
204 | 188 | ||
205 | if (qp->q.last_in & INET_FRAG_COMPLETE) | 189 | if (qp->q.flags & INET_FRAG_COMPLETE) |
206 | goto out; | 190 | goto out; |
207 | 191 | ||
208 | ipq_kill(qp); | 192 | ipq_kill(qp); |
209 | |||
210 | IP_INC_STATS_BH(net, IPSTATS_MIB_REASMTIMEOUT); | ||
211 | IP_INC_STATS_BH(net, IPSTATS_MIB_REASMFAILS); | 193 | IP_INC_STATS_BH(net, IPSTATS_MIB_REASMFAILS); |
212 | 194 | ||
213 | if ((qp->q.last_in & INET_FRAG_FIRST_IN) && qp->q.fragments != NULL) { | 195 | if (!(qp->q.flags & INET_FRAG_EVICTED)) { |
214 | struct sk_buff *head = qp->q.fragments; | 196 | struct sk_buff *head = qp->q.fragments; |
215 | const struct iphdr *iph; | 197 | const struct iphdr *iph; |
216 | int err; | 198 | int err; |
217 | 199 | ||
200 | IP_INC_STATS_BH(net, IPSTATS_MIB_REASMTIMEOUT); | ||
201 | |||
202 | if (!(qp->q.flags & INET_FRAG_FIRST_IN) || !qp->q.fragments) | ||
203 | goto out; | ||
204 | |||
218 | rcu_read_lock(); | 205 | rcu_read_lock(); |
219 | head->dev = dev_get_by_index_rcu(net, qp->iif); | 206 | head->dev = dev_get_by_index_rcu(net, qp->iif); |
220 | if (!head->dev) | 207 | if (!head->dev) |
@@ -227,8 +214,7 @@ static void ip_expire(unsigned long arg) | |||
227 | if (err) | 214 | if (err) |
228 | goto out_rcu_unlock; | 215 | goto out_rcu_unlock; |
229 | 216 | ||
230 | /* | 217 | /* Only an end host needs to send an ICMP |
231 | * Only an end host needs to send an ICMP | ||
232 | * "Fragment Reassembly Timeout" message, per RFC792. | 218 | * "Fragment Reassembly Timeout" message, per RFC792. |
233 | */ | 219 | */ |
234 | if (qp->user == IP_DEFRAG_AF_PACKET || | 220 | if (qp->user == IP_DEFRAG_AF_PACKET || |
@@ -237,7 +223,6 @@ static void ip_expire(unsigned long arg) | |||
237 | (skb_rtable(head)->rt_type != RTN_LOCAL))) | 223 | (skb_rtable(head)->rt_type != RTN_LOCAL))) |
238 | goto out_rcu_unlock; | 224 | goto out_rcu_unlock; |
239 | 225 | ||
240 | |||
241 | /* Send an ICMP "Fragment Reassembly Timeout" message. */ | 226 | /* Send an ICMP "Fragment Reassembly Timeout" message. */ |
242 | icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0); | 227 | icmp_send(head, ICMP_TIME_EXCEEDED, ICMP_EXC_FRAGTIME, 0); |
243 | out_rcu_unlock: | 228 | out_rcu_unlock: |
@@ -260,7 +245,6 @@ static inline struct ipq *ip_find(struct net *net, struct iphdr *iph, u32 user) | |||
260 | arg.iph = iph; | 245 | arg.iph = iph; |
261 | arg.user = user; | 246 | arg.user = user; |
262 | 247 | ||
263 | read_lock(&ip4_frags.lock); | ||
264 | hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol); | 248 | hash = ipqhashfn(iph->id, iph->saddr, iph->daddr, iph->protocol); |
265 | 249 | ||
266 | q = inet_frag_find(&net->ipv4.frags, &ip4_frags, &arg, hash); | 250 | q = inet_frag_find(&net->ipv4.frags, &ip4_frags, &arg, hash); |
@@ -319,7 +303,7 @@ static int ip_frag_reinit(struct ipq *qp) | |||
319 | } while (fp); | 303 | } while (fp); |
320 | sub_frag_mem_limit(&qp->q, sum_truesize); | 304 | sub_frag_mem_limit(&qp->q, sum_truesize); |
321 | 305 | ||
322 | qp->q.last_in = 0; | 306 | qp->q.flags = 0; |
323 | qp->q.len = 0; | 307 | qp->q.len = 0; |
324 | qp->q.meat = 0; | 308 | qp->q.meat = 0; |
325 | qp->q.fragments = NULL; | 309 | qp->q.fragments = NULL; |
@@ -340,7 +324,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb) | |||
340 | int err = -ENOENT; | 324 | int err = -ENOENT; |
341 | u8 ecn; | 325 | u8 ecn; |
342 | 326 | ||
343 | if (qp->q.last_in & INET_FRAG_COMPLETE) | 327 | if (qp->q.flags & INET_FRAG_COMPLETE) |
344 | goto err; | 328 | goto err; |
345 | 329 | ||
346 | if (!(IPCB(skb)->flags & IPSKB_FRAG_COMPLETE) && | 330 | if (!(IPCB(skb)->flags & IPSKB_FRAG_COMPLETE) && |
@@ -367,9 +351,9 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb) | |||
367 | * or have different end, the segment is corrupted. | 351 | * or have different end, the segment is corrupted. |
368 | */ | 352 | */ |
369 | if (end < qp->q.len || | 353 | if (end < qp->q.len || |
370 | ((qp->q.last_in & INET_FRAG_LAST_IN) && end != qp->q.len)) | 354 | ((qp->q.flags & INET_FRAG_LAST_IN) && end != qp->q.len)) |
371 | goto err; | 355 | goto err; |
372 | qp->q.last_in |= INET_FRAG_LAST_IN; | 356 | qp->q.flags |= INET_FRAG_LAST_IN; |
373 | qp->q.len = end; | 357 | qp->q.len = end; |
374 | } else { | 358 | } else { |
375 | if (end&7) { | 359 | if (end&7) { |
@@ -379,7 +363,7 @@ static int ip_frag_queue(struct ipq *qp, struct sk_buff *skb) | |||
379 | } | 363 | } |
380 | if (end > qp->q.len) { | 364 | if (end > qp->q.len) { |
381 | /* Some bits beyond end -> corruption. */ | 365 | /* Some bits beyond end -> corruption. */ |
382 | if (qp->q.last_in & INET_FRAG_LAST_IN) | 366 | if (qp->q.flags & INET_FRAG_LAST_IN) |
383 | goto err; | 367 | goto err; |
384 | qp->q.len = end; | 368 | qp->q.len = end; |
385 | } | 369 | } |
@@ -488,13 +472,13 @@ found: | |||
488 | qp->ecn |= ecn; | 472 | qp->ecn |= ecn; |
489 | add_frag_mem_limit(&qp->q, skb->truesize); | 473 | add_frag_mem_limit(&qp->q, skb->truesize); |
490 | if (offset == 0) | 474 | if (offset == 0) |
491 | qp->q.last_in |= INET_FRAG_FIRST_IN; | 475 | qp->q.flags |= INET_FRAG_FIRST_IN; |
492 | 476 | ||
493 | if (ip_hdr(skb)->frag_off & htons(IP_DF) && | 477 | if (ip_hdr(skb)->frag_off & htons(IP_DF) && |
494 | skb->len + ihl > qp->q.max_size) | 478 | skb->len + ihl > qp->q.max_size) |
495 | qp->q.max_size = skb->len + ihl; | 479 | qp->q.max_size = skb->len + ihl; |
496 | 480 | ||
497 | if (qp->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && | 481 | if (qp->q.flags == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && |
498 | qp->q.meat == qp->q.len) { | 482 | qp->q.meat == qp->q.len) { |
499 | unsigned long orefdst = skb->_skb_refdst; | 483 | unsigned long orefdst = skb->_skb_refdst; |
500 | 484 | ||
@@ -505,7 +489,6 @@ found: | |||
505 | } | 489 | } |
506 | 490 | ||
507 | skb_dst_drop(skb); | 491 | skb_dst_drop(skb); |
508 | inet_frag_lru_move(&qp->q); | ||
509 | return -EINPROGRESS; | 492 | return -EINPROGRESS; |
510 | 493 | ||
511 | err: | 494 | err: |
@@ -655,9 +638,6 @@ int ip_defrag(struct sk_buff *skb, u32 user) | |||
655 | net = skb->dev ? dev_net(skb->dev) : dev_net(skb_dst(skb)->dev); | 638 | net = skb->dev ? dev_net(skb->dev) : dev_net(skb_dst(skb)->dev); |
656 | IP_INC_STATS_BH(net, IPSTATS_MIB_REASMREQDS); | 639 | IP_INC_STATS_BH(net, IPSTATS_MIB_REASMREQDS); |
657 | 640 | ||
658 | /* Start by cleaning up the memory. */ | ||
659 | ip_evictor(net); | ||
660 | |||
661 | /* Lookup (or create) queue header */ | 641 | /* Lookup (or create) queue header */ |
662 | if ((qp = ip_find(net, ip_hdr(skb), user)) != NULL) { | 642 | if ((qp = ip_find(net, ip_hdr(skb), user)) != NULL) { |
663 | int ret; | 643 | int ret; |
@@ -721,14 +701,17 @@ static struct ctl_table ip4_frags_ns_ctl_table[] = { | |||
721 | .data = &init_net.ipv4.frags.high_thresh, | 701 | .data = &init_net.ipv4.frags.high_thresh, |
722 | .maxlen = sizeof(int), | 702 | .maxlen = sizeof(int), |
723 | .mode = 0644, | 703 | .mode = 0644, |
724 | .proc_handler = proc_dointvec | 704 | .proc_handler = proc_dointvec_minmax, |
705 | .extra1 = &init_net.ipv4.frags.low_thresh | ||
725 | }, | 706 | }, |
726 | { | 707 | { |
727 | .procname = "ipfrag_low_thresh", | 708 | .procname = "ipfrag_low_thresh", |
728 | .data = &init_net.ipv4.frags.low_thresh, | 709 | .data = &init_net.ipv4.frags.low_thresh, |
729 | .maxlen = sizeof(int), | 710 | .maxlen = sizeof(int), |
730 | .mode = 0644, | 711 | .mode = 0644, |
731 | .proc_handler = proc_dointvec | 712 | .proc_handler = proc_dointvec_minmax, |
713 | .extra1 = &zero, | ||
714 | .extra2 = &init_net.ipv4.frags.high_thresh | ||
732 | }, | 715 | }, |
733 | { | 716 | { |
734 | .procname = "ipfrag_time", | 717 | .procname = "ipfrag_time", |
@@ -740,10 +723,12 @@ static struct ctl_table ip4_frags_ns_ctl_table[] = { | |||
740 | { } | 723 | { } |
741 | }; | 724 | }; |
742 | 725 | ||
726 | /* secret interval has been deprecated */ | ||
727 | static int ip4_frags_secret_interval_unused; | ||
743 | static struct ctl_table ip4_frags_ctl_table[] = { | 728 | static struct ctl_table ip4_frags_ctl_table[] = { |
744 | { | 729 | { |
745 | .procname = "ipfrag_secret_interval", | 730 | .procname = "ipfrag_secret_interval", |
746 | .data = &ip4_frags.secret_interval, | 731 | .data = &ip4_frags_secret_interval_unused, |
747 | .maxlen = sizeof(int), | 732 | .maxlen = sizeof(int), |
748 | .mode = 0644, | 733 | .mode = 0644, |
749 | .proc_handler = proc_dointvec_jiffies, | 734 | .proc_handler = proc_dointvec_jiffies, |
@@ -771,7 +756,10 @@ static int __net_init ip4_frags_ns_ctl_register(struct net *net) | |||
771 | goto err_alloc; | 756 | goto err_alloc; |
772 | 757 | ||
773 | table[0].data = &net->ipv4.frags.high_thresh; | 758 | table[0].data = &net->ipv4.frags.high_thresh; |
759 | table[0].extra1 = &net->ipv4.frags.low_thresh; | ||
760 | table[0].extra2 = &init_net.ipv4.frags.high_thresh; | ||
774 | table[1].data = &net->ipv4.frags.low_thresh; | 761 | table[1].data = &net->ipv4.frags.low_thresh; |
762 | table[1].extra2 = &net->ipv4.frags.high_thresh; | ||
775 | table[2].data = &net->ipv4.frags.timeout; | 763 | table[2].data = &net->ipv4.frags.timeout; |
776 | 764 | ||
777 | /* Don't export sysctls to unprivileged users */ | 765 | /* Don't export sysctls to unprivileged users */ |
@@ -873,6 +861,7 @@ void __init ipfrag_init(void) | |||
873 | ip4_frags.qsize = sizeof(struct ipq); | 861 | ip4_frags.qsize = sizeof(struct ipq); |
874 | ip4_frags.match = ip4_frag_match; | 862 | ip4_frags.match = ip4_frag_match; |
875 | ip4_frags.frag_expire = ip_expire; | 863 | ip4_frags.frag_expire = ip_expire; |
876 | ip4_frags.secret_interval = 10 * 60 * HZ; | 864 | ip4_frags.frags_cache_name = ip_frag_cache_name; |
877 | inet_frags_init(&ip4_frags); | 865 | if (inet_frags_init(&ip4_frags)) |
866 | panic("IP: failed to allocate ip4_frags cache\n"); | ||
878 | } | 867 | } |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 8d3b6b0e9857..215af2b155cb 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
@@ -855,11 +855,15 @@ static int __ip_append_data(struct sock *sk, | |||
855 | unsigned int maxfraglen, fragheaderlen, maxnonfragsize; | 855 | unsigned int maxfraglen, fragheaderlen, maxnonfragsize; |
856 | int csummode = CHECKSUM_NONE; | 856 | int csummode = CHECKSUM_NONE; |
857 | struct rtable *rt = (struct rtable *)cork->dst; | 857 | struct rtable *rt = (struct rtable *)cork->dst; |
858 | u32 tskey = 0; | ||
858 | 859 | ||
859 | skb = skb_peek_tail(queue); | 860 | skb = skb_peek_tail(queue); |
860 | 861 | ||
861 | exthdrlen = !skb ? rt->dst.header_len : 0; | 862 | exthdrlen = !skb ? rt->dst.header_len : 0; |
862 | mtu = cork->fragsize; | 863 | mtu = cork->fragsize; |
864 | if (cork->tx_flags & SKBTX_ANY_SW_TSTAMP && | ||
865 | sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) | ||
866 | tskey = sk->sk_tskey++; | ||
863 | 867 | ||
864 | hh_len = LL_RESERVED_SPACE(rt->dst.dev); | 868 | hh_len = LL_RESERVED_SPACE(rt->dst.dev); |
865 | 869 | ||
@@ -962,10 +966,6 @@ alloc_new_skb: | |||
962 | sk->sk_allocation); | 966 | sk->sk_allocation); |
963 | if (unlikely(skb == NULL)) | 967 | if (unlikely(skb == NULL)) |
964 | err = -ENOBUFS; | 968 | err = -ENOBUFS; |
965 | else | ||
966 | /* only the initial fragment is | ||
967 | time stamped */ | ||
968 | cork->tx_flags = 0; | ||
969 | } | 969 | } |
970 | if (skb == NULL) | 970 | if (skb == NULL) |
971 | goto error; | 971 | goto error; |
@@ -976,7 +976,12 @@ alloc_new_skb: | |||
976 | skb->ip_summed = csummode; | 976 | skb->ip_summed = csummode; |
977 | skb->csum = 0; | 977 | skb->csum = 0; |
978 | skb_reserve(skb, hh_len); | 978 | skb_reserve(skb, hh_len); |
979 | |||
980 | /* only the initial fragment is time stamped */ | ||
979 | skb_shinfo(skb)->tx_flags = cork->tx_flags; | 981 | skb_shinfo(skb)->tx_flags = cork->tx_flags; |
982 | cork->tx_flags = 0; | ||
983 | skb_shinfo(skb)->tskey = tskey; | ||
984 | tskey = 0; | ||
980 | 985 | ||
981 | /* | 986 | /* |
982 | * Find where to start putting bytes. | 987 | * Find where to start putting bytes. |
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 64741b938632..5cb830c78990 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c | |||
@@ -1319,7 +1319,7 @@ static int do_ip_getsockopt(struct sock *sk, int level, int optname, | |||
1319 | if (sk->sk_type != SOCK_STREAM) | 1319 | if (sk->sk_type != SOCK_STREAM) |
1320 | return -ENOPROTOOPT; | 1320 | return -ENOPROTOOPT; |
1321 | 1321 | ||
1322 | msg.msg_control = optval; | 1322 | msg.msg_control = (__force void *) optval; |
1323 | msg.msg_controllen = len; | 1323 | msg.msg_controllen = len; |
1324 | msg.msg_flags = flags; | 1324 | msg.msg_flags = flags; |
1325 | 1325 | ||
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index 6f9de61dce5f..bda4bb8ae260 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c | |||
@@ -69,23 +69,25 @@ static unsigned int ip_tunnel_hash(__be32 key, __be32 remote) | |||
69 | } | 69 | } |
70 | 70 | ||
71 | static void __tunnel_dst_set(struct ip_tunnel_dst *idst, | 71 | static void __tunnel_dst_set(struct ip_tunnel_dst *idst, |
72 | struct dst_entry *dst) | 72 | struct dst_entry *dst, __be32 saddr) |
73 | { | 73 | { |
74 | struct dst_entry *old_dst; | 74 | struct dst_entry *old_dst; |
75 | 75 | ||
76 | dst_clone(dst); | 76 | dst_clone(dst); |
77 | old_dst = xchg((__force struct dst_entry **)&idst->dst, dst); | 77 | old_dst = xchg((__force struct dst_entry **)&idst->dst, dst); |
78 | dst_release(old_dst); | 78 | dst_release(old_dst); |
79 | idst->saddr = saddr; | ||
79 | } | 80 | } |
80 | 81 | ||
81 | static void tunnel_dst_set(struct ip_tunnel *t, struct dst_entry *dst) | 82 | static noinline void tunnel_dst_set(struct ip_tunnel *t, |
83 | struct dst_entry *dst, __be32 saddr) | ||
82 | { | 84 | { |
83 | __tunnel_dst_set(this_cpu_ptr(t->dst_cache), dst); | 85 | __tunnel_dst_set(raw_cpu_ptr(t->dst_cache), dst, saddr); |
84 | } | 86 | } |
85 | 87 | ||
86 | static void tunnel_dst_reset(struct ip_tunnel *t) | 88 | static void tunnel_dst_reset(struct ip_tunnel *t) |
87 | { | 89 | { |
88 | tunnel_dst_set(t, NULL); | 90 | tunnel_dst_set(t, NULL, 0); |
89 | } | 91 | } |
90 | 92 | ||
91 | void ip_tunnel_dst_reset_all(struct ip_tunnel *t) | 93 | void ip_tunnel_dst_reset_all(struct ip_tunnel *t) |
@@ -93,20 +95,25 @@ void ip_tunnel_dst_reset_all(struct ip_tunnel *t) | |||
93 | int i; | 95 | int i; |
94 | 96 | ||
95 | for_each_possible_cpu(i) | 97 | for_each_possible_cpu(i) |
96 | __tunnel_dst_set(per_cpu_ptr(t->dst_cache, i), NULL); | 98 | __tunnel_dst_set(per_cpu_ptr(t->dst_cache, i), NULL, 0); |
97 | } | 99 | } |
98 | EXPORT_SYMBOL(ip_tunnel_dst_reset_all); | 100 | EXPORT_SYMBOL(ip_tunnel_dst_reset_all); |
99 | 101 | ||
100 | static struct rtable *tunnel_rtable_get(struct ip_tunnel *t, u32 cookie) | 102 | static struct rtable *tunnel_rtable_get(struct ip_tunnel *t, |
103 | u32 cookie, __be32 *saddr) | ||
101 | { | 104 | { |
105 | struct ip_tunnel_dst *idst; | ||
102 | struct dst_entry *dst; | 106 | struct dst_entry *dst; |
103 | 107 | ||
104 | rcu_read_lock(); | 108 | rcu_read_lock(); |
105 | dst = rcu_dereference(this_cpu_ptr(t->dst_cache)->dst); | 109 | idst = raw_cpu_ptr(t->dst_cache); |
110 | dst = rcu_dereference(idst->dst); | ||
106 | if (dst && !atomic_inc_not_zero(&dst->__refcnt)) | 111 | if (dst && !atomic_inc_not_zero(&dst->__refcnt)) |
107 | dst = NULL; | 112 | dst = NULL; |
108 | if (dst) { | 113 | if (dst) { |
109 | if (dst->obsolete && dst->ops->check(dst, cookie) == NULL) { | 114 | if (!dst->obsolete || dst->ops->check(dst, cookie)) { |
115 | *saddr = idst->saddr; | ||
116 | } else { | ||
110 | tunnel_dst_reset(t); | 117 | tunnel_dst_reset(t); |
111 | dst_release(dst); | 118 | dst_release(dst); |
112 | dst = NULL; | 119 | dst = NULL; |
@@ -305,7 +312,7 @@ static struct net_device *__ip_tunnel_create(struct net *net, | |||
305 | } | 312 | } |
306 | 313 | ||
307 | ASSERT_RTNL(); | 314 | ASSERT_RTNL(); |
308 | dev = alloc_netdev(ops->priv_size, name, ops->setup); | 315 | dev = alloc_netdev(ops->priv_size, name, NET_NAME_UNKNOWN, ops->setup); |
309 | if (!dev) { | 316 | if (!dev) { |
310 | err = -ENOMEM; | 317 | err = -ENOMEM; |
311 | goto failed; | 318 | goto failed; |
@@ -367,7 +374,7 @@ static int ip_tunnel_bind_dev(struct net_device *dev) | |||
367 | 374 | ||
368 | if (!IS_ERR(rt)) { | 375 | if (!IS_ERR(rt)) { |
369 | tdev = rt->dst.dev; | 376 | tdev = rt->dst.dev; |
370 | tunnel_dst_set(tunnel, &rt->dst); | 377 | tunnel_dst_set(tunnel, &rt->dst, fl4.saddr); |
371 | ip_rt_put(rt); | 378 | ip_rt_put(rt); |
372 | } | 379 | } |
373 | if (dev->type != ARPHRD_ETHER) | 380 | if (dev->type != ARPHRD_ETHER) |
@@ -610,7 +617,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, | |||
610 | init_tunnel_flow(&fl4, protocol, dst, tnl_params->saddr, | 617 | init_tunnel_flow(&fl4, protocol, dst, tnl_params->saddr, |
611 | tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link); | 618 | tunnel->parms.o_key, RT_TOS(tos), tunnel->parms.link); |
612 | 619 | ||
613 | rt = connected ? tunnel_rtable_get(tunnel, 0) : NULL; | 620 | rt = connected ? tunnel_rtable_get(tunnel, 0, &fl4.saddr) : NULL; |
614 | 621 | ||
615 | if (!rt) { | 622 | if (!rt) { |
616 | rt = ip_route_output_key(tunnel->net, &fl4); | 623 | rt = ip_route_output_key(tunnel->net, &fl4); |
@@ -620,7 +627,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, | |||
620 | goto tx_error; | 627 | goto tx_error; |
621 | } | 628 | } |
622 | if (connected) | 629 | if (connected) |
623 | tunnel_dst_set(tunnel, &rt->dst); | 630 | tunnel_dst_set(tunnel, &rt->dst, fl4.saddr); |
624 | } | 631 | } |
625 | 632 | ||
626 | if (rt->dst.dev == dev) { | 633 | if (rt->dst.dev == dev) { |
@@ -757,9 +764,14 @@ int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd) | |||
757 | 764 | ||
758 | t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type); | 765 | t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type); |
759 | 766 | ||
760 | if (!t && (cmd == SIOCADDTUNNEL)) { | 767 | if (cmd == SIOCADDTUNNEL) { |
761 | t = ip_tunnel_create(net, itn, p); | 768 | if (!t) { |
762 | err = PTR_ERR_OR_ZERO(t); | 769 | t = ip_tunnel_create(net, itn, p); |
770 | err = PTR_ERR_OR_ZERO(t); | ||
771 | break; | ||
772 | } | ||
773 | |||
774 | err = -EEXIST; | ||
763 | break; | 775 | break; |
764 | } | 776 | } |
765 | if (dev != itn->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { | 777 | if (dev != itn->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { |
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index b8960f3527f3..e453cb724a95 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c | |||
@@ -534,40 +534,28 @@ static struct rtnl_link_ops vti_link_ops __read_mostly = { | |||
534 | 534 | ||
535 | static int __init vti_init(void) | 535 | static int __init vti_init(void) |
536 | { | 536 | { |
537 | const char *msg; | ||
537 | int err; | 538 | int err; |
538 | 539 | ||
539 | pr_info("IPv4 over IPSec tunneling driver\n"); | 540 | pr_info("IPv4 over IPsec tunneling driver\n"); |
540 | 541 | ||
542 | msg = "tunnel device"; | ||
541 | err = register_pernet_device(&vti_net_ops); | 543 | err = register_pernet_device(&vti_net_ops); |
542 | if (err < 0) | 544 | if (err < 0) |
543 | return err; | 545 | goto pernet_dev_failed; |
544 | err = xfrm4_protocol_register(&vti_esp4_protocol, IPPROTO_ESP); | ||
545 | if (err < 0) { | ||
546 | unregister_pernet_device(&vti_net_ops); | ||
547 | pr_info("vti init: can't register tunnel\n"); | ||
548 | |||
549 | return err; | ||
550 | } | ||
551 | 546 | ||
547 | msg = "tunnel protocols"; | ||
548 | err = xfrm4_protocol_register(&vti_esp4_protocol, IPPROTO_ESP); | ||
549 | if (err < 0) | ||
550 | goto xfrm_proto_esp_failed; | ||
552 | err = xfrm4_protocol_register(&vti_ah4_protocol, IPPROTO_AH); | 551 | err = xfrm4_protocol_register(&vti_ah4_protocol, IPPROTO_AH); |
553 | if (err < 0) { | 552 | if (err < 0) |
554 | xfrm4_protocol_deregister(&vti_esp4_protocol, IPPROTO_ESP); | 553 | goto xfrm_proto_ah_failed; |
555 | unregister_pernet_device(&vti_net_ops); | ||
556 | pr_info("vti init: can't register tunnel\n"); | ||
557 | |||
558 | return err; | ||
559 | } | ||
560 | |||
561 | err = xfrm4_protocol_register(&vti_ipcomp4_protocol, IPPROTO_COMP); | 554 | err = xfrm4_protocol_register(&vti_ipcomp4_protocol, IPPROTO_COMP); |
562 | if (err < 0) { | 555 | if (err < 0) |
563 | xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH); | 556 | goto xfrm_proto_comp_failed; |
564 | xfrm4_protocol_deregister(&vti_esp4_protocol, IPPROTO_ESP); | ||
565 | unregister_pernet_device(&vti_net_ops); | ||
566 | pr_info("vti init: can't register tunnel\n"); | ||
567 | |||
568 | return err; | ||
569 | } | ||
570 | 557 | ||
558 | msg = "netlink interface"; | ||
571 | err = rtnl_link_register(&vti_link_ops); | 559 | err = rtnl_link_register(&vti_link_ops); |
572 | if (err < 0) | 560 | if (err < 0) |
573 | goto rtnl_link_failed; | 561 | goto rtnl_link_failed; |
@@ -576,23 +564,23 @@ static int __init vti_init(void) | |||
576 | 564 | ||
577 | rtnl_link_failed: | 565 | rtnl_link_failed: |
578 | xfrm4_protocol_deregister(&vti_ipcomp4_protocol, IPPROTO_COMP); | 566 | xfrm4_protocol_deregister(&vti_ipcomp4_protocol, IPPROTO_COMP); |
567 | xfrm_proto_comp_failed: | ||
579 | xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH); | 568 | xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH); |
569 | xfrm_proto_ah_failed: | ||
580 | xfrm4_protocol_deregister(&vti_esp4_protocol, IPPROTO_ESP); | 570 | xfrm4_protocol_deregister(&vti_esp4_protocol, IPPROTO_ESP); |
571 | xfrm_proto_esp_failed: | ||
581 | unregister_pernet_device(&vti_net_ops); | 572 | unregister_pernet_device(&vti_net_ops); |
573 | pernet_dev_failed: | ||
574 | pr_err("vti init: failed to register %s\n", msg); | ||
582 | return err; | 575 | return err; |
583 | } | 576 | } |
584 | 577 | ||
585 | static void __exit vti_fini(void) | 578 | static void __exit vti_fini(void) |
586 | { | 579 | { |
587 | rtnl_link_unregister(&vti_link_ops); | 580 | rtnl_link_unregister(&vti_link_ops); |
588 | if (xfrm4_protocol_deregister(&vti_ipcomp4_protocol, IPPROTO_COMP)) | 581 | xfrm4_protocol_deregister(&vti_ipcomp4_protocol, IPPROTO_COMP); |
589 | pr_info("vti close: can't deregister tunnel\n"); | 582 | xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH); |
590 | if (xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH)) | 583 | xfrm4_protocol_deregister(&vti_esp4_protocol, IPPROTO_ESP); |
591 | pr_info("vti close: can't deregister tunnel\n"); | ||
592 | if (xfrm4_protocol_deregister(&vti_esp4_protocol, IPPROTO_ESP)) | ||
593 | pr_info("vti close: can't deregister tunnel\n"); | ||
594 | |||
595 | |||
596 | unregister_pernet_device(&vti_net_ops); | 584 | unregister_pernet_device(&vti_net_ops); |
597 | } | 585 | } |
598 | 586 | ||
diff --git a/net/ipv4/ipconfig.c b/net/ipv4/ipconfig.c index b3e86ea7b71b..5bbef4fdcb43 100644 --- a/net/ipv4/ipconfig.c +++ b/net/ipv4/ipconfig.c | |||
@@ -143,8 +143,6 @@ __be32 ic_servaddr = NONE; /* Boot server IP address */ | |||
143 | __be32 root_server_addr = NONE; /* Address of NFS server */ | 143 | __be32 root_server_addr = NONE; /* Address of NFS server */ |
144 | u8 root_server_path[256] = { 0, }; /* Path to mount as root */ | 144 | u8 root_server_path[256] = { 0, }; /* Path to mount as root */ |
145 | 145 | ||
146 | __be32 ic_dev_xid; /* Device under configuration */ | ||
147 | |||
148 | /* vendor class identifier */ | 146 | /* vendor class identifier */ |
149 | static char vendor_class_identifier[253] __initdata; | 147 | static char vendor_class_identifier[253] __initdata; |
150 | 148 | ||
@@ -654,6 +652,7 @@ static struct packet_type bootp_packet_type __initdata = { | |||
654 | .func = ic_bootp_recv, | 652 | .func = ic_bootp_recv, |
655 | }; | 653 | }; |
656 | 654 | ||
655 | static __be32 ic_dev_xid; /* Device under configuration */ | ||
657 | 656 | ||
658 | /* | 657 | /* |
659 | * Initialize DHCP/BOOTP extension fields in the request. | 658 | * Initialize DHCP/BOOTP extension fields in the request. |
@@ -1218,10 +1217,10 @@ static int __init ic_dynamic(void) | |||
1218 | get_random_bytes(&timeout, sizeof(timeout)); | 1217 | get_random_bytes(&timeout, sizeof(timeout)); |
1219 | timeout = CONF_BASE_TIMEOUT + (timeout % (unsigned int) CONF_TIMEOUT_RANDOM); | 1218 | timeout = CONF_BASE_TIMEOUT + (timeout % (unsigned int) CONF_TIMEOUT_RANDOM); |
1220 | for (;;) { | 1219 | for (;;) { |
1220 | #ifdef IPCONFIG_BOOTP | ||
1221 | /* Track the device we are configuring */ | 1221 | /* Track the device we are configuring */ |
1222 | ic_dev_xid = d->xid; | 1222 | ic_dev_xid = d->xid; |
1223 | 1223 | ||
1224 | #ifdef IPCONFIG_BOOTP | ||
1225 | if (do_bootp && (d->able & IC_BOOTP)) | 1224 | if (do_bootp && (d->able & IC_BOOTP)) |
1226 | ic_bootp_send_if(d, jiffies - start_jiffies); | 1225 | ic_bootp_send_if(d, jiffies - start_jiffies); |
1227 | #endif | 1226 | #endif |
diff --git a/net/ipv4/ipmr.c b/net/ipv4/ipmr.c index 65bcaa789043..c8034587859d 100644 --- a/net/ipv4/ipmr.c +++ b/net/ipv4/ipmr.c | |||
@@ -500,7 +500,7 @@ static struct net_device *ipmr_reg_vif(struct net *net, struct mr_table *mrt) | |||
500 | else | 500 | else |
501 | sprintf(name, "pimreg%u", mrt->id); | 501 | sprintf(name, "pimreg%u", mrt->id); |
502 | 502 | ||
503 | dev = alloc_netdev(0, name, reg_vif_setup); | 503 | dev = alloc_netdev(0, name, NET_NAME_UNKNOWN, reg_vif_setup); |
504 | 504 | ||
505 | if (dev == NULL) | 505 | if (dev == NULL) |
506 | return NULL; | 506 | return NULL; |
diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig index a26ce035e3fa..7cbcaf4f0194 100644 --- a/net/ipv4/netfilter/Kconfig +++ b/net/ipv4/netfilter/Kconfig | |||
@@ -36,6 +36,16 @@ config NF_CONNTRACK_PROC_COMPAT | |||
36 | 36 | ||
37 | If unsure, say Y. | 37 | If unsure, say Y. |
38 | 38 | ||
39 | config NF_LOG_ARP | ||
40 | tristate "ARP packet logging" | ||
41 | default m if NETFILTER_ADVANCED=n | ||
42 | select NF_LOG_COMMON | ||
43 | |||
44 | config NF_LOG_IPV4 | ||
45 | tristate "IPv4 packet logging" | ||
46 | default m if NETFILTER_ADVANCED=n | ||
47 | select NF_LOG_COMMON | ||
48 | |||
39 | config NF_TABLES_IPV4 | 49 | config NF_TABLES_IPV4 |
40 | depends on NF_TABLES | 50 | depends on NF_TABLES |
41 | tristate "IPv4 nf_tables support" | 51 | tristate "IPv4 nf_tables support" |
@@ -72,6 +82,52 @@ config NF_TABLES_ARP | |||
72 | help | 82 | help |
73 | This option enables the ARP support for nf_tables. | 83 | This option enables the ARP support for nf_tables. |
74 | 84 | ||
85 | config NF_NAT_IPV4 | ||
86 | tristate "IPv4 NAT" | ||
87 | depends on NF_CONNTRACK_IPV4 | ||
88 | default m if NETFILTER_ADVANCED=n | ||
89 | select NF_NAT | ||
90 | help | ||
91 | The IPv4 NAT option allows masquerading, port forwarding and other | ||
92 | forms of full Network Address Port Translation. This can be | ||
93 | controlled by iptables or nft. | ||
94 | |||
95 | if NF_NAT_IPV4 | ||
96 | |||
97 | config NF_NAT_SNMP_BASIC | ||
98 | tristate "Basic SNMP-ALG support" | ||
99 | depends on NF_CONNTRACK_SNMP | ||
100 | depends on NETFILTER_ADVANCED | ||
101 | default NF_NAT && NF_CONNTRACK_SNMP | ||
102 | ---help--- | ||
103 | |||
104 | This module implements an Application Layer Gateway (ALG) for | ||
105 | SNMP payloads. In conjunction with NAT, it allows a network | ||
106 | management system to access multiple private networks with | ||
107 | conflicting addresses. It works by modifying IP addresses | ||
108 | inside SNMP payloads to match IP-layer NAT mapping. | ||
109 | |||
110 | This is the "basic" form of SNMP-ALG, as described in RFC 2962 | ||
111 | |||
112 | To compile it as a module, choose M here. If unsure, say N. | ||
113 | |||
114 | config NF_NAT_PROTO_GRE | ||
115 | tristate | ||
116 | depends on NF_CT_PROTO_GRE | ||
117 | |||
118 | config NF_NAT_PPTP | ||
119 | tristate | ||
120 | depends on NF_CONNTRACK | ||
121 | default NF_CONNTRACK_PPTP | ||
122 | select NF_NAT_PROTO_GRE | ||
123 | |||
124 | config NF_NAT_H323 | ||
125 | tristate | ||
126 | depends on NF_CONNTRACK | ||
127 | default NF_CONNTRACK_H323 | ||
128 | |||
129 | endif # NF_NAT_IPV4 | ||
130 | |||
75 | config IP_NF_IPTABLES | 131 | config IP_NF_IPTABLES |
76 | tristate "IP tables support (required for filtering/masq/NAT)" | 132 | tristate "IP tables support (required for filtering/masq/NAT)" |
77 | default m if NETFILTER_ADVANCED=n | 133 | default m if NETFILTER_ADVANCED=n |
@@ -159,39 +215,22 @@ config IP_NF_TARGET_SYNPROXY | |||
159 | 215 | ||
160 | To compile it as a module, choose M here. If unsure, say N. | 216 | To compile it as a module, choose M here. If unsure, say N. |
161 | 217 | ||
162 | config IP_NF_TARGET_ULOG | ||
163 | tristate "ULOG target support (obsolete)" | ||
164 | default m if NETFILTER_ADVANCED=n | ||
165 | ---help--- | ||
166 | |||
167 | This option enables the old IPv4-only "ipt_ULOG" implementation | ||
168 | which has been obsoleted by the new "nfnetlink_log" code (see | ||
169 | CONFIG_NETFILTER_NETLINK_LOG). | ||
170 | |||
171 | This option adds a `ULOG' target, which allows you to create rules in | ||
172 | any iptables table. The packet is passed to a userspace logging | ||
173 | daemon using netlink multicast sockets; unlike the LOG target | ||
174 | which can only be viewed through syslog. | ||
175 | |||
176 | The appropriate userspace logging daemon (ulogd) may be obtained from | ||
177 | <http://www.netfilter.org/projects/ulogd/index.html> | ||
178 | |||
179 | To compile it as a module, choose M here. If unsure, say N. | ||
180 | |||
181 | # NAT + specific targets: nf_conntrack | 218 | # NAT + specific targets: nf_conntrack |
182 | config NF_NAT_IPV4 | 219 | config IP_NF_NAT |
183 | tristate "IPv4 NAT" | 220 | tristate "iptables NAT support" |
184 | depends on NF_CONNTRACK_IPV4 | 221 | depends on NF_CONNTRACK_IPV4 |
185 | default m if NETFILTER_ADVANCED=n | 222 | default m if NETFILTER_ADVANCED=n |
186 | select NF_NAT | 223 | select NF_NAT |
224 | select NF_NAT_IPV4 | ||
225 | select NETFILTER_XT_NAT | ||
187 | help | 226 | help |
188 | The IPv4 NAT option allows masquerading, port forwarding and other | 227 | This enables the `nat' table in iptables. This allows masquerading, |
189 | forms of full Network Address Port Translation. It is controlled by | 228 | port forwarding and other forms of full Network Address Port |
190 | the `nat' table in iptables: see the man page for iptables(8). | 229 | Translation. |
191 | 230 | ||
192 | To compile it as a module, choose M here. If unsure, say N. | 231 | To compile it as a module, choose M here. If unsure, say N. |
193 | 232 | ||
194 | if NF_NAT_IPV4 | 233 | if IP_NF_NAT |
195 | 234 | ||
196 | config IP_NF_TARGET_MASQUERADE | 235 | config IP_NF_TARGET_MASQUERADE |
197 | tristate "MASQUERADE target support" | 236 | tristate "MASQUERADE target support" |
@@ -223,47 +262,7 @@ config IP_NF_TARGET_REDIRECT | |||
223 | (e.g. when running oldconfig). It selects | 262 | (e.g. when running oldconfig). It selects |
224 | CONFIG_NETFILTER_XT_TARGET_REDIRECT. | 263 | CONFIG_NETFILTER_XT_TARGET_REDIRECT. |
225 | 264 | ||
226 | endif | 265 | endif # IP_NF_NAT |
227 | |||
228 | config NF_NAT_SNMP_BASIC | ||
229 | tristate "Basic SNMP-ALG support" | ||
230 | depends on NF_CONNTRACK_SNMP && NF_NAT_IPV4 | ||
231 | depends on NETFILTER_ADVANCED | ||
232 | default NF_NAT && NF_CONNTRACK_SNMP | ||
233 | ---help--- | ||
234 | |||
235 | This module implements an Application Layer Gateway (ALG) for | ||
236 | SNMP payloads. In conjunction with NAT, it allows a network | ||
237 | management system to access multiple private networks with | ||
238 | conflicting addresses. It works by modifying IP addresses | ||
239 | inside SNMP payloads to match IP-layer NAT mapping. | ||
240 | |||
241 | This is the "basic" form of SNMP-ALG, as described in RFC 2962 | ||
242 | |||
243 | To compile it as a module, choose M here. If unsure, say N. | ||
244 | |||
245 | # If they want FTP, set to $CONFIG_IP_NF_NAT (m or y), | ||
246 | # or $CONFIG_IP_NF_FTP (m or y), whichever is weaker. | ||
247 | # From kconfig-language.txt: | ||
248 | # | ||
249 | # <expr> '&&' <expr> (6) | ||
250 | # | ||
251 | # (6) Returns the result of min(/expr/, /expr/). | ||
252 | |||
253 | config NF_NAT_PROTO_GRE | ||
254 | tristate | ||
255 | depends on NF_NAT_IPV4 && NF_CT_PROTO_GRE | ||
256 | |||
257 | config NF_NAT_PPTP | ||
258 | tristate | ||
259 | depends on NF_CONNTRACK && NF_NAT_IPV4 | ||
260 | default NF_NAT_IPV4 && NF_CONNTRACK_PPTP | ||
261 | select NF_NAT_PROTO_GRE | ||
262 | |||
263 | config NF_NAT_H323 | ||
264 | tristate | ||
265 | depends on NF_CONNTRACK && NF_NAT_IPV4 | ||
266 | default NF_NAT_IPV4 && NF_CONNTRACK_H323 | ||
267 | 266 | ||
268 | # mangle + specific targets | 267 | # mangle + specific targets |
269 | config IP_NF_MANGLE | 268 | config IP_NF_MANGLE |
diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile index 90b82405331e..edf4af32e9f2 100644 --- a/net/ipv4/netfilter/Makefile +++ b/net/ipv4/netfilter/Makefile | |||
@@ -19,6 +19,10 @@ obj-$(CONFIG_NF_NAT_IPV4) += nf_nat_ipv4.o | |||
19 | # defrag | 19 | # defrag |
20 | obj-$(CONFIG_NF_DEFRAG_IPV4) += nf_defrag_ipv4.o | 20 | obj-$(CONFIG_NF_DEFRAG_IPV4) += nf_defrag_ipv4.o |
21 | 21 | ||
22 | # logging | ||
23 | obj-$(CONFIG_NF_LOG_ARP) += nf_log_arp.o | ||
24 | obj-$(CONFIG_NF_LOG_IPV4) += nf_log_ipv4.o | ||
25 | |||
22 | # NAT helpers (nf_conntrack) | 26 | # NAT helpers (nf_conntrack) |
23 | obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o | 27 | obj-$(CONFIG_NF_NAT_H323) += nf_nat_h323.o |
24 | obj-$(CONFIG_NF_NAT_PPTP) += nf_nat_pptp.o | 28 | obj-$(CONFIG_NF_NAT_PPTP) += nf_nat_pptp.o |
@@ -39,7 +43,7 @@ obj-$(CONFIG_IP_NF_IPTABLES) += ip_tables.o | |||
39 | # the three instances of ip_tables | 43 | # the three instances of ip_tables |
40 | obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o | 44 | obj-$(CONFIG_IP_NF_FILTER) += iptable_filter.o |
41 | obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o | 45 | obj-$(CONFIG_IP_NF_MANGLE) += iptable_mangle.o |
42 | obj-$(CONFIG_NF_NAT_IPV4) += iptable_nat.o | 46 | obj-$(CONFIG_IP_NF_NAT) += iptable_nat.o |
43 | obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o | 47 | obj-$(CONFIG_IP_NF_RAW) += iptable_raw.o |
44 | obj-$(CONFIG_IP_NF_SECURITY) += iptable_security.o | 48 | obj-$(CONFIG_IP_NF_SECURITY) += iptable_security.o |
45 | 49 | ||
@@ -53,7 +57,6 @@ obj-$(CONFIG_IP_NF_TARGET_ECN) += ipt_ECN.o | |||
53 | obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o | 57 | obj-$(CONFIG_IP_NF_TARGET_MASQUERADE) += ipt_MASQUERADE.o |
54 | obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o | 58 | obj-$(CONFIG_IP_NF_TARGET_REJECT) += ipt_REJECT.o |
55 | obj-$(CONFIG_IP_NF_TARGET_SYNPROXY) += ipt_SYNPROXY.o | 59 | obj-$(CONFIG_IP_NF_TARGET_SYNPROXY) += ipt_SYNPROXY.o |
56 | obj-$(CONFIG_IP_NF_TARGET_ULOG) += ipt_ULOG.o | ||
57 | 60 | ||
58 | # generic ARP tables | 61 | # generic ARP tables |
59 | obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o | 62 | obj-$(CONFIG_IP_NF_ARPTABLES) += arp_tables.o |
diff --git a/net/ipv4/netfilter/ipt_ULOG.c b/net/ipv4/netfilter/ipt_ULOG.c deleted file mode 100644 index 9cb993cd224b..000000000000 --- a/net/ipv4/netfilter/ipt_ULOG.c +++ /dev/null | |||
@@ -1,498 +0,0 @@ | |||
1 | /* | ||
2 | * netfilter module for userspace packet logging daemons | ||
3 | * | ||
4 | * (C) 2000-2004 by Harald Welte <laforge@netfilter.org> | ||
5 | * (C) 1999-2001 Paul `Rusty' Russell | ||
6 | * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> | ||
7 | * (C) 2005-2007 Patrick McHardy <kaber@trash.net> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | * | ||
13 | * This module accepts two parameters: | ||
14 | * | ||
15 | * nlbufsiz: | ||
16 | * The parameter specifies how big the buffer for each netlink multicast | ||
17 | * group is. e.g. If you say nlbufsiz=8192, up to eight kb of packets will | ||
18 | * get accumulated in the kernel until they are sent to userspace. It is | ||
19 | * NOT possible to allocate more than 128kB, and it is strongly discouraged, | ||
20 | * because atomically allocating 128kB inside the network rx softirq is not | ||
21 | * reliable. Please also keep in mind that this buffer size is allocated for | ||
22 | * each nlgroup you are using, so the total kernel memory usage increases | ||
23 | * by that factor. | ||
24 | * | ||
25 | * Actually you should use nlbufsiz a bit smaller than PAGE_SIZE, since | ||
26 | * nlbufsiz is used with alloc_skb, which adds another | ||
27 | * sizeof(struct skb_shared_info). Use NLMSG_GOODSIZE instead. | ||
28 | * | ||
29 | * flushtimeout: | ||
30 | * Specify, after how many hundredths of a second the queue should be | ||
31 | * flushed even if it is not full yet. | ||
32 | */ | ||
33 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | ||
34 | #include <linux/module.h> | ||
35 | #include <linux/spinlock.h> | ||
36 | #include <linux/socket.h> | ||
37 | #include <linux/slab.h> | ||
38 | #include <linux/skbuff.h> | ||
39 | #include <linux/kernel.h> | ||
40 | #include <linux/timer.h> | ||
41 | #include <net/netlink.h> | ||
42 | #include <linux/netdevice.h> | ||
43 | #include <linux/mm.h> | ||
44 | #include <linux/moduleparam.h> | ||
45 | #include <linux/netfilter.h> | ||
46 | #include <linux/netfilter/x_tables.h> | ||
47 | #include <linux/netfilter_ipv4/ipt_ULOG.h> | ||
48 | #include <net/netfilter/nf_log.h> | ||
49 | #include <net/netns/generic.h> | ||
50 | #include <net/sock.h> | ||
51 | #include <linux/bitops.h> | ||
52 | #include <asm/unaligned.h> | ||
53 | |||
54 | MODULE_LICENSE("GPL"); | ||
55 | MODULE_AUTHOR("Harald Welte <laforge@gnumonks.org>"); | ||
56 | MODULE_DESCRIPTION("Xtables: packet logging to netlink using ULOG"); | ||
57 | MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_NFLOG); | ||
58 | |||
59 | #define ULOG_NL_EVENT 111 /* Harald's favorite number */ | ||
60 | #define ULOG_MAXNLGROUPS 32 /* numer of nlgroups */ | ||
61 | |||
62 | static unsigned int nlbufsiz = NLMSG_GOODSIZE; | ||
63 | module_param(nlbufsiz, uint, 0400); | ||
64 | MODULE_PARM_DESC(nlbufsiz, "netlink buffer size"); | ||
65 | |||
66 | static unsigned int flushtimeout = 10; | ||
67 | module_param(flushtimeout, uint, 0600); | ||
68 | MODULE_PARM_DESC(flushtimeout, "buffer flush timeout (hundredths of a second)"); | ||
69 | |||
70 | static bool nflog = true; | ||
71 | module_param(nflog, bool, 0400); | ||
72 | MODULE_PARM_DESC(nflog, "register as internal netfilter logging module"); | ||
73 | |||
74 | /* global data structures */ | ||
75 | |||
76 | typedef struct { | ||
77 | unsigned int qlen; /* number of nlmsgs' in the skb */ | ||
78 | struct nlmsghdr *lastnlh; /* netlink header of last msg in skb */ | ||
79 | struct sk_buff *skb; /* the pre-allocated skb */ | ||
80 | struct timer_list timer; /* the timer function */ | ||
81 | } ulog_buff_t; | ||
82 | |||
83 | static int ulog_net_id __read_mostly; | ||
84 | struct ulog_net { | ||
85 | unsigned int nlgroup[ULOG_MAXNLGROUPS]; | ||
86 | ulog_buff_t ulog_buffers[ULOG_MAXNLGROUPS]; | ||
87 | struct sock *nflognl; | ||
88 | spinlock_t lock; | ||
89 | }; | ||
90 | |||
91 | static struct ulog_net *ulog_pernet(struct net *net) | ||
92 | { | ||
93 | return net_generic(net, ulog_net_id); | ||
94 | } | ||
95 | |||
96 | /* send one ulog_buff_t to userspace */ | ||
97 | static void ulog_send(struct ulog_net *ulog, unsigned int nlgroupnum) | ||
98 | { | ||
99 | ulog_buff_t *ub = &ulog->ulog_buffers[nlgroupnum]; | ||
100 | |||
101 | pr_debug("ulog_send: timer is deleting\n"); | ||
102 | del_timer(&ub->timer); | ||
103 | |||
104 | if (!ub->skb) { | ||
105 | pr_debug("ulog_send: nothing to send\n"); | ||
106 | return; | ||
107 | } | ||
108 | |||
109 | /* last nlmsg needs NLMSG_DONE */ | ||
110 | if (ub->qlen > 1) | ||
111 | ub->lastnlh->nlmsg_type = NLMSG_DONE; | ||
112 | |||
113 | NETLINK_CB(ub->skb).dst_group = nlgroupnum + 1; | ||
114 | pr_debug("throwing %d packets to netlink group %u\n", | ||
115 | ub->qlen, nlgroupnum + 1); | ||
116 | netlink_broadcast(ulog->nflognl, ub->skb, 0, nlgroupnum + 1, | ||
117 | GFP_ATOMIC); | ||
118 | |||
119 | ub->qlen = 0; | ||
120 | ub->skb = NULL; | ||
121 | ub->lastnlh = NULL; | ||
122 | } | ||
123 | |||
124 | |||
125 | /* timer function to flush queue in flushtimeout time */ | ||
126 | static void ulog_timer(unsigned long data) | ||
127 | { | ||
128 | unsigned int groupnum = *((unsigned int *)data); | ||
129 | struct ulog_net *ulog = container_of((void *)data, | ||
130 | struct ulog_net, | ||
131 | nlgroup[groupnum]); | ||
132 | pr_debug("timer function called, calling ulog_send\n"); | ||
133 | |||
134 | /* lock to protect against somebody modifying our structure | ||
135 | * from ipt_ulog_target at the same time */ | ||
136 | spin_lock_bh(&ulog->lock); | ||
137 | ulog_send(ulog, groupnum); | ||
138 | spin_unlock_bh(&ulog->lock); | ||
139 | } | ||
140 | |||
141 | static struct sk_buff *ulog_alloc_skb(unsigned int size) | ||
142 | { | ||
143 | struct sk_buff *skb; | ||
144 | unsigned int n; | ||
145 | |||
146 | /* alloc skb which should be big enough for a whole | ||
147 | * multipart message. WARNING: has to be <= 131000 | ||
148 | * due to slab allocator restrictions */ | ||
149 | |||
150 | n = max(size, nlbufsiz); | ||
151 | skb = alloc_skb(n, GFP_ATOMIC | __GFP_NOWARN); | ||
152 | if (!skb) { | ||
153 | if (n > size) { | ||
154 | /* try to allocate only as much as we need for | ||
155 | * current packet */ | ||
156 | |||
157 | skb = alloc_skb(size, GFP_ATOMIC); | ||
158 | if (!skb) | ||
159 | pr_debug("cannot even allocate %ub\n", size); | ||
160 | } | ||
161 | } | ||
162 | |||
163 | return skb; | ||
164 | } | ||
165 | |||
166 | static void ipt_ulog_packet(struct net *net, | ||
167 | unsigned int hooknum, | ||
168 | const struct sk_buff *skb, | ||
169 | const struct net_device *in, | ||
170 | const struct net_device *out, | ||
171 | const struct ipt_ulog_info *loginfo, | ||
172 | const char *prefix) | ||
173 | { | ||
174 | ulog_buff_t *ub; | ||
175 | ulog_packet_msg_t *pm; | ||
176 | size_t size, copy_len; | ||
177 | struct nlmsghdr *nlh; | ||
178 | struct timeval tv; | ||
179 | struct ulog_net *ulog = ulog_pernet(net); | ||
180 | |||
181 | /* ffs == find first bit set, necessary because userspace | ||
182 | * is already shifting groupnumber, but we need unshifted. | ||
183 | * ffs() returns [1..32], we need [0..31] */ | ||
184 | unsigned int groupnum = ffs(loginfo->nl_group) - 1; | ||
185 | |||
186 | /* calculate the size of the skb needed */ | ||
187 | if (loginfo->copy_range == 0 || loginfo->copy_range > skb->len) | ||
188 | copy_len = skb->len; | ||
189 | else | ||
190 | copy_len = loginfo->copy_range; | ||
191 | |||
192 | size = nlmsg_total_size(sizeof(*pm) + copy_len); | ||
193 | |||
194 | ub = &ulog->ulog_buffers[groupnum]; | ||
195 | |||
196 | spin_lock_bh(&ulog->lock); | ||
197 | |||
198 | if (!ub->skb) { | ||
199 | if (!(ub->skb = ulog_alloc_skb(size))) | ||
200 | goto alloc_failure; | ||
201 | } else if (ub->qlen >= loginfo->qthreshold || | ||
202 | size > skb_tailroom(ub->skb)) { | ||
203 | /* either the queue len is too high or we don't have | ||
204 | * enough room in nlskb left. send it to userspace. */ | ||
205 | |||
206 | ulog_send(ulog, groupnum); | ||
207 | |||
208 | if (!(ub->skb = ulog_alloc_skb(size))) | ||
209 | goto alloc_failure; | ||
210 | } | ||
211 | |||
212 | pr_debug("qlen %d, qthreshold %Zu\n", ub->qlen, loginfo->qthreshold); | ||
213 | |||
214 | nlh = nlmsg_put(ub->skb, 0, ub->qlen, ULOG_NL_EVENT, | ||
215 | sizeof(*pm)+copy_len, 0); | ||
216 | if (!nlh) { | ||
217 | pr_debug("error during nlmsg_put\n"); | ||
218 | goto out_unlock; | ||
219 | } | ||
220 | ub->qlen++; | ||
221 | |||
222 | pm = nlmsg_data(nlh); | ||
223 | memset(pm, 0, sizeof(*pm)); | ||
224 | |||
225 | /* We might not have a timestamp, get one */ | ||
226 | if (skb->tstamp.tv64 == 0) | ||
227 | __net_timestamp((struct sk_buff *)skb); | ||
228 | |||
229 | /* copy hook, prefix, timestamp, payload, etc. */ | ||
230 | pm->data_len = copy_len; | ||
231 | tv = ktime_to_timeval(skb->tstamp); | ||
232 | put_unaligned(tv.tv_sec, &pm->timestamp_sec); | ||
233 | put_unaligned(tv.tv_usec, &pm->timestamp_usec); | ||
234 | put_unaligned(skb->mark, &pm->mark); | ||
235 | pm->hook = hooknum; | ||
236 | if (prefix != NULL) { | ||
237 | strncpy(pm->prefix, prefix, sizeof(pm->prefix) - 1); | ||
238 | pm->prefix[sizeof(pm->prefix) - 1] = '\0'; | ||
239 | } | ||
240 | else if (loginfo->prefix[0] != '\0') | ||
241 | strncpy(pm->prefix, loginfo->prefix, sizeof(pm->prefix)); | ||
242 | |||
243 | if (in && in->hard_header_len > 0 && | ||
244 | skb->mac_header != skb->network_header && | ||
245 | in->hard_header_len <= ULOG_MAC_LEN) { | ||
246 | memcpy(pm->mac, skb_mac_header(skb), in->hard_header_len); | ||
247 | pm->mac_len = in->hard_header_len; | ||
248 | } else | ||
249 | pm->mac_len = 0; | ||
250 | |||
251 | if (in) | ||
252 | strncpy(pm->indev_name, in->name, sizeof(pm->indev_name)); | ||
253 | |||
254 | if (out) | ||
255 | strncpy(pm->outdev_name, out->name, sizeof(pm->outdev_name)); | ||
256 | |||
257 | /* copy_len <= skb->len, so can't fail. */ | ||
258 | if (skb_copy_bits(skb, 0, pm->payload, copy_len) < 0) | ||
259 | BUG(); | ||
260 | |||
261 | /* check if we are building multi-part messages */ | ||
262 | if (ub->qlen > 1) | ||
263 | ub->lastnlh->nlmsg_flags |= NLM_F_MULTI; | ||
264 | |||
265 | ub->lastnlh = nlh; | ||
266 | |||
267 | /* if timer isn't already running, start it */ | ||
268 | if (!timer_pending(&ub->timer)) { | ||
269 | ub->timer.expires = jiffies + flushtimeout * HZ / 100; | ||
270 | add_timer(&ub->timer); | ||
271 | } | ||
272 | |||
273 | /* if threshold is reached, send message to userspace */ | ||
274 | if (ub->qlen >= loginfo->qthreshold) { | ||
275 | if (loginfo->qthreshold > 1) | ||
276 | nlh->nlmsg_type = NLMSG_DONE; | ||
277 | ulog_send(ulog, groupnum); | ||
278 | } | ||
279 | out_unlock: | ||
280 | spin_unlock_bh(&ulog->lock); | ||
281 | |||
282 | return; | ||
283 | |||
284 | alloc_failure: | ||
285 | pr_debug("Error building netlink message\n"); | ||
286 | spin_unlock_bh(&ulog->lock); | ||
287 | } | ||
288 | |||
289 | static unsigned int | ||
290 | ulog_tg(struct sk_buff *skb, const struct xt_action_param *par) | ||
291 | { | ||
292 | struct net *net = dev_net(par->in ? par->in : par->out); | ||
293 | |||
294 | ipt_ulog_packet(net, par->hooknum, skb, par->in, par->out, | ||
295 | par->targinfo, NULL); | ||
296 | return XT_CONTINUE; | ||
297 | } | ||
298 | |||
299 | static void ipt_logfn(struct net *net, | ||
300 | u_int8_t pf, | ||
301 | unsigned int hooknum, | ||
302 | const struct sk_buff *skb, | ||
303 | const struct net_device *in, | ||
304 | const struct net_device *out, | ||
305 | const struct nf_loginfo *li, | ||
306 | const char *prefix) | ||
307 | { | ||
308 | struct ipt_ulog_info loginfo; | ||
309 | |||
310 | if (!li || li->type != NF_LOG_TYPE_ULOG) { | ||
311 | loginfo.nl_group = ULOG_DEFAULT_NLGROUP; | ||
312 | loginfo.copy_range = 0; | ||
313 | loginfo.qthreshold = ULOG_DEFAULT_QTHRESHOLD; | ||
314 | loginfo.prefix[0] = '\0'; | ||
315 | } else { | ||
316 | loginfo.nl_group = li->u.ulog.group; | ||
317 | loginfo.copy_range = li->u.ulog.copy_len; | ||
318 | loginfo.qthreshold = li->u.ulog.qthreshold; | ||
319 | strlcpy(loginfo.prefix, prefix, sizeof(loginfo.prefix)); | ||
320 | } | ||
321 | |||
322 | ipt_ulog_packet(net, hooknum, skb, in, out, &loginfo, prefix); | ||
323 | } | ||
324 | |||
325 | static int ulog_tg_check(const struct xt_tgchk_param *par) | ||
326 | { | ||
327 | const struct ipt_ulog_info *loginfo = par->targinfo; | ||
328 | |||
329 | if (!par->net->xt.ulog_warn_deprecated) { | ||
330 | pr_info("ULOG is deprecated and it will be removed soon, " | ||
331 | "use NFLOG instead\n"); | ||
332 | par->net->xt.ulog_warn_deprecated = true; | ||
333 | } | ||
334 | |||
335 | if (loginfo->prefix[sizeof(loginfo->prefix) - 1] != '\0') { | ||
336 | pr_debug("prefix not null-terminated\n"); | ||
337 | return -EINVAL; | ||
338 | } | ||
339 | if (loginfo->qthreshold > ULOG_MAX_QLEN) { | ||
340 | pr_debug("queue threshold %Zu > MAX_QLEN\n", | ||
341 | loginfo->qthreshold); | ||
342 | return -EINVAL; | ||
343 | } | ||
344 | return 0; | ||
345 | } | ||
346 | |||
347 | #ifdef CONFIG_COMPAT | ||
348 | struct compat_ipt_ulog_info { | ||
349 | compat_uint_t nl_group; | ||
350 | compat_size_t copy_range; | ||
351 | compat_size_t qthreshold; | ||
352 | char prefix[ULOG_PREFIX_LEN]; | ||
353 | }; | ||
354 | |||
355 | static void ulog_tg_compat_from_user(void *dst, const void *src) | ||
356 | { | ||
357 | const struct compat_ipt_ulog_info *cl = src; | ||
358 | struct ipt_ulog_info l = { | ||
359 | .nl_group = cl->nl_group, | ||
360 | .copy_range = cl->copy_range, | ||
361 | .qthreshold = cl->qthreshold, | ||
362 | }; | ||
363 | |||
364 | memcpy(l.prefix, cl->prefix, sizeof(l.prefix)); | ||
365 | memcpy(dst, &l, sizeof(l)); | ||
366 | } | ||
367 | |||
368 | static int ulog_tg_compat_to_user(void __user *dst, const void *src) | ||
369 | { | ||
370 | const struct ipt_ulog_info *l = src; | ||
371 | struct compat_ipt_ulog_info cl = { | ||
372 | .nl_group = l->nl_group, | ||
373 | .copy_range = l->copy_range, | ||
374 | .qthreshold = l->qthreshold, | ||
375 | }; | ||
376 | |||
377 | memcpy(cl.prefix, l->prefix, sizeof(cl.prefix)); | ||
378 | return copy_to_user(dst, &cl, sizeof(cl)) ? -EFAULT : 0; | ||
379 | } | ||
380 | #endif /* CONFIG_COMPAT */ | ||
381 | |||
382 | static struct xt_target ulog_tg_reg __read_mostly = { | ||
383 | .name = "ULOG", | ||
384 | .family = NFPROTO_IPV4, | ||
385 | .target = ulog_tg, | ||
386 | .targetsize = sizeof(struct ipt_ulog_info), | ||
387 | .checkentry = ulog_tg_check, | ||
388 | #ifdef CONFIG_COMPAT | ||
389 | .compatsize = sizeof(struct compat_ipt_ulog_info), | ||
390 | .compat_from_user = ulog_tg_compat_from_user, | ||
391 | .compat_to_user = ulog_tg_compat_to_user, | ||
392 | #endif | ||
393 | .me = THIS_MODULE, | ||
394 | }; | ||
395 | |||
396 | static struct nf_logger ipt_ulog_logger __read_mostly = { | ||
397 | .name = "ipt_ULOG", | ||
398 | .logfn = ipt_logfn, | ||
399 | .me = THIS_MODULE, | ||
400 | }; | ||
401 | |||
402 | static int __net_init ulog_tg_net_init(struct net *net) | ||
403 | { | ||
404 | int i; | ||
405 | struct ulog_net *ulog = ulog_pernet(net); | ||
406 | struct netlink_kernel_cfg cfg = { | ||
407 | .groups = ULOG_MAXNLGROUPS, | ||
408 | }; | ||
409 | |||
410 | spin_lock_init(&ulog->lock); | ||
411 | /* initialize ulog_buffers */ | ||
412 | for (i = 0; i < ULOG_MAXNLGROUPS; i++) { | ||
413 | ulog->nlgroup[i] = i; | ||
414 | setup_timer(&ulog->ulog_buffers[i].timer, ulog_timer, | ||
415 | (unsigned long)&ulog->nlgroup[i]); | ||
416 | } | ||
417 | |||
418 | ulog->nflognl = netlink_kernel_create(net, NETLINK_NFLOG, &cfg); | ||
419 | if (!ulog->nflognl) | ||
420 | return -ENOMEM; | ||
421 | |||
422 | if (nflog) | ||
423 | nf_log_set(net, NFPROTO_IPV4, &ipt_ulog_logger); | ||
424 | |||
425 | return 0; | ||
426 | } | ||
427 | |||
428 | static void __net_exit ulog_tg_net_exit(struct net *net) | ||
429 | { | ||
430 | ulog_buff_t *ub; | ||
431 | int i; | ||
432 | struct ulog_net *ulog = ulog_pernet(net); | ||
433 | |||
434 | if (nflog) | ||
435 | nf_log_unset(net, &ipt_ulog_logger); | ||
436 | |||
437 | netlink_kernel_release(ulog->nflognl); | ||
438 | |||
439 | /* remove pending timers and free allocated skb's */ | ||
440 | for (i = 0; i < ULOG_MAXNLGROUPS; i++) { | ||
441 | ub = &ulog->ulog_buffers[i]; | ||
442 | pr_debug("timer is deleting\n"); | ||
443 | del_timer(&ub->timer); | ||
444 | |||
445 | if (ub->skb) { | ||
446 | kfree_skb(ub->skb); | ||
447 | ub->skb = NULL; | ||
448 | } | ||
449 | } | ||
450 | } | ||
451 | |||
452 | static struct pernet_operations ulog_tg_net_ops = { | ||
453 | .init = ulog_tg_net_init, | ||
454 | .exit = ulog_tg_net_exit, | ||
455 | .id = &ulog_net_id, | ||
456 | .size = sizeof(struct ulog_net), | ||
457 | }; | ||
458 | |||
459 | static int __init ulog_tg_init(void) | ||
460 | { | ||
461 | int ret; | ||
462 | pr_debug("init module\n"); | ||
463 | |||
464 | if (nlbufsiz > 128*1024) { | ||
465 | pr_warn("Netlink buffer has to be <= 128kB\n"); | ||
466 | return -EINVAL; | ||
467 | } | ||
468 | |||
469 | ret = register_pernet_subsys(&ulog_tg_net_ops); | ||
470 | if (ret) | ||
471 | goto out_pernet; | ||
472 | |||
473 | ret = xt_register_target(&ulog_tg_reg); | ||
474 | if (ret < 0) | ||
475 | goto out_target; | ||
476 | |||
477 | if (nflog) | ||
478 | nf_log_register(NFPROTO_IPV4, &ipt_ulog_logger); | ||
479 | |||
480 | return 0; | ||
481 | |||
482 | out_target: | ||
483 | unregister_pernet_subsys(&ulog_tg_net_ops); | ||
484 | out_pernet: | ||
485 | return ret; | ||
486 | } | ||
487 | |||
488 | static void __exit ulog_tg_exit(void) | ||
489 | { | ||
490 | pr_debug("cleanup_module\n"); | ||
491 | if (nflog) | ||
492 | nf_log_unregister(&ipt_ulog_logger); | ||
493 | xt_unregister_target(&ulog_tg_reg); | ||
494 | unregister_pernet_subsys(&ulog_tg_net_ops); | ||
495 | } | ||
496 | |||
497 | module_init(ulog_tg_init); | ||
498 | module_exit(ulog_tg_exit); | ||
diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c index 8127dc802865..a054fe083431 100644 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | |||
@@ -314,7 +314,7 @@ getorigdst(struct sock *sk, int optval, void __user *user, int *len) | |||
314 | return -ENOENT; | 314 | return -ENOENT; |
315 | } | 315 | } |
316 | 316 | ||
317 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 317 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
318 | 318 | ||
319 | #include <linux/netfilter/nfnetlink.h> | 319 | #include <linux/netfilter/nfnetlink.h> |
320 | #include <linux/netfilter/nfnetlink_conntrack.h> | 320 | #include <linux/netfilter/nfnetlink_conntrack.h> |
@@ -358,7 +358,7 @@ static struct nf_sockopt_ops so_getorigdst = { | |||
358 | .pf = PF_INET, | 358 | .pf = PF_INET, |
359 | .get_optmin = SO_ORIGINAL_DST, | 359 | .get_optmin = SO_ORIGINAL_DST, |
360 | .get_optmax = SO_ORIGINAL_DST+1, | 360 | .get_optmax = SO_ORIGINAL_DST+1, |
361 | .get = &getorigdst, | 361 | .get = getorigdst, |
362 | .owner = THIS_MODULE, | 362 | .owner = THIS_MODULE, |
363 | }; | 363 | }; |
364 | 364 | ||
@@ -388,7 +388,7 @@ struct nf_conntrack_l3proto nf_conntrack_l3proto_ipv4 __read_mostly = { | |||
388 | .invert_tuple = ipv4_invert_tuple, | 388 | .invert_tuple = ipv4_invert_tuple, |
389 | .print_tuple = ipv4_print_tuple, | 389 | .print_tuple = ipv4_print_tuple, |
390 | .get_l4proto = ipv4_get_l4proto, | 390 | .get_l4proto = ipv4_get_l4proto, |
391 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 391 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
392 | .tuple_to_nlattr = ipv4_tuple_to_nlattr, | 392 | .tuple_to_nlattr = ipv4_tuple_to_nlattr, |
393 | .nlattr_tuple_size = ipv4_nlattr_tuple_size, | 393 | .nlattr_tuple_size = ipv4_nlattr_tuple_size, |
394 | .nlattr_to_tuple = ipv4_nlattr_to_tuple, | 394 | .nlattr_to_tuple = ipv4_nlattr_to_tuple, |
diff --git a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c index a338dad41b7d..b91b2641adda 100644 --- a/net/ipv4/netfilter/nf_conntrack_proto_icmp.c +++ b/net/ipv4/netfilter/nf_conntrack_proto_icmp.c | |||
@@ -226,7 +226,7 @@ icmp_error(struct net *net, struct nf_conn *tmpl, | |||
226 | return icmp_error_message(net, tmpl, skb, ctinfo, hooknum); | 226 | return icmp_error_message(net, tmpl, skb, ctinfo, hooknum); |
227 | } | 227 | } |
228 | 228 | ||
229 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 229 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
230 | 230 | ||
231 | #include <linux/netfilter/nfnetlink.h> | 231 | #include <linux/netfilter/nfnetlink.h> |
232 | #include <linux/netfilter/nfnetlink_conntrack.h> | 232 | #include <linux/netfilter/nfnetlink_conntrack.h> |
@@ -408,7 +408,7 @@ struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp __read_mostly = | |||
408 | .error = icmp_error, | 408 | .error = icmp_error, |
409 | .destroy = NULL, | 409 | .destroy = NULL, |
410 | .me = NULL, | 410 | .me = NULL, |
411 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 411 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
412 | .tuple_to_nlattr = icmp_tuple_to_nlattr, | 412 | .tuple_to_nlattr = icmp_tuple_to_nlattr, |
413 | .nlattr_tuple_size = icmp_nlattr_tuple_size, | 413 | .nlattr_tuple_size = icmp_nlattr_tuple_size, |
414 | .nlattr_to_tuple = icmp_nlattr_to_tuple, | 414 | .nlattr_to_tuple = icmp_nlattr_to_tuple, |
diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c index b8f6381c7d0b..76bd1aef257f 100644 --- a/net/ipv4/netfilter/nf_defrag_ipv4.c +++ b/net/ipv4/netfilter/nf_defrag_ipv4.c | |||
@@ -17,7 +17,7 @@ | |||
17 | #include <linux/netfilter_bridge.h> | 17 | #include <linux/netfilter_bridge.h> |
18 | #include <linux/netfilter_ipv4.h> | 18 | #include <linux/netfilter_ipv4.h> |
19 | #include <net/netfilter/ipv4/nf_defrag_ipv4.h> | 19 | #include <net/netfilter/ipv4/nf_defrag_ipv4.h> |
20 | #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) | 20 | #if IS_ENABLED(CONFIG_NF_CONNTRACK) |
21 | #include <net/netfilter/nf_conntrack.h> | 21 | #include <net/netfilter/nf_conntrack.h> |
22 | #endif | 22 | #endif |
23 | #include <net/netfilter/nf_conntrack_zones.h> | 23 | #include <net/netfilter/nf_conntrack_zones.h> |
@@ -45,7 +45,7 @@ static enum ip_defrag_users nf_ct_defrag_user(unsigned int hooknum, | |||
45 | { | 45 | { |
46 | u16 zone = NF_CT_DEFAULT_ZONE; | 46 | u16 zone = NF_CT_DEFAULT_ZONE; |
47 | 47 | ||
48 | #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) | 48 | #if IS_ENABLED(CONFIG_NF_CONNTRACK) |
49 | if (skb->nfct) | 49 | if (skb->nfct) |
50 | zone = nf_ct_zone((struct nf_conn *)skb->nfct); | 50 | zone = nf_ct_zone((struct nf_conn *)skb->nfct); |
51 | #endif | 51 | #endif |
@@ -74,8 +74,8 @@ static unsigned int ipv4_conntrack_defrag(const struct nf_hook_ops *ops, | |||
74 | inet->nodefrag) | 74 | inet->nodefrag) |
75 | return NF_ACCEPT; | 75 | return NF_ACCEPT; |
76 | 76 | ||
77 | #if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) | 77 | #if IS_ENABLED(CONFIG_NF_CONNTRACK) |
78 | #if !defined(CONFIG_NF_NAT) && !defined(CONFIG_NF_NAT_MODULE) | 78 | #if !IS_ENABLED(CONFIG_NF_NAT) |
79 | /* Previously seen (loopback)? Ignore. Do this before | 79 | /* Previously seen (loopback)? Ignore. Do this before |
80 | fragment check. */ | 80 | fragment check. */ |
81 | if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct)) | 81 | if (skb->nfct && !nf_ct_is_template((struct nf_conn *)skb->nfct)) |
diff --git a/net/ipv4/netfilter/nf_log_arp.c b/net/ipv4/netfilter/nf_log_arp.c new file mode 100644 index 000000000000..ccfc78db12ee --- /dev/null +++ b/net/ipv4/netfilter/nf_log_arp.c | |||
@@ -0,0 +1,149 @@ | |||
1 | /* | ||
2 | * (C) 2014 by Pablo Neira Ayuso <pablo@netfilter.org> | ||
3 | * | ||
4 | * Based on code from ebt_log from: | ||
5 | * | ||
6 | * Bart De Schuymer <bdschuym@pandora.be> | ||
7 | * Harald Welte <laforge@netfilter.org> | ||
8 | * | ||
9 | * This program is free software; you can redistribute it and/or modify | ||
10 | * it under the terms of the GNU General Public License version 2 as | ||
11 | * published by the Free Software Foundation. | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/spinlock.h> | ||
16 | #include <linux/skbuff.h> | ||
17 | #include <linux/if_arp.h> | ||
18 | #include <linux/ip.h> | ||
19 | #include <net/route.h> | ||
20 | |||
21 | #include <linux/netfilter.h> | ||
22 | #include <linux/netfilter/xt_LOG.h> | ||
23 | #include <net/netfilter/nf_log.h> | ||
24 | |||
25 | static struct nf_loginfo default_loginfo = { | ||
26 | .type = NF_LOG_TYPE_LOG, | ||
27 | .u = { | ||
28 | .log = { | ||
29 | .level = 5, | ||
30 | .logflags = NF_LOG_MASK, | ||
31 | }, | ||
32 | }, | ||
33 | }; | ||
34 | |||
35 | struct arppayload { | ||
36 | unsigned char mac_src[ETH_ALEN]; | ||
37 | unsigned char ip_src[4]; | ||
38 | unsigned char mac_dst[ETH_ALEN]; | ||
39 | unsigned char ip_dst[4]; | ||
40 | }; | ||
41 | |||
42 | static void dump_arp_packet(struct nf_log_buf *m, | ||
43 | const struct nf_loginfo *info, | ||
44 | const struct sk_buff *skb, unsigned int nhoff) | ||
45 | { | ||
46 | const struct arphdr *ah; | ||
47 | struct arphdr _arph; | ||
48 | const struct arppayload *ap; | ||
49 | struct arppayload _arpp; | ||
50 | |||
51 | ah = skb_header_pointer(skb, 0, sizeof(_arph), &_arph); | ||
52 | if (ah == NULL) { | ||
53 | nf_log_buf_add(m, "TRUNCATED"); | ||
54 | return; | ||
55 | } | ||
56 | nf_log_buf_add(m, "ARP HTYPE=%d PTYPE=0x%04x OPCODE=%d", | ||
57 | ntohs(ah->ar_hrd), ntohs(ah->ar_pro), ntohs(ah->ar_op)); | ||
58 | |||
59 | /* If it's for Ethernet and the lengths are OK, then log the ARP | ||
60 | * payload. | ||
61 | */ | ||
62 | if (ah->ar_hrd != htons(1) || | ||
63 | ah->ar_hln != ETH_ALEN || | ||
64 | ah->ar_pln != sizeof(__be32)) | ||
65 | return; | ||
66 | |||
67 | ap = skb_header_pointer(skb, sizeof(_arph), sizeof(_arpp), &_arpp); | ||
68 | if (ap == NULL) { | ||
69 | nf_log_buf_add(m, " INCOMPLETE [%Zu bytes]", | ||
70 | skb->len - sizeof(_arph)); | ||
71 | return; | ||
72 | } | ||
73 | nf_log_buf_add(m, " MACSRC=%pM IPSRC=%pI4 MACDST=%pM IPDST=%pI4", | ||
74 | ap->mac_src, ap->ip_src, ap->mac_dst, ap->ip_dst); | ||
75 | } | ||
76 | |||
77 | void nf_log_arp_packet(struct net *net, u_int8_t pf, | ||
78 | unsigned int hooknum, const struct sk_buff *skb, | ||
79 | const struct net_device *in, | ||
80 | const struct net_device *out, | ||
81 | const struct nf_loginfo *loginfo, | ||
82 | const char *prefix) | ||
83 | { | ||
84 | struct nf_log_buf *m; | ||
85 | |||
86 | /* FIXME: Disabled from containers until syslog ns is supported */ | ||
87 | if (!net_eq(net, &init_net)) | ||
88 | return; | ||
89 | |||
90 | m = nf_log_buf_open(); | ||
91 | |||
92 | if (!loginfo) | ||
93 | loginfo = &default_loginfo; | ||
94 | |||
95 | nf_log_dump_packet_common(m, pf, hooknum, skb, in, out, loginfo, | ||
96 | prefix); | ||
97 | dump_arp_packet(m, loginfo, skb, 0); | ||
98 | |||
99 | nf_log_buf_close(m); | ||
100 | } | ||
101 | |||
102 | static struct nf_logger nf_arp_logger __read_mostly = { | ||
103 | .name = "nf_log_arp", | ||
104 | .type = NF_LOG_TYPE_LOG, | ||
105 | .logfn = nf_log_arp_packet, | ||
106 | .me = THIS_MODULE, | ||
107 | }; | ||
108 | |||
109 | static int __net_init nf_log_arp_net_init(struct net *net) | ||
110 | { | ||
111 | nf_log_set(net, NFPROTO_ARP, &nf_arp_logger); | ||
112 | return 0; | ||
113 | } | ||
114 | |||
115 | static void __net_exit nf_log_arp_net_exit(struct net *net) | ||
116 | { | ||
117 | nf_log_unset(net, &nf_arp_logger); | ||
118 | } | ||
119 | |||
120 | static struct pernet_operations nf_log_arp_net_ops = { | ||
121 | .init = nf_log_arp_net_init, | ||
122 | .exit = nf_log_arp_net_exit, | ||
123 | }; | ||
124 | |||
125 | static int __init nf_log_arp_init(void) | ||
126 | { | ||
127 | int ret; | ||
128 | |||
129 | ret = register_pernet_subsys(&nf_log_arp_net_ops); | ||
130 | if (ret < 0) | ||
131 | return ret; | ||
132 | |||
133 | nf_log_register(NFPROTO_ARP, &nf_arp_logger); | ||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static void __exit nf_log_arp_exit(void) | ||
138 | { | ||
139 | unregister_pernet_subsys(&nf_log_arp_net_ops); | ||
140 | nf_log_unregister(&nf_arp_logger); | ||
141 | } | ||
142 | |||
143 | module_init(nf_log_arp_init); | ||
144 | module_exit(nf_log_arp_exit); | ||
145 | |||
146 | MODULE_AUTHOR("Pablo Neira Ayuso <pablo@netfilter.org>"); | ||
147 | MODULE_DESCRIPTION("Netfilter ARP packet logging"); | ||
148 | MODULE_LICENSE("GPL"); | ||
149 | MODULE_ALIAS_NF_LOGGER(3, 0); | ||
diff --git a/net/ipv4/netfilter/nf_log_ipv4.c b/net/ipv4/netfilter/nf_log_ipv4.c new file mode 100644 index 000000000000..078bdca1b607 --- /dev/null +++ b/net/ipv4/netfilter/nf_log_ipv4.c | |||
@@ -0,0 +1,385 @@ | |||
1 | /* (C) 1999-2001 Paul `Rusty' Russell | ||
2 | * (C) 2002-2004 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 | #include <linux/module.h> | ||
10 | #include <linux/spinlock.h> | ||
11 | #include <linux/skbuff.h> | ||
12 | #include <linux/if_arp.h> | ||
13 | #include <linux/ip.h> | ||
14 | #include <net/ipv6.h> | ||
15 | #include <net/icmp.h> | ||
16 | #include <net/udp.h> | ||
17 | #include <net/tcp.h> | ||
18 | #include <net/route.h> | ||
19 | |||
20 | #include <linux/netfilter.h> | ||
21 | #include <linux/netfilter/xt_LOG.h> | ||
22 | #include <net/netfilter/nf_log.h> | ||
23 | |||
24 | static struct nf_loginfo default_loginfo = { | ||
25 | .type = NF_LOG_TYPE_LOG, | ||
26 | .u = { | ||
27 | .log = { | ||
28 | .level = 5, | ||
29 | .logflags = NF_LOG_MASK, | ||
30 | }, | ||
31 | }, | ||
32 | }; | ||
33 | |||
34 | /* One level of recursion won't kill us */ | ||
35 | static void dump_ipv4_packet(struct nf_log_buf *m, | ||
36 | const struct nf_loginfo *info, | ||
37 | const struct sk_buff *skb, unsigned int iphoff) | ||
38 | { | ||
39 | struct iphdr _iph; | ||
40 | const struct iphdr *ih; | ||
41 | unsigned int logflags; | ||
42 | |||
43 | if (info->type == NF_LOG_TYPE_LOG) | ||
44 | logflags = info->u.log.logflags; | ||
45 | else | ||
46 | logflags = NF_LOG_MASK; | ||
47 | |||
48 | ih = skb_header_pointer(skb, iphoff, sizeof(_iph), &_iph); | ||
49 | if (ih == NULL) { | ||
50 | nf_log_buf_add(m, "TRUNCATED"); | ||
51 | return; | ||
52 | } | ||
53 | |||
54 | /* Important fields: | ||
55 | * TOS, len, DF/MF, fragment offset, TTL, src, dst, options. */ | ||
56 | /* Max length: 40 "SRC=255.255.255.255 DST=255.255.255.255 " */ | ||
57 | nf_log_buf_add(m, "SRC=%pI4 DST=%pI4 ", &ih->saddr, &ih->daddr); | ||
58 | |||
59 | /* Max length: 46 "LEN=65535 TOS=0xFF PREC=0xFF TTL=255 ID=65535 " */ | ||
60 | nf_log_buf_add(m, "LEN=%u TOS=0x%02X PREC=0x%02X TTL=%u ID=%u ", | ||
61 | ntohs(ih->tot_len), ih->tos & IPTOS_TOS_MASK, | ||
62 | ih->tos & IPTOS_PREC_MASK, ih->ttl, ntohs(ih->id)); | ||
63 | |||
64 | /* Max length: 6 "CE DF MF " */ | ||
65 | if (ntohs(ih->frag_off) & IP_CE) | ||
66 | nf_log_buf_add(m, "CE "); | ||
67 | if (ntohs(ih->frag_off) & IP_DF) | ||
68 | nf_log_buf_add(m, "DF "); | ||
69 | if (ntohs(ih->frag_off) & IP_MF) | ||
70 | nf_log_buf_add(m, "MF "); | ||
71 | |||
72 | /* Max length: 11 "FRAG:65535 " */ | ||
73 | if (ntohs(ih->frag_off) & IP_OFFSET) | ||
74 | nf_log_buf_add(m, "FRAG:%u ", ntohs(ih->frag_off) & IP_OFFSET); | ||
75 | |||
76 | if ((logflags & XT_LOG_IPOPT) && | ||
77 | ih->ihl * 4 > sizeof(struct iphdr)) { | ||
78 | const unsigned char *op; | ||
79 | unsigned char _opt[4 * 15 - sizeof(struct iphdr)]; | ||
80 | unsigned int i, optsize; | ||
81 | |||
82 | optsize = ih->ihl * 4 - sizeof(struct iphdr); | ||
83 | op = skb_header_pointer(skb, iphoff+sizeof(_iph), | ||
84 | optsize, _opt); | ||
85 | if (op == NULL) { | ||
86 | nf_log_buf_add(m, "TRUNCATED"); | ||
87 | return; | ||
88 | } | ||
89 | |||
90 | /* Max length: 127 "OPT (" 15*4*2chars ") " */ | ||
91 | nf_log_buf_add(m, "OPT ("); | ||
92 | for (i = 0; i < optsize; i++) | ||
93 | nf_log_buf_add(m, "%02X", op[i]); | ||
94 | nf_log_buf_add(m, ") "); | ||
95 | } | ||
96 | |||
97 | switch (ih->protocol) { | ||
98 | case IPPROTO_TCP: | ||
99 | if (nf_log_dump_tcp_header(m, skb, ih->protocol, | ||
100 | ntohs(ih->frag_off) & IP_OFFSET, | ||
101 | iphoff+ih->ihl*4, logflags)) | ||
102 | return; | ||
103 | break; | ||
104 | case IPPROTO_UDP: | ||
105 | case IPPROTO_UDPLITE: | ||
106 | if (nf_log_dump_udp_header(m, skb, ih->protocol, | ||
107 | ntohs(ih->frag_off) & IP_OFFSET, | ||
108 | iphoff+ih->ihl*4)) | ||
109 | return; | ||
110 | break; | ||
111 | case IPPROTO_ICMP: { | ||
112 | struct icmphdr _icmph; | ||
113 | const struct icmphdr *ich; | ||
114 | static const size_t required_len[NR_ICMP_TYPES+1] | ||
115 | = { [ICMP_ECHOREPLY] = 4, | ||
116 | [ICMP_DEST_UNREACH] | ||
117 | = 8 + sizeof(struct iphdr), | ||
118 | [ICMP_SOURCE_QUENCH] | ||
119 | = 8 + sizeof(struct iphdr), | ||
120 | [ICMP_REDIRECT] | ||
121 | = 8 + sizeof(struct iphdr), | ||
122 | [ICMP_ECHO] = 4, | ||
123 | [ICMP_TIME_EXCEEDED] | ||
124 | = 8 + sizeof(struct iphdr), | ||
125 | [ICMP_PARAMETERPROB] | ||
126 | = 8 + sizeof(struct iphdr), | ||
127 | [ICMP_TIMESTAMP] = 20, | ||
128 | [ICMP_TIMESTAMPREPLY] = 20, | ||
129 | [ICMP_ADDRESS] = 12, | ||
130 | [ICMP_ADDRESSREPLY] = 12 }; | ||
131 | |||
132 | /* Max length: 11 "PROTO=ICMP " */ | ||
133 | nf_log_buf_add(m, "PROTO=ICMP "); | ||
134 | |||
135 | if (ntohs(ih->frag_off) & IP_OFFSET) | ||
136 | break; | ||
137 | |||
138 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ | ||
139 | ich = skb_header_pointer(skb, iphoff + ih->ihl * 4, | ||
140 | sizeof(_icmph), &_icmph); | ||
141 | if (ich == NULL) { | ||
142 | nf_log_buf_add(m, "INCOMPLETE [%u bytes] ", | ||
143 | skb->len - iphoff - ih->ihl*4); | ||
144 | break; | ||
145 | } | ||
146 | |||
147 | /* Max length: 18 "TYPE=255 CODE=255 " */ | ||
148 | nf_log_buf_add(m, "TYPE=%u CODE=%u ", ich->type, ich->code); | ||
149 | |||
150 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ | ||
151 | if (ich->type <= NR_ICMP_TYPES && | ||
152 | required_len[ich->type] && | ||
153 | skb->len-iphoff-ih->ihl*4 < required_len[ich->type]) { | ||
154 | nf_log_buf_add(m, "INCOMPLETE [%u bytes] ", | ||
155 | skb->len - iphoff - ih->ihl*4); | ||
156 | break; | ||
157 | } | ||
158 | |||
159 | switch (ich->type) { | ||
160 | case ICMP_ECHOREPLY: | ||
161 | case ICMP_ECHO: | ||
162 | /* Max length: 19 "ID=65535 SEQ=65535 " */ | ||
163 | nf_log_buf_add(m, "ID=%u SEQ=%u ", | ||
164 | ntohs(ich->un.echo.id), | ||
165 | ntohs(ich->un.echo.sequence)); | ||
166 | break; | ||
167 | |||
168 | case ICMP_PARAMETERPROB: | ||
169 | /* Max length: 14 "PARAMETER=255 " */ | ||
170 | nf_log_buf_add(m, "PARAMETER=%u ", | ||
171 | ntohl(ich->un.gateway) >> 24); | ||
172 | break; | ||
173 | case ICMP_REDIRECT: | ||
174 | /* Max length: 24 "GATEWAY=255.255.255.255 " */ | ||
175 | nf_log_buf_add(m, "GATEWAY=%pI4 ", &ich->un.gateway); | ||
176 | /* Fall through */ | ||
177 | case ICMP_DEST_UNREACH: | ||
178 | case ICMP_SOURCE_QUENCH: | ||
179 | case ICMP_TIME_EXCEEDED: | ||
180 | /* Max length: 3+maxlen */ | ||
181 | if (!iphoff) { /* Only recurse once. */ | ||
182 | nf_log_buf_add(m, "["); | ||
183 | dump_ipv4_packet(m, info, skb, | ||
184 | iphoff + ih->ihl*4+sizeof(_icmph)); | ||
185 | nf_log_buf_add(m, "] "); | ||
186 | } | ||
187 | |||
188 | /* Max length: 10 "MTU=65535 " */ | ||
189 | if (ich->type == ICMP_DEST_UNREACH && | ||
190 | ich->code == ICMP_FRAG_NEEDED) { | ||
191 | nf_log_buf_add(m, "MTU=%u ", | ||
192 | ntohs(ich->un.frag.mtu)); | ||
193 | } | ||
194 | } | ||
195 | break; | ||
196 | } | ||
197 | /* Max Length */ | ||
198 | case IPPROTO_AH: { | ||
199 | struct ip_auth_hdr _ahdr; | ||
200 | const struct ip_auth_hdr *ah; | ||
201 | |||
202 | if (ntohs(ih->frag_off) & IP_OFFSET) | ||
203 | break; | ||
204 | |||
205 | /* Max length: 9 "PROTO=AH " */ | ||
206 | nf_log_buf_add(m, "PROTO=AH "); | ||
207 | |||
208 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ | ||
209 | ah = skb_header_pointer(skb, iphoff+ih->ihl*4, | ||
210 | sizeof(_ahdr), &_ahdr); | ||
211 | if (ah == NULL) { | ||
212 | nf_log_buf_add(m, "INCOMPLETE [%u bytes] ", | ||
213 | skb->len - iphoff - ih->ihl*4); | ||
214 | break; | ||
215 | } | ||
216 | |||
217 | /* Length: 15 "SPI=0xF1234567 " */ | ||
218 | nf_log_buf_add(m, "SPI=0x%x ", ntohl(ah->spi)); | ||
219 | break; | ||
220 | } | ||
221 | case IPPROTO_ESP: { | ||
222 | struct ip_esp_hdr _esph; | ||
223 | const struct ip_esp_hdr *eh; | ||
224 | |||
225 | /* Max length: 10 "PROTO=ESP " */ | ||
226 | nf_log_buf_add(m, "PROTO=ESP "); | ||
227 | |||
228 | if (ntohs(ih->frag_off) & IP_OFFSET) | ||
229 | break; | ||
230 | |||
231 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ | ||
232 | eh = skb_header_pointer(skb, iphoff+ih->ihl*4, | ||
233 | sizeof(_esph), &_esph); | ||
234 | if (eh == NULL) { | ||
235 | nf_log_buf_add(m, "INCOMPLETE [%u bytes] ", | ||
236 | skb->len - iphoff - ih->ihl*4); | ||
237 | break; | ||
238 | } | ||
239 | |||
240 | /* Length: 15 "SPI=0xF1234567 " */ | ||
241 | nf_log_buf_add(m, "SPI=0x%x ", ntohl(eh->spi)); | ||
242 | break; | ||
243 | } | ||
244 | /* Max length: 10 "PROTO 255 " */ | ||
245 | default: | ||
246 | nf_log_buf_add(m, "PROTO=%u ", ih->protocol); | ||
247 | } | ||
248 | |||
249 | /* Max length: 15 "UID=4294967295 " */ | ||
250 | if ((logflags & XT_LOG_UID) && !iphoff) | ||
251 | nf_log_dump_sk_uid_gid(m, skb->sk); | ||
252 | |||
253 | /* Max length: 16 "MARK=0xFFFFFFFF " */ | ||
254 | if (!iphoff && skb->mark) | ||
255 | nf_log_buf_add(m, "MARK=0x%x ", skb->mark); | ||
256 | |||
257 | /* Proto Max log string length */ | ||
258 | /* IP: 40+46+6+11+127 = 230 */ | ||
259 | /* TCP: 10+max(25,20+30+13+9+32+11+127) = 252 */ | ||
260 | /* UDP: 10+max(25,20) = 35 */ | ||
261 | /* UDPLITE: 14+max(25,20) = 39 */ | ||
262 | /* ICMP: 11+max(25, 18+25+max(19,14,24+3+n+10,3+n+10)) = 91+n */ | ||
263 | /* ESP: 10+max(25)+15 = 50 */ | ||
264 | /* AH: 9+max(25)+15 = 49 */ | ||
265 | /* unknown: 10 */ | ||
266 | |||
267 | /* (ICMP allows recursion one level deep) */ | ||
268 | /* maxlen = IP + ICMP + IP + max(TCP,UDP,ICMP,unknown) */ | ||
269 | /* maxlen = 230+ 91 + 230 + 252 = 803 */ | ||
270 | } | ||
271 | |||
272 | static void dump_ipv4_mac_header(struct nf_log_buf *m, | ||
273 | const struct nf_loginfo *info, | ||
274 | const struct sk_buff *skb) | ||
275 | { | ||
276 | struct net_device *dev = skb->dev; | ||
277 | unsigned int logflags = 0; | ||
278 | |||
279 | if (info->type == NF_LOG_TYPE_LOG) | ||
280 | logflags = info->u.log.logflags; | ||
281 | |||
282 | if (!(logflags & XT_LOG_MACDECODE)) | ||
283 | goto fallback; | ||
284 | |||
285 | switch (dev->type) { | ||
286 | case ARPHRD_ETHER: | ||
287 | nf_log_buf_add(m, "MACSRC=%pM MACDST=%pM MACPROTO=%04x ", | ||
288 | eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, | ||
289 | ntohs(eth_hdr(skb)->h_proto)); | ||
290 | return; | ||
291 | default: | ||
292 | break; | ||
293 | } | ||
294 | |||
295 | fallback: | ||
296 | nf_log_buf_add(m, "MAC="); | ||
297 | if (dev->hard_header_len && | ||
298 | skb->mac_header != skb->network_header) { | ||
299 | const unsigned char *p = skb_mac_header(skb); | ||
300 | unsigned int i; | ||
301 | |||
302 | nf_log_buf_add(m, "%02x", *p++); | ||
303 | for (i = 1; i < dev->hard_header_len; i++, p++) | ||
304 | nf_log_buf_add(m, ":%02x", *p); | ||
305 | } | ||
306 | nf_log_buf_add(m, " "); | ||
307 | } | ||
308 | |||
309 | static void nf_log_ip_packet(struct net *net, u_int8_t pf, | ||
310 | unsigned int hooknum, const struct sk_buff *skb, | ||
311 | const struct net_device *in, | ||
312 | const struct net_device *out, | ||
313 | const struct nf_loginfo *loginfo, | ||
314 | const char *prefix) | ||
315 | { | ||
316 | struct nf_log_buf *m; | ||
317 | |||
318 | /* FIXME: Disabled from containers until syslog ns is supported */ | ||
319 | if (!net_eq(net, &init_net)) | ||
320 | return; | ||
321 | |||
322 | m = nf_log_buf_open(); | ||
323 | |||
324 | if (!loginfo) | ||
325 | loginfo = &default_loginfo; | ||
326 | |||
327 | nf_log_dump_packet_common(m, pf, hooknum, skb, in, | ||
328 | out, loginfo, prefix); | ||
329 | |||
330 | if (in != NULL) | ||
331 | dump_ipv4_mac_header(m, loginfo, skb); | ||
332 | |||
333 | dump_ipv4_packet(m, loginfo, skb, 0); | ||
334 | |||
335 | nf_log_buf_close(m); | ||
336 | } | ||
337 | |||
338 | static struct nf_logger nf_ip_logger __read_mostly = { | ||
339 | .name = "nf_log_ipv4", | ||
340 | .type = NF_LOG_TYPE_LOG, | ||
341 | .logfn = nf_log_ip_packet, | ||
342 | .me = THIS_MODULE, | ||
343 | }; | ||
344 | |||
345 | static int __net_init nf_log_ipv4_net_init(struct net *net) | ||
346 | { | ||
347 | nf_log_set(net, NFPROTO_IPV4, &nf_ip_logger); | ||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | static void __net_exit nf_log_ipv4_net_exit(struct net *net) | ||
352 | { | ||
353 | nf_log_unset(net, &nf_ip_logger); | ||
354 | } | ||
355 | |||
356 | static struct pernet_operations nf_log_ipv4_net_ops = { | ||
357 | .init = nf_log_ipv4_net_init, | ||
358 | .exit = nf_log_ipv4_net_exit, | ||
359 | }; | ||
360 | |||
361 | static int __init nf_log_ipv4_init(void) | ||
362 | { | ||
363 | int ret; | ||
364 | |||
365 | ret = register_pernet_subsys(&nf_log_ipv4_net_ops); | ||
366 | if (ret < 0) | ||
367 | return ret; | ||
368 | |||
369 | nf_log_register(NFPROTO_IPV4, &nf_ip_logger); | ||
370 | return 0; | ||
371 | } | ||
372 | |||
373 | static void __exit nf_log_ipv4_exit(void) | ||
374 | { | ||
375 | unregister_pernet_subsys(&nf_log_ipv4_net_ops); | ||
376 | nf_log_unregister(&nf_ip_logger); | ||
377 | } | ||
378 | |||
379 | module_init(nf_log_ipv4_init); | ||
380 | module_exit(nf_log_ipv4_exit); | ||
381 | |||
382 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); | ||
383 | MODULE_DESCRIPTION("Netfilter IPv4 packet logging"); | ||
384 | MODULE_LICENSE("GPL"); | ||
385 | MODULE_ALIAS_NF_LOGGER(AF_INET, 0); | ||
diff --git a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c index d8b2e14efddc..14f5ccd06337 100644 --- a/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c +++ b/net/ipv4/netfilter/nf_nat_l3proto_ipv4.c | |||
@@ -154,6 +154,7 @@ static void nf_nat_ipv4_csum_recalc(struct sk_buff *skb, | |||
154 | htons(oldlen), htons(datalen), 1); | 154 | htons(oldlen), htons(datalen), 1); |
155 | } | 155 | } |
156 | 156 | ||
157 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) | ||
157 | static int nf_nat_ipv4_nlattr_to_range(struct nlattr *tb[], | 158 | static int nf_nat_ipv4_nlattr_to_range(struct nlattr *tb[], |
158 | struct nf_nat_range *range) | 159 | struct nf_nat_range *range) |
159 | { | 160 | { |
@@ -169,6 +170,7 @@ static int nf_nat_ipv4_nlattr_to_range(struct nlattr *tb[], | |||
169 | 170 | ||
170 | return 0; | 171 | return 0; |
171 | } | 172 | } |
173 | #endif | ||
172 | 174 | ||
173 | static const struct nf_nat_l3proto nf_nat_l3proto_ipv4 = { | 175 | static const struct nf_nat_l3proto nf_nat_l3proto_ipv4 = { |
174 | .l3proto = NFPROTO_IPV4, | 176 | .l3proto = NFPROTO_IPV4, |
@@ -177,7 +179,9 @@ static const struct nf_nat_l3proto nf_nat_l3proto_ipv4 = { | |||
177 | .manip_pkt = nf_nat_ipv4_manip_pkt, | 179 | .manip_pkt = nf_nat_ipv4_manip_pkt, |
178 | .csum_update = nf_nat_ipv4_csum_update, | 180 | .csum_update = nf_nat_ipv4_csum_update, |
179 | .csum_recalc = nf_nat_ipv4_csum_recalc, | 181 | .csum_recalc = nf_nat_ipv4_csum_recalc, |
182 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) | ||
180 | .nlattr_to_range = nf_nat_ipv4_nlattr_to_range, | 183 | .nlattr_to_range = nf_nat_ipv4_nlattr_to_range, |
184 | #endif | ||
181 | #ifdef CONFIG_XFRM | 185 | #ifdef CONFIG_XFRM |
182 | .decode_session = nf_nat_ipv4_decode_session, | 186 | .decode_session = nf_nat_ipv4_decode_session, |
183 | #endif | 187 | #endif |
diff --git a/net/ipv4/netfilter/nf_nat_proto_gre.c b/net/ipv4/netfilter/nf_nat_proto_gre.c index 690d890111bb..9414923f1e15 100644 --- a/net/ipv4/netfilter/nf_nat_proto_gre.c +++ b/net/ipv4/netfilter/nf_nat_proto_gre.c | |||
@@ -124,7 +124,7 @@ static const struct nf_nat_l4proto gre = { | |||
124 | .manip_pkt = gre_manip_pkt, | 124 | .manip_pkt = gre_manip_pkt, |
125 | .in_range = nf_nat_l4proto_in_range, | 125 | .in_range = nf_nat_l4proto_in_range, |
126 | .unique_tuple = gre_unique_tuple, | 126 | .unique_tuple = gre_unique_tuple, |
127 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 127 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
128 | .nlattr_to_range = nf_nat_l4proto_nlattr_to_range, | 128 | .nlattr_to_range = nf_nat_l4proto_nlattr_to_range, |
129 | #endif | 129 | #endif |
130 | }; | 130 | }; |
diff --git a/net/ipv4/netfilter/nf_nat_proto_icmp.c b/net/ipv4/netfilter/nf_nat_proto_icmp.c index eb303471bcf6..4557b4ab8342 100644 --- a/net/ipv4/netfilter/nf_nat_proto_icmp.c +++ b/net/ipv4/netfilter/nf_nat_proto_icmp.c | |||
@@ -77,7 +77,7 @@ const struct nf_nat_l4proto nf_nat_l4proto_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 IS_ENABLED(CONFIG_NF_CT_NETLINK) |
81 | .nlattr_to_range = nf_nat_l4proto_nlattr_to_range, | 81 | .nlattr_to_range = nf_nat_l4proto_nlattr_to_range, |
82 | #endif | 82 | #endif |
83 | }; | 83 | }; |
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 044a0ddf6a79..a3c59a077a5f 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c | |||
@@ -911,7 +911,7 @@ int ping_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
911 | sin6->sin6_flowinfo = ip6_flowinfo(ip6); | 911 | sin6->sin6_flowinfo = ip6_flowinfo(ip6); |
912 | sin6->sin6_scope_id = | 912 | sin6->sin6_scope_id = |
913 | ipv6_iface_scope_id(&sin6->sin6_addr, | 913 | ipv6_iface_scope_id(&sin6->sin6_addr, |
914 | IP6CB(skb)->iif); | 914 | inet6_iif(skb)); |
915 | *addr_len = sizeof(*sin6); | 915 | *addr_len = sizeof(*sin6); |
916 | } | 916 | } |
917 | 917 | ||
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index ae0af9386f7c..8e3eb39f84e7 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c | |||
@@ -52,6 +52,7 @@ | |||
52 | static int sockstat_seq_show(struct seq_file *seq, void *v) | 52 | static int sockstat_seq_show(struct seq_file *seq, void *v) |
53 | { | 53 | { |
54 | struct net *net = seq->private; | 54 | struct net *net = seq->private; |
55 | unsigned int frag_mem; | ||
55 | int orphans, sockets; | 56 | int orphans, sockets; |
56 | 57 | ||
57 | local_bh_disable(); | 58 | local_bh_disable(); |
@@ -71,8 +72,8 @@ static int sockstat_seq_show(struct seq_file *seq, void *v) | |||
71 | sock_prot_inuse_get(net, &udplite_prot)); | 72 | sock_prot_inuse_get(net, &udplite_prot)); |
72 | seq_printf(seq, "RAW: inuse %d\n", | 73 | seq_printf(seq, "RAW: inuse %d\n", |
73 | sock_prot_inuse_get(net, &raw_prot)); | 74 | sock_prot_inuse_get(net, &raw_prot)); |
74 | seq_printf(seq, "FRAG: inuse %d memory %d\n", | 75 | frag_mem = ip_frag_mem(net); |
75 | ip_frag_nqueues(net), ip_frag_mem(net)); | 76 | seq_printf(seq, "FRAG: inuse %u memory %u\n", !!frag_mem, frag_mem); |
76 | return 0; | 77 | return 0; |
77 | } | 78 | } |
78 | 79 | ||
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index 2c65160565e1..739db3100c23 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
@@ -58,6 +58,7 @@ | |||
58 | #include <linux/in_route.h> | 58 | #include <linux/in_route.h> |
59 | #include <linux/route.h> | 59 | #include <linux/route.h> |
60 | #include <linux/skbuff.h> | 60 | #include <linux/skbuff.h> |
61 | #include <linux/igmp.h> | ||
61 | #include <net/net_namespace.h> | 62 | #include <net/net_namespace.h> |
62 | #include <net/dst.h> | 63 | #include <net/dst.h> |
63 | #include <net/sock.h> | 64 | #include <net/sock.h> |
@@ -174,7 +175,9 @@ static int raw_v4_input(struct sk_buff *skb, const struct iphdr *iph, int hash) | |||
174 | 175 | ||
175 | while (sk) { | 176 | while (sk) { |
176 | delivered = 1; | 177 | delivered = 1; |
177 | if (iph->protocol != IPPROTO_ICMP || !icmp_filter(sk, skb)) { | 178 | if ((iph->protocol != IPPROTO_ICMP || !icmp_filter(sk, skb)) && |
179 | ip_mc_sf_allow(sk, iph->daddr, iph->saddr, | ||
180 | skb->dev->ifindex)) { | ||
178 | struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC); | 181 | struct sk_buff *clone = skb_clone(skb, GFP_ATOMIC); |
179 | 182 | ||
180 | /* Not releasing hash table! */ | 183 | /* Not releasing hash table! */ |
@@ -365,6 +368,8 @@ static int raw_send_hdrinc(struct sock *sk, struct flowi4 *fl4, | |||
365 | 368 | ||
366 | skb->ip_summed = CHECKSUM_NONE; | 369 | skb->ip_summed = CHECKSUM_NONE; |
367 | 370 | ||
371 | sock_tx_timestamp(sk, &skb_shinfo(skb)->tx_flags); | ||
372 | |||
368 | skb->transport_header = skb->network_header; | 373 | skb->transport_header = skb->network_header; |
369 | err = -EFAULT; | 374 | err = -EFAULT; |
370 | if (memcpy_fromiovecend((void *)iph, from, 0, length)) | 375 | if (memcpy_fromiovecend((void *)iph, from, 0, length)) |
@@ -606,6 +611,8 @@ back_from_confirm: | |||
606 | &rt, msg->msg_flags); | 611 | &rt, msg->msg_flags); |
607 | 612 | ||
608 | else { | 613 | else { |
614 | sock_tx_timestamp(sk, &ipc.tx_flags); | ||
615 | |||
609 | if (!ipc.addr) | 616 | if (!ipc.addr) |
610 | ipc.addr = fl4.daddr; | 617 | ipc.addr = fl4.daddr; |
611 | lock_sock(sk); | 618 | lock_sock(sk); |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 190199851c9a..cbadb942c332 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -746,7 +746,7 @@ static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flow | |||
746 | } | 746 | } |
747 | 747 | ||
748 | n = ipv4_neigh_lookup(&rt->dst, NULL, &new_gw); | 748 | n = ipv4_neigh_lookup(&rt->dst, NULL, &new_gw); |
749 | if (n) { | 749 | if (!IS_ERR(n)) { |
750 | if (!(n->nud_state & NUD_VALID)) { | 750 | if (!(n->nud_state & NUD_VALID)) { |
751 | neigh_event_send(n, NULL); | 751 | neigh_event_send(n, NULL); |
752 | } else { | 752 | } else { |
@@ -1798,8 +1798,6 @@ local_input: | |||
1798 | no_route: | 1798 | no_route: |
1799 | RT_CACHE_STAT_INC(in_no_route); | 1799 | RT_CACHE_STAT_INC(in_no_route); |
1800 | res.type = RTN_UNREACHABLE; | 1800 | res.type = RTN_UNREACHABLE; |
1801 | if (err == -ESRCH) | ||
1802 | err = -ENETUNREACH; | ||
1803 | goto local_input; | 1801 | goto local_input; |
1804 | 1802 | ||
1805 | /* | 1803 | /* |
@@ -2267,9 +2265,9 @@ struct rtable *ip_route_output_flow(struct net *net, struct flowi4 *flp4, | |||
2267 | return rt; | 2265 | return rt; |
2268 | 2266 | ||
2269 | if (flp4->flowi4_proto) | 2267 | if (flp4->flowi4_proto) |
2270 | rt = (struct rtable *) xfrm_lookup(net, &rt->dst, | 2268 | rt = (struct rtable *)xfrm_lookup_route(net, &rt->dst, |
2271 | flowi4_to_flowi(flp4), | 2269 | flowi4_to_flowi(flp4), |
2272 | sk, 0); | 2270 | sk, 0); |
2273 | 2271 | ||
2274 | return rt; | 2272 | return rt; |
2275 | } | 2273 | } |
diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c index c86624b36a62..c0c75688896e 100644 --- a/net/ipv4/syncookies.c +++ b/net/ipv4/syncookies.c | |||
@@ -170,7 +170,8 @@ u32 __cookie_v4_init_sequence(const struct iphdr *iph, const struct tcphdr *th, | |||
170 | } | 170 | } |
171 | EXPORT_SYMBOL_GPL(__cookie_v4_init_sequence); | 171 | EXPORT_SYMBOL_GPL(__cookie_v4_init_sequence); |
172 | 172 | ||
173 | __u32 cookie_v4_init_sequence(struct sock *sk, struct sk_buff *skb, __u16 *mssp) | 173 | __u32 cookie_v4_init_sequence(struct sock *sk, const struct sk_buff *skb, |
174 | __u16 *mssp) | ||
174 | { | 175 | { |
175 | const struct iphdr *iph = ip_hdr(skb); | 176 | const struct iphdr *iph = ip_hdr(skb); |
176 | const struct tcphdr *th = tcp_hdr(skb); | 177 | const struct tcphdr *th = tcp_hdr(skb); |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 9d2118e5fbc7..541f26a67ba2 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
@@ -426,6 +426,17 @@ void tcp_init_sock(struct sock *sk) | |||
426 | } | 426 | } |
427 | EXPORT_SYMBOL(tcp_init_sock); | 427 | EXPORT_SYMBOL(tcp_init_sock); |
428 | 428 | ||
429 | static void tcp_tx_timestamp(struct sock *sk, struct sk_buff *skb) | ||
430 | { | ||
431 | if (sk->sk_tsflags) { | ||
432 | struct skb_shared_info *shinfo = skb_shinfo(skb); | ||
433 | |||
434 | sock_tx_timestamp(sk, &shinfo->tx_flags); | ||
435 | if (shinfo->tx_flags & SKBTX_ANY_TSTAMP) | ||
436 | shinfo->tskey = TCP_SKB_CB(skb)->seq + skb->len - 1; | ||
437 | } | ||
438 | } | ||
439 | |||
429 | /* | 440 | /* |
430 | * Wait for a TCP event. | 441 | * Wait for a TCP event. |
431 | * | 442 | * |
@@ -523,7 +534,7 @@ unsigned int tcp_poll(struct file *file, struct socket *sock, poll_table *wait) | |||
523 | } | 534 | } |
524 | /* This barrier is coupled with smp_wmb() in tcp_reset() */ | 535 | /* This barrier is coupled with smp_wmb() in tcp_reset() */ |
525 | smp_rmb(); | 536 | smp_rmb(); |
526 | if (sk->sk_err) | 537 | if (sk->sk_err || !skb_queue_empty(&sk->sk_error_queue)) |
527 | mask |= POLLERR; | 538 | mask |= POLLERR; |
528 | 539 | ||
529 | return mask; | 540 | return mask; |
@@ -959,8 +970,10 @@ new_segment: | |||
959 | 970 | ||
960 | copied += copy; | 971 | copied += copy; |
961 | offset += copy; | 972 | offset += copy; |
962 | if (!(size -= copy)) | 973 | if (!(size -= copy)) { |
974 | tcp_tx_timestamp(sk, skb); | ||
963 | goto out; | 975 | goto out; |
976 | } | ||
964 | 977 | ||
965 | if (skb->len < size_goal || (flags & MSG_OOB)) | 978 | if (skb->len < size_goal || (flags & MSG_OOB)) |
966 | continue; | 979 | continue; |
@@ -1175,13 +1188,6 @@ new_segment: | |||
1175 | goto wait_for_memory; | 1188 | goto wait_for_memory; |
1176 | 1189 | ||
1177 | /* | 1190 | /* |
1178 | * All packets are restored as if they have | ||
1179 | * already been sent. | ||
1180 | */ | ||
1181 | if (tp->repair) | ||
1182 | TCP_SKB_CB(skb)->when = tcp_time_stamp; | ||
1183 | |||
1184 | /* | ||
1185 | * Check whether we can use HW checksum. | 1191 | * Check whether we can use HW checksum. |
1186 | */ | 1192 | */ |
1187 | if (sk->sk_route_caps & NETIF_F_ALL_CSUM) | 1193 | if (sk->sk_route_caps & NETIF_F_ALL_CSUM) |
@@ -1190,6 +1196,13 @@ new_segment: | |||
1190 | skb_entail(sk, skb); | 1196 | skb_entail(sk, skb); |
1191 | copy = size_goal; | 1197 | copy = size_goal; |
1192 | max = size_goal; | 1198 | max = size_goal; |
1199 | |||
1200 | /* All packets are restored as if they have | ||
1201 | * already been sent. skb_mstamp isn't set to | ||
1202 | * avoid wrong rtt estimation. | ||
1203 | */ | ||
1204 | if (tp->repair) | ||
1205 | TCP_SKB_CB(skb)->sacked |= TCPCB_REPAIRED; | ||
1193 | } | 1206 | } |
1194 | 1207 | ||
1195 | /* Try to append data to the end of skb. */ | 1208 | /* Try to append data to the end of skb. */ |
@@ -1252,8 +1265,10 @@ new_segment: | |||
1252 | 1265 | ||
1253 | from += copy; | 1266 | from += copy; |
1254 | copied += copy; | 1267 | copied += copy; |
1255 | if ((seglen -= copy) == 0 && iovlen == 0) | 1268 | if ((seglen -= copy) == 0 && iovlen == 0) { |
1269 | tcp_tx_timestamp(sk, skb); | ||
1256 | goto out; | 1270 | goto out; |
1271 | } | ||
1257 | 1272 | ||
1258 | if (skb->len < max || (flags & MSG_OOB) || unlikely(tp->repair)) | 1273 | if (skb->len < max || (flags & MSG_OOB) || unlikely(tp->repair)) |
1259 | continue; | 1274 | continue; |
@@ -1617,6 +1632,9 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
1617 | struct sk_buff *skb; | 1632 | struct sk_buff *skb; |
1618 | u32 urg_hole = 0; | 1633 | u32 urg_hole = 0; |
1619 | 1634 | ||
1635 | if (unlikely(flags & MSG_ERRQUEUE)) | ||
1636 | return ip_recv_error(sk, msg, len, addr_len); | ||
1637 | |||
1620 | if (sk_can_busy_loop(sk) && skb_queue_empty(&sk->sk_receive_queue) && | 1638 | if (sk_can_busy_loop(sk) && skb_queue_empty(&sk->sk_receive_queue) && |
1621 | (sk->sk_state == TCP_ESTABLISHED)) | 1639 | (sk->sk_state == TCP_ESTABLISHED)) |
1622 | sk_busy_loop(sk, nonblock); | 1640 | sk_busy_loop(sk, nonblock); |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 40639c288dc2..a906e0200ff2 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -74,6 +74,7 @@ | |||
74 | #include <linux/ipsec.h> | 74 | #include <linux/ipsec.h> |
75 | #include <asm/unaligned.h> | 75 | #include <asm/unaligned.h> |
76 | #include <net/netdma.h> | 76 | #include <net/netdma.h> |
77 | #include <linux/errqueue.h> | ||
77 | 78 | ||
78 | int sysctl_tcp_timestamps __read_mostly = 1; | 79 | int sysctl_tcp_timestamps __read_mostly = 1; |
79 | int sysctl_tcp_window_scaling __read_mostly = 1; | 80 | int sysctl_tcp_window_scaling __read_mostly = 1; |
@@ -1904,16 +1905,17 @@ void tcp_clear_retrans(struct tcp_sock *tp) | |||
1904 | tp->sacked_out = 0; | 1905 | tp->sacked_out = 0; |
1905 | } | 1906 | } |
1906 | 1907 | ||
1907 | /* Enter Loss state. If "how" is not zero, forget all SACK information | 1908 | /* Enter Loss state. If we detect SACK reneging, forget all SACK information |
1908 | * and reset tags completely, otherwise preserve SACKs. If receiver | 1909 | * and reset tags completely, otherwise preserve SACKs. If receiver |
1909 | * dropped its ofo queue, we will know this due to reneging detection. | 1910 | * dropped its ofo queue, we will know this due to reneging detection. |
1910 | */ | 1911 | */ |
1911 | void tcp_enter_loss(struct sock *sk, int how) | 1912 | void tcp_enter_loss(struct sock *sk) |
1912 | { | 1913 | { |
1913 | const struct inet_connection_sock *icsk = inet_csk(sk); | 1914 | const struct inet_connection_sock *icsk = inet_csk(sk); |
1914 | struct tcp_sock *tp = tcp_sk(sk); | 1915 | struct tcp_sock *tp = tcp_sk(sk); |
1915 | struct sk_buff *skb; | 1916 | struct sk_buff *skb; |
1916 | bool new_recovery = false; | 1917 | bool new_recovery = false; |
1918 | bool is_reneg; /* is receiver reneging on SACKs? */ | ||
1917 | 1919 | ||
1918 | /* Reduce ssthresh if it has not yet been made inside this window. */ | 1920 | /* Reduce ssthresh if it has not yet been made inside this window. */ |
1919 | if (icsk->icsk_ca_state <= TCP_CA_Disorder || | 1921 | if (icsk->icsk_ca_state <= TCP_CA_Disorder || |
@@ -1934,7 +1936,11 @@ void tcp_enter_loss(struct sock *sk, int how) | |||
1934 | tcp_reset_reno_sack(tp); | 1936 | tcp_reset_reno_sack(tp); |
1935 | 1937 | ||
1936 | tp->undo_marker = tp->snd_una; | 1938 | tp->undo_marker = tp->snd_una; |
1937 | if (how) { | 1939 | |
1940 | skb = tcp_write_queue_head(sk); | ||
1941 | is_reneg = skb && (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED); | ||
1942 | if (is_reneg) { | ||
1943 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSACKRENEGING); | ||
1938 | tp->sacked_out = 0; | 1944 | tp->sacked_out = 0; |
1939 | tp->fackets_out = 0; | 1945 | tp->fackets_out = 0; |
1940 | } | 1946 | } |
@@ -1948,7 +1954,7 @@ void tcp_enter_loss(struct sock *sk, int how) | |||
1948 | tp->undo_marker = 0; | 1954 | tp->undo_marker = 0; |
1949 | 1955 | ||
1950 | TCP_SKB_CB(skb)->sacked &= (~TCPCB_TAGBITS)|TCPCB_SACKED_ACKED; | 1956 | TCP_SKB_CB(skb)->sacked &= (~TCPCB_TAGBITS)|TCPCB_SACKED_ACKED; |
1951 | if (!(TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_ACKED) || how) { | 1957 | if (!(TCP_SKB_CB(skb)->sacked&TCPCB_SACKED_ACKED) || is_reneg) { |
1952 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_ACKED; | 1958 | TCP_SKB_CB(skb)->sacked &= ~TCPCB_SACKED_ACKED; |
1953 | TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; | 1959 | TCP_SKB_CB(skb)->sacked |= TCPCB_LOST; |
1954 | tp->lost_out += tcp_skb_pcount(skb); | 1960 | tp->lost_out += tcp_skb_pcount(skb); |
@@ -1981,19 +1987,21 @@ void tcp_enter_loss(struct sock *sk, int how) | |||
1981 | * remembered SACKs do not reflect real state of receiver i.e. | 1987 | * remembered SACKs do not reflect real state of receiver i.e. |
1982 | * receiver _host_ is heavily congested (or buggy). | 1988 | * receiver _host_ is heavily congested (or buggy). |
1983 | * | 1989 | * |
1984 | * Do processing similar to RTO timeout. | 1990 | * To avoid big spurious retransmission bursts due to transient SACK |
1991 | * scoreboard oddities that look like reneging, we give the receiver a | ||
1992 | * little time (max(RTT/2, 10ms)) to send us some more ACKs that will | ||
1993 | * restore sanity to the SACK scoreboard. If the apparent reneging | ||
1994 | * persists until this RTO then we'll clear the SACK scoreboard. | ||
1985 | */ | 1995 | */ |
1986 | static bool tcp_check_sack_reneging(struct sock *sk, int flag) | 1996 | static bool tcp_check_sack_reneging(struct sock *sk, int flag) |
1987 | { | 1997 | { |
1988 | if (flag & FLAG_SACK_RENEGING) { | 1998 | if (flag & FLAG_SACK_RENEGING) { |
1989 | struct inet_connection_sock *icsk = inet_csk(sk); | 1999 | struct tcp_sock *tp = tcp_sk(sk); |
1990 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSACKRENEGING); | 2000 | unsigned long delay = max(usecs_to_jiffies(tp->srtt_us >> 4), |
2001 | msecs_to_jiffies(10)); | ||
1991 | 2002 | ||
1992 | tcp_enter_loss(sk, 1); | ||
1993 | icsk->icsk_retransmits++; | ||
1994 | tcp_retransmit_skb(sk, tcp_write_queue_head(sk)); | ||
1995 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, | 2003 | inet_csk_reset_xmit_timer(sk, ICSK_TIME_RETRANS, |
1996 | icsk->icsk_rto, TCP_RTO_MAX); | 2004 | delay, TCP_RTO_MAX); |
1997 | return true; | 2005 | return true; |
1998 | } | 2006 | } |
1999 | return false; | 2007 | return false; |
@@ -2475,7 +2483,7 @@ static bool tcp_try_undo_loss(struct sock *sk, bool frto_undo) | |||
2475 | * losses and/or application stalls), do not perform any further cwnd | 2483 | * losses and/or application stalls), do not perform any further cwnd |
2476 | * reductions, but instead slow start up to ssthresh. | 2484 | * reductions, but instead slow start up to ssthresh. |
2477 | */ | 2485 | */ |
2478 | static void tcp_init_cwnd_reduction(struct sock *sk, const bool set_ssthresh) | 2486 | static void tcp_init_cwnd_reduction(struct sock *sk) |
2479 | { | 2487 | { |
2480 | struct tcp_sock *tp = tcp_sk(sk); | 2488 | struct tcp_sock *tp = tcp_sk(sk); |
2481 | 2489 | ||
@@ -2485,8 +2493,7 @@ static void tcp_init_cwnd_reduction(struct sock *sk, const bool set_ssthresh) | |||
2485 | tp->prior_cwnd = tp->snd_cwnd; | 2493 | tp->prior_cwnd = tp->snd_cwnd; |
2486 | tp->prr_delivered = 0; | 2494 | tp->prr_delivered = 0; |
2487 | tp->prr_out = 0; | 2495 | tp->prr_out = 0; |
2488 | if (set_ssthresh) | 2496 | tp->snd_ssthresh = inet_csk(sk)->icsk_ca_ops->ssthresh(sk); |
2489 | tp->snd_ssthresh = inet_csk(sk)->icsk_ca_ops->ssthresh(sk); | ||
2490 | TCP_ECN_queue_cwr(tp); | 2497 | TCP_ECN_queue_cwr(tp); |
2491 | } | 2498 | } |
2492 | 2499 | ||
@@ -2528,14 +2535,14 @@ static inline void tcp_end_cwnd_reduction(struct sock *sk) | |||
2528 | } | 2535 | } |
2529 | 2536 | ||
2530 | /* Enter CWR state. Disable cwnd undo since congestion is proven with ECN */ | 2537 | /* Enter CWR state. Disable cwnd undo since congestion is proven with ECN */ |
2531 | void tcp_enter_cwr(struct sock *sk, const int set_ssthresh) | 2538 | void tcp_enter_cwr(struct sock *sk) |
2532 | { | 2539 | { |
2533 | struct tcp_sock *tp = tcp_sk(sk); | 2540 | struct tcp_sock *tp = tcp_sk(sk); |
2534 | 2541 | ||
2535 | tp->prior_ssthresh = 0; | 2542 | tp->prior_ssthresh = 0; |
2536 | if (inet_csk(sk)->icsk_ca_state < TCP_CA_CWR) { | 2543 | if (inet_csk(sk)->icsk_ca_state < TCP_CA_CWR) { |
2537 | tp->undo_marker = 0; | 2544 | tp->undo_marker = 0; |
2538 | tcp_init_cwnd_reduction(sk, set_ssthresh); | 2545 | tcp_init_cwnd_reduction(sk); |
2539 | tcp_set_ca_state(sk, TCP_CA_CWR); | 2546 | tcp_set_ca_state(sk, TCP_CA_CWR); |
2540 | } | 2547 | } |
2541 | } | 2548 | } |
@@ -2564,7 +2571,7 @@ static void tcp_try_to_open(struct sock *sk, int flag, const int prior_unsacked) | |||
2564 | tp->retrans_stamp = 0; | 2571 | tp->retrans_stamp = 0; |
2565 | 2572 | ||
2566 | if (flag & FLAG_ECE) | 2573 | if (flag & FLAG_ECE) |
2567 | tcp_enter_cwr(sk, 1); | 2574 | tcp_enter_cwr(sk); |
2568 | 2575 | ||
2569 | if (inet_csk(sk)->icsk_ca_state != TCP_CA_CWR) { | 2576 | if (inet_csk(sk)->icsk_ca_state != TCP_CA_CWR) { |
2570 | tcp_try_keep_open(sk); | 2577 | tcp_try_keep_open(sk); |
@@ -2670,7 +2677,7 @@ static void tcp_enter_recovery(struct sock *sk, bool ece_ack) | |||
2670 | if (inet_csk(sk)->icsk_ca_state < TCP_CA_CWR) { | 2677 | if (inet_csk(sk)->icsk_ca_state < TCP_CA_CWR) { |
2671 | if (!ece_ack) | 2678 | if (!ece_ack) |
2672 | tp->prior_ssthresh = tcp_current_ssthresh(sk); | 2679 | tp->prior_ssthresh = tcp_current_ssthresh(sk); |
2673 | tcp_init_cwnd_reduction(sk, true); | 2680 | tcp_init_cwnd_reduction(sk); |
2674 | } | 2681 | } |
2675 | tcp_set_ca_state(sk, TCP_CA_Recovery); | 2682 | tcp_set_ca_state(sk, TCP_CA_Recovery); |
2676 | } | 2683 | } |
@@ -2680,7 +2687,6 @@ static void tcp_enter_recovery(struct sock *sk, bool ece_ack) | |||
2680 | */ | 2687 | */ |
2681 | static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack) | 2688 | static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack) |
2682 | { | 2689 | { |
2683 | struct inet_connection_sock *icsk = inet_csk(sk); | ||
2684 | struct tcp_sock *tp = tcp_sk(sk); | 2690 | struct tcp_sock *tp = tcp_sk(sk); |
2685 | bool recovered = !before(tp->snd_una, tp->high_seq); | 2691 | bool recovered = !before(tp->snd_una, tp->high_seq); |
2686 | 2692 | ||
@@ -2706,12 +2712,9 @@ static void tcp_process_loss(struct sock *sk, int flag, bool is_dupack) | |||
2706 | 2712 | ||
2707 | if (recovered) { | 2713 | if (recovered) { |
2708 | /* F-RTO RFC5682 sec 3.1 step 2.a and 1st part of step 3.a */ | 2714 | /* F-RTO RFC5682 sec 3.1 step 2.a and 1st part of step 3.a */ |
2709 | icsk->icsk_retransmits = 0; | ||
2710 | tcp_try_undo_recovery(sk); | 2715 | tcp_try_undo_recovery(sk); |
2711 | return; | 2716 | return; |
2712 | } | 2717 | } |
2713 | if (flag & FLAG_DATA_ACKED) | ||
2714 | icsk->icsk_retransmits = 0; | ||
2715 | if (tcp_is_reno(tp)) { | 2718 | if (tcp_is_reno(tp)) { |
2716 | /* A Reno DUPACK means new data in F-RTO step 2.b above are | 2719 | /* A Reno DUPACK means new data in F-RTO step 2.b above are |
2717 | * delivered. Lower inflight to clock out (re)tranmissions. | 2720 | * delivered. Lower inflight to clock out (re)tranmissions. |
@@ -3043,10 +3046,15 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets, | |||
3043 | first_ackt.v64 = 0; | 3046 | first_ackt.v64 = 0; |
3044 | 3047 | ||
3045 | while ((skb = tcp_write_queue_head(sk)) && skb != tcp_send_head(sk)) { | 3048 | while ((skb = tcp_write_queue_head(sk)) && skb != tcp_send_head(sk)) { |
3049 | struct skb_shared_info *shinfo = skb_shinfo(skb); | ||
3046 | struct tcp_skb_cb *scb = TCP_SKB_CB(skb); | 3050 | struct tcp_skb_cb *scb = TCP_SKB_CB(skb); |
3047 | u8 sacked = scb->sacked; | 3051 | u8 sacked = scb->sacked; |
3048 | u32 acked_pcount; | 3052 | u32 acked_pcount; |
3049 | 3053 | ||
3054 | if (unlikely(shinfo->tx_flags & SKBTX_ACK_TSTAMP) && | ||
3055 | between(shinfo->tskey, prior_snd_una, tp->snd_una - 1)) | ||
3056 | __skb_tstamp_tx(skb, NULL, sk, SCM_TSTAMP_ACK); | ||
3057 | |||
3050 | /* Determine how many packets and what bytes were acked, tso and else */ | 3058 | /* Determine how many packets and what bytes were acked, tso and else */ |
3051 | if (after(scb->end_seq, tp->snd_una)) { | 3059 | if (after(scb->end_seq, tp->snd_una)) { |
3052 | if (tcp_skb_pcount(skb) == 1 || | 3060 | if (tcp_skb_pcount(skb) == 1 || |
@@ -3346,7 +3354,7 @@ static void tcp_process_tlp_ack(struct sock *sk, u32 ack, int flag) | |||
3346 | tp->tlp_high_seq = 0; | 3354 | tp->tlp_high_seq = 0; |
3347 | /* Don't reduce cwnd if DSACK arrives for TLP retrans. */ | 3355 | /* Don't reduce cwnd if DSACK arrives for TLP retrans. */ |
3348 | if (!(flag & FLAG_DSACKING_ACK)) { | 3356 | if (!(flag & FLAG_DSACKING_ACK)) { |
3349 | tcp_init_cwnd_reduction(sk, true); | 3357 | tcp_init_cwnd_reduction(sk); |
3350 | tcp_set_ca_state(sk, TCP_CA_CWR); | 3358 | tcp_set_ca_state(sk, TCP_CA_CWR); |
3351 | tcp_end_cwnd_reduction(sk); | 3359 | tcp_end_cwnd_reduction(sk); |
3352 | tcp_try_keep_open(sk); | 3360 | tcp_try_keep_open(sk); |
@@ -3393,8 +3401,10 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) | |||
3393 | icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) | 3401 | icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) |
3394 | tcp_rearm_rto(sk); | 3402 | tcp_rearm_rto(sk); |
3395 | 3403 | ||
3396 | if (after(ack, prior_snd_una)) | 3404 | if (after(ack, prior_snd_una)) { |
3397 | flag |= FLAG_SND_UNA_ADVANCED; | 3405 | flag |= FLAG_SND_UNA_ADVANCED; |
3406 | icsk->icsk_retransmits = 0; | ||
3407 | } | ||
3398 | 3408 | ||
3399 | prior_fackets = tp->fackets_out; | 3409 | prior_fackets = tp->fackets_out; |
3400 | 3410 | ||
@@ -5877,3 +5887,156 @@ discard: | |||
5877 | return 0; | 5887 | return 0; |
5878 | } | 5888 | } |
5879 | EXPORT_SYMBOL(tcp_rcv_state_process); | 5889 | EXPORT_SYMBOL(tcp_rcv_state_process); |
5890 | |||
5891 | static inline void pr_drop_req(struct request_sock *req, __u16 port, int family) | ||
5892 | { | ||
5893 | struct inet_request_sock *ireq = inet_rsk(req); | ||
5894 | |||
5895 | if (family == AF_INET) | ||
5896 | LIMIT_NETDEBUG(KERN_DEBUG pr_fmt("drop open request from %pI4/%u\n"), | ||
5897 | &ireq->ir_rmt_addr, port); | ||
5898 | #if IS_ENABLED(CONFIG_IPV6) | ||
5899 | else if (family == AF_INET6) | ||
5900 | LIMIT_NETDEBUG(KERN_DEBUG pr_fmt("drop open request from %pI6/%u\n"), | ||
5901 | &ireq->ir_v6_rmt_addr, port); | ||
5902 | #endif | ||
5903 | } | ||
5904 | |||
5905 | int tcp_conn_request(struct request_sock_ops *rsk_ops, | ||
5906 | const struct tcp_request_sock_ops *af_ops, | ||
5907 | struct sock *sk, struct sk_buff *skb) | ||
5908 | { | ||
5909 | struct tcp_options_received tmp_opt; | ||
5910 | struct request_sock *req; | ||
5911 | struct tcp_sock *tp = tcp_sk(sk); | ||
5912 | struct dst_entry *dst = NULL; | ||
5913 | __u32 isn = TCP_SKB_CB(skb)->when; | ||
5914 | bool want_cookie = false, fastopen; | ||
5915 | struct flowi fl; | ||
5916 | struct tcp_fastopen_cookie foc = { .len = -1 }; | ||
5917 | int err; | ||
5918 | |||
5919 | |||
5920 | /* TW buckets are converted to open requests without | ||
5921 | * limitations, they conserve resources and peer is | ||
5922 | * evidently real one. | ||
5923 | */ | ||
5924 | if ((sysctl_tcp_syncookies == 2 || | ||
5925 | inet_csk_reqsk_queue_is_full(sk)) && !isn) { | ||
5926 | want_cookie = tcp_syn_flood_action(sk, skb, rsk_ops->slab_name); | ||
5927 | if (!want_cookie) | ||
5928 | goto drop; | ||
5929 | } | ||
5930 | |||
5931 | |||
5932 | /* Accept backlog is full. If we have already queued enough | ||
5933 | * of warm entries in syn queue, drop request. It is better than | ||
5934 | * clogging syn queue with openreqs with exponentially increasing | ||
5935 | * timeout. | ||
5936 | */ | ||
5937 | if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) { | ||
5938 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS); | ||
5939 | goto drop; | ||
5940 | } | ||
5941 | |||
5942 | req = inet_reqsk_alloc(rsk_ops); | ||
5943 | if (!req) | ||
5944 | goto drop; | ||
5945 | |||
5946 | tcp_rsk(req)->af_specific = af_ops; | ||
5947 | |||
5948 | tcp_clear_options(&tmp_opt); | ||
5949 | tmp_opt.mss_clamp = af_ops->mss_clamp; | ||
5950 | tmp_opt.user_mss = tp->rx_opt.user_mss; | ||
5951 | tcp_parse_options(skb, &tmp_opt, 0, want_cookie ? NULL : &foc); | ||
5952 | |||
5953 | if (want_cookie && !tmp_opt.saw_tstamp) | ||
5954 | tcp_clear_options(&tmp_opt); | ||
5955 | |||
5956 | tmp_opt.tstamp_ok = tmp_opt.saw_tstamp; | ||
5957 | tcp_openreq_init(req, &tmp_opt, skb, sk); | ||
5958 | |||
5959 | af_ops->init_req(req, sk, skb); | ||
5960 | |||
5961 | if (security_inet_conn_request(sk, skb, req)) | ||
5962 | goto drop_and_free; | ||
5963 | |||
5964 | if (!want_cookie || tmp_opt.tstamp_ok) | ||
5965 | TCP_ECN_create_request(req, skb, sock_net(sk)); | ||
5966 | |||
5967 | if (want_cookie) { | ||
5968 | isn = cookie_init_sequence(af_ops, sk, skb, &req->mss); | ||
5969 | req->cookie_ts = tmp_opt.tstamp_ok; | ||
5970 | } else if (!isn) { | ||
5971 | /* VJ's idea. We save last timestamp seen | ||
5972 | * from the destination in peer table, when entering | ||
5973 | * state TIME-WAIT, and check against it before | ||
5974 | * accepting new connection request. | ||
5975 | * | ||
5976 | * If "isn" is not zero, this request hit alive | ||
5977 | * timewait bucket, so that all the necessary checks | ||
5978 | * are made in the function processing timewait state. | ||
5979 | */ | ||
5980 | if (tcp_death_row.sysctl_tw_recycle) { | ||
5981 | bool strict; | ||
5982 | |||
5983 | dst = af_ops->route_req(sk, &fl, req, &strict); | ||
5984 | |||
5985 | if (dst && strict && | ||
5986 | !tcp_peer_is_proven(req, dst, true, | ||
5987 | tmp_opt.saw_tstamp)) { | ||
5988 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED); | ||
5989 | goto drop_and_release; | ||
5990 | } | ||
5991 | } | ||
5992 | /* Kill the following clause, if you dislike this way. */ | ||
5993 | else if (!sysctl_tcp_syncookies && | ||
5994 | (sysctl_max_syn_backlog - inet_csk_reqsk_queue_len(sk) < | ||
5995 | (sysctl_max_syn_backlog >> 2)) && | ||
5996 | !tcp_peer_is_proven(req, dst, false, | ||
5997 | tmp_opt.saw_tstamp)) { | ||
5998 | /* Without syncookies last quarter of | ||
5999 | * backlog is filled with destinations, | ||
6000 | * proven to be alive. | ||
6001 | * It means that we continue to communicate | ||
6002 | * to destinations, already remembered | ||
6003 | * to the moment of synflood. | ||
6004 | */ | ||
6005 | pr_drop_req(req, ntohs(tcp_hdr(skb)->source), | ||
6006 | rsk_ops->family); | ||
6007 | goto drop_and_release; | ||
6008 | } | ||
6009 | |||
6010 | isn = af_ops->init_seq(skb); | ||
6011 | } | ||
6012 | if (!dst) { | ||
6013 | dst = af_ops->route_req(sk, &fl, req, NULL); | ||
6014 | if (!dst) | ||
6015 | goto drop_and_free; | ||
6016 | } | ||
6017 | |||
6018 | tcp_rsk(req)->snt_isn = isn; | ||
6019 | tcp_openreq_init_rwin(req, sk, dst); | ||
6020 | fastopen = !want_cookie && | ||
6021 | tcp_try_fastopen(sk, skb, req, &foc, dst); | ||
6022 | err = af_ops->send_synack(sk, dst, &fl, req, | ||
6023 | skb_get_queue_mapping(skb), &foc); | ||
6024 | if (!fastopen) { | ||
6025 | if (err || want_cookie) | ||
6026 | goto drop_and_free; | ||
6027 | |||
6028 | tcp_rsk(req)->listener = NULL; | ||
6029 | af_ops->queue_hash_add(sk, req, TCP_TIMEOUT_INIT); | ||
6030 | } | ||
6031 | |||
6032 | return 0; | ||
6033 | |||
6034 | drop_and_release: | ||
6035 | dst_release(dst); | ||
6036 | drop_and_free: | ||
6037 | reqsk_free(req); | ||
6038 | drop: | ||
6039 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); | ||
6040 | return 0; | ||
6041 | } | ||
6042 | EXPORT_SYMBOL(tcp_conn_request); | ||
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 77cccda1ad0c..cd17f009aede 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
@@ -99,7 +99,7 @@ static int tcp_v4_md5_hash_hdr(char *md5_hash, const struct tcp_md5sig_key *key, | |||
99 | struct inet_hashinfo tcp_hashinfo; | 99 | struct inet_hashinfo tcp_hashinfo; |
100 | EXPORT_SYMBOL(tcp_hashinfo); | 100 | EXPORT_SYMBOL(tcp_hashinfo); |
101 | 101 | ||
102 | static inline __u32 tcp_v4_init_sequence(const struct sk_buff *skb) | 102 | static __u32 tcp_v4_init_sequence(const struct sk_buff *skb) |
103 | { | 103 | { |
104 | return secure_tcp_sequence_number(ip_hdr(skb)->daddr, | 104 | return secure_tcp_sequence_number(ip_hdr(skb)->daddr, |
105 | ip_hdr(skb)->saddr, | 105 | ip_hdr(skb)->saddr, |
@@ -208,6 +208,8 @@ int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len) | |||
208 | inet->inet_dport = usin->sin_port; | 208 | inet->inet_dport = usin->sin_port; |
209 | inet->inet_daddr = daddr; | 209 | inet->inet_daddr = daddr; |
210 | 210 | ||
211 | inet_set_txhash(sk); | ||
212 | |||
211 | inet_csk(sk)->icsk_ext_hdr_len = 0; | 213 | inet_csk(sk)->icsk_ext_hdr_len = 0; |
212 | if (inet_opt) | 214 | if (inet_opt) |
213 | inet_csk(sk)->icsk_ext_hdr_len = inet_opt->opt.optlen; | 215 | inet_csk(sk)->icsk_ext_hdr_len = inet_opt->opt.optlen; |
@@ -269,7 +271,7 @@ EXPORT_SYMBOL(tcp_v4_connect); | |||
269 | * It can be called through tcp_release_cb() if socket was owned by user | 271 | * It can be called through tcp_release_cb() if socket was owned by user |
270 | * at the time tcp_v4_err() was called to handle ICMP message. | 272 | * at the time tcp_v4_err() was called to handle ICMP message. |
271 | */ | 273 | */ |
272 | static void tcp_v4_mtu_reduced(struct sock *sk) | 274 | void tcp_v4_mtu_reduced(struct sock *sk) |
273 | { | 275 | { |
274 | struct dst_entry *dst; | 276 | struct dst_entry *dst; |
275 | struct inet_sock *inet = inet_sk(sk); | 277 | struct inet_sock *inet = inet_sk(sk); |
@@ -300,6 +302,7 @@ static void tcp_v4_mtu_reduced(struct sock *sk) | |||
300 | tcp_simple_retransmit(sk); | 302 | tcp_simple_retransmit(sk); |
301 | } /* else let the usual retransmit timer handle it */ | 303 | } /* else let the usual retransmit timer handle it */ |
302 | } | 304 | } |
305 | EXPORT_SYMBOL(tcp_v4_mtu_reduced); | ||
303 | 306 | ||
304 | static void do_redirect(struct sk_buff *skb, struct sock *sk) | 307 | static void do_redirect(struct sk_buff *skb, struct sock *sk) |
305 | { | 308 | { |
@@ -342,11 +345,6 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) | |||
342 | int err; | 345 | int err; |
343 | struct net *net = dev_net(icmp_skb->dev); | 346 | struct net *net = dev_net(icmp_skb->dev); |
344 | 347 | ||
345 | if (icmp_skb->len < (iph->ihl << 2) + 8) { | ||
346 | ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); | ||
347 | return; | ||
348 | } | ||
349 | |||
350 | sk = inet_lookup(net, &tcp_hashinfo, iph->daddr, th->dest, | 348 | sk = inet_lookup(net, &tcp_hashinfo, iph->daddr, th->dest, |
351 | iph->saddr, th->source, inet_iif(icmp_skb)); | 349 | iph->saddr, th->source, inet_iif(icmp_skb)); |
352 | if (!sk) { | 350 | if (!sk) { |
@@ -814,6 +812,7 @@ static void tcp_v4_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, | |||
814 | * socket. | 812 | * socket. |
815 | */ | 813 | */ |
816 | static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst, | 814 | static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst, |
815 | struct flowi *fl, | ||
817 | struct request_sock *req, | 816 | struct request_sock *req, |
818 | u16 queue_mapping, | 817 | u16 queue_mapping, |
819 | struct tcp_fastopen_cookie *foc) | 818 | struct tcp_fastopen_cookie *foc) |
@@ -837,24 +836,11 @@ static int tcp_v4_send_synack(struct sock *sk, struct dst_entry *dst, | |||
837 | ireq->ir_rmt_addr, | 836 | ireq->ir_rmt_addr, |
838 | ireq->opt); | 837 | ireq->opt); |
839 | err = net_xmit_eval(err); | 838 | err = net_xmit_eval(err); |
840 | if (!tcp_rsk(req)->snt_synack && !err) | ||
841 | tcp_rsk(req)->snt_synack = tcp_time_stamp; | ||
842 | } | 839 | } |
843 | 840 | ||
844 | return err; | 841 | return err; |
845 | } | 842 | } |
846 | 843 | ||
847 | static int tcp_v4_rtx_synack(struct sock *sk, struct request_sock *req) | ||
848 | { | ||
849 | int res = tcp_v4_send_synack(sk, NULL, req, 0, NULL); | ||
850 | |||
851 | if (!res) { | ||
852 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS); | ||
853 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSYNRETRANS); | ||
854 | } | ||
855 | return res; | ||
856 | } | ||
857 | |||
858 | /* | 844 | /* |
859 | * IPv4 request_sock destructor. | 845 | * IPv4 request_sock destructor. |
860 | */ | 846 | */ |
@@ -1064,7 +1050,7 @@ static int tcp_v4_parse_md5_keys(struct sock *sk, char __user *optval, | |||
1064 | if (sin->sin_family != AF_INET) | 1050 | if (sin->sin_family != AF_INET) |
1065 | return -EINVAL; | 1051 | return -EINVAL; |
1066 | 1052 | ||
1067 | if (!cmd.tcpm_key || !cmd.tcpm_keylen) | 1053 | if (!cmd.tcpm_keylen) |
1068 | return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin->sin_addr.s_addr, | 1054 | return tcp_md5_do_del(sk, (union tcp_md5_addr *)&sin->sin_addr.s_addr, |
1069 | AF_INET); | 1055 | AF_INET); |
1070 | 1056 | ||
@@ -1182,7 +1168,8 @@ clear_hash_noput: | |||
1182 | } | 1168 | } |
1183 | EXPORT_SYMBOL(tcp_v4_md5_hash_skb); | 1169 | EXPORT_SYMBOL(tcp_v4_md5_hash_skb); |
1184 | 1170 | ||
1185 | static bool tcp_v4_inbound_md5_hash(struct sock *sk, const struct sk_buff *skb) | 1171 | static bool __tcp_v4_inbound_md5_hash(struct sock *sk, |
1172 | const struct sk_buff *skb) | ||
1186 | { | 1173 | { |
1187 | /* | 1174 | /* |
1188 | * This gets called for each TCP segment that arrives | 1175 | * This gets called for each TCP segment that arrives |
@@ -1235,163 +1222,81 @@ static bool tcp_v4_inbound_md5_hash(struct sock *sk, const struct sk_buff *skb) | |||
1235 | return false; | 1222 | return false; |
1236 | } | 1223 | } |
1237 | 1224 | ||
1225 | static bool tcp_v4_inbound_md5_hash(struct sock *sk, const struct sk_buff *skb) | ||
1226 | { | ||
1227 | bool ret; | ||
1228 | |||
1229 | rcu_read_lock(); | ||
1230 | ret = __tcp_v4_inbound_md5_hash(sk, skb); | ||
1231 | rcu_read_unlock(); | ||
1232 | |||
1233 | return ret; | ||
1234 | } | ||
1235 | |||
1238 | #endif | 1236 | #endif |
1239 | 1237 | ||
1238 | static void tcp_v4_init_req(struct request_sock *req, struct sock *sk, | ||
1239 | struct sk_buff *skb) | ||
1240 | { | ||
1241 | struct inet_request_sock *ireq = inet_rsk(req); | ||
1242 | |||
1243 | ireq->ir_loc_addr = ip_hdr(skb)->daddr; | ||
1244 | ireq->ir_rmt_addr = ip_hdr(skb)->saddr; | ||
1245 | ireq->no_srccheck = inet_sk(sk)->transparent; | ||
1246 | ireq->opt = tcp_v4_save_options(skb); | ||
1247 | } | ||
1248 | |||
1249 | static struct dst_entry *tcp_v4_route_req(struct sock *sk, struct flowi *fl, | ||
1250 | const struct request_sock *req, | ||
1251 | bool *strict) | ||
1252 | { | ||
1253 | struct dst_entry *dst = inet_csk_route_req(sk, &fl->u.ip4, req); | ||
1254 | |||
1255 | if (strict) { | ||
1256 | if (fl->u.ip4.daddr == inet_rsk(req)->ir_rmt_addr) | ||
1257 | *strict = true; | ||
1258 | else | ||
1259 | *strict = false; | ||
1260 | } | ||
1261 | |||
1262 | return dst; | ||
1263 | } | ||
1264 | |||
1240 | struct request_sock_ops tcp_request_sock_ops __read_mostly = { | 1265 | struct request_sock_ops tcp_request_sock_ops __read_mostly = { |
1241 | .family = PF_INET, | 1266 | .family = PF_INET, |
1242 | .obj_size = sizeof(struct tcp_request_sock), | 1267 | .obj_size = sizeof(struct tcp_request_sock), |
1243 | .rtx_syn_ack = tcp_v4_rtx_synack, | 1268 | .rtx_syn_ack = tcp_rtx_synack, |
1244 | .send_ack = tcp_v4_reqsk_send_ack, | 1269 | .send_ack = tcp_v4_reqsk_send_ack, |
1245 | .destructor = tcp_v4_reqsk_destructor, | 1270 | .destructor = tcp_v4_reqsk_destructor, |
1246 | .send_reset = tcp_v4_send_reset, | 1271 | .send_reset = tcp_v4_send_reset, |
1247 | .syn_ack_timeout = tcp_syn_ack_timeout, | 1272 | .syn_ack_timeout = tcp_syn_ack_timeout, |
1248 | }; | 1273 | }; |
1249 | 1274 | ||
1250 | #ifdef CONFIG_TCP_MD5SIG | ||
1251 | static const struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = { | 1275 | static const struct tcp_request_sock_ops tcp_request_sock_ipv4_ops = { |
1276 | .mss_clamp = TCP_MSS_DEFAULT, | ||
1277 | #ifdef CONFIG_TCP_MD5SIG | ||
1252 | .md5_lookup = tcp_v4_reqsk_md5_lookup, | 1278 | .md5_lookup = tcp_v4_reqsk_md5_lookup, |
1253 | .calc_md5_hash = tcp_v4_md5_hash_skb, | 1279 | .calc_md5_hash = tcp_v4_md5_hash_skb, |
1254 | }; | ||
1255 | #endif | 1280 | #endif |
1281 | .init_req = tcp_v4_init_req, | ||
1282 | #ifdef CONFIG_SYN_COOKIES | ||
1283 | .cookie_init_seq = cookie_v4_init_sequence, | ||
1284 | #endif | ||
1285 | .route_req = tcp_v4_route_req, | ||
1286 | .init_seq = tcp_v4_init_sequence, | ||
1287 | .send_synack = tcp_v4_send_synack, | ||
1288 | .queue_hash_add = inet_csk_reqsk_queue_hash_add, | ||
1289 | }; | ||
1256 | 1290 | ||
1257 | int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) | 1291 | int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) |
1258 | { | 1292 | { |
1259 | struct tcp_options_received tmp_opt; | ||
1260 | struct request_sock *req; | ||
1261 | struct inet_request_sock *ireq; | ||
1262 | struct tcp_sock *tp = tcp_sk(sk); | ||
1263 | struct dst_entry *dst = NULL; | ||
1264 | __be32 saddr = ip_hdr(skb)->saddr; | ||
1265 | __be32 daddr = ip_hdr(skb)->daddr; | ||
1266 | __u32 isn = TCP_SKB_CB(skb)->when; | ||
1267 | bool want_cookie = false, fastopen; | ||
1268 | struct flowi4 fl4; | ||
1269 | struct tcp_fastopen_cookie foc = { .len = -1 }; | ||
1270 | int err; | ||
1271 | |||
1272 | /* Never answer to SYNs send to broadcast or multicast */ | 1293 | /* Never answer to SYNs send to broadcast or multicast */ |
1273 | if (skb_rtable(skb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) | 1294 | if (skb_rtable(skb)->rt_flags & (RTCF_BROADCAST | RTCF_MULTICAST)) |
1274 | goto drop; | 1295 | goto drop; |
1275 | 1296 | ||
1276 | /* TW buckets are converted to open requests without | 1297 | return tcp_conn_request(&tcp_request_sock_ops, |
1277 | * limitations, they conserve resources and peer is | 1298 | &tcp_request_sock_ipv4_ops, sk, skb); |
1278 | * evidently real one. | ||
1279 | */ | ||
1280 | if ((sysctl_tcp_syncookies == 2 || | ||
1281 | inet_csk_reqsk_queue_is_full(sk)) && !isn) { | ||
1282 | want_cookie = tcp_syn_flood_action(sk, skb, "TCP"); | ||
1283 | if (!want_cookie) | ||
1284 | goto drop; | ||
1285 | } | ||
1286 | |||
1287 | /* Accept backlog is full. If we have already queued enough | ||
1288 | * of warm entries in syn queue, drop request. It is better than | ||
1289 | * clogging syn queue with openreqs with exponentially increasing | ||
1290 | * timeout. | ||
1291 | */ | ||
1292 | if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) { | ||
1293 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS); | ||
1294 | goto drop; | ||
1295 | } | ||
1296 | |||
1297 | req = inet_reqsk_alloc(&tcp_request_sock_ops); | ||
1298 | if (!req) | ||
1299 | goto drop; | ||
1300 | |||
1301 | #ifdef CONFIG_TCP_MD5SIG | ||
1302 | tcp_rsk(req)->af_specific = &tcp_request_sock_ipv4_ops; | ||
1303 | #endif | ||
1304 | |||
1305 | tcp_clear_options(&tmp_opt); | ||
1306 | tmp_opt.mss_clamp = TCP_MSS_DEFAULT; | ||
1307 | tmp_opt.user_mss = tp->rx_opt.user_mss; | ||
1308 | tcp_parse_options(skb, &tmp_opt, 0, want_cookie ? NULL : &foc); | ||
1309 | |||
1310 | if (want_cookie && !tmp_opt.saw_tstamp) | ||
1311 | tcp_clear_options(&tmp_opt); | ||
1312 | |||
1313 | tmp_opt.tstamp_ok = tmp_opt.saw_tstamp; | ||
1314 | tcp_openreq_init(req, &tmp_opt, skb); | ||
1315 | |||
1316 | ireq = inet_rsk(req); | ||
1317 | ireq->ir_loc_addr = daddr; | ||
1318 | ireq->ir_rmt_addr = saddr; | ||
1319 | ireq->no_srccheck = inet_sk(sk)->transparent; | ||
1320 | ireq->opt = tcp_v4_save_options(skb); | ||
1321 | ireq->ir_mark = inet_request_mark(sk, skb); | ||
1322 | |||
1323 | if (security_inet_conn_request(sk, skb, req)) | ||
1324 | goto drop_and_free; | ||
1325 | |||
1326 | if (!want_cookie || tmp_opt.tstamp_ok) | ||
1327 | TCP_ECN_create_request(req, skb, sock_net(sk)); | ||
1328 | |||
1329 | if (want_cookie) { | ||
1330 | isn = cookie_v4_init_sequence(sk, skb, &req->mss); | ||
1331 | req->cookie_ts = tmp_opt.tstamp_ok; | ||
1332 | } else if (!isn) { | ||
1333 | /* VJ's idea. We save last timestamp seen | ||
1334 | * from the destination in peer table, when entering | ||
1335 | * state TIME-WAIT, and check against it before | ||
1336 | * accepting new connection request. | ||
1337 | * | ||
1338 | * If "isn" is not zero, this request hit alive | ||
1339 | * timewait bucket, so that all the necessary checks | ||
1340 | * are made in the function processing timewait state. | ||
1341 | */ | ||
1342 | if (tmp_opt.saw_tstamp && | ||
1343 | tcp_death_row.sysctl_tw_recycle && | ||
1344 | (dst = inet_csk_route_req(sk, &fl4, req)) != NULL && | ||
1345 | fl4.daddr == saddr) { | ||
1346 | if (!tcp_peer_is_proven(req, dst, true)) { | ||
1347 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED); | ||
1348 | goto drop_and_release; | ||
1349 | } | ||
1350 | } | ||
1351 | /* Kill the following clause, if you dislike this way. */ | ||
1352 | else if (!sysctl_tcp_syncookies && | ||
1353 | (sysctl_max_syn_backlog - inet_csk_reqsk_queue_len(sk) < | ||
1354 | (sysctl_max_syn_backlog >> 2)) && | ||
1355 | !tcp_peer_is_proven(req, dst, false)) { | ||
1356 | /* Without syncookies last quarter of | ||
1357 | * backlog is filled with destinations, | ||
1358 | * proven to be alive. | ||
1359 | * It means that we continue to communicate | ||
1360 | * to destinations, already remembered | ||
1361 | * to the moment of synflood. | ||
1362 | */ | ||
1363 | LIMIT_NETDEBUG(KERN_DEBUG pr_fmt("drop open request from %pI4/%u\n"), | ||
1364 | &saddr, ntohs(tcp_hdr(skb)->source)); | ||
1365 | goto drop_and_release; | ||
1366 | } | ||
1367 | |||
1368 | isn = tcp_v4_init_sequence(skb); | ||
1369 | } | ||
1370 | if (!dst && (dst = inet_csk_route_req(sk, &fl4, req)) == NULL) | ||
1371 | goto drop_and_free; | ||
1372 | |||
1373 | tcp_rsk(req)->snt_isn = isn; | ||
1374 | tcp_rsk(req)->snt_synack = tcp_time_stamp; | ||
1375 | tcp_openreq_init_rwin(req, sk, dst); | ||
1376 | fastopen = !want_cookie && | ||
1377 | tcp_try_fastopen(sk, skb, req, &foc, dst); | ||
1378 | err = tcp_v4_send_synack(sk, dst, req, | ||
1379 | skb_get_queue_mapping(skb), &foc); | ||
1380 | if (!fastopen) { | ||
1381 | if (err || want_cookie) | ||
1382 | goto drop_and_free; | ||
1383 | 1299 | ||
1384 | tcp_rsk(req)->snt_synack = tcp_time_stamp; | ||
1385 | tcp_rsk(req)->listener = NULL; | ||
1386 | inet_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); | ||
1387 | } | ||
1388 | |||
1389 | return 0; | ||
1390 | |||
1391 | drop_and_release: | ||
1392 | dst_release(dst); | ||
1393 | drop_and_free: | ||
1394 | reqsk_free(req); | ||
1395 | drop: | 1300 | drop: |
1396 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); | 1301 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); |
1397 | return 0; | 1302 | return 0; |
@@ -1439,6 +1344,7 @@ struct sock *tcp_v4_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1439 | newinet->mc_ttl = ip_hdr(skb)->ttl; | 1344 | newinet->mc_ttl = ip_hdr(skb)->ttl; |
1440 | newinet->rcv_tos = ip_hdr(skb)->tos; | 1345 | newinet->rcv_tos = ip_hdr(skb)->tos; |
1441 | inet_csk(newsk)->icsk_ext_hdr_len = 0; | 1346 | inet_csk(newsk)->icsk_ext_hdr_len = 0; |
1347 | inet_set_txhash(newsk); | ||
1442 | if (inet_opt) | 1348 | if (inet_opt) |
1443 | inet_csk(newsk)->icsk_ext_hdr_len = inet_opt->opt.optlen; | 1349 | inet_csk(newsk)->icsk_ext_hdr_len = inet_opt->opt.optlen; |
1444 | newinet->inet_id = newtp->write_seq ^ jiffies; | 1350 | newinet->inet_id = newtp->write_seq ^ jiffies; |
@@ -1539,16 +1445,6 @@ static struct sock *tcp_v4_hnd_req(struct sock *sk, struct sk_buff *skb) | |||
1539 | int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) | 1445 | int tcp_v4_do_rcv(struct sock *sk, struct sk_buff *skb) |
1540 | { | 1446 | { |
1541 | struct sock *rsk; | 1447 | struct sock *rsk; |
1542 | #ifdef CONFIG_TCP_MD5SIG | ||
1543 | /* | ||
1544 | * We really want to reject the packet as early as possible | ||
1545 | * if: | ||
1546 | * o We're expecting an MD5'd packet and this is no MD5 tcp option | ||
1547 | * o There is an MD5 option and we're not expecting one | ||
1548 | */ | ||
1549 | if (tcp_v4_inbound_md5_hash(sk, skb)) | ||
1550 | goto discard; | ||
1551 | #endif | ||
1552 | 1448 | ||
1553 | if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ | 1449 | if (sk->sk_state == TCP_ESTABLISHED) { /* Fast path */ |
1554 | struct dst_entry *dst = sk->sk_rx_dst; | 1450 | struct dst_entry *dst = sk->sk_rx_dst; |
@@ -1751,6 +1647,18 @@ process: | |||
1751 | 1647 | ||
1752 | if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) | 1648 | if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb)) |
1753 | goto discard_and_relse; | 1649 | goto discard_and_relse; |
1650 | |||
1651 | #ifdef CONFIG_TCP_MD5SIG | ||
1652 | /* | ||
1653 | * We really want to reject the packet as early as possible | ||
1654 | * if: | ||
1655 | * o We're expecting an MD5'd packet and this is no MD5 tcp option | ||
1656 | * o There is an MD5 option and we're not expecting one | ||
1657 | */ | ||
1658 | if (tcp_v4_inbound_md5_hash(sk, skb)) | ||
1659 | goto discard_and_relse; | ||
1660 | #endif | ||
1661 | |||
1754 | nf_reset(skb); | 1662 | nf_reset(skb); |
1755 | 1663 | ||
1756 | if (sk_filter(sk, skb)) | 1664 | if (sk_filter(sk, skb)) |
@@ -1880,6 +1788,7 @@ const struct inet_connection_sock_af_ops ipv4_specific = { | |||
1880 | .compat_setsockopt = compat_ip_setsockopt, | 1788 | .compat_setsockopt = compat_ip_setsockopt, |
1881 | .compat_getsockopt = compat_ip_getsockopt, | 1789 | .compat_getsockopt = compat_ip_getsockopt, |
1882 | #endif | 1790 | #endif |
1791 | .mtu_reduced = tcp_v4_mtu_reduced, | ||
1883 | }; | 1792 | }; |
1884 | EXPORT_SYMBOL(ipv4_specific); | 1793 | EXPORT_SYMBOL(ipv4_specific); |
1885 | 1794 | ||
@@ -2499,7 +2408,6 @@ struct proto tcp_prot = { | |||
2499 | .sendpage = tcp_sendpage, | 2408 | .sendpage = tcp_sendpage, |
2500 | .backlog_rcv = tcp_v4_do_rcv, | 2409 | .backlog_rcv = tcp_v4_do_rcv, |
2501 | .release_cb = tcp_release_cb, | 2410 | .release_cb = tcp_release_cb, |
2502 | .mtu_reduced = tcp_v4_mtu_reduced, | ||
2503 | .hash = inet_hash, | 2411 | .hash = inet_hash, |
2504 | .unhash = inet_unhash, | 2412 | .unhash = inet_unhash, |
2505 | .get_port = inet_csk_get_port, | 2413 | .get_port = inet_csk_get_port, |
diff --git a/net/ipv4/tcp_memcontrol.c b/net/ipv4/tcp_memcontrol.c index f7a2ec3ac584..3af522622fad 100644 --- a/net/ipv4/tcp_memcontrol.c +++ b/net/ipv4/tcp_memcontrol.c | |||
@@ -222,7 +222,7 @@ static struct cftype tcp_files[] = { | |||
222 | 222 | ||
223 | static int __init tcp_memcontrol_init(void) | 223 | static int __init tcp_memcontrol_init(void) |
224 | { | 224 | { |
225 | WARN_ON(cgroup_add_cftypes(&memory_cgrp_subsys, tcp_files)); | 225 | WARN_ON(cgroup_add_legacy_cftypes(&memory_cgrp_subsys, tcp_files)); |
226 | return 0; | 226 | return 0; |
227 | } | 227 | } |
228 | __initcall(tcp_memcontrol_init); | 228 | __initcall(tcp_memcontrol_init); |
diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c index 4fe041805989..ed9c9a91851c 100644 --- a/net/ipv4/tcp_metrics.c +++ b/net/ipv4/tcp_metrics.c | |||
@@ -576,7 +576,8 @@ reset: | |||
576 | tp->snd_cwnd_stamp = tcp_time_stamp; | 576 | tp->snd_cwnd_stamp = tcp_time_stamp; |
577 | } | 577 | } |
578 | 578 | ||
579 | bool tcp_peer_is_proven(struct request_sock *req, struct dst_entry *dst, bool paws_check) | 579 | bool tcp_peer_is_proven(struct request_sock *req, struct dst_entry *dst, |
580 | bool paws_check, bool timestamps) | ||
580 | { | 581 | { |
581 | struct tcp_metrics_block *tm; | 582 | struct tcp_metrics_block *tm; |
582 | bool ret; | 583 | bool ret; |
@@ -589,7 +590,8 @@ bool tcp_peer_is_proven(struct request_sock *req, struct dst_entry *dst, bool pa | |||
589 | if (paws_check) { | 590 | if (paws_check) { |
590 | if (tm && | 591 | if (tm && |
591 | (u32)get_seconds() - tm->tcpm_ts_stamp < TCP_PAWS_MSL && | 592 | (u32)get_seconds() - tm->tcpm_ts_stamp < TCP_PAWS_MSL && |
592 | (s32)(tm->tcpm_ts - req->ts_recent) > TCP_PAWS_WINDOW) | 593 | ((s32)(tm->tcpm_ts - req->ts_recent) > TCP_PAWS_WINDOW || |
594 | !timestamps)) | ||
593 | ret = false; | 595 | ret = false; |
594 | else | 596 | else |
595 | ret = true; | 597 | ret = true; |
@@ -1093,7 +1095,6 @@ static const struct genl_ops tcp_metrics_nl_ops[] = { | |||
1093 | .doit = tcp_metrics_nl_cmd_get, | 1095 | .doit = tcp_metrics_nl_cmd_get, |
1094 | .dumpit = tcp_metrics_nl_dump, | 1096 | .dumpit = tcp_metrics_nl_dump, |
1095 | .policy = tcp_metrics_nl_policy, | 1097 | .policy = tcp_metrics_nl_policy, |
1096 | .flags = GENL_ADMIN_PERM, | ||
1097 | }, | 1098 | }, |
1098 | { | 1099 | { |
1099 | .cmd = TCP_METRICS_CMD_DEL, | 1100 | .cmd = TCP_METRICS_CMD_DEL, |
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index e68e0d4af6c9..1649988bd1b6 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c | |||
@@ -298,7 +298,7 @@ void tcp_time_wait(struct sock *sk, int state, int timeo) | |||
298 | tw->tw_v6_rcv_saddr = sk->sk_v6_rcv_saddr; | 298 | tw->tw_v6_rcv_saddr = sk->sk_v6_rcv_saddr; |
299 | tw->tw_tclass = np->tclass; | 299 | tw->tw_tclass = np->tclass; |
300 | tw->tw_flowlabel = np->flow_label >> 12; | 300 | tw->tw_flowlabel = np->flow_label >> 12; |
301 | tw->tw_ipv6only = np->ipv6only; | 301 | tw->tw_ipv6only = sk->sk_ipv6only; |
302 | } | 302 | } |
303 | #endif | 303 | #endif |
304 | 304 | ||
diff --git a/net/ipv4/tcp_offload.c b/net/ipv4/tcp_offload.c index 55046ecd083e..bc1b83cb8309 100644 --- a/net/ipv4/tcp_offload.c +++ b/net/ipv4/tcp_offload.c | |||
@@ -14,6 +14,21 @@ | |||
14 | #include <net/tcp.h> | 14 | #include <net/tcp.h> |
15 | #include <net/protocol.h> | 15 | #include <net/protocol.h> |
16 | 16 | ||
17 | static void tcp_gso_tstamp(struct sk_buff *skb, unsigned int ts_seq, | ||
18 | unsigned int seq, unsigned int mss) | ||
19 | { | ||
20 | while (skb) { | ||
21 | if (before(ts_seq, seq + mss)) { | ||
22 | skb_shinfo(skb)->tx_flags |= SKBTX_SW_TSTAMP; | ||
23 | skb_shinfo(skb)->tskey = ts_seq; | ||
24 | return; | ||
25 | } | ||
26 | |||
27 | skb = skb->next; | ||
28 | seq += mss; | ||
29 | } | ||
30 | } | ||
31 | |||
17 | struct sk_buff *tcp_gso_segment(struct sk_buff *skb, | 32 | struct sk_buff *tcp_gso_segment(struct sk_buff *skb, |
18 | netdev_features_t features) | 33 | netdev_features_t features) |
19 | { | 34 | { |
@@ -91,6 +106,9 @@ struct sk_buff *tcp_gso_segment(struct sk_buff *skb, | |||
91 | th = tcp_hdr(skb); | 106 | th = tcp_hdr(skb); |
92 | seq = ntohl(th->seq); | 107 | seq = ntohl(th->seq); |
93 | 108 | ||
109 | if (unlikely(skb_shinfo(gso_skb)->tx_flags & SKBTX_SW_TSTAMP)) | ||
110 | tcp_gso_tstamp(segs, skb_shinfo(gso_skb)->tskey, seq, mss); | ||
111 | |||
94 | newcheck = ~csum_fold((__force __wsum)((__force u32)th->check + | 112 | newcheck = ~csum_fold((__force __wsum)((__force u32)th->check + |
95 | (__force u32)delta)); | 113 | (__force u32)delta)); |
96 | 114 | ||
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 179b51e6bda3..5a7c41fbc6d3 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
@@ -800,7 +800,7 @@ void tcp_release_cb(struct sock *sk) | |||
800 | __sock_put(sk); | 800 | __sock_put(sk); |
801 | } | 801 | } |
802 | if (flags & (1UL << TCP_MTU_REDUCED_DEFERRED)) { | 802 | if (flags & (1UL << TCP_MTU_REDUCED_DEFERRED)) { |
803 | sk->sk_prot->mtu_reduced(sk); | 803 | inet_csk(sk)->icsk_af_ops->mtu_reduced(sk); |
804 | __sock_put(sk); | 804 | __sock_put(sk); |
805 | } | 805 | } |
806 | } | 806 | } |
@@ -916,6 +916,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, | |||
916 | skb_orphan(skb); | 916 | skb_orphan(skb); |
917 | skb->sk = sk; | 917 | skb->sk = sk; |
918 | skb->destructor = tcp_wfree; | 918 | skb->destructor = tcp_wfree; |
919 | skb_set_hash_from_sk(skb, sk); | ||
919 | atomic_add(skb->truesize, &sk->sk_wmem_alloc); | 920 | atomic_add(skb->truesize, &sk->sk_wmem_alloc); |
920 | 921 | ||
921 | /* Build TCP header and checksum it. */ | 922 | /* Build TCP header and checksum it. */ |
@@ -978,7 +979,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, | |||
978 | if (likely(err <= 0)) | 979 | if (likely(err <= 0)) |
979 | return err; | 980 | return err; |
980 | 981 | ||
981 | tcp_enter_cwr(sk, 1); | 982 | tcp_enter_cwr(sk); |
982 | 983 | ||
983 | return net_xmit_eval(err); | 984 | return net_xmit_eval(err); |
984 | } | 985 | } |
@@ -1068,6 +1069,21 @@ static void tcp_adjust_pcount(struct sock *sk, const struct sk_buff *skb, int de | |||
1068 | tcp_verify_left_out(tp); | 1069 | tcp_verify_left_out(tp); |
1069 | } | 1070 | } |
1070 | 1071 | ||
1072 | static void tcp_fragment_tstamp(struct sk_buff *skb, struct sk_buff *skb2) | ||
1073 | { | ||
1074 | struct skb_shared_info *shinfo = skb_shinfo(skb); | ||
1075 | |||
1076 | if (unlikely(shinfo->tx_flags & SKBTX_ANY_TSTAMP) && | ||
1077 | !before(shinfo->tskey, TCP_SKB_CB(skb2)->seq)) { | ||
1078 | struct skb_shared_info *shinfo2 = skb_shinfo(skb2); | ||
1079 | u8 tsflags = shinfo->tx_flags & SKBTX_ANY_TSTAMP; | ||
1080 | |||
1081 | shinfo->tx_flags &= ~tsflags; | ||
1082 | shinfo2->tx_flags |= tsflags; | ||
1083 | swap(shinfo->tskey, shinfo2->tskey); | ||
1084 | } | ||
1085 | } | ||
1086 | |||
1071 | /* Function to create two new TCP segments. Shrinks the given segment | 1087 | /* Function to create two new TCP segments. Shrinks the given segment |
1072 | * to the specified size and appends a new segment with the rest of the | 1088 | * to the specified size and appends a new segment with the rest of the |
1073 | * packet to the list. This won't be called frequently, I hope. | 1089 | * packet to the list. This won't be called frequently, I hope. |
@@ -1135,6 +1151,7 @@ int tcp_fragment(struct sock *sk, struct sk_buff *skb, u32 len, | |||
1135 | */ | 1151 | */ |
1136 | TCP_SKB_CB(buff)->when = TCP_SKB_CB(skb)->when; | 1152 | TCP_SKB_CB(buff)->when = TCP_SKB_CB(skb)->when; |
1137 | buff->tstamp = skb->tstamp; | 1153 | buff->tstamp = skb->tstamp; |
1154 | tcp_fragment_tstamp(skb, buff); | ||
1138 | 1155 | ||
1139 | old_factor = tcp_skb_pcount(skb); | 1156 | old_factor = tcp_skb_pcount(skb); |
1140 | 1157 | ||
@@ -1651,6 +1668,7 @@ static int tso_fragment(struct sock *sk, struct sk_buff *skb, unsigned int len, | |||
1651 | 1668 | ||
1652 | buff->ip_summed = skb->ip_summed = CHECKSUM_PARTIAL; | 1669 | buff->ip_summed = skb->ip_summed = CHECKSUM_PARTIAL; |
1653 | skb_split(skb, buff, len); | 1670 | skb_split(skb, buff, len); |
1671 | tcp_fragment_tstamp(skb, buff); | ||
1654 | 1672 | ||
1655 | /* Fix up tso_factor for both original and new SKB. */ | 1673 | /* Fix up tso_factor for both original and new SKB. */ |
1656 | tcp_set_skb_tso_segs(sk, skb, mss_now); | 1674 | tcp_set_skb_tso_segs(sk, skb, mss_now); |
@@ -1916,8 +1934,11 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle, | |||
1916 | tso_segs = tcp_init_tso_segs(sk, skb, mss_now); | 1934 | tso_segs = tcp_init_tso_segs(sk, skb, mss_now); |
1917 | BUG_ON(!tso_segs); | 1935 | BUG_ON(!tso_segs); |
1918 | 1936 | ||
1919 | if (unlikely(tp->repair) && tp->repair_queue == TCP_SEND_QUEUE) | 1937 | if (unlikely(tp->repair) && tp->repair_queue == TCP_SEND_QUEUE) { |
1938 | /* "when" is used as a start point for the retransmit timer */ | ||
1939 | TCP_SKB_CB(skb)->when = tcp_time_stamp; | ||
1920 | goto repair; /* Skip network transmission */ | 1940 | goto repair; /* Skip network transmission */ |
1941 | } | ||
1921 | 1942 | ||
1922 | cwnd_quota = tcp_cwnd_test(tp, skb); | 1943 | cwnd_quota = tcp_cwnd_test(tp, skb); |
1923 | if (!cwnd_quota) { | 1944 | if (!cwnd_quota) { |
@@ -3301,3 +3322,18 @@ void tcp_send_probe0(struct sock *sk) | |||
3301 | TCP_RTO_MAX); | 3322 | TCP_RTO_MAX); |
3302 | } | 3323 | } |
3303 | } | 3324 | } |
3325 | |||
3326 | int tcp_rtx_synack(struct sock *sk, struct request_sock *req) | ||
3327 | { | ||
3328 | const struct tcp_request_sock_ops *af_ops = tcp_rsk(req)->af_specific; | ||
3329 | struct flowi fl; | ||
3330 | int res; | ||
3331 | |||
3332 | res = af_ops->send_synack(sk, NULL, &fl, req, 0, NULL); | ||
3333 | if (!res) { | ||
3334 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS); | ||
3335 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSYNRETRANS); | ||
3336 | } | ||
3337 | return res; | ||
3338 | } | ||
3339 | EXPORT_SYMBOL(tcp_rtx_synack); | ||
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 286227abed10..df90cd1ce37f 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c | |||
@@ -391,7 +391,7 @@ void tcp_retransmit_timer(struct sock *sk) | |||
391 | tcp_write_err(sk); | 391 | tcp_write_err(sk); |
392 | goto out; | 392 | goto out; |
393 | } | 393 | } |
394 | tcp_enter_loss(sk, 0); | 394 | tcp_enter_loss(sk); |
395 | tcp_retransmit_skb(sk, tcp_write_queue_head(sk)); | 395 | tcp_retransmit_skb(sk, tcp_write_queue_head(sk)); |
396 | __sk_dst_reset(sk); | 396 | __sk_dst_reset(sk); |
397 | goto out_reset_timer; | 397 | goto out_reset_timer; |
@@ -422,7 +422,7 @@ void tcp_retransmit_timer(struct sock *sk) | |||
422 | NET_INC_STATS_BH(sock_net(sk), mib_idx); | 422 | NET_INC_STATS_BH(sock_net(sk), mib_idx); |
423 | } | 423 | } |
424 | 424 | ||
425 | tcp_enter_loss(sk, 0); | 425 | tcp_enter_loss(sk); |
426 | 426 | ||
427 | if (tcp_retransmit_skb(sk, tcp_write_queue_head(sk)) > 0) { | 427 | if (tcp_retransmit_skb(sk, tcp_write_queue_head(sk)) > 0) { |
428 | /* Retransmission failed because of local congestion, | 428 | /* Retransmission failed because of local congestion, |
diff --git a/net/ipv4/tcp_vegas.c b/net/ipv4/tcp_vegas.c index 9a5e05f27f4f..b40ad897f945 100644 --- a/net/ipv4/tcp_vegas.c +++ b/net/ipv4/tcp_vegas.c | |||
@@ -218,7 +218,8 @@ static void tcp_vegas_cong_avoid(struct sock *sk, u32 ack, u32 acked) | |||
218 | * This is: | 218 | * This is: |
219 | * (actual rate in segments) * baseRTT | 219 | * (actual rate in segments) * baseRTT |
220 | */ | 220 | */ |
221 | target_cwnd = tp->snd_cwnd * vegas->baseRTT / rtt; | 221 | target_cwnd = (u64)tp->snd_cwnd * vegas->baseRTT; |
222 | do_div(target_cwnd, rtt); | ||
222 | 223 | ||
223 | /* Calculate the difference between the window we had, | 224 | /* Calculate the difference between the window we had, |
224 | * and the window we would like to have. This quantity | 225 | * and the window we would like to have. This quantity |
diff --git a/net/ipv4/tcp_veno.c b/net/ipv4/tcp_veno.c index 27b9825753d1..8276977d2c85 100644 --- a/net/ipv4/tcp_veno.c +++ b/net/ipv4/tcp_veno.c | |||
@@ -144,7 +144,7 @@ static void tcp_veno_cong_avoid(struct sock *sk, u32 ack, u32 acked) | |||
144 | 144 | ||
145 | rtt = veno->minrtt; | 145 | rtt = veno->minrtt; |
146 | 146 | ||
147 | target_cwnd = (tp->snd_cwnd * veno->basertt); | 147 | target_cwnd = (u64)tp->snd_cwnd * veno->basertt; |
148 | target_cwnd <<= V_PARAM_SHIFT; | 148 | target_cwnd <<= V_PARAM_SHIFT; |
149 | do_div(target_cwnd, rtt); | 149 | do_div(target_cwnd, rtt); |
150 | 150 | ||
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 7d5a8661df76..f57c0e4c2326 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
@@ -594,27 +594,6 @@ static inline bool __udp_is_mcast_sock(struct net *net, struct sock *sk, | |||
594 | return true; | 594 | return true; |
595 | } | 595 | } |
596 | 596 | ||
597 | static inline struct sock *udp_v4_mcast_next(struct net *net, struct sock *sk, | ||
598 | __be16 loc_port, __be32 loc_addr, | ||
599 | __be16 rmt_port, __be32 rmt_addr, | ||
600 | int dif) | ||
601 | { | ||
602 | struct hlist_nulls_node *node; | ||
603 | struct sock *s = sk; | ||
604 | unsigned short hnum = ntohs(loc_port); | ||
605 | |||
606 | sk_nulls_for_each_from(s, node) { | ||
607 | if (__udp_is_mcast_sock(net, s, | ||
608 | loc_port, loc_addr, | ||
609 | rmt_port, rmt_addr, | ||
610 | dif, hnum)) | ||
611 | goto found; | ||
612 | } | ||
613 | s = NULL; | ||
614 | found: | ||
615 | return s; | ||
616 | } | ||
617 | |||
618 | /* | 597 | /* |
619 | * This routine is called by the ICMP module when it gets some | 598 | * This routine is called by the ICMP module when it gets some |
620 | * sort of error condition. If err < 0 then the socket should | 599 | * sort of error condition. If err < 0 then the socket should |
@@ -1588,7 +1567,7 @@ int udp_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
1588 | goto csum_error; | 1567 | goto csum_error; |
1589 | 1568 | ||
1590 | 1569 | ||
1591 | if (sk_rcvqueues_full(sk, skb, sk->sk_rcvbuf)) { | 1570 | if (sk_rcvqueues_full(sk, sk->sk_rcvbuf)) { |
1592 | UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_RCVBUFERRORS, | 1571 | UDP_INC_STATS_BH(sock_net(sk), UDP_MIB_RCVBUFERRORS, |
1593 | is_udplite); | 1572 | is_udplite); |
1594 | goto drop; | 1573 | goto drop; |
@@ -1640,6 +1619,8 @@ static void flush_stack(struct sock **stack, unsigned int count, | |||
1640 | 1619 | ||
1641 | if (skb1 && udp_queue_rcv_skb(sk, skb1) <= 0) | 1620 | if (skb1 && udp_queue_rcv_skb(sk, skb1) <= 0) |
1642 | skb1 = NULL; | 1621 | skb1 = NULL; |
1622 | |||
1623 | sock_put(sk); | ||
1643 | } | 1624 | } |
1644 | if (unlikely(skb1)) | 1625 | if (unlikely(skb1)) |
1645 | kfree_skb(skb1); | 1626 | kfree_skb(skb1); |
@@ -1668,41 +1649,50 @@ static int __udp4_lib_mcast_deliver(struct net *net, struct sk_buff *skb, | |||
1668 | struct udp_table *udptable) | 1649 | struct udp_table *udptable) |
1669 | { | 1650 | { |
1670 | struct sock *sk, *stack[256 / sizeof(struct sock *)]; | 1651 | struct sock *sk, *stack[256 / sizeof(struct sock *)]; |
1671 | struct udp_hslot *hslot = udp_hashslot(udptable, net, ntohs(uh->dest)); | 1652 | struct hlist_nulls_node *node; |
1672 | int dif; | 1653 | unsigned short hnum = ntohs(uh->dest); |
1673 | unsigned int i, count = 0; | 1654 | struct udp_hslot *hslot = udp_hashslot(udptable, net, hnum); |
1655 | int dif = skb->dev->ifindex; | ||
1656 | unsigned int count = 0, offset = offsetof(typeof(*sk), sk_nulls_node); | ||
1657 | unsigned int hash2 = 0, hash2_any = 0, use_hash2 = (hslot->count > 10); | ||
1658 | |||
1659 | if (use_hash2) { | ||
1660 | hash2_any = udp4_portaddr_hash(net, htonl(INADDR_ANY), hnum) & | ||
1661 | udp_table.mask; | ||
1662 | hash2 = udp4_portaddr_hash(net, daddr, hnum) & udp_table.mask; | ||
1663 | start_lookup: | ||
1664 | hslot = &udp_table.hash2[hash2]; | ||
1665 | offset = offsetof(typeof(*sk), __sk_common.skc_portaddr_node); | ||
1666 | } | ||
1674 | 1667 | ||
1675 | spin_lock(&hslot->lock); | 1668 | spin_lock(&hslot->lock); |
1676 | sk = sk_nulls_head(&hslot->head); | 1669 | sk_nulls_for_each_entry_offset(sk, node, &hslot->head, offset) { |
1677 | dif = skb->dev->ifindex; | 1670 | if (__udp_is_mcast_sock(net, sk, |
1678 | sk = udp_v4_mcast_next(net, sk, uh->dest, daddr, uh->source, saddr, dif); | 1671 | uh->dest, daddr, |
1679 | while (sk) { | 1672 | uh->source, saddr, |
1680 | stack[count++] = sk; | 1673 | dif, hnum)) { |
1681 | sk = udp_v4_mcast_next(net, sk_nulls_next(sk), uh->dest, | 1674 | if (unlikely(count == ARRAY_SIZE(stack))) { |
1682 | daddr, uh->source, saddr, dif); | 1675 | flush_stack(stack, count, skb, ~0); |
1683 | if (unlikely(count == ARRAY_SIZE(stack))) { | 1676 | count = 0; |
1684 | if (!sk) | 1677 | } |
1685 | break; | 1678 | stack[count++] = sk; |
1686 | flush_stack(stack, count, skb, ~0); | 1679 | sock_hold(sk); |
1687 | count = 0; | ||
1688 | } | 1680 | } |
1689 | } | 1681 | } |
1690 | /* | ||
1691 | * before releasing chain lock, we must take a reference on sockets | ||
1692 | */ | ||
1693 | for (i = 0; i < count; i++) | ||
1694 | sock_hold(stack[i]); | ||
1695 | 1682 | ||
1696 | spin_unlock(&hslot->lock); | 1683 | spin_unlock(&hslot->lock); |
1697 | 1684 | ||
1685 | /* Also lookup *:port if we are using hash2 and haven't done so yet. */ | ||
1686 | if (use_hash2 && hash2 != hash2_any) { | ||
1687 | hash2 = hash2_any; | ||
1688 | goto start_lookup; | ||
1689 | } | ||
1690 | |||
1698 | /* | 1691 | /* |
1699 | * do the slow work with no lock held | 1692 | * do the slow work with no lock held |
1700 | */ | 1693 | */ |
1701 | if (count) { | 1694 | if (count) { |
1702 | flush_stack(stack, count, skb, count - 1); | 1695 | flush_stack(stack, count, skb, count - 1); |
1703 | |||
1704 | for (i = 0; i < count; i++) | ||
1705 | sock_put(stack[i]); | ||
1706 | } else { | 1696 | } else { |
1707 | kfree_skb(skb); | 1697 | kfree_skb(skb); |
1708 | } | 1698 | } |
@@ -2526,79 +2516,3 @@ void __init udp_init(void) | |||
2526 | sysctl_udp_rmem_min = SK_MEM_QUANTUM; | 2516 | sysctl_udp_rmem_min = SK_MEM_QUANTUM; |
2527 | sysctl_udp_wmem_min = SK_MEM_QUANTUM; | 2517 | sysctl_udp_wmem_min = SK_MEM_QUANTUM; |
2528 | } | 2518 | } |
2529 | |||
2530 | struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb, | ||
2531 | netdev_features_t features) | ||
2532 | { | ||
2533 | struct sk_buff *segs = ERR_PTR(-EINVAL); | ||
2534 | u16 mac_offset = skb->mac_header; | ||
2535 | int mac_len = skb->mac_len; | ||
2536 | int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb); | ||
2537 | __be16 protocol = skb->protocol; | ||
2538 | netdev_features_t enc_features; | ||
2539 | int udp_offset, outer_hlen; | ||
2540 | unsigned int oldlen; | ||
2541 | bool need_csum; | ||
2542 | |||
2543 | oldlen = (u16)~skb->len; | ||
2544 | |||
2545 | if (unlikely(!pskb_may_pull(skb, tnl_hlen))) | ||
2546 | goto out; | ||
2547 | |||
2548 | skb->encapsulation = 0; | ||
2549 | __skb_pull(skb, tnl_hlen); | ||
2550 | skb_reset_mac_header(skb); | ||
2551 | skb_set_network_header(skb, skb_inner_network_offset(skb)); | ||
2552 | skb->mac_len = skb_inner_network_offset(skb); | ||
2553 | skb->protocol = htons(ETH_P_TEB); | ||
2554 | |||
2555 | need_csum = !!(skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM); | ||
2556 | if (need_csum) | ||
2557 | skb->encap_hdr_csum = 1; | ||
2558 | |||
2559 | /* segment inner packet. */ | ||
2560 | enc_features = skb->dev->hw_enc_features & netif_skb_features(skb); | ||
2561 | segs = skb_mac_gso_segment(skb, enc_features); | ||
2562 | if (!segs || IS_ERR(segs)) { | ||
2563 | skb_gso_error_unwind(skb, protocol, tnl_hlen, mac_offset, | ||
2564 | mac_len); | ||
2565 | goto out; | ||
2566 | } | ||
2567 | |||
2568 | outer_hlen = skb_tnl_header_len(skb); | ||
2569 | udp_offset = outer_hlen - tnl_hlen; | ||
2570 | skb = segs; | ||
2571 | do { | ||
2572 | struct udphdr *uh; | ||
2573 | int len; | ||
2574 | |||
2575 | skb_reset_inner_headers(skb); | ||
2576 | skb->encapsulation = 1; | ||
2577 | |||
2578 | skb->mac_len = mac_len; | ||
2579 | |||
2580 | skb_push(skb, outer_hlen); | ||
2581 | skb_reset_mac_header(skb); | ||
2582 | skb_set_network_header(skb, mac_len); | ||
2583 | skb_set_transport_header(skb, udp_offset); | ||
2584 | len = skb->len - udp_offset; | ||
2585 | uh = udp_hdr(skb); | ||
2586 | uh->len = htons(len); | ||
2587 | |||
2588 | if (need_csum) { | ||
2589 | __be32 delta = htonl(oldlen + len); | ||
2590 | |||
2591 | uh->check = ~csum_fold((__force __wsum) | ||
2592 | ((__force u32)uh->check + | ||
2593 | (__force u32)delta)); | ||
2594 | uh->check = gso_make_checksum(skb, ~uh->check); | ||
2595 | |||
2596 | if (uh->check == 0) | ||
2597 | uh->check = CSUM_MANGLED_0; | ||
2598 | } | ||
2599 | |||
2600 | skb->protocol = protocol; | ||
2601 | } while ((skb = skb->next)); | ||
2602 | out: | ||
2603 | return segs; | ||
2604 | } | ||
diff --git a/net/ipv4/udp_offload.c b/net/ipv4/udp_offload.c index 546d2d439dda..59035bc3008d 100644 --- a/net/ipv4/udp_offload.c +++ b/net/ipv4/udp_offload.c | |||
@@ -47,6 +47,82 @@ static int udp4_ufo_send_check(struct sk_buff *skb) | |||
47 | return 0; | 47 | return 0; |
48 | } | 48 | } |
49 | 49 | ||
50 | struct sk_buff *skb_udp_tunnel_segment(struct sk_buff *skb, | ||
51 | netdev_features_t features) | ||
52 | { | ||
53 | struct sk_buff *segs = ERR_PTR(-EINVAL); | ||
54 | u16 mac_offset = skb->mac_header; | ||
55 | int mac_len = skb->mac_len; | ||
56 | int tnl_hlen = skb_inner_mac_header(skb) - skb_transport_header(skb); | ||
57 | __be16 protocol = skb->protocol; | ||
58 | netdev_features_t enc_features; | ||
59 | int udp_offset, outer_hlen; | ||
60 | unsigned int oldlen; | ||
61 | bool need_csum; | ||
62 | |||
63 | oldlen = (u16)~skb->len; | ||
64 | |||
65 | if (unlikely(!pskb_may_pull(skb, tnl_hlen))) | ||
66 | goto out; | ||
67 | |||
68 | skb->encapsulation = 0; | ||
69 | __skb_pull(skb, tnl_hlen); | ||
70 | skb_reset_mac_header(skb); | ||
71 | skb_set_network_header(skb, skb_inner_network_offset(skb)); | ||
72 | skb->mac_len = skb_inner_network_offset(skb); | ||
73 | skb->protocol = htons(ETH_P_TEB); | ||
74 | |||
75 | need_csum = !!(skb_shinfo(skb)->gso_type & SKB_GSO_UDP_TUNNEL_CSUM); | ||
76 | if (need_csum) | ||
77 | skb->encap_hdr_csum = 1; | ||
78 | |||
79 | /* segment inner packet. */ | ||
80 | enc_features = skb->dev->hw_enc_features & netif_skb_features(skb); | ||
81 | segs = skb_mac_gso_segment(skb, enc_features); | ||
82 | if (IS_ERR_OR_NULL(segs)) { | ||
83 | skb_gso_error_unwind(skb, protocol, tnl_hlen, mac_offset, | ||
84 | mac_len); | ||
85 | goto out; | ||
86 | } | ||
87 | |||
88 | outer_hlen = skb_tnl_header_len(skb); | ||
89 | udp_offset = outer_hlen - tnl_hlen; | ||
90 | skb = segs; | ||
91 | do { | ||
92 | struct udphdr *uh; | ||
93 | int len; | ||
94 | |||
95 | skb_reset_inner_headers(skb); | ||
96 | skb->encapsulation = 1; | ||
97 | |||
98 | skb->mac_len = mac_len; | ||
99 | |||
100 | skb_push(skb, outer_hlen); | ||
101 | skb_reset_mac_header(skb); | ||
102 | skb_set_network_header(skb, mac_len); | ||
103 | skb_set_transport_header(skb, udp_offset); | ||
104 | len = skb->len - udp_offset; | ||
105 | uh = udp_hdr(skb); | ||
106 | uh->len = htons(len); | ||
107 | |||
108 | if (need_csum) { | ||
109 | __be32 delta = htonl(oldlen + len); | ||
110 | |||
111 | uh->check = ~csum_fold((__force __wsum) | ||
112 | ((__force u32)uh->check + | ||
113 | (__force u32)delta)); | ||
114 | uh->check = gso_make_checksum(skb, ~uh->check); | ||
115 | |||
116 | if (uh->check == 0) | ||
117 | uh->check = CSUM_MANGLED_0; | ||
118 | } | ||
119 | |||
120 | skb->protocol = protocol; | ||
121 | } while ((skb = skb->next)); | ||
122 | out: | ||
123 | return segs; | ||
124 | } | ||
125 | |||
50 | static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb, | 126 | static struct sk_buff *udp4_ufo_fragment(struct sk_buff *skb, |
51 | netdev_features_t features) | 127 | netdev_features_t features) |
52 | { | 128 | { |
diff --git a/net/ipv4/udp_tunnel.c b/net/ipv4/udp_tunnel.c new file mode 100644 index 000000000000..61ec1a65207e --- /dev/null +++ b/net/ipv4/udp_tunnel.c | |||
@@ -0,0 +1,100 @@ | |||
1 | #include <linux/module.h> | ||
2 | #include <linux/errno.h> | ||
3 | #include <linux/socket.h> | ||
4 | #include <linux/udp.h> | ||
5 | #include <linux/types.h> | ||
6 | #include <linux/kernel.h> | ||
7 | #include <net/udp.h> | ||
8 | #include <net/udp_tunnel.h> | ||
9 | #include <net/net_namespace.h> | ||
10 | |||
11 | int udp_sock_create(struct net *net, struct udp_port_cfg *cfg, | ||
12 | struct socket **sockp) | ||
13 | { | ||
14 | int err = -EINVAL; | ||
15 | struct socket *sock = NULL; | ||
16 | |||
17 | #if IS_ENABLED(CONFIG_IPV6) | ||
18 | if (cfg->family == AF_INET6) { | ||
19 | struct sockaddr_in6 udp6_addr; | ||
20 | |||
21 | err = sock_create_kern(AF_INET6, SOCK_DGRAM, 0, &sock); | ||
22 | if (err < 0) | ||
23 | goto error; | ||
24 | |||
25 | sk_change_net(sock->sk, net); | ||
26 | |||
27 | udp6_addr.sin6_family = AF_INET6; | ||
28 | memcpy(&udp6_addr.sin6_addr, &cfg->local_ip6, | ||
29 | sizeof(udp6_addr.sin6_addr)); | ||
30 | udp6_addr.sin6_port = cfg->local_udp_port; | ||
31 | err = kernel_bind(sock, (struct sockaddr *)&udp6_addr, | ||
32 | sizeof(udp6_addr)); | ||
33 | if (err < 0) | ||
34 | goto error; | ||
35 | |||
36 | if (cfg->peer_udp_port) { | ||
37 | udp6_addr.sin6_family = AF_INET6; | ||
38 | memcpy(&udp6_addr.sin6_addr, &cfg->peer_ip6, | ||
39 | sizeof(udp6_addr.sin6_addr)); | ||
40 | udp6_addr.sin6_port = cfg->peer_udp_port; | ||
41 | err = kernel_connect(sock, | ||
42 | (struct sockaddr *)&udp6_addr, | ||
43 | sizeof(udp6_addr), 0); | ||
44 | } | ||
45 | if (err < 0) | ||
46 | goto error; | ||
47 | |||
48 | udp_set_no_check6_tx(sock->sk, !cfg->use_udp6_tx_checksums); | ||
49 | udp_set_no_check6_rx(sock->sk, !cfg->use_udp6_rx_checksums); | ||
50 | } else | ||
51 | #endif | ||
52 | if (cfg->family == AF_INET) { | ||
53 | struct sockaddr_in udp_addr; | ||
54 | |||
55 | err = sock_create_kern(AF_INET, SOCK_DGRAM, 0, &sock); | ||
56 | if (err < 0) | ||
57 | goto error; | ||
58 | |||
59 | sk_change_net(sock->sk, net); | ||
60 | |||
61 | udp_addr.sin_family = AF_INET; | ||
62 | udp_addr.sin_addr = cfg->local_ip; | ||
63 | udp_addr.sin_port = cfg->local_udp_port; | ||
64 | err = kernel_bind(sock, (struct sockaddr *)&udp_addr, | ||
65 | sizeof(udp_addr)); | ||
66 | if (err < 0) | ||
67 | goto error; | ||
68 | |||
69 | if (cfg->peer_udp_port) { | ||
70 | udp_addr.sin_family = AF_INET; | ||
71 | udp_addr.sin_addr = cfg->peer_ip; | ||
72 | udp_addr.sin_port = cfg->peer_udp_port; | ||
73 | err = kernel_connect(sock, | ||
74 | (struct sockaddr *)&udp_addr, | ||
75 | sizeof(udp_addr), 0); | ||
76 | if (err < 0) | ||
77 | goto error; | ||
78 | } | ||
79 | |||
80 | sock->sk->sk_no_check_tx = !cfg->use_udp_checksums; | ||
81 | } else { | ||
82 | return -EPFNOSUPPORT; | ||
83 | } | ||
84 | |||
85 | |||
86 | *sockp = sock; | ||
87 | |||
88 | return 0; | ||
89 | |||
90 | error: | ||
91 | if (sock) { | ||
92 | kernel_sock_shutdown(sock, SHUT_RDWR); | ||
93 | sk_release_kernel(sock->sk); | ||
94 | } | ||
95 | *sockp = NULL; | ||
96 | return err; | ||
97 | } | ||
98 | EXPORT_SYMBOL(udp_sock_create); | ||
99 | |||
100 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/ipv4/xfrm4_protocol.c b/net/ipv4/xfrm4_protocol.c index a2ce0101eaac..dccefa9d84cf 100644 --- a/net/ipv4/xfrm4_protocol.c +++ b/net/ipv4/xfrm4_protocol.c | |||
@@ -124,7 +124,7 @@ static int xfrm4_ah_rcv(struct sk_buff *skb) | |||
124 | 124 | ||
125 | for_each_protocol_rcu(ah4_handlers, handler) | 125 | for_each_protocol_rcu(ah4_handlers, handler) |
126 | if ((ret = handler->handler(skb)) != -EINVAL) | 126 | if ((ret = handler->handler(skb)) != -EINVAL) |
127 | return ret;; | 127 | return ret; |
128 | 128 | ||
129 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); | 129 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); |
130 | 130 | ||
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index 5667b3003af9..3e118dfddd02 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c | |||
@@ -108,11 +108,12 @@ static inline u32 cstamp_delta(unsigned long cstamp) | |||
108 | } | 108 | } |
109 | 109 | ||
110 | #ifdef CONFIG_SYSCTL | 110 | #ifdef CONFIG_SYSCTL |
111 | static void addrconf_sysctl_register(struct inet6_dev *idev); | 111 | static int addrconf_sysctl_register(struct inet6_dev *idev); |
112 | static void addrconf_sysctl_unregister(struct inet6_dev *idev); | 112 | static void addrconf_sysctl_unregister(struct inet6_dev *idev); |
113 | #else | 113 | #else |
114 | static inline void addrconf_sysctl_register(struct inet6_dev *idev) | 114 | static inline int addrconf_sysctl_register(struct inet6_dev *idev) |
115 | { | 115 | { |
116 | return 0; | ||
116 | } | 117 | } |
117 | 118 | ||
118 | static inline void addrconf_sysctl_unregister(struct inet6_dev *idev) | 119 | static inline void addrconf_sysctl_unregister(struct inet6_dev *idev) |
@@ -186,6 +187,7 @@ static struct ipv6_devconf ipv6_devconf __read_mostly = { | |||
186 | .max_desync_factor = MAX_DESYNC_FACTOR, | 187 | .max_desync_factor = MAX_DESYNC_FACTOR, |
187 | .max_addresses = IPV6_MAX_ADDRESSES, | 188 | .max_addresses = IPV6_MAX_ADDRESSES, |
188 | .accept_ra_defrtr = 1, | 189 | .accept_ra_defrtr = 1, |
190 | .accept_ra_from_local = 0, | ||
189 | .accept_ra_pinfo = 1, | 191 | .accept_ra_pinfo = 1, |
190 | #ifdef CONFIG_IPV6_ROUTER_PREF | 192 | #ifdef CONFIG_IPV6_ROUTER_PREF |
191 | .accept_ra_rtr_pref = 1, | 193 | .accept_ra_rtr_pref = 1, |
@@ -222,6 +224,7 @@ static struct ipv6_devconf ipv6_devconf_dflt __read_mostly = { | |||
222 | .max_desync_factor = MAX_DESYNC_FACTOR, | 224 | .max_desync_factor = MAX_DESYNC_FACTOR, |
223 | .max_addresses = IPV6_MAX_ADDRESSES, | 225 | .max_addresses = IPV6_MAX_ADDRESSES, |
224 | .accept_ra_defrtr = 1, | 226 | .accept_ra_defrtr = 1, |
227 | .accept_ra_from_local = 0, | ||
225 | .accept_ra_pinfo = 1, | 228 | .accept_ra_pinfo = 1, |
226 | #ifdef CONFIG_IPV6_ROUTER_PREF | 229 | #ifdef CONFIG_IPV6_ROUTER_PREF |
227 | .accept_ra_rtr_pref = 1, | 230 | .accept_ra_rtr_pref = 1, |
@@ -308,16 +311,16 @@ err_ip: | |||
308 | static struct inet6_dev *ipv6_add_dev(struct net_device *dev) | 311 | static struct inet6_dev *ipv6_add_dev(struct net_device *dev) |
309 | { | 312 | { |
310 | struct inet6_dev *ndev; | 313 | struct inet6_dev *ndev; |
314 | int err = -ENOMEM; | ||
311 | 315 | ||
312 | ASSERT_RTNL(); | 316 | ASSERT_RTNL(); |
313 | 317 | ||
314 | if (dev->mtu < IPV6_MIN_MTU) | 318 | if (dev->mtu < IPV6_MIN_MTU) |
315 | return NULL; | 319 | return ERR_PTR(-EINVAL); |
316 | 320 | ||
317 | ndev = kzalloc(sizeof(struct inet6_dev), GFP_KERNEL); | 321 | ndev = kzalloc(sizeof(struct inet6_dev), GFP_KERNEL); |
318 | |||
319 | if (ndev == NULL) | 322 | if (ndev == NULL) |
320 | return NULL; | 323 | return ERR_PTR(err); |
321 | 324 | ||
322 | rwlock_init(&ndev->lock); | 325 | rwlock_init(&ndev->lock); |
323 | ndev->dev = dev; | 326 | ndev->dev = dev; |
@@ -330,7 +333,7 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev) | |||
330 | ndev->nd_parms = neigh_parms_alloc(dev, &nd_tbl); | 333 | ndev->nd_parms = neigh_parms_alloc(dev, &nd_tbl); |
331 | if (ndev->nd_parms == NULL) { | 334 | if (ndev->nd_parms == NULL) { |
332 | kfree(ndev); | 335 | kfree(ndev); |
333 | return NULL; | 336 | return ERR_PTR(err); |
334 | } | 337 | } |
335 | if (ndev->cnf.forwarding) | 338 | if (ndev->cnf.forwarding) |
336 | dev_disable_lro(dev); | 339 | dev_disable_lro(dev); |
@@ -344,17 +347,14 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev) | |||
344 | neigh_parms_release(&nd_tbl, ndev->nd_parms); | 347 | neigh_parms_release(&nd_tbl, ndev->nd_parms); |
345 | dev_put(dev); | 348 | dev_put(dev); |
346 | kfree(ndev); | 349 | kfree(ndev); |
347 | return NULL; | 350 | return ERR_PTR(err); |
348 | } | 351 | } |
349 | 352 | ||
350 | if (snmp6_register_dev(ndev) < 0) { | 353 | if (snmp6_register_dev(ndev) < 0) { |
351 | ADBG(KERN_WARNING | 354 | ADBG(KERN_WARNING |
352 | "%s: cannot create /proc/net/dev_snmp6/%s\n", | 355 | "%s: cannot create /proc/net/dev_snmp6/%s\n", |
353 | __func__, dev->name); | 356 | __func__, dev->name); |
354 | neigh_parms_release(&nd_tbl, ndev->nd_parms); | 357 | goto err_release; |
355 | ndev->dead = 1; | ||
356 | in6_dev_finish_destroy(ndev); | ||
357 | return NULL; | ||
358 | } | 358 | } |
359 | 359 | ||
360 | /* One reference from device. We must do this before | 360 | /* One reference from device. We must do this before |
@@ -392,7 +392,12 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev) | |||
392 | 392 | ||
393 | ipv6_mc_init_dev(ndev); | 393 | ipv6_mc_init_dev(ndev); |
394 | ndev->tstamp = jiffies; | 394 | ndev->tstamp = jiffies; |
395 | addrconf_sysctl_register(ndev); | 395 | err = addrconf_sysctl_register(ndev); |
396 | if (err) { | ||
397 | ipv6_mc_destroy_dev(ndev); | ||
398 | del_timer(&ndev->regen_timer); | ||
399 | goto err_release; | ||
400 | } | ||
396 | /* protected by rtnl_lock */ | 401 | /* protected by rtnl_lock */ |
397 | rcu_assign_pointer(dev->ip6_ptr, ndev); | 402 | rcu_assign_pointer(dev->ip6_ptr, ndev); |
398 | 403 | ||
@@ -407,6 +412,12 @@ static struct inet6_dev *ipv6_add_dev(struct net_device *dev) | |||
407 | ipv6_dev_mc_inc(dev, &in6addr_linklocal_allrouters); | 412 | ipv6_dev_mc_inc(dev, &in6addr_linklocal_allrouters); |
408 | 413 | ||
409 | return ndev; | 414 | return ndev; |
415 | |||
416 | err_release: | ||
417 | neigh_parms_release(&nd_tbl, ndev->nd_parms); | ||
418 | ndev->dead = 1; | ||
419 | in6_dev_finish_destroy(ndev); | ||
420 | return ERR_PTR(err); | ||
410 | } | 421 | } |
411 | 422 | ||
412 | static struct inet6_dev *ipv6_find_idev(struct net_device *dev) | 423 | static struct inet6_dev *ipv6_find_idev(struct net_device *dev) |
@@ -418,7 +429,7 @@ static struct inet6_dev *ipv6_find_idev(struct net_device *dev) | |||
418 | idev = __in6_dev_get(dev); | 429 | idev = __in6_dev_get(dev); |
419 | if (!idev) { | 430 | if (!idev) { |
420 | idev = ipv6_add_dev(dev); | 431 | idev = ipv6_add_dev(dev); |
421 | if (!idev) | 432 | if (IS_ERR(idev)) |
422 | return NULL; | 433 | return NULL; |
423 | } | 434 | } |
424 | 435 | ||
@@ -1679,14 +1690,12 @@ void addrconf_dad_failure(struct inet6_ifaddr *ifp) | |||
1679 | addrconf_mod_dad_work(ifp, 0); | 1690 | addrconf_mod_dad_work(ifp, 0); |
1680 | } | 1691 | } |
1681 | 1692 | ||
1682 | /* Join to solicited addr multicast group. */ | 1693 | /* Join to solicited addr multicast group. |
1683 | 1694 | * caller must hold RTNL */ | |
1684 | void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr) | 1695 | void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr) |
1685 | { | 1696 | { |
1686 | struct in6_addr maddr; | 1697 | struct in6_addr maddr; |
1687 | 1698 | ||
1688 | ASSERT_RTNL(); | ||
1689 | |||
1690 | if (dev->flags&(IFF_LOOPBACK|IFF_NOARP)) | 1699 | if (dev->flags&(IFF_LOOPBACK|IFF_NOARP)) |
1691 | return; | 1700 | return; |
1692 | 1701 | ||
@@ -1694,12 +1703,11 @@ void addrconf_join_solict(struct net_device *dev, const struct in6_addr *addr) | |||
1694 | ipv6_dev_mc_inc(dev, &maddr); | 1703 | ipv6_dev_mc_inc(dev, &maddr); |
1695 | } | 1704 | } |
1696 | 1705 | ||
1706 | /* caller must hold RTNL */ | ||
1697 | void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr) | 1707 | void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr) |
1698 | { | 1708 | { |
1699 | struct in6_addr maddr; | 1709 | struct in6_addr maddr; |
1700 | 1710 | ||
1701 | ASSERT_RTNL(); | ||
1702 | |||
1703 | if (idev->dev->flags&(IFF_LOOPBACK|IFF_NOARP)) | 1711 | if (idev->dev->flags&(IFF_LOOPBACK|IFF_NOARP)) |
1704 | return; | 1712 | return; |
1705 | 1713 | ||
@@ -1707,12 +1715,11 @@ void addrconf_leave_solict(struct inet6_dev *idev, const struct in6_addr *addr) | |||
1707 | __ipv6_dev_mc_dec(idev, &maddr); | 1715 | __ipv6_dev_mc_dec(idev, &maddr); |
1708 | } | 1716 | } |
1709 | 1717 | ||
1718 | /* caller must hold RTNL */ | ||
1710 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp) | 1719 | static void addrconf_join_anycast(struct inet6_ifaddr *ifp) |
1711 | { | 1720 | { |
1712 | struct in6_addr addr; | 1721 | struct in6_addr addr; |
1713 | 1722 | ||
1714 | ASSERT_RTNL(); | ||
1715 | |||
1716 | if (ifp->prefix_len >= 127) /* RFC 6164 */ | 1723 | if (ifp->prefix_len >= 127) /* RFC 6164 */ |
1717 | return; | 1724 | return; |
1718 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); | 1725 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); |
@@ -1721,12 +1728,11 @@ static void addrconf_join_anycast(struct inet6_ifaddr *ifp) | |||
1721 | ipv6_dev_ac_inc(ifp->idev->dev, &addr); | 1728 | ipv6_dev_ac_inc(ifp->idev->dev, &addr); |
1722 | } | 1729 | } |
1723 | 1730 | ||
1731 | /* caller must hold RTNL */ | ||
1724 | static void addrconf_leave_anycast(struct inet6_ifaddr *ifp) | 1732 | static void addrconf_leave_anycast(struct inet6_ifaddr *ifp) |
1725 | { | 1733 | { |
1726 | struct in6_addr addr; | 1734 | struct in6_addr addr; |
1727 | 1735 | ||
1728 | ASSERT_RTNL(); | ||
1729 | |||
1730 | if (ifp->prefix_len >= 127) /* RFC 6164 */ | 1736 | if (ifp->prefix_len >= 127) /* RFC 6164 */ |
1731 | return; | 1737 | return; |
1732 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); | 1738 | ipv6_addr_prefix(&addr, &ifp->addr, ifp->prefix_len); |
@@ -2728,9 +2734,25 @@ static void addrconf_add_linklocal(struct inet6_dev *idev, const struct in6_addr | |||
2728 | } | 2734 | } |
2729 | } | 2735 | } |
2730 | 2736 | ||
2737 | static void addrconf_addr_gen(struct inet6_dev *idev, bool prefix_route) | ||
2738 | { | ||
2739 | if (idev->addr_gen_mode == IN6_ADDR_GEN_MODE_EUI64) { | ||
2740 | struct in6_addr addr; | ||
2741 | |||
2742 | ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0); | ||
2743 | /* addrconf_add_linklocal also adds a prefix_route and we | ||
2744 | * only need to care about prefix routes if ipv6_generate_eui64 | ||
2745 | * couldn't generate one. | ||
2746 | */ | ||
2747 | if (ipv6_generate_eui64(addr.s6_addr + 8, idev->dev) == 0) | ||
2748 | addrconf_add_linklocal(idev, &addr); | ||
2749 | else if (prefix_route) | ||
2750 | addrconf_prefix_route(&addr, 64, idev->dev, 0, 0); | ||
2751 | } | ||
2752 | } | ||
2753 | |||
2731 | static void addrconf_dev_config(struct net_device *dev) | 2754 | static void addrconf_dev_config(struct net_device *dev) |
2732 | { | 2755 | { |
2733 | struct in6_addr addr; | ||
2734 | struct inet6_dev *idev; | 2756 | struct inet6_dev *idev; |
2735 | 2757 | ||
2736 | ASSERT_RTNL(); | 2758 | ASSERT_RTNL(); |
@@ -2751,11 +2773,7 @@ static void addrconf_dev_config(struct net_device *dev) | |||
2751 | if (IS_ERR(idev)) | 2773 | if (IS_ERR(idev)) |
2752 | return; | 2774 | return; |
2753 | 2775 | ||
2754 | memset(&addr, 0, sizeof(struct in6_addr)); | 2776 | addrconf_addr_gen(idev, false); |
2755 | addr.s6_addr32[0] = htonl(0xFE800000); | ||
2756 | |||
2757 | if (ipv6_generate_eui64(addr.s6_addr + 8, dev) == 0) | ||
2758 | addrconf_add_linklocal(idev, &addr); | ||
2759 | } | 2777 | } |
2760 | 2778 | ||
2761 | #if IS_ENABLED(CONFIG_IPV6_SIT) | 2779 | #if IS_ENABLED(CONFIG_IPV6_SIT) |
@@ -2777,11 +2795,7 @@ static void addrconf_sit_config(struct net_device *dev) | |||
2777 | } | 2795 | } |
2778 | 2796 | ||
2779 | if (dev->priv_flags & IFF_ISATAP) { | 2797 | if (dev->priv_flags & IFF_ISATAP) { |
2780 | struct in6_addr addr; | 2798 | addrconf_addr_gen(idev, false); |
2781 | |||
2782 | ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0); | ||
2783 | if (!ipv6_generate_eui64(addr.s6_addr + 8, dev)) | ||
2784 | addrconf_add_linklocal(idev, &addr); | ||
2785 | return; | 2799 | return; |
2786 | } | 2800 | } |
2787 | 2801 | ||
@@ -2796,7 +2810,6 @@ static void addrconf_sit_config(struct net_device *dev) | |||
2796 | static void addrconf_gre_config(struct net_device *dev) | 2810 | static void addrconf_gre_config(struct net_device *dev) |
2797 | { | 2811 | { |
2798 | struct inet6_dev *idev; | 2812 | struct inet6_dev *idev; |
2799 | struct in6_addr addr; | ||
2800 | 2813 | ||
2801 | ASSERT_RTNL(); | 2814 | ASSERT_RTNL(); |
2802 | 2815 | ||
@@ -2805,11 +2818,7 @@ static void addrconf_gre_config(struct net_device *dev) | |||
2805 | return; | 2818 | return; |
2806 | } | 2819 | } |
2807 | 2820 | ||
2808 | ipv6_addr_set(&addr, htonl(0xFE800000), 0, 0, 0); | 2821 | addrconf_addr_gen(idev, true); |
2809 | if (!ipv6_generate_eui64(addr.s6_addr + 8, dev)) | ||
2810 | addrconf_add_linklocal(idev, &addr); | ||
2811 | else | ||
2812 | addrconf_prefix_route(&addr, 64, dev, 0, 0); | ||
2813 | } | 2822 | } |
2814 | #endif | 2823 | #endif |
2815 | 2824 | ||
@@ -2825,8 +2834,8 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2825 | case NETDEV_REGISTER: | 2834 | case NETDEV_REGISTER: |
2826 | if (!idev && dev->mtu >= IPV6_MIN_MTU) { | 2835 | if (!idev && dev->mtu >= IPV6_MIN_MTU) { |
2827 | idev = ipv6_add_dev(dev); | 2836 | idev = ipv6_add_dev(dev); |
2828 | if (!idev) | 2837 | if (IS_ERR(idev)) |
2829 | return notifier_from_errno(-ENOMEM); | 2838 | return notifier_from_errno(PTR_ERR(idev)); |
2830 | } | 2839 | } |
2831 | break; | 2840 | break; |
2832 | 2841 | ||
@@ -2846,7 +2855,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2846 | if (!idev && dev->mtu >= IPV6_MIN_MTU) | 2855 | if (!idev && dev->mtu >= IPV6_MIN_MTU) |
2847 | idev = ipv6_add_dev(dev); | 2856 | idev = ipv6_add_dev(dev); |
2848 | 2857 | ||
2849 | if (idev) { | 2858 | if (!IS_ERR_OR_NULL(idev)) { |
2850 | idev->if_flags |= IF_READY; | 2859 | idev->if_flags |= IF_READY; |
2851 | run_pending = 1; | 2860 | run_pending = 1; |
2852 | } | 2861 | } |
@@ -2889,7 +2898,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2889 | break; | 2898 | break; |
2890 | } | 2899 | } |
2891 | 2900 | ||
2892 | if (idev) { | 2901 | if (!IS_ERR_OR_NULL(idev)) { |
2893 | if (run_pending) | 2902 | if (run_pending) |
2894 | addrconf_dad_run(idev); | 2903 | addrconf_dad_run(idev); |
2895 | 2904 | ||
@@ -2924,7 +2933,7 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2924 | 2933 | ||
2925 | if (!idev && dev->mtu >= IPV6_MIN_MTU) { | 2934 | if (!idev && dev->mtu >= IPV6_MIN_MTU) { |
2926 | idev = ipv6_add_dev(dev); | 2935 | idev = ipv6_add_dev(dev); |
2927 | if (idev) | 2936 | if (!IS_ERR(idev)) |
2928 | break; | 2937 | break; |
2929 | } | 2938 | } |
2930 | 2939 | ||
@@ -2945,10 +2954,14 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event, | |||
2945 | if (idev) { | 2954 | if (idev) { |
2946 | snmp6_unregister_dev(idev); | 2955 | snmp6_unregister_dev(idev); |
2947 | addrconf_sysctl_unregister(idev); | 2956 | addrconf_sysctl_unregister(idev); |
2948 | addrconf_sysctl_register(idev); | 2957 | err = addrconf_sysctl_register(idev); |
2949 | err = snmp6_register_dev(idev); | ||
2950 | if (err) | 2958 | if (err) |
2951 | return notifier_from_errno(err); | 2959 | return notifier_from_errno(err); |
2960 | err = snmp6_register_dev(idev); | ||
2961 | if (err) { | ||
2962 | addrconf_sysctl_unregister(idev); | ||
2963 | return notifier_from_errno(err); | ||
2964 | } | ||
2952 | } | 2965 | } |
2953 | break; | 2966 | break; |
2954 | 2967 | ||
@@ -3081,11 +3094,13 @@ static int addrconf_ifdown(struct net_device *dev, int how) | |||
3081 | 3094 | ||
3082 | write_unlock_bh(&idev->lock); | 3095 | write_unlock_bh(&idev->lock); |
3083 | 3096 | ||
3084 | /* Step 5: Discard multicast list */ | 3097 | /* Step 5: Discard anycast and multicast list */ |
3085 | if (how) | 3098 | if (how) { |
3099 | ipv6_ac_destroy_dev(idev); | ||
3086 | ipv6_mc_destroy_dev(idev); | 3100 | ipv6_mc_destroy_dev(idev); |
3087 | else | 3101 | } else { |
3088 | ipv6_mc_down(idev); | 3102 | ipv6_mc_down(idev); |
3103 | } | ||
3089 | 3104 | ||
3090 | idev->tstamp = jiffies; | 3105 | idev->tstamp = jiffies; |
3091 | 3106 | ||
@@ -4321,6 +4336,7 @@ static inline void ipv6_store_devconf(struct ipv6_devconf *cnf, | |||
4321 | array[DEVCONF_FORCE_TLLAO] = cnf->force_tllao; | 4336 | array[DEVCONF_FORCE_TLLAO] = cnf->force_tllao; |
4322 | array[DEVCONF_NDISC_NOTIFY] = cnf->ndisc_notify; | 4337 | array[DEVCONF_NDISC_NOTIFY] = cnf->ndisc_notify; |
4323 | array[DEVCONF_SUPPRESS_FRAG_NDISC] = cnf->suppress_frag_ndisc; | 4338 | array[DEVCONF_SUPPRESS_FRAG_NDISC] = cnf->suppress_frag_ndisc; |
4339 | array[DEVCONF_ACCEPT_RA_FROM_LOCAL] = cnf->accept_ra_from_local; | ||
4324 | } | 4340 | } |
4325 | 4341 | ||
4326 | static inline size_t inet6_ifla6_size(void) | 4342 | static inline size_t inet6_ifla6_size(void) |
@@ -4420,6 +4436,10 @@ static int inet6_fill_ifla6_attrs(struct sk_buff *skb, struct inet6_dev *idev) | |||
4420 | nla = nla_reserve(skb, IFLA_INET6_TOKEN, sizeof(struct in6_addr)); | 4436 | nla = nla_reserve(skb, IFLA_INET6_TOKEN, sizeof(struct in6_addr)); |
4421 | if (nla == NULL) | 4437 | if (nla == NULL) |
4422 | goto nla_put_failure; | 4438 | goto nla_put_failure; |
4439 | |||
4440 | if (nla_put_u8(skb, IFLA_INET6_ADDR_GEN_MODE, idev->addr_gen_mode)) | ||
4441 | goto nla_put_failure; | ||
4442 | |||
4423 | read_lock_bh(&idev->lock); | 4443 | read_lock_bh(&idev->lock); |
4424 | memcpy(nla_data(nla), idev->token.s6_addr, nla_len(nla)); | 4444 | memcpy(nla_data(nla), idev->token.s6_addr, nla_len(nla)); |
4425 | read_unlock_bh(&idev->lock); | 4445 | read_unlock_bh(&idev->lock); |
@@ -4524,8 +4544,21 @@ static int inet6_set_link_af(struct net_device *dev, const struct nlattr *nla) | |||
4524 | if (nla_parse_nested(tb, IFLA_INET6_MAX, nla, NULL) < 0) | 4544 | if (nla_parse_nested(tb, IFLA_INET6_MAX, nla, NULL) < 0) |
4525 | BUG(); | 4545 | BUG(); |
4526 | 4546 | ||
4527 | if (tb[IFLA_INET6_TOKEN]) | 4547 | if (tb[IFLA_INET6_TOKEN]) { |
4528 | err = inet6_set_iftoken(idev, nla_data(tb[IFLA_INET6_TOKEN])); | 4548 | err = inet6_set_iftoken(idev, nla_data(tb[IFLA_INET6_TOKEN])); |
4549 | if (err) | ||
4550 | return err; | ||
4551 | } | ||
4552 | |||
4553 | if (tb[IFLA_INET6_ADDR_GEN_MODE]) { | ||
4554 | u8 mode = nla_get_u8(tb[IFLA_INET6_ADDR_GEN_MODE]); | ||
4555 | |||
4556 | if (mode != IN6_ADDR_GEN_MODE_EUI64 && | ||
4557 | mode != IN6_ADDR_GEN_MODE_NONE) | ||
4558 | return -EINVAL; | ||
4559 | idev->addr_gen_mode = mode; | ||
4560 | err = 0; | ||
4561 | } | ||
4529 | 4562 | ||
4530 | return err; | 4563 | return err; |
4531 | } | 4564 | } |
@@ -4737,24 +4770,21 @@ static void __ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | |||
4737 | addrconf_leave_solict(ifp->idev, &ifp->addr); | 4770 | addrconf_leave_solict(ifp->idev, &ifp->addr); |
4738 | if (!ipv6_addr_any(&ifp->peer_addr)) { | 4771 | if (!ipv6_addr_any(&ifp->peer_addr)) { |
4739 | struct rt6_info *rt; | 4772 | struct rt6_info *rt; |
4740 | struct net_device *dev = ifp->idev->dev; | 4773 | |
4741 | 4774 | rt = addrconf_get_prefix_route(&ifp->peer_addr, 128, | |
4742 | rt = rt6_lookup(dev_net(dev), &ifp->peer_addr, NULL, | 4775 | ifp->idev->dev, 0, 0); |
4743 | dev->ifindex, 1); | 4776 | if (rt && ip6_del_rt(rt)) |
4744 | if (rt) { | 4777 | dst_free(&rt->dst); |
4745 | dst_hold(&rt->dst); | ||
4746 | if (ip6_del_rt(rt)) | ||
4747 | dst_free(&rt->dst); | ||
4748 | } | ||
4749 | } | 4778 | } |
4750 | dst_hold(&ifp->rt->dst); | 4779 | dst_hold(&ifp->rt->dst); |
4751 | 4780 | ||
4752 | if (ip6_del_rt(ifp->rt)) | 4781 | if (ip6_del_rt(ifp->rt)) |
4753 | dst_free(&ifp->rt->dst); | 4782 | dst_free(&ifp->rt->dst); |
4783 | |||
4784 | rt_genid_bump_ipv6(net); | ||
4754 | break; | 4785 | break; |
4755 | } | 4786 | } |
4756 | atomic_inc(&net->ipv6.dev_addr_genid); | 4787 | atomic_inc(&net->ipv6.dev_addr_genid); |
4757 | rt_genid_bump_ipv6(net); | ||
4758 | } | 4788 | } |
4759 | 4789 | ||
4760 | static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) | 4790 | static void ipv6_ifa_notify(int event, struct inet6_ifaddr *ifp) |
@@ -5168,6 +5198,13 @@ static struct addrconf_sysctl_table | |||
5168 | .proc_handler = proc_dointvec | 5198 | .proc_handler = proc_dointvec |
5169 | }, | 5199 | }, |
5170 | { | 5200 | { |
5201 | .procname = "accept_ra_from_local", | ||
5202 | .data = &ipv6_devconf.accept_ra_from_local, | ||
5203 | .maxlen = sizeof(int), | ||
5204 | .mode = 0644, | ||
5205 | .proc_handler = proc_dointvec, | ||
5206 | }, | ||
5207 | { | ||
5171 | /* sentinel */ | 5208 | /* sentinel */ |
5172 | } | 5209 | } |
5173 | }, | 5210 | }, |
@@ -5218,12 +5255,23 @@ static void __addrconf_sysctl_unregister(struct ipv6_devconf *p) | |||
5218 | kfree(t); | 5255 | kfree(t); |
5219 | } | 5256 | } |
5220 | 5257 | ||
5221 | static void addrconf_sysctl_register(struct inet6_dev *idev) | 5258 | static int addrconf_sysctl_register(struct inet6_dev *idev) |
5222 | { | 5259 | { |
5223 | neigh_sysctl_register(idev->dev, idev->nd_parms, | 5260 | int err; |
5224 | &ndisc_ifinfo_sysctl_change); | 5261 | |
5225 | __addrconf_sysctl_register(dev_net(idev->dev), idev->dev->name, | 5262 | if (!sysctl_dev_name_is_allowed(idev->dev->name)) |
5226 | idev, &idev->cnf); | 5263 | return -EINVAL; |
5264 | |||
5265 | err = neigh_sysctl_register(idev->dev, idev->nd_parms, | ||
5266 | &ndisc_ifinfo_sysctl_change); | ||
5267 | if (err) | ||
5268 | return err; | ||
5269 | err = __addrconf_sysctl_register(dev_net(idev->dev), idev->dev->name, | ||
5270 | idev, &idev->cnf); | ||
5271 | if (err) | ||
5272 | neigh_sysctl_unregister(idev->nd_parms); | ||
5273 | |||
5274 | return err; | ||
5227 | } | 5275 | } |
5228 | 5276 | ||
5229 | static void addrconf_sysctl_unregister(struct inet6_dev *idev) | 5277 | static void addrconf_sysctl_unregister(struct inet6_dev *idev) |
@@ -5308,6 +5356,7 @@ static struct rtnl_af_ops inet6_ops = { | |||
5308 | 5356 | ||
5309 | int __init addrconf_init(void) | 5357 | int __init addrconf_init(void) |
5310 | { | 5358 | { |
5359 | struct inet6_dev *idev; | ||
5311 | int i, err; | 5360 | int i, err; |
5312 | 5361 | ||
5313 | err = ipv6_addr_label_init(); | 5362 | err = ipv6_addr_label_init(); |
@@ -5346,11 +5395,12 @@ int __init addrconf_init(void) | |||
5346 | * device and it being up should be removed. | 5395 | * device and it being up should be removed. |
5347 | */ | 5396 | */ |
5348 | rtnl_lock(); | 5397 | rtnl_lock(); |
5349 | if (!ipv6_add_dev(init_net.loopback_dev)) | 5398 | idev = ipv6_add_dev(init_net.loopback_dev); |
5350 | err = -ENOMEM; | ||
5351 | rtnl_unlock(); | 5399 | rtnl_unlock(); |
5352 | if (err) | 5400 | if (IS_ERR(idev)) { |
5401 | err = PTR_ERR(idev); | ||
5353 | goto errlo; | 5402 | goto errlo; |
5403 | } | ||
5354 | 5404 | ||
5355 | for (i = 0; i < IN6_ADDR_HSIZE; i++) | 5405 | for (i = 0; i < IN6_ADDR_HSIZE; i++) |
5356 | INIT_HLIST_HEAD(&inet6_addr_lst[i]); | 5406 | INIT_HLIST_HEAD(&inet6_addr_lst[i]); |
diff --git a/net/ipv6/addrconf_core.c b/net/ipv6/addrconf_core.c index e6960457f625..98cc4cd570e2 100644 --- a/net/ipv6/addrconf_core.c +++ b/net/ipv6/addrconf_core.c | |||
@@ -8,6 +8,13 @@ | |||
8 | #include <net/addrconf.h> | 8 | #include <net/addrconf.h> |
9 | #include <net/ip.h> | 9 | #include <net/ip.h> |
10 | 10 | ||
11 | /* if ipv6 module registers this function is used by xfrm to force all | ||
12 | * sockets to relookup their nodes - this is fairly expensive, be | ||
13 | * careful | ||
14 | */ | ||
15 | void (*__fib6_flush_trees)(struct net *); | ||
16 | EXPORT_SYMBOL(__fib6_flush_trees); | ||
17 | |||
11 | #define IPV6_ADDR_SCOPE_TYPE(scope) ((scope) << 16) | 18 | #define IPV6_ADDR_SCOPE_TYPE(scope) ((scope) << 16) |
12 | 19 | ||
13 | static inline unsigned int ipv6_addr_scope2type(unsigned int scope) | 20 | static inline unsigned int ipv6_addr_scope2type(unsigned int scope) |
diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c index 731e1e1722d9..fd0dc47f471d 100644 --- a/net/ipv6/addrlabel.c +++ b/net/ipv6/addrlabel.c | |||
@@ -277,7 +277,7 @@ static int __ip6addrlbl_add(struct ip6addrlbl_entry *newp, int replace) | |||
277 | last = p; | 277 | last = p; |
278 | } | 278 | } |
279 | if (last) | 279 | if (last) |
280 | hlist_add_after_rcu(&last->list, &newp->list); | 280 | hlist_add_behind_rcu(&newp->list, &last->list); |
281 | else | 281 | else |
282 | hlist_add_head_rcu(&newp->list, &ip6addrlbl_table.head); | 282 | hlist_add_head_rcu(&newp->list, &ip6addrlbl_table.head); |
283 | out: | 283 | out: |
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c index 7cb4392690dd..2daa3a133e49 100644 --- a/net/ipv6/af_inet6.c +++ b/net/ipv6/af_inet6.c | |||
@@ -197,7 +197,7 @@ lookup_protocol: | |||
197 | np->mcast_hops = IPV6_DEFAULT_MCASTHOPS; | 197 | np->mcast_hops = IPV6_DEFAULT_MCASTHOPS; |
198 | np->mc_loop = 1; | 198 | np->mc_loop = 1; |
199 | np->pmtudisc = IPV6_PMTUDISC_WANT; | 199 | np->pmtudisc = IPV6_PMTUDISC_WANT; |
200 | np->ipv6only = net->ipv6.sysctl.bindv6only; | 200 | sk->sk_ipv6only = net->ipv6.sysctl.bindv6only; |
201 | 201 | ||
202 | /* Init the ipv4 part of the socket since we can have sockets | 202 | /* Init the ipv4 part of the socket since we can have sockets |
203 | * using v6 API for ipv4. | 203 | * using v6 API for ipv4. |
@@ -294,7 +294,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
294 | /* Binding to v4-mapped address on a v6-only socket | 294 | /* Binding to v4-mapped address on a v6-only socket |
295 | * makes no sense | 295 | * makes no sense |
296 | */ | 296 | */ |
297 | if (np->ipv6only) { | 297 | if (sk->sk_ipv6only) { |
298 | err = -EINVAL; | 298 | err = -EINVAL; |
299 | goto out; | 299 | goto out; |
300 | } | 300 | } |
@@ -371,7 +371,7 @@ int inet6_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
371 | if (addr_type != IPV6_ADDR_ANY) { | 371 | if (addr_type != IPV6_ADDR_ANY) { |
372 | sk->sk_userlocks |= SOCK_BINDADDR_LOCK; | 372 | sk->sk_userlocks |= SOCK_BINDADDR_LOCK; |
373 | if (addr_type != IPV6_ADDR_MAPPED) | 373 | if (addr_type != IPV6_ADDR_MAPPED) |
374 | np->ipv6only = 1; | 374 | sk->sk_ipv6only = 1; |
375 | } | 375 | } |
376 | if (snum) | 376 | if (snum) |
377 | sk->sk_userlocks |= SOCK_BINDPORT_LOCK; | 377 | sk->sk_userlocks |= SOCK_BINDPORT_LOCK; |
@@ -765,6 +765,7 @@ static int __net_init inet6_net_init(struct net *net) | |||
765 | net->ipv6.sysctl.bindv6only = 0; | 765 | net->ipv6.sysctl.bindv6only = 0; |
766 | net->ipv6.sysctl.icmpv6_time = 1*HZ; | 766 | net->ipv6.sysctl.icmpv6_time = 1*HZ; |
767 | net->ipv6.sysctl.flowlabel_consistency = 1; | 767 | net->ipv6.sysctl.flowlabel_consistency = 1; |
768 | net->ipv6.sysctl.auto_flowlabels = 0; | ||
768 | atomic_set(&net->ipv6.rt_genid, 0); | 769 | atomic_set(&net->ipv6.rt_genid, 0); |
769 | 770 | ||
770 | err = ipv6_init_mibs(net); | 771 | err = ipv6_init_mibs(net); |
diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index 210183244689..9a386842fd62 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c | |||
@@ -77,6 +77,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
77 | pac->acl_next = NULL; | 77 | pac->acl_next = NULL; |
78 | pac->acl_addr = *addr; | 78 | pac->acl_addr = *addr; |
79 | 79 | ||
80 | rtnl_lock(); | ||
80 | rcu_read_lock(); | 81 | rcu_read_lock(); |
81 | if (ifindex == 0) { | 82 | if (ifindex == 0) { |
82 | struct rt6_info *rt; | 83 | struct rt6_info *rt; |
@@ -137,6 +138,7 @@ int ipv6_sock_ac_join(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
137 | 138 | ||
138 | error: | 139 | error: |
139 | rcu_read_unlock(); | 140 | rcu_read_unlock(); |
141 | rtnl_unlock(); | ||
140 | if (pac) | 142 | if (pac) |
141 | sock_kfree_s(sk, pac, sizeof(*pac)); | 143 | sock_kfree_s(sk, pac, sizeof(*pac)); |
142 | return err; | 144 | return err; |
@@ -171,11 +173,13 @@ int ipv6_sock_ac_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
171 | 173 | ||
172 | spin_unlock_bh(&ipv6_sk_ac_lock); | 174 | spin_unlock_bh(&ipv6_sk_ac_lock); |
173 | 175 | ||
176 | rtnl_lock(); | ||
174 | rcu_read_lock(); | 177 | rcu_read_lock(); |
175 | dev = dev_get_by_index_rcu(net, pac->acl_ifindex); | 178 | dev = dev_get_by_index_rcu(net, pac->acl_ifindex); |
176 | if (dev) | 179 | if (dev) |
177 | ipv6_dev_ac_dec(dev, &pac->acl_addr); | 180 | ipv6_dev_ac_dec(dev, &pac->acl_addr); |
178 | rcu_read_unlock(); | 181 | rcu_read_unlock(); |
182 | rtnl_unlock(); | ||
179 | 183 | ||
180 | sock_kfree_s(sk, pac, sizeof(*pac)); | 184 | sock_kfree_s(sk, pac, sizeof(*pac)); |
181 | return 0; | 185 | return 0; |
@@ -198,6 +202,7 @@ void ipv6_sock_ac_close(struct sock *sk) | |||
198 | spin_unlock_bh(&ipv6_sk_ac_lock); | 202 | spin_unlock_bh(&ipv6_sk_ac_lock); |
199 | 203 | ||
200 | prev_index = 0; | 204 | prev_index = 0; |
205 | rtnl_lock(); | ||
201 | rcu_read_lock(); | 206 | rcu_read_lock(); |
202 | while (pac) { | 207 | while (pac) { |
203 | struct ipv6_ac_socklist *next = pac->acl_next; | 208 | struct ipv6_ac_socklist *next = pac->acl_next; |
@@ -212,6 +217,7 @@ void ipv6_sock_ac_close(struct sock *sk) | |||
212 | pac = next; | 217 | pac = next; |
213 | } | 218 | } |
214 | rcu_read_unlock(); | 219 | rcu_read_unlock(); |
220 | rtnl_unlock(); | ||
215 | } | 221 | } |
216 | 222 | ||
217 | static void aca_put(struct ifacaddr6 *ac) | 223 | static void aca_put(struct ifacaddr6 *ac) |
@@ -233,6 +239,8 @@ int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr) | |||
233 | struct rt6_info *rt; | 239 | struct rt6_info *rt; |
234 | int err; | 240 | int err; |
235 | 241 | ||
242 | ASSERT_RTNL(); | ||
243 | |||
236 | idev = in6_dev_get(dev); | 244 | idev = in6_dev_get(dev); |
237 | 245 | ||
238 | if (idev == NULL) | 246 | if (idev == NULL) |
@@ -302,6 +310,8 @@ int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr) | |||
302 | { | 310 | { |
303 | struct ifacaddr6 *aca, *prev_aca; | 311 | struct ifacaddr6 *aca, *prev_aca; |
304 | 312 | ||
313 | ASSERT_RTNL(); | ||
314 | |||
305 | write_lock_bh(&idev->lock); | 315 | write_lock_bh(&idev->lock); |
306 | prev_aca = NULL; | 316 | prev_aca = NULL; |
307 | for (aca = idev->ac_list; aca; aca = aca->aca_next) { | 317 | for (aca = idev->ac_list; aca; aca = aca->aca_next) { |
@@ -341,6 +351,27 @@ static int ipv6_dev_ac_dec(struct net_device *dev, const struct in6_addr *addr) | |||
341 | return __ipv6_dev_ac_dec(idev, addr); | 351 | return __ipv6_dev_ac_dec(idev, addr); |
342 | } | 352 | } |
343 | 353 | ||
354 | void ipv6_ac_destroy_dev(struct inet6_dev *idev) | ||
355 | { | ||
356 | struct ifacaddr6 *aca; | ||
357 | |||
358 | write_lock_bh(&idev->lock); | ||
359 | while ((aca = idev->ac_list) != NULL) { | ||
360 | idev->ac_list = aca->aca_next; | ||
361 | write_unlock_bh(&idev->lock); | ||
362 | |||
363 | addrconf_leave_solict(idev, &aca->aca_addr); | ||
364 | |||
365 | dst_hold(&aca->aca_rt->dst); | ||
366 | ip6_del_rt(aca->aca_rt); | ||
367 | |||
368 | aca_put(aca); | ||
369 | |||
370 | write_lock_bh(&idev->lock); | ||
371 | } | ||
372 | write_unlock_bh(&idev->lock); | ||
373 | } | ||
374 | |||
344 | /* | 375 | /* |
345 | * check if the interface has this anycast address | 376 | * check if the interface has this anycast address |
346 | * called with rcu_read_lock() | 377 | * called with rcu_read_lock() |
diff --git a/net/ipv6/datagram.c b/net/ipv6/datagram.c index c3bf2d2e519e..2753319524f1 100644 --- a/net/ipv6/datagram.c +++ b/net/ipv6/datagram.c | |||
@@ -199,6 +199,7 @@ ipv4_connected: | |||
199 | NULL); | 199 | NULL); |
200 | 200 | ||
201 | sk->sk_state = TCP_ESTABLISHED; | 201 | sk->sk_state = TCP_ESTABLISHED; |
202 | ip6_set_txhash(sk); | ||
202 | out: | 203 | out: |
203 | fl6_sock_release(flowlabel); | 204 | fl6_sock_release(flowlabel); |
204 | return err; | 205 | return err; |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index f6c84a6eb238..06ba3e58320b 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
@@ -626,9 +626,10 @@ void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info) | |||
626 | int inner_offset; | 626 | int inner_offset; |
627 | __be16 frag_off; | 627 | __be16 frag_off; |
628 | u8 nexthdr; | 628 | u8 nexthdr; |
629 | struct net *net = dev_net(skb->dev); | ||
629 | 630 | ||
630 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) | 631 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) |
631 | return; | 632 | goto out; |
632 | 633 | ||
633 | nexthdr = ((struct ipv6hdr *)skb->data)->nexthdr; | 634 | nexthdr = ((struct ipv6hdr *)skb->data)->nexthdr; |
634 | if (ipv6_ext_hdr(nexthdr)) { | 635 | if (ipv6_ext_hdr(nexthdr)) { |
@@ -636,14 +637,14 @@ void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info) | |||
636 | inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), | 637 | inner_offset = ipv6_skip_exthdr(skb, sizeof(struct ipv6hdr), |
637 | &nexthdr, &frag_off); | 638 | &nexthdr, &frag_off); |
638 | if (inner_offset<0) | 639 | if (inner_offset<0) |
639 | return; | 640 | goto out; |
640 | } else { | 641 | } else { |
641 | inner_offset = sizeof(struct ipv6hdr); | 642 | inner_offset = sizeof(struct ipv6hdr); |
642 | } | 643 | } |
643 | 644 | ||
644 | /* Checkin header including 8 bytes of inner protocol header. */ | 645 | /* Checkin header including 8 bytes of inner protocol header. */ |
645 | if (!pskb_may_pull(skb, inner_offset+8)) | 646 | if (!pskb_may_pull(skb, inner_offset+8)) |
646 | return; | 647 | goto out; |
647 | 648 | ||
648 | /* BUGGG_FUTURE: we should try to parse exthdrs in this packet. | 649 | /* BUGGG_FUTURE: we should try to parse exthdrs in this packet. |
649 | Without this we will not able f.e. to make source routed | 650 | Without this we will not able f.e. to make source routed |
@@ -652,13 +653,15 @@ void icmpv6_notify(struct sk_buff *skb, u8 type, u8 code, __be32 info) | |||
652 | --ANK (980726) | 653 | --ANK (980726) |
653 | */ | 654 | */ |
654 | 655 | ||
655 | rcu_read_lock(); | ||
656 | ipprot = rcu_dereference(inet6_protos[nexthdr]); | 656 | ipprot = rcu_dereference(inet6_protos[nexthdr]); |
657 | if (ipprot && ipprot->err_handler) | 657 | if (ipprot && ipprot->err_handler) |
658 | ipprot->err_handler(skb, NULL, type, code, inner_offset, info); | 658 | ipprot->err_handler(skb, NULL, type, code, inner_offset, info); |
659 | rcu_read_unlock(); | ||
660 | 659 | ||
661 | raw6_icmp_error(skb, nexthdr, type, code, inner_offset, info); | 660 | raw6_icmp_error(skb, nexthdr, type, code, inner_offset, info); |
661 | return; | ||
662 | |||
663 | out: | ||
664 | ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev), ICMP6_MIB_INERRORS); | ||
662 | } | 665 | } |
663 | 666 | ||
664 | /* | 667 | /* |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index cb4459bd1d29..97b9fa8de377 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
@@ -643,7 +643,7 @@ static int fib6_commit_metrics(struct dst_entry *dst, | |||
643 | if (dst->flags & DST_HOST) { | 643 | if (dst->flags & DST_HOST) { |
644 | mp = dst_metrics_write_ptr(dst); | 644 | mp = dst_metrics_write_ptr(dst); |
645 | } else { | 645 | } else { |
646 | mp = kzalloc(sizeof(u32) * RTAX_MAX, GFP_KERNEL); | 646 | mp = kzalloc(sizeof(u32) * RTAX_MAX, GFP_ATOMIC); |
647 | if (!mp) | 647 | if (!mp) |
648 | return -ENOMEM; | 648 | return -ENOMEM; |
649 | dst_init_metrics(dst, mp, 0); | 649 | dst_init_metrics(dst, mp, 0); |
@@ -1605,6 +1605,24 @@ static void fib6_prune_clones(struct net *net, struct fib6_node *fn) | |||
1605 | fib6_clean_tree(net, fn, fib6_prune_clone, 1, NULL); | 1605 | fib6_clean_tree(net, fn, fib6_prune_clone, 1, NULL); |
1606 | } | 1606 | } |
1607 | 1607 | ||
1608 | static int fib6_update_sernum(struct rt6_info *rt, void *arg) | ||
1609 | { | ||
1610 | __u32 sernum = *(__u32 *)arg; | ||
1611 | |||
1612 | if (rt->rt6i_node && | ||
1613 | rt->rt6i_node->fn_sernum != sernum) | ||
1614 | rt->rt6i_node->fn_sernum = sernum; | ||
1615 | |||
1616 | return 0; | ||
1617 | } | ||
1618 | |||
1619 | static void fib6_flush_trees(struct net *net) | ||
1620 | { | ||
1621 | __u32 new_sernum = fib6_new_sernum(); | ||
1622 | |||
1623 | fib6_clean_all(net, fib6_update_sernum, &new_sernum); | ||
1624 | } | ||
1625 | |||
1608 | /* | 1626 | /* |
1609 | * Garbage collection | 1627 | * Garbage collection |
1610 | */ | 1628 | */ |
@@ -1788,6 +1806,8 @@ int __init fib6_init(void) | |||
1788 | NULL); | 1806 | NULL); |
1789 | if (ret) | 1807 | if (ret) |
1790 | goto out_unregister_subsys; | 1808 | goto out_unregister_subsys; |
1809 | |||
1810 | __fib6_flush_trees = fib6_flush_trees; | ||
1791 | out: | 1811 | out: |
1792 | return ret; | 1812 | return ret; |
1793 | 1813 | ||
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 3873181ed856..f304471477dc 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c | |||
@@ -314,6 +314,8 @@ static struct ip6_tnl *ip6gre_tunnel_locate(struct net *net, | |||
314 | struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); | 314 | struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); |
315 | 315 | ||
316 | t = ip6gre_tunnel_find(net, parms, ARPHRD_IP6GRE); | 316 | t = ip6gre_tunnel_find(net, parms, ARPHRD_IP6GRE); |
317 | if (t && create) | ||
318 | return NULL; | ||
317 | if (t || !create) | 319 | if (t || !create) |
318 | return t; | 320 | return t; |
319 | 321 | ||
@@ -322,7 +324,8 @@ static struct ip6_tnl *ip6gre_tunnel_locate(struct net *net, | |||
322 | else | 324 | else |
323 | strcpy(name, "ip6gre%d"); | 325 | strcpy(name, "ip6gre%d"); |
324 | 326 | ||
325 | dev = alloc_netdev(sizeof(*t), name, ip6gre_tunnel_setup); | 327 | dev = alloc_netdev(sizeof(*t), name, NET_NAME_UNKNOWN, |
328 | ip6gre_tunnel_setup); | ||
326 | if (!dev) | 329 | if (!dev) |
327 | return NULL; | 330 | return NULL; |
328 | 331 | ||
@@ -723,7 +726,8 @@ static netdev_tx_t ip6gre_xmit2(struct sk_buff *skb, | |||
723 | * Push down and install the IP header. | 726 | * Push down and install the IP header. |
724 | */ | 727 | */ |
725 | ipv6h = ipv6_hdr(skb); | 728 | ipv6h = ipv6_hdr(skb); |
726 | ip6_flow_hdr(ipv6h, INET_ECN_encapsulate(0, dsfield), fl6->flowlabel); | 729 | ip6_flow_hdr(ipv6h, INET_ECN_encapsulate(0, dsfield), |
730 | ip6_make_flowlabel(net, skb, fl6->flowlabel, false)); | ||
727 | ipv6h->hop_limit = tunnel->parms.hop_limit; | 731 | ipv6h->hop_limit = tunnel->parms.hop_limit; |
728 | ipv6h->nexthdr = proto; | 732 | ipv6h->nexthdr = proto; |
729 | ipv6h->saddr = fl6->saddr; | 733 | ipv6h->saddr = fl6->saddr; |
@@ -1174,7 +1178,9 @@ static int ip6gre_header(struct sk_buff *skb, struct net_device *dev, | |||
1174 | struct ipv6hdr *ipv6h = (struct ipv6hdr *)skb_push(skb, t->hlen); | 1178 | struct ipv6hdr *ipv6h = (struct ipv6hdr *)skb_push(skb, t->hlen); |
1175 | __be16 *p = (__be16 *)(ipv6h+1); | 1179 | __be16 *p = (__be16 *)(ipv6h+1); |
1176 | 1180 | ||
1177 | ip6_flow_hdr(ipv6h, 0, t->fl.u.ip6.flowlabel); | 1181 | ip6_flow_hdr(ipv6h, 0, |
1182 | ip6_make_flowlabel(dev_net(dev), skb, | ||
1183 | t->fl.u.ip6.flowlabel, false)); | ||
1178 | ipv6h->hop_limit = t->parms.hop_limit; | 1184 | ipv6h->hop_limit = t->parms.hop_limit; |
1179 | ipv6h->nexthdr = NEXTHDR_GRE; | 1185 | ipv6h->nexthdr = NEXTHDR_GRE; |
1180 | ipv6h->saddr = t->parms.laddr; | 1186 | ipv6h->saddr = t->parms.laddr; |
@@ -1323,7 +1329,8 @@ static int __net_init ip6gre_init_net(struct net *net) | |||
1323 | int err; | 1329 | int err; |
1324 | 1330 | ||
1325 | ign->fb_tunnel_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6gre0", | 1331 | ign->fb_tunnel_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6gre0", |
1326 | ip6gre_tunnel_setup); | 1332 | NET_NAME_UNKNOWN, |
1333 | ip6gre_tunnel_setup); | ||
1327 | if (!ign->fb_tunnel_dev) { | 1334 | if (!ign->fb_tunnel_dev) { |
1328 | err = -ENOMEM; | 1335 | err = -ENOMEM; |
1329 | goto err_alloc_dev; | 1336 | goto err_alloc_dev; |
@@ -1719,4 +1726,5 @@ MODULE_LICENSE("GPL"); | |||
1719 | MODULE_AUTHOR("D. Kozlov (xeb@mail.ru)"); | 1726 | MODULE_AUTHOR("D. Kozlov (xeb@mail.ru)"); |
1720 | MODULE_DESCRIPTION("GRE over IPv6 tunneling device"); | 1727 | MODULE_DESCRIPTION("GRE over IPv6 tunneling device"); |
1721 | MODULE_ALIAS_RTNL_LINK("ip6gre"); | 1728 | MODULE_ALIAS_RTNL_LINK("ip6gre"); |
1729 | MODULE_ALIAS_RTNL_LINK("ip6gretap"); | ||
1722 | MODULE_ALIAS_NETDEV("ip6gre0"); | 1730 | MODULE_ALIAS_NETDEV("ip6gre0"); |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 45702b8cd141..0a3448b2888f 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
@@ -205,7 +205,8 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi6 *fl6, | |||
205 | if (hlimit < 0) | 205 | if (hlimit < 0) |
206 | hlimit = ip6_dst_hoplimit(dst); | 206 | hlimit = ip6_dst_hoplimit(dst); |
207 | 207 | ||
208 | ip6_flow_hdr(hdr, tclass, fl6->flowlabel); | 208 | ip6_flow_hdr(hdr, tclass, ip6_make_flowlabel(net, skb, fl6->flowlabel, |
209 | np->autoflowlabel)); | ||
209 | 210 | ||
210 | hdr->payload_len = htons(seg_len); | 211 | hdr->payload_len = htons(seg_len); |
211 | hdr->nexthdr = proto; | 212 | hdr->nexthdr = proto; |
@@ -802,8 +803,8 @@ slow_path: | |||
802 | /* | 803 | /* |
803 | * Copy a block of the IP datagram. | 804 | * Copy a block of the IP datagram. |
804 | */ | 805 | */ |
805 | if (skb_copy_bits(skb, ptr, skb_transport_header(frag), len)) | 806 | BUG_ON(skb_copy_bits(skb, ptr, skb_transport_header(frag), |
806 | BUG(); | 807 | len)); |
807 | left -= len; | 808 | left -= len; |
808 | 809 | ||
809 | fh->frag_off = htons(offset); | 810 | fh->frag_off = htons(offset); |
@@ -1008,7 +1009,7 @@ struct dst_entry *ip6_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6, | |||
1008 | if (final_dst) | 1009 | if (final_dst) |
1009 | fl6->daddr = *final_dst; | 1010 | fl6->daddr = *final_dst; |
1010 | 1011 | ||
1011 | return xfrm_lookup(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0); | 1012 | return xfrm_lookup_route(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0); |
1012 | } | 1013 | } |
1013 | EXPORT_SYMBOL_GPL(ip6_dst_lookup_flow); | 1014 | EXPORT_SYMBOL_GPL(ip6_dst_lookup_flow); |
1014 | 1015 | ||
@@ -1040,7 +1041,7 @@ struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6, | |||
1040 | if (final_dst) | 1041 | if (final_dst) |
1041 | fl6->daddr = *final_dst; | 1042 | fl6->daddr = *final_dst; |
1042 | 1043 | ||
1043 | return xfrm_lookup(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0); | 1044 | return xfrm_lookup_route(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0); |
1044 | } | 1045 | } |
1045 | EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup_flow); | 1046 | EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup_flow); |
1046 | 1047 | ||
@@ -1156,6 +1157,7 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
1156 | int err; | 1157 | int err; |
1157 | int offset = 0; | 1158 | int offset = 0; |
1158 | __u8 tx_flags = 0; | 1159 | __u8 tx_flags = 0; |
1160 | u32 tskey = 0; | ||
1159 | 1161 | ||
1160 | if (flags&MSG_PROBE) | 1162 | if (flags&MSG_PROBE) |
1161 | return 0; | 1163 | return 0; |
@@ -1271,9 +1273,12 @@ emsgsize: | |||
1271 | } | 1273 | } |
1272 | } | 1274 | } |
1273 | 1275 | ||
1274 | /* For UDP, check if TX timestamp is enabled */ | 1276 | if (sk->sk_type == SOCK_DGRAM || sk->sk_type == SOCK_RAW) { |
1275 | if (sk->sk_type == SOCK_DGRAM) | ||
1276 | sock_tx_timestamp(sk, &tx_flags); | 1277 | sock_tx_timestamp(sk, &tx_flags); |
1278 | if (tx_flags & SKBTX_ANY_SW_TSTAMP && | ||
1279 | sk->sk_tsflags & SOF_TIMESTAMPING_OPT_ID) | ||
1280 | tskey = sk->sk_tskey++; | ||
1281 | } | ||
1277 | 1282 | ||
1278 | /* | 1283 | /* |
1279 | * Let's try using as much space as possible. | 1284 | * Let's try using as much space as possible. |
@@ -1381,12 +1386,6 @@ alloc_new_skb: | |||
1381 | sk->sk_allocation); | 1386 | sk->sk_allocation); |
1382 | if (unlikely(skb == NULL)) | 1387 | if (unlikely(skb == NULL)) |
1383 | err = -ENOBUFS; | 1388 | err = -ENOBUFS; |
1384 | else { | ||
1385 | /* Only the initial fragment | ||
1386 | * is time stamped. | ||
1387 | */ | ||
1388 | tx_flags = 0; | ||
1389 | } | ||
1390 | } | 1389 | } |
1391 | if (skb == NULL) | 1390 | if (skb == NULL) |
1392 | goto error; | 1391 | goto error; |
@@ -1400,8 +1399,11 @@ alloc_new_skb: | |||
1400 | skb_reserve(skb, hh_len + sizeof(struct frag_hdr) + | 1399 | skb_reserve(skb, hh_len + sizeof(struct frag_hdr) + |
1401 | dst_exthdrlen); | 1400 | dst_exthdrlen); |
1402 | 1401 | ||
1403 | if (sk->sk_type == SOCK_DGRAM) | 1402 | /* Only the initial fragment is time stamped */ |
1404 | skb_shinfo(skb)->tx_flags = tx_flags; | 1403 | skb_shinfo(skb)->tx_flags = tx_flags; |
1404 | tx_flags = 0; | ||
1405 | skb_shinfo(skb)->tskey = tskey; | ||
1406 | tskey = 0; | ||
1405 | 1407 | ||
1406 | /* | 1408 | /* |
1407 | * Find where to start putting bytes | 1409 | * Find where to start putting bytes |
@@ -1571,7 +1573,9 @@ int ip6_push_pending_frames(struct sock *sk) | |||
1571 | skb_reset_network_header(skb); | 1573 | skb_reset_network_header(skb); |
1572 | hdr = ipv6_hdr(skb); | 1574 | hdr = ipv6_hdr(skb); |
1573 | 1575 | ||
1574 | ip6_flow_hdr(hdr, np->cork.tclass, fl6->flowlabel); | 1576 | ip6_flow_hdr(hdr, np->cork.tclass, |
1577 | ip6_make_flowlabel(net, skb, fl6->flowlabel, | ||
1578 | np->autoflowlabel)); | ||
1575 | hdr->hop_limit = np->cork.hop_limit; | 1579 | hdr->hop_limit = np->cork.hop_limit; |
1576 | hdr->nexthdr = proto; | 1580 | hdr->nexthdr = proto; |
1577 | hdr->saddr = fl6->saddr; | 1581 | hdr->saddr = fl6->saddr; |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index afa082458360..69a84b464009 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
@@ -315,7 +315,8 @@ static struct ip6_tnl *ip6_tnl_create(struct net *net, struct __ip6_tnl_parm *p) | |||
315 | else | 315 | else |
316 | sprintf(name, "ip6tnl%%d"); | 316 | sprintf(name, "ip6tnl%%d"); |
317 | 317 | ||
318 | dev = alloc_netdev(sizeof (*t), name, ip6_tnl_dev_setup); | 318 | dev = alloc_netdev(sizeof(*t), name, NET_NAME_UNKNOWN, |
319 | ip6_tnl_dev_setup); | ||
319 | if (dev == NULL) | 320 | if (dev == NULL) |
320 | goto failed; | 321 | goto failed; |
321 | 322 | ||
@@ -363,8 +364,12 @@ static struct ip6_tnl *ip6_tnl_locate(struct net *net, | |||
363 | (t = rtnl_dereference(*tp)) != NULL; | 364 | (t = rtnl_dereference(*tp)) != NULL; |
364 | tp = &t->next) { | 365 | tp = &t->next) { |
365 | if (ipv6_addr_equal(local, &t->parms.laddr) && | 366 | if (ipv6_addr_equal(local, &t->parms.laddr) && |
366 | ipv6_addr_equal(remote, &t->parms.raddr)) | 367 | ipv6_addr_equal(remote, &t->parms.raddr)) { |
368 | if (create) | ||
369 | return NULL; | ||
370 | |||
367 | return t; | 371 | return t; |
372 | } | ||
368 | } | 373 | } |
369 | if (!create) | 374 | if (!create) |
370 | return NULL; | 375 | return NULL; |
@@ -1046,7 +1051,8 @@ static int ip6_tnl_xmit2(struct sk_buff *skb, | |||
1046 | skb_push(skb, sizeof(struct ipv6hdr)); | 1051 | skb_push(skb, sizeof(struct ipv6hdr)); |
1047 | skb_reset_network_header(skb); | 1052 | skb_reset_network_header(skb); |
1048 | ipv6h = ipv6_hdr(skb); | 1053 | ipv6h = ipv6_hdr(skb); |
1049 | ip6_flow_hdr(ipv6h, INET_ECN_encapsulate(0, dsfield), fl6->flowlabel); | 1054 | ip6_flow_hdr(ipv6h, INET_ECN_encapsulate(0, dsfield), |
1055 | ip6_make_flowlabel(net, skb, fl6->flowlabel, false)); | ||
1050 | ipv6h->hop_limit = t->parms.hop_limit; | 1056 | ipv6h->hop_limit = t->parms.hop_limit; |
1051 | ipv6h->nexthdr = proto; | 1057 | ipv6h->nexthdr = proto; |
1052 | ipv6h->saddr = fl6->saddr; | 1058 | ipv6h->saddr = fl6->saddr; |
@@ -1772,7 +1778,7 @@ static int __net_init ip6_tnl_init_net(struct net *net) | |||
1772 | 1778 | ||
1773 | err = -ENOMEM; | 1779 | err = -ENOMEM; |
1774 | ip6n->fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6tnl0", | 1780 | ip6n->fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6tnl0", |
1775 | ip6_tnl_dev_setup); | 1781 | NET_NAME_UNKNOWN, ip6_tnl_dev_setup); |
1776 | 1782 | ||
1777 | if (!ip6n->fb_tnl_dev) | 1783 | if (!ip6n->fb_tnl_dev) |
1778 | goto err_alloc_dev; | 1784 | goto err_alloc_dev; |
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index 9aaa6bb229e4..5833a2244467 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c | |||
@@ -204,7 +204,7 @@ static struct ip6_tnl *vti6_tnl_create(struct net *net, struct __ip6_tnl_parm *p | |||
204 | else | 204 | else |
205 | sprintf(name, "ip6_vti%%d"); | 205 | sprintf(name, "ip6_vti%%d"); |
206 | 206 | ||
207 | dev = alloc_netdev(sizeof(*t), name, vti6_dev_setup); | 207 | dev = alloc_netdev(sizeof(*t), name, NET_NAME_UNKNOWN, vti6_dev_setup); |
208 | if (dev == NULL) | 208 | if (dev == NULL) |
209 | goto failed; | 209 | goto failed; |
210 | 210 | ||
@@ -253,8 +253,12 @@ static struct ip6_tnl *vti6_locate(struct net *net, struct __ip6_tnl_parm *p, | |||
253 | (t = rtnl_dereference(*tp)) != NULL; | 253 | (t = rtnl_dereference(*tp)) != NULL; |
254 | tp = &t->next) { | 254 | tp = &t->next) { |
255 | if (ipv6_addr_equal(local, &t->parms.laddr) && | 255 | if (ipv6_addr_equal(local, &t->parms.laddr) && |
256 | ipv6_addr_equal(remote, &t->parms.raddr)) | 256 | ipv6_addr_equal(remote, &t->parms.raddr)) { |
257 | if (create) | ||
258 | return NULL; | ||
259 | |||
257 | return t; | 260 | return t; |
261 | } | ||
258 | } | 262 | } |
259 | if (!create) | 263 | if (!create) |
260 | return NULL; | 264 | return NULL; |
@@ -1020,7 +1024,7 @@ static int __net_init vti6_init_net(struct net *net) | |||
1020 | 1024 | ||
1021 | err = -ENOMEM; | 1025 | err = -ENOMEM; |
1022 | ip6n->fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6_vti0", | 1026 | ip6n->fb_tnl_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6_vti0", |
1023 | vti6_dev_setup); | 1027 | NET_NAME_UNKNOWN, vti6_dev_setup); |
1024 | 1028 | ||
1025 | if (!ip6n->fb_tnl_dev) | 1029 | if (!ip6n->fb_tnl_dev) |
1026 | goto err_alloc_dev; | 1030 | goto err_alloc_dev; |
@@ -1089,36 +1093,26 @@ static struct xfrm6_protocol vti_ipcomp6_protocol __read_mostly = { | |||
1089 | **/ | 1093 | **/ |
1090 | static int __init vti6_tunnel_init(void) | 1094 | static int __init vti6_tunnel_init(void) |
1091 | { | 1095 | { |
1092 | int err; | 1096 | const char *msg; |
1097 | int err; | ||
1093 | 1098 | ||
1099 | msg = "tunnel device"; | ||
1094 | err = register_pernet_device(&vti6_net_ops); | 1100 | err = register_pernet_device(&vti6_net_ops); |
1095 | if (err < 0) | 1101 | if (err < 0) |
1096 | goto out_pernet; | 1102 | goto pernet_dev_failed; |
1097 | 1103 | ||
1104 | msg = "tunnel protocols"; | ||
1098 | err = xfrm6_protocol_register(&vti_esp6_protocol, IPPROTO_ESP); | 1105 | err = xfrm6_protocol_register(&vti_esp6_protocol, IPPROTO_ESP); |
1099 | if (err < 0) { | 1106 | if (err < 0) |
1100 | pr_err("%s: can't register vti6 protocol\n", __func__); | 1107 | goto xfrm_proto_esp_failed; |
1101 | |||
1102 | goto out; | ||
1103 | } | ||
1104 | |||
1105 | err = xfrm6_protocol_register(&vti_ah6_protocol, IPPROTO_AH); | 1108 | err = xfrm6_protocol_register(&vti_ah6_protocol, IPPROTO_AH); |
1106 | if (err < 0) { | 1109 | if (err < 0) |
1107 | xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP); | 1110 | goto xfrm_proto_ah_failed; |
1108 | pr_err("%s: can't register vti6 protocol\n", __func__); | ||
1109 | |||
1110 | goto out; | ||
1111 | } | ||
1112 | |||
1113 | err = xfrm6_protocol_register(&vti_ipcomp6_protocol, IPPROTO_COMP); | 1111 | err = xfrm6_protocol_register(&vti_ipcomp6_protocol, IPPROTO_COMP); |
1114 | if (err < 0) { | 1112 | if (err < 0) |
1115 | xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH); | 1113 | goto xfrm_proto_comp_failed; |
1116 | xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP); | ||
1117 | pr_err("%s: can't register vti6 protocol\n", __func__); | ||
1118 | |||
1119 | goto out; | ||
1120 | } | ||
1121 | 1114 | ||
1115 | msg = "netlink interface"; | ||
1122 | err = rtnl_link_register(&vti6_link_ops); | 1116 | err = rtnl_link_register(&vti6_link_ops); |
1123 | if (err < 0) | 1117 | if (err < 0) |
1124 | goto rtnl_link_failed; | 1118 | goto rtnl_link_failed; |
@@ -1127,11 +1121,14 @@ static int __init vti6_tunnel_init(void) | |||
1127 | 1121 | ||
1128 | rtnl_link_failed: | 1122 | rtnl_link_failed: |
1129 | xfrm6_protocol_deregister(&vti_ipcomp6_protocol, IPPROTO_COMP); | 1123 | xfrm6_protocol_deregister(&vti_ipcomp6_protocol, IPPROTO_COMP); |
1124 | xfrm_proto_comp_failed: | ||
1130 | xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH); | 1125 | xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH); |
1126 | xfrm_proto_ah_failed: | ||
1131 | xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP); | 1127 | xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP); |
1132 | out: | 1128 | xfrm_proto_esp_failed: |
1133 | unregister_pernet_device(&vti6_net_ops); | 1129 | unregister_pernet_device(&vti6_net_ops); |
1134 | out_pernet: | 1130 | pernet_dev_failed: |
1131 | pr_err("vti6 init: failed to register %s\n", msg); | ||
1135 | return err; | 1132 | return err; |
1136 | } | 1133 | } |
1137 | 1134 | ||
@@ -1141,13 +1138,9 @@ out_pernet: | |||
1141 | static void __exit vti6_tunnel_cleanup(void) | 1138 | static void __exit vti6_tunnel_cleanup(void) |
1142 | { | 1139 | { |
1143 | rtnl_link_unregister(&vti6_link_ops); | 1140 | rtnl_link_unregister(&vti6_link_ops); |
1144 | if (xfrm6_protocol_deregister(&vti_ipcomp6_protocol, IPPROTO_COMP)) | 1141 | xfrm6_protocol_deregister(&vti_ipcomp6_protocol, IPPROTO_COMP); |
1145 | pr_info("%s: can't deregister protocol\n", __func__); | 1142 | xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH); |
1146 | if (xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH)) | 1143 | xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP); |
1147 | pr_info("%s: can't deregister protocol\n", __func__); | ||
1148 | if (xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP)) | ||
1149 | pr_info("%s: can't deregister protocol\n", __func__); | ||
1150 | |||
1151 | unregister_pernet_device(&vti6_net_ops); | 1144 | unregister_pernet_device(&vti6_net_ops); |
1152 | } | 1145 | } |
1153 | 1146 | ||
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c index 8250474ab7dc..f9a3fd320d1d 100644 --- a/net/ipv6/ip6mr.c +++ b/net/ipv6/ip6mr.c | |||
@@ -744,7 +744,7 @@ static struct net_device *ip6mr_reg_vif(struct net *net, struct mr6_table *mrt) | |||
744 | else | 744 | else |
745 | sprintf(name, "pim6reg%u", mrt->id); | 745 | sprintf(name, "pim6reg%u", mrt->id); |
746 | 746 | ||
747 | dev = alloc_netdev(0, name, reg_vif_setup); | 747 | dev = alloc_netdev(0, name, NET_NAME_UNKNOWN, reg_vif_setup); |
748 | if (dev == NULL) | 748 | if (dev == NULL) |
749 | return NULL; | 749 | return NULL; |
750 | 750 | ||
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index edb58aff4ae7..0c289982796d 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
@@ -235,7 +235,7 @@ static int do_ipv6_setsockopt(struct sock *sk, int level, int optname, | |||
235 | if (optlen < sizeof(int) || | 235 | if (optlen < sizeof(int) || |
236 | inet_sk(sk)->inet_num) | 236 | inet_sk(sk)->inet_num) |
237 | goto e_inval; | 237 | goto e_inval; |
238 | np->ipv6only = valbool; | 238 | sk->sk_ipv6only = valbool; |
239 | retv = 0; | 239 | retv = 0; |
240 | break; | 240 | break; |
241 | 241 | ||
@@ -834,6 +834,10 @@ pref_skip_coa: | |||
834 | np->dontfrag = valbool; | 834 | np->dontfrag = valbool; |
835 | retv = 0; | 835 | retv = 0; |
836 | break; | 836 | break; |
837 | case IPV6_AUTOFLOWLABEL: | ||
838 | np->autoflowlabel = valbool; | ||
839 | retv = 0; | ||
840 | break; | ||
837 | } | 841 | } |
838 | 842 | ||
839 | release_sock(sk); | 843 | release_sock(sk); |
@@ -1058,7 +1062,7 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
1058 | } | 1062 | } |
1059 | 1063 | ||
1060 | case IPV6_V6ONLY: | 1064 | case IPV6_V6ONLY: |
1061 | val = np->ipv6only; | 1065 | val = sk->sk_ipv6only; |
1062 | break; | 1066 | break; |
1063 | 1067 | ||
1064 | case IPV6_RECVPKTINFO: | 1068 | case IPV6_RECVPKTINFO: |
@@ -1158,7 +1162,6 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
1158 | return -EFAULT; | 1162 | return -EFAULT; |
1159 | 1163 | ||
1160 | return 0; | 1164 | return 0; |
1161 | break; | ||
1162 | } | 1165 | } |
1163 | 1166 | ||
1164 | case IPV6_TRANSPARENT: | 1167 | case IPV6_TRANSPARENT: |
@@ -1273,6 +1276,10 @@ static int do_ipv6_getsockopt(struct sock *sk, int level, int optname, | |||
1273 | val = np->dontfrag; | 1276 | val = np->dontfrag; |
1274 | break; | 1277 | break; |
1275 | 1278 | ||
1279 | case IPV6_AUTOFLOWLABEL: | ||
1280 | val = np->autoflowlabel; | ||
1281 | break; | ||
1282 | |||
1276 | default: | 1283 | default: |
1277 | return -ENOPROTOOPT; | 1284 | return -ENOPROTOOPT; |
1278 | } | 1285 | } |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index 617f0958e164..a23b655a7627 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
@@ -172,6 +172,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
172 | mc_lst->next = NULL; | 172 | mc_lst->next = NULL; |
173 | mc_lst->addr = *addr; | 173 | mc_lst->addr = *addr; |
174 | 174 | ||
175 | rtnl_lock(); | ||
175 | rcu_read_lock(); | 176 | rcu_read_lock(); |
176 | if (ifindex == 0) { | 177 | if (ifindex == 0) { |
177 | struct rt6_info *rt; | 178 | struct rt6_info *rt; |
@@ -185,6 +186,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
185 | 186 | ||
186 | if (dev == NULL) { | 187 | if (dev == NULL) { |
187 | rcu_read_unlock(); | 188 | rcu_read_unlock(); |
189 | rtnl_unlock(); | ||
188 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); | 190 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); |
189 | return -ENODEV; | 191 | return -ENODEV; |
190 | } | 192 | } |
@@ -202,6 +204,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
202 | 204 | ||
203 | if (err) { | 205 | if (err) { |
204 | rcu_read_unlock(); | 206 | rcu_read_unlock(); |
207 | rtnl_unlock(); | ||
205 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); | 208 | sock_kfree_s(sk, mc_lst, sizeof(*mc_lst)); |
206 | return err; | 209 | return err; |
207 | } | 210 | } |
@@ -212,6 +215,7 @@ int ipv6_sock_mc_join(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
212 | spin_unlock(&ipv6_sk_mc_lock); | 215 | spin_unlock(&ipv6_sk_mc_lock); |
213 | 216 | ||
214 | rcu_read_unlock(); | 217 | rcu_read_unlock(); |
218 | rtnl_unlock(); | ||
215 | 219 | ||
216 | return 0; | 220 | return 0; |
217 | } | 221 | } |
@@ -229,6 +233,7 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
229 | if (!ipv6_addr_is_multicast(addr)) | 233 | if (!ipv6_addr_is_multicast(addr)) |
230 | return -EINVAL; | 234 | return -EINVAL; |
231 | 235 | ||
236 | rtnl_lock(); | ||
232 | spin_lock(&ipv6_sk_mc_lock); | 237 | spin_lock(&ipv6_sk_mc_lock); |
233 | for (lnk = &np->ipv6_mc_list; | 238 | for (lnk = &np->ipv6_mc_list; |
234 | (mc_lst = rcu_dereference_protected(*lnk, | 239 | (mc_lst = rcu_dereference_protected(*lnk, |
@@ -252,12 +257,15 @@ int ipv6_sock_mc_drop(struct sock *sk, int ifindex, const struct in6_addr *addr) | |||
252 | } else | 257 | } else |
253 | (void) ip6_mc_leave_src(sk, mc_lst, NULL); | 258 | (void) ip6_mc_leave_src(sk, mc_lst, NULL); |
254 | rcu_read_unlock(); | 259 | rcu_read_unlock(); |
260 | rtnl_unlock(); | ||
261 | |||
255 | atomic_sub(sizeof(*mc_lst), &sk->sk_omem_alloc); | 262 | atomic_sub(sizeof(*mc_lst), &sk->sk_omem_alloc); |
256 | kfree_rcu(mc_lst, rcu); | 263 | kfree_rcu(mc_lst, rcu); |
257 | return 0; | 264 | return 0; |
258 | } | 265 | } |
259 | } | 266 | } |
260 | spin_unlock(&ipv6_sk_mc_lock); | 267 | spin_unlock(&ipv6_sk_mc_lock); |
268 | rtnl_unlock(); | ||
261 | 269 | ||
262 | return -EADDRNOTAVAIL; | 270 | return -EADDRNOTAVAIL; |
263 | } | 271 | } |
@@ -302,6 +310,7 @@ void ipv6_sock_mc_close(struct sock *sk) | |||
302 | if (!rcu_access_pointer(np->ipv6_mc_list)) | 310 | if (!rcu_access_pointer(np->ipv6_mc_list)) |
303 | return; | 311 | return; |
304 | 312 | ||
313 | rtnl_lock(); | ||
305 | spin_lock(&ipv6_sk_mc_lock); | 314 | spin_lock(&ipv6_sk_mc_lock); |
306 | while ((mc_lst = rcu_dereference_protected(np->ipv6_mc_list, | 315 | while ((mc_lst = rcu_dereference_protected(np->ipv6_mc_list, |
307 | lockdep_is_held(&ipv6_sk_mc_lock))) != NULL) { | 316 | lockdep_is_held(&ipv6_sk_mc_lock))) != NULL) { |
@@ -328,6 +337,7 @@ void ipv6_sock_mc_close(struct sock *sk) | |||
328 | spin_lock(&ipv6_sk_mc_lock); | 337 | spin_lock(&ipv6_sk_mc_lock); |
329 | } | 338 | } |
330 | spin_unlock(&ipv6_sk_mc_lock); | 339 | spin_unlock(&ipv6_sk_mc_lock); |
340 | rtnl_unlock(); | ||
331 | } | 341 | } |
332 | 342 | ||
333 | int ip6_mc_source(int add, int omode, struct sock *sk, | 343 | int ip6_mc_source(int add, int omode, struct sock *sk, |
@@ -845,6 +855,8 @@ int ipv6_dev_mc_inc(struct net_device *dev, const struct in6_addr *addr) | |||
845 | struct ifmcaddr6 *mc; | 855 | struct ifmcaddr6 *mc; |
846 | struct inet6_dev *idev; | 856 | struct inet6_dev *idev; |
847 | 857 | ||
858 | ASSERT_RTNL(); | ||
859 | |||
848 | /* we need to take a reference on idev */ | 860 | /* we need to take a reference on idev */ |
849 | idev = in6_dev_get(dev); | 861 | idev = in6_dev_get(dev); |
850 | 862 | ||
@@ -916,6 +928,8 @@ int __ipv6_dev_mc_dec(struct inet6_dev *idev, const struct in6_addr *addr) | |||
916 | { | 928 | { |
917 | struct ifmcaddr6 *ma, **map; | 929 | struct ifmcaddr6 *ma, **map; |
918 | 930 | ||
931 | ASSERT_RTNL(); | ||
932 | |||
919 | write_lock_bh(&idev->lock); | 933 | write_lock_bh(&idev->lock); |
920 | for (map = &idev->mc_list; (ma=*map) != NULL; map = &ma->next) { | 934 | for (map = &idev->mc_list; (ma=*map) != NULL; map = &ma->next) { |
921 | if (ipv6_addr_equal(&ma->mca_addr, addr)) { | 935 | if (ipv6_addr_equal(&ma->mca_addr, addr)) { |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index ca8d4ea48a5d..339078f95d1b 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -1070,6 +1070,9 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1070 | optlen = (skb_tail_pointer(skb) - skb_transport_header(skb)) - | 1070 | optlen = (skb_tail_pointer(skb) - skb_transport_header(skb)) - |
1071 | sizeof(struct ra_msg); | 1071 | sizeof(struct ra_msg); |
1072 | 1072 | ||
1073 | ND_PRINTK(2, info, | ||
1074 | "RA: %s, dev: %s\n", | ||
1075 | __func__, skb->dev->name); | ||
1073 | if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) { | 1076 | if (!(ipv6_addr_type(&ipv6_hdr(skb)->saddr) & IPV6_ADDR_LINKLOCAL)) { |
1074 | ND_PRINTK(2, warn, "RA: source address is not link-local\n"); | 1077 | ND_PRINTK(2, warn, "RA: source address is not link-local\n"); |
1075 | return; | 1078 | return; |
@@ -1102,13 +1105,21 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1102 | return; | 1105 | return; |
1103 | } | 1106 | } |
1104 | 1107 | ||
1105 | if (!ipv6_accept_ra(in6_dev)) | 1108 | if (!ipv6_accept_ra(in6_dev)) { |
1109 | ND_PRINTK(2, info, | ||
1110 | "RA: %s, did not accept ra for dev: %s\n", | ||
1111 | __func__, skb->dev->name); | ||
1106 | goto skip_linkparms; | 1112 | goto skip_linkparms; |
1113 | } | ||
1107 | 1114 | ||
1108 | #ifdef CONFIG_IPV6_NDISC_NODETYPE | 1115 | #ifdef CONFIG_IPV6_NDISC_NODETYPE |
1109 | /* skip link-specific parameters from interior routers */ | 1116 | /* skip link-specific parameters from interior routers */ |
1110 | if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT) | 1117 | if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT) { |
1118 | ND_PRINTK(2, info, | ||
1119 | "RA: %s, nodetype is NODEFAULT, dev: %s\n", | ||
1120 | __func__, skb->dev->name); | ||
1111 | goto skip_linkparms; | 1121 | goto skip_linkparms; |
1122 | } | ||
1112 | #endif | 1123 | #endif |
1113 | 1124 | ||
1114 | if (in6_dev->if_flags & IF_RS_SENT) { | 1125 | if (in6_dev->if_flags & IF_RS_SENT) { |
@@ -1130,11 +1141,24 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1130 | (ra_msg->icmph.icmp6_addrconf_other ? | 1141 | (ra_msg->icmph.icmp6_addrconf_other ? |
1131 | IF_RA_OTHERCONF : 0); | 1142 | IF_RA_OTHERCONF : 0); |
1132 | 1143 | ||
1133 | if (!in6_dev->cnf.accept_ra_defrtr) | 1144 | if (!in6_dev->cnf.accept_ra_defrtr) { |
1145 | ND_PRINTK(2, info, | ||
1146 | "RA: %s, defrtr is false for dev: %s\n", | ||
1147 | __func__, skb->dev->name); | ||
1134 | goto skip_defrtr; | 1148 | goto skip_defrtr; |
1149 | } | ||
1135 | 1150 | ||
1136 | if (ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr, NULL, 0)) | 1151 | /* Do not accept RA with source-addr found on local machine unless |
1152 | * accept_ra_from_local is set to true. | ||
1153 | */ | ||
1154 | if (!in6_dev->cnf.accept_ra_from_local && | ||
1155 | ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr, | ||
1156 | NULL, 0)) { | ||
1157 | ND_PRINTK(2, info, | ||
1158 | "RA from local address detected on dev: %s: default router ignored\n", | ||
1159 | skb->dev->name); | ||
1137 | goto skip_defrtr; | 1160 | goto skip_defrtr; |
1161 | } | ||
1138 | 1162 | ||
1139 | lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime); | 1163 | lifetime = ntohs(ra_msg->icmph.icmp6_rt_lifetime); |
1140 | 1164 | ||
@@ -1163,8 +1187,10 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1163 | rt = NULL; | 1187 | rt = NULL; |
1164 | } | 1188 | } |
1165 | 1189 | ||
1190 | ND_PRINTK(3, info, "RA: rt: %p lifetime: %d, for dev: %s\n", | ||
1191 | rt, lifetime, skb->dev->name); | ||
1166 | if (rt == NULL && lifetime) { | 1192 | if (rt == NULL && lifetime) { |
1167 | ND_PRINTK(3, dbg, "RA: adding default router\n"); | 1193 | ND_PRINTK(3, info, "RA: adding default router\n"); |
1168 | 1194 | ||
1169 | rt = rt6_add_dflt_router(&ipv6_hdr(skb)->saddr, skb->dev, pref); | 1195 | rt = rt6_add_dflt_router(&ipv6_hdr(skb)->saddr, skb->dev, pref); |
1170 | if (rt == NULL) { | 1196 | if (rt == NULL) { |
@@ -1260,12 +1286,22 @@ skip_linkparms: | |||
1260 | NEIGH_UPDATE_F_ISROUTER); | 1286 | NEIGH_UPDATE_F_ISROUTER); |
1261 | } | 1287 | } |
1262 | 1288 | ||
1263 | if (!ipv6_accept_ra(in6_dev)) | 1289 | if (!ipv6_accept_ra(in6_dev)) { |
1290 | ND_PRINTK(2, info, | ||
1291 | "RA: %s, accept_ra is false for dev: %s\n", | ||
1292 | __func__, skb->dev->name); | ||
1264 | goto out; | 1293 | goto out; |
1294 | } | ||
1265 | 1295 | ||
1266 | #ifdef CONFIG_IPV6_ROUTE_INFO | 1296 | #ifdef CONFIG_IPV6_ROUTE_INFO |
1267 | if (ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr, NULL, 0)) | 1297 | if (!in6_dev->cnf.accept_ra_from_local && |
1298 | ipv6_chk_addr(dev_net(in6_dev->dev), &ipv6_hdr(skb)->saddr, | ||
1299 | NULL, 0)) { | ||
1300 | ND_PRINTK(2, info, | ||
1301 | "RA from local address detected on dev: %s: router info ignored.\n", | ||
1302 | skb->dev->name); | ||
1268 | goto skip_routeinfo; | 1303 | goto skip_routeinfo; |
1304 | } | ||
1269 | 1305 | ||
1270 | if (in6_dev->cnf.accept_ra_rtr_pref && ndopts.nd_opts_ri) { | 1306 | if (in6_dev->cnf.accept_ra_rtr_pref && ndopts.nd_opts_ri) { |
1271 | struct nd_opt_hdr *p; | 1307 | struct nd_opt_hdr *p; |
@@ -1293,8 +1329,12 @@ skip_routeinfo: | |||
1293 | 1329 | ||
1294 | #ifdef CONFIG_IPV6_NDISC_NODETYPE | 1330 | #ifdef CONFIG_IPV6_NDISC_NODETYPE |
1295 | /* skip link-specific ndopts from interior routers */ | 1331 | /* skip link-specific ndopts from interior routers */ |
1296 | if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT) | 1332 | if (skb->ndisc_nodetype == NDISC_NODETYPE_NODEFAULT) { |
1333 | ND_PRINTK(2, info, | ||
1334 | "RA: %s, nodetype is NODEFAULT (interior routes), dev: %s\n", | ||
1335 | __func__, skb->dev->name); | ||
1297 | goto out; | 1336 | goto out; |
1337 | } | ||
1298 | #endif | 1338 | #endif |
1299 | 1339 | ||
1300 | if (in6_dev->cnf.accept_ra_pinfo && ndopts.nd_opts_pi) { | 1340 | if (in6_dev->cnf.accept_ra_pinfo && ndopts.nd_opts_pi) { |
@@ -1728,7 +1768,7 @@ int __init ndisc_init(void) | |||
1728 | 1768 | ||
1729 | #ifdef CONFIG_SYSCTL | 1769 | #ifdef CONFIG_SYSCTL |
1730 | err = neigh_sysctl_register(NULL, &nd_tbl.parms, | 1770 | err = neigh_sysctl_register(NULL, &nd_tbl.parms, |
1731 | &ndisc_ifinfo_sysctl_change); | 1771 | ndisc_ifinfo_sysctl_change); |
1732 | if (err) | 1772 | if (err) |
1733 | goto out_unregister_pernet; | 1773 | goto out_unregister_pernet; |
1734 | out: | 1774 | out: |
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig index 4bff1f297e39..2812816aabdc 100644 --- a/net/ipv6/netfilter/Kconfig +++ b/net/ipv6/netfilter/Kconfig | |||
@@ -55,6 +55,21 @@ config NFT_REJECT_IPV6 | |||
55 | default NFT_REJECT | 55 | default NFT_REJECT |
56 | tristate | 56 | tristate |
57 | 57 | ||
58 | config NF_LOG_IPV6 | ||
59 | tristate "IPv6 packet logging" | ||
60 | default m if NETFILTER_ADVANCED=n | ||
61 | select NF_LOG_COMMON | ||
62 | |||
63 | config NF_NAT_IPV6 | ||
64 | tristate "IPv6 NAT" | ||
65 | depends on NF_CONNTRACK_IPV6 | ||
66 | depends on NETFILTER_ADVANCED | ||
67 | select NF_NAT | ||
68 | help | ||
69 | The IPv6 NAT option allows masquerading, port forwarding and other | ||
70 | forms of full Network Address Port Translation. This can be | ||
71 | controlled by iptables or nft. | ||
72 | |||
58 | config IP6_NF_IPTABLES | 73 | config IP6_NF_IPTABLES |
59 | tristate "IP6 tables support (required for filtering)" | 74 | tristate "IP6 tables support (required for filtering)" |
60 | depends on INET && IPV6 | 75 | depends on INET && IPV6 |
@@ -227,19 +242,21 @@ config IP6_NF_SECURITY | |||
227 | 242 | ||
228 | If unsure, say N. | 243 | If unsure, say N. |
229 | 244 | ||
230 | config NF_NAT_IPV6 | 245 | config IP6_NF_NAT |
231 | tristate "IPv6 NAT" | 246 | tristate "ip6tables NAT support" |
232 | depends on NF_CONNTRACK_IPV6 | 247 | depends on NF_CONNTRACK_IPV6 |
233 | depends on NETFILTER_ADVANCED | 248 | depends on NETFILTER_ADVANCED |
234 | select NF_NAT | 249 | select NF_NAT |
250 | select NF_NAT_IPV6 | ||
251 | select NETFILTER_XT_NAT | ||
235 | help | 252 | help |
236 | The IPv6 NAT option allows masquerading, port forwarding and other | 253 | This enables the `nat' table in ip6tables. This allows masquerading, |
237 | forms of full Network Address Port Translation. It is controlled by | 254 | port forwarding and other forms of full Network Address Port |
238 | the `nat' table in ip6tables, see the man page for ip6tables(8). | 255 | Translation. |
239 | 256 | ||
240 | To compile it as a module, choose M here. If unsure, say N. | 257 | To compile it as a module, choose M here. If unsure, say N. |
241 | 258 | ||
242 | if NF_NAT_IPV6 | 259 | if IP6_NF_NAT |
243 | 260 | ||
244 | config IP6_NF_TARGET_MASQUERADE | 261 | config IP6_NF_TARGET_MASQUERADE |
245 | tristate "MASQUERADE target support" | 262 | tristate "MASQUERADE target support" |
@@ -260,7 +277,7 @@ config IP6_NF_TARGET_NPT | |||
260 | 277 | ||
261 | To compile it as a module, choose M here. If unsure, say N. | 278 | To compile it as a module, choose M here. If unsure, say N. |
262 | 279 | ||
263 | endif # NF_NAT_IPV6 | 280 | endif # IP6_NF_NAT |
264 | 281 | ||
265 | endif # IP6_NF_IPTABLES | 282 | endif # IP6_NF_IPTABLES |
266 | 283 | ||
diff --git a/net/ipv6/netfilter/Makefile b/net/ipv6/netfilter/Makefile index 70d3dd66f2cd..c3d3286db4bb 100644 --- a/net/ipv6/netfilter/Makefile +++ b/net/ipv6/netfilter/Makefile | |||
@@ -8,7 +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 | obj-$(CONFIG_IP6_NF_NAT) += ip6table_nat.o |
12 | 12 | ||
13 | # objects for l3 independent conntrack | 13 | # objects for l3 independent conntrack |
14 | 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 |
@@ -23,6 +23,9 @@ obj-$(CONFIG_NF_NAT_IPV6) += nf_nat_ipv6.o | |||
23 | 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 |
24 | obj-$(CONFIG_NF_DEFRAG_IPV6) += nf_defrag_ipv6.o | 24 | obj-$(CONFIG_NF_DEFRAG_IPV6) += nf_defrag_ipv6.o |
25 | 25 | ||
26 | # logging | ||
27 | obj-$(CONFIG_NF_LOG_IPV6) += nf_log_ipv6.o | ||
28 | |||
26 | # nf_tables | 29 | # nf_tables |
27 | obj-$(CONFIG_NF_TABLES_IPV6) += nf_tables_ipv6.o | 30 | obj-$(CONFIG_NF_TABLES_IPV6) += nf_tables_ipv6.o |
28 | obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV6) += nft_chain_route_ipv6.o | 31 | obj-$(CONFIG_NFT_CHAIN_ROUTE_IPV6) += nft_chain_route_ipv6.o |
diff --git a/net/ipv6/netfilter/ip6t_ipv6header.c b/net/ipv6/netfilter/ip6t_ipv6header.c index 54bd9790603f..8b147440fbdc 100644 --- a/net/ipv6/netfilter/ip6t_ipv6header.c +++ b/net/ipv6/netfilter/ip6t_ipv6header.c | |||
@@ -94,7 +94,6 @@ ipv6header_mt6(const struct sk_buff *skb, struct xt_action_param *par) | |||
94 | break; | 94 | break; |
95 | default: | 95 | default: |
96 | return false; | 96 | return false; |
97 | break; | ||
98 | } | 97 | } |
99 | 98 | ||
100 | nexthdr = hp->nexthdr; | 99 | nexthdr = hp->nexthdr; |
diff --git a/net/ipv6/netfilter/nf_conntrack_reasm.c b/net/ipv6/netfilter/nf_conntrack_reasm.c index 0d5279fd852a..6f187c8d8a1b 100644 --- a/net/ipv6/netfilter/nf_conntrack_reasm.c +++ b/net/ipv6/netfilter/nf_conntrack_reasm.c | |||
@@ -50,6 +50,7 @@ | |||
50 | #include <linux/module.h> | 50 | #include <linux/module.h> |
51 | #include <net/netfilter/ipv6/nf_defrag_ipv6.h> | 51 | #include <net/netfilter/ipv6/nf_defrag_ipv6.h> |
52 | 52 | ||
53 | static const char nf_frags_cache_name[] = "nf-frags"; | ||
53 | 54 | ||
54 | struct nf_ct_frag6_skb_cb | 55 | struct nf_ct_frag6_skb_cb |
55 | { | 56 | { |
@@ -63,6 +64,8 @@ struct nf_ct_frag6_skb_cb | |||
63 | static struct inet_frags nf_frags; | 64 | static struct inet_frags nf_frags; |
64 | 65 | ||
65 | #ifdef CONFIG_SYSCTL | 66 | #ifdef CONFIG_SYSCTL |
67 | static int zero; | ||
68 | |||
66 | static struct ctl_table nf_ct_frag6_sysctl_table[] = { | 69 | static struct ctl_table nf_ct_frag6_sysctl_table[] = { |
67 | { | 70 | { |
68 | .procname = "nf_conntrack_frag6_timeout", | 71 | .procname = "nf_conntrack_frag6_timeout", |
@@ -76,14 +79,17 @@ static struct ctl_table nf_ct_frag6_sysctl_table[] = { | |||
76 | .data = &init_net.nf_frag.frags.low_thresh, | 79 | .data = &init_net.nf_frag.frags.low_thresh, |
77 | .maxlen = sizeof(unsigned int), | 80 | .maxlen = sizeof(unsigned int), |
78 | .mode = 0644, | 81 | .mode = 0644, |
79 | .proc_handler = proc_dointvec, | 82 | .proc_handler = proc_dointvec_minmax, |
83 | .extra1 = &zero, | ||
84 | .extra2 = &init_net.nf_frag.frags.high_thresh | ||
80 | }, | 85 | }, |
81 | { | 86 | { |
82 | .procname = "nf_conntrack_frag6_high_thresh", | 87 | .procname = "nf_conntrack_frag6_high_thresh", |
83 | .data = &init_net.nf_frag.frags.high_thresh, | 88 | .data = &init_net.nf_frag.frags.high_thresh, |
84 | .maxlen = sizeof(unsigned int), | 89 | .maxlen = sizeof(unsigned int), |
85 | .mode = 0644, | 90 | .mode = 0644, |
86 | .proc_handler = proc_dointvec, | 91 | .proc_handler = proc_dointvec_minmax, |
92 | .extra1 = &init_net.nf_frag.frags.low_thresh | ||
87 | }, | 93 | }, |
88 | { } | 94 | { } |
89 | }; | 95 | }; |
@@ -102,7 +108,10 @@ static int nf_ct_frag6_sysctl_register(struct net *net) | |||
102 | 108 | ||
103 | table[0].data = &net->nf_frag.frags.timeout; | 109 | table[0].data = &net->nf_frag.frags.timeout; |
104 | table[1].data = &net->nf_frag.frags.low_thresh; | 110 | table[1].data = &net->nf_frag.frags.low_thresh; |
111 | table[1].extra2 = &net->nf_frag.frags.high_thresh; | ||
105 | table[2].data = &net->nf_frag.frags.high_thresh; | 112 | table[2].data = &net->nf_frag.frags.high_thresh; |
113 | table[2].extra1 = &net->nf_frag.frags.low_thresh; | ||
114 | table[2].extra2 = &init_net.nf_frag.frags.high_thresh; | ||
106 | } | 115 | } |
107 | 116 | ||
108 | hdr = register_net_sysctl(net, "net/netfilter", table); | 117 | hdr = register_net_sysctl(net, "net/netfilter", table); |
@@ -147,16 +156,13 @@ static inline u8 ip6_frag_ecn(const struct ipv6hdr *ipv6h) | |||
147 | static unsigned int nf_hash_frag(__be32 id, const struct in6_addr *saddr, | 156 | static unsigned int nf_hash_frag(__be32 id, const struct in6_addr *saddr, |
148 | const struct in6_addr *daddr) | 157 | const struct in6_addr *daddr) |
149 | { | 158 | { |
150 | u32 c; | ||
151 | |||
152 | net_get_random_once(&nf_frags.rnd, sizeof(nf_frags.rnd)); | 159 | net_get_random_once(&nf_frags.rnd, sizeof(nf_frags.rnd)); |
153 | c = jhash_3words(ipv6_addr_hash(saddr), ipv6_addr_hash(daddr), | 160 | return jhash_3words(ipv6_addr_hash(saddr), ipv6_addr_hash(daddr), |
154 | (__force u32)id, nf_frags.rnd); | 161 | (__force u32)id, nf_frags.rnd); |
155 | return c & (INETFRAGS_HASHSZ - 1); | ||
156 | } | 162 | } |
157 | 163 | ||
158 | 164 | ||
159 | static unsigned int nf_hashfn(struct inet_frag_queue *q) | 165 | static unsigned int nf_hashfn(const struct inet_frag_queue *q) |
160 | { | 166 | { |
161 | const struct frag_queue *nq; | 167 | const struct frag_queue *nq; |
162 | 168 | ||
@@ -196,7 +202,7 @@ static inline struct frag_queue *fq_find(struct net *net, __be32 id, | |||
196 | arg.dst = dst; | 202 | arg.dst = dst; |
197 | arg.ecn = ecn; | 203 | arg.ecn = ecn; |
198 | 204 | ||
199 | read_lock_bh(&nf_frags.lock); | 205 | local_bh_disable(); |
200 | hash = nf_hash_frag(id, src, dst); | 206 | hash = nf_hash_frag(id, src, dst); |
201 | 207 | ||
202 | q = inet_frag_find(&net->nf_frag.frags, &nf_frags, &arg, hash); | 208 | q = inet_frag_find(&net->nf_frag.frags, &nf_frags, &arg, hash); |
@@ -217,7 +223,7 @@ static int nf_ct_frag6_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
217 | int offset, end; | 223 | int offset, end; |
218 | u8 ecn; | 224 | u8 ecn; |
219 | 225 | ||
220 | if (fq->q.last_in & INET_FRAG_COMPLETE) { | 226 | if (fq->q.flags & INET_FRAG_COMPLETE) { |
221 | pr_debug("Already completed\n"); | 227 | pr_debug("Already completed\n"); |
222 | goto err; | 228 | goto err; |
223 | } | 229 | } |
@@ -248,11 +254,11 @@ static int nf_ct_frag6_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
248 | * or have different end, the segment is corrupted. | 254 | * or have different end, the segment is corrupted. |
249 | */ | 255 | */ |
250 | if (end < fq->q.len || | 256 | if (end < fq->q.len || |
251 | ((fq->q.last_in & INET_FRAG_LAST_IN) && end != fq->q.len)) { | 257 | ((fq->q.flags & INET_FRAG_LAST_IN) && end != fq->q.len)) { |
252 | pr_debug("already received last fragment\n"); | 258 | pr_debug("already received last fragment\n"); |
253 | goto err; | 259 | goto err; |
254 | } | 260 | } |
255 | fq->q.last_in |= INET_FRAG_LAST_IN; | 261 | fq->q.flags |= INET_FRAG_LAST_IN; |
256 | fq->q.len = end; | 262 | fq->q.len = end; |
257 | } else { | 263 | } else { |
258 | /* Check if the fragment is rounded to 8 bytes. | 264 | /* Check if the fragment is rounded to 8 bytes. |
@@ -267,7 +273,7 @@ static int nf_ct_frag6_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
267 | } | 273 | } |
268 | if (end > fq->q.len) { | 274 | if (end > fq->q.len) { |
269 | /* Some bits beyond end -> corruption. */ | 275 | /* Some bits beyond end -> corruption. */ |
270 | if (fq->q.last_in & INET_FRAG_LAST_IN) { | 276 | if (fq->q.flags & INET_FRAG_LAST_IN) { |
271 | pr_debug("last packet already reached.\n"); | 277 | pr_debug("last packet already reached.\n"); |
272 | goto err; | 278 | goto err; |
273 | } | 279 | } |
@@ -349,10 +355,9 @@ found: | |||
349 | */ | 355 | */ |
350 | if (offset == 0) { | 356 | if (offset == 0) { |
351 | fq->nhoffset = nhoff; | 357 | fq->nhoffset = nhoff; |
352 | fq->q.last_in |= INET_FRAG_FIRST_IN; | 358 | fq->q.flags |= INET_FRAG_FIRST_IN; |
353 | } | 359 | } |
354 | 360 | ||
355 | inet_frag_lru_move(&fq->q); | ||
356 | return 0; | 361 | return 0; |
357 | 362 | ||
358 | discard_fq: | 363 | discard_fq: |
@@ -597,10 +602,6 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user) | |||
597 | hdr = ipv6_hdr(clone); | 602 | hdr = ipv6_hdr(clone); |
598 | fhdr = (struct frag_hdr *)skb_transport_header(clone); | 603 | fhdr = (struct frag_hdr *)skb_transport_header(clone); |
599 | 604 | ||
600 | local_bh_disable(); | ||
601 | inet_frag_evictor(&net->nf_frag.frags, &nf_frags, false); | ||
602 | local_bh_enable(); | ||
603 | |||
604 | fq = fq_find(net, fhdr->identification, user, &hdr->saddr, &hdr->daddr, | 605 | fq = fq_find(net, fhdr->identification, user, &hdr->saddr, &hdr->daddr, |
605 | ip6_frag_ecn(hdr)); | 606 | ip6_frag_ecn(hdr)); |
606 | if (fq == NULL) { | 607 | if (fq == NULL) { |
@@ -617,7 +618,7 @@ struct sk_buff *nf_ct_frag6_gather(struct sk_buff *skb, u32 user) | |||
617 | goto ret_orig; | 618 | goto ret_orig; |
618 | } | 619 | } |
619 | 620 | ||
620 | if (fq->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && | 621 | if (fq->q.flags == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && |
621 | fq->q.meat == fq->q.len) { | 622 | fq->q.meat == fq->q.len) { |
622 | ret_skb = nf_ct_frag6_reasm(fq, dev); | 623 | ret_skb = nf_ct_frag6_reasm(fq, dev); |
623 | if (ret_skb == NULL) | 624 | if (ret_skb == NULL) |
@@ -677,13 +678,15 @@ int nf_ct_frag6_init(void) | |||
677 | nf_frags.qsize = sizeof(struct frag_queue); | 678 | nf_frags.qsize = sizeof(struct frag_queue); |
678 | nf_frags.match = ip6_frag_match; | 679 | nf_frags.match = ip6_frag_match; |
679 | nf_frags.frag_expire = nf_ct_frag6_expire; | 680 | nf_frags.frag_expire = nf_ct_frag6_expire; |
680 | nf_frags.secret_interval = 10 * 60 * HZ; | 681 | nf_frags.frags_cache_name = nf_frags_cache_name; |
681 | inet_frags_init(&nf_frags); | 682 | ret = inet_frags_init(&nf_frags); |
682 | 683 | if (ret) | |
684 | goto out; | ||
683 | ret = register_pernet_subsys(&nf_ct_net_ops); | 685 | ret = register_pernet_subsys(&nf_ct_net_ops); |
684 | if (ret) | 686 | if (ret) |
685 | inet_frags_fini(&nf_frags); | 687 | inet_frags_fini(&nf_frags); |
686 | 688 | ||
689 | out: | ||
687 | return ret; | 690 | return ret; |
688 | } | 691 | } |
689 | 692 | ||
diff --git a/net/ipv6/netfilter/nf_log_ipv6.c b/net/ipv6/netfilter/nf_log_ipv6.c new file mode 100644 index 000000000000..7b17a0be93e7 --- /dev/null +++ b/net/ipv6/netfilter/nf_log_ipv6.c | |||
@@ -0,0 +1,417 @@ | |||
1 | /* (C) 1999-2001 Paul `Rusty' Russell | ||
2 | * (C) 2002-2004 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 | #include <linux/module.h> | ||
10 | #include <linux/spinlock.h> | ||
11 | #include <linux/skbuff.h> | ||
12 | #include <linux/if_arp.h> | ||
13 | #include <linux/ip.h> | ||
14 | #include <net/ipv6.h> | ||
15 | #include <net/icmp.h> | ||
16 | #include <net/udp.h> | ||
17 | #include <net/tcp.h> | ||
18 | #include <net/route.h> | ||
19 | |||
20 | #include <linux/netfilter.h> | ||
21 | #include <linux/netfilter_ipv6/ip6_tables.h> | ||
22 | #include <linux/netfilter/xt_LOG.h> | ||
23 | #include <net/netfilter/nf_log.h> | ||
24 | |||
25 | static struct nf_loginfo default_loginfo = { | ||
26 | .type = NF_LOG_TYPE_LOG, | ||
27 | .u = { | ||
28 | .log = { | ||
29 | .level = 5, | ||
30 | .logflags = NF_LOG_MASK, | ||
31 | }, | ||
32 | }, | ||
33 | }; | ||
34 | |||
35 | /* One level of recursion won't kill us */ | ||
36 | static void dump_ipv6_packet(struct nf_log_buf *m, | ||
37 | const struct nf_loginfo *info, | ||
38 | const struct sk_buff *skb, unsigned int ip6hoff, | ||
39 | int recurse) | ||
40 | { | ||
41 | u_int8_t currenthdr; | ||
42 | int fragment; | ||
43 | struct ipv6hdr _ip6h; | ||
44 | const struct ipv6hdr *ih; | ||
45 | unsigned int ptr; | ||
46 | unsigned int hdrlen = 0; | ||
47 | unsigned int logflags; | ||
48 | |||
49 | if (info->type == NF_LOG_TYPE_LOG) | ||
50 | logflags = info->u.log.logflags; | ||
51 | else | ||
52 | logflags = NF_LOG_MASK; | ||
53 | |||
54 | ih = skb_header_pointer(skb, ip6hoff, sizeof(_ip6h), &_ip6h); | ||
55 | if (ih == NULL) { | ||
56 | nf_log_buf_add(m, "TRUNCATED"); | ||
57 | return; | ||
58 | } | ||
59 | |||
60 | /* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000 " */ | ||
61 | nf_log_buf_add(m, "SRC=%pI6 DST=%pI6 ", &ih->saddr, &ih->daddr); | ||
62 | |||
63 | /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */ | ||
64 | nf_log_buf_add(m, "LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ", | ||
65 | ntohs(ih->payload_len) + sizeof(struct ipv6hdr), | ||
66 | (ntohl(*(__be32 *)ih) & 0x0ff00000) >> 20, | ||
67 | ih->hop_limit, | ||
68 | (ntohl(*(__be32 *)ih) & 0x000fffff)); | ||
69 | |||
70 | fragment = 0; | ||
71 | ptr = ip6hoff + sizeof(struct ipv6hdr); | ||
72 | currenthdr = ih->nexthdr; | ||
73 | while (currenthdr != NEXTHDR_NONE && ip6t_ext_hdr(currenthdr)) { | ||
74 | struct ipv6_opt_hdr _hdr; | ||
75 | const struct ipv6_opt_hdr *hp; | ||
76 | |||
77 | hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); | ||
78 | if (hp == NULL) { | ||
79 | nf_log_buf_add(m, "TRUNCATED"); | ||
80 | return; | ||
81 | } | ||
82 | |||
83 | /* Max length: 48 "OPT (...) " */ | ||
84 | if (logflags & XT_LOG_IPOPT) | ||
85 | nf_log_buf_add(m, "OPT ( "); | ||
86 | |||
87 | switch (currenthdr) { | ||
88 | case IPPROTO_FRAGMENT: { | ||
89 | struct frag_hdr _fhdr; | ||
90 | const struct frag_hdr *fh; | ||
91 | |||
92 | nf_log_buf_add(m, "FRAG:"); | ||
93 | fh = skb_header_pointer(skb, ptr, sizeof(_fhdr), | ||
94 | &_fhdr); | ||
95 | if (fh == NULL) { | ||
96 | nf_log_buf_add(m, "TRUNCATED "); | ||
97 | return; | ||
98 | } | ||
99 | |||
100 | /* Max length: 6 "65535 " */ | ||
101 | nf_log_buf_add(m, "%u ", ntohs(fh->frag_off) & 0xFFF8); | ||
102 | |||
103 | /* Max length: 11 "INCOMPLETE " */ | ||
104 | if (fh->frag_off & htons(0x0001)) | ||
105 | nf_log_buf_add(m, "INCOMPLETE "); | ||
106 | |||
107 | nf_log_buf_add(m, "ID:%08x ", | ||
108 | ntohl(fh->identification)); | ||
109 | |||
110 | if (ntohs(fh->frag_off) & 0xFFF8) | ||
111 | fragment = 1; | ||
112 | |||
113 | hdrlen = 8; | ||
114 | |||
115 | break; | ||
116 | } | ||
117 | case IPPROTO_DSTOPTS: | ||
118 | case IPPROTO_ROUTING: | ||
119 | case IPPROTO_HOPOPTS: | ||
120 | if (fragment) { | ||
121 | if (logflags & XT_LOG_IPOPT) | ||
122 | nf_log_buf_add(m, ")"); | ||
123 | return; | ||
124 | } | ||
125 | hdrlen = ipv6_optlen(hp); | ||
126 | break; | ||
127 | /* Max Length */ | ||
128 | case IPPROTO_AH: | ||
129 | if (logflags & XT_LOG_IPOPT) { | ||
130 | struct ip_auth_hdr _ahdr; | ||
131 | const struct ip_auth_hdr *ah; | ||
132 | |||
133 | /* Max length: 3 "AH " */ | ||
134 | nf_log_buf_add(m, "AH "); | ||
135 | |||
136 | if (fragment) { | ||
137 | nf_log_buf_add(m, ")"); | ||
138 | return; | ||
139 | } | ||
140 | |||
141 | ah = skb_header_pointer(skb, ptr, sizeof(_ahdr), | ||
142 | &_ahdr); | ||
143 | if (ah == NULL) { | ||
144 | /* | ||
145 | * Max length: 26 "INCOMPLETE [65535 | ||
146 | * bytes] )" | ||
147 | */ | ||
148 | nf_log_buf_add(m, "INCOMPLETE [%u bytes] )", | ||
149 | skb->len - ptr); | ||
150 | return; | ||
151 | } | ||
152 | |||
153 | /* Length: 15 "SPI=0xF1234567 */ | ||
154 | nf_log_buf_add(m, "SPI=0x%x ", ntohl(ah->spi)); | ||
155 | |||
156 | } | ||
157 | |||
158 | hdrlen = (hp->hdrlen+2)<<2; | ||
159 | break; | ||
160 | case IPPROTO_ESP: | ||
161 | if (logflags & XT_LOG_IPOPT) { | ||
162 | struct ip_esp_hdr _esph; | ||
163 | const struct ip_esp_hdr *eh; | ||
164 | |||
165 | /* Max length: 4 "ESP " */ | ||
166 | nf_log_buf_add(m, "ESP "); | ||
167 | |||
168 | if (fragment) { | ||
169 | nf_log_buf_add(m, ")"); | ||
170 | return; | ||
171 | } | ||
172 | |||
173 | /* | ||
174 | * Max length: 26 "INCOMPLETE [65535 bytes] )" | ||
175 | */ | ||
176 | eh = skb_header_pointer(skb, ptr, sizeof(_esph), | ||
177 | &_esph); | ||
178 | if (eh == NULL) { | ||
179 | nf_log_buf_add(m, "INCOMPLETE [%u bytes] )", | ||
180 | skb->len - ptr); | ||
181 | return; | ||
182 | } | ||
183 | |||
184 | /* Length: 16 "SPI=0xF1234567 )" */ | ||
185 | nf_log_buf_add(m, "SPI=0x%x )", | ||
186 | ntohl(eh->spi)); | ||
187 | } | ||
188 | return; | ||
189 | default: | ||
190 | /* Max length: 20 "Unknown Ext Hdr 255" */ | ||
191 | nf_log_buf_add(m, "Unknown Ext Hdr %u", currenthdr); | ||
192 | return; | ||
193 | } | ||
194 | if (logflags & XT_LOG_IPOPT) | ||
195 | nf_log_buf_add(m, ") "); | ||
196 | |||
197 | currenthdr = hp->nexthdr; | ||
198 | ptr += hdrlen; | ||
199 | } | ||
200 | |||
201 | switch (currenthdr) { | ||
202 | case IPPROTO_TCP: | ||
203 | if (nf_log_dump_tcp_header(m, skb, currenthdr, fragment, | ||
204 | ptr, logflags)) | ||
205 | return; | ||
206 | break; | ||
207 | case IPPROTO_UDP: | ||
208 | case IPPROTO_UDPLITE: | ||
209 | if (nf_log_dump_udp_header(m, skb, currenthdr, fragment, ptr)) | ||
210 | return; | ||
211 | break; | ||
212 | case IPPROTO_ICMPV6: { | ||
213 | struct icmp6hdr _icmp6h; | ||
214 | const struct icmp6hdr *ic; | ||
215 | |||
216 | /* Max length: 13 "PROTO=ICMPv6 " */ | ||
217 | nf_log_buf_add(m, "PROTO=ICMPv6 "); | ||
218 | |||
219 | if (fragment) | ||
220 | break; | ||
221 | |||
222 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ | ||
223 | ic = skb_header_pointer(skb, ptr, sizeof(_icmp6h), &_icmp6h); | ||
224 | if (ic == NULL) { | ||
225 | nf_log_buf_add(m, "INCOMPLETE [%u bytes] ", | ||
226 | skb->len - ptr); | ||
227 | return; | ||
228 | } | ||
229 | |||
230 | /* Max length: 18 "TYPE=255 CODE=255 " */ | ||
231 | nf_log_buf_add(m, "TYPE=%u CODE=%u ", | ||
232 | ic->icmp6_type, ic->icmp6_code); | ||
233 | |||
234 | switch (ic->icmp6_type) { | ||
235 | case ICMPV6_ECHO_REQUEST: | ||
236 | case ICMPV6_ECHO_REPLY: | ||
237 | /* Max length: 19 "ID=65535 SEQ=65535 " */ | ||
238 | nf_log_buf_add(m, "ID=%u SEQ=%u ", | ||
239 | ntohs(ic->icmp6_identifier), | ||
240 | ntohs(ic->icmp6_sequence)); | ||
241 | break; | ||
242 | case ICMPV6_MGM_QUERY: | ||
243 | case ICMPV6_MGM_REPORT: | ||
244 | case ICMPV6_MGM_REDUCTION: | ||
245 | break; | ||
246 | |||
247 | case ICMPV6_PARAMPROB: | ||
248 | /* Max length: 17 "POINTER=ffffffff " */ | ||
249 | nf_log_buf_add(m, "POINTER=%08x ", | ||
250 | ntohl(ic->icmp6_pointer)); | ||
251 | /* Fall through */ | ||
252 | case ICMPV6_DEST_UNREACH: | ||
253 | case ICMPV6_PKT_TOOBIG: | ||
254 | case ICMPV6_TIME_EXCEED: | ||
255 | /* Max length: 3+maxlen */ | ||
256 | if (recurse) { | ||
257 | nf_log_buf_add(m, "["); | ||
258 | dump_ipv6_packet(m, info, skb, | ||
259 | ptr + sizeof(_icmp6h), 0); | ||
260 | nf_log_buf_add(m, "] "); | ||
261 | } | ||
262 | |||
263 | /* Max length: 10 "MTU=65535 " */ | ||
264 | if (ic->icmp6_type == ICMPV6_PKT_TOOBIG) { | ||
265 | nf_log_buf_add(m, "MTU=%u ", | ||
266 | ntohl(ic->icmp6_mtu)); | ||
267 | } | ||
268 | } | ||
269 | break; | ||
270 | } | ||
271 | /* Max length: 10 "PROTO=255 " */ | ||
272 | default: | ||
273 | nf_log_buf_add(m, "PROTO=%u ", currenthdr); | ||
274 | } | ||
275 | |||
276 | /* Max length: 15 "UID=4294967295 " */ | ||
277 | if ((logflags & XT_LOG_UID) && recurse) | ||
278 | nf_log_dump_sk_uid_gid(m, skb->sk); | ||
279 | |||
280 | /* Max length: 16 "MARK=0xFFFFFFFF " */ | ||
281 | if (recurse && skb->mark) | ||
282 | nf_log_buf_add(m, "MARK=0x%x ", skb->mark); | ||
283 | } | ||
284 | |||
285 | static void dump_ipv6_mac_header(struct nf_log_buf *m, | ||
286 | const struct nf_loginfo *info, | ||
287 | const struct sk_buff *skb) | ||
288 | { | ||
289 | struct net_device *dev = skb->dev; | ||
290 | unsigned int logflags = 0; | ||
291 | |||
292 | if (info->type == NF_LOG_TYPE_LOG) | ||
293 | logflags = info->u.log.logflags; | ||
294 | |||
295 | if (!(logflags & XT_LOG_MACDECODE)) | ||
296 | goto fallback; | ||
297 | |||
298 | switch (dev->type) { | ||
299 | case ARPHRD_ETHER: | ||
300 | nf_log_buf_add(m, "MACSRC=%pM MACDST=%pM MACPROTO=%04x ", | ||
301 | eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, | ||
302 | ntohs(eth_hdr(skb)->h_proto)); | ||
303 | return; | ||
304 | default: | ||
305 | break; | ||
306 | } | ||
307 | |||
308 | fallback: | ||
309 | nf_log_buf_add(m, "MAC="); | ||
310 | if (dev->hard_header_len && | ||
311 | skb->mac_header != skb->network_header) { | ||
312 | const unsigned char *p = skb_mac_header(skb); | ||
313 | unsigned int len = dev->hard_header_len; | ||
314 | unsigned int i; | ||
315 | |||
316 | if (dev->type == ARPHRD_SIT) { | ||
317 | p -= ETH_HLEN; | ||
318 | |||
319 | if (p < skb->head) | ||
320 | p = NULL; | ||
321 | } | ||
322 | |||
323 | if (p != NULL) { | ||
324 | nf_log_buf_add(m, "%02x", *p++); | ||
325 | for (i = 1; i < len; i++) | ||
326 | nf_log_buf_add(m, ":%02x", *p++); | ||
327 | } | ||
328 | nf_log_buf_add(m, " "); | ||
329 | |||
330 | if (dev->type == ARPHRD_SIT) { | ||
331 | const struct iphdr *iph = | ||
332 | (struct iphdr *)skb_mac_header(skb); | ||
333 | nf_log_buf_add(m, "TUNNEL=%pI4->%pI4 ", &iph->saddr, | ||
334 | &iph->daddr); | ||
335 | } | ||
336 | } else { | ||
337 | nf_log_buf_add(m, " "); | ||
338 | } | ||
339 | } | ||
340 | |||
341 | static void nf_log_ip6_packet(struct net *net, u_int8_t pf, | ||
342 | unsigned int hooknum, const struct sk_buff *skb, | ||
343 | const struct net_device *in, | ||
344 | const struct net_device *out, | ||
345 | const struct nf_loginfo *loginfo, | ||
346 | const char *prefix) | ||
347 | { | ||
348 | struct nf_log_buf *m; | ||
349 | |||
350 | /* FIXME: Disabled from containers until syslog ns is supported */ | ||
351 | if (!net_eq(net, &init_net)) | ||
352 | return; | ||
353 | |||
354 | m = nf_log_buf_open(); | ||
355 | |||
356 | if (!loginfo) | ||
357 | loginfo = &default_loginfo; | ||
358 | |||
359 | nf_log_dump_packet_common(m, pf, hooknum, skb, in, out, | ||
360 | loginfo, prefix); | ||
361 | |||
362 | if (in != NULL) | ||
363 | dump_ipv6_mac_header(m, loginfo, skb); | ||
364 | |||
365 | dump_ipv6_packet(m, loginfo, skb, skb_network_offset(skb), 1); | ||
366 | |||
367 | nf_log_buf_close(m); | ||
368 | } | ||
369 | |||
370 | static struct nf_logger nf_ip6_logger __read_mostly = { | ||
371 | .name = "nf_log_ipv6", | ||
372 | .type = NF_LOG_TYPE_LOG, | ||
373 | .logfn = nf_log_ip6_packet, | ||
374 | .me = THIS_MODULE, | ||
375 | }; | ||
376 | |||
377 | static int __net_init nf_log_ipv6_net_init(struct net *net) | ||
378 | { | ||
379 | nf_log_set(net, NFPROTO_IPV6, &nf_ip6_logger); | ||
380 | return 0; | ||
381 | } | ||
382 | |||
383 | static void __net_exit nf_log_ipv6_net_exit(struct net *net) | ||
384 | { | ||
385 | nf_log_unset(net, &nf_ip6_logger); | ||
386 | } | ||
387 | |||
388 | static struct pernet_operations nf_log_ipv6_net_ops = { | ||
389 | .init = nf_log_ipv6_net_init, | ||
390 | .exit = nf_log_ipv6_net_exit, | ||
391 | }; | ||
392 | |||
393 | static int __init nf_log_ipv6_init(void) | ||
394 | { | ||
395 | int ret; | ||
396 | |||
397 | ret = register_pernet_subsys(&nf_log_ipv6_net_ops); | ||
398 | if (ret < 0) | ||
399 | return ret; | ||
400 | |||
401 | nf_log_register(NFPROTO_IPV6, &nf_ip6_logger); | ||
402 | return 0; | ||
403 | } | ||
404 | |||
405 | static void __exit nf_log_ipv6_exit(void) | ||
406 | { | ||
407 | unregister_pernet_subsys(&nf_log_ipv6_net_ops); | ||
408 | nf_log_unregister(&nf_ip6_logger); | ||
409 | } | ||
410 | |||
411 | module_init(nf_log_ipv6_init); | ||
412 | module_exit(nf_log_ipv6_exit); | ||
413 | |||
414 | MODULE_AUTHOR("Netfilter Core Team <coreteam@netfilter.org>"); | ||
415 | MODULE_DESCRIPTION("Netfilter IPv4 packet logging"); | ||
416 | MODULE_LICENSE("GPL"); | ||
417 | MODULE_ALIAS_NF_LOGGER(AF_INET6, 0); | ||
diff --git a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c index abfe75a2e316..fc8e49b2ff3e 100644 --- a/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c +++ b/net/ipv6/netfilter/nf_nat_l3proto_ipv6.c | |||
@@ -158,6 +158,7 @@ static void nf_nat_ipv6_csum_recalc(struct sk_buff *skb, | |||
158 | htons(oldlen), htons(datalen), 1); | 158 | htons(oldlen), htons(datalen), 1); |
159 | } | 159 | } |
160 | 160 | ||
161 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) | ||
161 | static int nf_nat_ipv6_nlattr_to_range(struct nlattr *tb[], | 162 | static int nf_nat_ipv6_nlattr_to_range(struct nlattr *tb[], |
162 | struct nf_nat_range *range) | 163 | struct nf_nat_range *range) |
163 | { | 164 | { |
@@ -175,6 +176,7 @@ static int nf_nat_ipv6_nlattr_to_range(struct nlattr *tb[], | |||
175 | 176 | ||
176 | return 0; | 177 | return 0; |
177 | } | 178 | } |
179 | #endif | ||
178 | 180 | ||
179 | static const struct nf_nat_l3proto nf_nat_l3proto_ipv6 = { | 181 | static const struct nf_nat_l3proto nf_nat_l3proto_ipv6 = { |
180 | .l3proto = NFPROTO_IPV6, | 182 | .l3proto = NFPROTO_IPV6, |
@@ -183,7 +185,9 @@ static const struct nf_nat_l3proto nf_nat_l3proto_ipv6 = { | |||
183 | .manip_pkt = nf_nat_ipv6_manip_pkt, | 185 | .manip_pkt = nf_nat_ipv6_manip_pkt, |
184 | .csum_update = nf_nat_ipv6_csum_update, | 186 | .csum_update = nf_nat_ipv6_csum_update, |
185 | .csum_recalc = nf_nat_ipv6_csum_recalc, | 187 | .csum_recalc = nf_nat_ipv6_csum_recalc, |
188 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) | ||
186 | .nlattr_to_range = nf_nat_ipv6_nlattr_to_range, | 189 | .nlattr_to_range = nf_nat_ipv6_nlattr_to_range, |
190 | #endif | ||
187 | #ifdef CONFIG_XFRM | 191 | #ifdef CONFIG_XFRM |
188 | .decode_session = nf_nat_ipv6_decode_session, | 192 | .decode_session = nf_nat_ipv6_decode_session, |
189 | #endif | 193 | #endif |
diff --git a/net/ipv6/proc.c b/net/ipv6/proc.c index 3317440ea341..2d6f860e5c1e 100644 --- a/net/ipv6/proc.c +++ b/net/ipv6/proc.c | |||
@@ -33,6 +33,7 @@ | |||
33 | static int sockstat6_seq_show(struct seq_file *seq, void *v) | 33 | static int sockstat6_seq_show(struct seq_file *seq, void *v) |
34 | { | 34 | { |
35 | struct net *net = seq->private; | 35 | struct net *net = seq->private; |
36 | unsigned int frag_mem = ip6_frag_mem(net); | ||
36 | 37 | ||
37 | seq_printf(seq, "TCP6: inuse %d\n", | 38 | seq_printf(seq, "TCP6: inuse %d\n", |
38 | sock_prot_inuse_get(net, &tcpv6_prot)); | 39 | sock_prot_inuse_get(net, &tcpv6_prot)); |
@@ -42,8 +43,7 @@ static int sockstat6_seq_show(struct seq_file *seq, void *v) | |||
42 | sock_prot_inuse_get(net, &udplitev6_prot)); | 43 | sock_prot_inuse_get(net, &udplitev6_prot)); |
43 | seq_printf(seq, "RAW6: inuse %d\n", | 44 | seq_printf(seq, "RAW6: inuse %d\n", |
44 | sock_prot_inuse_get(net, &rawv6_prot)); | 45 | sock_prot_inuse_get(net, &rawv6_prot)); |
45 | seq_printf(seq, "FRAG6: inuse %d memory %d\n", | 46 | seq_printf(seq, "FRAG6: inuse %u memory %u\n", !!frag_mem, frag_mem); |
46 | ip6_frag_nqueues(net), ip6_frag_mem(net)); | ||
47 | return 0; | 47 | return 0; |
48 | } | 48 | } |
49 | 49 | ||
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index b2dc60b0c764..39d44226e402 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c | |||
@@ -176,7 +176,7 @@ static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) | |||
176 | goto out; | 176 | goto out; |
177 | 177 | ||
178 | net = dev_net(skb->dev); | 178 | net = dev_net(skb->dev); |
179 | sk = __raw_v6_lookup(net, sk, nexthdr, daddr, saddr, IP6CB(skb)->iif); | 179 | sk = __raw_v6_lookup(net, sk, nexthdr, daddr, saddr, inet6_iif(skb)); |
180 | 180 | ||
181 | while (sk) { | 181 | while (sk) { |
182 | int filtered; | 182 | int filtered; |
@@ -220,7 +220,7 @@ static bool ipv6_raw_deliver(struct sk_buff *skb, int nexthdr) | |||
220 | } | 220 | } |
221 | } | 221 | } |
222 | sk = __raw_v6_lookup(net, sk_next(sk), nexthdr, daddr, saddr, | 222 | sk = __raw_v6_lookup(net, sk_next(sk), nexthdr, daddr, saddr, |
223 | IP6CB(skb)->iif); | 223 | inet6_iif(skb)); |
224 | } | 224 | } |
225 | out: | 225 | out: |
226 | read_unlock(&raw_v6_hashinfo.lock); | 226 | read_unlock(&raw_v6_hashinfo.lock); |
@@ -375,7 +375,7 @@ void raw6_icmp_error(struct sk_buff *skb, int nexthdr, | |||
375 | net = dev_net(skb->dev); | 375 | net = dev_net(skb->dev); |
376 | 376 | ||
377 | while ((sk = __raw_v6_lookup(net, sk, nexthdr, saddr, daddr, | 377 | while ((sk = __raw_v6_lookup(net, sk, nexthdr, saddr, daddr, |
378 | IP6CB(skb)->iif))) { | 378 | inet6_iif(skb)))) { |
379 | rawv6_err(sk, skb, NULL, type, code, | 379 | rawv6_err(sk, skb, NULL, type, code, |
380 | inner_offset, info); | 380 | inner_offset, info); |
381 | sk = sk_next(sk); | 381 | sk = sk_next(sk); |
@@ -506,7 +506,7 @@ static int rawv6_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
506 | sin6->sin6_addr = ipv6_hdr(skb)->saddr; | 506 | sin6->sin6_addr = ipv6_hdr(skb)->saddr; |
507 | sin6->sin6_flowinfo = 0; | 507 | sin6->sin6_flowinfo = 0; |
508 | sin6->sin6_scope_id = ipv6_iface_scope_id(&sin6->sin6_addr, | 508 | sin6->sin6_scope_id = ipv6_iface_scope_id(&sin6->sin6_addr, |
509 | IP6CB(skb)->iif); | 509 | inet6_iif(skb)); |
510 | *addr_len = sizeof(*sin6); | 510 | *addr_len = sizeof(*sin6); |
511 | } | 511 | } |
512 | 512 | ||
@@ -588,8 +588,7 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, | |||
588 | } | 588 | } |
589 | 589 | ||
590 | offset += skb_transport_offset(skb); | 590 | offset += skb_transport_offset(skb); |
591 | if (skb_copy_bits(skb, offset, &csum, 2)) | 591 | BUG_ON(skb_copy_bits(skb, offset, &csum, 2)); |
592 | BUG(); | ||
593 | 592 | ||
594 | /* in case cksum was not initialized */ | 593 | /* in case cksum was not initialized */ |
595 | if (unlikely(csum)) | 594 | if (unlikely(csum)) |
@@ -601,8 +600,7 @@ static int rawv6_push_pending_frames(struct sock *sk, struct flowi6 *fl6, | |||
601 | if (csum == 0 && fl6->flowi6_proto == IPPROTO_UDP) | 600 | if (csum == 0 && fl6->flowi6_proto == IPPROTO_UDP) |
602 | csum = CSUM_MANGLED_0; | 601 | csum = CSUM_MANGLED_0; |
603 | 602 | ||
604 | if (skb_store_bits(skb, offset, &csum, 2)) | 603 | BUG_ON(skb_store_bits(skb, offset, &csum, 2)); |
605 | BUG(); | ||
606 | 604 | ||
607 | send: | 605 | send: |
608 | err = ip6_push_pending_frames(sk); | 606 | err = ip6_push_pending_frames(sk); |
diff --git a/net/ipv6/reassembly.c b/net/ipv6/reassembly.c index cc85a9ba5010..c6557d9f7808 100644 --- a/net/ipv6/reassembly.c +++ b/net/ipv6/reassembly.c | |||
@@ -60,6 +60,8 @@ | |||
60 | #include <net/inet_frag.h> | 60 | #include <net/inet_frag.h> |
61 | #include <net/inet_ecn.h> | 61 | #include <net/inet_ecn.h> |
62 | 62 | ||
63 | static const char ip6_frag_cache_name[] = "ip6-frags"; | ||
64 | |||
63 | struct ip6frag_skb_cb | 65 | struct ip6frag_skb_cb |
64 | { | 66 | { |
65 | struct inet6_skb_parm h; | 67 | struct inet6_skb_parm h; |
@@ -85,27 +87,23 @@ static int ip6_frag_reasm(struct frag_queue *fq, struct sk_buff *prev, | |||
85 | static unsigned int inet6_hash_frag(__be32 id, const struct in6_addr *saddr, | 87 | static unsigned int inet6_hash_frag(__be32 id, const struct in6_addr *saddr, |
86 | const struct in6_addr *daddr) | 88 | const struct in6_addr *daddr) |
87 | { | 89 | { |
88 | u32 c; | ||
89 | |||
90 | net_get_random_once(&ip6_frags.rnd, sizeof(ip6_frags.rnd)); | 90 | net_get_random_once(&ip6_frags.rnd, sizeof(ip6_frags.rnd)); |
91 | c = jhash_3words(ipv6_addr_hash(saddr), ipv6_addr_hash(daddr), | 91 | return jhash_3words(ipv6_addr_hash(saddr), ipv6_addr_hash(daddr), |
92 | (__force u32)id, ip6_frags.rnd); | 92 | (__force u32)id, ip6_frags.rnd); |
93 | |||
94 | return c & (INETFRAGS_HASHSZ - 1); | ||
95 | } | 93 | } |
96 | 94 | ||
97 | static unsigned int ip6_hashfn(struct inet_frag_queue *q) | 95 | static unsigned int ip6_hashfn(const struct inet_frag_queue *q) |
98 | { | 96 | { |
99 | struct frag_queue *fq; | 97 | const struct frag_queue *fq; |
100 | 98 | ||
101 | fq = container_of(q, struct frag_queue, q); | 99 | fq = container_of(q, struct frag_queue, q); |
102 | return inet6_hash_frag(fq->id, &fq->saddr, &fq->daddr); | 100 | return inet6_hash_frag(fq->id, &fq->saddr, &fq->daddr); |
103 | } | 101 | } |
104 | 102 | ||
105 | bool ip6_frag_match(struct inet_frag_queue *q, void *a) | 103 | bool ip6_frag_match(const struct inet_frag_queue *q, const void *a) |
106 | { | 104 | { |
107 | struct frag_queue *fq; | 105 | const struct frag_queue *fq; |
108 | struct ip6_create_arg *arg = a; | 106 | const struct ip6_create_arg *arg = a; |
109 | 107 | ||
110 | fq = container_of(q, struct frag_queue, q); | 108 | fq = container_of(q, struct frag_queue, q); |
111 | return fq->id == arg->id && | 109 | return fq->id == arg->id && |
@@ -115,10 +113,10 @@ bool ip6_frag_match(struct inet_frag_queue *q, void *a) | |||
115 | } | 113 | } |
116 | EXPORT_SYMBOL(ip6_frag_match); | 114 | EXPORT_SYMBOL(ip6_frag_match); |
117 | 115 | ||
118 | void ip6_frag_init(struct inet_frag_queue *q, void *a) | 116 | void ip6_frag_init(struct inet_frag_queue *q, const void *a) |
119 | { | 117 | { |
120 | struct frag_queue *fq = container_of(q, struct frag_queue, q); | 118 | struct frag_queue *fq = container_of(q, struct frag_queue, q); |
121 | struct ip6_create_arg *arg = a; | 119 | const struct ip6_create_arg *arg = a; |
122 | 120 | ||
123 | fq->id = arg->id; | 121 | fq->id = arg->id; |
124 | fq->user = arg->user; | 122 | fq->user = arg->user; |
@@ -135,7 +133,7 @@ void ip6_expire_frag_queue(struct net *net, struct frag_queue *fq, | |||
135 | 133 | ||
136 | spin_lock(&fq->q.lock); | 134 | spin_lock(&fq->q.lock); |
137 | 135 | ||
138 | if (fq->q.last_in & INET_FRAG_COMPLETE) | 136 | if (fq->q.flags & INET_FRAG_COMPLETE) |
139 | goto out; | 137 | goto out; |
140 | 138 | ||
141 | inet_frag_kill(&fq->q, frags); | 139 | inet_frag_kill(&fq->q, frags); |
@@ -145,17 +143,20 @@ void ip6_expire_frag_queue(struct net *net, struct frag_queue *fq, | |||
145 | if (!dev) | 143 | if (!dev) |
146 | goto out_rcu_unlock; | 144 | goto out_rcu_unlock; |
147 | 145 | ||
148 | IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMTIMEOUT); | ||
149 | IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMFAILS); | 146 | IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMFAILS); |
150 | 147 | ||
148 | if (fq->q.flags & INET_FRAG_EVICTED) | ||
149 | goto out_rcu_unlock; | ||
150 | |||
151 | IP6_INC_STATS_BH(net, __in6_dev_get(dev), IPSTATS_MIB_REASMTIMEOUT); | ||
152 | |||
151 | /* Don't send error if the first segment did not arrive. */ | 153 | /* Don't send error if the first segment did not arrive. */ |
152 | if (!(fq->q.last_in & INET_FRAG_FIRST_IN) || !fq->q.fragments) | 154 | if (!(fq->q.flags & INET_FRAG_FIRST_IN) || !fq->q.fragments) |
153 | goto out_rcu_unlock; | 155 | goto out_rcu_unlock; |
154 | 156 | ||
155 | /* | 157 | /* But use as source device on which LAST ARRIVED |
156 | But use as source device on which LAST ARRIVED | 158 | * segment was received. And do not use fq->dev |
157 | segment was received. And do not use fq->dev | 159 | * pointer directly, device might already disappeared. |
158 | pointer directly, device might already disappeared. | ||
159 | */ | 160 | */ |
160 | fq->q.fragments->dev = dev; | 161 | fq->q.fragments->dev = dev; |
161 | icmpv6_send(fq->q.fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0); | 162 | icmpv6_send(fq->q.fragments, ICMPV6_TIME_EXCEED, ICMPV6_EXC_FRAGTIME, 0); |
@@ -192,7 +193,6 @@ fq_find(struct net *net, __be32 id, const struct in6_addr *src, | |||
192 | arg.dst = dst; | 193 | arg.dst = dst; |
193 | arg.ecn = ecn; | 194 | arg.ecn = ecn; |
194 | 195 | ||
195 | read_lock(&ip6_frags.lock); | ||
196 | hash = inet6_hash_frag(id, src, dst); | 196 | hash = inet6_hash_frag(id, src, dst); |
197 | 197 | ||
198 | q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash); | 198 | q = inet_frag_find(&net->ipv6.frags, &ip6_frags, &arg, hash); |
@@ -212,7 +212,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
212 | struct net *net = dev_net(skb_dst(skb)->dev); | 212 | struct net *net = dev_net(skb_dst(skb)->dev); |
213 | u8 ecn; | 213 | u8 ecn; |
214 | 214 | ||
215 | if (fq->q.last_in & INET_FRAG_COMPLETE) | 215 | if (fq->q.flags & INET_FRAG_COMPLETE) |
216 | goto err; | 216 | goto err; |
217 | 217 | ||
218 | offset = ntohs(fhdr->frag_off) & ~0x7; | 218 | offset = ntohs(fhdr->frag_off) & ~0x7; |
@@ -243,9 +243,9 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
243 | * or have different end, the segment is corrupted. | 243 | * or have different end, the segment is corrupted. |
244 | */ | 244 | */ |
245 | if (end < fq->q.len || | 245 | if (end < fq->q.len || |
246 | ((fq->q.last_in & INET_FRAG_LAST_IN) && end != fq->q.len)) | 246 | ((fq->q.flags & INET_FRAG_LAST_IN) && end != fq->q.len)) |
247 | goto err; | 247 | goto err; |
248 | fq->q.last_in |= INET_FRAG_LAST_IN; | 248 | fq->q.flags |= INET_FRAG_LAST_IN; |
249 | fq->q.len = end; | 249 | fq->q.len = end; |
250 | } else { | 250 | } else { |
251 | /* Check if the fragment is rounded to 8 bytes. | 251 | /* Check if the fragment is rounded to 8 bytes. |
@@ -263,7 +263,7 @@ static int ip6_frag_queue(struct frag_queue *fq, struct sk_buff *skb, | |||
263 | } | 263 | } |
264 | if (end > fq->q.len) { | 264 | if (end > fq->q.len) { |
265 | /* Some bits beyond end -> corruption. */ | 265 | /* Some bits beyond end -> corruption. */ |
266 | if (fq->q.last_in & INET_FRAG_LAST_IN) | 266 | if (fq->q.flags & INET_FRAG_LAST_IN) |
267 | goto err; | 267 | goto err; |
268 | fq->q.len = end; | 268 | fq->q.len = end; |
269 | } | 269 | } |
@@ -338,10 +338,10 @@ found: | |||
338 | */ | 338 | */ |
339 | if (offset == 0) { | 339 | if (offset == 0) { |
340 | fq->nhoffset = nhoff; | 340 | fq->nhoffset = nhoff; |
341 | fq->q.last_in |= INET_FRAG_FIRST_IN; | 341 | fq->q.flags |= INET_FRAG_FIRST_IN; |
342 | } | 342 | } |
343 | 343 | ||
344 | if (fq->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && | 344 | if (fq->q.flags == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && |
345 | fq->q.meat == fq->q.len) { | 345 | fq->q.meat == fq->q.len) { |
346 | int res; | 346 | int res; |
347 | unsigned long orefdst = skb->_skb_refdst; | 347 | unsigned long orefdst = skb->_skb_refdst; |
@@ -353,14 +353,13 @@ found: | |||
353 | } | 353 | } |
354 | 354 | ||
355 | skb_dst_drop(skb); | 355 | skb_dst_drop(skb); |
356 | inet_frag_lru_move(&fq->q); | ||
357 | return -1; | 356 | return -1; |
358 | 357 | ||
359 | discard_fq: | 358 | discard_fq: |
360 | inet_frag_kill(&fq->q, &ip6_frags); | 359 | inet_frag_kill(&fq->q, &ip6_frags); |
361 | err: | 360 | err: |
362 | IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), | 361 | IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), |
363 | IPSTATS_MIB_REASMFAILS); | 362 | IPSTATS_MIB_REASMFAILS); |
364 | kfree_skb(skb); | 363 | kfree_skb(skb); |
365 | return -1; | 364 | return -1; |
366 | } | 365 | } |
@@ -523,7 +522,6 @@ static int ipv6_frag_rcv(struct sk_buff *skb) | |||
523 | struct frag_queue *fq; | 522 | struct frag_queue *fq; |
524 | const struct ipv6hdr *hdr = ipv6_hdr(skb); | 523 | const struct ipv6hdr *hdr = ipv6_hdr(skb); |
525 | struct net *net = dev_net(skb_dst(skb)->dev); | 524 | struct net *net = dev_net(skb_dst(skb)->dev); |
526 | int evicted; | ||
527 | 525 | ||
528 | if (IP6CB(skb)->flags & IP6SKB_FRAGMENTED) | 526 | if (IP6CB(skb)->flags & IP6SKB_FRAGMENTED) |
529 | goto fail_hdr; | 527 | goto fail_hdr; |
@@ -552,11 +550,6 @@ static int ipv6_frag_rcv(struct sk_buff *skb) | |||
552 | return 1; | 550 | return 1; |
553 | } | 551 | } |
554 | 552 | ||
555 | evicted = inet_frag_evictor(&net->ipv6.frags, &ip6_frags, false); | ||
556 | if (evicted) | ||
557 | IP6_ADD_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), | ||
558 | IPSTATS_MIB_REASMFAILS, evicted); | ||
559 | |||
560 | fq = fq_find(net, fhdr->identification, &hdr->saddr, &hdr->daddr, | 553 | fq = fq_find(net, fhdr->identification, &hdr->saddr, &hdr->daddr, |
561 | ip6_frag_ecn(hdr)); | 554 | ip6_frag_ecn(hdr)); |
562 | if (fq != NULL) { | 555 | if (fq != NULL) { |
@@ -576,7 +569,8 @@ static int ipv6_frag_rcv(struct sk_buff *skb) | |||
576 | return -1; | 569 | return -1; |
577 | 570 | ||
578 | fail_hdr: | 571 | fail_hdr: |
579 | IP6_INC_STATS(net, ip6_dst_idev(skb_dst(skb)), IPSTATS_MIB_INHDRERRORS); | 572 | IP6_INC_STATS_BH(net, ip6_dst_idev(skb_dst(skb)), |
573 | IPSTATS_MIB_INHDRERRORS); | ||
580 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb_network_header_len(skb)); | 574 | icmpv6_param_prob(skb, ICMPV6_HDR_FIELD, skb_network_header_len(skb)); |
581 | return -1; | 575 | return -1; |
582 | } | 576 | } |
@@ -588,20 +582,25 @@ static const struct inet6_protocol frag_protocol = | |||
588 | }; | 582 | }; |
589 | 583 | ||
590 | #ifdef CONFIG_SYSCTL | 584 | #ifdef CONFIG_SYSCTL |
585 | static int zero; | ||
586 | |||
591 | static struct ctl_table ip6_frags_ns_ctl_table[] = { | 587 | static struct ctl_table ip6_frags_ns_ctl_table[] = { |
592 | { | 588 | { |
593 | .procname = "ip6frag_high_thresh", | 589 | .procname = "ip6frag_high_thresh", |
594 | .data = &init_net.ipv6.frags.high_thresh, | 590 | .data = &init_net.ipv6.frags.high_thresh, |
595 | .maxlen = sizeof(int), | 591 | .maxlen = sizeof(int), |
596 | .mode = 0644, | 592 | .mode = 0644, |
597 | .proc_handler = proc_dointvec | 593 | .proc_handler = proc_dointvec_minmax, |
594 | .extra1 = &init_net.ipv6.frags.low_thresh | ||
598 | }, | 595 | }, |
599 | { | 596 | { |
600 | .procname = "ip6frag_low_thresh", | 597 | .procname = "ip6frag_low_thresh", |
601 | .data = &init_net.ipv6.frags.low_thresh, | 598 | .data = &init_net.ipv6.frags.low_thresh, |
602 | .maxlen = sizeof(int), | 599 | .maxlen = sizeof(int), |
603 | .mode = 0644, | 600 | .mode = 0644, |
604 | .proc_handler = proc_dointvec | 601 | .proc_handler = proc_dointvec_minmax, |
602 | .extra1 = &zero, | ||
603 | .extra2 = &init_net.ipv6.frags.high_thresh | ||
605 | }, | 604 | }, |
606 | { | 605 | { |
607 | .procname = "ip6frag_time", | 606 | .procname = "ip6frag_time", |
@@ -613,10 +612,12 @@ static struct ctl_table ip6_frags_ns_ctl_table[] = { | |||
613 | { } | 612 | { } |
614 | }; | 613 | }; |
615 | 614 | ||
615 | /* secret interval has been deprecated */ | ||
616 | static int ip6_frags_secret_interval_unused; | ||
616 | static struct ctl_table ip6_frags_ctl_table[] = { | 617 | static struct ctl_table ip6_frags_ctl_table[] = { |
617 | { | 618 | { |
618 | .procname = "ip6frag_secret_interval", | 619 | .procname = "ip6frag_secret_interval", |
619 | .data = &ip6_frags.secret_interval, | 620 | .data = &ip6_frags_secret_interval_unused, |
620 | .maxlen = sizeof(int), | 621 | .maxlen = sizeof(int), |
621 | .mode = 0644, | 622 | .mode = 0644, |
622 | .proc_handler = proc_dointvec_jiffies, | 623 | .proc_handler = proc_dointvec_jiffies, |
@@ -636,7 +637,10 @@ static int __net_init ip6_frags_ns_sysctl_register(struct net *net) | |||
636 | goto err_alloc; | 637 | goto err_alloc; |
637 | 638 | ||
638 | table[0].data = &net->ipv6.frags.high_thresh; | 639 | table[0].data = &net->ipv6.frags.high_thresh; |
640 | table[0].extra1 = &net->ipv6.frags.low_thresh; | ||
641 | table[0].extra2 = &init_net.ipv6.frags.high_thresh; | ||
639 | table[1].data = &net->ipv6.frags.low_thresh; | 642 | table[1].data = &net->ipv6.frags.low_thresh; |
643 | table[1].extra2 = &net->ipv6.frags.high_thresh; | ||
640 | table[2].data = &net->ipv6.frags.timeout; | 644 | table[2].data = &net->ipv6.frags.timeout; |
641 | 645 | ||
642 | /* Don't export sysctls to unprivileged users */ | 646 | /* Don't export sysctls to unprivileged users */ |
@@ -746,8 +750,10 @@ int __init ipv6_frag_init(void) | |||
746 | ip6_frags.qsize = sizeof(struct frag_queue); | 750 | ip6_frags.qsize = sizeof(struct frag_queue); |
747 | ip6_frags.match = ip6_frag_match; | 751 | ip6_frags.match = ip6_frag_match; |
748 | ip6_frags.frag_expire = ip6_frag_expire; | 752 | ip6_frags.frag_expire = ip6_frag_expire; |
749 | ip6_frags.secret_interval = 10 * 60 * HZ; | 753 | ip6_frags.frags_cache_name = ip6_frag_cache_name; |
750 | inet_frags_init(&ip6_frags); | 754 | ret = inet_frags_init(&ip6_frags); |
755 | if (ret) | ||
756 | goto err_pernet; | ||
751 | out: | 757 | out: |
752 | return ret; | 758 | return ret; |
753 | 759 | ||
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index f23fbd28a501..bafde82324c5 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -314,7 +314,6 @@ static inline struct rt6_info *ip6_dst_alloc(struct net *net, | |||
314 | 314 | ||
315 | memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst)); | 315 | memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst)); |
316 | rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers); | 316 | rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers); |
317 | rt->rt6i_genid = rt_genid_ipv6(net); | ||
318 | INIT_LIST_HEAD(&rt->rt6i_siblings); | 317 | INIT_LIST_HEAD(&rt->rt6i_siblings); |
319 | } | 318 | } |
320 | return rt; | 319 | return rt; |
@@ -1098,9 +1097,6 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie) | |||
1098 | * DST_OBSOLETE_FORCE_CHK which forces validation calls down | 1097 | * DST_OBSOLETE_FORCE_CHK which forces validation calls down |
1099 | * into this function always. | 1098 | * into this function always. |
1100 | */ | 1099 | */ |
1101 | if (rt->rt6i_genid != rt_genid_ipv6(dev_net(rt->dst.dev))) | ||
1102 | return NULL; | ||
1103 | |||
1104 | if (!rt->rt6i_node || (rt->rt6i_node->fn_sernum != cookie)) | 1100 | if (!rt->rt6i_node || (rt->rt6i_node->fn_sernum != cookie)) |
1105 | return NULL; | 1101 | return NULL; |
1106 | 1102 | ||
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 4f408176dc64..6163f851dc01 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
@@ -101,19 +101,19 @@ static struct ip_tunnel *ipip6_tunnel_lookup(struct net *net, | |||
101 | for_each_ip_tunnel_rcu(t, sitn->tunnels_r_l[h0 ^ h1]) { | 101 | for_each_ip_tunnel_rcu(t, sitn->tunnels_r_l[h0 ^ h1]) { |
102 | if (local == t->parms.iph.saddr && | 102 | if (local == t->parms.iph.saddr && |
103 | remote == t->parms.iph.daddr && | 103 | remote == t->parms.iph.daddr && |
104 | (!dev || !t->parms.link || dev->iflink == t->parms.link) && | 104 | (!dev || !t->parms.link || dev->ifindex == t->parms.link) && |
105 | (t->dev->flags & IFF_UP)) | 105 | (t->dev->flags & IFF_UP)) |
106 | return t; | 106 | return t; |
107 | } | 107 | } |
108 | for_each_ip_tunnel_rcu(t, sitn->tunnels_r[h0]) { | 108 | for_each_ip_tunnel_rcu(t, sitn->tunnels_r[h0]) { |
109 | if (remote == t->parms.iph.daddr && | 109 | if (remote == t->parms.iph.daddr && |
110 | (!dev || !t->parms.link || dev->iflink == t->parms.link) && | 110 | (!dev || !t->parms.link || dev->ifindex == t->parms.link) && |
111 | (t->dev->flags & IFF_UP)) | 111 | (t->dev->flags & IFF_UP)) |
112 | return t; | 112 | return t; |
113 | } | 113 | } |
114 | for_each_ip_tunnel_rcu(t, sitn->tunnels_l[h1]) { | 114 | for_each_ip_tunnel_rcu(t, sitn->tunnels_l[h1]) { |
115 | if (local == t->parms.iph.saddr && | 115 | if (local == t->parms.iph.saddr && |
116 | (!dev || !t->parms.link || dev->iflink == t->parms.link) && | 116 | (!dev || !t->parms.link || dev->ifindex == t->parms.link) && |
117 | (t->dev->flags & IFF_UP)) | 117 | (t->dev->flags & IFF_UP)) |
118 | return t; | 118 | return t; |
119 | } | 119 | } |
@@ -250,7 +250,8 @@ static struct ip_tunnel *ipip6_tunnel_locate(struct net *net, | |||
250 | else | 250 | else |
251 | strcpy(name, "sit%d"); | 251 | strcpy(name, "sit%d"); |
252 | 252 | ||
253 | dev = alloc_netdev(sizeof(*t), name, ipip6_tunnel_setup); | 253 | dev = alloc_netdev(sizeof(*t), name, NET_NAME_UNKNOWN, |
254 | ipip6_tunnel_setup); | ||
254 | if (dev == NULL) | 255 | if (dev == NULL) |
255 | return NULL; | 256 | return NULL; |
256 | 257 | ||
@@ -1729,6 +1730,7 @@ static int __net_init sit_init_net(struct net *net) | |||
1729 | sitn->tunnels[3] = sitn->tunnels_r_l; | 1730 | sitn->tunnels[3] = sitn->tunnels_r_l; |
1730 | 1731 | ||
1731 | sitn->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "sit0", | 1732 | sitn->fb_tunnel_dev = alloc_netdev(sizeof(struct ip_tunnel), "sit0", |
1733 | NET_NAME_UNKNOWN, | ||
1732 | ipip6_tunnel_setup); | 1734 | ipip6_tunnel_setup); |
1733 | if (!sitn->fb_tunnel_dev) { | 1735 | if (!sitn->fb_tunnel_dev) { |
1734 | err = -ENOMEM; | 1736 | err = -ENOMEM; |
diff --git a/net/ipv6/syncookies.c b/net/ipv6/syncookies.c index a822b880689b..83cea1d39466 100644 --- a/net/ipv6/syncookies.c +++ b/net/ipv6/syncookies.c | |||
@@ -187,7 +187,7 @@ struct sock *cookie_v6_check(struct sock *sk, struct sk_buff *skb) | |||
187 | goto out; | 187 | goto out; |
188 | 188 | ||
189 | ret = NULL; | 189 | ret = NULL; |
190 | req = inet6_reqsk_alloc(&tcp6_request_sock_ops); | 190 | req = inet_reqsk_alloc(&tcp6_request_sock_ops); |
191 | if (!req) | 191 | if (!req) |
192 | goto out; | 192 | goto out; |
193 | 193 | ||
diff --git a/net/ipv6/sysctl_net_ipv6.c b/net/ipv6/sysctl_net_ipv6.c index 058f3eca2e53..0c56c93619e0 100644 --- a/net/ipv6/sysctl_net_ipv6.c +++ b/net/ipv6/sysctl_net_ipv6.c | |||
@@ -39,6 +39,13 @@ static struct ctl_table ipv6_table_template[] = { | |||
39 | .proc_handler = proc_dointvec | 39 | .proc_handler = proc_dointvec |
40 | }, | 40 | }, |
41 | { | 41 | { |
42 | .procname = "auto_flowlabels", | ||
43 | .data = &init_net.ipv6.sysctl.auto_flowlabels, | ||
44 | .maxlen = sizeof(int), | ||
45 | .mode = 0644, | ||
46 | .proc_handler = proc_dointvec | ||
47 | }, | ||
48 | { | ||
42 | .procname = "fwmark_reflect", | 49 | .procname = "fwmark_reflect", |
43 | .data = &init_net.ipv6.sysctl.fwmark_reflect, | 50 | .data = &init_net.ipv6.sysctl.fwmark_reflect, |
44 | .maxlen = sizeof(int), | 51 | .maxlen = sizeof(int), |
@@ -74,6 +81,8 @@ static int __net_init ipv6_sysctl_net_init(struct net *net) | |||
74 | ipv6_table[0].data = &net->ipv6.sysctl.bindv6only; | 81 | ipv6_table[0].data = &net->ipv6.sysctl.bindv6only; |
75 | ipv6_table[1].data = &net->ipv6.sysctl.anycast_src_echo_reply; | 82 | ipv6_table[1].data = &net->ipv6.sysctl.anycast_src_echo_reply; |
76 | ipv6_table[2].data = &net->ipv6.sysctl.flowlabel_consistency; | 83 | ipv6_table[2].data = &net->ipv6.sysctl.flowlabel_consistency; |
84 | ipv6_table[3].data = &net->ipv6.sysctl.auto_flowlabels; | ||
85 | ipv6_table[4].data = &net->ipv6.sysctl.fwmark_reflect; | ||
77 | 86 | ||
78 | ipv6_route_table = ipv6_route_sysctl_init(net); | 87 | ipv6_route_table = ipv6_route_sysctl_init(net); |
79 | if (!ipv6_route_table) | 88 | if (!ipv6_route_table) |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 229239ad96b1..29964c3d363c 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
@@ -198,6 +198,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr, | |||
198 | sk->sk_v6_daddr = usin->sin6_addr; | 198 | sk->sk_v6_daddr = usin->sin6_addr; |
199 | np->flow_label = fl6.flowlabel; | 199 | np->flow_label = fl6.flowlabel; |
200 | 200 | ||
201 | ip6_set_txhash(sk); | ||
202 | |||
201 | /* | 203 | /* |
202 | * TCP over IPv4 | 204 | * TCP over IPv4 |
203 | */ | 205 | */ |
@@ -470,13 +472,14 @@ out: | |||
470 | 472 | ||
471 | 473 | ||
472 | static int tcp_v6_send_synack(struct sock *sk, struct dst_entry *dst, | 474 | static int tcp_v6_send_synack(struct sock *sk, struct dst_entry *dst, |
473 | struct flowi6 *fl6, | 475 | struct flowi *fl, |
474 | struct request_sock *req, | 476 | struct request_sock *req, |
475 | u16 queue_mapping, | 477 | u16 queue_mapping, |
476 | struct tcp_fastopen_cookie *foc) | 478 | struct tcp_fastopen_cookie *foc) |
477 | { | 479 | { |
478 | struct inet_request_sock *ireq = inet_rsk(req); | 480 | struct inet_request_sock *ireq = inet_rsk(req); |
479 | struct ipv6_pinfo *np = inet6_sk(sk); | 481 | struct ipv6_pinfo *np = inet6_sk(sk); |
482 | struct flowi6 *fl6 = &fl->u.ip6; | ||
480 | struct sk_buff *skb; | 483 | struct sk_buff *skb; |
481 | int err = -ENOMEM; | 484 | int err = -ENOMEM; |
482 | 485 | ||
@@ -503,18 +506,6 @@ done: | |||
503 | return err; | 506 | return err; |
504 | } | 507 | } |
505 | 508 | ||
506 | static int tcp_v6_rtx_synack(struct sock *sk, struct request_sock *req) | ||
507 | { | ||
508 | struct flowi6 fl6; | ||
509 | int res; | ||
510 | |||
511 | res = tcp_v6_send_synack(sk, NULL, &fl6, req, 0, NULL); | ||
512 | if (!res) { | ||
513 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS); | ||
514 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSYNRETRANS); | ||
515 | } | ||
516 | return res; | ||
517 | } | ||
518 | 509 | ||
519 | static void tcp_v6_reqsk_destructor(struct request_sock *req) | 510 | static void tcp_v6_reqsk_destructor(struct request_sock *req) |
520 | { | 511 | { |
@@ -676,7 +667,8 @@ clear_hash_noput: | |||
676 | return 1; | 667 | return 1; |
677 | } | 668 | } |
678 | 669 | ||
679 | static int tcp_v6_inbound_md5_hash(struct sock *sk, const struct sk_buff *skb) | 670 | static int __tcp_v6_inbound_md5_hash(struct sock *sk, |
671 | const struct sk_buff *skb) | ||
680 | { | 672 | { |
681 | const __u8 *hash_location = NULL; | 673 | const __u8 *hash_location = NULL; |
682 | struct tcp_md5sig_key *hash_expected; | 674 | struct tcp_md5sig_key *hash_expected; |
@@ -716,24 +708,80 @@ static int tcp_v6_inbound_md5_hash(struct sock *sk, const struct sk_buff *skb) | |||
716 | } | 708 | } |
717 | return 0; | 709 | return 0; |
718 | } | 710 | } |
711 | |||
712 | static int tcp_v6_inbound_md5_hash(struct sock *sk, const struct sk_buff *skb) | ||
713 | { | ||
714 | int ret; | ||
715 | |||
716 | rcu_read_lock(); | ||
717 | ret = __tcp_v6_inbound_md5_hash(sk, skb); | ||
718 | rcu_read_unlock(); | ||
719 | |||
720 | return ret; | ||
721 | } | ||
722 | |||
719 | #endif | 723 | #endif |
720 | 724 | ||
725 | static void tcp_v6_init_req(struct request_sock *req, struct sock *sk, | ||
726 | struct sk_buff *skb) | ||
727 | { | ||
728 | struct inet_request_sock *ireq = inet_rsk(req); | ||
729 | struct ipv6_pinfo *np = inet6_sk(sk); | ||
730 | |||
731 | ireq->ir_v6_rmt_addr = ipv6_hdr(skb)->saddr; | ||
732 | ireq->ir_v6_loc_addr = ipv6_hdr(skb)->daddr; | ||
733 | |||
734 | ireq->ir_iif = sk->sk_bound_dev_if; | ||
735 | |||
736 | /* So that link locals have meaning */ | ||
737 | if (!sk->sk_bound_dev_if && | ||
738 | ipv6_addr_type(&ireq->ir_v6_rmt_addr) & IPV6_ADDR_LINKLOCAL) | ||
739 | ireq->ir_iif = inet6_iif(skb); | ||
740 | |||
741 | if (!TCP_SKB_CB(skb)->when && | ||
742 | (ipv6_opt_accepted(sk, skb) || np->rxopt.bits.rxinfo || | ||
743 | np->rxopt.bits.rxoinfo || np->rxopt.bits.rxhlim || | ||
744 | np->rxopt.bits.rxohlim || np->repflow)) { | ||
745 | atomic_inc(&skb->users); | ||
746 | ireq->pktopts = skb; | ||
747 | } | ||
748 | } | ||
749 | |||
750 | static struct dst_entry *tcp_v6_route_req(struct sock *sk, struct flowi *fl, | ||
751 | const struct request_sock *req, | ||
752 | bool *strict) | ||
753 | { | ||
754 | if (strict) | ||
755 | *strict = true; | ||
756 | return inet6_csk_route_req(sk, &fl->u.ip6, req); | ||
757 | } | ||
758 | |||
721 | struct request_sock_ops tcp6_request_sock_ops __read_mostly = { | 759 | struct request_sock_ops tcp6_request_sock_ops __read_mostly = { |
722 | .family = AF_INET6, | 760 | .family = AF_INET6, |
723 | .obj_size = sizeof(struct tcp6_request_sock), | 761 | .obj_size = sizeof(struct tcp6_request_sock), |
724 | .rtx_syn_ack = tcp_v6_rtx_synack, | 762 | .rtx_syn_ack = tcp_rtx_synack, |
725 | .send_ack = tcp_v6_reqsk_send_ack, | 763 | .send_ack = tcp_v6_reqsk_send_ack, |
726 | .destructor = tcp_v6_reqsk_destructor, | 764 | .destructor = tcp_v6_reqsk_destructor, |
727 | .send_reset = tcp_v6_send_reset, | 765 | .send_reset = tcp_v6_send_reset, |
728 | .syn_ack_timeout = tcp_syn_ack_timeout, | 766 | .syn_ack_timeout = tcp_syn_ack_timeout, |
729 | }; | 767 | }; |
730 | 768 | ||
731 | #ifdef CONFIG_TCP_MD5SIG | ||
732 | static const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { | 769 | static const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { |
770 | .mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - | ||
771 | sizeof(struct ipv6hdr), | ||
772 | #ifdef CONFIG_TCP_MD5SIG | ||
733 | .md5_lookup = tcp_v6_reqsk_md5_lookup, | 773 | .md5_lookup = tcp_v6_reqsk_md5_lookup, |
734 | .calc_md5_hash = tcp_v6_md5_hash_skb, | 774 | .calc_md5_hash = tcp_v6_md5_hash_skb, |
735 | }; | ||
736 | #endif | 775 | #endif |
776 | .init_req = tcp_v6_init_req, | ||
777 | #ifdef CONFIG_SYN_COOKIES | ||
778 | .cookie_init_seq = cookie_v6_init_sequence, | ||
779 | #endif | ||
780 | .route_req = tcp_v6_route_req, | ||
781 | .init_seq = tcp_v6_init_sequence, | ||
782 | .send_synack = tcp_v6_send_synack, | ||
783 | .queue_hash_add = inet6_csk_reqsk_queue_hash_add, | ||
784 | }; | ||
737 | 785 | ||
738 | static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, | 786 | static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, |
739 | u32 tsval, u32 tsecr, int oif, | 787 | u32 tsval, u32 tsecr, int oif, |
@@ -973,153 +1021,17 @@ static struct sock *tcp_v6_hnd_req(struct sock *sk, struct sk_buff *skb) | |||
973 | return sk; | 1021 | return sk; |
974 | } | 1022 | } |
975 | 1023 | ||
976 | /* FIXME: this is substantially similar to the ipv4 code. | ||
977 | * Can some kind of merge be done? -- erics | ||
978 | */ | ||
979 | static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) | 1024 | static int tcp_v6_conn_request(struct sock *sk, struct sk_buff *skb) |
980 | { | 1025 | { |
981 | struct tcp_options_received tmp_opt; | ||
982 | struct request_sock *req; | ||
983 | struct inet_request_sock *ireq; | ||
984 | struct ipv6_pinfo *np = inet6_sk(sk); | ||
985 | struct tcp_sock *tp = tcp_sk(sk); | ||
986 | __u32 isn = TCP_SKB_CB(skb)->when; | ||
987 | struct dst_entry *dst = NULL; | ||
988 | struct tcp_fastopen_cookie foc = { .len = -1 }; | ||
989 | bool want_cookie = false, fastopen; | ||
990 | struct flowi6 fl6; | ||
991 | int err; | ||
992 | |||
993 | if (skb->protocol == htons(ETH_P_IP)) | 1026 | if (skb->protocol == htons(ETH_P_IP)) |
994 | return tcp_v4_conn_request(sk, skb); | 1027 | return tcp_v4_conn_request(sk, skb); |
995 | 1028 | ||
996 | if (!ipv6_unicast_destination(skb)) | 1029 | if (!ipv6_unicast_destination(skb)) |
997 | goto drop; | 1030 | goto drop; |
998 | 1031 | ||
999 | if ((sysctl_tcp_syncookies == 2 || | 1032 | return tcp_conn_request(&tcp6_request_sock_ops, |
1000 | inet_csk_reqsk_queue_is_full(sk)) && !isn) { | 1033 | &tcp_request_sock_ipv6_ops, sk, skb); |
1001 | want_cookie = tcp_syn_flood_action(sk, skb, "TCPv6"); | ||
1002 | if (!want_cookie) | ||
1003 | goto drop; | ||
1004 | } | ||
1005 | |||
1006 | if (sk_acceptq_is_full(sk) && inet_csk_reqsk_queue_young(sk) > 1) { | ||
1007 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENOVERFLOWS); | ||
1008 | goto drop; | ||
1009 | } | ||
1010 | |||
1011 | req = inet6_reqsk_alloc(&tcp6_request_sock_ops); | ||
1012 | if (req == NULL) | ||
1013 | goto drop; | ||
1014 | |||
1015 | #ifdef CONFIG_TCP_MD5SIG | ||
1016 | tcp_rsk(req)->af_specific = &tcp_request_sock_ipv6_ops; | ||
1017 | #endif | ||
1018 | |||
1019 | tcp_clear_options(&tmp_opt); | ||
1020 | tmp_opt.mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr); | ||
1021 | tmp_opt.user_mss = tp->rx_opt.user_mss; | ||
1022 | tcp_parse_options(skb, &tmp_opt, 0, want_cookie ? NULL : &foc); | ||
1023 | |||
1024 | if (want_cookie && !tmp_opt.saw_tstamp) | ||
1025 | tcp_clear_options(&tmp_opt); | ||
1026 | |||
1027 | tmp_opt.tstamp_ok = tmp_opt.saw_tstamp; | ||
1028 | tcp_openreq_init(req, &tmp_opt, skb); | ||
1029 | |||
1030 | ireq = inet_rsk(req); | ||
1031 | ireq->ir_v6_rmt_addr = ipv6_hdr(skb)->saddr; | ||
1032 | ireq->ir_v6_loc_addr = ipv6_hdr(skb)->daddr; | ||
1033 | if (!want_cookie || tmp_opt.tstamp_ok) | ||
1034 | TCP_ECN_create_request(req, skb, sock_net(sk)); | ||
1035 | |||
1036 | ireq->ir_iif = sk->sk_bound_dev_if; | ||
1037 | ireq->ir_mark = inet_request_mark(sk, skb); | ||
1038 | |||
1039 | /* So that link locals have meaning */ | ||
1040 | if (!sk->sk_bound_dev_if && | ||
1041 | ipv6_addr_type(&ireq->ir_v6_rmt_addr) & IPV6_ADDR_LINKLOCAL) | ||
1042 | ireq->ir_iif = inet6_iif(skb); | ||
1043 | |||
1044 | if (!isn) { | ||
1045 | if (ipv6_opt_accepted(sk, skb) || | ||
1046 | np->rxopt.bits.rxinfo || np->rxopt.bits.rxoinfo || | ||
1047 | np->rxopt.bits.rxhlim || np->rxopt.bits.rxohlim || | ||
1048 | np->repflow) { | ||
1049 | atomic_inc(&skb->users); | ||
1050 | ireq->pktopts = skb; | ||
1051 | } | ||
1052 | 1034 | ||
1053 | if (want_cookie) { | ||
1054 | isn = cookie_v6_init_sequence(sk, skb, &req->mss); | ||
1055 | req->cookie_ts = tmp_opt.tstamp_ok; | ||
1056 | goto have_isn; | ||
1057 | } | ||
1058 | |||
1059 | /* VJ's idea. We save last timestamp seen | ||
1060 | * from the destination in peer table, when entering | ||
1061 | * state TIME-WAIT, and check against it before | ||
1062 | * accepting new connection request. | ||
1063 | * | ||
1064 | * If "isn" is not zero, this request hit alive | ||
1065 | * timewait bucket, so that all the necessary checks | ||
1066 | * are made in the function processing timewait state. | ||
1067 | */ | ||
1068 | if (tmp_opt.saw_tstamp && | ||
1069 | tcp_death_row.sysctl_tw_recycle && | ||
1070 | (dst = inet6_csk_route_req(sk, &fl6, req)) != NULL) { | ||
1071 | if (!tcp_peer_is_proven(req, dst, true)) { | ||
1072 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED); | ||
1073 | goto drop_and_release; | ||
1074 | } | ||
1075 | } | ||
1076 | /* Kill the following clause, if you dislike this way. */ | ||
1077 | else if (!sysctl_tcp_syncookies && | ||
1078 | (sysctl_max_syn_backlog - inet_csk_reqsk_queue_len(sk) < | ||
1079 | (sysctl_max_syn_backlog >> 2)) && | ||
1080 | !tcp_peer_is_proven(req, dst, false)) { | ||
1081 | /* Without syncookies last quarter of | ||
1082 | * backlog is filled with destinations, | ||
1083 | * proven to be alive. | ||
1084 | * It means that we continue to communicate | ||
1085 | * to destinations, already remembered | ||
1086 | * to the moment of synflood. | ||
1087 | */ | ||
1088 | LIMIT_NETDEBUG(KERN_DEBUG "TCP: drop open request from %pI6/%u\n", | ||
1089 | &ireq->ir_v6_rmt_addr, ntohs(tcp_hdr(skb)->source)); | ||
1090 | goto drop_and_release; | ||
1091 | } | ||
1092 | |||
1093 | isn = tcp_v6_init_sequence(skb); | ||
1094 | } | ||
1095 | have_isn: | ||
1096 | |||
1097 | if (security_inet_conn_request(sk, skb, req)) | ||
1098 | goto drop_and_release; | ||
1099 | |||
1100 | if (!dst && (dst = inet6_csk_route_req(sk, &fl6, req)) == NULL) | ||
1101 | goto drop_and_free; | ||
1102 | |||
1103 | tcp_rsk(req)->snt_isn = isn; | ||
1104 | tcp_rsk(req)->snt_synack = tcp_time_stamp; | ||
1105 | tcp_openreq_init_rwin(req, sk, dst); | ||
1106 | fastopen = !want_cookie && | ||
1107 | tcp_try_fastopen(sk, skb, req, &foc, dst); | ||
1108 | err = tcp_v6_send_synack(sk, dst, &fl6, req, | ||
1109 | skb_get_queue_mapping(skb), &foc); | ||
1110 | if (!fastopen) { | ||
1111 | if (err || want_cookie) | ||
1112 | goto drop_and_free; | ||
1113 | |||
1114 | tcp_rsk(req)->listener = NULL; | ||
1115 | inet6_csk_reqsk_queue_hash_add(sk, req, TCP_TIMEOUT_INIT); | ||
1116 | } | ||
1117 | return 0; | ||
1118 | |||
1119 | drop_and_release: | ||
1120 | dst_release(dst); | ||
1121 | drop_and_free: | ||
1122 | reqsk_free(req); | ||
1123 | drop: | 1035 | drop: |
1124 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); | 1036 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_LISTENDROPS); |
1125 | return 0; /* don't send reset */ | 1037 | return 0; /* don't send reset */ |
@@ -1235,6 +1147,8 @@ static struct sock *tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
1235 | newsk->sk_v6_rcv_saddr = ireq->ir_v6_loc_addr; | 1147 | newsk->sk_v6_rcv_saddr = ireq->ir_v6_loc_addr; |
1236 | newsk->sk_bound_dev_if = ireq->ir_iif; | 1148 | newsk->sk_bound_dev_if = ireq->ir_iif; |
1237 | 1149 | ||
1150 | ip6_set_txhash(newsk); | ||
1151 | |||
1238 | /* Now IPv6 options... | 1152 | /* Now IPv6 options... |
1239 | 1153 | ||
1240 | First: no IPv4 options. | 1154 | First: no IPv4 options. |
@@ -1346,11 +1260,6 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
1346 | if (skb->protocol == htons(ETH_P_IP)) | 1260 | if (skb->protocol == htons(ETH_P_IP)) |
1347 | return tcp_v4_do_rcv(sk, skb); | 1261 | return tcp_v4_do_rcv(sk, skb); |
1348 | 1262 | ||
1349 | #ifdef CONFIG_TCP_MD5SIG | ||
1350 | if (tcp_v6_inbound_md5_hash(sk, skb)) | ||
1351 | goto discard; | ||
1352 | #endif | ||
1353 | |||
1354 | if (sk_filter(sk, skb)) | 1263 | if (sk_filter(sk, skb)) |
1355 | goto discard; | 1264 | goto discard; |
1356 | 1265 | ||
@@ -1523,6 +1432,11 @@ process: | |||
1523 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) | 1432 | if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb)) |
1524 | goto discard_and_relse; | 1433 | goto discard_and_relse; |
1525 | 1434 | ||
1435 | #ifdef CONFIG_TCP_MD5SIG | ||
1436 | if (tcp_v6_inbound_md5_hash(sk, skb)) | ||
1437 | goto discard_and_relse; | ||
1438 | #endif | ||
1439 | |||
1526 | if (sk_filter(sk, skb)) | 1440 | if (sk_filter(sk, skb)) |
1527 | goto discard_and_relse; | 1441 | goto discard_and_relse; |
1528 | 1442 | ||
@@ -1681,6 +1595,7 @@ static const struct inet_connection_sock_af_ops ipv6_specific = { | |||
1681 | .compat_setsockopt = compat_ipv6_setsockopt, | 1595 | .compat_setsockopt = compat_ipv6_setsockopt, |
1682 | .compat_getsockopt = compat_ipv6_getsockopt, | 1596 | .compat_getsockopt = compat_ipv6_getsockopt, |
1683 | #endif | 1597 | #endif |
1598 | .mtu_reduced = tcp_v6_mtu_reduced, | ||
1684 | }; | 1599 | }; |
1685 | 1600 | ||
1686 | #ifdef CONFIG_TCP_MD5SIG | 1601 | #ifdef CONFIG_TCP_MD5SIG |
@@ -1711,6 +1626,7 @@ static const struct inet_connection_sock_af_ops ipv6_mapped = { | |||
1711 | .compat_setsockopt = compat_ipv6_setsockopt, | 1626 | .compat_setsockopt = compat_ipv6_setsockopt, |
1712 | .compat_getsockopt = compat_ipv6_getsockopt, | 1627 | .compat_getsockopt = compat_ipv6_getsockopt, |
1713 | #endif | 1628 | #endif |
1629 | .mtu_reduced = tcp_v4_mtu_reduced, | ||
1714 | }; | 1630 | }; |
1715 | 1631 | ||
1716 | #ifdef CONFIG_TCP_MD5SIG | 1632 | #ifdef CONFIG_TCP_MD5SIG |
@@ -1950,7 +1866,6 @@ struct proto tcpv6_prot = { | |||
1950 | .sendpage = tcp_sendpage, | 1866 | .sendpage = tcp_sendpage, |
1951 | .backlog_rcv = tcp_v6_do_rcv, | 1867 | .backlog_rcv = tcp_v6_do_rcv, |
1952 | .release_cb = tcp_release_cb, | 1868 | .release_cb = tcp_release_cb, |
1953 | .mtu_reduced = tcp_v6_mtu_reduced, | ||
1954 | .hash = tcp_v6_hash, | 1869 | .hash = tcp_v6_hash, |
1955 | .unhash = inet_unhash, | 1870 | .unhash = inet_unhash, |
1956 | .get_port = inet_csk_get_port, | 1871 | .get_port = inet_csk_get_port, |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 7092ff78fd84..4836af8f582d 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -79,7 +79,6 @@ static unsigned int udp6_ehashfn(struct net *net, | |||
79 | int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) | 79 | int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) |
80 | { | 80 | { |
81 | const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2); | 81 | const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2); |
82 | int sk_ipv6only = ipv6_only_sock(sk); | ||
83 | int sk2_ipv6only = inet_v6_ipv6only(sk2); | 82 | int sk2_ipv6only = inet_v6_ipv6only(sk2); |
84 | int addr_type = ipv6_addr_type(&sk->sk_v6_rcv_saddr); | 83 | int addr_type = ipv6_addr_type(&sk->sk_v6_rcv_saddr); |
85 | int addr_type2 = sk2_rcv_saddr6 ? ipv6_addr_type(sk2_rcv_saddr6) : IPV6_ADDR_MAPPED; | 84 | int addr_type2 = sk2_rcv_saddr6 ? ipv6_addr_type(sk2_rcv_saddr6) : IPV6_ADDR_MAPPED; |
@@ -95,7 +94,7 @@ int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) | |||
95 | return 1; | 94 | return 1; |
96 | 95 | ||
97 | if (addr_type == IPV6_ADDR_ANY && | 96 | if (addr_type == IPV6_ADDR_ANY && |
98 | !(sk_ipv6only && addr_type2 == IPV6_ADDR_MAPPED)) | 97 | !(ipv6_only_sock(sk) && addr_type2 == IPV6_ADDR_MAPPED)) |
99 | return 1; | 98 | return 1; |
100 | 99 | ||
101 | if (sk2_rcv_saddr6 && | 100 | if (sk2_rcv_saddr6 && |
@@ -473,7 +472,7 @@ try_again: | |||
473 | sin6->sin6_addr = ipv6_hdr(skb)->saddr; | 472 | sin6->sin6_addr = ipv6_hdr(skb)->saddr; |
474 | sin6->sin6_scope_id = | 473 | sin6->sin6_scope_id = |
475 | ipv6_iface_scope_id(&sin6->sin6_addr, | 474 | ipv6_iface_scope_id(&sin6->sin6_addr, |
476 | IP6CB(skb)->iif); | 475 | inet6_iif(skb)); |
477 | } | 476 | } |
478 | *addr_len = sizeof(*sin6); | 477 | *addr_len = sizeof(*sin6); |
479 | } | 478 | } |
@@ -534,11 +533,15 @@ void __udp6_lib_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
534 | struct udphdr *uh = (struct udphdr*)(skb->data+offset); | 533 | struct udphdr *uh = (struct udphdr*)(skb->data+offset); |
535 | struct sock *sk; | 534 | struct sock *sk; |
536 | int err; | 535 | int err; |
536 | struct net *net = dev_net(skb->dev); | ||
537 | 537 | ||
538 | sk = __udp6_lib_lookup(dev_net(skb->dev), daddr, uh->dest, | 538 | sk = __udp6_lib_lookup(net, daddr, uh->dest, |
539 | saddr, uh->source, inet6_iif(skb), udptable); | 539 | saddr, uh->source, inet6_iif(skb), udptable); |
540 | if (sk == NULL) | 540 | if (sk == NULL) { |
541 | ICMP6_INC_STATS_BH(net, __in6_dev_get(skb->dev), | ||
542 | ICMP6_MIB_INERRORS); | ||
541 | return; | 543 | return; |
544 | } | ||
542 | 545 | ||
543 | if (type == ICMPV6_PKT_TOOBIG) { | 546 | if (type == ICMPV6_PKT_TOOBIG) { |
544 | if (!ip6_sk_accept_pmtu(sk)) | 547 | if (!ip6_sk_accept_pmtu(sk)) |
@@ -674,7 +677,7 @@ int udpv6_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
674 | goto csum_error; | 677 | goto csum_error; |
675 | } | 678 | } |
676 | 679 | ||
677 | if (sk_rcvqueues_full(sk, skb, sk->sk_rcvbuf)) { | 680 | if (sk_rcvqueues_full(sk, sk->sk_rcvbuf)) { |
678 | UDP6_INC_STATS_BH(sock_net(sk), | 681 | UDP6_INC_STATS_BH(sock_net(sk), |
679 | UDP_MIB_RCVBUFERRORS, is_udplite); | 682 | UDP_MIB_RCVBUFERRORS, is_udplite); |
680 | goto drop; | 683 | goto drop; |
@@ -703,43 +706,26 @@ drop: | |||
703 | return -1; | 706 | return -1; |
704 | } | 707 | } |
705 | 708 | ||
706 | static struct sock *udp_v6_mcast_next(struct net *net, struct sock *sk, | 709 | static bool __udp_v6_is_mcast_sock(struct net *net, struct sock *sk, |
707 | __be16 loc_port, const struct in6_addr *loc_addr, | 710 | __be16 loc_port, const struct in6_addr *loc_addr, |
708 | __be16 rmt_port, const struct in6_addr *rmt_addr, | 711 | __be16 rmt_port, const struct in6_addr *rmt_addr, |
709 | int dif) | 712 | int dif, unsigned short hnum) |
710 | { | 713 | { |
711 | struct hlist_nulls_node *node; | 714 | struct inet_sock *inet = inet_sk(sk); |
712 | unsigned short num = ntohs(loc_port); | ||
713 | |||
714 | sk_nulls_for_each_from(sk, node) { | ||
715 | struct inet_sock *inet = inet_sk(sk); | ||
716 | |||
717 | if (!net_eq(sock_net(sk), net)) | ||
718 | continue; | ||
719 | |||
720 | if (udp_sk(sk)->udp_port_hash == num && | ||
721 | sk->sk_family == PF_INET6) { | ||
722 | if (inet->inet_dport) { | ||
723 | if (inet->inet_dport != rmt_port) | ||
724 | continue; | ||
725 | } | ||
726 | if (!ipv6_addr_any(&sk->sk_v6_daddr) && | ||
727 | !ipv6_addr_equal(&sk->sk_v6_daddr, rmt_addr)) | ||
728 | continue; | ||
729 | |||
730 | if (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif) | ||
731 | continue; | ||
732 | 715 | ||
733 | if (!ipv6_addr_any(&sk->sk_v6_rcv_saddr)) { | 716 | if (!net_eq(sock_net(sk), net)) |
734 | if (!ipv6_addr_equal(&sk->sk_v6_rcv_saddr, loc_addr)) | 717 | return false; |
735 | continue; | 718 | |
736 | } | 719 | if (udp_sk(sk)->udp_port_hash != hnum || |
737 | if (!inet6_mc_check(sk, loc_addr, rmt_addr)) | 720 | sk->sk_family != PF_INET6 || |
738 | continue; | 721 | (inet->inet_dport && inet->inet_dport != rmt_port) || |
739 | return sk; | 722 | (!ipv6_addr_any(&sk->sk_v6_daddr) && |
740 | } | 723 | !ipv6_addr_equal(&sk->sk_v6_daddr, rmt_addr)) || |
741 | } | 724 | (sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif)) |
742 | return NULL; | 725 | return false; |
726 | if (!inet6_mc_check(sk, loc_addr, rmt_addr)) | ||
727 | return false; | ||
728 | return true; | ||
743 | } | 729 | } |
744 | 730 | ||
745 | static void flush_stack(struct sock **stack, unsigned int count, | 731 | static void flush_stack(struct sock **stack, unsigned int count, |
@@ -763,6 +749,7 @@ static void flush_stack(struct sock **stack, unsigned int count, | |||
763 | 749 | ||
764 | if (skb1 && udpv6_queue_rcv_skb(sk, skb1) <= 0) | 750 | if (skb1 && udpv6_queue_rcv_skb(sk, skb1) <= 0) |
765 | skb1 = NULL; | 751 | skb1 = NULL; |
752 | sock_put(sk); | ||
766 | } | 753 | } |
767 | if (unlikely(skb1)) | 754 | if (unlikely(skb1)) |
768 | kfree_skb(skb1); | 755 | kfree_skb(skb1); |
@@ -788,43 +775,51 @@ static int __udp6_lib_mcast_deliver(struct net *net, struct sk_buff *skb, | |||
788 | { | 775 | { |
789 | struct sock *sk, *stack[256 / sizeof(struct sock *)]; | 776 | struct sock *sk, *stack[256 / sizeof(struct sock *)]; |
790 | const struct udphdr *uh = udp_hdr(skb); | 777 | const struct udphdr *uh = udp_hdr(skb); |
791 | struct udp_hslot *hslot = udp_hashslot(udptable, net, ntohs(uh->dest)); | 778 | struct hlist_nulls_node *node; |
792 | int dif; | 779 | unsigned short hnum = ntohs(uh->dest); |
793 | unsigned int i, count = 0; | 780 | struct udp_hslot *hslot = udp_hashslot(udptable, net, hnum); |
781 | int dif = inet6_iif(skb); | ||
782 | unsigned int count = 0, offset = offsetof(typeof(*sk), sk_nulls_node); | ||
783 | unsigned int hash2 = 0, hash2_any = 0, use_hash2 = (hslot->count > 10); | ||
784 | |||
785 | if (use_hash2) { | ||
786 | hash2_any = udp6_portaddr_hash(net, &in6addr_any, hnum) & | ||
787 | udp_table.mask; | ||
788 | hash2 = udp6_portaddr_hash(net, daddr, hnum) & udp_table.mask; | ||
789 | start_lookup: | ||
790 | hslot = &udp_table.hash2[hash2]; | ||
791 | offset = offsetof(typeof(*sk), __sk_common.skc_portaddr_node); | ||
792 | } | ||
794 | 793 | ||
795 | spin_lock(&hslot->lock); | 794 | spin_lock(&hslot->lock); |
796 | sk = sk_nulls_head(&hslot->head); | 795 | sk_nulls_for_each_entry_offset(sk, node, &hslot->head, offset) { |
797 | dif = inet6_iif(skb); | 796 | if (__udp_v6_is_mcast_sock(net, sk, |
798 | sk = udp_v6_mcast_next(net, sk, uh->dest, daddr, uh->source, saddr, dif); | 797 | uh->dest, daddr, |
799 | while (sk) { | 798 | uh->source, saddr, |
800 | /* If zero checksum and no_check is not on for | 799 | dif, hnum) && |
801 | * the socket then skip it. | 800 | /* If zero checksum and no_check is not on for |
802 | */ | 801 | * the socket then skip it. |
803 | if (uh->check || udp_sk(sk)->no_check6_rx) | 802 | */ |
803 | (uh->check || udp_sk(sk)->no_check6_rx)) { | ||
804 | if (unlikely(count == ARRAY_SIZE(stack))) { | ||
805 | flush_stack(stack, count, skb, ~0); | ||
806 | count = 0; | ||
807 | } | ||
804 | stack[count++] = sk; | 808 | stack[count++] = sk; |
805 | 809 | sock_hold(sk); | |
806 | sk = udp_v6_mcast_next(net, sk_nulls_next(sk), uh->dest, daddr, | ||
807 | uh->source, saddr, dif); | ||
808 | if (unlikely(count == ARRAY_SIZE(stack))) { | ||
809 | if (!sk) | ||
810 | break; | ||
811 | flush_stack(stack, count, skb, ~0); | ||
812 | count = 0; | ||
813 | } | 810 | } |
814 | } | 811 | } |
815 | /* | ||
816 | * before releasing the lock, we must take reference on sockets | ||
817 | */ | ||
818 | for (i = 0; i < count; i++) | ||
819 | sock_hold(stack[i]); | ||
820 | 812 | ||
821 | spin_unlock(&hslot->lock); | 813 | spin_unlock(&hslot->lock); |
822 | 814 | ||
815 | /* Also lookup *:port if we are using hash2 and haven't done so yet. */ | ||
816 | if (use_hash2 && hash2 != hash2_any) { | ||
817 | hash2 = hash2_any; | ||
818 | goto start_lookup; | ||
819 | } | ||
820 | |||
823 | if (count) { | 821 | if (count) { |
824 | flush_stack(stack, count, skb, count - 1); | 822 | flush_stack(stack, count, skb, count - 1); |
825 | |||
826 | for (i = 0; i < count; i++) | ||
827 | sock_put(stack[i]); | ||
828 | } else { | 823 | } else { |
829 | kfree_skb(skb); | 824 | kfree_skb(skb); |
830 | } | 825 | } |
diff --git a/net/irda/af_irda.c b/net/irda/af_irda.c index 54747c25c86c..92fafd485deb 100644 --- a/net/irda/af_irda.c +++ b/net/irda/af_irda.c | |||
@@ -674,7 +674,6 @@ static int irda_discover_daddr_and_lsap_sel(struct irda_sock *self, char *name) | |||
674 | self->daddr = DEV_ADDR_ANY; | 674 | self->daddr = DEV_ADDR_ANY; |
675 | kfree(discoveries); | 675 | kfree(discoveries); |
676 | return -EHOSTUNREACH; | 676 | return -EHOSTUNREACH; |
677 | break; | ||
678 | } | 677 | } |
679 | } | 678 | } |
680 | /* Cleanup our copy of the discovery log */ | 679 | /* Cleanup our copy of the discovery log */ |
diff --git a/net/irda/ircomm/ircomm_tty.c b/net/irda/ircomm/ircomm_tty.c index 2ba8b9705bb7..61ceb4cdb4a2 100644 --- a/net/irda/ircomm/ircomm_tty.c +++ b/net/irda/ircomm/ircomm_tty.c | |||
@@ -320,8 +320,7 @@ static int ircomm_tty_block_til_ready(struct ircomm_tty_cb *self, | |||
320 | __FILE__, __LINE__, tty->driver->name, port->count); | 320 | __FILE__, __LINE__, tty->driver->name, port->count); |
321 | 321 | ||
322 | spin_lock_irqsave(&port->lock, flags); | 322 | spin_lock_irqsave(&port->lock, flags); |
323 | if (!tty_hung_up_p(filp)) | 323 | port->count--; |
324 | port->count--; | ||
325 | port->blocked_open++; | 324 | port->blocked_open++; |
326 | spin_unlock_irqrestore(&port->lock, flags); | 325 | spin_unlock_irqrestore(&port->lock, flags); |
327 | 326 | ||
@@ -458,8 +457,7 @@ static int ircomm_tty_open(struct tty_struct *tty, struct file *filp) | |||
458 | /* | 457 | /* |
459 | * If the port is the middle of closing, bail out now | 458 | * If the port is the middle of closing, bail out now |
460 | */ | 459 | */ |
461 | if (tty_hung_up_p(filp) || | 460 | if (test_bit(ASYNCB_CLOSING, &self->port.flags)) { |
462 | test_bit(ASYNCB_CLOSING, &self->port.flags)) { | ||
463 | 461 | ||
464 | /* Hm, why are we blocking on ASYNC_CLOSING if we | 462 | /* Hm, why are we blocking on ASYNC_CLOSING if we |
465 | * do return -EAGAIN/-ERESTARTSYS below anyway? | 463 | * do return -EAGAIN/-ERESTARTSYS below anyway? |
diff --git a/net/irda/irda_device.c b/net/irda/irda_device.c index 365b895da84b..9e0d909390fd 100644 --- a/net/irda/irda_device.c +++ b/net/irda/irda_device.c | |||
@@ -293,7 +293,8 @@ static void irda_device_setup(struct net_device *dev) | |||
293 | */ | 293 | */ |
294 | struct net_device *alloc_irdadev(int sizeof_priv) | 294 | struct net_device *alloc_irdadev(int sizeof_priv) |
295 | { | 295 | { |
296 | return alloc_netdev(sizeof_priv, "irda%d", irda_device_setup); | 296 | return alloc_netdev(sizeof_priv, "irda%d", NET_NAME_UNKNOWN, |
297 | irda_device_setup); | ||
297 | } | 298 | } |
298 | EXPORT_SYMBOL(alloc_irdadev); | 299 | EXPORT_SYMBOL(alloc_irdadev); |
299 | 300 | ||
diff --git a/net/irda/irlan/irlan_common.c b/net/irda/irlan/irlan_common.c index 7ac4d1becbfc..1bc49edf2296 100644 --- a/net/irda/irlan/irlan_common.c +++ b/net/irda/irlan/irlan_common.c | |||
@@ -1024,7 +1024,6 @@ static int __irlan_insert_param(struct sk_buff *skb, char *param, int type, | |||
1024 | default: | 1024 | default: |
1025 | IRDA_DEBUG(2, "%s(), Unknown parameter type!\n", __func__ ); | 1025 | IRDA_DEBUG(2, "%s(), Unknown parameter type!\n", __func__ ); |
1026 | return 0; | 1026 | return 0; |
1027 | break; | ||
1028 | } | 1027 | } |
1029 | 1028 | ||
1030 | /* Insert at end of sk-buffer */ | 1029 | /* Insert at end of sk-buffer */ |
diff --git a/net/irda/irlan/irlan_eth.c b/net/irda/irlan/irlan_eth.c index ffcec225b5d9..dc13f1a45f2f 100644 --- a/net/irda/irlan/irlan_eth.c +++ b/net/irda/irlan/irlan_eth.c | |||
@@ -96,7 +96,7 @@ static void irlan_eth_setup(struct net_device *dev) | |||
96 | */ | 96 | */ |
97 | struct net_device *alloc_irlandev(const char *name) | 97 | struct net_device *alloc_irlandev(const char *name) |
98 | { | 98 | { |
99 | return alloc_netdev(sizeof(struct irlan_cb), name, | 99 | return alloc_netdev(sizeof(struct irlan_cb), name, NET_NAME_UNKNOWN, |
100 | irlan_eth_setup); | 100 | irlan_eth_setup); |
101 | } | 101 | } |
102 | 102 | ||
diff --git a/net/irda/irlap_frame.c b/net/irda/irlap_frame.c index 9ea0c933b9ff..a37998c6273d 100644 --- a/net/irda/irlap_frame.c +++ b/net/irda/irlap_frame.c | |||
@@ -622,7 +622,7 @@ void irlap_send_rd_frame(struct irlap_cb *self) | |||
622 | frame = (struct rd_frame *)skb_put(tx_skb, 2); | 622 | frame = (struct rd_frame *)skb_put(tx_skb, 2); |
623 | 623 | ||
624 | frame->caddr = self->caddr; | 624 | frame->caddr = self->caddr; |
625 | frame->caddr = RD_RSP | PF_BIT; | 625 | frame->control = RD_RSP | PF_BIT; |
626 | 626 | ||
627 | irlap_queue_xmit(self, tx_skb); | 627 | irlap_queue_xmit(self, tx_skb); |
628 | } | 628 | } |
diff --git a/net/irda/irlmp.c b/net/irda/irlmp.c index 98ad6ec4bd3c..a5f28d421ea8 100644 --- a/net/irda/irlmp.c +++ b/net/irda/irlmp.c | |||
@@ -1426,7 +1426,8 @@ __u8 *irlmp_hint_to_service(__u8 *hint) | |||
1426 | if (hint[1] & HINT_TELEPHONY) { | 1426 | if (hint[1] & HINT_TELEPHONY) { |
1427 | IRDA_DEBUG(1, "Telephony "); | 1427 | IRDA_DEBUG(1, "Telephony "); |
1428 | service[i++] = S_TELEPHONY; | 1428 | service[i++] = S_TELEPHONY; |
1429 | } if (hint[1] & HINT_FILE_SERVER) | 1429 | } |
1430 | if (hint[1] & HINT_FILE_SERVER) | ||
1430 | IRDA_DEBUG(1, "File Server "); | 1431 | IRDA_DEBUG(1, "File Server "); |
1431 | 1432 | ||
1432 | if (hint[1] & HINT_COMM) { | 1433 | if (hint[1] & HINT_COMM) { |
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index 7a95fa4a3de1..a089b6b91650 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c | |||
@@ -1103,7 +1103,6 @@ static int iucv_sock_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
1103 | default: | 1103 | default: |
1104 | err = -EINVAL; | 1104 | err = -EINVAL; |
1105 | goto out; | 1105 | goto out; |
1106 | break; | ||
1107 | } | 1106 | } |
1108 | } | 1107 | } |
1109 | 1108 | ||
@@ -1543,7 +1542,8 @@ static int iucv_sock_shutdown(struct socket *sock, int how) | |||
1543 | 1542 | ||
1544 | sk->sk_shutdown |= how; | 1543 | sk->sk_shutdown |= how; |
1545 | if (how == RCV_SHUTDOWN || how == SHUTDOWN_MASK) { | 1544 | if (how == RCV_SHUTDOWN || how == SHUTDOWN_MASK) { |
1546 | if (iucv->transport == AF_IUCV_TRANS_IUCV) { | 1545 | if ((iucv->transport == AF_IUCV_TRANS_IUCV) && |
1546 | iucv->path) { | ||
1547 | err = pr_iucv->path_quiesce(iucv->path, NULL); | 1547 | err = pr_iucv->path_quiesce(iucv->path, NULL); |
1548 | if (err) | 1548 | if (err) |
1549 | err = -ENOTCONN; | 1549 | err = -ENOTCONN; |
diff --git a/net/key/af_key.c b/net/key/af_key.c index ba2a2f95911c..1847ec4e3930 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
@@ -405,7 +405,6 @@ static int verify_address_len(const void *p) | |||
405 | * XXX When it can, remove this -EINVAL. -DaveM | 405 | * XXX When it can, remove this -EINVAL. -DaveM |
406 | */ | 406 | */ |
407 | return -EINVAL; | 407 | return -EINVAL; |
408 | break; | ||
409 | } | 408 | } |
410 | 409 | ||
411 | return 0; | 410 | return 0; |
@@ -536,7 +535,6 @@ pfkey_satype2proto(uint8_t satype) | |||
536 | return IPPROTO_ESP; | 535 | return IPPROTO_ESP; |
537 | case SADB_X_SATYPE_IPCOMP: | 536 | case SADB_X_SATYPE_IPCOMP: |
538 | return IPPROTO_COMP; | 537 | return IPPROTO_COMP; |
539 | break; | ||
540 | default: | 538 | default: |
541 | return 0; | 539 | return 0; |
542 | } | 540 | } |
@@ -553,7 +551,6 @@ pfkey_proto2satype(uint16_t proto) | |||
553 | return SADB_SATYPE_ESP; | 551 | return SADB_SATYPE_ESP; |
554 | case IPPROTO_COMP: | 552 | case IPPROTO_COMP: |
555 | return SADB_X_SATYPE_IPCOMP; | 553 | return SADB_X_SATYPE_IPCOMP; |
556 | break; | ||
557 | default: | 554 | default: |
558 | return 0; | 555 | return 0; |
559 | } | 556 | } |
diff --git a/net/l2tp/Kconfig b/net/l2tp/Kconfig index adb9843dd7cf..378c73b26093 100644 --- a/net/l2tp/Kconfig +++ b/net/l2tp/Kconfig | |||
@@ -6,6 +6,7 @@ menuconfig L2TP | |||
6 | tristate "Layer Two Tunneling Protocol (L2TP)" | 6 | tristate "Layer Two Tunneling Protocol (L2TP)" |
7 | depends on (IPV6 || IPV6=n) | 7 | depends on (IPV6 || IPV6=n) |
8 | depends on INET | 8 | depends on INET |
9 | select NET_UDP_TUNNEL | ||
9 | ---help--- | 10 | ---help--- |
10 | Layer Two Tunneling Protocol | 11 | Layer Two Tunneling Protocol |
11 | 12 | ||
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index bea259043205..1109d3bb8dac 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c | |||
@@ -52,6 +52,7 @@ | |||
52 | #include <net/dst.h> | 52 | #include <net/dst.h> |
53 | #include <net/ip.h> | 53 | #include <net/ip.h> |
54 | #include <net/udp.h> | 54 | #include <net/udp.h> |
55 | #include <net/udp_tunnel.h> | ||
55 | #include <net/inet_common.h> | 56 | #include <net/inet_common.h> |
56 | #include <net/xfrm.h> | 57 | #include <net/xfrm.h> |
57 | #include <net/protocol.h> | 58 | #include <net/protocol.h> |
@@ -1358,81 +1359,46 @@ static int l2tp_tunnel_sock_create(struct net *net, | |||
1358 | { | 1359 | { |
1359 | int err = -EINVAL; | 1360 | int err = -EINVAL; |
1360 | struct socket *sock = NULL; | 1361 | struct socket *sock = NULL; |
1361 | struct sockaddr_in udp_addr = {0}; | 1362 | struct udp_port_cfg udp_conf; |
1362 | struct sockaddr_l2tpip ip_addr = {0}; | ||
1363 | #if IS_ENABLED(CONFIG_IPV6) | ||
1364 | struct sockaddr_in6 udp6_addr = {0}; | ||
1365 | struct sockaddr_l2tpip6 ip6_addr = {0}; | ||
1366 | #endif | ||
1367 | 1363 | ||
1368 | switch (cfg->encap) { | 1364 | switch (cfg->encap) { |
1369 | case L2TP_ENCAPTYPE_UDP: | 1365 | case L2TP_ENCAPTYPE_UDP: |
1366 | memset(&udp_conf, 0, sizeof(udp_conf)); | ||
1367 | |||
1370 | #if IS_ENABLED(CONFIG_IPV6) | 1368 | #if IS_ENABLED(CONFIG_IPV6) |
1371 | if (cfg->local_ip6 && cfg->peer_ip6) { | 1369 | if (cfg->local_ip6 && cfg->peer_ip6) { |
1372 | err = sock_create_kern(AF_INET6, SOCK_DGRAM, 0, &sock); | 1370 | udp_conf.family = AF_INET6; |
1373 | if (err < 0) | 1371 | memcpy(&udp_conf.local_ip6, cfg->local_ip6, |
1374 | goto out; | 1372 | sizeof(udp_conf.local_ip6)); |
1375 | 1373 | memcpy(&udp_conf.peer_ip6, cfg->peer_ip6, | |
1376 | sk_change_net(sock->sk, net); | 1374 | sizeof(udp_conf.peer_ip6)); |
1377 | 1375 | udp_conf.use_udp6_tx_checksums = | |
1378 | udp6_addr.sin6_family = AF_INET6; | 1376 | cfg->udp6_zero_tx_checksums; |
1379 | memcpy(&udp6_addr.sin6_addr, cfg->local_ip6, | 1377 | udp_conf.use_udp6_rx_checksums = |
1380 | sizeof(udp6_addr.sin6_addr)); | 1378 | cfg->udp6_zero_rx_checksums; |
1381 | udp6_addr.sin6_port = htons(cfg->local_udp_port); | ||
1382 | err = kernel_bind(sock, (struct sockaddr *) &udp6_addr, | ||
1383 | sizeof(udp6_addr)); | ||
1384 | if (err < 0) | ||
1385 | goto out; | ||
1386 | |||
1387 | udp6_addr.sin6_family = AF_INET6; | ||
1388 | memcpy(&udp6_addr.sin6_addr, cfg->peer_ip6, | ||
1389 | sizeof(udp6_addr.sin6_addr)); | ||
1390 | udp6_addr.sin6_port = htons(cfg->peer_udp_port); | ||
1391 | err = kernel_connect(sock, | ||
1392 | (struct sockaddr *) &udp6_addr, | ||
1393 | sizeof(udp6_addr), 0); | ||
1394 | if (err < 0) | ||
1395 | goto out; | ||
1396 | |||
1397 | if (cfg->udp6_zero_tx_checksums) | ||
1398 | udp_set_no_check6_tx(sock->sk, true); | ||
1399 | if (cfg->udp6_zero_rx_checksums) | ||
1400 | udp_set_no_check6_rx(sock->sk, true); | ||
1401 | } else | 1379 | } else |
1402 | #endif | 1380 | #endif |
1403 | { | 1381 | { |
1404 | err = sock_create_kern(AF_INET, SOCK_DGRAM, 0, &sock); | 1382 | udp_conf.family = AF_INET; |
1405 | if (err < 0) | 1383 | udp_conf.local_ip = cfg->local_ip; |
1406 | goto out; | 1384 | udp_conf.peer_ip = cfg->peer_ip; |
1407 | 1385 | udp_conf.use_udp_checksums = cfg->use_udp_checksums; | |
1408 | sk_change_net(sock->sk, net); | ||
1409 | |||
1410 | udp_addr.sin_family = AF_INET; | ||
1411 | udp_addr.sin_addr = cfg->local_ip; | ||
1412 | udp_addr.sin_port = htons(cfg->local_udp_port); | ||
1413 | err = kernel_bind(sock, (struct sockaddr *) &udp_addr, | ||
1414 | sizeof(udp_addr)); | ||
1415 | if (err < 0) | ||
1416 | goto out; | ||
1417 | |||
1418 | udp_addr.sin_family = AF_INET; | ||
1419 | udp_addr.sin_addr = cfg->peer_ip; | ||
1420 | udp_addr.sin_port = htons(cfg->peer_udp_port); | ||
1421 | err = kernel_connect(sock, | ||
1422 | (struct sockaddr *) &udp_addr, | ||
1423 | sizeof(udp_addr), 0); | ||
1424 | if (err < 0) | ||
1425 | goto out; | ||
1426 | } | 1386 | } |
1427 | 1387 | ||
1428 | if (!cfg->use_udp_checksums) | 1388 | udp_conf.local_udp_port = htons(cfg->local_udp_port); |
1429 | sock->sk->sk_no_check_tx = 1; | 1389 | udp_conf.peer_udp_port = htons(cfg->peer_udp_port); |
1390 | |||
1391 | err = udp_sock_create(net, &udp_conf, &sock); | ||
1392 | if (err < 0) | ||
1393 | goto out; | ||
1430 | 1394 | ||
1431 | break; | 1395 | break; |
1432 | 1396 | ||
1433 | case L2TP_ENCAPTYPE_IP: | 1397 | case L2TP_ENCAPTYPE_IP: |
1434 | #if IS_ENABLED(CONFIG_IPV6) | 1398 | #if IS_ENABLED(CONFIG_IPV6) |
1435 | if (cfg->local_ip6 && cfg->peer_ip6) { | 1399 | if (cfg->local_ip6 && cfg->peer_ip6) { |
1400 | struct sockaddr_l2tpip6 ip6_addr = {0}; | ||
1401 | |||
1436 | err = sock_create_kern(AF_INET6, SOCK_DGRAM, | 1402 | err = sock_create_kern(AF_INET6, SOCK_DGRAM, |
1437 | IPPROTO_L2TP, &sock); | 1403 | IPPROTO_L2TP, &sock); |
1438 | if (err < 0) | 1404 | if (err < 0) |
@@ -1461,6 +1427,8 @@ static int l2tp_tunnel_sock_create(struct net *net, | |||
1461 | } else | 1427 | } else |
1462 | #endif | 1428 | #endif |
1463 | { | 1429 | { |
1430 | struct sockaddr_l2tpip ip_addr = {0}; | ||
1431 | |||
1464 | err = sock_create_kern(AF_INET, SOCK_DGRAM, | 1432 | err = sock_create_kern(AF_INET, SOCK_DGRAM, |
1465 | IPPROTO_L2TP, &sock); | 1433 | IPPROTO_L2TP, &sock); |
1466 | if (err < 0) | 1434 | if (err < 0) |
diff --git a/net/l2tp/l2tp_eth.c b/net/l2tp/l2tp_eth.c index 76125c57ee6d..edb78e69efe4 100644 --- a/net/l2tp/l2tp_eth.c +++ b/net/l2tp/l2tp_eth.c | |||
@@ -246,7 +246,8 @@ static int l2tp_eth_create(struct net *net, u32 tunnel_id, u32 session_id, u32 p | |||
246 | goto out; | 246 | goto out; |
247 | } | 247 | } |
248 | 248 | ||
249 | dev = alloc_netdev(sizeof(*priv), name, l2tp_eth_dev_setup); | 249 | dev = alloc_netdev(sizeof(*priv), name, NET_NAME_UNKNOWN, |
250 | l2tp_eth_dev_setup); | ||
250 | if (!dev) { | 251 | if (!dev) { |
251 | rc = -ENOMEM; | 252 | rc = -ENOMEM; |
252 | goto out_del_session; | 253 | goto out_del_session; |
diff --git a/net/l2tp/l2tp_ip6.c b/net/l2tp/l2tp_ip6.c index f3f98a156cee..0edb263cc002 100644 --- a/net/l2tp/l2tp_ip6.c +++ b/net/l2tp/l2tp_ip6.c | |||
@@ -687,7 +687,7 @@ static int l2tp_ip6_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
687 | lsa->l2tp_scope_id = 0; | 687 | lsa->l2tp_scope_id = 0; |
688 | lsa->l2tp_conn_id = 0; | 688 | lsa->l2tp_conn_id = 0; |
689 | if (ipv6_addr_type(&lsa->l2tp_addr) & IPV6_ADDR_LINKLOCAL) | 689 | if (ipv6_addr_type(&lsa->l2tp_addr) & IPV6_ADDR_LINKLOCAL) |
690 | lsa->l2tp_scope_id = IP6CB(skb)->iif; | 690 | lsa->l2tp_scope_id = inet6_iif(skb); |
691 | } | 691 | } |
692 | 692 | ||
693 | if (np->rxopt.all) | 693 | if (np->rxopt.all) |
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index 13752d96275e..b704a9356208 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c | |||
@@ -755,7 +755,8 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, | |||
755 | /* If PMTU discovery was enabled, use the MTU that was discovered */ | 755 | /* If PMTU discovery was enabled, use the MTU that was discovered */ |
756 | dst = sk_dst_get(tunnel->sock); | 756 | dst = sk_dst_get(tunnel->sock); |
757 | if (dst != NULL) { | 757 | if (dst != NULL) { |
758 | u32 pmtu = dst_mtu(__sk_dst_get(tunnel->sock)); | 758 | u32 pmtu = dst_mtu(dst); |
759 | |||
759 | if (pmtu != 0) | 760 | if (pmtu != 0) |
760 | session->mtu = session->mru = pmtu - | 761 | session->mtu = session->mru = pmtu - |
761 | PPPOL2TP_HEADER_OVERHEAD; | 762 | PPPOL2TP_HEADER_OVERHEAD; |
diff --git a/net/mac80211/Kconfig b/net/mac80211/Kconfig index 97b5dcad5025..aeb6a483b3bc 100644 --- a/net/mac80211/Kconfig +++ b/net/mac80211/Kconfig | |||
@@ -19,14 +19,6 @@ if MAC80211 != n | |||
19 | config MAC80211_HAS_RC | 19 | config MAC80211_HAS_RC |
20 | bool | 20 | bool |
21 | 21 | ||
22 | config MAC80211_RC_PID | ||
23 | bool "PID controller based rate control algorithm" if EXPERT | ||
24 | select MAC80211_HAS_RC | ||
25 | ---help--- | ||
26 | This option enables a TX rate control algorithm for | ||
27 | mac80211 that uses a PID controller to select the TX | ||
28 | rate. | ||
29 | |||
30 | config MAC80211_RC_MINSTREL | 22 | config MAC80211_RC_MINSTREL |
31 | bool "Minstrel" if EXPERT | 23 | bool "Minstrel" if EXPERT |
32 | select MAC80211_HAS_RC | 24 | select MAC80211_HAS_RC |
@@ -51,14 +43,6 @@ choice | |||
51 | overridden through the ieee80211_default_rc_algo module | 43 | overridden through the ieee80211_default_rc_algo module |
52 | parameter if different algorithms are available. | 44 | parameter if different algorithms are available. |
53 | 45 | ||
54 | config MAC80211_RC_DEFAULT_PID | ||
55 | bool "PID controller based rate control algorithm" | ||
56 | depends on MAC80211_RC_PID | ||
57 | ---help--- | ||
58 | Select the PID controller based rate control as the | ||
59 | default rate control algorithm. You should choose | ||
60 | this unless you know what you are doing. | ||
61 | |||
62 | config MAC80211_RC_DEFAULT_MINSTREL | 46 | config MAC80211_RC_DEFAULT_MINSTREL |
63 | bool "Minstrel" | 47 | bool "Minstrel" |
64 | depends on MAC80211_RC_MINSTREL | 48 | depends on MAC80211_RC_MINSTREL |
@@ -72,7 +56,6 @@ config MAC80211_RC_DEFAULT | |||
72 | string | 56 | string |
73 | default "minstrel_ht" if MAC80211_RC_DEFAULT_MINSTREL && MAC80211_RC_MINSTREL_HT | 57 | default "minstrel_ht" if MAC80211_RC_DEFAULT_MINSTREL && MAC80211_RC_MINSTREL_HT |
74 | default "minstrel" if MAC80211_RC_DEFAULT_MINSTREL | 58 | default "minstrel" if MAC80211_RC_DEFAULT_MINSTREL |
75 | default "pid" if MAC80211_RC_DEFAULT_PID | ||
76 | default "" | 59 | default "" |
77 | 60 | ||
78 | endif | 61 | endif |
diff --git a/net/mac80211/Makefile b/net/mac80211/Makefile index 1e46ffa69167..7273d2796dd1 100644 --- a/net/mac80211/Makefile +++ b/net/mac80211/Makefile | |||
@@ -17,6 +17,7 @@ mac80211-y := \ | |||
17 | aes_ccm.o \ | 17 | aes_ccm.o \ |
18 | aes_cmac.o \ | 18 | aes_cmac.o \ |
19 | cfg.o \ | 19 | cfg.o \ |
20 | ethtool.o \ | ||
20 | rx.o \ | 21 | rx.o \ |
21 | spectmgmt.o \ | 22 | spectmgmt.o \ |
22 | tx.o \ | 23 | tx.o \ |
@@ -47,17 +48,12 @@ mac80211-$(CONFIG_PM) += pm.o | |||
47 | 48 | ||
48 | CFLAGS_trace.o := -I$(src) | 49 | CFLAGS_trace.o := -I$(src) |
49 | 50 | ||
50 | # objects for PID algorithm | ||
51 | rc80211_pid-y := rc80211_pid_algo.o | ||
52 | rc80211_pid-$(CONFIG_MAC80211_DEBUGFS) += rc80211_pid_debugfs.o | ||
53 | |||
54 | rc80211_minstrel-y := rc80211_minstrel.o | 51 | rc80211_minstrel-y := rc80211_minstrel.o |
55 | rc80211_minstrel-$(CONFIG_MAC80211_DEBUGFS) += rc80211_minstrel_debugfs.o | 52 | rc80211_minstrel-$(CONFIG_MAC80211_DEBUGFS) += rc80211_minstrel_debugfs.o |
56 | 53 | ||
57 | rc80211_minstrel_ht-y := rc80211_minstrel_ht.o | 54 | rc80211_minstrel_ht-y := rc80211_minstrel_ht.o |
58 | rc80211_minstrel_ht-$(CONFIG_MAC80211_DEBUGFS) += rc80211_minstrel_ht_debugfs.o | 55 | rc80211_minstrel_ht-$(CONFIG_MAC80211_DEBUGFS) += rc80211_minstrel_ht_debugfs.o |
59 | 56 | ||
60 | mac80211-$(CONFIG_MAC80211_RC_PID) += $(rc80211_pid-y) | ||
61 | mac80211-$(CONFIG_MAC80211_RC_MINSTREL) += $(rc80211_minstrel-y) | 57 | mac80211-$(CONFIG_MAC80211_RC_MINSTREL) += $(rc80211_minstrel-y) |
62 | mac80211-$(CONFIG_MAC80211_RC_MINSTREL_HT) += $(rc80211_minstrel_ht-y) | 58 | mac80211-$(CONFIG_MAC80211_RC_MINSTREL_HT) += $(rc80211_minstrel_ht-y) |
63 | 59 | ||
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 31bf2586fb84..f0e84bc48038 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -52,7 +52,7 @@ static void ieee80211_free_tid_rx(struct rcu_head *h) | |||
52 | del_timer_sync(&tid_rx->reorder_timer); | 52 | del_timer_sync(&tid_rx->reorder_timer); |
53 | 53 | ||
54 | for (i = 0; i < tid_rx->buf_size; i++) | 54 | for (i = 0; i < tid_rx->buf_size; i++) |
55 | dev_kfree_skb(tid_rx->reorder_buf[i]); | 55 | __skb_queue_purge(&tid_rx->reorder_buf[i]); |
56 | kfree(tid_rx->reorder_buf); | 56 | kfree(tid_rx->reorder_buf); |
57 | kfree(tid_rx->reorder_time); | 57 | kfree(tid_rx->reorder_time); |
58 | kfree(tid_rx); | 58 | kfree(tid_rx); |
@@ -224,28 +224,15 @@ static void ieee80211_send_addba_resp(struct ieee80211_sub_if_data *sdata, u8 *d | |||
224 | ieee80211_tx_skb(sdata, skb); | 224 | ieee80211_tx_skb(sdata, skb); |
225 | } | 225 | } |
226 | 226 | ||
227 | void ieee80211_process_addba_request(struct ieee80211_local *local, | 227 | void __ieee80211_start_rx_ba_session(struct sta_info *sta, |
228 | struct sta_info *sta, | 228 | u8 dialog_token, u16 timeout, |
229 | struct ieee80211_mgmt *mgmt, | 229 | u16 start_seq_num, u16 ba_policy, u16 tid, |
230 | size_t len) | 230 | u16 buf_size, bool tx) |
231 | { | 231 | { |
232 | struct ieee80211_local *local = sta->sdata->local; | ||
232 | struct tid_ampdu_rx *tid_agg_rx; | 233 | struct tid_ampdu_rx *tid_agg_rx; |
233 | u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num, status; | 234 | int i, ret = -EOPNOTSUPP; |
234 | u8 dialog_token; | 235 | u16 status = WLAN_STATUS_REQUEST_DECLINED; |
235 | int ret = -EOPNOTSUPP; | ||
236 | |||
237 | /* extract session parameters from addba request frame */ | ||
238 | dialog_token = mgmt->u.action.u.addba_req.dialog_token; | ||
239 | timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout); | ||
240 | start_seq_num = | ||
241 | le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4; | ||
242 | |||
243 | capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab); | ||
244 | ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1; | ||
245 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; | ||
246 | buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6; | ||
247 | |||
248 | status = WLAN_STATUS_REQUEST_DECLINED; | ||
249 | 236 | ||
250 | if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) { | 237 | if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) { |
251 | ht_dbg(sta->sdata, | 238 | ht_dbg(sta->sdata, |
@@ -264,7 +251,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
264 | status = WLAN_STATUS_INVALID_QOS_PARAM; | 251 | status = WLAN_STATUS_INVALID_QOS_PARAM; |
265 | ht_dbg_ratelimited(sta->sdata, | 252 | ht_dbg_ratelimited(sta->sdata, |
266 | "AddBA Req with bad params from %pM on tid %u. policy %d, buffer size %d\n", | 253 | "AddBA Req with bad params from %pM on tid %u. policy %d, buffer size %d\n", |
267 | mgmt->sa, tid, ba_policy, buf_size); | 254 | sta->sta.addr, tid, ba_policy, buf_size); |
268 | goto end_no_lock; | 255 | goto end_no_lock; |
269 | } | 256 | } |
270 | /* determine default buffer size */ | 257 | /* determine default buffer size */ |
@@ -281,7 +268,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
281 | if (sta->ampdu_mlme.tid_rx[tid]) { | 268 | if (sta->ampdu_mlme.tid_rx[tid]) { |
282 | ht_dbg_ratelimited(sta->sdata, | 269 | ht_dbg_ratelimited(sta->sdata, |
283 | "unexpected AddBA Req from %pM on tid %u\n", | 270 | "unexpected AddBA Req from %pM on tid %u\n", |
284 | mgmt->sa, tid); | 271 | sta->sta.addr, tid); |
285 | 272 | ||
286 | /* delete existing Rx BA session on the same tid */ | 273 | /* delete existing Rx BA session on the same tid */ |
287 | ___ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT, | 274 | ___ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT, |
@@ -308,7 +295,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
308 | 295 | ||
309 | /* prepare reordering buffer */ | 296 | /* prepare reordering buffer */ |
310 | tid_agg_rx->reorder_buf = | 297 | tid_agg_rx->reorder_buf = |
311 | kcalloc(buf_size, sizeof(struct sk_buff *), GFP_KERNEL); | 298 | kcalloc(buf_size, sizeof(struct sk_buff_head), GFP_KERNEL); |
312 | tid_agg_rx->reorder_time = | 299 | tid_agg_rx->reorder_time = |
313 | kcalloc(buf_size, sizeof(unsigned long), GFP_KERNEL); | 300 | kcalloc(buf_size, sizeof(unsigned long), GFP_KERNEL); |
314 | if (!tid_agg_rx->reorder_buf || !tid_agg_rx->reorder_time) { | 301 | if (!tid_agg_rx->reorder_buf || !tid_agg_rx->reorder_time) { |
@@ -318,6 +305,9 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
318 | goto end; | 305 | goto end; |
319 | } | 306 | } |
320 | 307 | ||
308 | for (i = 0; i < buf_size; i++) | ||
309 | __skb_queue_head_init(&tid_agg_rx->reorder_buf[i]); | ||
310 | |||
321 | ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START, | 311 | ret = drv_ampdu_action(local, sta->sdata, IEEE80211_AMPDU_RX_START, |
322 | &sta->sta, tid, &start_seq_num, 0); | 312 | &sta->sta, tid, &start_seq_num, 0); |
323 | ht_dbg(sta->sdata, "Rx A-MPDU request on %pM tid %d result %d\n", | 313 | ht_dbg(sta->sdata, "Rx A-MPDU request on %pM tid %d result %d\n", |
@@ -350,6 +340,74 @@ end: | |||
350 | mutex_unlock(&sta->ampdu_mlme.mtx); | 340 | mutex_unlock(&sta->ampdu_mlme.mtx); |
351 | 341 | ||
352 | end_no_lock: | 342 | end_no_lock: |
353 | ieee80211_send_addba_resp(sta->sdata, sta->sta.addr, tid, | 343 | if (tx) |
354 | dialog_token, status, 1, buf_size, timeout); | 344 | ieee80211_send_addba_resp(sta->sdata, sta->sta.addr, tid, |
345 | dialog_token, status, 1, buf_size, | ||
346 | timeout); | ||
347 | } | ||
348 | |||
349 | void ieee80211_process_addba_request(struct ieee80211_local *local, | ||
350 | struct sta_info *sta, | ||
351 | struct ieee80211_mgmt *mgmt, | ||
352 | size_t len) | ||
353 | { | ||
354 | u16 capab, tid, timeout, ba_policy, buf_size, start_seq_num; | ||
355 | u8 dialog_token; | ||
356 | |||
357 | /* extract session parameters from addba request frame */ | ||
358 | dialog_token = mgmt->u.action.u.addba_req.dialog_token; | ||
359 | timeout = le16_to_cpu(mgmt->u.action.u.addba_req.timeout); | ||
360 | start_seq_num = | ||
361 | le16_to_cpu(mgmt->u.action.u.addba_req.start_seq_num) >> 4; | ||
362 | |||
363 | capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab); | ||
364 | ba_policy = (capab & IEEE80211_ADDBA_PARAM_POLICY_MASK) >> 1; | ||
365 | tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; | ||
366 | buf_size = (capab & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) >> 6; | ||
367 | |||
368 | __ieee80211_start_rx_ba_session(sta, dialog_token, timeout, | ||
369 | start_seq_num, ba_policy, tid, | ||
370 | buf_size, true); | ||
371 | } | ||
372 | |||
373 | void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif, | ||
374 | const u8 *addr, u16 tid) | ||
375 | { | ||
376 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
377 | struct ieee80211_local *local = sdata->local; | ||
378 | struct ieee80211_rx_agg *rx_agg; | ||
379 | struct sk_buff *skb = dev_alloc_skb(0); | ||
380 | |||
381 | if (unlikely(!skb)) | ||
382 | return; | ||
383 | |||
384 | rx_agg = (struct ieee80211_rx_agg *) &skb->cb; | ||
385 | memcpy(&rx_agg->addr, addr, ETH_ALEN); | ||
386 | rx_agg->tid = tid; | ||
387 | |||
388 | skb->pkt_type = IEEE80211_SDATA_QUEUE_RX_AGG_START; | ||
389 | skb_queue_tail(&sdata->skb_queue, skb); | ||
390 | ieee80211_queue_work(&local->hw, &sdata->work); | ||
391 | } | ||
392 | EXPORT_SYMBOL(ieee80211_start_rx_ba_session_offl); | ||
393 | |||
394 | void ieee80211_stop_rx_ba_session_offl(struct ieee80211_vif *vif, | ||
395 | const u8 *addr, u16 tid) | ||
396 | { | ||
397 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
398 | struct ieee80211_local *local = sdata->local; | ||
399 | struct ieee80211_rx_agg *rx_agg; | ||
400 | struct sk_buff *skb = dev_alloc_skb(0); | ||
401 | |||
402 | if (unlikely(!skb)) | ||
403 | return; | ||
404 | |||
405 | rx_agg = (struct ieee80211_rx_agg *) &skb->cb; | ||
406 | memcpy(&rx_agg->addr, addr, ETH_ALEN); | ||
407 | rx_agg->tid = tid; | ||
408 | |||
409 | skb->pkt_type = IEEE80211_SDATA_QUEUE_RX_AGG_STOP; | ||
410 | skb_queue_tail(&sdata->skb_queue, skb); | ||
411 | ieee80211_queue_work(&local->hw, &sdata->work); | ||
355 | } | 412 | } |
413 | EXPORT_SYMBOL(ieee80211_stop_rx_ba_session_offl); | ||
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index ce9633a3cfb0..d6986f3aa5c4 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -170,10 +170,13 @@ ieee80211_stop_queue_agg(struct ieee80211_sub_if_data *sdata, int tid) | |||
170 | { | 170 | { |
171 | int queue = sdata->vif.hw_queue[ieee80211_ac_from_tid(tid)]; | 171 | int queue = sdata->vif.hw_queue[ieee80211_ac_from_tid(tid)]; |
172 | 172 | ||
173 | /* we do refcounting here, so don't use the queue reason refcounting */ | ||
174 | |||
173 | if (atomic_inc_return(&sdata->local->agg_queue_stop[queue]) == 1) | 175 | if (atomic_inc_return(&sdata->local->agg_queue_stop[queue]) == 1) |
174 | ieee80211_stop_queue_by_reason( | 176 | ieee80211_stop_queue_by_reason( |
175 | &sdata->local->hw, queue, | 177 | &sdata->local->hw, queue, |
176 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION); | 178 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION, |
179 | false); | ||
177 | __acquire(agg_queue); | 180 | __acquire(agg_queue); |
178 | } | 181 | } |
179 | 182 | ||
@@ -185,7 +188,8 @@ ieee80211_wake_queue_agg(struct ieee80211_sub_if_data *sdata, int tid) | |||
185 | if (atomic_dec_return(&sdata->local->agg_queue_stop[queue]) == 0) | 188 | if (atomic_dec_return(&sdata->local->agg_queue_stop[queue]) == 0) |
186 | ieee80211_wake_queue_by_reason( | 189 | ieee80211_wake_queue_by_reason( |
187 | &sdata->local->hw, queue, | 190 | &sdata->local->hw, queue, |
188 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION); | 191 | IEEE80211_QUEUE_STOP_REASON_AGGREGATION, |
192 | false); | ||
189 | __release(agg_queue); | 193 | __release(agg_queue); |
190 | } | 194 | } |
191 | 195 | ||
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 592f4b152ba8..927b4ea0128b 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -468,330 +468,6 @@ void sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo) | |||
468 | rinfo->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; | 468 | rinfo->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; |
469 | } | 469 | } |
470 | 470 | ||
471 | static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | ||
472 | { | ||
473 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
474 | struct ieee80211_local *local = sdata->local; | ||
475 | struct rate_control_ref *ref = NULL; | ||
476 | struct timespec uptime; | ||
477 | u64 packets = 0; | ||
478 | u32 thr = 0; | ||
479 | int i, ac; | ||
480 | |||
481 | if (test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) | ||
482 | ref = local->rate_ctrl; | ||
483 | |||
484 | sinfo->generation = sdata->local->sta_generation; | ||
485 | |||
486 | sinfo->filled = STATION_INFO_INACTIVE_TIME | | ||
487 | STATION_INFO_RX_BYTES64 | | ||
488 | STATION_INFO_TX_BYTES64 | | ||
489 | STATION_INFO_RX_PACKETS | | ||
490 | STATION_INFO_TX_PACKETS | | ||
491 | STATION_INFO_TX_RETRIES | | ||
492 | STATION_INFO_TX_FAILED | | ||
493 | STATION_INFO_TX_BITRATE | | ||
494 | STATION_INFO_RX_BITRATE | | ||
495 | STATION_INFO_RX_DROP_MISC | | ||
496 | STATION_INFO_BSS_PARAM | | ||
497 | STATION_INFO_CONNECTED_TIME | | ||
498 | STATION_INFO_STA_FLAGS | | ||
499 | STATION_INFO_BEACON_LOSS_COUNT; | ||
500 | |||
501 | do_posix_clock_monotonic_gettime(&uptime); | ||
502 | sinfo->connected_time = uptime.tv_sec - sta->last_connected; | ||
503 | |||
504 | sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); | ||
505 | sinfo->tx_bytes = 0; | ||
506 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | ||
507 | sinfo->tx_bytes += sta->tx_bytes[ac]; | ||
508 | packets += sta->tx_packets[ac]; | ||
509 | } | ||
510 | sinfo->tx_packets = packets; | ||
511 | sinfo->rx_bytes = sta->rx_bytes; | ||
512 | sinfo->rx_packets = sta->rx_packets; | ||
513 | sinfo->tx_retries = sta->tx_retry_count; | ||
514 | sinfo->tx_failed = sta->tx_retry_failed; | ||
515 | sinfo->rx_dropped_misc = sta->rx_dropped; | ||
516 | sinfo->beacon_loss_count = sta->beacon_loss_count; | ||
517 | |||
518 | if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) || | ||
519 | (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) { | ||
520 | sinfo->filled |= STATION_INFO_SIGNAL | STATION_INFO_SIGNAL_AVG; | ||
521 | if (!local->ops->get_rssi || | ||
522 | drv_get_rssi(local, sdata, &sta->sta, &sinfo->signal)) | ||
523 | sinfo->signal = (s8)sta->last_signal; | ||
524 | sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal); | ||
525 | } | ||
526 | if (sta->chains) { | ||
527 | sinfo->filled |= STATION_INFO_CHAIN_SIGNAL | | ||
528 | STATION_INFO_CHAIN_SIGNAL_AVG; | ||
529 | |||
530 | sinfo->chains = sta->chains; | ||
531 | for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) { | ||
532 | sinfo->chain_signal[i] = sta->chain_signal_last[i]; | ||
533 | sinfo->chain_signal_avg[i] = | ||
534 | (s8) -ewma_read(&sta->chain_signal_avg[i]); | ||
535 | } | ||
536 | } | ||
537 | |||
538 | sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate); | ||
539 | sta_set_rate_info_rx(sta, &sinfo->rxrate); | ||
540 | |||
541 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | ||
542 | #ifdef CONFIG_MAC80211_MESH | ||
543 | sinfo->filled |= STATION_INFO_LLID | | ||
544 | STATION_INFO_PLID | | ||
545 | STATION_INFO_PLINK_STATE | | ||
546 | STATION_INFO_LOCAL_PM | | ||
547 | STATION_INFO_PEER_PM | | ||
548 | STATION_INFO_NONPEER_PM; | ||
549 | |||
550 | sinfo->llid = sta->llid; | ||
551 | sinfo->plid = sta->plid; | ||
552 | sinfo->plink_state = sta->plink_state; | ||
553 | if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) { | ||
554 | sinfo->filled |= STATION_INFO_T_OFFSET; | ||
555 | sinfo->t_offset = sta->t_offset; | ||
556 | } | ||
557 | sinfo->local_pm = sta->local_pm; | ||
558 | sinfo->peer_pm = sta->peer_pm; | ||
559 | sinfo->nonpeer_pm = sta->nonpeer_pm; | ||
560 | #endif | ||
561 | } | ||
562 | |||
563 | sinfo->bss_param.flags = 0; | ||
564 | if (sdata->vif.bss_conf.use_cts_prot) | ||
565 | sinfo->bss_param.flags |= BSS_PARAM_FLAGS_CTS_PROT; | ||
566 | if (sdata->vif.bss_conf.use_short_preamble) | ||
567 | sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE; | ||
568 | if (sdata->vif.bss_conf.use_short_slot) | ||
569 | sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME; | ||
570 | sinfo->bss_param.dtim_period = sdata->local->hw.conf.ps_dtim_period; | ||
571 | sinfo->bss_param.beacon_interval = sdata->vif.bss_conf.beacon_int; | ||
572 | |||
573 | sinfo->sta_flags.set = 0; | ||
574 | sinfo->sta_flags.mask = BIT(NL80211_STA_FLAG_AUTHORIZED) | | ||
575 | BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) | | ||
576 | BIT(NL80211_STA_FLAG_WME) | | ||
577 | BIT(NL80211_STA_FLAG_MFP) | | ||
578 | BIT(NL80211_STA_FLAG_AUTHENTICATED) | | ||
579 | BIT(NL80211_STA_FLAG_ASSOCIATED) | | ||
580 | BIT(NL80211_STA_FLAG_TDLS_PEER); | ||
581 | if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) | ||
582 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHORIZED); | ||
583 | if (test_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE)) | ||
584 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE); | ||
585 | if (test_sta_flag(sta, WLAN_STA_WME)) | ||
586 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_WME); | ||
587 | if (test_sta_flag(sta, WLAN_STA_MFP)) | ||
588 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_MFP); | ||
589 | if (test_sta_flag(sta, WLAN_STA_AUTH)) | ||
590 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHENTICATED); | ||
591 | if (test_sta_flag(sta, WLAN_STA_ASSOC)) | ||
592 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_ASSOCIATED); | ||
593 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER)) | ||
594 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER); | ||
595 | |||
596 | /* check if the driver has a SW RC implementation */ | ||
597 | if (ref && ref->ops->get_expected_throughput) | ||
598 | thr = ref->ops->get_expected_throughput(sta->rate_ctrl_priv); | ||
599 | else | ||
600 | thr = drv_get_expected_throughput(local, &sta->sta); | ||
601 | |||
602 | if (thr != 0) { | ||
603 | sinfo->filled |= STATION_INFO_EXPECTED_THROUGHPUT; | ||
604 | sinfo->expected_throughput = thr; | ||
605 | } | ||
606 | } | ||
607 | |||
608 | static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = { | ||
609 | "rx_packets", "rx_bytes", "wep_weak_iv_count", | ||
610 | "rx_duplicates", "rx_fragments", "rx_dropped", | ||
611 | "tx_packets", "tx_bytes", "tx_fragments", | ||
612 | "tx_filtered", "tx_retry_failed", "tx_retries", | ||
613 | "beacon_loss", "sta_state", "txrate", "rxrate", "signal", | ||
614 | "channel", "noise", "ch_time", "ch_time_busy", | ||
615 | "ch_time_ext_busy", "ch_time_rx", "ch_time_tx" | ||
616 | }; | ||
617 | #define STA_STATS_LEN ARRAY_SIZE(ieee80211_gstrings_sta_stats) | ||
618 | |||
619 | static int ieee80211_get_et_sset_count(struct wiphy *wiphy, | ||
620 | struct net_device *dev, | ||
621 | int sset) | ||
622 | { | ||
623 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
624 | int rv = 0; | ||
625 | |||
626 | if (sset == ETH_SS_STATS) | ||
627 | rv += STA_STATS_LEN; | ||
628 | |||
629 | rv += drv_get_et_sset_count(sdata, sset); | ||
630 | |||
631 | if (rv == 0) | ||
632 | return -EOPNOTSUPP; | ||
633 | return rv; | ||
634 | } | ||
635 | |||
636 | static void ieee80211_get_et_stats(struct wiphy *wiphy, | ||
637 | struct net_device *dev, | ||
638 | struct ethtool_stats *stats, | ||
639 | u64 *data) | ||
640 | { | ||
641 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
642 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
643 | struct ieee80211_channel *channel; | ||
644 | struct sta_info *sta; | ||
645 | struct ieee80211_local *local = sdata->local; | ||
646 | struct station_info sinfo; | ||
647 | struct survey_info survey; | ||
648 | int i, q; | ||
649 | #define STA_STATS_SURVEY_LEN 7 | ||
650 | |||
651 | memset(data, 0, sizeof(u64) * STA_STATS_LEN); | ||
652 | |||
653 | #define ADD_STA_STATS(sta) \ | ||
654 | do { \ | ||
655 | data[i++] += sta->rx_packets; \ | ||
656 | data[i++] += sta->rx_bytes; \ | ||
657 | data[i++] += sta->wep_weak_iv_count; \ | ||
658 | data[i++] += sta->num_duplicates; \ | ||
659 | data[i++] += sta->rx_fragments; \ | ||
660 | data[i++] += sta->rx_dropped; \ | ||
661 | \ | ||
662 | data[i++] += sinfo.tx_packets; \ | ||
663 | data[i++] += sinfo.tx_bytes; \ | ||
664 | data[i++] += sta->tx_fragments; \ | ||
665 | data[i++] += sta->tx_filtered_count; \ | ||
666 | data[i++] += sta->tx_retry_failed; \ | ||
667 | data[i++] += sta->tx_retry_count; \ | ||
668 | data[i++] += sta->beacon_loss_count; \ | ||
669 | } while (0) | ||
670 | |||
671 | /* For Managed stations, find the single station based on BSSID | ||
672 | * and use that. For interface types, iterate through all available | ||
673 | * stations and add stats for any station that is assigned to this | ||
674 | * network device. | ||
675 | */ | ||
676 | |||
677 | mutex_lock(&local->sta_mtx); | ||
678 | |||
679 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
680 | sta = sta_info_get_bss(sdata, sdata->u.mgd.bssid); | ||
681 | |||
682 | if (!(sta && !WARN_ON(sta->sdata->dev != dev))) | ||
683 | goto do_survey; | ||
684 | |||
685 | sinfo.filled = 0; | ||
686 | sta_set_sinfo(sta, &sinfo); | ||
687 | |||
688 | i = 0; | ||
689 | ADD_STA_STATS(sta); | ||
690 | |||
691 | data[i++] = sta->sta_state; | ||
692 | |||
693 | |||
694 | if (sinfo.filled & STATION_INFO_TX_BITRATE) | ||
695 | data[i] = 100000 * | ||
696 | cfg80211_calculate_bitrate(&sinfo.txrate); | ||
697 | i++; | ||
698 | if (sinfo.filled & STATION_INFO_RX_BITRATE) | ||
699 | data[i] = 100000 * | ||
700 | cfg80211_calculate_bitrate(&sinfo.rxrate); | ||
701 | i++; | ||
702 | |||
703 | if (sinfo.filled & STATION_INFO_SIGNAL_AVG) | ||
704 | data[i] = (u8)sinfo.signal_avg; | ||
705 | i++; | ||
706 | } else { | ||
707 | list_for_each_entry(sta, &local->sta_list, list) { | ||
708 | /* Make sure this station belongs to the proper dev */ | ||
709 | if (sta->sdata->dev != dev) | ||
710 | continue; | ||
711 | |||
712 | sinfo.filled = 0; | ||
713 | sta_set_sinfo(sta, &sinfo); | ||
714 | i = 0; | ||
715 | ADD_STA_STATS(sta); | ||
716 | } | ||
717 | } | ||
718 | |||
719 | do_survey: | ||
720 | i = STA_STATS_LEN - STA_STATS_SURVEY_LEN; | ||
721 | /* Get survey stats for current channel */ | ||
722 | survey.filled = 0; | ||
723 | |||
724 | rcu_read_lock(); | ||
725 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
726 | if (chanctx_conf) | ||
727 | channel = chanctx_conf->def.chan; | ||
728 | else | ||
729 | channel = NULL; | ||
730 | rcu_read_unlock(); | ||
731 | |||
732 | if (channel) { | ||
733 | q = 0; | ||
734 | do { | ||
735 | survey.filled = 0; | ||
736 | if (drv_get_survey(local, q, &survey) != 0) { | ||
737 | survey.filled = 0; | ||
738 | break; | ||
739 | } | ||
740 | q++; | ||
741 | } while (channel != survey.channel); | ||
742 | } | ||
743 | |||
744 | if (survey.filled) | ||
745 | data[i++] = survey.channel->center_freq; | ||
746 | else | ||
747 | data[i++] = 0; | ||
748 | if (survey.filled & SURVEY_INFO_NOISE_DBM) | ||
749 | data[i++] = (u8)survey.noise; | ||
750 | else | ||
751 | data[i++] = -1LL; | ||
752 | if (survey.filled & SURVEY_INFO_CHANNEL_TIME) | ||
753 | data[i++] = survey.channel_time; | ||
754 | else | ||
755 | data[i++] = -1LL; | ||
756 | if (survey.filled & SURVEY_INFO_CHANNEL_TIME_BUSY) | ||
757 | data[i++] = survey.channel_time_busy; | ||
758 | else | ||
759 | data[i++] = -1LL; | ||
760 | if (survey.filled & SURVEY_INFO_CHANNEL_TIME_EXT_BUSY) | ||
761 | data[i++] = survey.channel_time_ext_busy; | ||
762 | else | ||
763 | data[i++] = -1LL; | ||
764 | if (survey.filled & SURVEY_INFO_CHANNEL_TIME_RX) | ||
765 | data[i++] = survey.channel_time_rx; | ||
766 | else | ||
767 | data[i++] = -1LL; | ||
768 | if (survey.filled & SURVEY_INFO_CHANNEL_TIME_TX) | ||
769 | data[i++] = survey.channel_time_tx; | ||
770 | else | ||
771 | data[i++] = -1LL; | ||
772 | |||
773 | mutex_unlock(&local->sta_mtx); | ||
774 | |||
775 | if (WARN_ON(i != STA_STATS_LEN)) | ||
776 | return; | ||
777 | |||
778 | drv_get_et_stats(sdata, stats, &(data[STA_STATS_LEN])); | ||
779 | } | ||
780 | |||
781 | static void ieee80211_get_et_strings(struct wiphy *wiphy, | ||
782 | struct net_device *dev, | ||
783 | u32 sset, u8 *data) | ||
784 | { | ||
785 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
786 | int sz_sta_stats = 0; | ||
787 | |||
788 | if (sset == ETH_SS_STATS) { | ||
789 | sz_sta_stats = sizeof(ieee80211_gstrings_sta_stats); | ||
790 | memcpy(data, ieee80211_gstrings_sta_stats, sz_sta_stats); | ||
791 | } | ||
792 | drv_get_et_strings(sdata, sset, &(data[sz_sta_stats])); | ||
793 | } | ||
794 | |||
795 | static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, | 471 | static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev, |
796 | int idx, u8 *mac, struct station_info *sinfo) | 472 | int idx, u8 *mac, struct station_info *sinfo) |
797 | { | 473 | { |
@@ -878,7 +554,8 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy, | |||
878 | } | 554 | } |
879 | 555 | ||
880 | static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, | 556 | static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, |
881 | const u8 *resp, size_t resp_len) | 557 | const u8 *resp, size_t resp_len, |
558 | const struct ieee80211_csa_settings *csa) | ||
882 | { | 559 | { |
883 | struct probe_resp *new, *old; | 560 | struct probe_resp *new, *old; |
884 | 561 | ||
@@ -894,6 +571,11 @@ static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
894 | new->len = resp_len; | 571 | new->len = resp_len; |
895 | memcpy(new->data, resp, resp_len); | 572 | memcpy(new->data, resp, resp_len); |
896 | 573 | ||
574 | if (csa) | ||
575 | memcpy(new->csa_counter_offsets, csa->counter_offsets_presp, | ||
576 | csa->n_counter_offsets_presp * | ||
577 | sizeof(new->csa_counter_offsets[0])); | ||
578 | |||
897 | rcu_assign_pointer(sdata->u.ap.probe_resp, new); | 579 | rcu_assign_pointer(sdata->u.ap.probe_resp, new); |
898 | if (old) | 580 | if (old) |
899 | kfree_rcu(old, rcu_head); | 581 | kfree_rcu(old, rcu_head); |
@@ -902,7 +584,8 @@ static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata, | |||
902 | } | 584 | } |
903 | 585 | ||
904 | static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, | 586 | static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, |
905 | struct cfg80211_beacon_data *params) | 587 | struct cfg80211_beacon_data *params, |
588 | const struct ieee80211_csa_settings *csa) | ||
906 | { | 589 | { |
907 | struct beacon_data *new, *old; | 590 | struct beacon_data *new, *old; |
908 | int new_head_len, new_tail_len; | 591 | int new_head_len, new_tail_len; |
@@ -946,6 +629,13 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, | |||
946 | new->head_len = new_head_len; | 629 | new->head_len = new_head_len; |
947 | new->tail_len = new_tail_len; | 630 | new->tail_len = new_tail_len; |
948 | 631 | ||
632 | if (csa) { | ||
633 | new->csa_current_counter = csa->count; | ||
634 | memcpy(new->csa_counter_offsets, csa->counter_offsets_beacon, | ||
635 | csa->n_counter_offsets_beacon * | ||
636 | sizeof(new->csa_counter_offsets[0])); | ||
637 | } | ||
638 | |||
949 | /* copy in head */ | 639 | /* copy in head */ |
950 | if (params->head) | 640 | if (params->head) |
951 | memcpy(new->head, params->head, new_head_len); | 641 | memcpy(new->head, params->head, new_head_len); |
@@ -960,7 +650,7 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata, | |||
960 | memcpy(new->tail, old->tail, new_tail_len); | 650 | memcpy(new->tail, old->tail, new_tail_len); |
961 | 651 | ||
962 | err = ieee80211_set_probe_resp(sdata, params->probe_resp, | 652 | err = ieee80211_set_probe_resp(sdata, params->probe_resp, |
963 | params->probe_resp_len); | 653 | params->probe_resp_len, csa); |
964 | if (err < 0) | 654 | if (err < 0) |
965 | return err; | 655 | return err; |
966 | if (err == 0) | 656 | if (err == 0) |
@@ -1045,7 +735,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
1045 | sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |= | 735 | sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |= |
1046 | IEEE80211_P2P_OPPPS_ENABLE_BIT; | 736 | IEEE80211_P2P_OPPPS_ENABLE_BIT; |
1047 | 737 | ||
1048 | err = ieee80211_assign_beacon(sdata, ¶ms->beacon); | 738 | err = ieee80211_assign_beacon(sdata, ¶ms->beacon, NULL); |
1049 | if (err < 0) { | 739 | if (err < 0) { |
1050 | ieee80211_vif_release_channel(sdata); | 740 | ieee80211_vif_release_channel(sdata); |
1051 | return err; | 741 | return err; |
@@ -1093,38 +783,13 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
1093 | if (!old) | 783 | if (!old) |
1094 | return -ENOENT; | 784 | return -ENOENT; |
1095 | 785 | ||
1096 | err = ieee80211_assign_beacon(sdata, params); | 786 | err = ieee80211_assign_beacon(sdata, params, NULL); |
1097 | if (err < 0) | 787 | if (err < 0) |
1098 | return err; | 788 | return err; |
1099 | ieee80211_bss_info_change_notify(sdata, err); | 789 | ieee80211_bss_info_change_notify(sdata, err); |
1100 | return 0; | 790 | return 0; |
1101 | } | 791 | } |
1102 | 792 | ||
1103 | bool ieee80211_csa_needs_block_tx(struct ieee80211_local *local) | ||
1104 | { | ||
1105 | struct ieee80211_sub_if_data *sdata; | ||
1106 | |||
1107 | lockdep_assert_held(&local->mtx); | ||
1108 | |||
1109 | rcu_read_lock(); | ||
1110 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | ||
1111 | if (!ieee80211_sdata_running(sdata)) | ||
1112 | continue; | ||
1113 | |||
1114 | if (!sdata->vif.csa_active) | ||
1115 | continue; | ||
1116 | |||
1117 | if (!sdata->csa_block_tx) | ||
1118 | continue; | ||
1119 | |||
1120 | rcu_read_unlock(); | ||
1121 | return true; | ||
1122 | } | ||
1123 | rcu_read_unlock(); | ||
1124 | |||
1125 | return false; | ||
1126 | } | ||
1127 | |||
1128 | static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | 793 | static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) |
1129 | { | 794 | { |
1130 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 795 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
@@ -1144,10 +809,12 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
1144 | /* abort any running channel switch */ | 809 | /* abort any running channel switch */ |
1145 | mutex_lock(&local->mtx); | 810 | mutex_lock(&local->mtx); |
1146 | sdata->vif.csa_active = false; | 811 | sdata->vif.csa_active = false; |
1147 | if (!ieee80211_csa_needs_block_tx(local)) | 812 | if (sdata->csa_block_tx) { |
1148 | ieee80211_wake_queues_by_reason(&local->hw, | 813 | ieee80211_wake_vif_queues(local, sdata, |
1149 | IEEE80211_MAX_QUEUE_MAP, | 814 | IEEE80211_QUEUE_STOP_REASON_CSA); |
1150 | IEEE80211_QUEUE_STOP_REASON_CSA); | 815 | sdata->csa_block_tx = false; |
816 | } | ||
817 | |||
1151 | mutex_unlock(&local->mtx); | 818 | mutex_unlock(&local->mtx); |
1152 | 819 | ||
1153 | kfree(sdata->u.ap.next_beacon); | 820 | kfree(sdata->u.ap.next_beacon); |
@@ -1330,9 +997,12 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1330 | } | 997 | } |
1331 | } | 998 | } |
1332 | 999 | ||
1333 | ret = sta_apply_auth_flags(local, sta, mask, set); | 1000 | /* auth flags will be set later for TDLS stations */ |
1334 | if (ret) | 1001 | if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) { |
1335 | return ret; | 1002 | ret = sta_apply_auth_flags(local, sta, mask, set); |
1003 | if (ret) | ||
1004 | return ret; | ||
1005 | } | ||
1336 | 1006 | ||
1337 | if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) { | 1007 | if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) { |
1338 | if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) | 1008 | if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) |
@@ -1469,6 +1139,13 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
1469 | #endif | 1139 | #endif |
1470 | } | 1140 | } |
1471 | 1141 | ||
1142 | /* set the STA state after all sta info from usermode has been set */ | ||
1143 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER)) { | ||
1144 | ret = sta_apply_auth_flags(local, sta, mask, set); | ||
1145 | if (ret) | ||
1146 | return ret; | ||
1147 | } | ||
1148 | |||
1472 | return 0; | 1149 | return 0; |
1473 | } | 1150 | } |
1474 | 1151 | ||
@@ -3076,7 +2753,8 @@ static int ieee80211_set_after_csa_beacon(struct ieee80211_sub_if_data *sdata, | |||
3076 | 2753 | ||
3077 | switch (sdata->vif.type) { | 2754 | switch (sdata->vif.type) { |
3078 | case NL80211_IFTYPE_AP: | 2755 | case NL80211_IFTYPE_AP: |
3079 | err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon); | 2756 | err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon, |
2757 | NULL); | ||
3080 | kfree(sdata->u.ap.next_beacon); | 2758 | kfree(sdata->u.ap.next_beacon); |
3081 | sdata->u.ap.next_beacon = NULL; | 2759 | sdata->u.ap.next_beacon = NULL; |
3082 | 2760 | ||
@@ -3114,17 +2792,35 @@ static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata) | |||
3114 | 2792 | ||
3115 | sdata_assert_lock(sdata); | 2793 | sdata_assert_lock(sdata); |
3116 | lockdep_assert_held(&local->mtx); | 2794 | lockdep_assert_held(&local->mtx); |
2795 | lockdep_assert_held(&local->chanctx_mtx); | ||
3117 | 2796 | ||
3118 | sdata->radar_required = sdata->csa_radar_required; | 2797 | /* |
3119 | err = ieee80211_vif_change_channel(sdata, &changed); | 2798 | * using reservation isn't immediate as it may be deferred until later |
3120 | if (err < 0) | 2799 | * with multi-vif. once reservation is complete it will re-schedule the |
3121 | return err; | 2800 | * work with no reserved_chanctx so verify chandef to check if it |
2801 | * completed successfully | ||
2802 | */ | ||
3122 | 2803 | ||
3123 | if (!local->use_chanctx) { | 2804 | if (sdata->reserved_chanctx) { |
3124 | local->_oper_chandef = sdata->csa_chandef; | 2805 | /* |
3125 | ieee80211_hw_config(local, 0); | 2806 | * with multi-vif csa driver may call ieee80211_csa_finish() |
2807 | * many times while waiting for other interfaces to use their | ||
2808 | * reservations | ||
2809 | */ | ||
2810 | if (sdata->reserved_ready) | ||
2811 | return 0; | ||
2812 | |||
2813 | err = ieee80211_vif_use_reserved_context(sdata); | ||
2814 | if (err) | ||
2815 | return err; | ||
2816 | |||
2817 | return 0; | ||
3126 | } | 2818 | } |
3127 | 2819 | ||
2820 | if (!cfg80211_chandef_identical(&sdata->vif.bss_conf.chandef, | ||
2821 | &sdata->csa_chandef)) | ||
2822 | return -EINVAL; | ||
2823 | |||
3128 | sdata->vif.csa_active = false; | 2824 | sdata->vif.csa_active = false; |
3129 | 2825 | ||
3130 | err = ieee80211_set_after_csa_beacon(sdata, &changed); | 2826 | err = ieee80211_set_after_csa_beacon(sdata, &changed); |
@@ -3134,10 +2830,11 @@ static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata) | |||
3134 | ieee80211_bss_info_change_notify(sdata, changed); | 2830 | ieee80211_bss_info_change_notify(sdata, changed); |
3135 | cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef); | 2831 | cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef); |
3136 | 2832 | ||
3137 | if (!ieee80211_csa_needs_block_tx(local)) | 2833 | if (sdata->csa_block_tx) { |
3138 | ieee80211_wake_queues_by_reason(&local->hw, | 2834 | ieee80211_wake_vif_queues(local, sdata, |
3139 | IEEE80211_MAX_QUEUE_MAP, | 2835 | IEEE80211_QUEUE_STOP_REASON_CSA); |
3140 | IEEE80211_QUEUE_STOP_REASON_CSA); | 2836 | sdata->csa_block_tx = false; |
2837 | } | ||
3141 | 2838 | ||
3142 | return 0; | 2839 | return 0; |
3143 | } | 2840 | } |
@@ -3160,6 +2857,7 @@ void ieee80211_csa_finalize_work(struct work_struct *work) | |||
3160 | 2857 | ||
3161 | sdata_lock(sdata); | 2858 | sdata_lock(sdata); |
3162 | mutex_lock(&local->mtx); | 2859 | mutex_lock(&local->mtx); |
2860 | mutex_lock(&local->chanctx_mtx); | ||
3163 | 2861 | ||
3164 | /* AP might have been stopped while waiting for the lock. */ | 2862 | /* AP might have been stopped while waiting for the lock. */ |
3165 | if (!sdata->vif.csa_active) | 2863 | if (!sdata->vif.csa_active) |
@@ -3171,6 +2869,7 @@ void ieee80211_csa_finalize_work(struct work_struct *work) | |||
3171 | ieee80211_csa_finalize(sdata); | 2869 | ieee80211_csa_finalize(sdata); |
3172 | 2870 | ||
3173 | unlock: | 2871 | unlock: |
2872 | mutex_unlock(&local->chanctx_mtx); | ||
3174 | mutex_unlock(&local->mtx); | 2873 | mutex_unlock(&local->mtx); |
3175 | sdata_unlock(sdata); | 2874 | sdata_unlock(sdata); |
3176 | } | 2875 | } |
@@ -3179,6 +2878,7 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata, | |||
3179 | struct cfg80211_csa_settings *params, | 2878 | struct cfg80211_csa_settings *params, |
3180 | u32 *changed) | 2879 | u32 *changed) |
3181 | { | 2880 | { |
2881 | struct ieee80211_csa_settings csa = {}; | ||
3182 | int err; | 2882 | int err; |
3183 | 2883 | ||
3184 | switch (sdata->vif.type) { | 2884 | switch (sdata->vif.type) { |
@@ -3213,20 +2913,13 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata, | |||
3213 | IEEE80211_MAX_CSA_COUNTERS_NUM)) | 2913 | IEEE80211_MAX_CSA_COUNTERS_NUM)) |
3214 | return -EINVAL; | 2914 | return -EINVAL; |
3215 | 2915 | ||
3216 | /* make sure we don't have garbage in other counters */ | 2916 | csa.counter_offsets_beacon = params->counter_offsets_beacon; |
3217 | memset(sdata->csa_counter_offset_beacon, 0, | 2917 | csa.counter_offsets_presp = params->counter_offsets_presp; |
3218 | sizeof(sdata->csa_counter_offset_beacon)); | 2918 | csa.n_counter_offsets_beacon = params->n_counter_offsets_beacon; |
3219 | memset(sdata->csa_counter_offset_presp, 0, | 2919 | csa.n_counter_offsets_presp = params->n_counter_offsets_presp; |
3220 | sizeof(sdata->csa_counter_offset_presp)); | 2920 | csa.count = params->count; |
3221 | |||
3222 | memcpy(sdata->csa_counter_offset_beacon, | ||
3223 | params->counter_offsets_beacon, | ||
3224 | params->n_counter_offsets_beacon * sizeof(u16)); | ||
3225 | memcpy(sdata->csa_counter_offset_presp, | ||
3226 | params->counter_offsets_presp, | ||
3227 | params->n_counter_offsets_presp * sizeof(u16)); | ||
3228 | 2921 | ||
3229 | err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa); | 2922 | err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa, &csa); |
3230 | if (err < 0) { | 2923 | if (err < 0) { |
3231 | kfree(sdata->u.ap.next_beacon); | 2924 | kfree(sdata->u.ap.next_beacon); |
3232 | return err; | 2925 | return err; |
@@ -3322,7 +3015,7 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
3322 | struct ieee80211_local *local = sdata->local; | 3015 | struct ieee80211_local *local = sdata->local; |
3323 | struct ieee80211_chanctx_conf *conf; | 3016 | struct ieee80211_chanctx_conf *conf; |
3324 | struct ieee80211_chanctx *chanctx; | 3017 | struct ieee80211_chanctx *chanctx; |
3325 | int err, num_chanctx, changed = 0; | 3018 | int err, changed = 0; |
3326 | 3019 | ||
3327 | sdata_assert_lock(sdata); | 3020 | sdata_assert_lock(sdata); |
3328 | lockdep_assert_held(&local->mtx); | 3021 | lockdep_assert_held(&local->mtx); |
@@ -3337,46 +3030,50 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
3337 | &sdata->vif.bss_conf.chandef)) | 3030 | &sdata->vif.bss_conf.chandef)) |
3338 | return -EINVAL; | 3031 | return -EINVAL; |
3339 | 3032 | ||
3033 | /* don't allow another channel switch if one is already active. */ | ||
3034 | if (sdata->vif.csa_active) | ||
3035 | return -EBUSY; | ||
3036 | |||
3340 | mutex_lock(&local->chanctx_mtx); | 3037 | mutex_lock(&local->chanctx_mtx); |
3341 | conf = rcu_dereference_protected(sdata->vif.chanctx_conf, | 3038 | conf = rcu_dereference_protected(sdata->vif.chanctx_conf, |
3342 | lockdep_is_held(&local->chanctx_mtx)); | 3039 | lockdep_is_held(&local->chanctx_mtx)); |
3343 | if (!conf) { | 3040 | if (!conf) { |
3344 | mutex_unlock(&local->chanctx_mtx); | 3041 | err = -EBUSY; |
3345 | return -EBUSY; | 3042 | goto out; |
3346 | } | 3043 | } |
3347 | 3044 | ||
3348 | /* don't handle for multi-VIF cases */ | ||
3349 | chanctx = container_of(conf, struct ieee80211_chanctx, conf); | 3045 | chanctx = container_of(conf, struct ieee80211_chanctx, conf); |
3350 | if (ieee80211_chanctx_refcount(local, chanctx) > 1) { | 3046 | if (!chanctx) { |
3351 | mutex_unlock(&local->chanctx_mtx); | 3047 | err = -EBUSY; |
3352 | return -EBUSY; | 3048 | goto out; |
3353 | } | 3049 | } |
3354 | num_chanctx = 0; | ||
3355 | list_for_each_entry_rcu(chanctx, &local->chanctx_list, list) | ||
3356 | num_chanctx++; | ||
3357 | mutex_unlock(&local->chanctx_mtx); | ||
3358 | 3050 | ||
3359 | if (num_chanctx > 1) | 3051 | err = ieee80211_vif_reserve_chanctx(sdata, ¶ms->chandef, |
3360 | return -EBUSY; | 3052 | chanctx->mode, |
3053 | params->radar_required); | ||
3054 | if (err) | ||
3055 | goto out; | ||
3361 | 3056 | ||
3362 | /* don't allow another channel switch if one is already active. */ | 3057 | /* if reservation is invalid then this will fail */ |
3363 | if (sdata->vif.csa_active) | 3058 | err = ieee80211_check_combinations(sdata, NULL, chanctx->mode, 0); |
3364 | return -EBUSY; | 3059 | if (err) { |
3060 | ieee80211_vif_unreserve_chanctx(sdata); | ||
3061 | goto out; | ||
3062 | } | ||
3365 | 3063 | ||
3366 | err = ieee80211_set_csa_beacon(sdata, params, &changed); | 3064 | err = ieee80211_set_csa_beacon(sdata, params, &changed); |
3367 | if (err) | 3065 | if (err) { |
3368 | return err; | 3066 | ieee80211_vif_unreserve_chanctx(sdata); |
3067 | goto out; | ||
3068 | } | ||
3369 | 3069 | ||
3370 | sdata->csa_radar_required = params->radar_required; | ||
3371 | sdata->csa_chandef = params->chandef; | 3070 | sdata->csa_chandef = params->chandef; |
3372 | sdata->csa_block_tx = params->block_tx; | 3071 | sdata->csa_block_tx = params->block_tx; |
3373 | sdata->csa_current_counter = params->count; | ||
3374 | sdata->vif.csa_active = true; | 3072 | sdata->vif.csa_active = true; |
3375 | 3073 | ||
3376 | if (sdata->csa_block_tx) | 3074 | if (sdata->csa_block_tx) |
3377 | ieee80211_stop_queues_by_reason(&local->hw, | 3075 | ieee80211_stop_vif_queues(local, sdata, |
3378 | IEEE80211_MAX_QUEUE_MAP, | 3076 | IEEE80211_QUEUE_STOP_REASON_CSA); |
3379 | IEEE80211_QUEUE_STOP_REASON_CSA); | ||
3380 | 3077 | ||
3381 | if (changed) { | 3078 | if (changed) { |
3382 | ieee80211_bss_info_change_notify(sdata, changed); | 3079 | ieee80211_bss_info_change_notify(sdata, changed); |
@@ -3386,7 +3083,9 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
3386 | ieee80211_csa_finalize(sdata); | 3083 | ieee80211_csa_finalize(sdata); |
3387 | } | 3084 | } |
3388 | 3085 | ||
3389 | return 0; | 3086 | out: |
3087 | mutex_unlock(&local->chanctx_mtx); | ||
3088 | return err; | ||
3390 | } | 3089 | } |
3391 | 3090 | ||
3392 | int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | 3091 | int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, |
@@ -3518,10 +3217,23 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, | |||
3518 | sdata->vif.type == NL80211_IFTYPE_ADHOC) && | 3217 | sdata->vif.type == NL80211_IFTYPE_ADHOC) && |
3519 | params->n_csa_offsets) { | 3218 | params->n_csa_offsets) { |
3520 | int i; | 3219 | int i; |
3521 | u8 c = sdata->csa_current_counter; | 3220 | struct beacon_data *beacon = NULL; |
3522 | 3221 | ||
3523 | for (i = 0; i < params->n_csa_offsets; i++) | 3222 | rcu_read_lock(); |
3524 | data[params->csa_offsets[i]] = c; | 3223 | |
3224 | if (sdata->vif.type == NL80211_IFTYPE_AP) | ||
3225 | beacon = rcu_dereference(sdata->u.ap.beacon); | ||
3226 | else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
3227 | beacon = rcu_dereference(sdata->u.ibss.presp); | ||
3228 | else if (ieee80211_vif_is_mesh(&sdata->vif)) | ||
3229 | beacon = rcu_dereference(sdata->u.mesh.beacon); | ||
3230 | |||
3231 | if (beacon) | ||
3232 | for (i = 0; i < params->n_csa_offsets; i++) | ||
3233 | data[params->csa_offsets[i]] = | ||
3234 | beacon->csa_current_counter; | ||
3235 | |||
3236 | rcu_read_unlock(); | ||
3525 | } | 3237 | } |
3526 | 3238 | ||
3527 | IEEE80211_SKB_CB(skb)->flags = flags; | 3239 | IEEE80211_SKB_CB(skb)->flags = flags; |
@@ -3601,21 +3313,6 @@ static int ieee80211_get_antenna(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant) | |||
3601 | return drv_get_antenna(local, tx_ant, rx_ant); | 3313 | return drv_get_antenna(local, tx_ant, rx_ant); |
3602 | } | 3314 | } |
3603 | 3315 | ||
3604 | static int ieee80211_set_ringparam(struct wiphy *wiphy, u32 tx, u32 rx) | ||
3605 | { | ||
3606 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
3607 | |||
3608 | return drv_set_ringparam(local, tx, rx); | ||
3609 | } | ||
3610 | |||
3611 | static void ieee80211_get_ringparam(struct wiphy *wiphy, | ||
3612 | u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max) | ||
3613 | { | ||
3614 | struct ieee80211_local *local = wiphy_priv(wiphy); | ||
3615 | |||
3616 | drv_get_ringparam(local, tx, tx_max, rx, rx_max); | ||
3617 | } | ||
3618 | |||
3619 | static int ieee80211_set_rekey_data(struct wiphy *wiphy, | 3316 | static int ieee80211_set_rekey_data(struct wiphy *wiphy, |
3620 | struct net_device *dev, | 3317 | struct net_device *dev, |
3621 | struct cfg80211_gtk_rekey_data *data) | 3318 | struct cfg80211_gtk_rekey_data *data) |
@@ -3847,8 +3544,6 @@ const struct cfg80211_ops mac80211_config_ops = { | |||
3847 | .mgmt_frame_register = ieee80211_mgmt_frame_register, | 3544 | .mgmt_frame_register = ieee80211_mgmt_frame_register, |
3848 | .set_antenna = ieee80211_set_antenna, | 3545 | .set_antenna = ieee80211_set_antenna, |
3849 | .get_antenna = ieee80211_get_antenna, | 3546 | .get_antenna = ieee80211_get_antenna, |
3850 | .set_ringparam = ieee80211_set_ringparam, | ||
3851 | .get_ringparam = ieee80211_get_ringparam, | ||
3852 | .set_rekey_data = ieee80211_set_rekey_data, | 3547 | .set_rekey_data = ieee80211_set_rekey_data, |
3853 | .tdls_oper = ieee80211_tdls_oper, | 3548 | .tdls_oper = ieee80211_tdls_oper, |
3854 | .tdls_mgmt = ieee80211_tdls_mgmt, | 3549 | .tdls_mgmt = ieee80211_tdls_mgmt, |
@@ -3857,9 +3552,6 @@ const struct cfg80211_ops mac80211_config_ops = { | |||
3857 | #ifdef CONFIG_PM | 3552 | #ifdef CONFIG_PM |
3858 | .set_wakeup = ieee80211_set_wakeup, | 3553 | .set_wakeup = ieee80211_set_wakeup, |
3859 | #endif | 3554 | #endif |
3860 | .get_et_sset_count = ieee80211_get_et_sset_count, | ||
3861 | .get_et_stats = ieee80211_get_et_stats, | ||
3862 | .get_et_strings = ieee80211_get_et_strings, | ||
3863 | .get_channel = ieee80211_cfg_get_channel, | 3555 | .get_channel = ieee80211_cfg_get_channel, |
3864 | .start_radar_detection = ieee80211_start_radar_detection, | 3556 | .start_radar_detection = ieee80211_start_radar_detection, |
3865 | .channel_switch = ieee80211_channel_switch, | 3557 | .channel_switch = ieee80211_channel_switch, |
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index a310e33972de..399ad82c997f 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
@@ -63,6 +63,20 @@ static bool ieee80211_can_create_new_chanctx(struct ieee80211_local *local) | |||
63 | return ieee80211_num_chanctx(local) < ieee80211_max_num_channels(local); | 63 | return ieee80211_num_chanctx(local) < ieee80211_max_num_channels(local); |
64 | } | 64 | } |
65 | 65 | ||
66 | static struct ieee80211_chanctx * | ||
67 | ieee80211_vif_get_chanctx(struct ieee80211_sub_if_data *sdata) | ||
68 | { | ||
69 | struct ieee80211_local *local __maybe_unused = sdata->local; | ||
70 | struct ieee80211_chanctx_conf *conf; | ||
71 | |||
72 | conf = rcu_dereference_protected(sdata->vif.chanctx_conf, | ||
73 | lockdep_is_held(&local->chanctx_mtx)); | ||
74 | if (!conf) | ||
75 | return NULL; | ||
76 | |||
77 | return container_of(conf, struct ieee80211_chanctx, conf); | ||
78 | } | ||
79 | |||
66 | static const struct cfg80211_chan_def * | 80 | static const struct cfg80211_chan_def * |
67 | ieee80211_chanctx_reserved_chandef(struct ieee80211_local *local, | 81 | ieee80211_chanctx_reserved_chandef(struct ieee80211_local *local, |
68 | struct ieee80211_chanctx *ctx, | 82 | struct ieee80211_chanctx *ctx, |
@@ -160,6 +174,9 @@ ieee80211_find_reservation_chanctx(struct ieee80211_local *local, | |||
160 | return NULL; | 174 | return NULL; |
161 | 175 | ||
162 | list_for_each_entry(ctx, &local->chanctx_list, list) { | 176 | list_for_each_entry(ctx, &local->chanctx_list, list) { |
177 | if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED) | ||
178 | continue; | ||
179 | |||
163 | if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) | 180 | if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) |
164 | continue; | 181 | continue; |
165 | 182 | ||
@@ -347,6 +364,9 @@ ieee80211_find_chanctx(struct ieee80211_local *local, | |||
347 | list_for_each_entry(ctx, &local->chanctx_list, list) { | 364 | list_for_each_entry(ctx, &local->chanctx_list, list) { |
348 | const struct cfg80211_chan_def *compat; | 365 | const struct cfg80211_chan_def *compat; |
349 | 366 | ||
367 | if (ctx->replace_state != IEEE80211_CHANCTX_REPLACE_NONE) | ||
368 | continue; | ||
369 | |||
350 | if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) | 370 | if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) |
351 | continue; | 371 | continue; |
352 | 372 | ||
@@ -521,6 +541,8 @@ static void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local, | |||
521 | continue; | 541 | continue; |
522 | if (rcu_access_pointer(sdata->vif.chanctx_conf) != conf) | 542 | if (rcu_access_pointer(sdata->vif.chanctx_conf) != conf) |
523 | continue; | 543 | continue; |
544 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
545 | continue; | ||
524 | 546 | ||
525 | if (!compat) | 547 | if (!compat) |
526 | compat = &sdata->vif.bss_conf.chandef; | 548 | compat = &sdata->vif.bss_conf.chandef; |
@@ -622,6 +644,7 @@ static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata) | |||
622 | struct ieee80211_local *local = sdata->local; | 644 | struct ieee80211_local *local = sdata->local; |
623 | struct ieee80211_chanctx_conf *conf; | 645 | struct ieee80211_chanctx_conf *conf; |
624 | struct ieee80211_chanctx *ctx; | 646 | struct ieee80211_chanctx *ctx; |
647 | bool use_reserved_switch = false; | ||
625 | 648 | ||
626 | lockdep_assert_held(&local->chanctx_mtx); | 649 | lockdep_assert_held(&local->chanctx_mtx); |
627 | 650 | ||
@@ -632,12 +655,23 @@ static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata) | |||
632 | 655 | ||
633 | ctx = container_of(conf, struct ieee80211_chanctx, conf); | 656 | ctx = container_of(conf, struct ieee80211_chanctx, conf); |
634 | 657 | ||
635 | if (sdata->reserved_chanctx) | 658 | if (sdata->reserved_chanctx) { |
659 | if (sdata->reserved_chanctx->replace_state == | ||
660 | IEEE80211_CHANCTX_REPLACES_OTHER && | ||
661 | ieee80211_chanctx_num_reserved(local, | ||
662 | sdata->reserved_chanctx) > 1) | ||
663 | use_reserved_switch = true; | ||
664 | |||
636 | ieee80211_vif_unreserve_chanctx(sdata); | 665 | ieee80211_vif_unreserve_chanctx(sdata); |
666 | } | ||
637 | 667 | ||
638 | ieee80211_assign_vif_chanctx(sdata, NULL); | 668 | ieee80211_assign_vif_chanctx(sdata, NULL); |
639 | if (ieee80211_chanctx_refcount(local, ctx) == 0) | 669 | if (ieee80211_chanctx_refcount(local, ctx) == 0) |
640 | ieee80211_free_chanctx(local, ctx); | 670 | ieee80211_free_chanctx(local, ctx); |
671 | |||
672 | /* Unreserving may ready an in-place reservation. */ | ||
673 | if (use_reserved_switch) | ||
674 | ieee80211_vif_use_reserved_switch(local); | ||
641 | } | 675 | } |
642 | 676 | ||
643 | void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, | 677 | void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local, |
@@ -787,70 +821,6 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata, | |||
787 | return ret; | 821 | return ret; |
788 | } | 822 | } |
789 | 823 | ||
790 | static int __ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata, | ||
791 | struct ieee80211_chanctx *ctx, | ||
792 | u32 *changed) | ||
793 | { | ||
794 | struct ieee80211_local *local = sdata->local; | ||
795 | const struct cfg80211_chan_def *chandef = &sdata->csa_chandef; | ||
796 | u32 chanctx_changed = 0; | ||
797 | |||
798 | if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef, | ||
799 | IEEE80211_CHAN_DISABLED)) | ||
800 | return -EINVAL; | ||
801 | |||
802 | if (ieee80211_chanctx_refcount(local, ctx) != 1) | ||
803 | return -EINVAL; | ||
804 | |||
805 | if (sdata->vif.bss_conf.chandef.width != chandef->width) { | ||
806 | chanctx_changed = IEEE80211_CHANCTX_CHANGE_WIDTH; | ||
807 | *changed |= BSS_CHANGED_BANDWIDTH; | ||
808 | } | ||
809 | |||
810 | sdata->vif.bss_conf.chandef = *chandef; | ||
811 | ctx->conf.def = *chandef; | ||
812 | |||
813 | chanctx_changed |= IEEE80211_CHANCTX_CHANGE_CHANNEL; | ||
814 | drv_change_chanctx(local, ctx, chanctx_changed); | ||
815 | |||
816 | ieee80211_recalc_chanctx_chantype(local, ctx); | ||
817 | ieee80211_recalc_smps_chanctx(local, ctx); | ||
818 | ieee80211_recalc_radar_chanctx(local, ctx); | ||
819 | ieee80211_recalc_chanctx_min_def(local, ctx); | ||
820 | |||
821 | return 0; | ||
822 | } | ||
823 | |||
824 | int ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata, | ||
825 | u32 *changed) | ||
826 | { | ||
827 | struct ieee80211_local *local = sdata->local; | ||
828 | struct ieee80211_chanctx_conf *conf; | ||
829 | struct ieee80211_chanctx *ctx; | ||
830 | int ret; | ||
831 | |||
832 | lockdep_assert_held(&local->mtx); | ||
833 | |||
834 | /* should never be called if not performing a channel switch. */ | ||
835 | if (WARN_ON(!sdata->vif.csa_active)) | ||
836 | return -EINVAL; | ||
837 | |||
838 | mutex_lock(&local->chanctx_mtx); | ||
839 | conf = rcu_dereference_protected(sdata->vif.chanctx_conf, | ||
840 | lockdep_is_held(&local->chanctx_mtx)); | ||
841 | if (!conf) { | ||
842 | ret = -EINVAL; | ||
843 | goto out; | ||
844 | } | ||
845 | |||
846 | ctx = container_of(conf, struct ieee80211_chanctx, conf); | ||
847 | |||
848 | ret = __ieee80211_vif_change_channel(sdata, ctx, changed); | ||
849 | out: | ||
850 | mutex_unlock(&local->chanctx_mtx); | ||
851 | return ret; | ||
852 | } | ||
853 | |||
854 | static void | 824 | static void |
855 | __ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata, | 825 | __ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata, |
856 | bool clear) | 826 | bool clear) |
@@ -905,8 +875,25 @@ int ieee80211_vif_unreserve_chanctx(struct ieee80211_sub_if_data *sdata) | |||
905 | list_del(&sdata->reserved_chanctx_list); | 875 | list_del(&sdata->reserved_chanctx_list); |
906 | sdata->reserved_chanctx = NULL; | 876 | sdata->reserved_chanctx = NULL; |
907 | 877 | ||
908 | if (ieee80211_chanctx_refcount(sdata->local, ctx) == 0) | 878 | if (ieee80211_chanctx_refcount(sdata->local, ctx) == 0) { |
909 | ieee80211_free_chanctx(sdata->local, ctx); | 879 | if (ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER) { |
880 | if (WARN_ON(!ctx->replace_ctx)) | ||
881 | return -EINVAL; | ||
882 | |||
883 | WARN_ON(ctx->replace_ctx->replace_state != | ||
884 | IEEE80211_CHANCTX_WILL_BE_REPLACED); | ||
885 | WARN_ON(ctx->replace_ctx->replace_ctx != ctx); | ||
886 | |||
887 | ctx->replace_ctx->replace_ctx = NULL; | ||
888 | ctx->replace_ctx->replace_state = | ||
889 | IEEE80211_CHANCTX_REPLACE_NONE; | ||
890 | |||
891 | list_del_rcu(&ctx->list); | ||
892 | kfree_rcu(ctx, rcu_head); | ||
893 | } else { | ||
894 | ieee80211_free_chanctx(sdata->local, ctx); | ||
895 | } | ||
896 | } | ||
910 | 897 | ||
911 | return 0; | 898 | return 0; |
912 | } | 899 | } |
@@ -917,40 +904,84 @@ int ieee80211_vif_reserve_chanctx(struct ieee80211_sub_if_data *sdata, | |||
917 | bool radar_required) | 904 | bool radar_required) |
918 | { | 905 | { |
919 | struct ieee80211_local *local = sdata->local; | 906 | struct ieee80211_local *local = sdata->local; |
920 | struct ieee80211_chanctx_conf *conf; | 907 | struct ieee80211_chanctx *new_ctx, *curr_ctx, *ctx; |
921 | struct ieee80211_chanctx *new_ctx, *curr_ctx; | ||
922 | int ret = 0; | ||
923 | |||
924 | mutex_lock(&local->chanctx_mtx); | ||
925 | 908 | ||
926 | conf = rcu_dereference_protected(sdata->vif.chanctx_conf, | 909 | lockdep_assert_held(&local->chanctx_mtx); |
927 | lockdep_is_held(&local->chanctx_mtx)); | ||
928 | if (!conf) { | ||
929 | ret = -EINVAL; | ||
930 | goto out; | ||
931 | } | ||
932 | 910 | ||
933 | curr_ctx = container_of(conf, struct ieee80211_chanctx, conf); | 911 | curr_ctx = ieee80211_vif_get_chanctx(sdata); |
912 | if (curr_ctx && local->use_chanctx && !local->ops->switch_vif_chanctx) | ||
913 | return -ENOTSUPP; | ||
934 | 914 | ||
935 | new_ctx = ieee80211_find_reservation_chanctx(local, chandef, mode); | 915 | new_ctx = ieee80211_find_reservation_chanctx(local, chandef, mode); |
936 | if (!new_ctx) { | 916 | if (!new_ctx) { |
937 | if (ieee80211_chanctx_refcount(local, curr_ctx) == 1 && | 917 | if (ieee80211_can_create_new_chanctx(local)) { |
938 | (local->hw.flags & IEEE80211_HW_CHANGE_RUNNING_CHANCTX)) { | ||
939 | /* if we're the only users of the chanctx and | ||
940 | * the driver supports changing a running | ||
941 | * context, reserve our current context | ||
942 | */ | ||
943 | new_ctx = curr_ctx; | ||
944 | } else if (ieee80211_can_create_new_chanctx(local)) { | ||
945 | /* create a new context and reserve it */ | ||
946 | new_ctx = ieee80211_new_chanctx(local, chandef, mode); | 918 | new_ctx = ieee80211_new_chanctx(local, chandef, mode); |
947 | if (IS_ERR(new_ctx)) { | 919 | if (IS_ERR(new_ctx)) |
948 | ret = PTR_ERR(new_ctx); | 920 | return PTR_ERR(new_ctx); |
949 | goto out; | ||
950 | } | ||
951 | } else { | 921 | } else { |
952 | ret = -EBUSY; | 922 | if (!curr_ctx || |
953 | goto out; | 923 | (curr_ctx->replace_state == |
924 | IEEE80211_CHANCTX_WILL_BE_REPLACED) || | ||
925 | !list_empty(&curr_ctx->reserved_vifs)) { | ||
926 | /* | ||
927 | * Another vif already requested this context | ||
928 | * for a reservation. Find another one hoping | ||
929 | * all vifs assigned to it will also switch | ||
930 | * soon enough. | ||
931 | * | ||
932 | * TODO: This needs a little more work as some | ||
933 | * cases (more than 2 chanctx capable devices) | ||
934 | * may fail which could otherwise succeed | ||
935 | * provided some channel context juggling was | ||
936 | * performed. | ||
937 | * | ||
938 | * Consider ctx1..3, vif1..6, each ctx has 2 | ||
939 | * vifs. vif1 and vif2 from ctx1 request new | ||
940 | * different chandefs starting 2 in-place | ||
941 | * reserations with ctx4 and ctx5 replacing | ||
942 | * ctx1 and ctx2 respectively. Next vif5 and | ||
943 | * vif6 from ctx3 reserve ctx4. If vif3 and | ||
944 | * vif4 remain on ctx2 as they are then this | ||
945 | * fails unless `replace_ctx` from ctx5 is | ||
946 | * replaced with ctx3. | ||
947 | */ | ||
948 | list_for_each_entry(ctx, &local->chanctx_list, | ||
949 | list) { | ||
950 | if (ctx->replace_state != | ||
951 | IEEE80211_CHANCTX_REPLACE_NONE) | ||
952 | continue; | ||
953 | |||
954 | if (!list_empty(&ctx->reserved_vifs)) | ||
955 | continue; | ||
956 | |||
957 | curr_ctx = ctx; | ||
958 | break; | ||
959 | } | ||
960 | } | ||
961 | |||
962 | /* | ||
963 | * If that's true then all available contexts already | ||
964 | * have reservations and cannot be used. | ||
965 | */ | ||
966 | if (!curr_ctx || | ||
967 | (curr_ctx->replace_state == | ||
968 | IEEE80211_CHANCTX_WILL_BE_REPLACED) || | ||
969 | !list_empty(&curr_ctx->reserved_vifs)) | ||
970 | return -EBUSY; | ||
971 | |||
972 | new_ctx = ieee80211_alloc_chanctx(local, chandef, mode); | ||
973 | if (!new_ctx) | ||
974 | return -ENOMEM; | ||
975 | |||
976 | new_ctx->replace_ctx = curr_ctx; | ||
977 | new_ctx->replace_state = | ||
978 | IEEE80211_CHANCTX_REPLACES_OTHER; | ||
979 | |||
980 | curr_ctx->replace_ctx = new_ctx; | ||
981 | curr_ctx->replace_state = | ||
982 | IEEE80211_CHANCTX_WILL_BE_REPLACED; | ||
983 | |||
984 | list_add_rcu(&new_ctx->list, &local->chanctx_list); | ||
954 | } | 985 | } |
955 | } | 986 | } |
956 | 987 | ||
@@ -958,82 +989,601 @@ int ieee80211_vif_reserve_chanctx(struct ieee80211_sub_if_data *sdata, | |||
958 | sdata->reserved_chanctx = new_ctx; | 989 | sdata->reserved_chanctx = new_ctx; |
959 | sdata->reserved_chandef = *chandef; | 990 | sdata->reserved_chandef = *chandef; |
960 | sdata->reserved_radar_required = radar_required; | 991 | sdata->reserved_radar_required = radar_required; |
961 | out: | 992 | sdata->reserved_ready = false; |
962 | mutex_unlock(&local->chanctx_mtx); | 993 | |
963 | return ret; | 994 | return 0; |
964 | } | 995 | } |
965 | 996 | ||
966 | int ieee80211_vif_use_reserved_context(struct ieee80211_sub_if_data *sdata, | 997 | static void |
967 | u32 *changed) | 998 | ieee80211_vif_chanctx_reservation_complete(struct ieee80211_sub_if_data *sdata) |
968 | { | 999 | { |
969 | struct ieee80211_local *local = sdata->local; | 1000 | switch (sdata->vif.type) { |
970 | struct ieee80211_chanctx *ctx; | 1001 | case NL80211_IFTYPE_ADHOC: |
971 | struct ieee80211_chanctx *old_ctx; | 1002 | case NL80211_IFTYPE_AP: |
972 | struct ieee80211_chanctx_conf *conf; | 1003 | case NL80211_IFTYPE_MESH_POINT: |
973 | int ret; | 1004 | ieee80211_queue_work(&sdata->local->hw, |
974 | u32 tmp_changed = *changed; | 1005 | &sdata->csa_finalize_work); |
1006 | break; | ||
1007 | case NL80211_IFTYPE_STATION: | ||
1008 | ieee80211_queue_work(&sdata->local->hw, | ||
1009 | &sdata->u.mgd.chswitch_work); | ||
1010 | break; | ||
1011 | case NL80211_IFTYPE_UNSPECIFIED: | ||
1012 | case NL80211_IFTYPE_AP_VLAN: | ||
1013 | case NL80211_IFTYPE_WDS: | ||
1014 | case NL80211_IFTYPE_MONITOR: | ||
1015 | case NL80211_IFTYPE_P2P_CLIENT: | ||
1016 | case NL80211_IFTYPE_P2P_GO: | ||
1017 | case NL80211_IFTYPE_P2P_DEVICE: | ||
1018 | case NUM_NL80211_IFTYPES: | ||
1019 | WARN_ON(1); | ||
1020 | break; | ||
1021 | } | ||
1022 | } | ||
975 | 1023 | ||
976 | /* TODO: need to recheck if the chandef is usable etc.? */ | 1024 | static int |
1025 | ieee80211_vif_use_reserved_reassign(struct ieee80211_sub_if_data *sdata) | ||
1026 | { | ||
1027 | struct ieee80211_local *local = sdata->local; | ||
1028 | struct ieee80211_vif_chanctx_switch vif_chsw[1] = {}; | ||
1029 | struct ieee80211_chanctx *old_ctx, *new_ctx; | ||
1030 | const struct cfg80211_chan_def *chandef; | ||
1031 | u32 changed = 0; | ||
1032 | int err; | ||
977 | 1033 | ||
978 | lockdep_assert_held(&local->mtx); | 1034 | lockdep_assert_held(&local->mtx); |
1035 | lockdep_assert_held(&local->chanctx_mtx); | ||
979 | 1036 | ||
980 | mutex_lock(&local->chanctx_mtx); | 1037 | new_ctx = sdata->reserved_chanctx; |
1038 | old_ctx = ieee80211_vif_get_chanctx(sdata); | ||
981 | 1039 | ||
982 | ctx = sdata->reserved_chanctx; | 1040 | if (WARN_ON(!sdata->reserved_ready)) |
983 | if (WARN_ON(!ctx)) { | 1041 | return -EBUSY; |
984 | ret = -EINVAL; | 1042 | |
985 | goto out; | 1043 | if (WARN_ON(!new_ctx)) |
986 | } | 1044 | return -EINVAL; |
1045 | |||
1046 | if (WARN_ON(!old_ctx)) | ||
1047 | return -EINVAL; | ||
1048 | |||
1049 | if (WARN_ON(new_ctx->replace_state == | ||
1050 | IEEE80211_CHANCTX_REPLACES_OTHER)) | ||
1051 | return -EINVAL; | ||
1052 | |||
1053 | chandef = ieee80211_chanctx_non_reserved_chandef(local, new_ctx, | ||
1054 | &sdata->reserved_chandef); | ||
1055 | if (WARN_ON(!chandef)) | ||
1056 | return -EINVAL; | ||
1057 | |||
1058 | vif_chsw[0].vif = &sdata->vif; | ||
1059 | vif_chsw[0].old_ctx = &old_ctx->conf; | ||
1060 | vif_chsw[0].new_ctx = &new_ctx->conf; | ||
1061 | |||
1062 | list_del(&sdata->reserved_chanctx_list); | ||
1063 | sdata->reserved_chanctx = NULL; | ||
1064 | |||
1065 | err = drv_switch_vif_chanctx(local, vif_chsw, 1, | ||
1066 | CHANCTX_SWMODE_REASSIGN_VIF); | ||
1067 | if (err) { | ||
1068 | if (ieee80211_chanctx_refcount(local, new_ctx) == 0) | ||
1069 | ieee80211_free_chanctx(local, new_ctx); | ||
987 | 1070 | ||
988 | conf = rcu_dereference_protected(sdata->vif.chanctx_conf, | ||
989 | lockdep_is_held(&local->chanctx_mtx)); | ||
990 | if (!conf) { | ||
991 | ret = -EINVAL; | ||
992 | goto out; | 1071 | goto out; |
993 | } | 1072 | } |
994 | 1073 | ||
995 | old_ctx = container_of(conf, struct ieee80211_chanctx, conf); | 1074 | list_move(&sdata->assigned_chanctx_list, &new_ctx->assigned_vifs); |
1075 | rcu_assign_pointer(sdata->vif.chanctx_conf, &new_ctx->conf); | ||
1076 | |||
1077 | if (sdata->vif.type == NL80211_IFTYPE_AP) | ||
1078 | __ieee80211_vif_copy_chanctx_to_vlans(sdata, false); | ||
1079 | |||
1080 | if (ieee80211_chanctx_refcount(local, old_ctx) == 0) | ||
1081 | ieee80211_free_chanctx(local, old_ctx); | ||
996 | 1082 | ||
997 | if (sdata->vif.bss_conf.chandef.width != sdata->reserved_chandef.width) | 1083 | if (sdata->vif.bss_conf.chandef.width != sdata->reserved_chandef.width) |
998 | tmp_changed |= BSS_CHANGED_BANDWIDTH; | 1084 | changed = BSS_CHANGED_BANDWIDTH; |
999 | 1085 | ||
1000 | sdata->vif.bss_conf.chandef = sdata->reserved_chandef; | 1086 | sdata->vif.bss_conf.chandef = sdata->reserved_chandef; |
1001 | 1087 | ||
1002 | /* unref our reservation */ | 1088 | if (changed) |
1003 | sdata->reserved_chanctx = NULL; | 1089 | ieee80211_bss_info_change_notify(sdata, changed); |
1004 | sdata->radar_required = sdata->reserved_radar_required; | 1090 | |
1091 | out: | ||
1092 | ieee80211_vif_chanctx_reservation_complete(sdata); | ||
1093 | return err; | ||
1094 | } | ||
1095 | |||
1096 | static int | ||
1097 | ieee80211_vif_use_reserved_assign(struct ieee80211_sub_if_data *sdata) | ||
1098 | { | ||
1099 | struct ieee80211_local *local = sdata->local; | ||
1100 | struct ieee80211_chanctx *old_ctx, *new_ctx; | ||
1101 | const struct cfg80211_chan_def *chandef; | ||
1102 | int err; | ||
1103 | |||
1104 | old_ctx = ieee80211_vif_get_chanctx(sdata); | ||
1105 | new_ctx = sdata->reserved_chanctx; | ||
1106 | |||
1107 | if (WARN_ON(!sdata->reserved_ready)) | ||
1108 | return -EINVAL; | ||
1109 | |||
1110 | if (WARN_ON(old_ctx)) | ||
1111 | return -EINVAL; | ||
1112 | |||
1113 | if (WARN_ON(!new_ctx)) | ||
1114 | return -EINVAL; | ||
1115 | |||
1116 | if (WARN_ON(new_ctx->replace_state == | ||
1117 | IEEE80211_CHANCTX_REPLACES_OTHER)) | ||
1118 | return -EINVAL; | ||
1119 | |||
1120 | chandef = ieee80211_chanctx_non_reserved_chandef(local, new_ctx, | ||
1121 | &sdata->reserved_chandef); | ||
1122 | if (WARN_ON(!chandef)) | ||
1123 | return -EINVAL; | ||
1124 | |||
1005 | list_del(&sdata->reserved_chanctx_list); | 1125 | list_del(&sdata->reserved_chanctx_list); |
1126 | sdata->reserved_chanctx = NULL; | ||
1006 | 1127 | ||
1007 | if (old_ctx == ctx) { | 1128 | err = ieee80211_assign_vif_chanctx(sdata, new_ctx); |
1008 | /* This is our own context, just change it */ | 1129 | if (err) { |
1009 | ret = __ieee80211_vif_change_channel(sdata, old_ctx, | 1130 | if (ieee80211_chanctx_refcount(local, new_ctx) == 0) |
1010 | &tmp_changed); | 1131 | ieee80211_free_chanctx(local, new_ctx); |
1011 | if (ret) | 1132 | |
1012 | goto out; | 1133 | goto out; |
1013 | } else { | 1134 | } |
1014 | ret = ieee80211_assign_vif_chanctx(sdata, ctx); | 1135 | |
1015 | if (ieee80211_chanctx_refcount(local, old_ctx) == 0) | 1136 | out: |
1016 | ieee80211_free_chanctx(local, old_ctx); | 1137 | ieee80211_vif_chanctx_reservation_complete(sdata); |
1017 | if (ret) { | 1138 | return err; |
1018 | /* if assign fails refcount stays the same */ | 1139 | } |
1019 | if (ieee80211_chanctx_refcount(local, ctx) == 0) | 1140 | |
1020 | ieee80211_free_chanctx(local, ctx); | 1141 | static bool |
1142 | ieee80211_vif_has_in_place_reservation(struct ieee80211_sub_if_data *sdata) | ||
1143 | { | ||
1144 | struct ieee80211_chanctx *old_ctx, *new_ctx; | ||
1145 | |||
1146 | lockdep_assert_held(&sdata->local->chanctx_mtx); | ||
1147 | |||
1148 | new_ctx = sdata->reserved_chanctx; | ||
1149 | old_ctx = ieee80211_vif_get_chanctx(sdata); | ||
1150 | |||
1151 | if (!old_ctx) | ||
1152 | return false; | ||
1153 | |||
1154 | if (WARN_ON(!new_ctx)) | ||
1155 | return false; | ||
1156 | |||
1157 | if (old_ctx->replace_state != IEEE80211_CHANCTX_WILL_BE_REPLACED) | ||
1158 | return false; | ||
1159 | |||
1160 | if (new_ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER) | ||
1161 | return false; | ||
1162 | |||
1163 | return true; | ||
1164 | } | ||
1165 | |||
1166 | static int ieee80211_chsw_switch_hwconf(struct ieee80211_local *local, | ||
1167 | struct ieee80211_chanctx *new_ctx) | ||
1168 | { | ||
1169 | const struct cfg80211_chan_def *chandef; | ||
1170 | |||
1171 | lockdep_assert_held(&local->mtx); | ||
1172 | lockdep_assert_held(&local->chanctx_mtx); | ||
1173 | |||
1174 | chandef = ieee80211_chanctx_reserved_chandef(local, new_ctx, NULL); | ||
1175 | if (WARN_ON(!chandef)) | ||
1176 | return -EINVAL; | ||
1177 | |||
1178 | local->hw.conf.radar_enabled = new_ctx->conf.radar_enabled; | ||
1179 | local->_oper_chandef = *chandef; | ||
1180 | ieee80211_hw_config(local, 0); | ||
1181 | |||
1182 | return 0; | ||
1183 | } | ||
1184 | |||
1185 | static int ieee80211_chsw_switch_vifs(struct ieee80211_local *local, | ||
1186 | int n_vifs) | ||
1187 | { | ||
1188 | struct ieee80211_vif_chanctx_switch *vif_chsw; | ||
1189 | struct ieee80211_sub_if_data *sdata; | ||
1190 | struct ieee80211_chanctx *ctx, *old_ctx; | ||
1191 | int i, err; | ||
1192 | |||
1193 | lockdep_assert_held(&local->mtx); | ||
1194 | lockdep_assert_held(&local->chanctx_mtx); | ||
1195 | |||
1196 | vif_chsw = kzalloc(sizeof(vif_chsw[0]) * n_vifs, GFP_KERNEL); | ||
1197 | if (!vif_chsw) | ||
1198 | return -ENOMEM; | ||
1199 | |||
1200 | i = 0; | ||
1201 | list_for_each_entry(ctx, &local->chanctx_list, list) { | ||
1202 | if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER) | ||
1203 | continue; | ||
1204 | |||
1205 | if (WARN_ON(!ctx->replace_ctx)) { | ||
1206 | err = -EINVAL; | ||
1021 | goto out; | 1207 | goto out; |
1022 | } | 1208 | } |
1023 | 1209 | ||
1024 | if (sdata->vif.type == NL80211_IFTYPE_AP) | 1210 | list_for_each_entry(sdata, &ctx->reserved_vifs, |
1025 | __ieee80211_vif_copy_chanctx_to_vlans(sdata, false); | 1211 | reserved_chanctx_list) { |
1212 | if (!ieee80211_vif_has_in_place_reservation( | ||
1213 | sdata)) | ||
1214 | continue; | ||
1215 | |||
1216 | old_ctx = ieee80211_vif_get_chanctx(sdata); | ||
1217 | vif_chsw[i].vif = &sdata->vif; | ||
1218 | vif_chsw[i].old_ctx = &old_ctx->conf; | ||
1219 | vif_chsw[i].new_ctx = &ctx->conf; | ||
1220 | |||
1221 | i++; | ||
1222 | } | ||
1026 | } | 1223 | } |
1027 | 1224 | ||
1028 | *changed = tmp_changed; | 1225 | err = drv_switch_vif_chanctx(local, vif_chsw, n_vifs, |
1226 | CHANCTX_SWMODE_SWAP_CONTEXTS); | ||
1029 | 1227 | ||
1030 | ieee80211_recalc_chanctx_chantype(local, ctx); | ||
1031 | ieee80211_recalc_smps_chanctx(local, ctx); | ||
1032 | ieee80211_recalc_radar_chanctx(local, ctx); | ||
1033 | ieee80211_recalc_chanctx_min_def(local, ctx); | ||
1034 | out: | 1228 | out: |
1035 | mutex_unlock(&local->chanctx_mtx); | 1229 | kfree(vif_chsw); |
1036 | return ret; | 1230 | return err; |
1231 | } | ||
1232 | |||
1233 | static int ieee80211_chsw_switch_ctxs(struct ieee80211_local *local) | ||
1234 | { | ||
1235 | struct ieee80211_chanctx *ctx; | ||
1236 | int err; | ||
1237 | |||
1238 | lockdep_assert_held(&local->mtx); | ||
1239 | lockdep_assert_held(&local->chanctx_mtx); | ||
1240 | |||
1241 | list_for_each_entry(ctx, &local->chanctx_list, list) { | ||
1242 | if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER) | ||
1243 | continue; | ||
1244 | |||
1245 | if (!list_empty(&ctx->replace_ctx->assigned_vifs)) | ||
1246 | continue; | ||
1247 | |||
1248 | ieee80211_del_chanctx(local, ctx->replace_ctx); | ||
1249 | err = ieee80211_add_chanctx(local, ctx); | ||
1250 | if (err) | ||
1251 | goto err; | ||
1252 | } | ||
1253 | |||
1254 | return 0; | ||
1255 | |||
1256 | err: | ||
1257 | WARN_ON(ieee80211_add_chanctx(local, ctx)); | ||
1258 | list_for_each_entry_continue_reverse(ctx, &local->chanctx_list, list) { | ||
1259 | if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER) | ||
1260 | continue; | ||
1261 | |||
1262 | if (!list_empty(&ctx->replace_ctx->assigned_vifs)) | ||
1263 | continue; | ||
1264 | |||
1265 | ieee80211_del_chanctx(local, ctx); | ||
1266 | WARN_ON(ieee80211_add_chanctx(local, ctx->replace_ctx)); | ||
1267 | } | ||
1268 | |||
1269 | return err; | ||
1270 | } | ||
1271 | |||
1272 | int | ||
1273 | ieee80211_vif_use_reserved_switch(struct ieee80211_local *local) | ||
1274 | { | ||
1275 | struct ieee80211_sub_if_data *sdata, *sdata_tmp; | ||
1276 | struct ieee80211_chanctx *ctx, *ctx_tmp, *old_ctx; | ||
1277 | struct ieee80211_chanctx *new_ctx = NULL; | ||
1278 | int i, err, n_assigned, n_reserved, n_ready; | ||
1279 | int n_ctx = 0, n_vifs_switch = 0, n_vifs_assign = 0, n_vifs_ctxless = 0; | ||
1280 | |||
1281 | lockdep_assert_held(&local->mtx); | ||
1282 | lockdep_assert_held(&local->chanctx_mtx); | ||
1283 | |||
1284 | /* | ||
1285 | * If there are 2 independent pairs of channel contexts performing | ||
1286 | * cross-switch of their vifs this code will still wait until both are | ||
1287 | * ready even though it could be possible to switch one before the | ||
1288 | * other is ready. | ||
1289 | * | ||
1290 | * For practical reasons and code simplicity just do a single huge | ||
1291 | * switch. | ||
1292 | */ | ||
1293 | |||
1294 | /* | ||
1295 | * Verify if the reservation is still feasible. | ||
1296 | * - if it's not then disconnect | ||
1297 | * - if it is but not all vifs necessary are ready then defer | ||
1298 | */ | ||
1299 | |||
1300 | list_for_each_entry(ctx, &local->chanctx_list, list) { | ||
1301 | if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER) | ||
1302 | continue; | ||
1303 | |||
1304 | if (WARN_ON(!ctx->replace_ctx)) { | ||
1305 | err = -EINVAL; | ||
1306 | goto err; | ||
1307 | } | ||
1308 | |||
1309 | if (!local->use_chanctx) | ||
1310 | new_ctx = ctx; | ||
1311 | |||
1312 | n_ctx++; | ||
1313 | |||
1314 | n_assigned = 0; | ||
1315 | n_reserved = 0; | ||
1316 | n_ready = 0; | ||
1317 | |||
1318 | list_for_each_entry(sdata, &ctx->replace_ctx->assigned_vifs, | ||
1319 | assigned_chanctx_list) { | ||
1320 | n_assigned++; | ||
1321 | if (sdata->reserved_chanctx) { | ||
1322 | n_reserved++; | ||
1323 | if (sdata->reserved_ready) | ||
1324 | n_ready++; | ||
1325 | } | ||
1326 | } | ||
1327 | |||
1328 | if (n_assigned != n_reserved) { | ||
1329 | if (n_ready == n_reserved) { | ||
1330 | wiphy_info(local->hw.wiphy, | ||
1331 | "channel context reservation cannot be finalized because some interfaces aren't switching\n"); | ||
1332 | err = -EBUSY; | ||
1333 | goto err; | ||
1334 | } | ||
1335 | |||
1336 | return -EAGAIN; | ||
1337 | } | ||
1338 | |||
1339 | ctx->conf.radar_enabled = false; | ||
1340 | list_for_each_entry(sdata, &ctx->reserved_vifs, | ||
1341 | reserved_chanctx_list) { | ||
1342 | if (ieee80211_vif_has_in_place_reservation(sdata) && | ||
1343 | !sdata->reserved_ready) | ||
1344 | return -EAGAIN; | ||
1345 | |||
1346 | old_ctx = ieee80211_vif_get_chanctx(sdata); | ||
1347 | if (old_ctx) { | ||
1348 | if (old_ctx->replace_state == | ||
1349 | IEEE80211_CHANCTX_WILL_BE_REPLACED) | ||
1350 | n_vifs_switch++; | ||
1351 | else | ||
1352 | n_vifs_assign++; | ||
1353 | } else { | ||
1354 | n_vifs_ctxless++; | ||
1355 | } | ||
1356 | |||
1357 | if (sdata->reserved_radar_required) | ||
1358 | ctx->conf.radar_enabled = true; | ||
1359 | } | ||
1360 | } | ||
1361 | |||
1362 | if (WARN_ON(n_ctx == 0) || | ||
1363 | WARN_ON(n_vifs_switch == 0 && | ||
1364 | n_vifs_assign == 0 && | ||
1365 | n_vifs_ctxless == 0) || | ||
1366 | WARN_ON(n_ctx > 1 && !local->use_chanctx) || | ||
1367 | WARN_ON(!new_ctx && !local->use_chanctx)) { | ||
1368 | err = -EINVAL; | ||
1369 | goto err; | ||
1370 | } | ||
1371 | |||
1372 | /* | ||
1373 | * All necessary vifs are ready. Perform the switch now depending on | ||
1374 | * reservations and driver capabilities. | ||
1375 | */ | ||
1376 | |||
1377 | if (local->use_chanctx) { | ||
1378 | if (n_vifs_switch > 0) { | ||
1379 | err = ieee80211_chsw_switch_vifs(local, n_vifs_switch); | ||
1380 | if (err) | ||
1381 | goto err; | ||
1382 | } | ||
1383 | |||
1384 | if (n_vifs_assign > 0 || n_vifs_ctxless > 0) { | ||
1385 | err = ieee80211_chsw_switch_ctxs(local); | ||
1386 | if (err) | ||
1387 | goto err; | ||
1388 | } | ||
1389 | } else { | ||
1390 | err = ieee80211_chsw_switch_hwconf(local, new_ctx); | ||
1391 | if (err) | ||
1392 | goto err; | ||
1393 | } | ||
1394 | |||
1395 | /* | ||
1396 | * Update all structures, values and pointers to point to new channel | ||
1397 | * context(s). | ||
1398 | */ | ||
1399 | |||
1400 | i = 0; | ||
1401 | list_for_each_entry(ctx, &local->chanctx_list, list) { | ||
1402 | if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER) | ||
1403 | continue; | ||
1404 | |||
1405 | if (WARN_ON(!ctx->replace_ctx)) { | ||
1406 | err = -EINVAL; | ||
1407 | goto err; | ||
1408 | } | ||
1409 | |||
1410 | list_for_each_entry(sdata, &ctx->reserved_vifs, | ||
1411 | reserved_chanctx_list) { | ||
1412 | u32 changed = 0; | ||
1413 | |||
1414 | if (!ieee80211_vif_has_in_place_reservation(sdata)) | ||
1415 | continue; | ||
1416 | |||
1417 | rcu_assign_pointer(sdata->vif.chanctx_conf, &ctx->conf); | ||
1418 | |||
1419 | if (sdata->vif.type == NL80211_IFTYPE_AP) | ||
1420 | __ieee80211_vif_copy_chanctx_to_vlans(sdata, | ||
1421 | false); | ||
1422 | |||
1423 | sdata->radar_required = sdata->reserved_radar_required; | ||
1424 | |||
1425 | if (sdata->vif.bss_conf.chandef.width != | ||
1426 | sdata->reserved_chandef.width) | ||
1427 | changed = BSS_CHANGED_BANDWIDTH; | ||
1428 | |||
1429 | sdata->vif.bss_conf.chandef = sdata->reserved_chandef; | ||
1430 | if (changed) | ||
1431 | ieee80211_bss_info_change_notify(sdata, | ||
1432 | changed); | ||
1433 | |||
1434 | ieee80211_recalc_txpower(sdata); | ||
1435 | } | ||
1436 | |||
1437 | ieee80211_recalc_chanctx_chantype(local, ctx); | ||
1438 | ieee80211_recalc_smps_chanctx(local, ctx); | ||
1439 | ieee80211_recalc_radar_chanctx(local, ctx); | ||
1440 | ieee80211_recalc_chanctx_min_def(local, ctx); | ||
1441 | |||
1442 | list_for_each_entry_safe(sdata, sdata_tmp, &ctx->reserved_vifs, | ||
1443 | reserved_chanctx_list) { | ||
1444 | if (ieee80211_vif_get_chanctx(sdata) != ctx) | ||
1445 | continue; | ||
1446 | |||
1447 | list_del(&sdata->reserved_chanctx_list); | ||
1448 | list_move(&sdata->assigned_chanctx_list, | ||
1449 | &ctx->assigned_vifs); | ||
1450 | sdata->reserved_chanctx = NULL; | ||
1451 | |||
1452 | ieee80211_vif_chanctx_reservation_complete(sdata); | ||
1453 | } | ||
1454 | |||
1455 | /* | ||
1456 | * This context might have been a dependency for an already | ||
1457 | * ready re-assign reservation interface that was deferred. Do | ||
1458 | * not propagate error to the caller though. The in-place | ||
1459 | * reservation for originally requested interface has already | ||
1460 | * succeeded at this point. | ||
1461 | */ | ||
1462 | list_for_each_entry_safe(sdata, sdata_tmp, &ctx->reserved_vifs, | ||
1463 | reserved_chanctx_list) { | ||
1464 | if (WARN_ON(ieee80211_vif_has_in_place_reservation( | ||
1465 | sdata))) | ||
1466 | continue; | ||
1467 | |||
1468 | if (WARN_ON(sdata->reserved_chanctx != ctx)) | ||
1469 | continue; | ||
1470 | |||
1471 | if (!sdata->reserved_ready) | ||
1472 | continue; | ||
1473 | |||
1474 | if (ieee80211_vif_get_chanctx(sdata)) | ||
1475 | err = ieee80211_vif_use_reserved_reassign( | ||
1476 | sdata); | ||
1477 | else | ||
1478 | err = ieee80211_vif_use_reserved_assign(sdata); | ||
1479 | |||
1480 | if (err) { | ||
1481 | sdata_info(sdata, | ||
1482 | "failed to finalize (re-)assign reservation (err=%d)\n", | ||
1483 | err); | ||
1484 | ieee80211_vif_unreserve_chanctx(sdata); | ||
1485 | cfg80211_stop_iface(local->hw.wiphy, | ||
1486 | &sdata->wdev, | ||
1487 | GFP_KERNEL); | ||
1488 | } | ||
1489 | } | ||
1490 | } | ||
1491 | |||
1492 | /* | ||
1493 | * Finally free old contexts | ||
1494 | */ | ||
1495 | |||
1496 | list_for_each_entry_safe(ctx, ctx_tmp, &local->chanctx_list, list) { | ||
1497 | if (ctx->replace_state != IEEE80211_CHANCTX_WILL_BE_REPLACED) | ||
1498 | continue; | ||
1499 | |||
1500 | ctx->replace_ctx->replace_ctx = NULL; | ||
1501 | ctx->replace_ctx->replace_state = | ||
1502 | IEEE80211_CHANCTX_REPLACE_NONE; | ||
1503 | |||
1504 | list_del_rcu(&ctx->list); | ||
1505 | kfree_rcu(ctx, rcu_head); | ||
1506 | } | ||
1507 | |||
1508 | return 0; | ||
1509 | |||
1510 | err: | ||
1511 | list_for_each_entry(ctx, &local->chanctx_list, list) { | ||
1512 | if (ctx->replace_state != IEEE80211_CHANCTX_REPLACES_OTHER) | ||
1513 | continue; | ||
1514 | |||
1515 | list_for_each_entry_safe(sdata, sdata_tmp, &ctx->reserved_vifs, | ||
1516 | reserved_chanctx_list) { | ||
1517 | ieee80211_vif_unreserve_chanctx(sdata); | ||
1518 | ieee80211_vif_chanctx_reservation_complete(sdata); | ||
1519 | } | ||
1520 | } | ||
1521 | |||
1522 | return err; | ||
1523 | } | ||
1524 | |||
1525 | int ieee80211_vif_use_reserved_context(struct ieee80211_sub_if_data *sdata) | ||
1526 | { | ||
1527 | struct ieee80211_local *local = sdata->local; | ||
1528 | struct ieee80211_chanctx *new_ctx; | ||
1529 | struct ieee80211_chanctx *old_ctx; | ||
1530 | int err; | ||
1531 | |||
1532 | lockdep_assert_held(&local->mtx); | ||
1533 | lockdep_assert_held(&local->chanctx_mtx); | ||
1534 | |||
1535 | new_ctx = sdata->reserved_chanctx; | ||
1536 | old_ctx = ieee80211_vif_get_chanctx(sdata); | ||
1537 | |||
1538 | if (WARN_ON(!new_ctx)) | ||
1539 | return -EINVAL; | ||
1540 | |||
1541 | if (WARN_ON(new_ctx->replace_state == | ||
1542 | IEEE80211_CHANCTX_WILL_BE_REPLACED)) | ||
1543 | return -EINVAL; | ||
1544 | |||
1545 | if (WARN_ON(sdata->reserved_ready)) | ||
1546 | return -EINVAL; | ||
1547 | |||
1548 | sdata->reserved_ready = true; | ||
1549 | |||
1550 | if (new_ctx->replace_state == IEEE80211_CHANCTX_REPLACE_NONE) { | ||
1551 | if (old_ctx) | ||
1552 | err = ieee80211_vif_use_reserved_reassign(sdata); | ||
1553 | else | ||
1554 | err = ieee80211_vif_use_reserved_assign(sdata); | ||
1555 | |||
1556 | if (err) | ||
1557 | return err; | ||
1558 | } | ||
1559 | |||
1560 | /* | ||
1561 | * In-place reservation may need to be finalized now either if: | ||
1562 | * a) sdata is taking part in the swapping itself and is the last one | ||
1563 | * b) sdata has switched with a re-assign reservation to an existing | ||
1564 | * context readying in-place switching of old_ctx | ||
1565 | * | ||
1566 | * In case of (b) do not propagate the error up because the requested | ||
1567 | * sdata already switched successfully. Just spill an extra warning. | ||
1568 | * The ieee80211_vif_use_reserved_switch() already stops all necessary | ||
1569 | * interfaces upon failure. | ||
1570 | */ | ||
1571 | if ((old_ctx && | ||
1572 | old_ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED) || | ||
1573 | new_ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER) { | ||
1574 | err = ieee80211_vif_use_reserved_switch(local); | ||
1575 | if (err && err != -EAGAIN) { | ||
1576 | if (new_ctx->replace_state == | ||
1577 | IEEE80211_CHANCTX_REPLACES_OTHER) | ||
1578 | return err; | ||
1579 | |||
1580 | wiphy_info(local->hw.wiphy, | ||
1581 | "depending in-place reservation failed (err=%d)\n", | ||
1582 | err); | ||
1583 | } | ||
1584 | } | ||
1585 | |||
1586 | return 0; | ||
1037 | } | 1587 | } |
1038 | 1588 | ||
1039 | int ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata, | 1589 | int ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata, |
@@ -1043,6 +1593,7 @@ int ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata, | |||
1043 | struct ieee80211_local *local = sdata->local; | 1593 | struct ieee80211_local *local = sdata->local; |
1044 | struct ieee80211_chanctx_conf *conf; | 1594 | struct ieee80211_chanctx_conf *conf; |
1045 | struct ieee80211_chanctx *ctx; | 1595 | struct ieee80211_chanctx *ctx; |
1596 | const struct cfg80211_chan_def *compat; | ||
1046 | int ret; | 1597 | int ret; |
1047 | 1598 | ||
1048 | if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef, | 1599 | if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef, |
@@ -1069,11 +1620,33 @@ int ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata, | |||
1069 | } | 1620 | } |
1070 | 1621 | ||
1071 | ctx = container_of(conf, struct ieee80211_chanctx, conf); | 1622 | ctx = container_of(conf, struct ieee80211_chanctx, conf); |
1072 | if (!cfg80211_chandef_compatible(&conf->def, chandef)) { | 1623 | |
1624 | compat = cfg80211_chandef_compatible(&conf->def, chandef); | ||
1625 | if (!compat) { | ||
1073 | ret = -EINVAL; | 1626 | ret = -EINVAL; |
1074 | goto out; | 1627 | goto out; |
1075 | } | 1628 | } |
1076 | 1629 | ||
1630 | switch (ctx->replace_state) { | ||
1631 | case IEEE80211_CHANCTX_REPLACE_NONE: | ||
1632 | if (!ieee80211_chanctx_reserved_chandef(local, ctx, compat)) { | ||
1633 | ret = -EBUSY; | ||
1634 | goto out; | ||
1635 | } | ||
1636 | break; | ||
1637 | case IEEE80211_CHANCTX_WILL_BE_REPLACED: | ||
1638 | /* TODO: Perhaps the bandwith change could be treated as a | ||
1639 | * reservation itself? */ | ||
1640 | ret = -EBUSY; | ||
1641 | goto out; | ||
1642 | case IEEE80211_CHANCTX_REPLACES_OTHER: | ||
1643 | /* channel context that is going to replace another channel | ||
1644 | * context doesn't really exist and shouldn't be assigned | ||
1645 | * anywhere yet */ | ||
1646 | WARN_ON(1); | ||
1647 | break; | ||
1648 | } | ||
1649 | |||
1077 | sdata->vif.bss_conf.chandef = *chandef; | 1650 | sdata->vif.bss_conf.chandef = *chandef; |
1078 | 1651 | ||
1079 | ieee80211_recalc_chanctx_chantype(local, ctx); | 1652 | ieee80211_recalc_chanctx_chantype(local, ctx); |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 2ecb4deddb5d..86173c0de40e 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -124,7 +124,7 @@ static ssize_t sta_connected_time_read(struct file *file, char __user *userbuf, | |||
124 | long connected_time_secs; | 124 | long connected_time_secs; |
125 | char buf[100]; | 125 | char buf[100]; |
126 | int res; | 126 | int res; |
127 | do_posix_clock_monotonic_gettime(&uptime); | 127 | ktime_get_ts(&uptime); |
128 | connected_time_secs = uptime.tv_sec - sta->last_connected; | 128 | connected_time_secs = uptime.tv_sec - sta->last_connected; |
129 | time_to_tm(connected_time_secs, 0, &result); | 129 | time_to_tm(connected_time_secs, 0, &result); |
130 | result.tm_year -= 70; | 130 | result.tm_year -= 70; |
@@ -167,7 +167,7 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, | |||
167 | p += scnprintf(p, sizeof(buf) + buf - p, "next dialog_token: %#02x\n", | 167 | p += scnprintf(p, sizeof(buf) + buf - p, "next dialog_token: %#02x\n", |
168 | sta->ampdu_mlme.dialog_token_allocator + 1); | 168 | sta->ampdu_mlme.dialog_token_allocator + 1); |
169 | p += scnprintf(p, sizeof(buf) + buf - p, | 169 | p += scnprintf(p, sizeof(buf) + buf - p, |
170 | "TID\t\tRX active\tDTKN\tSSN\t\tTX\tDTKN\tpending\n"); | 170 | "TID\t\tRX\tDTKN\tSSN\t\tTX\tDTKN\tpending\n"); |
171 | 171 | ||
172 | for (i = 0; i < IEEE80211_NUM_TIDS; i++) { | 172 | for (i = 0; i < IEEE80211_NUM_TIDS; i++) { |
173 | tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[i]); | 173 | tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[i]); |
@@ -587,7 +587,6 @@ void ieee80211_sta_debugfs_add(struct sta_info *sta) | |||
587 | DEBUGFS_ADD_COUNTER(tx_filtered, tx_filtered_count); | 587 | DEBUGFS_ADD_COUNTER(tx_filtered, tx_filtered_count); |
588 | DEBUGFS_ADD_COUNTER(tx_retry_failed, tx_retry_failed); | 588 | DEBUGFS_ADD_COUNTER(tx_retry_failed, tx_retry_failed); |
589 | DEBUGFS_ADD_COUNTER(tx_retry_count, tx_retry_count); | 589 | DEBUGFS_ADD_COUNTER(tx_retry_count, tx_retry_count); |
590 | DEBUGFS_ADD_COUNTER(wep_weak_iv_count, wep_weak_iv_count); | ||
591 | 590 | ||
592 | if (sizeof(sta->driver_buffered_tids) == sizeof(u32)) | 591 | if (sizeof(sta->driver_buffered_tids) == sizeof(u32)) |
593 | debugfs_create_x32("driver_buffered_tids", 0400, | 592 | debugfs_create_x32("driver_buffered_tids", 0400, |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index bd782dcffcc7..11423958116a 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
@@ -314,7 +314,7 @@ static inline void drv_update_tkip_key(struct ieee80211_local *local, | |||
314 | 314 | ||
315 | static inline int drv_hw_scan(struct ieee80211_local *local, | 315 | static inline int drv_hw_scan(struct ieee80211_local *local, |
316 | struct ieee80211_sub_if_data *sdata, | 316 | struct ieee80211_sub_if_data *sdata, |
317 | struct cfg80211_scan_request *req) | 317 | struct ieee80211_scan_request *req) |
318 | { | 318 | { |
319 | int ret; | 319 | int ret; |
320 | 320 | ||
@@ -346,7 +346,7 @@ static inline int | |||
346 | drv_sched_scan_start(struct ieee80211_local *local, | 346 | drv_sched_scan_start(struct ieee80211_local *local, |
347 | struct ieee80211_sub_if_data *sdata, | 347 | struct ieee80211_sub_if_data *sdata, |
348 | struct cfg80211_sched_scan_request *req, | 348 | struct cfg80211_sched_scan_request *req, |
349 | struct ieee80211_sched_scan_ies *ies) | 349 | struct ieee80211_scan_ies *ies) |
350 | { | 350 | { |
351 | int ret; | 351 | int ret; |
352 | 352 | ||
@@ -970,6 +970,22 @@ static inline void drv_mgd_prepare_tx(struct ieee80211_local *local, | |||
970 | trace_drv_return_void(local); | 970 | trace_drv_return_void(local); |
971 | } | 971 | } |
972 | 972 | ||
973 | static inline void | ||
974 | drv_mgd_protect_tdls_discover(struct ieee80211_local *local, | ||
975 | struct ieee80211_sub_if_data *sdata) | ||
976 | { | ||
977 | might_sleep(); | ||
978 | |||
979 | if (!check_sdata_in_driver(sdata)) | ||
980 | return; | ||
981 | WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION); | ||
982 | |||
983 | trace_drv_mgd_protect_tdls_discover(local, sdata); | ||
984 | if (local->ops->mgd_protect_tdls_discover) | ||
985 | local->ops->mgd_protect_tdls_discover(&local->hw, &sdata->vif); | ||
986 | trace_drv_return_void(local); | ||
987 | } | ||
988 | |||
973 | static inline int drv_add_chanctx(struct ieee80211_local *local, | 989 | static inline int drv_add_chanctx(struct ieee80211_local *local, |
974 | struct ieee80211_chanctx *ctx) | 990 | struct ieee80211_chanctx *ctx) |
975 | { | 991 | { |
diff --git a/net/mac80211/ethtool.c b/net/mac80211/ethtool.c new file mode 100644 index 000000000000..ebfc8091557b --- /dev/null +++ b/net/mac80211/ethtool.c | |||
@@ -0,0 +1,244 @@ | |||
1 | /* | ||
2 | * mac80211 ethtool hooks for cfg80211 | ||
3 | * | ||
4 | * Copied from cfg.c - originally | ||
5 | * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net> | ||
6 | * Copyright 2014 Intel Corporation (Author: Johannes Berg) | ||
7 | * | ||
8 | * This file is GPLv2 as found in COPYING. | ||
9 | */ | ||
10 | #include <linux/types.h> | ||
11 | #include <net/cfg80211.h> | ||
12 | #include "ieee80211_i.h" | ||
13 | #include "sta_info.h" | ||
14 | #include "driver-ops.h" | ||
15 | |||
16 | static int ieee80211_set_ringparam(struct net_device *dev, | ||
17 | struct ethtool_ringparam *rp) | ||
18 | { | ||
19 | struct ieee80211_local *local = wiphy_priv(dev->ieee80211_ptr->wiphy); | ||
20 | |||
21 | if (rp->rx_mini_pending != 0 || rp->rx_jumbo_pending != 0) | ||
22 | return -EINVAL; | ||
23 | |||
24 | return drv_set_ringparam(local, rp->tx_pending, rp->rx_pending); | ||
25 | } | ||
26 | |||
27 | static void ieee80211_get_ringparam(struct net_device *dev, | ||
28 | struct ethtool_ringparam *rp) | ||
29 | { | ||
30 | struct ieee80211_local *local = wiphy_priv(dev->ieee80211_ptr->wiphy); | ||
31 | |||
32 | memset(rp, 0, sizeof(*rp)); | ||
33 | |||
34 | drv_get_ringparam(local, &rp->tx_pending, &rp->tx_max_pending, | ||
35 | &rp->rx_pending, &rp->rx_max_pending); | ||
36 | } | ||
37 | |||
38 | static const char ieee80211_gstrings_sta_stats[][ETH_GSTRING_LEN] = { | ||
39 | "rx_packets", "rx_bytes", | ||
40 | "rx_duplicates", "rx_fragments", "rx_dropped", | ||
41 | "tx_packets", "tx_bytes", "tx_fragments", | ||
42 | "tx_filtered", "tx_retry_failed", "tx_retries", | ||
43 | "beacon_loss", "sta_state", "txrate", "rxrate", "signal", | ||
44 | "channel", "noise", "ch_time", "ch_time_busy", | ||
45 | "ch_time_ext_busy", "ch_time_rx", "ch_time_tx" | ||
46 | }; | ||
47 | #define STA_STATS_LEN ARRAY_SIZE(ieee80211_gstrings_sta_stats) | ||
48 | |||
49 | static int ieee80211_get_sset_count(struct net_device *dev, int sset) | ||
50 | { | ||
51 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
52 | int rv = 0; | ||
53 | |||
54 | if (sset == ETH_SS_STATS) | ||
55 | rv += STA_STATS_LEN; | ||
56 | |||
57 | rv += drv_get_et_sset_count(sdata, sset); | ||
58 | |||
59 | if (rv == 0) | ||
60 | return -EOPNOTSUPP; | ||
61 | return rv; | ||
62 | } | ||
63 | |||
64 | static void ieee80211_get_stats(struct net_device *dev, | ||
65 | struct ethtool_stats *stats, | ||
66 | u64 *data) | ||
67 | { | ||
68 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
69 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
70 | struct ieee80211_channel *channel; | ||
71 | struct sta_info *sta; | ||
72 | struct ieee80211_local *local = sdata->local; | ||
73 | struct station_info sinfo; | ||
74 | struct survey_info survey; | ||
75 | int i, q; | ||
76 | #define STA_STATS_SURVEY_LEN 7 | ||
77 | |||
78 | memset(data, 0, sizeof(u64) * STA_STATS_LEN); | ||
79 | |||
80 | #define ADD_STA_STATS(sta) \ | ||
81 | do { \ | ||
82 | data[i++] += sta->rx_packets; \ | ||
83 | data[i++] += sta->rx_bytes; \ | ||
84 | data[i++] += sta->num_duplicates; \ | ||
85 | data[i++] += sta->rx_fragments; \ | ||
86 | data[i++] += sta->rx_dropped; \ | ||
87 | \ | ||
88 | data[i++] += sinfo.tx_packets; \ | ||
89 | data[i++] += sinfo.tx_bytes; \ | ||
90 | data[i++] += sta->tx_fragments; \ | ||
91 | data[i++] += sta->tx_filtered_count; \ | ||
92 | data[i++] += sta->tx_retry_failed; \ | ||
93 | data[i++] += sta->tx_retry_count; \ | ||
94 | data[i++] += sta->beacon_loss_count; \ | ||
95 | } while (0) | ||
96 | |||
97 | /* For Managed stations, find the single station based on BSSID | ||
98 | * and use that. For interface types, iterate through all available | ||
99 | * stations and add stats for any station that is assigned to this | ||
100 | * network device. | ||
101 | */ | ||
102 | |||
103 | mutex_lock(&local->sta_mtx); | ||
104 | |||
105 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
106 | sta = sta_info_get_bss(sdata, sdata->u.mgd.bssid); | ||
107 | |||
108 | if (!(sta && !WARN_ON(sta->sdata->dev != dev))) | ||
109 | goto do_survey; | ||
110 | |||
111 | sinfo.filled = 0; | ||
112 | sta_set_sinfo(sta, &sinfo); | ||
113 | |||
114 | i = 0; | ||
115 | ADD_STA_STATS(sta); | ||
116 | |||
117 | data[i++] = sta->sta_state; | ||
118 | |||
119 | |||
120 | if (sinfo.filled & STATION_INFO_TX_BITRATE) | ||
121 | data[i] = 100000 * | ||
122 | cfg80211_calculate_bitrate(&sinfo.txrate); | ||
123 | i++; | ||
124 | if (sinfo.filled & STATION_INFO_RX_BITRATE) | ||
125 | data[i] = 100000 * | ||
126 | cfg80211_calculate_bitrate(&sinfo.rxrate); | ||
127 | i++; | ||
128 | |||
129 | if (sinfo.filled & STATION_INFO_SIGNAL_AVG) | ||
130 | data[i] = (u8)sinfo.signal_avg; | ||
131 | i++; | ||
132 | } else { | ||
133 | list_for_each_entry(sta, &local->sta_list, list) { | ||
134 | /* Make sure this station belongs to the proper dev */ | ||
135 | if (sta->sdata->dev != dev) | ||
136 | continue; | ||
137 | |||
138 | sinfo.filled = 0; | ||
139 | sta_set_sinfo(sta, &sinfo); | ||
140 | i = 0; | ||
141 | ADD_STA_STATS(sta); | ||
142 | } | ||
143 | } | ||
144 | |||
145 | do_survey: | ||
146 | i = STA_STATS_LEN - STA_STATS_SURVEY_LEN; | ||
147 | /* Get survey stats for current channel */ | ||
148 | survey.filled = 0; | ||
149 | |||
150 | rcu_read_lock(); | ||
151 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
152 | if (chanctx_conf) | ||
153 | channel = chanctx_conf->def.chan; | ||
154 | else | ||
155 | channel = NULL; | ||
156 | rcu_read_unlock(); | ||
157 | |||
158 | if (channel) { | ||
159 | q = 0; | ||
160 | do { | ||
161 | survey.filled = 0; | ||
162 | if (drv_get_survey(local, q, &survey) != 0) { | ||
163 | survey.filled = 0; | ||
164 | break; | ||
165 | } | ||
166 | q++; | ||
167 | } while (channel != survey.channel); | ||
168 | } | ||
169 | |||
170 | if (survey.filled) | ||
171 | data[i++] = survey.channel->center_freq; | ||
172 | else | ||
173 | data[i++] = 0; | ||
174 | if (survey.filled & SURVEY_INFO_NOISE_DBM) | ||
175 | data[i++] = (u8)survey.noise; | ||
176 | else | ||
177 | data[i++] = -1LL; | ||
178 | if (survey.filled & SURVEY_INFO_CHANNEL_TIME) | ||
179 | data[i++] = survey.channel_time; | ||
180 | else | ||
181 | data[i++] = -1LL; | ||
182 | if (survey.filled & SURVEY_INFO_CHANNEL_TIME_BUSY) | ||
183 | data[i++] = survey.channel_time_busy; | ||
184 | else | ||
185 | data[i++] = -1LL; | ||
186 | if (survey.filled & SURVEY_INFO_CHANNEL_TIME_EXT_BUSY) | ||
187 | data[i++] = survey.channel_time_ext_busy; | ||
188 | else | ||
189 | data[i++] = -1LL; | ||
190 | if (survey.filled & SURVEY_INFO_CHANNEL_TIME_RX) | ||
191 | data[i++] = survey.channel_time_rx; | ||
192 | else | ||
193 | data[i++] = -1LL; | ||
194 | if (survey.filled & SURVEY_INFO_CHANNEL_TIME_TX) | ||
195 | data[i++] = survey.channel_time_tx; | ||
196 | else | ||
197 | data[i++] = -1LL; | ||
198 | |||
199 | mutex_unlock(&local->sta_mtx); | ||
200 | |||
201 | if (WARN_ON(i != STA_STATS_LEN)) | ||
202 | return; | ||
203 | |||
204 | drv_get_et_stats(sdata, stats, &(data[STA_STATS_LEN])); | ||
205 | } | ||
206 | |||
207 | static void ieee80211_get_strings(struct net_device *dev, u32 sset, u8 *data) | ||
208 | { | ||
209 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
210 | int sz_sta_stats = 0; | ||
211 | |||
212 | if (sset == ETH_SS_STATS) { | ||
213 | sz_sta_stats = sizeof(ieee80211_gstrings_sta_stats); | ||
214 | memcpy(data, ieee80211_gstrings_sta_stats, sz_sta_stats); | ||
215 | } | ||
216 | drv_get_et_strings(sdata, sset, &(data[sz_sta_stats])); | ||
217 | } | ||
218 | |||
219 | static int ieee80211_get_regs_len(struct net_device *dev) | ||
220 | { | ||
221 | return 0; | ||
222 | } | ||
223 | |||
224 | static void ieee80211_get_regs(struct net_device *dev, | ||
225 | struct ethtool_regs *regs, | ||
226 | void *data) | ||
227 | { | ||
228 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
229 | |||
230 | regs->version = wdev->wiphy->hw_version; | ||
231 | regs->len = 0; | ||
232 | } | ||
233 | |||
234 | const struct ethtool_ops ieee80211_ethtool_ops = { | ||
235 | .get_drvinfo = cfg80211_get_drvinfo, | ||
236 | .get_regs_len = ieee80211_get_regs_len, | ||
237 | .get_regs = ieee80211_get_regs, | ||
238 | .get_link = ethtool_op_get_link, | ||
239 | .get_ringparam = ieee80211_get_ringparam, | ||
240 | .set_ringparam = ieee80211_set_ringparam, | ||
241 | .get_strings = ieee80211_get_strings, | ||
242 | .get_ethtool_stats = ieee80211_get_stats, | ||
243 | .get_sset_count = ieee80211_get_sset_count, | ||
244 | }; | ||
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 15702ff64a4c..ff630be2ca75 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -150,13 +150,12 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, | |||
150 | 150 | ||
151 | /* | 151 | /* |
152 | * If user has specified capability over-rides, take care | 152 | * If user has specified capability over-rides, take care |
153 | * of that if the station we're setting up is the AP that | 153 | * of that if the station we're setting up is the AP or TDLS peer that |
154 | * we advertised a restricted capability set to. Override | 154 | * we advertised a restricted capability set to. Override |
155 | * our own capabilities and then use those below. | 155 | * our own capabilities and then use those below. |
156 | */ | 156 | */ |
157 | if ((sdata->vif.type == NL80211_IFTYPE_STATION || | 157 | if (sdata->vif.type == NL80211_IFTYPE_STATION || |
158 | sdata->vif.type == NL80211_IFTYPE_ADHOC) && | 158 | sdata->vif.type == NL80211_IFTYPE_ADHOC) |
159 | !test_sta_flag(sta, WLAN_STA_TDLS_PEER)) | ||
160 | ieee80211_apply_htcap_overrides(sdata, &own_cap); | 159 | ieee80211_apply_htcap_overrides(sdata, &own_cap); |
161 | 160 | ||
162 | /* | 161 | /* |
@@ -228,6 +227,9 @@ bool ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_sub_if_data *sdata, | |||
228 | if (own_cap.mcs.rx_mask[32/8] & ht_cap_ie->mcs.rx_mask[32/8] & 1) | 227 | if (own_cap.mcs.rx_mask[32/8] & ht_cap_ie->mcs.rx_mask[32/8] & 1) |
229 | ht_cap.mcs.rx_mask[32/8] |= 1; | 228 | ht_cap.mcs.rx_mask[32/8] |= 1; |
230 | 229 | ||
230 | /* set Rx highest rate */ | ||
231 | ht_cap.mcs.rx_highest = ht_cap_ie->mcs.rx_highest; | ||
232 | |||
231 | apply: | 233 | apply: |
232 | changed = memcmp(&sta->sta.ht_cap, &ht_cap, sizeof(ht_cap)); | 234 | changed = memcmp(&sta->sta.ht_cap, &ht_cap, sizeof(ht_cap)); |
233 | 235 | ||
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 18ee0a256b1e..9713dc54ea4b 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
@@ -143,7 +143,7 @@ ieee80211_ibss_build_presp(struct ieee80211_sub_if_data *sdata, | |||
143 | *pos++ = csa_settings->block_tx ? 1 : 0; | 143 | *pos++ = csa_settings->block_tx ? 1 : 0; |
144 | *pos++ = ieee80211_frequency_to_channel( | 144 | *pos++ = ieee80211_frequency_to_channel( |
145 | csa_settings->chandef.chan->center_freq); | 145 | csa_settings->chandef.chan->center_freq); |
146 | sdata->csa_counter_offset_beacon[0] = (pos - presp->head); | 146 | presp->csa_counter_offsets[0] = (pos - presp->head); |
147 | *pos++ = csa_settings->count; | 147 | *pos++ = csa_settings->count; |
148 | } | 148 | } |
149 | 149 | ||
@@ -189,17 +189,8 @@ ieee80211_ibss_build_presp(struct ieee80211_sub_if_data *sdata, | |||
189 | chandef, 0); | 189 | chandef, 0); |
190 | } | 190 | } |
191 | 191 | ||
192 | if (local->hw.queues >= IEEE80211_NUM_ACS) { | 192 | if (local->hw.queues >= IEEE80211_NUM_ACS) |
193 | *pos++ = WLAN_EID_VENDOR_SPECIFIC; | 193 | pos = ieee80211_add_wmm_info_ie(pos, 0); /* U-APSD not in use */ |
194 | *pos++ = 7; /* len */ | ||
195 | *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */ | ||
196 | *pos++ = 0x50; | ||
197 | *pos++ = 0xf2; | ||
198 | *pos++ = 2; /* WME */ | ||
199 | *pos++ = 0; /* WME info */ | ||
200 | *pos++ = 1; /* WME ver */ | ||
201 | *pos++ = 0; /* U-APSD no in use */ | ||
202 | } | ||
203 | 194 | ||
204 | presp->head_len = pos - presp->head; | 195 | presp->head_len = pos - presp->head; |
205 | if (WARN_ON(presp->head_len > frame_len)) | 196 | if (WARN_ON(presp->head_len > frame_len)) |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index ac9836e0aab3..ef7a089ac546 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -229,16 +229,29 @@ struct ieee80211_rx_data { | |||
229 | u16 tkip_iv16; | 229 | u16 tkip_iv16; |
230 | }; | 230 | }; |
231 | 231 | ||
232 | struct ieee80211_csa_settings { | ||
233 | const u16 *counter_offsets_beacon; | ||
234 | const u16 *counter_offsets_presp; | ||
235 | |||
236 | int n_counter_offsets_beacon; | ||
237 | int n_counter_offsets_presp; | ||
238 | |||
239 | u8 count; | ||
240 | }; | ||
241 | |||
232 | struct beacon_data { | 242 | struct beacon_data { |
233 | u8 *head, *tail; | 243 | u8 *head, *tail; |
234 | int head_len, tail_len; | 244 | int head_len, tail_len; |
235 | struct ieee80211_meshconf_ie *meshconf; | 245 | struct ieee80211_meshconf_ie *meshconf; |
246 | u16 csa_counter_offsets[IEEE80211_MAX_CSA_COUNTERS_NUM]; | ||
247 | u8 csa_current_counter; | ||
236 | struct rcu_head rcu_head; | 248 | struct rcu_head rcu_head; |
237 | }; | 249 | }; |
238 | 250 | ||
239 | struct probe_resp { | 251 | struct probe_resp { |
240 | struct rcu_head rcu_head; | 252 | struct rcu_head rcu_head; |
241 | int len; | 253 | int len; |
254 | u16 csa_counter_offsets[IEEE80211_MAX_CSA_COUNTERS_NUM]; | ||
242 | u8 data[0]; | 255 | u8 data[0]; |
243 | }; | 256 | }; |
244 | 257 | ||
@@ -332,7 +345,6 @@ enum ieee80211_sta_flags { | |||
332 | IEEE80211_STA_CONNECTION_POLL = BIT(1), | 345 | IEEE80211_STA_CONNECTION_POLL = BIT(1), |
333 | IEEE80211_STA_CONTROL_PORT = BIT(2), | 346 | IEEE80211_STA_CONTROL_PORT = BIT(2), |
334 | IEEE80211_STA_DISABLE_HT = BIT(4), | 347 | IEEE80211_STA_DISABLE_HT = BIT(4), |
335 | IEEE80211_STA_CSA_RECEIVED = BIT(5), | ||
336 | IEEE80211_STA_MFP_ENABLED = BIT(6), | 348 | IEEE80211_STA_MFP_ENABLED = BIT(6), |
337 | IEEE80211_STA_UAPSD_ENABLED = BIT(7), | 349 | IEEE80211_STA_UAPSD_ENABLED = BIT(7), |
338 | IEEE80211_STA_NULLFUNC_ACKED = BIT(8), | 350 | IEEE80211_STA_NULLFUNC_ACKED = BIT(8), |
@@ -490,6 +502,9 @@ struct ieee80211_if_managed { | |||
490 | struct ieee80211_ht_cap ht_capa_mask; /* Valid parts of ht_capa */ | 502 | struct ieee80211_ht_cap ht_capa_mask; /* Valid parts of ht_capa */ |
491 | struct ieee80211_vht_cap vht_capa; /* configured VHT overrides */ | 503 | struct ieee80211_vht_cap vht_capa; /* configured VHT overrides */ |
492 | struct ieee80211_vht_cap vht_capa_mask; /* Valid parts of vht_capa */ | 504 | struct ieee80211_vht_cap vht_capa_mask; /* Valid parts of vht_capa */ |
505 | |||
506 | u8 tdls_peer[ETH_ALEN] __aligned(2); | ||
507 | struct delayed_work tdls_peer_del_work; | ||
493 | }; | 508 | }; |
494 | 509 | ||
495 | struct ieee80211_if_ibss { | 510 | struct ieee80211_if_ibss { |
@@ -688,6 +703,24 @@ enum ieee80211_chanctx_mode { | |||
688 | IEEE80211_CHANCTX_EXCLUSIVE | 703 | IEEE80211_CHANCTX_EXCLUSIVE |
689 | }; | 704 | }; |
690 | 705 | ||
706 | /** | ||
707 | * enum ieee80211_chanctx_replace_state - channel context replacement state | ||
708 | * | ||
709 | * This is used for channel context in-place reservations that require channel | ||
710 | * context switch/swap. | ||
711 | * | ||
712 | * @IEEE80211_CHANCTX_REPLACE_NONE: no replacement is taking place | ||
713 | * @IEEE80211_CHANCTX_WILL_BE_REPLACED: this channel context will be replaced | ||
714 | * by a (not yet registered) channel context pointed by %replace_ctx. | ||
715 | * @IEEE80211_CHANCTX_REPLACES_OTHER: this (not yet registered) channel context | ||
716 | * replaces an existing channel context pointed to by %replace_ctx. | ||
717 | */ | ||
718 | enum ieee80211_chanctx_replace_state { | ||
719 | IEEE80211_CHANCTX_REPLACE_NONE, | ||
720 | IEEE80211_CHANCTX_WILL_BE_REPLACED, | ||
721 | IEEE80211_CHANCTX_REPLACES_OTHER, | ||
722 | }; | ||
723 | |||
691 | struct ieee80211_chanctx { | 724 | struct ieee80211_chanctx { |
692 | struct list_head list; | 725 | struct list_head list; |
693 | struct rcu_head rcu_head; | 726 | struct rcu_head rcu_head; |
@@ -695,6 +728,9 @@ struct ieee80211_chanctx { | |||
695 | struct list_head assigned_vifs; | 728 | struct list_head assigned_vifs; |
696 | struct list_head reserved_vifs; | 729 | struct list_head reserved_vifs; |
697 | 730 | ||
731 | enum ieee80211_chanctx_replace_state replace_state; | ||
732 | struct ieee80211_chanctx *replace_ctx; | ||
733 | |||
698 | enum ieee80211_chanctx_mode mode; | 734 | enum ieee80211_chanctx_mode mode; |
699 | bool driver_present; | 735 | bool driver_present; |
700 | 736 | ||
@@ -754,9 +790,6 @@ struct ieee80211_sub_if_data { | |||
754 | struct mac80211_qos_map __rcu *qos_map; | 790 | struct mac80211_qos_map __rcu *qos_map; |
755 | 791 | ||
756 | struct work_struct csa_finalize_work; | 792 | struct work_struct csa_finalize_work; |
757 | u16 csa_counter_offset_beacon[IEEE80211_MAX_CSA_COUNTERS_NUM]; | ||
758 | u16 csa_counter_offset_presp[IEEE80211_MAX_CSA_COUNTERS_NUM]; | ||
759 | bool csa_radar_required; | ||
760 | bool csa_block_tx; /* write-protected by sdata_lock and local->mtx */ | 793 | bool csa_block_tx; /* write-protected by sdata_lock and local->mtx */ |
761 | struct cfg80211_chan_def csa_chandef; | 794 | struct cfg80211_chan_def csa_chandef; |
762 | 795 | ||
@@ -767,7 +800,7 @@ struct ieee80211_sub_if_data { | |||
767 | struct ieee80211_chanctx *reserved_chanctx; | 800 | struct ieee80211_chanctx *reserved_chanctx; |
768 | struct cfg80211_chan_def reserved_chandef; | 801 | struct cfg80211_chan_def reserved_chandef; |
769 | bool reserved_radar_required; | 802 | bool reserved_radar_required; |
770 | u8 csa_current_counter; | 803 | bool reserved_ready; |
771 | 804 | ||
772 | /* used to reconfigure hardware SM PS */ | 805 | /* used to reconfigure hardware SM PS */ |
773 | struct work_struct recalc_smps; | 806 | struct work_struct recalc_smps; |
@@ -892,10 +925,17 @@ ieee80211_vif_get_shift(struct ieee80211_vif *vif) | |||
892 | return shift; | 925 | return shift; |
893 | } | 926 | } |
894 | 927 | ||
928 | struct ieee80211_rx_agg { | ||
929 | u8 addr[ETH_ALEN]; | ||
930 | u16 tid; | ||
931 | }; | ||
932 | |||
895 | enum sdata_queue_type { | 933 | enum sdata_queue_type { |
896 | IEEE80211_SDATA_QUEUE_TYPE_FRAME = 0, | 934 | IEEE80211_SDATA_QUEUE_TYPE_FRAME = 0, |
897 | IEEE80211_SDATA_QUEUE_AGG_START = 1, | 935 | IEEE80211_SDATA_QUEUE_AGG_START = 1, |
898 | IEEE80211_SDATA_QUEUE_AGG_STOP = 2, | 936 | IEEE80211_SDATA_QUEUE_AGG_STOP = 2, |
937 | IEEE80211_SDATA_QUEUE_RX_AGG_START = 3, | ||
938 | IEEE80211_SDATA_QUEUE_RX_AGG_STOP = 4, | ||
899 | }; | 939 | }; |
900 | 940 | ||
901 | enum { | 941 | enum { |
@@ -912,6 +952,9 @@ enum queue_stop_reason { | |||
912 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD, | 952 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD, |
913 | IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL, | 953 | IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL, |
914 | IEEE80211_QUEUE_STOP_REASON_FLUSH, | 954 | IEEE80211_QUEUE_STOP_REASON_FLUSH, |
955 | IEEE80211_QUEUE_STOP_REASON_TDLS_TEARDOWN, | ||
956 | |||
957 | IEEE80211_QUEUE_STOP_REASONS, | ||
915 | }; | 958 | }; |
916 | 959 | ||
917 | #ifdef CONFIG_MAC80211_LEDS | 960 | #ifdef CONFIG_MAC80211_LEDS |
@@ -1008,6 +1051,7 @@ struct ieee80211_local { | |||
1008 | struct workqueue_struct *workqueue; | 1051 | struct workqueue_struct *workqueue; |
1009 | 1052 | ||
1010 | unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES]; | 1053 | unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES]; |
1054 | int q_stop_reasons[IEEE80211_MAX_QUEUES][IEEE80211_QUEUE_STOP_REASONS]; | ||
1011 | /* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */ | 1055 | /* also used to protect ampdu_ac_queue and amdpu_ac_stop_refcnt */ |
1012 | spinlock_t queue_stop_reason_lock; | 1056 | spinlock_t queue_stop_reason_lock; |
1013 | 1057 | ||
@@ -1135,7 +1179,8 @@ struct ieee80211_local { | |||
1135 | unsigned long scanning; | 1179 | unsigned long scanning; |
1136 | struct cfg80211_ssid scan_ssid; | 1180 | struct cfg80211_ssid scan_ssid; |
1137 | struct cfg80211_scan_request *int_scan_req; | 1181 | struct cfg80211_scan_request *int_scan_req; |
1138 | struct cfg80211_scan_request *scan_req, *hw_scan_req; | 1182 | struct cfg80211_scan_request *scan_req; |
1183 | struct ieee80211_scan_request *hw_scan_req; | ||
1139 | struct cfg80211_chan_def scan_chandef; | 1184 | struct cfg80211_chan_def scan_chandef; |
1140 | enum ieee80211_band hw_scan_band; | 1185 | enum ieee80211_band hw_scan_band; |
1141 | int scan_channel_idx; | 1186 | int scan_channel_idx; |
@@ -1476,7 +1521,6 @@ void ieee80211_sw_roc_work(struct work_struct *work); | |||
1476 | void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc); | 1521 | void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc); |
1477 | 1522 | ||
1478 | /* channel switch handling */ | 1523 | /* channel switch handling */ |
1479 | bool ieee80211_csa_needs_block_tx(struct ieee80211_local *local); | ||
1480 | void ieee80211_csa_finalize_work(struct work_struct *work); | 1524 | void ieee80211_csa_finalize_work(struct work_struct *work); |
1481 | int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | 1525 | int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, |
1482 | struct cfg80211_csa_settings *params); | 1526 | struct cfg80211_csa_settings *params); |
@@ -1540,6 +1584,10 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | |||
1540 | u16 initiator, u16 reason, bool stop); | 1584 | u16 initiator, u16 reason, bool stop); |
1541 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, | 1585 | void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, |
1542 | u16 initiator, u16 reason, bool stop); | 1586 | u16 initiator, u16 reason, bool stop); |
1587 | void __ieee80211_start_rx_ba_session(struct sta_info *sta, | ||
1588 | u8 dialog_token, u16 timeout, | ||
1589 | u16 start_seq_num, u16 ba_policy, u16 tid, | ||
1590 | u16 buf_size, bool tx); | ||
1543 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, | 1591 | void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, |
1544 | enum ieee80211_agg_stop_reason reason); | 1592 | enum ieee80211_agg_stop_reason reason); |
1545 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | 1593 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, |
@@ -1692,6 +1740,21 @@ static inline void ieee802_11_parse_elems(const u8 *start, size_t len, | |||
1692 | ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0); | 1740 | ieee802_11_parse_elems_crc(start, len, action, elems, 0, 0); |
1693 | } | 1741 | } |
1694 | 1742 | ||
1743 | static inline bool ieee80211_rx_reorder_ready(struct sk_buff_head *frames) | ||
1744 | { | ||
1745 | struct sk_buff *tail = skb_peek_tail(frames); | ||
1746 | struct ieee80211_rx_status *status; | ||
1747 | |||
1748 | if (!tail) | ||
1749 | return false; | ||
1750 | |||
1751 | status = IEEE80211_SKB_RXCB(tail); | ||
1752 | if (status->flag & RX_FLAG_AMSDU_MORE) | ||
1753 | return false; | ||
1754 | |||
1755 | return true; | ||
1756 | } | ||
1757 | |||
1695 | void ieee80211_dynamic_ps_enable_work(struct work_struct *work); | 1758 | void ieee80211_dynamic_ps_enable_work(struct work_struct *work); |
1696 | void ieee80211_dynamic_ps_disable_work(struct work_struct *work); | 1759 | void ieee80211_dynamic_ps_disable_work(struct work_struct *work); |
1697 | void ieee80211_dynamic_ps_timer(unsigned long data); | 1760 | void ieee80211_dynamic_ps_timer(unsigned long data); |
@@ -1705,14 +1768,24 @@ void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata, | |||
1705 | 1768 | ||
1706 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, | 1769 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, |
1707 | unsigned long queues, | 1770 | unsigned long queues, |
1708 | enum queue_stop_reason reason); | 1771 | enum queue_stop_reason reason, |
1772 | bool refcounted); | ||
1773 | void ieee80211_stop_vif_queues(struct ieee80211_local *local, | ||
1774 | struct ieee80211_sub_if_data *sdata, | ||
1775 | enum queue_stop_reason reason); | ||
1776 | void ieee80211_wake_vif_queues(struct ieee80211_local *local, | ||
1777 | struct ieee80211_sub_if_data *sdata, | ||
1778 | enum queue_stop_reason reason); | ||
1709 | void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, | 1779 | void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, |
1710 | unsigned long queues, | 1780 | unsigned long queues, |
1711 | enum queue_stop_reason reason); | 1781 | enum queue_stop_reason reason, |
1782 | bool refcounted); | ||
1712 | void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, | 1783 | void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, |
1713 | enum queue_stop_reason reason); | 1784 | enum queue_stop_reason reason, |
1785 | bool refcounted); | ||
1714 | void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, | 1786 | void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, |
1715 | enum queue_stop_reason reason); | 1787 | enum queue_stop_reason reason, |
1788 | bool refcounted); | ||
1716 | void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue); | 1789 | void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue); |
1717 | void ieee80211_add_pending_skb(struct ieee80211_local *local, | 1790 | void ieee80211_add_pending_skb(struct ieee80211_local *local, |
1718 | struct sk_buff *skb); | 1791 | struct sk_buff *skb); |
@@ -1730,8 +1803,10 @@ void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1730 | const u8 *bssid, u16 stype, u16 reason, | 1803 | const u8 *bssid, u16 stype, u16 reason, |
1731 | bool send_frame, u8 *frame_buf); | 1804 | bool send_frame, u8 *frame_buf); |
1732 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | 1805 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, |
1733 | size_t buffer_len, const u8 *ie, size_t ie_len, | 1806 | size_t buffer_len, |
1734 | enum ieee80211_band band, u32 rate_mask, | 1807 | struct ieee80211_scan_ies *ie_desc, |
1808 | const u8 *ie, size_t ie_len, | ||
1809 | u8 bands_used, u32 *rate_masks, | ||
1735 | struct cfg80211_chan_def *chandef); | 1810 | struct cfg80211_chan_def *chandef); |
1736 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | 1811 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, |
1737 | u8 *dst, u32 ratemask, | 1812 | u8 *dst, u32 ratemask, |
@@ -1774,6 +1849,7 @@ int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata, | |||
1774 | int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, | 1849 | int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata, |
1775 | struct sk_buff *skb, bool need_basic, | 1850 | struct sk_buff *skb, bool need_basic, |
1776 | enum ieee80211_band band); | 1851 | enum ieee80211_band band); |
1852 | u8 *ieee80211_add_wmm_info_ie(u8 *buf, u8 qosinfo); | ||
1777 | 1853 | ||
1778 | /* channel management */ | 1854 | /* channel management */ |
1779 | void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan, | 1855 | void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan, |
@@ -1791,18 +1867,14 @@ ieee80211_vif_reserve_chanctx(struct ieee80211_sub_if_data *sdata, | |||
1791 | enum ieee80211_chanctx_mode mode, | 1867 | enum ieee80211_chanctx_mode mode, |
1792 | bool radar_required); | 1868 | bool radar_required); |
1793 | int __must_check | 1869 | int __must_check |
1794 | ieee80211_vif_use_reserved_context(struct ieee80211_sub_if_data *sdata, | 1870 | ieee80211_vif_use_reserved_context(struct ieee80211_sub_if_data *sdata); |
1795 | u32 *changed); | ||
1796 | int ieee80211_vif_unreserve_chanctx(struct ieee80211_sub_if_data *sdata); | 1871 | int ieee80211_vif_unreserve_chanctx(struct ieee80211_sub_if_data *sdata); |
1872 | int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local); | ||
1797 | 1873 | ||
1798 | int __must_check | 1874 | int __must_check |
1799 | ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata, | 1875 | ieee80211_vif_change_bandwidth(struct ieee80211_sub_if_data *sdata, |
1800 | const struct cfg80211_chan_def *chandef, | 1876 | const struct cfg80211_chan_def *chandef, |
1801 | u32 *changed); | 1877 | u32 *changed); |
1802 | /* NOTE: only use ieee80211_vif_change_channel() for channel switch */ | ||
1803 | int __must_check | ||
1804 | ieee80211_vif_change_channel(struct ieee80211_sub_if_data *sdata, | ||
1805 | u32 *changed); | ||
1806 | void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata); | 1878 | void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata); |
1807 | void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata); | 1879 | void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata); |
1808 | void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata, | 1880 | void ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata, |
@@ -1842,11 +1914,14 @@ int ieee80211_max_num_channels(struct ieee80211_local *local); | |||
1842 | int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, | 1914 | int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, |
1843 | const u8 *peer, u8 action_code, u8 dialog_token, | 1915 | const u8 *peer, u8 action_code, u8 dialog_token, |
1844 | u16 status_code, u32 peer_capability, | 1916 | u16 status_code, u32 peer_capability, |
1845 | const u8 *extra_ies, size_t extra_ies_len); | 1917 | bool initiator, const u8 *extra_ies, |
1918 | size_t extra_ies_len); | ||
1846 | int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, | 1919 | int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, |
1847 | const u8 *peer, enum nl80211_tdls_operation oper); | 1920 | const u8 *peer, enum nl80211_tdls_operation oper); |
1848 | 1921 | ||
1849 | 1922 | ||
1923 | extern const struct ethtool_ops ieee80211_ethtool_ops; | ||
1924 | |||
1850 | #ifdef CONFIG_MAC80211_NOINLINE | 1925 | #ifdef CONFIG_MAC80211_NOINLINE |
1851 | #define debug_noinline noinline | 1926 | #define debug_noinline noinline |
1852 | #else | 1927 | #else |
@@ -1854,3 +1929,4 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, | |||
1854 | #endif | 1929 | #endif |
1855 | 1930 | ||
1856 | #endif /* IEEE80211_I_H */ | 1931 | #endif /* IEEE80211_I_H */ |
1932 | void ieee80211_tdls_peer_del_work(struct work_struct *wk); | ||
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 388b863e821c..f75e5f132c5a 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -841,10 +841,11 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
841 | sdata_lock(sdata); | 841 | sdata_lock(sdata); |
842 | mutex_lock(&local->mtx); | 842 | mutex_lock(&local->mtx); |
843 | sdata->vif.csa_active = false; | 843 | sdata->vif.csa_active = false; |
844 | if (!ieee80211_csa_needs_block_tx(local)) | 844 | if (sdata->csa_block_tx) { |
845 | ieee80211_wake_queues_by_reason(&local->hw, | 845 | ieee80211_wake_vif_queues(local, sdata, |
846 | IEEE80211_MAX_QUEUE_MAP, | 846 | IEEE80211_QUEUE_STOP_REASON_CSA); |
847 | IEEE80211_QUEUE_STOP_REASON_CSA); | 847 | sdata->csa_block_tx = false; |
848 | } | ||
848 | mutex_unlock(&local->mtx); | 849 | mutex_unlock(&local->mtx); |
849 | sdata_unlock(sdata); | 850 | sdata_unlock(sdata); |
850 | 851 | ||
@@ -1139,6 +1140,7 @@ static void ieee80211_iface_work(struct work_struct *work) | |||
1139 | struct sk_buff *skb; | 1140 | struct sk_buff *skb; |
1140 | struct sta_info *sta; | 1141 | struct sta_info *sta; |
1141 | struct ieee80211_ra_tid *ra_tid; | 1142 | struct ieee80211_ra_tid *ra_tid; |
1143 | struct ieee80211_rx_agg *rx_agg; | ||
1142 | 1144 | ||
1143 | if (!ieee80211_sdata_running(sdata)) | 1145 | if (!ieee80211_sdata_running(sdata)) |
1144 | return; | 1146 | return; |
@@ -1166,6 +1168,34 @@ static void ieee80211_iface_work(struct work_struct *work) | |||
1166 | ra_tid = (void *)&skb->cb; | 1168 | ra_tid = (void *)&skb->cb; |
1167 | ieee80211_stop_tx_ba_cb(&sdata->vif, ra_tid->ra, | 1169 | ieee80211_stop_tx_ba_cb(&sdata->vif, ra_tid->ra, |
1168 | ra_tid->tid); | 1170 | ra_tid->tid); |
1171 | } else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_START) { | ||
1172 | rx_agg = (void *)&skb->cb; | ||
1173 | mutex_lock(&local->sta_mtx); | ||
1174 | sta = sta_info_get_bss(sdata, rx_agg->addr); | ||
1175 | if (sta) { | ||
1176 | u16 last_seq; | ||
1177 | |||
1178 | last_seq = IEEE80211_SEQ_TO_SN(le16_to_cpu( | ||
1179 | sta->last_seq_ctrl[rx_agg->tid])); | ||
1180 | |||
1181 | __ieee80211_start_rx_ba_session(sta, | ||
1182 | 0, 0, | ||
1183 | ieee80211_sn_inc(last_seq), | ||
1184 | 1, rx_agg->tid, | ||
1185 | IEEE80211_MAX_AMPDU_BUF, | ||
1186 | false); | ||
1187 | } | ||
1188 | mutex_unlock(&local->sta_mtx); | ||
1189 | } else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_STOP) { | ||
1190 | rx_agg = (void *)&skb->cb; | ||
1191 | mutex_lock(&local->sta_mtx); | ||
1192 | sta = sta_info_get_bss(sdata, rx_agg->addr); | ||
1193 | if (sta) | ||
1194 | __ieee80211_stop_rx_ba_session(sta, | ||
1195 | rx_agg->tid, | ||
1196 | WLAN_BACK_RECIPIENT, 0, | ||
1197 | false); | ||
1198 | mutex_unlock(&local->sta_mtx); | ||
1169 | } else if (ieee80211_is_action(mgmt->frame_control) && | 1199 | } else if (ieee80211_is_action(mgmt->frame_control) && |
1170 | mgmt->u.action.category == WLAN_CATEGORY_BACK) { | 1200 | mgmt->u.action.category == WLAN_CATEGORY_BACK) { |
1171 | int len = skb->len; | 1201 | int len = skb->len; |
@@ -1623,9 +1653,9 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1623 | if (local->hw.queues >= IEEE80211_NUM_ACS) | 1653 | if (local->hw.queues >= IEEE80211_NUM_ACS) |
1624 | txqs = IEEE80211_NUM_ACS; | 1654 | txqs = IEEE80211_NUM_ACS; |
1625 | 1655 | ||
1626 | ndev = alloc_netdev_mqs(sizeof(*sdata) + | 1656 | ndev = alloc_netdev_mqs(sizeof(*sdata) + local->hw.vif_data_size, |
1627 | local->hw.vif_data_size, | 1657 | name, NET_NAME_UNKNOWN, |
1628 | name, ieee80211_if_setup, txqs, 1); | 1658 | ieee80211_if_setup, txqs, 1); |
1629 | if (!ndev) | 1659 | if (!ndev) |
1630 | return -ENOMEM; | 1660 | return -ENOMEM; |
1631 | dev_net_set(ndev, wiphy_net(local->hw.wiphy)); | 1661 | dev_net_set(ndev, wiphy_net(local->hw.wiphy)); |
@@ -1705,6 +1735,8 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name, | |||
1705 | 1735 | ||
1706 | ndev->features |= local->hw.netdev_features; | 1736 | ndev->features |= local->hw.netdev_features; |
1707 | 1737 | ||
1738 | netdev_set_default_ethtool_ops(ndev, &ieee80211_ethtool_ops); | ||
1739 | |||
1708 | ret = register_netdevice(ndev); | 1740 | ret = register_netdevice(ndev); |
1709 | if (ret) { | 1741 | if (ret) { |
1710 | free_netdev(ndev); | 1742 | free_netdev(ndev); |
diff --git a/net/mac80211/key.c b/net/mac80211/key.c index 16d97f044a20..d808cff80153 100644 --- a/net/mac80211/key.c +++ b/net/mac80211/key.c | |||
@@ -482,9 +482,6 @@ int ieee80211_key_link(struct ieee80211_key *key, | |||
482 | int idx, ret; | 482 | int idx, ret; |
483 | bool pairwise; | 483 | bool pairwise; |
484 | 484 | ||
485 | if (WARN_ON(!sdata || !key)) | ||
486 | return -EINVAL; | ||
487 | |||
488 | pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE; | 485 | pairwise = key->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE; |
489 | idx = key->conf.keyidx; | 486 | idx = key->conf.keyidx; |
490 | key->local = sdata->local; | 487 | key->local = sdata->local; |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index d17c26d6e369..e0ab4320a078 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -272,7 +272,8 @@ void ieee80211_restart_hw(struct ieee80211_hw *hw) | |||
272 | 272 | ||
273 | /* use this reason, ieee80211_reconfig will unblock it */ | 273 | /* use this reason, ieee80211_reconfig will unblock it */ |
274 | ieee80211_stop_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP, | 274 | ieee80211_stop_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP, |
275 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | 275 | IEEE80211_QUEUE_STOP_REASON_SUSPEND, |
276 | false); | ||
276 | 277 | ||
277 | /* | 278 | /* |
278 | * Stop all Rx during the reconfig. We don't want state changes | 279 | * Stop all Rx during the reconfig. We don't want state changes |
@@ -1187,18 +1188,12 @@ static int __init ieee80211_init(void) | |||
1187 | if (ret) | 1188 | if (ret) |
1188 | goto err_minstrel; | 1189 | goto err_minstrel; |
1189 | 1190 | ||
1190 | ret = rc80211_pid_init(); | ||
1191 | if (ret) | ||
1192 | goto err_pid; | ||
1193 | |||
1194 | ret = ieee80211_iface_init(); | 1191 | ret = ieee80211_iface_init(); |
1195 | if (ret) | 1192 | if (ret) |
1196 | goto err_netdev; | 1193 | goto err_netdev; |
1197 | 1194 | ||
1198 | return 0; | 1195 | return 0; |
1199 | err_netdev: | 1196 | err_netdev: |
1200 | rc80211_pid_exit(); | ||
1201 | err_pid: | ||
1202 | rc80211_minstrel_ht_exit(); | 1197 | rc80211_minstrel_ht_exit(); |
1203 | err_minstrel: | 1198 | err_minstrel: |
1204 | rc80211_minstrel_exit(); | 1199 | rc80211_minstrel_exit(); |
@@ -1208,7 +1203,6 @@ static int __init ieee80211_init(void) | |||
1208 | 1203 | ||
1209 | static void __exit ieee80211_exit(void) | 1204 | static void __exit ieee80211_exit(void) |
1210 | { | 1205 | { |
1211 | rc80211_pid_exit(); | ||
1212 | rc80211_minstrel_ht_exit(); | 1206 | rc80211_minstrel_ht_exit(); |
1213 | rc80211_minstrel_exit(); | 1207 | rc80211_minstrel_exit(); |
1214 | 1208 | ||
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 6495a3f0428d..e9f99c1e3fad 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -679,7 +679,7 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) | |||
679 | *pos++ = 0x0; | 679 | *pos++ = 0x0; |
680 | *pos++ = ieee80211_frequency_to_channel( | 680 | *pos++ = ieee80211_frequency_to_channel( |
681 | csa->settings.chandef.chan->center_freq); | 681 | csa->settings.chandef.chan->center_freq); |
682 | sdata->csa_counter_offset_beacon[0] = hdr_len + 6; | 682 | bcn->csa_counter_offsets[0] = hdr_len + 6; |
683 | *pos++ = csa->settings.count; | 683 | *pos++ = csa->settings.count; |
684 | *pos++ = WLAN_EID_CHAN_SWITCH_PARAM; | 684 | *pos++ = WLAN_EID_CHAN_SWITCH_PARAM; |
685 | *pos++ = 6; | 685 | *pos++ = 6; |
@@ -1122,7 +1122,7 @@ static int mesh_fwd_csa_frame(struct ieee80211_sub_if_data *sdata, | |||
1122 | mgmt_fwd = (struct ieee80211_mgmt *) skb_put(skb, len); | 1122 | mgmt_fwd = (struct ieee80211_mgmt *) skb_put(skb, len); |
1123 | 1123 | ||
1124 | /* offset_ttl is based on whether the secondary channel | 1124 | /* offset_ttl is based on whether the secondary channel |
1125 | * offset is available or not. Substract 1 from the mesh TTL | 1125 | * offset is available or not. Subtract 1 from the mesh TTL |
1126 | * and disable the initiator flag before forwarding. | 1126 | * and disable the initiator flag before forwarding. |
1127 | */ | 1127 | */ |
1128 | offset_ttl = (len < 42) ? 7 : 10; | 1128 | offset_ttl = (len < 42) ? 7 : 10; |
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c index 94758b9c9ed4..214e63b84e5c 100644 --- a/net/mac80211/mesh_hwmp.c +++ b/net/mac80211/mesh_hwmp.c | |||
@@ -157,7 +157,6 @@ static int mesh_path_sel_frame_tx(enum mpath_frame_type action, u8 flags, | |||
157 | default: | 157 | default: |
158 | kfree_skb(skb); | 158 | kfree_skb(skb); |
159 | return -ENOTSUPP; | 159 | return -ENOTSUPP; |
160 | break; | ||
161 | } | 160 | } |
162 | *pos++ = ie_len; | 161 | *pos++ = ie_len; |
163 | *pos++ = flags; | 162 | *pos++ = flags; |
diff --git a/net/mac80211/mesh_plink.c b/net/mac80211/mesh_plink.c index e8f60aa2e848..c47194d27149 100644 --- a/net/mac80211/mesh_plink.c +++ b/net/mac80211/mesh_plink.c | |||
@@ -551,11 +551,30 @@ static void mesh_plink_timer(unsigned long data) | |||
551 | return; | 551 | return; |
552 | 552 | ||
553 | spin_lock_bh(&sta->lock); | 553 | spin_lock_bh(&sta->lock); |
554 | if (sta->ignore_plink_timer) { | 554 | |
555 | sta->ignore_plink_timer = false; | 555 | /* If a timer fires just before a state transition on another CPU, |
556 | * we may have already extended the timeout and changed state by the | ||
557 | * time we've acquired the lock and arrived here. In that case, | ||
558 | * skip this timer and wait for the new one. | ||
559 | */ | ||
560 | if (time_before(jiffies, sta->plink_timer.expires)) { | ||
561 | mpl_dbg(sta->sdata, | ||
562 | "Ignoring timer for %pM in state %s (timer adjusted)", | ||
563 | sta->sta.addr, mplstates[sta->plink_state]); | ||
564 | spin_unlock_bh(&sta->lock); | ||
565 | return; | ||
566 | } | ||
567 | |||
568 | /* del_timer() and handler may race when entering these states */ | ||
569 | if (sta->plink_state == NL80211_PLINK_LISTEN || | ||
570 | sta->plink_state == NL80211_PLINK_ESTAB) { | ||
571 | mpl_dbg(sta->sdata, | ||
572 | "Ignoring timer for %pM in state %s (timer deleted)", | ||
573 | sta->sta.addr, mplstates[sta->plink_state]); | ||
556 | spin_unlock_bh(&sta->lock); | 574 | spin_unlock_bh(&sta->lock); |
557 | return; | 575 | return; |
558 | } | 576 | } |
577 | |||
559 | mpl_dbg(sta->sdata, | 578 | mpl_dbg(sta->sdata, |
560 | "Mesh plink timer for %pM fired on state %s\n", | 579 | "Mesh plink timer for %pM fired on state %s\n", |
561 | sta->sta.addr, mplstates[sta->plink_state]); | 580 | sta->sta.addr, mplstates[sta->plink_state]); |
@@ -773,9 +792,7 @@ static u32 mesh_plink_fsm(struct ieee80211_sub_if_data *sdata, | |||
773 | break; | 792 | break; |
774 | case CNF_ACPT: | 793 | case CNF_ACPT: |
775 | sta->plink_state = NL80211_PLINK_CNF_RCVD; | 794 | sta->plink_state = NL80211_PLINK_CNF_RCVD; |
776 | if (!mod_plink_timer(sta, | 795 | mod_plink_timer(sta, mshcfg->dot11MeshConfirmTimeout); |
777 | mshcfg->dot11MeshConfirmTimeout)) | ||
778 | sta->ignore_plink_timer = true; | ||
779 | break; | 796 | break; |
780 | default: | 797 | default: |
781 | break; | 798 | break; |
@@ -834,8 +851,7 @@ static u32 mesh_plink_fsm(struct ieee80211_sub_if_data *sdata, | |||
834 | case NL80211_PLINK_HOLDING: | 851 | case NL80211_PLINK_HOLDING: |
835 | switch (event) { | 852 | switch (event) { |
836 | case CLS_ACPT: | 853 | case CLS_ACPT: |
837 | if (del_timer(&sta->plink_timer)) | 854 | del_timer(&sta->plink_timer); |
838 | sta->ignore_plink_timer = 1; | ||
839 | mesh_plink_fsm_restart(sta); | 855 | mesh_plink_fsm_restart(sta); |
840 | break; | 856 | break; |
841 | case OPN_ACPT: | 857 | case OPN_ACPT: |
@@ -943,7 +959,8 @@ mesh_plink_get_event(struct ieee80211_sub_if_data *sdata, | |||
943 | if (!matches_local) | 959 | if (!matches_local) |
944 | event = CNF_RJCT; | 960 | event = CNF_RJCT; |
945 | if (!mesh_plink_free_count(sdata) || | 961 | if (!mesh_plink_free_count(sdata) || |
946 | (sta->llid != llid || sta->plid != plid)) | 962 | sta->llid != llid || |
963 | (sta->plid && sta->plid != plid)) | ||
947 | event = CNF_IGNR; | 964 | event = CNF_IGNR; |
948 | else | 965 | else |
949 | event = CNF_ACPT; | 966 | event = CNF_ACPT; |
@@ -1064,6 +1081,10 @@ mesh_process_plink_frame(struct ieee80211_sub_if_data *sdata, | |||
1064 | goto unlock_rcu; | 1081 | goto unlock_rcu; |
1065 | } | 1082 | } |
1066 | 1083 | ||
1084 | /* 802.11-2012 13.3.7.2 - update plid on CNF if not set */ | ||
1085 | if (!sta->plid && event == CNF_ACPT) | ||
1086 | sta->plid = plid; | ||
1087 | |||
1067 | changed |= mesh_plink_fsm(sdata, sta, event); | 1088 | changed |= mesh_plink_fsm(sdata, sta, event); |
1068 | 1089 | ||
1069 | unlock_rcu: | 1090 | unlock_rcu: |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 3345401be1b3..b82a12a9f0f1 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -830,16 +830,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
830 | qos_info = 0; | 830 | qos_info = 0; |
831 | } | 831 | } |
832 | 832 | ||
833 | pos = skb_put(skb, 9); | 833 | pos = ieee80211_add_wmm_info_ie(skb_put(skb, 9), qos_info); |
834 | *pos++ = WLAN_EID_VENDOR_SPECIFIC; | ||
835 | *pos++ = 7; /* len */ | ||
836 | *pos++ = 0x00; /* Microsoft OUI 00:50:F2 */ | ||
837 | *pos++ = 0x50; | ||
838 | *pos++ = 0xf2; | ||
839 | *pos++ = 2; /* WME */ | ||
840 | *pos++ = 0; /* WME info */ | ||
841 | *pos++ = 1; /* WME ver */ | ||
842 | *pos++ = qos_info; | ||
843 | } | 834 | } |
844 | 835 | ||
845 | /* add any remaining custom (i.e. vendor specific here) IEs */ | 836 | /* add any remaining custom (i.e. vendor specific here) IEs */ |
@@ -940,58 +931,77 @@ static void ieee80211_chswitch_work(struct work_struct *work) | |||
940 | container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work); | 931 | container_of(work, struct ieee80211_sub_if_data, u.mgd.chswitch_work); |
941 | struct ieee80211_local *local = sdata->local; | 932 | struct ieee80211_local *local = sdata->local; |
942 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 933 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
943 | u32 changed = 0; | ||
944 | int ret; | 934 | int ret; |
945 | 935 | ||
946 | if (!ieee80211_sdata_running(sdata)) | 936 | if (!ieee80211_sdata_running(sdata)) |
947 | return; | 937 | return; |
948 | 938 | ||
949 | sdata_lock(sdata); | 939 | sdata_lock(sdata); |
940 | mutex_lock(&local->mtx); | ||
941 | mutex_lock(&local->chanctx_mtx); | ||
942 | |||
950 | if (!ifmgd->associated) | 943 | if (!ifmgd->associated) |
951 | goto out; | 944 | goto out; |
952 | 945 | ||
953 | mutex_lock(&local->mtx); | 946 | if (!sdata->vif.csa_active) |
954 | ret = ieee80211_vif_change_channel(sdata, &changed); | 947 | goto out; |
955 | mutex_unlock(&local->mtx); | 948 | |
956 | if (ret) { | 949 | /* |
950 | * using reservation isn't immediate as it may be deferred until later | ||
951 | * with multi-vif. once reservation is complete it will re-schedule the | ||
952 | * work with no reserved_chanctx so verify chandef to check if it | ||
953 | * completed successfully | ||
954 | */ | ||
955 | |||
956 | if (sdata->reserved_chanctx) { | ||
957 | /* | ||
958 | * with multi-vif csa driver may call ieee80211_csa_finish() | ||
959 | * many times while waiting for other interfaces to use their | ||
960 | * reservations | ||
961 | */ | ||
962 | if (sdata->reserved_ready) | ||
963 | goto out; | ||
964 | |||
965 | ret = ieee80211_vif_use_reserved_context(sdata); | ||
966 | if (ret) { | ||
967 | sdata_info(sdata, | ||
968 | "failed to use reserved channel context, disconnecting (err=%d)\n", | ||
969 | ret); | ||
970 | ieee80211_queue_work(&sdata->local->hw, | ||
971 | &ifmgd->csa_connection_drop_work); | ||
972 | goto out; | ||
973 | } | ||
974 | |||
975 | goto out; | ||
976 | } | ||
977 | |||
978 | if (!cfg80211_chandef_identical(&sdata->vif.bss_conf.chandef, | ||
979 | &sdata->csa_chandef)) { | ||
957 | sdata_info(sdata, | 980 | sdata_info(sdata, |
958 | "vif channel switch failed, disconnecting\n"); | 981 | "failed to finalize channel switch, disconnecting\n"); |
959 | ieee80211_queue_work(&sdata->local->hw, | 982 | ieee80211_queue_work(&sdata->local->hw, |
960 | &ifmgd->csa_connection_drop_work); | 983 | &ifmgd->csa_connection_drop_work); |
961 | goto out; | 984 | goto out; |
962 | } | 985 | } |
963 | 986 | ||
964 | if (!local->use_chanctx) { | ||
965 | local->_oper_chandef = sdata->csa_chandef; | ||
966 | /* Call "hw_config" only if doing sw channel switch. | ||
967 | * Otherwise update the channel directly | ||
968 | */ | ||
969 | if (!local->ops->channel_switch) | ||
970 | ieee80211_hw_config(local, 0); | ||
971 | else | ||
972 | local->hw.conf.chandef = local->_oper_chandef; | ||
973 | } | ||
974 | |||
975 | /* XXX: shouldn't really modify cfg80211-owned data! */ | 987 | /* XXX: shouldn't really modify cfg80211-owned data! */ |
976 | ifmgd->associated->channel = sdata->csa_chandef.chan; | 988 | ifmgd->associated->channel = sdata->csa_chandef.chan; |
977 | 989 | ||
978 | ieee80211_bss_info_change_notify(sdata, changed); | ||
979 | |||
980 | mutex_lock(&local->mtx); | ||
981 | sdata->vif.csa_active = false; | 990 | sdata->vif.csa_active = false; |
982 | /* XXX: wait for a beacon first? */ | ||
983 | if (!ieee80211_csa_needs_block_tx(local)) | ||
984 | ieee80211_wake_queues_by_reason(&local->hw, | ||
985 | IEEE80211_MAX_QUEUE_MAP, | ||
986 | IEEE80211_QUEUE_STOP_REASON_CSA); | ||
987 | mutex_unlock(&local->mtx); | ||
988 | 991 | ||
989 | ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; | 992 | /* XXX: wait for a beacon first? */ |
993 | if (sdata->csa_block_tx) { | ||
994 | ieee80211_wake_vif_queues(local, sdata, | ||
995 | IEEE80211_QUEUE_STOP_REASON_CSA); | ||
996 | sdata->csa_block_tx = false; | ||
997 | } | ||
990 | 998 | ||
991 | ieee80211_sta_reset_beacon_monitor(sdata); | 999 | ieee80211_sta_reset_beacon_monitor(sdata); |
992 | ieee80211_sta_reset_conn_monitor(sdata); | 1000 | ieee80211_sta_reset_conn_monitor(sdata); |
993 | 1001 | ||
994 | out: | 1002 | out: |
1003 | mutex_unlock(&local->chanctx_mtx); | ||
1004 | mutex_unlock(&local->mtx); | ||
995 | sdata_unlock(sdata); | 1005 | sdata_unlock(sdata); |
996 | } | 1006 | } |
997 | 1007 | ||
@@ -1028,6 +1038,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1028 | struct ieee80211_local *local = sdata->local; | 1038 | struct ieee80211_local *local = sdata->local; |
1029 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 1039 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
1030 | struct cfg80211_bss *cbss = ifmgd->associated; | 1040 | struct cfg80211_bss *cbss = ifmgd->associated; |
1041 | struct ieee80211_chanctx_conf *conf; | ||
1031 | struct ieee80211_chanctx *chanctx; | 1042 | struct ieee80211_chanctx *chanctx; |
1032 | enum ieee80211_band current_band; | 1043 | enum ieee80211_band current_band; |
1033 | struct ieee80211_csa_ie csa_ie; | 1044 | struct ieee80211_csa_ie csa_ie; |
@@ -1042,7 +1053,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1042 | return; | 1053 | return; |
1043 | 1054 | ||
1044 | /* disregard subsequent announcements if we are already processing */ | 1055 | /* disregard subsequent announcements if we are already processing */ |
1045 | if (ifmgd->flags & IEEE80211_STA_CSA_RECEIVED) | 1056 | if (sdata->vif.csa_active) |
1046 | return; | 1057 | return; |
1047 | 1058 | ||
1048 | current_band = cbss->channel->band; | 1059 | current_band = cbss->channel->band; |
@@ -1069,9 +1080,22 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1069 | return; | 1080 | return; |
1070 | } | 1081 | } |
1071 | 1082 | ||
1072 | ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED; | 1083 | mutex_lock(&local->mtx); |
1073 | |||
1074 | mutex_lock(&local->chanctx_mtx); | 1084 | mutex_lock(&local->chanctx_mtx); |
1085 | conf = rcu_dereference_protected(sdata->vif.chanctx_conf, | ||
1086 | lockdep_is_held(&local->chanctx_mtx)); | ||
1087 | if (!conf) { | ||
1088 | sdata_info(sdata, | ||
1089 | "no channel context assigned to vif?, disconnecting\n"); | ||
1090 | ieee80211_queue_work(&local->hw, | ||
1091 | &ifmgd->csa_connection_drop_work); | ||
1092 | mutex_unlock(&local->chanctx_mtx); | ||
1093 | mutex_unlock(&local->mtx); | ||
1094 | return; | ||
1095 | } | ||
1096 | |||
1097 | chanctx = container_of(conf, struct ieee80211_chanctx, conf); | ||
1098 | |||
1075 | if (local->use_chanctx) { | 1099 | if (local->use_chanctx) { |
1076 | u32 num_chanctx = 0; | 1100 | u32 num_chanctx = 0; |
1077 | list_for_each_entry(chanctx, &local->chanctx_list, list) | 1101 | list_for_each_entry(chanctx, &local->chanctx_list, list) |
@@ -1084,38 +1108,32 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
1084 | ieee80211_queue_work(&local->hw, | 1108 | ieee80211_queue_work(&local->hw, |
1085 | &ifmgd->csa_connection_drop_work); | 1109 | &ifmgd->csa_connection_drop_work); |
1086 | mutex_unlock(&local->chanctx_mtx); | 1110 | mutex_unlock(&local->chanctx_mtx); |
1111 | mutex_unlock(&local->mtx); | ||
1087 | return; | 1112 | return; |
1088 | } | 1113 | } |
1089 | } | 1114 | } |
1090 | 1115 | ||
1091 | if (WARN_ON(!rcu_access_pointer(sdata->vif.chanctx_conf))) { | 1116 | res = ieee80211_vif_reserve_chanctx(sdata, &csa_ie.chandef, |
1092 | ieee80211_queue_work(&local->hw, | 1117 | chanctx->mode, false); |
1093 | &ifmgd->csa_connection_drop_work); | 1118 | if (res) { |
1094 | mutex_unlock(&local->chanctx_mtx); | ||
1095 | return; | ||
1096 | } | ||
1097 | chanctx = container_of(rcu_access_pointer(sdata->vif.chanctx_conf), | ||
1098 | struct ieee80211_chanctx, conf); | ||
1099 | if (ieee80211_chanctx_refcount(local, chanctx) > 1) { | ||
1100 | sdata_info(sdata, | 1119 | sdata_info(sdata, |
1101 | "channel switch with multiple interfaces on the same channel, disconnecting\n"); | 1120 | "failed to reserve channel context for channel switch, disconnecting (err=%d)\n", |
1121 | res); | ||
1102 | ieee80211_queue_work(&local->hw, | 1122 | ieee80211_queue_work(&local->hw, |
1103 | &ifmgd->csa_connection_drop_work); | 1123 | &ifmgd->csa_connection_drop_work); |
1104 | mutex_unlock(&local->chanctx_mtx); | 1124 | mutex_unlock(&local->chanctx_mtx); |
1125 | mutex_unlock(&local->mtx); | ||
1105 | return; | 1126 | return; |
1106 | } | 1127 | } |
1107 | mutex_unlock(&local->chanctx_mtx); | 1128 | mutex_unlock(&local->chanctx_mtx); |
1108 | 1129 | ||
1109 | sdata->csa_chandef = csa_ie.chandef; | ||
1110 | |||
1111 | mutex_lock(&local->mtx); | ||
1112 | sdata->vif.csa_active = true; | 1130 | sdata->vif.csa_active = true; |
1131 | sdata->csa_chandef = csa_ie.chandef; | ||
1113 | sdata->csa_block_tx = csa_ie.mode; | 1132 | sdata->csa_block_tx = csa_ie.mode; |
1114 | 1133 | ||
1115 | if (sdata->csa_block_tx) | 1134 | if (sdata->csa_block_tx) |
1116 | ieee80211_stop_queues_by_reason(&local->hw, | 1135 | ieee80211_stop_vif_queues(local, sdata, |
1117 | IEEE80211_MAX_QUEUE_MAP, | 1136 | IEEE80211_QUEUE_STOP_REASON_CSA); |
1118 | IEEE80211_QUEUE_STOP_REASON_CSA); | ||
1119 | mutex_unlock(&local->mtx); | 1137 | mutex_unlock(&local->mtx); |
1120 | 1138 | ||
1121 | if (local->ops->channel_switch) { | 1139 | if (local->ops->channel_switch) { |
@@ -1385,7 +1403,8 @@ void ieee80211_dynamic_ps_disable_work(struct work_struct *work) | |||
1385 | 1403 | ||
1386 | ieee80211_wake_queues_by_reason(&local->hw, | 1404 | ieee80211_wake_queues_by_reason(&local->hw, |
1387 | IEEE80211_MAX_QUEUE_MAP, | 1405 | IEEE80211_MAX_QUEUE_MAP, |
1388 | IEEE80211_QUEUE_STOP_REASON_PS); | 1406 | IEEE80211_QUEUE_STOP_REASON_PS, |
1407 | false); | ||
1389 | } | 1408 | } |
1390 | 1409 | ||
1391 | void ieee80211_dynamic_ps_enable_work(struct work_struct *work) | 1410 | void ieee80211_dynamic_ps_enable_work(struct work_struct *work) |
@@ -1830,10 +1849,11 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1830 | ieee80211_vif_release_channel(sdata); | 1849 | ieee80211_vif_release_channel(sdata); |
1831 | 1850 | ||
1832 | sdata->vif.csa_active = false; | 1851 | sdata->vif.csa_active = false; |
1833 | if (!ieee80211_csa_needs_block_tx(local)) | 1852 | if (sdata->csa_block_tx) { |
1834 | ieee80211_wake_queues_by_reason(&local->hw, | 1853 | ieee80211_wake_vif_queues(local, sdata, |
1835 | IEEE80211_MAX_QUEUE_MAP, | 1854 | IEEE80211_QUEUE_STOP_REASON_CSA); |
1836 | IEEE80211_QUEUE_STOP_REASON_CSA); | 1855 | sdata->csa_block_tx = false; |
1856 | } | ||
1837 | mutex_unlock(&local->mtx); | 1857 | mutex_unlock(&local->mtx); |
1838 | 1858 | ||
1839 | sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; | 1859 | sdata->encrypt_headroom = IEEE80211_ENCRYPT_HEADROOM; |
@@ -2075,14 +2095,13 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) | |||
2075 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, | 2095 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, |
2076 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, | 2096 | WLAN_REASON_DISASSOC_DUE_TO_INACTIVITY, |
2077 | true, frame_buf); | 2097 | true, frame_buf); |
2078 | ifmgd->flags &= ~IEEE80211_STA_CSA_RECEIVED; | ||
2079 | |||
2080 | mutex_lock(&local->mtx); | 2098 | mutex_lock(&local->mtx); |
2081 | sdata->vif.csa_active = false; | 2099 | sdata->vif.csa_active = false; |
2082 | if (!ieee80211_csa_needs_block_tx(local)) | 2100 | if (sdata->csa_block_tx) { |
2083 | ieee80211_wake_queues_by_reason(&local->hw, | 2101 | ieee80211_wake_vif_queues(local, sdata, |
2084 | IEEE80211_MAX_QUEUE_MAP, | 2102 | IEEE80211_QUEUE_STOP_REASON_CSA); |
2085 | IEEE80211_QUEUE_STOP_REASON_CSA); | 2103 | sdata->csa_block_tx = false; |
2104 | } | ||
2086 | mutex_unlock(&local->mtx); | 2105 | mutex_unlock(&local->mtx); |
2087 | 2106 | ||
2088 | cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, | 2107 | cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, |
@@ -3688,6 +3707,8 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
3688 | INIT_WORK(&ifmgd->csa_connection_drop_work, | 3707 | INIT_WORK(&ifmgd->csa_connection_drop_work, |
3689 | ieee80211_csa_connection_drop_work); | 3708 | ieee80211_csa_connection_drop_work); |
3690 | INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_mgd_work); | 3709 | INIT_WORK(&ifmgd->request_smps_work, ieee80211_request_smps_mgd_work); |
3710 | INIT_DELAYED_WORK(&ifmgd->tdls_peer_del_work, | ||
3711 | ieee80211_tdls_peer_del_work); | ||
3691 | setup_timer(&ifmgd->timer, ieee80211_sta_timer, | 3712 | setup_timer(&ifmgd->timer, ieee80211_sta_timer, |
3692 | (unsigned long) sdata); | 3713 | (unsigned long) sdata); |
3693 | setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, | 3714 | setup_timer(&ifmgd->bcn_mon_timer, ieee80211_sta_bcn_mon_timer, |
@@ -4355,8 +4376,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata, | |||
4355 | rcu_read_unlock(); | 4376 | rcu_read_unlock(); |
4356 | 4377 | ||
4357 | if (bss->wmm_used && bss->uapsd_supported && | 4378 | if (bss->wmm_used && bss->uapsd_supported && |
4358 | (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) && | 4379 | (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) { |
4359 | sdata->wmm_acm != 0xff) { | ||
4360 | assoc_data->uapsd = true; | 4380 | assoc_data->uapsd = true; |
4361 | ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED; | 4381 | ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED; |
4362 | } else { | 4382 | } else { |
@@ -4551,6 +4571,7 @@ void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata) | |||
4551 | cancel_work_sync(&ifmgd->request_smps_work); | 4571 | cancel_work_sync(&ifmgd->request_smps_work); |
4552 | cancel_work_sync(&ifmgd->csa_connection_drop_work); | 4572 | cancel_work_sync(&ifmgd->csa_connection_drop_work); |
4553 | cancel_work_sync(&ifmgd->chswitch_work); | 4573 | cancel_work_sync(&ifmgd->chswitch_work); |
4574 | cancel_delayed_work_sync(&ifmgd->tdls_peer_del_work); | ||
4554 | 4575 | ||
4555 | sdata_lock(sdata); | 4576 | sdata_lock(sdata); |
4556 | if (ifmgd->assoc_data) { | 4577 | if (ifmgd->assoc_data) { |
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c index 7a17decd27f9..ff20b2ebdb30 100644 --- a/net/mac80211/offchannel.c +++ b/net/mac80211/offchannel.c | |||
@@ -119,7 +119,8 @@ void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local) | |||
119 | * before sending nullfunc to enable powersave at the AP. | 119 | * before sending nullfunc to enable powersave at the AP. |
120 | */ | 120 | */ |
121 | ieee80211_stop_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP, | 121 | ieee80211_stop_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP, |
122 | IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL); | 122 | IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL, |
123 | false); | ||
123 | ieee80211_flush_queues(local, NULL); | 124 | ieee80211_flush_queues(local, NULL); |
124 | 125 | ||
125 | mutex_lock(&local->iflist_mtx); | 126 | mutex_lock(&local->iflist_mtx); |
@@ -182,7 +183,8 @@ void ieee80211_offchannel_return(struct ieee80211_local *local) | |||
182 | mutex_unlock(&local->iflist_mtx); | 183 | mutex_unlock(&local->iflist_mtx); |
183 | 184 | ||
184 | ieee80211_wake_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP, | 185 | ieee80211_wake_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP, |
185 | IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL); | 186 | IEEE80211_QUEUE_STOP_REASON_OFFCHANNEL, |
187 | false); | ||
186 | } | 188 | } |
187 | 189 | ||
188 | void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc) | 190 | void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc) |
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index d478b880a0af..4c5192e0d66c 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
@@ -35,7 +35,8 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
35 | 35 | ||
36 | ieee80211_stop_queues_by_reason(hw, | 36 | ieee80211_stop_queues_by_reason(hw, |
37 | IEEE80211_MAX_QUEUE_MAP, | 37 | IEEE80211_MAX_QUEUE_MAP, |
38 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | 38 | IEEE80211_QUEUE_STOP_REASON_SUSPEND, |
39 | false); | ||
39 | 40 | ||
40 | /* flush out all packets */ | 41 | /* flush out all packets */ |
41 | synchronize_net(); | 42 | synchronize_net(); |
@@ -74,7 +75,8 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
74 | } | 75 | } |
75 | ieee80211_wake_queues_by_reason(hw, | 76 | ieee80211_wake_queues_by_reason(hw, |
76 | IEEE80211_MAX_QUEUE_MAP, | 77 | IEEE80211_MAX_QUEUE_MAP, |
77 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | 78 | IEEE80211_QUEUE_STOP_REASON_SUSPEND, |
79 | false); | ||
78 | return err; | 80 | return err; |
79 | } else if (err > 0) { | 81 | } else if (err > 0) { |
80 | WARN_ON(err != 1); | 82 | WARN_ON(err != 1); |
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index 9aa2a1190a86..18babe302832 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h | |||
@@ -143,19 +143,6 @@ void rate_control_deinitialize(struct ieee80211_local *local); | |||
143 | 143 | ||
144 | 144 | ||
145 | /* Rate control algorithms */ | 145 | /* Rate control algorithms */ |
146 | #ifdef CONFIG_MAC80211_RC_PID | ||
147 | int rc80211_pid_init(void); | ||
148 | void rc80211_pid_exit(void); | ||
149 | #else | ||
150 | static inline int rc80211_pid_init(void) | ||
151 | { | ||
152 | return 0; | ||
153 | } | ||
154 | static inline void rc80211_pid_exit(void) | ||
155 | { | ||
156 | } | ||
157 | #endif | ||
158 | |||
159 | #ifdef CONFIG_MAC80211_RC_MINSTREL | 146 | #ifdef CONFIG_MAC80211_RC_MINSTREL |
160 | int rc80211_minstrel_init(void); | 147 | int rc80211_minstrel_init(void); |
161 | void rc80211_minstrel_exit(void); | 148 | void rc80211_minstrel_exit(void); |
diff --git a/net/mac80211/rc80211_pid.h b/net/mac80211/rc80211_pid.h deleted file mode 100644 index 19111c7bf454..000000000000 --- a/net/mac80211/rc80211_pid.h +++ /dev/null | |||
@@ -1,278 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright 2007, Mattias Nissler <mattias.nissler@gmx.de> | ||
3 | * Copyright 2007, Stefano Brivio <stefano.brivio@polimi.it> | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or modify | ||
6 | * it under the terms of the GNU General Public License version 2 as | ||
7 | * published by the Free Software Foundation. | ||
8 | */ | ||
9 | |||
10 | #ifndef RC80211_PID_H | ||
11 | #define RC80211_PID_H | ||
12 | |||
13 | /* Sampling period for measuring percentage of failed frames in ms. */ | ||
14 | #define RC_PID_INTERVAL 125 | ||
15 | |||
16 | /* Exponential averaging smoothness (used for I part of PID controller) */ | ||
17 | #define RC_PID_SMOOTHING_SHIFT 3 | ||
18 | #define RC_PID_SMOOTHING (1 << RC_PID_SMOOTHING_SHIFT) | ||
19 | |||
20 | /* Sharpening factor (used for D part of PID controller) */ | ||
21 | #define RC_PID_SHARPENING_FACTOR 0 | ||
22 | #define RC_PID_SHARPENING_DURATION 0 | ||
23 | |||
24 | /* Fixed point arithmetic shifting amount. */ | ||
25 | #define RC_PID_ARITH_SHIFT 8 | ||
26 | |||
27 | /* Proportional PID component coefficient. */ | ||
28 | #define RC_PID_COEFF_P 15 | ||
29 | /* Integral PID component coefficient. */ | ||
30 | #define RC_PID_COEFF_I 9 | ||
31 | /* Derivative PID component coefficient. */ | ||
32 | #define RC_PID_COEFF_D 15 | ||
33 | |||
34 | /* Target failed frames rate for the PID controller. NB: This effectively gives | ||
35 | * maximum failed frames percentage we're willing to accept. If the wireless | ||
36 | * link quality is good, the controller will fail to adjust failed frames | ||
37 | * percentage to the target. This is intentional. | ||
38 | */ | ||
39 | #define RC_PID_TARGET_PF 14 | ||
40 | |||
41 | /* Rate behaviour normalization quantity over time. */ | ||
42 | #define RC_PID_NORM_OFFSET 3 | ||
43 | |||
44 | /* Push high rates right after loading. */ | ||
45 | #define RC_PID_FAST_START 0 | ||
46 | |||
47 | /* Arithmetic right shift for positive and negative values for ISO C. */ | ||
48 | #define RC_PID_DO_ARITH_RIGHT_SHIFT(x, y) \ | ||
49 | ((x) < 0 ? -((-(x)) >> (y)) : (x) >> (y)) | ||
50 | |||
51 | enum rc_pid_event_type { | ||
52 | RC_PID_EVENT_TYPE_TX_STATUS, | ||
53 | RC_PID_EVENT_TYPE_RATE_CHANGE, | ||
54 | RC_PID_EVENT_TYPE_TX_RATE, | ||
55 | RC_PID_EVENT_TYPE_PF_SAMPLE, | ||
56 | }; | ||
57 | |||
58 | union rc_pid_event_data { | ||
59 | /* RC_PID_EVENT_TX_STATUS */ | ||
60 | struct { | ||
61 | u32 flags; | ||
62 | struct ieee80211_tx_info tx_status; | ||
63 | }; | ||
64 | /* RC_PID_EVENT_TYPE_RATE_CHANGE */ | ||
65 | /* RC_PID_EVENT_TYPE_TX_RATE */ | ||
66 | struct { | ||
67 | int index; | ||
68 | int rate; | ||
69 | }; | ||
70 | /* RC_PID_EVENT_TYPE_PF_SAMPLE */ | ||
71 | struct { | ||
72 | s32 pf_sample; | ||
73 | s32 prop_err; | ||
74 | s32 int_err; | ||
75 | s32 der_err; | ||
76 | }; | ||
77 | }; | ||
78 | |||
79 | struct rc_pid_event { | ||
80 | /* The time when the event occurred */ | ||
81 | unsigned long timestamp; | ||
82 | |||
83 | /* Event ID number */ | ||
84 | unsigned int id; | ||
85 | |||
86 | /* Type of event */ | ||
87 | enum rc_pid_event_type type; | ||
88 | |||
89 | /* type specific data */ | ||
90 | union rc_pid_event_data data; | ||
91 | }; | ||
92 | |||
93 | /* Size of the event ring buffer. */ | ||
94 | #define RC_PID_EVENT_RING_SIZE 32 | ||
95 | |||
96 | struct rc_pid_event_buffer { | ||
97 | /* Counter that generates event IDs */ | ||
98 | unsigned int ev_count; | ||
99 | |||
100 | /* Ring buffer of events */ | ||
101 | struct rc_pid_event ring[RC_PID_EVENT_RING_SIZE]; | ||
102 | |||
103 | /* Index to the entry in events_buf to be reused */ | ||
104 | unsigned int next_entry; | ||
105 | |||
106 | /* Lock that guards against concurrent access to this buffer struct */ | ||
107 | spinlock_t lock; | ||
108 | |||
109 | /* Wait queue for poll/select and blocking I/O */ | ||
110 | wait_queue_head_t waitqueue; | ||
111 | }; | ||
112 | |||
113 | struct rc_pid_events_file_info { | ||
114 | /* The event buffer we read */ | ||
115 | struct rc_pid_event_buffer *events; | ||
116 | |||
117 | /* The entry we have should read next */ | ||
118 | unsigned int next_entry; | ||
119 | }; | ||
120 | |||
121 | /** | ||
122 | * struct rc_pid_debugfs_entries - tunable parameters | ||
123 | * | ||
124 | * Algorithm parameters, tunable via debugfs. | ||
125 | * @target: target percentage for failed frames | ||
126 | * @sampling_period: error sampling interval in milliseconds | ||
127 | * @coeff_p: absolute value of the proportional coefficient | ||
128 | * @coeff_i: absolute value of the integral coefficient | ||
129 | * @coeff_d: absolute value of the derivative coefficient | ||
130 | * @smoothing_shift: absolute value of the integral smoothing factor (i.e. | ||
131 | * amount of smoothing introduced by the exponential moving average) | ||
132 | * @sharpen_factor: absolute value of the derivative sharpening factor (i.e. | ||
133 | * amount of emphasis given to the derivative term after low activity | ||
134 | * events) | ||
135 | * @sharpen_duration: duration of the sharpening effect after the detected low | ||
136 | * activity event, relative to sampling_period | ||
137 | * @norm_offset: amount of normalization periodically performed on the learnt | ||
138 | * rate behaviour values (lower means we should trust more what we learnt | ||
139 | * about behaviour of rates, higher means we should trust more the natural | ||
140 | * ordering of rates) | ||
141 | */ | ||
142 | struct rc_pid_debugfs_entries { | ||
143 | struct dentry *target; | ||
144 | struct dentry *sampling_period; | ||
145 | struct dentry *coeff_p; | ||
146 | struct dentry *coeff_i; | ||
147 | struct dentry *coeff_d; | ||
148 | struct dentry *smoothing_shift; | ||
149 | struct dentry *sharpen_factor; | ||
150 | struct dentry *sharpen_duration; | ||
151 | struct dentry *norm_offset; | ||
152 | }; | ||
153 | |||
154 | void rate_control_pid_event_tx_status(struct rc_pid_event_buffer *buf, | ||
155 | struct ieee80211_tx_info *stat); | ||
156 | |||
157 | void rate_control_pid_event_rate_change(struct rc_pid_event_buffer *buf, | ||
158 | int index, int rate); | ||
159 | |||
160 | void rate_control_pid_event_tx_rate(struct rc_pid_event_buffer *buf, | ||
161 | int index, int rate); | ||
162 | |||
163 | void rate_control_pid_event_pf_sample(struct rc_pid_event_buffer *buf, | ||
164 | s32 pf_sample, s32 prop_err, | ||
165 | s32 int_err, s32 der_err); | ||
166 | |||
167 | void rate_control_pid_add_sta_debugfs(void *priv, void *priv_sta, | ||
168 | struct dentry *dir); | ||
169 | |||
170 | void rate_control_pid_remove_sta_debugfs(void *priv, void *priv_sta); | ||
171 | |||
172 | struct rc_pid_sta_info { | ||
173 | unsigned long last_change; | ||
174 | unsigned long last_sample; | ||
175 | |||
176 | u32 tx_num_failed; | ||
177 | u32 tx_num_xmit; | ||
178 | |||
179 | int txrate_idx; | ||
180 | |||
181 | /* Average failed frames percentage error (i.e. actual vs. target | ||
182 | * percentage), scaled by RC_PID_SMOOTHING. This value is computed | ||
183 | * using using an exponential weighted average technique: | ||
184 | * | ||
185 | * (RC_PID_SMOOTHING - 1) * err_avg_old + err | ||
186 | * err_avg = ------------------------------------------ | ||
187 | * RC_PID_SMOOTHING | ||
188 | * | ||
189 | * where err_avg is the new approximation, err_avg_old the previous one | ||
190 | * and err is the error w.r.t. to the current failed frames percentage | ||
191 | * sample. Note that the bigger RC_PID_SMOOTHING the more weight is | ||
192 | * given to the previous estimate, resulting in smoother behavior (i.e. | ||
193 | * corresponding to a longer integration window). | ||
194 | * | ||
195 | * For computation, we actually don't use the above formula, but this | ||
196 | * one: | ||
197 | * | ||
198 | * err_avg_scaled = err_avg_old_scaled - err_avg_old + err | ||
199 | * | ||
200 | * where: | ||
201 | * err_avg_scaled = err * RC_PID_SMOOTHING | ||
202 | * err_avg_old_scaled = err_avg_old * RC_PID_SMOOTHING | ||
203 | * | ||
204 | * This avoids floating point numbers and the per_failed_old value can | ||
205 | * easily be obtained by shifting per_failed_old_scaled right by | ||
206 | * RC_PID_SMOOTHING_SHIFT. | ||
207 | */ | ||
208 | s32 err_avg_sc; | ||
209 | |||
210 | /* Last framed failes percentage sample. */ | ||
211 | u32 last_pf; | ||
212 | |||
213 | /* Sharpening needed. */ | ||
214 | u8 sharp_cnt; | ||
215 | |||
216 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
217 | /* Event buffer */ | ||
218 | struct rc_pid_event_buffer events; | ||
219 | |||
220 | /* Events debugfs file entry */ | ||
221 | struct dentry *events_entry; | ||
222 | #endif | ||
223 | }; | ||
224 | |||
225 | /* Algorithm parameters. We keep them on a per-algorithm approach, so they can | ||
226 | * be tuned individually for each interface. | ||
227 | */ | ||
228 | struct rc_pid_rateinfo { | ||
229 | |||
230 | /* Map sorted rates to rates in ieee80211_hw_mode. */ | ||
231 | int index; | ||
232 | |||
233 | /* Map rates in ieee80211_hw_mode to sorted rates. */ | ||
234 | int rev_index; | ||
235 | |||
236 | /* Did we do any measurement on this rate? */ | ||
237 | bool valid; | ||
238 | |||
239 | /* Comparison with the lowest rate. */ | ||
240 | int diff; | ||
241 | }; | ||
242 | |||
243 | struct rc_pid_info { | ||
244 | |||
245 | /* The failed frames percentage target. */ | ||
246 | unsigned int target; | ||
247 | |||
248 | /* Rate at which failed frames percentage is sampled in 0.001s. */ | ||
249 | unsigned int sampling_period; | ||
250 | |||
251 | /* P, I and D coefficients. */ | ||
252 | int coeff_p; | ||
253 | int coeff_i; | ||
254 | int coeff_d; | ||
255 | |||
256 | /* Exponential averaging shift. */ | ||
257 | unsigned int smoothing_shift; | ||
258 | |||
259 | /* Sharpening factor and duration. */ | ||
260 | unsigned int sharpen_factor; | ||
261 | unsigned int sharpen_duration; | ||
262 | |||
263 | /* Normalization offset. */ | ||
264 | unsigned int norm_offset; | ||
265 | |||
266 | /* Rates information. */ | ||
267 | struct rc_pid_rateinfo *rinfo; | ||
268 | |||
269 | /* Index of the last used rate. */ | ||
270 | int oldrate; | ||
271 | |||
272 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
273 | /* Debugfs entries created for the parameters above. */ | ||
274 | struct rc_pid_debugfs_entries dentries; | ||
275 | #endif | ||
276 | }; | ||
277 | |||
278 | #endif /* RC80211_PID_H */ | ||
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c deleted file mode 100644 index d0da2a70fe68..000000000000 --- a/net/mac80211/rc80211_pid_algo.c +++ /dev/null | |||
@@ -1,478 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright 2002-2005, Instant802 Networks, Inc. | ||
3 | * Copyright 2005, Devicescape Software, Inc. | ||
4 | * Copyright 2007, Mattias Nissler <mattias.nissler@gmx.de> | ||
5 | * Copyright 2007-2008, Stefano Brivio <stefano.brivio@polimi.it> | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | */ | ||
11 | |||
12 | #include <linux/netdevice.h> | ||
13 | #include <linux/types.h> | ||
14 | #include <linux/skbuff.h> | ||
15 | #include <linux/debugfs.h> | ||
16 | #include <linux/slab.h> | ||
17 | #include <net/mac80211.h> | ||
18 | #include "rate.h" | ||
19 | #include "mesh.h" | ||
20 | #include "rc80211_pid.h" | ||
21 | |||
22 | |||
23 | /* This is an implementation of a TX rate control algorithm that uses a PID | ||
24 | * controller. Given a target failed frames rate, the controller decides about | ||
25 | * TX rate changes to meet the target failed frames rate. | ||
26 | * | ||
27 | * The controller basically computes the following: | ||
28 | * | ||
29 | * adj = CP * err + CI * err_avg + CD * (err - last_err) * (1 + sharpening) | ||
30 | * | ||
31 | * where | ||
32 | * adj adjustment value that is used to switch TX rate (see below) | ||
33 | * err current error: target vs. current failed frames percentage | ||
34 | * last_err last error | ||
35 | * err_avg average (i.e. poor man's integral) of recent errors | ||
36 | * sharpening non-zero when fast response is needed (i.e. right after | ||
37 | * association or no frames sent for a long time), heading | ||
38 | * to zero over time | ||
39 | * CP Proportional coefficient | ||
40 | * CI Integral coefficient | ||
41 | * CD Derivative coefficient | ||
42 | * | ||
43 | * CP, CI, CD are subject to careful tuning. | ||
44 | * | ||
45 | * The integral component uses a exponential moving average approach instead of | ||
46 | * an actual sliding window. The advantage is that we don't need to keep an | ||
47 | * array of the last N error values and computation is easier. | ||
48 | * | ||
49 | * Once we have the adj value, we map it to a rate by means of a learning | ||
50 | * algorithm. This algorithm keeps the state of the percentual failed frames | ||
51 | * difference between rates. The behaviour of the lowest available rate is kept | ||
52 | * as a reference value, and every time we switch between two rates, we compute | ||
53 | * the difference between the failed frames each rate exhibited. By doing so, | ||
54 | * we compare behaviours which different rates exhibited in adjacent timeslices, | ||
55 | * thus the comparison is minimally affected by external conditions. This | ||
56 | * difference gets propagated to the whole set of measurements, so that the | ||
57 | * reference is always the same. Periodically, we normalize this set so that | ||
58 | * recent events weigh the most. By comparing the adj value with this set, we | ||
59 | * avoid pejorative switches to lower rates and allow for switches to higher | ||
60 | * rates if they behaved well. | ||
61 | * | ||
62 | * Note that for the computations we use a fixed-point representation to avoid | ||
63 | * floating point arithmetic. Hence, all values are shifted left by | ||
64 | * RC_PID_ARITH_SHIFT. | ||
65 | */ | ||
66 | |||
67 | |||
68 | /* Adjust the rate while ensuring that we won't switch to a lower rate if it | ||
69 | * exhibited a worse failed frames behaviour and we'll choose the highest rate | ||
70 | * whose failed frames behaviour is not worse than the one of the original rate | ||
71 | * target. While at it, check that the new rate is valid. */ | ||
72 | static void rate_control_pid_adjust_rate(struct ieee80211_supported_band *sband, | ||
73 | struct ieee80211_sta *sta, | ||
74 | struct rc_pid_sta_info *spinfo, int adj, | ||
75 | struct rc_pid_rateinfo *rinfo) | ||
76 | { | ||
77 | int cur_sorted, new_sorted, probe, tmp, n_bitrates, band; | ||
78 | int cur = spinfo->txrate_idx; | ||
79 | |||
80 | band = sband->band; | ||
81 | n_bitrates = sband->n_bitrates; | ||
82 | |||
83 | /* Map passed arguments to sorted values. */ | ||
84 | cur_sorted = rinfo[cur].rev_index; | ||
85 | new_sorted = cur_sorted + adj; | ||
86 | |||
87 | /* Check limits. */ | ||
88 | if (new_sorted < 0) | ||
89 | new_sorted = rinfo[0].rev_index; | ||
90 | else if (new_sorted >= n_bitrates) | ||
91 | new_sorted = rinfo[n_bitrates - 1].rev_index; | ||
92 | |||
93 | tmp = new_sorted; | ||
94 | |||
95 | if (adj < 0) { | ||
96 | /* Ensure that the rate decrease isn't disadvantageous. */ | ||
97 | for (probe = cur_sorted; probe >= new_sorted; probe--) | ||
98 | if (rinfo[probe].diff <= rinfo[cur_sorted].diff && | ||
99 | rate_supported(sta, band, rinfo[probe].index)) | ||
100 | tmp = probe; | ||
101 | } else { | ||
102 | /* Look for rate increase with zero (or below) cost. */ | ||
103 | for (probe = new_sorted + 1; probe < n_bitrates; probe++) | ||
104 | if (rinfo[probe].diff <= rinfo[new_sorted].diff && | ||
105 | rate_supported(sta, band, rinfo[probe].index)) | ||
106 | tmp = probe; | ||
107 | } | ||
108 | |||
109 | /* Fit the rate found to the nearest supported rate. */ | ||
110 | do { | ||
111 | if (rate_supported(sta, band, rinfo[tmp].index)) { | ||
112 | spinfo->txrate_idx = rinfo[tmp].index; | ||
113 | break; | ||
114 | } | ||
115 | if (adj < 0) | ||
116 | tmp--; | ||
117 | else | ||
118 | tmp++; | ||
119 | } while (tmp < n_bitrates && tmp >= 0); | ||
120 | |||
121 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
122 | rate_control_pid_event_rate_change(&spinfo->events, | ||
123 | spinfo->txrate_idx, | ||
124 | sband->bitrates[spinfo->txrate_idx].bitrate); | ||
125 | #endif | ||
126 | } | ||
127 | |||
128 | /* Normalize the failed frames per-rate differences. */ | ||
129 | static void rate_control_pid_normalize(struct rc_pid_info *pinfo, int l) | ||
130 | { | ||
131 | int i, norm_offset = pinfo->norm_offset; | ||
132 | struct rc_pid_rateinfo *r = pinfo->rinfo; | ||
133 | |||
134 | if (r[0].diff > norm_offset) | ||
135 | r[0].diff -= norm_offset; | ||
136 | else if (r[0].diff < -norm_offset) | ||
137 | r[0].diff += norm_offset; | ||
138 | for (i = 0; i < l - 1; i++) | ||
139 | if (r[i + 1].diff > r[i].diff + norm_offset) | ||
140 | r[i + 1].diff -= norm_offset; | ||
141 | else if (r[i + 1].diff <= r[i].diff) | ||
142 | r[i + 1].diff += norm_offset; | ||
143 | } | ||
144 | |||
145 | static void rate_control_pid_sample(struct rc_pid_info *pinfo, | ||
146 | struct ieee80211_supported_band *sband, | ||
147 | struct ieee80211_sta *sta, | ||
148 | struct rc_pid_sta_info *spinfo) | ||
149 | { | ||
150 | struct rc_pid_rateinfo *rinfo = pinfo->rinfo; | ||
151 | u32 pf; | ||
152 | s32 err_avg; | ||
153 | u32 err_prop; | ||
154 | u32 err_int; | ||
155 | u32 err_der; | ||
156 | int adj, i, j, tmp; | ||
157 | unsigned long period; | ||
158 | |||
159 | /* In case nothing happened during the previous control interval, turn | ||
160 | * the sharpening factor on. */ | ||
161 | period = msecs_to_jiffies(pinfo->sampling_period); | ||
162 | if (jiffies - spinfo->last_sample > 2 * period) | ||
163 | spinfo->sharp_cnt = pinfo->sharpen_duration; | ||
164 | |||
165 | spinfo->last_sample = jiffies; | ||
166 | |||
167 | /* This should never happen, but in case, we assume the old sample is | ||
168 | * still a good measurement and copy it. */ | ||
169 | if (unlikely(spinfo->tx_num_xmit == 0)) | ||
170 | pf = spinfo->last_pf; | ||
171 | else | ||
172 | pf = spinfo->tx_num_failed * 100 / spinfo->tx_num_xmit; | ||
173 | |||
174 | spinfo->tx_num_xmit = 0; | ||
175 | spinfo->tx_num_failed = 0; | ||
176 | |||
177 | /* If we just switched rate, update the rate behaviour info. */ | ||
178 | if (pinfo->oldrate != spinfo->txrate_idx) { | ||
179 | |||
180 | i = rinfo[pinfo->oldrate].rev_index; | ||
181 | j = rinfo[spinfo->txrate_idx].rev_index; | ||
182 | |||
183 | tmp = (pf - spinfo->last_pf); | ||
184 | tmp = RC_PID_DO_ARITH_RIGHT_SHIFT(tmp, RC_PID_ARITH_SHIFT); | ||
185 | |||
186 | rinfo[j].diff = rinfo[i].diff + tmp; | ||
187 | pinfo->oldrate = spinfo->txrate_idx; | ||
188 | } | ||
189 | rate_control_pid_normalize(pinfo, sband->n_bitrates); | ||
190 | |||
191 | /* Compute the proportional, integral and derivative errors. */ | ||
192 | err_prop = (pinfo->target - pf) << RC_PID_ARITH_SHIFT; | ||
193 | |||
194 | err_avg = spinfo->err_avg_sc >> pinfo->smoothing_shift; | ||
195 | spinfo->err_avg_sc = spinfo->err_avg_sc - err_avg + err_prop; | ||
196 | err_int = spinfo->err_avg_sc >> pinfo->smoothing_shift; | ||
197 | |||
198 | err_der = (pf - spinfo->last_pf) * | ||
199 | (1 + pinfo->sharpen_factor * spinfo->sharp_cnt); | ||
200 | spinfo->last_pf = pf; | ||
201 | if (spinfo->sharp_cnt) | ||
202 | spinfo->sharp_cnt--; | ||
203 | |||
204 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
205 | rate_control_pid_event_pf_sample(&spinfo->events, pf, err_prop, err_int, | ||
206 | err_der); | ||
207 | #endif | ||
208 | |||
209 | /* Compute the controller output. */ | ||
210 | adj = (err_prop * pinfo->coeff_p + err_int * pinfo->coeff_i | ||
211 | + err_der * pinfo->coeff_d); | ||
212 | adj = RC_PID_DO_ARITH_RIGHT_SHIFT(adj, 2 * RC_PID_ARITH_SHIFT); | ||
213 | |||
214 | /* Change rate. */ | ||
215 | if (adj) | ||
216 | rate_control_pid_adjust_rate(sband, sta, spinfo, adj, rinfo); | ||
217 | } | ||
218 | |||
219 | static void rate_control_pid_tx_status(void *priv, struct ieee80211_supported_band *sband, | ||
220 | struct ieee80211_sta *sta, void *priv_sta, | ||
221 | struct sk_buff *skb) | ||
222 | { | ||
223 | struct rc_pid_info *pinfo = priv; | ||
224 | struct rc_pid_sta_info *spinfo = priv_sta; | ||
225 | unsigned long period; | ||
226 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
227 | |||
228 | if (!spinfo) | ||
229 | return; | ||
230 | |||
231 | /* Ignore all frames that were sent with a different rate than the rate | ||
232 | * we currently advise mac80211 to use. */ | ||
233 | if (info->status.rates[0].idx != spinfo->txrate_idx) | ||
234 | return; | ||
235 | |||
236 | spinfo->tx_num_xmit++; | ||
237 | |||
238 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
239 | rate_control_pid_event_tx_status(&spinfo->events, info); | ||
240 | #endif | ||
241 | |||
242 | /* We count frames that totally failed to be transmitted as two bad | ||
243 | * frames, those that made it out but had some retries as one good and | ||
244 | * one bad frame. */ | ||
245 | if (!(info->flags & IEEE80211_TX_STAT_ACK)) { | ||
246 | spinfo->tx_num_failed += 2; | ||
247 | spinfo->tx_num_xmit++; | ||
248 | } else if (info->status.rates[0].count > 1) { | ||
249 | spinfo->tx_num_failed++; | ||
250 | spinfo->tx_num_xmit++; | ||
251 | } | ||
252 | |||
253 | /* Update PID controller state. */ | ||
254 | period = msecs_to_jiffies(pinfo->sampling_period); | ||
255 | if (time_after(jiffies, spinfo->last_sample + period)) | ||
256 | rate_control_pid_sample(pinfo, sband, sta, spinfo); | ||
257 | } | ||
258 | |||
259 | static void | ||
260 | rate_control_pid_get_rate(void *priv, struct ieee80211_sta *sta, | ||
261 | void *priv_sta, | ||
262 | struct ieee80211_tx_rate_control *txrc) | ||
263 | { | ||
264 | struct sk_buff *skb = txrc->skb; | ||
265 | struct ieee80211_supported_band *sband = txrc->sband; | ||
266 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
267 | struct rc_pid_sta_info *spinfo = priv_sta; | ||
268 | int rateidx; | ||
269 | |||
270 | if (txrc->rts) | ||
271 | info->control.rates[0].count = | ||
272 | txrc->hw->conf.long_frame_max_tx_count; | ||
273 | else | ||
274 | info->control.rates[0].count = | ||
275 | txrc->hw->conf.short_frame_max_tx_count; | ||
276 | |||
277 | /* Send management frames and NO_ACK data using lowest rate. */ | ||
278 | if (rate_control_send_low(sta, priv_sta, txrc)) | ||
279 | return; | ||
280 | |||
281 | rateidx = spinfo->txrate_idx; | ||
282 | |||
283 | if (rateidx >= sband->n_bitrates) | ||
284 | rateidx = sband->n_bitrates - 1; | ||
285 | |||
286 | info->control.rates[0].idx = rateidx; | ||
287 | |||
288 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
289 | rate_control_pid_event_tx_rate(&spinfo->events, | ||
290 | rateidx, sband->bitrates[rateidx].bitrate); | ||
291 | #endif | ||
292 | } | ||
293 | |||
294 | static void | ||
295 | rate_control_pid_rate_init(void *priv, struct ieee80211_supported_band *sband, | ||
296 | struct cfg80211_chan_def *chandef, | ||
297 | struct ieee80211_sta *sta, void *priv_sta) | ||
298 | { | ||
299 | struct rc_pid_sta_info *spinfo = priv_sta; | ||
300 | struct rc_pid_info *pinfo = priv; | ||
301 | struct rc_pid_rateinfo *rinfo = pinfo->rinfo; | ||
302 | int i, j, tmp; | ||
303 | bool s; | ||
304 | |||
305 | /* TODO: This routine should consider using RSSI from previous packets | ||
306 | * as we need to have IEEE 802.1X auth succeed immediately after assoc.. | ||
307 | * Until that method is implemented, we will use the lowest supported | ||
308 | * rate as a workaround. */ | ||
309 | |||
310 | /* Sort the rates. This is optimized for the most common case (i.e. | ||
311 | * almost-sorted CCK+OFDM rates). Kind of bubble-sort with reversed | ||
312 | * mapping too. */ | ||
313 | for (i = 0; i < sband->n_bitrates; i++) { | ||
314 | rinfo[i].index = i; | ||
315 | rinfo[i].rev_index = i; | ||
316 | if (RC_PID_FAST_START) | ||
317 | rinfo[i].diff = 0; | ||
318 | else | ||
319 | rinfo[i].diff = i * pinfo->norm_offset; | ||
320 | } | ||
321 | for (i = 1; i < sband->n_bitrates; i++) { | ||
322 | s = false; | ||
323 | for (j = 0; j < sband->n_bitrates - i; j++) | ||
324 | if (unlikely(sband->bitrates[rinfo[j].index].bitrate > | ||
325 | sband->bitrates[rinfo[j + 1].index].bitrate)) { | ||
326 | tmp = rinfo[j].index; | ||
327 | rinfo[j].index = rinfo[j + 1].index; | ||
328 | rinfo[j + 1].index = tmp; | ||
329 | rinfo[rinfo[j].index].rev_index = j; | ||
330 | rinfo[rinfo[j + 1].index].rev_index = j + 1; | ||
331 | s = true; | ||
332 | } | ||
333 | if (!s) | ||
334 | break; | ||
335 | } | ||
336 | |||
337 | spinfo->txrate_idx = rate_lowest_index(sband, sta); | ||
338 | } | ||
339 | |||
340 | static void *rate_control_pid_alloc(struct ieee80211_hw *hw, | ||
341 | struct dentry *debugfsdir) | ||
342 | { | ||
343 | struct rc_pid_info *pinfo; | ||
344 | struct rc_pid_rateinfo *rinfo; | ||
345 | struct ieee80211_supported_band *sband; | ||
346 | int i, max_rates = 0; | ||
347 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
348 | struct rc_pid_debugfs_entries *de; | ||
349 | #endif | ||
350 | |||
351 | pinfo = kmalloc(sizeof(*pinfo), GFP_ATOMIC); | ||
352 | if (!pinfo) | ||
353 | return NULL; | ||
354 | |||
355 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { | ||
356 | sband = hw->wiphy->bands[i]; | ||
357 | if (sband && sband->n_bitrates > max_rates) | ||
358 | max_rates = sband->n_bitrates; | ||
359 | } | ||
360 | |||
361 | rinfo = kmalloc(sizeof(*rinfo) * max_rates, GFP_ATOMIC); | ||
362 | if (!rinfo) { | ||
363 | kfree(pinfo); | ||
364 | return NULL; | ||
365 | } | ||
366 | |||
367 | pinfo->target = RC_PID_TARGET_PF; | ||
368 | pinfo->sampling_period = RC_PID_INTERVAL; | ||
369 | pinfo->coeff_p = RC_PID_COEFF_P; | ||
370 | pinfo->coeff_i = RC_PID_COEFF_I; | ||
371 | pinfo->coeff_d = RC_PID_COEFF_D; | ||
372 | pinfo->smoothing_shift = RC_PID_SMOOTHING_SHIFT; | ||
373 | pinfo->sharpen_factor = RC_PID_SHARPENING_FACTOR; | ||
374 | pinfo->sharpen_duration = RC_PID_SHARPENING_DURATION; | ||
375 | pinfo->norm_offset = RC_PID_NORM_OFFSET; | ||
376 | pinfo->rinfo = rinfo; | ||
377 | pinfo->oldrate = 0; | ||
378 | |||
379 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
380 | de = &pinfo->dentries; | ||
381 | de->target = debugfs_create_u32("target_pf", S_IRUSR | S_IWUSR, | ||
382 | debugfsdir, &pinfo->target); | ||
383 | de->sampling_period = debugfs_create_u32("sampling_period", | ||
384 | S_IRUSR | S_IWUSR, debugfsdir, | ||
385 | &pinfo->sampling_period); | ||
386 | de->coeff_p = debugfs_create_u32("coeff_p", S_IRUSR | S_IWUSR, | ||
387 | debugfsdir, (u32 *)&pinfo->coeff_p); | ||
388 | de->coeff_i = debugfs_create_u32("coeff_i", S_IRUSR | S_IWUSR, | ||
389 | debugfsdir, (u32 *)&pinfo->coeff_i); | ||
390 | de->coeff_d = debugfs_create_u32("coeff_d", S_IRUSR | S_IWUSR, | ||
391 | debugfsdir, (u32 *)&pinfo->coeff_d); | ||
392 | de->smoothing_shift = debugfs_create_u32("smoothing_shift", | ||
393 | S_IRUSR | S_IWUSR, debugfsdir, | ||
394 | &pinfo->smoothing_shift); | ||
395 | de->sharpen_factor = debugfs_create_u32("sharpen_factor", | ||
396 | S_IRUSR | S_IWUSR, debugfsdir, | ||
397 | &pinfo->sharpen_factor); | ||
398 | de->sharpen_duration = debugfs_create_u32("sharpen_duration", | ||
399 | S_IRUSR | S_IWUSR, debugfsdir, | ||
400 | &pinfo->sharpen_duration); | ||
401 | de->norm_offset = debugfs_create_u32("norm_offset", | ||
402 | S_IRUSR | S_IWUSR, debugfsdir, | ||
403 | &pinfo->norm_offset); | ||
404 | #endif | ||
405 | |||
406 | return pinfo; | ||
407 | } | ||
408 | |||
409 | static void rate_control_pid_free(void *priv) | ||
410 | { | ||
411 | struct rc_pid_info *pinfo = priv; | ||
412 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
413 | struct rc_pid_debugfs_entries *de = &pinfo->dentries; | ||
414 | |||
415 | debugfs_remove(de->norm_offset); | ||
416 | debugfs_remove(de->sharpen_duration); | ||
417 | debugfs_remove(de->sharpen_factor); | ||
418 | debugfs_remove(de->smoothing_shift); | ||
419 | debugfs_remove(de->coeff_d); | ||
420 | debugfs_remove(de->coeff_i); | ||
421 | debugfs_remove(de->coeff_p); | ||
422 | debugfs_remove(de->sampling_period); | ||
423 | debugfs_remove(de->target); | ||
424 | #endif | ||
425 | |||
426 | kfree(pinfo->rinfo); | ||
427 | kfree(pinfo); | ||
428 | } | ||
429 | |||
430 | static void *rate_control_pid_alloc_sta(void *priv, struct ieee80211_sta *sta, | ||
431 | gfp_t gfp) | ||
432 | { | ||
433 | struct rc_pid_sta_info *spinfo; | ||
434 | |||
435 | spinfo = kzalloc(sizeof(*spinfo), gfp); | ||
436 | if (spinfo == NULL) | ||
437 | return NULL; | ||
438 | |||
439 | spinfo->last_sample = jiffies; | ||
440 | |||
441 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
442 | spin_lock_init(&spinfo->events.lock); | ||
443 | init_waitqueue_head(&spinfo->events.waitqueue); | ||
444 | #endif | ||
445 | |||
446 | return spinfo; | ||
447 | } | ||
448 | |||
449 | static void rate_control_pid_free_sta(void *priv, struct ieee80211_sta *sta, | ||
450 | void *priv_sta) | ||
451 | { | ||
452 | kfree(priv_sta); | ||
453 | } | ||
454 | |||
455 | static const struct rate_control_ops mac80211_rcpid = { | ||
456 | .name = "pid", | ||
457 | .tx_status = rate_control_pid_tx_status, | ||
458 | .get_rate = rate_control_pid_get_rate, | ||
459 | .rate_init = rate_control_pid_rate_init, | ||
460 | .alloc = rate_control_pid_alloc, | ||
461 | .free = rate_control_pid_free, | ||
462 | .alloc_sta = rate_control_pid_alloc_sta, | ||
463 | .free_sta = rate_control_pid_free_sta, | ||
464 | #ifdef CONFIG_MAC80211_DEBUGFS | ||
465 | .add_sta_debugfs = rate_control_pid_add_sta_debugfs, | ||
466 | .remove_sta_debugfs = rate_control_pid_remove_sta_debugfs, | ||
467 | #endif | ||
468 | }; | ||
469 | |||
470 | int __init rc80211_pid_init(void) | ||
471 | { | ||
472 | return ieee80211_rate_control_register(&mac80211_rcpid); | ||
473 | } | ||
474 | |||
475 | void rc80211_pid_exit(void) | ||
476 | { | ||
477 | ieee80211_rate_control_unregister(&mac80211_rcpid); | ||
478 | } | ||
diff --git a/net/mac80211/rc80211_pid_debugfs.c b/net/mac80211/rc80211_pid_debugfs.c deleted file mode 100644 index 6ff134650a84..000000000000 --- a/net/mac80211/rc80211_pid_debugfs.c +++ /dev/null | |||
@@ -1,228 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright 2007, Mattias Nissler <mattias.nissler@gmx.de> | ||
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/sched.h> | ||
10 | #include <linux/spinlock.h> | ||
11 | #include <linux/poll.h> | ||
12 | #include <linux/netdevice.h> | ||
13 | #include <linux/types.h> | ||
14 | #include <linux/skbuff.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/export.h> | ||
17 | |||
18 | #include <net/mac80211.h> | ||
19 | #include "rate.h" | ||
20 | |||
21 | #include "rc80211_pid.h" | ||
22 | |||
23 | static void rate_control_pid_event(struct rc_pid_event_buffer *buf, | ||
24 | enum rc_pid_event_type type, | ||
25 | union rc_pid_event_data *data) | ||
26 | { | ||
27 | struct rc_pid_event *ev; | ||
28 | unsigned long status; | ||
29 | |||
30 | spin_lock_irqsave(&buf->lock, status); | ||
31 | ev = &(buf->ring[buf->next_entry]); | ||
32 | buf->next_entry = (buf->next_entry + 1) % RC_PID_EVENT_RING_SIZE; | ||
33 | |||
34 | ev->timestamp = jiffies; | ||
35 | ev->id = buf->ev_count++; | ||
36 | ev->type = type; | ||
37 | ev->data = *data; | ||
38 | |||
39 | spin_unlock_irqrestore(&buf->lock, status); | ||
40 | |||
41 | wake_up_all(&buf->waitqueue); | ||
42 | } | ||
43 | |||
44 | void rate_control_pid_event_tx_status(struct rc_pid_event_buffer *buf, | ||
45 | struct ieee80211_tx_info *stat) | ||
46 | { | ||
47 | union rc_pid_event_data evd; | ||
48 | |||
49 | evd.flags = stat->flags; | ||
50 | memcpy(&evd.tx_status, stat, sizeof(struct ieee80211_tx_info)); | ||
51 | rate_control_pid_event(buf, RC_PID_EVENT_TYPE_TX_STATUS, &evd); | ||
52 | } | ||
53 | |||
54 | void rate_control_pid_event_rate_change(struct rc_pid_event_buffer *buf, | ||
55 | int index, int rate) | ||
56 | { | ||
57 | union rc_pid_event_data evd; | ||
58 | |||
59 | evd.index = index; | ||
60 | evd.rate = rate; | ||
61 | rate_control_pid_event(buf, RC_PID_EVENT_TYPE_RATE_CHANGE, &evd); | ||
62 | } | ||
63 | |||
64 | void rate_control_pid_event_tx_rate(struct rc_pid_event_buffer *buf, | ||
65 | int index, int rate) | ||
66 | { | ||
67 | union rc_pid_event_data evd; | ||
68 | |||
69 | evd.index = index; | ||
70 | evd.rate = rate; | ||
71 | rate_control_pid_event(buf, RC_PID_EVENT_TYPE_TX_RATE, &evd); | ||
72 | } | ||
73 | |||
74 | void rate_control_pid_event_pf_sample(struct rc_pid_event_buffer *buf, | ||
75 | s32 pf_sample, s32 prop_err, | ||
76 | s32 int_err, s32 der_err) | ||
77 | { | ||
78 | union rc_pid_event_data evd; | ||
79 | |||
80 | evd.pf_sample = pf_sample; | ||
81 | evd.prop_err = prop_err; | ||
82 | evd.int_err = int_err; | ||
83 | evd.der_err = der_err; | ||
84 | rate_control_pid_event(buf, RC_PID_EVENT_TYPE_PF_SAMPLE, &evd); | ||
85 | } | ||
86 | |||
87 | static int rate_control_pid_events_open(struct inode *inode, struct file *file) | ||
88 | { | ||
89 | struct rc_pid_sta_info *sinfo = inode->i_private; | ||
90 | struct rc_pid_event_buffer *events = &sinfo->events; | ||
91 | struct rc_pid_events_file_info *file_info; | ||
92 | unsigned long status; | ||
93 | |||
94 | /* Allocate a state struct */ | ||
95 | file_info = kmalloc(sizeof(*file_info), GFP_KERNEL); | ||
96 | if (file_info == NULL) | ||
97 | return -ENOMEM; | ||
98 | |||
99 | spin_lock_irqsave(&events->lock, status); | ||
100 | |||
101 | file_info->next_entry = events->next_entry; | ||
102 | file_info->events = events; | ||
103 | |||
104 | spin_unlock_irqrestore(&events->lock, status); | ||
105 | |||
106 | file->private_data = file_info; | ||
107 | |||
108 | return 0; | ||
109 | } | ||
110 | |||
111 | static int rate_control_pid_events_release(struct inode *inode, | ||
112 | struct file *file) | ||
113 | { | ||
114 | struct rc_pid_events_file_info *file_info = file->private_data; | ||
115 | |||
116 | kfree(file_info); | ||
117 | |||
118 | return 0; | ||
119 | } | ||
120 | |||
121 | static unsigned int rate_control_pid_events_poll(struct file *file, | ||
122 | poll_table *wait) | ||
123 | { | ||
124 | struct rc_pid_events_file_info *file_info = file->private_data; | ||
125 | |||
126 | poll_wait(file, &file_info->events->waitqueue, wait); | ||
127 | |||
128 | return POLLIN | POLLRDNORM; | ||
129 | } | ||
130 | |||
131 | #define RC_PID_PRINT_BUF_SIZE 64 | ||
132 | |||
133 | static ssize_t rate_control_pid_events_read(struct file *file, char __user *buf, | ||
134 | size_t length, loff_t *offset) | ||
135 | { | ||
136 | struct rc_pid_events_file_info *file_info = file->private_data; | ||
137 | struct rc_pid_event_buffer *events = file_info->events; | ||
138 | struct rc_pid_event *ev; | ||
139 | char pb[RC_PID_PRINT_BUF_SIZE]; | ||
140 | int ret; | ||
141 | int p; | ||
142 | unsigned long status; | ||
143 | |||
144 | /* Check if there is something to read. */ | ||
145 | if (events->next_entry == file_info->next_entry) { | ||
146 | if (file->f_flags & O_NONBLOCK) | ||
147 | return -EAGAIN; | ||
148 | |||
149 | /* Wait */ | ||
150 | ret = wait_event_interruptible(events->waitqueue, | ||
151 | events->next_entry != file_info->next_entry); | ||
152 | |||
153 | if (ret) | ||
154 | return ret; | ||
155 | } | ||
156 | |||
157 | /* Write out one event per call. I don't care whether it's a little | ||
158 | * inefficient, this is debugging code anyway. */ | ||
159 | spin_lock_irqsave(&events->lock, status); | ||
160 | |||
161 | /* Get an event */ | ||
162 | ev = &(events->ring[file_info->next_entry]); | ||
163 | file_info->next_entry = (file_info->next_entry + 1) % | ||
164 | RC_PID_EVENT_RING_SIZE; | ||
165 | |||
166 | /* Print information about the event. Note that userspace needs to | ||
167 | * provide large enough buffers. */ | ||
168 | length = length < RC_PID_PRINT_BUF_SIZE ? | ||
169 | length : RC_PID_PRINT_BUF_SIZE; | ||
170 | p = scnprintf(pb, length, "%u %lu ", ev->id, ev->timestamp); | ||
171 | switch (ev->type) { | ||
172 | case RC_PID_EVENT_TYPE_TX_STATUS: | ||
173 | p += scnprintf(pb + p, length - p, "tx_status %u %u", | ||
174 | !(ev->data.flags & IEEE80211_TX_STAT_ACK), | ||
175 | ev->data.tx_status.status.rates[0].idx); | ||
176 | break; | ||
177 | case RC_PID_EVENT_TYPE_RATE_CHANGE: | ||
178 | p += scnprintf(pb + p, length - p, "rate_change %d %d", | ||
179 | ev->data.index, ev->data.rate); | ||
180 | break; | ||
181 | case RC_PID_EVENT_TYPE_TX_RATE: | ||
182 | p += scnprintf(pb + p, length - p, "tx_rate %d %d", | ||
183 | ev->data.index, ev->data.rate); | ||
184 | break; | ||
185 | case RC_PID_EVENT_TYPE_PF_SAMPLE: | ||
186 | p += scnprintf(pb + p, length - p, | ||
187 | "pf_sample %d %d %d %d", | ||
188 | ev->data.pf_sample, ev->data.prop_err, | ||
189 | ev->data.int_err, ev->data.der_err); | ||
190 | break; | ||
191 | } | ||
192 | p += scnprintf(pb + p, length - p, "\n"); | ||
193 | |||
194 | spin_unlock_irqrestore(&events->lock, status); | ||
195 | |||
196 | if (copy_to_user(buf, pb, p)) | ||
197 | return -EFAULT; | ||
198 | |||
199 | return p; | ||
200 | } | ||
201 | |||
202 | #undef RC_PID_PRINT_BUF_SIZE | ||
203 | |||
204 | static const struct file_operations rc_pid_fop_events = { | ||
205 | .owner = THIS_MODULE, | ||
206 | .read = rate_control_pid_events_read, | ||
207 | .poll = rate_control_pid_events_poll, | ||
208 | .open = rate_control_pid_events_open, | ||
209 | .release = rate_control_pid_events_release, | ||
210 | .llseek = noop_llseek, | ||
211 | }; | ||
212 | |||
213 | void rate_control_pid_add_sta_debugfs(void *priv, void *priv_sta, | ||
214 | struct dentry *dir) | ||
215 | { | ||
216 | struct rc_pid_sta_info *spinfo = priv_sta; | ||
217 | |||
218 | spinfo->events_entry = debugfs_create_file("rc_pid_events", S_IRUGO, | ||
219 | dir, spinfo, | ||
220 | &rc_pid_fop_events); | ||
221 | } | ||
222 | |||
223 | void rate_control_pid_remove_sta_debugfs(void *priv, void *priv_sta) | ||
224 | { | ||
225 | struct rc_pid_sta_info *spinfo = priv_sta; | ||
226 | |||
227 | debugfs_remove(spinfo->events_entry); | ||
228 | } | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 394e201cde6d..bd2c9b22c945 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -688,20 +688,27 @@ static void ieee80211_release_reorder_frame(struct ieee80211_sub_if_data *sdata, | |||
688 | int index, | 688 | int index, |
689 | struct sk_buff_head *frames) | 689 | struct sk_buff_head *frames) |
690 | { | 690 | { |
691 | struct sk_buff *skb = tid_agg_rx->reorder_buf[index]; | 691 | struct sk_buff_head *skb_list = &tid_agg_rx->reorder_buf[index]; |
692 | struct sk_buff *skb; | ||
692 | struct ieee80211_rx_status *status; | 693 | struct ieee80211_rx_status *status; |
693 | 694 | ||
694 | lockdep_assert_held(&tid_agg_rx->reorder_lock); | 695 | lockdep_assert_held(&tid_agg_rx->reorder_lock); |
695 | 696 | ||
696 | if (!skb) | 697 | if (skb_queue_empty(skb_list)) |
698 | goto no_frame; | ||
699 | |||
700 | if (!ieee80211_rx_reorder_ready(skb_list)) { | ||
701 | __skb_queue_purge(skb_list); | ||
697 | goto no_frame; | 702 | goto no_frame; |
703 | } | ||
698 | 704 | ||
699 | /* release the frame from the reorder ring buffer */ | 705 | /* release frames from the reorder ring buffer */ |
700 | tid_agg_rx->stored_mpdu_num--; | 706 | tid_agg_rx->stored_mpdu_num--; |
701 | tid_agg_rx->reorder_buf[index] = NULL; | 707 | while ((skb = __skb_dequeue(skb_list))) { |
702 | status = IEEE80211_SKB_RXCB(skb); | 708 | status = IEEE80211_SKB_RXCB(skb); |
703 | status->rx_flags |= IEEE80211_RX_DEFERRED_RELEASE; | 709 | status->rx_flags |= IEEE80211_RX_DEFERRED_RELEASE; |
704 | __skb_queue_tail(frames, skb); | 710 | __skb_queue_tail(frames, skb); |
711 | } | ||
705 | 712 | ||
706 | no_frame: | 713 | no_frame: |
707 | tid_agg_rx->head_seq_num = ieee80211_sn_inc(tid_agg_rx->head_seq_num); | 714 | tid_agg_rx->head_seq_num = ieee80211_sn_inc(tid_agg_rx->head_seq_num); |
@@ -738,13 +745,13 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, | |||
738 | struct tid_ampdu_rx *tid_agg_rx, | 745 | struct tid_ampdu_rx *tid_agg_rx, |
739 | struct sk_buff_head *frames) | 746 | struct sk_buff_head *frames) |
740 | { | 747 | { |
741 | int index, j; | 748 | int index, i, j; |
742 | 749 | ||
743 | lockdep_assert_held(&tid_agg_rx->reorder_lock); | 750 | lockdep_assert_held(&tid_agg_rx->reorder_lock); |
744 | 751 | ||
745 | /* release the buffer until next missing frame */ | 752 | /* release the buffer until next missing frame */ |
746 | index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size; | 753 | index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size; |
747 | if (!tid_agg_rx->reorder_buf[index] && | 754 | if (!ieee80211_rx_reorder_ready(&tid_agg_rx->reorder_buf[index]) && |
748 | tid_agg_rx->stored_mpdu_num) { | 755 | tid_agg_rx->stored_mpdu_num) { |
749 | /* | 756 | /* |
750 | * No buffers ready to be released, but check whether any | 757 | * No buffers ready to be released, but check whether any |
@@ -753,7 +760,8 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, | |||
753 | int skipped = 1; | 760 | int skipped = 1; |
754 | for (j = (index + 1) % tid_agg_rx->buf_size; j != index; | 761 | for (j = (index + 1) % tid_agg_rx->buf_size; j != index; |
755 | j = (j + 1) % tid_agg_rx->buf_size) { | 762 | j = (j + 1) % tid_agg_rx->buf_size) { |
756 | if (!tid_agg_rx->reorder_buf[j]) { | 763 | if (!ieee80211_rx_reorder_ready( |
764 | &tid_agg_rx->reorder_buf[j])) { | ||
757 | skipped++; | 765 | skipped++; |
758 | continue; | 766 | continue; |
759 | } | 767 | } |
@@ -762,6 +770,11 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, | |||
762 | HT_RX_REORDER_BUF_TIMEOUT)) | 770 | HT_RX_REORDER_BUF_TIMEOUT)) |
763 | goto set_release_timer; | 771 | goto set_release_timer; |
764 | 772 | ||
773 | /* don't leave incomplete A-MSDUs around */ | ||
774 | for (i = (index + 1) % tid_agg_rx->buf_size; i != j; | ||
775 | i = (i + 1) % tid_agg_rx->buf_size) | ||
776 | __skb_queue_purge(&tid_agg_rx->reorder_buf[i]); | ||
777 | |||
765 | ht_dbg_ratelimited(sdata, | 778 | ht_dbg_ratelimited(sdata, |
766 | "release an RX reorder frame due to timeout on earlier frames\n"); | 779 | "release an RX reorder frame due to timeout on earlier frames\n"); |
767 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, j, | 780 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, j, |
@@ -775,7 +788,8 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, | |||
775 | skipped) & IEEE80211_SN_MASK; | 788 | skipped) & IEEE80211_SN_MASK; |
776 | skipped = 0; | 789 | skipped = 0; |
777 | } | 790 | } |
778 | } else while (tid_agg_rx->reorder_buf[index]) { | 791 | } else while (ieee80211_rx_reorder_ready( |
792 | &tid_agg_rx->reorder_buf[index])) { | ||
779 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, index, | 793 | ieee80211_release_reorder_frame(sdata, tid_agg_rx, index, |
780 | frames); | 794 | frames); |
781 | index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size; | 795 | index = tid_agg_rx->head_seq_num % tid_agg_rx->buf_size; |
@@ -786,7 +800,8 @@ static void ieee80211_sta_reorder_release(struct ieee80211_sub_if_data *sdata, | |||
786 | 800 | ||
787 | for (; j != (index - 1) % tid_agg_rx->buf_size; | 801 | for (; j != (index - 1) % tid_agg_rx->buf_size; |
788 | j = (j + 1) % tid_agg_rx->buf_size) { | 802 | j = (j + 1) % tid_agg_rx->buf_size) { |
789 | if (tid_agg_rx->reorder_buf[j]) | 803 | if (ieee80211_rx_reorder_ready( |
804 | &tid_agg_rx->reorder_buf[j])) | ||
790 | break; | 805 | break; |
791 | } | 806 | } |
792 | 807 | ||
@@ -811,6 +826,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata | |||
811 | struct sk_buff_head *frames) | 826 | struct sk_buff_head *frames) |
812 | { | 827 | { |
813 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 828 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
829 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | ||
814 | u16 sc = le16_to_cpu(hdr->seq_ctrl); | 830 | u16 sc = le16_to_cpu(hdr->seq_ctrl); |
815 | u16 mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4; | 831 | u16 mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4; |
816 | u16 head_seq_num, buf_size; | 832 | u16 head_seq_num, buf_size; |
@@ -845,7 +861,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata | |||
845 | index = mpdu_seq_num % tid_agg_rx->buf_size; | 861 | index = mpdu_seq_num % tid_agg_rx->buf_size; |
846 | 862 | ||
847 | /* check if we already stored this frame */ | 863 | /* check if we already stored this frame */ |
848 | if (tid_agg_rx->reorder_buf[index]) { | 864 | if (ieee80211_rx_reorder_ready(&tid_agg_rx->reorder_buf[index])) { |
849 | dev_kfree_skb(skb); | 865 | dev_kfree_skb(skb); |
850 | goto out; | 866 | goto out; |
851 | } | 867 | } |
@@ -858,17 +874,20 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_sub_if_data *sdata | |||
858 | */ | 874 | */ |
859 | if (mpdu_seq_num == tid_agg_rx->head_seq_num && | 875 | if (mpdu_seq_num == tid_agg_rx->head_seq_num && |
860 | tid_agg_rx->stored_mpdu_num == 0) { | 876 | tid_agg_rx->stored_mpdu_num == 0) { |
861 | tid_agg_rx->head_seq_num = | 877 | if (!(status->flag & RX_FLAG_AMSDU_MORE)) |
862 | ieee80211_sn_inc(tid_agg_rx->head_seq_num); | 878 | tid_agg_rx->head_seq_num = |
879 | ieee80211_sn_inc(tid_agg_rx->head_seq_num); | ||
863 | ret = false; | 880 | ret = false; |
864 | goto out; | 881 | goto out; |
865 | } | 882 | } |
866 | 883 | ||
867 | /* put the frame in the reordering buffer */ | 884 | /* put the frame in the reordering buffer */ |
868 | tid_agg_rx->reorder_buf[index] = skb; | 885 | __skb_queue_tail(&tid_agg_rx->reorder_buf[index], skb); |
869 | tid_agg_rx->reorder_time[index] = jiffies; | 886 | if (!(status->flag & RX_FLAG_AMSDU_MORE)) { |
870 | tid_agg_rx->stored_mpdu_num++; | 887 | tid_agg_rx->reorder_time[index] = jiffies; |
871 | ieee80211_sta_reorder_release(sdata, tid_agg_rx, frames); | 888 | tid_agg_rx->stored_mpdu_num++; |
889 | ieee80211_sta_reorder_release(sdata, tid_agg_rx, frames); | ||
890 | } | ||
872 | 891 | ||
873 | out: | 892 | out: |
874 | spin_unlock(&tid_agg_rx->reorder_lock); | 893 | spin_unlock(&tid_agg_rx->reorder_lock); |
@@ -1107,6 +1126,8 @@ static void sta_ps_end(struct sta_info *sta) | |||
1107 | return; | 1126 | return; |
1108 | } | 1127 | } |
1109 | 1128 | ||
1129 | set_sta_flag(sta, WLAN_STA_PS_DELIVER); | ||
1130 | clear_sta_flag(sta, WLAN_STA_PS_STA); | ||
1110 | ieee80211_sta_ps_deliver_wakeup(sta); | 1131 | ieee80211_sta_ps_deliver_wakeup(sta); |
1111 | } | 1132 | } |
1112 | 1133 | ||
@@ -3127,6 +3148,14 @@ static bool prepare_for_handlers(struct ieee80211_rx_data *rx, | |||
3127 | if (!ieee80211_is_beacon(hdr->frame_control)) | 3148 | if (!ieee80211_is_beacon(hdr->frame_control)) |
3128 | return false; | 3149 | return false; |
3129 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; | 3150 | status->rx_flags &= ~IEEE80211_RX_RA_MATCH; |
3151 | } else if (!ieee80211_has_tods(hdr->frame_control)) { | ||
3152 | /* ignore data frames to TDLS-peers */ | ||
3153 | if (ieee80211_is_data(hdr->frame_control)) | ||
3154 | return false; | ||
3155 | /* ignore action frames to TDLS-peers */ | ||
3156 | if (ieee80211_is_action(hdr->frame_control) && | ||
3157 | !ether_addr_equal(bssid, hdr->addr1)) | ||
3158 | return false; | ||
3130 | } | 3159 | } |
3131 | break; | 3160 | break; |
3132 | case NL80211_IFTYPE_WDS: | 3161 | case NL80211_IFTYPE_WDS: |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index f40661eb75b5..a0a938145dcc 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -235,38 +235,51 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local) | |||
235 | { | 235 | { |
236 | struct cfg80211_scan_request *req = local->scan_req; | 236 | struct cfg80211_scan_request *req = local->scan_req; |
237 | struct cfg80211_chan_def chandef; | 237 | struct cfg80211_chan_def chandef; |
238 | enum ieee80211_band band; | 238 | u8 bands_used = 0; |
239 | int i, ielen, n_chans; | 239 | int i, ielen, n_chans; |
240 | 240 | ||
241 | if (test_bit(SCAN_HW_CANCELLED, &local->scanning)) | 241 | if (test_bit(SCAN_HW_CANCELLED, &local->scanning)) |
242 | return false; | 242 | return false; |
243 | 243 | ||
244 | do { | 244 | if (local->hw.flags & IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS) { |
245 | if (local->hw_scan_band == IEEE80211_NUM_BANDS) | ||
246 | return false; | ||
247 | |||
248 | band = local->hw_scan_band; | ||
249 | n_chans = 0; | ||
250 | for (i = 0; i < req->n_channels; i++) { | 245 | for (i = 0; i < req->n_channels; i++) { |
251 | if (req->channels[i]->band == band) { | 246 | local->hw_scan_req->req.channels[i] = req->channels[i]; |
252 | local->hw_scan_req->channels[n_chans] = | 247 | bands_used |= BIT(req->channels[i]->band); |
248 | } | ||
249 | |||
250 | n_chans = req->n_channels; | ||
251 | } else { | ||
252 | do { | ||
253 | if (local->hw_scan_band == IEEE80211_NUM_BANDS) | ||
254 | return false; | ||
255 | |||
256 | n_chans = 0; | ||
257 | |||
258 | for (i = 0; i < req->n_channels; i++) { | ||
259 | if (req->channels[i]->band != | ||
260 | local->hw_scan_band) | ||
261 | continue; | ||
262 | local->hw_scan_req->req.channels[n_chans] = | ||
253 | req->channels[i]; | 263 | req->channels[i]; |
254 | n_chans++; | 264 | n_chans++; |
265 | bands_used |= BIT(req->channels[i]->band); | ||
255 | } | 266 | } |
256 | } | ||
257 | 267 | ||
258 | local->hw_scan_band++; | 268 | local->hw_scan_band++; |
259 | } while (!n_chans); | 269 | } while (!n_chans); |
270 | } | ||
260 | 271 | ||
261 | local->hw_scan_req->n_channels = n_chans; | 272 | local->hw_scan_req->req.n_channels = n_chans; |
262 | ieee80211_prepare_scan_chandef(&chandef, req->scan_width); | 273 | ieee80211_prepare_scan_chandef(&chandef, req->scan_width); |
263 | 274 | ||
264 | ielen = ieee80211_build_preq_ies(local, (u8 *)local->hw_scan_req->ie, | 275 | ielen = ieee80211_build_preq_ies(local, |
276 | (u8 *)local->hw_scan_req->req.ie, | ||
265 | local->hw_scan_ies_bufsize, | 277 | local->hw_scan_ies_bufsize, |
266 | req->ie, req->ie_len, band, | 278 | &local->hw_scan_req->ies, |
267 | req->rates[band], &chandef); | 279 | req->ie, req->ie_len, |
268 | local->hw_scan_req->ie_len = ielen; | 280 | bands_used, req->rates, &chandef); |
269 | local->hw_scan_req->no_cck = req->no_cck; | 281 | local->hw_scan_req->req.ie_len = ielen; |
282 | local->hw_scan_req->req.no_cck = req->no_cck; | ||
270 | 283 | ||
271 | return true; | 284 | return true; |
272 | } | 285 | } |
@@ -291,7 +304,9 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
291 | if (WARN_ON(!local->scan_req)) | 304 | if (WARN_ON(!local->scan_req)) |
292 | return; | 305 | return; |
293 | 306 | ||
294 | if (hw_scan && !aborted && ieee80211_prep_hw_scan(local)) { | 307 | if (hw_scan && !aborted && |
308 | !(local->hw.flags & IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS) && | ||
309 | ieee80211_prep_hw_scan(local)) { | ||
295 | int rc; | 310 | int rc; |
296 | 311 | ||
297 | rc = drv_hw_scan(local, | 312 | rc = drv_hw_scan(local, |
@@ -473,6 +488,21 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
473 | u8 *ies; | 488 | u8 *ies; |
474 | 489 | ||
475 | local->hw_scan_ies_bufsize = local->scan_ies_len + req->ie_len; | 490 | local->hw_scan_ies_bufsize = local->scan_ies_len + req->ie_len; |
491 | |||
492 | if (local->hw.flags & IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS) { | ||
493 | int i, n_bands = 0; | ||
494 | u8 bands_counted = 0; | ||
495 | |||
496 | for (i = 0; i < req->n_channels; i++) { | ||
497 | if (bands_counted & BIT(req->channels[i]->band)) | ||
498 | continue; | ||
499 | bands_counted |= BIT(req->channels[i]->band); | ||
500 | n_bands++; | ||
501 | } | ||
502 | |||
503 | local->hw_scan_ies_bufsize *= n_bands; | ||
504 | } | ||
505 | |||
476 | local->hw_scan_req = kmalloc( | 506 | local->hw_scan_req = kmalloc( |
477 | sizeof(*local->hw_scan_req) + | 507 | sizeof(*local->hw_scan_req) + |
478 | req->n_channels * sizeof(req->channels[0]) + | 508 | req->n_channels * sizeof(req->channels[0]) + |
@@ -480,13 +510,13 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
480 | if (!local->hw_scan_req) | 510 | if (!local->hw_scan_req) |
481 | return -ENOMEM; | 511 | return -ENOMEM; |
482 | 512 | ||
483 | local->hw_scan_req->ssids = req->ssids; | 513 | local->hw_scan_req->req.ssids = req->ssids; |
484 | local->hw_scan_req->n_ssids = req->n_ssids; | 514 | local->hw_scan_req->req.n_ssids = req->n_ssids; |
485 | ies = (u8 *)local->hw_scan_req + | 515 | ies = (u8 *)local->hw_scan_req + |
486 | sizeof(*local->hw_scan_req) + | 516 | sizeof(*local->hw_scan_req) + |
487 | req->n_channels * sizeof(req->channels[0]); | 517 | req->n_channels * sizeof(req->channels[0]); |
488 | local->hw_scan_req->ie = ies; | 518 | local->hw_scan_req->req.ie = ies; |
489 | local->hw_scan_req->flags = req->flags; | 519 | local->hw_scan_req->req.flags = req->flags; |
490 | 520 | ||
491 | local->hw_scan_band = 0; | 521 | local->hw_scan_band = 0; |
492 | 522 | ||
@@ -973,9 +1003,13 @@ int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
973 | struct cfg80211_sched_scan_request *req) | 1003 | struct cfg80211_sched_scan_request *req) |
974 | { | 1004 | { |
975 | struct ieee80211_local *local = sdata->local; | 1005 | struct ieee80211_local *local = sdata->local; |
976 | struct ieee80211_sched_scan_ies sched_scan_ies = {}; | 1006 | struct ieee80211_scan_ies sched_scan_ies = {}; |
977 | struct cfg80211_chan_def chandef; | 1007 | struct cfg80211_chan_def chandef; |
978 | int ret, i, iebufsz; | 1008 | int ret, i, iebufsz, num_bands = 0; |
1009 | u32 rate_masks[IEEE80211_NUM_BANDS] = {}; | ||
1010 | u8 bands_used = 0; | ||
1011 | u8 *ie; | ||
1012 | size_t len; | ||
979 | 1013 | ||
980 | iebufsz = local->scan_ies_len + req->ie_len; | 1014 | iebufsz = local->scan_ies_len + req->ie_len; |
981 | 1015 | ||
@@ -985,33 +1019,35 @@ int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
985 | return -ENOTSUPP; | 1019 | return -ENOTSUPP; |
986 | 1020 | ||
987 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { | 1021 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { |
988 | if (!local->hw.wiphy->bands[i]) | 1022 | if (local->hw.wiphy->bands[i]) { |
989 | continue; | 1023 | bands_used |= BIT(i); |
990 | 1024 | rate_masks[i] = (u32) -1; | |
991 | sched_scan_ies.ie[i] = kzalloc(iebufsz, GFP_KERNEL); | 1025 | num_bands++; |
992 | if (!sched_scan_ies.ie[i]) { | ||
993 | ret = -ENOMEM; | ||
994 | goto out_free; | ||
995 | } | 1026 | } |
1027 | } | ||
996 | 1028 | ||
997 | ieee80211_prepare_scan_chandef(&chandef, req->scan_width); | 1029 | ie = kzalloc(num_bands * iebufsz, GFP_KERNEL); |
998 | 1030 | if (!ie) { | |
999 | sched_scan_ies.len[i] = | 1031 | ret = -ENOMEM; |
1000 | ieee80211_build_preq_ies(local, sched_scan_ies.ie[i], | 1032 | goto out; |
1001 | iebufsz, req->ie, req->ie_len, | ||
1002 | i, (u32) -1, &chandef); | ||
1003 | } | 1033 | } |
1004 | 1034 | ||
1035 | ieee80211_prepare_scan_chandef(&chandef, req->scan_width); | ||
1036 | |||
1037 | len = ieee80211_build_preq_ies(local, ie, num_bands * iebufsz, | ||
1038 | &sched_scan_ies, req->ie, | ||
1039 | req->ie_len, bands_used, | ||
1040 | rate_masks, &chandef); | ||
1041 | |||
1005 | ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies); | 1042 | ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies); |
1006 | if (ret == 0) { | 1043 | if (ret == 0) { |
1007 | rcu_assign_pointer(local->sched_scan_sdata, sdata); | 1044 | rcu_assign_pointer(local->sched_scan_sdata, sdata); |
1008 | local->sched_scan_req = req; | 1045 | local->sched_scan_req = req; |
1009 | } | 1046 | } |
1010 | 1047 | ||
1011 | out_free: | 1048 | kfree(ie); |
1012 | while (i > 0) | ||
1013 | kfree(sched_scan_ies.ie[--i]); | ||
1014 | 1049 | ||
1050 | out: | ||
1015 | if (ret) { | 1051 | if (ret) { |
1016 | /* Clean in case of failure after HW restart or upon resume. */ | 1052 | /* Clean in case of failure after HW restart or upon resume. */ |
1017 | RCU_INIT_POINTER(local->sched_scan_sdata, NULL); | 1053 | RCU_INIT_POINTER(local->sched_scan_sdata, NULL); |
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index a9b46d8ea22f..a1e433b88c66 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c | |||
@@ -100,7 +100,8 @@ static void __cleanup_single_sta(struct sta_info *sta) | |||
100 | struct ps_data *ps; | 100 | struct ps_data *ps; |
101 | 101 | ||
102 | if (test_sta_flag(sta, WLAN_STA_PS_STA) || | 102 | if (test_sta_flag(sta, WLAN_STA_PS_STA) || |
103 | test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { | 103 | test_sta_flag(sta, WLAN_STA_PS_DRIVER) || |
104 | test_sta_flag(sta, WLAN_STA_PS_DELIVER)) { | ||
104 | if (sta->sdata->vif.type == NL80211_IFTYPE_AP || | 105 | if (sta->sdata->vif.type == NL80211_IFTYPE_AP || |
105 | sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 106 | sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
106 | ps = &sdata->bss->ps; | 107 | ps = &sdata->bss->ps; |
@@ -111,6 +112,7 @@ static void __cleanup_single_sta(struct sta_info *sta) | |||
111 | 112 | ||
112 | clear_sta_flag(sta, WLAN_STA_PS_STA); | 113 | clear_sta_flag(sta, WLAN_STA_PS_STA); |
113 | clear_sta_flag(sta, WLAN_STA_PS_DRIVER); | 114 | clear_sta_flag(sta, WLAN_STA_PS_DRIVER); |
115 | clear_sta_flag(sta, WLAN_STA_PS_DELIVER); | ||
114 | 116 | ||
115 | atomic_dec(&ps->num_sta_ps); | 117 | atomic_dec(&ps->num_sta_ps); |
116 | sta_info_recalc_tim(sta); | 118 | sta_info_recalc_tim(sta); |
@@ -125,7 +127,7 @@ static void __cleanup_single_sta(struct sta_info *sta) | |||
125 | if (ieee80211_vif_is_mesh(&sdata->vif)) | 127 | if (ieee80211_vif_is_mesh(&sdata->vif)) |
126 | mesh_sta_cleanup(sta); | 128 | mesh_sta_cleanup(sta); |
127 | 129 | ||
128 | cancel_work_sync(&sta->drv_unblock_wk); | 130 | cancel_work_sync(&sta->drv_deliver_wk); |
129 | 131 | ||
130 | /* | 132 | /* |
131 | * Destroy aggregation state here. It would be nice to wait for the | 133 | * Destroy aggregation state here. It would be nice to wait for the |
@@ -253,33 +255,23 @@ static void sta_info_hash_add(struct ieee80211_local *local, | |||
253 | rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], sta); | 255 | rcu_assign_pointer(local->sta_hash[STA_HASH(sta->sta.addr)], sta); |
254 | } | 256 | } |
255 | 257 | ||
256 | static void sta_unblock(struct work_struct *wk) | 258 | static void sta_deliver_ps_frames(struct work_struct *wk) |
257 | { | 259 | { |
258 | struct sta_info *sta; | 260 | struct sta_info *sta; |
259 | 261 | ||
260 | sta = container_of(wk, struct sta_info, drv_unblock_wk); | 262 | sta = container_of(wk, struct sta_info, drv_deliver_wk); |
261 | 263 | ||
262 | if (sta->dead) | 264 | if (sta->dead) |
263 | return; | 265 | return; |
264 | 266 | ||
265 | if (!test_sta_flag(sta, WLAN_STA_PS_STA)) { | 267 | local_bh_disable(); |
266 | local_bh_disable(); | 268 | if (!test_sta_flag(sta, WLAN_STA_PS_STA)) |
267 | ieee80211_sta_ps_deliver_wakeup(sta); | 269 | ieee80211_sta_ps_deliver_wakeup(sta); |
268 | local_bh_enable(); | 270 | else if (test_and_clear_sta_flag(sta, WLAN_STA_PSPOLL)) |
269 | } else if (test_and_clear_sta_flag(sta, WLAN_STA_PSPOLL)) { | ||
270 | clear_sta_flag(sta, WLAN_STA_PS_DRIVER); | ||
271 | |||
272 | local_bh_disable(); | ||
273 | ieee80211_sta_ps_deliver_poll_response(sta); | 271 | ieee80211_sta_ps_deliver_poll_response(sta); |
274 | local_bh_enable(); | 272 | else if (test_and_clear_sta_flag(sta, WLAN_STA_UAPSD)) |
275 | } else if (test_and_clear_sta_flag(sta, WLAN_STA_UAPSD)) { | ||
276 | clear_sta_flag(sta, WLAN_STA_PS_DRIVER); | ||
277 | |||
278 | local_bh_disable(); | ||
279 | ieee80211_sta_ps_deliver_uapsd(sta); | 273 | ieee80211_sta_ps_deliver_uapsd(sta); |
280 | local_bh_enable(); | 274 | local_bh_enable(); |
281 | } else | ||
282 | clear_sta_flag(sta, WLAN_STA_PS_DRIVER); | ||
283 | } | 275 | } |
284 | 276 | ||
285 | static int sta_prepare_rate_control(struct ieee80211_local *local, | 277 | static int sta_prepare_rate_control(struct ieee80211_local *local, |
@@ -341,7 +333,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
341 | 333 | ||
342 | spin_lock_init(&sta->lock); | 334 | spin_lock_init(&sta->lock); |
343 | spin_lock_init(&sta->ps_lock); | 335 | spin_lock_init(&sta->ps_lock); |
344 | INIT_WORK(&sta->drv_unblock_wk, sta_unblock); | 336 | INIT_WORK(&sta->drv_deliver_wk, sta_deliver_ps_frames); |
345 | INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); | 337 | INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work); |
346 | mutex_init(&sta->ampdu_mlme.mtx); | 338 | mutex_init(&sta->ampdu_mlme.mtx); |
347 | #ifdef CONFIG_MAC80211_MESH | 339 | #ifdef CONFIG_MAC80211_MESH |
@@ -358,7 +350,7 @@ struct sta_info *sta_info_alloc(struct ieee80211_sub_if_data *sdata, | |||
358 | 350 | ||
359 | sta->sta_state = IEEE80211_STA_NONE; | 351 | sta->sta_state = IEEE80211_STA_NONE; |
360 | 352 | ||
361 | do_posix_clock_monotonic_gettime(&uptime); | 353 | ktime_get_ts(&uptime); |
362 | sta->last_connected = uptime.tv_sec; | 354 | sta->last_connected = uptime.tv_sec; |
363 | ewma_init(&sta->avg_signal, 1024, 8); | 355 | ewma_init(&sta->avg_signal, 1024, 8); |
364 | for (i = 0; i < ARRAY_SIZE(sta->chain_signal_avg); i++) | 356 | for (i = 0; i < ARRAY_SIZE(sta->chain_signal_avg); i++) |
@@ -1102,8 +1094,11 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | |||
1102 | unsigned long flags; | 1094 | unsigned long flags; |
1103 | struct ps_data *ps; | 1095 | struct ps_data *ps; |
1104 | 1096 | ||
1105 | if (sdata->vif.type == NL80211_IFTYPE_AP || | 1097 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) |
1106 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 1098 | sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, |
1099 | u.ap); | ||
1100 | |||
1101 | if (sdata->vif.type == NL80211_IFTYPE_AP) | ||
1107 | ps = &sdata->bss->ps; | 1102 | ps = &sdata->bss->ps; |
1108 | else if (ieee80211_vif_is_mesh(&sdata->vif)) | 1103 | else if (ieee80211_vif_is_mesh(&sdata->vif)) |
1109 | ps = &sdata->u.mesh.ps; | 1104 | ps = &sdata->u.mesh.ps; |
@@ -1141,8 +1136,15 @@ void ieee80211_sta_ps_deliver_wakeup(struct sta_info *sta) | |||
1141 | } | 1136 | } |
1142 | 1137 | ||
1143 | ieee80211_add_pending_skbs(local, &pending); | 1138 | ieee80211_add_pending_skbs(local, &pending); |
1144 | clear_sta_flag(sta, WLAN_STA_PS_DRIVER); | 1139 | |
1145 | clear_sta_flag(sta, WLAN_STA_PS_STA); | 1140 | /* now we're no longer in the deliver code */ |
1141 | clear_sta_flag(sta, WLAN_STA_PS_DELIVER); | ||
1142 | |||
1143 | /* The station might have polled and then woken up before we responded, | ||
1144 | * so clear these flags now to avoid them sticking around. | ||
1145 | */ | ||
1146 | clear_sta_flag(sta, WLAN_STA_PSPOLL); | ||
1147 | clear_sta_flag(sta, WLAN_STA_UAPSD); | ||
1146 | spin_unlock(&sta->ps_lock); | 1148 | spin_unlock(&sta->ps_lock); |
1147 | 1149 | ||
1148 | atomic_dec(&ps->num_sta_ps); | 1150 | atomic_dec(&ps->num_sta_ps); |
@@ -1543,10 +1545,26 @@ void ieee80211_sta_block_awake(struct ieee80211_hw *hw, | |||
1543 | 1545 | ||
1544 | trace_api_sta_block_awake(sta->local, pubsta, block); | 1546 | trace_api_sta_block_awake(sta->local, pubsta, block); |
1545 | 1547 | ||
1546 | if (block) | 1548 | if (block) { |
1547 | set_sta_flag(sta, WLAN_STA_PS_DRIVER); | 1549 | set_sta_flag(sta, WLAN_STA_PS_DRIVER); |
1548 | else if (test_sta_flag(sta, WLAN_STA_PS_DRIVER)) | 1550 | return; |
1549 | ieee80211_queue_work(hw, &sta->drv_unblock_wk); | 1551 | } |
1552 | |||
1553 | if (!test_sta_flag(sta, WLAN_STA_PS_DRIVER)) | ||
1554 | return; | ||
1555 | |||
1556 | if (!test_sta_flag(sta, WLAN_STA_PS_STA)) { | ||
1557 | set_sta_flag(sta, WLAN_STA_PS_DELIVER); | ||
1558 | clear_sta_flag(sta, WLAN_STA_PS_DRIVER); | ||
1559 | ieee80211_queue_work(hw, &sta->drv_deliver_wk); | ||
1560 | } else if (test_sta_flag(sta, WLAN_STA_PSPOLL) || | ||
1561 | test_sta_flag(sta, WLAN_STA_UAPSD)) { | ||
1562 | /* must be asleep in this case */ | ||
1563 | clear_sta_flag(sta, WLAN_STA_PS_DRIVER); | ||
1564 | ieee80211_queue_work(hw, &sta->drv_deliver_wk); | ||
1565 | } else { | ||
1566 | clear_sta_flag(sta, WLAN_STA_PS_DRIVER); | ||
1567 | } | ||
1550 | } | 1568 | } |
1551 | EXPORT_SYMBOL(ieee80211_sta_block_awake); | 1569 | EXPORT_SYMBOL(ieee80211_sta_block_awake); |
1552 | 1570 | ||
@@ -1704,3 +1722,140 @@ u8 sta_info_tx_streams(struct sta_info *sta) | |||
1704 | return ((ht_cap->mcs.tx_params & IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK) | 1722 | return ((ht_cap->mcs.tx_params & IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK) |
1705 | >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT) + 1; | 1723 | >> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT) + 1; |
1706 | } | 1724 | } |
1725 | |||
1726 | void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | ||
1727 | { | ||
1728 | struct ieee80211_sub_if_data *sdata = sta->sdata; | ||
1729 | struct ieee80211_local *local = sdata->local; | ||
1730 | struct rate_control_ref *ref = NULL; | ||
1731 | struct timespec uptime; | ||
1732 | u64 packets = 0; | ||
1733 | u32 thr = 0; | ||
1734 | int i, ac; | ||
1735 | |||
1736 | if (test_sta_flag(sta, WLAN_STA_RATE_CONTROL)) | ||
1737 | ref = local->rate_ctrl; | ||
1738 | |||
1739 | sinfo->generation = sdata->local->sta_generation; | ||
1740 | |||
1741 | sinfo->filled = STATION_INFO_INACTIVE_TIME | | ||
1742 | STATION_INFO_RX_BYTES64 | | ||
1743 | STATION_INFO_TX_BYTES64 | | ||
1744 | STATION_INFO_RX_PACKETS | | ||
1745 | STATION_INFO_TX_PACKETS | | ||
1746 | STATION_INFO_TX_RETRIES | | ||
1747 | STATION_INFO_TX_FAILED | | ||
1748 | STATION_INFO_TX_BITRATE | | ||
1749 | STATION_INFO_RX_BITRATE | | ||
1750 | STATION_INFO_RX_DROP_MISC | | ||
1751 | STATION_INFO_BSS_PARAM | | ||
1752 | STATION_INFO_CONNECTED_TIME | | ||
1753 | STATION_INFO_STA_FLAGS | | ||
1754 | STATION_INFO_BEACON_LOSS_COUNT; | ||
1755 | |||
1756 | ktime_get_ts(&uptime); | ||
1757 | sinfo->connected_time = uptime.tv_sec - sta->last_connected; | ||
1758 | |||
1759 | sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); | ||
1760 | sinfo->tx_bytes = 0; | ||
1761 | for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) { | ||
1762 | sinfo->tx_bytes += sta->tx_bytes[ac]; | ||
1763 | packets += sta->tx_packets[ac]; | ||
1764 | } | ||
1765 | sinfo->tx_packets = packets; | ||
1766 | sinfo->rx_bytes = sta->rx_bytes; | ||
1767 | sinfo->rx_packets = sta->rx_packets; | ||
1768 | sinfo->tx_retries = sta->tx_retry_count; | ||
1769 | sinfo->tx_failed = sta->tx_retry_failed; | ||
1770 | sinfo->rx_dropped_misc = sta->rx_dropped; | ||
1771 | sinfo->beacon_loss_count = sta->beacon_loss_count; | ||
1772 | |||
1773 | if ((sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) || | ||
1774 | (sta->local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)) { | ||
1775 | sinfo->filled |= STATION_INFO_SIGNAL | STATION_INFO_SIGNAL_AVG; | ||
1776 | if (!local->ops->get_rssi || | ||
1777 | drv_get_rssi(local, sdata, &sta->sta, &sinfo->signal)) | ||
1778 | sinfo->signal = (s8)sta->last_signal; | ||
1779 | sinfo->signal_avg = (s8) -ewma_read(&sta->avg_signal); | ||
1780 | } | ||
1781 | if (sta->chains) { | ||
1782 | sinfo->filled |= STATION_INFO_CHAIN_SIGNAL | | ||
1783 | STATION_INFO_CHAIN_SIGNAL_AVG; | ||
1784 | |||
1785 | sinfo->chains = sta->chains; | ||
1786 | for (i = 0; i < ARRAY_SIZE(sinfo->chain_signal); i++) { | ||
1787 | sinfo->chain_signal[i] = sta->chain_signal_last[i]; | ||
1788 | sinfo->chain_signal_avg[i] = | ||
1789 | (s8) -ewma_read(&sta->chain_signal_avg[i]); | ||
1790 | } | ||
1791 | } | ||
1792 | |||
1793 | sta_set_rate_info_tx(sta, &sta->last_tx_rate, &sinfo->txrate); | ||
1794 | sta_set_rate_info_rx(sta, &sinfo->rxrate); | ||
1795 | |||
1796 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | ||
1797 | #ifdef CONFIG_MAC80211_MESH | ||
1798 | sinfo->filled |= STATION_INFO_LLID | | ||
1799 | STATION_INFO_PLID | | ||
1800 | STATION_INFO_PLINK_STATE | | ||
1801 | STATION_INFO_LOCAL_PM | | ||
1802 | STATION_INFO_PEER_PM | | ||
1803 | STATION_INFO_NONPEER_PM; | ||
1804 | |||
1805 | sinfo->llid = sta->llid; | ||
1806 | sinfo->plid = sta->plid; | ||
1807 | sinfo->plink_state = sta->plink_state; | ||
1808 | if (test_sta_flag(sta, WLAN_STA_TOFFSET_KNOWN)) { | ||
1809 | sinfo->filled |= STATION_INFO_T_OFFSET; | ||
1810 | sinfo->t_offset = sta->t_offset; | ||
1811 | } | ||
1812 | sinfo->local_pm = sta->local_pm; | ||
1813 | sinfo->peer_pm = sta->peer_pm; | ||
1814 | sinfo->nonpeer_pm = sta->nonpeer_pm; | ||
1815 | #endif | ||
1816 | } | ||
1817 | |||
1818 | sinfo->bss_param.flags = 0; | ||
1819 | if (sdata->vif.bss_conf.use_cts_prot) | ||
1820 | sinfo->bss_param.flags |= BSS_PARAM_FLAGS_CTS_PROT; | ||
1821 | if (sdata->vif.bss_conf.use_short_preamble) | ||
1822 | sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE; | ||
1823 | if (sdata->vif.bss_conf.use_short_slot) | ||
1824 | sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME; | ||
1825 | sinfo->bss_param.dtim_period = sdata->vif.bss_conf.dtim_period; | ||
1826 | sinfo->bss_param.beacon_interval = sdata->vif.bss_conf.beacon_int; | ||
1827 | |||
1828 | sinfo->sta_flags.set = 0; | ||
1829 | sinfo->sta_flags.mask = BIT(NL80211_STA_FLAG_AUTHORIZED) | | ||
1830 | BIT(NL80211_STA_FLAG_SHORT_PREAMBLE) | | ||
1831 | BIT(NL80211_STA_FLAG_WME) | | ||
1832 | BIT(NL80211_STA_FLAG_MFP) | | ||
1833 | BIT(NL80211_STA_FLAG_AUTHENTICATED) | | ||
1834 | BIT(NL80211_STA_FLAG_ASSOCIATED) | | ||
1835 | BIT(NL80211_STA_FLAG_TDLS_PEER); | ||
1836 | if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) | ||
1837 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHORIZED); | ||
1838 | if (test_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE)) | ||
1839 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE); | ||
1840 | if (test_sta_flag(sta, WLAN_STA_WME)) | ||
1841 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_WME); | ||
1842 | if (test_sta_flag(sta, WLAN_STA_MFP)) | ||
1843 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_MFP); | ||
1844 | if (test_sta_flag(sta, WLAN_STA_AUTH)) | ||
1845 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHENTICATED); | ||
1846 | if (test_sta_flag(sta, WLAN_STA_ASSOC)) | ||
1847 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_ASSOCIATED); | ||
1848 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER)) | ||
1849 | sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_TDLS_PEER); | ||
1850 | |||
1851 | /* check if the driver has a SW RC implementation */ | ||
1852 | if (ref && ref->ops->get_expected_throughput) | ||
1853 | thr = ref->ops->get_expected_throughput(sta->rate_ctrl_priv); | ||
1854 | else | ||
1855 | thr = drv_get_expected_throughput(local, &sta->sta); | ||
1856 | |||
1857 | if (thr != 0) { | ||
1858 | sinfo->filled |= STATION_INFO_EXPECTED_THROUGHPUT; | ||
1859 | sinfo->expected_throughput = thr; | ||
1860 | } | ||
1861 | } | ||
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index 4acc5fc402fa..d411bcc8ef08 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -47,6 +47,8 @@ | |||
47 | * @WLAN_STA_TDLS_PEER: Station is a TDLS peer. | 47 | * @WLAN_STA_TDLS_PEER: Station is a TDLS peer. |
48 | * @WLAN_STA_TDLS_PEER_AUTH: This TDLS peer is authorized to send direct | 48 | * @WLAN_STA_TDLS_PEER_AUTH: This TDLS peer is authorized to send direct |
49 | * packets. This means the link is enabled. | 49 | * packets. This means the link is enabled. |
50 | * @WLAN_STA_TDLS_INITIATOR: We are the initiator of the TDLS link with this | ||
51 | * station. | ||
50 | * @WLAN_STA_UAPSD: Station requested unscheduled SP while driver was | 52 | * @WLAN_STA_UAPSD: Station requested unscheduled SP while driver was |
51 | * keeping station in power-save mode, reply when the driver | 53 | * keeping station in power-save mode, reply when the driver |
52 | * unblocks the station. | 54 | * unblocks the station. |
@@ -58,6 +60,8 @@ | |||
58 | * @WLAN_STA_TOFFSET_KNOWN: toffset calculated for this station is valid. | 60 | * @WLAN_STA_TOFFSET_KNOWN: toffset calculated for this station is valid. |
59 | * @WLAN_STA_MPSP_OWNER: local STA is owner of a mesh Peer Service Period. | 61 | * @WLAN_STA_MPSP_OWNER: local STA is owner of a mesh Peer Service Period. |
60 | * @WLAN_STA_MPSP_RECIPIENT: local STA is recipient of a MPSP. | 62 | * @WLAN_STA_MPSP_RECIPIENT: local STA is recipient of a MPSP. |
63 | * @WLAN_STA_PS_DELIVER: station woke up, but we're still blocking TX | ||
64 | * until pending frames are delivered | ||
61 | */ | 65 | */ |
62 | enum ieee80211_sta_info_flags { | 66 | enum ieee80211_sta_info_flags { |
63 | WLAN_STA_AUTH, | 67 | WLAN_STA_AUTH, |
@@ -74,6 +78,7 @@ enum ieee80211_sta_info_flags { | |||
74 | WLAN_STA_PSPOLL, | 78 | WLAN_STA_PSPOLL, |
75 | WLAN_STA_TDLS_PEER, | 79 | WLAN_STA_TDLS_PEER, |
76 | WLAN_STA_TDLS_PEER_AUTH, | 80 | WLAN_STA_TDLS_PEER_AUTH, |
81 | WLAN_STA_TDLS_INITIATOR, | ||
77 | WLAN_STA_UAPSD, | 82 | WLAN_STA_UAPSD, |
78 | WLAN_STA_SP, | 83 | WLAN_STA_SP, |
79 | WLAN_STA_4ADDR_EVENT, | 84 | WLAN_STA_4ADDR_EVENT, |
@@ -82,6 +87,7 @@ enum ieee80211_sta_info_flags { | |||
82 | WLAN_STA_TOFFSET_KNOWN, | 87 | WLAN_STA_TOFFSET_KNOWN, |
83 | WLAN_STA_MPSP_OWNER, | 88 | WLAN_STA_MPSP_OWNER, |
84 | WLAN_STA_MPSP_RECIPIENT, | 89 | WLAN_STA_MPSP_RECIPIENT, |
90 | WLAN_STA_PS_DELIVER, | ||
85 | }; | 91 | }; |
86 | 92 | ||
87 | #define ADDBA_RESP_INTERVAL HZ | 93 | #define ADDBA_RESP_INTERVAL HZ |
@@ -149,7 +155,8 @@ struct tid_ampdu_tx { | |||
149 | /** | 155 | /** |
150 | * struct tid_ampdu_rx - TID aggregation information (Rx). | 156 | * struct tid_ampdu_rx - TID aggregation information (Rx). |
151 | * | 157 | * |
152 | * @reorder_buf: buffer to reorder incoming aggregated MPDUs | 158 | * @reorder_buf: buffer to reorder incoming aggregated MPDUs. An MPDU may be an |
159 | * A-MSDU with individually reported subframes. | ||
153 | * @reorder_time: jiffies when skb was added | 160 | * @reorder_time: jiffies when skb was added |
154 | * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value) | 161 | * @session_timer: check if peer keeps Tx-ing on the TID (by timeout value) |
155 | * @reorder_timer: releases expired frames from the reorder buffer. | 162 | * @reorder_timer: releases expired frames from the reorder buffer. |
@@ -174,7 +181,7 @@ struct tid_ampdu_tx { | |||
174 | struct tid_ampdu_rx { | 181 | struct tid_ampdu_rx { |
175 | struct rcu_head rcu_head; | 182 | struct rcu_head rcu_head; |
176 | spinlock_t reorder_lock; | 183 | spinlock_t reorder_lock; |
177 | struct sk_buff **reorder_buf; | 184 | struct sk_buff_head *reorder_buf; |
178 | unsigned long *reorder_time; | 185 | unsigned long *reorder_time; |
179 | struct timer_list session_timer; | 186 | struct timer_list session_timer; |
180 | struct timer_list reorder_timer; | 187 | struct timer_list reorder_timer; |
@@ -265,7 +272,7 @@ struct ieee80211_tx_latency_stat { | |||
265 | * @last_rx_rate_vht_nss: rx status nss of last data packet | 272 | * @last_rx_rate_vht_nss: rx status nss of last data packet |
266 | * @lock: used for locking all fields that require locking, see comments | 273 | * @lock: used for locking all fields that require locking, see comments |
267 | * in the header file. | 274 | * in the header file. |
268 | * @drv_unblock_wk: used for driver PS unblocking | 275 | * @drv_deliver_wk: used for delivering frames after driver PS unblocking |
269 | * @listen_interval: listen interval of this station, when we're acting as AP | 276 | * @listen_interval: listen interval of this station, when we're acting as AP |
270 | * @_flags: STA flags, see &enum ieee80211_sta_info_flags, do not use directly | 277 | * @_flags: STA flags, see &enum ieee80211_sta_info_flags, do not use directly |
271 | * @ps_lock: used for powersave (when mac80211 is the AP) related locking | 278 | * @ps_lock: used for powersave (when mac80211 is the AP) related locking |
@@ -278,7 +285,6 @@ struct ieee80211_tx_latency_stat { | |||
278 | * @driver_buffered_tids: bitmap of TIDs the driver has data buffered on | 285 | * @driver_buffered_tids: bitmap of TIDs the driver has data buffered on |
279 | * @rx_packets: Number of MSDUs received from this STA | 286 | * @rx_packets: Number of MSDUs received from this STA |
280 | * @rx_bytes: Number of bytes received from this STA | 287 | * @rx_bytes: Number of bytes received from this STA |
281 | * @wep_weak_iv_count: number of weak WEP IVs received from this station | ||
282 | * @last_rx: time (in jiffies) when last frame was received from this STA | 288 | * @last_rx: time (in jiffies) when last frame was received from this STA |
283 | * @last_connected: time (in seconds) when a station got connected | 289 | * @last_connected: time (in seconds) when a station got connected |
284 | * @num_duplicates: number of duplicate frames received from this STA | 290 | * @num_duplicates: number of duplicate frames received from this STA |
@@ -303,7 +309,6 @@ struct ieee80211_tx_latency_stat { | |||
303 | * @plid: Peer link ID | 309 | * @plid: Peer link ID |
304 | * @reason: Cancel reason on PLINK_HOLDING state | 310 | * @reason: Cancel reason on PLINK_HOLDING state |
305 | * @plink_retries: Retries in establishment | 311 | * @plink_retries: Retries in establishment |
306 | * @ignore_plink_timer: ignore the peer-link timer (used internally) | ||
307 | * @plink_state: peer link state | 312 | * @plink_state: peer link state |
308 | * @plink_timeout: timeout of peer link | 313 | * @plink_timeout: timeout of peer link |
309 | * @plink_timer: peer link watch timer | 314 | * @plink_timer: peer link watch timer |
@@ -345,7 +350,7 @@ struct sta_info { | |||
345 | void *rate_ctrl_priv; | 350 | void *rate_ctrl_priv; |
346 | spinlock_t lock; | 351 | spinlock_t lock; |
347 | 352 | ||
348 | struct work_struct drv_unblock_wk; | 353 | struct work_struct drv_deliver_wk; |
349 | 354 | ||
350 | u16 listen_interval; | 355 | u16 listen_interval; |
351 | 356 | ||
@@ -367,7 +372,6 @@ struct sta_info { | |||
367 | /* Updated from RX path only, no locking requirements */ | 372 | /* Updated from RX path only, no locking requirements */ |
368 | unsigned long rx_packets; | 373 | unsigned long rx_packets; |
369 | u64 rx_bytes; | 374 | u64 rx_bytes; |
370 | unsigned long wep_weak_iv_count; | ||
371 | unsigned long last_rx; | 375 | unsigned long last_rx; |
372 | long last_connected; | 376 | long last_connected; |
373 | unsigned long num_duplicates; | 377 | unsigned long num_duplicates; |
@@ -418,7 +422,6 @@ struct sta_info { | |||
418 | u16 plid; | 422 | u16 plid; |
419 | u16 reason; | 423 | u16 reason; |
420 | u8 plink_retries; | 424 | u8 plink_retries; |
421 | bool ignore_plink_timer; | ||
422 | enum nl80211_plink_state plink_state; | 425 | enum nl80211_plink_state plink_state; |
423 | u32 plink_timeout; | 426 | u32 plink_timeout; |
424 | struct timer_list plink_timer; | 427 | struct timer_list plink_timer; |
@@ -628,6 +631,8 @@ void sta_set_rate_info_tx(struct sta_info *sta, | |||
628 | struct rate_info *rinfo); | 631 | struct rate_info *rinfo); |
629 | void sta_set_rate_info_rx(struct sta_info *sta, | 632 | void sta_set_rate_info_rx(struct sta_info *sta, |
630 | struct rate_info *rinfo); | 633 | struct rate_info *rinfo); |
634 | void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo); | ||
635 | |||
631 | void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, | 636 | void ieee80211_sta_expire(struct ieee80211_sub_if_data *sdata, |
632 | unsigned long exp_time); | 637 | unsigned long exp_time); |
633 | u8 sta_info_tx_streams(struct sta_info *sta); | 638 | u8 sta_info_tx_streams(struct sta_info *sta); |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index ba29ebc86141..aa06dcad336e 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -473,8 +473,6 @@ static void ieee80211_tx_latency_end_msrmnt(struct ieee80211_local *local, | |||
473 | struct sta_info *sta, | 473 | struct sta_info *sta, |
474 | struct ieee80211_hdr *hdr) | 474 | struct ieee80211_hdr *hdr) |
475 | { | 475 | { |
476 | ktime_t skb_dprt; | ||
477 | struct timespec dprt_time; | ||
478 | u32 msrmnt; | 476 | u32 msrmnt; |
479 | u16 tid; | 477 | u16 tid; |
480 | u8 *qc; | 478 | u8 *qc; |
@@ -506,9 +504,8 @@ static void ieee80211_tx_latency_end_msrmnt(struct ieee80211_local *local, | |||
506 | 504 | ||
507 | tx_lat = &sta->tx_lat[tid]; | 505 | tx_lat = &sta->tx_lat[tid]; |
508 | 506 | ||
509 | ktime_get_ts(&dprt_time); /* time stamp completion time */ | 507 | /* Calculate the latency */ |
510 | skb_dprt = ktime_set(dprt_time.tv_sec, dprt_time.tv_nsec); | 508 | msrmnt = ktime_to_ms(ktime_sub(ktime_get(), skb_arv)); |
511 | msrmnt = ktime_to_ms(ktime_sub(skb_dprt, skb_arv)); | ||
512 | 509 | ||
513 | if (tx_lat->max < msrmnt) /* update stats */ | 510 | if (tx_lat->max < msrmnt) /* update stats */ |
514 | tx_lat->max = msrmnt; | 511 | tx_lat->max = msrmnt; |
diff --git a/net/mac80211/tdls.c b/net/mac80211/tdls.c index 652813b2d3df..1b21050be174 100644 --- a/net/mac80211/tdls.c +++ b/net/mac80211/tdls.c | |||
@@ -8,7 +8,31 @@ | |||
8 | */ | 8 | */ |
9 | 9 | ||
10 | #include <linux/ieee80211.h> | 10 | #include <linux/ieee80211.h> |
11 | #include <linux/log2.h> | ||
12 | #include <net/cfg80211.h> | ||
11 | #include "ieee80211_i.h" | 13 | #include "ieee80211_i.h" |
14 | #include "driver-ops.h" | ||
15 | |||
16 | /* give usermode some time for retries in setting up the TDLS session */ | ||
17 | #define TDLS_PEER_SETUP_TIMEOUT (15 * HZ) | ||
18 | |||
19 | void ieee80211_tdls_peer_del_work(struct work_struct *wk) | ||
20 | { | ||
21 | struct ieee80211_sub_if_data *sdata; | ||
22 | struct ieee80211_local *local; | ||
23 | |||
24 | sdata = container_of(wk, struct ieee80211_sub_if_data, | ||
25 | u.mgd.tdls_peer_del_work.work); | ||
26 | local = sdata->local; | ||
27 | |||
28 | mutex_lock(&local->mtx); | ||
29 | if (!is_zero_ether_addr(sdata->u.mgd.tdls_peer)) { | ||
30 | tdls_dbg(sdata, "TDLS del peer %pM\n", sdata->u.mgd.tdls_peer); | ||
31 | sta_info_destroy_addr(sdata, sdata->u.mgd.tdls_peer); | ||
32 | eth_zero_addr(sdata->u.mgd.tdls_peer); | ||
33 | } | ||
34 | mutex_unlock(&local->mtx); | ||
35 | } | ||
12 | 36 | ||
13 | static void ieee80211_tdls_add_ext_capab(struct sk_buff *skb) | 37 | static void ieee80211_tdls_add_ext_capab(struct sk_buff *skb) |
14 | { | 38 | { |
@@ -23,11 +47,16 @@ static void ieee80211_tdls_add_ext_capab(struct sk_buff *skb) | |||
23 | *pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED; | 47 | *pos++ = WLAN_EXT_CAPA5_TDLS_ENABLED; |
24 | } | 48 | } |
25 | 49 | ||
26 | static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata) | 50 | static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata, |
51 | u16 status_code) | ||
27 | { | 52 | { |
28 | struct ieee80211_local *local = sdata->local; | 53 | struct ieee80211_local *local = sdata->local; |
29 | u16 capab; | 54 | u16 capab; |
30 | 55 | ||
56 | /* The capability will be 0 when sending a failure code */ | ||
57 | if (status_code != 0) | ||
58 | return 0; | ||
59 | |||
31 | capab = 0; | 60 | capab = 0; |
32 | if (ieee80211_get_sdata_band(sdata) != IEEE80211_BAND_2GHZ) | 61 | if (ieee80211_get_sdata_band(sdata) != IEEE80211_BAND_2GHZ) |
33 | return capab; | 62 | return capab; |
@@ -40,19 +69,332 @@ static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata) | |||
40 | return capab; | 69 | return capab; |
41 | } | 70 | } |
42 | 71 | ||
43 | static void ieee80211_tdls_add_link_ie(struct sk_buff *skb, const u8 *src_addr, | 72 | static void ieee80211_tdls_add_link_ie(struct ieee80211_sub_if_data *sdata, |
44 | const u8 *peer, const u8 *bssid) | 73 | struct sk_buff *skb, const u8 *peer, |
74 | bool initiator) | ||
45 | { | 75 | { |
46 | struct ieee80211_tdls_lnkie *lnkid; | 76 | struct ieee80211_tdls_lnkie *lnkid; |
77 | const u8 *init_addr, *rsp_addr; | ||
78 | |||
79 | if (initiator) { | ||
80 | init_addr = sdata->vif.addr; | ||
81 | rsp_addr = peer; | ||
82 | } else { | ||
83 | init_addr = peer; | ||
84 | rsp_addr = sdata->vif.addr; | ||
85 | } | ||
47 | 86 | ||
48 | lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie)); | 87 | lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie)); |
49 | 88 | ||
50 | lnkid->ie_type = WLAN_EID_LINK_ID; | 89 | lnkid->ie_type = WLAN_EID_LINK_ID; |
51 | lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2; | 90 | lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - 2; |
52 | 91 | ||
53 | memcpy(lnkid->bssid, bssid, ETH_ALEN); | 92 | memcpy(lnkid->bssid, sdata->u.mgd.bssid, ETH_ALEN); |
54 | memcpy(lnkid->init_sta, src_addr, ETH_ALEN); | 93 | memcpy(lnkid->init_sta, init_addr, ETH_ALEN); |
55 | memcpy(lnkid->resp_sta, peer, ETH_ALEN); | 94 | memcpy(lnkid->resp_sta, rsp_addr, ETH_ALEN); |
95 | } | ||
96 | |||
97 | /* translate numbering in the WMM parameter IE to the mac80211 notation */ | ||
98 | static enum ieee80211_ac_numbers ieee80211_ac_from_wmm(int ac) | ||
99 | { | ||
100 | switch (ac) { | ||
101 | default: | ||
102 | WARN_ON_ONCE(1); | ||
103 | case 0: | ||
104 | return IEEE80211_AC_BE; | ||
105 | case 1: | ||
106 | return IEEE80211_AC_BK; | ||
107 | case 2: | ||
108 | return IEEE80211_AC_VI; | ||
109 | case 3: | ||
110 | return IEEE80211_AC_VO; | ||
111 | } | ||
112 | } | ||
113 | |||
114 | static u8 ieee80211_wmm_aci_aifsn(int aifsn, bool acm, int aci) | ||
115 | { | ||
116 | u8 ret; | ||
117 | |||
118 | ret = aifsn & 0x0f; | ||
119 | if (acm) | ||
120 | ret |= 0x10; | ||
121 | ret |= (aci << 5) & 0x60; | ||
122 | return ret; | ||
123 | } | ||
124 | |||
125 | static u8 ieee80211_wmm_ecw(u16 cw_min, u16 cw_max) | ||
126 | { | ||
127 | return ((ilog2(cw_min + 1) << 0x0) & 0x0f) | | ||
128 | ((ilog2(cw_max + 1) << 0x4) & 0xf0); | ||
129 | } | ||
130 | |||
131 | static void ieee80211_tdls_add_wmm_param_ie(struct ieee80211_sub_if_data *sdata, | ||
132 | struct sk_buff *skb) | ||
133 | { | ||
134 | struct ieee80211_wmm_param_ie *wmm; | ||
135 | struct ieee80211_tx_queue_params *txq; | ||
136 | int i; | ||
137 | |||
138 | wmm = (void *)skb_put(skb, sizeof(*wmm)); | ||
139 | memset(wmm, 0, sizeof(*wmm)); | ||
140 | |||
141 | wmm->element_id = WLAN_EID_VENDOR_SPECIFIC; | ||
142 | wmm->len = sizeof(*wmm) - 2; | ||
143 | |||
144 | wmm->oui[0] = 0x00; /* Microsoft OUI 00:50:F2 */ | ||
145 | wmm->oui[1] = 0x50; | ||
146 | wmm->oui[2] = 0xf2; | ||
147 | wmm->oui_type = 2; /* WME */ | ||
148 | wmm->oui_subtype = 1; /* WME param */ | ||
149 | wmm->version = 1; /* WME ver */ | ||
150 | wmm->qos_info = 0; /* U-APSD not in use */ | ||
151 | |||
152 | /* | ||
153 | * Use the EDCA parameters defined for the BSS, or default if the AP | ||
154 | * doesn't support it, as mandated by 802.11-2012 section 10.22.4 | ||
155 | */ | ||
156 | for (i = 0; i < IEEE80211_NUM_ACS; i++) { | ||
157 | txq = &sdata->tx_conf[ieee80211_ac_from_wmm(i)]; | ||
158 | wmm->ac[i].aci_aifsn = ieee80211_wmm_aci_aifsn(txq->aifs, | ||
159 | txq->acm, i); | ||
160 | wmm->ac[i].cw = ieee80211_wmm_ecw(txq->cw_min, txq->cw_max); | ||
161 | wmm->ac[i].txop_limit = cpu_to_le16(txq->txop); | ||
162 | } | ||
163 | } | ||
164 | |||
165 | static void | ||
166 | ieee80211_tdls_add_setup_start_ies(struct ieee80211_sub_if_data *sdata, | ||
167 | struct sk_buff *skb, const u8 *peer, | ||
168 | u8 action_code, bool initiator, | ||
169 | const u8 *extra_ies, size_t extra_ies_len) | ||
170 | { | ||
171 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); | ||
172 | struct ieee80211_local *local = sdata->local; | ||
173 | struct ieee80211_supported_band *sband; | ||
174 | struct ieee80211_sta_ht_cap ht_cap; | ||
175 | struct sta_info *sta = NULL; | ||
176 | size_t offset = 0, noffset; | ||
177 | u8 *pos; | ||
178 | |||
179 | rcu_read_lock(); | ||
180 | |||
181 | /* we should have the peer STA if we're already responding */ | ||
182 | if (action_code == WLAN_TDLS_SETUP_RESPONSE) { | ||
183 | sta = sta_info_get(sdata, peer); | ||
184 | if (WARN_ON_ONCE(!sta)) { | ||
185 | rcu_read_unlock(); | ||
186 | return; | ||
187 | } | ||
188 | } | ||
189 | |||
190 | ieee80211_add_srates_ie(sdata, skb, false, band); | ||
191 | ieee80211_add_ext_srates_ie(sdata, skb, false, band); | ||
192 | |||
193 | /* add any custom IEs that go before Extended Capabilities */ | ||
194 | if (extra_ies_len) { | ||
195 | static const u8 before_ext_cap[] = { | ||
196 | WLAN_EID_SUPP_RATES, | ||
197 | WLAN_EID_COUNTRY, | ||
198 | WLAN_EID_EXT_SUPP_RATES, | ||
199 | WLAN_EID_SUPPORTED_CHANNELS, | ||
200 | WLAN_EID_RSN, | ||
201 | }; | ||
202 | noffset = ieee80211_ie_split(extra_ies, extra_ies_len, | ||
203 | before_ext_cap, | ||
204 | ARRAY_SIZE(before_ext_cap), | ||
205 | offset); | ||
206 | pos = skb_put(skb, noffset - offset); | ||
207 | memcpy(pos, extra_ies + offset, noffset - offset); | ||
208 | offset = noffset; | ||
209 | } | ||
210 | |||
211 | ieee80211_tdls_add_ext_capab(skb); | ||
212 | |||
213 | /* add the QoS element if we support it */ | ||
214 | if (local->hw.queues >= IEEE80211_NUM_ACS && | ||
215 | action_code != WLAN_PUB_ACTION_TDLS_DISCOVER_RES) | ||
216 | ieee80211_add_wmm_info_ie(skb_put(skb, 9), 0); /* no U-APSD */ | ||
217 | |||
218 | /* add any custom IEs that go before HT capabilities */ | ||
219 | if (extra_ies_len) { | ||
220 | static const u8 before_ht_cap[] = { | ||
221 | WLAN_EID_SUPP_RATES, | ||
222 | WLAN_EID_COUNTRY, | ||
223 | WLAN_EID_EXT_SUPP_RATES, | ||
224 | WLAN_EID_SUPPORTED_CHANNELS, | ||
225 | WLAN_EID_RSN, | ||
226 | WLAN_EID_EXT_CAPABILITY, | ||
227 | WLAN_EID_QOS_CAPA, | ||
228 | WLAN_EID_FAST_BSS_TRANSITION, | ||
229 | WLAN_EID_TIMEOUT_INTERVAL, | ||
230 | WLAN_EID_SUPPORTED_REGULATORY_CLASSES, | ||
231 | }; | ||
232 | noffset = ieee80211_ie_split(extra_ies, extra_ies_len, | ||
233 | before_ht_cap, | ||
234 | ARRAY_SIZE(before_ht_cap), | ||
235 | offset); | ||
236 | pos = skb_put(skb, noffset - offset); | ||
237 | memcpy(pos, extra_ies + offset, noffset - offset); | ||
238 | offset = noffset; | ||
239 | } | ||
240 | |||
241 | /* | ||
242 | * with TDLS we can switch channels, and HT-caps are not necessarily | ||
243 | * the same on all bands. The specification limits the setup to a | ||
244 | * single HT-cap, so use the current band for now. | ||
245 | */ | ||
246 | sband = local->hw.wiphy->bands[band]; | ||
247 | memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap)); | ||
248 | if ((action_code == WLAN_TDLS_SETUP_REQUEST || | ||
249 | action_code == WLAN_TDLS_SETUP_RESPONSE) && | ||
250 | ht_cap.ht_supported && (!sta || sta->sta.ht_cap.ht_supported)) { | ||
251 | if (action_code == WLAN_TDLS_SETUP_REQUEST) { | ||
252 | ieee80211_apply_htcap_overrides(sdata, &ht_cap); | ||
253 | |||
254 | /* disable SMPS in TDLS initiator */ | ||
255 | ht_cap.cap |= (WLAN_HT_CAP_SM_PS_DISABLED | ||
256 | << IEEE80211_HT_CAP_SM_PS_SHIFT); | ||
257 | } else { | ||
258 | /* disable SMPS in TDLS responder */ | ||
259 | sta->sta.ht_cap.cap |= | ||
260 | (WLAN_HT_CAP_SM_PS_DISABLED | ||
261 | << IEEE80211_HT_CAP_SM_PS_SHIFT); | ||
262 | |||
263 | /* the peer caps are already intersected with our own */ | ||
264 | memcpy(&ht_cap, &sta->sta.ht_cap, sizeof(ht_cap)); | ||
265 | } | ||
266 | |||
267 | pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); | ||
268 | ieee80211_ie_build_ht_cap(pos, &ht_cap, ht_cap.cap); | ||
269 | } | ||
270 | |||
271 | rcu_read_unlock(); | ||
272 | |||
273 | /* add any remaining IEs */ | ||
274 | if (extra_ies_len) { | ||
275 | noffset = extra_ies_len; | ||
276 | pos = skb_put(skb, noffset - offset); | ||
277 | memcpy(pos, extra_ies + offset, noffset - offset); | ||
278 | } | ||
279 | |||
280 | ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator); | ||
281 | } | ||
282 | |||
283 | static void | ||
284 | ieee80211_tdls_add_setup_cfm_ies(struct ieee80211_sub_if_data *sdata, | ||
285 | struct sk_buff *skb, const u8 *peer, | ||
286 | bool initiator, const u8 *extra_ies, | ||
287 | size_t extra_ies_len) | ||
288 | { | ||
289 | struct ieee80211_local *local = sdata->local; | ||
290 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
291 | size_t offset = 0, noffset; | ||
292 | struct sta_info *sta, *ap_sta; | ||
293 | u8 *pos; | ||
294 | |||
295 | rcu_read_lock(); | ||
296 | |||
297 | sta = sta_info_get(sdata, peer); | ||
298 | ap_sta = sta_info_get(sdata, ifmgd->bssid); | ||
299 | if (WARN_ON_ONCE(!sta || !ap_sta)) { | ||
300 | rcu_read_unlock(); | ||
301 | return; | ||
302 | } | ||
303 | |||
304 | /* add any custom IEs that go before the QoS IE */ | ||
305 | if (extra_ies_len) { | ||
306 | static const u8 before_qos[] = { | ||
307 | WLAN_EID_RSN, | ||
308 | }; | ||
309 | noffset = ieee80211_ie_split(extra_ies, extra_ies_len, | ||
310 | before_qos, | ||
311 | ARRAY_SIZE(before_qos), | ||
312 | offset); | ||
313 | pos = skb_put(skb, noffset - offset); | ||
314 | memcpy(pos, extra_ies + offset, noffset - offset); | ||
315 | offset = noffset; | ||
316 | } | ||
317 | |||
318 | /* add the QoS param IE if both the peer and we support it */ | ||
319 | if (local->hw.queues >= IEEE80211_NUM_ACS && | ||
320 | test_sta_flag(sta, WLAN_STA_WME)) | ||
321 | ieee80211_tdls_add_wmm_param_ie(sdata, skb); | ||
322 | |||
323 | /* add any custom IEs that go before HT operation */ | ||
324 | if (extra_ies_len) { | ||
325 | static const u8 before_ht_op[] = { | ||
326 | WLAN_EID_RSN, | ||
327 | WLAN_EID_QOS_CAPA, | ||
328 | WLAN_EID_FAST_BSS_TRANSITION, | ||
329 | WLAN_EID_TIMEOUT_INTERVAL, | ||
330 | }; | ||
331 | noffset = ieee80211_ie_split(extra_ies, extra_ies_len, | ||
332 | before_ht_op, | ||
333 | ARRAY_SIZE(before_ht_op), | ||
334 | offset); | ||
335 | pos = skb_put(skb, noffset - offset); | ||
336 | memcpy(pos, extra_ies + offset, noffset - offset); | ||
337 | offset = noffset; | ||
338 | } | ||
339 | |||
340 | /* if HT support is only added in TDLS, we need an HT-operation IE */ | ||
341 | if (!ap_sta->sta.ht_cap.ht_supported && sta->sta.ht_cap.ht_supported) { | ||
342 | struct ieee80211_chanctx_conf *chanctx_conf = | ||
343 | rcu_dereference(sdata->vif.chanctx_conf); | ||
344 | if (!WARN_ON(!chanctx_conf)) { | ||
345 | pos = skb_put(skb, 2 + | ||
346 | sizeof(struct ieee80211_ht_operation)); | ||
347 | /* send an empty HT operation IE */ | ||
348 | ieee80211_ie_build_ht_oper(pos, &sta->sta.ht_cap, | ||
349 | &chanctx_conf->def, 0); | ||
350 | } | ||
351 | } | ||
352 | |||
353 | rcu_read_unlock(); | ||
354 | |||
355 | /* add any remaining IEs */ | ||
356 | if (extra_ies_len) { | ||
357 | noffset = extra_ies_len; | ||
358 | pos = skb_put(skb, noffset - offset); | ||
359 | memcpy(pos, extra_ies + offset, noffset - offset); | ||
360 | } | ||
361 | |||
362 | ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator); | ||
363 | } | ||
364 | |||
365 | static void ieee80211_tdls_add_ies(struct ieee80211_sub_if_data *sdata, | ||
366 | struct sk_buff *skb, const u8 *peer, | ||
367 | u8 action_code, u16 status_code, | ||
368 | bool initiator, const u8 *extra_ies, | ||
369 | size_t extra_ies_len) | ||
370 | { | ||
371 | switch (action_code) { | ||
372 | case WLAN_TDLS_SETUP_REQUEST: | ||
373 | case WLAN_TDLS_SETUP_RESPONSE: | ||
374 | case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: | ||
375 | if (status_code == 0) | ||
376 | ieee80211_tdls_add_setup_start_ies(sdata, skb, peer, | ||
377 | action_code, | ||
378 | initiator, | ||
379 | extra_ies, | ||
380 | extra_ies_len); | ||
381 | break; | ||
382 | case WLAN_TDLS_SETUP_CONFIRM: | ||
383 | if (status_code == 0) | ||
384 | ieee80211_tdls_add_setup_cfm_ies(sdata, skb, peer, | ||
385 | initiator, extra_ies, | ||
386 | extra_ies_len); | ||
387 | break; | ||
388 | case WLAN_TDLS_TEARDOWN: | ||
389 | case WLAN_TDLS_DISCOVERY_REQUEST: | ||
390 | if (extra_ies_len) | ||
391 | memcpy(skb_put(skb, extra_ies_len), extra_ies, | ||
392 | extra_ies_len); | ||
393 | if (status_code == 0 || action_code == WLAN_TDLS_TEARDOWN) | ||
394 | ieee80211_tdls_add_link_ie(sdata, skb, peer, initiator); | ||
395 | break; | ||
396 | } | ||
397 | |||
56 | } | 398 | } |
57 | 399 | ||
58 | static int | 400 | static int |
@@ -61,7 +403,6 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, | |||
61 | u16 status_code, struct sk_buff *skb) | 403 | u16 status_code, struct sk_buff *skb) |
62 | { | 404 | { |
63 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 405 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
64 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); | ||
65 | struct ieee80211_tdls_data *tf; | 406 | struct ieee80211_tdls_data *tf; |
66 | 407 | ||
67 | tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u)); | 408 | tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u)); |
@@ -79,11 +420,8 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, | |||
79 | skb_put(skb, sizeof(tf->u.setup_req)); | 420 | skb_put(skb, sizeof(tf->u.setup_req)); |
80 | tf->u.setup_req.dialog_token = dialog_token; | 421 | tf->u.setup_req.dialog_token = dialog_token; |
81 | tf->u.setup_req.capability = | 422 | tf->u.setup_req.capability = |
82 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | 423 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata, |
83 | 424 | status_code)); | |
84 | ieee80211_add_srates_ie(sdata, skb, false, band); | ||
85 | ieee80211_add_ext_srates_ie(sdata, skb, false, band); | ||
86 | ieee80211_tdls_add_ext_capab(skb); | ||
87 | break; | 425 | break; |
88 | case WLAN_TDLS_SETUP_RESPONSE: | 426 | case WLAN_TDLS_SETUP_RESPONSE: |
89 | tf->category = WLAN_CATEGORY_TDLS; | 427 | tf->category = WLAN_CATEGORY_TDLS; |
@@ -93,11 +431,8 @@ ieee80211_prep_tdls_encap_data(struct wiphy *wiphy, struct net_device *dev, | |||
93 | tf->u.setup_resp.status_code = cpu_to_le16(status_code); | 431 | tf->u.setup_resp.status_code = cpu_to_le16(status_code); |
94 | tf->u.setup_resp.dialog_token = dialog_token; | 432 | tf->u.setup_resp.dialog_token = dialog_token; |
95 | tf->u.setup_resp.capability = | 433 | tf->u.setup_resp.capability = |
96 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | 434 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata, |
97 | 435 | status_code)); | |
98 | ieee80211_add_srates_ie(sdata, skb, false, band); | ||
99 | ieee80211_add_ext_srates_ie(sdata, skb, false, band); | ||
100 | ieee80211_tdls_add_ext_capab(skb); | ||
101 | break; | 436 | break; |
102 | case WLAN_TDLS_SETUP_CONFIRM: | 437 | case WLAN_TDLS_SETUP_CONFIRM: |
103 | tf->category = WLAN_CATEGORY_TDLS; | 438 | tf->category = WLAN_CATEGORY_TDLS; |
@@ -134,7 +469,6 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, | |||
134 | u16 status_code, struct sk_buff *skb) | 469 | u16 status_code, struct sk_buff *skb) |
135 | { | 470 | { |
136 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 471 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
137 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); | ||
138 | struct ieee80211_mgmt *mgmt; | 472 | struct ieee80211_mgmt *mgmt; |
139 | 473 | ||
140 | mgmt = (void *)skb_put(skb, 24); | 474 | mgmt = (void *)skb_put(skb, 24); |
@@ -155,11 +489,8 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, | |||
155 | mgmt->u.action.u.tdls_discover_resp.dialog_token = | 489 | mgmt->u.action.u.tdls_discover_resp.dialog_token = |
156 | dialog_token; | 490 | dialog_token; |
157 | mgmt->u.action.u.tdls_discover_resp.capability = | 491 | mgmt->u.action.u.tdls_discover_resp.capability = |
158 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata)); | 492 | cpu_to_le16(ieee80211_get_tdls_sta_capab(sdata, |
159 | 493 | status_code)); | |
160 | ieee80211_add_srates_ie(sdata, skb, false, band); | ||
161 | ieee80211_add_ext_srates_ie(sdata, skb, false, band); | ||
162 | ieee80211_tdls_add_ext_capab(skb); | ||
163 | break; | 494 | break; |
164 | default: | 495 | default: |
165 | return -EINVAL; | 496 | return -EINVAL; |
@@ -168,33 +499,28 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, | |||
168 | return 0; | 499 | return 0; |
169 | } | 500 | } |
170 | 501 | ||
171 | int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, | 502 | static int |
172 | const u8 *peer, u8 action_code, u8 dialog_token, | 503 | ieee80211_tdls_prep_mgmt_packet(struct wiphy *wiphy, struct net_device *dev, |
173 | u16 status_code, u32 peer_capability, | 504 | const u8 *peer, u8 action_code, |
174 | const u8 *extra_ies, size_t extra_ies_len) | 505 | u8 dialog_token, u16 status_code, |
506 | u32 peer_capability, bool initiator, | ||
507 | const u8 *extra_ies, size_t extra_ies_len) | ||
175 | { | 508 | { |
176 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 509 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
177 | struct ieee80211_local *local = sdata->local; | 510 | struct ieee80211_local *local = sdata->local; |
178 | struct sk_buff *skb = NULL; | 511 | struct sk_buff *skb = NULL; |
179 | bool send_direct; | 512 | bool send_direct; |
513 | struct sta_info *sta; | ||
180 | int ret; | 514 | int ret; |
181 | 515 | ||
182 | if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) | ||
183 | return -ENOTSUPP; | ||
184 | |||
185 | /* make sure we are in managed mode, and associated */ | ||
186 | if (sdata->vif.type != NL80211_IFTYPE_STATION || | ||
187 | !sdata->u.mgd.associated) | ||
188 | return -EINVAL; | ||
189 | |||
190 | tdls_dbg(sdata, "TDLS mgmt action %d peer %pM\n", | ||
191 | action_code, peer); | ||
192 | |||
193 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | 516 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + |
194 | max(sizeof(struct ieee80211_mgmt), | 517 | max(sizeof(struct ieee80211_mgmt), |
195 | sizeof(struct ieee80211_tdls_data)) + | 518 | sizeof(struct ieee80211_tdls_data)) + |
196 | 50 + /* supported rates */ | 519 | 50 + /* supported rates */ |
197 | 7 + /* ext capab */ | 520 | 7 + /* ext capab */ |
521 | 26 + /* max(WMM-info, WMM-param) */ | ||
522 | 2 + max(sizeof(struct ieee80211_ht_cap), | ||
523 | sizeof(struct ieee80211_ht_operation)) + | ||
198 | extra_ies_len + | 524 | extra_ies_len + |
199 | sizeof(struct ieee80211_tdls_lnkie)); | 525 | sizeof(struct ieee80211_tdls_lnkie)); |
200 | if (!skb) | 526 | if (!skb) |
@@ -227,30 +553,48 @@ int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, | |||
227 | if (ret < 0) | 553 | if (ret < 0) |
228 | goto fail; | 554 | goto fail; |
229 | 555 | ||
230 | if (extra_ies_len) | 556 | rcu_read_lock(); |
231 | memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len); | 557 | sta = sta_info_get(sdata, peer); |
232 | 558 | ||
233 | /* the TDLS link IE is always added last */ | 559 | /* infer the initiator if we can, to support old userspace */ |
234 | switch (action_code) { | 560 | switch (action_code) { |
235 | case WLAN_TDLS_SETUP_REQUEST: | 561 | case WLAN_TDLS_SETUP_REQUEST: |
562 | if (sta) | ||
563 | set_sta_flag(sta, WLAN_STA_TDLS_INITIATOR); | ||
564 | /* fall-through */ | ||
236 | case WLAN_TDLS_SETUP_CONFIRM: | 565 | case WLAN_TDLS_SETUP_CONFIRM: |
237 | case WLAN_TDLS_TEARDOWN: | ||
238 | case WLAN_TDLS_DISCOVERY_REQUEST: | 566 | case WLAN_TDLS_DISCOVERY_REQUEST: |
239 | /* we are the initiator */ | 567 | initiator = true; |
240 | ieee80211_tdls_add_link_ie(skb, sdata->vif.addr, peer, | ||
241 | sdata->u.mgd.bssid); | ||
242 | break; | 568 | break; |
243 | case WLAN_TDLS_SETUP_RESPONSE: | 569 | case WLAN_TDLS_SETUP_RESPONSE: |
570 | /* | ||
571 | * In some testing scenarios, we send a request and response. | ||
572 | * Make the last packet sent take effect for the initiator | ||
573 | * value. | ||
574 | */ | ||
575 | if (sta) | ||
576 | clear_sta_flag(sta, WLAN_STA_TDLS_INITIATOR); | ||
577 | /* fall-through */ | ||
244 | case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: | 578 | case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: |
245 | /* we are the responder */ | 579 | initiator = false; |
246 | ieee80211_tdls_add_link_ie(skb, peer, sdata->vif.addr, | 580 | break; |
247 | sdata->u.mgd.bssid); | 581 | case WLAN_TDLS_TEARDOWN: |
582 | /* any value is ok */ | ||
248 | break; | 583 | break; |
249 | default: | 584 | default: |
250 | ret = -ENOTSUPP; | 585 | ret = -ENOTSUPP; |
251 | goto fail; | 586 | break; |
252 | } | 587 | } |
253 | 588 | ||
589 | if (sta && test_sta_flag(sta, WLAN_STA_TDLS_INITIATOR)) | ||
590 | initiator = true; | ||
591 | |||
592 | rcu_read_unlock(); | ||
593 | if (ret < 0) | ||
594 | goto fail; | ||
595 | |||
596 | ieee80211_tdls_add_ies(sdata, skb, peer, action_code, status_code, | ||
597 | initiator, extra_ies, extra_ies_len); | ||
254 | if (send_direct) { | 598 | if (send_direct) { |
255 | ieee80211_tx_skb(sdata, skb); | 599 | ieee80211_tx_skb(sdata, skb); |
256 | return 0; | 600 | return 0; |
@@ -284,11 +628,175 @@ fail: | |||
284 | return ret; | 628 | return ret; |
285 | } | 629 | } |
286 | 630 | ||
631 | static int | ||
632 | ieee80211_tdls_mgmt_setup(struct wiphy *wiphy, struct net_device *dev, | ||
633 | const u8 *peer, u8 action_code, u8 dialog_token, | ||
634 | u16 status_code, u32 peer_capability, bool initiator, | ||
635 | const u8 *extra_ies, size_t extra_ies_len) | ||
636 | { | ||
637 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
638 | struct ieee80211_local *local = sdata->local; | ||
639 | int ret; | ||
640 | |||
641 | mutex_lock(&local->mtx); | ||
642 | |||
643 | /* we don't support concurrent TDLS peer setups */ | ||
644 | if (!is_zero_ether_addr(sdata->u.mgd.tdls_peer) && | ||
645 | !ether_addr_equal(sdata->u.mgd.tdls_peer, peer)) { | ||
646 | ret = -EBUSY; | ||
647 | goto exit; | ||
648 | } | ||
649 | |||
650 | /* | ||
651 | * make sure we have a STA representing the peer so we drop or buffer | ||
652 | * non-TDLS-setup frames to the peer. We can't send other packets | ||
653 | * during setup through the AP path. | ||
654 | * Allow error packets to be sent - sometimes we don't even add a STA | ||
655 | * before failing the setup. | ||
656 | */ | ||
657 | if (status_code == 0) { | ||
658 | rcu_read_lock(); | ||
659 | if (!sta_info_get(sdata, peer)) { | ||
660 | rcu_read_unlock(); | ||
661 | ret = -ENOLINK; | ||
662 | goto exit; | ||
663 | } | ||
664 | rcu_read_unlock(); | ||
665 | } | ||
666 | |||
667 | ieee80211_flush_queues(local, sdata); | ||
668 | |||
669 | ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, action_code, | ||
670 | dialog_token, status_code, | ||
671 | peer_capability, initiator, | ||
672 | extra_ies, extra_ies_len); | ||
673 | if (ret < 0) | ||
674 | goto exit; | ||
675 | |||
676 | memcpy(sdata->u.mgd.tdls_peer, peer, ETH_ALEN); | ||
677 | ieee80211_queue_delayed_work(&sdata->local->hw, | ||
678 | &sdata->u.mgd.tdls_peer_del_work, | ||
679 | TDLS_PEER_SETUP_TIMEOUT); | ||
680 | |||
681 | exit: | ||
682 | mutex_unlock(&local->mtx); | ||
683 | return ret; | ||
684 | } | ||
685 | |||
686 | static int | ||
687 | ieee80211_tdls_mgmt_teardown(struct wiphy *wiphy, struct net_device *dev, | ||
688 | const u8 *peer, u8 action_code, u8 dialog_token, | ||
689 | u16 status_code, u32 peer_capability, | ||
690 | bool initiator, const u8 *extra_ies, | ||
691 | size_t extra_ies_len) | ||
692 | { | ||
693 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
694 | struct ieee80211_local *local = sdata->local; | ||
695 | struct sta_info *sta; | ||
696 | int ret; | ||
697 | |||
698 | /* | ||
699 | * No packets can be transmitted to the peer via the AP during setup - | ||
700 | * the STA is set as a TDLS peer, but is not authorized. | ||
701 | * During teardown, we prevent direct transmissions by stopping the | ||
702 | * queues and flushing all direct packets. | ||
703 | */ | ||
704 | ieee80211_stop_vif_queues(local, sdata, | ||
705 | IEEE80211_QUEUE_STOP_REASON_TDLS_TEARDOWN); | ||
706 | ieee80211_flush_queues(local, sdata); | ||
707 | |||
708 | ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, action_code, | ||
709 | dialog_token, status_code, | ||
710 | peer_capability, initiator, | ||
711 | extra_ies, extra_ies_len); | ||
712 | if (ret < 0) | ||
713 | sdata_err(sdata, "Failed sending TDLS teardown packet %d\n", | ||
714 | ret); | ||
715 | |||
716 | /* | ||
717 | * Remove the STA AUTH flag to force further traffic through the AP. If | ||
718 | * the STA was unreachable, it was already removed. | ||
719 | */ | ||
720 | rcu_read_lock(); | ||
721 | sta = sta_info_get(sdata, peer); | ||
722 | if (sta) | ||
723 | clear_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH); | ||
724 | rcu_read_unlock(); | ||
725 | |||
726 | ieee80211_wake_vif_queues(local, sdata, | ||
727 | IEEE80211_QUEUE_STOP_REASON_TDLS_TEARDOWN); | ||
728 | |||
729 | return 0; | ||
730 | } | ||
731 | |||
732 | int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, | ||
733 | const u8 *peer, u8 action_code, u8 dialog_token, | ||
734 | u16 status_code, u32 peer_capability, | ||
735 | bool initiator, const u8 *extra_ies, | ||
736 | size_t extra_ies_len) | ||
737 | { | ||
738 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
739 | int ret; | ||
740 | |||
741 | if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) | ||
742 | return -ENOTSUPP; | ||
743 | |||
744 | /* make sure we are in managed mode, and associated */ | ||
745 | if (sdata->vif.type != NL80211_IFTYPE_STATION || | ||
746 | !sdata->u.mgd.associated) | ||
747 | return -EINVAL; | ||
748 | |||
749 | switch (action_code) { | ||
750 | case WLAN_TDLS_SETUP_REQUEST: | ||
751 | case WLAN_TDLS_SETUP_RESPONSE: | ||
752 | ret = ieee80211_tdls_mgmt_setup(wiphy, dev, peer, action_code, | ||
753 | dialog_token, status_code, | ||
754 | peer_capability, initiator, | ||
755 | extra_ies, extra_ies_len); | ||
756 | break; | ||
757 | case WLAN_TDLS_TEARDOWN: | ||
758 | ret = ieee80211_tdls_mgmt_teardown(wiphy, dev, peer, | ||
759 | action_code, dialog_token, | ||
760 | status_code, | ||
761 | peer_capability, initiator, | ||
762 | extra_ies, extra_ies_len); | ||
763 | break; | ||
764 | case WLAN_TDLS_DISCOVERY_REQUEST: | ||
765 | /* | ||
766 | * Protect the discovery so we can hear the TDLS discovery | ||
767 | * response frame. It is transmitted directly and not buffered | ||
768 | * by the AP. | ||
769 | */ | ||
770 | drv_mgd_protect_tdls_discover(sdata->local, sdata); | ||
771 | /* fall-through */ | ||
772 | case WLAN_TDLS_SETUP_CONFIRM: | ||
773 | case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: | ||
774 | /* no special handling */ | ||
775 | ret = ieee80211_tdls_prep_mgmt_packet(wiphy, dev, peer, | ||
776 | action_code, | ||
777 | dialog_token, | ||
778 | status_code, | ||
779 | peer_capability, | ||
780 | initiator, extra_ies, | ||
781 | extra_ies_len); | ||
782 | break; | ||
783 | default: | ||
784 | ret = -EOPNOTSUPP; | ||
785 | break; | ||
786 | } | ||
787 | |||
788 | tdls_dbg(sdata, "TDLS mgmt action %d peer %pM status %d\n", | ||
789 | action_code, peer, ret); | ||
790 | return ret; | ||
791 | } | ||
792 | |||
287 | int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, | 793 | int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, |
288 | const u8 *peer, enum nl80211_tdls_operation oper) | 794 | const u8 *peer, enum nl80211_tdls_operation oper) |
289 | { | 795 | { |
290 | struct sta_info *sta; | 796 | struct sta_info *sta; |
291 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 797 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
798 | struct ieee80211_local *local = sdata->local; | ||
799 | int ret; | ||
292 | 800 | ||
293 | if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) | 801 | if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) |
294 | return -ENOTSUPP; | 802 | return -ENOTSUPP; |
@@ -296,6 +804,18 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, | |||
296 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 804 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
297 | return -EINVAL; | 805 | return -EINVAL; |
298 | 806 | ||
807 | switch (oper) { | ||
808 | case NL80211_TDLS_ENABLE_LINK: | ||
809 | case NL80211_TDLS_DISABLE_LINK: | ||
810 | break; | ||
811 | case NL80211_TDLS_TEARDOWN: | ||
812 | case NL80211_TDLS_SETUP: | ||
813 | case NL80211_TDLS_DISCOVERY_REQ: | ||
814 | /* We don't support in-driver setup/teardown/discovery */ | ||
815 | return -ENOTSUPP; | ||
816 | } | ||
817 | |||
818 | mutex_lock(&local->mtx); | ||
299 | tdls_dbg(sdata, "TDLS oper %d peer %pM\n", oper, peer); | 819 | tdls_dbg(sdata, "TDLS oper %d peer %pM\n", oper, peer); |
300 | 820 | ||
301 | switch (oper) { | 821 | switch (oper) { |
@@ -304,22 +824,60 @@ int ieee80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, | |||
304 | sta = sta_info_get(sdata, peer); | 824 | sta = sta_info_get(sdata, peer); |
305 | if (!sta) { | 825 | if (!sta) { |
306 | rcu_read_unlock(); | 826 | rcu_read_unlock(); |
307 | return -ENOLINK; | 827 | ret = -ENOLINK; |
828 | break; | ||
308 | } | 829 | } |
309 | 830 | ||
310 | set_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH); | 831 | set_sta_flag(sta, WLAN_STA_TDLS_PEER_AUTH); |
311 | rcu_read_unlock(); | 832 | rcu_read_unlock(); |
833 | |||
834 | WARN_ON_ONCE(is_zero_ether_addr(sdata->u.mgd.tdls_peer) || | ||
835 | !ether_addr_equal(sdata->u.mgd.tdls_peer, peer)); | ||
836 | ret = 0; | ||
312 | break; | 837 | break; |
313 | case NL80211_TDLS_DISABLE_LINK: | 838 | case NL80211_TDLS_DISABLE_LINK: |
314 | return sta_info_destroy_addr(sdata, peer); | 839 | /* |
315 | case NL80211_TDLS_TEARDOWN: | 840 | * The teardown message in ieee80211_tdls_mgmt_teardown() was |
316 | case NL80211_TDLS_SETUP: | 841 | * created while the queues were stopped, so it might still be |
317 | case NL80211_TDLS_DISCOVERY_REQ: | 842 | * pending. Before flushing the queues we need to be sure the |
318 | /* We don't support in-driver setup/teardown/discovery */ | 843 | * message is handled by the tasklet handling pending messages, |
319 | return -ENOTSUPP; | 844 | * otherwise we might start destroying the station before |
845 | * sending the teardown packet. | ||
846 | * Note that this only forces the tasklet to flush pendings - | ||
847 | * not to stop the tasklet from rescheduling itself. | ||
848 | */ | ||
849 | tasklet_kill(&local->tx_pending_tasklet); | ||
850 | /* flush a potentially queued teardown packet */ | ||
851 | ieee80211_flush_queues(local, sdata); | ||
852 | |||
853 | ret = sta_info_destroy_addr(sdata, peer); | ||
854 | break; | ||
320 | default: | 855 | default: |
321 | return -ENOTSUPP; | 856 | ret = -ENOTSUPP; |
857 | break; | ||
322 | } | 858 | } |
323 | 859 | ||
324 | return 0; | 860 | if (ret == 0 && ether_addr_equal(sdata->u.mgd.tdls_peer, peer)) { |
861 | cancel_delayed_work(&sdata->u.mgd.tdls_peer_del_work); | ||
862 | eth_zero_addr(sdata->u.mgd.tdls_peer); | ||
863 | } | ||
864 | |||
865 | mutex_unlock(&local->mtx); | ||
866 | return ret; | ||
867 | } | ||
868 | |||
869 | void ieee80211_tdls_oper_request(struct ieee80211_vif *vif, const u8 *peer, | ||
870 | enum nl80211_tdls_operation oper, | ||
871 | u16 reason_code, gfp_t gfp) | ||
872 | { | ||
873 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
874 | |||
875 | if (vif->type != NL80211_IFTYPE_STATION || !vif->bss_conf.assoc) { | ||
876 | sdata_err(sdata, "Discarding TDLS oper %d - not STA or disconnected\n", | ||
877 | oper); | ||
878 | return; | ||
879 | } | ||
880 | |||
881 | cfg80211_tdls_oper_request(sdata->dev, peer, oper, reason_code, gfp); | ||
325 | } | 882 | } |
883 | EXPORT_SYMBOL(ieee80211_tdls_oper_request); | ||
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h index cfe1a0688b5c..02ac535d1274 100644 --- a/net/mac80211/trace.h +++ b/net/mac80211/trace.h | |||
@@ -1330,6 +1330,13 @@ DEFINE_EVENT(local_sdata_evt, drv_mgd_prepare_tx, | |||
1330 | TP_ARGS(local, sdata) | 1330 | TP_ARGS(local, sdata) |
1331 | ); | 1331 | ); |
1332 | 1332 | ||
1333 | DEFINE_EVENT(local_sdata_evt, drv_mgd_protect_tdls_discover, | ||
1334 | TP_PROTO(struct ieee80211_local *local, | ||
1335 | struct ieee80211_sub_if_data *sdata), | ||
1336 | |||
1337 | TP_ARGS(local, sdata) | ||
1338 | ); | ||
1339 | |||
1333 | DECLARE_EVENT_CLASS(local_chanctx, | 1340 | DECLARE_EVENT_CLASS(local_chanctx, |
1334 | TP_PROTO(struct ieee80211_local *local, | 1341 | TP_PROTO(struct ieee80211_local *local, |
1335 | struct ieee80211_chanctx *ctx), | 1342 | struct ieee80211_chanctx *ctx), |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 1a252c606ad0..464106c023d8 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -250,7 +250,8 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx) | |||
250 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { | 250 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { |
251 | ieee80211_stop_queues_by_reason(&local->hw, | 251 | ieee80211_stop_queues_by_reason(&local->hw, |
252 | IEEE80211_MAX_QUEUE_MAP, | 252 | IEEE80211_MAX_QUEUE_MAP, |
253 | IEEE80211_QUEUE_STOP_REASON_PS); | 253 | IEEE80211_QUEUE_STOP_REASON_PS, |
254 | false); | ||
254 | ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; | 255 | ifmgd->flags &= ~IEEE80211_STA_NULLFUNC_ACKED; |
255 | ieee80211_queue_work(&local->hw, | 256 | ieee80211_queue_work(&local->hw, |
256 | &local->dynamic_ps_disable_work); | 257 | &local->dynamic_ps_disable_work); |
@@ -473,7 +474,8 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
473 | return TX_CONTINUE; | 474 | return TX_CONTINUE; |
474 | 475 | ||
475 | if (unlikely((test_sta_flag(sta, WLAN_STA_PS_STA) || | 476 | if (unlikely((test_sta_flag(sta, WLAN_STA_PS_STA) || |
476 | test_sta_flag(sta, WLAN_STA_PS_DRIVER)) && | 477 | test_sta_flag(sta, WLAN_STA_PS_DRIVER) || |
478 | test_sta_flag(sta, WLAN_STA_PS_DELIVER)) && | ||
477 | !(info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER))) { | 479 | !(info->flags & IEEE80211_TX_CTL_NO_PS_BUFFER))) { |
478 | int ac = skb_get_queue_mapping(tx->skb); | 480 | int ac = skb_get_queue_mapping(tx->skb); |
479 | 481 | ||
@@ -496,7 +498,8 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) | |||
496 | * ahead and Tx the packet. | 498 | * ahead and Tx the packet. |
497 | */ | 499 | */ |
498 | if (!test_sta_flag(sta, WLAN_STA_PS_STA) && | 500 | if (!test_sta_flag(sta, WLAN_STA_PS_STA) && |
499 | !test_sta_flag(sta, WLAN_STA_PS_DRIVER)) { | 501 | !test_sta_flag(sta, WLAN_STA_PS_DRIVER) && |
502 | !test_sta_flag(sta, WLAN_STA_PS_DELIVER)) { | ||
500 | spin_unlock(&sta->ps_lock); | 503 | spin_unlock(&sta->ps_lock); |
501 | return TX_CONTINUE; | 504 | return TX_CONTINUE; |
502 | } | 505 | } |
@@ -1618,12 +1621,12 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1618 | { | 1621 | { |
1619 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 1622 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
1620 | struct ieee80211_chanctx_conf *chanctx_conf; | 1623 | struct ieee80211_chanctx_conf *chanctx_conf; |
1621 | struct ieee80211_channel *chan; | ||
1622 | struct ieee80211_radiotap_header *prthdr = | 1624 | struct ieee80211_radiotap_header *prthdr = |
1623 | (struct ieee80211_radiotap_header *)skb->data; | 1625 | (struct ieee80211_radiotap_header *)skb->data; |
1624 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1626 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1625 | struct ieee80211_hdr *hdr; | 1627 | struct ieee80211_hdr *hdr; |
1626 | struct ieee80211_sub_if_data *tmp_sdata, *sdata; | 1628 | struct ieee80211_sub_if_data *tmp_sdata, *sdata; |
1629 | struct cfg80211_chan_def *chandef; | ||
1627 | u16 len_rthdr; | 1630 | u16 len_rthdr; |
1628 | int hdrlen; | 1631 | int hdrlen; |
1629 | 1632 | ||
@@ -1721,9 +1724,9 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1721 | } | 1724 | } |
1722 | 1725 | ||
1723 | if (chanctx_conf) | 1726 | if (chanctx_conf) |
1724 | chan = chanctx_conf->def.chan; | 1727 | chandef = &chanctx_conf->def; |
1725 | else if (!local->use_chanctx) | 1728 | else if (!local->use_chanctx) |
1726 | chan = local->_oper_chandef.chan; | 1729 | chandef = &local->_oper_chandef; |
1727 | else | 1730 | else |
1728 | goto fail_rcu; | 1731 | goto fail_rcu; |
1729 | 1732 | ||
@@ -1743,10 +1746,11 @@ netdev_tx_t ieee80211_monitor_start_xmit(struct sk_buff *skb, | |||
1743 | * radar detection by itself. We can do that later by adding a | 1746 | * radar detection by itself. We can do that later by adding a |
1744 | * monitor flag interfaces used for AP support. | 1747 | * monitor flag interfaces used for AP support. |
1745 | */ | 1748 | */ |
1746 | if ((chan->flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_RADAR))) | 1749 | if (!cfg80211_reg_can_beacon(local->hw.wiphy, chandef, |
1750 | sdata->vif.type)) | ||
1747 | goto fail_rcu; | 1751 | goto fail_rcu; |
1748 | 1752 | ||
1749 | ieee80211_xmit(sdata, skb, chan->band); | 1753 | ieee80211_xmit(sdata, skb, chandef->chan->band); |
1750 | rcu_read_unlock(); | 1754 | rcu_read_unlock(); |
1751 | 1755 | ||
1752 | return NETDEV_TX_OK; | 1756 | return NETDEV_TX_OK; |
@@ -1767,15 +1771,12 @@ fail: | |||
1767 | static void ieee80211_tx_latency_start_msrmnt(struct ieee80211_local *local, | 1771 | static void ieee80211_tx_latency_start_msrmnt(struct ieee80211_local *local, |
1768 | struct sk_buff *skb) | 1772 | struct sk_buff *skb) |
1769 | { | 1773 | { |
1770 | struct timespec skb_arv; | ||
1771 | struct ieee80211_tx_latency_bin_ranges *tx_latency; | 1774 | struct ieee80211_tx_latency_bin_ranges *tx_latency; |
1772 | 1775 | ||
1773 | tx_latency = rcu_dereference(local->tx_latency); | 1776 | tx_latency = rcu_dereference(local->tx_latency); |
1774 | if (!tx_latency) | 1777 | if (!tx_latency) |
1775 | return; | 1778 | return; |
1776 | 1779 | skb->tstamp = ktime_get(); | |
1777 | ktime_get_ts(&skb_arv); | ||
1778 | skb->tstamp = ktime_set(skb_arv.tv_sec, skb_arv.tv_nsec); | ||
1779 | } | 1780 | } |
1780 | 1781 | ||
1781 | /** | 1782 | /** |
@@ -1810,7 +1811,7 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1810 | int nh_pos, h_pos; | 1811 | int nh_pos, h_pos; |
1811 | struct sta_info *sta = NULL; | 1812 | struct sta_info *sta = NULL; |
1812 | bool wme_sta = false, authorized = false, tdls_auth = false; | 1813 | bool wme_sta = false, authorized = false, tdls_auth = false; |
1813 | bool tdls_direct = false; | 1814 | bool tdls_peer = false, tdls_setup_frame = false; |
1814 | bool multicast; | 1815 | bool multicast; |
1815 | u32 info_flags = 0; | 1816 | u32 info_flags = 0; |
1816 | u16 info_id = 0; | 1817 | u16 info_id = 0; |
@@ -1952,34 +1953,35 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1952 | #endif | 1953 | #endif |
1953 | case NL80211_IFTYPE_STATION: | 1954 | case NL80211_IFTYPE_STATION: |
1954 | if (sdata->wdev.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) { | 1955 | if (sdata->wdev.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) { |
1955 | bool tdls_peer = false; | ||
1956 | |||
1957 | sta = sta_info_get(sdata, skb->data); | 1956 | sta = sta_info_get(sdata, skb->data); |
1958 | if (sta) { | 1957 | if (sta) { |
1959 | authorized = test_sta_flag(sta, | 1958 | authorized = test_sta_flag(sta, |
1960 | WLAN_STA_AUTHORIZED); | 1959 | WLAN_STA_AUTHORIZED); |
1961 | wme_sta = test_sta_flag(sta, WLAN_STA_WME); | 1960 | wme_sta = test_sta_flag(sta, WLAN_STA_WME); |
1962 | tdls_peer = test_sta_flag(sta, | 1961 | tdls_peer = test_sta_flag(sta, |
1963 | WLAN_STA_TDLS_PEER); | 1962 | WLAN_STA_TDLS_PEER); |
1964 | tdls_auth = test_sta_flag(sta, | 1963 | tdls_auth = test_sta_flag(sta, |
1965 | WLAN_STA_TDLS_PEER_AUTH); | 1964 | WLAN_STA_TDLS_PEER_AUTH); |
1966 | } | 1965 | } |
1967 | 1966 | ||
1968 | /* | 1967 | if (tdls_peer) |
1969 | * If the TDLS link is enabled, send everything | 1968 | tdls_setup_frame = |
1970 | * directly. Otherwise, allow TDLS setup frames | 1969 | ethertype == ETH_P_TDLS && |
1971 | * to be transmitted indirectly. | 1970 | skb->len > 14 && |
1972 | */ | 1971 | skb->data[14] == WLAN_TDLS_SNAP_RFTYPE; |
1973 | tdls_direct = tdls_peer && (tdls_auth || | ||
1974 | !(ethertype == ETH_P_TDLS && skb->len > 14 && | ||
1975 | skb->data[14] == WLAN_TDLS_SNAP_RFTYPE)); | ||
1976 | } | 1972 | } |
1977 | 1973 | ||
1978 | if (tdls_direct) { | 1974 | /* |
1979 | /* link during setup - throw out frames to peer */ | 1975 | * TDLS link during setup - throw out frames to peer. We allow |
1980 | if (!tdls_auth) | 1976 | * TDLS-setup frames to unauthorized peers for the special case |
1981 | goto fail_rcu; | 1977 | * of a link teardown after a TDLS sta is removed due to being |
1978 | * unreachable. | ||
1979 | */ | ||
1980 | if (tdls_peer && !tdls_auth && !tdls_setup_frame) | ||
1981 | goto fail_rcu; | ||
1982 | 1982 | ||
1983 | /* send direct packets to authorized TDLS peers */ | ||
1984 | if (tdls_peer && tdls_auth) { | ||
1983 | /* DA SA BSSID */ | 1985 | /* DA SA BSSID */ |
1984 | memcpy(hdr.addr1, skb->data, ETH_ALEN); | 1986 | memcpy(hdr.addr1, skb->data, ETH_ALEN); |
1985 | memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); | 1987 | memcpy(hdr.addr2, skb->data + ETH_ALEN, ETH_ALEN); |
@@ -2423,7 +2425,7 @@ static void ieee80211_set_csa(struct ieee80211_sub_if_data *sdata, | |||
2423 | u8 *beacon_data; | 2425 | u8 *beacon_data; |
2424 | size_t beacon_data_len; | 2426 | size_t beacon_data_len; |
2425 | int i; | 2427 | int i; |
2426 | u8 count = sdata->csa_current_counter; | 2428 | u8 count = beacon->csa_current_counter; |
2427 | 2429 | ||
2428 | switch (sdata->vif.type) { | 2430 | switch (sdata->vif.type) { |
2429 | case NL80211_IFTYPE_AP: | 2431 | case NL80211_IFTYPE_AP: |
@@ -2442,46 +2444,53 @@ static void ieee80211_set_csa(struct ieee80211_sub_if_data *sdata, | |||
2442 | return; | 2444 | return; |
2443 | } | 2445 | } |
2444 | 2446 | ||
2447 | rcu_read_lock(); | ||
2445 | for (i = 0; i < IEEE80211_MAX_CSA_COUNTERS_NUM; ++i) { | 2448 | for (i = 0; i < IEEE80211_MAX_CSA_COUNTERS_NUM; ++i) { |
2446 | u16 counter_offset_beacon = | 2449 | resp = rcu_dereference(sdata->u.ap.probe_resp); |
2447 | sdata->csa_counter_offset_beacon[i]; | ||
2448 | u16 counter_offset_presp = sdata->csa_counter_offset_presp[i]; | ||
2449 | 2450 | ||
2450 | if (counter_offset_beacon) { | 2451 | if (beacon->csa_counter_offsets[i]) { |
2451 | if (WARN_ON(counter_offset_beacon >= beacon_data_len)) | 2452 | if (WARN_ON_ONCE(beacon->csa_counter_offsets[i] >= |
2452 | return; | 2453 | beacon_data_len)) { |
2453 | |||
2454 | beacon_data[counter_offset_beacon] = count; | ||
2455 | } | ||
2456 | |||
2457 | if (sdata->vif.type == NL80211_IFTYPE_AP && | ||
2458 | counter_offset_presp) { | ||
2459 | rcu_read_lock(); | ||
2460 | resp = rcu_dereference(sdata->u.ap.probe_resp); | ||
2461 | |||
2462 | /* If nl80211 accepted the offset, this should | ||
2463 | * not happen. | ||
2464 | */ | ||
2465 | if (WARN_ON(!resp)) { | ||
2466 | rcu_read_unlock(); | 2454 | rcu_read_unlock(); |
2467 | return; | 2455 | return; |
2468 | } | 2456 | } |
2469 | resp->data[counter_offset_presp] = count; | 2457 | |
2470 | rcu_read_unlock(); | 2458 | beacon_data[beacon->csa_counter_offsets[i]] = count; |
2471 | } | 2459 | } |
2460 | |||
2461 | if (sdata->vif.type == NL80211_IFTYPE_AP && resp) | ||
2462 | resp->data[resp->csa_counter_offsets[i]] = count; | ||
2472 | } | 2463 | } |
2464 | rcu_read_unlock(); | ||
2473 | } | 2465 | } |
2474 | 2466 | ||
2475 | u8 ieee80211_csa_update_counter(struct ieee80211_vif *vif) | 2467 | u8 ieee80211_csa_update_counter(struct ieee80211_vif *vif) |
2476 | { | 2468 | { |
2477 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | 2469 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); |
2470 | struct beacon_data *beacon = NULL; | ||
2471 | u8 count = 0; | ||
2472 | |||
2473 | rcu_read_lock(); | ||
2478 | 2474 | ||
2479 | sdata->csa_current_counter--; | 2475 | if (sdata->vif.type == NL80211_IFTYPE_AP) |
2476 | beacon = rcu_dereference(sdata->u.ap.beacon); | ||
2477 | else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) | ||
2478 | beacon = rcu_dereference(sdata->u.ibss.presp); | ||
2479 | else if (ieee80211_vif_is_mesh(&sdata->vif)) | ||
2480 | beacon = rcu_dereference(sdata->u.mesh.beacon); | ||
2481 | |||
2482 | if (!beacon) | ||
2483 | goto unlock; | ||
2484 | |||
2485 | beacon->csa_current_counter--; | ||
2480 | 2486 | ||
2481 | /* the counter should never reach 0 */ | 2487 | /* the counter should never reach 0 */ |
2482 | WARN_ON(!sdata->csa_current_counter); | 2488 | WARN_ON_ONCE(!beacon->csa_current_counter); |
2489 | count = beacon->csa_current_counter; | ||
2483 | 2490 | ||
2484 | return sdata->csa_current_counter; | 2491 | unlock: |
2492 | rcu_read_unlock(); | ||
2493 | return count; | ||
2485 | } | 2494 | } |
2486 | EXPORT_SYMBOL(ieee80211_csa_update_counter); | 2495 | EXPORT_SYMBOL(ieee80211_csa_update_counter); |
2487 | 2496 | ||
@@ -2491,7 +2500,6 @@ bool ieee80211_csa_is_complete(struct ieee80211_vif *vif) | |||
2491 | struct beacon_data *beacon = NULL; | 2500 | struct beacon_data *beacon = NULL; |
2492 | u8 *beacon_data; | 2501 | u8 *beacon_data; |
2493 | size_t beacon_data_len; | 2502 | size_t beacon_data_len; |
2494 | int counter_beacon = sdata->csa_counter_offset_beacon[0]; | ||
2495 | int ret = false; | 2503 | int ret = false; |
2496 | 2504 | ||
2497 | if (!ieee80211_sdata_running(sdata)) | 2505 | if (!ieee80211_sdata_running(sdata)) |
@@ -2529,10 +2537,13 @@ bool ieee80211_csa_is_complete(struct ieee80211_vif *vif) | |||
2529 | goto out; | 2537 | goto out; |
2530 | } | 2538 | } |
2531 | 2539 | ||
2532 | if (WARN_ON(counter_beacon > beacon_data_len)) | 2540 | if (!beacon->csa_counter_offsets[0]) |
2533 | goto out; | 2541 | goto out; |
2534 | 2542 | ||
2535 | if (beacon_data[counter_beacon] == 1) | 2543 | if (WARN_ON_ONCE(beacon->csa_counter_offsets[0] > beacon_data_len)) |
2544 | goto out; | ||
2545 | |||
2546 | if (beacon_data[beacon->csa_counter_offsets[0]] == 1) | ||
2536 | ret = true; | 2547 | ret = true; |
2537 | out: | 2548 | out: |
2538 | rcu_read_unlock(); | 2549 | rcu_read_unlock(); |
@@ -2548,6 +2559,7 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
2548 | bool is_template) | 2559 | bool is_template) |
2549 | { | 2560 | { |
2550 | struct ieee80211_local *local = hw_to_local(hw); | 2561 | struct ieee80211_local *local = hw_to_local(hw); |
2562 | struct beacon_data *beacon = NULL; | ||
2551 | struct sk_buff *skb = NULL; | 2563 | struct sk_buff *skb = NULL; |
2552 | struct ieee80211_tx_info *info; | 2564 | struct ieee80211_tx_info *info; |
2553 | struct ieee80211_sub_if_data *sdata = NULL; | 2565 | struct ieee80211_sub_if_data *sdata = NULL; |
@@ -2569,10 +2581,10 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
2569 | 2581 | ||
2570 | if (sdata->vif.type == NL80211_IFTYPE_AP) { | 2582 | if (sdata->vif.type == NL80211_IFTYPE_AP) { |
2571 | struct ieee80211_if_ap *ap = &sdata->u.ap; | 2583 | struct ieee80211_if_ap *ap = &sdata->u.ap; |
2572 | struct beacon_data *beacon = rcu_dereference(ap->beacon); | ||
2573 | 2584 | ||
2585 | beacon = rcu_dereference(ap->beacon); | ||
2574 | if (beacon) { | 2586 | if (beacon) { |
2575 | if (sdata->vif.csa_active) { | 2587 | if (beacon->csa_counter_offsets[0]) { |
2576 | if (!is_template) | 2588 | if (!is_template) |
2577 | ieee80211_csa_update_counter(vif); | 2589 | ieee80211_csa_update_counter(vif); |
2578 | 2590 | ||
@@ -2613,37 +2625,37 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
2613 | } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { | 2625 | } else if (sdata->vif.type == NL80211_IFTYPE_ADHOC) { |
2614 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 2626 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
2615 | struct ieee80211_hdr *hdr; | 2627 | struct ieee80211_hdr *hdr; |
2616 | struct beacon_data *presp = rcu_dereference(ifibss->presp); | ||
2617 | 2628 | ||
2618 | if (!presp) | 2629 | beacon = rcu_dereference(ifibss->presp); |
2630 | if (!beacon) | ||
2619 | goto out; | 2631 | goto out; |
2620 | 2632 | ||
2621 | if (sdata->vif.csa_active) { | 2633 | if (beacon->csa_counter_offsets[0]) { |
2622 | if (!is_template) | 2634 | if (!is_template) |
2623 | ieee80211_csa_update_counter(vif); | 2635 | ieee80211_csa_update_counter(vif); |
2624 | 2636 | ||
2625 | ieee80211_set_csa(sdata, presp); | 2637 | ieee80211_set_csa(sdata, beacon); |
2626 | } | 2638 | } |
2627 | 2639 | ||
2628 | skb = dev_alloc_skb(local->tx_headroom + presp->head_len + | 2640 | skb = dev_alloc_skb(local->tx_headroom + beacon->head_len + |
2629 | local->hw.extra_beacon_tailroom); | 2641 | local->hw.extra_beacon_tailroom); |
2630 | if (!skb) | 2642 | if (!skb) |
2631 | goto out; | 2643 | goto out; |
2632 | skb_reserve(skb, local->tx_headroom); | 2644 | skb_reserve(skb, local->tx_headroom); |
2633 | memcpy(skb_put(skb, presp->head_len), presp->head, | 2645 | memcpy(skb_put(skb, beacon->head_len), beacon->head, |
2634 | presp->head_len); | 2646 | beacon->head_len); |
2635 | 2647 | ||
2636 | hdr = (struct ieee80211_hdr *) skb->data; | 2648 | hdr = (struct ieee80211_hdr *) skb->data; |
2637 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 2649 | hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
2638 | IEEE80211_STYPE_BEACON); | 2650 | IEEE80211_STYPE_BEACON); |
2639 | } else if (ieee80211_vif_is_mesh(&sdata->vif)) { | 2651 | } else if (ieee80211_vif_is_mesh(&sdata->vif)) { |
2640 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 2652 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
2641 | struct beacon_data *bcn = rcu_dereference(ifmsh->beacon); | ||
2642 | 2653 | ||
2643 | if (!bcn) | 2654 | beacon = rcu_dereference(ifmsh->beacon); |
2655 | if (!beacon) | ||
2644 | goto out; | 2656 | goto out; |
2645 | 2657 | ||
2646 | if (sdata->vif.csa_active) { | 2658 | if (beacon->csa_counter_offsets[0]) { |
2647 | if (!is_template) | 2659 | if (!is_template) |
2648 | /* TODO: For mesh csa_counter is in TU, so | 2660 | /* TODO: For mesh csa_counter is in TU, so |
2649 | * decrementing it by one isn't correct, but | 2661 | * decrementing it by one isn't correct, but |
@@ -2652,40 +2664,42 @@ __ieee80211_beacon_get(struct ieee80211_hw *hw, | |||
2652 | */ | 2664 | */ |
2653 | ieee80211_csa_update_counter(vif); | 2665 | ieee80211_csa_update_counter(vif); |
2654 | 2666 | ||
2655 | ieee80211_set_csa(sdata, bcn); | 2667 | ieee80211_set_csa(sdata, beacon); |
2656 | } | 2668 | } |
2657 | 2669 | ||
2658 | if (ifmsh->sync_ops) | 2670 | if (ifmsh->sync_ops) |
2659 | ifmsh->sync_ops->adjust_tbtt(sdata, bcn); | 2671 | ifmsh->sync_ops->adjust_tbtt(sdata, beacon); |
2660 | 2672 | ||
2661 | skb = dev_alloc_skb(local->tx_headroom + | 2673 | skb = dev_alloc_skb(local->tx_headroom + |
2662 | bcn->head_len + | 2674 | beacon->head_len + |
2663 | 256 + /* TIM IE */ | 2675 | 256 + /* TIM IE */ |
2664 | bcn->tail_len + | 2676 | beacon->tail_len + |
2665 | local->hw.extra_beacon_tailroom); | 2677 | local->hw.extra_beacon_tailroom); |
2666 | if (!skb) | 2678 | if (!skb) |
2667 | goto out; | 2679 | goto out; |
2668 | skb_reserve(skb, local->tx_headroom); | 2680 | skb_reserve(skb, local->tx_headroom); |
2669 | memcpy(skb_put(skb, bcn->head_len), bcn->head, bcn->head_len); | 2681 | memcpy(skb_put(skb, beacon->head_len), beacon->head, |
2682 | beacon->head_len); | ||
2670 | ieee80211_beacon_add_tim(sdata, &ifmsh->ps, skb, is_template); | 2683 | ieee80211_beacon_add_tim(sdata, &ifmsh->ps, skb, is_template); |
2671 | 2684 | ||
2672 | if (offs) { | 2685 | if (offs) { |
2673 | offs->tim_offset = bcn->head_len; | 2686 | offs->tim_offset = beacon->head_len; |
2674 | offs->tim_length = skb->len - bcn->head_len; | 2687 | offs->tim_length = skb->len - beacon->head_len; |
2675 | } | 2688 | } |
2676 | 2689 | ||
2677 | memcpy(skb_put(skb, bcn->tail_len), bcn->tail, bcn->tail_len); | 2690 | memcpy(skb_put(skb, beacon->tail_len), beacon->tail, |
2691 | beacon->tail_len); | ||
2678 | } else { | 2692 | } else { |
2679 | WARN_ON(1); | 2693 | WARN_ON(1); |
2680 | goto out; | 2694 | goto out; |
2681 | } | 2695 | } |
2682 | 2696 | ||
2683 | /* CSA offsets */ | 2697 | /* CSA offsets */ |
2684 | if (offs) { | 2698 | if (offs && beacon) { |
2685 | int i; | 2699 | int i; |
2686 | 2700 | ||
2687 | for (i = 0; i < IEEE80211_MAX_CSA_COUNTERS_NUM; i++) { | 2701 | for (i = 0; i < IEEE80211_MAX_CSA_COUNTERS_NUM; i++) { |
2688 | u16 csa_off = sdata->csa_counter_offset_beacon[i]; | 2702 | u16 csa_off = beacon->csa_counter_offsets[i]; |
2689 | 2703 | ||
2690 | if (!csa_off) | 2704 | if (!csa_off) |
2691 | continue; | 2705 | continue; |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index a6cda52ed920..725af7a468d2 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -317,7 +317,8 @@ void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue) | |||
317 | } | 317 | } |
318 | 318 | ||
319 | static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, | 319 | static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, |
320 | enum queue_stop_reason reason) | 320 | enum queue_stop_reason reason, |
321 | bool refcounted) | ||
321 | { | 322 | { |
322 | struct ieee80211_local *local = hw_to_local(hw); | 323 | struct ieee80211_local *local = hw_to_local(hw); |
323 | 324 | ||
@@ -329,7 +330,13 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, | |||
329 | if (!test_bit(reason, &local->queue_stop_reasons[queue])) | 330 | if (!test_bit(reason, &local->queue_stop_reasons[queue])) |
330 | return; | 331 | return; |
331 | 332 | ||
332 | __clear_bit(reason, &local->queue_stop_reasons[queue]); | 333 | if (!refcounted) |
334 | local->q_stop_reasons[queue][reason] = 0; | ||
335 | else | ||
336 | local->q_stop_reasons[queue][reason]--; | ||
337 | |||
338 | if (local->q_stop_reasons[queue][reason] == 0) | ||
339 | __clear_bit(reason, &local->queue_stop_reasons[queue]); | ||
333 | 340 | ||
334 | if (local->queue_stop_reasons[queue] != 0) | 341 | if (local->queue_stop_reasons[queue] != 0) |
335 | /* someone still has this queue stopped */ | 342 | /* someone still has this queue stopped */ |
@@ -344,25 +351,28 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, | |||
344 | } | 351 | } |
345 | 352 | ||
346 | void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, | 353 | void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, |
347 | enum queue_stop_reason reason) | 354 | enum queue_stop_reason reason, |
355 | bool refcounted) | ||
348 | { | 356 | { |
349 | struct ieee80211_local *local = hw_to_local(hw); | 357 | struct ieee80211_local *local = hw_to_local(hw); |
350 | unsigned long flags; | 358 | unsigned long flags; |
351 | 359 | ||
352 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 360 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
353 | __ieee80211_wake_queue(hw, queue, reason); | 361 | __ieee80211_wake_queue(hw, queue, reason, refcounted); |
354 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 362 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
355 | } | 363 | } |
356 | 364 | ||
357 | void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue) | 365 | void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue) |
358 | { | 366 | { |
359 | ieee80211_wake_queue_by_reason(hw, queue, | 367 | ieee80211_wake_queue_by_reason(hw, queue, |
360 | IEEE80211_QUEUE_STOP_REASON_DRIVER); | 368 | IEEE80211_QUEUE_STOP_REASON_DRIVER, |
369 | false); | ||
361 | } | 370 | } |
362 | EXPORT_SYMBOL(ieee80211_wake_queue); | 371 | EXPORT_SYMBOL(ieee80211_wake_queue); |
363 | 372 | ||
364 | static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue, | 373 | static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue, |
365 | enum queue_stop_reason reason) | 374 | enum queue_stop_reason reason, |
375 | bool refcounted) | ||
366 | { | 376 | { |
367 | struct ieee80211_local *local = hw_to_local(hw); | 377 | struct ieee80211_local *local = hw_to_local(hw); |
368 | struct ieee80211_sub_if_data *sdata; | 378 | struct ieee80211_sub_if_data *sdata; |
@@ -373,10 +383,13 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue, | |||
373 | if (WARN_ON(queue >= hw->queues)) | 383 | if (WARN_ON(queue >= hw->queues)) |
374 | return; | 384 | return; |
375 | 385 | ||
376 | if (test_bit(reason, &local->queue_stop_reasons[queue])) | 386 | if (!refcounted) |
377 | return; | 387 | local->q_stop_reasons[queue][reason] = 1; |
388 | else | ||
389 | local->q_stop_reasons[queue][reason]++; | ||
378 | 390 | ||
379 | __set_bit(reason, &local->queue_stop_reasons[queue]); | 391 | if (__test_and_set_bit(reason, &local->queue_stop_reasons[queue])) |
392 | return; | ||
380 | 393 | ||
381 | if (local->hw.queues < IEEE80211_NUM_ACS) | 394 | if (local->hw.queues < IEEE80211_NUM_ACS) |
382 | n_acs = 1; | 395 | n_acs = 1; |
@@ -398,20 +411,22 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue, | |||
398 | } | 411 | } |
399 | 412 | ||
400 | void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, | 413 | void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, |
401 | enum queue_stop_reason reason) | 414 | enum queue_stop_reason reason, |
415 | bool refcounted) | ||
402 | { | 416 | { |
403 | struct ieee80211_local *local = hw_to_local(hw); | 417 | struct ieee80211_local *local = hw_to_local(hw); |
404 | unsigned long flags; | 418 | unsigned long flags; |
405 | 419 | ||
406 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 420 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
407 | __ieee80211_stop_queue(hw, queue, reason); | 421 | __ieee80211_stop_queue(hw, queue, reason, refcounted); |
408 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 422 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
409 | } | 423 | } |
410 | 424 | ||
411 | void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue) | 425 | void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue) |
412 | { | 426 | { |
413 | ieee80211_stop_queue_by_reason(hw, queue, | 427 | ieee80211_stop_queue_by_reason(hw, queue, |
414 | IEEE80211_QUEUE_STOP_REASON_DRIVER); | 428 | IEEE80211_QUEUE_STOP_REASON_DRIVER, |
429 | false); | ||
415 | } | 430 | } |
416 | EXPORT_SYMBOL(ieee80211_stop_queue); | 431 | EXPORT_SYMBOL(ieee80211_stop_queue); |
417 | 432 | ||
@@ -429,9 +444,11 @@ void ieee80211_add_pending_skb(struct ieee80211_local *local, | |||
429 | } | 444 | } |
430 | 445 | ||
431 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 446 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
432 | __ieee80211_stop_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD); | 447 | __ieee80211_stop_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD, |
448 | false); | ||
433 | __skb_queue_tail(&local->pending[queue], skb); | 449 | __skb_queue_tail(&local->pending[queue], skb); |
434 | __ieee80211_wake_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD); | 450 | __ieee80211_wake_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD, |
451 | false); | ||
435 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 452 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
436 | } | 453 | } |
437 | 454 | ||
@@ -455,20 +472,23 @@ void ieee80211_add_pending_skbs(struct ieee80211_local *local, | |||
455 | queue = info->hw_queue; | 472 | queue = info->hw_queue; |
456 | 473 | ||
457 | __ieee80211_stop_queue(hw, queue, | 474 | __ieee80211_stop_queue(hw, queue, |
458 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD); | 475 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD, |
476 | false); | ||
459 | 477 | ||
460 | __skb_queue_tail(&local->pending[queue], skb); | 478 | __skb_queue_tail(&local->pending[queue], skb); |
461 | } | 479 | } |
462 | 480 | ||
463 | for (i = 0; i < hw->queues; i++) | 481 | for (i = 0; i < hw->queues; i++) |
464 | __ieee80211_wake_queue(hw, i, | 482 | __ieee80211_wake_queue(hw, i, |
465 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD); | 483 | IEEE80211_QUEUE_STOP_REASON_SKB_ADD, |
484 | false); | ||
466 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 485 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
467 | } | 486 | } |
468 | 487 | ||
469 | void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, | 488 | void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, |
470 | unsigned long queues, | 489 | unsigned long queues, |
471 | enum queue_stop_reason reason) | 490 | enum queue_stop_reason reason, |
491 | bool refcounted) | ||
472 | { | 492 | { |
473 | struct ieee80211_local *local = hw_to_local(hw); | 493 | struct ieee80211_local *local = hw_to_local(hw); |
474 | unsigned long flags; | 494 | unsigned long flags; |
@@ -477,7 +497,7 @@ void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, | |||
477 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 497 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
478 | 498 | ||
479 | for_each_set_bit(i, &queues, hw->queues) | 499 | for_each_set_bit(i, &queues, hw->queues) |
480 | __ieee80211_stop_queue(hw, i, reason); | 500 | __ieee80211_stop_queue(hw, i, reason, refcounted); |
481 | 501 | ||
482 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 502 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
483 | } | 503 | } |
@@ -485,7 +505,8 @@ void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, | |||
485 | void ieee80211_stop_queues(struct ieee80211_hw *hw) | 505 | void ieee80211_stop_queues(struct ieee80211_hw *hw) |
486 | { | 506 | { |
487 | ieee80211_stop_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP, | 507 | ieee80211_stop_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP, |
488 | IEEE80211_QUEUE_STOP_REASON_DRIVER); | 508 | IEEE80211_QUEUE_STOP_REASON_DRIVER, |
509 | false); | ||
489 | } | 510 | } |
490 | EXPORT_SYMBOL(ieee80211_stop_queues); | 511 | EXPORT_SYMBOL(ieee80211_stop_queues); |
491 | 512 | ||
@@ -508,7 +529,8 @@ EXPORT_SYMBOL(ieee80211_queue_stopped); | |||
508 | 529 | ||
509 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, | 530 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, |
510 | unsigned long queues, | 531 | unsigned long queues, |
511 | enum queue_stop_reason reason) | 532 | enum queue_stop_reason reason, |
533 | bool refcounted) | ||
512 | { | 534 | { |
513 | struct ieee80211_local *local = hw_to_local(hw); | 535 | struct ieee80211_local *local = hw_to_local(hw); |
514 | unsigned long flags; | 536 | unsigned long flags; |
@@ -517,7 +539,7 @@ void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, | |||
517 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | 539 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); |
518 | 540 | ||
519 | for_each_set_bit(i, &queues, hw->queues) | 541 | for_each_set_bit(i, &queues, hw->queues) |
520 | __ieee80211_wake_queue(hw, i, reason); | 542 | __ieee80211_wake_queue(hw, i, reason, refcounted); |
521 | 543 | ||
522 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | 544 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); |
523 | } | 545 | } |
@@ -525,17 +547,16 @@ void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, | |||
525 | void ieee80211_wake_queues(struct ieee80211_hw *hw) | 547 | void ieee80211_wake_queues(struct ieee80211_hw *hw) |
526 | { | 548 | { |
527 | ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP, | 549 | ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP, |
528 | IEEE80211_QUEUE_STOP_REASON_DRIVER); | 550 | IEEE80211_QUEUE_STOP_REASON_DRIVER, |
551 | false); | ||
529 | } | 552 | } |
530 | EXPORT_SYMBOL(ieee80211_wake_queues); | 553 | EXPORT_SYMBOL(ieee80211_wake_queues); |
531 | 554 | ||
532 | void ieee80211_flush_queues(struct ieee80211_local *local, | 555 | static unsigned int |
533 | struct ieee80211_sub_if_data *sdata) | 556 | ieee80211_get_vif_queues(struct ieee80211_local *local, |
557 | struct ieee80211_sub_if_data *sdata) | ||
534 | { | 558 | { |
535 | u32 queues; | 559 | unsigned int queues; |
536 | |||
537 | if (!local->ops->flush) | ||
538 | return; | ||
539 | 560 | ||
540 | if (sdata && local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) { | 561 | if (sdata && local->hw.flags & IEEE80211_HW_QUEUE_CONTROL) { |
541 | int ac; | 562 | int ac; |
@@ -551,13 +572,46 @@ void ieee80211_flush_queues(struct ieee80211_local *local, | |||
551 | queues = BIT(local->hw.queues) - 1; | 572 | queues = BIT(local->hw.queues) - 1; |
552 | } | 573 | } |
553 | 574 | ||
554 | ieee80211_stop_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP, | 575 | return queues; |
555 | IEEE80211_QUEUE_STOP_REASON_FLUSH); | 576 | } |
577 | |||
578 | void ieee80211_flush_queues(struct ieee80211_local *local, | ||
579 | struct ieee80211_sub_if_data *sdata) | ||
580 | { | ||
581 | unsigned int queues; | ||
582 | |||
583 | if (!local->ops->flush) | ||
584 | return; | ||
585 | |||
586 | queues = ieee80211_get_vif_queues(local, sdata); | ||
587 | |||
588 | ieee80211_stop_queues_by_reason(&local->hw, queues, | ||
589 | IEEE80211_QUEUE_STOP_REASON_FLUSH, | ||
590 | false); | ||
556 | 591 | ||
557 | drv_flush(local, sdata, queues, false); | 592 | drv_flush(local, sdata, queues, false); |
558 | 593 | ||
559 | ieee80211_wake_queues_by_reason(&local->hw, IEEE80211_MAX_QUEUE_MAP, | 594 | ieee80211_wake_queues_by_reason(&local->hw, queues, |
560 | IEEE80211_QUEUE_STOP_REASON_FLUSH); | 595 | IEEE80211_QUEUE_STOP_REASON_FLUSH, |
596 | false); | ||
597 | } | ||
598 | |||
599 | void ieee80211_stop_vif_queues(struct ieee80211_local *local, | ||
600 | struct ieee80211_sub_if_data *sdata, | ||
601 | enum queue_stop_reason reason) | ||
602 | { | ||
603 | ieee80211_stop_queues_by_reason(&local->hw, | ||
604 | ieee80211_get_vif_queues(local, sdata), | ||
605 | reason, true); | ||
606 | } | ||
607 | |||
608 | void ieee80211_wake_vif_queues(struct ieee80211_local *local, | ||
609 | struct ieee80211_sub_if_data *sdata, | ||
610 | enum queue_stop_reason reason) | ||
611 | { | ||
612 | ieee80211_wake_queues_by_reason(&local->hw, | ||
613 | ieee80211_get_vif_queues(local, sdata), | ||
614 | reason, true); | ||
561 | } | 615 | } |
562 | 616 | ||
563 | static void __iterate_active_interfaces(struct ieee80211_local *local, | 617 | static void __iterate_active_interfaces(struct ieee80211_local *local, |
@@ -1166,14 +1220,17 @@ void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1166 | } | 1220 | } |
1167 | } | 1221 | } |
1168 | 1222 | ||
1169 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | 1223 | static int ieee80211_build_preq_ies_band(struct ieee80211_local *local, |
1170 | size_t buffer_len, const u8 *ie, size_t ie_len, | 1224 | u8 *buffer, size_t buffer_len, |
1171 | enum ieee80211_band band, u32 rate_mask, | 1225 | const u8 *ie, size_t ie_len, |
1172 | struct cfg80211_chan_def *chandef) | 1226 | enum ieee80211_band band, |
1227 | u32 rate_mask, | ||
1228 | struct cfg80211_chan_def *chandef, | ||
1229 | size_t *offset) | ||
1173 | { | 1230 | { |
1174 | struct ieee80211_supported_band *sband; | 1231 | struct ieee80211_supported_band *sband; |
1175 | u8 *pos = buffer, *end = buffer + buffer_len; | 1232 | u8 *pos = buffer, *end = buffer + buffer_len; |
1176 | size_t offset = 0, noffset; | 1233 | size_t noffset; |
1177 | int supp_rates_len, i; | 1234 | int supp_rates_len, i; |
1178 | u8 rates[32]; | 1235 | u8 rates[32]; |
1179 | int num_rates; | 1236 | int num_rates; |
@@ -1181,6 +1238,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1181 | int shift; | 1238 | int shift; |
1182 | u32 rate_flags; | 1239 | u32 rate_flags; |
1183 | 1240 | ||
1241 | *offset = 0; | ||
1242 | |||
1184 | sband = local->hw.wiphy->bands[band]; | 1243 | sband = local->hw.wiphy->bands[band]; |
1185 | if (WARN_ON_ONCE(!sband)) | 1244 | if (WARN_ON_ONCE(!sband)) |
1186 | return 0; | 1245 | return 0; |
@@ -1219,12 +1278,12 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1219 | noffset = ieee80211_ie_split(ie, ie_len, | 1278 | noffset = ieee80211_ie_split(ie, ie_len, |
1220 | before_extrates, | 1279 | before_extrates, |
1221 | ARRAY_SIZE(before_extrates), | 1280 | ARRAY_SIZE(before_extrates), |
1222 | offset); | 1281 | *offset); |
1223 | if (end - pos < noffset - offset) | 1282 | if (end - pos < noffset - *offset) |
1224 | goto out_err; | 1283 | goto out_err; |
1225 | memcpy(pos, ie + offset, noffset - offset); | 1284 | memcpy(pos, ie + *offset, noffset - *offset); |
1226 | pos += noffset - offset; | 1285 | pos += noffset - *offset; |
1227 | offset = noffset; | 1286 | *offset = noffset; |
1228 | } | 1287 | } |
1229 | 1288 | ||
1230 | ext_rates_len = num_rates - supp_rates_len; | 1289 | ext_rates_len = num_rates - supp_rates_len; |
@@ -1258,12 +1317,12 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1258 | }; | 1317 | }; |
1259 | noffset = ieee80211_ie_split(ie, ie_len, | 1318 | noffset = ieee80211_ie_split(ie, ie_len, |
1260 | before_ht, ARRAY_SIZE(before_ht), | 1319 | before_ht, ARRAY_SIZE(before_ht), |
1261 | offset); | 1320 | *offset); |
1262 | if (end - pos < noffset - offset) | 1321 | if (end - pos < noffset - *offset) |
1263 | goto out_err; | 1322 | goto out_err; |
1264 | memcpy(pos, ie + offset, noffset - offset); | 1323 | memcpy(pos, ie + *offset, noffset - *offset); |
1265 | pos += noffset - offset; | 1324 | pos += noffset - *offset; |
1266 | offset = noffset; | 1325 | *offset = noffset; |
1267 | } | 1326 | } |
1268 | 1327 | ||
1269 | if (sband->ht_cap.ht_supported) { | 1328 | if (sband->ht_cap.ht_supported) { |
@@ -1298,12 +1357,12 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1298 | }; | 1357 | }; |
1299 | noffset = ieee80211_ie_split(ie, ie_len, | 1358 | noffset = ieee80211_ie_split(ie, ie_len, |
1300 | before_vht, ARRAY_SIZE(before_vht), | 1359 | before_vht, ARRAY_SIZE(before_vht), |
1301 | offset); | 1360 | *offset); |
1302 | if (end - pos < noffset - offset) | 1361 | if (end - pos < noffset - *offset) |
1303 | goto out_err; | 1362 | goto out_err; |
1304 | memcpy(pos, ie + offset, noffset - offset); | 1363 | memcpy(pos, ie + *offset, noffset - *offset); |
1305 | pos += noffset - offset; | 1364 | pos += noffset - *offset; |
1306 | offset = noffset; | 1365 | *offset = noffset; |
1307 | } | 1366 | } |
1308 | 1367 | ||
1309 | if (sband->vht_cap.vht_supported) { | 1368 | if (sband->vht_cap.vht_supported) { |
@@ -1313,21 +1372,54 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
1313 | sband->vht_cap.cap); | 1372 | sband->vht_cap.cap); |
1314 | } | 1373 | } |
1315 | 1374 | ||
1316 | /* add any remaining custom IEs */ | ||
1317 | if (ie && ie_len) { | ||
1318 | noffset = ie_len; | ||
1319 | if (end - pos < noffset - offset) | ||
1320 | goto out_err; | ||
1321 | memcpy(pos, ie + offset, noffset - offset); | ||
1322 | pos += noffset - offset; | ||
1323 | } | ||
1324 | |||
1325 | return pos - buffer; | 1375 | return pos - buffer; |
1326 | out_err: | 1376 | out_err: |
1327 | WARN_ONCE(1, "not enough space for preq IEs\n"); | 1377 | WARN_ONCE(1, "not enough space for preq IEs\n"); |
1328 | return pos - buffer; | 1378 | return pos - buffer; |
1329 | } | 1379 | } |
1330 | 1380 | ||
1381 | int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | ||
1382 | size_t buffer_len, | ||
1383 | struct ieee80211_scan_ies *ie_desc, | ||
1384 | const u8 *ie, size_t ie_len, | ||
1385 | u8 bands_used, u32 *rate_masks, | ||
1386 | struct cfg80211_chan_def *chandef) | ||
1387 | { | ||
1388 | size_t pos = 0, old_pos = 0, custom_ie_offset = 0; | ||
1389 | int i; | ||
1390 | |||
1391 | memset(ie_desc, 0, sizeof(*ie_desc)); | ||
1392 | |||
1393 | for (i = 0; i < IEEE80211_NUM_BANDS; i++) { | ||
1394 | if (bands_used & BIT(i)) { | ||
1395 | pos += ieee80211_build_preq_ies_band(local, | ||
1396 | buffer + pos, | ||
1397 | buffer_len - pos, | ||
1398 | ie, ie_len, i, | ||
1399 | rate_masks[i], | ||
1400 | chandef, | ||
1401 | &custom_ie_offset); | ||
1402 | ie_desc->ies[i] = buffer + old_pos; | ||
1403 | ie_desc->len[i] = pos - old_pos; | ||
1404 | old_pos = pos; | ||
1405 | } | ||
1406 | } | ||
1407 | |||
1408 | /* add any remaining custom IEs */ | ||
1409 | if (ie && ie_len) { | ||
1410 | if (WARN_ONCE(buffer_len - pos < ie_len - custom_ie_offset, | ||
1411 | "not enough space for preq custom IEs\n")) | ||
1412 | return pos; | ||
1413 | memcpy(buffer + pos, ie + custom_ie_offset, | ||
1414 | ie_len - custom_ie_offset); | ||
1415 | ie_desc->common_ies = buffer + pos; | ||
1416 | ie_desc->common_ie_len = ie_len - custom_ie_offset; | ||
1417 | pos += ie_len - custom_ie_offset; | ||
1418 | } | ||
1419 | |||
1420 | return pos; | ||
1421 | }; | ||
1422 | |||
1331 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | 1423 | struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, |
1332 | u8 *dst, u32 ratemask, | 1424 | u8 *dst, u32 ratemask, |
1333 | struct ieee80211_channel *chan, | 1425 | struct ieee80211_channel *chan, |
@@ -1340,6 +1432,8 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1340 | struct sk_buff *skb; | 1432 | struct sk_buff *skb; |
1341 | struct ieee80211_mgmt *mgmt; | 1433 | struct ieee80211_mgmt *mgmt; |
1342 | int ies_len; | 1434 | int ies_len; |
1435 | u32 rate_masks[IEEE80211_NUM_BANDS] = {}; | ||
1436 | struct ieee80211_scan_ies dummy_ie_desc; | ||
1343 | 1437 | ||
1344 | /* | 1438 | /* |
1345 | * Do not send DS Channel parameter for directed probe requests | 1439 | * Do not send DS Channel parameter for directed probe requests |
@@ -1357,10 +1451,11 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1357 | if (!skb) | 1451 | if (!skb) |
1358 | return NULL; | 1452 | return NULL; |
1359 | 1453 | ||
1454 | rate_masks[chan->band] = ratemask; | ||
1360 | ies_len = ieee80211_build_preq_ies(local, skb_tail_pointer(skb), | 1455 | ies_len = ieee80211_build_preq_ies(local, skb_tail_pointer(skb), |
1361 | skb_tailroom(skb), | 1456 | skb_tailroom(skb), &dummy_ie_desc, |
1362 | ie, ie_len, chan->band, | 1457 | ie, ie_len, BIT(chan->band), |
1363 | ratemask, &chandef); | 1458 | rate_masks, &chandef); |
1364 | skb_put(skb, ies_len); | 1459 | skb_put(skb, ies_len); |
1365 | 1460 | ||
1366 | if (dst) { | 1461 | if (dst) { |
@@ -1604,7 +1699,9 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1604 | if (local->use_chanctx) { | 1699 | if (local->use_chanctx) { |
1605 | mutex_lock(&local->chanctx_mtx); | 1700 | mutex_lock(&local->chanctx_mtx); |
1606 | list_for_each_entry(ctx, &local->chanctx_list, list) | 1701 | list_for_each_entry(ctx, &local->chanctx_list, list) |
1607 | WARN_ON(drv_add_chanctx(local, ctx)); | 1702 | if (ctx->replace_state != |
1703 | IEEE80211_CHANCTX_REPLACES_OTHER) | ||
1704 | WARN_ON(drv_add_chanctx(local, ctx)); | ||
1608 | mutex_unlock(&local->chanctx_mtx); | 1705 | mutex_unlock(&local->chanctx_mtx); |
1609 | 1706 | ||
1610 | list_for_each_entry(sdata, &local->interfaces, list) { | 1707 | list_for_each_entry(sdata, &local->interfaces, list) { |
@@ -1798,7 +1895,8 @@ int ieee80211_reconfig(struct ieee80211_local *local) | |||
1798 | } | 1895 | } |
1799 | 1896 | ||
1800 | ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP, | 1897 | ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP, |
1801 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | 1898 | IEEE80211_QUEUE_STOP_REASON_SUSPEND, |
1899 | false); | ||
1802 | 1900 | ||
1803 | /* | 1901 | /* |
1804 | * Reconfigure sched scan if it was interrupted by FW restart or | 1902 | * Reconfigure sched scan if it was interrupted by FW restart or |
@@ -2836,6 +2934,35 @@ void ieee80211_recalc_dtim(struct ieee80211_local *local, | |||
2836 | ps->dtim_count = dtim_count; | 2934 | ps->dtim_count = dtim_count; |
2837 | } | 2935 | } |
2838 | 2936 | ||
2937 | static u8 ieee80211_chanctx_radar_detect(struct ieee80211_local *local, | ||
2938 | struct ieee80211_chanctx *ctx) | ||
2939 | { | ||
2940 | struct ieee80211_sub_if_data *sdata; | ||
2941 | u8 radar_detect = 0; | ||
2942 | |||
2943 | lockdep_assert_held(&local->chanctx_mtx); | ||
2944 | |||
2945 | if (WARN_ON(ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED)) | ||
2946 | return 0; | ||
2947 | |||
2948 | list_for_each_entry(sdata, &ctx->reserved_vifs, reserved_chanctx_list) | ||
2949 | if (sdata->reserved_radar_required) | ||
2950 | radar_detect |= BIT(sdata->reserved_chandef.width); | ||
2951 | |||
2952 | /* | ||
2953 | * An in-place reservation context should not have any assigned vifs | ||
2954 | * until it replaces the other context. | ||
2955 | */ | ||
2956 | WARN_ON(ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER && | ||
2957 | !list_empty(&ctx->assigned_vifs)); | ||
2958 | |||
2959 | list_for_each_entry(sdata, &ctx->assigned_vifs, assigned_chanctx_list) | ||
2960 | if (sdata->radar_required) | ||
2961 | radar_detect |= BIT(sdata->vif.bss_conf.chandef.width); | ||
2962 | |||
2963 | return radar_detect; | ||
2964 | } | ||
2965 | |||
2839 | int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata, | 2966 | int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata, |
2840 | const struct cfg80211_chan_def *chandef, | 2967 | const struct cfg80211_chan_def *chandef, |
2841 | enum ieee80211_chanctx_mode chanmode, | 2968 | enum ieee80211_chanctx_mode chanmode, |
@@ -2877,8 +3004,9 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata, | |||
2877 | num[iftype] = 1; | 3004 | num[iftype] = 1; |
2878 | 3005 | ||
2879 | list_for_each_entry(ctx, &local->chanctx_list, list) { | 3006 | list_for_each_entry(ctx, &local->chanctx_list, list) { |
2880 | if (ctx->conf.radar_enabled) | 3007 | if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED) |
2881 | radar_detect |= BIT(ctx->conf.def.width); | 3008 | continue; |
3009 | radar_detect |= ieee80211_chanctx_radar_detect(local, ctx); | ||
2882 | if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) { | 3010 | if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) { |
2883 | num_different_channels++; | 3011 | num_different_channels++; |
2884 | continue; | 3012 | continue; |
@@ -2935,10 +3063,12 @@ int ieee80211_max_num_channels(struct ieee80211_local *local) | |||
2935 | lockdep_assert_held(&local->chanctx_mtx); | 3063 | lockdep_assert_held(&local->chanctx_mtx); |
2936 | 3064 | ||
2937 | list_for_each_entry(ctx, &local->chanctx_list, list) { | 3065 | list_for_each_entry(ctx, &local->chanctx_list, list) { |
3066 | if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED) | ||
3067 | continue; | ||
3068 | |||
2938 | num_different_channels++; | 3069 | num_different_channels++; |
2939 | 3070 | ||
2940 | if (ctx->conf.radar_enabled) | 3071 | radar_detect |= ieee80211_chanctx_radar_detect(local, ctx); |
2941 | radar_detect |= BIT(ctx->conf.def.width); | ||
2942 | } | 3072 | } |
2943 | 3073 | ||
2944 | list_for_each_entry_rcu(sdata, &local->interfaces, list) | 3074 | list_for_each_entry_rcu(sdata, &local->interfaces, list) |
@@ -2953,3 +3083,18 @@ int ieee80211_max_num_channels(struct ieee80211_local *local) | |||
2953 | 3083 | ||
2954 | return max_num_different_channels; | 3084 | return max_num_different_channels; |
2955 | } | 3085 | } |
3086 | |||
3087 | u8 *ieee80211_add_wmm_info_ie(u8 *buf, u8 qosinfo) | ||
3088 | { | ||
3089 | *buf++ = WLAN_EID_VENDOR_SPECIFIC; | ||
3090 | *buf++ = 7; /* len */ | ||
3091 | *buf++ = 0x00; /* Microsoft OUI 00:50:F2 */ | ||
3092 | *buf++ = 0x50; | ||
3093 | *buf++ = 0xf2; | ||
3094 | *buf++ = 2; /* WME */ | ||
3095 | *buf++ = 0; /* WME info */ | ||
3096 | *buf++ = 1; /* WME ver */ | ||
3097 | *buf++ = qosinfo; /* U-APSD no in use */ | ||
3098 | |||
3099 | return buf; | ||
3100 | } | ||
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c index 9265adfdabfc..671ce0d27a80 100644 --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c | |||
@@ -129,6 +129,10 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, | |||
129 | if (!vht_cap_ie || !sband->vht_cap.vht_supported) | 129 | if (!vht_cap_ie || !sband->vht_cap.vht_supported) |
130 | return; | 130 | return; |
131 | 131 | ||
132 | /* don't support VHT for TDLS peers for now */ | ||
133 | if (test_sta_flag(sta, WLAN_STA_TDLS_PEER)) | ||
134 | return; | ||
135 | |||
132 | /* | 136 | /* |
133 | * A VHT STA must support 40 MHz, but if we verify that here | 137 | * A VHT STA must support 40 MHz, but if we verify that here |
134 | * then we break a few things - some APs (e.g. Netgear R6300v2 | 138 | * then we break a few things - some APs (e.g. Netgear R6300v2 |
diff --git a/net/mac80211/wep.c b/net/mac80211/wep.c index 6ee2b5863572..9181fb6d6437 100644 --- a/net/mac80211/wep.c +++ b/net/mac80211/wep.c | |||
@@ -271,22 +271,6 @@ static int ieee80211_wep_decrypt(struct ieee80211_local *local, | |||
271 | return ret; | 271 | return ret; |
272 | } | 272 | } |
273 | 273 | ||
274 | |||
275 | static bool ieee80211_wep_is_weak_iv(struct sk_buff *skb, | ||
276 | struct ieee80211_key *key) | ||
277 | { | ||
278 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
279 | unsigned int hdrlen; | ||
280 | u8 *ivpos; | ||
281 | u32 iv; | ||
282 | |||
283 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | ||
284 | ivpos = skb->data + hdrlen; | ||
285 | iv = (ivpos[0] << 16) | (ivpos[1] << 8) | ivpos[2]; | ||
286 | |||
287 | return ieee80211_wep_weak_iv(iv, key->conf.keylen); | ||
288 | } | ||
289 | |||
290 | ieee80211_rx_result | 274 | ieee80211_rx_result |
291 | ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx) | 275 | ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx) |
292 | { | 276 | { |
@@ -301,16 +285,12 @@ ieee80211_crypto_wep_decrypt(struct ieee80211_rx_data *rx) | |||
301 | if (!(status->flag & RX_FLAG_DECRYPTED)) { | 285 | if (!(status->flag & RX_FLAG_DECRYPTED)) { |
302 | if (skb_linearize(rx->skb)) | 286 | if (skb_linearize(rx->skb)) |
303 | return RX_DROP_UNUSABLE; | 287 | return RX_DROP_UNUSABLE; |
304 | if (rx->sta && ieee80211_wep_is_weak_iv(rx->skb, rx->key)) | ||
305 | rx->sta->wep_weak_iv_count++; | ||
306 | if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key)) | 288 | if (ieee80211_wep_decrypt(rx->local, rx->skb, rx->key)) |
307 | return RX_DROP_UNUSABLE; | 289 | return RX_DROP_UNUSABLE; |
308 | } else if (!(status->flag & RX_FLAG_IV_STRIPPED)) { | 290 | } else if (!(status->flag & RX_FLAG_IV_STRIPPED)) { |
309 | if (!pskb_may_pull(rx->skb, ieee80211_hdrlen(fc) + | 291 | if (!pskb_may_pull(rx->skb, ieee80211_hdrlen(fc) + |
310 | IEEE80211_WEP_IV_LEN)) | 292 | IEEE80211_WEP_IV_LEN)) |
311 | return RX_DROP_UNUSABLE; | 293 | return RX_DROP_UNUSABLE; |
312 | if (rx->sta && ieee80211_wep_is_weak_iv(rx->skb, rx->key)) | ||
313 | rx->sta->wep_weak_iv_count++; | ||
314 | ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key); | 294 | ieee80211_wep_remove_iv(rx->local, rx->skb, rx->key); |
315 | /* remove ICV */ | 295 | /* remove ICV */ |
316 | if (pskb_trim(rx->skb, rx->skb->len - IEEE80211_WEP_ICV_LEN)) | 296 | if (pskb_trim(rx->skb, rx->skb->len - IEEE80211_WEP_ICV_LEN)) |
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 9b3dcc201145..f7d4ca4c46e0 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
@@ -811,7 +811,7 @@ ieee80211_crypto_hw_encrypt(struct ieee80211_tx_data *tx) | |||
811 | ieee80211_rx_result | 811 | ieee80211_rx_result |
812 | ieee80211_crypto_hw_decrypt(struct ieee80211_rx_data *rx) | 812 | ieee80211_crypto_hw_decrypt(struct ieee80211_rx_data *rx) |
813 | { | 813 | { |
814 | if (rx->sta->cipher_scheme) | 814 | if (rx->sta && rx->sta->cipher_scheme) |
815 | return ieee80211_crypto_cs_decrypt(rx); | 815 | return ieee80211_crypto_cs_decrypt(rx); |
816 | 816 | ||
817 | return RX_DROP_UNUSABLE; | 817 | return RX_DROP_UNUSABLE; |
diff --git a/net/mac802154/ieee802154_dev.c b/net/mac802154/ieee802154_dev.c index 2cf66d885e68..b36b2b996578 100644 --- a/net/mac802154/ieee802154_dev.c +++ b/net/mac802154/ieee802154_dev.c | |||
@@ -143,6 +143,7 @@ static void | |||
143 | mac802154_del_iface(struct wpan_phy *phy, struct net_device *dev) | 143 | mac802154_del_iface(struct wpan_phy *phy, struct net_device *dev) |
144 | { | 144 | { |
145 | struct mac802154_sub_if_data *sdata; | 145 | struct mac802154_sub_if_data *sdata; |
146 | |||
146 | ASSERT_RTNL(); | 147 | ASSERT_RTNL(); |
147 | 148 | ||
148 | sdata = netdev_priv(dev); | 149 | sdata = netdev_priv(dev); |
@@ -166,11 +167,13 @@ mac802154_add_iface(struct wpan_phy *phy, const char *name, int type) | |||
166 | switch (type) { | 167 | switch (type) { |
167 | case IEEE802154_DEV_MONITOR: | 168 | case IEEE802154_DEV_MONITOR: |
168 | dev = alloc_netdev(sizeof(struct mac802154_sub_if_data), | 169 | dev = alloc_netdev(sizeof(struct mac802154_sub_if_data), |
169 | name, mac802154_monitor_setup); | 170 | name, NET_NAME_UNKNOWN, |
171 | mac802154_monitor_setup); | ||
170 | break; | 172 | break; |
171 | case IEEE802154_DEV_WPAN: | 173 | case IEEE802154_DEV_WPAN: |
172 | dev = alloc_netdev(sizeof(struct mac802154_sub_if_data), | 174 | dev = alloc_netdev(sizeof(struct mac802154_sub_if_data), |
173 | name, mac802154_wpan_setup); | 175 | name, NET_NAME_UNKNOWN, |
176 | mac802154_wpan_setup); | ||
174 | break; | 177 | break; |
175 | default: | 178 | default: |
176 | dev = NULL; | 179 | dev = NULL; |
@@ -276,7 +279,8 @@ ieee802154_alloc_device(size_t priv_data_len, struct ieee802154_ops *ops) | |||
276 | } | 279 | } |
277 | 280 | ||
278 | priv = wpan_phy_priv(phy); | 281 | priv = wpan_phy_priv(phy); |
279 | priv->hw.phy = priv->phy = phy; | 282 | priv->phy = phy; |
283 | priv->hw.phy = priv->phy; | ||
280 | priv->hw.priv = (char *)priv + ALIGN(sizeof(*priv), NETDEV_ALIGN); | 284 | priv->hw.priv = (char *)priv + ALIGN(sizeof(*priv), NETDEV_ALIGN); |
281 | priv->ops = ops; | 285 | priv->ops = ops; |
282 | 286 | ||
@@ -302,29 +306,61 @@ EXPORT_SYMBOL(ieee802154_free_device); | |||
302 | int ieee802154_register_device(struct ieee802154_dev *dev) | 306 | int ieee802154_register_device(struct ieee802154_dev *dev) |
303 | { | 307 | { |
304 | struct mac802154_priv *priv = mac802154_to_priv(dev); | 308 | struct mac802154_priv *priv = mac802154_to_priv(dev); |
305 | int rc = -ENOMEM; | 309 | int rc = -ENOSYS; |
310 | |||
311 | if (dev->flags & IEEE802154_HW_TXPOWER) { | ||
312 | if (!priv->ops->set_txpower) | ||
313 | goto out; | ||
314 | |||
315 | priv->phy->set_txpower = mac802154_set_txpower; | ||
316 | } | ||
317 | |||
318 | if (dev->flags & IEEE802154_HW_LBT) { | ||
319 | if (!priv->ops->set_lbt) | ||
320 | goto out; | ||
321 | |||
322 | priv->phy->set_lbt = mac802154_set_lbt; | ||
323 | } | ||
324 | |||
325 | if (dev->flags & IEEE802154_HW_CCA_MODE) { | ||
326 | if (!priv->ops->set_cca_mode) | ||
327 | goto out; | ||
328 | |||
329 | priv->phy->set_cca_mode = mac802154_set_cca_mode; | ||
330 | } | ||
331 | |||
332 | if (dev->flags & IEEE802154_HW_CCA_ED_LEVEL) { | ||
333 | if (!priv->ops->set_cca_ed_level) | ||
334 | goto out; | ||
335 | |||
336 | priv->phy->set_cca_ed_level = mac802154_set_cca_ed_level; | ||
337 | } | ||
338 | |||
339 | if (dev->flags & IEEE802154_HW_CSMA_PARAMS) { | ||
340 | if (!priv->ops->set_csma_params) | ||
341 | goto out; | ||
342 | |||
343 | priv->phy->set_csma_params = mac802154_set_csma_params; | ||
344 | } | ||
345 | |||
346 | if (dev->flags & IEEE802154_HW_FRAME_RETRIES) { | ||
347 | if (!priv->ops->set_frame_retries) | ||
348 | goto out; | ||
349 | |||
350 | priv->phy->set_frame_retries = mac802154_set_frame_retries; | ||
351 | } | ||
306 | 352 | ||
307 | priv->dev_workqueue = | 353 | priv->dev_workqueue = |
308 | create_singlethread_workqueue(wpan_phy_name(priv->phy)); | 354 | create_singlethread_workqueue(wpan_phy_name(priv->phy)); |
309 | if (!priv->dev_workqueue) | 355 | if (!priv->dev_workqueue) { |
356 | rc = -ENOMEM; | ||
310 | goto out; | 357 | goto out; |
358 | } | ||
311 | 359 | ||
312 | wpan_phy_set_dev(priv->phy, priv->hw.parent); | 360 | wpan_phy_set_dev(priv->phy, priv->hw.parent); |
313 | 361 | ||
314 | priv->phy->add_iface = mac802154_add_iface; | 362 | priv->phy->add_iface = mac802154_add_iface; |
315 | priv->phy->del_iface = mac802154_del_iface; | 363 | priv->phy->del_iface = mac802154_del_iface; |
316 | if (priv->ops->set_txpower) | ||
317 | priv->phy->set_txpower = mac802154_set_txpower; | ||
318 | if (priv->ops->set_lbt) | ||
319 | priv->phy->set_lbt = mac802154_set_lbt; | ||
320 | if (priv->ops->set_cca_mode) | ||
321 | priv->phy->set_cca_mode = mac802154_set_cca_mode; | ||
322 | if (priv->ops->set_cca_ed_level) | ||
323 | priv->phy->set_cca_ed_level = mac802154_set_cca_ed_level; | ||
324 | if (priv->ops->set_csma_params) | ||
325 | priv->phy->set_csma_params = mac802154_set_csma_params; | ||
326 | if (priv->ops->set_frame_retries) | ||
327 | priv->phy->set_frame_retries = mac802154_set_frame_retries; | ||
328 | 364 | ||
329 | rc = wpan_phy_register(priv->phy); | 365 | rc = wpan_phy_register(priv->phy); |
330 | if (rc < 0) | 366 | if (rc < 0) |
diff --git a/net/mac802154/llsec.c b/net/mac802154/llsec.c index 1456f73b02b9..457058142098 100644 --- a/net/mac802154/llsec.c +++ b/net/mac802154/llsec.c | |||
@@ -538,6 +538,7 @@ static int llsec_recover_addr(struct mac802154_llsec *sec, | |||
538 | struct ieee802154_addr *addr) | 538 | struct ieee802154_addr *addr) |
539 | { | 539 | { |
540 | __le16 caddr = sec->params.coord_shortaddr; | 540 | __le16 caddr = sec->params.coord_shortaddr; |
541 | |||
541 | addr->pan_id = sec->params.pan_id; | 542 | addr->pan_id = sec->params.pan_id; |
542 | 543 | ||
543 | if (caddr == cpu_to_le16(IEEE802154_ADDR_BROADCAST)) { | 544 | if (caddr == cpu_to_le16(IEEE802154_ADDR_BROADCAST)) { |
diff --git a/net/mac802154/mib.c b/net/mac802154/mib.c index 15aa2f2b03a7..868a040fd422 100644 --- a/net/mac802154/mib.c +++ b/net/mac802154/mib.c | |||
@@ -175,9 +175,9 @@ static void phy_chan_notify(struct work_struct *work) | |||
175 | 175 | ||
176 | mutex_lock(&priv->hw->phy->pib_lock); | 176 | mutex_lock(&priv->hw->phy->pib_lock); |
177 | res = hw->ops->set_channel(&hw->hw, priv->page, priv->chan); | 177 | res = hw->ops->set_channel(&hw->hw, priv->page, priv->chan); |
178 | if (res) | 178 | if (res) { |
179 | pr_debug("set_channel failed\n"); | 179 | pr_debug("set_channel failed\n"); |
180 | else { | 180 | } else { |
181 | priv->hw->phy->current_channel = priv->chan; | 181 | priv->hw->phy->current_channel = priv->chan; |
182 | priv->hw->phy->current_page = priv->page; | 182 | priv->hw->phy->current_page = priv->page; |
183 | } | 183 | } |
@@ -210,8 +210,9 @@ void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan) | |||
210 | INIT_WORK(&work->work, phy_chan_notify); | 210 | INIT_WORK(&work->work, phy_chan_notify); |
211 | work->dev = dev; | 211 | work->dev = dev; |
212 | queue_work(priv->hw->dev_workqueue, &work->work); | 212 | queue_work(priv->hw->dev_workqueue, &work->work); |
213 | } else | 213 | } else { |
214 | mutex_unlock(&priv->hw->phy->pib_lock); | 214 | mutex_unlock(&priv->hw->phy->pib_lock); |
215 | } | ||
215 | } | 216 | } |
216 | 217 | ||
217 | 218 | ||
diff --git a/net/mac802154/tx.c b/net/mac802154/tx.c index 6d1647399d4f..8124353646ae 100644 --- a/net/mac802154/tx.c +++ b/net/mac802154/tx.c | |||
@@ -98,6 +98,7 @@ netdev_tx_t mac802154_tx(struct mac802154_priv *priv, struct sk_buff *skb, | |||
98 | if (!(priv->hw.flags & IEEE802154_HW_OMIT_CKSUM)) { | 98 | if (!(priv->hw.flags & IEEE802154_HW_OMIT_CKSUM)) { |
99 | u16 crc = crc_ccitt(0, skb->data, skb->len); | 99 | u16 crc = crc_ccitt(0, skb->data, skb->len); |
100 | u8 *data = skb_put(skb, 2); | 100 | u8 *data = skb_put(skb, 2); |
101 | |||
101 | data[0] = crc & 0xff; | 102 | data[0] = crc & 0xff; |
102 | data[1] = crc >> 8; | 103 | data[1] = crc >> 8; |
103 | } | 104 | } |
diff --git a/net/mac802154/wpan.c b/net/mac802154/wpan.c index 3c3069fd6971..547838822d5e 100644 --- a/net/mac802154/wpan.c +++ b/net/mac802154/wpan.c | |||
@@ -462,7 +462,10 @@ mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb, | |||
462 | skb->pkt_type = PACKET_OTHERHOST; | 462 | skb->pkt_type = PACKET_OTHERHOST; |
463 | break; | 463 | break; |
464 | default: | 464 | default: |
465 | break; | 465 | spin_unlock_bh(&sdata->mib_lock); |
466 | pr_debug("invalid dest mode\n"); | ||
467 | kfree_skb(skb); | ||
468 | return NET_RX_DROP; | ||
466 | } | 469 | } |
467 | 470 | ||
468 | spin_unlock_bh(&sdata->mib_lock); | 471 | spin_unlock_bh(&sdata->mib_lock); |
@@ -573,6 +576,7 @@ void mac802154_wpans_rx(struct mac802154_priv *priv, struct sk_buff *skb) | |||
573 | ret = mac802154_parse_frame_start(skb, &hdr); | 576 | ret = mac802154_parse_frame_start(skb, &hdr); |
574 | if (ret) { | 577 | if (ret) { |
575 | pr_debug("got invalid frame\n"); | 578 | pr_debug("got invalid frame\n"); |
579 | kfree_skb(skb); | ||
576 | return; | 580 | return; |
577 | } | 581 | } |
578 | 582 | ||
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index e9410d17619d..6d77cce481d5 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
@@ -46,6 +46,9 @@ config NF_CONNTRACK | |||
46 | 46 | ||
47 | To compile it as a module, choose M here. If unsure, say N. | 47 | To compile it as a module, choose M here. If unsure, say N. |
48 | 48 | ||
49 | config NF_LOG_COMMON | ||
50 | tristate | ||
51 | |||
49 | if NF_CONNTRACK | 52 | if NF_CONNTRACK |
50 | 53 | ||
51 | config NF_CONNTRACK_MARK | 54 | config NF_CONNTRACK_MARK |
@@ -496,7 +499,7 @@ config NFT_LIMIT | |||
496 | config NFT_NAT | 499 | config NFT_NAT |
497 | depends on NF_TABLES | 500 | depends on NF_TABLES |
498 | depends on NF_CONNTRACK | 501 | depends on NF_CONNTRACK |
499 | depends on NF_NAT | 502 | select NF_NAT |
500 | tristate "Netfilter nf_tables nat module" | 503 | tristate "Netfilter nf_tables nat module" |
501 | help | 504 | help |
502 | This option adds the "nat" expression that you can use to perform | 505 | This option adds the "nat" expression that you can use to perform |
@@ -744,6 +747,9 @@ config NETFILTER_XT_TARGET_LED | |||
744 | 747 | ||
745 | config NETFILTER_XT_TARGET_LOG | 748 | config NETFILTER_XT_TARGET_LOG |
746 | tristate "LOG target support" | 749 | tristate "LOG target support" |
750 | select NF_LOG_COMMON | ||
751 | select NF_LOG_IPV4 | ||
752 | select NF_LOG_IPV6 if IPV6 | ||
747 | default m if NETFILTER_ADVANCED=n | 753 | default m if NETFILTER_ADVANCED=n |
748 | help | 754 | help |
749 | This option adds a `LOG' target, which allows you to create rules in | 755 | This option adds a `LOG' target, which allows you to create rules in |
@@ -760,6 +766,14 @@ config NETFILTER_XT_TARGET_MARK | |||
760 | (e.g. when running oldconfig). It selects | 766 | (e.g. when running oldconfig). It selects |
761 | CONFIG_NETFILTER_XT_MARK (combined mark/MARK module). | 767 | CONFIG_NETFILTER_XT_MARK (combined mark/MARK module). |
762 | 768 | ||
769 | config NETFILTER_XT_NAT | ||
770 | tristate '"SNAT and DNAT" targets support' | ||
771 | depends on NF_NAT | ||
772 | ---help--- | ||
773 | This option enables the SNAT and DNAT targets. | ||
774 | |||
775 | To compile it as a module, choose M here. If unsure, say N. | ||
776 | |||
763 | config NETFILTER_XT_TARGET_NETMAP | 777 | config NETFILTER_XT_TARGET_NETMAP |
764 | tristate '"NETMAP" target support' | 778 | tristate '"NETMAP" target support' |
765 | depends on NF_NAT | 779 | depends on NF_NAT |
@@ -833,6 +847,7 @@ config NETFILTER_XT_TARGET_TPROXY | |||
833 | tristate '"TPROXY" target transparent proxying support' | 847 | tristate '"TPROXY" target transparent proxying support' |
834 | depends on NETFILTER_XTABLES | 848 | depends on NETFILTER_XTABLES |
835 | depends on NETFILTER_ADVANCED | 849 | depends on NETFILTER_ADVANCED |
850 | depends on (IPV6 || IPV6=n) | ||
836 | depends on IP_NF_MANGLE | 851 | depends on IP_NF_MANGLE |
837 | select NF_DEFRAG_IPV4 | 852 | select NF_DEFRAG_IPV4 |
838 | select NF_DEFRAG_IPV6 if IP6_NF_IPTABLES | 853 | select NF_DEFRAG_IPV6 if IP6_NF_IPTABLES |
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index bffdad774da7..fad5fdba34e5 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile | |||
@@ -47,6 +47,9 @@ obj-$(CONFIG_NF_CONNTRACK_TFTP) += nf_conntrack_tftp.o | |||
47 | nf_nat-y := nf_nat_core.o nf_nat_proto_unknown.o nf_nat_proto_common.o \ | 47 | nf_nat-y := nf_nat_core.o nf_nat_proto_unknown.o nf_nat_proto_common.o \ |
48 | nf_nat_proto_udp.o nf_nat_proto_tcp.o nf_nat_helper.o | 48 | nf_nat_proto_udp.o nf_nat_proto_tcp.o nf_nat_helper.o |
49 | 49 | ||
50 | # generic transport layer logging | ||
51 | obj-$(CONFIG_NF_LOG_COMMON) += nf_log_common.o | ||
52 | |||
50 | obj-$(CONFIG_NF_NAT) += nf_nat.o | 53 | obj-$(CONFIG_NF_NAT) += nf_nat.o |
51 | 54 | ||
52 | # NAT protocols (nf_nat) | 55 | # NAT protocols (nf_nat) |
@@ -92,7 +95,7 @@ obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o | |||
92 | obj-$(CONFIG_NETFILTER_XT_MARK) += xt_mark.o | 95 | obj-$(CONFIG_NETFILTER_XT_MARK) += xt_mark.o |
93 | obj-$(CONFIG_NETFILTER_XT_CONNMARK) += xt_connmark.o | 96 | obj-$(CONFIG_NETFILTER_XT_CONNMARK) += xt_connmark.o |
94 | obj-$(CONFIG_NETFILTER_XT_SET) += xt_set.o | 97 | obj-$(CONFIG_NETFILTER_XT_SET) += xt_set.o |
95 | obj-$(CONFIG_NF_NAT) += xt_nat.o | 98 | obj-$(CONFIG_NETFILTER_XT_NAT) += xt_nat.o |
96 | 99 | ||
97 | # targets | 100 | # targets |
98 | obj-$(CONFIG_NETFILTER_XT_TARGET_AUDIT) += xt_AUDIT.o | 101 | obj-$(CONFIG_NETFILTER_XT_TARGET_AUDIT) += xt_AUDIT.o |
diff --git a/net/netfilter/core.c b/net/netfilter/core.c index 1fbab0cdd302..024a2e25c8a4 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c | |||
@@ -35,11 +35,7 @@ EXPORT_SYMBOL_GPL(nf_ipv6_ops); | |||
35 | 35 | ||
36 | int nf_register_afinfo(const struct nf_afinfo *afinfo) | 36 | int nf_register_afinfo(const struct nf_afinfo *afinfo) |
37 | { | 37 | { |
38 | int err; | 38 | mutex_lock(&afinfo_mutex); |
39 | |||
40 | err = mutex_lock_interruptible(&afinfo_mutex); | ||
41 | if (err < 0) | ||
42 | return err; | ||
43 | RCU_INIT_POINTER(nf_afinfo[afinfo->family], afinfo); | 39 | RCU_INIT_POINTER(nf_afinfo[afinfo->family], afinfo); |
44 | mutex_unlock(&afinfo_mutex); | 40 | mutex_unlock(&afinfo_mutex); |
45 | return 0; | 41 | return 0; |
@@ -58,7 +54,7 @@ EXPORT_SYMBOL_GPL(nf_unregister_afinfo); | |||
58 | struct list_head nf_hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS] __read_mostly; | 54 | struct list_head nf_hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS] __read_mostly; |
59 | EXPORT_SYMBOL(nf_hooks); | 55 | EXPORT_SYMBOL(nf_hooks); |
60 | 56 | ||
61 | #if defined(CONFIG_JUMP_LABEL) | 57 | #ifdef HAVE_JUMP_LABEL |
62 | struct static_key nf_hooks_needed[NFPROTO_NUMPROTO][NF_MAX_HOOKS]; | 58 | struct static_key nf_hooks_needed[NFPROTO_NUMPROTO][NF_MAX_HOOKS]; |
63 | EXPORT_SYMBOL(nf_hooks_needed); | 59 | EXPORT_SYMBOL(nf_hooks_needed); |
64 | #endif | 60 | #endif |
@@ -68,18 +64,15 @@ static DEFINE_MUTEX(nf_hook_mutex); | |||
68 | int nf_register_hook(struct nf_hook_ops *reg) | 64 | int nf_register_hook(struct nf_hook_ops *reg) |
69 | { | 65 | { |
70 | struct nf_hook_ops *elem; | 66 | struct nf_hook_ops *elem; |
71 | int err; | ||
72 | 67 | ||
73 | err = mutex_lock_interruptible(&nf_hook_mutex); | 68 | mutex_lock(&nf_hook_mutex); |
74 | if (err < 0) | ||
75 | return err; | ||
76 | list_for_each_entry(elem, &nf_hooks[reg->pf][reg->hooknum], list) { | 69 | list_for_each_entry(elem, &nf_hooks[reg->pf][reg->hooknum], list) { |
77 | if (reg->priority < elem->priority) | 70 | if (reg->priority < elem->priority) |
78 | break; | 71 | break; |
79 | } | 72 | } |
80 | list_add_rcu(®->list, elem->list.prev); | 73 | list_add_rcu(®->list, elem->list.prev); |
81 | mutex_unlock(&nf_hook_mutex); | 74 | mutex_unlock(&nf_hook_mutex); |
82 | #if defined(CONFIG_JUMP_LABEL) | 75 | #ifdef HAVE_JUMP_LABEL |
83 | static_key_slow_inc(&nf_hooks_needed[reg->pf][reg->hooknum]); | 76 | static_key_slow_inc(&nf_hooks_needed[reg->pf][reg->hooknum]); |
84 | #endif | 77 | #endif |
85 | return 0; | 78 | return 0; |
@@ -91,7 +84,7 @@ void nf_unregister_hook(struct nf_hook_ops *reg) | |||
91 | mutex_lock(&nf_hook_mutex); | 84 | mutex_lock(&nf_hook_mutex); |
92 | list_del_rcu(®->list); | 85 | list_del_rcu(®->list); |
93 | mutex_unlock(&nf_hook_mutex); | 86 | mutex_unlock(&nf_hook_mutex); |
94 | #if defined(CONFIG_JUMP_LABEL) | 87 | #ifdef HAVE_JUMP_LABEL |
95 | static_key_slow_dec(&nf_hooks_needed[reg->pf][reg->hooknum]); | 88 | static_key_slow_dec(&nf_hooks_needed[reg->pf][reg->hooknum]); |
96 | #endif | 89 | #endif |
97 | synchronize_net(); | 90 | synchronize_net(); |
diff --git a/net/netfilter/ipvs/ip_vs_core.c b/net/netfilter/ipvs/ip_vs_core.c index e6836755c45d..5c34e8d42e01 100644 --- a/net/netfilter/ipvs/ip_vs_core.c +++ b/net/netfilter/ipvs/ip_vs_core.c | |||
@@ -1906,7 +1906,7 @@ static struct nf_hook_ops ip_vs_ops[] __read_mostly = { | |||
1906 | { | 1906 | { |
1907 | .hook = ip_vs_local_reply6, | 1907 | .hook = ip_vs_local_reply6, |
1908 | .owner = THIS_MODULE, | 1908 | .owner = THIS_MODULE, |
1909 | .pf = NFPROTO_IPV4, | 1909 | .pf = NFPROTO_IPV6, |
1910 | .hooknum = NF_INET_LOCAL_OUT, | 1910 | .hooknum = NF_INET_LOCAL_OUT, |
1911 | .priority = NF_IP6_PRI_NAT_DST + 1, | 1911 | .priority = NF_IP6_PRI_NAT_DST + 1, |
1912 | }, | 1912 | }, |
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 581a6584ed0c..fd3f444a4f96 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c | |||
@@ -1807,92 +1807,6 @@ static struct ctl_table vs_vars[] = { | |||
1807 | .proc_handler = proc_dointvec, | 1807 | .proc_handler = proc_dointvec, |
1808 | }, | 1808 | }, |
1809 | #endif | 1809 | #endif |
1810 | #if 0 | ||
1811 | { | ||
1812 | .procname = "timeout_established", | ||
1813 | .data = &vs_timeout_table_dos.timeout[IP_VS_S_ESTABLISHED], | ||
1814 | .maxlen = sizeof(int), | ||
1815 | .mode = 0644, | ||
1816 | .proc_handler = proc_dointvec_jiffies, | ||
1817 | }, | ||
1818 | { | ||
1819 | .procname = "timeout_synsent", | ||
1820 | .data = &vs_timeout_table_dos.timeout[IP_VS_S_SYN_SENT], | ||
1821 | .maxlen = sizeof(int), | ||
1822 | .mode = 0644, | ||
1823 | .proc_handler = proc_dointvec_jiffies, | ||
1824 | }, | ||
1825 | { | ||
1826 | .procname = "timeout_synrecv", | ||
1827 | .data = &vs_timeout_table_dos.timeout[IP_VS_S_SYN_RECV], | ||
1828 | .maxlen = sizeof(int), | ||
1829 | .mode = 0644, | ||
1830 | .proc_handler = proc_dointvec_jiffies, | ||
1831 | }, | ||
1832 | { | ||
1833 | .procname = "timeout_finwait", | ||
1834 | .data = &vs_timeout_table_dos.timeout[IP_VS_S_FIN_WAIT], | ||
1835 | .maxlen = sizeof(int), | ||
1836 | .mode = 0644, | ||
1837 | .proc_handler = proc_dointvec_jiffies, | ||
1838 | }, | ||
1839 | { | ||
1840 | .procname = "timeout_timewait", | ||
1841 | .data = &vs_timeout_table_dos.timeout[IP_VS_S_TIME_WAIT], | ||
1842 | .maxlen = sizeof(int), | ||
1843 | .mode = 0644, | ||
1844 | .proc_handler = proc_dointvec_jiffies, | ||
1845 | }, | ||
1846 | { | ||
1847 | .procname = "timeout_close", | ||
1848 | .data = &vs_timeout_table_dos.timeout[IP_VS_S_CLOSE], | ||
1849 | .maxlen = sizeof(int), | ||
1850 | .mode = 0644, | ||
1851 | .proc_handler = proc_dointvec_jiffies, | ||
1852 | }, | ||
1853 | { | ||
1854 | .procname = "timeout_closewait", | ||
1855 | .data = &vs_timeout_table_dos.timeout[IP_VS_S_CLOSE_WAIT], | ||
1856 | .maxlen = sizeof(int), | ||
1857 | .mode = 0644, | ||
1858 | .proc_handler = proc_dointvec_jiffies, | ||
1859 | }, | ||
1860 | { | ||
1861 | .procname = "timeout_lastack", | ||
1862 | .data = &vs_timeout_table_dos.timeout[IP_VS_S_LAST_ACK], | ||
1863 | .maxlen = sizeof(int), | ||
1864 | .mode = 0644, | ||
1865 | .proc_handler = proc_dointvec_jiffies, | ||
1866 | }, | ||
1867 | { | ||
1868 | .procname = "timeout_listen", | ||
1869 | .data = &vs_timeout_table_dos.timeout[IP_VS_S_LISTEN], | ||
1870 | .maxlen = sizeof(int), | ||
1871 | .mode = 0644, | ||
1872 | .proc_handler = proc_dointvec_jiffies, | ||
1873 | }, | ||
1874 | { | ||
1875 | .procname = "timeout_synack", | ||
1876 | .data = &vs_timeout_table_dos.timeout[IP_VS_S_SYNACK], | ||
1877 | .maxlen = sizeof(int), | ||
1878 | .mode = 0644, | ||
1879 | .proc_handler = proc_dointvec_jiffies, | ||
1880 | }, | ||
1881 | { | ||
1882 | .procname = "timeout_udp", | ||
1883 | .data = &vs_timeout_table_dos.timeout[IP_VS_S_UDP], | ||
1884 | .maxlen = sizeof(int), | ||
1885 | .mode = 0644, | ||
1886 | .proc_handler = proc_dointvec_jiffies, | ||
1887 | }, | ||
1888 | { | ||
1889 | .procname = "timeout_icmp", | ||
1890 | .data = &vs_timeout_table_dos.timeout[IP_VS_S_ICMP], | ||
1891 | .maxlen = sizeof(int), | ||
1892 | .mode = 0644, | ||
1893 | .proc_handler = proc_dointvec_jiffies, | ||
1894 | }, | ||
1895 | #endif | ||
1896 | { } | 1810 | { } |
1897 | }; | 1811 | }; |
1898 | 1812 | ||
@@ -2357,10 +2271,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) | |||
2357 | cmd == IP_VS_SO_SET_STOPDAEMON) { | 2271 | cmd == IP_VS_SO_SET_STOPDAEMON) { |
2358 | struct ip_vs_daemon_user *dm = (struct ip_vs_daemon_user *)arg; | 2272 | struct ip_vs_daemon_user *dm = (struct ip_vs_daemon_user *)arg; |
2359 | 2273 | ||
2360 | if (mutex_lock_interruptible(&ipvs->sync_mutex)) { | 2274 | mutex_lock(&ipvs->sync_mutex); |
2361 | ret = -ERESTARTSYS; | ||
2362 | goto out_dec; | ||
2363 | } | ||
2364 | if (cmd == IP_VS_SO_SET_STARTDAEMON) | 2275 | if (cmd == IP_VS_SO_SET_STARTDAEMON) |
2365 | ret = start_sync_thread(net, dm->state, dm->mcast_ifn, | 2276 | ret = start_sync_thread(net, dm->state, dm->mcast_ifn, |
2366 | dm->syncid); | 2277 | dm->syncid); |
@@ -2370,11 +2281,7 @@ do_ip_vs_set_ctl(struct sock *sk, int cmd, void __user *user, unsigned int len) | |||
2370 | goto out_dec; | 2281 | goto out_dec; |
2371 | } | 2282 | } |
2372 | 2283 | ||
2373 | if (mutex_lock_interruptible(&__ip_vs_mutex)) { | 2284 | mutex_lock(&__ip_vs_mutex); |
2374 | ret = -ERESTARTSYS; | ||
2375 | goto out_dec; | ||
2376 | } | ||
2377 | |||
2378 | if (cmd == IP_VS_SO_SET_FLUSH) { | 2285 | if (cmd == IP_VS_SO_SET_FLUSH) { |
2379 | /* Flush the virtual service */ | 2286 | /* Flush the virtual service */ |
2380 | ret = ip_vs_flush(net, false); | 2287 | ret = ip_vs_flush(net, false); |
@@ -2659,9 +2566,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
2659 | struct ip_vs_daemon_user d[2]; | 2566 | struct ip_vs_daemon_user d[2]; |
2660 | 2567 | ||
2661 | memset(&d, 0, sizeof(d)); | 2568 | memset(&d, 0, sizeof(d)); |
2662 | if (mutex_lock_interruptible(&ipvs->sync_mutex)) | 2569 | mutex_lock(&ipvs->sync_mutex); |
2663 | return -ERESTARTSYS; | ||
2664 | |||
2665 | if (ipvs->sync_state & IP_VS_STATE_MASTER) { | 2570 | if (ipvs->sync_state & IP_VS_STATE_MASTER) { |
2666 | d[0].state = IP_VS_STATE_MASTER; | 2571 | d[0].state = IP_VS_STATE_MASTER; |
2667 | strlcpy(d[0].mcast_ifn, ipvs->master_mcast_ifn, | 2572 | strlcpy(d[0].mcast_ifn, ipvs->master_mcast_ifn, |
@@ -2680,9 +2585,7 @@ do_ip_vs_get_ctl(struct sock *sk, int cmd, void __user *user, int *len) | |||
2680 | return ret; | 2585 | return ret; |
2681 | } | 2586 | } |
2682 | 2587 | ||
2683 | if (mutex_lock_interruptible(&__ip_vs_mutex)) | 2588 | mutex_lock(&__ip_vs_mutex); |
2684 | return -ERESTARTSYS; | ||
2685 | |||
2686 | switch (cmd) { | 2589 | switch (cmd) { |
2687 | case IP_VS_SO_GET_VERSION: | 2590 | case IP_VS_SO_GET_VERSION: |
2688 | { | 2591 | { |
diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c index db801263ee9f..eadffb29dec0 100644 --- a/net/netfilter/ipvs/ip_vs_sync.c +++ b/net/netfilter/ipvs/ip_vs_sync.c | |||
@@ -886,8 +886,7 @@ static void ip_vs_proc_conn(struct net *net, struct ip_vs_conn_param *param, | |||
886 | cp = ip_vs_conn_new(param, daddr, dport, flags, dest, fwmark); | 886 | cp = ip_vs_conn_new(param, daddr, dport, flags, dest, fwmark); |
887 | rcu_read_unlock(); | 887 | rcu_read_unlock(); |
888 | if (!cp) { | 888 | if (!cp) { |
889 | if (param->pe_data) | 889 | kfree(param->pe_data); |
890 | kfree(param->pe_data); | ||
891 | IP_VS_DBG(2, "BACKUP, add new conn. failed\n"); | 890 | IP_VS_DBG(2, "BACKUP, add new conn. failed\n"); |
892 | return; | 891 | return; |
893 | } | 892 | } |
diff --git a/net/netfilter/ipvs/ip_vs_xmit.c b/net/netfilter/ipvs/ip_vs_xmit.c index 73ba1cc7a88d..56896a412bce 100644 --- a/net/netfilter/ipvs/ip_vs_xmit.c +++ b/net/netfilter/ipvs/ip_vs_xmit.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <net/route.h> /* for ip_route_output */ | 38 | #include <net/route.h> /* for ip_route_output */ |
39 | #include <net/ipv6.h> | 39 | #include <net/ipv6.h> |
40 | #include <net/ip6_route.h> | 40 | #include <net/ip6_route.h> |
41 | #include <net/ip_tunnels.h> | ||
41 | #include <net/addrconf.h> | 42 | #include <net/addrconf.h> |
42 | #include <linux/icmpv6.h> | 43 | #include <linux/icmpv6.h> |
43 | #include <linux/netfilter.h> | 44 | #include <linux/netfilter.h> |
@@ -862,11 +863,15 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
862 | old_iph = ip_hdr(skb); | 863 | old_iph = ip_hdr(skb); |
863 | } | 864 | } |
864 | 865 | ||
865 | skb->transport_header = skb->network_header; | ||
866 | |||
867 | /* fix old IP header checksum */ | 866 | /* fix old IP header checksum */ |
868 | ip_send_check(old_iph); | 867 | ip_send_check(old_iph); |
869 | 868 | ||
869 | skb = iptunnel_handle_offloads(skb, false, SKB_GSO_IPIP); | ||
870 | if (IS_ERR(skb)) | ||
871 | goto tx_error; | ||
872 | |||
873 | skb->transport_header = skb->network_header; | ||
874 | |||
870 | skb_push(skb, sizeof(struct iphdr)); | 875 | skb_push(skb, sizeof(struct iphdr)); |
871 | skb_reset_network_header(skb); | 876 | skb_reset_network_header(skb); |
872 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); | 877 | memset(&(IPCB(skb)->opt), 0, sizeof(IPCB(skb)->opt)); |
@@ -900,7 +905,8 @@ ip_vs_tunnel_xmit(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
900 | return NF_STOLEN; | 905 | return NF_STOLEN; |
901 | 906 | ||
902 | tx_error: | 907 | tx_error: |
903 | kfree_skb(skb); | 908 | if (!IS_ERR(skb)) |
909 | kfree_skb(skb); | ||
904 | rcu_read_unlock(); | 910 | rcu_read_unlock(); |
905 | LeaveFunction(10); | 911 | LeaveFunction(10); |
906 | return NF_STOLEN; | 912 | return NF_STOLEN; |
@@ -953,6 +959,11 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
953 | old_iph = ipv6_hdr(skb); | 959 | old_iph = ipv6_hdr(skb); |
954 | } | 960 | } |
955 | 961 | ||
962 | /* GSO: we need to provide proper SKB_GSO_ value for IPv6 */ | ||
963 | skb = iptunnel_handle_offloads(skb, false, 0); /* SKB_GSO_SIT/IPV6 */ | ||
964 | if (IS_ERR(skb)) | ||
965 | goto tx_error; | ||
966 | |||
956 | skb->transport_header = skb->network_header; | 967 | skb->transport_header = skb->network_header; |
957 | 968 | ||
958 | skb_push(skb, sizeof(struct ipv6hdr)); | 969 | skb_push(skb, sizeof(struct ipv6hdr)); |
@@ -967,8 +978,8 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
967 | iph->nexthdr = IPPROTO_IPV6; | 978 | iph->nexthdr = IPPROTO_IPV6; |
968 | iph->payload_len = old_iph->payload_len; | 979 | iph->payload_len = old_iph->payload_len; |
969 | be16_add_cpu(&iph->payload_len, sizeof(*old_iph)); | 980 | be16_add_cpu(&iph->payload_len, sizeof(*old_iph)); |
970 | iph->priority = old_iph->priority; | ||
971 | memset(&iph->flow_lbl, 0, sizeof(iph->flow_lbl)); | 981 | memset(&iph->flow_lbl, 0, sizeof(iph->flow_lbl)); |
982 | ipv6_change_dsfield(iph, 0, ipv6_get_dsfield(old_iph)); | ||
972 | iph->daddr = cp->daddr.in6; | 983 | iph->daddr = cp->daddr.in6; |
973 | iph->saddr = saddr; | 984 | iph->saddr = saddr; |
974 | iph->hop_limit = old_iph->hop_limit; | 985 | iph->hop_limit = old_iph->hop_limit; |
@@ -988,7 +999,8 @@ ip_vs_tunnel_xmit_v6(struct sk_buff *skb, struct ip_vs_conn *cp, | |||
988 | return NF_STOLEN; | 999 | return NF_STOLEN; |
989 | 1000 | ||
990 | tx_error: | 1001 | tx_error: |
991 | kfree_skb(skb); | 1002 | if (!IS_ERR(skb)) |
1003 | kfree_skb(skb); | ||
992 | rcu_read_unlock(); | 1004 | rcu_read_unlock(); |
993 | LeaveFunction(10); | 1005 | LeaveFunction(10); |
994 | return NF_STOLEN; | 1006 | return NF_STOLEN; |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 1f4f954c4b47..de88c4ab5146 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
@@ -352,40 +352,6 @@ static void nf_ct_delete_from_lists(struct nf_conn *ct) | |||
352 | local_bh_enable(); | 352 | local_bh_enable(); |
353 | } | 353 | } |
354 | 354 | ||
355 | static void death_by_event(unsigned long ul_conntrack) | ||
356 | { | ||
357 | struct nf_conn *ct = (void *)ul_conntrack; | ||
358 | struct net *net = nf_ct_net(ct); | ||
359 | struct nf_conntrack_ecache *ecache = nf_ct_ecache_find(ct); | ||
360 | |||
361 | BUG_ON(ecache == NULL); | ||
362 | |||
363 | if (nf_conntrack_event(IPCT_DESTROY, ct) < 0) { | ||
364 | /* bad luck, let's retry again */ | ||
365 | ecache->timeout.expires = jiffies + | ||
366 | (prandom_u32() % net->ct.sysctl_events_retry_timeout); | ||
367 | add_timer(&ecache->timeout); | ||
368 | return; | ||
369 | } | ||
370 | /* we've got the event delivered, now it's dying */ | ||
371 | set_bit(IPS_DYING_BIT, &ct->status); | ||
372 | nf_ct_put(ct); | ||
373 | } | ||
374 | |||
375 | static void nf_ct_dying_timeout(struct nf_conn *ct) | ||
376 | { | ||
377 | struct net *net = nf_ct_net(ct); | ||
378 | struct nf_conntrack_ecache *ecache = nf_ct_ecache_find(ct); | ||
379 | |||
380 | BUG_ON(ecache == NULL); | ||
381 | |||
382 | /* set a new timer to retry event delivery */ | ||
383 | setup_timer(&ecache->timeout, death_by_event, (unsigned long)ct); | ||
384 | ecache->timeout.expires = jiffies + | ||
385 | (prandom_u32() % net->ct.sysctl_events_retry_timeout); | ||
386 | add_timer(&ecache->timeout); | ||
387 | } | ||
388 | |||
389 | bool nf_ct_delete(struct nf_conn *ct, u32 portid, int report) | 355 | bool nf_ct_delete(struct nf_conn *ct, u32 portid, int report) |
390 | { | 356 | { |
391 | struct nf_conn_tstamp *tstamp; | 357 | struct nf_conn_tstamp *tstamp; |
@@ -394,15 +360,20 @@ bool nf_ct_delete(struct nf_conn *ct, u32 portid, int report) | |||
394 | if (tstamp && tstamp->stop == 0) | 360 | if (tstamp && tstamp->stop == 0) |
395 | tstamp->stop = ktime_to_ns(ktime_get_real()); | 361 | tstamp->stop = ktime_to_ns(ktime_get_real()); |
396 | 362 | ||
397 | if (!nf_ct_is_dying(ct) && | 363 | if (nf_ct_is_dying(ct)) |
398 | unlikely(nf_conntrack_event_report(IPCT_DESTROY, ct, | 364 | goto delete; |
399 | portid, report) < 0)) { | 365 | |
366 | if (nf_conntrack_event_report(IPCT_DESTROY, ct, | ||
367 | portid, report) < 0) { | ||
400 | /* destroy event was not delivered */ | 368 | /* destroy event was not delivered */ |
401 | nf_ct_delete_from_lists(ct); | 369 | nf_ct_delete_from_lists(ct); |
402 | nf_ct_dying_timeout(ct); | 370 | nf_conntrack_ecache_delayed_work(nf_ct_net(ct)); |
403 | return false; | 371 | return false; |
404 | } | 372 | } |
373 | |||
374 | nf_conntrack_ecache_work(nf_ct_net(ct)); | ||
405 | set_bit(IPS_DYING_BIT, &ct->status); | 375 | set_bit(IPS_DYING_BIT, &ct->status); |
376 | delete: | ||
406 | nf_ct_delete_from_lists(ct); | 377 | nf_ct_delete_from_lists(ct); |
407 | nf_ct_put(ct); | 378 | nf_ct_put(ct); |
408 | return true; | 379 | return true; |
@@ -1464,26 +1435,6 @@ void nf_conntrack_flush_report(struct net *net, u32 portid, int report) | |||
1464 | } | 1435 | } |
1465 | EXPORT_SYMBOL_GPL(nf_conntrack_flush_report); | 1436 | EXPORT_SYMBOL_GPL(nf_conntrack_flush_report); |
1466 | 1437 | ||
1467 | static void nf_ct_release_dying_list(struct net *net) | ||
1468 | { | ||
1469 | struct nf_conntrack_tuple_hash *h; | ||
1470 | struct nf_conn *ct; | ||
1471 | struct hlist_nulls_node *n; | ||
1472 | int cpu; | ||
1473 | |||
1474 | for_each_possible_cpu(cpu) { | ||
1475 | struct ct_pcpu *pcpu = per_cpu_ptr(net->ct.pcpu_lists, cpu); | ||
1476 | |||
1477 | spin_lock_bh(&pcpu->lock); | ||
1478 | hlist_nulls_for_each_entry(h, n, &pcpu->dying, hnnode) { | ||
1479 | ct = nf_ct_tuplehash_to_ctrack(h); | ||
1480 | /* never fails to remove them, no listeners at this point */ | ||
1481 | nf_ct_kill(ct); | ||
1482 | } | ||
1483 | spin_unlock_bh(&pcpu->lock); | ||
1484 | } | ||
1485 | } | ||
1486 | |||
1487 | static int untrack_refs(void) | 1438 | static int untrack_refs(void) |
1488 | { | 1439 | { |
1489 | int cnt = 0, cpu; | 1440 | int cnt = 0, cpu; |
@@ -1548,7 +1499,6 @@ i_see_dead_people: | |||
1548 | busy = 0; | 1499 | busy = 0; |
1549 | list_for_each_entry(net, net_exit_list, exit_list) { | 1500 | list_for_each_entry(net, net_exit_list, exit_list) { |
1550 | nf_ct_iterate_cleanup(net, kill_all, NULL, 0, 0); | 1501 | nf_ct_iterate_cleanup(net, kill_all, NULL, 0, 0); |
1551 | nf_ct_release_dying_list(net); | ||
1552 | if (atomic_read(&net->ct.count) != 0) | 1502 | if (atomic_read(&net->ct.count) != 0) |
1553 | busy = 1; | 1503 | busy = 1; |
1554 | } | 1504 | } |
diff --git a/net/netfilter/nf_conntrack_ecache.c b/net/netfilter/nf_conntrack_ecache.c index 1df176146567..4e78c57b818f 100644 --- a/net/netfilter/nf_conntrack_ecache.c +++ b/net/netfilter/nf_conntrack_ecache.c | |||
@@ -29,6 +29,90 @@ | |||
29 | 29 | ||
30 | static DEFINE_MUTEX(nf_ct_ecache_mutex); | 30 | static DEFINE_MUTEX(nf_ct_ecache_mutex); |
31 | 31 | ||
32 | #define ECACHE_RETRY_WAIT (HZ/10) | ||
33 | |||
34 | enum retry_state { | ||
35 | STATE_CONGESTED, | ||
36 | STATE_RESTART, | ||
37 | STATE_DONE, | ||
38 | }; | ||
39 | |||
40 | static enum retry_state ecache_work_evict_list(struct ct_pcpu *pcpu) | ||
41 | { | ||
42 | struct nf_conn *refs[16]; | ||
43 | struct nf_conntrack_tuple_hash *h; | ||
44 | struct hlist_nulls_node *n; | ||
45 | unsigned int evicted = 0; | ||
46 | enum retry_state ret = STATE_DONE; | ||
47 | |||
48 | spin_lock(&pcpu->lock); | ||
49 | |||
50 | hlist_nulls_for_each_entry(h, n, &pcpu->dying, hnnode) { | ||
51 | struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(h); | ||
52 | |||
53 | if (nf_ct_is_dying(ct)) | ||
54 | continue; | ||
55 | |||
56 | if (nf_conntrack_event(IPCT_DESTROY, ct)) { | ||
57 | ret = STATE_CONGESTED; | ||
58 | break; | ||
59 | } | ||
60 | |||
61 | /* we've got the event delivered, now it's dying */ | ||
62 | set_bit(IPS_DYING_BIT, &ct->status); | ||
63 | refs[evicted] = ct; | ||
64 | |||
65 | if (++evicted >= ARRAY_SIZE(refs)) { | ||
66 | ret = STATE_RESTART; | ||
67 | break; | ||
68 | } | ||
69 | } | ||
70 | |||
71 | spin_unlock(&pcpu->lock); | ||
72 | |||
73 | /* can't _put while holding lock */ | ||
74 | while (evicted) | ||
75 | nf_ct_put(refs[--evicted]); | ||
76 | |||
77 | return ret; | ||
78 | } | ||
79 | |||
80 | static void ecache_work(struct work_struct *work) | ||
81 | { | ||
82 | struct netns_ct *ctnet = | ||
83 | container_of(work, struct netns_ct, ecache_dwork.work); | ||
84 | int cpu, delay = -1; | ||
85 | struct ct_pcpu *pcpu; | ||
86 | |||
87 | local_bh_disable(); | ||
88 | |||
89 | for_each_possible_cpu(cpu) { | ||
90 | enum retry_state ret; | ||
91 | |||
92 | pcpu = per_cpu_ptr(ctnet->pcpu_lists, cpu); | ||
93 | |||
94 | ret = ecache_work_evict_list(pcpu); | ||
95 | |||
96 | switch (ret) { | ||
97 | case STATE_CONGESTED: | ||
98 | delay = ECACHE_RETRY_WAIT; | ||
99 | goto out; | ||
100 | case STATE_RESTART: | ||
101 | delay = 0; | ||
102 | break; | ||
103 | case STATE_DONE: | ||
104 | break; | ||
105 | } | ||
106 | } | ||
107 | |||
108 | out: | ||
109 | local_bh_enable(); | ||
110 | |||
111 | ctnet->ecache_dwork_pending = delay > 0; | ||
112 | if (delay >= 0) | ||
113 | schedule_delayed_work(&ctnet->ecache_dwork, delay); | ||
114 | } | ||
115 | |||
32 | /* deliver cached events and clear cache entry - must be called with locally | 116 | /* deliver cached events and clear cache entry - must be called with locally |
33 | * disabled softirqs */ | 117 | * disabled softirqs */ |
34 | void nf_ct_deliver_cached_events(struct nf_conn *ct) | 118 | void nf_ct_deliver_cached_events(struct nf_conn *ct) |
@@ -157,7 +241,6 @@ EXPORT_SYMBOL_GPL(nf_ct_expect_unregister_notifier); | |||
157 | 241 | ||
158 | #define NF_CT_EVENTS_DEFAULT 1 | 242 | #define NF_CT_EVENTS_DEFAULT 1 |
159 | static int nf_ct_events __read_mostly = NF_CT_EVENTS_DEFAULT; | 243 | static int nf_ct_events __read_mostly = NF_CT_EVENTS_DEFAULT; |
160 | static int nf_ct_events_retry_timeout __read_mostly = 15*HZ; | ||
161 | 244 | ||
162 | #ifdef CONFIG_SYSCTL | 245 | #ifdef CONFIG_SYSCTL |
163 | static struct ctl_table event_sysctl_table[] = { | 246 | static struct ctl_table event_sysctl_table[] = { |
@@ -168,13 +251,6 @@ static struct ctl_table event_sysctl_table[] = { | |||
168 | .mode = 0644, | 251 | .mode = 0644, |
169 | .proc_handler = proc_dointvec, | 252 | .proc_handler = proc_dointvec, |
170 | }, | 253 | }, |
171 | { | ||
172 | .procname = "nf_conntrack_events_retry_timeout", | ||
173 | .data = &init_net.ct.sysctl_events_retry_timeout, | ||
174 | .maxlen = sizeof(unsigned int), | ||
175 | .mode = 0644, | ||
176 | .proc_handler = proc_dointvec_jiffies, | ||
177 | }, | ||
178 | {} | 254 | {} |
179 | }; | 255 | }; |
180 | #endif /* CONFIG_SYSCTL */ | 256 | #endif /* CONFIG_SYSCTL */ |
@@ -196,7 +272,6 @@ static int nf_conntrack_event_init_sysctl(struct net *net) | |||
196 | goto out; | 272 | goto out; |
197 | 273 | ||
198 | table[0].data = &net->ct.sysctl_events; | 274 | table[0].data = &net->ct.sysctl_events; |
199 | table[1].data = &net->ct.sysctl_events_retry_timeout; | ||
200 | 275 | ||
201 | /* Don't export sysctls to unprivileged users */ | 276 | /* Don't export sysctls to unprivileged users */ |
202 | if (net->user_ns != &init_user_ns) | 277 | if (net->user_ns != &init_user_ns) |
@@ -238,12 +313,13 @@ static void nf_conntrack_event_fini_sysctl(struct net *net) | |||
238 | int nf_conntrack_ecache_pernet_init(struct net *net) | 313 | int nf_conntrack_ecache_pernet_init(struct net *net) |
239 | { | 314 | { |
240 | net->ct.sysctl_events = nf_ct_events; | 315 | net->ct.sysctl_events = nf_ct_events; |
241 | net->ct.sysctl_events_retry_timeout = nf_ct_events_retry_timeout; | 316 | INIT_DELAYED_WORK(&net->ct.ecache_dwork, ecache_work); |
242 | return nf_conntrack_event_init_sysctl(net); | 317 | return nf_conntrack_event_init_sysctl(net); |
243 | } | 318 | } |
244 | 319 | ||
245 | void nf_conntrack_ecache_pernet_fini(struct net *net) | 320 | void nf_conntrack_ecache_pernet_fini(struct net *net) |
246 | { | 321 | { |
322 | cancel_delayed_work_sync(&net->ct.ecache_dwork); | ||
247 | nf_conntrack_event_fini_sysctl(net); | 323 | nf_conntrack_event_fini_sysctl(net); |
248 | } | 324 | } |
249 | 325 | ||
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index 300ed1eec729..355a5c4ef763 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
@@ -745,8 +745,7 @@ static int ctnetlink_done(struct netlink_callback *cb) | |||
745 | { | 745 | { |
746 | if (cb->args[1]) | 746 | if (cb->args[1]) |
747 | nf_ct_put((struct nf_conn *)cb->args[1]); | 747 | nf_ct_put((struct nf_conn *)cb->args[1]); |
748 | if (cb->data) | 748 | kfree(cb->data); |
749 | kfree(cb->data); | ||
750 | return 0; | 749 | return 0; |
751 | } | 750 | } |
752 | 751 | ||
diff --git a/net/netfilter/nf_log.c b/net/netfilter/nf_log.c index 85296d4eac0e..daad6022c689 100644 --- a/net/netfilter/nf_log.c +++ b/net/netfilter/nf_log.c | |||
@@ -16,16 +16,22 @@ | |||
16 | #define NF_LOG_PREFIXLEN 128 | 16 | #define NF_LOG_PREFIXLEN 128 |
17 | #define NFLOGGER_NAME_LEN 64 | 17 | #define NFLOGGER_NAME_LEN 64 |
18 | 18 | ||
19 | static struct list_head nf_loggers_l[NFPROTO_NUMPROTO] __read_mostly; | 19 | static struct nf_logger __rcu *loggers[NFPROTO_NUMPROTO][NF_LOG_TYPE_MAX] __read_mostly; |
20 | static DEFINE_MUTEX(nf_log_mutex); | 20 | static DEFINE_MUTEX(nf_log_mutex); |
21 | 21 | ||
22 | static struct nf_logger *__find_logger(int pf, const char *str_logger) | 22 | static struct nf_logger *__find_logger(int pf, const char *str_logger) |
23 | { | 23 | { |
24 | struct nf_logger *t; | 24 | struct nf_logger *log; |
25 | int i; | ||
26 | |||
27 | for (i = 0; i < NF_LOG_TYPE_MAX; i++) { | ||
28 | if (loggers[pf][i] == NULL) | ||
29 | continue; | ||
25 | 30 | ||
26 | list_for_each_entry(t, &nf_loggers_l[pf], list[pf]) { | 31 | log = rcu_dereference_protected(loggers[pf][i], |
27 | if (!strnicmp(str_logger, t->name, strlen(t->name))) | 32 | lockdep_is_held(&nf_log_mutex)); |
28 | return t; | 33 | if (!strnicmp(str_logger, log->name, strlen(log->name))) |
34 | return log; | ||
29 | } | 35 | } |
30 | 36 | ||
31 | return NULL; | 37 | return NULL; |
@@ -73,17 +79,14 @@ int nf_log_register(u_int8_t pf, struct nf_logger *logger) | |||
73 | if (pf >= ARRAY_SIZE(init_net.nf.nf_loggers)) | 79 | if (pf >= ARRAY_SIZE(init_net.nf.nf_loggers)) |
74 | return -EINVAL; | 80 | return -EINVAL; |
75 | 81 | ||
76 | for (i = 0; i < ARRAY_SIZE(logger->list); i++) | ||
77 | INIT_LIST_HEAD(&logger->list[i]); | ||
78 | |||
79 | mutex_lock(&nf_log_mutex); | 82 | mutex_lock(&nf_log_mutex); |
80 | 83 | ||
81 | if (pf == NFPROTO_UNSPEC) { | 84 | if (pf == NFPROTO_UNSPEC) { |
82 | for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) | 85 | for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) |
83 | list_add_tail(&(logger->list[i]), &(nf_loggers_l[i])); | 86 | rcu_assign_pointer(loggers[i][logger->type], logger); |
84 | } else { | 87 | } else { |
85 | /* register at end of list to honor first register win */ | 88 | /* register at end of list to honor first register win */ |
86 | list_add_tail(&logger->list[pf], &nf_loggers_l[pf]); | 89 | rcu_assign_pointer(loggers[pf][logger->type], logger); |
87 | } | 90 | } |
88 | 91 | ||
89 | mutex_unlock(&nf_log_mutex); | 92 | mutex_unlock(&nf_log_mutex); |
@@ -98,7 +101,7 @@ void nf_log_unregister(struct nf_logger *logger) | |||
98 | 101 | ||
99 | mutex_lock(&nf_log_mutex); | 102 | mutex_lock(&nf_log_mutex); |
100 | for (i = 0; i < NFPROTO_NUMPROTO; i++) | 103 | for (i = 0; i < NFPROTO_NUMPROTO; i++) |
101 | list_del(&logger->list[i]); | 104 | RCU_INIT_POINTER(loggers[i][logger->type], NULL); |
102 | mutex_unlock(&nf_log_mutex); | 105 | mutex_unlock(&nf_log_mutex); |
103 | } | 106 | } |
104 | EXPORT_SYMBOL(nf_log_unregister); | 107 | EXPORT_SYMBOL(nf_log_unregister); |
@@ -129,6 +132,48 @@ void nf_log_unbind_pf(struct net *net, u_int8_t pf) | |||
129 | } | 132 | } |
130 | EXPORT_SYMBOL(nf_log_unbind_pf); | 133 | EXPORT_SYMBOL(nf_log_unbind_pf); |
131 | 134 | ||
135 | void nf_logger_request_module(int pf, enum nf_log_type type) | ||
136 | { | ||
137 | if (loggers[pf][type] == NULL) | ||
138 | request_module("nf-logger-%u-%u", pf, type); | ||
139 | } | ||
140 | EXPORT_SYMBOL_GPL(nf_logger_request_module); | ||
141 | |||
142 | int nf_logger_find_get(int pf, enum nf_log_type type) | ||
143 | { | ||
144 | struct nf_logger *logger; | ||
145 | int ret = -ENOENT; | ||
146 | |||
147 | logger = loggers[pf][type]; | ||
148 | if (logger == NULL) | ||
149 | request_module("nf-logger-%u-%u", pf, type); | ||
150 | |||
151 | rcu_read_lock(); | ||
152 | logger = rcu_dereference(loggers[pf][type]); | ||
153 | if (logger == NULL) | ||
154 | goto out; | ||
155 | |||
156 | if (logger && try_module_get(logger->me)) | ||
157 | ret = 0; | ||
158 | out: | ||
159 | rcu_read_unlock(); | ||
160 | return ret; | ||
161 | } | ||
162 | EXPORT_SYMBOL_GPL(nf_logger_find_get); | ||
163 | |||
164 | void nf_logger_put(int pf, enum nf_log_type type) | ||
165 | { | ||
166 | struct nf_logger *logger; | ||
167 | |||
168 | BUG_ON(loggers[pf][type] == NULL); | ||
169 | |||
170 | rcu_read_lock(); | ||
171 | logger = rcu_dereference(loggers[pf][type]); | ||
172 | module_put(logger->me); | ||
173 | rcu_read_unlock(); | ||
174 | } | ||
175 | EXPORT_SYMBOL_GPL(nf_logger_put); | ||
176 | |||
132 | void nf_log_packet(struct net *net, | 177 | void nf_log_packet(struct net *net, |
133 | u_int8_t pf, | 178 | u_int8_t pf, |
134 | unsigned int hooknum, | 179 | unsigned int hooknum, |
@@ -143,7 +188,11 @@ void nf_log_packet(struct net *net, | |||
143 | const struct nf_logger *logger; | 188 | const struct nf_logger *logger; |
144 | 189 | ||
145 | rcu_read_lock(); | 190 | rcu_read_lock(); |
146 | logger = rcu_dereference(net->nf.nf_loggers[pf]); | 191 | if (loginfo != NULL) |
192 | logger = rcu_dereference(loggers[pf][loginfo->type]); | ||
193 | else | ||
194 | logger = rcu_dereference(net->nf.nf_loggers[pf]); | ||
195 | |||
147 | if (logger) { | 196 | if (logger) { |
148 | va_start(args, fmt); | 197 | va_start(args, fmt); |
149 | vsnprintf(prefix, sizeof(prefix), fmt, args); | 198 | vsnprintf(prefix, sizeof(prefix), fmt, args); |
@@ -154,6 +203,63 @@ void nf_log_packet(struct net *net, | |||
154 | } | 203 | } |
155 | EXPORT_SYMBOL(nf_log_packet); | 204 | EXPORT_SYMBOL(nf_log_packet); |
156 | 205 | ||
206 | #define S_SIZE (1024 - (sizeof(unsigned int) + 1)) | ||
207 | |||
208 | struct nf_log_buf { | ||
209 | unsigned int count; | ||
210 | char buf[S_SIZE + 1]; | ||
211 | }; | ||
212 | static struct nf_log_buf emergency, *emergency_ptr = &emergency; | ||
213 | |||
214 | __printf(2, 3) int nf_log_buf_add(struct nf_log_buf *m, const char *f, ...) | ||
215 | { | ||
216 | va_list args; | ||
217 | int len; | ||
218 | |||
219 | if (likely(m->count < S_SIZE)) { | ||
220 | va_start(args, f); | ||
221 | len = vsnprintf(m->buf + m->count, S_SIZE - m->count, f, args); | ||
222 | va_end(args); | ||
223 | if (likely(m->count + len < S_SIZE)) { | ||
224 | m->count += len; | ||
225 | return 0; | ||
226 | } | ||
227 | } | ||
228 | m->count = S_SIZE; | ||
229 | printk_once(KERN_ERR KBUILD_MODNAME " please increase S_SIZE\n"); | ||
230 | return -1; | ||
231 | } | ||
232 | EXPORT_SYMBOL_GPL(nf_log_buf_add); | ||
233 | |||
234 | struct nf_log_buf *nf_log_buf_open(void) | ||
235 | { | ||
236 | struct nf_log_buf *m = kmalloc(sizeof(*m), GFP_ATOMIC); | ||
237 | |||
238 | if (unlikely(!m)) { | ||
239 | local_bh_disable(); | ||
240 | do { | ||
241 | m = xchg(&emergency_ptr, NULL); | ||
242 | } while (!m); | ||
243 | } | ||
244 | m->count = 0; | ||
245 | return m; | ||
246 | } | ||
247 | EXPORT_SYMBOL_GPL(nf_log_buf_open); | ||
248 | |||
249 | void nf_log_buf_close(struct nf_log_buf *m) | ||
250 | { | ||
251 | m->buf[m->count] = 0; | ||
252 | printk("%s\n", m->buf); | ||
253 | |||
254 | if (likely(m != &emergency)) | ||
255 | kfree(m); | ||
256 | else { | ||
257 | emergency_ptr = m; | ||
258 | local_bh_enable(); | ||
259 | } | ||
260 | } | ||
261 | EXPORT_SYMBOL_GPL(nf_log_buf_close); | ||
262 | |||
157 | #ifdef CONFIG_PROC_FS | 263 | #ifdef CONFIG_PROC_FS |
158 | static void *seq_start(struct seq_file *seq, loff_t *pos) | 264 | static void *seq_start(struct seq_file *seq, loff_t *pos) |
159 | { | 265 | { |
@@ -188,8 +294,7 @@ static int seq_show(struct seq_file *s, void *v) | |||
188 | { | 294 | { |
189 | loff_t *pos = v; | 295 | loff_t *pos = v; |
190 | const struct nf_logger *logger; | 296 | const struct nf_logger *logger; |
191 | struct nf_logger *t; | 297 | int i, ret; |
192 | int ret; | ||
193 | struct net *net = seq_file_net(s); | 298 | struct net *net = seq_file_net(s); |
194 | 299 | ||
195 | logger = rcu_dereference_protected(net->nf.nf_loggers[*pos], | 300 | logger = rcu_dereference_protected(net->nf.nf_loggers[*pos], |
@@ -203,11 +308,16 @@ static int seq_show(struct seq_file *s, void *v) | |||
203 | if (ret < 0) | 308 | if (ret < 0) |
204 | return ret; | 309 | return ret; |
205 | 310 | ||
206 | list_for_each_entry(t, &nf_loggers_l[*pos], list[*pos]) { | 311 | for (i = 0; i < NF_LOG_TYPE_MAX; i++) { |
207 | ret = seq_printf(s, "%s", t->name); | 312 | if (loggers[*pos][i] == NULL) |
313 | continue; | ||
314 | |||
315 | logger = rcu_dereference_protected(loggers[*pos][i], | ||
316 | lockdep_is_held(&nf_log_mutex)); | ||
317 | ret = seq_printf(s, "%s", logger->name); | ||
208 | if (ret < 0) | 318 | if (ret < 0) |
209 | return ret; | 319 | return ret; |
210 | if (&t->list[*pos] != nf_loggers_l[*pos].prev) { | 320 | if (i == 0 && loggers[*pos][i + 1] != NULL) { |
211 | ret = seq_printf(s, ","); | 321 | ret = seq_printf(s, ","); |
212 | if (ret < 0) | 322 | if (ret < 0) |
213 | return ret; | 323 | return ret; |
@@ -389,14 +499,5 @@ static struct pernet_operations nf_log_net_ops = { | |||
389 | 499 | ||
390 | int __init netfilter_log_init(void) | 500 | int __init netfilter_log_init(void) |
391 | { | 501 | { |
392 | int i, ret; | 502 | return register_pernet_subsys(&nf_log_net_ops); |
393 | |||
394 | ret = register_pernet_subsys(&nf_log_net_ops); | ||
395 | if (ret < 0) | ||
396 | return ret; | ||
397 | |||
398 | for (i = NFPROTO_UNSPEC; i < NFPROTO_NUMPROTO; i++) | ||
399 | INIT_LIST_HEAD(&(nf_loggers_l[i])); | ||
400 | |||
401 | return 0; | ||
402 | } | 503 | } |
diff --git a/net/netfilter/nf_log_common.c b/net/netfilter/nf_log_common.c new file mode 100644 index 000000000000..eeb8ef4ff1a3 --- /dev/null +++ b/net/netfilter/nf_log_common.c | |||
@@ -0,0 +1,187 @@ | |||
1 | /* (C) 1999-2001 Paul `Rusty' Russell | ||
2 | * (C) 2002-2004 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 | #include <linux/module.h> | ||
10 | #include <linux/spinlock.h> | ||
11 | #include <linux/skbuff.h> | ||
12 | #include <linux/if_arp.h> | ||
13 | #include <linux/ip.h> | ||
14 | #include <net/icmp.h> | ||
15 | #include <net/udp.h> | ||
16 | #include <net/tcp.h> | ||
17 | #include <net/route.h> | ||
18 | |||
19 | #include <linux/netfilter.h> | ||
20 | #include <linux/netfilter/xt_LOG.h> | ||
21 | #include <net/netfilter/nf_log.h> | ||
22 | |||
23 | int nf_log_dump_udp_header(struct nf_log_buf *m, const struct sk_buff *skb, | ||
24 | u8 proto, int fragment, unsigned int offset) | ||
25 | { | ||
26 | struct udphdr _udph; | ||
27 | const struct udphdr *uh; | ||
28 | |||
29 | if (proto == IPPROTO_UDP) | ||
30 | /* Max length: 10 "PROTO=UDP " */ | ||
31 | nf_log_buf_add(m, "PROTO=UDP "); | ||
32 | else /* Max length: 14 "PROTO=UDPLITE " */ | ||
33 | nf_log_buf_add(m, "PROTO=UDPLITE "); | ||
34 | |||
35 | if (fragment) | ||
36 | goto out; | ||
37 | |||
38 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ | ||
39 | uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph); | ||
40 | if (uh == NULL) { | ||
41 | nf_log_buf_add(m, "INCOMPLETE [%u bytes] ", skb->len - offset); | ||
42 | |||
43 | return 1; | ||
44 | } | ||
45 | |||
46 | /* Max length: 20 "SPT=65535 DPT=65535 " */ | ||
47 | nf_log_buf_add(m, "SPT=%u DPT=%u LEN=%u ", | ||
48 | ntohs(uh->source), ntohs(uh->dest), ntohs(uh->len)); | ||
49 | |||
50 | out: | ||
51 | return 0; | ||
52 | } | ||
53 | EXPORT_SYMBOL_GPL(nf_log_dump_udp_header); | ||
54 | |||
55 | int nf_log_dump_tcp_header(struct nf_log_buf *m, const struct sk_buff *skb, | ||
56 | u8 proto, int fragment, unsigned int offset, | ||
57 | unsigned int logflags) | ||
58 | { | ||
59 | struct tcphdr _tcph; | ||
60 | const struct tcphdr *th; | ||
61 | |||
62 | /* Max length: 10 "PROTO=TCP " */ | ||
63 | nf_log_buf_add(m, "PROTO=TCP "); | ||
64 | |||
65 | if (fragment) | ||
66 | return 0; | ||
67 | |||
68 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ | ||
69 | th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph); | ||
70 | if (th == NULL) { | ||
71 | nf_log_buf_add(m, "INCOMPLETE [%u bytes] ", skb->len - offset); | ||
72 | return 1; | ||
73 | } | ||
74 | |||
75 | /* Max length: 20 "SPT=65535 DPT=65535 " */ | ||
76 | nf_log_buf_add(m, "SPT=%u DPT=%u ", | ||
77 | ntohs(th->source), ntohs(th->dest)); | ||
78 | /* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */ | ||
79 | if (logflags & XT_LOG_TCPSEQ) { | ||
80 | nf_log_buf_add(m, "SEQ=%u ACK=%u ", | ||
81 | ntohl(th->seq), ntohl(th->ack_seq)); | ||
82 | } | ||
83 | |||
84 | /* Max length: 13 "WINDOW=65535 " */ | ||
85 | nf_log_buf_add(m, "WINDOW=%u ", ntohs(th->window)); | ||
86 | /* Max length: 9 "RES=0x3C " */ | ||
87 | nf_log_buf_add(m, "RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(th) & | ||
88 | TCP_RESERVED_BITS) >> 22)); | ||
89 | /* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */ | ||
90 | if (th->cwr) | ||
91 | nf_log_buf_add(m, "CWR "); | ||
92 | if (th->ece) | ||
93 | nf_log_buf_add(m, "ECE "); | ||
94 | if (th->urg) | ||
95 | nf_log_buf_add(m, "URG "); | ||
96 | if (th->ack) | ||
97 | nf_log_buf_add(m, "ACK "); | ||
98 | if (th->psh) | ||
99 | nf_log_buf_add(m, "PSH "); | ||
100 | if (th->rst) | ||
101 | nf_log_buf_add(m, "RST "); | ||
102 | if (th->syn) | ||
103 | nf_log_buf_add(m, "SYN "); | ||
104 | if (th->fin) | ||
105 | nf_log_buf_add(m, "FIN "); | ||
106 | /* Max length: 11 "URGP=65535 " */ | ||
107 | nf_log_buf_add(m, "URGP=%u ", ntohs(th->urg_ptr)); | ||
108 | |||
109 | if ((logflags & XT_LOG_TCPOPT) && th->doff*4 > sizeof(struct tcphdr)) { | ||
110 | u_int8_t _opt[60 - sizeof(struct tcphdr)]; | ||
111 | const u_int8_t *op; | ||
112 | unsigned int i; | ||
113 | unsigned int optsize = th->doff*4 - sizeof(struct tcphdr); | ||
114 | |||
115 | op = skb_header_pointer(skb, offset + sizeof(struct tcphdr), | ||
116 | optsize, _opt); | ||
117 | if (op == NULL) { | ||
118 | nf_log_buf_add(m, "OPT (TRUNCATED)"); | ||
119 | return 1; | ||
120 | } | ||
121 | |||
122 | /* Max length: 127 "OPT (" 15*4*2chars ") " */ | ||
123 | nf_log_buf_add(m, "OPT ("); | ||
124 | for (i = 0; i < optsize; i++) | ||
125 | nf_log_buf_add(m, "%02X", op[i]); | ||
126 | |||
127 | nf_log_buf_add(m, ") "); | ||
128 | } | ||
129 | |||
130 | return 0; | ||
131 | } | ||
132 | EXPORT_SYMBOL_GPL(nf_log_dump_tcp_header); | ||
133 | |||
134 | void nf_log_dump_sk_uid_gid(struct nf_log_buf *m, struct sock *sk) | ||
135 | { | ||
136 | if (!sk || sk->sk_state == TCP_TIME_WAIT) | ||
137 | return; | ||
138 | |||
139 | read_lock_bh(&sk->sk_callback_lock); | ||
140 | if (sk->sk_socket && sk->sk_socket->file) { | ||
141 | const struct cred *cred = sk->sk_socket->file->f_cred; | ||
142 | nf_log_buf_add(m, "UID=%u GID=%u ", | ||
143 | from_kuid_munged(&init_user_ns, cred->fsuid), | ||
144 | from_kgid_munged(&init_user_ns, cred->fsgid)); | ||
145 | } | ||
146 | read_unlock_bh(&sk->sk_callback_lock); | ||
147 | } | ||
148 | EXPORT_SYMBOL_GPL(nf_log_dump_sk_uid_gid); | ||
149 | |||
150 | void | ||
151 | nf_log_dump_packet_common(struct nf_log_buf *m, u_int8_t pf, | ||
152 | unsigned int hooknum, const struct sk_buff *skb, | ||
153 | const struct net_device *in, | ||
154 | const struct net_device *out, | ||
155 | const struct nf_loginfo *loginfo, const char *prefix) | ||
156 | { | ||
157 | nf_log_buf_add(m, KERN_SOH "%c%sIN=%s OUT=%s ", | ||
158 | '0' + loginfo->u.log.level, prefix, | ||
159 | in ? in->name : "", | ||
160 | out ? out->name : ""); | ||
161 | #ifdef CONFIG_BRIDGE_NETFILTER | ||
162 | if (skb->nf_bridge) { | ||
163 | const struct net_device *physindev; | ||
164 | const struct net_device *physoutdev; | ||
165 | |||
166 | physindev = skb->nf_bridge->physindev; | ||
167 | if (physindev && in != physindev) | ||
168 | nf_log_buf_add(m, "PHYSIN=%s ", physindev->name); | ||
169 | physoutdev = skb->nf_bridge->physoutdev; | ||
170 | if (physoutdev && out != physoutdev) | ||
171 | nf_log_buf_add(m, "PHYSOUT=%s ", physoutdev->name); | ||
172 | } | ||
173 | #endif | ||
174 | } | ||
175 | EXPORT_SYMBOL_GPL(nf_log_dump_packet_common); | ||
176 | |||
177 | static int __init nf_log_common_init(void) | ||
178 | { | ||
179 | return 0; | ||
180 | } | ||
181 | |||
182 | static void __exit nf_log_common_exit(void) {} | ||
183 | |||
184 | module_init(nf_log_common_init); | ||
185 | module_exit(nf_log_common_exit); | ||
186 | |||
187 | MODULE_LICENSE("GPL"); | ||
diff --git a/net/netfilter/nf_nat_core.c b/net/netfilter/nf_nat_core.c index a49907b1dabc..552f97cd9fde 100644 --- a/net/netfilter/nf_nat_core.c +++ b/net/netfilter/nf_nat_core.c | |||
@@ -710,7 +710,7 @@ static struct nf_ct_ext_type nat_extend __read_mostly = { | |||
710 | .flags = NF_CT_EXT_F_PREALLOC, | 710 | .flags = NF_CT_EXT_F_PREALLOC, |
711 | }; | 711 | }; |
712 | 712 | ||
713 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 713 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
714 | 714 | ||
715 | #include <linux/netfilter/nfnetlink.h> | 715 | #include <linux/netfilter/nfnetlink.h> |
716 | #include <linux/netfilter/nfnetlink_conntrack.h> | 716 | #include <linux/netfilter/nfnetlink_conntrack.h> |
diff --git a/net/netfilter/nf_nat_proto_common.c b/net/netfilter/nf_nat_proto_common.c index 83a72a235cae..fbce552a796e 100644 --- a/net/netfilter/nf_nat_proto_common.c +++ b/net/netfilter/nf_nat_proto_common.c | |||
@@ -95,7 +95,7 @@ void nf_nat_l4proto_unique_tuple(const struct nf_nat_l3proto *l3proto, | |||
95 | } | 95 | } |
96 | EXPORT_SYMBOL_GPL(nf_nat_l4proto_unique_tuple); | 96 | EXPORT_SYMBOL_GPL(nf_nat_l4proto_unique_tuple); |
97 | 97 | ||
98 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 98 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
99 | int nf_nat_l4proto_nlattr_to_range(struct nlattr *tb[], | 99 | int nf_nat_l4proto_nlattr_to_range(struct nlattr *tb[], |
100 | struct nf_nat_range *range) | 100 | struct nf_nat_range *range) |
101 | { | 101 | { |
diff --git a/net/netfilter/nf_nat_proto_dccp.c b/net/netfilter/nf_nat_proto_dccp.c index c8be2cdac0bf..b8067b53ff3a 100644 --- a/net/netfilter/nf_nat_proto_dccp.c +++ b/net/netfilter/nf_nat_proto_dccp.c | |||
@@ -78,7 +78,7 @@ static const struct nf_nat_l4proto nf_nat_l4proto_dccp = { | |||
78 | .manip_pkt = dccp_manip_pkt, | 78 | .manip_pkt = dccp_manip_pkt, |
79 | .in_range = nf_nat_l4proto_in_range, | 79 | .in_range = nf_nat_l4proto_in_range, |
80 | .unique_tuple = dccp_unique_tuple, | 80 | .unique_tuple = dccp_unique_tuple, |
81 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 81 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
82 | .nlattr_to_range = nf_nat_l4proto_nlattr_to_range, | 82 | .nlattr_to_range = nf_nat_l4proto_nlattr_to_range, |
83 | #endif | 83 | #endif |
84 | }; | 84 | }; |
diff --git a/net/netfilter/nf_nat_proto_sctp.c b/net/netfilter/nf_nat_proto_sctp.c index 754536f2c674..cbc7ade1487b 100644 --- a/net/netfilter/nf_nat_proto_sctp.c +++ b/net/netfilter/nf_nat_proto_sctp.c | |||
@@ -59,7 +59,7 @@ static const struct nf_nat_l4proto nf_nat_l4proto_sctp = { | |||
59 | .manip_pkt = sctp_manip_pkt, | 59 | .manip_pkt = sctp_manip_pkt, |
60 | .in_range = nf_nat_l4proto_in_range, | 60 | .in_range = nf_nat_l4proto_in_range, |
61 | .unique_tuple = sctp_unique_tuple, | 61 | .unique_tuple = sctp_unique_tuple, |
62 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 62 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
63 | .nlattr_to_range = nf_nat_l4proto_nlattr_to_range, | 63 | .nlattr_to_range = nf_nat_l4proto_nlattr_to_range, |
64 | #endif | 64 | #endif |
65 | }; | 65 | }; |
diff --git a/net/netfilter/nf_nat_proto_tcp.c b/net/netfilter/nf_nat_proto_tcp.c index 83ec8a6e4c36..37f5505f4529 100644 --- a/net/netfilter/nf_nat_proto_tcp.c +++ b/net/netfilter/nf_nat_proto_tcp.c | |||
@@ -79,7 +79,7 @@ const struct nf_nat_l4proto nf_nat_l4proto_tcp = { | |||
79 | .manip_pkt = tcp_manip_pkt, | 79 | .manip_pkt = tcp_manip_pkt, |
80 | .in_range = nf_nat_l4proto_in_range, | 80 | .in_range = nf_nat_l4proto_in_range, |
81 | .unique_tuple = tcp_unique_tuple, | 81 | .unique_tuple = tcp_unique_tuple, |
82 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 82 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
83 | .nlattr_to_range = nf_nat_l4proto_nlattr_to_range, | 83 | .nlattr_to_range = nf_nat_l4proto_nlattr_to_range, |
84 | #endif | 84 | #endif |
85 | }; | 85 | }; |
diff --git a/net/netfilter/nf_nat_proto_udp.c b/net/netfilter/nf_nat_proto_udp.c index 7df613fb34a2..b0ede2f0d8bc 100644 --- a/net/netfilter/nf_nat_proto_udp.c +++ b/net/netfilter/nf_nat_proto_udp.c | |||
@@ -70,7 +70,7 @@ const struct nf_nat_l4proto nf_nat_l4proto_udp = { | |||
70 | .manip_pkt = udp_manip_pkt, | 70 | .manip_pkt = udp_manip_pkt, |
71 | .in_range = nf_nat_l4proto_in_range, | 71 | .in_range = nf_nat_l4proto_in_range, |
72 | .unique_tuple = udp_unique_tuple, | 72 | .unique_tuple = udp_unique_tuple, |
73 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 73 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
74 | .nlattr_to_range = nf_nat_l4proto_nlattr_to_range, | 74 | .nlattr_to_range = nf_nat_l4proto_nlattr_to_range, |
75 | #endif | 75 | #endif |
76 | }; | 76 | }; |
diff --git a/net/netfilter/nf_nat_proto_udplite.c b/net/netfilter/nf_nat_proto_udplite.c index 776a0d1317b1..368f14e01e75 100644 --- a/net/netfilter/nf_nat_proto_udplite.c +++ b/net/netfilter/nf_nat_proto_udplite.c | |||
@@ -69,7 +69,7 @@ static const struct nf_nat_l4proto nf_nat_l4proto_udplite = { | |||
69 | .manip_pkt = udplite_manip_pkt, | 69 | .manip_pkt = udplite_manip_pkt, |
70 | .in_range = nf_nat_l4proto_in_range, | 70 | .in_range = nf_nat_l4proto_in_range, |
71 | .unique_tuple = udplite_unique_tuple, | 71 | .unique_tuple = udplite_unique_tuple, |
72 | #if defined(CONFIG_NF_CT_NETLINK) || defined(CONFIG_NF_CT_NETLINK_MODULE) | 72 | #if IS_ENABLED(CONFIG_NF_CT_NETLINK) |
73 | .nlattr_to_range = nf_nat_l4proto_nlattr_to_range, | 73 | .nlattr_to_range = nf_nat_l4proto_nlattr_to_range, |
74 | #endif | 74 | #endif |
75 | }; | 75 | }; |
diff --git a/net/netfilter/nf_sockopt.c b/net/netfilter/nf_sockopt.c index f042ae521557..c68c1e58b362 100644 --- a/net/netfilter/nf_sockopt.c +++ b/net/netfilter/nf_sockopt.c | |||
@@ -26,9 +26,7 @@ int nf_register_sockopt(struct nf_sockopt_ops *reg) | |||
26 | struct nf_sockopt_ops *ops; | 26 | struct nf_sockopt_ops *ops; |
27 | int ret = 0; | 27 | int ret = 0; |
28 | 28 | ||
29 | if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0) | 29 | mutex_lock(&nf_sockopt_mutex); |
30 | return -EINTR; | ||
31 | |||
32 | list_for_each_entry(ops, &nf_sockopts, list) { | 30 | list_for_each_entry(ops, &nf_sockopts, list) { |
33 | if (ops->pf == reg->pf | 31 | if (ops->pf == reg->pf |
34 | && (overlap(ops->set_optmin, ops->set_optmax, | 32 | && (overlap(ops->set_optmin, ops->set_optmax, |
@@ -65,9 +63,7 @@ static struct nf_sockopt_ops *nf_sockopt_find(struct sock *sk, u_int8_t pf, | |||
65 | { | 63 | { |
66 | struct nf_sockopt_ops *ops; | 64 | struct nf_sockopt_ops *ops; |
67 | 65 | ||
68 | if (mutex_lock_interruptible(&nf_sockopt_mutex) != 0) | 66 | mutex_lock(&nf_sockopt_mutex); |
69 | return ERR_PTR(-EINTR); | ||
70 | |||
71 | list_for_each_entry(ops, &nf_sockopts, list) { | 67 | list_for_each_entry(ops, &nf_sockopts, list) { |
72 | if (ops->pf == pf) { | 68 | if (ops->pf == pf) { |
73 | if (!try_module_get(ops->owner)) | 69 | if (!try_module_get(ops->owner)) |
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 8746ff9a8357..deeb95fb7028 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c | |||
@@ -899,6 +899,9 @@ static struct nft_stats __percpu *nft_stats_alloc(const struct nlattr *attr) | |||
899 | static void nft_chain_stats_replace(struct nft_base_chain *chain, | 899 | static void nft_chain_stats_replace(struct nft_base_chain *chain, |
900 | struct nft_stats __percpu *newstats) | 900 | struct nft_stats __percpu *newstats) |
901 | { | 901 | { |
902 | if (newstats == NULL) | ||
903 | return; | ||
904 | |||
902 | if (chain->stats) { | 905 | if (chain->stats) { |
903 | struct nft_stats __percpu *oldstats = | 906 | struct nft_stats __percpu *oldstats = |
904 | nft_dereference(chain->stats); | 907 | nft_dereference(chain->stats); |
@@ -2247,80 +2250,7 @@ err: | |||
2247 | return err; | 2250 | return err; |
2248 | } | 2251 | } |
2249 | 2252 | ||
2250 | static int nf_tables_dump_sets_table(struct nft_ctx *ctx, struct sk_buff *skb, | 2253 | static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb) |
2251 | struct netlink_callback *cb) | ||
2252 | { | ||
2253 | const struct nft_set *set; | ||
2254 | unsigned int idx = 0, s_idx = cb->args[0]; | ||
2255 | |||
2256 | if (cb->args[1]) | ||
2257 | return skb->len; | ||
2258 | |||
2259 | rcu_read_lock(); | ||
2260 | cb->seq = ctx->net->nft.base_seq; | ||
2261 | |||
2262 | list_for_each_entry_rcu(set, &ctx->table->sets, list) { | ||
2263 | if (idx < s_idx) | ||
2264 | goto cont; | ||
2265 | if (nf_tables_fill_set(skb, ctx, set, NFT_MSG_NEWSET, | ||
2266 | NLM_F_MULTI) < 0) { | ||
2267 | cb->args[0] = idx; | ||
2268 | goto done; | ||
2269 | } | ||
2270 | nl_dump_check_consistent(cb, nlmsg_hdr(skb)); | ||
2271 | cont: | ||
2272 | idx++; | ||
2273 | } | ||
2274 | cb->args[1] = 1; | ||
2275 | done: | ||
2276 | rcu_read_unlock(); | ||
2277 | return skb->len; | ||
2278 | } | ||
2279 | |||
2280 | static int nf_tables_dump_sets_family(struct nft_ctx *ctx, struct sk_buff *skb, | ||
2281 | struct netlink_callback *cb) | ||
2282 | { | ||
2283 | const struct nft_set *set; | ||
2284 | unsigned int idx, s_idx = cb->args[0]; | ||
2285 | struct nft_table *table, *cur_table = (struct nft_table *)cb->args[2]; | ||
2286 | |||
2287 | if (cb->args[1]) | ||
2288 | return skb->len; | ||
2289 | |||
2290 | rcu_read_lock(); | ||
2291 | cb->seq = ctx->net->nft.base_seq; | ||
2292 | |||
2293 | list_for_each_entry_rcu(table, &ctx->afi->tables, list) { | ||
2294 | if (cur_table) { | ||
2295 | if (cur_table != table) | ||
2296 | continue; | ||
2297 | |||
2298 | cur_table = NULL; | ||
2299 | } | ||
2300 | ctx->table = table; | ||
2301 | idx = 0; | ||
2302 | list_for_each_entry_rcu(set, &ctx->table->sets, list) { | ||
2303 | if (idx < s_idx) | ||
2304 | goto cont; | ||
2305 | if (nf_tables_fill_set(skb, ctx, set, NFT_MSG_NEWSET, | ||
2306 | NLM_F_MULTI) < 0) { | ||
2307 | cb->args[0] = idx; | ||
2308 | cb->args[2] = (unsigned long) table; | ||
2309 | goto done; | ||
2310 | } | ||
2311 | nl_dump_check_consistent(cb, nlmsg_hdr(skb)); | ||
2312 | cont: | ||
2313 | idx++; | ||
2314 | } | ||
2315 | } | ||
2316 | cb->args[1] = 1; | ||
2317 | done: | ||
2318 | rcu_read_unlock(); | ||
2319 | return skb->len; | ||
2320 | } | ||
2321 | |||
2322 | static int nf_tables_dump_sets_all(struct nft_ctx *ctx, struct sk_buff *skb, | ||
2323 | struct netlink_callback *cb) | ||
2324 | { | 2254 | { |
2325 | const struct nft_set *set; | 2255 | const struct nft_set *set; |
2326 | unsigned int idx, s_idx = cb->args[0]; | 2256 | unsigned int idx, s_idx = cb->args[0]; |
@@ -2328,6 +2258,7 @@ static int nf_tables_dump_sets_all(struct nft_ctx *ctx, struct sk_buff *skb, | |||
2328 | struct nft_table *table, *cur_table = (struct nft_table *)cb->args[2]; | 2258 | struct nft_table *table, *cur_table = (struct nft_table *)cb->args[2]; |
2329 | struct net *net = sock_net(skb->sk); | 2259 | struct net *net = sock_net(skb->sk); |
2330 | int cur_family = cb->args[3]; | 2260 | int cur_family = cb->args[3]; |
2261 | struct nft_ctx *ctx = cb->data, ctx_set; | ||
2331 | 2262 | ||
2332 | if (cb->args[1]) | 2263 | if (cb->args[1]) |
2333 | return skb->len; | 2264 | return skb->len; |
@@ -2336,28 +2267,34 @@ static int nf_tables_dump_sets_all(struct nft_ctx *ctx, struct sk_buff *skb, | |||
2336 | cb->seq = net->nft.base_seq; | 2267 | cb->seq = net->nft.base_seq; |
2337 | 2268 | ||
2338 | list_for_each_entry_rcu(afi, &net->nft.af_info, list) { | 2269 | list_for_each_entry_rcu(afi, &net->nft.af_info, list) { |
2270 | if (ctx->afi && ctx->afi != afi) | ||
2271 | continue; | ||
2272 | |||
2339 | if (cur_family) { | 2273 | if (cur_family) { |
2340 | if (afi->family != cur_family) | 2274 | if (afi->family != cur_family) |
2341 | continue; | 2275 | continue; |
2342 | 2276 | ||
2343 | cur_family = 0; | 2277 | cur_family = 0; |
2344 | } | 2278 | } |
2345 | |||
2346 | list_for_each_entry_rcu(table, &afi->tables, list) { | 2279 | list_for_each_entry_rcu(table, &afi->tables, list) { |
2280 | if (ctx->table && ctx->table != table) | ||
2281 | continue; | ||
2282 | |||
2347 | if (cur_table) { | 2283 | if (cur_table) { |
2348 | if (cur_table != table) | 2284 | if (cur_table != table) |
2349 | continue; | 2285 | continue; |
2350 | 2286 | ||
2351 | cur_table = NULL; | 2287 | cur_table = NULL; |
2352 | } | 2288 | } |
2353 | |||
2354 | ctx->table = table; | ||
2355 | ctx->afi = afi; | ||
2356 | idx = 0; | 2289 | idx = 0; |
2357 | list_for_each_entry_rcu(set, &ctx->table->sets, list) { | 2290 | list_for_each_entry_rcu(set, &table->sets, list) { |
2358 | if (idx < s_idx) | 2291 | if (idx < s_idx) |
2359 | goto cont; | 2292 | goto cont; |
2360 | if (nf_tables_fill_set(skb, ctx, set, | 2293 | |
2294 | ctx_set = *ctx; | ||
2295 | ctx_set.table = table; | ||
2296 | ctx_set.afi = afi; | ||
2297 | if (nf_tables_fill_set(skb, &ctx_set, set, | ||
2361 | NFT_MSG_NEWSET, | 2298 | NFT_MSG_NEWSET, |
2362 | NLM_F_MULTI) < 0) { | 2299 | NLM_F_MULTI) < 0) { |
2363 | cb->args[0] = idx; | 2300 | cb->args[0] = idx; |
@@ -2379,31 +2316,10 @@ done: | |||
2379 | return skb->len; | 2316 | return skb->len; |
2380 | } | 2317 | } |
2381 | 2318 | ||
2382 | static int nf_tables_dump_sets(struct sk_buff *skb, struct netlink_callback *cb) | 2319 | static int nf_tables_dump_sets_done(struct netlink_callback *cb) |
2383 | { | 2320 | { |
2384 | const struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); | 2321 | kfree(cb->data); |
2385 | struct nlattr *nla[NFTA_SET_MAX + 1]; | 2322 | return 0; |
2386 | struct nft_ctx ctx; | ||
2387 | int err, ret; | ||
2388 | |||
2389 | err = nlmsg_parse(cb->nlh, sizeof(*nfmsg), nla, NFTA_SET_MAX, | ||
2390 | nft_set_policy); | ||
2391 | if (err < 0) | ||
2392 | return err; | ||
2393 | |||
2394 | err = nft_ctx_init_from_setattr(&ctx, cb->skb, cb->nlh, (void *)nla); | ||
2395 | if (err < 0) | ||
2396 | return err; | ||
2397 | |||
2398 | if (ctx.table == NULL) { | ||
2399 | if (ctx.afi == NULL) | ||
2400 | ret = nf_tables_dump_sets_all(&ctx, skb, cb); | ||
2401 | else | ||
2402 | ret = nf_tables_dump_sets_family(&ctx, skb, cb); | ||
2403 | } else | ||
2404 | ret = nf_tables_dump_sets_table(&ctx, skb, cb); | ||
2405 | |||
2406 | return ret; | ||
2407 | } | 2323 | } |
2408 | 2324 | ||
2409 | #define NFT_SET_INACTIVE (1 << 15) /* Internal set flag */ | 2325 | #define NFT_SET_INACTIVE (1 << 15) /* Internal set flag */ |
@@ -2426,7 +2342,17 @@ static int nf_tables_getset(struct sock *nlsk, struct sk_buff *skb, | |||
2426 | if (nlh->nlmsg_flags & NLM_F_DUMP) { | 2342 | if (nlh->nlmsg_flags & NLM_F_DUMP) { |
2427 | struct netlink_dump_control c = { | 2343 | struct netlink_dump_control c = { |
2428 | .dump = nf_tables_dump_sets, | 2344 | .dump = nf_tables_dump_sets, |
2345 | .done = nf_tables_dump_sets_done, | ||
2429 | }; | 2346 | }; |
2347 | struct nft_ctx *ctx_dump; | ||
2348 | |||
2349 | ctx_dump = kmalloc(sizeof(*ctx_dump), GFP_KERNEL); | ||
2350 | if (ctx_dump == NULL) | ||
2351 | return -ENOMEM; | ||
2352 | |||
2353 | *ctx_dump = ctx; | ||
2354 | c.data = ctx_dump; | ||
2355 | |||
2430 | return netlink_dump_start(nlsk, skb, nlh, &c); | 2356 | return netlink_dump_start(nlsk, skb, nlh, &c); |
2431 | } | 2357 | } |
2432 | 2358 | ||
@@ -3150,6 +3076,9 @@ static int nf_tables_newsetelem(struct sock *nlsk, struct sk_buff *skb, | |||
3150 | struct nft_ctx ctx; | 3076 | struct nft_ctx ctx; |
3151 | int rem, err = 0; | 3077 | int rem, err = 0; |
3152 | 3078 | ||
3079 | if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL) | ||
3080 | return -EINVAL; | ||
3081 | |||
3153 | err = nft_ctx_init_from_elemattr(&ctx, skb, nlh, nla, true); | 3082 | err = nft_ctx_init_from_elemattr(&ctx, skb, nlh, nla, true); |
3154 | if (err < 0) | 3083 | if (err < 0) |
3155 | return err; | 3084 | return err; |
@@ -3208,16 +3137,14 @@ static int nft_del_setelem(struct nft_ctx *ctx, struct nft_set *set, | |||
3208 | goto err2; | 3137 | goto err2; |
3209 | 3138 | ||
3210 | trans = nft_trans_elem_alloc(ctx, NFT_MSG_DELSETELEM, set); | 3139 | trans = nft_trans_elem_alloc(ctx, NFT_MSG_DELSETELEM, set); |
3211 | if (trans == NULL) | 3140 | if (trans == NULL) { |
3141 | err = -ENOMEM; | ||
3212 | goto err2; | 3142 | goto err2; |
3143 | } | ||
3213 | 3144 | ||
3214 | nft_trans_elem(trans) = elem; | 3145 | nft_trans_elem(trans) = elem; |
3215 | list_add_tail(&trans->list, &ctx->net->nft.commit_list); | 3146 | list_add_tail(&trans->list, &ctx->net->nft.commit_list); |
3216 | 3147 | return 0; | |
3217 | nft_data_uninit(&elem.key, NFT_DATA_VALUE); | ||
3218 | if (set->flags & NFT_SET_MAP) | ||
3219 | nft_data_uninit(&elem.data, set->dtype); | ||
3220 | |||
3221 | err2: | 3148 | err2: |
3222 | nft_data_uninit(&elem.key, desc.type); | 3149 | nft_data_uninit(&elem.key, desc.type); |
3223 | err1: | 3150 | err1: |
@@ -3233,6 +3160,9 @@ static int nf_tables_delsetelem(struct sock *nlsk, struct sk_buff *skb, | |||
3233 | struct nft_ctx ctx; | 3160 | struct nft_ctx ctx; |
3234 | int rem, err = 0; | 3161 | int rem, err = 0; |
3235 | 3162 | ||
3163 | if (nla[NFTA_SET_ELEM_LIST_ELEMENTS] == NULL) | ||
3164 | return -EINVAL; | ||
3165 | |||
3236 | err = nft_ctx_init_from_elemattr(&ctx, skb, nlh, nla, false); | 3166 | err = nft_ctx_init_from_elemattr(&ctx, skb, nlh, nla, false); |
3237 | if (err < 0) | 3167 | if (err < 0) |
3238 | return err; | 3168 | return err; |
@@ -3380,7 +3310,7 @@ static int nf_tables_commit(struct sk_buff *skb) | |||
3380 | { | 3310 | { |
3381 | struct net *net = sock_net(skb->sk); | 3311 | struct net *net = sock_net(skb->sk); |
3382 | struct nft_trans *trans, *next; | 3312 | struct nft_trans *trans, *next; |
3383 | struct nft_set *set; | 3313 | struct nft_trans_elem *te; |
3384 | 3314 | ||
3385 | /* Bump generation counter, invalidate any dump in progress */ | 3315 | /* Bump generation counter, invalidate any dump in progress */ |
3386 | while (++net->nft.base_seq == 0); | 3316 | while (++net->nft.base_seq == 0); |
@@ -3466,13 +3396,17 @@ static int nf_tables_commit(struct sk_buff *skb) | |||
3466 | nft_trans_destroy(trans); | 3396 | nft_trans_destroy(trans); |
3467 | break; | 3397 | break; |
3468 | case NFT_MSG_DELSETELEM: | 3398 | case NFT_MSG_DELSETELEM: |
3469 | nf_tables_setelem_notify(&trans->ctx, | 3399 | te = (struct nft_trans_elem *)trans->data; |
3470 | nft_trans_elem_set(trans), | 3400 | nf_tables_setelem_notify(&trans->ctx, te->set, |
3471 | &nft_trans_elem(trans), | 3401 | &te->elem, |
3472 | NFT_MSG_DELSETELEM, 0); | 3402 | NFT_MSG_DELSETELEM, 0); |
3473 | set = nft_trans_elem_set(trans); | 3403 | te->set->ops->get(te->set, &te->elem); |
3474 | set->ops->get(set, &nft_trans_elem(trans)); | 3404 | te->set->ops->remove(te->set, &te->elem); |
3475 | set->ops->remove(set, &nft_trans_elem(trans)); | 3405 | nft_data_uninit(&te->elem.key, NFT_DATA_VALUE); |
3406 | if (te->elem.flags & NFT_SET_MAP) { | ||
3407 | nft_data_uninit(&te->elem.data, | ||
3408 | te->set->dtype); | ||
3409 | } | ||
3476 | nft_trans_destroy(trans); | 3410 | nft_trans_destroy(trans); |
3477 | break; | 3411 | break; |
3478 | } | 3412 | } |
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index c138b8fbe280..f37f0716a9fc 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c | |||
@@ -222,6 +222,51 @@ replay: | |||
222 | } | 222 | } |
223 | } | 223 | } |
224 | 224 | ||
225 | struct nfnl_err { | ||
226 | struct list_head head; | ||
227 | struct nlmsghdr *nlh; | ||
228 | int err; | ||
229 | }; | ||
230 | |||
231 | static int nfnl_err_add(struct list_head *list, struct nlmsghdr *nlh, int err) | ||
232 | { | ||
233 | struct nfnl_err *nfnl_err; | ||
234 | |||
235 | nfnl_err = kmalloc(sizeof(struct nfnl_err), GFP_KERNEL); | ||
236 | if (nfnl_err == NULL) | ||
237 | return -ENOMEM; | ||
238 | |||
239 | nfnl_err->nlh = nlh; | ||
240 | nfnl_err->err = err; | ||
241 | list_add_tail(&nfnl_err->head, list); | ||
242 | |||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | static void nfnl_err_del(struct nfnl_err *nfnl_err) | ||
247 | { | ||
248 | list_del(&nfnl_err->head); | ||
249 | kfree(nfnl_err); | ||
250 | } | ||
251 | |||
252 | static void nfnl_err_reset(struct list_head *err_list) | ||
253 | { | ||
254 | struct nfnl_err *nfnl_err, *next; | ||
255 | |||
256 | list_for_each_entry_safe(nfnl_err, next, err_list, head) | ||
257 | nfnl_err_del(nfnl_err); | ||
258 | } | ||
259 | |||
260 | static void nfnl_err_deliver(struct list_head *err_list, struct sk_buff *skb) | ||
261 | { | ||
262 | struct nfnl_err *nfnl_err, *next; | ||
263 | |||
264 | list_for_each_entry_safe(nfnl_err, next, err_list, head) { | ||
265 | netlink_ack(skb, nfnl_err->nlh, nfnl_err->err); | ||
266 | nfnl_err_del(nfnl_err); | ||
267 | } | ||
268 | } | ||
269 | |||
225 | static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh, | 270 | static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh, |
226 | u_int16_t subsys_id) | 271 | u_int16_t subsys_id) |
227 | { | 272 | { |
@@ -230,6 +275,7 @@ static void nfnetlink_rcv_batch(struct sk_buff *skb, struct nlmsghdr *nlh, | |||
230 | const struct nfnetlink_subsystem *ss; | 275 | const struct nfnetlink_subsystem *ss; |
231 | const struct nfnl_callback *nc; | 276 | const struct nfnl_callback *nc; |
232 | bool success = true, done = false; | 277 | bool success = true, done = false; |
278 | static LIST_HEAD(err_list); | ||
233 | int err; | 279 | int err; |
234 | 280 | ||
235 | if (subsys_id >= NFNL_SUBSYS_COUNT) | 281 | if (subsys_id >= NFNL_SUBSYS_COUNT) |
@@ -287,6 +333,7 @@ replay: | |||
287 | type = nlh->nlmsg_type; | 333 | type = nlh->nlmsg_type; |
288 | if (type == NFNL_MSG_BATCH_BEGIN) { | 334 | if (type == NFNL_MSG_BATCH_BEGIN) { |
289 | /* Malformed: Batch begin twice */ | 335 | /* Malformed: Batch begin twice */ |
336 | nfnl_err_reset(&err_list); | ||
290 | success = false; | 337 | success = false; |
291 | goto done; | 338 | goto done; |
292 | } else if (type == NFNL_MSG_BATCH_END) { | 339 | } else if (type == NFNL_MSG_BATCH_END) { |
@@ -333,6 +380,7 @@ replay: | |||
333 | * original skb. | 380 | * original skb. |
334 | */ | 381 | */ |
335 | if (err == -EAGAIN) { | 382 | if (err == -EAGAIN) { |
383 | nfnl_err_reset(&err_list); | ||
336 | ss->abort(skb); | 384 | ss->abort(skb); |
337 | nfnl_unlock(subsys_id); | 385 | nfnl_unlock(subsys_id); |
338 | kfree_skb(nskb); | 386 | kfree_skb(nskb); |
@@ -341,11 +389,24 @@ replay: | |||
341 | } | 389 | } |
342 | ack: | 390 | ack: |
343 | if (nlh->nlmsg_flags & NLM_F_ACK || err) { | 391 | if (nlh->nlmsg_flags & NLM_F_ACK || err) { |
392 | /* Errors are delivered once the full batch has been | ||
393 | * processed, this avoids that the same error is | ||
394 | * reported several times when replaying the batch. | ||
395 | */ | ||
396 | if (nfnl_err_add(&err_list, nlh, err) < 0) { | ||
397 | /* We failed to enqueue an error, reset the | ||
398 | * list of errors and send OOM to userspace | ||
399 | * pointing to the batch header. | ||
400 | */ | ||
401 | nfnl_err_reset(&err_list); | ||
402 | netlink_ack(skb, nlmsg_hdr(oskb), -ENOMEM); | ||
403 | success = false; | ||
404 | goto done; | ||
405 | } | ||
344 | /* We don't stop processing the batch on errors, thus, | 406 | /* We don't stop processing the batch on errors, thus, |
345 | * userspace gets all the errors that the batch | 407 | * userspace gets all the errors that the batch |
346 | * triggers. | 408 | * triggers. |
347 | */ | 409 | */ |
348 | netlink_ack(skb, nlh, err); | ||
349 | if (err) | 410 | if (err) |
350 | success = false; | 411 | success = false; |
351 | } | 412 | } |
@@ -361,6 +422,7 @@ done: | |||
361 | else | 422 | else |
362 | ss->abort(skb); | 423 | ss->abort(skb); |
363 | 424 | ||
425 | nfnl_err_deliver(&err_list, oskb); | ||
364 | nfnl_unlock(subsys_id); | 426 | nfnl_unlock(subsys_id); |
365 | kfree_skb(nskb); | 427 | kfree_skb(nskb); |
366 | } | 428 | } |
diff --git a/net/netfilter/nfnetlink_acct.c b/net/netfilter/nfnetlink_acct.c index 2baa125c2e8d..3ea0eacbd970 100644 --- a/net/netfilter/nfnetlink_acct.c +++ b/net/netfilter/nfnetlink_acct.c | |||
@@ -41,6 +41,7 @@ struct nf_acct { | |||
41 | }; | 41 | }; |
42 | 42 | ||
43 | #define NFACCT_F_QUOTA (NFACCT_F_QUOTA_PKTS | NFACCT_F_QUOTA_BYTES) | 43 | #define NFACCT_F_QUOTA (NFACCT_F_QUOTA_PKTS | NFACCT_F_QUOTA_BYTES) |
44 | #define NFACCT_OVERQUOTA_BIT 2 /* NFACCT_F_OVERQUOTA */ | ||
44 | 45 | ||
45 | static int | 46 | static int |
46 | nfnl_acct_new(struct sock *nfnl, struct sk_buff *skb, | 47 | nfnl_acct_new(struct sock *nfnl, struct sk_buff *skb, |
@@ -77,7 +78,8 @@ nfnl_acct_new(struct sock *nfnl, struct sk_buff *skb, | |||
77 | smp_mb__before_atomic(); | 78 | smp_mb__before_atomic(); |
78 | /* reset overquota flag if quota is enabled. */ | 79 | /* reset overquota flag if quota is enabled. */ |
79 | if ((matching->flags & NFACCT_F_QUOTA)) | 80 | if ((matching->flags & NFACCT_F_QUOTA)) |
80 | clear_bit(NFACCT_F_OVERQUOTA, &matching->flags); | 81 | clear_bit(NFACCT_OVERQUOTA_BIT, |
82 | &matching->flags); | ||
81 | return 0; | 83 | return 0; |
82 | } | 84 | } |
83 | return -EBUSY; | 85 | return -EBUSY; |
@@ -129,6 +131,7 @@ nfnl_acct_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type, | |||
129 | struct nfgenmsg *nfmsg; | 131 | struct nfgenmsg *nfmsg; |
130 | unsigned int flags = portid ? NLM_F_MULTI : 0; | 132 | unsigned int flags = portid ? NLM_F_MULTI : 0; |
131 | u64 pkts, bytes; | 133 | u64 pkts, bytes; |
134 | u32 old_flags; | ||
132 | 135 | ||
133 | event |= NFNL_SUBSYS_ACCT << 8; | 136 | event |= NFNL_SUBSYS_ACCT << 8; |
134 | nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags); | 137 | nlh = nlmsg_put(skb, portid, seq, event, sizeof(*nfmsg), flags); |
@@ -143,12 +146,13 @@ nfnl_acct_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type, | |||
143 | if (nla_put_string(skb, NFACCT_NAME, acct->name)) | 146 | if (nla_put_string(skb, NFACCT_NAME, acct->name)) |
144 | goto nla_put_failure; | 147 | goto nla_put_failure; |
145 | 148 | ||
149 | old_flags = acct->flags; | ||
146 | if (type == NFNL_MSG_ACCT_GET_CTRZERO) { | 150 | if (type == NFNL_MSG_ACCT_GET_CTRZERO) { |
147 | pkts = atomic64_xchg(&acct->pkts, 0); | 151 | pkts = atomic64_xchg(&acct->pkts, 0); |
148 | bytes = atomic64_xchg(&acct->bytes, 0); | 152 | bytes = atomic64_xchg(&acct->bytes, 0); |
149 | smp_mb__before_atomic(); | 153 | smp_mb__before_atomic(); |
150 | if (acct->flags & NFACCT_F_QUOTA) | 154 | if (acct->flags & NFACCT_F_QUOTA) |
151 | clear_bit(NFACCT_F_OVERQUOTA, &acct->flags); | 155 | clear_bit(NFACCT_OVERQUOTA_BIT, &acct->flags); |
152 | } else { | 156 | } else { |
153 | pkts = atomic64_read(&acct->pkts); | 157 | pkts = atomic64_read(&acct->pkts); |
154 | bytes = atomic64_read(&acct->bytes); | 158 | bytes = atomic64_read(&acct->bytes); |
@@ -160,7 +164,7 @@ nfnl_acct_fill_info(struct sk_buff *skb, u32 portid, u32 seq, u32 type, | |||
160 | if (acct->flags & NFACCT_F_QUOTA) { | 164 | if (acct->flags & NFACCT_F_QUOTA) { |
161 | u64 *quota = (u64 *)acct->data; | 165 | u64 *quota = (u64 *)acct->data; |
162 | 166 | ||
163 | if (nla_put_be32(skb, NFACCT_FLAGS, htonl(acct->flags)) || | 167 | if (nla_put_be32(skb, NFACCT_FLAGS, htonl(old_flags)) || |
164 | nla_put_be64(skb, NFACCT_QUOTA, cpu_to_be64(*quota))) | 168 | nla_put_be64(skb, NFACCT_QUOTA, cpu_to_be64(*quota))) |
165 | goto nla_put_failure; | 169 | goto nla_put_failure; |
166 | } | 170 | } |
@@ -412,7 +416,7 @@ int nfnl_acct_overquota(const struct sk_buff *skb, struct nf_acct *nfacct) | |||
412 | ret = now > *quota; | 416 | ret = now > *quota; |
413 | 417 | ||
414 | if (now >= *quota && | 418 | if (now >= *quota && |
415 | !test_and_set_bit(NFACCT_F_OVERQUOTA, &nfacct->flags)) { | 419 | !test_and_set_bit(NFACCT_OVERQUOTA_BIT, &nfacct->flags)) { |
416 | nfnl_overquota_report(nfacct); | 420 | nfnl_overquota_report(nfacct); |
417 | } | 421 | } |
418 | 422 | ||
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index d292c8d286eb..a11c5ff2f720 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c | |||
@@ -773,6 +773,7 @@ nfulnl_recv_unsupp(struct sock *ctnl, struct sk_buff *skb, | |||
773 | 773 | ||
774 | static struct nf_logger nfulnl_logger __read_mostly = { | 774 | static struct nf_logger nfulnl_logger __read_mostly = { |
775 | .name = "nfnetlink_log", | 775 | .name = "nfnetlink_log", |
776 | .type = NF_LOG_TYPE_ULOG, | ||
776 | .logfn = &nfulnl_log_packet, | 777 | .logfn = &nfulnl_log_packet, |
777 | .me = THIS_MODULE, | 778 | .me = THIS_MODULE, |
778 | }; | 779 | }; |
@@ -1105,6 +1106,9 @@ MODULE_DESCRIPTION("netfilter userspace logging"); | |||
1105 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); | 1106 | MODULE_AUTHOR("Harald Welte <laforge@netfilter.org>"); |
1106 | MODULE_LICENSE("GPL"); | 1107 | MODULE_LICENSE("GPL"); |
1107 | MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_ULOG); | 1108 | MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_ULOG); |
1109 | MODULE_ALIAS_NF_LOGGER(AF_INET, 1); | ||
1110 | MODULE_ALIAS_NF_LOGGER(AF_INET6, 1); | ||
1111 | MODULE_ALIAS_NF_LOGGER(AF_BRIDGE, 1); | ||
1108 | 1112 | ||
1109 | module_init(nfnetlink_log_init); | 1113 | module_init(nfnetlink_log_init); |
1110 | module_exit(nfnetlink_log_fini); | 1114 | module_exit(nfnetlink_log_fini); |
diff --git a/net/netfilter/nft_hash.c b/net/netfilter/nft_hash.c index 4080ed6a072b..8892b7b6184a 100644 --- a/net/netfilter/nft_hash.c +++ b/net/netfilter/nft_hash.c | |||
@@ -15,209 +15,40 @@ | |||
15 | #include <linux/log2.h> | 15 | #include <linux/log2.h> |
16 | #include <linux/jhash.h> | 16 | #include <linux/jhash.h> |
17 | #include <linux/netlink.h> | 17 | #include <linux/netlink.h> |
18 | #include <linux/vmalloc.h> | 18 | #include <linux/rhashtable.h> |
19 | #include <linux/netfilter.h> | 19 | #include <linux/netfilter.h> |
20 | #include <linux/netfilter/nf_tables.h> | 20 | #include <linux/netfilter/nf_tables.h> |
21 | #include <net/netfilter/nf_tables.h> | 21 | #include <net/netfilter/nf_tables.h> |
22 | 22 | ||
23 | #define NFT_HASH_MIN_SIZE 4UL | 23 | /* We target a hash table size of 4, element hint is 75% of final size */ |
24 | 24 | #define NFT_HASH_ELEMENT_HINT 3 | |
25 | struct nft_hash { | ||
26 | struct nft_hash_table __rcu *tbl; | ||
27 | }; | ||
28 | |||
29 | struct nft_hash_table { | ||
30 | unsigned int size; | ||
31 | struct nft_hash_elem __rcu *buckets[]; | ||
32 | }; | ||
33 | 25 | ||
34 | struct nft_hash_elem { | 26 | struct nft_hash_elem { |
35 | struct nft_hash_elem __rcu *next; | 27 | struct rhash_head node; |
36 | struct nft_data key; | 28 | struct nft_data key; |
37 | struct nft_data data[]; | 29 | struct nft_data data[]; |
38 | }; | 30 | }; |
39 | 31 | ||
40 | #define nft_hash_for_each_entry(i, head) \ | ||
41 | for (i = nft_dereference(head); i != NULL; i = nft_dereference(i->next)) | ||
42 | #define nft_hash_for_each_entry_rcu(i, head) \ | ||
43 | for (i = rcu_dereference(head); i != NULL; i = rcu_dereference(i->next)) | ||
44 | |||
45 | static u32 nft_hash_rnd __read_mostly; | ||
46 | static bool nft_hash_rnd_initted __read_mostly; | ||
47 | |||
48 | static unsigned int nft_hash_data(const struct nft_data *data, | ||
49 | unsigned int hsize, unsigned int len) | ||
50 | { | ||
51 | unsigned int h; | ||
52 | |||
53 | h = jhash(data->data, len, nft_hash_rnd); | ||
54 | return h & (hsize - 1); | ||
55 | } | ||
56 | |||
57 | static bool nft_hash_lookup(const struct nft_set *set, | 32 | static bool nft_hash_lookup(const struct nft_set *set, |
58 | const struct nft_data *key, | 33 | const struct nft_data *key, |
59 | struct nft_data *data) | 34 | struct nft_data *data) |
60 | { | 35 | { |
61 | const struct nft_hash *priv = nft_set_priv(set); | 36 | const struct rhashtable *priv = nft_set_priv(set); |
62 | const struct nft_hash_table *tbl = rcu_dereference(priv->tbl); | ||
63 | const struct nft_hash_elem *he; | 37 | const struct nft_hash_elem *he; |
64 | unsigned int h; | ||
65 | |||
66 | h = nft_hash_data(key, tbl->size, set->klen); | ||
67 | nft_hash_for_each_entry_rcu(he, tbl->buckets[h]) { | ||
68 | if (nft_data_cmp(&he->key, key, set->klen)) | ||
69 | continue; | ||
70 | if (set->flags & NFT_SET_MAP) | ||
71 | nft_data_copy(data, he->data); | ||
72 | return true; | ||
73 | } | ||
74 | return false; | ||
75 | } | ||
76 | |||
77 | static void nft_hash_tbl_free(const struct nft_hash_table *tbl) | ||
78 | { | ||
79 | kvfree(tbl); | ||
80 | } | ||
81 | |||
82 | static unsigned int nft_hash_tbl_size(unsigned int nelem) | ||
83 | { | ||
84 | return max(roundup_pow_of_two(nelem * 4 / 3), NFT_HASH_MIN_SIZE); | ||
85 | } | ||
86 | |||
87 | static struct nft_hash_table *nft_hash_tbl_alloc(unsigned int nbuckets) | ||
88 | { | ||
89 | struct nft_hash_table *tbl; | ||
90 | size_t size; | ||
91 | |||
92 | size = sizeof(*tbl) + nbuckets * sizeof(tbl->buckets[0]); | ||
93 | tbl = kzalloc(size, GFP_KERNEL | __GFP_REPEAT | __GFP_NOWARN); | ||
94 | if (tbl == NULL) | ||
95 | tbl = vzalloc(size); | ||
96 | if (tbl == NULL) | ||
97 | return NULL; | ||
98 | tbl->size = nbuckets; | ||
99 | |||
100 | return tbl; | ||
101 | } | ||
102 | |||
103 | static void nft_hash_chain_unzip(const struct nft_set *set, | ||
104 | const struct nft_hash_table *ntbl, | ||
105 | struct nft_hash_table *tbl, unsigned int n) | ||
106 | { | ||
107 | struct nft_hash_elem *he, *last, *next; | ||
108 | unsigned int h; | ||
109 | |||
110 | he = nft_dereference(tbl->buckets[n]); | ||
111 | if (he == NULL) | ||
112 | return; | ||
113 | h = nft_hash_data(&he->key, ntbl->size, set->klen); | ||
114 | |||
115 | /* Find last element of first chain hashing to bucket h */ | ||
116 | last = he; | ||
117 | nft_hash_for_each_entry(he, he->next) { | ||
118 | if (nft_hash_data(&he->key, ntbl->size, set->klen) != h) | ||
119 | break; | ||
120 | last = he; | ||
121 | } | ||
122 | 38 | ||
123 | /* Unlink first chain from the old table */ | 39 | he = rhashtable_lookup(priv, key); |
124 | RCU_INIT_POINTER(tbl->buckets[n], last->next); | 40 | if (he && set->flags & NFT_SET_MAP) |
41 | nft_data_copy(data, he->data); | ||
125 | 42 | ||
126 | /* If end of chain reached, done */ | 43 | return !!he; |
127 | if (he == NULL) | ||
128 | return; | ||
129 | |||
130 | /* Find first element of second chain hashing to bucket h */ | ||
131 | next = NULL; | ||
132 | nft_hash_for_each_entry(he, he->next) { | ||
133 | if (nft_hash_data(&he->key, ntbl->size, set->klen) != h) | ||
134 | continue; | ||
135 | next = he; | ||
136 | break; | ||
137 | } | ||
138 | |||
139 | /* Link the two chains */ | ||
140 | RCU_INIT_POINTER(last->next, next); | ||
141 | } | ||
142 | |||
143 | static int nft_hash_tbl_expand(const struct nft_set *set, struct nft_hash *priv) | ||
144 | { | ||
145 | struct nft_hash_table *tbl = nft_dereference(priv->tbl), *ntbl; | ||
146 | struct nft_hash_elem *he; | ||
147 | unsigned int i, h; | ||
148 | bool complete; | ||
149 | |||
150 | ntbl = nft_hash_tbl_alloc(tbl->size * 2); | ||
151 | if (ntbl == NULL) | ||
152 | return -ENOMEM; | ||
153 | |||
154 | /* Link new table's buckets to first element in the old table | ||
155 | * hashing to the new bucket. | ||
156 | */ | ||
157 | for (i = 0; i < ntbl->size; i++) { | ||
158 | h = i < tbl->size ? i : i - tbl->size; | ||
159 | nft_hash_for_each_entry(he, tbl->buckets[h]) { | ||
160 | if (nft_hash_data(&he->key, ntbl->size, set->klen) != i) | ||
161 | continue; | ||
162 | RCU_INIT_POINTER(ntbl->buckets[i], he); | ||
163 | break; | ||
164 | } | ||
165 | } | ||
166 | |||
167 | /* Publish new table */ | ||
168 | rcu_assign_pointer(priv->tbl, ntbl); | ||
169 | |||
170 | /* Unzip interleaved hash chains */ | ||
171 | do { | ||
172 | /* Wait for readers to use new table/unzipped chains */ | ||
173 | synchronize_rcu(); | ||
174 | |||
175 | complete = true; | ||
176 | for (i = 0; i < tbl->size; i++) { | ||
177 | nft_hash_chain_unzip(set, ntbl, tbl, i); | ||
178 | if (tbl->buckets[i] != NULL) | ||
179 | complete = false; | ||
180 | } | ||
181 | } while (!complete); | ||
182 | |||
183 | nft_hash_tbl_free(tbl); | ||
184 | return 0; | ||
185 | } | ||
186 | |||
187 | static int nft_hash_tbl_shrink(const struct nft_set *set, struct nft_hash *priv) | ||
188 | { | ||
189 | struct nft_hash_table *tbl = nft_dereference(priv->tbl), *ntbl; | ||
190 | struct nft_hash_elem __rcu **pprev; | ||
191 | unsigned int i; | ||
192 | |||
193 | ntbl = nft_hash_tbl_alloc(tbl->size / 2); | ||
194 | if (ntbl == NULL) | ||
195 | return -ENOMEM; | ||
196 | |||
197 | for (i = 0; i < ntbl->size; i++) { | ||
198 | ntbl->buckets[i] = tbl->buckets[i]; | ||
199 | |||
200 | for (pprev = &ntbl->buckets[i]; *pprev != NULL; | ||
201 | pprev = &nft_dereference(*pprev)->next) | ||
202 | ; | ||
203 | RCU_INIT_POINTER(*pprev, tbl->buckets[i + ntbl->size]); | ||
204 | } | ||
205 | |||
206 | /* Publish new table */ | ||
207 | rcu_assign_pointer(priv->tbl, ntbl); | ||
208 | synchronize_rcu(); | ||
209 | |||
210 | nft_hash_tbl_free(tbl); | ||
211 | return 0; | ||
212 | } | 44 | } |
213 | 45 | ||
214 | static int nft_hash_insert(const struct nft_set *set, | 46 | static int nft_hash_insert(const struct nft_set *set, |
215 | const struct nft_set_elem *elem) | 47 | const struct nft_set_elem *elem) |
216 | { | 48 | { |
217 | struct nft_hash *priv = nft_set_priv(set); | 49 | struct rhashtable *priv = nft_set_priv(set); |
218 | struct nft_hash_table *tbl = nft_dereference(priv->tbl); | ||
219 | struct nft_hash_elem *he; | 50 | struct nft_hash_elem *he; |
220 | unsigned int size, h; | 51 | unsigned int size; |
221 | 52 | ||
222 | if (elem->flags != 0) | 53 | if (elem->flags != 0) |
223 | return -EINVAL; | 54 | return -EINVAL; |
@@ -234,13 +65,7 @@ static int nft_hash_insert(const struct nft_set *set, | |||
234 | if (set->flags & NFT_SET_MAP) | 65 | if (set->flags & NFT_SET_MAP) |
235 | nft_data_copy(he->data, &elem->data); | 66 | nft_data_copy(he->data, &elem->data); |
236 | 67 | ||
237 | h = nft_hash_data(&he->key, tbl->size, set->klen); | 68 | rhashtable_insert(priv, &he->node, GFP_KERNEL); |
238 | RCU_INIT_POINTER(he->next, tbl->buckets[h]); | ||
239 | rcu_assign_pointer(tbl->buckets[h], he); | ||
240 | |||
241 | /* Expand table when exceeding 75% load */ | ||
242 | if (set->nelems + 1 > tbl->size / 4 * 3) | ||
243 | nft_hash_tbl_expand(set, priv); | ||
244 | 69 | ||
245 | return 0; | 70 | return 0; |
246 | } | 71 | } |
@@ -257,36 +82,31 @@ static void nft_hash_elem_destroy(const struct nft_set *set, | |||
257 | static void nft_hash_remove(const struct nft_set *set, | 82 | static void nft_hash_remove(const struct nft_set *set, |
258 | const struct nft_set_elem *elem) | 83 | const struct nft_set_elem *elem) |
259 | { | 84 | { |
260 | struct nft_hash *priv = nft_set_priv(set); | 85 | struct rhashtable *priv = nft_set_priv(set); |
261 | struct nft_hash_table *tbl = nft_dereference(priv->tbl); | 86 | struct rhash_head *he, __rcu **pprev; |
262 | struct nft_hash_elem *he, __rcu **pprev; | ||
263 | 87 | ||
264 | pprev = elem->cookie; | 88 | pprev = elem->cookie; |
265 | he = nft_dereference((*pprev)); | 89 | he = rht_dereference((*pprev), priv); |
90 | |||
91 | rhashtable_remove_pprev(priv, he, pprev, GFP_KERNEL); | ||
266 | 92 | ||
267 | RCU_INIT_POINTER(*pprev, he->next); | ||
268 | synchronize_rcu(); | 93 | synchronize_rcu(); |
269 | kfree(he); | 94 | kfree(he); |
270 | |||
271 | /* Shrink table beneath 30% load */ | ||
272 | if (set->nelems - 1 < tbl->size * 3 / 10 && | ||
273 | tbl->size > NFT_HASH_MIN_SIZE) | ||
274 | nft_hash_tbl_shrink(set, priv); | ||
275 | } | 95 | } |
276 | 96 | ||
277 | static int nft_hash_get(const struct nft_set *set, struct nft_set_elem *elem) | 97 | static int nft_hash_get(const struct nft_set *set, struct nft_set_elem *elem) |
278 | { | 98 | { |
279 | const struct nft_hash *priv = nft_set_priv(set); | 99 | const struct rhashtable *priv = nft_set_priv(set); |
280 | const struct nft_hash_table *tbl = nft_dereference(priv->tbl); | 100 | const struct bucket_table *tbl = rht_dereference_rcu(priv->tbl, priv); |
281 | struct nft_hash_elem __rcu * const *pprev; | 101 | struct rhash_head __rcu * const *pprev; |
282 | struct nft_hash_elem *he; | 102 | struct nft_hash_elem *he; |
283 | unsigned int h; | 103 | u32 h; |
284 | 104 | ||
285 | h = nft_hash_data(&elem->key, tbl->size, set->klen); | 105 | h = rhashtable_hashfn(priv, &elem->key, set->klen); |
286 | pprev = &tbl->buckets[h]; | 106 | pprev = &tbl->buckets[h]; |
287 | nft_hash_for_each_entry(he, tbl->buckets[h]) { | 107 | rht_for_each_entry_rcu(he, tbl->buckets[h], node) { |
288 | if (nft_data_cmp(&he->key, &elem->key, set->klen)) { | 108 | if (nft_data_cmp(&he->key, &elem->key, set->klen)) { |
289 | pprev = &he->next; | 109 | pprev = &he->node.next; |
290 | continue; | 110 | continue; |
291 | } | 111 | } |
292 | 112 | ||
@@ -302,14 +122,15 @@ static int nft_hash_get(const struct nft_set *set, struct nft_set_elem *elem) | |||
302 | static void nft_hash_walk(const struct nft_ctx *ctx, const struct nft_set *set, | 122 | static void nft_hash_walk(const struct nft_ctx *ctx, const struct nft_set *set, |
303 | struct nft_set_iter *iter) | 123 | struct nft_set_iter *iter) |
304 | { | 124 | { |
305 | const struct nft_hash *priv = nft_set_priv(set); | 125 | const struct rhashtable *priv = nft_set_priv(set); |
306 | const struct nft_hash_table *tbl = nft_dereference(priv->tbl); | 126 | const struct bucket_table *tbl; |
307 | const struct nft_hash_elem *he; | 127 | const struct nft_hash_elem *he; |
308 | struct nft_set_elem elem; | 128 | struct nft_set_elem elem; |
309 | unsigned int i; | 129 | unsigned int i; |
310 | 130 | ||
131 | tbl = rht_dereference_rcu(priv->tbl, priv); | ||
311 | for (i = 0; i < tbl->size; i++) { | 132 | for (i = 0; i < tbl->size; i++) { |
312 | nft_hash_for_each_entry(he, tbl->buckets[i]) { | 133 | rht_for_each_entry_rcu(he, tbl->buckets[i], node) { |
313 | if (iter->count < iter->skip) | 134 | if (iter->count < iter->skip) |
314 | goto cont; | 135 | goto cont; |
315 | 136 | ||
@@ -329,48 +150,48 @@ cont: | |||
329 | 150 | ||
330 | static unsigned int nft_hash_privsize(const struct nlattr * const nla[]) | 151 | static unsigned int nft_hash_privsize(const struct nlattr * const nla[]) |
331 | { | 152 | { |
332 | return sizeof(struct nft_hash); | 153 | return sizeof(struct rhashtable); |
154 | } | ||
155 | |||
156 | static int lockdep_nfnl_lock_is_held(void) | ||
157 | { | ||
158 | return lockdep_nfnl_is_held(NFNL_SUBSYS_NFTABLES); | ||
333 | } | 159 | } |
334 | 160 | ||
335 | static int nft_hash_init(const struct nft_set *set, | 161 | static int nft_hash_init(const struct nft_set *set, |
336 | const struct nft_set_desc *desc, | 162 | const struct nft_set_desc *desc, |
337 | const struct nlattr * const tb[]) | 163 | const struct nlattr * const tb[]) |
338 | { | 164 | { |
339 | struct nft_hash *priv = nft_set_priv(set); | 165 | struct rhashtable *priv = nft_set_priv(set); |
340 | struct nft_hash_table *tbl; | 166 | struct rhashtable_params params = { |
341 | unsigned int size; | 167 | .nelem_hint = desc->size ? : NFT_HASH_ELEMENT_HINT, |
168 | .head_offset = offsetof(struct nft_hash_elem, node), | ||
169 | .key_offset = offsetof(struct nft_hash_elem, key), | ||
170 | .key_len = set->klen, | ||
171 | .hashfn = jhash, | ||
172 | .grow_decision = rht_grow_above_75, | ||
173 | .shrink_decision = rht_shrink_below_30, | ||
174 | .mutex_is_held = lockdep_nfnl_lock_is_held, | ||
175 | }; | ||
342 | 176 | ||
343 | if (unlikely(!nft_hash_rnd_initted)) { | 177 | return rhashtable_init(priv, ¶ms); |
344 | get_random_bytes(&nft_hash_rnd, 4); | ||
345 | nft_hash_rnd_initted = true; | ||
346 | } | ||
347 | |||
348 | size = NFT_HASH_MIN_SIZE; | ||
349 | if (desc->size) | ||
350 | size = nft_hash_tbl_size(desc->size); | ||
351 | |||
352 | tbl = nft_hash_tbl_alloc(size); | ||
353 | if (tbl == NULL) | ||
354 | return -ENOMEM; | ||
355 | RCU_INIT_POINTER(priv->tbl, tbl); | ||
356 | return 0; | ||
357 | } | 178 | } |
358 | 179 | ||
359 | static void nft_hash_destroy(const struct nft_set *set) | 180 | static void nft_hash_destroy(const struct nft_set *set) |
360 | { | 181 | { |
361 | const struct nft_hash *priv = nft_set_priv(set); | 182 | const struct rhashtable *priv = nft_set_priv(set); |
362 | const struct nft_hash_table *tbl = nft_dereference(priv->tbl); | 183 | const struct bucket_table *tbl = priv->tbl; |
363 | struct nft_hash_elem *he, *next; | 184 | struct nft_hash_elem *he, *next; |
364 | unsigned int i; | 185 | unsigned int i; |
365 | 186 | ||
366 | for (i = 0; i < tbl->size; i++) { | 187 | for (i = 0; i < tbl->size; i++) { |
367 | for (he = nft_dereference(tbl->buckets[i]); he != NULL; | 188 | for (he = rht_entry(tbl->buckets[i], struct nft_hash_elem, node); |
368 | he = next) { | 189 | he != NULL; he = next) { |
369 | next = nft_dereference(he->next); | 190 | next = rht_entry(he->node.next, struct nft_hash_elem, node); |
370 | nft_hash_elem_destroy(set, he); | 191 | nft_hash_elem_destroy(set, he); |
371 | } | 192 | } |
372 | } | 193 | } |
373 | kfree(tbl); | 194 | rhashtable_destroy(priv); |
374 | } | 195 | } |
375 | 196 | ||
376 | static bool nft_hash_estimate(const struct nft_set_desc *desc, u32 features, | 197 | static bool nft_hash_estimate(const struct nft_set_desc *desc, u32 features, |
@@ -383,8 +204,8 @@ static bool nft_hash_estimate(const struct nft_set_desc *desc, u32 features, | |||
383 | esize += FIELD_SIZEOF(struct nft_hash_elem, data[0]); | 204 | esize += FIELD_SIZEOF(struct nft_hash_elem, data[0]); |
384 | 205 | ||
385 | if (desc->size) { | 206 | if (desc->size) { |
386 | est->size = sizeof(struct nft_hash) + | 207 | est->size = sizeof(struct rhashtable) + |
387 | nft_hash_tbl_size(desc->size) * | 208 | roundup_pow_of_two(desc->size * 4 / 3) * |
388 | sizeof(struct nft_hash_elem *) + | 209 | sizeof(struct nft_hash_elem *) + |
389 | desc->size * esize; | 210 | desc->size * esize; |
390 | } else { | 211 | } else { |
diff --git a/net/netfilter/nft_log.c b/net/netfilter/nft_log.c index 10cfb156cdf4..bde05f28cf14 100644 --- a/net/netfilter/nft_log.c +++ b/net/netfilter/nft_log.c | |||
@@ -1,5 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net> | 2 | * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net> |
3 | * Copyright (c) 2012-2014 Pablo Neira Ayuso <pablo@netfilter.org> | ||
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 |
@@ -41,6 +42,8 @@ static const struct nla_policy nft_log_policy[NFTA_LOG_MAX + 1] = { | |||
41 | [NFTA_LOG_PREFIX] = { .type = NLA_STRING }, | 42 | [NFTA_LOG_PREFIX] = { .type = NLA_STRING }, |
42 | [NFTA_LOG_SNAPLEN] = { .type = NLA_U32 }, | 43 | [NFTA_LOG_SNAPLEN] = { .type = NLA_U32 }, |
43 | [NFTA_LOG_QTHRESHOLD] = { .type = NLA_U16 }, | 44 | [NFTA_LOG_QTHRESHOLD] = { .type = NLA_U16 }, |
45 | [NFTA_LOG_LEVEL] = { .type = NLA_U32 }, | ||
46 | [NFTA_LOG_FLAGS] = { .type = NLA_U32 }, | ||
44 | }; | 47 | }; |
45 | 48 | ||
46 | static int nft_log_init(const struct nft_ctx *ctx, | 49 | static int nft_log_init(const struct nft_ctx *ctx, |
@@ -50,6 +53,7 @@ static int nft_log_init(const struct nft_ctx *ctx, | |||
50 | struct nft_log *priv = nft_expr_priv(expr); | 53 | struct nft_log *priv = nft_expr_priv(expr); |
51 | struct nf_loginfo *li = &priv->loginfo; | 54 | struct nf_loginfo *li = &priv->loginfo; |
52 | const struct nlattr *nla; | 55 | const struct nlattr *nla; |
56 | int ret; | ||
53 | 57 | ||
54 | nla = tb[NFTA_LOG_PREFIX]; | 58 | nla = tb[NFTA_LOG_PREFIX]; |
55 | if (nla != NULL) { | 59 | if (nla != NULL) { |
@@ -57,30 +61,74 @@ static int nft_log_init(const struct nft_ctx *ctx, | |||
57 | if (priv->prefix == NULL) | 61 | if (priv->prefix == NULL) |
58 | return -ENOMEM; | 62 | return -ENOMEM; |
59 | nla_strlcpy(priv->prefix, nla, nla_len(nla) + 1); | 63 | nla_strlcpy(priv->prefix, nla, nla_len(nla) + 1); |
60 | } else | 64 | } else { |
61 | priv->prefix = (char *)nft_log_null_prefix; | 65 | priv->prefix = (char *)nft_log_null_prefix; |
66 | } | ||
62 | 67 | ||
63 | li->type = NF_LOG_TYPE_ULOG; | 68 | li->type = NF_LOG_TYPE_LOG; |
69 | if (tb[NFTA_LOG_LEVEL] != NULL && | ||
70 | tb[NFTA_LOG_GROUP] != NULL) | ||
71 | return -EINVAL; | ||
64 | if (tb[NFTA_LOG_GROUP] != NULL) | 72 | if (tb[NFTA_LOG_GROUP] != NULL) |
73 | li->type = NF_LOG_TYPE_ULOG; | ||
74 | |||
75 | switch (li->type) { | ||
76 | case NF_LOG_TYPE_LOG: | ||
77 | if (tb[NFTA_LOG_LEVEL] != NULL) { | ||
78 | li->u.log.level = | ||
79 | ntohl(nla_get_be32(tb[NFTA_LOG_LEVEL])); | ||
80 | } else { | ||
81 | li->u.log.level = 4; | ||
82 | } | ||
83 | if (tb[NFTA_LOG_FLAGS] != NULL) { | ||
84 | li->u.log.logflags = | ||
85 | ntohl(nla_get_be32(tb[NFTA_LOG_FLAGS])); | ||
86 | } | ||
87 | break; | ||
88 | case NF_LOG_TYPE_ULOG: | ||
65 | li->u.ulog.group = ntohs(nla_get_be16(tb[NFTA_LOG_GROUP])); | 89 | li->u.ulog.group = ntohs(nla_get_be16(tb[NFTA_LOG_GROUP])); |
90 | if (tb[NFTA_LOG_SNAPLEN] != NULL) { | ||
91 | li->u.ulog.copy_len = | ||
92 | ntohl(nla_get_be32(tb[NFTA_LOG_SNAPLEN])); | ||
93 | } | ||
94 | if (tb[NFTA_LOG_QTHRESHOLD] != NULL) { | ||
95 | li->u.ulog.qthreshold = | ||
96 | ntohs(nla_get_be16(tb[NFTA_LOG_QTHRESHOLD])); | ||
97 | } | ||
98 | break; | ||
99 | } | ||
66 | 100 | ||
67 | if (tb[NFTA_LOG_SNAPLEN] != NULL) | 101 | if (ctx->afi->family == NFPROTO_INET) { |
68 | li->u.ulog.copy_len = ntohl(nla_get_be32(tb[NFTA_LOG_SNAPLEN])); | 102 | ret = nf_logger_find_get(NFPROTO_IPV4, li->type); |
69 | if (tb[NFTA_LOG_QTHRESHOLD] != NULL) { | 103 | if (ret < 0) |
70 | li->u.ulog.qthreshold = | 104 | return ret; |
71 | ntohs(nla_get_be16(tb[NFTA_LOG_QTHRESHOLD])); | 105 | |
106 | ret = nf_logger_find_get(NFPROTO_IPV6, li->type); | ||
107 | if (ret < 0) { | ||
108 | nf_logger_put(NFPROTO_IPV4, li->type); | ||
109 | return ret; | ||
110 | } | ||
111 | return 0; | ||
72 | } | 112 | } |
73 | 113 | ||
74 | return 0; | 114 | return nf_logger_find_get(ctx->afi->family, li->type); |
75 | } | 115 | } |
76 | 116 | ||
77 | static void nft_log_destroy(const struct nft_ctx *ctx, | 117 | static void nft_log_destroy(const struct nft_ctx *ctx, |
78 | const struct nft_expr *expr) | 118 | const struct nft_expr *expr) |
79 | { | 119 | { |
80 | struct nft_log *priv = nft_expr_priv(expr); | 120 | struct nft_log *priv = nft_expr_priv(expr); |
121 | struct nf_loginfo *li = &priv->loginfo; | ||
81 | 122 | ||
82 | if (priv->prefix != nft_log_null_prefix) | 123 | if (priv->prefix != nft_log_null_prefix) |
83 | kfree(priv->prefix); | 124 | kfree(priv->prefix); |
125 | |||
126 | if (ctx->afi->family == NFPROTO_INET) { | ||
127 | nf_logger_put(NFPROTO_IPV4, li->type); | ||
128 | nf_logger_put(NFPROTO_IPV6, li->type); | ||
129 | } else { | ||
130 | nf_logger_put(ctx->afi->family, li->type); | ||
131 | } | ||
84 | } | 132 | } |
85 | 133 | ||
86 | static int nft_log_dump(struct sk_buff *skb, const struct nft_expr *expr) | 134 | static int nft_log_dump(struct sk_buff *skb, const struct nft_expr *expr) |
@@ -91,17 +139,33 @@ static int nft_log_dump(struct sk_buff *skb, const struct nft_expr *expr) | |||
91 | if (priv->prefix != nft_log_null_prefix) | 139 | if (priv->prefix != nft_log_null_prefix) |
92 | if (nla_put_string(skb, NFTA_LOG_PREFIX, priv->prefix)) | 140 | if (nla_put_string(skb, NFTA_LOG_PREFIX, priv->prefix)) |
93 | goto nla_put_failure; | 141 | goto nla_put_failure; |
94 | if (li->u.ulog.group) | 142 | switch (li->type) { |
95 | if (nla_put_be16(skb, NFTA_LOG_GROUP, htons(li->u.ulog.group))) | 143 | case NF_LOG_TYPE_LOG: |
96 | goto nla_put_failure; | 144 | if (nla_put_be32(skb, NFTA_LOG_LEVEL, htonl(li->u.log.level))) |
97 | if (li->u.ulog.copy_len) | ||
98 | if (nla_put_be32(skb, NFTA_LOG_SNAPLEN, | ||
99 | htonl(li->u.ulog.copy_len))) | ||
100 | goto nla_put_failure; | 145 | goto nla_put_failure; |
101 | if (li->u.ulog.qthreshold) | 146 | |
102 | if (nla_put_be16(skb, NFTA_LOG_QTHRESHOLD, | 147 | if (li->u.log.logflags) { |
103 | htons(li->u.ulog.qthreshold))) | 148 | if (nla_put_be32(skb, NFTA_LOG_FLAGS, |
149 | htonl(li->u.log.logflags))) | ||
150 | goto nla_put_failure; | ||
151 | } | ||
152 | break; | ||
153 | case NF_LOG_TYPE_ULOG: | ||
154 | if (nla_put_be16(skb, NFTA_LOG_GROUP, htons(li->u.ulog.group))) | ||
104 | goto nla_put_failure; | 155 | goto nla_put_failure; |
156 | |||
157 | if (li->u.ulog.copy_len) { | ||
158 | if (nla_put_be32(skb, NFTA_LOG_SNAPLEN, | ||
159 | htonl(li->u.ulog.copy_len))) | ||
160 | goto nla_put_failure; | ||
161 | } | ||
162 | if (li->u.ulog.qthreshold) { | ||
163 | if (nla_put_be16(skb, NFTA_LOG_QTHRESHOLD, | ||
164 | htons(li->u.ulog.qthreshold))) | ||
165 | goto nla_put_failure; | ||
166 | } | ||
167 | break; | ||
168 | } | ||
105 | return 0; | 169 | return 0; |
106 | 170 | ||
107 | nla_put_failure: | 171 | nla_put_failure: |
diff --git a/net/netfilter/nft_rbtree.c b/net/netfilter/nft_rbtree.c index e1836ff88199..46214f245665 100644 --- a/net/netfilter/nft_rbtree.c +++ b/net/netfilter/nft_rbtree.c | |||
@@ -234,13 +234,11 @@ static void nft_rbtree_destroy(const struct nft_set *set) | |||
234 | struct nft_rbtree_elem *rbe; | 234 | struct nft_rbtree_elem *rbe; |
235 | struct rb_node *node; | 235 | struct rb_node *node; |
236 | 236 | ||
237 | spin_lock_bh(&nft_rbtree_lock); | ||
238 | while ((node = priv->root.rb_node) != NULL) { | 237 | while ((node = priv->root.rb_node) != NULL) { |
239 | rb_erase(node, &priv->root); | 238 | rb_erase(node, &priv->root); |
240 | rbe = rb_entry(node, struct nft_rbtree_elem, node); | 239 | rbe = rb_entry(node, struct nft_rbtree_elem, node); |
241 | nft_rbtree_elem_destroy(set, rbe); | 240 | nft_rbtree_elem_destroy(set, rbe); |
242 | } | 241 | } |
243 | spin_unlock_bh(&nft_rbtree_lock); | ||
244 | } | 242 | } |
245 | 243 | ||
246 | static bool nft_rbtree_estimate(const struct nft_set_desc *desc, u32 features, | 244 | static bool nft_rbtree_estimate(const struct nft_set_desc *desc, u32 features, |
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 227aa11e8409..272ae4d6fdf4 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c | |||
@@ -71,18 +71,14 @@ static const char *const xt_prefix[NFPROTO_NUMPROTO] = { | |||
71 | static const unsigned int xt_jumpstack_multiplier = 2; | 71 | static const unsigned int xt_jumpstack_multiplier = 2; |
72 | 72 | ||
73 | /* Registration hooks for targets. */ | 73 | /* Registration hooks for targets. */ |
74 | int | 74 | int xt_register_target(struct xt_target *target) |
75 | xt_register_target(struct xt_target *target) | ||
76 | { | 75 | { |
77 | u_int8_t af = target->family; | 76 | u_int8_t af = target->family; |
78 | int ret; | ||
79 | 77 | ||
80 | ret = mutex_lock_interruptible(&xt[af].mutex); | 78 | mutex_lock(&xt[af].mutex); |
81 | if (ret != 0) | ||
82 | return ret; | ||
83 | list_add(&target->list, &xt[af].target); | 79 | list_add(&target->list, &xt[af].target); |
84 | mutex_unlock(&xt[af].mutex); | 80 | mutex_unlock(&xt[af].mutex); |
85 | return ret; | 81 | return 0; |
86 | } | 82 | } |
87 | EXPORT_SYMBOL(xt_register_target); | 83 | EXPORT_SYMBOL(xt_register_target); |
88 | 84 | ||
@@ -125,20 +121,14 @@ xt_unregister_targets(struct xt_target *target, unsigned int n) | |||
125 | } | 121 | } |
126 | EXPORT_SYMBOL(xt_unregister_targets); | 122 | EXPORT_SYMBOL(xt_unregister_targets); |
127 | 123 | ||
128 | int | 124 | int xt_register_match(struct xt_match *match) |
129 | xt_register_match(struct xt_match *match) | ||
130 | { | 125 | { |
131 | u_int8_t af = match->family; | 126 | u_int8_t af = match->family; |
132 | int ret; | ||
133 | |||
134 | ret = mutex_lock_interruptible(&xt[af].mutex); | ||
135 | if (ret != 0) | ||
136 | return ret; | ||
137 | 127 | ||
128 | mutex_lock(&xt[af].mutex); | ||
138 | list_add(&match->list, &xt[af].match); | 129 | list_add(&match->list, &xt[af].match); |
139 | mutex_unlock(&xt[af].mutex); | 130 | mutex_unlock(&xt[af].mutex); |
140 | 131 | return 0; | |
141 | return ret; | ||
142 | } | 132 | } |
143 | EXPORT_SYMBOL(xt_register_match); | 133 | EXPORT_SYMBOL(xt_register_match); |
144 | 134 | ||
@@ -194,9 +184,7 @@ struct xt_match *xt_find_match(u8 af, const char *name, u8 revision) | |||
194 | struct xt_match *m; | 184 | struct xt_match *m; |
195 | int err = -ENOENT; | 185 | int err = -ENOENT; |
196 | 186 | ||
197 | if (mutex_lock_interruptible(&xt[af].mutex) != 0) | 187 | mutex_lock(&xt[af].mutex); |
198 | return ERR_PTR(-EINTR); | ||
199 | |||
200 | list_for_each_entry(m, &xt[af].match, list) { | 188 | list_for_each_entry(m, &xt[af].match, list) { |
201 | if (strcmp(m->name, name) == 0) { | 189 | if (strcmp(m->name, name) == 0) { |
202 | if (m->revision == revision) { | 190 | if (m->revision == revision) { |
@@ -239,9 +227,7 @@ struct xt_target *xt_find_target(u8 af, const char *name, u8 revision) | |||
239 | struct xt_target *t; | 227 | struct xt_target *t; |
240 | int err = -ENOENT; | 228 | int err = -ENOENT; |
241 | 229 | ||
242 | if (mutex_lock_interruptible(&xt[af].mutex) != 0) | 230 | mutex_lock(&xt[af].mutex); |
243 | return ERR_PTR(-EINTR); | ||
244 | |||
245 | list_for_each_entry(t, &xt[af].target, list) { | 231 | list_for_each_entry(t, &xt[af].target, list) { |
246 | if (strcmp(t->name, name) == 0) { | 232 | if (strcmp(t->name, name) == 0) { |
247 | if (t->revision == revision) { | 233 | if (t->revision == revision) { |
@@ -323,10 +309,7 @@ int xt_find_revision(u8 af, const char *name, u8 revision, int target, | |||
323 | { | 309 | { |
324 | int have_rev, best = -1; | 310 | int have_rev, best = -1; |
325 | 311 | ||
326 | if (mutex_lock_interruptible(&xt[af].mutex) != 0) { | 312 | mutex_lock(&xt[af].mutex); |
327 | *err = -EINTR; | ||
328 | return 1; | ||
329 | } | ||
330 | if (target == 1) | 313 | if (target == 1) |
331 | have_rev = target_revfn(af, name, revision, &best); | 314 | have_rev = target_revfn(af, name, revision, &best); |
332 | else | 315 | else |
@@ -711,28 +694,15 @@ void xt_free_table_info(struct xt_table_info *info) | |||
711 | { | 694 | { |
712 | int cpu; | 695 | int cpu; |
713 | 696 | ||
714 | for_each_possible_cpu(cpu) { | 697 | for_each_possible_cpu(cpu) |
715 | if (info->size <= PAGE_SIZE) | 698 | kvfree(info->entries[cpu]); |
716 | kfree(info->entries[cpu]); | ||
717 | else | ||
718 | vfree(info->entries[cpu]); | ||
719 | } | ||
720 | 699 | ||
721 | if (info->jumpstack != NULL) { | 700 | if (info->jumpstack != NULL) { |
722 | if (sizeof(void *) * info->stacksize > PAGE_SIZE) { | 701 | for_each_possible_cpu(cpu) |
723 | for_each_possible_cpu(cpu) | 702 | kvfree(info->jumpstack[cpu]); |
724 | vfree(info->jumpstack[cpu]); | 703 | kvfree(info->jumpstack); |
725 | } else { | ||
726 | for_each_possible_cpu(cpu) | ||
727 | kfree(info->jumpstack[cpu]); | ||
728 | } | ||
729 | } | 704 | } |
730 | 705 | ||
731 | if (sizeof(void **) * nr_cpu_ids > PAGE_SIZE) | ||
732 | vfree(info->jumpstack); | ||
733 | else | ||
734 | kfree(info->jumpstack); | ||
735 | |||
736 | free_percpu(info->stackptr); | 706 | free_percpu(info->stackptr); |
737 | 707 | ||
738 | kfree(info); | 708 | kfree(info); |
@@ -745,9 +715,7 @@ struct xt_table *xt_find_table_lock(struct net *net, u_int8_t af, | |||
745 | { | 715 | { |
746 | struct xt_table *t; | 716 | struct xt_table *t; |
747 | 717 | ||
748 | if (mutex_lock_interruptible(&xt[af].mutex) != 0) | 718 | mutex_lock(&xt[af].mutex); |
749 | return ERR_PTR(-EINTR); | ||
750 | |||
751 | list_for_each_entry(t, &net->xt.tables[af], list) | 719 | list_for_each_entry(t, &net->xt.tables[af], list) |
752 | if (strcmp(t->name, name) == 0 && try_module_get(t->me)) | 720 | if (strcmp(t->name, name) == 0 && try_module_get(t->me)) |
753 | return t; | 721 | return t; |
@@ -896,10 +864,7 @@ struct xt_table *xt_register_table(struct net *net, | |||
896 | goto out; | 864 | goto out; |
897 | } | 865 | } |
898 | 866 | ||
899 | ret = mutex_lock_interruptible(&xt[table->af].mutex); | 867 | mutex_lock(&xt[table->af].mutex); |
900 | if (ret != 0) | ||
901 | goto out_free; | ||
902 | |||
903 | /* Don't autoload: we'd eat our tail... */ | 868 | /* Don't autoload: we'd eat our tail... */ |
904 | list_for_each_entry(t, &net->xt.tables[table->af], list) { | 869 | list_for_each_entry(t, &net->xt.tables[table->af], list) { |
905 | if (strcmp(t->name, table->name) == 0) { | 870 | if (strcmp(t->name, table->name) == 0) { |
@@ -924,9 +889,8 @@ struct xt_table *xt_register_table(struct net *net, | |||
924 | mutex_unlock(&xt[table->af].mutex); | 889 | mutex_unlock(&xt[table->af].mutex); |
925 | return table; | 890 | return table; |
926 | 891 | ||
927 | unlock: | 892 | unlock: |
928 | mutex_unlock(&xt[table->af].mutex); | 893 | mutex_unlock(&xt[table->af].mutex); |
929 | out_free: | ||
930 | kfree(table); | 894 | kfree(table); |
931 | out: | 895 | out: |
932 | return ERR_PTR(ret); | 896 | return ERR_PTR(ret); |
diff --git a/net/netfilter/xt_LED.c b/net/netfilter/xt_LED.c index 993de2ba89d3..3ba31c194cce 100644 --- a/net/netfilter/xt_LED.c +++ b/net/netfilter/xt_LED.c | |||
@@ -50,11 +50,14 @@ struct xt_led_info_internal { | |||
50 | struct timer_list timer; | 50 | struct timer_list timer; |
51 | }; | 51 | }; |
52 | 52 | ||
53 | #define XT_LED_BLINK_DELAY 50 /* ms */ | ||
54 | |||
53 | static unsigned int | 55 | static unsigned int |
54 | led_tg(struct sk_buff *skb, const struct xt_action_param *par) | 56 | led_tg(struct sk_buff *skb, const struct xt_action_param *par) |
55 | { | 57 | { |
56 | const struct xt_led_info *ledinfo = par->targinfo; | 58 | const struct xt_led_info *ledinfo = par->targinfo; |
57 | struct xt_led_info_internal *ledinternal = ledinfo->internal_data; | 59 | struct xt_led_info_internal *ledinternal = ledinfo->internal_data; |
60 | unsigned long led_delay = XT_LED_BLINK_DELAY; | ||
58 | 61 | ||
59 | /* | 62 | /* |
60 | * If "always blink" is enabled, and there's still some time until the | 63 | * If "always blink" is enabled, and there's still some time until the |
@@ -62,9 +65,10 @@ led_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
62 | */ | 65 | */ |
63 | if ((ledinfo->delay > 0) && ledinfo->always_blink && | 66 | if ((ledinfo->delay > 0) && ledinfo->always_blink && |
64 | timer_pending(&ledinternal->timer)) | 67 | timer_pending(&ledinternal->timer)) |
65 | led_trigger_event(&ledinternal->netfilter_led_trigger, LED_OFF); | 68 | led_trigger_blink_oneshot(&ledinternal->netfilter_led_trigger, |
66 | 69 | &led_delay, &led_delay, 1); | |
67 | led_trigger_event(&ledinternal->netfilter_led_trigger, LED_FULL); | 70 | else |
71 | led_trigger_event(&ledinternal->netfilter_led_trigger, LED_FULL); | ||
68 | 72 | ||
69 | /* If there's a positive delay, start/update the timer */ | 73 | /* If there's a positive delay, start/update the timer */ |
70 | if (ledinfo->delay > 0) { | 74 | if (ledinfo->delay > 0) { |
@@ -133,9 +137,7 @@ static int led_tg_check(const struct xt_tgchk_param *par) | |||
133 | 137 | ||
134 | err = led_trigger_register(&ledinternal->netfilter_led_trigger); | 138 | err = led_trigger_register(&ledinternal->netfilter_led_trigger); |
135 | if (err) { | 139 | if (err) { |
136 | pr_warning("led_trigger_register() failed\n"); | 140 | pr_err("Trigger name is already in use.\n"); |
137 | if (err == -EEXIST) | ||
138 | pr_warning("Trigger name is already in use.\n"); | ||
139 | goto exit_alloc; | 141 | goto exit_alloc; |
140 | } | 142 | } |
141 | 143 | ||
diff --git a/net/netfilter/xt_LOG.c b/net/netfilter/xt_LOG.c index 5ab24843370a..c13b79440ede 100644 --- a/net/netfilter/xt_LOG.c +++ b/net/netfilter/xt_LOG.c | |||
@@ -27,806 +27,6 @@ | |||
27 | #include <linux/netfilter/xt_LOG.h> | 27 | #include <linux/netfilter/xt_LOG.h> |
28 | #include <linux/netfilter_ipv6/ip6_tables.h> | 28 | #include <linux/netfilter_ipv6/ip6_tables.h> |
29 | #include <net/netfilter/nf_log.h> | 29 | #include <net/netfilter/nf_log.h> |
30 | #include <net/netfilter/xt_log.h> | ||
31 | |||
32 | static struct nf_loginfo default_loginfo = { | ||
33 | .type = NF_LOG_TYPE_LOG, | ||
34 | .u = { | ||
35 | .log = { | ||
36 | .level = 5, | ||
37 | .logflags = NF_LOG_MASK, | ||
38 | }, | ||
39 | }, | ||
40 | }; | ||
41 | |||
42 | static int dump_udp_header(struct sbuff *m, const struct sk_buff *skb, | ||
43 | u8 proto, int fragment, unsigned int offset) | ||
44 | { | ||
45 | struct udphdr _udph; | ||
46 | const struct udphdr *uh; | ||
47 | |||
48 | if (proto == IPPROTO_UDP) | ||
49 | /* Max length: 10 "PROTO=UDP " */ | ||
50 | sb_add(m, "PROTO=UDP "); | ||
51 | else /* Max length: 14 "PROTO=UDPLITE " */ | ||
52 | sb_add(m, "PROTO=UDPLITE "); | ||
53 | |||
54 | if (fragment) | ||
55 | goto out; | ||
56 | |||
57 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ | ||
58 | uh = skb_header_pointer(skb, offset, sizeof(_udph), &_udph); | ||
59 | if (uh == NULL) { | ||
60 | sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - offset); | ||
61 | |||
62 | return 1; | ||
63 | } | ||
64 | |||
65 | /* Max length: 20 "SPT=65535 DPT=65535 " */ | ||
66 | sb_add(m, "SPT=%u DPT=%u LEN=%u ", ntohs(uh->source), ntohs(uh->dest), | ||
67 | ntohs(uh->len)); | ||
68 | |||
69 | out: | ||
70 | return 0; | ||
71 | } | ||
72 | |||
73 | static int dump_tcp_header(struct sbuff *m, const struct sk_buff *skb, | ||
74 | u8 proto, int fragment, unsigned int offset, | ||
75 | unsigned int logflags) | ||
76 | { | ||
77 | struct tcphdr _tcph; | ||
78 | const struct tcphdr *th; | ||
79 | |||
80 | /* Max length: 10 "PROTO=TCP " */ | ||
81 | sb_add(m, "PROTO=TCP "); | ||
82 | |||
83 | if (fragment) | ||
84 | return 0; | ||
85 | |||
86 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ | ||
87 | th = skb_header_pointer(skb, offset, sizeof(_tcph), &_tcph); | ||
88 | if (th == NULL) { | ||
89 | sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - offset); | ||
90 | return 1; | ||
91 | } | ||
92 | |||
93 | /* Max length: 20 "SPT=65535 DPT=65535 " */ | ||
94 | sb_add(m, "SPT=%u DPT=%u ", ntohs(th->source), ntohs(th->dest)); | ||
95 | /* Max length: 30 "SEQ=4294967295 ACK=4294967295 " */ | ||
96 | if (logflags & XT_LOG_TCPSEQ) | ||
97 | sb_add(m, "SEQ=%u ACK=%u ", ntohl(th->seq), ntohl(th->ack_seq)); | ||
98 | |||
99 | /* Max length: 13 "WINDOW=65535 " */ | ||
100 | sb_add(m, "WINDOW=%u ", ntohs(th->window)); | ||
101 | /* Max length: 9 "RES=0x3C " */ | ||
102 | sb_add(m, "RES=0x%02x ", (u_int8_t)(ntohl(tcp_flag_word(th) & | ||
103 | TCP_RESERVED_BITS) >> 22)); | ||
104 | /* Max length: 32 "CWR ECE URG ACK PSH RST SYN FIN " */ | ||
105 | if (th->cwr) | ||
106 | sb_add(m, "CWR "); | ||
107 | if (th->ece) | ||
108 | sb_add(m, "ECE "); | ||
109 | if (th->urg) | ||
110 | sb_add(m, "URG "); | ||
111 | if (th->ack) | ||
112 | sb_add(m, "ACK "); | ||
113 | if (th->psh) | ||
114 | sb_add(m, "PSH "); | ||
115 | if (th->rst) | ||
116 | sb_add(m, "RST "); | ||
117 | if (th->syn) | ||
118 | sb_add(m, "SYN "); | ||
119 | if (th->fin) | ||
120 | sb_add(m, "FIN "); | ||
121 | /* Max length: 11 "URGP=65535 " */ | ||
122 | sb_add(m, "URGP=%u ", ntohs(th->urg_ptr)); | ||
123 | |||
124 | if ((logflags & XT_LOG_TCPOPT) && th->doff*4 > sizeof(struct tcphdr)) { | ||
125 | u_int8_t _opt[60 - sizeof(struct tcphdr)]; | ||
126 | const u_int8_t *op; | ||
127 | unsigned int i; | ||
128 | unsigned int optsize = th->doff*4 - sizeof(struct tcphdr); | ||
129 | |||
130 | op = skb_header_pointer(skb, offset + sizeof(struct tcphdr), | ||
131 | optsize, _opt); | ||
132 | if (op == NULL) { | ||
133 | sb_add(m, "OPT (TRUNCATED)"); | ||
134 | return 1; | ||
135 | } | ||
136 | |||
137 | /* Max length: 127 "OPT (" 15*4*2chars ") " */ | ||
138 | sb_add(m, "OPT ("); | ||
139 | for (i = 0; i < optsize; i++) | ||
140 | sb_add(m, "%02X", op[i]); | ||
141 | |||
142 | sb_add(m, ") "); | ||
143 | } | ||
144 | |||
145 | return 0; | ||
146 | } | ||
147 | |||
148 | static void dump_sk_uid_gid(struct sbuff *m, struct sock *sk) | ||
149 | { | ||
150 | if (!sk || sk->sk_state == TCP_TIME_WAIT) | ||
151 | return; | ||
152 | |||
153 | read_lock_bh(&sk->sk_callback_lock); | ||
154 | if (sk->sk_socket && sk->sk_socket->file) { | ||
155 | const struct cred *cred = sk->sk_socket->file->f_cred; | ||
156 | sb_add(m, "UID=%u GID=%u ", | ||
157 | from_kuid_munged(&init_user_ns, cred->fsuid), | ||
158 | from_kgid_munged(&init_user_ns, cred->fsgid)); | ||
159 | } | ||
160 | read_unlock_bh(&sk->sk_callback_lock); | ||
161 | } | ||
162 | |||
163 | /* One level of recursion won't kill us */ | ||
164 | static void dump_ipv4_packet(struct sbuff *m, | ||
165 | const struct nf_loginfo *info, | ||
166 | const struct sk_buff *skb, | ||
167 | unsigned int iphoff) | ||
168 | { | ||
169 | struct iphdr _iph; | ||
170 | const struct iphdr *ih; | ||
171 | unsigned int logflags; | ||
172 | |||
173 | if (info->type == NF_LOG_TYPE_LOG) | ||
174 | logflags = info->u.log.logflags; | ||
175 | else | ||
176 | logflags = NF_LOG_MASK; | ||
177 | |||
178 | ih = skb_header_pointer(skb, iphoff, sizeof(_iph), &_iph); | ||
179 | if (ih == NULL) { | ||
180 | sb_add(m, "TRUNCATED"); | ||
181 | return; | ||
182 | } | ||
183 | |||
184 | /* Important fields: | ||
185 | * TOS, len, DF/MF, fragment offset, TTL, src, dst, options. */ | ||
186 | /* Max length: 40 "SRC=255.255.255.255 DST=255.255.255.255 " */ | ||
187 | sb_add(m, "SRC=%pI4 DST=%pI4 ", | ||
188 | &ih->saddr, &ih->daddr); | ||
189 | |||
190 | /* Max length: 46 "LEN=65535 TOS=0xFF PREC=0xFF TTL=255 ID=65535 " */ | ||
191 | sb_add(m, "LEN=%u TOS=0x%02X PREC=0x%02X TTL=%u ID=%u ", | ||
192 | ntohs(ih->tot_len), ih->tos & IPTOS_TOS_MASK, | ||
193 | ih->tos & IPTOS_PREC_MASK, ih->ttl, ntohs(ih->id)); | ||
194 | |||
195 | /* Max length: 6 "CE DF MF " */ | ||
196 | if (ntohs(ih->frag_off) & IP_CE) | ||
197 | sb_add(m, "CE "); | ||
198 | if (ntohs(ih->frag_off) & IP_DF) | ||
199 | sb_add(m, "DF "); | ||
200 | if (ntohs(ih->frag_off) & IP_MF) | ||
201 | sb_add(m, "MF "); | ||
202 | |||
203 | /* Max length: 11 "FRAG:65535 " */ | ||
204 | if (ntohs(ih->frag_off) & IP_OFFSET) | ||
205 | sb_add(m, "FRAG:%u ", ntohs(ih->frag_off) & IP_OFFSET); | ||
206 | |||
207 | if ((logflags & XT_LOG_IPOPT) && | ||
208 | ih->ihl * 4 > sizeof(struct iphdr)) { | ||
209 | const unsigned char *op; | ||
210 | unsigned char _opt[4 * 15 - sizeof(struct iphdr)]; | ||
211 | unsigned int i, optsize; | ||
212 | |||
213 | optsize = ih->ihl * 4 - sizeof(struct iphdr); | ||
214 | op = skb_header_pointer(skb, iphoff+sizeof(_iph), | ||
215 | optsize, _opt); | ||
216 | if (op == NULL) { | ||
217 | sb_add(m, "TRUNCATED"); | ||
218 | return; | ||
219 | } | ||
220 | |||
221 | /* Max length: 127 "OPT (" 15*4*2chars ") " */ | ||
222 | sb_add(m, "OPT ("); | ||
223 | for (i = 0; i < optsize; i++) | ||
224 | sb_add(m, "%02X", op[i]); | ||
225 | sb_add(m, ") "); | ||
226 | } | ||
227 | |||
228 | switch (ih->protocol) { | ||
229 | case IPPROTO_TCP: | ||
230 | if (dump_tcp_header(m, skb, ih->protocol, | ||
231 | ntohs(ih->frag_off) & IP_OFFSET, | ||
232 | iphoff+ih->ihl*4, logflags)) | ||
233 | return; | ||
234 | break; | ||
235 | case IPPROTO_UDP: | ||
236 | case IPPROTO_UDPLITE: | ||
237 | if (dump_udp_header(m, skb, ih->protocol, | ||
238 | ntohs(ih->frag_off) & IP_OFFSET, | ||
239 | iphoff+ih->ihl*4)) | ||
240 | return; | ||
241 | break; | ||
242 | case IPPROTO_ICMP: { | ||
243 | struct icmphdr _icmph; | ||
244 | const struct icmphdr *ich; | ||
245 | static const size_t required_len[NR_ICMP_TYPES+1] | ||
246 | = { [ICMP_ECHOREPLY] = 4, | ||
247 | [ICMP_DEST_UNREACH] | ||
248 | = 8 + sizeof(struct iphdr), | ||
249 | [ICMP_SOURCE_QUENCH] | ||
250 | = 8 + sizeof(struct iphdr), | ||
251 | [ICMP_REDIRECT] | ||
252 | = 8 + sizeof(struct iphdr), | ||
253 | [ICMP_ECHO] = 4, | ||
254 | [ICMP_TIME_EXCEEDED] | ||
255 | = 8 + sizeof(struct iphdr), | ||
256 | [ICMP_PARAMETERPROB] | ||
257 | = 8 + sizeof(struct iphdr), | ||
258 | [ICMP_TIMESTAMP] = 20, | ||
259 | [ICMP_TIMESTAMPREPLY] = 20, | ||
260 | [ICMP_ADDRESS] = 12, | ||
261 | [ICMP_ADDRESSREPLY] = 12 }; | ||
262 | |||
263 | /* Max length: 11 "PROTO=ICMP " */ | ||
264 | sb_add(m, "PROTO=ICMP "); | ||
265 | |||
266 | if (ntohs(ih->frag_off) & IP_OFFSET) | ||
267 | break; | ||
268 | |||
269 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ | ||
270 | ich = skb_header_pointer(skb, iphoff + ih->ihl * 4, | ||
271 | sizeof(_icmph), &_icmph); | ||
272 | if (ich == NULL) { | ||
273 | sb_add(m, "INCOMPLETE [%u bytes] ", | ||
274 | skb->len - iphoff - ih->ihl*4); | ||
275 | break; | ||
276 | } | ||
277 | |||
278 | /* Max length: 18 "TYPE=255 CODE=255 " */ | ||
279 | sb_add(m, "TYPE=%u CODE=%u ", ich->type, ich->code); | ||
280 | |||
281 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ | ||
282 | if (ich->type <= NR_ICMP_TYPES && | ||
283 | required_len[ich->type] && | ||
284 | skb->len-iphoff-ih->ihl*4 < required_len[ich->type]) { | ||
285 | sb_add(m, "INCOMPLETE [%u bytes] ", | ||
286 | skb->len - iphoff - ih->ihl*4); | ||
287 | break; | ||
288 | } | ||
289 | |||
290 | switch (ich->type) { | ||
291 | case ICMP_ECHOREPLY: | ||
292 | case ICMP_ECHO: | ||
293 | /* Max length: 19 "ID=65535 SEQ=65535 " */ | ||
294 | sb_add(m, "ID=%u SEQ=%u ", | ||
295 | ntohs(ich->un.echo.id), | ||
296 | ntohs(ich->un.echo.sequence)); | ||
297 | break; | ||
298 | |||
299 | case ICMP_PARAMETERPROB: | ||
300 | /* Max length: 14 "PARAMETER=255 " */ | ||
301 | sb_add(m, "PARAMETER=%u ", | ||
302 | ntohl(ich->un.gateway) >> 24); | ||
303 | break; | ||
304 | case ICMP_REDIRECT: | ||
305 | /* Max length: 24 "GATEWAY=255.255.255.255 " */ | ||
306 | sb_add(m, "GATEWAY=%pI4 ", &ich->un.gateway); | ||
307 | /* Fall through */ | ||
308 | case ICMP_DEST_UNREACH: | ||
309 | case ICMP_SOURCE_QUENCH: | ||
310 | case ICMP_TIME_EXCEEDED: | ||
311 | /* Max length: 3+maxlen */ | ||
312 | if (!iphoff) { /* Only recurse once. */ | ||
313 | sb_add(m, "["); | ||
314 | dump_ipv4_packet(m, info, skb, | ||
315 | iphoff + ih->ihl*4+sizeof(_icmph)); | ||
316 | sb_add(m, "] "); | ||
317 | } | ||
318 | |||
319 | /* Max length: 10 "MTU=65535 " */ | ||
320 | if (ich->type == ICMP_DEST_UNREACH && | ||
321 | ich->code == ICMP_FRAG_NEEDED) | ||
322 | sb_add(m, "MTU=%u ", ntohs(ich->un.frag.mtu)); | ||
323 | } | ||
324 | break; | ||
325 | } | ||
326 | /* Max Length */ | ||
327 | case IPPROTO_AH: { | ||
328 | struct ip_auth_hdr _ahdr; | ||
329 | const struct ip_auth_hdr *ah; | ||
330 | |||
331 | if (ntohs(ih->frag_off) & IP_OFFSET) | ||
332 | break; | ||
333 | |||
334 | /* Max length: 9 "PROTO=AH " */ | ||
335 | sb_add(m, "PROTO=AH "); | ||
336 | |||
337 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ | ||
338 | ah = skb_header_pointer(skb, iphoff+ih->ihl*4, | ||
339 | sizeof(_ahdr), &_ahdr); | ||
340 | if (ah == NULL) { | ||
341 | sb_add(m, "INCOMPLETE [%u bytes] ", | ||
342 | skb->len - iphoff - ih->ihl*4); | ||
343 | break; | ||
344 | } | ||
345 | |||
346 | /* Length: 15 "SPI=0xF1234567 " */ | ||
347 | sb_add(m, "SPI=0x%x ", ntohl(ah->spi)); | ||
348 | break; | ||
349 | } | ||
350 | case IPPROTO_ESP: { | ||
351 | struct ip_esp_hdr _esph; | ||
352 | const struct ip_esp_hdr *eh; | ||
353 | |||
354 | /* Max length: 10 "PROTO=ESP " */ | ||
355 | sb_add(m, "PROTO=ESP "); | ||
356 | |||
357 | if (ntohs(ih->frag_off) & IP_OFFSET) | ||
358 | break; | ||
359 | |||
360 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ | ||
361 | eh = skb_header_pointer(skb, iphoff+ih->ihl*4, | ||
362 | sizeof(_esph), &_esph); | ||
363 | if (eh == NULL) { | ||
364 | sb_add(m, "INCOMPLETE [%u bytes] ", | ||
365 | skb->len - iphoff - ih->ihl*4); | ||
366 | break; | ||
367 | } | ||
368 | |||
369 | /* Length: 15 "SPI=0xF1234567 " */ | ||
370 | sb_add(m, "SPI=0x%x ", ntohl(eh->spi)); | ||
371 | break; | ||
372 | } | ||
373 | /* Max length: 10 "PROTO 255 " */ | ||
374 | default: | ||
375 | sb_add(m, "PROTO=%u ", ih->protocol); | ||
376 | } | ||
377 | |||
378 | /* Max length: 15 "UID=4294967295 " */ | ||
379 | if ((logflags & XT_LOG_UID) && !iphoff) | ||
380 | dump_sk_uid_gid(m, skb->sk); | ||
381 | |||
382 | /* Max length: 16 "MARK=0xFFFFFFFF " */ | ||
383 | if (!iphoff && skb->mark) | ||
384 | sb_add(m, "MARK=0x%x ", skb->mark); | ||
385 | |||
386 | /* Proto Max log string length */ | ||
387 | /* IP: 40+46+6+11+127 = 230 */ | ||
388 | /* TCP: 10+max(25,20+30+13+9+32+11+127) = 252 */ | ||
389 | /* UDP: 10+max(25,20) = 35 */ | ||
390 | /* UDPLITE: 14+max(25,20) = 39 */ | ||
391 | /* ICMP: 11+max(25, 18+25+max(19,14,24+3+n+10,3+n+10)) = 91+n */ | ||
392 | /* ESP: 10+max(25)+15 = 50 */ | ||
393 | /* AH: 9+max(25)+15 = 49 */ | ||
394 | /* unknown: 10 */ | ||
395 | |||
396 | /* (ICMP allows recursion one level deep) */ | ||
397 | /* maxlen = IP + ICMP + IP + max(TCP,UDP,ICMP,unknown) */ | ||
398 | /* maxlen = 230+ 91 + 230 + 252 = 803 */ | ||
399 | } | ||
400 | |||
401 | static void dump_ipv4_mac_header(struct sbuff *m, | ||
402 | const struct nf_loginfo *info, | ||
403 | const struct sk_buff *skb) | ||
404 | { | ||
405 | struct net_device *dev = skb->dev; | ||
406 | unsigned int logflags = 0; | ||
407 | |||
408 | if (info->type == NF_LOG_TYPE_LOG) | ||
409 | logflags = info->u.log.logflags; | ||
410 | |||
411 | if (!(logflags & XT_LOG_MACDECODE)) | ||
412 | goto fallback; | ||
413 | |||
414 | switch (dev->type) { | ||
415 | case ARPHRD_ETHER: | ||
416 | sb_add(m, "MACSRC=%pM MACDST=%pM MACPROTO=%04x ", | ||
417 | eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, | ||
418 | ntohs(eth_hdr(skb)->h_proto)); | ||
419 | return; | ||
420 | default: | ||
421 | break; | ||
422 | } | ||
423 | |||
424 | fallback: | ||
425 | sb_add(m, "MAC="); | ||
426 | if (dev->hard_header_len && | ||
427 | skb->mac_header != skb->network_header) { | ||
428 | const unsigned char *p = skb_mac_header(skb); | ||
429 | unsigned int i; | ||
430 | |||
431 | sb_add(m, "%02x", *p++); | ||
432 | for (i = 1; i < dev->hard_header_len; i++, p++) | ||
433 | sb_add(m, ":%02x", *p); | ||
434 | } | ||
435 | sb_add(m, " "); | ||
436 | } | ||
437 | |||
438 | static void | ||
439 | log_packet_common(struct sbuff *m, | ||
440 | u_int8_t pf, | ||
441 | unsigned int hooknum, | ||
442 | const struct sk_buff *skb, | ||
443 | const struct net_device *in, | ||
444 | const struct net_device *out, | ||
445 | const struct nf_loginfo *loginfo, | ||
446 | const char *prefix) | ||
447 | { | ||
448 | sb_add(m, KERN_SOH "%c%sIN=%s OUT=%s ", | ||
449 | '0' + loginfo->u.log.level, prefix, | ||
450 | in ? in->name : "", | ||
451 | out ? out->name : ""); | ||
452 | #ifdef CONFIG_BRIDGE_NETFILTER | ||
453 | if (skb->nf_bridge) { | ||
454 | const struct net_device *physindev; | ||
455 | const struct net_device *physoutdev; | ||
456 | |||
457 | physindev = skb->nf_bridge->physindev; | ||
458 | if (physindev && in != physindev) | ||
459 | sb_add(m, "PHYSIN=%s ", physindev->name); | ||
460 | physoutdev = skb->nf_bridge->physoutdev; | ||
461 | if (physoutdev && out != physoutdev) | ||
462 | sb_add(m, "PHYSOUT=%s ", physoutdev->name); | ||
463 | } | ||
464 | #endif | ||
465 | } | ||
466 | |||
467 | |||
468 | static void | ||
469 | ipt_log_packet(struct net *net, | ||
470 | u_int8_t pf, | ||
471 | unsigned int hooknum, | ||
472 | const struct sk_buff *skb, | ||
473 | const struct net_device *in, | ||
474 | const struct net_device *out, | ||
475 | const struct nf_loginfo *loginfo, | ||
476 | const char *prefix) | ||
477 | { | ||
478 | struct sbuff *m; | ||
479 | |||
480 | /* FIXME: Disabled from containers until syslog ns is supported */ | ||
481 | if (!net_eq(net, &init_net)) | ||
482 | return; | ||
483 | |||
484 | m = sb_open(); | ||
485 | |||
486 | if (!loginfo) | ||
487 | loginfo = &default_loginfo; | ||
488 | |||
489 | log_packet_common(m, pf, hooknum, skb, in, out, loginfo, prefix); | ||
490 | |||
491 | if (in != NULL) | ||
492 | dump_ipv4_mac_header(m, loginfo, skb); | ||
493 | |||
494 | dump_ipv4_packet(m, loginfo, skb, 0); | ||
495 | |||
496 | sb_close(m); | ||
497 | } | ||
498 | |||
499 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) | ||
500 | /* One level of recursion won't kill us */ | ||
501 | static void dump_ipv6_packet(struct sbuff *m, | ||
502 | const struct nf_loginfo *info, | ||
503 | const struct sk_buff *skb, unsigned int ip6hoff, | ||
504 | int recurse) | ||
505 | { | ||
506 | u_int8_t currenthdr; | ||
507 | int fragment; | ||
508 | struct ipv6hdr _ip6h; | ||
509 | const struct ipv6hdr *ih; | ||
510 | unsigned int ptr; | ||
511 | unsigned int hdrlen = 0; | ||
512 | unsigned int logflags; | ||
513 | |||
514 | if (info->type == NF_LOG_TYPE_LOG) | ||
515 | logflags = info->u.log.logflags; | ||
516 | else | ||
517 | logflags = NF_LOG_MASK; | ||
518 | |||
519 | ih = skb_header_pointer(skb, ip6hoff, sizeof(_ip6h), &_ip6h); | ||
520 | if (ih == NULL) { | ||
521 | sb_add(m, "TRUNCATED"); | ||
522 | return; | ||
523 | } | ||
524 | |||
525 | /* Max length: 88 "SRC=0000.0000.0000.0000.0000.0000.0000.0000 DST=0000.0000.0000.0000.0000.0000.0000.0000 " */ | ||
526 | sb_add(m, "SRC=%pI6 DST=%pI6 ", &ih->saddr, &ih->daddr); | ||
527 | |||
528 | /* Max length: 44 "LEN=65535 TC=255 HOPLIMIT=255 FLOWLBL=FFFFF " */ | ||
529 | sb_add(m, "LEN=%Zu TC=%u HOPLIMIT=%u FLOWLBL=%u ", | ||
530 | ntohs(ih->payload_len) + sizeof(struct ipv6hdr), | ||
531 | (ntohl(*(__be32 *)ih) & 0x0ff00000) >> 20, | ||
532 | ih->hop_limit, | ||
533 | (ntohl(*(__be32 *)ih) & 0x000fffff)); | ||
534 | |||
535 | fragment = 0; | ||
536 | ptr = ip6hoff + sizeof(struct ipv6hdr); | ||
537 | currenthdr = ih->nexthdr; | ||
538 | while (currenthdr != NEXTHDR_NONE && ip6t_ext_hdr(currenthdr)) { | ||
539 | struct ipv6_opt_hdr _hdr; | ||
540 | const struct ipv6_opt_hdr *hp; | ||
541 | |||
542 | hp = skb_header_pointer(skb, ptr, sizeof(_hdr), &_hdr); | ||
543 | if (hp == NULL) { | ||
544 | sb_add(m, "TRUNCATED"); | ||
545 | return; | ||
546 | } | ||
547 | |||
548 | /* Max length: 48 "OPT (...) " */ | ||
549 | if (logflags & XT_LOG_IPOPT) | ||
550 | sb_add(m, "OPT ( "); | ||
551 | |||
552 | switch (currenthdr) { | ||
553 | case IPPROTO_FRAGMENT: { | ||
554 | struct frag_hdr _fhdr; | ||
555 | const struct frag_hdr *fh; | ||
556 | |||
557 | sb_add(m, "FRAG:"); | ||
558 | fh = skb_header_pointer(skb, ptr, sizeof(_fhdr), | ||
559 | &_fhdr); | ||
560 | if (fh == NULL) { | ||
561 | sb_add(m, "TRUNCATED "); | ||
562 | return; | ||
563 | } | ||
564 | |||
565 | /* Max length: 6 "65535 " */ | ||
566 | sb_add(m, "%u ", ntohs(fh->frag_off) & 0xFFF8); | ||
567 | |||
568 | /* Max length: 11 "INCOMPLETE " */ | ||
569 | if (fh->frag_off & htons(0x0001)) | ||
570 | sb_add(m, "INCOMPLETE "); | ||
571 | |||
572 | sb_add(m, "ID:%08x ", ntohl(fh->identification)); | ||
573 | |||
574 | if (ntohs(fh->frag_off) & 0xFFF8) | ||
575 | fragment = 1; | ||
576 | |||
577 | hdrlen = 8; | ||
578 | |||
579 | break; | ||
580 | } | ||
581 | case IPPROTO_DSTOPTS: | ||
582 | case IPPROTO_ROUTING: | ||
583 | case IPPROTO_HOPOPTS: | ||
584 | if (fragment) { | ||
585 | if (logflags & XT_LOG_IPOPT) | ||
586 | sb_add(m, ")"); | ||
587 | return; | ||
588 | } | ||
589 | hdrlen = ipv6_optlen(hp); | ||
590 | break; | ||
591 | /* Max Length */ | ||
592 | case IPPROTO_AH: | ||
593 | if (logflags & XT_LOG_IPOPT) { | ||
594 | struct ip_auth_hdr _ahdr; | ||
595 | const struct ip_auth_hdr *ah; | ||
596 | |||
597 | /* Max length: 3 "AH " */ | ||
598 | sb_add(m, "AH "); | ||
599 | |||
600 | if (fragment) { | ||
601 | sb_add(m, ")"); | ||
602 | return; | ||
603 | } | ||
604 | |||
605 | ah = skb_header_pointer(skb, ptr, sizeof(_ahdr), | ||
606 | &_ahdr); | ||
607 | if (ah == NULL) { | ||
608 | /* | ||
609 | * Max length: 26 "INCOMPLETE [65535 | ||
610 | * bytes] )" | ||
611 | */ | ||
612 | sb_add(m, "INCOMPLETE [%u bytes] )", | ||
613 | skb->len - ptr); | ||
614 | return; | ||
615 | } | ||
616 | |||
617 | /* Length: 15 "SPI=0xF1234567 */ | ||
618 | sb_add(m, "SPI=0x%x ", ntohl(ah->spi)); | ||
619 | |||
620 | } | ||
621 | |||
622 | hdrlen = (hp->hdrlen+2)<<2; | ||
623 | break; | ||
624 | case IPPROTO_ESP: | ||
625 | if (logflags & XT_LOG_IPOPT) { | ||
626 | struct ip_esp_hdr _esph; | ||
627 | const struct ip_esp_hdr *eh; | ||
628 | |||
629 | /* Max length: 4 "ESP " */ | ||
630 | sb_add(m, "ESP "); | ||
631 | |||
632 | if (fragment) { | ||
633 | sb_add(m, ")"); | ||
634 | return; | ||
635 | } | ||
636 | |||
637 | /* | ||
638 | * Max length: 26 "INCOMPLETE [65535 bytes] )" | ||
639 | */ | ||
640 | eh = skb_header_pointer(skb, ptr, sizeof(_esph), | ||
641 | &_esph); | ||
642 | if (eh == NULL) { | ||
643 | sb_add(m, "INCOMPLETE [%u bytes] )", | ||
644 | skb->len - ptr); | ||
645 | return; | ||
646 | } | ||
647 | |||
648 | /* Length: 16 "SPI=0xF1234567 )" */ | ||
649 | sb_add(m, "SPI=0x%x )", ntohl(eh->spi)); | ||
650 | |||
651 | } | ||
652 | return; | ||
653 | default: | ||
654 | /* Max length: 20 "Unknown Ext Hdr 255" */ | ||
655 | sb_add(m, "Unknown Ext Hdr %u", currenthdr); | ||
656 | return; | ||
657 | } | ||
658 | if (logflags & XT_LOG_IPOPT) | ||
659 | sb_add(m, ") "); | ||
660 | |||
661 | currenthdr = hp->nexthdr; | ||
662 | ptr += hdrlen; | ||
663 | } | ||
664 | |||
665 | switch (currenthdr) { | ||
666 | case IPPROTO_TCP: | ||
667 | if (dump_tcp_header(m, skb, currenthdr, fragment, ptr, | ||
668 | logflags)) | ||
669 | return; | ||
670 | break; | ||
671 | case IPPROTO_UDP: | ||
672 | case IPPROTO_UDPLITE: | ||
673 | if (dump_udp_header(m, skb, currenthdr, fragment, ptr)) | ||
674 | return; | ||
675 | break; | ||
676 | case IPPROTO_ICMPV6: { | ||
677 | struct icmp6hdr _icmp6h; | ||
678 | const struct icmp6hdr *ic; | ||
679 | |||
680 | /* Max length: 13 "PROTO=ICMPv6 " */ | ||
681 | sb_add(m, "PROTO=ICMPv6 "); | ||
682 | |||
683 | if (fragment) | ||
684 | break; | ||
685 | |||
686 | /* Max length: 25 "INCOMPLETE [65535 bytes] " */ | ||
687 | ic = skb_header_pointer(skb, ptr, sizeof(_icmp6h), &_icmp6h); | ||
688 | if (ic == NULL) { | ||
689 | sb_add(m, "INCOMPLETE [%u bytes] ", skb->len - ptr); | ||
690 | return; | ||
691 | } | ||
692 | |||
693 | /* Max length: 18 "TYPE=255 CODE=255 " */ | ||
694 | sb_add(m, "TYPE=%u CODE=%u ", ic->icmp6_type, ic->icmp6_code); | ||
695 | |||
696 | switch (ic->icmp6_type) { | ||
697 | case ICMPV6_ECHO_REQUEST: | ||
698 | case ICMPV6_ECHO_REPLY: | ||
699 | /* Max length: 19 "ID=65535 SEQ=65535 " */ | ||
700 | sb_add(m, "ID=%u SEQ=%u ", | ||
701 | ntohs(ic->icmp6_identifier), | ||
702 | ntohs(ic->icmp6_sequence)); | ||
703 | break; | ||
704 | case ICMPV6_MGM_QUERY: | ||
705 | case ICMPV6_MGM_REPORT: | ||
706 | case ICMPV6_MGM_REDUCTION: | ||
707 | break; | ||
708 | |||
709 | case ICMPV6_PARAMPROB: | ||
710 | /* Max length: 17 "POINTER=ffffffff " */ | ||
711 | sb_add(m, "POINTER=%08x ", ntohl(ic->icmp6_pointer)); | ||
712 | /* Fall through */ | ||
713 | case ICMPV6_DEST_UNREACH: | ||
714 | case ICMPV6_PKT_TOOBIG: | ||
715 | case ICMPV6_TIME_EXCEED: | ||
716 | /* Max length: 3+maxlen */ | ||
717 | if (recurse) { | ||
718 | sb_add(m, "["); | ||
719 | dump_ipv6_packet(m, info, skb, | ||
720 | ptr + sizeof(_icmp6h), 0); | ||
721 | sb_add(m, "] "); | ||
722 | } | ||
723 | |||
724 | /* Max length: 10 "MTU=65535 " */ | ||
725 | if (ic->icmp6_type == ICMPV6_PKT_TOOBIG) | ||
726 | sb_add(m, "MTU=%u ", ntohl(ic->icmp6_mtu)); | ||
727 | } | ||
728 | break; | ||
729 | } | ||
730 | /* Max length: 10 "PROTO=255 " */ | ||
731 | default: | ||
732 | sb_add(m, "PROTO=%u ", currenthdr); | ||
733 | } | ||
734 | |||
735 | /* Max length: 15 "UID=4294967295 " */ | ||
736 | if ((logflags & XT_LOG_UID) && recurse) | ||
737 | dump_sk_uid_gid(m, skb->sk); | ||
738 | |||
739 | /* Max length: 16 "MARK=0xFFFFFFFF " */ | ||
740 | if (recurse && skb->mark) | ||
741 | sb_add(m, "MARK=0x%x ", skb->mark); | ||
742 | } | ||
743 | |||
744 | static void dump_ipv6_mac_header(struct sbuff *m, | ||
745 | const struct nf_loginfo *info, | ||
746 | const struct sk_buff *skb) | ||
747 | { | ||
748 | struct net_device *dev = skb->dev; | ||
749 | unsigned int logflags = 0; | ||
750 | |||
751 | if (info->type == NF_LOG_TYPE_LOG) | ||
752 | logflags = info->u.log.logflags; | ||
753 | |||
754 | if (!(logflags & XT_LOG_MACDECODE)) | ||
755 | goto fallback; | ||
756 | |||
757 | switch (dev->type) { | ||
758 | case ARPHRD_ETHER: | ||
759 | sb_add(m, "MACSRC=%pM MACDST=%pM MACPROTO=%04x ", | ||
760 | eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest, | ||
761 | ntohs(eth_hdr(skb)->h_proto)); | ||
762 | return; | ||
763 | default: | ||
764 | break; | ||
765 | } | ||
766 | |||
767 | fallback: | ||
768 | sb_add(m, "MAC="); | ||
769 | if (dev->hard_header_len && | ||
770 | skb->mac_header != skb->network_header) { | ||
771 | const unsigned char *p = skb_mac_header(skb); | ||
772 | unsigned int len = dev->hard_header_len; | ||
773 | unsigned int i; | ||
774 | |||
775 | if (dev->type == ARPHRD_SIT) { | ||
776 | p -= ETH_HLEN; | ||
777 | |||
778 | if (p < skb->head) | ||
779 | p = NULL; | ||
780 | } | ||
781 | |||
782 | if (p != NULL) { | ||
783 | sb_add(m, "%02x", *p++); | ||
784 | for (i = 1; i < len; i++) | ||
785 | sb_add(m, ":%02x", *p++); | ||
786 | } | ||
787 | sb_add(m, " "); | ||
788 | |||
789 | if (dev->type == ARPHRD_SIT) { | ||
790 | const struct iphdr *iph = | ||
791 | (struct iphdr *)skb_mac_header(skb); | ||
792 | sb_add(m, "TUNNEL=%pI4->%pI4 ", &iph->saddr, | ||
793 | &iph->daddr); | ||
794 | } | ||
795 | } else | ||
796 | sb_add(m, " "); | ||
797 | } | ||
798 | |||
799 | static void | ||
800 | ip6t_log_packet(struct net *net, | ||
801 | u_int8_t pf, | ||
802 | unsigned int hooknum, | ||
803 | const struct sk_buff *skb, | ||
804 | const struct net_device *in, | ||
805 | const struct net_device *out, | ||
806 | const struct nf_loginfo *loginfo, | ||
807 | const char *prefix) | ||
808 | { | ||
809 | struct sbuff *m; | ||
810 | |||
811 | /* FIXME: Disabled from containers until syslog ns is supported */ | ||
812 | if (!net_eq(net, &init_net)) | ||
813 | return; | ||
814 | |||
815 | m = sb_open(); | ||
816 | |||
817 | if (!loginfo) | ||
818 | loginfo = &default_loginfo; | ||
819 | |||
820 | log_packet_common(m, pf, hooknum, skb, in, out, loginfo, prefix); | ||
821 | |||
822 | if (in != NULL) | ||
823 | dump_ipv6_mac_header(m, loginfo, skb); | ||
824 | |||
825 | dump_ipv6_packet(m, loginfo, skb, skb_network_offset(skb), 1); | ||
826 | |||
827 | sb_close(m); | ||
828 | } | ||
829 | #endif | ||
830 | 30 | ||
831 | static unsigned int | 31 | static unsigned int |
832 | log_tg(struct sk_buff *skb, const struct xt_action_param *par) | 32 | log_tg(struct sk_buff *skb, const struct xt_action_param *par) |
@@ -839,17 +39,8 @@ log_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
839 | li.u.log.level = loginfo->level; | 39 | li.u.log.level = loginfo->level; |
840 | li.u.log.logflags = loginfo->logflags; | 40 | li.u.log.logflags = loginfo->logflags; |
841 | 41 | ||
842 | if (par->family == NFPROTO_IPV4) | 42 | nf_log_packet(net, par->family, par->hooknum, skb, par->in, par->out, |
843 | ipt_log_packet(net, NFPROTO_IPV4, par->hooknum, skb, par->in, | 43 | &li, "%s", loginfo->prefix); |
844 | par->out, &li, loginfo->prefix); | ||
845 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) | ||
846 | else if (par->family == NFPROTO_IPV6) | ||
847 | ip6t_log_packet(net, NFPROTO_IPV6, par->hooknum, skb, par->in, | ||
848 | par->out, &li, loginfo->prefix); | ||
849 | #endif | ||
850 | else | ||
851 | WARN_ON_ONCE(1); | ||
852 | |||
853 | return XT_CONTINUE; | 44 | return XT_CONTINUE; |
854 | } | 45 | } |
855 | 46 | ||
@@ -870,7 +61,12 @@ static int log_tg_check(const struct xt_tgchk_param *par) | |||
870 | return -EINVAL; | 61 | return -EINVAL; |
871 | } | 62 | } |
872 | 63 | ||
873 | return 0; | 64 | return nf_logger_find_get(par->family, NF_LOG_TYPE_LOG); |
65 | } | ||
66 | |||
67 | static void log_tg_destroy(const struct xt_tgdtor_param *par) | ||
68 | { | ||
69 | nf_logger_put(par->family, NF_LOG_TYPE_LOG); | ||
874 | } | 70 | } |
875 | 71 | ||
876 | static struct xt_target log_tg_regs[] __read_mostly = { | 72 | static struct xt_target log_tg_regs[] __read_mostly = { |
@@ -880,6 +76,7 @@ static struct xt_target log_tg_regs[] __read_mostly = { | |||
880 | .target = log_tg, | 76 | .target = log_tg, |
881 | .targetsize = sizeof(struct xt_log_info), | 77 | .targetsize = sizeof(struct xt_log_info), |
882 | .checkentry = log_tg_check, | 78 | .checkentry = log_tg_check, |
79 | .destroy = log_tg_destroy, | ||
883 | .me = THIS_MODULE, | 80 | .me = THIS_MODULE, |
884 | }, | 81 | }, |
885 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) | 82 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) |
@@ -889,78 +86,19 @@ static struct xt_target log_tg_regs[] __read_mostly = { | |||
889 | .target = log_tg, | 86 | .target = log_tg, |
890 | .targetsize = sizeof(struct xt_log_info), | 87 | .targetsize = sizeof(struct xt_log_info), |
891 | .checkentry = log_tg_check, | 88 | .checkentry = log_tg_check, |
89 | .destroy = log_tg_destroy, | ||
892 | .me = THIS_MODULE, | 90 | .me = THIS_MODULE, |
893 | }, | 91 | }, |
894 | #endif | 92 | #endif |
895 | }; | 93 | }; |
896 | 94 | ||
897 | static struct nf_logger ipt_log_logger __read_mostly = { | ||
898 | .name = "ipt_LOG", | ||
899 | .logfn = &ipt_log_packet, | ||
900 | .me = THIS_MODULE, | ||
901 | }; | ||
902 | |||
903 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) | ||
904 | static struct nf_logger ip6t_log_logger __read_mostly = { | ||
905 | .name = "ip6t_LOG", | ||
906 | .logfn = &ip6t_log_packet, | ||
907 | .me = THIS_MODULE, | ||
908 | }; | ||
909 | #endif | ||
910 | |||
911 | static int __net_init log_net_init(struct net *net) | ||
912 | { | ||
913 | nf_log_set(net, NFPROTO_IPV4, &ipt_log_logger); | ||
914 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) | ||
915 | nf_log_set(net, NFPROTO_IPV6, &ip6t_log_logger); | ||
916 | #endif | ||
917 | return 0; | ||
918 | } | ||
919 | |||
920 | static void __net_exit log_net_exit(struct net *net) | ||
921 | { | ||
922 | nf_log_unset(net, &ipt_log_logger); | ||
923 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) | ||
924 | nf_log_unset(net, &ip6t_log_logger); | ||
925 | #endif | ||
926 | } | ||
927 | |||
928 | static struct pernet_operations log_net_ops = { | ||
929 | .init = log_net_init, | ||
930 | .exit = log_net_exit, | ||
931 | }; | ||
932 | |||
933 | static int __init log_tg_init(void) | 95 | static int __init log_tg_init(void) |
934 | { | 96 | { |
935 | int ret; | 97 | return xt_register_targets(log_tg_regs, ARRAY_SIZE(log_tg_regs)); |
936 | |||
937 | ret = register_pernet_subsys(&log_net_ops); | ||
938 | if (ret < 0) | ||
939 | goto err_pernet; | ||
940 | |||
941 | ret = xt_register_targets(log_tg_regs, ARRAY_SIZE(log_tg_regs)); | ||
942 | if (ret < 0) | ||
943 | goto err_target; | ||
944 | |||
945 | nf_log_register(NFPROTO_IPV4, &ipt_log_logger); | ||
946 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) | ||
947 | nf_log_register(NFPROTO_IPV6, &ip6t_log_logger); | ||
948 | #endif | ||
949 | return 0; | ||
950 | |||
951 | err_target: | ||
952 | unregister_pernet_subsys(&log_net_ops); | ||
953 | err_pernet: | ||
954 | return ret; | ||
955 | } | 98 | } |
956 | 99 | ||
957 | static void __exit log_tg_exit(void) | 100 | static void __exit log_tg_exit(void) |
958 | { | 101 | { |
959 | unregister_pernet_subsys(&log_net_ops); | ||
960 | nf_log_unregister(&ipt_log_logger); | ||
961 | #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) | ||
962 | nf_log_unregister(&ip6t_log_logger); | ||
963 | #endif | ||
964 | xt_unregister_targets(log_tg_regs, ARRAY_SIZE(log_tg_regs)); | 102 | xt_unregister_targets(log_tg_regs, ARRAY_SIZE(log_tg_regs)); |
965 | } | 103 | } |
966 | 104 | ||
diff --git a/net/netfilter/xt_bpf.c b/net/netfilter/xt_bpf.c index bbffdbdaf603..dffee9d47ec4 100644 --- a/net/netfilter/xt_bpf.c +++ b/net/netfilter/xt_bpf.c | |||
@@ -28,7 +28,7 @@ static int bpf_mt_check(const struct xt_mtchk_param *par) | |||
28 | program.len = info->bpf_program_num_elem; | 28 | program.len = info->bpf_program_num_elem; |
29 | program.filter = info->bpf_program; | 29 | program.filter = info->bpf_program; |
30 | 30 | ||
31 | if (sk_unattached_filter_create(&info->filter, &program)) { | 31 | if (bpf_prog_create(&info->filter, &program)) { |
32 | pr_info("bpf: check failed: parse error\n"); | 32 | pr_info("bpf: check failed: parse error\n"); |
33 | return -EINVAL; | 33 | return -EINVAL; |
34 | } | 34 | } |
@@ -40,13 +40,13 @@ static bool bpf_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
40 | { | 40 | { |
41 | const struct xt_bpf_info *info = par->matchinfo; | 41 | const struct xt_bpf_info *info = par->matchinfo; |
42 | 42 | ||
43 | return SK_RUN_FILTER(info->filter, skb); | 43 | return BPF_PROG_RUN(info->filter, skb); |
44 | } | 44 | } |
45 | 45 | ||
46 | static void bpf_mt_destroy(const struct xt_mtdtor_param *par) | 46 | static void bpf_mt_destroy(const struct xt_mtdtor_param *par) |
47 | { | 47 | { |
48 | const struct xt_bpf_info *info = par->matchinfo; | 48 | const struct xt_bpf_info *info = par->matchinfo; |
49 | sk_unattached_filter_destroy(info->filter); | 49 | bpf_prog_destroy(info->filter); |
50 | } | 50 | } |
51 | 51 | ||
52 | static struct xt_match bpf_mt_reg __read_mostly = { | 52 | static struct xt_match bpf_mt_reg __read_mostly = { |
diff --git a/net/netfilter/xt_cgroup.c b/net/netfilter/xt_cgroup.c index f4e833005320..7198d660b4de 100644 --- a/net/netfilter/xt_cgroup.c +++ b/net/netfilter/xt_cgroup.c | |||
@@ -31,7 +31,7 @@ static int cgroup_mt_check(const struct xt_mtchk_param *par) | |||
31 | if (info->invert & ~1) | 31 | if (info->invert & ~1) |
32 | return -EINVAL; | 32 | return -EINVAL; |
33 | 33 | ||
34 | return info->id ? 0 : -EINVAL; | 34 | return 0; |
35 | } | 35 | } |
36 | 36 | ||
37 | static bool | 37 | static bool |
diff --git a/net/netfilter/xt_hashlimit.c b/net/netfilter/xt_hashlimit.c index a3910fc2122b..47dc6836830a 100644 --- a/net/netfilter/xt_hashlimit.c +++ b/net/netfilter/xt_hashlimit.c | |||
@@ -104,7 +104,7 @@ struct xt_hashlimit_htable { | |||
104 | spinlock_t lock; /* lock for list_head */ | 104 | spinlock_t lock; /* lock for list_head */ |
105 | u_int32_t rnd; /* random seed for hash */ | 105 | u_int32_t rnd; /* random seed for hash */ |
106 | unsigned int count; /* number entries in table */ | 106 | unsigned int count; /* number entries in table */ |
107 | struct timer_list timer; /* timer for gc */ | 107 | struct delayed_work gc_work; |
108 | 108 | ||
109 | /* seq_file stuff */ | 109 | /* seq_file stuff */ |
110 | struct proc_dir_entry *pde; | 110 | struct proc_dir_entry *pde; |
@@ -213,7 +213,7 @@ dsthash_free(struct xt_hashlimit_htable *ht, struct dsthash_ent *ent) | |||
213 | call_rcu_bh(&ent->rcu, dsthash_free_rcu); | 213 | call_rcu_bh(&ent->rcu, dsthash_free_rcu); |
214 | ht->count--; | 214 | ht->count--; |
215 | } | 215 | } |
216 | static void htable_gc(unsigned long htlong); | 216 | static void htable_gc(struct work_struct *work); |
217 | 217 | ||
218 | static int htable_create(struct net *net, struct xt_hashlimit_mtinfo1 *minfo, | 218 | static int htable_create(struct net *net, struct xt_hashlimit_mtinfo1 *minfo, |
219 | u_int8_t family) | 219 | u_int8_t family) |
@@ -273,9 +273,9 @@ static int htable_create(struct net *net, struct xt_hashlimit_mtinfo1 *minfo, | |||
273 | } | 273 | } |
274 | hinfo->net = net; | 274 | hinfo->net = net; |
275 | 275 | ||
276 | setup_timer(&hinfo->timer, htable_gc, (unsigned long)hinfo); | 276 | INIT_DEFERRABLE_WORK(&hinfo->gc_work, htable_gc); |
277 | hinfo->timer.expires = jiffies + msecs_to_jiffies(hinfo->cfg.gc_interval); | 277 | queue_delayed_work(system_power_efficient_wq, &hinfo->gc_work, |
278 | add_timer(&hinfo->timer); | 278 | msecs_to_jiffies(hinfo->cfg.gc_interval)); |
279 | 279 | ||
280 | hlist_add_head(&hinfo->node, &hashlimit_net->htables); | 280 | hlist_add_head(&hinfo->node, &hashlimit_net->htables); |
281 | 281 | ||
@@ -300,29 +300,30 @@ static void htable_selective_cleanup(struct xt_hashlimit_htable *ht, | |||
300 | { | 300 | { |
301 | unsigned int i; | 301 | unsigned int i; |
302 | 302 | ||
303 | /* lock hash table and iterate over it */ | ||
304 | spin_lock_bh(&ht->lock); | ||
305 | for (i = 0; i < ht->cfg.size; i++) { | 303 | for (i = 0; i < ht->cfg.size; i++) { |
306 | struct dsthash_ent *dh; | 304 | struct dsthash_ent *dh; |
307 | struct hlist_node *n; | 305 | struct hlist_node *n; |
306 | |||
307 | spin_lock_bh(&ht->lock); | ||
308 | hlist_for_each_entry_safe(dh, n, &ht->hash[i], node) { | 308 | hlist_for_each_entry_safe(dh, n, &ht->hash[i], node) { |
309 | if ((*select)(ht, dh)) | 309 | if ((*select)(ht, dh)) |
310 | dsthash_free(ht, dh); | 310 | dsthash_free(ht, dh); |
311 | } | 311 | } |
312 | spin_unlock_bh(&ht->lock); | ||
313 | cond_resched(); | ||
312 | } | 314 | } |
313 | spin_unlock_bh(&ht->lock); | ||
314 | } | 315 | } |
315 | 316 | ||
316 | /* hash table garbage collector, run by timer */ | 317 | static void htable_gc(struct work_struct *work) |
317 | static void htable_gc(unsigned long htlong) | ||
318 | { | 318 | { |
319 | struct xt_hashlimit_htable *ht = (struct xt_hashlimit_htable *)htlong; | 319 | struct xt_hashlimit_htable *ht; |
320 | |||
321 | ht = container_of(work, struct xt_hashlimit_htable, gc_work.work); | ||
320 | 322 | ||
321 | htable_selective_cleanup(ht, select_gc); | 323 | htable_selective_cleanup(ht, select_gc); |
322 | 324 | ||
323 | /* re-add the timer accordingly */ | 325 | queue_delayed_work(system_power_efficient_wq, |
324 | ht->timer.expires = jiffies + msecs_to_jiffies(ht->cfg.gc_interval); | 326 | &ht->gc_work, msecs_to_jiffies(ht->cfg.gc_interval)); |
325 | add_timer(&ht->timer); | ||
326 | } | 327 | } |
327 | 328 | ||
328 | static void htable_remove_proc_entry(struct xt_hashlimit_htable *hinfo) | 329 | static void htable_remove_proc_entry(struct xt_hashlimit_htable *hinfo) |
@@ -341,7 +342,7 @@ static void htable_remove_proc_entry(struct xt_hashlimit_htable *hinfo) | |||
341 | 342 | ||
342 | static void htable_destroy(struct xt_hashlimit_htable *hinfo) | 343 | static void htable_destroy(struct xt_hashlimit_htable *hinfo) |
343 | { | 344 | { |
344 | del_timer_sync(&hinfo->timer); | 345 | cancel_delayed_work_sync(&hinfo->gc_work); |
345 | htable_remove_proc_entry(hinfo); | 346 | htable_remove_proc_entry(hinfo); |
346 | htable_selective_cleanup(hinfo, select_all); | 347 | htable_selective_cleanup(hinfo, select_all); |
347 | kfree(hinfo->name); | 348 | kfree(hinfo->name); |
diff --git a/net/netlabel/netlabel_kapi.c b/net/netlabel/netlabel_kapi.c index 05ea4a4cc0ac..0b4692dd1c5e 100644 --- a/net/netlabel/netlabel_kapi.c +++ b/net/netlabel/netlabel_kapi.c | |||
@@ -170,7 +170,6 @@ int netlbl_cfg_unlbl_map_add(const char *domain, | |||
170 | #endif /* IPv6 */ | 170 | #endif /* IPv6 */ |
171 | default: | 171 | default: |
172 | goto cfg_unlbl_map_add_failure; | 172 | goto cfg_unlbl_map_add_failure; |
173 | break; | ||
174 | } | 173 | } |
175 | 174 | ||
176 | entry->def.addrsel = addrmap; | 175 | entry->def.addrsel = addrmap; |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index e6fac7e3db52..c416725d28c4 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
@@ -58,7 +58,9 @@ | |||
58 | #include <linux/mutex.h> | 58 | #include <linux/mutex.h> |
59 | #include <linux/vmalloc.h> | 59 | #include <linux/vmalloc.h> |
60 | #include <linux/if_arp.h> | 60 | #include <linux/if_arp.h> |
61 | #include <linux/rhashtable.h> | ||
61 | #include <asm/cacheflush.h> | 62 | #include <asm/cacheflush.h> |
63 | #include <linux/hash.h> | ||
62 | 64 | ||
63 | #include <net/net_namespace.h> | 65 | #include <net/net_namespace.h> |
64 | #include <net/sock.h> | 66 | #include <net/sock.h> |
@@ -100,6 +102,19 @@ static atomic_t nl_table_users = ATOMIC_INIT(0); | |||
100 | 102 | ||
101 | #define nl_deref_protected(X) rcu_dereference_protected(X, lockdep_is_held(&nl_table_lock)); | 103 | #define nl_deref_protected(X) rcu_dereference_protected(X, lockdep_is_held(&nl_table_lock)); |
102 | 104 | ||
105 | /* Protects netlink socket hash table mutations */ | ||
106 | DEFINE_MUTEX(nl_sk_hash_lock); | ||
107 | EXPORT_SYMBOL_GPL(nl_sk_hash_lock); | ||
108 | |||
109 | static int lockdep_nl_sk_hash_is_held(void) | ||
110 | { | ||
111 | #ifdef CONFIG_LOCKDEP | ||
112 | return (debug_locks) ? lockdep_is_held(&nl_sk_hash_lock) : 1; | ||
113 | #else | ||
114 | return 1; | ||
115 | #endif | ||
116 | } | ||
117 | |||
103 | static ATOMIC_NOTIFIER_HEAD(netlink_chain); | 118 | static ATOMIC_NOTIFIER_HEAD(netlink_chain); |
104 | 119 | ||
105 | static DEFINE_SPINLOCK(netlink_tap_lock); | 120 | static DEFINE_SPINLOCK(netlink_tap_lock); |
@@ -110,11 +125,6 @@ static inline u32 netlink_group_mask(u32 group) | |||
110 | return group ? 1 << (group - 1) : 0; | 125 | return group ? 1 << (group - 1) : 0; |
111 | } | 126 | } |
112 | 127 | ||
113 | static inline struct hlist_head *nl_portid_hashfn(struct nl_portid_hash *hash, u32 portid) | ||
114 | { | ||
115 | return &hash->table[jhash_1word(portid, hash->rnd) & hash->mask]; | ||
116 | } | ||
117 | |||
118 | int netlink_add_tap(struct netlink_tap *nt) | 128 | int netlink_add_tap(struct netlink_tap *nt) |
119 | { | 129 | { |
120 | if (unlikely(nt->dev->type != ARPHRD_NETLINK)) | 130 | if (unlikely(nt->dev->type != ARPHRD_NETLINK)) |
@@ -170,7 +180,6 @@ EXPORT_SYMBOL_GPL(netlink_remove_tap); | |||
170 | static bool netlink_filter_tap(const struct sk_buff *skb) | 180 | static bool netlink_filter_tap(const struct sk_buff *skb) |
171 | { | 181 | { |
172 | struct sock *sk = skb->sk; | 182 | struct sock *sk = skb->sk; |
173 | bool pass = false; | ||
174 | 183 | ||
175 | /* We take the more conservative approach and | 184 | /* We take the more conservative approach and |
176 | * whitelist socket protocols that may pass. | 185 | * whitelist socket protocols that may pass. |
@@ -184,11 +193,10 @@ static bool netlink_filter_tap(const struct sk_buff *skb) | |||
184 | case NETLINK_FIB_LOOKUP: | 193 | case NETLINK_FIB_LOOKUP: |
185 | case NETLINK_NETFILTER: | 194 | case NETLINK_NETFILTER: |
186 | case NETLINK_GENERIC: | 195 | case NETLINK_GENERIC: |
187 | pass = true; | 196 | return true; |
188 | break; | ||
189 | } | 197 | } |
190 | 198 | ||
191 | return pass; | 199 | return false; |
192 | } | 200 | } |
193 | 201 | ||
194 | static int __netlink_deliver_tap_skb(struct sk_buff *skb, | 202 | static int __netlink_deliver_tap_skb(struct sk_buff *skb, |
@@ -205,7 +213,7 @@ static int __netlink_deliver_tap_skb(struct sk_buff *skb, | |||
205 | nskb->protocol = htons((u16) sk->sk_protocol); | 213 | nskb->protocol = htons((u16) sk->sk_protocol); |
206 | nskb->pkt_type = netlink_is_kernel(sk) ? | 214 | nskb->pkt_type = netlink_is_kernel(sk) ? |
207 | PACKET_KERNEL : PACKET_USER; | 215 | PACKET_KERNEL : PACKET_USER; |
208 | 216 | skb_reset_network_header(nskb); | |
209 | ret = dev_queue_xmit(nskb); | 217 | ret = dev_queue_xmit(nskb); |
210 | if (unlikely(ret > 0)) | 218 | if (unlikely(ret > 0)) |
211 | ret = net_xmit_errno(ret); | 219 | ret = net_xmit_errno(ret); |
@@ -376,7 +384,7 @@ static int netlink_set_ring(struct sock *sk, struct nl_mmap_req *req, | |||
376 | 384 | ||
377 | if ((int)req->nm_block_size <= 0) | 385 | if ((int)req->nm_block_size <= 0) |
378 | return -EINVAL; | 386 | return -EINVAL; |
379 | if (!IS_ALIGNED(req->nm_block_size, PAGE_SIZE)) | 387 | if (!PAGE_ALIGNED(req->nm_block_size)) |
380 | return -EINVAL; | 388 | return -EINVAL; |
381 | if (req->nm_frame_size < NL_MMAP_HDRLEN) | 389 | if (req->nm_frame_size < NL_MMAP_HDRLEN) |
382 | return -EINVAL; | 390 | return -EINVAL; |
@@ -985,105 +993,48 @@ netlink_unlock_table(void) | |||
985 | wake_up(&nl_table_wait); | 993 | wake_up(&nl_table_wait); |
986 | } | 994 | } |
987 | 995 | ||
988 | static bool netlink_compare(struct net *net, struct sock *sk) | 996 | struct netlink_compare_arg |
989 | { | 997 | { |
990 | return net_eq(sock_net(sk), net); | 998 | struct net *net; |
991 | } | 999 | u32 portid; |
992 | 1000 | }; | |
993 | static struct sock *netlink_lookup(struct net *net, int protocol, u32 portid) | ||
994 | { | ||
995 | struct netlink_table *table = &nl_table[protocol]; | ||
996 | struct nl_portid_hash *hash = &table->hash; | ||
997 | struct hlist_head *head; | ||
998 | struct sock *sk; | ||
999 | |||
1000 | read_lock(&nl_table_lock); | ||
1001 | head = nl_portid_hashfn(hash, portid); | ||
1002 | sk_for_each(sk, head) { | ||
1003 | if (table->compare(net, sk) && | ||
1004 | (nlk_sk(sk)->portid == portid)) { | ||
1005 | sock_hold(sk); | ||
1006 | goto found; | ||
1007 | } | ||
1008 | } | ||
1009 | sk = NULL; | ||
1010 | found: | ||
1011 | read_unlock(&nl_table_lock); | ||
1012 | return sk; | ||
1013 | } | ||
1014 | 1001 | ||
1015 | static struct hlist_head *nl_portid_hash_zalloc(size_t size) | 1002 | static bool netlink_compare(void *ptr, void *arg) |
1016 | { | 1003 | { |
1017 | if (size <= PAGE_SIZE) | 1004 | struct netlink_compare_arg *x = arg; |
1018 | return kzalloc(size, GFP_ATOMIC); | 1005 | struct sock *sk = ptr; |
1019 | else | ||
1020 | return (struct hlist_head *) | ||
1021 | __get_free_pages(GFP_ATOMIC | __GFP_ZERO, | ||
1022 | get_order(size)); | ||
1023 | } | ||
1024 | 1006 | ||
1025 | static void nl_portid_hash_free(struct hlist_head *table, size_t size) | 1007 | return nlk_sk(sk)->portid == x->portid && |
1026 | { | 1008 | net_eq(sock_net(sk), x->net); |
1027 | if (size <= PAGE_SIZE) | ||
1028 | kfree(table); | ||
1029 | else | ||
1030 | free_pages((unsigned long)table, get_order(size)); | ||
1031 | } | 1009 | } |
1032 | 1010 | ||
1033 | static int nl_portid_hash_rehash(struct nl_portid_hash *hash, int grow) | 1011 | static struct sock *__netlink_lookup(struct netlink_table *table, u32 portid, |
1012 | struct net *net) | ||
1034 | { | 1013 | { |
1035 | unsigned int omask, mask, shift; | 1014 | struct netlink_compare_arg arg = { |
1036 | size_t osize, size; | 1015 | .net = net, |
1037 | struct hlist_head *otable, *table; | 1016 | .portid = portid, |
1038 | int i; | 1017 | }; |
1039 | 1018 | u32 hash; | |
1040 | omask = mask = hash->mask; | ||
1041 | osize = size = (mask + 1) * sizeof(*table); | ||
1042 | shift = hash->shift; | ||
1043 | |||
1044 | if (grow) { | ||
1045 | if (++shift > hash->max_shift) | ||
1046 | return 0; | ||
1047 | mask = mask * 2 + 1; | ||
1048 | size *= 2; | ||
1049 | } | ||
1050 | |||
1051 | table = nl_portid_hash_zalloc(size); | ||
1052 | if (!table) | ||
1053 | return 0; | ||
1054 | |||
1055 | otable = hash->table; | ||
1056 | hash->table = table; | ||
1057 | hash->mask = mask; | ||
1058 | hash->shift = shift; | ||
1059 | get_random_bytes(&hash->rnd, sizeof(hash->rnd)); | ||
1060 | 1019 | ||
1061 | for (i = 0; i <= omask; i++) { | 1020 | hash = rhashtable_hashfn(&table->hash, &portid, sizeof(portid)); |
1062 | struct sock *sk; | ||
1063 | struct hlist_node *tmp; | ||
1064 | |||
1065 | sk_for_each_safe(sk, tmp, &otable[i]) | ||
1066 | __sk_add_node(sk, nl_portid_hashfn(hash, nlk_sk(sk)->portid)); | ||
1067 | } | ||
1068 | 1021 | ||
1069 | nl_portid_hash_free(otable, osize); | 1022 | return rhashtable_lookup_compare(&table->hash, hash, |
1070 | hash->rehash_time = jiffies + 10 * 60 * HZ; | 1023 | &netlink_compare, &arg); |
1071 | return 1; | ||
1072 | } | 1024 | } |
1073 | 1025 | ||
1074 | static inline int nl_portid_hash_dilute(struct nl_portid_hash *hash, int len) | 1026 | static struct sock *netlink_lookup(struct net *net, int protocol, u32 portid) |
1075 | { | 1027 | { |
1076 | int avg = hash->entries >> hash->shift; | 1028 | struct netlink_table *table = &nl_table[protocol]; |
1077 | 1029 | struct sock *sk; | |
1078 | if (unlikely(avg > 1) && nl_portid_hash_rehash(hash, 1)) | ||
1079 | return 1; | ||
1080 | 1030 | ||
1081 | if (unlikely(len > avg) && time_after(jiffies, hash->rehash_time)) { | 1031 | rcu_read_lock(); |
1082 | nl_portid_hash_rehash(hash, 0); | 1032 | sk = __netlink_lookup(table, portid, net); |
1083 | return 1; | 1033 | if (sk) |
1084 | } | 1034 | sock_hold(sk); |
1035 | rcu_read_unlock(); | ||
1085 | 1036 | ||
1086 | return 0; | 1037 | return sk; |
1087 | } | 1038 | } |
1088 | 1039 | ||
1089 | static const struct proto_ops netlink_ops; | 1040 | static const struct proto_ops netlink_ops; |
@@ -1115,22 +1066,10 @@ netlink_update_listeners(struct sock *sk) | |||
1115 | static int netlink_insert(struct sock *sk, struct net *net, u32 portid) | 1066 | static int netlink_insert(struct sock *sk, struct net *net, u32 portid) |
1116 | { | 1067 | { |
1117 | struct netlink_table *table = &nl_table[sk->sk_protocol]; | 1068 | struct netlink_table *table = &nl_table[sk->sk_protocol]; |
1118 | struct nl_portid_hash *hash = &table->hash; | ||
1119 | struct hlist_head *head; | ||
1120 | int err = -EADDRINUSE; | 1069 | int err = -EADDRINUSE; |
1121 | struct sock *osk; | ||
1122 | int len; | ||
1123 | 1070 | ||
1124 | netlink_table_grab(); | 1071 | mutex_lock(&nl_sk_hash_lock); |
1125 | head = nl_portid_hashfn(hash, portid); | 1072 | if (__netlink_lookup(table, portid, net)) |
1126 | len = 0; | ||
1127 | sk_for_each(osk, head) { | ||
1128 | if (table->compare(net, osk) && | ||
1129 | (nlk_sk(osk)->portid == portid)) | ||
1130 | break; | ||
1131 | len++; | ||
1132 | } | ||
1133 | if (osk) | ||
1134 | goto err; | 1073 | goto err; |
1135 | 1074 | ||
1136 | err = -EBUSY; | 1075 | err = -EBUSY; |
@@ -1138,26 +1077,31 @@ static int netlink_insert(struct sock *sk, struct net *net, u32 portid) | |||
1138 | goto err; | 1077 | goto err; |
1139 | 1078 | ||
1140 | err = -ENOMEM; | 1079 | err = -ENOMEM; |
1141 | if (BITS_PER_LONG > 32 && unlikely(hash->entries >= UINT_MAX)) | 1080 | if (BITS_PER_LONG > 32 && unlikely(table->hash.nelems >= UINT_MAX)) |
1142 | goto err; | 1081 | goto err; |
1143 | 1082 | ||
1144 | if (len && nl_portid_hash_dilute(hash, len)) | ||
1145 | head = nl_portid_hashfn(hash, portid); | ||
1146 | hash->entries++; | ||
1147 | nlk_sk(sk)->portid = portid; | 1083 | nlk_sk(sk)->portid = portid; |
1148 | sk_add_node(sk, head); | 1084 | sock_hold(sk); |
1085 | rhashtable_insert(&table->hash, &nlk_sk(sk)->node, GFP_KERNEL); | ||
1149 | err = 0; | 1086 | err = 0; |
1150 | |||
1151 | err: | 1087 | err: |
1152 | netlink_table_ungrab(); | 1088 | mutex_unlock(&nl_sk_hash_lock); |
1153 | return err; | 1089 | return err; |
1154 | } | 1090 | } |
1155 | 1091 | ||
1156 | static void netlink_remove(struct sock *sk) | 1092 | static void netlink_remove(struct sock *sk) |
1157 | { | 1093 | { |
1094 | struct netlink_table *table; | ||
1095 | |||
1096 | mutex_lock(&nl_sk_hash_lock); | ||
1097 | table = &nl_table[sk->sk_protocol]; | ||
1098 | if (rhashtable_remove(&table->hash, &nlk_sk(sk)->node, GFP_KERNEL)) { | ||
1099 | WARN_ON(atomic_read(&sk->sk_refcnt) == 1); | ||
1100 | __sock_put(sk); | ||
1101 | } | ||
1102 | mutex_unlock(&nl_sk_hash_lock); | ||
1103 | |||
1158 | netlink_table_grab(); | 1104 | netlink_table_grab(); |
1159 | if (sk_del_node_init(sk)) | ||
1160 | nl_table[sk->sk_protocol].hash.entries--; | ||
1161 | if (nlk_sk(sk)->subscriptions) | 1105 | if (nlk_sk(sk)->subscriptions) |
1162 | __sk_del_bind_node(sk); | 1106 | __sk_del_bind_node(sk); |
1163 | netlink_table_ungrab(); | 1107 | netlink_table_ungrab(); |
@@ -1313,6 +1257,9 @@ static int netlink_release(struct socket *sock) | |||
1313 | } | 1257 | } |
1314 | netlink_table_ungrab(); | 1258 | netlink_table_ungrab(); |
1315 | 1259 | ||
1260 | /* Wait for readers to complete */ | ||
1261 | synchronize_net(); | ||
1262 | |||
1316 | kfree(nlk->groups); | 1263 | kfree(nlk->groups); |
1317 | nlk->groups = NULL; | 1264 | nlk->groups = NULL; |
1318 | 1265 | ||
@@ -1328,30 +1275,22 @@ static int netlink_autobind(struct socket *sock) | |||
1328 | struct sock *sk = sock->sk; | 1275 | struct sock *sk = sock->sk; |
1329 | struct net *net = sock_net(sk); | 1276 | struct net *net = sock_net(sk); |
1330 | struct netlink_table *table = &nl_table[sk->sk_protocol]; | 1277 | struct netlink_table *table = &nl_table[sk->sk_protocol]; |
1331 | struct nl_portid_hash *hash = &table->hash; | ||
1332 | struct hlist_head *head; | ||
1333 | struct sock *osk; | ||
1334 | s32 portid = task_tgid_vnr(current); | 1278 | s32 portid = task_tgid_vnr(current); |
1335 | int err; | 1279 | int err; |
1336 | static s32 rover = -4097; | 1280 | static s32 rover = -4097; |
1337 | 1281 | ||
1338 | retry: | 1282 | retry: |
1339 | cond_resched(); | 1283 | cond_resched(); |
1340 | netlink_table_grab(); | 1284 | rcu_read_lock(); |
1341 | head = nl_portid_hashfn(hash, portid); | 1285 | if (__netlink_lookup(table, portid, net)) { |
1342 | sk_for_each(osk, head) { | 1286 | /* Bind collision, search negative portid values. */ |
1343 | if (!table->compare(net, osk)) | 1287 | portid = rover--; |
1344 | continue; | 1288 | if (rover > -4097) |
1345 | if (nlk_sk(osk)->portid == portid) { | 1289 | rover = -4097; |
1346 | /* Bind collision, search negative portid values. */ | 1290 | rcu_read_unlock(); |
1347 | portid = rover--; | 1291 | goto retry; |
1348 | if (rover > -4097) | ||
1349 | rover = -4097; | ||
1350 | netlink_table_ungrab(); | ||
1351 | goto retry; | ||
1352 | } | ||
1353 | } | 1292 | } |
1354 | netlink_table_ungrab(); | 1293 | rcu_read_unlock(); |
1355 | 1294 | ||
1356 | err = netlink_insert(sk, net, portid); | 1295 | err = netlink_insert(sk, net, portid); |
1357 | if (err == -EADDRINUSE) | 1296 | if (err == -EADDRINUSE) |
@@ -1961,25 +1900,25 @@ struct netlink_broadcast_data { | |||
1961 | void *tx_data; | 1900 | void *tx_data; |
1962 | }; | 1901 | }; |
1963 | 1902 | ||
1964 | static int do_one_broadcast(struct sock *sk, | 1903 | static void do_one_broadcast(struct sock *sk, |
1965 | struct netlink_broadcast_data *p) | 1904 | struct netlink_broadcast_data *p) |
1966 | { | 1905 | { |
1967 | struct netlink_sock *nlk = nlk_sk(sk); | 1906 | struct netlink_sock *nlk = nlk_sk(sk); |
1968 | int val; | 1907 | int val; |
1969 | 1908 | ||
1970 | if (p->exclude_sk == sk) | 1909 | if (p->exclude_sk == sk) |
1971 | goto out; | 1910 | return; |
1972 | 1911 | ||
1973 | if (nlk->portid == p->portid || p->group - 1 >= nlk->ngroups || | 1912 | if (nlk->portid == p->portid || p->group - 1 >= nlk->ngroups || |
1974 | !test_bit(p->group - 1, nlk->groups)) | 1913 | !test_bit(p->group - 1, nlk->groups)) |
1975 | goto out; | 1914 | return; |
1976 | 1915 | ||
1977 | if (!net_eq(sock_net(sk), p->net)) | 1916 | if (!net_eq(sock_net(sk), p->net)) |
1978 | goto out; | 1917 | return; |
1979 | 1918 | ||
1980 | if (p->failure) { | 1919 | if (p->failure) { |
1981 | netlink_overrun(sk); | 1920 | netlink_overrun(sk); |
1982 | goto out; | 1921 | return; |
1983 | } | 1922 | } |
1984 | 1923 | ||
1985 | sock_hold(sk); | 1924 | sock_hold(sk); |
@@ -2017,9 +1956,6 @@ static int do_one_broadcast(struct sock *sk, | |||
2017 | p->skb2 = NULL; | 1956 | p->skb2 = NULL; |
2018 | } | 1957 | } |
2019 | sock_put(sk); | 1958 | sock_put(sk); |
2020 | |||
2021 | out: | ||
2022 | return 0; | ||
2023 | } | 1959 | } |
2024 | 1960 | ||
2025 | int netlink_broadcast_filtered(struct sock *ssk, struct sk_buff *skb, u32 portid, | 1961 | int netlink_broadcast_filtered(struct sock *ssk, struct sk_buff *skb, u32 portid, |
@@ -2958,14 +2894,18 @@ static struct sock *netlink_seq_socket_idx(struct seq_file *seq, loff_t pos) | |||
2958 | { | 2894 | { |
2959 | struct nl_seq_iter *iter = seq->private; | 2895 | struct nl_seq_iter *iter = seq->private; |
2960 | int i, j; | 2896 | int i, j; |
2897 | struct netlink_sock *nlk; | ||
2961 | struct sock *s; | 2898 | struct sock *s; |
2962 | loff_t off = 0; | 2899 | loff_t off = 0; |
2963 | 2900 | ||
2964 | for (i = 0; i < MAX_LINKS; i++) { | 2901 | for (i = 0; i < MAX_LINKS; i++) { |
2965 | struct nl_portid_hash *hash = &nl_table[i].hash; | 2902 | struct rhashtable *ht = &nl_table[i].hash; |
2903 | const struct bucket_table *tbl = rht_dereference_rcu(ht->tbl, ht); | ||
2904 | |||
2905 | for (j = 0; j < tbl->size; j++) { | ||
2906 | rht_for_each_entry_rcu(nlk, tbl->buckets[j], node) { | ||
2907 | s = (struct sock *)nlk; | ||
2966 | 2908 | ||
2967 | for (j = 0; j <= hash->mask; j++) { | ||
2968 | sk_for_each(s, &hash->table[j]) { | ||
2969 | if (sock_net(s) != seq_file_net(seq)) | 2909 | if (sock_net(s) != seq_file_net(seq)) |
2970 | continue; | 2910 | continue; |
2971 | if (off == pos) { | 2911 | if (off == pos) { |
@@ -2981,15 +2921,15 @@ static struct sock *netlink_seq_socket_idx(struct seq_file *seq, loff_t pos) | |||
2981 | } | 2921 | } |
2982 | 2922 | ||
2983 | static void *netlink_seq_start(struct seq_file *seq, loff_t *pos) | 2923 | static void *netlink_seq_start(struct seq_file *seq, loff_t *pos) |
2984 | __acquires(nl_table_lock) | 2924 | __acquires(RCU) |
2985 | { | 2925 | { |
2986 | read_lock(&nl_table_lock); | 2926 | rcu_read_lock(); |
2987 | return *pos ? netlink_seq_socket_idx(seq, *pos - 1) : SEQ_START_TOKEN; | 2927 | return *pos ? netlink_seq_socket_idx(seq, *pos - 1) : SEQ_START_TOKEN; |
2988 | } | 2928 | } |
2989 | 2929 | ||
2990 | static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos) | 2930 | static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos) |
2991 | { | 2931 | { |
2992 | struct sock *s; | 2932 | struct netlink_sock *nlk; |
2993 | struct nl_seq_iter *iter; | 2933 | struct nl_seq_iter *iter; |
2994 | struct net *net; | 2934 | struct net *net; |
2995 | int i, j; | 2935 | int i, j; |
@@ -3001,28 +2941,26 @@ static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
3001 | 2941 | ||
3002 | net = seq_file_net(seq); | 2942 | net = seq_file_net(seq); |
3003 | iter = seq->private; | 2943 | iter = seq->private; |
3004 | s = v; | 2944 | nlk = v; |
3005 | do { | 2945 | |
3006 | s = sk_next(s); | 2946 | rht_for_each_entry_rcu(nlk, nlk->node.next, node) |
3007 | } while (s && !nl_table[s->sk_protocol].compare(net, s)); | 2947 | if (net_eq(sock_net((struct sock *)nlk), net)) |
3008 | if (s) | 2948 | return nlk; |
3009 | return s; | ||
3010 | 2949 | ||
3011 | i = iter->link; | 2950 | i = iter->link; |
3012 | j = iter->hash_idx + 1; | 2951 | j = iter->hash_idx + 1; |
3013 | 2952 | ||
3014 | do { | 2953 | do { |
3015 | struct nl_portid_hash *hash = &nl_table[i].hash; | 2954 | struct rhashtable *ht = &nl_table[i].hash; |
3016 | 2955 | const struct bucket_table *tbl = rht_dereference_rcu(ht->tbl, ht); | |
3017 | for (; j <= hash->mask; j++) { | ||
3018 | s = sk_head(&hash->table[j]); | ||
3019 | 2956 | ||
3020 | while (s && !nl_table[s->sk_protocol].compare(net, s)) | 2957 | for (; j < tbl->size; j++) { |
3021 | s = sk_next(s); | 2958 | rht_for_each_entry_rcu(nlk, tbl->buckets[j], node) { |
3022 | if (s) { | 2959 | if (net_eq(sock_net((struct sock *)nlk), net)) { |
3023 | iter->link = i; | 2960 | iter->link = i; |
3024 | iter->hash_idx = j; | 2961 | iter->hash_idx = j; |
3025 | return s; | 2962 | return nlk; |
2963 | } | ||
3026 | } | 2964 | } |
3027 | } | 2965 | } |
3028 | 2966 | ||
@@ -3033,9 +2971,9 @@ static void *netlink_seq_next(struct seq_file *seq, void *v, loff_t *pos) | |||
3033 | } | 2971 | } |
3034 | 2972 | ||
3035 | static void netlink_seq_stop(struct seq_file *seq, void *v) | 2973 | static void netlink_seq_stop(struct seq_file *seq, void *v) |
3036 | __releases(nl_table_lock) | 2974 | __releases(RCU) |
3037 | { | 2975 | { |
3038 | read_unlock(&nl_table_lock); | 2976 | rcu_read_unlock(); |
3039 | } | 2977 | } |
3040 | 2978 | ||
3041 | 2979 | ||
@@ -3173,9 +3111,17 @@ static struct pernet_operations __net_initdata netlink_net_ops = { | |||
3173 | static int __init netlink_proto_init(void) | 3111 | static int __init netlink_proto_init(void) |
3174 | { | 3112 | { |
3175 | int i; | 3113 | int i; |
3176 | unsigned long limit; | ||
3177 | unsigned int order; | ||
3178 | int err = proto_register(&netlink_proto, 0); | 3114 | int err = proto_register(&netlink_proto, 0); |
3115 | struct rhashtable_params ht_params = { | ||
3116 | .head_offset = offsetof(struct netlink_sock, node), | ||
3117 | .key_offset = offsetof(struct netlink_sock, portid), | ||
3118 | .key_len = sizeof(u32), /* portid */ | ||
3119 | .hashfn = arch_fast_hash, | ||
3120 | .max_shift = 16, /* 64K */ | ||
3121 | .grow_decision = rht_grow_above_75, | ||
3122 | .shrink_decision = rht_shrink_below_30, | ||
3123 | .mutex_is_held = lockdep_nl_sk_hash_is_held, | ||
3124 | }; | ||
3179 | 3125 | ||
3180 | if (err != 0) | 3126 | if (err != 0) |
3181 | goto out; | 3127 | goto out; |
@@ -3186,32 +3132,13 @@ static int __init netlink_proto_init(void) | |||
3186 | if (!nl_table) | 3132 | if (!nl_table) |
3187 | goto panic; | 3133 | goto panic; |
3188 | 3134 | ||
3189 | if (totalram_pages >= (128 * 1024)) | ||
3190 | limit = totalram_pages >> (21 - PAGE_SHIFT); | ||
3191 | else | ||
3192 | limit = totalram_pages >> (23 - PAGE_SHIFT); | ||
3193 | |||
3194 | order = get_bitmask_order(limit) - 1 + PAGE_SHIFT; | ||
3195 | limit = (1UL << order) / sizeof(struct hlist_head); | ||
3196 | order = get_bitmask_order(min(limit, (unsigned long)UINT_MAX)) - 1; | ||
3197 | |||
3198 | for (i = 0; i < MAX_LINKS; i++) { | 3135 | for (i = 0; i < MAX_LINKS; i++) { |
3199 | struct nl_portid_hash *hash = &nl_table[i].hash; | 3136 | if (rhashtable_init(&nl_table[i].hash, &ht_params) < 0) { |
3200 | 3137 | while (--i > 0) | |
3201 | hash->table = nl_portid_hash_zalloc(1 * sizeof(*hash->table)); | 3138 | rhashtable_destroy(&nl_table[i].hash); |
3202 | if (!hash->table) { | ||
3203 | while (i-- > 0) | ||
3204 | nl_portid_hash_free(nl_table[i].hash.table, | ||
3205 | 1 * sizeof(*hash->table)); | ||
3206 | kfree(nl_table); | 3139 | kfree(nl_table); |
3207 | goto panic; | 3140 | goto panic; |
3208 | } | 3141 | } |
3209 | hash->max_shift = order; | ||
3210 | hash->shift = 0; | ||
3211 | hash->mask = 0; | ||
3212 | hash->rehash_time = jiffies; | ||
3213 | |||
3214 | nl_table[i].compare = netlink_compare; | ||
3215 | } | 3142 | } |
3216 | 3143 | ||
3217 | INIT_LIST_HEAD(&netlink_tap_all); | 3144 | INIT_LIST_HEAD(&netlink_tap_all); |
diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h index 0b59d441f5b6..b20a1731759b 100644 --- a/net/netlink/af_netlink.h +++ b/net/netlink/af_netlink.h | |||
@@ -1,6 +1,7 @@ | |||
1 | #ifndef _AF_NETLINK_H | 1 | #ifndef _AF_NETLINK_H |
2 | #define _AF_NETLINK_H | 2 | #define _AF_NETLINK_H |
3 | 3 | ||
4 | #include <linux/rhashtable.h> | ||
4 | #include <net/sock.h> | 5 | #include <net/sock.h> |
5 | 6 | ||
6 | #define NLGRPSZ(x) (ALIGN(x, sizeof(unsigned long) * 8) / 8) | 7 | #define NLGRPSZ(x) (ALIGN(x, sizeof(unsigned long) * 8) / 8) |
@@ -47,6 +48,8 @@ struct netlink_sock { | |||
47 | struct netlink_ring tx_ring; | 48 | struct netlink_ring tx_ring; |
48 | atomic_t mapped; | 49 | atomic_t mapped; |
49 | #endif /* CONFIG_NETLINK_MMAP */ | 50 | #endif /* CONFIG_NETLINK_MMAP */ |
51 | |||
52 | struct rhash_head node; | ||
50 | }; | 53 | }; |
51 | 54 | ||
52 | static inline struct netlink_sock *nlk_sk(struct sock *sk) | 55 | static inline struct netlink_sock *nlk_sk(struct sock *sk) |
@@ -54,21 +57,8 @@ static inline struct netlink_sock *nlk_sk(struct sock *sk) | |||
54 | return container_of(sk, struct netlink_sock, sk); | 57 | return container_of(sk, struct netlink_sock, sk); |
55 | } | 58 | } |
56 | 59 | ||
57 | struct nl_portid_hash { | ||
58 | struct hlist_head *table; | ||
59 | unsigned long rehash_time; | ||
60 | |||
61 | unsigned int mask; | ||
62 | unsigned int shift; | ||
63 | |||
64 | unsigned int entries; | ||
65 | unsigned int max_shift; | ||
66 | |||
67 | u32 rnd; | ||
68 | }; | ||
69 | |||
70 | struct netlink_table { | 60 | struct netlink_table { |
71 | struct nl_portid_hash hash; | 61 | struct rhashtable hash; |
72 | struct hlist_head mc_list; | 62 | struct hlist_head mc_list; |
73 | struct listeners __rcu *listeners; | 63 | struct listeners __rcu *listeners; |
74 | unsigned int flags; | 64 | unsigned int flags; |
@@ -83,5 +73,6 @@ struct netlink_table { | |||
83 | 73 | ||
84 | extern struct netlink_table *nl_table; | 74 | extern struct netlink_table *nl_table; |
85 | extern rwlock_t nl_table_lock; | 75 | extern rwlock_t nl_table_lock; |
76 | extern struct mutex nl_sk_hash_lock; | ||
86 | 77 | ||
87 | #endif | 78 | #endif |
diff --git a/net/netlink/diag.c b/net/netlink/diag.c index 1af29624b92f..de8c74a3c061 100644 --- a/net/netlink/diag.c +++ b/net/netlink/diag.c | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <linux/netlink.h> | 4 | #include <linux/netlink.h> |
5 | #include <linux/sock_diag.h> | 5 | #include <linux/sock_diag.h> |
6 | #include <linux/netlink_diag.h> | 6 | #include <linux/netlink_diag.h> |
7 | #include <linux/rhashtable.h> | ||
7 | 8 | ||
8 | #include "af_netlink.h" | 9 | #include "af_netlink.h" |
9 | 10 | ||
@@ -101,16 +102,20 @@ static int __netlink_diag_dump(struct sk_buff *skb, struct netlink_callback *cb, | |||
101 | int protocol, int s_num) | 102 | int protocol, int s_num) |
102 | { | 103 | { |
103 | struct netlink_table *tbl = &nl_table[protocol]; | 104 | struct netlink_table *tbl = &nl_table[protocol]; |
104 | struct nl_portid_hash *hash = &tbl->hash; | 105 | struct rhashtable *ht = &tbl->hash; |
106 | const struct bucket_table *htbl = rht_dereference(ht->tbl, ht); | ||
105 | struct net *net = sock_net(skb->sk); | 107 | struct net *net = sock_net(skb->sk); |
106 | struct netlink_diag_req *req; | 108 | struct netlink_diag_req *req; |
109 | struct netlink_sock *nlsk; | ||
107 | struct sock *sk; | 110 | struct sock *sk; |
108 | int ret = 0, num = 0, i; | 111 | int ret = 0, num = 0, i; |
109 | 112 | ||
110 | req = nlmsg_data(cb->nlh); | 113 | req = nlmsg_data(cb->nlh); |
111 | 114 | ||
112 | for (i = 0; i <= hash->mask; i++) { | 115 | for (i = 0; i < htbl->size; i++) { |
113 | sk_for_each(sk, &hash->table[i]) { | 116 | rht_for_each_entry(nlsk, htbl->buckets[i], ht, node) { |
117 | sk = (struct sock *)nlsk; | ||
118 | |||
114 | if (!net_eq(sock_net(sk), net)) | 119 | if (!net_eq(sock_net(sk), net)) |
115 | continue; | 120 | continue; |
116 | if (num < s_num) { | 121 | if (num < s_num) { |
@@ -165,6 +170,7 @@ static int netlink_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
165 | 170 | ||
166 | req = nlmsg_data(cb->nlh); | 171 | req = nlmsg_data(cb->nlh); |
167 | 172 | ||
173 | mutex_lock(&nl_sk_hash_lock); | ||
168 | read_lock(&nl_table_lock); | 174 | read_lock(&nl_table_lock); |
169 | 175 | ||
170 | if (req->sdiag_protocol == NDIAG_PROTO_ALL) { | 176 | if (req->sdiag_protocol == NDIAG_PROTO_ALL) { |
@@ -178,6 +184,7 @@ static int netlink_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
178 | } else { | 184 | } else { |
179 | if (req->sdiag_protocol >= MAX_LINKS) { | 185 | if (req->sdiag_protocol >= MAX_LINKS) { |
180 | read_unlock(&nl_table_lock); | 186 | read_unlock(&nl_table_lock); |
187 | mutex_unlock(&nl_sk_hash_lock); | ||
181 | return -ENOENT; | 188 | return -ENOENT; |
182 | } | 189 | } |
183 | 190 | ||
@@ -185,6 +192,7 @@ static int netlink_diag_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
185 | } | 192 | } |
186 | 193 | ||
187 | read_unlock(&nl_table_lock); | 194 | read_unlock(&nl_table_lock); |
195 | mutex_unlock(&nl_sk_hash_lock); | ||
188 | 196 | ||
189 | return skb->len; | 197 | return skb->len; |
190 | } | 198 | } |
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index ede50d197e10..71cf1bffea06 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c | |||
@@ -1418,7 +1418,7 @@ static int __init nr_proto_init(void) | |||
1418 | struct net_device *dev; | 1418 | struct net_device *dev; |
1419 | 1419 | ||
1420 | sprintf(name, "nr%d", i); | 1420 | sprintf(name, "nr%d", i); |
1421 | dev = alloc_netdev(0, name, nr_setup); | 1421 | dev = alloc_netdev(0, name, NET_NAME_UNKNOWN, nr_setup); |
1422 | if (!dev) { | 1422 | if (!dev) { |
1423 | printk(KERN_ERR "NET/ROM: nr_proto_init - unable to allocate device structure\n"); | 1423 | printk(KERN_ERR "NET/ROM: nr_proto_init - unable to allocate device structure\n"); |
1424 | goto fail; | 1424 | goto fail; |
diff --git a/net/nfc/digital.h b/net/nfc/digital.h index 71ad7eefddd4..3c39c72eb038 100644 --- a/net/nfc/digital.h +++ b/net/nfc/digital.h | |||
@@ -29,6 +29,7 @@ | |||
29 | #define DIGITAL_CMD_TG_SEND 1 | 29 | #define DIGITAL_CMD_TG_SEND 1 |
30 | #define DIGITAL_CMD_TG_LISTEN 2 | 30 | #define DIGITAL_CMD_TG_LISTEN 2 |
31 | #define DIGITAL_CMD_TG_LISTEN_MDAA 3 | 31 | #define DIGITAL_CMD_TG_LISTEN_MDAA 3 |
32 | #define DIGITAL_CMD_TG_LISTEN_MD 4 | ||
32 | 33 | ||
33 | #define DIGITAL_MAX_HEADER_LEN 7 | 34 | #define DIGITAL_MAX_HEADER_LEN 7 |
34 | #define DIGITAL_CRC_LEN 2 | 35 | #define DIGITAL_CRC_LEN 2 |
@@ -121,6 +122,8 @@ int digital_tg_send_dep_res(struct nfc_digital_dev *ddev, struct sk_buff *skb); | |||
121 | 122 | ||
122 | int digital_tg_listen_nfca(struct nfc_digital_dev *ddev, u8 rf_tech); | 123 | int digital_tg_listen_nfca(struct nfc_digital_dev *ddev, u8 rf_tech); |
123 | int digital_tg_listen_nfcf(struct nfc_digital_dev *ddev, u8 rf_tech); | 124 | int digital_tg_listen_nfcf(struct nfc_digital_dev *ddev, u8 rf_tech); |
125 | void digital_tg_recv_md_req(struct nfc_digital_dev *ddev, void *arg, | ||
126 | struct sk_buff *resp); | ||
124 | 127 | ||
125 | typedef u16 (*crc_func_t)(u16, const u8 *, size_t); | 128 | typedef u16 (*crc_func_t)(u16, const u8 *, size_t); |
126 | 129 | ||
diff --git a/net/nfc/digital_core.c b/net/nfc/digital_core.c index a6ce3c627e4e..009bcf317101 100644 --- a/net/nfc/digital_core.c +++ b/net/nfc/digital_core.c | |||
@@ -201,6 +201,11 @@ static void digital_wq_cmd(struct work_struct *work) | |||
201 | digital_send_cmd_complete, cmd); | 201 | digital_send_cmd_complete, cmd); |
202 | break; | 202 | break; |
203 | 203 | ||
204 | case DIGITAL_CMD_TG_LISTEN_MD: | ||
205 | rc = ddev->ops->tg_listen_md(ddev, cmd->timeout, | ||
206 | digital_send_cmd_complete, cmd); | ||
207 | break; | ||
208 | |||
204 | default: | 209 | default: |
205 | pr_err("Unknown cmd type %d\n", cmd->type); | 210 | pr_err("Unknown cmd type %d\n", cmd->type); |
206 | return; | 211 | return; |
@@ -293,12 +298,19 @@ static int digital_tg_listen_mdaa(struct nfc_digital_dev *ddev, u8 rf_tech) | |||
293 | 500, digital_tg_recv_atr_req, NULL); | 298 | 500, digital_tg_recv_atr_req, NULL); |
294 | } | 299 | } |
295 | 300 | ||
301 | static int digital_tg_listen_md(struct nfc_digital_dev *ddev, u8 rf_tech) | ||
302 | { | ||
303 | return digital_send_cmd(ddev, DIGITAL_CMD_TG_LISTEN_MD, NULL, NULL, 500, | ||
304 | digital_tg_recv_md_req, NULL); | ||
305 | } | ||
306 | |||
296 | int digital_target_found(struct nfc_digital_dev *ddev, | 307 | int digital_target_found(struct nfc_digital_dev *ddev, |
297 | struct nfc_target *target, u8 protocol) | 308 | struct nfc_target *target, u8 protocol) |
298 | { | 309 | { |
299 | int rc; | 310 | int rc; |
300 | u8 framing; | 311 | u8 framing; |
301 | u8 rf_tech; | 312 | u8 rf_tech; |
313 | u8 poll_tech_count; | ||
302 | int (*check_crc)(struct sk_buff *skb); | 314 | int (*check_crc)(struct sk_buff *skb); |
303 | void (*add_crc)(struct sk_buff *skb); | 315 | void (*add_crc)(struct sk_buff *skb); |
304 | 316 | ||
@@ -375,12 +387,16 @@ int digital_target_found(struct nfc_digital_dev *ddev, | |||
375 | return rc; | 387 | return rc; |
376 | 388 | ||
377 | target->supported_protocols = (1 << protocol); | 389 | target->supported_protocols = (1 << protocol); |
378 | rc = nfc_targets_found(ddev->nfc_dev, target, 1); | ||
379 | if (rc) | ||
380 | return rc; | ||
381 | 390 | ||
391 | poll_tech_count = ddev->poll_tech_count; | ||
382 | ddev->poll_tech_count = 0; | 392 | ddev->poll_tech_count = 0; |
383 | 393 | ||
394 | rc = nfc_targets_found(ddev->nfc_dev, target, 1); | ||
395 | if (rc) { | ||
396 | ddev->poll_tech_count = poll_tech_count; | ||
397 | return rc; | ||
398 | } | ||
399 | |||
384 | return 0; | 400 | return 0; |
385 | } | 401 | } |
386 | 402 | ||
@@ -505,6 +521,9 @@ static int digital_start_poll(struct nfc_dev *nfc_dev, __u32 im_protocols, | |||
505 | if (ddev->ops->tg_listen_mdaa) { | 521 | if (ddev->ops->tg_listen_mdaa) { |
506 | digital_add_poll_tech(ddev, 0, | 522 | digital_add_poll_tech(ddev, 0, |
507 | digital_tg_listen_mdaa); | 523 | digital_tg_listen_mdaa); |
524 | } else if (ddev->ops->tg_listen_md) { | ||
525 | digital_add_poll_tech(ddev, 0, | ||
526 | digital_tg_listen_md); | ||
508 | } else { | 527 | } else { |
509 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_106A, | 528 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_106A, |
510 | digital_tg_listen_nfca); | 529 | digital_tg_listen_nfca); |
@@ -732,7 +751,7 @@ struct nfc_digital_dev *nfc_digital_allocate_device(struct nfc_digital_ops *ops, | |||
732 | 751 | ||
733 | if (!ops->in_configure_hw || !ops->in_send_cmd || !ops->tg_listen || | 752 | if (!ops->in_configure_hw || !ops->in_send_cmd || !ops->tg_listen || |
734 | !ops->tg_configure_hw || !ops->tg_send_cmd || !ops->abort_cmd || | 753 | !ops->tg_configure_hw || !ops->tg_send_cmd || !ops->abort_cmd || |
735 | !ops->switch_rf) | 754 | !ops->switch_rf || (ops->tg_listen_md && !ops->tg_get_rf_tech)) |
736 | return NULL; | 755 | return NULL; |
737 | 756 | ||
738 | ddev = kzalloc(sizeof(struct nfc_digital_dev), GFP_KERNEL); | 757 | ddev = kzalloc(sizeof(struct nfc_digital_dev), GFP_KERNEL); |
diff --git a/net/nfc/digital_dep.c b/net/nfc/digital_dep.c index 171cb9949ab5..e1638dab076d 100644 --- a/net/nfc/digital_dep.c +++ b/net/nfc/digital_dep.c | |||
@@ -457,12 +457,10 @@ static void digital_tg_recv_dep_req(struct nfc_digital_dev *ddev, void *arg, | |||
457 | pr_err("Received a ACK/NACK PDU\n"); | 457 | pr_err("Received a ACK/NACK PDU\n"); |
458 | rc = -EINVAL; | 458 | rc = -EINVAL; |
459 | goto exit; | 459 | goto exit; |
460 | break; | ||
461 | case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU: | 460 | case DIGITAL_NFC_DEP_PFB_SUPERVISOR_PDU: |
462 | pr_err("Received a SUPERVISOR PDU\n"); | 461 | pr_err("Received a SUPERVISOR PDU\n"); |
463 | rc = -EINVAL; | 462 | rc = -EINVAL; |
464 | goto exit; | 463 | goto exit; |
465 | break; | ||
466 | } | 464 | } |
467 | 465 | ||
468 | skb_pull(resp, size); | 466 | skb_pull(resp, size); |
@@ -673,6 +671,7 @@ void digital_tg_recv_atr_req(struct nfc_digital_dev *ddev, void *arg, | |||
673 | int rc; | 671 | int rc; |
674 | struct digital_atr_req *atr_req; | 672 | struct digital_atr_req *atr_req; |
675 | size_t gb_len, min_size; | 673 | size_t gb_len, min_size; |
674 | u8 poll_tech_count; | ||
676 | 675 | ||
677 | if (IS_ERR(resp)) { | 676 | if (IS_ERR(resp)) { |
678 | rc = PTR_ERR(resp); | 677 | rc = PTR_ERR(resp); |
@@ -730,12 +729,16 @@ void digital_tg_recv_atr_req(struct nfc_digital_dev *ddev, void *arg, | |||
730 | goto exit; | 729 | goto exit; |
731 | 730 | ||
732 | gb_len = resp->len - sizeof(struct digital_atr_req); | 731 | gb_len = resp->len - sizeof(struct digital_atr_req); |
732 | |||
733 | poll_tech_count = ddev->poll_tech_count; | ||
734 | ddev->poll_tech_count = 0; | ||
735 | |||
733 | rc = nfc_tm_activated(ddev->nfc_dev, NFC_PROTO_NFC_DEP_MASK, | 736 | rc = nfc_tm_activated(ddev->nfc_dev, NFC_PROTO_NFC_DEP_MASK, |
734 | NFC_COMM_PASSIVE, atr_req->gb, gb_len); | 737 | NFC_COMM_PASSIVE, atr_req->gb, gb_len); |
735 | if (rc) | 738 | if (rc) { |
739 | ddev->poll_tech_count = poll_tech_count; | ||
736 | goto exit; | 740 | goto exit; |
737 | 741 | } | |
738 | ddev->poll_tech_count = 0; | ||
739 | 742 | ||
740 | rc = 0; | 743 | rc = 0; |
741 | exit: | 744 | exit: |
diff --git a/net/nfc/digital_technology.c b/net/nfc/digital_technology.c index c2c1c0189b7c..fb58ed2dd41d 100644 --- a/net/nfc/digital_technology.c +++ b/net/nfc/digital_technology.c | |||
@@ -318,6 +318,8 @@ static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg, | |||
318 | 318 | ||
319 | if (DIGITAL_SEL_RES_IS_T2T(sel_res)) { | 319 | if (DIGITAL_SEL_RES_IS_T2T(sel_res)) { |
320 | nfc_proto = NFC_PROTO_MIFARE; | 320 | nfc_proto = NFC_PROTO_MIFARE; |
321 | } else if (DIGITAL_SEL_RES_IS_NFC_DEP(sel_res)) { | ||
322 | nfc_proto = NFC_PROTO_NFC_DEP; | ||
321 | } else if (DIGITAL_SEL_RES_IS_T4T(sel_res)) { | 323 | } else if (DIGITAL_SEL_RES_IS_T4T(sel_res)) { |
322 | rc = digital_in_send_rats(ddev, target); | 324 | rc = digital_in_send_rats(ddev, target); |
323 | if (rc) | 325 | if (rc) |
@@ -327,8 +329,6 @@ static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg, | |||
327 | * done when receiving the ATS | 329 | * done when receiving the ATS |
328 | */ | 330 | */ |
329 | goto exit_free_skb; | 331 | goto exit_free_skb; |
330 | } else if (DIGITAL_SEL_RES_IS_NFC_DEP(sel_res)) { | ||
331 | nfc_proto = NFC_PROTO_NFC_DEP; | ||
332 | } else { | 332 | } else { |
333 | rc = -EOPNOTSUPP; | 333 | rc = -EOPNOTSUPP; |
334 | goto exit; | 334 | goto exit; |
@@ -944,6 +944,13 @@ static int digital_tg_send_sel_res(struct nfc_digital_dev *ddev) | |||
944 | if (!DIGITAL_DRV_CAPS_TG_CRC(ddev)) | 944 | if (!DIGITAL_DRV_CAPS_TG_CRC(ddev)) |
945 | digital_skb_add_crc_a(skb); | 945 | digital_skb_add_crc_a(skb); |
946 | 946 | ||
947 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | ||
948 | NFC_DIGITAL_FRAMING_NFCA_ANTICOL_COMPLETE); | ||
949 | if (rc) { | ||
950 | kfree_skb(skb); | ||
951 | return rc; | ||
952 | } | ||
953 | |||
947 | rc = digital_tg_send_cmd(ddev, skb, 300, digital_tg_recv_atr_req, | 954 | rc = digital_tg_send_cmd(ddev, skb, 300, digital_tg_recv_atr_req, |
948 | NULL); | 955 | NULL); |
949 | if (rc) | 956 | if (rc) |
@@ -1002,6 +1009,13 @@ static int digital_tg_send_sdd_res(struct nfc_digital_dev *ddev) | |||
1002 | for (i = 0; i < 4; i++) | 1009 | for (i = 0; i < 4; i++) |
1003 | sdd_res->bcc ^= sdd_res->nfcid1[i]; | 1010 | sdd_res->bcc ^= sdd_res->nfcid1[i]; |
1004 | 1011 | ||
1012 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | ||
1013 | NFC_DIGITAL_FRAMING_NFCA_STANDARD_WITH_CRC_A); | ||
1014 | if (rc) { | ||
1015 | kfree_skb(skb); | ||
1016 | return rc; | ||
1017 | } | ||
1018 | |||
1005 | rc = digital_tg_send_cmd(ddev, skb, 300, digital_tg_recv_sel_req, | 1019 | rc = digital_tg_send_cmd(ddev, skb, 300, digital_tg_recv_sel_req, |
1006 | NULL); | 1020 | NULL); |
1007 | if (rc) | 1021 | if (rc) |
@@ -1054,6 +1068,13 @@ static int digital_tg_send_sens_res(struct nfc_digital_dev *ddev) | |||
1054 | sens_res[0] = (DIGITAL_SENS_RES_NFC_DEP >> 8) & 0xFF; | 1068 | sens_res[0] = (DIGITAL_SENS_RES_NFC_DEP >> 8) & 0xFF; |
1055 | sens_res[1] = DIGITAL_SENS_RES_NFC_DEP & 0xFF; | 1069 | sens_res[1] = DIGITAL_SENS_RES_NFC_DEP & 0xFF; |
1056 | 1070 | ||
1071 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | ||
1072 | NFC_DIGITAL_FRAMING_NFCA_STANDARD); | ||
1073 | if (rc) { | ||
1074 | kfree_skb(skb); | ||
1075 | return rc; | ||
1076 | } | ||
1077 | |||
1057 | rc = digital_tg_send_cmd(ddev, skb, 300, digital_tg_recv_sdd_req, | 1078 | rc = digital_tg_send_cmd(ddev, skb, 300, digital_tg_recv_sdd_req, |
1058 | NULL); | 1079 | NULL); |
1059 | if (rc) | 1080 | if (rc) |
@@ -1197,33 +1218,48 @@ exit: | |||
1197 | dev_kfree_skb(resp); | 1218 | dev_kfree_skb(resp); |
1198 | } | 1219 | } |
1199 | 1220 | ||
1200 | int digital_tg_listen_nfca(struct nfc_digital_dev *ddev, u8 rf_tech) | 1221 | static int digital_tg_config_nfca(struct nfc_digital_dev *ddev) |
1201 | { | 1222 | { |
1202 | int rc; | 1223 | int rc; |
1203 | 1224 | ||
1204 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, rf_tech); | 1225 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, |
1226 | NFC_DIGITAL_RF_TECH_106A); | ||
1205 | if (rc) | 1227 | if (rc) |
1206 | return rc; | 1228 | return rc; |
1207 | 1229 | ||
1208 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | 1230 | return digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, |
1209 | NFC_DIGITAL_FRAMING_NFCA_NFC_DEP); | 1231 | NFC_DIGITAL_FRAMING_NFCA_NFC_DEP); |
1232 | } | ||
1233 | |||
1234 | int digital_tg_listen_nfca(struct nfc_digital_dev *ddev, u8 rf_tech) | ||
1235 | { | ||
1236 | int rc; | ||
1237 | |||
1238 | rc = digital_tg_config_nfca(ddev); | ||
1210 | if (rc) | 1239 | if (rc) |
1211 | return rc; | 1240 | return rc; |
1212 | 1241 | ||
1213 | return digital_tg_listen(ddev, 300, digital_tg_recv_sens_req, NULL); | 1242 | return digital_tg_listen(ddev, 300, digital_tg_recv_sens_req, NULL); |
1214 | } | 1243 | } |
1215 | 1244 | ||
1216 | int digital_tg_listen_nfcf(struct nfc_digital_dev *ddev, u8 rf_tech) | 1245 | static int digital_tg_config_nfcf(struct nfc_digital_dev *ddev, u8 rf_tech) |
1217 | { | 1246 | { |
1218 | int rc; | 1247 | int rc; |
1219 | u8 *nfcid2; | ||
1220 | 1248 | ||
1221 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, rf_tech); | 1249 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, rf_tech); |
1222 | if (rc) | 1250 | if (rc) |
1223 | return rc; | 1251 | return rc; |
1224 | 1252 | ||
1225 | rc = digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | 1253 | return digital_tg_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, |
1226 | NFC_DIGITAL_FRAMING_NFCF_NFC_DEP); | 1254 | NFC_DIGITAL_FRAMING_NFCF_NFC_DEP); |
1255 | } | ||
1256 | |||
1257 | int digital_tg_listen_nfcf(struct nfc_digital_dev *ddev, u8 rf_tech) | ||
1258 | { | ||
1259 | int rc; | ||
1260 | u8 *nfcid2; | ||
1261 | |||
1262 | rc = digital_tg_config_nfcf(ddev, rf_tech); | ||
1227 | if (rc) | 1263 | if (rc) |
1228 | return rc; | 1264 | return rc; |
1229 | 1265 | ||
@@ -1237,3 +1273,43 @@ int digital_tg_listen_nfcf(struct nfc_digital_dev *ddev, u8 rf_tech) | |||
1237 | 1273 | ||
1238 | return digital_tg_listen(ddev, 300, digital_tg_recv_sensf_req, nfcid2); | 1274 | return digital_tg_listen(ddev, 300, digital_tg_recv_sensf_req, nfcid2); |
1239 | } | 1275 | } |
1276 | |||
1277 | void digital_tg_recv_md_req(struct nfc_digital_dev *ddev, void *arg, | ||
1278 | struct sk_buff *resp) | ||
1279 | { | ||
1280 | u8 rf_tech; | ||
1281 | int rc; | ||
1282 | |||
1283 | if (IS_ERR(resp)) { | ||
1284 | resp = NULL; | ||
1285 | goto exit_free_skb; | ||
1286 | } | ||
1287 | |||
1288 | rc = ddev->ops->tg_get_rf_tech(ddev, &rf_tech); | ||
1289 | if (rc) | ||
1290 | goto exit_free_skb; | ||
1291 | |||
1292 | switch (rf_tech) { | ||
1293 | case NFC_DIGITAL_RF_TECH_106A: | ||
1294 | rc = digital_tg_config_nfca(ddev); | ||
1295 | if (rc) | ||
1296 | goto exit_free_skb; | ||
1297 | digital_tg_recv_sens_req(ddev, arg, resp); | ||
1298 | break; | ||
1299 | case NFC_DIGITAL_RF_TECH_212F: | ||
1300 | case NFC_DIGITAL_RF_TECH_424F: | ||
1301 | rc = digital_tg_config_nfcf(ddev, rf_tech); | ||
1302 | if (rc) | ||
1303 | goto exit_free_skb; | ||
1304 | digital_tg_recv_sensf_req(ddev, arg, resp); | ||
1305 | break; | ||
1306 | default: | ||
1307 | goto exit_free_skb; | ||
1308 | } | ||
1309 | |||
1310 | return; | ||
1311 | |||
1312 | exit_free_skb: | ||
1313 | digital_poll_next_tech(ddev); | ||
1314 | dev_kfree_skb(resp); | ||
1315 | } | ||
diff --git a/net/nfc/hci/core.c b/net/nfc/hci/core.c index 47403705197e..117708263ced 100644 --- a/net/nfc/hci/core.c +++ b/net/nfc/hci/core.c | |||
@@ -553,8 +553,11 @@ static void hci_stop_poll(struct nfc_dev *nfc_dev) | |||
553 | { | 553 | { |
554 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); | 554 | struct nfc_hci_dev *hdev = nfc_get_drvdata(nfc_dev); |
555 | 555 | ||
556 | nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, | 556 | if (hdev->ops->stop_poll) |
557 | NFC_HCI_EVT_END_OPERATION, NULL, 0); | 557 | hdev->ops->stop_poll(hdev); |
558 | else | ||
559 | nfc_hci_send_event(hdev, NFC_HCI_RF_READER_A_GATE, | ||
560 | NFC_HCI_EVT_END_OPERATION, NULL, 0); | ||
558 | } | 561 | } |
559 | 562 | ||
560 | static int hci_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, | 563 | static int hci_dep_link_up(struct nfc_dev *nfc_dev, struct nfc_target *target, |
diff --git a/net/nfc/nci/ntf.c b/net/nfc/nci/ntf.c index f8f6af231381..df91bb95b12a 100644 --- a/net/nfc/nci/ntf.c +++ b/net/nfc/nci/ntf.c | |||
@@ -166,7 +166,9 @@ static int nci_add_new_protocol(struct nci_dev *ndev, | |||
166 | struct rf_tech_specific_params_nfcf_poll *nfcf_poll; | 166 | struct rf_tech_specific_params_nfcf_poll *nfcf_poll; |
167 | __u32 protocol; | 167 | __u32 protocol; |
168 | 168 | ||
169 | if (rf_protocol == NCI_RF_PROTOCOL_T2T) | 169 | if (rf_protocol == NCI_RF_PROTOCOL_T1T) |
170 | protocol = NFC_PROTO_JEWEL_MASK; | ||
171 | else if (rf_protocol == NCI_RF_PROTOCOL_T2T) | ||
170 | protocol = NFC_PROTO_MIFARE_MASK; | 172 | protocol = NFC_PROTO_MIFARE_MASK; |
171 | else if (rf_protocol == NCI_RF_PROTOCOL_ISO_DEP) | 173 | else if (rf_protocol == NCI_RF_PROTOCOL_ISO_DEP) |
172 | if (rf_tech_and_mode == NCI_NFC_A_PASSIVE_POLL_MODE) | 174 | if (rf_tech_and_mode == NCI_NFC_A_PASSIVE_POLL_MODE) |
diff --git a/net/openvswitch/actions.c b/net/openvswitch/actions.c index e70d8b18e962..5231652a95d9 100644 --- a/net/openvswitch/actions.c +++ b/net/openvswitch/actions.c | |||
@@ -38,10 +38,13 @@ | |||
38 | #include "vport.h" | 38 | #include "vport.h" |
39 | 39 | ||
40 | static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, | 40 | static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, |
41 | const struct nlattr *attr, int len, bool keep_skb); | 41 | const struct nlattr *attr, int len); |
42 | 42 | ||
43 | static int make_writable(struct sk_buff *skb, int write_len) | 43 | static int make_writable(struct sk_buff *skb, int write_len) |
44 | { | 44 | { |
45 | if (!pskb_may_pull(skb, write_len)) | ||
46 | return -ENOMEM; | ||
47 | |||
45 | if (!skb_cloned(skb) || skb_clone_writable(skb, write_len)) | 48 | if (!skb_cloned(skb) || skb_clone_writable(skb, write_len)) |
46 | return 0; | 49 | return 0; |
47 | 50 | ||
@@ -70,6 +73,8 @@ static int __pop_vlan_tci(struct sk_buff *skb, __be16 *current_tci) | |||
70 | 73 | ||
71 | vlan_set_encap_proto(skb, vhdr); | 74 | vlan_set_encap_proto(skb, vhdr); |
72 | skb->mac_header += VLAN_HLEN; | 75 | skb->mac_header += VLAN_HLEN; |
76 | if (skb_network_offset(skb) < ETH_HLEN) | ||
77 | skb_set_network_header(skb, ETH_HLEN); | ||
73 | skb_reset_mac_len(skb); | 78 | skb_reset_mac_len(skb); |
74 | 79 | ||
75 | return 0; | 80 | return 0; |
@@ -434,11 +439,17 @@ static int output_userspace(struct datapath *dp, struct sk_buff *skb, | |||
434 | return ovs_dp_upcall(dp, skb, &upcall); | 439 | return ovs_dp_upcall(dp, skb, &upcall); |
435 | } | 440 | } |
436 | 441 | ||
442 | static bool last_action(const struct nlattr *a, int rem) | ||
443 | { | ||
444 | return a->nla_len == rem; | ||
445 | } | ||
446 | |||
437 | static int sample(struct datapath *dp, struct sk_buff *skb, | 447 | static int sample(struct datapath *dp, struct sk_buff *skb, |
438 | const struct nlattr *attr) | 448 | const struct nlattr *attr) |
439 | { | 449 | { |
440 | const struct nlattr *acts_list = NULL; | 450 | const struct nlattr *acts_list = NULL; |
441 | const struct nlattr *a; | 451 | const struct nlattr *a; |
452 | struct sk_buff *sample_skb; | ||
442 | int rem; | 453 | int rem; |
443 | 454 | ||
444 | for (a = nla_data(attr), rem = nla_len(attr); rem > 0; | 455 | for (a = nla_data(attr), rem = nla_len(attr); rem > 0; |
@@ -455,8 +466,34 @@ static int sample(struct datapath *dp, struct sk_buff *skb, | |||
455 | } | 466 | } |
456 | } | 467 | } |
457 | 468 | ||
458 | return do_execute_actions(dp, skb, nla_data(acts_list), | 469 | rem = nla_len(acts_list); |
459 | nla_len(acts_list), true); | 470 | a = nla_data(acts_list); |
471 | |||
472 | /* Actions list is either empty or only contains a single user-space | ||
473 | * action, the latter being a special case as it is the only known | ||
474 | * usage of the sample action. | ||
475 | * In these special cases don't clone the skb as there are no | ||
476 | * side-effects in the nested actions. | ||
477 | * Otherwise, clone in case the nested actions have side effects. | ||
478 | */ | ||
479 | if (likely(rem == 0 || (nla_type(a) == OVS_ACTION_ATTR_USERSPACE && | ||
480 | last_action(a, rem)))) { | ||
481 | sample_skb = skb; | ||
482 | skb_get(skb); | ||
483 | } else { | ||
484 | sample_skb = skb_clone(skb, GFP_ATOMIC); | ||
485 | if (!sample_skb) /* Skip sample action when out of memory. */ | ||
486 | return 0; | ||
487 | } | ||
488 | |||
489 | /* Note that do_execute_actions() never consumes skb. | ||
490 | * In the case where skb has been cloned above it is the clone that | ||
491 | * is consumed. Otherwise the skb_get(skb) call prevents | ||
492 | * consumption by do_execute_actions(). Thus, it is safe to simply | ||
493 | * return the error code and let the caller (also | ||
494 | * do_execute_actions()) free skb on error. | ||
495 | */ | ||
496 | return do_execute_actions(dp, sample_skb, a, rem); | ||
460 | } | 497 | } |
461 | 498 | ||
462 | static int execute_set_action(struct sk_buff *skb, | 499 | static int execute_set_action(struct sk_buff *skb, |
@@ -507,7 +544,7 @@ static int execute_set_action(struct sk_buff *skb, | |||
507 | 544 | ||
508 | /* Execute a list of actions against 'skb'. */ | 545 | /* Execute a list of actions against 'skb'. */ |
509 | static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, | 546 | static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, |
510 | const struct nlattr *attr, int len, bool keep_skb) | 547 | const struct nlattr *attr, int len) |
511 | { | 548 | { |
512 | /* Every output action needs a separate clone of 'skb', but the common | 549 | /* Every output action needs a separate clone of 'skb', but the common |
513 | * case is just a single output action, so that doing a clone and | 550 | * case is just a single output action, so that doing a clone and |
@@ -562,12 +599,9 @@ static int do_execute_actions(struct datapath *dp, struct sk_buff *skb, | |||
562 | } | 599 | } |
563 | } | 600 | } |
564 | 601 | ||
565 | if (prev_port != -1) { | 602 | if (prev_port != -1) |
566 | if (keep_skb) | ||
567 | skb = skb_clone(skb, GFP_ATOMIC); | ||
568 | |||
569 | do_output(dp, skb, prev_port); | 603 | do_output(dp, skb, prev_port); |
570 | } else if (!keep_skb) | 604 | else |
571 | consume_skb(skb); | 605 | consume_skb(skb); |
572 | 606 | ||
573 | return 0; | 607 | return 0; |
@@ -579,6 +613,5 @@ int ovs_execute_actions(struct datapath *dp, struct sk_buff *skb) | |||
579 | struct sw_flow_actions *acts = rcu_dereference(OVS_CB(skb)->flow->sf_acts); | 613 | struct sw_flow_actions *acts = rcu_dereference(OVS_CB(skb)->flow->sf_acts); |
580 | 614 | ||
581 | OVS_CB(skb)->tun_key = NULL; | 615 | OVS_CB(skb)->tun_key = NULL; |
582 | return do_execute_actions(dp, skb, acts->actions, | 616 | return do_execute_actions(dp, skb, acts->actions, acts->actions_len); |
583 | acts->actions_len, false); | ||
584 | } | 617 | } |
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 9db4bf6740d1..64dc864a417f 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
@@ -47,8 +47,6 @@ | |||
47 | #include <linux/openvswitch.h> | 47 | #include <linux/openvswitch.h> |
48 | #include <linux/rculist.h> | 48 | #include <linux/rculist.h> |
49 | #include <linux/dmi.h> | 49 | #include <linux/dmi.h> |
50 | #include <linux/genetlink.h> | ||
51 | #include <net/genetlink.h> | ||
52 | #include <net/genetlink.h> | 50 | #include <net/genetlink.h> |
53 | #include <net/net_namespace.h> | 51 | #include <net/net_namespace.h> |
54 | #include <net/netns/generic.h> | 52 | #include <net/netns/generic.h> |
@@ -66,25 +64,26 @@ static struct genl_family dp_packet_genl_family; | |||
66 | static struct genl_family dp_flow_genl_family; | 64 | static struct genl_family dp_flow_genl_family; |
67 | static struct genl_family dp_datapath_genl_family; | 65 | static struct genl_family dp_datapath_genl_family; |
68 | 66 | ||
69 | static struct genl_multicast_group ovs_dp_flow_multicast_group = { | 67 | static const struct genl_multicast_group ovs_dp_flow_multicast_group = { |
70 | .name = OVS_FLOW_MCGROUP | 68 | .name = OVS_FLOW_MCGROUP, |
71 | }; | 69 | }; |
72 | 70 | ||
73 | static struct genl_multicast_group ovs_dp_datapath_multicast_group = { | 71 | static const struct genl_multicast_group ovs_dp_datapath_multicast_group = { |
74 | .name = OVS_DATAPATH_MCGROUP | 72 | .name = OVS_DATAPATH_MCGROUP, |
75 | }; | 73 | }; |
76 | 74 | ||
77 | struct genl_multicast_group ovs_dp_vport_multicast_group = { | 75 | static const struct genl_multicast_group ovs_dp_vport_multicast_group = { |
78 | .name = OVS_VPORT_MCGROUP | 76 | .name = OVS_VPORT_MCGROUP, |
79 | }; | 77 | }; |
80 | 78 | ||
81 | /* Check if need to build a reply message. | 79 | /* Check if need to build a reply message. |
82 | * OVS userspace sets the NLM_F_ECHO flag if it needs the reply. */ | 80 | * OVS userspace sets the NLM_F_ECHO flag if it needs the reply. */ |
83 | static bool ovs_must_notify(struct genl_info *info, | 81 | static bool ovs_must_notify(struct genl_family *family, struct genl_info *info, |
84 | const struct genl_multicast_group *grp) | 82 | unsigned int group) |
85 | { | 83 | { |
86 | return info->nlhdr->nlmsg_flags & NLM_F_ECHO || | 84 | return info->nlhdr->nlmsg_flags & NLM_F_ECHO || |
87 | netlink_has_listeners(genl_info_net(info)->genl_sock, 0); | 85 | genl_has_listeners(family, genl_info_net(info)->genl_sock, |
86 | group); | ||
88 | } | 87 | } |
89 | 88 | ||
90 | static void ovs_notify(struct genl_family *family, | 89 | static void ovs_notify(struct genl_family *family, |
@@ -266,9 +265,12 @@ void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb) | |||
266 | upcall.cmd = OVS_PACKET_CMD_MISS; | 265 | upcall.cmd = OVS_PACKET_CMD_MISS; |
267 | upcall.key = &key; | 266 | upcall.key = &key; |
268 | upcall.userdata = NULL; | 267 | upcall.userdata = NULL; |
269 | upcall.portid = p->upcall_portid; | 268 | upcall.portid = ovs_vport_find_upcall_portid(p, skb); |
270 | ovs_dp_upcall(dp, skb, &upcall); | 269 | error = ovs_dp_upcall(dp, skb, &upcall); |
271 | consume_skb(skb); | 270 | if (unlikely(error)) |
271 | kfree_skb(skb); | ||
272 | else | ||
273 | consume_skb(skb); | ||
272 | stats_counter = &stats->n_missed; | 274 | stats_counter = &stats->n_missed; |
273 | goto out; | 275 | goto out; |
274 | } | 276 | } |
@@ -406,7 +408,7 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, | |||
406 | { | 408 | { |
407 | struct ovs_header *upcall; | 409 | struct ovs_header *upcall; |
408 | struct sk_buff *nskb = NULL; | 410 | struct sk_buff *nskb = NULL; |
409 | struct sk_buff *user_skb; /* to be queued to userspace */ | 411 | struct sk_buff *user_skb = NULL; /* to be queued to userspace */ |
410 | struct nlattr *nla; | 412 | struct nlattr *nla; |
411 | struct genl_info info = { | 413 | struct genl_info info = { |
412 | .dst_sk = ovs_dp_get_net(dp)->genl_sock, | 414 | .dst_sk = ovs_dp_get_net(dp)->genl_sock, |
@@ -464,7 +466,8 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, | |||
464 | upcall->dp_ifindex = dp_ifindex; | 466 | upcall->dp_ifindex = dp_ifindex; |
465 | 467 | ||
466 | nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_KEY); | 468 | nla = nla_nest_start(user_skb, OVS_PACKET_ATTR_KEY); |
467 | ovs_nla_put_flow(upcall_info->key, upcall_info->key, user_skb); | 469 | err = ovs_nla_put_flow(upcall_info->key, upcall_info->key, user_skb); |
470 | BUG_ON(err); | ||
468 | nla_nest_end(user_skb, nla); | 471 | nla_nest_end(user_skb, nla); |
469 | 472 | ||
470 | if (upcall_info->userdata) | 473 | if (upcall_info->userdata) |
@@ -495,9 +498,11 @@ static int queue_userspace_packet(struct datapath *dp, struct sk_buff *skb, | |||
495 | ((struct nlmsghdr *) user_skb->data)->nlmsg_len = user_skb->len; | 498 | ((struct nlmsghdr *) user_skb->data)->nlmsg_len = user_skb->len; |
496 | 499 | ||
497 | err = genlmsg_unicast(ovs_dp_get_net(dp), user_skb, upcall_info->portid); | 500 | err = genlmsg_unicast(ovs_dp_get_net(dp), user_skb, upcall_info->portid); |
501 | user_skb = NULL; | ||
498 | out: | 502 | out: |
499 | if (err) | 503 | if (err) |
500 | skb_tx_error(skb); | 504 | skb_tx_error(skb); |
505 | kfree_skb(user_skb); | ||
501 | kfree_skb(nskb); | 506 | kfree_skb(nskb); |
502 | return err; | 507 | return err; |
503 | } | 508 | } |
@@ -759,7 +764,7 @@ static struct sk_buff *ovs_flow_cmd_alloc_info(const struct sw_flow_actions *act | |||
759 | { | 764 | { |
760 | struct sk_buff *skb; | 765 | struct sk_buff *skb; |
761 | 766 | ||
762 | if (!always && !ovs_must_notify(info, &ovs_dp_flow_multicast_group)) | 767 | if (!always && !ovs_must_notify(&dp_flow_genl_family, info, 0)) |
763 | return NULL; | 768 | return NULL; |
764 | 769 | ||
765 | skb = genlmsg_new_unicast(ovs_flow_cmd_msg_size(acts), info, GFP_KERNEL); | 770 | skb = genlmsg_new_unicast(ovs_flow_cmd_msg_size(acts), info, GFP_KERNEL); |
@@ -780,7 +785,7 @@ static struct sk_buff *ovs_flow_cmd_build_info(const struct sw_flow *flow, | |||
780 | 785 | ||
781 | skb = ovs_flow_cmd_alloc_info(ovsl_dereference(flow->sf_acts), info, | 786 | skb = ovs_flow_cmd_alloc_info(ovsl_dereference(flow->sf_acts), info, |
782 | always); | 787 | always); |
783 | if (!skb || IS_ERR(skb)) | 788 | if (IS_ERR_OR_NULL(skb)) |
784 | return skb; | 789 | return skb; |
785 | 790 | ||
786 | retval = ovs_flow_cmd_fill_info(flow, dp_ifindex, skb, | 791 | retval = ovs_flow_cmd_fill_info(flow, dp_ifindex, skb, |
@@ -1189,7 +1194,7 @@ static const struct nla_policy flow_policy[OVS_FLOW_ATTR_MAX + 1] = { | |||
1189 | [OVS_FLOW_ATTR_CLEAR] = { .type = NLA_FLAG }, | 1194 | [OVS_FLOW_ATTR_CLEAR] = { .type = NLA_FLAG }, |
1190 | }; | 1195 | }; |
1191 | 1196 | ||
1192 | static struct genl_ops dp_flow_genl_ops[] = { | 1197 | static const struct genl_ops dp_flow_genl_ops[] = { |
1193 | { .cmd = OVS_FLOW_CMD_NEW, | 1198 | { .cmd = OVS_FLOW_CMD_NEW, |
1194 | .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ | 1199 | .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ |
1195 | .policy = flow_policy, | 1200 | .policy = flow_policy, |
@@ -1373,7 +1378,7 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info) | |||
1373 | parms.options = NULL; | 1378 | parms.options = NULL; |
1374 | parms.dp = dp; | 1379 | parms.dp = dp; |
1375 | parms.port_no = OVSP_LOCAL; | 1380 | parms.port_no = OVSP_LOCAL; |
1376 | parms.upcall_portid = nla_get_u32(a[OVS_DP_ATTR_UPCALL_PID]); | 1381 | parms.upcall_portids = a[OVS_DP_ATTR_UPCALL_PID]; |
1377 | 1382 | ||
1378 | ovs_dp_change(dp, a); | 1383 | ovs_dp_change(dp, a); |
1379 | 1384 | ||
@@ -1577,7 +1582,7 @@ static const struct nla_policy datapath_policy[OVS_DP_ATTR_MAX + 1] = { | |||
1577 | [OVS_DP_ATTR_USER_FEATURES] = { .type = NLA_U32 }, | 1582 | [OVS_DP_ATTR_USER_FEATURES] = { .type = NLA_U32 }, |
1578 | }; | 1583 | }; |
1579 | 1584 | ||
1580 | static struct genl_ops dp_datapath_genl_ops[] = { | 1585 | static const struct genl_ops dp_datapath_genl_ops[] = { |
1581 | { .cmd = OVS_DP_CMD_NEW, | 1586 | { .cmd = OVS_DP_CMD_NEW, |
1582 | .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ | 1587 | .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ |
1583 | .policy = datapath_policy, | 1588 | .policy = datapath_policy, |
@@ -1632,8 +1637,8 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb, | |||
1632 | 1637 | ||
1633 | if (nla_put_u32(skb, OVS_VPORT_ATTR_PORT_NO, vport->port_no) || | 1638 | if (nla_put_u32(skb, OVS_VPORT_ATTR_PORT_NO, vport->port_no) || |
1634 | nla_put_u32(skb, OVS_VPORT_ATTR_TYPE, vport->ops->type) || | 1639 | nla_put_u32(skb, OVS_VPORT_ATTR_TYPE, vport->ops->type) || |
1635 | nla_put_string(skb, OVS_VPORT_ATTR_NAME, vport->ops->get_name(vport)) || | 1640 | nla_put_string(skb, OVS_VPORT_ATTR_NAME, |
1636 | nla_put_u32(skb, OVS_VPORT_ATTR_UPCALL_PID, vport->upcall_portid)) | 1641 | vport->ops->get_name(vport))) |
1637 | goto nla_put_failure; | 1642 | goto nla_put_failure; |
1638 | 1643 | ||
1639 | ovs_vport_get_stats(vport, &vport_stats); | 1644 | ovs_vport_get_stats(vport, &vport_stats); |
@@ -1641,6 +1646,9 @@ static int ovs_vport_cmd_fill_info(struct vport *vport, struct sk_buff *skb, | |||
1641 | &vport_stats)) | 1646 | &vport_stats)) |
1642 | goto nla_put_failure; | 1647 | goto nla_put_failure; |
1643 | 1648 | ||
1649 | if (ovs_vport_get_upcall_portids(vport, skb)) | ||
1650 | goto nla_put_failure; | ||
1651 | |||
1644 | err = ovs_vport_get_options(vport, skb); | 1652 | err = ovs_vport_get_options(vport, skb); |
1645 | if (err == -EMSGSIZE) | 1653 | if (err == -EMSGSIZE) |
1646 | goto error; | 1654 | goto error; |
@@ -1762,7 +1770,7 @@ static int ovs_vport_cmd_new(struct sk_buff *skb, struct genl_info *info) | |||
1762 | parms.options = a[OVS_VPORT_ATTR_OPTIONS]; | 1770 | parms.options = a[OVS_VPORT_ATTR_OPTIONS]; |
1763 | parms.dp = dp; | 1771 | parms.dp = dp; |
1764 | parms.port_no = port_no; | 1772 | parms.port_no = port_no; |
1765 | parms.upcall_portid = nla_get_u32(a[OVS_VPORT_ATTR_UPCALL_PID]); | 1773 | parms.upcall_portids = a[OVS_VPORT_ATTR_UPCALL_PID]; |
1766 | 1774 | ||
1767 | vport = new_vport(&parms); | 1775 | vport = new_vport(&parms); |
1768 | err = PTR_ERR(vport); | 1776 | err = PTR_ERR(vport); |
@@ -1812,8 +1820,14 @@ static int ovs_vport_cmd_set(struct sk_buff *skb, struct genl_info *info) | |||
1812 | goto exit_unlock_free; | 1820 | goto exit_unlock_free; |
1813 | } | 1821 | } |
1814 | 1822 | ||
1815 | if (a[OVS_VPORT_ATTR_UPCALL_PID]) | 1823 | |
1816 | vport->upcall_portid = nla_get_u32(a[OVS_VPORT_ATTR_UPCALL_PID]); | 1824 | if (a[OVS_VPORT_ATTR_UPCALL_PID]) { |
1825 | struct nlattr *ids = a[OVS_VPORT_ATTR_UPCALL_PID]; | ||
1826 | |||
1827 | err = ovs_vport_set_upcall_portids(vport, ids); | ||
1828 | if (err) | ||
1829 | goto exit_unlock_free; | ||
1830 | } | ||
1817 | 1831 | ||
1818 | err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid, | 1832 | err = ovs_vport_cmd_fill_info(vport, reply, info->snd_portid, |
1819 | info->snd_seq, 0, OVS_VPORT_CMD_NEW); | 1833 | info->snd_seq, 0, OVS_VPORT_CMD_NEW); |
@@ -1944,7 +1958,7 @@ static const struct nla_policy vport_policy[OVS_VPORT_ATTR_MAX + 1] = { | |||
1944 | [OVS_VPORT_ATTR_OPTIONS] = { .type = NLA_NESTED }, | 1958 | [OVS_VPORT_ATTR_OPTIONS] = { .type = NLA_NESTED }, |
1945 | }; | 1959 | }; |
1946 | 1960 | ||
1947 | static struct genl_ops dp_vport_genl_ops[] = { | 1961 | static const struct genl_ops dp_vport_genl_ops[] = { |
1948 | { .cmd = OVS_VPORT_CMD_NEW, | 1962 | { .cmd = OVS_VPORT_CMD_NEW, |
1949 | .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ | 1963 | .flags = GENL_ADMIN_PERM, /* Requires CAP_NET_ADMIN privilege. */ |
1950 | .policy = vport_policy, | 1964 | .policy = vport_policy, |
@@ -2053,10 +2067,14 @@ static int __init dp_init(void) | |||
2053 | 2067 | ||
2054 | pr_info("Open vSwitch switching datapath\n"); | 2068 | pr_info("Open vSwitch switching datapath\n"); |
2055 | 2069 | ||
2056 | err = ovs_flow_init(); | 2070 | err = ovs_internal_dev_rtnl_link_register(); |
2057 | if (err) | 2071 | if (err) |
2058 | goto error; | 2072 | goto error; |
2059 | 2073 | ||
2074 | err = ovs_flow_init(); | ||
2075 | if (err) | ||
2076 | goto error_unreg_rtnl_link; | ||
2077 | |||
2060 | err = ovs_vport_init(); | 2078 | err = ovs_vport_init(); |
2061 | if (err) | 2079 | if (err) |
2062 | goto error_flow_exit; | 2080 | goto error_flow_exit; |
@@ -2083,6 +2101,8 @@ error_vport_exit: | |||
2083 | ovs_vport_exit(); | 2101 | ovs_vport_exit(); |
2084 | error_flow_exit: | 2102 | error_flow_exit: |
2085 | ovs_flow_exit(); | 2103 | ovs_flow_exit(); |
2104 | error_unreg_rtnl_link: | ||
2105 | ovs_internal_dev_rtnl_link_unregister(); | ||
2086 | error: | 2106 | error: |
2087 | return err; | 2107 | return err; |
2088 | } | 2108 | } |
@@ -2095,6 +2115,7 @@ static void dp_cleanup(void) | |||
2095 | rcu_barrier(); | 2115 | rcu_barrier(); |
2096 | ovs_vport_exit(); | 2116 | ovs_vport_exit(); |
2097 | ovs_flow_exit(); | 2117 | ovs_flow_exit(); |
2118 | ovs_internal_dev_rtnl_link_unregister(); | ||
2098 | } | 2119 | } |
2099 | 2120 | ||
2100 | module_init(dp_init); | 2121 | module_init(dp_init); |
diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h index 7ede507500d7..701b5738c38a 100644 --- a/net/openvswitch/datapath.h +++ b/net/openvswitch/datapath.h | |||
@@ -144,7 +144,7 @@ int lockdep_ovsl_is_held(void); | |||
144 | #define lockdep_ovsl_is_held() 1 | 144 | #define lockdep_ovsl_is_held() 1 |
145 | #endif | 145 | #endif |
146 | 146 | ||
147 | #define ASSERT_OVSL() WARN_ON(unlikely(!lockdep_ovsl_is_held())) | 147 | #define ASSERT_OVSL() WARN_ON(!lockdep_ovsl_is_held()) |
148 | #define ovsl_dereference(p) \ | 148 | #define ovsl_dereference(p) \ |
149 | rcu_dereference_protected(p, lockdep_ovsl_is_held()) | 149 | rcu_dereference_protected(p, lockdep_ovsl_is_held()) |
150 | #define rcu_dereference_ovsl(p) \ | 150 | #define rcu_dereference_ovsl(p) \ |
diff --git a/net/openvswitch/vport-internal_dev.c b/net/openvswitch/vport-internal_dev.c index 789af9280e77..84516126e5f3 100644 --- a/net/openvswitch/vport-internal_dev.c +++ b/net/openvswitch/vport-internal_dev.c | |||
@@ -26,6 +26,7 @@ | |||
26 | 26 | ||
27 | #include <net/dst.h> | 27 | #include <net/dst.h> |
28 | #include <net/xfrm.h> | 28 | #include <net/xfrm.h> |
29 | #include <net/rtnetlink.h> | ||
29 | 30 | ||
30 | #include "datapath.h" | 31 | #include "datapath.h" |
31 | #include "vport-internal_dev.h" | 32 | #include "vport-internal_dev.h" |
@@ -121,6 +122,10 @@ static const struct net_device_ops internal_dev_netdev_ops = { | |||
121 | .ndo_get_stats64 = internal_dev_get_stats, | 122 | .ndo_get_stats64 = internal_dev_get_stats, |
122 | }; | 123 | }; |
123 | 124 | ||
125 | static struct rtnl_link_ops internal_dev_link_ops __read_mostly = { | ||
126 | .kind = "openvswitch", | ||
127 | }; | ||
128 | |||
124 | static void do_setup(struct net_device *netdev) | 129 | static void do_setup(struct net_device *netdev) |
125 | { | 130 | { |
126 | ether_setup(netdev); | 131 | ether_setup(netdev); |
@@ -131,14 +136,18 @@ static void do_setup(struct net_device *netdev) | |||
131 | netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE; | 136 | netdev->priv_flags |= IFF_LIVE_ADDR_CHANGE; |
132 | netdev->destructor = internal_dev_destructor; | 137 | netdev->destructor = internal_dev_destructor; |
133 | netdev->ethtool_ops = &internal_dev_ethtool_ops; | 138 | netdev->ethtool_ops = &internal_dev_ethtool_ops; |
139 | netdev->rtnl_link_ops = &internal_dev_link_ops; | ||
134 | netdev->tx_queue_len = 0; | 140 | netdev->tx_queue_len = 0; |
135 | 141 | ||
136 | netdev->features = NETIF_F_LLTX | NETIF_F_SG | NETIF_F_FRAGLIST | | 142 | netdev->features = NETIF_F_LLTX | NETIF_F_SG | NETIF_F_FRAGLIST | |
137 | NETIF_F_HIGHDMA | NETIF_F_HW_CSUM | NETIF_F_GSO_SOFTWARE; | 143 | NETIF_F_HIGHDMA | NETIF_F_HW_CSUM | |
144 | NETIF_F_GSO_SOFTWARE | NETIF_F_GSO_ENCAP_ALL; | ||
138 | 145 | ||
139 | netdev->vlan_features = netdev->features; | 146 | netdev->vlan_features = netdev->features; |
147 | netdev->hw_enc_features = netdev->features; | ||
140 | netdev->features |= NETIF_F_HW_VLAN_CTAG_TX; | 148 | netdev->features |= NETIF_F_HW_VLAN_CTAG_TX; |
141 | netdev->hw_features = netdev->features & ~NETIF_F_LLTX; | 149 | netdev->hw_features = netdev->features & ~NETIF_F_LLTX; |
150 | |||
142 | eth_hw_addr_random(netdev); | 151 | eth_hw_addr_random(netdev); |
143 | } | 152 | } |
144 | 153 | ||
@@ -159,7 +168,8 @@ static struct vport *internal_dev_create(const struct vport_parms *parms) | |||
159 | netdev_vport = netdev_vport_priv(vport); | 168 | netdev_vport = netdev_vport_priv(vport); |
160 | 169 | ||
161 | netdev_vport->dev = alloc_netdev(sizeof(struct internal_dev), | 170 | netdev_vport->dev = alloc_netdev(sizeof(struct internal_dev), |
162 | parms->name, do_setup); | 171 | parms->name, NET_NAME_UNKNOWN, |
172 | do_setup); | ||
163 | if (!netdev_vport->dev) { | 173 | if (!netdev_vport->dev) { |
164 | err = -ENOMEM; | 174 | err = -ENOMEM; |
165 | goto error_free_vport; | 175 | goto error_free_vport; |
@@ -248,3 +258,13 @@ struct vport *ovs_internal_dev_get_vport(struct net_device *netdev) | |||
248 | 258 | ||
249 | return internal_dev_priv(netdev)->vport; | 259 | return internal_dev_priv(netdev)->vport; |
250 | } | 260 | } |
261 | |||
262 | int ovs_internal_dev_rtnl_link_register(void) | ||
263 | { | ||
264 | return rtnl_link_register(&internal_dev_link_ops); | ||
265 | } | ||
266 | |||
267 | void ovs_internal_dev_rtnl_link_unregister(void) | ||
268 | { | ||
269 | rtnl_link_unregister(&internal_dev_link_ops); | ||
270 | } | ||
diff --git a/net/openvswitch/vport-internal_dev.h b/net/openvswitch/vport-internal_dev.h index 9a7d30ecc6a2..1b179a190cff 100644 --- a/net/openvswitch/vport-internal_dev.h +++ b/net/openvswitch/vport-internal_dev.h | |||
@@ -24,5 +24,7 @@ | |||
24 | 24 | ||
25 | int ovs_is_internal_dev(const struct net_device *); | 25 | int ovs_is_internal_dev(const struct net_device *); |
26 | struct vport *ovs_internal_dev_get_vport(struct net_device *); | 26 | struct vport *ovs_internal_dev_get_vport(struct net_device *); |
27 | int ovs_internal_dev_rtnl_link_register(void); | ||
28 | void ovs_internal_dev_rtnl_link_unregister(void); | ||
27 | 29 | ||
28 | #endif /* vport-internal_dev.h */ | 30 | #endif /* vport-internal_dev.h */ |
diff --git a/net/openvswitch/vport-vxlan.c b/net/openvswitch/vport-vxlan.c index 0edbd95c60e7..d8b7e247bebf 100644 --- a/net/openvswitch/vport-vxlan.c +++ b/net/openvswitch/vport-vxlan.c | |||
@@ -143,8 +143,6 @@ static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb) | |||
143 | struct rtable *rt; | 143 | struct rtable *rt; |
144 | struct flowi4 fl; | 144 | struct flowi4 fl; |
145 | __be16 src_port; | 145 | __be16 src_port; |
146 | int port_min; | ||
147 | int port_max; | ||
148 | __be16 df; | 146 | __be16 df; |
149 | int err; | 147 | int err; |
150 | 148 | ||
@@ -172,8 +170,7 @@ static int vxlan_tnl_send(struct vport *vport, struct sk_buff *skb) | |||
172 | 170 | ||
173 | skb->ignore_df = 1; | 171 | skb->ignore_df = 1; |
174 | 172 | ||
175 | inet_get_local_port_range(net, &port_min, &port_max); | 173 | src_port = udp_flow_src_port(net, skb, 0, 0, true); |
176 | src_port = vxlan_src_port(port_min, port_max, skb); | ||
177 | 174 | ||
178 | err = vxlan_xmit_skb(vxlan_port->vs, rt, skb, | 175 | err = vxlan_xmit_skb(vxlan_port->vs, rt, skb, |
179 | fl.saddr, OVS_CB(skb)->tun_key->ipv4_dst, | 176 | fl.saddr, OVS_CB(skb)->tun_key->ipv4_dst, |
diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c index 42c0f4a0b78c..6d8f2ec481d9 100644 --- a/net/openvswitch/vport.c +++ b/net/openvswitch/vport.c | |||
@@ -134,10 +134,14 @@ struct vport *ovs_vport_alloc(int priv_size, const struct vport_ops *ops, | |||
134 | 134 | ||
135 | vport->dp = parms->dp; | 135 | vport->dp = parms->dp; |
136 | vport->port_no = parms->port_no; | 136 | vport->port_no = parms->port_no; |
137 | vport->upcall_portid = parms->upcall_portid; | ||
138 | vport->ops = ops; | 137 | vport->ops = ops; |
139 | INIT_HLIST_NODE(&vport->dp_hash_node); | 138 | INIT_HLIST_NODE(&vport->dp_hash_node); |
140 | 139 | ||
140 | if (ovs_vport_set_upcall_portids(vport, parms->upcall_portids)) { | ||
141 | kfree(vport); | ||
142 | return ERR_PTR(-EINVAL); | ||
143 | } | ||
144 | |||
141 | vport->percpu_stats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); | 145 | vport->percpu_stats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); |
142 | if (!vport->percpu_stats) { | 146 | if (!vport->percpu_stats) { |
143 | kfree(vport); | 147 | kfree(vport); |
@@ -161,6 +165,10 @@ struct vport *ovs_vport_alloc(int priv_size, const struct vport_ops *ops, | |||
161 | */ | 165 | */ |
162 | void ovs_vport_free(struct vport *vport) | 166 | void ovs_vport_free(struct vport *vport) |
163 | { | 167 | { |
168 | /* vport is freed from RCU callback or error path, Therefore | ||
169 | * it is safe to use raw dereference. | ||
170 | */ | ||
171 | kfree(rcu_dereference_raw(vport->upcall_portids)); | ||
164 | free_percpu(vport->percpu_stats); | 172 | free_percpu(vport->percpu_stats); |
165 | kfree(vport); | 173 | kfree(vport); |
166 | } | 174 | } |
@@ -327,6 +335,99 @@ int ovs_vport_get_options(const struct vport *vport, struct sk_buff *skb) | |||
327 | } | 335 | } |
328 | 336 | ||
329 | /** | 337 | /** |
338 | * ovs_vport_set_upcall_portids - set upcall portids of @vport. | ||
339 | * | ||
340 | * @vport: vport to modify. | ||
341 | * @ids: new configuration, an array of port ids. | ||
342 | * | ||
343 | * Sets the vport's upcall_portids to @ids. | ||
344 | * | ||
345 | * Returns 0 if successful, -EINVAL if @ids is zero length or cannot be parsed | ||
346 | * as an array of U32. | ||
347 | * | ||
348 | * Must be called with ovs_mutex. | ||
349 | */ | ||
350 | int ovs_vport_set_upcall_portids(struct vport *vport, struct nlattr *ids) | ||
351 | { | ||
352 | struct vport_portids *old, *vport_portids; | ||
353 | |||
354 | if (!nla_len(ids) || nla_len(ids) % sizeof(u32)) | ||
355 | return -EINVAL; | ||
356 | |||
357 | old = ovsl_dereference(vport->upcall_portids); | ||
358 | |||
359 | vport_portids = kmalloc(sizeof(*vport_portids) + nla_len(ids), | ||
360 | GFP_KERNEL); | ||
361 | if (!vport_portids) | ||
362 | return -ENOMEM; | ||
363 | |||
364 | vport_portids->n_ids = nla_len(ids) / sizeof(u32); | ||
365 | vport_portids->rn_ids = reciprocal_value(vport_portids->n_ids); | ||
366 | nla_memcpy(vport_portids->ids, ids, nla_len(ids)); | ||
367 | |||
368 | rcu_assign_pointer(vport->upcall_portids, vport_portids); | ||
369 | |||
370 | if (old) | ||
371 | kfree_rcu(old, rcu); | ||
372 | return 0; | ||
373 | } | ||
374 | |||
375 | /** | ||
376 | * ovs_vport_get_upcall_portids - get the upcall_portids of @vport. | ||
377 | * | ||
378 | * @vport: vport from which to retrieve the portids. | ||
379 | * @skb: sk_buff where portids should be appended. | ||
380 | * | ||
381 | * Retrieves the configuration of the given vport, appending the | ||
382 | * %OVS_VPORT_ATTR_UPCALL_PID attribute which is the array of upcall | ||
383 | * portids to @skb. | ||
384 | * | ||
385 | * Returns 0 if successful, -EMSGSIZE if @skb has insufficient room. | ||
386 | * If an error occurs, @skb is left unmodified. Must be called with | ||
387 | * ovs_mutex or rcu_read_lock. | ||
388 | */ | ||
389 | int ovs_vport_get_upcall_portids(const struct vport *vport, | ||
390 | struct sk_buff *skb) | ||
391 | { | ||
392 | struct vport_portids *ids; | ||
393 | |||
394 | ids = rcu_dereference_ovsl(vport->upcall_portids); | ||
395 | |||
396 | if (vport->dp->user_features & OVS_DP_F_VPORT_PIDS) | ||
397 | return nla_put(skb, OVS_VPORT_ATTR_UPCALL_PID, | ||
398 | ids->n_ids * sizeof(u32), (void *)ids->ids); | ||
399 | else | ||
400 | return nla_put_u32(skb, OVS_VPORT_ATTR_UPCALL_PID, ids->ids[0]); | ||
401 | } | ||
402 | |||
403 | /** | ||
404 | * ovs_vport_find_upcall_portid - find the upcall portid to send upcall. | ||
405 | * | ||
406 | * @vport: vport from which the missed packet is received. | ||
407 | * @skb: skb that the missed packet was received. | ||
408 | * | ||
409 | * Uses the skb_get_hash() to select the upcall portid to send the | ||
410 | * upcall. | ||
411 | * | ||
412 | * Returns the portid of the target socket. Must be called with rcu_read_lock. | ||
413 | */ | ||
414 | u32 ovs_vport_find_upcall_portid(const struct vport *p, struct sk_buff *skb) | ||
415 | { | ||
416 | struct vport_portids *ids; | ||
417 | u32 ids_index; | ||
418 | u32 hash; | ||
419 | |||
420 | ids = rcu_dereference(p->upcall_portids); | ||
421 | |||
422 | if (ids->n_ids == 1 && ids->ids[0] == 0) | ||
423 | return 0; | ||
424 | |||
425 | hash = skb_get_hash(skb); | ||
426 | ids_index = hash - ids->n_ids * reciprocal_divide(hash, ids->rn_ids); | ||
427 | return ids->ids[ids_index]; | ||
428 | } | ||
429 | |||
430 | /** | ||
330 | * ovs_vport_receive - pass up received packet to the datapath for processing | 431 | * ovs_vport_receive - pass up received packet to the datapath for processing |
331 | * | 432 | * |
332 | * @vport: vport that received the packet | 433 | * @vport: vport that received the packet |
diff --git a/net/openvswitch/vport.h b/net/openvswitch/vport.h index 8d721e62f388..35f89d84b45e 100644 --- a/net/openvswitch/vport.h +++ b/net/openvswitch/vport.h | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/list.h> | 23 | #include <linux/list.h> |
24 | #include <linux/netlink.h> | 24 | #include <linux/netlink.h> |
25 | #include <linux/openvswitch.h> | 25 | #include <linux/openvswitch.h> |
26 | #include <linux/reciprocal_div.h> | ||
26 | #include <linux/skbuff.h> | 27 | #include <linux/skbuff.h> |
27 | #include <linux/spinlock.h> | 28 | #include <linux/spinlock.h> |
28 | #include <linux/u64_stats_sync.h> | 29 | #include <linux/u64_stats_sync.h> |
@@ -52,6 +53,10 @@ void ovs_vport_get_stats(struct vport *, struct ovs_vport_stats *); | |||
52 | int ovs_vport_set_options(struct vport *, struct nlattr *options); | 53 | int ovs_vport_set_options(struct vport *, struct nlattr *options); |
53 | int ovs_vport_get_options(const struct vport *, struct sk_buff *); | 54 | int ovs_vport_get_options(const struct vport *, struct sk_buff *); |
54 | 55 | ||
56 | int ovs_vport_set_upcall_portids(struct vport *, struct nlattr *pids); | ||
57 | int ovs_vport_get_upcall_portids(const struct vport *, struct sk_buff *); | ||
58 | u32 ovs_vport_find_upcall_portid(const struct vport *, struct sk_buff *); | ||
59 | |||
55 | int ovs_vport_send(struct vport *, struct sk_buff *); | 60 | int ovs_vport_send(struct vport *, struct sk_buff *); |
56 | 61 | ||
57 | /* The following definitions are for implementers of vport devices: */ | 62 | /* The following definitions are for implementers of vport devices: */ |
@@ -62,13 +67,27 @@ struct vport_err_stats { | |||
62 | u64 tx_dropped; | 67 | u64 tx_dropped; |
63 | u64 tx_errors; | 68 | u64 tx_errors; |
64 | }; | 69 | }; |
70 | /** | ||
71 | * struct vport_portids - array of netlink portids of a vport. | ||
72 | * must be protected by rcu. | ||
73 | * @rn_ids: The reciprocal value of @n_ids. | ||
74 | * @rcu: RCU callback head for deferred destruction. | ||
75 | * @n_ids: Size of @ids array. | ||
76 | * @ids: Array storing the Netlink socket pids to be used for packets received | ||
77 | * on this port that miss the flow table. | ||
78 | */ | ||
79 | struct vport_portids { | ||
80 | struct reciprocal_value rn_ids; | ||
81 | struct rcu_head rcu; | ||
82 | u32 n_ids; | ||
83 | u32 ids[]; | ||
84 | }; | ||
65 | 85 | ||
66 | /** | 86 | /** |
67 | * struct vport - one port within a datapath | 87 | * struct vport - one port within a datapath |
68 | * @rcu: RCU callback head for deferred destruction. | 88 | * @rcu: RCU callback head for deferred destruction. |
69 | * @dp: Datapath to which this port belongs. | 89 | * @dp: Datapath to which this port belongs. |
70 | * @upcall_portid: The Netlink port to use for packets received on this port that | 90 | * @upcall_portids: RCU protected 'struct vport_portids'. |
71 | * miss the flow table. | ||
72 | * @port_no: Index into @dp's @ports array. | 91 | * @port_no: Index into @dp's @ports array. |
73 | * @hash_node: Element in @dev_table hash table in vport.c. | 92 | * @hash_node: Element in @dev_table hash table in vport.c. |
74 | * @dp_hash_node: Element in @datapath->ports hash table in datapath.c. | 93 | * @dp_hash_node: Element in @datapath->ports hash table in datapath.c. |
@@ -80,7 +99,7 @@ struct vport_err_stats { | |||
80 | struct vport { | 99 | struct vport { |
81 | struct rcu_head rcu; | 100 | struct rcu_head rcu; |
82 | struct datapath *dp; | 101 | struct datapath *dp; |
83 | u32 upcall_portid; | 102 | struct vport_portids __rcu *upcall_portids; |
84 | u16 port_no; | 103 | u16 port_no; |
85 | 104 | ||
86 | struct hlist_node hash_node; | 105 | struct hlist_node hash_node; |
@@ -111,7 +130,7 @@ struct vport_parms { | |||
111 | /* For ovs_vport_alloc(). */ | 130 | /* For ovs_vport_alloc(). */ |
112 | struct datapath *dp; | 131 | struct datapath *dp; |
113 | u16 port_no; | 132 | u16 port_no; |
114 | u32 upcall_portid; | 133 | struct nlattr *upcall_portids; |
115 | }; | 134 | }; |
116 | 135 | ||
117 | /** | 136 | /** |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index b85c67ccb797..93896d2092f6 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
@@ -441,14 +441,10 @@ static __u32 tpacket_get_timestamp(struct sk_buff *skb, struct timespec *ts, | |||
441 | { | 441 | { |
442 | struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb); | 442 | struct skb_shared_hwtstamps *shhwtstamps = skb_hwtstamps(skb); |
443 | 443 | ||
444 | if (shhwtstamps) { | 444 | if (shhwtstamps && |
445 | if ((flags & SOF_TIMESTAMPING_SYS_HARDWARE) && | 445 | (flags & SOF_TIMESTAMPING_RAW_HARDWARE) && |
446 | ktime_to_timespec_cond(shhwtstamps->syststamp, ts)) | 446 | ktime_to_timespec_cond(shhwtstamps->hwtstamp, ts)) |
447 | return TP_STATUS_TS_SYS_HARDWARE; | 447 | return TP_STATUS_TS_RAW_HARDWARE; |
448 | if ((flags & SOF_TIMESTAMPING_RAW_HARDWARE) && | ||
449 | ktime_to_timespec_cond(shhwtstamps->hwtstamp, ts)) | ||
450 | return TP_STATUS_TS_RAW_HARDWARE; | ||
451 | } | ||
452 | 448 | ||
453 | if (ktime_to_timespec_cond(skb->tstamp, ts)) | 449 | if (ktime_to_timespec_cond(skb->tstamp, ts)) |
454 | return TP_STATUS_TS_SOFTWARE; | 450 | return TP_STATUS_TS_SOFTWARE; |
@@ -636,6 +632,7 @@ static void init_prb_bdqc(struct packet_sock *po, | |||
636 | p1->tov_in_jiffies = msecs_to_jiffies(p1->retire_blk_tov); | 632 | p1->tov_in_jiffies = msecs_to_jiffies(p1->retire_blk_tov); |
637 | p1->blk_sizeof_priv = req_u->req3.tp_sizeof_priv; | 633 | p1->blk_sizeof_priv = req_u->req3.tp_sizeof_priv; |
638 | 634 | ||
635 | p1->max_frame_len = p1->kblk_size - BLK_PLUS_PRIV(p1->blk_sizeof_priv); | ||
639 | prb_init_ft_ops(p1, req_u); | 636 | prb_init_ft_ops(p1, req_u); |
640 | prb_setup_retire_blk_timer(po, tx_ring); | 637 | prb_setup_retire_blk_timer(po, tx_ring); |
641 | prb_open_block(p1, pbd); | 638 | prb_open_block(p1, pbd); |
@@ -1946,6 +1943,18 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, | |||
1946 | if ((int)snaplen < 0) | 1943 | if ((int)snaplen < 0) |
1947 | snaplen = 0; | 1944 | snaplen = 0; |
1948 | } | 1945 | } |
1946 | } else if (unlikely(macoff + snaplen > | ||
1947 | GET_PBDQC_FROM_RB(&po->rx_ring)->max_frame_len)) { | ||
1948 | u32 nval; | ||
1949 | |||
1950 | nval = GET_PBDQC_FROM_RB(&po->rx_ring)->max_frame_len - macoff; | ||
1951 | pr_err_once("tpacket_rcv: packet too big, clamped from %u to %u. macoff=%u\n", | ||
1952 | snaplen, nval, macoff); | ||
1953 | snaplen = nval; | ||
1954 | if (unlikely((int)snaplen < 0)) { | ||
1955 | snaplen = 0; | ||
1956 | macoff = GET_PBDQC_FROM_RB(&po->rx_ring)->max_frame_len; | ||
1957 | } | ||
1949 | } | 1958 | } |
1950 | spin_lock(&sk->sk_receive_queue.lock); | 1959 | spin_lock(&sk->sk_receive_queue.lock); |
1951 | h.raw = packet_current_rx_frame(po, skb, | 1960 | h.raw = packet_current_rx_frame(po, skb, |
@@ -3071,10 +3080,8 @@ static int packet_dev_mc(struct net_device *dev, struct packet_mclist *i, | |||
3071 | break; | 3080 | break; |
3072 | case PACKET_MR_PROMISC: | 3081 | case PACKET_MR_PROMISC: |
3073 | return dev_set_promiscuity(dev, what); | 3082 | return dev_set_promiscuity(dev, what); |
3074 | break; | ||
3075 | case PACKET_MR_ALLMULTI: | 3083 | case PACKET_MR_ALLMULTI: |
3076 | return dev_set_allmulti(dev, what); | 3084 | return dev_set_allmulti(dev, what); |
3077 | break; | ||
3078 | case PACKET_MR_UNICAST: | 3085 | case PACKET_MR_UNICAST: |
3079 | if (i->alen != dev->addr_len) | 3086 | if (i->alen != dev->addr_len) |
3080 | return -EINVAL; | 3087 | return -EINVAL; |
@@ -3789,6 +3796,10 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u, | |||
3789 | goto out; | 3796 | goto out; |
3790 | if (unlikely(req->tp_block_size & (PAGE_SIZE - 1))) | 3797 | if (unlikely(req->tp_block_size & (PAGE_SIZE - 1))) |
3791 | goto out; | 3798 | goto out; |
3799 | if (po->tp_version >= TPACKET_V3 && | ||
3800 | (int)(req->tp_block_size - | ||
3801 | BLK_PLUS_PRIV(req_u->req3.tp_sizeof_priv)) <= 0) | ||
3802 | goto out; | ||
3792 | if (unlikely(req->tp_frame_size < po->tp_hdrlen + | 3803 | if (unlikely(req->tp_frame_size < po->tp_hdrlen + |
3793 | po->tp_reserve)) | 3804 | po->tp_reserve)) |
3794 | goto out; | 3805 | goto out; |
diff --git a/net/packet/internal.h b/net/packet/internal.h index eb9580a6b25f..cdddf6a30399 100644 --- a/net/packet/internal.h +++ b/net/packet/internal.h | |||
@@ -29,6 +29,7 @@ struct tpacket_kbdq_core { | |||
29 | char *pkblk_start; | 29 | char *pkblk_start; |
30 | char *pkblk_end; | 30 | char *pkblk_end; |
31 | int kblk_size; | 31 | int kblk_size; |
32 | unsigned int max_frame_len; | ||
32 | unsigned int knum_blocks; | 33 | unsigned int knum_blocks; |
33 | uint64_t knxt_seq_num; | 34 | uint64_t knxt_seq_num; |
34 | char *prev; | 35 | char *prev; |
diff --git a/net/phonet/pep-gprs.c b/net/phonet/pep-gprs.c index 66dc65e7c6a1..e9a83a637185 100644 --- a/net/phonet/pep-gprs.c +++ b/net/phonet/pep-gprs.c | |||
@@ -267,7 +267,7 @@ int gprs_attach(struct sock *sk) | |||
267 | return -EINVAL; /* need packet boundaries */ | 267 | return -EINVAL; /* need packet boundaries */ |
268 | 268 | ||
269 | /* Create net device */ | 269 | /* Create net device */ |
270 | dev = alloc_netdev(sizeof(*gp), ifname, gprs_setup); | 270 | dev = alloc_netdev(sizeof(*gp), ifname, NET_NAME_UNKNOWN, gprs_setup); |
271 | if (!dev) | 271 | if (!dev) |
272 | return -ENOMEM; | 272 | return -ENOMEM; |
273 | gp = netdev_priv(dev); | 273 | gp = netdev_priv(dev); |
diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c index 14c98e48f261..0f62326c0f5e 100644 --- a/net/rfkill/rfkill-gpio.c +++ b/net/rfkill/rfkill-gpio.c | |||
@@ -54,7 +54,7 @@ static int rfkill_gpio_set_power(void *data, bool blocked) | |||
54 | if (blocked && !IS_ERR(rfkill->clk) && rfkill->clk_enabled) | 54 | if (blocked && !IS_ERR(rfkill->clk) && rfkill->clk_enabled) |
55 | clk_disable(rfkill->clk); | 55 | clk_disable(rfkill->clk); |
56 | 56 | ||
57 | rfkill->clk_enabled = blocked; | 57 | rfkill->clk_enabled = !blocked; |
58 | 58 | ||
59 | return 0; | 59 | return 0; |
60 | } | 60 | } |
@@ -158,10 +158,12 @@ static const struct acpi_device_id rfkill_acpi_match[] = { | |||
158 | { "BCM2E1A", RFKILL_TYPE_BLUETOOTH }, | 158 | { "BCM2E1A", RFKILL_TYPE_BLUETOOTH }, |
159 | { "BCM2E39", RFKILL_TYPE_BLUETOOTH }, | 159 | { "BCM2E39", RFKILL_TYPE_BLUETOOTH }, |
160 | { "BCM2E3D", RFKILL_TYPE_BLUETOOTH }, | 160 | { "BCM2E3D", RFKILL_TYPE_BLUETOOTH }, |
161 | { "BCM2E64", RFKILL_TYPE_BLUETOOTH }, | ||
161 | { "BCM4752", RFKILL_TYPE_GPS }, | 162 | { "BCM4752", RFKILL_TYPE_GPS }, |
162 | { "LNV4752", RFKILL_TYPE_GPS }, | 163 | { "LNV4752", RFKILL_TYPE_GPS }, |
163 | { }, | 164 | { }, |
164 | }; | 165 | }; |
166 | MODULE_DEVICE_TABLE(acpi, rfkill_acpi_match); | ||
165 | #endif | 167 | #endif |
166 | 168 | ||
167 | static struct platform_driver rfkill_gpio_driver = { | 169 | static struct platform_driver rfkill_gpio_driver = { |
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index 8451c8cdc9de..a85c1a086ae4 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c | |||
@@ -1538,7 +1538,7 @@ static int __init rose_proto_init(void) | |||
1538 | char name[IFNAMSIZ]; | 1538 | char name[IFNAMSIZ]; |
1539 | 1539 | ||
1540 | sprintf(name, "rose%d", i); | 1540 | sprintf(name, "rose%d", i); |
1541 | dev = alloc_netdev(0, name, rose_setup); | 1541 | dev = alloc_netdev(0, name, NET_NAME_UNKNOWN, rose_setup); |
1542 | if (!dev) { | 1542 | if (!dev) { |
1543 | printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate memory\n"); | 1543 | printk(KERN_ERR "ROSE: rose_proto_init - unable to allocate memory\n"); |
1544 | rc = -ENOMEM; | 1544 | rc = -ENOMEM; |
diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c index 10c6cb694b43..db0f39f5ef96 100644 --- a/net/rxrpc/ar-key.c +++ b/net/rxrpc/ar-key.c | |||
@@ -348,7 +348,7 @@ static int rxrpc_krb5_decode_tagged_array(struct krb5_tagged_data **_td, | |||
348 | 348 | ||
349 | n_elem = ntohl(*xdr++); | 349 | n_elem = ntohl(*xdr++); |
350 | toklen -= 4; | 350 | toklen -= 4; |
351 | if (n_elem < 0 || n_elem > max_n_elem) | 351 | if (n_elem > max_n_elem) |
352 | return -EINVAL; | 352 | return -EINVAL; |
353 | *_n_elem = n_elem; | 353 | *_n_elem = n_elem; |
354 | if (n_elem > 0) { | 354 | if (n_elem > 0) { |
@@ -1141,7 +1141,7 @@ static long rxrpc_read(const struct key *key, | |||
1141 | if (copy_to_user(xdr, (s), _l) != 0) \ | 1141 | if (copy_to_user(xdr, (s), _l) != 0) \ |
1142 | goto fault; \ | 1142 | goto fault; \ |
1143 | if (_l & 3 && \ | 1143 | if (_l & 3 && \ |
1144 | copy_to_user((u8 *)xdr + _l, &zero, 4 - (_l & 3)) != 0) \ | 1144 | copy_to_user((u8 __user *)xdr + _l, &zero, 4 - (_l & 3)) != 0) \ |
1145 | goto fault; \ | 1145 | goto fault; \ |
1146 | xdr += (_l + 3) >> 2; \ | 1146 | xdr += (_l + 3) >> 2; \ |
1147 | } while(0) | 1147 | } while(0) |
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c index 4f912c0e225b..eb48306033d9 100644 --- a/net/sched/act_mirred.c +++ b/net/sched/act_mirred.c | |||
@@ -218,10 +218,12 @@ static int mirred_device_event(struct notifier_block *unused, | |||
218 | 218 | ||
219 | if (event == NETDEV_UNREGISTER) | 219 | if (event == NETDEV_UNREGISTER) |
220 | list_for_each_entry(m, &mirred_list, tcfm_list) { | 220 | list_for_each_entry(m, &mirred_list, tcfm_list) { |
221 | spin_lock_bh(&m->tcf_lock); | ||
221 | if (m->tcfm_dev == dev) { | 222 | if (m->tcfm_dev == dev) { |
222 | dev_put(dev); | 223 | dev_put(dev); |
223 | m->tcfm_dev = NULL; | 224 | m->tcfm_dev = NULL; |
224 | } | 225 | } |
226 | spin_unlock_bh(&m->tcf_lock); | ||
225 | } | 227 | } |
226 | 228 | ||
227 | return NOTIFY_DONE; | 229 | return NOTIFY_DONE; |
diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 45527e6b52db..c28b0d327b12 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c | |||
@@ -561,13 +561,14 @@ EXPORT_SYMBOL(tcf_exts_change); | |||
561 | int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts) | 561 | int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts) |
562 | { | 562 | { |
563 | #ifdef CONFIG_NET_CLS_ACT | 563 | #ifdef CONFIG_NET_CLS_ACT |
564 | struct nlattr *nest; | ||
565 | |||
564 | if (exts->action && !list_empty(&exts->actions)) { | 566 | if (exts->action && !list_empty(&exts->actions)) { |
565 | /* | 567 | /* |
566 | * again for backward compatible mode - we want | 568 | * again for backward compatible mode - we want |
567 | * to work with both old and new modes of entering | 569 | * to work with both old and new modes of entering |
568 | * tc data even if iproute2 was newer - jhs | 570 | * tc data even if iproute2 was newer - jhs |
569 | */ | 571 | */ |
570 | struct nlattr *nest; | ||
571 | if (exts->type != TCA_OLD_COMPAT) { | 572 | if (exts->type != TCA_OLD_COMPAT) { |
572 | nest = nla_nest_start(skb, exts->action); | 573 | nest = nla_nest_start(skb, exts->action); |
573 | if (nest == NULL) | 574 | if (nest == NULL) |
@@ -585,10 +586,14 @@ int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts) | |||
585 | nla_nest_end(skb, nest); | 586 | nla_nest_end(skb, nest); |
586 | } | 587 | } |
587 | } | 588 | } |
588 | #endif | ||
589 | return 0; | 589 | return 0; |
590 | nla_put_failure: __attribute__ ((unused)) | 590 | |
591 | nla_put_failure: | ||
592 | nla_nest_cancel(skb, nest); | ||
591 | return -1; | 593 | return -1; |
594 | #else | ||
595 | return 0; | ||
596 | #endif | ||
592 | } | 597 | } |
593 | EXPORT_SYMBOL(tcf_exts_dump); | 598 | EXPORT_SYMBOL(tcf_exts_dump); |
594 | 599 | ||
diff --git a/net/sched/cls_bpf.c b/net/sched/cls_bpf.c index 13f64df2c710..0e30d58149da 100644 --- a/net/sched/cls_bpf.c +++ b/net/sched/cls_bpf.c | |||
@@ -30,7 +30,7 @@ struct cls_bpf_head { | |||
30 | }; | 30 | }; |
31 | 31 | ||
32 | struct cls_bpf_prog { | 32 | struct cls_bpf_prog { |
33 | struct sk_filter *filter; | 33 | struct bpf_prog *filter; |
34 | struct sock_filter *bpf_ops; | 34 | struct sock_filter *bpf_ops; |
35 | struct tcf_exts exts; | 35 | struct tcf_exts exts; |
36 | struct tcf_result res; | 36 | struct tcf_result res; |
@@ -54,7 +54,7 @@ static int cls_bpf_classify(struct sk_buff *skb, const struct tcf_proto *tp, | |||
54 | int ret; | 54 | int ret; |
55 | 55 | ||
56 | list_for_each_entry(prog, &head->plist, link) { | 56 | list_for_each_entry(prog, &head->plist, link) { |
57 | int filter_res = SK_RUN_FILTER(prog->filter, skb); | 57 | int filter_res = BPF_PROG_RUN(prog->filter, skb); |
58 | 58 | ||
59 | if (filter_res == 0) | 59 | if (filter_res == 0) |
60 | continue; | 60 | continue; |
@@ -92,7 +92,7 @@ static void cls_bpf_delete_prog(struct tcf_proto *tp, struct cls_bpf_prog *prog) | |||
92 | tcf_unbind_filter(tp, &prog->res); | 92 | tcf_unbind_filter(tp, &prog->res); |
93 | tcf_exts_destroy(tp, &prog->exts); | 93 | tcf_exts_destroy(tp, &prog->exts); |
94 | 94 | ||
95 | sk_unattached_filter_destroy(prog->filter); | 95 | bpf_prog_destroy(prog->filter); |
96 | 96 | ||
97 | kfree(prog->bpf_ops); | 97 | kfree(prog->bpf_ops); |
98 | kfree(prog); | 98 | kfree(prog); |
@@ -161,7 +161,7 @@ static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp, | |||
161 | struct sock_filter *bpf_ops, *bpf_old; | 161 | struct sock_filter *bpf_ops, *bpf_old; |
162 | struct tcf_exts exts; | 162 | struct tcf_exts exts; |
163 | struct sock_fprog_kern tmp; | 163 | struct sock_fprog_kern tmp; |
164 | struct sk_filter *fp, *fp_old; | 164 | struct bpf_prog *fp, *fp_old; |
165 | u16 bpf_size, bpf_len; | 165 | u16 bpf_size, bpf_len; |
166 | u32 classid; | 166 | u32 classid; |
167 | int ret; | 167 | int ret; |
@@ -193,7 +193,7 @@ static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp, | |||
193 | tmp.len = bpf_len; | 193 | tmp.len = bpf_len; |
194 | tmp.filter = bpf_ops; | 194 | tmp.filter = bpf_ops; |
195 | 195 | ||
196 | ret = sk_unattached_filter_create(&fp, &tmp); | 196 | ret = bpf_prog_create(&fp, &tmp); |
197 | if (ret) | 197 | if (ret) |
198 | goto errout_free; | 198 | goto errout_free; |
199 | 199 | ||
@@ -211,7 +211,7 @@ static int cls_bpf_modify_existing(struct net *net, struct tcf_proto *tp, | |||
211 | tcf_exts_change(tp, &prog->exts, &exts); | 211 | tcf_exts_change(tp, &prog->exts, &exts); |
212 | 212 | ||
213 | if (fp_old) | 213 | if (fp_old) |
214 | sk_unattached_filter_destroy(fp_old); | 214 | bpf_prog_destroy(fp_old); |
215 | if (bpf_old) | 215 | if (bpf_old) |
216 | kfree(bpf_old); | 216 | kfree(bpf_old); |
217 | 217 | ||
diff --git a/net/sched/cls_tcindex.c b/net/sched/cls_tcindex.c index c721cd4a469f..3e9f76413b3b 100644 --- a/net/sched/cls_tcindex.c +++ b/net/sched/cls_tcindex.c | |||
@@ -420,7 +420,7 @@ static void tcindex_destroy(struct tcf_proto *tp) | |||
420 | pr_debug("tcindex_destroy(tp %p),p %p\n", tp, p); | 420 | pr_debug("tcindex_destroy(tp %p),p %p\n", tp, p); |
421 | walker.count = 0; | 421 | walker.count = 0; |
422 | walker.skip = 0; | 422 | walker.skip = 0; |
423 | walker.fn = &tcindex_destroy_element; | 423 | walker.fn = tcindex_destroy_element; |
424 | tcindex_walk(tp, &walker); | 424 | tcindex_walk(tp, &walker); |
425 | kfree(p->perfect); | 425 | kfree(p->perfect); |
426 | kfree(p->h); | 426 | kfree(p->h); |
diff --git a/net/sched/em_canid.c b/net/sched/em_canid.c index bfd34e4c1afc..7c292d474f47 100644 --- a/net/sched/em_canid.c +++ b/net/sched/em_canid.c | |||
@@ -125,7 +125,6 @@ static int em_canid_change(struct tcf_proto *tp, void *data, int len, | |||
125 | { | 125 | { |
126 | struct can_filter *conf = data; /* Array with rules */ | 126 | struct can_filter *conf = data; /* Array with rules */ |
127 | struct canid_match *cm; | 127 | struct canid_match *cm; |
128 | struct canid_match *cm_old = (struct canid_match *)m->data; | ||
129 | int i; | 128 | int i; |
130 | 129 | ||
131 | if (!len) | 130 | if (!len) |
@@ -181,12 +180,6 @@ static int em_canid_change(struct tcf_proto *tp, void *data, int len, | |||
181 | 180 | ||
182 | m->datalen = sizeof(struct canid_match) + len; | 181 | m->datalen = sizeof(struct canid_match) + len; |
183 | m->data = (unsigned long)cm; | 182 | m->data = (unsigned long)cm; |
184 | |||
185 | if (cm_old != NULL) { | ||
186 | pr_err("canid: Configuring an existing ematch!\n"); | ||
187 | kfree(cm_old); | ||
188 | } | ||
189 | |||
190 | return 0; | 183 | return 0; |
191 | } | 184 | } |
192 | 185 | ||
diff --git a/net/sched/ematch.c b/net/sched/ematch.c index 3a633debb6df..ad57f4444b9c 100644 --- a/net/sched/ematch.c +++ b/net/sched/ematch.c | |||
@@ -526,9 +526,11 @@ pop_stack: | |||
526 | match_idx = stack[--stackp]; | 526 | match_idx = stack[--stackp]; |
527 | cur_match = tcf_em_get_match(tree, match_idx); | 527 | cur_match = tcf_em_get_match(tree, match_idx); |
528 | 528 | ||
529 | if (tcf_em_early_end(cur_match, res)) | 529 | if (tcf_em_early_end(cur_match, res)) { |
530 | if (tcf_em_is_inverted(cur_match)) | ||
531 | res = !res; | ||
530 | goto pop_stack; | 532 | goto pop_stack; |
531 | else { | 533 | } else { |
532 | match_idx++; | 534 | match_idx++; |
533 | goto proceed; | 535 | goto proceed; |
534 | } | 536 | } |
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index ead526467cca..762a04bb8f6d 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c | |||
@@ -159,7 +159,6 @@ struct cbq_sched_data { | |||
159 | struct cbq_class *tx_borrowed; | 159 | struct cbq_class *tx_borrowed; |
160 | int tx_len; | 160 | int tx_len; |
161 | psched_time_t now; /* Cached timestamp */ | 161 | psched_time_t now; /* Cached timestamp */ |
162 | psched_time_t now_rt; /* Cached real time */ | ||
163 | unsigned int pmask; | 162 | unsigned int pmask; |
164 | 163 | ||
165 | struct hrtimer delay_timer; | 164 | struct hrtimer delay_timer; |
@@ -353,12 +352,7 @@ cbq_mark_toplevel(struct cbq_sched_data *q, struct cbq_class *cl) | |||
353 | int toplevel = q->toplevel; | 352 | int toplevel = q->toplevel; |
354 | 353 | ||
355 | if (toplevel > cl->level && !(qdisc_is_throttled(cl->q))) { | 354 | if (toplevel > cl->level && !(qdisc_is_throttled(cl->q))) { |
356 | psched_time_t now; | 355 | psched_time_t now = psched_get_time(); |
357 | psched_tdiff_t incr; | ||
358 | |||
359 | now = psched_get_time(); | ||
360 | incr = now - q->now_rt; | ||
361 | now = q->now + incr; | ||
362 | 356 | ||
363 | do { | 357 | do { |
364 | if (cl->undertime < now) { | 358 | if (cl->undertime < now) { |
@@ -700,8 +694,13 @@ cbq_update(struct cbq_sched_data *q) | |||
700 | struct cbq_class *this = q->tx_class; | 694 | struct cbq_class *this = q->tx_class; |
701 | struct cbq_class *cl = this; | 695 | struct cbq_class *cl = this; |
702 | int len = q->tx_len; | 696 | int len = q->tx_len; |
697 | psched_time_t now; | ||
703 | 698 | ||
704 | q->tx_class = NULL; | 699 | q->tx_class = NULL; |
700 | /* Time integrator. We calculate EOS time | ||
701 | * by adding expected packet transmission time. | ||
702 | */ | ||
703 | now = q->now + L2T(&q->link, len); | ||
705 | 704 | ||
706 | for ( ; cl; cl = cl->share) { | 705 | for ( ; cl; cl = cl->share) { |
707 | long avgidle = cl->avgidle; | 706 | long avgidle = cl->avgidle; |
@@ -717,7 +716,7 @@ cbq_update(struct cbq_sched_data *q) | |||
717 | * idle = (now - last) - last_pktlen/rate | 716 | * idle = (now - last) - last_pktlen/rate |
718 | */ | 717 | */ |
719 | 718 | ||
720 | idle = q->now - cl->last; | 719 | idle = now - cl->last; |
721 | if ((unsigned long)idle > 128*1024*1024) { | 720 | if ((unsigned long)idle > 128*1024*1024) { |
722 | avgidle = cl->maxidle; | 721 | avgidle = cl->maxidle; |
723 | } else { | 722 | } else { |
@@ -761,7 +760,7 @@ cbq_update(struct cbq_sched_data *q) | |||
761 | idle -= L2T(&q->link, len); | 760 | idle -= L2T(&q->link, len); |
762 | idle += L2T(cl, len); | 761 | idle += L2T(cl, len); |
763 | 762 | ||
764 | cl->undertime = q->now + idle; | 763 | cl->undertime = now + idle; |
765 | } else { | 764 | } else { |
766 | /* Underlimit */ | 765 | /* Underlimit */ |
767 | 766 | ||
@@ -771,7 +770,8 @@ cbq_update(struct cbq_sched_data *q) | |||
771 | else | 770 | else |
772 | cl->avgidle = avgidle; | 771 | cl->avgidle = avgidle; |
773 | } | 772 | } |
774 | cl->last = q->now; | 773 | if ((s64)(now - cl->last) > 0) |
774 | cl->last = now; | ||
775 | } | 775 | } |
776 | 776 | ||
777 | cbq_update_toplevel(q, this, q->tx_borrowed); | 777 | cbq_update_toplevel(q, this, q->tx_borrowed); |
@@ -943,31 +943,13 @@ cbq_dequeue(struct Qdisc *sch) | |||
943 | struct sk_buff *skb; | 943 | struct sk_buff *skb; |
944 | struct cbq_sched_data *q = qdisc_priv(sch); | 944 | struct cbq_sched_data *q = qdisc_priv(sch); |
945 | psched_time_t now; | 945 | psched_time_t now; |
946 | psched_tdiff_t incr; | ||
947 | 946 | ||
948 | now = psched_get_time(); | 947 | now = psched_get_time(); |
949 | incr = now - q->now_rt; | 948 | |
950 | 949 | if (q->tx_class) | |
951 | if (q->tx_class) { | ||
952 | psched_tdiff_t incr2; | ||
953 | /* Time integrator. We calculate EOS time | ||
954 | * by adding expected packet transmission time. | ||
955 | * If real time is greater, we warp artificial clock, | ||
956 | * so that: | ||
957 | * | ||
958 | * cbq_time = max(real_time, work); | ||
959 | */ | ||
960 | incr2 = L2T(&q->link, q->tx_len); | ||
961 | q->now += incr2; | ||
962 | cbq_update(q); | 950 | cbq_update(q); |
963 | if ((incr -= incr2) < 0) | 951 | |
964 | incr = 0; | 952 | q->now = now; |
965 | q->now += incr; | ||
966 | } else { | ||
967 | if (now > q->now) | ||
968 | q->now = now; | ||
969 | } | ||
970 | q->now_rt = now; | ||
971 | 953 | ||
972 | for (;;) { | 954 | for (;;) { |
973 | q->wd_expires = 0; | 955 | q->wd_expires = 0; |
@@ -1223,7 +1205,6 @@ cbq_reset(struct Qdisc *sch) | |||
1223 | hrtimer_cancel(&q->delay_timer); | 1205 | hrtimer_cancel(&q->delay_timer); |
1224 | q->toplevel = TC_CBQ_MAXLEVEL; | 1206 | q->toplevel = TC_CBQ_MAXLEVEL; |
1225 | q->now = psched_get_time(); | 1207 | q->now = psched_get_time(); |
1226 | q->now_rt = q->now; | ||
1227 | 1208 | ||
1228 | for (prio = 0; prio <= TC_CBQ_MAXPRIO; prio++) | 1209 | for (prio = 0; prio <= TC_CBQ_MAXPRIO; prio++) |
1229 | q->active[prio] = NULL; | 1210 | q->active[prio] = NULL; |
@@ -1407,7 +1388,6 @@ static int cbq_init(struct Qdisc *sch, struct nlattr *opt) | |||
1407 | q->delay_timer.function = cbq_undelay; | 1388 | q->delay_timer.function = cbq_undelay; |
1408 | q->toplevel = TC_CBQ_MAXLEVEL; | 1389 | q->toplevel = TC_CBQ_MAXLEVEL; |
1409 | q->now = psched_get_time(); | 1390 | q->now = psched_get_time(); |
1410 | q->now_rt = q->now; | ||
1411 | 1391 | ||
1412 | cbq_link_class(&q->link); | 1392 | cbq_link_class(&q->link); |
1413 | 1393 | ||
diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c index ed30e436128b..fb666d1e4de3 100644 --- a/net/sched/sch_choke.c +++ b/net/sched/sch_choke.c | |||
@@ -133,10 +133,16 @@ static void choke_drop_by_idx(struct Qdisc *sch, unsigned int idx) | |||
133 | --sch->q.qlen; | 133 | --sch->q.qlen; |
134 | } | 134 | } |
135 | 135 | ||
136 | /* private part of skb->cb[] that a qdisc is allowed to use | ||
137 | * is limited to QDISC_CB_PRIV_LEN bytes. | ||
138 | * As a flow key might be too large, we store a part of it only. | ||
139 | */ | ||
140 | #define CHOKE_K_LEN min_t(u32, sizeof(struct flow_keys), QDISC_CB_PRIV_LEN - 3) | ||
141 | |||
136 | struct choke_skb_cb { | 142 | struct choke_skb_cb { |
137 | u16 classid; | 143 | u16 classid; |
138 | u8 keys_valid; | 144 | u8 keys_valid; |
139 | struct flow_keys keys; | 145 | u8 keys[QDISC_CB_PRIV_LEN - 3]; |
140 | }; | 146 | }; |
141 | 147 | ||
142 | static inline struct choke_skb_cb *choke_skb_cb(const struct sk_buff *skb) | 148 | static inline struct choke_skb_cb *choke_skb_cb(const struct sk_buff *skb) |
@@ -163,22 +169,26 @@ static u16 choke_get_classid(const struct sk_buff *skb) | |||
163 | static bool choke_match_flow(struct sk_buff *skb1, | 169 | static bool choke_match_flow(struct sk_buff *skb1, |
164 | struct sk_buff *skb2) | 170 | struct sk_buff *skb2) |
165 | { | 171 | { |
172 | struct flow_keys temp; | ||
173 | |||
166 | if (skb1->protocol != skb2->protocol) | 174 | if (skb1->protocol != skb2->protocol) |
167 | return false; | 175 | return false; |
168 | 176 | ||
169 | if (!choke_skb_cb(skb1)->keys_valid) { | 177 | if (!choke_skb_cb(skb1)->keys_valid) { |
170 | choke_skb_cb(skb1)->keys_valid = 1; | 178 | choke_skb_cb(skb1)->keys_valid = 1; |
171 | skb_flow_dissect(skb1, &choke_skb_cb(skb1)->keys); | 179 | skb_flow_dissect(skb1, &temp); |
180 | memcpy(&choke_skb_cb(skb1)->keys, &temp, CHOKE_K_LEN); | ||
172 | } | 181 | } |
173 | 182 | ||
174 | if (!choke_skb_cb(skb2)->keys_valid) { | 183 | if (!choke_skb_cb(skb2)->keys_valid) { |
175 | choke_skb_cb(skb2)->keys_valid = 1; | 184 | choke_skb_cb(skb2)->keys_valid = 1; |
176 | skb_flow_dissect(skb2, &choke_skb_cb(skb2)->keys); | 185 | skb_flow_dissect(skb2, &temp); |
186 | memcpy(&choke_skb_cb(skb2)->keys, &temp, CHOKE_K_LEN); | ||
177 | } | 187 | } |
178 | 188 | ||
179 | return !memcmp(&choke_skb_cb(skb1)->keys, | 189 | return !memcmp(&choke_skb_cb(skb1)->keys, |
180 | &choke_skb_cb(skb2)->keys, | 190 | &choke_skb_cb(skb2)->keys, |
181 | sizeof(struct flow_keys)); | 191 | CHOKE_K_LEN); |
182 | } | 192 | } |
183 | 193 | ||
184 | /* | 194 | /* |
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index e1543b03e39d..fc04fe93c2da 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
@@ -108,7 +108,7 @@ static inline int handle_dev_cpu_collision(struct sk_buff *skb, | |||
108 | 108 | ||
109 | /* | 109 | /* |
110 | * Transmit one skb, and handle the return status as required. Holding the | 110 | * Transmit one skb, and handle the return status as required. Holding the |
111 | * __QDISC_STATE_RUNNING bit guarantees that only one CPU can execute this | 111 | * __QDISC___STATE_RUNNING bit guarantees that only one CPU can execute this |
112 | * function. | 112 | * function. |
113 | * | 113 | * |
114 | * Returns to the caller: | 114 | * Returns to the caller: |
@@ -156,7 +156,7 @@ int sch_direct_xmit(struct sk_buff *skb, struct Qdisc *q, | |||
156 | /* | 156 | /* |
157 | * NOTE: Called under qdisc_lock(q) with locally disabled BH. | 157 | * NOTE: Called under qdisc_lock(q) with locally disabled BH. |
158 | * | 158 | * |
159 | * __QDISC_STATE_RUNNING guarantees only one CPU can process | 159 | * __QDISC___STATE_RUNNING guarantees only one CPU can process |
160 | * this qdisc at a time. qdisc_lock(q) serializes queue accesses for | 160 | * this qdisc at a time. qdisc_lock(q) serializes queue accesses for |
161 | * this queue. | 161 | * this queue. |
162 | * | 162 | * |
diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c index 474167162947..bd33793b527e 100644 --- a/net/sched/sch_teql.c +++ b/net/sched/sch_teql.c | |||
@@ -485,8 +485,8 @@ static int __init teql_init(void) | |||
485 | struct net_device *dev; | 485 | struct net_device *dev; |
486 | struct teql_master *master; | 486 | struct teql_master *master; |
487 | 487 | ||
488 | dev = alloc_netdev(sizeof(struct teql_master), | 488 | dev = alloc_netdev(sizeof(struct teql_master), "teql%d", |
489 | "teql%d", teql_master_setup); | 489 | NET_NAME_UNKNOWN, teql_master_setup); |
490 | if (!dev) { | 490 | if (!dev) { |
491 | err = -ENOMEM; | 491 | err = -ENOMEM; |
492 | break; | 492 | break; |
diff --git a/net/sctp/Makefile b/net/sctp/Makefile index 5c30b7a873df..3b4ffb021cf1 100644 --- a/net/sctp/Makefile +++ b/net/sctp/Makefile | |||
@@ -8,7 +8,7 @@ obj-$(CONFIG_NET_SCTPPROBE) += sctp_probe.o | |||
8 | sctp-y := sm_statetable.o sm_statefuns.o sm_sideeffect.o \ | 8 | sctp-y := sm_statetable.o sm_statefuns.o sm_sideeffect.o \ |
9 | protocol.o endpointola.o associola.o \ | 9 | protocol.o endpointola.o associola.o \ |
10 | transport.o chunk.o sm_make_chunk.o ulpevent.o \ | 10 | transport.o chunk.o sm_make_chunk.o ulpevent.o \ |
11 | inqueue.o outqueue.o ulpqueue.o command.o \ | 11 | inqueue.o outqueue.o ulpqueue.o \ |
12 | tsnmap.o bind_addr.o socket.o primitive.o \ | 12 | tsnmap.o bind_addr.o socket.o primitive.o \ |
13 | output.o input.o debug.o ssnmap.o auth.o | 13 | output.o input.o debug.o ssnmap.o auth.o |
14 | 14 | ||
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index 06a9ee6b2d3a..a88b8524846e 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
@@ -813,6 +813,7 @@ void sctp_assoc_control_transport(struct sctp_association *asoc, | |||
813 | else { | 813 | else { |
814 | dst_release(transport->dst); | 814 | dst_release(transport->dst); |
815 | transport->dst = NULL; | 815 | transport->dst = NULL; |
816 | ulp_notify = false; | ||
816 | } | 817 | } |
817 | 818 | ||
818 | spc_state = SCTP_ADDR_UNREACHABLE; | 819 | spc_state = SCTP_ADDR_UNREACHABLE; |
@@ -1244,7 +1245,7 @@ static struct sctp_transport *sctp_trans_elect_best(struct sctp_transport *curr, | |||
1244 | { | 1245 | { |
1245 | u8 score_curr, score_best; | 1246 | u8 score_curr, score_best; |
1246 | 1247 | ||
1247 | if (best == NULL) | 1248 | if (best == NULL || curr == best) |
1248 | return curr; | 1249 | return curr; |
1249 | 1250 | ||
1250 | score_curr = sctp_trans_score(curr); | 1251 | score_curr = sctp_trans_score(curr); |
@@ -1355,14 +1356,11 @@ static void sctp_select_active_and_retran_path(struct sctp_association *asoc) | |||
1355 | trans_sec = trans_pri; | 1356 | trans_sec = trans_pri; |
1356 | 1357 | ||
1357 | /* If we failed to find a usable transport, just camp on the | 1358 | /* If we failed to find a usable transport, just camp on the |
1358 | * primary or retran, even if they are inactive, if possible | 1359 | * active or pick a PF iff it's the better choice. |
1359 | * pick a PF iff it's the better choice. | ||
1360 | */ | 1360 | */ |
1361 | if (trans_pri == NULL) { | 1361 | if (trans_pri == NULL) { |
1362 | trans_pri = sctp_trans_elect_best(asoc->peer.primary_path, | 1362 | trans_pri = sctp_trans_elect_best(asoc->peer.active_path, trans_pf); |
1363 | asoc->peer.retran_path); | 1363 | trans_sec = trans_pri; |
1364 | trans_pri = sctp_trans_elect_best(trans_pri, trans_pf); | ||
1365 | trans_sec = asoc->peer.primary_path; | ||
1366 | } | 1364 | } |
1367 | 1365 | ||
1368 | /* Set the active and retran transports. */ | 1366 | /* Set the active and retran transports. */ |
diff --git a/net/sctp/command.c b/net/sctp/command.c deleted file mode 100644 index dd7375851618..000000000000 --- a/net/sctp/command.c +++ /dev/null | |||
@@ -1,68 +0,0 @@ | |||
1 | /* SCTP kernel implementation Copyright (C) 1999-2001 | ||
2 | * Cisco, Motorola, and IBM | ||
3 | * Copyright 2001 La Monte H.P. Yarroll | ||
4 | * | ||
5 | * This file is part of the SCTP kernel implementation | ||
6 | * | ||
7 | * These functions manipulate sctp command sequences. | ||
8 | * | ||
9 | * This SCTP implementation is free software; | ||
10 | * you can redistribute it and/or modify it under the terms of | ||
11 | * the GNU General Public License as published by | ||
12 | * the Free Software Foundation; either version 2, or (at your option) | ||
13 | * any later version. | ||
14 | * | ||
15 | * This SCTP implementation is distributed in the hope that it | ||
16 | * will be useful, but WITHOUT ANY WARRANTY; without even the implied | ||
17 | * ************************ | ||
18 | * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. | ||
19 | * See the GNU General Public License for more details. | ||
20 | * | ||
21 | * You should have received a copy of the GNU General Public License | ||
22 | * along with GNU CC; see the file COPYING. If not, see | ||
23 | * <http://www.gnu.org/licenses/>. | ||
24 | * | ||
25 | * Please send any bug reports or fixes you make to the | ||
26 | * email address(es): | ||
27 | * lksctp developers <linux-sctp@vger.kernel.org> | ||
28 | * | ||
29 | * Written or modified by: | ||
30 | * La Monte H.P. Yarroll <piggy@acm.org> | ||
31 | * Karl Knutson <karl@athena.chicago.il.us> | ||
32 | */ | ||
33 | |||
34 | #include <linux/types.h> | ||
35 | #include <net/sctp/sctp.h> | ||
36 | #include <net/sctp/sm.h> | ||
37 | |||
38 | /* Initialize a block of memory as a command sequence. */ | ||
39 | int sctp_init_cmd_seq(sctp_cmd_seq_t *seq) | ||
40 | { | ||
41 | memset(seq, 0, sizeof(sctp_cmd_seq_t)); | ||
42 | return 1; /* We always succeed. */ | ||
43 | } | ||
44 | |||
45 | /* Add a command to a sctp_cmd_seq_t. | ||
46 | * Return 0 if the command sequence is full. | ||
47 | */ | ||
48 | void sctp_add_cmd_sf(sctp_cmd_seq_t *seq, sctp_verb_t verb, sctp_arg_t obj) | ||
49 | { | ||
50 | BUG_ON(seq->next_free_slot >= SCTP_MAX_NUM_COMMANDS); | ||
51 | |||
52 | seq->cmds[seq->next_free_slot].verb = verb; | ||
53 | seq->cmds[seq->next_free_slot++].obj = obj; | ||
54 | } | ||
55 | |||
56 | /* Return the next command structure in a sctp_cmd_seq. | ||
57 | * Returns NULL at the end of the sequence. | ||
58 | */ | ||
59 | sctp_cmd_t *sctp_next_cmd(sctp_cmd_seq_t *seq) | ||
60 | { | ||
61 | sctp_cmd_t *retval = NULL; | ||
62 | |||
63 | if (seq->next_cmd < seq->next_free_slot) | ||
64 | retval = &seq->cmds[seq->next_cmd++]; | ||
65 | |||
66 | return retval; | ||
67 | } | ||
68 | |||
diff --git a/net/sctp/input.c b/net/sctp/input.c index f2e2cbd2d750..c1b991294516 100644 --- a/net/sctp/input.c +++ b/net/sctp/input.c | |||
@@ -575,11 +575,6 @@ void sctp_v4_err(struct sk_buff *skb, __u32 info) | |||
575 | int err; | 575 | int err; |
576 | struct net *net = dev_net(skb->dev); | 576 | struct net *net = dev_net(skb->dev); |
577 | 577 | ||
578 | if (skb->len < ihlen + 8) { | ||
579 | ICMP_INC_STATS_BH(net, ICMP_MIB_INERRORS); | ||
580 | return; | ||
581 | } | ||
582 | |||
583 | /* Fix up skb to look at the embedded net header. */ | 578 | /* Fix up skb to look at the embedded net header. */ |
584 | saveip = skb->network_header; | 579 | saveip = skb->network_header; |
585 | savesctp = skb->transport_header; | 580 | savesctp = skb->transport_header; |
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index 1999592ba88c..0e4198ee2370 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c | |||
@@ -434,7 +434,7 @@ static void sctp_v6_from_sk(union sctp_addr *addr, struct sock *sk) | |||
434 | /* Initialize sk->sk_rcv_saddr from sctp_addr. */ | 434 | /* Initialize sk->sk_rcv_saddr from sctp_addr. */ |
435 | static void sctp_v6_to_sk_saddr(union sctp_addr *addr, struct sock *sk) | 435 | static void sctp_v6_to_sk_saddr(union sctp_addr *addr, struct sock *sk) |
436 | { | 436 | { |
437 | if (addr->sa.sa_family == AF_INET && sctp_sk(sk)->v4mapped) { | 437 | if (addr->sa.sa_family == AF_INET) { |
438 | sk->sk_v6_rcv_saddr.s6_addr32[0] = 0; | 438 | sk->sk_v6_rcv_saddr.s6_addr32[0] = 0; |
439 | sk->sk_v6_rcv_saddr.s6_addr32[1] = 0; | 439 | sk->sk_v6_rcv_saddr.s6_addr32[1] = 0; |
440 | sk->sk_v6_rcv_saddr.s6_addr32[2] = htonl(0x0000ffff); | 440 | sk->sk_v6_rcv_saddr.s6_addr32[2] = htonl(0x0000ffff); |
@@ -448,7 +448,7 @@ static void sctp_v6_to_sk_saddr(union sctp_addr *addr, struct sock *sk) | |||
448 | /* Initialize sk->sk_daddr from sctp_addr. */ | 448 | /* Initialize sk->sk_daddr from sctp_addr. */ |
449 | static void sctp_v6_to_sk_daddr(union sctp_addr *addr, struct sock *sk) | 449 | static void sctp_v6_to_sk_daddr(union sctp_addr *addr, struct sock *sk) |
450 | { | 450 | { |
451 | if (addr->sa.sa_family == AF_INET && sctp_sk(sk)->v4mapped) { | 451 | if (addr->sa.sa_family == AF_INET) { |
452 | sk->sk_v6_daddr.s6_addr32[0] = 0; | 452 | sk->sk_v6_daddr.s6_addr32[0] = 0; |
453 | sk->sk_v6_daddr.s6_addr32[1] = 0; | 453 | sk->sk_v6_daddr.s6_addr32[1] = 0; |
454 | sk->sk_v6_daddr.s6_addr32[2] = htonl(0x0000ffff); | 454 | sk->sk_v6_daddr.s6_addr32[2] = htonl(0x0000ffff); |
@@ -556,8 +556,6 @@ static int sctp_v6_available(union sctp_addr *addr, struct sctp_sock *sp) | |||
556 | if (IPV6_ADDR_ANY == type) | 556 | if (IPV6_ADDR_ANY == type) |
557 | return 1; | 557 | return 1; |
558 | if (type == IPV6_ADDR_MAPPED) { | 558 | if (type == IPV6_ADDR_MAPPED) { |
559 | if (sp && !sp->v4mapped) | ||
560 | return 0; | ||
561 | if (sp && ipv6_only_sock(sctp_opt2sk(sp))) | 559 | if (sp && ipv6_only_sock(sctp_opt2sk(sp))) |
562 | return 0; | 560 | return 0; |
563 | sctp_v6_map_v4(addr); | 561 | sctp_v6_map_v4(addr); |
@@ -587,8 +585,6 @@ static int sctp_v6_addr_valid(union sctp_addr *addr, | |||
587 | /* Note: This routine is used in input, so v4-mapped-v6 | 585 | /* Note: This routine is used in input, so v4-mapped-v6 |
588 | * are disallowed here when there is no sctp_sock. | 586 | * are disallowed here when there is no sctp_sock. |
589 | */ | 587 | */ |
590 | if (!sp || !sp->v4mapped) | ||
591 | return 0; | ||
592 | if (sp && ipv6_only_sock(sctp_opt2sk(sp))) | 588 | if (sp && ipv6_only_sock(sctp_opt2sk(sp))) |
593 | return 0; | 589 | return 0; |
594 | sctp_v6_map_v4(addr); | 590 | sctp_v6_map_v4(addr); |
@@ -675,11 +671,23 @@ out: | |||
675 | return newsk; | 671 | return newsk; |
676 | } | 672 | } |
677 | 673 | ||
678 | /* Map v4 address to mapped v6 address */ | 674 | /* Format a sockaddr for return to user space. This makes sure the return is |
679 | static void sctp_v6_addr_v4map(struct sctp_sock *sp, union sctp_addr *addr) | 675 | * AF_INET or AF_INET6 depending on the SCTP_I_WANT_MAPPED_V4_ADDR option. |
676 | */ | ||
677 | static int sctp_v6_addr_to_user(struct sctp_sock *sp, union sctp_addr *addr) | ||
680 | { | 678 | { |
681 | if (sp->v4mapped && AF_INET == addr->sa.sa_family) | 679 | if (sp->v4mapped) { |
682 | sctp_v4_map_v6(addr); | 680 | if (addr->sa.sa_family == AF_INET) |
681 | sctp_v4_map_v6(addr); | ||
682 | } else { | ||
683 | if (addr->sa.sa_family == AF_INET6 && | ||
684 | ipv6_addr_v4mapped(&addr->v6.sin6_addr)) | ||
685 | sctp_v6_map_v4(addr); | ||
686 | } | ||
687 | |||
688 | if (addr->sa.sa_family == AF_INET) | ||
689 | return sizeof(struct sockaddr_in); | ||
690 | return sizeof(struct sockaddr_in6); | ||
683 | } | 691 | } |
684 | 692 | ||
685 | /* Where did this skb come from? */ | 693 | /* Where did this skb come from? */ |
@@ -706,82 +714,68 @@ static void sctp_v6_ecn_capable(struct sock *sk) | |||
706 | inet6_sk(sk)->tclass |= INET_ECN_ECT_0; | 714 | inet6_sk(sk)->tclass |= INET_ECN_ECT_0; |
707 | } | 715 | } |
708 | 716 | ||
709 | /* Initialize a PF_INET6 socket msg_name. */ | ||
710 | static void sctp_inet6_msgname(char *msgname, int *addr_len) | ||
711 | { | ||
712 | struct sockaddr_in6 *sin6; | ||
713 | |||
714 | sin6 = (struct sockaddr_in6 *)msgname; | ||
715 | sin6->sin6_family = AF_INET6; | ||
716 | sin6->sin6_flowinfo = 0; | ||
717 | sin6->sin6_scope_id = 0; /*FIXME */ | ||
718 | *addr_len = sizeof(struct sockaddr_in6); | ||
719 | } | ||
720 | |||
721 | /* Initialize a PF_INET msgname from a ulpevent. */ | 717 | /* Initialize a PF_INET msgname from a ulpevent. */ |
722 | static void sctp_inet6_event_msgname(struct sctp_ulpevent *event, | 718 | static void sctp_inet6_event_msgname(struct sctp_ulpevent *event, |
723 | char *msgname, int *addrlen) | 719 | char *msgname, int *addrlen) |
724 | { | 720 | { |
725 | struct sockaddr_in6 *sin6, *sin6from; | 721 | union sctp_addr *addr; |
726 | 722 | struct sctp_association *asoc; | |
727 | if (msgname) { | 723 | union sctp_addr *paddr; |
728 | union sctp_addr *addr; | ||
729 | struct sctp_association *asoc; | ||
730 | |||
731 | asoc = event->asoc; | ||
732 | sctp_inet6_msgname(msgname, addrlen); | ||
733 | sin6 = (struct sockaddr_in6 *)msgname; | ||
734 | sin6->sin6_port = htons(asoc->peer.port); | ||
735 | addr = &asoc->peer.primary_addr; | ||
736 | 724 | ||
737 | /* Note: If we go to a common v6 format, this code | 725 | if (!msgname) |
738 | * will change. | 726 | return; |
739 | */ | ||
740 | 727 | ||
741 | /* Map ipv4 address into v4-mapped-on-v6 address. */ | 728 | addr = (union sctp_addr *)msgname; |
742 | if (sctp_sk(asoc->base.sk)->v4mapped && | 729 | asoc = event->asoc; |
743 | AF_INET == addr->sa.sa_family) { | 730 | paddr = &asoc->peer.primary_addr; |
744 | sctp_v4_map_v6((union sctp_addr *)sin6); | ||
745 | sin6->sin6_addr.s6_addr32[3] = | ||
746 | addr->v4.sin_addr.s_addr; | ||
747 | return; | ||
748 | } | ||
749 | 731 | ||
750 | sin6from = &asoc->peer.primary_addr.v6; | 732 | if (paddr->sa.sa_family == AF_INET) { |
751 | sin6->sin6_addr = sin6from->sin6_addr; | 733 | addr->v4.sin_family = AF_INET; |
752 | if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) | 734 | addr->v4.sin_port = htons(asoc->peer.port); |
753 | sin6->sin6_scope_id = sin6from->sin6_scope_id; | 735 | addr->v4.sin_addr = paddr->v4.sin_addr; |
736 | } else { | ||
737 | addr->v6.sin6_family = AF_INET6; | ||
738 | addr->v6.sin6_flowinfo = 0; | ||
739 | if (ipv6_addr_type(&paddr->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL) | ||
740 | addr->v6.sin6_scope_id = paddr->v6.sin6_scope_id; | ||
741 | else | ||
742 | addr->v6.sin6_scope_id = 0; | ||
743 | addr->v6.sin6_port = htons(asoc->peer.port); | ||
744 | addr->v6.sin6_addr = paddr->v6.sin6_addr; | ||
754 | } | 745 | } |
746 | |||
747 | *addrlen = sctp_v6_addr_to_user(sctp_sk(asoc->base.sk), addr); | ||
755 | } | 748 | } |
756 | 749 | ||
757 | /* Initialize a msg_name from an inbound skb. */ | 750 | /* Initialize a msg_name from an inbound skb. */ |
758 | static void sctp_inet6_skb_msgname(struct sk_buff *skb, char *msgname, | 751 | static void sctp_inet6_skb_msgname(struct sk_buff *skb, char *msgname, |
759 | int *addr_len) | 752 | int *addr_len) |
760 | { | 753 | { |
754 | union sctp_addr *addr; | ||
761 | struct sctphdr *sh; | 755 | struct sctphdr *sh; |
762 | struct sockaddr_in6 *sin6; | ||
763 | |||
764 | if (msgname) { | ||
765 | sctp_inet6_msgname(msgname, addr_len); | ||
766 | sin6 = (struct sockaddr_in6 *)msgname; | ||
767 | sh = sctp_hdr(skb); | ||
768 | sin6->sin6_port = sh->source; | ||
769 | |||
770 | /* Map ipv4 address into v4-mapped-on-v6 address. */ | ||
771 | if (sctp_sk(skb->sk)->v4mapped && | ||
772 | ip_hdr(skb)->version == 4) { | ||
773 | sctp_v4_map_v6((union sctp_addr *)sin6); | ||
774 | sin6->sin6_addr.s6_addr32[3] = ip_hdr(skb)->saddr; | ||
775 | return; | ||
776 | } | ||
777 | 756 | ||
778 | /* Otherwise, just copy the v6 address. */ | 757 | if (!msgname) |
779 | sin6->sin6_addr = ipv6_hdr(skb)->saddr; | 758 | return; |
780 | if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL) { | 759 | |
760 | addr = (union sctp_addr *)msgname; | ||
761 | sh = sctp_hdr(skb); | ||
762 | |||
763 | if (ip_hdr(skb)->version == 4) { | ||
764 | addr->v4.sin_family = AF_INET; | ||
765 | addr->v4.sin_port = sh->source; | ||
766 | addr->v4.sin_addr.s_addr = ip_hdr(skb)->saddr; | ||
767 | } else { | ||
768 | addr->v6.sin6_family = AF_INET6; | ||
769 | addr->v6.sin6_flowinfo = 0; | ||
770 | addr->v6.sin6_port = sh->source; | ||
771 | addr->v6.sin6_addr = ipv6_hdr(skb)->saddr; | ||
772 | if (ipv6_addr_type(&addr->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL) { | ||
781 | struct sctp_ulpevent *ev = sctp_skb2event(skb); | 773 | struct sctp_ulpevent *ev = sctp_skb2event(skb); |
782 | sin6->sin6_scope_id = ev->iif; | 774 | addr->v6.sin6_scope_id = ev->iif; |
783 | } | 775 | } |
784 | } | 776 | } |
777 | |||
778 | *addr_len = sctp_v6_addr_to_user(sctp_sk(skb->sk), addr); | ||
785 | } | 779 | } |
786 | 780 | ||
787 | /* Do we support this AF? */ | 781 | /* Do we support this AF? */ |
@@ -857,9 +851,6 @@ static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr) | |||
857 | return 0; | 851 | return 0; |
858 | } | 852 | } |
859 | rcu_read_unlock(); | 853 | rcu_read_unlock(); |
860 | } else if (type == IPV6_ADDR_MAPPED) { | ||
861 | if (!opt->v4mapped) | ||
862 | return 0; | ||
863 | } | 854 | } |
864 | 855 | ||
865 | af = opt->pf->af; | 856 | af = opt->pf->af; |
@@ -914,6 +905,23 @@ static int sctp_inet6_supported_addrs(const struct sctp_sock *opt, | |||
914 | return 1; | 905 | return 1; |
915 | } | 906 | } |
916 | 907 | ||
908 | /* Handle SCTP_I_WANT_MAPPED_V4_ADDR for getpeername() and getsockname() */ | ||
909 | static int sctp_getname(struct socket *sock, struct sockaddr *uaddr, | ||
910 | int *uaddr_len, int peer) | ||
911 | { | ||
912 | int rc; | ||
913 | |||
914 | rc = inet6_getname(sock, uaddr, uaddr_len, peer); | ||
915 | |||
916 | if (rc != 0) | ||
917 | return rc; | ||
918 | |||
919 | *uaddr_len = sctp_v6_addr_to_user(sctp_sk(sock->sk), | ||
920 | (union sctp_addr *)uaddr); | ||
921 | |||
922 | return rc; | ||
923 | } | ||
924 | |||
917 | static const struct proto_ops inet6_seqpacket_ops = { | 925 | static const struct proto_ops inet6_seqpacket_ops = { |
918 | .family = PF_INET6, | 926 | .family = PF_INET6, |
919 | .owner = THIS_MODULE, | 927 | .owner = THIS_MODULE, |
@@ -922,7 +930,7 @@ static const struct proto_ops inet6_seqpacket_ops = { | |||
922 | .connect = inet_dgram_connect, | 930 | .connect = inet_dgram_connect, |
923 | .socketpair = sock_no_socketpair, | 931 | .socketpair = sock_no_socketpair, |
924 | .accept = inet_accept, | 932 | .accept = inet_accept, |
925 | .getname = inet6_getname, | 933 | .getname = sctp_getname, |
926 | .poll = sctp_poll, | 934 | .poll = sctp_poll, |
927 | .ioctl = inet6_ioctl, | 935 | .ioctl = inet6_ioctl, |
928 | .listen = sctp_inet_listen, | 936 | .listen = sctp_inet_listen, |
@@ -974,8 +982,6 @@ static struct sctp_af sctp_af_inet6 = { | |||
974 | .copy_addrlist = sctp_v6_copy_addrlist, | 982 | .copy_addrlist = sctp_v6_copy_addrlist, |
975 | .from_skb = sctp_v6_from_skb, | 983 | .from_skb = sctp_v6_from_skb, |
976 | .from_sk = sctp_v6_from_sk, | 984 | .from_sk = sctp_v6_from_sk, |
977 | .to_sk_saddr = sctp_v6_to_sk_saddr, | ||
978 | .to_sk_daddr = sctp_v6_to_sk_daddr, | ||
979 | .from_addr_param = sctp_v6_from_addr_param, | 985 | .from_addr_param = sctp_v6_from_addr_param, |
980 | .to_addr_param = sctp_v6_to_addr_param, | 986 | .to_addr_param = sctp_v6_to_addr_param, |
981 | .cmp_addr = sctp_v6_cmp_addr, | 987 | .cmp_addr = sctp_v6_cmp_addr, |
@@ -1005,7 +1011,9 @@ static struct sctp_pf sctp_pf_inet6 = { | |||
1005 | .send_verify = sctp_inet6_send_verify, | 1011 | .send_verify = sctp_inet6_send_verify, |
1006 | .supported_addrs = sctp_inet6_supported_addrs, | 1012 | .supported_addrs = sctp_inet6_supported_addrs, |
1007 | .create_accept_sk = sctp_v6_create_accept_sk, | 1013 | .create_accept_sk = sctp_v6_create_accept_sk, |
1008 | .addr_v4map = sctp_v6_addr_v4map, | 1014 | .addr_to_user = sctp_v6_addr_to_user, |
1015 | .to_sk_saddr = sctp_v6_to_sk_saddr, | ||
1016 | .to_sk_daddr = sctp_v6_to_sk_daddr, | ||
1009 | .af = &sctp_af_inet6, | 1017 | .af = &sctp_af_inet6, |
1010 | }; | 1018 | }; |
1011 | 1019 | ||
diff --git a/net/sctp/output.c b/net/sctp/output.c index 01ab8e0723f0..42dffd428389 100644 --- a/net/sctp/output.c +++ b/net/sctp/output.c | |||
@@ -178,7 +178,7 @@ sctp_xmit_t sctp_packet_transmit_chunk(struct sctp_packet *packet, | |||
178 | 178 | ||
179 | case SCTP_XMIT_RWND_FULL: | 179 | case SCTP_XMIT_RWND_FULL: |
180 | case SCTP_XMIT_OK: | 180 | case SCTP_XMIT_OK: |
181 | case SCTP_XMIT_NAGLE_DELAY: | 181 | case SCTP_XMIT_DELAY: |
182 | break; | 182 | break; |
183 | } | 183 | } |
184 | 184 | ||
@@ -599,7 +599,7 @@ out: | |||
599 | return err; | 599 | return err; |
600 | no_route: | 600 | no_route: |
601 | kfree_skb(nskb); | 601 | kfree_skb(nskb); |
602 | IP_INC_STATS_BH(sock_net(asoc->base.sk), IPSTATS_MIB_OUTNOROUTES); | 602 | IP_INC_STATS(sock_net(asoc->base.sk), IPSTATS_MIB_OUTNOROUTES); |
603 | 603 | ||
604 | /* FIXME: Returning the 'err' will effect all the associations | 604 | /* FIXME: Returning the 'err' will effect all the associations |
605 | * associated with a socket, although only one of the paths of the | 605 | * associated with a socket, although only one of the paths of the |
@@ -633,7 +633,6 @@ nomem: | |||
633 | static sctp_xmit_t sctp_packet_can_append_data(struct sctp_packet *packet, | 633 | static sctp_xmit_t sctp_packet_can_append_data(struct sctp_packet *packet, |
634 | struct sctp_chunk *chunk) | 634 | struct sctp_chunk *chunk) |
635 | { | 635 | { |
636 | sctp_xmit_t retval = SCTP_XMIT_OK; | ||
637 | size_t datasize, rwnd, inflight, flight_size; | 636 | size_t datasize, rwnd, inflight, flight_size; |
638 | struct sctp_transport *transport = packet->transport; | 637 | struct sctp_transport *transport = packet->transport; |
639 | struct sctp_association *asoc = transport->asoc; | 638 | struct sctp_association *asoc = transport->asoc; |
@@ -658,15 +657,11 @@ static sctp_xmit_t sctp_packet_can_append_data(struct sctp_packet *packet, | |||
658 | 657 | ||
659 | datasize = sctp_data_size(chunk); | 658 | datasize = sctp_data_size(chunk); |
660 | 659 | ||
661 | if (datasize > rwnd) { | 660 | if (datasize > rwnd && inflight > 0) |
662 | if (inflight > 0) { | 661 | /* We have (at least) one data chunk in flight, |
663 | /* We have (at least) one data chunk in flight, | 662 | * so we can't fall back to rule 6.1 B). |
664 | * so we can't fall back to rule 6.1 B). | 663 | */ |
665 | */ | 664 | return SCTP_XMIT_RWND_FULL; |
666 | retval = SCTP_XMIT_RWND_FULL; | ||
667 | goto finish; | ||
668 | } | ||
669 | } | ||
670 | 665 | ||
671 | /* RFC 2960 6.1 Transmission of DATA Chunks | 666 | /* RFC 2960 6.1 Transmission of DATA Chunks |
672 | * | 667 | * |
@@ -680,36 +675,44 @@ static sctp_xmit_t sctp_packet_can_append_data(struct sctp_packet *packet, | |||
680 | * When a Fast Retransmit is being performed the sender SHOULD | 675 | * When a Fast Retransmit is being performed the sender SHOULD |
681 | * ignore the value of cwnd and SHOULD NOT delay retransmission. | 676 | * ignore the value of cwnd and SHOULD NOT delay retransmission. |
682 | */ | 677 | */ |
683 | if (chunk->fast_retransmit != SCTP_NEED_FRTX) | 678 | if (chunk->fast_retransmit != SCTP_NEED_FRTX && |
684 | if (flight_size >= transport->cwnd) { | 679 | flight_size >= transport->cwnd) |
685 | retval = SCTP_XMIT_RWND_FULL; | 680 | return SCTP_XMIT_RWND_FULL; |
686 | goto finish; | ||
687 | } | ||
688 | 681 | ||
689 | /* Nagle's algorithm to solve small-packet problem: | 682 | /* Nagle's algorithm to solve small-packet problem: |
690 | * Inhibit the sending of new chunks when new outgoing data arrives | 683 | * Inhibit the sending of new chunks when new outgoing data arrives |
691 | * if any previously transmitted data on the connection remains | 684 | * if any previously transmitted data on the connection remains |
692 | * unacknowledged. | 685 | * unacknowledged. |
693 | */ | 686 | */ |
694 | if (!sctp_sk(asoc->base.sk)->nodelay && sctp_packet_empty(packet) && | ||
695 | inflight && sctp_state(asoc, ESTABLISHED)) { | ||
696 | unsigned int max = transport->pathmtu - packet->overhead; | ||
697 | unsigned int len = chunk->skb->len + q->out_qlen; | ||
698 | |||
699 | /* Check whether this chunk and all the rest of pending | ||
700 | * data will fit or delay in hopes of bundling a full | ||
701 | * sized packet. | ||
702 | * Don't delay large message writes that may have been | ||
703 | * fragmeneted into small peices. | ||
704 | */ | ||
705 | if ((len < max) && chunk->msg->can_delay) { | ||
706 | retval = SCTP_XMIT_NAGLE_DELAY; | ||
707 | goto finish; | ||
708 | } | ||
709 | } | ||
710 | 687 | ||
711 | finish: | 688 | if (sctp_sk(asoc->base.sk)->nodelay) |
712 | return retval; | 689 | /* Nagle disabled */ |
690 | return SCTP_XMIT_OK; | ||
691 | |||
692 | if (!sctp_packet_empty(packet)) | ||
693 | /* Append to packet */ | ||
694 | return SCTP_XMIT_OK; | ||
695 | |||
696 | if (inflight == 0) | ||
697 | /* Nothing unacked */ | ||
698 | return SCTP_XMIT_OK; | ||
699 | |||
700 | if (!sctp_state(asoc, ESTABLISHED)) | ||
701 | return SCTP_XMIT_OK; | ||
702 | |||
703 | /* Check whether this chunk and all the rest of pending data will fit | ||
704 | * or delay in hopes of bundling a full sized packet. | ||
705 | */ | ||
706 | if (chunk->skb->len + q->out_qlen >= transport->pathmtu - packet->overhead) | ||
707 | /* Enough data queued to fill a packet */ | ||
708 | return SCTP_XMIT_OK; | ||
709 | |||
710 | /* Don't delay large message writes that may have been fragmented */ | ||
711 | if (!chunk->msg->can_delay) | ||
712 | return SCTP_XMIT_OK; | ||
713 | |||
714 | /* Defer until all data acked or packet full */ | ||
715 | return SCTP_XMIT_DELAY; | ||
713 | } | 716 | } |
714 | 717 | ||
715 | /* This private function does management things when adding DATA chunk */ | 718 | /* This private function does management things when adding DATA chunk */ |
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c index 9c77947c0597..7e8f0a117106 100644 --- a/net/sctp/outqueue.c +++ b/net/sctp/outqueue.c | |||
@@ -629,7 +629,7 @@ redo: | |||
629 | done = 1; | 629 | done = 1; |
630 | break; | 630 | break; |
631 | 631 | ||
632 | case SCTP_XMIT_NAGLE_DELAY: | 632 | case SCTP_XMIT_DELAY: |
633 | /* Send this packet. */ | 633 | /* Send this packet. */ |
634 | error = sctp_packet_transmit(pkt); | 634 | error = sctp_packet_transmit(pkt); |
635 | 635 | ||
@@ -1015,7 +1015,7 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
1015 | switch (status) { | 1015 | switch (status) { |
1016 | case SCTP_XMIT_PMTU_FULL: | 1016 | case SCTP_XMIT_PMTU_FULL: |
1017 | case SCTP_XMIT_RWND_FULL: | 1017 | case SCTP_XMIT_RWND_FULL: |
1018 | case SCTP_XMIT_NAGLE_DELAY: | 1018 | case SCTP_XMIT_DELAY: |
1019 | /* We could not append this chunk, so put | 1019 | /* We could not append this chunk, so put |
1020 | * the chunk back on the output queue. | 1020 | * the chunk back on the output queue. |
1021 | */ | 1021 | */ |
@@ -1025,7 +1025,6 @@ static int sctp_outq_flush(struct sctp_outq *q, int rtx_timeout) | |||
1025 | 1025 | ||
1026 | sctp_outq_head_data(q, chunk); | 1026 | sctp_outq_head_data(q, chunk); |
1027 | goto sctp_flush_out; | 1027 | goto sctp_flush_out; |
1028 | break; | ||
1029 | 1028 | ||
1030 | case SCTP_XMIT_OK: | 1029 | case SCTP_XMIT_OK: |
1031 | /* The sender is in the SHUTDOWN-PENDING state, | 1030 | /* The sender is in the SHUTDOWN-PENDING state, |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 6789d785e698..6240834f4b95 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
@@ -576,10 +576,10 @@ out: | |||
576 | return newsk; | 576 | return newsk; |
577 | } | 577 | } |
578 | 578 | ||
579 | /* Map address, empty for v4 family */ | 579 | static int sctp_v4_addr_to_user(struct sctp_sock *sp, union sctp_addr *addr) |
580 | static void sctp_v4_addr_v4map(struct sctp_sock *sp, union sctp_addr *addr) | ||
581 | { | 580 | { |
582 | /* Empty */ | 581 | /* No address mapping for V4 sockets */ |
582 | return sizeof(struct sockaddr_in); | ||
583 | } | 583 | } |
584 | 584 | ||
585 | /* Dump the v4 addr to the seq file. */ | 585 | /* Dump the v4 addr to the seq file. */ |
@@ -976,7 +976,9 @@ static struct sctp_pf sctp_pf_inet = { | |||
976 | .send_verify = sctp_inet_send_verify, | 976 | .send_verify = sctp_inet_send_verify, |
977 | .supported_addrs = sctp_inet_supported_addrs, | 977 | .supported_addrs = sctp_inet_supported_addrs, |
978 | .create_accept_sk = sctp_v4_create_accept_sk, | 978 | .create_accept_sk = sctp_v4_create_accept_sk, |
979 | .addr_v4map = sctp_v4_addr_v4map, | 979 | .addr_to_user = sctp_v4_addr_to_user, |
980 | .to_sk_saddr = sctp_v4_to_sk_saddr, | ||
981 | .to_sk_daddr = sctp_v4_to_sk_daddr, | ||
980 | .af = &sctp_af_inet | 982 | .af = &sctp_af_inet |
981 | }; | 983 | }; |
982 | 984 | ||
@@ -1047,8 +1049,6 @@ static struct sctp_af sctp_af_inet = { | |||
1047 | .copy_addrlist = sctp_v4_copy_addrlist, | 1049 | .copy_addrlist = sctp_v4_copy_addrlist, |
1048 | .from_skb = sctp_v4_from_skb, | 1050 | .from_skb = sctp_v4_from_skb, |
1049 | .from_sk = sctp_v4_from_sk, | 1051 | .from_sk = sctp_v4_from_sk, |
1050 | .to_sk_saddr = sctp_v4_to_sk_saddr, | ||
1051 | .to_sk_daddr = sctp_v4_to_sk_daddr, | ||
1052 | .from_addr_param = sctp_v4_from_addr_param, | 1052 | .from_addr_param = sctp_v4_from_addr_param, |
1053 | .to_addr_param = sctp_v4_to_addr_param, | 1053 | .to_addr_param = sctp_v4_to_addr_param, |
1054 | .cmp_addr = sctp_v4_cmp_addr, | 1054 | .cmp_addr = sctp_v4_cmp_addr, |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 5170a1ff95a1..d3f1ea460c50 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
@@ -4182,7 +4182,6 @@ sctp_disposition_t sctp_sf_unk_chunk(struct net *net, | |||
4182 | case SCTP_CID_ACTION_DISCARD: | 4182 | case SCTP_CID_ACTION_DISCARD: |
4183 | /* Discard the packet. */ | 4183 | /* Discard the packet. */ |
4184 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); | 4184 | return sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
4185 | break; | ||
4186 | case SCTP_CID_ACTION_DISCARD_ERR: | 4185 | case SCTP_CID_ACTION_DISCARD_ERR: |
4187 | /* Generate an ERROR chunk as response. */ | 4186 | /* Generate an ERROR chunk as response. */ |
4188 | hdr = unk_chunk->chunk_hdr; | 4187 | hdr = unk_chunk->chunk_hdr; |
@@ -4198,11 +4197,9 @@ sctp_disposition_t sctp_sf_unk_chunk(struct net *net, | |||
4198 | /* Discard the packet. */ | 4197 | /* Discard the packet. */ |
4199 | sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); | 4198 | sctp_sf_pdiscard(net, ep, asoc, type, arg, commands); |
4200 | return SCTP_DISPOSITION_CONSUME; | 4199 | return SCTP_DISPOSITION_CONSUME; |
4201 | break; | ||
4202 | case SCTP_CID_ACTION_SKIP: | 4200 | case SCTP_CID_ACTION_SKIP: |
4203 | /* Skip the chunk. */ | 4201 | /* Skip the chunk. */ |
4204 | return SCTP_DISPOSITION_DISCARD; | 4202 | return SCTP_DISPOSITION_DISCARD; |
4205 | break; | ||
4206 | case SCTP_CID_ACTION_SKIP_ERR: | 4203 | case SCTP_CID_ACTION_SKIP_ERR: |
4207 | /* Generate an ERROR chunk as response. */ | 4204 | /* Generate an ERROR chunk as response. */ |
4208 | hdr = unk_chunk->chunk_hdr; | 4205 | hdr = unk_chunk->chunk_hdr; |
@@ -4216,7 +4213,6 @@ sctp_disposition_t sctp_sf_unk_chunk(struct net *net, | |||
4216 | } | 4213 | } |
4217 | /* Skip the chunk. */ | 4214 | /* Skip the chunk. */ |
4218 | return SCTP_DISPOSITION_CONSUME; | 4215 | return SCTP_DISPOSITION_CONSUME; |
4219 | break; | ||
4220 | default: | 4216 | default: |
4221 | break; | 4217 | break; |
4222 | } | 4218 | } |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 429899689408..634a2abb5f3a 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
@@ -254,7 +254,7 @@ static struct sctp_transport *sctp_addr_id2transport(struct sock *sk, | |||
254 | if (id_asoc && (id_asoc != addr_asoc)) | 254 | if (id_asoc && (id_asoc != addr_asoc)) |
255 | return NULL; | 255 | return NULL; |
256 | 256 | ||
257 | sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), | 257 | sctp_get_pf_specific(sk->sk_family)->addr_to_user(sctp_sk(sk), |
258 | (union sctp_addr *)addr); | 258 | (union sctp_addr *)addr); |
259 | 259 | ||
260 | return transport; | 260 | return transport; |
@@ -396,7 +396,7 @@ static int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len) | |||
396 | /* Copy back into socket for getsockname() use. */ | 396 | /* Copy back into socket for getsockname() use. */ |
397 | if (!ret) { | 397 | if (!ret) { |
398 | inet_sk(sk)->inet_sport = htons(inet_sk(sk)->inet_num); | 398 | inet_sk(sk)->inet_sport = htons(inet_sk(sk)->inet_num); |
399 | af->to_sk_saddr(addr, sk); | 399 | sp->pf->to_sk_saddr(addr, sk); |
400 | } | 400 | } |
401 | 401 | ||
402 | return ret; | 402 | return ret; |
@@ -1053,7 +1053,6 @@ static int __sctp_connect(struct sock *sk, | |||
1053 | struct sctp_association *asoc2; | 1053 | struct sctp_association *asoc2; |
1054 | struct sctp_transport *transport; | 1054 | struct sctp_transport *transport; |
1055 | union sctp_addr to; | 1055 | union sctp_addr to; |
1056 | struct sctp_af *af; | ||
1057 | sctp_scope_t scope; | 1056 | sctp_scope_t scope; |
1058 | long timeo; | 1057 | long timeo; |
1059 | int err = 0; | 1058 | int err = 0; |
@@ -1081,6 +1080,8 @@ static int __sctp_connect(struct sock *sk, | |||
1081 | /* Walk through the addrs buffer and count the number of addresses. */ | 1080 | /* Walk through the addrs buffer and count the number of addresses. */ |
1082 | addr_buf = kaddrs; | 1081 | addr_buf = kaddrs; |
1083 | while (walk_size < addrs_size) { | 1082 | while (walk_size < addrs_size) { |
1083 | struct sctp_af *af; | ||
1084 | |||
1084 | if (walk_size + sizeof(sa_family_t) > addrs_size) { | 1085 | if (walk_size + sizeof(sa_family_t) > addrs_size) { |
1085 | err = -EINVAL; | 1086 | err = -EINVAL; |
1086 | goto out_free; | 1087 | goto out_free; |
@@ -1205,8 +1206,7 @@ static int __sctp_connect(struct sock *sk, | |||
1205 | 1206 | ||
1206 | /* Initialize sk's dport and daddr for getpeername() */ | 1207 | /* Initialize sk's dport and daddr for getpeername() */ |
1207 | inet_sk(sk)->inet_dport = htons(asoc->peer.port); | 1208 | inet_sk(sk)->inet_dport = htons(asoc->peer.port); |
1208 | af = sctp_get_af_specific(sa_addr->sa.sa_family); | 1209 | sp->pf->to_sk_daddr(sa_addr, sk); |
1209 | af->to_sk_daddr(sa_addr, sk); | ||
1210 | sk->sk_err = 0; | 1210 | sk->sk_err = 0; |
1211 | 1211 | ||
1212 | /* in-kernel sockets don't generally have a file allocated to them | 1212 | /* in-kernel sockets don't generally have a file allocated to them |
@@ -1602,12 +1602,13 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1602 | struct sctp_initmsg *sinit; | 1602 | struct sctp_initmsg *sinit; |
1603 | sctp_assoc_t associd = 0; | 1603 | sctp_assoc_t associd = 0; |
1604 | sctp_cmsgs_t cmsgs = { NULL }; | 1604 | sctp_cmsgs_t cmsgs = { NULL }; |
1605 | int err; | ||
1606 | sctp_scope_t scope; | 1605 | sctp_scope_t scope; |
1607 | long timeo; | 1606 | bool fill_sinfo_ttl = false; |
1608 | __u16 sinfo_flags = 0; | ||
1609 | struct sctp_datamsg *datamsg; | 1607 | struct sctp_datamsg *datamsg; |
1610 | int msg_flags = msg->msg_flags; | 1608 | int msg_flags = msg->msg_flags; |
1609 | __u16 sinfo_flags = 0; | ||
1610 | long timeo; | ||
1611 | int err; | ||
1611 | 1612 | ||
1612 | err = 0; | 1613 | err = 0; |
1613 | sp = sctp_sk(sk); | 1614 | sp = sctp_sk(sk); |
@@ -1648,10 +1649,21 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1648 | msg_name = msg->msg_name; | 1649 | msg_name = msg->msg_name; |
1649 | } | 1650 | } |
1650 | 1651 | ||
1651 | sinfo = cmsgs.info; | ||
1652 | sinit = cmsgs.init; | 1652 | sinit = cmsgs.init; |
1653 | if (cmsgs.sinfo != NULL) { | ||
1654 | memset(&default_sinfo, 0, sizeof(default_sinfo)); | ||
1655 | default_sinfo.sinfo_stream = cmsgs.sinfo->snd_sid; | ||
1656 | default_sinfo.sinfo_flags = cmsgs.sinfo->snd_flags; | ||
1657 | default_sinfo.sinfo_ppid = cmsgs.sinfo->snd_ppid; | ||
1658 | default_sinfo.sinfo_context = cmsgs.sinfo->snd_context; | ||
1659 | default_sinfo.sinfo_assoc_id = cmsgs.sinfo->snd_assoc_id; | ||
1653 | 1660 | ||
1654 | /* Did the user specify SNDRCVINFO? */ | 1661 | sinfo = &default_sinfo; |
1662 | fill_sinfo_ttl = true; | ||
1663 | } else { | ||
1664 | sinfo = cmsgs.srinfo; | ||
1665 | } | ||
1666 | /* Did the user specify SNDINFO/SNDRCVINFO? */ | ||
1655 | if (sinfo) { | 1667 | if (sinfo) { |
1656 | sinfo_flags = sinfo->sinfo_flags; | 1668 | sinfo_flags = sinfo->sinfo_flags; |
1657 | associd = sinfo->sinfo_assoc_id; | 1669 | associd = sinfo->sinfo_assoc_id; |
@@ -1858,8 +1870,8 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1858 | pr_debug("%s: we have a valid association\n", __func__); | 1870 | pr_debug("%s: we have a valid association\n", __func__); |
1859 | 1871 | ||
1860 | if (!sinfo) { | 1872 | if (!sinfo) { |
1861 | /* If the user didn't specify SNDRCVINFO, make up one with | 1873 | /* If the user didn't specify SNDINFO/SNDRCVINFO, make up |
1862 | * some defaults. | 1874 | * one with some defaults. |
1863 | */ | 1875 | */ |
1864 | memset(&default_sinfo, 0, sizeof(default_sinfo)); | 1876 | memset(&default_sinfo, 0, sizeof(default_sinfo)); |
1865 | default_sinfo.sinfo_stream = asoc->default_stream; | 1877 | default_sinfo.sinfo_stream = asoc->default_stream; |
@@ -1868,7 +1880,13 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
1868 | default_sinfo.sinfo_context = asoc->default_context; | 1880 | default_sinfo.sinfo_context = asoc->default_context; |
1869 | default_sinfo.sinfo_timetolive = asoc->default_timetolive; | 1881 | default_sinfo.sinfo_timetolive = asoc->default_timetolive; |
1870 | default_sinfo.sinfo_assoc_id = sctp_assoc2id(asoc); | 1882 | default_sinfo.sinfo_assoc_id = sctp_assoc2id(asoc); |
1883 | |||
1871 | sinfo = &default_sinfo; | 1884 | sinfo = &default_sinfo; |
1885 | } else if (fill_sinfo_ttl) { | ||
1886 | /* In case SNDINFO was specified, we still need to fill | ||
1887 | * it with a default ttl from the assoc here. | ||
1888 | */ | ||
1889 | sinfo->sinfo_timetolive = asoc->default_timetolive; | ||
1872 | } | 1890 | } |
1873 | 1891 | ||
1874 | /* API 7.1.7, the sndbuf size per association bounds the | 1892 | /* API 7.1.7, the sndbuf size per association bounds the |
@@ -2042,8 +2060,6 @@ static int sctp_skb_pull(struct sk_buff *skb, int len) | |||
2042 | * flags - flags sent or received with the user message, see Section | 2060 | * flags - flags sent or received with the user message, see Section |
2043 | * 5 for complete description of the flags. | 2061 | * 5 for complete description of the flags. |
2044 | */ | 2062 | */ |
2045 | static struct sk_buff *sctp_skb_recv_datagram(struct sock *, int, int, int *); | ||
2046 | |||
2047 | static int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, | 2063 | static int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, |
2048 | struct msghdr *msg, size_t len, int noblock, | 2064 | struct msghdr *msg, size_t len, int noblock, |
2049 | int flags, int *addr_len) | 2065 | int flags, int *addr_len) |
@@ -2094,9 +2110,16 @@ static int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
2094 | sp->pf->skb_msgname(skb, msg->msg_name, addr_len); | 2110 | sp->pf->skb_msgname(skb, msg->msg_name, addr_len); |
2095 | } | 2111 | } |
2096 | 2112 | ||
2113 | /* Check if we allow SCTP_NXTINFO. */ | ||
2114 | if (sp->recvnxtinfo) | ||
2115 | sctp_ulpevent_read_nxtinfo(event, msg, sk); | ||
2116 | /* Check if we allow SCTP_RCVINFO. */ | ||
2117 | if (sp->recvrcvinfo) | ||
2118 | sctp_ulpevent_read_rcvinfo(event, msg); | ||
2097 | /* Check if we allow SCTP_SNDRCVINFO. */ | 2119 | /* Check if we allow SCTP_SNDRCVINFO. */ |
2098 | if (sp->subscribe.sctp_data_io_event) | 2120 | if (sp->subscribe.sctp_data_io_event) |
2099 | sctp_ulpevent_read_sndrcvinfo(event, msg); | 2121 | sctp_ulpevent_read_sndrcvinfo(event, msg); |
2122 | |||
2100 | #if 0 | 2123 | #if 0 |
2101 | /* FIXME: we should be calling IP/IPv6 layers. */ | 2124 | /* FIXME: we should be calling IP/IPv6 layers. */ |
2102 | if (sk->sk_protinfo.af_inet.cmsg_flags) | 2125 | if (sk->sk_protinfo.af_inet.cmsg_flags) |
@@ -2182,8 +2205,13 @@ static int sctp_setsockopt_events(struct sock *sk, char __user *optval, | |||
2182 | if (copy_from_user(&sctp_sk(sk)->subscribe, optval, optlen)) | 2205 | if (copy_from_user(&sctp_sk(sk)->subscribe, optval, optlen)) |
2183 | return -EFAULT; | 2206 | return -EFAULT; |
2184 | 2207 | ||
2185 | /* | 2208 | if (sctp_sk(sk)->subscribe.sctp_data_io_event) |
2186 | * At the time when a user app subscribes to SCTP_SENDER_DRY_EVENT, | 2209 | pr_warn_ratelimited(DEPRECATED "%s (pid %d) " |
2210 | "Requested SCTP_SNDRCVINFO event.\n" | ||
2211 | "Use SCTP_RCVINFO through SCTP_RECVRCVINFO option instead.\n", | ||
2212 | current->comm, task_pid_nr(current)); | ||
2213 | |||
2214 | /* At the time when a user app subscribes to SCTP_SENDER_DRY_EVENT, | ||
2187 | * if there is no data to be sent or retransmit, the stack will | 2215 | * if there is no data to be sent or retransmit, the stack will |
2188 | * immediately send up this notification. | 2216 | * immediately send up this notification. |
2189 | */ | 2217 | */ |
@@ -2747,19 +2775,22 @@ static int sctp_setsockopt_default_send_param(struct sock *sk, | |||
2747 | char __user *optval, | 2775 | char __user *optval, |
2748 | unsigned int optlen) | 2776 | unsigned int optlen) |
2749 | { | 2777 | { |
2750 | struct sctp_sndrcvinfo info; | ||
2751 | struct sctp_association *asoc; | ||
2752 | struct sctp_sock *sp = sctp_sk(sk); | 2778 | struct sctp_sock *sp = sctp_sk(sk); |
2779 | struct sctp_association *asoc; | ||
2780 | struct sctp_sndrcvinfo info; | ||
2753 | 2781 | ||
2754 | if (optlen != sizeof(struct sctp_sndrcvinfo)) | 2782 | if (optlen != sizeof(info)) |
2755 | return -EINVAL; | 2783 | return -EINVAL; |
2756 | if (copy_from_user(&info, optval, optlen)) | 2784 | if (copy_from_user(&info, optval, optlen)) |
2757 | return -EFAULT; | 2785 | return -EFAULT; |
2786 | if (info.sinfo_flags & | ||
2787 | ~(SCTP_UNORDERED | SCTP_ADDR_OVER | | ||
2788 | SCTP_ABORT | SCTP_EOF)) | ||
2789 | return -EINVAL; | ||
2758 | 2790 | ||
2759 | asoc = sctp_id2assoc(sk, info.sinfo_assoc_id); | 2791 | asoc = sctp_id2assoc(sk, info.sinfo_assoc_id); |
2760 | if (!asoc && info.sinfo_assoc_id && sctp_style(sk, UDP)) | 2792 | if (!asoc && info.sinfo_assoc_id && sctp_style(sk, UDP)) |
2761 | return -EINVAL; | 2793 | return -EINVAL; |
2762 | |||
2763 | if (asoc) { | 2794 | if (asoc) { |
2764 | asoc->default_stream = info.sinfo_stream; | 2795 | asoc->default_stream = info.sinfo_stream; |
2765 | asoc->default_flags = info.sinfo_flags; | 2796 | asoc->default_flags = info.sinfo_flags; |
@@ -2777,6 +2808,44 @@ static int sctp_setsockopt_default_send_param(struct sock *sk, | |||
2777 | return 0; | 2808 | return 0; |
2778 | } | 2809 | } |
2779 | 2810 | ||
2811 | /* RFC6458, Section 8.1.31. Set/get Default Send Parameters | ||
2812 | * (SCTP_DEFAULT_SNDINFO) | ||
2813 | */ | ||
2814 | static int sctp_setsockopt_default_sndinfo(struct sock *sk, | ||
2815 | char __user *optval, | ||
2816 | unsigned int optlen) | ||
2817 | { | ||
2818 | struct sctp_sock *sp = sctp_sk(sk); | ||
2819 | struct sctp_association *asoc; | ||
2820 | struct sctp_sndinfo info; | ||
2821 | |||
2822 | if (optlen != sizeof(info)) | ||
2823 | return -EINVAL; | ||
2824 | if (copy_from_user(&info, optval, optlen)) | ||
2825 | return -EFAULT; | ||
2826 | if (info.snd_flags & | ||
2827 | ~(SCTP_UNORDERED | SCTP_ADDR_OVER | | ||
2828 | SCTP_ABORT | SCTP_EOF)) | ||
2829 | return -EINVAL; | ||
2830 | |||
2831 | asoc = sctp_id2assoc(sk, info.snd_assoc_id); | ||
2832 | if (!asoc && info.snd_assoc_id && sctp_style(sk, UDP)) | ||
2833 | return -EINVAL; | ||
2834 | if (asoc) { | ||
2835 | asoc->default_stream = info.snd_sid; | ||
2836 | asoc->default_flags = info.snd_flags; | ||
2837 | asoc->default_ppid = info.snd_ppid; | ||
2838 | asoc->default_context = info.snd_context; | ||
2839 | } else { | ||
2840 | sp->default_stream = info.snd_sid; | ||
2841 | sp->default_flags = info.snd_flags; | ||
2842 | sp->default_ppid = info.snd_ppid; | ||
2843 | sp->default_context = info.snd_context; | ||
2844 | } | ||
2845 | |||
2846 | return 0; | ||
2847 | } | ||
2848 | |||
2780 | /* 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR) | 2849 | /* 7.1.10 Set Primary Address (SCTP_PRIMARY_ADDR) |
2781 | * | 2850 | * |
2782 | * Requests that the local SCTP stack use the enclosed peer address as | 2851 | * Requests that the local SCTP stack use the enclosed peer address as |
@@ -3523,7 +3592,6 @@ static int sctp_setsockopt_auto_asconf(struct sock *sk, char __user *optval, | |||
3523 | return 0; | 3592 | return 0; |
3524 | } | 3593 | } |
3525 | 3594 | ||
3526 | |||
3527 | /* | 3595 | /* |
3528 | * SCTP_PEER_ADDR_THLDS | 3596 | * SCTP_PEER_ADDR_THLDS |
3529 | * | 3597 | * |
@@ -3574,6 +3642,38 @@ static int sctp_setsockopt_paddr_thresholds(struct sock *sk, | |||
3574 | return 0; | 3642 | return 0; |
3575 | } | 3643 | } |
3576 | 3644 | ||
3645 | static int sctp_setsockopt_recvrcvinfo(struct sock *sk, | ||
3646 | char __user *optval, | ||
3647 | unsigned int optlen) | ||
3648 | { | ||
3649 | int val; | ||
3650 | |||
3651 | if (optlen < sizeof(int)) | ||
3652 | return -EINVAL; | ||
3653 | if (get_user(val, (int __user *) optval)) | ||
3654 | return -EFAULT; | ||
3655 | |||
3656 | sctp_sk(sk)->recvrcvinfo = (val == 0) ? 0 : 1; | ||
3657 | |||
3658 | return 0; | ||
3659 | } | ||
3660 | |||
3661 | static int sctp_setsockopt_recvnxtinfo(struct sock *sk, | ||
3662 | char __user *optval, | ||
3663 | unsigned int optlen) | ||
3664 | { | ||
3665 | int val; | ||
3666 | |||
3667 | if (optlen < sizeof(int)) | ||
3668 | return -EINVAL; | ||
3669 | if (get_user(val, (int __user *) optval)) | ||
3670 | return -EFAULT; | ||
3671 | |||
3672 | sctp_sk(sk)->recvnxtinfo = (val == 0) ? 0 : 1; | ||
3673 | |||
3674 | return 0; | ||
3675 | } | ||
3676 | |||
3577 | /* API 6.2 setsockopt(), getsockopt() | 3677 | /* API 6.2 setsockopt(), getsockopt() |
3578 | * | 3678 | * |
3579 | * Applications use setsockopt() and getsockopt() to set or retrieve | 3679 | * Applications use setsockopt() and getsockopt() to set or retrieve |
@@ -3671,6 +3771,9 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname, | |||
3671 | retval = sctp_setsockopt_default_send_param(sk, optval, | 3771 | retval = sctp_setsockopt_default_send_param(sk, optval, |
3672 | optlen); | 3772 | optlen); |
3673 | break; | 3773 | break; |
3774 | case SCTP_DEFAULT_SNDINFO: | ||
3775 | retval = sctp_setsockopt_default_sndinfo(sk, optval, optlen); | ||
3776 | break; | ||
3674 | case SCTP_PRIMARY_ADDR: | 3777 | case SCTP_PRIMARY_ADDR: |
3675 | retval = sctp_setsockopt_primary_addr(sk, optval, optlen); | 3778 | retval = sctp_setsockopt_primary_addr(sk, optval, optlen); |
3676 | break; | 3779 | break; |
@@ -3725,6 +3828,12 @@ static int sctp_setsockopt(struct sock *sk, int level, int optname, | |||
3725 | case SCTP_PEER_ADDR_THLDS: | 3828 | case SCTP_PEER_ADDR_THLDS: |
3726 | retval = sctp_setsockopt_paddr_thresholds(sk, optval, optlen); | 3829 | retval = sctp_setsockopt_paddr_thresholds(sk, optval, optlen); |
3727 | break; | 3830 | break; |
3831 | case SCTP_RECVRCVINFO: | ||
3832 | retval = sctp_setsockopt_recvrcvinfo(sk, optval, optlen); | ||
3833 | break; | ||
3834 | case SCTP_RECVNXTINFO: | ||
3835 | retval = sctp_setsockopt_recvnxtinfo(sk, optval, optlen); | ||
3836 | break; | ||
3728 | default: | 3837 | default: |
3729 | retval = -ENOPROTOOPT; | 3838 | retval = -ENOPROTOOPT; |
3730 | break; | 3839 | break; |
@@ -3971,6 +4080,9 @@ static int sctp_init_sock(struct sock *sk) | |||
3971 | /* Enable Nagle algorithm by default. */ | 4080 | /* Enable Nagle algorithm by default. */ |
3972 | sp->nodelay = 0; | 4081 | sp->nodelay = 0; |
3973 | 4082 | ||
4083 | sp->recvrcvinfo = 0; | ||
4084 | sp->recvnxtinfo = 0; | ||
4085 | |||
3974 | /* Enable by default. */ | 4086 | /* Enable by default. */ |
3975 | sp->v4mapped = 1; | 4087 | sp->v4mapped = 1; |
3976 | 4088 | ||
@@ -4131,7 +4243,7 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, | |||
4131 | transport = asoc->peer.primary_path; | 4243 | transport = asoc->peer.primary_path; |
4132 | 4244 | ||
4133 | status.sstat_assoc_id = sctp_assoc2id(asoc); | 4245 | status.sstat_assoc_id = sctp_assoc2id(asoc); |
4134 | status.sstat_state = asoc->state; | 4246 | status.sstat_state = sctp_assoc_to_state(asoc); |
4135 | status.sstat_rwnd = asoc->peer.rwnd; | 4247 | status.sstat_rwnd = asoc->peer.rwnd; |
4136 | status.sstat_unackdata = asoc->unack_data; | 4248 | status.sstat_unackdata = asoc->unack_data; |
4137 | 4249 | ||
@@ -4143,7 +4255,7 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len, | |||
4143 | memcpy(&status.sstat_primary.spinfo_address, &transport->ipaddr, | 4255 | memcpy(&status.sstat_primary.spinfo_address, &transport->ipaddr, |
4144 | transport->af_specific->sockaddr_len); | 4256 | transport->af_specific->sockaddr_len); |
4145 | /* Map ipv4 address into v4-mapped-on-v6 address. */ | 4257 | /* Map ipv4 address into v4-mapped-on-v6 address. */ |
4146 | sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), | 4258 | sctp_get_pf_specific(sk->sk_family)->addr_to_user(sctp_sk(sk), |
4147 | (union sctp_addr *)&status.sstat_primary.spinfo_address); | 4259 | (union sctp_addr *)&status.sstat_primary.spinfo_address); |
4148 | status.sstat_primary.spinfo_state = transport->state; | 4260 | status.sstat_primary.spinfo_state = transport->state; |
4149 | status.sstat_primary.spinfo_cwnd = transport->cwnd; | 4261 | status.sstat_primary.spinfo_cwnd = transport->cwnd; |
@@ -4301,8 +4413,8 @@ static int sctp_getsockopt_autoclose(struct sock *sk, int len, char __user *optv | |||
4301 | int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp) | 4413 | int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp) |
4302 | { | 4414 | { |
4303 | struct sctp_association *asoc = sctp_id2assoc(sk, id); | 4415 | struct sctp_association *asoc = sctp_id2assoc(sk, id); |
4416 | struct sctp_sock *sp = sctp_sk(sk); | ||
4304 | struct socket *sock; | 4417 | struct socket *sock; |
4305 | struct sctp_af *af; | ||
4306 | int err = 0; | 4418 | int err = 0; |
4307 | 4419 | ||
4308 | if (!asoc) | 4420 | if (!asoc) |
@@ -4324,8 +4436,7 @@ int sctp_do_peeloff(struct sock *sk, sctp_assoc_t id, struct socket **sockp) | |||
4324 | /* Make peeled-off sockets more like 1-1 accepted sockets. | 4436 | /* Make peeled-off sockets more like 1-1 accepted sockets. |
4325 | * Set the daddr and initialize id to something more random | 4437 | * Set the daddr and initialize id to something more random |
4326 | */ | 4438 | */ |
4327 | af = sctp_get_af_specific(asoc->peer.primary_addr.sa.sa_family); | 4439 | sp->pf->to_sk_daddr(&asoc->peer.primary_addr, sk); |
4328 | af->to_sk_daddr(&asoc->peer.primary_addr, sk); | ||
4329 | 4440 | ||
4330 | /* Populate the fields of the newsk from the oldsk and migrate the | 4441 | /* Populate the fields of the newsk from the oldsk and migrate the |
4331 | * asoc to the newsk. | 4442 | * asoc to the newsk. |
@@ -4709,8 +4820,8 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len, | |||
4709 | list_for_each_entry(from, &asoc->peer.transport_addr_list, | 4820 | list_for_each_entry(from, &asoc->peer.transport_addr_list, |
4710 | transports) { | 4821 | transports) { |
4711 | memcpy(&temp, &from->ipaddr, sizeof(temp)); | 4822 | memcpy(&temp, &from->ipaddr, sizeof(temp)); |
4712 | sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); | 4823 | addrlen = sctp_get_pf_specific(sk->sk_family) |
4713 | addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; | 4824 | ->addr_to_user(sp, &temp); |
4714 | if (space_left < addrlen) | 4825 | if (space_left < addrlen) |
4715 | return -ENOMEM; | 4826 | return -ENOMEM; |
4716 | if (copy_to_user(to, &temp, addrlen)) | 4827 | if (copy_to_user(to, &temp, addrlen)) |
@@ -4754,9 +4865,9 @@ static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to, | |||
4754 | if (!temp.v4.sin_port) | 4865 | if (!temp.v4.sin_port) |
4755 | temp.v4.sin_port = htons(port); | 4866 | temp.v4.sin_port = htons(port); |
4756 | 4867 | ||
4757 | sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk), | 4868 | addrlen = sctp_get_pf_specific(sk->sk_family) |
4758 | &temp); | 4869 | ->addr_to_user(sctp_sk(sk), &temp); |
4759 | addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; | 4870 | |
4760 | if (space_left < addrlen) { | 4871 | if (space_left < addrlen) { |
4761 | cnt = -ENOMEM; | 4872 | cnt = -ENOMEM; |
4762 | break; | 4873 | break; |
@@ -4844,8 +4955,8 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len, | |||
4844 | */ | 4955 | */ |
4845 | list_for_each_entry(addr, &bp->address_list, list) { | 4956 | list_for_each_entry(addr, &bp->address_list, list) { |
4846 | memcpy(&temp, &addr->a, sizeof(temp)); | 4957 | memcpy(&temp, &addr->a, sizeof(temp)); |
4847 | sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, &temp); | 4958 | addrlen = sctp_get_pf_specific(sk->sk_family) |
4848 | addrlen = sctp_get_af_specific(temp.sa.sa_family)->sockaddr_len; | 4959 | ->addr_to_user(sp, &temp); |
4849 | if (space_left < addrlen) { | 4960 | if (space_left < addrlen) { |
4850 | err = -ENOMEM; /*fixme: right error?*/ | 4961 | err = -ENOMEM; /*fixme: right error?*/ |
4851 | goto out; | 4962 | goto out; |
@@ -4904,7 +5015,7 @@ static int sctp_getsockopt_primary_addr(struct sock *sk, int len, | |||
4904 | memcpy(&prim.ssp_addr, &asoc->peer.primary_path->ipaddr, | 5015 | memcpy(&prim.ssp_addr, &asoc->peer.primary_path->ipaddr, |
4905 | asoc->peer.primary_path->af_specific->sockaddr_len); | 5016 | asoc->peer.primary_path->af_specific->sockaddr_len); |
4906 | 5017 | ||
4907 | sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp, | 5018 | sctp_get_pf_specific(sk->sk_family)->addr_to_user(sp, |
4908 | (union sctp_addr *)&prim.ssp_addr); | 5019 | (union sctp_addr *)&prim.ssp_addr); |
4909 | 5020 | ||
4910 | if (put_user(len, optlen)) | 5021 | if (put_user(len, optlen)) |
@@ -4964,14 +5075,14 @@ static int sctp_getsockopt_default_send_param(struct sock *sk, | |||
4964 | int len, char __user *optval, | 5075 | int len, char __user *optval, |
4965 | int __user *optlen) | 5076 | int __user *optlen) |
4966 | { | 5077 | { |
4967 | struct sctp_sndrcvinfo info; | ||
4968 | struct sctp_association *asoc; | ||
4969 | struct sctp_sock *sp = sctp_sk(sk); | 5078 | struct sctp_sock *sp = sctp_sk(sk); |
5079 | struct sctp_association *asoc; | ||
5080 | struct sctp_sndrcvinfo info; | ||
4970 | 5081 | ||
4971 | if (len < sizeof(struct sctp_sndrcvinfo)) | 5082 | if (len < sizeof(info)) |
4972 | return -EINVAL; | 5083 | return -EINVAL; |
4973 | 5084 | ||
4974 | len = sizeof(struct sctp_sndrcvinfo); | 5085 | len = sizeof(info); |
4975 | 5086 | ||
4976 | if (copy_from_user(&info, optval, len)) | 5087 | if (copy_from_user(&info, optval, len)) |
4977 | return -EFAULT; | 5088 | return -EFAULT; |
@@ -4979,7 +5090,6 @@ static int sctp_getsockopt_default_send_param(struct sock *sk, | |||
4979 | asoc = sctp_id2assoc(sk, info.sinfo_assoc_id); | 5090 | asoc = sctp_id2assoc(sk, info.sinfo_assoc_id); |
4980 | if (!asoc && info.sinfo_assoc_id && sctp_style(sk, UDP)) | 5091 | if (!asoc && info.sinfo_assoc_id && sctp_style(sk, UDP)) |
4981 | return -EINVAL; | 5092 | return -EINVAL; |
4982 | |||
4983 | if (asoc) { | 5093 | if (asoc) { |
4984 | info.sinfo_stream = asoc->default_stream; | 5094 | info.sinfo_stream = asoc->default_stream; |
4985 | info.sinfo_flags = asoc->default_flags; | 5095 | info.sinfo_flags = asoc->default_flags; |
@@ -5002,6 +5112,48 @@ static int sctp_getsockopt_default_send_param(struct sock *sk, | |||
5002 | return 0; | 5112 | return 0; |
5003 | } | 5113 | } |
5004 | 5114 | ||
5115 | /* RFC6458, Section 8.1.31. Set/get Default Send Parameters | ||
5116 | * (SCTP_DEFAULT_SNDINFO) | ||
5117 | */ | ||
5118 | static int sctp_getsockopt_default_sndinfo(struct sock *sk, int len, | ||
5119 | char __user *optval, | ||
5120 | int __user *optlen) | ||
5121 | { | ||
5122 | struct sctp_sock *sp = sctp_sk(sk); | ||
5123 | struct sctp_association *asoc; | ||
5124 | struct sctp_sndinfo info; | ||
5125 | |||
5126 | if (len < sizeof(info)) | ||
5127 | return -EINVAL; | ||
5128 | |||
5129 | len = sizeof(info); | ||
5130 | |||
5131 | if (copy_from_user(&info, optval, len)) | ||
5132 | return -EFAULT; | ||
5133 | |||
5134 | asoc = sctp_id2assoc(sk, info.snd_assoc_id); | ||
5135 | if (!asoc && info.snd_assoc_id && sctp_style(sk, UDP)) | ||
5136 | return -EINVAL; | ||
5137 | if (asoc) { | ||
5138 | info.snd_sid = asoc->default_stream; | ||
5139 | info.snd_flags = asoc->default_flags; | ||
5140 | info.snd_ppid = asoc->default_ppid; | ||
5141 | info.snd_context = asoc->default_context; | ||
5142 | } else { | ||
5143 | info.snd_sid = sp->default_stream; | ||
5144 | info.snd_flags = sp->default_flags; | ||
5145 | info.snd_ppid = sp->default_ppid; | ||
5146 | info.snd_context = sp->default_context; | ||
5147 | } | ||
5148 | |||
5149 | if (put_user(len, optlen)) | ||
5150 | return -EFAULT; | ||
5151 | if (copy_to_user(optval, &info, len)) | ||
5152 | return -EFAULT; | ||
5153 | |||
5154 | return 0; | ||
5155 | } | ||
5156 | |||
5005 | /* | 5157 | /* |
5006 | * | 5158 | * |
5007 | * 7.1.5 SCTP_NODELAY | 5159 | * 7.1.5 SCTP_NODELAY |
@@ -5752,6 +5904,46 @@ static int sctp_getsockopt_assoc_stats(struct sock *sk, int len, | |||
5752 | return 0; | 5904 | return 0; |
5753 | } | 5905 | } |
5754 | 5906 | ||
5907 | static int sctp_getsockopt_recvrcvinfo(struct sock *sk, int len, | ||
5908 | char __user *optval, | ||
5909 | int __user *optlen) | ||
5910 | { | ||
5911 | int val = 0; | ||
5912 | |||
5913 | if (len < sizeof(int)) | ||
5914 | return -EINVAL; | ||
5915 | |||
5916 | len = sizeof(int); | ||
5917 | if (sctp_sk(sk)->recvrcvinfo) | ||
5918 | val = 1; | ||
5919 | if (put_user(len, optlen)) | ||
5920 | return -EFAULT; | ||
5921 | if (copy_to_user(optval, &val, len)) | ||
5922 | return -EFAULT; | ||
5923 | |||
5924 | return 0; | ||
5925 | } | ||
5926 | |||
5927 | static int sctp_getsockopt_recvnxtinfo(struct sock *sk, int len, | ||
5928 | char __user *optval, | ||
5929 | int __user *optlen) | ||
5930 | { | ||
5931 | int val = 0; | ||
5932 | |||
5933 | if (len < sizeof(int)) | ||
5934 | return -EINVAL; | ||
5935 | |||
5936 | len = sizeof(int); | ||
5937 | if (sctp_sk(sk)->recvnxtinfo) | ||
5938 | val = 1; | ||
5939 | if (put_user(len, optlen)) | ||
5940 | return -EFAULT; | ||
5941 | if (copy_to_user(optval, &val, len)) | ||
5942 | return -EFAULT; | ||
5943 | |||
5944 | return 0; | ||
5945 | } | ||
5946 | |||
5755 | static int sctp_getsockopt(struct sock *sk, int level, int optname, | 5947 | static int sctp_getsockopt(struct sock *sk, int level, int optname, |
5756 | char __user *optval, int __user *optlen) | 5948 | char __user *optval, int __user *optlen) |
5757 | { | 5949 | { |
@@ -5821,6 +6013,10 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname, | |||
5821 | retval = sctp_getsockopt_default_send_param(sk, len, | 6013 | retval = sctp_getsockopt_default_send_param(sk, len, |
5822 | optval, optlen); | 6014 | optval, optlen); |
5823 | break; | 6015 | break; |
6016 | case SCTP_DEFAULT_SNDINFO: | ||
6017 | retval = sctp_getsockopt_default_sndinfo(sk, len, | ||
6018 | optval, optlen); | ||
6019 | break; | ||
5824 | case SCTP_PRIMARY_ADDR: | 6020 | case SCTP_PRIMARY_ADDR: |
5825 | retval = sctp_getsockopt_primary_addr(sk, len, optval, optlen); | 6021 | retval = sctp_getsockopt_primary_addr(sk, len, optval, optlen); |
5826 | break; | 6022 | break; |
@@ -5895,6 +6091,12 @@ static int sctp_getsockopt(struct sock *sk, int level, int optname, | |||
5895 | case SCTP_GET_ASSOC_STATS: | 6091 | case SCTP_GET_ASSOC_STATS: |
5896 | retval = sctp_getsockopt_assoc_stats(sk, len, optval, optlen); | 6092 | retval = sctp_getsockopt_assoc_stats(sk, len, optval, optlen); |
5897 | break; | 6093 | break; |
6094 | case SCTP_RECVRCVINFO: | ||
6095 | retval = sctp_getsockopt_recvrcvinfo(sk, len, optval, optlen); | ||
6096 | break; | ||
6097 | case SCTP_RECVNXTINFO: | ||
6098 | retval = sctp_getsockopt_recvnxtinfo(sk, len, optval, optlen); | ||
6099 | break; | ||
5898 | default: | 6100 | default: |
5899 | retval = -ENOPROTOOPT; | 6101 | retval = -ENOPROTOOPT; |
5900 | break; | 6102 | break; |
@@ -6390,8 +6592,7 @@ static int sctp_msghdr_parse(const struct msghdr *msg, sctp_cmsgs_t *cmsgs) | |||
6390 | struct cmsghdr *cmsg; | 6592 | struct cmsghdr *cmsg; |
6391 | struct msghdr *my_msg = (struct msghdr *)msg; | 6593 | struct msghdr *my_msg = (struct msghdr *)msg; |
6392 | 6594 | ||
6393 | for (cmsg = CMSG_FIRSTHDR(msg); | 6595 | for (cmsg = CMSG_FIRSTHDR(msg); cmsg != NULL; |
6394 | cmsg != NULL; | ||
6395 | cmsg = CMSG_NXTHDR(my_msg, cmsg)) { | 6596 | cmsg = CMSG_NXTHDR(my_msg, cmsg)) { |
6396 | if (!CMSG_OK(my_msg, cmsg)) | 6597 | if (!CMSG_OK(my_msg, cmsg)) |
6397 | return -EINVAL; | 6598 | return -EINVAL; |
@@ -6404,7 +6605,7 @@ static int sctp_msghdr_parse(const struct msghdr *msg, sctp_cmsgs_t *cmsgs) | |||
6404 | switch (cmsg->cmsg_type) { | 6605 | switch (cmsg->cmsg_type) { |
6405 | case SCTP_INIT: | 6606 | case SCTP_INIT: |
6406 | /* SCTP Socket API Extension | 6607 | /* SCTP Socket API Extension |
6407 | * 5.2.1 SCTP Initiation Structure (SCTP_INIT) | 6608 | * 5.3.1 SCTP Initiation Structure (SCTP_INIT) |
6408 | * | 6609 | * |
6409 | * This cmsghdr structure provides information for | 6610 | * This cmsghdr structure provides information for |
6410 | * initializing new SCTP associations with sendmsg(). | 6611 | * initializing new SCTP associations with sendmsg(). |
@@ -6416,15 +6617,15 @@ static int sctp_msghdr_parse(const struct msghdr *msg, sctp_cmsgs_t *cmsgs) | |||
6416 | * ------------ ------------ ---------------------- | 6617 | * ------------ ------------ ---------------------- |
6417 | * IPPROTO_SCTP SCTP_INIT struct sctp_initmsg | 6618 | * IPPROTO_SCTP SCTP_INIT struct sctp_initmsg |
6418 | */ | 6619 | */ |
6419 | if (cmsg->cmsg_len != | 6620 | if (cmsg->cmsg_len != CMSG_LEN(sizeof(struct sctp_initmsg))) |
6420 | CMSG_LEN(sizeof(struct sctp_initmsg))) | ||
6421 | return -EINVAL; | 6621 | return -EINVAL; |
6422 | cmsgs->init = (struct sctp_initmsg *)CMSG_DATA(cmsg); | 6622 | |
6623 | cmsgs->init = CMSG_DATA(cmsg); | ||
6423 | break; | 6624 | break; |
6424 | 6625 | ||
6425 | case SCTP_SNDRCV: | 6626 | case SCTP_SNDRCV: |
6426 | /* SCTP Socket API Extension | 6627 | /* SCTP Socket API Extension |
6427 | * 5.2.2 SCTP Header Information Structure(SCTP_SNDRCV) | 6628 | * 5.3.2 SCTP Header Information Structure(SCTP_SNDRCV) |
6428 | * | 6629 | * |
6429 | * This cmsghdr structure specifies SCTP options for | 6630 | * This cmsghdr structure specifies SCTP options for |
6430 | * sendmsg() and describes SCTP header information | 6631 | * sendmsg() and describes SCTP header information |
@@ -6434,24 +6635,44 @@ static int sctp_msghdr_parse(const struct msghdr *msg, sctp_cmsgs_t *cmsgs) | |||
6434 | * ------------ ------------ ---------------------- | 6635 | * ------------ ------------ ---------------------- |
6435 | * IPPROTO_SCTP SCTP_SNDRCV struct sctp_sndrcvinfo | 6636 | * IPPROTO_SCTP SCTP_SNDRCV struct sctp_sndrcvinfo |
6436 | */ | 6637 | */ |
6437 | if (cmsg->cmsg_len != | 6638 | if (cmsg->cmsg_len != CMSG_LEN(sizeof(struct sctp_sndrcvinfo))) |
6438 | CMSG_LEN(sizeof(struct sctp_sndrcvinfo))) | ||
6439 | return -EINVAL; | 6639 | return -EINVAL; |
6440 | 6640 | ||
6441 | cmsgs->info = | 6641 | cmsgs->srinfo = CMSG_DATA(cmsg); |
6442 | (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg); | ||
6443 | 6642 | ||
6444 | /* Minimally, validate the sinfo_flags. */ | 6643 | if (cmsgs->srinfo->sinfo_flags & |
6445 | if (cmsgs->info->sinfo_flags & | ||
6446 | ~(SCTP_UNORDERED | SCTP_ADDR_OVER | | 6644 | ~(SCTP_UNORDERED | SCTP_ADDR_OVER | |
6447 | SCTP_ABORT | SCTP_EOF)) | 6645 | SCTP_ABORT | SCTP_EOF)) |
6448 | return -EINVAL; | 6646 | return -EINVAL; |
6449 | break; | 6647 | break; |
6450 | 6648 | ||
6649 | case SCTP_SNDINFO: | ||
6650 | /* SCTP Socket API Extension | ||
6651 | * 5.3.4 SCTP Send Information Structure (SCTP_SNDINFO) | ||
6652 | * | ||
6653 | * This cmsghdr structure specifies SCTP options for | ||
6654 | * sendmsg(). This structure and SCTP_RCVINFO replaces | ||
6655 | * SCTP_SNDRCV which has been deprecated. | ||
6656 | * | ||
6657 | * cmsg_level cmsg_type cmsg_data[] | ||
6658 | * ------------ ------------ --------------------- | ||
6659 | * IPPROTO_SCTP SCTP_SNDINFO struct sctp_sndinfo | ||
6660 | */ | ||
6661 | if (cmsg->cmsg_len != CMSG_LEN(sizeof(struct sctp_sndinfo))) | ||
6662 | return -EINVAL; | ||
6663 | |||
6664 | cmsgs->sinfo = CMSG_DATA(cmsg); | ||
6665 | |||
6666 | if (cmsgs->sinfo->snd_flags & | ||
6667 | ~(SCTP_UNORDERED | SCTP_ADDR_OVER | | ||
6668 | SCTP_ABORT | SCTP_EOF)) | ||
6669 | return -EINVAL; | ||
6670 | break; | ||
6451 | default: | 6671 | default: |
6452 | return -EINVAL; | 6672 | return -EINVAL; |
6453 | } | 6673 | } |
6454 | } | 6674 | } |
6675 | |||
6455 | return 0; | 6676 | return 0; |
6456 | } | 6677 | } |
6457 | 6678 | ||
@@ -6518,8 +6739,8 @@ out: | |||
6518 | * Note: This is pretty much the same routine as in core/datagram.c | 6739 | * Note: This is pretty much the same routine as in core/datagram.c |
6519 | * with a few changes to make lksctp work. | 6740 | * with a few changes to make lksctp work. |
6520 | */ | 6741 | */ |
6521 | static struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags, | 6742 | struct sk_buff *sctp_skb_recv_datagram(struct sock *sk, int flags, |
6522 | int noblock, int *err) | 6743 | int noblock, int *err) |
6523 | { | 6744 | { |
6524 | int error; | 6745 | int error; |
6525 | struct sk_buff *skb; | 6746 | struct sk_buff *skb; |
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c index 12c7e01c2677..2e9ada10fd84 100644 --- a/net/sctp/sysctl.c +++ b/net/sctp/sysctl.c | |||
@@ -424,8 +424,9 @@ static int proc_sctp_do_alpha_beta(struct ctl_table *ctl, int write, | |||
424 | void __user *buffer, size_t *lenp, | 424 | void __user *buffer, size_t *lenp, |
425 | loff_t *ppos) | 425 | loff_t *ppos) |
426 | { | 426 | { |
427 | pr_warn_once("Changing rto_alpha or rto_beta may lead to " | 427 | if (write) |
428 | "suboptimal rtt/srtt estimations!\n"); | 428 | pr_warn_once("Changing rto_alpha or rto_beta may lead to " |
429 | "suboptimal rtt/srtt estimations!\n"); | ||
429 | 430 | ||
430 | return proc_dointvec_minmax(ctl, write, buffer, lenp, ppos); | 431 | return proc_dointvec_minmax(ctl, write, buffer, lenp, ppos); |
431 | } | 432 | } |
diff --git a/net/sctp/transport.c b/net/sctp/transport.c index 7dd672fa651f..a0a431824f63 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c | |||
@@ -289,8 +289,8 @@ void sctp_transport_route(struct sctp_transport *transport, | |||
289 | */ | 289 | */ |
290 | if (asoc && (!asoc->peer.primary_path || | 290 | if (asoc && (!asoc->peer.primary_path || |
291 | (transport == asoc->peer.active_path))) | 291 | (transport == asoc->peer.active_path))) |
292 | opt->pf->af->to_sk_saddr(&transport->saddr, | 292 | opt->pf->to_sk_saddr(&transport->saddr, |
293 | asoc->base.sk); | 293 | asoc->base.sk); |
294 | } else | 294 | } else |
295 | transport->pathmtu = SCTP_DEFAULT_MAXSEGMENT; | 295 | transport->pathmtu = SCTP_DEFAULT_MAXSEGMENT; |
296 | } | 296 | } |
@@ -594,15 +594,16 @@ void sctp_transport_burst_reset(struct sctp_transport *t) | |||
594 | } | 594 | } |
595 | 595 | ||
596 | /* What is the next timeout value for this transport? */ | 596 | /* What is the next timeout value for this transport? */ |
597 | unsigned long sctp_transport_timeout(struct sctp_transport *t) | 597 | unsigned long sctp_transport_timeout(struct sctp_transport *trans) |
598 | { | 598 | { |
599 | unsigned long timeout; | 599 | /* RTO + timer slack +/- 50% of RTO */ |
600 | timeout = t->rto + sctp_jitter(t->rto); | 600 | unsigned long timeout = (trans->rto >> 1) + prandom_u32_max(trans->rto); |
601 | if ((t->state != SCTP_UNCONFIRMED) && | 601 | |
602 | (t->state != SCTP_PF)) | 602 | if (trans->state != SCTP_UNCONFIRMED && |
603 | timeout += t->hbinterval; | 603 | trans->state != SCTP_PF) |
604 | timeout += jiffies; | 604 | timeout += trans->hbinterval; |
605 | return timeout; | 605 | |
606 | return timeout + jiffies; | ||
606 | } | 607 | } |
607 | 608 | ||
608 | /* Reset transport variables to their initial values */ | 609 | /* Reset transport variables to their initial values */ |
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index b6842fdb53d4..d1e38308f615 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c | |||
@@ -341,7 +341,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change( | |||
341 | memcpy(&spc->spc_aaddr, aaddr, sizeof(struct sockaddr_storage)); | 341 | memcpy(&spc->spc_aaddr, aaddr, sizeof(struct sockaddr_storage)); |
342 | 342 | ||
343 | /* Map ipv4 address into v4-mapped-on-v6 address. */ | 343 | /* Map ipv4 address into v4-mapped-on-v6 address. */ |
344 | sctp_get_pf_specific(asoc->base.sk->sk_family)->addr_v4map( | 344 | sctp_get_pf_specific(asoc->base.sk->sk_family)->addr_to_user( |
345 | sctp_sk(asoc->base.sk), | 345 | sctp_sk(asoc->base.sk), |
346 | (union sctp_addr *)&spc->spc_aaddr); | 346 | (union sctp_addr *)&spc->spc_aaddr); |
347 | 347 | ||
@@ -886,6 +886,69 @@ void sctp_ulpevent_read_sndrcvinfo(const struct sctp_ulpevent *event, | |||
886 | sizeof(sinfo), &sinfo); | 886 | sizeof(sinfo), &sinfo); |
887 | } | 887 | } |
888 | 888 | ||
889 | /* RFC6458, Section 5.3.5 SCTP Receive Information Structure | ||
890 | * (SCTP_SNDRCV) | ||
891 | */ | ||
892 | void sctp_ulpevent_read_rcvinfo(const struct sctp_ulpevent *event, | ||
893 | struct msghdr *msghdr) | ||
894 | { | ||
895 | struct sctp_rcvinfo rinfo; | ||
896 | |||
897 | if (sctp_ulpevent_is_notification(event)) | ||
898 | return; | ||
899 | |||
900 | memset(&rinfo, 0, sizeof(struct sctp_rcvinfo)); | ||
901 | rinfo.rcv_sid = event->stream; | ||
902 | rinfo.rcv_ssn = event->ssn; | ||
903 | rinfo.rcv_ppid = event->ppid; | ||
904 | rinfo.rcv_flags = event->flags; | ||
905 | rinfo.rcv_tsn = event->tsn; | ||
906 | rinfo.rcv_cumtsn = event->cumtsn; | ||
907 | rinfo.rcv_assoc_id = sctp_assoc2id(event->asoc); | ||
908 | rinfo.rcv_context = event->asoc->default_rcv_context; | ||
909 | |||
910 | put_cmsg(msghdr, IPPROTO_SCTP, SCTP_RCVINFO, | ||
911 | sizeof(rinfo), &rinfo); | ||
912 | } | ||
913 | |||
914 | /* RFC6458, Section 5.3.6. SCTP Next Receive Information Structure | ||
915 | * (SCTP_NXTINFO) | ||
916 | */ | ||
917 | static void __sctp_ulpevent_read_nxtinfo(const struct sctp_ulpevent *event, | ||
918 | struct msghdr *msghdr, | ||
919 | const struct sk_buff *skb) | ||
920 | { | ||
921 | struct sctp_nxtinfo nxtinfo; | ||
922 | |||
923 | memset(&nxtinfo, 0, sizeof(nxtinfo)); | ||
924 | nxtinfo.nxt_sid = event->stream; | ||
925 | nxtinfo.nxt_ppid = event->ppid; | ||
926 | nxtinfo.nxt_flags = event->flags; | ||
927 | if (sctp_ulpevent_is_notification(event)) | ||
928 | nxtinfo.nxt_flags |= SCTP_NOTIFICATION; | ||
929 | nxtinfo.nxt_length = skb->len; | ||
930 | nxtinfo.nxt_assoc_id = sctp_assoc2id(event->asoc); | ||
931 | |||
932 | put_cmsg(msghdr, IPPROTO_SCTP, SCTP_NXTINFO, | ||
933 | sizeof(nxtinfo), &nxtinfo); | ||
934 | } | ||
935 | |||
936 | void sctp_ulpevent_read_nxtinfo(const struct sctp_ulpevent *event, | ||
937 | struct msghdr *msghdr, | ||
938 | struct sock *sk) | ||
939 | { | ||
940 | struct sk_buff *skb; | ||
941 | int err; | ||
942 | |||
943 | skb = sctp_skb_recv_datagram(sk, MSG_PEEK, 1, &err); | ||
944 | if (skb != NULL) { | ||
945 | __sctp_ulpevent_read_nxtinfo(sctp_skb2event(skb), | ||
946 | msghdr, skb); | ||
947 | /* Just release refcount here. */ | ||
948 | kfree_skb(skb); | ||
949 | } | ||
950 | } | ||
951 | |||
889 | /* Do accounting for bytes received and hold a reference to the association | 952 | /* Do accounting for bytes received and hold a reference to the association |
890 | * for each skb. | 953 | * for each skb. |
891 | */ | 954 | */ |
diff --git a/net/socket.c b/net/socket.c index abf56b2a14f9..4cdbc107606f 100644 --- a/net/socket.c +++ b/net/socket.c | |||
@@ -106,6 +106,7 @@ | |||
106 | #include <linux/sockios.h> | 106 | #include <linux/sockios.h> |
107 | #include <linux/atalk.h> | 107 | #include <linux/atalk.h> |
108 | #include <net/busy_poll.h> | 108 | #include <net/busy_poll.h> |
109 | #include <linux/errqueue.h> | ||
109 | 110 | ||
110 | #ifdef CONFIG_NET_RX_BUSY_POLL | 111 | #ifdef CONFIG_NET_RX_BUSY_POLL |
111 | unsigned int sysctl_net_busy_read __read_mostly; | 112 | unsigned int sysctl_net_busy_read __read_mostly; |
@@ -609,15 +610,26 @@ void sock_release(struct socket *sock) | |||
609 | } | 610 | } |
610 | EXPORT_SYMBOL(sock_release); | 611 | EXPORT_SYMBOL(sock_release); |
611 | 612 | ||
612 | void sock_tx_timestamp(struct sock *sk, __u8 *tx_flags) | 613 | void sock_tx_timestamp(const struct sock *sk, __u8 *tx_flags) |
613 | { | 614 | { |
614 | *tx_flags = 0; | 615 | u8 flags = *tx_flags; |
615 | if (sock_flag(sk, SOCK_TIMESTAMPING_TX_HARDWARE)) | 616 | |
616 | *tx_flags |= SKBTX_HW_TSTAMP; | 617 | if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_HARDWARE) |
617 | if (sock_flag(sk, SOCK_TIMESTAMPING_TX_SOFTWARE)) | 618 | flags |= SKBTX_HW_TSTAMP; |
618 | *tx_flags |= SKBTX_SW_TSTAMP; | 619 | |
620 | if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_SOFTWARE) | ||
621 | flags |= SKBTX_SW_TSTAMP; | ||
622 | |||
623 | if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_SCHED) | ||
624 | flags |= SKBTX_SCHED_TSTAMP; | ||
625 | |||
626 | if (sk->sk_tsflags & SOF_TIMESTAMPING_TX_ACK) | ||
627 | flags |= SKBTX_ACK_TSTAMP; | ||
628 | |||
619 | if (sock_flag(sk, SOCK_WIFI_STATUS)) | 629 | if (sock_flag(sk, SOCK_WIFI_STATUS)) |
620 | *tx_flags |= SKBTX_WIFI_STATUS; | 630 | flags |= SKBTX_WIFI_STATUS; |
631 | |||
632 | *tx_flags = flags; | ||
621 | } | 633 | } |
622 | EXPORT_SYMBOL(sock_tx_timestamp); | 634 | EXPORT_SYMBOL(sock_tx_timestamp); |
623 | 635 | ||
@@ -697,7 +709,7 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, | |||
697 | struct sk_buff *skb) | 709 | struct sk_buff *skb) |
698 | { | 710 | { |
699 | int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP); | 711 | int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP); |
700 | struct timespec ts[3]; | 712 | struct scm_timestamping tss; |
701 | int empty = 1; | 713 | int empty = 1; |
702 | struct skb_shared_hwtstamps *shhwtstamps = | 714 | struct skb_shared_hwtstamps *shhwtstamps = |
703 | skb_hwtstamps(skb); | 715 | skb_hwtstamps(skb); |
@@ -714,28 +726,24 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk, | |||
714 | put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP, | 726 | put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMP, |
715 | sizeof(tv), &tv); | 727 | sizeof(tv), &tv); |
716 | } else { | 728 | } else { |
717 | skb_get_timestampns(skb, &ts[0]); | 729 | struct timespec ts; |
730 | skb_get_timestampns(skb, &ts); | ||
718 | put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS, | 731 | put_cmsg(msg, SOL_SOCKET, SCM_TIMESTAMPNS, |
719 | sizeof(ts[0]), &ts[0]); | 732 | sizeof(ts), &ts); |
720 | } | 733 | } |
721 | } | 734 | } |
722 | 735 | ||
723 | 736 | memset(&tss, 0, sizeof(tss)); | |
724 | memset(ts, 0, sizeof(ts)); | 737 | if ((sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE) && |
725 | if (sock_flag(sk, SOCK_TIMESTAMPING_SOFTWARE) && | 738 | ktime_to_timespec_cond(skb->tstamp, tss.ts + 0)) |
726 | ktime_to_timespec_cond(skb->tstamp, ts + 0)) | 739 | empty = 0; |
740 | if (shhwtstamps && | ||
741 | (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) && | ||
742 | ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2)) | ||
727 | empty = 0; | 743 | empty = 0; |
728 | if (shhwtstamps) { | ||
729 | if (sock_flag(sk, SOCK_TIMESTAMPING_SYS_HARDWARE) && | ||
730 | ktime_to_timespec_cond(shhwtstamps->syststamp, ts + 1)) | ||
731 | empty = 0; | ||
732 | if (sock_flag(sk, SOCK_TIMESTAMPING_RAW_HARDWARE) && | ||
733 | ktime_to_timespec_cond(shhwtstamps->hwtstamp, ts + 2)) | ||
734 | empty = 0; | ||
735 | } | ||
736 | if (!empty) | 744 | if (!empty) |
737 | put_cmsg(msg, SOL_SOCKET, | 745 | put_cmsg(msg, SOL_SOCKET, |
738 | SCM_TIMESTAMPING, sizeof(ts), &ts); | 746 | SCM_TIMESTAMPING, sizeof(tss), &tss); |
739 | } | 747 | } |
740 | EXPORT_SYMBOL_GPL(__sock_recv_timestamp); | 748 | EXPORT_SYMBOL_GPL(__sock_recv_timestamp); |
741 | 749 | ||
@@ -1988,6 +1996,9 @@ static int copy_msghdr_from_user(struct msghdr *kmsg, | |||
1988 | if (copy_from_user(kmsg, umsg, sizeof(struct msghdr))) | 1996 | if (copy_from_user(kmsg, umsg, sizeof(struct msghdr))) |
1989 | return -EFAULT; | 1997 | return -EFAULT; |
1990 | 1998 | ||
1999 | if (kmsg->msg_name == NULL) | ||
2000 | kmsg->msg_namelen = 0; | ||
2001 | |||
1991 | if (kmsg->msg_namelen < 0) | 2002 | if (kmsg->msg_namelen < 0) |
1992 | return -EINVAL; | 2003 | return -EINVAL; |
1993 | 2004 | ||
@@ -2593,7 +2604,7 @@ SYSCALL_DEFINE2(socketcall, int, call, unsigned long __user *, args) | |||
2593 | * | 2604 | * |
2594 | * This function is called by a protocol handler that wants to | 2605 | * This function is called by a protocol handler that wants to |
2595 | * advertise its address family, and have it linked into the | 2606 | * advertise its address family, and have it linked into the |
2596 | * socket interface. The value ops->family coresponds to the | 2607 | * socket interface. The value ops->family corresponds to the |
2597 | * socket system call protocol family. | 2608 | * socket system call protocol family. |
2598 | */ | 2609 | */ |
2599 | int sock_register(const struct net_proto_family *ops) | 2610 | int sock_register(const struct net_proto_family *ops) |
diff --git a/net/sunrpc/addr.c b/net/sunrpc/addr.c index a622ad64acd8..2e0a6f92e563 100644 --- a/net/sunrpc/addr.c +++ b/net/sunrpc/addr.c | |||
@@ -176,7 +176,7 @@ static int rpc_parse_scope_id(struct net *net, const char *buf, | |||
176 | len = (buf + buflen) - delim - 1; | 176 | len = (buf + buflen) - delim - 1; |
177 | p = kstrndup(delim + 1, len, GFP_KERNEL); | 177 | p = kstrndup(delim + 1, len, GFP_KERNEL); |
178 | if (p) { | 178 | if (p) { |
179 | unsigned long scope_id = 0; | 179 | u32 scope_id = 0; |
180 | struct net_device *dev; | 180 | struct net_device *dev; |
181 | 181 | ||
182 | dev = dev_get_by_name(net, p); | 182 | dev = dev_get_by_name(net, p); |
@@ -184,7 +184,7 @@ static int rpc_parse_scope_id(struct net *net, const char *buf, | |||
184 | scope_id = dev->ifindex; | 184 | scope_id = dev->ifindex; |
185 | dev_put(dev); | 185 | dev_put(dev); |
186 | } else { | 186 | } else { |
187 | if (strict_strtoul(p, 10, &scope_id) == 0) { | 187 | if (kstrtou32(p, 10, &scope_id) == 0) { |
188 | kfree(p); | 188 | kfree(p); |
189 | return 0; | 189 | return 0; |
190 | } | 190 | } |
@@ -304,7 +304,7 @@ char *rpc_sockaddr2uaddr(const struct sockaddr *sap, gfp_t gfp_flags) | |||
304 | * @sap: buffer into which to plant socket address | 304 | * @sap: buffer into which to plant socket address |
305 | * @salen: size of buffer | 305 | * @salen: size of buffer |
306 | * | 306 | * |
307 | * @uaddr does not have to be '\0'-terminated, but strict_strtoul() and | 307 | * @uaddr does not have to be '\0'-terminated, but kstrtou8() and |
308 | * rpc_pton() require proper string termination to be successful. | 308 | * rpc_pton() require proper string termination to be successful. |
309 | * | 309 | * |
310 | * Returns the size of the socket address if successful; otherwise | 310 | * Returns the size of the socket address if successful; otherwise |
@@ -315,7 +315,7 @@ size_t rpc_uaddr2sockaddr(struct net *net, const char *uaddr, | |||
315 | const size_t salen) | 315 | const size_t salen) |
316 | { | 316 | { |
317 | char *c, buf[RPCBIND_MAXUADDRLEN + sizeof('\0')]; | 317 | char *c, buf[RPCBIND_MAXUADDRLEN + sizeof('\0')]; |
318 | unsigned long portlo, porthi; | 318 | u8 portlo, porthi; |
319 | unsigned short port; | 319 | unsigned short port; |
320 | 320 | ||
321 | if (uaddr_len > RPCBIND_MAXUADDRLEN) | 321 | if (uaddr_len > RPCBIND_MAXUADDRLEN) |
@@ -327,18 +327,14 @@ size_t rpc_uaddr2sockaddr(struct net *net, const char *uaddr, | |||
327 | c = strrchr(buf, '.'); | 327 | c = strrchr(buf, '.'); |
328 | if (unlikely(c == NULL)) | 328 | if (unlikely(c == NULL)) |
329 | return 0; | 329 | return 0; |
330 | if (unlikely(strict_strtoul(c + 1, 10, &portlo) != 0)) | 330 | if (unlikely(kstrtou8(c + 1, 10, &portlo) != 0)) |
331 | return 0; | ||
332 | if (unlikely(portlo > 255)) | ||
333 | return 0; | 331 | return 0; |
334 | 332 | ||
335 | *c = '\0'; | 333 | *c = '\0'; |
336 | c = strrchr(buf, '.'); | 334 | c = strrchr(buf, '.'); |
337 | if (unlikely(c == NULL)) | 335 | if (unlikely(c == NULL)) |
338 | return 0; | 336 | return 0; |
339 | if (unlikely(strict_strtoul(c + 1, 10, &porthi) != 0)) | 337 | if (unlikely(kstrtou8(c + 1, 10, &porthi) != 0)) |
340 | return 0; | ||
341 | if (unlikely(porthi > 255)) | ||
342 | return 0; | 338 | return 0; |
343 | 339 | ||
344 | port = (unsigned short)((porthi << 8) | portlo); | 340 | port = (unsigned short)((porthi << 8) | portlo); |
diff --git a/net/sunrpc/auth.c b/net/sunrpc/auth.c index f77366717420..383eb919ac0b 100644 --- a/net/sunrpc/auth.c +++ b/net/sunrpc/auth.c | |||
@@ -48,7 +48,7 @@ static int param_set_hashtbl_sz(const char *val, const struct kernel_param *kp) | |||
48 | 48 | ||
49 | if (!val) | 49 | if (!val) |
50 | goto out_inval; | 50 | goto out_inval; |
51 | ret = strict_strtoul(val, 0, &num); | 51 | ret = kstrtoul(val, 0, &num); |
52 | if (ret == -EINVAL) | 52 | if (ret == -EINVAL) |
53 | goto out_inval; | 53 | goto out_inval; |
54 | nbits = fls(num); | 54 | nbits = fls(num); |
@@ -80,6 +80,10 @@ static struct kernel_param_ops param_ops_hashtbl_sz = { | |||
80 | module_param_named(auth_hashtable_size, auth_hashbits, hashtbl_sz, 0644); | 80 | module_param_named(auth_hashtable_size, auth_hashbits, hashtbl_sz, 0644); |
81 | MODULE_PARM_DESC(auth_hashtable_size, "RPC credential cache hashtable size"); | 81 | MODULE_PARM_DESC(auth_hashtable_size, "RPC credential cache hashtable size"); |
82 | 82 | ||
83 | static unsigned long auth_max_cred_cachesize = ULONG_MAX; | ||
84 | module_param(auth_max_cred_cachesize, ulong, 0644); | ||
85 | MODULE_PARM_DESC(auth_max_cred_cachesize, "RPC credential maximum total cache size"); | ||
86 | |||
83 | static u32 | 87 | static u32 |
84 | pseudoflavor_to_flavor(u32 flavor) { | 88 | pseudoflavor_to_flavor(u32 flavor) { |
85 | if (flavor > RPC_AUTH_MAXFLAVOR) | 89 | if (flavor > RPC_AUTH_MAXFLAVOR) |
@@ -363,6 +367,15 @@ rpcauth_cred_key_to_expire(struct rpc_cred *cred) | |||
363 | } | 367 | } |
364 | EXPORT_SYMBOL_GPL(rpcauth_cred_key_to_expire); | 368 | EXPORT_SYMBOL_GPL(rpcauth_cred_key_to_expire); |
365 | 369 | ||
370 | char * | ||
371 | rpcauth_stringify_acceptor(struct rpc_cred *cred) | ||
372 | { | ||
373 | if (!cred->cr_ops->crstringify_acceptor) | ||
374 | return NULL; | ||
375 | return cred->cr_ops->crstringify_acceptor(cred); | ||
376 | } | ||
377 | EXPORT_SYMBOL_GPL(rpcauth_stringify_acceptor); | ||
378 | |||
366 | /* | 379 | /* |
367 | * Destroy a list of credentials | 380 | * Destroy a list of credentials |
368 | */ | 381 | */ |
@@ -472,6 +485,20 @@ rpcauth_prune_expired(struct list_head *free, int nr_to_scan) | |||
472 | return freed; | 485 | return freed; |
473 | } | 486 | } |
474 | 487 | ||
488 | static unsigned long | ||
489 | rpcauth_cache_do_shrink(int nr_to_scan) | ||
490 | { | ||
491 | LIST_HEAD(free); | ||
492 | unsigned long freed; | ||
493 | |||
494 | spin_lock(&rpc_credcache_lock); | ||
495 | freed = rpcauth_prune_expired(&free, nr_to_scan); | ||
496 | spin_unlock(&rpc_credcache_lock); | ||
497 | rpcauth_destroy_credlist(&free); | ||
498 | |||
499 | return freed; | ||
500 | } | ||
501 | |||
475 | /* | 502 | /* |
476 | * Run memory cache shrinker. | 503 | * Run memory cache shrinker. |
477 | */ | 504 | */ |
@@ -479,9 +506,6 @@ static unsigned long | |||
479 | rpcauth_cache_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) | 506 | rpcauth_cache_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) |
480 | 507 | ||
481 | { | 508 | { |
482 | LIST_HEAD(free); | ||
483 | unsigned long freed; | ||
484 | |||
485 | if ((sc->gfp_mask & GFP_KERNEL) != GFP_KERNEL) | 509 | if ((sc->gfp_mask & GFP_KERNEL) != GFP_KERNEL) |
486 | return SHRINK_STOP; | 510 | return SHRINK_STOP; |
487 | 511 | ||
@@ -489,12 +513,7 @@ rpcauth_cache_shrink_scan(struct shrinker *shrink, struct shrink_control *sc) | |||
489 | if (list_empty(&cred_unused)) | 513 | if (list_empty(&cred_unused)) |
490 | return SHRINK_STOP; | 514 | return SHRINK_STOP; |
491 | 515 | ||
492 | spin_lock(&rpc_credcache_lock); | 516 | return rpcauth_cache_do_shrink(sc->nr_to_scan); |
493 | freed = rpcauth_prune_expired(&free, sc->nr_to_scan); | ||
494 | spin_unlock(&rpc_credcache_lock); | ||
495 | rpcauth_destroy_credlist(&free); | ||
496 | |||
497 | return freed; | ||
498 | } | 517 | } |
499 | 518 | ||
500 | static unsigned long | 519 | static unsigned long |
@@ -504,6 +523,21 @@ rpcauth_cache_shrink_count(struct shrinker *shrink, struct shrink_control *sc) | |||
504 | return (number_cred_unused / 100) * sysctl_vfs_cache_pressure; | 523 | return (number_cred_unused / 100) * sysctl_vfs_cache_pressure; |
505 | } | 524 | } |
506 | 525 | ||
526 | static void | ||
527 | rpcauth_cache_enforce_limit(void) | ||
528 | { | ||
529 | unsigned long diff; | ||
530 | unsigned int nr_to_scan; | ||
531 | |||
532 | if (number_cred_unused <= auth_max_cred_cachesize) | ||
533 | return; | ||
534 | diff = number_cred_unused - auth_max_cred_cachesize; | ||
535 | nr_to_scan = 100; | ||
536 | if (diff < nr_to_scan) | ||
537 | nr_to_scan = diff; | ||
538 | rpcauth_cache_do_shrink(nr_to_scan); | ||
539 | } | ||
540 | |||
507 | /* | 541 | /* |
508 | * Look up a process' credentials in the authentication cache | 542 | * Look up a process' credentials in the authentication cache |
509 | */ | 543 | */ |
@@ -523,6 +557,12 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred, | |||
523 | hlist_for_each_entry_rcu(entry, &cache->hashtable[nr], cr_hash) { | 557 | hlist_for_each_entry_rcu(entry, &cache->hashtable[nr], cr_hash) { |
524 | if (!entry->cr_ops->crmatch(acred, entry, flags)) | 558 | if (!entry->cr_ops->crmatch(acred, entry, flags)) |
525 | continue; | 559 | continue; |
560 | if (flags & RPCAUTH_LOOKUP_RCU) { | ||
561 | if (test_bit(RPCAUTH_CRED_HASHED, &entry->cr_flags) && | ||
562 | !test_bit(RPCAUTH_CRED_NEW, &entry->cr_flags)) | ||
563 | cred = entry; | ||
564 | break; | ||
565 | } | ||
526 | spin_lock(&cache->lock); | 566 | spin_lock(&cache->lock); |
527 | if (test_bit(RPCAUTH_CRED_HASHED, &entry->cr_flags) == 0) { | 567 | if (test_bit(RPCAUTH_CRED_HASHED, &entry->cr_flags) == 0) { |
528 | spin_unlock(&cache->lock); | 568 | spin_unlock(&cache->lock); |
@@ -537,6 +577,9 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred, | |||
537 | if (cred != NULL) | 577 | if (cred != NULL) |
538 | goto found; | 578 | goto found; |
539 | 579 | ||
580 | if (flags & RPCAUTH_LOOKUP_RCU) | ||
581 | return ERR_PTR(-ECHILD); | ||
582 | |||
540 | new = auth->au_ops->crcreate(auth, acred, flags); | 583 | new = auth->au_ops->crcreate(auth, acred, flags); |
541 | if (IS_ERR(new)) { | 584 | if (IS_ERR(new)) { |
542 | cred = new; | 585 | cred = new; |
@@ -557,6 +600,7 @@ rpcauth_lookup_credcache(struct rpc_auth *auth, struct auth_cred * acred, | |||
557 | } else | 600 | } else |
558 | list_add_tail(&new->cr_lru, &free); | 601 | list_add_tail(&new->cr_lru, &free); |
559 | spin_unlock(&cache->lock); | 602 | spin_unlock(&cache->lock); |
603 | rpcauth_cache_enforce_limit(); | ||
560 | found: | 604 | found: |
561 | if (test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags) && | 605 | if (test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags) && |
562 | cred->cr_ops->cr_init != NULL && | 606 | cred->cr_ops->cr_init != NULL && |
@@ -586,10 +630,8 @@ rpcauth_lookupcred(struct rpc_auth *auth, int flags) | |||
586 | memset(&acred, 0, sizeof(acred)); | 630 | memset(&acred, 0, sizeof(acred)); |
587 | acred.uid = cred->fsuid; | 631 | acred.uid = cred->fsuid; |
588 | acred.gid = cred->fsgid; | 632 | acred.gid = cred->fsgid; |
589 | acred.group_info = get_group_info(((struct cred *)cred)->group_info); | 633 | acred.group_info = cred->group_info; |
590 | |||
591 | ret = auth->au_ops->lookup_cred(auth, &acred, flags); | 634 | ret = auth->au_ops->lookup_cred(auth, &acred, flags); |
592 | put_group_info(acred.group_info); | ||
593 | return ret; | 635 | return ret; |
594 | } | 636 | } |
595 | EXPORT_SYMBOL_GPL(rpcauth_lookupcred); | 637 | EXPORT_SYMBOL_GPL(rpcauth_lookupcred); |
diff --git a/net/sunrpc/auth_generic.c b/net/sunrpc/auth_generic.c index ed04869b2d4f..6f6b829c9e8e 100644 --- a/net/sunrpc/auth_generic.c +++ b/net/sunrpc/auth_generic.c | |||
@@ -38,6 +38,12 @@ struct rpc_cred *rpc_lookup_cred(void) | |||
38 | } | 38 | } |
39 | EXPORT_SYMBOL_GPL(rpc_lookup_cred); | 39 | EXPORT_SYMBOL_GPL(rpc_lookup_cred); |
40 | 40 | ||
41 | struct rpc_cred *rpc_lookup_cred_nonblock(void) | ||
42 | { | ||
43 | return rpcauth_lookupcred(&generic_auth, RPCAUTH_LOOKUP_RCU); | ||
44 | } | ||
45 | EXPORT_SYMBOL_GPL(rpc_lookup_cred_nonblock); | ||
46 | |||
41 | /* | 47 | /* |
42 | * Public call interface for looking up machine creds. | 48 | * Public call interface for looking up machine creds. |
43 | */ | 49 | */ |
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c index b6e440baccc3..afb292cd797d 100644 --- a/net/sunrpc/auth_gss/auth_gss.c +++ b/net/sunrpc/auth_gss/auth_gss.c | |||
@@ -183,8 +183,9 @@ gss_cred_get_ctx(struct rpc_cred *cred) | |||
183 | struct gss_cl_ctx *ctx = NULL; | 183 | struct gss_cl_ctx *ctx = NULL; |
184 | 184 | ||
185 | rcu_read_lock(); | 185 | rcu_read_lock(); |
186 | if (gss_cred->gc_ctx) | 186 | ctx = rcu_dereference(gss_cred->gc_ctx); |
187 | ctx = gss_get_ctx(gss_cred->gc_ctx); | 187 | if (ctx) |
188 | gss_get_ctx(ctx); | ||
188 | rcu_read_unlock(); | 189 | rcu_read_unlock(); |
189 | return ctx; | 190 | return ctx; |
190 | } | 191 | } |
@@ -262,9 +263,22 @@ gss_fill_context(const void *p, const void *end, struct gss_cl_ctx *ctx, struct | |||
262 | p = ERR_PTR(ret); | 263 | p = ERR_PTR(ret); |
263 | goto err; | 264 | goto err; |
264 | } | 265 | } |
265 | dprintk("RPC: %s Success. gc_expiry %lu now %lu timeout %u\n", | 266 | |
266 | __func__, ctx->gc_expiry, now, timeout); | 267 | /* is there any trailing data? */ |
267 | return q; | 268 | if (q == end) { |
269 | p = q; | ||
270 | goto done; | ||
271 | } | ||
272 | |||
273 | /* pull in acceptor name (if there is one) */ | ||
274 | p = simple_get_netobj(q, end, &ctx->gc_acceptor); | ||
275 | if (IS_ERR(p)) | ||
276 | goto err; | ||
277 | done: | ||
278 | dprintk("RPC: %s Success. gc_expiry %lu now %lu timeout %u acceptor %.*s\n", | ||
279 | __func__, ctx->gc_expiry, now, timeout, ctx->gc_acceptor.len, | ||
280 | ctx->gc_acceptor.data); | ||
281 | return p; | ||
268 | err: | 282 | err: |
269 | dprintk("RPC: %s returns error %ld\n", __func__, -PTR_ERR(p)); | 283 | dprintk("RPC: %s returns error %ld\n", __func__, -PTR_ERR(p)); |
270 | return p; | 284 | return p; |
@@ -1194,13 +1208,13 @@ gss_destroying_context(struct rpc_cred *cred) | |||
1194 | { | 1208 | { |
1195 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); | 1209 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); |
1196 | struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth); | 1210 | struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth); |
1211 | struct gss_cl_ctx *ctx = rcu_dereference_protected(gss_cred->gc_ctx, 1); | ||
1197 | struct rpc_task *task; | 1212 | struct rpc_task *task; |
1198 | 1213 | ||
1199 | if (gss_cred->gc_ctx == NULL || | 1214 | if (test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0) |
1200 | test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags) == 0) | ||
1201 | return 0; | 1215 | return 0; |
1202 | 1216 | ||
1203 | gss_cred->gc_ctx->gc_proc = RPC_GSS_PROC_DESTROY; | 1217 | ctx->gc_proc = RPC_GSS_PROC_DESTROY; |
1204 | cred->cr_ops = &gss_nullops; | 1218 | cred->cr_ops = &gss_nullops; |
1205 | 1219 | ||
1206 | /* Take a reference to ensure the cred will be destroyed either | 1220 | /* Take a reference to ensure the cred will be destroyed either |
@@ -1225,6 +1239,7 @@ gss_do_free_ctx(struct gss_cl_ctx *ctx) | |||
1225 | 1239 | ||
1226 | gss_delete_sec_context(&ctx->gc_gss_ctx); | 1240 | gss_delete_sec_context(&ctx->gc_gss_ctx); |
1227 | kfree(ctx->gc_wire_ctx.data); | 1241 | kfree(ctx->gc_wire_ctx.data); |
1242 | kfree(ctx->gc_acceptor.data); | ||
1228 | kfree(ctx); | 1243 | kfree(ctx); |
1229 | } | 1244 | } |
1230 | 1245 | ||
@@ -1260,7 +1275,7 @@ gss_destroy_nullcred(struct rpc_cred *cred) | |||
1260 | { | 1275 | { |
1261 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); | 1276 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); |
1262 | struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth); | 1277 | struct gss_auth *gss_auth = container_of(cred->cr_auth, struct gss_auth, rpc_auth); |
1263 | struct gss_cl_ctx *ctx = gss_cred->gc_ctx; | 1278 | struct gss_cl_ctx *ctx = rcu_dereference_protected(gss_cred->gc_ctx, 1); |
1264 | 1279 | ||
1265 | RCU_INIT_POINTER(gss_cred->gc_ctx, NULL); | 1280 | RCU_INIT_POINTER(gss_cred->gc_ctx, NULL); |
1266 | call_rcu(&cred->cr_rcu, gss_free_cred_callback); | 1281 | call_rcu(&cred->cr_rcu, gss_free_cred_callback); |
@@ -1332,6 +1347,36 @@ gss_cred_init(struct rpc_auth *auth, struct rpc_cred *cred) | |||
1332 | return err; | 1347 | return err; |
1333 | } | 1348 | } |
1334 | 1349 | ||
1350 | static char * | ||
1351 | gss_stringify_acceptor(struct rpc_cred *cred) | ||
1352 | { | ||
1353 | char *string = NULL; | ||
1354 | struct gss_cred *gss_cred = container_of(cred, struct gss_cred, gc_base); | ||
1355 | struct gss_cl_ctx *ctx; | ||
1356 | struct xdr_netobj *acceptor; | ||
1357 | |||
1358 | rcu_read_lock(); | ||
1359 | ctx = rcu_dereference(gss_cred->gc_ctx); | ||
1360 | if (!ctx) | ||
1361 | goto out; | ||
1362 | |||
1363 | acceptor = &ctx->gc_acceptor; | ||
1364 | |||
1365 | /* no point if there's no string */ | ||
1366 | if (!acceptor->len) | ||
1367 | goto out; | ||
1368 | |||
1369 | string = kmalloc(acceptor->len + 1, GFP_KERNEL); | ||
1370 | if (!string) | ||
1371 | goto out; | ||
1372 | |||
1373 | memcpy(string, acceptor->data, acceptor->len); | ||
1374 | string[acceptor->len] = '\0'; | ||
1375 | out: | ||
1376 | rcu_read_unlock(); | ||
1377 | return string; | ||
1378 | } | ||
1379 | |||
1335 | /* | 1380 | /* |
1336 | * Returns -EACCES if GSS context is NULL or will expire within the | 1381 | * Returns -EACCES if GSS context is NULL or will expire within the |
1337 | * timeout (miliseconds) | 1382 | * timeout (miliseconds) |
@@ -1340,15 +1385,16 @@ static int | |||
1340 | gss_key_timeout(struct rpc_cred *rc) | 1385 | gss_key_timeout(struct rpc_cred *rc) |
1341 | { | 1386 | { |
1342 | struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base); | 1387 | struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base); |
1388 | struct gss_cl_ctx *ctx; | ||
1343 | unsigned long now = jiffies; | 1389 | unsigned long now = jiffies; |
1344 | unsigned long expire; | 1390 | unsigned long expire; |
1345 | 1391 | ||
1346 | if (gss_cred->gc_ctx == NULL) | 1392 | rcu_read_lock(); |
1347 | return -EACCES; | 1393 | ctx = rcu_dereference(gss_cred->gc_ctx); |
1348 | 1394 | if (ctx) | |
1349 | expire = gss_cred->gc_ctx->gc_expiry - (gss_key_expire_timeo * HZ); | 1395 | expire = ctx->gc_expiry - (gss_key_expire_timeo * HZ); |
1350 | 1396 | rcu_read_unlock(); | |
1351 | if (time_after(now, expire)) | 1397 | if (!ctx || time_after(now, expire)) |
1352 | return -EACCES; | 1398 | return -EACCES; |
1353 | return 0; | 1399 | return 0; |
1354 | } | 1400 | } |
@@ -1357,13 +1403,19 @@ static int | |||
1357 | gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags) | 1403 | gss_match(struct auth_cred *acred, struct rpc_cred *rc, int flags) |
1358 | { | 1404 | { |
1359 | struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base); | 1405 | struct gss_cred *gss_cred = container_of(rc, struct gss_cred, gc_base); |
1406 | struct gss_cl_ctx *ctx; | ||
1360 | int ret; | 1407 | int ret; |
1361 | 1408 | ||
1362 | if (test_bit(RPCAUTH_CRED_NEW, &rc->cr_flags)) | 1409 | if (test_bit(RPCAUTH_CRED_NEW, &rc->cr_flags)) |
1363 | goto out; | 1410 | goto out; |
1364 | /* Don't match with creds that have expired. */ | 1411 | /* Don't match with creds that have expired. */ |
1365 | if (time_after(jiffies, gss_cred->gc_ctx->gc_expiry)) | 1412 | rcu_read_lock(); |
1413 | ctx = rcu_dereference(gss_cred->gc_ctx); | ||
1414 | if (!ctx || time_after(jiffies, ctx->gc_expiry)) { | ||
1415 | rcu_read_unlock(); | ||
1366 | return 0; | 1416 | return 0; |
1417 | } | ||
1418 | rcu_read_unlock(); | ||
1367 | if (!test_bit(RPCAUTH_CRED_UPTODATE, &rc->cr_flags)) | 1419 | if (!test_bit(RPCAUTH_CRED_UPTODATE, &rc->cr_flags)) |
1368 | return 0; | 1420 | return 0; |
1369 | out: | 1421 | out: |
@@ -1909,29 +1961,31 @@ static const struct rpc_authops authgss_ops = { | |||
1909 | }; | 1961 | }; |
1910 | 1962 | ||
1911 | static const struct rpc_credops gss_credops = { | 1963 | static const struct rpc_credops gss_credops = { |
1912 | .cr_name = "AUTH_GSS", | 1964 | .cr_name = "AUTH_GSS", |
1913 | .crdestroy = gss_destroy_cred, | 1965 | .crdestroy = gss_destroy_cred, |
1914 | .cr_init = gss_cred_init, | 1966 | .cr_init = gss_cred_init, |
1915 | .crbind = rpcauth_generic_bind_cred, | 1967 | .crbind = rpcauth_generic_bind_cred, |
1916 | .crmatch = gss_match, | 1968 | .crmatch = gss_match, |
1917 | .crmarshal = gss_marshal, | 1969 | .crmarshal = gss_marshal, |
1918 | .crrefresh = gss_refresh, | 1970 | .crrefresh = gss_refresh, |
1919 | .crvalidate = gss_validate, | 1971 | .crvalidate = gss_validate, |
1920 | .crwrap_req = gss_wrap_req, | 1972 | .crwrap_req = gss_wrap_req, |
1921 | .crunwrap_resp = gss_unwrap_resp, | 1973 | .crunwrap_resp = gss_unwrap_resp, |
1922 | .crkey_timeout = gss_key_timeout, | 1974 | .crkey_timeout = gss_key_timeout, |
1975 | .crstringify_acceptor = gss_stringify_acceptor, | ||
1923 | }; | 1976 | }; |
1924 | 1977 | ||
1925 | static const struct rpc_credops gss_nullops = { | 1978 | static const struct rpc_credops gss_nullops = { |
1926 | .cr_name = "AUTH_GSS", | 1979 | .cr_name = "AUTH_GSS", |
1927 | .crdestroy = gss_destroy_nullcred, | 1980 | .crdestroy = gss_destroy_nullcred, |
1928 | .crbind = rpcauth_generic_bind_cred, | 1981 | .crbind = rpcauth_generic_bind_cred, |
1929 | .crmatch = gss_match, | 1982 | .crmatch = gss_match, |
1930 | .crmarshal = gss_marshal, | 1983 | .crmarshal = gss_marshal, |
1931 | .crrefresh = gss_refresh_null, | 1984 | .crrefresh = gss_refresh_null, |
1932 | .crvalidate = gss_validate, | 1985 | .crvalidate = gss_validate, |
1933 | .crwrap_req = gss_wrap_req, | 1986 | .crwrap_req = gss_wrap_req, |
1934 | .crunwrap_resp = gss_unwrap_resp, | 1987 | .crunwrap_resp = gss_unwrap_resp, |
1988 | .crstringify_acceptor = gss_stringify_acceptor, | ||
1935 | }; | 1989 | }; |
1936 | 1990 | ||
1937 | static const struct rpc_pipe_ops gss_upcall_ops_v0 = { | 1991 | static const struct rpc_pipe_ops gss_upcall_ops_v0 = { |
diff --git a/net/sunrpc/auth_gss/gss_krb5_crypto.c b/net/sunrpc/auth_gss/gss_krb5_crypto.c index 0f43e894bc0a..f5ed9f6ece06 100644 --- a/net/sunrpc/auth_gss/gss_krb5_crypto.c +++ b/net/sunrpc/auth_gss/gss_krb5_crypto.c | |||
@@ -641,7 +641,7 @@ out: | |||
641 | 641 | ||
642 | u32 | 642 | u32 |
643 | gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset, | 643 | gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset, |
644 | struct xdr_buf *buf, int ec, struct page **pages) | 644 | struct xdr_buf *buf, struct page **pages) |
645 | { | 645 | { |
646 | u32 err; | 646 | u32 err; |
647 | struct xdr_netobj hmac; | 647 | struct xdr_netobj hmac; |
@@ -684,13 +684,8 @@ gss_krb5_aes_encrypt(struct krb5_ctx *kctx, u32 offset, | |||
684 | ecptr = buf->tail[0].iov_base; | 684 | ecptr = buf->tail[0].iov_base; |
685 | } | 685 | } |
686 | 686 | ||
687 | memset(ecptr, 'X', ec); | ||
688 | buf->tail[0].iov_len += ec; | ||
689 | buf->len += ec; | ||
690 | |||
691 | /* copy plaintext gss token header after filler (if any) */ | 687 | /* copy plaintext gss token header after filler (if any) */ |
692 | memcpy(ecptr + ec, buf->head[0].iov_base + offset, | 688 | memcpy(ecptr, buf->head[0].iov_base + offset, GSS_KRB5_TOK_HDR_LEN); |
693 | GSS_KRB5_TOK_HDR_LEN); | ||
694 | buf->tail[0].iov_len += GSS_KRB5_TOK_HDR_LEN; | 689 | buf->tail[0].iov_len += GSS_KRB5_TOK_HDR_LEN; |
695 | buf->len += GSS_KRB5_TOK_HDR_LEN; | 690 | buf->len += GSS_KRB5_TOK_HDR_LEN; |
696 | 691 | ||
diff --git a/net/sunrpc/auth_gss/gss_krb5_seal.c b/net/sunrpc/auth_gss/gss_krb5_seal.c index 62ae3273186c..42768e5c3994 100644 --- a/net/sunrpc/auth_gss/gss_krb5_seal.c +++ b/net/sunrpc/auth_gss/gss_krb5_seal.c | |||
@@ -70,31 +70,37 @@ | |||
70 | 70 | ||
71 | DEFINE_SPINLOCK(krb5_seq_lock); | 71 | DEFINE_SPINLOCK(krb5_seq_lock); |
72 | 72 | ||
73 | static char * | 73 | static void * |
74 | setup_token(struct krb5_ctx *ctx, struct xdr_netobj *token) | 74 | setup_token(struct krb5_ctx *ctx, struct xdr_netobj *token) |
75 | { | 75 | { |
76 | __be16 *ptr, *krb5_hdr; | 76 | u16 *ptr; |
77 | void *krb5_hdr; | ||
77 | int body_size = GSS_KRB5_TOK_HDR_LEN + ctx->gk5e->cksumlength; | 78 | int body_size = GSS_KRB5_TOK_HDR_LEN + ctx->gk5e->cksumlength; |
78 | 79 | ||
79 | token->len = g_token_size(&ctx->mech_used, body_size); | 80 | token->len = g_token_size(&ctx->mech_used, body_size); |
80 | 81 | ||
81 | ptr = (__be16 *)token->data; | 82 | ptr = (u16 *)token->data; |
82 | g_make_token_header(&ctx->mech_used, body_size, (unsigned char **)&ptr); | 83 | g_make_token_header(&ctx->mech_used, body_size, (unsigned char **)&ptr); |
83 | 84 | ||
84 | /* ptr now at start of header described in rfc 1964, section 1.2.1: */ | 85 | /* ptr now at start of header described in rfc 1964, section 1.2.1: */ |
85 | krb5_hdr = ptr; | 86 | krb5_hdr = ptr; |
86 | *ptr++ = KG_TOK_MIC_MSG; | 87 | *ptr++ = KG_TOK_MIC_MSG; |
87 | *ptr++ = cpu_to_le16(ctx->gk5e->signalg); | 88 | /* |
89 | * signalg is stored as if it were converted from LE to host endian, even | ||
90 | * though it's an opaque pair of bytes according to the RFC. | ||
91 | */ | ||
92 | *ptr++ = (__force u16)cpu_to_le16(ctx->gk5e->signalg); | ||
88 | *ptr++ = SEAL_ALG_NONE; | 93 | *ptr++ = SEAL_ALG_NONE; |
89 | *ptr++ = 0xffff; | 94 | *ptr = 0xffff; |
90 | 95 | ||
91 | return (char *)krb5_hdr; | 96 | return krb5_hdr; |
92 | } | 97 | } |
93 | 98 | ||
94 | static void * | 99 | static void * |
95 | setup_token_v2(struct krb5_ctx *ctx, struct xdr_netobj *token) | 100 | setup_token_v2(struct krb5_ctx *ctx, struct xdr_netobj *token) |
96 | { | 101 | { |
97 | __be16 *ptr, *krb5_hdr; | 102 | u16 *ptr; |
103 | void *krb5_hdr; | ||
98 | u8 *p, flags = 0x00; | 104 | u8 *p, flags = 0x00; |
99 | 105 | ||
100 | if ((ctx->flags & KRB5_CTX_FLAG_INITIATOR) == 0) | 106 | if ((ctx->flags & KRB5_CTX_FLAG_INITIATOR) == 0) |
@@ -104,15 +110,15 @@ setup_token_v2(struct krb5_ctx *ctx, struct xdr_netobj *token) | |||
104 | 110 | ||
105 | /* Per rfc 4121, sec 4.2.6.1, there is no header, | 111 | /* Per rfc 4121, sec 4.2.6.1, there is no header, |
106 | * just start the token */ | 112 | * just start the token */ |
107 | krb5_hdr = ptr = (__be16 *)token->data; | 113 | krb5_hdr = ptr = (u16 *)token->data; |
108 | 114 | ||
109 | *ptr++ = KG2_TOK_MIC; | 115 | *ptr++ = KG2_TOK_MIC; |
110 | p = (u8 *)ptr; | 116 | p = (u8 *)ptr; |
111 | *p++ = flags; | 117 | *p++ = flags; |
112 | *p++ = 0xff; | 118 | *p++ = 0xff; |
113 | ptr = (__be16 *)p; | 119 | ptr = (u16 *)p; |
114 | *ptr++ = 0xffff; | ||
115 | *ptr++ = 0xffff; | 120 | *ptr++ = 0xffff; |
121 | *ptr = 0xffff; | ||
116 | 122 | ||
117 | token->len = GSS_KRB5_TOK_HDR_LEN + ctx->gk5e->cksumlength; | 123 | token->len = GSS_KRB5_TOK_HDR_LEN + ctx->gk5e->cksumlength; |
118 | return krb5_hdr; | 124 | return krb5_hdr; |
@@ -181,7 +187,7 @@ gss_get_mic_v2(struct krb5_ctx *ctx, struct xdr_buf *text, | |||
181 | spin_lock(&krb5_seq_lock); | 187 | spin_lock(&krb5_seq_lock); |
182 | seq_send = ctx->seq_send64++; | 188 | seq_send = ctx->seq_send64++; |
183 | spin_unlock(&krb5_seq_lock); | 189 | spin_unlock(&krb5_seq_lock); |
184 | *((u64 *)(krb5_hdr + 8)) = cpu_to_be64(seq_send); | 190 | *((__be64 *)(krb5_hdr + 8)) = cpu_to_be64(seq_send); |
185 | 191 | ||
186 | if (ctx->initiate) { | 192 | if (ctx->initiate) { |
187 | cksumkey = ctx->initiator_sign; | 193 | cksumkey = ctx->initiator_sign; |
diff --git a/net/sunrpc/auth_gss/gss_krb5_wrap.c b/net/sunrpc/auth_gss/gss_krb5_wrap.c index 42560e55d978..4b614c604fe0 100644 --- a/net/sunrpc/auth_gss/gss_krb5_wrap.c +++ b/net/sunrpc/auth_gss/gss_krb5_wrap.c | |||
@@ -201,9 +201,15 @@ gss_wrap_kerberos_v1(struct krb5_ctx *kctx, int offset, | |||
201 | 201 | ||
202 | msg_start = ptr + GSS_KRB5_TOK_HDR_LEN + kctx->gk5e->cksumlength; | 202 | msg_start = ptr + GSS_KRB5_TOK_HDR_LEN + kctx->gk5e->cksumlength; |
203 | 203 | ||
204 | *(__be16 *)(ptr + 2) = cpu_to_le16(kctx->gk5e->signalg); | 204 | /* |
205 | memset(ptr + 4, 0xff, 4); | 205 | * signalg and sealalg are stored as if they were converted from LE |
206 | *(__be16 *)(ptr + 4) = cpu_to_le16(kctx->gk5e->sealalg); | 206 | * to host endian, even though they're opaque pairs of bytes according |
207 | * to the RFC. | ||
208 | */ | ||
209 | *(__le16 *)(ptr + 2) = cpu_to_le16(kctx->gk5e->signalg); | ||
210 | *(__le16 *)(ptr + 4) = cpu_to_le16(kctx->gk5e->sealalg); | ||
211 | ptr[6] = 0xff; | ||
212 | ptr[7] = 0xff; | ||
207 | 213 | ||
208 | gss_krb5_make_confounder(msg_start, conflen); | 214 | gss_krb5_make_confounder(msg_start, conflen); |
209 | 215 | ||
@@ -438,7 +444,7 @@ gss_wrap_kerberos_v2(struct krb5_ctx *kctx, u32 offset, | |||
438 | u8 *ptr, *plainhdr; | 444 | u8 *ptr, *plainhdr; |
439 | s32 now; | 445 | s32 now; |
440 | u8 flags = 0x00; | 446 | u8 flags = 0x00; |
441 | __be16 *be16ptr, ec = 0; | 447 | __be16 *be16ptr; |
442 | __be64 *be64ptr; | 448 | __be64 *be64ptr; |
443 | u32 err; | 449 | u32 err; |
444 | 450 | ||
@@ -468,16 +474,16 @@ gss_wrap_kerberos_v2(struct krb5_ctx *kctx, u32 offset, | |||
468 | be16ptr = (__be16 *)ptr; | 474 | be16ptr = (__be16 *)ptr; |
469 | 475 | ||
470 | blocksize = crypto_blkcipher_blocksize(kctx->acceptor_enc); | 476 | blocksize = crypto_blkcipher_blocksize(kctx->acceptor_enc); |
471 | *be16ptr++ = cpu_to_be16(ec); | 477 | *be16ptr++ = 0; |
472 | /* "inner" token header always uses 0 for RRC */ | 478 | /* "inner" token header always uses 0 for RRC */ |
473 | *be16ptr++ = cpu_to_be16(0); | 479 | *be16ptr++ = 0; |
474 | 480 | ||
475 | be64ptr = (__be64 *)be16ptr; | 481 | be64ptr = (__be64 *)be16ptr; |
476 | spin_lock(&krb5_seq_lock); | 482 | spin_lock(&krb5_seq_lock); |
477 | *be64ptr = cpu_to_be64(kctx->seq_send64++); | 483 | *be64ptr = cpu_to_be64(kctx->seq_send64++); |
478 | spin_unlock(&krb5_seq_lock); | 484 | spin_unlock(&krb5_seq_lock); |
479 | 485 | ||
480 | err = (*kctx->gk5e->encrypt_v2)(kctx, offset, buf, ec, pages); | 486 | err = (*kctx->gk5e->encrypt_v2)(kctx, offset, buf, pages); |
481 | if (err) | 487 | if (err) |
482 | return err; | 488 | return err; |
483 | 489 | ||
diff --git a/net/sunrpc/auth_gss/svcauth_gss.c b/net/sunrpc/auth_gss/svcauth_gss.c index 4ce5eccec1f6..c548ab213f76 100644 --- a/net/sunrpc/auth_gss/svcauth_gss.c +++ b/net/sunrpc/auth_gss/svcauth_gss.c | |||
@@ -886,7 +886,7 @@ unwrap_priv_data(struct svc_rqst *rqstp, struct xdr_buf *buf, u32 seq, struct gs | |||
886 | u32 priv_len, maj_stat; | 886 | u32 priv_len, maj_stat; |
887 | int pad, saved_len, remaining_len, offset; | 887 | int pad, saved_len, remaining_len, offset; |
888 | 888 | ||
889 | rqstp->rq_splice_ok = 0; | 889 | rqstp->rq_splice_ok = false; |
890 | 890 | ||
891 | priv_len = svc_getnl(&buf->head[0]); | 891 | priv_len = svc_getnl(&buf->head[0]); |
892 | if (rqstp->rq_deferred) { | 892 | if (rqstp->rq_deferred) { |
diff --git a/net/sunrpc/auth_null.c b/net/sunrpc/auth_null.c index f0ebe07978a2..712c123e04e9 100644 --- a/net/sunrpc/auth_null.c +++ b/net/sunrpc/auth_null.c | |||
@@ -35,6 +35,8 @@ nul_destroy(struct rpc_auth *auth) | |||
35 | static struct rpc_cred * | 35 | static struct rpc_cred * |
36 | nul_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) | 36 | nul_lookup_cred(struct rpc_auth *auth, struct auth_cred *acred, int flags) |
37 | { | 37 | { |
38 | if (flags & RPCAUTH_LOOKUP_RCU) | ||
39 | return &null_cred; | ||
38 | return get_rpccred(&null_cred); | 40 | return get_rpccred(&null_cred); |
39 | } | 41 | } |
40 | 42 | ||
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 2e6ab10734f6..488ddeed9363 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
@@ -1746,6 +1746,7 @@ call_bind_status(struct rpc_task *task) | |||
1746 | case -EHOSTDOWN: | 1746 | case -EHOSTDOWN: |
1747 | case -EHOSTUNREACH: | 1747 | case -EHOSTUNREACH: |
1748 | case -ENETUNREACH: | 1748 | case -ENETUNREACH: |
1749 | case -ENOBUFS: | ||
1749 | case -EPIPE: | 1750 | case -EPIPE: |
1750 | dprintk("RPC: %5u remote rpcbind unreachable: %d\n", | 1751 | dprintk("RPC: %5u remote rpcbind unreachable: %d\n", |
1751 | task->tk_pid, task->tk_status); | 1752 | task->tk_pid, task->tk_status); |
@@ -1812,6 +1813,8 @@ call_connect_status(struct rpc_task *task) | |||
1812 | case -ECONNABORTED: | 1813 | case -ECONNABORTED: |
1813 | case -ENETUNREACH: | 1814 | case -ENETUNREACH: |
1814 | case -EHOSTUNREACH: | 1815 | case -EHOSTUNREACH: |
1816 | case -ENOBUFS: | ||
1817 | case -EPIPE: | ||
1815 | if (RPC_IS_SOFTCONN(task)) | 1818 | if (RPC_IS_SOFTCONN(task)) |
1816 | break; | 1819 | break; |
1817 | /* retry with existing socket, after a delay */ | 1820 | /* retry with existing socket, after a delay */ |
@@ -1918,6 +1921,7 @@ call_transmit_status(struct rpc_task *task) | |||
1918 | case -ECONNRESET: | 1921 | case -ECONNRESET: |
1919 | case -ECONNABORTED: | 1922 | case -ECONNABORTED: |
1920 | case -ENOTCONN: | 1923 | case -ENOTCONN: |
1924 | case -ENOBUFS: | ||
1921 | case -EPIPE: | 1925 | case -EPIPE: |
1922 | rpc_task_force_reencode(task); | 1926 | rpc_task_force_reencode(task); |
1923 | } | 1927 | } |
@@ -2034,6 +2038,7 @@ call_status(struct rpc_task *task) | |||
2034 | case -ECONNRESET: | 2038 | case -ECONNRESET: |
2035 | case -ECONNABORTED: | 2039 | case -ECONNABORTED: |
2036 | rpc_force_rebind(clnt); | 2040 | rpc_force_rebind(clnt); |
2041 | case -ENOBUFS: | ||
2037 | rpc_delay(task, 3*HZ); | 2042 | rpc_delay(task, 3*HZ); |
2038 | case -EPIPE: | 2043 | case -EPIPE: |
2039 | case -ENOTCONN: | 2044 | case -ENOTCONN: |
diff --git a/net/sunrpc/rpc_pipe.c b/net/sunrpc/rpc_pipe.c index b18554898562..2d12b76b5a64 100644 --- a/net/sunrpc/rpc_pipe.c +++ b/net/sunrpc/rpc_pipe.c | |||
@@ -195,7 +195,7 @@ static struct inode * | |||
195 | rpc_alloc_inode(struct super_block *sb) | 195 | rpc_alloc_inode(struct super_block *sb) |
196 | { | 196 | { |
197 | struct rpc_inode *rpci; | 197 | struct rpc_inode *rpci; |
198 | rpci = (struct rpc_inode *)kmem_cache_alloc(rpc_inode_cachep, GFP_KERNEL); | 198 | rpci = kmem_cache_alloc(rpc_inode_cachep, GFP_KERNEL); |
199 | if (!rpci) | 199 | if (!rpci) |
200 | return NULL; | 200 | return NULL; |
201 | return &rpci->vfs_inode; | 201 | return &rpci->vfs_inode; |
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index c0365c14b858..9358c79fd589 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
@@ -250,7 +250,7 @@ void rpc_destroy_wait_queue(struct rpc_wait_queue *queue) | |||
250 | } | 250 | } |
251 | EXPORT_SYMBOL_GPL(rpc_destroy_wait_queue); | 251 | EXPORT_SYMBOL_GPL(rpc_destroy_wait_queue); |
252 | 252 | ||
253 | static int rpc_wait_bit_killable(void *word) | 253 | static int rpc_wait_bit_killable(struct wait_bit_key *key) |
254 | { | 254 | { |
255 | if (fatal_signal_pending(current)) | 255 | if (fatal_signal_pending(current)) |
256 | return -ERESTARTSYS; | 256 | return -ERESTARTSYS; |
@@ -309,7 +309,7 @@ static int rpc_complete_task(struct rpc_task *task) | |||
309 | * to enforce taking of the wq->lock and hence avoid races with | 309 | * to enforce taking of the wq->lock and hence avoid races with |
310 | * rpc_complete_task(). | 310 | * rpc_complete_task(). |
311 | */ | 311 | */ |
312 | int __rpc_wait_for_completion_task(struct rpc_task *task, int (*action)(void *)) | 312 | int __rpc_wait_for_completion_task(struct rpc_task *task, wait_bit_action_f *action) |
313 | { | 313 | { |
314 | if (action == NULL) | 314 | if (action == NULL) |
315 | action = rpc_wait_bit_killable; | 315 | action = rpc_wait_bit_killable; |
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 5de6801cd924..1db5007ddbce 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c | |||
@@ -1086,9 +1086,9 @@ svc_process_common(struct svc_rqst *rqstp, struct kvec *argv, struct kvec *resv) | |||
1086 | goto err_short_len; | 1086 | goto err_short_len; |
1087 | 1087 | ||
1088 | /* Will be turned off only in gss privacy case: */ | 1088 | /* Will be turned off only in gss privacy case: */ |
1089 | rqstp->rq_splice_ok = 1; | 1089 | rqstp->rq_splice_ok = true; |
1090 | /* Will be turned off only when NFSv4 Sessions are used */ | 1090 | /* Will be turned off only when NFSv4 Sessions are used */ |
1091 | rqstp->rq_usedeferral = 1; | 1091 | rqstp->rq_usedeferral = true; |
1092 | rqstp->rq_dropme = false; | 1092 | rqstp->rq_dropme = false; |
1093 | 1093 | ||
1094 | /* Setup reply header */ | 1094 | /* Setup reply header */ |
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index b4737fbdec13..6666c6745858 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c | |||
@@ -23,6 +23,7 @@ static int svc_deferred_recv(struct svc_rqst *rqstp); | |||
23 | static struct cache_deferred_req *svc_defer(struct cache_req *req); | 23 | static struct cache_deferred_req *svc_defer(struct cache_req *req); |
24 | static void svc_age_temp_xprts(unsigned long closure); | 24 | static void svc_age_temp_xprts(unsigned long closure); |
25 | static void svc_delete_xprt(struct svc_xprt *xprt); | 25 | static void svc_delete_xprt(struct svc_xprt *xprt); |
26 | static void svc_xprt_do_enqueue(struct svc_xprt *xprt); | ||
26 | 27 | ||
27 | /* apparently the "standard" is that clients close | 28 | /* apparently the "standard" is that clients close |
28 | * idle connections after 5 minutes, servers after | 29 | * idle connections after 5 minutes, servers after |
@@ -222,11 +223,12 @@ static void svc_xprt_received(struct svc_xprt *xprt) | |||
222 | if (!test_bit(XPT_BUSY, &xprt->xpt_flags)) | 223 | if (!test_bit(XPT_BUSY, &xprt->xpt_flags)) |
223 | return; | 224 | return; |
224 | /* As soon as we clear busy, the xprt could be closed and | 225 | /* As soon as we clear busy, the xprt could be closed and |
225 | * 'put', so we need a reference to call svc_xprt_enqueue with: | 226 | * 'put', so we need a reference to call svc_xprt_do_enqueue with: |
226 | */ | 227 | */ |
227 | svc_xprt_get(xprt); | 228 | svc_xprt_get(xprt); |
229 | smp_mb__before_atomic(); | ||
228 | clear_bit(XPT_BUSY, &xprt->xpt_flags); | 230 | clear_bit(XPT_BUSY, &xprt->xpt_flags); |
229 | svc_xprt_enqueue(xprt); | 231 | svc_xprt_do_enqueue(xprt); |
230 | svc_xprt_put(xprt); | 232 | svc_xprt_put(xprt); |
231 | } | 233 | } |
232 | 234 | ||
@@ -335,12 +337,7 @@ static bool svc_xprt_has_something_to_do(struct svc_xprt *xprt) | |||
335 | return false; | 337 | return false; |
336 | } | 338 | } |
337 | 339 | ||
338 | /* | 340 | static void svc_xprt_do_enqueue(struct svc_xprt *xprt) |
339 | * Queue up a transport with data pending. If there are idle nfsd | ||
340 | * processes, wake 'em up. | ||
341 | * | ||
342 | */ | ||
343 | void svc_xprt_enqueue(struct svc_xprt *xprt) | ||
344 | { | 341 | { |
345 | struct svc_pool *pool; | 342 | struct svc_pool *pool; |
346 | struct svc_rqst *rqstp; | 343 | struct svc_rqst *rqstp; |
@@ -398,6 +395,18 @@ void svc_xprt_enqueue(struct svc_xprt *xprt) | |||
398 | out_unlock: | 395 | out_unlock: |
399 | spin_unlock_bh(&pool->sp_lock); | 396 | spin_unlock_bh(&pool->sp_lock); |
400 | } | 397 | } |
398 | |||
399 | /* | ||
400 | * Queue up a transport with data pending. If there are idle nfsd | ||
401 | * processes, wake 'em up. | ||
402 | * | ||
403 | */ | ||
404 | void svc_xprt_enqueue(struct svc_xprt *xprt) | ||
405 | { | ||
406 | if (test_bit(XPT_BUSY, &xprt->xpt_flags)) | ||
407 | return; | ||
408 | svc_xprt_do_enqueue(xprt); | ||
409 | } | ||
401 | EXPORT_SYMBOL_GPL(svc_xprt_enqueue); | 410 | EXPORT_SYMBOL_GPL(svc_xprt_enqueue); |
402 | 411 | ||
403 | /* | 412 | /* |
@@ -439,6 +448,8 @@ void svc_reserve(struct svc_rqst *rqstp, int space) | |||
439 | atomic_sub((rqstp->rq_reserved - space), &xprt->xpt_reserved); | 448 | atomic_sub((rqstp->rq_reserved - space), &xprt->xpt_reserved); |
440 | rqstp->rq_reserved = space; | 449 | rqstp->rq_reserved = space; |
441 | 450 | ||
451 | if (xprt->xpt_ops->xpo_adjust_wspace) | ||
452 | xprt->xpt_ops->xpo_adjust_wspace(xprt); | ||
442 | svc_xprt_enqueue(xprt); | 453 | svc_xprt_enqueue(xprt); |
443 | } | 454 | } |
444 | } | 455 | } |
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index b507cd327d9b..c24a8ff33f8f 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -446,15 +446,43 @@ static void svc_write_space(struct sock *sk) | |||
446 | } | 446 | } |
447 | } | 447 | } |
448 | 448 | ||
449 | static int svc_tcp_has_wspace(struct svc_xprt *xprt) | ||
450 | { | ||
451 | struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); | ||
452 | struct svc_serv *serv = svsk->sk_xprt.xpt_server; | ||
453 | int required; | ||
454 | |||
455 | if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) | ||
456 | return 1; | ||
457 | required = atomic_read(&xprt->xpt_reserved) + serv->sv_max_mesg; | ||
458 | if (sk_stream_wspace(svsk->sk_sk) >= required || | ||
459 | (sk_stream_min_wspace(svsk->sk_sk) == 0 && | ||
460 | atomic_read(&xprt->xpt_reserved) == 0)) | ||
461 | return 1; | ||
462 | set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); | ||
463 | return 0; | ||
464 | } | ||
465 | |||
449 | static void svc_tcp_write_space(struct sock *sk) | 466 | static void svc_tcp_write_space(struct sock *sk) |
450 | { | 467 | { |
468 | struct svc_sock *svsk = (struct svc_sock *)(sk->sk_user_data); | ||
451 | struct socket *sock = sk->sk_socket; | 469 | struct socket *sock = sk->sk_socket; |
452 | 470 | ||
453 | if (sk_stream_is_writeable(sk) && sock) | 471 | if (!sk_stream_is_writeable(sk) || !sock) |
472 | return; | ||
473 | if (!svsk || svc_tcp_has_wspace(&svsk->sk_xprt)) | ||
454 | clear_bit(SOCK_NOSPACE, &sock->flags); | 474 | clear_bit(SOCK_NOSPACE, &sock->flags); |
455 | svc_write_space(sk); | 475 | svc_write_space(sk); |
456 | } | 476 | } |
457 | 477 | ||
478 | static void svc_tcp_adjust_wspace(struct svc_xprt *xprt) | ||
479 | { | ||
480 | struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); | ||
481 | |||
482 | if (svc_tcp_has_wspace(xprt)) | ||
483 | clear_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); | ||
484 | } | ||
485 | |||
458 | /* | 486 | /* |
459 | * See net/ipv6/ip_sockglue.c : ip_cmsg_recv_pktinfo | 487 | * See net/ipv6/ip_sockglue.c : ip_cmsg_recv_pktinfo |
460 | */ | 488 | */ |
@@ -692,6 +720,7 @@ static struct svc_xprt_class svc_udp_class = { | |||
692 | .xcl_owner = THIS_MODULE, | 720 | .xcl_owner = THIS_MODULE, |
693 | .xcl_ops = &svc_udp_ops, | 721 | .xcl_ops = &svc_udp_ops, |
694 | .xcl_max_payload = RPCSVC_MAXPAYLOAD_UDP, | 722 | .xcl_max_payload = RPCSVC_MAXPAYLOAD_UDP, |
723 | .xcl_ident = XPRT_TRANSPORT_UDP, | ||
695 | }; | 724 | }; |
696 | 725 | ||
697 | static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv) | 726 | static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv) |
@@ -1197,23 +1226,6 @@ static void svc_tcp_prep_reply_hdr(struct svc_rqst *rqstp) | |||
1197 | svc_putnl(resv, 0); | 1226 | svc_putnl(resv, 0); |
1198 | } | 1227 | } |
1199 | 1228 | ||
1200 | static int svc_tcp_has_wspace(struct svc_xprt *xprt) | ||
1201 | { | ||
1202 | struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); | ||
1203 | struct svc_serv *serv = svsk->sk_xprt.xpt_server; | ||
1204 | int required; | ||
1205 | |||
1206 | if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) | ||
1207 | return 1; | ||
1208 | required = atomic_read(&xprt->xpt_reserved) + serv->sv_max_mesg; | ||
1209 | if (sk_stream_wspace(svsk->sk_sk) >= required || | ||
1210 | (sk_stream_min_wspace(svsk->sk_sk) == 0 && | ||
1211 | atomic_read(&xprt->xpt_reserved) == 0)) | ||
1212 | return 1; | ||
1213 | set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); | ||
1214 | return 0; | ||
1215 | } | ||
1216 | |||
1217 | static struct svc_xprt *svc_tcp_create(struct svc_serv *serv, | 1229 | static struct svc_xprt *svc_tcp_create(struct svc_serv *serv, |
1218 | struct net *net, | 1230 | struct net *net, |
1219 | struct sockaddr *sa, int salen, | 1231 | struct sockaddr *sa, int salen, |
@@ -1285,6 +1297,7 @@ static struct svc_xprt_ops svc_tcp_ops = { | |||
1285 | .xpo_has_wspace = svc_tcp_has_wspace, | 1297 | .xpo_has_wspace = svc_tcp_has_wspace, |
1286 | .xpo_accept = svc_tcp_accept, | 1298 | .xpo_accept = svc_tcp_accept, |
1287 | .xpo_secure_port = svc_sock_secure_port, | 1299 | .xpo_secure_port = svc_sock_secure_port, |
1300 | .xpo_adjust_wspace = svc_tcp_adjust_wspace, | ||
1288 | }; | 1301 | }; |
1289 | 1302 | ||
1290 | static struct svc_xprt_class svc_tcp_class = { | 1303 | static struct svc_xprt_class svc_tcp_class = { |
@@ -1292,6 +1305,7 @@ static struct svc_xprt_class svc_tcp_class = { | |||
1292 | .xcl_owner = THIS_MODULE, | 1305 | .xcl_owner = THIS_MODULE, |
1293 | .xcl_ops = &svc_tcp_ops, | 1306 | .xcl_ops = &svc_tcp_ops, |
1294 | .xcl_max_payload = RPCSVC_MAXPAYLOAD_TCP, | 1307 | .xcl_max_payload = RPCSVC_MAXPAYLOAD_TCP, |
1308 | .xcl_ident = XPRT_TRANSPORT_TCP, | ||
1295 | }; | 1309 | }; |
1296 | 1310 | ||
1297 | void svc_init_xprt_sock(void) | 1311 | void svc_init_xprt_sock(void) |
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 23fb4e75e245..290af97bf6f9 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c | |||
@@ -509,7 +509,8 @@ void xdr_commit_encode(struct xdr_stream *xdr) | |||
509 | } | 509 | } |
510 | EXPORT_SYMBOL_GPL(xdr_commit_encode); | 510 | EXPORT_SYMBOL_GPL(xdr_commit_encode); |
511 | 511 | ||
512 | __be32 *xdr_get_next_encode_buffer(struct xdr_stream *xdr, size_t nbytes) | 512 | static __be32 *xdr_get_next_encode_buffer(struct xdr_stream *xdr, |
513 | size_t nbytes) | ||
513 | { | 514 | { |
514 | static __be32 *p; | 515 | static __be32 *p; |
515 | int space_left; | 516 | int space_left; |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index c3b2b3369e52..56e4e150e80e 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -744,6 +744,7 @@ static void xprt_connect_status(struct rpc_task *task) | |||
744 | case -ECONNABORTED: | 744 | case -ECONNABORTED: |
745 | case -ENETUNREACH: | 745 | case -ENETUNREACH: |
746 | case -EHOSTUNREACH: | 746 | case -EHOSTUNREACH: |
747 | case -EPIPE: | ||
747 | case -EAGAIN: | 748 | case -EAGAIN: |
748 | dprintk("RPC: %5u xprt_connect_status: retrying\n", task->tk_pid); | 749 | dprintk("RPC: %5u xprt_connect_status: retrying\n", task->tk_pid); |
749 | break; | 750 | break; |
@@ -1306,7 +1307,7 @@ struct rpc_xprt *xprt_create_transport(struct xprt_create *args) | |||
1306 | } | 1307 | } |
1307 | } | 1308 | } |
1308 | spin_unlock(&xprt_list_lock); | 1309 | spin_unlock(&xprt_list_lock); |
1309 | printk(KERN_ERR "RPC: transport (%d) not supported\n", args->ident); | 1310 | dprintk("RPC: transport (%d) not supported\n", args->ident); |
1310 | return ERR_PTR(-EIO); | 1311 | return ERR_PTR(-EIO); |
1311 | 1312 | ||
1312 | found: | 1313 | found: |
diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c index 693966d3f33b..6166c985fe24 100644 --- a/net/sunrpc/xprtrdma/rpc_rdma.c +++ b/net/sunrpc/xprtrdma/rpc_rdma.c | |||
@@ -53,14 +53,6 @@ | |||
53 | # define RPCDBG_FACILITY RPCDBG_TRANS | 53 | # define RPCDBG_FACILITY RPCDBG_TRANS |
54 | #endif | 54 | #endif |
55 | 55 | ||
56 | enum rpcrdma_chunktype { | ||
57 | rpcrdma_noch = 0, | ||
58 | rpcrdma_readch, | ||
59 | rpcrdma_areadch, | ||
60 | rpcrdma_writech, | ||
61 | rpcrdma_replych | ||
62 | }; | ||
63 | |||
64 | #ifdef RPC_DEBUG | 56 | #ifdef RPC_DEBUG |
65 | static const char transfertypes[][12] = { | 57 | static const char transfertypes[][12] = { |
66 | "pure inline", /* no chunks */ | 58 | "pure inline", /* no chunks */ |
@@ -279,13 +271,37 @@ rpcrdma_create_chunks(struct rpc_rqst *rqst, struct xdr_buf *target, | |||
279 | return (unsigned char *)iptr - (unsigned char *)headerp; | 271 | return (unsigned char *)iptr - (unsigned char *)headerp; |
280 | 272 | ||
281 | out: | 273 | out: |
282 | for (pos = 0; nchunks--;) | 274 | if (r_xprt->rx_ia.ri_memreg_strategy != RPCRDMA_FRMR) { |
283 | pos += rpcrdma_deregister_external( | 275 | for (pos = 0; nchunks--;) |
284 | &req->rl_segments[pos], r_xprt); | 276 | pos += rpcrdma_deregister_external( |
277 | &req->rl_segments[pos], r_xprt); | ||
278 | } | ||
285 | return n; | 279 | return n; |
286 | } | 280 | } |
287 | 281 | ||
288 | /* | 282 | /* |
283 | * Marshal chunks. This routine returns the header length | ||
284 | * consumed by marshaling. | ||
285 | * | ||
286 | * Returns positive RPC/RDMA header size, or negative errno. | ||
287 | */ | ||
288 | |||
289 | ssize_t | ||
290 | rpcrdma_marshal_chunks(struct rpc_rqst *rqst, ssize_t result) | ||
291 | { | ||
292 | struct rpcrdma_req *req = rpcr_to_rdmar(rqst); | ||
293 | struct rpcrdma_msg *headerp = (struct rpcrdma_msg *)req->rl_base; | ||
294 | |||
295 | if (req->rl_rtype != rpcrdma_noch) | ||
296 | result = rpcrdma_create_chunks(rqst, &rqst->rq_snd_buf, | ||
297 | headerp, req->rl_rtype); | ||
298 | else if (req->rl_wtype != rpcrdma_noch) | ||
299 | result = rpcrdma_create_chunks(rqst, &rqst->rq_rcv_buf, | ||
300 | headerp, req->rl_wtype); | ||
301 | return result; | ||
302 | } | ||
303 | |||
304 | /* | ||
289 | * Copy write data inline. | 305 | * Copy write data inline. |
290 | * This function is used for "small" requests. Data which is passed | 306 | * This function is used for "small" requests. Data which is passed |
291 | * to RPC via iovecs (or page list) is copied directly into the | 307 | * to RPC via iovecs (or page list) is copied directly into the |
@@ -377,7 +393,6 @@ rpcrdma_marshal_req(struct rpc_rqst *rqst) | |||
377 | char *base; | 393 | char *base; |
378 | size_t rpclen, padlen; | 394 | size_t rpclen, padlen; |
379 | ssize_t hdrlen; | 395 | ssize_t hdrlen; |
380 | enum rpcrdma_chunktype rtype, wtype; | ||
381 | struct rpcrdma_msg *headerp; | 396 | struct rpcrdma_msg *headerp; |
382 | 397 | ||
383 | /* | 398 | /* |
@@ -415,13 +430,13 @@ rpcrdma_marshal_req(struct rpc_rqst *rqst) | |||
415 | * into pages; otherwise use reply chunks. | 430 | * into pages; otherwise use reply chunks. |
416 | */ | 431 | */ |
417 | if (rqst->rq_rcv_buf.buflen <= RPCRDMA_INLINE_READ_THRESHOLD(rqst)) | 432 | if (rqst->rq_rcv_buf.buflen <= RPCRDMA_INLINE_READ_THRESHOLD(rqst)) |
418 | wtype = rpcrdma_noch; | 433 | req->rl_wtype = rpcrdma_noch; |
419 | else if (rqst->rq_rcv_buf.page_len == 0) | 434 | else if (rqst->rq_rcv_buf.page_len == 0) |
420 | wtype = rpcrdma_replych; | 435 | req->rl_wtype = rpcrdma_replych; |
421 | else if (rqst->rq_rcv_buf.flags & XDRBUF_READ) | 436 | else if (rqst->rq_rcv_buf.flags & XDRBUF_READ) |
422 | wtype = rpcrdma_writech; | 437 | req->rl_wtype = rpcrdma_writech; |
423 | else | 438 | else |
424 | wtype = rpcrdma_replych; | 439 | req->rl_wtype = rpcrdma_replych; |
425 | 440 | ||
426 | /* | 441 | /* |
427 | * Chunks needed for arguments? | 442 | * Chunks needed for arguments? |
@@ -438,16 +453,16 @@ rpcrdma_marshal_req(struct rpc_rqst *rqst) | |||
438 | * TBD check NFSv4 setacl | 453 | * TBD check NFSv4 setacl |
439 | */ | 454 | */ |
440 | if (rqst->rq_snd_buf.len <= RPCRDMA_INLINE_WRITE_THRESHOLD(rqst)) | 455 | if (rqst->rq_snd_buf.len <= RPCRDMA_INLINE_WRITE_THRESHOLD(rqst)) |
441 | rtype = rpcrdma_noch; | 456 | req->rl_rtype = rpcrdma_noch; |
442 | else if (rqst->rq_snd_buf.page_len == 0) | 457 | else if (rqst->rq_snd_buf.page_len == 0) |
443 | rtype = rpcrdma_areadch; | 458 | req->rl_rtype = rpcrdma_areadch; |
444 | else | 459 | else |
445 | rtype = rpcrdma_readch; | 460 | req->rl_rtype = rpcrdma_readch; |
446 | 461 | ||
447 | /* The following simplification is not true forever */ | 462 | /* The following simplification is not true forever */ |
448 | if (rtype != rpcrdma_noch && wtype == rpcrdma_replych) | 463 | if (req->rl_rtype != rpcrdma_noch && req->rl_wtype == rpcrdma_replych) |
449 | wtype = rpcrdma_noch; | 464 | req->rl_wtype = rpcrdma_noch; |
450 | if (rtype != rpcrdma_noch && wtype != rpcrdma_noch) { | 465 | if (req->rl_rtype != rpcrdma_noch && req->rl_wtype != rpcrdma_noch) { |
451 | dprintk("RPC: %s: cannot marshal multiple chunk lists\n", | 466 | dprintk("RPC: %s: cannot marshal multiple chunk lists\n", |
452 | __func__); | 467 | __func__); |
453 | return -EIO; | 468 | return -EIO; |
@@ -461,7 +476,7 @@ rpcrdma_marshal_req(struct rpc_rqst *rqst) | |||
461 | * When padding is in use and applies to the transfer, insert | 476 | * When padding is in use and applies to the transfer, insert |
462 | * it and change the message type. | 477 | * it and change the message type. |
463 | */ | 478 | */ |
464 | if (rtype == rpcrdma_noch) { | 479 | if (req->rl_rtype == rpcrdma_noch) { |
465 | 480 | ||
466 | padlen = rpcrdma_inline_pullup(rqst, | 481 | padlen = rpcrdma_inline_pullup(rqst, |
467 | RPCRDMA_INLINE_PAD_VALUE(rqst)); | 482 | RPCRDMA_INLINE_PAD_VALUE(rqst)); |
@@ -476,7 +491,7 @@ rpcrdma_marshal_req(struct rpc_rqst *rqst) | |||
476 | headerp->rm_body.rm_padded.rm_pempty[1] = xdr_zero; | 491 | headerp->rm_body.rm_padded.rm_pempty[1] = xdr_zero; |
477 | headerp->rm_body.rm_padded.rm_pempty[2] = xdr_zero; | 492 | headerp->rm_body.rm_padded.rm_pempty[2] = xdr_zero; |
478 | hdrlen += 2 * sizeof(u32); /* extra words in padhdr */ | 493 | hdrlen += 2 * sizeof(u32); /* extra words in padhdr */ |
479 | if (wtype != rpcrdma_noch) { | 494 | if (req->rl_wtype != rpcrdma_noch) { |
480 | dprintk("RPC: %s: invalid chunk list\n", | 495 | dprintk("RPC: %s: invalid chunk list\n", |
481 | __func__); | 496 | __func__); |
482 | return -EIO; | 497 | return -EIO; |
@@ -497,30 +512,18 @@ rpcrdma_marshal_req(struct rpc_rqst *rqst) | |||
497 | * on receive. Therefore, we request a reply chunk | 512 | * on receive. Therefore, we request a reply chunk |
498 | * for non-writes wherever feasible and efficient. | 513 | * for non-writes wherever feasible and efficient. |
499 | */ | 514 | */ |
500 | if (wtype == rpcrdma_noch) | 515 | if (req->rl_wtype == rpcrdma_noch) |
501 | wtype = rpcrdma_replych; | 516 | req->rl_wtype = rpcrdma_replych; |
502 | } | 517 | } |
503 | } | 518 | } |
504 | 519 | ||
505 | /* | 520 | hdrlen = rpcrdma_marshal_chunks(rqst, hdrlen); |
506 | * Marshal chunks. This routine will return the header length | ||
507 | * consumed by marshaling. | ||
508 | */ | ||
509 | if (rtype != rpcrdma_noch) { | ||
510 | hdrlen = rpcrdma_create_chunks(rqst, | ||
511 | &rqst->rq_snd_buf, headerp, rtype); | ||
512 | wtype = rtype; /* simplify dprintk */ | ||
513 | |||
514 | } else if (wtype != rpcrdma_noch) { | ||
515 | hdrlen = rpcrdma_create_chunks(rqst, | ||
516 | &rqst->rq_rcv_buf, headerp, wtype); | ||
517 | } | ||
518 | if (hdrlen < 0) | 521 | if (hdrlen < 0) |
519 | return hdrlen; | 522 | return hdrlen; |
520 | 523 | ||
521 | dprintk("RPC: %s: %s: hdrlen %zd rpclen %zd padlen %zd" | 524 | dprintk("RPC: %s: %s: hdrlen %zd rpclen %zd padlen %zd" |
522 | " headerp 0x%p base 0x%p lkey 0x%x\n", | 525 | " headerp 0x%p base 0x%p lkey 0x%x\n", |
523 | __func__, transfertypes[wtype], hdrlen, rpclen, padlen, | 526 | __func__, transfertypes[req->rl_wtype], hdrlen, rpclen, padlen, |
524 | headerp, base, req->rl_iov.lkey); | 527 | headerp, base, req->rl_iov.lkey); |
525 | 528 | ||
526 | /* | 529 | /* |
diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c index 8f92a61ee2df..e0110270d650 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | |||
@@ -43,6 +43,7 @@ | |||
43 | #include <linux/sunrpc/debug.h> | 43 | #include <linux/sunrpc/debug.h> |
44 | #include <linux/sunrpc/rpc_rdma.h> | 44 | #include <linux/sunrpc/rpc_rdma.h> |
45 | #include <linux/spinlock.h> | 45 | #include <linux/spinlock.h> |
46 | #include <linux/highmem.h> | ||
46 | #include <asm/unaligned.h> | 47 | #include <asm/unaligned.h> |
47 | #include <rdma/ib_verbs.h> | 48 | #include <rdma/ib_verbs.h> |
48 | #include <rdma/rdma_cm.h> | 49 | #include <rdma/rdma_cm.h> |
@@ -435,6 +436,32 @@ static int rdma_read_chunks(struct svcxprt_rdma *xprt, | |||
435 | return ret; | 436 | return ret; |
436 | } | 437 | } |
437 | 438 | ||
439 | /* | ||
440 | * To avoid a separate RDMA READ just for a handful of zero bytes, | ||
441 | * RFC 5666 section 3.7 allows the client to omit the XDR zero pad | ||
442 | * in chunk lists. | ||
443 | */ | ||
444 | static void | ||
445 | rdma_fix_xdr_pad(struct xdr_buf *buf) | ||
446 | { | ||
447 | unsigned int page_len = buf->page_len; | ||
448 | unsigned int size = (XDR_QUADLEN(page_len) << 2) - page_len; | ||
449 | unsigned int offset, pg_no; | ||
450 | char *p; | ||
451 | |||
452 | if (size == 0) | ||
453 | return; | ||
454 | |||
455 | pg_no = page_len >> PAGE_SHIFT; | ||
456 | offset = page_len & ~PAGE_MASK; | ||
457 | p = page_address(buf->pages[pg_no]); | ||
458 | memset(p + offset, 0, size); | ||
459 | |||
460 | buf->page_len += size; | ||
461 | buf->buflen += size; | ||
462 | buf->len += size; | ||
463 | } | ||
464 | |||
438 | static int rdma_read_complete(struct svc_rqst *rqstp, | 465 | static int rdma_read_complete(struct svc_rqst *rqstp, |
439 | struct svc_rdma_op_ctxt *head) | 466 | struct svc_rdma_op_ctxt *head) |
440 | { | 467 | { |
@@ -449,6 +476,7 @@ static int rdma_read_complete(struct svc_rqst *rqstp, | |||
449 | rqstp->rq_pages[page_no] = head->pages[page_no]; | 476 | rqstp->rq_pages[page_no] = head->pages[page_no]; |
450 | } | 477 | } |
451 | /* Point rq_arg.pages past header */ | 478 | /* Point rq_arg.pages past header */ |
479 | rdma_fix_xdr_pad(&head->arg); | ||
452 | rqstp->rq_arg.pages = &rqstp->rq_pages[head->hdr_count]; | 480 | rqstp->rq_arg.pages = &rqstp->rq_pages[head->hdr_count]; |
453 | rqstp->rq_arg.page_len = head->arg.page_len; | 481 | rqstp->rq_arg.page_len = head->arg.page_len; |
454 | rqstp->rq_arg.page_base = head->arg.page_base; | 482 | rqstp->rq_arg.page_base = head->arg.page_base; |
diff --git a/net/sunrpc/xprtrdma/svc_rdma_sendto.c b/net/sunrpc/xprtrdma/svc_rdma_sendto.c index 49fd21a5c215..9f1b50689c0f 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_sendto.c +++ b/net/sunrpc/xprtrdma/svc_rdma_sendto.c | |||
@@ -192,6 +192,8 @@ static int send_write(struct svcxprt_rdma *xprt, struct svc_rqst *rqstp, | |||
192 | xdr_sge_no++; | 192 | xdr_sge_no++; |
193 | BUG_ON(xdr_sge_no > vec->count); | 193 | BUG_ON(xdr_sge_no > vec->count); |
194 | bc -= sge_bytes; | 194 | bc -= sge_bytes; |
195 | if (sge_no == xprt->sc_max_sge) | ||
196 | break; | ||
195 | } | 197 | } |
196 | 198 | ||
197 | /* Prepare WRITE WR */ | 199 | /* Prepare WRITE WR */ |
@@ -209,7 +211,7 @@ static int send_write(struct svcxprt_rdma *xprt, struct svc_rqst *rqstp, | |||
209 | atomic_inc(&rdma_stat_write); | 211 | atomic_inc(&rdma_stat_write); |
210 | if (svc_rdma_send(xprt, &write_wr)) | 212 | if (svc_rdma_send(xprt, &write_wr)) |
211 | goto err; | 213 | goto err; |
212 | return 0; | 214 | return write_len - bc; |
213 | err: | 215 | err: |
214 | svc_rdma_unmap_dma(ctxt); | 216 | svc_rdma_unmap_dma(ctxt); |
215 | svc_rdma_put_context(ctxt, 0); | 217 | svc_rdma_put_context(ctxt, 0); |
@@ -225,7 +227,6 @@ static int send_write_chunks(struct svcxprt_rdma *xprt, | |||
225 | { | 227 | { |
226 | u32 xfer_len = rqstp->rq_res.page_len + rqstp->rq_res.tail[0].iov_len; | 228 | u32 xfer_len = rqstp->rq_res.page_len + rqstp->rq_res.tail[0].iov_len; |
227 | int write_len; | 229 | int write_len; |
228 | int max_write; | ||
229 | u32 xdr_off; | 230 | u32 xdr_off; |
230 | int chunk_off; | 231 | int chunk_off; |
231 | int chunk_no; | 232 | int chunk_no; |
@@ -239,8 +240,6 @@ static int send_write_chunks(struct svcxprt_rdma *xprt, | |||
239 | res_ary = (struct rpcrdma_write_array *) | 240 | res_ary = (struct rpcrdma_write_array *) |
240 | &rdma_resp->rm_body.rm_chunks[1]; | 241 | &rdma_resp->rm_body.rm_chunks[1]; |
241 | 242 | ||
242 | max_write = xprt->sc_max_sge * PAGE_SIZE; | ||
243 | |||
244 | /* Write chunks start at the pagelist */ | 243 | /* Write chunks start at the pagelist */ |
245 | for (xdr_off = rqstp->rq_res.head[0].iov_len, chunk_no = 0; | 244 | for (xdr_off = rqstp->rq_res.head[0].iov_len, chunk_no = 0; |
246 | xfer_len && chunk_no < arg_ary->wc_nchunks; | 245 | xfer_len && chunk_no < arg_ary->wc_nchunks; |
@@ -260,23 +259,21 @@ static int send_write_chunks(struct svcxprt_rdma *xprt, | |||
260 | write_len); | 259 | write_len); |
261 | chunk_off = 0; | 260 | chunk_off = 0; |
262 | while (write_len) { | 261 | while (write_len) { |
263 | int this_write; | ||
264 | this_write = min(write_len, max_write); | ||
265 | ret = send_write(xprt, rqstp, | 262 | ret = send_write(xprt, rqstp, |
266 | ntohl(arg_ch->rs_handle), | 263 | ntohl(arg_ch->rs_handle), |
267 | rs_offset + chunk_off, | 264 | rs_offset + chunk_off, |
268 | xdr_off, | 265 | xdr_off, |
269 | this_write, | 266 | write_len, |
270 | vec); | 267 | vec); |
271 | if (ret) { | 268 | if (ret <= 0) { |
272 | dprintk("svcrdma: RDMA_WRITE failed, ret=%d\n", | 269 | dprintk("svcrdma: RDMA_WRITE failed, ret=%d\n", |
273 | ret); | 270 | ret); |
274 | return -EIO; | 271 | return -EIO; |
275 | } | 272 | } |
276 | chunk_off += this_write; | 273 | chunk_off += ret; |
277 | xdr_off += this_write; | 274 | xdr_off += ret; |
278 | xfer_len -= this_write; | 275 | xfer_len -= ret; |
279 | write_len -= this_write; | 276 | write_len -= ret; |
280 | } | 277 | } |
281 | } | 278 | } |
282 | /* Update the req with the number of chunks actually used */ | 279 | /* Update the req with the number of chunks actually used */ |
@@ -293,7 +290,6 @@ static int send_reply_chunks(struct svcxprt_rdma *xprt, | |||
293 | { | 290 | { |
294 | u32 xfer_len = rqstp->rq_res.len; | 291 | u32 xfer_len = rqstp->rq_res.len; |
295 | int write_len; | 292 | int write_len; |
296 | int max_write; | ||
297 | u32 xdr_off; | 293 | u32 xdr_off; |
298 | int chunk_no; | 294 | int chunk_no; |
299 | int chunk_off; | 295 | int chunk_off; |
@@ -311,8 +307,6 @@ static int send_reply_chunks(struct svcxprt_rdma *xprt, | |||
311 | res_ary = (struct rpcrdma_write_array *) | 307 | res_ary = (struct rpcrdma_write_array *) |
312 | &rdma_resp->rm_body.rm_chunks[2]; | 308 | &rdma_resp->rm_body.rm_chunks[2]; |
313 | 309 | ||
314 | max_write = xprt->sc_max_sge * PAGE_SIZE; | ||
315 | |||
316 | /* xdr offset starts at RPC message */ | 310 | /* xdr offset starts at RPC message */ |
317 | nchunks = ntohl(arg_ary->wc_nchunks); | 311 | nchunks = ntohl(arg_ary->wc_nchunks); |
318 | for (xdr_off = 0, chunk_no = 0; | 312 | for (xdr_off = 0, chunk_no = 0; |
@@ -330,24 +324,21 @@ static int send_reply_chunks(struct svcxprt_rdma *xprt, | |||
330 | write_len); | 324 | write_len); |
331 | chunk_off = 0; | 325 | chunk_off = 0; |
332 | while (write_len) { | 326 | while (write_len) { |
333 | int this_write; | ||
334 | |||
335 | this_write = min(write_len, max_write); | ||
336 | ret = send_write(xprt, rqstp, | 327 | ret = send_write(xprt, rqstp, |
337 | ntohl(ch->rs_handle), | 328 | ntohl(ch->rs_handle), |
338 | rs_offset + chunk_off, | 329 | rs_offset + chunk_off, |
339 | xdr_off, | 330 | xdr_off, |
340 | this_write, | 331 | write_len, |
341 | vec); | 332 | vec); |
342 | if (ret) { | 333 | if (ret <= 0) { |
343 | dprintk("svcrdma: RDMA_WRITE failed, ret=%d\n", | 334 | dprintk("svcrdma: RDMA_WRITE failed, ret=%d\n", |
344 | ret); | 335 | ret); |
345 | return -EIO; | 336 | return -EIO; |
346 | } | 337 | } |
347 | chunk_off += this_write; | 338 | chunk_off += ret; |
348 | xdr_off += this_write; | 339 | xdr_off += ret; |
349 | xfer_len -= this_write; | 340 | xfer_len -= ret; |
350 | write_len -= this_write; | 341 | write_len -= ret; |
351 | } | 342 | } |
352 | } | 343 | } |
353 | /* Update the req with the number of chunks actually used */ | 344 | /* Update the req with the number of chunks actually used */ |
diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c index e7323fbbd348..374feb44afea 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c | |||
@@ -92,6 +92,7 @@ struct svc_xprt_class svc_rdma_class = { | |||
92 | .xcl_owner = THIS_MODULE, | 92 | .xcl_owner = THIS_MODULE, |
93 | .xcl_ops = &svc_rdma_ops, | 93 | .xcl_ops = &svc_rdma_ops, |
94 | .xcl_max_payload = RPCSVC_MAXPAYLOAD_TCP, | 94 | .xcl_max_payload = RPCSVC_MAXPAYLOAD_TCP, |
95 | .xcl_ident = XPRT_TRANSPORT_RDMA, | ||
95 | }; | 96 | }; |
96 | 97 | ||
97 | struct svc_rdma_op_ctxt *svc_rdma_get_context(struct svcxprt_rdma *xprt) | 98 | struct svc_rdma_op_ctxt *svc_rdma_get_context(struct svcxprt_rdma *xprt) |
@@ -942,23 +943,8 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt) | |||
942 | 943 | ||
943 | ret = rdma_create_qp(newxprt->sc_cm_id, newxprt->sc_pd, &qp_attr); | 944 | ret = rdma_create_qp(newxprt->sc_cm_id, newxprt->sc_pd, &qp_attr); |
944 | if (ret) { | 945 | if (ret) { |
945 | /* | 946 | dprintk("svcrdma: failed to create QP, ret=%d\n", ret); |
946 | * XXX: This is a hack. We need a xx_request_qp interface | 947 | goto errout; |
947 | * that will adjust the qp_attr's with a best-effort | ||
948 | * number | ||
949 | */ | ||
950 | qp_attr.cap.max_send_sge -= 2; | ||
951 | qp_attr.cap.max_recv_sge -= 2; | ||
952 | ret = rdma_create_qp(newxprt->sc_cm_id, newxprt->sc_pd, | ||
953 | &qp_attr); | ||
954 | if (ret) { | ||
955 | dprintk("svcrdma: failed to create QP, ret=%d\n", ret); | ||
956 | goto errout; | ||
957 | } | ||
958 | newxprt->sc_max_sge = qp_attr.cap.max_send_sge; | ||
959 | newxprt->sc_max_sge = qp_attr.cap.max_recv_sge; | ||
960 | newxprt->sc_sq_depth = qp_attr.cap.max_send_wr; | ||
961 | newxprt->sc_max_requests = qp_attr.cap.max_recv_wr; | ||
962 | } | 948 | } |
963 | newxprt->sc_qp = newxprt->sc_cm_id->qp; | 949 | newxprt->sc_qp = newxprt->sc_cm_id->qp; |
964 | 950 | ||
diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index 66f91f0d071a..2faac4940563 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c | |||
@@ -296,7 +296,6 @@ xprt_setup_rdma(struct xprt_create *args) | |||
296 | 296 | ||
297 | xprt->resvport = 0; /* privileged port not needed */ | 297 | xprt->resvport = 0; /* privileged port not needed */ |
298 | xprt->tsh_size = 0; /* RPC-RDMA handles framing */ | 298 | xprt->tsh_size = 0; /* RPC-RDMA handles framing */ |
299 | xprt->max_payload = RPCRDMA_MAX_DATA_SEGS * PAGE_SIZE; | ||
300 | xprt->ops = &xprt_rdma_procs; | 299 | xprt->ops = &xprt_rdma_procs; |
301 | 300 | ||
302 | /* | 301 | /* |
@@ -382,6 +381,9 @@ xprt_setup_rdma(struct xprt_create *args) | |||
382 | new_ep->rep_xprt = xprt; | 381 | new_ep->rep_xprt = xprt; |
383 | 382 | ||
384 | xprt_rdma_format_addresses(xprt); | 383 | xprt_rdma_format_addresses(xprt); |
384 | xprt->max_payload = rpcrdma_max_payload(new_xprt); | ||
385 | dprintk("RPC: %s: transport data payload maximum: %zu bytes\n", | ||
386 | __func__, xprt->max_payload); | ||
385 | 387 | ||
386 | if (!try_module_get(THIS_MODULE)) | 388 | if (!try_module_get(THIS_MODULE)) |
387 | goto out4; | 389 | goto out4; |
@@ -412,7 +414,7 @@ xprt_rdma_close(struct rpc_xprt *xprt) | |||
412 | if (r_xprt->rx_ep.rep_connected > 0) | 414 | if (r_xprt->rx_ep.rep_connected > 0) |
413 | xprt->reestablish_timeout = 0; | 415 | xprt->reestablish_timeout = 0; |
414 | xprt_disconnect_done(xprt); | 416 | xprt_disconnect_done(xprt); |
415 | (void) rpcrdma_ep_disconnect(&r_xprt->rx_ep, &r_xprt->rx_ia); | 417 | rpcrdma_ep_disconnect(&r_xprt->rx_ep, &r_xprt->rx_ia); |
416 | } | 418 | } |
417 | 419 | ||
418 | static void | 420 | static void |
@@ -595,13 +597,14 @@ xprt_rdma_send_request(struct rpc_task *task) | |||
595 | struct rpc_xprt *xprt = rqst->rq_xprt; | 597 | struct rpc_xprt *xprt = rqst->rq_xprt; |
596 | struct rpcrdma_req *req = rpcr_to_rdmar(rqst); | 598 | struct rpcrdma_req *req = rpcr_to_rdmar(rqst); |
597 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); | 599 | struct rpcrdma_xprt *r_xprt = rpcx_to_rdmax(xprt); |
598 | int rc; | 600 | int rc = 0; |
599 | 601 | ||
600 | if (req->rl_niovs == 0) { | 602 | if (req->rl_niovs == 0) |
601 | rc = rpcrdma_marshal_req(rqst); | 603 | rc = rpcrdma_marshal_req(rqst); |
602 | if (rc < 0) | 604 | else if (r_xprt->rx_ia.ri_memreg_strategy == RPCRDMA_FRMR) |
603 | goto failed_marshal; | 605 | rc = rpcrdma_marshal_chunks(rqst, 0); |
604 | } | 606 | if (rc < 0) |
607 | goto failed_marshal; | ||
605 | 608 | ||
606 | if (req->rl_reply == NULL) /* e.g. reconnection */ | 609 | if (req->rl_reply == NULL) /* e.g. reconnection */ |
607 | rpcrdma_recv_buffer_get(req); | 610 | rpcrdma_recv_buffer_get(req); |
diff --git a/net/sunrpc/xprtrdma/verbs.c b/net/sunrpc/xprtrdma/verbs.c index 13dbd1c389ff..61c41298b4ea 100644 --- a/net/sunrpc/xprtrdma/verbs.c +++ b/net/sunrpc/xprtrdma/verbs.c | |||
@@ -61,6 +61,8 @@ | |||
61 | # define RPCDBG_FACILITY RPCDBG_TRANS | 61 | # define RPCDBG_FACILITY RPCDBG_TRANS |
62 | #endif | 62 | #endif |
63 | 63 | ||
64 | static void rpcrdma_reset_frmrs(struct rpcrdma_ia *); | ||
65 | |||
64 | /* | 66 | /* |
65 | * internal functions | 67 | * internal functions |
66 | */ | 68 | */ |
@@ -103,17 +105,6 @@ rpcrdma_run_tasklet(unsigned long data) | |||
103 | 105 | ||
104 | static DECLARE_TASKLET(rpcrdma_tasklet_g, rpcrdma_run_tasklet, 0UL); | 106 | static DECLARE_TASKLET(rpcrdma_tasklet_g, rpcrdma_run_tasklet, 0UL); |
105 | 107 | ||
106 | static inline void | ||
107 | rpcrdma_schedule_tasklet(struct rpcrdma_rep *rep) | ||
108 | { | ||
109 | unsigned long flags; | ||
110 | |||
111 | spin_lock_irqsave(&rpcrdma_tk_lock_g, flags); | ||
112 | list_add_tail(&rep->rr_list, &rpcrdma_tasklets_g); | ||
113 | spin_unlock_irqrestore(&rpcrdma_tk_lock_g, flags); | ||
114 | tasklet_schedule(&rpcrdma_tasklet_g); | ||
115 | } | ||
116 | |||
117 | static void | 108 | static void |
118 | rpcrdma_qp_async_error_upcall(struct ib_event *event, void *context) | 109 | rpcrdma_qp_async_error_upcall(struct ib_event *event, void *context) |
119 | { | 110 | { |
@@ -153,12 +144,7 @@ rpcrdma_sendcq_process_wc(struct ib_wc *wc) | |||
153 | if (wc->wr_id == 0ULL) | 144 | if (wc->wr_id == 0ULL) |
154 | return; | 145 | return; |
155 | if (wc->status != IB_WC_SUCCESS) | 146 | if (wc->status != IB_WC_SUCCESS) |
156 | return; | 147 | frmr->r.frmr.fr_state = FRMR_IS_STALE; |
157 | |||
158 | if (wc->opcode == IB_WC_FAST_REG_MR) | ||
159 | frmr->r.frmr.state = FRMR_IS_VALID; | ||
160 | else if (wc->opcode == IB_WC_LOCAL_INV) | ||
161 | frmr->r.frmr.state = FRMR_IS_INVALID; | ||
162 | } | 148 | } |
163 | 149 | ||
164 | static int | 150 | static int |
@@ -217,7 +203,7 @@ rpcrdma_sendcq_upcall(struct ib_cq *cq, void *cq_context) | |||
217 | } | 203 | } |
218 | 204 | ||
219 | static void | 205 | static void |
220 | rpcrdma_recvcq_process_wc(struct ib_wc *wc) | 206 | rpcrdma_recvcq_process_wc(struct ib_wc *wc, struct list_head *sched_list) |
221 | { | 207 | { |
222 | struct rpcrdma_rep *rep = | 208 | struct rpcrdma_rep *rep = |
223 | (struct rpcrdma_rep *)(unsigned long)wc->wr_id; | 209 | (struct rpcrdma_rep *)(unsigned long)wc->wr_id; |
@@ -248,28 +234,38 @@ rpcrdma_recvcq_process_wc(struct ib_wc *wc) | |||
248 | } | 234 | } |
249 | 235 | ||
250 | out_schedule: | 236 | out_schedule: |
251 | rpcrdma_schedule_tasklet(rep); | 237 | list_add_tail(&rep->rr_list, sched_list); |
252 | } | 238 | } |
253 | 239 | ||
254 | static int | 240 | static int |
255 | rpcrdma_recvcq_poll(struct ib_cq *cq, struct rpcrdma_ep *ep) | 241 | rpcrdma_recvcq_poll(struct ib_cq *cq, struct rpcrdma_ep *ep) |
256 | { | 242 | { |
243 | struct list_head sched_list; | ||
257 | struct ib_wc *wcs; | 244 | struct ib_wc *wcs; |
258 | int budget, count, rc; | 245 | int budget, count, rc; |
246 | unsigned long flags; | ||
259 | 247 | ||
248 | INIT_LIST_HEAD(&sched_list); | ||
260 | budget = RPCRDMA_WC_BUDGET / RPCRDMA_POLLSIZE; | 249 | budget = RPCRDMA_WC_BUDGET / RPCRDMA_POLLSIZE; |
261 | do { | 250 | do { |
262 | wcs = ep->rep_recv_wcs; | 251 | wcs = ep->rep_recv_wcs; |
263 | 252 | ||
264 | rc = ib_poll_cq(cq, RPCRDMA_POLLSIZE, wcs); | 253 | rc = ib_poll_cq(cq, RPCRDMA_POLLSIZE, wcs); |
265 | if (rc <= 0) | 254 | if (rc <= 0) |
266 | return rc; | 255 | goto out_schedule; |
267 | 256 | ||
268 | count = rc; | 257 | count = rc; |
269 | while (count-- > 0) | 258 | while (count-- > 0) |
270 | rpcrdma_recvcq_process_wc(wcs++); | 259 | rpcrdma_recvcq_process_wc(wcs++, &sched_list); |
271 | } while (rc == RPCRDMA_POLLSIZE && --budget); | 260 | } while (rc == RPCRDMA_POLLSIZE && --budget); |
272 | return 0; | 261 | rc = 0; |
262 | |||
263 | out_schedule: | ||
264 | spin_lock_irqsave(&rpcrdma_tk_lock_g, flags); | ||
265 | list_splice_tail(&sched_list, &rpcrdma_tasklets_g); | ||
266 | spin_unlock_irqrestore(&rpcrdma_tk_lock_g, flags); | ||
267 | tasklet_schedule(&rpcrdma_tasklet_g); | ||
268 | return rc; | ||
273 | } | 269 | } |
274 | 270 | ||
275 | /* | 271 | /* |
@@ -310,6 +306,13 @@ rpcrdma_recvcq_upcall(struct ib_cq *cq, void *cq_context) | |||
310 | rpcrdma_recvcq_poll(cq, ep); | 306 | rpcrdma_recvcq_poll(cq, ep); |
311 | } | 307 | } |
312 | 308 | ||
309 | static void | ||
310 | rpcrdma_flush_cqs(struct rpcrdma_ep *ep) | ||
311 | { | ||
312 | rpcrdma_recvcq_upcall(ep->rep_attr.recv_cq, ep); | ||
313 | rpcrdma_sendcq_upcall(ep->rep_attr.send_cq, ep); | ||
314 | } | ||
315 | |||
313 | #ifdef RPC_DEBUG | 316 | #ifdef RPC_DEBUG |
314 | static const char * const conn[] = { | 317 | static const char * const conn[] = { |
315 | "address resolved", | 318 | "address resolved", |
@@ -323,8 +326,16 @@ static const char * const conn[] = { | |||
323 | "rejected", | 326 | "rejected", |
324 | "established", | 327 | "established", |
325 | "disconnected", | 328 | "disconnected", |
326 | "device removal" | 329 | "device removal", |
330 | "multicast join", | ||
331 | "multicast error", | ||
332 | "address change", | ||
333 | "timewait exit", | ||
327 | }; | 334 | }; |
335 | |||
336 | #define CONNECTION_MSG(status) \ | ||
337 | ((status) < ARRAY_SIZE(conn) ? \ | ||
338 | conn[(status)] : "unrecognized connection error") | ||
328 | #endif | 339 | #endif |
329 | 340 | ||
330 | static int | 341 | static int |
@@ -382,23 +393,18 @@ rpcrdma_conn_upcall(struct rdma_cm_id *id, struct rdma_cm_event *event) | |||
382 | case RDMA_CM_EVENT_DEVICE_REMOVAL: | 393 | case RDMA_CM_EVENT_DEVICE_REMOVAL: |
383 | connstate = -ENODEV; | 394 | connstate = -ENODEV; |
384 | connected: | 395 | connected: |
385 | dprintk("RPC: %s: %s: %pI4:%u (ep 0x%p event 0x%x)\n", | ||
386 | __func__, | ||
387 | (event->event <= 11) ? conn[event->event] : | ||
388 | "unknown connection error", | ||
389 | &addr->sin_addr.s_addr, | ||
390 | ntohs(addr->sin_port), | ||
391 | ep, event->event); | ||
392 | atomic_set(&rpcx_to_rdmax(ep->rep_xprt)->rx_buf.rb_credits, 1); | 396 | atomic_set(&rpcx_to_rdmax(ep->rep_xprt)->rx_buf.rb_credits, 1); |
393 | dprintk("RPC: %s: %sconnected\n", | 397 | dprintk("RPC: %s: %sconnected\n", |
394 | __func__, connstate > 0 ? "" : "dis"); | 398 | __func__, connstate > 0 ? "" : "dis"); |
395 | ep->rep_connected = connstate; | 399 | ep->rep_connected = connstate; |
396 | ep->rep_func(ep); | 400 | ep->rep_func(ep); |
397 | wake_up_all(&ep->rep_connect_wait); | 401 | wake_up_all(&ep->rep_connect_wait); |
398 | break; | 402 | /*FALLTHROUGH*/ |
399 | default: | 403 | default: |
400 | dprintk("RPC: %s: unexpected CM event %d\n", | 404 | dprintk("RPC: %s: %pI4:%u (ep 0x%p): %s\n", |
401 | __func__, event->event); | 405 | __func__, &addr->sin_addr.s_addr, |
406 | ntohs(addr->sin_port), ep, | ||
407 | CONNECTION_MSG(event->event)); | ||
402 | break; | 408 | break; |
403 | } | 409 | } |
404 | 410 | ||
@@ -558,12 +564,7 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg) | |||
558 | if (!ia->ri_id->device->alloc_fmr) { | 564 | if (!ia->ri_id->device->alloc_fmr) { |
559 | dprintk("RPC: %s: MTHCAFMR registration " | 565 | dprintk("RPC: %s: MTHCAFMR registration " |
560 | "not supported by HCA\n", __func__); | 566 | "not supported by HCA\n", __func__); |
561 | #if RPCRDMA_PERSISTENT_REGISTRATION | ||
562 | memreg = RPCRDMA_ALLPHYSICAL; | 567 | memreg = RPCRDMA_ALLPHYSICAL; |
563 | #else | ||
564 | rc = -ENOMEM; | ||
565 | goto out2; | ||
566 | #endif | ||
567 | } | 568 | } |
568 | } | 569 | } |
569 | 570 | ||
@@ -578,20 +579,16 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg) | |||
578 | switch (memreg) { | 579 | switch (memreg) { |
579 | case RPCRDMA_FRMR: | 580 | case RPCRDMA_FRMR: |
580 | break; | 581 | break; |
581 | #if RPCRDMA_PERSISTENT_REGISTRATION | ||
582 | case RPCRDMA_ALLPHYSICAL: | 582 | case RPCRDMA_ALLPHYSICAL: |
583 | mem_priv = IB_ACCESS_LOCAL_WRITE | | 583 | mem_priv = IB_ACCESS_LOCAL_WRITE | |
584 | IB_ACCESS_REMOTE_WRITE | | 584 | IB_ACCESS_REMOTE_WRITE | |
585 | IB_ACCESS_REMOTE_READ; | 585 | IB_ACCESS_REMOTE_READ; |
586 | goto register_setup; | 586 | goto register_setup; |
587 | #endif | ||
588 | case RPCRDMA_MTHCAFMR: | 587 | case RPCRDMA_MTHCAFMR: |
589 | if (ia->ri_have_dma_lkey) | 588 | if (ia->ri_have_dma_lkey) |
590 | break; | 589 | break; |
591 | mem_priv = IB_ACCESS_LOCAL_WRITE; | 590 | mem_priv = IB_ACCESS_LOCAL_WRITE; |
592 | #if RPCRDMA_PERSISTENT_REGISTRATION | ||
593 | register_setup: | 591 | register_setup: |
594 | #endif | ||
595 | ia->ri_bind_mem = ib_get_dma_mr(ia->ri_pd, mem_priv); | 592 | ia->ri_bind_mem = ib_get_dma_mr(ia->ri_pd, mem_priv); |
596 | if (IS_ERR(ia->ri_bind_mem)) { | 593 | if (IS_ERR(ia->ri_bind_mem)) { |
597 | printk(KERN_ALERT "%s: ib_get_dma_mr for " | 594 | printk(KERN_ALERT "%s: ib_get_dma_mr for " |
@@ -613,6 +610,7 @@ rpcrdma_ia_open(struct rpcrdma_xprt *xprt, struct sockaddr *addr, int memreg) | |||
613 | /* Else will do memory reg/dereg for each chunk */ | 610 | /* Else will do memory reg/dereg for each chunk */ |
614 | ia->ri_memreg_strategy = memreg; | 611 | ia->ri_memreg_strategy = memreg; |
615 | 612 | ||
613 | rwlock_init(&ia->ri_qplock); | ||
616 | return 0; | 614 | return 0; |
617 | out2: | 615 | out2: |
618 | rdma_destroy_id(ia->ri_id); | 616 | rdma_destroy_id(ia->ri_id); |
@@ -826,10 +824,7 @@ rpcrdma_ep_destroy(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia) | |||
826 | cancel_delayed_work_sync(&ep->rep_connect_worker); | 824 | cancel_delayed_work_sync(&ep->rep_connect_worker); |
827 | 825 | ||
828 | if (ia->ri_id->qp) { | 826 | if (ia->ri_id->qp) { |
829 | rc = rpcrdma_ep_disconnect(ep, ia); | 827 | rpcrdma_ep_disconnect(ep, ia); |
830 | if (rc) | ||
831 | dprintk("RPC: %s: rpcrdma_ep_disconnect" | ||
832 | " returned %i\n", __func__, rc); | ||
833 | rdma_destroy_qp(ia->ri_id); | 828 | rdma_destroy_qp(ia->ri_id); |
834 | ia->ri_id->qp = NULL; | 829 | ia->ri_id->qp = NULL; |
835 | } | 830 | } |
@@ -859,7 +854,7 @@ rpcrdma_ep_destroy(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia) | |||
859 | int | 854 | int |
860 | rpcrdma_ep_connect(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia) | 855 | rpcrdma_ep_connect(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia) |
861 | { | 856 | { |
862 | struct rdma_cm_id *id; | 857 | struct rdma_cm_id *id, *old; |
863 | int rc = 0; | 858 | int rc = 0; |
864 | int retry_count = 0; | 859 | int retry_count = 0; |
865 | 860 | ||
@@ -867,13 +862,12 @@ rpcrdma_ep_connect(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia) | |||
867 | struct rpcrdma_xprt *xprt; | 862 | struct rpcrdma_xprt *xprt; |
868 | retry: | 863 | retry: |
869 | dprintk("RPC: %s: reconnecting...\n", __func__); | 864 | dprintk("RPC: %s: reconnecting...\n", __func__); |
870 | rc = rpcrdma_ep_disconnect(ep, ia); | ||
871 | if (rc && rc != -ENOTCONN) | ||
872 | dprintk("RPC: %s: rpcrdma_ep_disconnect" | ||
873 | " status %i\n", __func__, rc); | ||
874 | 865 | ||
875 | rpcrdma_clean_cq(ep->rep_attr.recv_cq); | 866 | rpcrdma_ep_disconnect(ep, ia); |
876 | rpcrdma_clean_cq(ep->rep_attr.send_cq); | 867 | rpcrdma_flush_cqs(ep); |
868 | |||
869 | if (ia->ri_memreg_strategy == RPCRDMA_FRMR) | ||
870 | rpcrdma_reset_frmrs(ia); | ||
877 | 871 | ||
878 | xprt = container_of(ia, struct rpcrdma_xprt, rx_ia); | 872 | xprt = container_of(ia, struct rpcrdma_xprt, rx_ia); |
879 | id = rpcrdma_create_id(xprt, ia, | 873 | id = rpcrdma_create_id(xprt, ia, |
@@ -905,9 +899,14 @@ retry: | |||
905 | rc = -ENETUNREACH; | 899 | rc = -ENETUNREACH; |
906 | goto out; | 900 | goto out; |
907 | } | 901 | } |
908 | rdma_destroy_qp(ia->ri_id); | 902 | |
909 | rdma_destroy_id(ia->ri_id); | 903 | write_lock(&ia->ri_qplock); |
904 | old = ia->ri_id; | ||
910 | ia->ri_id = id; | 905 | ia->ri_id = id; |
906 | write_unlock(&ia->ri_qplock); | ||
907 | |||
908 | rdma_destroy_qp(old); | ||
909 | rdma_destroy_id(old); | ||
911 | } else { | 910 | } else { |
912 | dprintk("RPC: %s: connecting...\n", __func__); | 911 | dprintk("RPC: %s: connecting...\n", __func__); |
913 | rc = rdma_create_qp(ia->ri_id, ia->ri_pd, &ep->rep_attr); | 912 | rc = rdma_create_qp(ia->ri_id, ia->ri_pd, &ep->rep_attr); |
@@ -974,13 +973,12 @@ out: | |||
974 | * This call is not reentrant, and must not be made in parallel | 973 | * This call is not reentrant, and must not be made in parallel |
975 | * on the same endpoint. | 974 | * on the same endpoint. |
976 | */ | 975 | */ |
977 | int | 976 | void |
978 | rpcrdma_ep_disconnect(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia) | 977 | rpcrdma_ep_disconnect(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia) |
979 | { | 978 | { |
980 | int rc; | 979 | int rc; |
981 | 980 | ||
982 | rpcrdma_clean_cq(ep->rep_attr.recv_cq); | 981 | rpcrdma_flush_cqs(ep); |
983 | rpcrdma_clean_cq(ep->rep_attr.send_cq); | ||
984 | rc = rdma_disconnect(ia->ri_id); | 982 | rc = rdma_disconnect(ia->ri_id); |
985 | if (!rc) { | 983 | if (!rc) { |
986 | /* returns without wait if not connected */ | 984 | /* returns without wait if not connected */ |
@@ -992,12 +990,93 @@ rpcrdma_ep_disconnect(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia) | |||
992 | dprintk("RPC: %s: rdma_disconnect %i\n", __func__, rc); | 990 | dprintk("RPC: %s: rdma_disconnect %i\n", __func__, rc); |
993 | ep->rep_connected = rc; | 991 | ep->rep_connected = rc; |
994 | } | 992 | } |
993 | } | ||
994 | |||
995 | static int | ||
996 | rpcrdma_init_fmrs(struct rpcrdma_ia *ia, struct rpcrdma_buffer *buf) | ||
997 | { | ||
998 | int mr_access_flags = IB_ACCESS_REMOTE_WRITE | IB_ACCESS_REMOTE_READ; | ||
999 | struct ib_fmr_attr fmr_attr = { | ||
1000 | .max_pages = RPCRDMA_MAX_DATA_SEGS, | ||
1001 | .max_maps = 1, | ||
1002 | .page_shift = PAGE_SHIFT | ||
1003 | }; | ||
1004 | struct rpcrdma_mw *r; | ||
1005 | int i, rc; | ||
1006 | |||
1007 | i = (buf->rb_max_requests + 1) * RPCRDMA_MAX_SEGS; | ||
1008 | dprintk("RPC: %s: initalizing %d FMRs\n", __func__, i); | ||
1009 | |||
1010 | while (i--) { | ||
1011 | r = kzalloc(sizeof(*r), GFP_KERNEL); | ||
1012 | if (r == NULL) | ||
1013 | return -ENOMEM; | ||
1014 | |||
1015 | r->r.fmr = ib_alloc_fmr(ia->ri_pd, mr_access_flags, &fmr_attr); | ||
1016 | if (IS_ERR(r->r.fmr)) { | ||
1017 | rc = PTR_ERR(r->r.fmr); | ||
1018 | dprintk("RPC: %s: ib_alloc_fmr failed %i\n", | ||
1019 | __func__, rc); | ||
1020 | goto out_free; | ||
1021 | } | ||
1022 | |||
1023 | list_add(&r->mw_list, &buf->rb_mws); | ||
1024 | list_add(&r->mw_all, &buf->rb_all); | ||
1025 | } | ||
1026 | return 0; | ||
1027 | |||
1028 | out_free: | ||
1029 | kfree(r); | ||
1030 | return rc; | ||
1031 | } | ||
1032 | |||
1033 | static int | ||
1034 | rpcrdma_init_frmrs(struct rpcrdma_ia *ia, struct rpcrdma_buffer *buf) | ||
1035 | { | ||
1036 | struct rpcrdma_frmr *f; | ||
1037 | struct rpcrdma_mw *r; | ||
1038 | int i, rc; | ||
1039 | |||
1040 | i = (buf->rb_max_requests + 1) * RPCRDMA_MAX_SEGS; | ||
1041 | dprintk("RPC: %s: initalizing %d FRMRs\n", __func__, i); | ||
1042 | |||
1043 | while (i--) { | ||
1044 | r = kzalloc(sizeof(*r), GFP_KERNEL); | ||
1045 | if (r == NULL) | ||
1046 | return -ENOMEM; | ||
1047 | f = &r->r.frmr; | ||
1048 | |||
1049 | f->fr_mr = ib_alloc_fast_reg_mr(ia->ri_pd, | ||
1050 | ia->ri_max_frmr_depth); | ||
1051 | if (IS_ERR(f->fr_mr)) { | ||
1052 | rc = PTR_ERR(f->fr_mr); | ||
1053 | dprintk("RPC: %s: ib_alloc_fast_reg_mr " | ||
1054 | "failed %i\n", __func__, rc); | ||
1055 | goto out_free; | ||
1056 | } | ||
1057 | |||
1058 | f->fr_pgl = ib_alloc_fast_reg_page_list(ia->ri_id->device, | ||
1059 | ia->ri_max_frmr_depth); | ||
1060 | if (IS_ERR(f->fr_pgl)) { | ||
1061 | rc = PTR_ERR(f->fr_pgl); | ||
1062 | dprintk("RPC: %s: ib_alloc_fast_reg_page_list " | ||
1063 | "failed %i\n", __func__, rc); | ||
1064 | |||
1065 | ib_dereg_mr(f->fr_mr); | ||
1066 | goto out_free; | ||
1067 | } | ||
1068 | |||
1069 | list_add(&r->mw_list, &buf->rb_mws); | ||
1070 | list_add(&r->mw_all, &buf->rb_all); | ||
1071 | } | ||
1072 | |||
1073 | return 0; | ||
1074 | |||
1075 | out_free: | ||
1076 | kfree(r); | ||
995 | return rc; | 1077 | return rc; |
996 | } | 1078 | } |
997 | 1079 | ||
998 | /* | ||
999 | * Initialize buffer memory | ||
1000 | */ | ||
1001 | int | 1080 | int |
1002 | rpcrdma_buffer_create(struct rpcrdma_buffer *buf, struct rpcrdma_ep *ep, | 1081 | rpcrdma_buffer_create(struct rpcrdma_buffer *buf, struct rpcrdma_ep *ep, |
1003 | struct rpcrdma_ia *ia, struct rpcrdma_create_data_internal *cdata) | 1082 | struct rpcrdma_ia *ia, struct rpcrdma_create_data_internal *cdata) |
@@ -1005,7 +1084,6 @@ rpcrdma_buffer_create(struct rpcrdma_buffer *buf, struct rpcrdma_ep *ep, | |||
1005 | char *p; | 1084 | char *p; |
1006 | size_t len, rlen, wlen; | 1085 | size_t len, rlen, wlen; |
1007 | int i, rc; | 1086 | int i, rc; |
1008 | struct rpcrdma_mw *r; | ||
1009 | 1087 | ||
1010 | buf->rb_max_requests = cdata->max_requests; | 1088 | buf->rb_max_requests = cdata->max_requests; |
1011 | spin_lock_init(&buf->rb_lock); | 1089 | spin_lock_init(&buf->rb_lock); |
@@ -1016,28 +1094,12 @@ rpcrdma_buffer_create(struct rpcrdma_buffer *buf, struct rpcrdma_ep *ep, | |||
1016 | * 2. arrays of struct rpcrdma_req to fill in pointers | 1094 | * 2. arrays of struct rpcrdma_req to fill in pointers |
1017 | * 3. array of struct rpcrdma_rep for replies | 1095 | * 3. array of struct rpcrdma_rep for replies |
1018 | * 4. padding, if any | 1096 | * 4. padding, if any |
1019 | * 5. mw's, fmr's or frmr's, if any | ||
1020 | * Send/recv buffers in req/rep need to be registered | 1097 | * Send/recv buffers in req/rep need to be registered |
1021 | */ | 1098 | */ |
1022 | |||
1023 | len = buf->rb_max_requests * | 1099 | len = buf->rb_max_requests * |
1024 | (sizeof(struct rpcrdma_req *) + sizeof(struct rpcrdma_rep *)); | 1100 | (sizeof(struct rpcrdma_req *) + sizeof(struct rpcrdma_rep *)); |
1025 | len += cdata->padding; | 1101 | len += cdata->padding; |
1026 | switch (ia->ri_memreg_strategy) { | ||
1027 | case RPCRDMA_FRMR: | ||
1028 | len += buf->rb_max_requests * RPCRDMA_MAX_SEGS * | ||
1029 | sizeof(struct rpcrdma_mw); | ||
1030 | break; | ||
1031 | case RPCRDMA_MTHCAFMR: | ||
1032 | /* TBD we are perhaps overallocating here */ | ||
1033 | len += (buf->rb_max_requests + 1) * RPCRDMA_MAX_SEGS * | ||
1034 | sizeof(struct rpcrdma_mw); | ||
1035 | break; | ||
1036 | default: | ||
1037 | break; | ||
1038 | } | ||
1039 | 1102 | ||
1040 | /* allocate 1, 4 and 5 in one shot */ | ||
1041 | p = kzalloc(len, GFP_KERNEL); | 1103 | p = kzalloc(len, GFP_KERNEL); |
1042 | if (p == NULL) { | 1104 | if (p == NULL) { |
1043 | dprintk("RPC: %s: req_t/rep_t/pad kzalloc(%zd) failed\n", | 1105 | dprintk("RPC: %s: req_t/rep_t/pad kzalloc(%zd) failed\n", |
@@ -1064,51 +1126,17 @@ rpcrdma_buffer_create(struct rpcrdma_buffer *buf, struct rpcrdma_ep *ep, | |||
1064 | p += cdata->padding; | 1126 | p += cdata->padding; |
1065 | 1127 | ||
1066 | INIT_LIST_HEAD(&buf->rb_mws); | 1128 | INIT_LIST_HEAD(&buf->rb_mws); |
1067 | r = (struct rpcrdma_mw *)p; | 1129 | INIT_LIST_HEAD(&buf->rb_all); |
1068 | switch (ia->ri_memreg_strategy) { | 1130 | switch (ia->ri_memreg_strategy) { |
1069 | case RPCRDMA_FRMR: | 1131 | case RPCRDMA_FRMR: |
1070 | for (i = buf->rb_max_requests * RPCRDMA_MAX_SEGS; i; i--) { | 1132 | rc = rpcrdma_init_frmrs(ia, buf); |
1071 | r->r.frmr.fr_mr = ib_alloc_fast_reg_mr(ia->ri_pd, | 1133 | if (rc) |
1072 | ia->ri_max_frmr_depth); | 1134 | goto out; |
1073 | if (IS_ERR(r->r.frmr.fr_mr)) { | ||
1074 | rc = PTR_ERR(r->r.frmr.fr_mr); | ||
1075 | dprintk("RPC: %s: ib_alloc_fast_reg_mr" | ||
1076 | " failed %i\n", __func__, rc); | ||
1077 | goto out; | ||
1078 | } | ||
1079 | r->r.frmr.fr_pgl = ib_alloc_fast_reg_page_list( | ||
1080 | ia->ri_id->device, | ||
1081 | ia->ri_max_frmr_depth); | ||
1082 | if (IS_ERR(r->r.frmr.fr_pgl)) { | ||
1083 | rc = PTR_ERR(r->r.frmr.fr_pgl); | ||
1084 | dprintk("RPC: %s: " | ||
1085 | "ib_alloc_fast_reg_page_list " | ||
1086 | "failed %i\n", __func__, rc); | ||
1087 | |||
1088 | ib_dereg_mr(r->r.frmr.fr_mr); | ||
1089 | goto out; | ||
1090 | } | ||
1091 | list_add(&r->mw_list, &buf->rb_mws); | ||
1092 | ++r; | ||
1093 | } | ||
1094 | break; | 1135 | break; |
1095 | case RPCRDMA_MTHCAFMR: | 1136 | case RPCRDMA_MTHCAFMR: |
1096 | /* TBD we are perhaps overallocating here */ | 1137 | rc = rpcrdma_init_fmrs(ia, buf); |
1097 | for (i = (buf->rb_max_requests+1) * RPCRDMA_MAX_SEGS; i; i--) { | 1138 | if (rc) |
1098 | static struct ib_fmr_attr fa = | 1139 | goto out; |
1099 | { RPCRDMA_MAX_DATA_SEGS, 1, PAGE_SHIFT }; | ||
1100 | r->r.fmr = ib_alloc_fmr(ia->ri_pd, | ||
1101 | IB_ACCESS_REMOTE_WRITE | IB_ACCESS_REMOTE_READ, | ||
1102 | &fa); | ||
1103 | if (IS_ERR(r->r.fmr)) { | ||
1104 | rc = PTR_ERR(r->r.fmr); | ||
1105 | dprintk("RPC: %s: ib_alloc_fmr" | ||
1106 | " failed %i\n", __func__, rc); | ||
1107 | goto out; | ||
1108 | } | ||
1109 | list_add(&r->mw_list, &buf->rb_mws); | ||
1110 | ++r; | ||
1111 | } | ||
1112 | break; | 1140 | break; |
1113 | default: | 1141 | default: |
1114 | break; | 1142 | break; |
@@ -1176,24 +1204,57 @@ out: | |||
1176 | return rc; | 1204 | return rc; |
1177 | } | 1205 | } |
1178 | 1206 | ||
1179 | /* | 1207 | static void |
1180 | * Unregister and destroy buffer memory. Need to deal with | 1208 | rpcrdma_destroy_fmrs(struct rpcrdma_buffer *buf) |
1181 | * partial initialization, so it's callable from failed create. | 1209 | { |
1182 | * Must be called before destroying endpoint, as registrations | 1210 | struct rpcrdma_mw *r; |
1183 | * reference it. | 1211 | int rc; |
1184 | */ | 1212 | |
1213 | while (!list_empty(&buf->rb_all)) { | ||
1214 | r = list_entry(buf->rb_all.next, struct rpcrdma_mw, mw_all); | ||
1215 | list_del(&r->mw_all); | ||
1216 | list_del(&r->mw_list); | ||
1217 | |||
1218 | rc = ib_dealloc_fmr(r->r.fmr); | ||
1219 | if (rc) | ||
1220 | dprintk("RPC: %s: ib_dealloc_fmr failed %i\n", | ||
1221 | __func__, rc); | ||
1222 | |||
1223 | kfree(r); | ||
1224 | } | ||
1225 | } | ||
1226 | |||
1227 | static void | ||
1228 | rpcrdma_destroy_frmrs(struct rpcrdma_buffer *buf) | ||
1229 | { | ||
1230 | struct rpcrdma_mw *r; | ||
1231 | int rc; | ||
1232 | |||
1233 | while (!list_empty(&buf->rb_all)) { | ||
1234 | r = list_entry(buf->rb_all.next, struct rpcrdma_mw, mw_all); | ||
1235 | list_del(&r->mw_all); | ||
1236 | list_del(&r->mw_list); | ||
1237 | |||
1238 | rc = ib_dereg_mr(r->r.frmr.fr_mr); | ||
1239 | if (rc) | ||
1240 | dprintk("RPC: %s: ib_dereg_mr failed %i\n", | ||
1241 | __func__, rc); | ||
1242 | ib_free_fast_reg_page_list(r->r.frmr.fr_pgl); | ||
1243 | |||
1244 | kfree(r); | ||
1245 | } | ||
1246 | } | ||
1247 | |||
1185 | void | 1248 | void |
1186 | rpcrdma_buffer_destroy(struct rpcrdma_buffer *buf) | 1249 | rpcrdma_buffer_destroy(struct rpcrdma_buffer *buf) |
1187 | { | 1250 | { |
1188 | int rc, i; | ||
1189 | struct rpcrdma_ia *ia = rdmab_to_ia(buf); | 1251 | struct rpcrdma_ia *ia = rdmab_to_ia(buf); |
1190 | struct rpcrdma_mw *r; | 1252 | int i; |
1191 | 1253 | ||
1192 | /* clean up in reverse order from create | 1254 | /* clean up in reverse order from create |
1193 | * 1. recv mr memory (mr free, then kfree) | 1255 | * 1. recv mr memory (mr free, then kfree) |
1194 | * 2. send mr memory (mr free, then kfree) | 1256 | * 2. send mr memory (mr free, then kfree) |
1195 | * 3. padding (if any) [moved to rpcrdma_ep_destroy] | 1257 | * 3. MWs |
1196 | * 4. arrays | ||
1197 | */ | 1258 | */ |
1198 | dprintk("RPC: %s: entering\n", __func__); | 1259 | dprintk("RPC: %s: entering\n", __func__); |
1199 | 1260 | ||
@@ -1212,34 +1273,217 @@ rpcrdma_buffer_destroy(struct rpcrdma_buffer *buf) | |||
1212 | } | 1273 | } |
1213 | } | 1274 | } |
1214 | 1275 | ||
1276 | switch (ia->ri_memreg_strategy) { | ||
1277 | case RPCRDMA_FRMR: | ||
1278 | rpcrdma_destroy_frmrs(buf); | ||
1279 | break; | ||
1280 | case RPCRDMA_MTHCAFMR: | ||
1281 | rpcrdma_destroy_fmrs(buf); | ||
1282 | break; | ||
1283 | default: | ||
1284 | break; | ||
1285 | } | ||
1286 | |||
1287 | kfree(buf->rb_pool); | ||
1288 | } | ||
1289 | |||
1290 | /* After a disconnect, a flushed FAST_REG_MR can leave an FRMR in | ||
1291 | * an unusable state. Find FRMRs in this state and dereg / reg | ||
1292 | * each. FRMRs that are VALID and attached to an rpcrdma_req are | ||
1293 | * also torn down. | ||
1294 | * | ||
1295 | * This gives all in-use FRMRs a fresh rkey and leaves them INVALID. | ||
1296 | * | ||
1297 | * This is invoked only in the transport connect worker in order | ||
1298 | * to serialize with rpcrdma_register_frmr_external(). | ||
1299 | */ | ||
1300 | static void | ||
1301 | rpcrdma_reset_frmrs(struct rpcrdma_ia *ia) | ||
1302 | { | ||
1303 | struct rpcrdma_xprt *r_xprt = | ||
1304 | container_of(ia, struct rpcrdma_xprt, rx_ia); | ||
1305 | struct rpcrdma_buffer *buf = &r_xprt->rx_buf; | ||
1306 | struct list_head *pos; | ||
1307 | struct rpcrdma_mw *r; | ||
1308 | int rc; | ||
1309 | |||
1310 | list_for_each(pos, &buf->rb_all) { | ||
1311 | r = list_entry(pos, struct rpcrdma_mw, mw_all); | ||
1312 | |||
1313 | if (r->r.frmr.fr_state == FRMR_IS_INVALID) | ||
1314 | continue; | ||
1315 | |||
1316 | rc = ib_dereg_mr(r->r.frmr.fr_mr); | ||
1317 | if (rc) | ||
1318 | dprintk("RPC: %s: ib_dereg_mr failed %i\n", | ||
1319 | __func__, rc); | ||
1320 | ib_free_fast_reg_page_list(r->r.frmr.fr_pgl); | ||
1321 | |||
1322 | r->r.frmr.fr_mr = ib_alloc_fast_reg_mr(ia->ri_pd, | ||
1323 | ia->ri_max_frmr_depth); | ||
1324 | if (IS_ERR(r->r.frmr.fr_mr)) { | ||
1325 | rc = PTR_ERR(r->r.frmr.fr_mr); | ||
1326 | dprintk("RPC: %s: ib_alloc_fast_reg_mr" | ||
1327 | " failed %i\n", __func__, rc); | ||
1328 | continue; | ||
1329 | } | ||
1330 | r->r.frmr.fr_pgl = ib_alloc_fast_reg_page_list( | ||
1331 | ia->ri_id->device, | ||
1332 | ia->ri_max_frmr_depth); | ||
1333 | if (IS_ERR(r->r.frmr.fr_pgl)) { | ||
1334 | rc = PTR_ERR(r->r.frmr.fr_pgl); | ||
1335 | dprintk("RPC: %s: " | ||
1336 | "ib_alloc_fast_reg_page_list " | ||
1337 | "failed %i\n", __func__, rc); | ||
1338 | |||
1339 | ib_dereg_mr(r->r.frmr.fr_mr); | ||
1340 | continue; | ||
1341 | } | ||
1342 | r->r.frmr.fr_state = FRMR_IS_INVALID; | ||
1343 | } | ||
1344 | } | ||
1345 | |||
1346 | /* "*mw" can be NULL when rpcrdma_buffer_get_mrs() fails, leaving | ||
1347 | * some req segments uninitialized. | ||
1348 | */ | ||
1349 | static void | ||
1350 | rpcrdma_buffer_put_mr(struct rpcrdma_mw **mw, struct rpcrdma_buffer *buf) | ||
1351 | { | ||
1352 | if (*mw) { | ||
1353 | list_add_tail(&(*mw)->mw_list, &buf->rb_mws); | ||
1354 | *mw = NULL; | ||
1355 | } | ||
1356 | } | ||
1357 | |||
1358 | /* Cycle mw's back in reverse order, and "spin" them. | ||
1359 | * This delays and scrambles reuse as much as possible. | ||
1360 | */ | ||
1361 | static void | ||
1362 | rpcrdma_buffer_put_mrs(struct rpcrdma_req *req, struct rpcrdma_buffer *buf) | ||
1363 | { | ||
1364 | struct rpcrdma_mr_seg *seg = req->rl_segments; | ||
1365 | struct rpcrdma_mr_seg *seg1 = seg; | ||
1366 | int i; | ||
1367 | |||
1368 | for (i = 1, seg++; i < RPCRDMA_MAX_SEGS; seg++, i++) | ||
1369 | rpcrdma_buffer_put_mr(&seg->mr_chunk.rl_mw, buf); | ||
1370 | rpcrdma_buffer_put_mr(&seg1->mr_chunk.rl_mw, buf); | ||
1371 | } | ||
1372 | |||
1373 | static void | ||
1374 | rpcrdma_buffer_put_sendbuf(struct rpcrdma_req *req, struct rpcrdma_buffer *buf) | ||
1375 | { | ||
1376 | buf->rb_send_bufs[--buf->rb_send_index] = req; | ||
1377 | req->rl_niovs = 0; | ||
1378 | if (req->rl_reply) { | ||
1379 | buf->rb_recv_bufs[--buf->rb_recv_index] = req->rl_reply; | ||
1380 | req->rl_reply->rr_func = NULL; | ||
1381 | req->rl_reply = NULL; | ||
1382 | } | ||
1383 | } | ||
1384 | |||
1385 | /* rpcrdma_unmap_one() was already done by rpcrdma_deregister_frmr_external(). | ||
1386 | * Redo only the ib_post_send(). | ||
1387 | */ | ||
1388 | static void | ||
1389 | rpcrdma_retry_local_inv(struct rpcrdma_mw *r, struct rpcrdma_ia *ia) | ||
1390 | { | ||
1391 | struct rpcrdma_xprt *r_xprt = | ||
1392 | container_of(ia, struct rpcrdma_xprt, rx_ia); | ||
1393 | struct ib_send_wr invalidate_wr, *bad_wr; | ||
1394 | int rc; | ||
1395 | |||
1396 | dprintk("RPC: %s: FRMR %p is stale\n", __func__, r); | ||
1397 | |||
1398 | /* When this FRMR is re-inserted into rb_mws, it is no longer stale */ | ||
1399 | r->r.frmr.fr_state = FRMR_IS_INVALID; | ||
1400 | |||
1401 | memset(&invalidate_wr, 0, sizeof(invalidate_wr)); | ||
1402 | invalidate_wr.wr_id = (unsigned long)(void *)r; | ||
1403 | invalidate_wr.opcode = IB_WR_LOCAL_INV; | ||
1404 | invalidate_wr.ex.invalidate_rkey = r->r.frmr.fr_mr->rkey; | ||
1405 | DECR_CQCOUNT(&r_xprt->rx_ep); | ||
1406 | |||
1407 | dprintk("RPC: %s: frmr %p invalidating rkey %08x\n", | ||
1408 | __func__, r, r->r.frmr.fr_mr->rkey); | ||
1409 | |||
1410 | read_lock(&ia->ri_qplock); | ||
1411 | rc = ib_post_send(ia->ri_id->qp, &invalidate_wr, &bad_wr); | ||
1412 | read_unlock(&ia->ri_qplock); | ||
1413 | if (rc) { | ||
1414 | /* Force rpcrdma_buffer_get() to retry */ | ||
1415 | r->r.frmr.fr_state = FRMR_IS_STALE; | ||
1416 | dprintk("RPC: %s: ib_post_send failed, %i\n", | ||
1417 | __func__, rc); | ||
1418 | } | ||
1419 | } | ||
1420 | |||
1421 | static void | ||
1422 | rpcrdma_retry_flushed_linv(struct list_head *stale, | ||
1423 | struct rpcrdma_buffer *buf) | ||
1424 | { | ||
1425 | struct rpcrdma_ia *ia = rdmab_to_ia(buf); | ||
1426 | struct list_head *pos; | ||
1427 | struct rpcrdma_mw *r; | ||
1428 | unsigned long flags; | ||
1429 | |||
1430 | list_for_each(pos, stale) { | ||
1431 | r = list_entry(pos, struct rpcrdma_mw, mw_list); | ||
1432 | rpcrdma_retry_local_inv(r, ia); | ||
1433 | } | ||
1434 | |||
1435 | spin_lock_irqsave(&buf->rb_lock, flags); | ||
1436 | list_splice_tail(stale, &buf->rb_mws); | ||
1437 | spin_unlock_irqrestore(&buf->rb_lock, flags); | ||
1438 | } | ||
1439 | |||
1440 | static struct rpcrdma_req * | ||
1441 | rpcrdma_buffer_get_frmrs(struct rpcrdma_req *req, struct rpcrdma_buffer *buf, | ||
1442 | struct list_head *stale) | ||
1443 | { | ||
1444 | struct rpcrdma_mw *r; | ||
1445 | int i; | ||
1446 | |||
1447 | i = RPCRDMA_MAX_SEGS - 1; | ||
1215 | while (!list_empty(&buf->rb_mws)) { | 1448 | while (!list_empty(&buf->rb_mws)) { |
1216 | r = list_entry(buf->rb_mws.next, | 1449 | r = list_entry(buf->rb_mws.next, |
1217 | struct rpcrdma_mw, mw_list); | 1450 | struct rpcrdma_mw, mw_list); |
1218 | list_del(&r->mw_list); | 1451 | list_del(&r->mw_list); |
1219 | switch (ia->ri_memreg_strategy) { | 1452 | if (r->r.frmr.fr_state == FRMR_IS_STALE) { |
1220 | case RPCRDMA_FRMR: | 1453 | list_add(&r->mw_list, stale); |
1221 | rc = ib_dereg_mr(r->r.frmr.fr_mr); | 1454 | continue; |
1222 | if (rc) | ||
1223 | dprintk("RPC: %s:" | ||
1224 | " ib_dereg_mr" | ||
1225 | " failed %i\n", | ||
1226 | __func__, rc); | ||
1227 | ib_free_fast_reg_page_list(r->r.frmr.fr_pgl); | ||
1228 | break; | ||
1229 | case RPCRDMA_MTHCAFMR: | ||
1230 | rc = ib_dealloc_fmr(r->r.fmr); | ||
1231 | if (rc) | ||
1232 | dprintk("RPC: %s:" | ||
1233 | " ib_dealloc_fmr" | ||
1234 | " failed %i\n", | ||
1235 | __func__, rc); | ||
1236 | break; | ||
1237 | default: | ||
1238 | break; | ||
1239 | } | 1455 | } |
1456 | req->rl_segments[i].mr_chunk.rl_mw = r; | ||
1457 | if (unlikely(i-- == 0)) | ||
1458 | return req; /* Success */ | ||
1240 | } | 1459 | } |
1241 | 1460 | ||
1242 | kfree(buf->rb_pool); | 1461 | /* Not enough entries on rb_mws for this req */ |
1462 | rpcrdma_buffer_put_sendbuf(req, buf); | ||
1463 | rpcrdma_buffer_put_mrs(req, buf); | ||
1464 | return NULL; | ||
1465 | } | ||
1466 | |||
1467 | static struct rpcrdma_req * | ||
1468 | rpcrdma_buffer_get_fmrs(struct rpcrdma_req *req, struct rpcrdma_buffer *buf) | ||
1469 | { | ||
1470 | struct rpcrdma_mw *r; | ||
1471 | int i; | ||
1472 | |||
1473 | i = RPCRDMA_MAX_SEGS - 1; | ||
1474 | while (!list_empty(&buf->rb_mws)) { | ||
1475 | r = list_entry(buf->rb_mws.next, | ||
1476 | struct rpcrdma_mw, mw_list); | ||
1477 | list_del(&r->mw_list); | ||
1478 | req->rl_segments[i].mr_chunk.rl_mw = r; | ||
1479 | if (unlikely(i-- == 0)) | ||
1480 | return req; /* Success */ | ||
1481 | } | ||
1482 | |||
1483 | /* Not enough entries on rb_mws for this req */ | ||
1484 | rpcrdma_buffer_put_sendbuf(req, buf); | ||
1485 | rpcrdma_buffer_put_mrs(req, buf); | ||
1486 | return NULL; | ||
1243 | } | 1487 | } |
1244 | 1488 | ||
1245 | /* | 1489 | /* |
@@ -1254,10 +1498,10 @@ rpcrdma_buffer_destroy(struct rpcrdma_buffer *buf) | |||
1254 | struct rpcrdma_req * | 1498 | struct rpcrdma_req * |
1255 | rpcrdma_buffer_get(struct rpcrdma_buffer *buffers) | 1499 | rpcrdma_buffer_get(struct rpcrdma_buffer *buffers) |
1256 | { | 1500 | { |
1501 | struct rpcrdma_ia *ia = rdmab_to_ia(buffers); | ||
1502 | struct list_head stale; | ||
1257 | struct rpcrdma_req *req; | 1503 | struct rpcrdma_req *req; |
1258 | unsigned long flags; | 1504 | unsigned long flags; |
1259 | int i; | ||
1260 | struct rpcrdma_mw *r; | ||
1261 | 1505 | ||
1262 | spin_lock_irqsave(&buffers->rb_lock, flags); | 1506 | spin_lock_irqsave(&buffers->rb_lock, flags); |
1263 | if (buffers->rb_send_index == buffers->rb_max_requests) { | 1507 | if (buffers->rb_send_index == buffers->rb_max_requests) { |
@@ -1277,16 +1521,21 @@ rpcrdma_buffer_get(struct rpcrdma_buffer *buffers) | |||
1277 | buffers->rb_recv_bufs[buffers->rb_recv_index++] = NULL; | 1521 | buffers->rb_recv_bufs[buffers->rb_recv_index++] = NULL; |
1278 | } | 1522 | } |
1279 | buffers->rb_send_bufs[buffers->rb_send_index++] = NULL; | 1523 | buffers->rb_send_bufs[buffers->rb_send_index++] = NULL; |
1280 | if (!list_empty(&buffers->rb_mws)) { | 1524 | |
1281 | i = RPCRDMA_MAX_SEGS - 1; | 1525 | INIT_LIST_HEAD(&stale); |
1282 | do { | 1526 | switch (ia->ri_memreg_strategy) { |
1283 | r = list_entry(buffers->rb_mws.next, | 1527 | case RPCRDMA_FRMR: |
1284 | struct rpcrdma_mw, mw_list); | 1528 | req = rpcrdma_buffer_get_frmrs(req, buffers, &stale); |
1285 | list_del(&r->mw_list); | 1529 | break; |
1286 | req->rl_segments[i].mr_chunk.rl_mw = r; | 1530 | case RPCRDMA_MTHCAFMR: |
1287 | } while (--i >= 0); | 1531 | req = rpcrdma_buffer_get_fmrs(req, buffers); |
1532 | break; | ||
1533 | default: | ||
1534 | break; | ||
1288 | } | 1535 | } |
1289 | spin_unlock_irqrestore(&buffers->rb_lock, flags); | 1536 | spin_unlock_irqrestore(&buffers->rb_lock, flags); |
1537 | if (!list_empty(&stale)) | ||
1538 | rpcrdma_retry_flushed_linv(&stale, buffers); | ||
1290 | return req; | 1539 | return req; |
1291 | } | 1540 | } |
1292 | 1541 | ||
@@ -1299,34 +1548,14 @@ rpcrdma_buffer_put(struct rpcrdma_req *req) | |||
1299 | { | 1548 | { |
1300 | struct rpcrdma_buffer *buffers = req->rl_buffer; | 1549 | struct rpcrdma_buffer *buffers = req->rl_buffer; |
1301 | struct rpcrdma_ia *ia = rdmab_to_ia(buffers); | 1550 | struct rpcrdma_ia *ia = rdmab_to_ia(buffers); |
1302 | int i; | ||
1303 | unsigned long flags; | 1551 | unsigned long flags; |
1304 | 1552 | ||
1305 | spin_lock_irqsave(&buffers->rb_lock, flags); | 1553 | spin_lock_irqsave(&buffers->rb_lock, flags); |
1306 | buffers->rb_send_bufs[--buffers->rb_send_index] = req; | 1554 | rpcrdma_buffer_put_sendbuf(req, buffers); |
1307 | req->rl_niovs = 0; | ||
1308 | if (req->rl_reply) { | ||
1309 | buffers->rb_recv_bufs[--buffers->rb_recv_index] = req->rl_reply; | ||
1310 | req->rl_reply->rr_func = NULL; | ||
1311 | req->rl_reply = NULL; | ||
1312 | } | ||
1313 | switch (ia->ri_memreg_strategy) { | 1555 | switch (ia->ri_memreg_strategy) { |
1314 | case RPCRDMA_FRMR: | 1556 | case RPCRDMA_FRMR: |
1315 | case RPCRDMA_MTHCAFMR: | 1557 | case RPCRDMA_MTHCAFMR: |
1316 | /* | 1558 | rpcrdma_buffer_put_mrs(req, buffers); |
1317 | * Cycle mw's back in reverse order, and "spin" them. | ||
1318 | * This delays and scrambles reuse as much as possible. | ||
1319 | */ | ||
1320 | i = 1; | ||
1321 | do { | ||
1322 | struct rpcrdma_mw **mw; | ||
1323 | mw = &req->rl_segments[i].mr_chunk.rl_mw; | ||
1324 | list_add_tail(&(*mw)->mw_list, &buffers->rb_mws); | ||
1325 | *mw = NULL; | ||
1326 | } while (++i < RPCRDMA_MAX_SEGS); | ||
1327 | list_add_tail(&req->rl_segments[0].mr_chunk.rl_mw->mw_list, | ||
1328 | &buffers->rb_mws); | ||
1329 | req->rl_segments[0].mr_chunk.rl_mw = NULL; | ||
1330 | break; | 1559 | break; |
1331 | default: | 1560 | default: |
1332 | break; | 1561 | break; |
@@ -1388,6 +1617,9 @@ rpcrdma_register_internal(struct rpcrdma_ia *ia, void *va, int len, | |||
1388 | */ | 1617 | */ |
1389 | iov->addr = ib_dma_map_single(ia->ri_id->device, | 1618 | iov->addr = ib_dma_map_single(ia->ri_id->device, |
1390 | va, len, DMA_BIDIRECTIONAL); | 1619 | va, len, DMA_BIDIRECTIONAL); |
1620 | if (ib_dma_mapping_error(ia->ri_id->device, iov->addr)) | ||
1621 | return -ENOMEM; | ||
1622 | |||
1391 | iov->length = len; | 1623 | iov->length = len; |
1392 | 1624 | ||
1393 | if (ia->ri_have_dma_lkey) { | 1625 | if (ia->ri_have_dma_lkey) { |
@@ -1483,8 +1715,10 @@ rpcrdma_register_frmr_external(struct rpcrdma_mr_seg *seg, | |||
1483 | struct rpcrdma_xprt *r_xprt) | 1715 | struct rpcrdma_xprt *r_xprt) |
1484 | { | 1716 | { |
1485 | struct rpcrdma_mr_seg *seg1 = seg; | 1717 | struct rpcrdma_mr_seg *seg1 = seg; |
1486 | struct ib_send_wr invalidate_wr, frmr_wr, *bad_wr, *post_wr; | 1718 | struct rpcrdma_mw *mw = seg1->mr_chunk.rl_mw; |
1487 | 1719 | struct rpcrdma_frmr *frmr = &mw->r.frmr; | |
1720 | struct ib_mr *mr = frmr->fr_mr; | ||
1721 | struct ib_send_wr fastreg_wr, *bad_wr; | ||
1488 | u8 key; | 1722 | u8 key; |
1489 | int len, pageoff; | 1723 | int len, pageoff; |
1490 | int i, rc; | 1724 | int i, rc; |
@@ -1502,8 +1736,7 @@ rpcrdma_register_frmr_external(struct rpcrdma_mr_seg *seg, | |||
1502 | rpcrdma_map_one(ia, seg, writing); | 1736 | rpcrdma_map_one(ia, seg, writing); |
1503 | pa = seg->mr_dma; | 1737 | pa = seg->mr_dma; |
1504 | for (seg_len = seg->mr_len; seg_len > 0; seg_len -= PAGE_SIZE) { | 1738 | for (seg_len = seg->mr_len; seg_len > 0; seg_len -= PAGE_SIZE) { |
1505 | seg1->mr_chunk.rl_mw->r.frmr.fr_pgl-> | 1739 | frmr->fr_pgl->page_list[page_no++] = pa; |
1506 | page_list[page_no++] = pa; | ||
1507 | pa += PAGE_SIZE; | 1740 | pa += PAGE_SIZE; |
1508 | } | 1741 | } |
1509 | len += seg->mr_len; | 1742 | len += seg->mr_len; |
@@ -1515,65 +1748,51 @@ rpcrdma_register_frmr_external(struct rpcrdma_mr_seg *seg, | |||
1515 | break; | 1748 | break; |
1516 | } | 1749 | } |
1517 | dprintk("RPC: %s: Using frmr %p to map %d segments\n", | 1750 | dprintk("RPC: %s: Using frmr %p to map %d segments\n", |
1518 | __func__, seg1->mr_chunk.rl_mw, i); | 1751 | __func__, mw, i); |
1519 | 1752 | ||
1520 | if (unlikely(seg1->mr_chunk.rl_mw->r.frmr.state == FRMR_IS_VALID)) { | 1753 | frmr->fr_state = FRMR_IS_VALID; |
1521 | dprintk("RPC: %s: frmr %x left valid, posting invalidate.\n", | 1754 | |
1522 | __func__, | 1755 | memset(&fastreg_wr, 0, sizeof(fastreg_wr)); |
1523 | seg1->mr_chunk.rl_mw->r.frmr.fr_mr->rkey); | 1756 | fastreg_wr.wr_id = (unsigned long)(void *)mw; |
1524 | /* Invalidate before using. */ | 1757 | fastreg_wr.opcode = IB_WR_FAST_REG_MR; |
1525 | memset(&invalidate_wr, 0, sizeof invalidate_wr); | 1758 | fastreg_wr.wr.fast_reg.iova_start = seg1->mr_dma; |
1526 | invalidate_wr.wr_id = (unsigned long)(void *)seg1->mr_chunk.rl_mw; | 1759 | fastreg_wr.wr.fast_reg.page_list = frmr->fr_pgl; |
1527 | invalidate_wr.next = &frmr_wr; | 1760 | fastreg_wr.wr.fast_reg.page_list_len = page_no; |
1528 | invalidate_wr.opcode = IB_WR_LOCAL_INV; | 1761 | fastreg_wr.wr.fast_reg.page_shift = PAGE_SHIFT; |
1529 | invalidate_wr.send_flags = IB_SEND_SIGNALED; | 1762 | fastreg_wr.wr.fast_reg.length = page_no << PAGE_SHIFT; |
1530 | invalidate_wr.ex.invalidate_rkey = | 1763 | if (fastreg_wr.wr.fast_reg.length < len) { |
1531 | seg1->mr_chunk.rl_mw->r.frmr.fr_mr->rkey; | 1764 | rc = -EIO; |
1532 | DECR_CQCOUNT(&r_xprt->rx_ep); | 1765 | goto out_err; |
1533 | post_wr = &invalidate_wr; | ||
1534 | } else | ||
1535 | post_wr = &frmr_wr; | ||
1536 | |||
1537 | /* Prepare FRMR WR */ | ||
1538 | memset(&frmr_wr, 0, sizeof frmr_wr); | ||
1539 | frmr_wr.wr_id = (unsigned long)(void *)seg1->mr_chunk.rl_mw; | ||
1540 | frmr_wr.opcode = IB_WR_FAST_REG_MR; | ||
1541 | frmr_wr.send_flags = IB_SEND_SIGNALED; | ||
1542 | frmr_wr.wr.fast_reg.iova_start = seg1->mr_dma; | ||
1543 | frmr_wr.wr.fast_reg.page_list = seg1->mr_chunk.rl_mw->r.frmr.fr_pgl; | ||
1544 | frmr_wr.wr.fast_reg.page_list_len = page_no; | ||
1545 | frmr_wr.wr.fast_reg.page_shift = PAGE_SHIFT; | ||
1546 | frmr_wr.wr.fast_reg.length = page_no << PAGE_SHIFT; | ||
1547 | if (frmr_wr.wr.fast_reg.length < len) { | ||
1548 | while (seg1->mr_nsegs--) | ||
1549 | rpcrdma_unmap_one(ia, seg++); | ||
1550 | return -EIO; | ||
1551 | } | 1766 | } |
1552 | 1767 | ||
1553 | /* Bump the key */ | 1768 | /* Bump the key */ |
1554 | key = (u8)(seg1->mr_chunk.rl_mw->r.frmr.fr_mr->rkey & 0x000000FF); | 1769 | key = (u8)(mr->rkey & 0x000000FF); |
1555 | ib_update_fast_reg_key(seg1->mr_chunk.rl_mw->r.frmr.fr_mr, ++key); | 1770 | ib_update_fast_reg_key(mr, ++key); |
1556 | 1771 | ||
1557 | frmr_wr.wr.fast_reg.access_flags = (writing ? | 1772 | fastreg_wr.wr.fast_reg.access_flags = (writing ? |
1558 | IB_ACCESS_REMOTE_WRITE | IB_ACCESS_LOCAL_WRITE : | 1773 | IB_ACCESS_REMOTE_WRITE | IB_ACCESS_LOCAL_WRITE : |
1559 | IB_ACCESS_REMOTE_READ); | 1774 | IB_ACCESS_REMOTE_READ); |
1560 | frmr_wr.wr.fast_reg.rkey = seg1->mr_chunk.rl_mw->r.frmr.fr_mr->rkey; | 1775 | fastreg_wr.wr.fast_reg.rkey = mr->rkey; |
1561 | DECR_CQCOUNT(&r_xprt->rx_ep); | 1776 | DECR_CQCOUNT(&r_xprt->rx_ep); |
1562 | 1777 | ||
1563 | rc = ib_post_send(ia->ri_id->qp, post_wr, &bad_wr); | 1778 | rc = ib_post_send(ia->ri_id->qp, &fastreg_wr, &bad_wr); |
1564 | |||
1565 | if (rc) { | 1779 | if (rc) { |
1566 | dprintk("RPC: %s: failed ib_post_send for register," | 1780 | dprintk("RPC: %s: failed ib_post_send for register," |
1567 | " status %i\n", __func__, rc); | 1781 | " status %i\n", __func__, rc); |
1568 | while (i--) | 1782 | ib_update_fast_reg_key(mr, --key); |
1569 | rpcrdma_unmap_one(ia, --seg); | 1783 | goto out_err; |
1570 | } else { | 1784 | } else { |
1571 | seg1->mr_rkey = seg1->mr_chunk.rl_mw->r.frmr.fr_mr->rkey; | 1785 | seg1->mr_rkey = mr->rkey; |
1572 | seg1->mr_base = seg1->mr_dma + pageoff; | 1786 | seg1->mr_base = seg1->mr_dma + pageoff; |
1573 | seg1->mr_nsegs = i; | 1787 | seg1->mr_nsegs = i; |
1574 | seg1->mr_len = len; | 1788 | seg1->mr_len = len; |
1575 | } | 1789 | } |
1576 | *nsegs = i; | 1790 | *nsegs = i; |
1791 | return 0; | ||
1792 | out_err: | ||
1793 | frmr->fr_state = FRMR_IS_INVALID; | ||
1794 | while (i--) | ||
1795 | rpcrdma_unmap_one(ia, --seg); | ||
1577 | return rc; | 1796 | return rc; |
1578 | } | 1797 | } |
1579 | 1798 | ||
@@ -1585,20 +1804,25 @@ rpcrdma_deregister_frmr_external(struct rpcrdma_mr_seg *seg, | |||
1585 | struct ib_send_wr invalidate_wr, *bad_wr; | 1804 | struct ib_send_wr invalidate_wr, *bad_wr; |
1586 | int rc; | 1805 | int rc; |
1587 | 1806 | ||
1588 | while (seg1->mr_nsegs--) | 1807 | seg1->mr_chunk.rl_mw->r.frmr.fr_state = FRMR_IS_INVALID; |
1589 | rpcrdma_unmap_one(ia, seg++); | ||
1590 | 1808 | ||
1591 | memset(&invalidate_wr, 0, sizeof invalidate_wr); | 1809 | memset(&invalidate_wr, 0, sizeof invalidate_wr); |
1592 | invalidate_wr.wr_id = (unsigned long)(void *)seg1->mr_chunk.rl_mw; | 1810 | invalidate_wr.wr_id = (unsigned long)(void *)seg1->mr_chunk.rl_mw; |
1593 | invalidate_wr.opcode = IB_WR_LOCAL_INV; | 1811 | invalidate_wr.opcode = IB_WR_LOCAL_INV; |
1594 | invalidate_wr.send_flags = IB_SEND_SIGNALED; | ||
1595 | invalidate_wr.ex.invalidate_rkey = seg1->mr_chunk.rl_mw->r.frmr.fr_mr->rkey; | 1812 | invalidate_wr.ex.invalidate_rkey = seg1->mr_chunk.rl_mw->r.frmr.fr_mr->rkey; |
1596 | DECR_CQCOUNT(&r_xprt->rx_ep); | 1813 | DECR_CQCOUNT(&r_xprt->rx_ep); |
1597 | 1814 | ||
1815 | read_lock(&ia->ri_qplock); | ||
1816 | while (seg1->mr_nsegs--) | ||
1817 | rpcrdma_unmap_one(ia, seg++); | ||
1598 | rc = ib_post_send(ia->ri_id->qp, &invalidate_wr, &bad_wr); | 1818 | rc = ib_post_send(ia->ri_id->qp, &invalidate_wr, &bad_wr); |
1599 | if (rc) | 1819 | read_unlock(&ia->ri_qplock); |
1820 | if (rc) { | ||
1821 | /* Force rpcrdma_buffer_get() to retry */ | ||
1822 | seg1->mr_chunk.rl_mw->r.frmr.fr_state = FRMR_IS_STALE; | ||
1600 | dprintk("RPC: %s: failed ib_post_send for invalidate," | 1823 | dprintk("RPC: %s: failed ib_post_send for invalidate," |
1601 | " status %i\n", __func__, rc); | 1824 | " status %i\n", __func__, rc); |
1825 | } | ||
1602 | return rc; | 1826 | return rc; |
1603 | } | 1827 | } |
1604 | 1828 | ||
@@ -1656,8 +1880,10 @@ rpcrdma_deregister_fmr_external(struct rpcrdma_mr_seg *seg, | |||
1656 | 1880 | ||
1657 | list_add(&seg1->mr_chunk.rl_mw->r.fmr->list, &l); | 1881 | list_add(&seg1->mr_chunk.rl_mw->r.fmr->list, &l); |
1658 | rc = ib_unmap_fmr(&l); | 1882 | rc = ib_unmap_fmr(&l); |
1883 | read_lock(&ia->ri_qplock); | ||
1659 | while (seg1->mr_nsegs--) | 1884 | while (seg1->mr_nsegs--) |
1660 | rpcrdma_unmap_one(ia, seg++); | 1885 | rpcrdma_unmap_one(ia, seg++); |
1886 | read_unlock(&ia->ri_qplock); | ||
1661 | if (rc) | 1887 | if (rc) |
1662 | dprintk("RPC: %s: failed ib_unmap_fmr," | 1888 | dprintk("RPC: %s: failed ib_unmap_fmr," |
1663 | " status %i\n", __func__, rc); | 1889 | " status %i\n", __func__, rc); |
@@ -1673,7 +1899,6 @@ rpcrdma_register_external(struct rpcrdma_mr_seg *seg, | |||
1673 | 1899 | ||
1674 | switch (ia->ri_memreg_strategy) { | 1900 | switch (ia->ri_memreg_strategy) { |
1675 | 1901 | ||
1676 | #if RPCRDMA_PERSISTENT_REGISTRATION | ||
1677 | case RPCRDMA_ALLPHYSICAL: | 1902 | case RPCRDMA_ALLPHYSICAL: |
1678 | rpcrdma_map_one(ia, seg, writing); | 1903 | rpcrdma_map_one(ia, seg, writing); |
1679 | seg->mr_rkey = ia->ri_bind_mem->rkey; | 1904 | seg->mr_rkey = ia->ri_bind_mem->rkey; |
@@ -1681,7 +1906,6 @@ rpcrdma_register_external(struct rpcrdma_mr_seg *seg, | |||
1681 | seg->mr_nsegs = 1; | 1906 | seg->mr_nsegs = 1; |
1682 | nsegs = 1; | 1907 | nsegs = 1; |
1683 | break; | 1908 | break; |
1684 | #endif | ||
1685 | 1909 | ||
1686 | /* Registration using frmr registration */ | 1910 | /* Registration using frmr registration */ |
1687 | case RPCRDMA_FRMR: | 1911 | case RPCRDMA_FRMR: |
@@ -1711,11 +1935,11 @@ rpcrdma_deregister_external(struct rpcrdma_mr_seg *seg, | |||
1711 | 1935 | ||
1712 | switch (ia->ri_memreg_strategy) { | 1936 | switch (ia->ri_memreg_strategy) { |
1713 | 1937 | ||
1714 | #if RPCRDMA_PERSISTENT_REGISTRATION | ||
1715 | case RPCRDMA_ALLPHYSICAL: | 1938 | case RPCRDMA_ALLPHYSICAL: |
1939 | read_lock(&ia->ri_qplock); | ||
1716 | rpcrdma_unmap_one(ia, seg); | 1940 | rpcrdma_unmap_one(ia, seg); |
1941 | read_unlock(&ia->ri_qplock); | ||
1717 | break; | 1942 | break; |
1718 | #endif | ||
1719 | 1943 | ||
1720 | case RPCRDMA_FRMR: | 1944 | case RPCRDMA_FRMR: |
1721 | rc = rpcrdma_deregister_frmr_external(seg, ia, r_xprt); | 1945 | rc = rpcrdma_deregister_frmr_external(seg, ia, r_xprt); |
@@ -1809,3 +2033,44 @@ rpcrdma_ep_post_recv(struct rpcrdma_ia *ia, | |||
1809 | rc); | 2033 | rc); |
1810 | return rc; | 2034 | return rc; |
1811 | } | 2035 | } |
2036 | |||
2037 | /* Physical mapping means one Read/Write list entry per-page. | ||
2038 | * All list entries must fit within an inline buffer | ||
2039 | * | ||
2040 | * NB: The server must return a Write list for NFS READ, | ||
2041 | * which has the same constraint. Factor in the inline | ||
2042 | * rsize as well. | ||
2043 | */ | ||
2044 | static size_t | ||
2045 | rpcrdma_physical_max_payload(struct rpcrdma_xprt *r_xprt) | ||
2046 | { | ||
2047 | struct rpcrdma_create_data_internal *cdata = &r_xprt->rx_data; | ||
2048 | unsigned int inline_size, pages; | ||
2049 | |||
2050 | inline_size = min_t(unsigned int, | ||
2051 | cdata->inline_wsize, cdata->inline_rsize); | ||
2052 | inline_size -= RPCRDMA_HDRLEN_MIN; | ||
2053 | pages = inline_size / sizeof(struct rpcrdma_segment); | ||
2054 | return pages << PAGE_SHIFT; | ||
2055 | } | ||
2056 | |||
2057 | static size_t | ||
2058 | rpcrdma_mr_max_payload(struct rpcrdma_xprt *r_xprt) | ||
2059 | { | ||
2060 | return RPCRDMA_MAX_DATA_SEGS << PAGE_SHIFT; | ||
2061 | } | ||
2062 | |||
2063 | size_t | ||
2064 | rpcrdma_max_payload(struct rpcrdma_xprt *r_xprt) | ||
2065 | { | ||
2066 | size_t result; | ||
2067 | |||
2068 | switch (r_xprt->rx_ia.ri_memreg_strategy) { | ||
2069 | case RPCRDMA_ALLPHYSICAL: | ||
2070 | result = rpcrdma_physical_max_payload(r_xprt); | ||
2071 | break; | ||
2072 | default: | ||
2073 | result = rpcrdma_mr_max_payload(r_xprt); | ||
2074 | } | ||
2075 | return result; | ||
2076 | } | ||
diff --git a/net/sunrpc/xprtrdma/xprt_rdma.h b/net/sunrpc/xprtrdma/xprt_rdma.h index 89e7cd479705..c419498b8f46 100644 --- a/net/sunrpc/xprtrdma/xprt_rdma.h +++ b/net/sunrpc/xprtrdma/xprt_rdma.h | |||
@@ -59,6 +59,7 @@ | |||
59 | * Interface Adapter -- one per transport instance | 59 | * Interface Adapter -- one per transport instance |
60 | */ | 60 | */ |
61 | struct rpcrdma_ia { | 61 | struct rpcrdma_ia { |
62 | rwlock_t ri_qplock; | ||
62 | struct rdma_cm_id *ri_id; | 63 | struct rdma_cm_id *ri_id; |
63 | struct ib_pd *ri_pd; | 64 | struct ib_pd *ri_pd; |
64 | struct ib_mr *ri_bind_mem; | 65 | struct ib_mr *ri_bind_mem; |
@@ -98,6 +99,14 @@ struct rpcrdma_ep { | |||
98 | #define INIT_CQCOUNT(ep) atomic_set(&(ep)->rep_cqcount, (ep)->rep_cqinit) | 99 | #define INIT_CQCOUNT(ep) atomic_set(&(ep)->rep_cqcount, (ep)->rep_cqinit) |
99 | #define DECR_CQCOUNT(ep) atomic_sub_return(1, &(ep)->rep_cqcount) | 100 | #define DECR_CQCOUNT(ep) atomic_sub_return(1, &(ep)->rep_cqcount) |
100 | 101 | ||
102 | enum rpcrdma_chunktype { | ||
103 | rpcrdma_noch = 0, | ||
104 | rpcrdma_readch, | ||
105 | rpcrdma_areadch, | ||
106 | rpcrdma_writech, | ||
107 | rpcrdma_replych | ||
108 | }; | ||
109 | |||
101 | /* | 110 | /* |
102 | * struct rpcrdma_rep -- this structure encapsulates state required to recv | 111 | * struct rpcrdma_rep -- this structure encapsulates state required to recv |
103 | * and complete a reply, asychronously. It needs several pieces of | 112 | * and complete a reply, asychronously. It needs several pieces of |
@@ -137,6 +146,40 @@ struct rpcrdma_rep { | |||
137 | }; | 146 | }; |
138 | 147 | ||
139 | /* | 148 | /* |
149 | * struct rpcrdma_mw - external memory region metadata | ||
150 | * | ||
151 | * An external memory region is any buffer or page that is registered | ||
152 | * on the fly (ie, not pre-registered). | ||
153 | * | ||
154 | * Each rpcrdma_buffer has a list of free MWs anchored in rb_mws. During | ||
155 | * call_allocate, rpcrdma_buffer_get() assigns one to each segment in | ||
156 | * an rpcrdma_req. Then rpcrdma_register_external() grabs these to keep | ||
157 | * track of registration metadata while each RPC is pending. | ||
158 | * rpcrdma_deregister_external() uses this metadata to unmap and | ||
159 | * release these resources when an RPC is complete. | ||
160 | */ | ||
161 | enum rpcrdma_frmr_state { | ||
162 | FRMR_IS_INVALID, /* ready to be used */ | ||
163 | FRMR_IS_VALID, /* in use */ | ||
164 | FRMR_IS_STALE, /* failed completion */ | ||
165 | }; | ||
166 | |||
167 | struct rpcrdma_frmr { | ||
168 | struct ib_fast_reg_page_list *fr_pgl; | ||
169 | struct ib_mr *fr_mr; | ||
170 | enum rpcrdma_frmr_state fr_state; | ||
171 | }; | ||
172 | |||
173 | struct rpcrdma_mw { | ||
174 | union { | ||
175 | struct ib_fmr *fmr; | ||
176 | struct rpcrdma_frmr frmr; | ||
177 | } r; | ||
178 | struct list_head mw_list; | ||
179 | struct list_head mw_all; | ||
180 | }; | ||
181 | |||
182 | /* | ||
140 | * struct rpcrdma_req -- structure central to the request/reply sequence. | 183 | * struct rpcrdma_req -- structure central to the request/reply sequence. |
141 | * | 184 | * |
142 | * N of these are associated with a transport instance, and stored in | 185 | * N of these are associated with a transport instance, and stored in |
@@ -163,17 +206,7 @@ struct rpcrdma_rep { | |||
163 | struct rpcrdma_mr_seg { /* chunk descriptors */ | 206 | struct rpcrdma_mr_seg { /* chunk descriptors */ |
164 | union { /* chunk memory handles */ | 207 | union { /* chunk memory handles */ |
165 | struct ib_mr *rl_mr; /* if registered directly */ | 208 | struct ib_mr *rl_mr; /* if registered directly */ |
166 | struct rpcrdma_mw { /* if registered from region */ | 209 | struct rpcrdma_mw *rl_mw; /* if registered from region */ |
167 | union { | ||
168 | struct ib_fmr *fmr; | ||
169 | struct { | ||
170 | struct ib_fast_reg_page_list *fr_pgl; | ||
171 | struct ib_mr *fr_mr; | ||
172 | enum { FRMR_IS_INVALID, FRMR_IS_VALID } state; | ||
173 | } frmr; | ||
174 | } r; | ||
175 | struct list_head mw_list; | ||
176 | } *rl_mw; | ||
177 | } mr_chunk; | 210 | } mr_chunk; |
178 | u64 mr_base; /* registration result */ | 211 | u64 mr_base; /* registration result */ |
179 | u32 mr_rkey; /* registration result */ | 212 | u32 mr_rkey; /* registration result */ |
@@ -191,6 +224,7 @@ struct rpcrdma_req { | |||
191 | unsigned int rl_niovs; /* 0, 2 or 4 */ | 224 | unsigned int rl_niovs; /* 0, 2 or 4 */ |
192 | unsigned int rl_nchunks; /* non-zero if chunks */ | 225 | unsigned int rl_nchunks; /* non-zero if chunks */ |
193 | unsigned int rl_connect_cookie; /* retry detection */ | 226 | unsigned int rl_connect_cookie; /* retry detection */ |
227 | enum rpcrdma_chunktype rl_rtype, rl_wtype; | ||
194 | struct rpcrdma_buffer *rl_buffer; /* home base for this structure */ | 228 | struct rpcrdma_buffer *rl_buffer; /* home base for this structure */ |
195 | struct rpcrdma_rep *rl_reply;/* holder for reply buffer */ | 229 | struct rpcrdma_rep *rl_reply;/* holder for reply buffer */ |
196 | struct rpcrdma_mr_seg rl_segments[RPCRDMA_MAX_SEGS];/* chunk segments */ | 230 | struct rpcrdma_mr_seg rl_segments[RPCRDMA_MAX_SEGS];/* chunk segments */ |
@@ -214,6 +248,7 @@ struct rpcrdma_buffer { | |||
214 | atomic_t rb_credits; /* most recent server credits */ | 248 | atomic_t rb_credits; /* most recent server credits */ |
215 | int rb_max_requests;/* client max requests */ | 249 | int rb_max_requests;/* client max requests */ |
216 | struct list_head rb_mws; /* optional memory windows/fmrs/frmrs */ | 250 | struct list_head rb_mws; /* optional memory windows/fmrs/frmrs */ |
251 | struct list_head rb_all; | ||
217 | int rb_send_index; | 252 | int rb_send_index; |
218 | struct rpcrdma_req **rb_send_bufs; | 253 | struct rpcrdma_req **rb_send_bufs; |
219 | int rb_recv_index; | 254 | int rb_recv_index; |
@@ -306,7 +341,7 @@ int rpcrdma_ep_create(struct rpcrdma_ep *, struct rpcrdma_ia *, | |||
306 | struct rpcrdma_create_data_internal *); | 341 | struct rpcrdma_create_data_internal *); |
307 | void rpcrdma_ep_destroy(struct rpcrdma_ep *, struct rpcrdma_ia *); | 342 | void rpcrdma_ep_destroy(struct rpcrdma_ep *, struct rpcrdma_ia *); |
308 | int rpcrdma_ep_connect(struct rpcrdma_ep *, struct rpcrdma_ia *); | 343 | int rpcrdma_ep_connect(struct rpcrdma_ep *, struct rpcrdma_ia *); |
309 | int rpcrdma_ep_disconnect(struct rpcrdma_ep *, struct rpcrdma_ia *); | 344 | void rpcrdma_ep_disconnect(struct rpcrdma_ep *, struct rpcrdma_ia *); |
310 | 345 | ||
311 | int rpcrdma_ep_post(struct rpcrdma_ia *, struct rpcrdma_ep *, | 346 | int rpcrdma_ep_post(struct rpcrdma_ia *, struct rpcrdma_ep *, |
312 | struct rpcrdma_req *); | 347 | struct rpcrdma_req *); |
@@ -346,7 +381,9 @@ void rpcrdma_reply_handler(struct rpcrdma_rep *); | |||
346 | /* | 381 | /* |
347 | * RPC/RDMA protocol calls - xprtrdma/rpc_rdma.c | 382 | * RPC/RDMA protocol calls - xprtrdma/rpc_rdma.c |
348 | */ | 383 | */ |
384 | ssize_t rpcrdma_marshal_chunks(struct rpc_rqst *, ssize_t); | ||
349 | int rpcrdma_marshal_req(struct rpc_rqst *); | 385 | int rpcrdma_marshal_req(struct rpc_rqst *); |
386 | size_t rpcrdma_max_payload(struct rpcrdma_xprt *); | ||
350 | 387 | ||
351 | /* Temporary NFS request map cache. Created in svc_rdma.c */ | 388 | /* Temporary NFS request map cache. Created in svc_rdma.c */ |
352 | extern struct kmem_cache *svc_rdma_map_cachep; | 389 | extern struct kmem_cache *svc_rdma_map_cachep; |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index be8bbd5d65ec..43cd89eacfab 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -594,6 +594,7 @@ static int xs_local_send_request(struct rpc_task *task) | |||
594 | } | 594 | } |
595 | 595 | ||
596 | switch (status) { | 596 | switch (status) { |
597 | case -ENOBUFS: | ||
597 | case -EAGAIN: | 598 | case -EAGAIN: |
598 | status = xs_nospace(task); | 599 | status = xs_nospace(task); |
599 | break; | 600 | break; |
@@ -661,6 +662,7 @@ static int xs_udp_send_request(struct rpc_task *task) | |||
661 | dprintk("RPC: sendmsg returned unrecognized error %d\n", | 662 | dprintk("RPC: sendmsg returned unrecognized error %d\n", |
662 | -status); | 663 | -status); |
663 | case -ENETUNREACH: | 664 | case -ENETUNREACH: |
665 | case -ENOBUFS: | ||
664 | case -EPIPE: | 666 | case -EPIPE: |
665 | case -ECONNREFUSED: | 667 | case -ECONNREFUSED: |
666 | /* When the server has died, an ICMP port unreachable message | 668 | /* When the server has died, an ICMP port unreachable message |
@@ -758,6 +760,7 @@ static int xs_tcp_send_request(struct rpc_task *task) | |||
758 | status = -ENOTCONN; | 760 | status = -ENOTCONN; |
759 | /* Should we call xs_close() here? */ | 761 | /* Should we call xs_close() here? */ |
760 | break; | 762 | break; |
763 | case -ENOBUFS: | ||
761 | case -EAGAIN: | 764 | case -EAGAIN: |
762 | status = xs_nospace(task); | 765 | status = xs_nospace(task); |
763 | break; | 766 | break; |
@@ -1946,6 +1949,7 @@ static int xs_local_setup_socket(struct sock_xprt *transport) | |||
1946 | dprintk("RPC: xprt %p connected to %s\n", | 1949 | dprintk("RPC: xprt %p connected to %s\n", |
1947 | xprt, xprt->address_strings[RPC_DISPLAY_ADDR]); | 1950 | xprt, xprt->address_strings[RPC_DISPLAY_ADDR]); |
1948 | xprt_set_connected(xprt); | 1951 | xprt_set_connected(xprt); |
1952 | case -ENOBUFS: | ||
1949 | break; | 1953 | break; |
1950 | case -ENOENT: | 1954 | case -ENOENT: |
1951 | dprintk("RPC: xprt %p: socket %s does not exist\n", | 1955 | dprintk("RPC: xprt %p: socket %s does not exist\n", |
@@ -2281,6 +2285,7 @@ static void xs_tcp_setup_socket(struct work_struct *work) | |||
2281 | case -ECONNREFUSED: | 2285 | case -ECONNREFUSED: |
2282 | case -ECONNRESET: | 2286 | case -ECONNRESET: |
2283 | case -ENETUNREACH: | 2287 | case -ENETUNREACH: |
2288 | case -ENOBUFS: | ||
2284 | /* retry with existing socket, after a delay */ | 2289 | /* retry with existing socket, after a delay */ |
2285 | goto out; | 2290 | goto out; |
2286 | } | 2291 | } |
@@ -3054,12 +3059,12 @@ static int param_set_uint_minmax(const char *val, | |||
3054 | const struct kernel_param *kp, | 3059 | const struct kernel_param *kp, |
3055 | unsigned int min, unsigned int max) | 3060 | unsigned int min, unsigned int max) |
3056 | { | 3061 | { |
3057 | unsigned long num; | 3062 | unsigned int num; |
3058 | int ret; | 3063 | int ret; |
3059 | 3064 | ||
3060 | if (!val) | 3065 | if (!val) |
3061 | return -EINVAL; | 3066 | return -EINVAL; |
3062 | ret = strict_strtoul(val, 0, &num); | 3067 | ret = kstrtouint(val, 0, &num); |
3063 | if (ret == -EINVAL || num < min || num > max) | 3068 | if (ret == -EINVAL || num < min || num > max) |
3064 | return -EINVAL; | 3069 | return -EINVAL; |
3065 | *((unsigned int *)kp->arg) = num; | 3070 | *((unsigned int *)kp->arg) = num; |
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index 55c6c9d3e1ce..dd13bfa09333 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * net/tipc/bcast.c: TIPC broadcast code | 2 | * net/tipc/bcast.c: TIPC broadcast code |
3 | * | 3 | * |
4 | * Copyright (c) 2004-2006, Ericsson AB | 4 | * Copyright (c) 2004-2006, 2014, Ericsson AB |
5 | * Copyright (c) 2004, Intel Corporation. | 5 | * Copyright (c) 2004, Intel Corporation. |
6 | * Copyright (c) 2005, 2010-2011, Wind River Systems | 6 | * Copyright (c) 2005, 2010-2011, Wind River Systems |
7 | * All rights reserved. | 7 | * All rights reserved. |
@@ -38,6 +38,8 @@ | |||
38 | #include "core.h" | 38 | #include "core.h" |
39 | #include "link.h" | 39 | #include "link.h" |
40 | #include "port.h" | 40 | #include "port.h" |
41 | #include "socket.h" | ||
42 | #include "msg.h" | ||
41 | #include "bcast.h" | 43 | #include "bcast.h" |
42 | #include "name_distr.h" | 44 | #include "name_distr.h" |
43 | 45 | ||
@@ -138,6 +140,11 @@ static void tipc_bclink_unlock(void) | |||
138 | tipc_link_reset_all(node); | 140 | tipc_link_reset_all(node); |
139 | } | 141 | } |
140 | 142 | ||
143 | uint tipc_bclink_get_mtu(void) | ||
144 | { | ||
145 | return MAX_PKT_DEFAULT_MCAST; | ||
146 | } | ||
147 | |||
141 | void tipc_bclink_set_flags(unsigned int flags) | 148 | void tipc_bclink_set_flags(unsigned int flags) |
142 | { | 149 | { |
143 | bclink->flags |= flags; | 150 | bclink->flags |= flags; |
@@ -382,30 +389,50 @@ static void bclink_peek_nack(struct tipc_msg *msg) | |||
382 | tipc_node_unlock(n_ptr); | 389 | tipc_node_unlock(n_ptr); |
383 | } | 390 | } |
384 | 391 | ||
385 | /* | 392 | /* tipc_bclink_xmit - broadcast buffer chain to all nodes in cluster |
386 | * tipc_bclink_xmit - broadcast a packet to all nodes in cluster | 393 | * and to identified node local sockets |
394 | * @buf: chain of buffers containing message | ||
395 | * Consumes the buffer chain, except when returning -ELINKCONG | ||
396 | * Returns 0 if success, otherwise errno: -ELINKCONG,-EHOSTUNREACH,-EMSGSIZE | ||
387 | */ | 397 | */ |
388 | int tipc_bclink_xmit(struct sk_buff *buf) | 398 | int tipc_bclink_xmit(struct sk_buff *buf) |
389 | { | 399 | { |
390 | int res; | 400 | int rc = 0; |
401 | int bc = 0; | ||
402 | struct sk_buff *clbuf; | ||
391 | 403 | ||
392 | tipc_bclink_lock(); | 404 | /* Prepare clone of message for local node */ |
393 | 405 | clbuf = tipc_msg_reassemble(buf); | |
394 | if (!bclink->bcast_nodes.count) { | 406 | if (unlikely(!clbuf)) { |
395 | res = msg_data_sz(buf_msg(buf)); | 407 | kfree_skb_list(buf); |
396 | kfree_skb(buf); | 408 | return -EHOSTUNREACH; |
397 | goto exit; | ||
398 | } | 409 | } |
399 | 410 | ||
400 | res = __tipc_link_xmit(bcl, buf); | 411 | /* Broadcast to all other nodes */ |
401 | if (likely(res >= 0)) { | 412 | if (likely(bclink)) { |
402 | bclink_set_last_sent(); | 413 | tipc_bclink_lock(); |
403 | bcl->stats.queue_sz_counts++; | 414 | if (likely(bclink->bcast_nodes.count)) { |
404 | bcl->stats.accu_queue_sz += bcl->out_queue_size; | 415 | rc = __tipc_link_xmit(bcl, buf); |
416 | if (likely(!rc)) { | ||
417 | bclink_set_last_sent(); | ||
418 | bcl->stats.queue_sz_counts++; | ||
419 | bcl->stats.accu_queue_sz += bcl->out_queue_size; | ||
420 | } | ||
421 | bc = 1; | ||
422 | } | ||
423 | tipc_bclink_unlock(); | ||
405 | } | 424 | } |
406 | exit: | 425 | |
407 | tipc_bclink_unlock(); | 426 | if (unlikely(!bc)) |
408 | return res; | 427 | kfree_skb_list(buf); |
428 | |||
429 | /* Deliver message clone */ | ||
430 | if (likely(!rc)) | ||
431 | tipc_sk_mcast_rcv(clbuf); | ||
432 | else | ||
433 | kfree_skb(clbuf); | ||
434 | |||
435 | return rc; | ||
409 | } | 436 | } |
410 | 437 | ||
411 | /** | 438 | /** |
@@ -443,7 +470,7 @@ void tipc_bclink_rcv(struct sk_buff *buf) | |||
443 | struct tipc_node *node; | 470 | struct tipc_node *node; |
444 | u32 next_in; | 471 | u32 next_in; |
445 | u32 seqno; | 472 | u32 seqno; |
446 | int deferred; | 473 | int deferred = 0; |
447 | 474 | ||
448 | /* Screen out unwanted broadcast messages */ | 475 | /* Screen out unwanted broadcast messages */ |
449 | 476 | ||
@@ -494,7 +521,7 @@ receive: | |||
494 | tipc_bclink_unlock(); | 521 | tipc_bclink_unlock(); |
495 | tipc_node_unlock(node); | 522 | tipc_node_unlock(node); |
496 | if (likely(msg_mcast(msg))) | 523 | if (likely(msg_mcast(msg))) |
497 | tipc_port_mcast_rcv(buf, NULL); | 524 | tipc_sk_mcast_rcv(buf); |
498 | else | 525 | else |
499 | kfree_skb(buf); | 526 | kfree_skb(buf); |
500 | } else if (msg_user(msg) == MSG_BUNDLER) { | 527 | } else if (msg_user(msg) == MSG_BUNDLER) { |
@@ -573,8 +600,7 @@ receive: | |||
573 | node->bclink.deferred_size += deferred; | 600 | node->bclink.deferred_size += deferred; |
574 | bclink_update_last_sent(node, seqno); | 601 | bclink_update_last_sent(node, seqno); |
575 | buf = NULL; | 602 | buf = NULL; |
576 | } else | 603 | } |
577 | deferred = 0; | ||
578 | 604 | ||
579 | tipc_bclink_lock(); | 605 | tipc_bclink_lock(); |
580 | 606 | ||
@@ -611,6 +637,7 @@ static int tipc_bcbearer_send(struct sk_buff *buf, struct tipc_bearer *unused1, | |||
611 | struct tipc_media_addr *unused2) | 637 | struct tipc_media_addr *unused2) |
612 | { | 638 | { |
613 | int bp_index; | 639 | int bp_index; |
640 | struct tipc_msg *msg = buf_msg(buf); | ||
614 | 641 | ||
615 | /* Prepare broadcast link message for reliable transmission, | 642 | /* Prepare broadcast link message for reliable transmission, |
616 | * if first time trying to send it; | 643 | * if first time trying to send it; |
@@ -618,10 +645,7 @@ static int tipc_bcbearer_send(struct sk_buff *buf, struct tipc_bearer *unused1, | |||
618 | * since they are sent in an unreliable manner and don't need it | 645 | * since they are sent in an unreliable manner and don't need it |
619 | */ | 646 | */ |
620 | if (likely(!msg_non_seq(buf_msg(buf)))) { | 647 | if (likely(!msg_non_seq(buf_msg(buf)))) { |
621 | struct tipc_msg *msg; | ||
622 | |||
623 | bcbuf_set_acks(buf, bclink->bcast_nodes.count); | 648 | bcbuf_set_acks(buf, bclink->bcast_nodes.count); |
624 | msg = buf_msg(buf); | ||
625 | msg_set_non_seq(msg, 1); | 649 | msg_set_non_seq(msg, 1); |
626 | msg_set_mc_netid(msg, tipc_net_id); | 650 | msg_set_mc_netid(msg, tipc_net_id); |
627 | bcl->stats.sent_info++; | 651 | bcl->stats.sent_info++; |
@@ -638,12 +662,14 @@ static int tipc_bcbearer_send(struct sk_buff *buf, struct tipc_bearer *unused1, | |||
638 | for (bp_index = 0; bp_index < MAX_BEARERS; bp_index++) { | 662 | for (bp_index = 0; bp_index < MAX_BEARERS; bp_index++) { |
639 | struct tipc_bearer *p = bcbearer->bpairs[bp_index].primary; | 663 | struct tipc_bearer *p = bcbearer->bpairs[bp_index].primary; |
640 | struct tipc_bearer *s = bcbearer->bpairs[bp_index].secondary; | 664 | struct tipc_bearer *s = bcbearer->bpairs[bp_index].secondary; |
641 | struct tipc_bearer *b = p; | 665 | struct tipc_bearer *bp[2] = {p, s}; |
666 | struct tipc_bearer *b = bp[msg_link_selector(msg)]; | ||
642 | struct sk_buff *tbuf; | 667 | struct sk_buff *tbuf; |
643 | 668 | ||
644 | if (!p) | 669 | if (!p) |
645 | break; /* No more bearers to try */ | 670 | break; /* No more bearers to try */ |
646 | 671 | if (!b) | |
672 | b = p; | ||
647 | tipc_nmap_diff(&bcbearer->remains, &b->nodes, | 673 | tipc_nmap_diff(&bcbearer->remains, &b->nodes, |
648 | &bcbearer->remains_new); | 674 | &bcbearer->remains_new); |
649 | if (bcbearer->remains_new.count == bcbearer->remains.count) | 675 | if (bcbearer->remains_new.count == bcbearer->remains.count) |
@@ -660,13 +686,6 @@ static int tipc_bcbearer_send(struct sk_buff *buf, struct tipc_bearer *unused1, | |||
660 | tipc_bearer_send(b->identity, tbuf, &b->bcast_addr); | 686 | tipc_bearer_send(b->identity, tbuf, &b->bcast_addr); |
661 | kfree_skb(tbuf); /* Bearer keeps a clone */ | 687 | kfree_skb(tbuf); /* Bearer keeps a clone */ |
662 | } | 688 | } |
663 | |||
664 | /* Swap bearers for next packet */ | ||
665 | if (s) { | ||
666 | bcbearer->bpairs[bp_index].primary = s; | ||
667 | bcbearer->bpairs[bp_index].secondary = p; | ||
668 | } | ||
669 | |||
670 | if (bcbearer->remains_new.count == 0) | 689 | if (bcbearer->remains_new.count == 0) |
671 | break; /* All targets reached */ | 690 | break; /* All targets reached */ |
672 | 691 | ||
diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h index 00330c45df3e..4875d9536aee 100644 --- a/net/tipc/bcast.h +++ b/net/tipc/bcast.h | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * net/tipc/bcast.h: Include file for TIPC broadcast code | 2 | * net/tipc/bcast.h: Include file for TIPC broadcast code |
3 | * | 3 | * |
4 | * Copyright (c) 2003-2006, Ericsson AB | 4 | * Copyright (c) 2003-2006, 2014, Ericsson AB |
5 | * Copyright (c) 2005, 2010-2011, Wind River Systems | 5 | * Copyright (c) 2005, 2010-2011, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
@@ -89,7 +89,6 @@ void tipc_bclink_add_node(u32 addr); | |||
89 | void tipc_bclink_remove_node(u32 addr); | 89 | void tipc_bclink_remove_node(u32 addr); |
90 | struct tipc_node *tipc_bclink_retransmit_to(void); | 90 | struct tipc_node *tipc_bclink_retransmit_to(void); |
91 | void tipc_bclink_acknowledge(struct tipc_node *n_ptr, u32 acked); | 91 | void tipc_bclink_acknowledge(struct tipc_node *n_ptr, u32 acked); |
92 | int tipc_bclink_xmit(struct sk_buff *buf); | ||
93 | void tipc_bclink_rcv(struct sk_buff *buf); | 92 | void tipc_bclink_rcv(struct sk_buff *buf); |
94 | u32 tipc_bclink_get_last_sent(void); | 93 | u32 tipc_bclink_get_last_sent(void); |
95 | u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr); | 94 | u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr); |
@@ -98,5 +97,7 @@ int tipc_bclink_stats(char *stats_buf, const u32 buf_size); | |||
98 | int tipc_bclink_reset_stats(void); | 97 | int tipc_bclink_reset_stats(void); |
99 | int tipc_bclink_set_queue_limits(u32 limit); | 98 | int tipc_bclink_set_queue_limits(u32 limit); |
100 | void tipc_bcbearer_sort(struct tipc_node_map *nm_ptr, u32 node, bool action); | 99 | void tipc_bcbearer_sort(struct tipc_node_map *nm_ptr, u32 node, bool action); |
100 | uint tipc_bclink_get_mtu(void); | ||
101 | int tipc_bclink_xmit(struct sk_buff *buf); | ||
101 | 102 | ||
102 | #endif | 103 | #endif |
diff --git a/net/tipc/link.c b/net/tipc/link.c index ad2c57f5868d..fb1485dc6736 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
@@ -82,15 +82,13 @@ static void tipc_link_proto_rcv(struct tipc_link *l_ptr, struct sk_buff *buf); | |||
82 | static int tipc_link_tunnel_rcv(struct tipc_node *n_ptr, | 82 | static int tipc_link_tunnel_rcv(struct tipc_node *n_ptr, |
83 | struct sk_buff **buf); | 83 | struct sk_buff **buf); |
84 | static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tolerance); | 84 | static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tolerance); |
85 | static int tipc_link_iovec_long_xmit(struct tipc_port *sender, | ||
86 | struct iovec const *msg_sect, | ||
87 | unsigned int len, u32 destnode); | ||
88 | static void link_state_event(struct tipc_link *l_ptr, u32 event); | 85 | static void link_state_event(struct tipc_link *l_ptr, u32 event); |
89 | static void link_reset_statistics(struct tipc_link *l_ptr); | 86 | static void link_reset_statistics(struct tipc_link *l_ptr); |
90 | static void link_print(struct tipc_link *l_ptr, const char *str); | 87 | static void link_print(struct tipc_link *l_ptr, const char *str); |
91 | static int tipc_link_frag_xmit(struct tipc_link *l_ptr, struct sk_buff *buf); | ||
92 | static void tipc_link_sync_xmit(struct tipc_link *l); | 88 | static void tipc_link_sync_xmit(struct tipc_link *l); |
93 | static void tipc_link_sync_rcv(struct tipc_node *n, struct sk_buff *buf); | 89 | static void tipc_link_sync_rcv(struct tipc_node *n, struct sk_buff *buf); |
90 | static int tipc_link_input(struct tipc_link *l, struct sk_buff *buf); | ||
91 | static int tipc_link_prepare_input(struct tipc_link *l, struct sk_buff **buf); | ||
94 | 92 | ||
95 | /* | 93 | /* |
96 | * Simple link routines | 94 | * Simple link routines |
@@ -335,13 +333,15 @@ void tipc_link_delete_list(unsigned int bearer_id, bool shutting_down) | |||
335 | static int link_schedule_port(struct tipc_link *l_ptr, u32 origport, u32 sz) | 333 | static int link_schedule_port(struct tipc_link *l_ptr, u32 origport, u32 sz) |
336 | { | 334 | { |
337 | struct tipc_port *p_ptr; | 335 | struct tipc_port *p_ptr; |
336 | struct tipc_sock *tsk; | ||
338 | 337 | ||
339 | spin_lock_bh(&tipc_port_list_lock); | 338 | spin_lock_bh(&tipc_port_list_lock); |
340 | p_ptr = tipc_port_lock(origport); | 339 | p_ptr = tipc_port_lock(origport); |
341 | if (p_ptr) { | 340 | if (p_ptr) { |
342 | if (!list_empty(&p_ptr->wait_list)) | 341 | if (!list_empty(&p_ptr->wait_list)) |
343 | goto exit; | 342 | goto exit; |
344 | p_ptr->congested = 1; | 343 | tsk = tipc_port_to_sock(p_ptr); |
344 | tsk->link_cong = 1; | ||
345 | p_ptr->waiting_pkts = 1 + ((sz - 1) / l_ptr->max_pkt); | 345 | p_ptr->waiting_pkts = 1 + ((sz - 1) / l_ptr->max_pkt); |
346 | list_add_tail(&p_ptr->wait_list, &l_ptr->waiting_ports); | 346 | list_add_tail(&p_ptr->wait_list, &l_ptr->waiting_ports); |
347 | l_ptr->stats.link_congs++; | 347 | l_ptr->stats.link_congs++; |
@@ -355,6 +355,7 @@ exit: | |||
355 | void tipc_link_wakeup_ports(struct tipc_link *l_ptr, int all) | 355 | void tipc_link_wakeup_ports(struct tipc_link *l_ptr, int all) |
356 | { | 356 | { |
357 | struct tipc_port *p_ptr; | 357 | struct tipc_port *p_ptr; |
358 | struct tipc_sock *tsk; | ||
358 | struct tipc_port *temp_p_ptr; | 359 | struct tipc_port *temp_p_ptr; |
359 | int win = l_ptr->queue_limit[0] - l_ptr->out_queue_size; | 360 | int win = l_ptr->queue_limit[0] - l_ptr->out_queue_size; |
360 | 361 | ||
@@ -370,10 +371,11 @@ void tipc_link_wakeup_ports(struct tipc_link *l_ptr, int all) | |||
370 | wait_list) { | 371 | wait_list) { |
371 | if (win <= 0) | 372 | if (win <= 0) |
372 | break; | 373 | break; |
374 | tsk = tipc_port_to_sock(p_ptr); | ||
373 | list_del_init(&p_ptr->wait_list); | 375 | list_del_init(&p_ptr->wait_list); |
374 | spin_lock_bh(p_ptr->lock); | 376 | spin_lock_bh(p_ptr->lock); |
375 | p_ptr->congested = 0; | 377 | tsk->link_cong = 0; |
376 | tipc_port_wakeup(p_ptr); | 378 | tipc_sock_wakeup(tsk); |
377 | win -= p_ptr->waiting_pkts; | 379 | win -= p_ptr->waiting_pkts; |
378 | spin_unlock_bh(p_ptr->lock); | 380 | spin_unlock_bh(p_ptr->lock); |
379 | } | 381 | } |
@@ -676,178 +678,142 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event) | |||
676 | } | 678 | } |
677 | } | 679 | } |
678 | 680 | ||
679 | /* | 681 | /* tipc_link_cong: determine return value and how to treat the |
680 | * link_bundle_buf(): Append contents of a buffer to | 682 | * sent buffer during link congestion. |
681 | * the tail of an existing one. | 683 | * - For plain, errorless user data messages we keep the buffer and |
684 | * return -ELINKONG. | ||
685 | * - For all other messages we discard the buffer and return -EHOSTUNREACH | ||
686 | * - For TIPC internal messages we also reset the link | ||
682 | */ | 687 | */ |
683 | static int link_bundle_buf(struct tipc_link *l_ptr, struct sk_buff *bundler, | 688 | static int tipc_link_cong(struct tipc_link *link, struct sk_buff *buf) |
684 | struct sk_buff *buf) | ||
685 | { | 689 | { |
686 | struct tipc_msg *bundler_msg = buf_msg(bundler); | ||
687 | struct tipc_msg *msg = buf_msg(buf); | 690 | struct tipc_msg *msg = buf_msg(buf); |
688 | u32 size = msg_size(msg); | 691 | uint psz = msg_size(msg); |
689 | u32 bundle_size = msg_size(bundler_msg); | 692 | uint imp = tipc_msg_tot_importance(msg); |
690 | u32 to_pos = align(bundle_size); | 693 | u32 oport = msg_tot_origport(msg); |
691 | u32 pad = to_pos - bundle_size; | ||
692 | |||
693 | if (msg_user(bundler_msg) != MSG_BUNDLER) | ||
694 | return 0; | ||
695 | if (msg_type(bundler_msg) != OPEN_MSG) | ||
696 | return 0; | ||
697 | if (skb_tailroom(bundler) < (pad + size)) | ||
698 | return 0; | ||
699 | if (l_ptr->max_pkt < (to_pos + size)) | ||
700 | return 0; | ||
701 | |||
702 | skb_put(bundler, pad + size); | ||
703 | skb_copy_to_linear_data_offset(bundler, to_pos, buf->data, size); | ||
704 | msg_set_size(bundler_msg, to_pos + size); | ||
705 | msg_set_msgcnt(bundler_msg, msg_msgcnt(bundler_msg) + 1); | ||
706 | kfree_skb(buf); | ||
707 | l_ptr->stats.sent_bundled++; | ||
708 | return 1; | ||
709 | } | ||
710 | |||
711 | static void link_add_to_outqueue(struct tipc_link *l_ptr, | ||
712 | struct sk_buff *buf, | ||
713 | struct tipc_msg *msg) | ||
714 | { | ||
715 | u32 ack = mod(l_ptr->next_in_no - 1); | ||
716 | u32 seqno = mod(l_ptr->next_out_no++); | ||
717 | 694 | ||
718 | msg_set_word(msg, 2, ((ack << 16) | seqno)); | 695 | if (likely(imp <= TIPC_CRITICAL_IMPORTANCE)) { |
719 | msg_set_bcast_ack(msg, l_ptr->owner->bclink.last_in); | 696 | if (!msg_errcode(msg) && !msg_reroute_cnt(msg)) { |
720 | buf->next = NULL; | 697 | link_schedule_port(link, oport, psz); |
721 | if (l_ptr->first_out) { | 698 | return -ELINKCONG; |
722 | l_ptr->last_out->next = buf; | 699 | } |
723 | l_ptr->last_out = buf; | 700 | } else { |
724 | } else | 701 | pr_warn("%s<%s>, send queue full", link_rst_msg, link->name); |
725 | l_ptr->first_out = l_ptr->last_out = buf; | 702 | tipc_link_reset(link); |
726 | |||
727 | l_ptr->out_queue_size++; | ||
728 | if (l_ptr->out_queue_size > l_ptr->stats.max_queue_sz) | ||
729 | l_ptr->stats.max_queue_sz = l_ptr->out_queue_size; | ||
730 | } | ||
731 | |||
732 | static void link_add_chain_to_outqueue(struct tipc_link *l_ptr, | ||
733 | struct sk_buff *buf_chain, | ||
734 | u32 long_msgno) | ||
735 | { | ||
736 | struct sk_buff *buf; | ||
737 | struct tipc_msg *msg; | ||
738 | |||
739 | if (!l_ptr->next_out) | ||
740 | l_ptr->next_out = buf_chain; | ||
741 | while (buf_chain) { | ||
742 | buf = buf_chain; | ||
743 | buf_chain = buf_chain->next; | ||
744 | |||
745 | msg = buf_msg(buf); | ||
746 | msg_set_long_msgno(msg, long_msgno); | ||
747 | link_add_to_outqueue(l_ptr, buf, msg); | ||
748 | } | 703 | } |
704 | kfree_skb_list(buf); | ||
705 | return -EHOSTUNREACH; | ||
749 | } | 706 | } |
750 | 707 | ||
751 | /* | 708 | /** |
752 | * tipc_link_xmit() is the 'full path' for messages, called from | 709 | * __tipc_link_xmit(): same as tipc_link_xmit, but destlink is known & locked |
753 | * inside TIPC when the 'fast path' in tipc_send_xmit | 710 | * @link: link to use |
754 | * has failed, and from link_send() | 711 | * @buf: chain of buffers containing message |
712 | * Consumes the buffer chain, except when returning -ELINKCONG | ||
713 | * Returns 0 if success, otherwise errno: -ELINKCONG, -EMSGSIZE (plain socket | ||
714 | * user data messages) or -EHOSTUNREACH (all other messages/senders) | ||
715 | * Only the socket functions tipc_send_stream() and tipc_send_packet() need | ||
716 | * to act on the return value, since they may need to do more send attempts. | ||
755 | */ | 717 | */ |
756 | int __tipc_link_xmit(struct tipc_link *l_ptr, struct sk_buff *buf) | 718 | int __tipc_link_xmit(struct tipc_link *link, struct sk_buff *buf) |
757 | { | 719 | { |
758 | struct tipc_msg *msg = buf_msg(buf); | 720 | struct tipc_msg *msg = buf_msg(buf); |
759 | u32 size = msg_size(msg); | 721 | uint psz = msg_size(msg); |
760 | u32 dsz = msg_data_sz(msg); | 722 | uint qsz = link->out_queue_size; |
761 | u32 queue_size = l_ptr->out_queue_size; | 723 | uint sndlim = link->queue_limit[0]; |
762 | u32 imp = tipc_msg_tot_importance(msg); | 724 | uint imp = tipc_msg_tot_importance(msg); |
763 | u32 queue_limit = l_ptr->queue_limit[imp]; | 725 | uint mtu = link->max_pkt; |
764 | u32 max_packet = l_ptr->max_pkt; | 726 | uint ack = mod(link->next_in_no - 1); |
765 | 727 | uint seqno = link->next_out_no; | |
766 | /* Match msg importance against queue limits: */ | 728 | uint bc_last_in = link->owner->bclink.last_in; |
767 | if (unlikely(queue_size >= queue_limit)) { | 729 | struct tipc_media_addr *addr = &link->media_addr; |
768 | if (imp <= TIPC_CRITICAL_IMPORTANCE) { | 730 | struct sk_buff *next = buf->next; |
769 | link_schedule_port(l_ptr, msg_origport(msg), size); | 731 | |
770 | kfree_skb(buf); | 732 | /* Match queue limits against msg importance: */ |
771 | return -ELINKCONG; | 733 | if (unlikely(qsz >= link->queue_limit[imp])) |
772 | } | 734 | return tipc_link_cong(link, buf); |
773 | kfree_skb(buf); | 735 | |
774 | if (imp > CONN_MANAGER) { | 736 | /* Has valid packet limit been used ? */ |
775 | pr_warn("%s<%s>, send queue full", link_rst_msg, | 737 | if (unlikely(psz > mtu)) { |
776 | l_ptr->name); | 738 | kfree_skb_list(buf); |
777 | tipc_link_reset(l_ptr); | 739 | return -EMSGSIZE; |
778 | } | ||
779 | return dsz; | ||
780 | } | 740 | } |
781 | 741 | ||
782 | /* Fragmentation needed ? */ | 742 | /* Prepare each packet for sending, and add to outqueue: */ |
783 | if (size > max_packet) | 743 | while (buf) { |
784 | return tipc_link_frag_xmit(l_ptr, buf); | 744 | next = buf->next; |
785 | 745 | msg = buf_msg(buf); | |
786 | /* Packet can be queued or sent. */ | 746 | msg_set_word(msg, 2, ((ack << 16) | mod(seqno))); |
787 | if (likely(!link_congested(l_ptr))) { | 747 | msg_set_bcast_ack(msg, bc_last_in); |
788 | link_add_to_outqueue(l_ptr, buf, msg); | 748 | |
749 | if (!link->first_out) { | ||
750 | link->first_out = buf; | ||
751 | } else if (qsz < sndlim) { | ||
752 | link->last_out->next = buf; | ||
753 | } else if (tipc_msg_bundle(link->last_out, buf, mtu)) { | ||
754 | link->stats.sent_bundled++; | ||
755 | buf = next; | ||
756 | next = buf->next; | ||
757 | continue; | ||
758 | } else if (tipc_msg_make_bundle(&buf, mtu, link->addr)) { | ||
759 | link->stats.sent_bundled++; | ||
760 | link->stats.sent_bundles++; | ||
761 | link->last_out->next = buf; | ||
762 | if (!link->next_out) | ||
763 | link->next_out = buf; | ||
764 | } else { | ||
765 | link->last_out->next = buf; | ||
766 | if (!link->next_out) | ||
767 | link->next_out = buf; | ||
768 | } | ||
789 | 769 | ||
790 | tipc_bearer_send(l_ptr->bearer_id, buf, &l_ptr->media_addr); | 770 | /* Send packet if possible: */ |
791 | l_ptr->unacked_window = 0; | 771 | if (likely(++qsz <= sndlim)) { |
792 | return dsz; | 772 | tipc_bearer_send(link->bearer_id, buf, addr); |
793 | } | 773 | link->next_out = next; |
794 | /* Congestion: can message be bundled ? */ | 774 | link->unacked_window = 0; |
795 | if ((msg_user(msg) != CHANGEOVER_PROTOCOL) && | ||
796 | (msg_user(msg) != MSG_FRAGMENTER)) { | ||
797 | |||
798 | /* Try adding message to an existing bundle */ | ||
799 | if (l_ptr->next_out && | ||
800 | link_bundle_buf(l_ptr, l_ptr->last_out, buf)) | ||
801 | return dsz; | ||
802 | |||
803 | /* Try creating a new bundle */ | ||
804 | if (size <= max_packet * 2 / 3) { | ||
805 | struct sk_buff *bundler = tipc_buf_acquire(max_packet); | ||
806 | struct tipc_msg bundler_hdr; | ||
807 | |||
808 | if (bundler) { | ||
809 | tipc_msg_init(&bundler_hdr, MSG_BUNDLER, OPEN_MSG, | ||
810 | INT_H_SIZE, l_ptr->addr); | ||
811 | skb_copy_to_linear_data(bundler, &bundler_hdr, | ||
812 | INT_H_SIZE); | ||
813 | skb_trim(bundler, INT_H_SIZE); | ||
814 | link_bundle_buf(l_ptr, bundler, buf); | ||
815 | buf = bundler; | ||
816 | msg = buf_msg(buf); | ||
817 | l_ptr->stats.sent_bundles++; | ||
818 | } | ||
819 | } | 775 | } |
776 | seqno++; | ||
777 | link->last_out = buf; | ||
778 | buf = next; | ||
820 | } | 779 | } |
821 | if (!l_ptr->next_out) | 780 | link->next_out_no = seqno; |
822 | l_ptr->next_out = buf; | 781 | link->out_queue_size = qsz; |
823 | link_add_to_outqueue(l_ptr, buf, msg); | 782 | return 0; |
824 | return dsz; | ||
825 | } | 783 | } |
826 | 784 | ||
827 | /* | 785 | /** |
828 | * tipc_link_xmit(): same as __tipc_link_xmit(), but the link to use | 786 | * tipc_link_xmit() is the general link level function for message sending |
829 | * has not been selected yet, and the the owner node is not locked | 787 | * @buf: chain of buffers containing message |
830 | * Called by TIPC internal users, e.g. the name distributor | 788 | * @dsz: amount of user data to be sent |
789 | * @dnode: address of destination node | ||
790 | * @selector: a number used for deterministic link selection | ||
791 | * Consumes the buffer chain, except when returning -ELINKCONG | ||
792 | * Returns 0 if success, otherwise errno: -ELINKCONG,-EHOSTUNREACH,-EMSGSIZE | ||
831 | */ | 793 | */ |
832 | int tipc_link_xmit(struct sk_buff *buf, u32 dest, u32 selector) | 794 | int tipc_link_xmit(struct sk_buff *buf, u32 dnode, u32 selector) |
833 | { | 795 | { |
834 | struct tipc_link *l_ptr; | 796 | struct tipc_link *link = NULL; |
835 | struct tipc_node *n_ptr; | 797 | struct tipc_node *node; |
836 | int res = -ELINKCONG; | 798 | int rc = -EHOSTUNREACH; |
837 | 799 | ||
838 | n_ptr = tipc_node_find(dest); | 800 | node = tipc_node_find(dnode); |
839 | if (n_ptr) { | 801 | if (node) { |
840 | tipc_node_lock(n_ptr); | 802 | tipc_node_lock(node); |
841 | l_ptr = n_ptr->active_links[selector & 1]; | 803 | link = node->active_links[selector & 1]; |
842 | if (l_ptr) | 804 | if (link) |
843 | res = __tipc_link_xmit(l_ptr, buf); | 805 | rc = __tipc_link_xmit(link, buf); |
844 | else | 806 | tipc_node_unlock(node); |
845 | kfree_skb(buf); | ||
846 | tipc_node_unlock(n_ptr); | ||
847 | } else { | ||
848 | kfree_skb(buf); | ||
849 | } | 807 | } |
850 | return res; | 808 | |
809 | if (link) | ||
810 | return rc; | ||
811 | |||
812 | if (likely(in_own_node(dnode))) | ||
813 | return tipc_sk_rcv(buf); | ||
814 | |||
815 | kfree_skb_list(buf); | ||
816 | return rc; | ||
851 | } | 817 | } |
852 | 818 | ||
853 | /* | 819 | /* |
@@ -858,7 +824,7 @@ int tipc_link_xmit(struct sk_buff *buf, u32 dest, u32 selector) | |||
858 | * | 824 | * |
859 | * Called with node locked | 825 | * Called with node locked |
860 | */ | 826 | */ |
861 | static void tipc_link_sync_xmit(struct tipc_link *l) | 827 | static void tipc_link_sync_xmit(struct tipc_link *link) |
862 | { | 828 | { |
863 | struct sk_buff *buf; | 829 | struct sk_buff *buf; |
864 | struct tipc_msg *msg; | 830 | struct tipc_msg *msg; |
@@ -868,10 +834,9 @@ static void tipc_link_sync_xmit(struct tipc_link *l) | |||
868 | return; | 834 | return; |
869 | 835 | ||
870 | msg = buf_msg(buf); | 836 | msg = buf_msg(buf); |
871 | tipc_msg_init(msg, BCAST_PROTOCOL, STATE_MSG, INT_H_SIZE, l->addr); | 837 | tipc_msg_init(msg, BCAST_PROTOCOL, STATE_MSG, INT_H_SIZE, link->addr); |
872 | msg_set_last_bcast(msg, l->owner->bclink.acked); | 838 | msg_set_last_bcast(msg, link->owner->bclink.acked); |
873 | link_add_chain_to_outqueue(l, buf, 0); | 839 | __tipc_link_xmit(link, buf); |
874 | tipc_link_push_queue(l); | ||
875 | } | 840 | } |
876 | 841 | ||
877 | /* | 842 | /* |
@@ -892,293 +857,6 @@ static void tipc_link_sync_rcv(struct tipc_node *n, struct sk_buff *buf) | |||
892 | } | 857 | } |
893 | 858 | ||
894 | /* | 859 | /* |
895 | * tipc_link_names_xmit - send name table entries to new neighbor | ||
896 | * | ||
897 | * Send routine for bulk delivery of name table messages when contact | ||
898 | * with a new neighbor occurs. No link congestion checking is performed | ||
899 | * because name table messages *must* be delivered. The messages must be | ||
900 | * small enough not to require fragmentation. | ||
901 | * Called without any locks held. | ||
902 | */ | ||
903 | void tipc_link_names_xmit(struct list_head *message_list, u32 dest) | ||
904 | { | ||
905 | struct tipc_node *n_ptr; | ||
906 | struct tipc_link *l_ptr; | ||
907 | struct sk_buff *buf; | ||
908 | struct sk_buff *temp_buf; | ||
909 | |||
910 | if (list_empty(message_list)) | ||
911 | return; | ||
912 | |||
913 | n_ptr = tipc_node_find(dest); | ||
914 | if (n_ptr) { | ||
915 | tipc_node_lock(n_ptr); | ||
916 | l_ptr = n_ptr->active_links[0]; | ||
917 | if (l_ptr) { | ||
918 | /* convert circular list to linear list */ | ||
919 | ((struct sk_buff *)message_list->prev)->next = NULL; | ||
920 | link_add_chain_to_outqueue(l_ptr, | ||
921 | (struct sk_buff *)message_list->next, 0); | ||
922 | tipc_link_push_queue(l_ptr); | ||
923 | INIT_LIST_HEAD(message_list); | ||
924 | } | ||
925 | tipc_node_unlock(n_ptr); | ||
926 | } | ||
927 | |||
928 | /* discard the messages if they couldn't be sent */ | ||
929 | list_for_each_safe(buf, temp_buf, ((struct sk_buff *)message_list)) { | ||
930 | list_del((struct list_head *)buf); | ||
931 | kfree_skb(buf); | ||
932 | } | ||
933 | } | ||
934 | |||
935 | /* | ||
936 | * tipc_link_xmit_fast: Entry for data messages where the | ||
937 | * destination link is known and the header is complete, | ||
938 | * inclusive total message length. Very time critical. | ||
939 | * Link is locked. Returns user data length. | ||
940 | */ | ||
941 | static int tipc_link_xmit_fast(struct tipc_link *l_ptr, struct sk_buff *buf, | ||
942 | u32 *used_max_pkt) | ||
943 | { | ||
944 | struct tipc_msg *msg = buf_msg(buf); | ||
945 | int res = msg_data_sz(msg); | ||
946 | |||
947 | if (likely(!link_congested(l_ptr))) { | ||
948 | if (likely(msg_size(msg) <= l_ptr->max_pkt)) { | ||
949 | link_add_to_outqueue(l_ptr, buf, msg); | ||
950 | tipc_bearer_send(l_ptr->bearer_id, buf, | ||
951 | &l_ptr->media_addr); | ||
952 | l_ptr->unacked_window = 0; | ||
953 | return res; | ||
954 | } | ||
955 | else | ||
956 | *used_max_pkt = l_ptr->max_pkt; | ||
957 | } | ||
958 | return __tipc_link_xmit(l_ptr, buf); /* All other cases */ | ||
959 | } | ||
960 | |||
961 | /* | ||
962 | * tipc_link_iovec_xmit_fast: Entry for messages where the | ||
963 | * destination processor is known and the header is complete, | ||
964 | * except for total message length. | ||
965 | * Returns user data length or errno. | ||
966 | */ | ||
967 | int tipc_link_iovec_xmit_fast(struct tipc_port *sender, | ||
968 | struct iovec const *msg_sect, | ||
969 | unsigned int len, u32 destaddr) | ||
970 | { | ||
971 | struct tipc_msg *hdr = &sender->phdr; | ||
972 | struct tipc_link *l_ptr; | ||
973 | struct sk_buff *buf; | ||
974 | struct tipc_node *node; | ||
975 | int res; | ||
976 | u32 selector = msg_origport(hdr) & 1; | ||
977 | |||
978 | again: | ||
979 | /* | ||
980 | * Try building message using port's max_pkt hint. | ||
981 | * (Must not hold any locks while building message.) | ||
982 | */ | ||
983 | res = tipc_msg_build(hdr, msg_sect, len, sender->max_pkt, &buf); | ||
984 | /* Exit if build request was invalid */ | ||
985 | if (unlikely(res < 0)) | ||
986 | return res; | ||
987 | |||
988 | node = tipc_node_find(destaddr); | ||
989 | if (likely(node)) { | ||
990 | tipc_node_lock(node); | ||
991 | l_ptr = node->active_links[selector]; | ||
992 | if (likely(l_ptr)) { | ||
993 | if (likely(buf)) { | ||
994 | res = tipc_link_xmit_fast(l_ptr, buf, | ||
995 | &sender->max_pkt); | ||
996 | exit: | ||
997 | tipc_node_unlock(node); | ||
998 | return res; | ||
999 | } | ||
1000 | |||
1001 | /* Exit if link (or bearer) is congested */ | ||
1002 | if (link_congested(l_ptr)) { | ||
1003 | res = link_schedule_port(l_ptr, | ||
1004 | sender->ref, res); | ||
1005 | goto exit; | ||
1006 | } | ||
1007 | |||
1008 | /* | ||
1009 | * Message size exceeds max_pkt hint; update hint, | ||
1010 | * then re-try fast path or fragment the message | ||
1011 | */ | ||
1012 | sender->max_pkt = l_ptr->max_pkt; | ||
1013 | tipc_node_unlock(node); | ||
1014 | |||
1015 | |||
1016 | if ((msg_hdr_sz(hdr) + res) <= sender->max_pkt) | ||
1017 | goto again; | ||
1018 | |||
1019 | return tipc_link_iovec_long_xmit(sender, msg_sect, | ||
1020 | len, destaddr); | ||
1021 | } | ||
1022 | tipc_node_unlock(node); | ||
1023 | } | ||
1024 | |||
1025 | /* Couldn't find a link to the destination node */ | ||
1026 | kfree_skb(buf); | ||
1027 | tipc_port_iovec_reject(sender, hdr, msg_sect, len, TIPC_ERR_NO_NODE); | ||
1028 | return -ENETUNREACH; | ||
1029 | } | ||
1030 | |||
1031 | /* | ||
1032 | * tipc_link_iovec_long_xmit(): Entry for long messages where the | ||
1033 | * destination node is known and the header is complete, | ||
1034 | * inclusive total message length. | ||
1035 | * Link and bearer congestion status have been checked to be ok, | ||
1036 | * and are ignored if they change. | ||
1037 | * | ||
1038 | * Note that fragments do not use the full link MTU so that they won't have | ||
1039 | * to undergo refragmentation if link changeover causes them to be sent | ||
1040 | * over another link with an additional tunnel header added as prefix. | ||
1041 | * (Refragmentation will still occur if the other link has a smaller MTU.) | ||
1042 | * | ||
1043 | * Returns user data length or errno. | ||
1044 | */ | ||
1045 | static int tipc_link_iovec_long_xmit(struct tipc_port *sender, | ||
1046 | struct iovec const *msg_sect, | ||
1047 | unsigned int len, u32 destaddr) | ||
1048 | { | ||
1049 | struct tipc_link *l_ptr; | ||
1050 | struct tipc_node *node; | ||
1051 | struct tipc_msg *hdr = &sender->phdr; | ||
1052 | u32 dsz = len; | ||
1053 | u32 max_pkt, fragm_sz, rest; | ||
1054 | struct tipc_msg fragm_hdr; | ||
1055 | struct sk_buff *buf, *buf_chain, *prev; | ||
1056 | u32 fragm_crs, fragm_rest, hsz, sect_rest; | ||
1057 | const unchar __user *sect_crs; | ||
1058 | int curr_sect; | ||
1059 | u32 fragm_no; | ||
1060 | int res = 0; | ||
1061 | |||
1062 | again: | ||
1063 | fragm_no = 1; | ||
1064 | max_pkt = sender->max_pkt - INT_H_SIZE; | ||
1065 | /* leave room for tunnel header in case of link changeover */ | ||
1066 | fragm_sz = max_pkt - INT_H_SIZE; | ||
1067 | /* leave room for fragmentation header in each fragment */ | ||
1068 | rest = dsz; | ||
1069 | fragm_crs = 0; | ||
1070 | fragm_rest = 0; | ||
1071 | sect_rest = 0; | ||
1072 | sect_crs = NULL; | ||
1073 | curr_sect = -1; | ||
1074 | |||
1075 | /* Prepare reusable fragment header */ | ||
1076 | tipc_msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT, | ||
1077 | INT_H_SIZE, msg_destnode(hdr)); | ||
1078 | msg_set_size(&fragm_hdr, max_pkt); | ||
1079 | msg_set_fragm_no(&fragm_hdr, 1); | ||
1080 | |||
1081 | /* Prepare header of first fragment */ | ||
1082 | buf_chain = buf = tipc_buf_acquire(max_pkt); | ||
1083 | if (!buf) | ||
1084 | return -ENOMEM; | ||
1085 | buf->next = NULL; | ||
1086 | skb_copy_to_linear_data(buf, &fragm_hdr, INT_H_SIZE); | ||
1087 | hsz = msg_hdr_sz(hdr); | ||
1088 | skb_copy_to_linear_data_offset(buf, INT_H_SIZE, hdr, hsz); | ||
1089 | |||
1090 | /* Chop up message */ | ||
1091 | fragm_crs = INT_H_SIZE + hsz; | ||
1092 | fragm_rest = fragm_sz - hsz; | ||
1093 | |||
1094 | do { /* For all sections */ | ||
1095 | u32 sz; | ||
1096 | |||
1097 | if (!sect_rest) { | ||
1098 | sect_rest = msg_sect[++curr_sect].iov_len; | ||
1099 | sect_crs = msg_sect[curr_sect].iov_base; | ||
1100 | } | ||
1101 | |||
1102 | if (sect_rest < fragm_rest) | ||
1103 | sz = sect_rest; | ||
1104 | else | ||
1105 | sz = fragm_rest; | ||
1106 | |||
1107 | if (copy_from_user(buf->data + fragm_crs, sect_crs, sz)) { | ||
1108 | res = -EFAULT; | ||
1109 | error: | ||
1110 | kfree_skb_list(buf_chain); | ||
1111 | return res; | ||
1112 | } | ||
1113 | sect_crs += sz; | ||
1114 | sect_rest -= sz; | ||
1115 | fragm_crs += sz; | ||
1116 | fragm_rest -= sz; | ||
1117 | rest -= sz; | ||
1118 | |||
1119 | if (!fragm_rest && rest) { | ||
1120 | |||
1121 | /* Initiate new fragment: */ | ||
1122 | if (rest <= fragm_sz) { | ||
1123 | fragm_sz = rest; | ||
1124 | msg_set_type(&fragm_hdr, LAST_FRAGMENT); | ||
1125 | } else { | ||
1126 | msg_set_type(&fragm_hdr, FRAGMENT); | ||
1127 | } | ||
1128 | msg_set_size(&fragm_hdr, fragm_sz + INT_H_SIZE); | ||
1129 | msg_set_fragm_no(&fragm_hdr, ++fragm_no); | ||
1130 | prev = buf; | ||
1131 | buf = tipc_buf_acquire(fragm_sz + INT_H_SIZE); | ||
1132 | if (!buf) { | ||
1133 | res = -ENOMEM; | ||
1134 | goto error; | ||
1135 | } | ||
1136 | |||
1137 | buf->next = NULL; | ||
1138 | prev->next = buf; | ||
1139 | skb_copy_to_linear_data(buf, &fragm_hdr, INT_H_SIZE); | ||
1140 | fragm_crs = INT_H_SIZE; | ||
1141 | fragm_rest = fragm_sz; | ||
1142 | } | ||
1143 | } while (rest > 0); | ||
1144 | |||
1145 | /* | ||
1146 | * Now we have a buffer chain. Select a link and check | ||
1147 | * that packet size is still OK | ||
1148 | */ | ||
1149 | node = tipc_node_find(destaddr); | ||
1150 | if (likely(node)) { | ||
1151 | tipc_node_lock(node); | ||
1152 | l_ptr = node->active_links[sender->ref & 1]; | ||
1153 | if (!l_ptr) { | ||
1154 | tipc_node_unlock(node); | ||
1155 | goto reject; | ||
1156 | } | ||
1157 | if (l_ptr->max_pkt < max_pkt) { | ||
1158 | sender->max_pkt = l_ptr->max_pkt; | ||
1159 | tipc_node_unlock(node); | ||
1160 | kfree_skb_list(buf_chain); | ||
1161 | goto again; | ||
1162 | } | ||
1163 | } else { | ||
1164 | reject: | ||
1165 | kfree_skb_list(buf_chain); | ||
1166 | tipc_port_iovec_reject(sender, hdr, msg_sect, len, | ||
1167 | TIPC_ERR_NO_NODE); | ||
1168 | return -ENETUNREACH; | ||
1169 | } | ||
1170 | |||
1171 | /* Append chain of fragments to send queue & send them */ | ||
1172 | l_ptr->long_msg_seq_no++; | ||
1173 | link_add_chain_to_outqueue(l_ptr, buf_chain, l_ptr->long_msg_seq_no); | ||
1174 | l_ptr->stats.sent_fragments += fragm_no; | ||
1175 | l_ptr->stats.sent_fragmented++; | ||
1176 | tipc_link_push_queue(l_ptr); | ||
1177 | tipc_node_unlock(node); | ||
1178 | return dsz; | ||
1179 | } | ||
1180 | |||
1181 | /* | ||
1182 | * tipc_link_push_packet: Push one unsent packet to the media | 860 | * tipc_link_push_packet: Push one unsent packet to the media |
1183 | */ | 861 | */ |
1184 | static u32 tipc_link_push_packet(struct tipc_link *l_ptr) | 862 | static u32 tipc_link_push_packet(struct tipc_link *l_ptr) |
@@ -1238,7 +916,7 @@ static u32 tipc_link_push_packet(struct tipc_link *l_ptr) | |||
1238 | tipc_bearer_send(l_ptr->bearer_id, buf, | 916 | tipc_bearer_send(l_ptr->bearer_id, buf, |
1239 | &l_ptr->media_addr); | 917 | &l_ptr->media_addr); |
1240 | if (msg_user(msg) == MSG_BUNDLER) | 918 | if (msg_user(msg) == MSG_BUNDLER) |
1241 | msg_set_type(msg, CLOSED_MSG); | 919 | msg_set_type(msg, BUNDLE_CLOSED); |
1242 | l_ptr->next_out = buf->next; | 920 | l_ptr->next_out = buf->next; |
1243 | return 0; | 921 | return 0; |
1244 | } | 922 | } |
@@ -1527,11 +1205,6 @@ void tipc_rcv(struct sk_buff *head, struct tipc_bearer *b_ptr) | |||
1527 | if (unlikely(!list_empty(&l_ptr->waiting_ports))) | 1205 | if (unlikely(!list_empty(&l_ptr->waiting_ports))) |
1528 | tipc_link_wakeup_ports(l_ptr, 0); | 1206 | tipc_link_wakeup_ports(l_ptr, 0); |
1529 | 1207 | ||
1530 | if (unlikely(++l_ptr->unacked_window >= TIPC_MIN_LINK_WIN)) { | ||
1531 | l_ptr->stats.sent_acks++; | ||
1532 | tipc_link_proto_xmit(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); | ||
1533 | } | ||
1534 | |||
1535 | /* Process the incoming packet */ | 1208 | /* Process the incoming packet */ |
1536 | if (unlikely(!link_working_working(l_ptr))) { | 1209 | if (unlikely(!link_working_working(l_ptr))) { |
1537 | if (msg_user(msg) == LINK_PROTOCOL) { | 1210 | if (msg_user(msg) == LINK_PROTOCOL) { |
@@ -1565,57 +1238,19 @@ void tipc_rcv(struct sk_buff *head, struct tipc_bearer *b_ptr) | |||
1565 | if (unlikely(l_ptr->oldest_deferred_in)) | 1238 | if (unlikely(l_ptr->oldest_deferred_in)) |
1566 | head = link_insert_deferred_queue(l_ptr, head); | 1239 | head = link_insert_deferred_queue(l_ptr, head); |
1567 | 1240 | ||
1568 | /* Deliver packet/message to correct user: */ | 1241 | if (unlikely(++l_ptr->unacked_window >= TIPC_MIN_LINK_WIN)) { |
1569 | if (unlikely(msg_user(msg) == CHANGEOVER_PROTOCOL)) { | 1242 | l_ptr->stats.sent_acks++; |
1570 | if (!tipc_link_tunnel_rcv(n_ptr, &buf)) { | 1243 | tipc_link_proto_xmit(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); |
1571 | tipc_node_unlock(n_ptr); | ||
1572 | continue; | ||
1573 | } | ||
1574 | msg = buf_msg(buf); | ||
1575 | } else if (msg_user(msg) == MSG_FRAGMENTER) { | ||
1576 | l_ptr->stats.recv_fragments++; | ||
1577 | if (tipc_buf_append(&l_ptr->reasm_buf, &buf)) { | ||
1578 | l_ptr->stats.recv_fragmented++; | ||
1579 | msg = buf_msg(buf); | ||
1580 | } else { | ||
1581 | if (!l_ptr->reasm_buf) | ||
1582 | tipc_link_reset(l_ptr); | ||
1583 | tipc_node_unlock(n_ptr); | ||
1584 | continue; | ||
1585 | } | ||
1586 | } | 1244 | } |
1587 | 1245 | ||
1588 | switch (msg_user(msg)) { | 1246 | if (tipc_link_prepare_input(l_ptr, &buf)) { |
1589 | case TIPC_LOW_IMPORTANCE: | ||
1590 | case TIPC_MEDIUM_IMPORTANCE: | ||
1591 | case TIPC_HIGH_IMPORTANCE: | ||
1592 | case TIPC_CRITICAL_IMPORTANCE: | ||
1593 | tipc_node_unlock(n_ptr); | 1247 | tipc_node_unlock(n_ptr); |
1594 | tipc_sk_rcv(buf); | ||
1595 | continue; | 1248 | continue; |
1596 | case MSG_BUNDLER: | ||
1597 | l_ptr->stats.recv_bundles++; | ||
1598 | l_ptr->stats.recv_bundled += msg_msgcnt(msg); | ||
1599 | tipc_node_unlock(n_ptr); | ||
1600 | tipc_link_bundle_rcv(buf); | ||
1601 | continue; | ||
1602 | case NAME_DISTRIBUTOR: | ||
1603 | n_ptr->bclink.recv_permitted = true; | ||
1604 | tipc_node_unlock(n_ptr); | ||
1605 | tipc_named_rcv(buf); | ||
1606 | continue; | ||
1607 | case CONN_MANAGER: | ||
1608 | tipc_node_unlock(n_ptr); | ||
1609 | tipc_port_proto_rcv(buf); | ||
1610 | continue; | ||
1611 | case BCAST_PROTOCOL: | ||
1612 | tipc_link_sync_rcv(n_ptr, buf); | ||
1613 | break; | ||
1614 | default: | ||
1615 | kfree_skb(buf); | ||
1616 | break; | ||
1617 | } | 1249 | } |
1618 | tipc_node_unlock(n_ptr); | 1250 | tipc_node_unlock(n_ptr); |
1251 | msg = buf_msg(buf); | ||
1252 | if (tipc_link_input(l_ptr, buf) != 0) | ||
1253 | goto discard; | ||
1619 | continue; | 1254 | continue; |
1620 | unlock_discard: | 1255 | unlock_discard: |
1621 | tipc_node_unlock(n_ptr); | 1256 | tipc_node_unlock(n_ptr); |
@@ -1625,6 +1260,80 @@ discard: | |||
1625 | } | 1260 | } |
1626 | 1261 | ||
1627 | /** | 1262 | /** |
1263 | * tipc_link_prepare_input - process TIPC link messages | ||
1264 | * | ||
1265 | * returns nonzero if the message was consumed | ||
1266 | * | ||
1267 | * Node lock must be held | ||
1268 | */ | ||
1269 | static int tipc_link_prepare_input(struct tipc_link *l, struct sk_buff **buf) | ||
1270 | { | ||
1271 | struct tipc_node *n; | ||
1272 | struct tipc_msg *msg; | ||
1273 | int res = -EINVAL; | ||
1274 | |||
1275 | n = l->owner; | ||
1276 | msg = buf_msg(*buf); | ||
1277 | switch (msg_user(msg)) { | ||
1278 | case CHANGEOVER_PROTOCOL: | ||
1279 | if (tipc_link_tunnel_rcv(n, buf)) | ||
1280 | res = 0; | ||
1281 | break; | ||
1282 | case MSG_FRAGMENTER: | ||
1283 | l->stats.recv_fragments++; | ||
1284 | if (tipc_buf_append(&l->reasm_buf, buf)) { | ||
1285 | l->stats.recv_fragmented++; | ||
1286 | res = 0; | ||
1287 | } else if (!l->reasm_buf) { | ||
1288 | tipc_link_reset(l); | ||
1289 | } | ||
1290 | break; | ||
1291 | case MSG_BUNDLER: | ||
1292 | l->stats.recv_bundles++; | ||
1293 | l->stats.recv_bundled += msg_msgcnt(msg); | ||
1294 | res = 0; | ||
1295 | break; | ||
1296 | case NAME_DISTRIBUTOR: | ||
1297 | n->bclink.recv_permitted = true; | ||
1298 | res = 0; | ||
1299 | break; | ||
1300 | case BCAST_PROTOCOL: | ||
1301 | tipc_link_sync_rcv(n, *buf); | ||
1302 | break; | ||
1303 | default: | ||
1304 | res = 0; | ||
1305 | } | ||
1306 | return res; | ||
1307 | } | ||
1308 | /** | ||
1309 | * tipc_link_input - Deliver message too higher layers | ||
1310 | */ | ||
1311 | static int tipc_link_input(struct tipc_link *l, struct sk_buff *buf) | ||
1312 | { | ||
1313 | struct tipc_msg *msg = buf_msg(buf); | ||
1314 | int res = 0; | ||
1315 | |||
1316 | switch (msg_user(msg)) { | ||
1317 | case TIPC_LOW_IMPORTANCE: | ||
1318 | case TIPC_MEDIUM_IMPORTANCE: | ||
1319 | case TIPC_HIGH_IMPORTANCE: | ||
1320 | case TIPC_CRITICAL_IMPORTANCE: | ||
1321 | case CONN_MANAGER: | ||
1322 | tipc_sk_rcv(buf); | ||
1323 | break; | ||
1324 | case NAME_DISTRIBUTOR: | ||
1325 | tipc_named_rcv(buf); | ||
1326 | break; | ||
1327 | case MSG_BUNDLER: | ||
1328 | tipc_link_bundle_rcv(buf); | ||
1329 | break; | ||
1330 | default: | ||
1331 | res = -EINVAL; | ||
1332 | } | ||
1333 | return res; | ||
1334 | } | ||
1335 | |||
1336 | /** | ||
1628 | * tipc_link_defer_pkt - Add out-of-sequence message to deferred reception queue | 1337 | * tipc_link_defer_pkt - Add out-of-sequence message to deferred reception queue |
1629 | * | 1338 | * |
1630 | * Returns increase in queue length (i.e. 0 or 1) | 1339 | * Returns increase in queue length (i.e. 0 or 1) |
@@ -2217,6 +1926,7 @@ void tipc_link_bundle_rcv(struct sk_buff *buf) | |||
2217 | u32 msgcount = msg_msgcnt(buf_msg(buf)); | 1926 | u32 msgcount = msg_msgcnt(buf_msg(buf)); |
2218 | u32 pos = INT_H_SIZE; | 1927 | u32 pos = INT_H_SIZE; |
2219 | struct sk_buff *obuf; | 1928 | struct sk_buff *obuf; |
1929 | struct tipc_msg *omsg; | ||
2220 | 1930 | ||
2221 | while (msgcount--) { | 1931 | while (msgcount--) { |
2222 | obuf = buf_extract(buf, pos); | 1932 | obuf = buf_extract(buf, pos); |
@@ -2224,82 +1934,18 @@ void tipc_link_bundle_rcv(struct sk_buff *buf) | |||
2224 | pr_warn("Link unable to unbundle message(s)\n"); | 1934 | pr_warn("Link unable to unbundle message(s)\n"); |
2225 | break; | 1935 | break; |
2226 | } | 1936 | } |
2227 | pos += align(msg_size(buf_msg(obuf))); | 1937 | omsg = buf_msg(obuf); |
2228 | tipc_net_route_msg(obuf); | 1938 | pos += align(msg_size(omsg)); |
2229 | } | 1939 | if (msg_isdata(omsg) || (msg_user(omsg) == CONN_MANAGER)) { |
2230 | kfree_skb(buf); | 1940 | tipc_sk_rcv(obuf); |
2231 | } | 1941 | } else if (msg_user(omsg) == NAME_DISTRIBUTOR) { |
2232 | 1942 | tipc_named_rcv(obuf); | |
2233 | /* | 1943 | } else { |
2234 | * Fragmentation/defragmentation: | 1944 | pr_warn("Illegal bundled msg: %u\n", msg_user(omsg)); |
2235 | */ | 1945 | kfree_skb(obuf); |
2236 | |||
2237 | /* | ||
2238 | * tipc_link_frag_xmit: Entry for buffers needing fragmentation. | ||
2239 | * The buffer is complete, inclusive total message length. | ||
2240 | * Returns user data length. | ||
2241 | */ | ||
2242 | static int tipc_link_frag_xmit(struct tipc_link *l_ptr, struct sk_buff *buf) | ||
2243 | { | ||
2244 | struct sk_buff *buf_chain = NULL; | ||
2245 | struct sk_buff *buf_chain_tail = (struct sk_buff *)&buf_chain; | ||
2246 | struct tipc_msg *inmsg = buf_msg(buf); | ||
2247 | struct tipc_msg fragm_hdr; | ||
2248 | u32 insize = msg_size(inmsg); | ||
2249 | u32 dsz = msg_data_sz(inmsg); | ||
2250 | unchar *crs = buf->data; | ||
2251 | u32 rest = insize; | ||
2252 | u32 pack_sz = l_ptr->max_pkt; | ||
2253 | u32 fragm_sz = pack_sz - INT_H_SIZE; | ||
2254 | u32 fragm_no = 0; | ||
2255 | u32 destaddr; | ||
2256 | |||
2257 | if (msg_short(inmsg)) | ||
2258 | destaddr = l_ptr->addr; | ||
2259 | else | ||
2260 | destaddr = msg_destnode(inmsg); | ||
2261 | |||
2262 | /* Prepare reusable fragment header: */ | ||
2263 | tipc_msg_init(&fragm_hdr, MSG_FRAGMENTER, FIRST_FRAGMENT, | ||
2264 | INT_H_SIZE, destaddr); | ||
2265 | |||
2266 | /* Chop up message: */ | ||
2267 | while (rest > 0) { | ||
2268 | struct sk_buff *fragm; | ||
2269 | |||
2270 | if (rest <= fragm_sz) { | ||
2271 | fragm_sz = rest; | ||
2272 | msg_set_type(&fragm_hdr, LAST_FRAGMENT); | ||
2273 | } | ||
2274 | fragm = tipc_buf_acquire(fragm_sz + INT_H_SIZE); | ||
2275 | if (fragm == NULL) { | ||
2276 | kfree_skb(buf); | ||
2277 | kfree_skb_list(buf_chain); | ||
2278 | return -ENOMEM; | ||
2279 | } | 1946 | } |
2280 | msg_set_size(&fragm_hdr, fragm_sz + INT_H_SIZE); | ||
2281 | fragm_no++; | ||
2282 | msg_set_fragm_no(&fragm_hdr, fragm_no); | ||
2283 | skb_copy_to_linear_data(fragm, &fragm_hdr, INT_H_SIZE); | ||
2284 | skb_copy_to_linear_data_offset(fragm, INT_H_SIZE, crs, | ||
2285 | fragm_sz); | ||
2286 | buf_chain_tail->next = fragm; | ||
2287 | buf_chain_tail = fragm; | ||
2288 | |||
2289 | rest -= fragm_sz; | ||
2290 | crs += fragm_sz; | ||
2291 | msg_set_type(&fragm_hdr, FRAGMENT); | ||
2292 | } | 1947 | } |
2293 | kfree_skb(buf); | 1948 | kfree_skb(buf); |
2294 | |||
2295 | /* Append chain of fragments to send queue & send them */ | ||
2296 | l_ptr->long_msg_seq_no++; | ||
2297 | link_add_chain_to_outqueue(l_ptr, buf_chain, l_ptr->long_msg_seq_no); | ||
2298 | l_ptr->stats.sent_fragments += fragm_no; | ||
2299 | l_ptr->stats.sent_fragmented++; | ||
2300 | tipc_link_push_queue(l_ptr); | ||
2301 | |||
2302 | return dsz; | ||
2303 | } | 1949 | } |
2304 | 1950 | ||
2305 | static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tolerance) | 1951 | static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tolerance) |
diff --git a/net/tipc/link.h b/net/tipc/link.h index 200d518b218e..782983ccd323 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h | |||
@@ -227,13 +227,8 @@ void tipc_link_reset_all(struct tipc_node *node); | |||
227 | void tipc_link_reset(struct tipc_link *l_ptr); | 227 | void tipc_link_reset(struct tipc_link *l_ptr); |
228 | void tipc_link_reset_list(unsigned int bearer_id); | 228 | void tipc_link_reset_list(unsigned int bearer_id); |
229 | int tipc_link_xmit(struct sk_buff *buf, u32 dest, u32 selector); | 229 | int tipc_link_xmit(struct sk_buff *buf, u32 dest, u32 selector); |
230 | void tipc_link_names_xmit(struct list_head *message_list, u32 dest); | 230 | int __tipc_link_xmit(struct tipc_link *link, struct sk_buff *buf); |
231 | int __tipc_link_xmit(struct tipc_link *l_ptr, struct sk_buff *buf); | ||
232 | int tipc_link_send_buf(struct tipc_link *l_ptr, struct sk_buff *buf); | ||
233 | u32 tipc_link_get_max_pkt(u32 dest, u32 selector); | 231 | u32 tipc_link_get_max_pkt(u32 dest, u32 selector); |
234 | int tipc_link_iovec_xmit_fast(struct tipc_port *sender, | ||
235 | struct iovec const *msg_sect, | ||
236 | unsigned int len, u32 destnode); | ||
237 | void tipc_link_bundle_rcv(struct sk_buff *buf); | 232 | void tipc_link_bundle_rcv(struct sk_buff *buf); |
238 | void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int prob, | 233 | void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int prob, |
239 | u32 gap, u32 tolerance, u32 priority, u32 acked_mtu); | 234 | u32 gap, u32 tolerance, u32 priority, u32 acked_mtu); |
diff --git a/net/tipc/msg.c b/net/tipc/msg.c index 0a37a472c29f..9680be6d388a 100644 --- a/net/tipc/msg.c +++ b/net/tipc/msg.c | |||
@@ -36,21 +36,16 @@ | |||
36 | 36 | ||
37 | #include "core.h" | 37 | #include "core.h" |
38 | #include "msg.h" | 38 | #include "msg.h" |
39 | #include "addr.h" | ||
40 | #include "name_table.h" | ||
39 | 41 | ||
40 | u32 tipc_msg_tot_importance(struct tipc_msg *m) | 42 | #define MAX_FORWARD_SIZE 1024 |
43 | |||
44 | static unsigned int align(unsigned int i) | ||
41 | { | 45 | { |
42 | if (likely(msg_isdata(m))) { | 46 | return (i + 3) & ~3u; |
43 | if (likely(msg_orignode(m) == tipc_own_addr)) | ||
44 | return msg_importance(m); | ||
45 | return msg_importance(m) + 4; | ||
46 | } | ||
47 | if ((msg_user(m) == MSG_FRAGMENTER) && | ||
48 | (msg_type(m) == FIRST_FRAGMENT)) | ||
49 | return msg_importance(msg_get_wrapped(m)); | ||
50 | return msg_importance(m); | ||
51 | } | 47 | } |
52 | 48 | ||
53 | |||
54 | void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize, | 49 | void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize, |
55 | u32 destnode) | 50 | u32 destnode) |
56 | { | 51 | { |
@@ -65,41 +60,6 @@ void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize, | |||
65 | msg_set_destnode(m, destnode); | 60 | msg_set_destnode(m, destnode); |
66 | } | 61 | } |
67 | 62 | ||
68 | /** | ||
69 | * tipc_msg_build - create message using specified header and data | ||
70 | * | ||
71 | * Note: Caller must not hold any locks in case copy_from_user() is interrupted! | ||
72 | * | ||
73 | * Returns message data size or errno | ||
74 | */ | ||
75 | int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect, | ||
76 | unsigned int len, int max_size, struct sk_buff **buf) | ||
77 | { | ||
78 | int dsz, sz, hsz; | ||
79 | unsigned char *to; | ||
80 | |||
81 | dsz = len; | ||
82 | hsz = msg_hdr_sz(hdr); | ||
83 | sz = hsz + dsz; | ||
84 | msg_set_size(hdr, sz); | ||
85 | if (unlikely(sz > max_size)) { | ||
86 | *buf = NULL; | ||
87 | return dsz; | ||
88 | } | ||
89 | |||
90 | *buf = tipc_buf_acquire(sz); | ||
91 | if (!(*buf)) | ||
92 | return -ENOMEM; | ||
93 | skb_copy_to_linear_data(*buf, hdr, hsz); | ||
94 | to = (*buf)->data + hsz; | ||
95 | if (len && memcpy_fromiovecend(to, msg_sect, 0, dsz)) { | ||
96 | kfree_skb(*buf); | ||
97 | *buf = NULL; | ||
98 | return -EFAULT; | ||
99 | } | ||
100 | return dsz; | ||
101 | } | ||
102 | |||
103 | /* tipc_buf_append(): Append a buffer to the fragment list of another buffer | 63 | /* tipc_buf_append(): Append a buffer to the fragment list of another buffer |
104 | * @*headbuf: in: NULL for first frag, otherwise value returned from prev call | 64 | * @*headbuf: in: NULL for first frag, otherwise value returned from prev call |
105 | * out: set when successful non-complete reassembly, otherwise NULL | 65 | * out: set when successful non-complete reassembly, otherwise NULL |
@@ -112,27 +72,38 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf) | |||
112 | struct sk_buff *head = *headbuf; | 72 | struct sk_buff *head = *headbuf; |
113 | struct sk_buff *frag = *buf; | 73 | struct sk_buff *frag = *buf; |
114 | struct sk_buff *tail; | 74 | struct sk_buff *tail; |
115 | struct tipc_msg *msg = buf_msg(frag); | 75 | struct tipc_msg *msg; |
116 | u32 fragid = msg_type(msg); | 76 | u32 fragid; |
117 | bool headstolen; | ||
118 | int delta; | 77 | int delta; |
78 | bool headstolen; | ||
119 | 79 | ||
80 | if (!frag) | ||
81 | goto err; | ||
82 | |||
83 | msg = buf_msg(frag); | ||
84 | fragid = msg_type(msg); | ||
85 | frag->next = NULL; | ||
120 | skb_pull(frag, msg_hdr_sz(msg)); | 86 | skb_pull(frag, msg_hdr_sz(msg)); |
121 | 87 | ||
122 | if (fragid == FIRST_FRAGMENT) { | 88 | if (fragid == FIRST_FRAGMENT) { |
123 | if (head || skb_unclone(frag, GFP_ATOMIC)) | 89 | if (unlikely(head)) |
124 | goto out_free; | 90 | goto err; |
91 | if (unlikely(skb_unclone(frag, GFP_ATOMIC))) | ||
92 | goto err; | ||
125 | head = *headbuf = frag; | 93 | head = *headbuf = frag; |
126 | skb_frag_list_init(head); | 94 | skb_frag_list_init(head); |
95 | TIPC_SKB_CB(head)->tail = NULL; | ||
127 | *buf = NULL; | 96 | *buf = NULL; |
128 | return 0; | 97 | return 0; |
129 | } | 98 | } |
99 | |||
130 | if (!head) | 100 | if (!head) |
131 | goto out_free; | 101 | goto err; |
132 | tail = TIPC_SKB_CB(head)->tail; | 102 | |
133 | if (skb_try_coalesce(head, frag, &headstolen, &delta)) { | 103 | if (skb_try_coalesce(head, frag, &headstolen, &delta)) { |
134 | kfree_skb_partial(frag, headstolen); | 104 | kfree_skb_partial(frag, headstolen); |
135 | } else { | 105 | } else { |
106 | tail = TIPC_SKB_CB(head)->tail; | ||
136 | if (!skb_has_frag_list(head)) | 107 | if (!skb_has_frag_list(head)) |
137 | skb_shinfo(head)->frag_list = frag; | 108 | skb_shinfo(head)->frag_list = frag; |
138 | else | 109 | else |
@@ -142,6 +113,7 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf) | |||
142 | head->len += frag->len; | 113 | head->len += frag->len; |
143 | TIPC_SKB_CB(head)->tail = frag; | 114 | TIPC_SKB_CB(head)->tail = frag; |
144 | } | 115 | } |
116 | |||
145 | if (fragid == LAST_FRAGMENT) { | 117 | if (fragid == LAST_FRAGMENT) { |
146 | *buf = head; | 118 | *buf = head; |
147 | TIPC_SKB_CB(head)->tail = NULL; | 119 | TIPC_SKB_CB(head)->tail = NULL; |
@@ -150,10 +122,311 @@ int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf) | |||
150 | } | 122 | } |
151 | *buf = NULL; | 123 | *buf = NULL; |
152 | return 0; | 124 | return 0; |
153 | out_free: | 125 | |
126 | err: | ||
154 | pr_warn_ratelimited("Unable to build fragment list\n"); | 127 | pr_warn_ratelimited("Unable to build fragment list\n"); |
155 | kfree_skb(*buf); | 128 | kfree_skb(*buf); |
156 | kfree_skb(*headbuf); | 129 | kfree_skb(*headbuf); |
157 | *buf = *headbuf = NULL; | 130 | *buf = *headbuf = NULL; |
158 | return 0; | 131 | return 0; |
159 | } | 132 | } |
133 | |||
134 | |||
135 | /** | ||
136 | * tipc_msg_build - create buffer chain containing specified header and data | ||
137 | * @mhdr: Message header, to be prepended to data | ||
138 | * @iov: User data | ||
139 | * @offset: Posision in iov to start copying from | ||
140 | * @dsz: Total length of user data | ||
141 | * @pktmax: Max packet size that can be used | ||
142 | * @chain: Buffer or chain of buffers to be returned to caller | ||
143 | * Returns message data size or errno: -ENOMEM, -EFAULT | ||
144 | */ | ||
145 | int tipc_msg_build(struct tipc_msg *mhdr, struct iovec const *iov, | ||
146 | int offset, int dsz, int pktmax , struct sk_buff **chain) | ||
147 | { | ||
148 | int mhsz = msg_hdr_sz(mhdr); | ||
149 | int msz = mhsz + dsz; | ||
150 | int pktno = 1; | ||
151 | int pktsz; | ||
152 | int pktrem = pktmax; | ||
153 | int drem = dsz; | ||
154 | struct tipc_msg pkthdr; | ||
155 | struct sk_buff *buf, *prev; | ||
156 | char *pktpos; | ||
157 | int rc; | ||
158 | |||
159 | msg_set_size(mhdr, msz); | ||
160 | |||
161 | /* No fragmentation needed? */ | ||
162 | if (likely(msz <= pktmax)) { | ||
163 | buf = tipc_buf_acquire(msz); | ||
164 | *chain = buf; | ||
165 | if (unlikely(!buf)) | ||
166 | return -ENOMEM; | ||
167 | skb_copy_to_linear_data(buf, mhdr, mhsz); | ||
168 | pktpos = buf->data + mhsz; | ||
169 | if (!dsz || !memcpy_fromiovecend(pktpos, iov, offset, dsz)) | ||
170 | return dsz; | ||
171 | rc = -EFAULT; | ||
172 | goto error; | ||
173 | } | ||
174 | |||
175 | /* Prepare reusable fragment header */ | ||
176 | tipc_msg_init(&pkthdr, MSG_FRAGMENTER, FIRST_FRAGMENT, | ||
177 | INT_H_SIZE, msg_destnode(mhdr)); | ||
178 | msg_set_size(&pkthdr, pktmax); | ||
179 | msg_set_fragm_no(&pkthdr, pktno); | ||
180 | |||
181 | /* Prepare first fragment */ | ||
182 | *chain = buf = tipc_buf_acquire(pktmax); | ||
183 | if (!buf) | ||
184 | return -ENOMEM; | ||
185 | pktpos = buf->data; | ||
186 | skb_copy_to_linear_data(buf, &pkthdr, INT_H_SIZE); | ||
187 | pktpos += INT_H_SIZE; | ||
188 | pktrem -= INT_H_SIZE; | ||
189 | skb_copy_to_linear_data_offset(buf, INT_H_SIZE, mhdr, mhsz); | ||
190 | pktpos += mhsz; | ||
191 | pktrem -= mhsz; | ||
192 | |||
193 | do { | ||
194 | if (drem < pktrem) | ||
195 | pktrem = drem; | ||
196 | |||
197 | if (memcpy_fromiovecend(pktpos, iov, offset, pktrem)) { | ||
198 | rc = -EFAULT; | ||
199 | goto error; | ||
200 | } | ||
201 | drem -= pktrem; | ||
202 | offset += pktrem; | ||
203 | |||
204 | if (!drem) | ||
205 | break; | ||
206 | |||
207 | /* Prepare new fragment: */ | ||
208 | if (drem < (pktmax - INT_H_SIZE)) | ||
209 | pktsz = drem + INT_H_SIZE; | ||
210 | else | ||
211 | pktsz = pktmax; | ||
212 | prev = buf; | ||
213 | buf = tipc_buf_acquire(pktsz); | ||
214 | if (!buf) { | ||
215 | rc = -ENOMEM; | ||
216 | goto error; | ||
217 | } | ||
218 | prev->next = buf; | ||
219 | msg_set_type(&pkthdr, FRAGMENT); | ||
220 | msg_set_size(&pkthdr, pktsz); | ||
221 | msg_set_fragm_no(&pkthdr, ++pktno); | ||
222 | skb_copy_to_linear_data(buf, &pkthdr, INT_H_SIZE); | ||
223 | pktpos = buf->data + INT_H_SIZE; | ||
224 | pktrem = pktsz - INT_H_SIZE; | ||
225 | |||
226 | } while (1); | ||
227 | |||
228 | msg_set_type(buf_msg(buf), LAST_FRAGMENT); | ||
229 | return dsz; | ||
230 | error: | ||
231 | kfree_skb_list(*chain); | ||
232 | *chain = NULL; | ||
233 | return rc; | ||
234 | } | ||
235 | |||
236 | /** | ||
237 | * tipc_msg_bundle(): Append contents of a buffer to tail of an existing one | ||
238 | * @bbuf: the existing buffer ("bundle") | ||
239 | * @buf: buffer to be appended | ||
240 | * @mtu: max allowable size for the bundle buffer | ||
241 | * Consumes buffer if successful | ||
242 | * Returns true if bundling could be performed, otherwise false | ||
243 | */ | ||
244 | bool tipc_msg_bundle(struct sk_buff *bbuf, struct sk_buff *buf, u32 mtu) | ||
245 | { | ||
246 | struct tipc_msg *bmsg = buf_msg(bbuf); | ||
247 | struct tipc_msg *msg = buf_msg(buf); | ||
248 | unsigned int bsz = msg_size(bmsg); | ||
249 | unsigned int msz = msg_size(msg); | ||
250 | u32 start = align(bsz); | ||
251 | u32 max = mtu - INT_H_SIZE; | ||
252 | u32 pad = start - bsz; | ||
253 | |||
254 | if (likely(msg_user(msg) == MSG_FRAGMENTER)) | ||
255 | return false; | ||
256 | if (unlikely(msg_user(msg) == CHANGEOVER_PROTOCOL)) | ||
257 | return false; | ||
258 | if (unlikely(msg_user(msg) == BCAST_PROTOCOL)) | ||
259 | return false; | ||
260 | if (likely(msg_user(bmsg) != MSG_BUNDLER)) | ||
261 | return false; | ||
262 | if (likely(msg_type(bmsg) != BUNDLE_OPEN)) | ||
263 | return false; | ||
264 | if (unlikely(skb_tailroom(bbuf) < (pad + msz))) | ||
265 | return false; | ||
266 | if (unlikely(max < (start + msz))) | ||
267 | return false; | ||
268 | |||
269 | skb_put(bbuf, pad + msz); | ||
270 | skb_copy_to_linear_data_offset(bbuf, start, buf->data, msz); | ||
271 | msg_set_size(bmsg, start + msz); | ||
272 | msg_set_msgcnt(bmsg, msg_msgcnt(bmsg) + 1); | ||
273 | bbuf->next = buf->next; | ||
274 | kfree_skb(buf); | ||
275 | return true; | ||
276 | } | ||
277 | |||
278 | /** | ||
279 | * tipc_msg_make_bundle(): Create bundle buf and append message to its tail | ||
280 | * @buf: buffer to be appended and replaced | ||
281 | * @mtu: max allowable size for the bundle buffer, inclusive header | ||
282 | * @dnode: destination node for message. (Not always present in header) | ||
283 | * Replaces buffer if successful | ||
284 | * Returns true if sucess, otherwise false | ||
285 | */ | ||
286 | bool tipc_msg_make_bundle(struct sk_buff **buf, u32 mtu, u32 dnode) | ||
287 | { | ||
288 | struct sk_buff *bbuf; | ||
289 | struct tipc_msg *bmsg; | ||
290 | struct tipc_msg *msg = buf_msg(*buf); | ||
291 | u32 msz = msg_size(msg); | ||
292 | u32 max = mtu - INT_H_SIZE; | ||
293 | |||
294 | if (msg_user(msg) == MSG_FRAGMENTER) | ||
295 | return false; | ||
296 | if (msg_user(msg) == CHANGEOVER_PROTOCOL) | ||
297 | return false; | ||
298 | if (msg_user(msg) == BCAST_PROTOCOL) | ||
299 | return false; | ||
300 | if (msz > (max / 2)) | ||
301 | return false; | ||
302 | |||
303 | bbuf = tipc_buf_acquire(max); | ||
304 | if (!bbuf) | ||
305 | return false; | ||
306 | |||
307 | skb_trim(bbuf, INT_H_SIZE); | ||
308 | bmsg = buf_msg(bbuf); | ||
309 | tipc_msg_init(bmsg, MSG_BUNDLER, BUNDLE_OPEN, INT_H_SIZE, dnode); | ||
310 | msg_set_seqno(bmsg, msg_seqno(msg)); | ||
311 | msg_set_ack(bmsg, msg_ack(msg)); | ||
312 | msg_set_bcast_ack(bmsg, msg_bcast_ack(msg)); | ||
313 | bbuf->next = (*buf)->next; | ||
314 | tipc_msg_bundle(bbuf, *buf, mtu); | ||
315 | *buf = bbuf; | ||
316 | return true; | ||
317 | } | ||
318 | |||
319 | /** | ||
320 | * tipc_msg_reverse(): swap source and destination addresses and add error code | ||
321 | * @buf: buffer containing message to be reversed | ||
322 | * @dnode: return value: node where to send message after reversal | ||
323 | * @err: error code to be set in message | ||
324 | * Consumes buffer if failure | ||
325 | * Returns true if success, otherwise false | ||
326 | */ | ||
327 | bool tipc_msg_reverse(struct sk_buff *buf, u32 *dnode, int err) | ||
328 | { | ||
329 | struct tipc_msg *msg = buf_msg(buf); | ||
330 | uint imp = msg_importance(msg); | ||
331 | struct tipc_msg ohdr; | ||
332 | uint rdsz = min_t(uint, msg_data_sz(msg), MAX_FORWARD_SIZE); | ||
333 | |||
334 | if (skb_linearize(buf)) | ||
335 | goto exit; | ||
336 | if (msg_dest_droppable(msg)) | ||
337 | goto exit; | ||
338 | if (msg_errcode(msg)) | ||
339 | goto exit; | ||
340 | |||
341 | memcpy(&ohdr, msg, msg_hdr_sz(msg)); | ||
342 | imp = min_t(uint, imp + 1, TIPC_CRITICAL_IMPORTANCE); | ||
343 | if (msg_isdata(msg)) | ||
344 | msg_set_importance(msg, imp); | ||
345 | msg_set_errcode(msg, err); | ||
346 | msg_set_origport(msg, msg_destport(&ohdr)); | ||
347 | msg_set_destport(msg, msg_origport(&ohdr)); | ||
348 | msg_set_prevnode(msg, tipc_own_addr); | ||
349 | if (!msg_short(msg)) { | ||
350 | msg_set_orignode(msg, msg_destnode(&ohdr)); | ||
351 | msg_set_destnode(msg, msg_orignode(&ohdr)); | ||
352 | } | ||
353 | msg_set_size(msg, msg_hdr_sz(msg) + rdsz); | ||
354 | skb_trim(buf, msg_size(msg)); | ||
355 | skb_orphan(buf); | ||
356 | *dnode = msg_orignode(&ohdr); | ||
357 | return true; | ||
358 | exit: | ||
359 | kfree_skb(buf); | ||
360 | return false; | ||
361 | } | ||
362 | |||
363 | /** | ||
364 | * tipc_msg_eval: determine fate of message that found no destination | ||
365 | * @buf: the buffer containing the message. | ||
366 | * @dnode: return value: next-hop node, if message to be forwarded | ||
367 | * @err: error code to use, if message to be rejected | ||
368 | * | ||
369 | * Does not consume buffer | ||
370 | * Returns 0 (TIPC_OK) if message ok and we can try again, -TIPC error | ||
371 | * code if message to be rejected | ||
372 | */ | ||
373 | int tipc_msg_eval(struct sk_buff *buf, u32 *dnode) | ||
374 | { | ||
375 | struct tipc_msg *msg = buf_msg(buf); | ||
376 | u32 dport; | ||
377 | |||
378 | if (msg_type(msg) != TIPC_NAMED_MSG) | ||
379 | return -TIPC_ERR_NO_PORT; | ||
380 | if (skb_linearize(buf)) | ||
381 | return -TIPC_ERR_NO_NAME; | ||
382 | if (msg_data_sz(msg) > MAX_FORWARD_SIZE) | ||
383 | return -TIPC_ERR_NO_NAME; | ||
384 | if (msg_reroute_cnt(msg) > 0) | ||
385 | return -TIPC_ERR_NO_NAME; | ||
386 | |||
387 | *dnode = addr_domain(msg_lookup_scope(msg)); | ||
388 | dport = tipc_nametbl_translate(msg_nametype(msg), | ||
389 | msg_nameinst(msg), | ||
390 | dnode); | ||
391 | if (!dport) | ||
392 | return -TIPC_ERR_NO_NAME; | ||
393 | msg_incr_reroute_cnt(msg); | ||
394 | msg_set_destnode(msg, *dnode); | ||
395 | msg_set_destport(msg, dport); | ||
396 | return TIPC_OK; | ||
397 | } | ||
398 | |||
399 | /* tipc_msg_reassemble() - clone a buffer chain of fragments and | ||
400 | * reassemble the clones into one message | ||
401 | */ | ||
402 | struct sk_buff *tipc_msg_reassemble(struct sk_buff *chain) | ||
403 | { | ||
404 | struct sk_buff *buf = chain; | ||
405 | struct sk_buff *frag = buf; | ||
406 | struct sk_buff *head = NULL; | ||
407 | int hdr_sz; | ||
408 | |||
409 | /* Copy header if single buffer */ | ||
410 | if (!buf->next) { | ||
411 | hdr_sz = skb_headroom(buf) + msg_hdr_sz(buf_msg(buf)); | ||
412 | return __pskb_copy(buf, hdr_sz, GFP_ATOMIC); | ||
413 | } | ||
414 | |||
415 | /* Clone all fragments and reassemble */ | ||
416 | while (buf) { | ||
417 | frag = skb_clone(buf, GFP_ATOMIC); | ||
418 | if (!frag) | ||
419 | goto error; | ||
420 | frag->next = NULL; | ||
421 | if (tipc_buf_append(&head, &frag)) | ||
422 | break; | ||
423 | if (!head) | ||
424 | goto error; | ||
425 | buf = buf->next; | ||
426 | } | ||
427 | return frag; | ||
428 | error: | ||
429 | pr_warn("Failed do clone local mcast rcv buffer\n"); | ||
430 | kfree_skb(head); | ||
431 | return NULL; | ||
432 | } | ||
diff --git a/net/tipc/msg.h b/net/tipc/msg.h index 503511903d1d..462fa194a6af 100644 --- a/net/tipc/msg.h +++ b/net/tipc/msg.h | |||
@@ -463,6 +463,11 @@ static inline struct tipc_msg *msg_get_wrapped(struct tipc_msg *m) | |||
463 | #define FRAGMENT 1 | 463 | #define FRAGMENT 1 |
464 | #define LAST_FRAGMENT 2 | 464 | #define LAST_FRAGMENT 2 |
465 | 465 | ||
466 | /* Bundling protocol message types | ||
467 | */ | ||
468 | #define BUNDLE_OPEN 0 | ||
469 | #define BUNDLE_CLOSED 1 | ||
470 | |||
466 | /* | 471 | /* |
467 | * Link management protocol message types | 472 | * Link management protocol message types |
468 | */ | 473 | */ |
@@ -706,12 +711,36 @@ static inline void msg_set_link_tolerance(struct tipc_msg *m, u32 n) | |||
706 | msg_set_bits(m, 9, 0, 0xffff, n); | 711 | msg_set_bits(m, 9, 0, 0xffff, n); |
707 | } | 712 | } |
708 | 713 | ||
709 | u32 tipc_msg_tot_importance(struct tipc_msg *m); | 714 | static inline u32 tipc_msg_tot_importance(struct tipc_msg *m) |
715 | { | ||
716 | if ((msg_user(m) == MSG_FRAGMENTER) && (msg_type(m) == FIRST_FRAGMENT)) | ||
717 | return msg_importance(msg_get_wrapped(m)); | ||
718 | return msg_importance(m); | ||
719 | } | ||
720 | |||
721 | static inline u32 msg_tot_origport(struct tipc_msg *m) | ||
722 | { | ||
723 | if ((msg_user(m) == MSG_FRAGMENTER) && (msg_type(m) == FIRST_FRAGMENT)) | ||
724 | return msg_origport(msg_get_wrapped(m)); | ||
725 | return msg_origport(m); | ||
726 | } | ||
727 | |||
728 | bool tipc_msg_reverse(struct sk_buff *buf, u32 *dnode, int err); | ||
729 | |||
730 | int tipc_msg_eval(struct sk_buff *buf, u32 *dnode); | ||
731 | |||
710 | void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize, | 732 | void tipc_msg_init(struct tipc_msg *m, u32 user, u32 type, u32 hsize, |
711 | u32 destnode); | 733 | u32 destnode); |
712 | int tipc_msg_build(struct tipc_msg *hdr, struct iovec const *msg_sect, | ||
713 | unsigned int len, int max_size, struct sk_buff **buf); | ||
714 | 734 | ||
715 | int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf); | 735 | int tipc_buf_append(struct sk_buff **headbuf, struct sk_buff **buf); |
716 | 736 | ||
737 | bool tipc_msg_bundle(struct sk_buff *bbuf, struct sk_buff *buf, u32 mtu); | ||
738 | |||
739 | bool tipc_msg_make_bundle(struct sk_buff **buf, u32 mtu, u32 dnode); | ||
740 | |||
741 | int tipc_msg_build(struct tipc_msg *mhdr, struct iovec const *iov, | ||
742 | int offset, int dsz, int mtu , struct sk_buff **chain); | ||
743 | |||
744 | struct sk_buff *tipc_msg_reassemble(struct sk_buff *chain); | ||
745 | |||
717 | #endif | 746 | #endif |
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index 8ce730984aa1..dcc15bcd5692 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c | |||
@@ -101,24 +101,22 @@ static struct sk_buff *named_prepare_buf(u32 type, u32 size, u32 dest) | |||
101 | 101 | ||
102 | void named_cluster_distribute(struct sk_buff *buf) | 102 | void named_cluster_distribute(struct sk_buff *buf) |
103 | { | 103 | { |
104 | struct sk_buff *buf_copy; | 104 | struct sk_buff *obuf; |
105 | struct tipc_node *n_ptr; | 105 | struct tipc_node *node; |
106 | struct tipc_link *l_ptr; | 106 | u32 dnode; |
107 | 107 | ||
108 | rcu_read_lock(); | 108 | rcu_read_lock(); |
109 | list_for_each_entry_rcu(n_ptr, &tipc_node_list, list) { | 109 | list_for_each_entry_rcu(node, &tipc_node_list, list) { |
110 | tipc_node_lock(n_ptr); | 110 | dnode = node->addr; |
111 | l_ptr = n_ptr->active_links[n_ptr->addr & 1]; | 111 | if (in_own_node(dnode)) |
112 | if (l_ptr) { | 112 | continue; |
113 | buf_copy = skb_copy(buf, GFP_ATOMIC); | 113 | if (!tipc_node_active_links(node)) |
114 | if (!buf_copy) { | 114 | continue; |
115 | tipc_node_unlock(n_ptr); | 115 | obuf = skb_copy(buf, GFP_ATOMIC); |
116 | break; | 116 | if (!obuf) |
117 | } | 117 | break; |
118 | msg_set_destnode(buf_msg(buf_copy), n_ptr->addr); | 118 | msg_set_destnode(buf_msg(obuf), dnode); |
119 | __tipc_link_xmit(l_ptr, buf_copy); | 119 | tipc_link_xmit(obuf, dnode, dnode); |
120 | } | ||
121 | tipc_node_unlock(n_ptr); | ||
122 | } | 120 | } |
123 | rcu_read_unlock(); | 121 | rcu_read_unlock(); |
124 | 122 | ||
@@ -175,34 +173,44 @@ struct sk_buff *tipc_named_withdraw(struct publication *publ) | |||
175 | return buf; | 173 | return buf; |
176 | } | 174 | } |
177 | 175 | ||
178 | /* | 176 | /** |
179 | * named_distribute - prepare name info for bulk distribution to another node | 177 | * named_distribute - prepare name info for bulk distribution to another node |
178 | * @msg_list: list of messages (buffers) to be returned from this function | ||
179 | * @dnode: node to be updated | ||
180 | * @pls: linked list of publication items to be packed into buffer chain | ||
180 | */ | 181 | */ |
181 | static void named_distribute(struct list_head *message_list, u32 node, | 182 | static void named_distribute(struct list_head *msg_list, u32 dnode, |
182 | struct publ_list *pls, u32 max_item_buf) | 183 | struct publ_list *pls) |
183 | { | 184 | { |
184 | struct publication *publ; | 185 | struct publication *publ; |
185 | struct sk_buff *buf = NULL; | 186 | struct sk_buff *buf = NULL; |
186 | struct distr_item *item = NULL; | 187 | struct distr_item *item = NULL; |
187 | u32 left = 0; | 188 | uint dsz = pls->size * ITEM_SIZE; |
188 | u32 rest = pls->size * ITEM_SIZE; | 189 | uint msg_dsz = (tipc_node_get_mtu(dnode, 0) / ITEM_SIZE) * ITEM_SIZE; |
190 | uint rem = dsz; | ||
191 | uint msg_rem = 0; | ||
189 | 192 | ||
190 | list_for_each_entry(publ, &pls->list, local_list) { | 193 | list_for_each_entry(publ, &pls->list, local_list) { |
194 | /* Prepare next buffer: */ | ||
191 | if (!buf) { | 195 | if (!buf) { |
192 | left = (rest <= max_item_buf) ? rest : max_item_buf; | 196 | msg_rem = min_t(uint, rem, msg_dsz); |
193 | rest -= left; | 197 | rem -= msg_rem; |
194 | buf = named_prepare_buf(PUBLICATION, left, node); | 198 | buf = named_prepare_buf(PUBLICATION, msg_rem, dnode); |
195 | if (!buf) { | 199 | if (!buf) { |
196 | pr_warn("Bulk publication failure\n"); | 200 | pr_warn("Bulk publication failure\n"); |
197 | return; | 201 | return; |
198 | } | 202 | } |
199 | item = (struct distr_item *)msg_data(buf_msg(buf)); | 203 | item = (struct distr_item *)msg_data(buf_msg(buf)); |
200 | } | 204 | } |
205 | |||
206 | /* Pack publication into message: */ | ||
201 | publ_to_item(item, publ); | 207 | publ_to_item(item, publ); |
202 | item++; | 208 | item++; |
203 | left -= ITEM_SIZE; | 209 | msg_rem -= ITEM_SIZE; |
204 | if (!left) { | 210 | |
205 | list_add_tail((struct list_head *)buf, message_list); | 211 | /* Append full buffer to list: */ |
212 | if (!msg_rem) { | ||
213 | list_add_tail((struct list_head *)buf, msg_list); | ||
206 | buf = NULL; | 214 | buf = NULL; |
207 | } | 215 | } |
208 | } | 216 | } |
@@ -211,16 +219,20 @@ static void named_distribute(struct list_head *message_list, u32 node, | |||
211 | /** | 219 | /** |
212 | * tipc_named_node_up - tell specified node about all publications by this node | 220 | * tipc_named_node_up - tell specified node about all publications by this node |
213 | */ | 221 | */ |
214 | void tipc_named_node_up(u32 max_item_buf, u32 node) | 222 | void tipc_named_node_up(u32 dnode) |
215 | { | 223 | { |
216 | LIST_HEAD(message_list); | 224 | LIST_HEAD(msg_list); |
225 | struct sk_buff *buf_chain; | ||
217 | 226 | ||
218 | read_lock_bh(&tipc_nametbl_lock); | 227 | read_lock_bh(&tipc_nametbl_lock); |
219 | named_distribute(&message_list, node, &publ_cluster, max_item_buf); | 228 | named_distribute(&msg_list, dnode, &publ_cluster); |
220 | named_distribute(&message_list, node, &publ_zone, max_item_buf); | 229 | named_distribute(&msg_list, dnode, &publ_zone); |
221 | read_unlock_bh(&tipc_nametbl_lock); | 230 | read_unlock_bh(&tipc_nametbl_lock); |
222 | 231 | ||
223 | tipc_link_names_xmit(&message_list, node); | 232 | /* Convert circular list to linear list and send: */ |
233 | buf_chain = (struct sk_buff *)msg_list.next; | ||
234 | ((struct sk_buff *)msg_list.prev)->next = NULL; | ||
235 | tipc_link_xmit(buf_chain, dnode, dnode); | ||
224 | } | 236 | } |
225 | 237 | ||
226 | /** | 238 | /** |
diff --git a/net/tipc/name_distr.h b/net/tipc/name_distr.h index b2eed4ec1526..8afe32b7fc9a 100644 --- a/net/tipc/name_distr.h +++ b/net/tipc/name_distr.h | |||
@@ -70,7 +70,7 @@ struct distr_item { | |||
70 | struct sk_buff *tipc_named_publish(struct publication *publ); | 70 | struct sk_buff *tipc_named_publish(struct publication *publ); |
71 | struct sk_buff *tipc_named_withdraw(struct publication *publ); | 71 | struct sk_buff *tipc_named_withdraw(struct publication *publ); |
72 | void named_cluster_distribute(struct sk_buff *buf); | 72 | void named_cluster_distribute(struct sk_buff *buf); |
73 | void tipc_named_node_up(u32 max_item_buf, u32 node); | 73 | void tipc_named_node_up(u32 dnode); |
74 | void tipc_named_rcv(struct sk_buff *buf); | 74 | void tipc_named_rcv(struct sk_buff *buf); |
75 | void tipc_named_reinit(void); | 75 | void tipc_named_reinit(void); |
76 | 76 | ||
diff --git a/net/tipc/net.c b/net/tipc/net.c index f64375e7f99f..7fcc94998fea 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * net/tipc/net.c: TIPC network routing code | 2 | * net/tipc/net.c: TIPC network routing code |
3 | * | 3 | * |
4 | * Copyright (c) 1995-2006, Ericsson AB | 4 | * Copyright (c) 1995-2006, 2014, Ericsson AB |
5 | * Copyright (c) 2005, 2010-2011, Wind River Systems | 5 | * Copyright (c) 2005, 2010-2011, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
@@ -104,67 +104,6 @@ | |||
104 | * - A local spin_lock protecting the queue of subscriber events. | 104 | * - A local spin_lock protecting the queue of subscriber events. |
105 | */ | 105 | */ |
106 | 106 | ||
107 | static void net_route_named_msg(struct sk_buff *buf) | ||
108 | { | ||
109 | struct tipc_msg *msg = buf_msg(buf); | ||
110 | u32 dnode; | ||
111 | u32 dport; | ||
112 | |||
113 | if (!msg_named(msg)) { | ||
114 | kfree_skb(buf); | ||
115 | return; | ||
116 | } | ||
117 | |||
118 | dnode = addr_domain(msg_lookup_scope(msg)); | ||
119 | dport = tipc_nametbl_translate(msg_nametype(msg), msg_nameinst(msg), &dnode); | ||
120 | if (dport) { | ||
121 | msg_set_destnode(msg, dnode); | ||
122 | msg_set_destport(msg, dport); | ||
123 | tipc_net_route_msg(buf); | ||
124 | return; | ||
125 | } | ||
126 | tipc_reject_msg(buf, TIPC_ERR_NO_NAME); | ||
127 | } | ||
128 | |||
129 | void tipc_net_route_msg(struct sk_buff *buf) | ||
130 | { | ||
131 | struct tipc_msg *msg; | ||
132 | u32 dnode; | ||
133 | |||
134 | if (!buf) | ||
135 | return; | ||
136 | msg = buf_msg(buf); | ||
137 | |||
138 | /* Handle message for this node */ | ||
139 | dnode = msg_short(msg) ? tipc_own_addr : msg_destnode(msg); | ||
140 | if (tipc_in_scope(dnode, tipc_own_addr)) { | ||
141 | if (msg_isdata(msg)) { | ||
142 | if (msg_mcast(msg)) | ||
143 | tipc_port_mcast_rcv(buf, NULL); | ||
144 | else if (msg_destport(msg)) | ||
145 | tipc_sk_rcv(buf); | ||
146 | else | ||
147 | net_route_named_msg(buf); | ||
148 | return; | ||
149 | } | ||
150 | switch (msg_user(msg)) { | ||
151 | case NAME_DISTRIBUTOR: | ||
152 | tipc_named_rcv(buf); | ||
153 | break; | ||
154 | case CONN_MANAGER: | ||
155 | tipc_port_proto_rcv(buf); | ||
156 | break; | ||
157 | default: | ||
158 | kfree_skb(buf); | ||
159 | } | ||
160 | return; | ||
161 | } | ||
162 | |||
163 | /* Handle message for another node */ | ||
164 | skb_trim(buf, msg_size(msg)); | ||
165 | tipc_link_xmit(buf, dnode, msg_link_selector(msg)); | ||
166 | } | ||
167 | |||
168 | int tipc_net_start(u32 addr) | 107 | int tipc_net_start(u32 addr) |
169 | { | 108 | { |
170 | char addr_string[16]; | 109 | char addr_string[16]; |
diff --git a/net/tipc/net.h b/net/tipc/net.h index c6c2b46f7c28..59ef3388be2c 100644 --- a/net/tipc/net.h +++ b/net/tipc/net.h | |||
@@ -37,8 +37,6 @@ | |||
37 | #ifndef _TIPC_NET_H | 37 | #ifndef _TIPC_NET_H |
38 | #define _TIPC_NET_H | 38 | #define _TIPC_NET_H |
39 | 39 | ||
40 | void tipc_net_route_msg(struct sk_buff *buf); | ||
41 | |||
42 | int tipc_net_start(u32 addr); | 40 | int tipc_net_start(u32 addr); |
43 | void tipc_net_stop(void); | 41 | void tipc_net_stop(void); |
44 | 42 | ||
diff --git a/net/tipc/node.c b/net/tipc/node.c index 5b44c3041be4..f7069299943f 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * net/tipc/node.c: TIPC node management routines | 2 | * net/tipc/node.c: TIPC node management routines |
3 | * | 3 | * |
4 | * Copyright (c) 2000-2006, 2012 Ericsson AB | 4 | * Copyright (c) 2000-2006, 2012-2014, Ericsson AB |
5 | * Copyright (c) 2005-2006, 2010-2014, Wind River Systems | 5 | * Copyright (c) 2005-2006, 2010-2014, Wind River Systems |
6 | * All rights reserved. | 6 | * All rights reserved. |
7 | * | 7 | * |
@@ -155,21 +155,25 @@ void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr) | |||
155 | if (!active[0]) { | 155 | if (!active[0]) { |
156 | active[0] = active[1] = l_ptr; | 156 | active[0] = active[1] = l_ptr; |
157 | node_established_contact(n_ptr); | 157 | node_established_contact(n_ptr); |
158 | return; | 158 | goto exit; |
159 | } | 159 | } |
160 | if (l_ptr->priority < active[0]->priority) { | 160 | if (l_ptr->priority < active[0]->priority) { |
161 | pr_info("New link <%s> becomes standby\n", l_ptr->name); | 161 | pr_info("New link <%s> becomes standby\n", l_ptr->name); |
162 | return; | 162 | goto exit; |
163 | } | 163 | } |
164 | tipc_link_dup_queue_xmit(active[0], l_ptr); | 164 | tipc_link_dup_queue_xmit(active[0], l_ptr); |
165 | if (l_ptr->priority == active[0]->priority) { | 165 | if (l_ptr->priority == active[0]->priority) { |
166 | active[0] = l_ptr; | 166 | active[0] = l_ptr; |
167 | return; | 167 | goto exit; |
168 | } | 168 | } |
169 | pr_info("Old link <%s> becomes standby\n", active[0]->name); | 169 | pr_info("Old link <%s> becomes standby\n", active[0]->name); |
170 | if (active[1] != active[0]) | 170 | if (active[1] != active[0]) |
171 | pr_info("Old link <%s> becomes standby\n", active[1]->name); | 171 | pr_info("Old link <%s> becomes standby\n", active[1]->name); |
172 | active[0] = active[1] = l_ptr; | 172 | active[0] = active[1] = l_ptr; |
173 | exit: | ||
174 | /* Leave room for changeover header when returning 'mtu' to users: */ | ||
175 | n_ptr->act_mtus[0] = active[0]->max_pkt - INT_H_SIZE; | ||
176 | n_ptr->act_mtus[1] = active[1]->max_pkt - INT_H_SIZE; | ||
173 | } | 177 | } |
174 | 178 | ||
175 | /** | 179 | /** |
@@ -229,6 +233,19 @@ void tipc_node_link_down(struct tipc_node *n_ptr, struct tipc_link *l_ptr) | |||
229 | tipc_link_failover_send_queue(l_ptr); | 233 | tipc_link_failover_send_queue(l_ptr); |
230 | else | 234 | else |
231 | node_lost_contact(n_ptr); | 235 | node_lost_contact(n_ptr); |
236 | |||
237 | /* Leave room for changeover header when returning 'mtu' to users: */ | ||
238 | if (active[0]) { | ||
239 | n_ptr->act_mtus[0] = active[0]->max_pkt - INT_H_SIZE; | ||
240 | n_ptr->act_mtus[1] = active[1]->max_pkt - INT_H_SIZE; | ||
241 | return; | ||
242 | } | ||
243 | |||
244 | /* Loopback link went down? No fragmentation needed from now on. */ | ||
245 | if (n_ptr->addr == tipc_own_addr) { | ||
246 | n_ptr->act_mtus[0] = MAX_MSG_SIZE; | ||
247 | n_ptr->act_mtus[1] = MAX_MSG_SIZE; | ||
248 | } | ||
232 | } | 249 | } |
233 | 250 | ||
234 | int tipc_node_active_links(struct tipc_node *n_ptr) | 251 | int tipc_node_active_links(struct tipc_node *n_ptr) |
@@ -457,8 +474,6 @@ int tipc_node_get_linkname(u32 bearer_id, u32 addr, char *linkname, size_t len) | |||
457 | void tipc_node_unlock(struct tipc_node *node) | 474 | void tipc_node_unlock(struct tipc_node *node) |
458 | { | 475 | { |
459 | LIST_HEAD(nsub_list); | 476 | LIST_HEAD(nsub_list); |
460 | struct tipc_link *link; | ||
461 | int pkt_sz = 0; | ||
462 | u32 addr = 0; | 477 | u32 addr = 0; |
463 | 478 | ||
464 | if (likely(!node->action_flags)) { | 479 | if (likely(!node->action_flags)) { |
@@ -471,18 +486,13 @@ void tipc_node_unlock(struct tipc_node *node) | |||
471 | node->action_flags &= ~TIPC_NOTIFY_NODE_DOWN; | 486 | node->action_flags &= ~TIPC_NOTIFY_NODE_DOWN; |
472 | } | 487 | } |
473 | if (node->action_flags & TIPC_NOTIFY_NODE_UP) { | 488 | if (node->action_flags & TIPC_NOTIFY_NODE_UP) { |
474 | link = node->active_links[0]; | ||
475 | node->action_flags &= ~TIPC_NOTIFY_NODE_UP; | 489 | node->action_flags &= ~TIPC_NOTIFY_NODE_UP; |
476 | if (link) { | 490 | addr = node->addr; |
477 | pkt_sz = ((link->max_pkt - INT_H_SIZE) / ITEM_SIZE) * | ||
478 | ITEM_SIZE; | ||
479 | addr = node->addr; | ||
480 | } | ||
481 | } | 491 | } |
482 | spin_unlock_bh(&node->lock); | 492 | spin_unlock_bh(&node->lock); |
483 | 493 | ||
484 | if (!list_empty(&nsub_list)) | 494 | if (!list_empty(&nsub_list)) |
485 | tipc_nodesub_notify(&nsub_list); | 495 | tipc_nodesub_notify(&nsub_list); |
486 | if (pkt_sz) | 496 | if (addr) |
487 | tipc_named_node_up(pkt_sz, addr); | 497 | tipc_named_node_up(addr); |
488 | } | 498 | } |
diff --git a/net/tipc/node.h b/net/tipc/node.h index 9087063793f2..b61716a8218e 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h | |||
@@ -41,6 +41,7 @@ | |||
41 | #include "addr.h" | 41 | #include "addr.h" |
42 | #include "net.h" | 42 | #include "net.h" |
43 | #include "bearer.h" | 43 | #include "bearer.h" |
44 | #include "msg.h" | ||
44 | 45 | ||
45 | /* | 46 | /* |
46 | * Out-of-range value for node signature | 47 | * Out-of-range value for node signature |
@@ -105,6 +106,7 @@ struct tipc_node { | |||
105 | spinlock_t lock; | 106 | spinlock_t lock; |
106 | struct hlist_node hash; | 107 | struct hlist_node hash; |
107 | struct tipc_link *active_links[2]; | 108 | struct tipc_link *active_links[2]; |
109 | u32 act_mtus[2]; | ||
108 | struct tipc_link *links[MAX_BEARERS]; | 110 | struct tipc_link *links[MAX_BEARERS]; |
109 | unsigned int action_flags; | 111 | unsigned int action_flags; |
110 | struct tipc_node_bclink bclink; | 112 | struct tipc_node_bclink bclink; |
@@ -143,4 +145,19 @@ static inline bool tipc_node_blocked(struct tipc_node *node) | |||
143 | TIPC_NOTIFY_NODE_DOWN | TIPC_WAIT_OWN_LINKS_DOWN)); | 145 | TIPC_NOTIFY_NODE_DOWN | TIPC_WAIT_OWN_LINKS_DOWN)); |
144 | } | 146 | } |
145 | 147 | ||
148 | static inline uint tipc_node_get_mtu(u32 addr, u32 selector) | ||
149 | { | ||
150 | struct tipc_node *node; | ||
151 | u32 mtu; | ||
152 | |||
153 | node = tipc_node_find(addr); | ||
154 | |||
155 | if (likely(node)) | ||
156 | mtu = node->act_mtus[selector & 1]; | ||
157 | else | ||
158 | mtu = MAX_MSG_SIZE; | ||
159 | |||
160 | return mtu; | ||
161 | } | ||
162 | |||
146 | #endif | 163 | #endif |
diff --git a/net/tipc/node_subscr.c b/net/tipc/node_subscr.c index 7c59ab1d6ecb..2d13eea8574a 100644 --- a/net/tipc/node_subscr.c +++ b/net/tipc/node_subscr.c | |||
@@ -84,11 +84,13 @@ void tipc_nodesub_unsubscribe(struct tipc_node_subscr *node_sub) | |||
84 | void tipc_nodesub_notify(struct list_head *nsub_list) | 84 | void tipc_nodesub_notify(struct list_head *nsub_list) |
85 | { | 85 | { |
86 | struct tipc_node_subscr *ns, *safe; | 86 | struct tipc_node_subscr *ns, *safe; |
87 | net_ev_handler handle_node_down; | ||
87 | 88 | ||
88 | list_for_each_entry_safe(ns, safe, nsub_list, nodesub_list) { | 89 | list_for_each_entry_safe(ns, safe, nsub_list, nodesub_list) { |
89 | if (ns->handle_node_down) { | 90 | handle_node_down = ns->handle_node_down; |
90 | ns->handle_node_down(ns->usr_handle); | 91 | if (handle_node_down) { |
91 | ns->handle_node_down = NULL; | 92 | ns->handle_node_down = NULL; |
93 | handle_node_down(ns->usr_handle); | ||
92 | } | 94 | } |
93 | } | 95 | } |
94 | } | 96 | } |
diff --git a/net/tipc/port.c b/net/tipc/port.c index 5fd7acce01ea..7e096a5e7701 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c | |||
@@ -42,8 +42,6 @@ | |||
42 | 42 | ||
43 | /* Connection management: */ | 43 | /* Connection management: */ |
44 | #define PROBING_INTERVAL 3600000 /* [ms] => 1 h */ | 44 | #define PROBING_INTERVAL 3600000 /* [ms] => 1 h */ |
45 | #define CONFIRMED 0 | ||
46 | #define PROBING 1 | ||
47 | 45 | ||
48 | #define MAX_REJECT_SIZE 1024 | 46 | #define MAX_REJECT_SIZE 1024 |
49 | 47 | ||
@@ -76,124 +74,6 @@ int tipc_port_peer_msg(struct tipc_port *p_ptr, struct tipc_msg *msg) | |||
76 | (!peernode && (orignode == tipc_own_addr)); | 74 | (!peernode && (orignode == tipc_own_addr)); |
77 | } | 75 | } |
78 | 76 | ||
79 | /** | ||
80 | * tipc_port_mcast_xmit - send a multicast message to local and remote | ||
81 | * destinations | ||
82 | */ | ||
83 | int tipc_port_mcast_xmit(struct tipc_port *oport, | ||
84 | struct tipc_name_seq const *seq, | ||
85 | struct iovec const *msg_sect, | ||
86 | unsigned int len) | ||
87 | { | ||
88 | struct tipc_msg *hdr; | ||
89 | struct sk_buff *buf; | ||
90 | struct sk_buff *ibuf = NULL; | ||
91 | struct tipc_port_list dports = {0, NULL, }; | ||
92 | int ext_targets; | ||
93 | int res; | ||
94 | |||
95 | /* Create multicast message */ | ||
96 | hdr = &oport->phdr; | ||
97 | msg_set_type(hdr, TIPC_MCAST_MSG); | ||
98 | msg_set_lookup_scope(hdr, TIPC_CLUSTER_SCOPE); | ||
99 | msg_set_destport(hdr, 0); | ||
100 | msg_set_destnode(hdr, 0); | ||
101 | msg_set_nametype(hdr, seq->type); | ||
102 | msg_set_namelower(hdr, seq->lower); | ||
103 | msg_set_nameupper(hdr, seq->upper); | ||
104 | msg_set_hdr_sz(hdr, MCAST_H_SIZE); | ||
105 | res = tipc_msg_build(hdr, msg_sect, len, MAX_MSG_SIZE, &buf); | ||
106 | if (unlikely(!buf)) | ||
107 | return res; | ||
108 | |||
109 | /* Figure out where to send multicast message */ | ||
110 | ext_targets = tipc_nametbl_mc_translate(seq->type, seq->lower, seq->upper, | ||
111 | TIPC_NODE_SCOPE, &dports); | ||
112 | |||
113 | /* Send message to destinations (duplicate it only if necessary) */ | ||
114 | if (ext_targets) { | ||
115 | if (dports.count != 0) { | ||
116 | ibuf = skb_copy(buf, GFP_ATOMIC); | ||
117 | if (ibuf == NULL) { | ||
118 | tipc_port_list_free(&dports); | ||
119 | kfree_skb(buf); | ||
120 | return -ENOMEM; | ||
121 | } | ||
122 | } | ||
123 | res = tipc_bclink_xmit(buf); | ||
124 | if ((res < 0) && (dports.count != 0)) | ||
125 | kfree_skb(ibuf); | ||
126 | } else { | ||
127 | ibuf = buf; | ||
128 | } | ||
129 | |||
130 | if (res >= 0) { | ||
131 | if (ibuf) | ||
132 | tipc_port_mcast_rcv(ibuf, &dports); | ||
133 | } else { | ||
134 | tipc_port_list_free(&dports); | ||
135 | } | ||
136 | return res; | ||
137 | } | ||
138 | |||
139 | /** | ||
140 | * tipc_port_mcast_rcv - deliver multicast message to all destination ports | ||
141 | * | ||
142 | * If there is no port list, perform a lookup to create one | ||
143 | */ | ||
144 | void tipc_port_mcast_rcv(struct sk_buff *buf, struct tipc_port_list *dp) | ||
145 | { | ||
146 | struct tipc_msg *msg; | ||
147 | struct tipc_port_list dports = {0, NULL, }; | ||
148 | struct tipc_port_list *item = dp; | ||
149 | int cnt = 0; | ||
150 | |||
151 | msg = buf_msg(buf); | ||
152 | |||
153 | /* Create destination port list, if one wasn't supplied */ | ||
154 | if (dp == NULL) { | ||
155 | tipc_nametbl_mc_translate(msg_nametype(msg), | ||
156 | msg_namelower(msg), | ||
157 | msg_nameupper(msg), | ||
158 | TIPC_CLUSTER_SCOPE, | ||
159 | &dports); | ||
160 | item = dp = &dports; | ||
161 | } | ||
162 | |||
163 | /* Deliver a copy of message to each destination port */ | ||
164 | if (dp->count != 0) { | ||
165 | msg_set_destnode(msg, tipc_own_addr); | ||
166 | if (dp->count == 1) { | ||
167 | msg_set_destport(msg, dp->ports[0]); | ||
168 | tipc_sk_rcv(buf); | ||
169 | tipc_port_list_free(dp); | ||
170 | return; | ||
171 | } | ||
172 | for (; cnt < dp->count; cnt++) { | ||
173 | int index = cnt % PLSIZE; | ||
174 | struct sk_buff *b = skb_clone(buf, GFP_ATOMIC); | ||
175 | |||
176 | if (b == NULL) { | ||
177 | pr_warn("Unable to deliver multicast message(s)\n"); | ||
178 | goto exit; | ||
179 | } | ||
180 | if ((index == 0) && (cnt != 0)) | ||
181 | item = item->next; | ||
182 | msg_set_destport(buf_msg(b), item->ports[index]); | ||
183 | tipc_sk_rcv(b); | ||
184 | } | ||
185 | } | ||
186 | exit: | ||
187 | kfree_skb(buf); | ||
188 | tipc_port_list_free(dp); | ||
189 | } | ||
190 | |||
191 | |||
192 | void tipc_port_wakeup(struct tipc_port *port) | ||
193 | { | ||
194 | tipc_sock_wakeup(tipc_port_to_sock(port)); | ||
195 | } | ||
196 | |||
197 | /* tipc_port_init - intiate TIPC port and lock it | 77 | /* tipc_port_init - intiate TIPC port and lock it |
198 | * | 78 | * |
199 | * Returns obtained reference if initialization is successful, zero otherwise | 79 | * Returns obtained reference if initialization is successful, zero otherwise |
@@ -235,6 +115,8 @@ u32 tipc_port_init(struct tipc_port *p_ptr, | |||
235 | void tipc_port_destroy(struct tipc_port *p_ptr) | 115 | void tipc_port_destroy(struct tipc_port *p_ptr) |
236 | { | 116 | { |
237 | struct sk_buff *buf = NULL; | 117 | struct sk_buff *buf = NULL; |
118 | struct tipc_msg *msg = NULL; | ||
119 | u32 peer; | ||
238 | 120 | ||
239 | tipc_withdraw(p_ptr, 0, NULL); | 121 | tipc_withdraw(p_ptr, 0, NULL); |
240 | 122 | ||
@@ -246,14 +128,15 @@ void tipc_port_destroy(struct tipc_port *p_ptr) | |||
246 | if (p_ptr->connected) { | 128 | if (p_ptr->connected) { |
247 | buf = port_build_peer_abort_msg(p_ptr, TIPC_ERR_NO_PORT); | 129 | buf = port_build_peer_abort_msg(p_ptr, TIPC_ERR_NO_PORT); |
248 | tipc_nodesub_unsubscribe(&p_ptr->subscription); | 130 | tipc_nodesub_unsubscribe(&p_ptr->subscription); |
131 | msg = buf_msg(buf); | ||
132 | peer = msg_destnode(msg); | ||
133 | tipc_link_xmit(buf, peer, msg_link_selector(msg)); | ||
249 | } | 134 | } |
250 | |||
251 | spin_lock_bh(&tipc_port_list_lock); | 135 | spin_lock_bh(&tipc_port_list_lock); |
252 | list_del(&p_ptr->port_list); | 136 | list_del(&p_ptr->port_list); |
253 | list_del(&p_ptr->wait_list); | 137 | list_del(&p_ptr->wait_list); |
254 | spin_unlock_bh(&tipc_port_list_lock); | 138 | spin_unlock_bh(&tipc_port_list_lock); |
255 | k_term_timer(&p_ptr->timer); | 139 | k_term_timer(&p_ptr->timer); |
256 | tipc_net_route_msg(buf); | ||
257 | } | 140 | } |
258 | 141 | ||
259 | /* | 142 | /* |
@@ -275,100 +158,16 @@ static struct sk_buff *port_build_proto_msg(struct tipc_port *p_ptr, | |||
275 | msg_set_destport(msg, tipc_port_peerport(p_ptr)); | 158 | msg_set_destport(msg, tipc_port_peerport(p_ptr)); |
276 | msg_set_origport(msg, p_ptr->ref); | 159 | msg_set_origport(msg, p_ptr->ref); |
277 | msg_set_msgcnt(msg, ack); | 160 | msg_set_msgcnt(msg, ack); |
161 | buf->next = NULL; | ||
278 | } | 162 | } |
279 | return buf; | 163 | return buf; |
280 | } | 164 | } |
281 | 165 | ||
282 | int tipc_reject_msg(struct sk_buff *buf, u32 err) | ||
283 | { | ||
284 | struct tipc_msg *msg = buf_msg(buf); | ||
285 | struct sk_buff *rbuf; | ||
286 | struct tipc_msg *rmsg; | ||
287 | int hdr_sz; | ||
288 | u32 imp; | ||
289 | u32 data_sz = msg_data_sz(msg); | ||
290 | u32 src_node; | ||
291 | u32 rmsg_sz; | ||
292 | |||
293 | /* discard rejected message if it shouldn't be returned to sender */ | ||
294 | if (WARN(!msg_isdata(msg), | ||
295 | "attempt to reject message with user=%u", msg_user(msg))) { | ||
296 | dump_stack(); | ||
297 | goto exit; | ||
298 | } | ||
299 | if (msg_errcode(msg) || msg_dest_droppable(msg)) | ||
300 | goto exit; | ||
301 | |||
302 | /* | ||
303 | * construct returned message by copying rejected message header and | ||
304 | * data (or subset), then updating header fields that need adjusting | ||
305 | */ | ||
306 | hdr_sz = msg_hdr_sz(msg); | ||
307 | rmsg_sz = hdr_sz + min_t(u32, data_sz, MAX_REJECT_SIZE); | ||
308 | |||
309 | rbuf = tipc_buf_acquire(rmsg_sz); | ||
310 | if (rbuf == NULL) | ||
311 | goto exit; | ||
312 | |||
313 | rmsg = buf_msg(rbuf); | ||
314 | skb_copy_to_linear_data(rbuf, msg, rmsg_sz); | ||
315 | |||
316 | if (msg_connected(rmsg)) { | ||
317 | imp = msg_importance(rmsg); | ||
318 | if (imp < TIPC_CRITICAL_IMPORTANCE) | ||
319 | msg_set_importance(rmsg, ++imp); | ||
320 | } | ||
321 | msg_set_non_seq(rmsg, 0); | ||
322 | msg_set_size(rmsg, rmsg_sz); | ||
323 | msg_set_errcode(rmsg, err); | ||
324 | msg_set_prevnode(rmsg, tipc_own_addr); | ||
325 | msg_swap_words(rmsg, 4, 5); | ||
326 | if (!msg_short(rmsg)) | ||
327 | msg_swap_words(rmsg, 6, 7); | ||
328 | |||
329 | /* send self-abort message when rejecting on a connected port */ | ||
330 | if (msg_connected(msg)) { | ||
331 | struct tipc_port *p_ptr = tipc_port_lock(msg_destport(msg)); | ||
332 | |||
333 | if (p_ptr) { | ||
334 | struct sk_buff *abuf = NULL; | ||
335 | |||
336 | if (p_ptr->connected) | ||
337 | abuf = port_build_self_abort_msg(p_ptr, err); | ||
338 | tipc_port_unlock(p_ptr); | ||
339 | tipc_net_route_msg(abuf); | ||
340 | } | ||
341 | } | ||
342 | |||
343 | /* send returned message & dispose of rejected message */ | ||
344 | src_node = msg_prevnode(msg); | ||
345 | if (in_own_node(src_node)) | ||
346 | tipc_sk_rcv(rbuf); | ||
347 | else | ||
348 | tipc_link_xmit(rbuf, src_node, msg_link_selector(rmsg)); | ||
349 | exit: | ||
350 | kfree_skb(buf); | ||
351 | return data_sz; | ||
352 | } | ||
353 | |||
354 | int tipc_port_iovec_reject(struct tipc_port *p_ptr, struct tipc_msg *hdr, | ||
355 | struct iovec const *msg_sect, unsigned int len, | ||
356 | int err) | ||
357 | { | ||
358 | struct sk_buff *buf; | ||
359 | int res; | ||
360 | |||
361 | res = tipc_msg_build(hdr, msg_sect, len, MAX_MSG_SIZE, &buf); | ||
362 | if (!buf) | ||
363 | return res; | ||
364 | |||
365 | return tipc_reject_msg(buf, err); | ||
366 | } | ||
367 | |||
368 | static void port_timeout(unsigned long ref) | 166 | static void port_timeout(unsigned long ref) |
369 | { | 167 | { |
370 | struct tipc_port *p_ptr = tipc_port_lock(ref); | 168 | struct tipc_port *p_ptr = tipc_port_lock(ref); |
371 | struct sk_buff *buf = NULL; | 169 | struct sk_buff *buf = NULL; |
170 | struct tipc_msg *msg = NULL; | ||
372 | 171 | ||
373 | if (!p_ptr) | 172 | if (!p_ptr) |
374 | return; | 173 | return; |
@@ -379,15 +178,16 @@ static void port_timeout(unsigned long ref) | |||
379 | } | 178 | } |
380 | 179 | ||
381 | /* Last probe answered ? */ | 180 | /* Last probe answered ? */ |
382 | if (p_ptr->probing_state == PROBING) { | 181 | if (p_ptr->probing_state == TIPC_CONN_PROBING) { |
383 | buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_PORT); | 182 | buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_PORT); |
384 | } else { | 183 | } else { |
385 | buf = port_build_proto_msg(p_ptr, CONN_PROBE, 0); | 184 | buf = port_build_proto_msg(p_ptr, CONN_PROBE, 0); |
386 | p_ptr->probing_state = PROBING; | 185 | p_ptr->probing_state = TIPC_CONN_PROBING; |
387 | k_start_timer(&p_ptr->timer, p_ptr->probing_interval); | 186 | k_start_timer(&p_ptr->timer, p_ptr->probing_interval); |
388 | } | 187 | } |
389 | tipc_port_unlock(p_ptr); | 188 | tipc_port_unlock(p_ptr); |
390 | tipc_net_route_msg(buf); | 189 | msg = buf_msg(buf); |
190 | tipc_link_xmit(buf, msg_destnode(msg), msg_link_selector(msg)); | ||
391 | } | 191 | } |
392 | 192 | ||
393 | 193 | ||
@@ -395,12 +195,14 @@ static void port_handle_node_down(unsigned long ref) | |||
395 | { | 195 | { |
396 | struct tipc_port *p_ptr = tipc_port_lock(ref); | 196 | struct tipc_port *p_ptr = tipc_port_lock(ref); |
397 | struct sk_buff *buf = NULL; | 197 | struct sk_buff *buf = NULL; |
198 | struct tipc_msg *msg = NULL; | ||
398 | 199 | ||
399 | if (!p_ptr) | 200 | if (!p_ptr) |
400 | return; | 201 | return; |
401 | buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_NODE); | 202 | buf = port_build_self_abort_msg(p_ptr, TIPC_ERR_NO_NODE); |
402 | tipc_port_unlock(p_ptr); | 203 | tipc_port_unlock(p_ptr); |
403 | tipc_net_route_msg(buf); | 204 | msg = buf_msg(buf); |
205 | tipc_link_xmit(buf, msg_destnode(msg), msg_link_selector(msg)); | ||
404 | } | 206 | } |
405 | 207 | ||
406 | 208 | ||
@@ -412,6 +214,7 @@ static struct sk_buff *port_build_self_abort_msg(struct tipc_port *p_ptr, u32 er | |||
412 | struct tipc_msg *msg = buf_msg(buf); | 214 | struct tipc_msg *msg = buf_msg(buf); |
413 | msg_swap_words(msg, 4, 5); | 215 | msg_swap_words(msg, 4, 5); |
414 | msg_swap_words(msg, 6, 7); | 216 | msg_swap_words(msg, 6, 7); |
217 | buf->next = NULL; | ||
415 | } | 218 | } |
416 | return buf; | 219 | return buf; |
417 | } | 220 | } |
@@ -436,60 +239,11 @@ static struct sk_buff *port_build_peer_abort_msg(struct tipc_port *p_ptr, u32 er | |||
436 | if (imp < TIPC_CRITICAL_IMPORTANCE) | 239 | if (imp < TIPC_CRITICAL_IMPORTANCE) |
437 | msg_set_importance(msg, ++imp); | 240 | msg_set_importance(msg, ++imp); |
438 | msg_set_errcode(msg, err); | 241 | msg_set_errcode(msg, err); |
242 | buf->next = NULL; | ||
439 | } | 243 | } |
440 | return buf; | 244 | return buf; |
441 | } | 245 | } |
442 | 246 | ||
443 | void tipc_port_proto_rcv(struct sk_buff *buf) | ||
444 | { | ||
445 | struct tipc_msg *msg = buf_msg(buf); | ||
446 | struct tipc_port *p_ptr; | ||
447 | struct sk_buff *r_buf = NULL; | ||
448 | u32 destport = msg_destport(msg); | ||
449 | int wakeable; | ||
450 | |||
451 | /* Validate connection */ | ||
452 | p_ptr = tipc_port_lock(destport); | ||
453 | if (!p_ptr || !p_ptr->connected || !tipc_port_peer_msg(p_ptr, msg)) { | ||
454 | r_buf = tipc_buf_acquire(BASIC_H_SIZE); | ||
455 | if (r_buf) { | ||
456 | msg = buf_msg(r_buf); | ||
457 | tipc_msg_init(msg, TIPC_HIGH_IMPORTANCE, TIPC_CONN_MSG, | ||
458 | BASIC_H_SIZE, msg_orignode(msg)); | ||
459 | msg_set_errcode(msg, TIPC_ERR_NO_PORT); | ||
460 | msg_set_origport(msg, destport); | ||
461 | msg_set_destport(msg, msg_origport(msg)); | ||
462 | } | ||
463 | if (p_ptr) | ||
464 | tipc_port_unlock(p_ptr); | ||
465 | goto exit; | ||
466 | } | ||
467 | |||
468 | /* Process protocol message sent by peer */ | ||
469 | switch (msg_type(msg)) { | ||
470 | case CONN_ACK: | ||
471 | wakeable = tipc_port_congested(p_ptr) && p_ptr->congested; | ||
472 | p_ptr->acked += msg_msgcnt(msg); | ||
473 | if (!tipc_port_congested(p_ptr)) { | ||
474 | p_ptr->congested = 0; | ||
475 | if (wakeable) | ||
476 | tipc_port_wakeup(p_ptr); | ||
477 | } | ||
478 | break; | ||
479 | case CONN_PROBE: | ||
480 | r_buf = port_build_proto_msg(p_ptr, CONN_PROBE_REPLY, 0); | ||
481 | break; | ||
482 | default: | ||
483 | /* CONN_PROBE_REPLY or unrecognized - no action required */ | ||
484 | break; | ||
485 | } | ||
486 | p_ptr->probing_state = CONFIRMED; | ||
487 | tipc_port_unlock(p_ptr); | ||
488 | exit: | ||
489 | tipc_net_route_msg(r_buf); | ||
490 | kfree_skb(buf); | ||
491 | } | ||
492 | |||
493 | static int port_print(struct tipc_port *p_ptr, char *buf, int len, int full_id) | 247 | static int port_print(struct tipc_port *p_ptr, char *buf, int len, int full_id) |
494 | { | 248 | { |
495 | struct publication *publ; | 249 | struct publication *publ; |
@@ -581,16 +335,19 @@ void tipc_acknowledge(u32 ref, u32 ack) | |||
581 | { | 335 | { |
582 | struct tipc_port *p_ptr; | 336 | struct tipc_port *p_ptr; |
583 | struct sk_buff *buf = NULL; | 337 | struct sk_buff *buf = NULL; |
338 | struct tipc_msg *msg; | ||
584 | 339 | ||
585 | p_ptr = tipc_port_lock(ref); | 340 | p_ptr = tipc_port_lock(ref); |
586 | if (!p_ptr) | 341 | if (!p_ptr) |
587 | return; | 342 | return; |
588 | if (p_ptr->connected) { | 343 | if (p_ptr->connected) |
589 | p_ptr->conn_unacked -= ack; | ||
590 | buf = port_build_proto_msg(p_ptr, CONN_ACK, ack); | 344 | buf = port_build_proto_msg(p_ptr, CONN_ACK, ack); |
591 | } | 345 | |
592 | tipc_port_unlock(p_ptr); | 346 | tipc_port_unlock(p_ptr); |
593 | tipc_net_route_msg(buf); | 347 | if (!buf) |
348 | return; | ||
349 | msg = buf_msg(buf); | ||
350 | tipc_link_xmit(buf, msg_destnode(msg), msg_link_selector(msg)); | ||
594 | } | 351 | } |
595 | 352 | ||
596 | int tipc_publish(struct tipc_port *p_ptr, unsigned int scope, | 353 | int tipc_publish(struct tipc_port *p_ptr, unsigned int scope, |
@@ -689,7 +446,7 @@ int __tipc_port_connect(u32 ref, struct tipc_port *p_ptr, | |||
689 | msg_set_hdr_sz(msg, SHORT_H_SIZE); | 446 | msg_set_hdr_sz(msg, SHORT_H_SIZE); |
690 | 447 | ||
691 | p_ptr->probing_interval = PROBING_INTERVAL; | 448 | p_ptr->probing_interval = PROBING_INTERVAL; |
692 | p_ptr->probing_state = CONFIRMED; | 449 | p_ptr->probing_state = TIPC_CONN_OK; |
693 | p_ptr->connected = 1; | 450 | p_ptr->connected = 1; |
694 | k_start_timer(&p_ptr->timer, p_ptr->probing_interval); | 451 | k_start_timer(&p_ptr->timer, p_ptr->probing_interval); |
695 | 452 | ||
@@ -698,7 +455,7 @@ int __tipc_port_connect(u32 ref, struct tipc_port *p_ptr, | |||
698 | (net_ev_handler)port_handle_node_down); | 455 | (net_ev_handler)port_handle_node_down); |
699 | res = 0; | 456 | res = 0; |
700 | exit: | 457 | exit: |
701 | p_ptr->max_pkt = tipc_link_get_max_pkt(peer->node, ref); | 458 | p_ptr->max_pkt = tipc_node_get_mtu(peer->node, ref); |
702 | return res; | 459 | return res; |
703 | } | 460 | } |
704 | 461 | ||
@@ -741,6 +498,7 @@ int tipc_port_disconnect(u32 ref) | |||
741 | */ | 498 | */ |
742 | int tipc_port_shutdown(u32 ref) | 499 | int tipc_port_shutdown(u32 ref) |
743 | { | 500 | { |
501 | struct tipc_msg *msg; | ||
744 | struct tipc_port *p_ptr; | 502 | struct tipc_port *p_ptr; |
745 | struct sk_buff *buf = NULL; | 503 | struct sk_buff *buf = NULL; |
746 | 504 | ||
@@ -750,149 +508,7 @@ int tipc_port_shutdown(u32 ref) | |||
750 | 508 | ||
751 | buf = port_build_peer_abort_msg(p_ptr, TIPC_CONN_SHUTDOWN); | 509 | buf = port_build_peer_abort_msg(p_ptr, TIPC_CONN_SHUTDOWN); |
752 | tipc_port_unlock(p_ptr); | 510 | tipc_port_unlock(p_ptr); |
753 | tipc_net_route_msg(buf); | 511 | msg = buf_msg(buf); |
512 | tipc_link_xmit(buf, msg_destnode(msg), msg_link_selector(msg)); | ||
754 | return tipc_port_disconnect(ref); | 513 | return tipc_port_disconnect(ref); |
755 | } | 514 | } |
756 | |||
757 | /* | ||
758 | * tipc_port_iovec_rcv: Concatenate and deliver sectioned | ||
759 | * message for this node. | ||
760 | */ | ||
761 | static int tipc_port_iovec_rcv(struct tipc_port *sender, | ||
762 | struct iovec const *msg_sect, | ||
763 | unsigned int len) | ||
764 | { | ||
765 | struct sk_buff *buf; | ||
766 | int res; | ||
767 | |||
768 | res = tipc_msg_build(&sender->phdr, msg_sect, len, MAX_MSG_SIZE, &buf); | ||
769 | if (likely(buf)) | ||
770 | tipc_sk_rcv(buf); | ||
771 | return res; | ||
772 | } | ||
773 | |||
774 | /** | ||
775 | * tipc_send - send message sections on connection | ||
776 | */ | ||
777 | int tipc_send(struct tipc_port *p_ptr, | ||
778 | struct iovec const *msg_sect, | ||
779 | unsigned int len) | ||
780 | { | ||
781 | u32 destnode; | ||
782 | int res; | ||
783 | |||
784 | if (!p_ptr->connected) | ||
785 | return -EINVAL; | ||
786 | |||
787 | p_ptr->congested = 1; | ||
788 | if (!tipc_port_congested(p_ptr)) { | ||
789 | destnode = tipc_port_peernode(p_ptr); | ||
790 | if (likely(!in_own_node(destnode))) | ||
791 | res = tipc_link_iovec_xmit_fast(p_ptr, msg_sect, len, | ||
792 | destnode); | ||
793 | else | ||
794 | res = tipc_port_iovec_rcv(p_ptr, msg_sect, len); | ||
795 | |||
796 | if (likely(res != -ELINKCONG)) { | ||
797 | p_ptr->congested = 0; | ||
798 | if (res > 0) | ||
799 | p_ptr->sent++; | ||
800 | return res; | ||
801 | } | ||
802 | } | ||
803 | if (tipc_port_unreliable(p_ptr)) { | ||
804 | p_ptr->congested = 0; | ||
805 | return len; | ||
806 | } | ||
807 | return -ELINKCONG; | ||
808 | } | ||
809 | |||
810 | /** | ||
811 | * tipc_send2name - send message sections to port name | ||
812 | */ | ||
813 | int tipc_send2name(struct tipc_port *p_ptr, | ||
814 | struct tipc_name const *name, | ||
815 | unsigned int domain, | ||
816 | struct iovec const *msg_sect, | ||
817 | unsigned int len) | ||
818 | { | ||
819 | struct tipc_msg *msg; | ||
820 | u32 destnode = domain; | ||
821 | u32 destport; | ||
822 | int res; | ||
823 | |||
824 | if (p_ptr->connected) | ||
825 | return -EINVAL; | ||
826 | |||
827 | msg = &p_ptr->phdr; | ||
828 | msg_set_type(msg, TIPC_NAMED_MSG); | ||
829 | msg_set_hdr_sz(msg, NAMED_H_SIZE); | ||
830 | msg_set_nametype(msg, name->type); | ||
831 | msg_set_nameinst(msg, name->instance); | ||
832 | msg_set_lookup_scope(msg, tipc_addr_scope(domain)); | ||
833 | destport = tipc_nametbl_translate(name->type, name->instance, &destnode); | ||
834 | msg_set_destnode(msg, destnode); | ||
835 | msg_set_destport(msg, destport); | ||
836 | |||
837 | if (likely(destport || destnode)) { | ||
838 | if (likely(in_own_node(destnode))) | ||
839 | res = tipc_port_iovec_rcv(p_ptr, msg_sect, len); | ||
840 | else if (tipc_own_addr) | ||
841 | res = tipc_link_iovec_xmit_fast(p_ptr, msg_sect, len, | ||
842 | destnode); | ||
843 | else | ||
844 | res = tipc_port_iovec_reject(p_ptr, msg, msg_sect, | ||
845 | len, TIPC_ERR_NO_NODE); | ||
846 | if (likely(res != -ELINKCONG)) { | ||
847 | if (res > 0) | ||
848 | p_ptr->sent++; | ||
849 | return res; | ||
850 | } | ||
851 | if (tipc_port_unreliable(p_ptr)) | ||
852 | return len; | ||
853 | |||
854 | return -ELINKCONG; | ||
855 | } | ||
856 | return tipc_port_iovec_reject(p_ptr, msg, msg_sect, len, | ||
857 | TIPC_ERR_NO_NAME); | ||
858 | } | ||
859 | |||
860 | /** | ||
861 | * tipc_send2port - send message sections to port identity | ||
862 | */ | ||
863 | int tipc_send2port(struct tipc_port *p_ptr, | ||
864 | struct tipc_portid const *dest, | ||
865 | struct iovec const *msg_sect, | ||
866 | unsigned int len) | ||
867 | { | ||
868 | struct tipc_msg *msg; | ||
869 | int res; | ||
870 | |||
871 | if (p_ptr->connected) | ||
872 | return -EINVAL; | ||
873 | |||
874 | msg = &p_ptr->phdr; | ||
875 | msg_set_type(msg, TIPC_DIRECT_MSG); | ||
876 | msg_set_lookup_scope(msg, 0); | ||
877 | msg_set_destnode(msg, dest->node); | ||
878 | msg_set_destport(msg, dest->ref); | ||
879 | msg_set_hdr_sz(msg, BASIC_H_SIZE); | ||
880 | |||
881 | if (in_own_node(dest->node)) | ||
882 | res = tipc_port_iovec_rcv(p_ptr, msg_sect, len); | ||
883 | else if (tipc_own_addr) | ||
884 | res = tipc_link_iovec_xmit_fast(p_ptr, msg_sect, len, | ||
885 | dest->node); | ||
886 | else | ||
887 | res = tipc_port_iovec_reject(p_ptr, msg, msg_sect, len, | ||
888 | TIPC_ERR_NO_NODE); | ||
889 | if (likely(res != -ELINKCONG)) { | ||
890 | if (res > 0) | ||
891 | p_ptr->sent++; | ||
892 | return res; | ||
893 | } | ||
894 | if (tipc_port_unreliable(p_ptr)) | ||
895 | return len; | ||
896 | |||
897 | return -ELINKCONG; | ||
898 | } | ||
diff --git a/net/tipc/port.h b/net/tipc/port.h index cf4ca5b1d9a4..3087da39ee47 100644 --- a/net/tipc/port.h +++ b/net/tipc/port.h | |||
@@ -53,17 +53,13 @@ | |||
53 | * @connected: non-zero if port is currently connected to a peer port | 53 | * @connected: non-zero if port is currently connected to a peer port |
54 | * @conn_type: TIPC type used when connection was established | 54 | * @conn_type: TIPC type used when connection was established |
55 | * @conn_instance: TIPC instance used when connection was established | 55 | * @conn_instance: TIPC instance used when connection was established |
56 | * @conn_unacked: number of unacknowledged messages received from peer port | ||
57 | * @published: non-zero if port has one or more associated names | 56 | * @published: non-zero if port has one or more associated names |
58 | * @congested: non-zero if cannot send because of link or port congestion | ||
59 | * @max_pkt: maximum packet size "hint" used when building messages sent by port | 57 | * @max_pkt: maximum packet size "hint" used when building messages sent by port |
60 | * @ref: unique reference to port in TIPC object registry | 58 | * @ref: unique reference to port in TIPC object registry |
61 | * @phdr: preformatted message header used when sending messages | 59 | * @phdr: preformatted message header used when sending messages |
62 | * @port_list: adjacent ports in TIPC's global list of ports | 60 | * @port_list: adjacent ports in TIPC's global list of ports |
63 | * @wait_list: adjacent ports in list of ports waiting on link congestion | 61 | * @wait_list: adjacent ports in list of ports waiting on link congestion |
64 | * @waiting_pkts: | 62 | * @waiting_pkts: |
65 | * @sent: # of non-empty messages sent by port | ||
66 | * @acked: # of non-empty message acknowledgements from connected port's peer | ||
67 | * @publications: list of publications for port | 63 | * @publications: list of publications for port |
68 | * @pub_count: total # of publications port has made during its lifetime | 64 | * @pub_count: total # of publications port has made during its lifetime |
69 | * @probing_state: | 65 | * @probing_state: |
@@ -76,17 +72,13 @@ struct tipc_port { | |||
76 | int connected; | 72 | int connected; |
77 | u32 conn_type; | 73 | u32 conn_type; |
78 | u32 conn_instance; | 74 | u32 conn_instance; |
79 | u32 conn_unacked; | ||
80 | int published; | 75 | int published; |
81 | u32 congested; | ||
82 | u32 max_pkt; | 76 | u32 max_pkt; |
83 | u32 ref; | 77 | u32 ref; |
84 | struct tipc_msg phdr; | 78 | struct tipc_msg phdr; |
85 | struct list_head port_list; | 79 | struct list_head port_list; |
86 | struct list_head wait_list; | 80 | struct list_head wait_list; |
87 | u32 waiting_pkts; | 81 | u32 waiting_pkts; |
88 | u32 sent; | ||
89 | u32 acked; | ||
90 | struct list_head publications; | 82 | struct list_head publications; |
91 | u32 pub_count; | 83 | u32 pub_count; |
92 | u32 probing_state; | 84 | u32 probing_state; |
@@ -104,8 +96,6 @@ struct tipc_port_list; | |||
104 | u32 tipc_port_init(struct tipc_port *p_ptr, | 96 | u32 tipc_port_init(struct tipc_port *p_ptr, |
105 | const unsigned int importance); | 97 | const unsigned int importance); |
106 | 98 | ||
107 | int tipc_reject_msg(struct sk_buff *buf, u32 err); | ||
108 | |||
109 | void tipc_acknowledge(u32 port_ref, u32 ack); | 99 | void tipc_acknowledge(u32 port_ref, u32 ack); |
110 | 100 | ||
111 | void tipc_port_destroy(struct tipc_port *p_ptr); | 101 | void tipc_port_destroy(struct tipc_port *p_ptr); |
@@ -122,8 +112,6 @@ int tipc_port_disconnect(u32 portref); | |||
122 | 112 | ||
123 | int tipc_port_shutdown(u32 ref); | 113 | int tipc_port_shutdown(u32 ref); |
124 | 114 | ||
125 | void tipc_port_wakeup(struct tipc_port *port); | ||
126 | |||
127 | /* | 115 | /* |
128 | * The following routines require that the port be locked on entry | 116 | * The following routines require that the port be locked on entry |
129 | */ | 117 | */ |
@@ -132,39 +120,7 @@ int __tipc_port_connect(u32 ref, struct tipc_port *p_ptr, | |||
132 | struct tipc_portid const *peer); | 120 | struct tipc_portid const *peer); |
133 | int tipc_port_peer_msg(struct tipc_port *p_ptr, struct tipc_msg *msg); | 121 | int tipc_port_peer_msg(struct tipc_port *p_ptr, struct tipc_msg *msg); |
134 | 122 | ||
135 | /* | ||
136 | * TIPC messaging routines | ||
137 | */ | ||
138 | |||
139 | int tipc_send(struct tipc_port *port, | ||
140 | struct iovec const *msg_sect, | ||
141 | unsigned int len); | ||
142 | |||
143 | int tipc_send2name(struct tipc_port *port, | ||
144 | struct tipc_name const *name, | ||
145 | u32 domain, | ||
146 | struct iovec const *msg_sect, | ||
147 | unsigned int len); | ||
148 | |||
149 | int tipc_send2port(struct tipc_port *port, | ||
150 | struct tipc_portid const *dest, | ||
151 | struct iovec const *msg_sect, | ||
152 | unsigned int len); | ||
153 | |||
154 | int tipc_port_mcast_xmit(struct tipc_port *port, | ||
155 | struct tipc_name_seq const *seq, | ||
156 | struct iovec const *msg, | ||
157 | unsigned int len); | ||
158 | |||
159 | int tipc_port_iovec_reject(struct tipc_port *p_ptr, | ||
160 | struct tipc_msg *hdr, | ||
161 | struct iovec const *msg_sect, | ||
162 | unsigned int len, | ||
163 | int err); | ||
164 | |||
165 | struct sk_buff *tipc_port_get_ports(void); | 123 | struct sk_buff *tipc_port_get_ports(void); |
166 | void tipc_port_proto_rcv(struct sk_buff *buf); | ||
167 | void tipc_port_mcast_rcv(struct sk_buff *buf, struct tipc_port_list *dp); | ||
168 | void tipc_port_reinit(void); | 124 | void tipc_port_reinit(void); |
169 | 125 | ||
170 | /** | 126 | /** |
@@ -185,12 +141,6 @@ static inline void tipc_port_unlock(struct tipc_port *p_ptr) | |||
185 | spin_unlock_bh(p_ptr->lock); | 141 | spin_unlock_bh(p_ptr->lock); |
186 | } | 142 | } |
187 | 143 | ||
188 | static inline int tipc_port_congested(struct tipc_port *p_ptr) | ||
189 | { | ||
190 | return ((p_ptr->sent - p_ptr->acked) >= TIPC_FLOWCTRL_WIN); | ||
191 | } | ||
192 | |||
193 | |||
194 | static inline u32 tipc_port_peernode(struct tipc_port *p_ptr) | 144 | static inline u32 tipc_port_peernode(struct tipc_port *p_ptr) |
195 | { | 145 | { |
196 | return msg_destnode(&p_ptr->phdr); | 146 | return msg_destnode(&p_ptr->phdr); |
@@ -229,9 +179,12 @@ static inline int tipc_port_importance(struct tipc_port *port) | |||
229 | return msg_importance(&port->phdr); | 179 | return msg_importance(&port->phdr); |
230 | } | 180 | } |
231 | 181 | ||
232 | static inline void tipc_port_set_importance(struct tipc_port *port, int imp) | 182 | static inline int tipc_port_set_importance(struct tipc_port *port, int imp) |
233 | { | 183 | { |
184 | if (imp > TIPC_CRITICAL_IMPORTANCE) | ||
185 | return -EINVAL; | ||
234 | msg_set_importance(&port->phdr, (u32)imp); | 186 | msg_set_importance(&port->phdr, (u32)imp); |
187 | return 0; | ||
235 | } | 188 | } |
236 | 189 | ||
237 | #endif | 190 | #endif |
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index ef0475568f9e..ff8c8118d56e 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
@@ -36,20 +36,23 @@ | |||
36 | 36 | ||
37 | #include "core.h" | 37 | #include "core.h" |
38 | #include "port.h" | 38 | #include "port.h" |
39 | #include "name_table.h" | ||
39 | #include "node.h" | 40 | #include "node.h" |
40 | 41 | #include "link.h" | |
41 | #include <linux/export.h> | 42 | #include <linux/export.h> |
42 | 43 | ||
43 | #define SS_LISTENING -1 /* socket is listening */ | 44 | #define SS_LISTENING -1 /* socket is listening */ |
44 | #define SS_READY -2 /* socket is connectionless */ | 45 | #define SS_READY -2 /* socket is connectionless */ |
45 | 46 | ||
46 | #define CONN_TIMEOUT_DEFAULT 8000 /* default connect timeout = 8s */ | 47 | #define CONN_TIMEOUT_DEFAULT 8000 /* default connect timeout = 8s */ |
48 | #define TIPC_FWD_MSG 1 | ||
47 | 49 | ||
48 | static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *skb); | 50 | static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *skb); |
49 | static void tipc_data_ready(struct sock *sk); | 51 | static void tipc_data_ready(struct sock *sk); |
50 | static void tipc_write_space(struct sock *sk); | 52 | static void tipc_write_space(struct sock *sk); |
51 | static int tipc_release(struct socket *sock); | 53 | static int tipc_release(struct socket *sock); |
52 | static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags); | 54 | static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags); |
55 | static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p); | ||
53 | 56 | ||
54 | static const struct proto_ops packet_ops; | 57 | static const struct proto_ops packet_ops; |
55 | static const struct proto_ops stream_ops; | 58 | static const struct proto_ops stream_ops; |
@@ -123,9 +126,12 @@ static void advance_rx_queue(struct sock *sk) | |||
123 | static void reject_rx_queue(struct sock *sk) | 126 | static void reject_rx_queue(struct sock *sk) |
124 | { | 127 | { |
125 | struct sk_buff *buf; | 128 | struct sk_buff *buf; |
129 | u32 dnode; | ||
126 | 130 | ||
127 | while ((buf = __skb_dequeue(&sk->sk_receive_queue))) | 131 | while ((buf = __skb_dequeue(&sk->sk_receive_queue))) { |
128 | tipc_reject_msg(buf, TIPC_ERR_NO_PORT); | 132 | if (tipc_msg_reverse(buf, &dnode, TIPC_ERR_NO_PORT)) |
133 | tipc_link_xmit(buf, dnode, 0); | ||
134 | } | ||
129 | } | 135 | } |
130 | 136 | ||
131 | /** | 137 | /** |
@@ -201,6 +207,7 @@ static int tipc_sk_create(struct net *net, struct socket *sock, | |||
201 | sk->sk_data_ready = tipc_data_ready; | 207 | sk->sk_data_ready = tipc_data_ready; |
202 | sk->sk_write_space = tipc_write_space; | 208 | sk->sk_write_space = tipc_write_space; |
203 | tsk->conn_timeout = CONN_TIMEOUT_DEFAULT; | 209 | tsk->conn_timeout = CONN_TIMEOUT_DEFAULT; |
210 | tsk->sent_unacked = 0; | ||
204 | atomic_set(&tsk->dupl_rcvcnt, 0); | 211 | atomic_set(&tsk->dupl_rcvcnt, 0); |
205 | tipc_port_unlock(port); | 212 | tipc_port_unlock(port); |
206 | 213 | ||
@@ -303,6 +310,7 @@ static int tipc_release(struct socket *sock) | |||
303 | struct tipc_sock *tsk; | 310 | struct tipc_sock *tsk; |
304 | struct tipc_port *port; | 311 | struct tipc_port *port; |
305 | struct sk_buff *buf; | 312 | struct sk_buff *buf; |
313 | u32 dnode; | ||
306 | 314 | ||
307 | /* | 315 | /* |
308 | * Exit if socket isn't fully initialized (occurs when a failed accept() | 316 | * Exit if socket isn't fully initialized (occurs when a failed accept() |
@@ -331,7 +339,8 @@ static int tipc_release(struct socket *sock) | |||
331 | sock->state = SS_DISCONNECTING; | 339 | sock->state = SS_DISCONNECTING; |
332 | tipc_port_disconnect(port->ref); | 340 | tipc_port_disconnect(port->ref); |
333 | } | 341 | } |
334 | tipc_reject_msg(buf, TIPC_ERR_NO_PORT); | 342 | if (tipc_msg_reverse(buf, &dnode, TIPC_ERR_NO_PORT)) |
343 | tipc_link_xmit(buf, dnode, 0); | ||
335 | } | 344 | } |
336 | } | 345 | } |
337 | 346 | ||
@@ -504,12 +513,12 @@ static unsigned int tipc_poll(struct file *file, struct socket *sock, | |||
504 | 513 | ||
505 | switch ((int)sock->state) { | 514 | switch ((int)sock->state) { |
506 | case SS_UNCONNECTED: | 515 | case SS_UNCONNECTED: |
507 | if (!tsk->port.congested) | 516 | if (!tsk->link_cong) |
508 | mask |= POLLOUT; | 517 | mask |= POLLOUT; |
509 | break; | 518 | break; |
510 | case SS_READY: | 519 | case SS_READY: |
511 | case SS_CONNECTED: | 520 | case SS_CONNECTED: |
512 | if (!tsk->port.congested) | 521 | if (!tsk->link_cong && !tipc_sk_conn_cong(tsk)) |
513 | mask |= POLLOUT; | 522 | mask |= POLLOUT; |
514 | /* fall thru' */ | 523 | /* fall thru' */ |
515 | case SS_CONNECTING: | 524 | case SS_CONNECTING: |
@@ -526,6 +535,136 @@ static unsigned int tipc_poll(struct file *file, struct socket *sock, | |||
526 | } | 535 | } |
527 | 536 | ||
528 | /** | 537 | /** |
538 | * tipc_sendmcast - send multicast message | ||
539 | * @sock: socket structure | ||
540 | * @seq: destination address | ||
541 | * @iov: message data to send | ||
542 | * @dsz: total length of message data | ||
543 | * @timeo: timeout to wait for wakeup | ||
544 | * | ||
545 | * Called from function tipc_sendmsg(), which has done all sanity checks | ||
546 | * Returns the number of bytes sent on success, or errno | ||
547 | */ | ||
548 | static int tipc_sendmcast(struct socket *sock, struct tipc_name_seq *seq, | ||
549 | struct iovec *iov, size_t dsz, long timeo) | ||
550 | { | ||
551 | struct sock *sk = sock->sk; | ||
552 | struct tipc_msg *mhdr = &tipc_sk(sk)->port.phdr; | ||
553 | struct sk_buff *buf; | ||
554 | uint mtu; | ||
555 | int rc; | ||
556 | |||
557 | msg_set_type(mhdr, TIPC_MCAST_MSG); | ||
558 | msg_set_lookup_scope(mhdr, TIPC_CLUSTER_SCOPE); | ||
559 | msg_set_destport(mhdr, 0); | ||
560 | msg_set_destnode(mhdr, 0); | ||
561 | msg_set_nametype(mhdr, seq->type); | ||
562 | msg_set_namelower(mhdr, seq->lower); | ||
563 | msg_set_nameupper(mhdr, seq->upper); | ||
564 | msg_set_hdr_sz(mhdr, MCAST_H_SIZE); | ||
565 | |||
566 | new_mtu: | ||
567 | mtu = tipc_bclink_get_mtu(); | ||
568 | rc = tipc_msg_build(mhdr, iov, 0, dsz, mtu, &buf); | ||
569 | if (unlikely(rc < 0)) | ||
570 | return rc; | ||
571 | |||
572 | do { | ||
573 | rc = tipc_bclink_xmit(buf); | ||
574 | if (likely(rc >= 0)) { | ||
575 | rc = dsz; | ||
576 | break; | ||
577 | } | ||
578 | if (rc == -EMSGSIZE) | ||
579 | goto new_mtu; | ||
580 | if (rc != -ELINKCONG) | ||
581 | break; | ||
582 | rc = tipc_wait_for_sndmsg(sock, &timeo); | ||
583 | if (rc) | ||
584 | kfree_skb_list(buf); | ||
585 | } while (!rc); | ||
586 | return rc; | ||
587 | } | ||
588 | |||
589 | /* tipc_sk_mcast_rcv - Deliver multicast message to all destination sockets | ||
590 | */ | ||
591 | void tipc_sk_mcast_rcv(struct sk_buff *buf) | ||
592 | { | ||
593 | struct tipc_msg *msg = buf_msg(buf); | ||
594 | struct tipc_port_list dports = {0, NULL, }; | ||
595 | struct tipc_port_list *item; | ||
596 | struct sk_buff *b; | ||
597 | uint i, last, dst = 0; | ||
598 | u32 scope = TIPC_CLUSTER_SCOPE; | ||
599 | |||
600 | if (in_own_node(msg_orignode(msg))) | ||
601 | scope = TIPC_NODE_SCOPE; | ||
602 | |||
603 | /* Create destination port list: */ | ||
604 | tipc_nametbl_mc_translate(msg_nametype(msg), | ||
605 | msg_namelower(msg), | ||
606 | msg_nameupper(msg), | ||
607 | scope, | ||
608 | &dports); | ||
609 | last = dports.count; | ||
610 | if (!last) { | ||
611 | kfree_skb(buf); | ||
612 | return; | ||
613 | } | ||
614 | |||
615 | for (item = &dports; item; item = item->next) { | ||
616 | for (i = 0; i < PLSIZE && ++dst <= last; i++) { | ||
617 | b = (dst != last) ? skb_clone(buf, GFP_ATOMIC) : buf; | ||
618 | if (!b) { | ||
619 | pr_warn("Failed do clone mcast rcv buffer\n"); | ||
620 | continue; | ||
621 | } | ||
622 | msg_set_destport(msg, item->ports[i]); | ||
623 | tipc_sk_rcv(b); | ||
624 | } | ||
625 | } | ||
626 | tipc_port_list_free(&dports); | ||
627 | } | ||
628 | |||
629 | /** | ||
630 | * tipc_sk_proto_rcv - receive a connection mng protocol message | ||
631 | * @tsk: receiving socket | ||
632 | * @dnode: node to send response message to, if any | ||
633 | * @buf: buffer containing protocol message | ||
634 | * Returns 0 (TIPC_OK) if message was consumed, 1 (TIPC_FWD_MSG) if | ||
635 | * (CONN_PROBE_REPLY) message should be forwarded. | ||
636 | */ | ||
637 | static int tipc_sk_proto_rcv(struct tipc_sock *tsk, u32 *dnode, | ||
638 | struct sk_buff *buf) | ||
639 | { | ||
640 | struct tipc_msg *msg = buf_msg(buf); | ||
641 | struct tipc_port *port = &tsk->port; | ||
642 | int conn_cong; | ||
643 | |||
644 | /* Ignore if connection cannot be validated: */ | ||
645 | if (!port->connected || !tipc_port_peer_msg(port, msg)) | ||
646 | goto exit; | ||
647 | |||
648 | port->probing_state = TIPC_CONN_OK; | ||
649 | |||
650 | if (msg_type(msg) == CONN_ACK) { | ||
651 | conn_cong = tipc_sk_conn_cong(tsk); | ||
652 | tsk->sent_unacked -= msg_msgcnt(msg); | ||
653 | if (conn_cong) | ||
654 | tipc_sock_wakeup(tsk); | ||
655 | } else if (msg_type(msg) == CONN_PROBE) { | ||
656 | if (!tipc_msg_reverse(buf, dnode, TIPC_OK)) | ||
657 | return TIPC_OK; | ||
658 | msg_set_type(msg, CONN_PROBE_REPLY); | ||
659 | return TIPC_FWD_MSG; | ||
660 | } | ||
661 | /* Do nothing if msg_type() == CONN_PROBE_REPLY */ | ||
662 | exit: | ||
663 | kfree_skb(buf); | ||
664 | return TIPC_OK; | ||
665 | } | ||
666 | |||
667 | /** | ||
529 | * dest_name_check - verify user is permitted to send to specified port name | 668 | * dest_name_check - verify user is permitted to send to specified port name |
530 | * @dest: destination address | 669 | * @dest: destination address |
531 | * @m: descriptor for message to be sent | 670 | * @m: descriptor for message to be sent |
@@ -539,6 +678,8 @@ static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m) | |||
539 | { | 678 | { |
540 | struct tipc_cfg_msg_hdr hdr; | 679 | struct tipc_cfg_msg_hdr hdr; |
541 | 680 | ||
681 | if (unlikely(dest->addrtype == TIPC_ADDR_ID)) | ||
682 | return 0; | ||
542 | if (likely(dest->addr.name.name.type >= TIPC_RESERVED_TYPES)) | 683 | if (likely(dest->addr.name.name.type >= TIPC_RESERVED_TYPES)) |
543 | return 0; | 684 | return 0; |
544 | if (likely(dest->addr.name.name.type == TIPC_TOP_SRV)) | 685 | if (likely(dest->addr.name.name.type == TIPC_TOP_SRV)) |
@@ -575,19 +716,18 @@ static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p) | |||
575 | return sock_intr_errno(*timeo_p); | 716 | return sock_intr_errno(*timeo_p); |
576 | 717 | ||
577 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | 718 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
578 | done = sk_wait_event(sk, timeo_p, !tsk->port.congested); | 719 | done = sk_wait_event(sk, timeo_p, !tsk->link_cong); |
579 | finish_wait(sk_sleep(sk), &wait); | 720 | finish_wait(sk_sleep(sk), &wait); |
580 | } while (!done); | 721 | } while (!done); |
581 | return 0; | 722 | return 0; |
582 | } | 723 | } |
583 | 724 | ||
584 | |||
585 | /** | 725 | /** |
586 | * tipc_sendmsg - send message in connectionless manner | 726 | * tipc_sendmsg - send message in connectionless manner |
587 | * @iocb: if NULL, indicates that socket lock is already held | 727 | * @iocb: if NULL, indicates that socket lock is already held |
588 | * @sock: socket structure | 728 | * @sock: socket structure |
589 | * @m: message to send | 729 | * @m: message to send |
590 | * @total_len: length of message | 730 | * @dsz: amount of user data to be sent |
591 | * | 731 | * |
592 | * Message must have an destination specified explicitly. | 732 | * Message must have an destination specified explicitly. |
593 | * Used for SOCK_RDM and SOCK_DGRAM messages, | 733 | * Used for SOCK_RDM and SOCK_DGRAM messages, |
@@ -597,100 +737,123 @@ static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p) | |||
597 | * Returns the number of bytes sent on success, or errno otherwise | 737 | * Returns the number of bytes sent on success, or errno otherwise |
598 | */ | 738 | */ |
599 | static int tipc_sendmsg(struct kiocb *iocb, struct socket *sock, | 739 | static int tipc_sendmsg(struct kiocb *iocb, struct socket *sock, |
600 | struct msghdr *m, size_t total_len) | 740 | struct msghdr *m, size_t dsz) |
601 | { | 741 | { |
742 | DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name); | ||
602 | struct sock *sk = sock->sk; | 743 | struct sock *sk = sock->sk; |
603 | struct tipc_sock *tsk = tipc_sk(sk); | 744 | struct tipc_sock *tsk = tipc_sk(sk); |
604 | struct tipc_port *port = &tsk->port; | 745 | struct tipc_port *port = &tsk->port; |
605 | DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name); | 746 | struct tipc_msg *mhdr = &port->phdr; |
606 | int needs_conn; | 747 | struct iovec *iov = m->msg_iov; |
748 | u32 dnode, dport; | ||
749 | struct sk_buff *buf; | ||
750 | struct tipc_name_seq *seq = &dest->addr.nameseq; | ||
751 | u32 mtu; | ||
607 | long timeo; | 752 | long timeo; |
608 | int res = -EINVAL; | 753 | int rc = -EINVAL; |
609 | 754 | ||
610 | if (unlikely(!dest)) | 755 | if (unlikely(!dest)) |
611 | return -EDESTADDRREQ; | 756 | return -EDESTADDRREQ; |
757 | |||
612 | if (unlikely((m->msg_namelen < sizeof(*dest)) || | 758 | if (unlikely((m->msg_namelen < sizeof(*dest)) || |
613 | (dest->family != AF_TIPC))) | 759 | (dest->family != AF_TIPC))) |
614 | return -EINVAL; | 760 | return -EINVAL; |
615 | if (total_len > TIPC_MAX_USER_MSG_SIZE) | 761 | |
762 | if (dsz > TIPC_MAX_USER_MSG_SIZE) | ||
616 | return -EMSGSIZE; | 763 | return -EMSGSIZE; |
617 | 764 | ||
618 | if (iocb) | 765 | if (iocb) |
619 | lock_sock(sk); | 766 | lock_sock(sk); |
620 | 767 | ||
621 | needs_conn = (sock->state != SS_READY); | 768 | if (unlikely(sock->state != SS_READY)) { |
622 | if (unlikely(needs_conn)) { | ||
623 | if (sock->state == SS_LISTENING) { | 769 | if (sock->state == SS_LISTENING) { |
624 | res = -EPIPE; | 770 | rc = -EPIPE; |
625 | goto exit; | 771 | goto exit; |
626 | } | 772 | } |
627 | if (sock->state != SS_UNCONNECTED) { | 773 | if (sock->state != SS_UNCONNECTED) { |
628 | res = -EISCONN; | 774 | rc = -EISCONN; |
629 | goto exit; | 775 | goto exit; |
630 | } | 776 | } |
631 | if (tsk->port.published) { | 777 | if (tsk->port.published) { |
632 | res = -EOPNOTSUPP; | 778 | rc = -EOPNOTSUPP; |
633 | goto exit; | 779 | goto exit; |
634 | } | 780 | } |
635 | if (dest->addrtype == TIPC_ADDR_NAME) { | 781 | if (dest->addrtype == TIPC_ADDR_NAME) { |
636 | tsk->port.conn_type = dest->addr.name.name.type; | 782 | tsk->port.conn_type = dest->addr.name.name.type; |
637 | tsk->port.conn_instance = dest->addr.name.name.instance; | 783 | tsk->port.conn_instance = dest->addr.name.name.instance; |
638 | } | 784 | } |
639 | |||
640 | /* Abort any pending connection attempts (very unlikely) */ | ||
641 | reject_rx_queue(sk); | ||
642 | } | 785 | } |
786 | rc = dest_name_check(dest, m); | ||
787 | if (rc) | ||
788 | goto exit; | ||
643 | 789 | ||
644 | timeo = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); | 790 | timeo = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); |
645 | do { | 791 | |
646 | if (dest->addrtype == TIPC_ADDR_NAME) { | 792 | if (dest->addrtype == TIPC_ADDR_MCAST) { |
647 | res = dest_name_check(dest, m); | 793 | rc = tipc_sendmcast(sock, seq, iov, dsz, timeo); |
648 | if (res) | 794 | goto exit; |
649 | break; | 795 | } else if (dest->addrtype == TIPC_ADDR_NAME) { |
650 | res = tipc_send2name(port, | 796 | u32 type = dest->addr.name.name.type; |
651 | &dest->addr.name.name, | 797 | u32 inst = dest->addr.name.name.instance; |
652 | dest->addr.name.domain, | 798 | u32 domain = dest->addr.name.domain; |
653 | m->msg_iov, | 799 | |
654 | total_len); | 800 | dnode = domain; |
655 | } else if (dest->addrtype == TIPC_ADDR_ID) { | 801 | msg_set_type(mhdr, TIPC_NAMED_MSG); |
656 | res = tipc_send2port(port, | 802 | msg_set_hdr_sz(mhdr, NAMED_H_SIZE); |
657 | &dest->addr.id, | 803 | msg_set_nametype(mhdr, type); |
658 | m->msg_iov, | 804 | msg_set_nameinst(mhdr, inst); |
659 | total_len); | 805 | msg_set_lookup_scope(mhdr, tipc_addr_scope(domain)); |
660 | } else if (dest->addrtype == TIPC_ADDR_MCAST) { | 806 | dport = tipc_nametbl_translate(type, inst, &dnode); |
661 | if (needs_conn) { | 807 | msg_set_destnode(mhdr, dnode); |
662 | res = -EOPNOTSUPP; | 808 | msg_set_destport(mhdr, dport); |
663 | break; | 809 | if (unlikely(!dport && !dnode)) { |
664 | } | 810 | rc = -EHOSTUNREACH; |
665 | res = dest_name_check(dest, m); | 811 | goto exit; |
666 | if (res) | ||
667 | break; | ||
668 | res = tipc_port_mcast_xmit(port, | ||
669 | &dest->addr.nameseq, | ||
670 | m->msg_iov, | ||
671 | total_len); | ||
672 | } | 812 | } |
673 | if (likely(res != -ELINKCONG)) { | 813 | } else if (dest->addrtype == TIPC_ADDR_ID) { |
674 | if (needs_conn && (res >= 0)) | 814 | dnode = dest->addr.id.node; |
815 | msg_set_type(mhdr, TIPC_DIRECT_MSG); | ||
816 | msg_set_lookup_scope(mhdr, 0); | ||
817 | msg_set_destnode(mhdr, dnode); | ||
818 | msg_set_destport(mhdr, dest->addr.id.ref); | ||
819 | msg_set_hdr_sz(mhdr, BASIC_H_SIZE); | ||
820 | } | ||
821 | |||
822 | new_mtu: | ||
823 | mtu = tipc_node_get_mtu(dnode, tsk->port.ref); | ||
824 | rc = tipc_msg_build(mhdr, iov, 0, dsz, mtu, &buf); | ||
825 | if (rc < 0) | ||
826 | goto exit; | ||
827 | |||
828 | do { | ||
829 | rc = tipc_link_xmit(buf, dnode, tsk->port.ref); | ||
830 | if (likely(rc >= 0)) { | ||
831 | if (sock->state != SS_READY) | ||
675 | sock->state = SS_CONNECTING; | 832 | sock->state = SS_CONNECTING; |
833 | rc = dsz; | ||
676 | break; | 834 | break; |
677 | } | 835 | } |
678 | res = tipc_wait_for_sndmsg(sock, &timeo); | 836 | if (rc == -EMSGSIZE) |
679 | if (res) | 837 | goto new_mtu; |
838 | |||
839 | if (rc != -ELINKCONG) | ||
680 | break; | 840 | break; |
681 | } while (1); | ||
682 | 841 | ||
842 | rc = tipc_wait_for_sndmsg(sock, &timeo); | ||
843 | if (rc) | ||
844 | kfree_skb_list(buf); | ||
845 | } while (!rc); | ||
683 | exit: | 846 | exit: |
684 | if (iocb) | 847 | if (iocb) |
685 | release_sock(sk); | 848 | release_sock(sk); |
686 | return res; | 849 | |
850 | return rc; | ||
687 | } | 851 | } |
688 | 852 | ||
689 | static int tipc_wait_for_sndpkt(struct socket *sock, long *timeo_p) | 853 | static int tipc_wait_for_sndpkt(struct socket *sock, long *timeo_p) |
690 | { | 854 | { |
691 | struct sock *sk = sock->sk; | 855 | struct sock *sk = sock->sk; |
692 | struct tipc_sock *tsk = tipc_sk(sk); | 856 | struct tipc_sock *tsk = tipc_sk(sk); |
693 | struct tipc_port *port = &tsk->port; | ||
694 | DEFINE_WAIT(wait); | 857 | DEFINE_WAIT(wait); |
695 | int done; | 858 | int done; |
696 | 859 | ||
@@ -709,37 +872,49 @@ static int tipc_wait_for_sndpkt(struct socket *sock, long *timeo_p) | |||
709 | 872 | ||
710 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | 873 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
711 | done = sk_wait_event(sk, timeo_p, | 874 | done = sk_wait_event(sk, timeo_p, |
712 | (!port->congested || !port->connected)); | 875 | (!tsk->link_cong && |
876 | !tipc_sk_conn_cong(tsk)) || | ||
877 | !tsk->port.connected); | ||
713 | finish_wait(sk_sleep(sk), &wait); | 878 | finish_wait(sk_sleep(sk), &wait); |
714 | } while (!done); | 879 | } while (!done); |
715 | return 0; | 880 | return 0; |
716 | } | 881 | } |
717 | 882 | ||
718 | /** | 883 | /** |
719 | * tipc_send_packet - send a connection-oriented message | 884 | * tipc_send_stream - send stream-oriented data |
720 | * @iocb: if NULL, indicates that socket lock is already held | 885 | * @iocb: (unused) |
721 | * @sock: socket structure | 886 | * @sock: socket structure |
722 | * @m: message to send | 887 | * @m: data to send |
723 | * @total_len: length of message | 888 | * @dsz: total length of data to be transmitted |
724 | * | 889 | * |
725 | * Used for SOCK_SEQPACKET messages and SOCK_STREAM data. | 890 | * Used for SOCK_STREAM data. |
726 | * | 891 | * |
727 | * Returns the number of bytes sent on success, or errno otherwise | 892 | * Returns the number of bytes sent on success (or partial success), |
893 | * or errno if no data sent | ||
728 | */ | 894 | */ |
729 | static int tipc_send_packet(struct kiocb *iocb, struct socket *sock, | 895 | static int tipc_send_stream(struct kiocb *iocb, struct socket *sock, |
730 | struct msghdr *m, size_t total_len) | 896 | struct msghdr *m, size_t dsz) |
731 | { | 897 | { |
732 | struct sock *sk = sock->sk; | 898 | struct sock *sk = sock->sk; |
733 | struct tipc_sock *tsk = tipc_sk(sk); | 899 | struct tipc_sock *tsk = tipc_sk(sk); |
900 | struct tipc_port *port = &tsk->port; | ||
901 | struct tipc_msg *mhdr = &port->phdr; | ||
902 | struct sk_buff *buf; | ||
734 | DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name); | 903 | DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name); |
735 | int res = -EINVAL; | 904 | u32 ref = port->ref; |
905 | int rc = -EINVAL; | ||
736 | long timeo; | 906 | long timeo; |
907 | u32 dnode; | ||
908 | uint mtu, send, sent = 0; | ||
737 | 909 | ||
738 | /* Handle implied connection establishment */ | 910 | /* Handle implied connection establishment */ |
739 | if (unlikely(dest)) | 911 | if (unlikely(dest)) { |
740 | return tipc_sendmsg(iocb, sock, m, total_len); | 912 | rc = tipc_sendmsg(iocb, sock, m, dsz); |
741 | 913 | if (dsz && (dsz == rc)) | |
742 | if (total_len > TIPC_MAX_USER_MSG_SIZE) | 914 | tsk->sent_unacked = 1; |
915 | return rc; | ||
916 | } | ||
917 | if (dsz > (uint)INT_MAX) | ||
743 | return -EMSGSIZE; | 918 | return -EMSGSIZE; |
744 | 919 | ||
745 | if (iocb) | 920 | if (iocb) |
@@ -747,123 +922,66 @@ static int tipc_send_packet(struct kiocb *iocb, struct socket *sock, | |||
747 | 922 | ||
748 | if (unlikely(sock->state != SS_CONNECTED)) { | 923 | if (unlikely(sock->state != SS_CONNECTED)) { |
749 | if (sock->state == SS_DISCONNECTING) | 924 | if (sock->state == SS_DISCONNECTING) |
750 | res = -EPIPE; | 925 | rc = -EPIPE; |
751 | else | 926 | else |
752 | res = -ENOTCONN; | 927 | rc = -ENOTCONN; |
753 | goto exit; | 928 | goto exit; |
754 | } | 929 | } |
755 | 930 | ||
756 | timeo = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); | 931 | timeo = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); |
932 | dnode = tipc_port_peernode(port); | ||
933 | |||
934 | next: | ||
935 | mtu = port->max_pkt; | ||
936 | send = min_t(uint, dsz - sent, TIPC_MAX_USER_MSG_SIZE); | ||
937 | rc = tipc_msg_build(mhdr, m->msg_iov, sent, send, mtu, &buf); | ||
938 | if (unlikely(rc < 0)) | ||
939 | goto exit; | ||
757 | do { | 940 | do { |
758 | res = tipc_send(&tsk->port, m->msg_iov, total_len); | 941 | if (likely(!tipc_sk_conn_cong(tsk))) { |
759 | if (likely(res != -ELINKCONG)) | 942 | rc = tipc_link_xmit(buf, dnode, ref); |
760 | break; | 943 | if (likely(!rc)) { |
761 | res = tipc_wait_for_sndpkt(sock, &timeo); | 944 | tsk->sent_unacked++; |
762 | if (res) | 945 | sent += send; |
763 | break; | 946 | if (sent == dsz) |
764 | } while (1); | 947 | break; |
948 | goto next; | ||
949 | } | ||
950 | if (rc == -EMSGSIZE) { | ||
951 | port->max_pkt = tipc_node_get_mtu(dnode, ref); | ||
952 | goto next; | ||
953 | } | ||
954 | if (rc != -ELINKCONG) | ||
955 | break; | ||
956 | } | ||
957 | rc = tipc_wait_for_sndpkt(sock, &timeo); | ||
958 | if (rc) | ||
959 | kfree_skb_list(buf); | ||
960 | } while (!rc); | ||
765 | exit: | 961 | exit: |
766 | if (iocb) | 962 | if (iocb) |
767 | release_sock(sk); | 963 | release_sock(sk); |
768 | return res; | 964 | return sent ? sent : rc; |
769 | } | 965 | } |
770 | 966 | ||
771 | /** | 967 | /** |
772 | * tipc_send_stream - send stream-oriented data | 968 | * tipc_send_packet - send a connection-oriented message |
773 | * @iocb: (unused) | 969 | * @iocb: if NULL, indicates that socket lock is already held |
774 | * @sock: socket structure | 970 | * @sock: socket structure |
775 | * @m: data to send | 971 | * @m: message to send |
776 | * @total_len: total length of data to be sent | 972 | * @dsz: length of data to be transmitted |
777 | * | 973 | * |
778 | * Used for SOCK_STREAM data. | 974 | * Used for SOCK_SEQPACKET messages. |
779 | * | 975 | * |
780 | * Returns the number of bytes sent on success (or partial success), | 976 | * Returns the number of bytes sent on success, or errno otherwise |
781 | * or errno if no data sent | ||
782 | */ | 977 | */ |
783 | static int tipc_send_stream(struct kiocb *iocb, struct socket *sock, | 978 | static int tipc_send_packet(struct kiocb *iocb, struct socket *sock, |
784 | struct msghdr *m, size_t total_len) | 979 | struct msghdr *m, size_t dsz) |
785 | { | 980 | { |
786 | struct sock *sk = sock->sk; | 981 | if (dsz > TIPC_MAX_USER_MSG_SIZE) |
787 | struct tipc_sock *tsk = tipc_sk(sk); | 982 | return -EMSGSIZE; |
788 | struct msghdr my_msg; | ||
789 | struct iovec my_iov; | ||
790 | struct iovec *curr_iov; | ||
791 | int curr_iovlen; | ||
792 | char __user *curr_start; | ||
793 | u32 hdr_size; | ||
794 | int curr_left; | ||
795 | int bytes_to_send; | ||
796 | int bytes_sent; | ||
797 | int res; | ||
798 | |||
799 | lock_sock(sk); | ||
800 | |||
801 | /* Handle special cases where there is no connection */ | ||
802 | if (unlikely(sock->state != SS_CONNECTED)) { | ||
803 | if (sock->state == SS_UNCONNECTED) | ||
804 | res = tipc_send_packet(NULL, sock, m, total_len); | ||
805 | else | ||
806 | res = sock->state == SS_DISCONNECTING ? -EPIPE : -ENOTCONN; | ||
807 | goto exit; | ||
808 | } | ||
809 | |||
810 | if (unlikely(m->msg_name)) { | ||
811 | res = -EISCONN; | ||
812 | goto exit; | ||
813 | } | ||
814 | |||
815 | if (total_len > (unsigned int)INT_MAX) { | ||
816 | res = -EMSGSIZE; | ||
817 | goto exit; | ||
818 | } | ||
819 | |||
820 | /* | ||
821 | * Send each iovec entry using one or more messages | ||
822 | * | ||
823 | * Note: This algorithm is good for the most likely case | ||
824 | * (i.e. one large iovec entry), but could be improved to pass sets | ||
825 | * of small iovec entries into send_packet(). | ||
826 | */ | ||
827 | curr_iov = m->msg_iov; | ||
828 | curr_iovlen = m->msg_iovlen; | ||
829 | my_msg.msg_iov = &my_iov; | ||
830 | my_msg.msg_iovlen = 1; | ||
831 | my_msg.msg_flags = m->msg_flags; | ||
832 | my_msg.msg_name = NULL; | ||
833 | bytes_sent = 0; | ||
834 | |||
835 | hdr_size = msg_hdr_sz(&tsk->port.phdr); | ||
836 | |||
837 | while (curr_iovlen--) { | ||
838 | curr_start = curr_iov->iov_base; | ||
839 | curr_left = curr_iov->iov_len; | ||
840 | |||
841 | while (curr_left) { | ||
842 | bytes_to_send = tsk->port.max_pkt - hdr_size; | ||
843 | if (bytes_to_send > TIPC_MAX_USER_MSG_SIZE) | ||
844 | bytes_to_send = TIPC_MAX_USER_MSG_SIZE; | ||
845 | if (curr_left < bytes_to_send) | ||
846 | bytes_to_send = curr_left; | ||
847 | my_iov.iov_base = curr_start; | ||
848 | my_iov.iov_len = bytes_to_send; | ||
849 | res = tipc_send_packet(NULL, sock, &my_msg, | ||
850 | bytes_to_send); | ||
851 | if (res < 0) { | ||
852 | if (bytes_sent) | ||
853 | res = bytes_sent; | ||
854 | goto exit; | ||
855 | } | ||
856 | curr_left -= bytes_to_send; | ||
857 | curr_start += bytes_to_send; | ||
858 | bytes_sent += bytes_to_send; | ||
859 | } | ||
860 | 983 | ||
861 | curr_iov++; | 984 | return tipc_send_stream(iocb, sock, m, dsz); |
862 | } | ||
863 | res = bytes_sent; | ||
864 | exit: | ||
865 | release_sock(sk); | ||
866 | return res; | ||
867 | } | 985 | } |
868 | 986 | ||
869 | /** | 987 | /** |
@@ -1104,8 +1222,10 @@ restart: | |||
1104 | /* Consume received message (optional) */ | 1222 | /* Consume received message (optional) */ |
1105 | if (likely(!(flags & MSG_PEEK))) { | 1223 | if (likely(!(flags & MSG_PEEK))) { |
1106 | if ((sock->state != SS_READY) && | 1224 | if ((sock->state != SS_READY) && |
1107 | (++port->conn_unacked >= TIPC_CONNACK_INTV)) | 1225 | (++tsk->rcv_unacked >= TIPC_CONNACK_INTV)) { |
1108 | tipc_acknowledge(port->ref, port->conn_unacked); | 1226 | tipc_acknowledge(port->ref, tsk->rcv_unacked); |
1227 | tsk->rcv_unacked = 0; | ||
1228 | } | ||
1109 | advance_rx_queue(sk); | 1229 | advance_rx_queue(sk); |
1110 | } | 1230 | } |
1111 | exit: | 1231 | exit: |
@@ -1213,8 +1333,10 @@ restart: | |||
1213 | 1333 | ||
1214 | /* Consume received message (optional) */ | 1334 | /* Consume received message (optional) */ |
1215 | if (likely(!(flags & MSG_PEEK))) { | 1335 | if (likely(!(flags & MSG_PEEK))) { |
1216 | if (unlikely(++port->conn_unacked >= TIPC_CONNACK_INTV)) | 1336 | if (unlikely(++tsk->rcv_unacked >= TIPC_CONNACK_INTV)) { |
1217 | tipc_acknowledge(port->ref, port->conn_unacked); | 1337 | tipc_acknowledge(port->ref, tsk->rcv_unacked); |
1338 | tsk->rcv_unacked = 0; | ||
1339 | } | ||
1218 | advance_rx_queue(sk); | 1340 | advance_rx_queue(sk); |
1219 | } | 1341 | } |
1220 | 1342 | ||
@@ -1269,17 +1391,16 @@ static void tipc_data_ready(struct sock *sk) | |||
1269 | * @tsk: TIPC socket | 1391 | * @tsk: TIPC socket |
1270 | * @msg: message | 1392 | * @msg: message |
1271 | * | 1393 | * |
1272 | * Returns TIPC error status code and socket error status code | 1394 | * Returns 0 (TIPC_OK) if everyting ok, -TIPC_ERR_NO_PORT otherwise |
1273 | * once it encounters some errors | ||
1274 | */ | 1395 | */ |
1275 | static u32 filter_connect(struct tipc_sock *tsk, struct sk_buff **buf) | 1396 | static int filter_connect(struct tipc_sock *tsk, struct sk_buff **buf) |
1276 | { | 1397 | { |
1277 | struct sock *sk = &tsk->sk; | 1398 | struct sock *sk = &tsk->sk; |
1278 | struct tipc_port *port = &tsk->port; | 1399 | struct tipc_port *port = &tsk->port; |
1279 | struct socket *sock = sk->sk_socket; | 1400 | struct socket *sock = sk->sk_socket; |
1280 | struct tipc_msg *msg = buf_msg(*buf); | 1401 | struct tipc_msg *msg = buf_msg(*buf); |
1281 | 1402 | ||
1282 | u32 retval = TIPC_ERR_NO_PORT; | 1403 | int retval = -TIPC_ERR_NO_PORT; |
1283 | int res; | 1404 | int res; |
1284 | 1405 | ||
1285 | if (msg_mcast(msg)) | 1406 | if (msg_mcast(msg)) |
@@ -1382,32 +1503,37 @@ static unsigned int rcvbuf_limit(struct sock *sk, struct sk_buff *buf) | |||
1382 | * | 1503 | * |
1383 | * Called with socket lock already taken; port lock may also be taken. | 1504 | * Called with socket lock already taken; port lock may also be taken. |
1384 | * | 1505 | * |
1385 | * Returns TIPC error status code (TIPC_OK if message is not to be rejected) | 1506 | * Returns 0 (TIPC_OK) if message was consumed, -TIPC error code if message |
1507 | * to be rejected, 1 (TIPC_FWD_MSG) if (CONN_MANAGER) message to be forwarded | ||
1386 | */ | 1508 | */ |
1387 | static u32 filter_rcv(struct sock *sk, struct sk_buff *buf) | 1509 | static int filter_rcv(struct sock *sk, struct sk_buff *buf) |
1388 | { | 1510 | { |
1389 | struct socket *sock = sk->sk_socket; | 1511 | struct socket *sock = sk->sk_socket; |
1390 | struct tipc_sock *tsk = tipc_sk(sk); | 1512 | struct tipc_sock *tsk = tipc_sk(sk); |
1391 | struct tipc_msg *msg = buf_msg(buf); | 1513 | struct tipc_msg *msg = buf_msg(buf); |
1392 | unsigned int limit = rcvbuf_limit(sk, buf); | 1514 | unsigned int limit = rcvbuf_limit(sk, buf); |
1393 | u32 res = TIPC_OK; | 1515 | u32 onode; |
1516 | int rc = TIPC_OK; | ||
1517 | |||
1518 | if (unlikely(msg_user(msg) == CONN_MANAGER)) | ||
1519 | return tipc_sk_proto_rcv(tsk, &onode, buf); | ||
1394 | 1520 | ||
1395 | /* Reject message if it is wrong sort of message for socket */ | 1521 | /* Reject message if it is wrong sort of message for socket */ |
1396 | if (msg_type(msg) > TIPC_DIRECT_MSG) | 1522 | if (msg_type(msg) > TIPC_DIRECT_MSG) |
1397 | return TIPC_ERR_NO_PORT; | 1523 | return -TIPC_ERR_NO_PORT; |
1398 | 1524 | ||
1399 | if (sock->state == SS_READY) { | 1525 | if (sock->state == SS_READY) { |
1400 | if (msg_connected(msg)) | 1526 | if (msg_connected(msg)) |
1401 | return TIPC_ERR_NO_PORT; | 1527 | return -TIPC_ERR_NO_PORT; |
1402 | } else { | 1528 | } else { |
1403 | res = filter_connect(tsk, &buf); | 1529 | rc = filter_connect(tsk, &buf); |
1404 | if (res != TIPC_OK || buf == NULL) | 1530 | if (rc != TIPC_OK || buf == NULL) |
1405 | return res; | 1531 | return rc; |
1406 | } | 1532 | } |
1407 | 1533 | ||
1408 | /* Reject message if there isn't room to queue it */ | 1534 | /* Reject message if there isn't room to queue it */ |
1409 | if (sk_rmem_alloc_get(sk) + buf->truesize >= limit) | 1535 | if (sk_rmem_alloc_get(sk) + buf->truesize >= limit) |
1410 | return TIPC_ERR_OVERLOAD; | 1536 | return -TIPC_ERR_OVERLOAD; |
1411 | 1537 | ||
1412 | /* Enqueue message */ | 1538 | /* Enqueue message */ |
1413 | TIPC_SKB_CB(buf)->handle = NULL; | 1539 | TIPC_SKB_CB(buf)->handle = NULL; |
@@ -1429,16 +1555,23 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf) | |||
1429 | */ | 1555 | */ |
1430 | static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *buf) | 1556 | static int tipc_backlog_rcv(struct sock *sk, struct sk_buff *buf) |
1431 | { | 1557 | { |
1432 | u32 res; | 1558 | int rc; |
1559 | u32 onode; | ||
1433 | struct tipc_sock *tsk = tipc_sk(sk); | 1560 | struct tipc_sock *tsk = tipc_sk(sk); |
1434 | uint truesize = buf->truesize; | 1561 | uint truesize = buf->truesize; |
1435 | 1562 | ||
1436 | res = filter_rcv(sk, buf); | 1563 | rc = filter_rcv(sk, buf); |
1437 | if (unlikely(res)) | ||
1438 | tipc_reject_msg(buf, res); | ||
1439 | 1564 | ||
1440 | if (atomic_read(&tsk->dupl_rcvcnt) < TIPC_CONN_OVERLOAD_LIMIT) | 1565 | if (likely(!rc)) { |
1441 | atomic_add(truesize, &tsk->dupl_rcvcnt); | 1566 | if (atomic_read(&tsk->dupl_rcvcnt) < TIPC_CONN_OVERLOAD_LIMIT) |
1567 | atomic_add(truesize, &tsk->dupl_rcvcnt); | ||
1568 | return 0; | ||
1569 | } | ||
1570 | |||
1571 | if ((rc < 0) && !tipc_msg_reverse(buf, &onode, -rc)) | ||
1572 | return 0; | ||
1573 | |||
1574 | tipc_link_xmit(buf, onode, 0); | ||
1442 | 1575 | ||
1443 | return 0; | 1576 | return 0; |
1444 | } | 1577 | } |
@@ -1455,19 +1588,14 @@ int tipc_sk_rcv(struct sk_buff *buf) | |||
1455 | struct tipc_port *port; | 1588 | struct tipc_port *port; |
1456 | struct sock *sk; | 1589 | struct sock *sk; |
1457 | u32 dport = msg_destport(buf_msg(buf)); | 1590 | u32 dport = msg_destport(buf_msg(buf)); |
1458 | int err = TIPC_OK; | 1591 | int rc = TIPC_OK; |
1459 | uint limit; | 1592 | uint limit; |
1593 | u32 dnode; | ||
1460 | 1594 | ||
1461 | /* Forward unresolved named message */ | 1595 | /* Validate destination and message */ |
1462 | if (unlikely(!dport)) { | ||
1463 | tipc_net_route_msg(buf); | ||
1464 | return 0; | ||
1465 | } | ||
1466 | |||
1467 | /* Validate destination */ | ||
1468 | port = tipc_port_lock(dport); | 1596 | port = tipc_port_lock(dport); |
1469 | if (unlikely(!port)) { | 1597 | if (unlikely(!port)) { |
1470 | err = TIPC_ERR_NO_PORT; | 1598 | rc = tipc_msg_eval(buf, &dnode); |
1471 | goto exit; | 1599 | goto exit; |
1472 | } | 1600 | } |
1473 | 1601 | ||
@@ -1478,23 +1606,25 @@ int tipc_sk_rcv(struct sk_buff *buf) | |||
1478 | bh_lock_sock(sk); | 1606 | bh_lock_sock(sk); |
1479 | 1607 | ||
1480 | if (!sock_owned_by_user(sk)) { | 1608 | if (!sock_owned_by_user(sk)) { |
1481 | err = filter_rcv(sk, buf); | 1609 | rc = filter_rcv(sk, buf); |
1482 | } else { | 1610 | } else { |
1483 | if (sk->sk_backlog.len == 0) | 1611 | if (sk->sk_backlog.len == 0) |
1484 | atomic_set(&tsk->dupl_rcvcnt, 0); | 1612 | atomic_set(&tsk->dupl_rcvcnt, 0); |
1485 | limit = rcvbuf_limit(sk, buf) + atomic_read(&tsk->dupl_rcvcnt); | 1613 | limit = rcvbuf_limit(sk, buf) + atomic_read(&tsk->dupl_rcvcnt); |
1486 | if (sk_add_backlog(sk, buf, limit)) | 1614 | if (sk_add_backlog(sk, buf, limit)) |
1487 | err = TIPC_ERR_OVERLOAD; | 1615 | rc = -TIPC_ERR_OVERLOAD; |
1488 | } | 1616 | } |
1489 | |||
1490 | bh_unlock_sock(sk); | 1617 | bh_unlock_sock(sk); |
1491 | tipc_port_unlock(port); | 1618 | tipc_port_unlock(port); |
1492 | 1619 | ||
1493 | if (likely(!err)) | 1620 | if (likely(!rc)) |
1494 | return 0; | 1621 | return 0; |
1495 | exit: | 1622 | exit: |
1496 | tipc_reject_msg(buf, err); | 1623 | if ((rc < 0) && !tipc_msg_reverse(buf, &dnode, -rc)) |
1497 | return -EHOSTUNREACH; | 1624 | return -EHOSTUNREACH; |
1625 | |||
1626 | tipc_link_xmit(buf, dnode, 0); | ||
1627 | return (rc < 0) ? -EHOSTUNREACH : 0; | ||
1498 | } | 1628 | } |
1499 | 1629 | ||
1500 | static int tipc_wait_for_connect(struct socket *sock, long *timeo_p) | 1630 | static int tipc_wait_for_connect(struct socket *sock, long *timeo_p) |
@@ -1758,6 +1888,7 @@ static int tipc_shutdown(struct socket *sock, int how) | |||
1758 | struct tipc_sock *tsk = tipc_sk(sk); | 1888 | struct tipc_sock *tsk = tipc_sk(sk); |
1759 | struct tipc_port *port = &tsk->port; | 1889 | struct tipc_port *port = &tsk->port; |
1760 | struct sk_buff *buf; | 1890 | struct sk_buff *buf; |
1891 | u32 peer; | ||
1761 | int res; | 1892 | int res; |
1762 | 1893 | ||
1763 | if (how != SHUT_RDWR) | 1894 | if (how != SHUT_RDWR) |
@@ -1778,7 +1909,8 @@ restart: | |||
1778 | goto restart; | 1909 | goto restart; |
1779 | } | 1910 | } |
1780 | tipc_port_disconnect(port->ref); | 1911 | tipc_port_disconnect(port->ref); |
1781 | tipc_reject_msg(buf, TIPC_CONN_SHUTDOWN); | 1912 | if (tipc_msg_reverse(buf, &peer, TIPC_CONN_SHUTDOWN)) |
1913 | tipc_link_xmit(buf, peer, 0); | ||
1782 | } else { | 1914 | } else { |
1783 | tipc_port_shutdown(port->ref); | 1915 | tipc_port_shutdown(port->ref); |
1784 | } | 1916 | } |
@@ -1841,7 +1973,7 @@ static int tipc_setsockopt(struct socket *sock, int lvl, int opt, | |||
1841 | 1973 | ||
1842 | switch (opt) { | 1974 | switch (opt) { |
1843 | case TIPC_IMPORTANCE: | 1975 | case TIPC_IMPORTANCE: |
1844 | tipc_port_set_importance(port, value); | 1976 | res = tipc_port_set_importance(port, value); |
1845 | break; | 1977 | break; |
1846 | case TIPC_SRC_DROPPABLE: | 1978 | case TIPC_SRC_DROPPABLE: |
1847 | if (sock->type != SOCK_STREAM) | 1979 | if (sock->type != SOCK_STREAM) |
@@ -1936,7 +2068,7 @@ static int tipc_getsockopt(struct socket *sock, int lvl, int opt, | |||
1936 | return put_user(sizeof(value), ol); | 2068 | return put_user(sizeof(value), ol); |
1937 | } | 2069 | } |
1938 | 2070 | ||
1939 | int tipc_ioctl(struct socket *sk, unsigned int cmd, unsigned long arg) | 2071 | static int tipc_ioctl(struct socket *sk, unsigned int cmd, unsigned long arg) |
1940 | { | 2072 | { |
1941 | struct tipc_sioc_ln_req lnr; | 2073 | struct tipc_sioc_ln_req lnr; |
1942 | void __user *argp = (void __user *)arg; | 2074 | void __user *argp = (void __user *)arg; |
@@ -1952,7 +2084,6 @@ int tipc_ioctl(struct socket *sk, unsigned int cmd, unsigned long arg) | |||
1952 | return 0; | 2084 | return 0; |
1953 | } | 2085 | } |
1954 | return -EADDRNOTAVAIL; | 2086 | return -EADDRNOTAVAIL; |
1955 | break; | ||
1956 | default: | 2087 | default: |
1957 | return -ENOIOCTLCMD; | 2088 | return -ENOIOCTLCMD; |
1958 | } | 2089 | } |
diff --git a/net/tipc/socket.h b/net/tipc/socket.h index 3afcd2a70b31..43b75b3ceced 100644 --- a/net/tipc/socket.h +++ b/net/tipc/socket.h | |||
@@ -38,6 +38,9 @@ | |||
38 | #include "port.h" | 38 | #include "port.h" |
39 | #include <net/sock.h> | 39 | #include <net/sock.h> |
40 | 40 | ||
41 | #define TIPC_CONN_OK 0 | ||
42 | #define TIPC_CONN_PROBING 1 | ||
43 | |||
41 | /** | 44 | /** |
42 | * struct tipc_sock - TIPC socket structure | 45 | * struct tipc_sock - TIPC socket structure |
43 | * @sk: socket - interacts with 'port' and with user via the socket API | 46 | * @sk: socket - interacts with 'port' and with user via the socket API |
@@ -45,6 +48,9 @@ | |||
45 | * @peer_name: the peer of the connection, if any | 48 | * @peer_name: the peer of the connection, if any |
46 | * @conn_timeout: the time we can wait for an unresponded setup request | 49 | * @conn_timeout: the time we can wait for an unresponded setup request |
47 | * @dupl_rcvcnt: number of bytes counted twice, in both backlog and rcv queue | 50 | * @dupl_rcvcnt: number of bytes counted twice, in both backlog and rcv queue |
51 | * @link_cong: non-zero if owner must sleep because of link congestion | ||
52 | * @sent_unacked: # messages sent by socket, and not yet acked by peer | ||
53 | * @rcv_unacked: # messages read by user, but not yet acked back to peer | ||
48 | */ | 54 | */ |
49 | 55 | ||
50 | struct tipc_sock { | 56 | struct tipc_sock { |
@@ -52,6 +58,9 @@ struct tipc_sock { | |||
52 | struct tipc_port port; | 58 | struct tipc_port port; |
53 | unsigned int conn_timeout; | 59 | unsigned int conn_timeout; |
54 | atomic_t dupl_rcvcnt; | 60 | atomic_t dupl_rcvcnt; |
61 | int link_cong; | ||
62 | uint sent_unacked; | ||
63 | uint rcv_unacked; | ||
55 | }; | 64 | }; |
56 | 65 | ||
57 | static inline struct tipc_sock *tipc_sk(const struct sock *sk) | 66 | static inline struct tipc_sock *tipc_sk(const struct sock *sk) |
@@ -69,6 +78,13 @@ static inline void tipc_sock_wakeup(struct tipc_sock *tsk) | |||
69 | tsk->sk.sk_write_space(&tsk->sk); | 78 | tsk->sk.sk_write_space(&tsk->sk); |
70 | } | 79 | } |
71 | 80 | ||
81 | static inline int tipc_sk_conn_cong(struct tipc_sock *tsk) | ||
82 | { | ||
83 | return tsk->sent_unacked >= TIPC_FLOWCTRL_WIN; | ||
84 | } | ||
85 | |||
72 | int tipc_sk_rcv(struct sk_buff *buf); | 86 | int tipc_sk_rcv(struct sk_buff *buf); |
73 | 87 | ||
88 | void tipc_sk_mcast_rcv(struct sk_buff *buf); | ||
89 | |||
74 | #endif | 90 | #endif |
diff --git a/net/wireless/Kconfig b/net/wireless/Kconfig index 405f3c4cf70c..29c8675f9a11 100644 --- a/net/wireless/Kconfig +++ b/net/wireless/Kconfig | |||
@@ -162,6 +162,12 @@ config CFG80211_INTERNAL_REGDB | |||
162 | and includes code to query that database. This is an alternative | 162 | and includes code to query that database. This is an alternative |
163 | to using CRDA for defining regulatory rules for the kernel. | 163 | to using CRDA for defining regulatory rules for the kernel. |
164 | 164 | ||
165 | Using this option requires some parsing of the db.txt at build time, | ||
166 | the parser will be upkept with the latest wireless-regdb updates but | ||
167 | older wireless-regdb formats will be ignored. The parser may later | ||
168 | be replaced to avoid issues with conflicts on versions of | ||
169 | wireless-regdb. | ||
170 | |||
165 | For details see: | 171 | For details see: |
166 | 172 | ||
167 | http://wireless.kernel.org/en/developers/Regulatory | 173 | http://wireless.kernel.org/en/developers/Regulatory |
diff --git a/net/wireless/core.c b/net/wireless/core.c index a1c40654dd9b..afee5e0455ea 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
@@ -25,7 +25,6 @@ | |||
25 | #include "sysfs.h" | 25 | #include "sysfs.h" |
26 | #include "debugfs.h" | 26 | #include "debugfs.h" |
27 | #include "wext-compat.h" | 27 | #include "wext-compat.h" |
28 | #include "ethtool.h" | ||
29 | #include "rdev-ops.h" | 28 | #include "rdev-ops.h" |
30 | 29 | ||
31 | /* name for sysfs, %d is appended */ | 30 | /* name for sysfs, %d is appended */ |
@@ -927,8 +926,6 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | |||
927 | /* allow mac80211 to determine the timeout */ | 926 | /* allow mac80211 to determine the timeout */ |
928 | wdev->ps_timeout = -1; | 927 | wdev->ps_timeout = -1; |
929 | 928 | ||
930 | netdev_set_default_ethtool_ops(dev, &cfg80211_ethtool_ops); | ||
931 | |||
932 | if ((wdev->iftype == NL80211_IFTYPE_STATION || | 929 | if ((wdev->iftype == NL80211_IFTYPE_STATION || |
933 | wdev->iftype == NL80211_IFTYPE_P2P_CLIENT || | 930 | wdev->iftype == NL80211_IFTYPE_P2P_CLIENT || |
934 | wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr) | 931 | wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr) |
diff --git a/net/wireless/ethtool.c b/net/wireless/ethtool.c index d4860bfc020e..e9e91298c70d 100644 --- a/net/wireless/ethtool.c +++ b/net/wireless/ethtool.c | |||
@@ -1,11 +1,9 @@ | |||
1 | #include <linux/utsname.h> | 1 | #include <linux/utsname.h> |
2 | #include <net/cfg80211.h> | 2 | #include <net/cfg80211.h> |
3 | #include "core.h" | 3 | #include "core.h" |
4 | #include "ethtool.h" | ||
5 | #include "rdev-ops.h" | 4 | #include "rdev-ops.h" |
6 | 5 | ||
7 | static void cfg80211_get_drvinfo(struct net_device *dev, | 6 | void cfg80211_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) |
8 | struct ethtool_drvinfo *info) | ||
9 | { | 7 | { |
10 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 8 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
11 | 9 | ||
@@ -23,84 +21,4 @@ static void cfg80211_get_drvinfo(struct net_device *dev, | |||
23 | strlcpy(info->bus_info, dev_name(wiphy_dev(wdev->wiphy)), | 21 | strlcpy(info->bus_info, dev_name(wiphy_dev(wdev->wiphy)), |
24 | sizeof(info->bus_info)); | 22 | sizeof(info->bus_info)); |
25 | } | 23 | } |
26 | 24 | EXPORT_SYMBOL(cfg80211_get_drvinfo); | |
27 | static int cfg80211_get_regs_len(struct net_device *dev) | ||
28 | { | ||
29 | /* For now, return 0... */ | ||
30 | return 0; | ||
31 | } | ||
32 | |||
33 | static void cfg80211_get_regs(struct net_device *dev, struct ethtool_regs *regs, | ||
34 | void *data) | ||
35 | { | ||
36 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
37 | |||
38 | regs->version = wdev->wiphy->hw_version; | ||
39 | regs->len = 0; | ||
40 | } | ||
41 | |||
42 | static void cfg80211_get_ringparam(struct net_device *dev, | ||
43 | struct ethtool_ringparam *rp) | ||
44 | { | ||
45 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
46 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); | ||
47 | |||
48 | memset(rp, 0, sizeof(*rp)); | ||
49 | |||
50 | if (rdev->ops->get_ringparam) | ||
51 | rdev_get_ringparam(rdev, &rp->tx_pending, &rp->tx_max_pending, | ||
52 | &rp->rx_pending, &rp->rx_max_pending); | ||
53 | } | ||
54 | |||
55 | static int cfg80211_set_ringparam(struct net_device *dev, | ||
56 | struct ethtool_ringparam *rp) | ||
57 | { | ||
58 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
59 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); | ||
60 | |||
61 | if (rp->rx_mini_pending != 0 || rp->rx_jumbo_pending != 0) | ||
62 | return -EINVAL; | ||
63 | |||
64 | if (rdev->ops->set_ringparam) | ||
65 | return rdev_set_ringparam(rdev, rp->tx_pending, rp->rx_pending); | ||
66 | |||
67 | return -ENOTSUPP; | ||
68 | } | ||
69 | |||
70 | static int cfg80211_get_sset_count(struct net_device *dev, int sset) | ||
71 | { | ||
72 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
73 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); | ||
74 | if (rdev->ops->get_et_sset_count) | ||
75 | return rdev_get_et_sset_count(rdev, dev, sset); | ||
76 | return -EOPNOTSUPP; | ||
77 | } | ||
78 | |||
79 | static void cfg80211_get_stats(struct net_device *dev, | ||
80 | struct ethtool_stats *stats, u64 *data) | ||
81 | { | ||
82 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
83 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); | ||
84 | if (rdev->ops->get_et_stats) | ||
85 | rdev_get_et_stats(rdev, dev, stats, data); | ||
86 | } | ||
87 | |||
88 | static void cfg80211_get_strings(struct net_device *dev, u32 sset, u8 *data) | ||
89 | { | ||
90 | struct wireless_dev *wdev = dev->ieee80211_ptr; | ||
91 | struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy); | ||
92 | if (rdev->ops->get_et_strings) | ||
93 | rdev_get_et_strings(rdev, dev, sset, data); | ||
94 | } | ||
95 | |||
96 | const struct ethtool_ops cfg80211_ethtool_ops = { | ||
97 | .get_drvinfo = cfg80211_get_drvinfo, | ||
98 | .get_regs_len = cfg80211_get_regs_len, | ||
99 | .get_regs = cfg80211_get_regs, | ||
100 | .get_link = ethtool_op_get_link, | ||
101 | .get_ringparam = cfg80211_get_ringparam, | ||
102 | .set_ringparam = cfg80211_set_ringparam, | ||
103 | .get_strings = cfg80211_get_strings, | ||
104 | .get_ethtool_stats = cfg80211_get_stats, | ||
105 | .get_sset_count = cfg80211_get_sset_count, | ||
106 | }; | ||
diff --git a/net/wireless/ethtool.h b/net/wireless/ethtool.h deleted file mode 100644 index 695ecad20bd6..000000000000 --- a/net/wireless/ethtool.h +++ /dev/null | |||
@@ -1,6 +0,0 @@ | |||
1 | #ifndef __CFG80211_ETHTOOL__ | ||
2 | #define __CFG80211_ETHTOOL__ | ||
3 | |||
4 | extern const struct ethtool_ops cfg80211_ethtool_ops; | ||
5 | |||
6 | #endif /* __CFG80211_ETHTOOL__ */ | ||
diff --git a/net/wireless/genregdb.awk b/net/wireless/genregdb.awk index 40c37fc5b67c..baf2426b555a 100644 --- a/net/wireless/genregdb.awk +++ b/net/wireless/genregdb.awk | |||
@@ -51,32 +51,41 @@ function parse_country_head() { | |||
51 | 51 | ||
52 | function parse_reg_rule() | 52 | function parse_reg_rule() |
53 | { | 53 | { |
54 | flag_starts_at = 7 | ||
55 | |||
54 | start = $1 | 56 | start = $1 |
55 | sub(/\(/, "", start) | 57 | sub(/\(/, "", start) |
56 | end = $3 | 58 | end = $3 |
57 | bw = $5 | 59 | bw = $5 |
58 | sub(/\),/, "", bw) | 60 | sub(/\),/, "", bw) |
59 | gain = $6 | 61 | gain = 0 |
60 | sub(/\(/, "", gain) | 62 | power = $6 |
61 | sub(/,/, "", gain) | ||
62 | power = $7 | ||
63 | sub(/\)/, "", power) | ||
64 | sub(/,/, "", power) | ||
65 | # power might be in mW... | 63 | # power might be in mW... |
66 | units = $8 | 64 | units = $7 |
65 | dfs_cac = 0 | ||
66 | |||
67 | sub(/\(/, "", power) | ||
68 | sub(/\),/, "", power) | ||
69 | sub(/\),/, "", units) | ||
67 | sub(/\)/, "", units) | 70 | sub(/\)/, "", units) |
68 | sub(/,/, "", units) | 71 | |
69 | dfs_cac = $9 | ||
70 | if (units == "mW") { | 72 | if (units == "mW") { |
73 | flag_starts_at = 8 | ||
71 | power = 10 * log(power)/log(10) | 74 | power = 10 * log(power)/log(10) |
75 | if ($8 ~ /[[:digit:]]/) { | ||
76 | flag_starts_at = 9 | ||
77 | dfs_cac = $8 | ||
78 | } | ||
72 | } else { | 79 | } else { |
73 | dfs_cac = $8 | 80 | if ($7 ~ /[[:digit:]]/) { |
81 | flag_starts_at = 8 | ||
82 | dfs_cac = $7 | ||
83 | } | ||
74 | } | 84 | } |
75 | sub(/,/, "", dfs_cac) | ||
76 | sub(/\(/, "", dfs_cac) | 85 | sub(/\(/, "", dfs_cac) |
77 | sub(/\)/, "", dfs_cac) | 86 | sub(/\),/, "", dfs_cac) |
78 | flagstr = "" | 87 | flagstr = "" |
79 | for (i=8; i<=NF; i++) | 88 | for (i=flag_starts_at; i<=NF; i++) |
80 | flagstr = flagstr $i | 89 | flagstr = flagstr $i |
81 | split(flagstr, flagarray, ",") | 90 | split(flagstr, flagarray, ",") |
82 | flags = "" | 91 | flags = "" |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 6668daf69326..7257164af91b 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -337,6 +337,7 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
337 | [NL80211_ATTR_TDLS_OPERATION] = { .type = NLA_U8 }, | 337 | [NL80211_ATTR_TDLS_OPERATION] = { .type = NLA_U8 }, |
338 | [NL80211_ATTR_TDLS_SUPPORT] = { .type = NLA_FLAG }, | 338 | [NL80211_ATTR_TDLS_SUPPORT] = { .type = NLA_FLAG }, |
339 | [NL80211_ATTR_TDLS_EXTERNAL_SETUP] = { .type = NLA_FLAG }, | 339 | [NL80211_ATTR_TDLS_EXTERNAL_SETUP] = { .type = NLA_FLAG }, |
340 | [NL80211_ATTR_TDLS_INITIATOR] = { .type = NLA_FLAG }, | ||
340 | [NL80211_ATTR_DONT_WAIT_FOR_ACK] = { .type = NLA_FLAG }, | 341 | [NL80211_ATTR_DONT_WAIT_FOR_ACK] = { .type = NLA_FLAG }, |
341 | [NL80211_ATTR_PROBE_RESP] = { .type = NLA_BINARY, | 342 | [NL80211_ATTR_PROBE_RESP] = { .type = NLA_BINARY, |
342 | .len = IEEE80211_MAX_DATA_LEN }, | 343 | .len = IEEE80211_MAX_DATA_LEN }, |
@@ -3813,7 +3814,8 @@ int cfg80211_check_station_change(struct wiphy *wiphy, | |||
3813 | { | 3814 | { |
3814 | if (params->listen_interval != -1) | 3815 | if (params->listen_interval != -1) |
3815 | return -EINVAL; | 3816 | return -EINVAL; |
3816 | if (params->aid) | 3817 | if (params->aid && |
3818 | !(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) | ||
3817 | return -EINVAL; | 3819 | return -EINVAL; |
3818 | 3820 | ||
3819 | /* When you run into this, adjust the code below for the new flag */ | 3821 | /* When you run into this, adjust the code below for the new flag */ |
@@ -6011,17 +6013,6 @@ skip_beacons: | |||
6011 | params.radar_required = true; | 6013 | params.radar_required = true; |
6012 | } | 6014 | } |
6013 | 6015 | ||
6014 | /* TODO: I left this here for now. With channel switch, the | ||
6015 | * verification is a bit more complicated, because we only do | ||
6016 | * it later when the channel switch really happens. | ||
6017 | */ | ||
6018 | err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, | ||
6019 | params.chandef.chan, | ||
6020 | CHAN_MODE_SHARED, | ||
6021 | radar_detect_width); | ||
6022 | if (err) | ||
6023 | return err; | ||
6024 | |||
6025 | if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX]) | 6016 | if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX]) |
6026 | params.block_tx = true; | 6017 | params.block_tx = true; |
6027 | 6018 | ||
@@ -6978,6 +6969,9 @@ void __cfg80211_send_event_skb(struct sk_buff *skb, gfp_t gfp) | |||
6978 | struct nlattr *data = ((void **)skb->cb)[2]; | 6969 | struct nlattr *data = ((void **)skb->cb)[2]; |
6979 | enum nl80211_multicast_groups mcgrp = NL80211_MCGRP_TESTMODE; | 6970 | enum nl80211_multicast_groups mcgrp = NL80211_MCGRP_TESTMODE; |
6980 | 6971 | ||
6972 | /* clear CB data for netlink core to own from now on */ | ||
6973 | memset(skb->cb, 0, sizeof(skb->cb)); | ||
6974 | |||
6981 | nla_nest_end(skb, data); | 6975 | nla_nest_end(skb, data); |
6982 | genlmsg_end(skb, hdr); | 6976 | genlmsg_end(skb, hdr); |
6983 | 6977 | ||
@@ -7364,6 +7358,7 @@ static int nl80211_tdls_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
7364 | u32 peer_capability = 0; | 7358 | u32 peer_capability = 0; |
7365 | u16 status_code; | 7359 | u16 status_code; |
7366 | u8 *peer; | 7360 | u8 *peer; |
7361 | bool initiator; | ||
7367 | 7362 | ||
7368 | if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) || | 7363 | if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) || |
7369 | !rdev->ops->tdls_mgmt) | 7364 | !rdev->ops->tdls_mgmt) |
@@ -7380,12 +7375,14 @@ static int nl80211_tdls_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
7380 | action_code = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_ACTION]); | 7375 | action_code = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_ACTION]); |
7381 | status_code = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]); | 7376 | status_code = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]); |
7382 | dialog_token = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN]); | 7377 | dialog_token = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN]); |
7378 | initiator = nla_get_flag(info->attrs[NL80211_ATTR_TDLS_INITIATOR]); | ||
7383 | if (info->attrs[NL80211_ATTR_TDLS_PEER_CAPABILITY]) | 7379 | if (info->attrs[NL80211_ATTR_TDLS_PEER_CAPABILITY]) |
7384 | peer_capability = | 7380 | peer_capability = |
7385 | nla_get_u32(info->attrs[NL80211_ATTR_TDLS_PEER_CAPABILITY]); | 7381 | nla_get_u32(info->attrs[NL80211_ATTR_TDLS_PEER_CAPABILITY]); |
7386 | 7382 | ||
7387 | return rdev_tdls_mgmt(rdev, dev, peer, action_code, | 7383 | return rdev_tdls_mgmt(rdev, dev, peer, action_code, |
7388 | dialog_token, status_code, peer_capability, | 7384 | dialog_token, status_code, peer_capability, |
7385 | initiator, | ||
7389 | nla_data(info->attrs[NL80211_ATTR_IE]), | 7386 | nla_data(info->attrs[NL80211_ATTR_IE]), |
7390 | nla_len(info->attrs[NL80211_ATTR_IE])); | 7387 | nla_len(info->attrs[NL80211_ATTR_IE])); |
7391 | } | 7388 | } |
@@ -9300,6 +9297,9 @@ int cfg80211_vendor_cmd_reply(struct sk_buff *skb) | |||
9300 | void *hdr = ((void **)skb->cb)[1]; | 9297 | void *hdr = ((void **)skb->cb)[1]; |
9301 | struct nlattr *data = ((void **)skb->cb)[2]; | 9298 | struct nlattr *data = ((void **)skb->cb)[2]; |
9302 | 9299 | ||
9300 | /* clear CB data for netlink core to own from now on */ | ||
9301 | memset(skb->cb, 0, sizeof(skb->cb)); | ||
9302 | |||
9303 | if (WARN_ON(!rdev->cur_cmd_info)) { | 9303 | if (WARN_ON(!rdev->cur_cmd_info)) { |
9304 | kfree_skb(skb); | 9304 | kfree_skb(skb); |
9305 | return -EINVAL; | 9305 | return -EINVAL; |
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h index d95bbe348138..56c2240c30ce 100644 --- a/net/wireless/rdev-ops.h +++ b/net/wireless/rdev-ops.h | |||
@@ -714,25 +714,6 @@ static inline int rdev_get_antenna(struct cfg80211_registered_device *rdev, | |||
714 | return ret; | 714 | return ret; |
715 | } | 715 | } |
716 | 716 | ||
717 | static inline int rdev_set_ringparam(struct cfg80211_registered_device *rdev, | ||
718 | u32 tx, u32 rx) | ||
719 | { | ||
720 | int ret; | ||
721 | trace_rdev_set_ringparam(&rdev->wiphy, tx, rx); | ||
722 | ret = rdev->ops->set_ringparam(&rdev->wiphy, tx, rx); | ||
723 | trace_rdev_return_int(&rdev->wiphy, ret); | ||
724 | return ret; | ||
725 | } | ||
726 | |||
727 | static inline void rdev_get_ringparam(struct cfg80211_registered_device *rdev, | ||
728 | u32 *tx, u32 *tx_max, u32 *rx, | ||
729 | u32 *rx_max) | ||
730 | { | ||
731 | trace_rdev_get_ringparam(&rdev->wiphy); | ||
732 | rdev->ops->get_ringparam(&rdev->wiphy, tx, tx_max, rx, rx_max); | ||
733 | trace_rdev_return_void_tx_rx(&rdev->wiphy, *tx, *tx_max, *rx, *rx_max); | ||
734 | } | ||
735 | |||
736 | static inline int | 717 | static inline int |
737 | rdev_sched_scan_start(struct cfg80211_registered_device *rdev, | 718 | rdev_sched_scan_start(struct cfg80211_registered_device *rdev, |
738 | struct net_device *dev, | 719 | struct net_device *dev, |
@@ -770,15 +751,15 @@ static inline int rdev_tdls_mgmt(struct cfg80211_registered_device *rdev, | |||
770 | struct net_device *dev, u8 *peer, | 751 | struct net_device *dev, u8 *peer, |
771 | u8 action_code, u8 dialog_token, | 752 | u8 action_code, u8 dialog_token, |
772 | u16 status_code, u32 peer_capability, | 753 | u16 status_code, u32 peer_capability, |
773 | const u8 *buf, size_t len) | 754 | bool initiator, const u8 *buf, size_t len) |
774 | { | 755 | { |
775 | int ret; | 756 | int ret; |
776 | trace_rdev_tdls_mgmt(&rdev->wiphy, dev, peer, action_code, | 757 | trace_rdev_tdls_mgmt(&rdev->wiphy, dev, peer, action_code, |
777 | dialog_token, status_code, peer_capability, | 758 | dialog_token, status_code, peer_capability, |
778 | buf, len); | 759 | initiator, buf, len); |
779 | ret = rdev->ops->tdls_mgmt(&rdev->wiphy, dev, peer, action_code, | 760 | ret = rdev->ops->tdls_mgmt(&rdev->wiphy, dev, peer, action_code, |
780 | dialog_token, status_code, peer_capability, | 761 | dialog_token, status_code, peer_capability, |
781 | buf, len); | 762 | initiator, buf, len); |
782 | trace_rdev_return_int(&rdev->wiphy, ret); | 763 | trace_rdev_return_int(&rdev->wiphy, ret); |
783 | return ret; | 764 | return ret; |
784 | } | 765 | } |
@@ -816,35 +797,6 @@ static inline int rdev_set_noack_map(struct cfg80211_registered_device *rdev, | |||
816 | } | 797 | } |
817 | 798 | ||
818 | static inline int | 799 | static inline int |
819 | rdev_get_et_sset_count(struct cfg80211_registered_device *rdev, | ||
820 | struct net_device *dev, int sset) | ||
821 | { | ||
822 | int ret; | ||
823 | trace_rdev_get_et_sset_count(&rdev->wiphy, dev, sset); | ||
824 | ret = rdev->ops->get_et_sset_count(&rdev->wiphy, dev, sset); | ||
825 | trace_rdev_return_int(&rdev->wiphy, ret); | ||
826 | return ret; | ||
827 | } | ||
828 | |||
829 | static inline void rdev_get_et_stats(struct cfg80211_registered_device *rdev, | ||
830 | struct net_device *dev, | ||
831 | struct ethtool_stats *stats, u64 *data) | ||
832 | { | ||
833 | trace_rdev_get_et_stats(&rdev->wiphy, dev); | ||
834 | rdev->ops->get_et_stats(&rdev->wiphy, dev, stats, data); | ||
835 | trace_rdev_return_void(&rdev->wiphy); | ||
836 | } | ||
837 | |||
838 | static inline void rdev_get_et_strings(struct cfg80211_registered_device *rdev, | ||
839 | struct net_device *dev, u32 sset, | ||
840 | u8 *data) | ||
841 | { | ||
842 | trace_rdev_get_et_strings(&rdev->wiphy, dev, sset); | ||
843 | rdev->ops->get_et_strings(&rdev->wiphy, dev, sset, data); | ||
844 | trace_rdev_return_void(&rdev->wiphy); | ||
845 | } | ||
846 | |||
847 | static inline int | ||
848 | rdev_get_channel(struct cfg80211_registered_device *rdev, | 800 | rdev_get_channel(struct cfg80211_registered_device *rdev, |
849 | struct wireless_dev *wdev, | 801 | struct wireless_dev *wdev, |
850 | struct cfg80211_chan_def *chandef) | 802 | struct cfg80211_chan_def *chandef) |
diff --git a/net/wireless/trace.h b/net/wireless/trace.h index 7cc887f9da11..0c524cd76c83 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h | |||
@@ -298,11 +298,6 @@ DEFINE_EVENT(wiphy_only_evt, rdev_return_void, | |||
298 | TP_ARGS(wiphy) | 298 | TP_ARGS(wiphy) |
299 | ); | 299 | ); |
300 | 300 | ||
301 | DEFINE_EVENT(wiphy_only_evt, rdev_get_ringparam, | ||
302 | TP_PROTO(struct wiphy *wiphy), | ||
303 | TP_ARGS(wiphy) | ||
304 | ); | ||
305 | |||
306 | DEFINE_EVENT(wiphy_only_evt, rdev_get_antenna, | 301 | DEFINE_EVENT(wiphy_only_evt, rdev_get_antenna, |
307 | TP_PROTO(struct wiphy *wiphy), | 302 | TP_PROTO(struct wiphy *wiphy), |
308 | TP_ARGS(wiphy) | 303 | TP_ARGS(wiphy) |
@@ -580,11 +575,6 @@ DEFINE_EVENT(wiphy_netdev_evt, rdev_stop_ap, | |||
580 | TP_ARGS(wiphy, netdev) | 575 | TP_ARGS(wiphy, netdev) |
581 | ); | 576 | ); |
582 | 577 | ||
583 | DEFINE_EVENT(wiphy_netdev_evt, rdev_get_et_stats, | ||
584 | TP_PROTO(struct wiphy *wiphy, struct net_device *netdev), | ||
585 | TP_ARGS(wiphy, netdev) | ||
586 | ); | ||
587 | |||
588 | DEFINE_EVENT(wiphy_netdev_evt, rdev_sched_scan_stop, | 578 | DEFINE_EVENT(wiphy_netdev_evt, rdev_sched_scan_stop, |
589 | TP_PROTO(struct wiphy *wiphy, struct net_device *netdev), | 579 | TP_PROTO(struct wiphy *wiphy, struct net_device *netdev), |
590 | TP_ARGS(wiphy, netdev) | 580 | TP_ARGS(wiphy, netdev) |
@@ -1439,11 +1429,6 @@ DECLARE_EVENT_CLASS(tx_rx_evt, | |||
1439 | WIPHY_PR_ARG, __entry->tx, __entry->rx) | 1429 | WIPHY_PR_ARG, __entry->tx, __entry->rx) |
1440 | ); | 1430 | ); |
1441 | 1431 | ||
1442 | DEFINE_EVENT(tx_rx_evt, rdev_set_ringparam, | ||
1443 | TP_PROTO(struct wiphy *wiphy, u32 tx, u32 rx), | ||
1444 | TP_ARGS(wiphy, rx, tx) | ||
1445 | ); | ||
1446 | |||
1447 | DEFINE_EVENT(tx_rx_evt, rdev_set_antenna, | 1432 | DEFINE_EVENT(tx_rx_evt, rdev_set_antenna, |
1448 | TP_PROTO(struct wiphy *wiphy, u32 tx, u32 rx), | 1433 | TP_PROTO(struct wiphy *wiphy, u32 tx, u32 rx), |
1449 | TP_ARGS(wiphy, rx, tx) | 1434 | TP_ARGS(wiphy, rx, tx) |
@@ -1469,9 +1454,9 @@ TRACE_EVENT(rdev_tdls_mgmt, | |||
1469 | TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, | 1454 | TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, |
1470 | u8 *peer, u8 action_code, u8 dialog_token, | 1455 | u8 *peer, u8 action_code, u8 dialog_token, |
1471 | u16 status_code, u32 peer_capability, | 1456 | u16 status_code, u32 peer_capability, |
1472 | const u8 *buf, size_t len), | 1457 | bool initiator, const u8 *buf, size_t len), |
1473 | TP_ARGS(wiphy, netdev, peer, action_code, dialog_token, status_code, | 1458 | TP_ARGS(wiphy, netdev, peer, action_code, dialog_token, status_code, |
1474 | peer_capability, buf, len), | 1459 | peer_capability, initiator, buf, len), |
1475 | TP_STRUCT__entry( | 1460 | TP_STRUCT__entry( |
1476 | WIPHY_ENTRY | 1461 | WIPHY_ENTRY |
1477 | NETDEV_ENTRY | 1462 | NETDEV_ENTRY |
@@ -1480,6 +1465,7 @@ TRACE_EVENT(rdev_tdls_mgmt, | |||
1480 | __field(u8, dialog_token) | 1465 | __field(u8, dialog_token) |
1481 | __field(u16, status_code) | 1466 | __field(u16, status_code) |
1482 | __field(u32, peer_capability) | 1467 | __field(u32, peer_capability) |
1468 | __field(bool, initiator) | ||
1483 | __dynamic_array(u8, buf, len) | 1469 | __dynamic_array(u8, buf, len) |
1484 | ), | 1470 | ), |
1485 | TP_fast_assign( | 1471 | TP_fast_assign( |
@@ -1490,13 +1476,16 @@ TRACE_EVENT(rdev_tdls_mgmt, | |||
1490 | __entry->dialog_token = dialog_token; | 1476 | __entry->dialog_token = dialog_token; |
1491 | __entry->status_code = status_code; | 1477 | __entry->status_code = status_code; |
1492 | __entry->peer_capability = peer_capability; | 1478 | __entry->peer_capability = peer_capability; |
1479 | __entry->initiator = initiator; | ||
1493 | memcpy(__get_dynamic_array(buf), buf, len); | 1480 | memcpy(__get_dynamic_array(buf), buf, len); |
1494 | ), | 1481 | ), |
1495 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT ", action_code: %u, " | 1482 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT ", action_code: %u, " |
1496 | "dialog_token: %u, status_code: %u, peer_capability: %u buf: %#.2x ", | 1483 | "dialog_token: %u, status_code: %u, peer_capability: %u " |
1484 | "initiator: %s buf: %#.2x ", | ||
1497 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer), | 1485 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer), |
1498 | __entry->action_code, __entry->dialog_token, | 1486 | __entry->action_code, __entry->dialog_token, |
1499 | __entry->status_code, __entry->peer_capability, | 1487 | __entry->status_code, __entry->peer_capability, |
1488 | BOOL_TO_STR(__entry->initiator), | ||
1500 | ((u8 *)__get_dynamic_array(buf))[0]) | 1489 | ((u8 *)__get_dynamic_array(buf))[0]) |
1501 | ); | 1490 | ); |
1502 | 1491 | ||
@@ -1725,40 +1714,6 @@ TRACE_EVENT(rdev_set_noack_map, | |||
1725 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->noack_map) | 1714 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->noack_map) |
1726 | ); | 1715 | ); |
1727 | 1716 | ||
1728 | TRACE_EVENT(rdev_get_et_sset_count, | ||
1729 | TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, int sset), | ||
1730 | TP_ARGS(wiphy, netdev, sset), | ||
1731 | TP_STRUCT__entry( | ||
1732 | WIPHY_ENTRY | ||
1733 | NETDEV_ENTRY | ||
1734 | __field(int, sset) | ||
1735 | ), | ||
1736 | TP_fast_assign( | ||
1737 | WIPHY_ASSIGN; | ||
1738 | NETDEV_ASSIGN; | ||
1739 | __entry->sset = sset; | ||
1740 | ), | ||
1741 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", sset: %d", | ||
1742 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->sset) | ||
1743 | ); | ||
1744 | |||
1745 | TRACE_EVENT(rdev_get_et_strings, | ||
1746 | TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, u32 sset), | ||
1747 | TP_ARGS(wiphy, netdev, sset), | ||
1748 | TP_STRUCT__entry( | ||
1749 | WIPHY_ENTRY | ||
1750 | NETDEV_ENTRY | ||
1751 | __field(u32, sset) | ||
1752 | ), | ||
1753 | TP_fast_assign( | ||
1754 | WIPHY_ASSIGN; | ||
1755 | NETDEV_ASSIGN; | ||
1756 | __entry->sset = sset; | ||
1757 | ), | ||
1758 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", sset: %u", | ||
1759 | WIPHY_PR_ARG, NETDEV_PR_ARG, __entry->sset) | ||
1760 | ); | ||
1761 | |||
1762 | DEFINE_EVENT(wiphy_wdev_evt, rdev_get_channel, | 1717 | DEFINE_EVENT(wiphy_wdev_evt, rdev_get_channel, |
1763 | TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev), | 1718 | TP_PROTO(struct wiphy *wiphy, struct wireless_dev *wdev), |
1764 | TP_ARGS(wiphy, wdev) | 1719 | TP_ARGS(wiphy, wdev) |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 0525d78ba328..fdde51f4271a 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -39,6 +39,11 @@ | |||
39 | #define XFRM_QUEUE_TMO_MAX ((unsigned)(60*HZ)) | 39 | #define XFRM_QUEUE_TMO_MAX ((unsigned)(60*HZ)) |
40 | #define XFRM_MAX_QUEUE_LEN 100 | 40 | #define XFRM_MAX_QUEUE_LEN 100 |
41 | 41 | ||
42 | struct xfrm_flo { | ||
43 | struct dst_entry *dst_orig; | ||
44 | u8 flags; | ||
45 | }; | ||
46 | |||
42 | static DEFINE_SPINLOCK(xfrm_policy_afinfo_lock); | 47 | static DEFINE_SPINLOCK(xfrm_policy_afinfo_lock); |
43 | static struct xfrm_policy_afinfo __rcu *xfrm_policy_afinfo[NPROTO] | 48 | static struct xfrm_policy_afinfo __rcu *xfrm_policy_afinfo[NPROTO] |
44 | __read_mostly; | 49 | __read_mostly; |
@@ -389,7 +394,7 @@ redo: | |||
389 | if (h != h0) | 394 | if (h != h0) |
390 | continue; | 395 | continue; |
391 | hlist_del(&pol->bydst); | 396 | hlist_del(&pol->bydst); |
392 | hlist_add_after(entry0, &pol->bydst); | 397 | hlist_add_behind(&pol->bydst, entry0); |
393 | } | 398 | } |
394 | entry0 = &pol->bydst; | 399 | entry0 = &pol->bydst; |
395 | } | 400 | } |
@@ -654,7 +659,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) | |||
654 | break; | 659 | break; |
655 | } | 660 | } |
656 | if (newpos) | 661 | if (newpos) |
657 | hlist_add_after(newpos, &policy->bydst); | 662 | hlist_add_behind(&policy->bydst, newpos); |
658 | else | 663 | else |
659 | hlist_add_head(&policy->bydst, chain); | 664 | hlist_add_head(&policy->bydst, chain); |
660 | xfrm_pol_hold(policy); | 665 | xfrm_pol_hold(policy); |
@@ -1877,13 +1882,14 @@ static int xdst_queue_output(struct sock *sk, struct sk_buff *skb) | |||
1877 | } | 1882 | } |
1878 | 1883 | ||
1879 | static struct xfrm_dst *xfrm_create_dummy_bundle(struct net *net, | 1884 | static struct xfrm_dst *xfrm_create_dummy_bundle(struct net *net, |
1880 | struct dst_entry *dst, | 1885 | struct xfrm_flo *xflo, |
1881 | const struct flowi *fl, | 1886 | const struct flowi *fl, |
1882 | int num_xfrms, | 1887 | int num_xfrms, |
1883 | u16 family) | 1888 | u16 family) |
1884 | { | 1889 | { |
1885 | int err; | 1890 | int err; |
1886 | struct net_device *dev; | 1891 | struct net_device *dev; |
1892 | struct dst_entry *dst; | ||
1887 | struct dst_entry *dst1; | 1893 | struct dst_entry *dst1; |
1888 | struct xfrm_dst *xdst; | 1894 | struct xfrm_dst *xdst; |
1889 | 1895 | ||
@@ -1891,9 +1897,12 @@ static struct xfrm_dst *xfrm_create_dummy_bundle(struct net *net, | |||
1891 | if (IS_ERR(xdst)) | 1897 | if (IS_ERR(xdst)) |
1892 | return xdst; | 1898 | return xdst; |
1893 | 1899 | ||
1894 | if (net->xfrm.sysctl_larval_drop || num_xfrms <= 0) | 1900 | if (!(xflo->flags & XFRM_LOOKUP_QUEUE) || |
1901 | net->xfrm.sysctl_larval_drop || | ||
1902 | num_xfrms <= 0) | ||
1895 | return xdst; | 1903 | return xdst; |
1896 | 1904 | ||
1905 | dst = xflo->dst_orig; | ||
1897 | dst1 = &xdst->u.dst; | 1906 | dst1 = &xdst->u.dst; |
1898 | dst_hold(dst); | 1907 | dst_hold(dst); |
1899 | xdst->route = dst; | 1908 | xdst->route = dst; |
@@ -1935,7 +1944,7 @@ static struct flow_cache_object * | |||
1935 | xfrm_bundle_lookup(struct net *net, const struct flowi *fl, u16 family, u8 dir, | 1944 | xfrm_bundle_lookup(struct net *net, const struct flowi *fl, u16 family, u8 dir, |
1936 | struct flow_cache_object *oldflo, void *ctx) | 1945 | struct flow_cache_object *oldflo, void *ctx) |
1937 | { | 1946 | { |
1938 | struct dst_entry *dst_orig = (struct dst_entry *)ctx; | 1947 | struct xfrm_flo *xflo = (struct xfrm_flo *)ctx; |
1939 | struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX]; | 1948 | struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX]; |
1940 | struct xfrm_dst *xdst, *new_xdst; | 1949 | struct xfrm_dst *xdst, *new_xdst; |
1941 | int num_pols = 0, num_xfrms = 0, i, err, pol_dead; | 1950 | int num_pols = 0, num_xfrms = 0, i, err, pol_dead; |
@@ -1976,7 +1985,8 @@ xfrm_bundle_lookup(struct net *net, const struct flowi *fl, u16 family, u8 dir, | |||
1976 | goto make_dummy_bundle; | 1985 | goto make_dummy_bundle; |
1977 | } | 1986 | } |
1978 | 1987 | ||
1979 | new_xdst = xfrm_resolve_and_create_bundle(pols, num_pols, fl, family, dst_orig); | 1988 | new_xdst = xfrm_resolve_and_create_bundle(pols, num_pols, fl, family, |
1989 | xflo->dst_orig); | ||
1980 | if (IS_ERR(new_xdst)) { | 1990 | if (IS_ERR(new_xdst)) { |
1981 | err = PTR_ERR(new_xdst); | 1991 | err = PTR_ERR(new_xdst); |
1982 | if (err != -EAGAIN) | 1992 | if (err != -EAGAIN) |
@@ -2010,7 +2020,7 @@ make_dummy_bundle: | |||
2010 | /* We found policies, but there's no bundles to instantiate: | 2020 | /* We found policies, but there's no bundles to instantiate: |
2011 | * either because the policy blocks, has no transformations or | 2021 | * either because the policy blocks, has no transformations or |
2012 | * we could not build template (no xfrm_states).*/ | 2022 | * we could not build template (no xfrm_states).*/ |
2013 | xdst = xfrm_create_dummy_bundle(net, dst_orig, fl, num_xfrms, family); | 2023 | xdst = xfrm_create_dummy_bundle(net, xflo, fl, num_xfrms, family); |
2014 | if (IS_ERR(xdst)) { | 2024 | if (IS_ERR(xdst)) { |
2015 | xfrm_pols_put(pols, num_pols); | 2025 | xfrm_pols_put(pols, num_pols); |
2016 | return ERR_CAST(xdst); | 2026 | return ERR_CAST(xdst); |
@@ -2104,13 +2114,18 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, | |||
2104 | } | 2114 | } |
2105 | 2115 | ||
2106 | if (xdst == NULL) { | 2116 | if (xdst == NULL) { |
2117 | struct xfrm_flo xflo; | ||
2118 | |||
2119 | xflo.dst_orig = dst_orig; | ||
2120 | xflo.flags = flags; | ||
2121 | |||
2107 | /* To accelerate a bit... */ | 2122 | /* To accelerate a bit... */ |
2108 | if ((dst_orig->flags & DST_NOXFRM) || | 2123 | if ((dst_orig->flags & DST_NOXFRM) || |
2109 | !net->xfrm.policy_count[XFRM_POLICY_OUT]) | 2124 | !net->xfrm.policy_count[XFRM_POLICY_OUT]) |
2110 | goto nopol; | 2125 | goto nopol; |
2111 | 2126 | ||
2112 | flo = flow_cache_lookup(net, fl, family, dir, | 2127 | flo = flow_cache_lookup(net, fl, family, dir, |
2113 | xfrm_bundle_lookup, dst_orig); | 2128 | xfrm_bundle_lookup, &xflo); |
2114 | if (flo == NULL) | 2129 | if (flo == NULL) |
2115 | goto nopol; | 2130 | goto nopol; |
2116 | if (IS_ERR(flo)) { | 2131 | if (IS_ERR(flo)) { |
@@ -2138,7 +2153,7 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, | |||
2138 | xfrm_pols_put(pols, drop_pols); | 2153 | xfrm_pols_put(pols, drop_pols); |
2139 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES); | 2154 | XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES); |
2140 | 2155 | ||
2141 | return make_blackhole(net, family, dst_orig); | 2156 | return ERR_PTR(-EREMOTE); |
2142 | } | 2157 | } |
2143 | 2158 | ||
2144 | err = -EAGAIN; | 2159 | err = -EAGAIN; |
@@ -2195,6 +2210,23 @@ dropdst: | |||
2195 | } | 2210 | } |
2196 | EXPORT_SYMBOL(xfrm_lookup); | 2211 | EXPORT_SYMBOL(xfrm_lookup); |
2197 | 2212 | ||
2213 | /* Callers of xfrm_lookup_route() must ensure a call to dst_output(). | ||
2214 | * Otherwise we may send out blackholed packets. | ||
2215 | */ | ||
2216 | struct dst_entry *xfrm_lookup_route(struct net *net, struct dst_entry *dst_orig, | ||
2217 | const struct flowi *fl, | ||
2218 | struct sock *sk, int flags) | ||
2219 | { | ||
2220 | struct dst_entry *dst = xfrm_lookup(net, dst_orig, fl, sk, | ||
2221 | flags | XFRM_LOOKUP_QUEUE); | ||
2222 | |||
2223 | if (IS_ERR(dst) && PTR_ERR(dst) == -EREMOTE) | ||
2224 | return make_blackhole(net, dst_orig->ops->family, dst_orig); | ||
2225 | |||
2226 | return dst; | ||
2227 | } | ||
2228 | EXPORT_SYMBOL(xfrm_lookup_route); | ||
2229 | |||
2198 | static inline int | 2230 | static inline int |
2199 | xfrm_secpath_reject(int idx, struct sk_buff *skb, const struct flowi *fl) | 2231 | xfrm_secpath_reject(int idx, struct sk_buff *skb, const struct flowi *fl) |
2200 | { | 2232 | { |
@@ -2460,7 +2492,7 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family) | |||
2460 | 2492 | ||
2461 | skb_dst_force(skb); | 2493 | skb_dst_force(skb); |
2462 | 2494 | ||
2463 | dst = xfrm_lookup(net, skb_dst(skb), &fl, NULL, 0); | 2495 | dst = xfrm_lookup(net, skb_dst(skb), &fl, NULL, XFRM_LOOKUP_QUEUE); |
2464 | if (IS_ERR(dst)) { | 2496 | if (IS_ERR(dst)) { |
2465 | res = 0; | 2497 | res = 0; |
2466 | dst = NULL; | 2498 | dst = NULL; |