diff options
Diffstat (limited to 'net')
36 files changed, 647 insertions, 311 deletions
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index f10b41fb05a0..5868597534e5 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c | |||
@@ -648,6 +648,7 @@ int bnep_del_connection(struct bnep_conndel_req *req) | |||
648 | 648 | ||
649 | static void __bnep_copy_ci(struct bnep_conninfo *ci, struct bnep_session *s) | 649 | static void __bnep_copy_ci(struct bnep_conninfo *ci, struct bnep_session *s) |
650 | { | 650 | { |
651 | memset(ci, 0, sizeof(*ci)); | ||
651 | memcpy(ci->dst, s->eh.h_source, ETH_ALEN); | 652 | memcpy(ci->dst, s->eh.h_source, ETH_ALEN); |
652 | strcpy(ci->device, s->dev->name); | 653 | strcpy(ci->device, s->dev->name); |
653 | ci->flags = s->flags; | 654 | ci->flags = s->flags; |
diff --git a/net/bluetooth/cmtp/core.c b/net/bluetooth/cmtp/core.c index ec0a1347f933..8e5f292529ac 100644 --- a/net/bluetooth/cmtp/core.c +++ b/net/bluetooth/cmtp/core.c | |||
@@ -78,6 +78,7 @@ static void __cmtp_unlink_session(struct cmtp_session *session) | |||
78 | 78 | ||
79 | static void __cmtp_copy_session(struct cmtp_session *session, struct cmtp_conninfo *ci) | 79 | static void __cmtp_copy_session(struct cmtp_session *session, struct cmtp_conninfo *ci) |
80 | { | 80 | { |
81 | memset(ci, 0, sizeof(*ci)); | ||
81 | bacpy(&ci->bdaddr, &session->bdaddr); | 82 | bacpy(&ci->bdaddr, &session->bdaddr); |
82 | 83 | ||
83 | ci->flags = session->flags; | 84 | ci->flags = session->flags; |
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 0b1e460fe440..6b90a4191734 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
@@ -39,7 +39,7 @@ | |||
39 | #include <net/sock.h> | 39 | #include <net/sock.h> |
40 | 40 | ||
41 | #include <asm/system.h> | 41 | #include <asm/system.h> |
42 | #include <asm/uaccess.h> | 42 | #include <linux/uaccess.h> |
43 | #include <asm/unaligned.h> | 43 | #include <asm/unaligned.h> |
44 | 44 | ||
45 | #include <net/bluetooth/bluetooth.h> | 45 | #include <net/bluetooth/bluetooth.h> |
@@ -66,7 +66,8 @@ void hci_acl_connect(struct hci_conn *conn) | |||
66 | bacpy(&cp.bdaddr, &conn->dst); | 66 | bacpy(&cp.bdaddr, &conn->dst); |
67 | cp.pscan_rep_mode = 0x02; | 67 | cp.pscan_rep_mode = 0x02; |
68 | 68 | ||
69 | if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst))) { | 69 | ie = hci_inquiry_cache_lookup(hdev, &conn->dst); |
70 | if (ie) { | ||
70 | if (inquiry_entry_age(ie) <= INQUIRY_ENTRY_AGE_MAX) { | 71 | if (inquiry_entry_age(ie) <= INQUIRY_ENTRY_AGE_MAX) { |
71 | cp.pscan_rep_mode = ie->data.pscan_rep_mode; | 72 | cp.pscan_rep_mode = ie->data.pscan_rep_mode; |
72 | cp.pscan_mode = ie->data.pscan_mode; | 73 | cp.pscan_mode = ie->data.pscan_mode; |
@@ -368,8 +369,10 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 | |||
368 | 369 | ||
369 | BT_DBG("%s dst %s", hdev->name, batostr(dst)); | 370 | BT_DBG("%s dst %s", hdev->name, batostr(dst)); |
370 | 371 | ||
371 | if (!(acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst))) { | 372 | acl = hci_conn_hash_lookup_ba(hdev, ACL_LINK, dst); |
372 | if (!(acl = hci_conn_add(hdev, ACL_LINK, dst))) | 373 | if (!acl) { |
374 | acl = hci_conn_add(hdev, ACL_LINK, dst); | ||
375 | if (!acl) | ||
373 | return NULL; | 376 | return NULL; |
374 | } | 377 | } |
375 | 378 | ||
@@ -389,8 +392,10 @@ struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, __u8 | |||
389 | if (type == ACL_LINK) | 392 | if (type == ACL_LINK) |
390 | return acl; | 393 | return acl; |
391 | 394 | ||
392 | if (!(sco = hci_conn_hash_lookup_ba(hdev, type, dst))) { | 395 | sco = hci_conn_hash_lookup_ba(hdev, type, dst); |
393 | if (!(sco = hci_conn_add(hdev, type, dst))) { | 396 | if (!sco) { |
397 | sco = hci_conn_add(hdev, type, dst); | ||
398 | if (!sco) { | ||
394 | hci_conn_put(acl); | 399 | hci_conn_put(acl); |
395 | return NULL; | 400 | return NULL; |
396 | } | 401 | } |
@@ -647,10 +652,12 @@ int hci_get_conn_list(void __user *arg) | |||
647 | 652 | ||
648 | size = sizeof(req) + req.conn_num * sizeof(*ci); | 653 | size = sizeof(req) + req.conn_num * sizeof(*ci); |
649 | 654 | ||
650 | if (!(cl = kmalloc(size, GFP_KERNEL))) | 655 | cl = kmalloc(size, GFP_KERNEL); |
656 | if (!cl) | ||
651 | return -ENOMEM; | 657 | return -ENOMEM; |
652 | 658 | ||
653 | if (!(hdev = hci_dev_get(req.dev_id))) { | 659 | hdev = hci_dev_get(req.dev_id); |
660 | if (!hdev) { | ||
654 | kfree(cl); | 661 | kfree(cl); |
655 | return -ENODEV; | 662 | return -ENODEV; |
656 | } | 663 | } |
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index bc2a052e518b..51c61f75a797 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
@@ -44,7 +44,7 @@ | |||
44 | #include <net/sock.h> | 44 | #include <net/sock.h> |
45 | 45 | ||
46 | #include <asm/system.h> | 46 | #include <asm/system.h> |
47 | #include <asm/uaccess.h> | 47 | #include <linux/uaccess.h> |
48 | #include <asm/unaligned.h> | 48 | #include <asm/unaligned.h> |
49 | 49 | ||
50 | #include <net/bluetooth/bluetooth.h> | 50 | #include <net/bluetooth/bluetooth.h> |
@@ -349,20 +349,23 @@ struct inquiry_entry *hci_inquiry_cache_lookup(struct hci_dev *hdev, bdaddr_t *b | |||
349 | void hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data) | 349 | void hci_inquiry_cache_update(struct hci_dev *hdev, struct inquiry_data *data) |
350 | { | 350 | { |
351 | struct inquiry_cache *cache = &hdev->inq_cache; | 351 | struct inquiry_cache *cache = &hdev->inq_cache; |
352 | struct inquiry_entry *e; | 352 | struct inquiry_entry *ie; |
353 | 353 | ||
354 | BT_DBG("cache %p, %s", cache, batostr(&data->bdaddr)); | 354 | BT_DBG("cache %p, %s", cache, batostr(&data->bdaddr)); |
355 | 355 | ||
356 | if (!(e = hci_inquiry_cache_lookup(hdev, &data->bdaddr))) { | 356 | ie = hci_inquiry_cache_lookup(hdev, &data->bdaddr); |
357 | if (!ie) { | ||
357 | /* Entry not in the cache. Add new one. */ | 358 | /* Entry not in the cache. Add new one. */ |
358 | if (!(e = kzalloc(sizeof(struct inquiry_entry), GFP_ATOMIC))) | 359 | ie = kzalloc(sizeof(struct inquiry_entry), GFP_ATOMIC); |
360 | if (!ie) | ||
359 | return; | 361 | return; |
360 | e->next = cache->list; | 362 | |
361 | cache->list = e; | 363 | ie->next = cache->list; |
364 | cache->list = ie; | ||
362 | } | 365 | } |
363 | 366 | ||
364 | memcpy(&e->data, data, sizeof(*data)); | 367 | memcpy(&ie->data, data, sizeof(*data)); |
365 | e->timestamp = jiffies; | 368 | ie->timestamp = jiffies; |
366 | cache->timestamp = jiffies; | 369 | cache->timestamp = jiffies; |
367 | } | 370 | } |
368 | 371 | ||
@@ -422,16 +425,20 @@ int hci_inquiry(void __user *arg) | |||
422 | 425 | ||
423 | hci_dev_lock_bh(hdev); | 426 | hci_dev_lock_bh(hdev); |
424 | if (inquiry_cache_age(hdev) > INQUIRY_CACHE_AGE_MAX || | 427 | if (inquiry_cache_age(hdev) > INQUIRY_CACHE_AGE_MAX || |
425 | inquiry_cache_empty(hdev) || | 428 | inquiry_cache_empty(hdev) || |
426 | ir.flags & IREQ_CACHE_FLUSH) { | 429 | ir.flags & IREQ_CACHE_FLUSH) { |
427 | inquiry_cache_flush(hdev); | 430 | inquiry_cache_flush(hdev); |
428 | do_inquiry = 1; | 431 | do_inquiry = 1; |
429 | } | 432 | } |
430 | hci_dev_unlock_bh(hdev); | 433 | hci_dev_unlock_bh(hdev); |
431 | 434 | ||
432 | timeo = ir.length * msecs_to_jiffies(2000); | 435 | timeo = ir.length * msecs_to_jiffies(2000); |
433 | if (do_inquiry && (err = hci_request(hdev, hci_inq_req, (unsigned long)&ir, timeo)) < 0) | 436 | |
434 | goto done; | 437 | if (do_inquiry) { |
438 | err = hci_request(hdev, hci_inq_req, (unsigned long)&ir, timeo); | ||
439 | if (err < 0) | ||
440 | goto done; | ||
441 | } | ||
435 | 442 | ||
436 | /* for unlimited number of responses we will use buffer with 255 entries */ | 443 | /* for unlimited number of responses we will use buffer with 255 entries */ |
437 | max_rsp = (ir.num_rsp == 0) ? 255 : ir.num_rsp; | 444 | max_rsp = (ir.num_rsp == 0) ? 255 : ir.num_rsp; |
@@ -439,7 +446,8 @@ int hci_inquiry(void __user *arg) | |||
439 | /* cache_dump can't sleep. Therefore we allocate temp buffer and then | 446 | /* cache_dump can't sleep. Therefore we allocate temp buffer and then |
440 | * copy it to the user space. | 447 | * copy it to the user space. |
441 | */ | 448 | */ |
442 | if (!(buf = kmalloc(sizeof(struct inquiry_info) * max_rsp, GFP_KERNEL))) { | 449 | buf = kmalloc(sizeof(struct inquiry_info) *max_rsp, GFP_KERNEL); |
450 | if (!buf) { | ||
443 | err = -ENOMEM; | 451 | err = -ENOMEM; |
444 | goto done; | 452 | goto done; |
445 | } | 453 | } |
@@ -611,7 +619,8 @@ int hci_dev_close(__u16 dev) | |||
611 | struct hci_dev *hdev; | 619 | struct hci_dev *hdev; |
612 | int err; | 620 | int err; |
613 | 621 | ||
614 | if (!(hdev = hci_dev_get(dev))) | 622 | hdev = hci_dev_get(dev); |
623 | if (!hdev) | ||
615 | return -ENODEV; | 624 | return -ENODEV; |
616 | err = hci_dev_do_close(hdev); | 625 | err = hci_dev_do_close(hdev); |
617 | hci_dev_put(hdev); | 626 | hci_dev_put(hdev); |
@@ -623,7 +632,8 @@ int hci_dev_reset(__u16 dev) | |||
623 | struct hci_dev *hdev; | 632 | struct hci_dev *hdev; |
624 | int ret = 0; | 633 | int ret = 0; |
625 | 634 | ||
626 | if (!(hdev = hci_dev_get(dev))) | 635 | hdev = hci_dev_get(dev); |
636 | if (!hdev) | ||
627 | return -ENODEV; | 637 | return -ENODEV; |
628 | 638 | ||
629 | hci_req_lock(hdev); | 639 | hci_req_lock(hdev); |
@@ -663,7 +673,8 @@ int hci_dev_reset_stat(__u16 dev) | |||
663 | struct hci_dev *hdev; | 673 | struct hci_dev *hdev; |
664 | int ret = 0; | 674 | int ret = 0; |
665 | 675 | ||
666 | if (!(hdev = hci_dev_get(dev))) | 676 | hdev = hci_dev_get(dev); |
677 | if (!hdev) | ||
667 | return -ENODEV; | 678 | return -ENODEV; |
668 | 679 | ||
669 | memset(&hdev->stat, 0, sizeof(struct hci_dev_stats)); | 680 | memset(&hdev->stat, 0, sizeof(struct hci_dev_stats)); |
@@ -682,7 +693,8 @@ int hci_dev_cmd(unsigned int cmd, void __user *arg) | |||
682 | if (copy_from_user(&dr, arg, sizeof(dr))) | 693 | if (copy_from_user(&dr, arg, sizeof(dr))) |
683 | return -EFAULT; | 694 | return -EFAULT; |
684 | 695 | ||
685 | if (!(hdev = hci_dev_get(dr.dev_id))) | 696 | hdev = hci_dev_get(dr.dev_id); |
697 | if (!hdev) | ||
686 | return -ENODEV; | 698 | return -ENODEV; |
687 | 699 | ||
688 | switch (cmd) { | 700 | switch (cmd) { |
@@ -763,7 +775,8 @@ int hci_get_dev_list(void __user *arg) | |||
763 | 775 | ||
764 | size = sizeof(*dl) + dev_num * sizeof(*dr); | 776 | size = sizeof(*dl) + dev_num * sizeof(*dr); |
765 | 777 | ||
766 | if (!(dl = kzalloc(size, GFP_KERNEL))) | 778 | dl = kzalloc(size, GFP_KERNEL); |
779 | if (!dl) | ||
767 | return -ENOMEM; | 780 | return -ENOMEM; |
768 | 781 | ||
769 | dr = dl->dev_req; | 782 | dr = dl->dev_req; |
@@ -797,7 +810,8 @@ int hci_get_dev_info(void __user *arg) | |||
797 | if (copy_from_user(&di, arg, sizeof(di))) | 810 | if (copy_from_user(&di, arg, sizeof(di))) |
798 | return -EFAULT; | 811 | return -EFAULT; |
799 | 812 | ||
800 | if (!(hdev = hci_dev_get(di.dev_id))) | 813 | hdev = hci_dev_get(di.dev_id); |
814 | if (!hdev) | ||
801 | return -ENODEV; | 815 | return -ENODEV; |
802 | 816 | ||
803 | strcpy(di.name, hdev->name); | 817 | strcpy(di.name, hdev->name); |
@@ -905,7 +919,7 @@ int hci_register_dev(struct hci_dev *hdev) | |||
905 | hdev->sniff_max_interval = 800; | 919 | hdev->sniff_max_interval = 800; |
906 | hdev->sniff_min_interval = 80; | 920 | hdev->sniff_min_interval = 80; |
907 | 921 | ||
908 | tasklet_init(&hdev->cmd_task, hci_cmd_task,(unsigned long) hdev); | 922 | tasklet_init(&hdev->cmd_task, hci_cmd_task, (unsigned long) hdev); |
909 | tasklet_init(&hdev->rx_task, hci_rx_task, (unsigned long) hdev); | 923 | tasklet_init(&hdev->rx_task, hci_rx_task, (unsigned long) hdev); |
910 | tasklet_init(&hdev->tx_task, hci_tx_task, (unsigned long) hdev); | 924 | tasklet_init(&hdev->tx_task, hci_tx_task, (unsigned long) hdev); |
911 | 925 | ||
@@ -1368,7 +1382,8 @@ void hci_send_acl(struct hci_conn *conn, struct sk_buff *skb, __u16 flags) | |||
1368 | bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT; | 1382 | bt_cb(skb)->pkt_type = HCI_ACLDATA_PKT; |
1369 | hci_add_acl_hdr(skb, conn->handle, flags | ACL_START); | 1383 | hci_add_acl_hdr(skb, conn->handle, flags | ACL_START); |
1370 | 1384 | ||
1371 | if (!(list = skb_shinfo(skb)->frag_list)) { | 1385 | list = skb_shinfo(skb)->frag_list; |
1386 | if (!list) { | ||
1372 | /* Non fragmented */ | 1387 | /* Non fragmented */ |
1373 | BT_DBG("%s nonfrag skb %p len %d", hdev->name, skb, skb->len); | 1388 | BT_DBG("%s nonfrag skb %p len %d", hdev->name, skb, skb->len); |
1374 | 1389 | ||
@@ -1609,7 +1624,8 @@ static inline void hci_acldata_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
1609 | hci_conn_enter_active_mode(conn); | 1624 | hci_conn_enter_active_mode(conn); |
1610 | 1625 | ||
1611 | /* Send to upper protocol */ | 1626 | /* Send to upper protocol */ |
1612 | if ((hp = hci_proto[HCI_PROTO_L2CAP]) && hp->recv_acldata) { | 1627 | hp = hci_proto[HCI_PROTO_L2CAP]; |
1628 | if (hp && hp->recv_acldata) { | ||
1613 | hp->recv_acldata(conn, skb, flags); | 1629 | hp->recv_acldata(conn, skb, flags); |
1614 | return; | 1630 | return; |
1615 | } | 1631 | } |
@@ -1644,7 +1660,8 @@ static inline void hci_scodata_packet(struct hci_dev *hdev, struct sk_buff *skb) | |||
1644 | register struct hci_proto *hp; | 1660 | register struct hci_proto *hp; |
1645 | 1661 | ||
1646 | /* Send to upper protocol */ | 1662 | /* Send to upper protocol */ |
1647 | if ((hp = hci_proto[HCI_PROTO_SCO]) && hp->recv_scodata) { | 1663 | hp = hci_proto[HCI_PROTO_SCO]; |
1664 | if (hp && hp->recv_scodata) { | ||
1648 | hp->recv_scodata(conn, skb); | 1665 | hp->recv_scodata(conn, skb); |
1649 | return; | 1666 | return; |
1650 | } | 1667 | } |
@@ -1727,7 +1744,8 @@ static void hci_cmd_task(unsigned long arg) | |||
1727 | if (atomic_read(&hdev->cmd_cnt) && (skb = skb_dequeue(&hdev->cmd_q))) { | 1744 | if (atomic_read(&hdev->cmd_cnt) && (skb = skb_dequeue(&hdev->cmd_q))) { |
1728 | kfree_skb(hdev->sent_cmd); | 1745 | kfree_skb(hdev->sent_cmd); |
1729 | 1746 | ||
1730 | if ((hdev->sent_cmd = skb_clone(skb, GFP_ATOMIC))) { | 1747 | hdev->sent_cmd = skb_clone(skb, GFP_ATOMIC); |
1748 | if (hdev->sent_cmd) { | ||
1731 | atomic_dec(&hdev->cmd_cnt); | 1749 | atomic_dec(&hdev->cmd_cnt); |
1732 | hci_send_frame(skb); | 1750 | hci_send_frame(skb); |
1733 | hdev->cmd_last_tx = jiffies; | 1751 | hdev->cmd_last_tx = jiffies; |
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 84093b0000b9..8923b36a67a2 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
@@ -39,7 +39,7 @@ | |||
39 | #include <net/sock.h> | 39 | #include <net/sock.h> |
40 | 40 | ||
41 | #include <asm/system.h> | 41 | #include <asm/system.h> |
42 | #include <asm/uaccess.h> | 42 | #include <linux/uaccess.h> |
43 | #include <asm/unaligned.h> | 43 | #include <asm/unaligned.h> |
44 | 44 | ||
45 | #include <net/bluetooth/bluetooth.h> | 45 | #include <net/bluetooth/bluetooth.h> |
@@ -677,9 +677,50 @@ static void hci_cs_set_conn_encrypt(struct hci_dev *hdev, __u8 status) | |||
677 | hci_dev_unlock(hdev); | 677 | hci_dev_unlock(hdev); |
678 | } | 678 | } |
679 | 679 | ||
680 | static int hci_outgoing_auth_needed(struct hci_dev *hdev, | ||
681 | struct hci_conn *conn) | ||
682 | { | ||
683 | if (conn->state != BT_CONFIG || !conn->out) | ||
684 | return 0; | ||
685 | |||
686 | if (conn->sec_level == BT_SECURITY_SDP) | ||
687 | return 0; | ||
688 | |||
689 | /* Only request authentication for SSP connections or non-SSP | ||
690 | * devices with sec_level HIGH */ | ||
691 | if (!(hdev->ssp_mode > 0 && conn->ssp_mode > 0) && | ||
692 | conn->sec_level != BT_SECURITY_HIGH) | ||
693 | return 0; | ||
694 | |||
695 | return 1; | ||
696 | } | ||
697 | |||
680 | static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) | 698 | static void hci_cs_remote_name_req(struct hci_dev *hdev, __u8 status) |
681 | { | 699 | { |
700 | struct hci_cp_remote_name_req *cp; | ||
701 | struct hci_conn *conn; | ||
702 | |||
682 | BT_DBG("%s status 0x%x", hdev->name, status); | 703 | BT_DBG("%s status 0x%x", hdev->name, status); |
704 | |||
705 | /* If successful wait for the name req complete event before | ||
706 | * checking for the need to do authentication */ | ||
707 | if (!status) | ||
708 | return; | ||
709 | |||
710 | cp = hci_sent_cmd_data(hdev, HCI_OP_REMOTE_NAME_REQ); | ||
711 | if (!cp) | ||
712 | return; | ||
713 | |||
714 | hci_dev_lock(hdev); | ||
715 | |||
716 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &cp->bdaddr); | ||
717 | if (conn && hci_outgoing_auth_needed(hdev, conn)) { | ||
718 | struct hci_cp_auth_requested cp; | ||
719 | cp.handle = __cpu_to_le16(conn->handle); | ||
720 | hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); | ||
721 | } | ||
722 | |||
723 | hci_dev_unlock(hdev); | ||
683 | } | 724 | } |
684 | 725 | ||
685 | static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) | 726 | static void hci_cs_read_remote_features(struct hci_dev *hdev, __u8 status) |
@@ -955,12 +996,14 @@ static inline void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *sk | |||
955 | 996 | ||
956 | hci_dev_lock(hdev); | 997 | hci_dev_lock(hdev); |
957 | 998 | ||
958 | if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr))) | 999 | ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); |
1000 | if (ie) | ||
959 | memcpy(ie->data.dev_class, ev->dev_class, 3); | 1001 | memcpy(ie->data.dev_class, ev->dev_class, 3); |
960 | 1002 | ||
961 | conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); | 1003 | conn = hci_conn_hash_lookup_ba(hdev, ev->link_type, &ev->bdaddr); |
962 | if (!conn) { | 1004 | if (!conn) { |
963 | if (!(conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr))) { | 1005 | conn = hci_conn_add(hdev, ev->link_type, &ev->bdaddr); |
1006 | if (!conn) { | ||
964 | BT_ERR("No memory for new connection"); | 1007 | BT_ERR("No memory for new connection"); |
965 | hci_dev_unlock(hdev); | 1008 | hci_dev_unlock(hdev); |
966 | return; | 1009 | return; |
@@ -1090,9 +1133,23 @@ static inline void hci_auth_complete_evt(struct hci_dev *hdev, struct sk_buff *s | |||
1090 | 1133 | ||
1091 | static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1134 | static inline void hci_remote_name_evt(struct hci_dev *hdev, struct sk_buff *skb) |
1092 | { | 1135 | { |
1136 | struct hci_ev_remote_name *ev = (void *) skb->data; | ||
1137 | struct hci_conn *conn; | ||
1138 | |||
1093 | BT_DBG("%s", hdev->name); | 1139 | BT_DBG("%s", hdev->name); |
1094 | 1140 | ||
1095 | hci_conn_check_pending(hdev); | 1141 | hci_conn_check_pending(hdev); |
1142 | |||
1143 | hci_dev_lock(hdev); | ||
1144 | |||
1145 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); | ||
1146 | if (conn && hci_outgoing_auth_needed(hdev, conn)) { | ||
1147 | struct hci_cp_auth_requested cp; | ||
1148 | cp.handle = __cpu_to_le16(conn->handle); | ||
1149 | hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, sizeof(cp), &cp); | ||
1150 | } | ||
1151 | |||
1152 | hci_dev_unlock(hdev); | ||
1096 | } | 1153 | } |
1097 | 1154 | ||
1098 | static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1155 | static inline void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) |
@@ -1162,33 +1219,39 @@ static inline void hci_remote_features_evt(struct hci_dev *hdev, struct sk_buff | |||
1162 | hci_dev_lock(hdev); | 1219 | hci_dev_lock(hdev); |
1163 | 1220 | ||
1164 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); | 1221 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); |
1165 | if (conn) { | 1222 | if (!conn) |
1166 | if (!ev->status) | 1223 | goto unlock; |
1167 | memcpy(conn->features, ev->features, 8); | ||
1168 | 1224 | ||
1169 | if (conn->state == BT_CONFIG) { | 1225 | if (!ev->status) |
1170 | if (!ev->status && lmp_ssp_capable(hdev) && | 1226 | memcpy(conn->features, ev->features, 8); |
1171 | lmp_ssp_capable(conn)) { | 1227 | |
1172 | struct hci_cp_read_remote_ext_features cp; | 1228 | if (conn->state != BT_CONFIG) |
1173 | cp.handle = ev->handle; | 1229 | goto unlock; |
1174 | cp.page = 0x01; | 1230 | |
1175 | hci_send_cmd(hdev, | 1231 | if (!ev->status && lmp_ssp_capable(hdev) && lmp_ssp_capable(conn)) { |
1176 | HCI_OP_READ_REMOTE_EXT_FEATURES, | 1232 | struct hci_cp_read_remote_ext_features cp; |
1177 | sizeof(cp), &cp); | 1233 | cp.handle = ev->handle; |
1178 | } else if (!ev->status && conn->out && | 1234 | cp.page = 0x01; |
1179 | conn->sec_level == BT_SECURITY_HIGH) { | 1235 | hci_send_cmd(hdev, HCI_OP_READ_REMOTE_EXT_FEATURES, |
1180 | struct hci_cp_auth_requested cp; | ||
1181 | cp.handle = ev->handle; | ||
1182 | hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, | ||
1183 | sizeof(cp), &cp); | 1236 | sizeof(cp), &cp); |
1184 | } else { | 1237 | goto unlock; |
1185 | conn->state = BT_CONNECTED; | 1238 | } |
1186 | hci_proto_connect_cfm(conn, ev->status); | 1239 | |
1187 | hci_conn_put(conn); | 1240 | if (!ev->status) { |
1188 | } | 1241 | struct hci_cp_remote_name_req cp; |
1189 | } | 1242 | memset(&cp, 0, sizeof(cp)); |
1243 | bacpy(&cp.bdaddr, &conn->dst); | ||
1244 | cp.pscan_rep_mode = 0x02; | ||
1245 | hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); | ||
1190 | } | 1246 | } |
1191 | 1247 | ||
1248 | if (!hci_outgoing_auth_needed(hdev, conn)) { | ||
1249 | conn->state = BT_CONNECTED; | ||
1250 | hci_proto_connect_cfm(conn, ev->status); | ||
1251 | hci_conn_put(conn); | ||
1252 | } | ||
1253 | |||
1254 | unlock: | ||
1192 | hci_dev_unlock(hdev); | 1255 | hci_dev_unlock(hdev); |
1193 | } | 1256 | } |
1194 | 1257 | ||
@@ -1449,10 +1512,12 @@ static inline void hci_num_comp_pkts_evt(struct hci_dev *hdev, struct sk_buff *s | |||
1449 | conn->sent -= count; | 1512 | conn->sent -= count; |
1450 | 1513 | ||
1451 | if (conn->type == ACL_LINK) { | 1514 | if (conn->type == ACL_LINK) { |
1452 | if ((hdev->acl_cnt += count) > hdev->acl_pkts) | 1515 | hdev->acl_cnt += count; |
1516 | if (hdev->acl_cnt > hdev->acl_pkts) | ||
1453 | hdev->acl_cnt = hdev->acl_pkts; | 1517 | hdev->acl_cnt = hdev->acl_pkts; |
1454 | } else { | 1518 | } else { |
1455 | if ((hdev->sco_cnt += count) > hdev->sco_pkts) | 1519 | hdev->sco_cnt += count; |
1520 | if (hdev->sco_cnt > hdev->sco_pkts) | ||
1456 | hdev->sco_cnt = hdev->sco_pkts; | 1521 | hdev->sco_cnt = hdev->sco_pkts; |
1457 | } | 1522 | } |
1458 | } | 1523 | } |
@@ -1547,7 +1612,8 @@ static inline void hci_clock_offset_evt(struct hci_dev *hdev, struct sk_buff *sk | |||
1547 | if (conn && !ev->status) { | 1612 | if (conn && !ev->status) { |
1548 | struct inquiry_entry *ie; | 1613 | struct inquiry_entry *ie; |
1549 | 1614 | ||
1550 | if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst))) { | 1615 | ie = hci_inquiry_cache_lookup(hdev, &conn->dst); |
1616 | if (ie) { | ||
1551 | ie->data.clock_offset = ev->clock_offset; | 1617 | ie->data.clock_offset = ev->clock_offset; |
1552 | ie->timestamp = jiffies; | 1618 | ie->timestamp = jiffies; |
1553 | } | 1619 | } |
@@ -1581,7 +1647,8 @@ static inline void hci_pscan_rep_mode_evt(struct hci_dev *hdev, struct sk_buff * | |||
1581 | 1647 | ||
1582 | hci_dev_lock(hdev); | 1648 | hci_dev_lock(hdev); |
1583 | 1649 | ||
1584 | if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr))) { | 1650 | ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); |
1651 | if (ie) { | ||
1585 | ie->data.pscan_rep_mode = ev->pscan_rep_mode; | 1652 | ie->data.pscan_rep_mode = ev->pscan_rep_mode; |
1586 | ie->timestamp = jiffies; | 1653 | ie->timestamp = jiffies; |
1587 | } | 1654 | } |
@@ -1646,32 +1713,37 @@ static inline void hci_remote_ext_features_evt(struct hci_dev *hdev, struct sk_b | |||
1646 | hci_dev_lock(hdev); | 1713 | hci_dev_lock(hdev); |
1647 | 1714 | ||
1648 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); | 1715 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); |
1649 | if (conn) { | 1716 | if (!conn) |
1650 | if (!ev->status && ev->page == 0x01) { | 1717 | goto unlock; |
1651 | struct inquiry_entry *ie; | ||
1652 | 1718 | ||
1653 | if ((ie = hci_inquiry_cache_lookup(hdev, &conn->dst))) | 1719 | if (!ev->status && ev->page == 0x01) { |
1654 | ie->data.ssp_mode = (ev->features[0] & 0x01); | 1720 | struct inquiry_entry *ie; |
1655 | 1721 | ||
1656 | conn->ssp_mode = (ev->features[0] & 0x01); | 1722 | ie = hci_inquiry_cache_lookup(hdev, &conn->dst); |
1657 | } | 1723 | if (ie) |
1724 | ie->data.ssp_mode = (ev->features[0] & 0x01); | ||
1658 | 1725 | ||
1659 | if (conn->state == BT_CONFIG) { | 1726 | conn->ssp_mode = (ev->features[0] & 0x01); |
1660 | if (!ev->status && hdev->ssp_mode > 0 && | ||
1661 | conn->ssp_mode > 0 && conn->out && | ||
1662 | conn->sec_level != BT_SECURITY_SDP) { | ||
1663 | struct hci_cp_auth_requested cp; | ||
1664 | cp.handle = ev->handle; | ||
1665 | hci_send_cmd(hdev, HCI_OP_AUTH_REQUESTED, | ||
1666 | sizeof(cp), &cp); | ||
1667 | } else { | ||
1668 | conn->state = BT_CONNECTED; | ||
1669 | hci_proto_connect_cfm(conn, ev->status); | ||
1670 | hci_conn_put(conn); | ||
1671 | } | ||
1672 | } | ||
1673 | } | 1727 | } |
1674 | 1728 | ||
1729 | if (conn->state != BT_CONFIG) | ||
1730 | goto unlock; | ||
1731 | |||
1732 | if (!ev->status) { | ||
1733 | struct hci_cp_remote_name_req cp; | ||
1734 | memset(&cp, 0, sizeof(cp)); | ||
1735 | bacpy(&cp.bdaddr, &conn->dst); | ||
1736 | cp.pscan_rep_mode = 0x02; | ||
1737 | hci_send_cmd(hdev, HCI_OP_REMOTE_NAME_REQ, sizeof(cp), &cp); | ||
1738 | } | ||
1739 | |||
1740 | if (!hci_outgoing_auth_needed(hdev, conn)) { | ||
1741 | conn->state = BT_CONNECTED; | ||
1742 | hci_proto_connect_cfm(conn, ev->status); | ||
1743 | hci_conn_put(conn); | ||
1744 | } | ||
1745 | |||
1746 | unlock: | ||
1675 | hci_dev_unlock(hdev); | 1747 | hci_dev_unlock(hdev); |
1676 | } | 1748 | } |
1677 | 1749 | ||
@@ -1821,7 +1893,8 @@ static inline void hci_remote_host_features_evt(struct hci_dev *hdev, struct sk_ | |||
1821 | 1893 | ||
1822 | hci_dev_lock(hdev); | 1894 | hci_dev_lock(hdev); |
1823 | 1895 | ||
1824 | if ((ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr))) | 1896 | ie = hci_inquiry_cache_lookup(hdev, &ev->bdaddr); |
1897 | if (ie) | ||
1825 | ie->data.ssp_mode = (ev->features[0] & 0x01); | 1898 | ie->data.ssp_mode = (ev->features[0] & 0x01); |
1826 | 1899 | ||
1827 | hci_dev_unlock(hdev); | 1900 | hci_dev_unlock(hdev); |
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 83acd164d39e..b3753bad2a55 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c | |||
@@ -43,7 +43,7 @@ | |||
43 | #include <net/sock.h> | 43 | #include <net/sock.h> |
44 | 44 | ||
45 | #include <asm/system.h> | 45 | #include <asm/system.h> |
46 | #include <asm/uaccess.h> | 46 | #include <linux/uaccess.h> |
47 | #include <asm/unaligned.h> | 47 | #include <asm/unaligned.h> |
48 | 48 | ||
49 | #include <net/bluetooth/bluetooth.h> | 49 | #include <net/bluetooth/bluetooth.h> |
@@ -125,7 +125,8 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb) | |||
125 | continue; | 125 | continue; |
126 | } | 126 | } |
127 | 127 | ||
128 | if (!(nskb = skb_clone(skb, GFP_ATOMIC))) | 128 | nskb = skb_clone(skb, GFP_ATOMIC); |
129 | if (!nskb) | ||
129 | continue; | 130 | continue; |
130 | 131 | ||
131 | /* Put type byte before the data */ | 132 | /* Put type byte before the data */ |
@@ -370,7 +371,8 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, int addr_le | |||
370 | } | 371 | } |
371 | 372 | ||
372 | if (haddr->hci_dev != HCI_DEV_NONE) { | 373 | if (haddr->hci_dev != HCI_DEV_NONE) { |
373 | if (!(hdev = hci_dev_get(haddr->hci_dev))) { | 374 | hdev = hci_dev_get(haddr->hci_dev); |
375 | if (!hdev) { | ||
374 | err = -ENODEV; | 376 | err = -ENODEV; |
375 | goto done; | 377 | goto done; |
376 | } | 378 | } |
@@ -457,7 +459,8 @@ static int hci_sock_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
457 | if (sk->sk_state == BT_CLOSED) | 459 | if (sk->sk_state == BT_CLOSED) |
458 | return 0; | 460 | return 0; |
459 | 461 | ||
460 | if (!(skb = skb_recv_datagram(sk, flags, noblock, &err))) | 462 | skb = skb_recv_datagram(sk, flags, noblock, &err); |
463 | if (!skb) | ||
461 | return err; | 464 | return err; |
462 | 465 | ||
463 | msg->msg_namelen = 0; | 466 | msg->msg_namelen = 0; |
@@ -499,7 +502,8 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
499 | 502 | ||
500 | lock_sock(sk); | 503 | lock_sock(sk); |
501 | 504 | ||
502 | if (!(hdev = hci_pi(sk)->hdev)) { | 505 | hdev = hci_pi(sk)->hdev; |
506 | if (!hdev) { | ||
503 | err = -EBADFD; | 507 | err = -EBADFD; |
504 | goto done; | 508 | goto done; |
505 | } | 509 | } |
@@ -509,7 +513,8 @@ static int hci_sock_sendmsg(struct kiocb *iocb, struct socket *sock, | |||
509 | goto done; | 513 | goto done; |
510 | } | 514 | } |
511 | 515 | ||
512 | if (!(skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err))) | 516 | skb = bt_skb_send_alloc(sk, len, msg->msg_flags & MSG_DONTWAIT, &err); |
517 | if (!skb) | ||
513 | goto done; | 518 | goto done; |
514 | 519 | ||
515 | if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { | 520 | if (memcpy_fromiovec(skb_put(skb, len), msg->msg_iov, len)) { |
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c index c0ee8b3928ed..29544c21f4b5 100644 --- a/net/bluetooth/hidp/core.c +++ b/net/bluetooth/hidp/core.c | |||
@@ -107,6 +107,7 @@ static void __hidp_unlink_session(struct hidp_session *session) | |||
107 | 107 | ||
108 | static void __hidp_copy_session(struct hidp_session *session, struct hidp_conninfo *ci) | 108 | static void __hidp_copy_session(struct hidp_session *session, struct hidp_conninfo *ci) |
109 | { | 109 | { |
110 | memset(ci, 0, sizeof(*ci)); | ||
110 | bacpy(&ci->bdaddr, &session->bdaddr); | 111 | bacpy(&ci->bdaddr, &session->bdaddr); |
111 | 112 | ||
112 | ci->flags = session->flags; | 113 | ci->flags = session->flags; |
@@ -115,7 +116,6 @@ static void __hidp_copy_session(struct hidp_session *session, struct hidp_connin | |||
115 | ci->vendor = 0x0000; | 116 | ci->vendor = 0x0000; |
116 | ci->product = 0x0000; | 117 | ci->product = 0x0000; |
117 | ci->version = 0x0000; | 118 | ci->version = 0x0000; |
118 | memset(ci->name, 0, 128); | ||
119 | 119 | ||
120 | if (session->input) { | 120 | if (session->input) { |
121 | ci->vendor = session->input->id.vendor; | 121 | ci->vendor = session->input->id.vendor; |
diff --git a/net/bluetooth/l2cap.c b/net/bluetooth/l2cap.c index cd8f6ea03841..c12eccfdfe01 100644 --- a/net/bluetooth/l2cap.c +++ b/net/bluetooth/l2cap.c | |||
@@ -57,7 +57,7 @@ | |||
57 | 57 | ||
58 | #define VERSION "2.15" | 58 | #define VERSION "2.15" |
59 | 59 | ||
60 | static int disable_ertm = 0; | 60 | static int disable_ertm; |
61 | 61 | ||
62 | static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN; | 62 | static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN; |
63 | static u8 l2cap_fixed_chan[8] = { 0x02, }; | 63 | static u8 l2cap_fixed_chan[8] = { 0x02, }; |
@@ -83,6 +83,18 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, | |||
83 | static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb); | 83 | static int l2cap_ertm_data_rcv(struct sock *sk, struct sk_buff *skb); |
84 | 84 | ||
85 | /* ---- L2CAP timers ---- */ | 85 | /* ---- L2CAP timers ---- */ |
86 | static void l2cap_sock_set_timer(struct sock *sk, long timeout) | ||
87 | { | ||
88 | BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout); | ||
89 | sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout); | ||
90 | } | ||
91 | |||
92 | static void l2cap_sock_clear_timer(struct sock *sk) | ||
93 | { | ||
94 | BT_DBG("sock %p state %d", sk, sk->sk_state); | ||
95 | sk_stop_timer(sk, &sk->sk_timer); | ||
96 | } | ||
97 | |||
86 | static void l2cap_sock_timeout(unsigned long arg) | 98 | static void l2cap_sock_timeout(unsigned long arg) |
87 | { | 99 | { |
88 | struct sock *sk = (struct sock *) arg; | 100 | struct sock *sk = (struct sock *) arg; |
@@ -92,6 +104,14 @@ static void l2cap_sock_timeout(unsigned long arg) | |||
92 | 104 | ||
93 | bh_lock_sock(sk); | 105 | bh_lock_sock(sk); |
94 | 106 | ||
107 | if (sock_owned_by_user(sk)) { | ||
108 | /* sk is owned by user. Try again later */ | ||
109 | l2cap_sock_set_timer(sk, HZ / 5); | ||
110 | bh_unlock_sock(sk); | ||
111 | sock_put(sk); | ||
112 | return; | ||
113 | } | ||
114 | |||
95 | if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG) | 115 | if (sk->sk_state == BT_CONNECTED || sk->sk_state == BT_CONFIG) |
96 | reason = ECONNREFUSED; | 116 | reason = ECONNREFUSED; |
97 | else if (sk->sk_state == BT_CONNECT && | 117 | else if (sk->sk_state == BT_CONNECT && |
@@ -108,18 +128,6 @@ static void l2cap_sock_timeout(unsigned long arg) | |||
108 | sock_put(sk); | 128 | sock_put(sk); |
109 | } | 129 | } |
110 | 130 | ||
111 | static void l2cap_sock_set_timer(struct sock *sk, long timeout) | ||
112 | { | ||
113 | BT_DBG("sk %p state %d timeout %ld", sk, sk->sk_state, timeout); | ||
114 | sk_reset_timer(sk, &sk->sk_timer, jiffies + timeout); | ||
115 | } | ||
116 | |||
117 | static void l2cap_sock_clear_timer(struct sock *sk) | ||
118 | { | ||
119 | BT_DBG("sock %p state %d", sk, sk->sk_state); | ||
120 | sk_stop_timer(sk, &sk->sk_timer); | ||
121 | } | ||
122 | |||
123 | /* ---- L2CAP channels ---- */ | 131 | /* ---- L2CAP channels ---- */ |
124 | static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid) | 132 | static struct sock *__l2cap_get_chan_by_dcid(struct l2cap_chan_list *l, u16 cid) |
125 | { | 133 | { |
@@ -743,11 +751,13 @@ found: | |||
743 | /* Find socket with psm and source bdaddr. | 751 | /* Find socket with psm and source bdaddr. |
744 | * Returns closest match. | 752 | * Returns closest match. |
745 | */ | 753 | */ |
746 | static struct sock *__l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src) | 754 | static struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src) |
747 | { | 755 | { |
748 | struct sock *sk = NULL, *sk1 = NULL; | 756 | struct sock *sk = NULL, *sk1 = NULL; |
749 | struct hlist_node *node; | 757 | struct hlist_node *node; |
750 | 758 | ||
759 | read_lock(&l2cap_sk_list.lock); | ||
760 | |||
751 | sk_for_each(sk, node, &l2cap_sk_list.head) { | 761 | sk_for_each(sk, node, &l2cap_sk_list.head) { |
752 | if (state && sk->sk_state != state) | 762 | if (state && sk->sk_state != state) |
753 | continue; | 763 | continue; |
@@ -762,20 +772,10 @@ static struct sock *__l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src | |||
762 | sk1 = sk; | 772 | sk1 = sk; |
763 | } | 773 | } |
764 | } | 774 | } |
765 | return node ? sk : sk1; | ||
766 | } | ||
767 | 775 | ||
768 | /* Find socket with given address (psm, src). | ||
769 | * Returns locked socket */ | ||
770 | static inline struct sock *l2cap_get_sock_by_psm(int state, __le16 psm, bdaddr_t *src) | ||
771 | { | ||
772 | struct sock *s; | ||
773 | read_lock(&l2cap_sk_list.lock); | ||
774 | s = __l2cap_get_sock_by_psm(state, psm, src); | ||
775 | if (s) | ||
776 | bh_lock_sock(s); | ||
777 | read_unlock(&l2cap_sk_list.lock); | 776 | read_unlock(&l2cap_sk_list.lock); |
778 | return s; | 777 | |
778 | return node ? sk : sk1; | ||
779 | } | 779 | } |
780 | 780 | ||
781 | static void l2cap_sock_destruct(struct sock *sk) | 781 | static void l2cap_sock_destruct(struct sock *sk) |
@@ -2926,6 +2926,8 @@ static inline int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
2926 | goto sendresp; | 2926 | goto sendresp; |
2927 | } | 2927 | } |
2928 | 2928 | ||
2929 | bh_lock_sock(parent); | ||
2930 | |||
2929 | /* Check if the ACL is secure enough (if not SDP) */ | 2931 | /* Check if the ACL is secure enough (if not SDP) */ |
2930 | if (psm != cpu_to_le16(0x0001) && | 2932 | if (psm != cpu_to_le16(0x0001) && |
2931 | !hci_conn_check_link_mode(conn->hcon)) { | 2933 | !hci_conn_check_link_mode(conn->hcon)) { |
@@ -3078,6 +3080,14 @@ static inline int l2cap_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hd | |||
3078 | break; | 3080 | break; |
3079 | 3081 | ||
3080 | default: | 3082 | default: |
3083 | /* don't delete l2cap channel if sk is owned by user */ | ||
3084 | if (sock_owned_by_user(sk)) { | ||
3085 | sk->sk_state = BT_DISCONN; | ||
3086 | l2cap_sock_clear_timer(sk); | ||
3087 | l2cap_sock_set_timer(sk, HZ / 5); | ||
3088 | break; | ||
3089 | } | ||
3090 | |||
3081 | l2cap_chan_del(sk, ECONNREFUSED); | 3091 | l2cap_chan_del(sk, ECONNREFUSED); |
3082 | break; | 3092 | break; |
3083 | } | 3093 | } |
@@ -3283,6 +3293,15 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd | |||
3283 | 3293 | ||
3284 | sk->sk_shutdown = SHUTDOWN_MASK; | 3294 | sk->sk_shutdown = SHUTDOWN_MASK; |
3285 | 3295 | ||
3296 | /* don't delete l2cap channel if sk is owned by user */ | ||
3297 | if (sock_owned_by_user(sk)) { | ||
3298 | sk->sk_state = BT_DISCONN; | ||
3299 | l2cap_sock_clear_timer(sk); | ||
3300 | l2cap_sock_set_timer(sk, HZ / 5); | ||
3301 | bh_unlock_sock(sk); | ||
3302 | return 0; | ||
3303 | } | ||
3304 | |||
3286 | l2cap_chan_del(sk, ECONNRESET); | 3305 | l2cap_chan_del(sk, ECONNRESET); |
3287 | bh_unlock_sock(sk); | 3306 | bh_unlock_sock(sk); |
3288 | 3307 | ||
@@ -3305,6 +3324,15 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd | |||
3305 | if (!sk) | 3324 | if (!sk) |
3306 | return 0; | 3325 | return 0; |
3307 | 3326 | ||
3327 | /* don't delete l2cap channel if sk is owned by user */ | ||
3328 | if (sock_owned_by_user(sk)) { | ||
3329 | sk->sk_state = BT_DISCONN; | ||
3330 | l2cap_sock_clear_timer(sk); | ||
3331 | l2cap_sock_set_timer(sk, HZ / 5); | ||
3332 | bh_unlock_sock(sk); | ||
3333 | return 0; | ||
3334 | } | ||
3335 | |||
3308 | l2cap_chan_del(sk, 0); | 3336 | l2cap_chan_del(sk, 0); |
3309 | bh_unlock_sock(sk); | 3337 | bh_unlock_sock(sk); |
3310 | 3338 | ||
@@ -4134,11 +4162,10 @@ static inline void l2cap_data_channel_rrframe(struct sock *sk, u16 rx_control) | |||
4134 | __mod_retrans_timer(); | 4162 | __mod_retrans_timer(); |
4135 | 4163 | ||
4136 | pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; | 4164 | pi->conn_state &= ~L2CAP_CONN_REMOTE_BUSY; |
4137 | if (pi->conn_state & L2CAP_CONN_SREJ_SENT) { | 4165 | if (pi->conn_state & L2CAP_CONN_SREJ_SENT) |
4138 | l2cap_send_ack(pi); | 4166 | l2cap_send_ack(pi); |
4139 | } else { | 4167 | else |
4140 | l2cap_ertm_send(sk); | 4168 | l2cap_ertm_send(sk); |
4141 | } | ||
4142 | } | 4169 | } |
4143 | } | 4170 | } |
4144 | 4171 | ||
@@ -4430,6 +4457,8 @@ static inline int l2cap_conless_channel(struct l2cap_conn *conn, __le16 psm, str | |||
4430 | if (!sk) | 4457 | if (!sk) |
4431 | goto drop; | 4458 | goto drop; |
4432 | 4459 | ||
4460 | bh_lock_sock(sk); | ||
4461 | |||
4433 | BT_DBG("sk %p, len %d", sk, skb->len); | 4462 | BT_DBG("sk %p, len %d", sk, skb->len); |
4434 | 4463 | ||
4435 | if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED) | 4464 | if (sk->sk_state != BT_BOUND && sk->sk_state != BT_CONNECTED) |
@@ -4841,8 +4870,10 @@ static int __init l2cap_init(void) | |||
4841 | return err; | 4870 | return err; |
4842 | 4871 | ||
4843 | _busy_wq = create_singlethread_workqueue("l2cap"); | 4872 | _busy_wq = create_singlethread_workqueue("l2cap"); |
4844 | if (!_busy_wq) | 4873 | if (!_busy_wq) { |
4845 | goto error; | 4874 | proto_unregister(&l2cap_proto); |
4875 | return -ENOMEM; | ||
4876 | } | ||
4846 | 4877 | ||
4847 | err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops); | 4878 | err = bt_sock_register(BTPROTO_L2CAP, &l2cap_sock_family_ops); |
4848 | if (err < 0) { | 4879 | if (err < 0) { |
@@ -4870,6 +4901,7 @@ static int __init l2cap_init(void) | |||
4870 | return 0; | 4901 | return 0; |
4871 | 4902 | ||
4872 | error: | 4903 | error: |
4904 | destroy_workqueue(_busy_wq); | ||
4873 | proto_unregister(&l2cap_proto); | 4905 | proto_unregister(&l2cap_proto); |
4874 | return err; | 4906 | return err; |
4875 | } | 4907 | } |
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index fa642aa652bd..c1e2bbafb549 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
@@ -41,7 +41,7 @@ | |||
41 | #include <linux/slab.h> | 41 | #include <linux/slab.h> |
42 | 42 | ||
43 | #include <net/sock.h> | 43 | #include <net/sock.h> |
44 | #include <asm/uaccess.h> | 44 | #include <linux/uaccess.h> |
45 | #include <asm/unaligned.h> | 45 | #include <asm/unaligned.h> |
46 | 46 | ||
47 | #include <net/bluetooth/bluetooth.h> | 47 | #include <net/bluetooth/bluetooth.h> |
@@ -51,10 +51,10 @@ | |||
51 | 51 | ||
52 | #define VERSION "1.11" | 52 | #define VERSION "1.11" |
53 | 53 | ||
54 | static int disable_cfc = 0; | 54 | static int disable_cfc; |
55 | static int l2cap_ertm; | ||
55 | static int channel_mtu = -1; | 56 | static int channel_mtu = -1; |
56 | static unsigned int l2cap_mtu = RFCOMM_MAX_L2CAP_MTU; | 57 | static unsigned int l2cap_mtu = RFCOMM_MAX_L2CAP_MTU; |
57 | static int l2cap_ertm = 0; | ||
58 | 58 | ||
59 | static struct task_struct *rfcomm_thread; | 59 | static struct task_struct *rfcomm_thread; |
60 | 60 | ||
@@ -1901,7 +1901,7 @@ static inline void rfcomm_check_connection(struct rfcomm_session *s) | |||
1901 | 1901 | ||
1902 | BT_DBG("%p state %ld", s, s->state); | 1902 | BT_DBG("%p state %ld", s, s->state); |
1903 | 1903 | ||
1904 | switch(sk->sk_state) { | 1904 | switch (sk->sk_state) { |
1905 | case BT_CONNECTED: | 1905 | case BT_CONNECTED: |
1906 | s->state = BT_CONNECT; | 1906 | s->state = BT_CONNECT; |
1907 | 1907 | ||
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index aec505f934df..66cc1f0c3df8 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c | |||
@@ -45,7 +45,7 @@ | |||
45 | #include <net/sock.h> | 45 | #include <net/sock.h> |
46 | 46 | ||
47 | #include <asm/system.h> | 47 | #include <asm/system.h> |
48 | #include <asm/uaccess.h> | 48 | #include <linux/uaccess.h> |
49 | 49 | ||
50 | #include <net/bluetooth/bluetooth.h> | 50 | #include <net/bluetooth/bluetooth.h> |
51 | #include <net/bluetooth/hci_core.h> | 51 | #include <net/bluetooth/hci_core.h> |
@@ -140,11 +140,13 @@ static struct sock *__rfcomm_get_sock_by_addr(u8 channel, bdaddr_t *src) | |||
140 | /* Find socket with channel and source bdaddr. | 140 | /* Find socket with channel and source bdaddr. |
141 | * Returns closest match. | 141 | * Returns closest match. |
142 | */ | 142 | */ |
143 | static struct sock *__rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t *src) | 143 | static struct sock *rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t *src) |
144 | { | 144 | { |
145 | struct sock *sk = NULL, *sk1 = NULL; | 145 | struct sock *sk = NULL, *sk1 = NULL; |
146 | struct hlist_node *node; | 146 | struct hlist_node *node; |
147 | 147 | ||
148 | read_lock(&rfcomm_sk_list.lock); | ||
149 | |||
148 | sk_for_each(sk, node, &rfcomm_sk_list.head) { | 150 | sk_for_each(sk, node, &rfcomm_sk_list.head) { |
149 | if (state && sk->sk_state != state) | 151 | if (state && sk->sk_state != state) |
150 | continue; | 152 | continue; |
@@ -159,19 +161,10 @@ static struct sock *__rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t | |||
159 | sk1 = sk; | 161 | sk1 = sk; |
160 | } | 162 | } |
161 | } | 163 | } |
162 | return node ? sk : sk1; | ||
163 | } | ||
164 | 164 | ||
165 | /* Find socket with given address (channel, src). | ||
166 | * Returns locked socket */ | ||
167 | static inline struct sock *rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t *src) | ||
168 | { | ||
169 | struct sock *s; | ||
170 | read_lock(&rfcomm_sk_list.lock); | ||
171 | s = __rfcomm_get_sock_by_channel(state, channel, src); | ||
172 | if (s) bh_lock_sock(s); | ||
173 | read_unlock(&rfcomm_sk_list.lock); | 165 | read_unlock(&rfcomm_sk_list.lock); |
174 | return s; | 166 | |
167 | return node ? sk : sk1; | ||
175 | } | 168 | } |
176 | 169 | ||
177 | static void rfcomm_sock_destruct(struct sock *sk) | 170 | static void rfcomm_sock_destruct(struct sock *sk) |
@@ -895,7 +888,8 @@ static int rfcomm_sock_shutdown(struct socket *sock, int how) | |||
895 | 888 | ||
896 | BT_DBG("sock %p, sk %p", sock, sk); | 889 | BT_DBG("sock %p, sk %p", sock, sk); |
897 | 890 | ||
898 | if (!sk) return 0; | 891 | if (!sk) |
892 | return 0; | ||
899 | 893 | ||
900 | lock_sock(sk); | 894 | lock_sock(sk); |
901 | if (!sk->sk_shutdown) { | 895 | if (!sk->sk_shutdown) { |
@@ -945,6 +939,8 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc * | |||
945 | if (!parent) | 939 | if (!parent) |
946 | return 0; | 940 | return 0; |
947 | 941 | ||
942 | bh_lock_sock(parent); | ||
943 | |||
948 | /* Check for backlog size */ | 944 | /* Check for backlog size */ |
949 | if (sk_acceptq_is_full(parent)) { | 945 | if (sk_acceptq_is_full(parent)) { |
950 | BT_DBG("backlog full %d", parent->sk_ack_backlog); | 946 | BT_DBG("backlog full %d", parent->sk_ack_backlog); |
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index a9b81f5dacd1..2575c2db6404 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c | |||
@@ -58,9 +58,9 @@ struct rfcomm_dev { | |||
58 | 58 | ||
59 | bdaddr_t src; | 59 | bdaddr_t src; |
60 | bdaddr_t dst; | 60 | bdaddr_t dst; |
61 | u8 channel; | 61 | u8 channel; |
62 | 62 | ||
63 | uint modem_status; | 63 | uint modem_status; |
64 | 64 | ||
65 | struct rfcomm_dlc *dlc; | 65 | struct rfcomm_dlc *dlc; |
66 | struct tty_struct *tty; | 66 | struct tty_struct *tty; |
@@ -69,7 +69,7 @@ struct rfcomm_dev { | |||
69 | 69 | ||
70 | struct device *tty_dev; | 70 | struct device *tty_dev; |
71 | 71 | ||
72 | atomic_t wmem_alloc; | 72 | atomic_t wmem_alloc; |
73 | 73 | ||
74 | struct sk_buff_head pending; | 74 | struct sk_buff_head pending; |
75 | }; | 75 | }; |
@@ -431,7 +431,8 @@ static int rfcomm_release_dev(void __user *arg) | |||
431 | 431 | ||
432 | BT_DBG("dev_id %d flags 0x%x", req.dev_id, req.flags); | 432 | BT_DBG("dev_id %d flags 0x%x", req.dev_id, req.flags); |
433 | 433 | ||
434 | if (!(dev = rfcomm_dev_get(req.dev_id))) | 434 | dev = rfcomm_dev_get(req.dev_id); |
435 | if (!dev) | ||
435 | return -ENODEV; | 436 | return -ENODEV; |
436 | 437 | ||
437 | if (dev->flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN)) { | 438 | if (dev->flags != NOCAP_FLAGS && !capable(CAP_NET_ADMIN)) { |
@@ -470,7 +471,8 @@ static int rfcomm_get_dev_list(void __user *arg) | |||
470 | 471 | ||
471 | size = sizeof(*dl) + dev_num * sizeof(*di); | 472 | size = sizeof(*dl) + dev_num * sizeof(*di); |
472 | 473 | ||
473 | if (!(dl = kmalloc(size, GFP_KERNEL))) | 474 | dl = kmalloc(size, GFP_KERNEL); |
475 | if (!dl) | ||
474 | return -ENOMEM; | 476 | return -ENOMEM; |
475 | 477 | ||
476 | di = dl->dev_info; | 478 | di = dl->dev_info; |
@@ -513,7 +515,8 @@ static int rfcomm_get_dev_info(void __user *arg) | |||
513 | if (copy_from_user(&di, arg, sizeof(di))) | 515 | if (copy_from_user(&di, arg, sizeof(di))) |
514 | return -EFAULT; | 516 | return -EFAULT; |
515 | 517 | ||
516 | if (!(dev = rfcomm_dev_get(di.id))) | 518 | dev = rfcomm_dev_get(di.id); |
519 | if (!dev) | ||
517 | return -ENODEV; | 520 | return -ENODEV; |
518 | 521 | ||
519 | di.flags = dev->flags; | 522 | di.flags = dev->flags; |
@@ -561,7 +564,8 @@ static void rfcomm_dev_data_ready(struct rfcomm_dlc *dlc, struct sk_buff *skb) | |||
561 | return; | 564 | return; |
562 | } | 565 | } |
563 | 566 | ||
564 | if (!(tty = dev->tty) || !skb_queue_empty(&dev->pending)) { | 567 | tty = dev->tty; |
568 | if (!tty || !skb_queue_empty(&dev->pending)) { | ||
565 | skb_queue_tail(&dev->pending, skb); | 569 | skb_queue_tail(&dev->pending, skb); |
566 | return; | 570 | return; |
567 | } | 571 | } |
@@ -796,7 +800,8 @@ static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, in | |||
796 | 800 | ||
797 | memcpy(skb_put(skb, size), buf + sent, size); | 801 | memcpy(skb_put(skb, size), buf + sent, size); |
798 | 802 | ||
799 | if ((err = rfcomm_dlc_send(dlc, skb)) < 0) { | 803 | err = rfcomm_dlc_send(dlc, skb); |
804 | if (err < 0) { | ||
800 | kfree_skb(skb); | 805 | kfree_skb(skb); |
801 | break; | 806 | break; |
802 | } | 807 | } |
@@ -892,7 +897,7 @@ static void rfcomm_tty_set_termios(struct tty_struct *tty, struct ktermios *old) | |||
892 | 897 | ||
893 | /* Parity on/off and when on, odd/even */ | 898 | /* Parity on/off and when on, odd/even */ |
894 | if (((old->c_cflag & PARENB) != (new->c_cflag & PARENB)) || | 899 | if (((old->c_cflag & PARENB) != (new->c_cflag & PARENB)) || |
895 | ((old->c_cflag & PARODD) != (new->c_cflag & PARODD)) ) { | 900 | ((old->c_cflag & PARODD) != (new->c_cflag & PARODD))) { |
896 | changes |= RFCOMM_RPN_PM_PARITY; | 901 | changes |= RFCOMM_RPN_PM_PARITY; |
897 | BT_DBG("Parity change detected."); | 902 | BT_DBG("Parity change detected."); |
898 | } | 903 | } |
@@ -937,11 +942,10 @@ static void rfcomm_tty_set_termios(struct tty_struct *tty, struct ktermios *old) | |||
937 | /* POSIX does not support 1.5 stop bits and RFCOMM does not | 942 | /* POSIX does not support 1.5 stop bits and RFCOMM does not |
938 | * support 2 stop bits. So a request for 2 stop bits gets | 943 | * support 2 stop bits. So a request for 2 stop bits gets |
939 | * translated to 1.5 stop bits */ | 944 | * translated to 1.5 stop bits */ |
940 | if (new->c_cflag & CSTOPB) { | 945 | if (new->c_cflag & CSTOPB) |
941 | stop_bits = RFCOMM_RPN_STOP_15; | 946 | stop_bits = RFCOMM_RPN_STOP_15; |
942 | } else { | 947 | else |
943 | stop_bits = RFCOMM_RPN_STOP_1; | 948 | stop_bits = RFCOMM_RPN_STOP_1; |
944 | } | ||
945 | 949 | ||
946 | /* Handle number of data bits [5-8] */ | 950 | /* Handle number of data bits [5-8] */ |
947 | if ((old->c_cflag & CSIZE) != (new->c_cflag & CSIZE)) | 951 | if ((old->c_cflag & CSIZE) != (new->c_cflag & CSIZE)) |
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 66b9e5c0523a..960c6d1637da 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
@@ -44,7 +44,7 @@ | |||
44 | #include <net/sock.h> | 44 | #include <net/sock.h> |
45 | 45 | ||
46 | #include <asm/system.h> | 46 | #include <asm/system.h> |
47 | #include <asm/uaccess.h> | 47 | #include <linux/uaccess.h> |
48 | 48 | ||
49 | #include <net/bluetooth/bluetooth.h> | 49 | #include <net/bluetooth/bluetooth.h> |
50 | #include <net/bluetooth/hci_core.h> | 50 | #include <net/bluetooth/hci_core.h> |
@@ -52,7 +52,7 @@ | |||
52 | 52 | ||
53 | #define VERSION "0.6" | 53 | #define VERSION "0.6" |
54 | 54 | ||
55 | static int disable_esco = 0; | 55 | static int disable_esco; |
56 | 56 | ||
57 | static const struct proto_ops sco_sock_ops; | 57 | static const struct proto_ops sco_sock_ops; |
58 | 58 | ||
@@ -138,16 +138,17 @@ static inline struct sock *sco_chan_get(struct sco_conn *conn) | |||
138 | 138 | ||
139 | static int sco_conn_del(struct hci_conn *hcon, int err) | 139 | static int sco_conn_del(struct hci_conn *hcon, int err) |
140 | { | 140 | { |
141 | struct sco_conn *conn; | 141 | struct sco_conn *conn = hcon->sco_data; |
142 | struct sock *sk; | 142 | struct sock *sk; |
143 | 143 | ||
144 | if (!(conn = hcon->sco_data)) | 144 | if (!conn) |
145 | return 0; | 145 | return 0; |
146 | 146 | ||
147 | BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); | 147 | BT_DBG("hcon %p conn %p, err %d", hcon, conn, err); |
148 | 148 | ||
149 | /* Kill socket */ | 149 | /* Kill socket */ |
150 | if ((sk = sco_chan_get(conn))) { | 150 | sk = sco_chan_get(conn); |
151 | if (sk) { | ||
151 | bh_lock_sock(sk); | 152 | bh_lock_sock(sk); |
152 | sco_sock_clear_timer(sk); | 153 | sco_sock_clear_timer(sk); |
153 | sco_chan_del(sk, err); | 154 | sco_chan_del(sk, err); |
@@ -185,7 +186,8 @@ static int sco_connect(struct sock *sk) | |||
185 | 186 | ||
186 | BT_DBG("%s -> %s", batostr(src), batostr(dst)); | 187 | BT_DBG("%s -> %s", batostr(src), batostr(dst)); |
187 | 188 | ||
188 | if (!(hdev = hci_get_route(dst, src))) | 189 | hdev = hci_get_route(dst, src); |
190 | if (!hdev) | ||
189 | return -EHOSTUNREACH; | 191 | return -EHOSTUNREACH; |
190 | 192 | ||
191 | hci_dev_lock_bh(hdev); | 193 | hci_dev_lock_bh(hdev); |
@@ -510,7 +512,8 @@ static int sco_sock_connect(struct socket *sock, struct sockaddr *addr, int alen | |||
510 | /* Set destination address and psm */ | 512 | /* Set destination address and psm */ |
511 | bacpy(&bt_sk(sk)->dst, &sa->sco_bdaddr); | 513 | bacpy(&bt_sk(sk)->dst, &sa->sco_bdaddr); |
512 | 514 | ||
513 | if ((err = sco_connect(sk))) | 515 | err = sco_connect(sk); |
516 | if (err) | ||
514 | goto done; | 517 | goto done; |
515 | 518 | ||
516 | err = bt_sock_wait_state(sk, BT_CONNECTED, | 519 | err = bt_sock_wait_state(sk, BT_CONNECTED, |
@@ -828,13 +831,14 @@ static void sco_chan_del(struct sock *sk, int err) | |||
828 | 831 | ||
829 | static void sco_conn_ready(struct sco_conn *conn) | 832 | static void sco_conn_ready(struct sco_conn *conn) |
830 | { | 833 | { |
831 | struct sock *parent, *sk; | 834 | struct sock *parent; |
835 | struct sock *sk = conn->sk; | ||
832 | 836 | ||
833 | BT_DBG("conn %p", conn); | 837 | BT_DBG("conn %p", conn); |
834 | 838 | ||
835 | sco_conn_lock(conn); | 839 | sco_conn_lock(conn); |
836 | 840 | ||
837 | if ((sk = conn->sk)) { | 841 | if (sk) { |
838 | sco_sock_clear_timer(sk); | 842 | sco_sock_clear_timer(sk); |
839 | bh_lock_sock(sk); | 843 | bh_lock_sock(sk); |
840 | sk->sk_state = BT_CONNECTED; | 844 | sk->sk_state = BT_CONNECTED; |
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 17cb0b633576..556443566e9c 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c | |||
@@ -141,7 +141,7 @@ static int br_change_mtu(struct net_device *dev, int new_mtu) | |||
141 | 141 | ||
142 | #ifdef CONFIG_BRIDGE_NETFILTER | 142 | #ifdef CONFIG_BRIDGE_NETFILTER |
143 | /* remember the MTU in the rtable for PMTU */ | 143 | /* remember the MTU in the rtable for PMTU */ |
144 | br->fake_rtable.dst.metrics[RTAX_MTU - 1] = new_mtu; | 144 | dst_metric_set(&br->fake_rtable.dst, RTAX_MTU, new_mtu); |
145 | #endif | 145 | #endif |
146 | 146 | ||
147 | return 0; | 147 | return 0; |
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index 6e1392093911..16f5c333596a 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
@@ -124,7 +124,7 @@ void br_netfilter_rtable_init(struct net_bridge *br) | |||
124 | atomic_set(&rt->dst.__refcnt, 1); | 124 | atomic_set(&rt->dst.__refcnt, 1); |
125 | rt->dst.dev = br->dev; | 125 | rt->dst.dev = br->dev; |
126 | rt->dst.path = &rt->dst; | 126 | rt->dst.path = &rt->dst; |
127 | rt->dst.metrics[RTAX_MTU - 1] = 1500; | 127 | dst_metric_set(&rt->dst, RTAX_MTU, 1500); |
128 | rt->dst.flags = DST_NOXFRM; | 128 | rt->dst.flags = DST_NOXFRM; |
129 | rt->dst.ops = &fake_dst_ops; | 129 | rt->dst.ops = &fake_dst_ops; |
130 | } | 130 | } |
diff --git a/net/core/filter.c b/net/core/filter.c index e193e29d4671..e8a6ac411ffb 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
@@ -88,7 +88,7 @@ enum { | |||
88 | }; | 88 | }; |
89 | 89 | ||
90 | /* No hurry in this branch */ | 90 | /* No hurry in this branch */ |
91 | static void *__load_pointer(const struct sk_buff *skb, int k) | 91 | static void *__load_pointer(const struct sk_buff *skb, int k, unsigned int size) |
92 | { | 92 | { |
93 | u8 *ptr = NULL; | 93 | u8 *ptr = NULL; |
94 | 94 | ||
@@ -97,7 +97,7 @@ static void *__load_pointer(const struct sk_buff *skb, int k) | |||
97 | else if (k >= SKF_LL_OFF) | 97 | else if (k >= SKF_LL_OFF) |
98 | ptr = skb_mac_header(skb) + k - SKF_LL_OFF; | 98 | ptr = skb_mac_header(skb) + k - SKF_LL_OFF; |
99 | 99 | ||
100 | if (ptr >= skb->head && ptr < skb_tail_pointer(skb)) | 100 | if (ptr >= skb->head && ptr + size <= skb_tail_pointer(skb)) |
101 | return ptr; | 101 | return ptr; |
102 | return NULL; | 102 | return NULL; |
103 | } | 103 | } |
@@ -110,7 +110,7 @@ static inline void *load_pointer(const struct sk_buff *skb, int k, | |||
110 | else { | 110 | else { |
111 | if (k >= SKF_AD_OFF) | 111 | if (k >= SKF_AD_OFF) |
112 | return NULL; | 112 | return NULL; |
113 | return __load_pointer(skb, k); | 113 | return __load_pointer(skb, k, size); |
114 | } | 114 | } |
115 | } | 115 | } |
116 | 116 | ||
diff --git a/net/core/sock.c b/net/core/sock.c index fb6080111461..bcdb6ff6e621 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
@@ -992,17 +992,18 @@ static inline void sock_lock_init(struct sock *sk) | |||
992 | /* | 992 | /* |
993 | * Copy all fields from osk to nsk but nsk->sk_refcnt must not change yet, | 993 | * Copy all fields from osk to nsk but nsk->sk_refcnt must not change yet, |
994 | * even temporarly, because of RCU lookups. sk_node should also be left as is. | 994 | * even temporarly, because of RCU lookups. sk_node should also be left as is. |
995 | * We must not copy fields between sk_dontcopy_begin and sk_dontcopy_end | ||
995 | */ | 996 | */ |
996 | static void sock_copy(struct sock *nsk, const struct sock *osk) | 997 | static void sock_copy(struct sock *nsk, const struct sock *osk) |
997 | { | 998 | { |
998 | #ifdef CONFIG_SECURITY_NETWORK | 999 | #ifdef CONFIG_SECURITY_NETWORK |
999 | void *sptr = nsk->sk_security; | 1000 | void *sptr = nsk->sk_security; |
1000 | #endif | 1001 | #endif |
1001 | BUILD_BUG_ON(offsetof(struct sock, sk_copy_start) != | 1002 | memcpy(nsk, osk, offsetof(struct sock, sk_dontcopy_begin)); |
1002 | sizeof(osk->sk_node) + sizeof(osk->sk_refcnt) + | 1003 | |
1003 | sizeof(osk->sk_tx_queue_mapping)); | 1004 | memcpy(&nsk->sk_dontcopy_end, &osk->sk_dontcopy_end, |
1004 | memcpy(&nsk->sk_copy_start, &osk->sk_copy_start, | 1005 | osk->sk_prot->obj_size - offsetof(struct sock, sk_dontcopy_end)); |
1005 | osk->sk_prot->obj_size - offsetof(struct sock, sk_copy_start)); | 1006 | |
1006 | #ifdef CONFIG_SECURITY_NETWORK | 1007 | #ifdef CONFIG_SECURITY_NETWORK |
1007 | nsk->sk_security = sptr; | 1008 | nsk->sk_security = sptr; |
1008 | security_sk_clone(osk, nsk); | 1009 | security_sk_clone(osk, nsk); |
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index 8280e43c8861..e2e926841fe6 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c | |||
@@ -240,13 +240,13 @@ static void dn_dst_update_pmtu(struct dst_entry *dst, u32 mtu) | |||
240 | 240 | ||
241 | if (dst_metric(dst, RTAX_MTU) > mtu && mtu >= min_mtu) { | 241 | if (dst_metric(dst, RTAX_MTU) > mtu && mtu >= min_mtu) { |
242 | if (!(dst_metric_locked(dst, RTAX_MTU))) { | 242 | if (!(dst_metric_locked(dst, RTAX_MTU))) { |
243 | dst->metrics[RTAX_MTU-1] = mtu; | 243 | dst_metric_set(dst, RTAX_MTU, mtu); |
244 | dst_set_expires(dst, dn_rt_mtu_expires); | 244 | dst_set_expires(dst, dn_rt_mtu_expires); |
245 | } | 245 | } |
246 | if (!(dst_metric_locked(dst, RTAX_ADVMSS))) { | 246 | if (!(dst_metric_locked(dst, RTAX_ADVMSS))) { |
247 | u32 mss = mtu - DN_MAX_NSP_DATA_HEADER; | 247 | u32 mss = mtu - DN_MAX_NSP_DATA_HEADER; |
248 | if (dst_metric(dst, RTAX_ADVMSS) > mss) | 248 | if (dst_metric(dst, RTAX_ADVMSS) > mss) |
249 | dst->metrics[RTAX_ADVMSS-1] = mss; | 249 | dst_metric_set(dst, RTAX_ADVMSS, mss); |
250 | } | 250 | } |
251 | } | 251 | } |
252 | } | 252 | } |
@@ -806,8 +806,7 @@ static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res) | |||
806 | if (DN_FIB_RES_GW(*res) && | 806 | if (DN_FIB_RES_GW(*res) && |
807 | DN_FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) | 807 | DN_FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) |
808 | rt->rt_gateway = DN_FIB_RES_GW(*res); | 808 | rt->rt_gateway = DN_FIB_RES_GW(*res); |
809 | memcpy(rt->dst.metrics, fi->fib_metrics, | 809 | dst_import_metrics(&rt->dst, fi->fib_metrics); |
810 | sizeof(rt->dst.metrics)); | ||
811 | } | 810 | } |
812 | rt->rt_type = res->type; | 811 | rt->rt_type = res->type; |
813 | 812 | ||
@@ -820,11 +819,11 @@ static int dn_rt_set_next_hop(struct dn_route *rt, struct dn_fib_res *res) | |||
820 | 819 | ||
821 | if (dst_metric(&rt->dst, RTAX_MTU) == 0 || | 820 | if (dst_metric(&rt->dst, RTAX_MTU) == 0 || |
822 | dst_metric(&rt->dst, RTAX_MTU) > rt->dst.dev->mtu) | 821 | dst_metric(&rt->dst, RTAX_MTU) > rt->dst.dev->mtu) |
823 | rt->dst.metrics[RTAX_MTU-1] = rt->dst.dev->mtu; | 822 | dst_metric_set(&rt->dst, RTAX_MTU, rt->dst.dev->mtu); |
824 | mss = dn_mss_from_pmtu(dev, dst_mtu(&rt->dst)); | 823 | mss = dn_mss_from_pmtu(dev, dst_mtu(&rt->dst)); |
825 | if (dst_metric(&rt->dst, RTAX_ADVMSS) == 0 || | 824 | if (dst_metric(&rt->dst, RTAX_ADVMSS) == 0 || |
826 | dst_metric(&rt->dst, RTAX_ADVMSS) > mss) | 825 | dst_metric(&rt->dst, RTAX_ADVMSS) > mss) |
827 | rt->dst.metrics[RTAX_ADVMSS-1] = mss; | 826 | dst_metric_set(&rt->dst, RTAX_ADVMSS, mss); |
828 | return 0; | 827 | return 0; |
829 | } | 828 | } |
830 | 829 | ||
@@ -1502,7 +1501,7 @@ static int dn_rt_fill_info(struct sk_buff *skb, u32 pid, u32 seq, | |||
1502 | RTA_PUT(skb, RTA_PREFSRC, 2, &rt->rt_local_src); | 1501 | RTA_PUT(skb, RTA_PREFSRC, 2, &rt->rt_local_src); |
1503 | if (rt->rt_daddr != rt->rt_gateway) | 1502 | if (rt->rt_daddr != rt->rt_gateway) |
1504 | RTA_PUT(skb, RTA_GATEWAY, 2, &rt->rt_gateway); | 1503 | RTA_PUT(skb, RTA_GATEWAY, 2, &rt->rt_gateway); |
1505 | if (rtnetlink_put_metrics(skb, rt->dst.metrics) < 0) | 1504 | if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0) |
1506 | goto rtattr_failure; | 1505 | goto rtattr_failure; |
1507 | expires = rt->dst.expires ? rt->dst.expires - jiffies : 0; | 1506 | expires = rt->dst.expires ? rt->dst.expires - jiffies : 0; |
1508 | if (rtnl_put_cacheinfo(skb, &rt->dst, 0, 0, 0, expires, | 1507 | if (rtnl_put_cacheinfo(skb, &rt->dst, 0, 0, 0, expires, |
diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c index 06f5f8f482f0..25e318153f14 100644 --- a/net/ipv4/inet_connection_sock.c +++ b/net/ipv4/inet_connection_sock.c | |||
@@ -55,7 +55,6 @@ EXPORT_SYMBOL(inet_get_local_port_range); | |||
55 | int inet_csk_bind_conflict(const struct sock *sk, | 55 | int inet_csk_bind_conflict(const struct sock *sk, |
56 | const struct inet_bind_bucket *tb) | 56 | const struct inet_bind_bucket *tb) |
57 | { | 57 | { |
58 | const __be32 sk_rcv_saddr = inet_rcv_saddr(sk); | ||
59 | struct sock *sk2; | 58 | struct sock *sk2; |
60 | struct hlist_node *node; | 59 | struct hlist_node *node; |
61 | int reuse = sk->sk_reuse; | 60 | int reuse = sk->sk_reuse; |
@@ -75,9 +74,9 @@ int inet_csk_bind_conflict(const struct sock *sk, | |||
75 | sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) { | 74 | sk->sk_bound_dev_if == sk2->sk_bound_dev_if)) { |
76 | if (!reuse || !sk2->sk_reuse || | 75 | if (!reuse || !sk2->sk_reuse || |
77 | sk2->sk_state == TCP_LISTEN) { | 76 | sk2->sk_state == TCP_LISTEN) { |
78 | const __be32 sk2_rcv_saddr = inet_rcv_saddr(sk2); | 77 | const __be32 sk2_rcv_saddr = sk_rcv_saddr(sk2); |
79 | if (!sk2_rcv_saddr || !sk_rcv_saddr || | 78 | if (!sk2_rcv_saddr || !sk_rcv_saddr(sk) || |
80 | sk2_rcv_saddr == sk_rcv_saddr) | 79 | sk2_rcv_saddr == sk_rcv_saddr(sk)) |
81 | break; | 80 | break; |
82 | } | 81 | } |
83 | } | 82 | } |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 258c98d5fa79..ff4e7a4e33ed 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -818,7 +818,7 @@ static netdev_tx_t ipgre_tunnel_xmit(struct sk_buff *skb, struct net_device *dev | |||
818 | !ipv4_is_multicast(tunnel->parms.iph.daddr)) || | 818 | !ipv4_is_multicast(tunnel->parms.iph.daddr)) || |
819 | rt6->rt6i_dst.plen == 128) { | 819 | rt6->rt6i_dst.plen == 128) { |
820 | rt6->rt6i_flags |= RTF_MODIFIED; | 820 | rt6->rt6i_flags |= RTF_MODIFIED; |
821 | skb_dst(skb)->metrics[RTAX_MTU-1] = mtu; | 821 | dst_metric_set(skb_dst(skb), RTAX_MTU, mtu); |
822 | } | 822 | } |
823 | } | 823 | } |
824 | 824 | ||
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 3843c2dfde82..26ac396eaa5e 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
@@ -1686,11 +1686,14 @@ unsigned short ip_rt_frag_needed(struct net *net, struct iphdr *iph, | |||
1686 | if (mtu < dst_mtu(&rth->dst)) { | 1686 | if (mtu < dst_mtu(&rth->dst)) { |
1687 | dst_confirm(&rth->dst); | 1687 | dst_confirm(&rth->dst); |
1688 | if (mtu < ip_rt_min_pmtu) { | 1688 | if (mtu < ip_rt_min_pmtu) { |
1689 | u32 lock = dst_metric(&rth->dst, | ||
1690 | RTAX_LOCK); | ||
1689 | mtu = ip_rt_min_pmtu; | 1691 | mtu = ip_rt_min_pmtu; |
1690 | rth->dst.metrics[RTAX_LOCK-1] |= | 1692 | lock |= (1 << RTAX_MTU); |
1691 | (1 << RTAX_MTU); | 1693 | dst_metric_set(&rth->dst, RTAX_LOCK, |
1694 | lock); | ||
1692 | } | 1695 | } |
1693 | rth->dst.metrics[RTAX_MTU-1] = mtu; | 1696 | dst_metric_set(&rth->dst, RTAX_MTU, mtu); |
1694 | dst_set_expires(&rth->dst, | 1697 | dst_set_expires(&rth->dst, |
1695 | ip_rt_mtu_expires); | 1698 | ip_rt_mtu_expires); |
1696 | } | 1699 | } |
@@ -1708,10 +1711,11 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, u32 mtu) | |||
1708 | if (dst_mtu(dst) > mtu && mtu >= 68 && | 1711 | if (dst_mtu(dst) > mtu && mtu >= 68 && |
1709 | !(dst_metric_locked(dst, RTAX_MTU))) { | 1712 | !(dst_metric_locked(dst, RTAX_MTU))) { |
1710 | if (mtu < ip_rt_min_pmtu) { | 1713 | if (mtu < ip_rt_min_pmtu) { |
1714 | u32 lock = dst_metric(dst, RTAX_LOCK); | ||
1711 | mtu = ip_rt_min_pmtu; | 1715 | mtu = ip_rt_min_pmtu; |
1712 | dst->metrics[RTAX_LOCK-1] |= (1 << RTAX_MTU); | 1716 | dst_metric_set(dst, RTAX_LOCK, lock | (1 << RTAX_MTU)); |
1713 | } | 1717 | } |
1714 | dst->metrics[RTAX_MTU-1] = mtu; | 1718 | dst_metric_set(dst, RTAX_MTU, mtu); |
1715 | dst_set_expires(dst, ip_rt_mtu_expires); | 1719 | dst_set_expires(dst, ip_rt_mtu_expires); |
1716 | call_netevent_notifiers(NETEVENT_PMTU_UPDATE, dst); | 1720 | call_netevent_notifiers(NETEVENT_PMTU_UPDATE, dst); |
1717 | } | 1721 | } |
@@ -1796,36 +1800,37 @@ static void set_class_tag(struct rtable *rt, u32 tag) | |||
1796 | 1800 | ||
1797 | static void rt_set_nexthop(struct rtable *rt, struct fib_result *res, u32 itag) | 1801 | static void rt_set_nexthop(struct rtable *rt, struct fib_result *res, u32 itag) |
1798 | { | 1802 | { |
1803 | struct dst_entry *dst = &rt->dst; | ||
1799 | struct fib_info *fi = res->fi; | 1804 | struct fib_info *fi = res->fi; |
1800 | 1805 | ||
1801 | if (fi) { | 1806 | if (fi) { |
1802 | if (FIB_RES_GW(*res) && | 1807 | if (FIB_RES_GW(*res) && |
1803 | FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) | 1808 | FIB_RES_NH(*res).nh_scope == RT_SCOPE_LINK) |
1804 | rt->rt_gateway = FIB_RES_GW(*res); | 1809 | rt->rt_gateway = FIB_RES_GW(*res); |
1805 | memcpy(rt->dst.metrics, fi->fib_metrics, | 1810 | dst_import_metrics(dst, fi->fib_metrics); |
1806 | sizeof(rt->dst.metrics)); | ||
1807 | if (fi->fib_mtu == 0) { | 1811 | if (fi->fib_mtu == 0) { |
1808 | rt->dst.metrics[RTAX_MTU-1] = rt->dst.dev->mtu; | 1812 | dst_metric_set(dst, RTAX_MTU, dst->dev->mtu); |
1809 | if (dst_metric_locked(&rt->dst, RTAX_MTU) && | 1813 | if (dst_metric_locked(dst, RTAX_MTU) && |
1810 | rt->rt_gateway != rt->rt_dst && | 1814 | rt->rt_gateway != rt->rt_dst && |
1811 | rt->dst.dev->mtu > 576) | 1815 | dst->dev->mtu > 576) |
1812 | rt->dst.metrics[RTAX_MTU-1] = 576; | 1816 | dst_metric_set(dst, RTAX_MTU, 576); |
1813 | } | 1817 | } |
1814 | #ifdef CONFIG_NET_CLS_ROUTE | 1818 | #ifdef CONFIG_NET_CLS_ROUTE |
1815 | rt->dst.tclassid = FIB_RES_NH(*res).nh_tclassid; | 1819 | dst->tclassid = FIB_RES_NH(*res).nh_tclassid; |
1816 | #endif | 1820 | #endif |
1817 | } else | 1821 | } else |
1818 | rt->dst.metrics[RTAX_MTU-1]= rt->dst.dev->mtu; | 1822 | dst_metric_set(dst, RTAX_MTU, dst->dev->mtu); |
1819 | 1823 | ||
1820 | if (dst_metric(&rt->dst, RTAX_HOPLIMIT) == 0) | 1824 | if (dst_metric(dst, RTAX_HOPLIMIT) == 0) |
1821 | rt->dst.metrics[RTAX_HOPLIMIT-1] = sysctl_ip_default_ttl; | 1825 | dst_metric_set(dst, RTAX_HOPLIMIT, sysctl_ip_default_ttl); |
1822 | if (dst_mtu(&rt->dst) > IP_MAX_MTU) | 1826 | if (dst_mtu(dst) > IP_MAX_MTU) |
1823 | rt->dst.metrics[RTAX_MTU-1] = IP_MAX_MTU; | 1827 | dst_metric_set(dst, RTAX_MTU, IP_MAX_MTU); |
1824 | if (dst_metric(&rt->dst, RTAX_ADVMSS) == 0) | 1828 | if (dst_metric(dst, RTAX_ADVMSS) == 0) |
1825 | rt->dst.metrics[RTAX_ADVMSS-1] = max_t(unsigned int, rt->dst.dev->mtu - 40, | 1829 | dst_metric_set(dst, RTAX_ADVMSS, |
1826 | ip_rt_min_advmss); | 1830 | max_t(unsigned int, dst->dev->mtu - 40, |
1827 | if (dst_metric(&rt->dst, RTAX_ADVMSS) > 65535 - 40) | 1831 | ip_rt_min_advmss)); |
1828 | rt->dst.metrics[RTAX_ADVMSS-1] = 65535 - 40; | 1832 | if (dst_metric(dst, RTAX_ADVMSS) > 65535 - 40) |
1833 | dst_metric_set(dst, RTAX_ADVMSS, 65535 - 40); | ||
1829 | 1834 | ||
1830 | #ifdef CONFIG_NET_CLS_ROUTE | 1835 | #ifdef CONFIG_NET_CLS_ROUTE |
1831 | #ifdef CONFIG_IP_MULTIPLE_TABLES | 1836 | #ifdef CONFIG_IP_MULTIPLE_TABLES |
@@ -2720,7 +2725,7 @@ static int ipv4_dst_blackhole(struct net *net, struct rtable **rp, struct flowi | |||
2720 | new->__use = 1; | 2725 | new->__use = 1; |
2721 | new->input = dst_discard; | 2726 | new->input = dst_discard; |
2722 | new->output = dst_discard; | 2727 | new->output = dst_discard; |
2723 | memcpy(new->metrics, ort->dst.metrics, RTAX_MAX*sizeof(u32)); | 2728 | dst_copy_metrics(new, &ort->dst); |
2724 | 2729 | ||
2725 | new->dev = ort->dst.dev; | 2730 | new->dev = ort->dst.dev; |
2726 | if (new->dev) | 2731 | if (new->dev) |
@@ -2827,7 +2832,7 @@ static int rt_fill_info(struct net *net, | |||
2827 | if (rt->rt_dst != rt->rt_gateway) | 2832 | if (rt->rt_dst != rt->rt_gateway) |
2828 | NLA_PUT_BE32(skb, RTA_GATEWAY, rt->rt_gateway); | 2833 | NLA_PUT_BE32(skb, RTA_GATEWAY, rt->rt_gateway); |
2829 | 2834 | ||
2830 | if (rtnetlink_put_metrics(skb, rt->dst.metrics) < 0) | 2835 | if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0) |
2831 | goto nla_put_failure; | 2836 | goto nla_put_failure; |
2832 | 2837 | ||
2833 | if (rt->fl.mark) | 2838 | if (rt->fl.mark) |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 6d8ab1c4efc3..824e8c8a17ad 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
@@ -734,7 +734,7 @@ void tcp_update_metrics(struct sock *sk) | |||
734 | * Reset our results. | 734 | * Reset our results. |
735 | */ | 735 | */ |
736 | if (!(dst_metric_locked(dst, RTAX_RTT))) | 736 | if (!(dst_metric_locked(dst, RTAX_RTT))) |
737 | dst->metrics[RTAX_RTT - 1] = 0; | 737 | dst_metric_set(dst, RTAX_RTT, 0); |
738 | return; | 738 | return; |
739 | } | 739 | } |
740 | 740 | ||
@@ -776,34 +776,38 @@ void tcp_update_metrics(struct sock *sk) | |||
776 | if (dst_metric(dst, RTAX_SSTHRESH) && | 776 | if (dst_metric(dst, RTAX_SSTHRESH) && |
777 | !dst_metric_locked(dst, RTAX_SSTHRESH) && | 777 | !dst_metric_locked(dst, RTAX_SSTHRESH) && |
778 | (tp->snd_cwnd >> 1) > dst_metric(dst, RTAX_SSTHRESH)) | 778 | (tp->snd_cwnd >> 1) > dst_metric(dst, RTAX_SSTHRESH)) |
779 | dst->metrics[RTAX_SSTHRESH-1] = tp->snd_cwnd >> 1; | 779 | dst_metric_set(dst, RTAX_SSTHRESH, tp->snd_cwnd >> 1); |
780 | if (!dst_metric_locked(dst, RTAX_CWND) && | 780 | if (!dst_metric_locked(dst, RTAX_CWND) && |
781 | tp->snd_cwnd > dst_metric(dst, RTAX_CWND)) | 781 | tp->snd_cwnd > dst_metric(dst, RTAX_CWND)) |
782 | dst->metrics[RTAX_CWND - 1] = tp->snd_cwnd; | 782 | dst_metric_set(dst, RTAX_CWND, tp->snd_cwnd); |
783 | } else if (tp->snd_cwnd > tp->snd_ssthresh && | 783 | } else if (tp->snd_cwnd > tp->snd_ssthresh && |
784 | icsk->icsk_ca_state == TCP_CA_Open) { | 784 | icsk->icsk_ca_state == TCP_CA_Open) { |
785 | /* Cong. avoidance phase, cwnd is reliable. */ | 785 | /* Cong. avoidance phase, cwnd is reliable. */ |
786 | if (!dst_metric_locked(dst, RTAX_SSTHRESH)) | 786 | if (!dst_metric_locked(dst, RTAX_SSTHRESH)) |
787 | dst->metrics[RTAX_SSTHRESH-1] = | 787 | dst_metric_set(dst, RTAX_SSTHRESH, |
788 | max(tp->snd_cwnd >> 1, tp->snd_ssthresh); | 788 | max(tp->snd_cwnd >> 1, tp->snd_ssthresh)); |
789 | if (!dst_metric_locked(dst, RTAX_CWND)) | 789 | if (!dst_metric_locked(dst, RTAX_CWND)) |
790 | dst->metrics[RTAX_CWND-1] = (dst_metric(dst, RTAX_CWND) + tp->snd_cwnd) >> 1; | 790 | dst_metric_set(dst, RTAX_CWND, |
791 | (dst_metric(dst, RTAX_CWND) + | ||
792 | tp->snd_cwnd) >> 1); | ||
791 | } else { | 793 | } else { |
792 | /* Else slow start did not finish, cwnd is non-sense, | 794 | /* Else slow start did not finish, cwnd is non-sense, |
793 | ssthresh may be also invalid. | 795 | ssthresh may be also invalid. |
794 | */ | 796 | */ |
795 | if (!dst_metric_locked(dst, RTAX_CWND)) | 797 | if (!dst_metric_locked(dst, RTAX_CWND)) |
796 | dst->metrics[RTAX_CWND-1] = (dst_metric(dst, RTAX_CWND) + tp->snd_ssthresh) >> 1; | 798 | dst_metric_set(dst, RTAX_CWND, |
799 | (dst_metric(dst, RTAX_CWND) + | ||
800 | tp->snd_ssthresh) >> 1); | ||
797 | if (dst_metric(dst, RTAX_SSTHRESH) && | 801 | if (dst_metric(dst, RTAX_SSTHRESH) && |
798 | !dst_metric_locked(dst, RTAX_SSTHRESH) && | 802 | !dst_metric_locked(dst, RTAX_SSTHRESH) && |
799 | tp->snd_ssthresh > dst_metric(dst, RTAX_SSTHRESH)) | 803 | tp->snd_ssthresh > dst_metric(dst, RTAX_SSTHRESH)) |
800 | dst->metrics[RTAX_SSTHRESH-1] = tp->snd_ssthresh; | 804 | dst_metric_set(dst, RTAX_SSTHRESH, tp->snd_ssthresh); |
801 | } | 805 | } |
802 | 806 | ||
803 | if (!dst_metric_locked(dst, RTAX_REORDERING)) { | 807 | if (!dst_metric_locked(dst, RTAX_REORDERING)) { |
804 | if (dst_metric(dst, RTAX_REORDERING) < tp->reordering && | 808 | if (dst_metric(dst, RTAX_REORDERING) < tp->reordering && |
805 | tp->reordering != sysctl_tcp_reordering) | 809 | tp->reordering != sysctl_tcp_reordering) |
806 | dst->metrics[RTAX_REORDERING-1] = tp->reordering; | 810 | dst_metric_set(dst, RTAX_REORDERING, tp->reordering); |
807 | } | 811 | } |
808 | } | 812 | } |
809 | } | 813 | } |
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c index e18f84130203..2342545a5ee9 100644 --- a/net/ipv6/ndisc.c +++ b/net/ipv6/ndisc.c | |||
@@ -1259,7 +1259,8 @@ static void ndisc_router_discovery(struct sk_buff *skb) | |||
1259 | if (ra_msg->icmph.icmp6_hop_limit) { | 1259 | if (ra_msg->icmph.icmp6_hop_limit) { |
1260 | in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit; | 1260 | in6_dev->cnf.hop_limit = ra_msg->icmph.icmp6_hop_limit; |
1261 | if (rt) | 1261 | if (rt) |
1262 | rt->dst.metrics[RTAX_HOPLIMIT-1] = ra_msg->icmph.icmp6_hop_limit; | 1262 | dst_metric_set(&rt->dst, RTAX_HOPLIMIT, |
1263 | ra_msg->icmph.icmp6_hop_limit); | ||
1263 | } | 1264 | } |
1264 | 1265 | ||
1265 | skip_defrtr: | 1266 | skip_defrtr: |
@@ -1377,7 +1378,7 @@ skip_linkparms: | |||
1377 | in6_dev->cnf.mtu6 = mtu; | 1378 | in6_dev->cnf.mtu6 = mtu; |
1378 | 1379 | ||
1379 | if (rt) | 1380 | if (rt) |
1380 | rt->dst.metrics[RTAX_MTU-1] = mtu; | 1381 | dst_metric_set(&rt->dst, RTAX_MTU, mtu); |
1381 | 1382 | ||
1382 | rt6_mtu_change(skb->dev, mtu); | 1383 | rt6_mtu_change(skb->dev, mtu); |
1383 | } | 1384 | } |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 026caef0326c..4aed0812b512 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
@@ -129,7 +129,6 @@ static struct rt6_info ip6_null_entry_template = { | |||
129 | .__use = 1, | 129 | .__use = 1, |
130 | .obsolete = -1, | 130 | .obsolete = -1, |
131 | .error = -ENETUNREACH, | 131 | .error = -ENETUNREACH, |
132 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, | ||
133 | .input = ip6_pkt_discard, | 132 | .input = ip6_pkt_discard, |
134 | .output = ip6_pkt_discard_out, | 133 | .output = ip6_pkt_discard_out, |
135 | }, | 134 | }, |
@@ -150,7 +149,6 @@ static struct rt6_info ip6_prohibit_entry_template = { | |||
150 | .__use = 1, | 149 | .__use = 1, |
151 | .obsolete = -1, | 150 | .obsolete = -1, |
152 | .error = -EACCES, | 151 | .error = -EACCES, |
153 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, | ||
154 | .input = ip6_pkt_prohibit, | 152 | .input = ip6_pkt_prohibit, |
155 | .output = ip6_pkt_prohibit_out, | 153 | .output = ip6_pkt_prohibit_out, |
156 | }, | 154 | }, |
@@ -166,7 +164,6 @@ static struct rt6_info ip6_blk_hole_entry_template = { | |||
166 | .__use = 1, | 164 | .__use = 1, |
167 | .obsolete = -1, | 165 | .obsolete = -1, |
168 | .error = -EINVAL, | 166 | .error = -EINVAL, |
169 | .metrics = { [RTAX_HOPLIMIT - 1] = 255, }, | ||
170 | .input = dst_discard, | 167 | .input = dst_discard, |
171 | .output = dst_discard, | 168 | .output = dst_discard, |
172 | }, | 169 | }, |
@@ -844,7 +841,7 @@ int ip6_dst_blackhole(struct sock *sk, struct dst_entry **dstp, struct flowi *fl | |||
844 | new->input = dst_discard; | 841 | new->input = dst_discard; |
845 | new->output = dst_discard; | 842 | new->output = dst_discard; |
846 | 843 | ||
847 | memcpy(new->metrics, ort->dst.metrics, RTAX_MAX*sizeof(u32)); | 844 | dst_copy_metrics(new, &ort->dst); |
848 | new->dev = ort->dst.dev; | 845 | new->dev = ort->dst.dev; |
849 | if (new->dev) | 846 | if (new->dev) |
850 | dev_hold(new->dev); | 847 | dev_hold(new->dev); |
@@ -928,10 +925,12 @@ static void ip6_rt_update_pmtu(struct dst_entry *dst, u32 mtu) | |||
928 | if (mtu < dst_mtu(dst) && rt6->rt6i_dst.plen == 128) { | 925 | if (mtu < dst_mtu(dst) && rt6->rt6i_dst.plen == 128) { |
929 | rt6->rt6i_flags |= RTF_MODIFIED; | 926 | rt6->rt6i_flags |= RTF_MODIFIED; |
930 | if (mtu < IPV6_MIN_MTU) { | 927 | if (mtu < IPV6_MIN_MTU) { |
928 | u32 features = dst_metric(dst, RTAX_FEATURES); | ||
931 | mtu = IPV6_MIN_MTU; | 929 | mtu = IPV6_MIN_MTU; |
932 | dst->metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG; | 930 | features |= RTAX_FEATURE_ALLFRAG; |
931 | dst_metric_set(dst, RTAX_FEATURES, features); | ||
933 | } | 932 | } |
934 | dst->metrics[RTAX_MTU-1] = mtu; | 933 | dst_metric_set(dst, RTAX_MTU, mtu); |
935 | call_netevent_notifiers(NETEVENT_PMTU_UPDATE, dst); | 934 | call_netevent_notifiers(NETEVENT_PMTU_UPDATE, dst); |
936 | } | 935 | } |
937 | } | 936 | } |
@@ -989,9 +988,9 @@ struct dst_entry *icmp6_dst_alloc(struct net_device *dev, | |||
989 | rt->rt6i_idev = idev; | 988 | rt->rt6i_idev = idev; |
990 | rt->rt6i_nexthop = neigh; | 989 | rt->rt6i_nexthop = neigh; |
991 | atomic_set(&rt->dst.__refcnt, 1); | 990 | atomic_set(&rt->dst.__refcnt, 1); |
992 | rt->dst.metrics[RTAX_HOPLIMIT-1] = 255; | 991 | dst_metric_set(&rt->dst, RTAX_HOPLIMIT, 255); |
993 | rt->dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev); | 992 | dst_metric_set(&rt->dst, RTAX_MTU, ipv6_get_mtu(rt->rt6i_dev)); |
994 | rt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->dst)); | 993 | dst_metric_set(&rt->dst, RTAX_ADVMSS, ipv6_advmss(net, dst_mtu(&rt->dst))); |
995 | rt->dst.output = ip6_output; | 994 | rt->dst.output = ip6_output; |
996 | 995 | ||
997 | #if 0 /* there's no chance to use these for ndisc */ | 996 | #if 0 /* there's no chance to use these for ndisc */ |
@@ -1305,17 +1304,17 @@ install_route: | |||
1305 | goto out; | 1304 | goto out; |
1306 | } | 1305 | } |
1307 | 1306 | ||
1308 | rt->dst.metrics[type - 1] = nla_get_u32(nla); | 1307 | dst_metric_set(&rt->dst, type, nla_get_u32(nla)); |
1309 | } | 1308 | } |
1310 | } | 1309 | } |
1311 | } | 1310 | } |
1312 | 1311 | ||
1313 | if (dst_metric(&rt->dst, RTAX_HOPLIMIT) == 0) | 1312 | if (dst_metric(&rt->dst, RTAX_HOPLIMIT) == 0) |
1314 | rt->dst.metrics[RTAX_HOPLIMIT-1] = -1; | 1313 | dst_metric_set(&rt->dst, RTAX_HOPLIMIT, -1); |
1315 | if (!dst_mtu(&rt->dst)) | 1314 | if (!dst_mtu(&rt->dst)) |
1316 | rt->dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(dev); | 1315 | dst_metric_set(&rt->dst, RTAX_MTU, ipv6_get_mtu(dev)); |
1317 | if (!dst_metric(&rt->dst, RTAX_ADVMSS)) | 1316 | if (!dst_metric(&rt->dst, RTAX_ADVMSS)) |
1318 | rt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->dst)); | 1317 | dst_metric_set(&rt->dst, RTAX_ADVMSS, ipv6_advmss(net, dst_mtu(&rt->dst))); |
1319 | rt->dst.dev = dev; | 1318 | rt->dst.dev = dev; |
1320 | rt->rt6i_idev = idev; | 1319 | rt->rt6i_idev = idev; |
1321 | rt->rt6i_table = table; | 1320 | rt->rt6i_table = table; |
@@ -1541,9 +1540,9 @@ void rt6_redirect(struct in6_addr *dest, struct in6_addr *src, | |||
1541 | ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key); | 1540 | ipv6_addr_copy(&nrt->rt6i_gateway, (struct in6_addr*)neigh->primary_key); |
1542 | nrt->rt6i_nexthop = neigh_clone(neigh); | 1541 | nrt->rt6i_nexthop = neigh_clone(neigh); |
1543 | /* Reset pmtu, it may be better */ | 1542 | /* Reset pmtu, it may be better */ |
1544 | nrt->dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(neigh->dev); | 1543 | dst_metric_set(&nrt->dst, RTAX_MTU, ipv6_get_mtu(neigh->dev)); |
1545 | nrt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(dev_net(neigh->dev), | 1544 | dst_metric_set(&nrt->dst, RTAX_ADVMSS, ipv6_advmss(dev_net(neigh->dev), |
1546 | dst_mtu(&nrt->dst)); | 1545 | dst_mtu(&nrt->dst))); |
1547 | 1546 | ||
1548 | if (ip6_ins_rt(nrt)) | 1547 | if (ip6_ins_rt(nrt)) |
1549 | goto out; | 1548 | goto out; |
@@ -1602,9 +1601,12 @@ static void rt6_do_pmtu_disc(struct in6_addr *daddr, struct in6_addr *saddr, | |||
1602 | would return automatically. | 1601 | would return automatically. |
1603 | */ | 1602 | */ |
1604 | if (rt->rt6i_flags & RTF_CACHE) { | 1603 | if (rt->rt6i_flags & RTF_CACHE) { |
1605 | rt->dst.metrics[RTAX_MTU-1] = pmtu; | 1604 | dst_metric_set(&rt->dst, RTAX_MTU, pmtu); |
1606 | if (allfrag) | 1605 | if (allfrag) { |
1607 | rt->dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG; | 1606 | u32 features = dst_metric(&rt->dst, RTAX_FEATURES); |
1607 | features |= RTAX_FEATURE_ALLFRAG; | ||
1608 | dst_metric_set(&rt->dst, RTAX_FEATURES, features); | ||
1609 | } | ||
1608 | dst_set_expires(&rt->dst, net->ipv6.sysctl.ip6_rt_mtu_expires); | 1610 | dst_set_expires(&rt->dst, net->ipv6.sysctl.ip6_rt_mtu_expires); |
1609 | rt->rt6i_flags |= RTF_MODIFIED|RTF_EXPIRES; | 1611 | rt->rt6i_flags |= RTF_MODIFIED|RTF_EXPIRES; |
1610 | goto out; | 1612 | goto out; |
@@ -1621,9 +1623,12 @@ static void rt6_do_pmtu_disc(struct in6_addr *daddr, struct in6_addr *saddr, | |||
1621 | nrt = rt6_alloc_clone(rt, daddr); | 1623 | nrt = rt6_alloc_clone(rt, daddr); |
1622 | 1624 | ||
1623 | if (nrt) { | 1625 | if (nrt) { |
1624 | nrt->dst.metrics[RTAX_MTU-1] = pmtu; | 1626 | dst_metric_set(&nrt->dst, RTAX_MTU, pmtu); |
1625 | if (allfrag) | 1627 | if (allfrag) { |
1626 | nrt->dst.metrics[RTAX_FEATURES-1] |= RTAX_FEATURE_ALLFRAG; | 1628 | u32 features = dst_metric(&nrt->dst, RTAX_FEATURES); |
1629 | features |= RTAX_FEATURE_ALLFRAG; | ||
1630 | dst_metric_set(&nrt->dst, RTAX_FEATURES, features); | ||
1631 | } | ||
1627 | 1632 | ||
1628 | /* According to RFC 1981, detecting PMTU increase shouldn't be | 1633 | /* According to RFC 1981, detecting PMTU increase shouldn't be |
1629 | * happened within 5 mins, the recommended timer is 10 mins. | 1634 | * happened within 5 mins, the recommended timer is 10 mins. |
@@ -1674,7 +1679,7 @@ static struct rt6_info * ip6_rt_copy(struct rt6_info *ort) | |||
1674 | rt->dst.input = ort->dst.input; | 1679 | rt->dst.input = ort->dst.input; |
1675 | rt->dst.output = ort->dst.output; | 1680 | rt->dst.output = ort->dst.output; |
1676 | 1681 | ||
1677 | memcpy(rt->dst.metrics, ort->dst.metrics, RTAX_MAX*sizeof(u32)); | 1682 | dst_copy_metrics(&rt->dst, &ort->dst); |
1678 | rt->dst.error = ort->dst.error; | 1683 | rt->dst.error = ort->dst.error; |
1679 | rt->dst.dev = ort->dst.dev; | 1684 | rt->dst.dev = ort->dst.dev; |
1680 | if (rt->dst.dev) | 1685 | if (rt->dst.dev) |
@@ -1966,9 +1971,9 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev, | |||
1966 | rt->dst.output = ip6_output; | 1971 | rt->dst.output = ip6_output; |
1967 | rt->rt6i_dev = net->loopback_dev; | 1972 | rt->rt6i_dev = net->loopback_dev; |
1968 | rt->rt6i_idev = idev; | 1973 | rt->rt6i_idev = idev; |
1969 | rt->dst.metrics[RTAX_MTU-1] = ipv6_get_mtu(rt->rt6i_dev); | 1974 | dst_metric_set(&rt->dst, RTAX_MTU, ipv6_get_mtu(rt->rt6i_dev)); |
1970 | rt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, dst_mtu(&rt->dst)); | 1975 | dst_metric_set(&rt->dst, RTAX_ADVMSS, ipv6_advmss(net, dst_mtu(&rt->dst))); |
1971 | rt->dst.metrics[RTAX_HOPLIMIT-1] = -1; | 1976 | dst_metric_set(&rt->dst, RTAX_HOPLIMIT, -1); |
1972 | rt->dst.obsolete = -1; | 1977 | rt->dst.obsolete = -1; |
1973 | 1978 | ||
1974 | rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP; | 1979 | rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP; |
@@ -2068,8 +2073,8 @@ static int rt6_mtu_change_route(struct rt6_info *rt, void *p_arg) | |||
2068 | (dst_mtu(&rt->dst) >= arg->mtu || | 2073 | (dst_mtu(&rt->dst) >= arg->mtu || |
2069 | (dst_mtu(&rt->dst) < arg->mtu && | 2074 | (dst_mtu(&rt->dst) < arg->mtu && |
2070 | dst_mtu(&rt->dst) == idev->cnf.mtu6))) { | 2075 | dst_mtu(&rt->dst) == idev->cnf.mtu6))) { |
2071 | rt->dst.metrics[RTAX_MTU-1] = arg->mtu; | 2076 | dst_metric_set(&rt->dst, RTAX_MTU, arg->mtu); |
2072 | rt->dst.metrics[RTAX_ADVMSS-1] = ipv6_advmss(net, arg->mtu); | 2077 | dst_metric_set(&rt->dst, RTAX_ADVMSS, ipv6_advmss(net, arg->mtu)); |
2073 | } | 2078 | } |
2074 | return 0; | 2079 | return 0; |
2075 | } | 2080 | } |
@@ -2295,7 +2300,7 @@ static int rt6_fill_node(struct net *net, | |||
2295 | NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); | 2300 | NLA_PUT(skb, RTA_PREFSRC, 16, &saddr_buf); |
2296 | } | 2301 | } |
2297 | 2302 | ||
2298 | if (rtnetlink_put_metrics(skb, rt->dst.metrics) < 0) | 2303 | if (rtnetlink_put_metrics(skb, dst_metrics_ptr(&rt->dst)) < 0) |
2299 | goto nla_put_failure; | 2304 | goto nla_put_failure; |
2300 | 2305 | ||
2301 | if (rt->dst.neighbour) | 2306 | if (rt->dst.neighbour) |
@@ -2686,6 +2691,7 @@ static int __net_init ip6_route_net_init(struct net *net) | |||
2686 | net->ipv6.ip6_null_entry->dst.path = | 2691 | net->ipv6.ip6_null_entry->dst.path = |
2687 | (struct dst_entry *)net->ipv6.ip6_null_entry; | 2692 | (struct dst_entry *)net->ipv6.ip6_null_entry; |
2688 | net->ipv6.ip6_null_entry->dst.ops = &net->ipv6.ip6_dst_ops; | 2693 | net->ipv6.ip6_null_entry->dst.ops = &net->ipv6.ip6_dst_ops; |
2694 | dst_metric_set(&net->ipv6.ip6_null_entry->dst, RTAX_HOPLIMIT, 255); | ||
2689 | 2695 | ||
2690 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES | 2696 | #ifdef CONFIG_IPV6_MULTIPLE_TABLES |
2691 | net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, | 2697 | net->ipv6.ip6_prohibit_entry = kmemdup(&ip6_prohibit_entry_template, |
@@ -2696,6 +2702,7 @@ static int __net_init ip6_route_net_init(struct net *net) | |||
2696 | net->ipv6.ip6_prohibit_entry->dst.path = | 2702 | net->ipv6.ip6_prohibit_entry->dst.path = |
2697 | (struct dst_entry *)net->ipv6.ip6_prohibit_entry; | 2703 | (struct dst_entry *)net->ipv6.ip6_prohibit_entry; |
2698 | net->ipv6.ip6_prohibit_entry->dst.ops = &net->ipv6.ip6_dst_ops; | 2704 | net->ipv6.ip6_prohibit_entry->dst.ops = &net->ipv6.ip6_dst_ops; |
2705 | dst_metric_set(&net->ipv6.ip6_prohibit_entry->dst, RTAX_HOPLIMIT, 255); | ||
2699 | 2706 | ||
2700 | net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, | 2707 | net->ipv6.ip6_blk_hole_entry = kmemdup(&ip6_blk_hole_entry_template, |
2701 | sizeof(*net->ipv6.ip6_blk_hole_entry), | 2708 | sizeof(*net->ipv6.ip6_blk_hole_entry), |
@@ -2705,6 +2712,7 @@ static int __net_init ip6_route_net_init(struct net *net) | |||
2705 | net->ipv6.ip6_blk_hole_entry->dst.path = | 2712 | net->ipv6.ip6_blk_hole_entry->dst.path = |
2706 | (struct dst_entry *)net->ipv6.ip6_blk_hole_entry; | 2713 | (struct dst_entry *)net->ipv6.ip6_blk_hole_entry; |
2707 | net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; | 2714 | net->ipv6.ip6_blk_hole_entry->dst.ops = &net->ipv6.ip6_dst_ops; |
2715 | dst_metric_set(&net->ipv6.ip6_blk_hole_entry->dst, RTAX_HOPLIMIT, 255); | ||
2708 | #endif | 2716 | #endif |
2709 | 2717 | ||
2710 | net->ipv6.sysctl.flush_delay = 0; | 2718 | net->ipv6.sysctl.flush_delay = 0; |
diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index b541a4e009fb..7aad12770867 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c | |||
@@ -54,8 +54,8 @@ int ipv6_rcv_saddr_equal(const struct sock *sk, const struct sock *sk2) | |||
54 | { | 54 | { |
55 | const struct in6_addr *sk_rcv_saddr6 = &inet6_sk(sk)->rcv_saddr; | 55 | const struct in6_addr *sk_rcv_saddr6 = &inet6_sk(sk)->rcv_saddr; |
56 | const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2); | 56 | const struct in6_addr *sk2_rcv_saddr6 = inet6_rcv_saddr(sk2); |
57 | __be32 sk1_rcv_saddr = inet_sk(sk)->inet_rcv_saddr; | 57 | __be32 sk1_rcv_saddr = sk_rcv_saddr(sk); |
58 | __be32 sk2_rcv_saddr = inet_rcv_saddr(sk2); | 58 | __be32 sk2_rcv_saddr = sk_rcv_saddr(sk2); |
59 | int sk_ipv6only = ipv6_only_sock(sk); | 59 | int sk_ipv6only = ipv6_only_sock(sk); |
60 | int sk2_ipv6only = inet_v6_ipv6only(sk2); | 60 | int sk2_ipv6only = inet_v6_ipv6only(sk2); |
61 | int addr_type = ipv6_addr_type(sk_rcv_saddr6); | 61 | int addr_type = ipv6_addr_type(sk_rcv_saddr6); |
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c index 720b7a84af59..f138b195d657 100644 --- a/net/mac80211/agg-rx.c +++ b/net/mac80211/agg-rx.c | |||
@@ -129,9 +129,7 @@ static void sta_rx_agg_reorder_timer_expired(unsigned long data) | |||
129 | timer_to_tid[0]); | 129 | timer_to_tid[0]); |
130 | 130 | ||
131 | rcu_read_lock(); | 131 | rcu_read_lock(); |
132 | spin_lock(&sta->lock); | ||
133 | ieee80211_release_reorder_timeout(sta, *ptid); | 132 | ieee80211_release_reorder_timeout(sta, *ptid); |
134 | spin_unlock(&sta->lock); | ||
135 | rcu_read_unlock(); | 133 | rcu_read_unlock(); |
136 | } | 134 | } |
137 | 135 | ||
@@ -256,7 +254,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
256 | } | 254 | } |
257 | 255 | ||
258 | /* prepare A-MPDU MLME for Rx aggregation */ | 256 | /* prepare A-MPDU MLME for Rx aggregation */ |
259 | tid_agg_rx = kmalloc(sizeof(struct tid_ampdu_rx), GFP_ATOMIC); | 257 | tid_agg_rx = kmalloc(sizeof(struct tid_ampdu_rx), GFP_KERNEL); |
260 | if (!tid_agg_rx) { | 258 | if (!tid_agg_rx) { |
261 | #ifdef CONFIG_MAC80211_HT_DEBUG | 259 | #ifdef CONFIG_MAC80211_HT_DEBUG |
262 | if (net_ratelimit()) | 260 | if (net_ratelimit()) |
@@ -280,9 +278,9 @@ void ieee80211_process_addba_request(struct ieee80211_local *local, | |||
280 | 278 | ||
281 | /* prepare reordering buffer */ | 279 | /* prepare reordering buffer */ |
282 | tid_agg_rx->reorder_buf = | 280 | tid_agg_rx->reorder_buf = |
283 | kcalloc(buf_size, sizeof(struct sk_buff *), GFP_ATOMIC); | 281 | kcalloc(buf_size, sizeof(struct sk_buff *), GFP_KERNEL); |
284 | tid_agg_rx->reorder_time = | 282 | tid_agg_rx->reorder_time = |
285 | kcalloc(buf_size, sizeof(unsigned long), GFP_ATOMIC); | 283 | kcalloc(buf_size, sizeof(unsigned long), GFP_KERNEL); |
286 | if (!tid_agg_rx->reorder_buf || !tid_agg_rx->reorder_time) { | 284 | if (!tid_agg_rx->reorder_buf || !tid_agg_rx->reorder_time) { |
287 | #ifdef CONFIG_MAC80211_HT_DEBUG | 285 | #ifdef CONFIG_MAC80211_HT_DEBUG |
288 | if (net_ratelimit()) | 286 | if (net_ratelimit()) |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 0c544074479e..db134b500caa 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -1551,27 +1551,54 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, | |||
1551 | return ieee80211_wk_cancel_remain_on_channel(sdata, cookie); | 1551 | return ieee80211_wk_cancel_remain_on_channel(sdata, cookie); |
1552 | } | 1552 | } |
1553 | 1553 | ||
1554 | static enum work_done_result | ||
1555 | ieee80211_offchan_tx_done(struct ieee80211_work *wk, struct sk_buff *skb) | ||
1556 | { | ||
1557 | /* | ||
1558 | * Use the data embedded in the work struct for reporting | ||
1559 | * here so if the driver mangled the SKB before dropping | ||
1560 | * it (which is the only way we really should get here) | ||
1561 | * then we don't report mangled data. | ||
1562 | * | ||
1563 | * If there was no wait time, then by the time we get here | ||
1564 | * the driver will likely not have reported the status yet, | ||
1565 | * so in that case userspace will have to deal with it. | ||
1566 | */ | ||
1567 | |||
1568 | if (wk->offchan_tx.wait && wk->offchan_tx.frame) | ||
1569 | cfg80211_mgmt_tx_status(wk->sdata->dev, | ||
1570 | (unsigned long) wk->offchan_tx.frame, | ||
1571 | wk->ie, wk->ie_len, false, GFP_KERNEL); | ||
1572 | |||
1573 | return WORK_DONE_DESTROY; | ||
1574 | } | ||
1575 | |||
1554 | static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | 1576 | static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, |
1555 | struct ieee80211_channel *chan, | 1577 | struct ieee80211_channel *chan, bool offchan, |
1556 | enum nl80211_channel_type channel_type, | 1578 | enum nl80211_channel_type channel_type, |
1557 | bool channel_type_valid, | 1579 | bool channel_type_valid, unsigned int wait, |
1558 | const u8 *buf, size_t len, u64 *cookie) | 1580 | const u8 *buf, size_t len, u64 *cookie) |
1559 | { | 1581 | { |
1560 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1582 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
1561 | struct ieee80211_local *local = sdata->local; | 1583 | struct ieee80211_local *local = sdata->local; |
1562 | struct sk_buff *skb; | 1584 | struct sk_buff *skb; |
1563 | struct sta_info *sta; | 1585 | struct sta_info *sta; |
1586 | struct ieee80211_work *wk; | ||
1564 | const struct ieee80211_mgmt *mgmt = (void *)buf; | 1587 | const struct ieee80211_mgmt *mgmt = (void *)buf; |
1565 | u32 flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX | | 1588 | u32 flags = IEEE80211_TX_INTFL_NL80211_FRAME_TX | |
1566 | IEEE80211_TX_CTL_REQ_TX_STATUS; | 1589 | IEEE80211_TX_CTL_REQ_TX_STATUS; |
1590 | bool is_offchan = false; | ||
1567 | 1591 | ||
1568 | /* Check that we are on the requested channel for transmission */ | 1592 | /* Check that we are on the requested channel for transmission */ |
1569 | if (chan != local->tmp_channel && | 1593 | if (chan != local->tmp_channel && |
1570 | chan != local->oper_channel) | 1594 | chan != local->oper_channel) |
1571 | return -EBUSY; | 1595 | is_offchan = true; |
1572 | if (channel_type_valid && | 1596 | if (channel_type_valid && |
1573 | (channel_type != local->tmp_channel_type && | 1597 | (channel_type != local->tmp_channel_type && |
1574 | channel_type != local->_oper_channel_type)) | 1598 | channel_type != local->_oper_channel_type)) |
1599 | is_offchan = true; | ||
1600 | |||
1601 | if (is_offchan && !offchan) | ||
1575 | return -EBUSY; | 1602 | return -EBUSY; |
1576 | 1603 | ||
1577 | switch (sdata->vif.type) { | 1604 | switch (sdata->vif.type) { |
@@ -1605,12 +1632,70 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev, | |||
1605 | IEEE80211_SKB_CB(skb)->flags = flags; | 1632 | IEEE80211_SKB_CB(skb)->flags = flags; |
1606 | 1633 | ||
1607 | skb->dev = sdata->dev; | 1634 | skb->dev = sdata->dev; |
1608 | ieee80211_tx_skb(sdata, skb); | ||
1609 | 1635 | ||
1610 | *cookie = (unsigned long) skb; | 1636 | *cookie = (unsigned long) skb; |
1637 | |||
1638 | /* | ||
1639 | * Can transmit right away if the channel was the | ||
1640 | * right one and there's no wait involved... If a | ||
1641 | * wait is involved, we might otherwise not be on | ||
1642 | * the right channel for long enough! | ||
1643 | */ | ||
1644 | if (!is_offchan && !wait && !sdata->vif.bss_conf.idle) { | ||
1645 | ieee80211_tx_skb(sdata, skb); | ||
1646 | return 0; | ||
1647 | } | ||
1648 | |||
1649 | wk = kzalloc(sizeof(*wk) + len, GFP_KERNEL); | ||
1650 | if (!wk) { | ||
1651 | kfree_skb(skb); | ||
1652 | return -ENOMEM; | ||
1653 | } | ||
1654 | |||
1655 | wk->type = IEEE80211_WORK_OFFCHANNEL_TX; | ||
1656 | wk->chan = chan; | ||
1657 | wk->sdata = sdata; | ||
1658 | wk->done = ieee80211_offchan_tx_done; | ||
1659 | wk->offchan_tx.frame = skb; | ||
1660 | wk->offchan_tx.wait = wait; | ||
1661 | wk->ie_len = len; | ||
1662 | memcpy(wk->ie, buf, len); | ||
1663 | |||
1664 | ieee80211_add_work(wk); | ||
1611 | return 0; | 1665 | return 0; |
1612 | } | 1666 | } |
1613 | 1667 | ||
1668 | static int ieee80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, | ||
1669 | struct net_device *dev, | ||
1670 | u64 cookie) | ||
1671 | { | ||
1672 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
1673 | struct ieee80211_local *local = sdata->local; | ||
1674 | struct ieee80211_work *wk; | ||
1675 | int ret = -ENOENT; | ||
1676 | |||
1677 | mutex_lock(&local->mtx); | ||
1678 | list_for_each_entry(wk, &local->work_list, list) { | ||
1679 | if (wk->sdata != sdata) | ||
1680 | continue; | ||
1681 | |||
1682 | if (wk->type != IEEE80211_WORK_OFFCHANNEL_TX) | ||
1683 | continue; | ||
1684 | |||
1685 | if (cookie != (unsigned long) wk->offchan_tx.frame) | ||
1686 | continue; | ||
1687 | |||
1688 | wk->timeout = jiffies; | ||
1689 | |||
1690 | ieee80211_queue_work(&local->hw, &local->work_work); | ||
1691 | ret = 0; | ||
1692 | break; | ||
1693 | } | ||
1694 | mutex_unlock(&local->mtx); | ||
1695 | |||
1696 | return ret; | ||
1697 | } | ||
1698 | |||
1614 | static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, | 1699 | static void ieee80211_mgmt_frame_register(struct wiphy *wiphy, |
1615 | struct net_device *dev, | 1700 | struct net_device *dev, |
1616 | u16 frame_type, bool reg) | 1701 | u16 frame_type, bool reg) |
@@ -1695,6 +1780,7 @@ struct cfg80211_ops mac80211_config_ops = { | |||
1695 | .remain_on_channel = ieee80211_remain_on_channel, | 1780 | .remain_on_channel = ieee80211_remain_on_channel, |
1696 | .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, | 1781 | .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel, |
1697 | .mgmt_tx = ieee80211_mgmt_tx, | 1782 | .mgmt_tx = ieee80211_mgmt_tx, |
1783 | .mgmt_tx_cancel_wait = ieee80211_mgmt_tx_cancel_wait, | ||
1698 | .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config, | 1784 | .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config, |
1699 | .mgmt_frame_register = ieee80211_mgmt_frame_register, | 1785 | .mgmt_frame_register = ieee80211_mgmt_frame_register, |
1700 | .set_antenna = ieee80211_set_antenna, | 1786 | .set_antenna = ieee80211_set_antenna, |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index f0fce37f4069..8bb5af85f469 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
@@ -112,34 +112,35 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, | |||
112 | char buf[71 + STA_TID_NUM * 40], *p = buf; | 112 | char buf[71 + STA_TID_NUM * 40], *p = buf; |
113 | int i; | 113 | int i; |
114 | struct sta_info *sta = file->private_data; | 114 | struct sta_info *sta = file->private_data; |
115 | struct tid_ampdu_rx *tid_rx; | ||
116 | struct tid_ampdu_tx *tid_tx; | ||
117 | |||
118 | rcu_read_lock(); | ||
115 | 119 | ||
116 | spin_lock_bh(&sta->lock); | ||
117 | p += scnprintf(p, sizeof(buf) + buf - p, "next dialog_token: %#02x\n", | 120 | p += scnprintf(p, sizeof(buf) + buf - p, "next dialog_token: %#02x\n", |
118 | sta->ampdu_mlme.dialog_token_allocator + 1); | 121 | sta->ampdu_mlme.dialog_token_allocator + 1); |
119 | p += scnprintf(p, sizeof(buf) + buf - p, | 122 | p += scnprintf(p, sizeof(buf) + buf - p, |
120 | "TID\t\tRX active\tDTKN\tSSN\t\tTX\tDTKN\tpending\n"); | 123 | "TID\t\tRX active\tDTKN\tSSN\t\tTX\tDTKN\tpending\n"); |
124 | |||
121 | for (i = 0; i < STA_TID_NUM; i++) { | 125 | for (i = 0; i < STA_TID_NUM; i++) { |
126 | tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[i]); | ||
127 | tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[i]); | ||
128 | |||
122 | p += scnprintf(p, sizeof(buf) + buf - p, "%02d", i); | 129 | p += scnprintf(p, sizeof(buf) + buf - p, "%02d", i); |
123 | p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", | 130 | p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", !!tid_rx); |
124 | !!sta->ampdu_mlme.tid_rx[i]); | ||
125 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x", | 131 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x", |
126 | sta->ampdu_mlme.tid_rx[i] ? | 132 | tid_rx ? tid_rx->dialog_token : 0); |
127 | sta->ampdu_mlme.tid_rx[i]->dialog_token : 0); | ||
128 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x", | 133 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x", |
129 | sta->ampdu_mlme.tid_rx[i] ? | 134 | tid_rx ? tid_rx->ssn : 0); |
130 | sta->ampdu_mlme.tid_rx[i]->ssn : 0); | ||
131 | 135 | ||
132 | p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", | 136 | p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", !!tid_tx); |
133 | !!sta->ampdu_mlme.tid_tx[i]); | ||
134 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x", | 137 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x", |
135 | sta->ampdu_mlme.tid_tx[i] ? | 138 | tid_tx ? tid_tx->dialog_token : 0); |
136 | sta->ampdu_mlme.tid_tx[i]->dialog_token : 0); | ||
137 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%03d", | 139 | p += scnprintf(p, sizeof(buf) + buf - p, "\t%03d", |
138 | sta->ampdu_mlme.tid_tx[i] ? | 140 | tid_tx ? skb_queue_len(&tid_tx->pending) : 0); |
139 | skb_queue_len(&sta->ampdu_mlme.tid_tx[i]->pending) : 0); | ||
140 | p += scnprintf(p, sizeof(buf) + buf - p, "\n"); | 141 | p += scnprintf(p, sizeof(buf) + buf - p, "\n"); |
141 | } | 142 | } |
142 | spin_unlock_bh(&sta->lock); | 143 | rcu_read_unlock(); |
143 | 144 | ||
144 | return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); | 145 | return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); |
145 | } | 146 | } |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 5bc0745368fe..66b0b52b828d 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -260,6 +260,7 @@ enum ieee80211_work_type { | |||
260 | IEEE80211_WORK_ASSOC_BEACON_WAIT, | 260 | IEEE80211_WORK_ASSOC_BEACON_WAIT, |
261 | IEEE80211_WORK_ASSOC, | 261 | IEEE80211_WORK_ASSOC, |
262 | IEEE80211_WORK_REMAIN_ON_CHANNEL, | 262 | IEEE80211_WORK_REMAIN_ON_CHANNEL, |
263 | IEEE80211_WORK_OFFCHANNEL_TX, | ||
263 | }; | 264 | }; |
264 | 265 | ||
265 | /** | 266 | /** |
@@ -320,6 +321,10 @@ struct ieee80211_work { | |||
320 | struct { | 321 | struct { |
321 | u32 duration; | 322 | u32 duration; |
322 | } remain; | 323 | } remain; |
324 | struct { | ||
325 | struct sk_buff *frame; | ||
326 | u32 wait; | ||
327 | } offchan_tx; | ||
323 | }; | 328 | }; |
324 | 329 | ||
325 | int ie_len; | 330 | int ie_len; |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 55337709de41..6289525c0998 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -538,6 +538,8 @@ static void ieee80211_release_reorder_frame(struct ieee80211_hw *hw, | |||
538 | { | 538 | { |
539 | struct sk_buff *skb = tid_agg_rx->reorder_buf[index]; | 539 | struct sk_buff *skb = tid_agg_rx->reorder_buf[index]; |
540 | 540 | ||
541 | lockdep_assert_held(&tid_agg_rx->reorder_lock); | ||
542 | |||
541 | if (!skb) | 543 | if (!skb) |
542 | goto no_frame; | 544 | goto no_frame; |
543 | 545 | ||
@@ -557,6 +559,8 @@ static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw, | |||
557 | { | 559 | { |
558 | int index; | 560 | int index; |
559 | 561 | ||
562 | lockdep_assert_held(&tid_agg_rx->reorder_lock); | ||
563 | |||
560 | while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) { | 564 | while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) { |
561 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | 565 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % |
562 | tid_agg_rx->buf_size; | 566 | tid_agg_rx->buf_size; |
@@ -581,6 +585,8 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw, | |||
581 | { | 585 | { |
582 | int index, j; | 586 | int index, j; |
583 | 587 | ||
588 | lockdep_assert_held(&tid_agg_rx->reorder_lock); | ||
589 | |||
584 | /* release the buffer until next missing frame */ | 590 | /* release the buffer until next missing frame */ |
585 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | 591 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % |
586 | tid_agg_rx->buf_size; | 592 | tid_agg_rx->buf_size; |
@@ -683,10 +689,11 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
683 | int index; | 689 | int index; |
684 | bool ret = true; | 690 | bool ret = true; |
685 | 691 | ||
692 | spin_lock(&tid_agg_rx->reorder_lock); | ||
693 | |||
686 | buf_size = tid_agg_rx->buf_size; | 694 | buf_size = tid_agg_rx->buf_size; |
687 | head_seq_num = tid_agg_rx->head_seq_num; | 695 | head_seq_num = tid_agg_rx->head_seq_num; |
688 | 696 | ||
689 | spin_lock(&tid_agg_rx->reorder_lock); | ||
690 | /* frame with out of date sequence number */ | 697 | /* frame with out of date sequence number */ |
691 | if (seq_less(mpdu_seq_num, head_seq_num)) { | 698 | if (seq_less(mpdu_seq_num, head_seq_num)) { |
692 | dev_kfree_skb(skb); | 699 | dev_kfree_skb(skb); |
@@ -1870,9 +1877,8 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx) | |||
1870 | dev->stats.rx_packets++; | 1877 | dev->stats.rx_packets++; |
1871 | dev->stats.rx_bytes += rx->skb->len; | 1878 | dev->stats.rx_bytes += rx->skb->len; |
1872 | 1879 | ||
1873 | if (ieee80211_is_data(hdr->frame_control) && | 1880 | if (local->ps_sdata && local->hw.conf.dynamic_ps_timeout > 0 && |
1874 | !is_multicast_ether_addr(hdr->addr1) && | 1881 | !is_multicast_ether_addr(((struct ethhdr *)rx->skb->data)->h_dest)) { |
1875 | local->hw.conf.dynamic_ps_timeout > 0 && local->ps_sdata) { | ||
1876 | mod_timer(&local->dynamic_ps_timer, jiffies + | 1882 | mod_timer(&local->dynamic_ps_timer, jiffies + |
1877 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); | 1883 | msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout)); |
1878 | } | 1884 | } |
@@ -1921,9 +1927,12 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames) | |||
1921 | mod_timer(&tid_agg_rx->session_timer, | 1927 | mod_timer(&tid_agg_rx->session_timer, |
1922 | TU_TO_EXP_TIME(tid_agg_rx->timeout)); | 1928 | TU_TO_EXP_TIME(tid_agg_rx->timeout)); |
1923 | 1929 | ||
1930 | spin_lock(&tid_agg_rx->reorder_lock); | ||
1924 | /* release stored frames up to start of BAR */ | 1931 | /* release stored frames up to start of BAR */ |
1925 | ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num, | 1932 | ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num, |
1926 | frames); | 1933 | frames); |
1934 | spin_unlock(&tid_agg_rx->reorder_lock); | ||
1935 | |||
1927 | kfree_skb(skb); | 1936 | kfree_skb(skb); |
1928 | return RX_QUEUED; | 1937 | return RX_QUEUED; |
1929 | } | 1938 | } |
@@ -2519,9 +2528,8 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx) | |||
2519 | } | 2528 | } |
2520 | 2529 | ||
2521 | /* | 2530 | /* |
2522 | * This function makes calls into the RX path. Therefore the | 2531 | * This function makes calls into the RX path, therefore |
2523 | * caller must hold the sta_info->lock and everything has to | 2532 | * it has to be invoked under RCU read lock. |
2524 | * be under rcu_read_lock protection as well. | ||
2525 | */ | 2533 | */ |
2526 | void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) | 2534 | void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) |
2527 | { | 2535 | { |
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index b562d9b6a702..05f11302443b 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
@@ -81,13 +81,14 @@ enum ieee80211_sta_info_flags { | |||
81 | * @stop_initiator: initiator of a session stop | 81 | * @stop_initiator: initiator of a session stop |
82 | * @tx_stop: TX DelBA frame when stopping | 82 | * @tx_stop: TX DelBA frame when stopping |
83 | * | 83 | * |
84 | * This structure is protected by RCU and the per-station | 84 | * This structure's lifetime is managed by RCU, assignments to |
85 | * spinlock. Assignments to the array holding it must hold | 85 | * the array holding it must hold the aggregation mutex. |
86 | * the spinlock, only the TX path can access it under RCU | 86 | * |
87 | * lock-free if, and only if, the state has the flag | 87 | * The TX path can access it under RCU lock-free if, and |
88 | * %HT_AGG_STATE_OPERATIONAL set. Otherwise, the TX path | 88 | * only if, the state has the flag %HT_AGG_STATE_OPERATIONAL |
89 | * must also acquire the spinlock and re-check the state, | 89 | * set. Otherwise, the TX path must also acquire the spinlock |
90 | * see comments in the tx code touching it. | 90 | * and re-check the state, see comments in the tx code |
91 | * touching it. | ||
91 | */ | 92 | */ |
92 | struct tid_ampdu_tx { | 93 | struct tid_ampdu_tx { |
93 | struct rcu_head rcu_head; | 94 | struct rcu_head rcu_head; |
@@ -115,15 +116,13 @@ struct tid_ampdu_tx { | |||
115 | * @rcu_head: RCU head used for freeing this struct | 116 | * @rcu_head: RCU head used for freeing this struct |
116 | * @reorder_lock: serializes access to reorder buffer, see below. | 117 | * @reorder_lock: serializes access to reorder buffer, see below. |
117 | * | 118 | * |
118 | * This structure is protected by RCU and the per-station | 119 | * This structure's lifetime is managed by RCU, assignments to |
119 | * spinlock. Assignments to the array holding it must hold | 120 | * the array holding it must hold the aggregation mutex. |
120 | * the spinlock. | ||
121 | * | 121 | * |
122 | * The @reorder_lock is used to protect the variables and | 122 | * The @reorder_lock is used to protect the members of this |
123 | * arrays such as @reorder_buf, @reorder_time, @head_seq_num, | 123 | * struct, except for @timeout, @buf_size and @dialog_token, |
124 | * @stored_mpdu_num and @reorder_time from being corrupted by | 124 | * which are constant across the lifetime of the struct (the |
125 | * concurrent access of the RX path and the expired frame | 125 | * dialog token being used only for debugging). |
126 | * release timer. | ||
127 | */ | 126 | */ |
128 | struct tid_ampdu_rx { | 127 | struct tid_ampdu_rx { |
129 | struct rcu_head rcu_head; | 128 | struct rcu_head rcu_head; |
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index bed7e32ed908..4958710a7d92 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
@@ -321,10 +321,23 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
321 | msecs_to_jiffies(10)); | 321 | msecs_to_jiffies(10)); |
322 | } | 322 | } |
323 | 323 | ||
324 | if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) | 324 | if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) { |
325 | struct ieee80211_work *wk; | ||
326 | |||
327 | rcu_read_lock(); | ||
328 | list_for_each_entry_rcu(wk, &local->work_list, list) { | ||
329 | if (wk->type != IEEE80211_WORK_OFFCHANNEL_TX) | ||
330 | continue; | ||
331 | if (wk->offchan_tx.frame != skb) | ||
332 | continue; | ||
333 | wk->offchan_tx.frame = NULL; | ||
334 | break; | ||
335 | } | ||
336 | rcu_read_unlock(); | ||
325 | cfg80211_mgmt_tx_status( | 337 | cfg80211_mgmt_tx_status( |
326 | skb->dev, (unsigned long) skb, skb->data, skb->len, | 338 | skb->dev, (unsigned long) skb, skb->data, skb->len, |
327 | !!(info->flags & IEEE80211_TX_STAT_ACK), GFP_ATOMIC); | 339 | !!(info->flags & IEEE80211_TX_STAT_ACK), GFP_ATOMIC); |
340 | } | ||
328 | 341 | ||
329 | /* this was a transmitted frame, but now we want to reuse it */ | 342 | /* this was a transmitted frame, but now we want to reuse it */ |
330 | skb_orphan(skb); | 343 | skb_orphan(skb); |
diff --git a/net/mac80211/work.c b/net/mac80211/work.c index ae344d1ba056..2b5c3f267198 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c | |||
@@ -561,6 +561,25 @@ ieee80211_remain_on_channel_timeout(struct ieee80211_work *wk) | |||
561 | } | 561 | } |
562 | 562 | ||
563 | static enum work_action __must_check | 563 | static enum work_action __must_check |
564 | ieee80211_offchannel_tx(struct ieee80211_work *wk) | ||
565 | { | ||
566 | if (!wk->started) { | ||
567 | wk->timeout = jiffies + msecs_to_jiffies(wk->offchan_tx.wait); | ||
568 | |||
569 | /* | ||
570 | * After this, offchan_tx.frame remains but now is no | ||
571 | * longer a valid pointer -- we still need it as the | ||
572 | * cookie for canceling this work. | ||
573 | */ | ||
574 | ieee80211_tx_skb(wk->sdata, wk->offchan_tx.frame); | ||
575 | |||
576 | return WORK_ACT_NONE; | ||
577 | } | ||
578 | |||
579 | return WORK_ACT_TIMEOUT; | ||
580 | } | ||
581 | |||
582 | static enum work_action __must_check | ||
564 | ieee80211_assoc_beacon_wait(struct ieee80211_work *wk) | 583 | ieee80211_assoc_beacon_wait(struct ieee80211_work *wk) |
565 | { | 584 | { |
566 | if (wk->started) | 585 | if (wk->started) |
@@ -955,6 +974,9 @@ static void ieee80211_work_work(struct work_struct *work) | |||
955 | case IEEE80211_WORK_REMAIN_ON_CHANNEL: | 974 | case IEEE80211_WORK_REMAIN_ON_CHANNEL: |
956 | rma = ieee80211_remain_on_channel_timeout(wk); | 975 | rma = ieee80211_remain_on_channel_timeout(wk); |
957 | break; | 976 | break; |
977 | case IEEE80211_WORK_OFFCHANNEL_TX: | ||
978 | rma = ieee80211_offchannel_tx(wk); | ||
979 | break; | ||
958 | case IEEE80211_WORK_ASSOC_BEACON_WAIT: | 980 | case IEEE80211_WORK_ASSOC_BEACON_WAIT: |
959 | rma = ieee80211_assoc_beacon_wait(wk); | 981 | rma = ieee80211_assoc_beacon_wait(wk); |
960 | break; | 982 | break; |
diff --git a/net/wireless/core.h b/net/wireless/core.h index 6583cca0e2ee..ee80ad8dc655 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
@@ -341,9 +341,9 @@ void cfg80211_mlme_unregister_socket(struct wireless_dev *wdev, u32 nlpid); | |||
341 | void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev); | 341 | void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev); |
342 | int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, | 342 | int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, |
343 | struct net_device *dev, | 343 | struct net_device *dev, |
344 | struct ieee80211_channel *chan, | 344 | struct ieee80211_channel *chan, bool offchan, |
345 | enum nl80211_channel_type channel_type, | 345 | enum nl80211_channel_type channel_type, |
346 | bool channel_type_valid, | 346 | bool channel_type_valid, unsigned int wait, |
347 | const u8 *buf, size_t len, u64 *cookie); | 347 | const u8 *buf, size_t len, u64 *cookie); |
348 | 348 | ||
349 | /* SME */ | 349 | /* SME */ |
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 6980a0c315b2..d7680f2a4c5b 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
@@ -864,9 +864,9 @@ void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev) | |||
864 | 864 | ||
865 | int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, | 865 | int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, |
866 | struct net_device *dev, | 866 | struct net_device *dev, |
867 | struct ieee80211_channel *chan, | 867 | struct ieee80211_channel *chan, bool offchan, |
868 | enum nl80211_channel_type channel_type, | 868 | enum nl80211_channel_type channel_type, |
869 | bool channel_type_valid, | 869 | bool channel_type_valid, unsigned int wait, |
870 | const u8 *buf, size_t len, u64 *cookie) | 870 | const u8 *buf, size_t len, u64 *cookie) |
871 | { | 871 | { |
872 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 872 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
@@ -946,8 +946,9 @@ int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev, | |||
946 | return -EINVAL; | 946 | return -EINVAL; |
947 | 947 | ||
948 | /* Transmit the Action frame as requested by user space */ | 948 | /* Transmit the Action frame as requested by user space */ |
949 | return rdev->ops->mgmt_tx(&rdev->wiphy, dev, chan, channel_type, | 949 | return rdev->ops->mgmt_tx(&rdev->wiphy, dev, chan, offchan, |
950 | channel_type_valid, buf, len, cookie); | 950 | channel_type, channel_type_valid, |
951 | wait, buf, len, cookie); | ||
951 | } | 952 | } |
952 | 953 | ||
953 | bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf, | 954 | bool cfg80211_rx_mgmt(struct net_device *dev, int freq, const u8 *buf, |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 67ff7e92cb99..960be4e650f0 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -163,16 +163,13 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
163 | [NL80211_ATTR_CQM] = { .type = NLA_NESTED, }, | 163 | [NL80211_ATTR_CQM] = { .type = NLA_NESTED, }, |
164 | [NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG }, | 164 | [NL80211_ATTR_LOCAL_STATE_CHANGE] = { .type = NLA_FLAG }, |
165 | [NL80211_ATTR_AP_ISOLATE] = { .type = NLA_U8 }, | 165 | [NL80211_ATTR_AP_ISOLATE] = { .type = NLA_U8 }, |
166 | |||
167 | [NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 }, | 166 | [NL80211_ATTR_WIPHY_TX_POWER_SETTING] = { .type = NLA_U32 }, |
168 | [NL80211_ATTR_WIPHY_TX_POWER_LEVEL] = { .type = NLA_U32 }, | 167 | [NL80211_ATTR_WIPHY_TX_POWER_LEVEL] = { .type = NLA_U32 }, |
169 | |||
170 | [NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 }, | 168 | [NL80211_ATTR_FRAME_TYPE] = { .type = NLA_U16 }, |
171 | |||
172 | [NL80211_ATTR_WIPHY_ANTENNA_TX] = { .type = NLA_U32 }, | 169 | [NL80211_ATTR_WIPHY_ANTENNA_TX] = { .type = NLA_U32 }, |
173 | [NL80211_ATTR_WIPHY_ANTENNA_RX] = { .type = NLA_U32 }, | 170 | [NL80211_ATTR_WIPHY_ANTENNA_RX] = { .type = NLA_U32 }, |
174 | |||
175 | [NL80211_ATTR_MCAST_RATE] = { .type = NLA_U32 }, | 171 | [NL80211_ATTR_MCAST_RATE] = { .type = NLA_U32 }, |
172 | [NL80211_ATTR_OFFCHANNEL_TX_OK] = { .type = NLA_FLAG }, | ||
176 | }; | 173 | }; |
177 | 174 | ||
178 | /* policy for the key attributes */ | 175 | /* policy for the key attributes */ |
@@ -677,6 +674,7 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
677 | CMD(remain_on_channel, REMAIN_ON_CHANNEL); | 674 | CMD(remain_on_channel, REMAIN_ON_CHANNEL); |
678 | CMD(set_bitrate_mask, SET_TX_BITRATE_MASK); | 675 | CMD(set_bitrate_mask, SET_TX_BITRATE_MASK); |
679 | CMD(mgmt_tx, FRAME); | 676 | CMD(mgmt_tx, FRAME); |
677 | CMD(mgmt_tx_cancel_wait, FRAME_WAIT_CANCEL); | ||
680 | if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { | 678 | if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { |
681 | i++; | 679 | i++; |
682 | NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); | 680 | NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); |
@@ -698,6 +696,10 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags, | |||
698 | 696 | ||
699 | nla_nest_end(msg, nl_cmds); | 697 | nla_nest_end(msg, nl_cmds); |
700 | 698 | ||
699 | /* for now at least assume all drivers have it */ | ||
700 | if (dev->ops->mgmt_tx) | ||
701 | NLA_PUT_FLAG(msg, NL80211_ATTR_OFFCHANNEL_TX_OK); | ||
702 | |||
701 | if (mgmt_stypes) { | 703 | if (mgmt_stypes) { |
702 | u16 stypes; | 704 | u16 stypes; |
703 | struct nlattr *nl_ftypes, *nl_ifs; | 705 | struct nlattr *nl_ftypes, *nl_ifs; |
@@ -4244,6 +4246,8 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
4244 | void *hdr; | 4246 | void *hdr; |
4245 | u64 cookie; | 4247 | u64 cookie; |
4246 | struct sk_buff *msg; | 4248 | struct sk_buff *msg; |
4249 | unsigned int wait = 0; | ||
4250 | bool offchan; | ||
4247 | 4251 | ||
4248 | if (!info->attrs[NL80211_ATTR_FRAME] || | 4252 | if (!info->attrs[NL80211_ATTR_FRAME] || |
4249 | !info->attrs[NL80211_ATTR_WIPHY_FREQ]) | 4253 | !info->attrs[NL80211_ATTR_WIPHY_FREQ]) |
@@ -4260,6 +4264,12 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
4260 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) | 4264 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) |
4261 | return -EOPNOTSUPP; | 4265 | return -EOPNOTSUPP; |
4262 | 4266 | ||
4267 | if (info->attrs[NL80211_ATTR_DURATION]) { | ||
4268 | if (!rdev->ops->mgmt_tx_cancel_wait) | ||
4269 | return -EINVAL; | ||
4270 | wait = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]); | ||
4271 | } | ||
4272 | |||
4263 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { | 4273 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { |
4264 | channel_type = nla_get_u32( | 4274 | channel_type = nla_get_u32( |
4265 | info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]); | 4275 | info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]); |
@@ -4271,6 +4281,8 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
4271 | channel_type_valid = true; | 4281 | channel_type_valid = true; |
4272 | } | 4282 | } |
4273 | 4283 | ||
4284 | offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK]; | ||
4285 | |||
4274 | freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); | 4286 | freq = nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ]); |
4275 | chan = rdev_freq_to_chan(rdev, freq, channel_type); | 4287 | chan = rdev_freq_to_chan(rdev, freq, channel_type); |
4276 | if (chan == NULL) | 4288 | if (chan == NULL) |
@@ -4287,8 +4299,8 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
4287 | err = PTR_ERR(hdr); | 4299 | err = PTR_ERR(hdr); |
4288 | goto free_msg; | 4300 | goto free_msg; |
4289 | } | 4301 | } |
4290 | err = cfg80211_mlme_mgmt_tx(rdev, dev, chan, channel_type, | 4302 | err = cfg80211_mlme_mgmt_tx(rdev, dev, chan, offchan, channel_type, |
4291 | channel_type_valid, | 4303 | channel_type_valid, wait, |
4292 | nla_data(info->attrs[NL80211_ATTR_FRAME]), | 4304 | nla_data(info->attrs[NL80211_ATTR_FRAME]), |
4293 | nla_len(info->attrs[NL80211_ATTR_FRAME]), | 4305 | nla_len(info->attrs[NL80211_ATTR_FRAME]), |
4294 | &cookie); | 4306 | &cookie); |
@@ -4307,6 +4319,31 @@ static int nl80211_tx_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
4307 | return err; | 4319 | return err; |
4308 | } | 4320 | } |
4309 | 4321 | ||
4322 | static int nl80211_tx_mgmt_cancel_wait(struct sk_buff *skb, struct genl_info *info) | ||
4323 | { | ||
4324 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | ||
4325 | struct net_device *dev = info->user_ptr[1]; | ||
4326 | u64 cookie; | ||
4327 | |||
4328 | if (!info->attrs[NL80211_ATTR_COOKIE]) | ||
4329 | return -EINVAL; | ||
4330 | |||
4331 | if (!rdev->ops->mgmt_tx_cancel_wait) | ||
4332 | return -EOPNOTSUPP; | ||
4333 | |||
4334 | if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION && | ||
4335 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_ADHOC && | ||
4336 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_CLIENT && | ||
4337 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP && | ||
4338 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN && | ||
4339 | dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO) | ||
4340 | return -EOPNOTSUPP; | ||
4341 | |||
4342 | cookie = nla_get_u64(info->attrs[NL80211_ATTR_COOKIE]); | ||
4343 | |||
4344 | return rdev->ops->mgmt_tx_cancel_wait(&rdev->wiphy, dev, cookie); | ||
4345 | } | ||
4346 | |||
4310 | static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info) | 4347 | static int nl80211_set_power_save(struct sk_buff *skb, struct genl_info *info) |
4311 | { | 4348 | { |
4312 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 4349 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
@@ -4880,6 +4917,14 @@ static struct genl_ops nl80211_ops[] = { | |||
4880 | NL80211_FLAG_NEED_RTNL, | 4917 | NL80211_FLAG_NEED_RTNL, |
4881 | }, | 4918 | }, |
4882 | { | 4919 | { |
4920 | .cmd = NL80211_CMD_FRAME_WAIT_CANCEL, | ||
4921 | .doit = nl80211_tx_mgmt_cancel_wait, | ||
4922 | .policy = nl80211_policy, | ||
4923 | .flags = GENL_ADMIN_PERM, | ||
4924 | .internal_flags = NL80211_FLAG_NEED_NETDEV_UP | | ||
4925 | NL80211_FLAG_NEED_RTNL, | ||
4926 | }, | ||
4927 | { | ||
4883 | .cmd = NL80211_CMD_SET_POWER_SAVE, | 4928 | .cmd = NL80211_CMD_SET_POWER_SAVE, |
4884 | .doit = nl80211_set_power_save, | 4929 | .doit = nl80211_set_power_save, |
4885 | .policy = nl80211_policy, | 4930 | .policy = nl80211_policy, |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 044e77898512..6e50ccd8c532 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
@@ -1433,7 +1433,7 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy, | |||
1433 | } | 1433 | } |
1434 | 1434 | ||
1435 | xdst->route = dst; | 1435 | xdst->route = dst; |
1436 | memcpy(&dst1->metrics, &dst->metrics, sizeof(dst->metrics)); | 1436 | dst_copy_metrics(dst1, dst); |
1437 | 1437 | ||
1438 | if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) { | 1438 | if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) { |
1439 | family = xfrm[i]->props.family; | 1439 | family = xfrm[i]->props.family; |
@@ -2271,7 +2271,7 @@ static void xfrm_init_pmtu(struct dst_entry *dst) | |||
2271 | if (pmtu > route_mtu_cached) | 2271 | if (pmtu > route_mtu_cached) |
2272 | pmtu = route_mtu_cached; | 2272 | pmtu = route_mtu_cached; |
2273 | 2273 | ||
2274 | dst->metrics[RTAX_MTU-1] = pmtu; | 2274 | dst_metric_set(dst, RTAX_MTU, pmtu); |
2275 | } while ((dst = dst->next)); | 2275 | } while ((dst = dst->next)); |
2276 | } | 2276 | } |
2277 | 2277 | ||
@@ -2349,7 +2349,7 @@ static int xfrm_bundle_ok(struct xfrm_policy *pol, struct xfrm_dst *first, | |||
2349 | mtu = xfrm_state_mtu(dst->xfrm, mtu); | 2349 | mtu = xfrm_state_mtu(dst->xfrm, mtu); |
2350 | if (mtu > last->route_mtu_cached) | 2350 | if (mtu > last->route_mtu_cached) |
2351 | mtu = last->route_mtu_cached; | 2351 | mtu = last->route_mtu_cached; |
2352 | dst->metrics[RTAX_MTU-1] = mtu; | 2352 | dst_metric_set(dst, RTAX_MTU, mtu); |
2353 | 2353 | ||
2354 | if (last == first) | 2354 | if (last == first) |
2355 | break; | 2355 | break; |