diff options
Diffstat (limited to 'net')
418 files changed, 17055 insertions, 8204 deletions
diff --git a/net/8021q/vlan.h b/net/8021q/vlan.h index 5704ed9c3a23..9d010a09ab98 100644 --- a/net/8021q/vlan.h +++ b/net/8021q/vlan.h | |||
| @@ -38,9 +38,9 @@ struct vlan_info { | |||
| 38 | static inline unsigned int vlan_proto_idx(__be16 proto) | 38 | static inline unsigned int vlan_proto_idx(__be16 proto) |
| 39 | { | 39 | { |
| 40 | switch (proto) { | 40 | switch (proto) { |
| 41 | case __constant_htons(ETH_P_8021Q): | 41 | case htons(ETH_P_8021Q): |
| 42 | return VLAN_PROTO_8021Q; | 42 | return VLAN_PROTO_8021Q; |
| 43 | case __constant_htons(ETH_P_8021AD): | 43 | case htons(ETH_P_8021AD): |
| 44 | return VLAN_PROTO_8021AD; | 44 | return VLAN_PROTO_8021AD; |
| 45 | default: | 45 | default: |
| 46 | BUG(); | 46 | BUG(); |
diff --git a/net/8021q/vlan_core.c b/net/8021q/vlan_core.c index 6ee48aac776f..3c32bd257b73 100644 --- a/net/8021q/vlan_core.c +++ b/net/8021q/vlan_core.c | |||
| @@ -22,11 +22,11 @@ bool vlan_do_receive(struct sk_buff **skbp) | |||
| 22 | return false; | 22 | return false; |
| 23 | 23 | ||
| 24 | skb->dev = vlan_dev; | 24 | skb->dev = vlan_dev; |
| 25 | if (skb->pkt_type == PACKET_OTHERHOST) { | 25 | if (unlikely(skb->pkt_type == PACKET_OTHERHOST)) { |
| 26 | /* Our lower layer thinks this is not local, let's make sure. | 26 | /* Our lower layer thinks this is not local, let's make sure. |
| 27 | * This allows the VLAN to have a different MAC than the | 27 | * This allows the VLAN to have a different MAC than the |
| 28 | * underlying device, and still route correctly. */ | 28 | * underlying device, and still route correctly. */ |
| 29 | if (ether_addr_equal(eth_hdr(skb)->h_dest, vlan_dev->dev_addr)) | 29 | if (ether_addr_equal_64bits(eth_hdr(skb)->h_dest, vlan_dev->dev_addr)) |
| 30 | skb->pkt_type = PACKET_HOST; | 30 | skb->pkt_type = PACKET_HOST; |
| 31 | } | 31 | } |
| 32 | 32 | ||
| @@ -106,6 +106,12 @@ u16 vlan_dev_vlan_id(const struct net_device *dev) | |||
| 106 | } | 106 | } |
| 107 | EXPORT_SYMBOL(vlan_dev_vlan_id); | 107 | EXPORT_SYMBOL(vlan_dev_vlan_id); |
| 108 | 108 | ||
| 109 | __be16 vlan_dev_vlan_proto(const struct net_device *dev) | ||
| 110 | { | ||
| 111 | return vlan_dev_priv(dev)->vlan_proto; | ||
| 112 | } | ||
| 113 | EXPORT_SYMBOL(vlan_dev_vlan_proto); | ||
| 114 | |||
| 109 | static struct sk_buff *vlan_reorder_header(struct sk_buff *skb) | 115 | static struct sk_buff *vlan_reorder_header(struct sk_buff *skb) |
| 110 | { | 116 | { |
| 111 | if (skb_cow(skb, skb_headroom(skb)) < 0) | 117 | if (skb_cow(skb, skb_headroom(skb)) < 0) |
diff --git a/net/8021q/vlan_dev.c b/net/8021q/vlan_dev.c index 27bfe2f8e2de..6f142f03716d 100644 --- a/net/8021q/vlan_dev.c +++ b/net/8021q/vlan_dev.c | |||
| @@ -559,7 +559,7 @@ static const struct net_device_ops vlan_netdev_ops; | |||
| 559 | static int vlan_dev_init(struct net_device *dev) | 559 | static int vlan_dev_init(struct net_device *dev) |
| 560 | { | 560 | { |
| 561 | struct net_device *real_dev = vlan_dev_priv(dev)->real_dev; | 561 | struct net_device *real_dev = vlan_dev_priv(dev)->real_dev; |
| 562 | int subclass = 0, i; | 562 | int subclass = 0; |
| 563 | 563 | ||
| 564 | netif_carrier_off(dev); | 564 | netif_carrier_off(dev); |
| 565 | 565 | ||
| @@ -613,17 +613,10 @@ static int vlan_dev_init(struct net_device *dev) | |||
| 613 | 613 | ||
| 614 | vlan_dev_set_lockdep_class(dev, subclass); | 614 | vlan_dev_set_lockdep_class(dev, subclass); |
| 615 | 615 | ||
| 616 | vlan_dev_priv(dev)->vlan_pcpu_stats = alloc_percpu(struct vlan_pcpu_stats); | 616 | vlan_dev_priv(dev)->vlan_pcpu_stats = netdev_alloc_pcpu_stats(struct vlan_pcpu_stats); |
| 617 | if (!vlan_dev_priv(dev)->vlan_pcpu_stats) | 617 | if (!vlan_dev_priv(dev)->vlan_pcpu_stats) |
| 618 | return -ENOMEM; | 618 | return -ENOMEM; |
| 619 | 619 | ||
| 620 | for_each_possible_cpu(i) { | ||
| 621 | struct vlan_pcpu_stats *vlan_stat; | ||
| 622 | vlan_stat = per_cpu_ptr(vlan_dev_priv(dev)->vlan_pcpu_stats, i); | ||
| 623 | u64_stats_init(&vlan_stat->syncp); | ||
| 624 | } | ||
| 625 | |||
| 626 | |||
| 627 | return 0; | 620 | return 0; |
| 628 | } | 621 | } |
| 629 | 622 | ||
| @@ -689,13 +682,13 @@ static struct rtnl_link_stats64 *vlan_dev_get_stats64(struct net_device *dev, st | |||
| 689 | 682 | ||
| 690 | p = per_cpu_ptr(vlan_dev_priv(dev)->vlan_pcpu_stats, i); | 683 | p = per_cpu_ptr(vlan_dev_priv(dev)->vlan_pcpu_stats, i); |
| 691 | do { | 684 | do { |
| 692 | start = u64_stats_fetch_begin_bh(&p->syncp); | 685 | start = u64_stats_fetch_begin_irq(&p->syncp); |
| 693 | rxpackets = p->rx_packets; | 686 | rxpackets = p->rx_packets; |
| 694 | rxbytes = p->rx_bytes; | 687 | rxbytes = p->rx_bytes; |
| 695 | rxmulticast = p->rx_multicast; | 688 | rxmulticast = p->rx_multicast; |
| 696 | txpackets = p->tx_packets; | 689 | txpackets = p->tx_packets; |
| 697 | txbytes = p->tx_bytes; | 690 | txbytes = p->tx_bytes; |
| 698 | } while (u64_stats_fetch_retry_bh(&p->syncp, start)); | 691 | } while (u64_stats_fetch_retry_irq(&p->syncp, start)); |
| 699 | 692 | ||
| 700 | stats->rx_packets += rxpackets; | 693 | stats->rx_packets += rxpackets; |
| 701 | stats->rx_bytes += rxbytes; | 694 | stats->rx_bytes += rxbytes; |
| @@ -718,20 +711,19 @@ static void vlan_dev_poll_controller(struct net_device *dev) | |||
| 718 | return; | 711 | return; |
| 719 | } | 712 | } |
| 720 | 713 | ||
| 721 | static int vlan_dev_netpoll_setup(struct net_device *dev, struct netpoll_info *npinfo, | 714 | static int vlan_dev_netpoll_setup(struct net_device *dev, struct netpoll_info *npinfo) |
| 722 | gfp_t gfp) | ||
| 723 | { | 715 | { |
| 724 | struct vlan_dev_priv *vlan = vlan_dev_priv(dev); | 716 | struct vlan_dev_priv *vlan = vlan_dev_priv(dev); |
| 725 | struct net_device *real_dev = vlan->real_dev; | 717 | struct net_device *real_dev = vlan->real_dev; |
| 726 | struct netpoll *netpoll; | 718 | struct netpoll *netpoll; |
| 727 | int err = 0; | 719 | int err = 0; |
| 728 | 720 | ||
| 729 | netpoll = kzalloc(sizeof(*netpoll), gfp); | 721 | netpoll = kzalloc(sizeof(*netpoll), GFP_KERNEL); |
| 730 | err = -ENOMEM; | 722 | err = -ENOMEM; |
| 731 | if (!netpoll) | 723 | if (!netpoll) |
| 732 | goto out; | 724 | goto out; |
| 733 | 725 | ||
| 734 | err = __netpoll_setup(netpoll, real_dev, gfp); | 726 | err = __netpoll_setup(netpoll, real_dev); |
| 735 | if (err) { | 727 | if (err) { |
| 736 | kfree(netpoll); | 728 | kfree(netpoll); |
| 737 | goto out; | 729 | goto out; |
diff --git a/net/8021q/vlan_netlink.c b/net/8021q/vlan_netlink.c index c7e634af8516..8ac8a5cc2143 100644 --- a/net/8021q/vlan_netlink.c +++ b/net/8021q/vlan_netlink.c | |||
| @@ -56,8 +56,8 @@ static int vlan_validate(struct nlattr *tb[], struct nlattr *data[]) | |||
| 56 | 56 | ||
| 57 | if (data[IFLA_VLAN_PROTOCOL]) { | 57 | if (data[IFLA_VLAN_PROTOCOL]) { |
| 58 | switch (nla_get_be16(data[IFLA_VLAN_PROTOCOL])) { | 58 | switch (nla_get_be16(data[IFLA_VLAN_PROTOCOL])) { |
| 59 | case __constant_htons(ETH_P_8021Q): | 59 | case htons(ETH_P_8021Q): |
| 60 | case __constant_htons(ETH_P_8021AD): | 60 | case htons(ETH_P_8021AD): |
| 61 | break; | 61 | break; |
| 62 | default: | 62 | default: |
| 63 | return -EPROTONOSUPPORT; | 63 | return -EPROTONOSUPPORT; |
diff --git a/net/9p/client.c b/net/9p/client.c index 9186550d77a6..0004cbaac4a4 100644 --- a/net/9p/client.c +++ b/net/9p/client.c | |||
| @@ -415,9 +415,17 @@ static void p9_free_req(struct p9_client *c, struct p9_req_t *r) | |||
| 415 | * req: request received | 415 | * req: request received |
| 416 | * | 416 | * |
| 417 | */ | 417 | */ |
| 418 | void p9_client_cb(struct p9_client *c, struct p9_req_t *req) | 418 | void p9_client_cb(struct p9_client *c, struct p9_req_t *req, int status) |
| 419 | { | 419 | { |
| 420 | p9_debug(P9_DEBUG_MUX, " tag %d\n", req->tc->tag); | 420 | p9_debug(P9_DEBUG_MUX, " tag %d\n", req->tc->tag); |
| 421 | |||
| 422 | /* | ||
| 423 | * This barrier is needed to make sure any change made to req before | ||
| 424 | * the other thread wakes up will indeed be seen by the waiting side. | ||
| 425 | */ | ||
| 426 | smp_wmb(); | ||
| 427 | req->status = status; | ||
| 428 | |||
| 421 | wake_up(req->wq); | 429 | wake_up(req->wq); |
| 422 | p9_debug(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag); | 430 | p9_debug(P9_DEBUG_MUX, "wakeup: %d\n", req->tc->tag); |
| 423 | } | 431 | } |
| @@ -655,16 +663,13 @@ static int p9_client_flush(struct p9_client *c, struct p9_req_t *oldreq) | |||
| 655 | if (IS_ERR(req)) | 663 | if (IS_ERR(req)) |
| 656 | return PTR_ERR(req); | 664 | return PTR_ERR(req); |
| 657 | 665 | ||
| 658 | |||
| 659 | /* | 666 | /* |
| 660 | * if we haven't received a response for oldreq, | 667 | * if we haven't received a response for oldreq, |
| 661 | * remove it from the list | 668 | * remove it from the list |
| 662 | */ | 669 | */ |
| 663 | if (oldreq->status == REQ_STATUS_FLSH) { | 670 | if (oldreq->status == REQ_STATUS_SENT) |
| 664 | spin_lock(&c->lock); | 671 | if (c->trans_mod->cancelled) |
| 665 | list_del(&oldreq->req_list); | 672 | c->trans_mod->cancelled(c, oldreq); |
| 666 | spin_unlock(&c->lock); | ||
| 667 | } | ||
| 668 | 673 | ||
| 669 | p9_free_req(c, req); | 674 | p9_free_req(c, req); |
| 670 | return 0; | 675 | return 0; |
| @@ -751,6 +756,12 @@ again: | |||
| 751 | err = wait_event_interruptible(*req->wq, | 756 | err = wait_event_interruptible(*req->wq, |
| 752 | req->status >= REQ_STATUS_RCVD); | 757 | req->status >= REQ_STATUS_RCVD); |
| 753 | 758 | ||
| 759 | /* | ||
| 760 | * Make sure our req is coherent with regard to updates in other | ||
| 761 | * threads - echoes to wmb() in the callback | ||
| 762 | */ | ||
| 763 | smp_rmb(); | ||
| 764 | |||
| 754 | if ((err == -ERESTARTSYS) && (c->status == Connected) | 765 | if ((err == -ERESTARTSYS) && (c->status == Connected) |
| 755 | && (type == P9_TFLUSH)) { | 766 | && (type == P9_TFLUSH)) { |
| 756 | sigpending = 1; | 767 | sigpending = 1; |
diff --git a/net/9p/trans_fd.c b/net/9p/trans_fd.c index b7bd7f2961bf..80d08f6664cb 100644 --- a/net/9p/trans_fd.c +++ b/net/9p/trans_fd.c | |||
| @@ -66,20 +66,6 @@ struct p9_fd_opts { | |||
| 66 | int privport; | 66 | int privport; |
| 67 | }; | 67 | }; |
| 68 | 68 | ||
| 69 | /** | ||
| 70 | * struct p9_trans_fd - transport state | ||
| 71 | * @rd: reference to file to read from | ||
| 72 | * @wr: reference of file to write to | ||
| 73 | * @conn: connection state reference | ||
| 74 | * | ||
| 75 | */ | ||
| 76 | |||
| 77 | struct p9_trans_fd { | ||
| 78 | struct file *rd; | ||
| 79 | struct file *wr; | ||
| 80 | struct p9_conn *conn; | ||
| 81 | }; | ||
| 82 | |||
| 83 | /* | 69 | /* |
| 84 | * Option Parsing (code inspired by NFS code) | 70 | * Option Parsing (code inspired by NFS code) |
| 85 | * - a little lazy - parse all fd-transport options | 71 | * - a little lazy - parse all fd-transport options |
| @@ -159,6 +145,20 @@ struct p9_conn { | |||
| 159 | unsigned long wsched; | 145 | unsigned long wsched; |
| 160 | }; | 146 | }; |
| 161 | 147 | ||
| 148 | /** | ||
| 149 | * struct p9_trans_fd - transport state | ||
| 150 | * @rd: reference to file to read from | ||
| 151 | * @wr: reference of file to write to | ||
| 152 | * @conn: connection state reference | ||
| 153 | * | ||
| 154 | */ | ||
| 155 | |||
| 156 | struct p9_trans_fd { | ||
| 157 | struct file *rd; | ||
| 158 | struct file *wr; | ||
| 159 | struct p9_conn conn; | ||
| 160 | }; | ||
| 161 | |||
| 162 | static void p9_poll_workfn(struct work_struct *work); | 162 | static void p9_poll_workfn(struct work_struct *work); |
| 163 | 163 | ||
| 164 | static DEFINE_SPINLOCK(p9_poll_lock); | 164 | static DEFINE_SPINLOCK(p9_poll_lock); |
| @@ -212,15 +212,9 @@ static void p9_conn_cancel(struct p9_conn *m, int err) | |||
| 212 | m->err = err; | 212 | m->err = err; |
| 213 | 213 | ||
| 214 | list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) { | 214 | list_for_each_entry_safe(req, rtmp, &m->req_list, req_list) { |
| 215 | req->status = REQ_STATUS_ERROR; | ||
| 216 | if (!req->t_err) | ||
| 217 | req->t_err = err; | ||
| 218 | list_move(&req->req_list, &cancel_list); | 215 | list_move(&req->req_list, &cancel_list); |
| 219 | } | 216 | } |
| 220 | list_for_each_entry_safe(req, rtmp, &m->unsent_req_list, req_list) { | 217 | list_for_each_entry_safe(req, rtmp, &m->unsent_req_list, req_list) { |
| 221 | req->status = REQ_STATUS_ERROR; | ||
| 222 | if (!req->t_err) | ||
| 223 | req->t_err = err; | ||
| 224 | list_move(&req->req_list, &cancel_list); | 218 | list_move(&req->req_list, &cancel_list); |
| 225 | } | 219 | } |
| 226 | spin_unlock_irqrestore(&m->client->lock, flags); | 220 | spin_unlock_irqrestore(&m->client->lock, flags); |
| @@ -228,7 +222,9 @@ static void p9_conn_cancel(struct p9_conn *m, int err) | |||
| 228 | list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) { | 222 | list_for_each_entry_safe(req, rtmp, &cancel_list, req_list) { |
| 229 | p9_debug(P9_DEBUG_ERROR, "call back req %p\n", req); | 223 | p9_debug(P9_DEBUG_ERROR, "call back req %p\n", req); |
| 230 | list_del(&req->req_list); | 224 | list_del(&req->req_list); |
| 231 | p9_client_cb(m->client, req); | 225 | if (!req->t_err) |
| 226 | req->t_err = err; | ||
| 227 | p9_client_cb(m->client, req, REQ_STATUS_ERROR); | ||
| 232 | } | 228 | } |
| 233 | } | 229 | } |
| 234 | 230 | ||
| @@ -302,6 +298,7 @@ static void p9_read_work(struct work_struct *work) | |||
| 302 | { | 298 | { |
| 303 | int n, err; | 299 | int n, err; |
| 304 | struct p9_conn *m; | 300 | struct p9_conn *m; |
| 301 | int status = REQ_STATUS_ERROR; | ||
| 305 | 302 | ||
| 306 | m = container_of(work, struct p9_conn, rq); | 303 | m = container_of(work, struct p9_conn, rq); |
| 307 | 304 | ||
| @@ -348,8 +345,7 @@ static void p9_read_work(struct work_struct *work) | |||
| 348 | "mux %p pkt: size: %d bytes tag: %d\n", m, n, tag); | 345 | "mux %p pkt: size: %d bytes tag: %d\n", m, n, tag); |
| 349 | 346 | ||
| 350 | m->req = p9_tag_lookup(m->client, tag); | 347 | m->req = p9_tag_lookup(m->client, tag); |
| 351 | if (!m->req || (m->req->status != REQ_STATUS_SENT && | 348 | if (!m->req || (m->req->status != REQ_STATUS_SENT)) { |
| 352 | m->req->status != REQ_STATUS_FLSH)) { | ||
| 353 | p9_debug(P9_DEBUG_ERROR, "Unexpected packet tag %d\n", | 349 | p9_debug(P9_DEBUG_ERROR, "Unexpected packet tag %d\n", |
| 354 | tag); | 350 | tag); |
| 355 | err = -EIO; | 351 | err = -EIO; |
| @@ -375,10 +371,10 @@ static void p9_read_work(struct work_struct *work) | |||
| 375 | p9_debug(P9_DEBUG_TRANS, "got new packet\n"); | 371 | p9_debug(P9_DEBUG_TRANS, "got new packet\n"); |
| 376 | spin_lock(&m->client->lock); | 372 | spin_lock(&m->client->lock); |
| 377 | if (m->req->status != REQ_STATUS_ERROR) | 373 | if (m->req->status != REQ_STATUS_ERROR) |
| 378 | m->req->status = REQ_STATUS_RCVD; | 374 | status = REQ_STATUS_RCVD; |
| 379 | list_del(&m->req->req_list); | 375 | list_del(&m->req->req_list); |
| 380 | spin_unlock(&m->client->lock); | 376 | spin_unlock(&m->client->lock); |
| 381 | p9_client_cb(m->client, m->req); | 377 | p9_client_cb(m->client, m->req, status); |
| 382 | m->rbuf = NULL; | 378 | m->rbuf = NULL; |
| 383 | m->rpos = 0; | 379 | m->rpos = 0; |
| 384 | m->rsize = 0; | 380 | m->rsize = 0; |
| @@ -573,21 +569,19 @@ p9_pollwait(struct file *filp, wait_queue_head_t *wait_address, poll_table *p) | |||
| 573 | } | 569 | } |
| 574 | 570 | ||
| 575 | /** | 571 | /** |
| 576 | * p9_conn_create - allocate and initialize the per-session mux data | 572 | * p9_conn_create - initialize the per-session mux data |
| 577 | * @client: client instance | 573 | * @client: client instance |
| 578 | * | 574 | * |
| 579 | * Note: Creates the polling task if this is the first session. | 575 | * Note: Creates the polling task if this is the first session. |
| 580 | */ | 576 | */ |
| 581 | 577 | ||
| 582 | static struct p9_conn *p9_conn_create(struct p9_client *client) | 578 | static void p9_conn_create(struct p9_client *client) |
| 583 | { | 579 | { |
| 584 | int n; | 580 | int n; |
| 585 | struct p9_conn *m; | 581 | struct p9_trans_fd *ts = client->trans; |
| 582 | struct p9_conn *m = &ts->conn; | ||
| 586 | 583 | ||
| 587 | p9_debug(P9_DEBUG_TRANS, "client %p msize %d\n", client, client->msize); | 584 | p9_debug(P9_DEBUG_TRANS, "client %p msize %d\n", client, client->msize); |
| 588 | m = kzalloc(sizeof(struct p9_conn), GFP_KERNEL); | ||
| 589 | if (!m) | ||
| 590 | return ERR_PTR(-ENOMEM); | ||
| 591 | 585 | ||
| 592 | INIT_LIST_HEAD(&m->mux_list); | 586 | INIT_LIST_HEAD(&m->mux_list); |
| 593 | m->client = client; | 587 | m->client = client; |
| @@ -609,8 +603,6 @@ static struct p9_conn *p9_conn_create(struct p9_client *client) | |||
| 609 | p9_debug(P9_DEBUG_TRANS, "mux %p can write\n", m); | 603 | p9_debug(P9_DEBUG_TRANS, "mux %p can write\n", m); |
| 610 | set_bit(Wpending, &m->wsched); | 604 | set_bit(Wpending, &m->wsched); |
| 611 | } | 605 | } |
| 612 | |||
| 613 | return m; | ||
| 614 | } | 606 | } |
| 615 | 607 | ||
| 616 | /** | 608 | /** |
| @@ -669,7 +661,7 @@ static int p9_fd_request(struct p9_client *client, struct p9_req_t *req) | |||
| 669 | { | 661 | { |
| 670 | int n; | 662 | int n; |
| 671 | struct p9_trans_fd *ts = client->trans; | 663 | struct p9_trans_fd *ts = client->trans; |
| 672 | struct p9_conn *m = ts->conn; | 664 | struct p9_conn *m = &ts->conn; |
| 673 | 665 | ||
| 674 | p9_debug(P9_DEBUG_TRANS, "mux %p task %p tcall %p id %d\n", | 666 | p9_debug(P9_DEBUG_TRANS, "mux %p task %p tcall %p id %d\n", |
| 675 | m, current, req->tc, req->tc->id); | 667 | m, current, req->tc, req->tc->id); |
| @@ -704,14 +696,26 @@ static int p9_fd_cancel(struct p9_client *client, struct p9_req_t *req) | |||
| 704 | list_del(&req->req_list); | 696 | list_del(&req->req_list); |
| 705 | req->status = REQ_STATUS_FLSHD; | 697 | req->status = REQ_STATUS_FLSHD; |
| 706 | ret = 0; | 698 | ret = 0; |
| 707 | } else if (req->status == REQ_STATUS_SENT) | 699 | } |
| 708 | req->status = REQ_STATUS_FLSH; | ||
| 709 | |||
| 710 | spin_unlock(&client->lock); | 700 | spin_unlock(&client->lock); |
| 711 | 701 | ||
| 712 | return ret; | 702 | return ret; |
| 713 | } | 703 | } |
| 714 | 704 | ||
| 705 | static int p9_fd_cancelled(struct p9_client *client, struct p9_req_t *req) | ||
| 706 | { | ||
| 707 | p9_debug(P9_DEBUG_TRANS, "client %p req %p\n", client, req); | ||
| 708 | |||
| 709 | /* we haven't received a response for oldreq, | ||
| 710 | * remove it from the list. | ||
| 711 | */ | ||
| 712 | spin_lock(&client->lock); | ||
| 713 | list_del(&req->req_list); | ||
| 714 | spin_unlock(&client->lock); | ||
| 715 | |||
| 716 | return 0; | ||
| 717 | } | ||
| 718 | |||
| 715 | /** | 719 | /** |
| 716 | * parse_opts - parse mount options into p9_fd_opts structure | 720 | * parse_opts - parse mount options into p9_fd_opts structure |
| 717 | * @params: options string passed from mount | 721 | * @params: options string passed from mount |
| @@ -780,7 +784,7 @@ static int parse_opts(char *params, struct p9_fd_opts *opts) | |||
| 780 | 784 | ||
| 781 | static int p9_fd_open(struct p9_client *client, int rfd, int wfd) | 785 | static int p9_fd_open(struct p9_client *client, int rfd, int wfd) |
| 782 | { | 786 | { |
| 783 | struct p9_trans_fd *ts = kmalloc(sizeof(struct p9_trans_fd), | 787 | struct p9_trans_fd *ts = kzalloc(sizeof(struct p9_trans_fd), |
| 784 | GFP_KERNEL); | 788 | GFP_KERNEL); |
| 785 | if (!ts) | 789 | if (!ts) |
| 786 | return -ENOMEM; | 790 | return -ENOMEM; |
| @@ -806,9 +810,8 @@ static int p9_socket_open(struct p9_client *client, struct socket *csocket) | |||
| 806 | { | 810 | { |
| 807 | struct p9_trans_fd *p; | 811 | struct p9_trans_fd *p; |
| 808 | struct file *file; | 812 | struct file *file; |
| 809 | int ret; | ||
| 810 | 813 | ||
| 811 | p = kmalloc(sizeof(struct p9_trans_fd), GFP_KERNEL); | 814 | p = kzalloc(sizeof(struct p9_trans_fd), GFP_KERNEL); |
| 812 | if (!p) | 815 | if (!p) |
| 813 | return -ENOMEM; | 816 | return -ENOMEM; |
| 814 | 817 | ||
| @@ -829,20 +832,12 @@ static int p9_socket_open(struct p9_client *client, struct socket *csocket) | |||
| 829 | 832 | ||
| 830 | p->rd->f_flags |= O_NONBLOCK; | 833 | p->rd->f_flags |= O_NONBLOCK; |
| 831 | 834 | ||
| 832 | p->conn = p9_conn_create(client); | 835 | p9_conn_create(client); |
| 833 | if (IS_ERR(p->conn)) { | ||
| 834 | ret = PTR_ERR(p->conn); | ||
| 835 | p->conn = NULL; | ||
| 836 | kfree(p); | ||
| 837 | sockfd_put(csocket); | ||
| 838 | sockfd_put(csocket); | ||
| 839 | return ret; | ||
| 840 | } | ||
| 841 | return 0; | 836 | return 0; |
| 842 | } | 837 | } |
| 843 | 838 | ||
| 844 | /** | 839 | /** |
| 845 | * p9_mux_destroy - cancels all pending requests and frees mux resources | 840 | * p9_mux_destroy - cancels all pending requests of mux |
| 846 | * @m: mux to destroy | 841 | * @m: mux to destroy |
| 847 | * | 842 | * |
| 848 | */ | 843 | */ |
| @@ -859,7 +854,6 @@ static void p9_conn_destroy(struct p9_conn *m) | |||
| 859 | p9_conn_cancel(m, -ECONNRESET); | 854 | p9_conn_cancel(m, -ECONNRESET); |
| 860 | 855 | ||
| 861 | m->client = NULL; | 856 | m->client = NULL; |
| 862 | kfree(m); | ||
| 863 | } | 857 | } |
| 864 | 858 | ||
| 865 | /** | 859 | /** |
| @@ -881,7 +875,7 @@ static void p9_fd_close(struct p9_client *client) | |||
| 881 | 875 | ||
| 882 | client->status = Disconnected; | 876 | client->status = Disconnected; |
| 883 | 877 | ||
| 884 | p9_conn_destroy(ts->conn); | 878 | p9_conn_destroy(&ts->conn); |
| 885 | 879 | ||
| 886 | if (ts->rd) | 880 | if (ts->rd) |
| 887 | fput(ts->rd); | 881 | fput(ts->rd); |
| @@ -1033,14 +1027,7 @@ p9_fd_create(struct p9_client *client, const char *addr, char *args) | |||
| 1033 | return err; | 1027 | return err; |
| 1034 | 1028 | ||
| 1035 | p = (struct p9_trans_fd *) client->trans; | 1029 | p = (struct p9_trans_fd *) client->trans; |
| 1036 | p->conn = p9_conn_create(client); | 1030 | p9_conn_create(client); |
| 1037 | if (IS_ERR(p->conn)) { | ||
| 1038 | err = PTR_ERR(p->conn); | ||
| 1039 | p->conn = NULL; | ||
| 1040 | fput(p->rd); | ||
| 1041 | fput(p->wr); | ||
| 1042 | return err; | ||
| 1043 | } | ||
| 1044 | 1031 | ||
| 1045 | return 0; | 1032 | return 0; |
| 1046 | } | 1033 | } |
| @@ -1053,6 +1040,7 @@ static struct p9_trans_module p9_tcp_trans = { | |||
| 1053 | .close = p9_fd_close, | 1040 | .close = p9_fd_close, |
| 1054 | .request = p9_fd_request, | 1041 | .request = p9_fd_request, |
| 1055 | .cancel = p9_fd_cancel, | 1042 | .cancel = p9_fd_cancel, |
| 1043 | .cancelled = p9_fd_cancelled, | ||
| 1056 | .owner = THIS_MODULE, | 1044 | .owner = THIS_MODULE, |
| 1057 | }; | 1045 | }; |
| 1058 | 1046 | ||
| @@ -1064,6 +1052,7 @@ static struct p9_trans_module p9_unix_trans = { | |||
| 1064 | .close = p9_fd_close, | 1052 | .close = p9_fd_close, |
| 1065 | .request = p9_fd_request, | 1053 | .request = p9_fd_request, |
| 1066 | .cancel = p9_fd_cancel, | 1054 | .cancel = p9_fd_cancel, |
| 1055 | .cancelled = p9_fd_cancelled, | ||
| 1067 | .owner = THIS_MODULE, | 1056 | .owner = THIS_MODULE, |
| 1068 | }; | 1057 | }; |
| 1069 | 1058 | ||
| @@ -1075,6 +1064,7 @@ static struct p9_trans_module p9_fd_trans = { | |||
| 1075 | .close = p9_fd_close, | 1064 | .close = p9_fd_close, |
| 1076 | .request = p9_fd_request, | 1065 | .request = p9_fd_request, |
| 1077 | .cancel = p9_fd_cancel, | 1066 | .cancel = p9_fd_cancel, |
| 1067 | .cancelled = p9_fd_cancelled, | ||
| 1078 | .owner = THIS_MODULE, | 1068 | .owner = THIS_MODULE, |
| 1079 | }; | 1069 | }; |
| 1080 | 1070 | ||
diff --git a/net/9p/trans_rdma.c b/net/9p/trans_rdma.c index 8f68df5d2973..14ad43b5cf89 100644 --- a/net/9p/trans_rdma.c +++ b/net/9p/trans_rdma.c | |||
| @@ -193,6 +193,8 @@ static int parse_opts(char *params, struct p9_rdma_opts *opts) | |||
| 193 | if (!*p) | 193 | if (!*p) |
| 194 | continue; | 194 | continue; |
| 195 | token = match_token(p, tokens, args); | 195 | token = match_token(p, tokens, args); |
| 196 | if (token == Opt_err) | ||
| 197 | continue; | ||
| 196 | r = match_int(&args[0], &option); | 198 | r = match_int(&args[0], &option); |
| 197 | if (r < 0) { | 199 | if (r < 0) { |
| 198 | p9_debug(P9_DEBUG_ERROR, | 200 | p9_debug(P9_DEBUG_ERROR, |
| @@ -305,8 +307,7 @@ handle_recv(struct p9_client *client, struct p9_trans_rdma *rdma, | |||
| 305 | } | 307 | } |
| 306 | 308 | ||
| 307 | req->rc = c->rc; | 309 | req->rc = c->rc; |
| 308 | req->status = REQ_STATUS_RCVD; | 310 | p9_client_cb(client, req, REQ_STATUS_RCVD); |
| 309 | p9_client_cb(client, req); | ||
| 310 | 311 | ||
| 311 | return; | 312 | return; |
| 312 | 313 | ||
| @@ -511,6 +512,11 @@ dont_need_post_recv: | |||
| 511 | goto send_error; | 512 | goto send_error; |
| 512 | } | 513 | } |
| 513 | 514 | ||
| 515 | /* Mark request as `sent' *before* we actually send it, | ||
| 516 | * because doing if after could erase the REQ_STATUS_RCVD | ||
| 517 | * status in case of a very fast reply. | ||
| 518 | */ | ||
| 519 | req->status = REQ_STATUS_SENT; | ||
| 514 | err = ib_post_send(rdma->qp, &wr, &bad_wr); | 520 | err = ib_post_send(rdma->qp, &wr, &bad_wr); |
| 515 | if (err) | 521 | if (err) |
| 516 | goto send_error; | 522 | goto send_error; |
| @@ -520,6 +526,7 @@ dont_need_post_recv: | |||
| 520 | 526 | ||
| 521 | /* Handle errors that happened during or while preparing the send: */ | 527 | /* Handle errors that happened during or while preparing the send: */ |
| 522 | send_error: | 528 | send_error: |
| 529 | req->status = REQ_STATUS_ERROR; | ||
| 523 | kfree(c); | 530 | kfree(c); |
| 524 | p9_debug(P9_DEBUG_ERROR, "Error %d in rdma_request()\n", err); | 531 | p9_debug(P9_DEBUG_ERROR, "Error %d in rdma_request()\n", err); |
| 525 | 532 | ||
| @@ -582,12 +589,24 @@ static struct p9_trans_rdma *alloc_rdma(struct p9_rdma_opts *opts) | |||
| 582 | return rdma; | 589 | return rdma; |
| 583 | } | 590 | } |
| 584 | 591 | ||
| 585 | /* its not clear to me we can do anything after send has been posted */ | ||
| 586 | static int rdma_cancel(struct p9_client *client, struct p9_req_t *req) | 592 | static int rdma_cancel(struct p9_client *client, struct p9_req_t *req) |
| 587 | { | 593 | { |
| 594 | /* Nothing to do here. | ||
| 595 | * We will take care of it (if we have to) in rdma_cancelled() | ||
| 596 | */ | ||
| 588 | return 1; | 597 | return 1; |
| 589 | } | 598 | } |
| 590 | 599 | ||
| 600 | /* A request has been fully flushed without a reply. | ||
| 601 | * That means we have posted one buffer in excess. | ||
| 602 | */ | ||
| 603 | static int rdma_cancelled(struct p9_client *client, struct p9_req_t *req) | ||
| 604 | { | ||
| 605 | struct p9_trans_rdma *rdma = client->trans; | ||
| 606 | atomic_inc(&rdma->excess_rc); | ||
| 607 | return 0; | ||
| 608 | } | ||
| 609 | |||
| 591 | /** | 610 | /** |
| 592 | * trans_create_rdma - Transport method for creating atransport instance | 611 | * trans_create_rdma - Transport method for creating atransport instance |
| 593 | * @client: client instance | 612 | * @client: client instance |
| @@ -721,6 +740,7 @@ static struct p9_trans_module p9_rdma_trans = { | |||
| 721 | .close = rdma_close, | 740 | .close = rdma_close, |
| 722 | .request = rdma_request, | 741 | .request = rdma_request, |
| 723 | .cancel = rdma_cancel, | 742 | .cancel = rdma_cancel, |
| 743 | .cancelled = rdma_cancelled, | ||
| 724 | }; | 744 | }; |
| 725 | 745 | ||
| 726 | /** | 746 | /** |
diff --git a/net/9p/trans_virtio.c b/net/9p/trans_virtio.c index ac2666c1d011..6940d8fe8971 100644 --- a/net/9p/trans_virtio.c +++ b/net/9p/trans_virtio.c | |||
| @@ -164,8 +164,7 @@ static void req_done(struct virtqueue *vq) | |||
| 164 | p9_debug(P9_DEBUG_TRANS, ": rc %p\n", rc); | 164 | p9_debug(P9_DEBUG_TRANS, ": rc %p\n", rc); |
| 165 | p9_debug(P9_DEBUG_TRANS, ": lookup tag %d\n", rc->tag); | 165 | p9_debug(P9_DEBUG_TRANS, ": lookup tag %d\n", rc->tag); |
| 166 | req = p9_tag_lookup(chan->client, rc->tag); | 166 | req = p9_tag_lookup(chan->client, rc->tag); |
| 167 | req->status = REQ_STATUS_RCVD; | 167 | p9_client_cb(chan->client, req, REQ_STATUS_RCVD); |
| 168 | p9_client_cb(chan->client, req); | ||
| 169 | } | 168 | } |
| 170 | } | 169 | } |
| 171 | 170 | ||
diff --git a/net/Kconfig b/net/Kconfig index e411046a62e3..d92afe4204d9 100644 --- a/net/Kconfig +++ b/net/Kconfig | |||
| @@ -89,8 +89,12 @@ config NETWORK_SECMARK | |||
| 89 | to nfmark, but designated for security purposes. | 89 | to nfmark, but designated for security purposes. |
| 90 | If you are unsure how to answer this question, answer N. | 90 | If you are unsure how to answer this question, answer N. |
| 91 | 91 | ||
| 92 | config NET_PTP_CLASSIFY | ||
| 93 | def_bool n | ||
| 94 | |||
| 92 | config NETWORK_PHY_TIMESTAMPING | 95 | config NETWORK_PHY_TIMESTAMPING |
| 93 | bool "Timestamping in PHY devices" | 96 | bool "Timestamping in PHY devices" |
| 97 | select NET_PTP_CLASSIFY | ||
| 94 | help | 98 | help |
| 95 | This allows timestamping of network packets by PHYs with | 99 | This allows timestamping of network packets by PHYs with |
| 96 | hardware timestamping capabilities. This option adds some | 100 | hardware timestamping capabilities. This option adds some |
| @@ -239,7 +243,7 @@ config XPS | |||
| 239 | default y | 243 | default y |
| 240 | 244 | ||
| 241 | config CGROUP_NET_PRIO | 245 | config CGROUP_NET_PRIO |
| 242 | tristate "Network priority cgroup" | 246 | bool "Network priority cgroup" |
| 243 | depends on CGROUPS | 247 | depends on CGROUPS |
| 244 | ---help--- | 248 | ---help--- |
| 245 | Cgroup subsystem for use in assigning processes to network priorities on | 249 | Cgroup subsystem for use in assigning processes to network priorities on |
diff --git a/net/appletalk/aarp.c b/net/appletalk/aarp.c index d27b86dfb0e9..d1c55d8dd0a2 100644 --- a/net/appletalk/aarp.c +++ b/net/appletalk/aarp.c | |||
| @@ -926,7 +926,7 @@ static struct aarp_entry *iter_next(struct aarp_iter_state *iter, loff_t *pos) | |||
| 926 | struct aarp_entry *entry; | 926 | struct aarp_entry *entry; |
| 927 | 927 | ||
| 928 | rescan: | 928 | rescan: |
| 929 | while(ct < AARP_HASH_SIZE) { | 929 | while (ct < AARP_HASH_SIZE) { |
| 930 | for (entry = table[ct]; entry; entry = entry->next) { | 930 | for (entry = table[ct]; entry; entry = entry->next) { |
| 931 | if (!pos || ++off == *pos) { | 931 | if (!pos || ++off == *pos) { |
| 932 | iter->table = table; | 932 | iter->table = table; |
| @@ -995,7 +995,7 @@ static const char *dt2str(unsigned long ticks) | |||
| 995 | { | 995 | { |
| 996 | static char buf[32]; | 996 | static char buf[32]; |
| 997 | 997 | ||
| 998 | sprintf(buf, "%ld.%02ld", ticks / HZ, ((ticks % HZ) * 100 ) / HZ); | 998 | sprintf(buf, "%ld.%02ld", ticks / HZ, ((ticks % HZ) * 100) / HZ); |
| 999 | 999 | ||
| 1000 | return buf; | 1000 | return buf; |
| 1001 | } | 1001 | } |
diff --git a/net/appletalk/ddp.c b/net/appletalk/ddp.c index 02806c6b2ff3..786ee2f83d5f 100644 --- a/net/appletalk/ddp.c +++ b/net/appletalk/ddp.c | |||
| @@ -293,7 +293,7 @@ static int atif_probe_device(struct atalk_iface *atif) | |||
| 293 | 293 | ||
| 294 | /* Perform AARP probing for a proxy address */ | 294 | /* Perform AARP probing for a proxy address */ |
| 295 | static int atif_proxy_probe_device(struct atalk_iface *atif, | 295 | static int atif_proxy_probe_device(struct atalk_iface *atif, |
| 296 | struct atalk_addr* proxy_addr) | 296 | struct atalk_addr *proxy_addr) |
| 297 | { | 297 | { |
| 298 | int netrange = ntohs(atif->nets.nr_lastnet) - | 298 | int netrange = ntohs(atif->nets.nr_lastnet) - |
| 299 | ntohs(atif->nets.nr_firstnet) + 1; | 299 | ntohs(atif->nets.nr_firstnet) + 1; |
| @@ -581,7 +581,7 @@ out: | |||
| 581 | } | 581 | } |
| 582 | 582 | ||
| 583 | /* Delete a route. Find it and discard it */ | 583 | /* Delete a route. Find it and discard it */ |
| 584 | static int atrtr_delete(struct atalk_addr * addr) | 584 | static int atrtr_delete(struct atalk_addr *addr) |
| 585 | { | 585 | { |
| 586 | struct atalk_route **r = &atalk_routes; | 586 | struct atalk_route **r = &atalk_routes; |
| 587 | int retval = 0; | 587 | int retval = 0; |
| @@ -936,11 +936,11 @@ static unsigned long atalk_sum_skb(const struct sk_buff *skb, int offset, | |||
| 936 | int i, copy; | 936 | int i, copy; |
| 937 | 937 | ||
| 938 | /* checksum stuff in header space */ | 938 | /* checksum stuff in header space */ |
| 939 | if ( (copy = start - offset) > 0) { | 939 | if ((copy = start - offset) > 0) { |
| 940 | if (copy > len) | 940 | if (copy > len) |
| 941 | copy = len; | 941 | copy = len; |
| 942 | sum = atalk_sum_partial(skb->data + offset, copy, sum); | 942 | sum = atalk_sum_partial(skb->data + offset, copy, sum); |
| 943 | if ( (len -= copy) == 0) | 943 | if ((len -= copy) == 0) |
| 944 | return sum; | 944 | return sum; |
| 945 | 945 | ||
| 946 | offset += copy; | 946 | offset += copy; |
| @@ -1151,7 +1151,7 @@ static int atalk_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len) | |||
| 1151 | goto out; | 1151 | goto out; |
| 1152 | 1152 | ||
| 1153 | at->src_net = addr->sat_addr.s_net = ap->s_net; | 1153 | at->src_net = addr->sat_addr.s_net = ap->s_net; |
| 1154 | at->src_node = addr->sat_addr.s_node= ap->s_node; | 1154 | at->src_node = addr->sat_addr.s_node = ap->s_node; |
| 1155 | } else { | 1155 | } else { |
| 1156 | err = -EADDRNOTAVAIL; | 1156 | err = -EADDRNOTAVAIL; |
| 1157 | if (!atalk_find_interface(addr->sat_addr.s_net, | 1157 | if (!atalk_find_interface(addr->sat_addr.s_net, |
| @@ -1790,53 +1790,53 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | |||
| 1790 | void __user *argp = (void __user *)arg; | 1790 | void __user *argp = (void __user *)arg; |
| 1791 | 1791 | ||
| 1792 | switch (cmd) { | 1792 | switch (cmd) { |
| 1793 | /* Protocol layer */ | 1793 | /* Protocol layer */ |
| 1794 | case TIOCOUTQ: { | 1794 | case TIOCOUTQ: { |
| 1795 | long amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); | 1795 | long amount = sk->sk_sndbuf - sk_wmem_alloc_get(sk); |
| 1796 | 1796 | ||
| 1797 | if (amount < 0) | 1797 | if (amount < 0) |
| 1798 | amount = 0; | 1798 | amount = 0; |
| 1799 | rc = put_user(amount, (int __user *)argp); | 1799 | rc = put_user(amount, (int __user *)argp); |
| 1800 | break; | 1800 | break; |
| 1801 | } | 1801 | } |
| 1802 | case TIOCINQ: { | 1802 | case TIOCINQ: { |
| 1803 | /* | 1803 | /* |
| 1804 | * These two are safe on a single CPU system as only | 1804 | * These two are safe on a single CPU system as only |
| 1805 | * user tasks fiddle here | 1805 | * user tasks fiddle here |
| 1806 | */ | 1806 | */ |
| 1807 | struct sk_buff *skb = skb_peek(&sk->sk_receive_queue); | 1807 | struct sk_buff *skb = skb_peek(&sk->sk_receive_queue); |
| 1808 | long amount = 0; | 1808 | long amount = 0; |
| 1809 | 1809 | ||
| 1810 | if (skb) | 1810 | if (skb) |
| 1811 | amount = skb->len - sizeof(struct ddpehdr); | 1811 | amount = skb->len - sizeof(struct ddpehdr); |
| 1812 | rc = put_user(amount, (int __user *)argp); | 1812 | rc = put_user(amount, (int __user *)argp); |
| 1813 | break; | 1813 | break; |
| 1814 | } | 1814 | } |
| 1815 | case SIOCGSTAMP: | 1815 | case SIOCGSTAMP: |
| 1816 | rc = sock_get_timestamp(sk, argp); | 1816 | rc = sock_get_timestamp(sk, argp); |
| 1817 | break; | 1817 | break; |
| 1818 | case SIOCGSTAMPNS: | 1818 | case SIOCGSTAMPNS: |
| 1819 | rc = sock_get_timestampns(sk, argp); | 1819 | rc = sock_get_timestampns(sk, argp); |
| 1820 | break; | 1820 | break; |
| 1821 | /* Routing */ | 1821 | /* Routing */ |
| 1822 | case SIOCADDRT: | 1822 | case SIOCADDRT: |
| 1823 | case SIOCDELRT: | 1823 | case SIOCDELRT: |
| 1824 | rc = -EPERM; | 1824 | rc = -EPERM; |
| 1825 | if (capable(CAP_NET_ADMIN)) | 1825 | if (capable(CAP_NET_ADMIN)) |
| 1826 | rc = atrtr_ioctl(cmd, argp); | 1826 | rc = atrtr_ioctl(cmd, argp); |
| 1827 | break; | 1827 | break; |
| 1828 | /* Interface */ | 1828 | /* Interface */ |
| 1829 | case SIOCGIFADDR: | 1829 | case SIOCGIFADDR: |
| 1830 | case SIOCSIFADDR: | 1830 | case SIOCSIFADDR: |
| 1831 | case SIOCGIFBRDADDR: | 1831 | case SIOCGIFBRDADDR: |
| 1832 | case SIOCATALKDIFADDR: | 1832 | case SIOCATALKDIFADDR: |
| 1833 | case SIOCDIFADDR: | 1833 | case SIOCDIFADDR: |
| 1834 | case SIOCSARP: /* proxy AARP */ | 1834 | case SIOCSARP: /* proxy AARP */ |
| 1835 | case SIOCDARP: /* proxy AARP */ | 1835 | case SIOCDARP: /* proxy AARP */ |
| 1836 | rtnl_lock(); | 1836 | rtnl_lock(); |
| 1837 | rc = atif_ioctl(cmd, argp); | 1837 | rc = atif_ioctl(cmd, argp); |
| 1838 | rtnl_unlock(); | 1838 | rtnl_unlock(); |
| 1839 | break; | 1839 | break; |
| 1840 | } | 1840 | } |
| 1841 | 1841 | ||
| 1842 | return rc; | 1842 | return rc; |
diff --git a/net/atm/clip.c b/net/atm/clip.c index 8215f7cb170b..ba291ce4bdff 100644 --- a/net/atm/clip.c +++ b/net/atm/clip.c | |||
| @@ -68,7 +68,7 @@ static int to_atmarpd(enum atmarp_ctrl_type type, int itf, __be32 ip) | |||
| 68 | 68 | ||
| 69 | sk = sk_atm(atmarpd); | 69 | sk = sk_atm(atmarpd); |
| 70 | skb_queue_tail(&sk->sk_receive_queue, skb); | 70 | skb_queue_tail(&sk->sk_receive_queue, skb); |
| 71 | sk->sk_data_ready(sk, skb->len); | 71 | sk->sk_data_ready(sk); |
| 72 | return 0; | 72 | return 0; |
| 73 | } | 73 | } |
| 74 | 74 | ||
diff --git a/net/atm/lec.c b/net/atm/lec.c index 5a2f602d07e1..4c5b8ba0f84f 100644 --- a/net/atm/lec.c +++ b/net/atm/lec.c | |||
| @@ -152,7 +152,7 @@ static void lec_handle_bridge(struct sk_buff *skb, struct net_device *dev) | |||
| 152 | atm_force_charge(priv->lecd, skb2->truesize); | 152 | atm_force_charge(priv->lecd, skb2->truesize); |
| 153 | sk = sk_atm(priv->lecd); | 153 | sk = sk_atm(priv->lecd); |
| 154 | skb_queue_tail(&sk->sk_receive_queue, skb2); | 154 | skb_queue_tail(&sk->sk_receive_queue, skb2); |
| 155 | sk->sk_data_ready(sk, skb2->len); | 155 | sk->sk_data_ready(sk); |
| 156 | } | 156 | } |
| 157 | } | 157 | } |
| 158 | #endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */ | 158 | #endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */ |
| @@ -447,7 +447,7 @@ static int lec_atm_send(struct atm_vcc *vcc, struct sk_buff *skb) | |||
| 447 | atm_force_charge(priv->lecd, skb2->truesize); | 447 | atm_force_charge(priv->lecd, skb2->truesize); |
| 448 | sk = sk_atm(priv->lecd); | 448 | sk = sk_atm(priv->lecd); |
| 449 | skb_queue_tail(&sk->sk_receive_queue, skb2); | 449 | skb_queue_tail(&sk->sk_receive_queue, skb2); |
| 450 | sk->sk_data_ready(sk, skb2->len); | 450 | sk->sk_data_ready(sk); |
| 451 | } | 451 | } |
| 452 | } | 452 | } |
| 453 | #endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */ | 453 | #endif /* defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE) */ |
| @@ -530,13 +530,13 @@ send_to_lecd(struct lec_priv *priv, atmlec_msg_type type, | |||
| 530 | atm_force_charge(priv->lecd, skb->truesize); | 530 | atm_force_charge(priv->lecd, skb->truesize); |
| 531 | sk = sk_atm(priv->lecd); | 531 | sk = sk_atm(priv->lecd); |
| 532 | skb_queue_tail(&sk->sk_receive_queue, skb); | 532 | skb_queue_tail(&sk->sk_receive_queue, skb); |
| 533 | sk->sk_data_ready(sk, skb->len); | 533 | sk->sk_data_ready(sk); |
| 534 | 534 | ||
| 535 | if (data != NULL) { | 535 | if (data != NULL) { |
| 536 | pr_debug("about to send %d bytes of data\n", data->len); | 536 | pr_debug("about to send %d bytes of data\n", data->len); |
| 537 | atm_force_charge(priv->lecd, data->truesize); | 537 | atm_force_charge(priv->lecd, data->truesize); |
| 538 | skb_queue_tail(&sk->sk_receive_queue, data); | 538 | skb_queue_tail(&sk->sk_receive_queue, data); |
| 539 | sk->sk_data_ready(sk, skb->len); | 539 | sk->sk_data_ready(sk); |
| 540 | } | 540 | } |
| 541 | 541 | ||
| 542 | return 0; | 542 | return 0; |
| @@ -616,7 +616,7 @@ static void lec_push(struct atm_vcc *vcc, struct sk_buff *skb) | |||
| 616 | 616 | ||
| 617 | pr_debug("%s: To daemon\n", dev->name); | 617 | pr_debug("%s: To daemon\n", dev->name); |
| 618 | skb_queue_tail(&sk->sk_receive_queue, skb); | 618 | skb_queue_tail(&sk->sk_receive_queue, skb); |
| 619 | sk->sk_data_ready(sk, skb->len); | 619 | sk->sk_data_ready(sk); |
| 620 | } else { /* Data frame, queue to protocol handlers */ | 620 | } else { /* Data frame, queue to protocol handlers */ |
| 621 | struct lec_arp_table *entry; | 621 | struct lec_arp_table *entry; |
| 622 | unsigned char *src, *dst; | 622 | unsigned char *src, *dst; |
diff --git a/net/atm/mpc.c b/net/atm/mpc.c index b71ff6b234f2..e8e0e7a8a23d 100644 --- a/net/atm/mpc.c +++ b/net/atm/mpc.c | |||
| @@ -706,7 +706,7 @@ static void mpc_push(struct atm_vcc *vcc, struct sk_buff *skb) | |||
| 706 | dprintk("(%s) control packet arrived\n", dev->name); | 706 | dprintk("(%s) control packet arrived\n", dev->name); |
| 707 | /* Pass control packets to daemon */ | 707 | /* Pass control packets to daemon */ |
| 708 | skb_queue_tail(&sk->sk_receive_queue, skb); | 708 | skb_queue_tail(&sk->sk_receive_queue, skb); |
| 709 | sk->sk_data_ready(sk, skb->len); | 709 | sk->sk_data_ready(sk); |
| 710 | return; | 710 | return; |
| 711 | } | 711 | } |
| 712 | 712 | ||
| @@ -992,7 +992,7 @@ int msg_to_mpoad(struct k_message *mesg, struct mpoa_client *mpc) | |||
| 992 | 992 | ||
| 993 | sk = sk_atm(mpc->mpoad_vcc); | 993 | sk = sk_atm(mpc->mpoad_vcc); |
| 994 | skb_queue_tail(&sk->sk_receive_queue, skb); | 994 | skb_queue_tail(&sk->sk_receive_queue, skb); |
| 995 | sk->sk_data_ready(sk, skb->len); | 995 | sk->sk_data_ready(sk); |
| 996 | 996 | ||
| 997 | return 0; | 997 | return 0; |
| 998 | } | 998 | } |
| @@ -1273,7 +1273,7 @@ static void purge_egress_shortcut(struct atm_vcc *vcc, eg_cache_entry *entry) | |||
| 1273 | 1273 | ||
| 1274 | sk = sk_atm(vcc); | 1274 | sk = sk_atm(vcc); |
| 1275 | skb_queue_tail(&sk->sk_receive_queue, skb); | 1275 | skb_queue_tail(&sk->sk_receive_queue, skb); |
| 1276 | sk->sk_data_ready(sk, skb->len); | 1276 | sk->sk_data_ready(sk); |
| 1277 | dprintk("exiting\n"); | 1277 | dprintk("exiting\n"); |
| 1278 | } | 1278 | } |
| 1279 | 1279 | ||
| @@ -1492,7 +1492,7 @@ static void __exit atm_mpoa_cleanup(void) | |||
| 1492 | 1492 | ||
| 1493 | mpc_proc_clean(); | 1493 | mpc_proc_clean(); |
| 1494 | 1494 | ||
| 1495 | del_timer(&mpc_timer); | 1495 | del_timer_sync(&mpc_timer); |
| 1496 | unregister_netdevice_notifier(&mpoa_notifier); | 1496 | unregister_netdevice_notifier(&mpoa_notifier); |
| 1497 | deregister_atm_ioctl(&atm_ioctl_ops); | 1497 | deregister_atm_ioctl(&atm_ioctl_ops); |
| 1498 | 1498 | ||
diff --git a/net/atm/raw.c b/net/atm/raw.c index b4f7b9ff3c74..2e17e97a7a8b 100644 --- a/net/atm/raw.c +++ b/net/atm/raw.c | |||
| @@ -25,7 +25,7 @@ static void atm_push_raw(struct atm_vcc *vcc, struct sk_buff *skb) | |||
| 25 | struct sock *sk = sk_atm(vcc); | 25 | struct sock *sk = sk_atm(vcc); |
| 26 | 26 | ||
| 27 | skb_queue_tail(&sk->sk_receive_queue, skb); | 27 | skb_queue_tail(&sk->sk_receive_queue, skb); |
| 28 | sk->sk_data_ready(sk, skb->len); | 28 | sk->sk_data_ready(sk); |
| 29 | } | 29 | } |
| 30 | } | 30 | } |
| 31 | 31 | ||
diff --git a/net/atm/signaling.c b/net/atm/signaling.c index 4176887e72eb..523bce72f698 100644 --- a/net/atm/signaling.c +++ b/net/atm/signaling.c | |||
| @@ -51,7 +51,7 @@ static void sigd_put_skb(struct sk_buff *skb) | |||
| 51 | #endif | 51 | #endif |
| 52 | atm_force_charge(sigd, skb->truesize); | 52 | atm_force_charge(sigd, skb->truesize); |
| 53 | skb_queue_tail(&sk_atm(sigd)->sk_receive_queue, skb); | 53 | skb_queue_tail(&sk_atm(sigd)->sk_receive_queue, skb); |
| 54 | sk_atm(sigd)->sk_data_ready(sk_atm(sigd), skb->len); | 54 | sk_atm(sigd)->sk_data_ready(sk_atm(sigd)); |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | static void modify_qos(struct atm_vcc *vcc, struct atmsvc_msg *msg) | 57 | static void modify_qos(struct atm_vcc *vcc, struct atmsvc_msg *msg) |
diff --git a/net/ax25/ax25_in.c b/net/ax25/ax25_in.c index 96f4cab3a2f9..7ed8ab724819 100644 --- a/net/ax25/ax25_in.c +++ b/net/ax25/ax25_in.c | |||
| @@ -422,7 +422,7 @@ static int ax25_rcv(struct sk_buff *skb, struct net_device *dev, | |||
| 422 | 422 | ||
| 423 | if (sk) { | 423 | if (sk) { |
| 424 | if (!sock_flag(sk, SOCK_DEAD)) | 424 | if (!sock_flag(sk, SOCK_DEAD)) |
| 425 | sk->sk_data_ready(sk, skb->len); | 425 | sk->sk_data_ready(sk); |
| 426 | sock_put(sk); | 426 | sock_put(sk); |
| 427 | } else { | 427 | } else { |
| 428 | free: | 428 | free: |
diff --git a/net/batman-adv/Kconfig b/net/batman-adv/Kconfig index fa780b76630e..11660a3aab5a 100644 --- a/net/batman-adv/Kconfig +++ b/net/batman-adv/Kconfig | |||
| @@ -50,6 +50,15 @@ config BATMAN_ADV_NC | |||
| 50 | If you think that your network does not need this feature you | 50 | If you think that your network does not need this feature you |
| 51 | can safely disable it and save some space. | 51 | can safely disable it and save some space. |
| 52 | 52 | ||
| 53 | config BATMAN_ADV_MCAST | ||
| 54 | bool "Multicast optimisation" | ||
| 55 | depends on BATMAN_ADV | ||
| 56 | default n | ||
| 57 | help | ||
| 58 | This option enables the multicast optimisation which aims to | ||
| 59 | reduce the air overhead while improving the reliability of | ||
| 60 | multicast messages. | ||
| 61 | |||
| 53 | config BATMAN_ADV_DEBUG | 62 | config BATMAN_ADV_DEBUG |
| 54 | bool "B.A.T.M.A.N. debugging" | 63 | bool "B.A.T.M.A.N. debugging" |
| 55 | depends on BATMAN_ADV | 64 | depends on BATMAN_ADV |
diff --git a/net/batman-adv/Makefile b/net/batman-adv/Makefile index 42df18f877e9..eb7d8c0388e4 100644 --- a/net/batman-adv/Makefile +++ b/net/batman-adv/Makefile | |||
| @@ -36,3 +36,4 @@ batman-adv-y += send.o | |||
| 36 | batman-adv-y += soft-interface.o | 36 | batman-adv-y += soft-interface.o |
| 37 | batman-adv-y += sysfs.o | 37 | batman-adv-y += sysfs.o |
| 38 | batman-adv-y += translation-table.o | 38 | batman-adv-y += translation-table.o |
| 39 | batman-adv-$(CONFIG_BATMAN_ADV_MCAST) += multicast.o | ||
diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c index 8323bced8e5b..b3bd4ec3fd94 100644 --- a/net/batman-adv/bat_iv_ogm.c +++ b/net/batman-adv/bat_iv_ogm.c | |||
| @@ -347,10 +347,10 @@ static void batadv_iv_ogm_iface_update_mac(struct batadv_hard_iface *hard_iface) | |||
| 347 | unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff; | 347 | unsigned char *ogm_buff = hard_iface->bat_iv.ogm_buff; |
| 348 | 348 | ||
| 349 | batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff; | 349 | batadv_ogm_packet = (struct batadv_ogm_packet *)ogm_buff; |
| 350 | memcpy(batadv_ogm_packet->orig, | 350 | ether_addr_copy(batadv_ogm_packet->orig, |
| 351 | hard_iface->net_dev->dev_addr, ETH_ALEN); | 351 | hard_iface->net_dev->dev_addr); |
| 352 | memcpy(batadv_ogm_packet->prev_sender, | 352 | ether_addr_copy(batadv_ogm_packet->prev_sender, |
| 353 | hard_iface->net_dev->dev_addr, ETH_ALEN); | 353 | hard_iface->net_dev->dev_addr); |
| 354 | } | 354 | } |
| 355 | 355 | ||
| 356 | static void | 356 | static void |
| @@ -830,7 +830,7 @@ static void batadv_iv_ogm_forward(struct batadv_orig_node *orig_node, | |||
| 830 | tvlv_len = ntohs(batadv_ogm_packet->tvlv_len); | 830 | tvlv_len = ntohs(batadv_ogm_packet->tvlv_len); |
| 831 | 831 | ||
| 832 | batadv_ogm_packet->ttl--; | 832 | batadv_ogm_packet->ttl--; |
| 833 | memcpy(batadv_ogm_packet->prev_sender, ethhdr->h_source, ETH_ALEN); | 833 | ether_addr_copy(batadv_ogm_packet->prev_sender, ethhdr->h_source); |
| 834 | 834 | ||
| 835 | /* apply hop penalty */ | 835 | /* apply hop penalty */ |
| 836 | batadv_ogm_packet->tq = batadv_hop_penalty(batadv_ogm_packet->tq, | 836 | batadv_ogm_packet->tq = batadv_hop_penalty(batadv_ogm_packet->tq, |
diff --git a/net/batman-adv/bridge_loop_avoidance.c b/net/batman-adv/bridge_loop_avoidance.c index 05f0712be5e7..6f0d9ec37950 100644 --- a/net/batman-adv/bridge_loop_avoidance.c +++ b/net/batman-adv/bridge_loop_avoidance.c | |||
| @@ -191,7 +191,7 @@ batadv_backbone_hash_find(struct batadv_priv *bat_priv, | |||
| 191 | if (!hash) | 191 | if (!hash) |
| 192 | return NULL; | 192 | return NULL; |
| 193 | 193 | ||
| 194 | memcpy(search_entry.orig, addr, ETH_ALEN); | 194 | ether_addr_copy(search_entry.orig, addr); |
| 195 | search_entry.vid = vid; | 195 | search_entry.vid = vid; |
| 196 | 196 | ||
| 197 | index = batadv_choose_backbone_gw(&search_entry, hash->size); | 197 | index = batadv_choose_backbone_gw(&search_entry, hash->size); |
| @@ -305,7 +305,7 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac, | |||
| 305 | /* normal claim frame | 305 | /* normal claim frame |
| 306 | * set Ethernet SRC to the clients mac | 306 | * set Ethernet SRC to the clients mac |
| 307 | */ | 307 | */ |
| 308 | memcpy(ethhdr->h_source, mac, ETH_ALEN); | 308 | ether_addr_copy(ethhdr->h_source, mac); |
| 309 | batadv_dbg(BATADV_DBG_BLA, bat_priv, | 309 | batadv_dbg(BATADV_DBG_BLA, bat_priv, |
| 310 | "bla_send_claim(): CLAIM %pM on vid %d\n", mac, | 310 | "bla_send_claim(): CLAIM %pM on vid %d\n", mac, |
| 311 | BATADV_PRINT_VID(vid)); | 311 | BATADV_PRINT_VID(vid)); |
| @@ -314,7 +314,7 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac, | |||
| 314 | /* unclaim frame | 314 | /* unclaim frame |
| 315 | * set HW SRC to the clients mac | 315 | * set HW SRC to the clients mac |
| 316 | */ | 316 | */ |
| 317 | memcpy(hw_src, mac, ETH_ALEN); | 317 | ether_addr_copy(hw_src, mac); |
| 318 | batadv_dbg(BATADV_DBG_BLA, bat_priv, | 318 | batadv_dbg(BATADV_DBG_BLA, bat_priv, |
| 319 | "bla_send_claim(): UNCLAIM %pM on vid %d\n", mac, | 319 | "bla_send_claim(): UNCLAIM %pM on vid %d\n", mac, |
| 320 | BATADV_PRINT_VID(vid)); | 320 | BATADV_PRINT_VID(vid)); |
| @@ -323,7 +323,7 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac, | |||
| 323 | /* announcement frame | 323 | /* announcement frame |
| 324 | * set HW SRC to the special mac containg the crc | 324 | * set HW SRC to the special mac containg the crc |
| 325 | */ | 325 | */ |
| 326 | memcpy(hw_src, mac, ETH_ALEN); | 326 | ether_addr_copy(hw_src, mac); |
| 327 | batadv_dbg(BATADV_DBG_BLA, bat_priv, | 327 | batadv_dbg(BATADV_DBG_BLA, bat_priv, |
| 328 | "bla_send_claim(): ANNOUNCE of %pM on vid %d\n", | 328 | "bla_send_claim(): ANNOUNCE of %pM on vid %d\n", |
| 329 | ethhdr->h_source, BATADV_PRINT_VID(vid)); | 329 | ethhdr->h_source, BATADV_PRINT_VID(vid)); |
| @@ -333,8 +333,8 @@ static void batadv_bla_send_claim(struct batadv_priv *bat_priv, uint8_t *mac, | |||
| 333 | * set HW SRC and header destination to the receiving backbone | 333 | * set HW SRC and header destination to the receiving backbone |
| 334 | * gws mac | 334 | * gws mac |
| 335 | */ | 335 | */ |
| 336 | memcpy(hw_src, mac, ETH_ALEN); | 336 | ether_addr_copy(hw_src, mac); |
| 337 | memcpy(ethhdr->h_dest, mac, ETH_ALEN); | 337 | ether_addr_copy(ethhdr->h_dest, mac); |
| 338 | batadv_dbg(BATADV_DBG_BLA, bat_priv, | 338 | batadv_dbg(BATADV_DBG_BLA, bat_priv, |
| 339 | "bla_send_claim(): REQUEST of %pM to %pM on vid %d\n", | 339 | "bla_send_claim(): REQUEST of %pM to %pM on vid %d\n", |
| 340 | ethhdr->h_source, ethhdr->h_dest, | 340 | ethhdr->h_source, ethhdr->h_dest, |
| @@ -395,7 +395,7 @@ batadv_bla_get_backbone_gw(struct batadv_priv *bat_priv, uint8_t *orig, | |||
| 395 | entry->bat_priv = bat_priv; | 395 | entry->bat_priv = bat_priv; |
| 396 | atomic_set(&entry->request_sent, 0); | 396 | atomic_set(&entry->request_sent, 0); |
| 397 | atomic_set(&entry->wait_periods, 0); | 397 | atomic_set(&entry->wait_periods, 0); |
| 398 | memcpy(entry->orig, orig, ETH_ALEN); | 398 | ether_addr_copy(entry->orig, orig); |
| 399 | 399 | ||
| 400 | /* one for the hash, one for returning */ | 400 | /* one for the hash, one for returning */ |
| 401 | atomic_set(&entry->refcount, 2); | 401 | atomic_set(&entry->refcount, 2); |
| @@ -563,7 +563,7 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv, | |||
| 563 | struct batadv_bla_claim search_claim; | 563 | struct batadv_bla_claim search_claim; |
| 564 | int hash_added; | 564 | int hash_added; |
| 565 | 565 | ||
| 566 | memcpy(search_claim.addr, mac, ETH_ALEN); | 566 | ether_addr_copy(search_claim.addr, mac); |
| 567 | search_claim.vid = vid; | 567 | search_claim.vid = vid; |
| 568 | claim = batadv_claim_hash_find(bat_priv, &search_claim); | 568 | claim = batadv_claim_hash_find(bat_priv, &search_claim); |
| 569 | 569 | ||
| @@ -573,7 +573,7 @@ static void batadv_bla_add_claim(struct batadv_priv *bat_priv, | |||
| 573 | if (!claim) | 573 | if (!claim) |
| 574 | return; | 574 | return; |
| 575 | 575 | ||
| 576 | memcpy(claim->addr, mac, ETH_ALEN); | 576 | ether_addr_copy(claim->addr, mac); |
| 577 | claim->vid = vid; | 577 | claim->vid = vid; |
| 578 | claim->lasttime = jiffies; | 578 | claim->lasttime = jiffies; |
| 579 | claim->backbone_gw = backbone_gw; | 579 | claim->backbone_gw = backbone_gw; |
| @@ -624,7 +624,7 @@ static void batadv_bla_del_claim(struct batadv_priv *bat_priv, | |||
| 624 | { | 624 | { |
| 625 | struct batadv_bla_claim search_claim, *claim; | 625 | struct batadv_bla_claim search_claim, *claim; |
| 626 | 626 | ||
| 627 | memcpy(search_claim.addr, mac, ETH_ALEN); | 627 | ether_addr_copy(search_claim.addr, mac); |
| 628 | search_claim.vid = vid; | 628 | search_claim.vid = vid; |
| 629 | claim = batadv_claim_hash_find(bat_priv, &search_claim); | 629 | claim = batadv_claim_hash_find(bat_priv, &search_claim); |
| 630 | if (!claim) | 630 | if (!claim) |
| @@ -882,7 +882,7 @@ static int batadv_bla_process_claim(struct batadv_priv *bat_priv, | |||
| 882 | proto = ethhdr->h_proto; | 882 | proto = ethhdr->h_proto; |
| 883 | headlen = ETH_HLEN; | 883 | headlen = ETH_HLEN; |
| 884 | if (vid & BATADV_VLAN_HAS_TAG) { | 884 | if (vid & BATADV_VLAN_HAS_TAG) { |
| 885 | vhdr = (struct vlan_ethhdr *)ethhdr; | 885 | vhdr = vlan_eth_hdr(skb); |
| 886 | proto = vhdr->h_vlan_encapsulated_proto; | 886 | proto = vhdr->h_vlan_encapsulated_proto; |
| 887 | headlen += VLAN_HLEN; | 887 | headlen += VLAN_HLEN; |
| 888 | } | 888 | } |
| @@ -1103,8 +1103,8 @@ void batadv_bla_update_orig_address(struct batadv_priv *bat_priv, | |||
| 1103 | oldif->net_dev->dev_addr)) | 1103 | oldif->net_dev->dev_addr)) |
| 1104 | continue; | 1104 | continue; |
| 1105 | 1105 | ||
| 1106 | memcpy(backbone_gw->orig, | 1106 | ether_addr_copy(backbone_gw->orig, |
| 1107 | primary_if->net_dev->dev_addr, ETH_ALEN); | 1107 | primary_if->net_dev->dev_addr); |
| 1108 | /* send an announce frame so others will ask for our | 1108 | /* send an announce frame so others will ask for our |
| 1109 | * claims and update their tables. | 1109 | * claims and update their tables. |
| 1110 | */ | 1110 | */ |
| @@ -1310,7 +1310,7 @@ int batadv_bla_check_bcast_duplist(struct batadv_priv *bat_priv, | |||
| 1310 | entry = &bat_priv->bla.bcast_duplist[curr]; | 1310 | entry = &bat_priv->bla.bcast_duplist[curr]; |
| 1311 | entry->crc = crc; | 1311 | entry->crc = crc; |
| 1312 | entry->entrytime = jiffies; | 1312 | entry->entrytime = jiffies; |
| 1313 | memcpy(entry->orig, bcast_packet->orig, ETH_ALEN); | 1313 | ether_addr_copy(entry->orig, bcast_packet->orig); |
| 1314 | bat_priv->bla.bcast_duplist_curr = curr; | 1314 | bat_priv->bla.bcast_duplist_curr = curr; |
| 1315 | 1315 | ||
| 1316 | out: | 1316 | out: |
| @@ -1458,7 +1458,7 @@ int batadv_bla_rx(struct batadv_priv *bat_priv, struct sk_buff *skb, | |||
| 1458 | if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast) | 1458 | if (is_multicast_ether_addr(ethhdr->h_dest) && is_bcast) |
| 1459 | goto handled; | 1459 | goto handled; |
| 1460 | 1460 | ||
| 1461 | memcpy(search_claim.addr, ethhdr->h_source, ETH_ALEN); | 1461 | ether_addr_copy(search_claim.addr, ethhdr->h_source); |
| 1462 | search_claim.vid = vid; | 1462 | search_claim.vid = vid; |
| 1463 | claim = batadv_claim_hash_find(bat_priv, &search_claim); | 1463 | claim = batadv_claim_hash_find(bat_priv, &search_claim); |
| 1464 | 1464 | ||
| @@ -1547,9 +1547,6 @@ int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, | |||
| 1547 | if (!atomic_read(&bat_priv->bridge_loop_avoidance)) | 1547 | if (!atomic_read(&bat_priv->bridge_loop_avoidance)) |
| 1548 | goto allow; | 1548 | goto allow; |
| 1549 | 1549 | ||
| 1550 | /* in VLAN case, the mac header might not be set. */ | ||
| 1551 | skb_reset_mac_header(skb); | ||
| 1552 | |||
| 1553 | if (batadv_bla_process_claim(bat_priv, primary_if, skb)) | 1550 | if (batadv_bla_process_claim(bat_priv, primary_if, skb)) |
| 1554 | goto handled; | 1551 | goto handled; |
| 1555 | 1552 | ||
| @@ -1560,7 +1557,7 @@ int batadv_bla_tx(struct batadv_priv *bat_priv, struct sk_buff *skb, | |||
| 1560 | if (is_multicast_ether_addr(ethhdr->h_dest)) | 1557 | if (is_multicast_ether_addr(ethhdr->h_dest)) |
| 1561 | goto handled; | 1558 | goto handled; |
| 1562 | 1559 | ||
| 1563 | memcpy(search_claim.addr, ethhdr->h_source, ETH_ALEN); | 1560 | ether_addr_copy(search_claim.addr, ethhdr->h_source); |
| 1564 | search_claim.vid = vid; | 1561 | search_claim.vid = vid; |
| 1565 | 1562 | ||
| 1566 | claim = batadv_claim_hash_find(bat_priv, &search_claim); | 1563 | claim = batadv_claim_hash_find(bat_priv, &search_claim); |
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index edee50411892..b25fd64d727b 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c | |||
| @@ -277,7 +277,7 @@ static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip, | |||
| 277 | /* if this entry is already known, just update it */ | 277 | /* if this entry is already known, just update it */ |
| 278 | if (dat_entry) { | 278 | if (dat_entry) { |
| 279 | if (!batadv_compare_eth(dat_entry->mac_addr, mac_addr)) | 279 | if (!batadv_compare_eth(dat_entry->mac_addr, mac_addr)) |
| 280 | memcpy(dat_entry->mac_addr, mac_addr, ETH_ALEN); | 280 | ether_addr_copy(dat_entry->mac_addr, mac_addr); |
| 281 | dat_entry->last_update = jiffies; | 281 | dat_entry->last_update = jiffies; |
| 282 | batadv_dbg(BATADV_DBG_DAT, bat_priv, | 282 | batadv_dbg(BATADV_DBG_DAT, bat_priv, |
| 283 | "Entry updated: %pI4 %pM (vid: %d)\n", | 283 | "Entry updated: %pI4 %pM (vid: %d)\n", |
| @@ -292,7 +292,7 @@ static void batadv_dat_entry_add(struct batadv_priv *bat_priv, __be32 ip, | |||
| 292 | 292 | ||
| 293 | dat_entry->ip = ip; | 293 | dat_entry->ip = ip; |
| 294 | dat_entry->vid = vid; | 294 | dat_entry->vid = vid; |
| 295 | memcpy(dat_entry->mac_addr, mac_addr, ETH_ALEN); | 295 | ether_addr_copy(dat_entry->mac_addr, mac_addr); |
| 296 | dat_entry->last_update = jiffies; | 296 | dat_entry->last_update = jiffies; |
| 297 | atomic_set(&dat_entry->refcount, 2); | 297 | atomic_set(&dat_entry->refcount, 2); |
| 298 | 298 | ||
| @@ -1027,6 +1027,11 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv, | |||
| 1027 | if (!skb_new) | 1027 | if (!skb_new) |
| 1028 | goto out; | 1028 | goto out; |
| 1029 | 1029 | ||
| 1030 | /* the rest of the TX path assumes that the mac_header offset pointing | ||
| 1031 | * to the inner Ethernet header has been set, therefore reset it now. | ||
| 1032 | */ | ||
| 1033 | skb_reset_mac_header(skb_new); | ||
| 1034 | |||
| 1030 | if (vid & BATADV_VLAN_HAS_TAG) | 1035 | if (vid & BATADV_VLAN_HAS_TAG) |
| 1031 | skb_new = vlan_insert_tag(skb_new, htons(ETH_P_8021Q), | 1036 | skb_new = vlan_insert_tag(skb_new, htons(ETH_P_8021Q), |
| 1032 | vid & VLAN_VID_MASK); | 1037 | vid & VLAN_VID_MASK); |
diff --git a/net/batman-adv/distributed-arp-table.h b/net/batman-adv/distributed-arp-table.h index ac9be9b67a25..d76e1d06c5b5 100644 --- a/net/batman-adv/distributed-arp-table.h +++ b/net/batman-adv/distributed-arp-table.h | |||
| @@ -25,6 +25,9 @@ | |||
| 25 | 25 | ||
| 26 | #include <linux/if_arp.h> | 26 | #include <linux/if_arp.h> |
| 27 | 27 | ||
| 28 | /** | ||
| 29 | * BATADV_DAT_ADDR_MAX - maximum address value in the DHT space | ||
| 30 | */ | ||
| 28 | #define BATADV_DAT_ADDR_MAX ((batadv_dat_addr_t)~(batadv_dat_addr_t)0) | 31 | #define BATADV_DAT_ADDR_MAX ((batadv_dat_addr_t)~(batadv_dat_addr_t)0) |
| 29 | 32 | ||
| 30 | void batadv_dat_status_update(struct net_device *net_dev); | 33 | void batadv_dat_status_update(struct net_device *net_dev); |
diff --git a/net/batman-adv/fragmentation.c b/net/batman-adv/fragmentation.c index 88df9b1d552d..bcc4bea632fa 100644 --- a/net/batman-adv/fragmentation.c +++ b/net/batman-adv/fragmentation.c | |||
| @@ -449,8 +449,8 @@ bool batadv_frag_send_packet(struct sk_buff *skb, | |||
| 449 | frag_header.reserved = 0; | 449 | frag_header.reserved = 0; |
| 450 | frag_header.no = 0; | 450 | frag_header.no = 0; |
| 451 | frag_header.total_size = htons(skb->len); | 451 | frag_header.total_size = htons(skb->len); |
| 452 | memcpy(frag_header.orig, primary_if->net_dev->dev_addr, ETH_ALEN); | 452 | ether_addr_copy(frag_header.orig, primary_if->net_dev->dev_addr); |
| 453 | memcpy(frag_header.dest, orig_node->orig, ETH_ALEN); | 453 | ether_addr_copy(frag_header.dest, orig_node->orig); |
| 454 | 454 | ||
| 455 | /* Eat and send fragments from the tail of skb */ | 455 | /* Eat and send fragments from the tail of skb */ |
| 456 | while (skb->len > max_fragment_size) { | 456 | while (skb->len > max_fragment_size) { |
diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 55cf2260d295..c835e137423b 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c | |||
| @@ -389,8 +389,6 @@ out: | |||
| 389 | batadv_neigh_ifinfo_free_ref(router_gw_tq); | 389 | batadv_neigh_ifinfo_free_ref(router_gw_tq); |
| 390 | if (router_orig_tq) | 390 | if (router_orig_tq) |
| 391 | batadv_neigh_ifinfo_free_ref(router_orig_tq); | 391 | batadv_neigh_ifinfo_free_ref(router_orig_tq); |
| 392 | |||
| 393 | return; | ||
| 394 | } | 392 | } |
| 395 | 393 | ||
| 396 | /** | 394 | /** |
| @@ -680,7 +678,7 @@ batadv_gw_dhcp_recipient_get(struct sk_buff *skb, unsigned int *header_len, | |||
| 680 | if (!pskb_may_pull(skb, *header_len + ETH_HLEN)) | 678 | if (!pskb_may_pull(skb, *header_len + ETH_HLEN)) |
| 681 | return BATADV_DHCP_NO; | 679 | return BATADV_DHCP_NO; |
| 682 | 680 | ||
| 683 | ethhdr = (struct ethhdr *)skb->data; | 681 | ethhdr = eth_hdr(skb); |
| 684 | proto = ethhdr->h_proto; | 682 | proto = ethhdr->h_proto; |
| 685 | *header_len += ETH_HLEN; | 683 | *header_len += ETH_HLEN; |
| 686 | 684 | ||
| @@ -689,7 +687,7 @@ batadv_gw_dhcp_recipient_get(struct sk_buff *skb, unsigned int *header_len, | |||
| 689 | if (!pskb_may_pull(skb, *header_len + VLAN_HLEN)) | 687 | if (!pskb_may_pull(skb, *header_len + VLAN_HLEN)) |
| 690 | return BATADV_DHCP_NO; | 688 | return BATADV_DHCP_NO; |
| 691 | 689 | ||
| 692 | vhdr = (struct vlan_ethhdr *)skb->data; | 690 | vhdr = vlan_eth_hdr(skb); |
| 693 | proto = vhdr->h_vlan_encapsulated_proto; | 691 | proto = vhdr->h_vlan_encapsulated_proto; |
| 694 | *header_len += VLAN_HLEN; | 692 | *header_len += VLAN_HLEN; |
| 695 | } | 693 | } |
| @@ -728,7 +726,7 @@ batadv_gw_dhcp_recipient_get(struct sk_buff *skb, unsigned int *header_len, | |||
| 728 | return BATADV_DHCP_NO; | 726 | return BATADV_DHCP_NO; |
| 729 | 727 | ||
| 730 | /* skb->data might have been reallocated by pskb_may_pull() */ | 728 | /* skb->data might have been reallocated by pskb_may_pull() */ |
| 731 | ethhdr = (struct ethhdr *)skb->data; | 729 | ethhdr = eth_hdr(skb); |
| 732 | if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) | 730 | if (ntohs(ethhdr->h_proto) == ETH_P_8021Q) |
| 733 | ethhdr = (struct ethhdr *)(skb->data + VLAN_HLEN); | 731 | ethhdr = (struct ethhdr *)(skb->data + VLAN_HLEN); |
| 734 | 732 | ||
| @@ -765,7 +763,7 @@ batadv_gw_dhcp_recipient_get(struct sk_buff *skb, unsigned int *header_len, | |||
| 765 | if (*p != ETH_ALEN) | 763 | if (*p != ETH_ALEN) |
| 766 | return BATADV_DHCP_NO; | 764 | return BATADV_DHCP_NO; |
| 767 | 765 | ||
| 768 | memcpy(chaddr, skb->data + chaddr_offset, ETH_ALEN); | 766 | ether_addr_copy(chaddr, skb->data + chaddr_offset); |
| 769 | } | 767 | } |
| 770 | 768 | ||
| 771 | return ret; | 769 | return ret; |
diff --git a/net/batman-adv/icmp_socket.c b/net/batman-adv/icmp_socket.c index abb9d6e0388b..161ef8f17d2e 100644 --- a/net/batman-adv/icmp_socket.c +++ b/net/batman-adv/icmp_socket.c | |||
| @@ -158,6 +158,7 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff, | |||
| 158 | struct batadv_orig_node *orig_node = NULL; | 158 | struct batadv_orig_node *orig_node = NULL; |
| 159 | struct batadv_neigh_node *neigh_node = NULL; | 159 | struct batadv_neigh_node *neigh_node = NULL; |
| 160 | size_t packet_len = sizeof(struct batadv_icmp_packet); | 160 | size_t packet_len = sizeof(struct batadv_icmp_packet); |
| 161 | uint8_t *addr; | ||
| 161 | 162 | ||
| 162 | if (len < sizeof(struct batadv_icmp_header)) { | 163 | if (len < sizeof(struct batadv_icmp_header)) { |
| 163 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, | 164 | batadv_dbg(BATADV_DBG_BATMAN, bat_priv, |
| @@ -227,10 +228,10 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff, | |||
| 227 | goto dst_unreach; | 228 | goto dst_unreach; |
| 228 | 229 | ||
| 229 | icmp_packet_rr = (struct batadv_icmp_packet_rr *)icmp_header; | 230 | icmp_packet_rr = (struct batadv_icmp_packet_rr *)icmp_header; |
| 230 | if (packet_len == sizeof(*icmp_packet_rr)) | 231 | if (packet_len == sizeof(*icmp_packet_rr)) { |
| 231 | memcpy(icmp_packet_rr->rr, | 232 | addr = neigh_node->if_incoming->net_dev->dev_addr; |
| 232 | neigh_node->if_incoming->net_dev->dev_addr, | 233 | ether_addr_copy(icmp_packet_rr->rr[0], addr); |
| 233 | ETH_ALEN); | 234 | } |
| 234 | 235 | ||
| 235 | break; | 236 | break; |
| 236 | default: | 237 | default: |
| @@ -250,7 +251,7 @@ static ssize_t batadv_socket_write(struct file *file, const char __user *buff, | |||
| 250 | goto free_skb; | 251 | goto free_skb; |
| 251 | } | 252 | } |
| 252 | 253 | ||
| 253 | memcpy(icmp_header->orig, primary_if->net_dev->dev_addr, ETH_ALEN); | 254 | ether_addr_copy(icmp_header->orig, primary_if->net_dev->dev_addr); |
| 254 | 255 | ||
| 255 | batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); | 256 | batadv_send_skb_packet(skb, neigh_node->if_incoming, neigh_node->addr); |
| 256 | goto out; | 257 | goto out; |
diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 66ae135b9f27..d1183e882167 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | #include "gateway_client.h" | 34 | #include "gateway_client.h" |
| 35 | #include "bridge_loop_avoidance.h" | 35 | #include "bridge_loop_avoidance.h" |
| 36 | #include "distributed-arp-table.h" | 36 | #include "distributed-arp-table.h" |
| 37 | #include "multicast.h" | ||
| 37 | #include "gateway_common.h" | 38 | #include "gateway_common.h" |
| 38 | #include "hash.h" | 39 | #include "hash.h" |
| 39 | #include "bat_algo.h" | 40 | #include "bat_algo.h" |
| @@ -110,6 +111,9 @@ int batadv_mesh_init(struct net_device *soft_iface) | |||
| 110 | spin_lock_init(&bat_priv->tt.last_changeset_lock); | 111 | spin_lock_init(&bat_priv->tt.last_changeset_lock); |
| 111 | spin_lock_init(&bat_priv->tt.commit_lock); | 112 | spin_lock_init(&bat_priv->tt.commit_lock); |
| 112 | spin_lock_init(&bat_priv->gw.list_lock); | 113 | spin_lock_init(&bat_priv->gw.list_lock); |
| 114 | #ifdef CONFIG_BATMAN_ADV_MCAST | ||
| 115 | spin_lock_init(&bat_priv->mcast.want_lists_lock); | ||
| 116 | #endif | ||
| 113 | spin_lock_init(&bat_priv->tvlv.container_list_lock); | 117 | spin_lock_init(&bat_priv->tvlv.container_list_lock); |
| 114 | spin_lock_init(&bat_priv->tvlv.handler_list_lock); | 118 | spin_lock_init(&bat_priv->tvlv.handler_list_lock); |
| 115 | spin_lock_init(&bat_priv->softif_vlan_list_lock); | 119 | spin_lock_init(&bat_priv->softif_vlan_list_lock); |
| @@ -117,9 +121,17 @@ int batadv_mesh_init(struct net_device *soft_iface) | |||
| 117 | INIT_HLIST_HEAD(&bat_priv->forw_bat_list); | 121 | INIT_HLIST_HEAD(&bat_priv->forw_bat_list); |
| 118 | INIT_HLIST_HEAD(&bat_priv->forw_bcast_list); | 122 | INIT_HLIST_HEAD(&bat_priv->forw_bcast_list); |
| 119 | INIT_HLIST_HEAD(&bat_priv->gw.list); | 123 | INIT_HLIST_HEAD(&bat_priv->gw.list); |
| 124 | #ifdef CONFIG_BATMAN_ADV_MCAST | ||
| 125 | INIT_HLIST_HEAD(&bat_priv->mcast.want_all_unsnoopables_list); | ||
| 126 | INIT_HLIST_HEAD(&bat_priv->mcast.want_all_ipv4_list); | ||
| 127 | INIT_HLIST_HEAD(&bat_priv->mcast.want_all_ipv6_list); | ||
| 128 | #endif | ||
| 120 | INIT_LIST_HEAD(&bat_priv->tt.changes_list); | 129 | INIT_LIST_HEAD(&bat_priv->tt.changes_list); |
| 121 | INIT_LIST_HEAD(&bat_priv->tt.req_list); | 130 | INIT_LIST_HEAD(&bat_priv->tt.req_list); |
| 122 | INIT_LIST_HEAD(&bat_priv->tt.roam_list); | 131 | INIT_LIST_HEAD(&bat_priv->tt.roam_list); |
| 132 | #ifdef CONFIG_BATMAN_ADV_MCAST | ||
| 133 | INIT_HLIST_HEAD(&bat_priv->mcast.mla_list); | ||
| 134 | #endif | ||
| 123 | INIT_HLIST_HEAD(&bat_priv->tvlv.container_list); | 135 | INIT_HLIST_HEAD(&bat_priv->tvlv.container_list); |
| 124 | INIT_HLIST_HEAD(&bat_priv->tvlv.handler_list); | 136 | INIT_HLIST_HEAD(&bat_priv->tvlv.handler_list); |
| 125 | INIT_HLIST_HEAD(&bat_priv->softif_vlan_list); | 137 | INIT_HLIST_HEAD(&bat_priv->softif_vlan_list); |
| @@ -145,6 +157,7 @@ int batadv_mesh_init(struct net_device *soft_iface) | |||
| 145 | goto err; | 157 | goto err; |
| 146 | 158 | ||
| 147 | batadv_gw_init(bat_priv); | 159 | batadv_gw_init(bat_priv); |
| 160 | batadv_mcast_init(bat_priv); | ||
| 148 | 161 | ||
| 149 | atomic_set(&bat_priv->gw.reselect, 0); | 162 | atomic_set(&bat_priv->gw.reselect, 0); |
| 150 | atomic_set(&bat_priv->mesh_state, BATADV_MESH_ACTIVE); | 163 | atomic_set(&bat_priv->mesh_state, BATADV_MESH_ACTIVE); |
| @@ -169,6 +182,8 @@ void batadv_mesh_free(struct net_device *soft_iface) | |||
| 169 | batadv_dat_free(bat_priv); | 182 | batadv_dat_free(bat_priv); |
| 170 | batadv_bla_free(bat_priv); | 183 | batadv_bla_free(bat_priv); |
| 171 | 184 | ||
| 185 | batadv_mcast_free(bat_priv); | ||
| 186 | |||
| 172 | /* Free the TT and the originator tables only after having terminated | 187 | /* Free the TT and the originator tables only after having terminated |
| 173 | * all the other depending components which may use these structures for | 188 | * all the other depending components which may use these structures for |
| 174 | * their purposes. | 189 | * their purposes. |
| @@ -1133,8 +1148,8 @@ void batadv_tvlv_unicast_send(struct batadv_priv *bat_priv, uint8_t *src, | |||
| 1133 | unicast_tvlv_packet->reserved = 0; | 1148 | unicast_tvlv_packet->reserved = 0; |
| 1134 | unicast_tvlv_packet->tvlv_len = htons(tvlv_len); | 1149 | unicast_tvlv_packet->tvlv_len = htons(tvlv_len); |
| 1135 | unicast_tvlv_packet->align = 0; | 1150 | unicast_tvlv_packet->align = 0; |
| 1136 | memcpy(unicast_tvlv_packet->src, src, ETH_ALEN); | 1151 | ether_addr_copy(unicast_tvlv_packet->src, src); |
| 1137 | memcpy(unicast_tvlv_packet->dst, dst, ETH_ALEN); | 1152 | ether_addr_copy(unicast_tvlv_packet->dst, dst); |
| 1138 | 1153 | ||
| 1139 | tvlv_buff = (unsigned char *)(unicast_tvlv_packet + 1); | 1154 | tvlv_buff = (unsigned char *)(unicast_tvlv_packet + 1); |
| 1140 | tvlv_hdr = (struct batadv_tvlv_hdr *)tvlv_buff; | 1155 | tvlv_hdr = (struct batadv_tvlv_hdr *)tvlv_buff; |
diff --git a/net/batman-adv/main.h b/net/batman-adv/main.h index 9374f1a51348..770dc890ceef 100644 --- a/net/batman-adv/main.h +++ b/net/batman-adv/main.h | |||
| @@ -24,7 +24,7 @@ | |||
| 24 | #define BATADV_DRIVER_DEVICE "batman-adv" | 24 | #define BATADV_DRIVER_DEVICE "batman-adv" |
| 25 | 25 | ||
| 26 | #ifndef BATADV_SOURCE_VERSION | 26 | #ifndef BATADV_SOURCE_VERSION |
| 27 | #define BATADV_SOURCE_VERSION "2014.1.0" | 27 | #define BATADV_SOURCE_VERSION "2014.2.0" |
| 28 | #endif | 28 | #endif |
| 29 | 29 | ||
| 30 | /* B.A.T.M.A.N. parameters */ | 30 | /* B.A.T.M.A.N. parameters */ |
| @@ -176,6 +176,8 @@ enum batadv_uev_type { | |||
| 176 | #include <linux/percpu.h> | 176 | #include <linux/percpu.h> |
| 177 | #include <linux/slab.h> | 177 | #include <linux/slab.h> |
| 178 | #include <net/sock.h> /* struct sock */ | 178 | #include <net/sock.h> /* struct sock */ |
| 179 | #include <net/addrconf.h> /* ipv6 address stuff */ | ||
| 180 | #include <linux/ip.h> | ||
| 179 | #include <net/rtnetlink.h> | 181 | #include <net/rtnetlink.h> |
| 180 | #include <linux/jiffies.h> | 182 | #include <linux/jiffies.h> |
| 181 | #include <linux/seq_file.h> | 183 | #include <linux/seq_file.h> |
diff --git a/net/batman-adv/multicast.c b/net/batman-adv/multicast.c new file mode 100644 index 000000000000..8c7ca811de6e --- /dev/null +++ b/net/batman-adv/multicast.c | |||
| @@ -0,0 +1,748 @@ | |||
| 1 | /* Copyright (C) 2014 B.A.T.M.A.N. contributors: | ||
| 2 | * | ||
| 3 | * Linus Lüssing | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or | ||
| 6 | * modify it under the terms of version 2 of the GNU General Public | ||
| 7 | * License as published by the Free Software Foundation. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, but | ||
| 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 12 | * General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License | ||
| 15 | * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #include "main.h" | ||
| 19 | #include "multicast.h" | ||
| 20 | #include "originator.h" | ||
| 21 | #include "hard-interface.h" | ||
| 22 | #include "translation-table.h" | ||
| 23 | #include "multicast.h" | ||
| 24 | |||
| 25 | /** | ||
| 26 | * batadv_mcast_mla_softif_get - get softif multicast listeners | ||
| 27 | * @dev: the device to collect multicast addresses from | ||
| 28 | * @mcast_list: a list to put found addresses into | ||
| 29 | * | ||
| 30 | * Collect multicast addresses of the local multicast listeners | ||
| 31 | * on the given soft interface, dev, in the given mcast_list. | ||
| 32 | * | ||
| 33 | * Returns -ENOMEM on memory allocation error or the number of | ||
| 34 | * items added to the mcast_list otherwise. | ||
| 35 | */ | ||
| 36 | static int batadv_mcast_mla_softif_get(struct net_device *dev, | ||
| 37 | struct hlist_head *mcast_list) | ||
| 38 | { | ||
| 39 | struct netdev_hw_addr *mc_list_entry; | ||
| 40 | struct batadv_hw_addr *new; | ||
| 41 | int ret = 0; | ||
| 42 | |||
| 43 | netif_addr_lock_bh(dev); | ||
| 44 | netdev_for_each_mc_addr(mc_list_entry, dev) { | ||
| 45 | new = kmalloc(sizeof(*new), GFP_ATOMIC); | ||
| 46 | if (!new) { | ||
| 47 | ret = -ENOMEM; | ||
| 48 | break; | ||
| 49 | } | ||
| 50 | |||
| 51 | ether_addr_copy(new->addr, mc_list_entry->addr); | ||
| 52 | hlist_add_head(&new->list, mcast_list); | ||
| 53 | ret++; | ||
| 54 | } | ||
| 55 | netif_addr_unlock_bh(dev); | ||
| 56 | |||
| 57 | return ret; | ||
| 58 | } | ||
| 59 | |||
| 60 | /** | ||
| 61 | * batadv_mcast_mla_is_duplicate - check whether an address is in a list | ||
| 62 | * @mcast_addr: the multicast address to check | ||
| 63 | * @mcast_list: the list with multicast addresses to search in | ||
| 64 | * | ||
| 65 | * Returns true if the given address is already in the given list. | ||
| 66 | * Otherwise returns false. | ||
| 67 | */ | ||
| 68 | static bool batadv_mcast_mla_is_duplicate(uint8_t *mcast_addr, | ||
| 69 | struct hlist_head *mcast_list) | ||
| 70 | { | ||
| 71 | struct batadv_hw_addr *mcast_entry; | ||
| 72 | |||
| 73 | hlist_for_each_entry(mcast_entry, mcast_list, list) | ||
| 74 | if (batadv_compare_eth(mcast_entry->addr, mcast_addr)) | ||
| 75 | return true; | ||
| 76 | |||
| 77 | return false; | ||
| 78 | } | ||
| 79 | |||
| 80 | /** | ||
| 81 | * batadv_mcast_mla_list_free - free a list of multicast addresses | ||
| 82 | * @mcast_list: the list to free | ||
| 83 | * | ||
| 84 | * Removes and frees all items in the given mcast_list. | ||
| 85 | */ | ||
| 86 | static void batadv_mcast_mla_list_free(struct hlist_head *mcast_list) | ||
| 87 | { | ||
| 88 | struct batadv_hw_addr *mcast_entry; | ||
| 89 | struct hlist_node *tmp; | ||
| 90 | |||
| 91 | hlist_for_each_entry_safe(mcast_entry, tmp, mcast_list, list) { | ||
| 92 | hlist_del(&mcast_entry->list); | ||
| 93 | kfree(mcast_entry); | ||
| 94 | } | ||
| 95 | } | ||
| 96 | |||
| 97 | /** | ||
| 98 | * batadv_mcast_mla_tt_retract - clean up multicast listener announcements | ||
| 99 | * @bat_priv: the bat priv with all the soft interface information | ||
| 100 | * @mcast_list: a list of addresses which should _not_ be removed | ||
| 101 | * | ||
| 102 | * Retracts the announcement of any multicast listener from the | ||
| 103 | * translation table except the ones listed in the given mcast_list. | ||
| 104 | * | ||
| 105 | * If mcast_list is NULL then all are retracted. | ||
| 106 | */ | ||
| 107 | static void batadv_mcast_mla_tt_retract(struct batadv_priv *bat_priv, | ||
| 108 | struct hlist_head *mcast_list) | ||
| 109 | { | ||
| 110 | struct batadv_hw_addr *mcast_entry; | ||
| 111 | struct hlist_node *tmp; | ||
| 112 | |||
| 113 | hlist_for_each_entry_safe(mcast_entry, tmp, &bat_priv->mcast.mla_list, | ||
| 114 | list) { | ||
| 115 | if (mcast_list && | ||
| 116 | batadv_mcast_mla_is_duplicate(mcast_entry->addr, | ||
| 117 | mcast_list)) | ||
| 118 | continue; | ||
| 119 | |||
| 120 | batadv_tt_local_remove(bat_priv, mcast_entry->addr, | ||
| 121 | BATADV_NO_FLAGS, | ||
| 122 | "mcast TT outdated", false); | ||
| 123 | |||
| 124 | hlist_del(&mcast_entry->list); | ||
| 125 | kfree(mcast_entry); | ||
| 126 | } | ||
| 127 | } | ||
| 128 | |||
| 129 | /** | ||
| 130 | * batadv_mcast_mla_tt_add - add multicast listener announcements | ||
| 131 | * @bat_priv: the bat priv with all the soft interface information | ||
| 132 | * @mcast_list: a list of addresses which are going to get added | ||
| 133 | * | ||
| 134 | * Adds multicast listener announcements from the given mcast_list to the | ||
| 135 | * translation table if they have not been added yet. | ||
| 136 | */ | ||
| 137 | static void batadv_mcast_mla_tt_add(struct batadv_priv *bat_priv, | ||
| 138 | struct hlist_head *mcast_list) | ||
| 139 | { | ||
| 140 | struct batadv_hw_addr *mcast_entry; | ||
| 141 | struct hlist_node *tmp; | ||
| 142 | |||
| 143 | if (!mcast_list) | ||
| 144 | return; | ||
| 145 | |||
| 146 | hlist_for_each_entry_safe(mcast_entry, tmp, mcast_list, list) { | ||
| 147 | if (batadv_mcast_mla_is_duplicate(mcast_entry->addr, | ||
| 148 | &bat_priv->mcast.mla_list)) | ||
| 149 | continue; | ||
| 150 | |||
| 151 | if (!batadv_tt_local_add(bat_priv->soft_iface, | ||
| 152 | mcast_entry->addr, BATADV_NO_FLAGS, | ||
| 153 | BATADV_NULL_IFINDEX, BATADV_NO_MARK)) | ||
| 154 | continue; | ||
| 155 | |||
| 156 | hlist_del(&mcast_entry->list); | ||
| 157 | hlist_add_head(&mcast_entry->list, &bat_priv->mcast.mla_list); | ||
| 158 | } | ||
| 159 | } | ||
| 160 | |||
| 161 | /** | ||
| 162 | * batadv_mcast_has_bridge - check whether the soft-iface is bridged | ||
| 163 | * @bat_priv: the bat priv with all the soft interface information | ||
| 164 | * | ||
| 165 | * Checks whether there is a bridge on top of our soft interface. Returns | ||
| 166 | * true if so, false otherwise. | ||
| 167 | */ | ||
| 168 | static bool batadv_mcast_has_bridge(struct batadv_priv *bat_priv) | ||
| 169 | { | ||
| 170 | struct net_device *upper = bat_priv->soft_iface; | ||
| 171 | |||
| 172 | rcu_read_lock(); | ||
| 173 | do { | ||
| 174 | upper = netdev_master_upper_dev_get_rcu(upper); | ||
| 175 | } while (upper && !(upper->priv_flags & IFF_EBRIDGE)); | ||
| 176 | rcu_read_unlock(); | ||
| 177 | |||
| 178 | return upper; | ||
| 179 | } | ||
| 180 | |||
| 181 | /** | ||
| 182 | * batadv_mcast_mla_tvlv_update - update multicast tvlv | ||
| 183 | * @bat_priv: the bat priv with all the soft interface information | ||
| 184 | * | ||
| 185 | * Updates the own multicast tvlv with our current multicast related settings, | ||
| 186 | * capabilities and inabilities. | ||
| 187 | * | ||
| 188 | * Returns true if the tvlv container is registered afterwards. Otherwise | ||
| 189 | * returns false. | ||
| 190 | */ | ||
| 191 | static bool batadv_mcast_mla_tvlv_update(struct batadv_priv *bat_priv) | ||
| 192 | { | ||
| 193 | struct batadv_tvlv_mcast_data mcast_data; | ||
| 194 | |||
| 195 | mcast_data.flags = BATADV_NO_FLAGS; | ||
| 196 | memset(mcast_data.reserved, 0, sizeof(mcast_data.reserved)); | ||
| 197 | |||
| 198 | /* Avoid attaching MLAs, if there is a bridge on top of our soft | ||
| 199 | * interface, we don't support that yet (TODO) | ||
| 200 | */ | ||
| 201 | if (batadv_mcast_has_bridge(bat_priv)) { | ||
| 202 | if (bat_priv->mcast.enabled) { | ||
| 203 | batadv_tvlv_container_unregister(bat_priv, | ||
| 204 | BATADV_TVLV_MCAST, 1); | ||
| 205 | bat_priv->mcast.enabled = false; | ||
| 206 | } | ||
| 207 | |||
| 208 | return false; | ||
| 209 | } | ||
| 210 | |||
| 211 | if (!bat_priv->mcast.enabled || | ||
| 212 | mcast_data.flags != bat_priv->mcast.flags) { | ||
| 213 | batadv_tvlv_container_register(bat_priv, BATADV_TVLV_MCAST, 1, | ||
| 214 | &mcast_data, sizeof(mcast_data)); | ||
| 215 | bat_priv->mcast.flags = mcast_data.flags; | ||
| 216 | bat_priv->mcast.enabled = true; | ||
| 217 | } | ||
| 218 | |||
| 219 | return true; | ||
| 220 | } | ||
| 221 | |||
| 222 | /** | ||
| 223 | * batadv_mcast_mla_update - update the own MLAs | ||
| 224 | * @bat_priv: the bat priv with all the soft interface information | ||
| 225 | * | ||
| 226 | * Updates the own multicast listener announcements in the translation | ||
| 227 | * table as well as the own, announced multicast tvlv container. | ||
| 228 | */ | ||
| 229 | void batadv_mcast_mla_update(struct batadv_priv *bat_priv) | ||
| 230 | { | ||
| 231 | struct net_device *soft_iface = bat_priv->soft_iface; | ||
| 232 | struct hlist_head mcast_list = HLIST_HEAD_INIT; | ||
| 233 | int ret; | ||
| 234 | |||
| 235 | if (!batadv_mcast_mla_tvlv_update(bat_priv)) | ||
| 236 | goto update; | ||
| 237 | |||
| 238 | ret = batadv_mcast_mla_softif_get(soft_iface, &mcast_list); | ||
| 239 | if (ret < 0) | ||
| 240 | goto out; | ||
| 241 | |||
| 242 | update: | ||
| 243 | batadv_mcast_mla_tt_retract(bat_priv, &mcast_list); | ||
| 244 | batadv_mcast_mla_tt_add(bat_priv, &mcast_list); | ||
| 245 | |||
| 246 | out: | ||
| 247 | batadv_mcast_mla_list_free(&mcast_list); | ||
| 248 | } | ||
| 249 | |||
| 250 | /** | ||
| 251 | * batadv_mcast_forw_mode_check_ipv4 - check for optimized forwarding potential | ||
| 252 | * @bat_priv: the bat priv with all the soft interface information | ||
| 253 | * @skb: the IPv4 packet to check | ||
| 254 | * @is_unsnoopable: stores whether the destination is snoopable | ||
| 255 | * | ||
| 256 | * Checks whether the given IPv4 packet has the potential to be forwarded with a | ||
| 257 | * mode more optimal than classic flooding. | ||
| 258 | * | ||
| 259 | * If so then returns 0. Otherwise -EINVAL is returned or -ENOMEM in case of | ||
| 260 | * memory allocation failure. | ||
| 261 | */ | ||
| 262 | static int batadv_mcast_forw_mode_check_ipv4(struct batadv_priv *bat_priv, | ||
| 263 | struct sk_buff *skb, | ||
| 264 | bool *is_unsnoopable) | ||
| 265 | { | ||
| 266 | struct iphdr *iphdr; | ||
| 267 | |||
| 268 | /* We might fail due to out-of-memory -> drop it */ | ||
| 269 | if (!pskb_may_pull(skb, sizeof(struct ethhdr) + sizeof(*iphdr))) | ||
| 270 | return -ENOMEM; | ||
| 271 | |||
| 272 | iphdr = ip_hdr(skb); | ||
| 273 | |||
| 274 | /* TODO: Implement Multicast Router Discovery (RFC4286), | ||
| 275 | * then allow scope > link local, too | ||
| 276 | */ | ||
| 277 | if (!ipv4_is_local_multicast(iphdr->daddr)) | ||
| 278 | return -EINVAL; | ||
| 279 | |||
| 280 | /* link-local multicast listeners behind a bridge are | ||
| 281 | * not snoopable (see RFC4541, section 2.1.2.2) | ||
| 282 | */ | ||
| 283 | *is_unsnoopable = true; | ||
| 284 | |||
| 285 | return 0; | ||
| 286 | } | ||
| 287 | |||
| 288 | /** | ||
| 289 | * batadv_mcast_forw_mode_check_ipv6 - check for optimized forwarding potential | ||
| 290 | * @bat_priv: the bat priv with all the soft interface information | ||
| 291 | * @skb: the IPv6 packet to check | ||
| 292 | * @is_unsnoopable: stores whether the destination is snoopable | ||
| 293 | * | ||
| 294 | * Checks whether the given IPv6 packet has the potential to be forwarded with a | ||
| 295 | * mode more optimal than classic flooding. | ||
| 296 | * | ||
| 297 | * If so then returns 0. Otherwise -EINVAL is returned or -ENOMEM if we are out | ||
| 298 | * of memory. | ||
| 299 | */ | ||
| 300 | static int batadv_mcast_forw_mode_check_ipv6(struct batadv_priv *bat_priv, | ||
| 301 | struct sk_buff *skb, | ||
| 302 | bool *is_unsnoopable) | ||
| 303 | { | ||
| 304 | struct ipv6hdr *ip6hdr; | ||
| 305 | |||
| 306 | /* We might fail due to out-of-memory -> drop it */ | ||
| 307 | if (!pskb_may_pull(skb, sizeof(struct ethhdr) + sizeof(*ip6hdr))) | ||
| 308 | return -ENOMEM; | ||
| 309 | |||
| 310 | ip6hdr = ipv6_hdr(skb); | ||
| 311 | |||
| 312 | /* TODO: Implement Multicast Router Discovery (RFC4286), | ||
| 313 | * then allow scope > link local, too | ||
| 314 | */ | ||
| 315 | if (IPV6_ADDR_MC_SCOPE(&ip6hdr->daddr) != IPV6_ADDR_SCOPE_LINKLOCAL) | ||
| 316 | return -EINVAL; | ||
| 317 | |||
| 318 | /* link-local-all-nodes multicast listeners behind a bridge are | ||
| 319 | * not snoopable (see RFC4541, section 3, paragraph 3) | ||
| 320 | */ | ||
| 321 | if (ipv6_addr_is_ll_all_nodes(&ip6hdr->daddr)) | ||
| 322 | *is_unsnoopable = true; | ||
| 323 | |||
| 324 | return 0; | ||
| 325 | } | ||
| 326 | |||
| 327 | /** | ||
| 328 | * batadv_mcast_forw_mode_check - check for optimized forwarding potential | ||
| 329 | * @bat_priv: the bat priv with all the soft interface information | ||
| 330 | * @skb: the multicast frame to check | ||
| 331 | * @is_unsnoopable: stores whether the destination is snoopable | ||
| 332 | * | ||
| 333 | * Checks whether the given multicast ethernet frame has the potential to be | ||
| 334 | * forwarded with a mode more optimal than classic flooding. | ||
| 335 | * | ||
| 336 | * If so then returns 0. Otherwise -EINVAL is returned or -ENOMEM if we are out | ||
| 337 | * of memory. | ||
| 338 | */ | ||
| 339 | static int batadv_mcast_forw_mode_check(struct batadv_priv *bat_priv, | ||
| 340 | struct sk_buff *skb, | ||
| 341 | bool *is_unsnoopable) | ||
| 342 | { | ||
| 343 | struct ethhdr *ethhdr = eth_hdr(skb); | ||
| 344 | |||
| 345 | if (!atomic_read(&bat_priv->multicast_mode)) | ||
| 346 | return -EINVAL; | ||
| 347 | |||
| 348 | if (atomic_read(&bat_priv->mcast.num_disabled)) | ||
| 349 | return -EINVAL; | ||
| 350 | |||
| 351 | switch (ntohs(ethhdr->h_proto)) { | ||
| 352 | case ETH_P_IP: | ||
| 353 | return batadv_mcast_forw_mode_check_ipv4(bat_priv, skb, | ||
| 354 | is_unsnoopable); | ||
| 355 | case ETH_P_IPV6: | ||
| 356 | return batadv_mcast_forw_mode_check_ipv6(bat_priv, skb, | ||
| 357 | is_unsnoopable); | ||
| 358 | default: | ||
| 359 | return -EINVAL; | ||
| 360 | } | ||
| 361 | } | ||
| 362 | |||
| 363 | /** | ||
| 364 | * batadv_mcast_want_all_ip_count - count nodes with unspecific mcast interest | ||
| 365 | * @bat_priv: the bat priv with all the soft interface information | ||
| 366 | * @ethhdr: ethernet header of a packet | ||
| 367 | * | ||
| 368 | * Returns the number of nodes which want all IPv4 multicast traffic if the | ||
| 369 | * given ethhdr is from an IPv4 packet or the number of nodes which want all | ||
| 370 | * IPv6 traffic if it matches an IPv6 packet. | ||
| 371 | */ | ||
| 372 | static int batadv_mcast_forw_want_all_ip_count(struct batadv_priv *bat_priv, | ||
| 373 | struct ethhdr *ethhdr) | ||
| 374 | { | ||
| 375 | switch (ntohs(ethhdr->h_proto)) { | ||
| 376 | case ETH_P_IP: | ||
| 377 | return atomic_read(&bat_priv->mcast.num_want_all_ipv4); | ||
| 378 | case ETH_P_IPV6: | ||
| 379 | return atomic_read(&bat_priv->mcast.num_want_all_ipv6); | ||
| 380 | default: | ||
| 381 | /* we shouldn't be here... */ | ||
| 382 | return 0; | ||
| 383 | } | ||
| 384 | } | ||
| 385 | |||
| 386 | /** | ||
| 387 | * batadv_mcast_forw_tt_node_get - get a multicast tt node | ||
| 388 | * @bat_priv: the bat priv with all the soft interface information | ||
| 389 | * @ethhdr: the ether header containing the multicast destination | ||
| 390 | * | ||
| 391 | * Returns an orig_node matching the multicast address provided by ethhdr | ||
| 392 | * via a translation table lookup. This increases the returned nodes refcount. | ||
| 393 | */ | ||
| 394 | static struct batadv_orig_node * | ||
| 395 | batadv_mcast_forw_tt_node_get(struct batadv_priv *bat_priv, | ||
| 396 | struct ethhdr *ethhdr) | ||
| 397 | { | ||
| 398 | return batadv_transtable_search(bat_priv, ethhdr->h_source, | ||
| 399 | ethhdr->h_dest, BATADV_NO_FLAGS); | ||
| 400 | } | ||
| 401 | |||
| 402 | /** | ||
| 403 | * batadv_mcast_want_forw_ipv4_node_get - get a node with an ipv4 flag | ||
| 404 | * @bat_priv: the bat priv with all the soft interface information | ||
| 405 | * | ||
| 406 | * Returns an orig_node which has the BATADV_MCAST_WANT_ALL_IPV4 flag set and | ||
| 407 | * increases its refcount. | ||
| 408 | */ | ||
| 409 | static struct batadv_orig_node * | ||
| 410 | batadv_mcast_forw_ipv4_node_get(struct batadv_priv *bat_priv) | ||
| 411 | { | ||
| 412 | struct batadv_orig_node *tmp_orig_node, *orig_node = NULL; | ||
| 413 | |||
| 414 | rcu_read_lock(); | ||
| 415 | hlist_for_each_entry_rcu(tmp_orig_node, | ||
| 416 | &bat_priv->mcast.want_all_ipv4_list, | ||
| 417 | mcast_want_all_ipv4_node) { | ||
| 418 | if (!atomic_inc_not_zero(&orig_node->refcount)) | ||
| 419 | continue; | ||
| 420 | |||
| 421 | orig_node = tmp_orig_node; | ||
| 422 | break; | ||
| 423 | } | ||
| 424 | rcu_read_unlock(); | ||
| 425 | |||
| 426 | return orig_node; | ||
| 427 | } | ||
| 428 | |||
| 429 | /** | ||
| 430 | * batadv_mcast_want_forw_ipv6_node_get - get a node with an ipv6 flag | ||
| 431 | * @bat_priv: the bat priv with all the soft interface information | ||
| 432 | * | ||
| 433 | * Returns an orig_node which has the BATADV_MCAST_WANT_ALL_IPV6 flag set | ||
| 434 | * and increases its refcount. | ||
| 435 | */ | ||
| 436 | static struct batadv_orig_node * | ||
| 437 | batadv_mcast_forw_ipv6_node_get(struct batadv_priv *bat_priv) | ||
| 438 | { | ||
| 439 | struct batadv_orig_node *tmp_orig_node, *orig_node = NULL; | ||
| 440 | |||
| 441 | rcu_read_lock(); | ||
| 442 | hlist_for_each_entry_rcu(tmp_orig_node, | ||
| 443 | &bat_priv->mcast.want_all_ipv6_list, | ||
| 444 | mcast_want_all_ipv6_node) { | ||
| 445 | if (!atomic_inc_not_zero(&orig_node->refcount)) | ||
| 446 | continue; | ||
| 447 | |||
| 448 | orig_node = tmp_orig_node; | ||
| 449 | break; | ||
| 450 | } | ||
| 451 | rcu_read_unlock(); | ||
| 452 | |||
| 453 | return orig_node; | ||
| 454 | } | ||
| 455 | |||
| 456 | /** | ||
| 457 | * batadv_mcast_want_forw_ip_node_get - get a node with an ipv4/ipv6 flag | ||
| 458 | * @bat_priv: the bat priv with all the soft interface information | ||
| 459 | * @ethhdr: an ethernet header to determine the protocol family from | ||
| 460 | * | ||
| 461 | * Returns an orig_node which has the BATADV_MCAST_WANT_ALL_IPV4 or | ||
| 462 | * BATADV_MCAST_WANT_ALL_IPV6 flag, depending on the provided ethhdr, set and | ||
| 463 | * increases its refcount. | ||
| 464 | */ | ||
| 465 | static struct batadv_orig_node * | ||
| 466 | batadv_mcast_forw_ip_node_get(struct batadv_priv *bat_priv, | ||
| 467 | struct ethhdr *ethhdr) | ||
| 468 | { | ||
| 469 | switch (ntohs(ethhdr->h_proto)) { | ||
| 470 | case ETH_P_IP: | ||
| 471 | return batadv_mcast_forw_ipv4_node_get(bat_priv); | ||
| 472 | case ETH_P_IPV6: | ||
| 473 | return batadv_mcast_forw_ipv6_node_get(bat_priv); | ||
| 474 | default: | ||
| 475 | /* we shouldn't be here... */ | ||
| 476 | return NULL; | ||
| 477 | } | ||
| 478 | } | ||
| 479 | |||
| 480 | /** | ||
| 481 | * batadv_mcast_want_forw_unsnoop_node_get - get a node with an unsnoopable flag | ||
| 482 | * @bat_priv: the bat priv with all the soft interface information | ||
| 483 | * | ||
| 484 | * Returns an orig_node which has the BATADV_MCAST_WANT_ALL_UNSNOOPABLES flag | ||
| 485 | * set and increases its refcount. | ||
| 486 | */ | ||
| 487 | static struct batadv_orig_node * | ||
| 488 | batadv_mcast_forw_unsnoop_node_get(struct batadv_priv *bat_priv) | ||
| 489 | { | ||
| 490 | struct batadv_orig_node *tmp_orig_node, *orig_node = NULL; | ||
| 491 | |||
| 492 | rcu_read_lock(); | ||
| 493 | hlist_for_each_entry_rcu(tmp_orig_node, | ||
| 494 | &bat_priv->mcast.want_all_unsnoopables_list, | ||
| 495 | mcast_want_all_unsnoopables_node) { | ||
| 496 | if (!atomic_inc_not_zero(&orig_node->refcount)) | ||
| 497 | continue; | ||
| 498 | |||
| 499 | orig_node = tmp_orig_node; | ||
| 500 | break; | ||
| 501 | } | ||
| 502 | rcu_read_unlock(); | ||
| 503 | |||
| 504 | return orig_node; | ||
| 505 | } | ||
| 506 | |||
| 507 | /** | ||
| 508 | * batadv_mcast_forw_mode - check on how to forward a multicast packet | ||
| 509 | * @bat_priv: the bat priv with all the soft interface information | ||
| 510 | * @skb: The multicast packet to check | ||
| 511 | * @orig: an originator to be set to forward the skb to | ||
| 512 | * | ||
| 513 | * Returns the forwarding mode as enum batadv_forw_mode and in case of | ||
| 514 | * BATADV_FORW_SINGLE set the orig to the single originator the skb | ||
| 515 | * should be forwarded to. | ||
| 516 | */ | ||
| 517 | enum batadv_forw_mode | ||
| 518 | batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb, | ||
| 519 | struct batadv_orig_node **orig) | ||
| 520 | { | ||
| 521 | int ret, tt_count, ip_count, unsnoop_count, total_count; | ||
| 522 | bool is_unsnoopable = false; | ||
| 523 | struct ethhdr *ethhdr; | ||
| 524 | |||
| 525 | ret = batadv_mcast_forw_mode_check(bat_priv, skb, &is_unsnoopable); | ||
| 526 | if (ret == -ENOMEM) | ||
| 527 | return BATADV_FORW_NONE; | ||
| 528 | else if (ret < 0) | ||
| 529 | return BATADV_FORW_ALL; | ||
| 530 | |||
| 531 | ethhdr = eth_hdr(skb); | ||
| 532 | |||
| 533 | tt_count = batadv_tt_global_hash_count(bat_priv, ethhdr->h_dest, | ||
| 534 | BATADV_NO_FLAGS); | ||
| 535 | ip_count = batadv_mcast_forw_want_all_ip_count(bat_priv, ethhdr); | ||
| 536 | unsnoop_count = !is_unsnoopable ? 0 : | ||
| 537 | atomic_read(&bat_priv->mcast.num_want_all_unsnoopables); | ||
| 538 | |||
| 539 | total_count = tt_count + ip_count + unsnoop_count; | ||
| 540 | |||
| 541 | switch (total_count) { | ||
| 542 | case 1: | ||
| 543 | if (tt_count) | ||
| 544 | *orig = batadv_mcast_forw_tt_node_get(bat_priv, ethhdr); | ||
| 545 | else if (ip_count) | ||
| 546 | *orig = batadv_mcast_forw_ip_node_get(bat_priv, ethhdr); | ||
| 547 | else if (unsnoop_count) | ||
| 548 | *orig = batadv_mcast_forw_unsnoop_node_get(bat_priv); | ||
| 549 | |||
| 550 | if (*orig) | ||
| 551 | return BATADV_FORW_SINGLE; | ||
| 552 | |||
| 553 | /* fall through */ | ||
| 554 | case 0: | ||
| 555 | return BATADV_FORW_NONE; | ||
| 556 | default: | ||
| 557 | return BATADV_FORW_ALL; | ||
| 558 | } | ||
| 559 | } | ||
| 560 | |||
| 561 | /** | ||
| 562 | * batadv_mcast_want_unsnoop_update - update unsnoop counter and list | ||
| 563 | * @bat_priv: the bat priv with all the soft interface information | ||
| 564 | * @orig: the orig_node which multicast state might have changed of | ||
| 565 | * @mcast_flags: flags indicating the new multicast state | ||
| 566 | * | ||
| 567 | * If the BATADV_MCAST_WANT_ALL_UNSNOOPABLES flag of this originator, | ||
| 568 | * orig, has toggled then this method updates counter and list accordingly. | ||
| 569 | */ | ||
| 570 | static void batadv_mcast_want_unsnoop_update(struct batadv_priv *bat_priv, | ||
| 571 | struct batadv_orig_node *orig, | ||
| 572 | uint8_t mcast_flags) | ||
| 573 | { | ||
| 574 | /* switched from flag unset to set */ | ||
| 575 | if (mcast_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES && | ||
| 576 | !(orig->mcast_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES)) { | ||
| 577 | atomic_inc(&bat_priv->mcast.num_want_all_unsnoopables); | ||
| 578 | |||
| 579 | spin_lock_bh(&bat_priv->mcast.want_lists_lock); | ||
| 580 | hlist_add_head_rcu(&orig->mcast_want_all_unsnoopables_node, | ||
| 581 | &bat_priv->mcast.want_all_unsnoopables_list); | ||
| 582 | spin_unlock_bh(&bat_priv->mcast.want_lists_lock); | ||
| 583 | /* switched from flag set to unset */ | ||
| 584 | } else if (!(mcast_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES) && | ||
| 585 | orig->mcast_flags & BATADV_MCAST_WANT_ALL_UNSNOOPABLES) { | ||
| 586 | atomic_dec(&bat_priv->mcast.num_want_all_unsnoopables); | ||
| 587 | |||
| 588 | spin_lock_bh(&bat_priv->mcast.want_lists_lock); | ||
| 589 | hlist_del_rcu(&orig->mcast_want_all_unsnoopables_node); | ||
| 590 | spin_unlock_bh(&bat_priv->mcast.want_lists_lock); | ||
| 591 | } | ||
| 592 | } | ||
| 593 | |||
| 594 | /** | ||
| 595 | * batadv_mcast_want_ipv4_update - update want-all-ipv4 counter and list | ||
| 596 | * @bat_priv: the bat priv with all the soft interface information | ||
| 597 | * @orig: the orig_node which multicast state might have changed of | ||
| 598 | * @mcast_flags: flags indicating the new multicast state | ||
| 599 | * | ||
| 600 | * If the BATADV_MCAST_WANT_ALL_IPV4 flag of this originator, orig, has | ||
| 601 | * toggled then this method updates counter and list accordingly. | ||
| 602 | */ | ||
| 603 | static void batadv_mcast_want_ipv4_update(struct batadv_priv *bat_priv, | ||
| 604 | struct batadv_orig_node *orig, | ||
| 605 | uint8_t mcast_flags) | ||
| 606 | { | ||
| 607 | /* switched from flag unset to set */ | ||
| 608 | if (mcast_flags & BATADV_MCAST_WANT_ALL_IPV4 && | ||
| 609 | !(orig->mcast_flags & BATADV_MCAST_WANT_ALL_IPV4)) { | ||
| 610 | atomic_inc(&bat_priv->mcast.num_want_all_ipv4); | ||
| 611 | |||
| 612 | spin_lock_bh(&bat_priv->mcast.want_lists_lock); | ||
| 613 | hlist_add_head_rcu(&orig->mcast_want_all_ipv4_node, | ||
| 614 | &bat_priv->mcast.want_all_ipv4_list); | ||
| 615 | spin_unlock_bh(&bat_priv->mcast.want_lists_lock); | ||
| 616 | /* switched from flag set to unset */ | ||
| 617 | } else if (!(mcast_flags & BATADV_MCAST_WANT_ALL_IPV4) && | ||
| 618 | orig->mcast_flags & BATADV_MCAST_WANT_ALL_IPV4) { | ||
| 619 | atomic_dec(&bat_priv->mcast.num_want_all_ipv4); | ||
| 620 | |||
| 621 | spin_lock_bh(&bat_priv->mcast.want_lists_lock); | ||
| 622 | hlist_del_rcu(&orig->mcast_want_all_ipv4_node); | ||
| 623 | spin_unlock_bh(&bat_priv->mcast.want_lists_lock); | ||
| 624 | } | ||
| 625 | } | ||
| 626 | |||
| 627 | /** | ||
| 628 | * batadv_mcast_want_ipv6_update - update want-all-ipv6 counter and list | ||
| 629 | * @bat_priv: the bat priv with all the soft interface information | ||
| 630 | * @orig: the orig_node which multicast state might have changed of | ||
| 631 | * @mcast_flags: flags indicating the new multicast state | ||
| 632 | * | ||
| 633 | * If the BATADV_MCAST_WANT_ALL_IPV6 flag of this originator, orig, has | ||
| 634 | * toggled then this method updates counter and list accordingly. | ||
| 635 | */ | ||
| 636 | static void batadv_mcast_want_ipv6_update(struct batadv_priv *bat_priv, | ||
| 637 | struct batadv_orig_node *orig, | ||
| 638 | uint8_t mcast_flags) | ||
| 639 | { | ||
| 640 | /* switched from flag unset to set */ | ||
| 641 | if (mcast_flags & BATADV_MCAST_WANT_ALL_IPV6 && | ||
| 642 | !(orig->mcast_flags & BATADV_MCAST_WANT_ALL_IPV6)) { | ||
| 643 | atomic_inc(&bat_priv->mcast.num_want_all_ipv6); | ||
| 644 | |||
| 645 | spin_lock_bh(&bat_priv->mcast.want_lists_lock); | ||
| 646 | hlist_add_head_rcu(&orig->mcast_want_all_ipv6_node, | ||
| 647 | &bat_priv->mcast.want_all_ipv6_list); | ||
| 648 | spin_unlock_bh(&bat_priv->mcast.want_lists_lock); | ||
| 649 | /* switched from flag set to unset */ | ||
| 650 | } else if (!(mcast_flags & BATADV_MCAST_WANT_ALL_IPV6) && | ||
| 651 | orig->mcast_flags & BATADV_MCAST_WANT_ALL_IPV6) { | ||
| 652 | atomic_dec(&bat_priv->mcast.num_want_all_ipv6); | ||
| 653 | |||
| 654 | spin_lock_bh(&bat_priv->mcast.want_lists_lock); | ||
| 655 | hlist_del_rcu(&orig->mcast_want_all_ipv6_node); | ||
| 656 | spin_unlock_bh(&bat_priv->mcast.want_lists_lock); | ||
| 657 | } | ||
| 658 | } | ||
| 659 | |||
| 660 | /** | ||
| 661 | * batadv_mcast_tvlv_ogm_handler_v1 - process incoming multicast tvlv container | ||
| 662 | * @bat_priv: the bat priv with all the soft interface information | ||
| 663 | * @orig: the orig_node of the ogm | ||
| 664 | * @flags: flags indicating the tvlv state (see batadv_tvlv_handler_flags) | ||
| 665 | * @tvlv_value: tvlv buffer containing the multicast data | ||
| 666 | * @tvlv_value_len: tvlv buffer length | ||
| 667 | */ | ||
| 668 | static void batadv_mcast_tvlv_ogm_handler_v1(struct batadv_priv *bat_priv, | ||
| 669 | struct batadv_orig_node *orig, | ||
| 670 | uint8_t flags, | ||
| 671 | void *tvlv_value, | ||
| 672 | uint16_t tvlv_value_len) | ||
| 673 | { | ||
| 674 | bool orig_mcast_enabled = !(flags & BATADV_TVLV_HANDLER_OGM_CIFNOTFND); | ||
| 675 | uint8_t mcast_flags = BATADV_NO_FLAGS; | ||
| 676 | bool orig_initialized; | ||
| 677 | |||
| 678 | orig_initialized = orig->capa_initialized & BATADV_ORIG_CAPA_HAS_MCAST; | ||
| 679 | |||
| 680 | /* If mcast support is turned on decrease the disabled mcast node | ||
| 681 | * counter only if we had increased it for this node before. If this | ||
| 682 | * is a completely new orig_node no need to decrease the counter. | ||
| 683 | */ | ||
| 684 | if (orig_mcast_enabled && | ||
| 685 | !(orig->capabilities & BATADV_ORIG_CAPA_HAS_MCAST)) { | ||
| 686 | if (orig_initialized) | ||
| 687 | atomic_dec(&bat_priv->mcast.num_disabled); | ||
| 688 | orig->capabilities |= BATADV_ORIG_CAPA_HAS_MCAST; | ||
| 689 | /* If mcast support is being switched off increase the disabled | ||
| 690 | * mcast node counter. | ||
| 691 | */ | ||
| 692 | } else if (!orig_mcast_enabled && | ||
| 693 | orig->capabilities & BATADV_ORIG_CAPA_HAS_MCAST) { | ||
| 694 | atomic_inc(&bat_priv->mcast.num_disabled); | ||
| 695 | orig->capabilities &= ~BATADV_ORIG_CAPA_HAS_MCAST; | ||
| 696 | } | ||
| 697 | |||
| 698 | orig->capa_initialized |= BATADV_ORIG_CAPA_HAS_MCAST; | ||
| 699 | |||
| 700 | if (orig_mcast_enabled && tvlv_value && | ||
| 701 | (tvlv_value_len >= sizeof(mcast_flags))) | ||
| 702 | mcast_flags = *(uint8_t *)tvlv_value; | ||
| 703 | |||
| 704 | batadv_mcast_want_unsnoop_update(bat_priv, orig, mcast_flags); | ||
| 705 | batadv_mcast_want_ipv4_update(bat_priv, orig, mcast_flags); | ||
| 706 | batadv_mcast_want_ipv6_update(bat_priv, orig, mcast_flags); | ||
| 707 | |||
| 708 | orig->mcast_flags = mcast_flags; | ||
| 709 | } | ||
| 710 | |||
| 711 | /** | ||
| 712 | * batadv_mcast_init - initialize the multicast optimizations structures | ||
| 713 | * @bat_priv: the bat priv with all the soft interface information | ||
| 714 | */ | ||
| 715 | void batadv_mcast_init(struct batadv_priv *bat_priv) | ||
| 716 | { | ||
| 717 | batadv_tvlv_handler_register(bat_priv, batadv_mcast_tvlv_ogm_handler_v1, | ||
| 718 | NULL, BATADV_TVLV_MCAST, 1, | ||
| 719 | BATADV_TVLV_HANDLER_OGM_CIFNOTFND); | ||
| 720 | } | ||
| 721 | |||
| 722 | /** | ||
| 723 | * batadv_mcast_free - free the multicast optimizations structures | ||
| 724 | * @bat_priv: the bat priv with all the soft interface information | ||
| 725 | */ | ||
| 726 | void batadv_mcast_free(struct batadv_priv *bat_priv) | ||
| 727 | { | ||
| 728 | batadv_tvlv_container_unregister(bat_priv, BATADV_TVLV_MCAST, 1); | ||
| 729 | batadv_tvlv_handler_unregister(bat_priv, BATADV_TVLV_MCAST, 1); | ||
| 730 | |||
| 731 | batadv_mcast_mla_tt_retract(bat_priv, NULL); | ||
| 732 | } | ||
| 733 | |||
| 734 | /** | ||
| 735 | * batadv_mcast_purge_orig - reset originator global mcast state modifications | ||
| 736 | * @orig: the originator which is going to get purged | ||
| 737 | */ | ||
| 738 | void batadv_mcast_purge_orig(struct batadv_orig_node *orig) | ||
| 739 | { | ||
| 740 | struct batadv_priv *bat_priv = orig->bat_priv; | ||
| 741 | |||
| 742 | if (!(orig->capabilities & BATADV_ORIG_CAPA_HAS_MCAST)) | ||
| 743 | atomic_dec(&bat_priv->mcast.num_disabled); | ||
| 744 | |||
| 745 | batadv_mcast_want_unsnoop_update(bat_priv, orig, BATADV_NO_FLAGS); | ||
| 746 | batadv_mcast_want_ipv4_update(bat_priv, orig, BATADV_NO_FLAGS); | ||
| 747 | batadv_mcast_want_ipv6_update(bat_priv, orig, BATADV_NO_FLAGS); | ||
| 748 | } | ||
diff --git a/net/batman-adv/multicast.h b/net/batman-adv/multicast.h new file mode 100644 index 000000000000..73b5d45819c1 --- /dev/null +++ b/net/batman-adv/multicast.h | |||
| @@ -0,0 +1,80 @@ | |||
| 1 | /* Copyright (C) 2014 B.A.T.M.A.N. contributors: | ||
| 2 | * | ||
| 3 | * Linus Lüssing | ||
| 4 | * | ||
| 5 | * This program is free software; you can redistribute it and/or | ||
| 6 | * modify it under the terms of version 2 of the GNU General Public | ||
| 7 | * License as published by the Free Software Foundation. | ||
| 8 | * | ||
| 9 | * This program is distributed in the hope that it will be useful, but | ||
| 10 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 12 | * General Public License for more details. | ||
| 13 | * | ||
| 14 | * You should have received a copy of the GNU General Public License | ||
| 15 | * along with this program; if not, see <http://www.gnu.org/licenses/>. | ||
| 16 | */ | ||
| 17 | |||
| 18 | #ifndef _NET_BATMAN_ADV_MULTICAST_H_ | ||
| 19 | #define _NET_BATMAN_ADV_MULTICAST_H_ | ||
| 20 | |||
| 21 | /** | ||
| 22 | * batadv_forw_mode - the way a packet should be forwarded as | ||
| 23 | * @BATADV_FORW_ALL: forward the packet to all nodes (currently via classic | ||
| 24 | * flooding) | ||
| 25 | * @BATADV_FORW_SINGLE: forward the packet to a single node (currently via the | ||
| 26 | * BATMAN unicast routing protocol) | ||
| 27 | * @BATADV_FORW_NONE: don't forward, drop it | ||
| 28 | */ | ||
| 29 | enum batadv_forw_mode { | ||
| 30 | BATADV_FORW_ALL, | ||
| 31 | BATADV_FORW_SINGLE, | ||
| 32 | BATADV_FORW_NONE, | ||
| 33 | }; | ||
| 34 | |||
| 35 | #ifdef CONFIG_BATMAN_ADV_MCAST | ||
| 36 | |||
| 37 | void batadv_mcast_mla_update(struct batadv_priv *bat_priv); | ||
| 38 | |||
| 39 | enum batadv_forw_mode | ||
| 40 | batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb, | ||
| 41 | struct batadv_orig_node **mcast_single_orig); | ||
| 42 | |||
| 43 | void batadv_mcast_init(struct batadv_priv *bat_priv); | ||
| 44 | |||
| 45 | void batadv_mcast_free(struct batadv_priv *bat_priv); | ||
| 46 | |||
| 47 | void batadv_mcast_purge_orig(struct batadv_orig_node *orig_node); | ||
| 48 | |||
| 49 | #else | ||
| 50 | |||
| 51 | static inline void batadv_mcast_mla_update(struct batadv_priv *bat_priv) | ||
| 52 | { | ||
| 53 | return; | ||
| 54 | } | ||
| 55 | |||
| 56 | static inline enum batadv_forw_mode | ||
| 57 | batadv_mcast_forw_mode(struct batadv_priv *bat_priv, struct sk_buff *skb, | ||
| 58 | struct batadv_orig_node **mcast_single_orig) | ||
| 59 | { | ||
| 60 | return BATADV_FORW_ALL; | ||
| 61 | } | ||
| 62 | |||
| 63 | static inline int batadv_mcast_init(struct batadv_priv *bat_priv) | ||
| 64 | { | ||
| 65 | return 0; | ||
| 66 | } | ||
| 67 | |||
| 68 | static inline void batadv_mcast_free(struct batadv_priv *bat_priv) | ||
| 69 | { | ||
| 70 | return; | ||
| 71 | } | ||
| 72 | |||
| 73 | static inline void batadv_mcast_purge_orig(struct batadv_orig_node *orig_node) | ||
| 74 | { | ||
| 75 | return; | ||
| 76 | } | ||
| 77 | |||
| 78 | #endif /* CONFIG_BATMAN_ADV_MCAST */ | ||
| 79 | |||
| 80 | #endif /* _NET_BATMAN_ADV_MULTICAST_H_ */ | ||
diff --git a/net/batman-adv/network-coding.c b/net/batman-adv/network-coding.c index f1b604d88dc3..a9546fe541eb 100644 --- a/net/batman-adv/network-coding.c +++ b/net/batman-adv/network-coding.c | |||
| @@ -819,7 +819,7 @@ static struct batadv_nc_node | |||
| 819 | 819 | ||
| 820 | /* Initialize nc_node */ | 820 | /* Initialize nc_node */ |
| 821 | INIT_LIST_HEAD(&nc_node->list); | 821 | INIT_LIST_HEAD(&nc_node->list); |
| 822 | memcpy(nc_node->addr, orig_node->orig, ETH_ALEN); | 822 | ether_addr_copy(nc_node->addr, orig_node->orig); |
| 823 | nc_node->orig_node = orig_neigh_node; | 823 | nc_node->orig_node = orig_neigh_node; |
| 824 | atomic_set(&nc_node->refcount, 2); | 824 | atomic_set(&nc_node->refcount, 2); |
| 825 | 825 | ||
| @@ -941,8 +941,8 @@ static struct batadv_nc_path *batadv_nc_get_path(struct batadv_priv *bat_priv, | |||
| 941 | spin_lock_init(&nc_path->packet_list_lock); | 941 | spin_lock_init(&nc_path->packet_list_lock); |
| 942 | atomic_set(&nc_path->refcount, 2); | 942 | atomic_set(&nc_path->refcount, 2); |
| 943 | nc_path->last_valid = jiffies; | 943 | nc_path->last_valid = jiffies; |
| 944 | memcpy(nc_path->next_hop, dst, ETH_ALEN); | 944 | ether_addr_copy(nc_path->next_hop, dst); |
| 945 | memcpy(nc_path->prev_hop, src, ETH_ALEN); | 945 | ether_addr_copy(nc_path->prev_hop, src); |
| 946 | 946 | ||
| 947 | batadv_dbg(BATADV_DBG_NC, bat_priv, "Adding nc_path %pM -> %pM\n", | 947 | batadv_dbg(BATADV_DBG_NC, bat_priv, "Adding nc_path %pM -> %pM\n", |
| 948 | nc_path->prev_hop, | 948 | nc_path->prev_hop, |
| @@ -1114,15 +1114,15 @@ static bool batadv_nc_code_packets(struct batadv_priv *bat_priv, | |||
| 1114 | coded_packet->ttl = packet1->ttl; | 1114 | coded_packet->ttl = packet1->ttl; |
| 1115 | 1115 | ||
| 1116 | /* Info about first unicast packet */ | 1116 | /* Info about first unicast packet */ |
| 1117 | memcpy(coded_packet->first_source, first_source, ETH_ALEN); | 1117 | ether_addr_copy(coded_packet->first_source, first_source); |
| 1118 | memcpy(coded_packet->first_orig_dest, packet1->dest, ETH_ALEN); | 1118 | ether_addr_copy(coded_packet->first_orig_dest, packet1->dest); |
| 1119 | coded_packet->first_crc = packet_id1; | 1119 | coded_packet->first_crc = packet_id1; |
| 1120 | coded_packet->first_ttvn = packet1->ttvn; | 1120 | coded_packet->first_ttvn = packet1->ttvn; |
| 1121 | 1121 | ||
| 1122 | /* Info about second unicast packet */ | 1122 | /* Info about second unicast packet */ |
| 1123 | memcpy(coded_packet->second_dest, second_dest, ETH_ALEN); | 1123 | ether_addr_copy(coded_packet->second_dest, second_dest); |
| 1124 | memcpy(coded_packet->second_source, second_source, ETH_ALEN); | 1124 | ether_addr_copy(coded_packet->second_source, second_source); |
| 1125 | memcpy(coded_packet->second_orig_dest, packet2->dest, ETH_ALEN); | 1125 | ether_addr_copy(coded_packet->second_orig_dest, packet2->dest); |
| 1126 | coded_packet->second_crc = packet_id2; | 1126 | coded_packet->second_crc = packet_id2; |
| 1127 | coded_packet->second_ttl = packet2->ttl; | 1127 | coded_packet->second_ttl = packet2->ttl; |
| 1128 | coded_packet->second_ttvn = packet2->ttvn; | 1128 | coded_packet->second_ttvn = packet2->ttvn; |
| @@ -1349,8 +1349,8 @@ static void batadv_nc_skb_store_before_coding(struct batadv_priv *bat_priv, | |||
| 1349 | 1349 | ||
| 1350 | /* Set the mac header as if we actually sent the packet uncoded */ | 1350 | /* Set the mac header as if we actually sent the packet uncoded */ |
| 1351 | ethhdr = eth_hdr(skb); | 1351 | ethhdr = eth_hdr(skb); |
| 1352 | memcpy(ethhdr->h_source, ethhdr->h_dest, ETH_ALEN); | 1352 | ether_addr_copy(ethhdr->h_source, ethhdr->h_dest); |
| 1353 | memcpy(ethhdr->h_dest, eth_dst_new, ETH_ALEN); | 1353 | ether_addr_copy(ethhdr->h_dest, eth_dst_new); |
| 1354 | 1354 | ||
| 1355 | /* Set data pointer to MAC header to mimic packets from our tx path */ | 1355 | /* Set data pointer to MAC header to mimic packets from our tx path */ |
| 1356 | skb_push(skb, ETH_HLEN); | 1356 | skb_push(skb, ETH_HLEN); |
| @@ -1636,7 +1636,7 @@ batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb, | |||
| 1636 | 1636 | ||
| 1637 | /* Reconstruct original mac header */ | 1637 | /* Reconstruct original mac header */ |
| 1638 | ethhdr = eth_hdr(skb); | 1638 | ethhdr = eth_hdr(skb); |
| 1639 | memcpy(ethhdr, ðhdr_tmp, sizeof(*ethhdr)); | 1639 | *ethhdr = ethhdr_tmp; |
| 1640 | 1640 | ||
| 1641 | /* Select the correct unicast header information based on the location | 1641 | /* Select the correct unicast header information based on the location |
| 1642 | * of our mac address in the coded_packet header | 1642 | * of our mac address in the coded_packet header |
| @@ -1646,7 +1646,7 @@ batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb, | |||
| 1646 | * so the Ethernet address must be copied to h_dest and | 1646 | * so the Ethernet address must be copied to h_dest and |
| 1647 | * pkt_type changed from PACKET_OTHERHOST to PACKET_HOST | 1647 | * pkt_type changed from PACKET_OTHERHOST to PACKET_HOST |
| 1648 | */ | 1648 | */ |
| 1649 | memcpy(ethhdr->h_dest, coded_packet_tmp.second_dest, ETH_ALEN); | 1649 | ether_addr_copy(ethhdr->h_dest, coded_packet_tmp.second_dest); |
| 1650 | skb->pkt_type = PACKET_HOST; | 1650 | skb->pkt_type = PACKET_HOST; |
| 1651 | 1651 | ||
| 1652 | orig_dest = coded_packet_tmp.second_orig_dest; | 1652 | orig_dest = coded_packet_tmp.second_orig_dest; |
| @@ -1682,7 +1682,7 @@ batadv_nc_skb_decode_packet(struct batadv_priv *bat_priv, struct sk_buff *skb, | |||
| 1682 | unicast_packet->packet_type = BATADV_UNICAST; | 1682 | unicast_packet->packet_type = BATADV_UNICAST; |
| 1683 | unicast_packet->version = BATADV_COMPAT_VERSION; | 1683 | unicast_packet->version = BATADV_COMPAT_VERSION; |
| 1684 | unicast_packet->ttl = ttl; | 1684 | unicast_packet->ttl = ttl; |
| 1685 | memcpy(unicast_packet->dest, orig_dest, ETH_ALEN); | 1685 | ether_addr_copy(unicast_packet->dest, orig_dest); |
| 1686 | unicast_packet->ttvn = ttvn; | 1686 | unicast_packet->ttvn = ttvn; |
| 1687 | 1687 | ||
| 1688 | batadv_nc_packet_free(nc_packet); | 1688 | batadv_nc_packet_free(nc_packet); |
diff --git a/net/batman-adv/originator.c b/net/batman-adv/originator.c index 853941629dc1..ffd9dfbd9b0e 100644 --- a/net/batman-adv/originator.c +++ b/net/batman-adv/originator.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include "bridge_loop_avoidance.h" | 27 | #include "bridge_loop_avoidance.h" |
| 28 | #include "network-coding.h" | 28 | #include "network-coding.h" |
| 29 | #include "fragmentation.h" | 29 | #include "fragmentation.h" |
| 30 | #include "multicast.h" | ||
| 30 | 31 | ||
| 31 | /* hash class keys */ | 32 | /* hash class keys */ |
| 32 | static struct lock_class_key batadv_orig_hash_lock_class_key; | 33 | static struct lock_class_key batadv_orig_hash_lock_class_key; |
| @@ -446,7 +447,7 @@ batadv_neigh_node_new(struct batadv_hard_iface *hard_iface, | |||
| 446 | INIT_HLIST_HEAD(&neigh_node->ifinfo_list); | 447 | INIT_HLIST_HEAD(&neigh_node->ifinfo_list); |
| 447 | spin_lock_init(&neigh_node->ifinfo_lock); | 448 | spin_lock_init(&neigh_node->ifinfo_lock); |
| 448 | 449 | ||
| 449 | memcpy(neigh_node->addr, neigh_addr, ETH_ALEN); | 450 | ether_addr_copy(neigh_node->addr, neigh_addr); |
| 450 | neigh_node->if_incoming = hard_iface; | 451 | neigh_node->if_incoming = hard_iface; |
| 451 | neigh_node->orig_node = orig_node; | 452 | neigh_node->orig_node = orig_node; |
| 452 | 453 | ||
| @@ -557,6 +558,8 @@ static void batadv_orig_node_free_rcu(struct rcu_head *rcu) | |||
| 557 | } | 558 | } |
| 558 | spin_unlock_bh(&orig_node->neigh_list_lock); | 559 | spin_unlock_bh(&orig_node->neigh_list_lock); |
| 559 | 560 | ||
| 561 | batadv_mcast_purge_orig(orig_node); | ||
| 562 | |||
| 560 | /* Free nc_nodes */ | 563 | /* Free nc_nodes */ |
| 561 | batadv_nc_purge_orig(orig_node->bat_priv, orig_node, NULL); | 564 | batadv_nc_purge_orig(orig_node->bat_priv, orig_node, NULL); |
| 562 | 565 | ||
| @@ -664,15 +667,17 @@ struct batadv_orig_node *batadv_orig_node_new(struct batadv_priv *bat_priv, | |||
| 664 | /* extra reference for return */ | 667 | /* extra reference for return */ |
| 665 | atomic_set(&orig_node->refcount, 2); | 668 | atomic_set(&orig_node->refcount, 2); |
| 666 | 669 | ||
| 667 | orig_node->tt_initialised = false; | ||
| 668 | orig_node->bat_priv = bat_priv; | 670 | orig_node->bat_priv = bat_priv; |
| 669 | memcpy(orig_node->orig, addr, ETH_ALEN); | 671 | ether_addr_copy(orig_node->orig, addr); |
| 670 | batadv_dat_init_orig_node_addr(orig_node); | 672 | batadv_dat_init_orig_node_addr(orig_node); |
| 671 | atomic_set(&orig_node->last_ttvn, 0); | 673 | atomic_set(&orig_node->last_ttvn, 0); |
| 672 | orig_node->tt_buff = NULL; | 674 | orig_node->tt_buff = NULL; |
| 673 | orig_node->tt_buff_len = 0; | 675 | orig_node->tt_buff_len = 0; |
| 674 | reset_time = jiffies - 1 - msecs_to_jiffies(BATADV_RESET_PROTECTION_MS); | 676 | reset_time = jiffies - 1 - msecs_to_jiffies(BATADV_RESET_PROTECTION_MS); |
| 675 | orig_node->bcast_seqno_reset = reset_time; | 677 | orig_node->bcast_seqno_reset = reset_time; |
| 678 | #ifdef CONFIG_BATMAN_ADV_MCAST | ||
| 679 | orig_node->mcast_flags = BATADV_NO_FLAGS; | ||
| 680 | #endif | ||
| 676 | 681 | ||
| 677 | /* create a vlan object for the "untagged" LAN */ | 682 | /* create a vlan object for the "untagged" LAN */ |
| 678 | vlan = batadv_orig_node_vlan_new(orig_node, BATADV_NO_FLAGS); | 683 | vlan = batadv_orig_node_vlan_new(orig_node, BATADV_NO_FLAGS); |
diff --git a/net/batman-adv/packet.h b/net/batman-adv/packet.h index 0a381d1174c1..34e096d2dce1 100644 --- a/net/batman-adv/packet.h +++ b/net/batman-adv/packet.h | |||
| @@ -89,6 +89,19 @@ enum batadv_icmp_packettype { | |||
| 89 | BATADV_PARAMETER_PROBLEM = 12, | 89 | BATADV_PARAMETER_PROBLEM = 12, |
| 90 | }; | 90 | }; |
| 91 | 91 | ||
| 92 | /** | ||
| 93 | * enum batadv_mcast_flags - flags for multicast capabilities and settings | ||
| 94 | * @BATADV_MCAST_WANT_ALL_UNSNOOPABLES: we want all packets destined for | ||
| 95 | * 224.0.0.0/24 or ff02::1 | ||
| 96 | * @BATADV_MCAST_WANT_ALL_IPV4: we want all IPv4 multicast packets | ||
| 97 | * @BATADV_MCAST_WANT_ALL_IPV6: we want all IPv6 multicast packets | ||
| 98 | */ | ||
| 99 | enum batadv_mcast_flags { | ||
| 100 | BATADV_MCAST_WANT_ALL_UNSNOOPABLES = BIT(0), | ||
| 101 | BATADV_MCAST_WANT_ALL_IPV4 = BIT(1), | ||
| 102 | BATADV_MCAST_WANT_ALL_IPV6 = BIT(2), | ||
| 103 | }; | ||
| 104 | |||
| 92 | /* tt data subtypes */ | 105 | /* tt data subtypes */ |
| 93 | #define BATADV_TT_DATA_TYPE_MASK 0x0F | 106 | #define BATADV_TT_DATA_TYPE_MASK 0x0F |
| 94 | 107 | ||
| @@ -106,10 +119,30 @@ enum batadv_tt_data_flags { | |||
| 106 | BATADV_TT_FULL_TABLE = BIT(4), | 119 | BATADV_TT_FULL_TABLE = BIT(4), |
| 107 | }; | 120 | }; |
| 108 | 121 | ||
| 109 | /* BATADV_TT_CLIENT flags. | 122 | /** |
| 110 | * Flags from BIT(0) to BIT(7) are sent on the wire, while flags from BIT(8) to | 123 | * enum batadv_tt_client_flags - TT client specific flags |
| 111 | * BIT(15) are used for local computation only. | 124 | * @BATADV_TT_CLIENT_DEL: the client has to be deleted from the table |
| 112 | * Flags from BIT(4) to BIT(7) are kept in sync with the rest of the network. | 125 | * @BATADV_TT_CLIENT_ROAM: the client roamed to/from another node and the new |
| 126 | * update telling its new real location has not been received/sent yet | ||
| 127 | * @BATADV_TT_CLIENT_WIFI: this client is connected through a wifi interface. | ||
| 128 | * This information is used by the "AP Isolation" feature | ||
| 129 | * @BATADV_TT_CLIENT_ISOLA: this client is considered "isolated". This | ||
| 130 | * information is used by the Extended Isolation feature | ||
| 131 | * @BATADV_TT_CLIENT_NOPURGE: this client should never be removed from the table | ||
| 132 | * @BATADV_TT_CLIENT_NEW: this client has been added to the local table but has | ||
| 133 | * not been announced yet | ||
| 134 | * @BATADV_TT_CLIENT_PENDING: this client is marked for removal but it is kept | ||
| 135 | * in the table for one more originator interval for consistency purposes | ||
| 136 | * @BATADV_TT_CLIENT_TEMP: this global client has been detected to be part of | ||
| 137 | * the network but no nnode has already announced it | ||
| 138 | * | ||
| 139 | * Bits from 0 to 7 are called _remote flags_ because they are sent on the wire. | ||
| 140 | * Bits from 8 to 15 are called _local flags_ because they are used for local | ||
| 141 | * computations only. | ||
| 142 | * | ||
| 143 | * Bits from 4 to 7 - a subset of remote flags - are ensured to be in sync with | ||
| 144 | * the other nodes in the network. To achieve this goal these flags are included | ||
| 145 | * in the TT CRC computation. | ||
| 113 | */ | 146 | */ |
| 114 | enum batadv_tt_client_flags { | 147 | enum batadv_tt_client_flags { |
| 115 | BATADV_TT_CLIENT_DEL = BIT(0), | 148 | BATADV_TT_CLIENT_DEL = BIT(0), |
| @@ -145,6 +178,7 @@ enum batadv_bla_claimframe { | |||
| 145 | * @BATADV_TVLV_NC: network coding tvlv | 178 | * @BATADV_TVLV_NC: network coding tvlv |
| 146 | * @BATADV_TVLV_TT: translation table tvlv | 179 | * @BATADV_TVLV_TT: translation table tvlv |
| 147 | * @BATADV_TVLV_ROAM: roaming advertisement tvlv | 180 | * @BATADV_TVLV_ROAM: roaming advertisement tvlv |
| 181 | * @BATADV_TVLV_MCAST: multicast capability tvlv | ||
| 148 | */ | 182 | */ |
| 149 | enum batadv_tvlv_type { | 183 | enum batadv_tvlv_type { |
| 150 | BATADV_TVLV_GW = 0x01, | 184 | BATADV_TVLV_GW = 0x01, |
| @@ -152,6 +186,7 @@ enum batadv_tvlv_type { | |||
| 152 | BATADV_TVLV_NC = 0x03, | 186 | BATADV_TVLV_NC = 0x03, |
| 153 | BATADV_TVLV_TT = 0x04, | 187 | BATADV_TVLV_TT = 0x04, |
| 154 | BATADV_TVLV_ROAM = 0x05, | 188 | BATADV_TVLV_ROAM = 0x05, |
| 189 | BATADV_TVLV_MCAST = 0x06, | ||
| 155 | }; | 190 | }; |
| 156 | 191 | ||
| 157 | #pragma pack(2) | 192 | #pragma pack(2) |
| @@ -504,4 +539,14 @@ struct batadv_tvlv_roam_adv { | |||
| 504 | __be16 vid; | 539 | __be16 vid; |
| 505 | }; | 540 | }; |
| 506 | 541 | ||
| 542 | /** | ||
| 543 | * struct batadv_tvlv_mcast_data - payload of a multicast tvlv | ||
| 544 | * @flags: multicast flags announced by the orig node | ||
| 545 | * @reserved: reserved field | ||
| 546 | */ | ||
| 547 | struct batadv_tvlv_mcast_data { | ||
| 548 | uint8_t flags; | ||
| 549 | uint8_t reserved[3]; | ||
| 550 | }; | ||
| 551 | |||
| 507 | #endif /* _NET_BATMAN_ADV_PACKET_H_ */ | 552 | #endif /* _NET_BATMAN_ADV_PACKET_H_ */ |
diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index a953d5b196a3..35141534938e 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c | |||
| @@ -222,8 +222,8 @@ static int batadv_recv_my_icmp_packet(struct batadv_priv *bat_priv, | |||
| 222 | 222 | ||
| 223 | icmph = (struct batadv_icmp_header *)skb->data; | 223 | icmph = (struct batadv_icmp_header *)skb->data; |
| 224 | 224 | ||
| 225 | memcpy(icmph->dst, icmph->orig, ETH_ALEN); | 225 | ether_addr_copy(icmph->dst, icmph->orig); |
| 226 | memcpy(icmph->orig, primary_if->net_dev->dev_addr, ETH_ALEN); | 226 | ether_addr_copy(icmph->orig, primary_if->net_dev->dev_addr); |
| 227 | icmph->msg_type = BATADV_ECHO_REPLY; | 227 | icmph->msg_type = BATADV_ECHO_REPLY; |
| 228 | icmph->ttl = BATADV_TTL; | 228 | icmph->ttl = BATADV_TTL; |
| 229 | 229 | ||
| @@ -276,9 +276,8 @@ static int batadv_recv_icmp_ttl_exceeded(struct batadv_priv *bat_priv, | |||
| 276 | 276 | ||
| 277 | icmp_packet = (struct batadv_icmp_packet *)skb->data; | 277 | icmp_packet = (struct batadv_icmp_packet *)skb->data; |
| 278 | 278 | ||
| 279 | memcpy(icmp_packet->dst, icmp_packet->orig, ETH_ALEN); | 279 | ether_addr_copy(icmp_packet->dst, icmp_packet->orig); |
| 280 | memcpy(icmp_packet->orig, primary_if->net_dev->dev_addr, | 280 | ether_addr_copy(icmp_packet->orig, primary_if->net_dev->dev_addr); |
| 281 | ETH_ALEN); | ||
| 282 | icmp_packet->msg_type = BATADV_TTL_EXCEEDED; | 281 | icmp_packet->msg_type = BATADV_TTL_EXCEEDED; |
| 283 | icmp_packet->ttl = BATADV_TTL; | 282 | icmp_packet->ttl = BATADV_TTL; |
| 284 | 283 | ||
| @@ -341,8 +340,8 @@ int batadv_recv_icmp_packet(struct sk_buff *skb, | |||
| 341 | if (icmp_packet_rr->rr_cur >= BATADV_RR_LEN) | 340 | if (icmp_packet_rr->rr_cur >= BATADV_RR_LEN) |
| 342 | goto out; | 341 | goto out; |
| 343 | 342 | ||
| 344 | memcpy(&(icmp_packet_rr->rr[icmp_packet_rr->rr_cur]), | 343 | ether_addr_copy(icmp_packet_rr->rr[icmp_packet_rr->rr_cur], |
| 345 | ethhdr->h_dest, ETH_ALEN); | 344 | ethhdr->h_dest); |
| 346 | icmp_packet_rr->rr_cur++; | 345 | icmp_packet_rr->rr_cur++; |
| 347 | } | 346 | } |
| 348 | 347 | ||
| @@ -664,7 +663,7 @@ batadv_reroute_unicast_packet(struct batadv_priv *bat_priv, | |||
| 664 | } | 663 | } |
| 665 | 664 | ||
| 666 | /* update the packet header */ | 665 | /* update the packet header */ |
| 667 | memcpy(unicast_packet->dest, orig_addr, ETH_ALEN); | 666 | ether_addr_copy(unicast_packet->dest, orig_addr); |
| 668 | unicast_packet->ttvn = orig_ttvn; | 667 | unicast_packet->ttvn = orig_ttvn; |
| 669 | 668 | ||
| 670 | ret = true; | 669 | ret = true; |
| @@ -774,7 +773,7 @@ static int batadv_check_unicast_ttvn(struct batadv_priv *bat_priv, | |||
| 774 | if (!primary_if) | 773 | if (!primary_if) |
| 775 | return 0; | 774 | return 0; |
| 776 | 775 | ||
| 777 | memcpy(unicast_packet->dest, primary_if->net_dev->dev_addr, ETH_ALEN); | 776 | ether_addr_copy(unicast_packet->dest, primary_if->net_dev->dev_addr); |
| 778 | 777 | ||
| 779 | batadv_hardif_free_ref(primary_if); | 778 | batadv_hardif_free_ref(primary_if); |
| 780 | 779 | ||
diff --git a/net/batman-adv/send.c b/net/batman-adv/send.c index 843febd1e519..3d64ed20c393 100644 --- a/net/batman-adv/send.c +++ b/net/batman-adv/send.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include "originator.h" | 27 | #include "originator.h" |
| 28 | #include "network-coding.h" | 28 | #include "network-coding.h" |
| 29 | #include "fragmentation.h" | 29 | #include "fragmentation.h" |
| 30 | #include "multicast.h" | ||
| 30 | 31 | ||
| 31 | static void batadv_send_outstanding_bcast_packet(struct work_struct *work); | 32 | static void batadv_send_outstanding_bcast_packet(struct work_struct *work); |
| 32 | 33 | ||
| @@ -59,8 +60,8 @@ int batadv_send_skb_packet(struct sk_buff *skb, | |||
| 59 | skb_reset_mac_header(skb); | 60 | skb_reset_mac_header(skb); |
| 60 | 61 | ||
| 61 | ethhdr = eth_hdr(skb); | 62 | ethhdr = eth_hdr(skb); |
| 62 | memcpy(ethhdr->h_source, hard_iface->net_dev->dev_addr, ETH_ALEN); | 63 | ether_addr_copy(ethhdr->h_source, hard_iface->net_dev->dev_addr); |
| 63 | memcpy(ethhdr->h_dest, dst_addr, ETH_ALEN); | 64 | ether_addr_copy(ethhdr->h_dest, dst_addr); |
| 64 | ethhdr->h_proto = htons(ETH_P_BATMAN); | 65 | ethhdr->h_proto = htons(ETH_P_BATMAN); |
| 65 | 66 | ||
| 66 | skb_set_network_header(skb, ETH_HLEN); | 67 | skb_set_network_header(skb, ETH_HLEN); |
| @@ -165,7 +166,7 @@ batadv_send_skb_push_fill_unicast(struct sk_buff *skb, int hdr_size, | |||
| 165 | /* set unicast ttl */ | 166 | /* set unicast ttl */ |
| 166 | unicast_packet->ttl = BATADV_TTL; | 167 | unicast_packet->ttl = BATADV_TTL; |
| 167 | /* copy the destination for faster routing */ | 168 | /* copy the destination for faster routing */ |
| 168 | memcpy(unicast_packet->dest, orig_node->orig, ETH_ALEN); | 169 | ether_addr_copy(unicast_packet->dest, orig_node->orig); |
| 169 | /* set the destination tt version number */ | 170 | /* set the destination tt version number */ |
| 170 | unicast_packet->ttvn = ttvn; | 171 | unicast_packet->ttvn = ttvn; |
| 171 | 172 | ||
| @@ -220,7 +221,7 @@ bool batadv_send_skb_prepare_unicast_4addr(struct batadv_priv *bat_priv, | |||
| 220 | 221 | ||
| 221 | uc_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data; | 222 | uc_4addr_packet = (struct batadv_unicast_4addr_packet *)skb->data; |
| 222 | uc_4addr_packet->u.packet_type = BATADV_UNICAST_4ADDR; | 223 | uc_4addr_packet->u.packet_type = BATADV_UNICAST_4ADDR; |
| 223 | memcpy(uc_4addr_packet->src, primary_if->net_dev->dev_addr, ETH_ALEN); | 224 | ether_addr_copy(uc_4addr_packet->src, primary_if->net_dev->dev_addr); |
| 224 | uc_4addr_packet->subtype = packet_subtype; | 225 | uc_4addr_packet->subtype = packet_subtype; |
| 225 | uc_4addr_packet->reserved = 0; | 226 | uc_4addr_packet->reserved = 0; |
| 226 | 227 | ||
| @@ -248,15 +249,15 @@ out: | |||
| 248 | * | 249 | * |
| 249 | * Returns NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise. | 250 | * Returns NET_XMIT_DROP in case of error or NET_XMIT_SUCCESS otherwise. |
| 250 | */ | 251 | */ |
| 251 | static int batadv_send_skb_unicast(struct batadv_priv *bat_priv, | 252 | int batadv_send_skb_unicast(struct batadv_priv *bat_priv, |
| 252 | struct sk_buff *skb, int packet_type, | 253 | struct sk_buff *skb, int packet_type, |
| 253 | int packet_subtype, | 254 | int packet_subtype, |
| 254 | struct batadv_orig_node *orig_node, | 255 | struct batadv_orig_node *orig_node, |
| 255 | unsigned short vid) | 256 | unsigned short vid) |
| 256 | { | 257 | { |
| 257 | struct ethhdr *ethhdr; | 258 | struct ethhdr *ethhdr; |
| 258 | struct batadv_unicast_packet *unicast_packet; | 259 | struct batadv_unicast_packet *unicast_packet; |
| 259 | int ret = NET_XMIT_DROP, hdr_size; | 260 | int ret = NET_XMIT_DROP; |
| 260 | 261 | ||
| 261 | if (!orig_node) | 262 | if (!orig_node) |
| 262 | goto out; | 263 | goto out; |
| @@ -265,16 +266,12 @@ static int batadv_send_skb_unicast(struct batadv_priv *bat_priv, | |||
| 265 | case BATADV_UNICAST: | 266 | case BATADV_UNICAST: |
| 266 | if (!batadv_send_skb_prepare_unicast(skb, orig_node)) | 267 | if (!batadv_send_skb_prepare_unicast(skb, orig_node)) |
| 267 | goto out; | 268 | goto out; |
| 268 | |||
| 269 | hdr_size = sizeof(*unicast_packet); | ||
| 270 | break; | 269 | break; |
| 271 | case BATADV_UNICAST_4ADDR: | 270 | case BATADV_UNICAST_4ADDR: |
| 272 | if (!batadv_send_skb_prepare_unicast_4addr(bat_priv, skb, | 271 | if (!batadv_send_skb_prepare_unicast_4addr(bat_priv, skb, |
| 273 | orig_node, | 272 | orig_node, |
| 274 | packet_subtype)) | 273 | packet_subtype)) |
| 275 | goto out; | 274 | goto out; |
| 276 | |||
| 277 | hdr_size = sizeof(struct batadv_unicast_4addr_packet); | ||
| 278 | break; | 275 | break; |
| 279 | default: | 276 | default: |
| 280 | /* this function supports UNICAST and UNICAST_4ADDR only. It | 277 | /* this function supports UNICAST and UNICAST_4ADDR only. It |
| @@ -283,7 +280,10 @@ static int batadv_send_skb_unicast(struct batadv_priv *bat_priv, | |||
| 283 | goto out; | 280 | goto out; |
| 284 | } | 281 | } |
| 285 | 282 | ||
| 286 | ethhdr = (struct ethhdr *)(skb->data + hdr_size); | 283 | /* skb->data might have been reallocated by |
| 284 | * batadv_send_skb_prepare_unicast{,_4addr}() | ||
| 285 | */ | ||
| 286 | ethhdr = eth_hdr(skb); | ||
| 287 | unicast_packet = (struct batadv_unicast_packet *)skb->data; | 287 | unicast_packet = (struct batadv_unicast_packet *)skb->data; |
| 288 | 288 | ||
| 289 | /* inform the destination node that we are still missing a correct route | 289 | /* inform the destination node that we are still missing a correct route |
| @@ -312,6 +312,7 @@ out: | |||
| 312 | * @packet_type: the batman unicast packet type to use | 312 | * @packet_type: the batman unicast packet type to use |
| 313 | * @packet_subtype: the unicast 4addr packet subtype (only relevant for unicast | 313 | * @packet_subtype: the unicast 4addr packet subtype (only relevant for unicast |
| 314 | * 4addr packets) | 314 | * 4addr packets) |
| 315 | * @dst_hint: can be used to override the destination contained in the skb | ||
| 315 | * @vid: the vid to be used to search the translation table | 316 | * @vid: the vid to be used to search the translation table |
| 316 | * | 317 | * |
| 317 | * Look up the recipient node for the destination address in the ethernet | 318 | * Look up the recipient node for the destination address in the ethernet |
diff --git a/net/batman-adv/send.h b/net/batman-adv/send.h index aaddaa9661ce..38d0ec1833ae 100644 --- a/net/batman-adv/send.h +++ b/net/batman-adv/send.h | |||
| @@ -36,6 +36,11 @@ bool batadv_send_skb_prepare_unicast_4addr(struct batadv_priv *bat_priv, | |||
| 36 | struct sk_buff *skb, | 36 | struct sk_buff *skb, |
| 37 | struct batadv_orig_node *orig_node, | 37 | struct batadv_orig_node *orig_node, |
| 38 | int packet_subtype); | 38 | int packet_subtype); |
| 39 | int batadv_send_skb_unicast(struct batadv_priv *bat_priv, | ||
| 40 | struct sk_buff *skb, int packet_type, | ||
| 41 | int packet_subtype, | ||
| 42 | struct batadv_orig_node *orig_node, | ||
| 43 | unsigned short vid); | ||
| 39 | int batadv_send_skb_via_tt_generic(struct batadv_priv *bat_priv, | 44 | int batadv_send_skb_via_tt_generic(struct batadv_priv *bat_priv, |
| 40 | struct sk_buff *skb, int packet_type, | 45 | struct sk_buff *skb, int packet_type, |
| 41 | int packet_subtype, uint8_t *dst_hint, | 46 | int packet_subtype, uint8_t *dst_hint, |
| @@ -47,6 +52,7 @@ int batadv_send_skb_via_gw(struct batadv_priv *bat_priv, struct sk_buff *skb, | |||
| 47 | * batadv_send_skb_via_tt - send an skb via TT lookup | 52 | * batadv_send_skb_via_tt - send an skb via TT lookup |
| 48 | * @bat_priv: the bat priv with all the soft interface information | 53 | * @bat_priv: the bat priv with all the soft interface information |
| 49 | * @skb: the payload to send | 54 | * @skb: the payload to send |
| 55 | * @dst_hint: can be used to override the destination contained in the skb | ||
| 50 | * @vid: the vid to be used to search the translation table | 56 | * @vid: the vid to be used to search the translation table |
| 51 | * | 57 | * |
| 52 | * Look up the recipient node for the destination address in the ethernet | 58 | * Look up the recipient node for the destination address in the ethernet |
| @@ -68,6 +74,7 @@ static inline int batadv_send_skb_via_tt(struct batadv_priv *bat_priv, | |||
| 68 | * @bat_priv: the bat priv with all the soft interface information | 74 | * @bat_priv: the bat priv with all the soft interface information |
| 69 | * @skb: the payload to send | 75 | * @skb: the payload to send |
| 70 | * @packet_subtype: the unicast 4addr packet subtype to use | 76 | * @packet_subtype: the unicast 4addr packet subtype to use |
| 77 | * @dst_hint: can be used to override the destination contained in the skb | ||
| 71 | * @vid: the vid to be used to search the translation table | 78 | * @vid: the vid to be used to search the translation table |
| 72 | * | 79 | * |
| 73 | * Look up the recipient node for the destination address in the ethernet | 80 | * Look up the recipient node for the destination address in the ethernet |
diff --git a/net/batman-adv/soft-interface.c b/net/batman-adv/soft-interface.c index f82c267e1886..744a59b85e15 100644 --- a/net/batman-adv/soft-interface.c +++ b/net/batman-adv/soft-interface.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <linux/ethtool.h> | 32 | #include <linux/ethtool.h> |
| 33 | #include <linux/etherdevice.h> | 33 | #include <linux/etherdevice.h> |
| 34 | #include <linux/if_vlan.h> | 34 | #include <linux/if_vlan.h> |
| 35 | #include "multicast.h" | ||
| 35 | #include "bridge_loop_avoidance.h" | 36 | #include "bridge_loop_avoidance.h" |
| 36 | #include "network-coding.h" | 37 | #include "network-coding.h" |
| 37 | 38 | ||
| @@ -111,8 +112,8 @@ static int batadv_interface_set_mac_addr(struct net_device *dev, void *p) | |||
| 111 | if (!is_valid_ether_addr(addr->sa_data)) | 112 | if (!is_valid_ether_addr(addr->sa_data)) |
| 112 | return -EADDRNOTAVAIL; | 113 | return -EADDRNOTAVAIL; |
| 113 | 114 | ||
| 114 | memcpy(old_addr, dev->dev_addr, ETH_ALEN); | 115 | ether_addr_copy(old_addr, dev->dev_addr); |
| 115 | memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN); | 116 | ether_addr_copy(dev->dev_addr, addr->sa_data); |
| 116 | 117 | ||
| 117 | /* only modify transtable if it has been initialized before */ | 118 | /* only modify transtable if it has been initialized before */ |
| 118 | if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE) { | 119 | if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE) { |
| @@ -170,17 +171,19 @@ static int batadv_interface_tx(struct sk_buff *skb, | |||
| 170 | unsigned short vid; | 171 | unsigned short vid; |
| 171 | uint32_t seqno; | 172 | uint32_t seqno; |
| 172 | int gw_mode; | 173 | int gw_mode; |
| 174 | enum batadv_forw_mode forw_mode; | ||
| 175 | struct batadv_orig_node *mcast_single_orig = NULL; | ||
| 173 | 176 | ||
| 174 | if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) | 177 | if (atomic_read(&bat_priv->mesh_state) != BATADV_MESH_ACTIVE) |
| 175 | goto dropped; | 178 | goto dropped; |
| 176 | 179 | ||
| 177 | soft_iface->trans_start = jiffies; | 180 | soft_iface->trans_start = jiffies; |
| 178 | vid = batadv_get_vid(skb, 0); | 181 | vid = batadv_get_vid(skb, 0); |
| 179 | ethhdr = (struct ethhdr *)skb->data; | 182 | ethhdr = eth_hdr(skb); |
| 180 | 183 | ||
| 181 | switch (ntohs(ethhdr->h_proto)) { | 184 | switch (ntohs(ethhdr->h_proto)) { |
| 182 | case ETH_P_8021Q: | 185 | case ETH_P_8021Q: |
| 183 | vhdr = (struct vlan_ethhdr *)skb->data; | 186 | vhdr = vlan_eth_hdr(skb); |
| 184 | 187 | ||
| 185 | if (vhdr->h_vlan_encapsulated_proto != ethertype) | 188 | if (vhdr->h_vlan_encapsulated_proto != ethertype) |
| 186 | break; | 189 | break; |
| @@ -194,7 +197,7 @@ static int batadv_interface_tx(struct sk_buff *skb, | |||
| 194 | goto dropped; | 197 | goto dropped; |
| 195 | 198 | ||
| 196 | /* skb->data might have been reallocated by batadv_bla_tx() */ | 199 | /* skb->data might have been reallocated by batadv_bla_tx() */ |
| 197 | ethhdr = (struct ethhdr *)skb->data; | 200 | ethhdr = eth_hdr(skb); |
| 198 | 201 | ||
| 199 | /* Register the client MAC in the transtable */ | 202 | /* Register the client MAC in the transtable */ |
| 200 | if (!is_multicast_ether_addr(ethhdr->h_source)) { | 203 | if (!is_multicast_ether_addr(ethhdr->h_source)) { |
| @@ -230,7 +233,7 @@ static int batadv_interface_tx(struct sk_buff *skb, | |||
| 230 | /* skb->data may have been modified by | 233 | /* skb->data may have been modified by |
| 231 | * batadv_gw_dhcp_recipient_get() | 234 | * batadv_gw_dhcp_recipient_get() |
| 232 | */ | 235 | */ |
| 233 | ethhdr = (struct ethhdr *)skb->data; | 236 | ethhdr = eth_hdr(skb); |
| 234 | /* if gw_mode is on, broadcast any non-DHCP message. | 237 | /* if gw_mode is on, broadcast any non-DHCP message. |
| 235 | * All the DHCP packets are going to be sent as unicast | 238 | * All the DHCP packets are going to be sent as unicast |
| 236 | */ | 239 | */ |
| @@ -247,9 +250,19 @@ static int batadv_interface_tx(struct sk_buff *skb, | |||
| 247 | * directed to a DHCP server | 250 | * directed to a DHCP server |
| 248 | */ | 251 | */ |
| 249 | goto dropped; | 252 | goto dropped; |
| 250 | } | ||
| 251 | 253 | ||
| 252 | send: | 254 | send: |
| 255 | if (do_bcast && !is_broadcast_ether_addr(ethhdr->h_dest)) { | ||
| 256 | forw_mode = batadv_mcast_forw_mode(bat_priv, skb, | ||
| 257 | &mcast_single_orig); | ||
| 258 | if (forw_mode == BATADV_FORW_NONE) | ||
| 259 | goto dropped; | ||
| 260 | |||
| 261 | if (forw_mode == BATADV_FORW_SINGLE) | ||
| 262 | do_bcast = false; | ||
| 263 | } | ||
| 264 | } | ||
| 265 | |||
| 253 | batadv_skb_set_priority(skb, 0); | 266 | batadv_skb_set_priority(skb, 0); |
| 254 | 267 | ||
| 255 | /* ethernet packet should be broadcasted */ | 268 | /* ethernet packet should be broadcasted */ |
| @@ -279,8 +292,8 @@ send: | |||
| 279 | /* hw address of first interface is the orig mac because only | 292 | /* hw address of first interface is the orig mac because only |
| 280 | * this mac is known throughout the mesh | 293 | * this mac is known throughout the mesh |
| 281 | */ | 294 | */ |
| 282 | memcpy(bcast_packet->orig, | 295 | ether_addr_copy(bcast_packet->orig, |
| 283 | primary_if->net_dev->dev_addr, ETH_ALEN); | 296 | primary_if->net_dev->dev_addr); |
| 284 | 297 | ||
| 285 | /* set broadcast sequence number */ | 298 | /* set broadcast sequence number */ |
| 286 | seqno = atomic_inc_return(&bat_priv->bcast_seqno); | 299 | seqno = atomic_inc_return(&bat_priv->bcast_seqno); |
| @@ -301,6 +314,10 @@ send: | |||
| 301 | if (ret) | 314 | if (ret) |
| 302 | goto dropped; | 315 | goto dropped; |
| 303 | ret = batadv_send_skb_via_gw(bat_priv, skb, vid); | 316 | ret = batadv_send_skb_via_gw(bat_priv, skb, vid); |
| 317 | } else if (mcast_single_orig) { | ||
| 318 | ret = batadv_send_skb_unicast(bat_priv, skb, | ||
| 319 | BATADV_UNICAST, 0, | ||
| 320 | mcast_single_orig, vid); | ||
| 304 | } else { | 321 | } else { |
| 305 | if (batadv_dat_snoop_outgoing_arp_request(bat_priv, | 322 | if (batadv_dat_snoop_outgoing_arp_request(bat_priv, |
| 306 | skb)) | 323 | skb)) |
| @@ -652,10 +669,7 @@ static void batadv_softif_destroy_finish(struct work_struct *work) | |||
| 652 | } | 669 | } |
| 653 | 670 | ||
| 654 | batadv_sysfs_del_meshif(soft_iface); | 671 | batadv_sysfs_del_meshif(soft_iface); |
| 655 | 672 | unregister_netdev(soft_iface); | |
| 656 | rtnl_lock(); | ||
| 657 | unregister_netdevice(soft_iface); | ||
| 658 | rtnl_unlock(); | ||
| 659 | } | 673 | } |
| 660 | 674 | ||
| 661 | /** | 675 | /** |
| @@ -692,6 +706,14 @@ static int batadv_softif_init_late(struct net_device *dev) | |||
| 692 | #ifdef CONFIG_BATMAN_ADV_DAT | 706 | #ifdef CONFIG_BATMAN_ADV_DAT |
| 693 | atomic_set(&bat_priv->distributed_arp_table, 1); | 707 | atomic_set(&bat_priv->distributed_arp_table, 1); |
| 694 | #endif | 708 | #endif |
| 709 | #ifdef CONFIG_BATMAN_ADV_MCAST | ||
| 710 | bat_priv->mcast.flags = BATADV_NO_FLAGS; | ||
| 711 | atomic_set(&bat_priv->multicast_mode, 1); | ||
| 712 | atomic_set(&bat_priv->mcast.num_disabled, 0); | ||
| 713 | atomic_set(&bat_priv->mcast.num_want_all_unsnoopables, 0); | ||
| 714 | atomic_set(&bat_priv->mcast.num_want_all_ipv4, 0); | ||
| 715 | atomic_set(&bat_priv->mcast.num_want_all_ipv6, 0); | ||
| 716 | #endif | ||
| 695 | atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF); | 717 | atomic_set(&bat_priv->gw_mode, BATADV_GW_MODE_OFF); |
| 696 | atomic_set(&bat_priv->gw_sel_class, 20); | 718 | atomic_set(&bat_priv->gw_sel_class, 20); |
| 697 | atomic_set(&bat_priv->gw.bandwidth_down, 100); | 719 | atomic_set(&bat_priv->gw.bandwidth_down, 100); |
diff --git a/net/batman-adv/sysfs.c b/net/batman-adv/sysfs.c index e456bf6bb284..1ebb0d9e2ea5 100644 --- a/net/batman-adv/sysfs.c +++ b/net/batman-adv/sysfs.c | |||
| @@ -539,6 +539,9 @@ BATADV_ATTR_SIF_UINT(gw_sel_class, S_IRUGO | S_IWUSR, 1, BATADV_TQ_MAX_VALUE, | |||
| 539 | batadv_post_gw_reselect); | 539 | batadv_post_gw_reselect); |
| 540 | static BATADV_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, batadv_show_gw_bwidth, | 540 | static BATADV_ATTR(gw_bandwidth, S_IRUGO | S_IWUSR, batadv_show_gw_bwidth, |
| 541 | batadv_store_gw_bwidth); | 541 | batadv_store_gw_bwidth); |
| 542 | #ifdef CONFIG_BATMAN_ADV_MCAST | ||
| 543 | BATADV_ATTR_SIF_BOOL(multicast_mode, S_IRUGO | S_IWUSR, NULL); | ||
| 544 | #endif | ||
| 542 | #ifdef CONFIG_BATMAN_ADV_DEBUG | 545 | #ifdef CONFIG_BATMAN_ADV_DEBUG |
| 543 | BATADV_ATTR_SIF_UINT(log_level, S_IRUGO | S_IWUSR, 0, BATADV_DBG_ALL, NULL); | 546 | BATADV_ATTR_SIF_UINT(log_level, S_IRUGO | S_IWUSR, 0, BATADV_DBG_ALL, NULL); |
| 544 | #endif | 547 | #endif |
| @@ -558,6 +561,9 @@ static struct batadv_attribute *batadv_mesh_attrs[] = { | |||
| 558 | #ifdef CONFIG_BATMAN_ADV_DAT | 561 | #ifdef CONFIG_BATMAN_ADV_DAT |
| 559 | &batadv_attr_distributed_arp_table, | 562 | &batadv_attr_distributed_arp_table, |
| 560 | #endif | 563 | #endif |
| 564 | #ifdef CONFIG_BATMAN_ADV_MCAST | ||
| 565 | &batadv_attr_multicast_mode, | ||
| 566 | #endif | ||
| 561 | &batadv_attr_fragmentation, | 567 | &batadv_attr_fragmentation, |
| 562 | &batadv_attr_routing_algo, | 568 | &batadv_attr_routing_algo, |
| 563 | &batadv_attr_gw_mode, | 569 | &batadv_attr_gw_mode, |
diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index 959dde721c46..d636bde72c9a 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include "originator.h" | 24 | #include "originator.h" |
| 25 | #include "routing.h" | 25 | #include "routing.h" |
| 26 | #include "bridge_loop_avoidance.h" | 26 | #include "bridge_loop_avoidance.h" |
| 27 | #include "multicast.h" | ||
| 27 | 28 | ||
| 28 | #include <linux/crc32c.h> | 29 | #include <linux/crc32c.h> |
| 29 | 30 | ||
| @@ -96,7 +97,7 @@ batadv_tt_hash_find(struct batadv_hashtable *hash, const uint8_t *addr, | |||
| 96 | if (!hash) | 97 | if (!hash) |
| 97 | return NULL; | 98 | return NULL; |
| 98 | 99 | ||
| 99 | memcpy(to_search.addr, addr, ETH_ALEN); | 100 | ether_addr_copy(to_search.addr, addr); |
| 100 | to_search.vid = vid; | 101 | to_search.vid = vid; |
| 101 | 102 | ||
| 102 | index = batadv_choose_tt(&to_search, hash->size); | 103 | index = batadv_choose_tt(&to_search, hash->size); |
| @@ -192,6 +193,31 @@ batadv_tt_global_entry_free_ref(struct batadv_tt_global_entry *tt_global_entry) | |||
| 192 | } | 193 | } |
| 193 | } | 194 | } |
| 194 | 195 | ||
| 196 | /** | ||
| 197 | * batadv_tt_global_hash_count - count the number of orig entries | ||
| 198 | * @hash: hash table containing the tt entries | ||
| 199 | * @addr: the mac address of the client to count entries for | ||
| 200 | * @vid: VLAN identifier | ||
| 201 | * | ||
| 202 | * Return the number of originators advertising the given address/data | ||
| 203 | * (excluding ourself). | ||
| 204 | */ | ||
| 205 | int batadv_tt_global_hash_count(struct batadv_priv *bat_priv, | ||
| 206 | const uint8_t *addr, unsigned short vid) | ||
| 207 | { | ||
| 208 | struct batadv_tt_global_entry *tt_global_entry; | ||
| 209 | int count; | ||
| 210 | |||
| 211 | tt_global_entry = batadv_tt_global_hash_find(bat_priv, addr, vid); | ||
| 212 | if (!tt_global_entry) | ||
| 213 | return 0; | ||
| 214 | |||
| 215 | count = atomic_read(&tt_global_entry->orig_list_count); | ||
| 216 | batadv_tt_global_entry_free_ref(tt_global_entry); | ||
| 217 | |||
| 218 | return count; | ||
| 219 | } | ||
| 220 | |||
| 195 | static void batadv_tt_orig_list_entry_free_rcu(struct rcu_head *rcu) | 221 | static void batadv_tt_orig_list_entry_free_rcu(struct rcu_head *rcu) |
| 196 | { | 222 | { |
| 197 | struct batadv_tt_orig_list_entry *orig_entry; | 223 | struct batadv_tt_orig_list_entry *orig_entry; |
| @@ -333,7 +359,7 @@ static void batadv_tt_local_event(struct batadv_priv *bat_priv, | |||
| 333 | tt_change_node->change.flags = flags; | 359 | tt_change_node->change.flags = flags; |
| 334 | memset(tt_change_node->change.reserved, 0, | 360 | memset(tt_change_node->change.reserved, 0, |
| 335 | sizeof(tt_change_node->change.reserved)); | 361 | sizeof(tt_change_node->change.reserved)); |
| 336 | memcpy(tt_change_node->change.addr, common->addr, ETH_ALEN); | 362 | ether_addr_copy(tt_change_node->change.addr, common->addr); |
| 337 | tt_change_node->change.vid = htons(common->vid); | 363 | tt_change_node->change.vid = htons(common->vid); |
| 338 | 364 | ||
| 339 | del_op_requested = flags & BATADV_TT_CLIENT_DEL; | 365 | del_op_requested = flags & BATADV_TT_CLIENT_DEL; |
| @@ -484,7 +510,7 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, | |||
| 484 | { | 510 | { |
| 485 | struct batadv_priv *bat_priv = netdev_priv(soft_iface); | 511 | struct batadv_priv *bat_priv = netdev_priv(soft_iface); |
| 486 | struct batadv_tt_local_entry *tt_local; | 512 | struct batadv_tt_local_entry *tt_local; |
| 487 | struct batadv_tt_global_entry *tt_global; | 513 | struct batadv_tt_global_entry *tt_global = NULL; |
| 488 | struct net_device *in_dev = NULL; | 514 | struct net_device *in_dev = NULL; |
| 489 | struct hlist_head *head; | 515 | struct hlist_head *head; |
| 490 | struct batadv_tt_orig_list_entry *orig_entry; | 516 | struct batadv_tt_orig_list_entry *orig_entry; |
| @@ -497,7 +523,9 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, | |||
| 497 | in_dev = dev_get_by_index(&init_net, ifindex); | 523 | in_dev = dev_get_by_index(&init_net, ifindex); |
| 498 | 524 | ||
| 499 | tt_local = batadv_tt_local_hash_find(bat_priv, addr, vid); | 525 | tt_local = batadv_tt_local_hash_find(bat_priv, addr, vid); |
| 500 | tt_global = batadv_tt_global_hash_find(bat_priv, addr, vid); | 526 | |
| 527 | if (!is_multicast_ether_addr(addr)) | ||
| 528 | tt_global = batadv_tt_global_hash_find(bat_priv, addr, vid); | ||
| 501 | 529 | ||
| 502 | if (tt_local) { | 530 | if (tt_local) { |
| 503 | tt_local->last_seen = jiffies; | 531 | tt_local->last_seen = jiffies; |
| @@ -549,7 +577,7 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, | |||
| 549 | addr, BATADV_PRINT_VID(vid), | 577 | addr, BATADV_PRINT_VID(vid), |
| 550 | (uint8_t)atomic_read(&bat_priv->tt.vn)); | 578 | (uint8_t)atomic_read(&bat_priv->tt.vn)); |
| 551 | 579 | ||
| 552 | memcpy(tt_local->common.addr, addr, ETH_ALEN); | 580 | ether_addr_copy(tt_local->common.addr, addr); |
| 553 | /* The local entry has to be marked as NEW to avoid to send it in | 581 | /* The local entry has to be marked as NEW to avoid to send it in |
| 554 | * a full table response going out before the next ttvn increment | 582 | * a full table response going out before the next ttvn increment |
| 555 | * (consistency check) | 583 | * (consistency check) |
| @@ -562,8 +590,11 @@ bool batadv_tt_local_add(struct net_device *soft_iface, const uint8_t *addr, | |||
| 562 | tt_local->last_seen = jiffies; | 590 | tt_local->last_seen = jiffies; |
| 563 | tt_local->common.added_at = tt_local->last_seen; | 591 | tt_local->common.added_at = tt_local->last_seen; |
| 564 | 592 | ||
| 565 | /* the batman interface mac address should never be purged */ | 593 | /* the batman interface mac and multicast addresses should never be |
| 566 | if (batadv_compare_eth(addr, soft_iface->dev_addr)) | 594 | * purged |
| 595 | */ | ||
| 596 | if (batadv_compare_eth(addr, soft_iface->dev_addr) || | ||
| 597 | is_multicast_ether_addr(addr)) | ||
| 567 | tt_local->common.flags |= BATADV_TT_CLIENT_NOPURGE; | 598 | tt_local->common.flags |= BATADV_TT_CLIENT_NOPURGE; |
| 568 | 599 | ||
| 569 | hash_added = batadv_hash_add(bat_priv->tt.local_hash, batadv_compare_tt, | 600 | hash_added = batadv_hash_add(bat_priv->tt.local_hash, batadv_compare_tt, |
| @@ -1219,6 +1250,8 @@ batadv_tt_global_orig_entry_add(struct batadv_tt_global_entry *tt_global, | |||
| 1219 | hlist_add_head_rcu(&orig_entry->list, | 1250 | hlist_add_head_rcu(&orig_entry->list, |
| 1220 | &tt_global->orig_list); | 1251 | &tt_global->orig_list); |
| 1221 | spin_unlock_bh(&tt_global->list_lock); | 1252 | spin_unlock_bh(&tt_global->list_lock); |
| 1253 | atomic_inc(&tt_global->orig_list_count); | ||
| 1254 | |||
| 1222 | out: | 1255 | out: |
| 1223 | if (orig_entry) | 1256 | if (orig_entry) |
| 1224 | batadv_tt_orig_list_entry_free_ref(orig_entry); | 1257 | batadv_tt_orig_list_entry_free_ref(orig_entry); |
| @@ -1277,7 +1310,7 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv, | |||
| 1277 | goto out; | 1310 | goto out; |
| 1278 | 1311 | ||
| 1279 | common = &tt_global_entry->common; | 1312 | common = &tt_global_entry->common; |
| 1280 | memcpy(common->addr, tt_addr, ETH_ALEN); | 1313 | ether_addr_copy(common->addr, tt_addr); |
| 1281 | common->vid = vid; | 1314 | common->vid = vid; |
| 1282 | 1315 | ||
| 1283 | common->flags = flags; | 1316 | common->flags = flags; |
| @@ -1292,6 +1325,7 @@ static bool batadv_tt_global_add(struct batadv_priv *bat_priv, | |||
| 1292 | common->added_at = jiffies; | 1325 | common->added_at = jiffies; |
| 1293 | 1326 | ||
| 1294 | INIT_HLIST_HEAD(&tt_global_entry->orig_list); | 1327 | INIT_HLIST_HEAD(&tt_global_entry->orig_list); |
| 1328 | atomic_set(&tt_global_entry->orig_list_count, 0); | ||
| 1295 | spin_lock_init(&tt_global_entry->list_lock); | 1329 | spin_lock_init(&tt_global_entry->list_lock); |
| 1296 | 1330 | ||
| 1297 | hash_added = batadv_hash_add(bat_priv->tt.global_hash, | 1331 | hash_added = batadv_hash_add(bat_priv->tt.global_hash, |
| @@ -1361,6 +1395,11 @@ add_orig_entry: | |||
| 1361 | ret = true; | 1395 | ret = true; |
| 1362 | 1396 | ||
| 1363 | out_remove: | 1397 | out_remove: |
| 1398 | /* Do not remove multicast addresses from the local hash on | ||
| 1399 | * global additions | ||
| 1400 | */ | ||
| 1401 | if (is_multicast_ether_addr(tt_addr)) | ||
| 1402 | goto out; | ||
| 1364 | 1403 | ||
| 1365 | /* remove address from local hash if present */ | 1404 | /* remove address from local hash if present */ |
| 1366 | local_flags = batadv_tt_local_remove(bat_priv, tt_addr, vid, | 1405 | local_flags = batadv_tt_local_remove(bat_priv, tt_addr, vid, |
| @@ -1552,6 +1591,25 @@ out: | |||
| 1552 | return 0; | 1591 | return 0; |
| 1553 | } | 1592 | } |
| 1554 | 1593 | ||
| 1594 | /** | ||
| 1595 | * batadv_tt_global_del_orig_entry - remove and free an orig_entry | ||
| 1596 | * @tt_global_entry: the global entry to remove the orig_entry from | ||
| 1597 | * @orig_entry: the orig entry to remove and free | ||
| 1598 | * | ||
| 1599 | * Remove an orig_entry from its list in the given tt_global_entry and | ||
| 1600 | * free this orig_entry afterwards. | ||
| 1601 | */ | ||
| 1602 | static void | ||
| 1603 | batadv_tt_global_del_orig_entry(struct batadv_tt_global_entry *tt_global_entry, | ||
| 1604 | struct batadv_tt_orig_list_entry *orig_entry) | ||
| 1605 | { | ||
| 1606 | batadv_tt_global_size_dec(orig_entry->orig_node, | ||
| 1607 | tt_global_entry->common.vid); | ||
| 1608 | atomic_dec(&tt_global_entry->orig_list_count); | ||
| 1609 | hlist_del_rcu(&orig_entry->list); | ||
| 1610 | batadv_tt_orig_list_entry_free_ref(orig_entry); | ||
| 1611 | } | ||
| 1612 | |||
| 1555 | /* deletes the orig list of a tt_global_entry */ | 1613 | /* deletes the orig list of a tt_global_entry */ |
| 1556 | static void | 1614 | static void |
| 1557 | batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry) | 1615 | batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry) |
| @@ -1562,20 +1620,26 @@ batadv_tt_global_del_orig_list(struct batadv_tt_global_entry *tt_global_entry) | |||
| 1562 | 1620 | ||
| 1563 | spin_lock_bh(&tt_global_entry->list_lock); | 1621 | spin_lock_bh(&tt_global_entry->list_lock); |
| 1564 | head = &tt_global_entry->orig_list; | 1622 | head = &tt_global_entry->orig_list; |
| 1565 | hlist_for_each_entry_safe(orig_entry, safe, head, list) { | 1623 | hlist_for_each_entry_safe(orig_entry, safe, head, list) |
| 1566 | hlist_del_rcu(&orig_entry->list); | 1624 | batadv_tt_global_del_orig_entry(tt_global_entry, orig_entry); |
| 1567 | batadv_tt_global_size_dec(orig_entry->orig_node, | ||
| 1568 | tt_global_entry->common.vid); | ||
| 1569 | batadv_tt_orig_list_entry_free_ref(orig_entry); | ||
| 1570 | } | ||
| 1571 | spin_unlock_bh(&tt_global_entry->list_lock); | 1625 | spin_unlock_bh(&tt_global_entry->list_lock); |
| 1572 | } | 1626 | } |
| 1573 | 1627 | ||
| 1628 | /** | ||
| 1629 | * batadv_tt_global_del_orig_node - remove orig_node from a global tt entry | ||
| 1630 | * @bat_priv: the bat priv with all the soft interface information | ||
| 1631 | * @tt_global_entry: the global entry to remove the orig_node from | ||
| 1632 | * @orig_node: the originator announcing the client | ||
| 1633 | * @message: message to append to the log on deletion | ||
| 1634 | * | ||
| 1635 | * Remove the given orig_node and its according orig_entry from the given | ||
| 1636 | * global tt entry. | ||
| 1637 | */ | ||
| 1574 | static void | 1638 | static void |
| 1575 | batadv_tt_global_del_orig_entry(struct batadv_priv *bat_priv, | 1639 | batadv_tt_global_del_orig_node(struct batadv_priv *bat_priv, |
| 1576 | struct batadv_tt_global_entry *tt_global_entry, | 1640 | struct batadv_tt_global_entry *tt_global_entry, |
| 1577 | struct batadv_orig_node *orig_node, | 1641 | struct batadv_orig_node *orig_node, |
| 1578 | const char *message) | 1642 | const char *message) |
| 1579 | { | 1643 | { |
| 1580 | struct hlist_head *head; | 1644 | struct hlist_head *head; |
| 1581 | struct hlist_node *safe; | 1645 | struct hlist_node *safe; |
| @@ -1592,10 +1656,8 @@ batadv_tt_global_del_orig_entry(struct batadv_priv *bat_priv, | |||
| 1592 | orig_node->orig, | 1656 | orig_node->orig, |
| 1593 | tt_global_entry->common.addr, | 1657 | tt_global_entry->common.addr, |
| 1594 | BATADV_PRINT_VID(vid), message); | 1658 | BATADV_PRINT_VID(vid), message); |
| 1595 | hlist_del_rcu(&orig_entry->list); | 1659 | batadv_tt_global_del_orig_entry(tt_global_entry, |
| 1596 | batadv_tt_global_size_dec(orig_node, | 1660 | orig_entry); |
| 1597 | tt_global_entry->common.vid); | ||
| 1598 | batadv_tt_orig_list_entry_free_ref(orig_entry); | ||
| 1599 | } | 1661 | } |
| 1600 | } | 1662 | } |
| 1601 | spin_unlock_bh(&tt_global_entry->list_lock); | 1663 | spin_unlock_bh(&tt_global_entry->list_lock); |
| @@ -1637,8 +1699,8 @@ batadv_tt_global_del_roaming(struct batadv_priv *bat_priv, | |||
| 1637 | /* there is another entry, we can simply delete this | 1699 | /* there is another entry, we can simply delete this |
| 1638 | * one and can still use the other one. | 1700 | * one and can still use the other one. |
| 1639 | */ | 1701 | */ |
| 1640 | batadv_tt_global_del_orig_entry(bat_priv, tt_global_entry, | 1702 | batadv_tt_global_del_orig_node(bat_priv, tt_global_entry, |
| 1641 | orig_node, message); | 1703 | orig_node, message); |
| 1642 | } | 1704 | } |
| 1643 | 1705 | ||
| 1644 | /** | 1706 | /** |
| @@ -1664,8 +1726,8 @@ static void batadv_tt_global_del(struct batadv_priv *bat_priv, | |||
| 1664 | goto out; | 1726 | goto out; |
| 1665 | 1727 | ||
| 1666 | if (!roaming) { | 1728 | if (!roaming) { |
| 1667 | batadv_tt_global_del_orig_entry(bat_priv, tt_global_entry, | 1729 | batadv_tt_global_del_orig_node(bat_priv, tt_global_entry, |
| 1668 | orig_node, message); | 1730 | orig_node, message); |
| 1669 | 1731 | ||
| 1670 | if (hlist_empty(&tt_global_entry->orig_list)) | 1732 | if (hlist_empty(&tt_global_entry->orig_list)) |
| 1671 | batadv_tt_global_free(bat_priv, tt_global_entry, | 1733 | batadv_tt_global_free(bat_priv, tt_global_entry, |
| @@ -1748,8 +1810,8 @@ void batadv_tt_global_del_orig(struct batadv_priv *bat_priv, | |||
| 1748 | struct batadv_tt_global_entry, | 1810 | struct batadv_tt_global_entry, |
| 1749 | common); | 1811 | common); |
| 1750 | 1812 | ||
| 1751 | batadv_tt_global_del_orig_entry(bat_priv, tt_global, | 1813 | batadv_tt_global_del_orig_node(bat_priv, tt_global, |
| 1752 | orig_node, message); | 1814 | orig_node, message); |
| 1753 | 1815 | ||
| 1754 | if (hlist_empty(&tt_global->orig_list)) { | 1816 | if (hlist_empty(&tt_global->orig_list)) { |
| 1755 | vid = tt_global->common.vid; | 1817 | vid = tt_global->common.vid; |
| @@ -1763,7 +1825,7 @@ void batadv_tt_global_del_orig(struct batadv_priv *bat_priv, | |||
| 1763 | } | 1825 | } |
| 1764 | spin_unlock_bh(list_lock); | 1826 | spin_unlock_bh(list_lock); |
| 1765 | } | 1827 | } |
| 1766 | orig_node->tt_initialised = false; | 1828 | orig_node->capa_initialized &= ~BATADV_ORIG_CAPA_HAS_TT; |
| 1767 | } | 1829 | } |
| 1768 | 1830 | ||
| 1769 | static bool batadv_tt_global_to_purge(struct batadv_tt_global_entry *tt_global, | 1831 | static bool batadv_tt_global_to_purge(struct batadv_tt_global_entry *tt_global, |
| @@ -2160,7 +2222,7 @@ batadv_new_tt_req_node(struct batadv_priv *bat_priv, | |||
| 2160 | if (!tt_req_node) | 2222 | if (!tt_req_node) |
| 2161 | goto unlock; | 2223 | goto unlock; |
| 2162 | 2224 | ||
| 2163 | memcpy(tt_req_node->addr, orig_node->orig, ETH_ALEN); | 2225 | ether_addr_copy(tt_req_node->addr, orig_node->orig); |
| 2164 | tt_req_node->issued_at = jiffies; | 2226 | tt_req_node->issued_at = jiffies; |
| 2165 | 2227 | ||
| 2166 | list_add(&tt_req_node->list, &bat_priv->tt.req_list); | 2228 | list_add(&tt_req_node->list, &bat_priv->tt.req_list); |
| @@ -2240,8 +2302,7 @@ static void batadv_tt_tvlv_generate(struct batadv_priv *bat_priv, | |||
| 2240 | if ((valid_cb) && (!valid_cb(tt_common_entry, cb_data))) | 2302 | if ((valid_cb) && (!valid_cb(tt_common_entry, cb_data))) |
| 2241 | continue; | 2303 | continue; |
| 2242 | 2304 | ||
| 2243 | memcpy(tt_change->addr, tt_common_entry->addr, | 2305 | ether_addr_copy(tt_change->addr, tt_common_entry->addr); |
| 2244 | ETH_ALEN); | ||
| 2245 | tt_change->flags = tt_common_entry->flags; | 2306 | tt_change->flags = tt_common_entry->flags; |
| 2246 | tt_change->vid = htons(tt_common_entry->vid); | 2307 | tt_change->vid = htons(tt_common_entry->vid); |
| 2247 | memset(tt_change->reserved, 0, | 2308 | memset(tt_change->reserved, 0, |
| @@ -2724,7 +2785,7 @@ static void _batadv_tt_update_changes(struct batadv_priv *bat_priv, | |||
| 2724 | return; | 2785 | return; |
| 2725 | } | 2786 | } |
| 2726 | } | 2787 | } |
| 2727 | orig_node->tt_initialised = true; | 2788 | orig_node->capa_initialized |= BATADV_ORIG_CAPA_HAS_TT; |
| 2728 | } | 2789 | } |
| 2729 | 2790 | ||
| 2730 | static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv, | 2791 | static void batadv_tt_fill_gtable(struct batadv_priv *bat_priv, |
| @@ -2932,7 +2993,7 @@ static bool batadv_tt_check_roam_count(struct batadv_priv *bat_priv, | |||
| 2932 | tt_roam_node->first_time = jiffies; | 2993 | tt_roam_node->first_time = jiffies; |
| 2933 | atomic_set(&tt_roam_node->counter, | 2994 | atomic_set(&tt_roam_node->counter, |
| 2934 | BATADV_ROAMING_MAX_COUNT - 1); | 2995 | BATADV_ROAMING_MAX_COUNT - 1); |
| 2935 | memcpy(tt_roam_node->addr, client, ETH_ALEN); | 2996 | ether_addr_copy(tt_roam_node->addr, client); |
| 2936 | 2997 | ||
| 2937 | list_add(&tt_roam_node->list, &bat_priv->tt.roam_list); | 2998 | list_add(&tt_roam_node->list, &bat_priv->tt.roam_list); |
| 2938 | ret = true; | 2999 | ret = true; |
| @@ -3121,6 +3182,9 @@ static void batadv_tt_local_purge_pending_clients(struct batadv_priv *bat_priv) | |||
| 3121 | */ | 3182 | */ |
| 3122 | static void batadv_tt_local_commit_changes_nolock(struct batadv_priv *bat_priv) | 3183 | static void batadv_tt_local_commit_changes_nolock(struct batadv_priv *bat_priv) |
| 3123 | { | 3184 | { |
| 3185 | /* Update multicast addresses in local translation table */ | ||
| 3186 | batadv_mcast_mla_update(bat_priv); | ||
| 3187 | |||
| 3124 | if (atomic_read(&bat_priv->tt.local_changes) < 1) { | 3188 | if (atomic_read(&bat_priv->tt.local_changes) < 1) { |
| 3125 | if (!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt)) | 3189 | if (!batadv_atomic_dec_not_zero(&bat_priv->tt.ogm_append_cnt)) |
| 3126 | batadv_tt_tvlv_container_update(bat_priv); | 3190 | batadv_tt_tvlv_container_update(bat_priv); |
| @@ -3211,13 +3275,15 @@ static void batadv_tt_update_orig(struct batadv_priv *bat_priv, | |||
| 3211 | uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); | 3275 | uint8_t orig_ttvn = (uint8_t)atomic_read(&orig_node->last_ttvn); |
| 3212 | struct batadv_tvlv_tt_vlan_data *tt_vlan; | 3276 | struct batadv_tvlv_tt_vlan_data *tt_vlan; |
| 3213 | bool full_table = true; | 3277 | bool full_table = true; |
| 3278 | bool has_tt_init; | ||
| 3214 | 3279 | ||
| 3215 | tt_vlan = (struct batadv_tvlv_tt_vlan_data *)tt_buff; | 3280 | tt_vlan = (struct batadv_tvlv_tt_vlan_data *)tt_buff; |
| 3281 | has_tt_init = orig_node->capa_initialized & BATADV_ORIG_CAPA_HAS_TT; | ||
| 3282 | |||
| 3216 | /* orig table not initialised AND first diff is in the OGM OR the ttvn | 3283 | /* orig table not initialised AND first diff is in the OGM OR the ttvn |
| 3217 | * increased by one -> we can apply the attached changes | 3284 | * increased by one -> we can apply the attached changes |
| 3218 | */ | 3285 | */ |
| 3219 | if ((!orig_node->tt_initialised && ttvn == 1) || | 3286 | if ((!has_tt_init && ttvn == 1) || ttvn - orig_ttvn == 1) { |
| 3220 | ttvn - orig_ttvn == 1) { | ||
| 3221 | /* the OGM could not contain the changes due to their size or | 3287 | /* the OGM could not contain the changes due to their size or |
| 3222 | * because they have already been sent BATADV_TT_OGM_APPEND_MAX | 3288 | * because they have already been sent BATADV_TT_OGM_APPEND_MAX |
| 3223 | * times. | 3289 | * times. |
| @@ -3257,7 +3323,7 @@ static void batadv_tt_update_orig(struct batadv_priv *bat_priv, | |||
| 3257 | /* if we missed more than one change or our tables are not | 3323 | /* if we missed more than one change or our tables are not |
| 3258 | * in sync anymore -> request fresh tt data | 3324 | * in sync anymore -> request fresh tt data |
| 3259 | */ | 3325 | */ |
| 3260 | if (!orig_node->tt_initialised || ttvn != orig_ttvn || | 3326 | if (!has_tt_init || ttvn != orig_ttvn || |
| 3261 | !batadv_tt_global_check_crc(orig_node, tt_vlan, | 3327 | !batadv_tt_global_check_crc(orig_node, tt_vlan, |
| 3262 | tt_num_vlan)) { | 3328 | tt_num_vlan)) { |
| 3263 | request_table: | 3329 | request_table: |
diff --git a/net/batman-adv/translation-table.h b/net/batman-adv/translation-table.h index 20a1d7861ded..ad84d7b89e39 100644 --- a/net/batman-adv/translation-table.h +++ b/net/batman-adv/translation-table.h | |||
| @@ -29,6 +29,8 @@ int batadv_tt_global_seq_print_text(struct seq_file *seq, void *offset); | |||
| 29 | void batadv_tt_global_del_orig(struct batadv_priv *bat_priv, | 29 | void batadv_tt_global_del_orig(struct batadv_priv *bat_priv, |
| 30 | struct batadv_orig_node *orig_node, | 30 | struct batadv_orig_node *orig_node, |
| 31 | int32_t match_vid, const char *message); | 31 | int32_t match_vid, const char *message); |
| 32 | int batadv_tt_global_hash_count(struct batadv_priv *bat_priv, | ||
| 33 | const uint8_t *addr, unsigned short vid); | ||
| 32 | struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv, | 34 | struct batadv_orig_node *batadv_transtable_search(struct batadv_priv *bat_priv, |
| 33 | const uint8_t *src, | 35 | const uint8_t *src, |
| 34 | const uint8_t *addr, | 36 | const uint8_t *addr, |
diff --git a/net/batman-adv/types.h b/net/batman-adv/types.h index 78370ab31f9c..34891a56773f 100644 --- a/net/batman-adv/types.h +++ b/net/batman-adv/types.h | |||
| @@ -24,8 +24,9 @@ | |||
| 24 | 24 | ||
| 25 | #ifdef CONFIG_BATMAN_ADV_DAT | 25 | #ifdef CONFIG_BATMAN_ADV_DAT |
| 26 | 26 | ||
| 27 | /* batadv_dat_addr_t is the type used for all DHT addresses. If it is changed, | 27 | /** |
| 28 | * BATADV_DAT_ADDR_MAX is changed as well. | 28 | * batadv_dat_addr_t - it is the type used for all DHT addresses. If it is |
| 29 | * changed, BATADV_DAT_ADDR_MAX is changed as well. | ||
| 29 | * | 30 | * |
| 30 | * *Please be careful: batadv_dat_addr_t must be UNSIGNED* | 31 | * *Please be careful: batadv_dat_addr_t must be UNSIGNED* |
| 31 | */ | 32 | */ |
| @@ -163,7 +164,7 @@ struct batadv_vlan_tt { | |||
| 163 | }; | 164 | }; |
| 164 | 165 | ||
| 165 | /** | 166 | /** |
| 166 | * batadv_orig_node_vlan - VLAN specific data per orig_node | 167 | * struct batadv_orig_node_vlan - VLAN specific data per orig_node |
| 167 | * @vid: the VLAN identifier | 168 | * @vid: the VLAN identifier |
| 168 | * @tt: VLAN specific TT attributes | 169 | * @tt: VLAN specific TT attributes |
| 169 | * @list: list node for orig_node::vlan_list | 170 | * @list: list node for orig_node::vlan_list |
| @@ -204,14 +205,18 @@ struct batadv_orig_bat_iv { | |||
| 204 | * @batadv_dat_addr_t: address of the orig node in the distributed hash | 205 | * @batadv_dat_addr_t: address of the orig node in the distributed hash |
| 205 | * @last_seen: time when last packet from this node was received | 206 | * @last_seen: time when last packet from this node was received |
| 206 | * @bcast_seqno_reset: time when the broadcast seqno window was reset | 207 | * @bcast_seqno_reset: time when the broadcast seqno window was reset |
| 208 | * @mcast_flags: multicast flags announced by the orig node | ||
| 209 | * @mcast_want_all_unsnoop_node: a list node for the | ||
| 210 | * mcast.want_all_unsnoopables list | ||
| 211 | * @mcast_want_all_ipv4_node: a list node for the mcast.want_all_ipv4 list | ||
| 212 | * @mcast_want_all_ipv6_node: a list node for the mcast.want_all_ipv6 list | ||
| 207 | * @capabilities: announced capabilities of this originator | 213 | * @capabilities: announced capabilities of this originator |
| 214 | * @capa_initialized: bitfield to remember whether a capability was initialized | ||
| 208 | * @last_ttvn: last seen translation table version number | 215 | * @last_ttvn: last seen translation table version number |
| 209 | * @tt_buff: last tt changeset this node received from the orig node | 216 | * @tt_buff: last tt changeset this node received from the orig node |
| 210 | * @tt_buff_len: length of the last tt changeset this node received from the | 217 | * @tt_buff_len: length of the last tt changeset this node received from the |
| 211 | * orig node | 218 | * orig node |
| 212 | * @tt_buff_lock: lock that protects tt_buff and tt_buff_len | 219 | * @tt_buff_lock: lock that protects tt_buff and tt_buff_len |
| 213 | * @tt_initialised: bool keeping track of whether or not this node have received | ||
| 214 | * any translation table information from the orig node yet | ||
| 215 | * @tt_lock: prevents from updating the table while reading it. Table update is | 220 | * @tt_lock: prevents from updating the table while reading it. Table update is |
| 216 | * made up by two operations (data structure update and metdata -CRC/TTVN- | 221 | * made up by two operations (data structure update and metdata -CRC/TTVN- |
| 217 | * recalculation) and they have to be executed atomically in order to avoid | 222 | * recalculation) and they have to be executed atomically in order to avoid |
| @@ -247,12 +252,18 @@ struct batadv_orig_node { | |||
| 247 | #endif | 252 | #endif |
| 248 | unsigned long last_seen; | 253 | unsigned long last_seen; |
| 249 | unsigned long bcast_seqno_reset; | 254 | unsigned long bcast_seqno_reset; |
| 255 | #ifdef CONFIG_BATMAN_ADV_MCAST | ||
| 256 | uint8_t mcast_flags; | ||
| 257 | struct hlist_node mcast_want_all_unsnoopables_node; | ||
| 258 | struct hlist_node mcast_want_all_ipv4_node; | ||
| 259 | struct hlist_node mcast_want_all_ipv6_node; | ||
| 260 | #endif | ||
| 250 | uint8_t capabilities; | 261 | uint8_t capabilities; |
| 262 | uint8_t capa_initialized; | ||
| 251 | atomic_t last_ttvn; | 263 | atomic_t last_ttvn; |
| 252 | unsigned char *tt_buff; | 264 | unsigned char *tt_buff; |
| 253 | int16_t tt_buff_len; | 265 | int16_t tt_buff_len; |
| 254 | spinlock_t tt_buff_lock; /* protects tt_buff & tt_buff_len */ | 266 | spinlock_t tt_buff_lock; /* protects tt_buff & tt_buff_len */ |
| 255 | bool tt_initialised; | ||
| 256 | /* prevents from changing the table while reading it */ | 267 | /* prevents from changing the table while reading it */ |
| 257 | spinlock_t tt_lock; | 268 | spinlock_t tt_lock; |
| 258 | DECLARE_BITMAP(bcast_bits, BATADV_TQ_LOCAL_WINDOW_SIZE); | 269 | DECLARE_BITMAP(bcast_bits, BATADV_TQ_LOCAL_WINDOW_SIZE); |
| @@ -282,10 +293,15 @@ struct batadv_orig_node { | |||
| 282 | * enum batadv_orig_capabilities - orig node capabilities | 293 | * enum batadv_orig_capabilities - orig node capabilities |
| 283 | * @BATADV_ORIG_CAPA_HAS_DAT: orig node has distributed arp table enabled | 294 | * @BATADV_ORIG_CAPA_HAS_DAT: orig node has distributed arp table enabled |
| 284 | * @BATADV_ORIG_CAPA_HAS_NC: orig node has network coding enabled | 295 | * @BATADV_ORIG_CAPA_HAS_NC: orig node has network coding enabled |
| 296 | * @BATADV_ORIG_CAPA_HAS_TT: orig node has tt capability | ||
| 297 | * @BATADV_ORIG_CAPA_HAS_MCAST: orig node has some multicast capability | ||
| 298 | * (= orig node announces a tvlv of type BATADV_TVLV_MCAST) | ||
| 285 | */ | 299 | */ |
| 286 | enum batadv_orig_capabilities { | 300 | enum batadv_orig_capabilities { |
| 287 | BATADV_ORIG_CAPA_HAS_DAT = BIT(0), | 301 | BATADV_ORIG_CAPA_HAS_DAT = BIT(0), |
| 288 | BATADV_ORIG_CAPA_HAS_NC = BIT(1), | 302 | BATADV_ORIG_CAPA_HAS_NC = BIT(1), |
| 303 | BATADV_ORIG_CAPA_HAS_TT = BIT(2), | ||
| 304 | BATADV_ORIG_CAPA_HAS_MCAST = BIT(3), | ||
| 289 | }; | 305 | }; |
| 290 | 306 | ||
| 291 | /** | 307 | /** |
| @@ -334,7 +350,7 @@ struct batadv_neigh_node { | |||
| 334 | }; | 350 | }; |
| 335 | 351 | ||
| 336 | /** | 352 | /** |
| 337 | * struct batadv_neigh_node_bat_iv - neighbor information per outgoing | 353 | * struct batadv_neigh_ifinfo_bat_iv - neighbor information per outgoing |
| 338 | * interface for BATMAN IV | 354 | * interface for BATMAN IV |
| 339 | * @tq_recv: ring buffer of received TQ values from this neigh node | 355 | * @tq_recv: ring buffer of received TQ values from this neigh node |
| 340 | * @tq_index: ring buffer index | 356 | * @tq_index: ring buffer index |
| @@ -544,7 +560,7 @@ struct batadv_priv_bla { | |||
| 544 | #endif | 560 | #endif |
| 545 | 561 | ||
| 546 | /** | 562 | /** |
| 547 | * struct batadv_debug_log - debug logging data | 563 | * struct batadv_priv_debug_log - debug logging data |
| 548 | * @log_buff: buffer holding the logs (ring bufer) | 564 | * @log_buff: buffer holding the logs (ring bufer) |
| 549 | * @log_start: index of next character to read | 565 | * @log_start: index of next character to read |
| 550 | * @log_end: index of next character to write | 566 | * @log_end: index of next character to write |
| @@ -607,6 +623,39 @@ struct batadv_priv_dat { | |||
| 607 | }; | 623 | }; |
| 608 | #endif | 624 | #endif |
| 609 | 625 | ||
| 626 | #ifdef CONFIG_BATMAN_ADV_MCAST | ||
| 627 | /** | ||
| 628 | * struct batadv_priv_mcast - per mesh interface mcast data | ||
| 629 | * @mla_list: list of multicast addresses we are currently announcing via TT | ||
| 630 | * @want_all_unsnoopables_list: a list of orig_nodes wanting all unsnoopable | ||
| 631 | * multicast traffic | ||
| 632 | * @want_all_ipv4_list: a list of orig_nodes wanting all IPv4 multicast traffic | ||
| 633 | * @want_all_ipv6_list: a list of orig_nodes wanting all IPv6 multicast traffic | ||
| 634 | * @flags: the flags we have last sent in our mcast tvlv | ||
| 635 | * @enabled: whether the multicast tvlv is currently enabled | ||
| 636 | * @num_disabled: number of nodes that have no mcast tvlv | ||
| 637 | * @num_want_all_unsnoopables: number of nodes wanting unsnoopable IP traffic | ||
| 638 | * @num_want_all_ipv4: counter for items in want_all_ipv4_list | ||
| 639 | * @num_want_all_ipv6: counter for items in want_all_ipv6_list | ||
| 640 | * @want_lists_lock: lock for protecting modifications to mcast want lists | ||
| 641 | * (traversals are rcu-locked) | ||
| 642 | */ | ||
| 643 | struct batadv_priv_mcast { | ||
| 644 | struct hlist_head mla_list; | ||
| 645 | struct hlist_head want_all_unsnoopables_list; | ||
| 646 | struct hlist_head want_all_ipv4_list; | ||
| 647 | struct hlist_head want_all_ipv6_list; | ||
| 648 | uint8_t flags; | ||
| 649 | bool enabled; | ||
| 650 | atomic_t num_disabled; | ||
| 651 | atomic_t num_want_all_unsnoopables; | ||
| 652 | atomic_t num_want_all_ipv4; | ||
| 653 | atomic_t num_want_all_ipv6; | ||
| 654 | /* protects want_all_{unsnoopables,ipv4,ipv6}_list */ | ||
| 655 | spinlock_t want_lists_lock; | ||
| 656 | }; | ||
| 657 | #endif | ||
| 658 | |||
| 610 | /** | 659 | /** |
| 611 | * struct batadv_priv_nc - per mesh interface network coding private data | 660 | * struct batadv_priv_nc - per mesh interface network coding private data |
| 612 | * @work: work queue callback item for cleanup | 661 | * @work: work queue callback item for cleanup |
| @@ -672,6 +721,8 @@ struct batadv_softif_vlan { | |||
| 672 | * enabled | 721 | * enabled |
| 673 | * @distributed_arp_table: bool indicating whether distributed ARP table is | 722 | * @distributed_arp_table: bool indicating whether distributed ARP table is |
| 674 | * enabled | 723 | * enabled |
| 724 | * @multicast_mode: Enable or disable multicast optimizations on this node's | ||
| 725 | * sender/originating side | ||
| 675 | * @gw_mode: gateway operation: off, client or server (see batadv_gw_modes) | 726 | * @gw_mode: gateway operation: off, client or server (see batadv_gw_modes) |
| 676 | * @gw_sel_class: gateway selection class (applies if gw_mode client) | 727 | * @gw_sel_class: gateway selection class (applies if gw_mode client) |
| 677 | * @orig_interval: OGM broadcast interval in milliseconds | 728 | * @orig_interval: OGM broadcast interval in milliseconds |
| @@ -702,6 +753,7 @@ struct batadv_softif_vlan { | |||
| 702 | * @tt: translation table data | 753 | * @tt: translation table data |
| 703 | * @tvlv: type-version-length-value data | 754 | * @tvlv: type-version-length-value data |
| 704 | * @dat: distributed arp table data | 755 | * @dat: distributed arp table data |
| 756 | * @mcast: multicast data | ||
| 705 | * @network_coding: bool indicating whether network coding is enabled | 757 | * @network_coding: bool indicating whether network coding is enabled |
| 706 | * @batadv_priv_nc: network coding data | 758 | * @batadv_priv_nc: network coding data |
| 707 | */ | 759 | */ |
| @@ -721,6 +773,9 @@ struct batadv_priv { | |||
| 721 | #ifdef CONFIG_BATMAN_ADV_DAT | 773 | #ifdef CONFIG_BATMAN_ADV_DAT |
| 722 | atomic_t distributed_arp_table; | 774 | atomic_t distributed_arp_table; |
| 723 | #endif | 775 | #endif |
| 776 | #ifdef CONFIG_BATMAN_ADV_MCAST | ||
| 777 | atomic_t multicast_mode; | ||
| 778 | #endif | ||
| 724 | atomic_t gw_mode; | 779 | atomic_t gw_mode; |
| 725 | atomic_t gw_sel_class; | 780 | atomic_t gw_sel_class; |
| 726 | atomic_t orig_interval; | 781 | atomic_t orig_interval; |
| @@ -759,6 +814,9 @@ struct batadv_priv { | |||
| 759 | #ifdef CONFIG_BATMAN_ADV_DAT | 814 | #ifdef CONFIG_BATMAN_ADV_DAT |
| 760 | struct batadv_priv_dat dat; | 815 | struct batadv_priv_dat dat; |
| 761 | #endif | 816 | #endif |
| 817 | #ifdef CONFIG_BATMAN_ADV_MCAST | ||
| 818 | struct batadv_priv_mcast mcast; | ||
| 819 | #endif | ||
| 762 | #ifdef CONFIG_BATMAN_ADV_NC | 820 | #ifdef CONFIG_BATMAN_ADV_NC |
| 763 | atomic_t network_coding; | 821 | atomic_t network_coding; |
| 764 | struct batadv_priv_nc nc; | 822 | struct batadv_priv_nc nc; |
| @@ -881,12 +939,14 @@ struct batadv_tt_local_entry { | |||
| 881 | * struct batadv_tt_global_entry - translation table global entry data | 939 | * struct batadv_tt_global_entry - translation table global entry data |
| 882 | * @common: general translation table data | 940 | * @common: general translation table data |
| 883 | * @orig_list: list of orig nodes announcing this non-mesh client | 941 | * @orig_list: list of orig nodes announcing this non-mesh client |
| 942 | * @orig_list_count: number of items in the orig_list | ||
| 884 | * @list_lock: lock protecting orig_list | 943 | * @list_lock: lock protecting orig_list |
| 885 | * @roam_at: time at which TT_GLOBAL_ROAM was set | 944 | * @roam_at: time at which TT_GLOBAL_ROAM was set |
| 886 | */ | 945 | */ |
| 887 | struct batadv_tt_global_entry { | 946 | struct batadv_tt_global_entry { |
| 888 | struct batadv_tt_common_entry common; | 947 | struct batadv_tt_common_entry common; |
| 889 | struct hlist_head orig_list; | 948 | struct hlist_head orig_list; |
| 949 | atomic_t orig_list_count; | ||
| 890 | spinlock_t list_lock; /* protects orig_list */ | 950 | spinlock_t list_lock; /* protects orig_list */ |
| 891 | unsigned long roam_at; | 951 | unsigned long roam_at; |
| 892 | }; | 952 | }; |
| @@ -1004,8 +1064,8 @@ struct batadv_nc_packet { | |||
| 1004 | }; | 1064 | }; |
| 1005 | 1065 | ||
| 1006 | /** | 1066 | /** |
| 1007 | * batadv_skb_cb - control buffer structure used to store private data relevant | 1067 | * struct batadv_skb_cb - control buffer structure used to store private data |
| 1008 | * to batman-adv in the skb->cb buffer in skbs. | 1068 | * relevant to batman-adv in the skb->cb buffer in skbs. |
| 1009 | * @decoded: Marks a skb as decoded, which is checked when searching for coding | 1069 | * @decoded: Marks a skb as decoded, which is checked when searching for coding |
| 1010 | * opportunities in network-coding.c | 1070 | * opportunities in network-coding.c |
| 1011 | */ | 1071 | */ |
| @@ -1116,6 +1176,16 @@ struct batadv_dat_entry { | |||
| 1116 | }; | 1176 | }; |
| 1117 | 1177 | ||
| 1118 | /** | 1178 | /** |
| 1179 | * struct batadv_hw_addr - a list entry for a MAC address | ||
| 1180 | * @list: list node for the linking of entries | ||
| 1181 | * @addr: the MAC address of this list entry | ||
| 1182 | */ | ||
| 1183 | struct batadv_hw_addr { | ||
| 1184 | struct hlist_node list; | ||
| 1185 | unsigned char addr[ETH_ALEN]; | ||
| 1186 | }; | ||
| 1187 | |||
| 1188 | /** | ||
| 1119 | * struct batadv_dat_candidate - candidate destination for DAT operations | 1189 | * struct batadv_dat_candidate - candidate destination for DAT operations |
| 1120 | * @type: the type of the selected candidate. It can one of the following: | 1190 | * @type: the type of the selected candidate. It can one of the following: |
| 1121 | * - BATADV_DAT_CANDIDATE_NOT_FOUND | 1191 | * - BATADV_DAT_CANDIDATE_NOT_FOUND |
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c index adb3ea04adaa..73492b91105a 100644 --- a/net/bluetooth/6lowpan.c +++ b/net/bluetooth/6lowpan.c | |||
| @@ -27,7 +27,7 @@ | |||
| 27 | 27 | ||
| 28 | #include "6lowpan.h" | 28 | #include "6lowpan.h" |
| 29 | 29 | ||
| 30 | #include "../ieee802154/6lowpan.h" /* for the compression support */ | 30 | #include <net/6lowpan.h> /* for the compression support */ |
| 31 | 31 | ||
| 32 | #define IFACE_NAME_TEMPLATE "bt%d" | 32 | #define IFACE_NAME_TEMPLATE "bt%d" |
| 33 | #define EUI64_ADDR_LEN 8 | 33 | #define EUI64_ADDR_LEN 8 |
diff --git a/net/bluetooth/6lowpan.h b/net/bluetooth/6lowpan.h index 680eac808d74..5d281f1eaf55 100644 --- a/net/bluetooth/6lowpan.h +++ b/net/bluetooth/6lowpan.h | |||
| @@ -14,13 +14,34 @@ | |||
| 14 | #ifndef __6LOWPAN_H | 14 | #ifndef __6LOWPAN_H |
| 15 | #define __6LOWPAN_H | 15 | #define __6LOWPAN_H |
| 16 | 16 | ||
| 17 | #include <linux/errno.h> | ||
| 17 | #include <linux/skbuff.h> | 18 | #include <linux/skbuff.h> |
| 18 | #include <net/bluetooth/l2cap.h> | 19 | #include <net/bluetooth/l2cap.h> |
| 19 | 20 | ||
| 21 | #if IS_ENABLED(CONFIG_BT_6LOWPAN) | ||
| 20 | int bt_6lowpan_recv(struct l2cap_conn *conn, struct sk_buff *skb); | 22 | int bt_6lowpan_recv(struct l2cap_conn *conn, struct sk_buff *skb); |
| 21 | int bt_6lowpan_add_conn(struct l2cap_conn *conn); | 23 | int bt_6lowpan_add_conn(struct l2cap_conn *conn); |
| 22 | int bt_6lowpan_del_conn(struct l2cap_conn *conn); | 24 | int bt_6lowpan_del_conn(struct l2cap_conn *conn); |
| 23 | int bt_6lowpan_init(void); | 25 | int bt_6lowpan_init(void); |
| 24 | void bt_6lowpan_cleanup(void); | 26 | void bt_6lowpan_cleanup(void); |
| 27 | #else | ||
| 28 | static int bt_6lowpan_recv(struct l2cap_conn *conn, struct sk_buff *skb) | ||
| 29 | { | ||
| 30 | return -EOPNOTSUPP; | ||
| 31 | } | ||
| 32 | static int bt_6lowpan_add_conn(struct l2cap_conn *conn) | ||
| 33 | { | ||
| 34 | return -EOPNOTSUPP; | ||
| 35 | } | ||
| 36 | int bt_6lowpan_del_conn(struct l2cap_conn *conn) | ||
| 37 | { | ||
| 38 | return -EOPNOTSUPP; | ||
| 39 | } | ||
| 40 | static int bt_6lowpan_init(void) | ||
| 41 | { | ||
| 42 | return -EOPNOTSUPP; | ||
| 43 | } | ||
| 44 | static void bt_6lowpan_cleanup(void) { } | ||
| 45 | #endif | ||
| 25 | 46 | ||
| 26 | #endif /* __6LOWPAN_H */ | 47 | #endif /* __6LOWPAN_H */ |
diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig index 985b56070d26..06ec14499ca1 100644 --- a/net/bluetooth/Kconfig +++ b/net/bluetooth/Kconfig | |||
| @@ -6,13 +6,13 @@ menuconfig BT | |||
| 6 | tristate "Bluetooth subsystem support" | 6 | tristate "Bluetooth subsystem support" |
| 7 | depends on NET && !S390 | 7 | depends on NET && !S390 |
| 8 | depends on RFKILL || !RFKILL | 8 | depends on RFKILL || !RFKILL |
| 9 | select 6LOWPAN_IPHC if BT_6LOWPAN | ||
| 9 | select CRC16 | 10 | select CRC16 |
| 10 | select CRYPTO | 11 | select CRYPTO |
| 11 | select CRYPTO_BLKCIPHER | 12 | select CRYPTO_BLKCIPHER |
| 12 | select CRYPTO_AES | 13 | select CRYPTO_AES |
| 13 | select CRYPTO_ECB | 14 | select CRYPTO_ECB |
| 14 | select CRYPTO_SHA256 | 15 | select CRYPTO_SHA256 |
| 15 | select 6LOWPAN_IPHC | ||
| 16 | help | 16 | help |
| 17 | Bluetooth is low-cost, low-power, short-range wireless technology. | 17 | Bluetooth is low-cost, low-power, short-range wireless technology. |
| 18 | It was designed as a replacement for cables and other short-range | 18 | It was designed as a replacement for cables and other short-range |
| @@ -40,6 +40,12 @@ menuconfig BT | |||
| 40 | to Bluetooth kernel modules are provided in the BlueZ packages. For | 40 | to Bluetooth kernel modules are provided in the BlueZ packages. For |
| 41 | more information, see <http://www.bluez.org/>. | 41 | more information, see <http://www.bluez.org/>. |
| 42 | 42 | ||
| 43 | config BT_6LOWPAN | ||
| 44 | bool "Bluetooth 6LoWPAN support" | ||
| 45 | depends on BT && IPV6 | ||
| 46 | help | ||
| 47 | IPv6 compression over Bluetooth. | ||
| 48 | |||
| 43 | source "net/bluetooth/rfcomm/Kconfig" | 49 | source "net/bluetooth/rfcomm/Kconfig" |
| 44 | 50 | ||
| 45 | source "net/bluetooth/bnep/Kconfig" | 51 | source "net/bluetooth/bnep/Kconfig" |
diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile index 80cb215826e8..ca51246b1016 100644 --- a/net/bluetooth/Makefile +++ b/net/bluetooth/Makefile | |||
| @@ -10,6 +10,7 @@ obj-$(CONFIG_BT_HIDP) += hidp/ | |||
| 10 | 10 | ||
| 11 | bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \ | 11 | bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \ |
| 12 | hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o \ | 12 | hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o sco.o lib.o \ |
| 13 | a2mp.o amp.o 6lowpan.o | 13 | a2mp.o amp.o |
| 14 | bluetooth-$(CONFIG_BT_6LOWPAN) += 6lowpan.o | ||
| 14 | 15 | ||
| 15 | subdir-ccflags-y += -D__CHECK_ENDIAN__ | 16 | subdir-ccflags-y += -D__CHECK_ENDIAN__ |
diff --git a/net/bluetooth/a2mp.c b/net/bluetooth/a2mp.c index efcd108822c4..9514cc9e850c 100644 --- a/net/bluetooth/a2mp.c +++ b/net/bluetooth/a2mp.c | |||
| @@ -162,7 +162,7 @@ static int a2mp_discover_req(struct amp_mgr *mgr, struct sk_buff *skb, | |||
| 162 | return -ENOMEM; | 162 | return -ENOMEM; |
| 163 | } | 163 | } |
| 164 | 164 | ||
| 165 | rsp->mtu = __constant_cpu_to_le16(L2CAP_A2MP_DEFAULT_MTU); | 165 | rsp->mtu = cpu_to_le16(L2CAP_A2MP_DEFAULT_MTU); |
| 166 | rsp->ext_feat = 0; | 166 | rsp->ext_feat = 0; |
| 167 | 167 | ||
| 168 | __a2mp_add_cl(mgr, rsp->cl); | 168 | __a2mp_add_cl(mgr, rsp->cl); |
| @@ -235,7 +235,7 @@ static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb, | |||
| 235 | BT_DBG("chan %p state %s", chan, | 235 | BT_DBG("chan %p state %s", chan, |
| 236 | state_to_string(chan->state)); | 236 | state_to_string(chan->state)); |
| 237 | 237 | ||
| 238 | if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) | 238 | if (chan->scid == L2CAP_CID_A2MP) |
| 239 | continue; | 239 | continue; |
| 240 | 240 | ||
| 241 | l2cap_chan_lock(chan); | 241 | l2cap_chan_lock(chan); |
| @@ -649,7 +649,7 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb) | |||
| 649 | if (err) { | 649 | if (err) { |
| 650 | struct a2mp_cmd_rej rej; | 650 | struct a2mp_cmd_rej rej; |
| 651 | 651 | ||
| 652 | rej.reason = __constant_cpu_to_le16(0); | 652 | rej.reason = cpu_to_le16(0); |
| 653 | hdr = (void *) skb->data; | 653 | hdr = (void *) skb->data; |
| 654 | 654 | ||
| 655 | BT_DBG("Send A2MP Rej: cmd 0x%2.2x err %d", hdr->code, err); | 655 | BT_DBG("Send A2MP Rej: cmd 0x%2.2x err %d", hdr->code, err); |
| @@ -695,7 +695,13 @@ static void a2mp_chan_state_change_cb(struct l2cap_chan *chan, int state, | |||
| 695 | static struct sk_buff *a2mp_chan_alloc_skb_cb(struct l2cap_chan *chan, | 695 | static struct sk_buff *a2mp_chan_alloc_skb_cb(struct l2cap_chan *chan, |
| 696 | unsigned long len, int nb) | 696 | unsigned long len, int nb) |
| 697 | { | 697 | { |
| 698 | return bt_skb_alloc(len, GFP_KERNEL); | 698 | struct sk_buff *skb; |
| 699 | |||
| 700 | skb = bt_skb_alloc(len, GFP_KERNEL); | ||
| 701 | if (!skb) | ||
| 702 | return ERR_PTR(-ENOMEM); | ||
| 703 | |||
| 704 | return skb; | ||
| 699 | } | 705 | } |
| 700 | 706 | ||
| 701 | static struct l2cap_ops a2mp_chan_ops = { | 707 | static struct l2cap_ops a2mp_chan_ops = { |
| @@ -726,7 +732,11 @@ static struct l2cap_chan *a2mp_chan_open(struct l2cap_conn *conn, bool locked) | |||
| 726 | 732 | ||
| 727 | BT_DBG("chan %p", chan); | 733 | BT_DBG("chan %p", chan); |
| 728 | 734 | ||
| 729 | chan->chan_type = L2CAP_CHAN_CONN_FIX_A2MP; | 735 | chan->chan_type = L2CAP_CHAN_FIXED; |
| 736 | chan->scid = L2CAP_CID_A2MP; | ||
| 737 | chan->dcid = L2CAP_CID_A2MP; | ||
| 738 | chan->omtu = L2CAP_A2MP_DEFAULT_MTU; | ||
| 739 | chan->imtu = L2CAP_A2MP_DEFAULT_MTU; | ||
| 730 | chan->flush_to = L2CAP_DEFAULT_FLUSH_TO; | 740 | chan->flush_to = L2CAP_DEFAULT_FLUSH_TO; |
| 731 | 741 | ||
| 732 | chan->ops = &a2mp_chan_ops; | 742 | chan->ops = &a2mp_chan_ops; |
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c index 0c5866bb49b6..2021c481cdb6 100644 --- a/net/bluetooth/af_bluetooth.c +++ b/net/bluetooth/af_bluetooth.c | |||
| @@ -31,7 +31,7 @@ | |||
| 31 | #include <net/bluetooth/bluetooth.h> | 31 | #include <net/bluetooth/bluetooth.h> |
| 32 | #include <linux/proc_fs.h> | 32 | #include <linux/proc_fs.h> |
| 33 | 33 | ||
| 34 | #define VERSION "2.18" | 34 | #define VERSION "2.19" |
| 35 | 35 | ||
| 36 | /* Bluetooth sockets */ | 36 | /* Bluetooth sockets */ |
| 37 | #define BT_MAX_PROTO 8 | 37 | #define BT_MAX_PROTO 8 |
diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index ba5366c320da..d958e2dca52f 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c | |||
| @@ -82,7 +82,7 @@ static void hci_acl_create_connection(struct hci_conn *conn) | |||
| 82 | cp.pscan_rep_mode = ie->data.pscan_rep_mode; | 82 | cp.pscan_rep_mode = ie->data.pscan_rep_mode; |
| 83 | cp.pscan_mode = ie->data.pscan_mode; | 83 | cp.pscan_mode = ie->data.pscan_mode; |
| 84 | cp.clock_offset = ie->data.clock_offset | | 84 | cp.clock_offset = ie->data.clock_offset | |
| 85 | __constant_cpu_to_le16(0x8000); | 85 | cpu_to_le16(0x8000); |
| 86 | } | 86 | } |
| 87 | 87 | ||
| 88 | memcpy(conn->dev_class, ie->data.dev_class, 3); | 88 | memcpy(conn->dev_class, ie->data.dev_class, 3); |
| @@ -182,8 +182,8 @@ bool hci_setup_sync(struct hci_conn *conn, __u16 handle) | |||
| 182 | 182 | ||
| 183 | cp.handle = cpu_to_le16(handle); | 183 | cp.handle = cpu_to_le16(handle); |
| 184 | 184 | ||
| 185 | cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40); | 185 | cp.tx_bandwidth = cpu_to_le32(0x00001f40); |
| 186 | cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40); | 186 | cp.rx_bandwidth = cpu_to_le32(0x00001f40); |
| 187 | cp.voice_setting = cpu_to_le16(conn->setting); | 187 | cp.voice_setting = cpu_to_le16(conn->setting); |
| 188 | 188 | ||
| 189 | switch (conn->setting & SCO_AIRMODE_MASK) { | 189 | switch (conn->setting & SCO_AIRMODE_MASK) { |
| @@ -225,13 +225,13 @@ void hci_le_conn_update(struct hci_conn *conn, u16 min, u16 max, | |||
| 225 | cp.conn_interval_max = cpu_to_le16(max); | 225 | cp.conn_interval_max = cpu_to_le16(max); |
| 226 | cp.conn_latency = cpu_to_le16(latency); | 226 | cp.conn_latency = cpu_to_le16(latency); |
| 227 | cp.supervision_timeout = cpu_to_le16(to_multiplier); | 227 | cp.supervision_timeout = cpu_to_le16(to_multiplier); |
| 228 | cp.min_ce_len = __constant_cpu_to_le16(0x0001); | 228 | cp.min_ce_len = cpu_to_le16(0x0000); |
| 229 | cp.max_ce_len = __constant_cpu_to_le16(0x0001); | 229 | cp.max_ce_len = cpu_to_le16(0x0000); |
| 230 | 230 | ||
| 231 | hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp); | 231 | hci_send_cmd(hdev, HCI_OP_LE_CONN_UPDATE, sizeof(cp), &cp); |
| 232 | } | 232 | } |
| 233 | 233 | ||
| 234 | void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8], | 234 | void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __le64 rand, |
| 235 | __u8 ltk[16]) | 235 | __u8 ltk[16]) |
| 236 | { | 236 | { |
| 237 | struct hci_dev *hdev = conn->hdev; | 237 | struct hci_dev *hdev = conn->hdev; |
| @@ -242,9 +242,9 @@ void hci_le_start_enc(struct hci_conn *conn, __le16 ediv, __u8 rand[8], | |||
| 242 | memset(&cp, 0, sizeof(cp)); | 242 | memset(&cp, 0, sizeof(cp)); |
| 243 | 243 | ||
| 244 | cp.handle = cpu_to_le16(conn->handle); | 244 | cp.handle = cpu_to_le16(conn->handle); |
| 245 | memcpy(cp.ltk, ltk, sizeof(cp.ltk)); | 245 | cp.rand = rand; |
| 246 | cp.ediv = ediv; | 246 | cp.ediv = ediv; |
| 247 | memcpy(cp.rand, rand, sizeof(cp.rand)); | 247 | memcpy(cp.ltk, ltk, sizeof(cp.ltk)); |
| 248 | 248 | ||
| 249 | hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp); | 249 | hci_send_cmd(hdev, HCI_OP_LE_START_ENC, sizeof(cp), &cp); |
| 250 | } | 250 | } |
| @@ -337,9 +337,9 @@ static void hci_conn_idle(struct work_struct *work) | |||
| 337 | if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) { | 337 | if (lmp_sniffsubr_capable(hdev) && lmp_sniffsubr_capable(conn)) { |
| 338 | struct hci_cp_sniff_subrate cp; | 338 | struct hci_cp_sniff_subrate cp; |
| 339 | cp.handle = cpu_to_le16(conn->handle); | 339 | cp.handle = cpu_to_le16(conn->handle); |
| 340 | cp.max_latency = __constant_cpu_to_le16(0); | 340 | cp.max_latency = cpu_to_le16(0); |
| 341 | cp.min_remote_timeout = __constant_cpu_to_le16(0); | 341 | cp.min_remote_timeout = cpu_to_le16(0); |
| 342 | cp.min_local_timeout = __constant_cpu_to_le16(0); | 342 | cp.min_local_timeout = cpu_to_le16(0); |
| 343 | hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp); | 343 | hci_send_cmd(hdev, HCI_OP_SNIFF_SUBRATE, sizeof(cp), &cp); |
| 344 | } | 344 | } |
| 345 | 345 | ||
| @@ -348,8 +348,8 @@ static void hci_conn_idle(struct work_struct *work) | |||
| 348 | cp.handle = cpu_to_le16(conn->handle); | 348 | cp.handle = cpu_to_le16(conn->handle); |
| 349 | cp.max_interval = cpu_to_le16(hdev->sniff_max_interval); | 349 | cp.max_interval = cpu_to_le16(hdev->sniff_max_interval); |
| 350 | cp.min_interval = cpu_to_le16(hdev->sniff_min_interval); | 350 | cp.min_interval = cpu_to_le16(hdev->sniff_min_interval); |
| 351 | cp.attempt = __constant_cpu_to_le16(4); | 351 | cp.attempt = cpu_to_le16(4); |
| 352 | cp.timeout = __constant_cpu_to_le16(1); | 352 | cp.timeout = cpu_to_le16(1); |
| 353 | hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp); | 353 | hci_send_cmd(hdev, HCI_OP_SNIFF_MODE, sizeof(cp), &cp); |
| 354 | } | 354 | } |
| 355 | } | 355 | } |
| @@ -363,6 +363,16 @@ static void hci_conn_auto_accept(struct work_struct *work) | |||
| 363 | &conn->dst); | 363 | &conn->dst); |
| 364 | } | 364 | } |
| 365 | 365 | ||
| 366 | static void le_conn_timeout(struct work_struct *work) | ||
| 367 | { | ||
| 368 | struct hci_conn *conn = container_of(work, struct hci_conn, | ||
| 369 | le_conn_timeout.work); | ||
| 370 | |||
| 371 | BT_DBG(""); | ||
| 372 | |||
| 373 | hci_le_create_connection_cancel(conn); | ||
| 374 | } | ||
| 375 | |||
| 366 | struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) | 376 | struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) |
| 367 | { | 377 | { |
| 368 | struct hci_conn *conn; | 378 | struct hci_conn *conn; |
| @@ -410,6 +420,7 @@ struct hci_conn *hci_conn_add(struct hci_dev *hdev, int type, bdaddr_t *dst) | |||
| 410 | INIT_DELAYED_WORK(&conn->disc_work, hci_conn_timeout); | 420 | INIT_DELAYED_WORK(&conn->disc_work, hci_conn_timeout); |
| 411 | INIT_DELAYED_WORK(&conn->auto_accept_work, hci_conn_auto_accept); | 421 | INIT_DELAYED_WORK(&conn->auto_accept_work, hci_conn_auto_accept); |
| 412 | INIT_DELAYED_WORK(&conn->idle_work, hci_conn_idle); | 422 | INIT_DELAYED_WORK(&conn->idle_work, hci_conn_idle); |
| 423 | INIT_DELAYED_WORK(&conn->le_conn_timeout, le_conn_timeout); | ||
| 413 | 424 | ||
| 414 | atomic_set(&conn->refcnt, 0); | 425 | atomic_set(&conn->refcnt, 0); |
| 415 | 426 | ||
| @@ -442,6 +453,8 @@ int hci_conn_del(struct hci_conn *conn) | |||
| 442 | /* Unacked frames */ | 453 | /* Unacked frames */ |
| 443 | hdev->acl_cnt += conn->sent; | 454 | hdev->acl_cnt += conn->sent; |
| 444 | } else if (conn->type == LE_LINK) { | 455 | } else if (conn->type == LE_LINK) { |
| 456 | cancel_delayed_work_sync(&conn->le_conn_timeout); | ||
| 457 | |||
| 445 | if (hdev->le_pkts) | 458 | if (hdev->le_pkts) |
| 446 | hdev->le_cnt += conn->sent; | 459 | hdev->le_cnt += conn->sent; |
| 447 | else | 460 | else |
| @@ -514,6 +527,26 @@ struct hci_dev *hci_get_route(bdaddr_t *dst, bdaddr_t *src) | |||
| 514 | } | 527 | } |
| 515 | EXPORT_SYMBOL(hci_get_route); | 528 | EXPORT_SYMBOL(hci_get_route); |
| 516 | 529 | ||
| 530 | /* This function requires the caller holds hdev->lock */ | ||
| 531 | void hci_le_conn_failed(struct hci_conn *conn, u8 status) | ||
| 532 | { | ||
| 533 | struct hci_dev *hdev = conn->hdev; | ||
| 534 | |||
| 535 | conn->state = BT_CLOSED; | ||
| 536 | |||
| 537 | mgmt_connect_failed(hdev, &conn->dst, conn->type, conn->dst_type, | ||
| 538 | status); | ||
| 539 | |||
| 540 | hci_proto_connect_cfm(conn, status); | ||
| 541 | |||
| 542 | hci_conn_del(conn); | ||
| 543 | |||
| 544 | /* Since we may have temporarily stopped the background scanning in | ||
| 545 | * favor of connection establishment, we should restart it. | ||
| 546 | */ | ||
| 547 | hci_update_background_scan(hdev); | ||
| 548 | } | ||
| 549 | |||
| 517 | static void create_le_conn_complete(struct hci_dev *hdev, u8 status) | 550 | static void create_le_conn_complete(struct hci_dev *hdev, u8 status) |
| 518 | { | 551 | { |
| 519 | struct hci_conn *conn; | 552 | struct hci_conn *conn; |
| @@ -530,55 +563,55 @@ static void create_le_conn_complete(struct hci_dev *hdev, u8 status) | |||
| 530 | if (!conn) | 563 | if (!conn) |
| 531 | goto done; | 564 | goto done; |
| 532 | 565 | ||
| 533 | conn->state = BT_CLOSED; | 566 | hci_le_conn_failed(conn, status); |
| 534 | |||
| 535 | mgmt_connect_failed(hdev, &conn->dst, conn->type, conn->dst_type, | ||
| 536 | status); | ||
| 537 | |||
| 538 | hci_proto_connect_cfm(conn, status); | ||
| 539 | |||
| 540 | hci_conn_del(conn); | ||
| 541 | 567 | ||
| 542 | done: | 568 | done: |
| 543 | hci_dev_unlock(hdev); | 569 | hci_dev_unlock(hdev); |
| 544 | } | 570 | } |
| 545 | 571 | ||
| 546 | static int hci_create_le_conn(struct hci_conn *conn) | 572 | static void hci_req_add_le_create_conn(struct hci_request *req, |
| 573 | struct hci_conn *conn) | ||
| 547 | { | 574 | { |
| 548 | struct hci_dev *hdev = conn->hdev; | ||
| 549 | struct hci_cp_le_create_conn cp; | 575 | struct hci_cp_le_create_conn cp; |
| 550 | struct hci_request req; | 576 | struct hci_dev *hdev = conn->hdev; |
| 551 | int err; | 577 | u8 own_addr_type; |
| 552 | |||
| 553 | hci_req_init(&req, hdev); | ||
| 554 | 578 | ||
| 555 | memset(&cp, 0, sizeof(cp)); | 579 | memset(&cp, 0, sizeof(cp)); |
| 580 | |||
| 581 | /* Update random address, but set require_privacy to false so | ||
| 582 | * that we never connect with an unresolvable address. | ||
| 583 | */ | ||
| 584 | if (hci_update_random_address(req, false, &own_addr_type)) | ||
| 585 | return; | ||
| 586 | |||
| 587 | /* Save the address type used for this connnection attempt so we able | ||
| 588 | * to retrieve this information if we need it. | ||
| 589 | */ | ||
| 590 | conn->src_type = own_addr_type; | ||
| 591 | |||
| 556 | cp.scan_interval = cpu_to_le16(hdev->le_scan_interval); | 592 | cp.scan_interval = cpu_to_le16(hdev->le_scan_interval); |
| 557 | cp.scan_window = cpu_to_le16(hdev->le_scan_window); | 593 | cp.scan_window = cpu_to_le16(hdev->le_scan_window); |
| 558 | bacpy(&cp.peer_addr, &conn->dst); | 594 | bacpy(&cp.peer_addr, &conn->dst); |
| 559 | cp.peer_addr_type = conn->dst_type; | 595 | cp.peer_addr_type = conn->dst_type; |
| 560 | cp.own_address_type = conn->src_type; | 596 | cp.own_address_type = own_addr_type; |
| 561 | cp.conn_interval_min = cpu_to_le16(hdev->le_conn_min_interval); | 597 | cp.conn_interval_min = cpu_to_le16(conn->le_conn_min_interval); |
| 562 | cp.conn_interval_max = cpu_to_le16(hdev->le_conn_max_interval); | 598 | cp.conn_interval_max = cpu_to_le16(conn->le_conn_max_interval); |
| 563 | cp.supervision_timeout = __constant_cpu_to_le16(0x002a); | 599 | cp.supervision_timeout = cpu_to_le16(0x002a); |
| 564 | cp.min_ce_len = __constant_cpu_to_le16(0x0000); | 600 | cp.min_ce_len = cpu_to_le16(0x0000); |
| 565 | cp.max_ce_len = __constant_cpu_to_le16(0x0000); | 601 | cp.max_ce_len = cpu_to_le16(0x0000); |
| 566 | 602 | ||
| 567 | hci_req_add(&req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp); | 603 | hci_req_add(req, HCI_OP_LE_CREATE_CONN, sizeof(cp), &cp); |
| 568 | 604 | ||
| 569 | err = hci_req_run(&req, create_le_conn_complete); | 605 | conn->state = BT_CONNECT; |
| 570 | if (err) { | ||
| 571 | hci_conn_del(conn); | ||
| 572 | return err; | ||
| 573 | } | ||
| 574 | |||
| 575 | return 0; | ||
| 576 | } | 606 | } |
| 577 | 607 | ||
| 578 | static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, | 608 | struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, |
| 579 | u8 dst_type, u8 sec_level, u8 auth_type) | 609 | u8 dst_type, u8 sec_level, u8 auth_type) |
| 580 | { | 610 | { |
| 611 | struct hci_conn_params *params; | ||
| 581 | struct hci_conn *conn; | 612 | struct hci_conn *conn; |
| 613 | struct smp_irk *irk; | ||
| 614 | struct hci_request req; | ||
| 582 | int err; | 615 | int err; |
| 583 | 616 | ||
| 584 | if (test_bit(HCI_ADVERTISING, &hdev->flags)) | 617 | if (test_bit(HCI_ADVERTISING, &hdev->flags)) |
| @@ -607,35 +640,74 @@ static struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, | |||
| 607 | if (conn) | 640 | if (conn) |
| 608 | return ERR_PTR(-EBUSY); | 641 | return ERR_PTR(-EBUSY); |
| 609 | 642 | ||
| 643 | /* When given an identity address with existing identity | ||
| 644 | * resolving key, the connection needs to be established | ||
| 645 | * to a resolvable random address. | ||
| 646 | * | ||
| 647 | * This uses the cached random resolvable address from | ||
| 648 | * a previous scan. When no cached address is available, | ||
| 649 | * try connecting to the identity address instead. | ||
| 650 | * | ||
| 651 | * Storing the resolvable random address is required here | ||
| 652 | * to handle connection failures. The address will later | ||
| 653 | * be resolved back into the original identity address | ||
| 654 | * from the connect request. | ||
| 655 | */ | ||
| 656 | irk = hci_find_irk_by_addr(hdev, dst, dst_type); | ||
| 657 | if (irk && bacmp(&irk->rpa, BDADDR_ANY)) { | ||
| 658 | dst = &irk->rpa; | ||
| 659 | dst_type = ADDR_LE_DEV_RANDOM; | ||
| 660 | } | ||
| 661 | |||
| 610 | conn = hci_conn_add(hdev, LE_LINK, dst); | 662 | conn = hci_conn_add(hdev, LE_LINK, dst); |
| 611 | if (!conn) | 663 | if (!conn) |
| 612 | return ERR_PTR(-ENOMEM); | 664 | return ERR_PTR(-ENOMEM); |
| 613 | 665 | ||
| 614 | if (dst_type == BDADDR_LE_PUBLIC) | 666 | conn->dst_type = dst_type; |
| 615 | conn->dst_type = ADDR_LE_DEV_PUBLIC; | ||
| 616 | else | ||
| 617 | conn->dst_type = ADDR_LE_DEV_RANDOM; | ||
| 618 | |||
| 619 | conn->src_type = hdev->own_addr_type; | ||
| 620 | 667 | ||
| 621 | conn->state = BT_CONNECT; | ||
| 622 | conn->out = true; | 668 | conn->out = true; |
| 623 | conn->link_mode |= HCI_LM_MASTER; | 669 | conn->link_mode |= HCI_LM_MASTER; |
| 624 | conn->sec_level = BT_SECURITY_LOW; | 670 | conn->sec_level = BT_SECURITY_LOW; |
| 625 | conn->pending_sec_level = sec_level; | 671 | conn->pending_sec_level = sec_level; |
| 626 | conn->auth_type = auth_type; | 672 | conn->auth_type = auth_type; |
| 627 | 673 | ||
| 628 | err = hci_create_le_conn(conn); | 674 | params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type); |
| 629 | if (err) | 675 | if (params) { |
| 676 | conn->le_conn_min_interval = params->conn_min_interval; | ||
| 677 | conn->le_conn_max_interval = params->conn_max_interval; | ||
| 678 | } else { | ||
| 679 | conn->le_conn_min_interval = hdev->le_conn_min_interval; | ||
| 680 | conn->le_conn_max_interval = hdev->le_conn_max_interval; | ||
| 681 | } | ||
| 682 | |||
| 683 | hci_req_init(&req, hdev); | ||
| 684 | |||
| 685 | /* If controller is scanning, we stop it since some controllers are | ||
| 686 | * not able to scan and connect at the same time. Also set the | ||
| 687 | * HCI_LE_SCAN_INTERRUPTED flag so that the command complete | ||
| 688 | * handler for scan disabling knows to set the correct discovery | ||
| 689 | * state. | ||
| 690 | */ | ||
| 691 | if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) { | ||
| 692 | hci_req_add_le_scan_disable(&req); | ||
| 693 | set_bit(HCI_LE_SCAN_INTERRUPTED, &hdev->dev_flags); | ||
| 694 | } | ||
| 695 | |||
| 696 | hci_req_add_le_create_conn(&req, conn); | ||
| 697 | |||
| 698 | err = hci_req_run(&req, create_le_conn_complete); | ||
| 699 | if (err) { | ||
| 700 | hci_conn_del(conn); | ||
| 630 | return ERR_PTR(err); | 701 | return ERR_PTR(err); |
| 702 | } | ||
| 631 | 703 | ||
| 632 | done: | 704 | done: |
| 633 | hci_conn_hold(conn); | 705 | hci_conn_hold(conn); |
| 634 | return conn; | 706 | return conn; |
| 635 | } | 707 | } |
| 636 | 708 | ||
| 637 | static struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, | 709 | struct hci_conn *hci_connect_acl(struct hci_dev *hdev, bdaddr_t *dst, |
| 638 | u8 sec_level, u8 auth_type) | 710 | u8 sec_level, u8 auth_type) |
| 639 | { | 711 | { |
| 640 | struct hci_conn *acl; | 712 | struct hci_conn *acl; |
| 641 | 713 | ||
| @@ -704,27 +776,22 @@ struct hci_conn *hci_connect_sco(struct hci_dev *hdev, int type, bdaddr_t *dst, | |||
| 704 | return sco; | 776 | return sco; |
| 705 | } | 777 | } |
| 706 | 778 | ||
| 707 | /* Create SCO, ACL or LE connection. */ | ||
| 708 | struct hci_conn *hci_connect(struct hci_dev *hdev, int type, bdaddr_t *dst, | ||
| 709 | __u8 dst_type, __u8 sec_level, __u8 auth_type) | ||
| 710 | { | ||
| 711 | BT_DBG("%s dst %pMR type 0x%x", hdev->name, dst, type); | ||
| 712 | |||
| 713 | switch (type) { | ||
| 714 | case LE_LINK: | ||
| 715 | return hci_connect_le(hdev, dst, dst_type, sec_level, auth_type); | ||
| 716 | case ACL_LINK: | ||
| 717 | return hci_connect_acl(hdev, dst, sec_level, auth_type); | ||
| 718 | } | ||
| 719 | |||
| 720 | return ERR_PTR(-EINVAL); | ||
| 721 | } | ||
| 722 | |||
| 723 | /* Check link security requirement */ | 779 | /* Check link security requirement */ |
| 724 | int hci_conn_check_link_mode(struct hci_conn *conn) | 780 | int hci_conn_check_link_mode(struct hci_conn *conn) |
| 725 | { | 781 | { |
| 726 | BT_DBG("hcon %p", conn); | 782 | BT_DBG("hcon %p", conn); |
| 727 | 783 | ||
| 784 | /* In Secure Connections Only mode, it is required that Secure | ||
| 785 | * Connections is used and the link is encrypted with AES-CCM | ||
| 786 | * using a P-256 authenticated combination key. | ||
| 787 | */ | ||
| 788 | if (test_bit(HCI_SC_ONLY, &conn->hdev->flags)) { | ||
| 789 | if (!hci_conn_sc_enabled(conn) || | ||
| 790 | !test_bit(HCI_CONN_AES_CCM, &conn->flags) || | ||
| 791 | conn->key_type != HCI_LK_AUTH_COMBINATION_P256) | ||
| 792 | return 0; | ||
| 793 | } | ||
| 794 | |||
| 728 | if (hci_conn_ssp_enabled(conn) && !(conn->link_mode & HCI_LM_ENCRYPT)) | 795 | if (hci_conn_ssp_enabled(conn) && !(conn->link_mode & HCI_LM_ENCRYPT)) |
| 729 | return 0; | 796 | return 0; |
| 730 | 797 | ||
| @@ -800,14 +867,23 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) | |||
| 800 | if (!(conn->link_mode & HCI_LM_AUTH)) | 867 | if (!(conn->link_mode & HCI_LM_AUTH)) |
| 801 | goto auth; | 868 | goto auth; |
| 802 | 869 | ||
| 803 | /* An authenticated combination key has sufficient security for any | 870 | /* An authenticated FIPS approved combination key has sufficient |
| 804 | security level. */ | 871 | * security for security level 4. */ |
| 805 | if (conn->key_type == HCI_LK_AUTH_COMBINATION) | 872 | if (conn->key_type == HCI_LK_AUTH_COMBINATION_P256 && |
| 873 | sec_level == BT_SECURITY_FIPS) | ||
| 874 | goto encrypt; | ||
| 875 | |||
| 876 | /* An authenticated combination key has sufficient security for | ||
| 877 | security level 3. */ | ||
| 878 | if ((conn->key_type == HCI_LK_AUTH_COMBINATION_P192 || | ||
| 879 | conn->key_type == HCI_LK_AUTH_COMBINATION_P256) && | ||
| 880 | sec_level == BT_SECURITY_HIGH) | ||
| 806 | goto encrypt; | 881 | goto encrypt; |
| 807 | 882 | ||
| 808 | /* An unauthenticated combination key has sufficient security for | 883 | /* An unauthenticated combination key has sufficient security for |
| 809 | security level 1 and 2. */ | 884 | security level 1 and 2. */ |
| 810 | if (conn->key_type == HCI_LK_UNAUTH_COMBINATION && | 885 | if ((conn->key_type == HCI_LK_UNAUTH_COMBINATION_P192 || |
| 886 | conn->key_type == HCI_LK_UNAUTH_COMBINATION_P256) && | ||
| 811 | (sec_level == BT_SECURITY_MEDIUM || sec_level == BT_SECURITY_LOW)) | 887 | (sec_level == BT_SECURITY_MEDIUM || sec_level == BT_SECURITY_LOW)) |
| 812 | goto encrypt; | 888 | goto encrypt; |
| 813 | 889 | ||
| @@ -816,7 +892,8 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type) | |||
| 816 | is generated using maximum PIN code length (16). | 892 | is generated using maximum PIN code length (16). |
| 817 | For pre 2.1 units. */ | 893 | For pre 2.1 units. */ |
| 818 | if (conn->key_type == HCI_LK_COMBINATION && | 894 | if (conn->key_type == HCI_LK_COMBINATION && |
| 819 | (sec_level != BT_SECURITY_HIGH || conn->pin_length == 16)) | 895 | (sec_level == BT_SECURITY_MEDIUM || sec_level == BT_SECURITY_LOW || |
| 896 | conn->pin_length == 16)) | ||
| 820 | goto encrypt; | 897 | goto encrypt; |
| 821 | 898 | ||
| 822 | auth: | 899 | auth: |
| @@ -840,13 +917,17 @@ int hci_conn_check_secure(struct hci_conn *conn, __u8 sec_level) | |||
| 840 | { | 917 | { |
| 841 | BT_DBG("hcon %p", conn); | 918 | BT_DBG("hcon %p", conn); |
| 842 | 919 | ||
| 843 | if (sec_level != BT_SECURITY_HIGH) | 920 | /* Accept if non-secure or higher security level is required */ |
| 844 | return 1; /* Accept if non-secure is required */ | 921 | if (sec_level != BT_SECURITY_HIGH && sec_level != BT_SECURITY_FIPS) |
| 922 | return 1; | ||
| 845 | 923 | ||
| 846 | if (conn->sec_level == BT_SECURITY_HIGH) | 924 | /* Accept if secure or higher security level is already present */ |
| 925 | if (conn->sec_level == BT_SECURITY_HIGH || | ||
| 926 | conn->sec_level == BT_SECURITY_FIPS) | ||
| 847 | return 1; | 927 | return 1; |
| 848 | 928 | ||
| 849 | return 0; /* Reject not secure link */ | 929 | /* Reject not secure link */ |
| 930 | return 0; | ||
| 850 | } | 931 | } |
| 851 | EXPORT_SYMBOL(hci_conn_check_secure); | 932 | EXPORT_SYMBOL(hci_conn_check_secure); |
| 852 | 933 | ||
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 5e8663c194c1..1c6ffaa8902f 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c | |||
| @@ -29,11 +29,14 @@ | |||
| 29 | #include <linux/idr.h> | 29 | #include <linux/idr.h> |
| 30 | #include <linux/rfkill.h> | 30 | #include <linux/rfkill.h> |
| 31 | #include <linux/debugfs.h> | 31 | #include <linux/debugfs.h> |
| 32 | #include <linux/crypto.h> | ||
| 32 | #include <asm/unaligned.h> | 33 | #include <asm/unaligned.h> |
| 33 | 34 | ||
| 34 | #include <net/bluetooth/bluetooth.h> | 35 | #include <net/bluetooth/bluetooth.h> |
| 35 | #include <net/bluetooth/hci_core.h> | 36 | #include <net/bluetooth/hci_core.h> |
| 36 | 37 | ||
| 38 | #include "smp.h" | ||
| 39 | |||
| 37 | static void hci_rx_work(struct work_struct *work); | 40 | static void hci_rx_work(struct work_struct *work); |
| 38 | static void hci_cmd_work(struct work_struct *work); | 41 | static void hci_cmd_work(struct work_struct *work); |
| 39 | static void hci_tx_work(struct work_struct *work); | 42 | static void hci_tx_work(struct work_struct *work); |
| @@ -285,24 +288,6 @@ static const struct file_operations link_keys_fops = { | |||
| 285 | .release = single_release, | 288 | .release = single_release, |
| 286 | }; | 289 | }; |
| 287 | 290 | ||
| 288 | static ssize_t use_debug_keys_read(struct file *file, char __user *user_buf, | ||
| 289 | size_t count, loff_t *ppos) | ||
| 290 | { | ||
| 291 | struct hci_dev *hdev = file->private_data; | ||
| 292 | char buf[3]; | ||
| 293 | |||
| 294 | buf[0] = test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags) ? 'Y': 'N'; | ||
| 295 | buf[1] = '\n'; | ||
| 296 | buf[2] = '\0'; | ||
| 297 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); | ||
| 298 | } | ||
| 299 | |||
| 300 | static const struct file_operations use_debug_keys_fops = { | ||
| 301 | .open = simple_open, | ||
| 302 | .read = use_debug_keys_read, | ||
| 303 | .llseek = default_llseek, | ||
| 304 | }; | ||
| 305 | |||
| 306 | static int dev_class_show(struct seq_file *f, void *ptr) | 291 | static int dev_class_show(struct seq_file *f, void *ptr) |
| 307 | { | 292 | { |
| 308 | struct hci_dev *hdev = f->private; | 293 | struct hci_dev *hdev = f->private; |
| @@ -415,6 +400,70 @@ static int ssp_debug_mode_get(void *data, u64 *val) | |||
| 415 | DEFINE_SIMPLE_ATTRIBUTE(ssp_debug_mode_fops, ssp_debug_mode_get, | 400 | DEFINE_SIMPLE_ATTRIBUTE(ssp_debug_mode_fops, ssp_debug_mode_get, |
| 416 | ssp_debug_mode_set, "%llu\n"); | 401 | ssp_debug_mode_set, "%llu\n"); |
| 417 | 402 | ||
| 403 | static ssize_t force_sc_support_read(struct file *file, char __user *user_buf, | ||
| 404 | size_t count, loff_t *ppos) | ||
| 405 | { | ||
| 406 | struct hci_dev *hdev = file->private_data; | ||
| 407 | char buf[3]; | ||
| 408 | |||
| 409 | buf[0] = test_bit(HCI_FORCE_SC, &hdev->dev_flags) ? 'Y': 'N'; | ||
| 410 | buf[1] = '\n'; | ||
| 411 | buf[2] = '\0'; | ||
| 412 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); | ||
| 413 | } | ||
| 414 | |||
| 415 | static ssize_t force_sc_support_write(struct file *file, | ||
| 416 | const char __user *user_buf, | ||
| 417 | size_t count, loff_t *ppos) | ||
| 418 | { | ||
| 419 | struct hci_dev *hdev = file->private_data; | ||
| 420 | char buf[32]; | ||
| 421 | size_t buf_size = min(count, (sizeof(buf)-1)); | ||
| 422 | bool enable; | ||
| 423 | |||
| 424 | if (test_bit(HCI_UP, &hdev->flags)) | ||
| 425 | return -EBUSY; | ||
| 426 | |||
| 427 | if (copy_from_user(buf, user_buf, buf_size)) | ||
| 428 | return -EFAULT; | ||
| 429 | |||
| 430 | buf[buf_size] = '\0'; | ||
| 431 | if (strtobool(buf, &enable)) | ||
| 432 | return -EINVAL; | ||
| 433 | |||
| 434 | if (enable == test_bit(HCI_FORCE_SC, &hdev->dev_flags)) | ||
| 435 | return -EALREADY; | ||
| 436 | |||
| 437 | change_bit(HCI_FORCE_SC, &hdev->dev_flags); | ||
| 438 | |||
| 439 | return count; | ||
| 440 | } | ||
| 441 | |||
| 442 | static const struct file_operations force_sc_support_fops = { | ||
| 443 | .open = simple_open, | ||
| 444 | .read = force_sc_support_read, | ||
| 445 | .write = force_sc_support_write, | ||
| 446 | .llseek = default_llseek, | ||
| 447 | }; | ||
| 448 | |||
| 449 | static ssize_t sc_only_mode_read(struct file *file, char __user *user_buf, | ||
| 450 | size_t count, loff_t *ppos) | ||
| 451 | { | ||
| 452 | struct hci_dev *hdev = file->private_data; | ||
| 453 | char buf[3]; | ||
| 454 | |||
| 455 | buf[0] = test_bit(HCI_SC_ONLY, &hdev->dev_flags) ? 'Y': 'N'; | ||
| 456 | buf[1] = '\n'; | ||
| 457 | buf[2] = '\0'; | ||
| 458 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); | ||
| 459 | } | ||
| 460 | |||
| 461 | static const struct file_operations sc_only_mode_fops = { | ||
| 462 | .open = simple_open, | ||
| 463 | .read = sc_only_mode_read, | ||
| 464 | .llseek = default_llseek, | ||
| 465 | }; | ||
| 466 | |||
| 418 | static int idle_timeout_set(void *data, u64 val) | 467 | static int idle_timeout_set(void *data, u64 val) |
| 419 | { | 468 | { |
| 420 | struct hci_dev *hdev = data; | 469 | struct hci_dev *hdev = data; |
| @@ -443,6 +492,37 @@ static int idle_timeout_get(void *data, u64 *val) | |||
| 443 | DEFINE_SIMPLE_ATTRIBUTE(idle_timeout_fops, idle_timeout_get, | 492 | DEFINE_SIMPLE_ATTRIBUTE(idle_timeout_fops, idle_timeout_get, |
| 444 | idle_timeout_set, "%llu\n"); | 493 | idle_timeout_set, "%llu\n"); |
| 445 | 494 | ||
| 495 | static int rpa_timeout_set(void *data, u64 val) | ||
| 496 | { | ||
| 497 | struct hci_dev *hdev = data; | ||
| 498 | |||
| 499 | /* Require the RPA timeout to be at least 30 seconds and at most | ||
| 500 | * 24 hours. | ||
| 501 | */ | ||
| 502 | if (val < 30 || val > (60 * 60 * 24)) | ||
| 503 | return -EINVAL; | ||
| 504 | |||
| 505 | hci_dev_lock(hdev); | ||
| 506 | hdev->rpa_timeout = val; | ||
| 507 | hci_dev_unlock(hdev); | ||
| 508 | |||
| 509 | return 0; | ||
| 510 | } | ||
| 511 | |||
| 512 | static int rpa_timeout_get(void *data, u64 *val) | ||
| 513 | { | ||
| 514 | struct hci_dev *hdev = data; | ||
| 515 | |||
| 516 | hci_dev_lock(hdev); | ||
| 517 | *val = hdev->rpa_timeout; | ||
| 518 | hci_dev_unlock(hdev); | ||
| 519 | |||
| 520 | return 0; | ||
| 521 | } | ||
| 522 | |||
| 523 | DEFINE_SIMPLE_ATTRIBUTE(rpa_timeout_fops, rpa_timeout_get, | ||
| 524 | rpa_timeout_set, "%llu\n"); | ||
| 525 | |||
| 446 | static int sniff_min_interval_set(void *data, u64 val) | 526 | static int sniff_min_interval_set(void *data, u64 val) |
| 447 | { | 527 | { |
| 448 | struct hci_dev *hdev = data; | 528 | struct hci_dev *hdev = data; |
| @@ -499,6 +579,59 @@ static int sniff_max_interval_get(void *data, u64 *val) | |||
| 499 | DEFINE_SIMPLE_ATTRIBUTE(sniff_max_interval_fops, sniff_max_interval_get, | 579 | DEFINE_SIMPLE_ATTRIBUTE(sniff_max_interval_fops, sniff_max_interval_get, |
| 500 | sniff_max_interval_set, "%llu\n"); | 580 | sniff_max_interval_set, "%llu\n"); |
| 501 | 581 | ||
| 582 | static int identity_show(struct seq_file *f, void *p) | ||
| 583 | { | ||
| 584 | struct hci_dev *hdev = f->private; | ||
| 585 | bdaddr_t addr; | ||
| 586 | u8 addr_type; | ||
| 587 | |||
| 588 | hci_dev_lock(hdev); | ||
| 589 | |||
| 590 | hci_copy_identity_address(hdev, &addr, &addr_type); | ||
| 591 | |||
| 592 | seq_printf(f, "%pMR (type %u) %*phN %pMR\n", &addr, addr_type, | ||
| 593 | 16, hdev->irk, &hdev->rpa); | ||
| 594 | |||
| 595 | hci_dev_unlock(hdev); | ||
| 596 | |||
| 597 | return 0; | ||
| 598 | } | ||
| 599 | |||
| 600 | static int identity_open(struct inode *inode, struct file *file) | ||
| 601 | { | ||
| 602 | return single_open(file, identity_show, inode->i_private); | ||
| 603 | } | ||
| 604 | |||
| 605 | static const struct file_operations identity_fops = { | ||
| 606 | .open = identity_open, | ||
| 607 | .read = seq_read, | ||
| 608 | .llseek = seq_lseek, | ||
| 609 | .release = single_release, | ||
| 610 | }; | ||
| 611 | |||
| 612 | static int random_address_show(struct seq_file *f, void *p) | ||
| 613 | { | ||
| 614 | struct hci_dev *hdev = f->private; | ||
| 615 | |||
| 616 | hci_dev_lock(hdev); | ||
| 617 | seq_printf(f, "%pMR\n", &hdev->random_addr); | ||
| 618 | hci_dev_unlock(hdev); | ||
| 619 | |||
| 620 | return 0; | ||
| 621 | } | ||
| 622 | |||
| 623 | static int random_address_open(struct inode *inode, struct file *file) | ||
| 624 | { | ||
| 625 | return single_open(file, random_address_show, inode->i_private); | ||
| 626 | } | ||
| 627 | |||
| 628 | static const struct file_operations random_address_fops = { | ||
| 629 | .open = random_address_open, | ||
| 630 | .read = seq_read, | ||
| 631 | .llseek = seq_lseek, | ||
| 632 | .release = single_release, | ||
| 633 | }; | ||
| 634 | |||
| 502 | static int static_address_show(struct seq_file *f, void *p) | 635 | static int static_address_show(struct seq_file *f, void *p) |
| 503 | { | 636 | { |
| 504 | struct hci_dev *hdev = f->private; | 637 | struct hci_dev *hdev = f->private; |
| @@ -522,33 +655,107 @@ static const struct file_operations static_address_fops = { | |||
| 522 | .release = single_release, | 655 | .release = single_release, |
| 523 | }; | 656 | }; |
| 524 | 657 | ||
| 525 | static int own_address_type_set(void *data, u64 val) | 658 | static ssize_t force_static_address_read(struct file *file, |
| 659 | char __user *user_buf, | ||
| 660 | size_t count, loff_t *ppos) | ||
| 526 | { | 661 | { |
| 527 | struct hci_dev *hdev = data; | 662 | struct hci_dev *hdev = file->private_data; |
| 663 | char buf[3]; | ||
| 528 | 664 | ||
| 529 | if (val != 0 && val != 1) | 665 | buf[0] = test_bit(HCI_FORCE_STATIC_ADDR, &hdev->dev_flags) ? 'Y': 'N'; |
| 666 | buf[1] = '\n'; | ||
| 667 | buf[2] = '\0'; | ||
| 668 | return simple_read_from_buffer(user_buf, count, ppos, buf, 2); | ||
| 669 | } | ||
| 670 | |||
| 671 | static ssize_t force_static_address_write(struct file *file, | ||
| 672 | const char __user *user_buf, | ||
| 673 | size_t count, loff_t *ppos) | ||
| 674 | { | ||
| 675 | struct hci_dev *hdev = file->private_data; | ||
| 676 | char buf[32]; | ||
| 677 | size_t buf_size = min(count, (sizeof(buf)-1)); | ||
| 678 | bool enable; | ||
| 679 | |||
| 680 | if (test_bit(HCI_UP, &hdev->flags)) | ||
| 681 | return -EBUSY; | ||
| 682 | |||
| 683 | if (copy_from_user(buf, user_buf, buf_size)) | ||
| 684 | return -EFAULT; | ||
| 685 | |||
| 686 | buf[buf_size] = '\0'; | ||
| 687 | if (strtobool(buf, &enable)) | ||
| 530 | return -EINVAL; | 688 | return -EINVAL; |
| 531 | 689 | ||
| 690 | if (enable == test_bit(HCI_FORCE_STATIC_ADDR, &hdev->dev_flags)) | ||
| 691 | return -EALREADY; | ||
| 692 | |||
| 693 | change_bit(HCI_FORCE_STATIC_ADDR, &hdev->dev_flags); | ||
| 694 | |||
| 695 | return count; | ||
| 696 | } | ||
| 697 | |||
| 698 | static const struct file_operations force_static_address_fops = { | ||
| 699 | .open = simple_open, | ||
| 700 | .read = force_static_address_read, | ||
| 701 | .write = force_static_address_write, | ||
| 702 | .llseek = default_llseek, | ||
| 703 | }; | ||
| 704 | |||
| 705 | static int white_list_show(struct seq_file *f, void *ptr) | ||
| 706 | { | ||
| 707 | struct hci_dev *hdev = f->private; | ||
| 708 | struct bdaddr_list *b; | ||
| 709 | |||
| 532 | hci_dev_lock(hdev); | 710 | hci_dev_lock(hdev); |
| 533 | hdev->own_addr_type = val; | 711 | list_for_each_entry(b, &hdev->le_white_list, list) |
| 712 | seq_printf(f, "%pMR (type %u)\n", &b->bdaddr, b->bdaddr_type); | ||
| 534 | hci_dev_unlock(hdev); | 713 | hci_dev_unlock(hdev); |
| 535 | 714 | ||
| 536 | return 0; | 715 | return 0; |
| 537 | } | 716 | } |
| 538 | 717 | ||
| 539 | static int own_address_type_get(void *data, u64 *val) | 718 | static int white_list_open(struct inode *inode, struct file *file) |
| 540 | { | 719 | { |
| 541 | struct hci_dev *hdev = data; | 720 | return single_open(file, white_list_show, inode->i_private); |
| 721 | } | ||
| 722 | |||
| 723 | static const struct file_operations white_list_fops = { | ||
| 724 | .open = white_list_open, | ||
| 725 | .read = seq_read, | ||
| 726 | .llseek = seq_lseek, | ||
| 727 | .release = single_release, | ||
| 728 | }; | ||
| 729 | |||
| 730 | static int identity_resolving_keys_show(struct seq_file *f, void *ptr) | ||
| 731 | { | ||
| 732 | struct hci_dev *hdev = f->private; | ||
| 733 | struct list_head *p, *n; | ||
| 542 | 734 | ||
| 543 | hci_dev_lock(hdev); | 735 | hci_dev_lock(hdev); |
| 544 | *val = hdev->own_addr_type; | 736 | list_for_each_safe(p, n, &hdev->identity_resolving_keys) { |
| 737 | struct smp_irk *irk = list_entry(p, struct smp_irk, list); | ||
| 738 | seq_printf(f, "%pMR (type %u) %*phN %pMR\n", | ||
| 739 | &irk->bdaddr, irk->addr_type, | ||
| 740 | 16, irk->val, &irk->rpa); | ||
| 741 | } | ||
| 545 | hci_dev_unlock(hdev); | 742 | hci_dev_unlock(hdev); |
| 546 | 743 | ||
| 547 | return 0; | 744 | return 0; |
| 548 | } | 745 | } |
| 549 | 746 | ||
| 550 | DEFINE_SIMPLE_ATTRIBUTE(own_address_type_fops, own_address_type_get, | 747 | static int identity_resolving_keys_open(struct inode *inode, struct file *file) |
| 551 | own_address_type_set, "%llu\n"); | 748 | { |
| 749 | return single_open(file, identity_resolving_keys_show, | ||
| 750 | inode->i_private); | ||
| 751 | } | ||
| 752 | |||
| 753 | static const struct file_operations identity_resolving_keys_fops = { | ||
| 754 | .open = identity_resolving_keys_open, | ||
| 755 | .read = seq_read, | ||
| 756 | .llseek = seq_lseek, | ||
| 757 | .release = single_release, | ||
| 758 | }; | ||
| 552 | 759 | ||
| 553 | static int long_term_keys_show(struct seq_file *f, void *ptr) | 760 | static int long_term_keys_show(struct seq_file *f, void *ptr) |
| 554 | { | 761 | { |
| @@ -556,12 +763,12 @@ static int long_term_keys_show(struct seq_file *f, void *ptr) | |||
| 556 | struct list_head *p, *n; | 763 | struct list_head *p, *n; |
| 557 | 764 | ||
| 558 | hci_dev_lock(hdev); | 765 | hci_dev_lock(hdev); |
| 559 | list_for_each_safe(p, n, &hdev->link_keys) { | 766 | list_for_each_safe(p, n, &hdev->long_term_keys) { |
| 560 | struct smp_ltk *ltk = list_entry(p, struct smp_ltk, list); | 767 | struct smp_ltk *ltk = list_entry(p, struct smp_ltk, list); |
| 561 | seq_printf(f, "%pMR (type %u) %u %u %u %.4x %*phN %*phN\\n", | 768 | seq_printf(f, "%pMR (type %u) %u 0x%02x %u %.4x %.16llx %*phN\n", |
| 562 | <k->bdaddr, ltk->bdaddr_type, ltk->authenticated, | 769 | <k->bdaddr, ltk->bdaddr_type, ltk->authenticated, |
| 563 | ltk->type, ltk->enc_size, __le16_to_cpu(ltk->ediv), | 770 | ltk->type, ltk->enc_size, __le16_to_cpu(ltk->ediv), |
| 564 | 8, ltk->rand, 16, ltk->val); | 771 | __le64_to_cpu(ltk->rand), 16, ltk->val); |
| 565 | } | 772 | } |
| 566 | hci_dev_unlock(hdev); | 773 | hci_dev_unlock(hdev); |
| 567 | 774 | ||
| @@ -636,6 +843,34 @@ static int conn_max_interval_get(void *data, u64 *val) | |||
| 636 | DEFINE_SIMPLE_ATTRIBUTE(conn_max_interval_fops, conn_max_interval_get, | 843 | DEFINE_SIMPLE_ATTRIBUTE(conn_max_interval_fops, conn_max_interval_get, |
| 637 | conn_max_interval_set, "%llu\n"); | 844 | conn_max_interval_set, "%llu\n"); |
| 638 | 845 | ||
| 846 | static int adv_channel_map_set(void *data, u64 val) | ||
| 847 | { | ||
| 848 | struct hci_dev *hdev = data; | ||
| 849 | |||
| 850 | if (val < 0x01 || val > 0x07) | ||
| 851 | return -EINVAL; | ||
| 852 | |||
| 853 | hci_dev_lock(hdev); | ||
| 854 | hdev->le_adv_channel_map = val; | ||
| 855 | hci_dev_unlock(hdev); | ||
| 856 | |||
| 857 | return 0; | ||
| 858 | } | ||
| 859 | |||
| 860 | static int adv_channel_map_get(void *data, u64 *val) | ||
| 861 | { | ||
| 862 | struct hci_dev *hdev = data; | ||
| 863 | |||
| 864 | hci_dev_lock(hdev); | ||
| 865 | *val = hdev->le_adv_channel_map; | ||
| 866 | hci_dev_unlock(hdev); | ||
| 867 | |||
| 868 | return 0; | ||
| 869 | } | ||
| 870 | |||
| 871 | DEFINE_SIMPLE_ATTRIBUTE(adv_channel_map_fops, adv_channel_map_get, | ||
| 872 | adv_channel_map_set, "%llu\n"); | ||
| 873 | |||
| 639 | static ssize_t lowpan_read(struct file *file, char __user *user_buf, | 874 | static ssize_t lowpan_read(struct file *file, char __user *user_buf, |
| 640 | size_t count, loff_t *ppos) | 875 | size_t count, loff_t *ppos) |
| 641 | { | 876 | { |
| @@ -679,6 +914,115 @@ static const struct file_operations lowpan_debugfs_fops = { | |||
| 679 | .llseek = default_llseek, | 914 | .llseek = default_llseek, |
| 680 | }; | 915 | }; |
| 681 | 916 | ||
| 917 | static int le_auto_conn_show(struct seq_file *sf, void *ptr) | ||
| 918 | { | ||
| 919 | struct hci_dev *hdev = sf->private; | ||
| 920 | struct hci_conn_params *p; | ||
| 921 | |||
| 922 | hci_dev_lock(hdev); | ||
| 923 | |||
| 924 | list_for_each_entry(p, &hdev->le_conn_params, list) { | ||
| 925 | seq_printf(sf, "%pMR %u %u\n", &p->addr, p->addr_type, | ||
| 926 | p->auto_connect); | ||
| 927 | } | ||
| 928 | |||
| 929 | hci_dev_unlock(hdev); | ||
| 930 | |||
| 931 | return 0; | ||
| 932 | } | ||
| 933 | |||
| 934 | static int le_auto_conn_open(struct inode *inode, struct file *file) | ||
| 935 | { | ||
| 936 | return single_open(file, le_auto_conn_show, inode->i_private); | ||
| 937 | } | ||
| 938 | |||
| 939 | static ssize_t le_auto_conn_write(struct file *file, const char __user *data, | ||
| 940 | size_t count, loff_t *offset) | ||
| 941 | { | ||
| 942 | struct seq_file *sf = file->private_data; | ||
| 943 | struct hci_dev *hdev = sf->private; | ||
| 944 | u8 auto_connect = 0; | ||
| 945 | bdaddr_t addr; | ||
| 946 | u8 addr_type; | ||
| 947 | char *buf; | ||
| 948 | int err = 0; | ||
| 949 | int n; | ||
| 950 | |||
| 951 | /* Don't allow partial write */ | ||
| 952 | if (*offset != 0) | ||
| 953 | return -EINVAL; | ||
| 954 | |||
| 955 | if (count < 3) | ||
| 956 | return -EINVAL; | ||
| 957 | |||
| 958 | buf = kzalloc(count, GFP_KERNEL); | ||
| 959 | if (!buf) | ||
| 960 | return -ENOMEM; | ||
| 961 | |||
| 962 | if (copy_from_user(buf, data, count)) { | ||
| 963 | err = -EFAULT; | ||
| 964 | goto done; | ||
| 965 | } | ||
| 966 | |||
| 967 | if (memcmp(buf, "add", 3) == 0) { | ||
| 968 | n = sscanf(&buf[4], "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %hhu %hhu", | ||
| 969 | &addr.b[5], &addr.b[4], &addr.b[3], &addr.b[2], | ||
| 970 | &addr.b[1], &addr.b[0], &addr_type, | ||
| 971 | &auto_connect); | ||
| 972 | |||
| 973 | if (n < 7) { | ||
| 974 | err = -EINVAL; | ||
| 975 | goto done; | ||
| 976 | } | ||
| 977 | |||
| 978 | hci_dev_lock(hdev); | ||
| 979 | err = hci_conn_params_add(hdev, &addr, addr_type, auto_connect, | ||
| 980 | hdev->le_conn_min_interval, | ||
| 981 | hdev->le_conn_max_interval); | ||
| 982 | hci_dev_unlock(hdev); | ||
| 983 | |||
| 984 | if (err) | ||
| 985 | goto done; | ||
| 986 | } else if (memcmp(buf, "del", 3) == 0) { | ||
| 987 | n = sscanf(&buf[4], "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %hhu", | ||
| 988 | &addr.b[5], &addr.b[4], &addr.b[3], &addr.b[2], | ||
| 989 | &addr.b[1], &addr.b[0], &addr_type); | ||
| 990 | |||
| 991 | if (n < 7) { | ||
| 992 | err = -EINVAL; | ||
| 993 | goto done; | ||
| 994 | } | ||
| 995 | |||
| 996 | hci_dev_lock(hdev); | ||
| 997 | hci_conn_params_del(hdev, &addr, addr_type); | ||
| 998 | hci_dev_unlock(hdev); | ||
| 999 | } else if (memcmp(buf, "clr", 3) == 0) { | ||
| 1000 | hci_dev_lock(hdev); | ||
| 1001 | hci_conn_params_clear(hdev); | ||
| 1002 | hci_pend_le_conns_clear(hdev); | ||
| 1003 | hci_update_background_scan(hdev); | ||
| 1004 | hci_dev_unlock(hdev); | ||
| 1005 | } else { | ||
| 1006 | err = -EINVAL; | ||
| 1007 | } | ||
| 1008 | |||
| 1009 | done: | ||
| 1010 | kfree(buf); | ||
| 1011 | |||
| 1012 | if (err) | ||
| 1013 | return err; | ||
| 1014 | else | ||
| 1015 | return count; | ||
| 1016 | } | ||
| 1017 | |||
| 1018 | static const struct file_operations le_auto_conn_fops = { | ||
| 1019 | .open = le_auto_conn_open, | ||
| 1020 | .read = seq_read, | ||
| 1021 | .write = le_auto_conn_write, | ||
| 1022 | .llseek = seq_lseek, | ||
| 1023 | .release = single_release, | ||
| 1024 | }; | ||
| 1025 | |||
| 682 | /* ---- HCI requests ---- */ | 1026 | /* ---- HCI requests ---- */ |
| 683 | 1027 | ||
| 684 | static void hci_req_sync_complete(struct hci_dev *hdev, u8 result) | 1028 | static void hci_req_sync_complete(struct hci_dev *hdev, u8 result) |
| @@ -1005,7 +1349,7 @@ static void bredr_setup(struct hci_request *req) | |||
| 1005 | hci_req_add(req, HCI_OP_SET_EVENT_FLT, 1, &flt_type); | 1349 | hci_req_add(req, HCI_OP_SET_EVENT_FLT, 1, &flt_type); |
| 1006 | 1350 | ||
| 1007 | /* Connection accept timeout ~20 secs */ | 1351 | /* Connection accept timeout ~20 secs */ |
| 1008 | param = __constant_cpu_to_le16(0x7d00); | 1352 | param = cpu_to_le16(0x7d00); |
| 1009 | hci_req_add(req, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m); | 1353 | hci_req_add(req, HCI_OP_WRITE_CA_TIMEOUT, 2, ¶m); |
| 1010 | 1354 | ||
| 1011 | /* AVM Berlin (31), aka "BlueFRITZ!", reports version 1.2, | 1355 | /* AVM Berlin (31), aka "BlueFRITZ!", reports version 1.2, |
| @@ -1027,14 +1371,17 @@ static void le_setup(struct hci_request *req) | |||
| 1027 | /* Read LE Local Supported Features */ | 1371 | /* Read LE Local Supported Features */ |
| 1028 | hci_req_add(req, HCI_OP_LE_READ_LOCAL_FEATURES, 0, NULL); | 1372 | hci_req_add(req, HCI_OP_LE_READ_LOCAL_FEATURES, 0, NULL); |
| 1029 | 1373 | ||
| 1374 | /* Read LE Supported States */ | ||
| 1375 | hci_req_add(req, HCI_OP_LE_READ_SUPPORTED_STATES, 0, NULL); | ||
| 1376 | |||
| 1030 | /* Read LE Advertising Channel TX Power */ | 1377 | /* Read LE Advertising Channel TX Power */ |
| 1031 | hci_req_add(req, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL); | 1378 | hci_req_add(req, HCI_OP_LE_READ_ADV_TX_POWER, 0, NULL); |
| 1032 | 1379 | ||
| 1033 | /* Read LE White List Size */ | 1380 | /* Read LE White List Size */ |
| 1034 | hci_req_add(req, HCI_OP_LE_READ_WHITE_LIST_SIZE, 0, NULL); | 1381 | hci_req_add(req, HCI_OP_LE_READ_WHITE_LIST_SIZE, 0, NULL); |
| 1035 | 1382 | ||
| 1036 | /* Read LE Supported States */ | 1383 | /* Clear LE White List */ |
| 1037 | hci_req_add(req, HCI_OP_LE_READ_SUPPORTED_STATES, 0, NULL); | 1384 | hci_req_add(req, HCI_OP_LE_CLEAR_WHITE_LIST, 0, NULL); |
| 1038 | 1385 | ||
| 1039 | /* LE-only controllers have LE implicitly enabled */ | 1386 | /* LE-only controllers have LE implicitly enabled */ |
| 1040 | if (!lmp_bredr_capable(hdev)) | 1387 | if (!lmp_bredr_capable(hdev)) |
| @@ -1288,6 +1635,10 @@ static void hci_set_event_mask_page_2(struct hci_request *req) | |||
| 1288 | events[2] |= 0x08; /* Truncated Page Complete */ | 1635 | events[2] |= 0x08; /* Truncated Page Complete */ |
| 1289 | } | 1636 | } |
| 1290 | 1637 | ||
| 1638 | /* Enable Authenticated Payload Timeout Expired event if supported */ | ||
| 1639 | if (lmp_ping_capable(hdev)) | ||
| 1640 | events[2] |= 0x80; | ||
| 1641 | |||
| 1291 | hci_req_add(req, HCI_OP_SET_EVENT_MASK_PAGE_2, sizeof(events), events); | 1642 | hci_req_add(req, HCI_OP_SET_EVENT_MASK_PAGE_2, sizeof(events), events); |
| 1292 | } | 1643 | } |
| 1293 | 1644 | ||
| @@ -1322,21 +1673,8 @@ static void hci_init3_req(struct hci_request *req, unsigned long opt) | |||
| 1322 | if (hdev->commands[5] & 0x10) | 1673 | if (hdev->commands[5] & 0x10) |
| 1323 | hci_setup_link_policy(req); | 1674 | hci_setup_link_policy(req); |
| 1324 | 1675 | ||
| 1325 | if (lmp_le_capable(hdev)) { | 1676 | if (lmp_le_capable(hdev)) |
| 1326 | if (test_bit(HCI_SETUP, &hdev->dev_flags)) { | ||
| 1327 | /* If the controller has a public BD_ADDR, then | ||
| 1328 | * by default use that one. If this is a LE only | ||
| 1329 | * controller without a public address, default | ||
| 1330 | * to the random address. | ||
| 1331 | */ | ||
| 1332 | if (bacmp(&hdev->bdaddr, BDADDR_ANY)) | ||
| 1333 | hdev->own_addr_type = ADDR_LE_DEV_PUBLIC; | ||
| 1334 | else | ||
| 1335 | hdev->own_addr_type = ADDR_LE_DEV_RANDOM; | ||
| 1336 | } | ||
| 1337 | |||
| 1338 | hci_set_le_support(req); | 1677 | hci_set_le_support(req); |
| 1339 | } | ||
| 1340 | 1678 | ||
| 1341 | /* Read features beyond page 1 if available */ | 1679 | /* Read features beyond page 1 if available */ |
| 1342 | for (p = 2; p < HCI_MAX_PAGES && p <= hdev->max_page; p++) { | 1680 | for (p = 2; p < HCI_MAX_PAGES && p <= hdev->max_page; p++) { |
| @@ -1359,6 +1697,15 @@ static void hci_init4_req(struct hci_request *req, unsigned long opt) | |||
| 1359 | /* Check for Synchronization Train support */ | 1697 | /* Check for Synchronization Train support */ |
| 1360 | if (lmp_sync_train_capable(hdev)) | 1698 | if (lmp_sync_train_capable(hdev)) |
| 1361 | hci_req_add(req, HCI_OP_READ_SYNC_TRAIN_PARAMS, 0, NULL); | 1699 | hci_req_add(req, HCI_OP_READ_SYNC_TRAIN_PARAMS, 0, NULL); |
| 1700 | |||
| 1701 | /* Enable Secure Connections if supported and configured */ | ||
| 1702 | if ((lmp_sc_capable(hdev) || | ||
| 1703 | test_bit(HCI_FORCE_SC, &hdev->dev_flags)) && | ||
| 1704 | test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) { | ||
| 1705 | u8 support = 0x01; | ||
| 1706 | hci_req_add(req, HCI_OP_WRITE_SC_SUPPORT, | ||
| 1707 | sizeof(support), &support); | ||
| 1708 | } | ||
| 1362 | } | 1709 | } |
| 1363 | 1710 | ||
| 1364 | static int __hci_init(struct hci_dev *hdev) | 1711 | static int __hci_init(struct hci_dev *hdev) |
| @@ -1417,8 +1764,6 @@ static int __hci_init(struct hci_dev *hdev) | |||
| 1417 | hdev, &inquiry_cache_fops); | 1764 | hdev, &inquiry_cache_fops); |
| 1418 | debugfs_create_file("link_keys", 0400, hdev->debugfs, | 1765 | debugfs_create_file("link_keys", 0400, hdev->debugfs, |
| 1419 | hdev, &link_keys_fops); | 1766 | hdev, &link_keys_fops); |
| 1420 | debugfs_create_file("use_debug_keys", 0444, hdev->debugfs, | ||
| 1421 | hdev, &use_debug_keys_fops); | ||
| 1422 | debugfs_create_file("dev_class", 0444, hdev->debugfs, | 1767 | debugfs_create_file("dev_class", 0444, hdev->debugfs, |
| 1423 | hdev, &dev_class_fops); | 1768 | hdev, &dev_class_fops); |
| 1424 | debugfs_create_file("voice_setting", 0444, hdev->debugfs, | 1769 | debugfs_create_file("voice_setting", 0444, hdev->debugfs, |
| @@ -1430,6 +1775,10 @@ static int __hci_init(struct hci_dev *hdev) | |||
| 1430 | hdev, &auto_accept_delay_fops); | 1775 | hdev, &auto_accept_delay_fops); |
| 1431 | debugfs_create_file("ssp_debug_mode", 0644, hdev->debugfs, | 1776 | debugfs_create_file("ssp_debug_mode", 0644, hdev->debugfs, |
| 1432 | hdev, &ssp_debug_mode_fops); | 1777 | hdev, &ssp_debug_mode_fops); |
| 1778 | debugfs_create_file("force_sc_support", 0644, hdev->debugfs, | ||
| 1779 | hdev, &force_sc_support_fops); | ||
| 1780 | debugfs_create_file("sc_only_mode", 0444, hdev->debugfs, | ||
| 1781 | hdev, &sc_only_mode_fops); | ||
| 1433 | } | 1782 | } |
| 1434 | 1783 | ||
| 1435 | if (lmp_sniff_capable(hdev)) { | 1784 | if (lmp_sniff_capable(hdev)) { |
| @@ -1442,20 +1791,43 @@ static int __hci_init(struct hci_dev *hdev) | |||
| 1442 | } | 1791 | } |
| 1443 | 1792 | ||
| 1444 | if (lmp_le_capable(hdev)) { | 1793 | if (lmp_le_capable(hdev)) { |
| 1794 | debugfs_create_file("identity", 0400, hdev->debugfs, | ||
| 1795 | hdev, &identity_fops); | ||
| 1796 | debugfs_create_file("rpa_timeout", 0644, hdev->debugfs, | ||
| 1797 | hdev, &rpa_timeout_fops); | ||
| 1798 | debugfs_create_file("random_address", 0444, hdev->debugfs, | ||
| 1799 | hdev, &random_address_fops); | ||
| 1800 | debugfs_create_file("static_address", 0444, hdev->debugfs, | ||
| 1801 | hdev, &static_address_fops); | ||
| 1802 | |||
| 1803 | /* For controllers with a public address, provide a debug | ||
| 1804 | * option to force the usage of the configured static | ||
| 1805 | * address. By default the public address is used. | ||
| 1806 | */ | ||
| 1807 | if (bacmp(&hdev->bdaddr, BDADDR_ANY)) | ||
| 1808 | debugfs_create_file("force_static_address", 0644, | ||
| 1809 | hdev->debugfs, hdev, | ||
| 1810 | &force_static_address_fops); | ||
| 1811 | |||
| 1445 | debugfs_create_u8("white_list_size", 0444, hdev->debugfs, | 1812 | debugfs_create_u8("white_list_size", 0444, hdev->debugfs, |
| 1446 | &hdev->le_white_list_size); | 1813 | &hdev->le_white_list_size); |
| 1447 | debugfs_create_file("static_address", 0444, hdev->debugfs, | 1814 | debugfs_create_file("white_list", 0444, hdev->debugfs, hdev, |
| 1448 | hdev, &static_address_fops); | 1815 | &white_list_fops); |
| 1449 | debugfs_create_file("own_address_type", 0644, hdev->debugfs, | 1816 | debugfs_create_file("identity_resolving_keys", 0400, |
| 1450 | hdev, &own_address_type_fops); | 1817 | hdev->debugfs, hdev, |
| 1818 | &identity_resolving_keys_fops); | ||
| 1451 | debugfs_create_file("long_term_keys", 0400, hdev->debugfs, | 1819 | debugfs_create_file("long_term_keys", 0400, hdev->debugfs, |
| 1452 | hdev, &long_term_keys_fops); | 1820 | hdev, &long_term_keys_fops); |
| 1453 | debugfs_create_file("conn_min_interval", 0644, hdev->debugfs, | 1821 | debugfs_create_file("conn_min_interval", 0644, hdev->debugfs, |
| 1454 | hdev, &conn_min_interval_fops); | 1822 | hdev, &conn_min_interval_fops); |
| 1455 | debugfs_create_file("conn_max_interval", 0644, hdev->debugfs, | 1823 | debugfs_create_file("conn_max_interval", 0644, hdev->debugfs, |
| 1456 | hdev, &conn_max_interval_fops); | 1824 | hdev, &conn_max_interval_fops); |
| 1825 | debugfs_create_file("adv_channel_map", 0644, hdev->debugfs, | ||
| 1826 | hdev, &adv_channel_map_fops); | ||
| 1457 | debugfs_create_file("6lowpan", 0644, hdev->debugfs, hdev, | 1827 | debugfs_create_file("6lowpan", 0644, hdev->debugfs, hdev, |
| 1458 | &lowpan_debugfs_fops); | 1828 | &lowpan_debugfs_fops); |
| 1829 | debugfs_create_file("le_auto_conn", 0644, hdev->debugfs, hdev, | ||
| 1830 | &le_auto_conn_fops); | ||
| 1459 | } | 1831 | } |
| 1460 | 1832 | ||
| 1461 | return 0; | 1833 | return 0; |
| @@ -1548,6 +1920,8 @@ void hci_discovery_set_state(struct hci_dev *hdev, int state) | |||
| 1548 | 1920 | ||
| 1549 | switch (state) { | 1921 | switch (state) { |
| 1550 | case DISCOVERY_STOPPED: | 1922 | case DISCOVERY_STOPPED: |
| 1923 | hci_update_background_scan(hdev); | ||
| 1924 | |||
| 1551 | if (hdev->discovery.state != DISCOVERY_STARTING) | 1925 | if (hdev->discovery.state != DISCOVERY_STARTING) |
| 1552 | mgmt_discovering(hdev, 0); | 1926 | mgmt_discovering(hdev, 0); |
| 1553 | break; | 1927 | break; |
| @@ -1876,10 +2250,15 @@ static int hci_dev_do_open(struct hci_dev *hdev) | |||
| 1876 | * be able to determine if there is a public address | 2250 | * be able to determine if there is a public address |
| 1877 | * or not. | 2251 | * or not. |
| 1878 | * | 2252 | * |
| 2253 | * In case of user channel usage, it is not important | ||
| 2254 | * if a public address or static random address is | ||
| 2255 | * available. | ||
| 2256 | * | ||
| 1879 | * This check is only valid for BR/EDR controllers | 2257 | * This check is only valid for BR/EDR controllers |
| 1880 | * since AMP controllers do not have an address. | 2258 | * since AMP controllers do not have an address. |
| 1881 | */ | 2259 | */ |
| 1882 | if (hdev->dev_type == HCI_BREDR && | 2260 | if (!test_bit(HCI_USER_CHANNEL, &hdev->dev_flags) && |
| 2261 | hdev->dev_type == HCI_BREDR && | ||
| 1883 | !bacmp(&hdev->bdaddr, BDADDR_ANY) && | 2262 | !bacmp(&hdev->bdaddr, BDADDR_ANY) && |
| 1884 | !bacmp(&hdev->static_addr, BDADDR_ANY)) { | 2263 | !bacmp(&hdev->static_addr, BDADDR_ANY)) { |
| 1885 | ret = -EADDRNOTAVAIL; | 2264 | ret = -EADDRNOTAVAIL; |
| @@ -1916,6 +2295,7 @@ static int hci_dev_do_open(struct hci_dev *hdev) | |||
| 1916 | 2295 | ||
| 1917 | if (!ret) { | 2296 | if (!ret) { |
| 1918 | hci_dev_hold(hdev); | 2297 | hci_dev_hold(hdev); |
| 2298 | set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags); | ||
| 1919 | set_bit(HCI_UP, &hdev->flags); | 2299 | set_bit(HCI_UP, &hdev->flags); |
| 1920 | hci_notify(hdev, HCI_DEV_UP); | 2300 | hci_notify(hdev, HCI_DEV_UP); |
| 1921 | if (!test_bit(HCI_SETUP, &hdev->dev_flags) && | 2301 | if (!test_bit(HCI_SETUP, &hdev->dev_flags) && |
| @@ -2014,9 +2394,13 @@ static int hci_dev_do_close(struct hci_dev *hdev) | |||
| 2014 | 2394 | ||
| 2015 | cancel_delayed_work_sync(&hdev->le_scan_disable); | 2395 | cancel_delayed_work_sync(&hdev->le_scan_disable); |
| 2016 | 2396 | ||
| 2397 | if (test_bit(HCI_MGMT, &hdev->dev_flags)) | ||
| 2398 | cancel_delayed_work_sync(&hdev->rpa_expired); | ||
| 2399 | |||
| 2017 | hci_dev_lock(hdev); | 2400 | hci_dev_lock(hdev); |
| 2018 | hci_inquiry_cache_flush(hdev); | 2401 | hci_inquiry_cache_flush(hdev); |
| 2019 | hci_conn_hash_flush(hdev); | 2402 | hci_conn_hash_flush(hdev); |
| 2403 | hci_pend_le_conns_clear(hdev); | ||
| 2020 | hci_dev_unlock(hdev); | 2404 | hci_dev_unlock(hdev); |
| 2021 | 2405 | ||
| 2022 | hci_notify(hdev, HCI_DEV_DOWN); | 2406 | hci_notify(hdev, HCI_DEV_DOWN); |
| @@ -2074,6 +2458,7 @@ static int hci_dev_do_close(struct hci_dev *hdev) | |||
| 2074 | 2458 | ||
| 2075 | memset(hdev->eir, 0, sizeof(hdev->eir)); | 2459 | memset(hdev->eir, 0, sizeof(hdev->eir)); |
| 2076 | memset(hdev->dev_class, 0, sizeof(hdev->dev_class)); | 2460 | memset(hdev->dev_class, 0, sizeof(hdev->dev_class)); |
| 2461 | bacpy(&hdev->random_addr, BDADDR_ANY); | ||
| 2077 | 2462 | ||
| 2078 | hci_req_unlock(hdev); | 2463 | hci_req_unlock(hdev); |
| 2079 | 2464 | ||
| @@ -2437,7 +2822,7 @@ static void hci_discov_off(struct work_struct *work) | |||
| 2437 | mgmt_discoverable_timeout(hdev); | 2822 | mgmt_discoverable_timeout(hdev); |
| 2438 | } | 2823 | } |
| 2439 | 2824 | ||
| 2440 | int hci_uuids_clear(struct hci_dev *hdev) | 2825 | void hci_uuids_clear(struct hci_dev *hdev) |
| 2441 | { | 2826 | { |
| 2442 | struct bt_uuid *uuid, *tmp; | 2827 | struct bt_uuid *uuid, *tmp; |
| 2443 | 2828 | ||
| @@ -2445,11 +2830,9 @@ int hci_uuids_clear(struct hci_dev *hdev) | |||
| 2445 | list_del(&uuid->list); | 2830 | list_del(&uuid->list); |
| 2446 | kfree(uuid); | 2831 | kfree(uuid); |
| 2447 | } | 2832 | } |
| 2448 | |||
| 2449 | return 0; | ||
| 2450 | } | 2833 | } |
| 2451 | 2834 | ||
| 2452 | int hci_link_keys_clear(struct hci_dev *hdev) | 2835 | void hci_link_keys_clear(struct hci_dev *hdev) |
| 2453 | { | 2836 | { |
| 2454 | struct list_head *p, *n; | 2837 | struct list_head *p, *n; |
| 2455 | 2838 | ||
| @@ -2461,11 +2844,9 @@ int hci_link_keys_clear(struct hci_dev *hdev) | |||
| 2461 | list_del(p); | 2844 | list_del(p); |
| 2462 | kfree(key); | 2845 | kfree(key); |
| 2463 | } | 2846 | } |
| 2464 | |||
| 2465 | return 0; | ||
| 2466 | } | 2847 | } |
| 2467 | 2848 | ||
| 2468 | int hci_smp_ltks_clear(struct hci_dev *hdev) | 2849 | void hci_smp_ltks_clear(struct hci_dev *hdev) |
| 2469 | { | 2850 | { |
| 2470 | struct smp_ltk *k, *tmp; | 2851 | struct smp_ltk *k, *tmp; |
| 2471 | 2852 | ||
| @@ -2473,8 +2854,16 @@ int hci_smp_ltks_clear(struct hci_dev *hdev) | |||
| 2473 | list_del(&k->list); | 2854 | list_del(&k->list); |
| 2474 | kfree(k); | 2855 | kfree(k); |
| 2475 | } | 2856 | } |
| 2857 | } | ||
| 2476 | 2858 | ||
| 2477 | return 0; | 2859 | void hci_smp_irks_clear(struct hci_dev *hdev) |
| 2860 | { | ||
| 2861 | struct smp_irk *k, *tmp; | ||
| 2862 | |||
| 2863 | list_for_each_entry_safe(k, tmp, &hdev->identity_resolving_keys, list) { | ||
| 2864 | list_del(&k->list); | ||
| 2865 | kfree(k); | ||
| 2866 | } | ||
| 2478 | } | 2867 | } |
| 2479 | 2868 | ||
| 2480 | struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr) | 2869 | struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr) |
| @@ -2524,13 +2913,24 @@ static bool hci_persistent_key(struct hci_dev *hdev, struct hci_conn *conn, | |||
| 2524 | return false; | 2913 | return false; |
| 2525 | } | 2914 | } |
| 2526 | 2915 | ||
| 2527 | struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]) | 2916 | static bool ltk_type_master(u8 type) |
| 2917 | { | ||
| 2918 | if (type == HCI_SMP_STK || type == HCI_SMP_LTK) | ||
| 2919 | return true; | ||
| 2920 | |||
| 2921 | return false; | ||
| 2922 | } | ||
| 2923 | |||
| 2924 | struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, __le64 rand, | ||
| 2925 | bool master) | ||
| 2528 | { | 2926 | { |
| 2529 | struct smp_ltk *k; | 2927 | struct smp_ltk *k; |
| 2530 | 2928 | ||
| 2531 | list_for_each_entry(k, &hdev->long_term_keys, list) { | 2929 | list_for_each_entry(k, &hdev->long_term_keys, list) { |
| 2532 | if (k->ediv != ediv || | 2930 | if (k->ediv != ediv || k->rand != rand) |
| 2533 | memcmp(rand, k->rand, sizeof(k->rand))) | 2931 | continue; |
| 2932 | |||
| 2933 | if (ltk_type_master(k->type) != master) | ||
| 2534 | continue; | 2934 | continue; |
| 2535 | 2935 | ||
| 2536 | return k; | 2936 | return k; |
| @@ -2540,18 +2940,56 @@ struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, __le16 ediv, u8 rand[8]) | |||
| 2540 | } | 2940 | } |
| 2541 | 2941 | ||
| 2542 | struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr, | 2942 | struct smp_ltk *hci_find_ltk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr, |
| 2543 | u8 addr_type) | 2943 | u8 addr_type, bool master) |
| 2544 | { | 2944 | { |
| 2545 | struct smp_ltk *k; | 2945 | struct smp_ltk *k; |
| 2546 | 2946 | ||
| 2547 | list_for_each_entry(k, &hdev->long_term_keys, list) | 2947 | list_for_each_entry(k, &hdev->long_term_keys, list) |
| 2548 | if (addr_type == k->bdaddr_type && | 2948 | if (addr_type == k->bdaddr_type && |
| 2549 | bacmp(bdaddr, &k->bdaddr) == 0) | 2949 | bacmp(bdaddr, &k->bdaddr) == 0 && |
| 2950 | ltk_type_master(k->type) == master) | ||
| 2550 | return k; | 2951 | return k; |
| 2551 | 2952 | ||
| 2552 | return NULL; | 2953 | return NULL; |
| 2553 | } | 2954 | } |
| 2554 | 2955 | ||
| 2956 | struct smp_irk *hci_find_irk_by_rpa(struct hci_dev *hdev, bdaddr_t *rpa) | ||
| 2957 | { | ||
| 2958 | struct smp_irk *irk; | ||
| 2959 | |||
| 2960 | list_for_each_entry(irk, &hdev->identity_resolving_keys, list) { | ||
| 2961 | if (!bacmp(&irk->rpa, rpa)) | ||
| 2962 | return irk; | ||
| 2963 | } | ||
| 2964 | |||
| 2965 | list_for_each_entry(irk, &hdev->identity_resolving_keys, list) { | ||
| 2966 | if (smp_irk_matches(hdev->tfm_aes, irk->val, rpa)) { | ||
| 2967 | bacpy(&irk->rpa, rpa); | ||
| 2968 | return irk; | ||
| 2969 | } | ||
| 2970 | } | ||
| 2971 | |||
| 2972 | return NULL; | ||
| 2973 | } | ||
| 2974 | |||
| 2975 | struct smp_irk *hci_find_irk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr, | ||
| 2976 | u8 addr_type) | ||
| 2977 | { | ||
| 2978 | struct smp_irk *irk; | ||
| 2979 | |||
| 2980 | /* Identity Address must be public or static random */ | ||
| 2981 | if (addr_type == ADDR_LE_DEV_RANDOM && (bdaddr->b[5] & 0xc0) != 0xc0) | ||
| 2982 | return NULL; | ||
| 2983 | |||
| 2984 | list_for_each_entry(irk, &hdev->identity_resolving_keys, list) { | ||
| 2985 | if (addr_type == irk->addr_type && | ||
| 2986 | bacmp(bdaddr, &irk->bdaddr) == 0) | ||
| 2987 | return irk; | ||
| 2988 | } | ||
| 2989 | |||
| 2990 | return NULL; | ||
| 2991 | } | ||
| 2992 | |||
| 2555 | int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, | 2993 | int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, |
| 2556 | bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len) | 2994 | bdaddr_t *bdaddr, u8 *val, u8 type, u8 pin_len) |
| 2557 | { | 2995 | { |
| @@ -2565,7 +3003,7 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, | |||
| 2565 | key = old_key; | 3003 | key = old_key; |
| 2566 | } else { | 3004 | } else { |
| 2567 | old_key_type = conn ? conn->key_type : 0xff; | 3005 | old_key_type = conn ? conn->key_type : 0xff; |
| 2568 | key = kzalloc(sizeof(*key), GFP_ATOMIC); | 3006 | key = kzalloc(sizeof(*key), GFP_KERNEL); |
| 2569 | if (!key) | 3007 | if (!key) |
| 2570 | return -ENOMEM; | 3008 | return -ENOMEM; |
| 2571 | list_add(&key->list, &hdev->link_keys); | 3009 | list_add(&key->list, &hdev->link_keys); |
| @@ -2605,22 +3043,20 @@ int hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn, int new_key, | |||
| 2605 | return 0; | 3043 | return 0; |
| 2606 | } | 3044 | } |
| 2607 | 3045 | ||
| 2608 | int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type, u8 type, | 3046 | struct smp_ltk *hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, |
| 2609 | int new_key, u8 authenticated, u8 tk[16], u8 enc_size, __le16 | 3047 | u8 addr_type, u8 type, u8 authenticated, |
| 2610 | ediv, u8 rand[8]) | 3048 | u8 tk[16], u8 enc_size, __le16 ediv, __le64 rand) |
| 2611 | { | 3049 | { |
| 2612 | struct smp_ltk *key, *old_key; | 3050 | struct smp_ltk *key, *old_key; |
| 3051 | bool master = ltk_type_master(type); | ||
| 2613 | 3052 | ||
| 2614 | if (!(type & HCI_SMP_STK) && !(type & HCI_SMP_LTK)) | 3053 | old_key = hci_find_ltk_by_addr(hdev, bdaddr, addr_type, master); |
| 2615 | return 0; | ||
| 2616 | |||
| 2617 | old_key = hci_find_ltk_by_addr(hdev, bdaddr, addr_type); | ||
| 2618 | if (old_key) | 3054 | if (old_key) |
| 2619 | key = old_key; | 3055 | key = old_key; |
| 2620 | else { | 3056 | else { |
| 2621 | key = kzalloc(sizeof(*key), GFP_ATOMIC); | 3057 | key = kzalloc(sizeof(*key), GFP_KERNEL); |
| 2622 | if (!key) | 3058 | if (!key) |
| 2623 | return -ENOMEM; | 3059 | return NULL; |
| 2624 | list_add(&key->list, &hdev->long_term_keys); | 3060 | list_add(&key->list, &hdev->long_term_keys); |
| 2625 | } | 3061 | } |
| 2626 | 3062 | ||
| @@ -2629,17 +3065,34 @@ int hci_add_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type, u8 type, | |||
| 2629 | memcpy(key->val, tk, sizeof(key->val)); | 3065 | memcpy(key->val, tk, sizeof(key->val)); |
| 2630 | key->authenticated = authenticated; | 3066 | key->authenticated = authenticated; |
| 2631 | key->ediv = ediv; | 3067 | key->ediv = ediv; |
| 3068 | key->rand = rand; | ||
| 2632 | key->enc_size = enc_size; | 3069 | key->enc_size = enc_size; |
| 2633 | key->type = type; | 3070 | key->type = type; |
| 2634 | memcpy(key->rand, rand, sizeof(key->rand)); | ||
| 2635 | 3071 | ||
| 2636 | if (!new_key) | 3072 | return key; |
| 2637 | return 0; | 3073 | } |
| 3074 | |||
| 3075 | struct smp_irk *hci_add_irk(struct hci_dev *hdev, bdaddr_t *bdaddr, | ||
| 3076 | u8 addr_type, u8 val[16], bdaddr_t *rpa) | ||
| 3077 | { | ||
| 3078 | struct smp_irk *irk; | ||
| 2638 | 3079 | ||
| 2639 | if (type & HCI_SMP_LTK) | 3080 | irk = hci_find_irk_by_addr(hdev, bdaddr, addr_type); |
| 2640 | mgmt_new_ltk(hdev, key, 1); | 3081 | if (!irk) { |
| 3082 | irk = kzalloc(sizeof(*irk), GFP_KERNEL); | ||
| 3083 | if (!irk) | ||
| 3084 | return NULL; | ||
| 2641 | 3085 | ||
| 2642 | return 0; | 3086 | bacpy(&irk->bdaddr, bdaddr); |
| 3087 | irk->addr_type = addr_type; | ||
| 3088 | |||
| 3089 | list_add(&irk->list, &hdev->identity_resolving_keys); | ||
| 3090 | } | ||
| 3091 | |||
| 3092 | memcpy(irk->val, val, 16); | ||
| 3093 | bacpy(&irk->rpa, rpa); | ||
| 3094 | |||
| 3095 | return irk; | ||
| 2643 | } | 3096 | } |
| 2644 | 3097 | ||
| 2645 | int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr) | 3098 | int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr) |
| @@ -2658,21 +3111,38 @@ int hci_remove_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr) | |||
| 2658 | return 0; | 3111 | return 0; |
| 2659 | } | 3112 | } |
| 2660 | 3113 | ||
| 2661 | int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr) | 3114 | int hci_remove_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 bdaddr_type) |
| 2662 | { | 3115 | { |
| 2663 | struct smp_ltk *k, *tmp; | 3116 | struct smp_ltk *k, *tmp; |
| 3117 | int removed = 0; | ||
| 2664 | 3118 | ||
| 2665 | list_for_each_entry_safe(k, tmp, &hdev->long_term_keys, list) { | 3119 | list_for_each_entry_safe(k, tmp, &hdev->long_term_keys, list) { |
| 2666 | if (bacmp(bdaddr, &k->bdaddr)) | 3120 | if (bacmp(bdaddr, &k->bdaddr) || k->bdaddr_type != bdaddr_type) |
| 2667 | continue; | 3121 | continue; |
| 2668 | 3122 | ||
| 2669 | BT_DBG("%s removing %pMR", hdev->name, bdaddr); | 3123 | BT_DBG("%s removing %pMR", hdev->name, bdaddr); |
| 2670 | 3124 | ||
| 2671 | list_del(&k->list); | 3125 | list_del(&k->list); |
| 2672 | kfree(k); | 3126 | kfree(k); |
| 3127 | removed++; | ||
| 2673 | } | 3128 | } |
| 2674 | 3129 | ||
| 2675 | return 0; | 3130 | return removed ? 0 : -ENOENT; |
| 3131 | } | ||
| 3132 | |||
| 3133 | void hci_remove_irk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type) | ||
| 3134 | { | ||
| 3135 | struct smp_irk *k, *tmp; | ||
| 3136 | |||
| 3137 | list_for_each_entry_safe(k, tmp, &hdev->identity_resolving_keys, list) { | ||
| 3138 | if (bacmp(bdaddr, &k->bdaddr) || k->addr_type != addr_type) | ||
| 3139 | continue; | ||
| 3140 | |||
| 3141 | BT_DBG("%s removing %pMR", hdev->name, bdaddr); | ||
| 3142 | |||
| 3143 | list_del(&k->list); | ||
| 3144 | kfree(k); | ||
| 3145 | } | ||
| 2676 | } | 3146 | } |
| 2677 | 3147 | ||
| 2678 | /* HCI command timer function */ | 3148 | /* HCI command timer function */ |
| @@ -2721,7 +3191,7 @@ int hci_remove_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr) | |||
| 2721 | return 0; | 3191 | return 0; |
| 2722 | } | 3192 | } |
| 2723 | 3193 | ||
| 2724 | int hci_remote_oob_data_clear(struct hci_dev *hdev) | 3194 | void hci_remote_oob_data_clear(struct hci_dev *hdev) |
| 2725 | { | 3195 | { |
| 2726 | struct oob_data *data, *n; | 3196 | struct oob_data *data, *n; |
| 2727 | 3197 | ||
| @@ -2729,19 +3199,43 @@ int hci_remote_oob_data_clear(struct hci_dev *hdev) | |||
| 2729 | list_del(&data->list); | 3199 | list_del(&data->list); |
| 2730 | kfree(data); | 3200 | kfree(data); |
| 2731 | } | 3201 | } |
| 3202 | } | ||
| 3203 | |||
| 3204 | int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, | ||
| 3205 | u8 *hash, u8 *randomizer) | ||
| 3206 | { | ||
| 3207 | struct oob_data *data; | ||
| 3208 | |||
| 3209 | data = hci_find_remote_oob_data(hdev, bdaddr); | ||
| 3210 | if (!data) { | ||
| 3211 | data = kmalloc(sizeof(*data), GFP_KERNEL); | ||
| 3212 | if (!data) | ||
| 3213 | return -ENOMEM; | ||
| 3214 | |||
| 3215 | bacpy(&data->bdaddr, bdaddr); | ||
| 3216 | list_add(&data->list, &hdev->remote_oob_data); | ||
| 3217 | } | ||
| 3218 | |||
| 3219 | memcpy(data->hash192, hash, sizeof(data->hash192)); | ||
| 3220 | memcpy(data->randomizer192, randomizer, sizeof(data->randomizer192)); | ||
| 3221 | |||
| 3222 | memset(data->hash256, 0, sizeof(data->hash256)); | ||
| 3223 | memset(data->randomizer256, 0, sizeof(data->randomizer256)); | ||
| 3224 | |||
| 3225 | BT_DBG("%s for %pMR", hdev->name, bdaddr); | ||
| 2732 | 3226 | ||
| 2733 | return 0; | 3227 | return 0; |
| 2734 | } | 3228 | } |
| 2735 | 3229 | ||
| 2736 | int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash, | 3230 | int hci_add_remote_oob_ext_data(struct hci_dev *hdev, bdaddr_t *bdaddr, |
| 2737 | u8 *randomizer) | 3231 | u8 *hash192, u8 *randomizer192, |
| 3232 | u8 *hash256, u8 *randomizer256) | ||
| 2738 | { | 3233 | { |
| 2739 | struct oob_data *data; | 3234 | struct oob_data *data; |
| 2740 | 3235 | ||
| 2741 | data = hci_find_remote_oob_data(hdev, bdaddr); | 3236 | data = hci_find_remote_oob_data(hdev, bdaddr); |
| 2742 | |||
| 2743 | if (!data) { | 3237 | if (!data) { |
| 2744 | data = kmalloc(sizeof(*data), GFP_ATOMIC); | 3238 | data = kmalloc(sizeof(*data), GFP_KERNEL); |
| 2745 | if (!data) | 3239 | if (!data) |
| 2746 | return -ENOMEM; | 3240 | return -ENOMEM; |
| 2747 | 3241 | ||
| @@ -2749,8 +3243,11 @@ int hci_add_remote_oob_data(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 *hash, | |||
| 2749 | list_add(&data->list, &hdev->remote_oob_data); | 3243 | list_add(&data->list, &hdev->remote_oob_data); |
| 2750 | } | 3244 | } |
| 2751 | 3245 | ||
| 2752 | memcpy(data->hash, hash, sizeof(data->hash)); | 3246 | memcpy(data->hash192, hash192, sizeof(data->hash192)); |
| 2753 | memcpy(data->randomizer, randomizer, sizeof(data->randomizer)); | 3247 | memcpy(data->randomizer192, randomizer192, sizeof(data->randomizer192)); |
| 3248 | |||
| 3249 | memcpy(data->hash256, hash256, sizeof(data->hash256)); | ||
| 3250 | memcpy(data->randomizer256, randomizer256, sizeof(data->randomizer256)); | ||
| 2754 | 3251 | ||
| 2755 | BT_DBG("%s for %pMR", hdev->name, bdaddr); | 3252 | BT_DBG("%s for %pMR", hdev->name, bdaddr); |
| 2756 | 3253 | ||
| @@ -2770,7 +3267,7 @@ struct bdaddr_list *hci_blacklist_lookup(struct hci_dev *hdev, | |||
| 2770 | return NULL; | 3267 | return NULL; |
| 2771 | } | 3268 | } |
| 2772 | 3269 | ||
| 2773 | int hci_blacklist_clear(struct hci_dev *hdev) | 3270 | static void hci_blacklist_clear(struct hci_dev *hdev) |
| 2774 | { | 3271 | { |
| 2775 | struct list_head *p, *n; | 3272 | struct list_head *p, *n; |
| 2776 | 3273 | ||
| @@ -2780,8 +3277,6 @@ int hci_blacklist_clear(struct hci_dev *hdev) | |||
| 2780 | list_del(p); | 3277 | list_del(p); |
| 2781 | kfree(b); | 3278 | kfree(b); |
| 2782 | } | 3279 | } |
| 2783 | |||
| 2784 | return 0; | ||
| 2785 | } | 3280 | } |
| 2786 | 3281 | ||
| 2787 | int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) | 3282 | int hci_blacklist_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) |
| @@ -2810,8 +3305,10 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) | |||
| 2810 | { | 3305 | { |
| 2811 | struct bdaddr_list *entry; | 3306 | struct bdaddr_list *entry; |
| 2812 | 3307 | ||
| 2813 | if (!bacmp(bdaddr, BDADDR_ANY)) | 3308 | if (!bacmp(bdaddr, BDADDR_ANY)) { |
| 2814 | return hci_blacklist_clear(hdev); | 3309 | hci_blacklist_clear(hdev); |
| 3310 | return 0; | ||
| 3311 | } | ||
| 2815 | 3312 | ||
| 2816 | entry = hci_blacklist_lookup(hdev, bdaddr, type); | 3313 | entry = hci_blacklist_lookup(hdev, bdaddr, type); |
| 2817 | if (!entry) | 3314 | if (!entry) |
| @@ -2823,6 +3320,262 @@ int hci_blacklist_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) | |||
| 2823 | return mgmt_device_unblocked(hdev, bdaddr, type); | 3320 | return mgmt_device_unblocked(hdev, bdaddr, type); |
| 2824 | } | 3321 | } |
| 2825 | 3322 | ||
| 3323 | struct bdaddr_list *hci_white_list_lookup(struct hci_dev *hdev, | ||
| 3324 | bdaddr_t *bdaddr, u8 type) | ||
| 3325 | { | ||
| 3326 | struct bdaddr_list *b; | ||
| 3327 | |||
| 3328 | list_for_each_entry(b, &hdev->le_white_list, list) { | ||
| 3329 | if (!bacmp(&b->bdaddr, bdaddr) && b->bdaddr_type == type) | ||
| 3330 | return b; | ||
| 3331 | } | ||
| 3332 | |||
| 3333 | return NULL; | ||
| 3334 | } | ||
| 3335 | |||
| 3336 | void hci_white_list_clear(struct hci_dev *hdev) | ||
| 3337 | { | ||
| 3338 | struct list_head *p, *n; | ||
| 3339 | |||
| 3340 | list_for_each_safe(p, n, &hdev->le_white_list) { | ||
| 3341 | struct bdaddr_list *b = list_entry(p, struct bdaddr_list, list); | ||
| 3342 | |||
| 3343 | list_del(p); | ||
| 3344 | kfree(b); | ||
| 3345 | } | ||
| 3346 | } | ||
| 3347 | |||
| 3348 | int hci_white_list_add(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) | ||
| 3349 | { | ||
| 3350 | struct bdaddr_list *entry; | ||
| 3351 | |||
| 3352 | if (!bacmp(bdaddr, BDADDR_ANY)) | ||
| 3353 | return -EBADF; | ||
| 3354 | |||
| 3355 | entry = kzalloc(sizeof(struct bdaddr_list), GFP_KERNEL); | ||
| 3356 | if (!entry) | ||
| 3357 | return -ENOMEM; | ||
| 3358 | |||
| 3359 | bacpy(&entry->bdaddr, bdaddr); | ||
| 3360 | entry->bdaddr_type = type; | ||
| 3361 | |||
| 3362 | list_add(&entry->list, &hdev->le_white_list); | ||
| 3363 | |||
| 3364 | return 0; | ||
| 3365 | } | ||
| 3366 | |||
| 3367 | int hci_white_list_del(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type) | ||
| 3368 | { | ||
| 3369 | struct bdaddr_list *entry; | ||
| 3370 | |||
| 3371 | if (!bacmp(bdaddr, BDADDR_ANY)) | ||
| 3372 | return -EBADF; | ||
| 3373 | |||
| 3374 | entry = hci_white_list_lookup(hdev, bdaddr, type); | ||
| 3375 | if (!entry) | ||
| 3376 | return -ENOENT; | ||
| 3377 | |||
| 3378 | list_del(&entry->list); | ||
| 3379 | kfree(entry); | ||
| 3380 | |||
| 3381 | return 0; | ||
| 3382 | } | ||
| 3383 | |||
| 3384 | /* This function requires the caller holds hdev->lock */ | ||
| 3385 | struct hci_conn_params *hci_conn_params_lookup(struct hci_dev *hdev, | ||
| 3386 | bdaddr_t *addr, u8 addr_type) | ||
| 3387 | { | ||
| 3388 | struct hci_conn_params *params; | ||
| 3389 | |||
| 3390 | list_for_each_entry(params, &hdev->le_conn_params, list) { | ||
| 3391 | if (bacmp(¶ms->addr, addr) == 0 && | ||
| 3392 | params->addr_type == addr_type) { | ||
| 3393 | return params; | ||
| 3394 | } | ||
| 3395 | } | ||
| 3396 | |||
| 3397 | return NULL; | ||
| 3398 | } | ||
| 3399 | |||
| 3400 | static bool is_connected(struct hci_dev *hdev, bdaddr_t *addr, u8 type) | ||
| 3401 | { | ||
| 3402 | struct hci_conn *conn; | ||
| 3403 | |||
| 3404 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, addr); | ||
| 3405 | if (!conn) | ||
| 3406 | return false; | ||
| 3407 | |||
| 3408 | if (conn->dst_type != type) | ||
| 3409 | return false; | ||
| 3410 | |||
| 3411 | if (conn->state != BT_CONNECTED) | ||
| 3412 | return false; | ||
| 3413 | |||
| 3414 | return true; | ||
| 3415 | } | ||
| 3416 | |||
| 3417 | static bool is_identity_address(bdaddr_t *addr, u8 addr_type) | ||
| 3418 | { | ||
| 3419 | if (addr_type == ADDR_LE_DEV_PUBLIC) | ||
| 3420 | return true; | ||
| 3421 | |||
| 3422 | /* Check for Random Static address type */ | ||
| 3423 | if ((addr->b[5] & 0xc0) == 0xc0) | ||
| 3424 | return true; | ||
| 3425 | |||
| 3426 | return false; | ||
| 3427 | } | ||
| 3428 | |||
| 3429 | /* This function requires the caller holds hdev->lock */ | ||
| 3430 | int hci_conn_params_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type, | ||
| 3431 | u8 auto_connect, u16 conn_min_interval, | ||
| 3432 | u16 conn_max_interval) | ||
| 3433 | { | ||
| 3434 | struct hci_conn_params *params; | ||
| 3435 | |||
| 3436 | if (!is_identity_address(addr, addr_type)) | ||
| 3437 | return -EINVAL; | ||
| 3438 | |||
| 3439 | params = hci_conn_params_lookup(hdev, addr, addr_type); | ||
| 3440 | if (params) | ||
| 3441 | goto update; | ||
| 3442 | |||
| 3443 | params = kzalloc(sizeof(*params), GFP_KERNEL); | ||
| 3444 | if (!params) { | ||
| 3445 | BT_ERR("Out of memory"); | ||
| 3446 | return -ENOMEM; | ||
| 3447 | } | ||
| 3448 | |||
| 3449 | bacpy(¶ms->addr, addr); | ||
| 3450 | params->addr_type = addr_type; | ||
| 3451 | |||
| 3452 | list_add(¶ms->list, &hdev->le_conn_params); | ||
| 3453 | |||
| 3454 | update: | ||
| 3455 | params->conn_min_interval = conn_min_interval; | ||
| 3456 | params->conn_max_interval = conn_max_interval; | ||
| 3457 | params->auto_connect = auto_connect; | ||
| 3458 | |||
| 3459 | switch (auto_connect) { | ||
| 3460 | case HCI_AUTO_CONN_DISABLED: | ||
| 3461 | case HCI_AUTO_CONN_LINK_LOSS: | ||
| 3462 | hci_pend_le_conn_del(hdev, addr, addr_type); | ||
| 3463 | break; | ||
| 3464 | case HCI_AUTO_CONN_ALWAYS: | ||
| 3465 | if (!is_connected(hdev, addr, addr_type)) | ||
| 3466 | hci_pend_le_conn_add(hdev, addr, addr_type); | ||
| 3467 | break; | ||
| 3468 | } | ||
| 3469 | |||
| 3470 | BT_DBG("addr %pMR (type %u) auto_connect %u conn_min_interval 0x%.4x " | ||
| 3471 | "conn_max_interval 0x%.4x", addr, addr_type, auto_connect, | ||
| 3472 | conn_min_interval, conn_max_interval); | ||
| 3473 | |||
| 3474 | return 0; | ||
| 3475 | } | ||
| 3476 | |||
| 3477 | /* This function requires the caller holds hdev->lock */ | ||
| 3478 | void hci_conn_params_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type) | ||
| 3479 | { | ||
| 3480 | struct hci_conn_params *params; | ||
| 3481 | |||
| 3482 | params = hci_conn_params_lookup(hdev, addr, addr_type); | ||
| 3483 | if (!params) | ||
| 3484 | return; | ||
| 3485 | |||
| 3486 | hci_pend_le_conn_del(hdev, addr, addr_type); | ||
| 3487 | |||
| 3488 | list_del(¶ms->list); | ||
| 3489 | kfree(params); | ||
| 3490 | |||
| 3491 | BT_DBG("addr %pMR (type %u)", addr, addr_type); | ||
| 3492 | } | ||
| 3493 | |||
| 3494 | /* This function requires the caller holds hdev->lock */ | ||
| 3495 | void hci_conn_params_clear(struct hci_dev *hdev) | ||
| 3496 | { | ||
| 3497 | struct hci_conn_params *params, *tmp; | ||
| 3498 | |||
| 3499 | list_for_each_entry_safe(params, tmp, &hdev->le_conn_params, list) { | ||
| 3500 | list_del(¶ms->list); | ||
| 3501 | kfree(params); | ||
| 3502 | } | ||
| 3503 | |||
| 3504 | BT_DBG("All LE connection parameters were removed"); | ||
| 3505 | } | ||
| 3506 | |||
| 3507 | /* This function requires the caller holds hdev->lock */ | ||
| 3508 | struct bdaddr_list *hci_pend_le_conn_lookup(struct hci_dev *hdev, | ||
| 3509 | bdaddr_t *addr, u8 addr_type) | ||
| 3510 | { | ||
| 3511 | struct bdaddr_list *entry; | ||
| 3512 | |||
| 3513 | list_for_each_entry(entry, &hdev->pend_le_conns, list) { | ||
| 3514 | if (bacmp(&entry->bdaddr, addr) == 0 && | ||
| 3515 | entry->bdaddr_type == addr_type) | ||
| 3516 | return entry; | ||
| 3517 | } | ||
| 3518 | |||
| 3519 | return NULL; | ||
| 3520 | } | ||
| 3521 | |||
| 3522 | /* This function requires the caller holds hdev->lock */ | ||
| 3523 | void hci_pend_le_conn_add(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type) | ||
| 3524 | { | ||
| 3525 | struct bdaddr_list *entry; | ||
| 3526 | |||
| 3527 | entry = hci_pend_le_conn_lookup(hdev, addr, addr_type); | ||
| 3528 | if (entry) | ||
| 3529 | goto done; | ||
| 3530 | |||
| 3531 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); | ||
| 3532 | if (!entry) { | ||
| 3533 | BT_ERR("Out of memory"); | ||
| 3534 | return; | ||
| 3535 | } | ||
| 3536 | |||
| 3537 | bacpy(&entry->bdaddr, addr); | ||
| 3538 | entry->bdaddr_type = addr_type; | ||
| 3539 | |||
| 3540 | list_add(&entry->list, &hdev->pend_le_conns); | ||
| 3541 | |||
| 3542 | BT_DBG("addr %pMR (type %u)", addr, addr_type); | ||
| 3543 | |||
| 3544 | done: | ||
| 3545 | hci_update_background_scan(hdev); | ||
| 3546 | } | ||
| 3547 | |||
| 3548 | /* This function requires the caller holds hdev->lock */ | ||
| 3549 | void hci_pend_le_conn_del(struct hci_dev *hdev, bdaddr_t *addr, u8 addr_type) | ||
| 3550 | { | ||
| 3551 | struct bdaddr_list *entry; | ||
| 3552 | |||
| 3553 | entry = hci_pend_le_conn_lookup(hdev, addr, addr_type); | ||
| 3554 | if (!entry) | ||
| 3555 | goto done; | ||
| 3556 | |||
| 3557 | list_del(&entry->list); | ||
| 3558 | kfree(entry); | ||
| 3559 | |||
| 3560 | BT_DBG("addr %pMR (type %u)", addr, addr_type); | ||
| 3561 | |||
| 3562 | done: | ||
| 3563 | hci_update_background_scan(hdev); | ||
| 3564 | } | ||
| 3565 | |||
| 3566 | /* This function requires the caller holds hdev->lock */ | ||
| 3567 | void hci_pend_le_conns_clear(struct hci_dev *hdev) | ||
| 3568 | { | ||
| 3569 | struct bdaddr_list *entry, *tmp; | ||
| 3570 | |||
| 3571 | list_for_each_entry_safe(entry, tmp, &hdev->pend_le_conns, list) { | ||
| 3572 | list_del(&entry->list); | ||
| 3573 | kfree(entry); | ||
| 3574 | } | ||
| 3575 | |||
| 3576 | BT_DBG("All LE pending connections cleared"); | ||
| 3577 | } | ||
| 3578 | |||
| 2826 | static void inquiry_complete(struct hci_dev *hdev, u8 status) | 3579 | static void inquiry_complete(struct hci_dev *hdev, u8 status) |
| 2827 | { | 3580 | { |
| 2828 | if (status) { | 3581 | if (status) { |
| @@ -2882,7 +3635,6 @@ static void le_scan_disable_work(struct work_struct *work) | |||
| 2882 | { | 3635 | { |
| 2883 | struct hci_dev *hdev = container_of(work, struct hci_dev, | 3636 | struct hci_dev *hdev = container_of(work, struct hci_dev, |
| 2884 | le_scan_disable.work); | 3637 | le_scan_disable.work); |
| 2885 | struct hci_cp_le_set_scan_enable cp; | ||
| 2886 | struct hci_request req; | 3638 | struct hci_request req; |
| 2887 | int err; | 3639 | int err; |
| 2888 | 3640 | ||
| @@ -2890,15 +3642,128 @@ static void le_scan_disable_work(struct work_struct *work) | |||
| 2890 | 3642 | ||
| 2891 | hci_req_init(&req, hdev); | 3643 | hci_req_init(&req, hdev); |
| 2892 | 3644 | ||
| 2893 | memset(&cp, 0, sizeof(cp)); | 3645 | hci_req_add_le_scan_disable(&req); |
| 2894 | cp.enable = LE_SCAN_DISABLE; | ||
| 2895 | hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp); | ||
| 2896 | 3646 | ||
| 2897 | err = hci_req_run(&req, le_scan_disable_work_complete); | 3647 | err = hci_req_run(&req, le_scan_disable_work_complete); |
| 2898 | if (err) | 3648 | if (err) |
| 2899 | BT_ERR("Disable LE scanning request failed: err %d", err); | 3649 | BT_ERR("Disable LE scanning request failed: err %d", err); |
| 2900 | } | 3650 | } |
| 2901 | 3651 | ||
| 3652 | static void set_random_addr(struct hci_request *req, bdaddr_t *rpa) | ||
| 3653 | { | ||
| 3654 | struct hci_dev *hdev = req->hdev; | ||
| 3655 | |||
| 3656 | /* If we're advertising or initiating an LE connection we can't | ||
| 3657 | * go ahead and change the random address at this time. This is | ||
| 3658 | * because the eventual initiator address used for the | ||
| 3659 | * subsequently created connection will be undefined (some | ||
| 3660 | * controllers use the new address and others the one we had | ||
| 3661 | * when the operation started). | ||
| 3662 | * | ||
| 3663 | * In this kind of scenario skip the update and let the random | ||
| 3664 | * address be updated at the next cycle. | ||
| 3665 | */ | ||
| 3666 | if (test_bit(HCI_ADVERTISING, &hdev->dev_flags) || | ||
| 3667 | hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT)) { | ||
| 3668 | BT_DBG("Deferring random address update"); | ||
| 3669 | return; | ||
| 3670 | } | ||
| 3671 | |||
| 3672 | hci_req_add(req, HCI_OP_LE_SET_RANDOM_ADDR, 6, rpa); | ||
| 3673 | } | ||
| 3674 | |||
| 3675 | int hci_update_random_address(struct hci_request *req, bool require_privacy, | ||
| 3676 | u8 *own_addr_type) | ||
| 3677 | { | ||
| 3678 | struct hci_dev *hdev = req->hdev; | ||
| 3679 | int err; | ||
| 3680 | |||
| 3681 | /* If privacy is enabled use a resolvable private address. If | ||
| 3682 | * current RPA has expired or there is something else than | ||
| 3683 | * the current RPA in use, then generate a new one. | ||
| 3684 | */ | ||
| 3685 | if (test_bit(HCI_PRIVACY, &hdev->dev_flags)) { | ||
| 3686 | int to; | ||
| 3687 | |||
| 3688 | *own_addr_type = ADDR_LE_DEV_RANDOM; | ||
| 3689 | |||
| 3690 | if (!test_and_clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags) && | ||
| 3691 | !bacmp(&hdev->random_addr, &hdev->rpa)) | ||
| 3692 | return 0; | ||
| 3693 | |||
| 3694 | err = smp_generate_rpa(hdev->tfm_aes, hdev->irk, &hdev->rpa); | ||
| 3695 | if (err < 0) { | ||
| 3696 | BT_ERR("%s failed to generate new RPA", hdev->name); | ||
| 3697 | return err; | ||
| 3698 | } | ||
| 3699 | |||
| 3700 | set_random_addr(req, &hdev->rpa); | ||
| 3701 | |||
| 3702 | to = msecs_to_jiffies(hdev->rpa_timeout * 1000); | ||
| 3703 | queue_delayed_work(hdev->workqueue, &hdev->rpa_expired, to); | ||
| 3704 | |||
| 3705 | return 0; | ||
| 3706 | } | ||
| 3707 | |||
| 3708 | /* In case of required privacy without resolvable private address, | ||
| 3709 | * use an unresolvable private address. This is useful for active | ||
| 3710 | * scanning and non-connectable advertising. | ||
| 3711 | */ | ||
| 3712 | if (require_privacy) { | ||
| 3713 | bdaddr_t urpa; | ||
| 3714 | |||
| 3715 | get_random_bytes(&urpa, 6); | ||
| 3716 | urpa.b[5] &= 0x3f; /* Clear two most significant bits */ | ||
| 3717 | |||
| 3718 | *own_addr_type = ADDR_LE_DEV_RANDOM; | ||
| 3719 | set_random_addr(req, &urpa); | ||
| 3720 | return 0; | ||
| 3721 | } | ||
| 3722 | |||
| 3723 | /* If forcing static address is in use or there is no public | ||
| 3724 | * address use the static address as random address (but skip | ||
| 3725 | * the HCI command if the current random address is already the | ||
| 3726 | * static one. | ||
| 3727 | */ | ||
| 3728 | if (test_bit(HCI_FORCE_STATIC_ADDR, &hdev->dev_flags) || | ||
| 3729 | !bacmp(&hdev->bdaddr, BDADDR_ANY)) { | ||
| 3730 | *own_addr_type = ADDR_LE_DEV_RANDOM; | ||
| 3731 | if (bacmp(&hdev->static_addr, &hdev->random_addr)) | ||
| 3732 | hci_req_add(req, HCI_OP_LE_SET_RANDOM_ADDR, 6, | ||
| 3733 | &hdev->static_addr); | ||
| 3734 | return 0; | ||
| 3735 | } | ||
| 3736 | |||
| 3737 | /* Neither privacy nor static address is being used so use a | ||
| 3738 | * public address. | ||
| 3739 | */ | ||
| 3740 | *own_addr_type = ADDR_LE_DEV_PUBLIC; | ||
| 3741 | |||
| 3742 | return 0; | ||
| 3743 | } | ||
| 3744 | |||
| 3745 | /* Copy the Identity Address of the controller. | ||
| 3746 | * | ||
| 3747 | * If the controller has a public BD_ADDR, then by default use that one. | ||
| 3748 | * If this is a LE only controller without a public address, default to | ||
| 3749 | * the static random address. | ||
| 3750 | * | ||
| 3751 | * For debugging purposes it is possible to force controllers with a | ||
| 3752 | * public address to use the static random address instead. | ||
| 3753 | */ | ||
| 3754 | void hci_copy_identity_address(struct hci_dev *hdev, bdaddr_t *bdaddr, | ||
| 3755 | u8 *bdaddr_type) | ||
| 3756 | { | ||
| 3757 | if (test_bit(HCI_FORCE_STATIC_ADDR, &hdev->dev_flags) || | ||
| 3758 | !bacmp(&hdev->bdaddr, BDADDR_ANY)) { | ||
| 3759 | bacpy(bdaddr, &hdev->static_addr); | ||
| 3760 | *bdaddr_type = ADDR_LE_DEV_RANDOM; | ||
| 3761 | } else { | ||
| 3762 | bacpy(bdaddr, &hdev->bdaddr); | ||
| 3763 | *bdaddr_type = ADDR_LE_DEV_PUBLIC; | ||
| 3764 | } | ||
| 3765 | } | ||
| 3766 | |||
| 2902 | /* Alloc HCI device */ | 3767 | /* Alloc HCI device */ |
| 2903 | struct hci_dev *hci_alloc_dev(void) | 3768 | struct hci_dev *hci_alloc_dev(void) |
| 2904 | { | 3769 | { |
| @@ -2919,11 +3784,14 @@ struct hci_dev *hci_alloc_dev(void) | |||
| 2919 | hdev->sniff_max_interval = 800; | 3784 | hdev->sniff_max_interval = 800; |
| 2920 | hdev->sniff_min_interval = 80; | 3785 | hdev->sniff_min_interval = 80; |
| 2921 | 3786 | ||
| 3787 | hdev->le_adv_channel_map = 0x07; | ||
| 2922 | hdev->le_scan_interval = 0x0060; | 3788 | hdev->le_scan_interval = 0x0060; |
| 2923 | hdev->le_scan_window = 0x0030; | 3789 | hdev->le_scan_window = 0x0030; |
| 2924 | hdev->le_conn_min_interval = 0x0028; | 3790 | hdev->le_conn_min_interval = 0x0028; |
| 2925 | hdev->le_conn_max_interval = 0x0038; | 3791 | hdev->le_conn_max_interval = 0x0038; |
| 2926 | 3792 | ||
| 3793 | hdev->rpa_timeout = HCI_DEFAULT_RPA_TIMEOUT; | ||
| 3794 | |||
| 2927 | mutex_init(&hdev->lock); | 3795 | mutex_init(&hdev->lock); |
| 2928 | mutex_init(&hdev->req_lock); | 3796 | mutex_init(&hdev->req_lock); |
| 2929 | 3797 | ||
| @@ -2932,7 +3800,11 @@ struct hci_dev *hci_alloc_dev(void) | |||
| 2932 | INIT_LIST_HEAD(&hdev->uuids); | 3800 | INIT_LIST_HEAD(&hdev->uuids); |
| 2933 | INIT_LIST_HEAD(&hdev->link_keys); | 3801 | INIT_LIST_HEAD(&hdev->link_keys); |
| 2934 | INIT_LIST_HEAD(&hdev->long_term_keys); | 3802 | INIT_LIST_HEAD(&hdev->long_term_keys); |
| 3803 | INIT_LIST_HEAD(&hdev->identity_resolving_keys); | ||
| 2935 | INIT_LIST_HEAD(&hdev->remote_oob_data); | 3804 | INIT_LIST_HEAD(&hdev->remote_oob_data); |
| 3805 | INIT_LIST_HEAD(&hdev->le_white_list); | ||
| 3806 | INIT_LIST_HEAD(&hdev->le_conn_params); | ||
| 3807 | INIT_LIST_HEAD(&hdev->pend_le_conns); | ||
| 2936 | INIT_LIST_HEAD(&hdev->conn_hash.list); | 3808 | INIT_LIST_HEAD(&hdev->conn_hash.list); |
| 2937 | 3809 | ||
| 2938 | INIT_WORK(&hdev->rx_work, hci_rx_work); | 3810 | INIT_WORK(&hdev->rx_work, hci_rx_work); |
| @@ -3017,9 +3889,18 @@ int hci_register_dev(struct hci_dev *hdev) | |||
| 3017 | 3889 | ||
| 3018 | dev_set_name(&hdev->dev, "%s", hdev->name); | 3890 | dev_set_name(&hdev->dev, "%s", hdev->name); |
| 3019 | 3891 | ||
| 3892 | hdev->tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0, | ||
| 3893 | CRYPTO_ALG_ASYNC); | ||
| 3894 | if (IS_ERR(hdev->tfm_aes)) { | ||
| 3895 | BT_ERR("Unable to create crypto context"); | ||
| 3896 | error = PTR_ERR(hdev->tfm_aes); | ||
| 3897 | hdev->tfm_aes = NULL; | ||
| 3898 | goto err_wqueue; | ||
| 3899 | } | ||
| 3900 | |||
| 3020 | error = device_add(&hdev->dev); | 3901 | error = device_add(&hdev->dev); |
| 3021 | if (error < 0) | 3902 | if (error < 0) |
| 3022 | goto err_wqueue; | 3903 | goto err_tfm; |
| 3023 | 3904 | ||
| 3024 | hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev, | 3905 | hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev, |
| 3025 | RFKILL_TYPE_BLUETOOTH, &hci_rfkill_ops, | 3906 | RFKILL_TYPE_BLUETOOTH, &hci_rfkill_ops, |
| @@ -3055,6 +3936,8 @@ int hci_register_dev(struct hci_dev *hdev) | |||
| 3055 | 3936 | ||
| 3056 | return id; | 3937 | return id; |
| 3057 | 3938 | ||
| 3939 | err_tfm: | ||
| 3940 | crypto_free_blkcipher(hdev->tfm_aes); | ||
| 3058 | err_wqueue: | 3941 | err_wqueue: |
| 3059 | destroy_workqueue(hdev->workqueue); | 3942 | destroy_workqueue(hdev->workqueue); |
| 3060 | destroy_workqueue(hdev->req_workqueue); | 3943 | destroy_workqueue(hdev->req_workqueue); |
| @@ -3105,6 +3988,9 @@ void hci_unregister_dev(struct hci_dev *hdev) | |||
| 3105 | rfkill_destroy(hdev->rfkill); | 3988 | rfkill_destroy(hdev->rfkill); |
| 3106 | } | 3989 | } |
| 3107 | 3990 | ||
| 3991 | if (hdev->tfm_aes) | ||
| 3992 | crypto_free_blkcipher(hdev->tfm_aes); | ||
| 3993 | |||
| 3108 | device_del(&hdev->dev); | 3994 | device_del(&hdev->dev); |
| 3109 | 3995 | ||
| 3110 | debugfs_remove_recursive(hdev->debugfs); | 3996 | debugfs_remove_recursive(hdev->debugfs); |
| @@ -3117,7 +4003,11 @@ void hci_unregister_dev(struct hci_dev *hdev) | |||
| 3117 | hci_uuids_clear(hdev); | 4003 | hci_uuids_clear(hdev); |
| 3118 | hci_link_keys_clear(hdev); | 4004 | hci_link_keys_clear(hdev); |
| 3119 | hci_smp_ltks_clear(hdev); | 4005 | hci_smp_ltks_clear(hdev); |
| 4006 | hci_smp_irks_clear(hdev); | ||
| 3120 | hci_remote_oob_data_clear(hdev); | 4007 | hci_remote_oob_data_clear(hdev); |
| 4008 | hci_white_list_clear(hdev); | ||
| 4009 | hci_conn_params_clear(hdev); | ||
| 4010 | hci_pend_le_conns_clear(hdev); | ||
| 3121 | hci_dev_unlock(hdev); | 4011 | hci_dev_unlock(hdev); |
| 3122 | 4012 | ||
| 3123 | hci_dev_put(hdev); | 4013 | hci_dev_put(hdev); |
| @@ -4345,3 +5235,104 @@ static void hci_cmd_work(struct work_struct *work) | |||
| 4345 | } | 5235 | } |
| 4346 | } | 5236 | } |
| 4347 | } | 5237 | } |
| 5238 | |||
| 5239 | void hci_req_add_le_scan_disable(struct hci_request *req) | ||
| 5240 | { | ||
| 5241 | struct hci_cp_le_set_scan_enable cp; | ||
| 5242 | |||
| 5243 | memset(&cp, 0, sizeof(cp)); | ||
| 5244 | cp.enable = LE_SCAN_DISABLE; | ||
| 5245 | hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(cp), &cp); | ||
| 5246 | } | ||
| 5247 | |||
| 5248 | void hci_req_add_le_passive_scan(struct hci_request *req) | ||
| 5249 | { | ||
| 5250 | struct hci_cp_le_set_scan_param param_cp; | ||
| 5251 | struct hci_cp_le_set_scan_enable enable_cp; | ||
| 5252 | struct hci_dev *hdev = req->hdev; | ||
| 5253 | u8 own_addr_type; | ||
| 5254 | |||
| 5255 | /* Set require_privacy to true to avoid identification from | ||
| 5256 | * unknown peer devices. Since this is passive scanning, no | ||
| 5257 | * SCAN_REQ using the local identity should be sent. Mandating | ||
| 5258 | * privacy is just an extra precaution. | ||
| 5259 | */ | ||
| 5260 | if (hci_update_random_address(req, true, &own_addr_type)) | ||
| 5261 | return; | ||
| 5262 | |||
| 5263 | memset(¶m_cp, 0, sizeof(param_cp)); | ||
| 5264 | param_cp.type = LE_SCAN_PASSIVE; | ||
| 5265 | param_cp.interval = cpu_to_le16(hdev->le_scan_interval); | ||
| 5266 | param_cp.window = cpu_to_le16(hdev->le_scan_window); | ||
| 5267 | param_cp.own_address_type = own_addr_type; | ||
| 5268 | hci_req_add(req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp), | ||
| 5269 | ¶m_cp); | ||
| 5270 | |||
| 5271 | memset(&enable_cp, 0, sizeof(enable_cp)); | ||
| 5272 | enable_cp.enable = LE_SCAN_ENABLE; | ||
| 5273 | enable_cp.filter_dup = LE_SCAN_FILTER_DUP_ENABLE; | ||
| 5274 | hci_req_add(req, HCI_OP_LE_SET_SCAN_ENABLE, sizeof(enable_cp), | ||
| 5275 | &enable_cp); | ||
| 5276 | } | ||
| 5277 | |||
| 5278 | static void update_background_scan_complete(struct hci_dev *hdev, u8 status) | ||
| 5279 | { | ||
| 5280 | if (status) | ||
| 5281 | BT_DBG("HCI request failed to update background scanning: " | ||
| 5282 | "status 0x%2.2x", status); | ||
| 5283 | } | ||
| 5284 | |||
| 5285 | /* This function controls the background scanning based on hdev->pend_le_conns | ||
| 5286 | * list. If there are pending LE connection we start the background scanning, | ||
| 5287 | * otherwise we stop it. | ||
| 5288 | * | ||
| 5289 | * This function requires the caller holds hdev->lock. | ||
| 5290 | */ | ||
| 5291 | void hci_update_background_scan(struct hci_dev *hdev) | ||
| 5292 | { | ||
| 5293 | struct hci_request req; | ||
| 5294 | struct hci_conn *conn; | ||
| 5295 | int err; | ||
| 5296 | |||
| 5297 | hci_req_init(&req, hdev); | ||
| 5298 | |||
| 5299 | if (list_empty(&hdev->pend_le_conns)) { | ||
| 5300 | /* If there is no pending LE connections, we should stop | ||
| 5301 | * the background scanning. | ||
| 5302 | */ | ||
| 5303 | |||
| 5304 | /* If controller is not scanning we are done. */ | ||
| 5305 | if (!test_bit(HCI_LE_SCAN, &hdev->dev_flags)) | ||
| 5306 | return; | ||
| 5307 | |||
| 5308 | hci_req_add_le_scan_disable(&req); | ||
| 5309 | |||
| 5310 | BT_DBG("%s stopping background scanning", hdev->name); | ||
| 5311 | } else { | ||
| 5312 | /* If there is at least one pending LE connection, we should | ||
| 5313 | * keep the background scan running. | ||
| 5314 | */ | ||
| 5315 | |||
| 5316 | /* If controller is connecting, we should not start scanning | ||
| 5317 | * since some controllers are not able to scan and connect at | ||
| 5318 | * the same time. | ||
| 5319 | */ | ||
| 5320 | conn = hci_conn_hash_lookup_state(hdev, LE_LINK, BT_CONNECT); | ||
| 5321 | if (conn) | ||
| 5322 | return; | ||
| 5323 | |||
| 5324 | /* If controller is currently scanning, we stop it to ensure we | ||
| 5325 | * don't miss any advertising (due to duplicates filter). | ||
| 5326 | */ | ||
| 5327 | if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) | ||
| 5328 | hci_req_add_le_scan_disable(&req); | ||
| 5329 | |||
| 5330 | hci_req_add_le_passive_scan(&req); | ||
| 5331 | |||
| 5332 | BT_DBG("%s starting background scanning", hdev->name); | ||
| 5333 | } | ||
| 5334 | |||
| 5335 | err = hci_req_run(&req, update_background_scan_complete); | ||
| 5336 | if (err) | ||
| 5337 | BT_ERR("Failed to run HCI request: err %d", err); | ||
| 5338 | } | ||
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 5f812455a450..49774912cb01 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c | |||
| @@ -199,6 +199,8 @@ static void hci_cc_reset(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 199 | memset(hdev->scan_rsp_data, 0, sizeof(hdev->scan_rsp_data)); | 199 | memset(hdev->scan_rsp_data, 0, sizeof(hdev->scan_rsp_data)); |
| 200 | hdev->scan_rsp_data_len = 0; | 200 | hdev->scan_rsp_data_len = 0; |
| 201 | 201 | ||
| 202 | hdev->le_scan_type = LE_SCAN_PASSIVE; | ||
| 203 | |||
| 202 | hdev->ssp_debug_mode = 0; | 204 | hdev->ssp_debug_mode = 0; |
| 203 | } | 205 | } |
| 204 | 206 | ||
| @@ -461,6 +463,34 @@ static void hci_cc_write_ssp_mode(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 461 | } | 463 | } |
| 462 | } | 464 | } |
| 463 | 465 | ||
| 466 | static void hci_cc_write_sc_support(struct hci_dev *hdev, struct sk_buff *skb) | ||
| 467 | { | ||
| 468 | u8 status = *((u8 *) skb->data); | ||
| 469 | struct hci_cp_write_sc_support *sent; | ||
| 470 | |||
| 471 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
| 472 | |||
| 473 | sent = hci_sent_cmd_data(hdev, HCI_OP_WRITE_SC_SUPPORT); | ||
| 474 | if (!sent) | ||
| 475 | return; | ||
| 476 | |||
| 477 | if (!status) { | ||
| 478 | if (sent->support) | ||
| 479 | hdev->features[1][0] |= LMP_HOST_SC; | ||
| 480 | else | ||
| 481 | hdev->features[1][0] &= ~LMP_HOST_SC; | ||
| 482 | } | ||
| 483 | |||
| 484 | if (test_bit(HCI_MGMT, &hdev->dev_flags)) | ||
| 485 | mgmt_sc_enable_complete(hdev, sent->support, status); | ||
| 486 | else if (!status) { | ||
| 487 | if (sent->support) | ||
| 488 | set_bit(HCI_SC_ENABLED, &hdev->dev_flags); | ||
| 489 | else | ||
| 490 | clear_bit(HCI_SC_ENABLED, &hdev->dev_flags); | ||
| 491 | } | ||
| 492 | } | ||
| 493 | |||
| 464 | static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) | 494 | static void hci_cc_read_local_version(struct hci_dev *hdev, struct sk_buff *skb) |
| 465 | { | 495 | { |
| 466 | struct hci_rp_read_local_version *rp = (void *) skb->data; | 496 | struct hci_rp_read_local_version *rp = (void *) skb->data; |
| @@ -904,16 +934,50 @@ static void hci_cc_user_passkey_neg_reply(struct hci_dev *hdev, | |||
| 904 | hci_dev_unlock(hdev); | 934 | hci_dev_unlock(hdev); |
| 905 | } | 935 | } |
| 906 | 936 | ||
| 907 | static void hci_cc_read_local_oob_data_reply(struct hci_dev *hdev, | 937 | static void hci_cc_read_local_oob_data(struct hci_dev *hdev, |
| 908 | struct sk_buff *skb) | 938 | struct sk_buff *skb) |
| 909 | { | 939 | { |
| 910 | struct hci_rp_read_local_oob_data *rp = (void *) skb->data; | 940 | struct hci_rp_read_local_oob_data *rp = (void *) skb->data; |
| 911 | 941 | ||
| 912 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | 942 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); |
| 913 | 943 | ||
| 914 | hci_dev_lock(hdev); | 944 | hci_dev_lock(hdev); |
| 915 | mgmt_read_local_oob_data_reply_complete(hdev, rp->hash, | 945 | mgmt_read_local_oob_data_complete(hdev, rp->hash, rp->randomizer, |
| 916 | rp->randomizer, rp->status); | 946 | NULL, NULL, rp->status); |
| 947 | hci_dev_unlock(hdev); | ||
| 948 | } | ||
| 949 | |||
| 950 | static void hci_cc_read_local_oob_ext_data(struct hci_dev *hdev, | ||
| 951 | struct sk_buff *skb) | ||
| 952 | { | ||
| 953 | struct hci_rp_read_local_oob_ext_data *rp = (void *) skb->data; | ||
| 954 | |||
| 955 | BT_DBG("%s status 0x%2.2x", hdev->name, rp->status); | ||
| 956 | |||
| 957 | hci_dev_lock(hdev); | ||
| 958 | mgmt_read_local_oob_data_complete(hdev, rp->hash192, rp->randomizer192, | ||
| 959 | rp->hash256, rp->randomizer256, | ||
| 960 | rp->status); | ||
| 961 | hci_dev_unlock(hdev); | ||
| 962 | } | ||
| 963 | |||
| 964 | |||
| 965 | static void hci_cc_le_set_random_addr(struct hci_dev *hdev, struct sk_buff *skb) | ||
| 966 | { | ||
| 967 | __u8 status = *((__u8 *) skb->data); | ||
| 968 | bdaddr_t *sent; | ||
| 969 | |||
| 970 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
| 971 | |||
| 972 | sent = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_RANDOM_ADDR); | ||
| 973 | if (!sent) | ||
| 974 | return; | ||
| 975 | |||
| 976 | hci_dev_lock(hdev); | ||
| 977 | |||
| 978 | if (!status) | ||
| 979 | bacpy(&hdev->random_addr, sent); | ||
| 980 | |||
| 917 | hci_dev_unlock(hdev); | 981 | hci_dev_unlock(hdev); |
| 918 | } | 982 | } |
| 919 | 983 | ||
| @@ -929,12 +993,27 @@ static void hci_cc_le_set_adv_enable(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 929 | 993 | ||
| 930 | hci_dev_lock(hdev); | 994 | hci_dev_lock(hdev); |
| 931 | 995 | ||
| 932 | if (!status) { | 996 | if (!status) |
| 933 | if (*sent) | 997 | mgmt_advertising(hdev, *sent); |
| 934 | set_bit(HCI_ADVERTISING, &hdev->dev_flags); | 998 | |
| 935 | else | 999 | hci_dev_unlock(hdev); |
| 936 | clear_bit(HCI_ADVERTISING, &hdev->dev_flags); | 1000 | } |
| 937 | } | 1001 | |
| 1002 | static void hci_cc_le_set_scan_param(struct hci_dev *hdev, struct sk_buff *skb) | ||
| 1003 | { | ||
| 1004 | struct hci_cp_le_set_scan_param *cp; | ||
| 1005 | __u8 status = *((__u8 *) skb->data); | ||
| 1006 | |||
| 1007 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
| 1008 | |||
| 1009 | cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_SCAN_PARAM); | ||
| 1010 | if (!cp) | ||
| 1011 | return; | ||
| 1012 | |||
| 1013 | hci_dev_lock(hdev); | ||
| 1014 | |||
| 1015 | if (!status) | ||
| 1016 | hdev->le_scan_type = cp->type; | ||
| 938 | 1017 | ||
| 939 | hci_dev_unlock(hdev); | 1018 | hci_dev_unlock(hdev); |
| 940 | } | 1019 | } |
| @@ -960,7 +1039,19 @@ static void hci_cc_le_set_scan_enable(struct hci_dev *hdev, | |||
| 960 | break; | 1039 | break; |
| 961 | 1040 | ||
| 962 | case LE_SCAN_DISABLE: | 1041 | case LE_SCAN_DISABLE: |
| 1042 | /* Cancel this timer so that we don't try to disable scanning | ||
| 1043 | * when it's already disabled. | ||
| 1044 | */ | ||
| 1045 | cancel_delayed_work(&hdev->le_scan_disable); | ||
| 1046 | |||
| 963 | clear_bit(HCI_LE_SCAN, &hdev->dev_flags); | 1047 | clear_bit(HCI_LE_SCAN, &hdev->dev_flags); |
| 1048 | /* The HCI_LE_SCAN_INTERRUPTED flag indicates that we | ||
| 1049 | * interrupted scanning due to a connect request. Mark | ||
| 1050 | * therefore discovery as stopped. | ||
| 1051 | */ | ||
| 1052 | if (test_and_clear_bit(HCI_LE_SCAN_INTERRUPTED, | ||
| 1053 | &hdev->dev_flags)) | ||
| 1054 | hci_discovery_set_state(hdev, DISCOVERY_STOPPED); | ||
| 964 | break; | 1055 | break; |
| 965 | 1056 | ||
| 966 | default: | 1057 | default: |
| @@ -980,6 +1071,49 @@ static void hci_cc_le_read_white_list_size(struct hci_dev *hdev, | |||
| 980 | hdev->le_white_list_size = rp->size; | 1071 | hdev->le_white_list_size = rp->size; |
| 981 | } | 1072 | } |
| 982 | 1073 | ||
| 1074 | static void hci_cc_le_clear_white_list(struct hci_dev *hdev, | ||
| 1075 | struct sk_buff *skb) | ||
| 1076 | { | ||
| 1077 | __u8 status = *((__u8 *) skb->data); | ||
| 1078 | |||
| 1079 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
| 1080 | |||
| 1081 | if (!status) | ||
| 1082 | hci_white_list_clear(hdev); | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | static void hci_cc_le_add_to_white_list(struct hci_dev *hdev, | ||
| 1086 | struct sk_buff *skb) | ||
| 1087 | { | ||
| 1088 | struct hci_cp_le_add_to_white_list *sent; | ||
| 1089 | __u8 status = *((__u8 *) skb->data); | ||
| 1090 | |||
| 1091 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
| 1092 | |||
| 1093 | sent = hci_sent_cmd_data(hdev, HCI_OP_LE_ADD_TO_WHITE_LIST); | ||
| 1094 | if (!sent) | ||
| 1095 | return; | ||
| 1096 | |||
| 1097 | if (!status) | ||
| 1098 | hci_white_list_add(hdev, &sent->bdaddr, sent->bdaddr_type); | ||
| 1099 | } | ||
| 1100 | |||
| 1101 | static void hci_cc_le_del_from_white_list(struct hci_dev *hdev, | ||
| 1102 | struct sk_buff *skb) | ||
| 1103 | { | ||
| 1104 | struct hci_cp_le_del_from_white_list *sent; | ||
| 1105 | __u8 status = *((__u8 *) skb->data); | ||
| 1106 | |||
| 1107 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
| 1108 | |||
| 1109 | sent = hci_sent_cmd_data(hdev, HCI_OP_LE_DEL_FROM_WHITE_LIST); | ||
| 1110 | if (!sent) | ||
| 1111 | return; | ||
| 1112 | |||
| 1113 | if (!status) | ||
| 1114 | hci_white_list_del(hdev, &sent->bdaddr, sent->bdaddr_type); | ||
| 1115 | } | ||
| 1116 | |||
| 983 | static void hci_cc_le_read_supported_states(struct hci_dev *hdev, | 1117 | static void hci_cc_le_read_supported_states(struct hci_dev *hdev, |
| 984 | struct sk_buff *skb) | 1118 | struct sk_buff *skb) |
| 985 | { | 1119 | { |
| @@ -1020,6 +1154,25 @@ static void hci_cc_write_le_host_supported(struct hci_dev *hdev, | |||
| 1020 | } | 1154 | } |
| 1021 | } | 1155 | } |
| 1022 | 1156 | ||
| 1157 | static void hci_cc_set_adv_param(struct hci_dev *hdev, struct sk_buff *skb) | ||
| 1158 | { | ||
| 1159 | struct hci_cp_le_set_adv_param *cp; | ||
| 1160 | u8 status = *((u8 *) skb->data); | ||
| 1161 | |||
| 1162 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
| 1163 | |||
| 1164 | if (status) | ||
| 1165 | return; | ||
| 1166 | |||
| 1167 | cp = hci_sent_cmd_data(hdev, HCI_OP_LE_SET_ADV_PARAM); | ||
| 1168 | if (!cp) | ||
| 1169 | return; | ||
| 1170 | |||
| 1171 | hci_dev_lock(hdev); | ||
| 1172 | hdev->adv_addr_type = cp->own_address_type; | ||
| 1173 | hci_dev_unlock(hdev); | ||
| 1174 | } | ||
| 1175 | |||
| 1023 | static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev, | 1176 | static void hci_cc_write_remote_amp_assoc(struct hci_dev *hdev, |
| 1024 | struct sk_buff *skb) | 1177 | struct sk_buff *skb) |
| 1025 | { | 1178 | { |
| @@ -1185,9 +1338,12 @@ static int hci_outgoing_auth_needed(struct hci_dev *hdev, | |||
| 1185 | return 0; | 1338 | return 0; |
| 1186 | 1339 | ||
| 1187 | /* Only request authentication for SSP connections or non-SSP | 1340 | /* Only request authentication for SSP connections or non-SSP |
| 1188 | * devices with sec_level HIGH or if MITM protection is requested */ | 1341 | * devices with sec_level MEDIUM or HIGH or if MITM protection |
| 1342 | * is requested. | ||
| 1343 | */ | ||
| 1189 | if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) && | 1344 | if (!hci_conn_ssp_enabled(conn) && !(conn->auth_type & 0x01) && |
| 1190 | conn->pending_sec_level != BT_SECURITY_HIGH) | 1345 | conn->pending_sec_level != BT_SECURITY_HIGH && |
| 1346 | conn->pending_sec_level != BT_SECURITY_MEDIUM) | ||
| 1191 | return 0; | 1347 | return 0; |
| 1192 | 1348 | ||
| 1193 | return 1; | 1349 | return 1; |
| @@ -1518,6 +1674,87 @@ static void hci_cs_accept_phylink(struct hci_dev *hdev, u8 status) | |||
| 1518 | amp_write_remote_assoc(hdev, cp->phy_handle); | 1674 | amp_write_remote_assoc(hdev, cp->phy_handle); |
| 1519 | } | 1675 | } |
| 1520 | 1676 | ||
| 1677 | static void hci_cs_le_create_conn(struct hci_dev *hdev, u8 status) | ||
| 1678 | { | ||
| 1679 | struct hci_cp_le_create_conn *cp; | ||
| 1680 | struct hci_conn *conn; | ||
| 1681 | |||
| 1682 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
| 1683 | |||
| 1684 | /* All connection failure handling is taken care of by the | ||
| 1685 | * hci_le_conn_failed function which is triggered by the HCI | ||
| 1686 | * request completion callbacks used for connecting. | ||
| 1687 | */ | ||
| 1688 | if (status) | ||
| 1689 | return; | ||
| 1690 | |||
| 1691 | cp = hci_sent_cmd_data(hdev, HCI_OP_LE_CREATE_CONN); | ||
| 1692 | if (!cp) | ||
| 1693 | return; | ||
| 1694 | |||
| 1695 | hci_dev_lock(hdev); | ||
| 1696 | |||
| 1697 | conn = hci_conn_hash_lookup_ba(hdev, LE_LINK, &cp->peer_addr); | ||
| 1698 | if (!conn) | ||
| 1699 | goto unlock; | ||
| 1700 | |||
| 1701 | /* Store the initiator and responder address information which | ||
| 1702 | * is needed for SMP. These values will not change during the | ||
| 1703 | * lifetime of the connection. | ||
| 1704 | */ | ||
| 1705 | conn->init_addr_type = cp->own_address_type; | ||
| 1706 | if (cp->own_address_type == ADDR_LE_DEV_RANDOM) | ||
| 1707 | bacpy(&conn->init_addr, &hdev->random_addr); | ||
| 1708 | else | ||
| 1709 | bacpy(&conn->init_addr, &hdev->bdaddr); | ||
| 1710 | |||
| 1711 | conn->resp_addr_type = cp->peer_addr_type; | ||
| 1712 | bacpy(&conn->resp_addr, &cp->peer_addr); | ||
| 1713 | |||
| 1714 | /* We don't want the connection attempt to stick around | ||
| 1715 | * indefinitely since LE doesn't have a page timeout concept | ||
| 1716 | * like BR/EDR. Set a timer for any connection that doesn't use | ||
| 1717 | * the white list for connecting. | ||
| 1718 | */ | ||
| 1719 | if (cp->filter_policy == HCI_LE_USE_PEER_ADDR) | ||
| 1720 | queue_delayed_work(conn->hdev->workqueue, | ||
| 1721 | &conn->le_conn_timeout, | ||
| 1722 | HCI_LE_CONN_TIMEOUT); | ||
| 1723 | |||
| 1724 | unlock: | ||
| 1725 | hci_dev_unlock(hdev); | ||
| 1726 | } | ||
| 1727 | |||
| 1728 | static void hci_cs_le_start_enc(struct hci_dev *hdev, u8 status) | ||
| 1729 | { | ||
| 1730 | struct hci_cp_le_start_enc *cp; | ||
| 1731 | struct hci_conn *conn; | ||
| 1732 | |||
| 1733 | BT_DBG("%s status 0x%2.2x", hdev->name, status); | ||
| 1734 | |||
| 1735 | if (!status) | ||
| 1736 | return; | ||
| 1737 | |||
| 1738 | hci_dev_lock(hdev); | ||
| 1739 | |||
| 1740 | cp = hci_sent_cmd_data(hdev, HCI_OP_LE_START_ENC); | ||
| 1741 | if (!cp) | ||
| 1742 | goto unlock; | ||
| 1743 | |||
| 1744 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); | ||
| 1745 | if (!conn) | ||
| 1746 | goto unlock; | ||
| 1747 | |||
| 1748 | if (conn->state != BT_CONNECTED) | ||
| 1749 | goto unlock; | ||
| 1750 | |||
| 1751 | hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); | ||
| 1752 | hci_conn_drop(conn); | ||
| 1753 | |||
| 1754 | unlock: | ||
| 1755 | hci_dev_unlock(hdev); | ||
| 1756 | } | ||
| 1757 | |||
| 1521 | static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | 1758 | static void hci_inquiry_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) |
| 1522 | { | 1759 | { |
| 1523 | __u8 status = *((__u8 *) skb->data); | 1760 | __u8 status = *((__u8 *) skb->data); |
| @@ -1659,7 +1896,7 @@ static void hci_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 1659 | } else { | 1896 | } else { |
| 1660 | conn->state = BT_CLOSED; | 1897 | conn->state = BT_CLOSED; |
| 1661 | if (conn->type == ACL_LINK) | 1898 | if (conn->type == ACL_LINK) |
| 1662 | mgmt_connect_failed(hdev, &ev->bdaddr, conn->type, | 1899 | mgmt_connect_failed(hdev, &conn->dst, conn->type, |
| 1663 | conn->dst_type, ev->status); | 1900 | conn->dst_type, ev->status); |
| 1664 | } | 1901 | } |
| 1665 | 1902 | ||
| @@ -1738,9 +1975,9 @@ static void hci_conn_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 1738 | bacpy(&cp.bdaddr, &ev->bdaddr); | 1975 | bacpy(&cp.bdaddr, &ev->bdaddr); |
| 1739 | cp.pkt_type = cpu_to_le16(conn->pkt_type); | 1976 | cp.pkt_type = cpu_to_le16(conn->pkt_type); |
| 1740 | 1977 | ||
| 1741 | cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40); | 1978 | cp.tx_bandwidth = cpu_to_le32(0x00001f40); |
| 1742 | cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40); | 1979 | cp.rx_bandwidth = cpu_to_le32(0x00001f40); |
| 1743 | cp.max_latency = __constant_cpu_to_le16(0xffff); | 1980 | cp.max_latency = cpu_to_le16(0xffff); |
| 1744 | cp.content_format = cpu_to_le16(hdev->voice_setting); | 1981 | cp.content_format = cpu_to_le16(hdev->voice_setting); |
| 1745 | cp.retrans_effort = 0xff; | 1982 | cp.retrans_effort = 0xff; |
| 1746 | 1983 | ||
| @@ -1780,7 +2017,9 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 1780 | { | 2017 | { |
| 1781 | struct hci_ev_disconn_complete *ev = (void *) skb->data; | 2018 | struct hci_ev_disconn_complete *ev = (void *) skb->data; |
| 1782 | u8 reason = hci_to_mgmt_reason(ev->reason); | 2019 | u8 reason = hci_to_mgmt_reason(ev->reason); |
| 2020 | struct hci_conn_params *params; | ||
| 1783 | struct hci_conn *conn; | 2021 | struct hci_conn *conn; |
| 2022 | bool mgmt_connected; | ||
| 1784 | u8 type; | 2023 | u8 type; |
| 1785 | 2024 | ||
| 1786 | BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); | 2025 | BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); |
| @@ -1799,13 +2038,30 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 1799 | 2038 | ||
| 1800 | conn->state = BT_CLOSED; | 2039 | conn->state = BT_CLOSED; |
| 1801 | 2040 | ||
| 1802 | if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) | 2041 | mgmt_connected = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags); |
| 1803 | mgmt_device_disconnected(hdev, &conn->dst, conn->type, | 2042 | mgmt_device_disconnected(hdev, &conn->dst, conn->type, conn->dst_type, |
| 1804 | conn->dst_type, reason); | 2043 | reason, mgmt_connected); |
| 1805 | 2044 | ||
| 1806 | if (conn->type == ACL_LINK && conn->flush_key) | 2045 | if (conn->type == ACL_LINK && conn->flush_key) |
| 1807 | hci_remove_link_key(hdev, &conn->dst); | 2046 | hci_remove_link_key(hdev, &conn->dst); |
| 1808 | 2047 | ||
| 2048 | params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type); | ||
| 2049 | if (params) { | ||
| 2050 | switch (params->auto_connect) { | ||
| 2051 | case HCI_AUTO_CONN_LINK_LOSS: | ||
| 2052 | if (ev->reason != HCI_ERROR_CONNECTION_TIMEOUT) | ||
| 2053 | break; | ||
| 2054 | /* Fall through */ | ||
| 2055 | |||
| 2056 | case HCI_AUTO_CONN_ALWAYS: | ||
| 2057 | hci_pend_le_conn_add(hdev, &conn->dst, conn->dst_type); | ||
| 2058 | break; | ||
| 2059 | |||
| 2060 | default: | ||
| 2061 | break; | ||
| 2062 | } | ||
| 2063 | } | ||
| 2064 | |||
| 1809 | type = conn->type; | 2065 | type = conn->type; |
| 1810 | 2066 | ||
| 1811 | hci_proto_disconn_cfm(conn, ev->reason); | 2067 | hci_proto_disconn_cfm(conn, ev->reason); |
| @@ -1943,34 +2199,57 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 1943 | hci_dev_lock(hdev); | 2199 | hci_dev_lock(hdev); |
| 1944 | 2200 | ||
| 1945 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); | 2201 | conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle)); |
| 1946 | if (conn) { | 2202 | if (!conn) |
| 1947 | if (!ev->status) { | 2203 | goto unlock; |
| 1948 | if (ev->encrypt) { | 2204 | |
| 1949 | /* Encryption implies authentication */ | 2205 | if (!ev->status) { |
| 1950 | conn->link_mode |= HCI_LM_AUTH; | 2206 | if (ev->encrypt) { |
| 1951 | conn->link_mode |= HCI_LM_ENCRYPT; | 2207 | /* Encryption implies authentication */ |
| 1952 | conn->sec_level = conn->pending_sec_level; | 2208 | conn->link_mode |= HCI_LM_AUTH; |
| 1953 | } else | 2209 | conn->link_mode |= HCI_LM_ENCRYPT; |
| 1954 | conn->link_mode &= ~HCI_LM_ENCRYPT; | 2210 | conn->sec_level = conn->pending_sec_level; |
| 2211 | |||
| 2212 | /* P-256 authentication key implies FIPS */ | ||
| 2213 | if (conn->key_type == HCI_LK_AUTH_COMBINATION_P256) | ||
| 2214 | conn->link_mode |= HCI_LM_FIPS; | ||
| 2215 | |||
| 2216 | if ((conn->type == ACL_LINK && ev->encrypt == 0x02) || | ||
| 2217 | conn->type == LE_LINK) | ||
| 2218 | set_bit(HCI_CONN_AES_CCM, &conn->flags); | ||
| 2219 | } else { | ||
| 2220 | conn->link_mode &= ~HCI_LM_ENCRYPT; | ||
| 2221 | clear_bit(HCI_CONN_AES_CCM, &conn->flags); | ||
| 1955 | } | 2222 | } |
| 2223 | } | ||
| 1956 | 2224 | ||
| 1957 | clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); | 2225 | clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); |
| 1958 | 2226 | ||
| 1959 | if (ev->status && conn->state == BT_CONNECTED) { | 2227 | if (ev->status && conn->state == BT_CONNECTED) { |
| 1960 | hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); | 2228 | hci_disconnect(conn, HCI_ERROR_AUTH_FAILURE); |
| 2229 | hci_conn_drop(conn); | ||
| 2230 | goto unlock; | ||
| 2231 | } | ||
| 2232 | |||
| 2233 | if (conn->state == BT_CONFIG) { | ||
| 2234 | if (!ev->status) | ||
| 2235 | conn->state = BT_CONNECTED; | ||
| 2236 | |||
| 2237 | /* In Secure Connections Only mode, do not allow any | ||
| 2238 | * connections that are not encrypted with AES-CCM | ||
| 2239 | * using a P-256 authenticated combination key. | ||
| 2240 | */ | ||
| 2241 | if (test_bit(HCI_SC_ONLY, &hdev->dev_flags) && | ||
| 2242 | (!test_bit(HCI_CONN_AES_CCM, &conn->flags) || | ||
| 2243 | conn->key_type != HCI_LK_AUTH_COMBINATION_P256)) { | ||
| 2244 | hci_proto_connect_cfm(conn, HCI_ERROR_AUTH_FAILURE); | ||
| 1961 | hci_conn_drop(conn); | 2245 | hci_conn_drop(conn); |
| 1962 | goto unlock; | 2246 | goto unlock; |
| 1963 | } | 2247 | } |
| 1964 | 2248 | ||
| 1965 | if (conn->state == BT_CONFIG) { | 2249 | hci_proto_connect_cfm(conn, ev->status); |
| 1966 | if (!ev->status) | 2250 | hci_conn_drop(conn); |
| 1967 | conn->state = BT_CONNECTED; | 2251 | } else |
| 1968 | 2252 | hci_encrypt_cfm(conn, ev->status, ev->encrypt); | |
| 1969 | hci_proto_connect_cfm(conn, ev->status); | ||
| 1970 | hci_conn_drop(conn); | ||
| 1971 | } else | ||
| 1972 | hci_encrypt_cfm(conn, ev->status, ev->encrypt); | ||
| 1973 | } | ||
| 1974 | 2253 | ||
| 1975 | unlock: | 2254 | unlock: |
| 1976 | hci_dev_unlock(hdev); | 2255 | hci_dev_unlock(hdev); |
| @@ -2144,6 +2423,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 2144 | hci_cc_write_ssp_mode(hdev, skb); | 2423 | hci_cc_write_ssp_mode(hdev, skb); |
| 2145 | break; | 2424 | break; |
| 2146 | 2425 | ||
| 2426 | case HCI_OP_WRITE_SC_SUPPORT: | ||
| 2427 | hci_cc_write_sc_support(hdev, skb); | ||
| 2428 | break; | ||
| 2429 | |||
| 2147 | case HCI_OP_READ_LOCAL_VERSION: | 2430 | case HCI_OP_READ_LOCAL_VERSION: |
| 2148 | hci_cc_read_local_version(hdev, skb); | 2431 | hci_cc_read_local_version(hdev, skb); |
| 2149 | break; | 2432 | break; |
| @@ -2213,7 +2496,11 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 2213 | break; | 2496 | break; |
| 2214 | 2497 | ||
| 2215 | case HCI_OP_READ_LOCAL_OOB_DATA: | 2498 | case HCI_OP_READ_LOCAL_OOB_DATA: |
| 2216 | hci_cc_read_local_oob_data_reply(hdev, skb); | 2499 | hci_cc_read_local_oob_data(hdev, skb); |
| 2500 | break; | ||
| 2501 | |||
| 2502 | case HCI_OP_READ_LOCAL_OOB_EXT_DATA: | ||
| 2503 | hci_cc_read_local_oob_ext_data(hdev, skb); | ||
| 2217 | break; | 2504 | break; |
| 2218 | 2505 | ||
| 2219 | case HCI_OP_LE_READ_BUFFER_SIZE: | 2506 | case HCI_OP_LE_READ_BUFFER_SIZE: |
| @@ -2244,10 +2531,18 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 2244 | hci_cc_user_passkey_neg_reply(hdev, skb); | 2531 | hci_cc_user_passkey_neg_reply(hdev, skb); |
| 2245 | break; | 2532 | break; |
| 2246 | 2533 | ||
| 2534 | case HCI_OP_LE_SET_RANDOM_ADDR: | ||
| 2535 | hci_cc_le_set_random_addr(hdev, skb); | ||
| 2536 | break; | ||
| 2537 | |||
| 2247 | case HCI_OP_LE_SET_ADV_ENABLE: | 2538 | case HCI_OP_LE_SET_ADV_ENABLE: |
| 2248 | hci_cc_le_set_adv_enable(hdev, skb); | 2539 | hci_cc_le_set_adv_enable(hdev, skb); |
| 2249 | break; | 2540 | break; |
| 2250 | 2541 | ||
| 2542 | case HCI_OP_LE_SET_SCAN_PARAM: | ||
| 2543 | hci_cc_le_set_scan_param(hdev, skb); | ||
| 2544 | break; | ||
| 2545 | |||
| 2251 | case HCI_OP_LE_SET_SCAN_ENABLE: | 2546 | case HCI_OP_LE_SET_SCAN_ENABLE: |
| 2252 | hci_cc_le_set_scan_enable(hdev, skb); | 2547 | hci_cc_le_set_scan_enable(hdev, skb); |
| 2253 | break; | 2548 | break; |
| @@ -2256,6 +2551,18 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 2256 | hci_cc_le_read_white_list_size(hdev, skb); | 2551 | hci_cc_le_read_white_list_size(hdev, skb); |
| 2257 | break; | 2552 | break; |
| 2258 | 2553 | ||
| 2554 | case HCI_OP_LE_CLEAR_WHITE_LIST: | ||
| 2555 | hci_cc_le_clear_white_list(hdev, skb); | ||
| 2556 | break; | ||
| 2557 | |||
| 2558 | case HCI_OP_LE_ADD_TO_WHITE_LIST: | ||
| 2559 | hci_cc_le_add_to_white_list(hdev, skb); | ||
| 2560 | break; | ||
| 2561 | |||
| 2562 | case HCI_OP_LE_DEL_FROM_WHITE_LIST: | ||
| 2563 | hci_cc_le_del_from_white_list(hdev, skb); | ||
| 2564 | break; | ||
| 2565 | |||
| 2259 | case HCI_OP_LE_READ_SUPPORTED_STATES: | 2566 | case HCI_OP_LE_READ_SUPPORTED_STATES: |
| 2260 | hci_cc_le_read_supported_states(hdev, skb); | 2567 | hci_cc_le_read_supported_states(hdev, skb); |
| 2261 | break; | 2568 | break; |
| @@ -2264,6 +2571,10 @@ static void hci_cmd_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 2264 | hci_cc_write_le_host_supported(hdev, skb); | 2571 | hci_cc_write_le_host_supported(hdev, skb); |
| 2265 | break; | 2572 | break; |
| 2266 | 2573 | ||
| 2574 | case HCI_OP_LE_SET_ADV_PARAM: | ||
| 2575 | hci_cc_set_adv_param(hdev, skb); | ||
| 2576 | break; | ||
| 2577 | |||
| 2267 | case HCI_OP_WRITE_REMOTE_AMP_ASSOC: | 2578 | case HCI_OP_WRITE_REMOTE_AMP_ASSOC: |
| 2268 | hci_cc_write_remote_amp_assoc(hdev, skb); | 2579 | hci_cc_write_remote_amp_assoc(hdev, skb); |
| 2269 | break; | 2580 | break; |
| @@ -2351,6 +2662,14 @@ static void hci_cmd_status_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 2351 | hci_cs_accept_phylink(hdev, ev->status); | 2662 | hci_cs_accept_phylink(hdev, ev->status); |
| 2352 | break; | 2663 | break; |
| 2353 | 2664 | ||
| 2665 | case HCI_OP_LE_CREATE_CONN: | ||
| 2666 | hci_cs_le_create_conn(hdev, ev->status); | ||
| 2667 | break; | ||
| 2668 | |||
| 2669 | case HCI_OP_LE_START_ENC: | ||
| 2670 | hci_cs_le_start_enc(hdev, ev->status); | ||
| 2671 | break; | ||
| 2672 | |||
| 2354 | default: | 2673 | default: |
| 2355 | BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); | 2674 | BT_DBG("%s opcode 0x%4.4x", hdev->name, opcode); |
| 2356 | break; | 2675 | break; |
| @@ -2630,7 +2949,8 @@ static void hci_link_key_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 2630 | 2949 | ||
| 2631 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); | 2950 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &ev->bdaddr); |
| 2632 | if (conn) { | 2951 | if (conn) { |
| 2633 | if (key->type == HCI_LK_UNAUTH_COMBINATION && | 2952 | if ((key->type == HCI_LK_UNAUTH_COMBINATION_P192 || |
| 2953 | key->type == HCI_LK_UNAUTH_COMBINATION_P256) && | ||
| 2634 | conn->auth_type != 0xff && (conn->auth_type & 0x01)) { | 2954 | conn->auth_type != 0xff && (conn->auth_type & 0x01)) { |
| 2635 | BT_DBG("%s ignoring unauthenticated key", hdev->name); | 2955 | BT_DBG("%s ignoring unauthenticated key", hdev->name); |
| 2636 | goto not_found; | 2956 | goto not_found; |
| @@ -2844,6 +3164,9 @@ static void hci_remote_ext_features_evt(struct hci_dev *hdev, | |||
| 2844 | * features do not indicate SSP support */ | 3164 | * features do not indicate SSP support */ |
| 2845 | clear_bit(HCI_CONN_SSP_ENABLED, &conn->flags); | 3165 | clear_bit(HCI_CONN_SSP_ENABLED, &conn->flags); |
| 2846 | } | 3166 | } |
| 3167 | |||
| 3168 | if (ev->features[0] & LMP_HOST_SC) | ||
| 3169 | set_bit(HCI_CONN_SC_ENABLED, &conn->flags); | ||
| 2847 | } | 3170 | } |
| 2848 | 3171 | ||
| 2849 | if (conn->state != BT_CONFIG) | 3172 | if (conn->state != BT_CONFIG) |
| @@ -2905,6 +3228,7 @@ static void hci_sync_conn_complete_evt(struct hci_dev *hdev, | |||
| 2905 | case 0x1c: /* SCO interval rejected */ | 3228 | case 0x1c: /* SCO interval rejected */ |
| 2906 | case 0x1a: /* Unsupported Remote Feature */ | 3229 | case 0x1a: /* Unsupported Remote Feature */ |
| 2907 | case 0x1f: /* Unspecified error */ | 3230 | case 0x1f: /* Unspecified error */ |
| 3231 | case 0x20: /* Unsupported LMP Parameter value */ | ||
| 2908 | if (conn->out) { | 3232 | if (conn->out) { |
| 2909 | conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | | 3233 | conn->pkt_type = (hdev->esco_type & SCO_ESCO_MASK) | |
| 2910 | (hdev->esco_type & EDR_ESCO_MASK); | 3234 | (hdev->esco_type & EDR_ESCO_MASK); |
| @@ -3194,8 +3518,8 @@ static void hci_user_confirm_request_evt(struct hci_dev *hdev, | |||
| 3194 | } | 3518 | } |
| 3195 | 3519 | ||
| 3196 | confirm: | 3520 | confirm: |
| 3197 | mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, ev->passkey, | 3521 | mgmt_user_confirm_request(hdev, &ev->bdaddr, ACL_LINK, 0, |
| 3198 | confirm_hint); | 3522 | le32_to_cpu(ev->passkey), confirm_hint); |
| 3199 | 3523 | ||
| 3200 | unlock: | 3524 | unlock: |
| 3201 | hci_dev_unlock(hdev); | 3525 | hci_dev_unlock(hdev); |
| @@ -3337,20 +3661,36 @@ static void hci_remote_oob_data_request_evt(struct hci_dev *hdev, | |||
| 3337 | 3661 | ||
| 3338 | data = hci_find_remote_oob_data(hdev, &ev->bdaddr); | 3662 | data = hci_find_remote_oob_data(hdev, &ev->bdaddr); |
| 3339 | if (data) { | 3663 | if (data) { |
| 3340 | struct hci_cp_remote_oob_data_reply cp; | 3664 | if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) { |
| 3665 | struct hci_cp_remote_oob_ext_data_reply cp; | ||
| 3341 | 3666 | ||
| 3342 | bacpy(&cp.bdaddr, &ev->bdaddr); | 3667 | bacpy(&cp.bdaddr, &ev->bdaddr); |
| 3343 | memcpy(cp.hash, data->hash, sizeof(cp.hash)); | 3668 | memcpy(cp.hash192, data->hash192, sizeof(cp.hash192)); |
| 3344 | memcpy(cp.randomizer, data->randomizer, sizeof(cp.randomizer)); | 3669 | memcpy(cp.randomizer192, data->randomizer192, |
| 3670 | sizeof(cp.randomizer192)); | ||
| 3671 | memcpy(cp.hash256, data->hash256, sizeof(cp.hash256)); | ||
| 3672 | memcpy(cp.randomizer256, data->randomizer256, | ||
| 3673 | sizeof(cp.randomizer256)); | ||
| 3674 | |||
| 3675 | hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_EXT_DATA_REPLY, | ||
| 3676 | sizeof(cp), &cp); | ||
| 3677 | } else { | ||
| 3678 | struct hci_cp_remote_oob_data_reply cp; | ||
| 3679 | |||
| 3680 | bacpy(&cp.bdaddr, &ev->bdaddr); | ||
| 3681 | memcpy(cp.hash, data->hash192, sizeof(cp.hash)); | ||
| 3682 | memcpy(cp.randomizer, data->randomizer192, | ||
| 3683 | sizeof(cp.randomizer)); | ||
| 3345 | 3684 | ||
| 3346 | hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, sizeof(cp), | 3685 | hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_REPLY, |
| 3347 | &cp); | 3686 | sizeof(cp), &cp); |
| 3687 | } | ||
| 3348 | } else { | 3688 | } else { |
| 3349 | struct hci_cp_remote_oob_data_neg_reply cp; | 3689 | struct hci_cp_remote_oob_data_neg_reply cp; |
| 3350 | 3690 | ||
| 3351 | bacpy(&cp.bdaddr, &ev->bdaddr); | 3691 | bacpy(&cp.bdaddr, &ev->bdaddr); |
| 3352 | hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, sizeof(cp), | 3692 | hci_send_cmd(hdev, HCI_OP_REMOTE_OOB_DATA_NEG_REPLY, |
| 3353 | &cp); | 3693 | sizeof(cp), &cp); |
| 3354 | } | 3694 | } |
| 3355 | 3695 | ||
| 3356 | unlock: | 3696 | unlock: |
| @@ -3484,6 +3824,7 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 3484 | { | 3824 | { |
| 3485 | struct hci_ev_le_conn_complete *ev = (void *) skb->data; | 3825 | struct hci_ev_le_conn_complete *ev = (void *) skb->data; |
| 3486 | struct hci_conn *conn; | 3826 | struct hci_conn *conn; |
| 3827 | struct smp_irk *irk; | ||
| 3487 | 3828 | ||
| 3488 | BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); | 3829 | BT_DBG("%s status 0x%2.2x", hdev->name, ev->status); |
| 3489 | 3830 | ||
| @@ -3514,19 +3855,70 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 3514 | conn->out = true; | 3855 | conn->out = true; |
| 3515 | conn->link_mode |= HCI_LM_MASTER; | 3856 | conn->link_mode |= HCI_LM_MASTER; |
| 3516 | } | 3857 | } |
| 3858 | |||
| 3859 | /* If we didn't have a hci_conn object previously | ||
| 3860 | * but we're in master role this must be something | ||
| 3861 | * initiated using a white list. Since white list based | ||
| 3862 | * connections are not "first class citizens" we don't | ||
| 3863 | * have full tracking of them. Therefore, we go ahead | ||
| 3864 | * with a "best effort" approach of determining the | ||
| 3865 | * initiator address based on the HCI_PRIVACY flag. | ||
| 3866 | */ | ||
| 3867 | if (conn->out) { | ||
| 3868 | conn->resp_addr_type = ev->bdaddr_type; | ||
| 3869 | bacpy(&conn->resp_addr, &ev->bdaddr); | ||
| 3870 | if (test_bit(HCI_PRIVACY, &hdev->dev_flags)) { | ||
| 3871 | conn->init_addr_type = ADDR_LE_DEV_RANDOM; | ||
| 3872 | bacpy(&conn->init_addr, &hdev->rpa); | ||
| 3873 | } else { | ||
| 3874 | hci_copy_identity_address(hdev, | ||
| 3875 | &conn->init_addr, | ||
| 3876 | &conn->init_addr_type); | ||
| 3877 | } | ||
| 3878 | } else { | ||
| 3879 | /* Set the responder (our side) address type based on | ||
| 3880 | * the advertising address type. | ||
| 3881 | */ | ||
| 3882 | conn->resp_addr_type = hdev->adv_addr_type; | ||
| 3883 | if (hdev->adv_addr_type == ADDR_LE_DEV_RANDOM) | ||
| 3884 | bacpy(&conn->resp_addr, &hdev->random_addr); | ||
| 3885 | else | ||
| 3886 | bacpy(&conn->resp_addr, &hdev->bdaddr); | ||
| 3887 | |||
| 3888 | conn->init_addr_type = ev->bdaddr_type; | ||
| 3889 | bacpy(&conn->init_addr, &ev->bdaddr); | ||
| 3890 | } | ||
| 3891 | } else { | ||
| 3892 | cancel_delayed_work(&conn->le_conn_timeout); | ||
| 3893 | } | ||
| 3894 | |||
| 3895 | /* Ensure that the hci_conn contains the identity address type | ||
| 3896 | * regardless of which address the connection was made with. | ||
| 3897 | */ | ||
| 3898 | hci_copy_identity_address(hdev, &conn->src, &conn->src_type); | ||
| 3899 | |||
| 3900 | /* Lookup the identity address from the stored connection | ||
| 3901 | * address and address type. | ||
| 3902 | * | ||
| 3903 | * When establishing connections to an identity address, the | ||
| 3904 | * connection procedure will store the resolvable random | ||
| 3905 | * address first. Now if it can be converted back into the | ||
| 3906 | * identity address, start using the identity address from | ||
| 3907 | * now on. | ||
| 3908 | */ | ||
| 3909 | irk = hci_get_irk(hdev, &conn->dst, conn->dst_type); | ||
| 3910 | if (irk) { | ||
| 3911 | bacpy(&conn->dst, &irk->bdaddr); | ||
| 3912 | conn->dst_type = irk->addr_type; | ||
| 3517 | } | 3913 | } |
| 3518 | 3914 | ||
| 3519 | if (ev->status) { | 3915 | if (ev->status) { |
| 3520 | mgmt_connect_failed(hdev, &conn->dst, conn->type, | 3916 | hci_le_conn_failed(conn, ev->status); |
| 3521 | conn->dst_type, ev->status); | ||
| 3522 | hci_proto_connect_cfm(conn, ev->status); | ||
| 3523 | conn->state = BT_CLOSED; | ||
| 3524 | hci_conn_del(conn); | ||
| 3525 | goto unlock; | 3917 | goto unlock; |
| 3526 | } | 3918 | } |
| 3527 | 3919 | ||
| 3528 | if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) | 3920 | if (!test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) |
| 3529 | mgmt_device_connected(hdev, &ev->bdaddr, conn->type, | 3921 | mgmt_device_connected(hdev, &conn->dst, conn->type, |
| 3530 | conn->dst_type, 0, NULL, 0, NULL); | 3922 | conn->dst_type, 0, NULL, 0, NULL); |
| 3531 | 3923 | ||
| 3532 | conn->sec_level = BT_SECURITY_LOW; | 3924 | conn->sec_level = BT_SECURITY_LOW; |
| @@ -3540,25 +3932,73 @@ static void hci_le_conn_complete_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 3540 | 3932 | ||
| 3541 | hci_proto_connect_cfm(conn, ev->status); | 3933 | hci_proto_connect_cfm(conn, ev->status); |
| 3542 | 3934 | ||
| 3935 | hci_pend_le_conn_del(hdev, &conn->dst, conn->dst_type); | ||
| 3936 | |||
| 3543 | unlock: | 3937 | unlock: |
| 3544 | hci_dev_unlock(hdev); | 3938 | hci_dev_unlock(hdev); |
| 3545 | } | 3939 | } |
| 3546 | 3940 | ||
| 3941 | /* This function requires the caller holds hdev->lock */ | ||
| 3942 | static void check_pending_le_conn(struct hci_dev *hdev, bdaddr_t *addr, | ||
| 3943 | u8 addr_type) | ||
| 3944 | { | ||
| 3945 | struct hci_conn *conn; | ||
| 3946 | struct smp_irk *irk; | ||
| 3947 | |||
| 3948 | /* If this is a resolvable address, we should resolve it and then | ||
| 3949 | * update address and address type variables. | ||
| 3950 | */ | ||
| 3951 | irk = hci_get_irk(hdev, addr, addr_type); | ||
| 3952 | if (irk) { | ||
| 3953 | addr = &irk->bdaddr; | ||
| 3954 | addr_type = irk->addr_type; | ||
| 3955 | } | ||
| 3956 | |||
| 3957 | if (!hci_pend_le_conn_lookup(hdev, addr, addr_type)) | ||
| 3958 | return; | ||
| 3959 | |||
| 3960 | conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW, | ||
| 3961 | HCI_AT_NO_BONDING); | ||
| 3962 | if (!IS_ERR(conn)) | ||
| 3963 | return; | ||
| 3964 | |||
| 3965 | switch (PTR_ERR(conn)) { | ||
| 3966 | case -EBUSY: | ||
| 3967 | /* If hci_connect() returns -EBUSY it means there is already | ||
| 3968 | * an LE connection attempt going on. Since controllers don't | ||
| 3969 | * support more than one connection attempt at the time, we | ||
| 3970 | * don't consider this an error case. | ||
| 3971 | */ | ||
| 3972 | break; | ||
| 3973 | default: | ||
| 3974 | BT_DBG("Failed to connect: err %ld", PTR_ERR(conn)); | ||
| 3975 | } | ||
| 3976 | } | ||
| 3977 | |||
| 3547 | static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) | 3978 | static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb) |
| 3548 | { | 3979 | { |
| 3549 | u8 num_reports = skb->data[0]; | 3980 | u8 num_reports = skb->data[0]; |
| 3550 | void *ptr = &skb->data[1]; | 3981 | void *ptr = &skb->data[1]; |
| 3551 | s8 rssi; | 3982 | s8 rssi; |
| 3552 | 3983 | ||
| 3984 | hci_dev_lock(hdev); | ||
| 3985 | |||
| 3553 | while (num_reports--) { | 3986 | while (num_reports--) { |
| 3554 | struct hci_ev_le_advertising_info *ev = ptr; | 3987 | struct hci_ev_le_advertising_info *ev = ptr; |
| 3555 | 3988 | ||
| 3989 | if (ev->evt_type == LE_ADV_IND || | ||
| 3990 | ev->evt_type == LE_ADV_DIRECT_IND) | ||
| 3991 | check_pending_le_conn(hdev, &ev->bdaddr, | ||
| 3992 | ev->bdaddr_type); | ||
| 3993 | |||
| 3556 | rssi = ev->data[ev->length]; | 3994 | rssi = ev->data[ev->length]; |
| 3557 | mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type, | 3995 | mgmt_device_found(hdev, &ev->bdaddr, LE_LINK, ev->bdaddr_type, |
| 3558 | NULL, rssi, 0, 1, ev->data, ev->length); | 3996 | NULL, rssi, 0, 1, ev->data, ev->length); |
| 3559 | 3997 | ||
| 3560 | ptr += sizeof(*ev) + ev->length + 1; | 3998 | ptr += sizeof(*ev) + ev->length + 1; |
| 3561 | } | 3999 | } |
| 4000 | |||
| 4001 | hci_dev_unlock(hdev); | ||
| 3562 | } | 4002 | } |
| 3563 | 4003 | ||
| 3564 | static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | 4004 | static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) |
| @@ -3577,7 +4017,7 @@ static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 3577 | if (conn == NULL) | 4017 | if (conn == NULL) |
| 3578 | goto not_found; | 4018 | goto not_found; |
| 3579 | 4019 | ||
| 3580 | ltk = hci_find_ltk(hdev, ev->ediv, ev->random); | 4020 | ltk = hci_find_ltk(hdev, ev->ediv, ev->rand, conn->out); |
| 3581 | if (ltk == NULL) | 4021 | if (ltk == NULL) |
| 3582 | goto not_found; | 4022 | goto not_found; |
| 3583 | 4023 | ||
| @@ -3593,7 +4033,13 @@ static void hci_le_ltk_request_evt(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 3593 | 4033 | ||
| 3594 | hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); | 4034 | hci_send_cmd(hdev, HCI_OP_LE_LTK_REPLY, sizeof(cp), &cp); |
| 3595 | 4035 | ||
| 3596 | if (ltk->type & HCI_SMP_STK) { | 4036 | /* Ref. Bluetooth Core SPEC pages 1975 and 2004. STK is a |
| 4037 | * temporary key used to encrypt a connection following | ||
| 4038 | * pairing. It is used during the Encrypted Session Setup to | ||
| 4039 | * distribute the keys. Later, security can be re-established | ||
| 4040 | * using a distributed LTK. | ||
| 4041 | */ | ||
| 4042 | if (ltk->type == HCI_SMP_STK_SLAVE) { | ||
| 3597 | list_del(<k->list); | 4043 | list_del(<k->list); |
| 3598 | kfree(ltk); | 4044 | kfree(ltk); |
| 3599 | } | 4045 | } |
diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index 7552f9e3089c..b9a418e578e0 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c | |||
| @@ -211,22 +211,22 @@ void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb) | |||
| 211 | 211 | ||
| 212 | switch (bt_cb(skb)->pkt_type) { | 212 | switch (bt_cb(skb)->pkt_type) { |
| 213 | case HCI_COMMAND_PKT: | 213 | case HCI_COMMAND_PKT: |
| 214 | opcode = __constant_cpu_to_le16(HCI_MON_COMMAND_PKT); | 214 | opcode = cpu_to_le16(HCI_MON_COMMAND_PKT); |
| 215 | break; | 215 | break; |
| 216 | case HCI_EVENT_PKT: | 216 | case HCI_EVENT_PKT: |
| 217 | opcode = __constant_cpu_to_le16(HCI_MON_EVENT_PKT); | 217 | opcode = cpu_to_le16(HCI_MON_EVENT_PKT); |
| 218 | break; | 218 | break; |
| 219 | case HCI_ACLDATA_PKT: | 219 | case HCI_ACLDATA_PKT: |
| 220 | if (bt_cb(skb)->incoming) | 220 | if (bt_cb(skb)->incoming) |
| 221 | opcode = __constant_cpu_to_le16(HCI_MON_ACL_RX_PKT); | 221 | opcode = cpu_to_le16(HCI_MON_ACL_RX_PKT); |
| 222 | else | 222 | else |
| 223 | opcode = __constant_cpu_to_le16(HCI_MON_ACL_TX_PKT); | 223 | opcode = cpu_to_le16(HCI_MON_ACL_TX_PKT); |
| 224 | break; | 224 | break; |
| 225 | case HCI_SCODATA_PKT: | 225 | case HCI_SCODATA_PKT: |
| 226 | if (bt_cb(skb)->incoming) | 226 | if (bt_cb(skb)->incoming) |
| 227 | opcode = __constant_cpu_to_le16(HCI_MON_SCO_RX_PKT); | 227 | opcode = cpu_to_le16(HCI_MON_SCO_RX_PKT); |
| 228 | else | 228 | else |
| 229 | opcode = __constant_cpu_to_le16(HCI_MON_SCO_TX_PKT); | 229 | opcode = cpu_to_le16(HCI_MON_SCO_TX_PKT); |
| 230 | break; | 230 | break; |
| 231 | default: | 231 | default: |
| 232 | return; | 232 | return; |
| @@ -319,7 +319,7 @@ static struct sk_buff *create_monitor_event(struct hci_dev *hdev, int event) | |||
| 319 | bacpy(&ni->bdaddr, &hdev->bdaddr); | 319 | bacpy(&ni->bdaddr, &hdev->bdaddr); |
| 320 | memcpy(ni->name, hdev->name, 8); | 320 | memcpy(ni->name, hdev->name, 8); |
| 321 | 321 | ||
| 322 | opcode = __constant_cpu_to_le16(HCI_MON_NEW_INDEX); | 322 | opcode = cpu_to_le16(HCI_MON_NEW_INDEX); |
| 323 | break; | 323 | break; |
| 324 | 324 | ||
| 325 | case HCI_DEV_UNREG: | 325 | case HCI_DEV_UNREG: |
| @@ -327,7 +327,7 @@ static struct sk_buff *create_monitor_event(struct hci_dev *hdev, int event) | |||
| 327 | if (!skb) | 327 | if (!skb) |
| 328 | return NULL; | 328 | return NULL; |
| 329 | 329 | ||
| 330 | opcode = __constant_cpu_to_le16(HCI_MON_DEL_INDEX); | 330 | opcode = cpu_to_le16(HCI_MON_DEL_INDEX); |
| 331 | break; | 331 | break; |
| 332 | 332 | ||
| 333 | default: | 333 | default: |
| @@ -716,6 +716,7 @@ static int hci_sock_bind(struct socket *sock, struct sockaddr *addr, | |||
| 716 | err = hci_dev_open(hdev->id); | 716 | err = hci_dev_open(hdev->id); |
| 717 | if (err) { | 717 | if (err) { |
| 718 | clear_bit(HCI_USER_CHANNEL, &hdev->dev_flags); | 718 | clear_bit(HCI_USER_CHANNEL, &hdev->dev_flags); |
| 719 | mgmt_index_added(hdev); | ||
| 719 | hci_dev_put(hdev); | 720 | hci_dev_put(hdev); |
| 720 | goto done; | 721 | goto done; |
| 721 | } | 722 | } |
diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c index 0b61250cfdf9..555982a78a58 100644 --- a/net/bluetooth/hci_sysfs.c +++ b/net/bluetooth/hci_sysfs.c | |||
| @@ -49,14 +49,7 @@ static struct attribute *bt_link_attrs[] = { | |||
| 49 | NULL | 49 | NULL |
| 50 | }; | 50 | }; |
| 51 | 51 | ||
| 52 | static struct attribute_group bt_link_group = { | 52 | ATTRIBUTE_GROUPS(bt_link); |
| 53 | .attrs = bt_link_attrs, | ||
| 54 | }; | ||
| 55 | |||
| 56 | static const struct attribute_group *bt_link_groups[] = { | ||
| 57 | &bt_link_group, | ||
| 58 | NULL | ||
| 59 | }; | ||
| 60 | 53 | ||
| 61 | static void bt_link_release(struct device *dev) | 54 | static void bt_link_release(struct device *dev) |
| 62 | { | 55 | { |
| @@ -182,14 +175,7 @@ static struct attribute *bt_host_attrs[] = { | |||
| 182 | NULL | 175 | NULL |
| 183 | }; | 176 | }; |
| 184 | 177 | ||
| 185 | static struct attribute_group bt_host_group = { | 178 | ATTRIBUTE_GROUPS(bt_host); |
| 186 | .attrs = bt_host_attrs, | ||
| 187 | }; | ||
| 188 | |||
| 189 | static const struct attribute_group *bt_host_groups[] = { | ||
| 190 | &bt_host_group, | ||
| 191 | NULL | ||
| 192 | }; | ||
| 193 | 179 | ||
| 194 | static void bt_host_release(struct device *dev) | 180 | static void bt_host_release(struct device *dev) |
| 195 | { | 181 | { |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index b0ad2c752d73..a1e5bb7d06e8 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c | |||
| @@ -42,6 +42,8 @@ | |||
| 42 | #include "amp.h" | 42 | #include "amp.h" |
| 43 | #include "6lowpan.h" | 43 | #include "6lowpan.h" |
| 44 | 44 | ||
| 45 | #define LE_FLOWCTL_MAX_CREDITS 65535 | ||
| 46 | |||
| 45 | bool disable_ertm; | 47 | bool disable_ertm; |
| 46 | 48 | ||
| 47 | static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN | L2CAP_FEAT_UCD; | 49 | static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN | L2CAP_FEAT_UCD; |
| @@ -330,44 +332,20 @@ static inline bool l2cap_seq_list_contains(struct l2cap_seq_list *seq_list, | |||
| 330 | return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR; | 332 | return seq_list->list[seq & seq_list->mask] != L2CAP_SEQ_LIST_CLEAR; |
| 331 | } | 333 | } |
| 332 | 334 | ||
| 333 | static u16 l2cap_seq_list_remove(struct l2cap_seq_list *seq_list, u16 seq) | 335 | static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list) |
| 334 | { | 336 | { |
| 337 | u16 seq = seq_list->head; | ||
| 335 | u16 mask = seq_list->mask; | 338 | u16 mask = seq_list->mask; |
| 336 | 339 | ||
| 337 | if (seq_list->head == L2CAP_SEQ_LIST_CLEAR) { | 340 | seq_list->head = seq_list->list[seq & mask]; |
| 338 | /* In case someone tries to pop the head of an empty list */ | 341 | seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR; |
| 339 | return L2CAP_SEQ_LIST_CLEAR; | ||
| 340 | } else if (seq_list->head == seq) { | ||
| 341 | /* Head can be removed in constant time */ | ||
| 342 | seq_list->head = seq_list->list[seq & mask]; | ||
| 343 | seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR; | ||
| 344 | |||
| 345 | if (seq_list->head == L2CAP_SEQ_LIST_TAIL) { | ||
| 346 | seq_list->head = L2CAP_SEQ_LIST_CLEAR; | ||
| 347 | seq_list->tail = L2CAP_SEQ_LIST_CLEAR; | ||
| 348 | } | ||
| 349 | } else { | ||
| 350 | /* Walk the list to find the sequence number */ | ||
| 351 | u16 prev = seq_list->head; | ||
| 352 | while (seq_list->list[prev & mask] != seq) { | ||
| 353 | prev = seq_list->list[prev & mask]; | ||
| 354 | if (prev == L2CAP_SEQ_LIST_TAIL) | ||
| 355 | return L2CAP_SEQ_LIST_CLEAR; | ||
| 356 | } | ||
| 357 | 342 | ||
| 358 | /* Unlink the number from the list and clear it */ | 343 | if (seq_list->head == L2CAP_SEQ_LIST_TAIL) { |
| 359 | seq_list->list[prev & mask] = seq_list->list[seq & mask]; | 344 | seq_list->head = L2CAP_SEQ_LIST_CLEAR; |
| 360 | seq_list->list[seq & mask] = L2CAP_SEQ_LIST_CLEAR; | 345 | seq_list->tail = L2CAP_SEQ_LIST_CLEAR; |
| 361 | if (seq_list->tail == seq) | ||
| 362 | seq_list->tail = prev; | ||
| 363 | } | 346 | } |
| 364 | return seq; | ||
| 365 | } | ||
| 366 | 347 | ||
| 367 | static inline u16 l2cap_seq_list_pop(struct l2cap_seq_list *seq_list) | 348 | return seq; |
| 368 | { | ||
| 369 | /* Remove the head in constant time */ | ||
| 370 | return l2cap_seq_list_remove(seq_list, seq_list->head); | ||
| 371 | } | 349 | } |
| 372 | 350 | ||
| 373 | static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list) | 351 | static void l2cap_seq_list_clear(struct l2cap_seq_list *seq_list) |
| @@ -506,7 +484,7 @@ static void l2cap_le_flowctl_init(struct l2cap_chan *chan) | |||
| 506 | chan->sdu_len = 0; | 484 | chan->sdu_len = 0; |
| 507 | chan->tx_credits = 0; | 485 | chan->tx_credits = 0; |
| 508 | chan->rx_credits = le_max_credits; | 486 | chan->rx_credits = le_max_credits; |
| 509 | chan->mps = min_t(u16, chan->imtu, L2CAP_LE_DEFAULT_MPS); | 487 | chan->mps = min_t(u16, chan->imtu, le_default_mps); |
| 510 | 488 | ||
| 511 | skb_queue_head_init(&chan->tx_q); | 489 | skb_queue_head_init(&chan->tx_q); |
| 512 | } | 490 | } |
| @@ -522,18 +500,10 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) | |||
| 522 | 500 | ||
| 523 | switch (chan->chan_type) { | 501 | switch (chan->chan_type) { |
| 524 | case L2CAP_CHAN_CONN_ORIENTED: | 502 | case L2CAP_CHAN_CONN_ORIENTED: |
| 525 | if (conn->hcon->type == LE_LINK) { | 503 | /* Alloc CID for connection-oriented socket */ |
| 526 | if (chan->dcid == L2CAP_CID_ATT) { | 504 | chan->scid = l2cap_alloc_cid(conn); |
| 527 | chan->omtu = L2CAP_DEFAULT_MTU; | 505 | if (conn->hcon->type == ACL_LINK) |
| 528 | chan->scid = L2CAP_CID_ATT; | ||
| 529 | } else { | ||
| 530 | chan->scid = l2cap_alloc_cid(conn); | ||
| 531 | } | ||
| 532 | } else { | ||
| 533 | /* Alloc CID for connection-oriented socket */ | ||
| 534 | chan->scid = l2cap_alloc_cid(conn); | ||
| 535 | chan->omtu = L2CAP_DEFAULT_MTU; | 506 | chan->omtu = L2CAP_DEFAULT_MTU; |
| 536 | } | ||
| 537 | break; | 507 | break; |
| 538 | 508 | ||
| 539 | case L2CAP_CHAN_CONN_LESS: | 509 | case L2CAP_CHAN_CONN_LESS: |
| @@ -543,11 +513,8 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) | |||
| 543 | chan->omtu = L2CAP_DEFAULT_MTU; | 513 | chan->omtu = L2CAP_DEFAULT_MTU; |
| 544 | break; | 514 | break; |
| 545 | 515 | ||
| 546 | case L2CAP_CHAN_CONN_FIX_A2MP: | 516 | case L2CAP_CHAN_FIXED: |
| 547 | chan->scid = L2CAP_CID_A2MP; | 517 | /* Caller will set CID and CID specific MTU values */ |
| 548 | chan->dcid = L2CAP_CID_A2MP; | ||
| 549 | chan->omtu = L2CAP_A2MP_DEFAULT_MTU; | ||
| 550 | chan->imtu = L2CAP_A2MP_DEFAULT_MTU; | ||
| 551 | break; | 518 | break; |
| 552 | 519 | ||
| 553 | default: | 520 | default: |
| @@ -595,7 +562,7 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) | |||
| 595 | 562 | ||
| 596 | chan->conn = NULL; | 563 | chan->conn = NULL; |
| 597 | 564 | ||
| 598 | if (chan->chan_type != L2CAP_CHAN_CONN_FIX_A2MP) | 565 | if (chan->scid != L2CAP_CID_A2MP) |
| 599 | hci_conn_drop(conn->hcon); | 566 | hci_conn_drop(conn->hcon); |
| 600 | 567 | ||
| 601 | if (mgr && mgr->bredr_chan == chan) | 568 | if (mgr && mgr->bredr_chan == chan) |
| @@ -642,6 +609,23 @@ void l2cap_chan_del(struct l2cap_chan *chan, int err) | |||
| 642 | return; | 609 | return; |
| 643 | } | 610 | } |
| 644 | 611 | ||
| 612 | void l2cap_conn_update_id_addr(struct hci_conn *hcon) | ||
| 613 | { | ||
| 614 | struct l2cap_conn *conn = hcon->l2cap_data; | ||
| 615 | struct l2cap_chan *chan; | ||
| 616 | |||
| 617 | mutex_lock(&conn->chan_lock); | ||
| 618 | |||
| 619 | list_for_each_entry(chan, &conn->chan_l, list) { | ||
| 620 | l2cap_chan_lock(chan); | ||
| 621 | bacpy(&chan->dst, &hcon->dst); | ||
| 622 | chan->dst_type = bdaddr_type(hcon, hcon->dst_type); | ||
| 623 | l2cap_chan_unlock(chan); | ||
| 624 | } | ||
| 625 | |||
| 626 | mutex_unlock(&conn->chan_lock); | ||
| 627 | } | ||
| 628 | |||
| 645 | static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan) | 629 | static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan) |
| 646 | { | 630 | { |
| 647 | struct l2cap_conn *conn = chan->conn; | 631 | struct l2cap_conn *conn = chan->conn; |
| @@ -681,7 +665,7 @@ static void l2cap_chan_connect_reject(struct l2cap_chan *chan) | |||
| 681 | rsp.scid = cpu_to_le16(chan->dcid); | 665 | rsp.scid = cpu_to_le16(chan->dcid); |
| 682 | rsp.dcid = cpu_to_le16(chan->scid); | 666 | rsp.dcid = cpu_to_le16(chan->scid); |
| 683 | rsp.result = cpu_to_le16(result); | 667 | rsp.result = cpu_to_le16(result); |
| 684 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); | 668 | rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); |
| 685 | 669 | ||
| 686 | l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); | 670 | l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); |
| 687 | } | 671 | } |
| @@ -699,10 +683,7 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) | |||
| 699 | 683 | ||
| 700 | case BT_CONNECTED: | 684 | case BT_CONNECTED: |
| 701 | case BT_CONFIG: | 685 | case BT_CONFIG: |
| 702 | /* ATT uses L2CAP_CHAN_CONN_ORIENTED so we must also | 686 | if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED) { |
| 703 | * check for chan->psm. | ||
| 704 | */ | ||
| 705 | if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && chan->psm) { | ||
| 706 | __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); | 687 | __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); |
| 707 | l2cap_send_disconn_req(chan, reason); | 688 | l2cap_send_disconn_req(chan, reason); |
| 708 | } else | 689 | } else |
| @@ -737,6 +718,7 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) | |||
| 737 | case L2CAP_CHAN_RAW: | 718 | case L2CAP_CHAN_RAW: |
| 738 | switch (chan->sec_level) { | 719 | switch (chan->sec_level) { |
| 739 | case BT_SECURITY_HIGH: | 720 | case BT_SECURITY_HIGH: |
| 721 | case BT_SECURITY_FIPS: | ||
| 740 | return HCI_AT_DEDICATED_BONDING_MITM; | 722 | return HCI_AT_DEDICATED_BONDING_MITM; |
| 741 | case BT_SECURITY_MEDIUM: | 723 | case BT_SECURITY_MEDIUM: |
| 742 | return HCI_AT_DEDICATED_BONDING; | 724 | return HCI_AT_DEDICATED_BONDING; |
| @@ -745,21 +727,23 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) | |||
| 745 | } | 727 | } |
| 746 | break; | 728 | break; |
| 747 | case L2CAP_CHAN_CONN_LESS: | 729 | case L2CAP_CHAN_CONN_LESS: |
| 748 | if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_3DSP)) { | 730 | if (chan->psm == cpu_to_le16(L2CAP_PSM_3DSP)) { |
| 749 | if (chan->sec_level == BT_SECURITY_LOW) | 731 | if (chan->sec_level == BT_SECURITY_LOW) |
| 750 | chan->sec_level = BT_SECURITY_SDP; | 732 | chan->sec_level = BT_SECURITY_SDP; |
| 751 | } | 733 | } |
| 752 | if (chan->sec_level == BT_SECURITY_HIGH) | 734 | if (chan->sec_level == BT_SECURITY_HIGH || |
| 735 | chan->sec_level == BT_SECURITY_FIPS) | ||
| 753 | return HCI_AT_NO_BONDING_MITM; | 736 | return HCI_AT_NO_BONDING_MITM; |
| 754 | else | 737 | else |
| 755 | return HCI_AT_NO_BONDING; | 738 | return HCI_AT_NO_BONDING; |
| 756 | break; | 739 | break; |
| 757 | case L2CAP_CHAN_CONN_ORIENTED: | 740 | case L2CAP_CHAN_CONN_ORIENTED: |
| 758 | if (chan->psm == __constant_cpu_to_le16(L2CAP_PSM_SDP)) { | 741 | if (chan->psm == cpu_to_le16(L2CAP_PSM_SDP)) { |
| 759 | if (chan->sec_level == BT_SECURITY_LOW) | 742 | if (chan->sec_level == BT_SECURITY_LOW) |
| 760 | chan->sec_level = BT_SECURITY_SDP; | 743 | chan->sec_level = BT_SECURITY_SDP; |
| 761 | 744 | ||
| 762 | if (chan->sec_level == BT_SECURITY_HIGH) | 745 | if (chan->sec_level == BT_SECURITY_HIGH || |
| 746 | chan->sec_level == BT_SECURITY_FIPS) | ||
| 763 | return HCI_AT_NO_BONDING_MITM; | 747 | return HCI_AT_NO_BONDING_MITM; |
| 764 | else | 748 | else |
| 765 | return HCI_AT_NO_BONDING; | 749 | return HCI_AT_NO_BONDING; |
| @@ -768,6 +752,7 @@ static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) | |||
| 768 | default: | 752 | default: |
| 769 | switch (chan->sec_level) { | 753 | switch (chan->sec_level) { |
| 770 | case BT_SECURITY_HIGH: | 754 | case BT_SECURITY_HIGH: |
| 755 | case BT_SECURITY_FIPS: | ||
| 771 | return HCI_AT_GENERAL_BONDING_MITM; | 756 | return HCI_AT_GENERAL_BONDING_MITM; |
| 772 | case BT_SECURITY_MEDIUM: | 757 | case BT_SECURITY_MEDIUM: |
| 773 | return HCI_AT_GENERAL_BONDING; | 758 | return HCI_AT_GENERAL_BONDING; |
| @@ -1288,7 +1273,7 @@ static void l2cap_do_start(struct l2cap_chan *chan) | |||
| 1288 | } | 1273 | } |
| 1289 | } else { | 1274 | } else { |
| 1290 | struct l2cap_info_req req; | 1275 | struct l2cap_info_req req; |
| 1291 | req.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); | 1276 | req.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); |
| 1292 | 1277 | ||
| 1293 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; | 1278 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; |
| 1294 | conn->info_ident = l2cap_get_ident(conn); | 1279 | conn->info_ident = l2cap_get_ident(conn); |
| @@ -1330,7 +1315,7 @@ static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err) | |||
| 1330 | __clear_ack_timer(chan); | 1315 | __clear_ack_timer(chan); |
| 1331 | } | 1316 | } |
| 1332 | 1317 | ||
| 1333 | if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { | 1318 | if (chan->scid == L2CAP_CID_A2MP) { |
| 1334 | l2cap_state_change(chan, BT_DISCONN); | 1319 | l2cap_state_change(chan, BT_DISCONN); |
| 1335 | return; | 1320 | return; |
| 1336 | } | 1321 | } |
| @@ -1385,18 +1370,18 @@ static void l2cap_conn_start(struct l2cap_conn *conn) | |||
| 1385 | 1370 | ||
| 1386 | if (l2cap_chan_check_security(chan)) { | 1371 | if (l2cap_chan_check_security(chan)) { |
| 1387 | if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { | 1372 | if (test_bit(FLAG_DEFER_SETUP, &chan->flags)) { |
| 1388 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); | 1373 | rsp.result = cpu_to_le16(L2CAP_CR_PEND); |
| 1389 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHOR_PEND); | 1374 | rsp.status = cpu_to_le16(L2CAP_CS_AUTHOR_PEND); |
| 1390 | chan->ops->defer(chan); | 1375 | chan->ops->defer(chan); |
| 1391 | 1376 | ||
| 1392 | } else { | 1377 | } else { |
| 1393 | l2cap_state_change(chan, BT_CONFIG); | 1378 | l2cap_state_change(chan, BT_CONFIG); |
| 1394 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); | 1379 | rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); |
| 1395 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); | 1380 | rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); |
| 1396 | } | 1381 | } |
| 1397 | } else { | 1382 | } else { |
| 1398 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_PEND); | 1383 | rsp.result = cpu_to_le16(L2CAP_CR_PEND); |
| 1399 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_AUTHEN_PEND); | 1384 | rsp.status = cpu_to_le16(L2CAP_CS_AUTHEN_PEND); |
| 1400 | } | 1385 | } |
| 1401 | 1386 | ||
| 1402 | l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, | 1387 | l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, |
| @@ -1493,8 +1478,6 @@ static void l2cap_le_conn_ready(struct l2cap_conn *conn) | |||
| 1493 | if (!chan) | 1478 | if (!chan) |
| 1494 | goto clean; | 1479 | goto clean; |
| 1495 | 1480 | ||
| 1496 | chan->dcid = L2CAP_CID_ATT; | ||
| 1497 | |||
| 1498 | bacpy(&chan->src, &hcon->src); | 1481 | bacpy(&chan->src, &hcon->src); |
| 1499 | bacpy(&chan->dst, &hcon->dst); | 1482 | bacpy(&chan->dst, &hcon->dst); |
| 1500 | chan->src_type = bdaddr_type(hcon, hcon->src_type); | 1483 | chan->src_type = bdaddr_type(hcon, hcon->src_type); |
| @@ -1528,7 +1511,7 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) | |||
| 1528 | 1511 | ||
| 1529 | l2cap_chan_lock(chan); | 1512 | l2cap_chan_lock(chan); |
| 1530 | 1513 | ||
| 1531 | if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { | 1514 | if (chan->scid == L2CAP_CID_A2MP) { |
| 1532 | l2cap_chan_unlock(chan); | 1515 | l2cap_chan_unlock(chan); |
| 1533 | continue; | 1516 | continue; |
| 1534 | } | 1517 | } |
| @@ -1546,6 +1529,8 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) | |||
| 1546 | } | 1529 | } |
| 1547 | 1530 | ||
| 1548 | mutex_unlock(&conn->chan_lock); | 1531 | mutex_unlock(&conn->chan_lock); |
| 1532 | |||
| 1533 | queue_work(hcon->hdev->workqueue, &conn->pending_rx_work); | ||
| 1549 | } | 1534 | } |
| 1550 | 1535 | ||
| 1551 | /* Notify sockets that we cannot guaranty reliability anymore */ | 1536 | /* Notify sockets that we cannot guaranty reliability anymore */ |
| @@ -1671,6 +1656,9 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) | |||
| 1671 | 1656 | ||
| 1672 | kfree_skb(conn->rx_skb); | 1657 | kfree_skb(conn->rx_skb); |
| 1673 | 1658 | ||
| 1659 | skb_queue_purge(&conn->pending_rx); | ||
| 1660 | flush_work(&conn->pending_rx_work); | ||
| 1661 | |||
| 1674 | l2cap_unregister_all_users(conn); | 1662 | l2cap_unregister_all_users(conn); |
| 1675 | 1663 | ||
| 1676 | mutex_lock(&conn->chan_lock); | 1664 | mutex_lock(&conn->chan_lock); |
| @@ -1718,66 +1706,6 @@ static void security_timeout(struct work_struct *work) | |||
| 1718 | } | 1706 | } |
| 1719 | } | 1707 | } |
| 1720 | 1708 | ||
| 1721 | static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) | ||
| 1722 | { | ||
| 1723 | struct l2cap_conn *conn = hcon->l2cap_data; | ||
| 1724 | struct hci_chan *hchan; | ||
| 1725 | |||
| 1726 | if (conn) | ||
| 1727 | return conn; | ||
| 1728 | |||
| 1729 | hchan = hci_chan_create(hcon); | ||
| 1730 | if (!hchan) | ||
| 1731 | return NULL; | ||
| 1732 | |||
| 1733 | conn = kzalloc(sizeof(struct l2cap_conn), GFP_KERNEL); | ||
| 1734 | if (!conn) { | ||
| 1735 | hci_chan_del(hchan); | ||
| 1736 | return NULL; | ||
| 1737 | } | ||
| 1738 | |||
| 1739 | kref_init(&conn->ref); | ||
| 1740 | hcon->l2cap_data = conn; | ||
| 1741 | conn->hcon = hcon; | ||
| 1742 | hci_conn_get(conn->hcon); | ||
| 1743 | conn->hchan = hchan; | ||
| 1744 | |||
| 1745 | BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); | ||
| 1746 | |||
| 1747 | switch (hcon->type) { | ||
| 1748 | case LE_LINK: | ||
| 1749 | if (hcon->hdev->le_mtu) { | ||
| 1750 | conn->mtu = hcon->hdev->le_mtu; | ||
| 1751 | break; | ||
| 1752 | } | ||
| 1753 | /* fall through */ | ||
| 1754 | default: | ||
| 1755 | conn->mtu = hcon->hdev->acl_mtu; | ||
| 1756 | break; | ||
| 1757 | } | ||
| 1758 | |||
| 1759 | conn->feat_mask = 0; | ||
| 1760 | |||
| 1761 | if (hcon->type == ACL_LINK) | ||
| 1762 | conn->hs_enabled = test_bit(HCI_HS_ENABLED, | ||
| 1763 | &hcon->hdev->dev_flags); | ||
| 1764 | |||
| 1765 | spin_lock_init(&conn->lock); | ||
| 1766 | mutex_init(&conn->chan_lock); | ||
| 1767 | |||
| 1768 | INIT_LIST_HEAD(&conn->chan_l); | ||
| 1769 | INIT_LIST_HEAD(&conn->users); | ||
| 1770 | |||
| 1771 | if (hcon->type == LE_LINK) | ||
| 1772 | INIT_DELAYED_WORK(&conn->security_timer, security_timeout); | ||
| 1773 | else | ||
| 1774 | INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout); | ||
| 1775 | |||
| 1776 | conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; | ||
| 1777 | |||
| 1778 | return conn; | ||
| 1779 | } | ||
| 1780 | |||
| 1781 | static void l2cap_conn_free(struct kref *ref) | 1709 | static void l2cap_conn_free(struct kref *ref) |
| 1782 | { | 1710 | { |
| 1783 | struct l2cap_conn *conn = container_of(ref, struct l2cap_conn, ref); | 1711 | struct l2cap_conn *conn = container_of(ref, struct l2cap_conn, ref); |
| @@ -1848,154 +1776,6 @@ static struct l2cap_chan *l2cap_global_chan_by_psm(int state, __le16 psm, | |||
| 1848 | return c1; | 1776 | return c1; |
| 1849 | } | 1777 | } |
| 1850 | 1778 | ||
| 1851 | static bool is_valid_psm(u16 psm, u8 dst_type) | ||
| 1852 | { | ||
| 1853 | if (!psm) | ||
| 1854 | return false; | ||
| 1855 | |||
| 1856 | if (bdaddr_type_is_le(dst_type)) | ||
| 1857 | return (psm <= 0x00ff); | ||
| 1858 | |||
| 1859 | /* PSM must be odd and lsb of upper byte must be 0 */ | ||
| 1860 | return ((psm & 0x0101) == 0x0001); | ||
| 1861 | } | ||
| 1862 | |||
| 1863 | int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | ||
| 1864 | bdaddr_t *dst, u8 dst_type) | ||
| 1865 | { | ||
| 1866 | struct l2cap_conn *conn; | ||
| 1867 | struct hci_conn *hcon; | ||
| 1868 | struct hci_dev *hdev; | ||
| 1869 | __u8 auth_type; | ||
| 1870 | int err; | ||
| 1871 | |||
| 1872 | BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", &chan->src, dst, | ||
| 1873 | dst_type, __le16_to_cpu(psm)); | ||
| 1874 | |||
| 1875 | hdev = hci_get_route(dst, &chan->src); | ||
| 1876 | if (!hdev) | ||
| 1877 | return -EHOSTUNREACH; | ||
| 1878 | |||
| 1879 | hci_dev_lock(hdev); | ||
| 1880 | |||
| 1881 | l2cap_chan_lock(chan); | ||
| 1882 | |||
| 1883 | if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid && | ||
| 1884 | chan->chan_type != L2CAP_CHAN_RAW) { | ||
| 1885 | err = -EINVAL; | ||
| 1886 | goto done; | ||
| 1887 | } | ||
| 1888 | |||
| 1889 | if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !(psm || cid)) { | ||
| 1890 | err = -EINVAL; | ||
| 1891 | goto done; | ||
| 1892 | } | ||
| 1893 | |||
| 1894 | switch (chan->mode) { | ||
| 1895 | case L2CAP_MODE_BASIC: | ||
| 1896 | break; | ||
| 1897 | case L2CAP_MODE_LE_FLOWCTL: | ||
| 1898 | l2cap_le_flowctl_init(chan); | ||
| 1899 | break; | ||
| 1900 | case L2CAP_MODE_ERTM: | ||
| 1901 | case L2CAP_MODE_STREAMING: | ||
| 1902 | if (!disable_ertm) | ||
| 1903 | break; | ||
| 1904 | /* fall through */ | ||
| 1905 | default: | ||
| 1906 | err = -ENOTSUPP; | ||
| 1907 | goto done; | ||
| 1908 | } | ||
| 1909 | |||
| 1910 | switch (chan->state) { | ||
| 1911 | case BT_CONNECT: | ||
| 1912 | case BT_CONNECT2: | ||
| 1913 | case BT_CONFIG: | ||
| 1914 | /* Already connecting */ | ||
| 1915 | err = 0; | ||
| 1916 | goto done; | ||
| 1917 | |||
| 1918 | case BT_CONNECTED: | ||
| 1919 | /* Already connected */ | ||
| 1920 | err = -EISCONN; | ||
| 1921 | goto done; | ||
| 1922 | |||
| 1923 | case BT_OPEN: | ||
| 1924 | case BT_BOUND: | ||
| 1925 | /* Can connect */ | ||
| 1926 | break; | ||
| 1927 | |||
| 1928 | default: | ||
| 1929 | err = -EBADFD; | ||
| 1930 | goto done; | ||
| 1931 | } | ||
| 1932 | |||
| 1933 | /* Set destination address and psm */ | ||
| 1934 | bacpy(&chan->dst, dst); | ||
| 1935 | chan->dst_type = dst_type; | ||
| 1936 | |||
| 1937 | chan->psm = psm; | ||
| 1938 | chan->dcid = cid; | ||
| 1939 | |||
| 1940 | auth_type = l2cap_get_auth_type(chan); | ||
| 1941 | |||
| 1942 | if (bdaddr_type_is_le(dst_type)) | ||
| 1943 | hcon = hci_connect(hdev, LE_LINK, dst, dst_type, | ||
| 1944 | chan->sec_level, auth_type); | ||
| 1945 | else | ||
| 1946 | hcon = hci_connect(hdev, ACL_LINK, dst, dst_type, | ||
| 1947 | chan->sec_level, auth_type); | ||
| 1948 | |||
| 1949 | if (IS_ERR(hcon)) { | ||
| 1950 | err = PTR_ERR(hcon); | ||
| 1951 | goto done; | ||
| 1952 | } | ||
| 1953 | |||
| 1954 | conn = l2cap_conn_add(hcon); | ||
| 1955 | if (!conn) { | ||
| 1956 | hci_conn_drop(hcon); | ||
| 1957 | err = -ENOMEM; | ||
| 1958 | goto done; | ||
| 1959 | } | ||
| 1960 | |||
| 1961 | if (cid && __l2cap_get_chan_by_dcid(conn, cid)) { | ||
| 1962 | hci_conn_drop(hcon); | ||
| 1963 | err = -EBUSY; | ||
| 1964 | goto done; | ||
| 1965 | } | ||
| 1966 | |||
| 1967 | /* Update source addr of the socket */ | ||
| 1968 | bacpy(&chan->src, &hcon->src); | ||
| 1969 | chan->src_type = bdaddr_type(hcon, hcon->src_type); | ||
| 1970 | |||
| 1971 | l2cap_chan_unlock(chan); | ||
| 1972 | l2cap_chan_add(conn, chan); | ||
| 1973 | l2cap_chan_lock(chan); | ||
| 1974 | |||
| 1975 | /* l2cap_chan_add takes its own ref so we can drop this one */ | ||
| 1976 | hci_conn_drop(hcon); | ||
| 1977 | |||
| 1978 | l2cap_state_change(chan, BT_CONNECT); | ||
| 1979 | __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); | ||
| 1980 | |||
| 1981 | if (hcon->state == BT_CONNECTED) { | ||
| 1982 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { | ||
| 1983 | __clear_chan_timer(chan); | ||
| 1984 | if (l2cap_chan_check_security(chan)) | ||
| 1985 | l2cap_state_change(chan, BT_CONNECTED); | ||
| 1986 | } else | ||
| 1987 | l2cap_do_start(chan); | ||
| 1988 | } | ||
| 1989 | |||
| 1990 | err = 0; | ||
| 1991 | |||
| 1992 | done: | ||
| 1993 | l2cap_chan_unlock(chan); | ||
| 1994 | hci_dev_unlock(hdev); | ||
| 1995 | hci_dev_put(hdev); | ||
| 1996 | return err; | ||
| 1997 | } | ||
| 1998 | |||
| 1999 | static void l2cap_monitor_timeout(struct work_struct *work) | 1779 | static void l2cap_monitor_timeout(struct work_struct *work) |
| 2000 | { | 1780 | { |
| 2001 | struct l2cap_chan *chan = container_of(work, struct l2cap_chan, | 1781 | struct l2cap_chan *chan = container_of(work, struct l2cap_chan, |
| @@ -2654,6 +2434,14 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, | |||
| 2654 | if (IS_ERR(skb)) | 2434 | if (IS_ERR(skb)) |
| 2655 | return PTR_ERR(skb); | 2435 | return PTR_ERR(skb); |
| 2656 | 2436 | ||
| 2437 | /* Channel lock is released before requesting new skb and then | ||
| 2438 | * reacquired thus we need to recheck channel state. | ||
| 2439 | */ | ||
| 2440 | if (chan->state != BT_CONNECTED) { | ||
| 2441 | kfree_skb(skb); | ||
| 2442 | return -ENOTCONN; | ||
| 2443 | } | ||
| 2444 | |||
| 2657 | l2cap_do_send(chan, skb); | 2445 | l2cap_do_send(chan, skb); |
| 2658 | return len; | 2446 | return len; |
| 2659 | } | 2447 | } |
| @@ -2703,6 +2491,14 @@ int l2cap_chan_send(struct l2cap_chan *chan, struct msghdr *msg, size_t len, | |||
| 2703 | if (IS_ERR(skb)) | 2491 | if (IS_ERR(skb)) |
| 2704 | return PTR_ERR(skb); | 2492 | return PTR_ERR(skb); |
| 2705 | 2493 | ||
| 2494 | /* Channel lock is released before requesting new skb and then | ||
| 2495 | * reacquired thus we need to recheck channel state. | ||
| 2496 | */ | ||
| 2497 | if (chan->state != BT_CONNECTED) { | ||
| 2498 | kfree_skb(skb); | ||
| 2499 | return -ENOTCONN; | ||
| 2500 | } | ||
| 2501 | |||
| 2706 | l2cap_do_send(chan, skb); | 2502 | l2cap_do_send(chan, skb); |
| 2707 | err = len; | 2503 | err = len; |
| 2708 | break; | 2504 | break; |
| @@ -3099,9 +2895,9 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code, | |||
| 3099 | lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen); | 2895 | lh->len = cpu_to_le16(L2CAP_CMD_HDR_SIZE + dlen); |
| 3100 | 2896 | ||
| 3101 | if (conn->hcon->type == LE_LINK) | 2897 | if (conn->hcon->type == LE_LINK) |
| 3102 | lh->cid = __constant_cpu_to_le16(L2CAP_CID_LE_SIGNALING); | 2898 | lh->cid = cpu_to_le16(L2CAP_CID_LE_SIGNALING); |
| 3103 | else | 2899 | else |
| 3104 | lh->cid = __constant_cpu_to_le16(L2CAP_CID_SIGNALING); | 2900 | lh->cid = cpu_to_le16(L2CAP_CID_SIGNALING); |
| 3105 | 2901 | ||
| 3106 | cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE); | 2902 | cmd = (struct l2cap_cmd_hdr *) skb_put(skb, L2CAP_CMD_HDR_SIZE); |
| 3107 | cmd->code = code; | 2903 | cmd->code = code; |
| @@ -3214,8 +3010,8 @@ static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan) | |||
| 3214 | efs.stype = chan->local_stype; | 3010 | efs.stype = chan->local_stype; |
| 3215 | efs.msdu = cpu_to_le16(chan->local_msdu); | 3011 | efs.msdu = cpu_to_le16(chan->local_msdu); |
| 3216 | efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); | 3012 | efs.sdu_itime = cpu_to_le32(chan->local_sdu_itime); |
| 3217 | efs.acc_lat = __constant_cpu_to_le32(L2CAP_DEFAULT_ACC_LAT); | 3013 | efs.acc_lat = cpu_to_le32(L2CAP_DEFAULT_ACC_LAT); |
| 3218 | efs.flush_to = __constant_cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO); | 3014 | efs.flush_to = cpu_to_le32(L2CAP_EFS_DEFAULT_FLUSH_TO); |
| 3219 | break; | 3015 | break; |
| 3220 | 3016 | ||
| 3221 | case L2CAP_MODE_STREAMING: | 3017 | case L2CAP_MODE_STREAMING: |
| @@ -3356,8 +3152,8 @@ static void __l2cap_set_ertm_timeouts(struct l2cap_chan *chan, | |||
| 3356 | rfc->retrans_timeout = cpu_to_le16((u16) ertm_to); | 3152 | rfc->retrans_timeout = cpu_to_le16((u16) ertm_to); |
| 3357 | rfc->monitor_timeout = rfc->retrans_timeout; | 3153 | rfc->monitor_timeout = rfc->retrans_timeout; |
| 3358 | } else { | 3154 | } else { |
| 3359 | rfc->retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); | 3155 | rfc->retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO); |
| 3360 | rfc->monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); | 3156 | rfc->monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO); |
| 3361 | } | 3157 | } |
| 3362 | } | 3158 | } |
| 3363 | 3159 | ||
| @@ -3489,7 +3285,7 @@ done: | |||
| 3489 | } | 3285 | } |
| 3490 | 3286 | ||
| 3491 | req->dcid = cpu_to_le16(chan->dcid); | 3287 | req->dcid = cpu_to_le16(chan->dcid); |
| 3492 | req->flags = __constant_cpu_to_le16(0); | 3288 | req->flags = cpu_to_le16(0); |
| 3493 | 3289 | ||
| 3494 | return ptr - data; | 3290 | return ptr - data; |
| 3495 | } | 3291 | } |
| @@ -3703,7 +3499,7 @@ done: | |||
| 3703 | } | 3499 | } |
| 3704 | rsp->scid = cpu_to_le16(chan->dcid); | 3500 | rsp->scid = cpu_to_le16(chan->dcid); |
| 3705 | rsp->result = cpu_to_le16(result); | 3501 | rsp->result = cpu_to_le16(result); |
| 3706 | rsp->flags = __constant_cpu_to_le16(0); | 3502 | rsp->flags = cpu_to_le16(0); |
| 3707 | 3503 | ||
| 3708 | return ptr - data; | 3504 | return ptr - data; |
| 3709 | } | 3505 | } |
| @@ -3812,7 +3608,7 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, | |||
| 3812 | } | 3608 | } |
| 3813 | 3609 | ||
| 3814 | req->dcid = cpu_to_le16(chan->dcid); | 3610 | req->dcid = cpu_to_le16(chan->dcid); |
| 3815 | req->flags = __constant_cpu_to_le16(0); | 3611 | req->flags = cpu_to_le16(0); |
| 3816 | 3612 | ||
| 3817 | return ptr - data; | 3613 | return ptr - data; |
| 3818 | } | 3614 | } |
| @@ -3843,7 +3639,7 @@ void __l2cap_le_connect_rsp_defer(struct l2cap_chan *chan) | |||
| 3843 | rsp.mtu = cpu_to_le16(chan->imtu); | 3639 | rsp.mtu = cpu_to_le16(chan->imtu); |
| 3844 | rsp.mps = cpu_to_le16(chan->mps); | 3640 | rsp.mps = cpu_to_le16(chan->mps); |
| 3845 | rsp.credits = cpu_to_le16(chan->rx_credits); | 3641 | rsp.credits = cpu_to_le16(chan->rx_credits); |
| 3846 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); | 3642 | rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); |
| 3847 | 3643 | ||
| 3848 | l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), | 3644 | l2cap_send_cmd(conn, chan->ident, L2CAP_LE_CONN_RSP, sizeof(rsp), |
| 3849 | &rsp); | 3645 | &rsp); |
| @@ -3858,8 +3654,8 @@ void __l2cap_connect_rsp_defer(struct l2cap_chan *chan) | |||
| 3858 | 3654 | ||
| 3859 | rsp.scid = cpu_to_le16(chan->dcid); | 3655 | rsp.scid = cpu_to_le16(chan->dcid); |
| 3860 | rsp.dcid = cpu_to_le16(chan->scid); | 3656 | rsp.dcid = cpu_to_le16(chan->scid); |
| 3861 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); | 3657 | rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); |
| 3862 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); | 3658 | rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); |
| 3863 | 3659 | ||
| 3864 | if (chan->hs_hcon) | 3660 | if (chan->hs_hcon) |
| 3865 | rsp_code = L2CAP_CREATE_CHAN_RSP; | 3661 | rsp_code = L2CAP_CREATE_CHAN_RSP; |
| @@ -3888,8 +3684,8 @@ static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) | |||
| 3888 | u16 txwin_ext = chan->ack_win; | 3684 | u16 txwin_ext = chan->ack_win; |
| 3889 | struct l2cap_conf_rfc rfc = { | 3685 | struct l2cap_conf_rfc rfc = { |
| 3890 | .mode = chan->mode, | 3686 | .mode = chan->mode, |
| 3891 | .retrans_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO), | 3687 | .retrans_timeout = cpu_to_le16(L2CAP_DEFAULT_RETRANS_TO), |
| 3892 | .monitor_timeout = __constant_cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO), | 3688 | .monitor_timeout = cpu_to_le16(L2CAP_DEFAULT_MONITOR_TO), |
| 3893 | .max_pdu_size = cpu_to_le16(chan->imtu), | 3689 | .max_pdu_size = cpu_to_le16(chan->imtu), |
| 3894 | .txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW), | 3690 | .txwin_size = min_t(u16, chan->ack_win, L2CAP_DEFAULT_TX_WINDOW), |
| 3895 | }; | 3691 | }; |
| @@ -3980,7 +3776,7 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn, | |||
| 3980 | l2cap_chan_lock(pchan); | 3776 | l2cap_chan_lock(pchan); |
| 3981 | 3777 | ||
| 3982 | /* Check if the ACL is secure enough (if not SDP) */ | 3778 | /* Check if the ACL is secure enough (if not SDP) */ |
| 3983 | if (psm != __constant_cpu_to_le16(L2CAP_PSM_SDP) && | 3779 | if (psm != cpu_to_le16(L2CAP_PSM_SDP) && |
| 3984 | !hci_conn_check_link_mode(conn->hcon)) { | 3780 | !hci_conn_check_link_mode(conn->hcon)) { |
| 3985 | conn->disc_reason = HCI_ERROR_AUTH_FAILURE; | 3781 | conn->disc_reason = HCI_ERROR_AUTH_FAILURE; |
| 3986 | result = L2CAP_CR_SEC_BLOCK; | 3782 | result = L2CAP_CR_SEC_BLOCK; |
| @@ -4065,7 +3861,7 @@ sendresp: | |||
| 4065 | 3861 | ||
| 4066 | if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { | 3862 | if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { |
| 4067 | struct l2cap_info_req info; | 3863 | struct l2cap_info_req info; |
| 4068 | info.type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); | 3864 | info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); |
| 4069 | 3865 | ||
| 4070 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; | 3866 | conn->info_state |= L2CAP_INFO_FEAT_MASK_REQ_SENT; |
| 4071 | conn->info_ident = l2cap_get_ident(conn); | 3867 | conn->info_ident = l2cap_get_ident(conn); |
| @@ -4214,7 +4010,7 @@ static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident, | |||
| 4214 | { | 4010 | { |
| 4215 | struct l2cap_cmd_rej_cid rej; | 4011 | struct l2cap_cmd_rej_cid rej; |
| 4216 | 4012 | ||
| 4217 | rej.reason = __constant_cpu_to_le16(L2CAP_REJ_INVALID_CID); | 4013 | rej.reason = cpu_to_le16(L2CAP_REJ_INVALID_CID); |
| 4218 | rej.scid = __cpu_to_le16(scid); | 4014 | rej.scid = __cpu_to_le16(scid); |
| 4219 | rej.dcid = __cpu_to_le16(dcid); | 4015 | rej.dcid = __cpu_to_le16(dcid); |
| 4220 | 4016 | ||
| @@ -4546,8 +4342,8 @@ static inline int l2cap_information_req(struct l2cap_conn *conn, | |||
| 4546 | u8 buf[8]; | 4342 | u8 buf[8]; |
| 4547 | u32 feat_mask = l2cap_feat_mask; | 4343 | u32 feat_mask = l2cap_feat_mask; |
| 4548 | struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; | 4344 | struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) buf; |
| 4549 | rsp->type = __constant_cpu_to_le16(L2CAP_IT_FEAT_MASK); | 4345 | rsp->type = cpu_to_le16(L2CAP_IT_FEAT_MASK); |
| 4550 | rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS); | 4346 | rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); |
| 4551 | if (!disable_ertm) | 4347 | if (!disable_ertm) |
| 4552 | feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING | 4348 | feat_mask |= L2CAP_FEAT_ERTM | L2CAP_FEAT_STREAMING |
| 4553 | | L2CAP_FEAT_FCS; | 4349 | | L2CAP_FEAT_FCS; |
| @@ -4567,15 +4363,15 @@ static inline int l2cap_information_req(struct l2cap_conn *conn, | |||
| 4567 | else | 4363 | else |
| 4568 | l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP; | 4364 | l2cap_fixed_chan[0] &= ~L2CAP_FC_A2MP; |
| 4569 | 4365 | ||
| 4570 | rsp->type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN); | 4366 | rsp->type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); |
| 4571 | rsp->result = __constant_cpu_to_le16(L2CAP_IR_SUCCESS); | 4367 | rsp->result = cpu_to_le16(L2CAP_IR_SUCCESS); |
| 4572 | memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan)); | 4368 | memcpy(rsp->data, l2cap_fixed_chan, sizeof(l2cap_fixed_chan)); |
| 4573 | l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf), | 4369 | l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(buf), |
| 4574 | buf); | 4370 | buf); |
| 4575 | } else { | 4371 | } else { |
| 4576 | struct l2cap_info_rsp rsp; | 4372 | struct l2cap_info_rsp rsp; |
| 4577 | rsp.type = cpu_to_le16(type); | 4373 | rsp.type = cpu_to_le16(type); |
| 4578 | rsp.result = __constant_cpu_to_le16(L2CAP_IR_NOTSUPP); | 4374 | rsp.result = cpu_to_le16(L2CAP_IR_NOTSUPP); |
| 4579 | l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp), | 4375 | l2cap_send_cmd(conn, cmd->ident, L2CAP_INFO_RSP, sizeof(rsp), |
| 4580 | &rsp); | 4376 | &rsp); |
| 4581 | } | 4377 | } |
| @@ -4620,7 +4416,7 @@ static inline int l2cap_information_rsp(struct l2cap_conn *conn, | |||
| 4620 | 4416 | ||
| 4621 | if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { | 4417 | if (conn->feat_mask & L2CAP_FEAT_FIXED_CHAN) { |
| 4622 | struct l2cap_info_req req; | 4418 | struct l2cap_info_req req; |
| 4623 | req.type = __constant_cpu_to_le16(L2CAP_IT_FIXED_CHAN); | 4419 | req.type = cpu_to_le16(L2CAP_IT_FIXED_CHAN); |
| 4624 | 4420 | ||
| 4625 | conn->info_ident = l2cap_get_ident(conn); | 4421 | conn->info_ident = l2cap_get_ident(conn); |
| 4626 | 4422 | ||
| @@ -4714,8 +4510,8 @@ static int l2cap_create_channel_req(struct l2cap_conn *conn, | |||
| 4714 | error: | 4510 | error: |
| 4715 | rsp.dcid = 0; | 4511 | rsp.dcid = 0; |
| 4716 | rsp.scid = cpu_to_le16(scid); | 4512 | rsp.scid = cpu_to_le16(scid); |
| 4717 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_BAD_AMP); | 4513 | rsp.result = cpu_to_le16(L2CAP_CR_BAD_AMP); |
| 4718 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); | 4514 | rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); |
| 4719 | 4515 | ||
| 4720 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP, | 4516 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CREATE_CHAN_RSP, |
| 4721 | sizeof(rsp), &rsp); | 4517 | sizeof(rsp), &rsp); |
| @@ -4779,7 +4575,7 @@ static void l2cap_send_move_chan_cfm_icid(struct l2cap_conn *conn, u16 icid) | |||
| 4779 | BT_DBG("conn %p, icid 0x%4.4x", conn, icid); | 4575 | BT_DBG("conn %p, icid 0x%4.4x", conn, icid); |
| 4780 | 4576 | ||
| 4781 | cfm.icid = cpu_to_le16(icid); | 4577 | cfm.icid = cpu_to_le16(icid); |
| 4782 | cfm.result = __constant_cpu_to_le16(L2CAP_MC_UNCONFIRMED); | 4578 | cfm.result = cpu_to_le16(L2CAP_MC_UNCONFIRMED); |
| 4783 | 4579 | ||
| 4784 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_MOVE_CHAN_CFM, | 4580 | l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_MOVE_CHAN_CFM, |
| 4785 | sizeof(cfm), &cfm); | 4581 | sizeof(cfm), &cfm); |
| @@ -4962,12 +4758,12 @@ static void l2cap_do_create(struct l2cap_chan *chan, int result, | |||
| 4962 | 4758 | ||
| 4963 | if (result == L2CAP_CR_SUCCESS) { | 4759 | if (result == L2CAP_CR_SUCCESS) { |
| 4964 | /* Send successful response */ | 4760 | /* Send successful response */ |
| 4965 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_SUCCESS); | 4761 | rsp.result = cpu_to_le16(L2CAP_CR_SUCCESS); |
| 4966 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); | 4762 | rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); |
| 4967 | } else { | 4763 | } else { |
| 4968 | /* Send negative response */ | 4764 | /* Send negative response */ |
| 4969 | rsp.result = __constant_cpu_to_le16(L2CAP_CR_NO_MEM); | 4765 | rsp.result = cpu_to_le16(L2CAP_CR_NO_MEM); |
| 4970 | rsp.status = __constant_cpu_to_le16(L2CAP_CS_NO_INFO); | 4766 | rsp.status = cpu_to_le16(L2CAP_CS_NO_INFO); |
| 4971 | } | 4767 | } |
| 4972 | 4768 | ||
| 4973 | l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_RSP, | 4769 | l2cap_send_cmd(chan->conn, chan->ident, L2CAP_CREATE_CHAN_RSP, |
| @@ -5095,7 +4891,7 @@ static inline int l2cap_move_channel_req(struct l2cap_conn *conn, | |||
| 5095 | chan = l2cap_get_chan_by_dcid(conn, icid); | 4891 | chan = l2cap_get_chan_by_dcid(conn, icid); |
| 5096 | if (!chan) { | 4892 | if (!chan) { |
| 5097 | rsp.icid = cpu_to_le16(icid); | 4893 | rsp.icid = cpu_to_le16(icid); |
| 5098 | rsp.result = __constant_cpu_to_le16(L2CAP_MR_NOT_ALLOWED); | 4894 | rsp.result = cpu_to_le16(L2CAP_MR_NOT_ALLOWED); |
| 5099 | l2cap_send_cmd(conn, cmd->ident, L2CAP_MOVE_CHAN_RSP, | 4895 | l2cap_send_cmd(conn, cmd->ident, L2CAP_MOVE_CHAN_RSP, |
| 5100 | sizeof(rsp), &rsp); | 4896 | sizeof(rsp), &rsp); |
| 5101 | return 0; | 4897 | return 0; |
| @@ -5439,9 +5235,9 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, | |||
| 5439 | 5235 | ||
| 5440 | err = l2cap_check_conn_param(min, max, latency, to_multiplier); | 5236 | err = l2cap_check_conn_param(min, max, latency, to_multiplier); |
| 5441 | if (err) | 5237 | if (err) |
| 5442 | rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); | 5238 | rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_REJECTED); |
| 5443 | else | 5239 | else |
| 5444 | rsp.result = __constant_cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED); | 5240 | rsp.result = cpu_to_le16(L2CAP_CONN_PARAM_ACCEPTED); |
| 5445 | 5241 | ||
| 5446 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, | 5242 | l2cap_send_cmd(conn, cmd->ident, L2CAP_CONN_PARAM_UPDATE_RSP, |
| 5447 | sizeof(rsp), &rsp); | 5243 | sizeof(rsp), &rsp); |
| @@ -5709,7 +5505,7 @@ static inline int l2cap_le_credits(struct l2cap_conn *conn, | |||
| 5709 | { | 5505 | { |
| 5710 | struct l2cap_le_credits *pkt; | 5506 | struct l2cap_le_credits *pkt; |
| 5711 | struct l2cap_chan *chan; | 5507 | struct l2cap_chan *chan; |
| 5712 | u16 cid, credits; | 5508 | u16 cid, credits, max_credits; |
| 5713 | 5509 | ||
| 5714 | if (cmd_len != sizeof(*pkt)) | 5510 | if (cmd_len != sizeof(*pkt)) |
| 5715 | return -EPROTO; | 5511 | return -EPROTO; |
| @@ -5724,6 +5520,17 @@ static inline int l2cap_le_credits(struct l2cap_conn *conn, | |||
| 5724 | if (!chan) | 5520 | if (!chan) |
| 5725 | return -EBADSLT; | 5521 | return -EBADSLT; |
| 5726 | 5522 | ||
| 5523 | max_credits = LE_FLOWCTL_MAX_CREDITS - chan->tx_credits; | ||
| 5524 | if (credits > max_credits) { | ||
| 5525 | BT_ERR("LE credits overflow"); | ||
| 5526 | l2cap_send_disconn_req(chan, ECONNRESET); | ||
| 5527 | |||
| 5528 | /* Return 0 so that we don't trigger an unnecessary | ||
| 5529 | * command reject packet. | ||
| 5530 | */ | ||
| 5531 | return 0; | ||
| 5532 | } | ||
| 5533 | |||
| 5727 | chan->tx_credits += credits; | 5534 | chan->tx_credits += credits; |
| 5728 | 5535 | ||
| 5729 | while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) { | 5536 | while (chan->tx_credits && !skb_queue_empty(&chan->tx_q)) { |
| @@ -5770,17 +5577,6 @@ static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, | |||
| 5770 | { | 5577 | { |
| 5771 | int err = 0; | 5578 | int err = 0; |
| 5772 | 5579 | ||
| 5773 | if (!enable_lecoc) { | ||
| 5774 | switch (cmd->code) { | ||
| 5775 | case L2CAP_LE_CONN_REQ: | ||
| 5776 | case L2CAP_LE_CONN_RSP: | ||
| 5777 | case L2CAP_LE_CREDITS: | ||
| 5778 | case L2CAP_DISCONN_REQ: | ||
| 5779 | case L2CAP_DISCONN_RSP: | ||
| 5780 | return -EINVAL; | ||
| 5781 | } | ||
| 5782 | } | ||
| 5783 | |||
| 5784 | switch (cmd->code) { | 5580 | switch (cmd->code) { |
| 5785 | case L2CAP_COMMAND_REJ: | 5581 | case L2CAP_COMMAND_REJ: |
| 5786 | l2cap_le_command_rej(conn, cmd, cmd_len, data); | 5582 | l2cap_le_command_rej(conn, cmd, cmd_len, data); |
| @@ -5854,7 +5650,7 @@ static inline void l2cap_le_sig_channel(struct l2cap_conn *conn, | |||
| 5854 | 5650 | ||
| 5855 | BT_ERR("Wrong link type (%d)", err); | 5651 | BT_ERR("Wrong link type (%d)", err); |
| 5856 | 5652 | ||
| 5857 | rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); | 5653 | rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); |
| 5858 | l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, | 5654 | l2cap_send_cmd(conn, cmd->ident, L2CAP_COMMAND_REJ, |
| 5859 | sizeof(rej), &rej); | 5655 | sizeof(rej), &rej); |
| 5860 | } | 5656 | } |
| @@ -5899,7 +5695,7 @@ static inline void l2cap_sig_channel(struct l2cap_conn *conn, | |||
| 5899 | 5695 | ||
| 5900 | BT_ERR("Wrong link type (%d)", err); | 5696 | BT_ERR("Wrong link type (%d)", err); |
| 5901 | 5697 | ||
| 5902 | rej.reason = __constant_cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); | 5698 | rej.reason = cpu_to_le16(L2CAP_REJ_NOT_UNDERSTOOD); |
| 5903 | l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, | 5699 | l2cap_send_cmd(conn, cmd.ident, L2CAP_COMMAND_REJ, |
| 5904 | sizeof(rej), &rej); | 5700 | sizeof(rej), &rej); |
| 5905 | } | 5701 | } |
| @@ -6871,6 +6667,7 @@ static int l2cap_le_data_rcv(struct l2cap_chan *chan, struct sk_buff *skb) | |||
| 6871 | 6667 | ||
| 6872 | if (!chan->rx_credits) { | 6668 | if (!chan->rx_credits) { |
| 6873 | BT_ERR("No credits to receive LE L2CAP data"); | 6669 | BT_ERR("No credits to receive LE L2CAP data"); |
| 6670 | l2cap_send_disconn_req(chan, ECONNRESET); | ||
| 6874 | return -ENOBUFS; | 6671 | return -ENOBUFS; |
| 6875 | } | 6672 | } |
| 6876 | 6673 | ||
| @@ -6995,8 +6792,10 @@ static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid, | |||
| 6995 | * But we don't have any other choice. L2CAP doesn't | 6792 | * But we don't have any other choice. L2CAP doesn't |
| 6996 | * provide flow control mechanism. */ | 6793 | * provide flow control mechanism. */ |
| 6997 | 6794 | ||
| 6998 | if (chan->imtu < skb->len) | 6795 | if (chan->imtu < skb->len) { |
| 6796 | BT_ERR("Dropping L2CAP data: receive buffer overflow"); | ||
| 6999 | goto drop; | 6797 | goto drop; |
| 6798 | } | ||
| 7000 | 6799 | ||
| 7001 | if (!chan->ops->recv(chan, skb)) | 6800 | if (!chan->ops->recv(chan, skb)) |
| 7002 | goto done; | 6801 | goto done; |
| @@ -7084,9 +6883,16 @@ drop: | |||
| 7084 | static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) | 6883 | static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) |
| 7085 | { | 6884 | { |
| 7086 | struct l2cap_hdr *lh = (void *) skb->data; | 6885 | struct l2cap_hdr *lh = (void *) skb->data; |
| 6886 | struct hci_conn *hcon = conn->hcon; | ||
| 7087 | u16 cid, len; | 6887 | u16 cid, len; |
| 7088 | __le16 psm; | 6888 | __le16 psm; |
| 7089 | 6889 | ||
| 6890 | if (hcon->state != BT_CONNECTED) { | ||
| 6891 | BT_DBG("queueing pending rx skb"); | ||
| 6892 | skb_queue_tail(&conn->pending_rx, skb); | ||
| 6893 | return; | ||
| 6894 | } | ||
| 6895 | |||
| 7090 | skb_pull(skb, L2CAP_HDR_SIZE); | 6896 | skb_pull(skb, L2CAP_HDR_SIZE); |
| 7091 | cid = __le16_to_cpu(lh->cid); | 6897 | cid = __le16_to_cpu(lh->cid); |
| 7092 | len = __le16_to_cpu(lh->len); | 6898 | len = __le16_to_cpu(lh->len); |
| @@ -7132,6 +6938,247 @@ static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) | |||
| 7132 | } | 6938 | } |
| 7133 | } | 6939 | } |
| 7134 | 6940 | ||
| 6941 | static void process_pending_rx(struct work_struct *work) | ||
| 6942 | { | ||
| 6943 | struct l2cap_conn *conn = container_of(work, struct l2cap_conn, | ||
| 6944 | pending_rx_work); | ||
| 6945 | struct sk_buff *skb; | ||
| 6946 | |||
| 6947 | BT_DBG(""); | ||
| 6948 | |||
| 6949 | while ((skb = skb_dequeue(&conn->pending_rx))) | ||
| 6950 | l2cap_recv_frame(conn, skb); | ||
| 6951 | } | ||
| 6952 | |||
| 6953 | static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) | ||
| 6954 | { | ||
| 6955 | struct l2cap_conn *conn = hcon->l2cap_data; | ||
| 6956 | struct hci_chan *hchan; | ||
| 6957 | |||
| 6958 | if (conn) | ||
| 6959 | return conn; | ||
| 6960 | |||
| 6961 | hchan = hci_chan_create(hcon); | ||
| 6962 | if (!hchan) | ||
| 6963 | return NULL; | ||
| 6964 | |||
| 6965 | conn = kzalloc(sizeof(struct l2cap_conn), GFP_KERNEL); | ||
| 6966 | if (!conn) { | ||
| 6967 | hci_chan_del(hchan); | ||
| 6968 | return NULL; | ||
| 6969 | } | ||
| 6970 | |||
| 6971 | kref_init(&conn->ref); | ||
| 6972 | hcon->l2cap_data = conn; | ||
| 6973 | conn->hcon = hcon; | ||
| 6974 | hci_conn_get(conn->hcon); | ||
| 6975 | conn->hchan = hchan; | ||
| 6976 | |||
| 6977 | BT_DBG("hcon %p conn %p hchan %p", hcon, conn, hchan); | ||
| 6978 | |||
| 6979 | switch (hcon->type) { | ||
| 6980 | case LE_LINK: | ||
| 6981 | if (hcon->hdev->le_mtu) { | ||
| 6982 | conn->mtu = hcon->hdev->le_mtu; | ||
| 6983 | break; | ||
| 6984 | } | ||
| 6985 | /* fall through */ | ||
| 6986 | default: | ||
| 6987 | conn->mtu = hcon->hdev->acl_mtu; | ||
| 6988 | break; | ||
| 6989 | } | ||
| 6990 | |||
| 6991 | conn->feat_mask = 0; | ||
| 6992 | |||
| 6993 | if (hcon->type == ACL_LINK) | ||
| 6994 | conn->hs_enabled = test_bit(HCI_HS_ENABLED, | ||
| 6995 | &hcon->hdev->dev_flags); | ||
| 6996 | |||
| 6997 | spin_lock_init(&conn->lock); | ||
| 6998 | mutex_init(&conn->chan_lock); | ||
| 6999 | |||
| 7000 | INIT_LIST_HEAD(&conn->chan_l); | ||
| 7001 | INIT_LIST_HEAD(&conn->users); | ||
| 7002 | |||
| 7003 | if (hcon->type == LE_LINK) | ||
| 7004 | INIT_DELAYED_WORK(&conn->security_timer, security_timeout); | ||
| 7005 | else | ||
| 7006 | INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout); | ||
| 7007 | |||
| 7008 | skb_queue_head_init(&conn->pending_rx); | ||
| 7009 | INIT_WORK(&conn->pending_rx_work, process_pending_rx); | ||
| 7010 | |||
| 7011 | conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; | ||
| 7012 | |||
| 7013 | return conn; | ||
| 7014 | } | ||
| 7015 | |||
| 7016 | static bool is_valid_psm(u16 psm, u8 dst_type) { | ||
| 7017 | if (!psm) | ||
| 7018 | return false; | ||
| 7019 | |||
| 7020 | if (bdaddr_type_is_le(dst_type)) | ||
| 7021 | return (psm <= 0x00ff); | ||
| 7022 | |||
| 7023 | /* PSM must be odd and lsb of upper byte must be 0 */ | ||
| 7024 | return ((psm & 0x0101) == 0x0001); | ||
| 7025 | } | ||
| 7026 | |||
| 7027 | int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, | ||
| 7028 | bdaddr_t *dst, u8 dst_type) | ||
| 7029 | { | ||
| 7030 | struct l2cap_conn *conn; | ||
| 7031 | struct hci_conn *hcon; | ||
| 7032 | struct hci_dev *hdev; | ||
| 7033 | __u8 auth_type; | ||
| 7034 | int err; | ||
| 7035 | |||
| 7036 | BT_DBG("%pMR -> %pMR (type %u) psm 0x%2.2x", &chan->src, dst, | ||
| 7037 | dst_type, __le16_to_cpu(psm)); | ||
| 7038 | |||
| 7039 | hdev = hci_get_route(dst, &chan->src); | ||
| 7040 | if (!hdev) | ||
| 7041 | return -EHOSTUNREACH; | ||
| 7042 | |||
| 7043 | hci_dev_lock(hdev); | ||
| 7044 | |||
| 7045 | l2cap_chan_lock(chan); | ||
| 7046 | |||
| 7047 | if (!is_valid_psm(__le16_to_cpu(psm), dst_type) && !cid && | ||
| 7048 | chan->chan_type != L2CAP_CHAN_RAW) { | ||
| 7049 | err = -EINVAL; | ||
| 7050 | goto done; | ||
| 7051 | } | ||
| 7052 | |||
| 7053 | if (chan->chan_type == L2CAP_CHAN_CONN_ORIENTED && !psm) { | ||
| 7054 | err = -EINVAL; | ||
| 7055 | goto done; | ||
| 7056 | } | ||
| 7057 | |||
| 7058 | if (chan->chan_type == L2CAP_CHAN_FIXED && !cid) { | ||
| 7059 | err = -EINVAL; | ||
| 7060 | goto done; | ||
| 7061 | } | ||
| 7062 | |||
| 7063 | switch (chan->mode) { | ||
| 7064 | case L2CAP_MODE_BASIC: | ||
| 7065 | break; | ||
| 7066 | case L2CAP_MODE_LE_FLOWCTL: | ||
| 7067 | l2cap_le_flowctl_init(chan); | ||
| 7068 | break; | ||
| 7069 | case L2CAP_MODE_ERTM: | ||
| 7070 | case L2CAP_MODE_STREAMING: | ||
| 7071 | if (!disable_ertm) | ||
| 7072 | break; | ||
| 7073 | /* fall through */ | ||
| 7074 | default: | ||
| 7075 | err = -ENOTSUPP; | ||
| 7076 | goto done; | ||
| 7077 | } | ||
| 7078 | |||
| 7079 | switch (chan->state) { | ||
| 7080 | case BT_CONNECT: | ||
| 7081 | case BT_CONNECT2: | ||
| 7082 | case BT_CONFIG: | ||
| 7083 | /* Already connecting */ | ||
| 7084 | err = 0; | ||
| 7085 | goto done; | ||
| 7086 | |||
| 7087 | case BT_CONNECTED: | ||
| 7088 | /* Already connected */ | ||
| 7089 | err = -EISCONN; | ||
| 7090 | goto done; | ||
| 7091 | |||
| 7092 | case BT_OPEN: | ||
| 7093 | case BT_BOUND: | ||
| 7094 | /* Can connect */ | ||
| 7095 | break; | ||
| 7096 | |||
| 7097 | default: | ||
| 7098 | err = -EBADFD; | ||
| 7099 | goto done; | ||
| 7100 | } | ||
| 7101 | |||
| 7102 | /* Set destination address and psm */ | ||
| 7103 | bacpy(&chan->dst, dst); | ||
| 7104 | chan->dst_type = dst_type; | ||
| 7105 | |||
| 7106 | chan->psm = psm; | ||
| 7107 | chan->dcid = cid; | ||
| 7108 | |||
| 7109 | auth_type = l2cap_get_auth_type(chan); | ||
| 7110 | |||
| 7111 | if (bdaddr_type_is_le(dst_type)) { | ||
| 7112 | /* Convert from L2CAP channel address type to HCI address type | ||
| 7113 | */ | ||
| 7114 | if (dst_type == BDADDR_LE_PUBLIC) | ||
| 7115 | dst_type = ADDR_LE_DEV_PUBLIC; | ||
| 7116 | else | ||
| 7117 | dst_type = ADDR_LE_DEV_RANDOM; | ||
| 7118 | |||
| 7119 | hcon = hci_connect_le(hdev, dst, dst_type, chan->sec_level, | ||
| 7120 | auth_type); | ||
| 7121 | } else { | ||
| 7122 | hcon = hci_connect_acl(hdev, dst, chan->sec_level, auth_type); | ||
| 7123 | } | ||
| 7124 | |||
| 7125 | if (IS_ERR(hcon)) { | ||
| 7126 | err = PTR_ERR(hcon); | ||
| 7127 | goto done; | ||
| 7128 | } | ||
| 7129 | |||
| 7130 | conn = l2cap_conn_add(hcon); | ||
| 7131 | if (!conn) { | ||
| 7132 | hci_conn_drop(hcon); | ||
| 7133 | err = -ENOMEM; | ||
| 7134 | goto done; | ||
| 7135 | } | ||
| 7136 | |||
| 7137 | if (cid && __l2cap_get_chan_by_dcid(conn, cid)) { | ||
| 7138 | hci_conn_drop(hcon); | ||
| 7139 | err = -EBUSY; | ||
| 7140 | goto done; | ||
| 7141 | } | ||
| 7142 | |||
| 7143 | /* Update source addr of the socket */ | ||
| 7144 | bacpy(&chan->src, &hcon->src); | ||
| 7145 | chan->src_type = bdaddr_type(hcon, hcon->src_type); | ||
| 7146 | |||
| 7147 | l2cap_chan_unlock(chan); | ||
| 7148 | l2cap_chan_add(conn, chan); | ||
| 7149 | l2cap_chan_lock(chan); | ||
| 7150 | |||
| 7151 | /* l2cap_chan_add takes its own ref so we can drop this one */ | ||
| 7152 | hci_conn_drop(hcon); | ||
| 7153 | |||
| 7154 | l2cap_state_change(chan, BT_CONNECT); | ||
| 7155 | __set_chan_timer(chan, chan->ops->get_sndtimeo(chan)); | ||
| 7156 | |||
| 7157 | /* Release chan->sport so that it can be reused by other | ||
| 7158 | * sockets (as it's only used for listening sockets). | ||
| 7159 | */ | ||
| 7160 | write_lock(&chan_list_lock); | ||
| 7161 | chan->sport = 0; | ||
| 7162 | write_unlock(&chan_list_lock); | ||
| 7163 | |||
| 7164 | if (hcon->state == BT_CONNECTED) { | ||
| 7165 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { | ||
| 7166 | __clear_chan_timer(chan); | ||
| 7167 | if (l2cap_chan_check_security(chan)) | ||
| 7168 | l2cap_state_change(chan, BT_CONNECTED); | ||
| 7169 | } else | ||
| 7170 | l2cap_do_start(chan); | ||
| 7171 | } | ||
| 7172 | |||
| 7173 | err = 0; | ||
| 7174 | |||
| 7175 | done: | ||
| 7176 | l2cap_chan_unlock(chan); | ||
| 7177 | hci_dev_unlock(hdev); | ||
| 7178 | hci_dev_put(hdev); | ||
| 7179 | return err; | ||
| 7180 | } | ||
| 7181 | |||
| 7135 | /* ---- L2CAP interface with lower layer (HCI) ---- */ | 7182 | /* ---- L2CAP interface with lower layer (HCI) ---- */ |
| 7136 | 7183 | ||
| 7137 | int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) | 7184 | int l2cap_connect_ind(struct hci_dev *hdev, bdaddr_t *bdaddr) |
| @@ -7206,7 +7253,8 @@ static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) | |||
| 7206 | if (encrypt == 0x00) { | 7253 | if (encrypt == 0x00) { |
| 7207 | if (chan->sec_level == BT_SECURITY_MEDIUM) { | 7254 | if (chan->sec_level == BT_SECURITY_MEDIUM) { |
| 7208 | __set_chan_timer(chan, L2CAP_ENC_TIMEOUT); | 7255 | __set_chan_timer(chan, L2CAP_ENC_TIMEOUT); |
| 7209 | } else if (chan->sec_level == BT_SECURITY_HIGH) | 7256 | } else if (chan->sec_level == BT_SECURITY_HIGH || |
| 7257 | chan->sec_level == BT_SECURITY_FIPS) | ||
| 7210 | l2cap_chan_close(chan, ECONNREFUSED); | 7258 | l2cap_chan_close(chan, ECONNREFUSED); |
| 7211 | } else { | 7259 | } else { |
| 7212 | if (chan->sec_level == BT_SECURITY_MEDIUM) | 7260 | if (chan->sec_level == BT_SECURITY_MEDIUM) |
| @@ -7226,7 +7274,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
| 7226 | 7274 | ||
| 7227 | if (hcon->type == LE_LINK) { | 7275 | if (hcon->type == LE_LINK) { |
| 7228 | if (!status && encrypt) | 7276 | if (!status && encrypt) |
| 7229 | smp_distribute_keys(conn, 0); | 7277 | smp_distribute_keys(conn); |
| 7230 | cancel_delayed_work(&conn->security_timer); | 7278 | cancel_delayed_work(&conn->security_timer); |
| 7231 | } | 7279 | } |
| 7232 | 7280 | ||
| @@ -7238,7 +7286,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) | |||
| 7238 | BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid, | 7286 | BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid, |
| 7239 | state_to_string(chan->state)); | 7287 | state_to_string(chan->state)); |
| 7240 | 7288 | ||
| 7241 | if (chan->chan_type == L2CAP_CHAN_CONN_FIX_A2MP) { | 7289 | if (chan->scid == L2CAP_CID_A2MP) { |
| 7242 | l2cap_chan_unlock(chan); | 7290 | l2cap_chan_unlock(chan); |
| 7243 | continue; | 7291 | continue; |
| 7244 | } | 7292 | } |
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index d58f76bcebd1..ef5e5b04f34f 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
| @@ -36,8 +36,6 @@ | |||
| 36 | 36 | ||
| 37 | #include "smp.h" | 37 | #include "smp.h" |
| 38 | 38 | ||
| 39 | bool enable_lecoc; | ||
| 40 | |||
| 41 | static struct bt_sock_list l2cap_sk_list = { | 39 | static struct bt_sock_list l2cap_sk_list = { |
| 42 | .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock) | 40 | .lock = __RW_LOCK_UNLOCKED(l2cap_sk_list.lock) |
| 43 | }; | 41 | }; |
| @@ -101,12 +99,19 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) | |||
| 101 | if (!bdaddr_type_is_valid(la.l2_bdaddr_type)) | 99 | if (!bdaddr_type_is_valid(la.l2_bdaddr_type)) |
| 102 | return -EINVAL; | 100 | return -EINVAL; |
| 103 | 101 | ||
| 102 | if (la.l2_cid) { | ||
| 103 | /* When the socket gets created it defaults to | ||
| 104 | * CHAN_CONN_ORIENTED, so we need to overwrite the | ||
| 105 | * default here. | ||
| 106 | */ | ||
| 107 | chan->chan_type = L2CAP_CHAN_FIXED; | ||
| 108 | chan->omtu = L2CAP_DEFAULT_MTU; | ||
| 109 | } | ||
| 110 | |||
| 104 | if (bdaddr_type_is_le(la.l2_bdaddr_type)) { | 111 | if (bdaddr_type_is_le(la.l2_bdaddr_type)) { |
| 105 | if (!enable_lecoc && la.l2_psm) | ||
| 106 | return -EINVAL; | ||
| 107 | /* We only allow ATT user space socket */ | 112 | /* We only allow ATT user space socket */ |
| 108 | if (la.l2_cid && | 113 | if (la.l2_cid && |
| 109 | la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT)) | 114 | la.l2_cid != cpu_to_le16(L2CAP_CID_ATT)) |
| 110 | return -EINVAL; | 115 | return -EINVAL; |
| 111 | } | 116 | } |
| 112 | 117 | ||
| @@ -204,7 +209,7 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, | |||
| 204 | * ATT. Anything else is an invalid combination. | 209 | * ATT. Anything else is an invalid combination. |
| 205 | */ | 210 | */ |
| 206 | if (chan->scid != L2CAP_CID_ATT || | 211 | if (chan->scid != L2CAP_CID_ATT || |
| 207 | la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT)) | 212 | la.l2_cid != cpu_to_le16(L2CAP_CID_ATT)) |
| 208 | return -EINVAL; | 213 | return -EINVAL; |
| 209 | 214 | ||
| 210 | /* We don't have the hdev available here to make a | 215 | /* We don't have the hdev available here to make a |
| @@ -220,11 +225,9 @@ static int l2cap_sock_connect(struct socket *sock, struct sockaddr *addr, | |||
| 220 | return -EINVAL; | 225 | return -EINVAL; |
| 221 | 226 | ||
| 222 | if (bdaddr_type_is_le(la.l2_bdaddr_type)) { | 227 | if (bdaddr_type_is_le(la.l2_bdaddr_type)) { |
| 223 | if (!enable_lecoc && la.l2_psm) | ||
| 224 | return -EINVAL; | ||
| 225 | /* We only allow ATT user space socket */ | 228 | /* We only allow ATT user space socket */ |
| 226 | if (la.l2_cid && | 229 | if (la.l2_cid && |
| 227 | la.l2_cid != __constant_cpu_to_le16(L2CAP_CID_ATT)) | 230 | la.l2_cid != cpu_to_le16(L2CAP_CID_ATT)) |
| 228 | return -EINVAL; | 231 | return -EINVAL; |
| 229 | } | 232 | } |
| 230 | 233 | ||
| @@ -357,17 +360,21 @@ static int l2cap_sock_getname(struct socket *sock, struct sockaddr *addr, | |||
| 357 | 360 | ||
| 358 | BT_DBG("sock %p, sk %p", sock, sk); | 361 | BT_DBG("sock %p, sk %p", sock, sk); |
| 359 | 362 | ||
| 363 | if (peer && sk->sk_state != BT_CONNECTED && | ||
| 364 | sk->sk_state != BT_CONNECT && sk->sk_state != BT_CONNECT2) | ||
| 365 | return -ENOTCONN; | ||
| 366 | |||
| 360 | memset(la, 0, sizeof(struct sockaddr_l2)); | 367 | memset(la, 0, sizeof(struct sockaddr_l2)); |
| 361 | addr->sa_family = AF_BLUETOOTH; | 368 | addr->sa_family = AF_BLUETOOTH; |
| 362 | *len = sizeof(struct sockaddr_l2); | 369 | *len = sizeof(struct sockaddr_l2); |
| 363 | 370 | ||
| 371 | la->l2_psm = chan->psm; | ||
| 372 | |||
| 364 | if (peer) { | 373 | if (peer) { |
| 365 | la->l2_psm = chan->psm; | ||
| 366 | bacpy(&la->l2_bdaddr, &chan->dst); | 374 | bacpy(&la->l2_bdaddr, &chan->dst); |
| 367 | la->l2_cid = cpu_to_le16(chan->dcid); | 375 | la->l2_cid = cpu_to_le16(chan->dcid); |
| 368 | la->l2_bdaddr_type = chan->dst_type; | 376 | la->l2_bdaddr_type = chan->dst_type; |
| 369 | } else { | 377 | } else { |
| 370 | la->l2_psm = chan->sport; | ||
| 371 | bacpy(&la->l2_bdaddr, &chan->src); | 378 | bacpy(&la->l2_bdaddr, &chan->src); |
| 372 | la->l2_cid = cpu_to_le16(chan->scid); | 379 | la->l2_cid = cpu_to_le16(chan->scid); |
| 373 | la->l2_bdaddr_type = chan->src_type; | 380 | la->l2_bdaddr_type = chan->src_type; |
| @@ -432,6 +439,10 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, | |||
| 432 | opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT | | 439 | opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT | |
| 433 | L2CAP_LM_SECURE; | 440 | L2CAP_LM_SECURE; |
| 434 | break; | 441 | break; |
| 442 | case BT_SECURITY_FIPS: | ||
| 443 | opt = L2CAP_LM_AUTH | L2CAP_LM_ENCRYPT | | ||
| 444 | L2CAP_LM_SECURE | L2CAP_LM_FIPS; | ||
| 445 | break; | ||
| 435 | default: | 446 | default: |
| 436 | opt = 0; | 447 | opt = 0; |
| 437 | break; | 448 | break; |
| @@ -445,6 +456,7 @@ static int l2cap_sock_getsockopt_old(struct socket *sock, int optname, | |||
| 445 | 456 | ||
| 446 | if (put_user(opt, (u32 __user *) optval)) | 457 | if (put_user(opt, (u32 __user *) optval)) |
| 447 | err = -EFAULT; | 458 | err = -EFAULT; |
| 459 | |||
| 448 | break; | 460 | break; |
| 449 | 461 | ||
| 450 | case L2CAP_CONNINFO: | 462 | case L2CAP_CONNINFO: |
| @@ -499,6 +511,7 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, | |||
| 499 | switch (optname) { | 511 | switch (optname) { |
| 500 | case BT_SECURITY: | 512 | case BT_SECURITY: |
| 501 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED && | 513 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED && |
| 514 | chan->chan_type != L2CAP_CHAN_FIXED && | ||
| 502 | chan->chan_type != L2CAP_CHAN_RAW) { | 515 | chan->chan_type != L2CAP_CHAN_RAW) { |
| 503 | err = -EINVAL; | 516 | err = -EINVAL; |
| 504 | break; | 517 | break; |
| @@ -560,11 +573,6 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, | |||
| 560 | break; | 573 | break; |
| 561 | 574 | ||
| 562 | case BT_SNDMTU: | 575 | case BT_SNDMTU: |
| 563 | if (!enable_lecoc) { | ||
| 564 | err = -EPROTONOSUPPORT; | ||
| 565 | break; | ||
| 566 | } | ||
| 567 | |||
| 568 | if (!bdaddr_type_is_le(chan->src_type)) { | 576 | if (!bdaddr_type_is_le(chan->src_type)) { |
| 569 | err = -EINVAL; | 577 | err = -EINVAL; |
| 570 | break; | 578 | break; |
| @@ -580,11 +588,6 @@ static int l2cap_sock_getsockopt(struct socket *sock, int level, int optname, | |||
| 580 | break; | 588 | break; |
| 581 | 589 | ||
| 582 | case BT_RCVMTU: | 590 | case BT_RCVMTU: |
| 583 | if (!enable_lecoc) { | ||
| 584 | err = -EPROTONOSUPPORT; | ||
| 585 | break; | ||
| 586 | } | ||
| 587 | |||
| 588 | if (!bdaddr_type_is_le(chan->src_type)) { | 591 | if (!bdaddr_type_is_le(chan->src_type)) { |
| 589 | err = -EINVAL; | 592 | err = -EINVAL; |
| 590 | break; | 593 | break; |
| @@ -699,6 +702,11 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, | |||
| 699 | break; | 702 | break; |
| 700 | } | 703 | } |
| 701 | 704 | ||
| 705 | if (opt & L2CAP_LM_FIPS) { | ||
| 706 | err = -EINVAL; | ||
| 707 | break; | ||
| 708 | } | ||
| 709 | |||
| 702 | if (opt & L2CAP_LM_AUTH) | 710 | if (opt & L2CAP_LM_AUTH) |
| 703 | chan->sec_level = BT_SECURITY_LOW; | 711 | chan->sec_level = BT_SECURITY_LOW; |
| 704 | if (opt & L2CAP_LM_ENCRYPT) | 712 | if (opt & L2CAP_LM_ENCRYPT) |
| @@ -750,6 +758,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, | |||
| 750 | switch (optname) { | 758 | switch (optname) { |
| 751 | case BT_SECURITY: | 759 | case BT_SECURITY: |
| 752 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED && | 760 | if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED && |
| 761 | chan->chan_type != L2CAP_CHAN_FIXED && | ||
| 753 | chan->chan_type != L2CAP_CHAN_RAW) { | 762 | chan->chan_type != L2CAP_CHAN_RAW) { |
| 754 | err = -EINVAL; | 763 | err = -EINVAL; |
| 755 | break; | 764 | break; |
| @@ -895,11 +904,6 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, | |||
| 895 | break; | 904 | break; |
| 896 | 905 | ||
| 897 | case BT_SNDMTU: | 906 | case BT_SNDMTU: |
| 898 | if (!enable_lecoc) { | ||
| 899 | err = -EPROTONOSUPPORT; | ||
| 900 | break; | ||
| 901 | } | ||
| 902 | |||
| 903 | if (!bdaddr_type_is_le(chan->src_type)) { | 907 | if (!bdaddr_type_is_le(chan->src_type)) { |
| 904 | err = -EINVAL; | 908 | err = -EINVAL; |
| 905 | break; | 909 | break; |
| @@ -912,11 +916,6 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, | |||
| 912 | break; | 916 | break; |
| 913 | 917 | ||
| 914 | case BT_RCVMTU: | 918 | case BT_RCVMTU: |
| 915 | if (!enable_lecoc) { | ||
| 916 | err = -EPROTONOSUPPORT; | ||
| 917 | break; | ||
| 918 | } | ||
| 919 | |||
| 920 | if (!bdaddr_type_is_le(chan->src_type)) { | 919 | if (!bdaddr_type_is_le(chan->src_type)) { |
| 921 | err = -EINVAL; | 920 | err = -EINVAL; |
| 922 | break; | 921 | break; |
| @@ -1272,7 +1271,7 @@ static void l2cap_sock_teardown_cb(struct l2cap_chan *chan, int err) | |||
| 1272 | 1271 | ||
| 1273 | if (parent) { | 1272 | if (parent) { |
| 1274 | bt_accept_unlink(sk); | 1273 | bt_accept_unlink(sk); |
| 1275 | parent->sk_data_ready(parent, 0); | 1274 | parent->sk_data_ready(parent); |
| 1276 | } else { | 1275 | } else { |
| 1277 | sk->sk_state_change(sk); | 1276 | sk->sk_state_change(sk); |
| 1278 | } | 1277 | } |
| @@ -1328,7 +1327,7 @@ static void l2cap_sock_ready_cb(struct l2cap_chan *chan) | |||
| 1328 | sk->sk_state_change(sk); | 1327 | sk->sk_state_change(sk); |
| 1329 | 1328 | ||
| 1330 | if (parent) | 1329 | if (parent) |
| 1331 | parent->sk_data_ready(parent, 0); | 1330 | parent->sk_data_ready(parent); |
| 1332 | 1331 | ||
| 1333 | release_sock(sk); | 1332 | release_sock(sk); |
| 1334 | } | 1333 | } |
| @@ -1341,7 +1340,7 @@ static void l2cap_sock_defer_cb(struct l2cap_chan *chan) | |||
| 1341 | 1340 | ||
| 1342 | parent = bt_sk(sk)->parent; | 1341 | parent = bt_sk(sk)->parent; |
| 1343 | if (parent) | 1342 | if (parent) |
| 1344 | parent->sk_data_ready(parent, 0); | 1343 | parent->sk_data_ready(parent); |
| 1345 | 1344 | ||
| 1346 | release_sock(sk); | 1345 | release_sock(sk); |
| 1347 | } | 1346 | } |
| @@ -1449,6 +1448,11 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) | |||
| 1449 | chan->tx_credits = pchan->tx_credits; | 1448 | chan->tx_credits = pchan->tx_credits; |
| 1450 | chan->rx_credits = pchan->rx_credits; | 1449 | chan->rx_credits = pchan->rx_credits; |
| 1451 | 1450 | ||
| 1451 | if (chan->chan_type == L2CAP_CHAN_FIXED) { | ||
| 1452 | chan->scid = pchan->scid; | ||
| 1453 | chan->dcid = pchan->scid; | ||
| 1454 | } | ||
| 1455 | |||
| 1452 | security_sk_clone(parent, sk); | 1456 | security_sk_clone(parent, sk); |
| 1453 | } else { | 1457 | } else { |
| 1454 | switch (sk->sk_type) { | 1458 | switch (sk->sk_type) { |
| @@ -1614,6 +1618,3 @@ void l2cap_cleanup_sockets(void) | |||
| 1614 | bt_sock_unregister(BTPROTO_L2CAP); | 1618 | bt_sock_unregister(BTPROTO_L2CAP); |
| 1615 | proto_unregister(&l2cap_proto); | 1619 | proto_unregister(&l2cap_proto); |
| 1616 | } | 1620 | } |
| 1617 | |||
| 1618 | module_param(enable_lecoc, bool, 0644); | ||
| 1619 | MODULE_PARM_DESC(enable_lecoc, "Enable support for LE CoC"); | ||
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index a03ca3ca91bf..d2d4e0d5aed0 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c | |||
| @@ -34,7 +34,7 @@ | |||
| 34 | #include "smp.h" | 34 | #include "smp.h" |
| 35 | 35 | ||
| 36 | #define MGMT_VERSION 1 | 36 | #define MGMT_VERSION 1 |
| 37 | #define MGMT_REVISION 4 | 37 | #define MGMT_REVISION 5 |
| 38 | 38 | ||
| 39 | static const u16 mgmt_commands[] = { | 39 | static const u16 mgmt_commands[] = { |
| 40 | MGMT_OP_READ_INDEX_LIST, | 40 | MGMT_OP_READ_INDEX_LIST, |
| @@ -79,6 +79,10 @@ static const u16 mgmt_commands[] = { | |||
| 79 | MGMT_OP_SET_BREDR, | 79 | MGMT_OP_SET_BREDR, |
| 80 | MGMT_OP_SET_STATIC_ADDRESS, | 80 | MGMT_OP_SET_STATIC_ADDRESS, |
| 81 | MGMT_OP_SET_SCAN_PARAMS, | 81 | MGMT_OP_SET_SCAN_PARAMS, |
| 82 | MGMT_OP_SET_SECURE_CONN, | ||
| 83 | MGMT_OP_SET_DEBUG_KEYS, | ||
| 84 | MGMT_OP_SET_PRIVACY, | ||
| 85 | MGMT_OP_LOAD_IRKS, | ||
| 82 | }; | 86 | }; |
| 83 | 87 | ||
| 84 | static const u16 mgmt_events[] = { | 88 | static const u16 mgmt_events[] = { |
| @@ -103,6 +107,8 @@ static const u16 mgmt_events[] = { | |||
| 103 | MGMT_EV_DEVICE_UNBLOCKED, | 107 | MGMT_EV_DEVICE_UNBLOCKED, |
| 104 | MGMT_EV_DEVICE_UNPAIRED, | 108 | MGMT_EV_DEVICE_UNPAIRED, |
| 105 | MGMT_EV_PASSKEY_NOTIFY, | 109 | MGMT_EV_PASSKEY_NOTIFY, |
| 110 | MGMT_EV_NEW_IRK, | ||
| 111 | MGMT_EV_NEW_CSRK, | ||
| 106 | }; | 112 | }; |
| 107 | 113 | ||
| 108 | #define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000) | 114 | #define CACHE_TIMEOUT msecs_to_jiffies(2 * 1000) |
| @@ -127,7 +133,7 @@ static u8 mgmt_status_table[] = { | |||
| 127 | MGMT_STATUS_FAILED, /* Hardware Failure */ | 133 | MGMT_STATUS_FAILED, /* Hardware Failure */ |
| 128 | MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */ | 134 | MGMT_STATUS_CONNECT_FAILED, /* Page Timeout */ |
| 129 | MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */ | 135 | MGMT_STATUS_AUTH_FAILED, /* Authentication Failed */ |
| 130 | MGMT_STATUS_NOT_PAIRED, /* PIN or Key Missing */ | 136 | MGMT_STATUS_AUTH_FAILED, /* PIN or Key Missing */ |
| 131 | MGMT_STATUS_NO_RESOURCES, /* Memory Full */ | 137 | MGMT_STATUS_NO_RESOURCES, /* Memory Full */ |
| 132 | MGMT_STATUS_TIMEOUT, /* Connection Timeout */ | 138 | MGMT_STATUS_TIMEOUT, /* Connection Timeout */ |
| 133 | MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */ | 139 | MGMT_STATUS_NO_RESOURCES, /* Max Number of Connections */ |
| @@ -207,7 +213,7 @@ static int cmd_status(struct sock *sk, u16 index, u16 cmd, u8 status) | |||
| 207 | 213 | ||
| 208 | hdr = (void *) skb_put(skb, sizeof(*hdr)); | 214 | hdr = (void *) skb_put(skb, sizeof(*hdr)); |
| 209 | 215 | ||
| 210 | hdr->opcode = __constant_cpu_to_le16(MGMT_EV_CMD_STATUS); | 216 | hdr->opcode = cpu_to_le16(MGMT_EV_CMD_STATUS); |
| 211 | hdr->index = cpu_to_le16(index); | 217 | hdr->index = cpu_to_le16(index); |
| 212 | hdr->len = cpu_to_le16(sizeof(*ev)); | 218 | hdr->len = cpu_to_le16(sizeof(*ev)); |
| 213 | 219 | ||
| @@ -238,7 +244,7 @@ static int cmd_complete(struct sock *sk, u16 index, u16 cmd, u8 status, | |||
| 238 | 244 | ||
| 239 | hdr = (void *) skb_put(skb, sizeof(*hdr)); | 245 | hdr = (void *) skb_put(skb, sizeof(*hdr)); |
| 240 | 246 | ||
| 241 | hdr->opcode = __constant_cpu_to_le16(MGMT_EV_CMD_COMPLETE); | 247 | hdr->opcode = cpu_to_le16(MGMT_EV_CMD_COMPLETE); |
| 242 | hdr->index = cpu_to_le16(index); | 248 | hdr->index = cpu_to_le16(index); |
| 243 | hdr->len = cpu_to_le16(sizeof(*ev) + rp_len); | 249 | hdr->len = cpu_to_le16(sizeof(*ev) + rp_len); |
| 244 | 250 | ||
| @@ -264,7 +270,7 @@ static int read_version(struct sock *sk, struct hci_dev *hdev, void *data, | |||
| 264 | BT_DBG("sock %p", sk); | 270 | BT_DBG("sock %p", sk); |
| 265 | 271 | ||
| 266 | rp.version = MGMT_VERSION; | 272 | rp.version = MGMT_VERSION; |
| 267 | rp.revision = __constant_cpu_to_le16(MGMT_REVISION); | 273 | rp.revision = cpu_to_le16(MGMT_REVISION); |
| 268 | 274 | ||
| 269 | return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp, | 275 | return cmd_complete(sk, MGMT_INDEX_NONE, MGMT_OP_READ_VERSION, 0, &rp, |
| 270 | sizeof(rp)); | 276 | sizeof(rp)); |
| @@ -288,8 +294,8 @@ static int read_commands(struct sock *sk, struct hci_dev *hdev, void *data, | |||
| 288 | if (!rp) | 294 | if (!rp) |
| 289 | return -ENOMEM; | 295 | return -ENOMEM; |
| 290 | 296 | ||
| 291 | rp->num_commands = __constant_cpu_to_le16(num_commands); | 297 | rp->num_commands = cpu_to_le16(num_commands); |
| 292 | rp->num_events = __constant_cpu_to_le16(num_events); | 298 | rp->num_events = cpu_to_le16(num_events); |
| 293 | 299 | ||
| 294 | for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++) | 300 | for (i = 0, opcode = rp->opcodes; i < num_commands; i++, opcode++) |
| 295 | put_unaligned_le16(mgmt_commands[i], opcode); | 301 | put_unaligned_le16(mgmt_commands[i], opcode); |
| @@ -363,6 +369,7 @@ static u32 get_supported_settings(struct hci_dev *hdev) | |||
| 363 | 369 | ||
| 364 | settings |= MGMT_SETTING_POWERED; | 370 | settings |= MGMT_SETTING_POWERED; |
| 365 | settings |= MGMT_SETTING_PAIRABLE; | 371 | settings |= MGMT_SETTING_PAIRABLE; |
| 372 | settings |= MGMT_SETTING_DEBUG_KEYS; | ||
| 366 | 373 | ||
| 367 | if (lmp_bredr_capable(hdev)) { | 374 | if (lmp_bredr_capable(hdev)) { |
| 368 | settings |= MGMT_SETTING_CONNECTABLE; | 375 | settings |= MGMT_SETTING_CONNECTABLE; |
| @@ -376,11 +383,16 @@ static u32 get_supported_settings(struct hci_dev *hdev) | |||
| 376 | settings |= MGMT_SETTING_SSP; | 383 | settings |= MGMT_SETTING_SSP; |
| 377 | settings |= MGMT_SETTING_HS; | 384 | settings |= MGMT_SETTING_HS; |
| 378 | } | 385 | } |
| 386 | |||
| 387 | if (lmp_sc_capable(hdev) || | ||
| 388 | test_bit(HCI_FORCE_SC, &hdev->dev_flags)) | ||
| 389 | settings |= MGMT_SETTING_SECURE_CONN; | ||
| 379 | } | 390 | } |
| 380 | 391 | ||
| 381 | if (lmp_le_capable(hdev)) { | 392 | if (lmp_le_capable(hdev)) { |
| 382 | settings |= MGMT_SETTING_LE; | 393 | settings |= MGMT_SETTING_LE; |
| 383 | settings |= MGMT_SETTING_ADVERTISING; | 394 | settings |= MGMT_SETTING_ADVERTISING; |
| 395 | settings |= MGMT_SETTING_PRIVACY; | ||
| 384 | } | 396 | } |
| 385 | 397 | ||
| 386 | return settings; | 398 | return settings; |
| @@ -423,6 +435,15 @@ static u32 get_current_settings(struct hci_dev *hdev) | |||
| 423 | if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) | 435 | if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) |
| 424 | settings |= MGMT_SETTING_ADVERTISING; | 436 | settings |= MGMT_SETTING_ADVERTISING; |
| 425 | 437 | ||
| 438 | if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) | ||
| 439 | settings |= MGMT_SETTING_SECURE_CONN; | ||
| 440 | |||
| 441 | if (test_bit(HCI_DEBUG_KEYS, &hdev->dev_flags)) | ||
| 442 | settings |= MGMT_SETTING_DEBUG_KEYS; | ||
| 443 | |||
| 444 | if (test_bit(HCI_PRIVACY, &hdev->dev_flags)) | ||
| 445 | settings |= MGMT_SETTING_PRIVACY; | ||
| 446 | |||
| 426 | return settings; | 447 | return settings; |
| 427 | } | 448 | } |
| 428 | 449 | ||
| @@ -629,14 +650,8 @@ static u8 create_adv_data(struct hci_dev *hdev, u8 *ptr) | |||
| 629 | 650 | ||
| 630 | flags |= get_adv_discov_flags(hdev); | 651 | flags |= get_adv_discov_flags(hdev); |
| 631 | 652 | ||
| 632 | if (test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) { | 653 | if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags)) |
| 633 | if (lmp_le_br_capable(hdev)) | ||
| 634 | flags |= LE_AD_SIM_LE_BREDR_CTRL; | ||
| 635 | if (lmp_host_le_br_capable(hdev)) | ||
| 636 | flags |= LE_AD_SIM_LE_BREDR_HOST; | ||
| 637 | } else { | ||
| 638 | flags |= LE_AD_NO_BREDR; | 654 | flags |= LE_AD_NO_BREDR; |
| 639 | } | ||
| 640 | 655 | ||
| 641 | if (flags) { | 656 | if (flags) { |
| 642 | BT_DBG("adv flags 0x%02x", flags); | 657 | BT_DBG("adv flags 0x%02x", flags); |
| @@ -803,6 +818,64 @@ static void update_class(struct hci_request *req) | |||
| 803 | hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod); | 818 | hci_req_add(req, HCI_OP_WRITE_CLASS_OF_DEV, sizeof(cod), cod); |
| 804 | } | 819 | } |
| 805 | 820 | ||
| 821 | static bool get_connectable(struct hci_dev *hdev) | ||
| 822 | { | ||
| 823 | struct pending_cmd *cmd; | ||
| 824 | |||
| 825 | /* If there's a pending mgmt command the flag will not yet have | ||
| 826 | * it's final value, so check for this first. | ||
| 827 | */ | ||
| 828 | cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev); | ||
| 829 | if (cmd) { | ||
| 830 | struct mgmt_mode *cp = cmd->param; | ||
| 831 | return cp->val; | ||
| 832 | } | ||
| 833 | |||
| 834 | return test_bit(HCI_CONNECTABLE, &hdev->dev_flags); | ||
| 835 | } | ||
| 836 | |||
| 837 | static void enable_advertising(struct hci_request *req) | ||
| 838 | { | ||
| 839 | struct hci_dev *hdev = req->hdev; | ||
| 840 | struct hci_cp_le_set_adv_param cp; | ||
| 841 | u8 own_addr_type, enable = 0x01; | ||
| 842 | bool connectable; | ||
| 843 | |||
| 844 | /* Clear the HCI_ADVERTISING bit temporarily so that the | ||
| 845 | * hci_update_random_address knows that it's safe to go ahead | ||
| 846 | * and write a new random address. The flag will be set back on | ||
| 847 | * as soon as the SET_ADV_ENABLE HCI command completes. | ||
| 848 | */ | ||
| 849 | clear_bit(HCI_ADVERTISING, &hdev->dev_flags); | ||
| 850 | |||
| 851 | connectable = get_connectable(hdev); | ||
| 852 | |||
| 853 | /* Set require_privacy to true only when non-connectable | ||
| 854 | * advertising is used. In that case it is fine to use a | ||
| 855 | * non-resolvable private address. | ||
| 856 | */ | ||
| 857 | if (hci_update_random_address(req, !connectable, &own_addr_type) < 0) | ||
| 858 | return; | ||
| 859 | |||
| 860 | memset(&cp, 0, sizeof(cp)); | ||
| 861 | cp.min_interval = cpu_to_le16(0x0800); | ||
| 862 | cp.max_interval = cpu_to_le16(0x0800); | ||
| 863 | cp.type = connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND; | ||
| 864 | cp.own_address_type = own_addr_type; | ||
| 865 | cp.channel_map = hdev->le_adv_channel_map; | ||
| 866 | |||
| 867 | hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp); | ||
| 868 | |||
| 869 | hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable); | ||
| 870 | } | ||
| 871 | |||
| 872 | static void disable_advertising(struct hci_request *req) | ||
| 873 | { | ||
| 874 | u8 enable = 0x00; | ||
| 875 | |||
| 876 | hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable); | ||
| 877 | } | ||
| 878 | |||
| 806 | static void service_cache_off(struct work_struct *work) | 879 | static void service_cache_off(struct work_struct *work) |
| 807 | { | 880 | { |
| 808 | struct hci_dev *hdev = container_of(work, struct hci_dev, | 881 | struct hci_dev *hdev = container_of(work, struct hci_dev, |
| @@ -824,12 +897,39 @@ static void service_cache_off(struct work_struct *work) | |||
| 824 | hci_req_run(&req, NULL); | 897 | hci_req_run(&req, NULL); |
| 825 | } | 898 | } |
| 826 | 899 | ||
| 900 | static void rpa_expired(struct work_struct *work) | ||
| 901 | { | ||
| 902 | struct hci_dev *hdev = container_of(work, struct hci_dev, | ||
| 903 | rpa_expired.work); | ||
| 904 | struct hci_request req; | ||
| 905 | |||
| 906 | BT_DBG(""); | ||
| 907 | |||
| 908 | set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags); | ||
| 909 | |||
| 910 | if (!test_bit(HCI_ADVERTISING, &hdev->dev_flags) || | ||
| 911 | hci_conn_num(hdev, LE_LINK) > 0) | ||
| 912 | return; | ||
| 913 | |||
| 914 | /* The generation of a new RPA and programming it into the | ||
| 915 | * controller happens in the enable_advertising() function. | ||
| 916 | */ | ||
| 917 | |||
| 918 | hci_req_init(&req, hdev); | ||
| 919 | |||
| 920 | disable_advertising(&req); | ||
| 921 | enable_advertising(&req); | ||
| 922 | |||
| 923 | hci_req_run(&req, NULL); | ||
| 924 | } | ||
| 925 | |||
| 827 | static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev) | 926 | static void mgmt_init_hdev(struct sock *sk, struct hci_dev *hdev) |
| 828 | { | 927 | { |
| 829 | if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags)) | 928 | if (test_and_set_bit(HCI_MGMT, &hdev->dev_flags)) |
| 830 | return; | 929 | return; |
| 831 | 930 | ||
| 832 | INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off); | 931 | INIT_DELAYED_WORK(&hdev->service_cache, service_cache_off); |
| 932 | INIT_DELAYED_WORK(&hdev->rpa_expired, rpa_expired); | ||
| 833 | 933 | ||
| 834 | /* Non-mgmt controlled devices get this bit set | 934 | /* Non-mgmt controlled devices get this bit set |
| 835 | * implicitly so that pairing works for them, however | 935 | * implicitly so that pairing works for them, however |
| @@ -935,6 +1035,71 @@ static int send_settings_rsp(struct sock *sk, u16 opcode, struct hci_dev *hdev) | |||
| 935 | sizeof(settings)); | 1035 | sizeof(settings)); |
| 936 | } | 1036 | } |
| 937 | 1037 | ||
| 1038 | static void clean_up_hci_complete(struct hci_dev *hdev, u8 status) | ||
| 1039 | { | ||
| 1040 | BT_DBG("%s status 0x%02x", hdev->name, status); | ||
| 1041 | |||
| 1042 | if (hci_conn_count(hdev) == 0) { | ||
| 1043 | cancel_delayed_work(&hdev->power_off); | ||
| 1044 | queue_work(hdev->req_workqueue, &hdev->power_off.work); | ||
| 1045 | } | ||
| 1046 | } | ||
| 1047 | |||
| 1048 | static int clean_up_hci_state(struct hci_dev *hdev) | ||
| 1049 | { | ||
| 1050 | struct hci_request req; | ||
| 1051 | struct hci_conn *conn; | ||
| 1052 | |||
| 1053 | hci_req_init(&req, hdev); | ||
| 1054 | |||
| 1055 | if (test_bit(HCI_ISCAN, &hdev->flags) || | ||
| 1056 | test_bit(HCI_PSCAN, &hdev->flags)) { | ||
| 1057 | u8 scan = 0x00; | ||
| 1058 | hci_req_add(&req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan); | ||
| 1059 | } | ||
| 1060 | |||
| 1061 | if (test_bit(HCI_ADVERTISING, &hdev->dev_flags)) | ||
| 1062 | disable_advertising(&req); | ||
| 1063 | |||
| 1064 | if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) { | ||
| 1065 | hci_req_add_le_scan_disable(&req); | ||
| 1066 | } | ||
| 1067 | |||
| 1068 | list_for_each_entry(conn, &hdev->conn_hash.list, list) { | ||
| 1069 | struct hci_cp_disconnect dc; | ||
| 1070 | struct hci_cp_reject_conn_req rej; | ||
| 1071 | |||
| 1072 | switch (conn->state) { | ||
| 1073 | case BT_CONNECTED: | ||
| 1074 | case BT_CONFIG: | ||
| 1075 | dc.handle = cpu_to_le16(conn->handle); | ||
| 1076 | dc.reason = 0x15; /* Terminated due to Power Off */ | ||
| 1077 | hci_req_add(&req, HCI_OP_DISCONNECT, sizeof(dc), &dc); | ||
| 1078 | break; | ||
| 1079 | case BT_CONNECT: | ||
| 1080 | if (conn->type == LE_LINK) | ||
| 1081 | hci_req_add(&req, HCI_OP_LE_CREATE_CONN_CANCEL, | ||
| 1082 | 0, NULL); | ||
| 1083 | else if (conn->type == ACL_LINK) | ||
| 1084 | hci_req_add(&req, HCI_OP_CREATE_CONN_CANCEL, | ||
| 1085 | 6, &conn->dst); | ||
| 1086 | break; | ||
| 1087 | case BT_CONNECT2: | ||
| 1088 | bacpy(&rej.bdaddr, &conn->dst); | ||
| 1089 | rej.reason = 0x15; /* Terminated due to Power Off */ | ||
| 1090 | if (conn->type == ACL_LINK) | ||
| 1091 | hci_req_add(&req, HCI_OP_REJECT_CONN_REQ, | ||
| 1092 | sizeof(rej), &rej); | ||
| 1093 | else if (conn->type == SCO_LINK) | ||
| 1094 | hci_req_add(&req, HCI_OP_REJECT_SYNC_CONN_REQ, | ||
| 1095 | sizeof(rej), &rej); | ||
| 1096 | break; | ||
| 1097 | } | ||
| 1098 | } | ||
| 1099 | |||
| 1100 | return hci_req_run(&req, clean_up_hci_complete); | ||
| 1101 | } | ||
| 1102 | |||
| 938 | static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data, | 1103 | static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data, |
| 939 | u16 len) | 1104 | u16 len) |
| 940 | { | 1105 | { |
| @@ -978,12 +1143,23 @@ static int set_powered(struct sock *sk, struct hci_dev *hdev, void *data, | |||
| 978 | goto failed; | 1143 | goto failed; |
| 979 | } | 1144 | } |
| 980 | 1145 | ||
| 981 | if (cp->val) | 1146 | if (cp->val) { |
| 982 | queue_work(hdev->req_workqueue, &hdev->power_on); | 1147 | queue_work(hdev->req_workqueue, &hdev->power_on); |
| 983 | else | 1148 | err = 0; |
| 984 | queue_work(hdev->req_workqueue, &hdev->power_off.work); | 1149 | } else { |
| 985 | 1150 | /* Disconnect connections, stop scans, etc */ | |
| 986 | err = 0; | 1151 | err = clean_up_hci_state(hdev); |
| 1152 | if (!err) | ||
| 1153 | queue_delayed_work(hdev->req_workqueue, &hdev->power_off, | ||
| 1154 | HCI_POWER_OFF_TIMEOUT); | ||
| 1155 | |||
| 1156 | /* ENODATA means there were no HCI commands queued */ | ||
| 1157 | if (err == -ENODATA) { | ||
| 1158 | cancel_delayed_work(&hdev->power_off); | ||
| 1159 | queue_work(hdev->req_workqueue, &hdev->power_off.work); | ||
| 1160 | err = 0; | ||
| 1161 | } | ||
| 1162 | } | ||
| 987 | 1163 | ||
| 988 | failed: | 1164 | failed: |
| 989 | hci_dev_unlock(hdev); | 1165 | hci_dev_unlock(hdev); |
| @@ -1005,7 +1181,7 @@ static int mgmt_event(u16 event, struct hci_dev *hdev, void *data, u16 data_len, | |||
| 1005 | if (hdev) | 1181 | if (hdev) |
| 1006 | hdr->index = cpu_to_le16(hdev->id); | 1182 | hdr->index = cpu_to_le16(hdev->id); |
| 1007 | else | 1183 | else |
| 1008 | hdr->index = __constant_cpu_to_le16(MGMT_INDEX_NONE); | 1184 | hdr->index = cpu_to_le16(MGMT_INDEX_NONE); |
| 1009 | hdr->len = cpu_to_le16(data_len); | 1185 | hdr->len = cpu_to_le16(data_len); |
| 1010 | 1186 | ||
| 1011 | if (data) | 1187 | if (data) |
| @@ -1317,15 +1493,15 @@ static void write_fast_connectable(struct hci_request *req, bool enable) | |||
| 1317 | type = PAGE_SCAN_TYPE_INTERLACED; | 1493 | type = PAGE_SCAN_TYPE_INTERLACED; |
| 1318 | 1494 | ||
| 1319 | /* 160 msec page scan interval */ | 1495 | /* 160 msec page scan interval */ |
| 1320 | acp.interval = __constant_cpu_to_le16(0x0100); | 1496 | acp.interval = cpu_to_le16(0x0100); |
| 1321 | } else { | 1497 | } else { |
| 1322 | type = PAGE_SCAN_TYPE_STANDARD; /* default */ | 1498 | type = PAGE_SCAN_TYPE_STANDARD; /* default */ |
| 1323 | 1499 | ||
| 1324 | /* default 1.28 sec page scan */ | 1500 | /* default 1.28 sec page scan */ |
| 1325 | acp.interval = __constant_cpu_to_le16(0x0800); | 1501 | acp.interval = cpu_to_le16(0x0800); |
| 1326 | } | 1502 | } |
| 1327 | 1503 | ||
| 1328 | acp.window = __constant_cpu_to_le16(0x0012); | 1504 | acp.window = cpu_to_le16(0x0012); |
| 1329 | 1505 | ||
| 1330 | if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval || | 1506 | if (__cpu_to_le16(hdev->page_scan_interval) != acp.interval || |
| 1331 | __cpu_to_le16(hdev->page_scan_window) != acp.window) | 1507 | __cpu_to_le16(hdev->page_scan_window) != acp.window) |
| @@ -1336,50 +1512,6 @@ static void write_fast_connectable(struct hci_request *req, bool enable) | |||
| 1336 | hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type); | 1512 | hci_req_add(req, HCI_OP_WRITE_PAGE_SCAN_TYPE, 1, &type); |
| 1337 | } | 1513 | } |
| 1338 | 1514 | ||
| 1339 | static u8 get_adv_type(struct hci_dev *hdev) | ||
| 1340 | { | ||
| 1341 | struct pending_cmd *cmd; | ||
| 1342 | bool connectable; | ||
| 1343 | |||
| 1344 | /* If there's a pending mgmt command the flag will not yet have | ||
| 1345 | * it's final value, so check for this first. | ||
| 1346 | */ | ||
| 1347 | cmd = mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev); | ||
| 1348 | if (cmd) { | ||
| 1349 | struct mgmt_mode *cp = cmd->param; | ||
| 1350 | connectable = !!cp->val; | ||
| 1351 | } else { | ||
| 1352 | connectable = test_bit(HCI_CONNECTABLE, &hdev->dev_flags); | ||
| 1353 | } | ||
| 1354 | |||
| 1355 | return connectable ? LE_ADV_IND : LE_ADV_NONCONN_IND; | ||
| 1356 | } | ||
| 1357 | |||
| 1358 | static void enable_advertising(struct hci_request *req) | ||
| 1359 | { | ||
| 1360 | struct hci_dev *hdev = req->hdev; | ||
| 1361 | struct hci_cp_le_set_adv_param cp; | ||
| 1362 | u8 enable = 0x01; | ||
| 1363 | |||
| 1364 | memset(&cp, 0, sizeof(cp)); | ||
| 1365 | cp.min_interval = __constant_cpu_to_le16(0x0800); | ||
| 1366 | cp.max_interval = __constant_cpu_to_le16(0x0800); | ||
| 1367 | cp.type = get_adv_type(hdev); | ||
| 1368 | cp.own_address_type = hdev->own_addr_type; | ||
| 1369 | cp.channel_map = 0x07; | ||
| 1370 | |||
| 1371 | hci_req_add(req, HCI_OP_LE_SET_ADV_PARAM, sizeof(cp), &cp); | ||
| 1372 | |||
| 1373 | hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable); | ||
| 1374 | } | ||
| 1375 | |||
| 1376 | static void disable_advertising(struct hci_request *req) | ||
| 1377 | { | ||
| 1378 | u8 enable = 0x00; | ||
| 1379 | |||
| 1380 | hci_req_add(req, HCI_OP_LE_SET_ADV_ENABLE, sizeof(enable), &enable); | ||
| 1381 | } | ||
| 1382 | |||
| 1383 | static void set_connectable_complete(struct hci_dev *hdev, u8 status) | 1515 | static void set_connectable_complete(struct hci_dev *hdev, u8 status) |
| 1384 | { | 1516 | { |
| 1385 | struct pending_cmd *cmd; | 1517 | struct pending_cmd *cmd; |
| @@ -2065,7 +2197,7 @@ static int remove_uuid(struct sock *sk, struct hci_dev *hdev, void *data, | |||
| 2065 | } | 2197 | } |
| 2066 | 2198 | ||
| 2067 | if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) { | 2199 | if (memcmp(cp->uuid, bt_uuid_any, 16) == 0) { |
| 2068 | err = hci_uuids_clear(hdev); | 2200 | hci_uuids_clear(hdev); |
| 2069 | 2201 | ||
| 2070 | if (enable_service_cache(hdev)) { | 2202 | if (enable_service_cache(hdev)) { |
| 2071 | err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, | 2203 | err = cmd_complete(sk, hdev->id, MGMT_OP_REMOVE_UUID, |
| @@ -2205,6 +2337,7 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data, | |||
| 2205 | { | 2337 | { |
| 2206 | struct mgmt_cp_load_link_keys *cp = data; | 2338 | struct mgmt_cp_load_link_keys *cp = data; |
| 2207 | u16 key_count, expected_len; | 2339 | u16 key_count, expected_len; |
| 2340 | bool changed; | ||
| 2208 | int i; | 2341 | int i; |
| 2209 | 2342 | ||
| 2210 | BT_DBG("request for %s", hdev->name); | 2343 | BT_DBG("request for %s", hdev->name); |
| @@ -2219,7 +2352,7 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data, | |||
| 2219 | sizeof(struct mgmt_link_key_info); | 2352 | sizeof(struct mgmt_link_key_info); |
| 2220 | if (expected_len != len) { | 2353 | if (expected_len != len) { |
| 2221 | BT_ERR("load_link_keys: expected %u bytes, got %u bytes", | 2354 | BT_ERR("load_link_keys: expected %u bytes, got %u bytes", |
| 2222 | len, expected_len); | 2355 | expected_len, len); |
| 2223 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, | 2356 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, |
| 2224 | MGMT_STATUS_INVALID_PARAMS); | 2357 | MGMT_STATUS_INVALID_PARAMS); |
| 2225 | } | 2358 | } |
| @@ -2234,7 +2367,7 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data, | |||
| 2234 | for (i = 0; i < key_count; i++) { | 2367 | for (i = 0; i < key_count; i++) { |
| 2235 | struct mgmt_link_key_info *key = &cp->keys[i]; | 2368 | struct mgmt_link_key_info *key = &cp->keys[i]; |
| 2236 | 2369 | ||
| 2237 | if (key->addr.type != BDADDR_BREDR) | 2370 | if (key->addr.type != BDADDR_BREDR || key->type > 0x08) |
| 2238 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, | 2371 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LINK_KEYS, |
| 2239 | MGMT_STATUS_INVALID_PARAMS); | 2372 | MGMT_STATUS_INVALID_PARAMS); |
| 2240 | } | 2373 | } |
| @@ -2244,9 +2377,12 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data, | |||
| 2244 | hci_link_keys_clear(hdev); | 2377 | hci_link_keys_clear(hdev); |
| 2245 | 2378 | ||
| 2246 | if (cp->debug_keys) | 2379 | if (cp->debug_keys) |
| 2247 | set_bit(HCI_DEBUG_KEYS, &hdev->dev_flags); | 2380 | changed = !test_and_set_bit(HCI_DEBUG_KEYS, &hdev->dev_flags); |
| 2248 | else | 2381 | else |
| 2249 | clear_bit(HCI_DEBUG_KEYS, &hdev->dev_flags); | 2382 | changed = test_and_clear_bit(HCI_DEBUG_KEYS, &hdev->dev_flags); |
| 2383 | |||
| 2384 | if (changed) | ||
| 2385 | new_settings(hdev, NULL); | ||
| 2250 | 2386 | ||
| 2251 | for (i = 0; i < key_count; i++) { | 2387 | for (i = 0; i < key_count; i++) { |
| 2252 | struct mgmt_link_key_info *key = &cp->keys[i]; | 2388 | struct mgmt_link_key_info *key = &cp->keys[i]; |
| @@ -2306,10 +2442,22 @@ static int unpair_device(struct sock *sk, struct hci_dev *hdev, void *data, | |||
| 2306 | goto unlock; | 2442 | goto unlock; |
| 2307 | } | 2443 | } |
| 2308 | 2444 | ||
| 2309 | if (cp->addr.type == BDADDR_BREDR) | 2445 | if (cp->addr.type == BDADDR_BREDR) { |
| 2310 | err = hci_remove_link_key(hdev, &cp->addr.bdaddr); | 2446 | err = hci_remove_link_key(hdev, &cp->addr.bdaddr); |
| 2311 | else | 2447 | } else { |
| 2312 | err = hci_remove_ltk(hdev, &cp->addr.bdaddr); | 2448 | u8 addr_type; |
| 2449 | |||
| 2450 | if (cp->addr.type == BDADDR_LE_PUBLIC) | ||
| 2451 | addr_type = ADDR_LE_DEV_PUBLIC; | ||
| 2452 | else | ||
| 2453 | addr_type = ADDR_LE_DEV_RANDOM; | ||
| 2454 | |||
| 2455 | hci_remove_irk(hdev, &cp->addr.bdaddr, addr_type); | ||
| 2456 | |||
| 2457 | hci_conn_params_del(hdev, &cp->addr.bdaddr, addr_type); | ||
| 2458 | |||
| 2459 | err = hci_remove_ltk(hdev, &cp->addr.bdaddr, addr_type); | ||
| 2460 | } | ||
| 2313 | 2461 | ||
| 2314 | if (err < 0) { | 2462 | if (err < 0) { |
| 2315 | err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, | 2463 | err = cmd_complete(sk, hdev->id, MGMT_OP_UNPAIR_DEVICE, |
| @@ -2633,6 +2781,16 @@ static void pairing_complete(struct pending_cmd *cmd, u8 status) | |||
| 2633 | mgmt_pending_remove(cmd); | 2781 | mgmt_pending_remove(cmd); |
| 2634 | } | 2782 | } |
| 2635 | 2783 | ||
| 2784 | void mgmt_smp_complete(struct hci_conn *conn, bool complete) | ||
| 2785 | { | ||
| 2786 | u8 status = complete ? MGMT_STATUS_SUCCESS : MGMT_STATUS_FAILED; | ||
| 2787 | struct pending_cmd *cmd; | ||
| 2788 | |||
| 2789 | cmd = find_pairing(conn); | ||
| 2790 | if (cmd) | ||
| 2791 | pairing_complete(cmd, status); | ||
| 2792 | } | ||
| 2793 | |||
| 2636 | static void pairing_complete_cb(struct hci_conn *conn, u8 status) | 2794 | static void pairing_complete_cb(struct hci_conn *conn, u8 status) |
| 2637 | { | 2795 | { |
| 2638 | struct pending_cmd *cmd; | 2796 | struct pending_cmd *cmd; |
| @@ -2646,7 +2804,7 @@ static void pairing_complete_cb(struct hci_conn *conn, u8 status) | |||
| 2646 | pairing_complete(cmd, mgmt_status(status)); | 2804 | pairing_complete(cmd, mgmt_status(status)); |
| 2647 | } | 2805 | } |
| 2648 | 2806 | ||
| 2649 | static void le_connect_complete_cb(struct hci_conn *conn, u8 status) | 2807 | static void le_pairing_complete_cb(struct hci_conn *conn, u8 status) |
| 2650 | { | 2808 | { |
| 2651 | struct pending_cmd *cmd; | 2809 | struct pending_cmd *cmd; |
| 2652 | 2810 | ||
| @@ -2697,12 +2855,22 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, | |||
| 2697 | else | 2855 | else |
| 2698 | auth_type = HCI_AT_DEDICATED_BONDING_MITM; | 2856 | auth_type = HCI_AT_DEDICATED_BONDING_MITM; |
| 2699 | 2857 | ||
| 2700 | if (cp->addr.type == BDADDR_BREDR) | 2858 | if (cp->addr.type == BDADDR_BREDR) { |
| 2701 | conn = hci_connect(hdev, ACL_LINK, &cp->addr.bdaddr, | 2859 | conn = hci_connect_acl(hdev, &cp->addr.bdaddr, sec_level, |
| 2702 | cp->addr.type, sec_level, auth_type); | 2860 | auth_type); |
| 2703 | else | 2861 | } else { |
| 2704 | conn = hci_connect(hdev, LE_LINK, &cp->addr.bdaddr, | 2862 | u8 addr_type; |
| 2705 | cp->addr.type, sec_level, auth_type); | 2863 | |
| 2864 | /* Convert from L2CAP channel address type to HCI address type | ||
| 2865 | */ | ||
| 2866 | if (cp->addr.type == BDADDR_LE_PUBLIC) | ||
| 2867 | addr_type = ADDR_LE_DEV_PUBLIC; | ||
| 2868 | else | ||
| 2869 | addr_type = ADDR_LE_DEV_RANDOM; | ||
| 2870 | |||
| 2871 | conn = hci_connect_le(hdev, &cp->addr.bdaddr, addr_type, | ||
| 2872 | sec_level, auth_type); | ||
| 2873 | } | ||
| 2706 | 2874 | ||
| 2707 | if (IS_ERR(conn)) { | 2875 | if (IS_ERR(conn)) { |
| 2708 | int status; | 2876 | int status; |
| @@ -2733,13 +2901,16 @@ static int pair_device(struct sock *sk, struct hci_dev *hdev, void *data, | |||
| 2733 | } | 2901 | } |
| 2734 | 2902 | ||
| 2735 | /* For LE, just connecting isn't a proof that the pairing finished */ | 2903 | /* For LE, just connecting isn't a proof that the pairing finished */ |
| 2736 | if (cp->addr.type == BDADDR_BREDR) | 2904 | if (cp->addr.type == BDADDR_BREDR) { |
| 2737 | conn->connect_cfm_cb = pairing_complete_cb; | 2905 | conn->connect_cfm_cb = pairing_complete_cb; |
| 2738 | else | 2906 | conn->security_cfm_cb = pairing_complete_cb; |
| 2739 | conn->connect_cfm_cb = le_connect_complete_cb; | 2907 | conn->disconn_cfm_cb = pairing_complete_cb; |
| 2908 | } else { | ||
| 2909 | conn->connect_cfm_cb = le_pairing_complete_cb; | ||
| 2910 | conn->security_cfm_cb = le_pairing_complete_cb; | ||
| 2911 | conn->disconn_cfm_cb = le_pairing_complete_cb; | ||
| 2912 | } | ||
| 2740 | 2913 | ||
| 2741 | conn->security_cfm_cb = pairing_complete_cb; | ||
| 2742 | conn->disconn_cfm_cb = pairing_complete_cb; | ||
| 2743 | conn->io_capability = cp->io_cap; | 2914 | conn->io_capability = cp->io_cap; |
| 2744 | cmd->user_data = conn; | 2915 | cmd->user_data = conn; |
| 2745 | 2916 | ||
| @@ -3071,7 +3242,12 @@ static int read_local_oob_data(struct sock *sk, struct hci_dev *hdev, | |||
| 3071 | goto unlock; | 3242 | goto unlock; |
| 3072 | } | 3243 | } |
| 3073 | 3244 | ||
| 3074 | err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL); | 3245 | if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags)) |
| 3246 | err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_EXT_DATA, | ||
| 3247 | 0, NULL); | ||
| 3248 | else | ||
| 3249 | err = hci_send_cmd(hdev, HCI_OP_READ_LOCAL_OOB_DATA, 0, NULL); | ||
| 3250 | |||
| 3075 | if (err < 0) | 3251 | if (err < 0) |
| 3076 | mgmt_pending_remove(cmd); | 3252 | mgmt_pending_remove(cmd); |
| 3077 | 3253 | ||
| @@ -3083,23 +3259,46 @@ unlock: | |||
| 3083 | static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev, | 3259 | static int add_remote_oob_data(struct sock *sk, struct hci_dev *hdev, |
| 3084 | void *data, u16 len) | 3260 | void *data, u16 len) |
| 3085 | { | 3261 | { |
| 3086 | struct mgmt_cp_add_remote_oob_data *cp = data; | ||
| 3087 | u8 status; | ||
| 3088 | int err; | 3262 | int err; |
| 3089 | 3263 | ||
| 3090 | BT_DBG("%s ", hdev->name); | 3264 | BT_DBG("%s ", hdev->name); |
| 3091 | 3265 | ||
| 3092 | hci_dev_lock(hdev); | 3266 | hci_dev_lock(hdev); |
| 3093 | 3267 | ||
| 3094 | err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr, cp->hash, | 3268 | if (len == MGMT_ADD_REMOTE_OOB_DATA_SIZE) { |
| 3095 | cp->randomizer); | 3269 | struct mgmt_cp_add_remote_oob_data *cp = data; |
| 3096 | if (err < 0) | 3270 | u8 status; |
| 3097 | status = MGMT_STATUS_FAILED; | ||
| 3098 | else | ||
| 3099 | status = MGMT_STATUS_SUCCESS; | ||
| 3100 | 3271 | ||
| 3101 | err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA, status, | 3272 | err = hci_add_remote_oob_data(hdev, &cp->addr.bdaddr, |
| 3102 | &cp->addr, sizeof(cp->addr)); | 3273 | cp->hash, cp->randomizer); |
| 3274 | if (err < 0) | ||
| 3275 | status = MGMT_STATUS_FAILED; | ||
| 3276 | else | ||
| 3277 | status = MGMT_STATUS_SUCCESS; | ||
| 3278 | |||
| 3279 | err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA, | ||
| 3280 | status, &cp->addr, sizeof(cp->addr)); | ||
| 3281 | } else if (len == MGMT_ADD_REMOTE_OOB_EXT_DATA_SIZE) { | ||
| 3282 | struct mgmt_cp_add_remote_oob_ext_data *cp = data; | ||
| 3283 | u8 status; | ||
| 3284 | |||
| 3285 | err = hci_add_remote_oob_ext_data(hdev, &cp->addr.bdaddr, | ||
| 3286 | cp->hash192, | ||
| 3287 | cp->randomizer192, | ||
| 3288 | cp->hash256, | ||
| 3289 | cp->randomizer256); | ||
| 3290 | if (err < 0) | ||
| 3291 | status = MGMT_STATUS_FAILED; | ||
| 3292 | else | ||
| 3293 | status = MGMT_STATUS_SUCCESS; | ||
| 3294 | |||
| 3295 | err = cmd_complete(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA, | ||
| 3296 | status, &cp->addr, sizeof(cp->addr)); | ||
| 3297 | } else { | ||
| 3298 | BT_ERR("add_remote_oob_data: invalid length of %u bytes", len); | ||
| 3299 | err = cmd_status(sk, hdev->id, MGMT_OP_ADD_REMOTE_OOB_DATA, | ||
| 3300 | MGMT_STATUS_INVALID_PARAMS); | ||
| 3301 | } | ||
| 3103 | 3302 | ||
| 3104 | hci_dev_unlock(hdev); | 3303 | hci_dev_unlock(hdev); |
| 3105 | return err; | 3304 | return err; |
| @@ -3195,7 +3394,7 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, | |||
| 3195 | struct hci_request req; | 3394 | struct hci_request req; |
| 3196 | /* General inquiry access code (GIAC) */ | 3395 | /* General inquiry access code (GIAC) */ |
| 3197 | u8 lap[3] = { 0x33, 0x8b, 0x9e }; | 3396 | u8 lap[3] = { 0x33, 0x8b, 0x9e }; |
| 3198 | u8 status; | 3397 | u8 status, own_addr_type; |
| 3199 | int err; | 3398 | int err; |
| 3200 | 3399 | ||
| 3201 | BT_DBG("%s", hdev->name); | 3400 | BT_DBG("%s", hdev->name); |
| @@ -3280,18 +3479,31 @@ static int start_discovery(struct sock *sk, struct hci_dev *hdev, | |||
| 3280 | goto failed; | 3479 | goto failed; |
| 3281 | } | 3480 | } |
| 3282 | 3481 | ||
| 3283 | if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) { | 3482 | /* If controller is scanning, it means the background scanning |
| 3483 | * is running. Thus, we should temporarily stop it in order to | ||
| 3484 | * set the discovery scanning parameters. | ||
| 3485 | */ | ||
| 3486 | if (test_bit(HCI_LE_SCAN, &hdev->dev_flags)) | ||
| 3487 | hci_req_add_le_scan_disable(&req); | ||
| 3488 | |||
| 3489 | memset(¶m_cp, 0, sizeof(param_cp)); | ||
| 3490 | |||
| 3491 | /* All active scans will be done with either a resolvable | ||
| 3492 | * private address (when privacy feature has been enabled) | ||
| 3493 | * or unresolvable private address. | ||
| 3494 | */ | ||
| 3495 | err = hci_update_random_address(&req, true, &own_addr_type); | ||
| 3496 | if (err < 0) { | ||
| 3284 | err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, | 3497 | err = cmd_status(sk, hdev->id, MGMT_OP_START_DISCOVERY, |
| 3285 | MGMT_STATUS_BUSY); | 3498 | MGMT_STATUS_FAILED); |
| 3286 | mgmt_pending_remove(cmd); | 3499 | mgmt_pending_remove(cmd); |
| 3287 | goto failed; | 3500 | goto failed; |
| 3288 | } | 3501 | } |
| 3289 | 3502 | ||
| 3290 | memset(¶m_cp, 0, sizeof(param_cp)); | ||
| 3291 | param_cp.type = LE_SCAN_ACTIVE; | 3503 | param_cp.type = LE_SCAN_ACTIVE; |
| 3292 | param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT); | 3504 | param_cp.interval = cpu_to_le16(DISCOV_LE_SCAN_INT); |
| 3293 | param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN); | 3505 | param_cp.window = cpu_to_le16(DISCOV_LE_SCAN_WIN); |
| 3294 | param_cp.own_address_type = hdev->own_addr_type; | 3506 | param_cp.own_address_type = own_addr_type; |
| 3295 | hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp), | 3507 | hci_req_add(&req, HCI_OP_LE_SET_SCAN_PARAM, sizeof(param_cp), |
| 3296 | ¶m_cp); | 3508 | ¶m_cp); |
| 3297 | 3509 | ||
| @@ -3361,7 +3573,6 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data, | |||
| 3361 | struct hci_cp_remote_name_req_cancel cp; | 3573 | struct hci_cp_remote_name_req_cancel cp; |
| 3362 | struct inquiry_entry *e; | 3574 | struct inquiry_entry *e; |
| 3363 | struct hci_request req; | 3575 | struct hci_request req; |
| 3364 | struct hci_cp_le_set_scan_enable enable_cp; | ||
| 3365 | int err; | 3576 | int err; |
| 3366 | 3577 | ||
| 3367 | BT_DBG("%s", hdev->name); | 3578 | BT_DBG("%s", hdev->name); |
| @@ -3397,10 +3608,7 @@ static int stop_discovery(struct sock *sk, struct hci_dev *hdev, void *data, | |||
| 3397 | } else { | 3608 | } else { |
| 3398 | cancel_delayed_work(&hdev->le_scan_disable); | 3609 | cancel_delayed_work(&hdev->le_scan_disable); |
| 3399 | 3610 | ||
| 3400 | memset(&enable_cp, 0, sizeof(enable_cp)); | 3611 | hci_req_add_le_scan_disable(&req); |
| 3401 | enable_cp.enable = LE_SCAN_DISABLE; | ||
| 3402 | hci_req_add(&req, HCI_OP_LE_SET_SCAN_ENABLE, | ||
| 3403 | sizeof(enable_cp), &enable_cp); | ||
| 3404 | } | 3612 | } |
| 3405 | 3613 | ||
| 3406 | break; | 3614 | break; |
| @@ -3457,15 +3665,17 @@ static int confirm_name(struct sock *sk, struct hci_dev *hdev, void *data, | |||
| 3457 | hci_dev_lock(hdev); | 3665 | hci_dev_lock(hdev); |
| 3458 | 3666 | ||
| 3459 | if (!hci_discovery_active(hdev)) { | 3667 | if (!hci_discovery_active(hdev)) { |
| 3460 | err = cmd_status(sk, hdev->id, MGMT_OP_CONFIRM_NAME, | 3668 | err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, |
| 3461 | MGMT_STATUS_FAILED); | 3669 | MGMT_STATUS_FAILED, &cp->addr, |
| 3670 | sizeof(cp->addr)); | ||
| 3462 | goto failed; | 3671 | goto failed; |
| 3463 | } | 3672 | } |
| 3464 | 3673 | ||
| 3465 | e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr); | 3674 | e = hci_inquiry_cache_lookup_unknown(hdev, &cp->addr.bdaddr); |
| 3466 | if (!e) { | 3675 | if (!e) { |
| 3467 | err = cmd_status(sk, hdev->id, MGMT_OP_CONFIRM_NAME, | 3676 | err = cmd_complete(sk, hdev->id, MGMT_OP_CONFIRM_NAME, |
| 3468 | MGMT_STATUS_INVALID_PARAMS); | 3677 | MGMT_STATUS_INVALID_PARAMS, &cp->addr, |
| 3678 | sizeof(cp->addr)); | ||
| 3469 | goto failed; | 3679 | goto failed; |
| 3470 | } | 3680 | } |
| 3471 | 3681 | ||
| @@ -3754,6 +3964,21 @@ static int set_scan_params(struct sock *sk, struct hci_dev *hdev, | |||
| 3754 | 3964 | ||
| 3755 | err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0); | 3965 | err = cmd_complete(sk, hdev->id, MGMT_OP_SET_SCAN_PARAMS, 0, NULL, 0); |
| 3756 | 3966 | ||
| 3967 | /* If background scan is running, restart it so new parameters are | ||
| 3968 | * loaded. | ||
| 3969 | */ | ||
| 3970 | if (test_bit(HCI_LE_SCAN, &hdev->dev_flags) && | ||
| 3971 | hdev->discovery.state == DISCOVERY_STOPPED) { | ||
| 3972 | struct hci_request req; | ||
| 3973 | |||
| 3974 | hci_req_init(&req, hdev); | ||
| 3975 | |||
| 3976 | hci_req_add_le_scan_disable(&req); | ||
| 3977 | hci_req_add_le_passive_scan(&req); | ||
| 3978 | |||
| 3979 | hci_req_run(&req, NULL); | ||
| 3980 | } | ||
| 3981 | |||
| 3757 | hci_dev_unlock(hdev); | 3982 | hci_dev_unlock(hdev); |
| 3758 | 3983 | ||
| 3759 | return err; | 3984 | return err; |
| @@ -3999,15 +4224,269 @@ unlock: | |||
| 3999 | return err; | 4224 | return err; |
| 4000 | } | 4225 | } |
| 4001 | 4226 | ||
| 4227 | static int set_secure_conn(struct sock *sk, struct hci_dev *hdev, | ||
| 4228 | void *data, u16 len) | ||
| 4229 | { | ||
| 4230 | struct mgmt_mode *cp = data; | ||
| 4231 | struct pending_cmd *cmd; | ||
| 4232 | u8 val, status; | ||
| 4233 | int err; | ||
| 4234 | |||
| 4235 | BT_DBG("request for %s", hdev->name); | ||
| 4236 | |||
| 4237 | status = mgmt_bredr_support(hdev); | ||
| 4238 | if (status) | ||
| 4239 | return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN, | ||
| 4240 | status); | ||
| 4241 | |||
| 4242 | if (!lmp_sc_capable(hdev) && | ||
| 4243 | !test_bit(HCI_FORCE_SC, &hdev->dev_flags)) | ||
| 4244 | return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN, | ||
| 4245 | MGMT_STATUS_NOT_SUPPORTED); | ||
| 4246 | |||
| 4247 | if (cp->val != 0x00 && cp->val != 0x01 && cp->val != 0x02) | ||
| 4248 | return cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN, | ||
| 4249 | MGMT_STATUS_INVALID_PARAMS); | ||
| 4250 | |||
| 4251 | hci_dev_lock(hdev); | ||
| 4252 | |||
| 4253 | if (!hdev_is_powered(hdev)) { | ||
| 4254 | bool changed; | ||
| 4255 | |||
| 4256 | if (cp->val) { | ||
| 4257 | changed = !test_and_set_bit(HCI_SC_ENABLED, | ||
| 4258 | &hdev->dev_flags); | ||
| 4259 | if (cp->val == 0x02) | ||
| 4260 | set_bit(HCI_SC_ONLY, &hdev->dev_flags); | ||
| 4261 | else | ||
| 4262 | clear_bit(HCI_SC_ONLY, &hdev->dev_flags); | ||
| 4263 | } else { | ||
| 4264 | changed = test_and_clear_bit(HCI_SC_ENABLED, | ||
| 4265 | &hdev->dev_flags); | ||
| 4266 | clear_bit(HCI_SC_ONLY, &hdev->dev_flags); | ||
| 4267 | } | ||
| 4268 | |||
| 4269 | err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev); | ||
| 4270 | if (err < 0) | ||
| 4271 | goto failed; | ||
| 4272 | |||
| 4273 | if (changed) | ||
| 4274 | err = new_settings(hdev, sk); | ||
| 4275 | |||
| 4276 | goto failed; | ||
| 4277 | } | ||
| 4278 | |||
| 4279 | if (mgmt_pending_find(MGMT_OP_SET_SECURE_CONN, hdev)) { | ||
| 4280 | err = cmd_status(sk, hdev->id, MGMT_OP_SET_SECURE_CONN, | ||
| 4281 | MGMT_STATUS_BUSY); | ||
| 4282 | goto failed; | ||
| 4283 | } | ||
| 4284 | |||
| 4285 | val = !!cp->val; | ||
| 4286 | |||
| 4287 | if (val == test_bit(HCI_SC_ENABLED, &hdev->dev_flags) && | ||
| 4288 | (cp->val == 0x02) == test_bit(HCI_SC_ONLY, &hdev->dev_flags)) { | ||
| 4289 | err = send_settings_rsp(sk, MGMT_OP_SET_SECURE_CONN, hdev); | ||
| 4290 | goto failed; | ||
| 4291 | } | ||
| 4292 | |||
| 4293 | cmd = mgmt_pending_add(sk, MGMT_OP_SET_SECURE_CONN, hdev, data, len); | ||
| 4294 | if (!cmd) { | ||
| 4295 | err = -ENOMEM; | ||
| 4296 | goto failed; | ||
| 4297 | } | ||
| 4298 | |||
| 4299 | err = hci_send_cmd(hdev, HCI_OP_WRITE_SC_SUPPORT, 1, &val); | ||
| 4300 | if (err < 0) { | ||
| 4301 | mgmt_pending_remove(cmd); | ||
| 4302 | goto failed; | ||
| 4303 | } | ||
| 4304 | |||
| 4305 | if (cp->val == 0x02) | ||
| 4306 | set_bit(HCI_SC_ONLY, &hdev->dev_flags); | ||
| 4307 | else | ||
| 4308 | clear_bit(HCI_SC_ONLY, &hdev->dev_flags); | ||
| 4309 | |||
| 4310 | failed: | ||
| 4311 | hci_dev_unlock(hdev); | ||
| 4312 | return err; | ||
| 4313 | } | ||
| 4314 | |||
| 4315 | static int set_debug_keys(struct sock *sk, struct hci_dev *hdev, | ||
| 4316 | void *data, u16 len) | ||
| 4317 | { | ||
| 4318 | struct mgmt_mode *cp = data; | ||
| 4319 | bool changed; | ||
| 4320 | int err; | ||
| 4321 | |||
| 4322 | BT_DBG("request for %s", hdev->name); | ||
| 4323 | |||
| 4324 | if (cp->val != 0x00 && cp->val != 0x01) | ||
| 4325 | return cmd_status(sk, hdev->id, MGMT_OP_SET_DEBUG_KEYS, | ||
| 4326 | MGMT_STATUS_INVALID_PARAMS); | ||
| 4327 | |||
| 4328 | hci_dev_lock(hdev); | ||
| 4329 | |||
| 4330 | if (cp->val) | ||
| 4331 | changed = !test_and_set_bit(HCI_DEBUG_KEYS, &hdev->dev_flags); | ||
| 4332 | else | ||
| 4333 | changed = test_and_clear_bit(HCI_DEBUG_KEYS, &hdev->dev_flags); | ||
| 4334 | |||
| 4335 | err = send_settings_rsp(sk, MGMT_OP_SET_DEBUG_KEYS, hdev); | ||
| 4336 | if (err < 0) | ||
| 4337 | goto unlock; | ||
| 4338 | |||
| 4339 | if (changed) | ||
| 4340 | err = new_settings(hdev, sk); | ||
| 4341 | |||
| 4342 | unlock: | ||
| 4343 | hci_dev_unlock(hdev); | ||
| 4344 | return err; | ||
| 4345 | } | ||
| 4346 | |||
| 4347 | static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data, | ||
| 4348 | u16 len) | ||
| 4349 | { | ||
| 4350 | struct mgmt_cp_set_privacy *cp = cp_data; | ||
| 4351 | bool changed; | ||
| 4352 | int err; | ||
| 4353 | |||
| 4354 | BT_DBG("request for %s", hdev->name); | ||
| 4355 | |||
| 4356 | if (!lmp_le_capable(hdev)) | ||
| 4357 | return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY, | ||
| 4358 | MGMT_STATUS_NOT_SUPPORTED); | ||
| 4359 | |||
| 4360 | if (cp->privacy != 0x00 && cp->privacy != 0x01) | ||
| 4361 | return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY, | ||
| 4362 | MGMT_STATUS_INVALID_PARAMS); | ||
| 4363 | |||
| 4364 | if (hdev_is_powered(hdev)) | ||
| 4365 | return cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY, | ||
| 4366 | MGMT_STATUS_REJECTED); | ||
| 4367 | |||
| 4368 | hci_dev_lock(hdev); | ||
| 4369 | |||
| 4370 | /* If user space supports this command it is also expected to | ||
| 4371 | * handle IRKs. Therefore, set the HCI_RPA_RESOLVING flag. | ||
| 4372 | */ | ||
| 4373 | set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags); | ||
| 4374 | |||
| 4375 | if (cp->privacy) { | ||
| 4376 | changed = !test_and_set_bit(HCI_PRIVACY, &hdev->dev_flags); | ||
| 4377 | memcpy(hdev->irk, cp->irk, sizeof(hdev->irk)); | ||
| 4378 | set_bit(HCI_RPA_EXPIRED, &hdev->dev_flags); | ||
| 4379 | } else { | ||
| 4380 | changed = test_and_clear_bit(HCI_PRIVACY, &hdev->dev_flags); | ||
| 4381 | memset(hdev->irk, 0, sizeof(hdev->irk)); | ||
| 4382 | clear_bit(HCI_RPA_EXPIRED, &hdev->dev_flags); | ||
| 4383 | } | ||
| 4384 | |||
| 4385 | err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev); | ||
| 4386 | if (err < 0) | ||
| 4387 | goto unlock; | ||
| 4388 | |||
| 4389 | if (changed) | ||
| 4390 | err = new_settings(hdev, sk); | ||
| 4391 | |||
| 4392 | unlock: | ||
| 4393 | hci_dev_unlock(hdev); | ||
| 4394 | return err; | ||
| 4395 | } | ||
| 4396 | |||
| 4397 | static bool irk_is_valid(struct mgmt_irk_info *irk) | ||
| 4398 | { | ||
| 4399 | switch (irk->addr.type) { | ||
| 4400 | case BDADDR_LE_PUBLIC: | ||
| 4401 | return true; | ||
| 4402 | |||
| 4403 | case BDADDR_LE_RANDOM: | ||
| 4404 | /* Two most significant bits shall be set */ | ||
| 4405 | if ((irk->addr.bdaddr.b[5] & 0xc0) != 0xc0) | ||
| 4406 | return false; | ||
| 4407 | return true; | ||
| 4408 | } | ||
| 4409 | |||
| 4410 | return false; | ||
| 4411 | } | ||
| 4412 | |||
| 4413 | static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data, | ||
| 4414 | u16 len) | ||
| 4415 | { | ||
| 4416 | struct mgmt_cp_load_irks *cp = cp_data; | ||
| 4417 | u16 irk_count, expected_len; | ||
| 4418 | int i, err; | ||
| 4419 | |||
| 4420 | BT_DBG("request for %s", hdev->name); | ||
| 4421 | |||
| 4422 | if (!lmp_le_capable(hdev)) | ||
| 4423 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS, | ||
| 4424 | MGMT_STATUS_NOT_SUPPORTED); | ||
| 4425 | |||
| 4426 | irk_count = __le16_to_cpu(cp->irk_count); | ||
| 4427 | |||
| 4428 | expected_len = sizeof(*cp) + irk_count * sizeof(struct mgmt_irk_info); | ||
| 4429 | if (expected_len != len) { | ||
| 4430 | BT_ERR("load_irks: expected %u bytes, got %u bytes", | ||
| 4431 | expected_len, len); | ||
| 4432 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_IRKS, | ||
| 4433 | MGMT_STATUS_INVALID_PARAMS); | ||
| 4434 | } | ||
| 4435 | |||
| 4436 | BT_DBG("%s irk_count %u", hdev->name, irk_count); | ||
| 4437 | |||
| 4438 | for (i = 0; i < irk_count; i++) { | ||
| 4439 | struct mgmt_irk_info *key = &cp->irks[i]; | ||
| 4440 | |||
| 4441 | if (!irk_is_valid(key)) | ||
| 4442 | return cmd_status(sk, hdev->id, | ||
| 4443 | MGMT_OP_LOAD_IRKS, | ||
| 4444 | MGMT_STATUS_INVALID_PARAMS); | ||
| 4445 | } | ||
| 4446 | |||
| 4447 | hci_dev_lock(hdev); | ||
| 4448 | |||
| 4449 | hci_smp_irks_clear(hdev); | ||
| 4450 | |||
| 4451 | for (i = 0; i < irk_count; i++) { | ||
| 4452 | struct mgmt_irk_info *irk = &cp->irks[i]; | ||
| 4453 | u8 addr_type; | ||
| 4454 | |||
| 4455 | if (irk->addr.type == BDADDR_LE_PUBLIC) | ||
| 4456 | addr_type = ADDR_LE_DEV_PUBLIC; | ||
| 4457 | else | ||
| 4458 | addr_type = ADDR_LE_DEV_RANDOM; | ||
| 4459 | |||
| 4460 | hci_add_irk(hdev, &irk->addr.bdaddr, addr_type, irk->val, | ||
| 4461 | BDADDR_ANY); | ||
| 4462 | } | ||
| 4463 | |||
| 4464 | set_bit(HCI_RPA_RESOLVING, &hdev->dev_flags); | ||
| 4465 | |||
| 4466 | err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_IRKS, 0, NULL, 0); | ||
| 4467 | |||
| 4468 | hci_dev_unlock(hdev); | ||
| 4469 | |||
| 4470 | return err; | ||
| 4471 | } | ||
| 4472 | |||
| 4002 | static bool ltk_is_valid(struct mgmt_ltk_info *key) | 4473 | static bool ltk_is_valid(struct mgmt_ltk_info *key) |
| 4003 | { | 4474 | { |
| 4004 | if (key->authenticated != 0x00 && key->authenticated != 0x01) | ||
| 4005 | return false; | ||
| 4006 | if (key->master != 0x00 && key->master != 0x01) | 4475 | if (key->master != 0x00 && key->master != 0x01) |
| 4007 | return false; | 4476 | return false; |
| 4008 | if (!bdaddr_type_is_le(key->addr.type)) | 4477 | |
| 4009 | return false; | 4478 | switch (key->addr.type) { |
| 4010 | return true; | 4479 | case BDADDR_LE_PUBLIC: |
| 4480 | return true; | ||
| 4481 | |||
| 4482 | case BDADDR_LE_RANDOM: | ||
| 4483 | /* Two most significant bits shall be set */ | ||
| 4484 | if ((key->addr.bdaddr.b[5] & 0xc0) != 0xc0) | ||
| 4485 | return false; | ||
| 4486 | return true; | ||
| 4487 | } | ||
| 4488 | |||
| 4489 | return false; | ||
| 4011 | } | 4490 | } |
| 4012 | 4491 | ||
| 4013 | static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev, | 4492 | static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev, |
| @@ -4029,7 +4508,7 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev, | |||
| 4029 | sizeof(struct mgmt_ltk_info); | 4508 | sizeof(struct mgmt_ltk_info); |
| 4030 | if (expected_len != len) { | 4509 | if (expected_len != len) { |
| 4031 | BT_ERR("load_keys: expected %u bytes, got %u bytes", | 4510 | BT_ERR("load_keys: expected %u bytes, got %u bytes", |
| 4032 | len, expected_len); | 4511 | expected_len, len); |
| 4033 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, | 4512 | return cmd_status(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, |
| 4034 | MGMT_STATUS_INVALID_PARAMS); | 4513 | MGMT_STATUS_INVALID_PARAMS); |
| 4035 | } | 4514 | } |
| @@ -4063,9 +4542,9 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev, | |||
| 4063 | else | 4542 | else |
| 4064 | type = HCI_SMP_LTK_SLAVE; | 4543 | type = HCI_SMP_LTK_SLAVE; |
| 4065 | 4544 | ||
| 4066 | hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, | 4545 | hci_add_ltk(hdev, &key->addr.bdaddr, addr_type, type, |
| 4067 | type, 0, key->authenticated, key->val, | 4546 | key->type, key->val, key->enc_size, key->ediv, |
| 4068 | key->enc_size, key->ediv, key->rand); | 4547 | key->rand); |
| 4069 | } | 4548 | } |
| 4070 | 4549 | ||
| 4071 | err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0, | 4550 | err = cmd_complete(sk, hdev->id, MGMT_OP_LOAD_LONG_TERM_KEYS, 0, |
| @@ -4115,7 +4594,7 @@ static const struct mgmt_handler { | |||
| 4115 | { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE }, | 4594 | { user_passkey_reply, false, MGMT_USER_PASSKEY_REPLY_SIZE }, |
| 4116 | { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE }, | 4595 | { user_passkey_neg_reply, false, MGMT_USER_PASSKEY_NEG_REPLY_SIZE }, |
| 4117 | { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE }, | 4596 | { read_local_oob_data, false, MGMT_READ_LOCAL_OOB_DATA_SIZE }, |
| 4118 | { add_remote_oob_data, false, MGMT_ADD_REMOTE_OOB_DATA_SIZE }, | 4597 | { add_remote_oob_data, true, MGMT_ADD_REMOTE_OOB_DATA_SIZE }, |
| 4119 | { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE }, | 4598 | { remove_remote_oob_data, false, MGMT_REMOVE_REMOTE_OOB_DATA_SIZE }, |
| 4120 | { start_discovery, false, MGMT_START_DISCOVERY_SIZE }, | 4599 | { start_discovery, false, MGMT_START_DISCOVERY_SIZE }, |
| 4121 | { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE }, | 4600 | { stop_discovery, false, MGMT_STOP_DISCOVERY_SIZE }, |
| @@ -4127,6 +4606,10 @@ static const struct mgmt_handler { | |||
| 4127 | { set_bredr, false, MGMT_SETTING_SIZE }, | 4606 | { set_bredr, false, MGMT_SETTING_SIZE }, |
| 4128 | { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE }, | 4607 | { set_static_address, false, MGMT_SET_STATIC_ADDRESS_SIZE }, |
| 4129 | { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE }, | 4608 | { set_scan_params, false, MGMT_SET_SCAN_PARAMS_SIZE }, |
| 4609 | { set_secure_conn, false, MGMT_SETTING_SIZE }, | ||
| 4610 | { set_debug_keys, false, MGMT_SETTING_SIZE }, | ||
| 4611 | { set_privacy, false, MGMT_SET_PRIVACY_SIZE }, | ||
| 4612 | { load_irks, true, MGMT_LOAD_IRKS_SIZE }, | ||
| 4130 | }; | 4613 | }; |
| 4131 | 4614 | ||
| 4132 | 4615 | ||
| @@ -4243,6 +4726,17 @@ void mgmt_index_removed(struct hci_dev *hdev) | |||
| 4243 | mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL); | 4726 | mgmt_event(MGMT_EV_INDEX_REMOVED, hdev, NULL, 0, NULL); |
| 4244 | } | 4727 | } |
| 4245 | 4728 | ||
| 4729 | /* This function requires the caller holds hdev->lock */ | ||
| 4730 | static void restart_le_auto_conns(struct hci_dev *hdev) | ||
| 4731 | { | ||
| 4732 | struct hci_conn_params *p; | ||
| 4733 | |||
| 4734 | list_for_each_entry(p, &hdev->le_conn_params, list) { | ||
| 4735 | if (p->auto_connect == HCI_AUTO_CONN_ALWAYS) | ||
| 4736 | hci_pend_le_conn_add(hdev, &p->addr, p->addr_type); | ||
| 4737 | } | ||
| 4738 | } | ||
| 4739 | |||
| 4246 | static void powered_complete(struct hci_dev *hdev, u8 status) | 4740 | static void powered_complete(struct hci_dev *hdev, u8 status) |
| 4247 | { | 4741 | { |
| 4248 | struct cmd_lookup match = { NULL, hdev }; | 4742 | struct cmd_lookup match = { NULL, hdev }; |
| @@ -4251,6 +4745,8 @@ static void powered_complete(struct hci_dev *hdev, u8 status) | |||
| 4251 | 4745 | ||
| 4252 | hci_dev_lock(hdev); | 4746 | hci_dev_lock(hdev); |
| 4253 | 4747 | ||
| 4748 | restart_le_auto_conns(hdev); | ||
| 4749 | |||
| 4254 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); | 4750 | mgmt_pending_foreach(MGMT_OP_SET_POWERED, hdev, settings_rsp, &match); |
| 4255 | 4751 | ||
| 4256 | new_settings(hdev, match.sk); | 4752 | new_settings(hdev, match.sk); |
| @@ -4292,11 +4788,6 @@ static int powered_update_hci(struct hci_dev *hdev) | |||
| 4292 | } | 4788 | } |
| 4293 | 4789 | ||
| 4294 | if (lmp_le_capable(hdev)) { | 4790 | if (lmp_le_capable(hdev)) { |
| 4295 | /* Set random address to static address if configured */ | ||
| 4296 | if (bacmp(&hdev->static_addr, BDADDR_ANY)) | ||
| 4297 | hci_req_add(&req, HCI_OP_LE_SET_RANDOM_ADDR, 6, | ||
| 4298 | &hdev->static_addr); | ||
| 4299 | |||
| 4300 | /* Make sure the controller has a good default for | 4791 | /* Make sure the controller has a good default for |
| 4301 | * advertising data. This also applies to the case | 4792 | * advertising data. This also applies to the case |
| 4302 | * where BR/EDR was toggled during the AUTO_OFF phase. | 4793 | * where BR/EDR was toggled during the AUTO_OFF phase. |
| @@ -4422,6 +4913,10 @@ void mgmt_discoverable(struct hci_dev *hdev, u8 discoverable) | |||
| 4422 | if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev)) | 4913 | if (mgmt_pending_find(MGMT_OP_SET_DISCOVERABLE, hdev)) |
| 4423 | return; | 4914 | return; |
| 4424 | 4915 | ||
| 4916 | /* Powering off may clear the scan mode - don't let that interfere */ | ||
| 4917 | if (!discoverable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) | ||
| 4918 | return; | ||
| 4919 | |||
| 4425 | if (discoverable) { | 4920 | if (discoverable) { |
| 4426 | changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags); | 4921 | changed = !test_and_set_bit(HCI_DISCOVERABLE, &hdev->dev_flags); |
| 4427 | } else { | 4922 | } else { |
| @@ -4455,6 +4950,10 @@ void mgmt_connectable(struct hci_dev *hdev, u8 connectable) | |||
| 4455 | if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) | 4950 | if (mgmt_pending_find(MGMT_OP_SET_CONNECTABLE, hdev)) |
| 4456 | return; | 4951 | return; |
| 4457 | 4952 | ||
| 4953 | /* Powering off may clear the scan mode - don't let that interfere */ | ||
| 4954 | if (!connectable && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) | ||
| 4955 | return; | ||
| 4956 | |||
| 4458 | if (connectable) | 4957 | if (connectable) |
| 4459 | changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags); | 4958 | changed = !test_and_set_bit(HCI_CONNECTABLE, &hdev->dev_flags); |
| 4460 | else | 4959 | else |
| @@ -4464,6 +4963,18 @@ void mgmt_connectable(struct hci_dev *hdev, u8 connectable) | |||
| 4464 | new_settings(hdev, NULL); | 4963 | new_settings(hdev, NULL); |
| 4465 | } | 4964 | } |
| 4466 | 4965 | ||
| 4966 | void mgmt_advertising(struct hci_dev *hdev, u8 advertising) | ||
| 4967 | { | ||
| 4968 | /* Powering off may stop advertising - don't let that interfere */ | ||
| 4969 | if (!advertising && mgmt_pending_find(MGMT_OP_SET_POWERED, hdev)) | ||
| 4970 | return; | ||
| 4971 | |||
| 4972 | if (advertising) | ||
| 4973 | set_bit(HCI_ADVERTISING, &hdev->dev_flags); | ||
| 4974 | else | ||
| 4975 | clear_bit(HCI_ADVERTISING, &hdev->dev_flags); | ||
| 4976 | } | ||
| 4977 | |||
| 4467 | void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status) | 4978 | void mgmt_write_scan_failed(struct hci_dev *hdev, u8 scan, u8 status) |
| 4468 | { | 4979 | { |
| 4469 | u8 mgmt_err = mgmt_status(status); | 4980 | u8 mgmt_err = mgmt_status(status); |
| @@ -4494,28 +5005,104 @@ void mgmt_new_link_key(struct hci_dev *hdev, struct link_key *key, | |||
| 4494 | mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL); | 5005 | mgmt_event(MGMT_EV_NEW_LINK_KEY, hdev, &ev, sizeof(ev), NULL); |
| 4495 | } | 5006 | } |
| 4496 | 5007 | ||
| 4497 | void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, u8 persistent) | 5008 | void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent) |
| 4498 | { | 5009 | { |
| 4499 | struct mgmt_ev_new_long_term_key ev; | 5010 | struct mgmt_ev_new_long_term_key ev; |
| 4500 | 5011 | ||
| 4501 | memset(&ev, 0, sizeof(ev)); | 5012 | memset(&ev, 0, sizeof(ev)); |
| 4502 | 5013 | ||
| 4503 | ev.store_hint = persistent; | 5014 | /* Devices using resolvable or non-resolvable random addresses |
| 5015 | * without providing an indentity resolving key don't require | ||
| 5016 | * to store long term keys. Their addresses will change the | ||
| 5017 | * next time around. | ||
| 5018 | * | ||
| 5019 | * Only when a remote device provides an identity address | ||
| 5020 | * make sure the long term key is stored. If the remote | ||
| 5021 | * identity is known, the long term keys are internally | ||
| 5022 | * mapped to the identity address. So allow static random | ||
| 5023 | * and public addresses here. | ||
| 5024 | */ | ||
| 5025 | if (key->bdaddr_type == ADDR_LE_DEV_RANDOM && | ||
| 5026 | (key->bdaddr.b[5] & 0xc0) != 0xc0) | ||
| 5027 | ev.store_hint = 0x00; | ||
| 5028 | else | ||
| 5029 | ev.store_hint = persistent; | ||
| 5030 | |||
| 4504 | bacpy(&ev.key.addr.bdaddr, &key->bdaddr); | 5031 | bacpy(&ev.key.addr.bdaddr, &key->bdaddr); |
| 4505 | ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type); | 5032 | ev.key.addr.type = link_to_bdaddr(LE_LINK, key->bdaddr_type); |
| 4506 | ev.key.authenticated = key->authenticated; | 5033 | ev.key.type = key->authenticated; |
| 4507 | ev.key.enc_size = key->enc_size; | 5034 | ev.key.enc_size = key->enc_size; |
| 4508 | ev.key.ediv = key->ediv; | 5035 | ev.key.ediv = key->ediv; |
| 5036 | ev.key.rand = key->rand; | ||
| 4509 | 5037 | ||
| 4510 | if (key->type == HCI_SMP_LTK) | 5038 | if (key->type == HCI_SMP_LTK) |
| 4511 | ev.key.master = 1; | 5039 | ev.key.master = 1; |
| 4512 | 5040 | ||
| 4513 | memcpy(ev.key.rand, key->rand, sizeof(key->rand)); | ||
| 4514 | memcpy(ev.key.val, key->val, sizeof(key->val)); | 5041 | memcpy(ev.key.val, key->val, sizeof(key->val)); |
| 4515 | 5042 | ||
| 4516 | mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL); | 5043 | mgmt_event(MGMT_EV_NEW_LONG_TERM_KEY, hdev, &ev, sizeof(ev), NULL); |
| 4517 | } | 5044 | } |
| 4518 | 5045 | ||
| 5046 | void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk) | ||
| 5047 | { | ||
| 5048 | struct mgmt_ev_new_irk ev; | ||
| 5049 | |||
| 5050 | memset(&ev, 0, sizeof(ev)); | ||
| 5051 | |||
| 5052 | /* For identity resolving keys from devices that are already | ||
| 5053 | * using a public address or static random address, do not | ||
| 5054 | * ask for storing this key. The identity resolving key really | ||
| 5055 | * is only mandatory for devices using resovlable random | ||
| 5056 | * addresses. | ||
| 5057 | * | ||
| 5058 | * Storing all identity resolving keys has the downside that | ||
| 5059 | * they will be also loaded on next boot of they system. More | ||
| 5060 | * identity resolving keys, means more time during scanning is | ||
| 5061 | * needed to actually resolve these addresses. | ||
| 5062 | */ | ||
| 5063 | if (bacmp(&irk->rpa, BDADDR_ANY)) | ||
| 5064 | ev.store_hint = 0x01; | ||
| 5065 | else | ||
| 5066 | ev.store_hint = 0x00; | ||
| 5067 | |||
| 5068 | bacpy(&ev.rpa, &irk->rpa); | ||
| 5069 | bacpy(&ev.irk.addr.bdaddr, &irk->bdaddr); | ||
| 5070 | ev.irk.addr.type = link_to_bdaddr(LE_LINK, irk->addr_type); | ||
| 5071 | memcpy(ev.irk.val, irk->val, sizeof(irk->val)); | ||
| 5072 | |||
| 5073 | mgmt_event(MGMT_EV_NEW_IRK, hdev, &ev, sizeof(ev), NULL); | ||
| 5074 | } | ||
| 5075 | |||
| 5076 | void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk, | ||
| 5077 | bool persistent) | ||
| 5078 | { | ||
| 5079 | struct mgmt_ev_new_csrk ev; | ||
| 5080 | |||
| 5081 | memset(&ev, 0, sizeof(ev)); | ||
| 5082 | |||
| 5083 | /* Devices using resolvable or non-resolvable random addresses | ||
| 5084 | * without providing an indentity resolving key don't require | ||
| 5085 | * to store signature resolving keys. Their addresses will change | ||
| 5086 | * the next time around. | ||
| 5087 | * | ||
| 5088 | * Only when a remote device provides an identity address | ||
| 5089 | * make sure the signature resolving key is stored. So allow | ||
| 5090 | * static random and public addresses here. | ||
| 5091 | */ | ||
| 5092 | if (csrk->bdaddr_type == ADDR_LE_DEV_RANDOM && | ||
| 5093 | (csrk->bdaddr.b[5] & 0xc0) != 0xc0) | ||
| 5094 | ev.store_hint = 0x00; | ||
| 5095 | else | ||
| 5096 | ev.store_hint = persistent; | ||
| 5097 | |||
| 5098 | bacpy(&ev.key.addr.bdaddr, &csrk->bdaddr); | ||
| 5099 | ev.key.addr.type = link_to_bdaddr(LE_LINK, csrk->bdaddr_type); | ||
| 5100 | ev.key.master = csrk->master; | ||
| 5101 | memcpy(ev.key.val, csrk->val, sizeof(csrk->val)); | ||
| 5102 | |||
| 5103 | mgmt_event(MGMT_EV_NEW_CSRK, hdev, &ev, sizeof(ev), NULL); | ||
| 5104 | } | ||
| 5105 | |||
| 4519 | static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data, | 5106 | static inline u16 eir_append_data(u8 *eir, u16 eir_len, u8 type, u8 *data, |
| 4520 | u8 data_len) | 5107 | u8 data_len) |
| 4521 | { | 5108 | { |
| @@ -4590,11 +5177,29 @@ static void unpair_device_rsp(struct pending_cmd *cmd, void *data) | |||
| 4590 | } | 5177 | } |
| 4591 | 5178 | ||
| 4592 | void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, | 5179 | void mgmt_device_disconnected(struct hci_dev *hdev, bdaddr_t *bdaddr, |
| 4593 | u8 link_type, u8 addr_type, u8 reason) | 5180 | u8 link_type, u8 addr_type, u8 reason, |
| 5181 | bool mgmt_connected) | ||
| 4594 | { | 5182 | { |
| 4595 | struct mgmt_ev_device_disconnected ev; | 5183 | struct mgmt_ev_device_disconnected ev; |
| 5184 | struct pending_cmd *power_off; | ||
| 4596 | struct sock *sk = NULL; | 5185 | struct sock *sk = NULL; |
| 4597 | 5186 | ||
| 5187 | power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev); | ||
| 5188 | if (power_off) { | ||
| 5189 | struct mgmt_mode *cp = power_off->param; | ||
| 5190 | |||
| 5191 | /* The connection is still in hci_conn_hash so test for 1 | ||
| 5192 | * instead of 0 to know if this is the last one. | ||
| 5193 | */ | ||
| 5194 | if (!cp->val && hci_conn_count(hdev) == 1) { | ||
| 5195 | cancel_delayed_work(&hdev->power_off); | ||
| 5196 | queue_work(hdev->req_workqueue, &hdev->power_off.work); | ||
| 5197 | } | ||
| 5198 | } | ||
| 5199 | |||
| 5200 | if (!mgmt_connected) | ||
| 5201 | return; | ||
| 5202 | |||
| 4598 | if (link_type != ACL_LINK && link_type != LE_LINK) | 5203 | if (link_type != ACL_LINK && link_type != LE_LINK) |
| 4599 | return; | 5204 | return; |
| 4600 | 5205 | ||
| @@ -4649,6 +5254,20 @@ void mgmt_connect_failed(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | |||
| 4649 | u8 addr_type, u8 status) | 5254 | u8 addr_type, u8 status) |
| 4650 | { | 5255 | { |
| 4651 | struct mgmt_ev_connect_failed ev; | 5256 | struct mgmt_ev_connect_failed ev; |
| 5257 | struct pending_cmd *power_off; | ||
| 5258 | |||
| 5259 | power_off = mgmt_pending_find(MGMT_OP_SET_POWERED, hdev); | ||
| 5260 | if (power_off) { | ||
| 5261 | struct mgmt_mode *cp = power_off->param; | ||
| 5262 | |||
| 5263 | /* The connection is still in hci_conn_hash so test for 1 | ||
| 5264 | * instead of 0 to know if this is the last one. | ||
| 5265 | */ | ||
| 5266 | if (!cp->val && hci_conn_count(hdev) == 1) { | ||
| 5267 | cancel_delayed_work(&hdev->power_off); | ||
| 5268 | queue_work(hdev->req_workqueue, &hdev->power_off.work); | ||
| 5269 | } | ||
| 5270 | } | ||
| 4652 | 5271 | ||
| 4653 | bacpy(&ev.addr.bdaddr, bdaddr); | 5272 | bacpy(&ev.addr.bdaddr, bdaddr); |
| 4654 | ev.addr.type = link_to_bdaddr(link_type, addr_type); | 5273 | ev.addr.type = link_to_bdaddr(link_type, addr_type); |
| @@ -4707,7 +5326,7 @@ void mgmt_pin_code_neg_reply_complete(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
| 4707 | } | 5326 | } |
| 4708 | 5327 | ||
| 4709 | int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr, | 5328 | int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr, |
| 4710 | u8 link_type, u8 addr_type, __le32 value, | 5329 | u8 link_type, u8 addr_type, u32 value, |
| 4711 | u8 confirm_hint) | 5330 | u8 confirm_hint) |
| 4712 | { | 5331 | { |
| 4713 | struct mgmt_ev_user_confirm_request ev; | 5332 | struct mgmt_ev_user_confirm_request ev; |
| @@ -4717,7 +5336,7 @@ int mgmt_user_confirm_request(struct hci_dev *hdev, bdaddr_t *bdaddr, | |||
| 4717 | bacpy(&ev.addr.bdaddr, bdaddr); | 5336 | bacpy(&ev.addr.bdaddr, bdaddr); |
| 4718 | ev.addr.type = link_to_bdaddr(link_type, addr_type); | 5337 | ev.addr.type = link_to_bdaddr(link_type, addr_type); |
| 4719 | ev.confirm_hint = confirm_hint; | 5338 | ev.confirm_hint = confirm_hint; |
| 4720 | ev.value = value; | 5339 | ev.value = cpu_to_le32(value); |
| 4721 | 5340 | ||
| 4722 | return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev), | 5341 | return mgmt_event(MGMT_EV_USER_CONFIRM_REQUEST, hdev, &ev, sizeof(ev), |
| 4723 | NULL); | 5342 | NULL); |
| @@ -4910,6 +5529,43 @@ void mgmt_ssp_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) | |||
| 4910 | hci_req_run(&req, NULL); | 5529 | hci_req_run(&req, NULL); |
| 4911 | } | 5530 | } |
| 4912 | 5531 | ||
| 5532 | void mgmt_sc_enable_complete(struct hci_dev *hdev, u8 enable, u8 status) | ||
| 5533 | { | ||
| 5534 | struct cmd_lookup match = { NULL, hdev }; | ||
| 5535 | bool changed = false; | ||
| 5536 | |||
| 5537 | if (status) { | ||
| 5538 | u8 mgmt_err = mgmt_status(status); | ||
| 5539 | |||
| 5540 | if (enable) { | ||
| 5541 | if (test_and_clear_bit(HCI_SC_ENABLED, | ||
| 5542 | &hdev->dev_flags)) | ||
| 5543 | new_settings(hdev, NULL); | ||
| 5544 | clear_bit(HCI_SC_ONLY, &hdev->dev_flags); | ||
| 5545 | } | ||
| 5546 | |||
| 5547 | mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev, | ||
| 5548 | cmd_status_rsp, &mgmt_err); | ||
| 5549 | return; | ||
| 5550 | } | ||
| 5551 | |||
| 5552 | if (enable) { | ||
| 5553 | changed = !test_and_set_bit(HCI_SC_ENABLED, &hdev->dev_flags); | ||
| 5554 | } else { | ||
| 5555 | changed = test_and_clear_bit(HCI_SC_ENABLED, &hdev->dev_flags); | ||
| 5556 | clear_bit(HCI_SC_ONLY, &hdev->dev_flags); | ||
| 5557 | } | ||
| 5558 | |||
| 5559 | mgmt_pending_foreach(MGMT_OP_SET_SECURE_CONN, hdev, | ||
| 5560 | settings_rsp, &match); | ||
| 5561 | |||
| 5562 | if (changed) | ||
| 5563 | new_settings(hdev, match.sk); | ||
| 5564 | |||
| 5565 | if (match.sk) | ||
| 5566 | sock_put(match.sk); | ||
| 5567 | } | ||
| 5568 | |||
| 4913 | static void sk_lookup(struct pending_cmd *cmd, void *data) | 5569 | static void sk_lookup(struct pending_cmd *cmd, void *data) |
| 4914 | { | 5570 | { |
| 4915 | struct cmd_lookup *match = data; | 5571 | struct cmd_lookup *match = data; |
| @@ -4964,8 +5620,9 @@ void mgmt_set_local_name_complete(struct hci_dev *hdev, u8 *name, u8 status) | |||
| 4964 | cmd ? cmd->sk : NULL); | 5620 | cmd ? cmd->sk : NULL); |
| 4965 | } | 5621 | } |
| 4966 | 5622 | ||
| 4967 | void mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, | 5623 | void mgmt_read_local_oob_data_complete(struct hci_dev *hdev, u8 *hash192, |
| 4968 | u8 *randomizer, u8 status) | 5624 | u8 *randomizer192, u8 *hash256, |
| 5625 | u8 *randomizer256, u8 status) | ||
| 4969 | { | 5626 | { |
| 4970 | struct pending_cmd *cmd; | 5627 | struct pending_cmd *cmd; |
| 4971 | 5628 | ||
| @@ -4979,13 +5636,32 @@ void mgmt_read_local_oob_data_reply_complete(struct hci_dev *hdev, u8 *hash, | |||
| 4979 | cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, | 5636 | cmd_status(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, |
| 4980 | mgmt_status(status)); | 5637 | mgmt_status(status)); |
| 4981 | } else { | 5638 | } else { |
| 4982 | struct mgmt_rp_read_local_oob_data rp; | 5639 | if (test_bit(HCI_SC_ENABLED, &hdev->dev_flags) && |
| 5640 | hash256 && randomizer256) { | ||
| 5641 | struct mgmt_rp_read_local_oob_ext_data rp; | ||
| 5642 | |||
| 5643 | memcpy(rp.hash192, hash192, sizeof(rp.hash192)); | ||
| 5644 | memcpy(rp.randomizer192, randomizer192, | ||
| 5645 | sizeof(rp.randomizer192)); | ||
| 4983 | 5646 | ||
| 4984 | memcpy(rp.hash, hash, sizeof(rp.hash)); | 5647 | memcpy(rp.hash256, hash256, sizeof(rp.hash256)); |
| 4985 | memcpy(rp.randomizer, randomizer, sizeof(rp.randomizer)); | 5648 | memcpy(rp.randomizer256, randomizer256, |
| 5649 | sizeof(rp.randomizer256)); | ||
| 5650 | |||
| 5651 | cmd_complete(cmd->sk, hdev->id, | ||
| 5652 | MGMT_OP_READ_LOCAL_OOB_DATA, 0, | ||
| 5653 | &rp, sizeof(rp)); | ||
| 5654 | } else { | ||
| 5655 | struct mgmt_rp_read_local_oob_data rp; | ||
| 4986 | 5656 | ||
| 4987 | cmd_complete(cmd->sk, hdev->id, MGMT_OP_READ_LOCAL_OOB_DATA, | 5657 | memcpy(rp.hash, hash192, sizeof(rp.hash)); |
| 4988 | 0, &rp, sizeof(rp)); | 5658 | memcpy(rp.randomizer, randomizer192, |
| 5659 | sizeof(rp.randomizer)); | ||
| 5660 | |||
| 5661 | cmd_complete(cmd->sk, hdev->id, | ||
| 5662 | MGMT_OP_READ_LOCAL_OOB_DATA, 0, | ||
| 5663 | &rp, sizeof(rp)); | ||
| 5664 | } | ||
| 4989 | } | 5665 | } |
| 4990 | 5666 | ||
| 4991 | mgmt_pending_remove(cmd); | 5667 | mgmt_pending_remove(cmd); |
| @@ -4997,6 +5673,7 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | |||
| 4997 | { | 5673 | { |
| 4998 | char buf[512]; | 5674 | char buf[512]; |
| 4999 | struct mgmt_ev_device_found *ev = (void *) buf; | 5675 | struct mgmt_ev_device_found *ev = (void *) buf; |
| 5676 | struct smp_irk *irk; | ||
| 5000 | size_t ev_size; | 5677 | size_t ev_size; |
| 5001 | 5678 | ||
| 5002 | if (!hci_discovery_active(hdev)) | 5679 | if (!hci_discovery_active(hdev)) |
| @@ -5008,13 +5685,20 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, | |||
| 5008 | 5685 | ||
| 5009 | memset(buf, 0, sizeof(buf)); | 5686 | memset(buf, 0, sizeof(buf)); |
| 5010 | 5687 | ||
| 5011 | bacpy(&ev->addr.bdaddr, bdaddr); | 5688 | irk = hci_get_irk(hdev, bdaddr, addr_type); |
| 5012 | ev->addr.type = link_to_bdaddr(link_type, addr_type); | 5689 | if (irk) { |
| 5690 | bacpy(&ev->addr.bdaddr, &irk->bdaddr); | ||
| 5691 | ev->addr.type = link_to_bdaddr(link_type, irk->addr_type); | ||
| 5692 | } else { | ||
| 5693 | bacpy(&ev->addr.bdaddr, bdaddr); | ||
| 5694 | ev->addr.type = link_to_bdaddr(link_type, addr_type); | ||
| 5695 | } | ||
| 5696 | |||
| 5013 | ev->rssi = rssi; | 5697 | ev->rssi = rssi; |
| 5014 | if (cfm_name) | 5698 | if (cfm_name) |
| 5015 | ev->flags |= __constant_cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME); | 5699 | ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_CONFIRM_NAME); |
| 5016 | if (!ssp) | 5700 | if (!ssp) |
| 5017 | ev->flags |= __constant_cpu_to_le32(MGMT_DEV_FOUND_LEGACY_PAIRING); | 5701 | ev->flags |= cpu_to_le32(MGMT_DEV_FOUND_LEGACY_PAIRING); |
| 5018 | 5702 | ||
| 5019 | if (eir_len > 0) | 5703 | if (eir_len > 0) |
| 5020 | memcpy(ev->eir, eir, eir_len); | 5704 | memcpy(ev->eir, eir, eir_len); |
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index facd8a79c038..cf620260affa 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c | |||
| @@ -186,9 +186,9 @@ static void rfcomm_l2state_change(struct sock *sk) | |||
| 186 | rfcomm_schedule(); | 186 | rfcomm_schedule(); |
| 187 | } | 187 | } |
| 188 | 188 | ||
| 189 | static void rfcomm_l2data_ready(struct sock *sk, int bytes) | 189 | static void rfcomm_l2data_ready(struct sock *sk) |
| 190 | { | 190 | { |
| 191 | BT_DBG("%p bytes %d", sk, bytes); | 191 | BT_DBG("%p", sk); |
| 192 | rfcomm_schedule(); | 192 | rfcomm_schedule(); |
| 193 | } | 193 | } |
| 194 | 194 | ||
| @@ -216,6 +216,7 @@ static int rfcomm_check_security(struct rfcomm_dlc *d) | |||
| 216 | 216 | ||
| 217 | switch (d->sec_level) { | 217 | switch (d->sec_level) { |
| 218 | case BT_SECURITY_HIGH: | 218 | case BT_SECURITY_HIGH: |
| 219 | case BT_SECURITY_FIPS: | ||
| 219 | auth_type = HCI_AT_GENERAL_BONDING_MITM; | 220 | auth_type = HCI_AT_GENERAL_BONDING_MITM; |
| 220 | break; | 221 | break; |
| 221 | case BT_SECURITY_MEDIUM: | 222 | case BT_SECURITY_MEDIUM: |
| @@ -359,6 +360,11 @@ static struct rfcomm_dlc *rfcomm_dlc_get(struct rfcomm_session *s, u8 dlci) | |||
| 359 | return NULL; | 360 | return NULL; |
| 360 | } | 361 | } |
| 361 | 362 | ||
| 363 | static int rfcomm_check_channel(u8 channel) | ||
| 364 | { | ||
| 365 | return channel < 1 || channel > 30; | ||
| 366 | } | ||
| 367 | |||
| 362 | static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, u8 channel) | 368 | static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, u8 channel) |
| 363 | { | 369 | { |
| 364 | struct rfcomm_session *s; | 370 | struct rfcomm_session *s; |
| @@ -368,7 +374,7 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, | |||
| 368 | BT_DBG("dlc %p state %ld %pMR -> %pMR channel %d", | 374 | BT_DBG("dlc %p state %ld %pMR -> %pMR channel %d", |
| 369 | d, d->state, src, dst, channel); | 375 | d, d->state, src, dst, channel); |
| 370 | 376 | ||
| 371 | if (channel < 1 || channel > 30) | 377 | if (rfcomm_check_channel(channel)) |
| 372 | return -EINVAL; | 378 | return -EINVAL; |
| 373 | 379 | ||
| 374 | if (d->state != BT_OPEN && d->state != BT_CLOSED) | 380 | if (d->state != BT_OPEN && d->state != BT_CLOSED) |
| @@ -425,6 +431,20 @@ int rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, u8 chann | |||
| 425 | return r; | 431 | return r; |
| 426 | } | 432 | } |
| 427 | 433 | ||
| 434 | static void __rfcomm_dlc_disconn(struct rfcomm_dlc *d) | ||
| 435 | { | ||
| 436 | struct rfcomm_session *s = d->session; | ||
| 437 | |||
| 438 | d->state = BT_DISCONN; | ||
| 439 | if (skb_queue_empty(&d->tx_queue)) { | ||
| 440 | rfcomm_send_disc(s, d->dlci); | ||
| 441 | rfcomm_dlc_set_timer(d, RFCOMM_DISC_TIMEOUT); | ||
| 442 | } else { | ||
| 443 | rfcomm_queue_disc(d); | ||
| 444 | rfcomm_dlc_set_timer(d, RFCOMM_DISC_TIMEOUT * 2); | ||
| 445 | } | ||
| 446 | } | ||
| 447 | |||
| 428 | static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err) | 448 | static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err) |
| 429 | { | 449 | { |
| 430 | struct rfcomm_session *s = d->session; | 450 | struct rfcomm_session *s = d->session; |
| @@ -437,32 +457,29 @@ static int __rfcomm_dlc_close(struct rfcomm_dlc *d, int err) | |||
| 437 | switch (d->state) { | 457 | switch (d->state) { |
| 438 | case BT_CONNECT: | 458 | case BT_CONNECT: |
| 439 | case BT_CONFIG: | 459 | case BT_CONFIG: |
| 460 | case BT_OPEN: | ||
| 461 | case BT_CONNECT2: | ||
| 440 | if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) { | 462 | if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) { |
| 441 | set_bit(RFCOMM_AUTH_REJECT, &d->flags); | 463 | set_bit(RFCOMM_AUTH_REJECT, &d->flags); |
| 442 | rfcomm_schedule(); | 464 | rfcomm_schedule(); |
| 443 | break; | 465 | return 0; |
| 444 | } | 466 | } |
| 445 | /* Fall through */ | 467 | } |
| 446 | 468 | ||
| 469 | switch (d->state) { | ||
| 470 | case BT_CONNECT: | ||
| 447 | case BT_CONNECTED: | 471 | case BT_CONNECTED: |
| 448 | d->state = BT_DISCONN; | 472 | __rfcomm_dlc_disconn(d); |
| 449 | if (skb_queue_empty(&d->tx_queue)) { | ||
| 450 | rfcomm_send_disc(s, d->dlci); | ||
| 451 | rfcomm_dlc_set_timer(d, RFCOMM_DISC_TIMEOUT); | ||
| 452 | } else { | ||
| 453 | rfcomm_queue_disc(d); | ||
| 454 | rfcomm_dlc_set_timer(d, RFCOMM_DISC_TIMEOUT * 2); | ||
| 455 | } | ||
| 456 | break; | 473 | break; |
| 457 | 474 | ||
| 458 | case BT_OPEN: | 475 | case BT_CONFIG: |
| 459 | case BT_CONNECT2: | 476 | if (s->state != BT_BOUND) { |
| 460 | if (test_and_clear_bit(RFCOMM_DEFER_SETUP, &d->flags)) { | 477 | __rfcomm_dlc_disconn(d); |
| 461 | set_bit(RFCOMM_AUTH_REJECT, &d->flags); | ||
| 462 | rfcomm_schedule(); | ||
| 463 | break; | 478 | break; |
| 464 | } | 479 | } |
| 465 | /* Fall through */ | 480 | /* if closing a dlc in a session that hasn't been started, |
| 481 | * just close and unlink the dlc | ||
| 482 | */ | ||
| 466 | 483 | ||
| 467 | default: | 484 | default: |
| 468 | rfcomm_dlc_clear_timer(d); | 485 | rfcomm_dlc_clear_timer(d); |
| @@ -513,6 +530,25 @@ no_session: | |||
| 513 | return r; | 530 | return r; |
| 514 | } | 531 | } |
| 515 | 532 | ||
| 533 | struct rfcomm_dlc *rfcomm_dlc_exists(bdaddr_t *src, bdaddr_t *dst, u8 channel) | ||
| 534 | { | ||
| 535 | struct rfcomm_session *s; | ||
| 536 | struct rfcomm_dlc *dlc = NULL; | ||
| 537 | u8 dlci; | ||
| 538 | |||
| 539 | if (rfcomm_check_channel(channel)) | ||
| 540 | return ERR_PTR(-EINVAL); | ||
| 541 | |||
| 542 | rfcomm_lock(); | ||
| 543 | s = rfcomm_session_get(src, dst); | ||
| 544 | if (s) { | ||
| 545 | dlci = __dlci(!s->initiator, channel); | ||
| 546 | dlc = rfcomm_dlc_get(s, dlci); | ||
| 547 | } | ||
| 548 | rfcomm_unlock(); | ||
| 549 | return dlc; | ||
| 550 | } | ||
| 551 | |||
| 516 | int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb) | 552 | int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb) |
| 517 | { | 553 | { |
| 518 | int len = skb->len; | 554 | int len = skb->len; |
| @@ -533,6 +569,20 @@ int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb) | |||
| 533 | return len; | 569 | return len; |
| 534 | } | 570 | } |
| 535 | 571 | ||
| 572 | void rfcomm_dlc_send_noerror(struct rfcomm_dlc *d, struct sk_buff *skb) | ||
| 573 | { | ||
| 574 | int len = skb->len; | ||
| 575 | |||
| 576 | BT_DBG("dlc %p mtu %d len %d", d, d->mtu, len); | ||
| 577 | |||
| 578 | rfcomm_make_uih(skb, d->addr); | ||
| 579 | skb_queue_tail(&d->tx_queue, skb); | ||
| 580 | |||
| 581 | if (d->state == BT_CONNECTED && | ||
| 582 | !test_bit(RFCOMM_TX_THROTTLED, &d->flags)) | ||
| 583 | rfcomm_schedule(); | ||
| 584 | } | ||
| 585 | |||
| 536 | void __rfcomm_dlc_throttle(struct rfcomm_dlc *d) | 586 | void __rfcomm_dlc_throttle(struct rfcomm_dlc *d) |
| 537 | { | 587 | { |
| 538 | BT_DBG("dlc %p state %ld", d, d->state); | 588 | BT_DBG("dlc %p state %ld", d, d->state); |
| @@ -718,7 +768,7 @@ static struct rfcomm_session *rfcomm_session_create(bdaddr_t *src, | |||
| 718 | 768 | ||
| 719 | bacpy(&addr.l2_bdaddr, dst); | 769 | bacpy(&addr.l2_bdaddr, dst); |
| 720 | addr.l2_family = AF_BLUETOOTH; | 770 | addr.l2_family = AF_BLUETOOTH; |
| 721 | addr.l2_psm = __constant_cpu_to_le16(RFCOMM_PSM); | 771 | addr.l2_psm = cpu_to_le16(RFCOMM_PSM); |
| 722 | addr.l2_cid = 0; | 772 | addr.l2_cid = 0; |
| 723 | addr.l2_bdaddr_type = BDADDR_BREDR; | 773 | addr.l2_bdaddr_type = BDADDR_BREDR; |
| 724 | *err = kernel_connect(sock, (struct sockaddr *) &addr, sizeof(addr), O_NONBLOCK); | 774 | *err = kernel_connect(sock, (struct sockaddr *) &addr, sizeof(addr), O_NONBLOCK); |
| @@ -1943,12 +1993,11 @@ static void rfcomm_process_sessions(void) | |||
| 1943 | continue; | 1993 | continue; |
| 1944 | } | 1994 | } |
| 1945 | 1995 | ||
| 1946 | if (s->state == BT_LISTEN) { | 1996 | switch (s->state) { |
| 1997 | case BT_LISTEN: | ||
| 1947 | rfcomm_accept_connection(s); | 1998 | rfcomm_accept_connection(s); |
| 1948 | continue; | 1999 | continue; |
| 1949 | } | ||
| 1950 | 2000 | ||
| 1951 | switch (s->state) { | ||
| 1952 | case BT_BOUND: | 2001 | case BT_BOUND: |
| 1953 | s = rfcomm_check_connection(s); | 2002 | s = rfcomm_check_connection(s); |
| 1954 | break; | 2003 | break; |
| @@ -1983,7 +2032,7 @@ static int rfcomm_add_listener(bdaddr_t *ba) | |||
| 1983 | /* Bind socket */ | 2032 | /* Bind socket */ |
| 1984 | bacpy(&addr.l2_bdaddr, ba); | 2033 | bacpy(&addr.l2_bdaddr, ba); |
| 1985 | addr.l2_family = AF_BLUETOOTH; | 2034 | addr.l2_family = AF_BLUETOOTH; |
| 1986 | addr.l2_psm = __constant_cpu_to_le16(RFCOMM_PSM); | 2035 | addr.l2_psm = cpu_to_le16(RFCOMM_PSM); |
| 1987 | addr.l2_cid = 0; | 2036 | addr.l2_cid = 0; |
| 1988 | addr.l2_bdaddr_type = BDADDR_BREDR; | 2037 | addr.l2_bdaddr_type = BDADDR_BREDR; |
| 1989 | err = kernel_bind(sock, (struct sockaddr *) &addr, sizeof(addr)); | 2038 | err = kernel_bind(sock, (struct sockaddr *) &addr, sizeof(addr)); |
| @@ -2085,7 +2134,8 @@ static void rfcomm_security_cfm(struct hci_conn *conn, u8 status, u8 encrypt) | |||
| 2085 | set_bit(RFCOMM_SEC_PENDING, &d->flags); | 2134 | set_bit(RFCOMM_SEC_PENDING, &d->flags); |
| 2086 | rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT); | 2135 | rfcomm_dlc_set_timer(d, RFCOMM_AUTH_TIMEOUT); |
| 2087 | continue; | 2136 | continue; |
| 2088 | } else if (d->sec_level == BT_SECURITY_HIGH) { | 2137 | } else if (d->sec_level == BT_SECURITY_HIGH || |
| 2138 | d->sec_level == BT_SECURITY_FIPS) { | ||
| 2089 | set_bit(RFCOMM_ENC_DROP, &d->flags); | 2139 | set_bit(RFCOMM_ENC_DROP, &d->flags); |
| 2090 | continue; | 2140 | continue; |
| 2091 | } | 2141 | } |
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index 3c2d3e4aa2f5..c603a5eb4720 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c | |||
| @@ -54,7 +54,7 @@ static void rfcomm_sk_data_ready(struct rfcomm_dlc *d, struct sk_buff *skb) | |||
| 54 | 54 | ||
| 55 | atomic_add(skb->len, &sk->sk_rmem_alloc); | 55 | atomic_add(skb->len, &sk->sk_rmem_alloc); |
| 56 | skb_queue_tail(&sk->sk_receive_queue, skb); | 56 | skb_queue_tail(&sk->sk_receive_queue, skb); |
| 57 | sk->sk_data_ready(sk, skb->len); | 57 | sk->sk_data_ready(sk); |
| 58 | 58 | ||
| 59 | if (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf) | 59 | if (atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf) |
| 60 | rfcomm_dlc_throttle(d); | 60 | rfcomm_dlc_throttle(d); |
| @@ -84,7 +84,7 @@ static void rfcomm_sk_state_change(struct rfcomm_dlc *d, int err) | |||
| 84 | sock_set_flag(sk, SOCK_ZAPPED); | 84 | sock_set_flag(sk, SOCK_ZAPPED); |
| 85 | bt_accept_unlink(sk); | 85 | bt_accept_unlink(sk); |
| 86 | } | 86 | } |
| 87 | parent->sk_data_ready(parent, 0); | 87 | parent->sk_data_ready(parent); |
| 88 | } else { | 88 | } else { |
| 89 | if (d->state == BT_CONNECTED) | 89 | if (d->state == BT_CONNECTED) |
| 90 | rfcomm_session_getaddr(d->session, | 90 | rfcomm_session_getaddr(d->session, |
| @@ -105,13 +105,18 @@ static void rfcomm_sk_state_change(struct rfcomm_dlc *d, int err) | |||
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | /* ---- Socket functions ---- */ | 107 | /* ---- Socket functions ---- */ |
| 108 | static struct sock *__rfcomm_get_sock_by_addr(u8 channel, bdaddr_t *src) | 108 | static struct sock *__rfcomm_get_listen_sock_by_addr(u8 channel, bdaddr_t *src) |
| 109 | { | 109 | { |
| 110 | struct sock *sk = NULL; | 110 | struct sock *sk = NULL; |
| 111 | 111 | ||
| 112 | sk_for_each(sk, &rfcomm_sk_list.head) { | 112 | sk_for_each(sk, &rfcomm_sk_list.head) { |
| 113 | if (rfcomm_pi(sk)->channel == channel && | 113 | if (rfcomm_pi(sk)->channel != channel) |
| 114 | !bacmp(&rfcomm_pi(sk)->src, src)) | 114 | continue; |
| 115 | |||
| 116 | if (bacmp(&rfcomm_pi(sk)->src, src)) | ||
| 117 | continue; | ||
| 118 | |||
| 119 | if (sk->sk_state == BT_BOUND || sk->sk_state == BT_LISTEN) | ||
| 115 | break; | 120 | break; |
| 116 | } | 121 | } |
| 117 | 122 | ||
| @@ -331,6 +336,7 @@ static int rfcomm_sock_bind(struct socket *sock, struct sockaddr *addr, int addr | |||
| 331 | { | 336 | { |
| 332 | struct sockaddr_rc *sa = (struct sockaddr_rc *) addr; | 337 | struct sockaddr_rc *sa = (struct sockaddr_rc *) addr; |
| 333 | struct sock *sk = sock->sk; | 338 | struct sock *sk = sock->sk; |
| 339 | int chan = sa->rc_channel; | ||
| 334 | int err = 0; | 340 | int err = 0; |
| 335 | 341 | ||
| 336 | BT_DBG("sk %p %pMR", sk, &sa->rc_bdaddr); | 342 | BT_DBG("sk %p %pMR", sk, &sa->rc_bdaddr); |
| @@ -352,12 +358,12 @@ static int rfcomm_sock_bind(struct socket *sock, struct sockaddr *addr, int addr | |||
| 352 | 358 | ||
| 353 | write_lock(&rfcomm_sk_list.lock); | 359 | write_lock(&rfcomm_sk_list.lock); |
| 354 | 360 | ||
| 355 | if (sa->rc_channel && __rfcomm_get_sock_by_addr(sa->rc_channel, &sa->rc_bdaddr)) { | 361 | if (chan && __rfcomm_get_listen_sock_by_addr(chan, &sa->rc_bdaddr)) { |
| 356 | err = -EADDRINUSE; | 362 | err = -EADDRINUSE; |
| 357 | } else { | 363 | } else { |
| 358 | /* Save source address */ | 364 | /* Save source address */ |
| 359 | bacpy(&rfcomm_pi(sk)->src, &sa->rc_bdaddr); | 365 | bacpy(&rfcomm_pi(sk)->src, &sa->rc_bdaddr); |
| 360 | rfcomm_pi(sk)->channel = sa->rc_channel; | 366 | rfcomm_pi(sk)->channel = chan; |
| 361 | sk->sk_state = BT_BOUND; | 367 | sk->sk_state = BT_BOUND; |
| 362 | } | 368 | } |
| 363 | 369 | ||
| @@ -439,7 +445,7 @@ static int rfcomm_sock_listen(struct socket *sock, int backlog) | |||
| 439 | write_lock(&rfcomm_sk_list.lock); | 445 | write_lock(&rfcomm_sk_list.lock); |
| 440 | 446 | ||
| 441 | for (channel = 1; channel < 31; channel++) | 447 | for (channel = 1; channel < 31; channel++) |
| 442 | if (!__rfcomm_get_sock_by_addr(channel, src)) { | 448 | if (!__rfcomm_get_listen_sock_by_addr(channel, src)) { |
| 443 | rfcomm_pi(sk)->channel = channel; | 449 | rfcomm_pi(sk)->channel = channel; |
| 444 | err = 0; | 450 | err = 0; |
| 445 | break; | 451 | break; |
| @@ -528,6 +534,10 @@ static int rfcomm_sock_getname(struct socket *sock, struct sockaddr *addr, int * | |||
| 528 | 534 | ||
| 529 | BT_DBG("sock %p, sk %p", sock, sk); | 535 | BT_DBG("sock %p, sk %p", sock, sk); |
| 530 | 536 | ||
| 537 | if (peer && sk->sk_state != BT_CONNECTED && | ||
| 538 | sk->sk_state != BT_CONNECT && sk->sk_state != BT_CONNECT2) | ||
| 539 | return -ENOTCONN; | ||
| 540 | |||
| 531 | memset(sa, 0, sizeof(*sa)); | 541 | memset(sa, 0, sizeof(*sa)); |
| 532 | sa->rc_family = AF_BLUETOOTH; | 542 | sa->rc_family = AF_BLUETOOTH; |
| 533 | sa->rc_channel = rfcomm_pi(sk)->channel; | 543 | sa->rc_channel = rfcomm_pi(sk)->channel; |
| @@ -648,6 +658,11 @@ static int rfcomm_sock_setsockopt_old(struct socket *sock, int optname, char __u | |||
| 648 | break; | 658 | break; |
| 649 | } | 659 | } |
| 650 | 660 | ||
| 661 | if (opt & RFCOMM_LM_FIPS) { | ||
| 662 | err = -EINVAL; | ||
| 663 | break; | ||
| 664 | } | ||
| 665 | |||
| 651 | if (opt & RFCOMM_LM_AUTH) | 666 | if (opt & RFCOMM_LM_AUTH) |
| 652 | rfcomm_pi(sk)->sec_level = BT_SECURITY_LOW; | 667 | rfcomm_pi(sk)->sec_level = BT_SECURITY_LOW; |
| 653 | if (opt & RFCOMM_LM_ENCRYPT) | 668 | if (opt & RFCOMM_LM_ENCRYPT) |
| @@ -762,7 +777,11 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u | |||
| 762 | break; | 777 | break; |
| 763 | case BT_SECURITY_HIGH: | 778 | case BT_SECURITY_HIGH: |
| 764 | opt = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT | | 779 | opt = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT | |
| 765 | RFCOMM_LM_SECURE; | 780 | RFCOMM_LM_SECURE; |
| 781 | break; | ||
| 782 | case BT_SECURITY_FIPS: | ||
| 783 | opt = RFCOMM_LM_AUTH | RFCOMM_LM_ENCRYPT | | ||
| 784 | RFCOMM_LM_SECURE | RFCOMM_LM_FIPS; | ||
| 766 | break; | 785 | break; |
| 767 | default: | 786 | default: |
| 768 | opt = 0; | 787 | opt = 0; |
| @@ -774,6 +793,7 @@ static int rfcomm_sock_getsockopt_old(struct socket *sock, int optname, char __u | |||
| 774 | 793 | ||
| 775 | if (put_user(opt, (u32 __user *) optval)) | 794 | if (put_user(opt, (u32 __user *) optval)) |
| 776 | err = -EFAULT; | 795 | err = -EFAULT; |
| 796 | |||
| 777 | break; | 797 | break; |
| 778 | 798 | ||
| 779 | case RFCOMM_CONNINFO: | 799 | case RFCOMM_CONNINFO: |
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index f9c0980abeea..403ec09f480a 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c | |||
| @@ -40,6 +40,7 @@ | |||
| 40 | #define RFCOMM_TTY_MAJOR 216 /* device node major id of the usb/bluetooth.c driver */ | 40 | #define RFCOMM_TTY_MAJOR 216 /* device node major id of the usb/bluetooth.c driver */ |
| 41 | #define RFCOMM_TTY_MINOR 0 | 41 | #define RFCOMM_TTY_MINOR 0 |
| 42 | 42 | ||
| 43 | static DEFINE_MUTEX(rfcomm_ioctl_mutex); | ||
| 43 | static struct tty_driver *rfcomm_tty_driver; | 44 | static struct tty_driver *rfcomm_tty_driver; |
| 44 | 45 | ||
| 45 | struct rfcomm_dev { | 46 | struct rfcomm_dev { |
| @@ -51,6 +52,8 @@ struct rfcomm_dev { | |||
| 51 | unsigned long flags; | 52 | unsigned long flags; |
| 52 | int err; | 53 | int err; |
| 53 | 54 | ||
| 55 | unsigned long status; /* don't export to userspace */ | ||
| 56 | |||
| 54 | bdaddr_t src; | 57 | bdaddr_t src; |
| 55 | bdaddr_t dst; | 58 | bdaddr_t dst; |
| 56 | u8 channel; | 59 | u8 channel; |
| @@ -58,7 +61,6 @@ struct rfcomm_dev { | |||
| 58 | uint modem_status; | 61 | uint modem_status; |
| 59 | 62 | ||
| 60 | struct rfcomm_dlc *dlc; | 63 | struct rfcomm_dlc *dlc; |
| 61 | wait_queue_head_t conn_wait; | ||
| 62 | 64 | ||
| 63 | struct device *tty_dev; | 65 | struct device *tty_dev; |
| 64 | 66 | ||
| @@ -83,10 +85,6 @@ static void rfcomm_dev_destruct(struct tty_port *port) | |||
| 83 | 85 | ||
| 84 | BT_DBG("dev %p dlc %p", dev, dlc); | 86 | BT_DBG("dev %p dlc %p", dev, dlc); |
| 85 | 87 | ||
| 86 | spin_lock(&rfcomm_dev_lock); | ||
| 87 | list_del(&dev->list); | ||
| 88 | spin_unlock(&rfcomm_dev_lock); | ||
| 89 | |||
| 90 | rfcomm_dlc_lock(dlc); | 88 | rfcomm_dlc_lock(dlc); |
| 91 | /* Detach DLC if it's owned by this dev */ | 89 | /* Detach DLC if it's owned by this dev */ |
| 92 | if (dlc->owner == dev) | 90 | if (dlc->owner == dev) |
| @@ -95,7 +93,12 @@ static void rfcomm_dev_destruct(struct tty_port *port) | |||
| 95 | 93 | ||
| 96 | rfcomm_dlc_put(dlc); | 94 | rfcomm_dlc_put(dlc); |
| 97 | 95 | ||
| 98 | tty_unregister_device(rfcomm_tty_driver, dev->id); | 96 | if (dev->tty_dev) |
| 97 | tty_unregister_device(rfcomm_tty_driver, dev->id); | ||
| 98 | |||
| 99 | spin_lock(&rfcomm_dev_lock); | ||
| 100 | list_del(&dev->list); | ||
| 101 | spin_unlock(&rfcomm_dev_lock); | ||
| 99 | 102 | ||
| 100 | kfree(dev); | 103 | kfree(dev); |
| 101 | 104 | ||
| @@ -104,60 +107,24 @@ static void rfcomm_dev_destruct(struct tty_port *port) | |||
| 104 | module_put(THIS_MODULE); | 107 | module_put(THIS_MODULE); |
| 105 | } | 108 | } |
| 106 | 109 | ||
| 107 | static struct device *rfcomm_get_device(struct rfcomm_dev *dev) | ||
| 108 | { | ||
| 109 | struct hci_dev *hdev; | ||
| 110 | struct hci_conn *conn; | ||
| 111 | |||
| 112 | hdev = hci_get_route(&dev->dst, &dev->src); | ||
| 113 | if (!hdev) | ||
| 114 | return NULL; | ||
| 115 | |||
| 116 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &dev->dst); | ||
| 117 | |||
| 118 | hci_dev_put(hdev); | ||
| 119 | |||
| 120 | return conn ? &conn->dev : NULL; | ||
| 121 | } | ||
| 122 | |||
| 123 | /* device-specific initialization: open the dlc */ | 110 | /* device-specific initialization: open the dlc */ |
| 124 | static int rfcomm_dev_activate(struct tty_port *port, struct tty_struct *tty) | 111 | static int rfcomm_dev_activate(struct tty_port *port, struct tty_struct *tty) |
| 125 | { | 112 | { |
| 126 | struct rfcomm_dev *dev = container_of(port, struct rfcomm_dev, port); | 113 | struct rfcomm_dev *dev = container_of(port, struct rfcomm_dev, port); |
| 127 | DEFINE_WAIT(wait); | ||
| 128 | int err; | 114 | int err; |
| 129 | 115 | ||
| 130 | err = rfcomm_dlc_open(dev->dlc, &dev->src, &dev->dst, dev->channel); | 116 | err = rfcomm_dlc_open(dev->dlc, &dev->src, &dev->dst, dev->channel); |
| 131 | if (err) | 117 | if (err) |
| 132 | return err; | 118 | set_bit(TTY_IO_ERROR, &tty->flags); |
| 133 | 119 | return err; | |
| 134 | while (1) { | 120 | } |
| 135 | prepare_to_wait(&dev->conn_wait, &wait, TASK_INTERRUPTIBLE); | ||
| 136 | |||
| 137 | if (dev->dlc->state == BT_CLOSED) { | ||
| 138 | err = -dev->err; | ||
| 139 | break; | ||
| 140 | } | ||
| 141 | |||
| 142 | if (dev->dlc->state == BT_CONNECTED) | ||
| 143 | break; | ||
| 144 | |||
| 145 | if (signal_pending(current)) { | ||
| 146 | err = -ERESTARTSYS; | ||
| 147 | break; | ||
| 148 | } | ||
| 149 | |||
| 150 | tty_unlock(tty); | ||
| 151 | schedule(); | ||
| 152 | tty_lock(tty); | ||
| 153 | } | ||
| 154 | finish_wait(&dev->conn_wait, &wait); | ||
| 155 | 121 | ||
| 156 | if (!err) | 122 | /* we block the open until the dlc->state becomes BT_CONNECTED */ |
| 157 | device_move(dev->tty_dev, rfcomm_get_device(dev), | 123 | static int rfcomm_dev_carrier_raised(struct tty_port *port) |
| 158 | DPM_ORDER_DEV_AFTER_PARENT); | 124 | { |
| 125 | struct rfcomm_dev *dev = container_of(port, struct rfcomm_dev, port); | ||
| 159 | 126 | ||
| 160 | return err; | 127 | return (dev->dlc->state == BT_CONNECTED); |
| 161 | } | 128 | } |
| 162 | 129 | ||
| 163 | /* device-specific cleanup: close the dlc */ | 130 | /* device-specific cleanup: close the dlc */ |
| @@ -176,9 +143,10 @@ static const struct tty_port_operations rfcomm_port_ops = { | |||
| 176 | .destruct = rfcomm_dev_destruct, | 143 | .destruct = rfcomm_dev_destruct, |
| 177 | .activate = rfcomm_dev_activate, | 144 | .activate = rfcomm_dev_activate, |
| 178 | .shutdown = rfcomm_dev_shutdown, | 145 | .shutdown = rfcomm_dev_shutdown, |
| 146 | .carrier_raised = rfcomm_dev_carrier_raised, | ||
| 179 | }; | 147 | }; |
| 180 | 148 | ||
| 181 | static struct rfcomm_dev *__rfcomm_dev_get(int id) | 149 | static struct rfcomm_dev *__rfcomm_dev_lookup(int id) |
| 182 | { | 150 | { |
| 183 | struct rfcomm_dev *dev; | 151 | struct rfcomm_dev *dev; |
| 184 | 152 | ||
| @@ -195,20 +163,41 @@ static struct rfcomm_dev *rfcomm_dev_get(int id) | |||
| 195 | 163 | ||
| 196 | spin_lock(&rfcomm_dev_lock); | 164 | spin_lock(&rfcomm_dev_lock); |
| 197 | 165 | ||
| 198 | dev = __rfcomm_dev_get(id); | 166 | dev = __rfcomm_dev_lookup(id); |
| 199 | 167 | ||
| 200 | if (dev) { | 168 | if (dev && !tty_port_get(&dev->port)) |
| 201 | if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) | 169 | dev = NULL; |
| 202 | dev = NULL; | ||
| 203 | else | ||
| 204 | tty_port_get(&dev->port); | ||
| 205 | } | ||
| 206 | 170 | ||
| 207 | spin_unlock(&rfcomm_dev_lock); | 171 | spin_unlock(&rfcomm_dev_lock); |
| 208 | 172 | ||
| 209 | return dev; | 173 | return dev; |
| 210 | } | 174 | } |
| 211 | 175 | ||
| 176 | static void rfcomm_reparent_device(struct rfcomm_dev *dev) | ||
| 177 | { | ||
| 178 | struct hci_dev *hdev; | ||
| 179 | struct hci_conn *conn; | ||
| 180 | |||
| 181 | hdev = hci_get_route(&dev->dst, &dev->src); | ||
| 182 | if (!hdev) | ||
| 183 | return; | ||
| 184 | |||
| 185 | /* The lookup results are unsafe to access without the | ||
| 186 | * hci device lock (FIXME: why is this not documented?) | ||
| 187 | */ | ||
| 188 | hci_dev_lock(hdev); | ||
| 189 | conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &dev->dst); | ||
| 190 | |||
| 191 | /* Just because the acl link is in the hash table is no | ||
| 192 | * guarantee the sysfs device has been added ... | ||
| 193 | */ | ||
| 194 | if (conn && device_is_registered(&conn->dev)) | ||
| 195 | device_move(dev->tty_dev, &conn->dev, DPM_ORDER_DEV_AFTER_PARENT); | ||
| 196 | |||
| 197 | hci_dev_unlock(hdev); | ||
| 198 | hci_dev_put(hdev); | ||
| 199 | } | ||
| 200 | |||
| 212 | static ssize_t show_address(struct device *tty_dev, struct device_attribute *attr, char *buf) | 201 | static ssize_t show_address(struct device *tty_dev, struct device_attribute *attr, char *buf) |
| 213 | { | 202 | { |
| 214 | struct rfcomm_dev *dev = dev_get_drvdata(tty_dev); | 203 | struct rfcomm_dev *dev = dev_get_drvdata(tty_dev); |
| @@ -224,17 +213,16 @@ static ssize_t show_channel(struct device *tty_dev, struct device_attribute *att | |||
| 224 | static DEVICE_ATTR(address, S_IRUGO, show_address, NULL); | 213 | static DEVICE_ATTR(address, S_IRUGO, show_address, NULL); |
| 225 | static DEVICE_ATTR(channel, S_IRUGO, show_channel, NULL); | 214 | static DEVICE_ATTR(channel, S_IRUGO, show_channel, NULL); |
| 226 | 215 | ||
| 227 | static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc) | 216 | static struct rfcomm_dev *__rfcomm_dev_add(struct rfcomm_dev_req *req, |
| 217 | struct rfcomm_dlc *dlc) | ||
| 228 | { | 218 | { |
| 229 | struct rfcomm_dev *dev, *entry; | 219 | struct rfcomm_dev *dev, *entry; |
| 230 | struct list_head *head = &rfcomm_dev_list; | 220 | struct list_head *head = &rfcomm_dev_list; |
| 231 | int err = 0; | 221 | int err = 0; |
| 232 | 222 | ||
| 233 | BT_DBG("id %d channel %d", req->dev_id, req->channel); | ||
| 234 | |||
| 235 | dev = kzalloc(sizeof(struct rfcomm_dev), GFP_KERNEL); | 223 | dev = kzalloc(sizeof(struct rfcomm_dev), GFP_KERNEL); |
| 236 | if (!dev) | 224 | if (!dev) |
| 237 | return -ENOMEM; | 225 | return ERR_PTR(-ENOMEM); |
| 238 | 226 | ||
| 239 | spin_lock(&rfcomm_dev_lock); | 227 | spin_lock(&rfcomm_dev_lock); |
| 240 | 228 | ||
| @@ -282,7 +270,6 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc) | |||
| 282 | 270 | ||
| 283 | tty_port_init(&dev->port); | 271 | tty_port_init(&dev->port); |
| 284 | dev->port.ops = &rfcomm_port_ops; | 272 | dev->port.ops = &rfcomm_port_ops; |
| 285 | init_waitqueue_head(&dev->conn_wait); | ||
| 286 | 273 | ||
| 287 | skb_queue_head_init(&dev->pending); | 274 | skb_queue_head_init(&dev->pending); |
| 288 | 275 | ||
| @@ -318,22 +305,37 @@ static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc) | |||
| 318 | holds reference to this module. */ | 305 | holds reference to this module. */ |
| 319 | __module_get(THIS_MODULE); | 306 | __module_get(THIS_MODULE); |
| 320 | 307 | ||
| 308 | spin_unlock(&rfcomm_dev_lock); | ||
| 309 | return dev; | ||
| 310 | |||
| 321 | out: | 311 | out: |
| 322 | spin_unlock(&rfcomm_dev_lock); | 312 | spin_unlock(&rfcomm_dev_lock); |
| 313 | kfree(dev); | ||
| 314 | return ERR_PTR(err); | ||
| 315 | } | ||
| 316 | |||
| 317 | static int rfcomm_dev_add(struct rfcomm_dev_req *req, struct rfcomm_dlc *dlc) | ||
| 318 | { | ||
| 319 | struct rfcomm_dev *dev; | ||
| 320 | struct device *tty; | ||
| 321 | |||
| 322 | BT_DBG("id %d channel %d", req->dev_id, req->channel); | ||
| 323 | 323 | ||
| 324 | if (err < 0) | 324 | dev = __rfcomm_dev_add(req, dlc); |
| 325 | goto free; | 325 | if (IS_ERR(dev)) { |
| 326 | rfcomm_dlc_put(dlc); | ||
| 327 | return PTR_ERR(dev); | ||
| 328 | } | ||
| 326 | 329 | ||
| 327 | dev->tty_dev = tty_port_register_device(&dev->port, rfcomm_tty_driver, | 330 | tty = tty_port_register_device(&dev->port, rfcomm_tty_driver, |
| 328 | dev->id, NULL); | 331 | dev->id, NULL); |
| 329 | if (IS_ERR(dev->tty_dev)) { | 332 | if (IS_ERR(tty)) { |
| 330 | err = PTR_ERR(dev->tty_dev); | 333 | tty_port_put(&dev->port); |
| 331 | spin_lock(&rfcomm_dev_lock); | 334 | return PTR_ERR(tty); |
| 332 | list_del(&dev->list); | ||
| 333 | spin_unlock(&rfcomm_dev_lock); | ||
| 334 | goto free; | ||
| 335 | } | 335 | } |
| 336 | 336 | ||
| 337 | dev->tty_dev = tty; | ||
| 338 | rfcomm_reparent_device(dev); | ||
| 337 | dev_set_drvdata(dev->tty_dev, dev); | 339 | dev_set_drvdata(dev->tty_dev, dev); |
| 338 | 340 | ||
| 339 | if (device_create_file(dev->tty_dev, &dev_attr_address) < 0) | 341 | if (device_create_file(dev->tty_dev, &dev_attr_address) < 0) |
| @@ -343,24 +345,23 @@ out: | |||
| 343 | BT_ERR("Failed to create channel attribute"); | 345 | BT_ERR("Failed to create channel attribute"); |
| 344 | 346 | ||
| 345 | return dev->id; | 347 | return dev->id; |
| 346 | |||
| 347 | free: | ||
| 348 | kfree(dev); | ||
| 349 | return err; | ||
| 350 | } | 348 | } |
| 351 | 349 | ||
| 352 | /* ---- Send buffer ---- */ | 350 | /* ---- Send buffer ---- */ |
| 353 | static inline unsigned int rfcomm_room(struct rfcomm_dlc *dlc) | 351 | static inline unsigned int rfcomm_room(struct rfcomm_dev *dev) |
| 354 | { | 352 | { |
| 355 | /* We can't let it be zero, because we don't get a callback | 353 | struct rfcomm_dlc *dlc = dev->dlc; |
| 356 | when tx_credits becomes nonzero, hence we'd never wake up */ | 354 | |
| 357 | return dlc->mtu * (dlc->tx_credits?:1); | 355 | /* Limit the outstanding number of packets not yet sent to 40 */ |
| 356 | int pending = 40 - atomic_read(&dev->wmem_alloc); | ||
| 357 | |||
| 358 | return max(0, pending) * dlc->mtu; | ||
| 358 | } | 359 | } |
| 359 | 360 | ||
| 360 | static void rfcomm_wfree(struct sk_buff *skb) | 361 | static void rfcomm_wfree(struct sk_buff *skb) |
| 361 | { | 362 | { |
| 362 | struct rfcomm_dev *dev = (void *) skb->sk; | 363 | struct rfcomm_dev *dev = (void *) skb->sk; |
| 363 | atomic_sub(skb->truesize, &dev->wmem_alloc); | 364 | atomic_dec(&dev->wmem_alloc); |
| 364 | if (test_bit(RFCOMM_TTY_ATTACHED, &dev->flags)) | 365 | if (test_bit(RFCOMM_TTY_ATTACHED, &dev->flags)) |
| 365 | tty_port_tty_wakeup(&dev->port); | 366 | tty_port_tty_wakeup(&dev->port); |
| 366 | tty_port_put(&dev->port); | 367 | tty_port_put(&dev->port); |
| @@ -369,28 +370,24 @@ static void rfcomm_wfree(struct sk_buff *skb) | |||
| 369 | static void rfcomm_set_owner_w(struct sk_buff *skb, struct rfcomm_dev *dev) | 370 | static void rfcomm_set_owner_w(struct sk_buff *skb, struct rfcomm_dev *dev) |
| 370 | { | 371 | { |
| 371 | tty_port_get(&dev->port); | 372 | tty_port_get(&dev->port); |
| 372 | atomic_add(skb->truesize, &dev->wmem_alloc); | 373 | atomic_inc(&dev->wmem_alloc); |
| 373 | skb->sk = (void *) dev; | 374 | skb->sk = (void *) dev; |
| 374 | skb->destructor = rfcomm_wfree; | 375 | skb->destructor = rfcomm_wfree; |
| 375 | } | 376 | } |
| 376 | 377 | ||
| 377 | static struct sk_buff *rfcomm_wmalloc(struct rfcomm_dev *dev, unsigned long size, gfp_t priority) | 378 | static struct sk_buff *rfcomm_wmalloc(struct rfcomm_dev *dev, unsigned long size, gfp_t priority) |
| 378 | { | 379 | { |
| 379 | if (atomic_read(&dev->wmem_alloc) < rfcomm_room(dev->dlc)) { | 380 | struct sk_buff *skb = alloc_skb(size, priority); |
| 380 | struct sk_buff *skb = alloc_skb(size, priority); | 381 | if (skb) |
| 381 | if (skb) { | 382 | rfcomm_set_owner_w(skb, dev); |
| 382 | rfcomm_set_owner_w(skb, dev); | 383 | return skb; |
| 383 | return skb; | ||
| 384 | } | ||
| 385 | } | ||
| 386 | return NULL; | ||
| 387 | } | 384 | } |
| 388 | 385 | ||
| 389 | /* ---- Device IOCTLs ---- */ | 386 | /* ---- Device IOCTLs ---- */ |
| 390 | 387 | ||
| 391 | #define NOCAP_FLAGS ((1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEASE_ONHUP)) | 388 | #define NOCAP_FLAGS ((1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEASE_ONHUP)) |
| 392 | 389 | ||
| 393 | static int rfcomm_create_dev(struct sock *sk, void __user *arg) | 390 | static int __rfcomm_create_dev(struct sock *sk, void __user *arg) |
| 394 | { | 391 | { |
| 395 | struct rfcomm_dev_req req; | 392 | struct rfcomm_dev_req req; |
| 396 | struct rfcomm_dlc *dlc; | 393 | struct rfcomm_dlc *dlc; |
| @@ -412,16 +409,22 @@ static int rfcomm_create_dev(struct sock *sk, void __user *arg) | |||
| 412 | dlc = rfcomm_pi(sk)->dlc; | 409 | dlc = rfcomm_pi(sk)->dlc; |
| 413 | rfcomm_dlc_hold(dlc); | 410 | rfcomm_dlc_hold(dlc); |
| 414 | } else { | 411 | } else { |
| 412 | /* Validate the channel is unused */ | ||
| 413 | dlc = rfcomm_dlc_exists(&req.src, &req.dst, req.channel); | ||
| 414 | if (IS_ERR(dlc)) | ||
| 415 | return PTR_ERR(dlc); | ||
| 416 | else if (dlc) { | ||
| 417 | rfcomm_dlc_put(dlc); | ||
| 418 | return -EBUSY; | ||
| 419 | } | ||
| 415 | dlc = rfcomm_dlc_alloc(GFP_KERNEL); | 420 | dlc = rfcomm_dlc_alloc(GFP_KERNEL); |
| 416 | if (!dlc) | 421 | if (!dlc) |
| 417 | return -ENOMEM; | 422 | return -ENOMEM; |
| 418 | } | 423 | } |
| 419 | 424 | ||
| 420 | id = rfcomm_dev_add(&req, dlc); | 425 | id = rfcomm_dev_add(&req, dlc); |
| 421 | if (id < 0) { | 426 | if (id < 0) |
| 422 | rfcomm_dlc_put(dlc); | ||
| 423 | return id; | 427 | return id; |
| 424 | } | ||
| 425 | 428 | ||
| 426 | if (req.flags & (1 << RFCOMM_REUSE_DLC)) { | 429 | if (req.flags & (1 << RFCOMM_REUSE_DLC)) { |
| 427 | /* DLC is now used by device. | 430 | /* DLC is now used by device. |
| @@ -432,7 +435,7 @@ static int rfcomm_create_dev(struct sock *sk, void __user *arg) | |||
| 432 | return id; | 435 | return id; |
| 433 | } | 436 | } |
| 434 | 437 | ||
| 435 | static int rfcomm_release_dev(void __user *arg) | 438 | static int __rfcomm_release_dev(void __user *arg) |
| 436 | { | 439 | { |
| 437 | struct rfcomm_dev_req req; | 440 | struct rfcomm_dev_req req; |
| 438 | struct rfcomm_dev *dev; | 441 | struct rfcomm_dev *dev; |
| @@ -452,6 +455,12 @@ static int rfcomm_release_dev(void __user *arg) | |||
| 452 | return -EPERM; | 455 | return -EPERM; |
| 453 | } | 456 | } |
| 454 | 457 | ||
| 458 | /* only release once */ | ||
| 459 | if (test_and_set_bit(RFCOMM_DEV_RELEASED, &dev->status)) { | ||
| 460 | tty_port_put(&dev->port); | ||
| 461 | return -EALREADY; | ||
| 462 | } | ||
| 463 | |||
| 455 | if (req.flags & (1 << RFCOMM_HANGUP_NOW)) | 464 | if (req.flags & (1 << RFCOMM_HANGUP_NOW)) |
| 456 | rfcomm_dlc_close(dev->dlc, 0); | 465 | rfcomm_dlc_close(dev->dlc, 0); |
| 457 | 466 | ||
| @@ -462,14 +471,35 @@ static int rfcomm_release_dev(void __user *arg) | |||
| 462 | tty_kref_put(tty); | 471 | tty_kref_put(tty); |
| 463 | } | 472 | } |
| 464 | 473 | ||
| 465 | if (!test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags) && | 474 | if (!test_bit(RFCOMM_TTY_OWNED, &dev->status)) |
| 466 | !test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags)) | ||
| 467 | tty_port_put(&dev->port); | 475 | tty_port_put(&dev->port); |
| 468 | 476 | ||
| 469 | tty_port_put(&dev->port); | 477 | tty_port_put(&dev->port); |
| 470 | return 0; | 478 | return 0; |
| 471 | } | 479 | } |
| 472 | 480 | ||
| 481 | static int rfcomm_create_dev(struct sock *sk, void __user *arg) | ||
| 482 | { | ||
| 483 | int ret; | ||
| 484 | |||
| 485 | mutex_lock(&rfcomm_ioctl_mutex); | ||
| 486 | ret = __rfcomm_create_dev(sk, arg); | ||
| 487 | mutex_unlock(&rfcomm_ioctl_mutex); | ||
| 488 | |||
| 489 | return ret; | ||
| 490 | } | ||
| 491 | |||
| 492 | static int rfcomm_release_dev(void __user *arg) | ||
| 493 | { | ||
| 494 | int ret; | ||
| 495 | |||
| 496 | mutex_lock(&rfcomm_ioctl_mutex); | ||
| 497 | ret = __rfcomm_release_dev(arg); | ||
| 498 | mutex_unlock(&rfcomm_ioctl_mutex); | ||
| 499 | |||
| 500 | return ret; | ||
| 501 | } | ||
| 502 | |||
| 473 | static int rfcomm_get_dev_list(void __user *arg) | 503 | static int rfcomm_get_dev_list(void __user *arg) |
| 474 | { | 504 | { |
| 475 | struct rfcomm_dev *dev; | 505 | struct rfcomm_dev *dev; |
| @@ -497,7 +527,7 @@ static int rfcomm_get_dev_list(void __user *arg) | |||
| 497 | spin_lock(&rfcomm_dev_lock); | 527 | spin_lock(&rfcomm_dev_lock); |
| 498 | 528 | ||
| 499 | list_for_each_entry(dev, &rfcomm_dev_list, list) { | 529 | list_for_each_entry(dev, &rfcomm_dev_list, list) { |
| 500 | if (test_bit(RFCOMM_TTY_RELEASED, &dev->flags)) | 530 | if (!tty_port_get(&dev->port)) |
| 501 | continue; | 531 | continue; |
| 502 | (di + n)->id = dev->id; | 532 | (di + n)->id = dev->id; |
| 503 | (di + n)->flags = dev->flags; | 533 | (di + n)->flags = dev->flags; |
| @@ -505,6 +535,7 @@ static int rfcomm_get_dev_list(void __user *arg) | |||
| 505 | (di + n)->channel = dev->channel; | 535 | (di + n)->channel = dev->channel; |
| 506 | bacpy(&(di + n)->src, &dev->src); | 536 | bacpy(&(di + n)->src, &dev->src); |
| 507 | bacpy(&(di + n)->dst, &dev->dst); | 537 | bacpy(&(di + n)->dst, &dev->dst); |
| 538 | tty_port_put(&dev->port); | ||
| 508 | if (++n >= dev_num) | 539 | if (++n >= dev_num) |
| 509 | break; | 540 | break; |
| 510 | } | 541 | } |
| @@ -601,9 +632,11 @@ static void rfcomm_dev_state_change(struct rfcomm_dlc *dlc, int err) | |||
| 601 | BT_DBG("dlc %p dev %p err %d", dlc, dev, err); | 632 | BT_DBG("dlc %p dev %p err %d", dlc, dev, err); |
| 602 | 633 | ||
| 603 | dev->err = err; | 634 | dev->err = err; |
| 604 | wake_up_interruptible(&dev->conn_wait); | 635 | if (dlc->state == BT_CONNECTED) { |
| 636 | rfcomm_reparent_device(dev); | ||
| 605 | 637 | ||
| 606 | if (dlc->state == BT_CLOSED) | 638 | wake_up_interruptible(&dev->port.open_wait); |
| 639 | } else if (dlc->state == BT_CLOSED) | ||
| 607 | tty_port_tty_hangup(&dev->port, false); | 640 | tty_port_tty_hangup(&dev->port, false); |
| 608 | } | 641 | } |
| 609 | 642 | ||
| @@ -703,8 +736,10 @@ static int rfcomm_tty_install(struct tty_driver *driver, struct tty_struct *tty) | |||
| 703 | * when the last process closes the tty. The behaviour is expected by | 736 | * when the last process closes the tty. The behaviour is expected by |
| 704 | * userspace. | 737 | * userspace. |
| 705 | */ | 738 | */ |
| 706 | if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) | 739 | if (test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags)) { |
| 740 | set_bit(RFCOMM_TTY_OWNED, &dev->status); | ||
| 707 | tty_port_put(&dev->port); | 741 | tty_port_put(&dev->port); |
| 742 | } | ||
| 708 | 743 | ||
| 709 | return 0; | 744 | return 0; |
| 710 | } | 745 | } |
| @@ -750,7 +785,7 @@ static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, in | |||
| 750 | struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; | 785 | struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; |
| 751 | struct rfcomm_dlc *dlc = dev->dlc; | 786 | struct rfcomm_dlc *dlc = dev->dlc; |
| 752 | struct sk_buff *skb; | 787 | struct sk_buff *skb; |
| 753 | int err = 0, sent = 0, size; | 788 | int sent = 0, size; |
| 754 | 789 | ||
| 755 | BT_DBG("tty %p count %d", tty, count); | 790 | BT_DBG("tty %p count %d", tty, count); |
| 756 | 791 | ||
| @@ -758,7 +793,6 @@ static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, in | |||
| 758 | size = min_t(uint, count, dlc->mtu); | 793 | size = min_t(uint, count, dlc->mtu); |
| 759 | 794 | ||
| 760 | skb = rfcomm_wmalloc(dev, size + RFCOMM_SKB_RESERVE, GFP_ATOMIC); | 795 | skb = rfcomm_wmalloc(dev, size + RFCOMM_SKB_RESERVE, GFP_ATOMIC); |
| 761 | |||
| 762 | if (!skb) | 796 | if (!skb) |
| 763 | break; | 797 | break; |
| 764 | 798 | ||
| @@ -766,32 +800,24 @@ static int rfcomm_tty_write(struct tty_struct *tty, const unsigned char *buf, in | |||
| 766 | 800 | ||
| 767 | memcpy(skb_put(skb, size), buf + sent, size); | 801 | memcpy(skb_put(skb, size), buf + sent, size); |
| 768 | 802 | ||
| 769 | err = rfcomm_dlc_send(dlc, skb); | 803 | rfcomm_dlc_send_noerror(dlc, skb); |
| 770 | if (err < 0) { | ||
| 771 | kfree_skb(skb); | ||
| 772 | break; | ||
| 773 | } | ||
| 774 | 804 | ||
| 775 | sent += size; | 805 | sent += size; |
| 776 | count -= size; | 806 | count -= size; |
| 777 | } | 807 | } |
| 778 | 808 | ||
| 779 | return sent ? sent : err; | 809 | return sent; |
| 780 | } | 810 | } |
| 781 | 811 | ||
| 782 | static int rfcomm_tty_write_room(struct tty_struct *tty) | 812 | static int rfcomm_tty_write_room(struct tty_struct *tty) |
| 783 | { | 813 | { |
| 784 | struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; | 814 | struct rfcomm_dev *dev = (struct rfcomm_dev *) tty->driver_data; |
| 785 | int room; | 815 | int room = 0; |
| 786 | 816 | ||
| 787 | BT_DBG("tty %p", tty); | 817 | if (dev && dev->dlc) |
| 788 | 818 | room = rfcomm_room(dev); | |
| 789 | if (!dev || !dev->dlc) | ||
| 790 | return 0; | ||
| 791 | 819 | ||
| 792 | room = rfcomm_room(dev->dlc) - atomic_read(&dev->wmem_alloc); | 820 | BT_DBG("tty %p room %d", tty, room); |
| 793 | if (room < 0) | ||
| 794 | room = 0; | ||
| 795 | 821 | ||
| 796 | return room; | 822 | return room; |
| 797 | } | 823 | } |
| @@ -1125,7 +1151,7 @@ int __init rfcomm_init_ttys(void) | |||
| 1125 | rfcomm_tty_driver->subtype = SERIAL_TYPE_NORMAL; | 1151 | rfcomm_tty_driver->subtype = SERIAL_TYPE_NORMAL; |
| 1126 | rfcomm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; | 1152 | rfcomm_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV; |
| 1127 | rfcomm_tty_driver->init_termios = tty_std_termios; | 1153 | rfcomm_tty_driver->init_termios = tty_std_termios; |
| 1128 | rfcomm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL; | 1154 | rfcomm_tty_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL; |
| 1129 | rfcomm_tty_driver->init_termios.c_lflag &= ~ICANON; | 1155 | rfcomm_tty_driver->init_termios.c_lflag &= ~ICANON; |
| 1130 | tty_set_operations(rfcomm_tty_driver, &rfcomm_ops); | 1156 | tty_set_operations(rfcomm_tty_driver, &rfcomm_ops); |
| 1131 | 1157 | ||
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index 24fa3964b3c8..c06dbd3938e8 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c | |||
| @@ -676,20 +676,20 @@ static void sco_conn_defer_accept(struct hci_conn *conn, u16 setting) | |||
| 676 | bacpy(&cp.bdaddr, &conn->dst); | 676 | bacpy(&cp.bdaddr, &conn->dst); |
| 677 | cp.pkt_type = cpu_to_le16(conn->pkt_type); | 677 | cp.pkt_type = cpu_to_le16(conn->pkt_type); |
| 678 | 678 | ||
| 679 | cp.tx_bandwidth = __constant_cpu_to_le32(0x00001f40); | 679 | cp.tx_bandwidth = cpu_to_le32(0x00001f40); |
| 680 | cp.rx_bandwidth = __constant_cpu_to_le32(0x00001f40); | 680 | cp.rx_bandwidth = cpu_to_le32(0x00001f40); |
| 681 | cp.content_format = cpu_to_le16(setting); | 681 | cp.content_format = cpu_to_le16(setting); |
| 682 | 682 | ||
| 683 | switch (setting & SCO_AIRMODE_MASK) { | 683 | switch (setting & SCO_AIRMODE_MASK) { |
| 684 | case SCO_AIRMODE_TRANSP: | 684 | case SCO_AIRMODE_TRANSP: |
| 685 | if (conn->pkt_type & ESCO_2EV3) | 685 | if (conn->pkt_type & ESCO_2EV3) |
| 686 | cp.max_latency = __constant_cpu_to_le16(0x0008); | 686 | cp.max_latency = cpu_to_le16(0x0008); |
| 687 | else | 687 | else |
| 688 | cp.max_latency = __constant_cpu_to_le16(0x000D); | 688 | cp.max_latency = cpu_to_le16(0x000D); |
| 689 | cp.retrans_effort = 0x02; | 689 | cp.retrans_effort = 0x02; |
| 690 | break; | 690 | break; |
| 691 | case SCO_AIRMODE_CVSD: | 691 | case SCO_AIRMODE_CVSD: |
| 692 | cp.max_latency = __constant_cpu_to_le16(0xffff); | 692 | cp.max_latency = cpu_to_le16(0xffff); |
| 693 | cp.retrans_effort = 0xff; | 693 | cp.retrans_effort = 0xff; |
| 694 | break; | 694 | break; |
| 695 | } | 695 | } |
| @@ -1024,7 +1024,7 @@ static void sco_conn_ready(struct sco_conn *conn) | |||
| 1024 | sk->sk_state = BT_CONNECTED; | 1024 | sk->sk_state = BT_CONNECTED; |
| 1025 | 1025 | ||
| 1026 | /* Wake up parent */ | 1026 | /* Wake up parent */ |
| 1027 | parent->sk_data_ready(parent, 1); | 1027 | parent->sk_data_ready(parent); |
| 1028 | 1028 | ||
| 1029 | bh_unlock_sock(parent); | 1029 | bh_unlock_sock(parent); |
| 1030 | 1030 | ||
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 45007362683b..dfb4e1161c10 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
| @@ -35,14 +35,14 @@ | |||
| 35 | 35 | ||
| 36 | #define AUTH_REQ_MASK 0x07 | 36 | #define AUTH_REQ_MASK 0x07 |
| 37 | 37 | ||
| 38 | static inline void swap128(u8 src[16], u8 dst[16]) | 38 | static inline void swap128(const u8 src[16], u8 dst[16]) |
| 39 | { | 39 | { |
| 40 | int i; | 40 | int i; |
| 41 | for (i = 0; i < 16; i++) | 41 | for (i = 0; i < 16; i++) |
| 42 | dst[15 - i] = src[i]; | 42 | dst[15 - i] = src[i]; |
| 43 | } | 43 | } |
| 44 | 44 | ||
| 45 | static inline void swap56(u8 src[7], u8 dst[7]) | 45 | static inline void swap56(const u8 src[7], u8 dst[7]) |
| 46 | { | 46 | { |
| 47 | int i; | 47 | int i; |
| 48 | for (i = 0; i < 7; i++) | 48 | for (i = 0; i < 7; i++) |
| @@ -53,6 +53,7 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r) | |||
| 53 | { | 53 | { |
| 54 | struct blkcipher_desc desc; | 54 | struct blkcipher_desc desc; |
| 55 | struct scatterlist sg; | 55 | struct scatterlist sg; |
| 56 | uint8_t tmp[16], data[16]; | ||
| 56 | int err; | 57 | int err; |
| 57 | 58 | ||
| 58 | if (tfm == NULL) { | 59 | if (tfm == NULL) { |
| @@ -63,21 +64,89 @@ static int smp_e(struct crypto_blkcipher *tfm, const u8 *k, u8 *r) | |||
| 63 | desc.tfm = tfm; | 64 | desc.tfm = tfm; |
| 64 | desc.flags = 0; | 65 | desc.flags = 0; |
| 65 | 66 | ||
| 66 | err = crypto_blkcipher_setkey(tfm, k, 16); | 67 | /* The most significant octet of key corresponds to k[0] */ |
| 68 | swap128(k, tmp); | ||
| 69 | |||
| 70 | err = crypto_blkcipher_setkey(tfm, tmp, 16); | ||
| 67 | if (err) { | 71 | if (err) { |
| 68 | BT_ERR("cipher setkey failed: %d", err); | 72 | BT_ERR("cipher setkey failed: %d", err); |
| 69 | return err; | 73 | return err; |
| 70 | } | 74 | } |
| 71 | 75 | ||
| 72 | sg_init_one(&sg, r, 16); | 76 | /* Most significant octet of plaintextData corresponds to data[0] */ |
| 77 | swap128(r, data); | ||
| 78 | |||
| 79 | sg_init_one(&sg, data, 16); | ||
| 73 | 80 | ||
| 74 | err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16); | 81 | err = crypto_blkcipher_encrypt(&desc, &sg, &sg, 16); |
| 75 | if (err) | 82 | if (err) |
| 76 | BT_ERR("Encrypt data error %d", err); | 83 | BT_ERR("Encrypt data error %d", err); |
| 77 | 84 | ||
| 85 | /* Most significant octet of encryptedData corresponds to data[0] */ | ||
| 86 | swap128(data, r); | ||
| 87 | |||
| 78 | return err; | 88 | return err; |
| 79 | } | 89 | } |
| 80 | 90 | ||
| 91 | static int smp_ah(struct crypto_blkcipher *tfm, u8 irk[16], u8 r[3], u8 res[3]) | ||
| 92 | { | ||
| 93 | u8 _res[16]; | ||
| 94 | int err; | ||
| 95 | |||
| 96 | /* r' = padding || r */ | ||
| 97 | memcpy(_res, r, 3); | ||
| 98 | memset(_res + 3, 0, 13); | ||
| 99 | |||
| 100 | err = smp_e(tfm, irk, _res); | ||
| 101 | if (err) { | ||
| 102 | BT_ERR("Encrypt error"); | ||
| 103 | return err; | ||
| 104 | } | ||
| 105 | |||
| 106 | /* The output of the random address function ah is: | ||
| 107 | * ah(h, r) = e(k, r') mod 2^24 | ||
| 108 | * The output of the security function e is then truncated to 24 bits | ||
| 109 | * by taking the least significant 24 bits of the output of e as the | ||
| 110 | * result of ah. | ||
| 111 | */ | ||
| 112 | memcpy(res, _res, 3); | ||
| 113 | |||
| 114 | return 0; | ||
| 115 | } | ||
| 116 | |||
| 117 | bool smp_irk_matches(struct crypto_blkcipher *tfm, u8 irk[16], | ||
| 118 | bdaddr_t *bdaddr) | ||
| 119 | { | ||
| 120 | u8 hash[3]; | ||
| 121 | int err; | ||
| 122 | |||
| 123 | BT_DBG("RPA %pMR IRK %*phN", bdaddr, 16, irk); | ||
| 124 | |||
| 125 | err = smp_ah(tfm, irk, &bdaddr->b[3], hash); | ||
| 126 | if (err) | ||
| 127 | return false; | ||
| 128 | |||
| 129 | return !memcmp(bdaddr->b, hash, 3); | ||
| 130 | } | ||
| 131 | |||
| 132 | int smp_generate_rpa(struct crypto_blkcipher *tfm, u8 irk[16], bdaddr_t *rpa) | ||
| 133 | { | ||
| 134 | int err; | ||
| 135 | |||
| 136 | get_random_bytes(&rpa->b[3], 3); | ||
| 137 | |||
| 138 | rpa->b[5] &= 0x3f; /* Clear two most significant bits */ | ||
| 139 | rpa->b[5] |= 0x40; /* Set second most significant bit */ | ||
| 140 | |||
| 141 | err = smp_ah(tfm, irk, &rpa->b[3], rpa->b); | ||
| 142 | if (err < 0) | ||
| 143 | return err; | ||
| 144 | |||
| 145 | BT_DBG("RPA %pMR", rpa); | ||
| 146 | |||
| 147 | return 0; | ||
| 148 | } | ||
| 149 | |||
| 81 | static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16], | 150 | static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16], |
| 82 | u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia, | 151 | u8 preq[7], u8 pres[7], u8 _iat, bdaddr_t *ia, |
| 83 | u8 _rat, bdaddr_t *ra, u8 res[16]) | 152 | u8 _rat, bdaddr_t *ra, u8 res[16]) |
| @@ -88,16 +157,15 @@ static int smp_c1(struct crypto_blkcipher *tfm, u8 k[16], u8 r[16], | |||
| 88 | memset(p1, 0, 16); | 157 | memset(p1, 0, 16); |
| 89 | 158 | ||
| 90 | /* p1 = pres || preq || _rat || _iat */ | 159 | /* p1 = pres || preq || _rat || _iat */ |
| 91 | swap56(pres, p1); | 160 | p1[0] = _iat; |
| 92 | swap56(preq, p1 + 7); | 161 | p1[1] = _rat; |
| 93 | p1[14] = _rat; | 162 | memcpy(p1 + 2, preq, 7); |
| 94 | p1[15] = _iat; | 163 | memcpy(p1 + 9, pres, 7); |
| 95 | |||
| 96 | memset(p2, 0, 16); | ||
| 97 | 164 | ||
| 98 | /* p2 = padding || ia || ra */ | 165 | /* p2 = padding || ia || ra */ |
| 99 | baswap((bdaddr_t *) (p2 + 4), ia); | 166 | memcpy(p2, ra, 6); |
| 100 | baswap((bdaddr_t *) (p2 + 10), ra); | 167 | memcpy(p2 + 6, ia, 6); |
| 168 | memset(p2 + 12, 0, 4); | ||
| 101 | 169 | ||
| 102 | /* res = r XOR p1 */ | 170 | /* res = r XOR p1 */ |
| 103 | u128_xor((u128 *) res, (u128 *) r, (u128 *) p1); | 171 | u128_xor((u128 *) res, (u128 *) r, (u128 *) p1); |
| @@ -126,8 +194,8 @@ static int smp_s1(struct crypto_blkcipher *tfm, u8 k[16], u8 r1[16], | |||
| 126 | int err; | 194 | int err; |
| 127 | 195 | ||
| 128 | /* Just least significant octets from r1 and r2 are considered */ | 196 | /* Just least significant octets from r1 and r2 are considered */ |
| 129 | memcpy(_r, r1 + 8, 8); | 197 | memcpy(_r, r2, 8); |
| 130 | memcpy(_r + 8, r2 + 8, 8); | 198 | memcpy(_r + 8, r1, 8); |
| 131 | 199 | ||
| 132 | err = smp_e(tfm, k, _r); | 200 | err = smp_e(tfm, k, _r); |
| 133 | if (err) | 201 | if (err) |
| @@ -154,7 +222,7 @@ static struct sk_buff *smp_build_cmd(struct l2cap_conn *conn, u8 code, | |||
| 154 | 222 | ||
| 155 | lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); | 223 | lh = (struct l2cap_hdr *) skb_put(skb, L2CAP_HDR_SIZE); |
| 156 | lh->len = cpu_to_le16(sizeof(code) + dlen); | 224 | lh->len = cpu_to_le16(sizeof(code) + dlen); |
| 157 | lh->cid = __constant_cpu_to_le16(L2CAP_CID_SMP); | 225 | lh->cid = cpu_to_le16(L2CAP_CID_SMP); |
| 158 | 226 | ||
| 159 | memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code)); | 227 | memcpy(skb_put(skb, sizeof(code)), &code, sizeof(code)); |
| 160 | 228 | ||
| @@ -203,31 +271,45 @@ static void build_pairing_cmd(struct l2cap_conn *conn, | |||
| 203 | struct smp_cmd_pairing *req, | 271 | struct smp_cmd_pairing *req, |
| 204 | struct smp_cmd_pairing *rsp, __u8 authreq) | 272 | struct smp_cmd_pairing *rsp, __u8 authreq) |
| 205 | { | 273 | { |
| 206 | u8 dist_keys = 0; | 274 | struct smp_chan *smp = conn->smp_chan; |
| 275 | struct hci_conn *hcon = conn->hcon; | ||
| 276 | struct hci_dev *hdev = hcon->hdev; | ||
| 277 | u8 local_dist = 0, remote_dist = 0; | ||
| 207 | 278 | ||
| 208 | if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->dev_flags)) { | 279 | if (test_bit(HCI_PAIRABLE, &conn->hcon->hdev->dev_flags)) { |
| 209 | dist_keys = SMP_DIST_ENC_KEY; | 280 | local_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN; |
| 281 | remote_dist = SMP_DIST_ENC_KEY | SMP_DIST_SIGN; | ||
| 210 | authreq |= SMP_AUTH_BONDING; | 282 | authreq |= SMP_AUTH_BONDING; |
| 211 | } else { | 283 | } else { |
| 212 | authreq &= ~SMP_AUTH_BONDING; | 284 | authreq &= ~SMP_AUTH_BONDING; |
| 213 | } | 285 | } |
| 214 | 286 | ||
| 287 | if (test_bit(HCI_RPA_RESOLVING, &hdev->dev_flags)) | ||
| 288 | remote_dist |= SMP_DIST_ID_KEY; | ||
| 289 | |||
| 290 | if (test_bit(HCI_PRIVACY, &hdev->dev_flags)) | ||
| 291 | local_dist |= SMP_DIST_ID_KEY; | ||
| 292 | |||
| 215 | if (rsp == NULL) { | 293 | if (rsp == NULL) { |
| 216 | req->io_capability = conn->hcon->io_capability; | 294 | req->io_capability = conn->hcon->io_capability; |
| 217 | req->oob_flag = SMP_OOB_NOT_PRESENT; | 295 | req->oob_flag = SMP_OOB_NOT_PRESENT; |
| 218 | req->max_key_size = SMP_MAX_ENC_KEY_SIZE; | 296 | req->max_key_size = SMP_MAX_ENC_KEY_SIZE; |
| 219 | req->init_key_dist = 0; | 297 | req->init_key_dist = local_dist; |
| 220 | req->resp_key_dist = dist_keys; | 298 | req->resp_key_dist = remote_dist; |
| 221 | req->auth_req = (authreq & AUTH_REQ_MASK); | 299 | req->auth_req = (authreq & AUTH_REQ_MASK); |
| 300 | |||
| 301 | smp->remote_key_dist = remote_dist; | ||
| 222 | return; | 302 | return; |
| 223 | } | 303 | } |
| 224 | 304 | ||
| 225 | rsp->io_capability = conn->hcon->io_capability; | 305 | rsp->io_capability = conn->hcon->io_capability; |
| 226 | rsp->oob_flag = SMP_OOB_NOT_PRESENT; | 306 | rsp->oob_flag = SMP_OOB_NOT_PRESENT; |
| 227 | rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE; | 307 | rsp->max_key_size = SMP_MAX_ENC_KEY_SIZE; |
| 228 | rsp->init_key_dist = 0; | 308 | rsp->init_key_dist = req->init_key_dist & remote_dist; |
| 229 | rsp->resp_key_dist = req->resp_key_dist & dist_keys; | 309 | rsp->resp_key_dist = req->resp_key_dist & local_dist; |
| 230 | rsp->auth_req = (authreq & AUTH_REQ_MASK); | 310 | rsp->auth_req = (authreq & AUTH_REQ_MASK); |
| 311 | |||
| 312 | smp->remote_key_dist = rsp->init_key_dist; | ||
| 231 | } | 313 | } |
| 232 | 314 | ||
| 233 | static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size) | 315 | static u8 check_enc_key_size(struct l2cap_conn *conn, __u8 max_key_size) |
| @@ -305,6 +387,11 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth, | |||
| 305 | if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM) | 387 | if (!(auth & SMP_AUTH_BONDING) && method == JUST_CFM) |
| 306 | method = JUST_WORKS; | 388 | method = JUST_WORKS; |
| 307 | 389 | ||
| 390 | /* Don't confirm locally initiated pairing attempts */ | ||
| 391 | if (method == JUST_CFM && test_bit(SMP_FLAG_INITIATOR, | ||
| 392 | &smp->smp_flags)) | ||
| 393 | method = JUST_WORKS; | ||
| 394 | |||
| 308 | /* If Just Works, Continue with Zero TK */ | 395 | /* If Just Works, Continue with Zero TK */ |
| 309 | if (method == JUST_WORKS) { | 396 | if (method == JUST_WORKS) { |
| 310 | set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags); | 397 | set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags); |
| @@ -325,16 +412,14 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth, | |||
| 325 | method = REQ_PASSKEY; | 412 | method = REQ_PASSKEY; |
| 326 | } | 413 | } |
| 327 | 414 | ||
| 328 | /* Generate random passkey. Not valid until confirmed. */ | 415 | /* Generate random passkey. */ |
| 329 | if (method == CFM_PASSKEY) { | 416 | if (method == CFM_PASSKEY) { |
| 330 | u8 key[16]; | 417 | memset(smp->tk, 0, sizeof(smp->tk)); |
| 331 | |||
| 332 | memset(key, 0, sizeof(key)); | ||
| 333 | get_random_bytes(&passkey, sizeof(passkey)); | 418 | get_random_bytes(&passkey, sizeof(passkey)); |
| 334 | passkey %= 1000000; | 419 | passkey %= 1000000; |
| 335 | put_unaligned_le32(passkey, key); | 420 | put_unaligned_le32(passkey, smp->tk); |
| 336 | swap128(key, smp->tk); | ||
| 337 | BT_DBG("PassKey: %d", passkey); | 421 | BT_DBG("PassKey: %d", passkey); |
| 422 | set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags); | ||
| 338 | } | 423 | } |
| 339 | 424 | ||
| 340 | hci_dev_lock(hcon->hdev); | 425 | hci_dev_lock(hcon->hdev); |
| @@ -342,10 +427,14 @@ static int tk_request(struct l2cap_conn *conn, u8 remote_oob, u8 auth, | |||
| 342 | if (method == REQ_PASSKEY) | 427 | if (method == REQ_PASSKEY) |
| 343 | ret = mgmt_user_passkey_request(hcon->hdev, &hcon->dst, | 428 | ret = mgmt_user_passkey_request(hcon->hdev, &hcon->dst, |
| 344 | hcon->type, hcon->dst_type); | 429 | hcon->type, hcon->dst_type); |
| 345 | else | 430 | else if (method == JUST_CFM) |
| 346 | ret = mgmt_user_confirm_request(hcon->hdev, &hcon->dst, | 431 | ret = mgmt_user_confirm_request(hcon->hdev, &hcon->dst, |
| 347 | hcon->type, hcon->dst_type, | 432 | hcon->type, hcon->dst_type, |
| 348 | cpu_to_le32(passkey), 0); | 433 | passkey, 1); |
| 434 | else | ||
| 435 | ret = mgmt_user_passkey_notify(hcon->hdev, &hcon->dst, | ||
| 436 | hcon->type, hcon->dst_type, | ||
| 437 | passkey, 0); | ||
| 349 | 438 | ||
| 350 | hci_dev_unlock(hcon->hdev); | 439 | hci_dev_unlock(hcon->hdev); |
| 351 | 440 | ||
| @@ -356,29 +445,24 @@ static void confirm_work(struct work_struct *work) | |||
| 356 | { | 445 | { |
| 357 | struct smp_chan *smp = container_of(work, struct smp_chan, confirm); | 446 | struct smp_chan *smp = container_of(work, struct smp_chan, confirm); |
| 358 | struct l2cap_conn *conn = smp->conn; | 447 | struct l2cap_conn *conn = smp->conn; |
| 359 | struct crypto_blkcipher *tfm; | 448 | struct hci_dev *hdev = conn->hcon->hdev; |
| 449 | struct crypto_blkcipher *tfm = hdev->tfm_aes; | ||
| 360 | struct smp_cmd_pairing_confirm cp; | 450 | struct smp_cmd_pairing_confirm cp; |
| 361 | int ret; | 451 | int ret; |
| 362 | u8 res[16], reason; | 452 | u8 reason; |
| 363 | 453 | ||
| 364 | BT_DBG("conn %p", conn); | 454 | BT_DBG("conn %p", conn); |
| 365 | 455 | ||
| 366 | tfm = crypto_alloc_blkcipher("ecb(aes)", 0, CRYPTO_ALG_ASYNC); | 456 | /* Prevent mutual access to hdev->tfm_aes */ |
| 367 | if (IS_ERR(tfm)) { | 457 | hci_dev_lock(hdev); |
| 368 | reason = SMP_UNSPECIFIED; | ||
| 369 | goto error; | ||
| 370 | } | ||
| 371 | 458 | ||
| 372 | smp->tfm = tfm; | 459 | ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, |
| 460 | conn->hcon->init_addr_type, &conn->hcon->init_addr, | ||
| 461 | conn->hcon->resp_addr_type, &conn->hcon->resp_addr, | ||
| 462 | cp.confirm_val); | ||
| 463 | |||
| 464 | hci_dev_unlock(hdev); | ||
| 373 | 465 | ||
| 374 | if (conn->hcon->out) | ||
| 375 | ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, | ||
| 376 | conn->hcon->src_type, &conn->hcon->src, | ||
| 377 | conn->hcon->dst_type, &conn->hcon->dst, res); | ||
| 378 | else | ||
| 379 | ret = smp_c1(tfm, smp->tk, smp->prnd, smp->preq, smp->prsp, | ||
| 380 | conn->hcon->dst_type, &conn->hcon->dst, | ||
| 381 | conn->hcon->src_type, &conn->hcon->src, res); | ||
| 382 | if (ret) { | 466 | if (ret) { |
| 383 | reason = SMP_UNSPECIFIED; | 467 | reason = SMP_UNSPECIFIED; |
| 384 | goto error; | 468 | goto error; |
| @@ -386,7 +470,6 @@ static void confirm_work(struct work_struct *work) | |||
| 386 | 470 | ||
| 387 | clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags); | 471 | clear_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags); |
| 388 | 472 | ||
| 389 | swap128(res, cp.confirm_val); | ||
| 390 | smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp); | 473 | smp_send_cmd(smp->conn, SMP_CMD_PAIRING_CONFIRM, sizeof(cp), &cp); |
| 391 | 474 | ||
| 392 | return; | 475 | return; |
| @@ -400,8 +483,9 @@ static void random_work(struct work_struct *work) | |||
| 400 | struct smp_chan *smp = container_of(work, struct smp_chan, random); | 483 | struct smp_chan *smp = container_of(work, struct smp_chan, random); |
| 401 | struct l2cap_conn *conn = smp->conn; | 484 | struct l2cap_conn *conn = smp->conn; |
| 402 | struct hci_conn *hcon = conn->hcon; | 485 | struct hci_conn *hcon = conn->hcon; |
| 403 | struct crypto_blkcipher *tfm = smp->tfm; | 486 | struct hci_dev *hdev = hcon->hdev; |
| 404 | u8 reason, confirm[16], res[16], key[16]; | 487 | struct crypto_blkcipher *tfm = hdev->tfm_aes; |
| 488 | u8 reason, confirm[16]; | ||
| 405 | int ret; | 489 | int ret; |
| 406 | 490 | ||
| 407 | if (IS_ERR_OR_NULL(tfm)) { | 491 | if (IS_ERR_OR_NULL(tfm)) { |
| @@ -411,21 +495,20 @@ static void random_work(struct work_struct *work) | |||
| 411 | 495 | ||
| 412 | BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); | 496 | BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); |
| 413 | 497 | ||
| 414 | if (hcon->out) | 498 | /* Prevent mutual access to hdev->tfm_aes */ |
| 415 | ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, | 499 | hci_dev_lock(hdev); |
| 416 | hcon->src_type, &hcon->src, | 500 | |
| 417 | hcon->dst_type, &hcon->dst, res); | 501 | ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, |
| 418 | else | 502 | hcon->init_addr_type, &hcon->init_addr, |
| 419 | ret = smp_c1(tfm, smp->tk, smp->rrnd, smp->preq, smp->prsp, | 503 | hcon->resp_addr_type, &hcon->resp_addr, confirm); |
| 420 | hcon->dst_type, &hcon->dst, | 504 | |
| 421 | hcon->src_type, &hcon->src, res); | 505 | hci_dev_unlock(hdev); |
| 506 | |||
| 422 | if (ret) { | 507 | if (ret) { |
| 423 | reason = SMP_UNSPECIFIED; | 508 | reason = SMP_UNSPECIFIED; |
| 424 | goto error; | 509 | goto error; |
| 425 | } | 510 | } |
| 426 | 511 | ||
| 427 | swap128(res, confirm); | ||
| 428 | |||
| 429 | if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) { | 512 | if (memcmp(smp->pcnf, confirm, sizeof(smp->pcnf)) != 0) { |
| 430 | BT_ERR("Pairing failed (confirmation values mismatch)"); | 513 | BT_ERR("Pairing failed (confirmation values mismatch)"); |
| 431 | reason = SMP_CONFIRM_FAILED; | 514 | reason = SMP_CONFIRM_FAILED; |
| @@ -433,14 +516,11 @@ static void random_work(struct work_struct *work) | |||
| 433 | } | 516 | } |
| 434 | 517 | ||
| 435 | if (hcon->out) { | 518 | if (hcon->out) { |
| 436 | u8 stk[16], rand[8]; | 519 | u8 stk[16]; |
| 437 | __le16 ediv; | 520 | __le64 rand = 0; |
| 438 | 521 | __le16 ediv = 0; | |
| 439 | memset(rand, 0, sizeof(rand)); | ||
| 440 | ediv = 0; | ||
| 441 | 522 | ||
| 442 | smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, key); | 523 | smp_s1(tfm, smp->tk, smp->rrnd, smp->prnd, stk); |
| 443 | swap128(key, stk); | ||
| 444 | 524 | ||
| 445 | memset(stk + smp->enc_key_size, 0, | 525 | memset(stk + smp->enc_key_size, 0, |
| 446 | SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size); | 526 | SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size); |
| @@ -453,23 +533,20 @@ static void random_work(struct work_struct *work) | |||
| 453 | hci_le_start_enc(hcon, ediv, rand, stk); | 533 | hci_le_start_enc(hcon, ediv, rand, stk); |
| 454 | hcon->enc_key_size = smp->enc_key_size; | 534 | hcon->enc_key_size = smp->enc_key_size; |
| 455 | } else { | 535 | } else { |
| 456 | u8 stk[16], r[16], rand[8]; | 536 | u8 stk[16]; |
| 457 | __le16 ediv; | 537 | __le64 rand = 0; |
| 458 | 538 | __le16 ediv = 0; | |
| 459 | memset(rand, 0, sizeof(rand)); | ||
| 460 | ediv = 0; | ||
| 461 | 539 | ||
| 462 | swap128(smp->prnd, r); | 540 | smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd), |
| 463 | smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(r), r); | 541 | smp->prnd); |
| 464 | 542 | ||
| 465 | smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, key); | 543 | smp_s1(tfm, smp->tk, smp->prnd, smp->rrnd, stk); |
| 466 | swap128(key, stk); | ||
| 467 | 544 | ||
| 468 | memset(stk + smp->enc_key_size, 0, | 545 | memset(stk + smp->enc_key_size, 0, |
| 469 | SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size); | 546 | SMP_MAX_ENC_KEY_SIZE - smp->enc_key_size); |
| 470 | 547 | ||
| 471 | hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, | 548 | hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, |
| 472 | HCI_SMP_STK_SLAVE, 0, 0, stk, smp->enc_key_size, | 549 | HCI_SMP_STK_SLAVE, 0, stk, smp->enc_key_size, |
| 473 | ediv, rand); | 550 | ediv, rand); |
| 474 | } | 551 | } |
| 475 | 552 | ||
| @@ -502,11 +579,33 @@ static struct smp_chan *smp_chan_create(struct l2cap_conn *conn) | |||
| 502 | void smp_chan_destroy(struct l2cap_conn *conn) | 579 | void smp_chan_destroy(struct l2cap_conn *conn) |
| 503 | { | 580 | { |
| 504 | struct smp_chan *smp = conn->smp_chan; | 581 | struct smp_chan *smp = conn->smp_chan; |
| 582 | bool complete; | ||
| 505 | 583 | ||
| 506 | BUG_ON(!smp); | 584 | BUG_ON(!smp); |
| 507 | 585 | ||
| 508 | if (smp->tfm) | 586 | complete = test_bit(SMP_FLAG_COMPLETE, &smp->smp_flags); |
| 509 | crypto_free_blkcipher(smp->tfm); | 587 | mgmt_smp_complete(conn->hcon, complete); |
| 588 | |||
| 589 | kfree(smp->csrk); | ||
| 590 | kfree(smp->slave_csrk); | ||
| 591 | |||
| 592 | /* If pairing failed clean up any keys we might have */ | ||
| 593 | if (!complete) { | ||
| 594 | if (smp->ltk) { | ||
| 595 | list_del(&smp->ltk->list); | ||
| 596 | kfree(smp->ltk); | ||
| 597 | } | ||
| 598 | |||
| 599 | if (smp->slave_ltk) { | ||
| 600 | list_del(&smp->slave_ltk->list); | ||
| 601 | kfree(smp->slave_ltk); | ||
| 602 | } | ||
| 603 | |||
| 604 | if (smp->remote_irk) { | ||
| 605 | list_del(&smp->remote_irk->list); | ||
| 606 | kfree(smp->remote_irk); | ||
| 607 | } | ||
| 608 | } | ||
| 510 | 609 | ||
| 511 | kfree(smp); | 610 | kfree(smp); |
| 512 | conn->smp_chan = NULL; | 611 | conn->smp_chan = NULL; |
| @@ -519,7 +618,6 @@ int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey) | |||
| 519 | struct l2cap_conn *conn = hcon->smp_conn; | 618 | struct l2cap_conn *conn = hcon->smp_conn; |
| 520 | struct smp_chan *smp; | 619 | struct smp_chan *smp; |
| 521 | u32 value; | 620 | u32 value; |
| 522 | u8 key[16]; | ||
| 523 | 621 | ||
| 524 | BT_DBG(""); | 622 | BT_DBG(""); |
| 525 | 623 | ||
| @@ -531,10 +629,9 @@ int smp_user_confirm_reply(struct hci_conn *hcon, u16 mgmt_op, __le32 passkey) | |||
| 531 | switch (mgmt_op) { | 629 | switch (mgmt_op) { |
| 532 | case MGMT_OP_USER_PASSKEY_REPLY: | 630 | case MGMT_OP_USER_PASSKEY_REPLY: |
| 533 | value = le32_to_cpu(passkey); | 631 | value = le32_to_cpu(passkey); |
| 534 | memset(key, 0, sizeof(key)); | 632 | memset(smp->tk, 0, sizeof(smp->tk)); |
| 535 | BT_DBG("PassKey: %d", value); | 633 | BT_DBG("PassKey: %d", value); |
| 536 | put_unaligned_le32(value, key); | 634 | put_unaligned_le32(value, smp->tk); |
| 537 | swap128(key, smp->tk); | ||
| 538 | /* Fall Through */ | 635 | /* Fall Through */ |
| 539 | case MGMT_OP_USER_CONFIRM_REPLY: | 636 | case MGMT_OP_USER_CONFIRM_REPLY: |
| 540 | set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags); | 637 | set_bit(SMP_FLAG_TK_VALID, &smp->smp_flags); |
| @@ -565,6 +662,9 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
| 565 | 662 | ||
| 566 | BT_DBG("conn %p", conn); | 663 | BT_DBG("conn %p", conn); |
| 567 | 664 | ||
| 665 | if (skb->len < sizeof(*req)) | ||
| 666 | return SMP_UNSPECIFIED; | ||
| 667 | |||
| 568 | if (conn->hcon->link_mode & HCI_LM_MASTER) | 668 | if (conn->hcon->link_mode & HCI_LM_MASTER) |
| 569 | return SMP_CMD_NOTSUPP; | 669 | return SMP_CMD_NOTSUPP; |
| 570 | 670 | ||
| @@ -604,6 +704,8 @@ static u8 smp_cmd_pairing_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
| 604 | if (ret) | 704 | if (ret) |
| 605 | return SMP_UNSPECIFIED; | 705 | return SMP_UNSPECIFIED; |
| 606 | 706 | ||
| 707 | clear_bit(SMP_FLAG_INITIATOR, &smp->smp_flags); | ||
| 708 | |||
| 607 | return 0; | 709 | return 0; |
| 608 | } | 710 | } |
| 609 | 711 | ||
| @@ -617,6 +719,9 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) | |||
| 617 | 719 | ||
| 618 | BT_DBG("conn %p", conn); | 720 | BT_DBG("conn %p", conn); |
| 619 | 721 | ||
| 722 | if (skb->len < sizeof(*rsp)) | ||
| 723 | return SMP_UNSPECIFIED; | ||
| 724 | |||
| 620 | if (!(conn->hcon->link_mode & HCI_LM_MASTER)) | 725 | if (!(conn->hcon->link_mode & HCI_LM_MASTER)) |
| 621 | return SMP_CMD_NOTSUPP; | 726 | return SMP_CMD_NOTSUPP; |
| 622 | 727 | ||
| @@ -633,6 +738,11 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) | |||
| 633 | smp->prsp[0] = SMP_CMD_PAIRING_RSP; | 738 | smp->prsp[0] = SMP_CMD_PAIRING_RSP; |
| 634 | memcpy(&smp->prsp[1], rsp, sizeof(*rsp)); | 739 | memcpy(&smp->prsp[1], rsp, sizeof(*rsp)); |
| 635 | 740 | ||
| 741 | /* Update remote key distribution in case the remote cleared | ||
| 742 | * some bits that we had enabled in our request. | ||
| 743 | */ | ||
| 744 | smp->remote_key_dist &= rsp->resp_key_dist; | ||
| 745 | |||
| 636 | if ((req->auth_req & SMP_AUTH_BONDING) && | 746 | if ((req->auth_req & SMP_AUTH_BONDING) && |
| 637 | (rsp->auth_req & SMP_AUTH_BONDING)) | 747 | (rsp->auth_req & SMP_AUTH_BONDING)) |
| 638 | auth = SMP_AUTH_BONDING; | 748 | auth = SMP_AUTH_BONDING; |
| @@ -646,10 +756,8 @@ static u8 smp_cmd_pairing_rsp(struct l2cap_conn *conn, struct sk_buff *skb) | |||
| 646 | set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags); | 756 | set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags); |
| 647 | 757 | ||
| 648 | /* Can't compose response until we have been confirmed */ | 758 | /* Can't compose response until we have been confirmed */ |
| 649 | if (!test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) | 759 | if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) |
| 650 | return 0; | 760 | queue_work(hdev->workqueue, &smp->confirm); |
| 651 | |||
| 652 | queue_work(hdev->workqueue, &smp->confirm); | ||
| 653 | 761 | ||
| 654 | return 0; | 762 | return 0; |
| 655 | } | 763 | } |
| @@ -661,20 +769,19 @@ static u8 smp_cmd_pairing_confirm(struct l2cap_conn *conn, struct sk_buff *skb) | |||
| 661 | 769 | ||
| 662 | BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); | 770 | BT_DBG("conn %p %s", conn, conn->hcon->out ? "master" : "slave"); |
| 663 | 771 | ||
| 772 | if (skb->len < sizeof(smp->pcnf)) | ||
| 773 | return SMP_UNSPECIFIED; | ||
| 774 | |||
| 664 | memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf)); | 775 | memcpy(smp->pcnf, skb->data, sizeof(smp->pcnf)); |
| 665 | skb_pull(skb, sizeof(smp->pcnf)); | 776 | skb_pull(skb, sizeof(smp->pcnf)); |
| 666 | 777 | ||
| 667 | if (conn->hcon->out) { | 778 | if (conn->hcon->out) |
| 668 | u8 random[16]; | 779 | smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(smp->prnd), |
| 669 | 780 | smp->prnd); | |
| 670 | swap128(smp->prnd, random); | 781 | else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) |
| 671 | smp_send_cmd(conn, SMP_CMD_PAIRING_RANDOM, sizeof(random), | ||
| 672 | random); | ||
| 673 | } else if (test_bit(SMP_FLAG_TK_VALID, &smp->smp_flags)) { | ||
| 674 | queue_work(hdev->workqueue, &smp->confirm); | 782 | queue_work(hdev->workqueue, &smp->confirm); |
| 675 | } else { | 783 | else |
| 676 | set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags); | 784 | set_bit(SMP_FLAG_CFM_PENDING, &smp->smp_flags); |
| 677 | } | ||
| 678 | 785 | ||
| 679 | return 0; | 786 | return 0; |
| 680 | } | 787 | } |
| @@ -686,7 +793,10 @@ static u8 smp_cmd_pairing_random(struct l2cap_conn *conn, struct sk_buff *skb) | |||
| 686 | 793 | ||
| 687 | BT_DBG("conn %p", conn); | 794 | BT_DBG("conn %p", conn); |
| 688 | 795 | ||
| 689 | swap128(skb->data, smp->rrnd); | 796 | if (skb->len < sizeof(smp->rrnd)) |
| 797 | return SMP_UNSPECIFIED; | ||
| 798 | |||
| 799 | memcpy(smp->rrnd, skb->data, sizeof(smp->rrnd)); | ||
| 690 | skb_pull(skb, sizeof(smp->rrnd)); | 800 | skb_pull(skb, sizeof(smp->rrnd)); |
| 691 | 801 | ||
| 692 | queue_work(hdev->workqueue, &smp->random); | 802 | queue_work(hdev->workqueue, &smp->random); |
| @@ -699,7 +809,8 @@ static u8 smp_ltk_encrypt(struct l2cap_conn *conn, u8 sec_level) | |||
| 699 | struct smp_ltk *key; | 809 | struct smp_ltk *key; |
| 700 | struct hci_conn *hcon = conn->hcon; | 810 | struct hci_conn *hcon = conn->hcon; |
| 701 | 811 | ||
| 702 | key = hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type); | 812 | key = hci_find_ltk_by_addr(hcon->hdev, &hcon->dst, hcon->dst_type, |
| 813 | hcon->out); | ||
| 703 | if (!key) | 814 | if (!key) |
| 704 | return 0; | 815 | return 0; |
| 705 | 816 | ||
| @@ -724,6 +835,9 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
| 724 | 835 | ||
| 725 | BT_DBG("conn %p", conn); | 836 | BT_DBG("conn %p", conn); |
| 726 | 837 | ||
| 838 | if (skb->len < sizeof(*rp)) | ||
| 839 | return SMP_UNSPECIFIED; | ||
| 840 | |||
| 727 | if (!(conn->hcon->link_mode & HCI_LM_MASTER)) | 841 | if (!(conn->hcon->link_mode & HCI_LM_MASTER)) |
| 728 | return SMP_CMD_NOTSUPP; | 842 | return SMP_CMD_NOTSUPP; |
| 729 | 843 | ||
| @@ -747,6 +861,8 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb) | |||
| 747 | 861 | ||
| 748 | smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); | 862 | smp_send_cmd(conn, SMP_CMD_PAIRING_REQ, sizeof(cp), &cp); |
| 749 | 863 | ||
| 864 | clear_bit(SMP_FLAG_INITIATOR, &smp->smp_flags); | ||
| 865 | |||
| 750 | return 0; | 866 | return 0; |
| 751 | } | 867 | } |
| 752 | 868 | ||
| @@ -764,11 +880,15 @@ bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level) | |||
| 764 | int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) | 880 | int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) |
| 765 | { | 881 | { |
| 766 | struct l2cap_conn *conn = hcon->l2cap_data; | 882 | struct l2cap_conn *conn = hcon->l2cap_data; |
| 767 | struct smp_chan *smp = conn->smp_chan; | 883 | struct smp_chan *smp; |
| 768 | __u8 authreq; | 884 | __u8 authreq; |
| 769 | 885 | ||
| 770 | BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level); | 886 | BT_DBG("conn %p hcon %p level 0x%2.2x", conn, hcon, sec_level); |
| 771 | 887 | ||
| 888 | /* This may be NULL if there's an unexpected disconnection */ | ||
| 889 | if (!conn) | ||
| 890 | return 1; | ||
| 891 | |||
| 772 | if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) | 892 | if (!test_bit(HCI_LE_ENABLED, &hcon->hdev->dev_flags)) |
| 773 | return 1; | 893 | return 1; |
| 774 | 894 | ||
| @@ -788,6 +908,12 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) | |||
| 788 | 908 | ||
| 789 | authreq = seclevel_to_authreq(sec_level); | 909 | authreq = seclevel_to_authreq(sec_level); |
| 790 | 910 | ||
| 911 | /* hcon->auth_type is set by pair_device in mgmt.c. If the MITM | ||
| 912 | * flag is set we should also set it for the SMP request. | ||
| 913 | */ | ||
| 914 | if ((hcon->auth_type & 0x01)) | ||
| 915 | authreq |= SMP_AUTH_MITM; | ||
| 916 | |||
| 791 | if (hcon->link_mode & HCI_LM_MASTER) { | 917 | if (hcon->link_mode & HCI_LM_MASTER) { |
| 792 | struct smp_cmd_pairing cp; | 918 | struct smp_cmd_pairing cp; |
| 793 | 919 | ||
| @@ -802,6 +928,8 @@ int smp_conn_security(struct hci_conn *hcon, __u8 sec_level) | |||
| 802 | smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp); | 928 | smp_send_cmd(conn, SMP_CMD_SECURITY_REQ, sizeof(cp), &cp); |
| 803 | } | 929 | } |
| 804 | 930 | ||
| 931 | set_bit(SMP_FLAG_INITIATOR, &smp->smp_flags); | ||
| 932 | |||
| 805 | done: | 933 | done: |
| 806 | hcon->pending_sec_level = sec_level; | 934 | hcon->pending_sec_level = sec_level; |
| 807 | 935 | ||
| @@ -813,6 +941,15 @@ static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb) | |||
| 813 | struct smp_cmd_encrypt_info *rp = (void *) skb->data; | 941 | struct smp_cmd_encrypt_info *rp = (void *) skb->data; |
| 814 | struct smp_chan *smp = conn->smp_chan; | 942 | struct smp_chan *smp = conn->smp_chan; |
| 815 | 943 | ||
| 944 | BT_DBG("conn %p", conn); | ||
| 945 | |||
| 946 | if (skb->len < sizeof(*rp)) | ||
| 947 | return SMP_UNSPECIFIED; | ||
| 948 | |||
| 949 | /* Ignore this PDU if it wasn't requested */ | ||
| 950 | if (!(smp->remote_key_dist & SMP_DIST_ENC_KEY)) | ||
| 951 | return 0; | ||
| 952 | |||
| 816 | skb_pull(skb, sizeof(*rp)); | 953 | skb_pull(skb, sizeof(*rp)); |
| 817 | 954 | ||
| 818 | memcpy(smp->tk, rp->ltk, sizeof(smp->tk)); | 955 | memcpy(smp->tk, rp->ltk, sizeof(smp->tk)); |
| @@ -826,16 +963,138 @@ static int smp_cmd_master_ident(struct l2cap_conn *conn, struct sk_buff *skb) | |||
| 826 | struct smp_chan *smp = conn->smp_chan; | 963 | struct smp_chan *smp = conn->smp_chan; |
| 827 | struct hci_dev *hdev = conn->hcon->hdev; | 964 | struct hci_dev *hdev = conn->hcon->hdev; |
| 828 | struct hci_conn *hcon = conn->hcon; | 965 | struct hci_conn *hcon = conn->hcon; |
| 966 | struct smp_ltk *ltk; | ||
| 829 | u8 authenticated; | 967 | u8 authenticated; |
| 830 | 968 | ||
| 969 | BT_DBG("conn %p", conn); | ||
| 970 | |||
| 971 | if (skb->len < sizeof(*rp)) | ||
| 972 | return SMP_UNSPECIFIED; | ||
| 973 | |||
| 974 | /* Ignore this PDU if it wasn't requested */ | ||
| 975 | if (!(smp->remote_key_dist & SMP_DIST_ENC_KEY)) | ||
| 976 | return 0; | ||
| 977 | |||
| 978 | /* Mark the information as received */ | ||
| 979 | smp->remote_key_dist &= ~SMP_DIST_ENC_KEY; | ||
| 980 | |||
| 831 | skb_pull(skb, sizeof(*rp)); | 981 | skb_pull(skb, sizeof(*rp)); |
| 832 | 982 | ||
| 833 | hci_dev_lock(hdev); | 983 | hci_dev_lock(hdev); |
| 834 | authenticated = (hcon->sec_level == BT_SECURITY_HIGH); | 984 | authenticated = (hcon->sec_level == BT_SECURITY_HIGH); |
| 835 | hci_add_ltk(hdev, &hcon->dst, hcon->dst_type, HCI_SMP_LTK, 1, | 985 | ltk = hci_add_ltk(hdev, &hcon->dst, hcon->dst_type, HCI_SMP_LTK, |
| 836 | authenticated, smp->tk, smp->enc_key_size, | 986 | authenticated, smp->tk, smp->enc_key_size, |
| 837 | rp->ediv, rp->rand); | 987 | rp->ediv, rp->rand); |
| 838 | smp_distribute_keys(conn, 1); | 988 | smp->ltk = ltk; |
| 989 | if (!(smp->remote_key_dist & SMP_DIST_ID_KEY)) | ||
| 990 | smp_distribute_keys(conn); | ||
| 991 | hci_dev_unlock(hdev); | ||
| 992 | |||
| 993 | return 0; | ||
| 994 | } | ||
| 995 | |||
| 996 | static int smp_cmd_ident_info(struct l2cap_conn *conn, struct sk_buff *skb) | ||
| 997 | { | ||
| 998 | struct smp_cmd_ident_info *info = (void *) skb->data; | ||
| 999 | struct smp_chan *smp = conn->smp_chan; | ||
| 1000 | |||
| 1001 | BT_DBG(""); | ||
| 1002 | |||
| 1003 | if (skb->len < sizeof(*info)) | ||
| 1004 | return SMP_UNSPECIFIED; | ||
| 1005 | |||
| 1006 | /* Ignore this PDU if it wasn't requested */ | ||
| 1007 | if (!(smp->remote_key_dist & SMP_DIST_ID_KEY)) | ||
| 1008 | return 0; | ||
| 1009 | |||
| 1010 | skb_pull(skb, sizeof(*info)); | ||
| 1011 | |||
| 1012 | memcpy(smp->irk, info->irk, 16); | ||
| 1013 | |||
| 1014 | return 0; | ||
| 1015 | } | ||
| 1016 | |||
| 1017 | static int smp_cmd_ident_addr_info(struct l2cap_conn *conn, | ||
| 1018 | struct sk_buff *skb) | ||
| 1019 | { | ||
| 1020 | struct smp_cmd_ident_addr_info *info = (void *) skb->data; | ||
| 1021 | struct smp_chan *smp = conn->smp_chan; | ||
| 1022 | struct hci_conn *hcon = conn->hcon; | ||
| 1023 | bdaddr_t rpa; | ||
| 1024 | |||
| 1025 | BT_DBG(""); | ||
| 1026 | |||
| 1027 | if (skb->len < sizeof(*info)) | ||
| 1028 | return SMP_UNSPECIFIED; | ||
| 1029 | |||
| 1030 | /* Ignore this PDU if it wasn't requested */ | ||
| 1031 | if (!(smp->remote_key_dist & SMP_DIST_ID_KEY)) | ||
| 1032 | return 0; | ||
| 1033 | |||
| 1034 | /* Mark the information as received */ | ||
| 1035 | smp->remote_key_dist &= ~SMP_DIST_ID_KEY; | ||
| 1036 | |||
| 1037 | skb_pull(skb, sizeof(*info)); | ||
| 1038 | |||
| 1039 | /* Strictly speaking the Core Specification (4.1) allows sending | ||
| 1040 | * an empty address which would force us to rely on just the IRK | ||
| 1041 | * as "identity information". However, since such | ||
| 1042 | * implementations are not known of and in order to not over | ||
| 1043 | * complicate our implementation, simply pretend that we never | ||
| 1044 | * received an IRK for such a device. | ||
| 1045 | */ | ||
| 1046 | if (!bacmp(&info->bdaddr, BDADDR_ANY)) { | ||
| 1047 | BT_ERR("Ignoring IRK with no identity address"); | ||
| 1048 | smp_distribute_keys(conn); | ||
| 1049 | return 0; | ||
| 1050 | } | ||
| 1051 | |||
| 1052 | bacpy(&smp->id_addr, &info->bdaddr); | ||
| 1053 | smp->id_addr_type = info->addr_type; | ||
| 1054 | |||
| 1055 | if (hci_bdaddr_is_rpa(&hcon->dst, hcon->dst_type)) | ||
| 1056 | bacpy(&rpa, &hcon->dst); | ||
| 1057 | else | ||
| 1058 | bacpy(&rpa, BDADDR_ANY); | ||
| 1059 | |||
| 1060 | smp->remote_irk = hci_add_irk(conn->hcon->hdev, &smp->id_addr, | ||
| 1061 | smp->id_addr_type, smp->irk, &rpa); | ||
| 1062 | |||
| 1063 | smp_distribute_keys(conn); | ||
| 1064 | |||
| 1065 | return 0; | ||
| 1066 | } | ||
| 1067 | |||
| 1068 | static int smp_cmd_sign_info(struct l2cap_conn *conn, struct sk_buff *skb) | ||
| 1069 | { | ||
| 1070 | struct smp_cmd_sign_info *rp = (void *) skb->data; | ||
| 1071 | struct smp_chan *smp = conn->smp_chan; | ||
| 1072 | struct hci_dev *hdev = conn->hcon->hdev; | ||
| 1073 | struct smp_csrk *csrk; | ||
| 1074 | |||
| 1075 | BT_DBG("conn %p", conn); | ||
| 1076 | |||
| 1077 | if (skb->len < sizeof(*rp)) | ||
| 1078 | return SMP_UNSPECIFIED; | ||
| 1079 | |||
| 1080 | /* Ignore this PDU if it wasn't requested */ | ||
| 1081 | if (!(smp->remote_key_dist & SMP_DIST_SIGN)) | ||
| 1082 | return 0; | ||
| 1083 | |||
| 1084 | /* Mark the information as received */ | ||
| 1085 | smp->remote_key_dist &= ~SMP_DIST_SIGN; | ||
| 1086 | |||
| 1087 | skb_pull(skb, sizeof(*rp)); | ||
| 1088 | |||
| 1089 | hci_dev_lock(hdev); | ||
| 1090 | csrk = kzalloc(sizeof(*csrk), GFP_KERNEL); | ||
| 1091 | if (csrk) { | ||
| 1092 | csrk->master = 0x01; | ||
| 1093 | memcpy(csrk->val, rp->csrk, sizeof(csrk->val)); | ||
| 1094 | } | ||
| 1095 | smp->csrk = csrk; | ||
| 1096 | if (!(smp->remote_key_dist & SMP_DIST_SIGN)) | ||
| 1097 | smp_distribute_keys(conn); | ||
| 839 | hci_dev_unlock(hdev); | 1098 | hci_dev_unlock(hdev); |
| 840 | 1099 | ||
| 841 | return 0; | 1100 | return 0; |
| @@ -915,10 +1174,15 @@ int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) | |||
| 915 | break; | 1174 | break; |
| 916 | 1175 | ||
| 917 | case SMP_CMD_IDENT_INFO: | 1176 | case SMP_CMD_IDENT_INFO: |
| 1177 | reason = smp_cmd_ident_info(conn, skb); | ||
| 1178 | break; | ||
| 1179 | |||
| 918 | case SMP_CMD_IDENT_ADDR_INFO: | 1180 | case SMP_CMD_IDENT_ADDR_INFO: |
| 1181 | reason = smp_cmd_ident_addr_info(conn, skb); | ||
| 1182 | break; | ||
| 1183 | |||
| 919 | case SMP_CMD_SIGN_INFO: | 1184 | case SMP_CMD_SIGN_INFO: |
| 920 | /* Just ignored */ | 1185 | reason = smp_cmd_sign_info(conn, skb); |
| 921 | reason = 0; | ||
| 922 | break; | 1186 | break; |
| 923 | 1187 | ||
| 924 | default: | 1188 | default: |
| @@ -937,26 +1201,78 @@ done: | |||
| 937 | return err; | 1201 | return err; |
| 938 | } | 1202 | } |
| 939 | 1203 | ||
| 940 | int smp_distribute_keys(struct l2cap_conn *conn, __u8 force) | 1204 | static void smp_notify_keys(struct l2cap_conn *conn) |
| 1205 | { | ||
| 1206 | struct smp_chan *smp = conn->smp_chan; | ||
| 1207 | struct hci_conn *hcon = conn->hcon; | ||
| 1208 | struct hci_dev *hdev = hcon->hdev; | ||
| 1209 | struct smp_cmd_pairing *req = (void *) &smp->preq[1]; | ||
| 1210 | struct smp_cmd_pairing *rsp = (void *) &smp->prsp[1]; | ||
| 1211 | bool persistent; | ||
| 1212 | |||
| 1213 | if (smp->remote_irk) { | ||
| 1214 | mgmt_new_irk(hdev, smp->remote_irk); | ||
| 1215 | /* Now that user space can be considered to know the | ||
| 1216 | * identity address track the connection based on it | ||
| 1217 | * from now on. | ||
| 1218 | */ | ||
| 1219 | bacpy(&hcon->dst, &smp->remote_irk->bdaddr); | ||
| 1220 | hcon->dst_type = smp->remote_irk->addr_type; | ||
| 1221 | l2cap_conn_update_id_addr(hcon); | ||
| 1222 | } | ||
| 1223 | |||
| 1224 | /* The LTKs and CSRKs should be persistent only if both sides | ||
| 1225 | * had the bonding bit set in their authentication requests. | ||
| 1226 | */ | ||
| 1227 | persistent = !!((req->auth_req & rsp->auth_req) & SMP_AUTH_BONDING); | ||
| 1228 | |||
| 1229 | if (smp->csrk) { | ||
| 1230 | smp->csrk->bdaddr_type = hcon->dst_type; | ||
| 1231 | bacpy(&smp->csrk->bdaddr, &hcon->dst); | ||
| 1232 | mgmt_new_csrk(hdev, smp->csrk, persistent); | ||
| 1233 | } | ||
| 1234 | |||
| 1235 | if (smp->slave_csrk) { | ||
| 1236 | smp->slave_csrk->bdaddr_type = hcon->dst_type; | ||
| 1237 | bacpy(&smp->slave_csrk->bdaddr, &hcon->dst); | ||
| 1238 | mgmt_new_csrk(hdev, smp->slave_csrk, persistent); | ||
| 1239 | } | ||
| 1240 | |||
| 1241 | if (smp->ltk) { | ||
| 1242 | smp->ltk->bdaddr_type = hcon->dst_type; | ||
| 1243 | bacpy(&smp->ltk->bdaddr, &hcon->dst); | ||
| 1244 | mgmt_new_ltk(hdev, smp->ltk, persistent); | ||
| 1245 | } | ||
| 1246 | |||
| 1247 | if (smp->slave_ltk) { | ||
| 1248 | smp->slave_ltk->bdaddr_type = hcon->dst_type; | ||
| 1249 | bacpy(&smp->slave_ltk->bdaddr, &hcon->dst); | ||
| 1250 | mgmt_new_ltk(hdev, smp->slave_ltk, persistent); | ||
| 1251 | } | ||
| 1252 | } | ||
| 1253 | |||
| 1254 | int smp_distribute_keys(struct l2cap_conn *conn) | ||
| 941 | { | 1255 | { |
| 942 | struct smp_cmd_pairing *req, *rsp; | 1256 | struct smp_cmd_pairing *req, *rsp; |
| 943 | struct smp_chan *smp = conn->smp_chan; | 1257 | struct smp_chan *smp = conn->smp_chan; |
| 1258 | struct hci_conn *hcon = conn->hcon; | ||
| 1259 | struct hci_dev *hdev = hcon->hdev; | ||
| 944 | __u8 *keydist; | 1260 | __u8 *keydist; |
| 945 | 1261 | ||
| 946 | BT_DBG("conn %p force %d", conn, force); | 1262 | BT_DBG("conn %p", conn); |
| 947 | 1263 | ||
| 948 | if (!test_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) | 1264 | if (!test_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags)) |
| 949 | return 0; | 1265 | return 0; |
| 950 | 1266 | ||
| 951 | rsp = (void *) &smp->prsp[1]; | 1267 | rsp = (void *) &smp->prsp[1]; |
| 952 | 1268 | ||
| 953 | /* The responder sends its keys first */ | 1269 | /* The responder sends its keys first */ |
| 954 | if (!force && conn->hcon->out && (rsp->resp_key_dist & 0x07)) | 1270 | if (hcon->out && (smp->remote_key_dist & 0x07)) |
| 955 | return 0; | 1271 | return 0; |
| 956 | 1272 | ||
| 957 | req = (void *) &smp->preq[1]; | 1273 | req = (void *) &smp->preq[1]; |
| 958 | 1274 | ||
| 959 | if (conn->hcon->out) { | 1275 | if (hcon->out) { |
| 960 | keydist = &rsp->init_key_dist; | 1276 | keydist = &rsp->init_key_dist; |
| 961 | *keydist &= req->init_key_dist; | 1277 | *keydist &= req->init_key_dist; |
| 962 | } else { | 1278 | } else { |
| @@ -964,28 +1280,30 @@ int smp_distribute_keys(struct l2cap_conn *conn, __u8 force) | |||
| 964 | *keydist &= req->resp_key_dist; | 1280 | *keydist &= req->resp_key_dist; |
| 965 | } | 1281 | } |
| 966 | 1282 | ||
| 967 | |||
| 968 | BT_DBG("keydist 0x%x", *keydist); | 1283 | BT_DBG("keydist 0x%x", *keydist); |
| 969 | 1284 | ||
| 970 | if (*keydist & SMP_DIST_ENC_KEY) { | 1285 | if (*keydist & SMP_DIST_ENC_KEY) { |
| 971 | struct smp_cmd_encrypt_info enc; | 1286 | struct smp_cmd_encrypt_info enc; |
| 972 | struct smp_cmd_master_ident ident; | 1287 | struct smp_cmd_master_ident ident; |
| 973 | struct hci_conn *hcon = conn->hcon; | 1288 | struct smp_ltk *ltk; |
| 974 | u8 authenticated; | 1289 | u8 authenticated; |
| 975 | __le16 ediv; | 1290 | __le16 ediv; |
| 1291 | __le64 rand; | ||
| 976 | 1292 | ||
| 977 | get_random_bytes(enc.ltk, sizeof(enc.ltk)); | 1293 | get_random_bytes(enc.ltk, sizeof(enc.ltk)); |
| 978 | get_random_bytes(&ediv, sizeof(ediv)); | 1294 | get_random_bytes(&ediv, sizeof(ediv)); |
| 979 | get_random_bytes(ident.rand, sizeof(ident.rand)); | 1295 | get_random_bytes(&rand, sizeof(rand)); |
| 980 | 1296 | ||
| 981 | smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc); | 1297 | smp_send_cmd(conn, SMP_CMD_ENCRYPT_INFO, sizeof(enc), &enc); |
| 982 | 1298 | ||
| 983 | authenticated = hcon->sec_level == BT_SECURITY_HIGH; | 1299 | authenticated = hcon->sec_level == BT_SECURITY_HIGH; |
| 984 | hci_add_ltk(hcon->hdev, &hcon->dst, hcon->dst_type, | 1300 | ltk = hci_add_ltk(hdev, &hcon->dst, hcon->dst_type, |
| 985 | HCI_SMP_LTK_SLAVE, 1, authenticated, | 1301 | HCI_SMP_LTK_SLAVE, authenticated, enc.ltk, |
| 986 | enc.ltk, smp->enc_key_size, ediv, ident.rand); | 1302 | smp->enc_key_size, ediv, rand); |
| 1303 | smp->slave_ltk = ltk; | ||
| 987 | 1304 | ||
| 988 | ident.ediv = ediv; | 1305 | ident.ediv = ediv; |
| 1306 | ident.rand = rand; | ||
| 989 | 1307 | ||
| 990 | smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident); | 1308 | smp_send_cmd(conn, SMP_CMD_MASTER_IDENT, sizeof(ident), &ident); |
| 991 | 1309 | ||
| @@ -996,14 +1314,18 @@ int smp_distribute_keys(struct l2cap_conn *conn, __u8 force) | |||
| 996 | struct smp_cmd_ident_addr_info addrinfo; | 1314 | struct smp_cmd_ident_addr_info addrinfo; |
| 997 | struct smp_cmd_ident_info idinfo; | 1315 | struct smp_cmd_ident_info idinfo; |
| 998 | 1316 | ||
| 999 | /* Send a dummy key */ | 1317 | memcpy(idinfo.irk, hdev->irk, sizeof(idinfo.irk)); |
| 1000 | get_random_bytes(idinfo.irk, sizeof(idinfo.irk)); | ||
| 1001 | 1318 | ||
| 1002 | smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo); | 1319 | smp_send_cmd(conn, SMP_CMD_IDENT_INFO, sizeof(idinfo), &idinfo); |
| 1003 | 1320 | ||
| 1004 | /* Just public address */ | 1321 | /* The hci_conn contains the local identity address |
| 1005 | memset(&addrinfo, 0, sizeof(addrinfo)); | 1322 | * after the connection has been established. |
| 1006 | bacpy(&addrinfo.bdaddr, &conn->hcon->src); | 1323 | * |
| 1324 | * This is true even when the connection has been | ||
| 1325 | * established using a resolvable random address. | ||
| 1326 | */ | ||
| 1327 | bacpy(&addrinfo.bdaddr, &hcon->src); | ||
| 1328 | addrinfo.addr_type = hcon->src_type; | ||
| 1007 | 1329 | ||
| 1008 | smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo), | 1330 | smp_send_cmd(conn, SMP_CMD_IDENT_ADDR_INFO, sizeof(addrinfo), |
| 1009 | &addrinfo); | 1331 | &addrinfo); |
| @@ -1013,20 +1335,33 @@ int smp_distribute_keys(struct l2cap_conn *conn, __u8 force) | |||
| 1013 | 1335 | ||
| 1014 | if (*keydist & SMP_DIST_SIGN) { | 1336 | if (*keydist & SMP_DIST_SIGN) { |
| 1015 | struct smp_cmd_sign_info sign; | 1337 | struct smp_cmd_sign_info sign; |
| 1338 | struct smp_csrk *csrk; | ||
| 1016 | 1339 | ||
| 1017 | /* Send a dummy key */ | 1340 | /* Generate a new random key */ |
| 1018 | get_random_bytes(sign.csrk, sizeof(sign.csrk)); | 1341 | get_random_bytes(sign.csrk, sizeof(sign.csrk)); |
| 1019 | 1342 | ||
| 1343 | csrk = kzalloc(sizeof(*csrk), GFP_KERNEL); | ||
| 1344 | if (csrk) { | ||
| 1345 | csrk->master = 0x00; | ||
| 1346 | memcpy(csrk->val, sign.csrk, sizeof(csrk->val)); | ||
| 1347 | } | ||
| 1348 | smp->slave_csrk = csrk; | ||
| 1349 | |||
| 1020 | smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign); | 1350 | smp_send_cmd(conn, SMP_CMD_SIGN_INFO, sizeof(sign), &sign); |
| 1021 | 1351 | ||
| 1022 | *keydist &= ~SMP_DIST_SIGN; | 1352 | *keydist &= ~SMP_DIST_SIGN; |
| 1023 | } | 1353 | } |
| 1024 | 1354 | ||
| 1025 | if (conn->hcon->out || force) { | 1355 | /* If there are still keys to be received wait for them */ |
| 1026 | clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags); | 1356 | if ((smp->remote_key_dist & 0x07)) |
| 1027 | cancel_delayed_work_sync(&conn->security_timer); | 1357 | return 0; |
| 1028 | smp_chan_destroy(conn); | 1358 | |
| 1029 | } | 1359 | clear_bit(HCI_CONN_LE_SMP_PEND, &hcon->flags); |
| 1360 | cancel_delayed_work_sync(&conn->security_timer); | ||
| 1361 | set_bit(SMP_FLAG_COMPLETE, &smp->smp_flags); | ||
| 1362 | smp_notify_keys(conn); | ||
| 1363 | |||
| 1364 | smp_chan_destroy(conn); | ||
| 1030 | 1365 | ||
| 1031 | return 0; | 1366 | return 0; |
| 1032 | } | 1367 | } |
diff --git a/net/bluetooth/smp.h b/net/bluetooth/smp.h index a700bcb490d7..1277147a9150 100644 --- a/net/bluetooth/smp.h +++ b/net/bluetooth/smp.h | |||
| @@ -78,7 +78,7 @@ struct smp_cmd_encrypt_info { | |||
| 78 | #define SMP_CMD_MASTER_IDENT 0x07 | 78 | #define SMP_CMD_MASTER_IDENT 0x07 |
| 79 | struct smp_cmd_master_ident { | 79 | struct smp_cmd_master_ident { |
| 80 | __le16 ediv; | 80 | __le16 ediv; |
| 81 | __u8 rand[8]; | 81 | __le64 rand; |
| 82 | } __packed; | 82 | } __packed; |
| 83 | 83 | ||
| 84 | #define SMP_CMD_IDENT_INFO 0x08 | 84 | #define SMP_CMD_IDENT_INFO 0x08 |
| @@ -118,6 +118,8 @@ struct smp_cmd_security_req { | |||
| 118 | #define SMP_FLAG_TK_VALID 1 | 118 | #define SMP_FLAG_TK_VALID 1 |
| 119 | #define SMP_FLAG_CFM_PENDING 2 | 119 | #define SMP_FLAG_CFM_PENDING 2 |
| 120 | #define SMP_FLAG_MITM_AUTH 3 | 120 | #define SMP_FLAG_MITM_AUTH 3 |
| 121 | #define SMP_FLAG_COMPLETE 4 | ||
| 122 | #define SMP_FLAG_INITIATOR 5 | ||
| 121 | 123 | ||
| 122 | struct smp_chan { | 124 | struct smp_chan { |
| 123 | struct l2cap_conn *conn; | 125 | struct l2cap_conn *conn; |
| @@ -128,20 +130,31 @@ struct smp_chan { | |||
| 128 | u8 pcnf[16]; /* SMP Pairing Confirm */ | 130 | u8 pcnf[16]; /* SMP Pairing Confirm */ |
| 129 | u8 tk[16]; /* SMP Temporary Key */ | 131 | u8 tk[16]; /* SMP Temporary Key */ |
| 130 | u8 enc_key_size; | 132 | u8 enc_key_size; |
| 133 | u8 remote_key_dist; | ||
| 134 | bdaddr_t id_addr; | ||
| 135 | u8 id_addr_type; | ||
| 136 | u8 irk[16]; | ||
| 137 | struct smp_csrk *csrk; | ||
| 138 | struct smp_csrk *slave_csrk; | ||
| 139 | struct smp_ltk *ltk; | ||
| 140 | struct smp_ltk *slave_ltk; | ||
| 141 | struct smp_irk *remote_irk; | ||
| 131 | unsigned long smp_flags; | 142 | unsigned long smp_flags; |
| 132 | struct crypto_blkcipher *tfm; | ||
| 133 | struct work_struct confirm; | 143 | struct work_struct confirm; |
| 134 | struct work_struct random; | 144 | struct work_struct random; |
| 135 | |||
| 136 | }; | 145 | }; |
| 137 | 146 | ||
| 138 | /* SMP Commands */ | 147 | /* SMP Commands */ |
| 139 | bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level); | 148 | bool smp_sufficient_security(struct hci_conn *hcon, u8 sec_level); |
| 140 | int smp_conn_security(struct hci_conn *hcon, __u8 sec_level); | 149 | int smp_conn_security(struct hci_conn *hcon, __u8 sec_level); |
| 141 | int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb); | 150 | int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb); |
| 142 | int smp_distribute_keys(struct l2cap_conn *conn, __u8 force); | 151 | int smp_distribute_keys(struct l2cap_conn *conn); |
| 143 | int smp_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, __le32 passkey); | 152 | int smp_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, __le32 passkey); |
| 144 | 153 | ||
| 145 | void smp_chan_destroy(struct l2cap_conn *conn); | 154 | void smp_chan_destroy(struct l2cap_conn *conn); |
| 146 | 155 | ||
| 156 | bool smp_irk_matches(struct crypto_blkcipher *tfm, u8 irk[16], | ||
| 157 | bdaddr_t *bdaddr); | ||
| 158 | int smp_generate_rpa(struct crypto_blkcipher *tfm, u8 irk[16], bdaddr_t *rpa); | ||
| 159 | |||
| 147 | #endif /* __SMP_H */ | 160 | #endif /* __SMP_H */ |
diff --git a/net/bridge/br_device.c b/net/bridge/br_device.c index 8fe8b71b487a..3e2da2cb72db 100644 --- a/net/bridge/br_device.c +++ b/net/bridge/br_device.c | |||
| @@ -88,18 +88,11 @@ out: | |||
| 88 | static int br_dev_init(struct net_device *dev) | 88 | static int br_dev_init(struct net_device *dev) |
| 89 | { | 89 | { |
| 90 | struct net_bridge *br = netdev_priv(dev); | 90 | struct net_bridge *br = netdev_priv(dev); |
| 91 | int i; | ||
| 92 | 91 | ||
| 93 | br->stats = alloc_percpu(struct pcpu_sw_netstats); | 92 | br->stats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); |
| 94 | if (!br->stats) | 93 | if (!br->stats) |
| 95 | return -ENOMEM; | 94 | return -ENOMEM; |
| 96 | 95 | ||
| 97 | for_each_possible_cpu(i) { | ||
| 98 | struct pcpu_sw_netstats *br_dev_stats; | ||
| 99 | br_dev_stats = per_cpu_ptr(br->stats, i); | ||
| 100 | u64_stats_init(&br_dev_stats->syncp); | ||
| 101 | } | ||
| 102 | |||
| 103 | return 0; | 96 | return 0; |
| 104 | } | 97 | } |
| 105 | 98 | ||
| @@ -143,9 +136,9 @@ static struct rtnl_link_stats64 *br_get_stats64(struct net_device *dev, | |||
| 143 | const struct pcpu_sw_netstats *bstats | 136 | const struct pcpu_sw_netstats *bstats |
| 144 | = per_cpu_ptr(br->stats, cpu); | 137 | = per_cpu_ptr(br->stats, cpu); |
| 145 | do { | 138 | do { |
| 146 | start = u64_stats_fetch_begin_bh(&bstats->syncp); | 139 | start = u64_stats_fetch_begin_irq(&bstats->syncp); |
| 147 | memcpy(&tmp, bstats, sizeof(tmp)); | 140 | memcpy(&tmp, bstats, sizeof(tmp)); |
| 148 | } while (u64_stats_fetch_retry_bh(&bstats->syncp, start)); | 141 | } while (u64_stats_fetch_retry_irq(&bstats->syncp, start)); |
| 149 | sum.tx_bytes += tmp.tx_bytes; | 142 | sum.tx_bytes += tmp.tx_bytes; |
| 150 | sum.tx_packets += tmp.tx_packets; | 143 | sum.tx_packets += tmp.tx_packets; |
| 151 | sum.rx_bytes += tmp.rx_bytes; | 144 | sum.rx_bytes += tmp.rx_bytes; |
| @@ -225,16 +218,16 @@ static void br_netpoll_cleanup(struct net_device *dev) | |||
| 225 | br_netpoll_disable(p); | 218 | br_netpoll_disable(p); |
| 226 | } | 219 | } |
| 227 | 220 | ||
| 228 | static int __br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp) | 221 | static int __br_netpoll_enable(struct net_bridge_port *p) |
| 229 | { | 222 | { |
| 230 | struct netpoll *np; | 223 | struct netpoll *np; |
| 231 | int err; | 224 | int err; |
| 232 | 225 | ||
| 233 | np = kzalloc(sizeof(*p->np), gfp); | 226 | np = kzalloc(sizeof(*p->np), GFP_KERNEL); |
| 234 | if (!np) | 227 | if (!np) |
| 235 | return -ENOMEM; | 228 | return -ENOMEM; |
| 236 | 229 | ||
| 237 | err = __netpoll_setup(np, p->dev, gfp); | 230 | err = __netpoll_setup(np, p->dev); |
| 238 | if (err) { | 231 | if (err) { |
| 239 | kfree(np); | 232 | kfree(np); |
| 240 | return err; | 233 | return err; |
| @@ -244,16 +237,15 @@ static int __br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp) | |||
| 244 | return err; | 237 | return err; |
| 245 | } | 238 | } |
| 246 | 239 | ||
| 247 | int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp) | 240 | int br_netpoll_enable(struct net_bridge_port *p) |
| 248 | { | 241 | { |
| 249 | if (!p->br->dev->npinfo) | 242 | if (!p->br->dev->npinfo) |
| 250 | return 0; | 243 | return 0; |
| 251 | 244 | ||
| 252 | return __br_netpoll_enable(p, gfp); | 245 | return __br_netpoll_enable(p); |
| 253 | } | 246 | } |
| 254 | 247 | ||
| 255 | static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, | 248 | static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni) |
| 256 | gfp_t gfp) | ||
| 257 | { | 249 | { |
| 258 | struct net_bridge *br = netdev_priv(dev); | 250 | struct net_bridge *br = netdev_priv(dev); |
| 259 | struct net_bridge_port *p; | 251 | struct net_bridge_port *p; |
| @@ -262,7 +254,7 @@ static int br_netpoll_setup(struct net_device *dev, struct netpoll_info *ni, | |||
| 262 | list_for_each_entry(p, &br->port_list, list) { | 254 | list_for_each_entry(p, &br->port_list, list) { |
| 263 | if (!p->dev) | 255 | if (!p->dev) |
| 264 | continue; | 256 | continue; |
| 265 | err = __br_netpoll_enable(p, gfp); | 257 | err = __br_netpoll_enable(p); |
| 266 | if (err) | 258 | if (err) |
| 267 | goto fail; | 259 | goto fail; |
| 268 | } | 260 | } |
| @@ -374,7 +366,7 @@ void br_dev_setup(struct net_device *dev) | |||
| 374 | br->bridge_id.prio[0] = 0x80; | 366 | br->bridge_id.prio[0] = 0x80; |
| 375 | br->bridge_id.prio[1] = 0x00; | 367 | br->bridge_id.prio[1] = 0x00; |
| 376 | 368 | ||
| 377 | memcpy(br->group_addr, eth_reserved_addr_base, ETH_ALEN); | 369 | ether_addr_copy(br->group_addr, eth_reserved_addr_base); |
| 378 | 370 | ||
| 379 | br->stp_enabled = BR_NO_STP; | 371 | br->stp_enabled = BR_NO_STP; |
| 380 | br->group_fwd_mask = BR_GROUPFWD_DEFAULT; | 372 | br->group_fwd_mask = BR_GROUPFWD_DEFAULT; |
diff --git a/net/bridge/br_forward.c b/net/bridge/br_forward.c index d3409e6b5453..056b67b0e277 100644 --- a/net/bridge/br_forward.c +++ b/net/bridge/br_forward.c | |||
| @@ -35,16 +35,11 @@ static inline int should_deliver(const struct net_bridge_port *p, | |||
| 35 | p->state == BR_STATE_FORWARDING; | 35 | p->state == BR_STATE_FORWARDING; |
| 36 | } | 36 | } |
| 37 | 37 | ||
| 38 | static inline unsigned int packet_length(const struct sk_buff *skb) | ||
| 39 | { | ||
| 40 | return skb->len - (skb->protocol == htons(ETH_P_8021Q) ? VLAN_HLEN : 0); | ||
| 41 | } | ||
| 42 | |||
| 43 | int br_dev_queue_push_xmit(struct sk_buff *skb) | 38 | int br_dev_queue_push_xmit(struct sk_buff *skb) |
| 44 | { | 39 | { |
| 45 | /* ip_fragment doesn't copy the MAC header */ | 40 | /* ip_fragment doesn't copy the MAC header */ |
| 46 | if (nf_bridge_maybe_copy_header(skb) || | 41 | if (nf_bridge_maybe_copy_header(skb) || |
| 47 | (packet_length(skb) > skb->dev->mtu && !skb_is_gso(skb))) { | 42 | !is_skb_forwardable(skb->dev, skb)) { |
| 48 | kfree_skb(skb); | 43 | kfree_skb(skb); |
| 49 | } else { | 44 | } else { |
| 50 | skb_push(skb, ETH_HLEN); | 45 | skb_push(skb, ETH_HLEN); |
| @@ -71,7 +66,7 @@ static void __br_deliver(const struct net_bridge_port *to, struct sk_buff *skb) | |||
| 71 | skb->dev = to->dev; | 66 | skb->dev = to->dev; |
| 72 | 67 | ||
| 73 | if (unlikely(netpoll_tx_running(to->br->dev))) { | 68 | if (unlikely(netpoll_tx_running(to->br->dev))) { |
| 74 | if (packet_length(skb) > skb->dev->mtu && !skb_is_gso(skb)) | 69 | if (!is_skb_forwardable(skb->dev, skb)) |
| 75 | kfree_skb(skb); | 70 | kfree_skb(skb); |
| 76 | else { | 71 | else { |
| 77 | skb_push(skb, ETH_HLEN); | 72 | skb_push(skb, ETH_HLEN); |
diff --git a/net/bridge/br_if.c b/net/bridge/br_if.c index 54d207d3a31c..5262b8617eb9 100644 --- a/net/bridge/br_if.c +++ b/net/bridge/br_if.c | |||
| @@ -366,7 +366,7 @@ int br_add_if(struct net_bridge *br, struct net_device *dev) | |||
| 366 | if (err) | 366 | if (err) |
| 367 | goto err2; | 367 | goto err2; |
| 368 | 368 | ||
| 369 | err = br_netpoll_enable(p, GFP_KERNEL); | 369 | err = br_netpoll_enable(p); |
| 370 | if (err) | 370 | if (err) |
| 371 | goto err3; | 371 | goto err3; |
| 372 | 372 | ||
diff --git a/net/bridge/br_input.c b/net/bridge/br_input.c index d0cca3c65f01..7985deaff52f 100644 --- a/net/bridge/br_input.c +++ b/net/bridge/br_input.c | |||
| @@ -73,7 +73,7 @@ int br_handle_frame_finish(struct sk_buff *skb) | |||
| 73 | goto drop; | 73 | goto drop; |
| 74 | 74 | ||
| 75 | if (!br_allowed_ingress(p->br, nbp_get_vlan_info(p), skb, &vid)) | 75 | if (!br_allowed_ingress(p->br, nbp_get_vlan_info(p), skb, &vid)) |
| 76 | goto drop; | 76 | goto out; |
| 77 | 77 | ||
| 78 | /* insert into forwarding database after filtering to avoid spoofing */ | 78 | /* insert into forwarding database after filtering to avoid spoofing */ |
| 79 | br = p->br; | 79 | br = p->br; |
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c index 93067ecdb9a2..7b757b5dc773 100644 --- a/net/bridge/br_multicast.c +++ b/net/bridge/br_multicast.c | |||
| @@ -363,7 +363,7 @@ static struct sk_buff *br_ip4_multicast_alloc_query(struct net_bridge *br, | |||
| 363 | skb_reset_mac_header(skb); | 363 | skb_reset_mac_header(skb); |
| 364 | eth = eth_hdr(skb); | 364 | eth = eth_hdr(skb); |
| 365 | 365 | ||
| 366 | memcpy(eth->h_source, br->dev->dev_addr, ETH_ALEN); | 366 | ether_addr_copy(eth->h_source, br->dev->dev_addr); |
| 367 | eth->h_dest[0] = 1; | 367 | eth->h_dest[0] = 1; |
| 368 | eth->h_dest[1] = 0; | 368 | eth->h_dest[1] = 0; |
| 369 | eth->h_dest[2] = 0x5e; | 369 | eth->h_dest[2] = 0x5e; |
| @@ -433,7 +433,7 @@ static struct sk_buff *br_ip6_multicast_alloc_query(struct net_bridge *br, | |||
| 433 | skb_reset_mac_header(skb); | 433 | skb_reset_mac_header(skb); |
| 434 | eth = eth_hdr(skb); | 434 | eth = eth_hdr(skb); |
| 435 | 435 | ||
| 436 | memcpy(eth->h_source, br->dev->dev_addr, ETH_ALEN); | 436 | ether_addr_copy(eth->h_source, br->dev->dev_addr); |
| 437 | eth->h_proto = htons(ETH_P_IPV6); | 437 | eth->h_proto = htons(ETH_P_IPV6); |
| 438 | skb_put(skb, sizeof(*eth)); | 438 | skb_put(skb, sizeof(*eth)); |
| 439 | 439 | ||
diff --git a/net/bridge/br_netfilter.c b/net/bridge/br_netfilter.c index b008c59a92c4..80e1b0f60a30 100644 --- a/net/bridge/br_netfilter.c +++ b/net/bridge/br_netfilter.c | |||
| @@ -167,7 +167,7 @@ void br_netfilter_rtable_init(struct net_bridge *br) | |||
| 167 | rt->dst.dev = br->dev; | 167 | rt->dst.dev = br->dev; |
| 168 | rt->dst.path = &rt->dst; | 168 | rt->dst.path = &rt->dst; |
| 169 | dst_init_metrics(&rt->dst, br_dst_default_metrics, true); | 169 | dst_init_metrics(&rt->dst, br_dst_default_metrics, true); |
| 170 | rt->dst.flags = DST_NOXFRM | DST_NOPEER | DST_FAKE_RTABLE; | 170 | rt->dst.flags = DST_NOXFRM | DST_FAKE_RTABLE; |
| 171 | rt->dst.ops = &fake_dst_ops; | 171 | rt->dst.ops = &fake_dst_ops; |
| 172 | } | 172 | } |
| 173 | 173 | ||
| @@ -506,7 +506,7 @@ bridged_dnat: | |||
| 506 | 1); | 506 | 1); |
| 507 | return 0; | 507 | return 0; |
| 508 | } | 508 | } |
| 509 | memcpy(eth_hdr(skb)->h_dest, dev->dev_addr, ETH_ALEN); | 509 | ether_addr_copy(eth_hdr(skb)->h_dest, dev->dev_addr); |
| 510 | skb->pkt_type = PACKET_HOST; | 510 | skb->pkt_type = PACKET_HOST; |
| 511 | } | 511 | } |
| 512 | } else { | 512 | } else { |
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 3ba11bc99b65..06811d79f89f 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h | |||
| @@ -46,12 +46,12 @@ typedef __u16 port_id; | |||
| 46 | struct bridge_id | 46 | struct bridge_id |
| 47 | { | 47 | { |
| 48 | unsigned char prio[2]; | 48 | unsigned char prio[2]; |
| 49 | unsigned char addr[6]; | 49 | unsigned char addr[ETH_ALEN]; |
| 50 | }; | 50 | }; |
| 51 | 51 | ||
| 52 | struct mac_addr | 52 | struct mac_addr |
| 53 | { | 53 | { |
| 54 | unsigned char addr[6]; | 54 | unsigned char addr[ETH_ALEN]; |
| 55 | }; | 55 | }; |
| 56 | 56 | ||
| 57 | struct br_ip | 57 | struct br_ip |
| @@ -349,7 +349,7 @@ static inline void br_netpoll_send_skb(const struct net_bridge_port *p, | |||
| 349 | netpoll_send_skb(np, skb); | 349 | netpoll_send_skb(np, skb); |
| 350 | } | 350 | } |
| 351 | 351 | ||
| 352 | int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp); | 352 | int br_netpoll_enable(struct net_bridge_port *p); |
| 353 | void br_netpoll_disable(struct net_bridge_port *p); | 353 | void br_netpoll_disable(struct net_bridge_port *p); |
| 354 | #else | 354 | #else |
| 355 | static inline void br_netpoll_send_skb(const struct net_bridge_port *p, | 355 | static inline void br_netpoll_send_skb(const struct net_bridge_port *p, |
| @@ -357,7 +357,7 @@ static inline void br_netpoll_send_skb(const struct net_bridge_port *p, | |||
| 357 | { | 357 | { |
| 358 | } | 358 | } |
| 359 | 359 | ||
| 360 | static inline int br_netpoll_enable(struct net_bridge_port *p, gfp_t gfp) | 360 | static inline int br_netpoll_enable(struct net_bridge_port *p) |
| 361 | { | 361 | { |
| 362 | return 0; | 362 | return 0; |
| 363 | } | 363 | } |
diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index f23c74b3a953..4a3716102789 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c | |||
| @@ -99,9 +99,9 @@ static int __vlan_del(struct net_port_vlans *v, u16 vid) | |||
| 99 | v->num_vlans--; | 99 | v->num_vlans--; |
| 100 | if (bitmap_empty(v->vlan_bitmap, VLAN_N_VID)) { | 100 | if (bitmap_empty(v->vlan_bitmap, VLAN_N_VID)) { |
| 101 | if (v->port_idx) | 101 | if (v->port_idx) |
| 102 | rcu_assign_pointer(v->parent.port->vlan_info, NULL); | 102 | RCU_INIT_POINTER(v->parent.port->vlan_info, NULL); |
| 103 | else | 103 | else |
| 104 | rcu_assign_pointer(v->parent.br->vlan_info, NULL); | 104 | RCU_INIT_POINTER(v->parent.br->vlan_info, NULL); |
| 105 | kfree_rcu(v, rcu); | 105 | kfree_rcu(v, rcu); |
| 106 | } | 106 | } |
| 107 | return 0; | 107 | return 0; |
| @@ -113,9 +113,9 @@ static void __vlan_flush(struct net_port_vlans *v) | |||
| 113 | v->pvid = 0; | 113 | v->pvid = 0; |
| 114 | bitmap_zero(v->vlan_bitmap, VLAN_N_VID); | 114 | bitmap_zero(v->vlan_bitmap, VLAN_N_VID); |
| 115 | if (v->port_idx) | 115 | if (v->port_idx) |
| 116 | rcu_assign_pointer(v->parent.port->vlan_info, NULL); | 116 | RCU_INIT_POINTER(v->parent.port->vlan_info, NULL); |
| 117 | else | 117 | else |
| 118 | rcu_assign_pointer(v->parent.br->vlan_info, NULL); | 118 | RCU_INIT_POINTER(v->parent.br->vlan_info, NULL); |
| 119 | kfree_rcu(v, rcu); | 119 | kfree_rcu(v, rcu); |
| 120 | } | 120 | } |
| 121 | 121 | ||
| @@ -170,7 +170,7 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, | |||
| 170 | * rejected. | 170 | * rejected. |
| 171 | */ | 171 | */ |
| 172 | if (!v) | 172 | if (!v) |
| 173 | return false; | 173 | goto drop; |
| 174 | 174 | ||
| 175 | /* If vlan tx offload is disabled on bridge device and frame was | 175 | /* If vlan tx offload is disabled on bridge device and frame was |
| 176 | * sent from vlan device on the bridge device, it does not have | 176 | * sent from vlan device on the bridge device, it does not have |
| @@ -193,7 +193,7 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, | |||
| 193 | * vlan untagged or priority-tagged traffic belongs to. | 193 | * vlan untagged or priority-tagged traffic belongs to. |
| 194 | */ | 194 | */ |
| 195 | if (pvid == VLAN_N_VID) | 195 | if (pvid == VLAN_N_VID) |
| 196 | return false; | 196 | goto drop; |
| 197 | 197 | ||
| 198 | /* PVID is set on this port. Any untagged or priority-tagged | 198 | /* PVID is set on this port. Any untagged or priority-tagged |
| 199 | * ingress frame is considered to belong to this vlan. | 199 | * ingress frame is considered to belong to this vlan. |
| @@ -216,7 +216,8 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, | |||
| 216 | /* Frame had a valid vlan tag. See if vlan is allowed */ | 216 | /* Frame had a valid vlan tag. See if vlan is allowed */ |
| 217 | if (test_bit(*vid, v->vlan_bitmap)) | 217 | if (test_bit(*vid, v->vlan_bitmap)) |
| 218 | return true; | 218 | return true; |
| 219 | 219 | drop: | |
| 220 | kfree_skb(skb); | ||
| 220 | return false; | 221 | return false; |
| 221 | } | 222 | } |
| 222 | 223 | ||
diff --git a/net/bridge/netfilter/ebt_among.c b/net/bridge/netfilter/ebt_among.c index 3fb3c848affe..9024283d2bca 100644 --- a/net/bridge/netfilter/ebt_among.c +++ b/net/bridge/netfilter/ebt_among.c | |||
| @@ -28,7 +28,7 @@ static bool ebt_mac_wormhash_contains(const struct ebt_mac_wormhash *wh, | |||
| 28 | uint32_t cmp[2] = { 0, 0 }; | 28 | uint32_t cmp[2] = { 0, 0 }; |
| 29 | int key = ((const unsigned char *)mac)[5]; | 29 | int key = ((const unsigned char *)mac)[5]; |
| 30 | 30 | ||
| 31 | memcpy(((char *) cmp) + 2, mac, ETH_ALEN); | 31 | ether_addr_copy(((char *) cmp) + 2, mac); |
| 32 | start = wh->table[key]; | 32 | start = wh->table[key]; |
| 33 | limit = wh->table[key + 1]; | 33 | limit = wh->table[key + 1]; |
| 34 | if (ip) { | 34 | if (ip) { |
diff --git a/net/bridge/netfilter/ebt_dnat.c b/net/bridge/netfilter/ebt_dnat.c index c59f7bfae6e2..4e0b0c359325 100644 --- a/net/bridge/netfilter/ebt_dnat.c +++ b/net/bridge/netfilter/ebt_dnat.c | |||
| @@ -22,7 +22,7 @@ ebt_dnat_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
| 22 | if (!skb_make_writable(skb, 0)) | 22 | if (!skb_make_writable(skb, 0)) |
| 23 | return EBT_DROP; | 23 | return EBT_DROP; |
| 24 | 24 | ||
| 25 | memcpy(eth_hdr(skb)->h_dest, info->mac, ETH_ALEN); | 25 | ether_addr_copy(eth_hdr(skb)->h_dest, info->mac); |
| 26 | return info->target; | 26 | return info->target; |
| 27 | } | 27 | } |
| 28 | 28 | ||
diff --git a/net/bridge/netfilter/ebt_redirect.c b/net/bridge/netfilter/ebt_redirect.c index 46624bb6d9be..203964997a51 100644 --- a/net/bridge/netfilter/ebt_redirect.c +++ b/net/bridge/netfilter/ebt_redirect.c | |||
| @@ -25,10 +25,10 @@ ebt_redirect_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
| 25 | 25 | ||
| 26 | if (par->hooknum != NF_BR_BROUTING) | 26 | if (par->hooknum != NF_BR_BROUTING) |
| 27 | /* rcu_read_lock()ed by nf_hook_slow */ | 27 | /* rcu_read_lock()ed by nf_hook_slow */ |
| 28 | memcpy(eth_hdr(skb)->h_dest, | 28 | ether_addr_copy(eth_hdr(skb)->h_dest, |
| 29 | br_port_get_rcu(par->in)->br->dev->dev_addr, ETH_ALEN); | 29 | br_port_get_rcu(par->in)->br->dev->dev_addr); |
| 30 | else | 30 | else |
| 31 | memcpy(eth_hdr(skb)->h_dest, par->in->dev_addr, ETH_ALEN); | 31 | ether_addr_copy(eth_hdr(skb)->h_dest, par->in->dev_addr); |
| 32 | skb->pkt_type = PACKET_HOST; | 32 | skb->pkt_type = PACKET_HOST; |
| 33 | return info->target; | 33 | return info->target; |
| 34 | } | 34 | } |
diff --git a/net/bridge/netfilter/ebt_snat.c b/net/bridge/netfilter/ebt_snat.c index 0f6b118d6cb2..e56ccd060d26 100644 --- a/net/bridge/netfilter/ebt_snat.c +++ b/net/bridge/netfilter/ebt_snat.c | |||
| @@ -24,7 +24,7 @@ ebt_snat_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
| 24 | if (!skb_make_writable(skb, 0)) | 24 | if (!skb_make_writable(skb, 0)) |
| 25 | return EBT_DROP; | 25 | return EBT_DROP; |
| 26 | 26 | ||
| 27 | memcpy(eth_hdr(skb)->h_source, info->mac, ETH_ALEN); | 27 | ether_addr_copy(eth_hdr(skb)->h_source, info->mac); |
| 28 | if (!(info->target & NAT_ARP_BIT) && | 28 | if (!(info->target & NAT_ARP_BIT) && |
| 29 | eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) { | 29 | eth_hdr(skb)->h_proto == htons(ETH_P_ARP)) { |
| 30 | const struct arphdr *ap; | 30 | const struct arphdr *ap; |
diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index 0e474b13463b..1059ed3bc255 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c | |||
| @@ -1044,10 +1044,9 @@ static int do_replace_finish(struct net *net, struct ebt_replace *repl, | |||
| 1044 | if (repl->num_counters && | 1044 | if (repl->num_counters && |
| 1045 | copy_to_user(repl->counters, counterstmp, | 1045 | copy_to_user(repl->counters, counterstmp, |
| 1046 | repl->num_counters * sizeof(struct ebt_counter))) { | 1046 | repl->num_counters * sizeof(struct ebt_counter))) { |
| 1047 | ret = -EFAULT; | 1047 | /* Silent error, can't fail, new table is already in place */ |
| 1048 | net_warn_ratelimited("ebtables: counters copy to user failed while replacing table\n"); | ||
| 1048 | } | 1049 | } |
| 1049 | else | ||
| 1050 | ret = 0; | ||
| 1051 | 1050 | ||
| 1052 | /* decrease module count and free resources */ | 1051 | /* decrease module count and free resources */ |
| 1053 | EBT_ENTRY_ITERATE(table->entries, table->entries_size, | 1052 | EBT_ENTRY_ITERATE(table->entries, table->entries_size, |
diff --git a/net/caif/caif_socket.c b/net/caif/caif_socket.c index d6be3edb7a43..e8437094d15f 100644 --- a/net/caif/caif_socket.c +++ b/net/caif/caif_socket.c | |||
| @@ -124,7 +124,6 @@ static void caif_flow_ctrl(struct sock *sk, int mode) | |||
| 124 | static int caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | 124 | static int caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) |
| 125 | { | 125 | { |
| 126 | int err; | 126 | int err; |
| 127 | int skb_len; | ||
| 128 | unsigned long flags; | 127 | unsigned long flags; |
| 129 | struct sk_buff_head *list = &sk->sk_receive_queue; | 128 | struct sk_buff_head *list = &sk->sk_receive_queue; |
| 130 | struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); | 129 | struct caifsock *cf_sk = container_of(sk, struct caifsock, sk); |
| @@ -153,14 +152,13 @@ static int caif_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
| 153 | * may be freed by other threads of control pulling packets | 152 | * may be freed by other threads of control pulling packets |
| 154 | * from the queue. | 153 | * from the queue. |
| 155 | */ | 154 | */ |
| 156 | skb_len = skb->len; | ||
| 157 | spin_lock_irqsave(&list->lock, flags); | 155 | spin_lock_irqsave(&list->lock, flags); |
| 158 | if (!sock_flag(sk, SOCK_DEAD)) | 156 | if (!sock_flag(sk, SOCK_DEAD)) |
| 159 | __skb_queue_tail(list, skb); | 157 | __skb_queue_tail(list, skb); |
| 160 | spin_unlock_irqrestore(&list->lock, flags); | 158 | spin_unlock_irqrestore(&list->lock, flags); |
| 161 | 159 | ||
| 162 | if (!sock_flag(sk, SOCK_DEAD)) | 160 | if (!sock_flag(sk, SOCK_DEAD)) |
| 163 | sk->sk_data_ready(sk, skb_len); | 161 | sk->sk_data_ready(sk); |
| 164 | else | 162 | else |
| 165 | kfree_skb(skb); | 163 | kfree_skb(skb); |
| 166 | return 0; | 164 | return 0; |
diff --git a/net/ceph/crush/mapper.c b/net/ceph/crush/mapper.c index b703790b4e44..a1ef53c04415 100644 --- a/net/ceph/crush/mapper.c +++ b/net/ceph/crush/mapper.c | |||
| @@ -292,10 +292,12 @@ static int is_out(const struct crush_map *map, | |||
| 292 | * @outpos: our position in that vector | 292 | * @outpos: our position in that vector |
| 293 | * @tries: number of attempts to make | 293 | * @tries: number of attempts to make |
| 294 | * @recurse_tries: number of attempts to have recursive chooseleaf make | 294 | * @recurse_tries: number of attempts to have recursive chooseleaf make |
| 295 | * @local_tries: localized retries | 295 | * @local_retries: localized retries |
| 296 | * @local_fallback_tries: localized fallback retries | 296 | * @local_fallback_retries: localized fallback retries |
| 297 | * @recurse_to_leaf: true if we want one device under each item of given type (chooseleaf instead of choose) | 297 | * @recurse_to_leaf: true if we want one device under each item of given type (chooseleaf instead of choose) |
| 298 | * @vary_r: pass r to recursive calls | ||
| 298 | * @out2: second output vector for leaf items (if @recurse_to_leaf) | 299 | * @out2: second output vector for leaf items (if @recurse_to_leaf) |
| 300 | * @parent_r: r value passed from the parent | ||
| 299 | */ | 301 | */ |
| 300 | static int crush_choose_firstn(const struct crush_map *map, | 302 | static int crush_choose_firstn(const struct crush_map *map, |
| 301 | struct crush_bucket *bucket, | 303 | struct crush_bucket *bucket, |
| @@ -304,10 +306,12 @@ static int crush_choose_firstn(const struct crush_map *map, | |||
| 304 | int *out, int outpos, | 306 | int *out, int outpos, |
| 305 | unsigned int tries, | 307 | unsigned int tries, |
| 306 | unsigned int recurse_tries, | 308 | unsigned int recurse_tries, |
| 307 | unsigned int local_tries, | 309 | unsigned int local_retries, |
| 308 | unsigned int local_fallback_tries, | 310 | unsigned int local_fallback_retries, |
| 309 | int recurse_to_leaf, | 311 | int recurse_to_leaf, |
| 310 | int *out2) | 312 | unsigned int vary_r, |
| 313 | int *out2, | ||
| 314 | int parent_r) | ||
| 311 | { | 315 | { |
| 312 | int rep; | 316 | int rep; |
| 313 | unsigned int ftotal, flocal; | 317 | unsigned int ftotal, flocal; |
| @@ -319,8 +323,11 @@ static int crush_choose_firstn(const struct crush_map *map, | |||
| 319 | int itemtype; | 323 | int itemtype; |
| 320 | int collide, reject; | 324 | int collide, reject; |
| 321 | 325 | ||
| 322 | dprintk("CHOOSE%s bucket %d x %d outpos %d numrep %d\n", recurse_to_leaf ? "_LEAF" : "", | 326 | dprintk("CHOOSE%s bucket %d x %d outpos %d numrep %d tries %d recurse_tries %d local_retries %d local_fallback_retries %d parent_r %d\n", |
| 323 | bucket->id, x, outpos, numrep); | 327 | recurse_to_leaf ? "_LEAF" : "", |
| 328 | bucket->id, x, outpos, numrep, | ||
| 329 | tries, recurse_tries, local_retries, local_fallback_retries, | ||
| 330 | parent_r); | ||
| 324 | 331 | ||
| 325 | for (rep = outpos; rep < numrep; rep++) { | 332 | for (rep = outpos; rep < numrep; rep++) { |
| 326 | /* keep trying until we get a non-out, non-colliding item */ | 333 | /* keep trying until we get a non-out, non-colliding item */ |
| @@ -335,7 +342,7 @@ static int crush_choose_firstn(const struct crush_map *map, | |||
| 335 | do { | 342 | do { |
| 336 | collide = 0; | 343 | collide = 0; |
| 337 | retry_bucket = 0; | 344 | retry_bucket = 0; |
| 338 | r = rep; | 345 | r = rep + parent_r; |
| 339 | /* r' = r + f_total */ | 346 | /* r' = r + f_total */ |
| 340 | r += ftotal; | 347 | r += ftotal; |
| 341 | 348 | ||
| @@ -344,9 +351,9 @@ static int crush_choose_firstn(const struct crush_map *map, | |||
| 344 | reject = 1; | 351 | reject = 1; |
| 345 | goto reject; | 352 | goto reject; |
| 346 | } | 353 | } |
| 347 | if (local_fallback_tries > 0 && | 354 | if (local_fallback_retries > 0 && |
| 348 | flocal >= (in->size>>1) && | 355 | flocal >= (in->size>>1) && |
| 349 | flocal > local_fallback_tries) | 356 | flocal > local_fallback_retries) |
| 350 | item = bucket_perm_choose(in, x, r); | 357 | item = bucket_perm_choose(in, x, r); |
| 351 | else | 358 | else |
| 352 | item = crush_bucket_choose(in, x, r); | 359 | item = crush_bucket_choose(in, x, r); |
| @@ -387,16 +394,23 @@ static int crush_choose_firstn(const struct crush_map *map, | |||
| 387 | reject = 0; | 394 | reject = 0; |
| 388 | if (!collide && recurse_to_leaf) { | 395 | if (!collide && recurse_to_leaf) { |
| 389 | if (item < 0) { | 396 | if (item < 0) { |
| 397 | int sub_r; | ||
| 398 | if (vary_r) | ||
| 399 | sub_r = r >> (vary_r-1); | ||
| 400 | else | ||
| 401 | sub_r = 0; | ||
| 390 | if (crush_choose_firstn(map, | 402 | if (crush_choose_firstn(map, |
| 391 | map->buckets[-1-item], | 403 | map->buckets[-1-item], |
| 392 | weight, weight_max, | 404 | weight, weight_max, |
| 393 | x, outpos+1, 0, | 405 | x, outpos+1, 0, |
| 394 | out2, outpos, | 406 | out2, outpos, |
| 395 | recurse_tries, 0, | 407 | recurse_tries, 0, |
| 396 | local_tries, | 408 | local_retries, |
| 397 | local_fallback_tries, | 409 | local_fallback_retries, |
| 398 | 0, | 410 | 0, |
| 399 | NULL) <= outpos) | 411 | vary_r, |
| 412 | NULL, | ||
| 413 | sub_r) <= outpos) | ||
| 400 | /* didn't get leaf */ | 414 | /* didn't get leaf */ |
| 401 | reject = 1; | 415 | reject = 1; |
| 402 | } else { | 416 | } else { |
| @@ -420,14 +434,14 @@ reject: | |||
| 420 | ftotal++; | 434 | ftotal++; |
| 421 | flocal++; | 435 | flocal++; |
| 422 | 436 | ||
| 423 | if (collide && flocal <= local_tries) | 437 | if (collide && flocal <= local_retries) |
| 424 | /* retry locally a few times */ | 438 | /* retry locally a few times */ |
| 425 | retry_bucket = 1; | 439 | retry_bucket = 1; |
| 426 | else if (local_fallback_tries > 0 && | 440 | else if (local_fallback_retries > 0 && |
| 427 | flocal <= in->size + local_fallback_tries) | 441 | flocal <= in->size + local_fallback_retries) |
| 428 | /* exhaustive bucket search */ | 442 | /* exhaustive bucket search */ |
| 429 | retry_bucket = 1; | 443 | retry_bucket = 1; |
| 430 | else if (ftotal <= tries) | 444 | else if (ftotal < tries) |
| 431 | /* then retry descent */ | 445 | /* then retry descent */ |
| 432 | retry_descent = 1; | 446 | retry_descent = 1; |
| 433 | else | 447 | else |
| @@ -640,10 +654,20 @@ int crush_do_rule(const struct crush_map *map, | |||
| 640 | __u32 step; | 654 | __u32 step; |
| 641 | int i, j; | 655 | int i, j; |
| 642 | int numrep; | 656 | int numrep; |
| 643 | int choose_tries = map->choose_total_tries; | 657 | /* |
| 644 | int choose_local_tries = map->choose_local_tries; | 658 | * the original choose_total_tries value was off by one (it |
| 645 | int choose_local_fallback_tries = map->choose_local_fallback_tries; | 659 | * counted "retries" and not "tries"). add one. |
| 660 | */ | ||
| 661 | int choose_tries = map->choose_total_tries + 1; | ||
| 646 | int choose_leaf_tries = 0; | 662 | int choose_leaf_tries = 0; |
| 663 | /* | ||
| 664 | * the local tries values were counted as "retries", though, | ||
| 665 | * and need no adjustment | ||
| 666 | */ | ||
| 667 | int choose_local_retries = map->choose_local_tries; | ||
| 668 | int choose_local_fallback_retries = map->choose_local_fallback_tries; | ||
| 669 | |||
| 670 | int vary_r = map->chooseleaf_vary_r; | ||
| 647 | 671 | ||
| 648 | if ((__u32)ruleno >= map->max_rules) { | 672 | if ((__u32)ruleno >= map->max_rules) { |
| 649 | dprintk(" bad ruleno %d\n", ruleno); | 673 | dprintk(" bad ruleno %d\n", ruleno); |
| @@ -676,13 +700,18 @@ int crush_do_rule(const struct crush_map *map, | |||
| 676 | break; | 700 | break; |
| 677 | 701 | ||
| 678 | case CRUSH_RULE_SET_CHOOSE_LOCAL_TRIES: | 702 | case CRUSH_RULE_SET_CHOOSE_LOCAL_TRIES: |
| 679 | if (curstep->arg1 > 0) | 703 | if (curstep->arg1 >= 0) |
| 680 | choose_local_tries = curstep->arg1; | 704 | choose_local_retries = curstep->arg1; |
| 681 | break; | 705 | break; |
| 682 | 706 | ||
| 683 | case CRUSH_RULE_SET_CHOOSE_LOCAL_FALLBACK_TRIES: | 707 | case CRUSH_RULE_SET_CHOOSE_LOCAL_FALLBACK_TRIES: |
| 684 | if (curstep->arg1 > 0) | 708 | if (curstep->arg1 >= 0) |
| 685 | choose_local_fallback_tries = curstep->arg1; | 709 | choose_local_fallback_retries = curstep->arg1; |
| 710 | break; | ||
| 711 | |||
| 712 | case CRUSH_RULE_SET_CHOOSELEAF_VARY_R: | ||
| 713 | if (curstep->arg1 >= 0) | ||
| 714 | vary_r = curstep->arg1; | ||
| 686 | break; | 715 | break; |
| 687 | 716 | ||
| 688 | case CRUSH_RULE_CHOOSELEAF_FIRSTN: | 717 | case CRUSH_RULE_CHOOSELEAF_FIRSTN: |
| @@ -734,10 +763,12 @@ int crush_do_rule(const struct crush_map *map, | |||
| 734 | o+osize, j, | 763 | o+osize, j, |
| 735 | choose_tries, | 764 | choose_tries, |
| 736 | recurse_tries, | 765 | recurse_tries, |
| 737 | choose_local_tries, | 766 | choose_local_retries, |
| 738 | choose_local_fallback_tries, | 767 | choose_local_fallback_retries, |
| 739 | recurse_to_leaf, | 768 | recurse_to_leaf, |
| 740 | c+osize); | 769 | vary_r, |
| 770 | c+osize, | ||
| 771 | 0); | ||
| 741 | } else { | 772 | } else { |
| 742 | crush_choose_indep( | 773 | crush_choose_indep( |
| 743 | map, | 774 | map, |
diff --git a/net/ceph/debugfs.c b/net/ceph/debugfs.c index 258a382e75ed..10421a4b76f8 100644 --- a/net/ceph/debugfs.c +++ b/net/ceph/debugfs.c | |||
| @@ -53,34 +53,55 @@ static int osdmap_show(struct seq_file *s, void *p) | |||
| 53 | { | 53 | { |
| 54 | int i; | 54 | int i; |
| 55 | struct ceph_client *client = s->private; | 55 | struct ceph_client *client = s->private; |
| 56 | struct ceph_osdmap *map = client->osdc.osdmap; | ||
| 56 | struct rb_node *n; | 57 | struct rb_node *n; |
| 57 | 58 | ||
| 58 | if (client->osdc.osdmap == NULL) | 59 | if (map == NULL) |
| 59 | return 0; | 60 | return 0; |
| 60 | seq_printf(s, "epoch %d\n", client->osdc.osdmap->epoch); | 61 | |
| 62 | seq_printf(s, "epoch %d\n", map->epoch); | ||
| 61 | seq_printf(s, "flags%s%s\n", | 63 | seq_printf(s, "flags%s%s\n", |
| 62 | (client->osdc.osdmap->flags & CEPH_OSDMAP_NEARFULL) ? | 64 | (map->flags & CEPH_OSDMAP_NEARFULL) ? " NEARFULL" : "", |
| 63 | " NEARFULL" : "", | 65 | (map->flags & CEPH_OSDMAP_FULL) ? " FULL" : ""); |
| 64 | (client->osdc.osdmap->flags & CEPH_OSDMAP_FULL) ? | 66 | |
| 65 | " FULL" : ""); | 67 | for (n = rb_first(&map->pg_pools); n; n = rb_next(n)) { |
| 66 | for (n = rb_first(&client->osdc.osdmap->pg_pools); n; n = rb_next(n)) { | ||
| 67 | struct ceph_pg_pool_info *pool = | 68 | struct ceph_pg_pool_info *pool = |
| 68 | rb_entry(n, struct ceph_pg_pool_info, node); | 69 | rb_entry(n, struct ceph_pg_pool_info, node); |
| 69 | seq_printf(s, "pg_pool %llu pg_num %d / %d\n", | 70 | |
| 70 | (unsigned long long)pool->id, pool->pg_num, | 71 | seq_printf(s, "pool %lld pg_num %u (%d) read_tier %lld write_tier %lld\n", |
| 71 | pool->pg_num_mask); | 72 | pool->id, pool->pg_num, pool->pg_num_mask, |
| 73 | pool->read_tier, pool->write_tier); | ||
| 72 | } | 74 | } |
| 73 | for (i = 0; i < client->osdc.osdmap->max_osd; i++) { | 75 | for (i = 0; i < map->max_osd; i++) { |
| 74 | struct ceph_entity_addr *addr = | 76 | struct ceph_entity_addr *addr = &map->osd_addr[i]; |
| 75 | &client->osdc.osdmap->osd_addr[i]; | 77 | int state = map->osd_state[i]; |
| 76 | int state = client->osdc.osdmap->osd_state[i]; | ||
| 77 | char sb[64]; | 78 | char sb[64]; |
| 78 | 79 | ||
| 79 | seq_printf(s, "\tosd%d\t%s\t%3d%%\t(%s)\n", | 80 | seq_printf(s, "osd%d\t%s\t%3d%%\t(%s)\t%3d%%\n", |
| 80 | i, ceph_pr_addr(&addr->in_addr), | 81 | i, ceph_pr_addr(&addr->in_addr), |
| 81 | ((client->osdc.osdmap->osd_weight[i]*100) >> 16), | 82 | ((map->osd_weight[i]*100) >> 16), |
| 82 | ceph_osdmap_state_str(sb, sizeof(sb), state)); | 83 | ceph_osdmap_state_str(sb, sizeof(sb), state), |
| 84 | ((ceph_get_primary_affinity(map, i)*100) >> 16)); | ||
| 85 | } | ||
| 86 | for (n = rb_first(&map->pg_temp); n; n = rb_next(n)) { | ||
| 87 | struct ceph_pg_mapping *pg = | ||
| 88 | rb_entry(n, struct ceph_pg_mapping, node); | ||
| 89 | |||
| 90 | seq_printf(s, "pg_temp %llu.%x [", pg->pgid.pool, | ||
| 91 | pg->pgid.seed); | ||
| 92 | for (i = 0; i < pg->pg_temp.len; i++) | ||
| 93 | seq_printf(s, "%s%d", (i == 0 ? "" : ","), | ||
| 94 | pg->pg_temp.osds[i]); | ||
| 95 | seq_printf(s, "]\n"); | ||
| 83 | } | 96 | } |
| 97 | for (n = rb_first(&map->primary_temp); n; n = rb_next(n)) { | ||
| 98 | struct ceph_pg_mapping *pg = | ||
| 99 | rb_entry(n, struct ceph_pg_mapping, node); | ||
| 100 | |||
| 101 | seq_printf(s, "primary_temp %llu.%x %d\n", pg->pgid.pool, | ||
| 102 | pg->pgid.seed, pg->primary_temp.osd); | ||
| 103 | } | ||
| 104 | |||
| 84 | return 0; | 105 | return 0; |
| 85 | } | 106 | } |
| 86 | 107 | ||
diff --git a/net/ceph/messenger.c b/net/ceph/messenger.c index 30efc5c18622..dac7f9b98687 100644 --- a/net/ceph/messenger.c +++ b/net/ceph/messenger.c | |||
| @@ -383,7 +383,7 @@ static void con_sock_state_closed(struct ceph_connection *con) | |||
| 383 | */ | 383 | */ |
| 384 | 384 | ||
| 385 | /* data available on socket, or listen socket received a connect */ | 385 | /* data available on socket, or listen socket received a connect */ |
| 386 | static void ceph_sock_data_ready(struct sock *sk, int count_unused) | 386 | static void ceph_sock_data_ready(struct sock *sk) |
| 387 | { | 387 | { |
| 388 | struct ceph_connection *con = sk->sk_user_data; | 388 | struct ceph_connection *con = sk->sk_user_data; |
| 389 | if (atomic_read(&con->msgr->stopping)) { | 389 | if (atomic_read(&con->msgr->stopping)) { |
| @@ -919,6 +919,9 @@ static bool ceph_msg_data_pages_advance(struct ceph_msg_data_cursor *cursor, | |||
| 919 | if (!bytes || cursor->page_offset) | 919 | if (!bytes || cursor->page_offset) |
| 920 | return false; /* more bytes to process in the current page */ | 920 | return false; /* more bytes to process in the current page */ |
| 921 | 921 | ||
| 922 | if (!cursor->resid) | ||
| 923 | return false; /* no more data */ | ||
| 924 | |||
| 922 | /* Move on to the next page; offset is already at 0 */ | 925 | /* Move on to the next page; offset is already at 0 */ |
| 923 | 926 | ||
| 924 | BUG_ON(cursor->page_index >= cursor->page_count); | 927 | BUG_ON(cursor->page_index >= cursor->page_count); |
| @@ -1004,6 +1007,9 @@ static bool ceph_msg_data_pagelist_advance(struct ceph_msg_data_cursor *cursor, | |||
| 1004 | if (!bytes || cursor->offset & ~PAGE_MASK) | 1007 | if (!bytes || cursor->offset & ~PAGE_MASK) |
| 1005 | return false; /* more bytes to process in the current page */ | 1008 | return false; /* more bytes to process in the current page */ |
| 1006 | 1009 | ||
| 1010 | if (!cursor->resid) | ||
| 1011 | return false; /* no more data */ | ||
| 1012 | |||
| 1007 | /* Move on to the next page */ | 1013 | /* Move on to the next page */ |
| 1008 | 1014 | ||
| 1009 | BUG_ON(list_is_last(&cursor->page->lru, &pagelist->head)); | 1015 | BUG_ON(list_is_last(&cursor->page->lru, &pagelist->head)); |
diff --git a/net/ceph/osd_client.c b/net/ceph/osd_client.c index 0676f2b199d6..b0dfce77656a 100644 --- a/net/ceph/osd_client.c +++ b/net/ceph/osd_client.c | |||
| @@ -436,6 +436,7 @@ static bool osd_req_opcode_valid(u16 opcode) | |||
| 436 | case CEPH_OSD_OP_OMAPCLEAR: | 436 | case CEPH_OSD_OP_OMAPCLEAR: |
| 437 | case CEPH_OSD_OP_OMAPRMKEYS: | 437 | case CEPH_OSD_OP_OMAPRMKEYS: |
| 438 | case CEPH_OSD_OP_OMAP_CMP: | 438 | case CEPH_OSD_OP_OMAP_CMP: |
| 439 | case CEPH_OSD_OP_SETALLOCHINT: | ||
| 439 | case CEPH_OSD_OP_CLONERANGE: | 440 | case CEPH_OSD_OP_CLONERANGE: |
| 440 | case CEPH_OSD_OP_ASSERT_SRC_VERSION: | 441 | case CEPH_OSD_OP_ASSERT_SRC_VERSION: |
| 441 | case CEPH_OSD_OP_SRC_CMPXATTR: | 442 | case CEPH_OSD_OP_SRC_CMPXATTR: |
| @@ -591,6 +592,26 @@ void osd_req_op_watch_init(struct ceph_osd_request *osd_req, | |||
| 591 | } | 592 | } |
| 592 | EXPORT_SYMBOL(osd_req_op_watch_init); | 593 | EXPORT_SYMBOL(osd_req_op_watch_init); |
| 593 | 594 | ||
| 595 | void osd_req_op_alloc_hint_init(struct ceph_osd_request *osd_req, | ||
| 596 | unsigned int which, | ||
| 597 | u64 expected_object_size, | ||
| 598 | u64 expected_write_size) | ||
| 599 | { | ||
| 600 | struct ceph_osd_req_op *op = _osd_req_op_init(osd_req, which, | ||
| 601 | CEPH_OSD_OP_SETALLOCHINT); | ||
| 602 | |||
| 603 | op->alloc_hint.expected_object_size = expected_object_size; | ||
| 604 | op->alloc_hint.expected_write_size = expected_write_size; | ||
| 605 | |||
| 606 | /* | ||
| 607 | * CEPH_OSD_OP_SETALLOCHINT op is advisory and therefore deemed | ||
| 608 | * not worth a feature bit. Set FAILOK per-op flag to make | ||
| 609 | * sure older osds don't trip over an unsupported opcode. | ||
| 610 | */ | ||
| 611 | op->flags |= CEPH_OSD_OP_FLAG_FAILOK; | ||
| 612 | } | ||
| 613 | EXPORT_SYMBOL(osd_req_op_alloc_hint_init); | ||
| 614 | |||
| 594 | static void ceph_osdc_msg_data_add(struct ceph_msg *msg, | 615 | static void ceph_osdc_msg_data_add(struct ceph_msg *msg, |
| 595 | struct ceph_osd_data *osd_data) | 616 | struct ceph_osd_data *osd_data) |
| 596 | { | 617 | { |
| @@ -681,6 +702,12 @@ static u64 osd_req_encode_op(struct ceph_osd_request *req, | |||
| 681 | dst->watch.ver = cpu_to_le64(src->watch.ver); | 702 | dst->watch.ver = cpu_to_le64(src->watch.ver); |
| 682 | dst->watch.flag = src->watch.flag; | 703 | dst->watch.flag = src->watch.flag; |
| 683 | break; | 704 | break; |
| 705 | case CEPH_OSD_OP_SETALLOCHINT: | ||
| 706 | dst->alloc_hint.expected_object_size = | ||
| 707 | cpu_to_le64(src->alloc_hint.expected_object_size); | ||
| 708 | dst->alloc_hint.expected_write_size = | ||
| 709 | cpu_to_le64(src->alloc_hint.expected_write_size); | ||
| 710 | break; | ||
| 684 | default: | 711 | default: |
| 685 | pr_err("unsupported osd opcode %s\n", | 712 | pr_err("unsupported osd opcode %s\n", |
| 686 | ceph_osd_op_name(src->op)); | 713 | ceph_osd_op_name(src->op)); |
| @@ -688,7 +715,9 @@ static u64 osd_req_encode_op(struct ceph_osd_request *req, | |||
| 688 | 715 | ||
| 689 | return 0; | 716 | return 0; |
| 690 | } | 717 | } |
| 718 | |||
| 691 | dst->op = cpu_to_le16(src->op); | 719 | dst->op = cpu_to_le16(src->op); |
| 720 | dst->flags = cpu_to_le32(src->flags); | ||
| 692 | dst->payload_len = cpu_to_le32(src->payload_len); | 721 | dst->payload_len = cpu_to_le32(src->payload_len); |
| 693 | 722 | ||
| 694 | return request_data_len; | 723 | return request_data_len; |
| @@ -1304,7 +1333,7 @@ static int __map_request(struct ceph_osd_client *osdc, | |||
| 1304 | { | 1333 | { |
| 1305 | struct ceph_pg pgid; | 1334 | struct ceph_pg pgid; |
| 1306 | int acting[CEPH_PG_MAX_SIZE]; | 1335 | int acting[CEPH_PG_MAX_SIZE]; |
| 1307 | int o = -1, num = 0; | 1336 | int num, o; |
| 1308 | int err; | 1337 | int err; |
| 1309 | bool was_paused; | 1338 | bool was_paused; |
| 1310 | 1339 | ||
| @@ -1317,11 +1346,9 @@ static int __map_request(struct ceph_osd_client *osdc, | |||
| 1317 | } | 1346 | } |
| 1318 | req->r_pgid = pgid; | 1347 | req->r_pgid = pgid; |
| 1319 | 1348 | ||
| 1320 | err = ceph_calc_pg_acting(osdc->osdmap, pgid, acting); | 1349 | num = ceph_calc_pg_acting(osdc->osdmap, pgid, acting, &o); |
| 1321 | if (err > 0) { | 1350 | if (num < 0) |
| 1322 | o = acting[0]; | 1351 | num = 0; |
| 1323 | num = err; | ||
| 1324 | } | ||
| 1325 | 1352 | ||
| 1326 | was_paused = req->r_paused; | 1353 | was_paused = req->r_paused; |
| 1327 | req->r_paused = __req_should_be_paused(osdc, req); | 1354 | req->r_paused = __req_should_be_paused(osdc, req); |
| @@ -2033,7 +2060,7 @@ void ceph_osdc_handle_map(struct ceph_osd_client *osdc, struct ceph_msg *msg) | |||
| 2033 | int skipped_map = 0; | 2060 | int skipped_map = 0; |
| 2034 | 2061 | ||
| 2035 | dout("taking full map %u len %d\n", epoch, maplen); | 2062 | dout("taking full map %u len %d\n", epoch, maplen); |
| 2036 | newmap = osdmap_decode(&p, p+maplen); | 2063 | newmap = ceph_osdmap_decode(&p, p+maplen); |
| 2037 | if (IS_ERR(newmap)) { | 2064 | if (IS_ERR(newmap)) { |
| 2038 | err = PTR_ERR(newmap); | 2065 | err = PTR_ERR(newmap); |
| 2039 | goto bad; | 2066 | goto bad; |
| @@ -2082,7 +2109,6 @@ bad: | |||
| 2082 | pr_err("osdc handle_map corrupt msg\n"); | 2109 | pr_err("osdc handle_map corrupt msg\n"); |
| 2083 | ceph_msg_dump(msg); | 2110 | ceph_msg_dump(msg); |
| 2084 | up_write(&osdc->map_sem); | 2111 | up_write(&osdc->map_sem); |
| 2085 | return; | ||
| 2086 | } | 2112 | } |
| 2087 | 2113 | ||
| 2088 | /* | 2114 | /* |
| @@ -2281,7 +2307,6 @@ done_err: | |||
| 2281 | 2307 | ||
| 2282 | bad: | 2308 | bad: |
| 2283 | pr_err("osdc handle_watch_notify corrupt msg\n"); | 2309 | pr_err("osdc handle_watch_notify corrupt msg\n"); |
| 2284 | return; | ||
| 2285 | } | 2310 | } |
| 2286 | 2311 | ||
| 2287 | /* | 2312 | /* |
diff --git a/net/ceph/osdmap.c b/net/ceph/osdmap.c index aade4a5c1c07..e632b5a52f5b 100644 --- a/net/ceph/osdmap.c +++ b/net/ceph/osdmap.c | |||
| @@ -343,7 +343,7 @@ bad: | |||
| 343 | 343 | ||
| 344 | /* | 344 | /* |
| 345 | * rbtree of pg_mapping for handling pg_temp (explicit mapping of pgid | 345 | * rbtree of pg_mapping for handling pg_temp (explicit mapping of pgid |
| 346 | * to a set of osds) | 346 | * to a set of osds) and primary_temp (explicit primary setting) |
| 347 | */ | 347 | */ |
| 348 | static int pgid_cmp(struct ceph_pg l, struct ceph_pg r) | 348 | static int pgid_cmp(struct ceph_pg l, struct ceph_pg r) |
| 349 | { | 349 | { |
| @@ -506,7 +506,7 @@ static void __remove_pg_pool(struct rb_root *root, struct ceph_pg_pool_info *pi) | |||
| 506 | kfree(pi); | 506 | kfree(pi); |
| 507 | } | 507 | } |
| 508 | 508 | ||
| 509 | static int __decode_pool(void **p, void *end, struct ceph_pg_pool_info *pi) | 509 | static int decode_pool(void **p, void *end, struct ceph_pg_pool_info *pi) |
| 510 | { | 510 | { |
| 511 | u8 ev, cv; | 511 | u8 ev, cv; |
| 512 | unsigned len, num; | 512 | unsigned len, num; |
| @@ -587,7 +587,7 @@ bad: | |||
| 587 | return -EINVAL; | 587 | return -EINVAL; |
| 588 | } | 588 | } |
| 589 | 589 | ||
| 590 | static int __decode_pool_names(void **p, void *end, struct ceph_osdmap *map) | 590 | static int decode_pool_names(void **p, void *end, struct ceph_osdmap *map) |
| 591 | { | 591 | { |
| 592 | struct ceph_pg_pool_info *pi; | 592 | struct ceph_pg_pool_info *pi; |
| 593 | u32 num, len; | 593 | u32 num, len; |
| @@ -633,6 +633,13 @@ void ceph_osdmap_destroy(struct ceph_osdmap *map) | |||
| 633 | rb_erase(&pg->node, &map->pg_temp); | 633 | rb_erase(&pg->node, &map->pg_temp); |
| 634 | kfree(pg); | 634 | kfree(pg); |
| 635 | } | 635 | } |
| 636 | while (!RB_EMPTY_ROOT(&map->primary_temp)) { | ||
| 637 | struct ceph_pg_mapping *pg = | ||
| 638 | rb_entry(rb_first(&map->primary_temp), | ||
| 639 | struct ceph_pg_mapping, node); | ||
| 640 | rb_erase(&pg->node, &map->primary_temp); | ||
| 641 | kfree(pg); | ||
| 642 | } | ||
| 636 | while (!RB_EMPTY_ROOT(&map->pg_pools)) { | 643 | while (!RB_EMPTY_ROOT(&map->pg_pools)) { |
| 637 | struct ceph_pg_pool_info *pi = | 644 | struct ceph_pg_pool_info *pi = |
| 638 | rb_entry(rb_first(&map->pg_pools), | 645 | rb_entry(rb_first(&map->pg_pools), |
| @@ -642,186 +649,516 @@ void ceph_osdmap_destroy(struct ceph_osdmap *map) | |||
| 642 | kfree(map->osd_state); | 649 | kfree(map->osd_state); |
| 643 | kfree(map->osd_weight); | 650 | kfree(map->osd_weight); |
| 644 | kfree(map->osd_addr); | 651 | kfree(map->osd_addr); |
| 652 | kfree(map->osd_primary_affinity); | ||
| 645 | kfree(map); | 653 | kfree(map); |
| 646 | } | 654 | } |
| 647 | 655 | ||
| 648 | /* | 656 | /* |
| 649 | * adjust max osd value. reallocate arrays. | 657 | * Adjust max_osd value, (re)allocate arrays. |
| 658 | * | ||
| 659 | * The new elements are properly initialized. | ||
| 650 | */ | 660 | */ |
| 651 | static int osdmap_set_max_osd(struct ceph_osdmap *map, int max) | 661 | static int osdmap_set_max_osd(struct ceph_osdmap *map, int max) |
| 652 | { | 662 | { |
| 653 | u8 *state; | 663 | u8 *state; |
| 654 | struct ceph_entity_addr *addr; | ||
| 655 | u32 *weight; | 664 | u32 *weight; |
| 665 | struct ceph_entity_addr *addr; | ||
| 666 | int i; | ||
| 656 | 667 | ||
| 657 | state = kcalloc(max, sizeof(*state), GFP_NOFS); | 668 | state = krealloc(map->osd_state, max*sizeof(*state), GFP_NOFS); |
| 658 | addr = kcalloc(max, sizeof(*addr), GFP_NOFS); | 669 | weight = krealloc(map->osd_weight, max*sizeof(*weight), GFP_NOFS); |
| 659 | weight = kcalloc(max, sizeof(*weight), GFP_NOFS); | 670 | addr = krealloc(map->osd_addr, max*sizeof(*addr), GFP_NOFS); |
| 660 | if (state == NULL || addr == NULL || weight == NULL) { | 671 | if (!state || !weight || !addr) { |
| 661 | kfree(state); | 672 | kfree(state); |
| 662 | kfree(addr); | ||
| 663 | kfree(weight); | 673 | kfree(weight); |
| 674 | kfree(addr); | ||
| 675 | |||
| 664 | return -ENOMEM; | 676 | return -ENOMEM; |
| 665 | } | 677 | } |
| 666 | 678 | ||
| 667 | /* copy old? */ | 679 | for (i = map->max_osd; i < max; i++) { |
| 668 | if (map->osd_state) { | 680 | state[i] = 0; |
| 669 | memcpy(state, map->osd_state, map->max_osd*sizeof(*state)); | 681 | weight[i] = CEPH_OSD_OUT; |
| 670 | memcpy(addr, map->osd_addr, map->max_osd*sizeof(*addr)); | 682 | memset(addr + i, 0, sizeof(*addr)); |
| 671 | memcpy(weight, map->osd_weight, map->max_osd*sizeof(*weight)); | ||
| 672 | kfree(map->osd_state); | ||
| 673 | kfree(map->osd_addr); | ||
| 674 | kfree(map->osd_weight); | ||
| 675 | } | 683 | } |
| 676 | 684 | ||
| 677 | map->osd_state = state; | 685 | map->osd_state = state; |
| 678 | map->osd_weight = weight; | 686 | map->osd_weight = weight; |
| 679 | map->osd_addr = addr; | 687 | map->osd_addr = addr; |
| 688 | |||
| 689 | if (map->osd_primary_affinity) { | ||
| 690 | u32 *affinity; | ||
| 691 | |||
| 692 | affinity = krealloc(map->osd_primary_affinity, | ||
| 693 | max*sizeof(*affinity), GFP_NOFS); | ||
| 694 | if (!affinity) | ||
| 695 | return -ENOMEM; | ||
| 696 | |||
| 697 | for (i = map->max_osd; i < max; i++) | ||
| 698 | affinity[i] = CEPH_OSD_DEFAULT_PRIMARY_AFFINITY; | ||
| 699 | |||
| 700 | map->osd_primary_affinity = affinity; | ||
| 701 | } | ||
| 702 | |||
| 680 | map->max_osd = max; | 703 | map->max_osd = max; |
| 704 | |||
| 681 | return 0; | 705 | return 0; |
| 682 | } | 706 | } |
| 683 | 707 | ||
| 708 | #define OSDMAP_WRAPPER_COMPAT_VER 7 | ||
| 709 | #define OSDMAP_CLIENT_DATA_COMPAT_VER 1 | ||
| 710 | |||
| 684 | /* | 711 | /* |
| 685 | * decode a full map. | 712 | * Return 0 or error. On success, *v is set to 0 for old (v6) osdmaps, |
| 713 | * to struct_v of the client_data section for new (v7 and above) | ||
| 714 | * osdmaps. | ||
| 686 | */ | 715 | */ |
| 687 | struct ceph_osdmap *osdmap_decode(void **p, void *end) | 716 | static int get_osdmap_client_data_v(void **p, void *end, |
| 717 | const char *prefix, u8 *v) | ||
| 688 | { | 718 | { |
| 689 | struct ceph_osdmap *map; | 719 | u8 struct_v; |
| 690 | u16 version; | 720 | |
| 691 | u32 len, max, i; | 721 | ceph_decode_8_safe(p, end, struct_v, e_inval); |
| 692 | int err = -EINVAL; | 722 | if (struct_v >= 7) { |
| 693 | void *start = *p; | 723 | u8 struct_compat; |
| 694 | struct ceph_pg_pool_info *pi; | 724 | |
| 725 | ceph_decode_8_safe(p, end, struct_compat, e_inval); | ||
| 726 | if (struct_compat > OSDMAP_WRAPPER_COMPAT_VER) { | ||
| 727 | pr_warning("got v %d cv %d > %d of %s ceph_osdmap\n", | ||
| 728 | struct_v, struct_compat, | ||
| 729 | OSDMAP_WRAPPER_COMPAT_VER, prefix); | ||
| 730 | return -EINVAL; | ||
| 731 | } | ||
| 732 | *p += 4; /* ignore wrapper struct_len */ | ||
| 733 | |||
| 734 | ceph_decode_8_safe(p, end, struct_v, e_inval); | ||
| 735 | ceph_decode_8_safe(p, end, struct_compat, e_inval); | ||
| 736 | if (struct_compat > OSDMAP_CLIENT_DATA_COMPAT_VER) { | ||
| 737 | pr_warning("got v %d cv %d > %d of %s ceph_osdmap client data\n", | ||
| 738 | struct_v, struct_compat, | ||
| 739 | OSDMAP_CLIENT_DATA_COMPAT_VER, prefix); | ||
| 740 | return -EINVAL; | ||
| 741 | } | ||
| 742 | *p += 4; /* ignore client data struct_len */ | ||
| 743 | } else { | ||
| 744 | u16 version; | ||
| 745 | |||
| 746 | *p -= 1; | ||
| 747 | ceph_decode_16_safe(p, end, version, e_inval); | ||
| 748 | if (version < 6) { | ||
| 749 | pr_warning("got v %d < 6 of %s ceph_osdmap\n", version, | ||
| 750 | prefix); | ||
| 751 | return -EINVAL; | ||
| 752 | } | ||
| 695 | 753 | ||
| 696 | dout("osdmap_decode %p to %p len %d\n", *p, end, (int)(end - *p)); | 754 | /* old osdmap enconding */ |
| 755 | struct_v = 0; | ||
| 756 | } | ||
| 697 | 757 | ||
| 698 | map = kzalloc(sizeof(*map), GFP_NOFS); | 758 | *v = struct_v; |
| 699 | if (map == NULL) | 759 | return 0; |
| 700 | return ERR_PTR(-ENOMEM); | ||
| 701 | map->pg_temp = RB_ROOT; | ||
| 702 | 760 | ||
| 703 | ceph_decode_16_safe(p, end, version, bad); | 761 | e_inval: |
| 704 | if (version > 6) { | 762 | return -EINVAL; |
| 705 | pr_warning("got unknown v %d > 6 of osdmap\n", version); | 763 | } |
| 706 | goto bad; | 764 | |
| 765 | static int __decode_pools(void **p, void *end, struct ceph_osdmap *map, | ||
| 766 | bool incremental) | ||
| 767 | { | ||
| 768 | u32 n; | ||
| 769 | |||
| 770 | ceph_decode_32_safe(p, end, n, e_inval); | ||
| 771 | while (n--) { | ||
| 772 | struct ceph_pg_pool_info *pi; | ||
| 773 | u64 pool; | ||
| 774 | int ret; | ||
| 775 | |||
| 776 | ceph_decode_64_safe(p, end, pool, e_inval); | ||
| 777 | |||
| 778 | pi = __lookup_pg_pool(&map->pg_pools, pool); | ||
| 779 | if (!incremental || !pi) { | ||
| 780 | pi = kzalloc(sizeof(*pi), GFP_NOFS); | ||
| 781 | if (!pi) | ||
| 782 | return -ENOMEM; | ||
| 783 | |||
| 784 | pi->id = pool; | ||
| 785 | |||
| 786 | ret = __insert_pg_pool(&map->pg_pools, pi); | ||
| 787 | if (ret) { | ||
| 788 | kfree(pi); | ||
| 789 | return ret; | ||
| 790 | } | ||
| 791 | } | ||
| 792 | |||
| 793 | ret = decode_pool(p, end, pi); | ||
| 794 | if (ret) | ||
| 795 | return ret; | ||
| 707 | } | 796 | } |
| 708 | if (version < 6) { | 797 | |
| 709 | pr_warning("got old v %d < 6 of osdmap\n", version); | 798 | return 0; |
| 710 | goto bad; | 799 | |
| 800 | e_inval: | ||
| 801 | return -EINVAL; | ||
| 802 | } | ||
| 803 | |||
| 804 | static int decode_pools(void **p, void *end, struct ceph_osdmap *map) | ||
| 805 | { | ||
| 806 | return __decode_pools(p, end, map, false); | ||
| 807 | } | ||
| 808 | |||
| 809 | static int decode_new_pools(void **p, void *end, struct ceph_osdmap *map) | ||
| 810 | { | ||
| 811 | return __decode_pools(p, end, map, true); | ||
| 812 | } | ||
| 813 | |||
| 814 | static int __decode_pg_temp(void **p, void *end, struct ceph_osdmap *map, | ||
| 815 | bool incremental) | ||
| 816 | { | ||
| 817 | u32 n; | ||
| 818 | |||
| 819 | ceph_decode_32_safe(p, end, n, e_inval); | ||
| 820 | while (n--) { | ||
| 821 | struct ceph_pg pgid; | ||
| 822 | u32 len, i; | ||
| 823 | int ret; | ||
| 824 | |||
| 825 | ret = ceph_decode_pgid(p, end, &pgid); | ||
| 826 | if (ret) | ||
| 827 | return ret; | ||
| 828 | |||
| 829 | ceph_decode_32_safe(p, end, len, e_inval); | ||
| 830 | |||
| 831 | ret = __remove_pg_mapping(&map->pg_temp, pgid); | ||
| 832 | BUG_ON(!incremental && ret != -ENOENT); | ||
| 833 | |||
| 834 | if (!incremental || len > 0) { | ||
| 835 | struct ceph_pg_mapping *pg; | ||
| 836 | |||
| 837 | ceph_decode_need(p, end, len*sizeof(u32), e_inval); | ||
| 838 | |||
| 839 | if (len > (UINT_MAX - sizeof(*pg)) / sizeof(u32)) | ||
| 840 | return -EINVAL; | ||
| 841 | |||
| 842 | pg = kzalloc(sizeof(*pg) + len*sizeof(u32), GFP_NOFS); | ||
| 843 | if (!pg) | ||
| 844 | return -ENOMEM; | ||
| 845 | |||
| 846 | pg->pgid = pgid; | ||
| 847 | pg->pg_temp.len = len; | ||
| 848 | for (i = 0; i < len; i++) | ||
| 849 | pg->pg_temp.osds[i] = ceph_decode_32(p); | ||
| 850 | |||
| 851 | ret = __insert_pg_mapping(pg, &map->pg_temp); | ||
| 852 | if (ret) { | ||
| 853 | kfree(pg); | ||
| 854 | return ret; | ||
| 855 | } | ||
| 856 | } | ||
| 711 | } | 857 | } |
| 712 | 858 | ||
| 713 | ceph_decode_need(p, end, 2*sizeof(u64)+6*sizeof(u32), bad); | 859 | return 0; |
| 860 | |||
| 861 | e_inval: | ||
| 862 | return -EINVAL; | ||
| 863 | } | ||
| 864 | |||
| 865 | static int decode_pg_temp(void **p, void *end, struct ceph_osdmap *map) | ||
| 866 | { | ||
| 867 | return __decode_pg_temp(p, end, map, false); | ||
| 868 | } | ||
| 869 | |||
| 870 | static int decode_new_pg_temp(void **p, void *end, struct ceph_osdmap *map) | ||
| 871 | { | ||
| 872 | return __decode_pg_temp(p, end, map, true); | ||
| 873 | } | ||
| 874 | |||
| 875 | static int __decode_primary_temp(void **p, void *end, struct ceph_osdmap *map, | ||
| 876 | bool incremental) | ||
| 877 | { | ||
| 878 | u32 n; | ||
| 879 | |||
| 880 | ceph_decode_32_safe(p, end, n, e_inval); | ||
| 881 | while (n--) { | ||
| 882 | struct ceph_pg pgid; | ||
| 883 | u32 osd; | ||
| 884 | int ret; | ||
| 885 | |||
| 886 | ret = ceph_decode_pgid(p, end, &pgid); | ||
| 887 | if (ret) | ||
| 888 | return ret; | ||
| 889 | |||
| 890 | ceph_decode_32_safe(p, end, osd, e_inval); | ||
| 891 | |||
| 892 | ret = __remove_pg_mapping(&map->primary_temp, pgid); | ||
| 893 | BUG_ON(!incremental && ret != -ENOENT); | ||
| 894 | |||
| 895 | if (!incremental || osd != (u32)-1) { | ||
| 896 | struct ceph_pg_mapping *pg; | ||
| 897 | |||
| 898 | pg = kzalloc(sizeof(*pg), GFP_NOFS); | ||
| 899 | if (!pg) | ||
| 900 | return -ENOMEM; | ||
| 901 | |||
| 902 | pg->pgid = pgid; | ||
| 903 | pg->primary_temp.osd = osd; | ||
| 904 | |||
| 905 | ret = __insert_pg_mapping(pg, &map->primary_temp); | ||
| 906 | if (ret) { | ||
| 907 | kfree(pg); | ||
| 908 | return ret; | ||
| 909 | } | ||
| 910 | } | ||
| 911 | } | ||
| 912 | |||
| 913 | return 0; | ||
| 914 | |||
| 915 | e_inval: | ||
| 916 | return -EINVAL; | ||
| 917 | } | ||
| 918 | |||
| 919 | static int decode_primary_temp(void **p, void *end, struct ceph_osdmap *map) | ||
| 920 | { | ||
| 921 | return __decode_primary_temp(p, end, map, false); | ||
| 922 | } | ||
| 923 | |||
| 924 | static int decode_new_primary_temp(void **p, void *end, | ||
| 925 | struct ceph_osdmap *map) | ||
| 926 | { | ||
| 927 | return __decode_primary_temp(p, end, map, true); | ||
| 928 | } | ||
| 929 | |||
| 930 | u32 ceph_get_primary_affinity(struct ceph_osdmap *map, int osd) | ||
| 931 | { | ||
| 932 | BUG_ON(osd >= map->max_osd); | ||
| 933 | |||
| 934 | if (!map->osd_primary_affinity) | ||
| 935 | return CEPH_OSD_DEFAULT_PRIMARY_AFFINITY; | ||
| 936 | |||
| 937 | return map->osd_primary_affinity[osd]; | ||
| 938 | } | ||
| 939 | |||
| 940 | static int set_primary_affinity(struct ceph_osdmap *map, int osd, u32 aff) | ||
| 941 | { | ||
| 942 | BUG_ON(osd >= map->max_osd); | ||
| 943 | |||
| 944 | if (!map->osd_primary_affinity) { | ||
| 945 | int i; | ||
| 946 | |||
| 947 | map->osd_primary_affinity = kmalloc(map->max_osd*sizeof(u32), | ||
| 948 | GFP_NOFS); | ||
| 949 | if (!map->osd_primary_affinity) | ||
| 950 | return -ENOMEM; | ||
| 951 | |||
| 952 | for (i = 0; i < map->max_osd; i++) | ||
| 953 | map->osd_primary_affinity[i] = | ||
| 954 | CEPH_OSD_DEFAULT_PRIMARY_AFFINITY; | ||
| 955 | } | ||
| 956 | |||
| 957 | map->osd_primary_affinity[osd] = aff; | ||
| 958 | |||
| 959 | return 0; | ||
| 960 | } | ||
| 961 | |||
| 962 | static int decode_primary_affinity(void **p, void *end, | ||
| 963 | struct ceph_osdmap *map) | ||
| 964 | { | ||
| 965 | u32 len, i; | ||
| 966 | |||
| 967 | ceph_decode_32_safe(p, end, len, e_inval); | ||
| 968 | if (len == 0) { | ||
| 969 | kfree(map->osd_primary_affinity); | ||
| 970 | map->osd_primary_affinity = NULL; | ||
| 971 | return 0; | ||
| 972 | } | ||
| 973 | if (len != map->max_osd) | ||
| 974 | goto e_inval; | ||
| 975 | |||
| 976 | ceph_decode_need(p, end, map->max_osd*sizeof(u32), e_inval); | ||
| 977 | |||
| 978 | for (i = 0; i < map->max_osd; i++) { | ||
| 979 | int ret; | ||
| 980 | |||
| 981 | ret = set_primary_affinity(map, i, ceph_decode_32(p)); | ||
| 982 | if (ret) | ||
| 983 | return ret; | ||
| 984 | } | ||
| 985 | |||
| 986 | return 0; | ||
| 987 | |||
| 988 | e_inval: | ||
| 989 | return -EINVAL; | ||
| 990 | } | ||
| 991 | |||
| 992 | static int decode_new_primary_affinity(void **p, void *end, | ||
| 993 | struct ceph_osdmap *map) | ||
| 994 | { | ||
| 995 | u32 n; | ||
| 996 | |||
| 997 | ceph_decode_32_safe(p, end, n, e_inval); | ||
| 998 | while (n--) { | ||
| 999 | u32 osd, aff; | ||
| 1000 | int ret; | ||
| 1001 | |||
| 1002 | ceph_decode_32_safe(p, end, osd, e_inval); | ||
| 1003 | ceph_decode_32_safe(p, end, aff, e_inval); | ||
| 1004 | |||
| 1005 | ret = set_primary_affinity(map, osd, aff); | ||
| 1006 | if (ret) | ||
| 1007 | return ret; | ||
| 1008 | |||
| 1009 | pr_info("osd%d primary-affinity 0x%x\n", osd, aff); | ||
| 1010 | } | ||
| 1011 | |||
| 1012 | return 0; | ||
| 1013 | |||
| 1014 | e_inval: | ||
| 1015 | return -EINVAL; | ||
| 1016 | } | ||
| 1017 | |||
| 1018 | /* | ||
| 1019 | * decode a full map. | ||
| 1020 | */ | ||
| 1021 | static int osdmap_decode(void **p, void *end, struct ceph_osdmap *map) | ||
| 1022 | { | ||
| 1023 | u8 struct_v; | ||
| 1024 | u32 epoch = 0; | ||
| 1025 | void *start = *p; | ||
| 1026 | u32 max; | ||
| 1027 | u32 len, i; | ||
| 1028 | int err; | ||
| 1029 | |||
| 1030 | dout("%s %p to %p len %d\n", __func__, *p, end, (int)(end - *p)); | ||
| 1031 | |||
| 1032 | err = get_osdmap_client_data_v(p, end, "full", &struct_v); | ||
| 1033 | if (err) | ||
| 1034 | goto bad; | ||
| 1035 | |||
| 1036 | /* fsid, epoch, created, modified */ | ||
| 1037 | ceph_decode_need(p, end, sizeof(map->fsid) + sizeof(u32) + | ||
| 1038 | sizeof(map->created) + sizeof(map->modified), e_inval); | ||
| 714 | ceph_decode_copy(p, &map->fsid, sizeof(map->fsid)); | 1039 | ceph_decode_copy(p, &map->fsid, sizeof(map->fsid)); |
| 715 | map->epoch = ceph_decode_32(p); | 1040 | epoch = map->epoch = ceph_decode_32(p); |
| 716 | ceph_decode_copy(p, &map->created, sizeof(map->created)); | 1041 | ceph_decode_copy(p, &map->created, sizeof(map->created)); |
| 717 | ceph_decode_copy(p, &map->modified, sizeof(map->modified)); | 1042 | ceph_decode_copy(p, &map->modified, sizeof(map->modified)); |
| 718 | 1043 | ||
| 719 | ceph_decode_32_safe(p, end, max, bad); | 1044 | /* pools */ |
| 720 | while (max--) { | 1045 | err = decode_pools(p, end, map); |
| 721 | ceph_decode_need(p, end, 8 + 2, bad); | 1046 | if (err) |
| 722 | err = -ENOMEM; | 1047 | goto bad; |
| 723 | pi = kzalloc(sizeof(*pi), GFP_NOFS); | ||
| 724 | if (!pi) | ||
| 725 | goto bad; | ||
| 726 | pi->id = ceph_decode_64(p); | ||
| 727 | err = __decode_pool(p, end, pi); | ||
| 728 | if (err < 0) { | ||
| 729 | kfree(pi); | ||
| 730 | goto bad; | ||
| 731 | } | ||
| 732 | __insert_pg_pool(&map->pg_pools, pi); | ||
| 733 | } | ||
| 734 | 1048 | ||
| 735 | err = __decode_pool_names(p, end, map); | 1049 | /* pool_name */ |
| 736 | if (err < 0) { | 1050 | err = decode_pool_names(p, end, map); |
| 737 | dout("fail to decode pool names"); | 1051 | if (err) |
| 738 | goto bad; | 1052 | goto bad; |
| 739 | } | ||
| 740 | 1053 | ||
| 741 | ceph_decode_32_safe(p, end, map->pool_max, bad); | 1054 | ceph_decode_32_safe(p, end, map->pool_max, e_inval); |
| 742 | 1055 | ||
| 743 | ceph_decode_32_safe(p, end, map->flags, bad); | 1056 | ceph_decode_32_safe(p, end, map->flags, e_inval); |
| 744 | 1057 | ||
| 745 | max = ceph_decode_32(p); | 1058 | /* max_osd */ |
| 1059 | ceph_decode_32_safe(p, end, max, e_inval); | ||
| 746 | 1060 | ||
| 747 | /* (re)alloc osd arrays */ | 1061 | /* (re)alloc osd arrays */ |
| 748 | err = osdmap_set_max_osd(map, max); | 1062 | err = osdmap_set_max_osd(map, max); |
| 749 | if (err < 0) | 1063 | if (err) |
| 750 | goto bad; | 1064 | goto bad; |
| 751 | dout("osdmap_decode max_osd = %d\n", map->max_osd); | ||
| 752 | 1065 | ||
| 753 | /* osds */ | 1066 | /* osd_state, osd_weight, osd_addrs->client_addr */ |
| 754 | err = -EINVAL; | ||
| 755 | ceph_decode_need(p, end, 3*sizeof(u32) + | 1067 | ceph_decode_need(p, end, 3*sizeof(u32) + |
| 756 | map->max_osd*(1 + sizeof(*map->osd_weight) + | 1068 | map->max_osd*(1 + sizeof(*map->osd_weight) + |
| 757 | sizeof(*map->osd_addr)), bad); | 1069 | sizeof(*map->osd_addr)), e_inval); |
| 758 | *p += 4; /* skip length field (should match max) */ | 1070 | |
| 1071 | if (ceph_decode_32(p) != map->max_osd) | ||
| 1072 | goto e_inval; | ||
| 1073 | |||
| 759 | ceph_decode_copy(p, map->osd_state, map->max_osd); | 1074 | ceph_decode_copy(p, map->osd_state, map->max_osd); |
| 760 | 1075 | ||
| 761 | *p += 4; /* skip length field (should match max) */ | 1076 | if (ceph_decode_32(p) != map->max_osd) |
| 1077 | goto e_inval; | ||
| 1078 | |||
| 762 | for (i = 0; i < map->max_osd; i++) | 1079 | for (i = 0; i < map->max_osd; i++) |
| 763 | map->osd_weight[i] = ceph_decode_32(p); | 1080 | map->osd_weight[i] = ceph_decode_32(p); |
| 764 | 1081 | ||
| 765 | *p += 4; /* skip length field (should match max) */ | 1082 | if (ceph_decode_32(p) != map->max_osd) |
| 1083 | goto e_inval; | ||
| 1084 | |||
| 766 | ceph_decode_copy(p, map->osd_addr, map->max_osd*sizeof(*map->osd_addr)); | 1085 | ceph_decode_copy(p, map->osd_addr, map->max_osd*sizeof(*map->osd_addr)); |
| 767 | for (i = 0; i < map->max_osd; i++) | 1086 | for (i = 0; i < map->max_osd; i++) |
| 768 | ceph_decode_addr(&map->osd_addr[i]); | 1087 | ceph_decode_addr(&map->osd_addr[i]); |
| 769 | 1088 | ||
| 770 | /* pg_temp */ | 1089 | /* pg_temp */ |
| 771 | ceph_decode_32_safe(p, end, len, bad); | 1090 | err = decode_pg_temp(p, end, map); |
| 772 | for (i = 0; i < len; i++) { | 1091 | if (err) |
| 773 | int n, j; | 1092 | goto bad; |
| 774 | struct ceph_pg pgid; | ||
| 775 | struct ceph_pg_mapping *pg; | ||
| 776 | 1093 | ||
| 777 | err = ceph_decode_pgid(p, end, &pgid); | 1094 | /* primary_temp */ |
| 1095 | if (struct_v >= 1) { | ||
| 1096 | err = decode_primary_temp(p, end, map); | ||
| 778 | if (err) | 1097 | if (err) |
| 779 | goto bad; | 1098 | goto bad; |
| 780 | ceph_decode_need(p, end, sizeof(u32), bad); | 1099 | } |
| 781 | n = ceph_decode_32(p); | ||
| 782 | err = -EINVAL; | ||
| 783 | if (n > (UINT_MAX - sizeof(*pg)) / sizeof(u32)) | ||
| 784 | goto bad; | ||
| 785 | ceph_decode_need(p, end, n * sizeof(u32), bad); | ||
| 786 | err = -ENOMEM; | ||
| 787 | pg = kmalloc(sizeof(*pg) + n*sizeof(u32), GFP_NOFS); | ||
| 788 | if (!pg) | ||
| 789 | goto bad; | ||
| 790 | pg->pgid = pgid; | ||
| 791 | pg->len = n; | ||
| 792 | for (j = 0; j < n; j++) | ||
| 793 | pg->osds[j] = ceph_decode_32(p); | ||
| 794 | 1100 | ||
| 795 | err = __insert_pg_mapping(pg, &map->pg_temp); | 1101 | /* primary_affinity */ |
| 1102 | if (struct_v >= 2) { | ||
| 1103 | err = decode_primary_affinity(p, end, map); | ||
| 796 | if (err) | 1104 | if (err) |
| 797 | goto bad; | 1105 | goto bad; |
| 798 | dout(" added pg_temp %lld.%x len %d\n", pgid.pool, pgid.seed, | 1106 | } else { |
| 799 | len); | 1107 | /* XXX can this happen? */ |
| 1108 | kfree(map->osd_primary_affinity); | ||
| 1109 | map->osd_primary_affinity = NULL; | ||
| 800 | } | 1110 | } |
| 801 | 1111 | ||
| 802 | /* crush */ | 1112 | /* crush */ |
| 803 | ceph_decode_32_safe(p, end, len, bad); | 1113 | ceph_decode_32_safe(p, end, len, e_inval); |
| 804 | dout("osdmap_decode crush len %d from off 0x%x\n", len, | 1114 | map->crush = crush_decode(*p, min(*p + len, end)); |
| 805 | (int)(*p - start)); | ||
| 806 | ceph_decode_need(p, end, len, bad); | ||
| 807 | map->crush = crush_decode(*p, end); | ||
| 808 | *p += len; | ||
| 809 | if (IS_ERR(map->crush)) { | 1115 | if (IS_ERR(map->crush)) { |
| 810 | err = PTR_ERR(map->crush); | 1116 | err = PTR_ERR(map->crush); |
| 811 | map->crush = NULL; | 1117 | map->crush = NULL; |
| 812 | goto bad; | 1118 | goto bad; |
| 813 | } | 1119 | } |
| 1120 | *p += len; | ||
| 814 | 1121 | ||
| 815 | /* ignore the rest of the map */ | 1122 | /* ignore the rest */ |
| 816 | *p = end; | 1123 | *p = end; |
| 817 | 1124 | ||
| 818 | dout("osdmap_decode done %p %p\n", *p, end); | 1125 | dout("full osdmap epoch %d max_osd %d\n", map->epoch, map->max_osd); |
| 819 | return map; | 1126 | return 0; |
| 820 | 1127 | ||
| 1128 | e_inval: | ||
| 1129 | err = -EINVAL; | ||
| 821 | bad: | 1130 | bad: |
| 822 | dout("osdmap_decode fail err %d\n", err); | 1131 | pr_err("corrupt full osdmap (%d) epoch %d off %d (%p of %p-%p)\n", |
| 823 | ceph_osdmap_destroy(map); | 1132 | err, epoch, (int)(*p - start), *p, start, end); |
| 824 | return ERR_PTR(err); | 1133 | print_hex_dump(KERN_DEBUG, "osdmap: ", |
| 1134 | DUMP_PREFIX_OFFSET, 16, 1, | ||
| 1135 | start, end - start, true); | ||
| 1136 | return err; | ||
| 1137 | } | ||
| 1138 | |||
| 1139 | /* | ||
| 1140 | * Allocate and decode a full map. | ||
| 1141 | */ | ||
| 1142 | struct ceph_osdmap *ceph_osdmap_decode(void **p, void *end) | ||
| 1143 | { | ||
| 1144 | struct ceph_osdmap *map; | ||
| 1145 | int ret; | ||
| 1146 | |||
| 1147 | map = kzalloc(sizeof(*map), GFP_NOFS); | ||
| 1148 | if (!map) | ||
| 1149 | return ERR_PTR(-ENOMEM); | ||
| 1150 | |||
| 1151 | map->pg_temp = RB_ROOT; | ||
| 1152 | map->primary_temp = RB_ROOT; | ||
| 1153 | mutex_init(&map->crush_scratch_mutex); | ||
| 1154 | |||
| 1155 | ret = osdmap_decode(p, end, map); | ||
| 1156 | if (ret) { | ||
| 1157 | ceph_osdmap_destroy(map); | ||
| 1158 | return ERR_PTR(ret); | ||
| 1159 | } | ||
| 1160 | |||
| 1161 | return map; | ||
| 825 | } | 1162 | } |
| 826 | 1163 | ||
| 827 | /* | 1164 | /* |
| @@ -840,17 +1177,18 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, | |||
| 840 | __s64 new_pool_max; | 1177 | __s64 new_pool_max; |
| 841 | __s32 new_flags, max; | 1178 | __s32 new_flags, max; |
| 842 | void *start = *p; | 1179 | void *start = *p; |
| 843 | int err = -EINVAL; | 1180 | int err; |
| 844 | u16 version; | 1181 | u8 struct_v; |
| 1182 | |||
| 1183 | dout("%s %p to %p len %d\n", __func__, *p, end, (int)(end - *p)); | ||
| 845 | 1184 | ||
| 846 | ceph_decode_16_safe(p, end, version, bad); | 1185 | err = get_osdmap_client_data_v(p, end, "inc", &struct_v); |
| 847 | if (version != 6) { | 1186 | if (err) |
| 848 | pr_warning("got unknown v %d != 6 of inc osdmap\n", version); | ||
| 849 | goto bad; | 1187 | goto bad; |
| 850 | } | ||
| 851 | 1188 | ||
| 852 | ceph_decode_need(p, end, sizeof(fsid)+sizeof(modified)+2*sizeof(u32), | 1189 | /* fsid, epoch, modified, new_pool_max, new_flags */ |
| 853 | bad); | 1190 | ceph_decode_need(p, end, sizeof(fsid) + sizeof(u32) + sizeof(modified) + |
| 1191 | sizeof(u64) + sizeof(u32), e_inval); | ||
| 854 | ceph_decode_copy(p, &fsid, sizeof(fsid)); | 1192 | ceph_decode_copy(p, &fsid, sizeof(fsid)); |
| 855 | epoch = ceph_decode_32(p); | 1193 | epoch = ceph_decode_32(p); |
| 856 | BUG_ON(epoch != map->epoch+1); | 1194 | BUG_ON(epoch != map->epoch+1); |
| @@ -859,21 +1197,22 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, | |||
| 859 | new_flags = ceph_decode_32(p); | 1197 | new_flags = ceph_decode_32(p); |
| 860 | 1198 | ||
| 861 | /* full map? */ | 1199 | /* full map? */ |
| 862 | ceph_decode_32_safe(p, end, len, bad); | 1200 | ceph_decode_32_safe(p, end, len, e_inval); |
| 863 | if (len > 0) { | 1201 | if (len > 0) { |
| 864 | dout("apply_incremental full map len %d, %p to %p\n", | 1202 | dout("apply_incremental full map len %d, %p to %p\n", |
| 865 | len, *p, end); | 1203 | len, *p, end); |
| 866 | return osdmap_decode(p, min(*p+len, end)); | 1204 | return ceph_osdmap_decode(p, min(*p+len, end)); |
| 867 | } | 1205 | } |
| 868 | 1206 | ||
| 869 | /* new crush? */ | 1207 | /* new crush? */ |
| 870 | ceph_decode_32_safe(p, end, len, bad); | 1208 | ceph_decode_32_safe(p, end, len, e_inval); |
| 871 | if (len > 0) { | 1209 | if (len > 0) { |
| 872 | dout("apply_incremental new crush map len %d, %p to %p\n", | ||
| 873 | len, *p, end); | ||
| 874 | newcrush = crush_decode(*p, min(*p+len, end)); | 1210 | newcrush = crush_decode(*p, min(*p+len, end)); |
| 875 | if (IS_ERR(newcrush)) | 1211 | if (IS_ERR(newcrush)) { |
| 876 | return ERR_CAST(newcrush); | 1212 | err = PTR_ERR(newcrush); |
| 1213 | newcrush = NULL; | ||
| 1214 | goto bad; | ||
| 1215 | } | ||
| 877 | *p += len; | 1216 | *p += len; |
| 878 | } | 1217 | } |
| 879 | 1218 | ||
| @@ -883,13 +1222,11 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, | |||
| 883 | if (new_pool_max >= 0) | 1222 | if (new_pool_max >= 0) |
| 884 | map->pool_max = new_pool_max; | 1223 | map->pool_max = new_pool_max; |
| 885 | 1224 | ||
| 886 | ceph_decode_need(p, end, 5*sizeof(u32), bad); | ||
| 887 | |||
| 888 | /* new max? */ | 1225 | /* new max? */ |
| 889 | max = ceph_decode_32(p); | 1226 | ceph_decode_32_safe(p, end, max, e_inval); |
| 890 | if (max >= 0) { | 1227 | if (max >= 0) { |
| 891 | err = osdmap_set_max_osd(map, max); | 1228 | err = osdmap_set_max_osd(map, max); |
| 892 | if (err < 0) | 1229 | if (err) |
| 893 | goto bad; | 1230 | goto bad; |
| 894 | } | 1231 | } |
| 895 | 1232 | ||
| @@ -902,51 +1239,34 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, | |||
| 902 | newcrush = NULL; | 1239 | newcrush = NULL; |
| 903 | } | 1240 | } |
| 904 | 1241 | ||
| 905 | /* new_pool */ | 1242 | /* new_pools */ |
| 906 | ceph_decode_32_safe(p, end, len, bad); | 1243 | err = decode_new_pools(p, end, map); |
| 907 | while (len--) { | 1244 | if (err) |
| 908 | struct ceph_pg_pool_info *pi; | 1245 | goto bad; |
| 909 | 1246 | ||
| 910 | ceph_decode_64_safe(p, end, pool, bad); | 1247 | /* new_pool_names */ |
| 911 | pi = __lookup_pg_pool(&map->pg_pools, pool); | 1248 | err = decode_pool_names(p, end, map); |
| 912 | if (!pi) { | 1249 | if (err) |
| 913 | pi = kzalloc(sizeof(*pi), GFP_NOFS); | 1250 | goto bad; |
| 914 | if (!pi) { | ||
| 915 | err = -ENOMEM; | ||
| 916 | goto bad; | ||
| 917 | } | ||
| 918 | pi->id = pool; | ||
| 919 | __insert_pg_pool(&map->pg_pools, pi); | ||
| 920 | } | ||
| 921 | err = __decode_pool(p, end, pi); | ||
| 922 | if (err < 0) | ||
| 923 | goto bad; | ||
| 924 | } | ||
| 925 | if (version >= 5) { | ||
| 926 | err = __decode_pool_names(p, end, map); | ||
| 927 | if (err < 0) | ||
| 928 | goto bad; | ||
| 929 | } | ||
| 930 | 1251 | ||
| 931 | /* old_pool */ | 1252 | /* old_pool */ |
| 932 | ceph_decode_32_safe(p, end, len, bad); | 1253 | ceph_decode_32_safe(p, end, len, e_inval); |
| 933 | while (len--) { | 1254 | while (len--) { |
| 934 | struct ceph_pg_pool_info *pi; | 1255 | struct ceph_pg_pool_info *pi; |
| 935 | 1256 | ||
| 936 | ceph_decode_64_safe(p, end, pool, bad); | 1257 | ceph_decode_64_safe(p, end, pool, e_inval); |
| 937 | pi = __lookup_pg_pool(&map->pg_pools, pool); | 1258 | pi = __lookup_pg_pool(&map->pg_pools, pool); |
| 938 | if (pi) | 1259 | if (pi) |
| 939 | __remove_pg_pool(&map->pg_pools, pi); | 1260 | __remove_pg_pool(&map->pg_pools, pi); |
| 940 | } | 1261 | } |
| 941 | 1262 | ||
| 942 | /* new_up */ | 1263 | /* new_up */ |
| 943 | err = -EINVAL; | 1264 | ceph_decode_32_safe(p, end, len, e_inval); |
| 944 | ceph_decode_32_safe(p, end, len, bad); | ||
| 945 | while (len--) { | 1265 | while (len--) { |
| 946 | u32 osd; | 1266 | u32 osd; |
| 947 | struct ceph_entity_addr addr; | 1267 | struct ceph_entity_addr addr; |
| 948 | ceph_decode_32_safe(p, end, osd, bad); | 1268 | ceph_decode_32_safe(p, end, osd, e_inval); |
| 949 | ceph_decode_copy_safe(p, end, &addr, sizeof(addr), bad); | 1269 | ceph_decode_copy_safe(p, end, &addr, sizeof(addr), e_inval); |
| 950 | ceph_decode_addr(&addr); | 1270 | ceph_decode_addr(&addr); |
| 951 | pr_info("osd%d up\n", osd); | 1271 | pr_info("osd%d up\n", osd); |
| 952 | BUG_ON(osd >= map->max_osd); | 1272 | BUG_ON(osd >= map->max_osd); |
| @@ -955,11 +1275,11 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, | |||
| 955 | } | 1275 | } |
| 956 | 1276 | ||
| 957 | /* new_state */ | 1277 | /* new_state */ |
| 958 | ceph_decode_32_safe(p, end, len, bad); | 1278 | ceph_decode_32_safe(p, end, len, e_inval); |
| 959 | while (len--) { | 1279 | while (len--) { |
| 960 | u32 osd; | 1280 | u32 osd; |
| 961 | u8 xorstate; | 1281 | u8 xorstate; |
| 962 | ceph_decode_32_safe(p, end, osd, bad); | 1282 | ceph_decode_32_safe(p, end, osd, e_inval); |
| 963 | xorstate = **(u8 **)p; | 1283 | xorstate = **(u8 **)p; |
| 964 | (*p)++; /* clean flag */ | 1284 | (*p)++; /* clean flag */ |
| 965 | if (xorstate == 0) | 1285 | if (xorstate == 0) |
| @@ -971,10 +1291,10 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, | |||
| 971 | } | 1291 | } |
| 972 | 1292 | ||
| 973 | /* new_weight */ | 1293 | /* new_weight */ |
| 974 | ceph_decode_32_safe(p, end, len, bad); | 1294 | ceph_decode_32_safe(p, end, len, e_inval); |
| 975 | while (len--) { | 1295 | while (len--) { |
| 976 | u32 osd, off; | 1296 | u32 osd, off; |
| 977 | ceph_decode_need(p, end, sizeof(u32)*2, bad); | 1297 | ceph_decode_need(p, end, sizeof(u32)*2, e_inval); |
| 978 | osd = ceph_decode_32(p); | 1298 | osd = ceph_decode_32(p); |
| 979 | off = ceph_decode_32(p); | 1299 | off = ceph_decode_32(p); |
| 980 | pr_info("osd%d weight 0x%x %s\n", osd, off, | 1300 | pr_info("osd%d weight 0x%x %s\n", osd, off, |
| @@ -985,56 +1305,35 @@ struct ceph_osdmap *osdmap_apply_incremental(void **p, void *end, | |||
| 985 | } | 1305 | } |
| 986 | 1306 | ||
| 987 | /* new_pg_temp */ | 1307 | /* new_pg_temp */ |
| 988 | ceph_decode_32_safe(p, end, len, bad); | 1308 | err = decode_new_pg_temp(p, end, map); |
| 989 | while (len--) { | 1309 | if (err) |
| 990 | struct ceph_pg_mapping *pg; | 1310 | goto bad; |
| 991 | int j; | ||
| 992 | struct ceph_pg pgid; | ||
| 993 | u32 pglen; | ||
| 994 | 1311 | ||
| 995 | err = ceph_decode_pgid(p, end, &pgid); | 1312 | /* new_primary_temp */ |
| 1313 | if (struct_v >= 1) { | ||
| 1314 | err = decode_new_primary_temp(p, end, map); | ||
| 996 | if (err) | 1315 | if (err) |
| 997 | goto bad; | 1316 | goto bad; |
| 998 | ceph_decode_need(p, end, sizeof(u32), bad); | 1317 | } |
| 999 | pglen = ceph_decode_32(p); | ||
| 1000 | if (pglen) { | ||
| 1001 | ceph_decode_need(p, end, pglen*sizeof(u32), bad); | ||
| 1002 | |||
| 1003 | /* removing existing (if any) */ | ||
| 1004 | (void) __remove_pg_mapping(&map->pg_temp, pgid); | ||
| 1005 | 1318 | ||
| 1006 | /* insert */ | 1319 | /* new_primary_affinity */ |
| 1007 | err = -EINVAL; | 1320 | if (struct_v >= 2) { |
| 1008 | if (pglen > (UINT_MAX - sizeof(*pg)) / sizeof(u32)) | 1321 | err = decode_new_primary_affinity(p, end, map); |
| 1009 | goto bad; | 1322 | if (err) |
| 1010 | err = -ENOMEM; | 1323 | goto bad; |
| 1011 | pg = kmalloc(sizeof(*pg) + sizeof(u32)*pglen, GFP_NOFS); | ||
| 1012 | if (!pg) | ||
| 1013 | goto bad; | ||
| 1014 | pg->pgid = pgid; | ||
| 1015 | pg->len = pglen; | ||
| 1016 | for (j = 0; j < pglen; j++) | ||
| 1017 | pg->osds[j] = ceph_decode_32(p); | ||
| 1018 | err = __insert_pg_mapping(pg, &map->pg_temp); | ||
| 1019 | if (err) { | ||
| 1020 | kfree(pg); | ||
| 1021 | goto bad; | ||
| 1022 | } | ||
| 1023 | dout(" added pg_temp %lld.%x len %d\n", pgid.pool, | ||
| 1024 | pgid.seed, pglen); | ||
| 1025 | } else { | ||
| 1026 | /* remove */ | ||
| 1027 | __remove_pg_mapping(&map->pg_temp, pgid); | ||
| 1028 | } | ||
| 1029 | } | 1324 | } |
| 1030 | 1325 | ||
| 1031 | /* ignore the rest */ | 1326 | /* ignore the rest */ |
| 1032 | *p = end; | 1327 | *p = end; |
| 1328 | |||
| 1329 | dout("inc osdmap epoch %d max_osd %d\n", map->epoch, map->max_osd); | ||
| 1033 | return map; | 1330 | return map; |
| 1034 | 1331 | ||
| 1332 | e_inval: | ||
| 1333 | err = -EINVAL; | ||
| 1035 | bad: | 1334 | bad: |
| 1036 | pr_err("corrupt inc osdmap epoch %d off %d (%p of %p-%p)\n", | 1335 | pr_err("corrupt inc osdmap (%d) epoch %d off %d (%p of %p-%p)\n", |
| 1037 | epoch, (int)(*p - start), *p, start, end); | 1336 | err, epoch, (int)(*p - start), *p, start, end); |
| 1038 | print_hex_dump(KERN_DEBUG, "osdmap: ", | 1337 | print_hex_dump(KERN_DEBUG, "osdmap: ", |
| 1039 | DUMP_PREFIX_OFFSET, 16, 1, | 1338 | DUMP_PREFIX_OFFSET, 16, 1, |
| 1040 | start, end - start, true); | 1339 | start, end - start, true); |
| @@ -1142,61 +1441,249 @@ int ceph_oloc_oid_to_pg(struct ceph_osdmap *osdmap, | |||
| 1142 | } | 1441 | } |
| 1143 | EXPORT_SYMBOL(ceph_oloc_oid_to_pg); | 1442 | EXPORT_SYMBOL(ceph_oloc_oid_to_pg); |
| 1144 | 1443 | ||
| 1145 | static int crush_do_rule_ary(const struct crush_map *map, int ruleno, int x, | 1444 | static int do_crush(struct ceph_osdmap *map, int ruleno, int x, |
| 1146 | int *result, int result_max, | 1445 | int *result, int result_max, |
| 1147 | const __u32 *weight, int weight_max) | 1446 | const __u32 *weight, int weight_max) |
| 1148 | { | 1447 | { |
| 1149 | int scratch[result_max * 3]; | 1448 | int r; |
| 1150 | 1449 | ||
| 1151 | return crush_do_rule(map, ruleno, x, result, result_max, | 1450 | BUG_ON(result_max > CEPH_PG_MAX_SIZE); |
| 1152 | weight, weight_max, scratch); | 1451 | |
| 1452 | mutex_lock(&map->crush_scratch_mutex); | ||
| 1453 | r = crush_do_rule(map->crush, ruleno, x, result, result_max, | ||
| 1454 | weight, weight_max, map->crush_scratch_ary); | ||
| 1455 | mutex_unlock(&map->crush_scratch_mutex); | ||
| 1456 | |||
| 1457 | return r; | ||
| 1153 | } | 1458 | } |
| 1154 | 1459 | ||
| 1155 | /* | 1460 | /* |
| 1156 | * Calculate raw osd vector for the given pgid. Return pointer to osd | 1461 | * Calculate raw (crush) set for given pgid. |
| 1157 | * array, or NULL on failure. | 1462 | * |
| 1463 | * Return raw set length, or error. | ||
| 1158 | */ | 1464 | */ |
| 1159 | static int *calc_pg_raw(struct ceph_osdmap *osdmap, struct ceph_pg pgid, | 1465 | static int pg_to_raw_osds(struct ceph_osdmap *osdmap, |
| 1160 | int *osds, int *num) | 1466 | struct ceph_pg_pool_info *pool, |
| 1467 | struct ceph_pg pgid, u32 pps, int *osds) | ||
| 1161 | { | 1468 | { |
| 1162 | struct ceph_pg_mapping *pg; | ||
| 1163 | struct ceph_pg_pool_info *pool; | ||
| 1164 | int ruleno; | 1469 | int ruleno; |
| 1165 | int r; | 1470 | int len; |
| 1166 | u32 pps; | ||
| 1167 | 1471 | ||
| 1168 | pool = __lookup_pg_pool(&osdmap->pg_pools, pgid.pool); | 1472 | /* crush */ |
| 1169 | if (!pool) | 1473 | ruleno = crush_find_rule(osdmap->crush, pool->crush_ruleset, |
| 1170 | return NULL; | 1474 | pool->type, pool->size); |
| 1475 | if (ruleno < 0) { | ||
| 1476 | pr_err("no crush rule: pool %lld ruleset %d type %d size %d\n", | ||
| 1477 | pgid.pool, pool->crush_ruleset, pool->type, | ||
| 1478 | pool->size); | ||
| 1479 | return -ENOENT; | ||
| 1480 | } | ||
| 1171 | 1481 | ||
| 1172 | /* pg_temp? */ | 1482 | len = do_crush(osdmap, ruleno, pps, osds, |
| 1483 | min_t(int, pool->size, CEPH_PG_MAX_SIZE), | ||
| 1484 | osdmap->osd_weight, osdmap->max_osd); | ||
| 1485 | if (len < 0) { | ||
| 1486 | pr_err("error %d from crush rule %d: pool %lld ruleset %d type %d size %d\n", | ||
| 1487 | len, ruleno, pgid.pool, pool->crush_ruleset, | ||
| 1488 | pool->type, pool->size); | ||
| 1489 | return len; | ||
| 1490 | } | ||
| 1491 | |||
| 1492 | return len; | ||
| 1493 | } | ||
| 1494 | |||
| 1495 | /* | ||
| 1496 | * Given raw set, calculate up set and up primary. | ||
| 1497 | * | ||
| 1498 | * Return up set length. *primary is set to up primary osd id, or -1 | ||
| 1499 | * if up set is empty. | ||
| 1500 | */ | ||
| 1501 | static int raw_to_up_osds(struct ceph_osdmap *osdmap, | ||
| 1502 | struct ceph_pg_pool_info *pool, | ||
| 1503 | int *osds, int len, int *primary) | ||
| 1504 | { | ||
| 1505 | int up_primary = -1; | ||
| 1506 | int i; | ||
| 1507 | |||
| 1508 | if (ceph_can_shift_osds(pool)) { | ||
| 1509 | int removed = 0; | ||
| 1510 | |||
| 1511 | for (i = 0; i < len; i++) { | ||
| 1512 | if (ceph_osd_is_down(osdmap, osds[i])) { | ||
| 1513 | removed++; | ||
| 1514 | continue; | ||
| 1515 | } | ||
| 1516 | if (removed) | ||
| 1517 | osds[i - removed] = osds[i]; | ||
| 1518 | } | ||
| 1519 | |||
| 1520 | len -= removed; | ||
| 1521 | if (len > 0) | ||
| 1522 | up_primary = osds[0]; | ||
| 1523 | } else { | ||
| 1524 | for (i = len - 1; i >= 0; i--) { | ||
| 1525 | if (ceph_osd_is_down(osdmap, osds[i])) | ||
| 1526 | osds[i] = CRUSH_ITEM_NONE; | ||
| 1527 | else | ||
| 1528 | up_primary = osds[i]; | ||
| 1529 | } | ||
| 1530 | } | ||
| 1531 | |||
| 1532 | *primary = up_primary; | ||
| 1533 | return len; | ||
| 1534 | } | ||
| 1535 | |||
| 1536 | static void apply_primary_affinity(struct ceph_osdmap *osdmap, u32 pps, | ||
| 1537 | struct ceph_pg_pool_info *pool, | ||
| 1538 | int *osds, int len, int *primary) | ||
| 1539 | { | ||
| 1540 | int i; | ||
| 1541 | int pos = -1; | ||
| 1542 | |||
| 1543 | /* | ||
| 1544 | * Do we have any non-default primary_affinity values for these | ||
| 1545 | * osds? | ||
| 1546 | */ | ||
| 1547 | if (!osdmap->osd_primary_affinity) | ||
| 1548 | return; | ||
| 1549 | |||
| 1550 | for (i = 0; i < len; i++) { | ||
| 1551 | if (osds[i] != CRUSH_ITEM_NONE && | ||
| 1552 | osdmap->osd_primary_affinity[i] != | ||
| 1553 | CEPH_OSD_DEFAULT_PRIMARY_AFFINITY) { | ||
| 1554 | break; | ||
| 1555 | } | ||
| 1556 | } | ||
| 1557 | if (i == len) | ||
| 1558 | return; | ||
| 1559 | |||
| 1560 | /* | ||
| 1561 | * Pick the primary. Feed both the seed (for the pg) and the | ||
| 1562 | * osd into the hash/rng so that a proportional fraction of an | ||
| 1563 | * osd's pgs get rejected as primary. | ||
| 1564 | */ | ||
| 1565 | for (i = 0; i < len; i++) { | ||
| 1566 | int osd; | ||
| 1567 | u32 aff; | ||
| 1568 | |||
| 1569 | osd = osds[i]; | ||
| 1570 | if (osd == CRUSH_ITEM_NONE) | ||
| 1571 | continue; | ||
| 1572 | |||
| 1573 | aff = osdmap->osd_primary_affinity[osd]; | ||
| 1574 | if (aff < CEPH_OSD_MAX_PRIMARY_AFFINITY && | ||
| 1575 | (crush_hash32_2(CRUSH_HASH_RJENKINS1, | ||
| 1576 | pps, osd) >> 16) >= aff) { | ||
| 1577 | /* | ||
| 1578 | * We chose not to use this primary. Note it | ||
| 1579 | * anyway as a fallback in case we don't pick | ||
| 1580 | * anyone else, but keep looking. | ||
| 1581 | */ | ||
| 1582 | if (pos < 0) | ||
| 1583 | pos = i; | ||
| 1584 | } else { | ||
| 1585 | pos = i; | ||
| 1586 | break; | ||
| 1587 | } | ||
| 1588 | } | ||
| 1589 | if (pos < 0) | ||
| 1590 | return; | ||
| 1591 | |||
| 1592 | *primary = osds[pos]; | ||
| 1593 | |||
| 1594 | if (ceph_can_shift_osds(pool) && pos > 0) { | ||
| 1595 | /* move the new primary to the front */ | ||
| 1596 | for (i = pos; i > 0; i--) | ||
| 1597 | osds[i] = osds[i - 1]; | ||
| 1598 | osds[0] = *primary; | ||
| 1599 | } | ||
| 1600 | } | ||
| 1601 | |||
| 1602 | /* | ||
| 1603 | * Given up set, apply pg_temp and primary_temp mappings. | ||
| 1604 | * | ||
| 1605 | * Return acting set length. *primary is set to acting primary osd id, | ||
| 1606 | * or -1 if acting set is empty. | ||
| 1607 | */ | ||
| 1608 | static int apply_temps(struct ceph_osdmap *osdmap, | ||
| 1609 | struct ceph_pg_pool_info *pool, struct ceph_pg pgid, | ||
| 1610 | int *osds, int len, int *primary) | ||
| 1611 | { | ||
| 1612 | struct ceph_pg_mapping *pg; | ||
| 1613 | int temp_len; | ||
| 1614 | int temp_primary; | ||
| 1615 | int i; | ||
| 1616 | |||
| 1617 | /* raw_pg -> pg */ | ||
| 1173 | pgid.seed = ceph_stable_mod(pgid.seed, pool->pg_num, | 1618 | pgid.seed = ceph_stable_mod(pgid.seed, pool->pg_num, |
| 1174 | pool->pg_num_mask); | 1619 | pool->pg_num_mask); |
| 1620 | |||
| 1621 | /* pg_temp? */ | ||
| 1175 | pg = __lookup_pg_mapping(&osdmap->pg_temp, pgid); | 1622 | pg = __lookup_pg_mapping(&osdmap->pg_temp, pgid); |
| 1176 | if (pg) { | 1623 | if (pg) { |
| 1177 | *num = pg->len; | 1624 | temp_len = 0; |
| 1178 | return pg->osds; | 1625 | temp_primary = -1; |
| 1626 | |||
| 1627 | for (i = 0; i < pg->pg_temp.len; i++) { | ||
| 1628 | if (ceph_osd_is_down(osdmap, pg->pg_temp.osds[i])) { | ||
| 1629 | if (ceph_can_shift_osds(pool)) | ||
| 1630 | continue; | ||
| 1631 | else | ||
| 1632 | osds[temp_len++] = CRUSH_ITEM_NONE; | ||
| 1633 | } else { | ||
| 1634 | osds[temp_len++] = pg->pg_temp.osds[i]; | ||
| 1635 | } | ||
| 1636 | } | ||
| 1637 | |||
| 1638 | /* apply pg_temp's primary */ | ||
| 1639 | for (i = 0; i < temp_len; i++) { | ||
| 1640 | if (osds[i] != CRUSH_ITEM_NONE) { | ||
| 1641 | temp_primary = osds[i]; | ||
| 1642 | break; | ||
| 1643 | } | ||
| 1644 | } | ||
| 1645 | } else { | ||
| 1646 | temp_len = len; | ||
| 1647 | temp_primary = *primary; | ||
| 1179 | } | 1648 | } |
| 1180 | 1649 | ||
| 1181 | /* crush */ | 1650 | /* primary_temp? */ |
| 1182 | ruleno = crush_find_rule(osdmap->crush, pool->crush_ruleset, | 1651 | pg = __lookup_pg_mapping(&osdmap->primary_temp, pgid); |
| 1183 | pool->type, pool->size); | 1652 | if (pg) |
| 1184 | if (ruleno < 0) { | 1653 | temp_primary = pg->primary_temp.osd; |
| 1185 | pr_err("no crush rule pool %lld ruleset %d type %d size %d\n", | 1654 | |
| 1186 | pgid.pool, pool->crush_ruleset, pool->type, | 1655 | *primary = temp_primary; |
| 1187 | pool->size); | 1656 | return temp_len; |
| 1188 | return NULL; | 1657 | } |
| 1658 | |||
| 1659 | /* | ||
| 1660 | * Calculate acting set for given pgid. | ||
| 1661 | * | ||
| 1662 | * Return acting set length, or error. *primary is set to acting | ||
| 1663 | * primary osd id, or -1 if acting set is empty or on error. | ||
| 1664 | */ | ||
| 1665 | int ceph_calc_pg_acting(struct ceph_osdmap *osdmap, struct ceph_pg pgid, | ||
| 1666 | int *osds, int *primary) | ||
| 1667 | { | ||
| 1668 | struct ceph_pg_pool_info *pool; | ||
| 1669 | u32 pps; | ||
| 1670 | int len; | ||
| 1671 | |||
| 1672 | pool = __lookup_pg_pool(&osdmap->pg_pools, pgid.pool); | ||
| 1673 | if (!pool) { | ||
| 1674 | *primary = -1; | ||
| 1675 | return -ENOENT; | ||
| 1189 | } | 1676 | } |
| 1190 | 1677 | ||
| 1191 | if (pool->flags & CEPH_POOL_FLAG_HASHPSPOOL) { | 1678 | if (pool->flags & CEPH_POOL_FLAG_HASHPSPOOL) { |
| 1192 | /* hash pool id and seed sothat pool PGs do not overlap */ | 1679 | /* hash pool id and seed so that pool PGs do not overlap */ |
| 1193 | pps = crush_hash32_2(CRUSH_HASH_RJENKINS1, | 1680 | pps = crush_hash32_2(CRUSH_HASH_RJENKINS1, |
| 1194 | ceph_stable_mod(pgid.seed, pool->pgp_num, | 1681 | ceph_stable_mod(pgid.seed, pool->pgp_num, |
| 1195 | pool->pgp_num_mask), | 1682 | pool->pgp_num_mask), |
| 1196 | pgid.pool); | 1683 | pgid.pool); |
| 1197 | } else { | 1684 | } else { |
| 1198 | /* | 1685 | /* |
| 1199 | * legacy ehavior: add ps and pool together. this is | 1686 | * legacy behavior: add ps and pool together. this is |
| 1200 | * not a great approach because the PGs from each pool | 1687 | * not a great approach because the PGs from each pool |
| 1201 | * will overlap on top of each other: 0.5 == 1.4 == | 1688 | * will overlap on top of each other: 0.5 == 1.4 == |
| 1202 | * 2.3 == ... | 1689 | * 2.3 == ... |
| @@ -1205,38 +1692,20 @@ static int *calc_pg_raw(struct ceph_osdmap *osdmap, struct ceph_pg pgid, | |||
| 1205 | pool->pgp_num_mask) + | 1692 | pool->pgp_num_mask) + |
| 1206 | (unsigned)pgid.pool; | 1693 | (unsigned)pgid.pool; |
| 1207 | } | 1694 | } |
| 1208 | r = crush_do_rule_ary(osdmap->crush, ruleno, pps, | 1695 | |
| 1209 | osds, min_t(int, pool->size, *num), | 1696 | len = pg_to_raw_osds(osdmap, pool, pgid, pps, osds); |
| 1210 | osdmap->osd_weight, osdmap->max_osd); | 1697 | if (len < 0) { |
| 1211 | if (r < 0) { | 1698 | *primary = -1; |
| 1212 | pr_err("error %d from crush rule: pool %lld ruleset %d type %d" | 1699 | return len; |
| 1213 | " size %d\n", r, pgid.pool, pool->crush_ruleset, | ||
| 1214 | pool->type, pool->size); | ||
| 1215 | return NULL; | ||
| 1216 | } | 1700 | } |
| 1217 | *num = r; | ||
| 1218 | return osds; | ||
| 1219 | } | ||
| 1220 | 1701 | ||
| 1221 | /* | 1702 | len = raw_to_up_osds(osdmap, pool, osds, len, primary); |
| 1222 | * Return acting set for given pgid. | ||
| 1223 | */ | ||
| 1224 | int ceph_calc_pg_acting(struct ceph_osdmap *osdmap, struct ceph_pg pgid, | ||
| 1225 | int *acting) | ||
| 1226 | { | ||
| 1227 | int rawosds[CEPH_PG_MAX_SIZE], *osds; | ||
| 1228 | int i, o, num = CEPH_PG_MAX_SIZE; | ||
| 1229 | 1703 | ||
| 1230 | osds = calc_pg_raw(osdmap, pgid, rawosds, &num); | 1704 | apply_primary_affinity(osdmap, pps, pool, osds, len, primary); |
| 1231 | if (!osds) | ||
| 1232 | return -1; | ||
| 1233 | 1705 | ||
| 1234 | /* primary is first up osd */ | 1706 | len = apply_temps(osdmap, pool, pgid, osds, len, primary); |
| 1235 | o = 0; | 1707 | |
| 1236 | for (i = 0; i < num; i++) | 1708 | return len; |
| 1237 | if (ceph_osd_is_up(osdmap, osds[i])) | ||
| 1238 | acting[o++] = osds[i]; | ||
| 1239 | return o; | ||
| 1240 | } | 1709 | } |
| 1241 | 1710 | ||
| 1242 | /* | 1711 | /* |
| @@ -1244,17 +1713,11 @@ int ceph_calc_pg_acting(struct ceph_osdmap *osdmap, struct ceph_pg pgid, | |||
| 1244 | */ | 1713 | */ |
| 1245 | int ceph_calc_pg_primary(struct ceph_osdmap *osdmap, struct ceph_pg pgid) | 1714 | int ceph_calc_pg_primary(struct ceph_osdmap *osdmap, struct ceph_pg pgid) |
| 1246 | { | 1715 | { |
| 1247 | int rawosds[CEPH_PG_MAX_SIZE], *osds; | 1716 | int osds[CEPH_PG_MAX_SIZE]; |
| 1248 | int i, num = CEPH_PG_MAX_SIZE; | 1717 | int primary; |
| 1249 | 1718 | ||
| 1250 | osds = calc_pg_raw(osdmap, pgid, rawosds, &num); | 1719 | ceph_calc_pg_acting(osdmap, pgid, osds, &primary); |
| 1251 | if (!osds) | ||
| 1252 | return -1; | ||
| 1253 | 1720 | ||
| 1254 | /* primary is first up osd */ | 1721 | return primary; |
| 1255 | for (i = 0; i < num; i++) | ||
| 1256 | if (ceph_osd_is_up(osdmap, osds[i])) | ||
| 1257 | return osds[i]; | ||
| 1258 | return -1; | ||
| 1259 | } | 1722 | } |
| 1260 | EXPORT_SYMBOL(ceph_calc_pg_primary); | 1723 | EXPORT_SYMBOL(ceph_calc_pg_primary); |
diff --git a/net/core/Makefile b/net/core/Makefile index 9628c20acff6..826b925aa453 100644 --- a/net/core/Makefile +++ b/net/core/Makefile | |||
| @@ -21,5 +21,6 @@ obj-$(CONFIG_FIB_RULES) += fib_rules.o | |||
| 21 | obj-$(CONFIG_TRACEPOINTS) += net-traces.o | 21 | obj-$(CONFIG_TRACEPOINTS) += net-traces.o |
| 22 | obj-$(CONFIG_NET_DROP_MONITOR) += drop_monitor.o | 22 | obj-$(CONFIG_NET_DROP_MONITOR) += drop_monitor.o |
| 23 | obj-$(CONFIG_NETWORK_PHY_TIMESTAMPING) += timestamping.o | 23 | obj-$(CONFIG_NETWORK_PHY_TIMESTAMPING) += timestamping.o |
| 24 | obj-$(CONFIG_NET_PTP_CLASSIFY) += ptp_classifier.o | ||
| 24 | obj-$(CONFIG_CGROUP_NET_PRIO) += netprio_cgroup.o | 25 | obj-$(CONFIG_CGROUP_NET_PRIO) += netprio_cgroup.o |
| 25 | obj-$(CONFIG_CGROUP_NET_CLASSID) += netclassid_cgroup.o | 26 | obj-$(CONFIG_CGROUP_NET_CLASSID) += netclassid_cgroup.o |
diff --git a/net/core/dev.c b/net/core/dev.c index 4a91591b30a6..5b3042e69f85 100644 --- a/net/core/dev.c +++ b/net/core/dev.c | |||
| @@ -1245,7 +1245,7 @@ static int __dev_open(struct net_device *dev) | |||
| 1245 | * If we don't do this there is a chance ndo_poll_controller | 1245 | * If we don't do this there is a chance ndo_poll_controller |
| 1246 | * or ndo_poll may be running while we open the device | 1246 | * or ndo_poll may be running while we open the device |
| 1247 | */ | 1247 | */ |
| 1248 | netpoll_rx_disable(dev); | 1248 | netpoll_poll_disable(dev); |
| 1249 | 1249 | ||
| 1250 | ret = call_netdevice_notifiers(NETDEV_PRE_UP, dev); | 1250 | ret = call_netdevice_notifiers(NETDEV_PRE_UP, dev); |
| 1251 | ret = notifier_to_errno(ret); | 1251 | ret = notifier_to_errno(ret); |
| @@ -1260,7 +1260,7 @@ static int __dev_open(struct net_device *dev) | |||
| 1260 | if (!ret && ops->ndo_open) | 1260 | if (!ret && ops->ndo_open) |
| 1261 | ret = ops->ndo_open(dev); | 1261 | ret = ops->ndo_open(dev); |
| 1262 | 1262 | ||
| 1263 | netpoll_rx_enable(dev); | 1263 | netpoll_poll_enable(dev); |
| 1264 | 1264 | ||
| 1265 | if (ret) | 1265 | if (ret) |
| 1266 | clear_bit(__LINK_STATE_START, &dev->state); | 1266 | clear_bit(__LINK_STATE_START, &dev->state); |
| @@ -1313,6 +1313,9 @@ static int __dev_close_many(struct list_head *head) | |||
| 1313 | might_sleep(); | 1313 | might_sleep(); |
| 1314 | 1314 | ||
| 1315 | list_for_each_entry(dev, head, close_list) { | 1315 | list_for_each_entry(dev, head, close_list) { |
| 1316 | /* Temporarily disable netpoll until the interface is down */ | ||
| 1317 | netpoll_poll_disable(dev); | ||
| 1318 | |||
| 1316 | call_netdevice_notifiers(NETDEV_GOING_DOWN, dev); | 1319 | call_netdevice_notifiers(NETDEV_GOING_DOWN, dev); |
| 1317 | 1320 | ||
| 1318 | clear_bit(__LINK_STATE_START, &dev->state); | 1321 | clear_bit(__LINK_STATE_START, &dev->state); |
| @@ -1343,6 +1346,7 @@ static int __dev_close_many(struct list_head *head) | |||
| 1343 | 1346 | ||
| 1344 | dev->flags &= ~IFF_UP; | 1347 | dev->flags &= ~IFF_UP; |
| 1345 | net_dmaengine_put(); | 1348 | net_dmaengine_put(); |
| 1349 | netpoll_poll_enable(dev); | ||
| 1346 | } | 1350 | } |
| 1347 | 1351 | ||
| 1348 | return 0; | 1352 | return 0; |
| @@ -1353,14 +1357,10 @@ static int __dev_close(struct net_device *dev) | |||
| 1353 | int retval; | 1357 | int retval; |
| 1354 | LIST_HEAD(single); | 1358 | LIST_HEAD(single); |
| 1355 | 1359 | ||
| 1356 | /* Temporarily disable netpoll until the interface is down */ | ||
| 1357 | netpoll_rx_disable(dev); | ||
| 1358 | |||
| 1359 | list_add(&dev->close_list, &single); | 1360 | list_add(&dev->close_list, &single); |
| 1360 | retval = __dev_close_many(&single); | 1361 | retval = __dev_close_many(&single); |
| 1361 | list_del(&single); | 1362 | list_del(&single); |
| 1362 | 1363 | ||
| 1363 | netpoll_rx_enable(dev); | ||
| 1364 | return retval; | 1364 | return retval; |
| 1365 | } | 1365 | } |
| 1366 | 1366 | ||
| @@ -1398,14 +1398,9 @@ int dev_close(struct net_device *dev) | |||
| 1398 | if (dev->flags & IFF_UP) { | 1398 | if (dev->flags & IFF_UP) { |
| 1399 | LIST_HEAD(single); | 1399 | LIST_HEAD(single); |
| 1400 | 1400 | ||
| 1401 | /* Block netpoll rx while the interface is going down */ | ||
| 1402 | netpoll_rx_disable(dev); | ||
| 1403 | |||
| 1404 | list_add(&dev->close_list, &single); | 1401 | list_add(&dev->close_list, &single); |
| 1405 | dev_close_many(&single); | 1402 | dev_close_many(&single); |
| 1406 | list_del(&single); | 1403 | list_del(&single); |
| 1407 | |||
| 1408 | netpoll_rx_enable(dev); | ||
| 1409 | } | 1404 | } |
| 1410 | return 0; | 1405 | return 0; |
| 1411 | } | 1406 | } |
| @@ -1645,8 +1640,7 @@ static inline void net_timestamp_set(struct sk_buff *skb) | |||
| 1645 | __net_timestamp(SKB); \ | 1640 | __net_timestamp(SKB); \ |
| 1646 | } \ | 1641 | } \ |
| 1647 | 1642 | ||
| 1648 | static inline bool is_skb_forwardable(struct net_device *dev, | 1643 | bool is_skb_forwardable(struct net_device *dev, struct sk_buff *skb) |
| 1649 | struct sk_buff *skb) | ||
| 1650 | { | 1644 | { |
| 1651 | unsigned int len; | 1645 | unsigned int len; |
| 1652 | 1646 | ||
| @@ -1665,6 +1659,7 @@ static inline bool is_skb_forwardable(struct net_device *dev, | |||
| 1665 | 1659 | ||
| 1666 | return false; | 1660 | return false; |
| 1667 | } | 1661 | } |
| 1662 | EXPORT_SYMBOL_GPL(is_skb_forwardable); | ||
| 1668 | 1663 | ||
| 1669 | /** | 1664 | /** |
| 1670 | * dev_forward_skb - loopback an skb to another netif | 1665 | * dev_forward_skb - loopback an skb to another netif |
| @@ -2289,7 +2284,7 @@ EXPORT_SYMBOL(skb_checksum_help); | |||
| 2289 | __be16 skb_network_protocol(struct sk_buff *skb, int *depth) | 2284 | __be16 skb_network_protocol(struct sk_buff *skb, int *depth) |
| 2290 | { | 2285 | { |
| 2291 | __be16 type = skb->protocol; | 2286 | __be16 type = skb->protocol; |
| 2292 | int vlan_depth = ETH_HLEN; | 2287 | int vlan_depth = skb->mac_len; |
| 2293 | 2288 | ||
| 2294 | /* Tunnel gso handlers can set protocol to ethernet. */ | 2289 | /* Tunnel gso handlers can set protocol to ethernet. */ |
| 2295 | if (type == htons(ETH_P_TEB)) { | 2290 | if (type == htons(ETH_P_TEB)) { |
| @@ -2885,6 +2880,7 @@ recursion_alert: | |||
| 2885 | rc = -ENETDOWN; | 2880 | rc = -ENETDOWN; |
| 2886 | rcu_read_unlock_bh(); | 2881 | rcu_read_unlock_bh(); |
| 2887 | 2882 | ||
| 2883 | atomic_long_inc(&dev->tx_dropped); | ||
| 2888 | kfree_skb(skb); | 2884 | kfree_skb(skb); |
| 2889 | return rc; | 2885 | return rc; |
| 2890 | out: | 2886 | out: |
| @@ -2957,7 +2953,7 @@ set_rps_cpu(struct net_device *dev, struct sk_buff *skb, | |||
| 2957 | flow_table = rcu_dereference(rxqueue->rps_flow_table); | 2953 | flow_table = rcu_dereference(rxqueue->rps_flow_table); |
| 2958 | if (!flow_table) | 2954 | if (!flow_table) |
| 2959 | goto out; | 2955 | goto out; |
| 2960 | flow_id = skb->rxhash & flow_table->mask; | 2956 | flow_id = skb_get_hash(skb) & flow_table->mask; |
| 2961 | rc = dev->netdev_ops->ndo_rx_flow_steer(dev, skb, | 2957 | rc = dev->netdev_ops->ndo_rx_flow_steer(dev, skb, |
| 2962 | rxq_index, flow_id); | 2958 | rxq_index, flow_id); |
| 2963 | if (rc < 0) | 2959 | if (rc < 0) |
| @@ -2991,6 +2987,7 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb, | |||
| 2991 | struct rps_sock_flow_table *sock_flow_table; | 2987 | struct rps_sock_flow_table *sock_flow_table; |
| 2992 | int cpu = -1; | 2988 | int cpu = -1; |
| 2993 | u16 tcpu; | 2989 | u16 tcpu; |
| 2990 | u32 hash; | ||
| 2994 | 2991 | ||
| 2995 | if (skb_rx_queue_recorded(skb)) { | 2992 | if (skb_rx_queue_recorded(skb)) { |
| 2996 | u16 index = skb_get_rx_queue(skb); | 2993 | u16 index = skb_get_rx_queue(skb); |
| @@ -3019,7 +3016,8 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb, | |||
| 3019 | } | 3016 | } |
| 3020 | 3017 | ||
| 3021 | skb_reset_network_header(skb); | 3018 | skb_reset_network_header(skb); |
| 3022 | if (!skb_get_hash(skb)) | 3019 | hash = skb_get_hash(skb); |
| 3020 | if (!hash) | ||
| 3023 | goto done; | 3021 | goto done; |
| 3024 | 3022 | ||
| 3025 | flow_table = rcu_dereference(rxqueue->rps_flow_table); | 3023 | flow_table = rcu_dereference(rxqueue->rps_flow_table); |
| @@ -3028,11 +3026,10 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb, | |||
| 3028 | u16 next_cpu; | 3026 | u16 next_cpu; |
| 3029 | struct rps_dev_flow *rflow; | 3027 | struct rps_dev_flow *rflow; |
| 3030 | 3028 | ||
| 3031 | rflow = &flow_table->flows[skb->rxhash & flow_table->mask]; | 3029 | rflow = &flow_table->flows[hash & flow_table->mask]; |
| 3032 | tcpu = rflow->cpu; | 3030 | tcpu = rflow->cpu; |
| 3033 | 3031 | ||
| 3034 | next_cpu = sock_flow_table->ents[skb->rxhash & | 3032 | next_cpu = sock_flow_table->ents[hash & sock_flow_table->mask]; |
| 3035 | sock_flow_table->mask]; | ||
| 3036 | 3033 | ||
| 3037 | /* | 3034 | /* |
| 3038 | * If the desired CPU (where last recvmsg was done) is | 3035 | * If the desired CPU (where last recvmsg was done) is |
| @@ -3061,7 +3058,7 @@ static int get_rps_cpu(struct net_device *dev, struct sk_buff *skb, | |||
| 3061 | } | 3058 | } |
| 3062 | 3059 | ||
| 3063 | if (map) { | 3060 | if (map) { |
| 3064 | tcpu = map->cpus[((u64) skb->rxhash * map->len) >> 32]; | 3061 | tcpu = map->cpus[((u64) hash * map->len) >> 32]; |
| 3065 | 3062 | ||
| 3066 | if (cpu_online(tcpu)) { | 3063 | if (cpu_online(tcpu)) { |
| 3067 | cpu = tcpu; | 3064 | cpu = tcpu; |
| @@ -3236,10 +3233,6 @@ static int netif_rx_internal(struct sk_buff *skb) | |||
| 3236 | { | 3233 | { |
| 3237 | int ret; | 3234 | int ret; |
| 3238 | 3235 | ||
| 3239 | /* if netpoll wants it, pretend we never saw it */ | ||
| 3240 | if (netpoll_rx(skb)) | ||
| 3241 | return NET_RX_DROP; | ||
| 3242 | |||
| 3243 | net_timestamp_check(netdev_tstamp_prequeue, skb); | 3236 | net_timestamp_check(netdev_tstamp_prequeue, skb); |
| 3244 | 3237 | ||
| 3245 | trace_netif_rx(skb); | 3238 | trace_netif_rx(skb); |
| @@ -3500,11 +3493,11 @@ EXPORT_SYMBOL_GPL(netdev_rx_handler_unregister); | |||
| 3500 | static bool skb_pfmemalloc_protocol(struct sk_buff *skb) | 3493 | static bool skb_pfmemalloc_protocol(struct sk_buff *skb) |
| 3501 | { | 3494 | { |
| 3502 | switch (skb->protocol) { | 3495 | switch (skb->protocol) { |
| 3503 | case __constant_htons(ETH_P_ARP): | 3496 | case htons(ETH_P_ARP): |
| 3504 | case __constant_htons(ETH_P_IP): | 3497 | case htons(ETH_P_IP): |
| 3505 | case __constant_htons(ETH_P_IPV6): | 3498 | case htons(ETH_P_IPV6): |
| 3506 | case __constant_htons(ETH_P_8021Q): | 3499 | case htons(ETH_P_8021Q): |
| 3507 | case __constant_htons(ETH_P_8021AD): | 3500 | case htons(ETH_P_8021AD): |
| 3508 | return true; | 3501 | return true; |
| 3509 | default: | 3502 | default: |
| 3510 | return false; | 3503 | return false; |
| @@ -3525,10 +3518,6 @@ static int __netif_receive_skb_core(struct sk_buff *skb, bool pfmemalloc) | |||
| 3525 | 3518 | ||
| 3526 | trace_netif_receive_skb(skb); | 3519 | trace_netif_receive_skb(skb); |
| 3527 | 3520 | ||
| 3528 | /* if we've gotten here through NAPI, check netpoll */ | ||
| 3529 | if (netpoll_receive_skb(skb)) | ||
| 3530 | goto out; | ||
| 3531 | |||
| 3532 | orig_dev = skb->dev; | 3521 | orig_dev = skb->dev; |
| 3533 | 3522 | ||
| 3534 | skb_reset_network_header(skb); | 3523 | skb_reset_network_header(skb); |
| @@ -3655,7 +3644,6 @@ drop: | |||
| 3655 | 3644 | ||
| 3656 | unlock: | 3645 | unlock: |
| 3657 | rcu_read_unlock(); | 3646 | rcu_read_unlock(); |
| 3658 | out: | ||
| 3659 | return ret; | 3647 | return ret; |
| 3660 | } | 3648 | } |
| 3661 | 3649 | ||
| @@ -3845,10 +3833,10 @@ static void gro_list_prepare(struct napi_struct *napi, struct sk_buff *skb) | |||
| 3845 | diffs |= p->vlan_tci ^ skb->vlan_tci; | 3833 | diffs |= p->vlan_tci ^ skb->vlan_tci; |
| 3846 | if (maclen == ETH_HLEN) | 3834 | if (maclen == ETH_HLEN) |
| 3847 | diffs |= compare_ether_header(skb_mac_header(p), | 3835 | diffs |= compare_ether_header(skb_mac_header(p), |
| 3848 | skb_gro_mac_header(skb)); | 3836 | skb_mac_header(skb)); |
| 3849 | else if (!diffs) | 3837 | else if (!diffs) |
| 3850 | diffs = memcmp(skb_mac_header(p), | 3838 | diffs = memcmp(skb_mac_header(p), |
| 3851 | skb_gro_mac_header(skb), | 3839 | skb_mac_header(skb), |
| 3852 | maclen); | 3840 | maclen); |
| 3853 | NAPI_GRO_CB(p)->same_flow = !diffs; | 3841 | NAPI_GRO_CB(p)->same_flow = !diffs; |
| 3854 | } | 3842 | } |
| @@ -3871,6 +3859,27 @@ static void skb_gro_reset_offset(struct sk_buff *skb) | |||
| 3871 | } | 3859 | } |
| 3872 | } | 3860 | } |
| 3873 | 3861 | ||
| 3862 | static void gro_pull_from_frag0(struct sk_buff *skb, int grow) | ||
| 3863 | { | ||
| 3864 | struct skb_shared_info *pinfo = skb_shinfo(skb); | ||
| 3865 | |||
| 3866 | BUG_ON(skb->end - skb->tail < grow); | ||
| 3867 | |||
| 3868 | memcpy(skb_tail_pointer(skb), NAPI_GRO_CB(skb)->frag0, grow); | ||
| 3869 | |||
| 3870 | skb->data_len -= grow; | ||
| 3871 | skb->tail += grow; | ||
| 3872 | |||
| 3873 | pinfo->frags[0].page_offset += grow; | ||
| 3874 | skb_frag_size_sub(&pinfo->frags[0], grow); | ||
| 3875 | |||
| 3876 | if (unlikely(!skb_frag_size(&pinfo->frags[0]))) { | ||
| 3877 | skb_frag_unref(skb, 0); | ||
| 3878 | memmove(pinfo->frags, pinfo->frags + 1, | ||
| 3879 | --pinfo->nr_frags * sizeof(pinfo->frags[0])); | ||
| 3880 | } | ||
| 3881 | } | ||
| 3882 | |||
| 3874 | static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) | 3883 | static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff *skb) |
| 3875 | { | 3884 | { |
| 3876 | struct sk_buff **pp = NULL; | 3885 | struct sk_buff **pp = NULL; |
| @@ -3879,14 +3888,14 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff | |||
| 3879 | struct list_head *head = &offload_base; | 3888 | struct list_head *head = &offload_base; |
| 3880 | int same_flow; | 3889 | int same_flow; |
| 3881 | enum gro_result ret; | 3890 | enum gro_result ret; |
| 3891 | int grow; | ||
| 3882 | 3892 | ||
| 3883 | if (!(skb->dev->features & NETIF_F_GRO) || netpoll_rx_on(skb)) | 3893 | if (!(skb->dev->features & NETIF_F_GRO)) |
| 3884 | goto normal; | 3894 | goto normal; |
| 3885 | 3895 | ||
| 3886 | if (skb_is_gso(skb) || skb_has_frag_list(skb)) | 3896 | if (skb_is_gso(skb) || skb_has_frag_list(skb)) |
| 3887 | goto normal; | 3897 | goto normal; |
| 3888 | 3898 | ||
| 3889 | skb_gro_reset_offset(skb); | ||
| 3890 | gro_list_prepare(napi, skb); | 3899 | gro_list_prepare(napi, skb); |
| 3891 | NAPI_GRO_CB(skb)->csum = skb->csum; /* Needed for CHECKSUM_COMPLETE */ | 3900 | NAPI_GRO_CB(skb)->csum = skb->csum; /* Needed for CHECKSUM_COMPLETE */ |
| 3892 | 3901 | ||
| @@ -3950,27 +3959,9 @@ static enum gro_result dev_gro_receive(struct napi_struct *napi, struct sk_buff | |||
| 3950 | ret = GRO_HELD; | 3959 | ret = GRO_HELD; |
| 3951 | 3960 | ||
| 3952 | pull: | 3961 | pull: |
| 3953 | if (skb_headlen(skb) < skb_gro_offset(skb)) { | 3962 | grow = skb_gro_offset(skb) - skb_headlen(skb); |
| 3954 | int grow = skb_gro_offset(skb) - skb_headlen(skb); | 3963 | if (grow > 0) |
| 3955 | 3964 | gro_pull_from_frag0(skb, grow); | |
| 3956 | BUG_ON(skb->end - skb->tail < grow); | ||
| 3957 | |||
| 3958 | memcpy(skb_tail_pointer(skb), NAPI_GRO_CB(skb)->frag0, grow); | ||
| 3959 | |||
| 3960 | skb->tail += grow; | ||
| 3961 | skb->data_len -= grow; | ||
| 3962 | |||
| 3963 | skb_shinfo(skb)->frags[0].page_offset += grow; | ||
| 3964 | skb_frag_size_sub(&skb_shinfo(skb)->frags[0], grow); | ||
| 3965 | |||
| 3966 | if (unlikely(!skb_frag_size(&skb_shinfo(skb)->frags[0]))) { | ||
| 3967 | skb_frag_unref(skb, 0); | ||
| 3968 | memmove(skb_shinfo(skb)->frags, | ||
| 3969 | skb_shinfo(skb)->frags + 1, | ||
| 3970 | --skb_shinfo(skb)->nr_frags * sizeof(skb_frag_t)); | ||
| 3971 | } | ||
| 3972 | } | ||
| 3973 | |||
| 3974 | ok: | 3965 | ok: |
| 3975 | return ret; | 3966 | return ret; |
| 3976 | 3967 | ||
| @@ -4038,6 +4029,8 @@ gro_result_t napi_gro_receive(struct napi_struct *napi, struct sk_buff *skb) | |||
| 4038 | { | 4029 | { |
| 4039 | trace_napi_gro_receive_entry(skb); | 4030 | trace_napi_gro_receive_entry(skb); |
| 4040 | 4031 | ||
| 4032 | skb_gro_reset_offset(skb); | ||
| 4033 | |||
| 4041 | return napi_skb_finish(dev_gro_receive(napi, skb), skb); | 4034 | return napi_skb_finish(dev_gro_receive(napi, skb), skb); |
| 4042 | } | 4035 | } |
| 4043 | EXPORT_SYMBOL(napi_gro_receive); | 4036 | EXPORT_SYMBOL(napi_gro_receive); |
| @@ -4050,6 +4043,7 @@ static void napi_reuse_skb(struct napi_struct *napi, struct sk_buff *skb) | |||
| 4050 | skb->vlan_tci = 0; | 4043 | skb->vlan_tci = 0; |
| 4051 | skb->dev = napi->dev; | 4044 | skb->dev = napi->dev; |
| 4052 | skb->skb_iif = 0; | 4045 | skb->skb_iif = 0; |
| 4046 | skb->truesize = SKB_TRUESIZE(skb_end_offset(skb)); | ||
| 4053 | 4047 | ||
| 4054 | napi->skb = skb; | 4048 | napi->skb = skb; |
| 4055 | } | 4049 | } |
| @@ -4066,12 +4060,16 @@ struct sk_buff *napi_get_frags(struct napi_struct *napi) | |||
| 4066 | } | 4060 | } |
| 4067 | EXPORT_SYMBOL(napi_get_frags); | 4061 | EXPORT_SYMBOL(napi_get_frags); |
| 4068 | 4062 | ||
| 4069 | static gro_result_t napi_frags_finish(struct napi_struct *napi, struct sk_buff *skb, | 4063 | static gro_result_t napi_frags_finish(struct napi_struct *napi, |
| 4070 | gro_result_t ret) | 4064 | struct sk_buff *skb, |
| 4065 | gro_result_t ret) | ||
| 4071 | { | 4066 | { |
| 4072 | switch (ret) { | 4067 | switch (ret) { |
| 4073 | case GRO_NORMAL: | 4068 | case GRO_NORMAL: |
| 4074 | if (netif_receive_skb_internal(skb)) | 4069 | case GRO_HELD: |
| 4070 | __skb_push(skb, ETH_HLEN); | ||
| 4071 | skb->protocol = eth_type_trans(skb, skb->dev); | ||
| 4072 | if (ret == GRO_NORMAL && netif_receive_skb_internal(skb)) | ||
| 4075 | ret = GRO_DROP; | 4073 | ret = GRO_DROP; |
| 4076 | break; | 4074 | break; |
| 4077 | 4075 | ||
| @@ -4080,7 +4078,6 @@ static gro_result_t napi_frags_finish(struct napi_struct *napi, struct sk_buff * | |||
| 4080 | napi_reuse_skb(napi, skb); | 4078 | napi_reuse_skb(napi, skb); |
| 4081 | break; | 4079 | break; |
| 4082 | 4080 | ||
| 4083 | case GRO_HELD: | ||
| 4084 | case GRO_MERGED: | 4081 | case GRO_MERGED: |
| 4085 | break; | 4082 | break; |
| 4086 | } | 4083 | } |
| @@ -4088,17 +4085,41 @@ static gro_result_t napi_frags_finish(struct napi_struct *napi, struct sk_buff * | |||
| 4088 | return ret; | 4085 | return ret; |
| 4089 | } | 4086 | } |
| 4090 | 4087 | ||
| 4088 | /* Upper GRO stack assumes network header starts at gro_offset=0 | ||
| 4089 | * Drivers could call both napi_gro_frags() and napi_gro_receive() | ||
| 4090 | * We copy ethernet header into skb->data to have a common layout. | ||
| 4091 | */ | ||
| 4091 | static struct sk_buff *napi_frags_skb(struct napi_struct *napi) | 4092 | static struct sk_buff *napi_frags_skb(struct napi_struct *napi) |
| 4092 | { | 4093 | { |
| 4093 | struct sk_buff *skb = napi->skb; | 4094 | struct sk_buff *skb = napi->skb; |
| 4095 | const struct ethhdr *eth; | ||
| 4096 | unsigned int hlen = sizeof(*eth); | ||
| 4094 | 4097 | ||
| 4095 | napi->skb = NULL; | 4098 | napi->skb = NULL; |
| 4096 | 4099 | ||
| 4097 | if (unlikely(!pskb_may_pull(skb, sizeof(struct ethhdr)))) { | 4100 | skb_reset_mac_header(skb); |
| 4098 | napi_reuse_skb(napi, skb); | 4101 | skb_gro_reset_offset(skb); |
| 4099 | return NULL; | 4102 | |
| 4103 | eth = skb_gro_header_fast(skb, 0); | ||
| 4104 | if (unlikely(skb_gro_header_hard(skb, hlen))) { | ||
| 4105 | eth = skb_gro_header_slow(skb, hlen, 0); | ||
| 4106 | if (unlikely(!eth)) { | ||
| 4107 | napi_reuse_skb(napi, skb); | ||
| 4108 | return NULL; | ||
| 4109 | } | ||
| 4110 | } else { | ||
| 4111 | gro_pull_from_frag0(skb, hlen); | ||
| 4112 | NAPI_GRO_CB(skb)->frag0 += hlen; | ||
| 4113 | NAPI_GRO_CB(skb)->frag0_len -= hlen; | ||
| 4100 | } | 4114 | } |
| 4101 | skb->protocol = eth_type_trans(skb, skb->dev); | 4115 | __skb_pull(skb, hlen); |
| 4116 | |||
| 4117 | /* | ||
| 4118 | * This works because the only protocols we care about don't require | ||
| 4119 | * special handling. | ||
| 4120 | * We'll fix it up properly in napi_frags_finish() | ||
| 4121 | */ | ||
| 4122 | skb->protocol = eth->h_proto; | ||
| 4102 | 4123 | ||
| 4103 | return skb; | 4124 | return skb; |
| 4104 | } | 4125 | } |
| @@ -4568,8 +4589,7 @@ void *netdev_lower_get_next_private(struct net_device *dev, | |||
| 4568 | if (&lower->list == &dev->adj_list.lower) | 4589 | if (&lower->list == &dev->adj_list.lower) |
| 4569 | return NULL; | 4590 | return NULL; |
| 4570 | 4591 | ||
| 4571 | if (iter) | 4592 | *iter = lower->list.next; |
| 4572 | *iter = lower->list.next; | ||
| 4573 | 4593 | ||
| 4574 | return lower->private; | 4594 | return lower->private; |
| 4575 | } | 4595 | } |
| @@ -4597,8 +4617,7 @@ void *netdev_lower_get_next_private_rcu(struct net_device *dev, | |||
| 4597 | if (&lower->list == &dev->adj_list.lower) | 4617 | if (&lower->list == &dev->adj_list.lower) |
| 4598 | return NULL; | 4618 | return NULL; |
| 4599 | 4619 | ||
| 4600 | if (iter) | 4620 | *iter = &lower->list; |
| 4601 | *iter = &lower->list; | ||
| 4602 | 4621 | ||
| 4603 | return lower->private; | 4622 | return lower->private; |
| 4604 | } | 4623 | } |
| @@ -5676,6 +5695,13 @@ static netdev_features_t netdev_fix_features(struct net_device *dev, | |||
| 5676 | } | 5695 | } |
| 5677 | } | 5696 | } |
| 5678 | 5697 | ||
| 5698 | #ifdef CONFIG_NET_RX_BUSY_POLL | ||
| 5699 | if (dev->netdev_ops->ndo_busy_poll) | ||
| 5700 | features |= NETIF_F_BUSY_POLL; | ||
| 5701 | else | ||
| 5702 | #endif | ||
| 5703 | features &= ~NETIF_F_BUSY_POLL; | ||
| 5704 | |||
| 5679 | return features; | 5705 | return features; |
| 5680 | } | 5706 | } |
| 5681 | 5707 | ||
| @@ -6251,6 +6277,7 @@ struct rtnl_link_stats64 *dev_get_stats(struct net_device *dev, | |||
| 6251 | netdev_stats_to_stats64(storage, &dev->stats); | 6277 | netdev_stats_to_stats64(storage, &dev->stats); |
| 6252 | } | 6278 | } |
| 6253 | storage->rx_dropped += atomic_long_read(&dev->rx_dropped); | 6279 | storage->rx_dropped += atomic_long_read(&dev->rx_dropped); |
| 6280 | storage->tx_dropped += atomic_long_read(&dev->tx_dropped); | ||
| 6254 | return storage; | 6281 | return storage; |
| 6255 | } | 6282 | } |
| 6256 | EXPORT_SYMBOL(dev_get_stats); | 6283 | EXPORT_SYMBOL(dev_get_stats); |
diff --git a/net/core/dst.c b/net/core/dst.c index ca4231ec7347..80d6286c8b62 100644 --- a/net/core/dst.c +++ b/net/core/dst.c | |||
| @@ -142,12 +142,12 @@ loop: | |||
| 142 | mutex_unlock(&dst_gc_mutex); | 142 | mutex_unlock(&dst_gc_mutex); |
| 143 | } | 143 | } |
| 144 | 144 | ||
| 145 | int dst_discard(struct sk_buff *skb) | 145 | int dst_discard_sk(struct sock *sk, struct sk_buff *skb) |
| 146 | { | 146 | { |
| 147 | kfree_skb(skb); | 147 | kfree_skb(skb); |
| 148 | return 0; | 148 | return 0; |
| 149 | } | 149 | } |
| 150 | EXPORT_SYMBOL(dst_discard); | 150 | EXPORT_SYMBOL(dst_discard_sk); |
| 151 | 151 | ||
| 152 | const u32 dst_default_metrics[RTAX_MAX + 1] = { | 152 | const u32 dst_default_metrics[RTAX_MAX + 1] = { |
| 153 | /* This initializer is needed to force linker to place this variable | 153 | /* This initializer is needed to force linker to place this variable |
| @@ -184,7 +184,7 @@ void *dst_alloc(struct dst_ops *ops, struct net_device *dev, | |||
| 184 | dst->xfrm = NULL; | 184 | dst->xfrm = NULL; |
| 185 | #endif | 185 | #endif |
| 186 | dst->input = dst_discard; | 186 | dst->input = dst_discard; |
| 187 | dst->output = dst_discard; | 187 | dst->output = dst_discard_sk; |
| 188 | dst->error = 0; | 188 | dst->error = 0; |
| 189 | dst->obsolete = initial_obsolete; | 189 | dst->obsolete = initial_obsolete; |
| 190 | dst->header_len = 0; | 190 | dst->header_len = 0; |
| @@ -209,8 +209,10 @@ static void ___dst_free(struct dst_entry *dst) | |||
| 209 | /* The first case (dev==NULL) is required, when | 209 | /* The first case (dev==NULL) is required, when |
| 210 | protocol module is unloaded. | 210 | protocol module is unloaded. |
| 211 | */ | 211 | */ |
| 212 | if (dst->dev == NULL || !(dst->dev->flags&IFF_UP)) | 212 | if (dst->dev == NULL || !(dst->dev->flags&IFF_UP)) { |
| 213 | dst->input = dst->output = dst_discard; | 213 | dst->input = dst_discard; |
| 214 | dst->output = dst_discard_sk; | ||
| 215 | } | ||
| 214 | dst->obsolete = DST_OBSOLETE_DEAD; | 216 | dst->obsolete = DST_OBSOLETE_DEAD; |
| 215 | } | 217 | } |
| 216 | 218 | ||
| @@ -361,7 +363,8 @@ static void dst_ifdown(struct dst_entry *dst, struct net_device *dev, | |||
| 361 | return; | 363 | return; |
| 362 | 364 | ||
| 363 | if (!unregister) { | 365 | if (!unregister) { |
| 364 | dst->input = dst->output = dst_discard; | 366 | dst->input = dst_discard; |
| 367 | dst->output = dst_discard_sk; | ||
| 365 | } else { | 368 | } else { |
| 366 | dst->dev = dev_net(dst->dev)->loopback_dev; | 369 | dst->dev = dev_net(dst->dev)->loopback_dev; |
| 367 | dev_hold(dst->dev); | 370 | dev_hold(dst->dev); |
diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 30071dec287a..640ba0e5831c 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c | |||
| @@ -97,6 +97,7 @@ static const char netdev_features_strings[NETDEV_FEATURE_COUNT][ETH_GSTRING_LEN] | |||
| 97 | [NETIF_F_RXFCS_BIT] = "rx-fcs", | 97 | [NETIF_F_RXFCS_BIT] = "rx-fcs", |
| 98 | [NETIF_F_RXALL_BIT] = "rx-all", | 98 | [NETIF_F_RXALL_BIT] = "rx-all", |
| 99 | [NETIF_F_HW_L2FW_DOFFLOAD_BIT] = "l2-fwd-offload", | 99 | [NETIF_F_HW_L2FW_DOFFLOAD_BIT] = "l2-fwd-offload", |
| 100 | [NETIF_F_BUSY_POLL_BIT] = "busy-poll", | ||
| 100 | }; | 101 | }; |
| 101 | 102 | ||
| 102 | static int ethtool_get_features(struct net_device *dev, void __user *useraddr) | 103 | static int ethtool_get_features(struct net_device *dev, void __user *useraddr) |
diff --git a/net/core/filter.c b/net/core/filter.c index ad30d626a5bd..cd58614660cf 100644 --- a/net/core/filter.c +++ b/net/core/filter.c | |||
| @@ -1,11 +1,16 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Linux Socket Filter - Kernel level socket filtering | 2 | * Linux Socket Filter - Kernel level socket filtering |
| 3 | * | 3 | * |
| 4 | * Author: | 4 | * Based on the design of the Berkeley Packet Filter. The new |
| 5 | * Jay Schulist <jschlst@samba.org> | 5 | * internal format has been designed by PLUMgrid: |
| 6 | * | 6 | * |
| 7 | * Based on the design of: | 7 | * Copyright (c) 2011 - 2014 PLUMgrid, http://plumgrid.com |
| 8 | * - The Berkeley Packet Filter | 8 | * |
| 9 | * Authors: | ||
| 10 | * | ||
| 11 | * Jay Schulist <jschlst@samba.org> | ||
| 12 | * Alexei Starovoitov <ast@plumgrid.com> | ||
| 13 | * Daniel Borkmann <dborkman@redhat.com> | ||
| 9 | * | 14 | * |
| 10 | * This program is free software; you can redistribute it and/or | 15 | * This program is free software; you can redistribute it and/or |
| 11 | * modify it under the terms of the GNU General Public License | 16 | * modify it under the terms of the GNU General Public License |
| @@ -108,304 +113,1051 @@ int sk_filter(struct sock *sk, struct sk_buff *skb) | |||
| 108 | } | 113 | } |
| 109 | EXPORT_SYMBOL(sk_filter); | 114 | EXPORT_SYMBOL(sk_filter); |
| 110 | 115 | ||
| 116 | /* Base function for offset calculation. Needs to go into .text section, | ||
| 117 | * therefore keeping it non-static as well; will also be used by JITs | ||
| 118 | * anyway later on, so do not let the compiler omit it. | ||
| 119 | */ | ||
| 120 | noinline u64 __bpf_call_base(u64 r1, u64 r2, u64 r3, u64 r4, u64 r5) | ||
| 121 | { | ||
| 122 | return 0; | ||
| 123 | } | ||
| 124 | |||
| 111 | /** | 125 | /** |
| 112 | * sk_run_filter - run a filter on a socket | 126 | * __sk_run_filter - run a filter on a given context |
| 113 | * @skb: buffer to run the filter on | 127 | * @ctx: buffer to run the filter on |
| 114 | * @fentry: filter to apply | 128 | * @insn: filter to apply |
| 115 | * | 129 | * |
| 116 | * Decode and apply filter instructions to the skb->data. | 130 | * Decode and apply filter instructions to the skb->data. Return length to |
| 117 | * Return length to keep, 0 for none. @skb is the data we are | 131 | * keep, 0 for none. @ctx is the data we are operating on, @insn is the |
| 118 | * filtering, @filter is the array of filter instructions. | 132 | * array of filter instructions. |
| 119 | * Because all jumps are guaranteed to be before last instruction, | ||
| 120 | * and last instruction guaranteed to be a RET, we dont need to check | ||
| 121 | * flen. (We used to pass to this function the length of filter) | ||
| 122 | */ | 133 | */ |
| 123 | unsigned int sk_run_filter(const struct sk_buff *skb, | 134 | unsigned int __sk_run_filter(void *ctx, const struct sock_filter_int *insn) |
| 124 | const struct sock_filter *fentry) | ||
| 125 | { | 135 | { |
| 136 | u64 stack[MAX_BPF_STACK / sizeof(u64)]; | ||
| 137 | u64 regs[MAX_BPF_REG], tmp; | ||
| 126 | void *ptr; | 138 | void *ptr; |
| 127 | u32 A = 0; /* Accumulator */ | 139 | int off; |
| 128 | u32 X = 0; /* Index Register */ | ||
| 129 | u32 mem[BPF_MEMWORDS]; /* Scratch Memory Store */ | ||
| 130 | u32 tmp; | ||
| 131 | int k; | ||
| 132 | 140 | ||
| 133 | /* | 141 | #define K insn->imm |
| 134 | * Process array of filter instructions. | 142 | #define A regs[insn->a_reg] |
| 135 | */ | 143 | #define X regs[insn->x_reg] |
| 136 | for (;; fentry++) { | 144 | #define R0 regs[0] |
| 137 | #if defined(CONFIG_X86_32) | 145 | |
| 138 | #define K (fentry->k) | 146 | #define CONT ({insn++; goto select_insn; }) |
| 139 | #else | 147 | #define CONT_JMP ({insn++; goto select_insn; }) |
| 140 | const u32 K = fentry->k; | 148 | |
| 141 | #endif | 149 | static const void *jumptable[256] = { |
| 142 | 150 | [0 ... 255] = &&default_label, | |
| 143 | switch (fentry->code) { | 151 | /* Now overwrite non-defaults ... */ |
| 144 | case BPF_S_ALU_ADD_X: | 152 | #define DL(A, B, C) [A|B|C] = &&A##_##B##_##C |
| 145 | A += X; | 153 | DL(BPF_ALU, BPF_ADD, BPF_X), |
| 146 | continue; | 154 | DL(BPF_ALU, BPF_ADD, BPF_K), |
| 147 | case BPF_S_ALU_ADD_K: | 155 | DL(BPF_ALU, BPF_SUB, BPF_X), |
| 148 | A += K; | 156 | DL(BPF_ALU, BPF_SUB, BPF_K), |
| 149 | continue; | 157 | DL(BPF_ALU, BPF_AND, BPF_X), |
| 150 | case BPF_S_ALU_SUB_X: | 158 | DL(BPF_ALU, BPF_AND, BPF_K), |
| 151 | A -= X; | 159 | DL(BPF_ALU, BPF_OR, BPF_X), |
| 152 | continue; | 160 | DL(BPF_ALU, BPF_OR, BPF_K), |
| 153 | case BPF_S_ALU_SUB_K: | 161 | DL(BPF_ALU, BPF_LSH, BPF_X), |
| 154 | A -= K; | 162 | DL(BPF_ALU, BPF_LSH, BPF_K), |
| 155 | continue; | 163 | DL(BPF_ALU, BPF_RSH, BPF_X), |
| 156 | case BPF_S_ALU_MUL_X: | 164 | DL(BPF_ALU, BPF_RSH, BPF_K), |
| 157 | A *= X; | 165 | DL(BPF_ALU, BPF_XOR, BPF_X), |
| 158 | continue; | 166 | DL(BPF_ALU, BPF_XOR, BPF_K), |
| 159 | case BPF_S_ALU_MUL_K: | 167 | DL(BPF_ALU, BPF_MUL, BPF_X), |
| 160 | A *= K; | 168 | DL(BPF_ALU, BPF_MUL, BPF_K), |
| 161 | continue; | 169 | DL(BPF_ALU, BPF_MOV, BPF_X), |
| 162 | case BPF_S_ALU_DIV_X: | 170 | DL(BPF_ALU, BPF_MOV, BPF_K), |
| 163 | if (X == 0) | 171 | DL(BPF_ALU, BPF_DIV, BPF_X), |
| 164 | return 0; | 172 | DL(BPF_ALU, BPF_DIV, BPF_K), |
| 165 | A /= X; | 173 | DL(BPF_ALU, BPF_MOD, BPF_X), |
| 166 | continue; | 174 | DL(BPF_ALU, BPF_MOD, BPF_K), |
| 167 | case BPF_S_ALU_DIV_K: | 175 | DL(BPF_ALU, BPF_NEG, 0), |
| 168 | A /= K; | 176 | DL(BPF_ALU, BPF_END, BPF_TO_BE), |
| 169 | continue; | 177 | DL(BPF_ALU, BPF_END, BPF_TO_LE), |
| 170 | case BPF_S_ALU_MOD_X: | 178 | DL(BPF_ALU64, BPF_ADD, BPF_X), |
| 171 | if (X == 0) | 179 | DL(BPF_ALU64, BPF_ADD, BPF_K), |
| 172 | return 0; | 180 | DL(BPF_ALU64, BPF_SUB, BPF_X), |
| 173 | A %= X; | 181 | DL(BPF_ALU64, BPF_SUB, BPF_K), |
| 174 | continue; | 182 | DL(BPF_ALU64, BPF_AND, BPF_X), |
| 175 | case BPF_S_ALU_MOD_K: | 183 | DL(BPF_ALU64, BPF_AND, BPF_K), |
| 176 | A %= K; | 184 | DL(BPF_ALU64, BPF_OR, BPF_X), |
| 177 | continue; | 185 | DL(BPF_ALU64, BPF_OR, BPF_K), |
| 178 | case BPF_S_ALU_AND_X: | 186 | DL(BPF_ALU64, BPF_LSH, BPF_X), |
| 179 | A &= X; | 187 | DL(BPF_ALU64, BPF_LSH, BPF_K), |
| 180 | continue; | 188 | DL(BPF_ALU64, BPF_RSH, BPF_X), |
| 181 | case BPF_S_ALU_AND_K: | 189 | DL(BPF_ALU64, BPF_RSH, BPF_K), |
| 182 | A &= K; | 190 | DL(BPF_ALU64, BPF_XOR, BPF_X), |
| 183 | continue; | 191 | DL(BPF_ALU64, BPF_XOR, BPF_K), |
| 184 | case BPF_S_ALU_OR_X: | 192 | DL(BPF_ALU64, BPF_MUL, BPF_X), |
| 185 | A |= X; | 193 | DL(BPF_ALU64, BPF_MUL, BPF_K), |
| 186 | continue; | 194 | DL(BPF_ALU64, BPF_MOV, BPF_X), |
| 187 | case BPF_S_ALU_OR_K: | 195 | DL(BPF_ALU64, BPF_MOV, BPF_K), |
| 188 | A |= K; | 196 | DL(BPF_ALU64, BPF_ARSH, BPF_X), |
| 189 | continue; | 197 | DL(BPF_ALU64, BPF_ARSH, BPF_K), |
| 190 | case BPF_S_ANC_ALU_XOR_X: | 198 | DL(BPF_ALU64, BPF_DIV, BPF_X), |
| 191 | case BPF_S_ALU_XOR_X: | 199 | DL(BPF_ALU64, BPF_DIV, BPF_K), |
| 192 | A ^= X; | 200 | DL(BPF_ALU64, BPF_MOD, BPF_X), |
| 193 | continue; | 201 | DL(BPF_ALU64, BPF_MOD, BPF_K), |
| 194 | case BPF_S_ALU_XOR_K: | 202 | DL(BPF_ALU64, BPF_NEG, 0), |
| 195 | A ^= K; | 203 | DL(BPF_JMP, BPF_CALL, 0), |
| 196 | continue; | 204 | DL(BPF_JMP, BPF_JA, 0), |
| 197 | case BPF_S_ALU_LSH_X: | 205 | DL(BPF_JMP, BPF_JEQ, BPF_X), |
| 198 | A <<= X; | 206 | DL(BPF_JMP, BPF_JEQ, BPF_K), |
| 199 | continue; | 207 | DL(BPF_JMP, BPF_JNE, BPF_X), |
| 200 | case BPF_S_ALU_LSH_K: | 208 | DL(BPF_JMP, BPF_JNE, BPF_K), |
| 201 | A <<= K; | 209 | DL(BPF_JMP, BPF_JGT, BPF_X), |
| 202 | continue; | 210 | DL(BPF_JMP, BPF_JGT, BPF_K), |
| 203 | case BPF_S_ALU_RSH_X: | 211 | DL(BPF_JMP, BPF_JGE, BPF_X), |
| 204 | A >>= X; | 212 | DL(BPF_JMP, BPF_JGE, BPF_K), |
| 205 | continue; | 213 | DL(BPF_JMP, BPF_JSGT, BPF_X), |
| 206 | case BPF_S_ALU_RSH_K: | 214 | DL(BPF_JMP, BPF_JSGT, BPF_K), |
| 207 | A >>= K; | 215 | DL(BPF_JMP, BPF_JSGE, BPF_X), |
| 208 | continue; | 216 | DL(BPF_JMP, BPF_JSGE, BPF_K), |
| 209 | case BPF_S_ALU_NEG: | 217 | DL(BPF_JMP, BPF_JSET, BPF_X), |
| 210 | A = -A; | 218 | DL(BPF_JMP, BPF_JSET, BPF_K), |
| 211 | continue; | 219 | DL(BPF_JMP, BPF_EXIT, 0), |
| 212 | case BPF_S_JMP_JA: | 220 | DL(BPF_STX, BPF_MEM, BPF_B), |
| 213 | fentry += K; | 221 | DL(BPF_STX, BPF_MEM, BPF_H), |
| 214 | continue; | 222 | DL(BPF_STX, BPF_MEM, BPF_W), |
| 215 | case BPF_S_JMP_JGT_K: | 223 | DL(BPF_STX, BPF_MEM, BPF_DW), |
| 216 | fentry += (A > K) ? fentry->jt : fentry->jf; | 224 | DL(BPF_STX, BPF_XADD, BPF_W), |
| 217 | continue; | 225 | DL(BPF_STX, BPF_XADD, BPF_DW), |
| 218 | case BPF_S_JMP_JGE_K: | 226 | DL(BPF_ST, BPF_MEM, BPF_B), |
| 219 | fentry += (A >= K) ? fentry->jt : fentry->jf; | 227 | DL(BPF_ST, BPF_MEM, BPF_H), |
| 220 | continue; | 228 | DL(BPF_ST, BPF_MEM, BPF_W), |
| 221 | case BPF_S_JMP_JEQ_K: | 229 | DL(BPF_ST, BPF_MEM, BPF_DW), |
| 222 | fentry += (A == K) ? fentry->jt : fentry->jf; | 230 | DL(BPF_LDX, BPF_MEM, BPF_B), |
| 223 | continue; | 231 | DL(BPF_LDX, BPF_MEM, BPF_H), |
| 224 | case BPF_S_JMP_JSET_K: | 232 | DL(BPF_LDX, BPF_MEM, BPF_W), |
| 225 | fentry += (A & K) ? fentry->jt : fentry->jf; | 233 | DL(BPF_LDX, BPF_MEM, BPF_DW), |
| 226 | continue; | 234 | DL(BPF_LD, BPF_ABS, BPF_W), |
| 227 | case BPF_S_JMP_JGT_X: | 235 | DL(BPF_LD, BPF_ABS, BPF_H), |
| 228 | fentry += (A > X) ? fentry->jt : fentry->jf; | 236 | DL(BPF_LD, BPF_ABS, BPF_B), |
| 229 | continue; | 237 | DL(BPF_LD, BPF_IND, BPF_W), |
| 230 | case BPF_S_JMP_JGE_X: | 238 | DL(BPF_LD, BPF_IND, BPF_H), |
| 231 | fentry += (A >= X) ? fentry->jt : fentry->jf; | 239 | DL(BPF_LD, BPF_IND, BPF_B), |
| 232 | continue; | 240 | #undef DL |
| 233 | case BPF_S_JMP_JEQ_X: | 241 | }; |
| 234 | fentry += (A == X) ? fentry->jt : fentry->jf; | 242 | |
| 235 | continue; | 243 | regs[FP_REG] = (u64) (unsigned long) &stack[ARRAY_SIZE(stack)]; |
| 236 | case BPF_S_JMP_JSET_X: | 244 | regs[ARG1_REG] = (u64) (unsigned long) ctx; |
| 237 | fentry += (A & X) ? fentry->jt : fentry->jf; | 245 | |
| 238 | continue; | 246 | select_insn: |
| 239 | case BPF_S_LD_W_ABS: | 247 | goto *jumptable[insn->code]; |
| 240 | k = K; | 248 | |
| 241 | load_w: | 249 | /* ALU */ |
| 242 | ptr = load_pointer(skb, k, 4, &tmp); | 250 | #define ALU(OPCODE, OP) \ |
| 243 | if (ptr != NULL) { | 251 | BPF_ALU64_##OPCODE##_BPF_X: \ |
| 244 | A = get_unaligned_be32(ptr); | 252 | A = A OP X; \ |
| 245 | continue; | 253 | CONT; \ |
| 246 | } | 254 | BPF_ALU_##OPCODE##_BPF_X: \ |
| 255 | A = (u32) A OP (u32) X; \ | ||
| 256 | CONT; \ | ||
| 257 | BPF_ALU64_##OPCODE##_BPF_K: \ | ||
| 258 | A = A OP K; \ | ||
| 259 | CONT; \ | ||
| 260 | BPF_ALU_##OPCODE##_BPF_K: \ | ||
| 261 | A = (u32) A OP (u32) K; \ | ||
| 262 | CONT; | ||
| 263 | |||
| 264 | ALU(BPF_ADD, +) | ||
| 265 | ALU(BPF_SUB, -) | ||
| 266 | ALU(BPF_AND, &) | ||
| 267 | ALU(BPF_OR, |) | ||
| 268 | ALU(BPF_LSH, <<) | ||
| 269 | ALU(BPF_RSH, >>) | ||
| 270 | ALU(BPF_XOR, ^) | ||
| 271 | ALU(BPF_MUL, *) | ||
| 272 | #undef ALU | ||
| 273 | BPF_ALU_BPF_NEG_0: | ||
| 274 | A = (u32) -A; | ||
| 275 | CONT; | ||
| 276 | BPF_ALU64_BPF_NEG_0: | ||
| 277 | A = -A; | ||
| 278 | CONT; | ||
| 279 | BPF_ALU_BPF_MOV_BPF_X: | ||
| 280 | A = (u32) X; | ||
| 281 | CONT; | ||
| 282 | BPF_ALU_BPF_MOV_BPF_K: | ||
| 283 | A = (u32) K; | ||
| 284 | CONT; | ||
| 285 | BPF_ALU64_BPF_MOV_BPF_X: | ||
| 286 | A = X; | ||
| 287 | CONT; | ||
| 288 | BPF_ALU64_BPF_MOV_BPF_K: | ||
| 289 | A = K; | ||
| 290 | CONT; | ||
| 291 | BPF_ALU64_BPF_ARSH_BPF_X: | ||
| 292 | (*(s64 *) &A) >>= X; | ||
| 293 | CONT; | ||
| 294 | BPF_ALU64_BPF_ARSH_BPF_K: | ||
| 295 | (*(s64 *) &A) >>= K; | ||
| 296 | CONT; | ||
| 297 | BPF_ALU64_BPF_MOD_BPF_X: | ||
| 298 | if (unlikely(X == 0)) | ||
| 247 | return 0; | 299 | return 0; |
| 248 | case BPF_S_LD_H_ABS: | 300 | tmp = A; |
| 249 | k = K; | 301 | A = do_div(tmp, X); |
| 250 | load_h: | 302 | CONT; |
| 251 | ptr = load_pointer(skb, k, 2, &tmp); | 303 | BPF_ALU_BPF_MOD_BPF_X: |
| 252 | if (ptr != NULL) { | 304 | if (unlikely(X == 0)) |
| 253 | A = get_unaligned_be16(ptr); | ||
| 254 | continue; | ||
| 255 | } | ||
| 256 | return 0; | 305 | return 0; |
| 257 | case BPF_S_LD_B_ABS: | 306 | tmp = (u32) A; |
| 258 | k = K; | 307 | A = do_div(tmp, (u32) X); |
| 259 | load_b: | 308 | CONT; |
| 260 | ptr = load_pointer(skb, k, 1, &tmp); | 309 | BPF_ALU64_BPF_MOD_BPF_K: |
| 261 | if (ptr != NULL) { | 310 | tmp = A; |
| 262 | A = *(u8 *)ptr; | 311 | A = do_div(tmp, K); |
| 263 | continue; | 312 | CONT; |
| 264 | } | 313 | BPF_ALU_BPF_MOD_BPF_K: |
| 314 | tmp = (u32) A; | ||
| 315 | A = do_div(tmp, (u32) K); | ||
| 316 | CONT; | ||
| 317 | BPF_ALU64_BPF_DIV_BPF_X: | ||
| 318 | if (unlikely(X == 0)) | ||
| 265 | return 0; | 319 | return 0; |
| 266 | case BPF_S_LD_W_LEN: | 320 | do_div(A, X); |
| 267 | A = skb->len; | 321 | CONT; |
| 268 | continue; | 322 | BPF_ALU_BPF_DIV_BPF_X: |
| 269 | case BPF_S_LDX_W_LEN: | 323 | if (unlikely(X == 0)) |
| 270 | X = skb->len; | ||
| 271 | continue; | ||
| 272 | case BPF_S_LD_W_IND: | ||
| 273 | k = X + K; | ||
| 274 | goto load_w; | ||
| 275 | case BPF_S_LD_H_IND: | ||
| 276 | k = X + K; | ||
| 277 | goto load_h; | ||
| 278 | case BPF_S_LD_B_IND: | ||
| 279 | k = X + K; | ||
| 280 | goto load_b; | ||
| 281 | case BPF_S_LDX_B_MSH: | ||
| 282 | ptr = load_pointer(skb, K, 1, &tmp); | ||
| 283 | if (ptr != NULL) { | ||
| 284 | X = (*(u8 *)ptr & 0xf) << 2; | ||
| 285 | continue; | ||
| 286 | } | ||
| 287 | return 0; | 324 | return 0; |
| 288 | case BPF_S_LD_IMM: | 325 | tmp = (u32) A; |
| 289 | A = K; | 326 | do_div(tmp, (u32) X); |
| 290 | continue; | 327 | A = (u32) tmp; |
| 291 | case BPF_S_LDX_IMM: | 328 | CONT; |
| 292 | X = K; | 329 | BPF_ALU64_BPF_DIV_BPF_K: |
| 293 | continue; | 330 | do_div(A, K); |
| 294 | case BPF_S_LD_MEM: | 331 | CONT; |
| 295 | A = mem[K]; | 332 | BPF_ALU_BPF_DIV_BPF_K: |
| 296 | continue; | 333 | tmp = (u32) A; |
| 297 | case BPF_S_LDX_MEM: | 334 | do_div(tmp, (u32) K); |
| 298 | X = mem[K]; | 335 | A = (u32) tmp; |
| 299 | continue; | 336 | CONT; |
| 300 | case BPF_S_MISC_TAX: | 337 | BPF_ALU_BPF_END_BPF_TO_BE: |
| 301 | X = A; | 338 | switch (K) { |
| 302 | continue; | 339 | case 16: |
| 303 | case BPF_S_MISC_TXA: | 340 | A = (__force u16) cpu_to_be16(A); |
| 304 | A = X; | 341 | break; |
| 305 | continue; | 342 | case 32: |
| 306 | case BPF_S_RET_K: | 343 | A = (__force u32) cpu_to_be32(A); |
| 307 | return K; | 344 | break; |
| 308 | case BPF_S_RET_A: | 345 | case 64: |
| 309 | return A; | 346 | A = (__force u64) cpu_to_be64(A); |
| 310 | case BPF_S_ST: | 347 | break; |
| 311 | mem[K] = A; | 348 | } |
| 312 | continue; | 349 | CONT; |
| 313 | case BPF_S_STX: | 350 | BPF_ALU_BPF_END_BPF_TO_LE: |
| 314 | mem[K] = X; | 351 | switch (K) { |
| 315 | continue; | 352 | case 16: |
| 316 | case BPF_S_ANC_PROTOCOL: | 353 | A = (__force u16) cpu_to_le16(A); |
| 317 | A = ntohs(skb->protocol); | 354 | break; |
| 318 | continue; | 355 | case 32: |
| 319 | case BPF_S_ANC_PKTTYPE: | 356 | A = (__force u32) cpu_to_le32(A); |
| 320 | A = skb->pkt_type; | 357 | break; |
| 321 | continue; | 358 | case 64: |
| 322 | case BPF_S_ANC_IFINDEX: | 359 | A = (__force u64) cpu_to_le64(A); |
| 323 | if (!skb->dev) | 360 | break; |
| 324 | return 0; | 361 | } |
| 325 | A = skb->dev->ifindex; | 362 | CONT; |
| 326 | continue; | 363 | |
| 327 | case BPF_S_ANC_MARK: | 364 | /* CALL */ |
| 328 | A = skb->mark; | 365 | BPF_JMP_BPF_CALL_0: |
| 329 | continue; | 366 | /* Function call scratches R1-R5 registers, preserves R6-R9, |
| 330 | case BPF_S_ANC_QUEUE: | 367 | * and stores return value into R0. |
| 331 | A = skb->queue_mapping; | 368 | */ |
| 332 | continue; | 369 | R0 = (__bpf_call_base + insn->imm)(regs[1], regs[2], regs[3], |
| 333 | case BPF_S_ANC_HATYPE: | 370 | regs[4], regs[5]); |
| 334 | if (!skb->dev) | 371 | CONT; |
| 335 | return 0; | 372 | |
| 336 | A = skb->dev->type; | 373 | /* JMP */ |
| 337 | continue; | 374 | BPF_JMP_BPF_JA_0: |
| 338 | case BPF_S_ANC_RXHASH: | 375 | insn += insn->off; |
| 339 | A = skb->rxhash; | 376 | CONT; |
| 340 | continue; | 377 | BPF_JMP_BPF_JEQ_BPF_X: |
| 341 | case BPF_S_ANC_CPU: | 378 | if (A == X) { |
| 342 | A = raw_smp_processor_id(); | 379 | insn += insn->off; |
| 343 | continue; | 380 | CONT_JMP; |
| 344 | case BPF_S_ANC_VLAN_TAG: | 381 | } |
| 345 | A = vlan_tx_tag_get(skb); | 382 | CONT; |
| 346 | continue; | 383 | BPF_JMP_BPF_JEQ_BPF_K: |
| 347 | case BPF_S_ANC_VLAN_TAG_PRESENT: | 384 | if (A == K) { |
| 348 | A = !!vlan_tx_tag_present(skb); | 385 | insn += insn->off; |
| 349 | continue; | 386 | CONT_JMP; |
| 350 | case BPF_S_ANC_PAY_OFFSET: | 387 | } |
| 351 | A = __skb_get_poff(skb); | 388 | CONT; |
| 352 | continue; | 389 | BPF_JMP_BPF_JNE_BPF_X: |
| 353 | case BPF_S_ANC_NLATTR: { | 390 | if (A != X) { |
| 354 | struct nlattr *nla; | 391 | insn += insn->off; |
| 355 | 392 | CONT_JMP; | |
| 356 | if (skb_is_nonlinear(skb)) | 393 | } |
| 357 | return 0; | 394 | CONT; |
| 358 | if (A > skb->len - sizeof(struct nlattr)) | 395 | BPF_JMP_BPF_JNE_BPF_K: |
| 359 | return 0; | 396 | if (A != K) { |
| 360 | 397 | insn += insn->off; | |
| 361 | nla = nla_find((struct nlattr *)&skb->data[A], | 398 | CONT_JMP; |
| 362 | skb->len - A, X); | 399 | } |
| 363 | if (nla) | 400 | CONT; |
| 364 | A = (void *)nla - (void *)skb->data; | 401 | BPF_JMP_BPF_JGT_BPF_X: |
| 365 | else | 402 | if (A > X) { |
| 366 | A = 0; | 403 | insn += insn->off; |
| 367 | continue; | 404 | CONT_JMP; |
| 405 | } | ||
| 406 | CONT; | ||
| 407 | BPF_JMP_BPF_JGT_BPF_K: | ||
| 408 | if (A > K) { | ||
| 409 | insn += insn->off; | ||
| 410 | CONT_JMP; | ||
| 411 | } | ||
| 412 | CONT; | ||
| 413 | BPF_JMP_BPF_JGE_BPF_X: | ||
| 414 | if (A >= X) { | ||
| 415 | insn += insn->off; | ||
| 416 | CONT_JMP; | ||
| 417 | } | ||
| 418 | CONT; | ||
| 419 | BPF_JMP_BPF_JGE_BPF_K: | ||
| 420 | if (A >= K) { | ||
| 421 | insn += insn->off; | ||
| 422 | CONT_JMP; | ||
| 423 | } | ||
| 424 | CONT; | ||
| 425 | BPF_JMP_BPF_JSGT_BPF_X: | ||
| 426 | if (((s64)A) > ((s64)X)) { | ||
| 427 | insn += insn->off; | ||
| 428 | CONT_JMP; | ||
| 429 | } | ||
| 430 | CONT; | ||
| 431 | BPF_JMP_BPF_JSGT_BPF_K: | ||
| 432 | if (((s64)A) > ((s64)K)) { | ||
| 433 | insn += insn->off; | ||
| 434 | CONT_JMP; | ||
| 435 | } | ||
| 436 | CONT; | ||
| 437 | BPF_JMP_BPF_JSGE_BPF_X: | ||
| 438 | if (((s64)A) >= ((s64)X)) { | ||
| 439 | insn += insn->off; | ||
| 440 | CONT_JMP; | ||
| 441 | } | ||
| 442 | CONT; | ||
| 443 | BPF_JMP_BPF_JSGE_BPF_K: | ||
| 444 | if (((s64)A) >= ((s64)K)) { | ||
| 445 | insn += insn->off; | ||
| 446 | CONT_JMP; | ||
| 447 | } | ||
| 448 | CONT; | ||
| 449 | BPF_JMP_BPF_JSET_BPF_X: | ||
| 450 | if (A & X) { | ||
| 451 | insn += insn->off; | ||
| 452 | CONT_JMP; | ||
| 453 | } | ||
| 454 | CONT; | ||
| 455 | BPF_JMP_BPF_JSET_BPF_K: | ||
| 456 | if (A & K) { | ||
| 457 | insn += insn->off; | ||
| 458 | CONT_JMP; | ||
| 459 | } | ||
| 460 | CONT; | ||
| 461 | BPF_JMP_BPF_EXIT_0: | ||
| 462 | return R0; | ||
| 463 | |||
| 464 | /* STX and ST and LDX*/ | ||
| 465 | #define LDST(SIZEOP, SIZE) \ | ||
| 466 | BPF_STX_BPF_MEM_##SIZEOP: \ | ||
| 467 | *(SIZE *)(unsigned long) (A + insn->off) = X; \ | ||
| 468 | CONT; \ | ||
| 469 | BPF_ST_BPF_MEM_##SIZEOP: \ | ||
| 470 | *(SIZE *)(unsigned long) (A + insn->off) = K; \ | ||
| 471 | CONT; \ | ||
| 472 | BPF_LDX_BPF_MEM_##SIZEOP: \ | ||
| 473 | A = *(SIZE *)(unsigned long) (X + insn->off); \ | ||
| 474 | CONT; | ||
| 475 | |||
| 476 | LDST(BPF_B, u8) | ||
| 477 | LDST(BPF_H, u16) | ||
| 478 | LDST(BPF_W, u32) | ||
| 479 | LDST(BPF_DW, u64) | ||
| 480 | #undef LDST | ||
| 481 | BPF_STX_BPF_XADD_BPF_W: /* lock xadd *(u32 *)(A + insn->off) += X */ | ||
| 482 | atomic_add((u32) X, (atomic_t *)(unsigned long) | ||
| 483 | (A + insn->off)); | ||
| 484 | CONT; | ||
| 485 | BPF_STX_BPF_XADD_BPF_DW: /* lock xadd *(u64 *)(A + insn->off) += X */ | ||
| 486 | atomic64_add((u64) X, (atomic64_t *)(unsigned long) | ||
| 487 | (A + insn->off)); | ||
| 488 | CONT; | ||
| 489 | BPF_LD_BPF_ABS_BPF_W: /* R0 = ntohl(*(u32 *) (skb->data + K)) */ | ||
| 490 | off = K; | ||
| 491 | load_word: | ||
| 492 | /* BPF_LD + BPD_ABS and BPF_LD + BPF_IND insns are only | ||
| 493 | * appearing in the programs where ctx == skb. All programs | ||
| 494 | * keep 'ctx' in regs[CTX_REG] == R6, sk_convert_filter() | ||
| 495 | * saves it in R6, internal BPF verifier will check that | ||
| 496 | * R6 == ctx. | ||
| 497 | * | ||
| 498 | * BPF_ABS and BPF_IND are wrappers of function calls, so | ||
| 499 | * they scratch R1-R5 registers, preserve R6-R9, and store | ||
| 500 | * return value into R0. | ||
| 501 | * | ||
| 502 | * Implicit input: | ||
| 503 | * ctx | ||
| 504 | * | ||
| 505 | * Explicit input: | ||
| 506 | * X == any register | ||
| 507 | * K == 32-bit immediate | ||
| 508 | * | ||
| 509 | * Output: | ||
| 510 | * R0 - 8/16/32-bit skb data converted to cpu endianness | ||
| 511 | */ | ||
| 512 | ptr = load_pointer((struct sk_buff *) ctx, off, 4, &tmp); | ||
| 513 | if (likely(ptr != NULL)) { | ||
| 514 | R0 = get_unaligned_be32(ptr); | ||
| 515 | CONT; | ||
| 516 | } | ||
| 517 | return 0; | ||
| 518 | BPF_LD_BPF_ABS_BPF_H: /* R0 = ntohs(*(u16 *) (skb->data + K)) */ | ||
| 519 | off = K; | ||
| 520 | load_half: | ||
| 521 | ptr = load_pointer((struct sk_buff *) ctx, off, 2, &tmp); | ||
| 522 | if (likely(ptr != NULL)) { | ||
| 523 | R0 = get_unaligned_be16(ptr); | ||
| 524 | CONT; | ||
| 525 | } | ||
| 526 | return 0; | ||
| 527 | BPF_LD_BPF_ABS_BPF_B: /* R0 = *(u8 *) (ctx + K) */ | ||
| 528 | off = K; | ||
| 529 | load_byte: | ||
| 530 | ptr = load_pointer((struct sk_buff *) ctx, off, 1, &tmp); | ||
| 531 | if (likely(ptr != NULL)) { | ||
| 532 | R0 = *(u8 *)ptr; | ||
| 533 | CONT; | ||
| 534 | } | ||
| 535 | return 0; | ||
| 536 | BPF_LD_BPF_IND_BPF_W: /* R0 = ntohl(*(u32 *) (skb->data + X + K)) */ | ||
| 537 | off = K + X; | ||
| 538 | goto load_word; | ||
| 539 | BPF_LD_BPF_IND_BPF_H: /* R0 = ntohs(*(u16 *) (skb->data + X + K)) */ | ||
| 540 | off = K + X; | ||
| 541 | goto load_half; | ||
| 542 | BPF_LD_BPF_IND_BPF_B: /* R0 = *(u8 *) (skb->data + X + K) */ | ||
| 543 | off = K + X; | ||
| 544 | goto load_byte; | ||
| 545 | |||
| 546 | default_label: | ||
| 547 | /* If we ever reach this, we have a bug somewhere. */ | ||
| 548 | WARN_RATELIMIT(1, "unknown opcode %02x\n", insn->code); | ||
| 549 | return 0; | ||
| 550 | #undef CONT_JMP | ||
| 551 | #undef CONT | ||
| 552 | |||
| 553 | #undef R0 | ||
| 554 | #undef X | ||
| 555 | #undef A | ||
| 556 | #undef K | ||
| 557 | } | ||
| 558 | |||
| 559 | u32 sk_run_filter_int_seccomp(const struct seccomp_data *ctx, | ||
| 560 | const struct sock_filter_int *insni) | ||
| 561 | __attribute__ ((alias ("__sk_run_filter"))); | ||
| 562 | |||
| 563 | u32 sk_run_filter_int_skb(const struct sk_buff *ctx, | ||
| 564 | const struct sock_filter_int *insni) | ||
| 565 | __attribute__ ((alias ("__sk_run_filter"))); | ||
| 566 | EXPORT_SYMBOL_GPL(sk_run_filter_int_skb); | ||
| 567 | |||
| 568 | /* Helper to find the offset of pkt_type in sk_buff structure. We want | ||
| 569 | * to make sure its still a 3bit field starting at a byte boundary; | ||
| 570 | * taken from arch/x86/net/bpf_jit_comp.c. | ||
| 571 | */ | ||
| 572 | #define PKT_TYPE_MAX 7 | ||
| 573 | static unsigned int pkt_type_offset(void) | ||
| 574 | { | ||
| 575 | struct sk_buff skb_probe = { .pkt_type = ~0, }; | ||
| 576 | u8 *ct = (u8 *) &skb_probe; | ||
| 577 | unsigned int off; | ||
| 578 | |||
| 579 | for (off = 0; off < sizeof(struct sk_buff); off++) { | ||
| 580 | if (ct[off] == PKT_TYPE_MAX) | ||
| 581 | return off; | ||
| 582 | } | ||
| 583 | |||
| 584 | pr_err_once("Please fix %s, as pkt_type couldn't be found!\n", __func__); | ||
| 585 | return -1; | ||
| 586 | } | ||
| 587 | |||
| 588 | static u64 __skb_get_pay_offset(u64 ctx, u64 A, u64 X, u64 r4, u64 r5) | ||
| 589 | { | ||
| 590 | struct sk_buff *skb = (struct sk_buff *)(long) ctx; | ||
| 591 | |||
| 592 | return __skb_get_poff(skb); | ||
| 593 | } | ||
| 594 | |||
| 595 | static u64 __skb_get_nlattr(u64 ctx, u64 A, u64 X, u64 r4, u64 r5) | ||
| 596 | { | ||
| 597 | struct sk_buff *skb = (struct sk_buff *)(long) ctx; | ||
| 598 | struct nlattr *nla; | ||
| 599 | |||
| 600 | if (skb_is_nonlinear(skb)) | ||
| 601 | return 0; | ||
| 602 | |||
| 603 | if (skb->len < sizeof(struct nlattr)) | ||
| 604 | return 0; | ||
| 605 | |||
| 606 | if (A > skb->len - sizeof(struct nlattr)) | ||
| 607 | return 0; | ||
| 608 | |||
| 609 | nla = nla_find((struct nlattr *) &skb->data[A], skb->len - A, X); | ||
| 610 | if (nla) | ||
| 611 | return (void *) nla - (void *) skb->data; | ||
| 612 | |||
| 613 | return 0; | ||
| 614 | } | ||
| 615 | |||
| 616 | static u64 __skb_get_nlattr_nest(u64 ctx, u64 A, u64 X, u64 r4, u64 r5) | ||
| 617 | { | ||
| 618 | struct sk_buff *skb = (struct sk_buff *)(long) ctx; | ||
| 619 | struct nlattr *nla; | ||
| 620 | |||
| 621 | if (skb_is_nonlinear(skb)) | ||
| 622 | return 0; | ||
| 623 | |||
| 624 | if (skb->len < sizeof(struct nlattr)) | ||
| 625 | return 0; | ||
| 626 | |||
| 627 | if (A > skb->len - sizeof(struct nlattr)) | ||
| 628 | return 0; | ||
| 629 | |||
| 630 | nla = (struct nlattr *) &skb->data[A]; | ||
| 631 | if (nla->nla_len > skb->len - A) | ||
| 632 | return 0; | ||
| 633 | |||
| 634 | nla = nla_find_nested(nla, X); | ||
| 635 | if (nla) | ||
| 636 | return (void *) nla - (void *) skb->data; | ||
| 637 | |||
| 638 | return 0; | ||
| 639 | } | ||
| 640 | |||
| 641 | static u64 __get_raw_cpu_id(u64 ctx, u64 A, u64 X, u64 r4, u64 r5) | ||
| 642 | { | ||
| 643 | return raw_smp_processor_id(); | ||
| 644 | } | ||
| 645 | |||
| 646 | /* Register mappings for user programs. */ | ||
| 647 | #define A_REG 0 | ||
| 648 | #define X_REG 7 | ||
| 649 | #define TMP_REG 8 | ||
| 650 | #define ARG2_REG 2 | ||
| 651 | #define ARG3_REG 3 | ||
| 652 | |||
| 653 | static bool convert_bpf_extensions(struct sock_filter *fp, | ||
| 654 | struct sock_filter_int **insnp) | ||
| 655 | { | ||
| 656 | struct sock_filter_int *insn = *insnp; | ||
| 657 | |||
| 658 | switch (fp->k) { | ||
| 659 | case SKF_AD_OFF + SKF_AD_PROTOCOL: | ||
| 660 | BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, protocol) != 2); | ||
| 661 | |||
| 662 | insn->code = BPF_LDX | BPF_MEM | BPF_H; | ||
| 663 | insn->a_reg = A_REG; | ||
| 664 | insn->x_reg = CTX_REG; | ||
| 665 | insn->off = offsetof(struct sk_buff, protocol); | ||
| 666 | insn++; | ||
| 667 | |||
| 668 | /* A = ntohs(A) [emitting a nop or swap16] */ | ||
| 669 | insn->code = BPF_ALU | BPF_END | BPF_FROM_BE; | ||
| 670 | insn->a_reg = A_REG; | ||
| 671 | insn->imm = 16; | ||
| 672 | break; | ||
| 673 | |||
| 674 | case SKF_AD_OFF + SKF_AD_PKTTYPE: | ||
| 675 | insn->code = BPF_LDX | BPF_MEM | BPF_B; | ||
| 676 | insn->a_reg = A_REG; | ||
| 677 | insn->x_reg = CTX_REG; | ||
| 678 | insn->off = pkt_type_offset(); | ||
| 679 | if (insn->off < 0) | ||
| 680 | return false; | ||
| 681 | insn++; | ||
| 682 | |||
| 683 | insn->code = BPF_ALU | BPF_AND | BPF_K; | ||
| 684 | insn->a_reg = A_REG; | ||
| 685 | insn->imm = PKT_TYPE_MAX; | ||
| 686 | break; | ||
| 687 | |||
| 688 | case SKF_AD_OFF + SKF_AD_IFINDEX: | ||
| 689 | case SKF_AD_OFF + SKF_AD_HATYPE: | ||
| 690 | if (FIELD_SIZEOF(struct sk_buff, dev) == 8) | ||
| 691 | insn->code = BPF_LDX | BPF_MEM | BPF_DW; | ||
| 692 | else | ||
| 693 | insn->code = BPF_LDX | BPF_MEM | BPF_W; | ||
| 694 | insn->a_reg = TMP_REG; | ||
| 695 | insn->x_reg = CTX_REG; | ||
| 696 | insn->off = offsetof(struct sk_buff, dev); | ||
| 697 | insn++; | ||
| 698 | |||
| 699 | insn->code = BPF_JMP | BPF_JNE | BPF_K; | ||
| 700 | insn->a_reg = TMP_REG; | ||
| 701 | insn->imm = 0; | ||
| 702 | insn->off = 1; | ||
| 703 | insn++; | ||
| 704 | |||
| 705 | insn->code = BPF_JMP | BPF_EXIT; | ||
| 706 | insn++; | ||
| 707 | |||
| 708 | BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, ifindex) != 4); | ||
| 709 | BUILD_BUG_ON(FIELD_SIZEOF(struct net_device, type) != 2); | ||
| 710 | |||
| 711 | insn->a_reg = A_REG; | ||
| 712 | insn->x_reg = TMP_REG; | ||
| 713 | |||
| 714 | if (fp->k == SKF_AD_OFF + SKF_AD_IFINDEX) { | ||
| 715 | insn->code = BPF_LDX | BPF_MEM | BPF_W; | ||
| 716 | insn->off = offsetof(struct net_device, ifindex); | ||
| 717 | } else { | ||
| 718 | insn->code = BPF_LDX | BPF_MEM | BPF_H; | ||
| 719 | insn->off = offsetof(struct net_device, type); | ||
| 368 | } | 720 | } |
| 369 | case BPF_S_ANC_NLATTR_NEST: { | 721 | break; |
| 370 | struct nlattr *nla; | 722 | |
| 371 | 723 | case SKF_AD_OFF + SKF_AD_MARK: | |
| 372 | if (skb_is_nonlinear(skb)) | 724 | BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, mark) != 4); |
| 373 | return 0; | 725 | |
| 374 | if (A > skb->len - sizeof(struct nlattr)) | 726 | insn->code = BPF_LDX | BPF_MEM | BPF_W; |
| 375 | return 0; | 727 | insn->a_reg = A_REG; |
| 376 | 728 | insn->x_reg = CTX_REG; | |
| 377 | nla = (struct nlattr *)&skb->data[A]; | 729 | insn->off = offsetof(struct sk_buff, mark); |
| 378 | if (nla->nla_len > A - skb->len) | 730 | break; |
| 379 | return 0; | 731 | |
| 380 | 732 | case SKF_AD_OFF + SKF_AD_RXHASH: | |
| 381 | nla = nla_find_nested(nla, X); | 733 | BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, hash) != 4); |
| 382 | if (nla) | 734 | |
| 383 | A = (void *)nla - (void *)skb->data; | 735 | insn->code = BPF_LDX | BPF_MEM | BPF_W; |
| 384 | else | 736 | insn->a_reg = A_REG; |
| 385 | A = 0; | 737 | insn->x_reg = CTX_REG; |
| 386 | continue; | 738 | insn->off = offsetof(struct sk_buff, hash); |
| 739 | break; | ||
| 740 | |||
| 741 | case SKF_AD_OFF + SKF_AD_QUEUE: | ||
| 742 | BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, queue_mapping) != 2); | ||
| 743 | |||
| 744 | insn->code = BPF_LDX | BPF_MEM | BPF_H; | ||
| 745 | insn->a_reg = A_REG; | ||
| 746 | insn->x_reg = CTX_REG; | ||
| 747 | insn->off = offsetof(struct sk_buff, queue_mapping); | ||
| 748 | break; | ||
| 749 | |||
| 750 | case SKF_AD_OFF + SKF_AD_VLAN_TAG: | ||
| 751 | case SKF_AD_OFF + SKF_AD_VLAN_TAG_PRESENT: | ||
| 752 | BUILD_BUG_ON(FIELD_SIZEOF(struct sk_buff, vlan_tci) != 2); | ||
| 753 | |||
| 754 | insn->code = BPF_LDX | BPF_MEM | BPF_H; | ||
| 755 | insn->a_reg = A_REG; | ||
| 756 | insn->x_reg = CTX_REG; | ||
| 757 | insn->off = offsetof(struct sk_buff, vlan_tci); | ||
| 758 | insn++; | ||
| 759 | |||
| 760 | BUILD_BUG_ON(VLAN_TAG_PRESENT != 0x1000); | ||
| 761 | |||
| 762 | if (fp->k == SKF_AD_OFF + SKF_AD_VLAN_TAG) { | ||
| 763 | insn->code = BPF_ALU | BPF_AND | BPF_K; | ||
| 764 | insn->a_reg = A_REG; | ||
| 765 | insn->imm = ~VLAN_TAG_PRESENT; | ||
| 766 | } else { | ||
| 767 | insn->code = BPF_ALU | BPF_RSH | BPF_K; | ||
| 768 | insn->a_reg = A_REG; | ||
| 769 | insn->imm = 12; | ||
| 770 | insn++; | ||
| 771 | |||
| 772 | insn->code = BPF_ALU | BPF_AND | BPF_K; | ||
| 773 | insn->a_reg = A_REG; | ||
| 774 | insn->imm = 1; | ||
| 387 | } | 775 | } |
| 388 | #ifdef CONFIG_SECCOMP_FILTER | 776 | break; |
| 389 | case BPF_S_ANC_SECCOMP_LD_W: | 777 | |
| 390 | A = seccomp_bpf_load(fentry->k); | 778 | case SKF_AD_OFF + SKF_AD_PAY_OFFSET: |
| 391 | continue; | 779 | case SKF_AD_OFF + SKF_AD_NLATTR: |
| 392 | #endif | 780 | case SKF_AD_OFF + SKF_AD_NLATTR_NEST: |
| 781 | case SKF_AD_OFF + SKF_AD_CPU: | ||
| 782 | /* arg1 = ctx */ | ||
| 783 | insn->code = BPF_ALU64 | BPF_MOV | BPF_X; | ||
| 784 | insn->a_reg = ARG1_REG; | ||
| 785 | insn->x_reg = CTX_REG; | ||
| 786 | insn++; | ||
| 787 | |||
| 788 | /* arg2 = A */ | ||
| 789 | insn->code = BPF_ALU64 | BPF_MOV | BPF_X; | ||
| 790 | insn->a_reg = ARG2_REG; | ||
| 791 | insn->x_reg = A_REG; | ||
| 792 | insn++; | ||
| 793 | |||
| 794 | /* arg3 = X */ | ||
| 795 | insn->code = BPF_ALU64 | BPF_MOV | BPF_X; | ||
| 796 | insn->a_reg = ARG3_REG; | ||
| 797 | insn->x_reg = X_REG; | ||
| 798 | insn++; | ||
| 799 | |||
| 800 | /* Emit call(ctx, arg2=A, arg3=X) */ | ||
| 801 | insn->code = BPF_JMP | BPF_CALL; | ||
| 802 | switch (fp->k) { | ||
| 803 | case SKF_AD_OFF + SKF_AD_PAY_OFFSET: | ||
| 804 | insn->imm = __skb_get_pay_offset - __bpf_call_base; | ||
| 805 | break; | ||
| 806 | case SKF_AD_OFF + SKF_AD_NLATTR: | ||
| 807 | insn->imm = __skb_get_nlattr - __bpf_call_base; | ||
| 808 | break; | ||
| 809 | case SKF_AD_OFF + SKF_AD_NLATTR_NEST: | ||
| 810 | insn->imm = __skb_get_nlattr_nest - __bpf_call_base; | ||
| 811 | break; | ||
| 812 | case SKF_AD_OFF + SKF_AD_CPU: | ||
| 813 | insn->imm = __get_raw_cpu_id - __bpf_call_base; | ||
| 814 | break; | ||
| 815 | } | ||
| 816 | break; | ||
| 817 | |||
| 818 | case SKF_AD_OFF + SKF_AD_ALU_XOR_X: | ||
| 819 | insn->code = BPF_ALU | BPF_XOR | BPF_X; | ||
| 820 | insn->a_reg = A_REG; | ||
| 821 | insn->x_reg = X_REG; | ||
| 822 | break; | ||
| 823 | |||
| 824 | default: | ||
| 825 | /* This is just a dummy call to avoid letting the compiler | ||
| 826 | * evict __bpf_call_base() as an optimization. Placed here | ||
| 827 | * where no-one bothers. | ||
| 828 | */ | ||
| 829 | BUG_ON(__bpf_call_base(0, 0, 0, 0, 0) != 0); | ||
| 830 | return false; | ||
| 831 | } | ||
| 832 | |||
| 833 | *insnp = insn; | ||
| 834 | return true; | ||
| 835 | } | ||
| 836 | |||
| 837 | /** | ||
| 838 | * sk_convert_filter - convert filter program | ||
| 839 | * @prog: the user passed filter program | ||
| 840 | * @len: the length of the user passed filter program | ||
| 841 | * @new_prog: buffer where converted program will be stored | ||
| 842 | * @new_len: pointer to store length of converted program | ||
| 843 | * | ||
| 844 | * Remap 'sock_filter' style BPF instruction set to 'sock_filter_ext' style. | ||
| 845 | * Conversion workflow: | ||
| 846 | * | ||
| 847 | * 1) First pass for calculating the new program length: | ||
| 848 | * sk_convert_filter(old_prog, old_len, NULL, &new_len) | ||
| 849 | * | ||
| 850 | * 2) 2nd pass to remap in two passes: 1st pass finds new | ||
| 851 | * jump offsets, 2nd pass remapping: | ||
| 852 | * new_prog = kmalloc(sizeof(struct sock_filter_int) * new_len); | ||
| 853 | * sk_convert_filter(old_prog, old_len, new_prog, &new_len); | ||
| 854 | * | ||
| 855 | * User BPF's register A is mapped to our BPF register 6, user BPF | ||
| 856 | * register X is mapped to BPF register 7; frame pointer is always | ||
| 857 | * register 10; Context 'void *ctx' is stored in register 1, that is, | ||
| 858 | * for socket filters: ctx == 'struct sk_buff *', for seccomp: | ||
| 859 | * ctx == 'struct seccomp_data *'. | ||
| 860 | */ | ||
| 861 | int sk_convert_filter(struct sock_filter *prog, int len, | ||
| 862 | struct sock_filter_int *new_prog, int *new_len) | ||
| 863 | { | ||
| 864 | int new_flen = 0, pass = 0, target, i; | ||
| 865 | struct sock_filter_int *new_insn; | ||
| 866 | struct sock_filter *fp; | ||
| 867 | int *addrs = NULL; | ||
| 868 | u8 bpf_src; | ||
| 869 | |||
| 870 | BUILD_BUG_ON(BPF_MEMWORDS * sizeof(u32) > MAX_BPF_STACK); | ||
| 871 | BUILD_BUG_ON(FP_REG + 1 != MAX_BPF_REG); | ||
| 872 | |||
| 873 | if (len <= 0 || len >= BPF_MAXINSNS) | ||
| 874 | return -EINVAL; | ||
| 875 | |||
| 876 | if (new_prog) { | ||
| 877 | addrs = kzalloc(len * sizeof(*addrs), GFP_KERNEL); | ||
| 878 | if (!addrs) | ||
| 879 | return -ENOMEM; | ||
| 880 | } | ||
| 881 | |||
| 882 | do_pass: | ||
| 883 | new_insn = new_prog; | ||
| 884 | fp = prog; | ||
| 885 | |||
| 886 | if (new_insn) { | ||
| 887 | new_insn->code = BPF_ALU64 | BPF_MOV | BPF_X; | ||
| 888 | new_insn->a_reg = CTX_REG; | ||
| 889 | new_insn->x_reg = ARG1_REG; | ||
| 890 | } | ||
| 891 | new_insn++; | ||
| 892 | |||
| 893 | for (i = 0; i < len; fp++, i++) { | ||
| 894 | struct sock_filter_int tmp_insns[6] = { }; | ||
| 895 | struct sock_filter_int *insn = tmp_insns; | ||
| 896 | |||
| 897 | if (addrs) | ||
| 898 | addrs[i] = new_insn - new_prog; | ||
| 899 | |||
| 900 | switch (fp->code) { | ||
| 901 | /* All arithmetic insns and skb loads map as-is. */ | ||
| 902 | case BPF_ALU | BPF_ADD | BPF_X: | ||
| 903 | case BPF_ALU | BPF_ADD | BPF_K: | ||
| 904 | case BPF_ALU | BPF_SUB | BPF_X: | ||
| 905 | case BPF_ALU | BPF_SUB | BPF_K: | ||
| 906 | case BPF_ALU | BPF_AND | BPF_X: | ||
| 907 | case BPF_ALU | BPF_AND | BPF_K: | ||
| 908 | case BPF_ALU | BPF_OR | BPF_X: | ||
| 909 | case BPF_ALU | BPF_OR | BPF_K: | ||
| 910 | case BPF_ALU | BPF_LSH | BPF_X: | ||
| 911 | case BPF_ALU | BPF_LSH | BPF_K: | ||
| 912 | case BPF_ALU | BPF_RSH | BPF_X: | ||
| 913 | case BPF_ALU | BPF_RSH | BPF_K: | ||
| 914 | case BPF_ALU | BPF_XOR | BPF_X: | ||
| 915 | case BPF_ALU | BPF_XOR | BPF_K: | ||
| 916 | case BPF_ALU | BPF_MUL | BPF_X: | ||
| 917 | case BPF_ALU | BPF_MUL | BPF_K: | ||
| 918 | case BPF_ALU | BPF_DIV | BPF_X: | ||
| 919 | case BPF_ALU | BPF_DIV | BPF_K: | ||
| 920 | case BPF_ALU | BPF_MOD | BPF_X: | ||
| 921 | case BPF_ALU | BPF_MOD | BPF_K: | ||
| 922 | case BPF_ALU | BPF_NEG: | ||
| 923 | case BPF_LD | BPF_ABS | BPF_W: | ||
| 924 | case BPF_LD | BPF_ABS | BPF_H: | ||
| 925 | case BPF_LD | BPF_ABS | BPF_B: | ||
| 926 | case BPF_LD | BPF_IND | BPF_W: | ||
| 927 | case BPF_LD | BPF_IND | BPF_H: | ||
| 928 | case BPF_LD | BPF_IND | BPF_B: | ||
| 929 | /* Check for overloaded BPF extension and | ||
| 930 | * directly convert it if found, otherwise | ||
| 931 | * just move on with mapping. | ||
| 932 | */ | ||
| 933 | if (BPF_CLASS(fp->code) == BPF_LD && | ||
| 934 | BPF_MODE(fp->code) == BPF_ABS && | ||
| 935 | convert_bpf_extensions(fp, &insn)) | ||
| 936 | break; | ||
| 937 | |||
| 938 | insn->code = fp->code; | ||
| 939 | insn->a_reg = A_REG; | ||
| 940 | insn->x_reg = X_REG; | ||
| 941 | insn->imm = fp->k; | ||
| 942 | break; | ||
| 943 | |||
| 944 | /* Jump opcodes map as-is, but offsets need adjustment. */ | ||
| 945 | case BPF_JMP | BPF_JA: | ||
| 946 | target = i + fp->k + 1; | ||
| 947 | insn->code = fp->code; | ||
| 948 | #define EMIT_JMP \ | ||
| 949 | do { \ | ||
| 950 | if (target >= len || target < 0) \ | ||
| 951 | goto err; \ | ||
| 952 | insn->off = addrs ? addrs[target] - addrs[i] - 1 : 0; \ | ||
| 953 | /* Adjust pc relative offset for 2nd or 3rd insn. */ \ | ||
| 954 | insn->off -= insn - tmp_insns; \ | ||
| 955 | } while (0) | ||
| 956 | |||
| 957 | EMIT_JMP; | ||
| 958 | break; | ||
| 959 | |||
| 960 | case BPF_JMP | BPF_JEQ | BPF_K: | ||
| 961 | case BPF_JMP | BPF_JEQ | BPF_X: | ||
| 962 | case BPF_JMP | BPF_JSET | BPF_K: | ||
| 963 | case BPF_JMP | BPF_JSET | BPF_X: | ||
| 964 | case BPF_JMP | BPF_JGT | BPF_K: | ||
| 965 | case BPF_JMP | BPF_JGT | BPF_X: | ||
| 966 | case BPF_JMP | BPF_JGE | BPF_K: | ||
| 967 | case BPF_JMP | BPF_JGE | BPF_X: | ||
| 968 | if (BPF_SRC(fp->code) == BPF_K && (int) fp->k < 0) { | ||
| 969 | /* BPF immediates are signed, zero extend | ||
| 970 | * immediate into tmp register and use it | ||
| 971 | * in compare insn. | ||
| 972 | */ | ||
| 973 | insn->code = BPF_ALU | BPF_MOV | BPF_K; | ||
| 974 | insn->a_reg = TMP_REG; | ||
| 975 | insn->imm = fp->k; | ||
| 976 | insn++; | ||
| 977 | |||
| 978 | insn->a_reg = A_REG; | ||
| 979 | insn->x_reg = TMP_REG; | ||
| 980 | bpf_src = BPF_X; | ||
| 981 | } else { | ||
| 982 | insn->a_reg = A_REG; | ||
| 983 | insn->x_reg = X_REG; | ||
| 984 | insn->imm = fp->k; | ||
| 985 | bpf_src = BPF_SRC(fp->code); | ||
| 986 | } | ||
| 987 | |||
| 988 | /* Common case where 'jump_false' is next insn. */ | ||
| 989 | if (fp->jf == 0) { | ||
| 990 | insn->code = BPF_JMP | BPF_OP(fp->code) | bpf_src; | ||
| 991 | target = i + fp->jt + 1; | ||
| 992 | EMIT_JMP; | ||
| 993 | break; | ||
| 994 | } | ||
| 995 | |||
| 996 | /* Convert JEQ into JNE when 'jump_true' is next insn. */ | ||
| 997 | if (fp->jt == 0 && BPF_OP(fp->code) == BPF_JEQ) { | ||
| 998 | insn->code = BPF_JMP | BPF_JNE | bpf_src; | ||
| 999 | target = i + fp->jf + 1; | ||
| 1000 | EMIT_JMP; | ||
| 1001 | break; | ||
| 1002 | } | ||
| 1003 | |||
| 1004 | /* Other jumps are mapped into two insns: Jxx and JA. */ | ||
| 1005 | target = i + fp->jt + 1; | ||
| 1006 | insn->code = BPF_JMP | BPF_OP(fp->code) | bpf_src; | ||
| 1007 | EMIT_JMP; | ||
| 1008 | insn++; | ||
| 1009 | |||
| 1010 | insn->code = BPF_JMP | BPF_JA; | ||
| 1011 | target = i + fp->jf + 1; | ||
| 1012 | EMIT_JMP; | ||
| 1013 | break; | ||
| 1014 | |||
| 1015 | /* ldxb 4 * ([14] & 0xf) is remaped into 6 insns. */ | ||
| 1016 | case BPF_LDX | BPF_MSH | BPF_B: | ||
| 1017 | insn->code = BPF_ALU64 | BPF_MOV | BPF_X; | ||
| 1018 | insn->a_reg = TMP_REG; | ||
| 1019 | insn->x_reg = A_REG; | ||
| 1020 | insn++; | ||
| 1021 | |||
| 1022 | insn->code = BPF_LD | BPF_ABS | BPF_B; | ||
| 1023 | insn->a_reg = A_REG; | ||
| 1024 | insn->imm = fp->k; | ||
| 1025 | insn++; | ||
| 1026 | |||
| 1027 | insn->code = BPF_ALU | BPF_AND | BPF_K; | ||
| 1028 | insn->a_reg = A_REG; | ||
| 1029 | insn->imm = 0xf; | ||
| 1030 | insn++; | ||
| 1031 | |||
| 1032 | insn->code = BPF_ALU | BPF_LSH | BPF_K; | ||
| 1033 | insn->a_reg = A_REG; | ||
| 1034 | insn->imm = 2; | ||
| 1035 | insn++; | ||
| 1036 | |||
| 1037 | insn->code = BPF_ALU64 | BPF_MOV | BPF_X; | ||
| 1038 | insn->a_reg = X_REG; | ||
| 1039 | insn->x_reg = A_REG; | ||
| 1040 | insn++; | ||
| 1041 | |||
| 1042 | insn->code = BPF_ALU64 | BPF_MOV | BPF_X; | ||
| 1043 | insn->a_reg = A_REG; | ||
| 1044 | insn->x_reg = TMP_REG; | ||
| 1045 | break; | ||
| 1046 | |||
| 1047 | /* RET_K, RET_A are remaped into 2 insns. */ | ||
| 1048 | case BPF_RET | BPF_A: | ||
| 1049 | case BPF_RET | BPF_K: | ||
| 1050 | insn->code = BPF_ALU | BPF_MOV | | ||
| 1051 | (BPF_RVAL(fp->code) == BPF_K ? | ||
| 1052 | BPF_K : BPF_X); | ||
| 1053 | insn->a_reg = 0; | ||
| 1054 | insn->x_reg = A_REG; | ||
| 1055 | insn->imm = fp->k; | ||
| 1056 | insn++; | ||
| 1057 | |||
| 1058 | insn->code = BPF_JMP | BPF_EXIT; | ||
| 1059 | break; | ||
| 1060 | |||
| 1061 | /* Store to stack. */ | ||
| 1062 | case BPF_ST: | ||
| 1063 | case BPF_STX: | ||
| 1064 | insn->code = BPF_STX | BPF_MEM | BPF_W; | ||
| 1065 | insn->a_reg = FP_REG; | ||
| 1066 | insn->x_reg = fp->code == BPF_ST ? A_REG : X_REG; | ||
| 1067 | insn->off = -(BPF_MEMWORDS - fp->k) * 4; | ||
| 1068 | break; | ||
| 1069 | |||
| 1070 | /* Load from stack. */ | ||
| 1071 | case BPF_LD | BPF_MEM: | ||
| 1072 | case BPF_LDX | BPF_MEM: | ||
| 1073 | insn->code = BPF_LDX | BPF_MEM | BPF_W; | ||
| 1074 | insn->a_reg = BPF_CLASS(fp->code) == BPF_LD ? | ||
| 1075 | A_REG : X_REG; | ||
| 1076 | insn->x_reg = FP_REG; | ||
| 1077 | insn->off = -(BPF_MEMWORDS - fp->k) * 4; | ||
| 1078 | break; | ||
| 1079 | |||
| 1080 | /* A = K or X = K */ | ||
| 1081 | case BPF_LD | BPF_IMM: | ||
| 1082 | case BPF_LDX | BPF_IMM: | ||
| 1083 | insn->code = BPF_ALU | BPF_MOV | BPF_K; | ||
| 1084 | insn->a_reg = BPF_CLASS(fp->code) == BPF_LD ? | ||
| 1085 | A_REG : X_REG; | ||
| 1086 | insn->imm = fp->k; | ||
| 1087 | break; | ||
| 1088 | |||
| 1089 | /* X = A */ | ||
| 1090 | case BPF_MISC | BPF_TAX: | ||
| 1091 | insn->code = BPF_ALU64 | BPF_MOV | BPF_X; | ||
| 1092 | insn->a_reg = X_REG; | ||
| 1093 | insn->x_reg = A_REG; | ||
| 1094 | break; | ||
| 1095 | |||
| 1096 | /* A = X */ | ||
| 1097 | case BPF_MISC | BPF_TXA: | ||
| 1098 | insn->code = BPF_ALU64 | BPF_MOV | BPF_X; | ||
| 1099 | insn->a_reg = A_REG; | ||
| 1100 | insn->x_reg = X_REG; | ||
| 1101 | break; | ||
| 1102 | |||
| 1103 | /* A = skb->len or X = skb->len */ | ||
| 1104 | case BPF_LD | BPF_W | BPF_LEN: | ||
| 1105 | case BPF_LDX | BPF_W | BPF_LEN: | ||
| 1106 | insn->code = BPF_LDX | BPF_MEM | BPF_W; | ||
| 1107 | insn->a_reg = BPF_CLASS(fp->code) == BPF_LD ? | ||
| 1108 | A_REG : X_REG; | ||
| 1109 | insn->x_reg = CTX_REG; | ||
| 1110 | insn->off = offsetof(struct sk_buff, len); | ||
| 1111 | break; | ||
| 1112 | |||
| 1113 | /* access seccomp_data fields */ | ||
| 1114 | case BPF_LDX | BPF_ABS | BPF_W: | ||
| 1115 | insn->code = BPF_LDX | BPF_MEM | BPF_W; | ||
| 1116 | insn->a_reg = A_REG; | ||
| 1117 | insn->x_reg = CTX_REG; | ||
| 1118 | insn->off = fp->k; | ||
| 1119 | break; | ||
| 1120 | |||
| 393 | default: | 1121 | default: |
| 394 | WARN_RATELIMIT(1, "Unknown code:%u jt:%u tf:%u k:%u\n", | 1122 | goto err; |
| 395 | fentry->code, fentry->jt, | ||
| 396 | fentry->jf, fentry->k); | ||
| 397 | return 0; | ||
| 398 | } | 1123 | } |
| 1124 | |||
| 1125 | insn++; | ||
| 1126 | if (new_prog) | ||
| 1127 | memcpy(new_insn, tmp_insns, | ||
| 1128 | sizeof(*insn) * (insn - tmp_insns)); | ||
| 1129 | |||
| 1130 | new_insn += insn - tmp_insns; | ||
| 399 | } | 1131 | } |
| 400 | 1132 | ||
| 1133 | if (!new_prog) { | ||
| 1134 | /* Only calculating new length. */ | ||
| 1135 | *new_len = new_insn - new_prog; | ||
| 1136 | return 0; | ||
| 1137 | } | ||
| 1138 | |||
| 1139 | pass++; | ||
| 1140 | if (new_flen != new_insn - new_prog) { | ||
| 1141 | new_flen = new_insn - new_prog; | ||
| 1142 | if (pass > 2) | ||
| 1143 | goto err; | ||
| 1144 | |||
| 1145 | goto do_pass; | ||
| 1146 | } | ||
| 1147 | |||
| 1148 | kfree(addrs); | ||
| 1149 | BUG_ON(*new_len != new_flen); | ||
| 401 | return 0; | 1150 | return 0; |
| 1151 | err: | ||
| 1152 | kfree(addrs); | ||
| 1153 | return -EINVAL; | ||
| 402 | } | 1154 | } |
| 403 | EXPORT_SYMBOL(sk_run_filter); | ||
| 404 | 1155 | ||
| 405 | /* | 1156 | /* Security: |
| 406 | * Security : | 1157 | * |
| 407 | * A BPF program is able to use 16 cells of memory to store intermediate | 1158 | * A BPF program is able to use 16 cells of memory to store intermediate |
| 408 | * values (check u32 mem[BPF_MEMWORDS] in sk_run_filter()) | 1159 | * values (check u32 mem[BPF_MEMWORDS] in sk_run_filter()). |
| 1160 | * | ||
| 409 | * As we dont want to clear mem[] array for each packet going through | 1161 | * As we dont want to clear mem[] array for each packet going through |
| 410 | * sk_run_filter(), we check that filter loaded by user never try to read | 1162 | * sk_run_filter(), we check that filter loaded by user never try to read |
| 411 | * a cell if not previously written, and we check all branches to be sure | 1163 | * a cell if not previously written, and we check all branches to be sure |
| @@ -629,30 +1381,197 @@ int sk_chk_filter(struct sock_filter *filter, unsigned int flen) | |||
| 629 | } | 1381 | } |
| 630 | EXPORT_SYMBOL(sk_chk_filter); | 1382 | EXPORT_SYMBOL(sk_chk_filter); |
| 631 | 1383 | ||
| 1384 | static int sk_store_orig_filter(struct sk_filter *fp, | ||
| 1385 | const struct sock_fprog *fprog) | ||
| 1386 | { | ||
| 1387 | unsigned int fsize = sk_filter_proglen(fprog); | ||
| 1388 | struct sock_fprog_kern *fkprog; | ||
| 1389 | |||
| 1390 | fp->orig_prog = kmalloc(sizeof(*fkprog), GFP_KERNEL); | ||
| 1391 | if (!fp->orig_prog) | ||
| 1392 | return -ENOMEM; | ||
| 1393 | |||
| 1394 | fkprog = fp->orig_prog; | ||
| 1395 | fkprog->len = fprog->len; | ||
| 1396 | fkprog->filter = kmemdup(fp->insns, fsize, GFP_KERNEL); | ||
| 1397 | if (!fkprog->filter) { | ||
| 1398 | kfree(fp->orig_prog); | ||
| 1399 | return -ENOMEM; | ||
| 1400 | } | ||
| 1401 | |||
| 1402 | return 0; | ||
| 1403 | } | ||
| 1404 | |||
| 1405 | static void sk_release_orig_filter(struct sk_filter *fp) | ||
| 1406 | { | ||
| 1407 | struct sock_fprog_kern *fprog = fp->orig_prog; | ||
| 1408 | |||
| 1409 | if (fprog) { | ||
| 1410 | kfree(fprog->filter); | ||
| 1411 | kfree(fprog); | ||
| 1412 | } | ||
| 1413 | } | ||
| 1414 | |||
| 632 | /** | 1415 | /** |
| 633 | * sk_filter_release_rcu - Release a socket filter by rcu_head | 1416 | * sk_filter_release_rcu - Release a socket filter by rcu_head |
| 634 | * @rcu: rcu_head that contains the sk_filter to free | 1417 | * @rcu: rcu_head that contains the sk_filter to free |
| 635 | */ | 1418 | */ |
| 636 | void sk_filter_release_rcu(struct rcu_head *rcu) | 1419 | static void sk_filter_release_rcu(struct rcu_head *rcu) |
| 637 | { | 1420 | { |
| 638 | struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu); | 1421 | struct sk_filter *fp = container_of(rcu, struct sk_filter, rcu); |
| 639 | 1422 | ||
| 1423 | sk_release_orig_filter(fp); | ||
| 640 | bpf_jit_free(fp); | 1424 | bpf_jit_free(fp); |
| 641 | } | 1425 | } |
| 642 | EXPORT_SYMBOL(sk_filter_release_rcu); | ||
| 643 | 1426 | ||
| 644 | static int __sk_prepare_filter(struct sk_filter *fp) | 1427 | /** |
| 1428 | * sk_filter_release - release a socket filter | ||
| 1429 | * @fp: filter to remove | ||
| 1430 | * | ||
| 1431 | * Remove a filter from a socket and release its resources. | ||
| 1432 | */ | ||
| 1433 | static void sk_filter_release(struct sk_filter *fp) | ||
| 1434 | { | ||
| 1435 | if (atomic_dec_and_test(&fp->refcnt)) | ||
| 1436 | call_rcu(&fp->rcu, sk_filter_release_rcu); | ||
| 1437 | } | ||
| 1438 | |||
| 1439 | void sk_filter_uncharge(struct sock *sk, struct sk_filter *fp) | ||
| 1440 | { | ||
| 1441 | atomic_sub(sk_filter_size(fp->len), &sk->sk_omem_alloc); | ||
| 1442 | sk_filter_release(fp); | ||
| 1443 | } | ||
| 1444 | |||
| 1445 | void sk_filter_charge(struct sock *sk, struct sk_filter *fp) | ||
| 1446 | { | ||
| 1447 | atomic_inc(&fp->refcnt); | ||
| 1448 | atomic_add(sk_filter_size(fp->len), &sk->sk_omem_alloc); | ||
| 1449 | } | ||
| 1450 | |||
| 1451 | static struct sk_filter *__sk_migrate_realloc(struct sk_filter *fp, | ||
| 1452 | struct sock *sk, | ||
| 1453 | unsigned int len) | ||
| 1454 | { | ||
| 1455 | struct sk_filter *fp_new; | ||
| 1456 | |||
| 1457 | if (sk == NULL) | ||
| 1458 | return krealloc(fp, len, GFP_KERNEL); | ||
| 1459 | |||
| 1460 | fp_new = sock_kmalloc(sk, len, GFP_KERNEL); | ||
| 1461 | if (fp_new) { | ||
| 1462 | memcpy(fp_new, fp, sizeof(struct sk_filter)); | ||
| 1463 | /* As we're kepping orig_prog in fp_new along, | ||
| 1464 | * we need to make sure we're not evicting it | ||
| 1465 | * from the old fp. | ||
| 1466 | */ | ||
| 1467 | fp->orig_prog = NULL; | ||
| 1468 | sk_filter_uncharge(sk, fp); | ||
| 1469 | } | ||
| 1470 | |||
| 1471 | return fp_new; | ||
| 1472 | } | ||
| 1473 | |||
| 1474 | static struct sk_filter *__sk_migrate_filter(struct sk_filter *fp, | ||
| 1475 | struct sock *sk) | ||
| 1476 | { | ||
| 1477 | struct sock_filter *old_prog; | ||
| 1478 | struct sk_filter *old_fp; | ||
| 1479 | int i, err, new_len, old_len = fp->len; | ||
| 1480 | |||
| 1481 | /* We are free to overwrite insns et al right here as it | ||
| 1482 | * won't be used at this point in time anymore internally | ||
| 1483 | * after the migration to the internal BPF instruction | ||
| 1484 | * representation. | ||
| 1485 | */ | ||
| 1486 | BUILD_BUG_ON(sizeof(struct sock_filter) != | ||
| 1487 | sizeof(struct sock_filter_int)); | ||
| 1488 | |||
| 1489 | /* For now, we need to unfiddle BPF_S_* identifiers in place. | ||
| 1490 | * This can sooner or later on be subject to removal, e.g. when | ||
| 1491 | * JITs have been converted. | ||
| 1492 | */ | ||
| 1493 | for (i = 0; i < fp->len; i++) | ||
| 1494 | sk_decode_filter(&fp->insns[i], &fp->insns[i]); | ||
| 1495 | |||
| 1496 | /* Conversion cannot happen on overlapping memory areas, | ||
| 1497 | * so we need to keep the user BPF around until the 2nd | ||
| 1498 | * pass. At this time, the user BPF is stored in fp->insns. | ||
| 1499 | */ | ||
| 1500 | old_prog = kmemdup(fp->insns, old_len * sizeof(struct sock_filter), | ||
| 1501 | GFP_KERNEL); | ||
| 1502 | if (!old_prog) { | ||
| 1503 | err = -ENOMEM; | ||
| 1504 | goto out_err; | ||
| 1505 | } | ||
| 1506 | |||
| 1507 | /* 1st pass: calculate the new program length. */ | ||
| 1508 | err = sk_convert_filter(old_prog, old_len, NULL, &new_len); | ||
| 1509 | if (err) | ||
| 1510 | goto out_err_free; | ||
| 1511 | |||
| 1512 | /* Expand fp for appending the new filter representation. */ | ||
| 1513 | old_fp = fp; | ||
| 1514 | fp = __sk_migrate_realloc(old_fp, sk, sk_filter_size(new_len)); | ||
| 1515 | if (!fp) { | ||
| 1516 | /* The old_fp is still around in case we couldn't | ||
| 1517 | * allocate new memory, so uncharge on that one. | ||
| 1518 | */ | ||
| 1519 | fp = old_fp; | ||
| 1520 | err = -ENOMEM; | ||
| 1521 | goto out_err_free; | ||
| 1522 | } | ||
| 1523 | |||
| 1524 | fp->bpf_func = sk_run_filter_int_skb; | ||
| 1525 | fp->len = new_len; | ||
| 1526 | |||
| 1527 | /* 2nd pass: remap sock_filter insns into sock_filter_int insns. */ | ||
| 1528 | err = sk_convert_filter(old_prog, old_len, fp->insnsi, &new_len); | ||
| 1529 | if (err) | ||
| 1530 | /* 2nd sk_convert_filter() can fail only if it fails | ||
| 1531 | * to allocate memory, remapping must succeed. Note, | ||
| 1532 | * that at this time old_fp has already been released | ||
| 1533 | * by __sk_migrate_realloc(). | ||
| 1534 | */ | ||
| 1535 | goto out_err_free; | ||
| 1536 | |||
| 1537 | kfree(old_prog); | ||
| 1538 | return fp; | ||
| 1539 | |||
| 1540 | out_err_free: | ||
| 1541 | kfree(old_prog); | ||
| 1542 | out_err: | ||
| 1543 | /* Rollback filter setup. */ | ||
| 1544 | if (sk != NULL) | ||
| 1545 | sk_filter_uncharge(sk, fp); | ||
| 1546 | else | ||
| 1547 | kfree(fp); | ||
| 1548 | return ERR_PTR(err); | ||
| 1549 | } | ||
| 1550 | |||
| 1551 | static struct sk_filter *__sk_prepare_filter(struct sk_filter *fp, | ||
| 1552 | struct sock *sk) | ||
| 645 | { | 1553 | { |
| 646 | int err; | 1554 | int err; |
| 647 | 1555 | ||
| 648 | fp->bpf_func = sk_run_filter; | 1556 | fp->bpf_func = NULL; |
| 1557 | fp->jited = 0; | ||
| 649 | 1558 | ||
| 650 | err = sk_chk_filter(fp->insns, fp->len); | 1559 | err = sk_chk_filter(fp->insns, fp->len); |
| 651 | if (err) | 1560 | if (err) |
| 652 | return err; | 1561 | return ERR_PTR(err); |
| 653 | 1562 | ||
| 1563 | /* Probe if we can JIT compile the filter and if so, do | ||
| 1564 | * the compilation of the filter. | ||
| 1565 | */ | ||
| 654 | bpf_jit_compile(fp); | 1566 | bpf_jit_compile(fp); |
| 655 | return 0; | 1567 | |
| 1568 | /* JIT compiler couldn't process this filter, so do the | ||
| 1569 | * internal BPF translation for the optimized interpreter. | ||
| 1570 | */ | ||
| 1571 | if (!fp->jited) | ||
| 1572 | fp = __sk_migrate_filter(fp, sk); | ||
| 1573 | |||
| 1574 | return fp; | ||
| 656 | } | 1575 | } |
| 657 | 1576 | ||
| 658 | /** | 1577 | /** |
| @@ -668,9 +1587,8 @@ static int __sk_prepare_filter(struct sk_filter *fp) | |||
| 668 | int sk_unattached_filter_create(struct sk_filter **pfp, | 1587 | int sk_unattached_filter_create(struct sk_filter **pfp, |
| 669 | struct sock_fprog *fprog) | 1588 | struct sock_fprog *fprog) |
| 670 | { | 1589 | { |
| 1590 | unsigned int fsize = sk_filter_proglen(fprog); | ||
| 671 | struct sk_filter *fp; | 1591 | struct sk_filter *fp; |
| 672 | unsigned int fsize = sizeof(struct sock_filter) * fprog->len; | ||
| 673 | int err; | ||
| 674 | 1592 | ||
| 675 | /* Make sure new filter is there and in the right amounts. */ | 1593 | /* Make sure new filter is there and in the right amounts. */ |
| 676 | if (fprog->filter == NULL) | 1594 | if (fprog->filter == NULL) |
| @@ -679,20 +1597,26 @@ int sk_unattached_filter_create(struct sk_filter **pfp, | |||
| 679 | fp = kmalloc(sk_filter_size(fprog->len), GFP_KERNEL); | 1597 | fp = kmalloc(sk_filter_size(fprog->len), GFP_KERNEL); |
| 680 | if (!fp) | 1598 | if (!fp) |
| 681 | return -ENOMEM; | 1599 | return -ENOMEM; |
| 1600 | |||
| 682 | memcpy(fp->insns, fprog->filter, fsize); | 1601 | memcpy(fp->insns, fprog->filter, fsize); |
| 683 | 1602 | ||
| 684 | atomic_set(&fp->refcnt, 1); | 1603 | atomic_set(&fp->refcnt, 1); |
| 685 | fp->len = fprog->len; | 1604 | fp->len = fprog->len; |
| 1605 | /* Since unattached filters are not copied back to user | ||
| 1606 | * space through sk_get_filter(), we do not need to hold | ||
| 1607 | * a copy here, and can spare us the work. | ||
| 1608 | */ | ||
| 1609 | fp->orig_prog = NULL; | ||
| 686 | 1610 | ||
| 687 | err = __sk_prepare_filter(fp); | 1611 | /* __sk_prepare_filter() already takes care of uncharging |
| 688 | if (err) | 1612 | * memory in case something goes wrong. |
| 689 | goto free_mem; | 1613 | */ |
| 1614 | fp = __sk_prepare_filter(fp, NULL); | ||
| 1615 | if (IS_ERR(fp)) | ||
| 1616 | return PTR_ERR(fp); | ||
| 690 | 1617 | ||
| 691 | *pfp = fp; | 1618 | *pfp = fp; |
| 692 | return 0; | 1619 | return 0; |
| 693 | free_mem: | ||
| 694 | kfree(fp); | ||
| 695 | return err; | ||
| 696 | } | 1620 | } |
| 697 | EXPORT_SYMBOL_GPL(sk_unattached_filter_create); | 1621 | EXPORT_SYMBOL_GPL(sk_unattached_filter_create); |
| 698 | 1622 | ||
| @@ -715,7 +1639,7 @@ EXPORT_SYMBOL_GPL(sk_unattached_filter_destroy); | |||
| 715 | int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) | 1639 | int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) |
| 716 | { | 1640 | { |
| 717 | struct sk_filter *fp, *old_fp; | 1641 | struct sk_filter *fp, *old_fp; |
| 718 | unsigned int fsize = sizeof(struct sock_filter) * fprog->len; | 1642 | unsigned int fsize = sk_filter_proglen(fprog); |
| 719 | unsigned int sk_fsize = sk_filter_size(fprog->len); | 1643 | unsigned int sk_fsize = sk_filter_size(fprog->len); |
| 720 | int err; | 1644 | int err; |
| 721 | 1645 | ||
| @@ -729,6 +1653,7 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) | |||
| 729 | fp = sock_kmalloc(sk, sk_fsize, GFP_KERNEL); | 1653 | fp = sock_kmalloc(sk, sk_fsize, GFP_KERNEL); |
| 730 | if (!fp) | 1654 | if (!fp) |
| 731 | return -ENOMEM; | 1655 | return -ENOMEM; |
| 1656 | |||
| 732 | if (copy_from_user(fp->insns, fprog->filter, fsize)) { | 1657 | if (copy_from_user(fp->insns, fprog->filter, fsize)) { |
| 733 | sock_kfree_s(sk, fp, sk_fsize); | 1658 | sock_kfree_s(sk, fp, sk_fsize); |
| 734 | return -EFAULT; | 1659 | return -EFAULT; |
| @@ -737,18 +1662,26 @@ int sk_attach_filter(struct sock_fprog *fprog, struct sock *sk) | |||
| 737 | atomic_set(&fp->refcnt, 1); | 1662 | atomic_set(&fp->refcnt, 1); |
| 738 | fp->len = fprog->len; | 1663 | fp->len = fprog->len; |
| 739 | 1664 | ||
| 740 | err = __sk_prepare_filter(fp); | 1665 | err = sk_store_orig_filter(fp, fprog); |
| 741 | if (err) { | 1666 | if (err) { |
| 742 | sk_filter_uncharge(sk, fp); | 1667 | sk_filter_uncharge(sk, fp); |
| 743 | return err; | 1668 | return -ENOMEM; |
| 744 | } | 1669 | } |
| 745 | 1670 | ||
| 1671 | /* __sk_prepare_filter() already takes care of uncharging | ||
| 1672 | * memory in case something goes wrong. | ||
| 1673 | */ | ||
| 1674 | fp = __sk_prepare_filter(fp, sk); | ||
| 1675 | if (IS_ERR(fp)) | ||
| 1676 | return PTR_ERR(fp); | ||
| 1677 | |||
| 746 | old_fp = rcu_dereference_protected(sk->sk_filter, | 1678 | old_fp = rcu_dereference_protected(sk->sk_filter, |
| 747 | sock_owned_by_user(sk)); | 1679 | sock_owned_by_user(sk)); |
| 748 | rcu_assign_pointer(sk->sk_filter, fp); | 1680 | rcu_assign_pointer(sk->sk_filter, fp); |
| 749 | 1681 | ||
| 750 | if (old_fp) | 1682 | if (old_fp) |
| 751 | sk_filter_uncharge(sk, old_fp); | 1683 | sk_filter_uncharge(sk, old_fp); |
| 1684 | |||
| 752 | return 0; | 1685 | return 0; |
| 753 | } | 1686 | } |
| 754 | EXPORT_SYMBOL_GPL(sk_attach_filter); | 1687 | EXPORT_SYMBOL_GPL(sk_attach_filter); |
| @@ -768,6 +1701,7 @@ int sk_detach_filter(struct sock *sk) | |||
| 768 | sk_filter_uncharge(sk, filter); | 1701 | sk_filter_uncharge(sk, filter); |
| 769 | ret = 0; | 1702 | ret = 0; |
| 770 | } | 1703 | } |
| 1704 | |||
| 771 | return ret; | 1705 | return ret; |
| 772 | } | 1706 | } |
| 773 | EXPORT_SYMBOL_GPL(sk_detach_filter); | 1707 | EXPORT_SYMBOL_GPL(sk_detach_filter); |
| @@ -809,7 +1743,6 @@ void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to) | |||
| 809 | [BPF_S_ANC_RXHASH] = BPF_LD|BPF_B|BPF_ABS, | 1743 | [BPF_S_ANC_RXHASH] = BPF_LD|BPF_B|BPF_ABS, |
| 810 | [BPF_S_ANC_CPU] = BPF_LD|BPF_B|BPF_ABS, | 1744 | [BPF_S_ANC_CPU] = BPF_LD|BPF_B|BPF_ABS, |
| 811 | [BPF_S_ANC_ALU_XOR_X] = BPF_LD|BPF_B|BPF_ABS, | 1745 | [BPF_S_ANC_ALU_XOR_X] = BPF_LD|BPF_B|BPF_ABS, |
| 812 | [BPF_S_ANC_SECCOMP_LD_W] = BPF_LD|BPF_B|BPF_ABS, | ||
| 813 | [BPF_S_ANC_VLAN_TAG] = BPF_LD|BPF_B|BPF_ABS, | 1746 | [BPF_S_ANC_VLAN_TAG] = BPF_LD|BPF_B|BPF_ABS, |
| 814 | [BPF_S_ANC_VLAN_TAG_PRESENT] = BPF_LD|BPF_B|BPF_ABS, | 1747 | [BPF_S_ANC_VLAN_TAG_PRESENT] = BPF_LD|BPF_B|BPF_ABS, |
| 815 | [BPF_S_ANC_PAY_OFFSET] = BPF_LD|BPF_B|BPF_ABS, | 1748 | [BPF_S_ANC_PAY_OFFSET] = BPF_LD|BPF_B|BPF_ABS, |
| @@ -850,34 +1783,41 @@ void sk_decode_filter(struct sock_filter *filt, struct sock_filter *to) | |||
| 850 | to->k = filt->k; | 1783 | to->k = filt->k; |
| 851 | } | 1784 | } |
| 852 | 1785 | ||
| 853 | int sk_get_filter(struct sock *sk, struct sock_filter __user *ubuf, unsigned int len) | 1786 | int sk_get_filter(struct sock *sk, struct sock_filter __user *ubuf, |
| 1787 | unsigned int len) | ||
| 854 | { | 1788 | { |
| 1789 | struct sock_fprog_kern *fprog; | ||
| 855 | struct sk_filter *filter; | 1790 | struct sk_filter *filter; |
| 856 | int i, ret; | 1791 | int ret = 0; |
| 857 | 1792 | ||
| 858 | lock_sock(sk); | 1793 | lock_sock(sk); |
| 859 | filter = rcu_dereference_protected(sk->sk_filter, | 1794 | filter = rcu_dereference_protected(sk->sk_filter, |
| 860 | sock_owned_by_user(sk)); | 1795 | sock_owned_by_user(sk)); |
| 861 | ret = 0; | ||
| 862 | if (!filter) | 1796 | if (!filter) |
| 863 | goto out; | 1797 | goto out; |
| 864 | ret = filter->len; | 1798 | |
| 1799 | /* We're copying the filter that has been originally attached, | ||
| 1800 | * so no conversion/decode needed anymore. | ||
| 1801 | */ | ||
| 1802 | fprog = filter->orig_prog; | ||
| 1803 | |||
| 1804 | ret = fprog->len; | ||
| 865 | if (!len) | 1805 | if (!len) |
| 1806 | /* User space only enquires number of filter blocks. */ | ||
| 866 | goto out; | 1807 | goto out; |
| 1808 | |||
| 867 | ret = -EINVAL; | 1809 | ret = -EINVAL; |
| 868 | if (len < filter->len) | 1810 | if (len < fprog->len) |
| 869 | goto out; | 1811 | goto out; |
| 870 | 1812 | ||
| 871 | ret = -EFAULT; | 1813 | ret = -EFAULT; |
| 872 | for (i = 0; i < filter->len; i++) { | 1814 | if (copy_to_user(ubuf, fprog->filter, sk_filter_proglen(fprog))) |
| 873 | struct sock_filter fb; | 1815 | goto out; |
| 874 | |||
| 875 | sk_decode_filter(&filter->insns[i], &fb); | ||
| 876 | if (copy_to_user(&ubuf[i], &fb, sizeof(fb))) | ||
| 877 | goto out; | ||
| 878 | } | ||
| 879 | 1816 | ||
| 880 | ret = filter->len; | 1817 | /* Instead of bytes, the API requests to return the number |
| 1818 | * of filter blocks. | ||
| 1819 | */ | ||
| 1820 | ret = fprog->len; | ||
| 881 | out: | 1821 | out: |
| 882 | release_sock(sk); | 1822 | release_sock(sk); |
| 883 | return ret; | 1823 | return ret; |
diff --git a/net/core/flow.c b/net/core/flow.c index dfa602ceb8cd..a0348fde1fdf 100644 --- a/net/core/flow.c +++ b/net/core/flow.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <net/flow.h> | 24 | #include <net/flow.h> |
| 25 | #include <linux/atomic.h> | 25 | #include <linux/atomic.h> |
| 26 | #include <linux/security.h> | 26 | #include <linux/security.h> |
| 27 | #include <net/net_namespace.h> | ||
| 27 | 28 | ||
| 28 | struct flow_cache_entry { | 29 | struct flow_cache_entry { |
| 29 | union { | 30 | union { |
| @@ -38,37 +39,14 @@ struct flow_cache_entry { | |||
| 38 | struct flow_cache_object *object; | 39 | struct flow_cache_object *object; |
| 39 | }; | 40 | }; |
| 40 | 41 | ||
| 41 | struct flow_cache_percpu { | ||
| 42 | struct hlist_head *hash_table; | ||
| 43 | int hash_count; | ||
| 44 | u32 hash_rnd; | ||
| 45 | int hash_rnd_recalc; | ||
| 46 | struct tasklet_struct flush_tasklet; | ||
| 47 | }; | ||
| 48 | |||
| 49 | struct flow_flush_info { | 42 | struct flow_flush_info { |
| 50 | struct flow_cache *cache; | 43 | struct flow_cache *cache; |
| 51 | atomic_t cpuleft; | 44 | atomic_t cpuleft; |
| 52 | struct completion completion; | 45 | struct completion completion; |
| 53 | }; | 46 | }; |
| 54 | 47 | ||
| 55 | struct flow_cache { | ||
| 56 | u32 hash_shift; | ||
| 57 | struct flow_cache_percpu __percpu *percpu; | ||
| 58 | struct notifier_block hotcpu_notifier; | ||
| 59 | int low_watermark; | ||
| 60 | int high_watermark; | ||
| 61 | struct timer_list rnd_timer; | ||
| 62 | }; | ||
| 63 | |||
| 64 | atomic_t flow_cache_genid = ATOMIC_INIT(0); | ||
| 65 | EXPORT_SYMBOL(flow_cache_genid); | ||
| 66 | static struct flow_cache flow_cache_global; | ||
| 67 | static struct kmem_cache *flow_cachep __read_mostly; | 48 | static struct kmem_cache *flow_cachep __read_mostly; |
| 68 | 49 | ||
| 69 | static DEFINE_SPINLOCK(flow_cache_gc_lock); | ||
| 70 | static LIST_HEAD(flow_cache_gc_list); | ||
| 71 | |||
| 72 | #define flow_cache_hash_size(cache) (1 << (cache)->hash_shift) | 50 | #define flow_cache_hash_size(cache) (1 << (cache)->hash_shift) |
| 73 | #define FLOW_HASH_RND_PERIOD (10 * 60 * HZ) | 51 | #define FLOW_HASH_RND_PERIOD (10 * 60 * HZ) |
| 74 | 52 | ||
| @@ -84,16 +62,18 @@ static void flow_cache_new_hashrnd(unsigned long arg) | |||
| 84 | add_timer(&fc->rnd_timer); | 62 | add_timer(&fc->rnd_timer); |
| 85 | } | 63 | } |
| 86 | 64 | ||
| 87 | static int flow_entry_valid(struct flow_cache_entry *fle) | 65 | static int flow_entry_valid(struct flow_cache_entry *fle, |
| 66 | struct netns_xfrm *xfrm) | ||
| 88 | { | 67 | { |
| 89 | if (atomic_read(&flow_cache_genid) != fle->genid) | 68 | if (atomic_read(&xfrm->flow_cache_genid) != fle->genid) |
| 90 | return 0; | 69 | return 0; |
| 91 | if (fle->object && !fle->object->ops->check(fle->object)) | 70 | if (fle->object && !fle->object->ops->check(fle->object)) |
| 92 | return 0; | 71 | return 0; |
| 93 | return 1; | 72 | return 1; |
| 94 | } | 73 | } |
| 95 | 74 | ||
| 96 | static void flow_entry_kill(struct flow_cache_entry *fle) | 75 | static void flow_entry_kill(struct flow_cache_entry *fle, |
| 76 | struct netns_xfrm *xfrm) | ||
| 97 | { | 77 | { |
| 98 | if (fle->object) | 78 | if (fle->object) |
| 99 | fle->object->ops->delete(fle->object); | 79 | fle->object->ops->delete(fle->object); |
| @@ -104,26 +84,28 @@ static void flow_cache_gc_task(struct work_struct *work) | |||
| 104 | { | 84 | { |
| 105 | struct list_head gc_list; | 85 | struct list_head gc_list; |
| 106 | struct flow_cache_entry *fce, *n; | 86 | struct flow_cache_entry *fce, *n; |
| 87 | struct netns_xfrm *xfrm = container_of(work, struct netns_xfrm, | ||
| 88 | flow_cache_gc_work); | ||
| 107 | 89 | ||
| 108 | INIT_LIST_HEAD(&gc_list); | 90 | INIT_LIST_HEAD(&gc_list); |
| 109 | spin_lock_bh(&flow_cache_gc_lock); | 91 | spin_lock_bh(&xfrm->flow_cache_gc_lock); |
| 110 | list_splice_tail_init(&flow_cache_gc_list, &gc_list); | 92 | list_splice_tail_init(&xfrm->flow_cache_gc_list, &gc_list); |
| 111 | spin_unlock_bh(&flow_cache_gc_lock); | 93 | spin_unlock_bh(&xfrm->flow_cache_gc_lock); |
| 112 | 94 | ||
| 113 | list_for_each_entry_safe(fce, n, &gc_list, u.gc_list) | 95 | list_for_each_entry_safe(fce, n, &gc_list, u.gc_list) |
| 114 | flow_entry_kill(fce); | 96 | flow_entry_kill(fce, xfrm); |
| 115 | } | 97 | } |
| 116 | static DECLARE_WORK(flow_cache_gc_work, flow_cache_gc_task); | ||
| 117 | 98 | ||
| 118 | static void flow_cache_queue_garbage(struct flow_cache_percpu *fcp, | 99 | static void flow_cache_queue_garbage(struct flow_cache_percpu *fcp, |
| 119 | int deleted, struct list_head *gc_list) | 100 | int deleted, struct list_head *gc_list, |
| 101 | struct netns_xfrm *xfrm) | ||
| 120 | { | 102 | { |
| 121 | if (deleted) { | 103 | if (deleted) { |
| 122 | fcp->hash_count -= deleted; | 104 | fcp->hash_count -= deleted; |
| 123 | spin_lock_bh(&flow_cache_gc_lock); | 105 | spin_lock_bh(&xfrm->flow_cache_gc_lock); |
| 124 | list_splice_tail(gc_list, &flow_cache_gc_list); | 106 | list_splice_tail(gc_list, &xfrm->flow_cache_gc_list); |
| 125 | spin_unlock_bh(&flow_cache_gc_lock); | 107 | spin_unlock_bh(&xfrm->flow_cache_gc_lock); |
| 126 | schedule_work(&flow_cache_gc_work); | 108 | schedule_work(&xfrm->flow_cache_gc_work); |
| 127 | } | 109 | } |
| 128 | } | 110 | } |
| 129 | 111 | ||
| @@ -135,6 +117,8 @@ static void __flow_cache_shrink(struct flow_cache *fc, | |||
| 135 | struct hlist_node *tmp; | 117 | struct hlist_node *tmp; |
| 136 | LIST_HEAD(gc_list); | 118 | LIST_HEAD(gc_list); |
| 137 | int i, deleted = 0; | 119 | int i, deleted = 0; |
| 120 | struct netns_xfrm *xfrm = container_of(fc, struct netns_xfrm, | ||
| 121 | flow_cache_global); | ||
| 138 | 122 | ||
| 139 | for (i = 0; i < flow_cache_hash_size(fc); i++) { | 123 | for (i = 0; i < flow_cache_hash_size(fc); i++) { |
| 140 | int saved = 0; | 124 | int saved = 0; |
| @@ -142,7 +126,7 @@ static void __flow_cache_shrink(struct flow_cache *fc, | |||
| 142 | hlist_for_each_entry_safe(fle, tmp, | 126 | hlist_for_each_entry_safe(fle, tmp, |
| 143 | &fcp->hash_table[i], u.hlist) { | 127 | &fcp->hash_table[i], u.hlist) { |
| 144 | if (saved < shrink_to && | 128 | if (saved < shrink_to && |
| 145 | flow_entry_valid(fle)) { | 129 | flow_entry_valid(fle, xfrm)) { |
| 146 | saved++; | 130 | saved++; |
| 147 | } else { | 131 | } else { |
| 148 | deleted++; | 132 | deleted++; |
| @@ -152,7 +136,7 @@ static void __flow_cache_shrink(struct flow_cache *fc, | |||
| 152 | } | 136 | } |
| 153 | } | 137 | } |
| 154 | 138 | ||
| 155 | flow_cache_queue_garbage(fcp, deleted, &gc_list); | 139 | flow_cache_queue_garbage(fcp, deleted, &gc_list, xfrm); |
| 156 | } | 140 | } |
| 157 | 141 | ||
| 158 | static void flow_cache_shrink(struct flow_cache *fc, | 142 | static void flow_cache_shrink(struct flow_cache *fc, |
| @@ -208,7 +192,7 @@ struct flow_cache_object * | |||
| 208 | flow_cache_lookup(struct net *net, const struct flowi *key, u16 family, u8 dir, | 192 | flow_cache_lookup(struct net *net, const struct flowi *key, u16 family, u8 dir, |
| 209 | flow_resolve_t resolver, void *ctx) | 193 | flow_resolve_t resolver, void *ctx) |
| 210 | { | 194 | { |
| 211 | struct flow_cache *fc = &flow_cache_global; | 195 | struct flow_cache *fc = &net->xfrm.flow_cache_global; |
| 212 | struct flow_cache_percpu *fcp; | 196 | struct flow_cache_percpu *fcp; |
| 213 | struct flow_cache_entry *fle, *tfle; | 197 | struct flow_cache_entry *fle, *tfle; |
| 214 | struct flow_cache_object *flo; | 198 | struct flow_cache_object *flo; |
| @@ -258,7 +242,7 @@ flow_cache_lookup(struct net *net, const struct flowi *key, u16 family, u8 dir, | |||
| 258 | hlist_add_head(&fle->u.hlist, &fcp->hash_table[hash]); | 242 | hlist_add_head(&fle->u.hlist, &fcp->hash_table[hash]); |
| 259 | fcp->hash_count++; | 243 | fcp->hash_count++; |
| 260 | } | 244 | } |
| 261 | } else if (likely(fle->genid == atomic_read(&flow_cache_genid))) { | 245 | } else if (likely(fle->genid == atomic_read(&net->xfrm.flow_cache_genid))) { |
| 262 | flo = fle->object; | 246 | flo = fle->object; |
| 263 | if (!flo) | 247 | if (!flo) |
| 264 | goto ret_object; | 248 | goto ret_object; |
| @@ -279,7 +263,7 @@ nocache: | |||
| 279 | } | 263 | } |
| 280 | flo = resolver(net, key, family, dir, flo, ctx); | 264 | flo = resolver(net, key, family, dir, flo, ctx); |
| 281 | if (fle) { | 265 | if (fle) { |
| 282 | fle->genid = atomic_read(&flow_cache_genid); | 266 | fle->genid = atomic_read(&net->xfrm.flow_cache_genid); |
| 283 | if (!IS_ERR(flo)) | 267 | if (!IS_ERR(flo)) |
| 284 | fle->object = flo; | 268 | fle->object = flo; |
| 285 | else | 269 | else |
| @@ -303,12 +287,14 @@ static void flow_cache_flush_tasklet(unsigned long data) | |||
| 303 | struct hlist_node *tmp; | 287 | struct hlist_node *tmp; |
| 304 | LIST_HEAD(gc_list); | 288 | LIST_HEAD(gc_list); |
| 305 | int i, deleted = 0; | 289 | int i, deleted = 0; |
| 290 | struct netns_xfrm *xfrm = container_of(fc, struct netns_xfrm, | ||
| 291 | flow_cache_global); | ||
| 306 | 292 | ||
| 307 | fcp = this_cpu_ptr(fc->percpu); | 293 | fcp = this_cpu_ptr(fc->percpu); |
| 308 | for (i = 0; i < flow_cache_hash_size(fc); i++) { | 294 | for (i = 0; i < flow_cache_hash_size(fc); i++) { |
| 309 | hlist_for_each_entry_safe(fle, tmp, | 295 | hlist_for_each_entry_safe(fle, tmp, |
| 310 | &fcp->hash_table[i], u.hlist) { | 296 | &fcp->hash_table[i], u.hlist) { |
| 311 | if (flow_entry_valid(fle)) | 297 | if (flow_entry_valid(fle, xfrm)) |
| 312 | continue; | 298 | continue; |
| 313 | 299 | ||
| 314 | deleted++; | 300 | deleted++; |
| @@ -317,7 +303,7 @@ static void flow_cache_flush_tasklet(unsigned long data) | |||
| 317 | } | 303 | } |
| 318 | } | 304 | } |
| 319 | 305 | ||
| 320 | flow_cache_queue_garbage(fcp, deleted, &gc_list); | 306 | flow_cache_queue_garbage(fcp, deleted, &gc_list, xfrm); |
| 321 | 307 | ||
| 322 | if (atomic_dec_and_test(&info->cpuleft)) | 308 | if (atomic_dec_and_test(&info->cpuleft)) |
| 323 | complete(&info->completion); | 309 | complete(&info->completion); |
| @@ -351,10 +337,9 @@ static void flow_cache_flush_per_cpu(void *data) | |||
| 351 | tasklet_schedule(tasklet); | 337 | tasklet_schedule(tasklet); |
| 352 | } | 338 | } |
| 353 | 339 | ||
| 354 | void flow_cache_flush(void) | 340 | void flow_cache_flush(struct net *net) |
| 355 | { | 341 | { |
| 356 | struct flow_flush_info info; | 342 | struct flow_flush_info info; |
| 357 | static DEFINE_MUTEX(flow_flush_sem); | ||
| 358 | cpumask_var_t mask; | 343 | cpumask_var_t mask; |
| 359 | int i, self; | 344 | int i, self; |
| 360 | 345 | ||
| @@ -365,8 +350,8 @@ void flow_cache_flush(void) | |||
| 365 | 350 | ||
| 366 | /* Don't want cpus going down or up during this. */ | 351 | /* Don't want cpus going down or up during this. */ |
| 367 | get_online_cpus(); | 352 | get_online_cpus(); |
| 368 | mutex_lock(&flow_flush_sem); | 353 | mutex_lock(&net->xfrm.flow_flush_sem); |
| 369 | info.cache = &flow_cache_global; | 354 | info.cache = &net->xfrm.flow_cache_global; |
| 370 | for_each_online_cpu(i) | 355 | for_each_online_cpu(i) |
| 371 | if (!flow_cache_percpu_empty(info.cache, i)) | 356 | if (!flow_cache_percpu_empty(info.cache, i)) |
| 372 | cpumask_set_cpu(i, mask); | 357 | cpumask_set_cpu(i, mask); |
| @@ -386,21 +371,23 @@ void flow_cache_flush(void) | |||
| 386 | wait_for_completion(&info.completion); | 371 | wait_for_completion(&info.completion); |
| 387 | 372 | ||
| 388 | done: | 373 | done: |
| 389 | mutex_unlock(&flow_flush_sem); | 374 | mutex_unlock(&net->xfrm.flow_flush_sem); |
| 390 | put_online_cpus(); | 375 | put_online_cpus(); |
| 391 | free_cpumask_var(mask); | 376 | free_cpumask_var(mask); |
| 392 | } | 377 | } |
| 393 | 378 | ||
| 394 | static void flow_cache_flush_task(struct work_struct *work) | 379 | static void flow_cache_flush_task(struct work_struct *work) |
| 395 | { | 380 | { |
| 396 | flow_cache_flush(); | 381 | struct netns_xfrm *xfrm = container_of(work, struct netns_xfrm, |
| 397 | } | 382 | flow_cache_gc_work); |
| 383 | struct net *net = container_of(xfrm, struct net, xfrm); | ||
| 398 | 384 | ||
| 399 | static DECLARE_WORK(flow_cache_flush_work, flow_cache_flush_task); | 385 | flow_cache_flush(net); |
| 386 | } | ||
| 400 | 387 | ||
| 401 | void flow_cache_flush_deferred(void) | 388 | void flow_cache_flush_deferred(struct net *net) |
| 402 | { | 389 | { |
| 403 | schedule_work(&flow_cache_flush_work); | 390 | schedule_work(&net->xfrm.flow_cache_flush_work); |
| 404 | } | 391 | } |
| 405 | 392 | ||
| 406 | static int flow_cache_cpu_prepare(struct flow_cache *fc, int cpu) | 393 | static int flow_cache_cpu_prepare(struct flow_cache *fc, int cpu) |
| @@ -425,7 +412,8 @@ static int flow_cache_cpu(struct notifier_block *nfb, | |||
| 425 | unsigned long action, | 412 | unsigned long action, |
| 426 | void *hcpu) | 413 | void *hcpu) |
| 427 | { | 414 | { |
| 428 | struct flow_cache *fc = container_of(nfb, struct flow_cache, hotcpu_notifier); | 415 | struct flow_cache *fc = container_of(nfb, struct flow_cache, |
| 416 | hotcpu_notifier); | ||
| 429 | int res, cpu = (unsigned long) hcpu; | 417 | int res, cpu = (unsigned long) hcpu; |
| 430 | struct flow_cache_percpu *fcp = per_cpu_ptr(fc->percpu, cpu); | 418 | struct flow_cache_percpu *fcp = per_cpu_ptr(fc->percpu, cpu); |
| 431 | 419 | ||
| @@ -444,9 +432,20 @@ static int flow_cache_cpu(struct notifier_block *nfb, | |||
| 444 | return NOTIFY_OK; | 432 | return NOTIFY_OK; |
| 445 | } | 433 | } |
| 446 | 434 | ||
| 447 | static int __init flow_cache_init(struct flow_cache *fc) | 435 | int flow_cache_init(struct net *net) |
| 448 | { | 436 | { |
| 449 | int i; | 437 | int i; |
| 438 | struct flow_cache *fc = &net->xfrm.flow_cache_global; | ||
| 439 | |||
| 440 | if (!flow_cachep) | ||
| 441 | flow_cachep = kmem_cache_create("flow_cache", | ||
| 442 | sizeof(struct flow_cache_entry), | ||
| 443 | 0, SLAB_PANIC, NULL); | ||
| 444 | spin_lock_init(&net->xfrm.flow_cache_gc_lock); | ||
| 445 | INIT_LIST_HEAD(&net->xfrm.flow_cache_gc_list); | ||
| 446 | INIT_WORK(&net->xfrm.flow_cache_gc_work, flow_cache_gc_task); | ||
| 447 | INIT_WORK(&net->xfrm.flow_cache_flush_work, flow_cache_flush_task); | ||
| 448 | mutex_init(&net->xfrm.flow_flush_sem); | ||
| 450 | 449 | ||
| 451 | fc->hash_shift = 10; | 450 | fc->hash_shift = 10; |
| 452 | fc->low_watermark = 2 * flow_cache_hash_size(fc); | 451 | fc->low_watermark = 2 * flow_cache_hash_size(fc); |
| @@ -456,6 +455,8 @@ static int __init flow_cache_init(struct flow_cache *fc) | |||
| 456 | if (!fc->percpu) | 455 | if (!fc->percpu) |
| 457 | return -ENOMEM; | 456 | return -ENOMEM; |
| 458 | 457 | ||
| 458 | cpu_notifier_register_begin(); | ||
| 459 | |||
| 459 | for_each_online_cpu(i) { | 460 | for_each_online_cpu(i) { |
| 460 | if (flow_cache_cpu_prepare(fc, i)) | 461 | if (flow_cache_cpu_prepare(fc, i)) |
| 461 | goto err; | 462 | goto err; |
| @@ -463,7 +464,9 @@ static int __init flow_cache_init(struct flow_cache *fc) | |||
| 463 | fc->hotcpu_notifier = (struct notifier_block){ | 464 | fc->hotcpu_notifier = (struct notifier_block){ |
| 464 | .notifier_call = flow_cache_cpu, | 465 | .notifier_call = flow_cache_cpu, |
| 465 | }; | 466 | }; |
| 466 | register_hotcpu_notifier(&fc->hotcpu_notifier); | 467 | __register_hotcpu_notifier(&fc->hotcpu_notifier); |
| 468 | |||
| 469 | cpu_notifier_register_done(); | ||
| 467 | 470 | ||
| 468 | setup_timer(&fc->rnd_timer, flow_cache_new_hashrnd, | 471 | setup_timer(&fc->rnd_timer, flow_cache_new_hashrnd, |
| 469 | (unsigned long) fc); | 472 | (unsigned long) fc); |
| @@ -479,19 +482,30 @@ err: | |||
| 479 | fcp->hash_table = NULL; | 482 | fcp->hash_table = NULL; |
| 480 | } | 483 | } |
| 481 | 484 | ||
| 485 | cpu_notifier_register_done(); | ||
| 486 | |||
| 482 | free_percpu(fc->percpu); | 487 | free_percpu(fc->percpu); |
| 483 | fc->percpu = NULL; | 488 | fc->percpu = NULL; |
| 484 | 489 | ||
| 485 | return -ENOMEM; | 490 | return -ENOMEM; |
| 486 | } | 491 | } |
| 492 | EXPORT_SYMBOL(flow_cache_init); | ||
| 487 | 493 | ||
| 488 | static int __init flow_cache_init_global(void) | 494 | void flow_cache_fini(struct net *net) |
| 489 | { | 495 | { |
| 490 | flow_cachep = kmem_cache_create("flow_cache", | 496 | int i; |
| 491 | sizeof(struct flow_cache_entry), | 497 | struct flow_cache *fc = &net->xfrm.flow_cache_global; |
| 492 | 0, SLAB_PANIC, NULL); | ||
| 493 | 498 | ||
| 494 | return flow_cache_init(&flow_cache_global); | 499 | del_timer_sync(&fc->rnd_timer); |
| 495 | } | 500 | unregister_hotcpu_notifier(&fc->hotcpu_notifier); |
| 501 | |||
| 502 | for_each_possible_cpu(i) { | ||
| 503 | struct flow_cache_percpu *fcp = per_cpu_ptr(fc->percpu, i); | ||
| 504 | kfree(fcp->hash_table); | ||
| 505 | fcp->hash_table = NULL; | ||
| 506 | } | ||
| 496 | 507 | ||
| 497 | module_init(flow_cache_init_global); | 508 | free_percpu(fc->percpu); |
| 509 | fc->percpu = NULL; | ||
| 510 | } | ||
| 511 | EXPORT_SYMBOL(flow_cache_fini); | ||
diff --git a/net/core/flow_dissector.c b/net/core/flow_dissector.c index e29e810663d7..107ed12a5323 100644 --- a/net/core/flow_dissector.c +++ b/net/core/flow_dissector.c | |||
| @@ -61,7 +61,7 @@ bool skb_flow_dissect(const struct sk_buff *skb, struct flow_keys *flow) | |||
| 61 | 61 | ||
| 62 | again: | 62 | again: |
| 63 | switch (proto) { | 63 | switch (proto) { |
| 64 | case __constant_htons(ETH_P_IP): { | 64 | case htons(ETH_P_IP): { |
| 65 | const struct iphdr *iph; | 65 | const struct iphdr *iph; |
| 66 | struct iphdr _iph; | 66 | struct iphdr _iph; |
| 67 | ip: | 67 | ip: |
| @@ -77,7 +77,7 @@ ip: | |||
| 77 | iph_to_flow_copy_addrs(flow, iph); | 77 | iph_to_flow_copy_addrs(flow, iph); |
| 78 | break; | 78 | break; |
| 79 | } | 79 | } |
| 80 | case __constant_htons(ETH_P_IPV6): { | 80 | case htons(ETH_P_IPV6): { |
| 81 | const struct ipv6hdr *iph; | 81 | const struct ipv6hdr *iph; |
| 82 | struct ipv6hdr _iph; | 82 | struct ipv6hdr _iph; |
| 83 | ipv6: | 83 | ipv6: |
| @@ -91,8 +91,8 @@ ipv6: | |||
| 91 | nhoff += sizeof(struct ipv6hdr); | 91 | nhoff += sizeof(struct ipv6hdr); |
| 92 | break; | 92 | break; |
| 93 | } | 93 | } |
| 94 | case __constant_htons(ETH_P_8021AD): | 94 | case htons(ETH_P_8021AD): |
| 95 | case __constant_htons(ETH_P_8021Q): { | 95 | case htons(ETH_P_8021Q): { |
| 96 | const struct vlan_hdr *vlan; | 96 | const struct vlan_hdr *vlan; |
| 97 | struct vlan_hdr _vlan; | 97 | struct vlan_hdr _vlan; |
| 98 | 98 | ||
| @@ -104,7 +104,7 @@ ipv6: | |||
| 104 | nhoff += sizeof(*vlan); | 104 | nhoff += sizeof(*vlan); |
| 105 | goto again; | 105 | goto again; |
| 106 | } | 106 | } |
| 107 | case __constant_htons(ETH_P_PPP_SES): { | 107 | case htons(ETH_P_PPP_SES): { |
| 108 | struct { | 108 | struct { |
| 109 | struct pppoe_hdr hdr; | 109 | struct pppoe_hdr hdr; |
| 110 | __be16 proto; | 110 | __be16 proto; |
| @@ -115,9 +115,9 @@ ipv6: | |||
| 115 | proto = hdr->proto; | 115 | proto = hdr->proto; |
| 116 | nhoff += PPPOE_SES_HLEN; | 116 | nhoff += PPPOE_SES_HLEN; |
| 117 | switch (proto) { | 117 | switch (proto) { |
| 118 | case __constant_htons(PPP_IP): | 118 | case htons(PPP_IP): |
| 119 | goto ip; | 119 | goto ip; |
| 120 | case __constant_htons(PPP_IPV6): | 120 | case htons(PPP_IPV6): |
| 121 | goto ipv6; | 121 | goto ipv6; |
| 122 | default: | 122 | default: |
| 123 | return false; | 123 | return false; |
| @@ -203,8 +203,8 @@ static __always_inline u32 __flow_hash_1word(u32 a) | |||
| 203 | 203 | ||
| 204 | /* | 204 | /* |
| 205 | * __skb_get_hash: calculate a flow hash based on src/dst addresses | 205 | * __skb_get_hash: calculate a flow hash based on src/dst addresses |
| 206 | * and src/dst port numbers. Sets rxhash in skb to non-zero hash value | 206 | * and src/dst port numbers. Sets hash in skb to non-zero hash value |
| 207 | * on success, zero indicates no valid hash. Also, sets l4_rxhash in skb | 207 | * on success, zero indicates no valid hash. Also, sets l4_hash in skb |
| 208 | * if hash is a canonical 4-tuple hash over transport ports. | 208 | * if hash is a canonical 4-tuple hash over transport ports. |
| 209 | */ | 209 | */ |
| 210 | void __skb_get_hash(struct sk_buff *skb) | 210 | void __skb_get_hash(struct sk_buff *skb) |
| @@ -216,7 +216,7 @@ void __skb_get_hash(struct sk_buff *skb) | |||
| 216 | return; | 216 | return; |
| 217 | 217 | ||
| 218 | if (keys.ports) | 218 | if (keys.ports) |
| 219 | skb->l4_rxhash = 1; | 219 | skb->l4_hash = 1; |
| 220 | 220 | ||
| 221 | /* get a consistent hash (same value on both flow directions) */ | 221 | /* get a consistent hash (same value on both flow directions) */ |
| 222 | if (((__force u32)keys.dst < (__force u32)keys.src) || | 222 | if (((__force u32)keys.dst < (__force u32)keys.src) || |
| @@ -232,7 +232,7 @@ void __skb_get_hash(struct sk_buff *skb) | |||
| 232 | if (!hash) | 232 | if (!hash) |
| 233 | hash = 1; | 233 | hash = 1; |
| 234 | 234 | ||
| 235 | skb->rxhash = hash; | 235 | skb->hash = hash; |
| 236 | } | 236 | } |
| 237 | EXPORT_SYMBOL(__skb_get_hash); | 237 | EXPORT_SYMBOL(__skb_get_hash); |
| 238 | 238 | ||
| @@ -344,7 +344,7 @@ static inline int get_xps_queue(struct net_device *dev, struct sk_buff *skb) | |||
| 344 | hash = skb->sk->sk_hash; | 344 | hash = skb->sk->sk_hash; |
| 345 | else | 345 | else |
| 346 | hash = (__force u16) skb->protocol ^ | 346 | hash = (__force u16) skb->protocol ^ |
| 347 | skb->rxhash; | 347 | skb->hash; |
| 348 | hash = __flow_hash_1word(hash); | 348 | hash = __flow_hash_1word(hash); |
| 349 | queue_index = map->queues[ | 349 | queue_index = map->queues[ |
| 350 | ((u64)hash * map->len) >> 32]; | 350 | ((u64)hash * map->len) >> 32]; |
diff --git a/net/core/neighbour.c b/net/core/neighbour.c index e16129019c66..8f8a96ef9f3f 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c | |||
| @@ -836,10 +836,10 @@ out: | |||
| 836 | static __inline__ int neigh_max_probes(struct neighbour *n) | 836 | static __inline__ int neigh_max_probes(struct neighbour *n) |
| 837 | { | 837 | { |
| 838 | struct neigh_parms *p = n->parms; | 838 | struct neigh_parms *p = n->parms; |
| 839 | return (n->nud_state & NUD_PROBE) ? | 839 | int max_probes = NEIGH_VAR(p, UCAST_PROBES) + NEIGH_VAR(p, APP_PROBES); |
| 840 | NEIGH_VAR(p, UCAST_PROBES) : | 840 | if (!(n->nud_state & NUD_PROBE)) |
| 841 | NEIGH_VAR(p, UCAST_PROBES) + NEIGH_VAR(p, APP_PROBES) + | 841 | max_probes += NEIGH_VAR(p, MCAST_PROBES); |
| 842 | NEIGH_VAR(p, MCAST_PROBES); | 842 | return max_probes; |
| 843 | } | 843 | } |
| 844 | 844 | ||
| 845 | static void neigh_invalidate(struct neighbour *neigh) | 845 | static void neigh_invalidate(struct neighbour *neigh) |
| @@ -945,6 +945,7 @@ static void neigh_timer_handler(unsigned long arg) | |||
| 945 | neigh->nud_state = NUD_FAILED; | 945 | neigh->nud_state = NUD_FAILED; |
| 946 | notify = 1; | 946 | notify = 1; |
| 947 | neigh_invalidate(neigh); | 947 | neigh_invalidate(neigh); |
| 948 | goto out; | ||
| 948 | } | 949 | } |
| 949 | 950 | ||
| 950 | if (neigh->nud_state & NUD_IN_TIMER) { | 951 | if (neigh->nud_state & NUD_IN_TIMER) { |
diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index 549043c078c9..1cac29ebb05b 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c | |||
| @@ -104,6 +104,7 @@ static ssize_t netdev_store(struct device *dev, struct device_attribute *attr, | |||
| 104 | } | 104 | } |
| 105 | 105 | ||
| 106 | NETDEVICE_SHOW_RO(dev_id, fmt_hex); | 106 | NETDEVICE_SHOW_RO(dev_id, fmt_hex); |
| 107 | NETDEVICE_SHOW_RO(dev_port, fmt_dec); | ||
| 107 | NETDEVICE_SHOW_RO(addr_assign_type, fmt_dec); | 108 | NETDEVICE_SHOW_RO(addr_assign_type, fmt_dec); |
| 108 | NETDEVICE_SHOW_RO(addr_len, fmt_dec); | 109 | NETDEVICE_SHOW_RO(addr_len, fmt_dec); |
| 109 | NETDEVICE_SHOW_RO(iflink, fmt_dec); | 110 | NETDEVICE_SHOW_RO(iflink, fmt_dec); |
| @@ -252,6 +253,16 @@ static ssize_t operstate_show(struct device *dev, | |||
| 252 | } | 253 | } |
| 253 | static DEVICE_ATTR_RO(operstate); | 254 | static DEVICE_ATTR_RO(operstate); |
| 254 | 255 | ||
| 256 | static ssize_t carrier_changes_show(struct device *dev, | ||
| 257 | struct device_attribute *attr, | ||
| 258 | char *buf) | ||
| 259 | { | ||
| 260 | struct net_device *netdev = to_net_dev(dev); | ||
| 261 | return sprintf(buf, fmt_dec, | ||
| 262 | atomic_read(&netdev->carrier_changes)); | ||
| 263 | } | ||
| 264 | static DEVICE_ATTR_RO(carrier_changes); | ||
| 265 | |||
| 255 | /* read-write attributes */ | 266 | /* read-write attributes */ |
| 256 | 267 | ||
| 257 | static int change_mtu(struct net_device *net, unsigned long new_mtu) | 268 | static int change_mtu(struct net_device *net, unsigned long new_mtu) |
| @@ -373,6 +384,7 @@ static struct attribute *net_class_attrs[] = { | |||
| 373 | &dev_attr_netdev_group.attr, | 384 | &dev_attr_netdev_group.attr, |
| 374 | &dev_attr_type.attr, | 385 | &dev_attr_type.attr, |
| 375 | &dev_attr_dev_id.attr, | 386 | &dev_attr_dev_id.attr, |
| 387 | &dev_attr_dev_port.attr, | ||
| 376 | &dev_attr_iflink.attr, | 388 | &dev_attr_iflink.attr, |
| 377 | &dev_attr_ifindex.attr, | 389 | &dev_attr_ifindex.attr, |
| 378 | &dev_attr_addr_assign_type.attr, | 390 | &dev_attr_addr_assign_type.attr, |
| @@ -384,6 +396,7 @@ static struct attribute *net_class_attrs[] = { | |||
| 384 | &dev_attr_duplex.attr, | 396 | &dev_attr_duplex.attr, |
| 385 | &dev_attr_dormant.attr, | 397 | &dev_attr_dormant.attr, |
| 386 | &dev_attr_operstate.attr, | 398 | &dev_attr_operstate.attr, |
| 399 | &dev_attr_carrier_changes.attr, | ||
| 387 | &dev_attr_ifalias.attr, | 400 | &dev_attr_ifalias.attr, |
| 388 | &dev_attr_carrier.attr, | 401 | &dev_attr_carrier.attr, |
| 389 | &dev_attr_mtu.attr, | 402 | &dev_attr_mtu.attr, |
| @@ -996,15 +1009,12 @@ static struct attribute_group dql_group = { | |||
| 996 | #endif /* CONFIG_BQL */ | 1009 | #endif /* CONFIG_BQL */ |
| 997 | 1010 | ||
| 998 | #ifdef CONFIG_XPS | 1011 | #ifdef CONFIG_XPS |
| 999 | static inline unsigned int get_netdev_queue_index(struct netdev_queue *queue) | 1012 | static unsigned int get_netdev_queue_index(struct netdev_queue *queue) |
| 1000 | { | 1013 | { |
| 1001 | struct net_device *dev = queue->dev; | 1014 | struct net_device *dev = queue->dev; |
| 1002 | int i; | 1015 | unsigned int i; |
| 1003 | |||
| 1004 | for (i = 0; i < dev->num_tx_queues; i++) | ||
| 1005 | if (queue == &dev->_tx[i]) | ||
| 1006 | break; | ||
| 1007 | 1016 | ||
| 1017 | i = queue - dev->_tx; | ||
| 1008 | BUG_ON(i >= dev->num_tx_queues); | 1018 | BUG_ON(i >= dev->num_tx_queues); |
| 1009 | 1019 | ||
| 1010 | return i; | 1020 | return i; |
diff --git a/net/core/netclassid_cgroup.c b/net/core/netclassid_cgroup.c index 719efd541668..22931e1b99b4 100644 --- a/net/core/netclassid_cgroup.c +++ b/net/core/netclassid_cgroup.c | |||
| @@ -23,7 +23,7 @@ static inline struct cgroup_cls_state *css_cls_state(struct cgroup_subsys_state | |||
| 23 | 23 | ||
| 24 | struct cgroup_cls_state *task_cls_state(struct task_struct *p) | 24 | struct cgroup_cls_state *task_cls_state(struct task_struct *p) |
| 25 | { | 25 | { |
| 26 | return css_cls_state(task_css(p, net_cls_subsys_id)); | 26 | return css_cls_state(task_css(p, net_cls_cgrp_id)); |
| 27 | } | 27 | } |
| 28 | EXPORT_SYMBOL_GPL(task_cls_state); | 28 | EXPORT_SYMBOL_GPL(task_cls_state); |
| 29 | 29 | ||
| @@ -73,7 +73,7 @@ static void cgrp_attach(struct cgroup_subsys_state *css, | |||
| 73 | void *v = (void *)(unsigned long)cs->classid; | 73 | void *v = (void *)(unsigned long)cs->classid; |
| 74 | struct task_struct *p; | 74 | struct task_struct *p; |
| 75 | 75 | ||
| 76 | cgroup_taskset_for_each(p, css, tset) { | 76 | cgroup_taskset_for_each(p, tset) { |
| 77 | task_lock(p); | 77 | task_lock(p); |
| 78 | iterate_fd(p->files, 0, update_classid, v); | 78 | iterate_fd(p->files, 0, update_classid, v); |
| 79 | task_unlock(p); | 79 | task_unlock(p); |
| @@ -102,19 +102,10 @@ static struct cftype ss_files[] = { | |||
| 102 | { } /* terminate */ | 102 | { } /* terminate */ |
| 103 | }; | 103 | }; |
| 104 | 104 | ||
| 105 | struct cgroup_subsys net_cls_subsys = { | 105 | struct cgroup_subsys net_cls_cgrp_subsys = { |
| 106 | .name = "net_cls", | ||
| 107 | .css_alloc = cgrp_css_alloc, | 106 | .css_alloc = cgrp_css_alloc, |
| 108 | .css_online = cgrp_css_online, | 107 | .css_online = cgrp_css_online, |
| 109 | .css_free = cgrp_css_free, | 108 | .css_free = cgrp_css_free, |
| 110 | .attach = cgrp_attach, | 109 | .attach = cgrp_attach, |
| 111 | .subsys_id = net_cls_subsys_id, | ||
| 112 | .base_cftypes = ss_files, | 110 | .base_cftypes = ss_files, |
| 113 | .module = THIS_MODULE, | ||
| 114 | }; | 111 | }; |
| 115 | |||
| 116 | static int __init init_netclassid_cgroup(void) | ||
| 117 | { | ||
| 118 | return cgroup_load_subsys(&net_cls_subsys); | ||
| 119 | } | ||
| 120 | __initcall(init_netclassid_cgroup); | ||
diff --git a/net/core/netpoll.c b/net/core/netpoll.c index df9e6b1a9759..e33937fb32a0 100644 --- a/net/core/netpoll.c +++ b/net/core/netpoll.c | |||
| @@ -46,13 +46,9 @@ | |||
| 46 | 46 | ||
| 47 | static struct sk_buff_head skb_pool; | 47 | static struct sk_buff_head skb_pool; |
| 48 | 48 | ||
| 49 | static atomic_t trapped; | ||
| 50 | |||
| 51 | DEFINE_STATIC_SRCU(netpoll_srcu); | 49 | DEFINE_STATIC_SRCU(netpoll_srcu); |
| 52 | 50 | ||
| 53 | #define USEC_PER_POLL 50 | 51 | #define USEC_PER_POLL 50 |
| 54 | #define NETPOLL_RX_ENABLED 1 | ||
| 55 | #define NETPOLL_RX_DROP 2 | ||
| 56 | 52 | ||
| 57 | #define MAX_SKB_SIZE \ | 53 | #define MAX_SKB_SIZE \ |
| 58 | (sizeof(struct ethhdr) + \ | 54 | (sizeof(struct ethhdr) + \ |
| @@ -61,7 +57,6 @@ DEFINE_STATIC_SRCU(netpoll_srcu); | |||
| 61 | MAX_UDP_CHUNK) | 57 | MAX_UDP_CHUNK) |
| 62 | 58 | ||
| 63 | static void zap_completion_queue(void); | 59 | static void zap_completion_queue(void); |
| 64 | static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo); | ||
| 65 | static void netpoll_async_cleanup(struct work_struct *work); | 60 | static void netpoll_async_cleanup(struct work_struct *work); |
| 66 | 61 | ||
| 67 | static unsigned int carrier_timeout = 4; | 62 | static unsigned int carrier_timeout = 4; |
| @@ -74,6 +69,37 @@ module_param(carrier_timeout, uint, 0644); | |||
| 74 | #define np_notice(np, fmt, ...) \ | 69 | #define np_notice(np, fmt, ...) \ |
| 75 | pr_notice("%s: " fmt, np->name, ##__VA_ARGS__) | 70 | pr_notice("%s: " fmt, np->name, ##__VA_ARGS__) |
| 76 | 71 | ||
| 72 | static int netpoll_start_xmit(struct sk_buff *skb, struct net_device *dev, | ||
| 73 | struct netdev_queue *txq) | ||
| 74 | { | ||
| 75 | const struct net_device_ops *ops = dev->netdev_ops; | ||
| 76 | int status = NETDEV_TX_OK; | ||
| 77 | netdev_features_t features; | ||
| 78 | |||
| 79 | features = netif_skb_features(skb); | ||
| 80 | |||
| 81 | if (vlan_tx_tag_present(skb) && | ||
| 82 | !vlan_hw_offload_capable(features, skb->vlan_proto)) { | ||
| 83 | skb = __vlan_put_tag(skb, skb->vlan_proto, | ||
| 84 | vlan_tx_tag_get(skb)); | ||
| 85 | if (unlikely(!skb)) { | ||
| 86 | /* This is actually a packet drop, but we | ||
| 87 | * don't want the code that calls this | ||
| 88 | * function to try and operate on a NULL skb. | ||
| 89 | */ | ||
| 90 | goto out; | ||
| 91 | } | ||
| 92 | skb->vlan_tci = 0; | ||
| 93 | } | ||
| 94 | |||
| 95 | status = ops->ndo_start_xmit(skb, dev); | ||
| 96 | if (status == NETDEV_TX_OK) | ||
| 97 | txq_trans_update(txq); | ||
| 98 | |||
| 99 | out: | ||
| 100 | return status; | ||
| 101 | } | ||
| 102 | |||
| 77 | static void queue_process(struct work_struct *work) | 103 | static void queue_process(struct work_struct *work) |
| 78 | { | 104 | { |
| 79 | struct netpoll_info *npinfo = | 105 | struct netpoll_info *npinfo = |
| @@ -83,51 +109,31 @@ static void queue_process(struct work_struct *work) | |||
| 83 | 109 | ||
| 84 | while ((skb = skb_dequeue(&npinfo->txq))) { | 110 | while ((skb = skb_dequeue(&npinfo->txq))) { |
| 85 | struct net_device *dev = skb->dev; | 111 | struct net_device *dev = skb->dev; |
| 86 | const struct net_device_ops *ops = dev->netdev_ops; | ||
| 87 | struct netdev_queue *txq; | 112 | struct netdev_queue *txq; |
| 88 | 113 | ||
| 89 | if (!netif_device_present(dev) || !netif_running(dev)) { | 114 | if (!netif_device_present(dev) || !netif_running(dev)) { |
| 90 | __kfree_skb(skb); | 115 | kfree_skb(skb); |
| 91 | continue; | 116 | continue; |
| 92 | } | 117 | } |
| 93 | 118 | ||
| 94 | txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); | 119 | txq = netdev_get_tx_queue(dev, skb_get_queue_mapping(skb)); |
| 95 | 120 | ||
| 96 | local_irq_save(flags); | 121 | local_irq_save(flags); |
| 97 | __netif_tx_lock(txq, smp_processor_id()); | 122 | HARD_TX_LOCK(dev, txq, smp_processor_id()); |
| 98 | if (netif_xmit_frozen_or_stopped(txq) || | 123 | if (netif_xmit_frozen_or_stopped(txq) || |
| 99 | ops->ndo_start_xmit(skb, dev) != NETDEV_TX_OK) { | 124 | netpoll_start_xmit(skb, dev, txq) != NETDEV_TX_OK) { |
| 100 | skb_queue_head(&npinfo->txq, skb); | 125 | skb_queue_head(&npinfo->txq, skb); |
| 101 | __netif_tx_unlock(txq); | 126 | HARD_TX_UNLOCK(dev, txq); |
| 102 | local_irq_restore(flags); | 127 | local_irq_restore(flags); |
| 103 | 128 | ||
| 104 | schedule_delayed_work(&npinfo->tx_work, HZ/10); | 129 | schedule_delayed_work(&npinfo->tx_work, HZ/10); |
| 105 | return; | 130 | return; |
| 106 | } | 131 | } |
| 107 | __netif_tx_unlock(txq); | 132 | HARD_TX_UNLOCK(dev, txq); |
| 108 | local_irq_restore(flags); | 133 | local_irq_restore(flags); |
| 109 | } | 134 | } |
| 110 | } | 135 | } |
| 111 | 136 | ||
| 112 | static __sum16 checksum_udp(struct sk_buff *skb, struct udphdr *uh, | ||
| 113 | unsigned short ulen, __be32 saddr, __be32 daddr) | ||
| 114 | { | ||
| 115 | __wsum psum; | ||
| 116 | |||
| 117 | if (uh->check == 0 || skb_csum_unnecessary(skb)) | ||
| 118 | return 0; | ||
| 119 | |||
| 120 | psum = csum_tcpudp_nofold(saddr, daddr, ulen, IPPROTO_UDP, 0); | ||
| 121 | |||
| 122 | if (skb->ip_summed == CHECKSUM_COMPLETE && | ||
| 123 | !csum_fold(csum_add(psum, skb->csum))) | ||
| 124 | return 0; | ||
| 125 | |||
| 126 | skb->csum = psum; | ||
| 127 | |||
| 128 | return __skb_checksum_complete(skb); | ||
| 129 | } | ||
| 130 | |||
| 131 | /* | 137 | /* |
| 132 | * Check whether delayed processing was scheduled for our NIC. If so, | 138 | * Check whether delayed processing was scheduled for our NIC. If so, |
| 133 | * we attempt to grab the poll lock and use ->poll() to pump the card. | 139 | * we attempt to grab the poll lock and use ->poll() to pump the card. |
| @@ -138,14 +144,8 @@ static __sum16 checksum_udp(struct sk_buff *skb, struct udphdr *uh, | |||
| 138 | * trylock here and interrupts are already disabled in the softirq | 144 | * trylock here and interrupts are already disabled in the softirq |
| 139 | * case. Further, we test the poll_owner to avoid recursion on UP | 145 | * case. Further, we test the poll_owner to avoid recursion on UP |
| 140 | * systems where the lock doesn't exist. | 146 | * systems where the lock doesn't exist. |
| 141 | * | ||
| 142 | * In cases where there is bi-directional communications, reading only | ||
| 143 | * one message at a time can lead to packets being dropped by the | ||
| 144 | * network adapter, forcing superfluous retries and possibly timeouts. | ||
| 145 | * Thus, we set our budget to greater than 1. | ||
| 146 | */ | 147 | */ |
| 147 | static int poll_one_napi(struct netpoll_info *npinfo, | 148 | static int poll_one_napi(struct napi_struct *napi, int budget) |
| 148 | struct napi_struct *napi, int budget) | ||
| 149 | { | 149 | { |
| 150 | int work; | 150 | int work; |
| 151 | 151 | ||
| @@ -156,52 +156,35 @@ static int poll_one_napi(struct netpoll_info *npinfo, | |||
| 156 | if (!test_bit(NAPI_STATE_SCHED, &napi->state)) | 156 | if (!test_bit(NAPI_STATE_SCHED, &napi->state)) |
| 157 | return budget; | 157 | return budget; |
| 158 | 158 | ||
| 159 | npinfo->rx_flags |= NETPOLL_RX_DROP; | ||
| 160 | atomic_inc(&trapped); | ||
| 161 | set_bit(NAPI_STATE_NPSVC, &napi->state); | 159 | set_bit(NAPI_STATE_NPSVC, &napi->state); |
| 162 | 160 | ||
| 163 | work = napi->poll(napi, budget); | 161 | work = napi->poll(napi, budget); |
| 162 | WARN_ONCE(work > budget, "%pF exceeded budget in poll\n", napi->poll); | ||
| 164 | trace_napi_poll(napi); | 163 | trace_napi_poll(napi); |
| 165 | 164 | ||
| 166 | clear_bit(NAPI_STATE_NPSVC, &napi->state); | 165 | clear_bit(NAPI_STATE_NPSVC, &napi->state); |
| 167 | atomic_dec(&trapped); | ||
| 168 | npinfo->rx_flags &= ~NETPOLL_RX_DROP; | ||
| 169 | 166 | ||
| 170 | return budget - work; | 167 | return budget - work; |
| 171 | } | 168 | } |
| 172 | 169 | ||
| 173 | static void poll_napi(struct net_device *dev) | 170 | static void poll_napi(struct net_device *dev, int budget) |
| 174 | { | 171 | { |
| 175 | struct napi_struct *napi; | 172 | struct napi_struct *napi; |
| 176 | int budget = 16; | ||
| 177 | 173 | ||
| 178 | list_for_each_entry(napi, &dev->napi_list, dev_list) { | 174 | list_for_each_entry(napi, &dev->napi_list, dev_list) { |
| 179 | if (napi->poll_owner != smp_processor_id() && | 175 | if (napi->poll_owner != smp_processor_id() && |
| 180 | spin_trylock(&napi->poll_lock)) { | 176 | spin_trylock(&napi->poll_lock)) { |
| 181 | budget = poll_one_napi(rcu_dereference_bh(dev->npinfo), | 177 | budget = poll_one_napi(napi, budget); |
| 182 | napi, budget); | ||
| 183 | spin_unlock(&napi->poll_lock); | 178 | spin_unlock(&napi->poll_lock); |
| 184 | |||
| 185 | if (!budget) | ||
| 186 | break; | ||
| 187 | } | 179 | } |
| 188 | } | 180 | } |
| 189 | } | 181 | } |
| 190 | 182 | ||
| 191 | static void service_neigh_queue(struct netpoll_info *npi) | ||
| 192 | { | ||
| 193 | if (npi) { | ||
| 194 | struct sk_buff *skb; | ||
| 195 | |||
| 196 | while ((skb = skb_dequeue(&npi->neigh_tx))) | ||
| 197 | netpoll_neigh_reply(skb, npi); | ||
| 198 | } | ||
| 199 | } | ||
| 200 | |||
| 201 | static void netpoll_poll_dev(struct net_device *dev) | 183 | static void netpoll_poll_dev(struct net_device *dev) |
| 202 | { | 184 | { |
| 203 | const struct net_device_ops *ops; | 185 | const struct net_device_ops *ops; |
| 204 | struct netpoll_info *ni = rcu_dereference_bh(dev->npinfo); | 186 | struct netpoll_info *ni = rcu_dereference_bh(dev->npinfo); |
| 187 | int budget = 0; | ||
| 205 | 188 | ||
| 206 | /* Don't do any rx activity if the dev_lock mutex is held | 189 | /* Don't do any rx activity if the dev_lock mutex is held |
| 207 | * the dev_open/close paths use this to block netpoll activity | 190 | * the dev_open/close paths use this to block netpoll activity |
| @@ -224,31 +207,14 @@ static void netpoll_poll_dev(struct net_device *dev) | |||
| 224 | /* Process pending work on NIC */ | 207 | /* Process pending work on NIC */ |
| 225 | ops->ndo_poll_controller(dev); | 208 | ops->ndo_poll_controller(dev); |
| 226 | 209 | ||
| 227 | poll_napi(dev); | 210 | poll_napi(dev, budget); |
| 228 | 211 | ||
| 229 | up(&ni->dev_lock); | 212 | up(&ni->dev_lock); |
| 230 | 213 | ||
| 231 | if (dev->flags & IFF_SLAVE) { | ||
| 232 | if (ni) { | ||
| 233 | struct net_device *bond_dev; | ||
| 234 | struct sk_buff *skb; | ||
| 235 | struct netpoll_info *bond_ni; | ||
| 236 | |||
| 237 | bond_dev = netdev_master_upper_dev_get_rcu(dev); | ||
| 238 | bond_ni = rcu_dereference_bh(bond_dev->npinfo); | ||
| 239 | while ((skb = skb_dequeue(&ni->neigh_tx))) { | ||
| 240 | skb->dev = bond_dev; | ||
| 241 | skb_queue_tail(&bond_ni->neigh_tx, skb); | ||
| 242 | } | ||
| 243 | } | ||
| 244 | } | ||
| 245 | |||
| 246 | service_neigh_queue(ni); | ||
| 247 | |||
| 248 | zap_completion_queue(); | 214 | zap_completion_queue(); |
| 249 | } | 215 | } |
| 250 | 216 | ||
| 251 | void netpoll_rx_disable(struct net_device *dev) | 217 | void netpoll_poll_disable(struct net_device *dev) |
| 252 | { | 218 | { |
| 253 | struct netpoll_info *ni; | 219 | struct netpoll_info *ni; |
| 254 | int idx; | 220 | int idx; |
| @@ -259,9 +225,9 @@ void netpoll_rx_disable(struct net_device *dev) | |||
| 259 | down(&ni->dev_lock); | 225 | down(&ni->dev_lock); |
| 260 | srcu_read_unlock(&netpoll_srcu, idx); | 226 | srcu_read_unlock(&netpoll_srcu, idx); |
| 261 | } | 227 | } |
| 262 | EXPORT_SYMBOL(netpoll_rx_disable); | 228 | EXPORT_SYMBOL(netpoll_poll_disable); |
| 263 | 229 | ||
| 264 | void netpoll_rx_enable(struct net_device *dev) | 230 | void netpoll_poll_enable(struct net_device *dev) |
| 265 | { | 231 | { |
| 266 | struct netpoll_info *ni; | 232 | struct netpoll_info *ni; |
| 267 | rcu_read_lock(); | 233 | rcu_read_lock(); |
| @@ -270,7 +236,7 @@ void netpoll_rx_enable(struct net_device *dev) | |||
| 270 | up(&ni->dev_lock); | 236 | up(&ni->dev_lock); |
| 271 | rcu_read_unlock(); | 237 | rcu_read_unlock(); |
| 272 | } | 238 | } |
| 273 | EXPORT_SYMBOL(netpoll_rx_enable); | 239 | EXPORT_SYMBOL(netpoll_poll_enable); |
| 274 | 240 | ||
| 275 | static void refill_skbs(void) | 241 | static void refill_skbs(void) |
| 276 | { | 242 | { |
| @@ -304,7 +270,7 @@ static void zap_completion_queue(void) | |||
| 304 | while (clist != NULL) { | 270 | while (clist != NULL) { |
| 305 | struct sk_buff *skb = clist; | 271 | struct sk_buff *skb = clist; |
| 306 | clist = clist->next; | 272 | clist = clist->next; |
| 307 | if (skb->destructor) { | 273 | if (!skb_irq_freeable(skb)) { |
| 308 | atomic_inc(&skb->users); | 274 | atomic_inc(&skb->users); |
| 309 | dev_kfree_skb_any(skb); /* put this one back */ | 275 | dev_kfree_skb_any(skb); /* put this one back */ |
| 310 | } else { | 276 | } else { |
| @@ -359,7 +325,6 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, | |||
| 359 | { | 325 | { |
| 360 | int status = NETDEV_TX_BUSY; | 326 | int status = NETDEV_TX_BUSY; |
| 361 | unsigned long tries; | 327 | unsigned long tries; |
| 362 | const struct net_device_ops *ops = dev->netdev_ops; | ||
| 363 | /* It is up to the caller to keep npinfo alive. */ | 328 | /* It is up to the caller to keep npinfo alive. */ |
| 364 | struct netpoll_info *npinfo; | 329 | struct netpoll_info *npinfo; |
| 365 | 330 | ||
| @@ -367,7 +332,7 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, | |||
| 367 | 332 | ||
| 368 | npinfo = rcu_dereference_bh(np->dev->npinfo); | 333 | npinfo = rcu_dereference_bh(np->dev->npinfo); |
| 369 | if (!npinfo || !netif_running(dev) || !netif_device_present(dev)) { | 334 | if (!npinfo || !netif_running(dev) || !netif_device_present(dev)) { |
| 370 | __kfree_skb(skb); | 335 | dev_kfree_skb_irq(skb); |
| 371 | return; | 336 | return; |
| 372 | } | 337 | } |
| 373 | 338 | ||
| @@ -380,29 +345,11 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, | |||
| 380 | /* try until next clock tick */ | 345 | /* try until next clock tick */ |
| 381 | for (tries = jiffies_to_usecs(1)/USEC_PER_POLL; | 346 | for (tries = jiffies_to_usecs(1)/USEC_PER_POLL; |
| 382 | tries > 0; --tries) { | 347 | tries > 0; --tries) { |
| 383 | if (__netif_tx_trylock(txq)) { | 348 | if (HARD_TX_TRYLOCK(dev, txq)) { |
| 384 | if (!netif_xmit_stopped(txq)) { | 349 | if (!netif_xmit_stopped(txq)) |
| 385 | if (vlan_tx_tag_present(skb) && | 350 | status = netpoll_start_xmit(skb, dev, txq); |
| 386 | !vlan_hw_offload_capable(netif_skb_features(skb), | 351 | |
| 387 | skb->vlan_proto)) { | 352 | HARD_TX_UNLOCK(dev, txq); |
| 388 | skb = __vlan_put_tag(skb, skb->vlan_proto, vlan_tx_tag_get(skb)); | ||
| 389 | if (unlikely(!skb)) { | ||
| 390 | /* This is actually a packet drop, but we | ||
| 391 | * don't want the code at the end of this | ||
| 392 | * function to try and re-queue a NULL skb. | ||
| 393 | */ | ||
| 394 | status = NETDEV_TX_OK; | ||
| 395 | goto unlock_txq; | ||
| 396 | } | ||
| 397 | skb->vlan_tci = 0; | ||
| 398 | } | ||
| 399 | |||
| 400 | status = ops->ndo_start_xmit(skb, dev); | ||
| 401 | if (status == NETDEV_TX_OK) | ||
| 402 | txq_trans_update(txq); | ||
| 403 | } | ||
| 404 | unlock_txq: | ||
| 405 | __netif_tx_unlock(txq); | ||
| 406 | 353 | ||
| 407 | if (status == NETDEV_TX_OK) | 354 | if (status == NETDEV_TX_OK) |
| 408 | break; | 355 | break; |
| @@ -417,7 +364,7 @@ void netpoll_send_skb_on_dev(struct netpoll *np, struct sk_buff *skb, | |||
| 417 | 364 | ||
| 418 | WARN_ONCE(!irqs_disabled(), | 365 | WARN_ONCE(!irqs_disabled(), |
| 419 | "netpoll_send_skb_on_dev(): %s enabled interrupts in poll (%pF)\n", | 366 | "netpoll_send_skb_on_dev(): %s enabled interrupts in poll (%pF)\n", |
| 420 | dev->name, ops->ndo_start_xmit); | 367 | dev->name, dev->netdev_ops->ndo_start_xmit); |
| 421 | 368 | ||
| 422 | } | 369 | } |
| 423 | 370 | ||
| @@ -529,384 +476,6 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len) | |||
| 529 | } | 476 | } |
| 530 | EXPORT_SYMBOL(netpoll_send_udp); | 477 | EXPORT_SYMBOL(netpoll_send_udp); |
| 531 | 478 | ||
| 532 | static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo) | ||
| 533 | { | ||
| 534 | int size, type = ARPOP_REPLY; | ||
| 535 | __be32 sip, tip; | ||
| 536 | unsigned char *sha; | ||
| 537 | struct sk_buff *send_skb; | ||
| 538 | struct netpoll *np, *tmp; | ||
| 539 | unsigned long flags; | ||
| 540 | int hlen, tlen; | ||
| 541 | int hits = 0, proto; | ||
| 542 | |||
| 543 | if (list_empty(&npinfo->rx_np)) | ||
| 544 | return; | ||
| 545 | |||
| 546 | /* Before checking the packet, we do some early | ||
| 547 | inspection whether this is interesting at all */ | ||
| 548 | spin_lock_irqsave(&npinfo->rx_lock, flags); | ||
| 549 | list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) { | ||
| 550 | if (np->dev == skb->dev) | ||
| 551 | hits++; | ||
| 552 | } | ||
| 553 | spin_unlock_irqrestore(&npinfo->rx_lock, flags); | ||
| 554 | |||
| 555 | /* No netpoll struct is using this dev */ | ||
| 556 | if (!hits) | ||
| 557 | return; | ||
| 558 | |||
| 559 | proto = ntohs(eth_hdr(skb)->h_proto); | ||
| 560 | if (proto == ETH_P_ARP) { | ||
| 561 | struct arphdr *arp; | ||
| 562 | unsigned char *arp_ptr; | ||
| 563 | /* No arp on this interface */ | ||
| 564 | if (skb->dev->flags & IFF_NOARP) | ||
| 565 | return; | ||
| 566 | |||
| 567 | if (!pskb_may_pull(skb, arp_hdr_len(skb->dev))) | ||
| 568 | return; | ||
| 569 | |||
| 570 | skb_reset_network_header(skb); | ||
| 571 | skb_reset_transport_header(skb); | ||
| 572 | arp = arp_hdr(skb); | ||
| 573 | |||
| 574 | if ((arp->ar_hrd != htons(ARPHRD_ETHER) && | ||
| 575 | arp->ar_hrd != htons(ARPHRD_IEEE802)) || | ||
| 576 | arp->ar_pro != htons(ETH_P_IP) || | ||
| 577 | arp->ar_op != htons(ARPOP_REQUEST)) | ||
| 578 | return; | ||
| 579 | |||
| 580 | arp_ptr = (unsigned char *)(arp+1); | ||
| 581 | /* save the location of the src hw addr */ | ||
| 582 | sha = arp_ptr; | ||
| 583 | arp_ptr += skb->dev->addr_len; | ||
| 584 | memcpy(&sip, arp_ptr, 4); | ||
| 585 | arp_ptr += 4; | ||
| 586 | /* If we actually cared about dst hw addr, | ||
| 587 | it would get copied here */ | ||
| 588 | arp_ptr += skb->dev->addr_len; | ||
| 589 | memcpy(&tip, arp_ptr, 4); | ||
| 590 | |||
| 591 | /* Should we ignore arp? */ | ||
| 592 | if (ipv4_is_loopback(tip) || ipv4_is_multicast(tip)) | ||
| 593 | return; | ||
| 594 | |||
| 595 | size = arp_hdr_len(skb->dev); | ||
| 596 | |||
| 597 | spin_lock_irqsave(&npinfo->rx_lock, flags); | ||
| 598 | list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) { | ||
| 599 | if (tip != np->local_ip.ip) | ||
| 600 | continue; | ||
| 601 | |||
| 602 | hlen = LL_RESERVED_SPACE(np->dev); | ||
| 603 | tlen = np->dev->needed_tailroom; | ||
| 604 | send_skb = find_skb(np, size + hlen + tlen, hlen); | ||
| 605 | if (!send_skb) | ||
| 606 | continue; | ||
| 607 | |||
| 608 | skb_reset_network_header(send_skb); | ||
| 609 | arp = (struct arphdr *) skb_put(send_skb, size); | ||
| 610 | send_skb->dev = skb->dev; | ||
| 611 | send_skb->protocol = htons(ETH_P_ARP); | ||
| 612 | |||
| 613 | /* Fill the device header for the ARP frame */ | ||
| 614 | if (dev_hard_header(send_skb, skb->dev, ETH_P_ARP, | ||
| 615 | sha, np->dev->dev_addr, | ||
| 616 | send_skb->len) < 0) { | ||
| 617 | kfree_skb(send_skb); | ||
| 618 | continue; | ||
| 619 | } | ||
| 620 | |||
| 621 | /* | ||
| 622 | * Fill out the arp protocol part. | ||
| 623 | * | ||
| 624 | * we only support ethernet device type, | ||
| 625 | * which (according to RFC 1390) should | ||
| 626 | * always equal 1 (Ethernet). | ||
| 627 | */ | ||
| 628 | |||
| 629 | arp->ar_hrd = htons(np->dev->type); | ||
| 630 | arp->ar_pro = htons(ETH_P_IP); | ||
| 631 | arp->ar_hln = np->dev->addr_len; | ||
| 632 | arp->ar_pln = 4; | ||
| 633 | arp->ar_op = htons(type); | ||
| 634 | |||
| 635 | arp_ptr = (unsigned char *)(arp + 1); | ||
| 636 | memcpy(arp_ptr, np->dev->dev_addr, np->dev->addr_len); | ||
| 637 | arp_ptr += np->dev->addr_len; | ||
| 638 | memcpy(arp_ptr, &tip, 4); | ||
| 639 | arp_ptr += 4; | ||
| 640 | memcpy(arp_ptr, sha, np->dev->addr_len); | ||
| 641 | arp_ptr += np->dev->addr_len; | ||
| 642 | memcpy(arp_ptr, &sip, 4); | ||
| 643 | |||
| 644 | netpoll_send_skb(np, send_skb); | ||
| 645 | |||
| 646 | /* If there are several rx_skb_hooks for the same | ||
| 647 | * address we're fine by sending a single reply | ||
| 648 | */ | ||
| 649 | break; | ||
| 650 | } | ||
| 651 | spin_unlock_irqrestore(&npinfo->rx_lock, flags); | ||
| 652 | } else if( proto == ETH_P_IPV6) { | ||
| 653 | #if IS_ENABLED(CONFIG_IPV6) | ||
| 654 | struct nd_msg *msg; | ||
| 655 | u8 *lladdr = NULL; | ||
| 656 | struct ipv6hdr *hdr; | ||
| 657 | struct icmp6hdr *icmp6h; | ||
| 658 | const struct in6_addr *saddr; | ||
| 659 | const struct in6_addr *daddr; | ||
| 660 | struct inet6_dev *in6_dev = NULL; | ||
| 661 | struct in6_addr *target; | ||
| 662 | |||
| 663 | in6_dev = in6_dev_get(skb->dev); | ||
| 664 | if (!in6_dev || !in6_dev->cnf.accept_ra) | ||
| 665 | return; | ||
| 666 | |||
| 667 | if (!pskb_may_pull(skb, skb->len)) | ||
| 668 | return; | ||
| 669 | |||
| 670 | msg = (struct nd_msg *)skb_transport_header(skb); | ||
| 671 | |||
| 672 | __skb_push(skb, skb->data - skb_transport_header(skb)); | ||
| 673 | |||
| 674 | if (ipv6_hdr(skb)->hop_limit != 255) | ||
| 675 | return; | ||
| 676 | if (msg->icmph.icmp6_code != 0) | ||
| 677 | return; | ||
| 678 | if (msg->icmph.icmp6_type != NDISC_NEIGHBOUR_SOLICITATION) | ||
| 679 | return; | ||
| 680 | |||
| 681 | saddr = &ipv6_hdr(skb)->saddr; | ||
| 682 | daddr = &ipv6_hdr(skb)->daddr; | ||
| 683 | |||
| 684 | size = sizeof(struct icmp6hdr) + sizeof(struct in6_addr); | ||
| 685 | |||
| 686 | spin_lock_irqsave(&npinfo->rx_lock, flags); | ||
| 687 | list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) { | ||
| 688 | if (!ipv6_addr_equal(daddr, &np->local_ip.in6)) | ||
| 689 | continue; | ||
| 690 | |||
| 691 | hlen = LL_RESERVED_SPACE(np->dev); | ||
| 692 | tlen = np->dev->needed_tailroom; | ||
| 693 | send_skb = find_skb(np, size + hlen + tlen, hlen); | ||
| 694 | if (!send_skb) | ||
| 695 | continue; | ||
| 696 | |||
| 697 | send_skb->protocol = htons(ETH_P_IPV6); | ||
| 698 | send_skb->dev = skb->dev; | ||
| 699 | |||
| 700 | skb_reset_network_header(send_skb); | ||
| 701 | hdr = (struct ipv6hdr *) skb_put(send_skb, sizeof(struct ipv6hdr)); | ||
| 702 | *(__be32*)hdr = htonl(0x60000000); | ||
| 703 | hdr->payload_len = htons(size); | ||
| 704 | hdr->nexthdr = IPPROTO_ICMPV6; | ||
| 705 | hdr->hop_limit = 255; | ||
| 706 | hdr->saddr = *saddr; | ||
| 707 | hdr->daddr = *daddr; | ||
| 708 | |||
| 709 | icmp6h = (struct icmp6hdr *) skb_put(send_skb, sizeof(struct icmp6hdr)); | ||
| 710 | icmp6h->icmp6_type = NDISC_NEIGHBOUR_ADVERTISEMENT; | ||
| 711 | icmp6h->icmp6_router = 0; | ||
| 712 | icmp6h->icmp6_solicited = 1; | ||
| 713 | |||
| 714 | target = (struct in6_addr *) skb_put(send_skb, sizeof(struct in6_addr)); | ||
| 715 | *target = msg->target; | ||
| 716 | icmp6h->icmp6_cksum = csum_ipv6_magic(saddr, daddr, size, | ||
| 717 | IPPROTO_ICMPV6, | ||
| 718 | csum_partial(icmp6h, | ||
| 719 | size, 0)); | ||
| 720 | |||
| 721 | if (dev_hard_header(send_skb, skb->dev, ETH_P_IPV6, | ||
| 722 | lladdr, np->dev->dev_addr, | ||
| 723 | send_skb->len) < 0) { | ||
| 724 | kfree_skb(send_skb); | ||
| 725 | continue; | ||
| 726 | } | ||
| 727 | |||
| 728 | netpoll_send_skb(np, send_skb); | ||
| 729 | |||
| 730 | /* If there are several rx_skb_hooks for the same | ||
| 731 | * address, we're fine by sending a single reply | ||
| 732 | */ | ||
| 733 | break; | ||
| 734 | } | ||
| 735 | spin_unlock_irqrestore(&npinfo->rx_lock, flags); | ||
| 736 | #endif | ||
| 737 | } | ||
| 738 | } | ||
| 739 | |||
| 740 | static bool pkt_is_ns(struct sk_buff *skb) | ||
| 741 | { | ||
| 742 | struct nd_msg *msg; | ||
| 743 | struct ipv6hdr *hdr; | ||
| 744 | |||
| 745 | if (skb->protocol != htons(ETH_P_IPV6)) | ||
| 746 | return false; | ||
| 747 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + sizeof(struct nd_msg))) | ||
| 748 | return false; | ||
| 749 | |||
| 750 | msg = (struct nd_msg *)skb_transport_header(skb); | ||
| 751 | __skb_push(skb, skb->data - skb_transport_header(skb)); | ||
| 752 | hdr = ipv6_hdr(skb); | ||
| 753 | |||
| 754 | if (hdr->nexthdr != IPPROTO_ICMPV6) | ||
| 755 | return false; | ||
| 756 | if (hdr->hop_limit != 255) | ||
| 757 | return false; | ||
| 758 | if (msg->icmph.icmp6_code != 0) | ||
| 759 | return false; | ||
| 760 | if (msg->icmph.icmp6_type != NDISC_NEIGHBOUR_SOLICITATION) | ||
| 761 | return false; | ||
| 762 | |||
| 763 | return true; | ||
| 764 | } | ||
| 765 | |||
| 766 | int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo) | ||
| 767 | { | ||
| 768 | int proto, len, ulen, data_len; | ||
| 769 | int hits = 0, offset; | ||
| 770 | const struct iphdr *iph; | ||
| 771 | struct udphdr *uh; | ||
| 772 | struct netpoll *np, *tmp; | ||
| 773 | uint16_t source; | ||
| 774 | |||
| 775 | if (list_empty(&npinfo->rx_np)) | ||
| 776 | goto out; | ||
| 777 | |||
| 778 | if (skb->dev->type != ARPHRD_ETHER) | ||
| 779 | goto out; | ||
| 780 | |||
| 781 | /* check if netpoll clients need ARP */ | ||
| 782 | if (skb->protocol == htons(ETH_P_ARP) && atomic_read(&trapped)) { | ||
| 783 | skb_queue_tail(&npinfo->neigh_tx, skb); | ||
| 784 | return 1; | ||
| 785 | } else if (pkt_is_ns(skb) && atomic_read(&trapped)) { | ||
| 786 | skb_queue_tail(&npinfo->neigh_tx, skb); | ||
| 787 | return 1; | ||
| 788 | } | ||
| 789 | |||
| 790 | if (skb->protocol == cpu_to_be16(ETH_P_8021Q)) { | ||
| 791 | skb = vlan_untag(skb); | ||
| 792 | if (unlikely(!skb)) | ||
| 793 | goto out; | ||
| 794 | } | ||
| 795 | |||
| 796 | proto = ntohs(eth_hdr(skb)->h_proto); | ||
| 797 | if (proto != ETH_P_IP && proto != ETH_P_IPV6) | ||
| 798 | goto out; | ||
| 799 | if (skb->pkt_type == PACKET_OTHERHOST) | ||
| 800 | goto out; | ||
| 801 | if (skb_shared(skb)) | ||
| 802 | goto out; | ||
| 803 | |||
| 804 | if (proto == ETH_P_IP) { | ||
| 805 | if (!pskb_may_pull(skb, sizeof(struct iphdr))) | ||
| 806 | goto out; | ||
| 807 | iph = (struct iphdr *)skb->data; | ||
| 808 | if (iph->ihl < 5 || iph->version != 4) | ||
| 809 | goto out; | ||
| 810 | if (!pskb_may_pull(skb, iph->ihl*4)) | ||
| 811 | goto out; | ||
| 812 | iph = (struct iphdr *)skb->data; | ||
| 813 | if (ip_fast_csum((u8 *)iph, iph->ihl) != 0) | ||
| 814 | goto out; | ||
| 815 | |||
| 816 | len = ntohs(iph->tot_len); | ||
| 817 | if (skb->len < len || len < iph->ihl*4) | ||
| 818 | goto out; | ||
| 819 | |||
| 820 | /* | ||
| 821 | * Our transport medium may have padded the buffer out. | ||
| 822 | * Now We trim to the true length of the frame. | ||
| 823 | */ | ||
| 824 | if (pskb_trim_rcsum(skb, len)) | ||
| 825 | goto out; | ||
| 826 | |||
| 827 | iph = (struct iphdr *)skb->data; | ||
| 828 | if (iph->protocol != IPPROTO_UDP) | ||
| 829 | goto out; | ||
| 830 | |||
| 831 | len -= iph->ihl*4; | ||
| 832 | uh = (struct udphdr *)(((char *)iph) + iph->ihl*4); | ||
| 833 | offset = (unsigned char *)(uh + 1) - skb->data; | ||
| 834 | ulen = ntohs(uh->len); | ||
| 835 | data_len = skb->len - offset; | ||
| 836 | source = ntohs(uh->source); | ||
| 837 | |||
| 838 | if (ulen != len) | ||
| 839 | goto out; | ||
| 840 | if (checksum_udp(skb, uh, ulen, iph->saddr, iph->daddr)) | ||
| 841 | goto out; | ||
| 842 | list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) { | ||
| 843 | if (np->local_ip.ip && np->local_ip.ip != iph->daddr) | ||
| 844 | continue; | ||
| 845 | if (np->remote_ip.ip && np->remote_ip.ip != iph->saddr) | ||
| 846 | continue; | ||
| 847 | if (np->local_port && np->local_port != ntohs(uh->dest)) | ||
| 848 | continue; | ||
| 849 | |||
| 850 | np->rx_skb_hook(np, source, skb, offset, data_len); | ||
| 851 | hits++; | ||
| 852 | } | ||
| 853 | } else { | ||
| 854 | #if IS_ENABLED(CONFIG_IPV6) | ||
| 855 | const struct ipv6hdr *ip6h; | ||
| 856 | |||
| 857 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) | ||
| 858 | goto out; | ||
| 859 | ip6h = (struct ipv6hdr *)skb->data; | ||
| 860 | if (ip6h->version != 6) | ||
| 861 | goto out; | ||
| 862 | len = ntohs(ip6h->payload_len); | ||
| 863 | if (!len) | ||
| 864 | goto out; | ||
| 865 | if (len + sizeof(struct ipv6hdr) > skb->len) | ||
| 866 | goto out; | ||
| 867 | if (pskb_trim_rcsum(skb, len + sizeof(struct ipv6hdr))) | ||
| 868 | goto out; | ||
| 869 | ip6h = ipv6_hdr(skb); | ||
| 870 | if (!pskb_may_pull(skb, sizeof(struct udphdr))) | ||
| 871 | goto out; | ||
| 872 | uh = udp_hdr(skb); | ||
| 873 | offset = (unsigned char *)(uh + 1) - skb->data; | ||
| 874 | ulen = ntohs(uh->len); | ||
| 875 | data_len = skb->len - offset; | ||
| 876 | source = ntohs(uh->source); | ||
| 877 | if (ulen != skb->len) | ||
| 878 | goto out; | ||
| 879 | if (udp6_csum_init(skb, uh, IPPROTO_UDP)) | ||
| 880 | goto out; | ||
| 881 | list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) { | ||
| 882 | if (!ipv6_addr_equal(&np->local_ip.in6, &ip6h->daddr)) | ||
| 883 | continue; | ||
| 884 | if (!ipv6_addr_equal(&np->remote_ip.in6, &ip6h->saddr)) | ||
| 885 | continue; | ||
| 886 | if (np->local_port && np->local_port != ntohs(uh->dest)) | ||
| 887 | continue; | ||
| 888 | |||
| 889 | np->rx_skb_hook(np, source, skb, offset, data_len); | ||
| 890 | hits++; | ||
| 891 | } | ||
| 892 | #endif | ||
| 893 | } | ||
| 894 | |||
| 895 | if (!hits) | ||
| 896 | goto out; | ||
| 897 | |||
| 898 | kfree_skb(skb); | ||
| 899 | return 1; | ||
| 900 | |||
| 901 | out: | ||
| 902 | if (atomic_read(&trapped)) { | ||
| 903 | kfree_skb(skb); | ||
| 904 | return 1; | ||
| 905 | } | ||
| 906 | |||
| 907 | return 0; | ||
| 908 | } | ||
| 909 | |||
| 910 | void netpoll_print_options(struct netpoll *np) | 479 | void netpoll_print_options(struct netpoll *np) |
| 911 | { | 480 | { |
| 912 | np_info(np, "local port %d\n", np->local_port); | 481 | np_info(np, "local port %d\n", np->local_port); |
| @@ -1026,11 +595,10 @@ int netpoll_parse_options(struct netpoll *np, char *opt) | |||
| 1026 | } | 595 | } |
| 1027 | EXPORT_SYMBOL(netpoll_parse_options); | 596 | EXPORT_SYMBOL(netpoll_parse_options); |
| 1028 | 597 | ||
| 1029 | int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp) | 598 | int __netpoll_setup(struct netpoll *np, struct net_device *ndev) |
| 1030 | { | 599 | { |
| 1031 | struct netpoll_info *npinfo; | 600 | struct netpoll_info *npinfo; |
| 1032 | const struct net_device_ops *ops; | 601 | const struct net_device_ops *ops; |
| 1033 | unsigned long flags; | ||
| 1034 | int err; | 602 | int err; |
| 1035 | 603 | ||
| 1036 | np->dev = ndev; | 604 | np->dev = ndev; |
| @@ -1046,18 +614,13 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp) | |||
| 1046 | } | 614 | } |
| 1047 | 615 | ||
| 1048 | if (!ndev->npinfo) { | 616 | if (!ndev->npinfo) { |
| 1049 | npinfo = kmalloc(sizeof(*npinfo), gfp); | 617 | npinfo = kmalloc(sizeof(*npinfo), GFP_KERNEL); |
| 1050 | if (!npinfo) { | 618 | if (!npinfo) { |
| 1051 | err = -ENOMEM; | 619 | err = -ENOMEM; |
| 1052 | goto out; | 620 | goto out; |
| 1053 | } | 621 | } |
| 1054 | 622 | ||
| 1055 | npinfo->rx_flags = 0; | ||
| 1056 | INIT_LIST_HEAD(&npinfo->rx_np); | ||
| 1057 | |||
| 1058 | spin_lock_init(&npinfo->rx_lock); | ||
| 1059 | sema_init(&npinfo->dev_lock, 1); | 623 | sema_init(&npinfo->dev_lock, 1); |
| 1060 | skb_queue_head_init(&npinfo->neigh_tx); | ||
| 1061 | skb_queue_head_init(&npinfo->txq); | 624 | skb_queue_head_init(&npinfo->txq); |
| 1062 | INIT_DELAYED_WORK(&npinfo->tx_work, queue_process); | 625 | INIT_DELAYED_WORK(&npinfo->tx_work, queue_process); |
| 1063 | 626 | ||
| @@ -1065,7 +628,7 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp) | |||
| 1065 | 628 | ||
| 1066 | ops = np->dev->netdev_ops; | 629 | ops = np->dev->netdev_ops; |
| 1067 | if (ops->ndo_netpoll_setup) { | 630 | if (ops->ndo_netpoll_setup) { |
| 1068 | err = ops->ndo_netpoll_setup(ndev, npinfo, gfp); | 631 | err = ops->ndo_netpoll_setup(ndev, npinfo); |
| 1069 | if (err) | 632 | if (err) |
| 1070 | goto free_npinfo; | 633 | goto free_npinfo; |
| 1071 | } | 634 | } |
| @@ -1076,13 +639,6 @@ int __netpoll_setup(struct netpoll *np, struct net_device *ndev, gfp_t gfp) | |||
| 1076 | 639 | ||
| 1077 | npinfo->netpoll = np; | 640 | npinfo->netpoll = np; |
| 1078 | 641 | ||
| 1079 | if (np->rx_skb_hook) { | ||
| 1080 | spin_lock_irqsave(&npinfo->rx_lock, flags); | ||
| 1081 | npinfo->rx_flags |= NETPOLL_RX_ENABLED; | ||
| 1082 | list_add_tail(&np->rx, &npinfo->rx_np); | ||
| 1083 | spin_unlock_irqrestore(&npinfo->rx_lock, flags); | ||
| 1084 | } | ||
| 1085 | |||
| 1086 | /* last thing to do is link it to the net device structure */ | 642 | /* last thing to do is link it to the net device structure */ |
| 1087 | rcu_assign_pointer(ndev->npinfo, npinfo); | 643 | rcu_assign_pointer(ndev->npinfo, npinfo); |
| 1088 | 644 | ||
| @@ -1204,7 +760,7 @@ int netpoll_setup(struct netpoll *np) | |||
| 1204 | /* fill up the skb queue */ | 760 | /* fill up the skb queue */ |
| 1205 | refill_skbs(); | 761 | refill_skbs(); |
| 1206 | 762 | ||
| 1207 | err = __netpoll_setup(np, ndev, GFP_KERNEL); | 763 | err = __netpoll_setup(np, ndev); |
| 1208 | if (err) | 764 | if (err) |
| 1209 | goto put; | 765 | goto put; |
| 1210 | 766 | ||
| @@ -1231,7 +787,6 @@ static void rcu_cleanup_netpoll_info(struct rcu_head *rcu_head) | |||
| 1231 | struct netpoll_info *npinfo = | 787 | struct netpoll_info *npinfo = |
| 1232 | container_of(rcu_head, struct netpoll_info, rcu); | 788 | container_of(rcu_head, struct netpoll_info, rcu); |
| 1233 | 789 | ||
| 1234 | skb_queue_purge(&npinfo->neigh_tx); | ||
| 1235 | skb_queue_purge(&npinfo->txq); | 790 | skb_queue_purge(&npinfo->txq); |
| 1236 | 791 | ||
| 1237 | /* we can't call cancel_delayed_work_sync here, as we are in softirq */ | 792 | /* we can't call cancel_delayed_work_sync here, as we are in softirq */ |
| @@ -1247,7 +802,6 @@ static void rcu_cleanup_netpoll_info(struct rcu_head *rcu_head) | |||
| 1247 | void __netpoll_cleanup(struct netpoll *np) | 802 | void __netpoll_cleanup(struct netpoll *np) |
| 1248 | { | 803 | { |
| 1249 | struct netpoll_info *npinfo; | 804 | struct netpoll_info *npinfo; |
| 1250 | unsigned long flags; | ||
| 1251 | 805 | ||
| 1252 | /* rtnl_dereference would be preferable here but | 806 | /* rtnl_dereference would be preferable here but |
| 1253 | * rcu_cleanup_netpoll path can put us in here safely without | 807 | * rcu_cleanup_netpoll path can put us in here safely without |
| @@ -1257,14 +811,6 @@ void __netpoll_cleanup(struct netpoll *np) | |||
| 1257 | if (!npinfo) | 811 | if (!npinfo) |
| 1258 | return; | 812 | return; |
| 1259 | 813 | ||
| 1260 | if (!list_empty(&npinfo->rx_np)) { | ||
| 1261 | spin_lock_irqsave(&npinfo->rx_lock, flags); | ||
| 1262 | list_del(&np->rx); | ||
| 1263 | if (list_empty(&npinfo->rx_np)) | ||
| 1264 | npinfo->rx_flags &= ~NETPOLL_RX_ENABLED; | ||
| 1265 | spin_unlock_irqrestore(&npinfo->rx_lock, flags); | ||
| 1266 | } | ||
| 1267 | |||
| 1268 | synchronize_srcu(&netpoll_srcu); | 814 | synchronize_srcu(&netpoll_srcu); |
| 1269 | 815 | ||
| 1270 | if (atomic_dec_and_test(&npinfo->refcnt)) { | 816 | if (atomic_dec_and_test(&npinfo->refcnt)) { |
| @@ -1274,7 +820,7 @@ void __netpoll_cleanup(struct netpoll *np) | |||
| 1274 | if (ops->ndo_netpoll_cleanup) | 820 | if (ops->ndo_netpoll_cleanup) |
| 1275 | ops->ndo_netpoll_cleanup(np->dev); | 821 | ops->ndo_netpoll_cleanup(np->dev); |
| 1276 | 822 | ||
| 1277 | rcu_assign_pointer(np->dev->npinfo, NULL); | 823 | RCU_INIT_POINTER(np->dev->npinfo, NULL); |
| 1278 | call_rcu_bh(&npinfo->rcu, rcu_cleanup_netpoll_info); | 824 | call_rcu_bh(&npinfo->rcu, rcu_cleanup_netpoll_info); |
| 1279 | } | 825 | } |
| 1280 | } | 826 | } |
| @@ -1308,18 +854,3 @@ out: | |||
| 1308 | rtnl_unlock(); | 854 | rtnl_unlock(); |
| 1309 | } | 855 | } |
| 1310 | EXPORT_SYMBOL(netpoll_cleanup); | 856 | EXPORT_SYMBOL(netpoll_cleanup); |
| 1311 | |||
| 1312 | int netpoll_trap(void) | ||
| 1313 | { | ||
| 1314 | return atomic_read(&trapped); | ||
| 1315 | } | ||
| 1316 | EXPORT_SYMBOL(netpoll_trap); | ||
| 1317 | |||
| 1318 | void netpoll_set_trap(int trap) | ||
| 1319 | { | ||
| 1320 | if (trap) | ||
| 1321 | atomic_inc(&trapped); | ||
| 1322 | else | ||
| 1323 | atomic_dec(&trapped); | ||
| 1324 | } | ||
| 1325 | EXPORT_SYMBOL(netpoll_set_trap); | ||
diff --git a/net/core/netprio_cgroup.c b/net/core/netprio_cgroup.c index 9043caedcd08..3825f669147b 100644 --- a/net/core/netprio_cgroup.c +++ b/net/core/netprio_cgroup.c | |||
| @@ -186,7 +186,7 @@ static int read_priomap(struct seq_file *sf, void *v) | |||
| 186 | } | 186 | } |
| 187 | 187 | ||
| 188 | static int write_priomap(struct cgroup_subsys_state *css, struct cftype *cft, | 188 | static int write_priomap(struct cgroup_subsys_state *css, struct cftype *cft, |
| 189 | const char *buffer) | 189 | char *buffer) |
| 190 | { | 190 | { |
| 191 | char devname[IFNAMSIZ + 1]; | 191 | char devname[IFNAMSIZ + 1]; |
| 192 | struct net_device *dev; | 192 | struct net_device *dev; |
| @@ -224,7 +224,7 @@ static void net_prio_attach(struct cgroup_subsys_state *css, | |||
| 224 | struct task_struct *p; | 224 | struct task_struct *p; |
| 225 | void *v = (void *)(unsigned long)css->cgroup->id; | 225 | void *v = (void *)(unsigned long)css->cgroup->id; |
| 226 | 226 | ||
| 227 | cgroup_taskset_for_each(p, css, tset) { | 227 | cgroup_taskset_for_each(p, tset) { |
| 228 | task_lock(p); | 228 | task_lock(p); |
| 229 | iterate_fd(p->files, 0, update_netprio, v); | 229 | iterate_fd(p->files, 0, update_netprio, v); |
| 230 | task_unlock(p); | 230 | task_unlock(p); |
| @@ -244,15 +244,12 @@ static struct cftype ss_files[] = { | |||
| 244 | { } /* terminate */ | 244 | { } /* terminate */ |
| 245 | }; | 245 | }; |
| 246 | 246 | ||
| 247 | struct cgroup_subsys net_prio_subsys = { | 247 | struct cgroup_subsys net_prio_cgrp_subsys = { |
| 248 | .name = "net_prio", | ||
| 249 | .css_alloc = cgrp_css_alloc, | 248 | .css_alloc = cgrp_css_alloc, |
| 250 | .css_online = cgrp_css_online, | 249 | .css_online = cgrp_css_online, |
| 251 | .css_free = cgrp_css_free, | 250 | .css_free = cgrp_css_free, |
| 252 | .attach = net_prio_attach, | 251 | .attach = net_prio_attach, |
| 253 | .subsys_id = net_prio_subsys_id, | ||
| 254 | .base_cftypes = ss_files, | 252 | .base_cftypes = ss_files, |
| 255 | .module = THIS_MODULE, | ||
| 256 | }; | 253 | }; |
| 257 | 254 | ||
| 258 | static int netprio_device_event(struct notifier_block *unused, | 255 | static int netprio_device_event(struct notifier_block *unused, |
| @@ -283,37 +280,9 @@ static struct notifier_block netprio_device_notifier = { | |||
| 283 | 280 | ||
| 284 | static int __init init_cgroup_netprio(void) | 281 | static int __init init_cgroup_netprio(void) |
| 285 | { | 282 | { |
| 286 | int ret; | ||
| 287 | |||
| 288 | ret = cgroup_load_subsys(&net_prio_subsys); | ||
| 289 | if (ret) | ||
| 290 | goto out; | ||
| 291 | |||
| 292 | register_netdevice_notifier(&netprio_device_notifier); | 283 | register_netdevice_notifier(&netprio_device_notifier); |
| 293 | 284 | return 0; | |
| 294 | out: | ||
| 295 | return ret; | ||
| 296 | } | ||
| 297 | |||
| 298 | static void __exit exit_cgroup_netprio(void) | ||
| 299 | { | ||
| 300 | struct netprio_map *old; | ||
| 301 | struct net_device *dev; | ||
| 302 | |||
| 303 | unregister_netdevice_notifier(&netprio_device_notifier); | ||
| 304 | |||
| 305 | cgroup_unload_subsys(&net_prio_subsys); | ||
| 306 | |||
| 307 | rtnl_lock(); | ||
| 308 | for_each_netdev(&init_net, dev) { | ||
| 309 | old = rtnl_dereference(dev->priomap); | ||
| 310 | RCU_INIT_POINTER(dev->priomap, NULL); | ||
| 311 | if (old) | ||
| 312 | kfree_rcu(old, rcu); | ||
| 313 | } | ||
| 314 | rtnl_unlock(); | ||
| 315 | } | 285 | } |
| 316 | 286 | ||
| 317 | module_init(init_cgroup_netprio); | 287 | subsys_initcall(init_cgroup_netprio); |
| 318 | module_exit(exit_cgroup_netprio); | ||
| 319 | MODULE_LICENSE("GPL v2"); | 288 | MODULE_LICENSE("GPL v2"); |
diff --git a/net/core/pktgen.c b/net/core/pktgen.c index fdac61cac1bd..0304f981f7ff 100644 --- a/net/core/pktgen.c +++ b/net/core/pktgen.c | |||
| @@ -476,23 +476,22 @@ static int pgctrl_show(struct seq_file *seq, void *v) | |||
| 476 | static ssize_t pgctrl_write(struct file *file, const char __user *buf, | 476 | static ssize_t pgctrl_write(struct file *file, const char __user *buf, |
| 477 | size_t count, loff_t *ppos) | 477 | size_t count, loff_t *ppos) |
| 478 | { | 478 | { |
| 479 | int err = 0; | ||
| 480 | char data[128]; | 479 | char data[128]; |
| 481 | struct pktgen_net *pn = net_generic(current->nsproxy->net_ns, pg_net_id); | 480 | struct pktgen_net *pn = net_generic(current->nsproxy->net_ns, pg_net_id); |
| 482 | 481 | ||
| 483 | if (!capable(CAP_NET_ADMIN)) { | 482 | if (!capable(CAP_NET_ADMIN)) |
| 484 | err = -EPERM; | 483 | return -EPERM; |
| 485 | goto out; | 484 | |
| 486 | } | 485 | if (count == 0) |
| 486 | return -EINVAL; | ||
| 487 | 487 | ||
| 488 | if (count > sizeof(data)) | 488 | if (count > sizeof(data)) |
| 489 | count = sizeof(data); | 489 | count = sizeof(data); |
| 490 | 490 | ||
| 491 | if (copy_from_user(data, buf, count)) { | 491 | if (copy_from_user(data, buf, count)) |
| 492 | err = -EFAULT; | 492 | return -EFAULT; |
| 493 | goto out; | 493 | |
| 494 | } | 494 | data[count - 1] = 0; /* Strip trailing '\n' and terminate string */ |
| 495 | data[count - 1] = 0; /* Make string */ | ||
| 496 | 495 | ||
| 497 | if (!strcmp(data, "stop")) | 496 | if (!strcmp(data, "stop")) |
| 498 | pktgen_stop_all_threads_ifs(pn); | 497 | pktgen_stop_all_threads_ifs(pn); |
| @@ -506,10 +505,7 @@ static ssize_t pgctrl_write(struct file *file, const char __user *buf, | |||
| 506 | else | 505 | else |
| 507 | pr_warning("Unknown command: %s\n", data); | 506 | pr_warning("Unknown command: %s\n", data); |
| 508 | 507 | ||
| 509 | err = count; | 508 | return count; |
| 510 | |||
| 511 | out: | ||
| 512 | return err; | ||
| 513 | } | 509 | } |
| 514 | 510 | ||
| 515 | static int pgctrl_open(struct inode *inode, struct file *file) | 511 | static int pgctrl_open(struct inode *inode, struct file *file) |
| @@ -1251,7 +1247,13 @@ static ssize_t pktgen_if_write(struct file *file, | |||
| 1251 | "Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s", | 1247 | "Flag -:%s:- unknown\nAvailable flags, (prepend ! to un-set flag):\n%s", |
| 1252 | f, | 1248 | f, |
| 1253 | "IPSRC_RND, IPDST_RND, UDPSRC_RND, UDPDST_RND, " | 1249 | "IPSRC_RND, IPDST_RND, UDPSRC_RND, UDPDST_RND, " |
| 1254 | "MACSRC_RND, MACDST_RND, TXSIZE_RND, IPV6, MPLS_RND, VID_RND, SVID_RND, FLOW_SEQ, IPSEC, NODE_ALLOC\n"); | 1250 | "MACSRC_RND, MACDST_RND, TXSIZE_RND, IPV6, " |
| 1251 | "MPLS_RND, VID_RND, SVID_RND, FLOW_SEQ, " | ||
| 1252 | "QUEUE_MAP_RND, QUEUE_MAP_CPU, UDPCSUM, " | ||
| 1253 | #ifdef CONFIG_XFRM | ||
| 1254 | "IPSEC, " | ||
| 1255 | #endif | ||
| 1256 | "NODE_ALLOC\n"); | ||
| 1255 | return count; | 1257 | return count; |
| 1256 | } | 1258 | } |
| 1257 | sprintf(pg_result, "OK: flags=0x%x", pkt_dev->flags); | 1259 | sprintf(pg_result, "OK: flags=0x%x", pkt_dev->flags); |
| @@ -3336,9 +3338,11 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev) | |||
| 3336 | queue_map = skb_get_queue_mapping(pkt_dev->skb); | 3338 | queue_map = skb_get_queue_mapping(pkt_dev->skb); |
| 3337 | txq = netdev_get_tx_queue(odev, queue_map); | 3339 | txq = netdev_get_tx_queue(odev, queue_map); |
| 3338 | 3340 | ||
| 3339 | __netif_tx_lock_bh(txq); | 3341 | local_bh_disable(); |
| 3340 | 3342 | ||
| 3341 | if (unlikely(netif_xmit_frozen_or_stopped(txq))) { | 3343 | HARD_TX_LOCK(odev, txq, smp_processor_id()); |
| 3344 | |||
| 3345 | if (unlikely(netif_xmit_frozen_or_drv_stopped(txq))) { | ||
| 3342 | ret = NETDEV_TX_BUSY; | 3346 | ret = NETDEV_TX_BUSY; |
| 3343 | pkt_dev->last_ok = 0; | 3347 | pkt_dev->last_ok = 0; |
| 3344 | goto unlock; | 3348 | goto unlock; |
| @@ -3372,7 +3376,9 @@ static void pktgen_xmit(struct pktgen_dev *pkt_dev) | |||
| 3372 | pkt_dev->last_ok = 0; | 3376 | pkt_dev->last_ok = 0; |
| 3373 | } | 3377 | } |
| 3374 | unlock: | 3378 | unlock: |
| 3375 | __netif_tx_unlock_bh(txq); | 3379 | HARD_TX_UNLOCK(odev, txq); |
| 3380 | |||
| 3381 | local_bh_enable(); | ||
| 3376 | 3382 | ||
| 3377 | /* If pkt_dev->count is zero, then run forever */ | 3383 | /* If pkt_dev->count is zero, then run forever */ |
| 3378 | if ((pkt_dev->count != 0) && (pkt_dev->sofar >= pkt_dev->count)) { | 3384 | if ((pkt_dev->count != 0) && (pkt_dev->sofar >= pkt_dev->count)) { |
diff --git a/net/core/ptp_classifier.c b/net/core/ptp_classifier.c new file mode 100644 index 000000000000..eaba0f68f860 --- /dev/null +++ b/net/core/ptp_classifier.c | |||
| @@ -0,0 +1,141 @@ | |||
| 1 | /* PTP classifier | ||
| 2 | * | ||
| 3 | * This program is free software; you can redistribute it and/or | ||
| 4 | * modify it under the terms of version 2 of the GNU General Public | ||
| 5 | * License as published by the Free Software Foundation. | ||
| 6 | * | ||
| 7 | * This program is distributed in the hope that it will be useful, but | ||
| 8 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
| 10 | * General Public License for more details. | ||
| 11 | */ | ||
| 12 | |||
| 13 | /* The below program is the bpf_asm (tools/net/) representation of | ||
| 14 | * the opcode array in the ptp_filter structure. | ||
| 15 | * | ||
| 16 | * For convenience, this can easily be altered and reviewed with | ||
| 17 | * bpf_asm and bpf_dbg, e.g. `./bpf_asm -c prog` where prog is a | ||
| 18 | * simple file containing the below program: | ||
| 19 | * | ||
| 20 | * ldh [12] ; load ethertype | ||
| 21 | * | ||
| 22 | * ; PTP over UDP over IPv4 over Ethernet | ||
| 23 | * test_ipv4: | ||
| 24 | * jneq #0x800, test_ipv6 ; ETH_P_IP ? | ||
| 25 | * ldb [23] ; load proto | ||
| 26 | * jneq #17, drop_ipv4 ; IPPROTO_UDP ? | ||
| 27 | * ldh [20] ; load frag offset field | ||
| 28 | * jset #0x1fff, drop_ipv4 ; don't allow fragments | ||
| 29 | * ldxb 4*([14]&0xf) ; load IP header len | ||
| 30 | * ldh [x + 16] ; load UDP dst port | ||
| 31 | * jneq #319, drop_ipv4 ; is port PTP_EV_PORT ? | ||
| 32 | * ldh [x + 22] ; load payload | ||
| 33 | * and #0xf ; mask PTP_CLASS_VMASK | ||
| 34 | * or #0x10 ; PTP_CLASS_IPV4 | ||
| 35 | * ret a ; return PTP class | ||
| 36 | * drop_ipv4: ret #0x0 ; PTP_CLASS_NONE | ||
| 37 | * | ||
| 38 | * ; PTP over UDP over IPv6 over Ethernet | ||
| 39 | * test_ipv6: | ||
| 40 | * jneq #0x86dd, test_8021q ; ETH_P_IPV6 ? | ||
| 41 | * ldb [20] ; load proto | ||
| 42 | * jneq #17, drop_ipv6 ; IPPROTO_UDP ? | ||
| 43 | * ldh [56] ; load UDP dst port | ||
| 44 | * jneq #319, drop_ipv6 ; is port PTP_EV_PORT ? | ||
| 45 | * ldh [62] ; load payload | ||
| 46 | * and #0xf ; mask PTP_CLASS_VMASK | ||
| 47 | * or #0x20 ; PTP_CLASS_IPV6 | ||
| 48 | * ret a ; return PTP class | ||
| 49 | * drop_ipv6: ret #0x0 ; PTP_CLASS_NONE | ||
| 50 | * | ||
| 51 | * ; PTP over 802.1Q over Ethernet | ||
| 52 | * test_8021q: | ||
| 53 | * jneq #0x8100, test_ieee1588 ; ETH_P_8021Q ? | ||
| 54 | * ldh [16] ; load inner type | ||
| 55 | * jneq #0x88f7, drop_ieee1588 ; ETH_P_1588 ? | ||
| 56 | * ldb [18] ; load payload | ||
| 57 | * and #0x8 ; as we don't have ports here, test | ||
| 58 | * jneq #0x0, drop_ieee1588 ; for PTP_GEN_BIT and drop these | ||
| 59 | * ldh [18] ; reload payload | ||
| 60 | * and #0xf ; mask PTP_CLASS_VMASK | ||
| 61 | * or #0x40 ; PTP_CLASS_V2_VLAN | ||
| 62 | * ret a ; return PTP class | ||
| 63 | * | ||
| 64 | * ; PTP over Ethernet | ||
| 65 | * test_ieee1588: | ||
| 66 | * jneq #0x88f7, drop_ieee1588 ; ETH_P_1588 ? | ||
| 67 | * ldb [14] ; load payload | ||
| 68 | * and #0x8 ; as we don't have ports here, test | ||
| 69 | * jneq #0x0, drop_ieee1588 ; for PTP_GEN_BIT and drop these | ||
| 70 | * ldh [14] ; reload payload | ||
| 71 | * and #0xf ; mask PTP_CLASS_VMASK | ||
| 72 | * or #0x30 ; PTP_CLASS_L2 | ||
| 73 | * ret a ; return PTP class | ||
| 74 | * drop_ieee1588: ret #0x0 ; PTP_CLASS_NONE | ||
| 75 | */ | ||
| 76 | |||
| 77 | #include <linux/skbuff.h> | ||
| 78 | #include <linux/filter.h> | ||
| 79 | #include <linux/ptp_classify.h> | ||
| 80 | |||
| 81 | static struct sk_filter *ptp_insns __read_mostly; | ||
| 82 | |||
| 83 | unsigned int ptp_classify_raw(const struct sk_buff *skb) | ||
| 84 | { | ||
| 85 | return SK_RUN_FILTER(ptp_insns, skb); | ||
| 86 | } | ||
| 87 | EXPORT_SYMBOL_GPL(ptp_classify_raw); | ||
| 88 | |||
| 89 | void __init ptp_classifier_init(void) | ||
| 90 | { | ||
| 91 | static struct sock_filter ptp_filter[] = { | ||
| 92 | { 0x28, 0, 0, 0x0000000c }, | ||
| 93 | { 0x15, 0, 12, 0x00000800 }, | ||
| 94 | { 0x30, 0, 0, 0x00000017 }, | ||
| 95 | { 0x15, 0, 9, 0x00000011 }, | ||
| 96 | { 0x28, 0, 0, 0x00000014 }, | ||
| 97 | { 0x45, 7, 0, 0x00001fff }, | ||
| 98 | { 0xb1, 0, 0, 0x0000000e }, | ||
| 99 | { 0x48, 0, 0, 0x00000010 }, | ||
| 100 | { 0x15, 0, 4, 0x0000013f }, | ||
| 101 | { 0x48, 0, 0, 0x00000016 }, | ||
| 102 | { 0x54, 0, 0, 0x0000000f }, | ||
| 103 | { 0x44, 0, 0, 0x00000010 }, | ||
| 104 | { 0x16, 0, 0, 0x00000000 }, | ||
| 105 | { 0x06, 0, 0, 0x00000000 }, | ||
| 106 | { 0x15, 0, 9, 0x000086dd }, | ||
| 107 | { 0x30, 0, 0, 0x00000014 }, | ||
| 108 | { 0x15, 0, 6, 0x00000011 }, | ||
| 109 | { 0x28, 0, 0, 0x00000038 }, | ||
| 110 | { 0x15, 0, 4, 0x0000013f }, | ||
| 111 | { 0x28, 0, 0, 0x0000003e }, | ||
| 112 | { 0x54, 0, 0, 0x0000000f }, | ||
| 113 | { 0x44, 0, 0, 0x00000020 }, | ||
| 114 | { 0x16, 0, 0, 0x00000000 }, | ||
| 115 | { 0x06, 0, 0, 0x00000000 }, | ||
| 116 | { 0x15, 0, 9, 0x00008100 }, | ||
| 117 | { 0x28, 0, 0, 0x00000010 }, | ||
| 118 | { 0x15, 0, 15, 0x000088f7 }, | ||
| 119 | { 0x30, 0, 0, 0x00000012 }, | ||
| 120 | { 0x54, 0, 0, 0x00000008 }, | ||
| 121 | { 0x15, 0, 12, 0x00000000 }, | ||
| 122 | { 0x28, 0, 0, 0x00000012 }, | ||
| 123 | { 0x54, 0, 0, 0x0000000f }, | ||
| 124 | { 0x44, 0, 0, 0x00000040 }, | ||
| 125 | { 0x16, 0, 0, 0x00000000 }, | ||
| 126 | { 0x15, 0, 7, 0x000088f7 }, | ||
| 127 | { 0x30, 0, 0, 0x0000000e }, | ||
| 128 | { 0x54, 0, 0, 0x00000008 }, | ||
| 129 | { 0x15, 0, 4, 0x00000000 }, | ||
| 130 | { 0x28, 0, 0, 0x0000000e }, | ||
| 131 | { 0x54, 0, 0, 0x0000000f }, | ||
| 132 | { 0x44, 0, 0, 0x00000030 }, | ||
| 133 | { 0x16, 0, 0, 0x00000000 }, | ||
| 134 | { 0x06, 0, 0, 0x00000000 }, | ||
| 135 | }; | ||
| 136 | struct sock_fprog ptp_prog = { | ||
| 137 | .len = ARRAY_SIZE(ptp_filter), .filter = ptp_filter, | ||
| 138 | }; | ||
| 139 | |||
| 140 | BUG_ON(sk_unattached_filter_create(&ptp_insns, &ptp_prog)); | ||
| 141 | } | ||
diff --git a/net/core/request_sock.c b/net/core/request_sock.c index 4425148d2b51..467f326126e0 100644 --- a/net/core/request_sock.c +++ b/net/core/request_sock.c | |||
| @@ -221,5 +221,4 @@ void reqsk_fastopen_remove(struct sock *sk, struct request_sock *req, | |||
| 221 | out: | 221 | out: |
| 222 | spin_unlock_bh(&fastopenq->lock); | 222 | spin_unlock_bh(&fastopenq->lock); |
| 223 | sock_put(lsk); | 223 | sock_put(lsk); |
| 224 | return; | ||
| 225 | } | 224 | } |
diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 120eecc0f5a4..d4ff41739b0f 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c | |||
| @@ -822,6 +822,7 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev, | |||
| 822 | + nla_total_size(4) /* IFLA_NUM_RX_QUEUES */ | 822 | + nla_total_size(4) /* IFLA_NUM_RX_QUEUES */ |
| 823 | + nla_total_size(1) /* IFLA_OPERSTATE */ | 823 | + nla_total_size(1) /* IFLA_OPERSTATE */ |
| 824 | + nla_total_size(1) /* IFLA_LINKMODE */ | 824 | + nla_total_size(1) /* IFLA_LINKMODE */ |
| 825 | + nla_total_size(4) /* IFLA_CARRIER_CHANGES */ | ||
| 825 | + nla_total_size(ext_filter_mask | 826 | + nla_total_size(ext_filter_mask |
| 826 | & RTEXT_FILTER_VF ? 4 : 0) /* IFLA_NUM_VF */ | 827 | & RTEXT_FILTER_VF ? 4 : 0) /* IFLA_NUM_VF */ |
| 827 | + rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */ | 828 | + rtnl_vfinfo_size(dev, ext_filter_mask) /* IFLA_VFINFO_LIST */ |
| @@ -970,7 +971,9 @@ static int rtnl_fill_ifinfo(struct sk_buff *skb, struct net_device *dev, | |||
| 970 | (dev->qdisc && | 971 | (dev->qdisc && |
| 971 | nla_put_string(skb, IFLA_QDISC, dev->qdisc->ops->id)) || | 972 | nla_put_string(skb, IFLA_QDISC, dev->qdisc->ops->id)) || |
| 972 | (dev->ifalias && | 973 | (dev->ifalias && |
| 973 | nla_put_string(skb, IFLA_IFALIAS, dev->ifalias))) | 974 | nla_put_string(skb, IFLA_IFALIAS, dev->ifalias)) || |
| 975 | nla_put_u32(skb, IFLA_CARRIER_CHANGES, | ||
| 976 | atomic_read(&dev->carrier_changes))) | ||
| 974 | goto nla_put_failure; | 977 | goto nla_put_failure; |
| 975 | 978 | ||
| 976 | if (1) { | 979 | if (1) { |
| @@ -1121,56 +1124,7 @@ nla_put_failure: | |||
| 1121 | return -EMSGSIZE; | 1124 | return -EMSGSIZE; |
| 1122 | } | 1125 | } |
| 1123 | 1126 | ||
| 1124 | static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | 1127 | static const struct nla_policy ifla_policy[IFLA_MAX+1] = { |
| 1125 | { | ||
| 1126 | struct net *net = sock_net(skb->sk); | ||
| 1127 | int h, s_h; | ||
| 1128 | int idx = 0, s_idx; | ||
| 1129 | struct net_device *dev; | ||
| 1130 | struct hlist_head *head; | ||
| 1131 | struct nlattr *tb[IFLA_MAX+1]; | ||
| 1132 | u32 ext_filter_mask = 0; | ||
| 1133 | |||
| 1134 | s_h = cb->args[0]; | ||
| 1135 | s_idx = cb->args[1]; | ||
| 1136 | |||
| 1137 | rcu_read_lock(); | ||
| 1138 | cb->seq = net->dev_base_seq; | ||
| 1139 | |||
| 1140 | if (nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX, | ||
| 1141 | ifla_policy) >= 0) { | ||
| 1142 | |||
| 1143 | if (tb[IFLA_EXT_MASK]) | ||
| 1144 | ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]); | ||
| 1145 | } | ||
| 1146 | |||
| 1147 | for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { | ||
| 1148 | idx = 0; | ||
| 1149 | head = &net->dev_index_head[h]; | ||
| 1150 | hlist_for_each_entry_rcu(dev, head, index_hlist) { | ||
| 1151 | if (idx < s_idx) | ||
| 1152 | goto cont; | ||
| 1153 | if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK, | ||
| 1154 | NETLINK_CB(cb->skb).portid, | ||
| 1155 | cb->nlh->nlmsg_seq, 0, | ||
| 1156 | NLM_F_MULTI, | ||
| 1157 | ext_filter_mask) <= 0) | ||
| 1158 | goto out; | ||
| 1159 | |||
| 1160 | nl_dump_check_consistent(cb, nlmsg_hdr(skb)); | ||
| 1161 | cont: | ||
| 1162 | idx++; | ||
| 1163 | } | ||
| 1164 | } | ||
| 1165 | out: | ||
| 1166 | rcu_read_unlock(); | ||
| 1167 | cb->args[1] = idx; | ||
| 1168 | cb->args[0] = h; | ||
| 1169 | |||
| 1170 | return skb->len; | ||
| 1171 | } | ||
| 1172 | |||
| 1173 | const struct nla_policy ifla_policy[IFLA_MAX+1] = { | ||
| 1174 | [IFLA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ-1 }, | 1128 | [IFLA_IFNAME] = { .type = NLA_STRING, .len = IFNAMSIZ-1 }, |
| 1175 | [IFLA_ADDRESS] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN }, | 1129 | [IFLA_ADDRESS] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN }, |
| 1176 | [IFLA_BROADCAST] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN }, | 1130 | [IFLA_BROADCAST] = { .type = NLA_BINARY, .len = MAX_ADDR_LEN }, |
| @@ -1196,8 +1150,8 @@ const struct nla_policy ifla_policy[IFLA_MAX+1] = { | |||
| 1196 | [IFLA_NUM_TX_QUEUES] = { .type = NLA_U32 }, | 1150 | [IFLA_NUM_TX_QUEUES] = { .type = NLA_U32 }, |
| 1197 | [IFLA_NUM_RX_QUEUES] = { .type = NLA_U32 }, | 1151 | [IFLA_NUM_RX_QUEUES] = { .type = NLA_U32 }, |
| 1198 | [IFLA_PHYS_PORT_ID] = { .type = NLA_BINARY, .len = MAX_PHYS_PORT_ID_LEN }, | 1152 | [IFLA_PHYS_PORT_ID] = { .type = NLA_BINARY, .len = MAX_PHYS_PORT_ID_LEN }, |
| 1153 | [IFLA_CARRIER_CHANGES] = { .type = NLA_U32 }, /* ignored */ | ||
| 1199 | }; | 1154 | }; |
| 1200 | EXPORT_SYMBOL(ifla_policy); | ||
| 1201 | 1155 | ||
| 1202 | static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { | 1156 | static const struct nla_policy ifla_info_policy[IFLA_INFO_MAX+1] = { |
| 1203 | [IFLA_INFO_KIND] = { .type = NLA_STRING }, | 1157 | [IFLA_INFO_KIND] = { .type = NLA_STRING }, |
| @@ -1235,6 +1189,61 @@ static const struct nla_policy ifla_port_policy[IFLA_PORT_MAX+1] = { | |||
| 1235 | [IFLA_PORT_RESPONSE] = { .type = NLA_U16, }, | 1189 | [IFLA_PORT_RESPONSE] = { .type = NLA_U16, }, |
| 1236 | }; | 1190 | }; |
| 1237 | 1191 | ||
| 1192 | static int rtnl_dump_ifinfo(struct sk_buff *skb, struct netlink_callback *cb) | ||
| 1193 | { | ||
| 1194 | struct net *net = sock_net(skb->sk); | ||
| 1195 | int h, s_h; | ||
| 1196 | int idx = 0, s_idx; | ||
| 1197 | struct net_device *dev; | ||
| 1198 | struct hlist_head *head; | ||
| 1199 | struct nlattr *tb[IFLA_MAX+1]; | ||
| 1200 | u32 ext_filter_mask = 0; | ||
| 1201 | |||
| 1202 | s_h = cb->args[0]; | ||
| 1203 | s_idx = cb->args[1]; | ||
| 1204 | |||
| 1205 | rcu_read_lock(); | ||
| 1206 | cb->seq = net->dev_base_seq; | ||
| 1207 | |||
| 1208 | if (nlmsg_parse(cb->nlh, sizeof(struct ifinfomsg), tb, IFLA_MAX, | ||
| 1209 | ifla_policy) >= 0) { | ||
| 1210 | |||
| 1211 | if (tb[IFLA_EXT_MASK]) | ||
| 1212 | ext_filter_mask = nla_get_u32(tb[IFLA_EXT_MASK]); | ||
| 1213 | } | ||
| 1214 | |||
| 1215 | for (h = s_h; h < NETDEV_HASHENTRIES; h++, s_idx = 0) { | ||
| 1216 | idx = 0; | ||
| 1217 | head = &net->dev_index_head[h]; | ||
| 1218 | hlist_for_each_entry_rcu(dev, head, index_hlist) { | ||
| 1219 | if (idx < s_idx) | ||
| 1220 | goto cont; | ||
| 1221 | if (rtnl_fill_ifinfo(skb, dev, RTM_NEWLINK, | ||
| 1222 | NETLINK_CB(cb->skb).portid, | ||
| 1223 | cb->nlh->nlmsg_seq, 0, | ||
| 1224 | NLM_F_MULTI, | ||
| 1225 | ext_filter_mask) <= 0) | ||
| 1226 | goto out; | ||
| 1227 | |||
| 1228 | nl_dump_check_consistent(cb, nlmsg_hdr(skb)); | ||
| 1229 | cont: | ||
| 1230 | idx++; | ||
| 1231 | } | ||
| 1232 | } | ||
| 1233 | out: | ||
| 1234 | rcu_read_unlock(); | ||
| 1235 | cb->args[1] = idx; | ||
| 1236 | cb->args[0] = h; | ||
| 1237 | |||
| 1238 | return skb->len; | ||
| 1239 | } | ||
| 1240 | |||
| 1241 | int rtnl_nla_parse_ifla(struct nlattr **tb, const struct nlattr *head, int len) | ||
| 1242 | { | ||
| 1243 | return nla_parse(tb, IFLA_MAX, head, len, ifla_policy); | ||
| 1244 | } | ||
| 1245 | EXPORT_SYMBOL(rtnl_nla_parse_ifla); | ||
| 1246 | |||
| 1238 | struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]) | 1247 | struct net *rtnl_link_get_net(struct net *src_net, struct nlattr *tb[]) |
| 1239 | { | 1248 | { |
| 1240 | struct net *net; | 1249 | struct net *net; |
diff --git a/net/core/skbuff.c b/net/core/skbuff.c index 90b96a11b974..1b62343f5837 100644 --- a/net/core/skbuff.c +++ b/net/core/skbuff.c | |||
| @@ -3300,6 +3300,32 @@ __skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) | |||
| 3300 | return elt; | 3300 | return elt; |
| 3301 | } | 3301 | } |
| 3302 | 3302 | ||
| 3303 | /* As compared with skb_to_sgvec, skb_to_sgvec_nomark only map skb to given | ||
| 3304 | * sglist without mark the sg which contain last skb data as the end. | ||
| 3305 | * So the caller can mannipulate sg list as will when padding new data after | ||
| 3306 | * the first call without calling sg_unmark_end to expend sg list. | ||
| 3307 | * | ||
| 3308 | * Scenario to use skb_to_sgvec_nomark: | ||
| 3309 | * 1. sg_init_table | ||
| 3310 | * 2. skb_to_sgvec_nomark(payload1) | ||
| 3311 | * 3. skb_to_sgvec_nomark(payload2) | ||
| 3312 | * | ||
| 3313 | * This is equivalent to: | ||
| 3314 | * 1. sg_init_table | ||
| 3315 | * 2. skb_to_sgvec(payload1) | ||
| 3316 | * 3. sg_unmark_end | ||
| 3317 | * 4. skb_to_sgvec(payload2) | ||
| 3318 | * | ||
| 3319 | * When mapping mutilple payload conditionally, skb_to_sgvec_nomark | ||
| 3320 | * is more preferable. | ||
| 3321 | */ | ||
| 3322 | int skb_to_sgvec_nomark(struct sk_buff *skb, struct scatterlist *sg, | ||
| 3323 | int offset, int len) | ||
| 3324 | { | ||
| 3325 | return __skb_to_sgvec(skb, sg, offset, len); | ||
| 3326 | } | ||
| 3327 | EXPORT_SYMBOL_GPL(skb_to_sgvec_nomark); | ||
| 3328 | |||
| 3303 | int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) | 3329 | int skb_to_sgvec(struct sk_buff *skb, struct scatterlist *sg, int offset, int len) |
| 3304 | { | 3330 | { |
| 3305 | int nsg = __skb_to_sgvec(skb, sg, offset, len); | 3331 | int nsg = __skb_to_sgvec(skb, sg, offset, len); |
| @@ -3432,8 +3458,6 @@ static void sock_rmem_free(struct sk_buff *skb) | |||
| 3432 | */ | 3458 | */ |
| 3433 | int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb) | 3459 | int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb) |
| 3434 | { | 3460 | { |
| 3435 | int len = skb->len; | ||
| 3436 | |||
| 3437 | if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= | 3461 | if (atomic_read(&sk->sk_rmem_alloc) + skb->truesize >= |
| 3438 | (unsigned int)sk->sk_rcvbuf) | 3462 | (unsigned int)sk->sk_rcvbuf) |
| 3439 | return -ENOMEM; | 3463 | return -ENOMEM; |
| @@ -3448,7 +3472,7 @@ int sock_queue_err_skb(struct sock *sk, struct sk_buff *skb) | |||
| 3448 | 3472 | ||
| 3449 | skb_queue_tail(&sk->sk_error_queue, skb); | 3473 | skb_queue_tail(&sk->sk_error_queue, skb); |
| 3450 | if (!sock_flag(sk, SOCK_DEAD)) | 3474 | if (!sock_flag(sk, SOCK_DEAD)) |
| 3451 | sk->sk_data_ready(sk, len); | 3475 | sk->sk_data_ready(sk); |
| 3452 | return 0; | 3476 | return 0; |
| 3453 | } | 3477 | } |
| 3454 | EXPORT_SYMBOL(sock_queue_err_skb); | 3478 | EXPORT_SYMBOL(sock_queue_err_skb); |
| @@ -3562,15 +3586,47 @@ static int skb_maybe_pull_tail(struct sk_buff *skb, unsigned int len, | |||
| 3562 | return 0; | 3586 | return 0; |
| 3563 | } | 3587 | } |
| 3564 | 3588 | ||
| 3589 | #define MAX_TCP_HDR_LEN (15 * 4) | ||
| 3590 | |||
| 3591 | static __sum16 *skb_checksum_setup_ip(struct sk_buff *skb, | ||
| 3592 | typeof(IPPROTO_IP) proto, | ||
| 3593 | unsigned int off) | ||
| 3594 | { | ||
| 3595 | switch (proto) { | ||
| 3596 | int err; | ||
| 3597 | |||
| 3598 | case IPPROTO_TCP: | ||
| 3599 | err = skb_maybe_pull_tail(skb, off + sizeof(struct tcphdr), | ||
| 3600 | off + MAX_TCP_HDR_LEN); | ||
| 3601 | if (!err && !skb_partial_csum_set(skb, off, | ||
| 3602 | offsetof(struct tcphdr, | ||
| 3603 | check))) | ||
| 3604 | err = -EPROTO; | ||
| 3605 | return err ? ERR_PTR(err) : &tcp_hdr(skb)->check; | ||
| 3606 | |||
| 3607 | case IPPROTO_UDP: | ||
| 3608 | err = skb_maybe_pull_tail(skb, off + sizeof(struct udphdr), | ||
| 3609 | off + sizeof(struct udphdr)); | ||
| 3610 | if (!err && !skb_partial_csum_set(skb, off, | ||
| 3611 | offsetof(struct udphdr, | ||
| 3612 | check))) | ||
| 3613 | err = -EPROTO; | ||
| 3614 | return err ? ERR_PTR(err) : &udp_hdr(skb)->check; | ||
| 3615 | } | ||
| 3616 | |||
| 3617 | return ERR_PTR(-EPROTO); | ||
| 3618 | } | ||
| 3619 | |||
| 3565 | /* This value should be large enough to cover a tagged ethernet header plus | 3620 | /* This value should be large enough to cover a tagged ethernet header plus |
| 3566 | * maximally sized IP and TCP or UDP headers. | 3621 | * maximally sized IP and TCP or UDP headers. |
| 3567 | */ | 3622 | */ |
| 3568 | #define MAX_IP_HDR_LEN 128 | 3623 | #define MAX_IP_HDR_LEN 128 |
| 3569 | 3624 | ||
| 3570 | static int skb_checksum_setup_ip(struct sk_buff *skb, bool recalculate) | 3625 | static int skb_checksum_setup_ipv4(struct sk_buff *skb, bool recalculate) |
| 3571 | { | 3626 | { |
| 3572 | unsigned int off; | 3627 | unsigned int off; |
| 3573 | bool fragment; | 3628 | bool fragment; |
| 3629 | __sum16 *csum; | ||
| 3574 | int err; | 3630 | int err; |
| 3575 | 3631 | ||
| 3576 | fragment = false; | 3632 | fragment = false; |
| @@ -3591,51 +3647,15 @@ static int skb_checksum_setup_ip(struct sk_buff *skb, bool recalculate) | |||
| 3591 | if (fragment) | 3647 | if (fragment) |
| 3592 | goto out; | 3648 | goto out; |
| 3593 | 3649 | ||
| 3594 | switch (ip_hdr(skb)->protocol) { | 3650 | csum = skb_checksum_setup_ip(skb, ip_hdr(skb)->protocol, off); |
| 3595 | case IPPROTO_TCP: | 3651 | if (IS_ERR(csum)) |
| 3596 | err = skb_maybe_pull_tail(skb, | 3652 | return PTR_ERR(csum); |
| 3597 | off + sizeof(struct tcphdr), | ||
| 3598 | MAX_IP_HDR_LEN); | ||
| 3599 | if (err < 0) | ||
| 3600 | goto out; | ||
| 3601 | |||
| 3602 | if (!skb_partial_csum_set(skb, off, | ||
| 3603 | offsetof(struct tcphdr, check))) { | ||
| 3604 | err = -EPROTO; | ||
| 3605 | goto out; | ||
| 3606 | } | ||
| 3607 | |||
| 3608 | if (recalculate) | ||
| 3609 | tcp_hdr(skb)->check = | ||
| 3610 | ~csum_tcpudp_magic(ip_hdr(skb)->saddr, | ||
| 3611 | ip_hdr(skb)->daddr, | ||
| 3612 | skb->len - off, | ||
| 3613 | IPPROTO_TCP, 0); | ||
| 3614 | break; | ||
| 3615 | case IPPROTO_UDP: | ||
| 3616 | err = skb_maybe_pull_tail(skb, | ||
| 3617 | off + sizeof(struct udphdr), | ||
| 3618 | MAX_IP_HDR_LEN); | ||
| 3619 | if (err < 0) | ||
| 3620 | goto out; | ||
| 3621 | |||
| 3622 | if (!skb_partial_csum_set(skb, off, | ||
| 3623 | offsetof(struct udphdr, check))) { | ||
| 3624 | err = -EPROTO; | ||
| 3625 | goto out; | ||
| 3626 | } | ||
| 3627 | |||
| 3628 | if (recalculate) | ||
| 3629 | udp_hdr(skb)->check = | ||
| 3630 | ~csum_tcpudp_magic(ip_hdr(skb)->saddr, | ||
| 3631 | ip_hdr(skb)->daddr, | ||
| 3632 | skb->len - off, | ||
| 3633 | IPPROTO_UDP, 0); | ||
| 3634 | break; | ||
| 3635 | default: | ||
| 3636 | goto out; | ||
| 3637 | } | ||
| 3638 | 3653 | ||
| 3654 | if (recalculate) | ||
| 3655 | *csum = ~csum_tcpudp_magic(ip_hdr(skb)->saddr, | ||
| 3656 | ip_hdr(skb)->daddr, | ||
| 3657 | skb->len - off, | ||
| 3658 | ip_hdr(skb)->protocol, 0); | ||
| 3639 | err = 0; | 3659 | err = 0; |
| 3640 | 3660 | ||
| 3641 | out: | 3661 | out: |
| @@ -3658,6 +3678,7 @@ static int skb_checksum_setup_ipv6(struct sk_buff *skb, bool recalculate) | |||
| 3658 | unsigned int len; | 3678 | unsigned int len; |
| 3659 | bool fragment; | 3679 | bool fragment; |
| 3660 | bool done; | 3680 | bool done; |
| 3681 | __sum16 *csum; | ||
| 3661 | 3682 | ||
| 3662 | fragment = false; | 3683 | fragment = false; |
| 3663 | done = false; | 3684 | done = false; |
| @@ -3735,51 +3756,14 @@ static int skb_checksum_setup_ipv6(struct sk_buff *skb, bool recalculate) | |||
| 3735 | if (!done || fragment) | 3756 | if (!done || fragment) |
| 3736 | goto out; | 3757 | goto out; |
| 3737 | 3758 | ||
| 3738 | switch (nexthdr) { | 3759 | csum = skb_checksum_setup_ip(skb, nexthdr, off); |
| 3739 | case IPPROTO_TCP: | 3760 | if (IS_ERR(csum)) |
| 3740 | err = skb_maybe_pull_tail(skb, | 3761 | return PTR_ERR(csum); |
| 3741 | off + sizeof(struct tcphdr), | ||
| 3742 | MAX_IPV6_HDR_LEN); | ||
| 3743 | if (err < 0) | ||
| 3744 | goto out; | ||
| 3745 | |||
| 3746 | if (!skb_partial_csum_set(skb, off, | ||
| 3747 | offsetof(struct tcphdr, check))) { | ||
| 3748 | err = -EPROTO; | ||
| 3749 | goto out; | ||
| 3750 | } | ||
| 3751 | |||
| 3752 | if (recalculate) | ||
| 3753 | tcp_hdr(skb)->check = | ||
| 3754 | ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, | ||
| 3755 | &ipv6_hdr(skb)->daddr, | ||
| 3756 | skb->len - off, | ||
| 3757 | IPPROTO_TCP, 0); | ||
| 3758 | break; | ||
| 3759 | case IPPROTO_UDP: | ||
| 3760 | err = skb_maybe_pull_tail(skb, | ||
| 3761 | off + sizeof(struct udphdr), | ||
| 3762 | MAX_IPV6_HDR_LEN); | ||
| 3763 | if (err < 0) | ||
| 3764 | goto out; | ||
| 3765 | |||
| 3766 | if (!skb_partial_csum_set(skb, off, | ||
| 3767 | offsetof(struct udphdr, check))) { | ||
| 3768 | err = -EPROTO; | ||
| 3769 | goto out; | ||
| 3770 | } | ||
| 3771 | |||
| 3772 | if (recalculate) | ||
| 3773 | udp_hdr(skb)->check = | ||
| 3774 | ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, | ||
| 3775 | &ipv6_hdr(skb)->daddr, | ||
| 3776 | skb->len - off, | ||
| 3777 | IPPROTO_UDP, 0); | ||
| 3778 | break; | ||
| 3779 | default: | ||
| 3780 | goto out; | ||
| 3781 | } | ||
| 3782 | 3762 | ||
| 3763 | if (recalculate) | ||
| 3764 | *csum = ~csum_ipv6_magic(&ipv6_hdr(skb)->saddr, | ||
| 3765 | &ipv6_hdr(skb)->daddr, | ||
| 3766 | skb->len - off, nexthdr, 0); | ||
| 3783 | err = 0; | 3767 | err = 0; |
| 3784 | 3768 | ||
| 3785 | out: | 3769 | out: |
| @@ -3797,7 +3781,7 @@ int skb_checksum_setup(struct sk_buff *skb, bool recalculate) | |||
| 3797 | 3781 | ||
| 3798 | switch (skb->protocol) { | 3782 | switch (skb->protocol) { |
| 3799 | case htons(ETH_P_IP): | 3783 | case htons(ETH_P_IP): |
| 3800 | err = skb_checksum_setup_ip(skb, recalculate); | 3784 | err = skb_checksum_setup_ipv4(skb, recalculate); |
| 3801 | break; | 3785 | break; |
| 3802 | 3786 | ||
| 3803 | case htons(ETH_P_IPV6): | 3787 | case htons(ETH_P_IPV6): |
| @@ -3951,12 +3935,14 @@ EXPORT_SYMBOL_GPL(skb_scrub_packet); | |||
| 3951 | unsigned int skb_gso_transport_seglen(const struct sk_buff *skb) | 3935 | unsigned int skb_gso_transport_seglen(const struct sk_buff *skb) |
| 3952 | { | 3936 | { |
| 3953 | const struct skb_shared_info *shinfo = skb_shinfo(skb); | 3937 | const struct skb_shared_info *shinfo = skb_shinfo(skb); |
| 3954 | unsigned int hdr_len; | ||
| 3955 | 3938 | ||
| 3956 | if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))) | 3939 | if (likely(shinfo->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))) |
| 3957 | hdr_len = tcp_hdrlen(skb); | 3940 | return tcp_hdrlen(skb) + shinfo->gso_size; |
| 3958 | else | 3941 | |
| 3959 | hdr_len = sizeof(struct udphdr); | 3942 | /* UFO sets gso_size to the size of the fragmentation |
| 3960 | return hdr_len + shinfo->gso_size; | 3943 | * payload, i.e. the size of the L4 (UDP) header is already |
| 3944 | * accounted for. | ||
| 3945 | */ | ||
| 3946 | return shinfo->gso_size; | ||
| 3961 | } | 3947 | } |
| 3962 | EXPORT_SYMBOL_GPL(skb_gso_transport_seglen); | 3948 | EXPORT_SYMBOL_GPL(skb_gso_transport_seglen); |
diff --git a/net/core/sock.c b/net/core/sock.c index c0fc6bdad1e3..b4fff008136f 100644 --- a/net/core/sock.c +++ b/net/core/sock.c | |||
| @@ -428,7 +428,7 @@ int sock_queue_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
| 428 | spin_unlock_irqrestore(&list->lock, flags); | 428 | spin_unlock_irqrestore(&list->lock, flags); |
| 429 | 429 | ||
| 430 | if (!sock_flag(sk, SOCK_DEAD)) | 430 | if (!sock_flag(sk, SOCK_DEAD)) |
| 431 | sk->sk_data_ready(sk, skb_len); | 431 | sk->sk_data_ready(sk); |
| 432 | return 0; | 432 | return 0; |
| 433 | } | 433 | } |
| 434 | EXPORT_SYMBOL(sock_queue_rcv_skb); | 434 | EXPORT_SYMBOL(sock_queue_rcv_skb); |
| @@ -2196,7 +2196,7 @@ static void sock_def_error_report(struct sock *sk) | |||
| 2196 | rcu_read_unlock(); | 2196 | rcu_read_unlock(); |
| 2197 | } | 2197 | } |
| 2198 | 2198 | ||
| 2199 | static void sock_def_readable(struct sock *sk, int len) | 2199 | static void sock_def_readable(struct sock *sk) |
| 2200 | { | 2200 | { |
| 2201 | struct socket_wq *wq; | 2201 | struct socket_wq *wq; |
| 2202 | 2202 | ||
diff --git a/net/core/sock_diag.c b/net/core/sock_diag.c index a0e9cf6379de..d7af18859322 100644 --- a/net/core/sock_diag.c +++ b/net/core/sock_diag.c | |||
| @@ -52,9 +52,10 @@ EXPORT_SYMBOL_GPL(sock_diag_put_meminfo); | |||
| 52 | int sock_diag_put_filterinfo(struct user_namespace *user_ns, struct sock *sk, | 52 | int sock_diag_put_filterinfo(struct user_namespace *user_ns, struct sock *sk, |
| 53 | struct sk_buff *skb, int attrtype) | 53 | struct sk_buff *skb, int attrtype) |
| 54 | { | 54 | { |
| 55 | struct nlattr *attr; | 55 | struct sock_fprog_kern *fprog; |
| 56 | struct sk_filter *filter; | 56 | struct sk_filter *filter; |
| 57 | unsigned int len; | 57 | struct nlattr *attr; |
| 58 | unsigned int flen; | ||
| 58 | int err = 0; | 59 | int err = 0; |
| 59 | 60 | ||
| 60 | if (!ns_capable(user_ns, CAP_NET_ADMIN)) { | 61 | if (!ns_capable(user_ns, CAP_NET_ADMIN)) { |
| @@ -63,24 +64,20 @@ int sock_diag_put_filterinfo(struct user_namespace *user_ns, struct sock *sk, | |||
| 63 | } | 64 | } |
| 64 | 65 | ||
| 65 | rcu_read_lock(); | 66 | rcu_read_lock(); |
| 66 | |||
| 67 | filter = rcu_dereference(sk->sk_filter); | 67 | filter = rcu_dereference(sk->sk_filter); |
| 68 | len = filter ? filter->len * sizeof(struct sock_filter) : 0; | 68 | if (!filter) |
| 69 | goto out; | ||
| 69 | 70 | ||
| 70 | attr = nla_reserve(skb, attrtype, len); | 71 | fprog = filter->orig_prog; |
| 72 | flen = sk_filter_proglen(fprog); | ||
| 73 | |||
| 74 | attr = nla_reserve(skb, attrtype, flen); | ||
| 71 | if (attr == NULL) { | 75 | if (attr == NULL) { |
| 72 | err = -EMSGSIZE; | 76 | err = -EMSGSIZE; |
| 73 | goto out; | 77 | goto out; |
| 74 | } | 78 | } |
| 75 | 79 | ||
| 76 | if (filter) { | 80 | memcpy(nla_data(attr), fprog->filter, flen); |
| 77 | struct sock_filter *fb = (struct sock_filter *)nla_data(attr); | ||
| 78 | int i; | ||
| 79 | |||
| 80 | for (i = 0; i < filter->len; i++, fb++) | ||
| 81 | sk_decode_filter(&filter->insns[i], fb); | ||
| 82 | } | ||
| 83 | |||
| 84 | out: | 81 | out: |
| 85 | rcu_read_unlock(); | 82 | rcu_read_unlock(); |
| 86 | return err; | 83 | return err; |
diff --git a/net/core/timestamping.c b/net/core/timestamping.c index 661b5a40ec10..6521dfd8b7c8 100644 --- a/net/core/timestamping.c +++ b/net/core/timestamping.c | |||
| @@ -23,16 +23,11 @@ | |||
| 23 | #include <linux/skbuff.h> | 23 | #include <linux/skbuff.h> |
| 24 | #include <linux/export.h> | 24 | #include <linux/export.h> |
| 25 | 25 | ||
| 26 | static struct sock_filter ptp_filter[] = { | ||
| 27 | PTP_FILTER | ||
| 28 | }; | ||
| 29 | |||
| 30 | static unsigned int classify(const struct sk_buff *skb) | 26 | static unsigned int classify(const struct sk_buff *skb) |
| 31 | { | 27 | { |
| 32 | if (likely(skb->dev && | 28 | if (likely(skb->dev && skb->dev->phydev && |
| 33 | skb->dev->phydev && | ||
| 34 | skb->dev->phydev->drv)) | 29 | skb->dev->phydev->drv)) |
| 35 | return sk_run_filter(skb, ptp_filter); | 30 | return ptp_classify_raw(skb); |
| 36 | else | 31 | else |
| 37 | return PTP_CLASS_NONE; | 32 | return PTP_CLASS_NONE; |
| 38 | } | 33 | } |
| @@ -60,11 +55,13 @@ void skb_clone_tx_timestamp(struct sk_buff *skb) | |||
| 60 | if (likely(phydev->drv->txtstamp)) { | 55 | if (likely(phydev->drv->txtstamp)) { |
| 61 | if (!atomic_inc_not_zero(&sk->sk_refcnt)) | 56 | if (!atomic_inc_not_zero(&sk->sk_refcnt)) |
| 62 | return; | 57 | return; |
| 58 | |||
| 63 | clone = skb_clone(skb, GFP_ATOMIC); | 59 | clone = skb_clone(skb, GFP_ATOMIC); |
| 64 | if (!clone) { | 60 | if (!clone) { |
| 65 | sock_put(sk); | 61 | sock_put(sk); |
| 66 | return; | 62 | return; |
| 67 | } | 63 | } |
| 64 | |||
| 68 | clone->sk = sk; | 65 | clone->sk = sk; |
| 69 | phydev->drv->txtstamp(phydev, clone, type); | 66 | phydev->drv->txtstamp(phydev, clone, type); |
| 70 | } | 67 | } |
| @@ -89,12 +86,15 @@ void skb_complete_tx_timestamp(struct sk_buff *skb, | |||
| 89 | } | 86 | } |
| 90 | 87 | ||
| 91 | *skb_hwtstamps(skb) = *hwtstamps; | 88 | *skb_hwtstamps(skb) = *hwtstamps; |
| 89 | |||
| 92 | serr = SKB_EXT_ERR(skb); | 90 | serr = SKB_EXT_ERR(skb); |
| 93 | memset(serr, 0, sizeof(*serr)); | 91 | memset(serr, 0, sizeof(*serr)); |
| 94 | serr->ee.ee_errno = ENOMSG; | 92 | serr->ee.ee_errno = ENOMSG; |
| 95 | serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING; | 93 | serr->ee.ee_origin = SO_EE_ORIGIN_TIMESTAMPING; |
| 96 | skb->sk = NULL; | 94 | skb->sk = NULL; |
| 95 | |||
| 97 | err = sock_queue_err_skb(sk, skb); | 96 | err = sock_queue_err_skb(sk, skb); |
| 97 | |||
| 98 | sock_put(sk); | 98 | sock_put(sk); |
| 99 | if (err) | 99 | if (err) |
| 100 | kfree_skb(skb); | 100 | kfree_skb(skb); |
| @@ -132,8 +132,3 @@ bool skb_defer_rx_timestamp(struct sk_buff *skb) | |||
| 132 | return false; | 132 | return false; |
| 133 | } | 133 | } |
| 134 | EXPORT_SYMBOL_GPL(skb_defer_rx_timestamp); | 134 | EXPORT_SYMBOL_GPL(skb_defer_rx_timestamp); |
| 135 | |||
| 136 | void __init skb_timestamping_init(void) | ||
| 137 | { | ||
| 138 | BUG_ON(sk_chk_filter(ptp_filter, ARRAY_SIZE(ptp_filter))); | ||
| 139 | } | ||
diff --git a/net/dccp/input.c b/net/dccp/input.c index 14cdafad7a90..3c8ec7d4a34e 100644 --- a/net/dccp/input.c +++ b/net/dccp/input.c | |||
| @@ -28,7 +28,7 @@ static void dccp_enqueue_skb(struct sock *sk, struct sk_buff *skb) | |||
| 28 | __skb_pull(skb, dccp_hdr(skb)->dccph_doff * 4); | 28 | __skb_pull(skb, dccp_hdr(skb)->dccph_doff * 4); |
| 29 | __skb_queue_tail(&sk->sk_receive_queue, skb); | 29 | __skb_queue_tail(&sk->sk_receive_queue, skb); |
| 30 | skb_set_owner_r(skb, sk); | 30 | skb_set_owner_r(skb, sk); |
| 31 | sk->sk_data_ready(sk, 0); | 31 | sk->sk_data_ready(sk); |
| 32 | } | 32 | } |
| 33 | 33 | ||
| 34 | static void dccp_fin(struct sock *sk, struct sk_buff *skb) | 34 | static void dccp_fin(struct sock *sk, struct sk_buff *skb) |
diff --git a/net/dccp/minisocks.c b/net/dccp/minisocks.c index 9e2f78bc1553..c69eb9c4fbb8 100644 --- a/net/dccp/minisocks.c +++ b/net/dccp/minisocks.c | |||
| @@ -237,7 +237,7 @@ int dccp_child_process(struct sock *parent, struct sock *child, | |||
| 237 | 237 | ||
| 238 | /* Wakeup parent, send SIGIO */ | 238 | /* Wakeup parent, send SIGIO */ |
| 239 | if (state == DCCP_RESPOND && child->sk_state != state) | 239 | if (state == DCCP_RESPOND && child->sk_state != state) |
| 240 | parent->sk_data_ready(parent, 0); | 240 | parent->sk_data_ready(parent); |
| 241 | } else { | 241 | } else { |
| 242 | /* Alas, it is possible again, because we do lookup | 242 | /* Alas, it is possible again, because we do lookup |
| 243 | * in main socket hash table and lock on listening | 243 | * in main socket hash table and lock on listening |
diff --git a/net/dccp/output.c b/net/dccp/output.c index 8876078859da..0248e8a3460c 100644 --- a/net/dccp/output.c +++ b/net/dccp/output.c | |||
| @@ -138,7 +138,7 @@ static int dccp_transmit_skb(struct sock *sk, struct sk_buff *skb) | |||
| 138 | 138 | ||
| 139 | DCCP_INC_STATS(DCCP_MIB_OUTSEGS); | 139 | DCCP_INC_STATS(DCCP_MIB_OUTSEGS); |
| 140 | 140 | ||
| 141 | err = icsk->icsk_af_ops->queue_xmit(skb, &inet->cork.fl); | 141 | err = icsk->icsk_af_ops->queue_xmit(sk, skb, &inet->cork.fl); |
| 142 | return net_xmit_eval(err); | 142 | return net_xmit_eval(err); |
| 143 | } | 143 | } |
| 144 | return -ENOBUFS; | 144 | return -ENOBUFS; |
diff --git a/net/decnet/dn_nsp_in.c b/net/decnet/dn_nsp_in.c index c344163e6ac0..fe5f01485d33 100644 --- a/net/decnet/dn_nsp_in.c +++ b/net/decnet/dn_nsp_in.c | |||
| @@ -585,7 +585,6 @@ out: | |||
| 585 | static __inline__ int dn_queue_skb(struct sock *sk, struct sk_buff *skb, int sig, struct sk_buff_head *queue) | 585 | static __inline__ int dn_queue_skb(struct sock *sk, struct sk_buff *skb, int sig, struct sk_buff_head *queue) |
| 586 | { | 586 | { |
| 587 | int err; | 587 | int err; |
| 588 | int skb_len; | ||
| 589 | 588 | ||
| 590 | /* Cast skb->rcvbuf to unsigned... It's pointless, but reduces | 589 | /* Cast skb->rcvbuf to unsigned... It's pointless, but reduces |
| 591 | number of warnings when compiling with -W --ANK | 590 | number of warnings when compiling with -W --ANK |
| @@ -600,12 +599,11 @@ static __inline__ int dn_queue_skb(struct sock *sk, struct sk_buff *skb, int sig | |||
| 600 | if (err) | 599 | if (err) |
| 601 | goto out; | 600 | goto out; |
| 602 | 601 | ||
| 603 | skb_len = skb->len; | ||
| 604 | skb_set_owner_r(skb, sk); | 602 | skb_set_owner_r(skb, sk); |
| 605 | skb_queue_tail(queue, skb); | 603 | skb_queue_tail(queue, skb); |
| 606 | 604 | ||
| 607 | if (!sock_flag(sk, SOCK_DEAD)) | 605 | if (!sock_flag(sk, SOCK_DEAD)) |
| 608 | sk->sk_data_ready(sk, skb_len); | 606 | sk->sk_data_ready(sk); |
| 609 | out: | 607 | out: |
| 610 | return err; | 608 | return err; |
| 611 | } | 609 | } |
diff --git a/net/decnet/dn_route.c b/net/decnet/dn_route.c index ce0cbbfe0f43..daccc4a36d80 100644 --- a/net/decnet/dn_route.c +++ b/net/decnet/dn_route.c | |||
| @@ -752,7 +752,7 @@ static int dn_to_neigh_output(struct sk_buff *skb) | |||
| 752 | return n->output(n, skb); | 752 | return n->output(n, skb); |
| 753 | } | 753 | } |
| 754 | 754 | ||
| 755 | static int dn_output(struct sk_buff *skb) | 755 | static int dn_output(struct sock *sk, struct sk_buff *skb) |
| 756 | { | 756 | { |
| 757 | struct dst_entry *dst = skb_dst(skb); | 757 | struct dst_entry *dst = skb_dst(skb); |
| 758 | struct dn_route *rt = (struct dn_route *)dst; | 758 | struct dn_route *rt = (struct dn_route *)dst; |
| @@ -838,6 +838,18 @@ drop: | |||
| 838 | * Used to catch bugs. This should never normally get | 838 | * Used to catch bugs. This should never normally get |
| 839 | * called. | 839 | * called. |
| 840 | */ | 840 | */ |
| 841 | static int dn_rt_bug_sk(struct sock *sk, struct sk_buff *skb) | ||
| 842 | { | ||
| 843 | struct dn_skb_cb *cb = DN_SKB_CB(skb); | ||
| 844 | |||
| 845 | net_dbg_ratelimited("dn_rt_bug: skb from:%04x to:%04x\n", | ||
| 846 | le16_to_cpu(cb->src), le16_to_cpu(cb->dst)); | ||
| 847 | |||
| 848 | kfree_skb(skb); | ||
| 849 | |||
| 850 | return NET_RX_DROP; | ||
| 851 | } | ||
| 852 | |||
| 841 | static int dn_rt_bug(struct sk_buff *skb) | 853 | static int dn_rt_bug(struct sk_buff *skb) |
| 842 | { | 854 | { |
| 843 | struct dn_skb_cb *cb = DN_SKB_CB(skb); | 855 | struct dn_skb_cb *cb = DN_SKB_CB(skb); |
| @@ -1463,7 +1475,7 @@ make_route: | |||
| 1463 | 1475 | ||
| 1464 | rt->n = neigh; | 1476 | rt->n = neigh; |
| 1465 | rt->dst.lastuse = jiffies; | 1477 | rt->dst.lastuse = jiffies; |
| 1466 | rt->dst.output = dn_rt_bug; | 1478 | rt->dst.output = dn_rt_bug_sk; |
| 1467 | switch (res.type) { | 1479 | switch (res.type) { |
| 1468 | case RTN_UNICAST: | 1480 | case RTN_UNICAST: |
| 1469 | rt->dst.input = dn_forward; | 1481 | rt->dst.input = dn_forward; |
diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c index cac505f166d5..e5302b7f7ca9 100644 --- a/net/hsr/hsr_device.c +++ b/net/hsr/hsr_device.c | |||
| @@ -209,7 +209,7 @@ static int slave_xmit(struct sk_buff *skb, struct hsr_priv *hsr_priv, | |||
| 209 | /* Address substitution (IEC62439-3 pp 26, 50): replace mac | 209 | /* Address substitution (IEC62439-3 pp 26, 50): replace mac |
| 210 | * address of outgoing frame with that of the outgoing slave's. | 210 | * address of outgoing frame with that of the outgoing slave's. |
| 211 | */ | 211 | */ |
| 212 | memcpy(hsr_ethhdr->ethhdr.h_source, skb->dev->dev_addr, ETH_ALEN); | 212 | ether_addr_copy(hsr_ethhdr->ethhdr.h_source, skb->dev->dev_addr); |
| 213 | 213 | ||
| 214 | return dev_queue_xmit(skb); | 214 | return dev_queue_xmit(skb); |
| 215 | } | 215 | } |
| @@ -346,7 +346,7 @@ static void send_hsr_supervision_frame(struct net_device *hsr_dev, u8 type) | |||
| 346 | 346 | ||
| 347 | /* Payload: MacAddressA */ | 347 | /* Payload: MacAddressA */ |
| 348 | hsr_sp = (typeof(hsr_sp)) skb_put(skb, sizeof(*hsr_sp)); | 348 | hsr_sp = (typeof(hsr_sp)) skb_put(skb, sizeof(*hsr_sp)); |
| 349 | memcpy(hsr_sp->MacAddressA, hsr_dev->dev_addr, ETH_ALEN); | 349 | ether_addr_copy(hsr_sp->MacAddressA, hsr_dev->dev_addr); |
| 350 | 350 | ||
| 351 | dev_queue_xmit(skb); | 351 | dev_queue_xmit(skb); |
| 352 | return; | 352 | return; |
| @@ -493,7 +493,7 @@ static int check_slave_ok(struct net_device *dev) | |||
| 493 | 493 | ||
| 494 | 494 | ||
| 495 | /* Default multicast address for HSR Supervision frames */ | 495 | /* Default multicast address for HSR Supervision frames */ |
| 496 | static const unsigned char def_multicast_addr[ETH_ALEN] = { | 496 | static const unsigned char def_multicast_addr[ETH_ALEN] __aligned(2) = { |
| 497 | 0x01, 0x15, 0x4e, 0x00, 0x01, 0x00 | 497 | 0x01, 0x15, 0x4e, 0x00, 0x01, 0x00 |
| 498 | }; | 498 | }; |
| 499 | 499 | ||
| @@ -519,7 +519,7 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2], | |||
| 519 | hsr_priv->announce_timer.function = hsr_announce; | 519 | hsr_priv->announce_timer.function = hsr_announce; |
| 520 | hsr_priv->announce_timer.data = (unsigned long) hsr_priv; | 520 | hsr_priv->announce_timer.data = (unsigned long) hsr_priv; |
| 521 | 521 | ||
| 522 | memcpy(hsr_priv->sup_multicast_addr, def_multicast_addr, ETH_ALEN); | 522 | ether_addr_copy(hsr_priv->sup_multicast_addr, def_multicast_addr); |
| 523 | hsr_priv->sup_multicast_addr[ETH_ALEN - 1] = multicast_spec; | 523 | hsr_priv->sup_multicast_addr[ETH_ALEN - 1] = multicast_spec; |
| 524 | 524 | ||
| 525 | /* FIXME: should I modify the value of these? | 525 | /* FIXME: should I modify the value of these? |
| @@ -547,7 +547,7 @@ int hsr_dev_finalize(struct net_device *hsr_dev, struct net_device *slave[2], | |||
| 547 | hsr_dev->features |= NETIF_F_VLAN_CHALLENGED; | 547 | hsr_dev->features |= NETIF_F_VLAN_CHALLENGED; |
| 548 | 548 | ||
| 549 | /* Set hsr_dev's MAC address to that of mac_slave1 */ | 549 | /* Set hsr_dev's MAC address to that of mac_slave1 */ |
| 550 | memcpy(hsr_dev->dev_addr, hsr_priv->slave[0]->dev_addr, ETH_ALEN); | 550 | ether_addr_copy(hsr_dev->dev_addr, hsr_priv->slave[0]->dev_addr); |
| 551 | 551 | ||
| 552 | /* Set required header length */ | 552 | /* Set required header length */ |
| 553 | for (i = 0; i < HSR_MAX_SLAVE; i++) { | 553 | for (i = 0; i < HSR_MAX_SLAVE; i++) { |
diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c index 7ae0d7f6dbd0..83e58449366a 100644 --- a/net/hsr/hsr_framereg.c +++ b/net/hsr/hsr_framereg.c | |||
| @@ -108,8 +108,8 @@ int hsr_create_self_node(struct list_head *self_node_db, | |||
| 108 | if (!node) | 108 | if (!node) |
| 109 | return -ENOMEM; | 109 | return -ENOMEM; |
| 110 | 110 | ||
| 111 | memcpy(node->MacAddressA, addr_a, ETH_ALEN); | 111 | ether_addr_copy(node->MacAddressA, addr_a); |
| 112 | memcpy(node->MacAddressB, addr_b, ETH_ALEN); | 112 | ether_addr_copy(node->MacAddressB, addr_b); |
| 113 | 113 | ||
| 114 | rcu_read_lock(); | 114 | rcu_read_lock(); |
| 115 | oldnode = list_first_or_null_rcu(self_node_db, | 115 | oldnode = list_first_or_null_rcu(self_node_db, |
| @@ -199,7 +199,7 @@ struct node_entry *hsr_merge_node(struct hsr_priv *hsr_priv, | |||
| 199 | /* Node is known, but frame was received from an unknown | 199 | /* Node is known, but frame was received from an unknown |
| 200 | * address. Node is PICS_SUBS capable; merge its AddrB. | 200 | * address. Node is PICS_SUBS capable; merge its AddrB. |
| 201 | */ | 201 | */ |
| 202 | memcpy(node->MacAddressB, hsr_ethsup->ethhdr.h_source, ETH_ALEN); | 202 | ether_addr_copy(node->MacAddressB, hsr_ethsup->ethhdr.h_source); |
| 203 | node->AddrB_if = dev_idx; | 203 | node->AddrB_if = dev_idx; |
| 204 | return node; | 204 | return node; |
| 205 | } | 205 | } |
| @@ -208,8 +208,8 @@ struct node_entry *hsr_merge_node(struct hsr_priv *hsr_priv, | |||
| 208 | if (!node) | 208 | if (!node) |
| 209 | return NULL; | 209 | return NULL; |
| 210 | 210 | ||
| 211 | memcpy(node->MacAddressA, hsr_sp->MacAddressA, ETH_ALEN); | 211 | ether_addr_copy(node->MacAddressA, hsr_sp->MacAddressA); |
| 212 | memcpy(node->MacAddressB, hsr_ethsup->ethhdr.h_source, ETH_ALEN); | 212 | ether_addr_copy(node->MacAddressB, hsr_ethsup->ethhdr.h_source); |
| 213 | if (!ether_addr_equal(hsr_sp->MacAddressA, hsr_ethsup->ethhdr.h_source)) | 213 | if (!ether_addr_equal(hsr_sp->MacAddressA, hsr_ethsup->ethhdr.h_source)) |
| 214 | node->AddrB_if = dev_idx; | 214 | node->AddrB_if = dev_idx; |
| 215 | else | 215 | else |
| @@ -250,7 +250,7 @@ void hsr_addr_subst_source(struct hsr_priv *hsr_priv, struct sk_buff *skb) | |||
| 250 | rcu_read_lock(); | 250 | rcu_read_lock(); |
| 251 | node = find_node_by_AddrB(&hsr_priv->node_db, ethhdr->h_source); | 251 | node = find_node_by_AddrB(&hsr_priv->node_db, ethhdr->h_source); |
| 252 | if (node) | 252 | if (node) |
| 253 | memcpy(ethhdr->h_source, node->MacAddressA, ETH_ALEN); | 253 | ether_addr_copy(ethhdr->h_source, node->MacAddressA); |
| 254 | rcu_read_unlock(); | 254 | rcu_read_unlock(); |
| 255 | } | 255 | } |
| 256 | 256 | ||
| @@ -272,7 +272,7 @@ void hsr_addr_subst_dest(struct hsr_priv *hsr_priv, struct ethhdr *ethhdr, | |||
| 272 | rcu_read_lock(); | 272 | rcu_read_lock(); |
| 273 | node = find_node_by_AddrA(&hsr_priv->node_db, ethhdr->h_dest); | 273 | node = find_node_by_AddrA(&hsr_priv->node_db, ethhdr->h_dest); |
| 274 | if (node && (node->AddrB_if == dev_idx)) | 274 | if (node && (node->AddrB_if == dev_idx)) |
| 275 | memcpy(ethhdr->h_dest, node->MacAddressB, ETH_ALEN); | 275 | ether_addr_copy(ethhdr->h_dest, node->MacAddressB); |
| 276 | rcu_read_unlock(); | 276 | rcu_read_unlock(); |
| 277 | } | 277 | } |
| 278 | 278 | ||
| @@ -428,13 +428,13 @@ void *hsr_get_next_node(struct hsr_priv *hsr_priv, void *_pos, | |||
| 428 | node = list_first_or_null_rcu(&hsr_priv->node_db, | 428 | node = list_first_or_null_rcu(&hsr_priv->node_db, |
| 429 | struct node_entry, mac_list); | 429 | struct node_entry, mac_list); |
| 430 | if (node) | 430 | if (node) |
| 431 | memcpy(addr, node->MacAddressA, ETH_ALEN); | 431 | ether_addr_copy(addr, node->MacAddressA); |
| 432 | return node; | 432 | return node; |
| 433 | } | 433 | } |
| 434 | 434 | ||
| 435 | node = _pos; | 435 | node = _pos; |
| 436 | list_for_each_entry_continue_rcu(node, &hsr_priv->node_db, mac_list) { | 436 | list_for_each_entry_continue_rcu(node, &hsr_priv->node_db, mac_list) { |
| 437 | memcpy(addr, node->MacAddressA, ETH_ALEN); | 437 | ether_addr_copy(addr, node->MacAddressA); |
| 438 | return node; | 438 | return node; |
| 439 | } | 439 | } |
| 440 | 440 | ||
| @@ -462,7 +462,7 @@ int hsr_get_node_data(struct hsr_priv *hsr_priv, | |||
| 462 | return -ENOENT; /* No such entry */ | 462 | return -ENOENT; /* No such entry */ |
| 463 | } | 463 | } |
| 464 | 464 | ||
| 465 | memcpy(addr_b, node->MacAddressB, ETH_ALEN); | 465 | ether_addr_copy(addr_b, node->MacAddressB); |
| 466 | 466 | ||
| 467 | tdiff = jiffies - node->time_in[HSR_DEV_SLAVE_A]; | 467 | tdiff = jiffies - node->time_in[HSR_DEV_SLAVE_A]; |
| 468 | if (node->time_in_stale[HSR_DEV_SLAVE_A]) | 468 | if (node->time_in_stale[HSR_DEV_SLAVE_A]) |
diff --git a/net/hsr/hsr_main.c b/net/hsr/hsr_main.c index af68dd83a4e3..3fee5218a691 100644 --- a/net/hsr/hsr_main.c +++ b/net/hsr/hsr_main.c | |||
| @@ -138,8 +138,8 @@ static int hsr_netdev_notify(struct notifier_block *nb, unsigned long event, | |||
| 138 | break; | 138 | break; |
| 139 | 139 | ||
| 140 | if (dev == hsr_priv->slave[0]) | 140 | if (dev == hsr_priv->slave[0]) |
| 141 | memcpy(hsr_priv->dev->dev_addr, | 141 | ether_addr_copy(hsr_priv->dev->dev_addr, |
| 142 | hsr_priv->slave[0]->dev_addr, ETH_ALEN); | 142 | hsr_priv->slave[0]->dev_addr); |
| 143 | 143 | ||
| 144 | /* Make sure we recognize frames from ourselves in hsr_rcv() */ | 144 | /* Make sure we recognize frames from ourselves in hsr_rcv() */ |
| 145 | res = hsr_create_self_node(&hsr_priv->self_node_db, | 145 | res = hsr_create_self_node(&hsr_priv->self_node_db, |
| @@ -459,7 +459,7 @@ static int __init hsr_init(void) | |||
| 459 | static void __exit hsr_exit(void) | 459 | static void __exit hsr_exit(void) |
| 460 | { | 460 | { |
| 461 | unregister_netdevice_notifier(&hsr_nb); | 461 | unregister_netdevice_notifier(&hsr_nb); |
| 462 | del_timer(&prune_timer); | 462 | del_timer_sync(&prune_timer); |
| 463 | hsr_netlink_exit(); | 463 | hsr_netlink_exit(); |
| 464 | dev_remove_pack(&hsr_pt); | 464 | dev_remove_pack(&hsr_pt); |
| 465 | } | 465 | } |
diff --git a/net/ieee802154/6lowpan.h b/net/ieee802154/6lowpan.h deleted file mode 100644 index 2b835db3bda8..000000000000 --- a/net/ieee802154/6lowpan.h +++ /dev/null | |||
| @@ -1,319 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Copyright 2011, Siemens AG | ||
| 3 | * written by Alexander Smirnov <alex.bluesman.smirnov@gmail.com> | ||
| 4 | */ | ||
| 5 | |||
| 6 | /* | ||
| 7 | * Based on patches from Jon Smirl <jonsmirl@gmail.com> | ||
| 8 | * Copyright (c) 2011 Jon Smirl <jonsmirl@gmail.com> | ||
| 9 | * | ||
| 10 | * This program is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License version 2 | ||
| 12 | * as published by the Free Software Foundation. | ||
| 13 | * | ||
| 14 | * This program is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License along | ||
| 20 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 21 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 22 | */ | ||
| 23 | |||
| 24 | /* Jon's code is based on 6lowpan implementation for Contiki which is: | ||
| 25 | * Copyright (c) 2008, Swedish Institute of Computer Science. | ||
| 26 | * All rights reserved. | ||
| 27 | * | ||
| 28 | * Redistribution and use in source and binary forms, with or without | ||
| 29 | * modification, are permitted provided that the following conditions | ||
| 30 | * are met: | ||
| 31 | * 1. Redistributions of source code must retain the above copyright | ||
| 32 | * notice, this list of conditions and the following disclaimer. | ||
| 33 | * 2. Redistributions in binary form must reproduce the above copyright | ||
| 34 | * notice, this list of conditions and the following disclaimer in the | ||
| 35 | * documentation and/or other materials provided with the distribution. | ||
| 36 | * 3. Neither the name of the Institute nor the names of its contributors | ||
| 37 | * may be used to endorse or promote products derived from this software | ||
| 38 | * without specific prior written permission. | ||
| 39 | * | ||
| 40 | * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND | ||
| 41 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
| 42 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 43 | * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE | ||
| 44 | * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
| 45 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
| 46 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
| 47 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||
| 48 | * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||
| 49 | * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||
| 50 | * SUCH DAMAGE. | ||
| 51 | */ | ||
| 52 | |||
| 53 | #ifndef __6LOWPAN_H__ | ||
| 54 | #define __6LOWPAN_H__ | ||
| 55 | |||
| 56 | #define UIP_802154_SHORTADDR_LEN 2 /* compressed ipv6 address length */ | ||
| 57 | #define UIP_IPH_LEN 40 /* ipv6 fixed header size */ | ||
| 58 | #define UIP_PROTO_UDP 17 /* ipv6 next header value for UDP */ | ||
| 59 | #define UIP_FRAGH_LEN 8 /* ipv6 fragment header size */ | ||
| 60 | |||
| 61 | /* | ||
| 62 | * ipv6 address based on mac | ||
| 63 | * second bit-flip (Universe/Local) is done according RFC2464 | ||
| 64 | */ | ||
| 65 | #define is_addr_mac_addr_based(a, m) \ | ||
| 66 | ((((a)->s6_addr[8]) == (((m)[0]) ^ 0x02)) && \ | ||
| 67 | (((a)->s6_addr[9]) == (m)[1]) && \ | ||
| 68 | (((a)->s6_addr[10]) == (m)[2]) && \ | ||
| 69 | (((a)->s6_addr[11]) == (m)[3]) && \ | ||
| 70 | (((a)->s6_addr[12]) == (m)[4]) && \ | ||
| 71 | (((a)->s6_addr[13]) == (m)[5]) && \ | ||
| 72 | (((a)->s6_addr[14]) == (m)[6]) && \ | ||
| 73 | (((a)->s6_addr[15]) == (m)[7])) | ||
| 74 | |||
| 75 | /* ipv6 address is unspecified */ | ||
| 76 | #define is_addr_unspecified(a) \ | ||
| 77 | ((((a)->s6_addr32[0]) == 0) && \ | ||
| 78 | (((a)->s6_addr32[1]) == 0) && \ | ||
| 79 | (((a)->s6_addr32[2]) == 0) && \ | ||
| 80 | (((a)->s6_addr32[3]) == 0)) | ||
| 81 | |||
| 82 | /* compare ipv6 addresses prefixes */ | ||
| 83 | #define ipaddr_prefixcmp(addr1, addr2, length) \ | ||
| 84 | (memcmp(addr1, addr2, length >> 3) == 0) | ||
| 85 | |||
| 86 | /* local link, i.e. FE80::/10 */ | ||
| 87 | #define is_addr_link_local(a) (((a)->s6_addr16[0]) == htons(0xFE80)) | ||
| 88 | |||
| 89 | /* | ||
| 90 | * check whether we can compress the IID to 16 bits, | ||
| 91 | * it's possible for unicast adresses with first 49 bits are zero only. | ||
| 92 | */ | ||
| 93 | #define lowpan_is_iid_16_bit_compressable(a) \ | ||
| 94 | ((((a)->s6_addr16[4]) == 0) && \ | ||
| 95 | (((a)->s6_addr[10]) == 0) && \ | ||
| 96 | (((a)->s6_addr[11]) == 0xff) && \ | ||
| 97 | (((a)->s6_addr[12]) == 0xfe) && \ | ||
| 98 | (((a)->s6_addr[13]) == 0)) | ||
| 99 | |||
| 100 | /* multicast address */ | ||
| 101 | #define is_addr_mcast(a) (((a)->s6_addr[0]) == 0xFF) | ||
| 102 | |||
| 103 | /* check whether the 112-bit gid of the multicast address is mappable to: */ | ||
| 104 | |||
| 105 | /* 9 bits, for FF02::1 (all nodes) and FF02::2 (all routers) addresses only. */ | ||
| 106 | #define lowpan_is_mcast_addr_compressable(a) \ | ||
| 107 | ((((a)->s6_addr16[1]) == 0) && \ | ||
| 108 | (((a)->s6_addr16[2]) == 0) && \ | ||
| 109 | (((a)->s6_addr16[3]) == 0) && \ | ||
| 110 | (((a)->s6_addr16[4]) == 0) && \ | ||
| 111 | (((a)->s6_addr16[5]) == 0) && \ | ||
| 112 | (((a)->s6_addr16[6]) == 0) && \ | ||
| 113 | (((a)->s6_addr[14]) == 0) && \ | ||
| 114 | ((((a)->s6_addr[15]) == 1) || (((a)->s6_addr[15]) == 2))) | ||
| 115 | |||
| 116 | /* 48 bits, FFXX::00XX:XXXX:XXXX */ | ||
| 117 | #define lowpan_is_mcast_addr_compressable48(a) \ | ||
| 118 | ((((a)->s6_addr16[1]) == 0) && \ | ||
| 119 | (((a)->s6_addr16[2]) == 0) && \ | ||
| 120 | (((a)->s6_addr16[3]) == 0) && \ | ||
| 121 | (((a)->s6_addr16[4]) == 0) && \ | ||
| 122 | (((a)->s6_addr[10]) == 0)) | ||
| 123 | |||
| 124 | /* 32 bits, FFXX::00XX:XXXX */ | ||
| 125 | #define lowpan_is_mcast_addr_compressable32(a) \ | ||
| 126 | ((((a)->s6_addr16[1]) == 0) && \ | ||
| 127 | (((a)->s6_addr16[2]) == 0) && \ | ||
| 128 | (((a)->s6_addr16[3]) == 0) && \ | ||
| 129 | (((a)->s6_addr16[4]) == 0) && \ | ||
| 130 | (((a)->s6_addr16[5]) == 0) && \ | ||
| 131 | (((a)->s6_addr[12]) == 0)) | ||
| 132 | |||
| 133 | /* 8 bits, FF02::00XX */ | ||
| 134 | #define lowpan_is_mcast_addr_compressable8(a) \ | ||
| 135 | ((((a)->s6_addr[1]) == 2) && \ | ||
| 136 | (((a)->s6_addr16[1]) == 0) && \ | ||
| 137 | (((a)->s6_addr16[2]) == 0) && \ | ||
| 138 | (((a)->s6_addr16[3]) == 0) && \ | ||
| 139 | (((a)->s6_addr16[4]) == 0) && \ | ||
| 140 | (((a)->s6_addr16[5]) == 0) && \ | ||
| 141 | (((a)->s6_addr16[6]) == 0) && \ | ||
| 142 | (((a)->s6_addr[14]) == 0)) | ||
| 143 | |||
| 144 | #define lowpan_is_addr_broadcast(a) \ | ||
| 145 | ((((a)[0]) == 0xFF) && \ | ||
| 146 | (((a)[1]) == 0xFF) && \ | ||
| 147 | (((a)[2]) == 0xFF) && \ | ||
| 148 | (((a)[3]) == 0xFF) && \ | ||
| 149 | (((a)[4]) == 0xFF) && \ | ||
| 150 | (((a)[5]) == 0xFF) && \ | ||
| 151 | (((a)[6]) == 0xFF) && \ | ||
| 152 | (((a)[7]) == 0xFF)) | ||
| 153 | |||
| 154 | #define LOWPAN_DISPATCH_IPV6 0x41 /* 01000001 = 65 */ | ||
| 155 | #define LOWPAN_DISPATCH_HC1 0x42 /* 01000010 = 66 */ | ||
| 156 | #define LOWPAN_DISPATCH_IPHC 0x60 /* 011xxxxx = ... */ | ||
| 157 | #define LOWPAN_DISPATCH_FRAG1 0xc0 /* 11000xxx */ | ||
| 158 | #define LOWPAN_DISPATCH_FRAGN 0xe0 /* 11100xxx */ | ||
| 159 | |||
| 160 | #define LOWPAN_DISPATCH_MASK 0xf8 /* 11111000 */ | ||
| 161 | |||
| 162 | #define LOWPAN_FRAG_TIMEOUT (HZ * 60) /* time-out 60 sec */ | ||
| 163 | |||
| 164 | #define LOWPAN_FRAG1_HEAD_SIZE 0x4 | ||
| 165 | #define LOWPAN_FRAGN_HEAD_SIZE 0x5 | ||
| 166 | |||
| 167 | /* | ||
| 168 | * According IEEE802.15.4 standard: | ||
| 169 | * - MTU is 127 octets | ||
| 170 | * - maximum MHR size is 37 octets | ||
| 171 | * - MFR size is 2 octets | ||
| 172 | * | ||
| 173 | * so minimal payload size that we may guarantee is: | ||
| 174 | * MTU - MHR - MFR = 88 octets | ||
| 175 | */ | ||
| 176 | #define LOWPAN_FRAG_SIZE 88 | ||
| 177 | |||
| 178 | /* | ||
| 179 | * Values of fields within the IPHC encoding first byte | ||
| 180 | * (C stands for compressed and I for inline) | ||
| 181 | */ | ||
| 182 | #define LOWPAN_IPHC_TF 0x18 | ||
| 183 | |||
| 184 | #define LOWPAN_IPHC_FL_C 0x10 | ||
| 185 | #define LOWPAN_IPHC_TC_C 0x08 | ||
| 186 | #define LOWPAN_IPHC_NH_C 0x04 | ||
| 187 | #define LOWPAN_IPHC_TTL_1 0x01 | ||
| 188 | #define LOWPAN_IPHC_TTL_64 0x02 | ||
| 189 | #define LOWPAN_IPHC_TTL_255 0x03 | ||
| 190 | #define LOWPAN_IPHC_TTL_I 0x00 | ||
| 191 | |||
| 192 | |||
| 193 | /* Values of fields within the IPHC encoding second byte */ | ||
| 194 | #define LOWPAN_IPHC_CID 0x80 | ||
| 195 | |||
| 196 | #define LOWPAN_IPHC_ADDR_00 0x00 | ||
| 197 | #define LOWPAN_IPHC_ADDR_01 0x01 | ||
| 198 | #define LOWPAN_IPHC_ADDR_02 0x02 | ||
| 199 | #define LOWPAN_IPHC_ADDR_03 0x03 | ||
| 200 | |||
| 201 | #define LOWPAN_IPHC_SAC 0x40 | ||
| 202 | #define LOWPAN_IPHC_SAM 0x30 | ||
| 203 | |||
| 204 | #define LOWPAN_IPHC_SAM_BIT 4 | ||
| 205 | |||
| 206 | #define LOWPAN_IPHC_M 0x08 | ||
| 207 | #define LOWPAN_IPHC_DAC 0x04 | ||
| 208 | #define LOWPAN_IPHC_DAM_00 0x00 | ||
| 209 | #define LOWPAN_IPHC_DAM_01 0x01 | ||
| 210 | #define LOWPAN_IPHC_DAM_10 0x02 | ||
| 211 | #define LOWPAN_IPHC_DAM_11 0x03 | ||
| 212 | |||
| 213 | #define LOWPAN_IPHC_DAM_BIT 0 | ||
| 214 | /* | ||
| 215 | * LOWPAN_UDP encoding (works together with IPHC) | ||
| 216 | */ | ||
| 217 | #define LOWPAN_NHC_UDP_MASK 0xF8 | ||
| 218 | #define LOWPAN_NHC_UDP_ID 0xF0 | ||
| 219 | #define LOWPAN_NHC_UDP_CHECKSUMC 0x04 | ||
| 220 | #define LOWPAN_NHC_UDP_CHECKSUMI 0x00 | ||
| 221 | |||
| 222 | #define LOWPAN_NHC_UDP_4BIT_PORT 0xF0B0 | ||
| 223 | #define LOWPAN_NHC_UDP_4BIT_MASK 0xFFF0 | ||
| 224 | #define LOWPAN_NHC_UDP_8BIT_PORT 0xF000 | ||
| 225 | #define LOWPAN_NHC_UDP_8BIT_MASK 0xFF00 | ||
| 226 | |||
| 227 | /* values for port compression, _with checksum_ ie bit 5 set to 0 */ | ||
| 228 | #define LOWPAN_NHC_UDP_CS_P_00 0xF0 /* all inline */ | ||
| 229 | #define LOWPAN_NHC_UDP_CS_P_01 0xF1 /* source 16bit inline, | ||
| 230 | dest = 0xF0 + 8 bit inline */ | ||
| 231 | #define LOWPAN_NHC_UDP_CS_P_10 0xF2 /* source = 0xF0 + 8bit inline, | ||
| 232 | dest = 16 bit inline */ | ||
| 233 | #define LOWPAN_NHC_UDP_CS_P_11 0xF3 /* source & dest = 0xF0B + 4bit inline */ | ||
| 234 | #define LOWPAN_NHC_UDP_CS_C 0x04 /* checksum elided */ | ||
| 235 | |||
| 236 | #ifdef DEBUG | ||
| 237 | /* print data in line */ | ||
| 238 | static inline void raw_dump_inline(const char *caller, char *msg, | ||
| 239 | unsigned char *buf, int len) | ||
| 240 | { | ||
| 241 | if (msg) | ||
| 242 | pr_debug("%s():%s: ", caller, msg); | ||
| 243 | |||
| 244 | print_hex_dump_debug("", DUMP_PREFIX_NONE, 16, 1, buf, len, false); | ||
| 245 | } | ||
| 246 | |||
| 247 | /* print data in a table format: | ||
| 248 | * | ||
| 249 | * addr: xx xx xx xx xx xx | ||
| 250 | * addr: xx xx xx xx xx xx | ||
| 251 | * ... | ||
| 252 | */ | ||
| 253 | static inline void raw_dump_table(const char *caller, char *msg, | ||
| 254 | unsigned char *buf, int len) | ||
| 255 | { | ||
| 256 | if (msg) | ||
| 257 | pr_debug("%s():%s:\n", caller, msg); | ||
| 258 | |||
| 259 | print_hex_dump_debug("\t", DUMP_PREFIX_OFFSET, 16, 1, buf, len, false); | ||
| 260 | } | ||
| 261 | #else | ||
| 262 | static inline void raw_dump_table(const char *caller, char *msg, | ||
| 263 | unsigned char *buf, int len) { } | ||
| 264 | static inline void raw_dump_inline(const char *caller, char *msg, | ||
| 265 | unsigned char *buf, int len) { } | ||
| 266 | #endif | ||
| 267 | |||
| 268 | static inline int lowpan_fetch_skb_u8(struct sk_buff *skb, u8 *val) | ||
| 269 | { | ||
| 270 | if (unlikely(!pskb_may_pull(skb, 1))) | ||
| 271 | return -EINVAL; | ||
| 272 | |||
| 273 | *val = skb->data[0]; | ||
| 274 | skb_pull(skb, 1); | ||
| 275 | |||
| 276 | return 0; | ||
| 277 | } | ||
| 278 | |||
| 279 | static inline int lowpan_fetch_skb_u16(struct sk_buff *skb, u16 *val) | ||
| 280 | { | ||
| 281 | if (unlikely(!pskb_may_pull(skb, 2))) | ||
| 282 | return -EINVAL; | ||
| 283 | |||
| 284 | *val = (skb->data[0] << 8) | skb->data[1]; | ||
| 285 | skb_pull(skb, 2); | ||
| 286 | |||
| 287 | return 0; | ||
| 288 | } | ||
| 289 | |||
| 290 | static inline bool lowpan_fetch_skb(struct sk_buff *skb, | ||
| 291 | void *data, const unsigned int len) | ||
| 292 | { | ||
| 293 | if (unlikely(!pskb_may_pull(skb, len))) | ||
| 294 | return true; | ||
| 295 | |||
| 296 | skb_copy_from_linear_data(skb, data, len); | ||
| 297 | skb_pull(skb, len); | ||
| 298 | |||
| 299 | return false; | ||
| 300 | } | ||
| 301 | |||
| 302 | static inline void lowpan_push_hc_data(u8 **hc_ptr, const void *data, | ||
| 303 | const size_t len) | ||
| 304 | { | ||
| 305 | memcpy(*hc_ptr, data, len); | ||
| 306 | *hc_ptr += len; | ||
| 307 | } | ||
| 308 | |||
| 309 | typedef int (*skb_delivery_cb)(struct sk_buff *skb, struct net_device *dev); | ||
| 310 | |||
| 311 | int lowpan_process_data(struct sk_buff *skb, struct net_device *dev, | ||
| 312 | const u8 *saddr, const u8 saddr_type, const u8 saddr_len, | ||
| 313 | const u8 *daddr, const u8 daddr_type, const u8 daddr_len, | ||
| 314 | u8 iphc0, u8 iphc1, skb_delivery_cb skb_deliver); | ||
| 315 | int lowpan_header_compress(struct sk_buff *skb, struct net_device *dev, | ||
| 316 | unsigned short type, const void *_daddr, | ||
| 317 | const void *_saddr, unsigned int len); | ||
| 318 | |||
| 319 | #endif /* __6LOWPAN_H__ */ | ||
diff --git a/net/ieee802154/6lowpan_iphc.c b/net/ieee802154/6lowpan_iphc.c index 860aa2d445ba..211b5686d719 100644 --- a/net/ieee802154/6lowpan_iphc.c +++ b/net/ieee802154/6lowpan_iphc.c | |||
| @@ -54,11 +54,10 @@ | |||
| 54 | #include <linux/if_arp.h> | 54 | #include <linux/if_arp.h> |
| 55 | #include <linux/module.h> | 55 | #include <linux/module.h> |
| 56 | #include <linux/netdevice.h> | 56 | #include <linux/netdevice.h> |
| 57 | #include <net/6lowpan.h> | ||
| 57 | #include <net/ipv6.h> | 58 | #include <net/ipv6.h> |
| 58 | #include <net/af_ieee802154.h> | 59 | #include <net/af_ieee802154.h> |
| 59 | 60 | ||
| 60 | #include "6lowpan.h" | ||
| 61 | |||
| 62 | /* | 61 | /* |
| 63 | * Uncompress address function for source and | 62 | * Uncompress address function for source and |
| 64 | * destination address(non-multicast). | 63 | * destination address(non-multicast). |
diff --git a/net/ieee802154/6lowpan.c b/net/ieee802154/6lowpan_rtnl.c index 8edfea5da572..0f5a69ed746d 100644 --- a/net/ieee802154/6lowpan.c +++ b/net/ieee802154/6lowpan_rtnl.c | |||
| @@ -1,10 +1,8 @@ | |||
| 1 | /* | 1 | /* Copyright 2011, Siemens AG |
| 2 | * Copyright 2011, Siemens AG | ||
| 3 | * written by Alexander Smirnov <alex.bluesman.smirnov@gmail.com> | 2 | * written by Alexander Smirnov <alex.bluesman.smirnov@gmail.com> |
| 4 | */ | 3 | */ |
| 5 | 4 | ||
| 6 | /* | 5 | /* Based on patches from Jon Smirl <jonsmirl@gmail.com> |
| 7 | * Based on patches from Jon Smirl <jonsmirl@gmail.com> | ||
| 8 | * Copyright (c) 2011 Jon Smirl <jonsmirl@gmail.com> | 6 | * Copyright (c) 2011 Jon Smirl <jonsmirl@gmail.com> |
| 9 | * | 7 | * |
| 10 | * This program is free software; you can redistribute it and/or modify | 8 | * This program is free software; you can redistribute it and/or modify |
| @@ -15,10 +13,6 @@ | |||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 14 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 17 | * GNU General Public License for more details. | 15 | * GNU General Public License for more details. |
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License along | ||
| 20 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
| 21 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
| 22 | */ | 16 | */ |
| 23 | 17 | ||
| 24 | /* Jon's code is based on 6lowpan implementation for Contiki which is: | 18 | /* Jon's code is based on 6lowpan implementation for Contiki which is: |
| @@ -58,9 +52,10 @@ | |||
| 58 | #include <net/af_ieee802154.h> | 52 | #include <net/af_ieee802154.h> |
| 59 | #include <net/ieee802154.h> | 53 | #include <net/ieee802154.h> |
| 60 | #include <net/ieee802154_netdev.h> | 54 | #include <net/ieee802154_netdev.h> |
| 55 | #include <net/6lowpan.h> | ||
| 61 | #include <net/ipv6.h> | 56 | #include <net/ipv6.h> |
| 62 | 57 | ||
| 63 | #include "6lowpan.h" | 58 | #include "reassembly.h" |
| 64 | 59 | ||
| 65 | static LIST_HEAD(lowpan_devices); | 60 | static LIST_HEAD(lowpan_devices); |
| 66 | 61 | ||
| @@ -68,7 +63,7 @@ static LIST_HEAD(lowpan_devices); | |||
| 68 | struct lowpan_dev_info { | 63 | struct lowpan_dev_info { |
| 69 | struct net_device *real_dev; /* real WPAN device ptr */ | 64 | struct net_device *real_dev; /* real WPAN device ptr */ |
| 70 | struct mutex dev_list_mtx; /* mutex for list ops */ | 65 | struct mutex dev_list_mtx; /* mutex for list ops */ |
| 71 | unsigned short fragment_tag; | 66 | __be16 fragment_tag; |
| 72 | }; | 67 | }; |
| 73 | 68 | ||
| 74 | struct lowpan_dev_record { | 69 | struct lowpan_dev_record { |
| @@ -76,18 +71,6 @@ struct lowpan_dev_record { | |||
| 76 | struct list_head list; | 71 | struct list_head list; |
| 77 | }; | 72 | }; |
| 78 | 73 | ||
| 79 | struct lowpan_fragment { | ||
| 80 | struct sk_buff *skb; /* skb to be assembled */ | ||
| 81 | u16 length; /* length to be assemled */ | ||
| 82 | u32 bytes_rcv; /* bytes received */ | ||
| 83 | u16 tag; /* current fragment tag */ | ||
| 84 | struct timer_list timer; /* assembling timer */ | ||
| 85 | struct list_head list; /* fragments list */ | ||
| 86 | }; | ||
| 87 | |||
| 88 | static LIST_HEAD(lowpan_fragments); | ||
| 89 | static DEFINE_SPINLOCK(flist_lock); | ||
| 90 | |||
| 91 | static inline struct | 74 | static inline struct |
| 92 | lowpan_dev_info *lowpan_dev_info(const struct net_device *dev) | 75 | lowpan_dev_info *lowpan_dev_info(const struct net_device *dev) |
| 93 | { | 76 | { |
| @@ -124,13 +107,11 @@ static int lowpan_header_create(struct sk_buff *skb, | |||
| 124 | 107 | ||
| 125 | lowpan_header_compress(skb, dev, type, daddr, saddr, len); | 108 | lowpan_header_compress(skb, dev, type, daddr, saddr, len); |
| 126 | 109 | ||
| 127 | /* | 110 | /* NOTE1: I'm still unsure about the fact that compression and WPAN |
| 128 | * NOTE1: I'm still unsure about the fact that compression and WPAN | ||
| 129 | * header are created here and not later in the xmit. So wait for | 111 | * header are created here and not later in the xmit. So wait for |
| 130 | * an opinion of net maintainers. | 112 | * an opinion of net maintainers. |
| 131 | */ | 113 | */ |
| 132 | /* | 114 | /* NOTE2: to be absolutely correct, we must derive PANid information |
| 133 | * NOTE2: to be absolutely correct, we must derive PANid information | ||
| 134 | * from MAC subif of the 'dev' and 'real_dev' network devices, but | 115 | * from MAC subif of the 'dev' and 'real_dev' network devices, but |
| 135 | * this isn't implemented in mainline yet, so currently we assign 0xff | 116 | * this isn't implemented in mainline yet, so currently we assign 0xff |
| 136 | */ | 117 | */ |
| @@ -138,30 +119,29 @@ static int lowpan_header_create(struct sk_buff *skb, | |||
| 138 | mac_cb(skb)->seq = ieee802154_mlme_ops(dev)->get_dsn(dev); | 119 | mac_cb(skb)->seq = ieee802154_mlme_ops(dev)->get_dsn(dev); |
| 139 | 120 | ||
| 140 | /* prepare wpan address data */ | 121 | /* prepare wpan address data */ |
| 141 | sa.addr_type = IEEE802154_ADDR_LONG; | 122 | sa.mode = IEEE802154_ADDR_LONG; |
| 142 | sa.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); | 123 | sa.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); |
| 124 | sa.extended_addr = ieee802154_devaddr_from_raw(saddr); | ||
| 143 | 125 | ||
| 144 | memcpy(&(sa.hwaddr), saddr, 8); | ||
| 145 | /* intra-PAN communications */ | 126 | /* intra-PAN communications */ |
| 146 | da.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); | 127 | da.pan_id = sa.pan_id; |
| 147 | 128 | ||
| 148 | /* | 129 | /* if the destination address is the broadcast address, use the |
| 149 | * if the destination address is the broadcast address, use the | ||
| 150 | * corresponding short address | 130 | * corresponding short address |
| 151 | */ | 131 | */ |
| 152 | if (lowpan_is_addr_broadcast(daddr)) { | 132 | if (lowpan_is_addr_broadcast(daddr)) { |
| 153 | da.addr_type = IEEE802154_ADDR_SHORT; | 133 | da.mode = IEEE802154_ADDR_SHORT; |
| 154 | da.short_addr = IEEE802154_ADDR_BROADCAST; | 134 | da.short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST); |
| 155 | } else { | 135 | } else { |
| 156 | da.addr_type = IEEE802154_ADDR_LONG; | 136 | da.mode = IEEE802154_ADDR_LONG; |
| 157 | memcpy(&(da.hwaddr), daddr, IEEE802154_ADDR_LEN); | 137 | da.extended_addr = ieee802154_devaddr_from_raw(daddr); |
| 158 | 138 | ||
| 159 | /* request acknowledgment */ | 139 | /* request acknowledgment */ |
| 160 | mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ; | 140 | mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ; |
| 161 | } | 141 | } |
| 162 | 142 | ||
| 163 | return dev_hard_header(skb, lowpan_dev_info(dev)->real_dev, | 143 | return dev_hard_header(skb, lowpan_dev_info(dev)->real_dev, |
| 164 | type, (void *)&da, (void *)&sa, skb->len); | 144 | type, (void *)&da, (void *)&sa, 0); |
| 165 | } | 145 | } |
| 166 | 146 | ||
| 167 | static int lowpan_give_skb_to_devices(struct sk_buff *skb, | 147 | static int lowpan_give_skb_to_devices(struct sk_buff *skb, |
| @@ -188,73 +168,11 @@ static int lowpan_give_skb_to_devices(struct sk_buff *skb, | |||
| 188 | return stat; | 168 | return stat; |
| 189 | } | 169 | } |
| 190 | 170 | ||
| 191 | static void lowpan_fragment_timer_expired(unsigned long entry_addr) | 171 | static int process_data(struct sk_buff *skb, const struct ieee802154_hdr *hdr) |
| 192 | { | ||
| 193 | struct lowpan_fragment *entry = (struct lowpan_fragment *)entry_addr; | ||
| 194 | |||
| 195 | pr_debug("timer expired for frame with tag %d\n", entry->tag); | ||
| 196 | |||
| 197 | list_del(&entry->list); | ||
| 198 | dev_kfree_skb(entry->skb); | ||
| 199 | kfree(entry); | ||
| 200 | } | ||
| 201 | |||
| 202 | static struct lowpan_fragment * | ||
| 203 | lowpan_alloc_new_frame(struct sk_buff *skb, u16 len, u16 tag) | ||
| 204 | { | ||
| 205 | struct lowpan_fragment *frame; | ||
| 206 | |||
| 207 | frame = kzalloc(sizeof(struct lowpan_fragment), | ||
| 208 | GFP_ATOMIC); | ||
| 209 | if (!frame) | ||
| 210 | goto frame_err; | ||
| 211 | |||
| 212 | INIT_LIST_HEAD(&frame->list); | ||
| 213 | |||
| 214 | frame->length = len; | ||
| 215 | frame->tag = tag; | ||
| 216 | |||
| 217 | /* allocate buffer for frame assembling */ | ||
| 218 | frame->skb = netdev_alloc_skb_ip_align(skb->dev, frame->length + | ||
| 219 | sizeof(struct ipv6hdr)); | ||
| 220 | |||
| 221 | if (!frame->skb) | ||
| 222 | goto skb_err; | ||
| 223 | |||
| 224 | frame->skb->priority = skb->priority; | ||
| 225 | |||
| 226 | /* reserve headroom for uncompressed ipv6 header */ | ||
| 227 | skb_reserve(frame->skb, sizeof(struct ipv6hdr)); | ||
| 228 | skb_put(frame->skb, frame->length); | ||
| 229 | |||
| 230 | /* copy the first control block to keep a | ||
| 231 | * trace of the link-layer addresses in case | ||
| 232 | * of a link-local compressed address | ||
| 233 | */ | ||
| 234 | memcpy(frame->skb->cb, skb->cb, sizeof(skb->cb)); | ||
| 235 | |||
| 236 | init_timer(&frame->timer); | ||
| 237 | /* time out is the same as for ipv6 - 60 sec */ | ||
| 238 | frame->timer.expires = jiffies + LOWPAN_FRAG_TIMEOUT; | ||
| 239 | frame->timer.data = (unsigned long)frame; | ||
| 240 | frame->timer.function = lowpan_fragment_timer_expired; | ||
| 241 | |||
| 242 | add_timer(&frame->timer); | ||
| 243 | |||
| 244 | list_add_tail(&frame->list, &lowpan_fragments); | ||
| 245 | |||
| 246 | return frame; | ||
| 247 | |||
| 248 | skb_err: | ||
| 249 | kfree(frame); | ||
| 250 | frame_err: | ||
| 251 | return NULL; | ||
| 252 | } | ||
| 253 | |||
| 254 | static int process_data(struct sk_buff *skb) | ||
| 255 | { | 172 | { |
| 256 | u8 iphc0, iphc1; | 173 | u8 iphc0, iphc1; |
| 257 | const struct ieee802154_addr *_saddr, *_daddr; | 174 | struct ieee802154_addr_sa sa, da; |
| 175 | void *sap, *dap; | ||
| 258 | 176 | ||
| 259 | raw_dump_table(__func__, "raw skb data dump", skb->data, skb->len); | 177 | raw_dump_table(__func__, "raw skb data dump", skb->data, skb->len); |
| 260 | /* at least two bytes will be used for the encoding */ | 178 | /* at least two bytes will be used for the encoding */ |
| @@ -264,108 +182,27 @@ static int process_data(struct sk_buff *skb) | |||
| 264 | if (lowpan_fetch_skb_u8(skb, &iphc0)) | 182 | if (lowpan_fetch_skb_u8(skb, &iphc0)) |
| 265 | goto drop; | 183 | goto drop; |
| 266 | 184 | ||
| 267 | /* fragments assembling */ | ||
| 268 | switch (iphc0 & LOWPAN_DISPATCH_MASK) { | ||
| 269 | case LOWPAN_DISPATCH_FRAG1: | ||
| 270 | case LOWPAN_DISPATCH_FRAGN: | ||
| 271 | { | ||
| 272 | struct lowpan_fragment *frame; | ||
| 273 | /* slen stores the rightmost 8 bits of the 11 bits length */ | ||
| 274 | u8 slen, offset = 0; | ||
| 275 | u16 len, tag; | ||
| 276 | bool found = false; | ||
| 277 | |||
| 278 | if (lowpan_fetch_skb_u8(skb, &slen) || /* frame length */ | ||
| 279 | lowpan_fetch_skb_u16(skb, &tag)) /* fragment tag */ | ||
| 280 | goto drop; | ||
| 281 | |||
| 282 | /* adds the 3 MSB to the 8 LSB to retrieve the 11 bits length */ | ||
| 283 | len = ((iphc0 & 7) << 8) | slen; | ||
| 284 | |||
| 285 | if ((iphc0 & LOWPAN_DISPATCH_MASK) == LOWPAN_DISPATCH_FRAG1) { | ||
| 286 | pr_debug("%s received a FRAG1 packet (tag: %d, " | ||
| 287 | "size of the entire IP packet: %d)", | ||
| 288 | __func__, tag, len); | ||
| 289 | } else { /* FRAGN */ | ||
| 290 | if (lowpan_fetch_skb_u8(skb, &offset)) | ||
| 291 | goto unlock_and_drop; | ||
| 292 | pr_debug("%s received a FRAGN packet (tag: %d, " | ||
| 293 | "size of the entire IP packet: %d, " | ||
| 294 | "offset: %d)", __func__, tag, len, offset * 8); | ||
| 295 | } | ||
| 296 | |||
| 297 | /* | ||
| 298 | * check if frame assembling with the same tag is | ||
| 299 | * already in progress | ||
| 300 | */ | ||
| 301 | spin_lock_bh(&flist_lock); | ||
| 302 | |||
| 303 | list_for_each_entry(frame, &lowpan_fragments, list) | ||
| 304 | if (frame->tag == tag) { | ||
| 305 | found = true; | ||
| 306 | break; | ||
| 307 | } | ||
| 308 | |||
| 309 | /* alloc new frame structure */ | ||
| 310 | if (!found) { | ||
| 311 | pr_debug("%s first fragment received for tag %d, " | ||
| 312 | "begin packet reassembly", __func__, tag); | ||
| 313 | frame = lowpan_alloc_new_frame(skb, len, tag); | ||
| 314 | if (!frame) | ||
| 315 | goto unlock_and_drop; | ||
| 316 | } | ||
| 317 | |||
| 318 | /* if payload fits buffer, copy it */ | ||
| 319 | if (likely((offset * 8 + skb->len) <= frame->length)) | ||
| 320 | skb_copy_to_linear_data_offset(frame->skb, offset * 8, | ||
| 321 | skb->data, skb->len); | ||
| 322 | else | ||
| 323 | goto unlock_and_drop; | ||
| 324 | |||
| 325 | frame->bytes_rcv += skb->len; | ||
| 326 | |||
| 327 | /* frame assembling complete */ | ||
| 328 | if ((frame->bytes_rcv == frame->length) && | ||
| 329 | frame->timer.expires > jiffies) { | ||
| 330 | /* if timer haven't expired - first of all delete it */ | ||
| 331 | del_timer_sync(&frame->timer); | ||
| 332 | list_del(&frame->list); | ||
| 333 | spin_unlock_bh(&flist_lock); | ||
| 334 | |||
| 335 | pr_debug("%s successfully reassembled fragment " | ||
| 336 | "(tag %d)", __func__, tag); | ||
| 337 | |||
| 338 | dev_kfree_skb(skb); | ||
| 339 | skb = frame->skb; | ||
| 340 | kfree(frame); | ||
| 341 | |||
| 342 | if (lowpan_fetch_skb_u8(skb, &iphc0)) | ||
| 343 | goto drop; | ||
| 344 | |||
| 345 | break; | ||
| 346 | } | ||
| 347 | spin_unlock_bh(&flist_lock); | ||
| 348 | |||
| 349 | return kfree_skb(skb), 0; | ||
| 350 | } | ||
| 351 | default: | ||
| 352 | break; | ||
| 353 | } | ||
| 354 | |||
| 355 | if (lowpan_fetch_skb_u8(skb, &iphc1)) | 185 | if (lowpan_fetch_skb_u8(skb, &iphc1)) |
| 356 | goto drop; | 186 | goto drop; |
| 357 | 187 | ||
| 358 | _saddr = &mac_cb(skb)->sa; | 188 | ieee802154_addr_to_sa(&sa, &hdr->source); |
| 359 | _daddr = &mac_cb(skb)->da; | 189 | ieee802154_addr_to_sa(&da, &hdr->dest); |
| 190 | |||
| 191 | if (sa.addr_type == IEEE802154_ADDR_SHORT) | ||
| 192 | sap = &sa.short_addr; | ||
| 193 | else | ||
| 194 | sap = &sa.hwaddr; | ||
| 360 | 195 | ||
| 361 | return lowpan_process_data(skb, skb->dev, (u8 *)_saddr->hwaddr, | 196 | if (da.addr_type == IEEE802154_ADDR_SHORT) |
| 362 | _saddr->addr_type, IEEE802154_ADDR_LEN, | 197 | dap = &da.short_addr; |
| 363 | (u8 *)_daddr->hwaddr, _daddr->addr_type, | 198 | else |
| 364 | IEEE802154_ADDR_LEN, iphc0, iphc1, | 199 | dap = &da.hwaddr; |
| 365 | lowpan_give_skb_to_devices); | 200 | |
| 201 | return lowpan_process_data(skb, skb->dev, sap, sa.addr_type, | ||
| 202 | IEEE802154_ADDR_LEN, dap, da.addr_type, | ||
| 203 | IEEE802154_ADDR_LEN, iphc0, iphc1, | ||
| 204 | lowpan_give_skb_to_devices); | ||
| 366 | 205 | ||
| 367 | unlock_and_drop: | ||
| 368 | spin_unlock_bh(&flist_lock); | ||
| 369 | drop: | 206 | drop: |
| 370 | kfree_skb(skb); | 207 | kfree_skb(skb); |
| 371 | return -EINVAL; | 208 | return -EINVAL; |
| @@ -386,7 +223,7 @@ static int lowpan_set_address(struct net_device *dev, void *p) | |||
| 386 | 223 | ||
| 387 | static int | 224 | static int |
| 388 | lowpan_fragment_xmit(struct sk_buff *skb, u8 *head, | 225 | lowpan_fragment_xmit(struct sk_buff *skb, u8 *head, |
| 389 | int mlen, int plen, int offset, int type) | 226 | int mlen, int plen, int offset, int type) |
| 390 | { | 227 | { |
| 391 | struct sk_buff *frag; | 228 | struct sk_buff *frag; |
| 392 | int hlen; | 229 | int hlen; |
| @@ -422,51 +259,68 @@ lowpan_fragment_xmit(struct sk_buff *skb, u8 *head, | |||
| 422 | static int | 259 | static int |
| 423 | lowpan_skb_fragmentation(struct sk_buff *skb, struct net_device *dev) | 260 | lowpan_skb_fragmentation(struct sk_buff *skb, struct net_device *dev) |
| 424 | { | 261 | { |
| 425 | int err, header_length, payload_length, tag, offset = 0; | 262 | int err; |
| 263 | u16 dgram_offset, dgram_size, payload_length, header_length, | ||
| 264 | lowpan_size, frag_plen, offset; | ||
| 265 | __be16 tag; | ||
| 426 | u8 head[5]; | 266 | u8 head[5]; |
| 427 | 267 | ||
| 428 | header_length = skb->mac_len; | 268 | header_length = skb->mac_len; |
| 429 | payload_length = skb->len - header_length; | 269 | payload_length = skb->len - header_length; |
| 430 | tag = lowpan_dev_info(dev)->fragment_tag++; | 270 | tag = lowpan_dev_info(dev)->fragment_tag++; |
| 271 | lowpan_size = skb_network_header_len(skb); | ||
| 272 | dgram_size = lowpan_uncompress_size(skb, &dgram_offset) - | ||
| 273 | header_length; | ||
| 431 | 274 | ||
| 432 | /* first fragment header */ | 275 | /* first fragment header */ |
| 433 | head[0] = LOWPAN_DISPATCH_FRAG1 | ((payload_length >> 8) & 0x7); | 276 | head[0] = LOWPAN_DISPATCH_FRAG1 | ((dgram_size >> 8) & 0x7); |
| 434 | head[1] = payload_length & 0xff; | 277 | head[1] = dgram_size & 0xff; |
| 435 | head[2] = tag >> 8; | 278 | memcpy(head + 2, &tag, sizeof(tag)); |
| 436 | head[3] = tag & 0xff; | ||
| 437 | 279 | ||
| 438 | err = lowpan_fragment_xmit(skb, head, header_length, LOWPAN_FRAG_SIZE, | 280 | /* calc the nearest payload length(divided to 8) for first fragment |
| 439 | 0, LOWPAN_DISPATCH_FRAG1); | 281 | * which fits into a IEEE802154_MTU |
| 282 | */ | ||
| 283 | frag_plen = round_down(IEEE802154_MTU - header_length - | ||
| 284 | LOWPAN_FRAG1_HEAD_SIZE - lowpan_size - | ||
| 285 | IEEE802154_MFR_SIZE, 8); | ||
| 440 | 286 | ||
| 287 | err = lowpan_fragment_xmit(skb, head, header_length, | ||
| 288 | frag_plen + lowpan_size, 0, | ||
| 289 | LOWPAN_DISPATCH_FRAG1); | ||
| 441 | if (err) { | 290 | if (err) { |
| 442 | pr_debug("%s unable to send FRAG1 packet (tag: %d)", | 291 | pr_debug("%s unable to send FRAG1 packet (tag: %d)", |
| 443 | __func__, tag); | 292 | __func__, tag); |
| 444 | goto exit; | 293 | goto exit; |
| 445 | } | 294 | } |
| 446 | 295 | ||
| 447 | offset = LOWPAN_FRAG_SIZE; | 296 | offset = lowpan_size + frag_plen; |
| 297 | dgram_offset += frag_plen; | ||
| 448 | 298 | ||
| 449 | /* next fragment header */ | 299 | /* next fragment header */ |
| 450 | head[0] &= ~LOWPAN_DISPATCH_FRAG1; | 300 | head[0] &= ~LOWPAN_DISPATCH_FRAG1; |
| 451 | head[0] |= LOWPAN_DISPATCH_FRAGN; | 301 | head[0] |= LOWPAN_DISPATCH_FRAGN; |
| 452 | 302 | ||
| 303 | frag_plen = round_down(IEEE802154_MTU - header_length - | ||
| 304 | LOWPAN_FRAGN_HEAD_SIZE - IEEE802154_MFR_SIZE, 8); | ||
| 305 | |||
| 453 | while (payload_length - offset > 0) { | 306 | while (payload_length - offset > 0) { |
| 454 | int len = LOWPAN_FRAG_SIZE; | 307 | int len = frag_plen; |
| 455 | 308 | ||
| 456 | head[4] = offset / 8; | 309 | head[4] = dgram_offset >> 3; |
| 457 | 310 | ||
| 458 | if (payload_length - offset < len) | 311 | if (payload_length - offset < len) |
| 459 | len = payload_length - offset; | 312 | len = payload_length - offset; |
| 460 | 313 | ||
| 461 | err = lowpan_fragment_xmit(skb, head, header_length, | 314 | err = lowpan_fragment_xmit(skb, head, header_length, len, |
| 462 | len, offset, LOWPAN_DISPATCH_FRAGN); | 315 | offset, LOWPAN_DISPATCH_FRAGN); |
| 463 | if (err) { | 316 | if (err) { |
| 464 | pr_debug("%s unable to send a subsequent FRAGN packet " | 317 | pr_debug("%s unable to send a FRAGN packet. (tag: %d, offset: %d)\n", |
| 465 | "(tag: %d, offset: %d", __func__, tag, offset); | 318 | __func__, tag, offset); |
| 466 | goto exit; | 319 | goto exit; |
| 467 | } | 320 | } |
| 468 | 321 | ||
| 469 | offset += len; | 322 | offset += len; |
| 323 | dgram_offset += len; | ||
| 470 | } | 324 | } |
| 471 | 325 | ||
| 472 | exit: | 326 | exit: |
| @@ -508,13 +362,13 @@ static struct wpan_phy *lowpan_get_phy(const struct net_device *dev) | |||
| 508 | return ieee802154_mlme_ops(real_dev)->get_phy(real_dev); | 362 | return ieee802154_mlme_ops(real_dev)->get_phy(real_dev); |
| 509 | } | 363 | } |
| 510 | 364 | ||
| 511 | static u16 lowpan_get_pan_id(const struct net_device *dev) | 365 | static __le16 lowpan_get_pan_id(const struct net_device *dev) |
| 512 | { | 366 | { |
| 513 | struct net_device *real_dev = lowpan_dev_info(dev)->real_dev; | 367 | struct net_device *real_dev = lowpan_dev_info(dev)->real_dev; |
| 514 | return ieee802154_mlme_ops(real_dev)->get_pan_id(real_dev); | 368 | return ieee802154_mlme_ops(real_dev)->get_pan_id(real_dev); |
| 515 | } | 369 | } |
| 516 | 370 | ||
| 517 | static u16 lowpan_get_short_addr(const struct net_device *dev) | 371 | static __le16 lowpan_get_short_addr(const struct net_device *dev) |
| 518 | { | 372 | { |
| 519 | struct net_device *real_dev = lowpan_dev_info(dev)->real_dev; | 373 | struct net_device *real_dev = lowpan_dev_info(dev)->real_dev; |
| 520 | return ieee802154_mlme_ops(real_dev)->get_short_addr(real_dev); | 374 | return ieee802154_mlme_ops(real_dev)->get_short_addr(real_dev); |
| @@ -593,45 +447,55 @@ static int lowpan_validate(struct nlattr *tb[], struct nlattr *data[]) | |||
| 593 | static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev, | 447 | static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev, |
| 594 | struct packet_type *pt, struct net_device *orig_dev) | 448 | struct packet_type *pt, struct net_device *orig_dev) |
| 595 | { | 449 | { |
| 596 | struct sk_buff *local_skb; | 450 | struct ieee802154_hdr hdr; |
| 451 | int ret; | ||
| 597 | 452 | ||
| 598 | if (!netif_running(dev)) | 453 | skb = skb_share_check(skb, GFP_ATOMIC); |
| 454 | if (!skb) | ||
| 599 | goto drop; | 455 | goto drop; |
| 600 | 456 | ||
| 457 | if (!netif_running(dev)) | ||
| 458 | goto drop_skb; | ||
| 459 | |||
| 601 | if (dev->type != ARPHRD_IEEE802154) | 460 | if (dev->type != ARPHRD_IEEE802154) |
| 602 | goto drop; | 461 | goto drop_skb; |
| 462 | |||
| 463 | if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0) | ||
| 464 | goto drop_skb; | ||
| 603 | 465 | ||
| 604 | /* check that it's our buffer */ | 466 | /* check that it's our buffer */ |
| 605 | if (skb->data[0] == LOWPAN_DISPATCH_IPV6) { | 467 | if (skb->data[0] == LOWPAN_DISPATCH_IPV6) { |
| 606 | /* Copy the packet so that the IPv6 header is | 468 | skb->protocol = htons(ETH_P_IPV6); |
| 607 | * properly aligned. | 469 | skb->pkt_type = PACKET_HOST; |
| 608 | */ | ||
| 609 | local_skb = skb_copy_expand(skb, NET_SKB_PAD - 1, | ||
| 610 | skb_tailroom(skb), GFP_ATOMIC); | ||
| 611 | if (!local_skb) | ||
| 612 | goto drop; | ||
| 613 | |||
| 614 | local_skb->protocol = htons(ETH_P_IPV6); | ||
| 615 | local_skb->pkt_type = PACKET_HOST; | ||
| 616 | 470 | ||
| 617 | /* Pull off the 1-byte of 6lowpan header. */ | 471 | /* Pull off the 1-byte of 6lowpan header. */ |
| 618 | skb_pull(local_skb, 1); | 472 | skb_pull(skb, 1); |
| 619 | |||
| 620 | lowpan_give_skb_to_devices(local_skb, NULL); | ||
| 621 | 473 | ||
| 622 | kfree_skb(local_skb); | 474 | ret = lowpan_give_skb_to_devices(skb, NULL); |
| 623 | kfree_skb(skb); | 475 | if (ret == NET_RX_DROP) |
| 476 | goto drop; | ||
| 624 | } else { | 477 | } else { |
| 625 | switch (skb->data[0] & 0xe0) { | 478 | switch (skb->data[0] & 0xe0) { |
| 626 | case LOWPAN_DISPATCH_IPHC: /* ipv6 datagram */ | 479 | case LOWPAN_DISPATCH_IPHC: /* ipv6 datagram */ |
| 480 | ret = process_data(skb, &hdr); | ||
| 481 | if (ret == NET_RX_DROP) | ||
| 482 | goto drop; | ||
| 483 | break; | ||
| 627 | case LOWPAN_DISPATCH_FRAG1: /* first fragment header */ | 484 | case LOWPAN_DISPATCH_FRAG1: /* first fragment header */ |
| 485 | ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAG1); | ||
| 486 | if (ret == 1) { | ||
| 487 | ret = process_data(skb, &hdr); | ||
| 488 | if (ret == NET_RX_DROP) | ||
| 489 | goto drop; | ||
| 490 | } | ||
| 491 | break; | ||
| 628 | case LOWPAN_DISPATCH_FRAGN: /* next fragments headers */ | 492 | case LOWPAN_DISPATCH_FRAGN: /* next fragments headers */ |
| 629 | local_skb = skb_clone(skb, GFP_ATOMIC); | 493 | ret = lowpan_frag_rcv(skb, LOWPAN_DISPATCH_FRAGN); |
| 630 | if (!local_skb) | 494 | if (ret == 1) { |
| 631 | goto drop; | 495 | ret = process_data(skb, &hdr); |
| 632 | process_data(local_skb); | 496 | if (ret == NET_RX_DROP) |
| 633 | 497 | goto drop; | |
| 634 | kfree_skb(skb); | 498 | } |
| 635 | break; | 499 | break; |
| 636 | default: | 500 | default: |
| 637 | break; | 501 | break; |
| @@ -639,9 +503,9 @@ static int lowpan_rcv(struct sk_buff *skb, struct net_device *dev, | |||
| 639 | } | 503 | } |
| 640 | 504 | ||
| 641 | return NET_RX_SUCCESS; | 505 | return NET_RX_SUCCESS; |
| 642 | 506 | drop_skb: | |
| 643 | drop: | ||
| 644 | kfree_skb(skb); | 507 | kfree_skb(skb); |
| 508 | drop: | ||
| 645 | return NET_RX_DROP; | 509 | return NET_RX_DROP; |
| 646 | } | 510 | } |
| 647 | 511 | ||
| @@ -665,10 +529,9 @@ static int lowpan_newlink(struct net *src_net, struct net_device *dev, | |||
| 665 | } | 529 | } |
| 666 | 530 | ||
| 667 | lowpan_dev_info(dev)->real_dev = real_dev; | 531 | lowpan_dev_info(dev)->real_dev = real_dev; |
| 668 | lowpan_dev_info(dev)->fragment_tag = 0; | ||
| 669 | mutex_init(&lowpan_dev_info(dev)->dev_list_mtx); | 532 | mutex_init(&lowpan_dev_info(dev)->dev_list_mtx); |
| 670 | 533 | ||
| 671 | entry = kzalloc(sizeof(struct lowpan_dev_record), GFP_KERNEL); | 534 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); |
| 672 | if (!entry) { | 535 | if (!entry) { |
| 673 | dev_put(real_dev); | 536 | dev_put(real_dev); |
| 674 | lowpan_dev_info(dev)->real_dev = NULL; | 537 | lowpan_dev_info(dev)->real_dev = NULL; |
| @@ -761,7 +624,7 @@ static struct notifier_block lowpan_dev_notifier = { | |||
| 761 | }; | 624 | }; |
| 762 | 625 | ||
| 763 | static struct packet_type lowpan_packet_type = { | 626 | static struct packet_type lowpan_packet_type = { |
| 764 | .type = __constant_htons(ETH_P_IEEE802154), | 627 | .type = htons(ETH_P_IEEE802154), |
| 765 | .func = lowpan_rcv, | 628 | .func = lowpan_rcv, |
| 766 | }; | 629 | }; |
| 767 | 630 | ||
| @@ -769,43 +632,40 @@ static int __init lowpan_init_module(void) | |||
| 769 | { | 632 | { |
| 770 | int err = 0; | 633 | int err = 0; |
| 771 | 634 | ||
| 772 | err = lowpan_netlink_init(); | 635 | err = lowpan_net_frag_init(); |
| 773 | if (err < 0) | 636 | if (err < 0) |
| 774 | goto out; | 637 | goto out; |
| 775 | 638 | ||
| 639 | err = lowpan_netlink_init(); | ||
| 640 | if (err < 0) | ||
| 641 | goto out_frag; | ||
| 642 | |||
| 776 | dev_add_pack(&lowpan_packet_type); | 643 | dev_add_pack(&lowpan_packet_type); |
| 777 | 644 | ||
| 778 | err = register_netdevice_notifier(&lowpan_dev_notifier); | 645 | err = register_netdevice_notifier(&lowpan_dev_notifier); |
| 779 | if (err < 0) { | 646 | if (err < 0) |
| 780 | dev_remove_pack(&lowpan_packet_type); | 647 | goto out_pack; |
| 781 | lowpan_netlink_fini(); | 648 | |
| 782 | } | 649 | return 0; |
| 650 | |||
| 651 | out_pack: | ||
| 652 | dev_remove_pack(&lowpan_packet_type); | ||
| 653 | lowpan_netlink_fini(); | ||
| 654 | out_frag: | ||
| 655 | lowpan_net_frag_exit(); | ||
| 783 | out: | 656 | out: |
| 784 | return err; | 657 | return err; |
| 785 | } | 658 | } |
| 786 | 659 | ||
| 787 | static void __exit lowpan_cleanup_module(void) | 660 | static void __exit lowpan_cleanup_module(void) |
| 788 | { | 661 | { |
| 789 | struct lowpan_fragment *frame, *tframe; | ||
| 790 | |||
| 791 | lowpan_netlink_fini(); | 662 | lowpan_netlink_fini(); |
| 792 | 663 | ||
| 793 | dev_remove_pack(&lowpan_packet_type); | 664 | dev_remove_pack(&lowpan_packet_type); |
| 794 | 665 | ||
| 795 | unregister_netdevice_notifier(&lowpan_dev_notifier); | 666 | lowpan_net_frag_exit(); |
| 796 | 667 | ||
| 797 | /* Now 6lowpan packet_type is removed, so no new fragments are | 668 | unregister_netdevice_notifier(&lowpan_dev_notifier); |
| 798 | * expected on RX, therefore that's the time to clean incomplete | ||
| 799 | * fragments. | ||
| 800 | */ | ||
| 801 | spin_lock_bh(&flist_lock); | ||
| 802 | list_for_each_entry_safe(frame, tframe, &lowpan_fragments, list) { | ||
| 803 | del_timer_sync(&frame->timer); | ||
| 804 | list_del(&frame->list); | ||
| 805 | dev_kfree_skb(frame->skb); | ||
| 806 | kfree(frame); | ||
| 807 | } | ||
| 808 | spin_unlock_bh(&flist_lock); | ||
| 809 | } | 669 | } |
| 810 | 670 | ||
| 811 | module_init(lowpan_init_module); | 671 | module_init(lowpan_init_module); |
diff --git a/net/ieee802154/Kconfig b/net/ieee802154/Kconfig index 9c9879d5ea64..8af1330b3137 100644 --- a/net/ieee802154/Kconfig +++ b/net/ieee802154/Kconfig | |||
| @@ -15,7 +15,7 @@ config IEEE802154_6LOWPAN | |||
| 15 | depends on IEEE802154 && IPV6 | 15 | depends on IEEE802154 && IPV6 |
| 16 | select 6LOWPAN_IPHC | 16 | select 6LOWPAN_IPHC |
| 17 | ---help--- | 17 | ---help--- |
| 18 | IPv6 compression over IEEE 802.15.4. | 18 | IPv6 compression over IEEE 802.15.4. |
| 19 | 19 | ||
| 20 | config 6LOWPAN_IPHC | 20 | config 6LOWPAN_IPHC |
| 21 | tristate | 21 | tristate |
diff --git a/net/ieee802154/Makefile b/net/ieee802154/Makefile index e8f05885ced6..bf1b51497a41 100644 --- a/net/ieee802154/Makefile +++ b/net/ieee802154/Makefile | |||
| @@ -2,5 +2,9 @@ obj-$(CONFIG_IEEE802154) += ieee802154.o af_802154.o | |||
| 2 | obj-$(CONFIG_IEEE802154_6LOWPAN) += 6lowpan.o | 2 | obj-$(CONFIG_IEEE802154_6LOWPAN) += 6lowpan.o |
| 3 | obj-$(CONFIG_6LOWPAN_IPHC) += 6lowpan_iphc.o | 3 | obj-$(CONFIG_6LOWPAN_IPHC) += 6lowpan_iphc.o |
| 4 | 4 | ||
| 5 | ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o | 5 | 6lowpan-y := 6lowpan_rtnl.o reassembly.o |
| 6 | ieee802154-y := netlink.o nl-mac.o nl-phy.o nl_policy.o wpan-class.o \ | ||
| 7 | header_ops.o | ||
| 6 | af_802154-y := af_ieee802154.o raw.o dgram.o | 8 | af_802154-y := af_ieee802154.o raw.o dgram.o |
| 9 | |||
| 10 | ccflags-y += -D__CHECK_ENDIAN__ | ||
diff --git a/net/ieee802154/af802154.h b/net/ieee802154/af802154.h index b1ec52537522..8330a09bfc95 100644 --- a/net/ieee802154/af802154.h +++ b/net/ieee802154/af802154.h | |||
| @@ -25,12 +25,13 @@ | |||
| 25 | #define AF802154_H | 25 | #define AF802154_H |
| 26 | 26 | ||
| 27 | struct sk_buff; | 27 | struct sk_buff; |
| 28 | struct net_devce; | 28 | struct net_device; |
| 29 | struct ieee802154_addr; | ||
| 29 | extern struct proto ieee802154_raw_prot; | 30 | extern struct proto ieee802154_raw_prot; |
| 30 | extern struct proto ieee802154_dgram_prot; | 31 | extern struct proto ieee802154_dgram_prot; |
| 31 | void ieee802154_raw_deliver(struct net_device *dev, struct sk_buff *skb); | 32 | void ieee802154_raw_deliver(struct net_device *dev, struct sk_buff *skb); |
| 32 | int ieee802154_dgram_deliver(struct net_device *dev, struct sk_buff *skb); | 33 | int ieee802154_dgram_deliver(struct net_device *dev, struct sk_buff *skb); |
| 33 | struct net_device *ieee802154_get_dev(struct net *net, | 34 | struct net_device *ieee802154_get_dev(struct net *net, |
| 34 | struct ieee802154_addr *addr); | 35 | const struct ieee802154_addr *addr); |
| 35 | 36 | ||
| 36 | #endif | 37 | #endif |
diff --git a/net/ieee802154/af_ieee802154.c b/net/ieee802154/af_ieee802154.c index 40e606f3788f..351d9a94ec2f 100644 --- a/net/ieee802154/af_ieee802154.c +++ b/net/ieee802154/af_ieee802154.c | |||
| @@ -43,25 +43,27 @@ | |||
| 43 | /* | 43 | /* |
| 44 | * Utility function for families | 44 | * Utility function for families |
| 45 | */ | 45 | */ |
| 46 | struct net_device *ieee802154_get_dev(struct net *net, | 46 | struct net_device* |
| 47 | struct ieee802154_addr *addr) | 47 | ieee802154_get_dev(struct net *net, const struct ieee802154_addr *addr) |
| 48 | { | 48 | { |
| 49 | struct net_device *dev = NULL; | 49 | struct net_device *dev = NULL; |
| 50 | struct net_device *tmp; | 50 | struct net_device *tmp; |
| 51 | u16 pan_id, short_addr; | 51 | __le16 pan_id, short_addr; |
| 52 | u8 hwaddr[IEEE802154_ADDR_LEN]; | ||
| 52 | 53 | ||
| 53 | switch (addr->addr_type) { | 54 | switch (addr->mode) { |
| 54 | case IEEE802154_ADDR_LONG: | 55 | case IEEE802154_ADDR_LONG: |
| 56 | ieee802154_devaddr_to_raw(hwaddr, addr->extended_addr); | ||
| 55 | rcu_read_lock(); | 57 | rcu_read_lock(); |
| 56 | dev = dev_getbyhwaddr_rcu(net, ARPHRD_IEEE802154, addr->hwaddr); | 58 | dev = dev_getbyhwaddr_rcu(net, ARPHRD_IEEE802154, hwaddr); |
| 57 | if (dev) | 59 | if (dev) |
| 58 | dev_hold(dev); | 60 | dev_hold(dev); |
| 59 | rcu_read_unlock(); | 61 | rcu_read_unlock(); |
| 60 | break; | 62 | break; |
| 61 | case IEEE802154_ADDR_SHORT: | 63 | case IEEE802154_ADDR_SHORT: |
| 62 | if (addr->pan_id == 0xffff || | 64 | if (addr->pan_id == cpu_to_le16(IEEE802154_PANID_BROADCAST) || |
| 63 | addr->short_addr == IEEE802154_ADDR_UNDEF || | 65 | addr->short_addr == cpu_to_le16(IEEE802154_ADDR_UNDEF) || |
| 64 | addr->short_addr == 0xffff) | 66 | addr->short_addr == cpu_to_le16(IEEE802154_ADDR_BROADCAST)) |
| 65 | break; | 67 | break; |
| 66 | 68 | ||
| 67 | rtnl_lock(); | 69 | rtnl_lock(); |
| @@ -86,7 +88,7 @@ struct net_device *ieee802154_get_dev(struct net *net, | |||
| 86 | break; | 88 | break; |
| 87 | default: | 89 | default: |
| 88 | pr_warning("Unsupported ieee802154 address type: %d\n", | 90 | pr_warning("Unsupported ieee802154 address type: %d\n", |
| 89 | addr->addr_type); | 91 | addr->mode); |
| 90 | break; | 92 | break; |
| 91 | } | 93 | } |
| 92 | 94 | ||
| @@ -326,7 +328,7 @@ drop: | |||
| 326 | 328 | ||
| 327 | 329 | ||
| 328 | static struct packet_type ieee802154_packet_type = { | 330 | static struct packet_type ieee802154_packet_type = { |
| 329 | .type = __constant_htons(ETH_P_IEEE802154), | 331 | .type = htons(ETH_P_IEEE802154), |
| 330 | .func = ieee802154_rcv, | 332 | .func = ieee802154_rcv, |
| 331 | }; | 333 | }; |
| 332 | 334 | ||
diff --git a/net/ieee802154/dgram.c b/net/ieee802154/dgram.c index 1846c1fe0d06..786437bc0c08 100644 --- a/net/ieee802154/dgram.c +++ b/net/ieee802154/dgram.c | |||
| @@ -73,10 +73,10 @@ static int dgram_init(struct sock *sk) | |||
| 73 | { | 73 | { |
| 74 | struct dgram_sock *ro = dgram_sk(sk); | 74 | struct dgram_sock *ro = dgram_sk(sk); |
| 75 | 75 | ||
| 76 | ro->dst_addr.addr_type = IEEE802154_ADDR_LONG; | 76 | ro->dst_addr.mode = IEEE802154_ADDR_LONG; |
| 77 | ro->dst_addr.pan_id = 0xffff; | 77 | ro->dst_addr.pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST); |
| 78 | ro->want_ack = 1; | 78 | ro->want_ack = 1; |
| 79 | memset(&ro->dst_addr.hwaddr, 0xff, sizeof(ro->dst_addr.hwaddr)); | 79 | memset(&ro->dst_addr.extended_addr, 0xff, IEEE802154_ADDR_LEN); |
| 80 | return 0; | 80 | return 0; |
| 81 | } | 81 | } |
| 82 | 82 | ||
| @@ -88,6 +88,7 @@ static void dgram_close(struct sock *sk, long timeout) | |||
| 88 | static int dgram_bind(struct sock *sk, struct sockaddr *uaddr, int len) | 88 | static int dgram_bind(struct sock *sk, struct sockaddr *uaddr, int len) |
| 89 | { | 89 | { |
| 90 | struct sockaddr_ieee802154 *addr = (struct sockaddr_ieee802154 *)uaddr; | 90 | struct sockaddr_ieee802154 *addr = (struct sockaddr_ieee802154 *)uaddr; |
| 91 | struct ieee802154_addr haddr; | ||
| 91 | struct dgram_sock *ro = dgram_sk(sk); | 92 | struct dgram_sock *ro = dgram_sk(sk); |
| 92 | int err = -EINVAL; | 93 | int err = -EINVAL; |
| 93 | struct net_device *dev; | 94 | struct net_device *dev; |
| @@ -102,7 +103,8 @@ static int dgram_bind(struct sock *sk, struct sockaddr *uaddr, int len) | |||
| 102 | if (addr->family != AF_IEEE802154) | 103 | if (addr->family != AF_IEEE802154) |
| 103 | goto out; | 104 | goto out; |
| 104 | 105 | ||
| 105 | dev = ieee802154_get_dev(sock_net(sk), &addr->addr); | 106 | ieee802154_addr_from_sa(&haddr, &addr->addr); |
| 107 | dev = ieee802154_get_dev(sock_net(sk), &haddr); | ||
| 106 | if (!dev) { | 108 | if (!dev) { |
| 107 | err = -ENODEV; | 109 | err = -ENODEV; |
| 108 | goto out; | 110 | goto out; |
| @@ -113,7 +115,7 @@ static int dgram_bind(struct sock *sk, struct sockaddr *uaddr, int len) | |||
| 113 | goto out_put; | 115 | goto out_put; |
| 114 | } | 116 | } |
| 115 | 117 | ||
| 116 | memcpy(&ro->src_addr, &addr->addr, sizeof(struct ieee802154_addr)); | 118 | ro->src_addr = haddr; |
| 117 | 119 | ||
| 118 | ro->bound = 1; | 120 | ro->bound = 1; |
| 119 | err = 0; | 121 | err = 0; |
| @@ -149,8 +151,7 @@ static int dgram_ioctl(struct sock *sk, int cmd, unsigned long arg) | |||
| 149 | * of this packet since that is all | 151 | * of this packet since that is all |
| 150 | * that will be read. | 152 | * that will be read. |
| 151 | */ | 153 | */ |
| 152 | /* FIXME: parse the header for more correct value */ | 154 | amount = skb->len - ieee802154_hdr_length(skb); |
| 153 | amount = skb->len - (3+8+8); | ||
| 154 | } | 155 | } |
| 155 | spin_unlock_bh(&sk->sk_receive_queue.lock); | 156 | spin_unlock_bh(&sk->sk_receive_queue.lock); |
| 156 | return put_user(amount, (int __user *)arg); | 157 | return put_user(amount, (int __user *)arg); |
| @@ -181,7 +182,7 @@ static int dgram_connect(struct sock *sk, struct sockaddr *uaddr, | |||
| 181 | goto out; | 182 | goto out; |
| 182 | } | 183 | } |
| 183 | 184 | ||
| 184 | memcpy(&ro->dst_addr, &addr->addr, sizeof(struct ieee802154_addr)); | 185 | ieee802154_addr_from_sa(&ro->dst_addr, &addr->addr); |
| 185 | 186 | ||
| 186 | out: | 187 | out: |
| 187 | release_sock(sk); | 188 | release_sock(sk); |
| @@ -194,8 +195,8 @@ static int dgram_disconnect(struct sock *sk, int flags) | |||
| 194 | 195 | ||
| 195 | lock_sock(sk); | 196 | lock_sock(sk); |
| 196 | 197 | ||
| 197 | ro->dst_addr.addr_type = IEEE802154_ADDR_LONG; | 198 | ro->dst_addr.mode = IEEE802154_ADDR_LONG; |
| 198 | memset(&ro->dst_addr.hwaddr, 0xff, sizeof(ro->dst_addr.hwaddr)); | 199 | memset(&ro->dst_addr.extended_addr, 0xff, IEEE802154_ADDR_LEN); |
| 199 | 200 | ||
| 200 | release_sock(sk); | 201 | release_sock(sk); |
| 201 | 202 | ||
| @@ -232,7 +233,7 @@ static int dgram_sendmsg(struct kiocb *iocb, struct sock *sk, | |||
| 232 | 233 | ||
| 233 | if (size > mtu) { | 234 | if (size > mtu) { |
| 234 | pr_debug("size = %Zu, mtu = %u\n", size, mtu); | 235 | pr_debug("size = %Zu, mtu = %u\n", size, mtu); |
| 235 | err = -EINVAL; | 236 | err = -EMSGSIZE; |
| 236 | goto out_dev; | 237 | goto out_dev; |
| 237 | } | 238 | } |
| 238 | 239 | ||
| @@ -312,7 +313,7 @@ static int dgram_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
| 312 | 313 | ||
| 313 | if (saddr) { | 314 | if (saddr) { |
| 314 | saddr->family = AF_IEEE802154; | 315 | saddr->family = AF_IEEE802154; |
| 315 | saddr->addr = mac_cb(skb)->sa; | 316 | ieee802154_addr_to_sa(&saddr->addr, &mac_cb(skb)->source); |
| 316 | *addr_len = sizeof(*saddr); | 317 | *addr_len = sizeof(*saddr); |
| 317 | } | 318 | } |
| 318 | 319 | ||
| @@ -328,6 +329,10 @@ out: | |||
| 328 | 329 | ||
| 329 | static int dgram_rcv_skb(struct sock *sk, struct sk_buff *skb) | 330 | static int dgram_rcv_skb(struct sock *sk, struct sk_buff *skb) |
| 330 | { | 331 | { |
| 332 | skb = skb_share_check(skb, GFP_ATOMIC); | ||
| 333 | if (!skb) | ||
| 334 | return NET_RX_DROP; | ||
| 335 | |||
| 331 | if (sock_queue_rcv_skb(sk, skb) < 0) { | 336 | if (sock_queue_rcv_skb(sk, skb) < 0) { |
| 332 | kfree_skb(skb); | 337 | kfree_skb(skb); |
| 333 | return NET_RX_DROP; | 338 | return NET_RX_DROP; |
| @@ -336,40 +341,43 @@ static int dgram_rcv_skb(struct sock *sk, struct sk_buff *skb) | |||
| 336 | return NET_RX_SUCCESS; | 341 | return NET_RX_SUCCESS; |
| 337 | } | 342 | } |
| 338 | 343 | ||
| 339 | static inline int ieee802154_match_sock(u8 *hw_addr, u16 pan_id, | 344 | static inline bool |
| 340 | u16 short_addr, struct dgram_sock *ro) | 345 | ieee802154_match_sock(__le64 hw_addr, __le16 pan_id, __le16 short_addr, |
| 346 | struct dgram_sock *ro) | ||
| 341 | { | 347 | { |
| 342 | if (!ro->bound) | 348 | if (!ro->bound) |
| 343 | return 1; | 349 | return true; |
| 344 | 350 | ||
| 345 | if (ro->src_addr.addr_type == IEEE802154_ADDR_LONG && | 351 | if (ro->src_addr.mode == IEEE802154_ADDR_LONG && |
| 346 | !memcmp(ro->src_addr.hwaddr, hw_addr, IEEE802154_ADDR_LEN)) | 352 | hw_addr == ro->src_addr.extended_addr) |
| 347 | return 1; | 353 | return true; |
| 348 | 354 | ||
| 349 | if (ro->src_addr.addr_type == IEEE802154_ADDR_SHORT && | 355 | if (ro->src_addr.mode == IEEE802154_ADDR_SHORT && |
| 350 | pan_id == ro->src_addr.pan_id && | 356 | pan_id == ro->src_addr.pan_id && |
| 351 | short_addr == ro->src_addr.short_addr) | 357 | short_addr == ro->src_addr.short_addr) |
| 352 | return 1; | 358 | return true; |
| 353 | 359 | ||
| 354 | return 0; | 360 | return false; |
| 355 | } | 361 | } |
| 356 | 362 | ||
| 357 | int ieee802154_dgram_deliver(struct net_device *dev, struct sk_buff *skb) | 363 | int ieee802154_dgram_deliver(struct net_device *dev, struct sk_buff *skb) |
| 358 | { | 364 | { |
| 359 | struct sock *sk, *prev = NULL; | 365 | struct sock *sk, *prev = NULL; |
| 360 | int ret = NET_RX_SUCCESS; | 366 | int ret = NET_RX_SUCCESS; |
| 361 | u16 pan_id, short_addr; | 367 | __le16 pan_id, short_addr; |
| 368 | __le64 hw_addr; | ||
| 362 | 369 | ||
| 363 | /* Data frame processing */ | 370 | /* Data frame processing */ |
| 364 | BUG_ON(dev->type != ARPHRD_IEEE802154); | 371 | BUG_ON(dev->type != ARPHRD_IEEE802154); |
| 365 | 372 | ||
| 366 | pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); | 373 | pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); |
| 367 | short_addr = ieee802154_mlme_ops(dev)->get_short_addr(dev); | 374 | short_addr = ieee802154_mlme_ops(dev)->get_short_addr(dev); |
| 375 | hw_addr = ieee802154_devaddr_from_raw(dev->dev_addr); | ||
| 368 | 376 | ||
| 369 | read_lock(&dgram_lock); | 377 | read_lock(&dgram_lock); |
| 370 | sk_for_each(sk, &dgram_head) { | 378 | sk_for_each(sk, &dgram_head) { |
| 371 | if (ieee802154_match_sock(dev->dev_addr, pan_id, short_addr, | 379 | if (ieee802154_match_sock(hw_addr, pan_id, short_addr, |
| 372 | dgram_sk(sk))) { | 380 | dgram_sk(sk))) { |
| 373 | if (prev) { | 381 | if (prev) { |
| 374 | struct sk_buff *clone; | 382 | struct sk_buff *clone; |
| 375 | clone = skb_clone(skb, GFP_ATOMIC); | 383 | clone = skb_clone(skb, GFP_ATOMIC); |
diff --git a/net/ieee802154/header_ops.c b/net/ieee802154/header_ops.c new file mode 100644 index 000000000000..bed42a48408c --- /dev/null +++ b/net/ieee802154/header_ops.c | |||
| @@ -0,0 +1,287 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (C) 2014 Fraunhofer ITWM | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License version 2 | ||
| 6 | * as published by the Free Software Foundation. | ||
| 7 | * | ||
| 8 | * This program is distributed in the hope that it will be useful, | ||
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 11 | * GNU General Public License for more details. | ||
| 12 | * | ||
| 13 | * Written by: | ||
| 14 | * Phoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de> | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <net/mac802154.h> | ||
| 18 | #include <net/ieee802154.h> | ||
| 19 | #include <net/ieee802154_netdev.h> | ||
| 20 | |||
| 21 | static int | ||
| 22 | ieee802154_hdr_push_addr(u8 *buf, const struct ieee802154_addr *addr, | ||
| 23 | bool omit_pan) | ||
| 24 | { | ||
| 25 | int pos = 0; | ||
| 26 | |||
| 27 | if (addr->mode == IEEE802154_ADDR_NONE) | ||
| 28 | return 0; | ||
| 29 | |||
| 30 | if (!omit_pan) { | ||
| 31 | memcpy(buf + pos, &addr->pan_id, 2); | ||
| 32 | pos += 2; | ||
| 33 | } | ||
| 34 | |||
| 35 | switch (addr->mode) { | ||
| 36 | case IEEE802154_ADDR_SHORT: | ||
| 37 | memcpy(buf + pos, &addr->short_addr, 2); | ||
| 38 | pos += 2; | ||
| 39 | break; | ||
| 40 | |||
| 41 | case IEEE802154_ADDR_LONG: | ||
| 42 | memcpy(buf + pos, &addr->extended_addr, IEEE802154_ADDR_LEN); | ||
| 43 | pos += IEEE802154_ADDR_LEN; | ||
| 44 | break; | ||
| 45 | |||
| 46 | default: | ||
| 47 | return -EINVAL; | ||
| 48 | } | ||
| 49 | |||
| 50 | return pos; | ||
| 51 | } | ||
| 52 | |||
| 53 | static int | ||
| 54 | ieee802154_hdr_push_sechdr(u8 *buf, const struct ieee802154_sechdr *hdr) | ||
| 55 | { | ||
| 56 | int pos = 5; | ||
| 57 | |||
| 58 | memcpy(buf, hdr, 1); | ||
| 59 | memcpy(buf + 1, &hdr->frame_counter, 4); | ||
| 60 | |||
| 61 | switch (hdr->key_id_mode) { | ||
| 62 | case IEEE802154_SCF_KEY_IMPLICIT: | ||
| 63 | return pos; | ||
| 64 | |||
| 65 | case IEEE802154_SCF_KEY_INDEX: | ||
| 66 | break; | ||
| 67 | |||
| 68 | case IEEE802154_SCF_KEY_SHORT_INDEX: | ||
| 69 | memcpy(buf + pos, &hdr->short_src, 4); | ||
| 70 | pos += 4; | ||
| 71 | break; | ||
| 72 | |||
| 73 | case IEEE802154_SCF_KEY_HW_INDEX: | ||
| 74 | memcpy(buf + pos, &hdr->extended_src, IEEE802154_ADDR_LEN); | ||
| 75 | pos += IEEE802154_ADDR_LEN; | ||
| 76 | break; | ||
| 77 | } | ||
| 78 | |||
| 79 | buf[pos++] = hdr->key_id; | ||
| 80 | |||
| 81 | return pos; | ||
| 82 | } | ||
| 83 | |||
| 84 | int | ||
| 85 | ieee802154_hdr_push(struct sk_buff *skb, const struct ieee802154_hdr *hdr) | ||
| 86 | { | ||
| 87 | u8 buf[MAC802154_FRAME_HARD_HEADER_LEN]; | ||
| 88 | int pos = 2; | ||
| 89 | int rc; | ||
| 90 | struct ieee802154_hdr_fc fc = hdr->fc; | ||
| 91 | |||
| 92 | buf[pos++] = hdr->seq; | ||
| 93 | |||
| 94 | fc.dest_addr_mode = hdr->dest.mode; | ||
| 95 | |||
| 96 | rc = ieee802154_hdr_push_addr(buf + pos, &hdr->dest, false); | ||
| 97 | if (rc < 0) | ||
| 98 | return -EINVAL; | ||
| 99 | pos += rc; | ||
| 100 | |||
| 101 | fc.source_addr_mode = hdr->source.mode; | ||
| 102 | |||
| 103 | if (hdr->source.pan_id == hdr->dest.pan_id && | ||
| 104 | hdr->dest.mode != IEEE802154_ADDR_NONE) | ||
| 105 | fc.intra_pan = true; | ||
| 106 | |||
| 107 | rc = ieee802154_hdr_push_addr(buf + pos, &hdr->source, fc.intra_pan); | ||
| 108 | if (rc < 0) | ||
| 109 | return -EINVAL; | ||
| 110 | pos += rc; | ||
| 111 | |||
| 112 | if (fc.security_enabled) { | ||
| 113 | fc.version = 1; | ||
| 114 | |||
| 115 | rc = ieee802154_hdr_push_sechdr(buf + pos, &hdr->sec); | ||
| 116 | if (rc < 0) | ||
| 117 | return -EINVAL; | ||
| 118 | |||
| 119 | pos += rc; | ||
| 120 | } | ||
| 121 | |||
| 122 | memcpy(buf, &fc, 2); | ||
| 123 | |||
| 124 | memcpy(skb_push(skb, pos), buf, pos); | ||
| 125 | |||
| 126 | return pos; | ||
| 127 | } | ||
| 128 | EXPORT_SYMBOL_GPL(ieee802154_hdr_push); | ||
| 129 | |||
| 130 | static int | ||
| 131 | ieee802154_hdr_get_addr(const u8 *buf, int mode, bool omit_pan, | ||
| 132 | struct ieee802154_addr *addr) | ||
| 133 | { | ||
| 134 | int pos = 0; | ||
| 135 | |||
| 136 | addr->mode = mode; | ||
| 137 | |||
| 138 | if (mode == IEEE802154_ADDR_NONE) | ||
| 139 | return 0; | ||
| 140 | |||
| 141 | if (!omit_pan) { | ||
| 142 | memcpy(&addr->pan_id, buf + pos, 2); | ||
| 143 | pos += 2; | ||
| 144 | } | ||
| 145 | |||
| 146 | if (mode == IEEE802154_ADDR_SHORT) { | ||
| 147 | memcpy(&addr->short_addr, buf + pos, 2); | ||
| 148 | return pos + 2; | ||
| 149 | } else { | ||
| 150 | memcpy(&addr->extended_addr, buf + pos, IEEE802154_ADDR_LEN); | ||
| 151 | return pos + IEEE802154_ADDR_LEN; | ||
| 152 | } | ||
| 153 | } | ||
| 154 | |||
| 155 | static int ieee802154_hdr_addr_len(int mode, bool omit_pan) | ||
| 156 | { | ||
| 157 | int pan_len = omit_pan ? 0 : 2; | ||
| 158 | |||
| 159 | switch (mode) { | ||
| 160 | case IEEE802154_ADDR_NONE: return 0; | ||
| 161 | case IEEE802154_ADDR_SHORT: return 2 + pan_len; | ||
| 162 | case IEEE802154_ADDR_LONG: return IEEE802154_ADDR_LEN + pan_len; | ||
| 163 | default: return -EINVAL; | ||
| 164 | } | ||
| 165 | } | ||
| 166 | |||
| 167 | static int | ||
| 168 | ieee802154_hdr_get_sechdr(const u8 *buf, struct ieee802154_sechdr *hdr) | ||
| 169 | { | ||
| 170 | int pos = 5; | ||
| 171 | |||
| 172 | memcpy(hdr, buf, 1); | ||
| 173 | memcpy(&hdr->frame_counter, buf + 1, 4); | ||
| 174 | |||
| 175 | switch (hdr->key_id_mode) { | ||
| 176 | case IEEE802154_SCF_KEY_IMPLICIT: | ||
| 177 | return pos; | ||
| 178 | |||
| 179 | case IEEE802154_SCF_KEY_INDEX: | ||
| 180 | break; | ||
| 181 | |||
| 182 | case IEEE802154_SCF_KEY_SHORT_INDEX: | ||
| 183 | memcpy(&hdr->short_src, buf + pos, 4); | ||
| 184 | pos += 4; | ||
| 185 | break; | ||
| 186 | |||
| 187 | case IEEE802154_SCF_KEY_HW_INDEX: | ||
| 188 | memcpy(&hdr->extended_src, buf + pos, IEEE802154_ADDR_LEN); | ||
| 189 | pos += IEEE802154_ADDR_LEN; | ||
| 190 | break; | ||
| 191 | } | ||
| 192 | |||
| 193 | hdr->key_id = buf[pos++]; | ||
| 194 | |||
| 195 | return pos; | ||
| 196 | } | ||
| 197 | |||
| 198 | static int ieee802154_hdr_sechdr_len(u8 sc) | ||
| 199 | { | ||
| 200 | switch (IEEE802154_SCF_KEY_ID_MODE(sc)) { | ||
| 201 | case IEEE802154_SCF_KEY_IMPLICIT: return 5; | ||
| 202 | case IEEE802154_SCF_KEY_INDEX: return 6; | ||
| 203 | case IEEE802154_SCF_KEY_SHORT_INDEX: return 10; | ||
| 204 | case IEEE802154_SCF_KEY_HW_INDEX: return 14; | ||
| 205 | default: return -EINVAL; | ||
| 206 | } | ||
| 207 | } | ||
| 208 | |||
| 209 | static int ieee802154_hdr_minlen(const struct ieee802154_hdr *hdr) | ||
| 210 | { | ||
| 211 | int dlen, slen; | ||
| 212 | |||
| 213 | dlen = ieee802154_hdr_addr_len(hdr->fc.dest_addr_mode, false); | ||
| 214 | slen = ieee802154_hdr_addr_len(hdr->fc.source_addr_mode, | ||
| 215 | hdr->fc.intra_pan); | ||
| 216 | |||
| 217 | if (slen < 0 || dlen < 0) | ||
| 218 | return -EINVAL; | ||
| 219 | |||
| 220 | return 3 + dlen + slen + hdr->fc.security_enabled; | ||
| 221 | } | ||
| 222 | |||
| 223 | static int | ||
| 224 | ieee802154_hdr_get_addrs(const u8 *buf, struct ieee802154_hdr *hdr) | ||
| 225 | { | ||
| 226 | int pos = 0; | ||
| 227 | |||
| 228 | pos += ieee802154_hdr_get_addr(buf + pos, hdr->fc.dest_addr_mode, | ||
| 229 | false, &hdr->dest); | ||
| 230 | pos += ieee802154_hdr_get_addr(buf + pos, hdr->fc.source_addr_mode, | ||
| 231 | hdr->fc.intra_pan, &hdr->source); | ||
| 232 | |||
| 233 | if (hdr->fc.intra_pan) | ||
| 234 | hdr->source.pan_id = hdr->dest.pan_id; | ||
| 235 | |||
| 236 | return pos; | ||
| 237 | } | ||
| 238 | |||
| 239 | int | ||
| 240 | ieee802154_hdr_pull(struct sk_buff *skb, struct ieee802154_hdr *hdr) | ||
| 241 | { | ||
| 242 | int pos = 3, rc; | ||
| 243 | |||
| 244 | if (!pskb_may_pull(skb, 3)) | ||
| 245 | return -EINVAL; | ||
| 246 | |||
| 247 | memcpy(hdr, skb->data, 3); | ||
| 248 | |||
| 249 | rc = ieee802154_hdr_minlen(hdr); | ||
| 250 | if (rc < 0 || !pskb_may_pull(skb, rc)) | ||
| 251 | return -EINVAL; | ||
| 252 | |||
| 253 | pos += ieee802154_hdr_get_addrs(skb->data + pos, hdr); | ||
| 254 | |||
| 255 | if (hdr->fc.security_enabled) { | ||
| 256 | int want = pos + ieee802154_hdr_sechdr_len(skb->data[pos]); | ||
| 257 | |||
| 258 | if (!pskb_may_pull(skb, want)) | ||
| 259 | return -EINVAL; | ||
| 260 | |||
| 261 | pos += ieee802154_hdr_get_sechdr(skb->data + pos, &hdr->sec); | ||
| 262 | } | ||
| 263 | |||
| 264 | skb_pull(skb, pos); | ||
| 265 | return pos; | ||
| 266 | } | ||
| 267 | EXPORT_SYMBOL_GPL(ieee802154_hdr_pull); | ||
| 268 | |||
| 269 | int | ||
| 270 | ieee802154_hdr_peek_addrs(const struct sk_buff *skb, struct ieee802154_hdr *hdr) | ||
| 271 | { | ||
| 272 | const u8 *buf = skb_mac_header(skb); | ||
| 273 | int pos = 3, rc; | ||
| 274 | |||
| 275 | if (buf + 3 > skb_tail_pointer(skb)) | ||
| 276 | return -EINVAL; | ||
| 277 | |||
| 278 | memcpy(hdr, buf, 3); | ||
| 279 | |||
| 280 | rc = ieee802154_hdr_minlen(hdr); | ||
| 281 | if (rc < 0 || buf + rc > skb_tail_pointer(skb)) | ||
| 282 | return -EINVAL; | ||
| 283 | |||
| 284 | pos += ieee802154_hdr_get_addrs(buf + pos, hdr); | ||
| 285 | return pos; | ||
| 286 | } | ||
| 287 | EXPORT_SYMBOL_GPL(ieee802154_hdr_peek_addrs); | ||
diff --git a/net/ieee802154/ieee802154.h b/net/ieee802154/ieee802154.h index cee4425b9956..6693a5cf01ce 100644 --- a/net/ieee802154/ieee802154.h +++ b/net/ieee802154/ieee802154.h | |||
| @@ -66,5 +66,6 @@ int ieee802154_scan_req(struct sk_buff *skb, struct genl_info *info); | |||
| 66 | int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info); | 66 | int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info); |
| 67 | int ieee802154_list_iface(struct sk_buff *skb, struct genl_info *info); | 67 | int ieee802154_list_iface(struct sk_buff *skb, struct genl_info *info); |
| 68 | int ieee802154_dump_iface(struct sk_buff *skb, struct netlink_callback *cb); | 68 | int ieee802154_dump_iface(struct sk_buff *skb, struct netlink_callback *cb); |
| 69 | int ieee802154_set_macparams(struct sk_buff *skb, struct genl_info *info); | ||
| 69 | 70 | ||
| 70 | #endif | 71 | #endif |
diff --git a/net/ieee802154/netlink.c b/net/ieee802154/netlink.c index 43f1b2bf469f..04b20589d97a 100644 --- a/net/ieee802154/netlink.c +++ b/net/ieee802154/netlink.c | |||
| @@ -123,6 +123,7 @@ static const struct genl_ops ieee8021154_ops[] = { | |||
| 123 | IEEE802154_OP(IEEE802154_START_REQ, ieee802154_start_req), | 123 | IEEE802154_OP(IEEE802154_START_REQ, ieee802154_start_req), |
| 124 | IEEE802154_DUMP(IEEE802154_LIST_IFACE, ieee802154_list_iface, | 124 | IEEE802154_DUMP(IEEE802154_LIST_IFACE, ieee802154_list_iface, |
| 125 | ieee802154_dump_iface), | 125 | ieee802154_dump_iface), |
| 126 | IEEE802154_OP(IEEE802154_SET_MACPARAMS, ieee802154_set_macparams), | ||
| 126 | }; | 127 | }; |
| 127 | 128 | ||
| 128 | static const struct genl_multicast_group ieee802154_mcgrps[] = { | 129 | static const struct genl_multicast_group ieee802154_mcgrps[] = { |
diff --git a/net/ieee802154/nl-mac.c b/net/ieee802154/nl-mac.c index ba5c1e002f37..5d285498c0f6 100644 --- a/net/ieee802154/nl-mac.c +++ b/net/ieee802154/nl-mac.c | |||
| @@ -39,6 +39,26 @@ | |||
| 39 | 39 | ||
| 40 | #include "ieee802154.h" | 40 | #include "ieee802154.h" |
| 41 | 41 | ||
| 42 | static int nla_put_hwaddr(struct sk_buff *msg, int type, __le64 hwaddr) | ||
| 43 | { | ||
| 44 | return nla_put_u64(msg, type, swab64((__force u64)hwaddr)); | ||
| 45 | } | ||
| 46 | |||
| 47 | static __le64 nla_get_hwaddr(const struct nlattr *nla) | ||
| 48 | { | ||
| 49 | return ieee802154_devaddr_from_raw(nla_data(nla)); | ||
| 50 | } | ||
| 51 | |||
| 52 | static int nla_put_shortaddr(struct sk_buff *msg, int type, __le16 addr) | ||
| 53 | { | ||
| 54 | return nla_put_u16(msg, type, le16_to_cpu(addr)); | ||
| 55 | } | ||
| 56 | |||
| 57 | static __le16 nla_get_shortaddr(const struct nlattr *nla) | ||
| 58 | { | ||
| 59 | return cpu_to_le16(nla_get_u16(nla)); | ||
| 60 | } | ||
| 61 | |||
| 42 | int ieee802154_nl_assoc_indic(struct net_device *dev, | 62 | int ieee802154_nl_assoc_indic(struct net_device *dev, |
| 43 | struct ieee802154_addr *addr, u8 cap) | 63 | struct ieee802154_addr *addr, u8 cap) |
| 44 | { | 64 | { |
| @@ -46,7 +66,7 @@ int ieee802154_nl_assoc_indic(struct net_device *dev, | |||
| 46 | 66 | ||
| 47 | pr_debug("%s\n", __func__); | 67 | pr_debug("%s\n", __func__); |
| 48 | 68 | ||
| 49 | if (addr->addr_type != IEEE802154_ADDR_LONG) { | 69 | if (addr->mode != IEEE802154_ADDR_LONG) { |
| 50 | pr_err("%s: received non-long source address!\n", __func__); | 70 | pr_err("%s: received non-long source address!\n", __func__); |
| 51 | return -EINVAL; | 71 | return -EINVAL; |
| 52 | } | 72 | } |
| @@ -59,8 +79,8 @@ int ieee802154_nl_assoc_indic(struct net_device *dev, | |||
| 59 | nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || | 79 | nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || |
| 60 | nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, | 80 | nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, |
| 61 | dev->dev_addr) || | 81 | dev->dev_addr) || |
| 62 | nla_put(msg, IEEE802154_ATTR_SRC_HW_ADDR, IEEE802154_ADDR_LEN, | 82 | nla_put_hwaddr(msg, IEEE802154_ATTR_SRC_HW_ADDR, |
| 63 | addr->hwaddr) || | 83 | addr->extended_addr) || |
| 64 | nla_put_u8(msg, IEEE802154_ATTR_CAPABILITY, cap)) | 84 | nla_put_u8(msg, IEEE802154_ATTR_CAPABILITY, cap)) |
| 65 | goto nla_put_failure; | 85 | goto nla_put_failure; |
| 66 | 86 | ||
| @@ -72,7 +92,7 @@ nla_put_failure: | |||
| 72 | } | 92 | } |
| 73 | EXPORT_SYMBOL(ieee802154_nl_assoc_indic); | 93 | EXPORT_SYMBOL(ieee802154_nl_assoc_indic); |
| 74 | 94 | ||
| 75 | int ieee802154_nl_assoc_confirm(struct net_device *dev, u16 short_addr, | 95 | int ieee802154_nl_assoc_confirm(struct net_device *dev, __le16 short_addr, |
| 76 | u8 status) | 96 | u8 status) |
| 77 | { | 97 | { |
| 78 | struct sk_buff *msg; | 98 | struct sk_buff *msg; |
| @@ -87,7 +107,7 @@ int ieee802154_nl_assoc_confirm(struct net_device *dev, u16 short_addr, | |||
| 87 | nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || | 107 | nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || |
| 88 | nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, | 108 | nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, |
| 89 | dev->dev_addr) || | 109 | dev->dev_addr) || |
| 90 | nla_put_u16(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr) || | 110 | nla_put_shortaddr(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr) || |
| 91 | nla_put_u8(msg, IEEE802154_ATTR_STATUS, status)) | 111 | nla_put_u8(msg, IEEE802154_ATTR_STATUS, status)) |
| 92 | goto nla_put_failure; | 112 | goto nla_put_failure; |
| 93 | return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP); | 113 | return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP); |
| @@ -114,13 +134,13 @@ int ieee802154_nl_disassoc_indic(struct net_device *dev, | |||
| 114 | nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, | 134 | nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, |
| 115 | dev->dev_addr)) | 135 | dev->dev_addr)) |
| 116 | goto nla_put_failure; | 136 | goto nla_put_failure; |
| 117 | if (addr->addr_type == IEEE802154_ADDR_LONG) { | 137 | if (addr->mode == IEEE802154_ADDR_LONG) { |
| 118 | if (nla_put(msg, IEEE802154_ATTR_SRC_HW_ADDR, IEEE802154_ADDR_LEN, | 138 | if (nla_put_hwaddr(msg, IEEE802154_ATTR_SRC_HW_ADDR, |
| 119 | addr->hwaddr)) | 139 | addr->extended_addr)) |
| 120 | goto nla_put_failure; | 140 | goto nla_put_failure; |
| 121 | } else { | 141 | } else { |
| 122 | if (nla_put_u16(msg, IEEE802154_ATTR_SRC_SHORT_ADDR, | 142 | if (nla_put_shortaddr(msg, IEEE802154_ATTR_SRC_SHORT_ADDR, |
| 123 | addr->short_addr)) | 143 | addr->short_addr)) |
| 124 | goto nla_put_failure; | 144 | goto nla_put_failure; |
| 125 | } | 145 | } |
| 126 | if (nla_put_u8(msg, IEEE802154_ATTR_REASON, reason)) | 146 | if (nla_put_u8(msg, IEEE802154_ATTR_REASON, reason)) |
| @@ -157,8 +177,8 @@ nla_put_failure: | |||
| 157 | } | 177 | } |
| 158 | EXPORT_SYMBOL(ieee802154_nl_disassoc_confirm); | 178 | EXPORT_SYMBOL(ieee802154_nl_disassoc_confirm); |
| 159 | 179 | ||
| 160 | int ieee802154_nl_beacon_indic(struct net_device *dev, | 180 | int ieee802154_nl_beacon_indic(struct net_device *dev, __le16 panid, |
| 161 | u16 panid, u16 coord_addr) | 181 | __le16 coord_addr) |
| 162 | { | 182 | { |
| 163 | struct sk_buff *msg; | 183 | struct sk_buff *msg; |
| 164 | 184 | ||
| @@ -172,8 +192,9 @@ int ieee802154_nl_beacon_indic(struct net_device *dev, | |||
| 172 | nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || | 192 | nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || |
| 173 | nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, | 193 | nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, |
| 174 | dev->dev_addr) || | 194 | dev->dev_addr) || |
| 175 | nla_put_u16(msg, IEEE802154_ATTR_COORD_SHORT_ADDR, coord_addr) || | 195 | nla_put_shortaddr(msg, IEEE802154_ATTR_COORD_SHORT_ADDR, |
| 176 | nla_put_u16(msg, IEEE802154_ATTR_COORD_PAN_ID, panid)) | 196 | coord_addr) || |
| 197 | nla_put_shortaddr(msg, IEEE802154_ATTR_COORD_PAN_ID, panid)) | ||
| 177 | goto nla_put_failure; | 198 | goto nla_put_failure; |
| 178 | return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP); | 199 | return ieee802154_nl_mcast(msg, IEEE802154_COORD_MCGRP); |
| 179 | 200 | ||
| @@ -243,6 +264,8 @@ static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 portid, | |||
| 243 | { | 264 | { |
| 244 | void *hdr; | 265 | void *hdr; |
| 245 | struct wpan_phy *phy; | 266 | struct wpan_phy *phy; |
| 267 | struct ieee802154_mlme_ops *ops; | ||
| 268 | __le16 short_addr, pan_id; | ||
| 246 | 269 | ||
| 247 | pr_debug("%s\n", __func__); | 270 | pr_debug("%s\n", __func__); |
| 248 | 271 | ||
| @@ -251,19 +274,45 @@ static int ieee802154_nl_fill_iface(struct sk_buff *msg, u32 portid, | |||
| 251 | if (!hdr) | 274 | if (!hdr) |
| 252 | goto out; | 275 | goto out; |
| 253 | 276 | ||
| 254 | phy = ieee802154_mlme_ops(dev)->get_phy(dev); | 277 | ops = ieee802154_mlme_ops(dev); |
| 278 | phy = ops->get_phy(dev); | ||
| 255 | BUG_ON(!phy); | 279 | BUG_ON(!phy); |
| 256 | 280 | ||
| 281 | short_addr = ops->get_short_addr(dev); | ||
| 282 | pan_id = ops->get_pan_id(dev); | ||
| 283 | |||
| 257 | if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || | 284 | if (nla_put_string(msg, IEEE802154_ATTR_DEV_NAME, dev->name) || |
| 258 | nla_put_string(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)) || | 285 | nla_put_string(msg, IEEE802154_ATTR_PHY_NAME, wpan_phy_name(phy)) || |
| 259 | nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || | 286 | nla_put_u32(msg, IEEE802154_ATTR_DEV_INDEX, dev->ifindex) || |
| 260 | nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, | 287 | nla_put(msg, IEEE802154_ATTR_HW_ADDR, IEEE802154_ADDR_LEN, |
| 261 | dev->dev_addr) || | 288 | dev->dev_addr) || |
| 262 | nla_put_u16(msg, IEEE802154_ATTR_SHORT_ADDR, | 289 | nla_put_shortaddr(msg, IEEE802154_ATTR_SHORT_ADDR, short_addr) || |
| 263 | ieee802154_mlme_ops(dev)->get_short_addr(dev)) || | 290 | nla_put_shortaddr(msg, IEEE802154_ATTR_PAN_ID, pan_id)) |
| 264 | nla_put_u16(msg, IEEE802154_ATTR_PAN_ID, | ||
| 265 | ieee802154_mlme_ops(dev)->get_pan_id(dev))) | ||
| 266 | goto nla_put_failure; | 291 | goto nla_put_failure; |
| 292 | |||
| 293 | if (ops->get_mac_params) { | ||
| 294 | struct ieee802154_mac_params params; | ||
| 295 | |||
| 296 | ops->get_mac_params(dev, ¶ms); | ||
| 297 | |||
| 298 | if (nla_put_s8(msg, IEEE802154_ATTR_TXPOWER, | ||
| 299 | params.transmit_power) || | ||
| 300 | nla_put_u8(msg, IEEE802154_ATTR_LBT_ENABLED, params.lbt) || | ||
| 301 | nla_put_u8(msg, IEEE802154_ATTR_CCA_MODE, | ||
| 302 | params.cca_mode) || | ||
| 303 | nla_put_s32(msg, IEEE802154_ATTR_CCA_ED_LEVEL, | ||
| 304 | params.cca_ed_level) || | ||
| 305 | nla_put_u8(msg, IEEE802154_ATTR_CSMA_RETRIES, | ||
| 306 | params.csma_retries) || | ||
| 307 | nla_put_u8(msg, IEEE802154_ATTR_CSMA_MIN_BE, | ||
| 308 | params.min_be) || | ||
| 309 | nla_put_u8(msg, IEEE802154_ATTR_CSMA_MAX_BE, | ||
| 310 | params.max_be) || | ||
| 311 | nla_put_s8(msg, IEEE802154_ATTR_FRAME_RETRIES, | ||
| 312 | params.frame_retries)) | ||
| 313 | goto nla_put_failure; | ||
| 314 | } | ||
| 315 | |||
| 267 | wpan_phy_put(phy); | 316 | wpan_phy_put(phy); |
| 268 | return genlmsg_end(msg, hdr); | 317 | return genlmsg_end(msg, hdr); |
| 269 | 318 | ||
| @@ -322,16 +371,16 @@ int ieee802154_associate_req(struct sk_buff *skb, struct genl_info *info) | |||
| 322 | goto out; | 371 | goto out; |
| 323 | 372 | ||
| 324 | if (info->attrs[IEEE802154_ATTR_COORD_HW_ADDR]) { | 373 | if (info->attrs[IEEE802154_ATTR_COORD_HW_ADDR]) { |
| 325 | addr.addr_type = IEEE802154_ADDR_LONG; | 374 | addr.mode = IEEE802154_ADDR_LONG; |
| 326 | nla_memcpy(addr.hwaddr, | 375 | addr.extended_addr = nla_get_hwaddr( |
| 327 | info->attrs[IEEE802154_ATTR_COORD_HW_ADDR], | 376 | info->attrs[IEEE802154_ATTR_COORD_HW_ADDR]); |
| 328 | IEEE802154_ADDR_LEN); | ||
| 329 | } else { | 377 | } else { |
| 330 | addr.addr_type = IEEE802154_ADDR_SHORT; | 378 | addr.mode = IEEE802154_ADDR_SHORT; |
| 331 | addr.short_addr = nla_get_u16( | 379 | addr.short_addr = nla_get_shortaddr( |
| 332 | info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]); | 380 | info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]); |
| 333 | } | 381 | } |
| 334 | addr.pan_id = nla_get_u16(info->attrs[IEEE802154_ATTR_COORD_PAN_ID]); | 382 | addr.pan_id = nla_get_shortaddr( |
| 383 | info->attrs[IEEE802154_ATTR_COORD_PAN_ID]); | ||
| 335 | 384 | ||
| 336 | if (info->attrs[IEEE802154_ATTR_PAGE]) | 385 | if (info->attrs[IEEE802154_ATTR_PAGE]) |
| 337 | page = nla_get_u8(info->attrs[IEEE802154_ATTR_PAGE]); | 386 | page = nla_get_u8(info->attrs[IEEE802154_ATTR_PAGE]); |
| @@ -365,14 +414,13 @@ int ieee802154_associate_resp(struct sk_buff *skb, struct genl_info *info) | |||
| 365 | if (!ieee802154_mlme_ops(dev)->assoc_resp) | 414 | if (!ieee802154_mlme_ops(dev)->assoc_resp) |
| 366 | goto out; | 415 | goto out; |
| 367 | 416 | ||
| 368 | addr.addr_type = IEEE802154_ADDR_LONG; | 417 | addr.mode = IEEE802154_ADDR_LONG; |
| 369 | nla_memcpy(addr.hwaddr, info->attrs[IEEE802154_ATTR_DEST_HW_ADDR], | 418 | addr.extended_addr = nla_get_hwaddr( |
| 370 | IEEE802154_ADDR_LEN); | 419 | info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]); |
| 371 | addr.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); | 420 | addr.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); |
| 372 | 421 | ||
| 373 | |||
| 374 | ret = ieee802154_mlme_ops(dev)->assoc_resp(dev, &addr, | 422 | ret = ieee802154_mlme_ops(dev)->assoc_resp(dev, &addr, |
| 375 | nla_get_u16(info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]), | 423 | nla_get_shortaddr(info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]), |
| 376 | nla_get_u8(info->attrs[IEEE802154_ATTR_STATUS])); | 424 | nla_get_u8(info->attrs[IEEE802154_ATTR_STATUS])); |
| 377 | 425 | ||
| 378 | out: | 426 | out: |
| @@ -398,13 +446,12 @@ int ieee802154_disassociate_req(struct sk_buff *skb, struct genl_info *info) | |||
| 398 | goto out; | 446 | goto out; |
| 399 | 447 | ||
| 400 | if (info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]) { | 448 | if (info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]) { |
| 401 | addr.addr_type = IEEE802154_ADDR_LONG; | 449 | addr.mode = IEEE802154_ADDR_LONG; |
| 402 | nla_memcpy(addr.hwaddr, | 450 | addr.extended_addr = nla_get_hwaddr( |
| 403 | info->attrs[IEEE802154_ATTR_DEST_HW_ADDR], | 451 | info->attrs[IEEE802154_ATTR_DEST_HW_ADDR]); |
| 404 | IEEE802154_ADDR_LEN); | ||
| 405 | } else { | 452 | } else { |
| 406 | addr.addr_type = IEEE802154_ADDR_SHORT; | 453 | addr.mode = IEEE802154_ADDR_SHORT; |
| 407 | addr.short_addr = nla_get_u16( | 454 | addr.short_addr = nla_get_shortaddr( |
| 408 | info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]); | 455 | info->attrs[IEEE802154_ATTR_DEST_SHORT_ADDR]); |
| 409 | } | 456 | } |
| 410 | addr.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); | 457 | addr.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev); |
| @@ -449,10 +496,11 @@ int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info) | |||
| 449 | if (!ieee802154_mlme_ops(dev)->start_req) | 496 | if (!ieee802154_mlme_ops(dev)->start_req) |
| 450 | goto out; | 497 | goto out; |
| 451 | 498 | ||
| 452 | addr.addr_type = IEEE802154_ADDR_SHORT; | 499 | addr.mode = IEEE802154_ADDR_SHORT; |
| 453 | addr.short_addr = nla_get_u16( | 500 | addr.short_addr = nla_get_shortaddr( |
| 454 | info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]); | 501 | info->attrs[IEEE802154_ATTR_COORD_SHORT_ADDR]); |
| 455 | addr.pan_id = nla_get_u16(info->attrs[IEEE802154_ATTR_COORD_PAN_ID]); | 502 | addr.pan_id = nla_get_shortaddr( |
| 503 | info->attrs[IEEE802154_ATTR_COORD_PAN_ID]); | ||
| 456 | 504 | ||
| 457 | channel = nla_get_u8(info->attrs[IEEE802154_ATTR_CHANNEL]); | 505 | channel = nla_get_u8(info->attrs[IEEE802154_ATTR_CHANNEL]); |
| 458 | bcn_ord = nla_get_u8(info->attrs[IEEE802154_ATTR_BCN_ORD]); | 506 | bcn_ord = nla_get_u8(info->attrs[IEEE802154_ATTR_BCN_ORD]); |
| @@ -467,7 +515,7 @@ int ieee802154_start_req(struct sk_buff *skb, struct genl_info *info) | |||
| 467 | page = 0; | 515 | page = 0; |
| 468 | 516 | ||
| 469 | 517 | ||
| 470 | if (addr.short_addr == IEEE802154_ADDR_BROADCAST) { | 518 | if (addr.short_addr == cpu_to_le16(IEEE802154_ADDR_BROADCAST)) { |
| 471 | ieee802154_nl_start_confirm(dev, IEEE802154_NO_SHORT_ADDRESS); | 519 | ieee802154_nl_start_confirm(dev, IEEE802154_NO_SHORT_ADDRESS); |
| 472 | dev_put(dev); | 520 | dev_put(dev); |
| 473 | return -EINVAL; | 521 | return -EINVAL; |
| @@ -577,3 +625,93 @@ cont: | |||
| 577 | 625 | ||
| 578 | return skb->len; | 626 | return skb->len; |
| 579 | } | 627 | } |
| 628 | |||
| 629 | int ieee802154_set_macparams(struct sk_buff *skb, struct genl_info *info) | ||
| 630 | { | ||
| 631 | struct net_device *dev = NULL; | ||
| 632 | struct ieee802154_mlme_ops *ops; | ||
| 633 | struct ieee802154_mac_params params; | ||
| 634 | struct wpan_phy *phy; | ||
| 635 | int rc = -EINVAL; | ||
| 636 | |||
| 637 | pr_debug("%s\n", __func__); | ||
| 638 | |||
| 639 | dev = ieee802154_nl_get_dev(info); | ||
| 640 | if (!dev) | ||
| 641 | return -ENODEV; | ||
| 642 | |||
| 643 | ops = ieee802154_mlme_ops(dev); | ||
| 644 | |||
| 645 | if (!ops->get_mac_params || !ops->set_mac_params) { | ||
| 646 | rc = -EOPNOTSUPP; | ||
| 647 | goto out; | ||
| 648 | } | ||
| 649 | |||
| 650 | if (netif_running(dev)) { | ||
| 651 | rc = -EBUSY; | ||
| 652 | goto out; | ||
| 653 | } | ||
| 654 | |||
| 655 | if (!info->attrs[IEEE802154_ATTR_LBT_ENABLED] && | ||
| 656 | !info->attrs[IEEE802154_ATTR_CCA_MODE] && | ||
| 657 | !info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL] && | ||
| 658 | !info->attrs[IEEE802154_ATTR_CSMA_RETRIES] && | ||
| 659 | !info->attrs[IEEE802154_ATTR_CSMA_MIN_BE] && | ||
| 660 | !info->attrs[IEEE802154_ATTR_CSMA_MAX_BE] && | ||
| 661 | !info->attrs[IEEE802154_ATTR_FRAME_RETRIES]) | ||
| 662 | goto out; | ||
| 663 | |||
| 664 | phy = ops->get_phy(dev); | ||
| 665 | |||
| 666 | if ((!phy->set_lbt && info->attrs[IEEE802154_ATTR_LBT_ENABLED]) || | ||
| 667 | (!phy->set_cca_mode && info->attrs[IEEE802154_ATTR_CCA_MODE]) || | ||
| 668 | (!phy->set_cca_ed_level && | ||
| 669 | info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL]) || | ||
| 670 | (!phy->set_csma_params && | ||
| 671 | (info->attrs[IEEE802154_ATTR_CSMA_RETRIES] || | ||
| 672 | info->attrs[IEEE802154_ATTR_CSMA_MIN_BE] || | ||
| 673 | info->attrs[IEEE802154_ATTR_CSMA_MAX_BE])) || | ||
| 674 | (!phy->set_frame_retries && | ||
| 675 | info->attrs[IEEE802154_ATTR_FRAME_RETRIES])) { | ||
| 676 | rc = -EOPNOTSUPP; | ||
| 677 | goto out_phy; | ||
| 678 | } | ||
| 679 | |||
| 680 | ops->get_mac_params(dev, ¶ms); | ||
| 681 | |||
| 682 | if (info->attrs[IEEE802154_ATTR_TXPOWER]) | ||
| 683 | params.transmit_power = nla_get_s8(info->attrs[IEEE802154_ATTR_TXPOWER]); | ||
| 684 | |||
| 685 | if (info->attrs[IEEE802154_ATTR_LBT_ENABLED]) | ||
| 686 | params.lbt = nla_get_u8(info->attrs[IEEE802154_ATTR_LBT_ENABLED]); | ||
| 687 | |||
| 688 | if (info->attrs[IEEE802154_ATTR_CCA_MODE]) | ||
| 689 | params.cca_mode = nla_get_u8(info->attrs[IEEE802154_ATTR_CCA_MODE]); | ||
| 690 | |||
| 691 | if (info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL]) | ||
| 692 | params.cca_ed_level = nla_get_s32(info->attrs[IEEE802154_ATTR_CCA_ED_LEVEL]); | ||
| 693 | |||
| 694 | if (info->attrs[IEEE802154_ATTR_CSMA_RETRIES]) | ||
| 695 | params.csma_retries = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_RETRIES]); | ||
| 696 | |||
| 697 | if (info->attrs[IEEE802154_ATTR_CSMA_MIN_BE]) | ||
| 698 | params.min_be = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_MIN_BE]); | ||
| 699 | |||
| 700 | if (info->attrs[IEEE802154_ATTR_CSMA_MAX_BE]) | ||
| 701 | params.max_be = nla_get_u8(info->attrs[IEEE802154_ATTR_CSMA_MAX_BE]); | ||
| 702 | |||
| 703 | if (info->attrs[IEEE802154_ATTR_FRAME_RETRIES]) | ||
| 704 | params.frame_retries = nla_get_s8(info->attrs[IEEE802154_ATTR_FRAME_RETRIES]); | ||
| 705 | |||
| 706 | rc = ops->set_mac_params(dev, ¶ms); | ||
| 707 | |||
| 708 | wpan_phy_put(phy); | ||
| 709 | dev_put(dev); | ||
| 710 | return rc; | ||
| 711 | |||
| 712 | out_phy: | ||
| 713 | wpan_phy_put(phy); | ||
| 714 | out: | ||
| 715 | dev_put(dev); | ||
| 716 | return rc; | ||
| 717 | } | ||
diff --git a/net/ieee802154/nl_policy.c b/net/ieee802154/nl_policy.c index 6adda4d46f95..fd7be5e45cef 100644 --- a/net/ieee802154/nl_policy.c +++ b/net/ieee802154/nl_policy.c | |||
| @@ -52,5 +52,15 @@ const struct nla_policy ieee802154_policy[IEEE802154_ATTR_MAX + 1] = { | |||
| 52 | [IEEE802154_ATTR_DURATION] = { .type = NLA_U8, }, | 52 | [IEEE802154_ATTR_DURATION] = { .type = NLA_U8, }, |
| 53 | [IEEE802154_ATTR_ED_LIST] = { .len = 27 }, | 53 | [IEEE802154_ATTR_ED_LIST] = { .len = 27 }, |
| 54 | [IEEE802154_ATTR_CHANNEL_PAGE_LIST] = { .len = 32 * 4, }, | 54 | [IEEE802154_ATTR_CHANNEL_PAGE_LIST] = { .len = 32 * 4, }, |
| 55 | |||
| 56 | [IEEE802154_ATTR_TXPOWER] = { .type = NLA_S8, }, | ||
| 57 | [IEEE802154_ATTR_LBT_ENABLED] = { .type = NLA_U8, }, | ||
| 58 | [IEEE802154_ATTR_CCA_MODE] = { .type = NLA_U8, }, | ||
| 59 | [IEEE802154_ATTR_CCA_ED_LEVEL] = { .type = NLA_S32, }, | ||
| 60 | [IEEE802154_ATTR_CSMA_RETRIES] = { .type = NLA_U8, }, | ||
| 61 | [IEEE802154_ATTR_CSMA_MIN_BE] = { .type = NLA_U8, }, | ||
| 62 | [IEEE802154_ATTR_CSMA_MAX_BE] = { .type = NLA_U8, }, | ||
| 63 | |||
| 64 | [IEEE802154_ATTR_FRAME_RETRIES] = { .type = NLA_S8, }, | ||
| 55 | }; | 65 | }; |
| 56 | 66 | ||
diff --git a/net/ieee802154/raw.c b/net/ieee802154/raw.c index 41f538b8e59c..74d54fae33d7 100644 --- a/net/ieee802154/raw.c +++ b/net/ieee802154/raw.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
| 29 | #include <net/sock.h> | 29 | #include <net/sock.h> |
| 30 | #include <net/af_ieee802154.h> | 30 | #include <net/af_ieee802154.h> |
| 31 | #include <net/ieee802154_netdev.h> | ||
| 31 | 32 | ||
| 32 | #include "af802154.h" | 33 | #include "af802154.h" |
| 33 | 34 | ||
| @@ -55,21 +56,24 @@ static void raw_close(struct sock *sk, long timeout) | |||
| 55 | sk_common_release(sk); | 56 | sk_common_release(sk); |
| 56 | } | 57 | } |
| 57 | 58 | ||
| 58 | static int raw_bind(struct sock *sk, struct sockaddr *uaddr, int len) | 59 | static int raw_bind(struct sock *sk, struct sockaddr *_uaddr, int len) |
| 59 | { | 60 | { |
| 60 | struct sockaddr_ieee802154 *addr = (struct sockaddr_ieee802154 *)uaddr; | 61 | struct ieee802154_addr addr; |
| 62 | struct sockaddr_ieee802154 *uaddr = (struct sockaddr_ieee802154 *)_uaddr; | ||
| 61 | int err = 0; | 63 | int err = 0; |
| 62 | struct net_device *dev = NULL; | 64 | struct net_device *dev = NULL; |
| 63 | 65 | ||
| 64 | if (len < sizeof(*addr)) | 66 | if (len < sizeof(*uaddr)) |
| 65 | return -EINVAL; | 67 | return -EINVAL; |
| 66 | 68 | ||
| 67 | if (addr->family != AF_IEEE802154) | 69 | uaddr = (struct sockaddr_ieee802154 *)_uaddr; |
| 70 | if (uaddr->family != AF_IEEE802154) | ||
| 68 | return -EINVAL; | 71 | return -EINVAL; |
| 69 | 72 | ||
| 70 | lock_sock(sk); | 73 | lock_sock(sk); |
| 71 | 74 | ||
| 72 | dev = ieee802154_get_dev(sock_net(sk), &addr->addr); | 75 | ieee802154_addr_from_sa(&addr, &uaddr->addr); |
| 76 | dev = ieee802154_get_dev(sock_net(sk), &addr); | ||
| 73 | if (!dev) { | 77 | if (!dev) { |
| 74 | err = -ENODEV; | 78 | err = -ENODEV; |
| 75 | goto out; | 79 | goto out; |
| @@ -209,6 +213,10 @@ out: | |||
| 209 | 213 | ||
| 210 | static int raw_rcv_skb(struct sock *sk, struct sk_buff *skb) | 214 | static int raw_rcv_skb(struct sock *sk, struct sk_buff *skb) |
| 211 | { | 215 | { |
| 216 | skb = skb_share_check(skb, GFP_ATOMIC); | ||
| 217 | if (!skb) | ||
| 218 | return NET_RX_DROP; | ||
| 219 | |||
| 212 | if (sock_queue_rcv_skb(sk, skb) < 0) { | 220 | if (sock_queue_rcv_skb(sk, skb) < 0) { |
| 213 | kfree_skb(skb); | 221 | kfree_skb(skb); |
| 214 | return NET_RX_DROP; | 222 | return NET_RX_DROP; |
diff --git a/net/ieee802154/reassembly.c b/net/ieee802154/reassembly.c new file mode 100644 index 000000000000..ef2d54372b13 --- /dev/null +++ b/net/ieee802154/reassembly.c | |||
| @@ -0,0 +1,571 @@ | |||
| 1 | /* 6LoWPAN fragment reassembly | ||
| 2 | * | ||
| 3 | * | ||
| 4 | * Authors: | ||
| 5 | * Alexander Aring <aar@pengutronix.de> | ||
| 6 | * | ||
| 7 | * Based on: net/ipv6/reassembly.c | ||
| 8 | * | ||
| 9 | * This program is free software; you can redistribute it and/or | ||
| 10 | * modify it under the terms of the GNU General Public License | ||
| 11 | * as published by the Free Software Foundation; either version | ||
| 12 | * 2 of the License, or (at your option) any later version. | ||
| 13 | */ | ||
| 14 | |||
| 15 | #define pr_fmt(fmt) "6LoWPAN: " fmt | ||
| 16 | |||
| 17 | #include <linux/net.h> | ||
| 18 | #include <linux/list.h> | ||
| 19 | #include <linux/netdevice.h> | ||
| 20 | #include <linux/random.h> | ||
| 21 | #include <linux/jhash.h> | ||
| 22 | #include <linux/skbuff.h> | ||
| 23 | #include <linux/slab.h> | ||
| 24 | #include <linux/export.h> | ||
| 25 | |||
| 26 | #include <net/ieee802154_netdev.h> | ||
| 27 | #include <net/6lowpan.h> | ||
| 28 | #include <net/ipv6.h> | ||
| 29 | #include <net/inet_frag.h> | ||
| 30 | |||
| 31 | #include "reassembly.h" | ||
| 32 | |||
| 33 | struct lowpan_frag_info { | ||
| 34 | __be16 d_tag; | ||
| 35 | u16 d_size; | ||
| 36 | u8 d_offset; | ||
| 37 | }; | ||
| 38 | |||
| 39 | struct lowpan_frag_info *lowpan_cb(struct sk_buff *skb) | ||
| 40 | { | ||
| 41 | return (struct lowpan_frag_info *)skb->cb; | ||
| 42 | } | ||
| 43 | |||
| 44 | static struct inet_frags lowpan_frags; | ||
| 45 | |||
| 46 | static int lowpan_frag_reasm(struct lowpan_frag_queue *fq, | ||
| 47 | struct sk_buff *prev, struct net_device *dev); | ||
| 48 | |||
| 49 | static unsigned int lowpan_hash_frag(__be16 tag, u16 d_size, | ||
| 50 | const struct ieee802154_addr *saddr, | ||
| 51 | const struct ieee802154_addr *daddr) | ||
| 52 | { | ||
| 53 | u32 c; | ||
| 54 | |||
| 55 | net_get_random_once(&lowpan_frags.rnd, sizeof(lowpan_frags.rnd)); | ||
| 56 | c = jhash_3words(ieee802154_addr_hash(saddr), | ||
| 57 | ieee802154_addr_hash(daddr), | ||
| 58 | (__force u32)(tag + (d_size << 16)), | ||
| 59 | lowpan_frags.rnd); | ||
| 60 | |||
| 61 | return c & (INETFRAGS_HASHSZ - 1); | ||
| 62 | } | ||
| 63 | |||
| 64 | static unsigned int lowpan_hashfn(struct inet_frag_queue *q) | ||
| 65 | { | ||
| 66 | struct lowpan_frag_queue *fq; | ||
| 67 | |||
| 68 | fq = container_of(q, struct lowpan_frag_queue, q); | ||
| 69 | return lowpan_hash_frag(fq->tag, fq->d_size, &fq->saddr, &fq->daddr); | ||
| 70 | } | ||
| 71 | |||
| 72 | static bool lowpan_frag_match(struct inet_frag_queue *q, void *a) | ||
| 73 | { | ||
| 74 | struct lowpan_frag_queue *fq; | ||
| 75 | struct lowpan_create_arg *arg = a; | ||
| 76 | |||
| 77 | fq = container_of(q, struct lowpan_frag_queue, q); | ||
| 78 | return fq->tag == arg->tag && fq->d_size == arg->d_size && | ||
| 79 | ieee802154_addr_equal(&fq->saddr, arg->src) && | ||
| 80 | ieee802154_addr_equal(&fq->daddr, arg->dst); | ||
| 81 | } | ||
| 82 | |||
| 83 | static void lowpan_frag_init(struct inet_frag_queue *q, void *a) | ||
| 84 | { | ||
| 85 | struct lowpan_frag_queue *fq; | ||
| 86 | struct lowpan_create_arg *arg = a; | ||
| 87 | |||
| 88 | fq = container_of(q, struct lowpan_frag_queue, q); | ||
| 89 | |||
| 90 | fq->tag = arg->tag; | ||
| 91 | fq->d_size = arg->d_size; | ||
| 92 | fq->saddr = *arg->src; | ||
| 93 | fq->daddr = *arg->dst; | ||
| 94 | } | ||
| 95 | |||
| 96 | static void lowpan_frag_expire(unsigned long data) | ||
| 97 | { | ||
| 98 | struct frag_queue *fq; | ||
| 99 | struct net *net; | ||
| 100 | |||
| 101 | fq = container_of((struct inet_frag_queue *)data, struct frag_queue, q); | ||
| 102 | net = container_of(fq->q.net, struct net, ieee802154_lowpan.frags); | ||
| 103 | |||
| 104 | spin_lock(&fq->q.lock); | ||
| 105 | |||
| 106 | if (fq->q.last_in & INET_FRAG_COMPLETE) | ||
| 107 | goto out; | ||
| 108 | |||
| 109 | inet_frag_kill(&fq->q, &lowpan_frags); | ||
| 110 | out: | ||
| 111 | spin_unlock(&fq->q.lock); | ||
| 112 | inet_frag_put(&fq->q, &lowpan_frags); | ||
| 113 | } | ||
| 114 | |||
| 115 | static inline struct lowpan_frag_queue * | ||
| 116 | fq_find(struct net *net, const struct lowpan_frag_info *frag_info, | ||
| 117 | const struct ieee802154_addr *src, | ||
| 118 | const struct ieee802154_addr *dst) | ||
| 119 | { | ||
| 120 | struct inet_frag_queue *q; | ||
| 121 | struct lowpan_create_arg arg; | ||
| 122 | unsigned int hash; | ||
| 123 | |||
| 124 | arg.tag = frag_info->d_tag; | ||
| 125 | arg.d_size = frag_info->d_size; | ||
| 126 | arg.src = src; | ||
| 127 | arg.dst = dst; | ||
| 128 | |||
| 129 | read_lock(&lowpan_frags.lock); | ||
| 130 | hash = lowpan_hash_frag(frag_info->d_tag, frag_info->d_size, src, dst); | ||
| 131 | |||
| 132 | q = inet_frag_find(&net->ieee802154_lowpan.frags, | ||
| 133 | &lowpan_frags, &arg, hash); | ||
| 134 | if (IS_ERR_OR_NULL(q)) { | ||
| 135 | inet_frag_maybe_warn_overflow(q, pr_fmt()); | ||
| 136 | return NULL; | ||
| 137 | } | ||
| 138 | return container_of(q, struct lowpan_frag_queue, q); | ||
| 139 | } | ||
| 140 | |||
| 141 | static int lowpan_frag_queue(struct lowpan_frag_queue *fq, | ||
| 142 | struct sk_buff *skb, const u8 frag_type) | ||
| 143 | { | ||
| 144 | struct sk_buff *prev, *next; | ||
| 145 | struct net_device *dev; | ||
| 146 | int end, offset; | ||
| 147 | |||
| 148 | if (fq->q.last_in & INET_FRAG_COMPLETE) | ||
| 149 | goto err; | ||
| 150 | |||
| 151 | offset = lowpan_cb(skb)->d_offset << 3; | ||
| 152 | end = lowpan_cb(skb)->d_size; | ||
| 153 | |||
| 154 | /* Is this the final fragment? */ | ||
| 155 | if (offset + skb->len == end) { | ||
| 156 | /* If we already have some bits beyond end | ||
| 157 | * or have different end, the segment is corrupted. | ||
| 158 | */ | ||
| 159 | if (end < fq->q.len || | ||
| 160 | ((fq->q.last_in & INET_FRAG_LAST_IN) && end != fq->q.len)) | ||
| 161 | goto err; | ||
| 162 | fq->q.last_in |= INET_FRAG_LAST_IN; | ||
| 163 | fq->q.len = end; | ||
| 164 | } else { | ||
| 165 | if (end > fq->q.len) { | ||
| 166 | /* Some bits beyond end -> corruption. */ | ||
| 167 | if (fq->q.last_in & INET_FRAG_LAST_IN) | ||
| 168 | goto err; | ||
| 169 | fq->q.len = end; | ||
| 170 | } | ||
| 171 | } | ||
| 172 | |||
| 173 | /* Find out which fragments are in front and at the back of us | ||
| 174 | * in the chain of fragments so far. We must know where to put | ||
| 175 | * this fragment, right? | ||
| 176 | */ | ||
| 177 | prev = fq->q.fragments_tail; | ||
| 178 | if (!prev || lowpan_cb(prev)->d_offset < lowpan_cb(skb)->d_offset) { | ||
| 179 | next = NULL; | ||
| 180 | goto found; | ||
| 181 | } | ||
| 182 | prev = NULL; | ||
| 183 | for (next = fq->q.fragments; next != NULL; next = next->next) { | ||
| 184 | if (lowpan_cb(next)->d_offset >= lowpan_cb(skb)->d_offset) | ||
| 185 | break; /* bingo! */ | ||
| 186 | prev = next; | ||
| 187 | } | ||
| 188 | |||
| 189 | found: | ||
| 190 | /* Insert this fragment in the chain of fragments. */ | ||
| 191 | skb->next = next; | ||
| 192 | if (!next) | ||
| 193 | fq->q.fragments_tail = skb; | ||
| 194 | if (prev) | ||
| 195 | prev->next = skb; | ||
| 196 | else | ||
| 197 | fq->q.fragments = skb; | ||
| 198 | |||
| 199 | dev = skb->dev; | ||
| 200 | if (dev) | ||
| 201 | skb->dev = NULL; | ||
| 202 | |||
| 203 | fq->q.stamp = skb->tstamp; | ||
| 204 | if (frag_type == LOWPAN_DISPATCH_FRAG1) { | ||
| 205 | /* Calculate uncomp. 6lowpan header to estimate full size */ | ||
| 206 | fq->q.meat += lowpan_uncompress_size(skb, NULL); | ||
| 207 | fq->q.last_in |= INET_FRAG_FIRST_IN; | ||
| 208 | } else { | ||
| 209 | fq->q.meat += skb->len; | ||
| 210 | } | ||
| 211 | add_frag_mem_limit(&fq->q, skb->truesize); | ||
| 212 | |||
| 213 | if (fq->q.last_in == (INET_FRAG_FIRST_IN | INET_FRAG_LAST_IN) && | ||
| 214 | fq->q.meat == fq->q.len) { | ||
| 215 | int res; | ||
| 216 | unsigned long orefdst = skb->_skb_refdst; | ||
| 217 | |||
| 218 | skb->_skb_refdst = 0UL; | ||
| 219 | res = lowpan_frag_reasm(fq, prev, dev); | ||
| 220 | skb->_skb_refdst = orefdst; | ||
| 221 | return res; | ||
| 222 | } | ||
| 223 | |||
| 224 | inet_frag_lru_move(&fq->q); | ||
| 225 | return -1; | ||
| 226 | err: | ||
| 227 | kfree_skb(skb); | ||
| 228 | return -1; | ||
| 229 | } | ||
| 230 | |||
| 231 | /* Check if this packet is complete. | ||
| 232 | * Returns NULL on failure by any reason, and pointer | ||
| 233 | * to current nexthdr field in reassembled frame. | ||
| 234 | * | ||
| 235 | * It is called with locked fq, and caller must check that | ||
| 236 | * queue is eligible for reassembly i.e. it is not COMPLETE, | ||
| 237 | * the last and the first frames arrived and all the bits are here. | ||
| 238 | */ | ||
| 239 | static int lowpan_frag_reasm(struct lowpan_frag_queue *fq, struct sk_buff *prev, | ||
| 240 | struct net_device *dev) | ||
| 241 | { | ||
| 242 | struct sk_buff *fp, *head = fq->q.fragments; | ||
| 243 | int sum_truesize; | ||
| 244 | |||
| 245 | inet_frag_kill(&fq->q, &lowpan_frags); | ||
| 246 | |||
| 247 | /* Make the one we just received the head. */ | ||
| 248 | if (prev) { | ||
| 249 | head = prev->next; | ||
| 250 | fp = skb_clone(head, GFP_ATOMIC); | ||
| 251 | |||
| 252 | if (!fp) | ||
| 253 | goto out_oom; | ||
| 254 | |||
| 255 | fp->next = head->next; | ||
| 256 | if (!fp->next) | ||
| 257 | fq->q.fragments_tail = fp; | ||
| 258 | prev->next = fp; | ||
| 259 | |||
| 260 | skb_morph(head, fq->q.fragments); | ||
| 261 | head->next = fq->q.fragments->next; | ||
| 262 | |||
| 263 | consume_skb(fq->q.fragments); | ||
| 264 | fq->q.fragments = head; | ||
| 265 | } | ||
| 266 | |||
| 267 | /* Head of list must not be cloned. */ | ||
| 268 | if (skb_unclone(head, GFP_ATOMIC)) | ||
| 269 | goto out_oom; | ||
| 270 | |||
| 271 | /* If the first fragment is fragmented itself, we split | ||
| 272 | * it to two chunks: the first with data and paged part | ||
| 273 | * and the second, holding only fragments. | ||
| 274 | */ | ||
| 275 | if (skb_has_frag_list(head)) { | ||
| 276 | struct sk_buff *clone; | ||
| 277 | int i, plen = 0; | ||
| 278 | |||
| 279 | clone = alloc_skb(0, GFP_ATOMIC); | ||
| 280 | if (!clone) | ||
| 281 | goto out_oom; | ||
| 282 | clone->next = head->next; | ||
| 283 | head->next = clone; | ||
| 284 | skb_shinfo(clone)->frag_list = skb_shinfo(head)->frag_list; | ||
| 285 | skb_frag_list_init(head); | ||
| 286 | for (i = 0; i < skb_shinfo(head)->nr_frags; i++) | ||
| 287 | plen += skb_frag_size(&skb_shinfo(head)->frags[i]); | ||
| 288 | clone->len = head->data_len - plen; | ||
| 289 | clone->data_len = clone->len; | ||
| 290 | head->data_len -= clone->len; | ||
| 291 | head->len -= clone->len; | ||
| 292 | add_frag_mem_limit(&fq->q, clone->truesize); | ||
| 293 | } | ||
| 294 | |||
| 295 | WARN_ON(head == NULL); | ||
| 296 | |||
| 297 | sum_truesize = head->truesize; | ||
| 298 | for (fp = head->next; fp;) { | ||
| 299 | bool headstolen; | ||
| 300 | int delta; | ||
| 301 | struct sk_buff *next = fp->next; | ||
| 302 | |||
| 303 | sum_truesize += fp->truesize; | ||
| 304 | if (skb_try_coalesce(head, fp, &headstolen, &delta)) { | ||
| 305 | kfree_skb_partial(fp, headstolen); | ||
| 306 | } else { | ||
| 307 | if (!skb_shinfo(head)->frag_list) | ||
| 308 | skb_shinfo(head)->frag_list = fp; | ||
| 309 | head->data_len += fp->len; | ||
| 310 | head->len += fp->len; | ||
| 311 | head->truesize += fp->truesize; | ||
| 312 | } | ||
| 313 | fp = next; | ||
| 314 | } | ||
| 315 | sub_frag_mem_limit(&fq->q, sum_truesize); | ||
| 316 | |||
| 317 | head->next = NULL; | ||
| 318 | head->dev = dev; | ||
| 319 | head->tstamp = fq->q.stamp; | ||
| 320 | |||
| 321 | fq->q.fragments = NULL; | ||
| 322 | fq->q.fragments_tail = NULL; | ||
| 323 | |||
| 324 | return 1; | ||
| 325 | out_oom: | ||
| 326 | net_dbg_ratelimited("lowpan_frag_reasm: no memory for reassembly\n"); | ||
| 327 | return -1; | ||
| 328 | } | ||
| 329 | |||
| 330 | static int lowpan_get_frag_info(struct sk_buff *skb, const u8 frag_type, | ||
| 331 | struct lowpan_frag_info *frag_info) | ||
| 332 | { | ||
| 333 | bool fail; | ||
| 334 | u8 pattern = 0, low = 0; | ||
| 335 | |||
| 336 | fail = lowpan_fetch_skb(skb, &pattern, 1); | ||
| 337 | fail |= lowpan_fetch_skb(skb, &low, 1); | ||
| 338 | frag_info->d_size = (pattern & 7) << 8 | low; | ||
| 339 | fail |= lowpan_fetch_skb(skb, &frag_info->d_tag, 2); | ||
| 340 | |||
| 341 | if (frag_type == LOWPAN_DISPATCH_FRAGN) { | ||
| 342 | fail |= lowpan_fetch_skb(skb, &frag_info->d_offset, 1); | ||
| 343 | } else { | ||
| 344 | skb_reset_network_header(skb); | ||
| 345 | frag_info->d_offset = 0; | ||
| 346 | } | ||
| 347 | |||
| 348 | if (unlikely(fail)) | ||
| 349 | return -EIO; | ||
| 350 | |||
| 351 | return 0; | ||
| 352 | } | ||
| 353 | |||
| 354 | int lowpan_frag_rcv(struct sk_buff *skb, const u8 frag_type) | ||
| 355 | { | ||
| 356 | struct lowpan_frag_queue *fq; | ||
| 357 | struct net *net = dev_net(skb->dev); | ||
| 358 | struct lowpan_frag_info *frag_info = lowpan_cb(skb); | ||
| 359 | struct ieee802154_addr source, dest; | ||
| 360 | int err; | ||
| 361 | |||
| 362 | source = mac_cb(skb)->source; | ||
| 363 | dest = mac_cb(skb)->dest; | ||
| 364 | |||
| 365 | err = lowpan_get_frag_info(skb, frag_type, frag_info); | ||
| 366 | if (err < 0) | ||
| 367 | goto err; | ||
| 368 | |||
| 369 | if (frag_info->d_size > net->ieee802154_lowpan.max_dsize) | ||
| 370 | goto err; | ||
| 371 | |||
| 372 | inet_frag_evictor(&net->ieee802154_lowpan.frags, &lowpan_frags, false); | ||
| 373 | |||
| 374 | fq = fq_find(net, frag_info, &source, &dest); | ||
| 375 | if (fq != NULL) { | ||
| 376 | int ret; | ||
| 377 | spin_lock(&fq->q.lock); | ||
| 378 | ret = lowpan_frag_queue(fq, skb, frag_type); | ||
| 379 | spin_unlock(&fq->q.lock); | ||
| 380 | |||
| 381 | inet_frag_put(&fq->q, &lowpan_frags); | ||
| 382 | return ret; | ||
| 383 | } | ||
| 384 | |||
| 385 | err: | ||
| 386 | kfree_skb(skb); | ||
| 387 | return -1; | ||
| 388 | } | ||
| 389 | EXPORT_SYMBOL(lowpan_frag_rcv); | ||
| 390 | |||
| 391 | #ifdef CONFIG_SYSCTL | ||
| 392 | static struct ctl_table lowpan_frags_ns_ctl_table[] = { | ||
| 393 | { | ||
| 394 | .procname = "6lowpanfrag_high_thresh", | ||
| 395 | .data = &init_net.ieee802154_lowpan.frags.high_thresh, | ||
| 396 | .maxlen = sizeof(int), | ||
| 397 | .mode = 0644, | ||
| 398 | .proc_handler = proc_dointvec | ||
| 399 | }, | ||
| 400 | { | ||
| 401 | .procname = "6lowpanfrag_low_thresh", | ||
| 402 | .data = &init_net.ieee802154_lowpan.frags.low_thresh, | ||
| 403 | .maxlen = sizeof(int), | ||
| 404 | .mode = 0644, | ||
| 405 | .proc_handler = proc_dointvec | ||
| 406 | }, | ||
| 407 | { | ||
| 408 | .procname = "6lowpanfrag_time", | ||
| 409 | .data = &init_net.ieee802154_lowpan.frags.timeout, | ||
| 410 | .maxlen = sizeof(int), | ||
| 411 | .mode = 0644, | ||
| 412 | .proc_handler = proc_dointvec_jiffies, | ||
| 413 | }, | ||
| 414 | { | ||
| 415 | .procname = "6lowpanfrag_max_datagram_size", | ||
| 416 | .data = &init_net.ieee802154_lowpan.max_dsize, | ||
| 417 | .maxlen = sizeof(int), | ||
| 418 | .mode = 0644, | ||
| 419 | .proc_handler = proc_dointvec | ||
| 420 | }, | ||
| 421 | { } | ||
| 422 | }; | ||
| 423 | |||
| 424 | static struct ctl_table lowpan_frags_ctl_table[] = { | ||
| 425 | { | ||
| 426 | .procname = "6lowpanfrag_secret_interval", | ||
| 427 | .data = &lowpan_frags.secret_interval, | ||
| 428 | .maxlen = sizeof(int), | ||
| 429 | .mode = 0644, | ||
| 430 | .proc_handler = proc_dointvec_jiffies, | ||
| 431 | }, | ||
| 432 | { } | ||
| 433 | }; | ||
| 434 | |||
| 435 | static int __net_init lowpan_frags_ns_sysctl_register(struct net *net) | ||
| 436 | { | ||
| 437 | struct ctl_table *table; | ||
| 438 | struct ctl_table_header *hdr; | ||
| 439 | |||
| 440 | table = lowpan_frags_ns_ctl_table; | ||
| 441 | if (!net_eq(net, &init_net)) { | ||
| 442 | table = kmemdup(table, sizeof(lowpan_frags_ns_ctl_table), | ||
| 443 | GFP_KERNEL); | ||
| 444 | if (table == NULL) | ||
| 445 | goto err_alloc; | ||
| 446 | |||
| 447 | table[0].data = &net->ieee802154_lowpan.frags.high_thresh; | ||
| 448 | table[1].data = &net->ieee802154_lowpan.frags.low_thresh; | ||
| 449 | table[2].data = &net->ieee802154_lowpan.frags.timeout; | ||
| 450 | table[3].data = &net->ieee802154_lowpan.max_dsize; | ||
| 451 | |||
| 452 | /* Don't export sysctls to unprivileged users */ | ||
| 453 | if (net->user_ns != &init_user_ns) | ||
| 454 | table[0].procname = NULL; | ||
| 455 | } | ||
| 456 | |||
| 457 | hdr = register_net_sysctl(net, "net/ieee802154/6lowpan", table); | ||
| 458 | if (hdr == NULL) | ||
| 459 | goto err_reg; | ||
| 460 | |||
| 461 | net->ieee802154_lowpan.sysctl.frags_hdr = hdr; | ||
| 462 | return 0; | ||
| 463 | |||
| 464 | err_reg: | ||
| 465 | if (!net_eq(net, &init_net)) | ||
| 466 | kfree(table); | ||
| 467 | err_alloc: | ||
| 468 | return -ENOMEM; | ||
| 469 | } | ||
| 470 | |||
| 471 | static void __net_exit lowpan_frags_ns_sysctl_unregister(struct net *net) | ||
| 472 | { | ||
| 473 | struct ctl_table *table; | ||
| 474 | |||
| 475 | table = net->ieee802154_lowpan.sysctl.frags_hdr->ctl_table_arg; | ||
| 476 | unregister_net_sysctl_table(net->ieee802154_lowpan.sysctl.frags_hdr); | ||
| 477 | if (!net_eq(net, &init_net)) | ||
| 478 | kfree(table); | ||
| 479 | } | ||
| 480 | |||
| 481 | static struct ctl_table_header *lowpan_ctl_header; | ||
| 482 | |||
| 483 | static int lowpan_frags_sysctl_register(void) | ||
| 484 | { | ||
| 485 | lowpan_ctl_header = register_net_sysctl(&init_net, | ||
| 486 | "net/ieee802154/6lowpan", | ||
| 487 | lowpan_frags_ctl_table); | ||
| 488 | return lowpan_ctl_header == NULL ? -ENOMEM : 0; | ||
| 489 | } | ||
| 490 | |||
| 491 | static void lowpan_frags_sysctl_unregister(void) | ||
| 492 | { | ||
| 493 | unregister_net_sysctl_table(lowpan_ctl_header); | ||
| 494 | } | ||
| 495 | #else | ||
| 496 | static inline int lowpan_frags_ns_sysctl_register(struct net *net) | ||
| 497 | { | ||
| 498 | return 0; | ||
| 499 | } | ||
| 500 | |||
| 501 | static inline void lowpan_frags_ns_sysctl_unregister(struct net *net) | ||
| 502 | { | ||
| 503 | } | ||
| 504 | |||
| 505 | static inline int lowpan_frags_sysctl_register(void) | ||
| 506 | { | ||
| 507 | return 0; | ||
| 508 | } | ||
| 509 | |||
| 510 | static inline void lowpan_frags_sysctl_unregister(void) | ||
| 511 | { | ||
| 512 | } | ||
| 513 | #endif | ||
| 514 | |||
| 515 | static int __net_init lowpan_frags_init_net(struct net *net) | ||
| 516 | { | ||
| 517 | net->ieee802154_lowpan.frags.high_thresh = IPV6_FRAG_HIGH_THRESH; | ||
| 518 | net->ieee802154_lowpan.frags.low_thresh = IPV6_FRAG_LOW_THRESH; | ||
| 519 | net->ieee802154_lowpan.frags.timeout = IPV6_FRAG_TIMEOUT; | ||
| 520 | net->ieee802154_lowpan.max_dsize = 0xFFFF; | ||
| 521 | |||
| 522 | inet_frags_init_net(&net->ieee802154_lowpan.frags); | ||
| 523 | |||
| 524 | return lowpan_frags_ns_sysctl_register(net); | ||
| 525 | } | ||
| 526 | |||
| 527 | static void __net_exit lowpan_frags_exit_net(struct net *net) | ||
| 528 | { | ||
| 529 | lowpan_frags_ns_sysctl_unregister(net); | ||
| 530 | inet_frags_exit_net(&net->ieee802154_lowpan.frags, &lowpan_frags); | ||
| 531 | } | ||
| 532 | |||
| 533 | static struct pernet_operations lowpan_frags_ops = { | ||
| 534 | .init = lowpan_frags_init_net, | ||
| 535 | .exit = lowpan_frags_exit_net, | ||
| 536 | }; | ||
| 537 | |||
| 538 | int __init lowpan_net_frag_init(void) | ||
| 539 | { | ||
| 540 | int ret; | ||
| 541 | |||
| 542 | ret = lowpan_frags_sysctl_register(); | ||
| 543 | if (ret) | ||
| 544 | return ret; | ||
| 545 | |||
| 546 | ret = register_pernet_subsys(&lowpan_frags_ops); | ||
| 547 | if (ret) | ||
| 548 | goto err_pernet; | ||
| 549 | |||
| 550 | lowpan_frags.hashfn = lowpan_hashfn; | ||
| 551 | lowpan_frags.constructor = lowpan_frag_init; | ||
| 552 | lowpan_frags.destructor = NULL; | ||
| 553 | lowpan_frags.skb_free = NULL; | ||
| 554 | lowpan_frags.qsize = sizeof(struct frag_queue); | ||
| 555 | lowpan_frags.match = lowpan_frag_match; | ||
| 556 | lowpan_frags.frag_expire = lowpan_frag_expire; | ||
| 557 | lowpan_frags.secret_interval = 10 * 60 * HZ; | ||
| 558 | inet_frags_init(&lowpan_frags); | ||
| 559 | |||
| 560 | return ret; | ||
| 561 | err_pernet: | ||
| 562 | lowpan_frags_sysctl_unregister(); | ||
| 563 | return ret; | ||
| 564 | } | ||
| 565 | |||
| 566 | void lowpan_net_frag_exit(void) | ||
| 567 | { | ||
| 568 | inet_frags_fini(&lowpan_frags); | ||
| 569 | lowpan_frags_sysctl_unregister(); | ||
| 570 | unregister_pernet_subsys(&lowpan_frags_ops); | ||
| 571 | } | ||
diff --git a/net/ieee802154/reassembly.h b/net/ieee802154/reassembly.h new file mode 100644 index 000000000000..74e4a7c98191 --- /dev/null +++ b/net/ieee802154/reassembly.h | |||
| @@ -0,0 +1,41 @@ | |||
| 1 | #ifndef __IEEE802154_6LOWPAN_REASSEMBLY_H__ | ||
| 2 | #define __IEEE802154_6LOWPAN_REASSEMBLY_H__ | ||
| 3 | |||
| 4 | #include <net/inet_frag.h> | ||
| 5 | |||
| 6 | struct lowpan_create_arg { | ||
| 7 | __be16 tag; | ||
| 8 | u16 d_size; | ||
| 9 | const struct ieee802154_addr *src; | ||
| 10 | const struct ieee802154_addr *dst; | ||
| 11 | }; | ||
| 12 | |||
| 13 | /* Equivalent of ipv4 struct ip | ||
| 14 | */ | ||
| 15 | struct lowpan_frag_queue { | ||
| 16 | struct inet_frag_queue q; | ||
| 17 | |||
| 18 | __be16 tag; | ||
| 19 | u16 d_size; | ||
| 20 | struct ieee802154_addr saddr; | ||
| 21 | struct ieee802154_addr daddr; | ||
| 22 | }; | ||
| 23 | |||
| 24 | static inline u32 ieee802154_addr_hash(const struct ieee802154_addr *a) | ||
| 25 | { | ||
| 26 | switch (a->mode) { | ||
| 27 | case IEEE802154_ADDR_LONG: | ||
| 28 | return (((__force u64)a->extended_addr) >> 32) ^ | ||
| 29 | (((__force u64)a->extended_addr) & 0xffffffff); | ||
| 30 | case IEEE802154_ADDR_SHORT: | ||
| 31 | return (__force u32)(a->short_addr); | ||
| 32 | default: | ||
| 33 | return 0; | ||
| 34 | } | ||
| 35 | } | ||
| 36 | |||
| 37 | int lowpan_frag_rcv(struct sk_buff *skb, const u8 frag_type); | ||
| 38 | void lowpan_net_frag_exit(void); | ||
| 39 | int lowpan_net_frag_init(void); | ||
| 40 | |||
| 41 | #endif /* __IEEE802154_6LOWPAN_REASSEMBLY_H__ */ | ||
diff --git a/net/ieee802154/wpan-class.c b/net/ieee802154/wpan-class.c index 4dd37615a749..8d6f6704da84 100644 --- a/net/ieee802154/wpan-class.c +++ b/net/ieee802154/wpan-class.c | |||
| @@ -44,9 +44,7 @@ static DEVICE_ATTR_RO(name); | |||
| 44 | 44 | ||
| 45 | MASTER_SHOW(current_channel, "%d"); | 45 | MASTER_SHOW(current_channel, "%d"); |
| 46 | MASTER_SHOW(current_page, "%d"); | 46 | MASTER_SHOW(current_page, "%d"); |
| 47 | MASTER_SHOW_COMPLEX(transmit_power, "%d +- %d dB", | 47 | MASTER_SHOW(transmit_power, "%d +- 1 dB"); |
| 48 | ((signed char) (phy->transmit_power << 2)) >> 2, | ||
| 49 | (phy->transmit_power >> 6) ? (phy->transmit_power >> 6) * 3 : 1); | ||
| 50 | MASTER_SHOW(cca_mode, "%d"); | 48 | MASTER_SHOW(cca_mode, "%d"); |
| 51 | 49 | ||
| 52 | static ssize_t channels_supported_show(struct device *dev, | 50 | static ssize_t channels_supported_show(struct device *dev, |
diff --git a/net/ipv4/Makefile b/net/ipv4/Makefile index f8c49ce5b283..f032688d20d3 100644 --- a/net/ipv4/Makefile +++ b/net/ipv4/Makefile | |||
| @@ -55,4 +55,4 @@ obj-$(CONFIG_MEMCG_KMEM) += tcp_memcontrol.o | |||
| 55 | obj-$(CONFIG_NETLABEL) += cipso_ipv4.o | 55 | obj-$(CONFIG_NETLABEL) += cipso_ipv4.o |
| 56 | 56 | ||
| 57 | obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \ | 57 | obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \ |
| 58 | xfrm4_output.o | 58 | xfrm4_output.o xfrm4_protocol.o |
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c index 19ab78aca547..8c54870db792 100644 --- a/net/ipv4/af_inet.c +++ b/net/ipv4/af_inet.c | |||
| @@ -1505,9 +1505,9 @@ u64 snmp_fold_field64(void __percpu *mib[], int offt, size_t syncp_offset) | |||
| 1505 | bhptr = per_cpu_ptr(mib[0], cpu); | 1505 | bhptr = per_cpu_ptr(mib[0], cpu); |
| 1506 | syncp = (struct u64_stats_sync *)(bhptr + syncp_offset); | 1506 | syncp = (struct u64_stats_sync *)(bhptr + syncp_offset); |
| 1507 | do { | 1507 | do { |
| 1508 | start = u64_stats_fetch_begin_bh(syncp); | 1508 | start = u64_stats_fetch_begin_irq(syncp); |
| 1509 | v = *(((u64 *) bhptr) + offt); | 1509 | v = *(((u64 *) bhptr) + offt); |
| 1510 | } while (u64_stats_fetch_retry_bh(syncp, start)); | 1510 | } while (u64_stats_fetch_retry_irq(syncp, start)); |
| 1511 | 1511 | ||
| 1512 | res += v; | 1512 | res += v; |
| 1513 | } | 1513 | } |
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index 717902669d2f..a2afa89513a0 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c | |||
| @@ -155,6 +155,10 @@ static int ah_output(struct xfrm_state *x, struct sk_buff *skb) | |||
| 155 | struct iphdr *iph, *top_iph; | 155 | struct iphdr *iph, *top_iph; |
| 156 | struct ip_auth_hdr *ah; | 156 | struct ip_auth_hdr *ah; |
| 157 | struct ah_data *ahp; | 157 | struct ah_data *ahp; |
| 158 | int seqhi_len = 0; | ||
| 159 | __be32 *seqhi; | ||
| 160 | int sglists = 0; | ||
| 161 | struct scatterlist *seqhisg; | ||
| 158 | 162 | ||
| 159 | ahp = x->data; | 163 | ahp = x->data; |
| 160 | ahash = ahp->ahash; | 164 | ahash = ahp->ahash; |
| @@ -167,14 +171,19 @@ static int ah_output(struct xfrm_state *x, struct sk_buff *skb) | |||
| 167 | ah = ip_auth_hdr(skb); | 171 | ah = ip_auth_hdr(skb); |
| 168 | ihl = ip_hdrlen(skb); | 172 | ihl = ip_hdrlen(skb); |
| 169 | 173 | ||
| 174 | if (x->props.flags & XFRM_STATE_ESN) { | ||
| 175 | sglists = 1; | ||
| 176 | seqhi_len = sizeof(*seqhi); | ||
| 177 | } | ||
| 170 | err = -ENOMEM; | 178 | err = -ENOMEM; |
| 171 | iph = ah_alloc_tmp(ahash, nfrags, ihl); | 179 | iph = ah_alloc_tmp(ahash, nfrags + sglists, ihl + seqhi_len); |
| 172 | if (!iph) | 180 | if (!iph) |
| 173 | goto out; | 181 | goto out; |
| 174 | 182 | seqhi = (__be32 *)((char *)iph + ihl); | |
| 175 | icv = ah_tmp_icv(ahash, iph, ihl); | 183 | icv = ah_tmp_icv(ahash, seqhi, seqhi_len); |
| 176 | req = ah_tmp_req(ahash, icv); | 184 | req = ah_tmp_req(ahash, icv); |
| 177 | sg = ah_req_sg(ahash, req); | 185 | sg = ah_req_sg(ahash, req); |
| 186 | seqhisg = sg + nfrags; | ||
| 178 | 187 | ||
| 179 | memset(ah->auth_data, 0, ahp->icv_trunc_len); | 188 | memset(ah->auth_data, 0, ahp->icv_trunc_len); |
| 180 | 189 | ||
| @@ -210,10 +219,15 @@ static int ah_output(struct xfrm_state *x, struct sk_buff *skb) | |||
| 210 | ah->spi = x->id.spi; | 219 | ah->spi = x->id.spi; |
| 211 | ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.low); | 220 | ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.low); |
| 212 | 221 | ||
| 213 | sg_init_table(sg, nfrags); | 222 | sg_init_table(sg, nfrags + sglists); |
| 214 | skb_to_sgvec(skb, sg, 0, skb->len); | 223 | skb_to_sgvec_nomark(skb, sg, 0, skb->len); |
| 215 | 224 | ||
| 216 | ahash_request_set_crypt(req, sg, icv, skb->len); | 225 | if (x->props.flags & XFRM_STATE_ESN) { |
| 226 | /* Attach seqhi sg right after packet payload */ | ||
| 227 | *seqhi = htonl(XFRM_SKB_CB(skb)->seq.output.hi); | ||
| 228 | sg_set_buf(seqhisg, seqhi, seqhi_len); | ||
| 229 | } | ||
| 230 | ahash_request_set_crypt(req, sg, icv, skb->len + seqhi_len); | ||
| 217 | ahash_request_set_callback(req, 0, ah_output_done, skb); | 231 | ahash_request_set_callback(req, 0, ah_output_done, skb); |
| 218 | 232 | ||
| 219 | AH_SKB_CB(skb)->tmp = iph; | 233 | AH_SKB_CB(skb)->tmp = iph; |
| @@ -295,6 +309,10 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb) | |||
| 295 | struct ip_auth_hdr *ah; | 309 | struct ip_auth_hdr *ah; |
| 296 | struct ah_data *ahp; | 310 | struct ah_data *ahp; |
| 297 | int err = -ENOMEM; | 311 | int err = -ENOMEM; |
| 312 | int seqhi_len = 0; | ||
| 313 | __be32 *seqhi; | ||
| 314 | int sglists = 0; | ||
| 315 | struct scatterlist *seqhisg; | ||
| 298 | 316 | ||
| 299 | if (!pskb_may_pull(skb, sizeof(*ah))) | 317 | if (!pskb_may_pull(skb, sizeof(*ah))) |
| 300 | goto out; | 318 | goto out; |
| @@ -335,14 +353,22 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb) | |||
| 335 | iph = ip_hdr(skb); | 353 | iph = ip_hdr(skb); |
| 336 | ihl = ip_hdrlen(skb); | 354 | ihl = ip_hdrlen(skb); |
| 337 | 355 | ||
| 338 | work_iph = ah_alloc_tmp(ahash, nfrags, ihl + ahp->icv_trunc_len); | 356 | if (x->props.flags & XFRM_STATE_ESN) { |
| 357 | sglists = 1; | ||
| 358 | seqhi_len = sizeof(*seqhi); | ||
| 359 | } | ||
| 360 | |||
| 361 | work_iph = ah_alloc_tmp(ahash, nfrags + sglists, ihl + | ||
| 362 | ahp->icv_trunc_len + seqhi_len); | ||
| 339 | if (!work_iph) | 363 | if (!work_iph) |
| 340 | goto out; | 364 | goto out; |
| 341 | 365 | ||
| 342 | auth_data = ah_tmp_auth(work_iph, ihl); | 366 | seqhi = (__be32 *)((char *)work_iph + ihl); |
| 367 | auth_data = ah_tmp_auth(seqhi, seqhi_len); | ||
| 343 | icv = ah_tmp_icv(ahash, auth_data, ahp->icv_trunc_len); | 368 | icv = ah_tmp_icv(ahash, auth_data, ahp->icv_trunc_len); |
| 344 | req = ah_tmp_req(ahash, icv); | 369 | req = ah_tmp_req(ahash, icv); |
| 345 | sg = ah_req_sg(ahash, req); | 370 | sg = ah_req_sg(ahash, req); |
| 371 | seqhisg = sg + nfrags; | ||
| 346 | 372 | ||
| 347 | memcpy(work_iph, iph, ihl); | 373 | memcpy(work_iph, iph, ihl); |
| 348 | memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len); | 374 | memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len); |
| @@ -361,10 +387,15 @@ static int ah_input(struct xfrm_state *x, struct sk_buff *skb) | |||
| 361 | 387 | ||
| 362 | skb_push(skb, ihl); | 388 | skb_push(skb, ihl); |
| 363 | 389 | ||
| 364 | sg_init_table(sg, nfrags); | 390 | sg_init_table(sg, nfrags + sglists); |
| 365 | skb_to_sgvec(skb, sg, 0, skb->len); | 391 | skb_to_sgvec_nomark(skb, sg, 0, skb->len); |
| 366 | 392 | ||
| 367 | ahash_request_set_crypt(req, sg, icv, skb->len); | 393 | if (x->props.flags & XFRM_STATE_ESN) { |
| 394 | /* Attach seqhi sg right after packet payload */ | ||
| 395 | *seqhi = XFRM_SKB_CB(skb)->seq.input.hi; | ||
| 396 | sg_set_buf(seqhisg, seqhi, seqhi_len); | ||
| 397 | } | ||
| 398 | ahash_request_set_crypt(req, sg, icv, skb->len + seqhi_len); | ||
| 368 | ahash_request_set_callback(req, 0, ah_input_done, skb); | 399 | ahash_request_set_callback(req, 0, ah_input_done, skb); |
| 369 | 400 | ||
| 370 | AH_SKB_CB(skb)->tmp = work_iph; | 401 | AH_SKB_CB(skb)->tmp = work_iph; |
| @@ -397,7 +428,7 @@ out: | |||
| 397 | return err; | 428 | return err; |
| 398 | } | 429 | } |
| 399 | 430 | ||
| 400 | static void ah4_err(struct sk_buff *skb, u32 info) | 431 | static int ah4_err(struct sk_buff *skb, u32 info) |
| 401 | { | 432 | { |
| 402 | struct net *net = dev_net(skb->dev); | 433 | struct net *net = dev_net(skb->dev); |
| 403 | const struct iphdr *iph = (const struct iphdr *)skb->data; | 434 | const struct iphdr *iph = (const struct iphdr *)skb->data; |
| @@ -407,23 +438,25 @@ static void ah4_err(struct sk_buff *skb, u32 info) | |||
| 407 | switch (icmp_hdr(skb)->type) { | 438 | switch (icmp_hdr(skb)->type) { |
| 408 | case ICMP_DEST_UNREACH: | 439 | case ICMP_DEST_UNREACH: |
| 409 | if (icmp_hdr(skb)->code != ICMP_FRAG_NEEDED) | 440 | if (icmp_hdr(skb)->code != ICMP_FRAG_NEEDED) |
| 410 | return; | 441 | return 0; |
| 411 | case ICMP_REDIRECT: | 442 | case ICMP_REDIRECT: |
| 412 | break; | 443 | break; |
| 413 | default: | 444 | default: |
| 414 | return; | 445 | return 0; |
| 415 | } | 446 | } |
| 416 | 447 | ||
| 417 | x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, | 448 | x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, |
| 418 | ah->spi, IPPROTO_AH, AF_INET); | 449 | ah->spi, IPPROTO_AH, AF_INET); |
| 419 | if (!x) | 450 | if (!x) |
| 420 | return; | 451 | return 0; |
| 421 | 452 | ||
| 422 | if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) | 453 | if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) |
| 423 | ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_AH, 0); | 454 | ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_AH, 0); |
| 424 | else | 455 | else |
| 425 | ipv4_redirect(skb, net, 0, 0, IPPROTO_AH, 0); | 456 | ipv4_redirect(skb, net, 0, 0, IPPROTO_AH, 0); |
| 426 | xfrm_state_put(x); | 457 | xfrm_state_put(x); |
| 458 | |||
| 459 | return 0; | ||
| 427 | } | 460 | } |
| 428 | 461 | ||
| 429 | static int ah_init_state(struct xfrm_state *x) | 462 | static int ah_init_state(struct xfrm_state *x) |
| @@ -505,6 +538,10 @@ static void ah_destroy(struct xfrm_state *x) | |||
| 505 | kfree(ahp); | 538 | kfree(ahp); |
| 506 | } | 539 | } |
| 507 | 540 | ||
| 541 | static int ah4_rcv_cb(struct sk_buff *skb, int err) | ||
| 542 | { | ||
| 543 | return 0; | ||
| 544 | } | ||
| 508 | 545 | ||
| 509 | static const struct xfrm_type ah_type = | 546 | static const struct xfrm_type ah_type = |
| 510 | { | 547 | { |
| @@ -518,11 +555,12 @@ static const struct xfrm_type ah_type = | |||
| 518 | .output = ah_output | 555 | .output = ah_output |
| 519 | }; | 556 | }; |
| 520 | 557 | ||
| 521 | static const struct net_protocol ah4_protocol = { | 558 | static struct xfrm4_protocol ah4_protocol = { |
| 522 | .handler = xfrm4_rcv, | 559 | .handler = xfrm4_rcv, |
| 560 | .input_handler = xfrm_input, | ||
| 561 | .cb_handler = ah4_rcv_cb, | ||
| 523 | .err_handler = ah4_err, | 562 | .err_handler = ah4_err, |
| 524 | .no_policy = 1, | 563 | .priority = 0, |
| 525 | .netns_ok = 1, | ||
| 526 | }; | 564 | }; |
| 527 | 565 | ||
| 528 | static int __init ah4_init(void) | 566 | static int __init ah4_init(void) |
| @@ -531,7 +569,7 @@ static int __init ah4_init(void) | |||
| 531 | pr_info("%s: can't add xfrm type\n", __func__); | 569 | pr_info("%s: can't add xfrm type\n", __func__); |
| 532 | return -EAGAIN; | 570 | return -EAGAIN; |
| 533 | } | 571 | } |
| 534 | if (inet_add_protocol(&ah4_protocol, IPPROTO_AH) < 0) { | 572 | if (xfrm4_protocol_register(&ah4_protocol, IPPROTO_AH) < 0) { |
| 535 | pr_info("%s: can't add protocol\n", __func__); | 573 | pr_info("%s: can't add protocol\n", __func__); |
| 536 | xfrm_unregister_type(&ah_type, AF_INET); | 574 | xfrm_unregister_type(&ah_type, AF_INET); |
| 537 | return -EAGAIN; | 575 | return -EAGAIN; |
| @@ -541,7 +579,7 @@ static int __init ah4_init(void) | |||
| 541 | 579 | ||
| 542 | static void __exit ah4_fini(void) | 580 | static void __exit ah4_fini(void) |
| 543 | { | 581 | { |
| 544 | if (inet_del_protocol(&ah4_protocol, IPPROTO_AH) < 0) | 582 | if (xfrm4_protocol_deregister(&ah4_protocol, IPPROTO_AH) < 0) |
| 545 | pr_info("%s: can't remove protocol\n", __func__); | 583 | pr_info("%s: can't remove protocol\n", __func__); |
| 546 | if (xfrm_unregister_type(&ah_type, AF_INET) < 0) | 584 | if (xfrm_unregister_type(&ah_type, AF_INET) < 0) |
| 547 | pr_info("%s: can't remove xfrm type\n", __func__); | 585 | pr_info("%s: can't remove xfrm type\n", __func__); |
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index 7785b28061ac..360b565918c4 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c | |||
| @@ -473,7 +473,7 @@ static u32 esp4_get_mtu(struct xfrm_state *x, int mtu) | |||
| 473 | net_adj) & ~(blksize - 1)) + net_adj - 2; | 473 | net_adj) & ~(blksize - 1)) + net_adj - 2; |
| 474 | } | 474 | } |
| 475 | 475 | ||
| 476 | static void esp4_err(struct sk_buff *skb, u32 info) | 476 | static int esp4_err(struct sk_buff *skb, u32 info) |
| 477 | { | 477 | { |
| 478 | struct net *net = dev_net(skb->dev); | 478 | struct net *net = dev_net(skb->dev); |
| 479 | const struct iphdr *iph = (const struct iphdr *)skb->data; | 479 | const struct iphdr *iph = (const struct iphdr *)skb->data; |
| @@ -483,23 +483,25 @@ static void esp4_err(struct sk_buff *skb, u32 info) | |||
| 483 | switch (icmp_hdr(skb)->type) { | 483 | switch (icmp_hdr(skb)->type) { |
| 484 | case ICMP_DEST_UNREACH: | 484 | case ICMP_DEST_UNREACH: |
| 485 | if (icmp_hdr(skb)->code != ICMP_FRAG_NEEDED) | 485 | if (icmp_hdr(skb)->code != ICMP_FRAG_NEEDED) |
| 486 | return; | 486 | return 0; |
| 487 | case ICMP_REDIRECT: | 487 | case ICMP_REDIRECT: |
| 488 | break; | 488 | break; |
| 489 | default: | 489 | default: |
| 490 | return; | 490 | return 0; |
| 491 | } | 491 | } |
| 492 | 492 | ||
| 493 | x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, | 493 | x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, |
| 494 | esph->spi, IPPROTO_ESP, AF_INET); | 494 | esph->spi, IPPROTO_ESP, AF_INET); |
| 495 | if (!x) | 495 | if (!x) |
| 496 | return; | 496 | return 0; |
| 497 | 497 | ||
| 498 | if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) | 498 | if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) |
| 499 | ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_ESP, 0); | 499 | ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_ESP, 0); |
| 500 | else | 500 | else |
| 501 | ipv4_redirect(skb, net, 0, 0, IPPROTO_ESP, 0); | 501 | ipv4_redirect(skb, net, 0, 0, IPPROTO_ESP, 0); |
| 502 | xfrm_state_put(x); | 502 | xfrm_state_put(x); |
| 503 | |||
| 504 | return 0; | ||
| 503 | } | 505 | } |
| 504 | 506 | ||
| 505 | static void esp_destroy(struct xfrm_state *x) | 507 | static void esp_destroy(struct xfrm_state *x) |
| @@ -672,6 +674,11 @@ error: | |||
| 672 | return err; | 674 | return err; |
| 673 | } | 675 | } |
| 674 | 676 | ||
| 677 | static int esp4_rcv_cb(struct sk_buff *skb, int err) | ||
| 678 | { | ||
| 679 | return 0; | ||
| 680 | } | ||
| 681 | |||
| 675 | static const struct xfrm_type esp_type = | 682 | static const struct xfrm_type esp_type = |
| 676 | { | 683 | { |
| 677 | .description = "ESP4", | 684 | .description = "ESP4", |
| @@ -685,11 +692,12 @@ static const struct xfrm_type esp_type = | |||
| 685 | .output = esp_output | 692 | .output = esp_output |
| 686 | }; | 693 | }; |
| 687 | 694 | ||
| 688 | static const struct net_protocol esp4_protocol = { | 695 | static struct xfrm4_protocol esp4_protocol = { |
| 689 | .handler = xfrm4_rcv, | 696 | .handler = xfrm4_rcv, |
| 697 | .input_handler = xfrm_input, | ||
| 698 | .cb_handler = esp4_rcv_cb, | ||
| 690 | .err_handler = esp4_err, | 699 | .err_handler = esp4_err, |
| 691 | .no_policy = 1, | 700 | .priority = 0, |
| 692 | .netns_ok = 1, | ||
| 693 | }; | 701 | }; |
| 694 | 702 | ||
| 695 | static int __init esp4_init(void) | 703 | static int __init esp4_init(void) |
| @@ -698,7 +706,7 @@ static int __init esp4_init(void) | |||
| 698 | pr_info("%s: can't add xfrm type\n", __func__); | 706 | pr_info("%s: can't add xfrm type\n", __func__); |
| 699 | return -EAGAIN; | 707 | return -EAGAIN; |
| 700 | } | 708 | } |
| 701 | if (inet_add_protocol(&esp4_protocol, IPPROTO_ESP) < 0) { | 709 | if (xfrm4_protocol_register(&esp4_protocol, IPPROTO_ESP) < 0) { |
| 702 | pr_info("%s: can't add protocol\n", __func__); | 710 | pr_info("%s: can't add protocol\n", __func__); |
| 703 | xfrm_unregister_type(&esp_type, AF_INET); | 711 | xfrm_unregister_type(&esp_type, AF_INET); |
| 704 | return -EAGAIN; | 712 | return -EAGAIN; |
| @@ -708,7 +716,7 @@ static int __init esp4_init(void) | |||
| 708 | 716 | ||
| 709 | static void __exit esp4_fini(void) | 717 | static void __exit esp4_fini(void) |
| 710 | { | 718 | { |
| 711 | if (inet_del_protocol(&esp4_protocol, IPPROTO_ESP) < 0) | 719 | if (xfrm4_protocol_deregister(&esp4_protocol, IPPROTO_ESP) < 0) |
| 712 | pr_info("%s: can't remove protocol\n", __func__); | 720 | pr_info("%s: can't remove protocol\n", __func__); |
| 713 | if (xfrm_unregister_type(&esp_type, AF_INET) < 0) | 721 | if (xfrm_unregister_type(&esp_type, AF_INET) < 0) |
| 714 | pr_info("%s: can't remove xfrm type\n", __func__); | 722 | pr_info("%s: can't remove xfrm type\n", __func__); |
diff --git a/net/ipv4/fib_frontend.c b/net/ipv4/fib_frontend.c index c7539e22868b..1a629f870274 100644 --- a/net/ipv4/fib_frontend.c +++ b/net/ipv4/fib_frontend.c | |||
| @@ -659,7 +659,7 @@ static int inet_dump_fib(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 659 | 659 | ||
| 660 | if (nlmsg_len(cb->nlh) >= sizeof(struct rtmsg) && | 660 | if (nlmsg_len(cb->nlh) >= sizeof(struct rtmsg) && |
| 661 | ((struct rtmsg *) nlmsg_data(cb->nlh))->rtm_flags & RTM_F_CLONED) | 661 | ((struct rtmsg *) nlmsg_data(cb->nlh))->rtm_flags & RTM_F_CLONED) |
| 662 | return ip_rt_dump(skb, cb); | 662 | return skb->len; |
| 663 | 663 | ||
| 664 | s_h = cb->args[0]; | 664 | s_h = cb->args[0]; |
| 665 | s_e = cb->args[1]; | 665 | s_e = cb->args[1]; |
diff --git a/net/ipv4/ip_forward.c b/net/ipv4/ip_forward.c index f3869c186d97..be8abe73bb9f 100644 --- a/net/ipv4/ip_forward.c +++ b/net/ipv4/ip_forward.c | |||
| @@ -127,6 +127,10 @@ int ip_forward(struct sk_buff *skb) | |||
| 127 | struct rtable *rt; /* Route we use */ | 127 | struct rtable *rt; /* Route we use */ |
| 128 | struct ip_options *opt = &(IPCB(skb)->opt); | 128 | struct ip_options *opt = &(IPCB(skb)->opt); |
| 129 | 129 | ||
| 130 | /* that should never happen */ | ||
| 131 | if (skb->pkt_type != PACKET_HOST) | ||
| 132 | goto drop; | ||
| 133 | |||
| 130 | if (skb_warn_if_lro(skb)) | 134 | if (skb_warn_if_lro(skb)) |
| 131 | goto drop; | 135 | goto drop; |
| 132 | 136 | ||
| @@ -136,9 +140,6 @@ int ip_forward(struct sk_buff *skb) | |||
| 136 | if (IPCB(skb)->opt.router_alert && ip_call_ra_chain(skb)) | 140 | if (IPCB(skb)->opt.router_alert && ip_call_ra_chain(skb)) |
| 137 | return NET_RX_SUCCESS; | 141 | return NET_RX_SUCCESS; |
| 138 | 142 | ||
| 139 | if (skb->pkt_type != PACKET_HOST) | ||
| 140 | goto drop; | ||
| 141 | |||
| 142 | skb_forward_csum(skb); | 143 | skb_forward_csum(skb); |
| 143 | 144 | ||
| 144 | /* | 145 | /* |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index ec4f762efda5..94213c891565 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
| @@ -463,6 +463,7 @@ static const struct net_device_ops ipgre_netdev_ops = { | |||
| 463 | static void ipgre_tunnel_setup(struct net_device *dev) | 463 | static void ipgre_tunnel_setup(struct net_device *dev) |
| 464 | { | 464 | { |
| 465 | dev->netdev_ops = &ipgre_netdev_ops; | 465 | dev->netdev_ops = &ipgre_netdev_ops; |
| 466 | dev->type = ARPHRD_IPGRE; | ||
| 466 | ip_tunnel_setup(dev, ipgre_net_id); | 467 | ip_tunnel_setup(dev, ipgre_net_id); |
| 467 | } | 468 | } |
| 468 | 469 | ||
| @@ -501,7 +502,6 @@ static int ipgre_tunnel_init(struct net_device *dev) | |||
| 501 | memcpy(dev->dev_addr, &iph->saddr, 4); | 502 | memcpy(dev->dev_addr, &iph->saddr, 4); |
| 502 | memcpy(dev->broadcast, &iph->daddr, 4); | 503 | memcpy(dev->broadcast, &iph->daddr, 4); |
| 503 | 504 | ||
| 504 | dev->type = ARPHRD_IPGRE; | ||
| 505 | dev->flags = IFF_NOARP; | 505 | dev->flags = IFF_NOARP; |
| 506 | dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; | 506 | dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; |
| 507 | dev->addr_len = 4; | 507 | dev->addr_len = 4; |
diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c index 73c6b63bba74..1cbeba5edff9 100644 --- a/net/ipv4/ip_output.c +++ b/net/ipv4/ip_output.c | |||
| @@ -101,17 +101,17 @@ int __ip_local_out(struct sk_buff *skb) | |||
| 101 | skb_dst(skb)->dev, dst_output); | 101 | skb_dst(skb)->dev, dst_output); |
| 102 | } | 102 | } |
| 103 | 103 | ||
| 104 | int ip_local_out(struct sk_buff *skb) | 104 | int ip_local_out_sk(struct sock *sk, struct sk_buff *skb) |
| 105 | { | 105 | { |
| 106 | int err; | 106 | int err; |
| 107 | 107 | ||
| 108 | err = __ip_local_out(skb); | 108 | err = __ip_local_out(skb); |
| 109 | if (likely(err == 1)) | 109 | if (likely(err == 1)) |
| 110 | err = dst_output(skb); | 110 | err = dst_output_sk(sk, skb); |
| 111 | 111 | ||
| 112 | return err; | 112 | return err; |
| 113 | } | 113 | } |
| 114 | EXPORT_SYMBOL_GPL(ip_local_out); | 114 | EXPORT_SYMBOL_GPL(ip_local_out_sk); |
| 115 | 115 | ||
| 116 | static inline int ip_select_ttl(struct inet_sock *inet, struct dst_entry *dst) | 116 | static inline int ip_select_ttl(struct inet_sock *inet, struct dst_entry *dst) |
| 117 | { | 117 | { |
| @@ -226,9 +226,8 @@ static int ip_finish_output(struct sk_buff *skb) | |||
| 226 | return ip_finish_output2(skb); | 226 | return ip_finish_output2(skb); |
| 227 | } | 227 | } |
| 228 | 228 | ||
| 229 | int ip_mc_output(struct sk_buff *skb) | 229 | int ip_mc_output(struct sock *sk, struct sk_buff *skb) |
| 230 | { | 230 | { |
| 231 | struct sock *sk = skb->sk; | ||
| 232 | struct rtable *rt = skb_rtable(skb); | 231 | struct rtable *rt = skb_rtable(skb); |
| 233 | struct net_device *dev = rt->dst.dev; | 232 | struct net_device *dev = rt->dst.dev; |
| 234 | 233 | ||
| @@ -287,7 +286,7 @@ int ip_mc_output(struct sk_buff *skb) | |||
| 287 | !(IPCB(skb)->flags & IPSKB_REROUTED)); | 286 | !(IPCB(skb)->flags & IPSKB_REROUTED)); |
| 288 | } | 287 | } |
| 289 | 288 | ||
| 290 | int ip_output(struct sk_buff *skb) | 289 | int ip_output(struct sock *sk, struct sk_buff *skb) |
| 291 | { | 290 | { |
| 292 | struct net_device *dev = skb_dst(skb)->dev; | 291 | struct net_device *dev = skb_dst(skb)->dev; |
| 293 | 292 | ||
| @@ -315,9 +314,9 @@ static void ip_copy_addrs(struct iphdr *iph, const struct flowi4 *fl4) | |||
| 315 | sizeof(fl4->saddr) + sizeof(fl4->daddr)); | 314 | sizeof(fl4->saddr) + sizeof(fl4->daddr)); |
| 316 | } | 315 | } |
| 317 | 316 | ||
| 318 | int ip_queue_xmit(struct sk_buff *skb, struct flowi *fl) | 317 | /* Note: skb->sk can be different from sk, in case of tunnels */ |
| 318 | int ip_queue_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl) | ||
| 319 | { | 319 | { |
| 320 | struct sock *sk = skb->sk; | ||
| 321 | struct inet_sock *inet = inet_sk(sk); | 320 | struct inet_sock *inet = inet_sk(sk); |
| 322 | struct ip_options_rcu *inet_opt; | 321 | struct ip_options_rcu *inet_opt; |
| 323 | struct flowi4 *fl4; | 322 | struct flowi4 *fl4; |
| @@ -389,6 +388,7 @@ packet_routed: | |||
| 389 | ip_select_ident_more(skb, &rt->dst, sk, | 388 | ip_select_ident_more(skb, &rt->dst, sk, |
| 390 | (skb_shinfo(skb)->gso_segs ?: 1) - 1); | 389 | (skb_shinfo(skb)->gso_segs ?: 1) - 1); |
| 391 | 390 | ||
| 391 | /* TODO : should we use skb->sk here instead of sk ? */ | ||
| 392 | skb->priority = sk->sk_priority; | 392 | skb->priority = sk->sk_priority; |
| 393 | skb->mark = sk->sk_mark; | 393 | skb->mark = sk->sk_mark; |
| 394 | 394 | ||
| @@ -446,7 +446,6 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
| 446 | __be16 not_last_frag; | 446 | __be16 not_last_frag; |
| 447 | struct rtable *rt = skb_rtable(skb); | 447 | struct rtable *rt = skb_rtable(skb); |
| 448 | int err = 0; | 448 | int err = 0; |
| 449 | bool forwarding = IPCB(skb)->flags & IPSKB_FORWARDED; | ||
| 450 | 449 | ||
| 451 | dev = rt->dst.dev; | 450 | dev = rt->dst.dev; |
| 452 | 451 | ||
| @@ -456,7 +455,7 @@ int ip_fragment(struct sk_buff *skb, int (*output)(struct sk_buff *)) | |||
| 456 | 455 | ||
| 457 | iph = ip_hdr(skb); | 456 | iph = ip_hdr(skb); |
| 458 | 457 | ||
| 459 | mtu = ip_dst_mtu_maybe_forward(&rt->dst, forwarding); | 458 | mtu = ip_skb_dst_mtu(skb); |
| 460 | if (unlikely(((iph->frag_off & htons(IP_DF)) && !skb->local_df) || | 459 | if (unlikely(((iph->frag_off & htons(IP_DF)) && !skb->local_df) || |
| 461 | (IPCB(skb)->frag_max_size && | 460 | (IPCB(skb)->frag_max_size && |
| 462 | IPCB(skb)->frag_max_size > mtu))) { | 461 | IPCB(skb)->frag_max_size > mtu))) { |
| @@ -822,8 +821,7 @@ static int __ip_append_data(struct sock *sk, | |||
| 822 | 821 | ||
| 823 | fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0); | 822 | fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0); |
| 824 | maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen; | 823 | maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen; |
| 825 | maxnonfragsize = (inet->pmtudisc >= IP_PMTUDISC_DO) ? | 824 | maxnonfragsize = ip_sk_local_df(sk) ? 0xFFFF : mtu; |
| 826 | mtu : 0xFFFF; | ||
| 827 | 825 | ||
| 828 | if (cork->length + length > maxnonfragsize - fragheaderlen) { | 826 | if (cork->length + length > maxnonfragsize - fragheaderlen) { |
| 829 | ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport, | 827 | ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport, |
| @@ -1146,8 +1144,7 @@ ssize_t ip_append_page(struct sock *sk, struct flowi4 *fl4, struct page *page, | |||
| 1146 | 1144 | ||
| 1147 | fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0); | 1145 | fragheaderlen = sizeof(struct iphdr) + (opt ? opt->optlen : 0); |
| 1148 | maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen; | 1146 | maxfraglen = ((mtu - fragheaderlen) & ~7) + fragheaderlen; |
| 1149 | maxnonfragsize = (inet->pmtudisc >= IP_PMTUDISC_DO) ? | 1147 | maxnonfragsize = ip_sk_local_df(sk) ? 0xFFFF : mtu; |
| 1150 | mtu : 0xFFFF; | ||
| 1151 | 1148 | ||
| 1152 | if (cork->length + size > maxnonfragsize - fragheaderlen) { | 1149 | if (cork->length + size > maxnonfragsize - fragheaderlen) { |
| 1153 | ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport, | 1150 | ip_local_error(sk, EMSGSIZE, fl4->daddr, inet->inet_dport, |
| @@ -1308,8 +1305,7 @@ struct sk_buff *__ip_make_skb(struct sock *sk, | |||
| 1308 | * to fragment the frame generated here. No matter, what transforms | 1305 | * to fragment the frame generated here. No matter, what transforms |
| 1309 | * how transforms change size of the packet, it will come out. | 1306 | * how transforms change size of the packet, it will come out. |
| 1310 | */ | 1307 | */ |
| 1311 | if (inet->pmtudisc < IP_PMTUDISC_DO) | 1308 | skb->local_df = ip_sk_local_df(sk); |
| 1312 | skb->local_df = 1; | ||
| 1313 | 1309 | ||
| 1314 | /* DF bit is set when we want to see DF on outgoing frames. | 1310 | /* DF bit is set when we want to see DF on outgoing frames. |
| 1315 | * If local_df is set too, we still allow to fragment this frame | 1311 | * If local_df is set too, we still allow to fragment this frame |
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c index 580dd96666e0..64741b938632 100644 --- a/net/ipv4/ip_sockglue.c +++ b/net/ipv4/ip_sockglue.c | |||
| @@ -186,7 +186,8 @@ void ip_cmsg_recv(struct msghdr *msg, struct sk_buff *skb) | |||
| 186 | } | 186 | } |
| 187 | EXPORT_SYMBOL(ip_cmsg_recv); | 187 | EXPORT_SYMBOL(ip_cmsg_recv); |
| 188 | 188 | ||
| 189 | int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc) | 189 | int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc, |
| 190 | bool allow_ipv6) | ||
| 190 | { | 191 | { |
| 191 | int err, val; | 192 | int err, val; |
| 192 | struct cmsghdr *cmsg; | 193 | struct cmsghdr *cmsg; |
| @@ -194,6 +195,22 @@ int ip_cmsg_send(struct net *net, struct msghdr *msg, struct ipcm_cookie *ipc) | |||
| 194 | for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { | 195 | for (cmsg = CMSG_FIRSTHDR(msg); cmsg; cmsg = CMSG_NXTHDR(msg, cmsg)) { |
| 195 | if (!CMSG_OK(msg, cmsg)) | 196 | if (!CMSG_OK(msg, cmsg)) |
| 196 | return -EINVAL; | 197 | return -EINVAL; |
| 198 | #if defined(CONFIG_IPV6) | ||
| 199 | if (allow_ipv6 && | ||
| 200 | cmsg->cmsg_level == SOL_IPV6 && | ||
| 201 | cmsg->cmsg_type == IPV6_PKTINFO) { | ||
| 202 | struct in6_pktinfo *src_info; | ||
| 203 | |||
| 204 | if (cmsg->cmsg_len < CMSG_LEN(sizeof(*src_info))) | ||
| 205 | return -EINVAL; | ||
| 206 | src_info = (struct in6_pktinfo *)CMSG_DATA(cmsg); | ||
| 207 | if (!ipv6_addr_v4mapped(&src_info->ipi6_addr)) | ||
| 208 | return -EINVAL; | ||
| 209 | ipc->oif = src_info->ipi6_ifindex; | ||
| 210 | ipc->addr = src_info->ipi6_addr.s6_addr32[3]; | ||
| 211 | continue; | ||
| 212 | } | ||
| 213 | #endif | ||
| 197 | if (cmsg->cmsg_level != SOL_IP) | 214 | if (cmsg->cmsg_level != SOL_IP) |
| 198 | continue; | 215 | continue; |
| 199 | switch (cmsg->cmsg_type) { | 216 | switch (cmsg->cmsg_type) { |
| @@ -626,7 +643,7 @@ static int do_ip_setsockopt(struct sock *sk, int level, | |||
| 626 | inet->nodefrag = val ? 1 : 0; | 643 | inet->nodefrag = val ? 1 : 0; |
| 627 | break; | 644 | break; |
| 628 | case IP_MTU_DISCOVER: | 645 | case IP_MTU_DISCOVER: |
| 629 | if (val < IP_PMTUDISC_DONT || val > IP_PMTUDISC_INTERFACE) | 646 | if (val < IP_PMTUDISC_DONT || val > IP_PMTUDISC_OMIT) |
| 630 | goto e_inval; | 647 | goto e_inval; |
| 631 | inet->pmtudisc = val; | 648 | inet->pmtudisc = val; |
| 632 | break; | 649 | break; |
diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index a82a22d8f77f..484d0ce27ef7 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c | |||
| @@ -235,13 +235,17 @@ static struct hlist_head *ip_bucket(struct ip_tunnel_net *itn, | |||
| 235 | { | 235 | { |
| 236 | unsigned int h; | 236 | unsigned int h; |
| 237 | __be32 remote; | 237 | __be32 remote; |
| 238 | __be32 i_key = parms->i_key; | ||
| 238 | 239 | ||
| 239 | if (parms->iph.daddr && !ipv4_is_multicast(parms->iph.daddr)) | 240 | if (parms->iph.daddr && !ipv4_is_multicast(parms->iph.daddr)) |
| 240 | remote = parms->iph.daddr; | 241 | remote = parms->iph.daddr; |
| 241 | else | 242 | else |
| 242 | remote = 0; | 243 | remote = 0; |
| 243 | 244 | ||
| 244 | h = ip_tunnel_hash(parms->i_key, remote); | 245 | if (!(parms->i_flags & TUNNEL_KEY) && (parms->i_flags & VTI_ISVTI)) |
| 246 | i_key = 0; | ||
| 247 | |||
| 248 | h = ip_tunnel_hash(i_key, remote); | ||
| 245 | return &itn->tunnels[h]; | 249 | return &itn->tunnels[h]; |
| 246 | } | 250 | } |
| 247 | 251 | ||
| @@ -398,7 +402,7 @@ static struct ip_tunnel *ip_tunnel_create(struct net *net, | |||
| 398 | fbt = netdev_priv(itn->fb_tunnel_dev); | 402 | fbt = netdev_priv(itn->fb_tunnel_dev); |
| 399 | dev = __ip_tunnel_create(net, itn->fb_tunnel_dev->rtnl_link_ops, parms); | 403 | dev = __ip_tunnel_create(net, itn->fb_tunnel_dev->rtnl_link_ops, parms); |
| 400 | if (IS_ERR(dev)) | 404 | if (IS_ERR(dev)) |
| 401 | return NULL; | 405 | return ERR_CAST(dev); |
| 402 | 406 | ||
| 403 | dev->mtu = ip_tunnel_bind_dev(dev); | 407 | dev->mtu = ip_tunnel_bind_dev(dev); |
| 404 | 408 | ||
| @@ -666,7 +670,7 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev, | |||
| 666 | return; | 670 | return; |
| 667 | } | 671 | } |
| 668 | 672 | ||
| 669 | err = iptunnel_xmit(rt, skb, fl4.saddr, fl4.daddr, protocol, | 673 | err = iptunnel_xmit(skb->sk, rt, skb, fl4.saddr, fl4.daddr, protocol, |
| 670 | tos, ttl, df, !net_eq(tunnel->net, dev_net(dev))); | 674 | tos, ttl, df, !net_eq(tunnel->net, dev_net(dev))); |
| 671 | iptunnel_xmit_stats(err, &dev->stats, dev->tstats); | 675 | iptunnel_xmit_stats(err, &dev->stats, dev->tstats); |
| 672 | 676 | ||
| @@ -748,9 +752,13 @@ int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd) | |||
| 748 | 752 | ||
| 749 | t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type); | 753 | t = ip_tunnel_find(itn, p, itn->fb_tunnel_dev->type); |
| 750 | 754 | ||
| 751 | if (!t && (cmd == SIOCADDTUNNEL)) | 755 | if (!t && (cmd == SIOCADDTUNNEL)) { |
| 752 | t = ip_tunnel_create(net, itn, p); | 756 | t = ip_tunnel_create(net, itn, p); |
| 753 | 757 | if (IS_ERR(t)) { | |
| 758 | err = PTR_ERR(t); | ||
| 759 | break; | ||
| 760 | } | ||
| 761 | } | ||
| 754 | if (dev != itn->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { | 762 | if (dev != itn->fb_tunnel_dev && cmd == SIOCCHGTUNNEL) { |
| 755 | if (t != NULL) { | 763 | if (t != NULL) { |
| 756 | if (t->dev != dev) { | 764 | if (t->dev != dev) { |
| @@ -777,8 +785,9 @@ int ip_tunnel_ioctl(struct net_device *dev, struct ip_tunnel_parm *p, int cmd) | |||
| 777 | if (t) { | 785 | if (t) { |
| 778 | err = 0; | 786 | err = 0; |
| 779 | ip_tunnel_update(itn, t, dev, p, true); | 787 | ip_tunnel_update(itn, t, dev, p, true); |
| 780 | } else | 788 | } else { |
| 781 | err = (cmd == SIOCADDTUNNEL ? -ENOBUFS : -ENOENT); | 789 | err = -ENOENT; |
| 790 | } | ||
| 782 | break; | 791 | break; |
| 783 | 792 | ||
| 784 | case SIOCDELTUNNEL: | 793 | case SIOCDELTUNNEL: |
| @@ -993,19 +1002,13 @@ int ip_tunnel_init(struct net_device *dev) | |||
| 993 | { | 1002 | { |
| 994 | struct ip_tunnel *tunnel = netdev_priv(dev); | 1003 | struct ip_tunnel *tunnel = netdev_priv(dev); |
| 995 | struct iphdr *iph = &tunnel->parms.iph; | 1004 | struct iphdr *iph = &tunnel->parms.iph; |
| 996 | int i, err; | 1005 | int err; |
| 997 | 1006 | ||
| 998 | dev->destructor = ip_tunnel_dev_free; | 1007 | dev->destructor = ip_tunnel_dev_free; |
| 999 | dev->tstats = alloc_percpu(struct pcpu_sw_netstats); | 1008 | dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); |
| 1000 | if (!dev->tstats) | 1009 | if (!dev->tstats) |
| 1001 | return -ENOMEM; | 1010 | return -ENOMEM; |
| 1002 | 1011 | ||
| 1003 | for_each_possible_cpu(i) { | ||
| 1004 | struct pcpu_sw_netstats *ipt_stats; | ||
| 1005 | ipt_stats = per_cpu_ptr(dev->tstats, i); | ||
| 1006 | u64_stats_init(&ipt_stats->syncp); | ||
| 1007 | } | ||
| 1008 | |||
| 1009 | tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst); | 1012 | tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst); |
| 1010 | if (!tunnel->dst_cache) { | 1013 | if (!tunnel->dst_cache) { |
| 1011 | free_percpu(dev->tstats); | 1014 | free_percpu(dev->tstats); |
diff --git a/net/ipv4/ip_tunnel_core.c b/net/ipv4/ip_tunnel_core.c index 8d69626f2206..bcf206c79005 100644 --- a/net/ipv4/ip_tunnel_core.c +++ b/net/ipv4/ip_tunnel_core.c | |||
| @@ -46,7 +46,7 @@ | |||
| 46 | #include <net/netns/generic.h> | 46 | #include <net/netns/generic.h> |
| 47 | #include <net/rtnetlink.h> | 47 | #include <net/rtnetlink.h> |
| 48 | 48 | ||
| 49 | int iptunnel_xmit(struct rtable *rt, struct sk_buff *skb, | 49 | int iptunnel_xmit(struct sock *sk, struct rtable *rt, struct sk_buff *skb, |
| 50 | __be32 src, __be32 dst, __u8 proto, | 50 | __be32 src, __be32 dst, __u8 proto, |
| 51 | __u8 tos, __u8 ttl, __be16 df, bool xnet) | 51 | __u8 tos, __u8 ttl, __be16 df, bool xnet) |
| 52 | { | 52 | { |
| @@ -76,7 +76,7 @@ int iptunnel_xmit(struct rtable *rt, struct sk_buff *skb, | |||
| 76 | iph->ttl = ttl; | 76 | iph->ttl = ttl; |
| 77 | __ip_select_ident(iph, &rt->dst, (skb_shinfo(skb)->gso_segs ?: 1) - 1); | 77 | __ip_select_ident(iph, &rt->dst, (skb_shinfo(skb)->gso_segs ?: 1) - 1); |
| 78 | 78 | ||
| 79 | err = ip_local_out(skb); | 79 | err = ip_local_out_sk(sk, skb); |
| 80 | if (unlikely(net_xmit_eval(err))) | 80 | if (unlikely(net_xmit_eval(err))) |
| 81 | pkt_len = 0; | 81 | pkt_len = 0; |
| 82 | return pkt_len; | 82 | return pkt_len; |
| @@ -162,12 +162,12 @@ struct rtnl_link_stats64 *ip_tunnel_get_stats64(struct net_device *dev, | |||
| 162 | unsigned int start; | 162 | unsigned int start; |
| 163 | 163 | ||
| 164 | do { | 164 | do { |
| 165 | start = u64_stats_fetch_begin_bh(&tstats->syncp); | 165 | start = u64_stats_fetch_begin_irq(&tstats->syncp); |
| 166 | rx_packets = tstats->rx_packets; | 166 | rx_packets = tstats->rx_packets; |
| 167 | tx_packets = tstats->tx_packets; | 167 | tx_packets = tstats->tx_packets; |
| 168 | rx_bytes = tstats->rx_bytes; | 168 | rx_bytes = tstats->rx_bytes; |
| 169 | tx_bytes = tstats->tx_bytes; | 169 | tx_bytes = tstats->tx_bytes; |
| 170 | } while (u64_stats_fetch_retry_bh(&tstats->syncp, start)); | 170 | } while (u64_stats_fetch_retry_irq(&tstats->syncp, start)); |
| 171 | 171 | ||
| 172 | tot->rx_packets += rx_packets; | 172 | tot->rx_packets += rx_packets; |
| 173 | tot->tx_packets += tx_packets; | 173 | tot->tx_packets += tx_packets; |
diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index 48eafae51769..afcee51b90ed 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c | |||
| @@ -34,6 +34,7 @@ | |||
| 34 | #include <linux/init.h> | 34 | #include <linux/init.h> |
| 35 | #include <linux/netfilter_ipv4.h> | 35 | #include <linux/netfilter_ipv4.h> |
| 36 | #include <linux/if_ether.h> | 36 | #include <linux/if_ether.h> |
| 37 | #include <linux/icmpv6.h> | ||
| 37 | 38 | ||
| 38 | #include <net/sock.h> | 39 | #include <net/sock.h> |
| 39 | #include <net/ip.h> | 40 | #include <net/ip.h> |
| @@ -49,8 +50,8 @@ static struct rtnl_link_ops vti_link_ops __read_mostly; | |||
| 49 | static int vti_net_id __read_mostly; | 50 | static int vti_net_id __read_mostly; |
| 50 | static int vti_tunnel_init(struct net_device *dev); | 51 | static int vti_tunnel_init(struct net_device *dev); |
| 51 | 52 | ||
| 52 | /* We dont digest the packet therefore let the packet pass */ | 53 | static int vti_input(struct sk_buff *skb, int nexthdr, __be32 spi, |
| 53 | static int vti_rcv(struct sk_buff *skb) | 54 | int encap_type) |
| 54 | { | 55 | { |
| 55 | struct ip_tunnel *tunnel; | 56 | struct ip_tunnel *tunnel; |
| 56 | const struct iphdr *iph = ip_hdr(skb); | 57 | const struct iphdr *iph = ip_hdr(skb); |
| @@ -60,79 +61,120 @@ static int vti_rcv(struct sk_buff *skb) | |||
| 60 | tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY, | 61 | tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY, |
| 61 | iph->saddr, iph->daddr, 0); | 62 | iph->saddr, iph->daddr, 0); |
| 62 | if (tunnel != NULL) { | 63 | if (tunnel != NULL) { |
| 63 | struct pcpu_sw_netstats *tstats; | 64 | if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb)) |
| 64 | u32 oldmark = skb->mark; | 65 | goto drop; |
| 65 | int ret; | 66 | |
| 66 | 67 | XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = tunnel; | |
| 67 | 68 | skb->mark = be32_to_cpu(tunnel->parms.i_key); | |
| 68 | /* temporarily mark the skb with the tunnel o_key, to | 69 | |
| 69 | * only match policies with this mark. | 70 | return xfrm_input(skb, nexthdr, spi, encap_type); |
| 70 | */ | 71 | } |
| 71 | skb->mark = be32_to_cpu(tunnel->parms.o_key); | 72 | |
| 72 | ret = xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb); | 73 | return -EINVAL; |
| 73 | skb->mark = oldmark; | 74 | drop: |
| 74 | if (!ret) | 75 | kfree_skb(skb); |
| 75 | return -1; | 76 | return 0; |
| 76 | 77 | } | |
| 77 | tstats = this_cpu_ptr(tunnel->dev->tstats); | 78 | |
| 78 | u64_stats_update_begin(&tstats->syncp); | 79 | static int vti_rcv(struct sk_buff *skb) |
| 79 | tstats->rx_packets++; | 80 | { |
| 80 | tstats->rx_bytes += skb->len; | 81 | XFRM_SPI_SKB_CB(skb)->family = AF_INET; |
| 81 | u64_stats_update_end(&tstats->syncp); | 82 | XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr); |
| 82 | 83 | ||
| 83 | secpath_reset(skb); | 84 | return vti_input(skb, ip_hdr(skb)->protocol, 0, 0); |
| 84 | skb->dev = tunnel->dev; | 85 | } |
| 86 | |||
| 87 | static int vti_rcv_cb(struct sk_buff *skb, int err) | ||
| 88 | { | ||
| 89 | unsigned short family; | ||
| 90 | struct net_device *dev; | ||
| 91 | struct pcpu_sw_netstats *tstats; | ||
| 92 | struct xfrm_state *x; | ||
| 93 | struct ip_tunnel *tunnel = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4; | ||
| 94 | |||
| 95 | if (!tunnel) | ||
| 85 | return 1; | 96 | return 1; |
| 97 | |||
| 98 | dev = tunnel->dev; | ||
| 99 | |||
| 100 | if (err) { | ||
| 101 | dev->stats.rx_errors++; | ||
| 102 | dev->stats.rx_dropped++; | ||
| 103 | |||
| 104 | return 0; | ||
| 86 | } | 105 | } |
| 87 | 106 | ||
| 88 | return -1; | 107 | x = xfrm_input_state(skb); |
| 108 | family = x->inner_mode->afinfo->family; | ||
| 109 | |||
| 110 | if (!xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family)) | ||
| 111 | return -EPERM; | ||
| 112 | |||
| 113 | skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(skb->dev))); | ||
| 114 | skb->dev = dev; | ||
| 115 | |||
| 116 | tstats = this_cpu_ptr(dev->tstats); | ||
| 117 | |||
| 118 | u64_stats_update_begin(&tstats->syncp); | ||
| 119 | tstats->rx_packets++; | ||
| 120 | tstats->rx_bytes += skb->len; | ||
| 121 | u64_stats_update_end(&tstats->syncp); | ||
| 122 | |||
| 123 | return 0; | ||
| 89 | } | 124 | } |
| 90 | 125 | ||
| 91 | /* This function assumes it is being called from dev_queue_xmit() | 126 | static bool vti_state_check(const struct xfrm_state *x, __be32 dst, __be32 src) |
| 92 | * and that skb is filled properly by that function. | 127 | { |
| 93 | */ | 128 | xfrm_address_t *daddr = (xfrm_address_t *)&dst; |
| 129 | xfrm_address_t *saddr = (xfrm_address_t *)&src; | ||
| 94 | 130 | ||
| 95 | static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | 131 | /* if there is no transform then this tunnel is not functional. |
| 132 | * Or if the xfrm is not mode tunnel. | ||
| 133 | */ | ||
| 134 | if (!x || x->props.mode != XFRM_MODE_TUNNEL || | ||
| 135 | x->props.family != AF_INET) | ||
| 136 | return false; | ||
| 137 | |||
| 138 | if (!dst) | ||
| 139 | return xfrm_addr_equal(saddr, &x->props.saddr, AF_INET); | ||
| 140 | |||
| 141 | if (!xfrm_state_addr_check(x, daddr, saddr, AF_INET)) | ||
| 142 | return false; | ||
| 143 | |||
| 144 | return true; | ||
| 145 | } | ||
| 146 | |||
| 147 | static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev, | ||
| 148 | struct flowi *fl) | ||
| 96 | { | 149 | { |
| 97 | struct ip_tunnel *tunnel = netdev_priv(dev); | 150 | struct ip_tunnel *tunnel = netdev_priv(dev); |
| 98 | struct iphdr *tiph = &tunnel->parms.iph; | 151 | struct ip_tunnel_parm *parms = &tunnel->parms; |
| 99 | u8 tos; | 152 | struct dst_entry *dst = skb_dst(skb); |
| 100 | struct rtable *rt; /* Route to the other host */ | ||
| 101 | struct net_device *tdev; /* Device to other host */ | 153 | struct net_device *tdev; /* Device to other host */ |
| 102 | struct iphdr *old_iph = ip_hdr(skb); | ||
| 103 | __be32 dst = tiph->daddr; | ||
| 104 | struct flowi4 fl4; | ||
| 105 | int err; | 154 | int err; |
| 106 | 155 | ||
| 107 | if (skb->protocol != htons(ETH_P_IP)) | 156 | if (!dst) { |
| 108 | goto tx_error; | 157 | dev->stats.tx_carrier_errors++; |
| 109 | 158 | goto tx_error_icmp; | |
| 110 | tos = old_iph->tos; | 159 | } |
| 111 | 160 | ||
| 112 | memset(&fl4, 0, sizeof(fl4)); | 161 | dst_hold(dst); |
| 113 | flowi4_init_output(&fl4, tunnel->parms.link, | 162 | dst = xfrm_lookup(tunnel->net, dst, fl, NULL, 0); |
| 114 | be32_to_cpu(tunnel->parms.o_key), RT_TOS(tos), | 163 | if (IS_ERR(dst)) { |
| 115 | RT_SCOPE_UNIVERSE, | ||
| 116 | IPPROTO_IPIP, 0, | ||
| 117 | dst, tiph->saddr, 0, 0); | ||
| 118 | rt = ip_route_output_key(dev_net(dev), &fl4); | ||
| 119 | if (IS_ERR(rt)) { | ||
| 120 | dev->stats.tx_carrier_errors++; | 164 | dev->stats.tx_carrier_errors++; |
| 121 | goto tx_error_icmp; | 165 | goto tx_error_icmp; |
| 122 | } | 166 | } |
| 123 | /* if there is no transform then this tunnel is not functional. | 167 | |
| 124 | * Or if the xfrm is not mode tunnel. | 168 | if (!vti_state_check(dst->xfrm, parms->iph.daddr, parms->iph.saddr)) { |
| 125 | */ | ||
| 126 | if (!rt->dst.xfrm || | ||
| 127 | rt->dst.xfrm->props.mode != XFRM_MODE_TUNNEL) { | ||
| 128 | dev->stats.tx_carrier_errors++; | 169 | dev->stats.tx_carrier_errors++; |
| 129 | ip_rt_put(rt); | 170 | dst_release(dst); |
| 130 | goto tx_error_icmp; | 171 | goto tx_error_icmp; |
| 131 | } | 172 | } |
| 132 | tdev = rt->dst.dev; | 173 | |
| 174 | tdev = dst->dev; | ||
| 133 | 175 | ||
| 134 | if (tdev == dev) { | 176 | if (tdev == dev) { |
| 135 | ip_rt_put(rt); | 177 | dst_release(dst); |
| 136 | dev->stats.collisions++; | 178 | dev->stats.collisions++; |
| 137 | goto tx_error; | 179 | goto tx_error; |
| 138 | } | 180 | } |
| @@ -146,10 +188,8 @@ static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 146 | tunnel->err_count = 0; | 188 | tunnel->err_count = 0; |
| 147 | } | 189 | } |
| 148 | 190 | ||
| 149 | memset(IPCB(skb), 0, sizeof(*IPCB(skb))); | 191 | skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(dev))); |
| 150 | skb_dst_drop(skb); | 192 | skb_dst_set(skb, dst); |
| 151 | skb_dst_set(skb, &rt->dst); | ||
| 152 | nf_reset(skb); | ||
| 153 | skb->dev = skb_dst(skb)->dev; | 193 | skb->dev = skb_dst(skb)->dev; |
| 154 | 194 | ||
| 155 | err = dst_output(skb); | 195 | err = dst_output(skb); |
| @@ -166,6 +206,95 @@ tx_error: | |||
| 166 | return NETDEV_TX_OK; | 206 | return NETDEV_TX_OK; |
| 167 | } | 207 | } |
| 168 | 208 | ||
| 209 | /* This function assumes it is being called from dev_queue_xmit() | ||
| 210 | * and that skb is filled properly by that function. | ||
| 211 | */ | ||
| 212 | static netdev_tx_t vti_tunnel_xmit(struct sk_buff *skb, struct net_device *dev) | ||
| 213 | { | ||
| 214 | struct ip_tunnel *tunnel = netdev_priv(dev); | ||
| 215 | struct flowi fl; | ||
| 216 | |||
| 217 | memset(&fl, 0, sizeof(fl)); | ||
| 218 | |||
| 219 | skb->mark = be32_to_cpu(tunnel->parms.o_key); | ||
| 220 | |||
| 221 | switch (skb->protocol) { | ||
| 222 | case htons(ETH_P_IP): | ||
| 223 | xfrm_decode_session(skb, &fl, AF_INET); | ||
| 224 | memset(IPCB(skb), 0, sizeof(*IPCB(skb))); | ||
| 225 | break; | ||
| 226 | case htons(ETH_P_IPV6): | ||
| 227 | xfrm_decode_session(skb, &fl, AF_INET6); | ||
| 228 | memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); | ||
| 229 | break; | ||
| 230 | default: | ||
| 231 | dev->stats.tx_errors++; | ||
| 232 | dev_kfree_skb(skb); | ||
| 233 | return NETDEV_TX_OK; | ||
| 234 | } | ||
| 235 | |||
| 236 | return vti_xmit(skb, dev, &fl); | ||
| 237 | } | ||
| 238 | |||
| 239 | static int vti4_err(struct sk_buff *skb, u32 info) | ||
| 240 | { | ||
| 241 | __be32 spi; | ||
| 242 | struct xfrm_state *x; | ||
| 243 | struct ip_tunnel *tunnel; | ||
| 244 | struct ip_esp_hdr *esph; | ||
| 245 | struct ip_auth_hdr *ah ; | ||
| 246 | struct ip_comp_hdr *ipch; | ||
| 247 | struct net *net = dev_net(skb->dev); | ||
| 248 | const struct iphdr *iph = (const struct iphdr *)skb->data; | ||
| 249 | int protocol = iph->protocol; | ||
| 250 | struct ip_tunnel_net *itn = net_generic(net, vti_net_id); | ||
| 251 | |||
| 252 | tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY, | ||
| 253 | iph->daddr, iph->saddr, 0); | ||
| 254 | if (!tunnel) | ||
| 255 | return -1; | ||
| 256 | |||
| 257 | switch (protocol) { | ||
| 258 | case IPPROTO_ESP: | ||
| 259 | esph = (struct ip_esp_hdr *)(skb->data+(iph->ihl<<2)); | ||
| 260 | spi = esph->spi; | ||
| 261 | break; | ||
| 262 | case IPPROTO_AH: | ||
| 263 | ah = (struct ip_auth_hdr *)(skb->data+(iph->ihl<<2)); | ||
| 264 | spi = ah->spi; | ||
| 265 | break; | ||
| 266 | case IPPROTO_COMP: | ||
| 267 | ipch = (struct ip_comp_hdr *)(skb->data+(iph->ihl<<2)); | ||
| 268 | spi = htonl(ntohs(ipch->cpi)); | ||
| 269 | break; | ||
| 270 | default: | ||
| 271 | return 0; | ||
| 272 | } | ||
| 273 | |||
| 274 | switch (icmp_hdr(skb)->type) { | ||
| 275 | case ICMP_DEST_UNREACH: | ||
| 276 | if (icmp_hdr(skb)->code != ICMP_FRAG_NEEDED) | ||
| 277 | return 0; | ||
| 278 | case ICMP_REDIRECT: | ||
| 279 | break; | ||
| 280 | default: | ||
| 281 | return 0; | ||
| 282 | } | ||
| 283 | |||
| 284 | x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, | ||
| 285 | spi, protocol, AF_INET); | ||
| 286 | if (!x) | ||
| 287 | return 0; | ||
| 288 | |||
| 289 | if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) | ||
| 290 | ipv4_update_pmtu(skb, net, info, 0, 0, protocol, 0); | ||
| 291 | else | ||
| 292 | ipv4_redirect(skb, net, 0, 0, protocol, 0); | ||
| 293 | xfrm_state_put(x); | ||
| 294 | |||
| 295 | return 0; | ||
| 296 | } | ||
| 297 | |||
| 169 | static int | 298 | static int |
| 170 | vti_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | 299 | vti_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) |
| 171 | { | 300 | { |
| @@ -181,12 +310,13 @@ vti_tunnel_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
| 181 | return -EINVAL; | 310 | return -EINVAL; |
| 182 | } | 311 | } |
| 183 | 312 | ||
| 313 | p.i_flags |= VTI_ISVTI; | ||
| 184 | err = ip_tunnel_ioctl(dev, &p, cmd); | 314 | err = ip_tunnel_ioctl(dev, &p, cmd); |
| 185 | if (err) | 315 | if (err) |
| 186 | return err; | 316 | return err; |
| 187 | 317 | ||
| 188 | if (cmd != SIOCDELTUNNEL) { | 318 | if (cmd != SIOCDELTUNNEL) { |
| 189 | p.i_flags |= GRE_KEY | VTI_ISVTI; | 319 | p.i_flags |= GRE_KEY; |
| 190 | p.o_flags |= GRE_KEY; | 320 | p.o_flags |= GRE_KEY; |
| 191 | } | 321 | } |
| 192 | 322 | ||
| @@ -207,6 +337,7 @@ static const struct net_device_ops vti_netdev_ops = { | |||
| 207 | static void vti_tunnel_setup(struct net_device *dev) | 337 | static void vti_tunnel_setup(struct net_device *dev) |
| 208 | { | 338 | { |
| 209 | dev->netdev_ops = &vti_netdev_ops; | 339 | dev->netdev_ops = &vti_netdev_ops; |
| 340 | dev->type = ARPHRD_TUNNEL; | ||
| 210 | ip_tunnel_setup(dev, vti_net_id); | 341 | ip_tunnel_setup(dev, vti_net_id); |
| 211 | } | 342 | } |
| 212 | 343 | ||
| @@ -218,13 +349,11 @@ static int vti_tunnel_init(struct net_device *dev) | |||
| 218 | memcpy(dev->dev_addr, &iph->saddr, 4); | 349 | memcpy(dev->dev_addr, &iph->saddr, 4); |
| 219 | memcpy(dev->broadcast, &iph->daddr, 4); | 350 | memcpy(dev->broadcast, &iph->daddr, 4); |
| 220 | 351 | ||
| 221 | dev->type = ARPHRD_TUNNEL; | ||
| 222 | dev->hard_header_len = LL_MAX_HEADER + sizeof(struct iphdr); | 352 | dev->hard_header_len = LL_MAX_HEADER + sizeof(struct iphdr); |
| 223 | dev->mtu = ETH_DATA_LEN; | 353 | dev->mtu = ETH_DATA_LEN; |
| 224 | dev->flags = IFF_NOARP; | 354 | dev->flags = IFF_NOARP; |
| 225 | dev->iflink = 0; | 355 | dev->iflink = 0; |
| 226 | dev->addr_len = 4; | 356 | dev->addr_len = 4; |
| 227 | dev->features |= NETIF_F_NETNS_LOCAL; | ||
| 228 | dev->features |= NETIF_F_LLTX; | 357 | dev->features |= NETIF_F_LLTX; |
| 229 | dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; | 358 | dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; |
| 230 | 359 | ||
| @@ -241,9 +370,28 @@ static void __net_init vti_fb_tunnel_init(struct net_device *dev) | |||
| 241 | iph->ihl = 5; | 370 | iph->ihl = 5; |
| 242 | } | 371 | } |
| 243 | 372 | ||
| 244 | static struct xfrm_tunnel_notifier vti_handler __read_mostly = { | 373 | static struct xfrm4_protocol vti_esp4_protocol __read_mostly = { |
| 374 | .handler = vti_rcv, | ||
| 375 | .input_handler = vti_input, | ||
| 376 | .cb_handler = vti_rcv_cb, | ||
| 377 | .err_handler = vti4_err, | ||
| 378 | .priority = 100, | ||
| 379 | }; | ||
| 380 | |||
| 381 | static struct xfrm4_protocol vti_ah4_protocol __read_mostly = { | ||
| 245 | .handler = vti_rcv, | 382 | .handler = vti_rcv, |
| 246 | .priority = 1, | 383 | .input_handler = vti_input, |
| 384 | .cb_handler = vti_rcv_cb, | ||
| 385 | .err_handler = vti4_err, | ||
| 386 | .priority = 100, | ||
| 387 | }; | ||
| 388 | |||
| 389 | static struct xfrm4_protocol vti_ipcomp4_protocol __read_mostly = { | ||
| 390 | .handler = vti_rcv, | ||
| 391 | .input_handler = vti_input, | ||
| 392 | .cb_handler = vti_rcv_cb, | ||
| 393 | .err_handler = vti4_err, | ||
| 394 | .priority = 100, | ||
| 247 | }; | 395 | }; |
| 248 | 396 | ||
| 249 | static int __net_init vti_init_net(struct net *net) | 397 | static int __net_init vti_init_net(struct net *net) |
| @@ -287,6 +435,8 @@ static void vti_netlink_parms(struct nlattr *data[], | |||
| 287 | if (!data) | 435 | if (!data) |
| 288 | return; | 436 | return; |
| 289 | 437 | ||
| 438 | parms->i_flags = VTI_ISVTI; | ||
| 439 | |||
| 290 | if (data[IFLA_VTI_LINK]) | 440 | if (data[IFLA_VTI_LINK]) |
| 291 | parms->link = nla_get_u32(data[IFLA_VTI_LINK]); | 441 | parms->link = nla_get_u32(data[IFLA_VTI_LINK]); |
| 292 | 442 | ||
| @@ -382,10 +532,31 @@ static int __init vti_init(void) | |||
| 382 | err = register_pernet_device(&vti_net_ops); | 532 | err = register_pernet_device(&vti_net_ops); |
| 383 | if (err < 0) | 533 | if (err < 0) |
| 384 | return err; | 534 | return err; |
| 385 | err = xfrm4_mode_tunnel_input_register(&vti_handler); | 535 | err = xfrm4_protocol_register(&vti_esp4_protocol, IPPROTO_ESP); |
| 386 | if (err < 0) { | 536 | if (err < 0) { |
| 387 | unregister_pernet_device(&vti_net_ops); | 537 | unregister_pernet_device(&vti_net_ops); |
| 388 | pr_info("vti init: can't register tunnel\n"); | 538 | pr_info("vti init: can't register tunnel\n"); |
| 539 | |||
| 540 | return err; | ||
| 541 | } | ||
| 542 | |||
| 543 | err = xfrm4_protocol_register(&vti_ah4_protocol, IPPROTO_AH); | ||
| 544 | if (err < 0) { | ||
| 545 | xfrm4_protocol_deregister(&vti_esp4_protocol, IPPROTO_ESP); | ||
| 546 | unregister_pernet_device(&vti_net_ops); | ||
| 547 | pr_info("vti init: can't register tunnel\n"); | ||
| 548 | |||
| 549 | return err; | ||
| 550 | } | ||
| 551 | |||
| 552 | err = xfrm4_protocol_register(&vti_ipcomp4_protocol, IPPROTO_COMP); | ||
| 553 | if (err < 0) { | ||
| 554 | xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH); | ||
| 555 | xfrm4_protocol_deregister(&vti_esp4_protocol, IPPROTO_ESP); | ||
| 556 | unregister_pernet_device(&vti_net_ops); | ||
| 557 | pr_info("vti init: can't register tunnel\n"); | ||
| 558 | |||
| 559 | return err; | ||
| 389 | } | 560 | } |
| 390 | 561 | ||
| 391 | err = rtnl_link_register(&vti_link_ops); | 562 | err = rtnl_link_register(&vti_link_ops); |
| @@ -395,7 +566,9 @@ static int __init vti_init(void) | |||
| 395 | return err; | 566 | return err; |
| 396 | 567 | ||
| 397 | rtnl_link_failed: | 568 | rtnl_link_failed: |
| 398 | xfrm4_mode_tunnel_input_deregister(&vti_handler); | 569 | xfrm4_protocol_deregister(&vti_ipcomp4_protocol, IPPROTO_COMP); |
| 570 | xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH); | ||
| 571 | xfrm4_protocol_deregister(&vti_esp4_protocol, IPPROTO_ESP); | ||
| 399 | unregister_pernet_device(&vti_net_ops); | 572 | unregister_pernet_device(&vti_net_ops); |
| 400 | return err; | 573 | return err; |
| 401 | } | 574 | } |
| @@ -403,8 +576,13 @@ rtnl_link_failed: | |||
| 403 | static void __exit vti_fini(void) | 576 | static void __exit vti_fini(void) |
| 404 | { | 577 | { |
| 405 | rtnl_link_unregister(&vti_link_ops); | 578 | rtnl_link_unregister(&vti_link_ops); |
| 406 | if (xfrm4_mode_tunnel_input_deregister(&vti_handler)) | 579 | if (xfrm4_protocol_deregister(&vti_ipcomp4_protocol, IPPROTO_COMP)) |
| 407 | pr_info("vti close: can't deregister tunnel\n"); | 580 | pr_info("vti close: can't deregister tunnel\n"); |
| 581 | if (xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH)) | ||
| 582 | pr_info("vti close: can't deregister tunnel\n"); | ||
| 583 | if (xfrm4_protocol_deregister(&vti_esp4_protocol, IPPROTO_ESP)) | ||
| 584 | pr_info("vti close: can't deregister tunnel\n"); | ||
| 585 | |||
| 408 | 586 | ||
| 409 | unregister_pernet_device(&vti_net_ops); | 587 | unregister_pernet_device(&vti_net_ops); |
| 410 | } | 588 | } |
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c index 826be4cb482a..c0855d50a3fa 100644 --- a/net/ipv4/ipcomp.c +++ b/net/ipv4/ipcomp.c | |||
| @@ -23,7 +23,7 @@ | |||
| 23 | #include <net/protocol.h> | 23 | #include <net/protocol.h> |
| 24 | #include <net/sock.h> | 24 | #include <net/sock.h> |
| 25 | 25 | ||
| 26 | static void ipcomp4_err(struct sk_buff *skb, u32 info) | 26 | static int ipcomp4_err(struct sk_buff *skb, u32 info) |
| 27 | { | 27 | { |
| 28 | struct net *net = dev_net(skb->dev); | 28 | struct net *net = dev_net(skb->dev); |
| 29 | __be32 spi; | 29 | __be32 spi; |
| @@ -34,24 +34,26 @@ static void ipcomp4_err(struct sk_buff *skb, u32 info) | |||
| 34 | switch (icmp_hdr(skb)->type) { | 34 | switch (icmp_hdr(skb)->type) { |
| 35 | case ICMP_DEST_UNREACH: | 35 | case ICMP_DEST_UNREACH: |
| 36 | if (icmp_hdr(skb)->code != ICMP_FRAG_NEEDED) | 36 | if (icmp_hdr(skb)->code != ICMP_FRAG_NEEDED) |
| 37 | return; | 37 | return 0; |
| 38 | case ICMP_REDIRECT: | 38 | case ICMP_REDIRECT: |
| 39 | break; | 39 | break; |
| 40 | default: | 40 | default: |
| 41 | return; | 41 | return 0; |
| 42 | } | 42 | } |
| 43 | 43 | ||
| 44 | spi = htonl(ntohs(ipch->cpi)); | 44 | spi = htonl(ntohs(ipch->cpi)); |
| 45 | x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, | 45 | x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, |
| 46 | spi, IPPROTO_COMP, AF_INET); | 46 | spi, IPPROTO_COMP, AF_INET); |
| 47 | if (!x) | 47 | if (!x) |
| 48 | return; | 48 | return 0; |
| 49 | 49 | ||
| 50 | if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) | 50 | if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) |
| 51 | ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_COMP, 0); | 51 | ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_COMP, 0); |
| 52 | else | 52 | else |
| 53 | ipv4_redirect(skb, net, 0, 0, IPPROTO_COMP, 0); | 53 | ipv4_redirect(skb, net, 0, 0, IPPROTO_COMP, 0); |
| 54 | xfrm_state_put(x); | 54 | xfrm_state_put(x); |
| 55 | |||
| 56 | return 0; | ||
| 55 | } | 57 | } |
| 56 | 58 | ||
| 57 | /* We always hold one tunnel user reference to indicate a tunnel */ | 59 | /* We always hold one tunnel user reference to indicate a tunnel */ |
| @@ -147,6 +149,11 @@ out: | |||
| 147 | return err; | 149 | return err; |
| 148 | } | 150 | } |
| 149 | 151 | ||
| 152 | static int ipcomp4_rcv_cb(struct sk_buff *skb, int err) | ||
| 153 | { | ||
| 154 | return 0; | ||
| 155 | } | ||
| 156 | |||
| 150 | static const struct xfrm_type ipcomp_type = { | 157 | static const struct xfrm_type ipcomp_type = { |
| 151 | .description = "IPCOMP4", | 158 | .description = "IPCOMP4", |
| 152 | .owner = THIS_MODULE, | 159 | .owner = THIS_MODULE, |
| @@ -157,11 +164,12 @@ static const struct xfrm_type ipcomp_type = { | |||
| 157 | .output = ipcomp_output | 164 | .output = ipcomp_output |
| 158 | }; | 165 | }; |
| 159 | 166 | ||
| 160 | static const struct net_protocol ipcomp4_protocol = { | 167 | static struct xfrm4_protocol ipcomp4_protocol = { |
| 161 | .handler = xfrm4_rcv, | 168 | .handler = xfrm4_rcv, |
| 169 | .input_handler = xfrm_input, | ||
| 170 | .cb_handler = ipcomp4_rcv_cb, | ||
| 162 | .err_handler = ipcomp4_err, | 171 | .err_handler = ipcomp4_err, |
| 163 | .no_policy = 1, | 172 | .priority = 0, |
| 164 | .netns_ok = 1, | ||
| 165 | }; | 173 | }; |
| 166 | 174 | ||
| 167 | static int __init ipcomp4_init(void) | 175 | static int __init ipcomp4_init(void) |
| @@ -170,7 +178,7 @@ static int __init ipcomp4_init(void) | |||
| 170 | pr_info("%s: can't add xfrm type\n", __func__); | 178 | pr_info("%s: can't add xfrm type\n", __func__); |
| 171 | return -EAGAIN; | 179 | return -EAGAIN; |
| 172 | } | 180 | } |
| 173 | if (inet_add_protocol(&ipcomp4_protocol, IPPROTO_COMP) < 0) { | 181 | if (xfrm4_protocol_register(&ipcomp4_protocol, IPPROTO_COMP) < 0) { |
| 174 | pr_info("%s: can't add protocol\n", __func__); | 182 | pr_info("%s: can't add protocol\n", __func__); |
| 175 | xfrm_unregister_type(&ipcomp_type, AF_INET); | 183 | xfrm_unregister_type(&ipcomp_type, AF_INET); |
| 176 | return -EAGAIN; | 184 | return -EAGAIN; |
| @@ -180,7 +188,7 @@ static int __init ipcomp4_init(void) | |||
| 180 | 188 | ||
| 181 | static void __exit ipcomp4_fini(void) | 189 | static void __exit ipcomp4_fini(void) |
| 182 | { | 190 | { |
| 183 | if (inet_del_protocol(&ipcomp4_protocol, IPPROTO_COMP) < 0) | 191 | if (xfrm4_protocol_deregister(&ipcomp4_protocol, IPPROTO_COMP) < 0) |
| 184 | pr_info("%s: can't remove protocol\n", __func__); | 192 | pr_info("%s: can't remove protocol\n", __func__); |
| 185 | if (xfrm_unregister_type(&ipcomp_type, AF_INET) < 0) | 193 | if (xfrm_unregister_type(&ipcomp_type, AF_INET) < 0) |
| 186 | pr_info("%s: can't remove xfrm type\n", __func__); | 194 | pr_info("%s: can't remove xfrm type\n", __func__); |
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c index c3e0adea9c27..7ebd6e37875c 100644 --- a/net/ipv4/netfilter.c +++ b/net/ipv4/netfilter.c | |||
| @@ -61,7 +61,7 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned int addr_type) | |||
| 61 | skb_dst_set(skb, NULL); | 61 | skb_dst_set(skb, NULL); |
| 62 | dst = xfrm_lookup(net, dst, flowi4_to_flowi(&fl4), skb->sk, 0); | 62 | dst = xfrm_lookup(net, dst, flowi4_to_flowi(&fl4), skb->sk, 0); |
| 63 | if (IS_ERR(dst)) | 63 | if (IS_ERR(dst)) |
| 64 | return PTR_ERR(dst);; | 64 | return PTR_ERR(dst); |
| 65 | skb_dst_set(skb, dst); | 65 | skb_dst_set(skb, dst); |
| 66 | } | 66 | } |
| 67 | #endif | 67 | #endif |
diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 59da7cde0724..f95b6f93814b 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c | |||
| @@ -1044,8 +1044,10 @@ static int __do_replace(struct net *net, const char *name, | |||
| 1044 | 1044 | ||
| 1045 | xt_free_table_info(oldinfo); | 1045 | xt_free_table_info(oldinfo); |
| 1046 | if (copy_to_user(counters_ptr, counters, | 1046 | if (copy_to_user(counters_ptr, counters, |
| 1047 | sizeof(struct xt_counters) * num_counters) != 0) | 1047 | sizeof(struct xt_counters) * num_counters) != 0) { |
| 1048 | ret = -EFAULT; | 1048 | /* Silent error, can't fail, new table is already in place */ |
| 1049 | net_warn_ratelimited("arptables: counters copy to user failed while replacing table\n"); | ||
| 1050 | } | ||
| 1049 | vfree(counters); | 1051 | vfree(counters); |
| 1050 | xt_table_unlock(t); | 1052 | xt_table_unlock(t); |
| 1051 | return ret; | 1053 | return ret; |
diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index 718dfbd30cbe..99e810f84671 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c | |||
| @@ -1231,8 +1231,10 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, | |||
| 1231 | 1231 | ||
| 1232 | xt_free_table_info(oldinfo); | 1232 | xt_free_table_info(oldinfo); |
| 1233 | if (copy_to_user(counters_ptr, counters, | 1233 | if (copy_to_user(counters_ptr, counters, |
| 1234 | sizeof(struct xt_counters) * num_counters) != 0) | 1234 | sizeof(struct xt_counters) * num_counters) != 0) { |
| 1235 | ret = -EFAULT; | 1235 | /* Silent error, can't fail, new table is already in place */ |
| 1236 | net_warn_ratelimited("iptables: counters copy to user failed while replacing table\n"); | ||
| 1237 | } | ||
| 1236 | vfree(counters); | 1238 | vfree(counters); |
| 1237 | xt_table_unlock(t); | 1239 | xt_table_unlock(t); |
| 1238 | return ret; | 1240 | return ret; |
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c index 2d11c094296e..8210964a9f19 100644 --- a/net/ipv4/ping.c +++ b/net/ipv4/ping.c | |||
| @@ -252,26 +252,33 @@ int ping_init_sock(struct sock *sk) | |||
| 252 | { | 252 | { |
| 253 | struct net *net = sock_net(sk); | 253 | struct net *net = sock_net(sk); |
| 254 | kgid_t group = current_egid(); | 254 | kgid_t group = current_egid(); |
| 255 | struct group_info *group_info = get_current_groups(); | 255 | struct group_info *group_info; |
| 256 | int i, j, count = group_info->ngroups; | 256 | int i, j, count; |
| 257 | kgid_t low, high; | 257 | kgid_t low, high; |
| 258 | int ret = 0; | ||
| 258 | 259 | ||
| 259 | inet_get_ping_group_range_net(net, &low, &high); | 260 | inet_get_ping_group_range_net(net, &low, &high); |
| 260 | if (gid_lte(low, group) && gid_lte(group, high)) | 261 | if (gid_lte(low, group) && gid_lte(group, high)) |
| 261 | return 0; | 262 | return 0; |
| 262 | 263 | ||
| 264 | group_info = get_current_groups(); | ||
| 265 | count = group_info->ngroups; | ||
| 263 | for (i = 0; i < group_info->nblocks; i++) { | 266 | for (i = 0; i < group_info->nblocks; i++) { |
| 264 | int cp_count = min_t(int, NGROUPS_PER_BLOCK, count); | 267 | int cp_count = min_t(int, NGROUPS_PER_BLOCK, count); |
| 265 | for (j = 0; j < cp_count; j++) { | 268 | for (j = 0; j < cp_count; j++) { |
| 266 | kgid_t gid = group_info->blocks[i][j]; | 269 | kgid_t gid = group_info->blocks[i][j]; |
| 267 | if (gid_lte(low, gid) && gid_lte(gid, high)) | 270 | if (gid_lte(low, gid) && gid_lte(gid, high)) |
| 268 | return 0; | 271 | goto out_release_group; |
| 269 | } | 272 | } |
| 270 | 273 | ||
| 271 | count -= cp_count; | 274 | count -= cp_count; |
| 272 | } | 275 | } |
| 273 | 276 | ||
| 274 | return -EACCES; | 277 | ret = -EACCES; |
| 278 | |||
| 279 | out_release_group: | ||
| 280 | put_group_info(group_info); | ||
| 281 | return ret; | ||
| 275 | } | 282 | } |
| 276 | EXPORT_SYMBOL_GPL(ping_init_sock); | 283 | EXPORT_SYMBOL_GPL(ping_init_sock); |
| 277 | 284 | ||
| @@ -727,7 +734,7 @@ static int ping_v4_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m | |||
| 727 | sock_tx_timestamp(sk, &ipc.tx_flags); | 734 | sock_tx_timestamp(sk, &ipc.tx_flags); |
| 728 | 735 | ||
| 729 | if (msg->msg_controllen) { | 736 | if (msg->msg_controllen) { |
| 730 | err = ip_cmsg_send(sock_net(sk), msg, &ipc); | 737 | err = ip_cmsg_send(sock_net(sk), msg, &ipc, false); |
| 731 | if (err) | 738 | if (err) |
| 732 | return err; | 739 | return err; |
| 733 | if (ipc.opt) | 740 | if (ipc.opt) |
diff --git a/net/ipv4/proc.c b/net/ipv4/proc.c index a6c8a80ec9d6..ad737fad6d8b 100644 --- a/net/ipv4/proc.c +++ b/net/ipv4/proc.c | |||
| @@ -273,6 +273,7 @@ static const struct snmp_mib snmp4_net_list[] = { | |||
| 273 | SNMP_MIB_ITEM("TCPChallengeACK", LINUX_MIB_TCPCHALLENGEACK), | 273 | SNMP_MIB_ITEM("TCPChallengeACK", LINUX_MIB_TCPCHALLENGEACK), |
| 274 | SNMP_MIB_ITEM("TCPSYNChallenge", LINUX_MIB_TCPSYNCHALLENGE), | 274 | SNMP_MIB_ITEM("TCPSYNChallenge", LINUX_MIB_TCPSYNCHALLENGE), |
| 275 | SNMP_MIB_ITEM("TCPFastOpenActive", LINUX_MIB_TCPFASTOPENACTIVE), | 275 | SNMP_MIB_ITEM("TCPFastOpenActive", LINUX_MIB_TCPFASTOPENACTIVE), |
| 276 | SNMP_MIB_ITEM("TCPFastOpenActiveFail", LINUX_MIB_TCPFASTOPENACTIVEFAIL), | ||
| 276 | SNMP_MIB_ITEM("TCPFastOpenPassive", LINUX_MIB_TCPFASTOPENPASSIVE), | 277 | SNMP_MIB_ITEM("TCPFastOpenPassive", LINUX_MIB_TCPFASTOPENPASSIVE), |
| 277 | SNMP_MIB_ITEM("TCPFastOpenPassiveFail", LINUX_MIB_TCPFASTOPENPASSIVEFAIL), | 278 | SNMP_MIB_ITEM("TCPFastOpenPassiveFail", LINUX_MIB_TCPFASTOPENPASSIVEFAIL), |
| 278 | SNMP_MIB_ITEM("TCPFastOpenListenOverflow", LINUX_MIB_TCPFASTOPENLISTENOVERFLOW), | 279 | SNMP_MIB_ITEM("TCPFastOpenListenOverflow", LINUX_MIB_TCPFASTOPENLISTENOVERFLOW), |
| @@ -280,6 +281,11 @@ static const struct snmp_mib snmp4_net_list[] = { | |||
| 280 | SNMP_MIB_ITEM("TCPSpuriousRtxHostQueues", LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES), | 281 | SNMP_MIB_ITEM("TCPSpuriousRtxHostQueues", LINUX_MIB_TCPSPURIOUS_RTX_HOSTQUEUES), |
| 281 | SNMP_MIB_ITEM("BusyPollRxPackets", LINUX_MIB_BUSYPOLLRXPACKETS), | 282 | SNMP_MIB_ITEM("BusyPollRxPackets", LINUX_MIB_BUSYPOLLRXPACKETS), |
| 282 | SNMP_MIB_ITEM("TCPAutoCorking", LINUX_MIB_TCPAUTOCORKING), | 283 | SNMP_MIB_ITEM("TCPAutoCorking", LINUX_MIB_TCPAUTOCORKING), |
| 284 | SNMP_MIB_ITEM("TCPFromZeroWindowAdv", LINUX_MIB_TCPFROMZEROWINDOWADV), | ||
| 285 | SNMP_MIB_ITEM("TCPToZeroWindowAdv", LINUX_MIB_TCPTOZEROWINDOWADV), | ||
| 286 | SNMP_MIB_ITEM("TCPWantZeroWindowAdv", LINUX_MIB_TCPWANTZEROWINDOWADV), | ||
| 287 | SNMP_MIB_ITEM("TCPSynRetrans", LINUX_MIB_TCPSYNRETRANS), | ||
| 288 | SNMP_MIB_ITEM("TCPOrigDataSent", LINUX_MIB_TCPORIGDATASENT), | ||
| 283 | SNMP_MIB_SENTINEL | 289 | SNMP_MIB_SENTINEL |
| 284 | }; | 290 | }; |
| 285 | 291 | ||
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c index c04518f4850a..a9dbe58bdfe7 100644 --- a/net/ipv4/raw.c +++ b/net/ipv4/raw.c | |||
| @@ -524,7 +524,7 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
| 524 | ipc.oif = sk->sk_bound_dev_if; | 524 | ipc.oif = sk->sk_bound_dev_if; |
| 525 | 525 | ||
| 526 | if (msg->msg_controllen) { | 526 | if (msg->msg_controllen) { |
| 527 | err = ip_cmsg_send(sock_net(sk), msg, &ipc); | 527 | err = ip_cmsg_send(sock_net(sk), msg, &ipc, false); |
| 528 | if (err) | 528 | if (err) |
| 529 | goto out; | 529 | goto out; |
| 530 | if (ipc.opt) | 530 | if (ipc.opt) |
diff --git a/net/ipv4/route.c b/net/ipv4/route.c index 4c011ec69ed4..1485aafcad59 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c | |||
| @@ -139,11 +139,6 @@ static void ip_do_redirect(struct dst_entry *dst, struct sock *sk, | |||
| 139 | struct sk_buff *skb); | 139 | struct sk_buff *skb); |
| 140 | static void ipv4_dst_destroy(struct dst_entry *dst); | 140 | static void ipv4_dst_destroy(struct dst_entry *dst); |
| 141 | 141 | ||
| 142 | static void ipv4_dst_ifdown(struct dst_entry *dst, struct net_device *dev, | ||
| 143 | int how) | ||
| 144 | { | ||
| 145 | } | ||
| 146 | |||
| 147 | static u32 *ipv4_cow_metrics(struct dst_entry *dst, unsigned long old) | 142 | static u32 *ipv4_cow_metrics(struct dst_entry *dst, unsigned long old) |
| 148 | { | 143 | { |
| 149 | WARN_ON(1); | 144 | WARN_ON(1); |
| @@ -162,7 +157,6 @@ static struct dst_ops ipv4_dst_ops = { | |||
| 162 | .mtu = ipv4_mtu, | 157 | .mtu = ipv4_mtu, |
| 163 | .cow_metrics = ipv4_cow_metrics, | 158 | .cow_metrics = ipv4_cow_metrics, |
| 164 | .destroy = ipv4_dst_destroy, | 159 | .destroy = ipv4_dst_destroy, |
| 165 | .ifdown = ipv4_dst_ifdown, | ||
| 166 | .negative_advice = ipv4_negative_advice, | 160 | .negative_advice = ipv4_negative_advice, |
| 167 | .link_failure = ipv4_link_failure, | 161 | .link_failure = ipv4_link_failure, |
| 168 | .update_pmtu = ip_rt_update_pmtu, | 162 | .update_pmtu = ip_rt_update_pmtu, |
| @@ -194,7 +188,7 @@ const __u8 ip_tos2prio[16] = { | |||
| 194 | EXPORT_SYMBOL(ip_tos2prio); | 188 | EXPORT_SYMBOL(ip_tos2prio); |
| 195 | 189 | ||
| 196 | static DEFINE_PER_CPU(struct rt_cache_stat, rt_cache_stat); | 190 | static DEFINE_PER_CPU(struct rt_cache_stat, rt_cache_stat); |
| 197 | #define RT_CACHE_STAT_INC(field) __this_cpu_inc(rt_cache_stat.field) | 191 | #define RT_CACHE_STAT_INC(field) raw_cpu_inc(rt_cache_stat.field) |
| 198 | 192 | ||
| 199 | #ifdef CONFIG_PROC_FS | 193 | #ifdef CONFIG_PROC_FS |
| 200 | static void *rt_cache_seq_start(struct seq_file *seq, loff_t *pos) | 194 | static void *rt_cache_seq_start(struct seq_file *seq, loff_t *pos) |
| @@ -697,7 +691,6 @@ static void update_or_create_fnhe(struct fib_nh *nh, __be32 daddr, __be32 gw, | |||
| 697 | 691 | ||
| 698 | out_unlock: | 692 | out_unlock: |
| 699 | spin_unlock_bh(&fnhe_lock); | 693 | spin_unlock_bh(&fnhe_lock); |
| 700 | return; | ||
| 701 | } | 694 | } |
| 702 | 695 | ||
| 703 | static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flowi4 *fl4, | 696 | static void __ip_do_redirect(struct rtable *rt, struct sk_buff *skb, struct flowi4 *fl4, |
| @@ -1136,7 +1129,7 @@ static void ipv4_link_failure(struct sk_buff *skb) | |||
| 1136 | dst_set_expires(&rt->dst, 0); | 1129 | dst_set_expires(&rt->dst, 0); |
| 1137 | } | 1130 | } |
| 1138 | 1131 | ||
| 1139 | static int ip_rt_bug(struct sk_buff *skb) | 1132 | static int ip_rt_bug(struct sock *sk, struct sk_buff *skb) |
| 1140 | { | 1133 | { |
| 1141 | pr_debug("%s: %pI4 -> %pI4, %s\n", | 1134 | pr_debug("%s: %pI4 -> %pI4, %s\n", |
| 1142 | __func__, &ip_hdr(skb)->saddr, &ip_hdr(skb)->daddr, | 1135 | __func__, &ip_hdr(skb)->saddr, &ip_hdr(skb)->daddr, |
| @@ -2225,7 +2218,7 @@ struct dst_entry *ipv4_blackhole_route(struct net *net, struct dst_entry *dst_or | |||
| 2225 | 2218 | ||
| 2226 | new->__use = 1; | 2219 | new->__use = 1; |
| 2227 | new->input = dst_discard; | 2220 | new->input = dst_discard; |
| 2228 | new->output = dst_discard; | 2221 | new->output = dst_discard_sk; |
| 2229 | 2222 | ||
| 2230 | new->dev = ort->dst.dev; | 2223 | new->dev = ort->dst.dev; |
| 2231 | if (new->dev) | 2224 | if (new->dev) |
| @@ -2364,7 +2357,7 @@ static int rt_fill_info(struct net *net, __be32 dst, __be32 src, | |||
| 2364 | } | 2357 | } |
| 2365 | } else | 2358 | } else |
| 2366 | #endif | 2359 | #endif |
| 2367 | if (nla_put_u32(skb, RTA_IIF, rt->rt_iif)) | 2360 | if (nla_put_u32(skb, RTA_IIF, skb->dev->ifindex)) |
| 2368 | goto nla_put_failure; | 2361 | goto nla_put_failure; |
| 2369 | } | 2362 | } |
| 2370 | 2363 | ||
| @@ -2475,11 +2468,6 @@ errout_free: | |||
| 2475 | goto errout; | 2468 | goto errout; |
| 2476 | } | 2469 | } |
| 2477 | 2470 | ||
| 2478 | int ip_rt_dump(struct sk_buff *skb, struct netlink_callback *cb) | ||
| 2479 | { | ||
| 2480 | return skb->len; | ||
| 2481 | } | ||
| 2482 | |||
| 2483 | void ip_rt_multicast_event(struct in_device *in_dev) | 2471 | void ip_rt_multicast_event(struct in_device *in_dev) |
| 2484 | { | 2472 | { |
| 2485 | rt_cache_flush(dev_net(in_dev->dev)); | 2473 | rt_cache_flush(dev_net(in_dev->dev)); |
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c index 97c8f5620c43..4bd6d52eeffb 100644 --- a/net/ipv4/tcp.c +++ b/net/ipv4/tcp.c | |||
| @@ -387,7 +387,7 @@ void tcp_init_sock(struct sock *sk) | |||
| 387 | INIT_LIST_HEAD(&tp->tsq_node); | 387 | INIT_LIST_HEAD(&tp->tsq_node); |
| 388 | 388 | ||
| 389 | icsk->icsk_rto = TCP_TIMEOUT_INIT; | 389 | icsk->icsk_rto = TCP_TIMEOUT_INIT; |
| 390 | tp->mdev = TCP_TIMEOUT_INIT; | 390 | tp->mdev_us = jiffies_to_usecs(TCP_TIMEOUT_INIT); |
| 391 | 391 | ||
| 392 | /* So many TCP implementations out there (incorrectly) count the | 392 | /* So many TCP implementations out there (incorrectly) count the |
| 393 | * initial SYN frame in their delayed-ACK and congestion control | 393 | * initial SYN frame in their delayed-ACK and congestion control |
| @@ -2341,7 +2341,7 @@ int tcp_disconnect(struct sock *sk, int flags) | |||
| 2341 | 2341 | ||
| 2342 | sk->sk_shutdown = 0; | 2342 | sk->sk_shutdown = 0; |
| 2343 | sock_reset_flag(sk, SOCK_DONE); | 2343 | sock_reset_flag(sk, SOCK_DONE); |
| 2344 | tp->srtt = 0; | 2344 | tp->srtt_us = 0; |
| 2345 | if ((tp->write_seq += tp->max_window + 2) == 0) | 2345 | if ((tp->write_seq += tp->max_window + 2) == 0) |
| 2346 | tp->write_seq = 1; | 2346 | tp->write_seq = 1; |
| 2347 | icsk->icsk_backoff = 0; | 2347 | icsk->icsk_backoff = 0; |
| @@ -2785,8 +2785,8 @@ void tcp_get_info(const struct sock *sk, struct tcp_info *info) | |||
| 2785 | 2785 | ||
| 2786 | info->tcpi_pmtu = icsk->icsk_pmtu_cookie; | 2786 | info->tcpi_pmtu = icsk->icsk_pmtu_cookie; |
| 2787 | info->tcpi_rcv_ssthresh = tp->rcv_ssthresh; | 2787 | info->tcpi_rcv_ssthresh = tp->rcv_ssthresh; |
| 2788 | info->tcpi_rtt = jiffies_to_usecs(tp->srtt)>>3; | 2788 | info->tcpi_rtt = tp->srtt_us >> 3; |
| 2789 | info->tcpi_rttvar = jiffies_to_usecs(tp->mdev)>>2; | 2789 | info->tcpi_rttvar = tp->mdev_us >> 2; |
| 2790 | info->tcpi_snd_ssthresh = tp->snd_ssthresh; | 2790 | info->tcpi_snd_ssthresh = tp->snd_ssthresh; |
| 2791 | info->tcpi_snd_cwnd = tp->snd_cwnd; | 2791 | info->tcpi_snd_cwnd = tp->snd_cwnd; |
| 2792 | info->tcpi_advmss = tp->advmss; | 2792 | info->tcpi_advmss = tp->advmss; |
| @@ -2796,6 +2796,11 @@ void tcp_get_info(const struct sock *sk, struct tcp_info *info) | |||
| 2796 | info->tcpi_rcv_space = tp->rcvq_space.space; | 2796 | info->tcpi_rcv_space = tp->rcvq_space.space; |
| 2797 | 2797 | ||
| 2798 | info->tcpi_total_retrans = tp->total_retrans; | 2798 | info->tcpi_total_retrans = tp->total_retrans; |
| 2799 | |||
| 2800 | info->tcpi_pacing_rate = sk->sk_pacing_rate != ~0U ? | ||
| 2801 | sk->sk_pacing_rate : ~0ULL; | ||
| 2802 | info->tcpi_max_pacing_rate = sk->sk_max_pacing_rate != ~0U ? | ||
| 2803 | sk->sk_max_pacing_rate : ~0ULL; | ||
| 2799 | } | 2804 | } |
| 2800 | EXPORT_SYMBOL_GPL(tcp_get_info); | 2805 | EXPORT_SYMBOL_GPL(tcp_get_info); |
| 2801 | 2806 | ||
diff --git a/net/ipv4/tcp_cong.c b/net/ipv4/tcp_cong.c index 2388275adb9b..2b9464c93b88 100644 --- a/net/ipv4/tcp_cong.c +++ b/net/ipv4/tcp_cong.c | |||
| @@ -361,21 +361,12 @@ u32 tcp_reno_ssthresh(struct sock *sk) | |||
| 361 | } | 361 | } |
| 362 | EXPORT_SYMBOL_GPL(tcp_reno_ssthresh); | 362 | EXPORT_SYMBOL_GPL(tcp_reno_ssthresh); |
| 363 | 363 | ||
| 364 | /* Lower bound on congestion window with halving. */ | ||
| 365 | u32 tcp_reno_min_cwnd(const struct sock *sk) | ||
| 366 | { | ||
| 367 | const struct tcp_sock *tp = tcp_sk(sk); | ||
| 368 | return tp->snd_ssthresh/2; | ||
| 369 | } | ||
| 370 | EXPORT_SYMBOL_GPL(tcp_reno_min_cwnd); | ||
| 371 | |||
| 372 | struct tcp_congestion_ops tcp_reno = { | 364 | struct tcp_congestion_ops tcp_reno = { |
| 373 | .flags = TCP_CONG_NON_RESTRICTED, | 365 | .flags = TCP_CONG_NON_RESTRICTED, |
| 374 | .name = "reno", | 366 | .name = "reno", |
| 375 | .owner = THIS_MODULE, | 367 | .owner = THIS_MODULE, |
| 376 | .ssthresh = tcp_reno_ssthresh, | 368 | .ssthresh = tcp_reno_ssthresh, |
| 377 | .cong_avoid = tcp_reno_cong_avoid, | 369 | .cong_avoid = tcp_reno_cong_avoid, |
| 378 | .min_cwnd = tcp_reno_min_cwnd, | ||
| 379 | }; | 370 | }; |
| 380 | 371 | ||
| 381 | /* Initial congestion control used (until SYN) | 372 | /* Initial congestion control used (until SYN) |
| @@ -387,6 +378,5 @@ struct tcp_congestion_ops tcp_init_congestion_ops = { | |||
| 387 | .owner = THIS_MODULE, | 378 | .owner = THIS_MODULE, |
| 388 | .ssthresh = tcp_reno_ssthresh, | 379 | .ssthresh = tcp_reno_ssthresh, |
| 389 | .cong_avoid = tcp_reno_cong_avoid, | 380 | .cong_avoid = tcp_reno_cong_avoid, |
| 390 | .min_cwnd = tcp_reno_min_cwnd, | ||
| 391 | }; | 381 | }; |
| 392 | EXPORT_SYMBOL_GPL(tcp_init_congestion_ops); | 382 | EXPORT_SYMBOL_GPL(tcp_init_congestion_ops); |
diff --git a/net/ipv4/tcp_cubic.c b/net/ipv4/tcp_cubic.c index 828e4c3ffbaf..8bf224516ba2 100644 --- a/net/ipv4/tcp_cubic.c +++ b/net/ipv4/tcp_cubic.c | |||
| @@ -476,10 +476,6 @@ static int __init cubictcp_register(void) | |||
| 476 | /* divide by bic_scale and by constant Srtt (100ms) */ | 476 | /* divide by bic_scale and by constant Srtt (100ms) */ |
| 477 | do_div(cube_factor, bic_scale * 10); | 477 | do_div(cube_factor, bic_scale * 10); |
| 478 | 478 | ||
| 479 | /* hystart needs ms clock resolution */ | ||
| 480 | if (hystart && HZ < 1000) | ||
| 481 | cubictcp.flags |= TCP_CONG_RTT_STAMP; | ||
| 482 | |||
| 483 | return tcp_register_congestion_control(&cubictcp); | 479 | return tcp_register_congestion_control(&cubictcp); |
| 484 | } | 480 | } |
| 485 | 481 | ||
diff --git a/net/ipv4/tcp_highspeed.c b/net/ipv4/tcp_highspeed.c index 8ed9305dfdf4..8b9e7bad77c0 100644 --- a/net/ipv4/tcp_highspeed.c +++ b/net/ipv4/tcp_highspeed.c | |||
| @@ -162,7 +162,6 @@ static struct tcp_congestion_ops tcp_highspeed __read_mostly = { | |||
| 162 | .init = hstcp_init, | 162 | .init = hstcp_init, |
| 163 | .ssthresh = hstcp_ssthresh, | 163 | .ssthresh = hstcp_ssthresh, |
| 164 | .cong_avoid = hstcp_cong_avoid, | 164 | .cong_avoid = hstcp_cong_avoid, |
| 165 | .min_cwnd = tcp_reno_min_cwnd, | ||
| 166 | 165 | ||
| 167 | .owner = THIS_MODULE, | 166 | .owner = THIS_MODULE, |
| 168 | .name = "highspeed" | 167 | .name = "highspeed" |
diff --git a/net/ipv4/tcp_hybla.c b/net/ipv4/tcp_hybla.c index 478fe82611bf..a15a799bf768 100644 --- a/net/ipv4/tcp_hybla.c +++ b/net/ipv4/tcp_hybla.c | |||
| @@ -21,7 +21,7 @@ struct hybla { | |||
| 21 | u32 rho2; /* Rho * Rho, integer part */ | 21 | u32 rho2; /* Rho * Rho, integer part */ |
| 22 | u32 rho_3ls; /* Rho parameter, <<3 */ | 22 | u32 rho_3ls; /* Rho parameter, <<3 */ |
| 23 | u32 rho2_7ls; /* Rho^2, <<7 */ | 23 | u32 rho2_7ls; /* Rho^2, <<7 */ |
| 24 | u32 minrtt; /* Minimum smoothed round trip time value seen */ | 24 | u32 minrtt_us; /* Minimum smoothed round trip time value seen */ |
| 25 | }; | 25 | }; |
| 26 | 26 | ||
| 27 | /* Hybla reference round trip time (default= 1/40 sec = 25 ms), in ms */ | 27 | /* Hybla reference round trip time (default= 1/40 sec = 25 ms), in ms */ |
| @@ -35,7 +35,9 @@ static inline void hybla_recalc_param (struct sock *sk) | |||
| 35 | { | 35 | { |
| 36 | struct hybla *ca = inet_csk_ca(sk); | 36 | struct hybla *ca = inet_csk_ca(sk); |
| 37 | 37 | ||
| 38 | ca->rho_3ls = max_t(u32, tcp_sk(sk)->srtt / msecs_to_jiffies(rtt0), 8); | 38 | ca->rho_3ls = max_t(u32, |
| 39 | tcp_sk(sk)->srtt_us / (rtt0 * USEC_PER_MSEC), | ||
| 40 | 8U); | ||
| 39 | ca->rho = ca->rho_3ls >> 3; | 41 | ca->rho = ca->rho_3ls >> 3; |
| 40 | ca->rho2_7ls = (ca->rho_3ls * ca->rho_3ls) << 1; | 42 | ca->rho2_7ls = (ca->rho_3ls * ca->rho_3ls) << 1; |
| 41 | ca->rho2 = ca->rho2_7ls >> 7; | 43 | ca->rho2 = ca->rho2_7ls >> 7; |
| @@ -59,7 +61,7 @@ static void hybla_init(struct sock *sk) | |||
| 59 | hybla_recalc_param(sk); | 61 | hybla_recalc_param(sk); |
| 60 | 62 | ||
| 61 | /* set minimum rtt as this is the 1st ever seen */ | 63 | /* set minimum rtt as this is the 1st ever seen */ |
| 62 | ca->minrtt = tp->srtt; | 64 | ca->minrtt_us = tp->srtt_us; |
| 63 | tp->snd_cwnd = ca->rho; | 65 | tp->snd_cwnd = ca->rho; |
| 64 | } | 66 | } |
| 65 | 67 | ||
| @@ -94,9 +96,9 @@ static void hybla_cong_avoid(struct sock *sk, u32 ack, u32 acked, | |||
| 94 | int is_slowstart = 0; | 96 | int is_slowstart = 0; |
| 95 | 97 | ||
| 96 | /* Recalculate rho only if this srtt is the lowest */ | 98 | /* Recalculate rho only if this srtt is the lowest */ |
| 97 | if (tp->srtt < ca->minrtt){ | 99 | if (tp->srtt_us < ca->minrtt_us) { |
| 98 | hybla_recalc_param(sk); | 100 | hybla_recalc_param(sk); |
| 99 | ca->minrtt = tp->srtt; | 101 | ca->minrtt_us = tp->srtt_us; |
| 100 | } | 102 | } |
| 101 | 103 | ||
| 102 | if (!tcp_is_cwnd_limited(sk, in_flight)) | 104 | if (!tcp_is_cwnd_limited(sk, in_flight)) |
| @@ -166,7 +168,6 @@ static void hybla_cong_avoid(struct sock *sk, u32 ack, u32 acked, | |||
| 166 | static struct tcp_congestion_ops tcp_hybla __read_mostly = { | 168 | static struct tcp_congestion_ops tcp_hybla __read_mostly = { |
| 167 | .init = hybla_init, | 169 | .init = hybla_init, |
| 168 | .ssthresh = tcp_reno_ssthresh, | 170 | .ssthresh = tcp_reno_ssthresh, |
| 169 | .min_cwnd = tcp_reno_min_cwnd, | ||
| 170 | .cong_avoid = hybla_cong_avoid, | 171 | .cong_avoid = hybla_cong_avoid, |
| 171 | .set_state = hybla_state, | 172 | .set_state = hybla_state, |
| 172 | 173 | ||
diff --git a/net/ipv4/tcp_illinois.c b/net/ipv4/tcp_illinois.c index e498a62b8f97..863d105e3015 100644 --- a/net/ipv4/tcp_illinois.c +++ b/net/ipv4/tcp_illinois.c | |||
| @@ -325,10 +325,8 @@ static void tcp_illinois_info(struct sock *sk, u32 ext, | |||
| 325 | } | 325 | } |
| 326 | 326 | ||
| 327 | static struct tcp_congestion_ops tcp_illinois __read_mostly = { | 327 | static struct tcp_congestion_ops tcp_illinois __read_mostly = { |
| 328 | .flags = TCP_CONG_RTT_STAMP, | ||
| 329 | .init = tcp_illinois_init, | 328 | .init = tcp_illinois_init, |
| 330 | .ssthresh = tcp_illinois_ssthresh, | 329 | .ssthresh = tcp_illinois_ssthresh, |
| 331 | .min_cwnd = tcp_reno_min_cwnd, | ||
| 332 | .cong_avoid = tcp_illinois_cong_avoid, | 330 | .cong_avoid = tcp_illinois_cong_avoid, |
| 333 | .set_state = tcp_illinois_state, | 331 | .set_state = tcp_illinois_state, |
| 334 | .get_info = tcp_illinois_info, | 332 | .get_info = tcp_illinois_info, |
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index eeaac399420d..d6b46eb2f94c 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c | |||
| @@ -667,11 +667,11 @@ static void tcp_event_data_recv(struct sock *sk, struct sk_buff *skb) | |||
| 667 | * To save cycles in the RFC 1323 implementation it was better to break | 667 | * To save cycles in the RFC 1323 implementation it was better to break |
| 668 | * it up into three procedures. -- erics | 668 | * it up into three procedures. -- erics |
| 669 | */ | 669 | */ |
| 670 | static void tcp_rtt_estimator(struct sock *sk, const __u32 mrtt) | 670 | static void tcp_rtt_estimator(struct sock *sk, long mrtt_us) |
| 671 | { | 671 | { |
| 672 | struct tcp_sock *tp = tcp_sk(sk); | 672 | struct tcp_sock *tp = tcp_sk(sk); |
| 673 | long m = mrtt; /* RTT */ | 673 | long m = mrtt_us; /* RTT */ |
| 674 | u32 srtt = tp->srtt; | 674 | u32 srtt = tp->srtt_us; |
| 675 | 675 | ||
| 676 | /* The following amusing code comes from Jacobson's | 676 | /* The following amusing code comes from Jacobson's |
| 677 | * article in SIGCOMM '88. Note that rtt and mdev | 677 | * article in SIGCOMM '88. Note that rtt and mdev |
| @@ -694,7 +694,7 @@ static void tcp_rtt_estimator(struct sock *sk, const __u32 mrtt) | |||
| 694 | srtt += m; /* rtt = 7/8 rtt + 1/8 new */ | 694 | srtt += m; /* rtt = 7/8 rtt + 1/8 new */ |
| 695 | if (m < 0) { | 695 | if (m < 0) { |
| 696 | m = -m; /* m is now abs(error) */ | 696 | m = -m; /* m is now abs(error) */ |
| 697 | m -= (tp->mdev >> 2); /* similar update on mdev */ | 697 | m -= (tp->mdev_us >> 2); /* similar update on mdev */ |
| 698 | /* This is similar to one of Eifel findings. | 698 | /* This is similar to one of Eifel findings. |
| 699 | * Eifel blocks mdev updates when rtt decreases. | 699 | * Eifel blocks mdev updates when rtt decreases. |
| 700 | * This solution is a bit different: we use finer gain | 700 | * This solution is a bit different: we use finer gain |
| @@ -706,28 +706,29 @@ static void tcp_rtt_estimator(struct sock *sk, const __u32 mrtt) | |||
| 706 | if (m > 0) | 706 | if (m > 0) |
| 707 | m >>= 3; | 707 | m >>= 3; |
| 708 | } else { | 708 | } else { |
| 709 | m -= (tp->mdev >> 2); /* similar update on mdev */ | 709 | m -= (tp->mdev_us >> 2); /* similar update on mdev */ |
| 710 | } | 710 | } |
| 711 | tp->mdev += m; /* mdev = 3/4 mdev + 1/4 new */ | 711 | tp->mdev_us += m; /* mdev = 3/4 mdev + 1/4 new */ |
| 712 | if (tp->mdev > tp->mdev_max) { | 712 | if (tp->mdev_us > tp->mdev_max_us) { |
| 713 | tp->mdev_max = tp->mdev; | 713 | tp->mdev_max_us = tp->mdev_us; |
| 714 | if (tp->mdev_max > tp->rttvar) | 714 | if (tp->mdev_max_us > tp->rttvar_us) |
| 715 | tp->rttvar = tp->mdev_max; | 715 | tp->rttvar_us = tp->mdev_max_us; |
| 716 | } | 716 | } |
| 717 | if (after(tp->snd_una, tp->rtt_seq)) { | 717 | if (after(tp->snd_una, tp->rtt_seq)) { |
| 718 | if (tp->mdev_max < tp->rttvar) | 718 | if (tp->mdev_max_us < tp->rttvar_us) |
| 719 | tp->rttvar -= (tp->rttvar - tp->mdev_max) >> 2; | 719 | tp->rttvar_us -= (tp->rttvar_us - tp->mdev_max_us) >> 2; |
| 720 | tp->rtt_seq = tp->snd_nxt; | 720 | tp->rtt_seq = tp->snd_nxt; |
| 721 | tp->mdev_max = tcp_rto_min(sk); | 721 | tp->mdev_max_us = tcp_rto_min_us(sk); |
| 722 | } | 722 | } |
| 723 | } else { | 723 | } else { |
| 724 | /* no previous measure. */ | 724 | /* no previous measure. */ |
| 725 | srtt = m << 3; /* take the measured time to be rtt */ | 725 | srtt = m << 3; /* take the measured time to be rtt */ |
| 726 | tp->mdev = m << 1; /* make sure rto = 3*rtt */ | 726 | tp->mdev_us = m << 1; /* make sure rto = 3*rtt */ |
| 727 | tp->mdev_max = tp->rttvar = max(tp->mdev, tcp_rto_min(sk)); | 727 | tp->rttvar_us = max(tp->mdev_us, tcp_rto_min_us(sk)); |
| 728 | tp->mdev_max_us = tp->rttvar_us; | ||
| 728 | tp->rtt_seq = tp->snd_nxt; | 729 | tp->rtt_seq = tp->snd_nxt; |
| 729 | } | 730 | } |
| 730 | tp->srtt = max(1U, srtt); | 731 | tp->srtt_us = max(1U, srtt); |
| 731 | } | 732 | } |
| 732 | 733 | ||
| 733 | /* Set the sk_pacing_rate to allow proper sizing of TSO packets. | 734 | /* Set the sk_pacing_rate to allow proper sizing of TSO packets. |
| @@ -742,20 +743,12 @@ static void tcp_update_pacing_rate(struct sock *sk) | |||
| 742 | u64 rate; | 743 | u64 rate; |
| 743 | 744 | ||
| 744 | /* set sk_pacing_rate to 200 % of current rate (mss * cwnd / srtt) */ | 745 | /* set sk_pacing_rate to 200 % of current rate (mss * cwnd / srtt) */ |
| 745 | rate = (u64)tp->mss_cache * 2 * (HZ << 3); | 746 | rate = (u64)tp->mss_cache * 2 * (USEC_PER_SEC << 3); |
| 746 | 747 | ||
| 747 | rate *= max(tp->snd_cwnd, tp->packets_out); | 748 | rate *= max(tp->snd_cwnd, tp->packets_out); |
| 748 | 749 | ||
| 749 | /* Correction for small srtt and scheduling constraints. | 750 | if (likely(tp->srtt_us)) |
| 750 | * For small rtt, consider noise is too high, and use | 751 | do_div(rate, tp->srtt_us); |
| 751 | * the minimal value (srtt = 1 -> 125 us for HZ=1000) | ||
| 752 | * | ||
| 753 | * We probably need usec resolution in the future. | ||
| 754 | * Note: This also takes care of possible srtt=0 case, | ||
| 755 | * when tcp_rtt_estimator() was not yet called. | ||
| 756 | */ | ||
| 757 | if (tp->srtt > 8 + 2) | ||
| 758 | do_div(rate, tp->srtt); | ||
| 759 | 752 | ||
| 760 | /* ACCESS_ONCE() is needed because sch_fq fetches sk_pacing_rate | 753 | /* ACCESS_ONCE() is needed because sch_fq fetches sk_pacing_rate |
| 761 | * without any lock. We want to make sure compiler wont store | 754 | * without any lock. We want to make sure compiler wont store |
| @@ -1122,10 +1115,10 @@ static bool tcp_check_dsack(struct sock *sk, const struct sk_buff *ack_skb, | |||
| 1122 | } | 1115 | } |
| 1123 | 1116 | ||
| 1124 | struct tcp_sacktag_state { | 1117 | struct tcp_sacktag_state { |
| 1125 | int reord; | 1118 | int reord; |
| 1126 | int fack_count; | 1119 | int fack_count; |
| 1127 | int flag; | 1120 | long rtt_us; /* RTT measured by SACKing never-retransmitted data */ |
| 1128 | s32 rtt; /* RTT measured by SACKing never-retransmitted data */ | 1121 | int flag; |
| 1129 | }; | 1122 | }; |
| 1130 | 1123 | ||
| 1131 | /* Check if skb is fully within the SACK block. In presence of GSO skbs, | 1124 | /* Check if skb is fully within the SACK block. In presence of GSO skbs, |
| @@ -1186,7 +1179,8 @@ static int tcp_match_skb_to_sack(struct sock *sk, struct sk_buff *skb, | |||
| 1186 | static u8 tcp_sacktag_one(struct sock *sk, | 1179 | static u8 tcp_sacktag_one(struct sock *sk, |
| 1187 | struct tcp_sacktag_state *state, u8 sacked, | 1180 | struct tcp_sacktag_state *state, u8 sacked, |
| 1188 | u32 start_seq, u32 end_seq, | 1181 | u32 start_seq, u32 end_seq, |
| 1189 | int dup_sack, int pcount, u32 xmit_time) | 1182 | int dup_sack, int pcount, |
| 1183 | const struct skb_mstamp *xmit_time) | ||
| 1190 | { | 1184 | { |
| 1191 | struct tcp_sock *tp = tcp_sk(sk); | 1185 | struct tcp_sock *tp = tcp_sk(sk); |
| 1192 | int fack_count = state->fack_count; | 1186 | int fack_count = state->fack_count; |
| @@ -1227,8 +1221,13 @@ static u8 tcp_sacktag_one(struct sock *sk, | |||
| 1227 | if (!after(end_seq, tp->high_seq)) | 1221 | if (!after(end_seq, tp->high_seq)) |
| 1228 | state->flag |= FLAG_ORIG_SACK_ACKED; | 1222 | state->flag |= FLAG_ORIG_SACK_ACKED; |
| 1229 | /* Pick the earliest sequence sacked for RTT */ | 1223 | /* Pick the earliest sequence sacked for RTT */ |
| 1230 | if (state->rtt < 0) | 1224 | if (state->rtt_us < 0) { |
| 1231 | state->rtt = tcp_time_stamp - xmit_time; | 1225 | struct skb_mstamp now; |
| 1226 | |||
| 1227 | skb_mstamp_get(&now); | ||
| 1228 | state->rtt_us = skb_mstamp_us_delta(&now, | ||
| 1229 | xmit_time); | ||
| 1230 | } | ||
| 1232 | } | 1231 | } |
| 1233 | 1232 | ||
| 1234 | if (sacked & TCPCB_LOST) { | 1233 | if (sacked & TCPCB_LOST) { |
| @@ -1287,7 +1286,7 @@ static bool tcp_shifted_skb(struct sock *sk, struct sk_buff *skb, | |||
| 1287 | */ | 1286 | */ |
| 1288 | tcp_sacktag_one(sk, state, TCP_SKB_CB(skb)->sacked, | 1287 | tcp_sacktag_one(sk, state, TCP_SKB_CB(skb)->sacked, |
| 1289 | start_seq, end_seq, dup_sack, pcount, | 1288 | start_seq, end_seq, dup_sack, pcount, |
| 1290 | TCP_SKB_CB(skb)->when); | 1289 | &skb->skb_mstamp); |
| 1291 | 1290 | ||
| 1292 | if (skb == tp->lost_skb_hint) | 1291 | if (skb == tp->lost_skb_hint) |
| 1293 | tp->lost_cnt_hint += pcount; | 1292 | tp->lost_cnt_hint += pcount; |
| @@ -1565,7 +1564,7 @@ static struct sk_buff *tcp_sacktag_walk(struct sk_buff *skb, struct sock *sk, | |||
| 1565 | TCP_SKB_CB(skb)->end_seq, | 1564 | TCP_SKB_CB(skb)->end_seq, |
| 1566 | dup_sack, | 1565 | dup_sack, |
| 1567 | tcp_skb_pcount(skb), | 1566 | tcp_skb_pcount(skb), |
| 1568 | TCP_SKB_CB(skb)->when); | 1567 | &skb->skb_mstamp); |
| 1569 | 1568 | ||
| 1570 | if (!before(TCP_SKB_CB(skb)->seq, | 1569 | if (!before(TCP_SKB_CB(skb)->seq, |
| 1571 | tcp_highest_sack_seq(tp))) | 1570 | tcp_highest_sack_seq(tp))) |
| @@ -1622,7 +1621,7 @@ static int tcp_sack_cache_ok(const struct tcp_sock *tp, const struct tcp_sack_bl | |||
| 1622 | 1621 | ||
| 1623 | static int | 1622 | static int |
| 1624 | tcp_sacktag_write_queue(struct sock *sk, const struct sk_buff *ack_skb, | 1623 | tcp_sacktag_write_queue(struct sock *sk, const struct sk_buff *ack_skb, |
| 1625 | u32 prior_snd_una, s32 *sack_rtt) | 1624 | u32 prior_snd_una, long *sack_rtt_us) |
| 1626 | { | 1625 | { |
| 1627 | struct tcp_sock *tp = tcp_sk(sk); | 1626 | struct tcp_sock *tp = tcp_sk(sk); |
| 1628 | const unsigned char *ptr = (skb_transport_header(ack_skb) + | 1627 | const unsigned char *ptr = (skb_transport_header(ack_skb) + |
| @@ -1640,7 +1639,7 @@ tcp_sacktag_write_queue(struct sock *sk, const struct sk_buff *ack_skb, | |||
| 1640 | 1639 | ||
| 1641 | state.flag = 0; | 1640 | state.flag = 0; |
| 1642 | state.reord = tp->packets_out; | 1641 | state.reord = tp->packets_out; |
| 1643 | state.rtt = -1; | 1642 | state.rtt_us = -1L; |
| 1644 | 1643 | ||
| 1645 | if (!tp->sacked_out) { | 1644 | if (!tp->sacked_out) { |
| 1646 | if (WARN_ON(tp->fackets_out)) | 1645 | if (WARN_ON(tp->fackets_out)) |
| @@ -1824,7 +1823,7 @@ out: | |||
| 1824 | WARN_ON((int)tp->retrans_out < 0); | 1823 | WARN_ON((int)tp->retrans_out < 0); |
| 1825 | WARN_ON((int)tcp_packets_in_flight(tp) < 0); | 1824 | WARN_ON((int)tcp_packets_in_flight(tp) < 0); |
| 1826 | #endif | 1825 | #endif |
| 1827 | *sack_rtt = state.rtt; | 1826 | *sack_rtt_us = state.rtt_us; |
| 1828 | return state.flag; | 1827 | return state.flag; |
| 1829 | } | 1828 | } |
| 1830 | 1829 | ||
| @@ -2035,10 +2034,12 @@ static bool tcp_pause_early_retransmit(struct sock *sk, int flag) | |||
| 2035 | * available, or RTO is scheduled to fire first. | 2034 | * available, or RTO is scheduled to fire first. |
| 2036 | */ | 2035 | */ |
| 2037 | if (sysctl_tcp_early_retrans < 2 || sysctl_tcp_early_retrans > 3 || | 2036 | if (sysctl_tcp_early_retrans < 2 || sysctl_tcp_early_retrans > 3 || |
| 2038 | (flag & FLAG_ECE) || !tp->srtt) | 2037 | (flag & FLAG_ECE) || !tp->srtt_us) |
| 2039 | return false; | 2038 | return false; |
| 2040 | 2039 | ||
| 2041 | delay = max_t(unsigned long, (tp->srtt >> 5), msecs_to_jiffies(2)); | 2040 | delay = max(usecs_to_jiffies(tp->srtt_us >> 5), |
| 2041 | msecs_to_jiffies(2)); | ||
| 2042 | |||
| 2042 | if (!time_after(inet_csk(sk)->icsk_timeout, (jiffies + delay))) | 2043 | if (!time_after(inet_csk(sk)->icsk_timeout, (jiffies + delay))) |
| 2043 | return false; | 2044 | return false; |
| 2044 | 2045 | ||
| @@ -2885,7 +2886,7 @@ static void tcp_fastretrans_alert(struct sock *sk, const int acked, | |||
| 2885 | } | 2886 | } |
| 2886 | 2887 | ||
| 2887 | static inline bool tcp_ack_update_rtt(struct sock *sk, const int flag, | 2888 | static inline bool tcp_ack_update_rtt(struct sock *sk, const int flag, |
| 2888 | s32 seq_rtt, s32 sack_rtt) | 2889 | long seq_rtt_us, long sack_rtt_us) |
| 2889 | { | 2890 | { |
| 2890 | const struct tcp_sock *tp = tcp_sk(sk); | 2891 | const struct tcp_sock *tp = tcp_sk(sk); |
| 2891 | 2892 | ||
| @@ -2895,10 +2896,10 @@ static inline bool tcp_ack_update_rtt(struct sock *sk, const int flag, | |||
| 2895 | * is acked (RFC6298). | 2896 | * is acked (RFC6298). |
| 2896 | */ | 2897 | */ |
| 2897 | if (flag & FLAG_RETRANS_DATA_ACKED) | 2898 | if (flag & FLAG_RETRANS_DATA_ACKED) |
| 2898 | seq_rtt = -1; | 2899 | seq_rtt_us = -1L; |
| 2899 | 2900 | ||
| 2900 | if (seq_rtt < 0) | 2901 | if (seq_rtt_us < 0) |
| 2901 | seq_rtt = sack_rtt; | 2902 | seq_rtt_us = sack_rtt_us; |
| 2902 | 2903 | ||
| 2903 | /* RTTM Rule: A TSecr value received in a segment is used to | 2904 | /* RTTM Rule: A TSecr value received in a segment is used to |
| 2904 | * update the averaged RTT measurement only if the segment | 2905 | * update the averaged RTT measurement only if the segment |
| @@ -2906,14 +2907,14 @@ static inline bool tcp_ack_update_rtt(struct sock *sk, const int flag, | |||
| 2906 | * left edge of the send window. | 2907 | * left edge of the send window. |
| 2907 | * See draft-ietf-tcplw-high-performance-00, section 3.3. | 2908 | * See draft-ietf-tcplw-high-performance-00, section 3.3. |
| 2908 | */ | 2909 | */ |
| 2909 | if (seq_rtt < 0 && tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr && | 2910 | if (seq_rtt_us < 0 && tp->rx_opt.saw_tstamp && tp->rx_opt.rcv_tsecr && |
| 2910 | flag & FLAG_ACKED) | 2911 | flag & FLAG_ACKED) |
| 2911 | seq_rtt = tcp_time_stamp - tp->rx_opt.rcv_tsecr; | 2912 | seq_rtt_us = jiffies_to_usecs(tcp_time_stamp - tp->rx_opt.rcv_tsecr); |
| 2912 | 2913 | ||
| 2913 | if (seq_rtt < 0) | 2914 | if (seq_rtt_us < 0) |
| 2914 | return false; | 2915 | return false; |
| 2915 | 2916 | ||
| 2916 | tcp_rtt_estimator(sk, seq_rtt); | 2917 | tcp_rtt_estimator(sk, seq_rtt_us); |
| 2917 | tcp_set_rto(sk); | 2918 | tcp_set_rto(sk); |
| 2918 | 2919 | ||
| 2919 | /* RFC6298: only reset backoff on valid RTT measurement. */ | 2920 | /* RFC6298: only reset backoff on valid RTT measurement. */ |
| @@ -2925,16 +2926,16 @@ static inline bool tcp_ack_update_rtt(struct sock *sk, const int flag, | |||
| 2925 | static void tcp_synack_rtt_meas(struct sock *sk, const u32 synack_stamp) | 2926 | static void tcp_synack_rtt_meas(struct sock *sk, const u32 synack_stamp) |
| 2926 | { | 2927 | { |
| 2927 | struct tcp_sock *tp = tcp_sk(sk); | 2928 | struct tcp_sock *tp = tcp_sk(sk); |
| 2928 | s32 seq_rtt = -1; | 2929 | long seq_rtt_us = -1L; |
| 2929 | 2930 | ||
| 2930 | if (synack_stamp && !tp->total_retrans) | 2931 | if (synack_stamp && !tp->total_retrans) |
| 2931 | seq_rtt = tcp_time_stamp - synack_stamp; | 2932 | seq_rtt_us = jiffies_to_usecs(tcp_time_stamp - synack_stamp); |
| 2932 | 2933 | ||
| 2933 | /* If the ACK acks both the SYNACK and the (Fast Open'd) data packets | 2934 | /* If the ACK acks both the SYNACK and the (Fast Open'd) data packets |
| 2934 | * sent in SYN_RECV, SYNACK RTT is the smooth RTT computed in tcp_ack() | 2935 | * sent in SYN_RECV, SYNACK RTT is the smooth RTT computed in tcp_ack() |
| 2935 | */ | 2936 | */ |
| 2936 | if (!tp->srtt) | 2937 | if (!tp->srtt_us) |
| 2937 | tcp_ack_update_rtt(sk, FLAG_SYN_ACKED, seq_rtt, -1); | 2938 | tcp_ack_update_rtt(sk, FLAG_SYN_ACKED, seq_rtt_us, -1L); |
| 2938 | } | 2939 | } |
| 2939 | 2940 | ||
| 2940 | static void tcp_cong_avoid(struct sock *sk, u32 ack, u32 acked, u32 in_flight) | 2941 | static void tcp_cong_avoid(struct sock *sk, u32 ack, u32 acked, u32 in_flight) |
| @@ -3023,26 +3024,27 @@ static u32 tcp_tso_acked(struct sock *sk, struct sk_buff *skb) | |||
| 3023 | * arrived at the other end. | 3024 | * arrived at the other end. |
| 3024 | */ | 3025 | */ |
| 3025 | static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets, | 3026 | static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets, |
| 3026 | u32 prior_snd_una, s32 sack_rtt) | 3027 | u32 prior_snd_una, long sack_rtt_us) |
| 3027 | { | 3028 | { |
| 3028 | struct tcp_sock *tp = tcp_sk(sk); | ||
| 3029 | const struct inet_connection_sock *icsk = inet_csk(sk); | 3029 | const struct inet_connection_sock *icsk = inet_csk(sk); |
| 3030 | struct sk_buff *skb; | 3030 | struct skb_mstamp first_ackt, last_ackt, now; |
| 3031 | u32 now = tcp_time_stamp; | 3031 | struct tcp_sock *tp = tcp_sk(sk); |
| 3032 | u32 prior_sacked = tp->sacked_out; | ||
| 3033 | u32 reord = tp->packets_out; | ||
| 3032 | bool fully_acked = true; | 3034 | bool fully_acked = true; |
| 3033 | int flag = 0; | 3035 | long ca_seq_rtt_us = -1L; |
| 3036 | long seq_rtt_us = -1L; | ||
| 3037 | struct sk_buff *skb; | ||
| 3034 | u32 pkts_acked = 0; | 3038 | u32 pkts_acked = 0; |
| 3035 | u32 reord = tp->packets_out; | ||
| 3036 | u32 prior_sacked = tp->sacked_out; | ||
| 3037 | s32 seq_rtt = -1; | ||
| 3038 | s32 ca_seq_rtt = -1; | ||
| 3039 | ktime_t last_ackt = net_invalid_timestamp(); | ||
| 3040 | bool rtt_update; | 3039 | bool rtt_update; |
| 3040 | int flag = 0; | ||
| 3041 | |||
| 3042 | first_ackt.v64 = 0; | ||
| 3041 | 3043 | ||
| 3042 | while ((skb = tcp_write_queue_head(sk)) && skb != tcp_send_head(sk)) { | 3044 | while ((skb = tcp_write_queue_head(sk)) && skb != tcp_send_head(sk)) { |
| 3043 | struct tcp_skb_cb *scb = TCP_SKB_CB(skb); | 3045 | struct tcp_skb_cb *scb = TCP_SKB_CB(skb); |
| 3044 | u32 acked_pcount; | ||
| 3045 | u8 sacked = scb->sacked; | 3046 | u8 sacked = scb->sacked; |
| 3047 | u32 acked_pcount; | ||
| 3046 | 3048 | ||
| 3047 | /* Determine how many packets and what bytes were acked, tso and else */ | 3049 | /* Determine how many packets and what bytes were acked, tso and else */ |
| 3048 | if (after(scb->end_seq, tp->snd_una)) { | 3050 | if (after(scb->end_seq, tp->snd_una)) { |
| @@ -3064,11 +3066,11 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets, | |||
| 3064 | tp->retrans_out -= acked_pcount; | 3066 | tp->retrans_out -= acked_pcount; |
| 3065 | flag |= FLAG_RETRANS_DATA_ACKED; | 3067 | flag |= FLAG_RETRANS_DATA_ACKED; |
| 3066 | } else { | 3068 | } else { |
| 3067 | ca_seq_rtt = now - scb->when; | 3069 | last_ackt = skb->skb_mstamp; |
| 3068 | last_ackt = skb->tstamp; | 3070 | WARN_ON_ONCE(last_ackt.v64 == 0); |
| 3069 | if (seq_rtt < 0) { | 3071 | if (!first_ackt.v64) |
| 3070 | seq_rtt = ca_seq_rtt; | 3072 | first_ackt = last_ackt; |
| 3071 | } | 3073 | |
| 3072 | if (!(sacked & TCPCB_SACKED_ACKED)) | 3074 | if (!(sacked & TCPCB_SACKED_ACKED)) |
| 3073 | reord = min(pkts_acked, reord); | 3075 | reord = min(pkts_acked, reord); |
| 3074 | if (!after(scb->end_seq, tp->high_seq)) | 3076 | if (!after(scb->end_seq, tp->high_seq)) |
| @@ -3114,7 +3116,13 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets, | |||
| 3114 | if (skb && (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)) | 3116 | if (skb && (TCP_SKB_CB(skb)->sacked & TCPCB_SACKED_ACKED)) |
| 3115 | flag |= FLAG_SACK_RENEGING; | 3117 | flag |= FLAG_SACK_RENEGING; |
| 3116 | 3118 | ||
| 3117 | rtt_update = tcp_ack_update_rtt(sk, flag, seq_rtt, sack_rtt); | 3119 | skb_mstamp_get(&now); |
| 3120 | if (first_ackt.v64) { | ||
| 3121 | seq_rtt_us = skb_mstamp_us_delta(&now, &first_ackt); | ||
| 3122 | ca_seq_rtt_us = skb_mstamp_us_delta(&now, &last_ackt); | ||
| 3123 | } | ||
| 3124 | |||
| 3125 | rtt_update = tcp_ack_update_rtt(sk, flag, seq_rtt_us, sack_rtt_us); | ||
| 3118 | 3126 | ||
| 3119 | if (flag & FLAG_ACKED) { | 3127 | if (flag & FLAG_ACKED) { |
| 3120 | const struct tcp_congestion_ops *ca_ops | 3128 | const struct tcp_congestion_ops *ca_ops |
| @@ -3142,25 +3150,11 @@ static int tcp_clean_rtx_queue(struct sock *sk, int prior_fackets, | |||
| 3142 | 3150 | ||
| 3143 | tp->fackets_out -= min(pkts_acked, tp->fackets_out); | 3151 | tp->fackets_out -= min(pkts_acked, tp->fackets_out); |
| 3144 | 3152 | ||
| 3145 | if (ca_ops->pkts_acked) { | 3153 | if (ca_ops->pkts_acked) |
| 3146 | s32 rtt_us = -1; | 3154 | ca_ops->pkts_acked(sk, pkts_acked, ca_seq_rtt_us); |
| 3147 | |||
| 3148 | /* Is the ACK triggering packet unambiguous? */ | ||
| 3149 | if (!(flag & FLAG_RETRANS_DATA_ACKED)) { | ||
| 3150 | /* High resolution needed and available? */ | ||
| 3151 | if (ca_ops->flags & TCP_CONG_RTT_STAMP && | ||
| 3152 | !ktime_equal(last_ackt, | ||
| 3153 | net_invalid_timestamp())) | ||
| 3154 | rtt_us = ktime_us_delta(ktime_get_real(), | ||
| 3155 | last_ackt); | ||
| 3156 | else if (ca_seq_rtt >= 0) | ||
| 3157 | rtt_us = jiffies_to_usecs(ca_seq_rtt); | ||
| 3158 | } | ||
| 3159 | 3155 | ||
| 3160 | ca_ops->pkts_acked(sk, pkts_acked, rtt_us); | 3156 | } else if (skb && rtt_update && sack_rtt_us >= 0 && |
| 3161 | } | 3157 | sack_rtt_us > skb_mstamp_us_delta(&now, &skb->skb_mstamp)) { |
| 3162 | } else if (skb && rtt_update && sack_rtt >= 0 && | ||
| 3163 | sack_rtt > (s32)(now - TCP_SKB_CB(skb)->when)) { | ||
| 3164 | /* Do not re-arm RTO if the sack RTT is measured from data sent | 3158 | /* Do not re-arm RTO if the sack RTT is measured from data sent |
| 3165 | * after when the head was last (re)transmitted. Otherwise the | 3159 | * after when the head was last (re)transmitted. Otherwise the |
| 3166 | * timeout may continue to extend in loss recovery. | 3160 | * timeout may continue to extend in loss recovery. |
| @@ -3370,12 +3364,12 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) | |||
| 3370 | u32 ack_seq = TCP_SKB_CB(skb)->seq; | 3364 | u32 ack_seq = TCP_SKB_CB(skb)->seq; |
| 3371 | u32 ack = TCP_SKB_CB(skb)->ack_seq; | 3365 | u32 ack = TCP_SKB_CB(skb)->ack_seq; |
| 3372 | bool is_dupack = false; | 3366 | bool is_dupack = false; |
| 3373 | u32 prior_in_flight, prior_cwnd = tp->snd_cwnd, prior_rtt = tp->srtt; | 3367 | u32 prior_in_flight; |
| 3374 | u32 prior_fackets; | 3368 | u32 prior_fackets; |
| 3375 | int prior_packets = tp->packets_out; | 3369 | int prior_packets = tp->packets_out; |
| 3376 | const int prior_unsacked = tp->packets_out - tp->sacked_out; | 3370 | const int prior_unsacked = tp->packets_out - tp->sacked_out; |
| 3377 | int acked = 0; /* Number of packets newly acked */ | 3371 | int acked = 0; /* Number of packets newly acked */ |
| 3378 | s32 sack_rtt = -1; | 3372 | long sack_rtt_us = -1L; |
| 3379 | 3373 | ||
| 3380 | /* If the ack is older than previous acks | 3374 | /* If the ack is older than previous acks |
| 3381 | * then we can probably ignore it. | 3375 | * then we can probably ignore it. |
| @@ -3433,7 +3427,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) | |||
| 3433 | 3427 | ||
| 3434 | if (TCP_SKB_CB(skb)->sacked) | 3428 | if (TCP_SKB_CB(skb)->sacked) |
| 3435 | flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una, | 3429 | flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una, |
| 3436 | &sack_rtt); | 3430 | &sack_rtt_us); |
| 3437 | 3431 | ||
| 3438 | if (TCP_ECN_rcv_ecn_echo(tp, tcp_hdr(skb))) | 3432 | if (TCP_ECN_rcv_ecn_echo(tp, tcp_hdr(skb))) |
| 3439 | flag |= FLAG_ECE; | 3433 | flag |= FLAG_ECE; |
| @@ -3452,7 +3446,8 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) | |||
| 3452 | 3446 | ||
| 3453 | /* See if we can take anything off of the retransmit queue. */ | 3447 | /* See if we can take anything off of the retransmit queue. */ |
| 3454 | acked = tp->packets_out; | 3448 | acked = tp->packets_out; |
| 3455 | flag |= tcp_clean_rtx_queue(sk, prior_fackets, prior_snd_una, sack_rtt); | 3449 | flag |= tcp_clean_rtx_queue(sk, prior_fackets, prior_snd_una, |
| 3450 | sack_rtt_us); | ||
| 3456 | acked -= tp->packets_out; | 3451 | acked -= tp->packets_out; |
| 3457 | 3452 | ||
| 3458 | /* Advance cwnd if state allows */ | 3453 | /* Advance cwnd if state allows */ |
| @@ -3475,8 +3470,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) | |||
| 3475 | 3470 | ||
| 3476 | if (icsk->icsk_pending == ICSK_TIME_RETRANS) | 3471 | if (icsk->icsk_pending == ICSK_TIME_RETRANS) |
| 3477 | tcp_schedule_loss_probe(sk); | 3472 | tcp_schedule_loss_probe(sk); |
| 3478 | if (tp->srtt != prior_rtt || tp->snd_cwnd != prior_cwnd) | 3473 | tcp_update_pacing_rate(sk); |
| 3479 | tcp_update_pacing_rate(sk); | ||
| 3480 | return 1; | 3474 | return 1; |
| 3481 | 3475 | ||
| 3482 | no_queue: | 3476 | no_queue: |
| @@ -3505,7 +3499,7 @@ old_ack: | |||
| 3505 | */ | 3499 | */ |
| 3506 | if (TCP_SKB_CB(skb)->sacked) { | 3500 | if (TCP_SKB_CB(skb)->sacked) { |
| 3507 | flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una, | 3501 | flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una, |
| 3508 | &sack_rtt); | 3502 | &sack_rtt_us); |
| 3509 | tcp_fastretrans_alert(sk, acked, prior_unsacked, | 3503 | tcp_fastretrans_alert(sk, acked, prior_unsacked, |
| 3510 | is_dupack, flag); | 3504 | is_dupack, flag); |
| 3511 | } | 3505 | } |
| @@ -4419,7 +4413,7 @@ queue_and_out: | |||
| 4419 | if (eaten > 0) | 4413 | if (eaten > 0) |
| 4420 | kfree_skb_partial(skb, fragstolen); | 4414 | kfree_skb_partial(skb, fragstolen); |
| 4421 | if (!sock_flag(sk, SOCK_DEAD)) | 4415 | if (!sock_flag(sk, SOCK_DEAD)) |
| 4422 | sk->sk_data_ready(sk, 0); | 4416 | sk->sk_data_ready(sk); |
| 4423 | return; | 4417 | return; |
| 4424 | } | 4418 | } |
| 4425 | 4419 | ||
| @@ -4920,7 +4914,7 @@ static void tcp_urg(struct sock *sk, struct sk_buff *skb, const struct tcphdr *t | |||
| 4920 | BUG(); | 4914 | BUG(); |
| 4921 | tp->urg_data = TCP_URG_VALID | tmp; | 4915 | tp->urg_data = TCP_URG_VALID | tmp; |
| 4922 | if (!sock_flag(sk, SOCK_DEAD)) | 4916 | if (!sock_flag(sk, SOCK_DEAD)) |
| 4923 | sk->sk_data_ready(sk, 0); | 4917 | sk->sk_data_ready(sk); |
| 4924 | } | 4918 | } |
| 4925 | } | 4919 | } |
| 4926 | } | 4920 | } |
| @@ -5006,11 +5000,11 @@ static bool tcp_dma_try_early_copy(struct sock *sk, struct sk_buff *skb, | |||
| 5006 | (tcp_flag_word(tcp_hdr(skb)) & TCP_FLAG_PSH) || | 5000 | (tcp_flag_word(tcp_hdr(skb)) & TCP_FLAG_PSH) || |
| 5007 | (atomic_read(&sk->sk_rmem_alloc) > (sk->sk_rcvbuf >> 1))) { | 5001 | (atomic_read(&sk->sk_rmem_alloc) > (sk->sk_rcvbuf >> 1))) { |
| 5008 | tp->ucopy.wakeup = 1; | 5002 | tp->ucopy.wakeup = 1; |
| 5009 | sk->sk_data_ready(sk, 0); | 5003 | sk->sk_data_ready(sk); |
| 5010 | } | 5004 | } |
| 5011 | } else if (chunk > 0) { | 5005 | } else if (chunk > 0) { |
| 5012 | tp->ucopy.wakeup = 1; | 5006 | tp->ucopy.wakeup = 1; |
| 5013 | sk->sk_data_ready(sk, 0); | 5007 | sk->sk_data_ready(sk); |
| 5014 | } | 5008 | } |
| 5015 | out: | 5009 | out: |
| 5016 | return copied_early; | 5010 | return copied_early; |
| @@ -5281,7 +5275,7 @@ no_ack: | |||
| 5281 | #endif | 5275 | #endif |
| 5282 | if (eaten) | 5276 | if (eaten) |
| 5283 | kfree_skb_partial(skb, fragstolen); | 5277 | kfree_skb_partial(skb, fragstolen); |
| 5284 | sk->sk_data_ready(sk, 0); | 5278 | sk->sk_data_ready(sk); |
| 5285 | return; | 5279 | return; |
| 5286 | } | 5280 | } |
| 5287 | } | 5281 | } |
| @@ -5401,9 +5395,12 @@ static bool tcp_rcv_fastopen_synack(struct sock *sk, struct sk_buff *synack, | |||
| 5401 | break; | 5395 | break; |
| 5402 | } | 5396 | } |
| 5403 | tcp_rearm_rto(sk); | 5397 | tcp_rearm_rto(sk); |
| 5398 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPFASTOPENACTIVEFAIL); | ||
| 5404 | return true; | 5399 | return true; |
| 5405 | } | 5400 | } |
| 5406 | tp->syn_data_acked = tp->syn_data; | 5401 | tp->syn_data_acked = tp->syn_data; |
| 5402 | if (tp->syn_data_acked) | ||
| 5403 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPFASTOPENACTIVE); | ||
| 5407 | return false; | 5404 | return false; |
| 5408 | } | 5405 | } |
| 5409 | 5406 | ||
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c index 1e4eac779f51..438f3b95143d 100644 --- a/net/ipv4/tcp_ipv4.c +++ b/net/ipv4/tcp_ipv4.c | |||
| @@ -435,7 +435,7 @@ void tcp_v4_err(struct sk_buff *icmp_skb, u32 info) | |||
| 435 | break; | 435 | break; |
| 436 | 436 | ||
| 437 | icsk->icsk_backoff--; | 437 | icsk->icsk_backoff--; |
| 438 | inet_csk(sk)->icsk_rto = (tp->srtt ? __tcp_set_rto(tp) : | 438 | inet_csk(sk)->icsk_rto = (tp->srtt_us ? __tcp_set_rto(tp) : |
| 439 | TCP_TIMEOUT_INIT) << icsk->icsk_backoff; | 439 | TCP_TIMEOUT_INIT) << icsk->icsk_backoff; |
| 440 | tcp_bound_rto(sk); | 440 | tcp_bound_rto(sk); |
| 441 | 441 | ||
| @@ -854,8 +854,10 @@ static int tcp_v4_rtx_synack(struct sock *sk, struct request_sock *req) | |||
| 854 | { | 854 | { |
| 855 | int res = tcp_v4_send_synack(sk, NULL, req, 0); | 855 | int res = tcp_v4_send_synack(sk, NULL, req, 0); |
| 856 | 856 | ||
| 857 | if (!res) | 857 | if (!res) { |
| 858 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS); | 858 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS); |
| 859 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSYNRETRANS); | ||
| 860 | } | ||
| 859 | return res; | 861 | return res; |
| 860 | } | 862 | } |
| 861 | 863 | ||
| @@ -878,8 +880,6 @@ bool tcp_syn_flood_action(struct sock *sk, | |||
| 878 | bool want_cookie = false; | 880 | bool want_cookie = false; |
| 879 | struct listen_sock *lopt; | 881 | struct listen_sock *lopt; |
| 880 | 882 | ||
| 881 | |||
| 882 | |||
| 883 | #ifdef CONFIG_SYN_COOKIES | 883 | #ifdef CONFIG_SYN_COOKIES |
| 884 | if (sysctl_tcp_syncookies) { | 884 | if (sysctl_tcp_syncookies) { |
| 885 | msg = "Sending cookies"; | 885 | msg = "Sending cookies"; |
| @@ -1434,7 +1434,7 @@ static int tcp_v4_conn_req_fastopen(struct sock *sk, | |||
| 1434 | tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq; | 1434 | tp->rcv_nxt = TCP_SKB_CB(skb)->end_seq; |
| 1435 | tp->syn_data_acked = 1; | 1435 | tp->syn_data_acked = 1; |
| 1436 | } | 1436 | } |
| 1437 | sk->sk_data_ready(sk, 0); | 1437 | sk->sk_data_ready(sk); |
| 1438 | bh_unlock_sock(child); | 1438 | bh_unlock_sock(child); |
| 1439 | sock_put(child); | 1439 | sock_put(child); |
| 1440 | WARN_ON(req->sk == NULL); | 1440 | WARN_ON(req->sk == NULL); |
diff --git a/net/ipv4/tcp_lp.c b/net/ipv4/tcp_lp.c index 991d62a2f9bb..c9aecae31327 100644 --- a/net/ipv4/tcp_lp.c +++ b/net/ipv4/tcp_lp.c | |||
| @@ -315,11 +315,9 @@ static void tcp_lp_pkts_acked(struct sock *sk, u32 num_acked, s32 rtt_us) | |||
| 315 | } | 315 | } |
| 316 | 316 | ||
| 317 | static struct tcp_congestion_ops tcp_lp __read_mostly = { | 317 | static struct tcp_congestion_ops tcp_lp __read_mostly = { |
| 318 | .flags = TCP_CONG_RTT_STAMP, | ||
| 319 | .init = tcp_lp_init, | 318 | .init = tcp_lp_init, |
| 320 | .ssthresh = tcp_reno_ssthresh, | 319 | .ssthresh = tcp_reno_ssthresh, |
| 321 | .cong_avoid = tcp_lp_cong_avoid, | 320 | .cong_avoid = tcp_lp_cong_avoid, |
| 322 | .min_cwnd = tcp_reno_min_cwnd, | ||
| 323 | .pkts_acked = tcp_lp_pkts_acked, | 321 | .pkts_acked = tcp_lp_pkts_acked, |
| 324 | 322 | ||
| 325 | .owner = THIS_MODULE, | 323 | .owner = THIS_MODULE, |
diff --git a/net/ipv4/tcp_memcontrol.c b/net/ipv4/tcp_memcontrol.c index f7e522c558ba..d4f015ad6c84 100644 --- a/net/ipv4/tcp_memcontrol.c +++ b/net/ipv4/tcp_memcontrol.c | |||
| @@ -103,7 +103,7 @@ static int tcp_update_limit(struct mem_cgroup *memcg, u64 val) | |||
| 103 | } | 103 | } |
| 104 | 104 | ||
| 105 | static int tcp_cgroup_write(struct cgroup_subsys_state *css, struct cftype *cft, | 105 | static int tcp_cgroup_write(struct cgroup_subsys_state *css, struct cftype *cft, |
| 106 | const char *buffer) | 106 | char *buffer) |
| 107 | { | 107 | { |
| 108 | struct mem_cgroup *memcg = mem_cgroup_from_css(css); | 108 | struct mem_cgroup *memcg = mem_cgroup_from_css(css); |
| 109 | unsigned long long val; | 109 | unsigned long long val; |
| @@ -219,7 +219,7 @@ static struct cftype tcp_files[] = { | |||
| 219 | 219 | ||
| 220 | static int __init tcp_memcontrol_init(void) | 220 | static int __init tcp_memcontrol_init(void) |
| 221 | { | 221 | { |
| 222 | WARN_ON(cgroup_add_cftypes(&mem_cgroup_subsys, tcp_files)); | 222 | WARN_ON(cgroup_add_cftypes(&memory_cgrp_subsys, tcp_files)); |
| 223 | return 0; | 223 | return 0; |
| 224 | } | 224 | } |
| 225 | __initcall(tcp_memcontrol_init); | 225 | __initcall(tcp_memcontrol_init); |
diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c index d547075d8300..dcaf72f10216 100644 --- a/net/ipv4/tcp_metrics.c +++ b/net/ipv4/tcp_metrics.c | |||
| @@ -33,6 +33,11 @@ struct tcp_fastopen_metrics { | |||
| 33 | struct tcp_fastopen_cookie cookie; | 33 | struct tcp_fastopen_cookie cookie; |
| 34 | }; | 34 | }; |
| 35 | 35 | ||
| 36 | /* TCP_METRIC_MAX includes 2 extra fields for userspace compatibility | ||
| 37 | * Kernel only stores RTT and RTTVAR in usec resolution | ||
| 38 | */ | ||
| 39 | #define TCP_METRIC_MAX_KERNEL (TCP_METRIC_MAX - 2) | ||
| 40 | |||
| 36 | struct tcp_metrics_block { | 41 | struct tcp_metrics_block { |
| 37 | struct tcp_metrics_block __rcu *tcpm_next; | 42 | struct tcp_metrics_block __rcu *tcpm_next; |
| 38 | struct inetpeer_addr tcpm_saddr; | 43 | struct inetpeer_addr tcpm_saddr; |
| @@ -41,7 +46,7 @@ struct tcp_metrics_block { | |||
| 41 | u32 tcpm_ts; | 46 | u32 tcpm_ts; |
| 42 | u32 tcpm_ts_stamp; | 47 | u32 tcpm_ts_stamp; |
| 43 | u32 tcpm_lock; | 48 | u32 tcpm_lock; |
| 44 | u32 tcpm_vals[TCP_METRIC_MAX + 1]; | 49 | u32 tcpm_vals[TCP_METRIC_MAX_KERNEL + 1]; |
| 45 | struct tcp_fastopen_metrics tcpm_fastopen; | 50 | struct tcp_fastopen_metrics tcpm_fastopen; |
| 46 | 51 | ||
| 47 | struct rcu_head rcu_head; | 52 | struct rcu_head rcu_head; |
| @@ -59,12 +64,6 @@ static u32 tcp_metric_get(struct tcp_metrics_block *tm, | |||
| 59 | return tm->tcpm_vals[idx]; | 64 | return tm->tcpm_vals[idx]; |
| 60 | } | 65 | } |
| 61 | 66 | ||
| 62 | static u32 tcp_metric_get_jiffies(struct tcp_metrics_block *tm, | ||
| 63 | enum tcp_metric_index idx) | ||
| 64 | { | ||
| 65 | return msecs_to_jiffies(tm->tcpm_vals[idx]); | ||
| 66 | } | ||
| 67 | |||
| 68 | static void tcp_metric_set(struct tcp_metrics_block *tm, | 67 | static void tcp_metric_set(struct tcp_metrics_block *tm, |
| 69 | enum tcp_metric_index idx, | 68 | enum tcp_metric_index idx, |
| 70 | u32 val) | 69 | u32 val) |
| @@ -72,13 +71,6 @@ static void tcp_metric_set(struct tcp_metrics_block *tm, | |||
| 72 | tm->tcpm_vals[idx] = val; | 71 | tm->tcpm_vals[idx] = val; |
| 73 | } | 72 | } |
| 74 | 73 | ||
| 75 | static void tcp_metric_set_msecs(struct tcp_metrics_block *tm, | ||
| 76 | enum tcp_metric_index idx, | ||
| 77 | u32 val) | ||
| 78 | { | ||
| 79 | tm->tcpm_vals[idx] = jiffies_to_msecs(val); | ||
| 80 | } | ||
| 81 | |||
| 82 | static bool addr_same(const struct inetpeer_addr *a, | 74 | static bool addr_same(const struct inetpeer_addr *a, |
| 83 | const struct inetpeer_addr *b) | 75 | const struct inetpeer_addr *b) |
| 84 | { | 76 | { |
| @@ -101,9 +93,11 @@ struct tcpm_hash_bucket { | |||
| 101 | 93 | ||
| 102 | static DEFINE_SPINLOCK(tcp_metrics_lock); | 94 | static DEFINE_SPINLOCK(tcp_metrics_lock); |
| 103 | 95 | ||
| 104 | static void tcpm_suck_dst(struct tcp_metrics_block *tm, struct dst_entry *dst, | 96 | static void tcpm_suck_dst(struct tcp_metrics_block *tm, |
| 97 | const struct dst_entry *dst, | ||
| 105 | bool fastopen_clear) | 98 | bool fastopen_clear) |
| 106 | { | 99 | { |
| 100 | u32 msval; | ||
| 107 | u32 val; | 101 | u32 val; |
| 108 | 102 | ||
| 109 | tm->tcpm_stamp = jiffies; | 103 | tm->tcpm_stamp = jiffies; |
| @@ -121,8 +115,11 @@ static void tcpm_suck_dst(struct tcp_metrics_block *tm, struct dst_entry *dst, | |||
| 121 | val |= 1 << TCP_METRIC_REORDERING; | 115 | val |= 1 << TCP_METRIC_REORDERING; |
| 122 | tm->tcpm_lock = val; | 116 | tm->tcpm_lock = val; |
| 123 | 117 | ||
| 124 | tm->tcpm_vals[TCP_METRIC_RTT] = dst_metric_raw(dst, RTAX_RTT); | 118 | msval = dst_metric_raw(dst, RTAX_RTT); |
| 125 | tm->tcpm_vals[TCP_METRIC_RTTVAR] = dst_metric_raw(dst, RTAX_RTTVAR); | 119 | tm->tcpm_vals[TCP_METRIC_RTT] = msval * USEC_PER_MSEC; |
| 120 | |||
| 121 | msval = dst_metric_raw(dst, RTAX_RTTVAR); | ||
| 122 | tm->tcpm_vals[TCP_METRIC_RTTVAR] = msval * USEC_PER_MSEC; | ||
| 126 | tm->tcpm_vals[TCP_METRIC_SSTHRESH] = dst_metric_raw(dst, RTAX_SSTHRESH); | 123 | tm->tcpm_vals[TCP_METRIC_SSTHRESH] = dst_metric_raw(dst, RTAX_SSTHRESH); |
| 127 | tm->tcpm_vals[TCP_METRIC_CWND] = dst_metric_raw(dst, RTAX_CWND); | 124 | tm->tcpm_vals[TCP_METRIC_CWND] = dst_metric_raw(dst, RTAX_CWND); |
| 128 | tm->tcpm_vals[TCP_METRIC_REORDERING] = dst_metric_raw(dst, RTAX_REORDERING); | 125 | tm->tcpm_vals[TCP_METRIC_REORDERING] = dst_metric_raw(dst, RTAX_REORDERING); |
| @@ -384,7 +381,7 @@ void tcp_update_metrics(struct sock *sk) | |||
| 384 | dst_confirm(dst); | 381 | dst_confirm(dst); |
| 385 | 382 | ||
| 386 | rcu_read_lock(); | 383 | rcu_read_lock(); |
| 387 | if (icsk->icsk_backoff || !tp->srtt) { | 384 | if (icsk->icsk_backoff || !tp->srtt_us) { |
| 388 | /* This session failed to estimate rtt. Why? | 385 | /* This session failed to estimate rtt. Why? |
| 389 | * Probably, no packets returned in time. Reset our | 386 | * Probably, no packets returned in time. Reset our |
| 390 | * results. | 387 | * results. |
| @@ -399,8 +396,8 @@ void tcp_update_metrics(struct sock *sk) | |||
| 399 | if (!tm) | 396 | if (!tm) |
| 400 | goto out_unlock; | 397 | goto out_unlock; |
| 401 | 398 | ||
| 402 | rtt = tcp_metric_get_jiffies(tm, TCP_METRIC_RTT); | 399 | rtt = tcp_metric_get(tm, TCP_METRIC_RTT); |
| 403 | m = rtt - tp->srtt; | 400 | m = rtt - tp->srtt_us; |
| 404 | 401 | ||
| 405 | /* If newly calculated rtt larger than stored one, store new | 402 | /* If newly calculated rtt larger than stored one, store new |
| 406 | * one. Otherwise, use EWMA. Remember, rtt overestimation is | 403 | * one. Otherwise, use EWMA. Remember, rtt overestimation is |
| @@ -408,10 +405,10 @@ void tcp_update_metrics(struct sock *sk) | |||
| 408 | */ | 405 | */ |
| 409 | if (!tcp_metric_locked(tm, TCP_METRIC_RTT)) { | 406 | if (!tcp_metric_locked(tm, TCP_METRIC_RTT)) { |
| 410 | if (m <= 0) | 407 | if (m <= 0) |
| 411 | rtt = tp->srtt; | 408 | rtt = tp->srtt_us; |
| 412 | else | 409 | else |
| 413 | rtt -= (m >> 3); | 410 | rtt -= (m >> 3); |
| 414 | tcp_metric_set_msecs(tm, TCP_METRIC_RTT, rtt); | 411 | tcp_metric_set(tm, TCP_METRIC_RTT, rtt); |
| 415 | } | 412 | } |
| 416 | 413 | ||
| 417 | if (!tcp_metric_locked(tm, TCP_METRIC_RTTVAR)) { | 414 | if (!tcp_metric_locked(tm, TCP_METRIC_RTTVAR)) { |
| @@ -422,16 +419,16 @@ void tcp_update_metrics(struct sock *sk) | |||
| 422 | 419 | ||
| 423 | /* Scale deviation to rttvar fixed point */ | 420 | /* Scale deviation to rttvar fixed point */ |
| 424 | m >>= 1; | 421 | m >>= 1; |
| 425 | if (m < tp->mdev) | 422 | if (m < tp->mdev_us) |
| 426 | m = tp->mdev; | 423 | m = tp->mdev_us; |
| 427 | 424 | ||
| 428 | var = tcp_metric_get_jiffies(tm, TCP_METRIC_RTTVAR); | 425 | var = tcp_metric_get(tm, TCP_METRIC_RTTVAR); |
| 429 | if (m >= var) | 426 | if (m >= var) |
| 430 | var = m; | 427 | var = m; |
| 431 | else | 428 | else |
| 432 | var -= (var - m) >> 2; | 429 | var -= (var - m) >> 2; |
| 433 | 430 | ||
| 434 | tcp_metric_set_msecs(tm, TCP_METRIC_RTTVAR, var); | 431 | tcp_metric_set(tm, TCP_METRIC_RTTVAR, var); |
| 435 | } | 432 | } |
| 436 | 433 | ||
| 437 | if (tcp_in_initial_slowstart(tp)) { | 434 | if (tcp_in_initial_slowstart(tp)) { |
| @@ -528,7 +525,7 @@ void tcp_init_metrics(struct sock *sk) | |||
| 528 | tp->reordering = val; | 525 | tp->reordering = val; |
| 529 | } | 526 | } |
| 530 | 527 | ||
| 531 | crtt = tcp_metric_get_jiffies(tm, TCP_METRIC_RTT); | 528 | crtt = tcp_metric_get(tm, TCP_METRIC_RTT); |
| 532 | rcu_read_unlock(); | 529 | rcu_read_unlock(); |
| 533 | reset: | 530 | reset: |
| 534 | /* The initial RTT measurement from the SYN/SYN-ACK is not ideal | 531 | /* The initial RTT measurement from the SYN/SYN-ACK is not ideal |
| @@ -551,18 +548,20 @@ reset: | |||
| 551 | * to low value, and then abruptly stops to do it and starts to delay | 548 | * to low value, and then abruptly stops to do it and starts to delay |
| 552 | * ACKs, wait for troubles. | 549 | * ACKs, wait for troubles. |
| 553 | */ | 550 | */ |
| 554 | if (crtt > tp->srtt) { | 551 | if (crtt > tp->srtt_us) { |
| 555 | /* Set RTO like tcp_rtt_estimator(), but from cached RTT. */ | 552 | /* Set RTO like tcp_rtt_estimator(), but from cached RTT. */ |
| 556 | crtt >>= 3; | 553 | crtt /= 8 * USEC_PER_MSEC; |
| 557 | inet_csk(sk)->icsk_rto = crtt + max(2 * crtt, tcp_rto_min(sk)); | 554 | inet_csk(sk)->icsk_rto = crtt + max(2 * crtt, tcp_rto_min(sk)); |
| 558 | } else if (tp->srtt == 0) { | 555 | } else if (tp->srtt_us == 0) { |
| 559 | /* RFC6298: 5.7 We've failed to get a valid RTT sample from | 556 | /* RFC6298: 5.7 We've failed to get a valid RTT sample from |
| 560 | * 3WHS. This is most likely due to retransmission, | 557 | * 3WHS. This is most likely due to retransmission, |
| 561 | * including spurious one. Reset the RTO back to 3secs | 558 | * including spurious one. Reset the RTO back to 3secs |
| 562 | * from the more aggressive 1sec to avoid more spurious | 559 | * from the more aggressive 1sec to avoid more spurious |
| 563 | * retransmission. | 560 | * retransmission. |
| 564 | */ | 561 | */ |
| 565 | tp->mdev = tp->mdev_max = tp->rttvar = TCP_TIMEOUT_FALLBACK; | 562 | tp->rttvar_us = jiffies_to_usecs(TCP_TIMEOUT_FALLBACK); |
| 563 | tp->mdev_us = tp->mdev_max_us = tp->rttvar_us; | ||
| 564 | |||
| 566 | inet_csk(sk)->icsk_rto = TCP_TIMEOUT_FALLBACK; | 565 | inet_csk(sk)->icsk_rto = TCP_TIMEOUT_FALLBACK; |
| 567 | } | 566 | } |
| 568 | /* Cut cwnd down to 1 per RFC5681 if SYN or SYN-ACK has been | 567 | /* Cut cwnd down to 1 per RFC5681 if SYN or SYN-ACK has been |
| @@ -809,10 +808,26 @@ static int tcp_metrics_fill_info(struct sk_buff *msg, | |||
| 809 | nest = nla_nest_start(msg, TCP_METRICS_ATTR_VALS); | 808 | nest = nla_nest_start(msg, TCP_METRICS_ATTR_VALS); |
| 810 | if (!nest) | 809 | if (!nest) |
| 811 | goto nla_put_failure; | 810 | goto nla_put_failure; |
| 812 | for (i = 0; i < TCP_METRIC_MAX + 1; i++) { | 811 | for (i = 0; i < TCP_METRIC_MAX_KERNEL + 1; i++) { |
| 813 | if (!tm->tcpm_vals[i]) | 812 | u32 val = tm->tcpm_vals[i]; |
| 813 | |||
| 814 | if (!val) | ||
| 814 | continue; | 815 | continue; |
| 815 | if (nla_put_u32(msg, i + 1, tm->tcpm_vals[i]) < 0) | 816 | if (i == TCP_METRIC_RTT) { |
| 817 | if (nla_put_u32(msg, TCP_METRIC_RTT_US + 1, | ||
| 818 | val) < 0) | ||
| 819 | goto nla_put_failure; | ||
| 820 | n++; | ||
| 821 | val = max(val / 1000, 1U); | ||
| 822 | } | ||
| 823 | if (i == TCP_METRIC_RTTVAR) { | ||
| 824 | if (nla_put_u32(msg, TCP_METRIC_RTTVAR_US + 1, | ||
| 825 | val) < 0) | ||
| 826 | goto nla_put_failure; | ||
| 827 | n++; | ||
| 828 | val = max(val / 1000, 1U); | ||
| 829 | } | ||
| 830 | if (nla_put_u32(msg, i + 1, val) < 0) | ||
| 816 | goto nla_put_failure; | 831 | goto nla_put_failure; |
| 817 | n++; | 832 | n++; |
| 818 | } | 833 | } |
diff --git a/net/ipv4/tcp_minisocks.c b/net/ipv4/tcp_minisocks.c index 7a436c517e44..05c1b155251d 100644 --- a/net/ipv4/tcp_minisocks.c +++ b/net/ipv4/tcp_minisocks.c | |||
| @@ -398,8 +398,8 @@ struct sock *tcp_create_openreq_child(struct sock *sk, struct request_sock *req, | |||
| 398 | 398 | ||
| 399 | tcp_init_wl(newtp, treq->rcv_isn); | 399 | tcp_init_wl(newtp, treq->rcv_isn); |
| 400 | 400 | ||
| 401 | newtp->srtt = 0; | 401 | newtp->srtt_us = 0; |
| 402 | newtp->mdev = TCP_TIMEOUT_INIT; | 402 | newtp->mdev_us = jiffies_to_usecs(TCP_TIMEOUT_INIT); |
| 403 | newicsk->icsk_rto = TCP_TIMEOUT_INIT; | 403 | newicsk->icsk_rto = TCP_TIMEOUT_INIT; |
| 404 | 404 | ||
| 405 | newtp->packets_out = 0; | 405 | newtp->packets_out = 0; |
| @@ -745,7 +745,7 @@ int tcp_child_process(struct sock *parent, struct sock *child, | |||
| 745 | skb->len); | 745 | skb->len); |
| 746 | /* Wakeup parent, send SIGIO */ | 746 | /* Wakeup parent, send SIGIO */ |
| 747 | if (state == TCP_SYN_RECV && child->sk_state != state) | 747 | if (state == TCP_SYN_RECV && child->sk_state != state) |
| 748 | parent->sk_data_ready(parent, 0); | 748 | parent->sk_data_ready(parent); |
| 749 | } else { | 749 | } else { |
| 750 | /* Alas, it is possible again, because we do lookup | 750 | /* Alas, it is possible again, because we do lookup |
| 751 | * in main socket hash table and lock on listening | 751 | * in main socket hash table and lock on listening |
diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 17a11e65e57f..025e25093984 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c | |||
| @@ -86,6 +86,9 @@ static void tcp_event_new_data_sent(struct sock *sk, const struct sk_buff *skb) | |||
| 86 | icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) { | 86 | icsk->icsk_pending == ICSK_TIME_LOSS_PROBE) { |
| 87 | tcp_rearm_rto(sk); | 87 | tcp_rearm_rto(sk); |
| 88 | } | 88 | } |
| 89 | |||
| 90 | NET_ADD_STATS(sock_net(sk), LINUX_MIB_TCPORIGDATASENT, | ||
| 91 | tcp_skb_pcount(skb)); | ||
| 89 | } | 92 | } |
| 90 | 93 | ||
| 91 | /* SND.NXT, if window was not shrunk. | 94 | /* SND.NXT, if window was not shrunk. |
| @@ -269,6 +272,7 @@ EXPORT_SYMBOL(tcp_select_initial_window); | |||
| 269 | static u16 tcp_select_window(struct sock *sk) | 272 | static u16 tcp_select_window(struct sock *sk) |
| 270 | { | 273 | { |
| 271 | struct tcp_sock *tp = tcp_sk(sk); | 274 | struct tcp_sock *tp = tcp_sk(sk); |
| 275 | u32 old_win = tp->rcv_wnd; | ||
| 272 | u32 cur_win = tcp_receive_window(tp); | 276 | u32 cur_win = tcp_receive_window(tp); |
| 273 | u32 new_win = __tcp_select_window(sk); | 277 | u32 new_win = __tcp_select_window(sk); |
| 274 | 278 | ||
| @@ -281,6 +285,9 @@ static u16 tcp_select_window(struct sock *sk) | |||
| 281 | * | 285 | * |
| 282 | * Relax Will Robinson. | 286 | * Relax Will Robinson. |
| 283 | */ | 287 | */ |
| 288 | if (new_win == 0) | ||
| 289 | NET_INC_STATS(sock_net(sk), | ||
| 290 | LINUX_MIB_TCPWANTZEROWINDOWADV); | ||
| 284 | new_win = ALIGN(cur_win, 1 << tp->rx_opt.rcv_wscale); | 291 | new_win = ALIGN(cur_win, 1 << tp->rx_opt.rcv_wscale); |
| 285 | } | 292 | } |
| 286 | tp->rcv_wnd = new_win; | 293 | tp->rcv_wnd = new_win; |
| @@ -298,8 +305,14 @@ static u16 tcp_select_window(struct sock *sk) | |||
| 298 | new_win >>= tp->rx_opt.rcv_wscale; | 305 | new_win >>= tp->rx_opt.rcv_wscale; |
| 299 | 306 | ||
| 300 | /* If we advertise zero window, disable fast path. */ | 307 | /* If we advertise zero window, disable fast path. */ |
| 301 | if (new_win == 0) | 308 | if (new_win == 0) { |
| 302 | tp->pred_flags = 0; | 309 | tp->pred_flags = 0; |
| 310 | if (old_win) | ||
| 311 | NET_INC_STATS(sock_net(sk), | ||
| 312 | LINUX_MIB_TCPTOZEROWINDOWADV); | ||
| 313 | } else if (old_win == 0) { | ||
| 314 | NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPFROMZEROWINDOWADV); | ||
| 315 | } | ||
| 303 | 316 | ||
| 304 | return new_win; | 317 | return new_win; |
| 305 | } | 318 | } |
| @@ -867,11 +880,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, | |||
| 867 | if (clone_it) { | 880 | if (clone_it) { |
| 868 | const struct sk_buff *fclone = skb + 1; | 881 | const struct sk_buff *fclone = skb + 1; |
| 869 | 882 | ||
| 870 | /* If congestion control is doing timestamping, we must | 883 | skb_mstamp_get(&skb->skb_mstamp); |
| 871 | * take such a timestamp before we potentially clone/copy. | ||
| 872 | */ | ||
| 873 | if (icsk->icsk_ca_ops->flags & TCP_CONG_RTT_STAMP) | ||
| 874 | __net_timestamp(skb); | ||
| 875 | 884 | ||
| 876 | if (unlikely(skb->fclone == SKB_FCLONE_ORIG && | 885 | if (unlikely(skb->fclone == SKB_FCLONE_ORIG && |
| 877 | fclone->fclone == SKB_FCLONE_CLONE)) | 886 | fclone->fclone == SKB_FCLONE_CLONE)) |
| @@ -884,6 +893,8 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, | |||
| 884 | skb = skb_clone(skb, gfp_mask); | 893 | skb = skb_clone(skb, gfp_mask); |
| 885 | if (unlikely(!skb)) | 894 | if (unlikely(!skb)) |
| 886 | return -ENOBUFS; | 895 | return -ENOBUFS; |
| 896 | /* Our usage of tstamp should remain private */ | ||
| 897 | skb->tstamp.tv64 = 0; | ||
| 887 | } | 898 | } |
| 888 | 899 | ||
| 889 | inet = inet_sk(sk); | 900 | inet = inet_sk(sk); |
| @@ -970,7 +981,7 @@ static int tcp_transmit_skb(struct sock *sk, struct sk_buff *skb, int clone_it, | |||
| 970 | TCP_ADD_STATS(sock_net(sk), TCP_MIB_OUTSEGS, | 981 | TCP_ADD_STATS(sock_net(sk), TCP_MIB_OUTSEGS, |
| 971 | tcp_skb_pcount(skb)); | 982 | tcp_skb_pcount(skb)); |
| 972 | 983 | ||
| 973 | err = icsk->icsk_af_ops->queue_xmit(skb, &inet->cork.fl); | 984 | err = icsk->icsk_af_ops->queue_xmit(sk, skb, &inet->cork.fl); |
| 974 | if (likely(err <= 0)) | 985 | if (likely(err <= 0)) |
| 975 | return err; | 986 | return err; |
| 976 | 987 | ||
| @@ -1426,7 +1437,7 @@ static void tcp_minshall_update(struct tcp_sock *tp, unsigned int mss_now, | |||
| 1426 | * With Minshall's modification: all sent small packets are ACKed. | 1437 | * With Minshall's modification: all sent small packets are ACKed. |
| 1427 | */ | 1438 | */ |
| 1428 | static bool tcp_nagle_check(bool partial, const struct tcp_sock *tp, | 1439 | static bool tcp_nagle_check(bool partial, const struct tcp_sock *tp, |
| 1429 | unsigned int mss_now, int nonagle) | 1440 | int nonagle) |
| 1430 | { | 1441 | { |
| 1431 | return partial && | 1442 | return partial && |
| 1432 | ((nonagle & TCP_NAGLE_CORK) || | 1443 | ((nonagle & TCP_NAGLE_CORK) || |
| @@ -1458,7 +1469,7 @@ static unsigned int tcp_mss_split_point(const struct sock *sk, | |||
| 1458 | * to include this last segment in this skb. | 1469 | * to include this last segment in this skb. |
| 1459 | * Otherwise, we'll split the skb at last MSS boundary | 1470 | * Otherwise, we'll split the skb at last MSS boundary |
| 1460 | */ | 1471 | */ |
| 1461 | if (tcp_nagle_check(partial != 0, tp, mss_now, nonagle)) | 1472 | if (tcp_nagle_check(partial != 0, tp, nonagle)) |
| 1462 | return needed - partial; | 1473 | return needed - partial; |
| 1463 | 1474 | ||
| 1464 | return needed; | 1475 | return needed; |
| @@ -1521,7 +1532,7 @@ static inline bool tcp_nagle_test(const struct tcp_sock *tp, const struct sk_buf | |||
| 1521 | if (tcp_urg_mode(tp) || (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN)) | 1532 | if (tcp_urg_mode(tp) || (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_FIN)) |
| 1522 | return true; | 1533 | return true; |
| 1523 | 1534 | ||
| 1524 | if (!tcp_nagle_check(skb->len < cur_mss, tp, cur_mss, nonagle)) | 1535 | if (!tcp_nagle_check(skb->len < cur_mss, tp, nonagle)) |
| 1525 | return true; | 1536 | return true; |
| 1526 | 1537 | ||
| 1527 | return false; | 1538 | return false; |
| @@ -1975,7 +1986,7 @@ bool tcp_schedule_loss_probe(struct sock *sk) | |||
| 1975 | struct inet_connection_sock *icsk = inet_csk(sk); | 1986 | struct inet_connection_sock *icsk = inet_csk(sk); |
| 1976 | struct tcp_sock *tp = tcp_sk(sk); | 1987 | struct tcp_sock *tp = tcp_sk(sk); |
| 1977 | u32 timeout, tlp_time_stamp, rto_time_stamp; | 1988 | u32 timeout, tlp_time_stamp, rto_time_stamp; |
| 1978 | u32 rtt = tp->srtt >> 3; | 1989 | u32 rtt = usecs_to_jiffies(tp->srtt_us >> 3); |
| 1979 | 1990 | ||
| 1980 | if (WARN_ON(icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS)) | 1991 | if (WARN_ON(icsk->icsk_pending == ICSK_TIME_EARLY_RETRANS)) |
| 1981 | return false; | 1992 | return false; |
| @@ -1997,7 +2008,7 @@ bool tcp_schedule_loss_probe(struct sock *sk) | |||
| 1997 | /* Schedule a loss probe in 2*RTT for SACK capable connections | 2008 | /* Schedule a loss probe in 2*RTT for SACK capable connections |
| 1998 | * in Open state, that are either limited by cwnd or application. | 2009 | * in Open state, that are either limited by cwnd or application. |
| 1999 | */ | 2010 | */ |
| 2000 | if (sysctl_tcp_early_retrans < 3 || !tp->srtt || !tp->packets_out || | 2011 | if (sysctl_tcp_early_retrans < 3 || !tp->srtt_us || !tp->packets_out || |
| 2001 | !tcp_is_sack(tp) || inet_csk(sk)->icsk_ca_state != TCP_CA_Open) | 2012 | !tcp_is_sack(tp) || inet_csk(sk)->icsk_ca_state != TCP_CA_Open) |
| 2002 | return false; | 2013 | return false; |
| 2003 | 2014 | ||
| @@ -2082,7 +2093,6 @@ rearm_timer: | |||
| 2082 | if (likely(!err)) | 2093 | if (likely(!err)) |
| 2083 | NET_INC_STATS_BH(sock_net(sk), | 2094 | NET_INC_STATS_BH(sock_net(sk), |
| 2084 | LINUX_MIB_TCPLOSSPROBES); | 2095 | LINUX_MIB_TCPLOSSPROBES); |
| 2085 | return; | ||
| 2086 | } | 2096 | } |
| 2087 | 2097 | ||
| 2088 | /* Push out any pending frames which were held back due to | 2098 | /* Push out any pending frames which were held back due to |
| @@ -2180,7 +2190,8 @@ u32 __tcp_select_window(struct sock *sk) | |||
| 2180 | */ | 2190 | */ |
| 2181 | int mss = icsk->icsk_ack.rcv_mss; | 2191 | int mss = icsk->icsk_ack.rcv_mss; |
| 2182 | int free_space = tcp_space(sk); | 2192 | int free_space = tcp_space(sk); |
| 2183 | int full_space = min_t(int, tp->window_clamp, tcp_full_space(sk)); | 2193 | int allowed_space = tcp_full_space(sk); |
| 2194 | int full_space = min_t(int, tp->window_clamp, allowed_space); | ||
| 2184 | int window; | 2195 | int window; |
| 2185 | 2196 | ||
| 2186 | if (mss > full_space) | 2197 | if (mss > full_space) |
| @@ -2193,7 +2204,19 @@ u32 __tcp_select_window(struct sock *sk) | |||
| 2193 | tp->rcv_ssthresh = min(tp->rcv_ssthresh, | 2204 | tp->rcv_ssthresh = min(tp->rcv_ssthresh, |
| 2194 | 4U * tp->advmss); | 2205 | 4U * tp->advmss); |
| 2195 | 2206 | ||
| 2196 | if (free_space < mss) | 2207 | /* free_space might become our new window, make sure we don't |
| 2208 | * increase it due to wscale. | ||
| 2209 | */ | ||
| 2210 | free_space = round_down(free_space, 1 << tp->rx_opt.rcv_wscale); | ||
| 2211 | |||
| 2212 | /* if free space is less than mss estimate, or is below 1/16th | ||
| 2213 | * of the maximum allowed, try to move to zero-window, else | ||
| 2214 | * tcp_clamp_window() will grow rcv buf up to tcp_rmem[2], and | ||
| 2215 | * new incoming data is dropped due to memory limits. | ||
| 2216 | * With large window, mss test triggers way too late in order | ||
| 2217 | * to announce zero window in time before rmem limit kicks in. | ||
| 2218 | */ | ||
| 2219 | if (free_space < (allowed_space >> 4) || free_space < mss) | ||
| 2197 | return 0; | 2220 | return 0; |
| 2198 | } | 2221 | } |
| 2199 | 2222 | ||
| @@ -2431,7 +2454,8 @@ int tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb) | |||
| 2431 | if (err == 0) { | 2454 | if (err == 0) { |
| 2432 | /* Update global TCP statistics. */ | 2455 | /* Update global TCP statistics. */ |
| 2433 | TCP_INC_STATS(sock_net(sk), TCP_MIB_RETRANSSEGS); | 2456 | TCP_INC_STATS(sock_net(sk), TCP_MIB_RETRANSSEGS); |
| 2434 | 2457 | if (TCP_SKB_CB(skb)->tcp_flags & TCPHDR_SYN) | |
| 2458 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSYNRETRANS); | ||
| 2435 | tp->total_retrans++; | 2459 | tp->total_retrans++; |
| 2436 | 2460 | ||
| 2437 | #if FASTRETRANS_DEBUG > 0 | 2461 | #if FASTRETRANS_DEBUG > 0 |
| @@ -2717,7 +2741,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | |||
| 2717 | int tcp_header_size; | 2741 | int tcp_header_size; |
| 2718 | int mss; | 2742 | int mss; |
| 2719 | 2743 | ||
| 2720 | skb = sock_wmalloc(sk, MAX_TCP_HEADER + 15, 1, GFP_ATOMIC); | 2744 | skb = sock_wmalloc(sk, MAX_TCP_HEADER, 1, GFP_ATOMIC); |
| 2721 | if (unlikely(!skb)) { | 2745 | if (unlikely(!skb)) { |
| 2722 | dst_release(dst); | 2746 | dst_release(dst); |
| 2723 | return NULL; | 2747 | return NULL; |
| @@ -2787,7 +2811,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst, | |||
| 2787 | th->window = htons(min(req->rcv_wnd, 65535U)); | 2811 | th->window = htons(min(req->rcv_wnd, 65535U)); |
| 2788 | tcp_options_write((__be32 *)(th + 1), tp, &opts); | 2812 | tcp_options_write((__be32 *)(th + 1), tp, &opts); |
| 2789 | th->doff = (tcp_header_size >> 2); | 2813 | th->doff = (tcp_header_size >> 2); |
| 2790 | TCP_ADD_STATS(sock_net(sk), TCP_MIB_OUTSEGS, tcp_skb_pcount(skb)); | 2814 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_OUTSEGS); |
| 2791 | 2815 | ||
| 2792 | #ifdef CONFIG_TCP_MD5SIG | 2816 | #ifdef CONFIG_TCP_MD5SIG |
| 2793 | /* Okay, we have all we need - do the md5 hash if needed */ | 2817 | /* Okay, we have all we need - do the md5 hash if needed */ |
| @@ -2959,9 +2983,15 @@ static int tcp_send_syn_data(struct sock *sk, struct sk_buff *syn) | |||
| 2959 | tcp_connect_queue_skb(sk, data); | 2983 | tcp_connect_queue_skb(sk, data); |
| 2960 | fo->copied = data->len; | 2984 | fo->copied = data->len; |
| 2961 | 2985 | ||
| 2986 | /* syn_data is about to be sent, we need to take current time stamps | ||
| 2987 | * for the packets that are in write queue : SYN packet and DATA | ||
| 2988 | */ | ||
| 2989 | skb_mstamp_get(&syn->skb_mstamp); | ||
| 2990 | data->skb_mstamp = syn->skb_mstamp; | ||
| 2991 | |||
| 2962 | if (tcp_transmit_skb(sk, syn_data, 0, sk->sk_allocation) == 0) { | 2992 | if (tcp_transmit_skb(sk, syn_data, 0, sk->sk_allocation) == 0) { |
| 2963 | tp->syn_data = (fo->copied > 0); | 2993 | tp->syn_data = (fo->copied > 0); |
| 2964 | NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPFASTOPENACTIVE); | 2994 | NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPORIGDATASENT); |
| 2965 | goto done; | 2995 | goto done; |
| 2966 | } | 2996 | } |
| 2967 | syn_data = NULL; | 2997 | syn_data = NULL; |
| @@ -3049,8 +3079,9 @@ void tcp_send_delayed_ack(struct sock *sk) | |||
| 3049 | * Do not use inet_csk(sk)->icsk_rto here, use results of rtt measurements | 3079 | * Do not use inet_csk(sk)->icsk_rto here, use results of rtt measurements |
| 3050 | * directly. | 3080 | * directly. |
| 3051 | */ | 3081 | */ |
| 3052 | if (tp->srtt) { | 3082 | if (tp->srtt_us) { |
| 3053 | int rtt = max(tp->srtt >> 3, TCP_DELACK_MIN); | 3083 | int rtt = max_t(int, usecs_to_jiffies(tp->srtt_us >> 3), |
| 3084 | TCP_DELACK_MIN); | ||
| 3054 | 3085 | ||
| 3055 | if (rtt < max_ato) | 3086 | if (rtt < max_ato) |
| 3056 | max_ato = rtt; | 3087 | max_ato = rtt; |
diff --git a/net/ipv4/tcp_probe.c b/net/ipv4/tcp_probe.c index 1f2d37613c9e..3b66610d4156 100644 --- a/net/ipv4/tcp_probe.c +++ b/net/ipv4/tcp_probe.c | |||
| @@ -154,7 +154,7 @@ static void jtcp_rcv_established(struct sock *sk, struct sk_buff *skb, | |||
| 154 | p->snd_wnd = tp->snd_wnd; | 154 | p->snd_wnd = tp->snd_wnd; |
| 155 | p->rcv_wnd = tp->rcv_wnd; | 155 | p->rcv_wnd = tp->rcv_wnd; |
| 156 | p->ssthresh = tcp_current_ssthresh(sk); | 156 | p->ssthresh = tcp_current_ssthresh(sk); |
| 157 | p->srtt = tp->srtt >> 3; | 157 | p->srtt = tp->srtt_us >> 3; |
| 158 | 158 | ||
| 159 | tcp_probe.head = (tcp_probe.head + 1) & (bufsize - 1); | 159 | tcp_probe.head = (tcp_probe.head + 1) & (bufsize - 1); |
| 160 | } | 160 | } |
diff --git a/net/ipv4/tcp_scalable.c b/net/ipv4/tcp_scalable.c index 19ea6c2951f3..0ac50836da4d 100644 --- a/net/ipv4/tcp_scalable.c +++ b/net/ipv4/tcp_scalable.c | |||
| @@ -39,7 +39,6 @@ static u32 tcp_scalable_ssthresh(struct sock *sk) | |||
| 39 | static struct tcp_congestion_ops tcp_scalable __read_mostly = { | 39 | static struct tcp_congestion_ops tcp_scalable __read_mostly = { |
| 40 | .ssthresh = tcp_scalable_ssthresh, | 40 | .ssthresh = tcp_scalable_ssthresh, |
| 41 | .cong_avoid = tcp_scalable_cong_avoid, | 41 | .cong_avoid = tcp_scalable_cong_avoid, |
| 42 | .min_cwnd = tcp_reno_min_cwnd, | ||
| 43 | 42 | ||
| 44 | .owner = THIS_MODULE, | 43 | .owner = THIS_MODULE, |
| 45 | .name = "scalable", | 44 | .name = "scalable", |
diff --git a/net/ipv4/tcp_timer.c b/net/ipv4/tcp_timer.c index 64f0354c84c7..286227abed10 100644 --- a/net/ipv4/tcp_timer.c +++ b/net/ipv4/tcp_timer.c | |||
| @@ -165,6 +165,9 @@ static int tcp_write_timeout(struct sock *sk) | |||
| 165 | dst_negative_advice(sk); | 165 | dst_negative_advice(sk); |
| 166 | if (tp->syn_fastopen || tp->syn_data) | 166 | if (tp->syn_fastopen || tp->syn_data) |
| 167 | tcp_fastopen_cache_set(sk, 0, NULL, true); | 167 | tcp_fastopen_cache_set(sk, 0, NULL, true); |
| 168 | if (tp->syn_data) | ||
| 169 | NET_INC_STATS_BH(sock_net(sk), | ||
| 170 | LINUX_MIB_TCPFASTOPENACTIVEFAIL); | ||
| 168 | } | 171 | } |
| 169 | retry_until = icsk->icsk_syn_retries ? : sysctl_tcp_syn_retries; | 172 | retry_until = icsk->icsk_syn_retries ? : sysctl_tcp_syn_retries; |
| 170 | syn_set = true; | 173 | syn_set = true; |
diff --git a/net/ipv4/tcp_vegas.c b/net/ipv4/tcp_vegas.c index 06cae62bf208..48539fff6357 100644 --- a/net/ipv4/tcp_vegas.c +++ b/net/ipv4/tcp_vegas.c | |||
| @@ -306,11 +306,9 @@ void tcp_vegas_get_info(struct sock *sk, u32 ext, struct sk_buff *skb) | |||
| 306 | EXPORT_SYMBOL_GPL(tcp_vegas_get_info); | 306 | EXPORT_SYMBOL_GPL(tcp_vegas_get_info); |
| 307 | 307 | ||
| 308 | static struct tcp_congestion_ops tcp_vegas __read_mostly = { | 308 | static struct tcp_congestion_ops tcp_vegas __read_mostly = { |
| 309 | .flags = TCP_CONG_RTT_STAMP, | ||
| 310 | .init = tcp_vegas_init, | 309 | .init = tcp_vegas_init, |
| 311 | .ssthresh = tcp_reno_ssthresh, | 310 | .ssthresh = tcp_reno_ssthresh, |
| 312 | .cong_avoid = tcp_vegas_cong_avoid, | 311 | .cong_avoid = tcp_vegas_cong_avoid, |
| 313 | .min_cwnd = tcp_reno_min_cwnd, | ||
| 314 | .pkts_acked = tcp_vegas_pkts_acked, | 312 | .pkts_acked = tcp_vegas_pkts_acked, |
| 315 | .set_state = tcp_vegas_state, | 313 | .set_state = tcp_vegas_state, |
| 316 | .cwnd_event = tcp_vegas_cwnd_event, | 314 | .cwnd_event = tcp_vegas_cwnd_event, |
diff --git a/net/ipv4/tcp_veno.c b/net/ipv4/tcp_veno.c index 326475a94865..1b8e28fcd7e1 100644 --- a/net/ipv4/tcp_veno.c +++ b/net/ipv4/tcp_veno.c | |||
| @@ -203,7 +203,6 @@ static u32 tcp_veno_ssthresh(struct sock *sk) | |||
| 203 | } | 203 | } |
| 204 | 204 | ||
| 205 | static struct tcp_congestion_ops tcp_veno __read_mostly = { | 205 | static struct tcp_congestion_ops tcp_veno __read_mostly = { |
| 206 | .flags = TCP_CONG_RTT_STAMP, | ||
| 207 | .init = tcp_veno_init, | 206 | .init = tcp_veno_init, |
| 208 | .ssthresh = tcp_veno_ssthresh, | 207 | .ssthresh = tcp_veno_ssthresh, |
| 209 | .cong_avoid = tcp_veno_cong_avoid, | 208 | .cong_avoid = tcp_veno_cong_avoid, |
diff --git a/net/ipv4/tcp_westwood.c b/net/ipv4/tcp_westwood.c index 76a1e23259e1..b94a04ae2ed5 100644 --- a/net/ipv4/tcp_westwood.c +++ b/net/ipv4/tcp_westwood.c | |||
| @@ -276,7 +276,6 @@ static struct tcp_congestion_ops tcp_westwood __read_mostly = { | |||
| 276 | .init = tcp_westwood_init, | 276 | .init = tcp_westwood_init, |
| 277 | .ssthresh = tcp_reno_ssthresh, | 277 | .ssthresh = tcp_reno_ssthresh, |
| 278 | .cong_avoid = tcp_reno_cong_avoid, | 278 | .cong_avoid = tcp_reno_cong_avoid, |
| 279 | .min_cwnd = tcp_westwood_bw_rttmin, | ||
| 280 | .cwnd_event = tcp_westwood_event, | 279 | .cwnd_event = tcp_westwood_event, |
| 281 | .get_info = tcp_westwood_info, | 280 | .get_info = tcp_westwood_info, |
| 282 | .pkts_acked = tcp_westwood_pkts_acked, | 281 | .pkts_acked = tcp_westwood_pkts_acked, |
diff --git a/net/ipv4/tcp_yeah.c b/net/ipv4/tcp_yeah.c index 1a8d271f994d..5ede0e727945 100644 --- a/net/ipv4/tcp_yeah.c +++ b/net/ipv4/tcp_yeah.c | |||
| @@ -227,11 +227,9 @@ static u32 tcp_yeah_ssthresh(struct sock *sk) { | |||
| 227 | } | 227 | } |
| 228 | 228 | ||
| 229 | static struct tcp_congestion_ops tcp_yeah __read_mostly = { | 229 | static struct tcp_congestion_ops tcp_yeah __read_mostly = { |
| 230 | .flags = TCP_CONG_RTT_STAMP, | ||
| 231 | .init = tcp_yeah_init, | 230 | .init = tcp_yeah_init, |
| 232 | .ssthresh = tcp_yeah_ssthresh, | 231 | .ssthresh = tcp_yeah_ssthresh, |
| 233 | .cong_avoid = tcp_yeah_cong_avoid, | 232 | .cong_avoid = tcp_yeah_cong_avoid, |
| 234 | .min_cwnd = tcp_reno_min_cwnd, | ||
| 235 | .set_state = tcp_vegas_state, | 233 | .set_state = tcp_vegas_state, |
| 236 | .cwnd_event = tcp_vegas_cwnd_event, | 234 | .cwnd_event = tcp_vegas_cwnd_event, |
| 237 | .get_info = tcp_vegas_get_info, | 235 | .get_info = tcp_vegas_get_info, |
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 77bd16fa9f34..4468e1adc094 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c | |||
| @@ -931,7 +931,8 @@ int udp_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
| 931 | sock_tx_timestamp(sk, &ipc.tx_flags); | 931 | sock_tx_timestamp(sk, &ipc.tx_flags); |
| 932 | 932 | ||
| 933 | if (msg->msg_controllen) { | 933 | if (msg->msg_controllen) { |
| 934 | err = ip_cmsg_send(sock_net(sk), msg, &ipc); | 934 | err = ip_cmsg_send(sock_net(sk), msg, &ipc, |
| 935 | sk->sk_family == AF_INET6); | ||
| 935 | if (err) | 936 | if (err) |
| 936 | return err; | 937 | return err; |
| 937 | if (ipc.opt) | 938 | if (ipc.opt) |
diff --git a/net/ipv4/xfrm4_input.c b/net/ipv4/xfrm4_input.c index 1f12c8b45864..aac6197b7a71 100644 --- a/net/ipv4/xfrm4_input.c +++ b/net/ipv4/xfrm4_input.c | |||
| @@ -37,15 +37,6 @@ drop: | |||
| 37 | return NET_RX_DROP; | 37 | return NET_RX_DROP; |
| 38 | } | 38 | } |
| 39 | 39 | ||
| 40 | int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi, | ||
| 41 | int encap_type) | ||
| 42 | { | ||
| 43 | XFRM_SPI_SKB_CB(skb)->family = AF_INET; | ||
| 44 | XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr); | ||
| 45 | return xfrm_input(skb, nexthdr, spi, encap_type); | ||
| 46 | } | ||
| 47 | EXPORT_SYMBOL(xfrm4_rcv_encap); | ||
| 48 | |||
| 49 | int xfrm4_transport_finish(struct sk_buff *skb, int async) | 40 | int xfrm4_transport_finish(struct sk_buff *skb, int async) |
| 50 | { | 41 | { |
| 51 | struct iphdr *iph = ip_hdr(skb); | 42 | struct iphdr *iph = ip_hdr(skb); |
diff --git a/net/ipv4/xfrm4_mode_tunnel.c b/net/ipv4/xfrm4_mode_tunnel.c index 31b18152528f..05f2b484954f 100644 --- a/net/ipv4/xfrm4_mode_tunnel.c +++ b/net/ipv4/xfrm4_mode_tunnel.c | |||
| @@ -15,65 +15,6 @@ | |||
| 15 | #include <net/ip.h> | 15 | #include <net/ip.h> |
| 16 | #include <net/xfrm.h> | 16 | #include <net/xfrm.h> |
| 17 | 17 | ||
| 18 | /* Informational hook. The decap is still done here. */ | ||
| 19 | static struct xfrm_tunnel_notifier __rcu *rcv_notify_handlers __read_mostly; | ||
| 20 | static DEFINE_MUTEX(xfrm4_mode_tunnel_input_mutex); | ||
| 21 | |||
| 22 | int xfrm4_mode_tunnel_input_register(struct xfrm_tunnel_notifier *handler) | ||
| 23 | { | ||
| 24 | struct xfrm_tunnel_notifier __rcu **pprev; | ||
| 25 | struct xfrm_tunnel_notifier *t; | ||
| 26 | int ret = -EEXIST; | ||
| 27 | int priority = handler->priority; | ||
| 28 | |||
| 29 | mutex_lock(&xfrm4_mode_tunnel_input_mutex); | ||
| 30 | |||
| 31 | for (pprev = &rcv_notify_handlers; | ||
| 32 | (t = rcu_dereference_protected(*pprev, | ||
| 33 | lockdep_is_held(&xfrm4_mode_tunnel_input_mutex))) != NULL; | ||
| 34 | pprev = &t->next) { | ||
| 35 | if (t->priority > priority) | ||
| 36 | break; | ||
| 37 | if (t->priority == priority) | ||
| 38 | goto err; | ||
| 39 | |||
| 40 | } | ||
| 41 | |||
| 42 | handler->next = *pprev; | ||
| 43 | rcu_assign_pointer(*pprev, handler); | ||
| 44 | |||
| 45 | ret = 0; | ||
| 46 | |||
| 47 | err: | ||
| 48 | mutex_unlock(&xfrm4_mode_tunnel_input_mutex); | ||
| 49 | return ret; | ||
| 50 | } | ||
| 51 | EXPORT_SYMBOL_GPL(xfrm4_mode_tunnel_input_register); | ||
| 52 | |||
| 53 | int xfrm4_mode_tunnel_input_deregister(struct xfrm_tunnel_notifier *handler) | ||
| 54 | { | ||
| 55 | struct xfrm_tunnel_notifier __rcu **pprev; | ||
| 56 | struct xfrm_tunnel_notifier *t; | ||
| 57 | int ret = -ENOENT; | ||
| 58 | |||
| 59 | mutex_lock(&xfrm4_mode_tunnel_input_mutex); | ||
| 60 | for (pprev = &rcv_notify_handlers; | ||
| 61 | (t = rcu_dereference_protected(*pprev, | ||
| 62 | lockdep_is_held(&xfrm4_mode_tunnel_input_mutex))) != NULL; | ||
| 63 | pprev = &t->next) { | ||
| 64 | if (t == handler) { | ||
| 65 | *pprev = handler->next; | ||
| 66 | ret = 0; | ||
| 67 | break; | ||
| 68 | } | ||
| 69 | } | ||
| 70 | mutex_unlock(&xfrm4_mode_tunnel_input_mutex); | ||
| 71 | synchronize_net(); | ||
| 72 | |||
| 73 | return ret; | ||
| 74 | } | ||
| 75 | EXPORT_SYMBOL_GPL(xfrm4_mode_tunnel_input_deregister); | ||
| 76 | |||
| 77 | static inline void ipip_ecn_decapsulate(struct sk_buff *skb) | 18 | static inline void ipip_ecn_decapsulate(struct sk_buff *skb) |
| 78 | { | 19 | { |
| 79 | struct iphdr *inner_iph = ipip_hdr(skb); | 20 | struct iphdr *inner_iph = ipip_hdr(skb); |
| @@ -127,14 +68,8 @@ static int xfrm4_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) | |||
| 127 | return 0; | 68 | return 0; |
| 128 | } | 69 | } |
| 129 | 70 | ||
| 130 | #define for_each_input_rcu(head, handler) \ | ||
| 131 | for (handler = rcu_dereference(head); \ | ||
| 132 | handler != NULL; \ | ||
| 133 | handler = rcu_dereference(handler->next)) | ||
| 134 | |||
| 135 | static int xfrm4_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) | 71 | static int xfrm4_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) |
| 136 | { | 72 | { |
| 137 | struct xfrm_tunnel_notifier *handler; | ||
| 138 | int err = -EINVAL; | 73 | int err = -EINVAL; |
| 139 | 74 | ||
| 140 | if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPIP) | 75 | if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPIP) |
| @@ -143,9 +78,6 @@ static int xfrm4_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) | |||
| 143 | if (!pskb_may_pull(skb, sizeof(struct iphdr))) | 78 | if (!pskb_may_pull(skb, sizeof(struct iphdr))) |
| 144 | goto out; | 79 | goto out; |
| 145 | 80 | ||
| 146 | for_each_input_rcu(rcv_notify_handlers, handler) | ||
| 147 | handler->handler(skb); | ||
| 148 | |||
| 149 | err = skb_unclone(skb, GFP_ATOMIC); | 81 | err = skb_unclone(skb, GFP_ATOMIC); |
| 150 | if (err) | 82 | if (err) |
| 151 | goto out; | 83 | goto out; |
diff --git a/net/ipv4/xfrm4_output.c b/net/ipv4/xfrm4_output.c index baa0f63731fd..40e701f2e1e0 100644 --- a/net/ipv4/xfrm4_output.c +++ b/net/ipv4/xfrm4_output.c | |||
| @@ -86,7 +86,7 @@ int xfrm4_output_finish(struct sk_buff *skb) | |||
| 86 | return xfrm_output(skb); | 86 | return xfrm_output(skb); |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | int xfrm4_output(struct sk_buff *skb) | 89 | int xfrm4_output(struct sock *sk, struct sk_buff *skb) |
| 90 | { | 90 | { |
| 91 | struct dst_entry *dst = skb_dst(skb); | 91 | struct dst_entry *dst = skb_dst(skb); |
| 92 | struct xfrm_state *x = dst->xfrm; | 92 | struct xfrm_state *x = dst->xfrm; |
diff --git a/net/ipv4/xfrm4_policy.c b/net/ipv4/xfrm4_policy.c index e1a63930a967..6156f68a1e90 100644 --- a/net/ipv4/xfrm4_policy.c +++ b/net/ipv4/xfrm4_policy.c | |||
| @@ -325,6 +325,7 @@ void __init xfrm4_init(void) | |||
| 325 | 325 | ||
| 326 | xfrm4_state_init(); | 326 | xfrm4_state_init(); |
| 327 | xfrm4_policy_init(); | 327 | xfrm4_policy_init(); |
| 328 | xfrm4_protocol_init(); | ||
| 328 | #ifdef CONFIG_SYSCTL | 329 | #ifdef CONFIG_SYSCTL |
| 329 | register_pernet_subsys(&xfrm4_net_ops); | 330 | register_pernet_subsys(&xfrm4_net_ops); |
| 330 | #endif | 331 | #endif |
diff --git a/net/ipv4/xfrm4_protocol.c b/net/ipv4/xfrm4_protocol.c new file mode 100644 index 000000000000..7f7b243e8139 --- /dev/null +++ b/net/ipv4/xfrm4_protocol.c | |||
| @@ -0,0 +1,286 @@ | |||
| 1 | /* xfrm4_protocol.c - Generic xfrm protocol multiplexer. | ||
| 2 | * | ||
| 3 | * Copyright (C) 2013 secunet Security Networks AG | ||
| 4 | * | ||
| 5 | * Author: | ||
| 6 | * Steffen Klassert <steffen.klassert@secunet.com> | ||
| 7 | * | ||
| 8 | * Based on: | ||
| 9 | * net/ipv4/tunnel4.c | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or | ||
| 12 | * modify it under the terms of the GNU General Public License | ||
| 13 | * as published by the Free Software Foundation; either version | ||
| 14 | * 2 of the License, or (at your option) any later version. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/init.h> | ||
| 18 | #include <linux/mutex.h> | ||
| 19 | #include <linux/skbuff.h> | ||
| 20 | #include <net/icmp.h> | ||
| 21 | #include <net/ip.h> | ||
| 22 | #include <net/protocol.h> | ||
| 23 | #include <net/xfrm.h> | ||
| 24 | |||
| 25 | static struct xfrm4_protocol __rcu *esp4_handlers __read_mostly; | ||
| 26 | static struct xfrm4_protocol __rcu *ah4_handlers __read_mostly; | ||
| 27 | static struct xfrm4_protocol __rcu *ipcomp4_handlers __read_mostly; | ||
| 28 | static DEFINE_MUTEX(xfrm4_protocol_mutex); | ||
| 29 | |||
| 30 | static inline struct xfrm4_protocol __rcu **proto_handlers(u8 protocol) | ||
| 31 | { | ||
| 32 | switch (protocol) { | ||
| 33 | case IPPROTO_ESP: | ||
| 34 | return &esp4_handlers; | ||
| 35 | case IPPROTO_AH: | ||
| 36 | return &ah4_handlers; | ||
| 37 | case IPPROTO_COMP: | ||
| 38 | return &ipcomp4_handlers; | ||
| 39 | } | ||
| 40 | |||
| 41 | return NULL; | ||
| 42 | } | ||
| 43 | |||
| 44 | #define for_each_protocol_rcu(head, handler) \ | ||
| 45 | for (handler = rcu_dereference(head); \ | ||
| 46 | handler != NULL; \ | ||
| 47 | handler = rcu_dereference(handler->next)) \ | ||
| 48 | |||
| 49 | int xfrm4_rcv_cb(struct sk_buff *skb, u8 protocol, int err) | ||
| 50 | { | ||
| 51 | int ret; | ||
| 52 | struct xfrm4_protocol *handler; | ||
| 53 | |||
| 54 | for_each_protocol_rcu(*proto_handlers(protocol), handler) | ||
| 55 | if ((ret = handler->cb_handler(skb, err)) <= 0) | ||
| 56 | return ret; | ||
| 57 | |||
| 58 | return 0; | ||
| 59 | } | ||
| 60 | EXPORT_SYMBOL(xfrm4_rcv_cb); | ||
| 61 | |||
| 62 | int xfrm4_rcv_encap(struct sk_buff *skb, int nexthdr, __be32 spi, | ||
| 63 | int encap_type) | ||
| 64 | { | ||
| 65 | int ret; | ||
| 66 | struct xfrm4_protocol *handler; | ||
| 67 | |||
| 68 | XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL; | ||
| 69 | XFRM_SPI_SKB_CB(skb)->family = AF_INET; | ||
| 70 | XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr); | ||
| 71 | |||
| 72 | for_each_protocol_rcu(*proto_handlers(nexthdr), handler) | ||
| 73 | if ((ret = handler->input_handler(skb, nexthdr, spi, encap_type)) != -EINVAL) | ||
| 74 | return ret; | ||
| 75 | |||
| 76 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); | ||
| 77 | |||
| 78 | kfree_skb(skb); | ||
| 79 | return 0; | ||
| 80 | } | ||
| 81 | EXPORT_SYMBOL(xfrm4_rcv_encap); | ||
| 82 | |||
| 83 | static int xfrm4_esp_rcv(struct sk_buff *skb) | ||
| 84 | { | ||
| 85 | int ret; | ||
| 86 | struct xfrm4_protocol *handler; | ||
| 87 | |||
| 88 | XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL; | ||
| 89 | |||
| 90 | for_each_protocol_rcu(esp4_handlers, handler) | ||
| 91 | if ((ret = handler->handler(skb)) != -EINVAL) | ||
| 92 | return ret; | ||
| 93 | |||
| 94 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); | ||
| 95 | |||
| 96 | kfree_skb(skb); | ||
| 97 | return 0; | ||
| 98 | } | ||
| 99 | |||
| 100 | static void xfrm4_esp_err(struct sk_buff *skb, u32 info) | ||
| 101 | { | ||
| 102 | struct xfrm4_protocol *handler; | ||
| 103 | |||
| 104 | for_each_protocol_rcu(esp4_handlers, handler) | ||
| 105 | if (!handler->err_handler(skb, info)) | ||
| 106 | break; | ||
| 107 | } | ||
| 108 | |||
| 109 | static int xfrm4_ah_rcv(struct sk_buff *skb) | ||
| 110 | { | ||
| 111 | int ret; | ||
| 112 | struct xfrm4_protocol *handler; | ||
| 113 | |||
| 114 | XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL; | ||
| 115 | |||
| 116 | for_each_protocol_rcu(ah4_handlers, handler) | ||
| 117 | if ((ret = handler->handler(skb)) != -EINVAL) | ||
| 118 | return ret;; | ||
| 119 | |||
| 120 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); | ||
| 121 | |||
| 122 | kfree_skb(skb); | ||
| 123 | return 0; | ||
| 124 | } | ||
| 125 | |||
| 126 | static void xfrm4_ah_err(struct sk_buff *skb, u32 info) | ||
| 127 | { | ||
| 128 | struct xfrm4_protocol *handler; | ||
| 129 | |||
| 130 | for_each_protocol_rcu(ah4_handlers, handler) | ||
| 131 | if (!handler->err_handler(skb, info)) | ||
| 132 | break; | ||
| 133 | } | ||
| 134 | |||
| 135 | static int xfrm4_ipcomp_rcv(struct sk_buff *skb) | ||
| 136 | { | ||
| 137 | int ret; | ||
| 138 | struct xfrm4_protocol *handler; | ||
| 139 | |||
| 140 | XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = NULL; | ||
| 141 | |||
| 142 | for_each_protocol_rcu(ipcomp4_handlers, handler) | ||
| 143 | if ((ret = handler->handler(skb)) != -EINVAL) | ||
| 144 | return ret; | ||
| 145 | |||
| 146 | icmp_send(skb, ICMP_DEST_UNREACH, ICMP_PORT_UNREACH, 0); | ||
| 147 | |||
| 148 | kfree_skb(skb); | ||
| 149 | return 0; | ||
| 150 | } | ||
| 151 | |||
| 152 | static void xfrm4_ipcomp_err(struct sk_buff *skb, u32 info) | ||
| 153 | { | ||
| 154 | struct xfrm4_protocol *handler; | ||
| 155 | |||
| 156 | for_each_protocol_rcu(ipcomp4_handlers, handler) | ||
| 157 | if (!handler->err_handler(skb, info)) | ||
| 158 | break; | ||
| 159 | } | ||
| 160 | |||
| 161 | static const struct net_protocol esp4_protocol = { | ||
| 162 | .handler = xfrm4_esp_rcv, | ||
| 163 | .err_handler = xfrm4_esp_err, | ||
| 164 | .no_policy = 1, | ||
| 165 | .netns_ok = 1, | ||
| 166 | }; | ||
| 167 | |||
| 168 | static const struct net_protocol ah4_protocol = { | ||
| 169 | .handler = xfrm4_ah_rcv, | ||
| 170 | .err_handler = xfrm4_ah_err, | ||
| 171 | .no_policy = 1, | ||
| 172 | .netns_ok = 1, | ||
| 173 | }; | ||
| 174 | |||
| 175 | static const struct net_protocol ipcomp4_protocol = { | ||
| 176 | .handler = xfrm4_ipcomp_rcv, | ||
| 177 | .err_handler = xfrm4_ipcomp_err, | ||
| 178 | .no_policy = 1, | ||
| 179 | .netns_ok = 1, | ||
| 180 | }; | ||
| 181 | |||
| 182 | static struct xfrm_input_afinfo xfrm4_input_afinfo = { | ||
| 183 | .family = AF_INET, | ||
| 184 | .owner = THIS_MODULE, | ||
| 185 | .callback = xfrm4_rcv_cb, | ||
| 186 | }; | ||
| 187 | |||
| 188 | static inline const struct net_protocol *netproto(unsigned char protocol) | ||
| 189 | { | ||
| 190 | switch (protocol) { | ||
| 191 | case IPPROTO_ESP: | ||
| 192 | return &esp4_protocol; | ||
| 193 | case IPPROTO_AH: | ||
| 194 | return &ah4_protocol; | ||
| 195 | case IPPROTO_COMP: | ||
| 196 | return &ipcomp4_protocol; | ||
| 197 | } | ||
| 198 | |||
| 199 | return NULL; | ||
| 200 | } | ||
| 201 | |||
| 202 | int xfrm4_protocol_register(struct xfrm4_protocol *handler, | ||
| 203 | unsigned char protocol) | ||
| 204 | { | ||
| 205 | struct xfrm4_protocol __rcu **pprev; | ||
| 206 | struct xfrm4_protocol *t; | ||
| 207 | bool add_netproto = false; | ||
| 208 | int ret = -EEXIST; | ||
| 209 | int priority = handler->priority; | ||
| 210 | |||
| 211 | mutex_lock(&xfrm4_protocol_mutex); | ||
| 212 | |||
| 213 | if (!rcu_dereference_protected(*proto_handlers(protocol), | ||
| 214 | lockdep_is_held(&xfrm4_protocol_mutex))) | ||
| 215 | add_netproto = true; | ||
| 216 | |||
| 217 | for (pprev = proto_handlers(protocol); | ||
| 218 | (t = rcu_dereference_protected(*pprev, | ||
| 219 | lockdep_is_held(&xfrm4_protocol_mutex))) != NULL; | ||
| 220 | pprev = &t->next) { | ||
| 221 | if (t->priority < priority) | ||
| 222 | break; | ||
| 223 | if (t->priority == priority) | ||
| 224 | goto err; | ||
| 225 | } | ||
| 226 | |||
| 227 | handler->next = *pprev; | ||
| 228 | rcu_assign_pointer(*pprev, handler); | ||
| 229 | |||
| 230 | ret = 0; | ||
| 231 | |||
| 232 | err: | ||
| 233 | mutex_unlock(&xfrm4_protocol_mutex); | ||
| 234 | |||
| 235 | if (add_netproto) { | ||
| 236 | if (inet_add_protocol(netproto(protocol), protocol)) { | ||
| 237 | pr_err("%s: can't add protocol\n", __func__); | ||
| 238 | ret = -EAGAIN; | ||
| 239 | } | ||
| 240 | } | ||
| 241 | |||
| 242 | return ret; | ||
| 243 | } | ||
| 244 | EXPORT_SYMBOL(xfrm4_protocol_register); | ||
| 245 | |||
| 246 | int xfrm4_protocol_deregister(struct xfrm4_protocol *handler, | ||
| 247 | unsigned char protocol) | ||
| 248 | { | ||
| 249 | struct xfrm4_protocol __rcu **pprev; | ||
| 250 | struct xfrm4_protocol *t; | ||
| 251 | int ret = -ENOENT; | ||
| 252 | |||
| 253 | mutex_lock(&xfrm4_protocol_mutex); | ||
| 254 | |||
| 255 | for (pprev = proto_handlers(protocol); | ||
| 256 | (t = rcu_dereference_protected(*pprev, | ||
| 257 | lockdep_is_held(&xfrm4_protocol_mutex))) != NULL; | ||
| 258 | pprev = &t->next) { | ||
| 259 | if (t == handler) { | ||
| 260 | *pprev = handler->next; | ||
| 261 | ret = 0; | ||
| 262 | break; | ||
| 263 | } | ||
| 264 | } | ||
| 265 | |||
| 266 | if (!rcu_dereference_protected(*proto_handlers(protocol), | ||
| 267 | lockdep_is_held(&xfrm4_protocol_mutex))) { | ||
| 268 | if (inet_del_protocol(netproto(protocol), protocol) < 0) { | ||
| 269 | pr_err("%s: can't remove protocol\n", __func__); | ||
| 270 | ret = -EAGAIN; | ||
| 271 | } | ||
| 272 | } | ||
| 273 | |||
| 274 | mutex_unlock(&xfrm4_protocol_mutex); | ||
| 275 | |||
| 276 | synchronize_net(); | ||
| 277 | |||
| 278 | return ret; | ||
| 279 | } | ||
| 280 | EXPORT_SYMBOL(xfrm4_protocol_deregister); | ||
| 281 | |||
| 282 | void __init xfrm4_protocol_init(void) | ||
| 283 | { | ||
| 284 | xfrm_input_register_afinfo(&xfrm4_input_afinfo); | ||
| 285 | } | ||
| 286 | EXPORT_SYMBOL(xfrm4_protocol_init); | ||
diff --git a/net/ipv6/Makefile b/net/ipv6/Makefile index 17bb830872db..2fe68364bb20 100644 --- a/net/ipv6/Makefile +++ b/net/ipv6/Makefile | |||
| @@ -16,7 +16,7 @@ ipv6-$(CONFIG_SYSCTL) = sysctl_net_ipv6.o | |||
| 16 | ipv6-$(CONFIG_IPV6_MROUTE) += ip6mr.o | 16 | ipv6-$(CONFIG_IPV6_MROUTE) += ip6mr.o |
| 17 | 17 | ||
| 18 | ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \ | 18 | ipv6-$(CONFIG_XFRM) += xfrm6_policy.o xfrm6_state.o xfrm6_input.o \ |
| 19 | xfrm6_output.o | 19 | xfrm6_output.o xfrm6_protocol.o |
| 20 | ipv6-$(CONFIG_NETFILTER) += netfilter.o | 20 | ipv6-$(CONFIG_NETFILTER) += netfilter.o |
| 21 | ipv6-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o | 21 | ipv6-$(CONFIG_IPV6_MULTIPLE_TABLES) += fib6_rules.o |
| 22 | ipv6-$(CONFIG_PROC_FS) += proc.o | 22 | ipv6-$(CONFIG_PROC_FS) += proc.o |
diff --git a/net/ipv6/addrlabel.c b/net/ipv6/addrlabel.c index b30ad3741b46..731e1e1722d9 100644 --- a/net/ipv6/addrlabel.c +++ b/net/ipv6/addrlabel.c | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | */ | 6 | */ |
| 7 | /* | 7 | /* |
| 8 | * Author: | 8 | * Author: |
| 9 | * YOSHIFUJI Hideaki @ USAGI/WIDE Project <yoshfuji@linux-ipv6.org> | 9 | * YOSHIFUJI Hideaki @ USAGI/WIDE Project <yoshfuji@linux-ipv6.org> |
| 10 | */ | 10 | */ |
| 11 | 11 | ||
| 12 | #include <linux/kernel.h> | 12 | #include <linux/kernel.h> |
| @@ -22,14 +22,13 @@ | |||
| 22 | #if 0 | 22 | #if 0 |
| 23 | #define ADDRLABEL(x...) printk(x) | 23 | #define ADDRLABEL(x...) printk(x) |
| 24 | #else | 24 | #else |
| 25 | #define ADDRLABEL(x...) do { ; } while(0) | 25 | #define ADDRLABEL(x...) do { ; } while (0) |
| 26 | #endif | 26 | #endif |
| 27 | 27 | ||
| 28 | /* | 28 | /* |
| 29 | * Policy Table | 29 | * Policy Table |
| 30 | */ | 30 | */ |
| 31 | struct ip6addrlbl_entry | 31 | struct ip6addrlbl_entry { |
| 32 | { | ||
| 33 | #ifdef CONFIG_NET_NS | 32 | #ifdef CONFIG_NET_NS |
| 34 | struct net *lbl_net; | 33 | struct net *lbl_net; |
| 35 | #endif | 34 | #endif |
| @@ -88,39 +87,39 @@ static const __net_initconst struct ip6addrlbl_init_table | |||
| 88 | { /* ::/0 */ | 87 | { /* ::/0 */ |
| 89 | .prefix = &in6addr_any, | 88 | .prefix = &in6addr_any, |
| 90 | .label = 1, | 89 | .label = 1, |
| 91 | },{ /* fc00::/7 */ | 90 | }, { /* fc00::/7 */ |
| 92 | .prefix = &(struct in6_addr){{{ 0xfc }}}, | 91 | .prefix = &(struct in6_addr){ { { 0xfc } } } , |
| 93 | .prefixlen = 7, | 92 | .prefixlen = 7, |
| 94 | .label = 5, | 93 | .label = 5, |
| 95 | },{ /* fec0::/10 */ | 94 | }, { /* fec0::/10 */ |
| 96 | .prefix = &(struct in6_addr){{{ 0xfe, 0xc0 }}}, | 95 | .prefix = &(struct in6_addr){ { { 0xfe, 0xc0 } } }, |
| 97 | .prefixlen = 10, | 96 | .prefixlen = 10, |
| 98 | .label = 11, | 97 | .label = 11, |
| 99 | },{ /* 2002::/16 */ | 98 | }, { /* 2002::/16 */ |
| 100 | .prefix = &(struct in6_addr){{{ 0x20, 0x02 }}}, | 99 | .prefix = &(struct in6_addr){ { { 0x20, 0x02 } } }, |
| 101 | .prefixlen = 16, | 100 | .prefixlen = 16, |
| 102 | .label = 2, | 101 | .label = 2, |
| 103 | },{ /* 3ffe::/16 */ | 102 | }, { /* 3ffe::/16 */ |
| 104 | .prefix = &(struct in6_addr){{{ 0x3f, 0xfe }}}, | 103 | .prefix = &(struct in6_addr){ { { 0x3f, 0xfe } } }, |
| 105 | .prefixlen = 16, | 104 | .prefixlen = 16, |
| 106 | .label = 12, | 105 | .label = 12, |
| 107 | },{ /* 2001::/32 */ | 106 | }, { /* 2001::/32 */ |
| 108 | .prefix = &(struct in6_addr){{{ 0x20, 0x01 }}}, | 107 | .prefix = &(struct in6_addr){ { { 0x20, 0x01 } } }, |
| 109 | .prefixlen = 32, | 108 | .prefixlen = 32, |
| 110 | .label = 6, | 109 | .label = 6, |
| 111 | },{ /* 2001:10::/28 */ | 110 | }, { /* 2001:10::/28 */ |
| 112 | .prefix = &(struct in6_addr){{{ 0x20, 0x01, 0x00, 0x10 }}}, | 111 | .prefix = &(struct in6_addr){ { { 0x20, 0x01, 0x00, 0x10 } } }, |
| 113 | .prefixlen = 28, | 112 | .prefixlen = 28, |
| 114 | .label = 7, | 113 | .label = 7, |
| 115 | },{ /* ::ffff:0:0 */ | 114 | }, { /* ::ffff:0:0 */ |
| 116 | .prefix = &(struct in6_addr){{{ [10] = 0xff, [11] = 0xff }}}, | 115 | .prefix = &(struct in6_addr){ { { [10] = 0xff, [11] = 0xff } } }, |
| 117 | .prefixlen = 96, | 116 | .prefixlen = 96, |
| 118 | .label = 4, | 117 | .label = 4, |
| 119 | },{ /* ::/96 */ | 118 | }, { /* ::/96 */ |
| 120 | .prefix = &in6addr_any, | 119 | .prefix = &in6addr_any, |
| 121 | .prefixlen = 96, | 120 | .prefixlen = 96, |
| 122 | .label = 3, | 121 | .label = 3, |
| 123 | },{ /* ::1/128 */ | 122 | }, { /* ::1/128 */ |
| 124 | .prefix = &in6addr_loopback, | 123 | .prefix = &in6addr_loopback, |
| 125 | .prefixlen = 128, | 124 | .prefixlen = 128, |
| 126 | .label = 0, | 125 | .label = 0, |
| @@ -441,7 +440,7 @@ static int ip6addrlbl_newdel(struct sk_buff *skb, struct nlmsghdr *nlh) | |||
| 441 | if (label == IPV6_ADDR_LABEL_DEFAULT) | 440 | if (label == IPV6_ADDR_LABEL_DEFAULT) |
| 442 | return -EINVAL; | 441 | return -EINVAL; |
| 443 | 442 | ||
| 444 | switch(nlh->nlmsg_type) { | 443 | switch (nlh->nlmsg_type) { |
| 445 | case RTM_NEWADDRLABEL: | 444 | case RTM_NEWADDRLABEL: |
| 446 | if (ifal->ifal_index && | 445 | if (ifal->ifal_index && |
| 447 | !__dev_get_by_index(net, ifal->ifal_index)) | 446 | !__dev_get_by_index(net, ifal->ifal_index)) |
| @@ -505,12 +504,13 @@ static int ip6addrlbl_dump(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 505 | hlist_for_each_entry_rcu(p, &ip6addrlbl_table.head, list) { | 504 | hlist_for_each_entry_rcu(p, &ip6addrlbl_table.head, list) { |
| 506 | if (idx >= s_idx && | 505 | if (idx >= s_idx && |
| 507 | net_eq(ip6addrlbl_net(p), net)) { | 506 | net_eq(ip6addrlbl_net(p), net)) { |
| 508 | if ((err = ip6addrlbl_fill(skb, p, | 507 | err = ip6addrlbl_fill(skb, p, |
| 509 | ip6addrlbl_table.seq, | 508 | ip6addrlbl_table.seq, |
| 510 | NETLINK_CB(cb->skb).portid, | 509 | NETLINK_CB(cb->skb).portid, |
| 511 | cb->nlh->nlmsg_seq, | 510 | cb->nlh->nlmsg_seq, |
| 512 | RTM_NEWADDRLABEL, | 511 | RTM_NEWADDRLABEL, |
| 513 | NLM_F_MULTI)) <= 0) | 512 | NLM_F_MULTI); |
| 513 | if (err <= 0) | ||
| 514 | break; | 514 | break; |
| 515 | } | 515 | } |
| 516 | idx++; | 516 | idx++; |
| @@ -527,7 +527,7 @@ static inline int ip6addrlbl_msgsize(void) | |||
| 527 | + nla_total_size(4); /* IFAL_LABEL */ | 527 | + nla_total_size(4); /* IFAL_LABEL */ |
| 528 | } | 528 | } |
| 529 | 529 | ||
| 530 | static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr* nlh) | 530 | static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr *nlh) |
| 531 | { | 531 | { |
| 532 | struct net *net = sock_net(in_skb->sk); | 532 | struct net *net = sock_net(in_skb->sk); |
| 533 | struct ifaddrlblmsg *ifal; | 533 | struct ifaddrlblmsg *ifal; |
| @@ -568,7 +568,8 @@ static int ip6addrlbl_get(struct sk_buff *in_skb, struct nlmsghdr* nlh) | |||
| 568 | goto out; | 568 | goto out; |
| 569 | } | 569 | } |
| 570 | 570 | ||
| 571 | if (!(skb = nlmsg_new(ip6addrlbl_msgsize(), GFP_KERNEL))) { | 571 | skb = nlmsg_new(ip6addrlbl_msgsize(), GFP_KERNEL); |
| 572 | if (!skb) { | ||
| 572 | ip6addrlbl_put(p); | 573 | ip6addrlbl_put(p); |
| 573 | return -ENOBUFS; | 574 | return -ENOBUFS; |
| 574 | } | 575 | } |
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 81e496a2e008..72a4930bdc0a 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c | |||
| @@ -346,6 +346,10 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb) | |||
| 346 | struct ip_auth_hdr *ah; | 346 | struct ip_auth_hdr *ah; |
| 347 | struct ah_data *ahp; | 347 | struct ah_data *ahp; |
| 348 | struct tmp_ext *iph_ext; | 348 | struct tmp_ext *iph_ext; |
| 349 | int seqhi_len = 0; | ||
| 350 | __be32 *seqhi; | ||
| 351 | int sglists = 0; | ||
| 352 | struct scatterlist *seqhisg; | ||
| 349 | 353 | ||
| 350 | ahp = x->data; | 354 | ahp = x->data; |
| 351 | ahash = ahp->ahash; | 355 | ahash = ahp->ahash; |
| @@ -359,15 +363,22 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb) | |||
| 359 | if (extlen) | 363 | if (extlen) |
| 360 | extlen += sizeof(*iph_ext); | 364 | extlen += sizeof(*iph_ext); |
| 361 | 365 | ||
| 366 | if (x->props.flags & XFRM_STATE_ESN) { | ||
| 367 | sglists = 1; | ||
| 368 | seqhi_len = sizeof(*seqhi); | ||
| 369 | } | ||
| 362 | err = -ENOMEM; | 370 | err = -ENOMEM; |
| 363 | iph_base = ah_alloc_tmp(ahash, nfrags, IPV6HDR_BASELEN + extlen); | 371 | iph_base = ah_alloc_tmp(ahash, nfrags + sglists, IPV6HDR_BASELEN + |
| 372 | extlen + seqhi_len); | ||
| 364 | if (!iph_base) | 373 | if (!iph_base) |
| 365 | goto out; | 374 | goto out; |
| 366 | 375 | ||
| 367 | iph_ext = ah_tmp_ext(iph_base); | 376 | iph_ext = ah_tmp_ext(iph_base); |
| 368 | icv = ah_tmp_icv(ahash, iph_ext, extlen); | 377 | seqhi = (__be32 *)((char *)iph_ext + extlen); |
| 378 | icv = ah_tmp_icv(ahash, seqhi, seqhi_len); | ||
| 369 | req = ah_tmp_req(ahash, icv); | 379 | req = ah_tmp_req(ahash, icv); |
| 370 | sg = ah_req_sg(ahash, req); | 380 | sg = ah_req_sg(ahash, req); |
| 381 | seqhisg = sg + nfrags; | ||
| 371 | 382 | ||
| 372 | ah = ip_auth_hdr(skb); | 383 | ah = ip_auth_hdr(skb); |
| 373 | memset(ah->auth_data, 0, ahp->icv_trunc_len); | 384 | memset(ah->auth_data, 0, ahp->icv_trunc_len); |
| @@ -411,10 +422,15 @@ static int ah6_output(struct xfrm_state *x, struct sk_buff *skb) | |||
| 411 | ah->spi = x->id.spi; | 422 | ah->spi = x->id.spi; |
| 412 | ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.low); | 423 | ah->seq_no = htonl(XFRM_SKB_CB(skb)->seq.output.low); |
| 413 | 424 | ||
| 414 | sg_init_table(sg, nfrags); | 425 | sg_init_table(sg, nfrags + sglists); |
| 415 | skb_to_sgvec(skb, sg, 0, skb->len); | 426 | skb_to_sgvec_nomark(skb, sg, 0, skb->len); |
| 416 | 427 | ||
| 417 | ahash_request_set_crypt(req, sg, icv, skb->len); | 428 | if (x->props.flags & XFRM_STATE_ESN) { |
| 429 | /* Attach seqhi sg right after packet payload */ | ||
| 430 | *seqhi = htonl(XFRM_SKB_CB(skb)->seq.output.hi); | ||
| 431 | sg_set_buf(seqhisg, seqhi, seqhi_len); | ||
| 432 | } | ||
| 433 | ahash_request_set_crypt(req, sg, icv, skb->len + seqhi_len); | ||
| 418 | ahash_request_set_callback(req, 0, ah6_output_done, skb); | 434 | ahash_request_set_callback(req, 0, ah6_output_done, skb); |
| 419 | 435 | ||
| 420 | AH_SKB_CB(skb)->tmp = iph_base; | 436 | AH_SKB_CB(skb)->tmp = iph_base; |
| @@ -514,6 +530,10 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
| 514 | int nexthdr; | 530 | int nexthdr; |
| 515 | int nfrags; | 531 | int nfrags; |
| 516 | int err = -ENOMEM; | 532 | int err = -ENOMEM; |
| 533 | int seqhi_len = 0; | ||
| 534 | __be32 *seqhi; | ||
| 535 | int sglists = 0; | ||
| 536 | struct scatterlist *seqhisg; | ||
| 517 | 537 | ||
| 518 | if (!pskb_may_pull(skb, sizeof(struct ip_auth_hdr))) | 538 | if (!pskb_may_pull(skb, sizeof(struct ip_auth_hdr))) |
| 519 | goto out; | 539 | goto out; |
| @@ -550,14 +570,22 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
| 550 | 570 | ||
| 551 | skb_push(skb, hdr_len); | 571 | skb_push(skb, hdr_len); |
| 552 | 572 | ||
| 553 | work_iph = ah_alloc_tmp(ahash, nfrags, hdr_len + ahp->icv_trunc_len); | 573 | if (x->props.flags & XFRM_STATE_ESN) { |
| 574 | sglists = 1; | ||
| 575 | seqhi_len = sizeof(*seqhi); | ||
| 576 | } | ||
| 577 | |||
| 578 | work_iph = ah_alloc_tmp(ahash, nfrags + sglists, hdr_len + | ||
| 579 | ahp->icv_trunc_len + seqhi_len); | ||
| 554 | if (!work_iph) | 580 | if (!work_iph) |
| 555 | goto out; | 581 | goto out; |
| 556 | 582 | ||
| 557 | auth_data = ah_tmp_auth(work_iph, hdr_len); | 583 | auth_data = ah_tmp_auth((u8 *)work_iph, hdr_len); |
| 558 | icv = ah_tmp_icv(ahash, auth_data, ahp->icv_trunc_len); | 584 | seqhi = (__be32 *)(auth_data + ahp->icv_trunc_len); |
| 585 | icv = ah_tmp_icv(ahash, seqhi, seqhi_len); | ||
| 559 | req = ah_tmp_req(ahash, icv); | 586 | req = ah_tmp_req(ahash, icv); |
| 560 | sg = ah_req_sg(ahash, req); | 587 | sg = ah_req_sg(ahash, req); |
| 588 | seqhisg = sg + nfrags; | ||
| 561 | 589 | ||
| 562 | memcpy(work_iph, ip6h, hdr_len); | 590 | memcpy(work_iph, ip6h, hdr_len); |
| 563 | memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len); | 591 | memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len); |
| @@ -572,10 +600,16 @@ static int ah6_input(struct xfrm_state *x, struct sk_buff *skb) | |||
| 572 | ip6h->flow_lbl[2] = 0; | 600 | ip6h->flow_lbl[2] = 0; |
| 573 | ip6h->hop_limit = 0; | 601 | ip6h->hop_limit = 0; |
| 574 | 602 | ||
| 575 | sg_init_table(sg, nfrags); | 603 | sg_init_table(sg, nfrags + sglists); |
| 576 | skb_to_sgvec(skb, sg, 0, skb->len); | 604 | skb_to_sgvec_nomark(skb, sg, 0, skb->len); |
| 605 | |||
| 606 | if (x->props.flags & XFRM_STATE_ESN) { | ||
| 607 | /* Attach seqhi sg right after packet payload */ | ||
| 608 | *seqhi = XFRM_SKB_CB(skb)->seq.input.hi; | ||
| 609 | sg_set_buf(seqhisg, seqhi, seqhi_len); | ||
| 610 | } | ||
| 577 | 611 | ||
| 578 | ahash_request_set_crypt(req, sg, icv, skb->len); | 612 | ahash_request_set_crypt(req, sg, icv, skb->len + seqhi_len); |
| 579 | ahash_request_set_callback(req, 0, ah6_input_done, skb); | 613 | ahash_request_set_callback(req, 0, ah6_input_done, skb); |
| 580 | 614 | ||
| 581 | AH_SKB_CB(skb)->tmp = work_iph; | 615 | AH_SKB_CB(skb)->tmp = work_iph; |
| @@ -609,8 +643,8 @@ out: | |||
| 609 | return err; | 643 | return err; |
| 610 | } | 644 | } |
| 611 | 645 | ||
| 612 | static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 646 | static int ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
| 613 | u8 type, u8 code, int offset, __be32 info) | 647 | u8 type, u8 code, int offset, __be32 info) |
| 614 | { | 648 | { |
| 615 | struct net *net = dev_net(skb->dev); | 649 | struct net *net = dev_net(skb->dev); |
| 616 | struct ipv6hdr *iph = (struct ipv6hdr*)skb->data; | 650 | struct ipv6hdr *iph = (struct ipv6hdr*)skb->data; |
| @@ -619,17 +653,19 @@ static void ah6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
| 619 | 653 | ||
| 620 | if (type != ICMPV6_PKT_TOOBIG && | 654 | if (type != ICMPV6_PKT_TOOBIG && |
| 621 | type != NDISC_REDIRECT) | 655 | type != NDISC_REDIRECT) |
| 622 | return; | 656 | return 0; |
| 623 | 657 | ||
| 624 | x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, ah->spi, IPPROTO_AH, AF_INET6); | 658 | x = xfrm_state_lookup(net, skb->mark, (xfrm_address_t *)&iph->daddr, ah->spi, IPPROTO_AH, AF_INET6); |
| 625 | if (!x) | 659 | if (!x) |
| 626 | return; | 660 | return 0; |
| 627 | 661 | ||
| 628 | if (type == NDISC_REDIRECT) | 662 | if (type == NDISC_REDIRECT) |
| 629 | ip6_redirect(skb, net, skb->dev->ifindex, 0); | 663 | ip6_redirect(skb, net, skb->dev->ifindex, 0); |
| 630 | else | 664 | else |
| 631 | ip6_update_pmtu(skb, net, info, 0, 0); | 665 | ip6_update_pmtu(skb, net, info, 0, 0); |
| 632 | xfrm_state_put(x); | 666 | xfrm_state_put(x); |
| 667 | |||
| 668 | return 0; | ||
| 633 | } | 669 | } |
| 634 | 670 | ||
| 635 | static int ah6_init_state(struct xfrm_state *x) | 671 | static int ah6_init_state(struct xfrm_state *x) |
| @@ -714,6 +750,11 @@ static void ah6_destroy(struct xfrm_state *x) | |||
| 714 | kfree(ahp); | 750 | kfree(ahp); |
| 715 | } | 751 | } |
| 716 | 752 | ||
| 753 | static int ah6_rcv_cb(struct sk_buff *skb, int err) | ||
| 754 | { | ||
| 755 | return 0; | ||
| 756 | } | ||
| 757 | |||
| 717 | static const struct xfrm_type ah6_type = | 758 | static const struct xfrm_type ah6_type = |
| 718 | { | 759 | { |
| 719 | .description = "AH6", | 760 | .description = "AH6", |
| @@ -727,10 +768,11 @@ static const struct xfrm_type ah6_type = | |||
| 727 | .hdr_offset = xfrm6_find_1stfragopt, | 768 | .hdr_offset = xfrm6_find_1stfragopt, |
| 728 | }; | 769 | }; |
| 729 | 770 | ||
| 730 | static const struct inet6_protocol ah6_protocol = { | 771 | static struct xfrm6_protocol ah6_protocol = { |
| 731 | .handler = xfrm6_rcv, | 772 | .handler = xfrm6_rcv, |
| 773 | .cb_handler = ah6_rcv_cb, | ||
| 732 | .err_handler = ah6_err, | 774 | .err_handler = ah6_err, |
| 733 | .flags = INET6_PROTO_NOPOLICY, | 775 | .priority = 0, |
| 734 | }; | 776 | }; |
| 735 | 777 | ||
| 736 | static int __init ah6_init(void) | 778 | static int __init ah6_init(void) |
| @@ -740,7 +782,7 @@ static int __init ah6_init(void) | |||
| 740 | return -EAGAIN; | 782 | return -EAGAIN; |
| 741 | } | 783 | } |
| 742 | 784 | ||
| 743 | if (inet6_add_protocol(&ah6_protocol, IPPROTO_AH) < 0) { | 785 | if (xfrm6_protocol_register(&ah6_protocol, IPPROTO_AH) < 0) { |
| 744 | pr_info("%s: can't add protocol\n", __func__); | 786 | pr_info("%s: can't add protocol\n", __func__); |
| 745 | xfrm_unregister_type(&ah6_type, AF_INET6); | 787 | xfrm_unregister_type(&ah6_type, AF_INET6); |
| 746 | return -EAGAIN; | 788 | return -EAGAIN; |
| @@ -751,7 +793,7 @@ static int __init ah6_init(void) | |||
| 751 | 793 | ||
| 752 | static void __exit ah6_fini(void) | 794 | static void __exit ah6_fini(void) |
| 753 | { | 795 | { |
| 754 | if (inet6_del_protocol(&ah6_protocol, IPPROTO_AH) < 0) | 796 | if (xfrm6_protocol_deregister(&ah6_protocol, IPPROTO_AH) < 0) |
| 755 | pr_info("%s: can't remove protocol\n", __func__); | 797 | pr_info("%s: can't remove protocol\n", __func__); |
| 756 | 798 | ||
| 757 | if (xfrm_unregister_type(&ah6_type, AF_INET6) < 0) | 799 | if (xfrm_unregister_type(&ah6_type, AF_INET6) < 0) |
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 6eef8a7e35f2..d15da1377149 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c | |||
| @@ -421,8 +421,8 @@ static u32 esp6_get_mtu(struct xfrm_state *x, int mtu) | |||
| 421 | net_adj) & ~(blksize - 1)) + net_adj - 2; | 421 | net_adj) & ~(blksize - 1)) + net_adj - 2; |
| 422 | } | 422 | } |
| 423 | 423 | ||
| 424 | static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 424 | static int esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
| 425 | u8 type, u8 code, int offset, __be32 info) | 425 | u8 type, u8 code, int offset, __be32 info) |
| 426 | { | 426 | { |
| 427 | struct net *net = dev_net(skb->dev); | 427 | struct net *net = dev_net(skb->dev); |
| 428 | const struct ipv6hdr *iph = (const struct ipv6hdr *)skb->data; | 428 | const struct ipv6hdr *iph = (const struct ipv6hdr *)skb->data; |
| @@ -431,18 +431,20 @@ static void esp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
| 431 | 431 | ||
| 432 | if (type != ICMPV6_PKT_TOOBIG && | 432 | if (type != ICMPV6_PKT_TOOBIG && |
| 433 | type != NDISC_REDIRECT) | 433 | type != NDISC_REDIRECT) |
| 434 | return; | 434 | return 0; |
| 435 | 435 | ||
| 436 | x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, | 436 | x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, |
| 437 | esph->spi, IPPROTO_ESP, AF_INET6); | 437 | esph->spi, IPPROTO_ESP, AF_INET6); |
| 438 | if (!x) | 438 | if (!x) |
| 439 | return; | 439 | return 0; |
| 440 | 440 | ||
| 441 | if (type == NDISC_REDIRECT) | 441 | if (type == NDISC_REDIRECT) |
| 442 | ip6_redirect(skb, net, skb->dev->ifindex, 0); | 442 | ip6_redirect(skb, net, skb->dev->ifindex, 0); |
| 443 | else | 443 | else |
| 444 | ip6_update_pmtu(skb, net, info, 0, 0); | 444 | ip6_update_pmtu(skb, net, info, 0, 0); |
| 445 | xfrm_state_put(x); | 445 | xfrm_state_put(x); |
| 446 | |||
| 447 | return 0; | ||
| 446 | } | 448 | } |
| 447 | 449 | ||
| 448 | static void esp6_destroy(struct xfrm_state *x) | 450 | static void esp6_destroy(struct xfrm_state *x) |
| @@ -614,6 +616,11 @@ error: | |||
| 614 | return err; | 616 | return err; |
| 615 | } | 617 | } |
| 616 | 618 | ||
| 619 | static int esp6_rcv_cb(struct sk_buff *skb, int err) | ||
| 620 | { | ||
| 621 | return 0; | ||
| 622 | } | ||
| 623 | |||
| 617 | static const struct xfrm_type esp6_type = | 624 | static const struct xfrm_type esp6_type = |
| 618 | { | 625 | { |
| 619 | .description = "ESP6", | 626 | .description = "ESP6", |
| @@ -628,10 +635,11 @@ static const struct xfrm_type esp6_type = | |||
| 628 | .hdr_offset = xfrm6_find_1stfragopt, | 635 | .hdr_offset = xfrm6_find_1stfragopt, |
| 629 | }; | 636 | }; |
| 630 | 637 | ||
| 631 | static const struct inet6_protocol esp6_protocol = { | 638 | static struct xfrm6_protocol esp6_protocol = { |
| 632 | .handler = xfrm6_rcv, | 639 | .handler = xfrm6_rcv, |
| 640 | .cb_handler = esp6_rcv_cb, | ||
| 633 | .err_handler = esp6_err, | 641 | .err_handler = esp6_err, |
| 634 | .flags = INET6_PROTO_NOPOLICY, | 642 | .priority = 0, |
| 635 | }; | 643 | }; |
| 636 | 644 | ||
| 637 | static int __init esp6_init(void) | 645 | static int __init esp6_init(void) |
| @@ -640,7 +648,7 @@ static int __init esp6_init(void) | |||
| 640 | pr_info("%s: can't add xfrm type\n", __func__); | 648 | pr_info("%s: can't add xfrm type\n", __func__); |
| 641 | return -EAGAIN; | 649 | return -EAGAIN; |
| 642 | } | 650 | } |
| 643 | if (inet6_add_protocol(&esp6_protocol, IPPROTO_ESP) < 0) { | 651 | if (xfrm6_protocol_register(&esp6_protocol, IPPROTO_ESP) < 0) { |
| 644 | pr_info("%s: can't add protocol\n", __func__); | 652 | pr_info("%s: can't add protocol\n", __func__); |
| 645 | xfrm_unregister_type(&esp6_type, AF_INET6); | 653 | xfrm_unregister_type(&esp6_type, AF_INET6); |
| 646 | return -EAGAIN; | 654 | return -EAGAIN; |
| @@ -651,7 +659,7 @@ static int __init esp6_init(void) | |||
| 651 | 659 | ||
| 652 | static void __exit esp6_fini(void) | 660 | static void __exit esp6_fini(void) |
| 653 | { | 661 | { |
| 654 | if (inet6_del_protocol(&esp6_protocol, IPPROTO_ESP) < 0) | 662 | if (xfrm6_protocol_deregister(&esp6_protocol, IPPROTO_ESP) < 0) |
| 655 | pr_info("%s: can't remove protocol\n", __func__); | 663 | pr_info("%s: can't remove protocol\n", __func__); |
| 656 | if (xfrm_unregister_type(&esp6_type, AF_INET6) < 0) | 664 | if (xfrm_unregister_type(&esp6_type, AF_INET6) < 0) |
| 657 | pr_info("%s: can't remove xfrm type\n", __func__); | 665 | pr_info("%s: can't remove xfrm type\n", __func__); |
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c index f2610e157660..7b326529e6a2 100644 --- a/net/ipv6/icmp.c +++ b/net/ipv6/icmp.c | |||
| @@ -520,7 +520,7 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info) | |||
| 520 | np->tclass, NULL, &fl6, (struct rt6_info *)dst, | 520 | np->tclass, NULL, &fl6, (struct rt6_info *)dst, |
| 521 | MSG_DONTWAIT, np->dontfrag); | 521 | MSG_DONTWAIT, np->dontfrag); |
| 522 | if (err) { | 522 | if (err) { |
| 523 | ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTERRORS); | 523 | ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTERRORS); |
| 524 | ip6_flush_pending_frames(sk); | 524 | ip6_flush_pending_frames(sk); |
| 525 | } else { | 525 | } else { |
| 526 | err = icmpv6_push_pending_frames(sk, &fl6, &tmp_hdr, | 526 | err = icmpv6_push_pending_frames(sk, &fl6, &tmp_hdr, |
diff --git a/net/ipv6/inet6_connection_sock.c b/net/ipv6/inet6_connection_sock.c index c9138189415a..d4ade34ab375 100644 --- a/net/ipv6/inet6_connection_sock.c +++ b/net/ipv6/inet6_connection_sock.c | |||
| @@ -224,9 +224,8 @@ static struct dst_entry *inet6_csk_route_socket(struct sock *sk, | |||
| 224 | return dst; | 224 | return dst; |
| 225 | } | 225 | } |
| 226 | 226 | ||
| 227 | int inet6_csk_xmit(struct sk_buff *skb, struct flowi *fl_unused) | 227 | int inet6_csk_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl_unused) |
| 228 | { | 228 | { |
| 229 | struct sock *sk = skb->sk; | ||
| 230 | struct ipv6_pinfo *np = inet6_sk(sk); | 229 | struct ipv6_pinfo *np = inet6_sk(sk); |
| 231 | struct flowi6 fl6; | 230 | struct flowi6 fl6; |
| 232 | struct dst_entry *dst; | 231 | struct dst_entry *dst; |
diff --git a/net/ipv6/ip6_checksum.c b/net/ipv6/ip6_checksum.c index 72d198b8e4d2..ee7a97f510cb 100644 --- a/net/ipv6/ip6_checksum.c +++ b/net/ipv6/ip6_checksum.c | |||
| @@ -79,7 +79,9 @@ int udp6_csum_init(struct sk_buff *skb, struct udphdr *uh, int proto) | |||
| 79 | /* RFC 2460 section 8.1 says that we SHOULD log | 79 | /* RFC 2460 section 8.1 says that we SHOULD log |
| 80 | this error. Well, it is reasonable. | 80 | this error. Well, it is reasonable. |
| 81 | */ | 81 | */ |
| 82 | LIMIT_NETDEBUG(KERN_INFO "IPv6: udp checksum is 0\n"); | 82 | LIMIT_NETDEBUG(KERN_INFO "IPv6: udp checksum is 0 for [%pI6c]:%u->[%pI6c]:%u\n", |
| 83 | &ipv6_hdr(skb)->saddr, ntohs(uh->source), | ||
| 84 | &ipv6_hdr(skb)->daddr, ntohs(uh->dest)); | ||
| 83 | return 1; | 85 | return 1; |
| 84 | } | 86 | } |
| 85 | if (skb->ip_summed == CHECKSUM_COMPLETE && | 87 | if (skb->ip_summed == CHECKSUM_COMPLETE && |
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c index 075602fc6b6a..34e0ded5c14b 100644 --- a/net/ipv6/ip6_fib.c +++ b/net/ipv6/ip6_fib.c | |||
| @@ -9,14 +9,12 @@ | |||
| 9 | * modify it under the terms of the GNU General Public License | 9 | * modify it under the terms of the GNU General Public License |
| 10 | * as published by the Free Software Foundation; either version | 10 | * as published by the Free Software Foundation; either version |
| 11 | * 2 of the License, or (at your option) any later version. | 11 | * 2 of the License, or (at your option) any later version. |
| 12 | */ | 12 | * |
| 13 | 13 | * Changes: | |
| 14 | /* | 14 | * Yuji SEKIYA @USAGI: Support default route on router node; |
| 15 | * Changes: | 15 | * remove ip6_null_entry from the top of |
| 16 | * Yuji SEKIYA @USAGI: Support default route on router node; | 16 | * routing table. |
| 17 | * remove ip6_null_entry from the top of | 17 | * Ville Nuorvala: Fixed routing subtrees. |
| 18 | * routing table. | ||
| 19 | * Ville Nuorvala: Fixed routing subtrees. | ||
| 20 | */ | 18 | */ |
| 21 | 19 | ||
| 22 | #define pr_fmt(fmt) "IPv6: " fmt | 20 | #define pr_fmt(fmt) "IPv6: " fmt |
| @@ -46,10 +44,9 @@ | |||
| 46 | #define RT6_TRACE(x...) do { ; } while (0) | 44 | #define RT6_TRACE(x...) do { ; } while (0) |
| 47 | #endif | 45 | #endif |
| 48 | 46 | ||
| 49 | static struct kmem_cache * fib6_node_kmem __read_mostly; | 47 | static struct kmem_cache *fib6_node_kmem __read_mostly; |
| 50 | 48 | ||
| 51 | enum fib_walk_state_t | 49 | enum fib_walk_state_t { |
| 52 | { | ||
| 53 | #ifdef CONFIG_IPV6_SUBTREES | 50 | #ifdef CONFIG_IPV6_SUBTREES |
| 54 | FWS_S, | 51 | FWS_S, |
| 55 | #endif | 52 | #endif |
| @@ -59,8 +56,7 @@ enum fib_walk_state_t | |||
| 59 | FWS_U | 56 | FWS_U |
| 60 | }; | 57 | }; |
| 61 | 58 | ||
| 62 | struct fib6_cleaner_t | 59 | struct fib6_cleaner_t { |
| 63 | { | ||
| 64 | struct fib6_walker_t w; | 60 | struct fib6_walker_t w; |
| 65 | struct net *net; | 61 | struct net *net; |
| 66 | int (*func)(struct rt6_info *, void *arg); | 62 | int (*func)(struct rt6_info *, void *arg); |
| @@ -138,7 +134,7 @@ static __inline__ __be32 addr_bit_set(const void *token, int fn_bit) | |||
| 138 | const __be32 *addr = token; | 134 | const __be32 *addr = token; |
| 139 | /* | 135 | /* |
| 140 | * Here, | 136 | * Here, |
| 141 | * 1 << ((~fn_bit ^ BITOP_BE32_SWIZZLE) & 0x1f) | 137 | * 1 << ((~fn_bit ^ BITOP_BE32_SWIZZLE) & 0x1f) |
| 142 | * is optimized version of | 138 | * is optimized version of |
| 143 | * htonl(1 << ((~fn_bit)&0x1F)) | 139 | * htonl(1 << ((~fn_bit)&0x1F)) |
| 144 | * See include/asm-generic/bitops/le.h. | 140 | * See include/asm-generic/bitops/le.h. |
| @@ -147,7 +143,7 @@ static __inline__ __be32 addr_bit_set(const void *token, int fn_bit) | |||
| 147 | addr[fn_bit >> 5]; | 143 | addr[fn_bit >> 5]; |
| 148 | } | 144 | } |
| 149 | 145 | ||
| 150 | static __inline__ struct fib6_node * node_alloc(void) | 146 | static __inline__ struct fib6_node *node_alloc(void) |
| 151 | { | 147 | { |
| 152 | struct fib6_node *fn; | 148 | struct fib6_node *fn; |
| 153 | 149 | ||
| @@ -156,7 +152,7 @@ static __inline__ struct fib6_node * node_alloc(void) | |||
| 156 | return fn; | 152 | return fn; |
| 157 | } | 153 | } |
| 158 | 154 | ||
| 159 | static __inline__ void node_free(struct fib6_node * fn) | 155 | static __inline__ void node_free(struct fib6_node *fn) |
| 160 | { | 156 | { |
| 161 | kmem_cache_free(fib6_node_kmem, fn); | 157 | kmem_cache_free(fib6_node_kmem, fn); |
| 162 | } | 158 | } |
| @@ -292,7 +288,7 @@ static int fib6_dump_node(struct fib6_walker_t *w) | |||
| 292 | 288 | ||
| 293 | static void fib6_dump_end(struct netlink_callback *cb) | 289 | static void fib6_dump_end(struct netlink_callback *cb) |
| 294 | { | 290 | { |
| 295 | struct fib6_walker_t *w = (void*)cb->args[2]; | 291 | struct fib6_walker_t *w = (void *)cb->args[2]; |
| 296 | 292 | ||
| 297 | if (w) { | 293 | if (w) { |
| 298 | if (cb->args[4]) { | 294 | if (cb->args[4]) { |
| @@ -302,7 +298,7 @@ static void fib6_dump_end(struct netlink_callback *cb) | |||
| 302 | cb->args[2] = 0; | 298 | cb->args[2] = 0; |
| 303 | kfree(w); | 299 | kfree(w); |
| 304 | } | 300 | } |
| 305 | cb->done = (void*)cb->args[3]; | 301 | cb->done = (void *)cb->args[3]; |
| 306 | cb->args[1] = 3; | 302 | cb->args[1] = 3; |
| 307 | } | 303 | } |
| 308 | 304 | ||
| @@ -485,7 +481,7 @@ static struct fib6_node *fib6_add_1(struct fib6_node *root, | |||
| 485 | fn->fn_sernum = sernum; | 481 | fn->fn_sernum = sernum; |
| 486 | dir = addr_bit_set(addr, fn->fn_bit); | 482 | dir = addr_bit_set(addr, fn->fn_bit); |
| 487 | pn = fn; | 483 | pn = fn; |
| 488 | fn = dir ? fn->right: fn->left; | 484 | fn = dir ? fn->right : fn->left; |
| 489 | } while (fn); | 485 | } while (fn); |
| 490 | 486 | ||
| 491 | if (!allow_create) { | 487 | if (!allow_create) { |
| @@ -638,12 +634,41 @@ static inline bool rt6_qualify_for_ecmp(struct rt6_info *rt) | |||
| 638 | RTF_GATEWAY; | 634 | RTF_GATEWAY; |
| 639 | } | 635 | } |
| 640 | 636 | ||
| 637 | static int fib6_commit_metrics(struct dst_entry *dst, | ||
| 638 | struct nlattr *mx, int mx_len) | ||
| 639 | { | ||
| 640 | struct nlattr *nla; | ||
| 641 | int remaining; | ||
| 642 | u32 *mp; | ||
| 643 | |||
| 644 | if (dst->flags & DST_HOST) { | ||
| 645 | mp = dst_metrics_write_ptr(dst); | ||
| 646 | } else { | ||
| 647 | mp = kzalloc(sizeof(u32) * RTAX_MAX, GFP_KERNEL); | ||
| 648 | if (!mp) | ||
| 649 | return -ENOMEM; | ||
| 650 | dst_init_metrics(dst, mp, 0); | ||
| 651 | } | ||
| 652 | |||
| 653 | nla_for_each_attr(nla, mx, mx_len, remaining) { | ||
| 654 | int type = nla_type(nla); | ||
| 655 | |||
| 656 | if (type) { | ||
| 657 | if (type > RTAX_MAX) | ||
| 658 | return -EINVAL; | ||
| 659 | |||
| 660 | mp[type - 1] = nla_get_u32(nla); | ||
| 661 | } | ||
| 662 | } | ||
| 663 | return 0; | ||
| 664 | } | ||
| 665 | |||
| 641 | /* | 666 | /* |
| 642 | * Insert routing information in a node. | 667 | * Insert routing information in a node. |
| 643 | */ | 668 | */ |
| 644 | 669 | ||
| 645 | static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, | 670 | static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, |
| 646 | struct nl_info *info) | 671 | struct nl_info *info, struct nlattr *mx, int mx_len) |
| 647 | { | 672 | { |
| 648 | struct rt6_info *iter = NULL; | 673 | struct rt6_info *iter = NULL; |
| 649 | struct rt6_info **ins; | 674 | struct rt6_info **ins; |
| @@ -653,6 +678,7 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, | |||
| 653 | (info->nlh->nlmsg_flags & NLM_F_CREATE)); | 678 | (info->nlh->nlmsg_flags & NLM_F_CREATE)); |
| 654 | int found = 0; | 679 | int found = 0; |
| 655 | bool rt_can_ecmp = rt6_qualify_for_ecmp(rt); | 680 | bool rt_can_ecmp = rt6_qualify_for_ecmp(rt); |
| 681 | int err; | ||
| 656 | 682 | ||
| 657 | ins = &fn->leaf; | 683 | ins = &fn->leaf; |
| 658 | 684 | ||
| @@ -751,6 +777,11 @@ static int fib6_add_rt2node(struct fib6_node *fn, struct rt6_info *rt, | |||
| 751 | pr_warn("NLM_F_CREATE should be set when creating new route\n"); | 777 | pr_warn("NLM_F_CREATE should be set when creating new route\n"); |
| 752 | 778 | ||
| 753 | add: | 779 | add: |
| 780 | if (mx) { | ||
| 781 | err = fib6_commit_metrics(&rt->dst, mx, mx_len); | ||
| 782 | if (err) | ||
| 783 | return err; | ||
| 784 | } | ||
| 754 | rt->dst.rt6_next = iter; | 785 | rt->dst.rt6_next = iter; |
| 755 | *ins = rt; | 786 | *ins = rt; |
| 756 | rt->rt6i_node = fn; | 787 | rt->rt6i_node = fn; |
| @@ -770,6 +801,11 @@ add: | |||
| 770 | pr_warn("NLM_F_REPLACE set, but no existing node found!\n"); | 801 | pr_warn("NLM_F_REPLACE set, but no existing node found!\n"); |
| 771 | return -ENOENT; | 802 | return -ENOENT; |
| 772 | } | 803 | } |
| 804 | if (mx) { | ||
| 805 | err = fib6_commit_metrics(&rt->dst, mx, mx_len); | ||
| 806 | if (err) | ||
| 807 | return err; | ||
| 808 | } | ||
| 773 | *ins = rt; | 809 | *ins = rt; |
| 774 | rt->rt6i_node = fn; | 810 | rt->rt6i_node = fn; |
| 775 | rt->dst.rt6_next = iter->dst.rt6_next; | 811 | rt->dst.rt6_next = iter->dst.rt6_next; |
| @@ -806,7 +842,8 @@ void fib6_force_start_gc(struct net *net) | |||
| 806 | * with source addr info in sub-trees | 842 | * with source addr info in sub-trees |
| 807 | */ | 843 | */ |
| 808 | 844 | ||
| 809 | int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info) | 845 | int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info, |
| 846 | struct nlattr *mx, int mx_len) | ||
| 810 | { | 847 | { |
| 811 | struct fib6_node *fn, *pn = NULL; | 848 | struct fib6_node *fn, *pn = NULL; |
| 812 | int err = -ENOMEM; | 849 | int err = -ENOMEM; |
| @@ -900,7 +937,7 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info) | |||
| 900 | } | 937 | } |
| 901 | #endif | 938 | #endif |
| 902 | 939 | ||
| 903 | err = fib6_add_rt2node(fn, rt, info); | 940 | err = fib6_add_rt2node(fn, rt, info, mx, mx_len); |
| 904 | if (!err) { | 941 | if (!err) { |
| 905 | fib6_start_gc(info->nl_net, rt); | 942 | fib6_start_gc(info->nl_net, rt); |
| 906 | if (!(rt->rt6i_flags & RTF_CACHE)) | 943 | if (!(rt->rt6i_flags & RTF_CACHE)) |
| @@ -955,8 +992,8 @@ struct lookup_args { | |||
| 955 | const struct in6_addr *addr; /* search key */ | 992 | const struct in6_addr *addr; /* search key */ |
| 956 | }; | 993 | }; |
| 957 | 994 | ||
| 958 | static struct fib6_node * fib6_lookup_1(struct fib6_node *root, | 995 | static struct fib6_node *fib6_lookup_1(struct fib6_node *root, |
| 959 | struct lookup_args *args) | 996 | struct lookup_args *args) |
| 960 | { | 997 | { |
| 961 | struct fib6_node *fn; | 998 | struct fib6_node *fn; |
| 962 | __be32 dir; | 999 | __be32 dir; |
| @@ -1018,8 +1055,8 @@ backtrack: | |||
| 1018 | return NULL; | 1055 | return NULL; |
| 1019 | } | 1056 | } |
| 1020 | 1057 | ||
| 1021 | struct fib6_node * fib6_lookup(struct fib6_node *root, const struct in6_addr *daddr, | 1058 | struct fib6_node *fib6_lookup(struct fib6_node *root, const struct in6_addr *daddr, |
| 1022 | const struct in6_addr *saddr) | 1059 | const struct in6_addr *saddr) |
| 1023 | { | 1060 | { |
| 1024 | struct fib6_node *fn; | 1061 | struct fib6_node *fn; |
| 1025 | struct lookup_args args[] = { | 1062 | struct lookup_args args[] = { |
| @@ -1051,9 +1088,9 @@ struct fib6_node * fib6_lookup(struct fib6_node *root, const struct in6_addr *da | |||
| 1051 | */ | 1088 | */ |
| 1052 | 1089 | ||
| 1053 | 1090 | ||
| 1054 | static struct fib6_node * fib6_locate_1(struct fib6_node *root, | 1091 | static struct fib6_node *fib6_locate_1(struct fib6_node *root, |
| 1055 | const struct in6_addr *addr, | 1092 | const struct in6_addr *addr, |
| 1056 | int plen, int offset) | 1093 | int plen, int offset) |
| 1057 | { | 1094 | { |
| 1058 | struct fib6_node *fn; | 1095 | struct fib6_node *fn; |
| 1059 | 1096 | ||
| @@ -1081,9 +1118,9 @@ static struct fib6_node * fib6_locate_1(struct fib6_node *root, | |||
| 1081 | return NULL; | 1118 | return NULL; |
| 1082 | } | 1119 | } |
| 1083 | 1120 | ||
| 1084 | struct fib6_node * fib6_locate(struct fib6_node *root, | 1121 | struct fib6_node *fib6_locate(struct fib6_node *root, |
| 1085 | const struct in6_addr *daddr, int dst_len, | 1122 | const struct in6_addr *daddr, int dst_len, |
| 1086 | const struct in6_addr *saddr, int src_len) | 1123 | const struct in6_addr *saddr, int src_len) |
| 1087 | { | 1124 | { |
| 1088 | struct fib6_node *fn; | 1125 | struct fib6_node *fn; |
| 1089 | 1126 | ||
| @@ -1151,8 +1188,10 @@ static struct fib6_node *fib6_repair_tree(struct net *net, | |||
| 1151 | 1188 | ||
| 1152 | children = 0; | 1189 | children = 0; |
| 1153 | child = NULL; | 1190 | child = NULL; |
| 1154 | if (fn->right) child = fn->right, children |= 1; | 1191 | if (fn->right) |
| 1155 | if (fn->left) child = fn->left, children |= 2; | 1192 | child = fn->right, children |= 1; |
| 1193 | if (fn->left) | ||
| 1194 | child = fn->left, children |= 2; | ||
| 1156 | 1195 | ||
| 1157 | if (children == 3 || FIB6_SUBTREE(fn) | 1196 | if (children == 3 || FIB6_SUBTREE(fn) |
| 1158 | #ifdef CONFIG_IPV6_SUBTREES | 1197 | #ifdef CONFIG_IPV6_SUBTREES |
| @@ -1180,8 +1219,10 @@ static struct fib6_node *fib6_repair_tree(struct net *net, | |||
| 1180 | } else { | 1219 | } else { |
| 1181 | WARN_ON(fn->fn_flags & RTN_ROOT); | 1220 | WARN_ON(fn->fn_flags & RTN_ROOT); |
| 1182 | #endif | 1221 | #endif |
| 1183 | if (pn->right == fn) pn->right = child; | 1222 | if (pn->right == fn) |
| 1184 | else if (pn->left == fn) pn->left = child; | 1223 | pn->right = child; |
| 1224 | else if (pn->left == fn) | ||
| 1225 | pn->left = child; | ||
| 1185 | #if RT6_DEBUG >= 2 | 1226 | #if RT6_DEBUG >= 2 |
| 1186 | else | 1227 | else |
| 1187 | WARN_ON(1); | 1228 | WARN_ON(1); |
| @@ -1213,10 +1254,10 @@ static struct fib6_node *fib6_repair_tree(struct net *net, | |||
| 1213 | w->node = child; | 1254 | w->node = child; |
| 1214 | if (children&2) { | 1255 | if (children&2) { |
| 1215 | RT6_TRACE("W %p adjusted by delnode 2, s=%d\n", w, w->state); | 1256 | RT6_TRACE("W %p adjusted by delnode 2, s=%d\n", w, w->state); |
| 1216 | w->state = w->state>=FWS_R ? FWS_U : FWS_INIT; | 1257 | w->state = w->state >= FWS_R ? FWS_U : FWS_INIT; |
| 1217 | } else { | 1258 | } else { |
| 1218 | RT6_TRACE("W %p adjusted by delnode 2, s=%d\n", w, w->state); | 1259 | RT6_TRACE("W %p adjusted by delnode 2, s=%d\n", w, w->state); |
| 1219 | w->state = w->state>=FWS_C ? FWS_U : FWS_INIT; | 1260 | w->state = w->state >= FWS_C ? FWS_U : FWS_INIT; |
| 1220 | } | 1261 | } |
| 1221 | } | 1262 | } |
| 1222 | } | 1263 | } |
| @@ -1314,7 +1355,7 @@ int fib6_del(struct rt6_info *rt, struct nl_info *info) | |||
| 1314 | struct rt6_info **rtp; | 1355 | struct rt6_info **rtp; |
| 1315 | 1356 | ||
| 1316 | #if RT6_DEBUG >= 2 | 1357 | #if RT6_DEBUG >= 2 |
| 1317 | if (rt->dst.obsolete>0) { | 1358 | if (rt->dst.obsolete > 0) { |
| 1318 | WARN_ON(fn != NULL); | 1359 | WARN_ON(fn != NULL); |
| 1319 | return -ENOENT; | 1360 | return -ENOENT; |
| 1320 | } | 1361 | } |
| @@ -1707,7 +1748,7 @@ out_rt6_stats: | |||
| 1707 | kfree(net->ipv6.rt6_stats); | 1748 | kfree(net->ipv6.rt6_stats); |
| 1708 | out_timer: | 1749 | out_timer: |
| 1709 | return -ENOMEM; | 1750 | return -ENOMEM; |
| 1710 | } | 1751 | } |
| 1711 | 1752 | ||
| 1712 | static void fib6_net_exit(struct net *net) | 1753 | static void fib6_net_exit(struct net *net) |
| 1713 | { | 1754 | { |
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c index dfa41bb4e0dc..0961b5ef866d 100644 --- a/net/ipv6/ip6_flowlabel.c +++ b/net/ipv6/ip6_flowlabel.c | |||
| @@ -15,9 +15,7 @@ | |||
| 15 | #include <linux/socket.h> | 15 | #include <linux/socket.h> |
| 16 | #include <linux/net.h> | 16 | #include <linux/net.h> |
| 17 | #include <linux/netdevice.h> | 17 | #include <linux/netdevice.h> |
| 18 | #include <linux/if_arp.h> | ||
| 19 | #include <linux/in6.h> | 18 | #include <linux/in6.h> |
| 20 | #include <linux/route.h> | ||
| 21 | #include <linux/proc_fs.h> | 19 | #include <linux/proc_fs.h> |
| 22 | #include <linux/seq_file.h> | 20 | #include <linux/seq_file.h> |
| 23 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
| @@ -28,12 +26,8 @@ | |||
| 28 | #include <net/sock.h> | 26 | #include <net/sock.h> |
| 29 | 27 | ||
| 30 | #include <net/ipv6.h> | 28 | #include <net/ipv6.h> |
| 31 | #include <net/ndisc.h> | ||
| 32 | #include <net/protocol.h> | ||
| 33 | #include <net/ip6_route.h> | ||
| 34 | #include <net/addrconf.h> | 29 | #include <net/addrconf.h> |
| 35 | #include <net/rawv6.h> | 30 | #include <net/rawv6.h> |
| 36 | #include <net/icmp.h> | ||
| 37 | #include <net/transp_v6.h> | 31 | #include <net/transp_v6.h> |
| 38 | 32 | ||
| 39 | #include <asm/uaccess.h> | 33 | #include <asm/uaccess.h> |
diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index f3ffb43f59c0..9d921462b57f 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c | |||
| @@ -1454,7 +1454,6 @@ static void ip6gre_netlink_parms(struct nlattr *data[], | |||
| 1454 | static int ip6gre_tap_init(struct net_device *dev) | 1454 | static int ip6gre_tap_init(struct net_device *dev) |
| 1455 | { | 1455 | { |
| 1456 | struct ip6_tnl *tunnel; | 1456 | struct ip6_tnl *tunnel; |
| 1457 | int i; | ||
| 1458 | 1457 | ||
| 1459 | tunnel = netdev_priv(dev); | 1458 | tunnel = netdev_priv(dev); |
| 1460 | 1459 | ||
| @@ -1464,16 +1463,10 @@ static int ip6gre_tap_init(struct net_device *dev) | |||
| 1464 | 1463 | ||
| 1465 | ip6gre_tnl_link_config(tunnel, 1); | 1464 | ip6gre_tnl_link_config(tunnel, 1); |
| 1466 | 1465 | ||
| 1467 | dev->tstats = alloc_percpu(struct pcpu_sw_netstats); | 1466 | dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); |
| 1468 | if (!dev->tstats) | 1467 | if (!dev->tstats) |
| 1469 | return -ENOMEM; | 1468 | return -ENOMEM; |
| 1470 | 1469 | ||
| 1471 | for_each_possible_cpu(i) { | ||
| 1472 | struct pcpu_sw_netstats *ip6gre_tap_stats; | ||
| 1473 | ip6gre_tap_stats = per_cpu_ptr(dev->tstats, i); | ||
| 1474 | u64_stats_init(&ip6gre_tap_stats->syncp); | ||
| 1475 | } | ||
| 1476 | |||
| 1477 | return 0; | 1470 | return 0; |
| 1478 | } | 1471 | } |
| 1479 | 1472 | ||
| @@ -1566,6 +1559,15 @@ static int ip6gre_changelink(struct net_device *dev, struct nlattr *tb[], | |||
| 1566 | return 0; | 1559 | return 0; |
| 1567 | } | 1560 | } |
| 1568 | 1561 | ||
| 1562 | static void ip6gre_dellink(struct net_device *dev, struct list_head *head) | ||
| 1563 | { | ||
| 1564 | struct net *net = dev_net(dev); | ||
| 1565 | struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); | ||
| 1566 | |||
| 1567 | if (dev != ign->fb_tunnel_dev) | ||
| 1568 | unregister_netdevice_queue(dev, head); | ||
| 1569 | } | ||
| 1570 | |||
| 1569 | static size_t ip6gre_get_size(const struct net_device *dev) | 1571 | static size_t ip6gre_get_size(const struct net_device *dev) |
| 1570 | { | 1572 | { |
| 1571 | return | 1573 | return |
| @@ -1643,6 +1645,7 @@ static struct rtnl_link_ops ip6gre_link_ops __read_mostly = { | |||
| 1643 | .validate = ip6gre_tunnel_validate, | 1645 | .validate = ip6gre_tunnel_validate, |
| 1644 | .newlink = ip6gre_newlink, | 1646 | .newlink = ip6gre_newlink, |
| 1645 | .changelink = ip6gre_changelink, | 1647 | .changelink = ip6gre_changelink, |
| 1648 | .dellink = ip6gre_dellink, | ||
| 1646 | .get_size = ip6gre_get_size, | 1649 | .get_size = ip6gre_get_size, |
| 1647 | .fill_info = ip6gre_fill_info, | 1650 | .fill_info = ip6gre_fill_info, |
| 1648 | }; | 1651 | }; |
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 64d6073731d3..40e7581374f7 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c | |||
| @@ -132,7 +132,7 @@ static int ip6_finish_output(struct sk_buff *skb) | |||
| 132 | return ip6_finish_output2(skb); | 132 | return ip6_finish_output2(skb); |
| 133 | } | 133 | } |
| 134 | 134 | ||
| 135 | int ip6_output(struct sk_buff *skb) | 135 | int ip6_output(struct sock *sk, struct sk_buff *skb) |
| 136 | { | 136 | { |
| 137 | struct net_device *dev = skb_dst(skb)->dev; | 137 | struct net_device *dev = skb_dst(skb)->dev; |
| 138 | struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); | 138 | struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); |
| @@ -367,6 +367,9 @@ int ip6_forward(struct sk_buff *skb) | |||
| 367 | if (net->ipv6.devconf_all->forwarding == 0) | 367 | if (net->ipv6.devconf_all->forwarding == 0) |
| 368 | goto error; | 368 | goto error; |
| 369 | 369 | ||
| 370 | if (skb->pkt_type != PACKET_HOST) | ||
| 371 | goto drop; | ||
| 372 | |||
| 370 | if (skb_warn_if_lro(skb)) | 373 | if (skb_warn_if_lro(skb)) |
| 371 | goto drop; | 374 | goto drop; |
| 372 | 375 | ||
| @@ -376,9 +379,6 @@ int ip6_forward(struct sk_buff *skb) | |||
| 376 | goto drop; | 379 | goto drop; |
| 377 | } | 380 | } |
| 378 | 381 | ||
| 379 | if (skb->pkt_type != PACKET_HOST) | ||
| 380 | goto drop; | ||
| 381 | |||
| 382 | skb_forward_csum(skb); | 382 | skb_forward_csum(skb); |
| 383 | 383 | ||
| 384 | /* | 384 | /* |
| @@ -1230,8 +1230,10 @@ int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, | |||
| 1230 | sizeof(struct frag_hdr) : 0) + | 1230 | sizeof(struct frag_hdr) : 0) + |
| 1231 | rt->rt6i_nfheader_len; | 1231 | rt->rt6i_nfheader_len; |
| 1232 | 1232 | ||
| 1233 | maxnonfragsize = (np->pmtudisc >= IPV6_PMTUDISC_DO) ? | 1233 | if (ip6_sk_local_df(sk)) |
| 1234 | mtu : sizeof(struct ipv6hdr) + IPV6_MAXPLEN; | 1234 | maxnonfragsize = sizeof(struct ipv6hdr) + IPV6_MAXPLEN; |
| 1235 | else | ||
| 1236 | maxnonfragsize = mtu; | ||
| 1235 | 1237 | ||
| 1236 | /* dontfrag active */ | 1238 | /* dontfrag active */ |
| 1237 | if ((cork->length + length > mtu - headersize) && dontfrag && | 1239 | if ((cork->length + length > mtu - headersize) && dontfrag && |
| @@ -1538,8 +1540,7 @@ int ip6_push_pending_frames(struct sock *sk) | |||
| 1538 | } | 1540 | } |
| 1539 | 1541 | ||
| 1540 | /* Allow local fragmentation. */ | 1542 | /* Allow local fragmentation. */ |
| 1541 | if (np->pmtudisc < IPV6_PMTUDISC_DO) | 1543 | skb->local_df = ip6_sk_local_df(sk); |
| 1542 | skb->local_df = 1; | ||
| 1543 | 1544 | ||
| 1544 | *final_dst = fl6->daddr; | 1545 | *final_dst = fl6->daddr; |
| 1545 | __skb_pull(skb, skb_network_header_len(skb)); | 1546 | __skb_pull(skb, skb_network_header_len(skb)); |
| @@ -1566,8 +1567,8 @@ int ip6_push_pending_frames(struct sock *sk) | |||
| 1566 | if (proto == IPPROTO_ICMPV6) { | 1567 | if (proto == IPPROTO_ICMPV6) { |
| 1567 | struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); | 1568 | struct inet6_dev *idev = ip6_dst_idev(skb_dst(skb)); |
| 1568 | 1569 | ||
| 1569 | ICMP6MSGOUT_INC_STATS_BH(net, idev, icmp6_hdr(skb)->icmp6_type); | 1570 | ICMP6MSGOUT_INC_STATS(net, idev, icmp6_hdr(skb)->icmp6_type); |
| 1570 | ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS); | 1571 | ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS); |
| 1571 | } | 1572 | } |
| 1572 | 1573 | ||
| 1573 | err = ip6_local_out(skb); | 1574 | err = ip6_local_out(skb); |
diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 5db8d310f9c0..e1df691d78be 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c | |||
| @@ -108,12 +108,12 @@ static struct net_device_stats *ip6_get_stats(struct net_device *dev) | |||
| 108 | per_cpu_ptr(dev->tstats, i); | 108 | per_cpu_ptr(dev->tstats, i); |
| 109 | 109 | ||
| 110 | do { | 110 | do { |
| 111 | start = u64_stats_fetch_begin_bh(&tstats->syncp); | 111 | start = u64_stats_fetch_begin_irq(&tstats->syncp); |
| 112 | tmp.rx_packets = tstats->rx_packets; | 112 | tmp.rx_packets = tstats->rx_packets; |
| 113 | tmp.rx_bytes = tstats->rx_bytes; | 113 | tmp.rx_bytes = tstats->rx_bytes; |
| 114 | tmp.tx_packets = tstats->tx_packets; | 114 | tmp.tx_packets = tstats->tx_packets; |
| 115 | tmp.tx_bytes = tstats->tx_bytes; | 115 | tmp.tx_bytes = tstats->tx_bytes; |
| 116 | } while (u64_stats_fetch_retry_bh(&tstats->syncp, start)); | 116 | } while (u64_stats_fetch_retry_irq(&tstats->syncp, start)); |
| 117 | 117 | ||
| 118 | sum.rx_packets += tmp.rx_packets; | 118 | sum.rx_packets += tmp.rx_packets; |
| 119 | sum.rx_bytes += tmp.rx_bytes; | 119 | sum.rx_bytes += tmp.rx_bytes; |
| @@ -1502,19 +1502,12 @@ static inline int | |||
| 1502 | ip6_tnl_dev_init_gen(struct net_device *dev) | 1502 | ip6_tnl_dev_init_gen(struct net_device *dev) |
| 1503 | { | 1503 | { |
| 1504 | struct ip6_tnl *t = netdev_priv(dev); | 1504 | struct ip6_tnl *t = netdev_priv(dev); |
| 1505 | int i; | ||
| 1506 | 1505 | ||
| 1507 | t->dev = dev; | 1506 | t->dev = dev; |
| 1508 | t->net = dev_net(dev); | 1507 | t->net = dev_net(dev); |
| 1509 | dev->tstats = alloc_percpu(struct pcpu_sw_netstats); | 1508 | dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); |
| 1510 | if (!dev->tstats) | 1509 | if (!dev->tstats) |
| 1511 | return -ENOMEM; | 1510 | return -ENOMEM; |
| 1512 | |||
| 1513 | for_each_possible_cpu(i) { | ||
| 1514 | struct pcpu_sw_netstats *ip6_tnl_stats; | ||
| 1515 | ip6_tnl_stats = per_cpu_ptr(dev->tstats, i); | ||
| 1516 | u64_stats_init(&ip6_tnl_stats->syncp); | ||
| 1517 | } | ||
| 1518 | return 0; | 1511 | return 0; |
| 1519 | } | 1512 | } |
| 1520 | 1513 | ||
diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index 2d19272b8cee..b7c0f827140b 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c | |||
| @@ -278,7 +278,6 @@ static void vti6_dev_uninit(struct net_device *dev) | |||
| 278 | RCU_INIT_POINTER(ip6n->tnls_wc[0], NULL); | 278 | RCU_INIT_POINTER(ip6n->tnls_wc[0], NULL); |
| 279 | else | 279 | else |
| 280 | vti6_tnl_unlink(ip6n, t); | 280 | vti6_tnl_unlink(ip6n, t); |
| 281 | ip6_tnl_dst_reset(t); | ||
| 282 | dev_put(dev); | 281 | dev_put(dev); |
| 283 | } | 282 | } |
| 284 | 283 | ||
| @@ -288,11 +287,8 @@ static int vti6_rcv(struct sk_buff *skb) | |||
| 288 | const struct ipv6hdr *ipv6h = ipv6_hdr(skb); | 287 | const struct ipv6hdr *ipv6h = ipv6_hdr(skb); |
| 289 | 288 | ||
| 290 | rcu_read_lock(); | 289 | rcu_read_lock(); |
| 291 | |||
| 292 | if ((t = vti6_tnl_lookup(dev_net(skb->dev), &ipv6h->saddr, | 290 | if ((t = vti6_tnl_lookup(dev_net(skb->dev), &ipv6h->saddr, |
| 293 | &ipv6h->daddr)) != NULL) { | 291 | &ipv6h->daddr)) != NULL) { |
| 294 | struct pcpu_sw_netstats *tstats; | ||
| 295 | |||
| 296 | if (t->parms.proto != IPPROTO_IPV6 && t->parms.proto != 0) { | 292 | if (t->parms.proto != IPPROTO_IPV6 && t->parms.proto != 0) { |
| 297 | rcu_read_unlock(); | 293 | rcu_read_unlock(); |
| 298 | goto discard; | 294 | goto discard; |
| @@ -309,27 +305,58 @@ static int vti6_rcv(struct sk_buff *skb) | |||
| 309 | goto discard; | 305 | goto discard; |
| 310 | } | 306 | } |
| 311 | 307 | ||
| 312 | tstats = this_cpu_ptr(t->dev->tstats); | 308 | XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = t; |
| 313 | u64_stats_update_begin(&tstats->syncp); | 309 | skb->mark = be32_to_cpu(t->parms.i_key); |
| 314 | tstats->rx_packets++; | ||
| 315 | tstats->rx_bytes += skb->len; | ||
| 316 | u64_stats_update_end(&tstats->syncp); | ||
| 317 | |||
| 318 | skb->mark = 0; | ||
| 319 | secpath_reset(skb); | ||
| 320 | skb->dev = t->dev; | ||
| 321 | 310 | ||
| 322 | rcu_read_unlock(); | 311 | rcu_read_unlock(); |
| 323 | return 0; | 312 | |
| 313 | return xfrm6_rcv(skb); | ||
| 324 | } | 314 | } |
| 325 | rcu_read_unlock(); | 315 | rcu_read_unlock(); |
| 326 | return 1; | 316 | return -EINVAL; |
| 327 | |||
| 328 | discard: | 317 | discard: |
| 329 | kfree_skb(skb); | 318 | kfree_skb(skb); |
| 330 | return 0; | 319 | return 0; |
| 331 | } | 320 | } |
| 332 | 321 | ||
| 322 | static int vti6_rcv_cb(struct sk_buff *skb, int err) | ||
| 323 | { | ||
| 324 | unsigned short family; | ||
| 325 | struct net_device *dev; | ||
| 326 | struct pcpu_sw_netstats *tstats; | ||
| 327 | struct xfrm_state *x; | ||
| 328 | struct ip6_tnl *t = XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6; | ||
| 329 | |||
| 330 | if (!t) | ||
| 331 | return 1; | ||
| 332 | |||
| 333 | dev = t->dev; | ||
| 334 | |||
| 335 | if (err) { | ||
| 336 | dev->stats.rx_errors++; | ||
| 337 | dev->stats.rx_dropped++; | ||
| 338 | |||
| 339 | return 0; | ||
| 340 | } | ||
| 341 | |||
| 342 | x = xfrm_input_state(skb); | ||
| 343 | family = x->inner_mode->afinfo->family; | ||
| 344 | |||
| 345 | if (!xfrm_policy_check(NULL, XFRM_POLICY_IN, skb, family)) | ||
| 346 | return -EPERM; | ||
| 347 | |||
| 348 | skb_scrub_packet(skb, !net_eq(t->net, dev_net(skb->dev))); | ||
| 349 | skb->dev = dev; | ||
| 350 | |||
| 351 | tstats = this_cpu_ptr(dev->tstats); | ||
| 352 | u64_stats_update_begin(&tstats->syncp); | ||
| 353 | tstats->rx_packets++; | ||
| 354 | tstats->rx_bytes += skb->len; | ||
| 355 | u64_stats_update_end(&tstats->syncp); | ||
| 356 | |||
| 357 | return 0; | ||
| 358 | } | ||
| 359 | |||
| 333 | /** | 360 | /** |
| 334 | * vti6_addr_conflict - compare packet addresses to tunnel's own | 361 | * vti6_addr_conflict - compare packet addresses to tunnel's own |
| 335 | * @t: the outgoing tunnel device | 362 | * @t: the outgoing tunnel device |
| @@ -349,44 +376,56 @@ vti6_addr_conflict(const struct ip6_tnl *t, const struct ipv6hdr *hdr) | |||
| 349 | return ipv6_addr_equal(&t->parms.raddr, &hdr->saddr); | 376 | return ipv6_addr_equal(&t->parms.raddr, &hdr->saddr); |
| 350 | } | 377 | } |
| 351 | 378 | ||
| 379 | static bool vti6_state_check(const struct xfrm_state *x, | ||
| 380 | const struct in6_addr *dst, | ||
| 381 | const struct in6_addr *src) | ||
| 382 | { | ||
| 383 | xfrm_address_t *daddr = (xfrm_address_t *)dst; | ||
| 384 | xfrm_address_t *saddr = (xfrm_address_t *)src; | ||
| 385 | |||
| 386 | /* if there is no transform then this tunnel is not functional. | ||
| 387 | * Or if the xfrm is not mode tunnel. | ||
| 388 | */ | ||
| 389 | if (!x || x->props.mode != XFRM_MODE_TUNNEL || | ||
| 390 | x->props.family != AF_INET6) | ||
| 391 | return false; | ||
| 392 | |||
| 393 | if (ipv6_addr_any(dst)) | ||
| 394 | return xfrm_addr_equal(saddr, &x->props.saddr, AF_INET6); | ||
| 395 | |||
| 396 | if (!xfrm_state_addr_check(x, daddr, saddr, AF_INET6)) | ||
| 397 | return false; | ||
| 398 | |||
| 399 | return true; | ||
| 400 | } | ||
| 401 | |||
| 352 | /** | 402 | /** |
| 353 | * vti6_xmit - send a packet | 403 | * vti6_xmit - send a packet |
| 354 | * @skb: the outgoing socket buffer | 404 | * @skb: the outgoing socket buffer |
| 355 | * @dev: the outgoing tunnel device | 405 | * @dev: the outgoing tunnel device |
| 406 | * @fl: the flow informations for the xfrm_lookup | ||
| 356 | **/ | 407 | **/ |
| 357 | static int vti6_xmit(struct sk_buff *skb, struct net_device *dev) | 408 | static int |
| 409 | vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) | ||
| 358 | { | 410 | { |
| 359 | struct net *net = dev_net(dev); | ||
| 360 | struct ip6_tnl *t = netdev_priv(dev); | 411 | struct ip6_tnl *t = netdev_priv(dev); |
| 361 | struct net_device_stats *stats = &t->dev->stats; | 412 | struct net_device_stats *stats = &t->dev->stats; |
| 362 | struct dst_entry *dst = NULL, *ndst = NULL; | 413 | struct dst_entry *dst = skb_dst(skb); |
| 363 | struct flowi6 fl6; | ||
| 364 | struct ipv6hdr *ipv6h = ipv6_hdr(skb); | ||
| 365 | struct net_device *tdev; | 414 | struct net_device *tdev; |
| 366 | int err = -1; | 415 | int err = -1; |
| 367 | 416 | ||
| 368 | if ((t->parms.proto != IPPROTO_IPV6 && t->parms.proto != 0) || | 417 | if (!dst) |
| 369 | !ip6_tnl_xmit_ctl(t) || vti6_addr_conflict(t, ipv6h)) | 418 | goto tx_err_link_failure; |
| 370 | return err; | ||
| 371 | |||
| 372 | dst = ip6_tnl_dst_check(t); | ||
| 373 | if (!dst) { | ||
| 374 | memcpy(&fl6, &t->fl.u.ip6, sizeof(fl6)); | ||
| 375 | |||
| 376 | ndst = ip6_route_output(net, NULL, &fl6); | ||
| 377 | 419 | ||
| 378 | if (ndst->error) | 420 | dst_hold(dst); |
| 379 | goto tx_err_link_failure; | 421 | dst = xfrm_lookup(t->net, dst, fl, NULL, 0); |
| 380 | ndst = xfrm_lookup(net, ndst, flowi6_to_flowi(&fl6), NULL, 0); | 422 | if (IS_ERR(dst)) { |
| 381 | if (IS_ERR(ndst)) { | 423 | err = PTR_ERR(dst); |
| 382 | err = PTR_ERR(ndst); | 424 | dst = NULL; |
| 383 | ndst = NULL; | 425 | goto tx_err_link_failure; |
| 384 | goto tx_err_link_failure; | ||
| 385 | } | ||
| 386 | dst = ndst; | ||
| 387 | } | 426 | } |
| 388 | 427 | ||
| 389 | if (!dst->xfrm || dst->xfrm->props.mode != XFRM_MODE_TUNNEL) | 428 | if (!vti6_state_check(dst->xfrm, &t->parms.raddr, &t->parms.laddr)) |
| 390 | goto tx_err_link_failure; | 429 | goto tx_err_link_failure; |
| 391 | 430 | ||
| 392 | tdev = dst->dev; | 431 | tdev = dst->dev; |
| @@ -398,14 +437,21 @@ static int vti6_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 398 | goto tx_err_dst_release; | 437 | goto tx_err_dst_release; |
| 399 | } | 438 | } |
| 400 | 439 | ||
| 440 | skb_scrub_packet(skb, !net_eq(t->net, dev_net(dev))); | ||
| 441 | skb_dst_set(skb, dst); | ||
| 442 | skb->dev = skb_dst(skb)->dev; | ||
| 401 | 443 | ||
| 402 | skb_dst_drop(skb); | 444 | err = dst_output(skb); |
| 403 | skb_dst_set_noref(skb, dst); | 445 | if (net_xmit_eval(err) == 0) { |
| 446 | struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats); | ||
| 404 | 447 | ||
| 405 | ip6tunnel_xmit(skb, dev); | 448 | u64_stats_update_begin(&tstats->syncp); |
| 406 | if (ndst) { | 449 | tstats->tx_bytes += skb->len; |
| 407 | dev->mtu = dst_mtu(ndst); | 450 | tstats->tx_packets++; |
| 408 | ip6_tnl_dst_store(t, ndst); | 451 | u64_stats_update_end(&tstats->syncp); |
| 452 | } else { | ||
| 453 | stats->tx_errors++; | ||
| 454 | stats->tx_aborted_errors++; | ||
| 409 | } | 455 | } |
| 410 | 456 | ||
| 411 | return 0; | 457 | return 0; |
| @@ -413,7 +459,7 @@ tx_err_link_failure: | |||
| 413 | stats->tx_carrier_errors++; | 459 | stats->tx_carrier_errors++; |
| 414 | dst_link_failure(skb); | 460 | dst_link_failure(skb); |
| 415 | tx_err_dst_release: | 461 | tx_err_dst_release: |
| 416 | dst_release(ndst); | 462 | dst_release(dst); |
| 417 | return err; | 463 | return err; |
| 418 | } | 464 | } |
| 419 | 465 | ||
| @@ -422,16 +468,33 @@ vti6_tnl_xmit(struct sk_buff *skb, struct net_device *dev) | |||
| 422 | { | 468 | { |
| 423 | struct ip6_tnl *t = netdev_priv(dev); | 469 | struct ip6_tnl *t = netdev_priv(dev); |
| 424 | struct net_device_stats *stats = &t->dev->stats; | 470 | struct net_device_stats *stats = &t->dev->stats; |
| 471 | struct ipv6hdr *ipv6h; | ||
| 472 | struct flowi fl; | ||
| 425 | int ret; | 473 | int ret; |
| 426 | 474 | ||
| 475 | memset(&fl, 0, sizeof(fl)); | ||
| 476 | skb->mark = be32_to_cpu(t->parms.o_key); | ||
| 477 | |||
| 427 | switch (skb->protocol) { | 478 | switch (skb->protocol) { |
| 428 | case htons(ETH_P_IPV6): | 479 | case htons(ETH_P_IPV6): |
| 429 | ret = vti6_xmit(skb, dev); | 480 | ipv6h = ipv6_hdr(skb); |
| 481 | |||
| 482 | if ((t->parms.proto != IPPROTO_IPV6 && t->parms.proto != 0) || | ||
| 483 | !ip6_tnl_xmit_ctl(t) || vti6_addr_conflict(t, ipv6h)) | ||
| 484 | goto tx_err; | ||
| 485 | |||
| 486 | xfrm_decode_session(skb, &fl, AF_INET6); | ||
| 487 | memset(IP6CB(skb), 0, sizeof(*IP6CB(skb))); | ||
| 488 | break; | ||
| 489 | case htons(ETH_P_IP): | ||
| 490 | xfrm_decode_session(skb, &fl, AF_INET); | ||
| 491 | memset(IPCB(skb), 0, sizeof(*IPCB(skb))); | ||
| 430 | break; | 492 | break; |
| 431 | default: | 493 | default: |
| 432 | goto tx_err; | 494 | goto tx_err; |
| 433 | } | 495 | } |
| 434 | 496 | ||
| 497 | ret = vti6_xmit(skb, dev, &fl); | ||
| 435 | if (ret < 0) | 498 | if (ret < 0) |
| 436 | goto tx_err; | 499 | goto tx_err; |
| 437 | 500 | ||
| @@ -444,24 +507,66 @@ tx_err: | |||
| 444 | return NETDEV_TX_OK; | 507 | return NETDEV_TX_OK; |
| 445 | } | 508 | } |
| 446 | 509 | ||
| 510 | static int vti6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | ||
| 511 | u8 type, u8 code, int offset, __be32 info) | ||
| 512 | { | ||
| 513 | __be32 spi; | ||
| 514 | struct xfrm_state *x; | ||
| 515 | struct ip6_tnl *t; | ||
| 516 | struct ip_esp_hdr *esph; | ||
| 517 | struct ip_auth_hdr *ah; | ||
| 518 | struct ip_comp_hdr *ipch; | ||
| 519 | struct net *net = dev_net(skb->dev); | ||
| 520 | const struct ipv6hdr *iph = (const struct ipv6hdr *)skb->data; | ||
| 521 | int protocol = iph->nexthdr; | ||
| 522 | |||
| 523 | t = vti6_tnl_lookup(dev_net(skb->dev), &iph->daddr, &iph->saddr); | ||
| 524 | if (!t) | ||
| 525 | return -1; | ||
| 526 | |||
| 527 | switch (protocol) { | ||
| 528 | case IPPROTO_ESP: | ||
| 529 | esph = (struct ip_esp_hdr *)(skb->data + offset); | ||
| 530 | spi = esph->spi; | ||
| 531 | break; | ||
| 532 | case IPPROTO_AH: | ||
| 533 | ah = (struct ip_auth_hdr *)(skb->data + offset); | ||
| 534 | spi = ah->spi; | ||
| 535 | break; | ||
| 536 | case IPPROTO_COMP: | ||
| 537 | ipch = (struct ip_comp_hdr *)(skb->data + offset); | ||
| 538 | spi = htonl(ntohs(ipch->cpi)); | ||
| 539 | break; | ||
| 540 | default: | ||
| 541 | return 0; | ||
| 542 | } | ||
| 543 | |||
| 544 | if (type != ICMPV6_PKT_TOOBIG && | ||
| 545 | type != NDISC_REDIRECT) | ||
| 546 | return 0; | ||
| 547 | |||
| 548 | x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, | ||
| 549 | spi, protocol, AF_INET6); | ||
| 550 | if (!x) | ||
| 551 | return 0; | ||
| 552 | |||
| 553 | if (type == NDISC_REDIRECT) | ||
| 554 | ip6_redirect(skb, net, skb->dev->ifindex, 0); | ||
| 555 | else | ||
| 556 | ip6_update_pmtu(skb, net, info, 0, 0); | ||
| 557 | xfrm_state_put(x); | ||
| 558 | |||
| 559 | return 0; | ||
| 560 | } | ||
| 561 | |||
| 447 | static void vti6_link_config(struct ip6_tnl *t) | 562 | static void vti6_link_config(struct ip6_tnl *t) |
| 448 | { | 563 | { |
| 449 | struct dst_entry *dst; | ||
| 450 | struct net_device *dev = t->dev; | 564 | struct net_device *dev = t->dev; |
| 451 | struct __ip6_tnl_parm *p = &t->parms; | 565 | struct __ip6_tnl_parm *p = &t->parms; |
| 452 | struct flowi6 *fl6 = &t->fl.u.ip6; | ||
| 453 | 566 | ||
| 454 | memcpy(dev->dev_addr, &p->laddr, sizeof(struct in6_addr)); | 567 | memcpy(dev->dev_addr, &p->laddr, sizeof(struct in6_addr)); |
| 455 | memcpy(dev->broadcast, &p->raddr, sizeof(struct in6_addr)); | 568 | memcpy(dev->broadcast, &p->raddr, sizeof(struct in6_addr)); |
| 456 | 569 | ||
| 457 | /* Set up flowi template */ | ||
| 458 | fl6->saddr = p->laddr; | ||
| 459 | fl6->daddr = p->raddr; | ||
| 460 | fl6->flowi6_oif = p->link; | ||
| 461 | fl6->flowi6_mark = be32_to_cpu(p->i_key); | ||
| 462 | fl6->flowi6_proto = p->proto; | ||
| 463 | fl6->flowlabel = 0; | ||
| 464 | |||
| 465 | p->flags &= ~(IP6_TNL_F_CAP_XMIT | IP6_TNL_F_CAP_RCV | | 570 | p->flags &= ~(IP6_TNL_F_CAP_XMIT | IP6_TNL_F_CAP_RCV | |
| 466 | IP6_TNL_F_CAP_PER_PACKET); | 571 | IP6_TNL_F_CAP_PER_PACKET); |
| 467 | p->flags |= ip6_tnl_get_cap(t, &p->laddr, &p->raddr); | 572 | p->flags |= ip6_tnl_get_cap(t, &p->laddr, &p->raddr); |
| @@ -472,28 +577,6 @@ static void vti6_link_config(struct ip6_tnl *t) | |||
| 472 | dev->flags &= ~IFF_POINTOPOINT; | 577 | dev->flags &= ~IFF_POINTOPOINT; |
| 473 | 578 | ||
| 474 | dev->iflink = p->link; | 579 | dev->iflink = p->link; |
| 475 | |||
| 476 | if (p->flags & IP6_TNL_F_CAP_XMIT) { | ||
| 477 | |||
| 478 | dst = ip6_route_output(dev_net(dev), NULL, fl6); | ||
| 479 | if (dst->error) | ||
| 480 | return; | ||
| 481 | |||
| 482 | dst = xfrm_lookup(dev_net(dev), dst, flowi6_to_flowi(fl6), | ||
| 483 | NULL, 0); | ||
| 484 | if (IS_ERR(dst)) | ||
| 485 | return; | ||
| 486 | |||
| 487 | if (dst->dev) { | ||
| 488 | dev->hard_header_len = dst->dev->hard_header_len; | ||
| 489 | |||
| 490 | dev->mtu = dst_mtu(dst); | ||
| 491 | |||
| 492 | if (dev->mtu < IPV6_MIN_MTU) | ||
| 493 | dev->mtu = IPV6_MIN_MTU; | ||
| 494 | } | ||
| 495 | dst_release(dst); | ||
| 496 | } | ||
| 497 | } | 580 | } |
| 498 | 581 | ||
| 499 | /** | 582 | /** |
| @@ -720,7 +803,6 @@ static void vti6_dev_setup(struct net_device *dev) | |||
| 720 | t = netdev_priv(dev); | 803 | t = netdev_priv(dev); |
| 721 | dev->flags |= IFF_NOARP; | 804 | dev->flags |= IFF_NOARP; |
| 722 | dev->addr_len = sizeof(struct in6_addr); | 805 | dev->addr_len = sizeof(struct in6_addr); |
| 723 | dev->features |= NETIF_F_NETNS_LOCAL; | ||
| 724 | dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; | 806 | dev->priv_flags &= ~IFF_XMIT_DST_RELEASE; |
| 725 | } | 807 | } |
| 726 | 808 | ||
| @@ -731,18 +813,12 @@ static void vti6_dev_setup(struct net_device *dev) | |||
| 731 | static inline int vti6_dev_init_gen(struct net_device *dev) | 813 | static inline int vti6_dev_init_gen(struct net_device *dev) |
| 732 | { | 814 | { |
| 733 | struct ip6_tnl *t = netdev_priv(dev); | 815 | struct ip6_tnl *t = netdev_priv(dev); |
| 734 | int i; | ||
| 735 | 816 | ||
| 736 | t->dev = dev; | 817 | t->dev = dev; |
| 737 | t->net = dev_net(dev); | 818 | t->net = dev_net(dev); |
| 738 | dev->tstats = alloc_percpu(struct pcpu_sw_netstats); | 819 | dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); |
| 739 | if (!dev->tstats) | 820 | if (!dev->tstats) |
| 740 | return -ENOMEM; | 821 | return -ENOMEM; |
| 741 | for_each_possible_cpu(i) { | ||
| 742 | struct pcpu_sw_netstats *stats; | ||
| 743 | stats = per_cpu_ptr(dev->tstats, i); | ||
| 744 | u64_stats_init(&stats->syncp); | ||
| 745 | } | ||
| 746 | return 0; | 822 | return 0; |
| 747 | } | 823 | } |
| 748 | 824 | ||
| @@ -914,11 +990,6 @@ static struct rtnl_link_ops vti6_link_ops __read_mostly = { | |||
| 914 | .fill_info = vti6_fill_info, | 990 | .fill_info = vti6_fill_info, |
| 915 | }; | 991 | }; |
| 916 | 992 | ||
| 917 | static struct xfrm_tunnel_notifier vti6_handler __read_mostly = { | ||
| 918 | .handler = vti6_rcv, | ||
| 919 | .priority = 1, | ||
| 920 | }; | ||
| 921 | |||
| 922 | static void __net_exit vti6_destroy_tunnels(struct vti6_net *ip6n) | 993 | static void __net_exit vti6_destroy_tunnels(struct vti6_net *ip6n) |
| 923 | { | 994 | { |
| 924 | int h; | 995 | int h; |
| @@ -990,6 +1061,27 @@ static struct pernet_operations vti6_net_ops = { | |||
| 990 | .size = sizeof(struct vti6_net), | 1061 | .size = sizeof(struct vti6_net), |
| 991 | }; | 1062 | }; |
| 992 | 1063 | ||
| 1064 | static struct xfrm6_protocol vti_esp6_protocol __read_mostly = { | ||
| 1065 | .handler = vti6_rcv, | ||
| 1066 | .cb_handler = vti6_rcv_cb, | ||
| 1067 | .err_handler = vti6_err, | ||
| 1068 | .priority = 100, | ||
| 1069 | }; | ||
| 1070 | |||
| 1071 | static struct xfrm6_protocol vti_ah6_protocol __read_mostly = { | ||
| 1072 | .handler = vti6_rcv, | ||
| 1073 | .cb_handler = vti6_rcv_cb, | ||
| 1074 | .err_handler = vti6_err, | ||
| 1075 | .priority = 100, | ||
| 1076 | }; | ||
| 1077 | |||
| 1078 | static struct xfrm6_protocol vti_ipcomp6_protocol __read_mostly = { | ||
| 1079 | .handler = vti6_rcv, | ||
| 1080 | .cb_handler = vti6_rcv_cb, | ||
| 1081 | .err_handler = vti6_err, | ||
| 1082 | .priority = 100, | ||
| 1083 | }; | ||
| 1084 | |||
| 993 | /** | 1085 | /** |
| 994 | * vti6_tunnel_init - register protocol and reserve needed resources | 1086 | * vti6_tunnel_init - register protocol and reserve needed resources |
| 995 | * | 1087 | * |
| @@ -1003,11 +1095,33 @@ static int __init vti6_tunnel_init(void) | |||
| 1003 | if (err < 0) | 1095 | if (err < 0) |
| 1004 | goto out_pernet; | 1096 | goto out_pernet; |
| 1005 | 1097 | ||
| 1006 | err = xfrm6_mode_tunnel_input_register(&vti6_handler); | 1098 | err = xfrm6_protocol_register(&vti_esp6_protocol, IPPROTO_ESP); |
| 1007 | if (err < 0) { | 1099 | if (err < 0) { |
| 1008 | pr_err("%s: can't register vti6\n", __func__); | 1100 | unregister_pernet_device(&vti6_net_ops); |
| 1101 | pr_err("%s: can't register vti6 protocol\n", __func__); | ||
| 1102 | |||
| 1009 | goto out; | 1103 | goto out; |
| 1010 | } | 1104 | } |
| 1105 | |||
| 1106 | err = xfrm6_protocol_register(&vti_ah6_protocol, IPPROTO_AH); | ||
| 1107 | if (err < 0) { | ||
| 1108 | xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP); | ||
| 1109 | unregister_pernet_device(&vti6_net_ops); | ||
| 1110 | pr_err("%s: can't register vti6 protocol\n", __func__); | ||
| 1111 | |||
| 1112 | goto out; | ||
| 1113 | } | ||
| 1114 | |||
| 1115 | err = xfrm6_protocol_register(&vti_ipcomp6_protocol, IPPROTO_COMP); | ||
| 1116 | if (err < 0) { | ||
| 1117 | xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH); | ||
| 1118 | xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP); | ||
| 1119 | unregister_pernet_device(&vti6_net_ops); | ||
| 1120 | pr_err("%s: can't register vti6 protocol\n", __func__); | ||
| 1121 | |||
| 1122 | goto out; | ||
| 1123 | } | ||
| 1124 | |||
| 1011 | err = rtnl_link_register(&vti6_link_ops); | 1125 | err = rtnl_link_register(&vti6_link_ops); |
| 1012 | if (err < 0) | 1126 | if (err < 0) |
| 1013 | goto rtnl_link_failed; | 1127 | goto rtnl_link_failed; |
| @@ -1015,7 +1129,9 @@ static int __init vti6_tunnel_init(void) | |||
| 1015 | return 0; | 1129 | return 0; |
| 1016 | 1130 | ||
| 1017 | rtnl_link_failed: | 1131 | rtnl_link_failed: |
| 1018 | xfrm6_mode_tunnel_input_deregister(&vti6_handler); | 1132 | xfrm6_protocol_deregister(&vti_ipcomp6_protocol, IPPROTO_COMP); |
| 1133 | xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH); | ||
| 1134 | xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP); | ||
| 1019 | out: | 1135 | out: |
| 1020 | unregister_pernet_device(&vti6_net_ops); | 1136 | unregister_pernet_device(&vti6_net_ops); |
| 1021 | out_pernet: | 1137 | out_pernet: |
| @@ -1028,8 +1144,12 @@ out_pernet: | |||
| 1028 | static void __exit vti6_tunnel_cleanup(void) | 1144 | static void __exit vti6_tunnel_cleanup(void) |
| 1029 | { | 1145 | { |
| 1030 | rtnl_link_unregister(&vti6_link_ops); | 1146 | rtnl_link_unregister(&vti6_link_ops); |
| 1031 | if (xfrm6_mode_tunnel_input_deregister(&vti6_handler)) | 1147 | if (xfrm6_protocol_deregister(&vti_ipcomp6_protocol, IPPROTO_COMP)) |
| 1032 | pr_info("%s: can't deregister vti6\n", __func__); | 1148 | pr_info("%s: can't deregister protocol\n", __func__); |
| 1149 | if (xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH)) | ||
| 1150 | pr_info("%s: can't deregister protocol\n", __func__); | ||
| 1151 | if (xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP)) | ||
| 1152 | pr_info("%s: can't deregister protocol\n", __func__); | ||
| 1033 | 1153 | ||
| 1034 | unregister_pernet_device(&vti6_net_ops); | 1154 | unregister_pernet_device(&vti6_net_ops); |
| 1035 | } | 1155 | } |
diff --git a/net/ipv6/ipcomp6.c b/net/ipv6/ipcomp6.c index da9becb42e81..d1c793cffcb5 100644 --- a/net/ipv6/ipcomp6.c +++ b/net/ipv6/ipcomp6.c | |||
| @@ -53,7 +53,7 @@ | |||
| 53 | #include <linux/icmpv6.h> | 53 | #include <linux/icmpv6.h> |
| 54 | #include <linux/mutex.h> | 54 | #include <linux/mutex.h> |
| 55 | 55 | ||
| 56 | static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | 56 | static int ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, |
| 57 | u8 type, u8 code, int offset, __be32 info) | 57 | u8 type, u8 code, int offset, __be32 info) |
| 58 | { | 58 | { |
| 59 | struct net *net = dev_net(skb->dev); | 59 | struct net *net = dev_net(skb->dev); |
| @@ -65,19 +65,21 @@ static void ipcomp6_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | |||
| 65 | 65 | ||
| 66 | if (type != ICMPV6_PKT_TOOBIG && | 66 | if (type != ICMPV6_PKT_TOOBIG && |
| 67 | type != NDISC_REDIRECT) | 67 | type != NDISC_REDIRECT) |
| 68 | return; | 68 | return 0; |
| 69 | 69 | ||
| 70 | spi = htonl(ntohs(ipcomph->cpi)); | 70 | spi = htonl(ntohs(ipcomph->cpi)); |
| 71 | x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, | 71 | x = xfrm_state_lookup(net, skb->mark, (const xfrm_address_t *)&iph->daddr, |
| 72 | spi, IPPROTO_COMP, AF_INET6); | 72 | spi, IPPROTO_COMP, AF_INET6); |
| 73 | if (!x) | 73 | if (!x) |
| 74 | return; | 74 | return 0; |
| 75 | 75 | ||
| 76 | if (type == NDISC_REDIRECT) | 76 | if (type == NDISC_REDIRECT) |
| 77 | ip6_redirect(skb, net, skb->dev->ifindex, 0); | 77 | ip6_redirect(skb, net, skb->dev->ifindex, 0); |
| 78 | else | 78 | else |
| 79 | ip6_update_pmtu(skb, net, info, 0, 0); | 79 | ip6_update_pmtu(skb, net, info, 0, 0); |
| 80 | xfrm_state_put(x); | 80 | xfrm_state_put(x); |
| 81 | |||
| 82 | return 0; | ||
| 81 | } | 83 | } |
| 82 | 84 | ||
| 83 | static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x) | 85 | static struct xfrm_state *ipcomp6_tunnel_create(struct xfrm_state *x) |
| @@ -174,6 +176,11 @@ out: | |||
| 174 | return err; | 176 | return err; |
| 175 | } | 177 | } |
| 176 | 178 | ||
| 179 | static int ipcomp6_rcv_cb(struct sk_buff *skb, int err) | ||
| 180 | { | ||
| 181 | return 0; | ||
| 182 | } | ||
| 183 | |||
| 177 | static const struct xfrm_type ipcomp6_type = | 184 | static const struct xfrm_type ipcomp6_type = |
| 178 | { | 185 | { |
| 179 | .description = "IPCOMP6", | 186 | .description = "IPCOMP6", |
| @@ -186,11 +193,12 @@ static const struct xfrm_type ipcomp6_type = | |||
| 186 | .hdr_offset = xfrm6_find_1stfragopt, | 193 | .hdr_offset = xfrm6_find_1stfragopt, |
| 187 | }; | 194 | }; |
| 188 | 195 | ||
| 189 | static const struct inet6_protocol ipcomp6_protocol = | 196 | static struct xfrm6_protocol ipcomp6_protocol = |
| 190 | { | 197 | { |
| 191 | .handler = xfrm6_rcv, | 198 | .handler = xfrm6_rcv, |
| 199 | .cb_handler = ipcomp6_rcv_cb, | ||
| 192 | .err_handler = ipcomp6_err, | 200 | .err_handler = ipcomp6_err, |
| 193 | .flags = INET6_PROTO_NOPOLICY, | 201 | .priority = 0, |
| 194 | }; | 202 | }; |
| 195 | 203 | ||
| 196 | static int __init ipcomp6_init(void) | 204 | static int __init ipcomp6_init(void) |
| @@ -199,7 +207,7 @@ static int __init ipcomp6_init(void) | |||
| 199 | pr_info("%s: can't add xfrm type\n", __func__); | 207 | pr_info("%s: can't add xfrm type\n", __func__); |
| 200 | return -EAGAIN; | 208 | return -EAGAIN; |
| 201 | } | 209 | } |
| 202 | if (inet6_add_protocol(&ipcomp6_protocol, IPPROTO_COMP) < 0) { | 210 | if (xfrm6_protocol_register(&ipcomp6_protocol, IPPROTO_COMP) < 0) { |
| 203 | pr_info("%s: can't add protocol\n", __func__); | 211 | pr_info("%s: can't add protocol\n", __func__); |
| 204 | xfrm_unregister_type(&ipcomp6_type, AF_INET6); | 212 | xfrm_unregister_type(&ipcomp6_type, AF_INET6); |
| 205 | return -EAGAIN; | 213 | return -EAGAIN; |
| @@ -209,7 +217,7 @@ static int __init ipcomp6_init(void) | |||
| 209 | 217 | ||
| 210 | static void __exit ipcomp6_fini(void) | 218 | static void __exit ipcomp6_fini(void) |
| 211 | { | 219 | { |
| 212 | if (inet6_del_protocol(&ipcomp6_protocol, IPPROTO_COMP) < 0) | 220 | if (xfrm6_protocol_deregister(&ipcomp6_protocol, IPPROTO_COMP) < 0) |
| 213 | pr_info("%s: can't remove protocol\n", __func__); | 221 | pr_info("%s: can't remove protocol\n", __func__); |
| 214 | if (xfrm_unregister_type(&ipcomp6_type, AF_INET6) < 0) | 222 | if (xfrm_unregister_type(&ipcomp6_type, AF_INET6) < 0) |
| 215 | pr_info("%s: can't remove xfrm type\n", __func__); | 223 | pr_info("%s: can't remove xfrm type\n", __func__); |
diff --git a/net/ipv6/ipv6_sockglue.c b/net/ipv6/ipv6_sockglue.c index 0a00f449de5e..edb58aff4ae7 100644 --- a/net/ipv6/ipv6_sockglue.c +++ b/net/ipv6/ipv6_sockglue.c | |||
| @@ -722,7 +722,7 @@ done: | |||
| 722 | case IPV6_MTU_DISCOVER: | 722 | case IPV6_MTU_DISCOVER: |
| 723 | if (optlen < sizeof(int)) | 723 | if (optlen < sizeof(int)) |
| 724 | goto e_inval; | 724 | goto e_inval; |
| 725 | if (val < IPV6_PMTUDISC_DONT || val > IPV6_PMTUDISC_INTERFACE) | 725 | if (val < IPV6_PMTUDISC_DONT || val > IPV6_PMTUDISC_OMIT) |
| 726 | goto e_inval; | 726 | goto e_inval; |
| 727 | np->pmtudisc = val; | 727 | np->pmtudisc = val; |
| 728 | retv = 0; | 728 | retv = 0; |
diff --git a/net/ipv6/mcast.c b/net/ipv6/mcast.c index e1e47350784b..08b367c6b9cf 100644 --- a/net/ipv6/mcast.c +++ b/net/ipv6/mcast.c | |||
| @@ -1620,11 +1620,12 @@ static void mld_sendpack(struct sk_buff *skb) | |||
| 1620 | dst_output); | 1620 | dst_output); |
| 1621 | out: | 1621 | out: |
| 1622 | if (!err) { | 1622 | if (!err) { |
| 1623 | ICMP6MSGOUT_INC_STATS_BH(net, idev, ICMPV6_MLD2_REPORT); | 1623 | ICMP6MSGOUT_INC_STATS(net, idev, ICMPV6_MLD2_REPORT); |
| 1624 | ICMP6_INC_STATS_BH(net, idev, ICMP6_MIB_OUTMSGS); | 1624 | ICMP6_INC_STATS(net, idev, ICMP6_MIB_OUTMSGS); |
| 1625 | IP6_UPD_PO_STATS_BH(net, idev, IPSTATS_MIB_OUTMCAST, payload_len); | 1625 | IP6_UPD_PO_STATS(net, idev, IPSTATS_MIB_OUTMCAST, payload_len); |
| 1626 | } else | 1626 | } else { |
| 1627 | IP6_INC_STATS_BH(net, idev, IPSTATS_MIB_OUTDISCARDS); | 1627 | IP6_INC_STATS(net, idev, IPSTATS_MIB_OUTDISCARDS); |
| 1628 | } | ||
| 1628 | 1629 | ||
| 1629 | rcu_read_unlock(); | 1630 | rcu_read_unlock(); |
| 1630 | return; | 1631 | return; |
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 710238f58aa9..e080fbbbc0e5 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c | |||
| @@ -1241,8 +1241,10 @@ __do_replace(struct net *net, const char *name, unsigned int valid_hooks, | |||
| 1241 | 1241 | ||
| 1242 | xt_free_table_info(oldinfo); | 1242 | xt_free_table_info(oldinfo); |
| 1243 | if (copy_to_user(counters_ptr, counters, | 1243 | if (copy_to_user(counters_ptr, counters, |
| 1244 | sizeof(struct xt_counters) * num_counters) != 0) | 1244 | sizeof(struct xt_counters) * num_counters) != 0) { |
| 1245 | ret = -EFAULT; | 1245 | /* Silent error, can't fail, new table is already in place */ |
| 1246 | net_warn_ratelimited("ip6tables: counters copy to user failed while replacing table\n"); | ||
| 1247 | } | ||
| 1246 | vfree(counters); | 1248 | vfree(counters); |
| 1247 | xt_table_unlock(t); | 1249 | xt_table_unlock(t); |
| 1248 | return ret; | 1250 | return ret; |
diff --git a/net/ipv6/output_core.c b/net/ipv6/output_core.c index 827f795209cf..6313abd53c9d 100644 --- a/net/ipv6/output_core.c +++ b/net/ipv6/output_core.c | |||
| @@ -6,24 +6,24 @@ | |||
| 6 | #include <net/ipv6.h> | 6 | #include <net/ipv6.h> |
| 7 | #include <net/ip6_fib.h> | 7 | #include <net/ip6_fib.h> |
| 8 | #include <net/addrconf.h> | 8 | #include <net/addrconf.h> |
| 9 | #include <net/secure_seq.h> | ||
| 9 | 10 | ||
| 10 | void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt) | 11 | void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt) |
| 11 | { | 12 | { |
| 12 | static atomic_t ipv6_fragmentation_id; | 13 | static atomic_t ipv6_fragmentation_id; |
| 14 | struct in6_addr addr; | ||
| 13 | int old, new; | 15 | int old, new; |
| 14 | 16 | ||
| 15 | #if IS_ENABLED(CONFIG_IPV6) | 17 | #if IS_ENABLED(CONFIG_IPV6) |
| 16 | if (rt && !(rt->dst.flags & DST_NOPEER)) { | 18 | struct inet_peer *peer; |
| 17 | struct inet_peer *peer; | 19 | struct net *net; |
| 18 | struct net *net; | 20 | |
| 19 | 21 | net = dev_net(rt->dst.dev); | |
| 20 | net = dev_net(rt->dst.dev); | 22 | peer = inet_getpeer_v6(net->ipv6.peers, &rt->rt6i_dst.addr, 1); |
| 21 | peer = inet_getpeer_v6(net->ipv6.peers, &rt->rt6i_dst.addr, 1); | 23 | if (peer) { |
| 22 | if (peer) { | 24 | fhdr->identification = htonl(inet_getid(peer, 0)); |
| 23 | fhdr->identification = htonl(inet_getid(peer, 0)); | 25 | inet_putpeer(peer); |
| 24 | inet_putpeer(peer); | 26 | return; |
| 25 | return; | ||
| 26 | } | ||
| 27 | } | 27 | } |
| 28 | #endif | 28 | #endif |
| 29 | do { | 29 | do { |
| @@ -32,7 +32,10 @@ void ipv6_select_ident(struct frag_hdr *fhdr, struct rt6_info *rt) | |||
| 32 | if (!new) | 32 | if (!new) |
| 33 | new = 1; | 33 | new = 1; |
| 34 | } while (atomic_cmpxchg(&ipv6_fragmentation_id, old, new) != old); | 34 | } while (atomic_cmpxchg(&ipv6_fragmentation_id, old, new) != old); |
| 35 | fhdr->identification = htonl(new); | 35 | |
| 36 | addr = rt->rt6i_dst.addr; | ||
| 37 | addr.s6_addr32[0] ^= (__force __be32)new; | ||
| 38 | fhdr->identification = htonl(secure_ipv6_id(addr.s6_addr32)); | ||
| 36 | } | 39 | } |
| 37 | EXPORT_SYMBOL(ipv6_select_ident); | 40 | EXPORT_SYMBOL(ipv6_select_ident); |
| 38 | 41 | ||
diff --git a/net/ipv6/ping.c b/net/ipv6/ping.c index 587bbdcb22b4..bda74291c3e0 100644 --- a/net/ipv6/ping.c +++ b/net/ipv6/ping.c | |||
| @@ -182,8 +182,8 @@ int ping_v6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, | |||
| 182 | MSG_DONTWAIT, np->dontfrag); | 182 | MSG_DONTWAIT, np->dontfrag); |
| 183 | 183 | ||
| 184 | if (err) { | 184 | if (err) { |
| 185 | ICMP6_INC_STATS_BH(sock_net(sk), rt->rt6i_idev, | 185 | ICMP6_INC_STATS(sock_net(sk), rt->rt6i_idev, |
| 186 | ICMP6_MIB_OUTERRORS); | 186 | ICMP6_MIB_OUTERRORS); |
| 187 | ip6_flush_pending_frames(sk); | 187 | ip6_flush_pending_frames(sk); |
| 188 | } else { | 188 | } else { |
| 189 | err = icmpv6_push_pending_frames(sk, &fl6, | 189 | err = icmpv6_push_pending_frames(sk, &fl6, |
diff --git a/net/ipv6/route.c b/net/ipv6/route.c index fba54a407bb2..4011617cca68 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c | |||
| @@ -84,9 +84,9 @@ static void ip6_dst_ifdown(struct dst_entry *, | |||
| 84 | static int ip6_dst_gc(struct dst_ops *ops); | 84 | static int ip6_dst_gc(struct dst_ops *ops); |
| 85 | 85 | ||
| 86 | static int ip6_pkt_discard(struct sk_buff *skb); | 86 | static int ip6_pkt_discard(struct sk_buff *skb); |
| 87 | static int ip6_pkt_discard_out(struct sk_buff *skb); | 87 | static int ip6_pkt_discard_out(struct sock *sk, struct sk_buff *skb); |
| 88 | static int ip6_pkt_prohibit(struct sk_buff *skb); | 88 | static int ip6_pkt_prohibit(struct sk_buff *skb); |
| 89 | static int ip6_pkt_prohibit_out(struct sk_buff *skb); | 89 | static int ip6_pkt_prohibit_out(struct sock *sk, struct sk_buff *skb); |
| 90 | static void ip6_link_failure(struct sk_buff *skb); | 90 | static void ip6_link_failure(struct sk_buff *skb); |
| 91 | static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, | 91 | static void ip6_rt_update_pmtu(struct dst_entry *dst, struct sock *sk, |
| 92 | struct sk_buff *skb, u32 mtu); | 92 | struct sk_buff *skb, u32 mtu); |
| @@ -149,7 +149,8 @@ static u32 *ipv6_cow_metrics(struct dst_entry *dst, unsigned long old) | |||
| 149 | unsigned long prev, new; | 149 | unsigned long prev, new; |
| 150 | 150 | ||
| 151 | p = peer->metrics; | 151 | p = peer->metrics; |
| 152 | if (inet_metrics_new(peer)) | 152 | if (inet_metrics_new(peer) || |
| 153 | (old & DST_METRICS_FORCE_OVERWRITE)) | ||
| 153 | memcpy(p, old_p, sizeof(u32) * RTAX_MAX); | 154 | memcpy(p, old_p, sizeof(u32) * RTAX_MAX); |
| 154 | 155 | ||
| 155 | new = (unsigned long) p; | 156 | new = (unsigned long) p; |
| @@ -289,7 +290,7 @@ static const struct rt6_info ip6_blk_hole_entry_template = { | |||
| 289 | .obsolete = DST_OBSOLETE_FORCE_CHK, | 290 | .obsolete = DST_OBSOLETE_FORCE_CHK, |
| 290 | .error = -EINVAL, | 291 | .error = -EINVAL, |
| 291 | .input = dst_discard, | 292 | .input = dst_discard, |
| 292 | .output = dst_discard, | 293 | .output = dst_discard_sk, |
| 293 | }, | 294 | }, |
| 294 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), | 295 | .rt6i_flags = (RTF_REJECT | RTF_NONEXTHOP), |
| 295 | .rt6i_protocol = RTPROT_KERNEL, | 296 | .rt6i_protocol = RTPROT_KERNEL, |
| @@ -373,12 +374,6 @@ static bool rt6_check_expired(const struct rt6_info *rt) | |||
| 373 | return false; | 374 | return false; |
| 374 | } | 375 | } |
| 375 | 376 | ||
| 376 | static bool rt6_need_strict(const struct in6_addr *daddr) | ||
| 377 | { | ||
| 378 | return ipv6_addr_type(daddr) & | ||
| 379 | (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL | IPV6_ADDR_LOOPBACK); | ||
| 380 | } | ||
| 381 | |||
| 382 | /* Multipath route selection: | 377 | /* Multipath route selection: |
| 383 | * Hash based function using packet header and flowlabel. | 378 | * Hash based function using packet header and flowlabel. |
| 384 | * Adapted from fib_info_hashfn() | 379 | * Adapted from fib_info_hashfn() |
| @@ -857,14 +852,15 @@ EXPORT_SYMBOL(rt6_lookup); | |||
| 857 | be destroyed. | 852 | be destroyed. |
| 858 | */ | 853 | */ |
| 859 | 854 | ||
| 860 | static int __ip6_ins_rt(struct rt6_info *rt, struct nl_info *info) | 855 | static int __ip6_ins_rt(struct rt6_info *rt, struct nl_info *info, |
| 856 | struct nlattr *mx, int mx_len) | ||
| 861 | { | 857 | { |
| 862 | int err; | 858 | int err; |
| 863 | struct fib6_table *table; | 859 | struct fib6_table *table; |
| 864 | 860 | ||
| 865 | table = rt->rt6i_table; | 861 | table = rt->rt6i_table; |
| 866 | write_lock_bh(&table->tb6_lock); | 862 | write_lock_bh(&table->tb6_lock); |
| 867 | err = fib6_add(&table->tb6_root, rt, info); | 863 | err = fib6_add(&table->tb6_root, rt, info, mx, mx_len); |
| 868 | write_unlock_bh(&table->tb6_lock); | 864 | write_unlock_bh(&table->tb6_lock); |
| 869 | 865 | ||
| 870 | return err; | 866 | return err; |
| @@ -875,7 +871,7 @@ int ip6_ins_rt(struct rt6_info *rt) | |||
| 875 | struct nl_info info = { | 871 | struct nl_info info = { |
| 876 | .nl_net = dev_net(rt->dst.dev), | 872 | .nl_net = dev_net(rt->dst.dev), |
| 877 | }; | 873 | }; |
| 878 | return __ip6_ins_rt(rt, &info); | 874 | return __ip6_ins_rt(rt, &info, NULL, 0); |
| 879 | } | 875 | } |
| 880 | 876 | ||
| 881 | static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, | 877 | static struct rt6_info *rt6_alloc_cow(struct rt6_info *ort, |
| @@ -1062,7 +1058,7 @@ struct dst_entry *ip6_blackhole_route(struct net *net, struct dst_entry *dst_ori | |||
| 1062 | 1058 | ||
| 1063 | new->__use = 1; | 1059 | new->__use = 1; |
| 1064 | new->input = dst_discard; | 1060 | new->input = dst_discard; |
| 1065 | new->output = dst_discard; | 1061 | new->output = dst_discard_sk; |
| 1066 | 1062 | ||
| 1067 | if (dst_metrics_read_only(&ort->dst)) | 1063 | if (dst_metrics_read_only(&ort->dst)) |
| 1068 | new->_metrics = ort->dst._metrics; | 1064 | new->_metrics = ort->dst._metrics; |
| @@ -1342,7 +1338,7 @@ static unsigned int ip6_mtu(const struct dst_entry *dst) | |||
| 1342 | unsigned int mtu = dst_metric_raw(dst, RTAX_MTU); | 1338 | unsigned int mtu = dst_metric_raw(dst, RTAX_MTU); |
| 1343 | 1339 | ||
| 1344 | if (mtu) | 1340 | if (mtu) |
| 1345 | return mtu; | 1341 | goto out; |
| 1346 | 1342 | ||
| 1347 | mtu = IPV6_MIN_MTU; | 1343 | mtu = IPV6_MIN_MTU; |
| 1348 | 1344 | ||
| @@ -1352,7 +1348,8 @@ static unsigned int ip6_mtu(const struct dst_entry *dst) | |||
| 1352 | mtu = idev->cnf.mtu6; | 1348 | mtu = idev->cnf.mtu6; |
| 1353 | rcu_read_unlock(); | 1349 | rcu_read_unlock(); |
| 1354 | 1350 | ||
| 1355 | return mtu; | 1351 | out: |
| 1352 | return min_t(unsigned int, mtu, IP6_MAX_MTU); | ||
| 1356 | } | 1353 | } |
| 1357 | 1354 | ||
| 1358 | static struct dst_entry *icmp6_dst_gc_list; | 1355 | static struct dst_entry *icmp6_dst_gc_list; |
| @@ -1543,17 +1540,11 @@ int ip6_route_add(struct fib6_config *cfg) | |||
| 1543 | 1540 | ||
| 1544 | ipv6_addr_prefix(&rt->rt6i_dst.addr, &cfg->fc_dst, cfg->fc_dst_len); | 1541 | ipv6_addr_prefix(&rt->rt6i_dst.addr, &cfg->fc_dst, cfg->fc_dst_len); |
| 1545 | rt->rt6i_dst.plen = cfg->fc_dst_len; | 1542 | rt->rt6i_dst.plen = cfg->fc_dst_len; |
| 1546 | if (rt->rt6i_dst.plen == 128) | 1543 | if (rt->rt6i_dst.plen == 128) { |
| 1547 | rt->dst.flags |= DST_HOST; | 1544 | rt->dst.flags |= DST_HOST; |
| 1548 | 1545 | dst_metrics_set_force_overwrite(&rt->dst); | |
| 1549 | if (!(rt->dst.flags & DST_HOST) && cfg->fc_mx) { | ||
| 1550 | u32 *metrics = kzalloc(sizeof(u32) * RTAX_MAX, GFP_KERNEL); | ||
| 1551 | if (!metrics) { | ||
| 1552 | err = -ENOMEM; | ||
| 1553 | goto out; | ||
| 1554 | } | ||
| 1555 | dst_init_metrics(&rt->dst, metrics, 0); | ||
| 1556 | } | 1546 | } |
| 1547 | |||
| 1557 | #ifdef CONFIG_IPV6_SUBTREES | 1548 | #ifdef CONFIG_IPV6_SUBTREES |
| 1558 | ipv6_addr_prefix(&rt->rt6i_src.addr, &cfg->fc_src, cfg->fc_src_len); | 1549 | ipv6_addr_prefix(&rt->rt6i_src.addr, &cfg->fc_src, cfg->fc_src_len); |
| 1559 | rt->rt6i_src.plen = cfg->fc_src_len; | 1550 | rt->rt6i_src.plen = cfg->fc_src_len; |
| @@ -1586,7 +1577,7 @@ int ip6_route_add(struct fib6_config *cfg) | |||
| 1586 | switch (cfg->fc_type) { | 1577 | switch (cfg->fc_type) { |
| 1587 | case RTN_BLACKHOLE: | 1578 | case RTN_BLACKHOLE: |
| 1588 | rt->dst.error = -EINVAL; | 1579 | rt->dst.error = -EINVAL; |
| 1589 | rt->dst.output = dst_discard; | 1580 | rt->dst.output = dst_discard_sk; |
| 1590 | rt->dst.input = dst_discard; | 1581 | rt->dst.input = dst_discard; |
| 1591 | break; | 1582 | break; |
| 1592 | case RTN_PROHIBIT: | 1583 | case RTN_PROHIBIT: |
| @@ -1672,31 +1663,13 @@ int ip6_route_add(struct fib6_config *cfg) | |||
| 1672 | rt->rt6i_flags = cfg->fc_flags; | 1663 | rt->rt6i_flags = cfg->fc_flags; |
| 1673 | 1664 | ||
| 1674 | install_route: | 1665 | install_route: |
| 1675 | if (cfg->fc_mx) { | ||
| 1676 | struct nlattr *nla; | ||
| 1677 | int remaining; | ||
| 1678 | |||
| 1679 | nla_for_each_attr(nla, cfg->fc_mx, cfg->fc_mx_len, remaining) { | ||
| 1680 | int type = nla_type(nla); | ||
| 1681 | |||
| 1682 | if (type) { | ||
| 1683 | if (type > RTAX_MAX) { | ||
| 1684 | err = -EINVAL; | ||
| 1685 | goto out; | ||
| 1686 | } | ||
| 1687 | |||
| 1688 | dst_metric_set(&rt->dst, type, nla_get_u32(nla)); | ||
| 1689 | } | ||
| 1690 | } | ||
| 1691 | } | ||
| 1692 | |||
| 1693 | rt->dst.dev = dev; | 1666 | rt->dst.dev = dev; |
| 1694 | rt->rt6i_idev = idev; | 1667 | rt->rt6i_idev = idev; |
| 1695 | rt->rt6i_table = table; | 1668 | rt->rt6i_table = table; |
| 1696 | 1669 | ||
| 1697 | cfg->fc_nlinfo.nl_net = dev_net(dev); | 1670 | cfg->fc_nlinfo.nl_net = dev_net(dev); |
| 1698 | 1671 | ||
| 1699 | return __ip6_ins_rt(rt, &cfg->fc_nlinfo); | 1672 | return __ip6_ins_rt(rt, &cfg->fc_nlinfo, cfg->fc_mx, cfg->fc_mx_len); |
| 1700 | 1673 | ||
| 1701 | out: | 1674 | out: |
| 1702 | if (dev) | 1675 | if (dev) |
| @@ -2156,7 +2129,7 @@ static int ip6_pkt_discard(struct sk_buff *skb) | |||
| 2156 | return ip6_pkt_drop(skb, ICMPV6_NOROUTE, IPSTATS_MIB_INNOROUTES); | 2129 | return ip6_pkt_drop(skb, ICMPV6_NOROUTE, IPSTATS_MIB_INNOROUTES); |
| 2157 | } | 2130 | } |
| 2158 | 2131 | ||
| 2159 | static int ip6_pkt_discard_out(struct sk_buff *skb) | 2132 | static int ip6_pkt_discard_out(struct sock *sk, struct sk_buff *skb) |
| 2160 | { | 2133 | { |
| 2161 | skb->dev = skb_dst(skb)->dev; | 2134 | skb->dev = skb_dst(skb)->dev; |
| 2162 | return ip6_pkt_drop(skb, ICMPV6_NOROUTE, IPSTATS_MIB_OUTNOROUTES); | 2135 | return ip6_pkt_drop(skb, ICMPV6_NOROUTE, IPSTATS_MIB_OUTNOROUTES); |
| @@ -2167,7 +2140,7 @@ static int ip6_pkt_prohibit(struct sk_buff *skb) | |||
| 2167 | return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_INNOROUTES); | 2140 | return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_INNOROUTES); |
| 2168 | } | 2141 | } |
| 2169 | 2142 | ||
| 2170 | static int ip6_pkt_prohibit_out(struct sk_buff *skb) | 2143 | static int ip6_pkt_prohibit_out(struct sock *sk, struct sk_buff *skb) |
| 2171 | { | 2144 | { |
| 2172 | skb->dev = skb_dst(skb)->dev; | 2145 | skb->dev = skb_dst(skb)->dev; |
| 2173 | return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES); | 2146 | return ip6_pkt_drop(skb, ICMPV6_ADM_PROHIBITED, IPSTATS_MIB_OUTNOROUTES); |
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index b4d74c86586c..8da8268d65f8 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c | |||
| @@ -974,8 +974,9 @@ static netdev_tx_t ipip6_tunnel_xmit(struct sk_buff *skb, | |||
| 974 | goto out; | 974 | goto out; |
| 975 | } | 975 | } |
| 976 | 976 | ||
| 977 | err = iptunnel_xmit(rt, skb, fl4.saddr, fl4.daddr, IPPROTO_IPV6, tos, | 977 | err = iptunnel_xmit(skb->sk, rt, skb, fl4.saddr, fl4.daddr, |
| 978 | ttl, df, !net_eq(tunnel->net, dev_net(dev))); | 978 | IPPROTO_IPV6, tos, ttl, df, |
| 979 | !net_eq(tunnel->net, dev_net(dev))); | ||
| 979 | iptunnel_xmit_stats(err, &dev->stats, dev->tstats); | 980 | iptunnel_xmit_stats(err, &dev->stats, dev->tstats); |
| 980 | return NETDEV_TX_OK; | 981 | return NETDEV_TX_OK; |
| 981 | 982 | ||
| @@ -1363,7 +1364,6 @@ static void ipip6_tunnel_setup(struct net_device *dev) | |||
| 1363 | static int ipip6_tunnel_init(struct net_device *dev) | 1364 | static int ipip6_tunnel_init(struct net_device *dev) |
| 1364 | { | 1365 | { |
| 1365 | struct ip_tunnel *tunnel = netdev_priv(dev); | 1366 | struct ip_tunnel *tunnel = netdev_priv(dev); |
| 1366 | int i; | ||
| 1367 | 1367 | ||
| 1368 | tunnel->dev = dev; | 1368 | tunnel->dev = dev; |
| 1369 | tunnel->net = dev_net(dev); | 1369 | tunnel->net = dev_net(dev); |
| @@ -1372,16 +1372,10 @@ static int ipip6_tunnel_init(struct net_device *dev) | |||
| 1372 | memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); | 1372 | memcpy(dev->broadcast, &tunnel->parms.iph.daddr, 4); |
| 1373 | 1373 | ||
| 1374 | ipip6_tunnel_bind_dev(dev); | 1374 | ipip6_tunnel_bind_dev(dev); |
| 1375 | dev->tstats = alloc_percpu(struct pcpu_sw_netstats); | 1375 | dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); |
| 1376 | if (!dev->tstats) | 1376 | if (!dev->tstats) |
| 1377 | return -ENOMEM; | 1377 | return -ENOMEM; |
| 1378 | 1378 | ||
| 1379 | for_each_possible_cpu(i) { | ||
| 1380 | struct pcpu_sw_netstats *ipip6_tunnel_stats; | ||
| 1381 | ipip6_tunnel_stats = per_cpu_ptr(dev->tstats, i); | ||
| 1382 | u64_stats_init(&ipip6_tunnel_stats->syncp); | ||
| 1383 | } | ||
| 1384 | |||
| 1385 | tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst); | 1379 | tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst); |
| 1386 | if (!tunnel->dst_cache) { | 1380 | if (!tunnel->dst_cache) { |
| 1387 | free_percpu(dev->tstats); | 1381 | free_percpu(dev->tstats); |
| @@ -1397,7 +1391,6 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev) | |||
| 1397 | struct iphdr *iph = &tunnel->parms.iph; | 1391 | struct iphdr *iph = &tunnel->parms.iph; |
| 1398 | struct net *net = dev_net(dev); | 1392 | struct net *net = dev_net(dev); |
| 1399 | struct sit_net *sitn = net_generic(net, sit_net_id); | 1393 | struct sit_net *sitn = net_generic(net, sit_net_id); |
| 1400 | int i; | ||
| 1401 | 1394 | ||
| 1402 | tunnel->dev = dev; | 1395 | tunnel->dev = dev; |
| 1403 | tunnel->net = dev_net(dev); | 1396 | tunnel->net = dev_net(dev); |
| @@ -1408,16 +1401,10 @@ static int __net_init ipip6_fb_tunnel_init(struct net_device *dev) | |||
| 1408 | iph->ihl = 5; | 1401 | iph->ihl = 5; |
| 1409 | iph->ttl = 64; | 1402 | iph->ttl = 64; |
| 1410 | 1403 | ||
| 1411 | dev->tstats = alloc_percpu(struct pcpu_sw_netstats); | 1404 | dev->tstats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); |
| 1412 | if (!dev->tstats) | 1405 | if (!dev->tstats) |
| 1413 | return -ENOMEM; | 1406 | return -ENOMEM; |
| 1414 | 1407 | ||
| 1415 | for_each_possible_cpu(i) { | ||
| 1416 | struct pcpu_sw_netstats *ipip6_fb_stats; | ||
| 1417 | ipip6_fb_stats = per_cpu_ptr(dev->tstats, i); | ||
| 1418 | u64_stats_init(&ipip6_fb_stats->syncp); | ||
| 1419 | } | ||
| 1420 | |||
| 1421 | tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst); | 1408 | tunnel->dst_cache = alloc_percpu(struct ip_tunnel_dst); |
| 1422 | if (!tunnel->dst_cache) { | 1409 | if (!tunnel->dst_cache) { |
| 1423 | free_percpu(dev->tstats); | 1410 | free_percpu(dev->tstats); |
diff --git a/net/ipv6/tcp_ipv6.c b/net/ipv6/tcp_ipv6.c index 889079b2ea85..e289830ed6e3 100644 --- a/net/ipv6/tcp_ipv6.c +++ b/net/ipv6/tcp_ipv6.c | |||
| @@ -39,7 +39,7 @@ | |||
| 39 | #include <linux/ipsec.h> | 39 | #include <linux/ipsec.h> |
| 40 | #include <linux/times.h> | 40 | #include <linux/times.h> |
| 41 | #include <linux/slab.h> | 41 | #include <linux/slab.h> |
| 42 | 42 | #include <linux/uaccess.h> | |
| 43 | #include <linux/ipv6.h> | 43 | #include <linux/ipv6.h> |
| 44 | #include <linux/icmpv6.h> | 44 | #include <linux/icmpv6.h> |
| 45 | #include <linux/random.h> | 45 | #include <linux/random.h> |
| @@ -65,8 +65,6 @@ | |||
| 65 | #include <net/tcp_memcontrol.h> | 65 | #include <net/tcp_memcontrol.h> |
| 66 | #include <net/busy_poll.h> | 66 | #include <net/busy_poll.h> |
| 67 | 67 | ||
| 68 | #include <asm/uaccess.h> | ||
| 69 | |||
| 70 | #include <linux/proc_fs.h> | 68 | #include <linux/proc_fs.h> |
| 71 | #include <linux/seq_file.h> | 69 | #include <linux/seq_file.h> |
| 72 | 70 | ||
| @@ -501,8 +499,10 @@ static int tcp_v6_rtx_synack(struct sock *sk, struct request_sock *req) | |||
| 501 | int res; | 499 | int res; |
| 502 | 500 | ||
| 503 | res = tcp_v6_send_synack(sk, NULL, &fl6, req, 0); | 501 | res = tcp_v6_send_synack(sk, NULL, &fl6, req, 0); |
| 504 | if (!res) | 502 | if (!res) { |
| 505 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS); | 503 | TCP_INC_STATS_BH(sock_net(sk), TCP_MIB_RETRANSSEGS); |
| 504 | NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_TCPSYNRETRANS); | ||
| 505 | } | ||
| 506 | return res; | 506 | return res; |
| 507 | } | 507 | } |
| 508 | 508 | ||
| @@ -530,8 +530,8 @@ static struct tcp_md5sig_key *tcp_v6_reqsk_md5_lookup(struct sock *sk, | |||
| 530 | return tcp_v6_md5_do_lookup(sk, &inet_rsk(req)->ir_v6_rmt_addr); | 530 | return tcp_v6_md5_do_lookup(sk, &inet_rsk(req)->ir_v6_rmt_addr); |
| 531 | } | 531 | } |
| 532 | 532 | ||
| 533 | static int tcp_v6_parse_md5_keys (struct sock *sk, char __user *optval, | 533 | static int tcp_v6_parse_md5_keys(struct sock *sk, char __user *optval, |
| 534 | int optlen) | 534 | int optlen) |
| 535 | { | 535 | { |
| 536 | struct tcp_md5sig cmd; | 536 | struct tcp_md5sig cmd; |
| 537 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&cmd.tcpm_addr; | 537 | struct sockaddr_in6 *sin6 = (struct sockaddr_in6 *)&cmd.tcpm_addr; |
| @@ -715,7 +715,7 @@ struct request_sock_ops tcp6_request_sock_ops __read_mostly = { | |||
| 715 | .send_ack = tcp_v6_reqsk_send_ack, | 715 | .send_ack = tcp_v6_reqsk_send_ack, |
| 716 | .destructor = tcp_v6_reqsk_destructor, | 716 | .destructor = tcp_v6_reqsk_destructor, |
| 717 | .send_reset = tcp_v6_send_reset, | 717 | .send_reset = tcp_v6_send_reset, |
| 718 | .syn_ack_timeout = tcp_syn_ack_timeout, | 718 | .syn_ack_timeout = tcp_syn_ack_timeout, |
| 719 | }; | 719 | }; |
| 720 | 720 | ||
| 721 | #ifdef CONFIG_TCP_MD5SIG | 721 | #ifdef CONFIG_TCP_MD5SIG |
| @@ -726,7 +726,7 @@ static const struct tcp_request_sock_ops tcp_request_sock_ipv6_ops = { | |||
| 726 | #endif | 726 | #endif |
| 727 | 727 | ||
| 728 | static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, | 728 | static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, |
| 729 | u32 tsval, u32 tsecr, | 729 | u32 tsval, u32 tsecr, int oif, |
| 730 | struct tcp_md5sig_key *key, int rst, u8 tclass, | 730 | struct tcp_md5sig_key *key, int rst, u8 tclass, |
| 731 | u32 label) | 731 | u32 label) |
| 732 | { | 732 | { |
| @@ -798,8 +798,10 @@ static void tcp_v6_send_response(struct sk_buff *skb, u32 seq, u32 ack, u32 win, | |||
| 798 | __tcp_v6_send_check(buff, &fl6.saddr, &fl6.daddr); | 798 | __tcp_v6_send_check(buff, &fl6.saddr, &fl6.daddr); |
| 799 | 799 | ||
| 800 | fl6.flowi6_proto = IPPROTO_TCP; | 800 | fl6.flowi6_proto = IPPROTO_TCP; |
| 801 | if (ipv6_addr_type(&fl6.daddr) & IPV6_ADDR_LINKLOCAL) | 801 | if (rt6_need_strict(&fl6.daddr) && !oif) |
| 802 | fl6.flowi6_oif = inet6_iif(skb); | 802 | fl6.flowi6_oif = inet6_iif(skb); |
| 803 | else | ||
| 804 | fl6.flowi6_oif = oif; | ||
| 803 | fl6.fl6_dport = t1->dest; | 805 | fl6.fl6_dport = t1->dest; |
| 804 | fl6.fl6_sport = t1->source; | 806 | fl6.fl6_sport = t1->source; |
| 805 | security_skb_classify_flow(skb, flowi6_to_flowi(&fl6)); | 807 | security_skb_classify_flow(skb, flowi6_to_flowi(&fl6)); |
| @@ -833,6 +835,7 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | |||
| 833 | int genhash; | 835 | int genhash; |
| 834 | struct sock *sk1 = NULL; | 836 | struct sock *sk1 = NULL; |
| 835 | #endif | 837 | #endif |
| 838 | int oif; | ||
| 836 | 839 | ||
| 837 | if (th->rst) | 840 | if (th->rst) |
| 838 | return; | 841 | return; |
| @@ -876,7 +879,8 @@ static void tcp_v6_send_reset(struct sock *sk, struct sk_buff *skb) | |||
| 876 | ack_seq = ntohl(th->seq) + th->syn + th->fin + skb->len - | 879 | ack_seq = ntohl(th->seq) + th->syn + th->fin + skb->len - |
| 877 | (th->doff << 2); | 880 | (th->doff << 2); |
| 878 | 881 | ||
| 879 | tcp_v6_send_response(skb, seq, ack_seq, 0, 0, 0, key, 1, 0, 0); | 882 | oif = sk ? sk->sk_bound_dev_if : 0; |
| 883 | tcp_v6_send_response(skb, seq, ack_seq, 0, 0, 0, oif, key, 1, 0, 0); | ||
| 880 | 884 | ||
| 881 | #ifdef CONFIG_TCP_MD5SIG | 885 | #ifdef CONFIG_TCP_MD5SIG |
| 882 | release_sk1: | 886 | release_sk1: |
| @@ -888,11 +892,11 @@ release_sk1: | |||
| 888 | } | 892 | } |
| 889 | 893 | ||
| 890 | static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, | 894 | static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, |
| 891 | u32 win, u32 tsval, u32 tsecr, | 895 | u32 win, u32 tsval, u32 tsecr, int oif, |
| 892 | struct tcp_md5sig_key *key, u8 tclass, | 896 | struct tcp_md5sig_key *key, u8 tclass, |
| 893 | u32 label) | 897 | u32 label) |
| 894 | { | 898 | { |
| 895 | tcp_v6_send_response(skb, seq, ack, win, tsval, tsecr, key, 0, tclass, | 899 | tcp_v6_send_response(skb, seq, ack, win, tsval, tsecr, oif, key, 0, tclass, |
| 896 | label); | 900 | label); |
| 897 | } | 901 | } |
| 898 | 902 | ||
| @@ -904,7 +908,7 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb) | |||
| 904 | tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, | 908 | tcp_v6_send_ack(skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, |
| 905 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, | 909 | tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, |
| 906 | tcp_time_stamp + tcptw->tw_ts_offset, | 910 | tcp_time_stamp + tcptw->tw_ts_offset, |
| 907 | tcptw->tw_ts_recent, tcp_twsk_md5_key(tcptw), | 911 | tcptw->tw_ts_recent, tw->tw_bound_dev_if, tcp_twsk_md5_key(tcptw), |
| 908 | tw->tw_tclass, (tw->tw_flowlabel << 12)); | 912 | tw->tw_tclass, (tw->tw_flowlabel << 12)); |
| 909 | 913 | ||
| 910 | inet_twsk_put(tw); | 914 | inet_twsk_put(tw); |
| @@ -914,7 +918,7 @@ static void tcp_v6_reqsk_send_ack(struct sock *sk, struct sk_buff *skb, | |||
| 914 | struct request_sock *req) | 918 | struct request_sock *req) |
| 915 | { | 919 | { |
| 916 | tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, | 920 | tcp_v6_send_ack(skb, tcp_rsk(req)->snt_isn + 1, tcp_rsk(req)->rcv_isn + 1, |
| 917 | req->rcv_wnd, tcp_time_stamp, req->ts_recent, | 921 | req->rcv_wnd, tcp_time_stamp, req->ts_recent, sk->sk_bound_dev_if, |
| 918 | tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr), | 922 | tcp_v6_md5_do_lookup(sk, &ipv6_hdr(skb)->daddr), |
| 919 | 0, 0); | 923 | 0, 0); |
| 920 | } | 924 | } |
| @@ -1259,7 +1263,8 @@ static struct sock *tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb, | |||
| 1259 | 1263 | ||
| 1260 | #ifdef CONFIG_TCP_MD5SIG | 1264 | #ifdef CONFIG_TCP_MD5SIG |
| 1261 | /* Copy over the MD5 key from the original socket */ | 1265 | /* Copy over the MD5 key from the original socket */ |
| 1262 | if ((key = tcp_v6_md5_do_lookup(sk, &newsk->sk_v6_daddr)) != NULL) { | 1266 | key = tcp_v6_md5_do_lookup(sk, &newsk->sk_v6_daddr); |
| 1267 | if (key != NULL) { | ||
| 1263 | /* We're using one, so create a matching key | 1268 | /* We're using one, so create a matching key |
| 1264 | * on the newsk structure. If we fail to get | 1269 | * on the newsk structure. If we fail to get |
| 1265 | * memory, then we end up not copying the key | 1270 | * memory, then we end up not copying the key |
| @@ -1303,9 +1308,8 @@ static __sum16 tcp_v6_checksum_init(struct sk_buff *skb) | |||
| 1303 | &ipv6_hdr(skb)->saddr, | 1308 | &ipv6_hdr(skb)->saddr, |
| 1304 | &ipv6_hdr(skb)->daddr, 0)); | 1309 | &ipv6_hdr(skb)->daddr, 0)); |
| 1305 | 1310 | ||
| 1306 | if (skb->len <= 76) { | 1311 | if (skb->len <= 76) |
| 1307 | return __skb_checksum_complete(skb); | 1312 | return __skb_checksum_complete(skb); |
| 1308 | } | ||
| 1309 | return 0; | 1313 | return 0; |
| 1310 | } | 1314 | } |
| 1311 | 1315 | ||
| @@ -1335,7 +1339,7 @@ static int tcp_v6_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
| 1335 | return tcp_v4_do_rcv(sk, skb); | 1339 | return tcp_v4_do_rcv(sk, skb); |
| 1336 | 1340 | ||
| 1337 | #ifdef CONFIG_TCP_MD5SIG | 1341 | #ifdef CONFIG_TCP_MD5SIG |
| 1338 | if (tcp_v6_inbound_md5_hash (sk, skb)) | 1342 | if (tcp_v6_inbound_md5_hash(sk, skb)) |
| 1339 | goto discard; | 1343 | goto discard; |
| 1340 | #endif | 1344 | #endif |
| 1341 | 1345 | ||
| @@ -1602,7 +1606,8 @@ do_time_wait: | |||
| 1602 | break; | 1606 | break; |
| 1603 | case TCP_TW_RST: | 1607 | case TCP_TW_RST: |
| 1604 | goto no_tcp_socket; | 1608 | goto no_tcp_socket; |
| 1605 | case TCP_TW_SUCCESS:; | 1609 | case TCP_TW_SUCCESS: |
| 1610 | ; | ||
| 1606 | } | 1611 | } |
| 1607 | goto discard_it; | 1612 | goto discard_it; |
| 1608 | } | 1613 | } |
| @@ -1647,7 +1652,7 @@ static void tcp_v6_early_demux(struct sk_buff *skb) | |||
| 1647 | static struct timewait_sock_ops tcp6_timewait_sock_ops = { | 1652 | static struct timewait_sock_ops tcp6_timewait_sock_ops = { |
| 1648 | .twsk_obj_size = sizeof(struct tcp6_timewait_sock), | 1653 | .twsk_obj_size = sizeof(struct tcp6_timewait_sock), |
| 1649 | .twsk_unique = tcp_twsk_unique, | 1654 | .twsk_unique = tcp_twsk_unique, |
| 1650 | .twsk_destructor= tcp_twsk_destructor, | 1655 | .twsk_destructor = tcp_twsk_destructor, |
| 1651 | }; | 1656 | }; |
| 1652 | 1657 | ||
| 1653 | static const struct inet_connection_sock_af_ops ipv6_specific = { | 1658 | static const struct inet_connection_sock_af_ops ipv6_specific = { |
| @@ -1681,7 +1686,6 @@ static const struct tcp_sock_af_ops tcp_sock_ipv6_specific = { | |||
| 1681 | /* | 1686 | /* |
| 1682 | * TCP over IPv4 via INET6 API | 1687 | * TCP over IPv4 via INET6 API |
| 1683 | */ | 1688 | */ |
| 1684 | |||
| 1685 | static const struct inet_connection_sock_af_ops ipv6_mapped = { | 1689 | static const struct inet_connection_sock_af_ops ipv6_mapped = { |
| 1686 | .queue_xmit = ip_queue_xmit, | 1690 | .queue_xmit = ip_queue_xmit, |
| 1687 | .send_check = tcp_v4_send_check, | 1691 | .send_check = tcp_v4_send_check, |
diff --git a/net/ipv6/xfrm6_mode_tunnel.c b/net/ipv6/xfrm6_mode_tunnel.c index cb04f7a16b5e..901ef6f8addc 100644 --- a/net/ipv6/xfrm6_mode_tunnel.c +++ b/net/ipv6/xfrm6_mode_tunnel.c | |||
| @@ -18,65 +18,6 @@ | |||
| 18 | #include <net/ipv6.h> | 18 | #include <net/ipv6.h> |
| 19 | #include <net/xfrm.h> | 19 | #include <net/xfrm.h> |
| 20 | 20 | ||
| 21 | /* Informational hook. The decap is still done here. */ | ||
| 22 | static struct xfrm_tunnel_notifier __rcu *rcv_notify_handlers __read_mostly; | ||
| 23 | static DEFINE_MUTEX(xfrm6_mode_tunnel_input_mutex); | ||
| 24 | |||
| 25 | int xfrm6_mode_tunnel_input_register(struct xfrm_tunnel_notifier *handler) | ||
| 26 | { | ||
| 27 | struct xfrm_tunnel_notifier __rcu **pprev; | ||
| 28 | struct xfrm_tunnel_notifier *t; | ||
| 29 | int ret = -EEXIST; | ||
| 30 | int priority = handler->priority; | ||
| 31 | |||
| 32 | mutex_lock(&xfrm6_mode_tunnel_input_mutex); | ||
| 33 | |||
| 34 | for (pprev = &rcv_notify_handlers; | ||
| 35 | (t = rcu_dereference_protected(*pprev, | ||
| 36 | lockdep_is_held(&xfrm6_mode_tunnel_input_mutex))) != NULL; | ||
| 37 | pprev = &t->next) { | ||
| 38 | if (t->priority > priority) | ||
| 39 | break; | ||
| 40 | if (t->priority == priority) | ||
| 41 | goto err; | ||
| 42 | |||
| 43 | } | ||
| 44 | |||
| 45 | handler->next = *pprev; | ||
| 46 | rcu_assign_pointer(*pprev, handler); | ||
| 47 | |||
| 48 | ret = 0; | ||
| 49 | |||
| 50 | err: | ||
| 51 | mutex_unlock(&xfrm6_mode_tunnel_input_mutex); | ||
| 52 | return ret; | ||
| 53 | } | ||
| 54 | EXPORT_SYMBOL_GPL(xfrm6_mode_tunnel_input_register); | ||
| 55 | |||
| 56 | int xfrm6_mode_tunnel_input_deregister(struct xfrm_tunnel_notifier *handler) | ||
| 57 | { | ||
| 58 | struct xfrm_tunnel_notifier __rcu **pprev; | ||
| 59 | struct xfrm_tunnel_notifier *t; | ||
| 60 | int ret = -ENOENT; | ||
| 61 | |||
| 62 | mutex_lock(&xfrm6_mode_tunnel_input_mutex); | ||
| 63 | for (pprev = &rcv_notify_handlers; | ||
| 64 | (t = rcu_dereference_protected(*pprev, | ||
| 65 | lockdep_is_held(&xfrm6_mode_tunnel_input_mutex))) != NULL; | ||
| 66 | pprev = &t->next) { | ||
| 67 | if (t == handler) { | ||
| 68 | *pprev = handler->next; | ||
| 69 | ret = 0; | ||
| 70 | break; | ||
| 71 | } | ||
| 72 | } | ||
| 73 | mutex_unlock(&xfrm6_mode_tunnel_input_mutex); | ||
| 74 | synchronize_net(); | ||
| 75 | |||
| 76 | return ret; | ||
| 77 | } | ||
| 78 | EXPORT_SYMBOL_GPL(xfrm6_mode_tunnel_input_deregister); | ||
| 79 | |||
| 80 | static inline void ipip6_ecn_decapsulate(struct sk_buff *skb) | 21 | static inline void ipip6_ecn_decapsulate(struct sk_buff *skb) |
| 81 | { | 22 | { |
| 82 | const struct ipv6hdr *outer_iph = ipv6_hdr(skb); | 23 | const struct ipv6hdr *outer_iph = ipv6_hdr(skb); |
| @@ -130,7 +71,6 @@ static int xfrm6_mode_tunnel_output(struct xfrm_state *x, struct sk_buff *skb) | |||
| 130 | 71 | ||
| 131 | static int xfrm6_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) | 72 | static int xfrm6_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) |
| 132 | { | 73 | { |
| 133 | struct xfrm_tunnel_notifier *handler; | ||
| 134 | int err = -EINVAL; | 74 | int err = -EINVAL; |
| 135 | 75 | ||
| 136 | if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPV6) | 76 | if (XFRM_MODE_SKB_CB(skb)->protocol != IPPROTO_IPV6) |
| @@ -138,9 +78,6 @@ static int xfrm6_mode_tunnel_input(struct xfrm_state *x, struct sk_buff *skb) | |||
| 138 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) | 78 | if (!pskb_may_pull(skb, sizeof(struct ipv6hdr))) |
| 139 | goto out; | 79 | goto out; |
| 140 | 80 | ||
| 141 | for_each_input_rcu(rcv_notify_handlers, handler) | ||
| 142 | handler->handler(skb); | ||
| 143 | |||
| 144 | err = skb_unclone(skb, GFP_ATOMIC); | 81 | err = skb_unclone(skb, GFP_ATOMIC); |
| 145 | if (err) | 82 | if (err) |
| 146 | goto out; | 83 | goto out; |
diff --git a/net/ipv6/xfrm6_output.c b/net/ipv6/xfrm6_output.c index 6cd625e37706..19ef329bdbf8 100644 --- a/net/ipv6/xfrm6_output.c +++ b/net/ipv6/xfrm6_output.c | |||
| @@ -163,7 +163,7 @@ static int __xfrm6_output(struct sk_buff *skb) | |||
| 163 | return x->outer_mode->afinfo->output_finish(skb); | 163 | return x->outer_mode->afinfo->output_finish(skb); |
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | int xfrm6_output(struct sk_buff *skb) | 166 | int xfrm6_output(struct sock *sk, struct sk_buff *skb) |
| 167 | { | 167 | { |
| 168 | return NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING, skb, NULL, | 168 | return NF_HOOK(NFPROTO_IPV6, NF_INET_POST_ROUTING, skb, NULL, |
| 169 | skb_dst(skb)->dev, __xfrm6_output); | 169 | skb_dst(skb)->dev, __xfrm6_output); |
diff --git a/net/ipv6/xfrm6_policy.c b/net/ipv6/xfrm6_policy.c index 5f8e128c512d..2a0bbda2c76a 100644 --- a/net/ipv6/xfrm6_policy.c +++ b/net/ipv6/xfrm6_policy.c | |||
| @@ -389,11 +389,17 @@ int __init xfrm6_init(void) | |||
| 389 | if (ret) | 389 | if (ret) |
| 390 | goto out_policy; | 390 | goto out_policy; |
| 391 | 391 | ||
| 392 | ret = xfrm6_protocol_init(); | ||
| 393 | if (ret) | ||
| 394 | goto out_state; | ||
| 395 | |||
| 392 | #ifdef CONFIG_SYSCTL | 396 | #ifdef CONFIG_SYSCTL |
| 393 | register_pernet_subsys(&xfrm6_net_ops); | 397 | register_pernet_subsys(&xfrm6_net_ops); |
| 394 | #endif | 398 | #endif |
| 395 | out: | 399 | out: |
| 396 | return ret; | 400 | return ret; |
| 401 | out_state: | ||
| 402 | xfrm6_state_fini(); | ||
| 397 | out_policy: | 403 | out_policy: |
| 398 | xfrm6_policy_fini(); | 404 | xfrm6_policy_fini(); |
| 399 | goto out; | 405 | goto out; |
| @@ -404,6 +410,7 @@ void xfrm6_fini(void) | |||
| 404 | #ifdef CONFIG_SYSCTL | 410 | #ifdef CONFIG_SYSCTL |
| 405 | unregister_pernet_subsys(&xfrm6_net_ops); | 411 | unregister_pernet_subsys(&xfrm6_net_ops); |
| 406 | #endif | 412 | #endif |
| 413 | xfrm6_protocol_fini(); | ||
| 407 | xfrm6_policy_fini(); | 414 | xfrm6_policy_fini(); |
| 408 | xfrm6_state_fini(); | 415 | xfrm6_state_fini(); |
| 409 | dst_entries_destroy(&xfrm6_dst_ops); | 416 | dst_entries_destroy(&xfrm6_dst_ops); |
diff --git a/net/ipv6/xfrm6_protocol.c b/net/ipv6/xfrm6_protocol.c new file mode 100644 index 000000000000..6ab989c486f7 --- /dev/null +++ b/net/ipv6/xfrm6_protocol.c | |||
| @@ -0,0 +1,270 @@ | |||
| 1 | /* xfrm6_protocol.c - Generic xfrm protocol multiplexer for ipv6. | ||
| 2 | * | ||
| 3 | * Copyright (C) 2013 secunet Security Networks AG | ||
| 4 | * | ||
| 5 | * Author: | ||
| 6 | * Steffen Klassert <steffen.klassert@secunet.com> | ||
| 7 | * | ||
| 8 | * Based on: | ||
| 9 | * net/ipv4/xfrm4_protocol.c | ||
| 10 | * | ||
| 11 | * This program is free software; you can redistribute it and/or | ||
| 12 | * modify it under the terms of the GNU General Public License | ||
| 13 | * as published by the Free Software Foundation; either version | ||
| 14 | * 2 of the License, or (at your option) any later version. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/init.h> | ||
| 18 | #include <linux/mutex.h> | ||
| 19 | #include <linux/skbuff.h> | ||
| 20 | #include <linux/icmpv6.h> | ||
| 21 | #include <net/ipv6.h> | ||
| 22 | #include <net/protocol.h> | ||
| 23 | #include <net/xfrm.h> | ||
| 24 | |||
| 25 | static struct xfrm6_protocol __rcu *esp6_handlers __read_mostly; | ||
| 26 | static struct xfrm6_protocol __rcu *ah6_handlers __read_mostly; | ||
| 27 | static struct xfrm6_protocol __rcu *ipcomp6_handlers __read_mostly; | ||
| 28 | static DEFINE_MUTEX(xfrm6_protocol_mutex); | ||
| 29 | |||
| 30 | static inline struct xfrm6_protocol __rcu **proto_handlers(u8 protocol) | ||
| 31 | { | ||
| 32 | switch (protocol) { | ||
| 33 | case IPPROTO_ESP: | ||
| 34 | return &esp6_handlers; | ||
| 35 | case IPPROTO_AH: | ||
| 36 | return &ah6_handlers; | ||
| 37 | case IPPROTO_COMP: | ||
| 38 | return &ipcomp6_handlers; | ||
| 39 | } | ||
| 40 | |||
| 41 | return NULL; | ||
| 42 | } | ||
| 43 | |||
| 44 | #define for_each_protocol_rcu(head, handler) \ | ||
| 45 | for (handler = rcu_dereference(head); \ | ||
| 46 | handler != NULL; \ | ||
| 47 | handler = rcu_dereference(handler->next)) \ | ||
| 48 | |||
| 49 | int xfrm6_rcv_cb(struct sk_buff *skb, u8 protocol, int err) | ||
| 50 | { | ||
| 51 | int ret; | ||
| 52 | struct xfrm6_protocol *handler; | ||
| 53 | |||
| 54 | for_each_protocol_rcu(*proto_handlers(protocol), handler) | ||
| 55 | if ((ret = handler->cb_handler(skb, err)) <= 0) | ||
| 56 | return ret; | ||
| 57 | |||
| 58 | return 0; | ||
| 59 | } | ||
| 60 | EXPORT_SYMBOL(xfrm6_rcv_cb); | ||
| 61 | |||
| 62 | static int xfrm6_esp_rcv(struct sk_buff *skb) | ||
| 63 | { | ||
| 64 | int ret; | ||
| 65 | struct xfrm6_protocol *handler; | ||
| 66 | |||
| 67 | XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL; | ||
| 68 | |||
| 69 | for_each_protocol_rcu(esp6_handlers, handler) | ||
| 70 | if ((ret = handler->handler(skb)) != -EINVAL) | ||
| 71 | return ret; | ||
| 72 | |||
| 73 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); | ||
| 74 | |||
| 75 | kfree_skb(skb); | ||
| 76 | return 0; | ||
| 77 | } | ||
| 78 | |||
| 79 | static void xfrm6_esp_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | ||
| 80 | u8 type, u8 code, int offset, __be32 info) | ||
| 81 | { | ||
| 82 | struct xfrm6_protocol *handler; | ||
| 83 | |||
| 84 | for_each_protocol_rcu(esp6_handlers, handler) | ||
| 85 | if (!handler->err_handler(skb, opt, type, code, offset, info)) | ||
| 86 | break; | ||
| 87 | } | ||
| 88 | |||
| 89 | static int xfrm6_ah_rcv(struct sk_buff *skb) | ||
| 90 | { | ||
| 91 | int ret; | ||
| 92 | struct xfrm6_protocol *handler; | ||
| 93 | |||
| 94 | XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL; | ||
| 95 | |||
| 96 | for_each_protocol_rcu(ah6_handlers, handler) | ||
| 97 | if ((ret = handler->handler(skb)) != -EINVAL) | ||
| 98 | return ret; | ||
| 99 | |||
| 100 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); | ||
| 101 | |||
| 102 | kfree_skb(skb); | ||
| 103 | return 0; | ||
| 104 | } | ||
| 105 | |||
| 106 | static void xfrm6_ah_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | ||
| 107 | u8 type, u8 code, int offset, __be32 info) | ||
| 108 | { | ||
| 109 | struct xfrm6_protocol *handler; | ||
| 110 | |||
| 111 | for_each_protocol_rcu(ah6_handlers, handler) | ||
| 112 | if (!handler->err_handler(skb, opt, type, code, offset, info)) | ||
| 113 | break; | ||
| 114 | } | ||
| 115 | |||
| 116 | static int xfrm6_ipcomp_rcv(struct sk_buff *skb) | ||
| 117 | { | ||
| 118 | int ret; | ||
| 119 | struct xfrm6_protocol *handler; | ||
| 120 | |||
| 121 | XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip6 = NULL; | ||
| 122 | |||
| 123 | for_each_protocol_rcu(ipcomp6_handlers, handler) | ||
| 124 | if ((ret = handler->handler(skb)) != -EINVAL) | ||
| 125 | return ret; | ||
| 126 | |||
| 127 | icmpv6_send(skb, ICMPV6_DEST_UNREACH, ICMPV6_PORT_UNREACH, 0); | ||
| 128 | |||
| 129 | kfree_skb(skb); | ||
| 130 | return 0; | ||
| 131 | } | ||
| 132 | |||
| 133 | static void xfrm6_ipcomp_err(struct sk_buff *skb, struct inet6_skb_parm *opt, | ||
| 134 | u8 type, u8 code, int offset, __be32 info) | ||
| 135 | { | ||
| 136 | struct xfrm6_protocol *handler; | ||
| 137 | |||
| 138 | for_each_protocol_rcu(ipcomp6_handlers, handler) | ||
| 139 | if (!handler->err_handler(skb, opt, type, code, offset, info)) | ||
| 140 | break; | ||
| 141 | } | ||
| 142 | |||
| 143 | static const struct inet6_protocol esp6_protocol = { | ||
| 144 | .handler = xfrm6_esp_rcv, | ||
| 145 | .err_handler = xfrm6_esp_err, | ||
| 146 | .flags = INET6_PROTO_NOPOLICY, | ||
| 147 | }; | ||
| 148 | |||
| 149 | static const struct inet6_protocol ah6_protocol = { | ||
| 150 | .handler = xfrm6_ah_rcv, | ||
| 151 | .err_handler = xfrm6_ah_err, | ||
| 152 | .flags = INET6_PROTO_NOPOLICY, | ||
| 153 | }; | ||
| 154 | |||
| 155 | static const struct inet6_protocol ipcomp6_protocol = { | ||
| 156 | .handler = xfrm6_ipcomp_rcv, | ||
| 157 | .err_handler = xfrm6_ipcomp_err, | ||
| 158 | .flags = INET6_PROTO_NOPOLICY, | ||
| 159 | }; | ||
| 160 | |||
| 161 | static struct xfrm_input_afinfo xfrm6_input_afinfo = { | ||
| 162 | .family = AF_INET6, | ||
| 163 | .owner = THIS_MODULE, | ||
| 164 | .callback = xfrm6_rcv_cb, | ||
| 165 | }; | ||
| 166 | |||
| 167 | static inline const struct inet6_protocol *netproto(unsigned char protocol) | ||
| 168 | { | ||
| 169 | switch (protocol) { | ||
| 170 | case IPPROTO_ESP: | ||
| 171 | return &esp6_protocol; | ||
| 172 | case IPPROTO_AH: | ||
| 173 | return &ah6_protocol; | ||
| 174 | case IPPROTO_COMP: | ||
| 175 | return &ipcomp6_protocol; | ||
| 176 | } | ||
| 177 | |||
| 178 | return NULL; | ||
| 179 | } | ||
| 180 | |||
| 181 | int xfrm6_protocol_register(struct xfrm6_protocol *handler, | ||
| 182 | unsigned char protocol) | ||
| 183 | { | ||
| 184 | struct xfrm6_protocol __rcu **pprev; | ||
| 185 | struct xfrm6_protocol *t; | ||
| 186 | bool add_netproto = false; | ||
| 187 | |||
| 188 | int ret = -EEXIST; | ||
| 189 | int priority = handler->priority; | ||
| 190 | |||
| 191 | mutex_lock(&xfrm6_protocol_mutex); | ||
| 192 | |||
| 193 | if (!rcu_dereference_protected(*proto_handlers(protocol), | ||
| 194 | lockdep_is_held(&xfrm6_protocol_mutex))) | ||
| 195 | add_netproto = true; | ||
| 196 | |||
| 197 | for (pprev = proto_handlers(protocol); | ||
| 198 | (t = rcu_dereference_protected(*pprev, | ||
| 199 | lockdep_is_held(&xfrm6_protocol_mutex))) != NULL; | ||
| 200 | pprev = &t->next) { | ||
| 201 | if (t->priority < priority) | ||
| 202 | break; | ||
| 203 | if (t->priority == priority) | ||
| 204 | goto err; | ||
| 205 | } | ||
| 206 | |||
| 207 | handler->next = *pprev; | ||
| 208 | rcu_assign_pointer(*pprev, handler); | ||
| 209 | |||
| 210 | ret = 0; | ||
| 211 | |||
| 212 | err: | ||
| 213 | mutex_unlock(&xfrm6_protocol_mutex); | ||
| 214 | |||
| 215 | if (add_netproto) { | ||
| 216 | if (inet6_add_protocol(netproto(protocol), protocol)) { | ||
| 217 | pr_err("%s: can't add protocol\n", __func__); | ||
| 218 | ret = -EAGAIN; | ||
| 219 | } | ||
| 220 | } | ||
| 221 | |||
| 222 | return ret; | ||
| 223 | } | ||
| 224 | EXPORT_SYMBOL(xfrm6_protocol_register); | ||
| 225 | |||
| 226 | int xfrm6_protocol_deregister(struct xfrm6_protocol *handler, | ||
| 227 | unsigned char protocol) | ||
| 228 | { | ||
| 229 | struct xfrm6_protocol __rcu **pprev; | ||
| 230 | struct xfrm6_protocol *t; | ||
| 231 | int ret = -ENOENT; | ||
| 232 | |||
| 233 | mutex_lock(&xfrm6_protocol_mutex); | ||
| 234 | |||
| 235 | for (pprev = proto_handlers(protocol); | ||
| 236 | (t = rcu_dereference_protected(*pprev, | ||
| 237 | lockdep_is_held(&xfrm6_protocol_mutex))) != NULL; | ||
| 238 | pprev = &t->next) { | ||
| 239 | if (t == handler) { | ||
| 240 | *pprev = handler->next; | ||
| 241 | ret = 0; | ||
| 242 | break; | ||
| 243 | } | ||
| 244 | } | ||
| 245 | |||
| 246 | if (!rcu_dereference_protected(*proto_handlers(protocol), | ||
| 247 | lockdep_is_held(&xfrm6_protocol_mutex))) { | ||
| 248 | if (inet6_del_protocol(netproto(protocol), protocol) < 0) { | ||
| 249 | pr_err("%s: can't remove protocol\n", __func__); | ||
| 250 | ret = -EAGAIN; | ||
| 251 | } | ||
| 252 | } | ||
| 253 | |||
| 254 | mutex_unlock(&xfrm6_protocol_mutex); | ||
| 255 | |||
| 256 | synchronize_net(); | ||
| 257 | |||
| 258 | return ret; | ||
| 259 | } | ||
| 260 | EXPORT_SYMBOL(xfrm6_protocol_deregister); | ||
| 261 | |||
| 262 | int __init xfrm6_protocol_init(void) | ||
| 263 | { | ||
| 264 | return xfrm_input_register_afinfo(&xfrm6_input_afinfo); | ||
| 265 | } | ||
| 266 | |||
| 267 | void xfrm6_protocol_fini(void) | ||
| 268 | { | ||
| 269 | xfrm_input_unregister_afinfo(&xfrm6_input_afinfo); | ||
| 270 | } | ||
diff --git a/net/ipx/af_ipx.c b/net/ipx/af_ipx.c index 00b2a6d1c009..41e4e93cb3aa 100644 --- a/net/ipx/af_ipx.c +++ b/net/ipx/af_ipx.c | |||
| @@ -1368,6 +1368,7 @@ static int ipx_release(struct socket *sock) | |||
| 1368 | goto out; | 1368 | goto out; |
| 1369 | 1369 | ||
| 1370 | lock_sock(sk); | 1370 | lock_sock(sk); |
| 1371 | sk->sk_shutdown = SHUTDOWN_MASK; | ||
| 1371 | if (!sock_flag(sk, SOCK_DEAD)) | 1372 | if (!sock_flag(sk, SOCK_DEAD)) |
| 1372 | sk->sk_state_change(sk); | 1373 | sk->sk_state_change(sk); |
| 1373 | 1374 | ||
| @@ -1791,8 +1792,11 @@ static int ipx_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
| 1791 | 1792 | ||
| 1792 | skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, | 1793 | skb = skb_recv_datagram(sk, flags & ~MSG_DONTWAIT, |
| 1793 | flags & MSG_DONTWAIT, &rc); | 1794 | flags & MSG_DONTWAIT, &rc); |
| 1794 | if (!skb) | 1795 | if (!skb) { |
| 1796 | if (rc == -EAGAIN && (sk->sk_shutdown & RCV_SHUTDOWN)) | ||
| 1797 | rc = 0; | ||
| 1795 | goto out; | 1798 | goto out; |
| 1799 | } | ||
| 1796 | 1800 | ||
| 1797 | ipx = ipx_hdr(skb); | 1801 | ipx = ipx_hdr(skb); |
| 1798 | copied = ntohs(ipx->ipx_pktsize) - sizeof(struct ipxhdr); | 1802 | copied = ntohs(ipx->ipx_pktsize) - sizeof(struct ipxhdr); |
| @@ -1922,6 +1926,26 @@ static int ipx_compat_ioctl(struct socket *sock, unsigned int cmd, unsigned long | |||
| 1922 | } | 1926 | } |
| 1923 | #endif | 1927 | #endif |
| 1924 | 1928 | ||
| 1929 | static int ipx_shutdown(struct socket *sock, int mode) | ||
| 1930 | { | ||
| 1931 | struct sock *sk = sock->sk; | ||
| 1932 | |||
| 1933 | if (mode < SHUT_RD || mode > SHUT_RDWR) | ||
| 1934 | return -EINVAL; | ||
| 1935 | /* This maps: | ||
| 1936 | * SHUT_RD (0) -> RCV_SHUTDOWN (1) | ||
| 1937 | * SHUT_WR (1) -> SEND_SHUTDOWN (2) | ||
| 1938 | * SHUT_RDWR (2) -> SHUTDOWN_MASK (3) | ||
| 1939 | */ | ||
| 1940 | ++mode; | ||
| 1941 | |||
| 1942 | lock_sock(sk); | ||
| 1943 | sk->sk_shutdown |= mode; | ||
| 1944 | release_sock(sk); | ||
| 1945 | sk->sk_state_change(sk); | ||
| 1946 | |||
| 1947 | return 0; | ||
| 1948 | } | ||
| 1925 | 1949 | ||
| 1926 | /* | 1950 | /* |
| 1927 | * Socket family declarations | 1951 | * Socket family declarations |
| @@ -1948,7 +1972,7 @@ static const struct proto_ops ipx_dgram_ops = { | |||
| 1948 | .compat_ioctl = ipx_compat_ioctl, | 1972 | .compat_ioctl = ipx_compat_ioctl, |
| 1949 | #endif | 1973 | #endif |
| 1950 | .listen = sock_no_listen, | 1974 | .listen = sock_no_listen, |
| 1951 | .shutdown = sock_no_shutdown, /* FIXME: support shutdown */ | 1975 | .shutdown = ipx_shutdown, |
| 1952 | .setsockopt = ipx_setsockopt, | 1976 | .setsockopt = ipx_setsockopt, |
| 1953 | .getsockopt = ipx_getsockopt, | 1977 | .getsockopt = ipx_getsockopt, |
| 1954 | .sendmsg = ipx_sendmsg, | 1978 | .sendmsg = ipx_sendmsg, |
diff --git a/net/iucv/af_iucv.c b/net/iucv/af_iucv.c index c4b7218058b6..01e77b0ae075 100644 --- a/net/iucv/af_iucv.c +++ b/net/iucv/af_iucv.c | |||
| @@ -1382,6 +1382,7 @@ static int iucv_sock_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
| 1382 | if (sk->sk_type == SOCK_STREAM) { | 1382 | if (sk->sk_type == SOCK_STREAM) { |
| 1383 | if (copied < rlen) { | 1383 | if (copied < rlen) { |
| 1384 | IUCV_SKB_CB(skb)->offset = offset + copied; | 1384 | IUCV_SKB_CB(skb)->offset = offset + copied; |
| 1385 | skb_queue_head(&sk->sk_receive_queue, skb); | ||
| 1385 | goto done; | 1386 | goto done; |
| 1386 | } | 1387 | } |
| 1387 | } | 1388 | } |
| @@ -1756,7 +1757,7 @@ static int iucv_callback_connreq(struct iucv_path *path, | |||
| 1756 | 1757 | ||
| 1757 | /* Wake up accept */ | 1758 | /* Wake up accept */ |
| 1758 | nsk->sk_state = IUCV_CONNECTED; | 1759 | nsk->sk_state = IUCV_CONNECTED; |
| 1759 | sk->sk_data_ready(sk, 1); | 1760 | sk->sk_data_ready(sk); |
| 1760 | err = 0; | 1761 | err = 0; |
| 1761 | fail: | 1762 | fail: |
| 1762 | bh_unlock_sock(sk); | 1763 | bh_unlock_sock(sk); |
| @@ -1967,7 +1968,7 @@ static int afiucv_hs_callback_syn(struct sock *sk, struct sk_buff *skb) | |||
| 1967 | if (!err) { | 1968 | if (!err) { |
| 1968 | iucv_accept_enqueue(sk, nsk); | 1969 | iucv_accept_enqueue(sk, nsk); |
| 1969 | nsk->sk_state = IUCV_CONNECTED; | 1970 | nsk->sk_state = IUCV_CONNECTED; |
| 1970 | sk->sk_data_ready(sk, 1); | 1971 | sk->sk_data_ready(sk); |
| 1971 | } else | 1972 | } else |
| 1972 | iucv_sock_kill(nsk); | 1973 | iucv_sock_kill(nsk); |
| 1973 | bh_unlock_sock(sk); | 1974 | bh_unlock_sock(sk); |
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c index cd5b8ec9be04..da787930df0a 100644 --- a/net/iucv/iucv.c +++ b/net/iucv/iucv.c | |||
| @@ -621,6 +621,42 @@ static void iucv_disable(void) | |||
| 621 | put_online_cpus(); | 621 | put_online_cpus(); |
| 622 | } | 622 | } |
| 623 | 623 | ||
| 624 | static void free_iucv_data(int cpu) | ||
| 625 | { | ||
| 626 | kfree(iucv_param_irq[cpu]); | ||
| 627 | iucv_param_irq[cpu] = NULL; | ||
| 628 | kfree(iucv_param[cpu]); | ||
| 629 | iucv_param[cpu] = NULL; | ||
| 630 | kfree(iucv_irq_data[cpu]); | ||
| 631 | iucv_irq_data[cpu] = NULL; | ||
| 632 | } | ||
| 633 | |||
| 634 | static int alloc_iucv_data(int cpu) | ||
| 635 | { | ||
| 636 | /* Note: GFP_DMA used to get memory below 2G */ | ||
| 637 | iucv_irq_data[cpu] = kmalloc_node(sizeof(struct iucv_irq_data), | ||
| 638 | GFP_KERNEL|GFP_DMA, cpu_to_node(cpu)); | ||
| 639 | if (!iucv_irq_data[cpu]) | ||
| 640 | goto out_free; | ||
| 641 | |||
| 642 | /* Allocate parameter blocks. */ | ||
| 643 | iucv_param[cpu] = kmalloc_node(sizeof(union iucv_param), | ||
| 644 | GFP_KERNEL|GFP_DMA, cpu_to_node(cpu)); | ||
| 645 | if (!iucv_param[cpu]) | ||
| 646 | goto out_free; | ||
| 647 | |||
| 648 | iucv_param_irq[cpu] = kmalloc_node(sizeof(union iucv_param), | ||
| 649 | GFP_KERNEL|GFP_DMA, cpu_to_node(cpu)); | ||
| 650 | if (!iucv_param_irq[cpu]) | ||
| 651 | goto out_free; | ||
| 652 | |||
| 653 | return 0; | ||
| 654 | |||
| 655 | out_free: | ||
| 656 | free_iucv_data(cpu); | ||
| 657 | return -ENOMEM; | ||
| 658 | } | ||
| 659 | |||
| 624 | static int iucv_cpu_notify(struct notifier_block *self, | 660 | static int iucv_cpu_notify(struct notifier_block *self, |
| 625 | unsigned long action, void *hcpu) | 661 | unsigned long action, void *hcpu) |
| 626 | { | 662 | { |
| @@ -630,38 +666,14 @@ static int iucv_cpu_notify(struct notifier_block *self, | |||
| 630 | switch (action) { | 666 | switch (action) { |
| 631 | case CPU_UP_PREPARE: | 667 | case CPU_UP_PREPARE: |
| 632 | case CPU_UP_PREPARE_FROZEN: | 668 | case CPU_UP_PREPARE_FROZEN: |
| 633 | iucv_irq_data[cpu] = kmalloc_node(sizeof(struct iucv_irq_data), | 669 | if (alloc_iucv_data(cpu)) |
| 634 | GFP_KERNEL|GFP_DMA, cpu_to_node(cpu)); | ||
| 635 | if (!iucv_irq_data[cpu]) | ||
| 636 | return notifier_from_errno(-ENOMEM); | ||
| 637 | |||
| 638 | iucv_param[cpu] = kmalloc_node(sizeof(union iucv_param), | ||
| 639 | GFP_KERNEL|GFP_DMA, cpu_to_node(cpu)); | ||
| 640 | if (!iucv_param[cpu]) { | ||
| 641 | kfree(iucv_irq_data[cpu]); | ||
| 642 | iucv_irq_data[cpu] = NULL; | ||
| 643 | return notifier_from_errno(-ENOMEM); | 670 | return notifier_from_errno(-ENOMEM); |
| 644 | } | ||
| 645 | iucv_param_irq[cpu] = kmalloc_node(sizeof(union iucv_param), | ||
| 646 | GFP_KERNEL|GFP_DMA, cpu_to_node(cpu)); | ||
| 647 | if (!iucv_param_irq[cpu]) { | ||
| 648 | kfree(iucv_param[cpu]); | ||
| 649 | iucv_param[cpu] = NULL; | ||
| 650 | kfree(iucv_irq_data[cpu]); | ||
| 651 | iucv_irq_data[cpu] = NULL; | ||
| 652 | return notifier_from_errno(-ENOMEM); | ||
| 653 | } | ||
| 654 | break; | 671 | break; |
| 655 | case CPU_UP_CANCELED: | 672 | case CPU_UP_CANCELED: |
| 656 | case CPU_UP_CANCELED_FROZEN: | 673 | case CPU_UP_CANCELED_FROZEN: |
| 657 | case CPU_DEAD: | 674 | case CPU_DEAD: |
| 658 | case CPU_DEAD_FROZEN: | 675 | case CPU_DEAD_FROZEN: |
| 659 | kfree(iucv_param_irq[cpu]); | 676 | free_iucv_data(cpu); |
| 660 | iucv_param_irq[cpu] = NULL; | ||
| 661 | kfree(iucv_param[cpu]); | ||
| 662 | iucv_param[cpu] = NULL; | ||
| 663 | kfree(iucv_irq_data[cpu]); | ||
| 664 | iucv_irq_data[cpu] = NULL; | ||
| 665 | break; | 677 | break; |
| 666 | case CPU_ONLINE: | 678 | case CPU_ONLINE: |
| 667 | case CPU_ONLINE_FROZEN: | 679 | case CPU_ONLINE_FROZEN: |
| @@ -2016,7 +2028,7 @@ static int __init iucv_init(void) | |||
| 2016 | rc = iucv_query_maxconn(); | 2028 | rc = iucv_query_maxconn(); |
| 2017 | if (rc) | 2029 | if (rc) |
| 2018 | goto out_ctl; | 2030 | goto out_ctl; |
| 2019 | rc = register_external_interrupt(0x4000, iucv_external_interrupt); | 2031 | rc = register_external_irq(EXT_IRQ_IUCV, iucv_external_interrupt); |
| 2020 | if (rc) | 2032 | if (rc) |
| 2021 | goto out_ctl; | 2033 | goto out_ctl; |
| 2022 | iucv_root = root_device_register("iucv"); | 2034 | iucv_root = root_device_register("iucv"); |
| @@ -2025,33 +2037,20 @@ static int __init iucv_init(void) | |||
| 2025 | goto out_int; | 2037 | goto out_int; |
| 2026 | } | 2038 | } |
| 2027 | 2039 | ||
| 2028 | for_each_online_cpu(cpu) { | 2040 | cpu_notifier_register_begin(); |
| 2029 | /* Note: GFP_DMA used to get memory below 2G */ | ||
| 2030 | iucv_irq_data[cpu] = kmalloc_node(sizeof(struct iucv_irq_data), | ||
| 2031 | GFP_KERNEL|GFP_DMA, cpu_to_node(cpu)); | ||
| 2032 | if (!iucv_irq_data[cpu]) { | ||
| 2033 | rc = -ENOMEM; | ||
| 2034 | goto out_free; | ||
| 2035 | } | ||
| 2036 | 2041 | ||
| 2037 | /* Allocate parameter blocks. */ | 2042 | for_each_online_cpu(cpu) { |
| 2038 | iucv_param[cpu] = kmalloc_node(sizeof(union iucv_param), | 2043 | if (alloc_iucv_data(cpu)) { |
| 2039 | GFP_KERNEL|GFP_DMA, cpu_to_node(cpu)); | ||
| 2040 | if (!iucv_param[cpu]) { | ||
| 2041 | rc = -ENOMEM; | ||
| 2042 | goto out_free; | ||
| 2043 | } | ||
| 2044 | iucv_param_irq[cpu] = kmalloc_node(sizeof(union iucv_param), | ||
| 2045 | GFP_KERNEL|GFP_DMA, cpu_to_node(cpu)); | ||
| 2046 | if (!iucv_param_irq[cpu]) { | ||
| 2047 | rc = -ENOMEM; | 2044 | rc = -ENOMEM; |
| 2048 | goto out_free; | 2045 | goto out_free; |
| 2049 | } | 2046 | } |
| 2050 | |||
| 2051 | } | 2047 | } |
| 2052 | rc = register_hotcpu_notifier(&iucv_cpu_notifier); | 2048 | rc = __register_hotcpu_notifier(&iucv_cpu_notifier); |
| 2053 | if (rc) | 2049 | if (rc) |
| 2054 | goto out_free; | 2050 | goto out_free; |
| 2051 | |||
| 2052 | cpu_notifier_register_done(); | ||
| 2053 | |||
| 2055 | rc = register_reboot_notifier(&iucv_reboot_notifier); | 2054 | rc = register_reboot_notifier(&iucv_reboot_notifier); |
| 2056 | if (rc) | 2055 | if (rc) |
| 2057 | goto out_cpu; | 2056 | goto out_cpu; |
| @@ -2069,19 +2068,17 @@ static int __init iucv_init(void) | |||
| 2069 | out_reboot: | 2068 | out_reboot: |
| 2070 | unregister_reboot_notifier(&iucv_reboot_notifier); | 2069 | unregister_reboot_notifier(&iucv_reboot_notifier); |
| 2071 | out_cpu: | 2070 | out_cpu: |
| 2072 | unregister_hotcpu_notifier(&iucv_cpu_notifier); | 2071 | cpu_notifier_register_begin(); |
| 2072 | __unregister_hotcpu_notifier(&iucv_cpu_notifier); | ||
| 2073 | out_free: | 2073 | out_free: |
| 2074 | for_each_possible_cpu(cpu) { | 2074 | for_each_possible_cpu(cpu) |
| 2075 | kfree(iucv_param_irq[cpu]); | 2075 | free_iucv_data(cpu); |
| 2076 | iucv_param_irq[cpu] = NULL; | 2076 | |
| 2077 | kfree(iucv_param[cpu]); | 2077 | cpu_notifier_register_done(); |
| 2078 | iucv_param[cpu] = NULL; | 2078 | |
| 2079 | kfree(iucv_irq_data[cpu]); | ||
| 2080 | iucv_irq_data[cpu] = NULL; | ||
| 2081 | } | ||
| 2082 | root_device_unregister(iucv_root); | 2079 | root_device_unregister(iucv_root); |
| 2083 | out_int: | 2080 | out_int: |
| 2084 | unregister_external_interrupt(0x4000, iucv_external_interrupt); | 2081 | unregister_external_irq(EXT_IRQ_IUCV, iucv_external_interrupt); |
| 2085 | out_ctl: | 2082 | out_ctl: |
| 2086 | ctl_clear_bit(0, 1); | 2083 | ctl_clear_bit(0, 1); |
| 2087 | out: | 2084 | out: |
| @@ -2105,18 +2102,14 @@ static void __exit iucv_exit(void) | |||
| 2105 | kfree(p); | 2102 | kfree(p); |
| 2106 | spin_unlock_irq(&iucv_queue_lock); | 2103 | spin_unlock_irq(&iucv_queue_lock); |
| 2107 | unregister_reboot_notifier(&iucv_reboot_notifier); | 2104 | unregister_reboot_notifier(&iucv_reboot_notifier); |
| 2108 | unregister_hotcpu_notifier(&iucv_cpu_notifier); | 2105 | cpu_notifier_register_begin(); |
| 2109 | for_each_possible_cpu(cpu) { | 2106 | __unregister_hotcpu_notifier(&iucv_cpu_notifier); |
| 2110 | kfree(iucv_param_irq[cpu]); | 2107 | for_each_possible_cpu(cpu) |
| 2111 | iucv_param_irq[cpu] = NULL; | 2108 | free_iucv_data(cpu); |
| 2112 | kfree(iucv_param[cpu]); | 2109 | cpu_notifier_register_done(); |
| 2113 | iucv_param[cpu] = NULL; | ||
| 2114 | kfree(iucv_irq_data[cpu]); | ||
| 2115 | iucv_irq_data[cpu] = NULL; | ||
| 2116 | } | ||
| 2117 | root_device_unregister(iucv_root); | 2110 | root_device_unregister(iucv_root); |
| 2118 | bus_unregister(&iucv_bus); | 2111 | bus_unregister(&iucv_bus); |
| 2119 | unregister_external_interrupt(0x4000, iucv_external_interrupt); | 2112 | unregister_external_irq(EXT_IRQ_IUCV, iucv_external_interrupt); |
| 2120 | } | 2113 | } |
| 2121 | 2114 | ||
| 2122 | subsys_initcall(iucv_init); | 2115 | subsys_initcall(iucv_init); |
diff --git a/net/key/af_key.c b/net/key/af_key.c index 79326978517a..f3c83073afc4 100644 --- a/net/key/af_key.c +++ b/net/key/af_key.c | |||
| @@ -205,7 +205,7 @@ static int pfkey_broadcast_one(struct sk_buff *skb, struct sk_buff **skb2, | |||
| 205 | if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf) { | 205 | if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf) { |
| 206 | skb_set_owner_r(*skb2, sk); | 206 | skb_set_owner_r(*skb2, sk); |
| 207 | skb_queue_tail(&sk->sk_receive_queue, *skb2); | 207 | skb_queue_tail(&sk->sk_receive_queue, *skb2); |
| 208 | sk->sk_data_ready(sk, (*skb2)->len); | 208 | sk->sk_data_ready(sk); |
| 209 | *skb2 = NULL; | 209 | *skb2 = NULL; |
| 210 | err = 0; | 210 | err = 0; |
| 211 | } | 211 | } |
| @@ -365,6 +365,7 @@ static const u8 sadb_ext_min_len[] = { | |||
| 365 | [SADB_X_EXT_NAT_T_OA] = (u8) sizeof(struct sadb_address), | 365 | [SADB_X_EXT_NAT_T_OA] = (u8) sizeof(struct sadb_address), |
| 366 | [SADB_X_EXT_SEC_CTX] = (u8) sizeof(struct sadb_x_sec_ctx), | 366 | [SADB_X_EXT_SEC_CTX] = (u8) sizeof(struct sadb_x_sec_ctx), |
| 367 | [SADB_X_EXT_KMADDRESS] = (u8) sizeof(struct sadb_x_kmaddress), | 367 | [SADB_X_EXT_KMADDRESS] = (u8) sizeof(struct sadb_x_kmaddress), |
| 368 | [SADB_X_EXT_FILTER] = (u8) sizeof(struct sadb_x_filter), | ||
| 368 | }; | 369 | }; |
| 369 | 370 | ||
| 370 | /* Verify sadb_address_{len,prefixlen} against sa_family. */ | 371 | /* Verify sadb_address_{len,prefixlen} against sa_family. */ |
| @@ -1799,6 +1800,7 @@ static void pfkey_dump_sa_done(struct pfkey_sock *pfk) | |||
| 1799 | static int pfkey_dump(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs) | 1800 | static int pfkey_dump(struct sock *sk, struct sk_buff *skb, const struct sadb_msg *hdr, void * const *ext_hdrs) |
| 1800 | { | 1801 | { |
| 1801 | u8 proto; | 1802 | u8 proto; |
| 1803 | struct xfrm_address_filter *filter = NULL; | ||
| 1802 | struct pfkey_sock *pfk = pfkey_sk(sk); | 1804 | struct pfkey_sock *pfk = pfkey_sk(sk); |
| 1803 | 1805 | ||
| 1804 | if (pfk->dump.dump != NULL) | 1806 | if (pfk->dump.dump != NULL) |
| @@ -1808,11 +1810,27 @@ static int pfkey_dump(struct sock *sk, struct sk_buff *skb, const struct sadb_ms | |||
| 1808 | if (proto == 0) | 1810 | if (proto == 0) |
| 1809 | return -EINVAL; | 1811 | return -EINVAL; |
| 1810 | 1812 | ||
| 1813 | if (ext_hdrs[SADB_X_EXT_FILTER - 1]) { | ||
| 1814 | struct sadb_x_filter *xfilter = ext_hdrs[SADB_X_EXT_FILTER - 1]; | ||
| 1815 | |||
| 1816 | filter = kmalloc(sizeof(*filter), GFP_KERNEL); | ||
| 1817 | if (filter == NULL) | ||
| 1818 | return -ENOMEM; | ||
| 1819 | |||
| 1820 | memcpy(&filter->saddr, &xfilter->sadb_x_filter_saddr, | ||
| 1821 | sizeof(xfrm_address_t)); | ||
| 1822 | memcpy(&filter->daddr, &xfilter->sadb_x_filter_daddr, | ||
| 1823 | sizeof(xfrm_address_t)); | ||
| 1824 | filter->family = xfilter->sadb_x_filter_family; | ||
| 1825 | filter->splen = xfilter->sadb_x_filter_splen; | ||
| 1826 | filter->dplen = xfilter->sadb_x_filter_dplen; | ||
| 1827 | } | ||
| 1828 | |||
| 1811 | pfk->dump.msg_version = hdr->sadb_msg_version; | 1829 | pfk->dump.msg_version = hdr->sadb_msg_version; |
| 1812 | pfk->dump.msg_portid = hdr->sadb_msg_pid; | 1830 | pfk->dump.msg_portid = hdr->sadb_msg_pid; |
| 1813 | pfk->dump.dump = pfkey_dump_sa; | 1831 | pfk->dump.dump = pfkey_dump_sa; |
| 1814 | pfk->dump.done = pfkey_dump_sa_done; | 1832 | pfk->dump.done = pfkey_dump_sa_done; |
| 1815 | xfrm_state_walk_init(&pfk->dump.u.state, proto); | 1833 | xfrm_state_walk_init(&pfk->dump.u.state, proto, filter); |
| 1816 | 1834 | ||
| 1817 | return pfkey_do_dump(pfk); | 1835 | return pfkey_do_dump(pfk); |
| 1818 | } | 1836 | } |
| @@ -3060,6 +3078,24 @@ static u32 get_acqseq(void) | |||
| 3060 | return res; | 3078 | return res; |
| 3061 | } | 3079 | } |
| 3062 | 3080 | ||
| 3081 | static bool pfkey_is_alive(const struct km_event *c) | ||
| 3082 | { | ||
| 3083 | struct netns_pfkey *net_pfkey = net_generic(c->net, pfkey_net_id); | ||
| 3084 | struct sock *sk; | ||
| 3085 | bool is_alive = false; | ||
| 3086 | |||
| 3087 | rcu_read_lock(); | ||
| 3088 | sk_for_each_rcu(sk, &net_pfkey->table) { | ||
| 3089 | if (pfkey_sk(sk)->registered) { | ||
| 3090 | is_alive = true; | ||
| 3091 | break; | ||
| 3092 | } | ||
| 3093 | } | ||
| 3094 | rcu_read_unlock(); | ||
| 3095 | |||
| 3096 | return is_alive; | ||
| 3097 | } | ||
| 3098 | |||
| 3063 | static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *xp) | 3099 | static int pfkey_send_acquire(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *xp) |
| 3064 | { | 3100 | { |
| 3065 | struct sk_buff *skb; | 3101 | struct sk_buff *skb; |
| @@ -3785,6 +3821,7 @@ static struct xfrm_mgr pfkeyv2_mgr = | |||
| 3785 | .new_mapping = pfkey_send_new_mapping, | 3821 | .new_mapping = pfkey_send_new_mapping, |
| 3786 | .notify_policy = pfkey_send_policy_notify, | 3822 | .notify_policy = pfkey_send_policy_notify, |
| 3787 | .migrate = pfkey_send_migrate, | 3823 | .migrate = pfkey_send_migrate, |
| 3824 | .is_alive = pfkey_is_alive, | ||
| 3788 | }; | 3825 | }; |
| 3789 | 3826 | ||
| 3790 | static int __net_init pfkey_net_init(struct net *net) | 3827 | static int __net_init pfkey_net_init(struct net *net) |
diff --git a/net/l2tp/l2tp_core.c b/net/l2tp/l2tp_core.c index c83827e7c324..a4e37d7158dc 100644 --- a/net/l2tp/l2tp_core.c +++ b/net/l2tp/l2tp_core.c | |||
| @@ -1130,11 +1130,11 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, | |||
| 1130 | /* Queue the packet to IP for output */ | 1130 | /* Queue the packet to IP for output */ |
| 1131 | skb->local_df = 1; | 1131 | skb->local_df = 1; |
| 1132 | #if IS_ENABLED(CONFIG_IPV6) | 1132 | #if IS_ENABLED(CONFIG_IPV6) |
| 1133 | if (skb->sk->sk_family == PF_INET6 && !tunnel->v4mapped) | 1133 | if (tunnel->sock->sk_family == PF_INET6 && !tunnel->v4mapped) |
| 1134 | error = inet6_csk_xmit(skb, NULL); | 1134 | error = inet6_csk_xmit(tunnel->sock, skb, NULL); |
| 1135 | else | 1135 | else |
| 1136 | #endif | 1136 | #endif |
| 1137 | error = ip_queue_xmit(skb, fl); | 1137 | error = ip_queue_xmit(tunnel->sock, skb, fl); |
| 1138 | 1138 | ||
| 1139 | /* Update stats */ | 1139 | /* Update stats */ |
| 1140 | if (error >= 0) { | 1140 | if (error >= 0) { |
| @@ -1150,23 +1150,6 @@ static int l2tp_xmit_core(struct l2tp_session *session, struct sk_buff *skb, | |||
| 1150 | return 0; | 1150 | return 0; |
| 1151 | } | 1151 | } |
| 1152 | 1152 | ||
| 1153 | /* Automatically called when the skb is freed. | ||
| 1154 | */ | ||
| 1155 | static void l2tp_sock_wfree(struct sk_buff *skb) | ||
| 1156 | { | ||
| 1157 | sock_put(skb->sk); | ||
| 1158 | } | ||
| 1159 | |||
| 1160 | /* For data skbs that we transmit, we associate with the tunnel socket | ||
| 1161 | * but don't do accounting. | ||
| 1162 | */ | ||
| 1163 | static inline void l2tp_skb_set_owner_w(struct sk_buff *skb, struct sock *sk) | ||
| 1164 | { | ||
| 1165 | sock_hold(sk); | ||
| 1166 | skb->sk = sk; | ||
| 1167 | skb->destructor = l2tp_sock_wfree; | ||
| 1168 | } | ||
| 1169 | |||
| 1170 | #if IS_ENABLED(CONFIG_IPV6) | 1153 | #if IS_ENABLED(CONFIG_IPV6) |
| 1171 | static void l2tp_xmit_ipv6_csum(struct sock *sk, struct sk_buff *skb, | 1154 | static void l2tp_xmit_ipv6_csum(struct sock *sk, struct sk_buff *skb, |
| 1172 | int udp_len) | 1155 | int udp_len) |
| @@ -1220,7 +1203,6 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len | |||
| 1220 | return NET_XMIT_DROP; | 1203 | return NET_XMIT_DROP; |
| 1221 | } | 1204 | } |
| 1222 | 1205 | ||
| 1223 | skb_orphan(skb); | ||
| 1224 | /* Setup L2TP header */ | 1206 | /* Setup L2TP header */ |
| 1225 | session->build_header(session, __skb_push(skb, hdr_len)); | 1207 | session->build_header(session, __skb_push(skb, hdr_len)); |
| 1226 | 1208 | ||
| @@ -1286,8 +1268,6 @@ int l2tp_xmit_skb(struct l2tp_session *session, struct sk_buff *skb, int hdr_len | |||
| 1286 | break; | 1268 | break; |
| 1287 | } | 1269 | } |
| 1288 | 1270 | ||
| 1289 | l2tp_skb_set_owner_w(skb, sk); | ||
| 1290 | |||
| 1291 | l2tp_xmit_core(session, skb, fl, data_len); | 1271 | l2tp_xmit_core(session, skb, fl, data_len); |
| 1292 | out_unlock: | 1272 | out_unlock: |
| 1293 | bh_unlock_sock(sk); | 1273 | bh_unlock_sock(sk); |
| @@ -1808,8 +1788,6 @@ void l2tp_session_free(struct l2tp_session *session) | |||
| 1808 | } | 1788 | } |
| 1809 | 1789 | ||
| 1810 | kfree(session); | 1790 | kfree(session); |
| 1811 | |||
| 1812 | return; | ||
| 1813 | } | 1791 | } |
| 1814 | EXPORT_SYMBOL_GPL(l2tp_session_free); | 1792 | EXPORT_SYMBOL_GPL(l2tp_session_free); |
| 1815 | 1793 | ||
diff --git a/net/l2tp/l2tp_ip.c b/net/l2tp/l2tp_ip.c index 0b44d855269c..3397fe6897c0 100644 --- a/net/l2tp/l2tp_ip.c +++ b/net/l2tp/l2tp_ip.c | |||
| @@ -487,7 +487,7 @@ static int l2tp_ip_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *m | |||
| 487 | 487 | ||
| 488 | xmit: | 488 | xmit: |
| 489 | /* Queue the packet to IP for output */ | 489 | /* Queue the packet to IP for output */ |
| 490 | rc = ip_queue_xmit(skb, &inet->cork.fl); | 490 | rc = ip_queue_xmit(sk, skb, &inet->cork.fl); |
| 491 | rcu_read_unlock(); | 491 | rcu_read_unlock(); |
| 492 | 492 | ||
| 493 | error: | 493 | error: |
diff --git a/net/l2tp/l2tp_ppp.c b/net/l2tp/l2tp_ppp.c index 5990919356a5..950909f04ee6 100644 --- a/net/l2tp/l2tp_ppp.c +++ b/net/l2tp/l2tp_ppp.c | |||
| @@ -456,13 +456,11 @@ static void pppol2tp_session_close(struct l2tp_session *session) | |||
| 456 | 456 | ||
| 457 | BUG_ON(session->magic != L2TP_SESSION_MAGIC); | 457 | BUG_ON(session->magic != L2TP_SESSION_MAGIC); |
| 458 | 458 | ||
| 459 | |||
| 460 | if (sock) { | 459 | if (sock) { |
| 461 | inet_shutdown(sock, 2); | 460 | inet_shutdown(sock, 2); |
| 462 | /* Don't let the session go away before our socket does */ | 461 | /* Don't let the session go away before our socket does */ |
| 463 | l2tp_session_inc_refcount(session); | 462 | l2tp_session_inc_refcount(session); |
| 464 | } | 463 | } |
| 465 | return; | ||
| 466 | } | 464 | } |
| 467 | 465 | ||
| 468 | /* Really kill the session socket. (Called from sock_put() if | 466 | /* Really kill the session socket. (Called from sock_put() if |
| @@ -476,7 +474,6 @@ static void pppol2tp_session_destruct(struct sock *sk) | |||
| 476 | BUG_ON(session->magic != L2TP_SESSION_MAGIC); | 474 | BUG_ON(session->magic != L2TP_SESSION_MAGIC); |
| 477 | l2tp_session_dec_refcount(session); | 475 | l2tp_session_dec_refcount(session); |
| 478 | } | 476 | } |
| 479 | return; | ||
| 480 | } | 477 | } |
| 481 | 478 | ||
| 482 | /* Called when the PPPoX socket (session) is closed. | 479 | /* Called when the PPPoX socket (session) is closed. |
| @@ -756,9 +753,9 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr, | |||
| 756 | session->deref = pppol2tp_session_sock_put; | 753 | session->deref = pppol2tp_session_sock_put; |
| 757 | 754 | ||
| 758 | /* If PMTU discovery was enabled, use the MTU that was discovered */ | 755 | /* If PMTU discovery was enabled, use the MTU that was discovered */ |
| 759 | dst = sk_dst_get(sk); | 756 | dst = sk_dst_get(tunnel->sock); |
| 760 | if (dst != NULL) { | 757 | if (dst != NULL) { |
| 761 | u32 pmtu = dst_mtu(__sk_dst_get(sk)); | 758 | u32 pmtu = dst_mtu(__sk_dst_get(tunnel->sock)); |
| 762 | if (pmtu != 0) | 759 | if (pmtu != 0) |
| 763 | session->mtu = session->mru = pmtu - | 760 | session->mtu = session->mru = pmtu - |
| 764 | PPPOL2TP_HEADER_OVERHEAD; | 761 | PPPOL2TP_HEADER_OVERHEAD; |
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 13b7683de5a4..ce9633a3cfb0 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
| @@ -107,7 +107,7 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, | |||
| 107 | mgmt->u.action.u.addba_req.start_seq_num = | 107 | mgmt->u.action.u.addba_req.start_seq_num = |
| 108 | cpu_to_le16(start_seq_num << 4); | 108 | cpu_to_le16(start_seq_num << 4); |
| 109 | 109 | ||
| 110 | ieee80211_tx_skb_tid(sdata, skb, tid); | 110 | ieee80211_tx_skb(sdata, skb); |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn) | 113 | void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn) |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 453e974287d1..aaa59d719592 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
| @@ -451,11 +451,11 @@ void sta_set_rate_info_rx(struct sta_info *sta, struct rate_info *rinfo) | |||
| 451 | rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | 451 | rinfo->flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; |
| 452 | if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI) | 452 | if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI) |
| 453 | rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; | 453 | rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI; |
| 454 | if (sta->last_rx_rate_flag & RX_FLAG_80MHZ) | 454 | if (sta->last_rx_rate_vht_flag & RX_VHT_FLAG_80MHZ) |
| 455 | rinfo->flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; | 455 | rinfo->flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; |
| 456 | if (sta->last_rx_rate_flag & RX_FLAG_80P80MHZ) | 456 | if (sta->last_rx_rate_vht_flag & RX_VHT_FLAG_80P80MHZ) |
| 457 | rinfo->flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH; | 457 | rinfo->flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH; |
| 458 | if (sta->last_rx_rate_flag & RX_FLAG_160MHZ) | 458 | if (sta->last_rx_rate_vht_flag & RX_VHT_FLAG_160MHZ) |
| 459 | rinfo->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; | 459 | rinfo->flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; |
| 460 | } | 460 | } |
| 461 | 461 | ||
| @@ -970,9 +970,9 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev, | |||
| 970 | /* TODO: make hostapd tell us what it wants */ | 970 | /* TODO: make hostapd tell us what it wants */ |
| 971 | sdata->smps_mode = IEEE80211_SMPS_OFF; | 971 | sdata->smps_mode = IEEE80211_SMPS_OFF; |
| 972 | sdata->needed_rx_chains = sdata->local->rx_chains; | 972 | sdata->needed_rx_chains = sdata->local->rx_chains; |
| 973 | sdata->radar_required = params->radar_required; | ||
| 974 | 973 | ||
| 975 | mutex_lock(&local->mtx); | 974 | mutex_lock(&local->mtx); |
| 975 | sdata->radar_required = params->radar_required; | ||
| 976 | err = ieee80211_vif_use_channel(sdata, ¶ms->chandef, | 976 | err = ieee80211_vif_use_channel(sdata, ¶ms->chandef, |
| 977 | IEEE80211_CHANCTX_SHARED); | 977 | IEEE80211_CHANCTX_SHARED); |
| 978 | mutex_unlock(&local->mtx); | 978 | mutex_unlock(&local->mtx); |
| @@ -1056,6 +1056,7 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev, | |||
| 1056 | int err; | 1056 | int err; |
| 1057 | 1057 | ||
| 1058 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 1058 | sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| 1059 | sdata_assert_lock(sdata); | ||
| 1059 | 1060 | ||
| 1060 | /* don't allow changing the beacon while CSA is in place - offset | 1061 | /* don't allow changing the beacon while CSA is in place - offset |
| 1061 | * of channel switch counter may change | 1062 | * of channel switch counter may change |
| @@ -1083,6 +1084,8 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
| 1083 | struct probe_resp *old_probe_resp; | 1084 | struct probe_resp *old_probe_resp; |
| 1084 | struct cfg80211_chan_def chandef; | 1085 | struct cfg80211_chan_def chandef; |
| 1085 | 1086 | ||
| 1087 | sdata_assert_lock(sdata); | ||
| 1088 | |||
| 1086 | old_beacon = sdata_dereference(sdata->u.ap.beacon, sdata); | 1089 | old_beacon = sdata_dereference(sdata->u.ap.beacon, sdata); |
| 1087 | if (!old_beacon) | 1090 | if (!old_beacon) |
| 1088 | return -ENOENT; | 1091 | return -ENOENT; |
| @@ -1343,6 +1346,15 @@ static int sta_apply_parameters(struct ieee80211_local *local, | |||
| 1343 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, | 1346 | ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband, |
| 1344 | params->vht_capa, sta); | 1347 | params->vht_capa, sta); |
| 1345 | 1348 | ||
| 1349 | if (params->opmode_notif_used) { | ||
| 1350 | /* returned value is only needed for rc update, but the | ||
| 1351 | * rc isn't initialized here yet, so ignore it | ||
| 1352 | */ | ||
| 1353 | __ieee80211_vht_handle_opmode(sdata, sta, | ||
| 1354 | params->opmode_notif, | ||
| 1355 | band, false); | ||
| 1356 | } | ||
| 1357 | |||
| 1346 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 1358 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
| 1347 | #ifdef CONFIG_MAC80211_MESH | 1359 | #ifdef CONFIG_MAC80211_MESH |
| 1348 | u32 changed = 0; | 1360 | u32 changed = 0; |
| @@ -2630,6 +2642,18 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
| 2630 | if (!roc) | 2642 | if (!roc) |
| 2631 | return -ENOMEM; | 2643 | return -ENOMEM; |
| 2632 | 2644 | ||
| 2645 | /* | ||
| 2646 | * If the duration is zero, then the driver | ||
| 2647 | * wouldn't actually do anything. Set it to | ||
| 2648 | * 10 for now. | ||
| 2649 | * | ||
| 2650 | * TODO: cancel the off-channel operation | ||
| 2651 | * when we get the SKB's TX status and | ||
| 2652 | * the wait time was zero before. | ||
| 2653 | */ | ||
| 2654 | if (!duration) | ||
| 2655 | duration = 10; | ||
| 2656 | |||
| 2633 | roc->chan = channel; | 2657 | roc->chan = channel; |
| 2634 | roc->duration = duration; | 2658 | roc->duration = duration; |
| 2635 | roc->req_duration = duration; | 2659 | roc->req_duration = duration; |
| @@ -2671,18 +2695,6 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local, | |||
| 2671 | 2695 | ||
| 2672 | /* otherwise actually kick it off here (for error handling) */ | 2696 | /* otherwise actually kick it off here (for error handling) */ |
| 2673 | 2697 | ||
| 2674 | /* | ||
| 2675 | * If the duration is zero, then the driver | ||
| 2676 | * wouldn't actually do anything. Set it to | ||
| 2677 | * 10 for now. | ||
| 2678 | * | ||
| 2679 | * TODO: cancel the off-channel operation | ||
| 2680 | * when we get the SKB's TX status and | ||
| 2681 | * the wait time was zero before. | ||
| 2682 | */ | ||
| 2683 | if (!duration) | ||
| 2684 | duration = 10; | ||
| 2685 | |||
| 2686 | ret = drv_remain_on_channel(local, sdata, channel, duration, type); | 2698 | ret = drv_remain_on_channel(local, sdata, channel, duration, type); |
| 2687 | if (ret) { | 2699 | if (ret) { |
| 2688 | kfree(roc); | 2700 | kfree(roc); |
| @@ -2902,11 +2914,11 @@ static int ieee80211_cancel_remain_on_channel(struct wiphy *wiphy, | |||
| 2902 | 2914 | ||
| 2903 | static int ieee80211_start_radar_detection(struct wiphy *wiphy, | 2915 | static int ieee80211_start_radar_detection(struct wiphy *wiphy, |
| 2904 | struct net_device *dev, | 2916 | struct net_device *dev, |
| 2905 | struct cfg80211_chan_def *chandef) | 2917 | struct cfg80211_chan_def *chandef, |
| 2918 | u32 cac_time_ms) | ||
| 2906 | { | 2919 | { |
| 2907 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 2920 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| 2908 | struct ieee80211_local *local = sdata->local; | 2921 | struct ieee80211_local *local = sdata->local; |
| 2909 | unsigned long timeout; | ||
| 2910 | int err; | 2922 | int err; |
| 2911 | 2923 | ||
| 2912 | mutex_lock(&local->mtx); | 2924 | mutex_lock(&local->mtx); |
| @@ -2925,9 +2937,9 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy, | |||
| 2925 | if (err) | 2937 | if (err) |
| 2926 | goto out_unlock; | 2938 | goto out_unlock; |
| 2927 | 2939 | ||
| 2928 | timeout = msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS); | ||
| 2929 | ieee80211_queue_delayed_work(&sdata->local->hw, | 2940 | ieee80211_queue_delayed_work(&sdata->local->hw, |
| 2930 | &sdata->dfs_cac_timer_work, timeout); | 2941 | &sdata->dfs_cac_timer_work, |
| 2942 | msecs_to_jiffies(cac_time_ms)); | ||
| 2931 | 2943 | ||
| 2932 | out_unlock: | 2944 | out_unlock: |
| 2933 | mutex_unlock(&local->mtx); | 2945 | mutex_unlock(&local->mtx); |
| @@ -2990,136 +3002,135 @@ cfg80211_beacon_dup(struct cfg80211_beacon_data *beacon) | |||
| 2990 | return new_beacon; | 3002 | return new_beacon; |
| 2991 | } | 3003 | } |
| 2992 | 3004 | ||
| 2993 | void ieee80211_csa_finalize_work(struct work_struct *work) | 3005 | void ieee80211_csa_finish(struct ieee80211_vif *vif) |
| 3006 | { | ||
| 3007 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
| 3008 | |||
| 3009 | ieee80211_queue_work(&sdata->local->hw, | ||
| 3010 | &sdata->csa_finalize_work); | ||
| 3011 | } | ||
| 3012 | EXPORT_SYMBOL(ieee80211_csa_finish); | ||
| 3013 | |||
| 3014 | static void ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata) | ||
| 2994 | { | 3015 | { |
| 2995 | struct ieee80211_sub_if_data *sdata = | ||
| 2996 | container_of(work, struct ieee80211_sub_if_data, | ||
| 2997 | csa_finalize_work); | ||
| 2998 | struct ieee80211_local *local = sdata->local; | 3016 | struct ieee80211_local *local = sdata->local; |
| 2999 | int err, changed = 0; | 3017 | int err, changed = 0; |
| 3000 | 3018 | ||
| 3001 | sdata_lock(sdata); | 3019 | sdata_assert_lock(sdata); |
| 3002 | /* AP might have been stopped while waiting for the lock. */ | ||
| 3003 | if (!sdata->vif.csa_active) | ||
| 3004 | goto unlock; | ||
| 3005 | |||
| 3006 | if (!ieee80211_sdata_running(sdata)) | ||
| 3007 | goto unlock; | ||
| 3008 | 3020 | ||
| 3009 | sdata->radar_required = sdata->csa_radar_required; | ||
| 3010 | mutex_lock(&local->mtx); | 3021 | mutex_lock(&local->mtx); |
| 3022 | sdata->radar_required = sdata->csa_radar_required; | ||
| 3011 | err = ieee80211_vif_change_channel(sdata, &changed); | 3023 | err = ieee80211_vif_change_channel(sdata, &changed); |
| 3012 | mutex_unlock(&local->mtx); | 3024 | mutex_unlock(&local->mtx); |
| 3013 | if (WARN_ON(err < 0)) | 3025 | if (WARN_ON(err < 0)) |
| 3014 | goto unlock; | 3026 | return; |
| 3015 | 3027 | ||
| 3016 | if (!local->use_chanctx) { | 3028 | if (!local->use_chanctx) { |
| 3017 | local->_oper_chandef = sdata->csa_chandef; | 3029 | local->_oper_chandef = sdata->csa_chandef; |
| 3018 | ieee80211_hw_config(local, 0); | 3030 | ieee80211_hw_config(local, 0); |
| 3019 | } | 3031 | } |
| 3020 | 3032 | ||
| 3021 | ieee80211_bss_info_change_notify(sdata, changed); | ||
| 3022 | |||
| 3023 | sdata->vif.csa_active = false; | 3033 | sdata->vif.csa_active = false; |
| 3024 | switch (sdata->vif.type) { | 3034 | switch (sdata->vif.type) { |
| 3025 | case NL80211_IFTYPE_AP: | 3035 | case NL80211_IFTYPE_AP: |
| 3026 | err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon); | 3036 | err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon); |
| 3027 | if (err < 0) | ||
| 3028 | goto unlock; | ||
| 3029 | |||
| 3030 | changed |= err; | ||
| 3031 | kfree(sdata->u.ap.next_beacon); | 3037 | kfree(sdata->u.ap.next_beacon); |
| 3032 | sdata->u.ap.next_beacon = NULL; | 3038 | sdata->u.ap.next_beacon = NULL; |
| 3033 | 3039 | ||
| 3034 | ieee80211_bss_info_change_notify(sdata, err); | 3040 | if (err < 0) |
| 3041 | return; | ||
| 3042 | changed |= err; | ||
| 3035 | break; | 3043 | break; |
| 3036 | case NL80211_IFTYPE_ADHOC: | 3044 | case NL80211_IFTYPE_ADHOC: |
| 3037 | ieee80211_ibss_finish_csa(sdata); | 3045 | err = ieee80211_ibss_finish_csa(sdata); |
| 3046 | if (err < 0) | ||
| 3047 | return; | ||
| 3048 | changed |= err; | ||
| 3038 | break; | 3049 | break; |
| 3039 | #ifdef CONFIG_MAC80211_MESH | 3050 | #ifdef CONFIG_MAC80211_MESH |
| 3040 | case NL80211_IFTYPE_MESH_POINT: | 3051 | case NL80211_IFTYPE_MESH_POINT: |
| 3041 | err = ieee80211_mesh_finish_csa(sdata); | 3052 | err = ieee80211_mesh_finish_csa(sdata); |
| 3042 | if (err < 0) | 3053 | if (err < 0) |
| 3043 | goto unlock; | 3054 | return; |
| 3055 | changed |= err; | ||
| 3044 | break; | 3056 | break; |
| 3045 | #endif | 3057 | #endif |
| 3046 | default: | 3058 | default: |
| 3047 | WARN_ON(1); | 3059 | WARN_ON(1); |
| 3048 | goto unlock; | 3060 | return; |
| 3049 | } | 3061 | } |
| 3050 | 3062 | ||
| 3063 | ieee80211_bss_info_change_notify(sdata, changed); | ||
| 3064 | |||
| 3051 | ieee80211_wake_queues_by_reason(&sdata->local->hw, | 3065 | ieee80211_wake_queues_by_reason(&sdata->local->hw, |
| 3052 | IEEE80211_MAX_QUEUE_MAP, | 3066 | IEEE80211_MAX_QUEUE_MAP, |
| 3053 | IEEE80211_QUEUE_STOP_REASON_CSA); | 3067 | IEEE80211_QUEUE_STOP_REASON_CSA); |
| 3054 | 3068 | ||
| 3055 | cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef); | 3069 | cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef); |
| 3056 | |||
| 3057 | unlock: | ||
| 3058 | sdata_unlock(sdata); | ||
| 3059 | } | 3070 | } |
| 3060 | 3071 | ||
| 3061 | int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | 3072 | void ieee80211_csa_finalize_work(struct work_struct *work) |
| 3062 | struct cfg80211_csa_settings *params) | ||
| 3063 | { | 3073 | { |
| 3064 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 3074 | struct ieee80211_sub_if_data *sdata = |
| 3065 | struct ieee80211_local *local = sdata->local; | 3075 | container_of(work, struct ieee80211_sub_if_data, |
| 3066 | struct ieee80211_chanctx_conf *chanctx_conf; | 3076 | csa_finalize_work); |
| 3067 | struct ieee80211_chanctx *chanctx; | ||
| 3068 | struct ieee80211_if_mesh __maybe_unused *ifmsh; | ||
| 3069 | int err, num_chanctx; | ||
| 3070 | |||
| 3071 | lockdep_assert_held(&sdata->wdev.mtx); | ||
| 3072 | |||
| 3073 | if (!list_empty(&local->roc_list) || local->scanning) | ||
| 3074 | return -EBUSY; | ||
| 3075 | 3077 | ||
| 3076 | if (sdata->wdev.cac_started) | 3078 | sdata_lock(sdata); |
| 3077 | return -EBUSY; | 3079 | /* AP might have been stopped while waiting for the lock. */ |
| 3080 | if (!sdata->vif.csa_active) | ||
| 3081 | goto unlock; | ||
| 3078 | 3082 | ||
| 3079 | if (cfg80211_chandef_identical(¶ms->chandef, | 3083 | if (!ieee80211_sdata_running(sdata)) |
| 3080 | &sdata->vif.bss_conf.chandef)) | 3084 | goto unlock; |
| 3081 | return -EINVAL; | ||
| 3082 | 3085 | ||
| 3083 | rcu_read_lock(); | 3086 | ieee80211_csa_finalize(sdata); |
| 3084 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
| 3085 | if (!chanctx_conf) { | ||
| 3086 | rcu_read_unlock(); | ||
| 3087 | return -EBUSY; | ||
| 3088 | } | ||
| 3089 | 3087 | ||
| 3090 | /* don't handle for multi-VIF cases */ | 3088 | unlock: |
| 3091 | chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf); | 3089 | sdata_unlock(sdata); |
| 3092 | if (chanctx->refcount > 1) { | 3090 | } |
| 3093 | rcu_read_unlock(); | ||
| 3094 | return -EBUSY; | ||
| 3095 | } | ||
| 3096 | num_chanctx = 0; | ||
| 3097 | list_for_each_entry_rcu(chanctx, &local->chanctx_list, list) | ||
| 3098 | num_chanctx++; | ||
| 3099 | rcu_read_unlock(); | ||
| 3100 | |||
| 3101 | if (num_chanctx > 1) | ||
| 3102 | return -EBUSY; | ||
| 3103 | 3091 | ||
| 3104 | /* don't allow another channel switch if one is already active. */ | 3092 | static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata, |
| 3105 | if (sdata->vif.csa_active) | 3093 | struct cfg80211_csa_settings *params, |
| 3106 | return -EBUSY; | 3094 | u32 *changed) |
| 3095 | { | ||
| 3096 | int err; | ||
| 3107 | 3097 | ||
| 3108 | switch (sdata->vif.type) { | 3098 | switch (sdata->vif.type) { |
| 3109 | case NL80211_IFTYPE_AP: | 3099 | case NL80211_IFTYPE_AP: |
| 3110 | sdata->csa_counter_offset_beacon = | ||
| 3111 | params->counter_offset_beacon; | ||
| 3112 | sdata->csa_counter_offset_presp = params->counter_offset_presp; | ||
| 3113 | sdata->u.ap.next_beacon = | 3100 | sdata->u.ap.next_beacon = |
| 3114 | cfg80211_beacon_dup(¶ms->beacon_after); | 3101 | cfg80211_beacon_dup(¶ms->beacon_after); |
| 3115 | if (!sdata->u.ap.next_beacon) | 3102 | if (!sdata->u.ap.next_beacon) |
| 3116 | return -ENOMEM; | 3103 | return -ENOMEM; |
| 3117 | 3104 | ||
| 3105 | /* | ||
| 3106 | * With a count of 0, we don't have to wait for any | ||
| 3107 | * TBTT before switching, so complete the CSA | ||
| 3108 | * immediately. In theory, with a count == 1 we | ||
| 3109 | * should delay the switch until just before the next | ||
| 3110 | * TBTT, but that would complicate things so we switch | ||
| 3111 | * immediately too. If we would delay the switch | ||
| 3112 | * until the next TBTT, we would have to set the probe | ||
| 3113 | * response here. | ||
| 3114 | * | ||
| 3115 | * TODO: A channel switch with count <= 1 without | ||
| 3116 | * sending a CSA action frame is kind of useless, | ||
| 3117 | * because the clients won't know we're changing | ||
| 3118 | * channels. The action frame must be implemented | ||
| 3119 | * either here or in the userspace. | ||
| 3120 | */ | ||
| 3121 | if (params->count <= 1) | ||
| 3122 | break; | ||
| 3123 | |||
| 3124 | sdata->csa_counter_offset_beacon = | ||
| 3125 | params->counter_offset_beacon; | ||
| 3126 | sdata->csa_counter_offset_presp = params->counter_offset_presp; | ||
| 3118 | err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa); | 3127 | err = ieee80211_assign_beacon(sdata, ¶ms->beacon_csa); |
| 3119 | if (err < 0) { | 3128 | if (err < 0) { |
| 3120 | kfree(sdata->u.ap.next_beacon); | 3129 | kfree(sdata->u.ap.next_beacon); |
| 3121 | return err; | 3130 | return err; |
| 3122 | } | 3131 | } |
| 3132 | *changed |= err; | ||
| 3133 | |||
| 3123 | break; | 3134 | break; |
| 3124 | case NL80211_IFTYPE_ADHOC: | 3135 | case NL80211_IFTYPE_ADHOC: |
| 3125 | if (!sdata->vif.bss_conf.ibss_joined) | 3136 | if (!sdata->vif.bss_conf.ibss_joined) |
| @@ -3147,16 +3158,20 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
| 3147 | params->chandef.chan->band) | 3158 | params->chandef.chan->band) |
| 3148 | return -EINVAL; | 3159 | return -EINVAL; |
| 3149 | 3160 | ||
| 3150 | err = ieee80211_ibss_csa_beacon(sdata, params); | 3161 | /* see comments in the NL80211_IFTYPE_AP block */ |
| 3151 | if (err < 0) | 3162 | if (params->count > 1) { |
| 3152 | return err; | 3163 | err = ieee80211_ibss_csa_beacon(sdata, params); |
| 3164 | if (err < 0) | ||
| 3165 | return err; | ||
| 3166 | *changed |= err; | ||
| 3167 | } | ||
| 3168 | |||
| 3169 | ieee80211_send_action_csa(sdata, params); | ||
| 3170 | |||
| 3153 | break; | 3171 | break; |
| 3154 | #ifdef CONFIG_MAC80211_MESH | 3172 | #ifdef CONFIG_MAC80211_MESH |
| 3155 | case NL80211_IFTYPE_MESH_POINT: | 3173 | case NL80211_IFTYPE_MESH_POINT: { |
| 3156 | ifmsh = &sdata->u.mesh; | 3174 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
| 3157 | |||
| 3158 | if (!ifmsh->mesh_id) | ||
| 3159 | return -EINVAL; | ||
| 3160 | 3175 | ||
| 3161 | if (params->chandef.width != sdata->vif.bss_conf.chandef.width) | 3176 | if (params->chandef.width != sdata->vif.bss_conf.chandef.width) |
| 3162 | return -EINVAL; | 3177 | return -EINVAL; |
| @@ -3166,23 +3181,87 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
| 3166 | params->chandef.chan->band) | 3181 | params->chandef.chan->band) |
| 3167 | return -EINVAL; | 3182 | return -EINVAL; |
| 3168 | 3183 | ||
| 3169 | ifmsh->chsw_init = true; | 3184 | if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_NONE) { |
| 3170 | if (!ifmsh->pre_value) | 3185 | ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_INIT; |
| 3171 | ifmsh->pre_value = 1; | 3186 | if (!ifmsh->pre_value) |
| 3172 | else | 3187 | ifmsh->pre_value = 1; |
| 3173 | ifmsh->pre_value++; | 3188 | else |
| 3189 | ifmsh->pre_value++; | ||
| 3190 | } | ||
| 3174 | 3191 | ||
| 3175 | err = ieee80211_mesh_csa_beacon(sdata, params, true); | 3192 | /* see comments in the NL80211_IFTYPE_AP block */ |
| 3176 | if (err < 0) { | 3193 | if (params->count > 1) { |
| 3177 | ifmsh->chsw_init = false; | 3194 | err = ieee80211_mesh_csa_beacon(sdata, params); |
| 3178 | return err; | 3195 | if (err < 0) { |
| 3196 | ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE; | ||
| 3197 | return err; | ||
| 3198 | } | ||
| 3199 | *changed |= err; | ||
| 3179 | } | 3200 | } |
| 3201 | |||
| 3202 | if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT) | ||
| 3203 | ieee80211_send_action_csa(sdata, params); | ||
| 3204 | |||
| 3180 | break; | 3205 | break; |
| 3206 | } | ||
| 3181 | #endif | 3207 | #endif |
| 3182 | default: | 3208 | default: |
| 3183 | return -EOPNOTSUPP; | 3209 | return -EOPNOTSUPP; |
| 3184 | } | 3210 | } |
| 3185 | 3211 | ||
| 3212 | return 0; | ||
| 3213 | } | ||
| 3214 | |||
| 3215 | int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | ||
| 3216 | struct cfg80211_csa_settings *params) | ||
| 3217 | { | ||
| 3218 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
| 3219 | struct ieee80211_local *local = sdata->local; | ||
| 3220 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
| 3221 | struct ieee80211_chanctx *chanctx; | ||
| 3222 | int err, num_chanctx, changed = 0; | ||
| 3223 | |||
| 3224 | sdata_assert_lock(sdata); | ||
| 3225 | |||
| 3226 | if (!list_empty(&local->roc_list) || local->scanning) | ||
| 3227 | return -EBUSY; | ||
| 3228 | |||
| 3229 | if (sdata->wdev.cac_started) | ||
| 3230 | return -EBUSY; | ||
| 3231 | |||
| 3232 | if (cfg80211_chandef_identical(¶ms->chandef, | ||
| 3233 | &sdata->vif.bss_conf.chandef)) | ||
| 3234 | return -EINVAL; | ||
| 3235 | |||
| 3236 | rcu_read_lock(); | ||
| 3237 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
| 3238 | if (!chanctx_conf) { | ||
| 3239 | rcu_read_unlock(); | ||
| 3240 | return -EBUSY; | ||
| 3241 | } | ||
| 3242 | |||
| 3243 | /* don't handle for multi-VIF cases */ | ||
| 3244 | chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf); | ||
| 3245 | if (chanctx->refcount > 1) { | ||
| 3246 | rcu_read_unlock(); | ||
| 3247 | return -EBUSY; | ||
| 3248 | } | ||
| 3249 | num_chanctx = 0; | ||
| 3250 | list_for_each_entry_rcu(chanctx, &local->chanctx_list, list) | ||
| 3251 | num_chanctx++; | ||
| 3252 | rcu_read_unlock(); | ||
| 3253 | |||
| 3254 | if (num_chanctx > 1) | ||
| 3255 | return -EBUSY; | ||
| 3256 | |||
| 3257 | /* don't allow another channel switch if one is already active. */ | ||
| 3258 | if (sdata->vif.csa_active) | ||
| 3259 | return -EBUSY; | ||
| 3260 | |||
| 3261 | err = ieee80211_set_csa_beacon(sdata, params, &changed); | ||
| 3262 | if (err) | ||
| 3263 | return err; | ||
| 3264 | |||
| 3186 | sdata->csa_radar_required = params->radar_required; | 3265 | sdata->csa_radar_required = params->radar_required; |
| 3187 | 3266 | ||
| 3188 | if (params->block_tx) | 3267 | if (params->block_tx) |
| @@ -3193,8 +3272,13 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
| 3193 | sdata->csa_chandef = params->chandef; | 3272 | sdata->csa_chandef = params->chandef; |
| 3194 | sdata->vif.csa_active = true; | 3273 | sdata->vif.csa_active = true; |
| 3195 | 3274 | ||
| 3196 | ieee80211_bss_info_change_notify(sdata, err); | 3275 | if (changed) { |
| 3197 | drv_channel_switch_beacon(sdata, ¶ms->chandef); | 3276 | ieee80211_bss_info_change_notify(sdata, changed); |
| 3277 | drv_channel_switch_beacon(sdata, ¶ms->chandef); | ||
| 3278 | } else { | ||
| 3279 | /* if the beacon didn't change, we can finalize immediately */ | ||
| 3280 | ieee80211_csa_finalize(sdata); | ||
| 3281 | } | ||
| 3198 | 3282 | ||
| 3199 | return 0; | 3283 | return 0; |
| 3200 | } | 3284 | } |
| @@ -3573,8 +3657,8 @@ ieee80211_prep_tdls_direct(struct wiphy *wiphy, struct net_device *dev, | |||
| 3573 | 3657 | ||
| 3574 | static int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, | 3658 | static int ieee80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, |
| 3575 | u8 *peer, u8 action_code, u8 dialog_token, | 3659 | u8 *peer, u8 action_code, u8 dialog_token, |
| 3576 | u16 status_code, const u8 *extra_ies, | 3660 | u16 status_code, u32 peer_capability, |
| 3577 | size_t extra_ies_len) | 3661 | const u8 *extra_ies, size_t extra_ies_len) |
| 3578 | { | 3662 | { |
| 3579 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 3663 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); |
| 3580 | struct ieee80211_local *local = sdata->local; | 3664 | struct ieee80211_local *local = sdata->local; |
| @@ -3865,7 +3949,7 @@ static int ieee80211_set_qos_map(struct wiphy *wiphy, | |||
| 3865 | return 0; | 3949 | return 0; |
| 3866 | } | 3950 | } |
| 3867 | 3951 | ||
| 3868 | struct cfg80211_ops mac80211_config_ops = { | 3952 | const struct cfg80211_ops mac80211_config_ops = { |
| 3869 | .add_virtual_intf = ieee80211_add_iface, | 3953 | .add_virtual_intf = ieee80211_add_iface, |
| 3870 | .del_virtual_intf = ieee80211_del_iface, | 3954 | .del_virtual_intf = ieee80211_del_iface, |
| 3871 | .change_virtual_intf = ieee80211_change_iface, | 3955 | .change_virtual_intf = ieee80211_change_iface, |
diff --git a/net/mac80211/cfg.h b/net/mac80211/cfg.h index 7d7879f5b00b..2d51f62dc76c 100644 --- a/net/mac80211/cfg.h +++ b/net/mac80211/cfg.h | |||
| @@ -4,6 +4,6 @@ | |||
| 4 | #ifndef __CFG_H | 4 | #ifndef __CFG_H |
| 5 | #define __CFG_H | 5 | #define __CFG_H |
| 6 | 6 | ||
| 7 | extern struct cfg80211_ops mac80211_config_ops; | 7 | extern const struct cfg80211_ops mac80211_config_ops; |
| 8 | 8 | ||
| 9 | #endif /* __CFG_H */ | 9 | #endif /* __CFG_H */ |
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c index 0c1ecfdf9a12..bd1fd8ea5105 100644 --- a/net/mac80211/chan.c +++ b/net/mac80211/chan.c | |||
| @@ -202,6 +202,8 @@ static bool ieee80211_is_radar_required(struct ieee80211_local *local) | |||
| 202 | { | 202 | { |
| 203 | struct ieee80211_sub_if_data *sdata; | 203 | struct ieee80211_sub_if_data *sdata; |
| 204 | 204 | ||
| 205 | lockdep_assert_held(&local->mtx); | ||
| 206 | |||
| 205 | rcu_read_lock(); | 207 | rcu_read_lock(); |
| 206 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 208 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { |
| 207 | if (sdata->radar_required) { | 209 | if (sdata->radar_required) { |
diff --git a/net/mac80211/debugfs_netdev.c b/net/mac80211/debugfs_netdev.c index ebf80f3abd83..40a648938985 100644 --- a/net/mac80211/debugfs_netdev.c +++ b/net/mac80211/debugfs_netdev.c | |||
| @@ -358,6 +358,18 @@ static ssize_t ieee80211_if_parse_tkip_mic_test( | |||
| 358 | } | 358 | } |
| 359 | IEEE80211_IF_FILE_W(tkip_mic_test); | 359 | IEEE80211_IF_FILE_W(tkip_mic_test); |
| 360 | 360 | ||
| 361 | static ssize_t ieee80211_if_parse_beacon_loss( | ||
| 362 | struct ieee80211_sub_if_data *sdata, const char *buf, int buflen) | ||
| 363 | { | ||
| 364 | if (!ieee80211_sdata_running(sdata) || !sdata->vif.bss_conf.assoc) | ||
| 365 | return -ENOTCONN; | ||
| 366 | |||
| 367 | ieee80211_beacon_loss(&sdata->vif); | ||
| 368 | |||
| 369 | return buflen; | ||
| 370 | } | ||
| 371 | IEEE80211_IF_FILE_W(beacon_loss); | ||
| 372 | |||
| 361 | static ssize_t ieee80211_if_fmt_uapsd_queues( | 373 | static ssize_t ieee80211_if_fmt_uapsd_queues( |
| 362 | const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) | 374 | const struct ieee80211_sub_if_data *sdata, char *buf, int buflen) |
| 363 | { | 375 | { |
| @@ -569,6 +581,7 @@ static void add_sta_files(struct ieee80211_sub_if_data *sdata) | |||
| 569 | DEBUGFS_ADD(beacon_timeout); | 581 | DEBUGFS_ADD(beacon_timeout); |
| 570 | DEBUGFS_ADD_MODE(smps, 0600); | 582 | DEBUGFS_ADD_MODE(smps, 0600); |
| 571 | DEBUGFS_ADD_MODE(tkip_mic_test, 0200); | 583 | DEBUGFS_ADD_MODE(tkip_mic_test, 0200); |
| 584 | DEBUGFS_ADD_MODE(beacon_loss, 0200); | ||
| 572 | DEBUGFS_ADD_MODE(uapsd_queues, 0600); | 585 | DEBUGFS_ADD_MODE(uapsd_queues, 0600); |
| 573 | DEBUGFS_ADD_MODE(uapsd_max_sp_len, 0600); | 586 | DEBUGFS_ADD_MODE(uapsd_max_sp_len, 0600); |
| 574 | } | 587 | } |
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c index 80194b557a0c..2ecb4deddb5d 100644 --- a/net/mac80211/debugfs_sta.c +++ b/net/mac80211/debugfs_sta.c | |||
| @@ -195,7 +195,7 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf, | |||
| 195 | static ssize_t sta_agg_status_write(struct file *file, const char __user *userbuf, | 195 | static ssize_t sta_agg_status_write(struct file *file, const char __user *userbuf, |
| 196 | size_t count, loff_t *ppos) | 196 | size_t count, loff_t *ppos) |
| 197 | { | 197 | { |
| 198 | char _buf[12], *buf = _buf; | 198 | char _buf[12] = {}, *buf = _buf; |
| 199 | struct sta_info *sta = file->private_data; | 199 | struct sta_info *sta = file->private_data; |
| 200 | bool start, tx; | 200 | bool start, tx; |
| 201 | unsigned long tid; | 201 | unsigned long tid; |
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h index ef8b385eff04..fc689f5d971e 100644 --- a/net/mac80211/driver-ops.h +++ b/net/mac80211/driver-ops.h | |||
| @@ -354,16 +354,20 @@ drv_sched_scan_start(struct ieee80211_local *local, | |||
| 354 | return ret; | 354 | return ret; |
| 355 | } | 355 | } |
| 356 | 356 | ||
| 357 | static inline void drv_sched_scan_stop(struct ieee80211_local *local, | 357 | static inline int drv_sched_scan_stop(struct ieee80211_local *local, |
| 358 | struct ieee80211_sub_if_data *sdata) | 358 | struct ieee80211_sub_if_data *sdata) |
| 359 | { | 359 | { |
| 360 | int ret; | ||
| 361 | |||
| 360 | might_sleep(); | 362 | might_sleep(); |
| 361 | 363 | ||
| 362 | check_sdata_in_driver(sdata); | 364 | check_sdata_in_driver(sdata); |
| 363 | 365 | ||
| 364 | trace_drv_sched_scan_stop(local, sdata); | 366 | trace_drv_sched_scan_stop(local, sdata); |
| 365 | local->ops->sched_scan_stop(&local->hw, &sdata->vif); | 367 | ret = local->ops->sched_scan_stop(&local->hw, &sdata->vif); |
| 366 | trace_drv_return_void(local); | 368 | trace_drv_return_int(local, ret); |
| 369 | |||
| 370 | return ret; | ||
| 367 | } | 371 | } |
| 368 | 372 | ||
| 369 | static inline void drv_sw_scan_start(struct ieee80211_local *local) | 373 | static inline void drv_sw_scan_start(struct ieee80211_local *local) |
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index 70dd013de836..c150b68436d7 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
| @@ -375,7 +375,7 @@ void ieee80211_send_delba(struct ieee80211_sub_if_data *sdata, | |||
| 375 | mgmt->u.action.u.delba.params = cpu_to_le16(params); | 375 | mgmt->u.action.u.delba.params = cpu_to_le16(params); |
| 376 | mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code); | 376 | mgmt->u.action.u.delba.reason_code = cpu_to_le16(reason_code); |
| 377 | 377 | ||
| 378 | ieee80211_tx_skb_tid(sdata, skb, tid); | 378 | ieee80211_tx_skb(sdata, skb); |
| 379 | } | 379 | } |
| 380 | 380 | ||
| 381 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, | 381 | void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, |
| @@ -482,8 +482,6 @@ void ieee80211_request_smps(struct ieee80211_vif *vif, | |||
| 482 | return; | 482 | return; |
| 483 | 483 | ||
| 484 | if (vif->type == NL80211_IFTYPE_STATION) { | 484 | if (vif->type == NL80211_IFTYPE_STATION) { |
| 485 | if (WARN_ON(smps_mode == IEEE80211_SMPS_OFF)) | ||
| 486 | smps_mode = IEEE80211_SMPS_AUTOMATIC; | ||
| 487 | if (sdata->u.mgd.driver_smps_mode == smps_mode) | 485 | if (sdata->u.mgd.driver_smps_mode == smps_mode) |
| 488 | return; | 486 | return; |
| 489 | sdata->u.mgd.driver_smps_mode = smps_mode; | 487 | sdata->u.mgd.driver_smps_mode = smps_mode; |
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c index 2796a198728f..06d28787945b 100644 --- a/net/mac80211/ibss.c +++ b/net/mac80211/ibss.c | |||
| @@ -220,7 +220,6 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
| 220 | { | 220 | { |
| 221 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 221 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
| 222 | struct ieee80211_local *local = sdata->local; | 222 | struct ieee80211_local *local = sdata->local; |
| 223 | struct ieee80211_supported_band *sband; | ||
| 224 | struct ieee80211_mgmt *mgmt; | 223 | struct ieee80211_mgmt *mgmt; |
| 225 | struct cfg80211_bss *bss; | 224 | struct cfg80211_bss *bss; |
| 226 | u32 bss_change; | 225 | u32 bss_change; |
| @@ -284,6 +283,11 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
| 284 | 283 | ||
| 285 | err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy, | 284 | err = cfg80211_chandef_dfs_required(sdata->local->hw.wiphy, |
| 286 | &chandef); | 285 | &chandef); |
| 286 | if (err < 0) { | ||
| 287 | sdata_info(sdata, | ||
| 288 | "Failed to join IBSS, invalid chandef\n"); | ||
| 289 | return; | ||
| 290 | } | ||
| 287 | if (err > 0) { | 291 | if (err > 0) { |
| 288 | if (!ifibss->userspace_handles_dfs) { | 292 | if (!ifibss->userspace_handles_dfs) { |
| 289 | sdata_info(sdata, | 293 | sdata_info(sdata, |
| @@ -294,7 +298,6 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
| 294 | } | 298 | } |
| 295 | 299 | ||
| 296 | mutex_lock(&local->mtx); | 300 | mutex_lock(&local->mtx); |
| 297 | ieee80211_vif_release_channel(sdata); | ||
| 298 | if (ieee80211_vif_use_channel(sdata, &chandef, | 301 | if (ieee80211_vif_use_channel(sdata, &chandef, |
| 299 | ifibss->fixed_channel ? | 302 | ifibss->fixed_channel ? |
| 300 | IEEE80211_CHANCTX_SHARED : | 303 | IEEE80211_CHANCTX_SHARED : |
| @@ -303,12 +306,11 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
| 303 | mutex_unlock(&local->mtx); | 306 | mutex_unlock(&local->mtx); |
| 304 | return; | 307 | return; |
| 305 | } | 308 | } |
| 309 | sdata->radar_required = radar_required; | ||
| 306 | mutex_unlock(&local->mtx); | 310 | mutex_unlock(&local->mtx); |
| 307 | 311 | ||
| 308 | memcpy(ifibss->bssid, bssid, ETH_ALEN); | 312 | memcpy(ifibss->bssid, bssid, ETH_ALEN); |
| 309 | 313 | ||
| 310 | sband = local->hw.wiphy->bands[chan->band]; | ||
| 311 | |||
| 312 | presp = ieee80211_ibss_build_presp(sdata, beacon_int, basic_rates, | 314 | presp = ieee80211_ibss_build_presp(sdata, beacon_int, basic_rates, |
| 313 | capability, tsf, &chandef, | 315 | capability, tsf, &chandef, |
| 314 | &have_higher_than_11mbit, NULL); | 316 | &have_higher_than_11mbit, NULL); |
| @@ -318,7 +320,6 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
| 318 | rcu_assign_pointer(ifibss->presp, presp); | 320 | rcu_assign_pointer(ifibss->presp, presp); |
| 319 | mgmt = (void *)presp->head; | 321 | mgmt = (void *)presp->head; |
| 320 | 322 | ||
| 321 | sdata->radar_required = radar_required; | ||
| 322 | sdata->vif.bss_conf.enable_beacon = true; | 323 | sdata->vif.bss_conf.enable_beacon = true; |
| 323 | sdata->vif.bss_conf.beacon_int = beacon_int; | 324 | sdata->vif.bss_conf.beacon_int = beacon_int; |
| 324 | sdata->vif.bss_conf.basic_rates = basic_rates; | 325 | sdata->vif.bss_conf.basic_rates = basic_rates; |
| @@ -386,7 +387,7 @@ static void __ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
| 386 | presp->head_len, 0, GFP_KERNEL); | 387 | presp->head_len, 0, GFP_KERNEL); |
| 387 | cfg80211_put_bss(local->hw.wiphy, bss); | 388 | cfg80211_put_bss(local->hw.wiphy, bss); |
| 388 | netif_carrier_on(sdata->dev); | 389 | netif_carrier_on(sdata->dev); |
| 389 | cfg80211_ibss_joined(sdata->dev, ifibss->bssid, GFP_KERNEL); | 390 | cfg80211_ibss_joined(sdata->dev, ifibss->bssid, chan, GFP_KERNEL); |
| 390 | } | 391 | } |
| 391 | 392 | ||
| 392 | static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | 393 | static void ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, |
| @@ -521,12 +522,6 @@ int ieee80211_ibss_csa_beacon(struct ieee80211_sub_if_data *sdata, | |||
| 521 | if (old_presp) | 522 | if (old_presp) |
| 522 | kfree_rcu(old_presp, rcu_head); | 523 | kfree_rcu(old_presp, rcu_head); |
| 523 | 524 | ||
| 524 | /* it might not send the beacon for a while. send an action frame | ||
| 525 | * immediately to announce the channel switch. | ||
| 526 | */ | ||
| 527 | if (csa_settings) | ||
| 528 | ieee80211_send_action_csa(sdata, csa_settings); | ||
| 529 | |||
| 530 | return BSS_CHANGED_BEACON; | 525 | return BSS_CHANGED_BEACON; |
| 531 | out: | 526 | out: |
| 532 | return ret; | 527 | return ret; |
| @@ -536,7 +531,7 @@ int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata) | |||
| 536 | { | 531 | { |
| 537 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; | 532 | struct ieee80211_if_ibss *ifibss = &sdata->u.ibss; |
| 538 | struct cfg80211_bss *cbss; | 533 | struct cfg80211_bss *cbss; |
| 539 | int err; | 534 | int err, changed = 0; |
| 540 | u16 capability; | 535 | u16 capability; |
| 541 | 536 | ||
| 542 | sdata_assert_lock(sdata); | 537 | sdata_assert_lock(sdata); |
| @@ -568,10 +563,9 @@ int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata) | |||
| 568 | if (err < 0) | 563 | if (err < 0) |
| 569 | return err; | 564 | return err; |
| 570 | 565 | ||
| 571 | if (err) | 566 | changed |= err; |
| 572 | ieee80211_bss_info_change_notify(sdata, err); | ||
| 573 | 567 | ||
| 574 | return 0; | 568 | return changed; |
| 575 | } | 569 | } |
| 576 | 570 | ||
| 577 | void ieee80211_ibss_stop(struct ieee80211_sub_if_data *sdata) | 571 | void ieee80211_ibss_stop(struct ieee80211_sub_if_data *sdata) |
| @@ -799,6 +793,8 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
| 799 | int err; | 793 | int err; |
| 800 | u32 sta_flags; | 794 | u32 sta_flags; |
| 801 | 795 | ||
| 796 | sdata_assert_lock(sdata); | ||
| 797 | |||
| 802 | sta_flags = IEEE80211_STA_DISABLE_VHT; | 798 | sta_flags = IEEE80211_STA_DISABLE_VHT; |
| 803 | switch (ifibss->chandef.width) { | 799 | switch (ifibss->chandef.width) { |
| 804 | case NL80211_CHAN_WIDTH_5: | 800 | case NL80211_CHAN_WIDTH_5: |
| @@ -995,7 +991,6 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
| 995 | struct ieee802_11_elems *elems) | 991 | struct ieee802_11_elems *elems) |
| 996 | { | 992 | { |
| 997 | struct ieee80211_local *local = sdata->local; | 993 | struct ieee80211_local *local = sdata->local; |
| 998 | int freq; | ||
| 999 | struct cfg80211_bss *cbss; | 994 | struct cfg80211_bss *cbss; |
| 1000 | struct ieee80211_bss *bss; | 995 | struct ieee80211_bss *bss; |
| 1001 | struct sta_info *sta; | 996 | struct sta_info *sta; |
| @@ -1007,15 +1002,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
| 1007 | struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; | 1002 | struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; |
| 1008 | bool rates_updated = false; | 1003 | bool rates_updated = false; |
| 1009 | 1004 | ||
| 1010 | if (elems->ds_params) | 1005 | channel = ieee80211_get_channel(local->hw.wiphy, rx_status->freq); |
| 1011 | freq = ieee80211_channel_to_frequency(elems->ds_params[0], | 1006 | if (!channel) |
| 1012 | band); | ||
| 1013 | else | ||
| 1014 | freq = rx_status->freq; | ||
| 1015 | |||
| 1016 | channel = ieee80211_get_channel(local->hw.wiphy, freq); | ||
| 1017 | |||
| 1018 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) | ||
| 1019 | return; | 1007 | return; |
| 1020 | 1008 | ||
| 1021 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && | 1009 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && |
| @@ -1468,6 +1456,11 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
| 1468 | memcpy(((struct ieee80211_mgmt *) skb->data)->da, mgmt->sa, ETH_ALEN); | 1456 | memcpy(((struct ieee80211_mgmt *) skb->data)->da, mgmt->sa, ETH_ALEN); |
| 1469 | ibss_dbg(sdata, "Sending ProbeResp to %pM\n", mgmt->sa); | 1457 | ibss_dbg(sdata, "Sending ProbeResp to %pM\n", mgmt->sa); |
| 1470 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 1458 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
| 1459 | |||
| 1460 | /* avoid excessive retries for probe request to wildcard SSIDs */ | ||
| 1461 | if (pos[1] == 0) | ||
| 1462 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_CTL_NO_ACK; | ||
| 1463 | |||
| 1471 | ieee80211_tx_skb(sdata, skb); | 1464 | ieee80211_tx_skb(sdata, skb); |
| 1472 | } | 1465 | } |
| 1473 | 1466 | ||
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 5e44e3179e02..222c28b75315 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
| @@ -616,7 +616,11 @@ struct ieee80211_if_mesh { | |||
| 616 | struct ps_data ps; | 616 | struct ps_data ps; |
| 617 | /* Channel Switching Support */ | 617 | /* Channel Switching Support */ |
| 618 | struct mesh_csa_settings __rcu *csa; | 618 | struct mesh_csa_settings __rcu *csa; |
| 619 | bool chsw_init; | 619 | enum { |
| 620 | IEEE80211_MESH_CSA_ROLE_NONE, | ||
| 621 | IEEE80211_MESH_CSA_ROLE_INIT, | ||
| 622 | IEEE80211_MESH_CSA_ROLE_REPEATER, | ||
| 623 | } csa_role; | ||
| 620 | u8 chsw_ttl; | 624 | u8 chsw_ttl; |
| 621 | u16 pre_value; | 625 | u16 pre_value; |
| 622 | 626 | ||
| @@ -1238,6 +1242,8 @@ struct ieee80211_local { | |||
| 1238 | 1242 | ||
| 1239 | struct ieee80211_sub_if_data __rcu *p2p_sdata; | 1243 | struct ieee80211_sub_if_data __rcu *p2p_sdata; |
| 1240 | 1244 | ||
| 1245 | struct napi_struct *napi; | ||
| 1246 | |||
| 1241 | /* virtual monitor interface */ | 1247 | /* virtual monitor interface */ |
| 1242 | struct ieee80211_sub_if_data __rcu *monitor_sdata; | 1248 | struct ieee80211_sub_if_data __rcu *monitor_sdata; |
| 1243 | struct cfg80211_chan_def monitor_chandef; | 1249 | struct cfg80211_chan_def monitor_chandef; |
| @@ -1385,6 +1391,7 @@ void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata); | |||
| 1385 | void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata); | 1391 | void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata); |
| 1386 | void ieee80211_mgd_conn_tx_status(struct ieee80211_sub_if_data *sdata, | 1392 | void ieee80211_mgd_conn_tx_status(struct ieee80211_sub_if_data *sdata, |
| 1387 | __le16 fc, bool acked); | 1393 | __le16 fc, bool acked); |
| 1394 | void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata); | ||
| 1388 | void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata); | 1395 | void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata); |
| 1389 | 1396 | ||
| 1390 | /* IBSS code */ | 1397 | /* IBSS code */ |
| @@ -1408,8 +1415,7 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata); | |||
| 1408 | void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | 1415 | void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, |
| 1409 | struct sk_buff *skb); | 1416 | struct sk_buff *skb); |
| 1410 | int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata, | 1417 | int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata, |
| 1411 | struct cfg80211_csa_settings *csa_settings, | 1418 | struct cfg80211_csa_settings *csa_settings); |
| 1412 | bool csa_action); | ||
| 1413 | int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata); | 1419 | int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata); |
| 1414 | 1420 | ||
| 1415 | /* scan/BSS handling */ | 1421 | /* scan/BSS handling */ |
| @@ -1553,6 +1559,9 @@ ieee80211_vht_cap_ie_to_sta_vht_cap(struct ieee80211_sub_if_data *sdata, | |||
| 1553 | struct sta_info *sta); | 1559 | struct sta_info *sta); |
| 1554 | enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta); | 1560 | enum ieee80211_sta_rx_bandwidth ieee80211_sta_cur_vht_bw(struct sta_info *sta); |
| 1555 | void ieee80211_sta_set_rx_nss(struct sta_info *sta); | 1561 | void ieee80211_sta_set_rx_nss(struct sta_info *sta); |
| 1562 | u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | ||
| 1563 | struct sta_info *sta, u8 opmode, | ||
| 1564 | enum ieee80211_band band, bool nss_only); | ||
| 1556 | void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | 1565 | void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, |
| 1557 | struct sta_info *sta, u8 opmode, | 1566 | struct sta_info *sta, u8 opmode, |
| 1558 | enum ieee80211_band band, bool nss_only); | 1567 | enum ieee80211_band band, bool nss_only); |
| @@ -1605,7 +1614,7 @@ static inline int __ieee80211_resume(struct ieee80211_hw *hw) | |||
| 1605 | } | 1614 | } |
| 1606 | 1615 | ||
| 1607 | /* utility functions/constants */ | 1616 | /* utility functions/constants */ |
| 1608 | extern void *mac80211_wiphy_privid; /* for wiphy privid */ | 1617 | extern const void *const mac80211_wiphy_privid; /* for wiphy privid */ |
| 1609 | u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, | 1618 | u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len, |
| 1610 | enum nl80211_iftype type); | 1619 | enum nl80211_iftype type); |
| 1611 | int ieee80211_frame_duration(enum ieee80211_band band, size_t len, | 1620 | int ieee80211_frame_duration(enum ieee80211_band band, size_t len, |
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index ce1c44370610..b8d331e7d883 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
| @@ -101,9 +101,8 @@ static u32 __ieee80211_idle_on(struct ieee80211_local *local) | |||
| 101 | static u32 __ieee80211_recalc_idle(struct ieee80211_local *local, | 101 | static u32 __ieee80211_recalc_idle(struct ieee80211_local *local, |
| 102 | bool force_active) | 102 | bool force_active) |
| 103 | { | 103 | { |
| 104 | bool working = false, scanning, active; | 104 | bool working, scanning, active; |
| 105 | unsigned int led_trig_start = 0, led_trig_stop = 0; | 105 | unsigned int led_trig_start = 0, led_trig_stop = 0; |
| 106 | struct ieee80211_roc_work *roc; | ||
| 107 | 106 | ||
| 108 | lockdep_assert_held(&local->mtx); | 107 | lockdep_assert_held(&local->mtx); |
| 109 | 108 | ||
| @@ -111,12 +110,8 @@ static u32 __ieee80211_recalc_idle(struct ieee80211_local *local, | |||
| 111 | !list_empty(&local->chanctx_list) || | 110 | !list_empty(&local->chanctx_list) || |
| 112 | local->monitors; | 111 | local->monitors; |
| 113 | 112 | ||
| 114 | if (!local->ops->remain_on_channel) { | 113 | working = !local->ops->remain_on_channel && |
| 115 | list_for_each_entry(roc, &local->roc_list, list) { | 114 | !list_empty(&local->roc_list); |
| 116 | working = true; | ||
| 117 | break; | ||
| 118 | } | ||
| 119 | } | ||
| 120 | 115 | ||
| 121 | scanning = test_bit(SCAN_SW_SCANNING, &local->scanning) || | 116 | scanning = test_bit(SCAN_SW_SCANNING, &local->scanning) || |
| 122 | test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning); | 117 | test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning); |
| @@ -833,7 +828,9 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
| 833 | cancel_work_sync(&local->dynamic_ps_enable_work); | 828 | cancel_work_sync(&local->dynamic_ps_enable_work); |
| 834 | 829 | ||
| 835 | cancel_work_sync(&sdata->recalc_smps); | 830 | cancel_work_sync(&sdata->recalc_smps); |
| 831 | sdata_lock(sdata); | ||
| 836 | sdata->vif.csa_active = false; | 832 | sdata->vif.csa_active = false; |
| 833 | sdata_unlock(sdata); | ||
| 837 | cancel_work_sync(&sdata->csa_finalize_work); | 834 | cancel_work_sync(&sdata->csa_finalize_work); |
| 838 | 835 | ||
| 839 | cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); | 836 | cancel_delayed_work_sync(&sdata->dfs_cac_timer_work); |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index d767cfb9b45f..b055f6a55c68 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
| @@ -893,10 +893,15 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
| 893 | /* mac80211 supports control port protocol changing */ | 893 | /* mac80211 supports control port protocol changing */ |
| 894 | local->hw.wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL; | 894 | local->hw.wiphy->flags |= WIPHY_FLAG_CONTROL_PORT_PROTOCOL; |
| 895 | 895 | ||
| 896 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) | 896 | if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM) { |
| 897 | local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; | 897 | local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; |
| 898 | else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) | 898 | } else if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC) { |
| 899 | local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC; | 899 | local->hw.wiphy->signal_type = CFG80211_SIGNAL_TYPE_UNSPEC; |
| 900 | if (hw->max_signal <= 0) { | ||
| 901 | result = -EINVAL; | ||
| 902 | goto fail_wiphy_register; | ||
| 903 | } | ||
| 904 | } | ||
| 900 | 905 | ||
| 901 | WARN((local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) | 906 | WARN((local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) |
| 902 | && (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK), | 907 | && (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK), |
| @@ -1071,6 +1076,18 @@ int ieee80211_register_hw(struct ieee80211_hw *hw) | |||
| 1071 | } | 1076 | } |
| 1072 | EXPORT_SYMBOL(ieee80211_register_hw); | 1077 | EXPORT_SYMBOL(ieee80211_register_hw); |
| 1073 | 1078 | ||
| 1079 | void ieee80211_napi_add(struct ieee80211_hw *hw, struct napi_struct *napi, | ||
| 1080 | struct net_device *napi_dev, | ||
| 1081 | int (*poll)(struct napi_struct *, int), | ||
| 1082 | int weight) | ||
| 1083 | { | ||
| 1084 | struct ieee80211_local *local = hw_to_local(hw); | ||
| 1085 | |||
| 1086 | netif_napi_add(napi_dev, napi, poll, weight); | ||
| 1087 | local->napi = napi; | ||
| 1088 | } | ||
| 1089 | EXPORT_SYMBOL_GPL(ieee80211_napi_add); | ||
| 1090 | |||
| 1074 | void ieee80211_unregister_hw(struct ieee80211_hw *hw) | 1091 | void ieee80211_unregister_hw(struct ieee80211_hw *hw) |
| 1075 | { | 1092 | { |
| 1076 | struct ieee80211_local *local = hw_to_local(hw); | 1093 | struct ieee80211_local *local = hw_to_local(hw); |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 5b919cab1de0..f70e9cd10552 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
| @@ -688,7 +688,7 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh) | |||
| 688 | *pos++ = csa->settings.count; | 688 | *pos++ = csa->settings.count; |
| 689 | *pos++ = WLAN_EID_CHAN_SWITCH_PARAM; | 689 | *pos++ = WLAN_EID_CHAN_SWITCH_PARAM; |
| 690 | *pos++ = 6; | 690 | *pos++ = 6; |
| 691 | if (ifmsh->chsw_init) { | 691 | if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT) { |
| 692 | *pos++ = ifmsh->mshcfg.dot11MeshTTL; | 692 | *pos++ = ifmsh->mshcfg.dot11MeshTTL; |
| 693 | *pos |= WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR; | 693 | *pos |= WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR; |
| 694 | } else { | 694 | } else { |
| @@ -859,18 +859,12 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata, | |||
| 859 | { | 859 | { |
| 860 | struct cfg80211_csa_settings params; | 860 | struct cfg80211_csa_settings params; |
| 861 | struct ieee80211_csa_ie csa_ie; | 861 | struct ieee80211_csa_ie csa_ie; |
| 862 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
| 863 | struct ieee80211_chanctx *chanctx; | ||
| 864 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 862 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
| 865 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); | 863 | enum ieee80211_band band = ieee80211_get_sdata_band(sdata); |
| 866 | int err, num_chanctx; | 864 | int err; |
| 867 | u32 sta_flags; | 865 | u32 sta_flags; |
| 868 | 866 | ||
| 869 | if (sdata->vif.csa_active) | 867 | sdata_assert_lock(sdata); |
| 870 | return true; | ||
| 871 | |||
| 872 | if (!ifmsh->mesh_id) | ||
| 873 | return false; | ||
| 874 | 868 | ||
| 875 | sta_flags = IEEE80211_STA_DISABLE_VHT; | 869 | sta_flags = IEEE80211_STA_DISABLE_VHT; |
| 876 | switch (sdata->vif.bss_conf.chandef.width) { | 870 | switch (sdata->vif.bss_conf.chandef.width) { |
| @@ -896,10 +890,6 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata, | |||
| 896 | params.chandef = csa_ie.chandef; | 890 | params.chandef = csa_ie.chandef; |
| 897 | params.count = csa_ie.count; | 891 | params.count = csa_ie.count; |
| 898 | 892 | ||
| 899 | if (sdata->vif.bss_conf.chandef.chan->band != | ||
| 900 | params.chandef.chan->band) | ||
| 901 | return false; | ||
| 902 | |||
| 903 | if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, ¶ms.chandef, | 893 | if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, ¶ms.chandef, |
| 904 | IEEE80211_CHAN_DISABLED)) { | 894 | IEEE80211_CHAN_DISABLED)) { |
| 905 | sdata_info(sdata, | 895 | sdata_info(sdata, |
| @@ -922,24 +912,12 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata, | |||
| 922 | return false; | 912 | return false; |
| 923 | } | 913 | } |
| 924 | 914 | ||
| 925 | rcu_read_lock(); | 915 | if (cfg80211_chandef_identical(¶ms.chandef, |
| 926 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | 916 | &sdata->vif.bss_conf.chandef)) { |
| 927 | if (!chanctx_conf) | 917 | mcsa_dbg(sdata, |
| 928 | goto failed_chswitch; | 918 | "received csa with an identical chandef, ignoring\n"); |
| 929 | 919 | return true; | |
| 930 | /* don't handle for multi-VIF cases */ | 920 | } |
| 931 | chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf); | ||
| 932 | if (chanctx->refcount > 1) | ||
| 933 | goto failed_chswitch; | ||
| 934 | |||
| 935 | num_chanctx = 0; | ||
| 936 | list_for_each_entry_rcu(chanctx, &sdata->local->chanctx_list, list) | ||
| 937 | num_chanctx++; | ||
| 938 | |||
| 939 | if (num_chanctx > 1) | ||
| 940 | goto failed_chswitch; | ||
| 941 | |||
| 942 | rcu_read_unlock(); | ||
| 943 | 921 | ||
| 944 | mcsa_dbg(sdata, | 922 | mcsa_dbg(sdata, |
| 945 | "received channel switch announcement to go to channel %d MHz\n", | 923 | "received channel switch announcement to go to channel %d MHz\n", |
| @@ -953,30 +931,16 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata, | |||
| 953 | ifmsh->pre_value = csa_ie.pre_value; | 931 | ifmsh->pre_value = csa_ie.pre_value; |
| 954 | } | 932 | } |
| 955 | 933 | ||
| 956 | if (ifmsh->chsw_ttl < ifmsh->mshcfg.dot11MeshTTL) { | 934 | if (ifmsh->chsw_ttl >= ifmsh->mshcfg.dot11MeshTTL) |
| 957 | if (ieee80211_mesh_csa_beacon(sdata, ¶ms, false) < 0) | ||
| 958 | return false; | ||
| 959 | } else { | ||
| 960 | return false; | 935 | return false; |
| 961 | } | ||
| 962 | 936 | ||
| 963 | sdata->csa_radar_required = params.radar_required; | 937 | ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_REPEATER; |
| 964 | 938 | ||
| 965 | if (params.block_tx) | 939 | if (ieee80211_channel_switch(sdata->local->hw.wiphy, sdata->dev, |
| 966 | ieee80211_stop_queues_by_reason(&sdata->local->hw, | 940 | ¶ms) < 0) |
| 967 | IEEE80211_MAX_QUEUE_MAP, | 941 | return false; |
| 968 | IEEE80211_QUEUE_STOP_REASON_CSA); | ||
| 969 | |||
| 970 | sdata->csa_chandef = params.chandef; | ||
| 971 | sdata->vif.csa_active = true; | ||
| 972 | |||
| 973 | ieee80211_bss_info_change_notify(sdata, err); | ||
| 974 | drv_channel_switch_beacon(sdata, ¶ms.chandef); | ||
| 975 | 942 | ||
| 976 | return true; | 943 | return true; |
| 977 | failed_chswitch: | ||
| 978 | rcu_read_unlock(); | ||
| 979 | return false; | ||
| 980 | } | 944 | } |
| 981 | 945 | ||
| 982 | static void | 946 | static void |
| @@ -1086,7 +1050,8 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata, | |||
| 1086 | ifmsh->sync_ops->rx_bcn_presp(sdata, | 1050 | ifmsh->sync_ops->rx_bcn_presp(sdata, |
| 1087 | stype, mgmt, &elems, rx_status); | 1051 | stype, mgmt, &elems, rx_status); |
| 1088 | 1052 | ||
| 1089 | if (!ifmsh->chsw_init) | 1053 | if (ifmsh->csa_role != IEEE80211_MESH_CSA_ROLE_INIT && |
| 1054 | !sdata->vif.csa_active) | ||
| 1090 | ieee80211_mesh_process_chnswitch(sdata, &elems, true); | 1055 | ieee80211_mesh_process_chnswitch(sdata, &elems, true); |
| 1091 | } | 1056 | } |
| 1092 | 1057 | ||
| @@ -1095,29 +1060,30 @@ int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata) | |||
| 1095 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 1060 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
| 1096 | struct mesh_csa_settings *tmp_csa_settings; | 1061 | struct mesh_csa_settings *tmp_csa_settings; |
| 1097 | int ret = 0; | 1062 | int ret = 0; |
| 1063 | int changed = 0; | ||
| 1098 | 1064 | ||
| 1099 | /* Reset the TTL value and Initiator flag */ | 1065 | /* Reset the TTL value and Initiator flag */ |
| 1100 | ifmsh->chsw_init = false; | 1066 | ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE; |
| 1101 | ifmsh->chsw_ttl = 0; | 1067 | ifmsh->chsw_ttl = 0; |
| 1102 | 1068 | ||
| 1103 | /* Remove the CSA and MCSP elements from the beacon */ | 1069 | /* Remove the CSA and MCSP elements from the beacon */ |
| 1104 | tmp_csa_settings = rcu_dereference(ifmsh->csa); | 1070 | tmp_csa_settings = rcu_dereference(ifmsh->csa); |
| 1105 | rcu_assign_pointer(ifmsh->csa, NULL); | 1071 | rcu_assign_pointer(ifmsh->csa, NULL); |
| 1106 | kfree_rcu(tmp_csa_settings, rcu_head); | 1072 | if (tmp_csa_settings) |
| 1073 | kfree_rcu(tmp_csa_settings, rcu_head); | ||
| 1107 | ret = ieee80211_mesh_rebuild_beacon(sdata); | 1074 | ret = ieee80211_mesh_rebuild_beacon(sdata); |
| 1108 | if (ret) | 1075 | if (ret) |
| 1109 | return -EINVAL; | 1076 | return -EINVAL; |
| 1110 | 1077 | ||
| 1111 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); | 1078 | changed |= BSS_CHANGED_BEACON; |
| 1112 | 1079 | ||
| 1113 | mcsa_dbg(sdata, "complete switching to center freq %d MHz", | 1080 | mcsa_dbg(sdata, "complete switching to center freq %d MHz", |
| 1114 | sdata->vif.bss_conf.chandef.chan->center_freq); | 1081 | sdata->vif.bss_conf.chandef.chan->center_freq); |
| 1115 | return 0; | 1082 | return changed; |
| 1116 | } | 1083 | } |
| 1117 | 1084 | ||
| 1118 | int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata, | 1085 | int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata, |
| 1119 | struct cfg80211_csa_settings *csa_settings, | 1086 | struct cfg80211_csa_settings *csa_settings) |
| 1120 | bool csa_action) | ||
| 1121 | { | 1087 | { |
| 1122 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; | 1088 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
| 1123 | struct mesh_csa_settings *tmp_csa_settings; | 1089 | struct mesh_csa_settings *tmp_csa_settings; |
| @@ -1141,12 +1107,7 @@ int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata, | |||
| 1141 | return ret; | 1107 | return ret; |
| 1142 | } | 1108 | } |
| 1143 | 1109 | ||
| 1144 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON); | 1110 | return BSS_CHANGED_BEACON; |
| 1145 | |||
| 1146 | if (csa_action) | ||
| 1147 | ieee80211_send_action_csa(sdata, csa_settings); | ||
| 1148 | |||
| 1149 | return 0; | ||
| 1150 | } | 1111 | } |
| 1151 | 1112 | ||
| 1152 | static int mesh_fwd_csa_frame(struct ieee80211_sub_if_data *sdata, | 1113 | static int mesh_fwd_csa_frame(struct ieee80211_sub_if_data *sdata, |
| @@ -1210,7 +1171,8 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata, | |||
| 1210 | 1171 | ||
| 1211 | ifmsh->pre_value = pre_value; | 1172 | ifmsh->pre_value = pre_value; |
| 1212 | 1173 | ||
| 1213 | if (!ieee80211_mesh_process_chnswitch(sdata, &elems, false)) { | 1174 | if (!sdata->vif.csa_active && |
| 1175 | !ieee80211_mesh_process_chnswitch(sdata, &elems, false)) { | ||
| 1214 | mcsa_dbg(sdata, "Failed to process CSA action frame"); | 1176 | mcsa_dbg(sdata, "Failed to process CSA action frame"); |
| 1215 | return; | 1177 | return; |
| 1216 | } | 1178 | } |
| @@ -1257,7 +1219,7 @@ void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, | |||
| 1257 | sdata_lock(sdata); | 1219 | sdata_lock(sdata); |
| 1258 | 1220 | ||
| 1259 | /* mesh already went down */ | 1221 | /* mesh already went down */ |
| 1260 | if (!sdata->wdev.mesh_id_len) | 1222 | if (!sdata->u.mesh.mesh_id_len) |
| 1261 | goto out; | 1223 | goto out; |
| 1262 | 1224 | ||
| 1263 | rx_status = IEEE80211_SKB_RXCB(skb); | 1225 | rx_status = IEEE80211_SKB_RXCB(skb); |
| @@ -1310,7 +1272,7 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata) | |||
| 1310 | sdata_lock(sdata); | 1272 | sdata_lock(sdata); |
| 1311 | 1273 | ||
| 1312 | /* mesh already went down */ | 1274 | /* mesh already went down */ |
| 1313 | if (!sdata->wdev.mesh_id_len) | 1275 | if (!sdata->u.mesh.mesh_id_len) |
| 1314 | goto out; | 1276 | goto out; |
| 1315 | 1277 | ||
| 1316 | if (ifmsh->preq_queue_len && | 1278 | if (ifmsh->preq_queue_len && |
| @@ -1365,7 +1327,7 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata) | |||
| 1365 | mesh_rmc_init(sdata); | 1327 | mesh_rmc_init(sdata); |
| 1366 | ifmsh->last_preq = jiffies; | 1328 | ifmsh->last_preq = jiffies; |
| 1367 | ifmsh->next_perr = jiffies; | 1329 | ifmsh->next_perr = jiffies; |
| 1368 | ifmsh->chsw_init = false; | 1330 | ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE; |
| 1369 | /* Allocate all mesh structures when creating the first mesh interface. */ | 1331 | /* Allocate all mesh structures when creating the first mesh interface. */ |
| 1370 | if (!mesh_allocated) | 1332 | if (!mesh_allocated) |
| 1371 | ieee80211s_init(); | 1333 | ieee80211s_init(); |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 245dce969b31..dee50aefd6e8 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
| @@ -131,13 +131,13 @@ void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata) | |||
| 131 | if (unlikely(!sdata->u.mgd.associated)) | 131 | if (unlikely(!sdata->u.mgd.associated)) |
| 132 | return; | 132 | return; |
| 133 | 133 | ||
| 134 | ifmgd->probe_send_count = 0; | ||
| 135 | |||
| 134 | if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) | 136 | if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR) |
| 135 | return; | 137 | return; |
| 136 | 138 | ||
| 137 | mod_timer(&sdata->u.mgd.conn_mon_timer, | 139 | mod_timer(&sdata->u.mgd.conn_mon_timer, |
| 138 | round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME)); | 140 | round_jiffies_up(jiffies + IEEE80211_CONNECTION_IDLE_TIME)); |
| 139 | |||
| 140 | ifmgd->probe_send_count = 0; | ||
| 141 | } | 141 | } |
| 142 | 142 | ||
| 143 | static int ecw2cw(int ecw) | 143 | static int ecw2cw(int ecw) |
| @@ -531,6 +531,7 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata, | |||
| 531 | u8 *pos; | 531 | u8 *pos; |
| 532 | u32 cap; | 532 | u32 cap; |
| 533 | struct ieee80211_sta_vht_cap vht_cap; | 533 | struct ieee80211_sta_vht_cap vht_cap; |
| 534 | u32 mask, ap_bf_sts, our_bf_sts; | ||
| 534 | 535 | ||
| 535 | BUILD_BUG_ON(sizeof(vht_cap) != sizeof(sband->vht_cap)); | 536 | BUILD_BUG_ON(sizeof(vht_cap) != sizeof(sband->vht_cap)); |
| 536 | 537 | ||
| @@ -558,6 +559,16 @@ static void ieee80211_add_vht_ie(struct ieee80211_sub_if_data *sdata, | |||
| 558 | cpu_to_le32(IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE))) | 559 | cpu_to_le32(IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE))) |
| 559 | cap &= ~IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; | 560 | cap &= ~IEEE80211_VHT_CAP_SU_BEAMFORMEE_CAPABLE; |
| 560 | 561 | ||
| 562 | mask = IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK; | ||
| 563 | |||
| 564 | ap_bf_sts = le32_to_cpu(ap_vht_cap->vht_cap_info) & mask; | ||
| 565 | our_bf_sts = cap & mask; | ||
| 566 | |||
| 567 | if (ap_bf_sts < our_bf_sts) { | ||
| 568 | cap &= ~mask; | ||
| 569 | cap |= ap_bf_sts; | ||
| 570 | } | ||
| 571 | |||
| 561 | /* reserve and fill IE */ | 572 | /* reserve and fill IE */ |
| 562 | pos = skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2); | 573 | pos = skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2); |
| 563 | ieee80211_ie_build_vht_cap(pos, &vht_cap, cap); | 574 | ieee80211_ie_build_vht_cap(pos, &vht_cap, cap); |
| @@ -768,6 +779,34 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata) | |||
| 768 | ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param, | 779 | ieee80211_add_ht_ie(sdata, skb, assoc_data->ap_ht_param, |
| 769 | sband, chan, sdata->smps_mode); | 780 | sband, chan, sdata->smps_mode); |
| 770 | 781 | ||
| 782 | /* if present, add any custom IEs that go before VHT */ | ||
| 783 | if (assoc_data->ie_len) { | ||
| 784 | static const u8 before_vht[] = { | ||
| 785 | WLAN_EID_SSID, | ||
| 786 | WLAN_EID_SUPP_RATES, | ||
| 787 | WLAN_EID_EXT_SUPP_RATES, | ||
| 788 | WLAN_EID_PWR_CAPABILITY, | ||
| 789 | WLAN_EID_SUPPORTED_CHANNELS, | ||
| 790 | WLAN_EID_RSN, | ||
| 791 | WLAN_EID_QOS_CAPA, | ||
| 792 | WLAN_EID_RRM_ENABLED_CAPABILITIES, | ||
| 793 | WLAN_EID_MOBILITY_DOMAIN, | ||
| 794 | WLAN_EID_SUPPORTED_REGULATORY_CLASSES, | ||
| 795 | WLAN_EID_HT_CAPABILITY, | ||
| 796 | WLAN_EID_BSS_COEX_2040, | ||
| 797 | WLAN_EID_EXT_CAPABILITY, | ||
| 798 | WLAN_EID_QOS_TRAFFIC_CAPA, | ||
| 799 | WLAN_EID_TIM_BCAST_REQ, | ||
| 800 | WLAN_EID_INTERWORKING, | ||
| 801 | }; | ||
| 802 | noffset = ieee80211_ie_split(assoc_data->ie, assoc_data->ie_len, | ||
| 803 | before_vht, ARRAY_SIZE(before_vht), | ||
| 804 | offset); | ||
| 805 | pos = skb_put(skb, noffset - offset); | ||
| 806 | memcpy(pos, assoc_data->ie + offset, noffset - offset); | ||
| 807 | offset = noffset; | ||
| 808 | } | ||
| 809 | |||
| 771 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) | 810 | if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT)) |
| 772 | ieee80211_add_vht_ie(sdata, skb, sband, | 811 | ieee80211_add_vht_ie(sdata, skb, sband, |
| 773 | &assoc_data->ap_vht_cap); | 812 | &assoc_data->ap_vht_cap); |
| @@ -1024,7 +1063,6 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
| 1024 | } | 1063 | } |
| 1025 | 1064 | ||
| 1026 | ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED; | 1065 | ifmgd->flags |= IEEE80211_STA_CSA_RECEIVED; |
| 1027 | sdata->vif.csa_active = true; | ||
| 1028 | 1066 | ||
| 1029 | mutex_lock(&local->chanctx_mtx); | 1067 | mutex_lock(&local->chanctx_mtx); |
| 1030 | if (local->use_chanctx) { | 1068 | if (local->use_chanctx) { |
| @@ -1062,6 +1100,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, | |||
| 1062 | mutex_unlock(&local->chanctx_mtx); | 1100 | mutex_unlock(&local->chanctx_mtx); |
| 1063 | 1101 | ||
| 1064 | sdata->csa_chandef = csa_ie.chandef; | 1102 | sdata->csa_chandef = csa_ie.chandef; |
| 1103 | sdata->vif.csa_active = true; | ||
| 1065 | 1104 | ||
| 1066 | if (csa_ie.mode) | 1105 | if (csa_ie.mode) |
| 1067 | ieee80211_stop_queues_by_reason(&local->hw, | 1106 | ieee80211_stop_queues_by_reason(&local->hw, |
| @@ -2233,6 +2272,62 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, | |||
| 2233 | /* ignore frame -- wait for timeout */ | 2272 | /* ignore frame -- wait for timeout */ |
| 2234 | } | 2273 | } |
| 2235 | 2274 | ||
| 2275 | #define case_WLAN(type) \ | ||
| 2276 | case WLAN_REASON_##type: return #type | ||
| 2277 | |||
| 2278 | static const char *ieee80211_get_reason_code_string(u16 reason_code) | ||
| 2279 | { | ||
| 2280 | switch (reason_code) { | ||
| 2281 | case_WLAN(UNSPECIFIED); | ||
| 2282 | case_WLAN(PREV_AUTH_NOT_VALID); | ||
| 2283 | case_WLAN(DEAUTH_LEAVING); | ||
| 2284 | case_WLAN(DISASSOC_DUE_TO_INACTIVITY); | ||
| 2285 | case_WLAN(DISASSOC_AP_BUSY); | ||
| 2286 | case_WLAN(CLASS2_FRAME_FROM_NONAUTH_STA); | ||
| 2287 | case_WLAN(CLASS3_FRAME_FROM_NONASSOC_STA); | ||
| 2288 | case_WLAN(DISASSOC_STA_HAS_LEFT); | ||
| 2289 | case_WLAN(STA_REQ_ASSOC_WITHOUT_AUTH); | ||
| 2290 | case_WLAN(DISASSOC_BAD_POWER); | ||
| 2291 | case_WLAN(DISASSOC_BAD_SUPP_CHAN); | ||
| 2292 | case_WLAN(INVALID_IE); | ||
| 2293 | case_WLAN(MIC_FAILURE); | ||
| 2294 | case_WLAN(4WAY_HANDSHAKE_TIMEOUT); | ||
| 2295 | case_WLAN(GROUP_KEY_HANDSHAKE_TIMEOUT); | ||
| 2296 | case_WLAN(IE_DIFFERENT); | ||
| 2297 | case_WLAN(INVALID_GROUP_CIPHER); | ||
| 2298 | case_WLAN(INVALID_PAIRWISE_CIPHER); | ||
| 2299 | case_WLAN(INVALID_AKMP); | ||
| 2300 | case_WLAN(UNSUPP_RSN_VERSION); | ||
| 2301 | case_WLAN(INVALID_RSN_IE_CAP); | ||
| 2302 | case_WLAN(IEEE8021X_FAILED); | ||
| 2303 | case_WLAN(CIPHER_SUITE_REJECTED); | ||
| 2304 | case_WLAN(DISASSOC_UNSPECIFIED_QOS); | ||
| 2305 | case_WLAN(DISASSOC_QAP_NO_BANDWIDTH); | ||
| 2306 | case_WLAN(DISASSOC_LOW_ACK); | ||
| 2307 | case_WLAN(DISASSOC_QAP_EXCEED_TXOP); | ||
| 2308 | case_WLAN(QSTA_LEAVE_QBSS); | ||
| 2309 | case_WLAN(QSTA_NOT_USE); | ||
| 2310 | case_WLAN(QSTA_REQUIRE_SETUP); | ||
| 2311 | case_WLAN(QSTA_TIMEOUT); | ||
| 2312 | case_WLAN(QSTA_CIPHER_NOT_SUPP); | ||
| 2313 | case_WLAN(MESH_PEER_CANCELED); | ||
| 2314 | case_WLAN(MESH_MAX_PEERS); | ||
| 2315 | case_WLAN(MESH_CONFIG); | ||
| 2316 | case_WLAN(MESH_CLOSE); | ||
| 2317 | case_WLAN(MESH_MAX_RETRIES); | ||
| 2318 | case_WLAN(MESH_CONFIRM_TIMEOUT); | ||
| 2319 | case_WLAN(MESH_INVALID_GTK); | ||
| 2320 | case_WLAN(MESH_INCONSISTENT_PARAM); | ||
| 2321 | case_WLAN(MESH_INVALID_SECURITY); | ||
| 2322 | case_WLAN(MESH_PATH_ERROR); | ||
| 2323 | case_WLAN(MESH_PATH_NOFORWARD); | ||
| 2324 | case_WLAN(MESH_PATH_DEST_UNREACHABLE); | ||
| 2325 | case_WLAN(MAC_EXISTS_IN_MBSS); | ||
| 2326 | case_WLAN(MESH_CHAN_REGULATORY); | ||
| 2327 | case_WLAN(MESH_CHAN); | ||
| 2328 | default: return "<unknown>"; | ||
| 2329 | } | ||
| 2330 | } | ||
| 2236 | 2331 | ||
| 2237 | static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | 2332 | static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, |
| 2238 | struct ieee80211_mgmt *mgmt, size_t len) | 2333 | struct ieee80211_mgmt *mgmt, size_t len) |
| @@ -2254,8 +2349,8 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | |||
| 2254 | 2349 | ||
| 2255 | reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); | 2350 | reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); |
| 2256 | 2351 | ||
| 2257 | sdata_info(sdata, "deauthenticated from %pM (Reason: %u)\n", | 2352 | sdata_info(sdata, "deauthenticated from %pM (Reason: %u=%s)\n", |
| 2258 | bssid, reason_code); | 2353 | bssid, reason_code, ieee80211_get_reason_code_string(reason_code)); |
| 2259 | 2354 | ||
| 2260 | ieee80211_set_disassoc(sdata, 0, 0, false, NULL); | 2355 | ieee80211_set_disassoc(sdata, 0, 0, false, NULL); |
| 2261 | 2356 | ||
| @@ -2688,28 +2783,20 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
| 2688 | struct ieee802_11_elems *elems) | 2783 | struct ieee802_11_elems *elems) |
| 2689 | { | 2784 | { |
| 2690 | struct ieee80211_local *local = sdata->local; | 2785 | struct ieee80211_local *local = sdata->local; |
| 2691 | int freq; | ||
| 2692 | struct ieee80211_bss *bss; | 2786 | struct ieee80211_bss *bss; |
| 2693 | struct ieee80211_channel *channel; | 2787 | struct ieee80211_channel *channel; |
| 2694 | 2788 | ||
| 2695 | sdata_assert_lock(sdata); | 2789 | sdata_assert_lock(sdata); |
| 2696 | 2790 | ||
| 2697 | if (elems->ds_params) | 2791 | channel = ieee80211_get_channel(local->hw.wiphy, rx_status->freq); |
| 2698 | freq = ieee80211_channel_to_frequency(elems->ds_params[0], | 2792 | if (!channel) |
| 2699 | rx_status->band); | ||
| 2700 | else | ||
| 2701 | freq = rx_status->freq; | ||
| 2702 | |||
| 2703 | channel = ieee80211_get_channel(local->hw.wiphy, freq); | ||
| 2704 | |||
| 2705 | if (!channel || channel->flags & IEEE80211_CHAN_DISABLED) | ||
| 2706 | return; | 2793 | return; |
| 2707 | 2794 | ||
| 2708 | bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, | 2795 | bss = ieee80211_bss_info_update(local, rx_status, mgmt, len, elems, |
| 2709 | channel); | 2796 | channel); |
| 2710 | if (bss) { | 2797 | if (bss) { |
| 2711 | ieee80211_rx_bss_put(local, bss); | ||
| 2712 | sdata->vif.bss_conf.beacon_rate = bss->beacon_rate; | 2798 | sdata->vif.bss_conf.beacon_rate = bss->beacon_rate; |
| 2799 | ieee80211_rx_bss_put(local, bss); | ||
| 2713 | } | 2800 | } |
| 2714 | } | 2801 | } |
| 2715 | 2802 | ||
| @@ -3504,6 +3591,32 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) | |||
| 3504 | } | 3591 | } |
| 3505 | 3592 | ||
| 3506 | #ifdef CONFIG_PM | 3593 | #ifdef CONFIG_PM |
| 3594 | void ieee80211_mgd_quiesce(struct ieee80211_sub_if_data *sdata) | ||
| 3595 | { | ||
| 3596 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
| 3597 | u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; | ||
| 3598 | |||
| 3599 | sdata_lock(sdata); | ||
| 3600 | |||
| 3601 | if (ifmgd->auth_data) { | ||
| 3602 | /* | ||
| 3603 | * If we are trying to authenticate while suspending, cfg80211 | ||
| 3604 | * won't know and won't actually abort those attempts, thus we | ||
| 3605 | * need to do that ourselves. | ||
| 3606 | */ | ||
| 3607 | ieee80211_send_deauth_disassoc(sdata, | ||
| 3608 | ifmgd->auth_data->bss->bssid, | ||
| 3609 | IEEE80211_STYPE_DEAUTH, | ||
| 3610 | WLAN_REASON_DEAUTH_LEAVING, | ||
| 3611 | false, frame_buf); | ||
| 3612 | ieee80211_destroy_auth_data(sdata, false); | ||
| 3613 | cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, | ||
| 3614 | IEEE80211_DEAUTH_FRAME_LEN); | ||
| 3615 | } | ||
| 3616 | |||
| 3617 | sdata_unlock(sdata); | ||
| 3618 | } | ||
| 3619 | |||
| 3507 | void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) | 3620 | void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) |
| 3508 | { | 3621 | { |
| 3509 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 3622 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
| @@ -4322,37 +4435,41 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, | |||
| 4322 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | 4435 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; |
| 4323 | u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; | 4436 | u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; |
| 4324 | bool tx = !req->local_state_change; | 4437 | bool tx = !req->local_state_change; |
| 4325 | bool report_frame = false; | ||
| 4326 | 4438 | ||
| 4327 | sdata_info(sdata, | 4439 | if (ifmgd->auth_data && |
| 4328 | "deauthenticating from %pM by local choice (reason=%d)\n", | 4440 | ether_addr_equal(ifmgd->auth_data->bss->bssid, req->bssid)) { |
| 4329 | req->bssid, req->reason_code); | 4441 | sdata_info(sdata, |
| 4442 | "aborting authentication with %pM by local choice (Reason: %u=%s)\n", | ||
| 4443 | req->bssid, req->reason_code, | ||
| 4444 | ieee80211_get_reason_code_string(req->reason_code)); | ||
| 4330 | 4445 | ||
| 4331 | if (ifmgd->auth_data) { | ||
| 4332 | drv_mgd_prepare_tx(sdata->local, sdata); | 4446 | drv_mgd_prepare_tx(sdata->local, sdata); |
| 4333 | ieee80211_send_deauth_disassoc(sdata, req->bssid, | 4447 | ieee80211_send_deauth_disassoc(sdata, req->bssid, |
| 4334 | IEEE80211_STYPE_DEAUTH, | 4448 | IEEE80211_STYPE_DEAUTH, |
| 4335 | req->reason_code, tx, | 4449 | req->reason_code, tx, |
| 4336 | frame_buf); | 4450 | frame_buf); |
| 4337 | ieee80211_destroy_auth_data(sdata, false); | 4451 | ieee80211_destroy_auth_data(sdata, false); |
| 4452 | cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, | ||
| 4453 | IEEE80211_DEAUTH_FRAME_LEN); | ||
| 4338 | 4454 | ||
| 4339 | report_frame = true; | 4455 | return 0; |
| 4340 | goto out; | ||
| 4341 | } | 4456 | } |
| 4342 | 4457 | ||
| 4343 | if (ifmgd->associated && | 4458 | if (ifmgd->associated && |
| 4344 | ether_addr_equal(ifmgd->associated->bssid, req->bssid)) { | 4459 | ether_addr_equal(ifmgd->associated->bssid, req->bssid)) { |
| 4460 | sdata_info(sdata, | ||
| 4461 | "deauthenticating from %pM by local choice (Reason: %u=%s)\n", | ||
| 4462 | req->bssid, req->reason_code, | ||
| 4463 | ieee80211_get_reason_code_string(req->reason_code)); | ||
| 4464 | |||
| 4345 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, | 4465 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, |
| 4346 | req->reason_code, tx, frame_buf); | 4466 | req->reason_code, tx, frame_buf); |
| 4347 | report_frame = true; | ||
| 4348 | } | ||
| 4349 | |||
| 4350 | out: | ||
| 4351 | if (report_frame) | ||
| 4352 | cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, | 4467 | cfg80211_tx_mlme_mgmt(sdata->dev, frame_buf, |
| 4353 | IEEE80211_DEAUTH_FRAME_LEN); | 4468 | IEEE80211_DEAUTH_FRAME_LEN); |
| 4469 | return 0; | ||
| 4470 | } | ||
| 4354 | 4471 | ||
| 4355 | return 0; | 4472 | return -ENOTCONN; |
| 4356 | } | 4473 | } |
| 4357 | 4474 | ||
| 4358 | int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | 4475 | int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, |
| @@ -4372,8 +4489,8 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata, | |||
| 4372 | return -ENOLINK; | 4489 | return -ENOLINK; |
| 4373 | 4490 | ||
| 4374 | sdata_info(sdata, | 4491 | sdata_info(sdata, |
| 4375 | "disassociating from %pM by local choice (reason=%d)\n", | 4492 | "disassociating from %pM by local choice (Reason: %u=%s)\n", |
| 4376 | req->bss->bssid, req->reason_code); | 4493 | req->bss->bssid, req->reason_code, ieee80211_get_reason_code_string(req->reason_code)); |
| 4377 | 4494 | ||
| 4378 | memcpy(bssid, req->bss->bssid, ETH_ALEN); | 4495 | memcpy(bssid, req->bss->bssid, ETH_ALEN); |
| 4379 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DISASSOC, | 4496 | ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DISASSOC, |
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c index af64fb8e8add..d478b880a0af 100644 --- a/net/mac80211/pm.c +++ b/net/mac80211/pm.c | |||
| @@ -100,10 +100,18 @@ int __ieee80211_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) | |||
| 100 | 100 | ||
| 101 | /* remove all interfaces that were created in the driver */ | 101 | /* remove all interfaces that were created in the driver */ |
| 102 | list_for_each_entry(sdata, &local->interfaces, list) { | 102 | list_for_each_entry(sdata, &local->interfaces, list) { |
| 103 | if (!ieee80211_sdata_running(sdata) || | 103 | if (!ieee80211_sdata_running(sdata)) |
| 104 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN || | ||
| 105 | sdata->vif.type == NL80211_IFTYPE_MONITOR) | ||
| 106 | continue; | 104 | continue; |
| 105 | switch (sdata->vif.type) { | ||
| 106 | case NL80211_IFTYPE_AP_VLAN: | ||
| 107 | case NL80211_IFTYPE_MONITOR: | ||
| 108 | continue; | ||
| 109 | case NL80211_IFTYPE_STATION: | ||
| 110 | ieee80211_mgd_quiesce(sdata); | ||
| 111 | break; | ||
| 112 | default: | ||
| 113 | break; | ||
| 114 | } | ||
| 107 | 115 | ||
| 108 | drv_remove_interface(local, sdata); | 116 | drv_remove_interface(local, sdata); |
| 109 | } | 117 | } |
diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 22b223f13c9f..8fdadfd94ba8 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c | |||
| @@ -10,15 +10,15 @@ | |||
| 10 | 10 | ||
| 11 | #include <linux/kernel.h> | 11 | #include <linux/kernel.h> |
| 12 | #include <linux/rtnetlink.h> | 12 | #include <linux/rtnetlink.h> |
| 13 | #include <linux/slab.h> | ||
| 14 | #include <linux/module.h> | 13 | #include <linux/module.h> |
| 14 | #include <linux/slab.h> | ||
| 15 | #include "rate.h" | 15 | #include "rate.h" |
| 16 | #include "ieee80211_i.h" | 16 | #include "ieee80211_i.h" |
| 17 | #include "debugfs.h" | 17 | #include "debugfs.h" |
| 18 | 18 | ||
| 19 | struct rate_control_alg { | 19 | struct rate_control_alg { |
| 20 | struct list_head list; | 20 | struct list_head list; |
| 21 | struct rate_control_ops *ops; | 21 | const struct rate_control_ops *ops; |
| 22 | }; | 22 | }; |
| 23 | 23 | ||
| 24 | static LIST_HEAD(rate_ctrl_algs); | 24 | static LIST_HEAD(rate_ctrl_algs); |
| @@ -29,7 +29,7 @@ module_param(ieee80211_default_rc_algo, charp, 0644); | |||
| 29 | MODULE_PARM_DESC(ieee80211_default_rc_algo, | 29 | MODULE_PARM_DESC(ieee80211_default_rc_algo, |
| 30 | "Default rate control algorithm for mac80211 to use"); | 30 | "Default rate control algorithm for mac80211 to use"); |
| 31 | 31 | ||
| 32 | int ieee80211_rate_control_register(struct rate_control_ops *ops) | 32 | int ieee80211_rate_control_register(const struct rate_control_ops *ops) |
| 33 | { | 33 | { |
| 34 | struct rate_control_alg *alg; | 34 | struct rate_control_alg *alg; |
| 35 | 35 | ||
| @@ -60,7 +60,7 @@ int ieee80211_rate_control_register(struct rate_control_ops *ops) | |||
| 60 | } | 60 | } |
| 61 | EXPORT_SYMBOL(ieee80211_rate_control_register); | 61 | EXPORT_SYMBOL(ieee80211_rate_control_register); |
| 62 | 62 | ||
| 63 | void ieee80211_rate_control_unregister(struct rate_control_ops *ops) | 63 | void ieee80211_rate_control_unregister(const struct rate_control_ops *ops) |
| 64 | { | 64 | { |
| 65 | struct rate_control_alg *alg; | 65 | struct rate_control_alg *alg; |
| 66 | 66 | ||
| @@ -76,32 +76,31 @@ void ieee80211_rate_control_unregister(struct rate_control_ops *ops) | |||
| 76 | } | 76 | } |
| 77 | EXPORT_SYMBOL(ieee80211_rate_control_unregister); | 77 | EXPORT_SYMBOL(ieee80211_rate_control_unregister); |
| 78 | 78 | ||
| 79 | static struct rate_control_ops * | 79 | static const struct rate_control_ops * |
| 80 | ieee80211_try_rate_control_ops_get(const char *name) | 80 | ieee80211_try_rate_control_ops_get(const char *name) |
| 81 | { | 81 | { |
| 82 | struct rate_control_alg *alg; | 82 | struct rate_control_alg *alg; |
| 83 | struct rate_control_ops *ops = NULL; | 83 | const struct rate_control_ops *ops = NULL; |
| 84 | 84 | ||
| 85 | if (!name) | 85 | if (!name) |
| 86 | return NULL; | 86 | return NULL; |
| 87 | 87 | ||
| 88 | mutex_lock(&rate_ctrl_mutex); | 88 | mutex_lock(&rate_ctrl_mutex); |
| 89 | list_for_each_entry(alg, &rate_ctrl_algs, list) { | 89 | list_for_each_entry(alg, &rate_ctrl_algs, list) { |
| 90 | if (!strcmp(alg->ops->name, name)) | 90 | if (!strcmp(alg->ops->name, name)) { |
| 91 | if (try_module_get(alg->ops->module)) { | 91 | ops = alg->ops; |
| 92 | ops = alg->ops; | 92 | break; |
| 93 | break; | 93 | } |
| 94 | } | ||
| 95 | } | 94 | } |
| 96 | mutex_unlock(&rate_ctrl_mutex); | 95 | mutex_unlock(&rate_ctrl_mutex); |
| 97 | return ops; | 96 | return ops; |
| 98 | } | 97 | } |
| 99 | 98 | ||
| 100 | /* Get the rate control algorithm. */ | 99 | /* Get the rate control algorithm. */ |
| 101 | static struct rate_control_ops * | 100 | static const struct rate_control_ops * |
| 102 | ieee80211_rate_control_ops_get(const char *name) | 101 | ieee80211_rate_control_ops_get(const char *name) |
| 103 | { | 102 | { |
| 104 | struct rate_control_ops *ops; | 103 | const struct rate_control_ops *ops; |
| 105 | const char *alg_name; | 104 | const char *alg_name; |
| 106 | 105 | ||
| 107 | kparam_block_sysfs_write(ieee80211_default_rc_algo); | 106 | kparam_block_sysfs_write(ieee80211_default_rc_algo); |
| @@ -111,10 +110,6 @@ ieee80211_rate_control_ops_get(const char *name) | |||
| 111 | alg_name = name; | 110 | alg_name = name; |
| 112 | 111 | ||
| 113 | ops = ieee80211_try_rate_control_ops_get(alg_name); | 112 | ops = ieee80211_try_rate_control_ops_get(alg_name); |
| 114 | if (!ops) { | ||
| 115 | request_module("rc80211_%s", alg_name); | ||
| 116 | ops = ieee80211_try_rate_control_ops_get(alg_name); | ||
| 117 | } | ||
| 118 | if (!ops && name) | 113 | if (!ops && name) |
| 119 | /* try default if specific alg requested but not found */ | 114 | /* try default if specific alg requested but not found */ |
| 120 | ops = ieee80211_try_rate_control_ops_get(ieee80211_default_rc_algo); | 115 | ops = ieee80211_try_rate_control_ops_get(ieee80211_default_rc_algo); |
| @@ -127,11 +122,6 @@ ieee80211_rate_control_ops_get(const char *name) | |||
| 127 | return ops; | 122 | return ops; |
| 128 | } | 123 | } |
| 129 | 124 | ||
| 130 | static void ieee80211_rate_control_ops_put(struct rate_control_ops *ops) | ||
| 131 | { | ||
| 132 | module_put(ops->module); | ||
| 133 | } | ||
| 134 | |||
| 135 | #ifdef CONFIG_MAC80211_DEBUGFS | 125 | #ifdef CONFIG_MAC80211_DEBUGFS |
| 136 | static ssize_t rcname_read(struct file *file, char __user *userbuf, | 126 | static ssize_t rcname_read(struct file *file, char __user *userbuf, |
| 137 | size_t count, loff_t *ppos) | 127 | size_t count, loff_t *ppos) |
| @@ -158,11 +148,11 @@ static struct rate_control_ref *rate_control_alloc(const char *name, | |||
| 158 | 148 | ||
| 159 | ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL); | 149 | ref = kmalloc(sizeof(struct rate_control_ref), GFP_KERNEL); |
| 160 | if (!ref) | 150 | if (!ref) |
| 161 | goto fail_ref; | 151 | return NULL; |
| 162 | ref->local = local; | 152 | ref->local = local; |
| 163 | ref->ops = ieee80211_rate_control_ops_get(name); | 153 | ref->ops = ieee80211_rate_control_ops_get(name); |
| 164 | if (!ref->ops) | 154 | if (!ref->ops) |
| 165 | goto fail_ops; | 155 | goto free; |
| 166 | 156 | ||
| 167 | #ifdef CONFIG_MAC80211_DEBUGFS | 157 | #ifdef CONFIG_MAC80211_DEBUGFS |
| 168 | debugfsdir = debugfs_create_dir("rc", local->hw.wiphy->debugfsdir); | 158 | debugfsdir = debugfs_create_dir("rc", local->hw.wiphy->debugfsdir); |
| @@ -172,14 +162,11 @@ static struct rate_control_ref *rate_control_alloc(const char *name, | |||
| 172 | 162 | ||
| 173 | ref->priv = ref->ops->alloc(&local->hw, debugfsdir); | 163 | ref->priv = ref->ops->alloc(&local->hw, debugfsdir); |
| 174 | if (!ref->priv) | 164 | if (!ref->priv) |
| 175 | goto fail_priv; | 165 | goto free; |
| 176 | return ref; | 166 | return ref; |
| 177 | 167 | ||
| 178 | fail_priv: | 168 | free: |
| 179 | ieee80211_rate_control_ops_put(ref->ops); | ||
| 180 | fail_ops: | ||
| 181 | kfree(ref); | 169 | kfree(ref); |
| 182 | fail_ref: | ||
| 183 | return NULL; | 170 | return NULL; |
| 184 | } | 171 | } |
| 185 | 172 | ||
| @@ -192,7 +179,6 @@ static void rate_control_free(struct rate_control_ref *ctrl_ref) | |||
| 192 | ctrl_ref->local->debugfs.rcdir = NULL; | 179 | ctrl_ref->local->debugfs.rcdir = NULL; |
| 193 | #endif | 180 | #endif |
| 194 | 181 | ||
| 195 | ieee80211_rate_control_ops_put(ctrl_ref->ops); | ||
| 196 | kfree(ctrl_ref); | 182 | kfree(ctrl_ref); |
| 197 | } | 183 | } |
| 198 | 184 | ||
diff --git a/net/mac80211/rate.h b/net/mac80211/rate.h index b95e16c07081..9aa2a1190a86 100644 --- a/net/mac80211/rate.h +++ b/net/mac80211/rate.h | |||
| @@ -21,7 +21,7 @@ | |||
| 21 | 21 | ||
| 22 | struct rate_control_ref { | 22 | struct rate_control_ref { |
| 23 | struct ieee80211_local *local; | 23 | struct ieee80211_local *local; |
| 24 | struct rate_control_ops *ops; | 24 | const struct rate_control_ops *ops; |
| 25 | void *priv; | 25 | void *priv; |
| 26 | }; | 26 | }; |
| 27 | 27 | ||
diff --git a/net/mac80211/rc80211_minstrel.c b/net/mac80211/rc80211_minstrel.c index f3d88b0c054c..26fd94fa0aed 100644 --- a/net/mac80211/rc80211_minstrel.c +++ b/net/mac80211/rc80211_minstrel.c | |||
| @@ -657,7 +657,7 @@ minstrel_free(void *priv) | |||
| 657 | kfree(priv); | 657 | kfree(priv); |
| 658 | } | 658 | } |
| 659 | 659 | ||
| 660 | struct rate_control_ops mac80211_minstrel = { | 660 | const struct rate_control_ops mac80211_minstrel = { |
| 661 | .name = "minstrel", | 661 | .name = "minstrel", |
| 662 | .tx_status = minstrel_tx_status, | 662 | .tx_status = minstrel_tx_status, |
| 663 | .get_rate = minstrel_get_rate, | 663 | .get_rate = minstrel_get_rate, |
diff --git a/net/mac80211/rc80211_minstrel.h b/net/mac80211/rc80211_minstrel.h index f4301f4b2e41..046d1bd598a8 100644 --- a/net/mac80211/rc80211_minstrel.h +++ b/net/mac80211/rc80211_minstrel.h | |||
| @@ -123,7 +123,7 @@ struct minstrel_debugfs_info { | |||
| 123 | char buf[]; | 123 | char buf[]; |
| 124 | }; | 124 | }; |
| 125 | 125 | ||
| 126 | extern struct rate_control_ops mac80211_minstrel; | 126 | extern const struct rate_control_ops mac80211_minstrel; |
| 127 | void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); | 127 | void minstrel_add_sta_debugfs(void *priv, void *priv_sta, struct dentry *dir); |
| 128 | void minstrel_remove_sta_debugfs(void *priv, void *priv_sta); | 128 | void minstrel_remove_sta_debugfs(void *priv, void *priv_sta); |
| 129 | 129 | ||
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c index c1b5b73c5b91..bccaf854a309 100644 --- a/net/mac80211/rc80211_minstrel_ht.c +++ b/net/mac80211/rc80211_minstrel_ht.c | |||
| @@ -124,7 +124,7 @@ const struct mcs_group minstrel_mcs_groups[] = { | |||
| 124 | 124 | ||
| 125 | #define MINSTREL_CCK_GROUP (ARRAY_SIZE(minstrel_mcs_groups) - 1) | 125 | #define MINSTREL_CCK_GROUP (ARRAY_SIZE(minstrel_mcs_groups) - 1) |
| 126 | 126 | ||
| 127 | static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES]; | 127 | static u8 sample_table[SAMPLE_COLUMNS][MCS_GROUP_RATES] __read_mostly; |
| 128 | 128 | ||
| 129 | static void | 129 | static void |
| 130 | minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi); | 130 | minstrel_ht_update_rates(struct minstrel_priv *mp, struct minstrel_ht_sta *mi); |
| @@ -1031,7 +1031,7 @@ minstrel_ht_free(void *priv) | |||
| 1031 | mac80211_minstrel.free(priv); | 1031 | mac80211_minstrel.free(priv); |
| 1032 | } | 1032 | } |
| 1033 | 1033 | ||
| 1034 | static struct rate_control_ops mac80211_minstrel_ht = { | 1034 | static const struct rate_control_ops mac80211_minstrel_ht = { |
| 1035 | .name = "minstrel_ht", | 1035 | .name = "minstrel_ht", |
| 1036 | .tx_status = minstrel_ht_tx_status, | 1036 | .tx_status = minstrel_ht_tx_status, |
| 1037 | .get_rate = minstrel_ht_get_rate, | 1037 | .get_rate = minstrel_ht_get_rate, |
| @@ -1048,8 +1048,7 @@ static struct rate_control_ops mac80211_minstrel_ht = { | |||
| 1048 | }; | 1048 | }; |
| 1049 | 1049 | ||
| 1050 | 1050 | ||
| 1051 | static void | 1051 | static void __init init_sample_table(void) |
| 1052 | init_sample_table(void) | ||
| 1053 | { | 1052 | { |
| 1054 | int col, i, new_idx; | 1053 | int col, i, new_idx; |
| 1055 | u8 rnd[MCS_GROUP_RATES]; | 1054 | u8 rnd[MCS_GROUP_RATES]; |
diff --git a/net/mac80211/rc80211_pid_algo.c b/net/mac80211/rc80211_pid_algo.c index 958fad07b54c..d0da2a70fe68 100644 --- a/net/mac80211/rc80211_pid_algo.c +++ b/net/mac80211/rc80211_pid_algo.c | |||
| @@ -452,7 +452,7 @@ static void rate_control_pid_free_sta(void *priv, struct ieee80211_sta *sta, | |||
| 452 | kfree(priv_sta); | 452 | kfree(priv_sta); |
| 453 | } | 453 | } |
| 454 | 454 | ||
| 455 | static struct rate_control_ops mac80211_rcpid = { | 455 | static const struct rate_control_ops mac80211_rcpid = { |
| 456 | .name = "pid", | 456 | .name = "pid", |
| 457 | .tx_status = rate_control_pid_tx_status, | 457 | .tx_status = rate_control_pid_tx_status, |
| 458 | .get_rate = rate_control_pid_get_rate, | 458 | .get_rate = rate_control_pid_get_rate, |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 3e57f96c9666..216c45b949e5 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
| @@ -40,8 +40,6 @@ | |||
| 40 | static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, | 40 | static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, |
| 41 | struct sk_buff *skb) | 41 | struct sk_buff *skb) |
| 42 | { | 42 | { |
| 43 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | ||
| 44 | |||
| 45 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) { | 43 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) { |
| 46 | if (likely(skb->len > FCS_LEN)) | 44 | if (likely(skb->len > FCS_LEN)) |
| 47 | __pskb_trim(skb, skb->len - FCS_LEN); | 45 | __pskb_trim(skb, skb->len - FCS_LEN); |
| @@ -53,9 +51,6 @@ static struct sk_buff *remove_monitor_info(struct ieee80211_local *local, | |||
| 53 | } | 51 | } |
| 54 | } | 52 | } |
| 55 | 53 | ||
| 56 | if (status->vendor_radiotap_len) | ||
| 57 | __pskb_pull(skb, status->vendor_radiotap_len); | ||
| 58 | |||
| 59 | return skb; | 54 | return skb; |
| 60 | } | 55 | } |
| 61 | 56 | ||
| @@ -64,14 +59,13 @@ static inline int should_drop_frame(struct sk_buff *skb, int present_fcs_len) | |||
| 64 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 59 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
| 65 | struct ieee80211_hdr *hdr; | 60 | struct ieee80211_hdr *hdr; |
| 66 | 61 | ||
| 67 | hdr = (void *)(skb->data + status->vendor_radiotap_len); | 62 | hdr = (void *)(skb->data); |
| 68 | 63 | ||
| 69 | if (status->flag & (RX_FLAG_FAILED_FCS_CRC | | 64 | if (status->flag & (RX_FLAG_FAILED_FCS_CRC | |
| 70 | RX_FLAG_FAILED_PLCP_CRC | | 65 | RX_FLAG_FAILED_PLCP_CRC | |
| 71 | RX_FLAG_AMPDU_IS_ZEROLEN)) | 66 | RX_FLAG_AMPDU_IS_ZEROLEN)) |
| 72 | return 1; | 67 | return 1; |
| 73 | if (unlikely(skb->len < 16 + present_fcs_len + | 68 | if (unlikely(skb->len < 16 + present_fcs_len)) |
| 74 | status->vendor_radiotap_len)) | ||
| 75 | return 1; | 69 | return 1; |
| 76 | if (ieee80211_is_ctl(hdr->frame_control) && | 70 | if (ieee80211_is_ctl(hdr->frame_control) && |
| 77 | !ieee80211_is_pspoll(hdr->frame_control) && | 71 | !ieee80211_is_pspoll(hdr->frame_control) && |
| @@ -90,8 +84,6 @@ ieee80211_rx_radiotap_space(struct ieee80211_local *local, | |||
| 90 | len = sizeof(struct ieee80211_radiotap_header) + 8; | 84 | len = sizeof(struct ieee80211_radiotap_header) + 8; |
| 91 | 85 | ||
| 92 | /* allocate extra bitmaps */ | 86 | /* allocate extra bitmaps */ |
| 93 | if (status->vendor_radiotap_len) | ||
| 94 | len += 4; | ||
| 95 | if (status->chains) | 87 | if (status->chains) |
| 96 | len += 4 * hweight8(status->chains); | 88 | len += 4 * hweight8(status->chains); |
| 97 | 89 | ||
| @@ -127,18 +119,6 @@ ieee80211_rx_radiotap_space(struct ieee80211_local *local, | |||
| 127 | len += 2 * hweight8(status->chains); | 119 | len += 2 * hweight8(status->chains); |
| 128 | } | 120 | } |
| 129 | 121 | ||
| 130 | if (status->vendor_radiotap_len) { | ||
| 131 | if (WARN_ON_ONCE(status->vendor_radiotap_align == 0)) | ||
| 132 | status->vendor_radiotap_align = 1; | ||
| 133 | /* align standard part of vendor namespace */ | ||
| 134 | len = ALIGN(len, 2); | ||
| 135 | /* allocate standard part of vendor namespace */ | ||
| 136 | len += 6; | ||
| 137 | /* align vendor-defined part */ | ||
| 138 | len = ALIGN(len, status->vendor_radiotap_align); | ||
| 139 | /* vendor-defined part is already in skb */ | ||
| 140 | } | ||
| 141 | |||
| 142 | return len; | 122 | return len; |
| 143 | } | 123 | } |
| 144 | 124 | ||
| @@ -172,7 +152,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
| 172 | it_present = &rthdr->it_present; | 152 | it_present = &rthdr->it_present; |
| 173 | 153 | ||
| 174 | /* radiotap header, set always present flags */ | 154 | /* radiotap header, set always present flags */ |
| 175 | rthdr->it_len = cpu_to_le16(rtap_len + status->vendor_radiotap_len); | 155 | rthdr->it_len = cpu_to_le16(rtap_len); |
| 176 | it_present_val = BIT(IEEE80211_RADIOTAP_FLAGS) | | 156 | it_present_val = BIT(IEEE80211_RADIOTAP_FLAGS) | |
| 177 | BIT(IEEE80211_RADIOTAP_CHANNEL) | | 157 | BIT(IEEE80211_RADIOTAP_CHANNEL) | |
| 178 | BIT(IEEE80211_RADIOTAP_RX_FLAGS); | 158 | BIT(IEEE80211_RADIOTAP_RX_FLAGS); |
| @@ -190,14 +170,6 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
| 190 | BIT(IEEE80211_RADIOTAP_DBM_ANTSIGNAL); | 170 | BIT(IEEE80211_RADIOTAP_DBM_ANTSIGNAL); |
| 191 | } | 171 | } |
| 192 | 172 | ||
| 193 | if (status->vendor_radiotap_len) { | ||
| 194 | it_present_val |= BIT(IEEE80211_RADIOTAP_VENDOR_NAMESPACE) | | ||
| 195 | BIT(IEEE80211_RADIOTAP_EXT); | ||
| 196 | put_unaligned_le32(it_present_val, it_present); | ||
| 197 | it_present++; | ||
| 198 | it_present_val = status->vendor_radiotap_bitmap; | ||
| 199 | } | ||
| 200 | |||
| 201 | put_unaligned_le32(it_present_val, it_present); | 173 | put_unaligned_le32(it_present_val, it_present); |
| 202 | 174 | ||
| 203 | pos = (void *)(it_present + 1); | 175 | pos = (void *)(it_present + 1); |
| @@ -307,6 +279,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
| 307 | *pos |= IEEE80211_RADIOTAP_MCS_BW_40; | 279 | *pos |= IEEE80211_RADIOTAP_MCS_BW_40; |
| 308 | if (status->flag & RX_FLAG_HT_GF) | 280 | if (status->flag & RX_FLAG_HT_GF) |
| 309 | *pos |= IEEE80211_RADIOTAP_MCS_FMT_GF; | 281 | *pos |= IEEE80211_RADIOTAP_MCS_FMT_GF; |
| 282 | if (status->flag & RX_FLAG_LDPC) | ||
| 283 | *pos |= IEEE80211_RADIOTAP_MCS_FEC_LDPC; | ||
| 310 | stbc = (status->flag & RX_FLAG_STBC_MASK) >> RX_FLAG_STBC_SHIFT; | 284 | stbc = (status->flag & RX_FLAG_STBC_MASK) >> RX_FLAG_STBC_SHIFT; |
| 311 | *pos |= stbc << IEEE80211_RADIOTAP_MCS_STBC_SHIFT; | 285 | *pos |= stbc << IEEE80211_RADIOTAP_MCS_STBC_SHIFT; |
| 312 | pos++; | 286 | pos++; |
| @@ -349,20 +323,25 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
| 349 | 323 | ||
| 350 | rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT); | 324 | rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_VHT); |
| 351 | /* known field - how to handle 80+80? */ | 325 | /* known field - how to handle 80+80? */ |
| 352 | if (status->flag & RX_FLAG_80P80MHZ) | 326 | if (status->vht_flag & RX_VHT_FLAG_80P80MHZ) |
| 353 | known &= ~IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; | 327 | known &= ~IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH; |
| 354 | put_unaligned_le16(known, pos); | 328 | put_unaligned_le16(known, pos); |
| 355 | pos += 2; | 329 | pos += 2; |
| 356 | /* flags */ | 330 | /* flags */ |
| 357 | if (status->flag & RX_FLAG_SHORT_GI) | 331 | if (status->flag & RX_FLAG_SHORT_GI) |
| 358 | *pos |= IEEE80211_RADIOTAP_VHT_FLAG_SGI; | 332 | *pos |= IEEE80211_RADIOTAP_VHT_FLAG_SGI; |
| 333 | /* in VHT, STBC is binary */ | ||
| 334 | if (status->flag & RX_FLAG_STBC_MASK) | ||
| 335 | *pos |= IEEE80211_RADIOTAP_VHT_FLAG_STBC; | ||
| 336 | if (status->vht_flag & RX_VHT_FLAG_BF) | ||
| 337 | *pos |= IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED; | ||
| 359 | pos++; | 338 | pos++; |
| 360 | /* bandwidth */ | 339 | /* bandwidth */ |
| 361 | if (status->flag & RX_FLAG_80MHZ) | 340 | if (status->vht_flag & RX_VHT_FLAG_80MHZ) |
| 362 | *pos++ = 4; | 341 | *pos++ = 4; |
| 363 | else if (status->flag & RX_FLAG_80P80MHZ) | 342 | else if (status->vht_flag & RX_VHT_FLAG_80P80MHZ) |
| 364 | *pos++ = 0; /* marked not known above */ | 343 | *pos++ = 0; /* marked not known above */ |
| 365 | else if (status->flag & RX_FLAG_160MHZ) | 344 | else if (status->vht_flag & RX_VHT_FLAG_160MHZ) |
| 366 | *pos++ = 11; | 345 | *pos++ = 11; |
| 367 | else if (status->flag & RX_FLAG_40MHZ) | 346 | else if (status->flag & RX_FLAG_40MHZ) |
| 368 | *pos++ = 1; | 347 | *pos++ = 1; |
| @@ -372,6 +351,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
| 372 | *pos = (status->rate_idx << 4) | status->vht_nss; | 351 | *pos = (status->rate_idx << 4) | status->vht_nss; |
| 373 | pos += 4; | 352 | pos += 4; |
| 374 | /* coding field */ | 353 | /* coding field */ |
| 354 | if (status->flag & RX_FLAG_LDPC) | ||
| 355 | *pos |= IEEE80211_RADIOTAP_CODING_LDPC_USER0; | ||
| 375 | pos++; | 356 | pos++; |
| 376 | /* group ID */ | 357 | /* group ID */ |
| 377 | pos++; | 358 | pos++; |
| @@ -383,21 +364,6 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
| 383 | *pos++ = status->chain_signal[chain]; | 364 | *pos++ = status->chain_signal[chain]; |
| 384 | *pos++ = chain; | 365 | *pos++ = chain; |
| 385 | } | 366 | } |
| 386 | |||
| 387 | if (status->vendor_radiotap_len) { | ||
| 388 | /* ensure 2 byte alignment for the vendor field as required */ | ||
| 389 | if ((pos - (u8 *)rthdr) & 1) | ||
| 390 | *pos++ = 0; | ||
| 391 | *pos++ = status->vendor_radiotap_oui[0]; | ||
| 392 | *pos++ = status->vendor_radiotap_oui[1]; | ||
| 393 | *pos++ = status->vendor_radiotap_oui[2]; | ||
| 394 | *pos++ = status->vendor_radiotap_subns; | ||
| 395 | put_unaligned_le16(status->vendor_radiotap_len, pos); | ||
| 396 | pos += 2; | ||
| 397 | /* align the actual payload as requested */ | ||
| 398 | while ((pos - (u8 *)rthdr) & (status->vendor_radiotap_align - 1)) | ||
| 399 | *pos++ = 0; | ||
| 400 | } | ||
| 401 | } | 367 | } |
| 402 | 368 | ||
| 403 | /* | 369 | /* |
| @@ -428,8 +394,8 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb, | |||
| 428 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) | 394 | if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) |
| 429 | present_fcs_len = FCS_LEN; | 395 | present_fcs_len = FCS_LEN; |
| 430 | 396 | ||
| 431 | /* ensure hdr->frame_control and vendor radiotap data are in skb head */ | 397 | /* ensure hdr->frame_control is in skb head */ |
| 432 | if (!pskb_may_pull(origskb, 2 + status->vendor_radiotap_len)) { | 398 | if (!pskb_may_pull(origskb, 2)) { |
| 433 | dev_kfree_skb(origskb); | 399 | dev_kfree_skb(origskb); |
| 434 | return NULL; | 400 | return NULL; |
| 435 | } | 401 | } |
| @@ -599,10 +565,10 @@ static int ieee80211_is_unicast_robust_mgmt_frame(struct sk_buff *skb) | |||
| 599 | { | 565 | { |
| 600 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 566 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
| 601 | 567 | ||
| 602 | if (skb->len < 24 || is_multicast_ether_addr(hdr->addr1)) | 568 | if (is_multicast_ether_addr(hdr->addr1)) |
| 603 | return 0; | 569 | return 0; |
| 604 | 570 | ||
| 605 | return ieee80211_is_robust_mgmt_frame(hdr); | 571 | return ieee80211_is_robust_mgmt_frame(skb); |
| 606 | } | 572 | } |
| 607 | 573 | ||
| 608 | 574 | ||
| @@ -610,10 +576,10 @@ static int ieee80211_is_multicast_robust_mgmt_frame(struct sk_buff *skb) | |||
| 610 | { | 576 | { |
| 611 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | 577 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
| 612 | 578 | ||
| 613 | if (skb->len < 24 || !is_multicast_ether_addr(hdr->addr1)) | 579 | if (!is_multicast_ether_addr(hdr->addr1)) |
| 614 | return 0; | 580 | return 0; |
| 615 | 581 | ||
| 616 | return ieee80211_is_robust_mgmt_frame(hdr); | 582 | return ieee80211_is_robust_mgmt_frame(skb); |
| 617 | } | 583 | } |
| 618 | 584 | ||
| 619 | 585 | ||
| @@ -626,7 +592,7 @@ static int ieee80211_get_mmie_keyidx(struct sk_buff *skb) | |||
| 626 | if (skb->len < 24 + sizeof(*mmie) || !is_multicast_ether_addr(hdr->da)) | 592 | if (skb->len < 24 + sizeof(*mmie) || !is_multicast_ether_addr(hdr->da)) |
| 627 | return -1; | 593 | return -1; |
| 628 | 594 | ||
| 629 | if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) hdr)) | 595 | if (!ieee80211_is_robust_mgmt_frame(skb)) |
| 630 | return -1; /* not a robust management frame */ | 596 | return -1; /* not a robust management frame */ |
| 631 | 597 | ||
| 632 | mmie = (struct ieee80211_mmie *) | 598 | mmie = (struct ieee80211_mmie *) |
| @@ -1268,6 +1234,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
| 1268 | if (ieee80211_is_data(hdr->frame_control)) { | 1234 | if (ieee80211_is_data(hdr->frame_control)) { |
| 1269 | sta->last_rx_rate_idx = status->rate_idx; | 1235 | sta->last_rx_rate_idx = status->rate_idx; |
| 1270 | sta->last_rx_rate_flag = status->flag; | 1236 | sta->last_rx_rate_flag = status->flag; |
| 1237 | sta->last_rx_rate_vht_flag = status->vht_flag; | ||
| 1271 | sta->last_rx_rate_vht_nss = status->vht_nss; | 1238 | sta->last_rx_rate_vht_nss = status->vht_nss; |
| 1272 | } | 1239 | } |
| 1273 | } | 1240 | } |
| @@ -1280,6 +1247,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
| 1280 | if (ieee80211_is_data(hdr->frame_control)) { | 1247 | if (ieee80211_is_data(hdr->frame_control)) { |
| 1281 | sta->last_rx_rate_idx = status->rate_idx; | 1248 | sta->last_rx_rate_idx = status->rate_idx; |
| 1282 | sta->last_rx_rate_flag = status->flag; | 1249 | sta->last_rx_rate_flag = status->flag; |
| 1250 | sta->last_rx_rate_vht_flag = status->vht_flag; | ||
| 1283 | sta->last_rx_rate_vht_nss = status->vht_nss; | 1251 | sta->last_rx_rate_vht_nss = status->vht_nss; |
| 1284 | } | 1252 | } |
| 1285 | } | 1253 | } |
| @@ -1318,18 +1286,15 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx) | |||
| 1318 | !ieee80211_has_morefrags(hdr->frame_control) && | 1286 | !ieee80211_has_morefrags(hdr->frame_control) && |
| 1319 | !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) && | 1287 | !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) && |
| 1320 | (rx->sdata->vif.type == NL80211_IFTYPE_AP || | 1288 | (rx->sdata->vif.type == NL80211_IFTYPE_AP || |
| 1321 | rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) { | 1289 | rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN) && |
| 1290 | /* PM bit is only checked in frames where it isn't reserved, | ||
| 1291 | * in AP mode it's reserved in non-bufferable management frames | ||
| 1292 | * (cf. IEEE 802.11-2012 8.2.4.1.7 Power Management field) | ||
| 1293 | */ | ||
| 1294 | (!ieee80211_is_mgmt(hdr->frame_control) || | ||
| 1295 | ieee80211_is_bufferable_mmpdu(hdr->frame_control))) { | ||
| 1322 | if (test_sta_flag(sta, WLAN_STA_PS_STA)) { | 1296 | if (test_sta_flag(sta, WLAN_STA_PS_STA)) { |
| 1323 | /* | 1297 | if (!ieee80211_has_pm(hdr->frame_control)) |
| 1324 | * Ignore doze->wake transitions that are | ||
| 1325 | * indicated by non-data frames, the standard | ||
| 1326 | * is unclear here, but for example going to | ||
| 1327 | * PS mode and then scanning would cause a | ||
| 1328 | * doze->wake transition for the probe request, | ||
| 1329 | * and that is clearly undesirable. | ||
| 1330 | */ | ||
| 1331 | if (ieee80211_is_data(hdr->frame_control) && | ||
| 1332 | !ieee80211_has_pm(hdr->frame_control)) | ||
| 1333 | sta_ps_end(sta); | 1298 | sta_ps_end(sta); |
| 1334 | } else { | 1299 | } else { |
| 1335 | if (ieee80211_has_pm(hdr->frame_control)) | 1300 | if (ieee80211_has_pm(hdr->frame_control)) |
| @@ -1852,8 +1817,7 @@ static int ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx) | |||
| 1852 | * having configured keys. | 1817 | * having configured keys. |
| 1853 | */ | 1818 | */ |
| 1854 | if (unlikely(ieee80211_is_action(fc) && !rx->key && | 1819 | if (unlikely(ieee80211_is_action(fc) && !rx->key && |
| 1855 | ieee80211_is_robust_mgmt_frame( | 1820 | ieee80211_is_robust_mgmt_frame(rx->skb))) |
| 1856 | (struct ieee80211_hdr *) rx->skb->data))) | ||
| 1857 | return -EACCES; | 1821 | return -EACCES; |
| 1858 | } | 1822 | } |
| 1859 | 1823 | ||
| @@ -2000,7 +1964,10 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx) | |||
| 2000 | /* deliver to local stack */ | 1964 | /* deliver to local stack */ |
| 2001 | skb->protocol = eth_type_trans(skb, dev); | 1965 | skb->protocol = eth_type_trans(skb, dev); |
| 2002 | memset(skb->cb, 0, sizeof(skb->cb)); | 1966 | memset(skb->cb, 0, sizeof(skb->cb)); |
| 2003 | netif_receive_skb(skb); | 1967 | if (rx->local->napi) |
| 1968 | napi_gro_receive(rx->local->napi, skb); | ||
| 1969 | else | ||
| 1970 | netif_receive_skb(skb); | ||
| 2004 | } | 1971 | } |
| 2005 | 1972 | ||
| 2006 | if (xmit_skb) { | 1973 | if (xmit_skb) { |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 88c81616f8f7..3ce7f2c8539a 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
| @@ -472,9 +472,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
| 472 | if (local->ops->hw_scan) { | 472 | if (local->ops->hw_scan) { |
| 473 | u8 *ies; | 473 | u8 *ies; |
| 474 | 474 | ||
| 475 | local->hw_scan_ies_bufsize = 2 + IEEE80211_MAX_SSID_LEN + | 475 | local->hw_scan_ies_bufsize = local->scan_ies_len + req->ie_len; |
| 476 | local->scan_ies_len + | ||
| 477 | req->ie_len; | ||
| 478 | local->hw_scan_req = kmalloc( | 476 | local->hw_scan_req = kmalloc( |
| 479 | sizeof(*local->hw_scan_req) + | 477 | sizeof(*local->hw_scan_req) + |
| 480 | req->n_channels * sizeof(req->channels[0]) + | 478 | req->n_channels * sizeof(req->channels[0]) + |
| @@ -979,8 +977,7 @@ int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata, | |||
| 979 | struct cfg80211_chan_def chandef; | 977 | struct cfg80211_chan_def chandef; |
| 980 | int ret, i, iebufsz; | 978 | int ret, i, iebufsz; |
| 981 | 979 | ||
| 982 | iebufsz = 2 + IEEE80211_MAX_SSID_LEN + | 980 | iebufsz = local->scan_ies_len + req->ie_len; |
| 983 | local->scan_ies_len + req->ie_len; | ||
| 984 | 981 | ||
| 985 | lockdep_assert_held(&local->mtx); | 982 | lockdep_assert_held(&local->mtx); |
| 986 | 983 | ||
| @@ -1058,9 +1055,11 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata) | |||
| 1058 | /* We don't want to restart sched scan anymore. */ | 1055 | /* We don't want to restart sched scan anymore. */ |
| 1059 | local->sched_scan_req = NULL; | 1056 | local->sched_scan_req = NULL; |
| 1060 | 1057 | ||
| 1061 | if (rcu_access_pointer(local->sched_scan_sdata)) | 1058 | if (rcu_access_pointer(local->sched_scan_sdata)) { |
| 1062 | drv_sched_scan_stop(local, sdata); | 1059 | ret = drv_sched_scan_stop(local, sdata); |
| 1063 | 1060 | if (!ret) | |
| 1061 | rcu_assign_pointer(local->sched_scan_sdata, NULL); | ||
| 1062 | } | ||
| 1064 | out: | 1063 | out: |
| 1065 | mutex_unlock(&local->mtx); | 1064 | mutex_unlock(&local->mtx); |
| 1066 | 1065 | ||
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h index d3a6d8208f2f..4acc5fc402fa 100644 --- a/net/mac80211/sta_info.h +++ b/net/mac80211/sta_info.h | |||
| @@ -261,6 +261,7 @@ struct ieee80211_tx_latency_stat { | |||
| 261 | * "the" transmit rate | 261 | * "the" transmit rate |
| 262 | * @last_rx_rate_idx: rx status rate index of the last data packet | 262 | * @last_rx_rate_idx: rx status rate index of the last data packet |
| 263 | * @last_rx_rate_flag: rx status flag of the last data packet | 263 | * @last_rx_rate_flag: rx status flag of the last data packet |
| 264 | * @last_rx_rate_vht_flag: rx status vht flag of the last data packet | ||
| 264 | * @last_rx_rate_vht_nss: rx status nss of last data packet | 265 | * @last_rx_rate_vht_nss: rx status nss of last data packet |
| 265 | * @lock: used for locking all fields that require locking, see comments | 266 | * @lock: used for locking all fields that require locking, see comments |
| 266 | * in the header file. | 267 | * in the header file. |
| @@ -396,6 +397,7 @@ struct sta_info { | |||
| 396 | struct ieee80211_tx_rate last_tx_rate; | 397 | struct ieee80211_tx_rate last_tx_rate; |
| 397 | int last_rx_rate_idx; | 398 | int last_rx_rate_idx; |
| 398 | u32 last_rx_rate_flag; | 399 | u32 last_rx_rate_flag; |
| 400 | u32 last_rx_rate_vht_flag; | ||
| 399 | u8 last_rx_rate_vht_nss; | 401 | u8 last_rx_rate_vht_nss; |
| 400 | u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; | 402 | u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1]; |
| 401 | 403 | ||
diff --git a/net/mac80211/status.c b/net/mac80211/status.c index 1ee85c402439..e6e574a307c8 100644 --- a/net/mac80211/status.c +++ b/net/mac80211/status.c | |||
| @@ -479,7 +479,7 @@ static void ieee80211_tx_latency_end_msrmnt(struct ieee80211_local *local, | |||
| 479 | u32 msrmnt; | 479 | u32 msrmnt; |
| 480 | u16 tid; | 480 | u16 tid; |
| 481 | u8 *qc; | 481 | u8 *qc; |
| 482 | int i, bin_range_count, bin_count; | 482 | int i, bin_range_count; |
| 483 | u32 *bin_ranges; | 483 | u32 *bin_ranges; |
| 484 | __le16 fc; | 484 | __le16 fc; |
| 485 | struct ieee80211_tx_latency_stat *tx_lat; | 485 | struct ieee80211_tx_latency_stat *tx_lat; |
| @@ -522,7 +522,6 @@ static void ieee80211_tx_latency_end_msrmnt(struct ieee80211_local *local, | |||
| 522 | /* count how many Tx frames transmitted with the appropriate latency */ | 522 | /* count how many Tx frames transmitted with the appropriate latency */ |
| 523 | bin_range_count = tx_latency->n_ranges; | 523 | bin_range_count = tx_latency->n_ranges; |
| 524 | bin_ranges = tx_latency->ranges; | 524 | bin_ranges = tx_latency->ranges; |
| 525 | bin_count = tx_lat->bin_count; | ||
| 526 | 525 | ||
| 527 | for (i = 0; i < bin_range_count; i++) { | 526 | for (i = 0; i < bin_range_count; i++) { |
| 528 | if (msrmnt <= bin_ranges[i]) { | 527 | if (msrmnt <= bin_ranges[i]) { |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 4080c615636f..19d36d4117e0 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
| @@ -452,8 +452,7 @@ static int ieee80211_use_mfp(__le16 fc, struct sta_info *sta, | |||
| 452 | if (sta == NULL || !test_sta_flag(sta, WLAN_STA_MFP)) | 452 | if (sta == NULL || !test_sta_flag(sta, WLAN_STA_MFP)) |
| 453 | return 0; | 453 | return 0; |
| 454 | 454 | ||
| 455 | if (!ieee80211_is_robust_mgmt_frame((struct ieee80211_hdr *) | 455 | if (!ieee80211_is_robust_mgmt_frame(skb)) |
| 456 | skb->data)) | ||
| 457 | return 0; | 456 | return 0; |
| 458 | 457 | ||
| 459 | return 1; | 458 | return 1; |
| @@ -538,11 +537,8 @@ ieee80211_tx_h_ps_buf(struct ieee80211_tx_data *tx) | |||
| 538 | if (unlikely(tx->flags & IEEE80211_TX_PS_BUFFERED)) | 537 | if (unlikely(tx->flags & IEEE80211_TX_PS_BUFFERED)) |
| 539 | return TX_CONTINUE; | 538 | return TX_CONTINUE; |
| 540 | 539 | ||
| 541 | /* only deauth, disassoc and action are bufferable MMPDUs */ | ||
| 542 | if (ieee80211_is_mgmt(hdr->frame_control) && | 540 | if (ieee80211_is_mgmt(hdr->frame_control) && |
| 543 | !ieee80211_is_deauth(hdr->frame_control) && | 541 | !ieee80211_is_bufferable_mmpdu(hdr->frame_control)) { |
| 544 | !ieee80211_is_disassoc(hdr->frame_control) && | ||
| 545 | !ieee80211_is_action(hdr->frame_control)) { | ||
| 546 | if (tx->flags & IEEE80211_TX_UNICAST) | 542 | if (tx->flags & IEEE80211_TX_UNICAST) |
| 547 | info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER; | 543 | info->flags |= IEEE80211_TX_CTL_NO_PS_BUFFER; |
| 548 | return TX_CONTINUE; | 544 | return TX_CONTINUE; |
| @@ -582,7 +578,7 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
| 582 | tx->key = key; | 578 | tx->key = key; |
| 583 | else if (ieee80211_is_mgmt(hdr->frame_control) && | 579 | else if (ieee80211_is_mgmt(hdr->frame_control) && |
| 584 | is_multicast_ether_addr(hdr->addr1) && | 580 | is_multicast_ether_addr(hdr->addr1) && |
| 585 | ieee80211_is_robust_mgmt_frame(hdr) && | 581 | ieee80211_is_robust_mgmt_frame(tx->skb) && |
| 586 | (key = rcu_dereference(tx->sdata->default_mgmt_key))) | 582 | (key = rcu_dereference(tx->sdata->default_mgmt_key))) |
| 587 | tx->key = key; | 583 | tx->key = key; |
| 588 | else if (is_multicast_ether_addr(hdr->addr1) && | 584 | else if (is_multicast_ether_addr(hdr->addr1) && |
| @@ -597,12 +593,12 @@ ieee80211_tx_h_select_key(struct ieee80211_tx_data *tx) | |||
| 597 | tx->key = NULL; | 593 | tx->key = NULL; |
| 598 | else if (tx->skb->protocol == tx->sdata->control_port_protocol) | 594 | else if (tx->skb->protocol == tx->sdata->control_port_protocol) |
| 599 | tx->key = NULL; | 595 | tx->key = NULL; |
| 600 | else if (ieee80211_is_robust_mgmt_frame(hdr) && | 596 | else if (ieee80211_is_robust_mgmt_frame(tx->skb) && |
| 601 | !(ieee80211_is_action(hdr->frame_control) && | 597 | !(ieee80211_is_action(hdr->frame_control) && |
| 602 | tx->sta && test_sta_flag(tx->sta, WLAN_STA_MFP))) | 598 | tx->sta && test_sta_flag(tx->sta, WLAN_STA_MFP))) |
| 603 | tx->key = NULL; | 599 | tx->key = NULL; |
| 604 | else if (ieee80211_is_mgmt(hdr->frame_control) && | 600 | else if (ieee80211_is_mgmt(hdr->frame_control) && |
| 605 | !ieee80211_is_robust_mgmt_frame(hdr)) | 601 | !ieee80211_is_robust_mgmt_frame(tx->skb)) |
| 606 | tx->key = NULL; | 602 | tx->key = NULL; |
| 607 | else { | 603 | else { |
| 608 | I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted); | 604 | I802_DEBUG_INC(tx->local->tx_handlers_drop_unencrypted); |
| @@ -2417,15 +2413,6 @@ static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata, | |||
| 2417 | return 0; | 2413 | return 0; |
| 2418 | } | 2414 | } |
| 2419 | 2415 | ||
| 2420 | void ieee80211_csa_finish(struct ieee80211_vif *vif) | ||
| 2421 | { | ||
| 2422 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
| 2423 | |||
| 2424 | ieee80211_queue_work(&sdata->local->hw, | ||
| 2425 | &sdata->csa_finalize_work); | ||
| 2426 | } | ||
| 2427 | EXPORT_SYMBOL(ieee80211_csa_finish); | ||
| 2428 | |||
| 2429 | static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata, | 2416 | static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata, |
| 2430 | struct beacon_data *beacon) | 2417 | struct beacon_data *beacon) |
| 2431 | { | 2418 | { |
| @@ -2454,8 +2441,12 @@ static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata, | |||
| 2454 | if (WARN_ON(counter_offset_beacon >= beacon_data_len)) | 2441 | if (WARN_ON(counter_offset_beacon >= beacon_data_len)) |
| 2455 | return; | 2442 | return; |
| 2456 | 2443 | ||
| 2457 | /* warn if the driver did not check for/react to csa completeness */ | 2444 | /* Warn if the driver did not check for/react to csa |
| 2458 | if (WARN_ON(beacon_data[counter_offset_beacon] == 0)) | 2445 | * completeness. A beacon with CSA counter set to 0 should |
| 2446 | * never occur, because a counter of 1 means switch just | ||
| 2447 | * before the next beacon. | ||
| 2448 | */ | ||
| 2449 | if (WARN_ON(beacon_data[counter_offset_beacon] == 1)) | ||
| 2459 | return; | 2450 | return; |
| 2460 | 2451 | ||
| 2461 | beacon_data[counter_offset_beacon]--; | 2452 | beacon_data[counter_offset_beacon]--; |
| @@ -2521,7 +2512,7 @@ bool ieee80211_csa_is_complete(struct ieee80211_vif *vif) | |||
| 2521 | if (WARN_ON(counter_beacon > beacon_data_len)) | 2512 | if (WARN_ON(counter_beacon > beacon_data_len)) |
| 2522 | goto out; | 2513 | goto out; |
| 2523 | 2514 | ||
| 2524 | if (beacon_data[counter_beacon] == 0) | 2515 | if (beacon_data[counter_beacon] == 1) |
| 2525 | ret = true; | 2516 | ret = true; |
| 2526 | out: | 2517 | out: |
| 2527 | rcu_read_unlock(); | 2518 | rcu_read_unlock(); |
| @@ -2909,7 +2900,7 @@ ieee80211_get_buffered_bc(struct ieee80211_hw *hw, | |||
| 2909 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); | 2900 | cpu_to_le16(IEEE80211_FCTL_MOREDATA); |
| 2910 | } | 2901 | } |
| 2911 | 2902 | ||
| 2912 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | 2903 | if (sdata->vif.type == NL80211_IFTYPE_AP) |
| 2913 | sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev); | 2904 | sdata = IEEE80211_DEV_TO_SUB_IF(skb->dev); |
| 2914 | if (!ieee80211_tx_prepare(sdata, &tx, skb)) | 2905 | if (!ieee80211_tx_prepare(sdata, &tx, skb)) |
| 2915 | break; | 2906 | break; |
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index b8700d417a9c..275c94f995f7 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
| @@ -34,7 +34,7 @@ | |||
| 34 | #include "wep.h" | 34 | #include "wep.h" |
| 35 | 35 | ||
| 36 | /* privid for wiphys to determine whether they belong to us or not */ | 36 | /* privid for wiphys to determine whether they belong to us or not */ |
| 37 | void *mac80211_wiphy_privid = &mac80211_wiphy_privid; | 37 | const void *const mac80211_wiphy_privid = &mac80211_wiphy_privid; |
| 38 | 38 | ||
| 39 | struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy) | 39 | struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy) |
| 40 | { | 40 | { |
| @@ -1277,13 +1277,32 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
| 1277 | * that calculates local->scan_ies_len. | 1277 | * that calculates local->scan_ies_len. |
| 1278 | */ | 1278 | */ |
| 1279 | 1279 | ||
| 1280 | /* add any remaining custom IEs */ | 1280 | /* insert custom IEs that go before VHT */ |
| 1281 | if (ie && ie_len) { | 1281 | if (ie && ie_len) { |
| 1282 | noffset = ie_len; | 1282 | static const u8 before_vht[] = { |
| 1283 | WLAN_EID_SSID, | ||
| 1284 | WLAN_EID_SUPP_RATES, | ||
| 1285 | WLAN_EID_REQUEST, | ||
| 1286 | WLAN_EID_EXT_SUPP_RATES, | ||
| 1287 | WLAN_EID_DS_PARAMS, | ||
| 1288 | WLAN_EID_SUPPORTED_REGULATORY_CLASSES, | ||
| 1289 | WLAN_EID_HT_CAPABILITY, | ||
| 1290 | WLAN_EID_BSS_COEX_2040, | ||
| 1291 | WLAN_EID_EXT_CAPABILITY, | ||
| 1292 | WLAN_EID_SSID_LIST, | ||
| 1293 | WLAN_EID_CHANNEL_USAGE, | ||
| 1294 | WLAN_EID_INTERWORKING, | ||
| 1295 | /* mesh ID can't happen here */ | ||
| 1296 | /* 60 GHz can't happen here right now */ | ||
| 1297 | }; | ||
| 1298 | noffset = ieee80211_ie_split(ie, ie_len, | ||
| 1299 | before_vht, ARRAY_SIZE(before_vht), | ||
| 1300 | offset); | ||
| 1283 | if (end - pos < noffset - offset) | 1301 | if (end - pos < noffset - offset) |
| 1284 | goto out_err; | 1302 | goto out_err; |
| 1285 | memcpy(pos, ie + offset, noffset - offset); | 1303 | memcpy(pos, ie + offset, noffset - offset); |
| 1286 | pos += noffset - offset; | 1304 | pos += noffset - offset; |
| 1305 | offset = noffset; | ||
| 1287 | } | 1306 | } |
| 1288 | 1307 | ||
| 1289 | if (sband->vht_cap.vht_supported) { | 1308 | if (sband->vht_cap.vht_supported) { |
| @@ -1293,6 +1312,15 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, | |||
| 1293 | sband->vht_cap.cap); | 1312 | sband->vht_cap.cap); |
| 1294 | } | 1313 | } |
| 1295 | 1314 | ||
| 1315 | /* add any remaining custom IEs */ | ||
| 1316 | if (ie && ie_len) { | ||
| 1317 | noffset = ie_len; | ||
| 1318 | if (end - pos < noffset - offset) | ||
| 1319 | goto out_err; | ||
| 1320 | memcpy(pos, ie + offset, noffset - offset); | ||
| 1321 | pos += noffset - offset; | ||
| 1322 | } | ||
| 1323 | |||
| 1296 | return pos - buffer; | 1324 | return pos - buffer; |
| 1297 | out_err: | 1325 | out_err: |
| 1298 | WARN_ONCE(1, "not enough space for preq IEs\n"); | 1326 | WARN_ONCE(1, "not enough space for preq IEs\n"); |
| @@ -1370,7 +1398,6 @@ u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata, | |||
| 1370 | enum ieee80211_band band, u32 *basic_rates) | 1398 | enum ieee80211_band band, u32 *basic_rates) |
| 1371 | { | 1399 | { |
| 1372 | struct ieee80211_supported_band *sband; | 1400 | struct ieee80211_supported_band *sband; |
| 1373 | struct ieee80211_rate *bitrates; | ||
| 1374 | size_t num_rates; | 1401 | size_t num_rates; |
| 1375 | u32 supp_rates, rate_flags; | 1402 | u32 supp_rates, rate_flags; |
| 1376 | int i, j, shift; | 1403 | int i, j, shift; |
| @@ -1382,7 +1409,6 @@ u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata, | |||
| 1382 | if (WARN_ON(!sband)) | 1409 | if (WARN_ON(!sband)) |
| 1383 | return 1; | 1410 | return 1; |
| 1384 | 1411 | ||
| 1385 | bitrates = sband->bitrates; | ||
| 1386 | num_rates = sband->n_bitrates; | 1412 | num_rates = sband->n_bitrates; |
| 1387 | supp_rates = 0; | 1413 | supp_rates = 0; |
| 1388 | for (i = 0; i < elems->supp_rates_len + | 1414 | for (i = 0; i < elems->supp_rates_len + |
| @@ -2268,11 +2294,11 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local, | |||
| 2268 | ri.nss = status->vht_nss; | 2294 | ri.nss = status->vht_nss; |
| 2269 | if (status->flag & RX_FLAG_40MHZ) | 2295 | if (status->flag & RX_FLAG_40MHZ) |
| 2270 | ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | 2296 | ri.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; |
| 2271 | if (status->flag & RX_FLAG_80MHZ) | 2297 | if (status->vht_flag & RX_VHT_FLAG_80MHZ) |
| 2272 | ri.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; | 2298 | ri.flags |= RATE_INFO_FLAGS_80_MHZ_WIDTH; |
| 2273 | if (status->flag & RX_FLAG_80P80MHZ) | 2299 | if (status->vht_flag & RX_VHT_FLAG_80P80MHZ) |
| 2274 | ri.flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH; | 2300 | ri.flags |= RATE_INFO_FLAGS_80P80_MHZ_WIDTH; |
| 2275 | if (status->flag & RX_FLAG_160MHZ) | 2301 | if (status->vht_flag & RX_VHT_FLAG_160MHZ) |
| 2276 | ri.flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; | 2302 | ri.flags |= RATE_INFO_FLAGS_160_MHZ_WIDTH; |
| 2277 | if (status->flag & RX_FLAG_SHORT_GI) | 2303 | if (status->flag & RX_FLAG_SHORT_GI) |
| 2278 | ri.flags |= RATE_INFO_FLAGS_SHORT_GI; | 2304 | ri.flags |= RATE_INFO_FLAGS_SHORT_GI; |
diff --git a/net/mac80211/vht.c b/net/mac80211/vht.c index d75f35c6e1a0..e9e36a256165 100644 --- a/net/mac80211/vht.c +++ b/net/mac80211/vht.c | |||
| @@ -349,9 +349,9 @@ void ieee80211_sta_set_rx_nss(struct sta_info *sta) | |||
| 349 | sta->sta.rx_nss = max_t(u8, 1, ht_rx_nss); | 349 | sta->sta.rx_nss = max_t(u8, 1, ht_rx_nss); |
| 350 | } | 350 | } |
| 351 | 351 | ||
| 352 | void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | 352 | u32 __ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, |
| 353 | struct sta_info *sta, u8 opmode, | 353 | struct sta_info *sta, u8 opmode, |
| 354 | enum ieee80211_band band, bool nss_only) | 354 | enum ieee80211_band band, bool nss_only) |
| 355 | { | 355 | { |
| 356 | struct ieee80211_local *local = sdata->local; | 356 | struct ieee80211_local *local = sdata->local; |
| 357 | struct ieee80211_supported_band *sband; | 357 | struct ieee80211_supported_band *sband; |
| @@ -363,7 +363,7 @@ void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | |||
| 363 | 363 | ||
| 364 | /* ignore - no support for BF yet */ | 364 | /* ignore - no support for BF yet */ |
| 365 | if (opmode & IEEE80211_OPMODE_NOTIF_RX_NSS_TYPE_BF) | 365 | if (opmode & IEEE80211_OPMODE_NOTIF_RX_NSS_TYPE_BF) |
| 366 | return; | 366 | return 0; |
| 367 | 367 | ||
| 368 | nss = opmode & IEEE80211_OPMODE_NOTIF_RX_NSS_MASK; | 368 | nss = opmode & IEEE80211_OPMODE_NOTIF_RX_NSS_MASK; |
| 369 | nss >>= IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT; | 369 | nss >>= IEEE80211_OPMODE_NOTIF_RX_NSS_SHIFT; |
| @@ -375,7 +375,7 @@ void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | |||
| 375 | } | 375 | } |
| 376 | 376 | ||
| 377 | if (nss_only) | 377 | if (nss_only) |
| 378 | goto change; | 378 | return changed; |
| 379 | 379 | ||
| 380 | switch (opmode & IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK) { | 380 | switch (opmode & IEEE80211_OPMODE_NOTIF_CHANWIDTH_MASK) { |
| 381 | case IEEE80211_OPMODE_NOTIF_CHANWIDTH_20MHZ: | 381 | case IEEE80211_OPMODE_NOTIF_CHANWIDTH_20MHZ: |
| @@ -398,7 +398,19 @@ void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | |||
| 398 | changed |= IEEE80211_RC_BW_CHANGED; | 398 | changed |= IEEE80211_RC_BW_CHANGED; |
| 399 | } | 399 | } |
| 400 | 400 | ||
| 401 | change: | 401 | return changed; |
| 402 | if (changed) | 402 | } |
| 403 | |||
| 404 | void ieee80211_vht_handle_opmode(struct ieee80211_sub_if_data *sdata, | ||
| 405 | struct sta_info *sta, u8 opmode, | ||
| 406 | enum ieee80211_band band, bool nss_only) | ||
| 407 | { | ||
| 408 | struct ieee80211_local *local = sdata->local; | ||
| 409 | struct ieee80211_supported_band *sband = local->hw.wiphy->bands[band]; | ||
| 410 | |||
| 411 | u32 changed = __ieee80211_vht_handle_opmode(sdata, sta, opmode, | ||
| 412 | band, nss_only); | ||
| 413 | |||
| 414 | if (changed > 0) | ||
| 403 | rate_control_rate_update(local, sband, sta, changed); | 415 | rate_control_rate_update(local, sband, sta, changed); |
| 404 | } | 416 | } |
diff --git a/net/mac80211/wpa.c b/net/mac80211/wpa.c index 21448d629b15..b8600e3c29c8 100644 --- a/net/mac80211/wpa.c +++ b/net/mac80211/wpa.c | |||
| @@ -301,8 +301,7 @@ ieee80211_crypto_tkip_decrypt(struct ieee80211_rx_data *rx) | |||
| 301 | } | 301 | } |
| 302 | 302 | ||
| 303 | 303 | ||
| 304 | static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad, | 304 | static void ccmp_special_blocks(struct sk_buff *skb, u8 *pn, u8 *b_0, u8 *aad) |
| 305 | int encrypted) | ||
| 306 | { | 305 | { |
| 307 | __le16 mask_fc; | 306 | __le16 mask_fc; |
| 308 | int a4_included, mgmt; | 307 | int a4_included, mgmt; |
| @@ -456,7 +455,7 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb) | |||
| 456 | return 0; | 455 | return 0; |
| 457 | 456 | ||
| 458 | pos += IEEE80211_CCMP_HDR_LEN; | 457 | pos += IEEE80211_CCMP_HDR_LEN; |
| 459 | ccmp_special_blocks(skb, pn, b_0, aad, 0); | 458 | ccmp_special_blocks(skb, pn, b_0, aad); |
| 460 | ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len, | 459 | ieee80211_aes_ccm_encrypt(key->u.ccmp.tfm, b_0, aad, pos, len, |
| 461 | skb_put(skb, IEEE80211_CCMP_MIC_LEN)); | 460 | skb_put(skb, IEEE80211_CCMP_MIC_LEN)); |
| 462 | 461 | ||
| @@ -495,7 +494,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
| 495 | hdrlen = ieee80211_hdrlen(hdr->frame_control); | 494 | hdrlen = ieee80211_hdrlen(hdr->frame_control); |
| 496 | 495 | ||
| 497 | if (!ieee80211_is_data(hdr->frame_control) && | 496 | if (!ieee80211_is_data(hdr->frame_control) && |
| 498 | !ieee80211_is_robust_mgmt_frame(hdr)) | 497 | !ieee80211_is_robust_mgmt_frame(skb)) |
| 499 | return RX_CONTINUE; | 498 | return RX_CONTINUE; |
| 500 | 499 | ||
| 501 | data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN - | 500 | data_len = skb->len - hdrlen - IEEE80211_CCMP_HDR_LEN - |
| @@ -524,7 +523,7 @@ ieee80211_crypto_ccmp_decrypt(struct ieee80211_rx_data *rx) | |||
| 524 | u8 aad[2 * AES_BLOCK_SIZE]; | 523 | u8 aad[2 * AES_BLOCK_SIZE]; |
| 525 | u8 b_0[AES_BLOCK_SIZE]; | 524 | u8 b_0[AES_BLOCK_SIZE]; |
| 526 | /* hardware didn't decrypt/verify MIC */ | 525 | /* hardware didn't decrypt/verify MIC */ |
| 527 | ccmp_special_blocks(skb, pn, b_0, aad, 1); | 526 | ccmp_special_blocks(skb, pn, b_0, aad); |
| 528 | 527 | ||
| 529 | if (ieee80211_aes_ccm_decrypt( | 528 | if (ieee80211_aes_ccm_decrypt( |
| 530 | key->u.ccmp.tfm, b_0, aad, | 529 | key->u.ccmp.tfm, b_0, aad, |
diff --git a/net/mac802154/Makefile b/net/mac802154/Makefile index 57cf5d1a2e4a..15d62df52182 100644 --- a/net/mac802154/Makefile +++ b/net/mac802154/Makefile | |||
| @@ -1,2 +1,4 @@ | |||
| 1 | obj-$(CONFIG_MAC802154) += mac802154.o | 1 | obj-$(CONFIG_MAC802154) += mac802154.o |
| 2 | mac802154-objs := ieee802154_dev.o rx.o tx.o mac_cmd.o mib.o monitor.o wpan.o | 2 | mac802154-objs := ieee802154_dev.o rx.o tx.o mac_cmd.o mib.o monitor.o wpan.o |
| 3 | |||
| 4 | ccflags-y += -D__CHECK_ENDIAN__ | ||
diff --git a/net/mac802154/ieee802154_dev.c b/net/mac802154/ieee802154_dev.c index 52ae6646a411..2cf66d885e68 100644 --- a/net/mac802154/ieee802154_dev.c +++ b/net/mac802154/ieee802154_dev.c | |||
| @@ -27,6 +27,7 @@ | |||
| 27 | #include <net/netlink.h> | 27 | #include <net/netlink.h> |
| 28 | #include <linux/nl802154.h> | 28 | #include <linux/nl802154.h> |
| 29 | #include <net/mac802154.h> | 29 | #include <net/mac802154.h> |
| 30 | #include <net/ieee802154_netdev.h> | ||
| 30 | #include <net/route.h> | 31 | #include <net/route.h> |
| 31 | #include <net/wpan-phy.h> | 32 | #include <net/wpan-phy.h> |
| 32 | 33 | ||
| @@ -35,9 +36,28 @@ | |||
| 35 | int mac802154_slave_open(struct net_device *dev) | 36 | int mac802154_slave_open(struct net_device *dev) |
| 36 | { | 37 | { |
| 37 | struct mac802154_sub_if_data *priv = netdev_priv(dev); | 38 | struct mac802154_sub_if_data *priv = netdev_priv(dev); |
| 39 | struct mac802154_sub_if_data *subif; | ||
| 38 | struct mac802154_priv *ipriv = priv->hw; | 40 | struct mac802154_priv *ipriv = priv->hw; |
| 39 | int res = 0; | 41 | int res = 0; |
| 40 | 42 | ||
| 43 | ASSERT_RTNL(); | ||
| 44 | |||
| 45 | if (priv->type == IEEE802154_DEV_WPAN) { | ||
| 46 | mutex_lock(&priv->hw->slaves_mtx); | ||
| 47 | list_for_each_entry(subif, &priv->hw->slaves, list) { | ||
| 48 | if (subif != priv && subif->type == priv->type && | ||
| 49 | subif->running) { | ||
| 50 | mutex_unlock(&priv->hw->slaves_mtx); | ||
| 51 | return -EBUSY; | ||
| 52 | } | ||
| 53 | } | ||
| 54 | mutex_unlock(&priv->hw->slaves_mtx); | ||
| 55 | } | ||
| 56 | |||
| 57 | mutex_lock(&priv->hw->slaves_mtx); | ||
| 58 | priv->running = true; | ||
| 59 | mutex_unlock(&priv->hw->slaves_mtx); | ||
| 60 | |||
| 41 | if (ipriv->open_count++ == 0) { | 61 | if (ipriv->open_count++ == 0) { |
| 42 | res = ipriv->ops->start(&ipriv->hw); | 62 | res = ipriv->ops->start(&ipriv->hw); |
| 43 | WARN_ON(res); | 63 | WARN_ON(res); |
| @@ -46,7 +66,9 @@ int mac802154_slave_open(struct net_device *dev) | |||
| 46 | } | 66 | } |
| 47 | 67 | ||
| 48 | if (ipriv->ops->ieee_addr) { | 68 | if (ipriv->ops->ieee_addr) { |
| 49 | res = ipriv->ops->ieee_addr(&ipriv->hw, dev->dev_addr); | 69 | __le64 addr = ieee802154_devaddr_from_raw(dev->dev_addr); |
| 70 | |||
| 71 | res = ipriv->ops->ieee_addr(&ipriv->hw, addr); | ||
| 50 | WARN_ON(res); | 72 | WARN_ON(res); |
| 51 | if (res) | 73 | if (res) |
| 52 | goto err; | 74 | goto err; |
| @@ -66,8 +88,14 @@ int mac802154_slave_close(struct net_device *dev) | |||
| 66 | struct mac802154_sub_if_data *priv = netdev_priv(dev); | 88 | struct mac802154_sub_if_data *priv = netdev_priv(dev); |
| 67 | struct mac802154_priv *ipriv = priv->hw; | 89 | struct mac802154_priv *ipriv = priv->hw; |
| 68 | 90 | ||
| 91 | ASSERT_RTNL(); | ||
| 92 | |||
| 69 | netif_stop_queue(dev); | 93 | netif_stop_queue(dev); |
| 70 | 94 | ||
| 95 | mutex_lock(&priv->hw->slaves_mtx); | ||
| 96 | priv->running = false; | ||
| 97 | mutex_unlock(&priv->hw->slaves_mtx); | ||
| 98 | |||
| 71 | if (!--ipriv->open_count) | 99 | if (!--ipriv->open_count) |
| 72 | ipriv->ops->stop(&ipriv->hw); | 100 | ipriv->ops->stop(&ipriv->hw); |
| 73 | 101 | ||
| @@ -165,6 +193,49 @@ err: | |||
| 165 | return ERR_PTR(err); | 193 | return ERR_PTR(err); |
| 166 | } | 194 | } |
| 167 | 195 | ||
| 196 | static int mac802154_set_txpower(struct wpan_phy *phy, int db) | ||
| 197 | { | ||
| 198 | struct mac802154_priv *priv = wpan_phy_priv(phy); | ||
| 199 | |||
| 200 | return priv->ops->set_txpower(&priv->hw, db); | ||
| 201 | } | ||
| 202 | |||
| 203 | static int mac802154_set_lbt(struct wpan_phy *phy, bool on) | ||
| 204 | { | ||
| 205 | struct mac802154_priv *priv = wpan_phy_priv(phy); | ||
| 206 | |||
| 207 | return priv->ops->set_lbt(&priv->hw, on); | ||
| 208 | } | ||
| 209 | |||
| 210 | static int mac802154_set_cca_mode(struct wpan_phy *phy, u8 mode) | ||
| 211 | { | ||
| 212 | struct mac802154_priv *priv = wpan_phy_priv(phy); | ||
| 213 | |||
| 214 | return priv->ops->set_cca_mode(&priv->hw, mode); | ||
| 215 | } | ||
| 216 | |||
| 217 | static int mac802154_set_cca_ed_level(struct wpan_phy *phy, s32 level) | ||
| 218 | { | ||
| 219 | struct mac802154_priv *priv = wpan_phy_priv(phy); | ||
| 220 | |||
| 221 | return priv->ops->set_cca_ed_level(&priv->hw, level); | ||
| 222 | } | ||
| 223 | |||
| 224 | static int mac802154_set_csma_params(struct wpan_phy *phy, u8 min_be, | ||
| 225 | u8 max_be, u8 retries) | ||
| 226 | { | ||
| 227 | struct mac802154_priv *priv = wpan_phy_priv(phy); | ||
| 228 | |||
| 229 | return priv->ops->set_csma_params(&priv->hw, min_be, max_be, retries); | ||
| 230 | } | ||
| 231 | |||
| 232 | static int mac802154_set_frame_retries(struct wpan_phy *phy, s8 retries) | ||
| 233 | { | ||
| 234 | struct mac802154_priv *priv = wpan_phy_priv(phy); | ||
| 235 | |||
| 236 | return priv->ops->set_frame_retries(&priv->hw, retries); | ||
| 237 | } | ||
| 238 | |||
| 168 | struct ieee802154_dev * | 239 | struct ieee802154_dev * |
| 169 | ieee802154_alloc_device(size_t priv_data_len, struct ieee802154_ops *ops) | 240 | ieee802154_alloc_device(size_t priv_data_len, struct ieee802154_ops *ops) |
| 170 | { | 241 | { |
| @@ -242,6 +313,18 @@ int ieee802154_register_device(struct ieee802154_dev *dev) | |||
| 242 | 313 | ||
| 243 | priv->phy->add_iface = mac802154_add_iface; | 314 | priv->phy->add_iface = mac802154_add_iface; |
| 244 | priv->phy->del_iface = mac802154_del_iface; | 315 | priv->phy->del_iface = mac802154_del_iface; |
| 316 | if (priv->ops->set_txpower) | ||
| 317 | priv->phy->set_txpower = mac802154_set_txpower; | ||
| 318 | if (priv->ops->set_lbt) | ||
| 319 | priv->phy->set_lbt = mac802154_set_lbt; | ||
| 320 | if (priv->ops->set_cca_mode) | ||
| 321 | priv->phy->set_cca_mode = mac802154_set_cca_mode; | ||
| 322 | if (priv->ops->set_cca_ed_level) | ||
| 323 | priv->phy->set_cca_ed_level = mac802154_set_cca_ed_level; | ||
| 324 | if (priv->ops->set_csma_params) | ||
| 325 | priv->phy->set_csma_params = mac802154_set_csma_params; | ||
| 326 | if (priv->ops->set_frame_retries) | ||
| 327 | priv->phy->set_frame_retries = mac802154_set_frame_retries; | ||
| 245 | 328 | ||
| 246 | rc = wpan_phy_register(priv->phy); | 329 | rc = wpan_phy_register(priv->phy); |
| 247 | if (rc < 0) | 330 | if (rc < 0) |
diff --git a/net/mac802154/mac802154.h b/net/mac802154/mac802154.h index d48422e27110..28ef59c566e6 100644 --- a/net/mac802154/mac802154.h +++ b/net/mac802154/mac802154.h | |||
| @@ -23,6 +23,8 @@ | |||
| 23 | #ifndef MAC802154_H | 23 | #ifndef MAC802154_H |
| 24 | #define MAC802154_H | 24 | #define MAC802154_H |
| 25 | 25 | ||
| 26 | #include <net/ieee802154_netdev.h> | ||
| 27 | |||
| 26 | /* mac802154 device private data */ | 28 | /* mac802154 device private data */ |
| 27 | struct mac802154_priv { | 29 | struct mac802154_priv { |
| 28 | struct ieee802154_dev hw; | 30 | struct ieee802154_dev hw; |
| @@ -71,15 +73,19 @@ struct mac802154_sub_if_data { | |||
| 71 | struct net_device *dev; | 73 | struct net_device *dev; |
| 72 | 74 | ||
| 73 | int type; | 75 | int type; |
| 76 | bool running; | ||
| 74 | 77 | ||
| 75 | spinlock_t mib_lock; | 78 | spinlock_t mib_lock; |
| 76 | 79 | ||
| 77 | __le16 pan_id; | 80 | __le16 pan_id; |
| 78 | __le16 short_addr; | 81 | __le16 short_addr; |
| 82 | __le64 extended_addr; | ||
| 79 | 83 | ||
| 80 | u8 chan; | 84 | u8 chan; |
| 81 | u8 page; | 85 | u8 page; |
| 82 | 86 | ||
| 87 | struct ieee802154_mac_params mac_params; | ||
| 88 | |||
| 83 | /* MAC BSN field */ | 89 | /* MAC BSN field */ |
| 84 | u8 bsn; | 90 | u8 bsn; |
| 85 | /* MAC DSN field */ | 91 | /* MAC DSN field */ |
| @@ -106,12 +112,17 @@ netdev_tx_t mac802154_tx(struct mac802154_priv *priv, struct sk_buff *skb, | |||
| 106 | u8 page, u8 chan); | 112 | u8 page, u8 chan); |
| 107 | 113 | ||
| 108 | /* MIB callbacks */ | 114 | /* MIB callbacks */ |
| 109 | void mac802154_dev_set_short_addr(struct net_device *dev, u16 val); | 115 | void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val); |
| 110 | u16 mac802154_dev_get_short_addr(const struct net_device *dev); | 116 | __le16 mac802154_dev_get_short_addr(const struct net_device *dev); |
| 111 | void mac802154_dev_set_ieee_addr(struct net_device *dev); | 117 | void mac802154_dev_set_ieee_addr(struct net_device *dev); |
| 112 | u16 mac802154_dev_get_pan_id(const struct net_device *dev); | 118 | __le16 mac802154_dev_get_pan_id(const struct net_device *dev); |
| 113 | void mac802154_dev_set_pan_id(struct net_device *dev, u16 val); | 119 | void mac802154_dev_set_pan_id(struct net_device *dev, __le16 val); |
| 114 | void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan); | 120 | void mac802154_dev_set_page_channel(struct net_device *dev, u8 page, u8 chan); |
| 115 | u8 mac802154_dev_get_dsn(const struct net_device *dev); | 121 | u8 mac802154_dev_get_dsn(const struct net_device *dev); |
| 116 | 122 | ||
| 123 | int mac802154_set_mac_params(struct net_device *dev, | ||
| 124 | const struct ieee802154_mac_params *params); | ||
| 125 | void mac802154_get_mac_params(struct net_device *dev, | ||
| 126 | struct ieee802154_mac_params *params); | ||
| 127 | |||
| 117 | #endif /* MAC802154_H */ | 128 | #endif /* MAC802154_H */ |
diff --git a/net/mac802154/mac_cmd.c b/net/mac802154/mac_cmd.c index a99910d4d52f..d40c0928bc62 100644 --- a/net/mac802154/mac_cmd.c +++ b/net/mac802154/mac_cmd.c | |||
| @@ -40,7 +40,7 @@ static int mac802154_mlme_start_req(struct net_device *dev, | |||
| 40 | u8 pan_coord, u8 blx, | 40 | u8 pan_coord, u8 blx, |
| 41 | u8 coord_realign) | 41 | u8 coord_realign) |
| 42 | { | 42 | { |
| 43 | BUG_ON(addr->addr_type != IEEE802154_ADDR_SHORT); | 43 | BUG_ON(addr->mode != IEEE802154_ADDR_SHORT); |
| 44 | 44 | ||
| 45 | mac802154_dev_set_pan_id(dev, addr->pan_id); | 45 | mac802154_dev_set_pan_id(dev, addr->pan_id); |
| 46 | mac802154_dev_set_short_addr(dev, addr->short_addr); | 46 | mac802154_dev_set_short_addr(dev, addr->short_addr); |
| @@ -74,4 +74,7 @@ struct ieee802154_mlme_ops mac802154_mlme_wpan = { | |||
| 74 | .get_pan_id = mac802154_dev_get_pan_id, | 74 | .get_pan_id = mac802154_dev_get_pan_id, |
| 75 | .get_short_addr = mac802154_dev_get_short_addr, | 75 | .get_short_addr = mac802154_dev_get_short_addr, |
| 76 | .get_dsn = mac802154_dev_get_dsn, | 76 | .get_dsn = mac802154_dev_get_dsn, |
| 77 | |||
| 78 | .set_mac_params = mac802154_set_mac_params, | ||
| 79 | .get_mac_params = mac802154_get_mac_params, | ||
| 77 | }; | 80 | }; |
diff --git a/net/mac802154/mib.c b/net/mac802154/mib.c index 8ded97cf1c33..f0991f2344d4 100644 --- a/net/mac802154/mib.c +++ b/net/mac802154/mib.c | |||
| @@ -24,6 +24,7 @@ | |||
| 24 | #include <linux/if_arp.h> | 24 | #include <linux/if_arp.h> |
| 25 | 25 | ||
| 26 | #include <net/mac802154.h> | 26 | #include <net/mac802154.h> |
| 27 | #include <net/ieee802154_netdev.h> | ||
| 27 | #include <net/wpan-phy.h> | 28 | #include <net/wpan-phy.h> |
| 28 | 29 | ||
| 29 | #include "mac802154.h" | 30 | #include "mac802154.h" |
| @@ -62,8 +63,6 @@ static void hw_addr_notify(struct work_struct *work) | |||
| 62 | pr_debug("failed changed mask %lx\n", nw->changed); | 63 | pr_debug("failed changed mask %lx\n", nw->changed); |
| 63 | 64 | ||
| 64 | kfree(nw); | 65 | kfree(nw); |
| 65 | |||
| 66 | return; | ||
| 67 | } | 66 | } |
| 68 | 67 | ||
| 69 | static void set_hw_addr_filt(struct net_device *dev, unsigned long changed) | 68 | static void set_hw_addr_filt(struct net_device *dev, unsigned long changed) |
| @@ -79,11 +78,9 @@ static void set_hw_addr_filt(struct net_device *dev, unsigned long changed) | |||
| 79 | work->dev = dev; | 78 | work->dev = dev; |
| 80 | work->changed = changed; | 79 | work->changed = changed; |
| 81 | queue_work(priv->hw->dev_workqueue, &work->work); | 80 | queue_work(priv->hw->dev_workqueue, &work->work); |
| 82 | |||
| 83 | return; | ||
| 84 | } | 81 | } |
| 85 | 82 | ||
| 86 | void mac802154_dev_set_short_addr(struct net_device *dev, u16 val) | 83 | void mac802154_dev_set_short_addr(struct net_device *dev, __le16 val) |
| 87 | { | 84 | { |
| 88 | struct mac802154_sub_if_data *priv = netdev_priv(dev); | 85 | struct mac802154_sub_if_data *priv = netdev_priv(dev); |
| 89 | 86 | ||
| @@ -100,10 +97,10 @@ void mac802154_dev_set_short_addr(struct net_device *dev, u16 val) | |||
| 100 | } | 97 | } |
| 101 | } | 98 | } |
| 102 | 99 | ||
| 103 | u16 mac802154_dev_get_short_addr(const struct net_device *dev) | 100 | __le16 mac802154_dev_get_short_addr(const struct net_device *dev) |
| 104 | { | 101 | { |
| 105 | struct mac802154_sub_if_data *priv = netdev_priv(dev); | 102 | struct mac802154_sub_if_data *priv = netdev_priv(dev); |
| 106 | u16 ret; | 103 | __le16 ret; |
| 107 | 104 | ||
| 108 | BUG_ON(dev->type != ARPHRD_IEEE802154); | 105 | BUG_ON(dev->type != ARPHRD_IEEE802154); |
| 109 | 106 | ||
| @@ -119,19 +116,19 @@ void mac802154_dev_set_ieee_addr(struct net_device *dev) | |||
| 119 | struct mac802154_sub_if_data *priv = netdev_priv(dev); | 116 | struct mac802154_sub_if_data *priv = netdev_priv(dev); |
| 120 | struct mac802154_priv *mac = priv->hw; | 117 | struct mac802154_priv *mac = priv->hw; |
| 121 | 118 | ||
| 119 | priv->extended_addr = ieee802154_devaddr_from_raw(dev->dev_addr); | ||
| 120 | |||
| 122 | if (mac->ops->set_hw_addr_filt && | 121 | if (mac->ops->set_hw_addr_filt && |
| 123 | memcmp(mac->hw.hw_filt.ieee_addr, | 122 | mac->hw.hw_filt.ieee_addr != priv->extended_addr) { |
| 124 | dev->dev_addr, IEEE802154_ADDR_LEN)) { | 123 | mac->hw.hw_filt.ieee_addr = priv->extended_addr; |
| 125 | memcpy(mac->hw.hw_filt.ieee_addr, | ||
| 126 | dev->dev_addr, IEEE802154_ADDR_LEN); | ||
| 127 | set_hw_addr_filt(dev, IEEE802515_AFILT_IEEEADDR_CHANGED); | 124 | set_hw_addr_filt(dev, IEEE802515_AFILT_IEEEADDR_CHANGED); |
| 128 | } | 125 | } |
| 129 | } | 126 | } |
| 130 | 127 | ||
| 131 | u16 mac802154_dev_get_pan_id(const struct net_device *dev) | 128 | __le16 mac802154_dev_get_pan_id(const struct net_device *dev) |
| 132 | { | 129 | { |
| 133 | struct mac802154_sub_if_data *priv = netdev_priv(dev); | 130 | struct mac802154_sub_if_data *priv = netdev_priv(dev); |
| 134 | u16 ret; | 131 | __le16 ret; |
| 135 | 132 | ||
| 136 | BUG_ON(dev->type != ARPHRD_IEEE802154); | 133 | BUG_ON(dev->type != ARPHRD_IEEE802154); |
| 137 | 134 | ||
| @@ -142,7 +139,7 @@ u16 mac802154_dev_get_pan_id(const struct net_device *dev) | |||
| 142 | return ret; | 139 | return ret; |
| 143 | } | 140 | } |
| 144 | 141 | ||
| 145 | void mac802154_dev_set_pan_id(struct net_device *dev, u16 val) | 142 | void mac802154_dev_set_pan_id(struct net_device *dev, __le16 val) |
| 146 | { | 143 | { |
| 147 | struct mac802154_sub_if_data *priv = netdev_priv(dev); | 144 | struct mac802154_sub_if_data *priv = netdev_priv(dev); |
| 148 | 145 | ||
diff --git a/net/mac802154/rx.c b/net/mac802154/rx.c index 38548ec2098f..03855b0677cc 100644 --- a/net/mac802154/rx.c +++ b/net/mac802154/rx.c | |||
| @@ -80,7 +80,6 @@ mac802154_subif_rx(struct ieee802154_dev *hw, struct sk_buff *skb, u8 lqi) | |||
| 80 | mac802154_wpans_rx(priv, skb); | 80 | mac802154_wpans_rx(priv, skb); |
| 81 | out: | 81 | out: |
| 82 | dev_kfree_skb(skb); | 82 | dev_kfree_skb(skb); |
| 83 | return; | ||
| 84 | } | 83 | } |
| 85 | 84 | ||
| 86 | static void mac802154_rx_worker(struct work_struct *work) | 85 | static void mac802154_rx_worker(struct work_struct *work) |
diff --git a/net/mac802154/wpan.c b/net/mac802154/wpan.c index 372d8a222b91..1df7a6a57386 100644 --- a/net/mac802154/wpan.c +++ b/net/mac802154/wpan.c | |||
| @@ -35,35 +35,6 @@ | |||
| 35 | 35 | ||
| 36 | #include "mac802154.h" | 36 | #include "mac802154.h" |
| 37 | 37 | ||
| 38 | static inline int mac802154_fetch_skb_u8(struct sk_buff *skb, u8 *val) | ||
| 39 | { | ||
| 40 | if (unlikely(!pskb_may_pull(skb, 1))) | ||
| 41 | return -EINVAL; | ||
| 42 | |||
| 43 | *val = skb->data[0]; | ||
| 44 | skb_pull(skb, 1); | ||
| 45 | |||
| 46 | return 0; | ||
| 47 | } | ||
| 48 | |||
| 49 | static inline int mac802154_fetch_skb_u16(struct sk_buff *skb, u16 *val) | ||
| 50 | { | ||
| 51 | if (unlikely(!pskb_may_pull(skb, 2))) | ||
| 52 | return -EINVAL; | ||
| 53 | |||
| 54 | *val = skb->data[0] | (skb->data[1] << 8); | ||
| 55 | skb_pull(skb, 2); | ||
| 56 | |||
| 57 | return 0; | ||
| 58 | } | ||
| 59 | |||
| 60 | static inline void mac802154_haddr_copy_swap(u8 *dest, const u8 *src) | ||
| 61 | { | ||
| 62 | int i; | ||
| 63 | for (i = 0; i < IEEE802154_ADDR_LEN; i++) | ||
| 64 | dest[IEEE802154_ADDR_LEN - i - 1] = src[i]; | ||
| 65 | } | ||
| 66 | |||
| 67 | static int | 38 | static int |
| 68 | mac802154_wpan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | 39 | mac802154_wpan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) |
| 69 | { | 40 | { |
| @@ -76,19 +47,25 @@ mac802154_wpan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
| 76 | 47 | ||
| 77 | switch (cmd) { | 48 | switch (cmd) { |
| 78 | case SIOCGIFADDR: | 49 | case SIOCGIFADDR: |
| 79 | if (priv->pan_id == IEEE802154_PANID_BROADCAST || | 50 | { |
| 80 | priv->short_addr == IEEE802154_ADDR_BROADCAST) { | 51 | u16 pan_id, short_addr; |
| 52 | |||
| 53 | pan_id = le16_to_cpu(priv->pan_id); | ||
| 54 | short_addr = le16_to_cpu(priv->short_addr); | ||
| 55 | if (pan_id == IEEE802154_PANID_BROADCAST || | ||
| 56 | short_addr == IEEE802154_ADDR_BROADCAST) { | ||
| 81 | err = -EADDRNOTAVAIL; | 57 | err = -EADDRNOTAVAIL; |
| 82 | break; | 58 | break; |
| 83 | } | 59 | } |
| 84 | 60 | ||
| 85 | sa->family = AF_IEEE802154; | 61 | sa->family = AF_IEEE802154; |
| 86 | sa->addr.addr_type = IEEE802154_ADDR_SHORT; | 62 | sa->addr.addr_type = IEEE802154_ADDR_SHORT; |
| 87 | sa->addr.pan_id = priv->pan_id; | 63 | sa->addr.pan_id = pan_id; |
| 88 | sa->addr.short_addr = priv->short_addr; | 64 | sa->addr.short_addr = short_addr; |
| 89 | 65 | ||
| 90 | err = 0; | 66 | err = 0; |
| 91 | break; | 67 | break; |
| 68 | } | ||
| 92 | case SIOCSIFADDR: | 69 | case SIOCSIFADDR: |
| 93 | dev_warn(&dev->dev, | 70 | dev_warn(&dev->dev, |
| 94 | "Using DEBUGing ioctl SIOCSIFADDR isn't recommened!\n"); | 71 | "Using DEBUGing ioctl SIOCSIFADDR isn't recommened!\n"); |
| @@ -101,8 +78,8 @@ mac802154_wpan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
| 101 | break; | 78 | break; |
| 102 | } | 79 | } |
| 103 | 80 | ||
| 104 | priv->pan_id = sa->addr.pan_id; | 81 | priv->pan_id = cpu_to_le16(sa->addr.pan_id); |
| 105 | priv->short_addr = sa->addr.short_addr; | 82 | priv->short_addr = cpu_to_le16(sa->addr.short_addr); |
| 106 | 83 | ||
| 107 | err = 0; | 84 | err = 0; |
| 108 | break; | 85 | break; |
| @@ -125,190 +102,154 @@ static int mac802154_wpan_mac_addr(struct net_device *dev, void *p) | |||
| 125 | return 0; | 102 | return 0; |
| 126 | } | 103 | } |
| 127 | 104 | ||
| 128 | static int mac802154_header_create(struct sk_buff *skb, | 105 | int mac802154_set_mac_params(struct net_device *dev, |
| 129 | struct net_device *dev, | 106 | const struct ieee802154_mac_params *params) |
| 130 | unsigned short type, | ||
| 131 | const void *_daddr, | ||
| 132 | const void *_saddr, | ||
| 133 | unsigned len) | ||
| 134 | { | 107 | { |
| 135 | const struct ieee802154_addr *saddr = _saddr; | ||
| 136 | const struct ieee802154_addr *daddr = _daddr; | ||
| 137 | struct ieee802154_addr dev_addr; | ||
| 138 | struct mac802154_sub_if_data *priv = netdev_priv(dev); | 108 | struct mac802154_sub_if_data *priv = netdev_priv(dev); |
| 139 | int pos = 2; | ||
| 140 | u8 head[MAC802154_FRAME_HARD_HEADER_LEN]; | ||
| 141 | u16 fc; | ||
| 142 | 109 | ||
| 143 | if (!daddr) | 110 | mutex_lock(&priv->hw->slaves_mtx); |
| 144 | return -EINVAL; | 111 | priv->mac_params = *params; |
| 112 | mutex_unlock(&priv->hw->slaves_mtx); | ||
| 145 | 113 | ||
| 146 | head[pos++] = mac_cb(skb)->seq; /* DSN/BSN */ | 114 | return 0; |
| 147 | fc = mac_cb_type(skb); | 115 | } |
| 148 | if (mac_cb_is_ackreq(skb)) | ||
| 149 | fc |= IEEE802154_FC_ACK_REQ; | ||
| 150 | 116 | ||
| 151 | if (!saddr) { | 117 | void mac802154_get_mac_params(struct net_device *dev, |
| 152 | spin_lock_bh(&priv->mib_lock); | 118 | struct ieee802154_mac_params *params) |
| 119 | { | ||
| 120 | struct mac802154_sub_if_data *priv = netdev_priv(dev); | ||
| 153 | 121 | ||
| 154 | if (priv->short_addr == IEEE802154_ADDR_BROADCAST || | 122 | mutex_lock(&priv->hw->slaves_mtx); |
| 155 | priv->short_addr == IEEE802154_ADDR_UNDEF || | 123 | *params = priv->mac_params; |
| 156 | priv->pan_id == IEEE802154_PANID_BROADCAST) { | 124 | mutex_unlock(&priv->hw->slaves_mtx); |
| 157 | dev_addr.addr_type = IEEE802154_ADDR_LONG; | 125 | } |
| 158 | memcpy(dev_addr.hwaddr, dev->dev_addr, | ||
| 159 | IEEE802154_ADDR_LEN); | ||
| 160 | } else { | ||
| 161 | dev_addr.addr_type = IEEE802154_ADDR_SHORT; | ||
| 162 | dev_addr.short_addr = priv->short_addr; | ||
| 163 | } | ||
| 164 | 126 | ||
| 165 | dev_addr.pan_id = priv->pan_id; | 127 | int mac802154_wpan_open(struct net_device *dev) |
| 166 | saddr = &dev_addr; | 128 | { |
| 129 | int rc; | ||
| 130 | struct mac802154_sub_if_data *priv = netdev_priv(dev); | ||
| 131 | struct wpan_phy *phy = priv->hw->phy; | ||
| 167 | 132 | ||
| 168 | spin_unlock_bh(&priv->mib_lock); | 133 | rc = mac802154_slave_open(dev); |
| 169 | } | 134 | if (rc < 0) |
| 135 | return rc; | ||
| 170 | 136 | ||
| 171 | if (daddr->addr_type != IEEE802154_ADDR_NONE) { | 137 | mutex_lock(&phy->pib_lock); |
| 172 | fc |= (daddr->addr_type << IEEE802154_FC_DAMODE_SHIFT); | ||
| 173 | 138 | ||
| 174 | head[pos++] = daddr->pan_id & 0xff; | 139 | if (phy->set_txpower) { |
| 175 | head[pos++] = daddr->pan_id >> 8; | 140 | rc = phy->set_txpower(phy, priv->mac_params.transmit_power); |
| 141 | if (rc < 0) | ||
| 142 | goto out; | ||
| 143 | } | ||
| 176 | 144 | ||
| 177 | if (daddr->addr_type == IEEE802154_ADDR_SHORT) { | 145 | if (phy->set_lbt) { |
| 178 | head[pos++] = daddr->short_addr & 0xff; | 146 | rc = phy->set_lbt(phy, priv->mac_params.lbt); |
| 179 | head[pos++] = daddr->short_addr >> 8; | 147 | if (rc < 0) |
| 180 | } else { | 148 | goto out; |
| 181 | mac802154_haddr_copy_swap(head + pos, daddr->hwaddr); | ||
| 182 | pos += IEEE802154_ADDR_LEN; | ||
| 183 | } | ||
| 184 | } | 149 | } |
| 185 | 150 | ||
| 186 | if (saddr->addr_type != IEEE802154_ADDR_NONE) { | 151 | if (phy->set_cca_mode) { |
| 187 | fc |= (saddr->addr_type << IEEE802154_FC_SAMODE_SHIFT); | 152 | rc = phy->set_cca_mode(phy, priv->mac_params.cca_mode); |
| 153 | if (rc < 0) | ||
| 154 | goto out; | ||
| 155 | } | ||
| 188 | 156 | ||
| 189 | if ((saddr->pan_id == daddr->pan_id) && | 157 | if (phy->set_cca_ed_level) { |
| 190 | (saddr->pan_id != IEEE802154_PANID_BROADCAST)) { | 158 | rc = phy->set_cca_ed_level(phy, priv->mac_params.cca_ed_level); |
| 191 | /* PANID compression/intra PAN */ | 159 | if (rc < 0) |
| 192 | fc |= IEEE802154_FC_INTRA_PAN; | 160 | goto out; |
| 193 | } else { | 161 | } |
| 194 | head[pos++] = saddr->pan_id & 0xff; | ||
| 195 | head[pos++] = saddr->pan_id >> 8; | ||
| 196 | } | ||
| 197 | 162 | ||
| 198 | if (saddr->addr_type == IEEE802154_ADDR_SHORT) { | 163 | if (phy->set_csma_params) { |
| 199 | head[pos++] = saddr->short_addr & 0xff; | 164 | rc = phy->set_csma_params(phy, priv->mac_params.min_be, |
| 200 | head[pos++] = saddr->short_addr >> 8; | 165 | priv->mac_params.max_be, |
| 201 | } else { | 166 | priv->mac_params.csma_retries); |
| 202 | mac802154_haddr_copy_swap(head + pos, saddr->hwaddr); | 167 | if (rc < 0) |
| 203 | pos += IEEE802154_ADDR_LEN; | 168 | goto out; |
| 204 | } | ||
| 205 | } | 169 | } |
| 206 | 170 | ||
| 207 | head[0] = fc; | 171 | if (phy->set_frame_retries) { |
| 208 | head[1] = fc >> 8; | 172 | rc = phy->set_frame_retries(phy, |
| 173 | priv->mac_params.frame_retries); | ||
| 174 | if (rc < 0) | ||
| 175 | goto out; | ||
| 176 | } | ||
| 209 | 177 | ||
| 210 | memcpy(skb_push(skb, pos), head, pos); | 178 | mutex_unlock(&phy->pib_lock); |
| 211 | skb_reset_mac_header(skb); | 179 | return 0; |
| 212 | skb->mac_len = pos; | ||
| 213 | 180 | ||
| 214 | return pos; | 181 | out: |
| 182 | mutex_unlock(&phy->pib_lock); | ||
| 183 | return rc; | ||
| 215 | } | 184 | } |
| 216 | 185 | ||
| 217 | static int | 186 | static int mac802154_header_create(struct sk_buff *skb, |
| 218 | mac802154_header_parse(const struct sk_buff *skb, unsigned char *haddr) | 187 | struct net_device *dev, |
| 188 | unsigned short type, | ||
| 189 | const void *daddr, | ||
| 190 | const void *saddr, | ||
| 191 | unsigned len) | ||
| 219 | { | 192 | { |
| 220 | const u8 *hdr = skb_mac_header(skb); | 193 | struct ieee802154_hdr hdr; |
| 221 | const u8 *tail = skb_tail_pointer(skb); | 194 | struct mac802154_sub_if_data *priv = netdev_priv(dev); |
| 222 | struct ieee802154_addr *addr = (struct ieee802154_addr *)haddr; | 195 | int hlen; |
| 223 | u16 fc; | ||
| 224 | int da_type; | ||
| 225 | |||
| 226 | if (hdr + 3 > tail) | ||
| 227 | goto malformed; | ||
| 228 | 196 | ||
| 229 | fc = hdr[0] | (hdr[1] << 8); | 197 | if (!daddr) |
| 198 | return -EINVAL; | ||
| 230 | 199 | ||
| 231 | hdr += 3; | 200 | memset(&hdr.fc, 0, sizeof(hdr.fc)); |
| 201 | hdr.fc.type = mac_cb_type(skb); | ||
| 202 | hdr.fc.security_enabled = mac_cb_is_secen(skb); | ||
| 203 | hdr.fc.ack_request = mac_cb_is_ackreq(skb); | ||
| 232 | 204 | ||
| 233 | da_type = IEEE802154_FC_DAMODE(fc); | 205 | if (!saddr) { |
| 234 | addr->addr_type = IEEE802154_FC_SAMODE(fc); | 206 | spin_lock_bh(&priv->mib_lock); |
| 235 | 207 | ||
| 236 | switch (da_type) { | 208 | if (priv->short_addr == cpu_to_le16(IEEE802154_ADDR_BROADCAST) || |
| 237 | case IEEE802154_ADDR_NONE: | 209 | priv->short_addr == cpu_to_le16(IEEE802154_ADDR_UNDEF) || |
| 238 | if (fc & IEEE802154_FC_INTRA_PAN) | 210 | priv->pan_id == cpu_to_le16(IEEE802154_PANID_BROADCAST)) { |
| 239 | goto malformed; | 211 | hdr.source.mode = IEEE802154_ADDR_LONG; |
| 240 | break; | 212 | hdr.source.extended_addr = priv->extended_addr; |
| 241 | case IEEE802154_ADDR_LONG: | 213 | } else { |
| 242 | if (fc & IEEE802154_FC_INTRA_PAN) { | 214 | hdr.source.mode = IEEE802154_ADDR_SHORT; |
| 243 | if (hdr + 2 > tail) | 215 | hdr.source.short_addr = priv->short_addr; |
| 244 | goto malformed; | ||
| 245 | addr->pan_id = hdr[0] | (hdr[1] << 8); | ||
| 246 | hdr += 2; | ||
| 247 | } | 216 | } |
| 248 | 217 | ||
| 249 | if (hdr + IEEE802154_ADDR_LEN > tail) | 218 | hdr.source.pan_id = priv->pan_id; |
| 250 | goto malformed; | ||
| 251 | 219 | ||
| 252 | hdr += IEEE802154_ADDR_LEN; | 220 | spin_unlock_bh(&priv->mib_lock); |
| 253 | break; | 221 | } else { |
| 254 | case IEEE802154_ADDR_SHORT: | 222 | hdr.source = *(const struct ieee802154_addr *)saddr; |
| 255 | if (fc & IEEE802154_FC_INTRA_PAN) { | 223 | } |
| 256 | if (hdr + 2 > tail) | ||
| 257 | goto malformed; | ||
| 258 | addr->pan_id = hdr[0] | (hdr[1] << 8); | ||
| 259 | hdr += 2; | ||
| 260 | } | ||
| 261 | |||
| 262 | if (hdr + 2 > tail) | ||
| 263 | goto malformed; | ||
| 264 | 224 | ||
| 265 | hdr += 2; | 225 | hdr.dest = *(const struct ieee802154_addr *)daddr; |
| 266 | break; | ||
| 267 | default: | ||
| 268 | goto malformed; | ||
| 269 | 226 | ||
| 270 | } | 227 | hlen = ieee802154_hdr_push(skb, &hdr); |
| 228 | if (hlen < 0) | ||
| 229 | return -EINVAL; | ||
| 271 | 230 | ||
| 272 | switch (addr->addr_type) { | 231 | skb_reset_mac_header(skb); |
| 273 | case IEEE802154_ADDR_NONE: | 232 | skb->mac_len = hlen; |
| 274 | break; | ||
| 275 | case IEEE802154_ADDR_LONG: | ||
| 276 | if (!(fc & IEEE802154_FC_INTRA_PAN)) { | ||
| 277 | if (hdr + 2 > tail) | ||
| 278 | goto malformed; | ||
| 279 | addr->pan_id = hdr[0] | (hdr[1] << 8); | ||
| 280 | hdr += 2; | ||
| 281 | } | ||
| 282 | 233 | ||
| 283 | if (hdr + IEEE802154_ADDR_LEN > tail) | 234 | if (hlen + len + 2 > dev->mtu) |
| 284 | goto malformed; | 235 | return -EMSGSIZE; |
| 285 | 236 | ||
| 286 | mac802154_haddr_copy_swap(addr->hwaddr, hdr); | 237 | return hlen; |
| 287 | hdr += IEEE802154_ADDR_LEN; | 238 | } |
| 288 | break; | ||
| 289 | case IEEE802154_ADDR_SHORT: | ||
| 290 | if (!(fc & IEEE802154_FC_INTRA_PAN)) { | ||
| 291 | if (hdr + 2 > tail) | ||
| 292 | goto malformed; | ||
| 293 | addr->pan_id = hdr[0] | (hdr[1] << 8); | ||
| 294 | hdr += 2; | ||
| 295 | } | ||
| 296 | 239 | ||
| 297 | if (hdr + 2 > tail) | 240 | static int |
| 298 | goto malformed; | 241 | mac802154_header_parse(const struct sk_buff *skb, unsigned char *haddr) |
| 242 | { | ||
| 243 | struct ieee802154_hdr hdr; | ||
| 244 | struct ieee802154_addr *addr = (struct ieee802154_addr *)haddr; | ||
| 299 | 245 | ||
| 300 | addr->short_addr = hdr[0] | (hdr[1] << 8); | 246 | if (ieee802154_hdr_peek_addrs(skb, &hdr) < 0) { |
| 301 | hdr += 2; | 247 | pr_debug("malformed packet\n"); |
| 302 | break; | 248 | return 0; |
| 303 | default: | ||
| 304 | goto malformed; | ||
| 305 | } | 249 | } |
| 306 | 250 | ||
| 307 | return sizeof(struct ieee802154_addr); | 251 | *addr = hdr.source; |
| 308 | 252 | return sizeof(*addr); | |
| 309 | malformed: | ||
| 310 | pr_debug("malformed packet\n"); | ||
| 311 | return 0; | ||
| 312 | } | 253 | } |
| 313 | 254 | ||
| 314 | static netdev_tx_t | 255 | static netdev_tx_t |
| @@ -344,7 +285,7 @@ static struct header_ops mac802154_header_ops = { | |||
| 344 | }; | 285 | }; |
| 345 | 286 | ||
| 346 | static const struct net_device_ops mac802154_wpan_ops = { | 287 | static const struct net_device_ops mac802154_wpan_ops = { |
| 347 | .ndo_open = mac802154_slave_open, | 288 | .ndo_open = mac802154_wpan_open, |
| 348 | .ndo_stop = mac802154_slave_close, | 289 | .ndo_stop = mac802154_slave_close, |
| 349 | .ndo_start_xmit = mac802154_wpan_xmit, | 290 | .ndo_start_xmit = mac802154_wpan_xmit, |
| 350 | .ndo_do_ioctl = mac802154_wpan_ioctl, | 291 | .ndo_do_ioctl = mac802154_wpan_ioctl, |
| @@ -382,8 +323,14 @@ void mac802154_wpan_setup(struct net_device *dev) | |||
| 382 | get_random_bytes(&priv->bsn, 1); | 323 | get_random_bytes(&priv->bsn, 1); |
| 383 | get_random_bytes(&priv->dsn, 1); | 324 | get_random_bytes(&priv->dsn, 1); |
| 384 | 325 | ||
| 385 | priv->pan_id = IEEE802154_PANID_BROADCAST; | 326 | /* defaults per 802.15.4-2011 */ |
| 386 | priv->short_addr = IEEE802154_ADDR_BROADCAST; | 327 | priv->mac_params.min_be = 3; |
| 328 | priv->mac_params.max_be = 5; | ||
| 329 | priv->mac_params.csma_retries = 4; | ||
| 330 | priv->mac_params.frame_retries = -1; /* for compatibility, actual default is 3 */ | ||
| 331 | |||
| 332 | priv->pan_id = cpu_to_le16(IEEE802154_PANID_BROADCAST); | ||
| 333 | priv->short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST); | ||
| 387 | } | 334 | } |
| 388 | 335 | ||
| 389 | static int mac802154_process_data(struct net_device *dev, struct sk_buff *skb) | 336 | static int mac802154_process_data(struct net_device *dev, struct sk_buff *skb) |
| @@ -394,13 +341,18 @@ static int mac802154_process_data(struct net_device *dev, struct sk_buff *skb) | |||
| 394 | static int | 341 | static int |
| 395 | mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb) | 342 | mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb) |
| 396 | { | 343 | { |
| 344 | __le16 span, sshort; | ||
| 345 | |||
| 397 | pr_debug("getting packet via slave interface %s\n", sdata->dev->name); | 346 | pr_debug("getting packet via slave interface %s\n", sdata->dev->name); |
| 398 | 347 | ||
| 399 | spin_lock_bh(&sdata->mib_lock); | 348 | spin_lock_bh(&sdata->mib_lock); |
| 400 | 349 | ||
| 401 | switch (mac_cb(skb)->da.addr_type) { | 350 | span = sdata->pan_id; |
| 351 | sshort = sdata->short_addr; | ||
| 352 | |||
| 353 | switch (mac_cb(skb)->dest.mode) { | ||
| 402 | case IEEE802154_ADDR_NONE: | 354 | case IEEE802154_ADDR_NONE: |
| 403 | if (mac_cb(skb)->sa.addr_type != IEEE802154_ADDR_NONE) | 355 | if (mac_cb(skb)->dest.mode != IEEE802154_ADDR_NONE) |
| 404 | /* FIXME: check if we are PAN coordinator */ | 356 | /* FIXME: check if we are PAN coordinator */ |
| 405 | skb->pkt_type = PACKET_OTHERHOST; | 357 | skb->pkt_type = PACKET_OTHERHOST; |
| 406 | else | 358 | else |
| @@ -408,23 +360,22 @@ mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb) | |||
| 408 | skb->pkt_type = PACKET_HOST; | 360 | skb->pkt_type = PACKET_HOST; |
| 409 | break; | 361 | break; |
| 410 | case IEEE802154_ADDR_LONG: | 362 | case IEEE802154_ADDR_LONG: |
| 411 | if (mac_cb(skb)->da.pan_id != sdata->pan_id && | 363 | if (mac_cb(skb)->dest.pan_id != span && |
| 412 | mac_cb(skb)->da.pan_id != IEEE802154_PANID_BROADCAST) | 364 | mac_cb(skb)->dest.pan_id != cpu_to_le16(IEEE802154_PANID_BROADCAST)) |
| 413 | skb->pkt_type = PACKET_OTHERHOST; | 365 | skb->pkt_type = PACKET_OTHERHOST; |
| 414 | else if (!memcmp(mac_cb(skb)->da.hwaddr, sdata->dev->dev_addr, | 366 | else if (mac_cb(skb)->dest.extended_addr == sdata->extended_addr) |
| 415 | IEEE802154_ADDR_LEN)) | ||
| 416 | skb->pkt_type = PACKET_HOST; | 367 | skb->pkt_type = PACKET_HOST; |
| 417 | else | 368 | else |
| 418 | skb->pkt_type = PACKET_OTHERHOST; | 369 | skb->pkt_type = PACKET_OTHERHOST; |
| 419 | break; | 370 | break; |
| 420 | case IEEE802154_ADDR_SHORT: | 371 | case IEEE802154_ADDR_SHORT: |
| 421 | if (mac_cb(skb)->da.pan_id != sdata->pan_id && | 372 | if (mac_cb(skb)->dest.pan_id != span && |
| 422 | mac_cb(skb)->da.pan_id != IEEE802154_PANID_BROADCAST) | 373 | mac_cb(skb)->dest.pan_id != cpu_to_le16(IEEE802154_PANID_BROADCAST)) |
| 423 | skb->pkt_type = PACKET_OTHERHOST; | 374 | skb->pkt_type = PACKET_OTHERHOST; |
| 424 | else if (mac_cb(skb)->da.short_addr == sdata->short_addr) | 375 | else if (mac_cb(skb)->dest.short_addr == sshort) |
| 425 | skb->pkt_type = PACKET_HOST; | 376 | skb->pkt_type = PACKET_HOST; |
| 426 | else if (mac_cb(skb)->da.short_addr == | 377 | else if (mac_cb(skb)->dest.short_addr == |
| 427 | IEEE802154_ADDR_BROADCAST) | 378 | cpu_to_le16(IEEE802154_ADDR_BROADCAST)) |
| 428 | skb->pkt_type = PACKET_BROADCAST; | 379 | skb->pkt_type = PACKET_BROADCAST; |
| 429 | else | 380 | else |
| 430 | skb->pkt_type = PACKET_OTHERHOST; | 381 | skb->pkt_type = PACKET_OTHERHOST; |
| @@ -451,88 +402,82 @@ mac802154_subif_frame(struct mac802154_sub_if_data *sdata, struct sk_buff *skb) | |||
| 451 | } | 402 | } |
| 452 | } | 403 | } |
| 453 | 404 | ||
| 454 | static int mac802154_parse_frame_start(struct sk_buff *skb) | 405 | static void mac802154_print_addr(const char *name, |
| 406 | const struct ieee802154_addr *addr) | ||
| 455 | { | 407 | { |
| 456 | u8 *head = skb->data; | 408 | if (addr->mode == IEEE802154_ADDR_NONE) |
| 457 | u16 fc; | 409 | pr_debug("%s not present\n", name); |
| 458 | |||
| 459 | if (mac802154_fetch_skb_u16(skb, &fc) || | ||
| 460 | mac802154_fetch_skb_u8(skb, &(mac_cb(skb)->seq))) | ||
| 461 | goto err; | ||
| 462 | |||
| 463 | pr_debug("fc: %04x dsn: %02x\n", fc, head[2]); | ||
| 464 | |||
| 465 | mac_cb(skb)->flags = IEEE802154_FC_TYPE(fc); | ||
| 466 | mac_cb(skb)->sa.addr_type = IEEE802154_FC_SAMODE(fc); | ||
| 467 | mac_cb(skb)->da.addr_type = IEEE802154_FC_DAMODE(fc); | ||
| 468 | 410 | ||
| 469 | if (fc & IEEE802154_FC_INTRA_PAN) | 411 | pr_debug("%s PAN ID: %04x\n", name, le16_to_cpu(addr->pan_id)); |
| 470 | mac_cb(skb)->flags |= MAC_CB_FLAG_INTRAPAN; | 412 | if (addr->mode == IEEE802154_ADDR_SHORT) { |
| 413 | pr_debug("%s is short: %04x\n", name, | ||
| 414 | le16_to_cpu(addr->short_addr)); | ||
| 415 | } else { | ||
| 416 | u64 hw = swab64((__force u64) addr->extended_addr); | ||
| 471 | 417 | ||
| 472 | if (mac_cb(skb)->da.addr_type != IEEE802154_ADDR_NONE) { | 418 | pr_debug("%s is hardware: %8phC\n", name, &hw); |
| 473 | if (mac802154_fetch_skb_u16(skb, &(mac_cb(skb)->da.pan_id))) | 419 | } |
| 474 | goto err; | 420 | } |
| 475 | |||
| 476 | /* source PAN id compression */ | ||
| 477 | if (mac_cb_is_intrapan(skb)) | ||
| 478 | mac_cb(skb)->sa.pan_id = mac_cb(skb)->da.pan_id; | ||
| 479 | 421 | ||
| 480 | pr_debug("dest PAN addr: %04x\n", mac_cb(skb)->da.pan_id); | 422 | static int mac802154_parse_frame_start(struct sk_buff *skb) |
| 423 | { | ||
| 424 | int hlen; | ||
| 425 | struct ieee802154_hdr hdr; | ||
| 481 | 426 | ||
| 482 | if (mac_cb(skb)->da.addr_type == IEEE802154_ADDR_SHORT) { | 427 | hlen = ieee802154_hdr_pull(skb, &hdr); |
| 483 | u16 *da = &(mac_cb(skb)->da.short_addr); | 428 | if (hlen < 0) |
| 429 | return -EINVAL; | ||
| 484 | 430 | ||
| 485 | if (mac802154_fetch_skb_u16(skb, da)) | 431 | skb->mac_len = hlen; |
| 486 | goto err; | ||
| 487 | 432 | ||
| 488 | pr_debug("destination address is short: %04x\n", | 433 | pr_debug("fc: %04x dsn: %02x\n", le16_to_cpup((__le16 *)&hdr.fc), |
| 489 | mac_cb(skb)->da.short_addr); | 434 | hdr.seq); |
| 490 | } else { | ||
| 491 | if (!pskb_may_pull(skb, IEEE802154_ADDR_LEN)) | ||
| 492 | goto err; | ||
| 493 | 435 | ||
| 494 | mac802154_haddr_copy_swap(mac_cb(skb)->da.hwaddr, | 436 | mac_cb(skb)->flags = hdr.fc.type; |
| 495 | skb->data); | ||
| 496 | skb_pull(skb, IEEE802154_ADDR_LEN); | ||
| 497 | 437 | ||
| 498 | pr_debug("destination address is hardware\n"); | 438 | if (hdr.fc.ack_request) |
| 499 | } | 439 | mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ; |
| 500 | } | 440 | if (hdr.fc.security_enabled) |
| 441 | mac_cb(skb)->flags |= MAC_CB_FLAG_SECEN; | ||
| 501 | 442 | ||
| 502 | if (mac_cb(skb)->sa.addr_type != IEEE802154_ADDR_NONE) { | 443 | mac802154_print_addr("destination", &hdr.dest); |
| 503 | /* non PAN-compression, fetch source address id */ | 444 | mac802154_print_addr("source", &hdr.source); |
| 504 | if (!(mac_cb_is_intrapan(skb))) { | ||
| 505 | u16 *sa_pan = &(mac_cb(skb)->sa.pan_id); | ||
| 506 | 445 | ||
| 507 | if (mac802154_fetch_skb_u16(skb, sa_pan)) | 446 | mac_cb(skb)->source = hdr.source; |
| 508 | goto err; | 447 | mac_cb(skb)->dest = hdr.dest; |
| 509 | } | ||
| 510 | 448 | ||
| 511 | pr_debug("source PAN addr: %04x\n", mac_cb(skb)->da.pan_id); | 449 | if (hdr.fc.security_enabled) { |
| 450 | u64 key; | ||
| 512 | 451 | ||
| 513 | if (mac_cb(skb)->sa.addr_type == IEEE802154_ADDR_SHORT) { | 452 | pr_debug("seclevel %i\n", hdr.sec.level); |
| 514 | u16 *sa = &(mac_cb(skb)->sa.short_addr); | ||
| 515 | 453 | ||
| 516 | if (mac802154_fetch_skb_u16(skb, sa)) | 454 | switch (hdr.sec.key_id_mode) { |
| 517 | goto err; | 455 | case IEEE802154_SCF_KEY_IMPLICIT: |
| 456 | pr_debug("implicit key\n"); | ||
| 457 | break; | ||
| 518 | 458 | ||
| 519 | pr_debug("source address is short: %04x\n", | 459 | case IEEE802154_SCF_KEY_INDEX: |
| 520 | mac_cb(skb)->sa.short_addr); | 460 | pr_debug("key %02x\n", hdr.sec.key_id); |
| 521 | } else { | 461 | break; |
| 522 | if (!pskb_may_pull(skb, IEEE802154_ADDR_LEN)) | ||
| 523 | goto err; | ||
| 524 | 462 | ||
| 525 | mac802154_haddr_copy_swap(mac_cb(skb)->sa.hwaddr, | 463 | case IEEE802154_SCF_KEY_SHORT_INDEX: |
| 526 | skb->data); | 464 | pr_debug("key %04x:%04x %02x\n", |
| 527 | skb_pull(skb, IEEE802154_ADDR_LEN); | 465 | le32_to_cpu(hdr.sec.short_src) >> 16, |
| 466 | le32_to_cpu(hdr.sec.short_src) & 0xffff, | ||
| 467 | hdr.sec.key_id); | ||
| 468 | break; | ||
| 528 | 469 | ||
| 529 | pr_debug("source address is hardware\n"); | 470 | case IEEE802154_SCF_KEY_HW_INDEX: |
| 471 | key = swab64((__force u64) hdr.sec.extended_src); | ||
| 472 | pr_debug("key source %8phC %02x\n", &key, | ||
| 473 | hdr.sec.key_id); | ||
| 474 | break; | ||
| 530 | } | 475 | } |
| 476 | |||
| 477 | return -EINVAL; | ||
| 531 | } | 478 | } |
| 532 | 479 | ||
| 533 | return 0; | 480 | return 0; |
| 534 | err: | ||
| 535 | return -EINVAL; | ||
| 536 | } | 481 | } |
| 537 | 482 | ||
| 538 | void mac802154_wpans_rx(struct mac802154_priv *priv, struct sk_buff *skb) | 483 | void mac802154_wpans_rx(struct mac802154_priv *priv, struct sk_buff *skb) |
diff --git a/net/netfilter/ipset/Kconfig b/net/netfilter/ipset/Kconfig index 44cd4f58adf0..2f7f5c32c6f9 100644 --- a/net/netfilter/ipset/Kconfig +++ b/net/netfilter/ipset/Kconfig | |||
| @@ -61,6 +61,15 @@ config IP_SET_HASH_IP | |||
| 61 | 61 | ||
| 62 | To compile it as a module, choose M here. If unsure, say N. | 62 | To compile it as a module, choose M here. If unsure, say N. |
| 63 | 63 | ||
| 64 | config IP_SET_HASH_IPMARK | ||
| 65 | tristate "hash:ip,mark set support" | ||
| 66 | depends on IP_SET | ||
| 67 | help | ||
| 68 | This option adds the hash:ip,mark set type support, by which one | ||
| 69 | can store IPv4/IPv6 address and mark pairs. | ||
| 70 | |||
| 71 | To compile it as a module, choose M here. If unsure, say N. | ||
| 72 | |||
| 64 | config IP_SET_HASH_IPPORT | 73 | config IP_SET_HASH_IPPORT |
| 65 | tristate "hash:ip,port set support" | 74 | tristate "hash:ip,port set support" |
| 66 | depends on IP_SET | 75 | depends on IP_SET |
diff --git a/net/netfilter/ipset/Makefile b/net/netfilter/ipset/Makefile index 44b2d38476fa..231f10196cb9 100644 --- a/net/netfilter/ipset/Makefile +++ b/net/netfilter/ipset/Makefile | |||
| @@ -14,6 +14,7 @@ obj-$(CONFIG_IP_SET_BITMAP_PORT) += ip_set_bitmap_port.o | |||
| 14 | 14 | ||
| 15 | # hash types | 15 | # hash types |
| 16 | obj-$(CONFIG_IP_SET_HASH_IP) += ip_set_hash_ip.o | 16 | obj-$(CONFIG_IP_SET_HASH_IP) += ip_set_hash_ip.o |
| 17 | obj-$(CONFIG_IP_SET_HASH_IPMARK) += ip_set_hash_ipmark.o | ||
| 17 | obj-$(CONFIG_IP_SET_HASH_IPPORT) += ip_set_hash_ipport.o | 18 | obj-$(CONFIG_IP_SET_HASH_IPPORT) += ip_set_hash_ipport.o |
| 18 | obj-$(CONFIG_IP_SET_HASH_IPPORTIP) += ip_set_hash_ipportip.o | 19 | obj-$(CONFIG_IP_SET_HASH_IPPORTIP) += ip_set_hash_ipportip.o |
| 19 | obj-$(CONFIG_IP_SET_HASH_IPPORTNET) += ip_set_hash_ipportnet.o | 20 | obj-$(CONFIG_IP_SET_HASH_IPPORTNET) += ip_set_hash_ipportnet.o |
diff --git a/net/netfilter/ipset/ip_set_core.c b/net/netfilter/ipset/ip_set_core.c index de770ec39e51..117208321f16 100644 --- a/net/netfilter/ipset/ip_set_core.c +++ b/net/netfilter/ipset/ip_set_core.c | |||
| @@ -54,10 +54,10 @@ MODULE_DESCRIPTION("core IP set support"); | |||
| 54 | MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_IPSET); | 54 | MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_IPSET); |
| 55 | 55 | ||
| 56 | /* When the nfnl mutex is held: */ | 56 | /* When the nfnl mutex is held: */ |
| 57 | #define nfnl_dereference(p) \ | 57 | #define ip_set_dereference(p) \ |
| 58 | rcu_dereference_protected(p, 1) | 58 | rcu_dereference_protected(p, 1) |
| 59 | #define nfnl_set(inst, id) \ | 59 | #define ip_set(inst, id) \ |
| 60 | nfnl_dereference((inst)->ip_set_list)[id] | 60 | ip_set_dereference((inst)->ip_set_list)[id] |
| 61 | 61 | ||
| 62 | /* | 62 | /* |
| 63 | * The set types are implemented in modules and registered set types | 63 | * The set types are implemented in modules and registered set types |
| @@ -368,6 +368,8 @@ ip_set_elem_len(struct ip_set *set, struct nlattr *tb[], size_t len) | |||
| 368 | 368 | ||
| 369 | if (tb[IPSET_ATTR_CADT_FLAGS]) | 369 | if (tb[IPSET_ATTR_CADT_FLAGS]) |
| 370 | cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); | 370 | cadt_flags = ip_set_get_h32(tb[IPSET_ATTR_CADT_FLAGS]); |
| 371 | if (cadt_flags & IPSET_FLAG_WITH_FORCEADD) | ||
| 372 | set->flags |= IPSET_CREATE_FLAG_FORCEADD; | ||
| 371 | for (id = 0; id < IPSET_EXT_ID_MAX; id++) { | 373 | for (id = 0; id < IPSET_EXT_ID_MAX; id++) { |
| 372 | if (!add_extension(id, cadt_flags, tb)) | 374 | if (!add_extension(id, cadt_flags, tb)) |
| 373 | continue; | 375 | continue; |
| @@ -510,7 +512,7 @@ ip_set_add(ip_set_id_t index, const struct sk_buff *skb, | |||
| 510 | 512 | ||
| 511 | if (opt->dim < set->type->dimension || | 513 | if (opt->dim < set->type->dimension || |
| 512 | !(opt->family == set->family || set->family == NFPROTO_UNSPEC)) | 514 | !(opt->family == set->family || set->family == NFPROTO_UNSPEC)) |
| 513 | return 0; | 515 | return -IPSET_ERR_TYPE_MISMATCH; |
| 514 | 516 | ||
| 515 | write_lock_bh(&set->lock); | 517 | write_lock_bh(&set->lock); |
| 516 | ret = set->variant->kadt(set, skb, par, IPSET_ADD, opt); | 518 | ret = set->variant->kadt(set, skb, par, IPSET_ADD, opt); |
| @@ -533,7 +535,7 @@ ip_set_del(ip_set_id_t index, const struct sk_buff *skb, | |||
| 533 | 535 | ||
| 534 | if (opt->dim < set->type->dimension || | 536 | if (opt->dim < set->type->dimension || |
| 535 | !(opt->family == set->family || set->family == NFPROTO_UNSPEC)) | 537 | !(opt->family == set->family || set->family == NFPROTO_UNSPEC)) |
| 536 | return 0; | 538 | return -IPSET_ERR_TYPE_MISMATCH; |
| 537 | 539 | ||
| 538 | write_lock_bh(&set->lock); | 540 | write_lock_bh(&set->lock); |
| 539 | ret = set->variant->kadt(set, skb, par, IPSET_DEL, opt); | 541 | ret = set->variant->kadt(set, skb, par, IPSET_DEL, opt); |
| @@ -640,7 +642,7 @@ ip_set_nfnl_get_byindex(struct net *net, ip_set_id_t index) | |||
| 640 | return IPSET_INVALID_ID; | 642 | return IPSET_INVALID_ID; |
| 641 | 643 | ||
| 642 | nfnl_lock(NFNL_SUBSYS_IPSET); | 644 | nfnl_lock(NFNL_SUBSYS_IPSET); |
| 643 | set = nfnl_set(inst, index); | 645 | set = ip_set(inst, index); |
| 644 | if (set) | 646 | if (set) |
| 645 | __ip_set_get(set); | 647 | __ip_set_get(set); |
| 646 | else | 648 | else |
| @@ -666,7 +668,7 @@ ip_set_nfnl_put(struct net *net, ip_set_id_t index) | |||
| 666 | 668 | ||
| 667 | nfnl_lock(NFNL_SUBSYS_IPSET); | 669 | nfnl_lock(NFNL_SUBSYS_IPSET); |
| 668 | if (!inst->is_deleted) { /* already deleted from ip_set_net_exit() */ | 670 | if (!inst->is_deleted) { /* already deleted from ip_set_net_exit() */ |
| 669 | set = nfnl_set(inst, index); | 671 | set = ip_set(inst, index); |
| 670 | if (set != NULL) | 672 | if (set != NULL) |
| 671 | __ip_set_put(set); | 673 | __ip_set_put(set); |
| 672 | } | 674 | } |
| @@ -734,7 +736,7 @@ find_set_and_id(struct ip_set_net *inst, const char *name, ip_set_id_t *id) | |||
| 734 | 736 | ||
| 735 | *id = IPSET_INVALID_ID; | 737 | *id = IPSET_INVALID_ID; |
| 736 | for (i = 0; i < inst->ip_set_max; i++) { | 738 | for (i = 0; i < inst->ip_set_max; i++) { |
| 737 | set = nfnl_set(inst, i); | 739 | set = ip_set(inst, i); |
| 738 | if (set != NULL && STREQ(set->name, name)) { | 740 | if (set != NULL && STREQ(set->name, name)) { |
| 739 | *id = i; | 741 | *id = i; |
| 740 | break; | 742 | break; |
| @@ -760,7 +762,7 @@ find_free_id(struct ip_set_net *inst, const char *name, ip_set_id_t *index, | |||
| 760 | 762 | ||
| 761 | *index = IPSET_INVALID_ID; | 763 | *index = IPSET_INVALID_ID; |
| 762 | for (i = 0; i < inst->ip_set_max; i++) { | 764 | for (i = 0; i < inst->ip_set_max; i++) { |
| 763 | s = nfnl_set(inst, i); | 765 | s = ip_set(inst, i); |
| 764 | if (s == NULL) { | 766 | if (s == NULL) { |
| 765 | if (*index == IPSET_INVALID_ID) | 767 | if (*index == IPSET_INVALID_ID) |
| 766 | *index = i; | 768 | *index = i; |
| @@ -883,7 +885,7 @@ ip_set_create(struct sock *ctnl, struct sk_buff *skb, | |||
| 883 | if (!list) | 885 | if (!list) |
| 884 | goto cleanup; | 886 | goto cleanup; |
| 885 | /* nfnl mutex is held, both lists are valid */ | 887 | /* nfnl mutex is held, both lists are valid */ |
| 886 | tmp = nfnl_dereference(inst->ip_set_list); | 888 | tmp = ip_set_dereference(inst->ip_set_list); |
| 887 | memcpy(list, tmp, sizeof(struct ip_set *) * inst->ip_set_max); | 889 | memcpy(list, tmp, sizeof(struct ip_set *) * inst->ip_set_max); |
| 888 | rcu_assign_pointer(inst->ip_set_list, list); | 890 | rcu_assign_pointer(inst->ip_set_list, list); |
| 889 | /* Make sure all current packets have passed through */ | 891 | /* Make sure all current packets have passed through */ |
| @@ -900,7 +902,7 @@ ip_set_create(struct sock *ctnl, struct sk_buff *skb, | |||
| 900 | * Finally! Add our shiny new set to the list, and be done. | 902 | * Finally! Add our shiny new set to the list, and be done. |
| 901 | */ | 903 | */ |
| 902 | pr_debug("create: '%s' created with index %u!\n", set->name, index); | 904 | pr_debug("create: '%s' created with index %u!\n", set->name, index); |
| 903 | nfnl_set(inst, index) = set; | 905 | ip_set(inst, index) = set; |
| 904 | 906 | ||
| 905 | return ret; | 907 | return ret; |
| 906 | 908 | ||
| @@ -925,10 +927,10 @@ ip_set_setname_policy[IPSET_ATTR_CMD_MAX + 1] = { | |||
| 925 | static void | 927 | static void |
| 926 | ip_set_destroy_set(struct ip_set_net *inst, ip_set_id_t index) | 928 | ip_set_destroy_set(struct ip_set_net *inst, ip_set_id_t index) |
| 927 | { | 929 | { |
| 928 | struct ip_set *set = nfnl_set(inst, index); | 930 | struct ip_set *set = ip_set(inst, index); |
| 929 | 931 | ||
| 930 | pr_debug("set: %s\n", set->name); | 932 | pr_debug("set: %s\n", set->name); |
| 931 | nfnl_set(inst, index) = NULL; | 933 | ip_set(inst, index) = NULL; |
| 932 | 934 | ||
| 933 | /* Must call it without holding any lock */ | 935 | /* Must call it without holding any lock */ |
| 934 | set->variant->destroy(set); | 936 | set->variant->destroy(set); |
| @@ -962,7 +964,7 @@ ip_set_destroy(struct sock *ctnl, struct sk_buff *skb, | |||
| 962 | read_lock_bh(&ip_set_ref_lock); | 964 | read_lock_bh(&ip_set_ref_lock); |
| 963 | if (!attr[IPSET_ATTR_SETNAME]) { | 965 | if (!attr[IPSET_ATTR_SETNAME]) { |
| 964 | for (i = 0; i < inst->ip_set_max; i++) { | 966 | for (i = 0; i < inst->ip_set_max; i++) { |
| 965 | s = nfnl_set(inst, i); | 967 | s = ip_set(inst, i); |
| 966 | if (s != NULL && s->ref) { | 968 | if (s != NULL && s->ref) { |
| 967 | ret = -IPSET_ERR_BUSY; | 969 | ret = -IPSET_ERR_BUSY; |
| 968 | goto out; | 970 | goto out; |
| @@ -970,7 +972,7 @@ ip_set_destroy(struct sock *ctnl, struct sk_buff *skb, | |||
| 970 | } | 972 | } |
| 971 | read_unlock_bh(&ip_set_ref_lock); | 973 | read_unlock_bh(&ip_set_ref_lock); |
| 972 | for (i = 0; i < inst->ip_set_max; i++) { | 974 | for (i = 0; i < inst->ip_set_max; i++) { |
| 973 | s = nfnl_set(inst, i); | 975 | s = ip_set(inst, i); |
| 974 | if (s != NULL) | 976 | if (s != NULL) |
| 975 | ip_set_destroy_set(inst, i); | 977 | ip_set_destroy_set(inst, i); |
| 976 | } | 978 | } |
| @@ -1020,7 +1022,7 @@ ip_set_flush(struct sock *ctnl, struct sk_buff *skb, | |||
| 1020 | 1022 | ||
| 1021 | if (!attr[IPSET_ATTR_SETNAME]) { | 1023 | if (!attr[IPSET_ATTR_SETNAME]) { |
| 1022 | for (i = 0; i < inst->ip_set_max; i++) { | 1024 | for (i = 0; i < inst->ip_set_max; i++) { |
| 1023 | s = nfnl_set(inst, i); | 1025 | s = ip_set(inst, i); |
| 1024 | if (s != NULL) | 1026 | if (s != NULL) |
| 1025 | ip_set_flush_set(s); | 1027 | ip_set_flush_set(s); |
| 1026 | } | 1028 | } |
| @@ -1074,7 +1076,7 @@ ip_set_rename(struct sock *ctnl, struct sk_buff *skb, | |||
| 1074 | 1076 | ||
| 1075 | name2 = nla_data(attr[IPSET_ATTR_SETNAME2]); | 1077 | name2 = nla_data(attr[IPSET_ATTR_SETNAME2]); |
| 1076 | for (i = 0; i < inst->ip_set_max; i++) { | 1078 | for (i = 0; i < inst->ip_set_max; i++) { |
| 1077 | s = nfnl_set(inst, i); | 1079 | s = ip_set(inst, i); |
| 1078 | if (s != NULL && STREQ(s->name, name2)) { | 1080 | if (s != NULL && STREQ(s->name, name2)) { |
| 1079 | ret = -IPSET_ERR_EXIST_SETNAME2; | 1081 | ret = -IPSET_ERR_EXIST_SETNAME2; |
| 1080 | goto out; | 1082 | goto out; |
| @@ -1134,8 +1136,8 @@ ip_set_swap(struct sock *ctnl, struct sk_buff *skb, | |||
| 1134 | 1136 | ||
| 1135 | write_lock_bh(&ip_set_ref_lock); | 1137 | write_lock_bh(&ip_set_ref_lock); |
| 1136 | swap(from->ref, to->ref); | 1138 | swap(from->ref, to->ref); |
| 1137 | nfnl_set(inst, from_id) = to; | 1139 | ip_set(inst, from_id) = to; |
| 1138 | nfnl_set(inst, to_id) = from; | 1140 | ip_set(inst, to_id) = from; |
| 1139 | write_unlock_bh(&ip_set_ref_lock); | 1141 | write_unlock_bh(&ip_set_ref_lock); |
| 1140 | 1142 | ||
| 1141 | return 0; | 1143 | return 0; |
| @@ -1157,7 +1159,7 @@ ip_set_dump_done(struct netlink_callback *cb) | |||
| 1157 | struct ip_set_net *inst = (struct ip_set_net *)cb->args[IPSET_CB_NET]; | 1159 | struct ip_set_net *inst = (struct ip_set_net *)cb->args[IPSET_CB_NET]; |
| 1158 | if (cb->args[IPSET_CB_ARG0]) { | 1160 | if (cb->args[IPSET_CB_ARG0]) { |
| 1159 | pr_debug("release set %s\n", | 1161 | pr_debug("release set %s\n", |
| 1160 | nfnl_set(inst, cb->args[IPSET_CB_INDEX])->name); | 1162 | ip_set(inst, cb->args[IPSET_CB_INDEX])->name); |
| 1161 | __ip_set_put_byindex(inst, | 1163 | __ip_set_put_byindex(inst, |
| 1162 | (ip_set_id_t) cb->args[IPSET_CB_INDEX]); | 1164 | (ip_set_id_t) cb->args[IPSET_CB_INDEX]); |
| 1163 | } | 1165 | } |
| @@ -1254,7 +1256,7 @@ dump_last: | |||
| 1254 | dump_type, dump_flags, cb->args[IPSET_CB_INDEX]); | 1256 | dump_type, dump_flags, cb->args[IPSET_CB_INDEX]); |
| 1255 | for (; cb->args[IPSET_CB_INDEX] < max; cb->args[IPSET_CB_INDEX]++) { | 1257 | for (; cb->args[IPSET_CB_INDEX] < max; cb->args[IPSET_CB_INDEX]++) { |
| 1256 | index = (ip_set_id_t) cb->args[IPSET_CB_INDEX]; | 1258 | index = (ip_set_id_t) cb->args[IPSET_CB_INDEX]; |
| 1257 | set = nfnl_set(inst, index); | 1259 | set = ip_set(inst, index); |
| 1258 | if (set == NULL) { | 1260 | if (set == NULL) { |
| 1259 | if (dump_type == DUMP_ONE) { | 1261 | if (dump_type == DUMP_ONE) { |
| 1260 | ret = -ENOENT; | 1262 | ret = -ENOENT; |
| @@ -1332,7 +1334,7 @@ next_set: | |||
| 1332 | release_refcount: | 1334 | release_refcount: |
| 1333 | /* If there was an error or set is done, release set */ | 1335 | /* If there was an error or set is done, release set */ |
| 1334 | if (ret || !cb->args[IPSET_CB_ARG0]) { | 1336 | if (ret || !cb->args[IPSET_CB_ARG0]) { |
| 1335 | pr_debug("release set %s\n", nfnl_set(inst, index)->name); | 1337 | pr_debug("release set %s\n", ip_set(inst, index)->name); |
| 1336 | __ip_set_put_byindex(inst, index); | 1338 | __ip_set_put_byindex(inst, index); |
| 1337 | cb->args[IPSET_CB_ARG0] = 0; | 1339 | cb->args[IPSET_CB_ARG0] = 0; |
| 1338 | } | 1340 | } |
| @@ -1887,7 +1889,7 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len) | |||
| 1887 | find_set_and_id(inst, req_get->set.name, &id); | 1889 | find_set_and_id(inst, req_get->set.name, &id); |
| 1888 | req_get->set.index = id; | 1890 | req_get->set.index = id; |
| 1889 | if (id != IPSET_INVALID_ID) | 1891 | if (id != IPSET_INVALID_ID) |
| 1890 | req_get->family = nfnl_set(inst, id)->family; | 1892 | req_get->family = ip_set(inst, id)->family; |
| 1891 | nfnl_unlock(NFNL_SUBSYS_IPSET); | 1893 | nfnl_unlock(NFNL_SUBSYS_IPSET); |
| 1892 | goto copy; | 1894 | goto copy; |
| 1893 | } | 1895 | } |
| @@ -1901,7 +1903,7 @@ ip_set_sockfn_get(struct sock *sk, int optval, void __user *user, int *len) | |||
| 1901 | goto done; | 1903 | goto done; |
| 1902 | } | 1904 | } |
| 1903 | nfnl_lock(NFNL_SUBSYS_IPSET); | 1905 | nfnl_lock(NFNL_SUBSYS_IPSET); |
| 1904 | set = nfnl_set(inst, req_get->set.index); | 1906 | set = ip_set(inst, req_get->set.index); |
| 1905 | strncpy(req_get->set.name, set ? set->name : "", | 1907 | strncpy(req_get->set.name, set ? set->name : "", |
| 1906 | IPSET_MAXNAMELEN); | 1908 | IPSET_MAXNAMELEN); |
| 1907 | nfnl_unlock(NFNL_SUBSYS_IPSET); | 1909 | nfnl_unlock(NFNL_SUBSYS_IPSET); |
| @@ -1945,7 +1947,6 @@ ip_set_net_init(struct net *net) | |||
| 1945 | return -ENOMEM; | 1947 | return -ENOMEM; |
| 1946 | inst->is_deleted = 0; | 1948 | inst->is_deleted = 0; |
| 1947 | rcu_assign_pointer(inst->ip_set_list, list); | 1949 | rcu_assign_pointer(inst->ip_set_list, list); |
| 1948 | pr_notice("ip_set: protocol %u\n", IPSET_PROTOCOL); | ||
| 1949 | return 0; | 1950 | return 0; |
| 1950 | } | 1951 | } |
| 1951 | 1952 | ||
| @@ -1960,7 +1961,7 @@ ip_set_net_exit(struct net *net) | |||
| 1960 | inst->is_deleted = 1; /* flag for ip_set_nfnl_put */ | 1961 | inst->is_deleted = 1; /* flag for ip_set_nfnl_put */ |
| 1961 | 1962 | ||
| 1962 | for (i = 0; i < inst->ip_set_max; i++) { | 1963 | for (i = 0; i < inst->ip_set_max; i++) { |
| 1963 | set = nfnl_set(inst, i); | 1964 | set = ip_set(inst, i); |
| 1964 | if (set != NULL) | 1965 | if (set != NULL) |
| 1965 | ip_set_destroy_set(inst, i); | 1966 | ip_set_destroy_set(inst, i); |
| 1966 | } | 1967 | } |
| @@ -1996,6 +1997,7 @@ ip_set_init(void) | |||
| 1996 | nfnetlink_subsys_unregister(&ip_set_netlink_subsys); | 1997 | nfnetlink_subsys_unregister(&ip_set_netlink_subsys); |
| 1997 | return ret; | 1998 | return ret; |
| 1998 | } | 1999 | } |
| 2000 | pr_info("ip_set: protocol %u\n", IPSET_PROTOCOL); | ||
| 1999 | return 0; | 2001 | return 0; |
| 2000 | } | 2002 | } |
| 2001 | 2003 | ||
diff --git a/net/netfilter/ipset/ip_set_hash_gen.h b/net/netfilter/ipset/ip_set_hash_gen.h index be6932ad3a86..61c7fb052802 100644 --- a/net/netfilter/ipset/ip_set_hash_gen.h +++ b/net/netfilter/ipset/ip_set_hash_gen.h | |||
| @@ -263,6 +263,9 @@ struct htype { | |||
| 263 | u32 maxelem; /* max elements in the hash */ | 263 | u32 maxelem; /* max elements in the hash */ |
| 264 | u32 elements; /* current element (vs timeout) */ | 264 | u32 elements; /* current element (vs timeout) */ |
| 265 | u32 initval; /* random jhash init value */ | 265 | u32 initval; /* random jhash init value */ |
| 266 | #ifdef IP_SET_HASH_WITH_MARKMASK | ||
| 267 | u32 markmask; /* markmask value for mark mask to store */ | ||
| 268 | #endif | ||
| 266 | struct timer_list gc; /* garbage collection when timeout enabled */ | 269 | struct timer_list gc; /* garbage collection when timeout enabled */ |
| 267 | struct mtype_elem next; /* temporary storage for uadd */ | 270 | struct mtype_elem next; /* temporary storage for uadd */ |
| 268 | #ifdef IP_SET_HASH_WITH_MULTI | 271 | #ifdef IP_SET_HASH_WITH_MULTI |
| @@ -454,6 +457,9 @@ mtype_same_set(const struct ip_set *a, const struct ip_set *b) | |||
| 454 | #ifdef IP_SET_HASH_WITH_NETMASK | 457 | #ifdef IP_SET_HASH_WITH_NETMASK |
| 455 | x->netmask == y->netmask && | 458 | x->netmask == y->netmask && |
| 456 | #endif | 459 | #endif |
| 460 | #ifdef IP_SET_HASH_WITH_MARKMASK | ||
| 461 | x->markmask == y->markmask && | ||
| 462 | #endif | ||
| 457 | a->extensions == b->extensions; | 463 | a->extensions == b->extensions; |
| 458 | } | 464 | } |
| 459 | 465 | ||
| @@ -627,6 +633,18 @@ mtype_add(struct ip_set *set, void *value, const struct ip_set_ext *ext, | |||
| 627 | bool flag_exist = flags & IPSET_FLAG_EXIST; | 633 | bool flag_exist = flags & IPSET_FLAG_EXIST; |
| 628 | u32 key, multi = 0; | 634 | u32 key, multi = 0; |
| 629 | 635 | ||
| 636 | if (h->elements >= h->maxelem && SET_WITH_FORCEADD(set)) { | ||
| 637 | rcu_read_lock_bh(); | ||
| 638 | t = rcu_dereference_bh(h->table); | ||
| 639 | key = HKEY(value, h->initval, t->htable_bits); | ||
| 640 | n = hbucket(t,key); | ||
| 641 | if (n->pos) { | ||
| 642 | /* Choosing the first entry in the array to replace */ | ||
| 643 | j = 0; | ||
| 644 | goto reuse_slot; | ||
| 645 | } | ||
| 646 | rcu_read_unlock_bh(); | ||
| 647 | } | ||
| 630 | if (SET_WITH_TIMEOUT(set) && h->elements >= h->maxelem) | 648 | if (SET_WITH_TIMEOUT(set) && h->elements >= h->maxelem) |
| 631 | /* FIXME: when set is full, we slow down here */ | 649 | /* FIXME: when set is full, we slow down here */ |
| 632 | mtype_expire(set, h, NLEN(set->family), set->dsize); | 650 | mtype_expire(set, h, NLEN(set->family), set->dsize); |
| @@ -908,6 +926,10 @@ mtype_head(struct ip_set *set, struct sk_buff *skb) | |||
| 908 | nla_put_u8(skb, IPSET_ATTR_NETMASK, h->netmask)) | 926 | nla_put_u8(skb, IPSET_ATTR_NETMASK, h->netmask)) |
| 909 | goto nla_put_failure; | 927 | goto nla_put_failure; |
| 910 | #endif | 928 | #endif |
| 929 | #ifdef IP_SET_HASH_WITH_MARKMASK | ||
| 930 | if (nla_put_u32(skb, IPSET_ATTR_MARKMASK, h->markmask)) | ||
| 931 | goto nla_put_failure; | ||
| 932 | #endif | ||
| 911 | if (nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)) || | 933 | if (nla_put_net32(skb, IPSET_ATTR_REFERENCES, htonl(set->ref - 1)) || |
| 912 | nla_put_net32(skb, IPSET_ATTR_MEMSIZE, htonl(memsize))) | 934 | nla_put_net32(skb, IPSET_ATTR_MEMSIZE, htonl(memsize))) |
| 913 | goto nla_put_failure; | 935 | goto nla_put_failure; |
| @@ -1016,6 +1038,9 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set, | |||
| 1016 | struct nlattr *tb[], u32 flags) | 1038 | struct nlattr *tb[], u32 flags) |
| 1017 | { | 1039 | { |
| 1018 | u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; | 1040 | u32 hashsize = IPSET_DEFAULT_HASHSIZE, maxelem = IPSET_DEFAULT_MAXELEM; |
| 1041 | #ifdef IP_SET_HASH_WITH_MARKMASK | ||
| 1042 | u32 markmask; | ||
| 1043 | #endif | ||
| 1019 | u8 hbits; | 1044 | u8 hbits; |
| 1020 | #ifdef IP_SET_HASH_WITH_NETMASK | 1045 | #ifdef IP_SET_HASH_WITH_NETMASK |
| 1021 | u8 netmask; | 1046 | u8 netmask; |
| @@ -1026,6 +1051,10 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set, | |||
| 1026 | 1051 | ||
| 1027 | if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) | 1052 | if (!(set->family == NFPROTO_IPV4 || set->family == NFPROTO_IPV6)) |
| 1028 | return -IPSET_ERR_INVALID_FAMILY; | 1053 | return -IPSET_ERR_INVALID_FAMILY; |
| 1054 | |||
| 1055 | #ifdef IP_SET_HASH_WITH_MARKMASK | ||
| 1056 | markmask = 0xffffffff; | ||
| 1057 | #endif | ||
| 1029 | #ifdef IP_SET_HASH_WITH_NETMASK | 1058 | #ifdef IP_SET_HASH_WITH_NETMASK |
| 1030 | netmask = set->family == NFPROTO_IPV4 ? 32 : 128; | 1059 | netmask = set->family == NFPROTO_IPV4 ? 32 : 128; |
| 1031 | pr_debug("Create set %s with family %s\n", | 1060 | pr_debug("Create set %s with family %s\n", |
| @@ -1034,6 +1063,9 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set, | |||
| 1034 | 1063 | ||
| 1035 | if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) || | 1064 | if (unlikely(!ip_set_optattr_netorder(tb, IPSET_ATTR_HASHSIZE) || |
| 1036 | !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) || | 1065 | !ip_set_optattr_netorder(tb, IPSET_ATTR_MAXELEM) || |
| 1066 | #ifdef IP_SET_HASH_WITH_MARKMASK | ||
| 1067 | !ip_set_optattr_netorder(tb, IPSET_ATTR_MARKMASK) || | ||
| 1068 | #endif | ||
| 1037 | !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || | 1069 | !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || |
| 1038 | !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) | 1070 | !ip_set_optattr_netorder(tb, IPSET_ATTR_CADT_FLAGS))) |
| 1039 | return -IPSET_ERR_PROTOCOL; | 1071 | return -IPSET_ERR_PROTOCOL; |
| @@ -1057,6 +1089,14 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set, | |||
| 1057 | return -IPSET_ERR_INVALID_NETMASK; | 1089 | return -IPSET_ERR_INVALID_NETMASK; |
| 1058 | } | 1090 | } |
| 1059 | #endif | 1091 | #endif |
| 1092 | #ifdef IP_SET_HASH_WITH_MARKMASK | ||
| 1093 | if (tb[IPSET_ATTR_MARKMASK]) { | ||
| 1094 | markmask = ntohl(nla_get_u32(tb[IPSET_ATTR_MARKMASK])); | ||
| 1095 | |||
| 1096 | if ((markmask > 4294967295u) || markmask == 0) | ||
| 1097 | return -IPSET_ERR_INVALID_MARKMASK; | ||
| 1098 | } | ||
| 1099 | #endif | ||
| 1060 | 1100 | ||
| 1061 | hsize = sizeof(*h); | 1101 | hsize = sizeof(*h); |
| 1062 | #ifdef IP_SET_HASH_WITH_NETS | 1102 | #ifdef IP_SET_HASH_WITH_NETS |
| @@ -1071,6 +1111,9 @@ IPSET_TOKEN(HTYPE, _create)(struct net *net, struct ip_set *set, | |||
| 1071 | #ifdef IP_SET_HASH_WITH_NETMASK | 1111 | #ifdef IP_SET_HASH_WITH_NETMASK |
| 1072 | h->netmask = netmask; | 1112 | h->netmask = netmask; |
| 1073 | #endif | 1113 | #endif |
| 1114 | #ifdef IP_SET_HASH_WITH_MARKMASK | ||
| 1115 | h->markmask = markmask; | ||
| 1116 | #endif | ||
| 1074 | get_random_bytes(&h->initval, sizeof(h->initval)); | 1117 | get_random_bytes(&h->initval, sizeof(h->initval)); |
| 1075 | set->timeout = IPSET_NO_TIMEOUT; | 1118 | set->timeout = IPSET_NO_TIMEOUT; |
| 1076 | 1119 | ||
diff --git a/net/netfilter/ipset/ip_set_hash_ip.c b/net/netfilter/ipset/ip_set_hash_ip.c index e65fc2423d56..dd40607f878e 100644 --- a/net/netfilter/ipset/ip_set_hash_ip.c +++ b/net/netfilter/ipset/ip_set_hash_ip.c | |||
| @@ -25,7 +25,8 @@ | |||
| 25 | 25 | ||
| 26 | #define IPSET_TYPE_REV_MIN 0 | 26 | #define IPSET_TYPE_REV_MIN 0 |
| 27 | /* 1 Counters support */ | 27 | /* 1 Counters support */ |
| 28 | #define IPSET_TYPE_REV_MAX 2 /* Comments support */ | 28 | /* 2 Comments support */ |
| 29 | #define IPSET_TYPE_REV_MAX 3 /* Forceadd support */ | ||
| 29 | 30 | ||
| 30 | MODULE_LICENSE("GPL"); | 31 | MODULE_LICENSE("GPL"); |
| 31 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); | 32 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); |
diff --git a/net/netfilter/ipset/ip_set_hash_ipmark.c b/net/netfilter/ipset/ip_set_hash_ipmark.c new file mode 100644 index 000000000000..4eff0a297254 --- /dev/null +++ b/net/netfilter/ipset/ip_set_hash_ipmark.c | |||
| @@ -0,0 +1,321 @@ | |||
| 1 | /* Copyright (C) 2003-2013 Jozsef Kadlecsik <kadlec@blackhole.kfki.hu> | ||
| 2 | * Copyright (C) 2013 Smoothwall Ltd. <vytas.dauksa@smoothwall.net> | ||
| 3 | * | ||
| 4 | * This program is free software; you can redistribute it and/or modify | ||
| 5 | * it under the terms of the GNU General Public License version 2 as | ||
| 6 | * published by the Free Software Foundation. | ||
| 7 | */ | ||
| 8 | |||
| 9 | /* Kernel module implementing an IP set type: the hash:ip,mark type */ | ||
| 10 | |||
| 11 | #include <linux/jhash.h> | ||
| 12 | #include <linux/module.h> | ||
| 13 | #include <linux/ip.h> | ||
| 14 | #include <linux/skbuff.h> | ||
| 15 | #include <linux/errno.h> | ||
| 16 | #include <linux/random.h> | ||
| 17 | #include <net/ip.h> | ||
| 18 | #include <net/ipv6.h> | ||
| 19 | #include <net/netlink.h> | ||
| 20 | #include <net/tcp.h> | ||
| 21 | |||
| 22 | #include <linux/netfilter.h> | ||
| 23 | #include <linux/netfilter/ipset/pfxlen.h> | ||
| 24 | #include <linux/netfilter/ipset/ip_set.h> | ||
| 25 | #include <linux/netfilter/ipset/ip_set_hash.h> | ||
| 26 | |||
| 27 | #define IPSET_TYPE_REV_MIN 0 | ||
| 28 | #define IPSET_TYPE_REV_MAX 1 /* Forceadd support */ | ||
| 29 | |||
| 30 | MODULE_LICENSE("GPL"); | ||
| 31 | MODULE_AUTHOR("Vytas Dauksa <vytas.dauksa@smoothwall.net>"); | ||
| 32 | IP_SET_MODULE_DESC("hash:ip,mark", IPSET_TYPE_REV_MIN, IPSET_TYPE_REV_MAX); | ||
| 33 | MODULE_ALIAS("ip_set_hash:ip,mark"); | ||
| 34 | |||
| 35 | /* Type specific function prefix */ | ||
| 36 | #define HTYPE hash_ipmark | ||
| 37 | #define IP_SET_HASH_WITH_MARKMASK | ||
| 38 | |||
| 39 | /* IPv4 variant */ | ||
| 40 | |||
| 41 | /* Member elements */ | ||
| 42 | struct hash_ipmark4_elem { | ||
| 43 | __be32 ip; | ||
| 44 | __u32 mark; | ||
| 45 | }; | ||
| 46 | |||
| 47 | /* Common functions */ | ||
| 48 | |||
| 49 | static inline bool | ||
| 50 | hash_ipmark4_data_equal(const struct hash_ipmark4_elem *ip1, | ||
| 51 | const struct hash_ipmark4_elem *ip2, | ||
| 52 | u32 *multi) | ||
| 53 | { | ||
| 54 | return ip1->ip == ip2->ip && | ||
| 55 | ip1->mark == ip2->mark; | ||
| 56 | } | ||
| 57 | |||
| 58 | static bool | ||
| 59 | hash_ipmark4_data_list(struct sk_buff *skb, | ||
| 60 | const struct hash_ipmark4_elem *data) | ||
| 61 | { | ||
| 62 | if (nla_put_ipaddr4(skb, IPSET_ATTR_IP, data->ip) || | ||
| 63 | nla_put_net32(skb, IPSET_ATTR_MARK, htonl(data->mark))) | ||
| 64 | goto nla_put_failure; | ||
| 65 | return 0; | ||
| 66 | |||
| 67 | nla_put_failure: | ||
| 68 | return 1; | ||
| 69 | } | ||
| 70 | |||
| 71 | static inline void | ||
| 72 | hash_ipmark4_data_next(struct hash_ipmark4_elem *next, | ||
| 73 | const struct hash_ipmark4_elem *d) | ||
| 74 | { | ||
| 75 | next->ip = d->ip; | ||
| 76 | } | ||
| 77 | |||
| 78 | #define MTYPE hash_ipmark4 | ||
| 79 | #define PF 4 | ||
| 80 | #define HOST_MASK 32 | ||
| 81 | #define HKEY_DATALEN sizeof(struct hash_ipmark4_elem) | ||
| 82 | #include "ip_set_hash_gen.h" | ||
| 83 | |||
| 84 | static int | ||
| 85 | hash_ipmark4_kadt(struct ip_set *set, const struct sk_buff *skb, | ||
| 86 | const struct xt_action_param *par, | ||
| 87 | enum ipset_adt adt, struct ip_set_adt_opt *opt) | ||
| 88 | { | ||
| 89 | const struct hash_ipmark *h = set->data; | ||
| 90 | ipset_adtfn adtfn = set->variant->adt[adt]; | ||
| 91 | struct hash_ipmark4_elem e = { }; | ||
| 92 | struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); | ||
| 93 | |||
| 94 | e.mark = skb->mark; | ||
| 95 | e.mark &= h->markmask; | ||
| 96 | |||
| 97 | ip4addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip); | ||
| 98 | return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); | ||
| 99 | } | ||
| 100 | |||
| 101 | static int | ||
| 102 | hash_ipmark4_uadt(struct ip_set *set, struct nlattr *tb[], | ||
| 103 | enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) | ||
| 104 | { | ||
| 105 | const struct hash_ipmark *h = set->data; | ||
| 106 | ipset_adtfn adtfn = set->variant->adt[adt]; | ||
| 107 | struct hash_ipmark4_elem e = { }; | ||
| 108 | struct ip_set_ext ext = IP_SET_INIT_UEXT(set); | ||
| 109 | u32 ip, ip_to = 0; | ||
| 110 | int ret; | ||
| 111 | |||
| 112 | if (unlikely(!tb[IPSET_ATTR_IP] || | ||
| 113 | !ip_set_attr_netorder(tb, IPSET_ATTR_MARK) || | ||
| 114 | !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || | ||
| 115 | !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || | ||
| 116 | !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES))) | ||
| 117 | return -IPSET_ERR_PROTOCOL; | ||
| 118 | |||
| 119 | if (tb[IPSET_ATTR_LINENO]) | ||
| 120 | *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); | ||
| 121 | |||
| 122 | ret = ip_set_get_ipaddr4(tb[IPSET_ATTR_IP], &e.ip) || | ||
| 123 | ip_set_get_extensions(set, tb, &ext); | ||
| 124 | if (ret) | ||
| 125 | return ret; | ||
| 126 | |||
| 127 | e.mark = ntohl(nla_get_u32(tb[IPSET_ATTR_MARK])); | ||
| 128 | e.mark &= h->markmask; | ||
| 129 | |||
| 130 | if (adt == IPSET_TEST || | ||
| 131 | !(tb[IPSET_ATTR_IP_TO] || tb[IPSET_ATTR_CIDR])) { | ||
| 132 | ret = adtfn(set, &e, &ext, &ext, flags); | ||
| 133 | return ip_set_eexist(ret, flags) ? 0 : ret; | ||
| 134 | } | ||
| 135 | |||
| 136 | ip_to = ip = ntohl(e.ip); | ||
| 137 | if (tb[IPSET_ATTR_IP_TO]) { | ||
| 138 | ret = ip_set_get_hostipaddr4(tb[IPSET_ATTR_IP_TO], &ip_to); | ||
| 139 | if (ret) | ||
| 140 | return ret; | ||
| 141 | if (ip > ip_to) | ||
| 142 | swap(ip, ip_to); | ||
| 143 | } else if (tb[IPSET_ATTR_CIDR]) { | ||
| 144 | u8 cidr = nla_get_u8(tb[IPSET_ATTR_CIDR]); | ||
| 145 | |||
| 146 | if (!cidr || cidr > 32) | ||
| 147 | return -IPSET_ERR_INVALID_CIDR; | ||
| 148 | ip_set_mask_from_to(ip, ip_to, cidr); | ||
| 149 | } | ||
| 150 | |||
| 151 | if (retried) | ||
| 152 | ip = ntohl(h->next.ip); | ||
| 153 | for (; !before(ip_to, ip); ip++) { | ||
| 154 | e.ip = htonl(ip); | ||
| 155 | ret = adtfn(set, &e, &ext, &ext, flags); | ||
| 156 | |||
| 157 | if (ret && !ip_set_eexist(ret, flags)) | ||
| 158 | return ret; | ||
| 159 | else | ||
| 160 | ret = 0; | ||
| 161 | } | ||
| 162 | return ret; | ||
| 163 | } | ||
| 164 | |||
| 165 | /* IPv6 variant */ | ||
| 166 | |||
| 167 | struct hash_ipmark6_elem { | ||
| 168 | union nf_inet_addr ip; | ||
| 169 | __u32 mark; | ||
| 170 | }; | ||
| 171 | |||
| 172 | /* Common functions */ | ||
| 173 | |||
| 174 | static inline bool | ||
| 175 | hash_ipmark6_data_equal(const struct hash_ipmark6_elem *ip1, | ||
| 176 | const struct hash_ipmark6_elem *ip2, | ||
| 177 | u32 *multi) | ||
| 178 | { | ||
| 179 | return ipv6_addr_equal(&ip1->ip.in6, &ip2->ip.in6) && | ||
| 180 | ip1->mark == ip2->mark; | ||
| 181 | } | ||
| 182 | |||
| 183 | static bool | ||
| 184 | hash_ipmark6_data_list(struct sk_buff *skb, | ||
| 185 | const struct hash_ipmark6_elem *data) | ||
| 186 | { | ||
| 187 | if (nla_put_ipaddr6(skb, IPSET_ATTR_IP, &data->ip.in6) || | ||
| 188 | nla_put_net32(skb, IPSET_ATTR_MARK, htonl(data->mark))) | ||
| 189 | goto nla_put_failure; | ||
| 190 | return 0; | ||
| 191 | |||
| 192 | nla_put_failure: | ||
| 193 | return 1; | ||
| 194 | } | ||
| 195 | |||
| 196 | static inline void | ||
| 197 | hash_ipmark6_data_next(struct hash_ipmark4_elem *next, | ||
| 198 | const struct hash_ipmark6_elem *d) | ||
| 199 | { | ||
| 200 | } | ||
| 201 | |||
| 202 | #undef MTYPE | ||
| 203 | #undef PF | ||
| 204 | #undef HOST_MASK | ||
| 205 | #undef HKEY_DATALEN | ||
| 206 | |||
| 207 | #define MTYPE hash_ipmark6 | ||
| 208 | #define PF 6 | ||
| 209 | #define HOST_MASK 128 | ||
| 210 | #define HKEY_DATALEN sizeof(struct hash_ipmark6_elem) | ||
| 211 | #define IP_SET_EMIT_CREATE | ||
| 212 | #include "ip_set_hash_gen.h" | ||
| 213 | |||
| 214 | |||
| 215 | static int | ||
| 216 | hash_ipmark6_kadt(struct ip_set *set, const struct sk_buff *skb, | ||
| 217 | const struct xt_action_param *par, | ||
| 218 | enum ipset_adt adt, struct ip_set_adt_opt *opt) | ||
| 219 | { | ||
| 220 | const struct hash_ipmark *h = set->data; | ||
| 221 | ipset_adtfn adtfn = set->variant->adt[adt]; | ||
| 222 | struct hash_ipmark6_elem e = { }; | ||
| 223 | struct ip_set_ext ext = IP_SET_INIT_KEXT(skb, opt, set); | ||
| 224 | |||
| 225 | e.mark = skb->mark; | ||
| 226 | e.mark &= h->markmask; | ||
| 227 | |||
| 228 | ip6addrptr(skb, opt->flags & IPSET_DIM_ONE_SRC, &e.ip.in6); | ||
| 229 | return adtfn(set, &e, &ext, &opt->ext, opt->cmdflags); | ||
| 230 | } | ||
| 231 | |||
| 232 | static int | ||
| 233 | hash_ipmark6_uadt(struct ip_set *set, struct nlattr *tb[], | ||
| 234 | enum ipset_adt adt, u32 *lineno, u32 flags, bool retried) | ||
| 235 | { | ||
| 236 | const struct hash_ipmark *h = set->data; | ||
| 237 | ipset_adtfn adtfn = set->variant->adt[adt]; | ||
| 238 | struct hash_ipmark6_elem e = { }; | ||
| 239 | struct ip_set_ext ext = IP_SET_INIT_UEXT(set); | ||
| 240 | int ret; | ||
| 241 | |||
| 242 | if (unlikely(!tb[IPSET_ATTR_IP] || | ||
| 243 | !ip_set_attr_netorder(tb, IPSET_ATTR_MARK) || | ||
| 244 | !ip_set_optattr_netorder(tb, IPSET_ATTR_TIMEOUT) || | ||
| 245 | !ip_set_optattr_netorder(tb, IPSET_ATTR_PACKETS) || | ||
| 246 | !ip_set_optattr_netorder(tb, IPSET_ATTR_BYTES) || | ||
| 247 | tb[IPSET_ATTR_IP_TO] || | ||
| 248 | tb[IPSET_ATTR_CIDR])) | ||
| 249 | return -IPSET_ERR_PROTOCOL; | ||
| 250 | |||
| 251 | if (tb[IPSET_ATTR_LINENO]) | ||
| 252 | *lineno = nla_get_u32(tb[IPSET_ATTR_LINENO]); | ||
| 253 | |||
| 254 | ret = ip_set_get_ipaddr6(tb[IPSET_ATTR_IP], &e.ip) || | ||
| 255 | ip_set_get_extensions(set, tb, &ext); | ||
| 256 | if (ret) | ||
| 257 | return ret; | ||
| 258 | |||
| 259 | e.mark = ntohl(nla_get_u32(tb[IPSET_ATTR_MARK])); | ||
| 260 | e.mark &= h->markmask; | ||
| 261 | |||
| 262 | if (adt == IPSET_TEST) { | ||
| 263 | ret = adtfn(set, &e, &ext, &ext, flags); | ||
| 264 | return ip_set_eexist(ret, flags) ? 0 : ret; | ||
| 265 | } | ||
| 266 | |||
| 267 | ret = adtfn(set, &e, &ext, &ext, flags); | ||
| 268 | if (ret && !ip_set_eexist(ret, flags)) | ||
| 269 | return ret; | ||
| 270 | else | ||
| 271 | ret = 0; | ||
| 272 | |||
| 273 | return ret; | ||
| 274 | } | ||
| 275 | |||
| 276 | static struct ip_set_type hash_ipmark_type __read_mostly = { | ||
| 277 | .name = "hash:ip,mark", | ||
| 278 | .protocol = IPSET_PROTOCOL, | ||
| 279 | .features = IPSET_TYPE_IP | IPSET_TYPE_MARK, | ||
| 280 | .dimension = IPSET_DIM_TWO, | ||
| 281 | .family = NFPROTO_UNSPEC, | ||
| 282 | .revision_min = IPSET_TYPE_REV_MIN, | ||
| 283 | .revision_max = IPSET_TYPE_REV_MAX, | ||
| 284 | .create = hash_ipmark_create, | ||
| 285 | .create_policy = { | ||
| 286 | [IPSET_ATTR_MARKMASK] = { .type = NLA_U32 }, | ||
| 287 | [IPSET_ATTR_HASHSIZE] = { .type = NLA_U32 }, | ||
| 288 | [IPSET_ATTR_MAXELEM] = { .type = NLA_U32 }, | ||
| 289 | [IPSET_ATTR_PROBES] = { .type = NLA_U8 }, | ||
| 290 | [IPSET_ATTR_RESIZE] = { .type = NLA_U8 }, | ||
| 291 | [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, | ||
| 292 | [IPSET_ATTR_CADT_FLAGS] = { .type = NLA_U32 }, | ||
| 293 | }, | ||
| 294 | .adt_policy = { | ||
| 295 | [IPSET_ATTR_IP] = { .type = NLA_NESTED }, | ||
| 296 | [IPSET_ATTR_IP_TO] = { .type = NLA_NESTED }, | ||
| 297 | [IPSET_ATTR_MARK] = { .type = NLA_U32 }, | ||
| 298 | [IPSET_ATTR_CIDR] = { .type = NLA_U8 }, | ||
| 299 | [IPSET_ATTR_TIMEOUT] = { .type = NLA_U32 }, | ||
| 300 | [IPSET_ATTR_LINENO] = { .type = NLA_U32 }, | ||
| 301 | [IPSET_ATTR_BYTES] = { .type = NLA_U64 }, | ||
| 302 | [IPSET_ATTR_PACKETS] = { .type = NLA_U64 }, | ||
| 303 | [IPSET_ATTR_COMMENT] = { .type = NLA_NUL_STRING }, | ||
| 304 | }, | ||
| 305 | .me = THIS_MODULE, | ||
| 306 | }; | ||
| 307 | |||
| 308 | static int __init | ||
| 309 | hash_ipmark_init(void) | ||
| 310 | { | ||
| 311 | return ip_set_type_register(&hash_ipmark_type); | ||
| 312 | } | ||
| 313 | |||
| 314 | static void __exit | ||
| 315 | hash_ipmark_fini(void) | ||
| 316 | { | ||
| 317 | ip_set_type_unregister(&hash_ipmark_type); | ||
| 318 | } | ||
| 319 | |||
| 320 | module_init(hash_ipmark_init); | ||
| 321 | module_exit(hash_ipmark_fini); | ||
diff --git a/net/netfilter/ipset/ip_set_hash_ipport.c b/net/netfilter/ipset/ip_set_hash_ipport.c index 525a595dd1fe..7597b82a8b03 100644 --- a/net/netfilter/ipset/ip_set_hash_ipport.c +++ b/net/netfilter/ipset/ip_set_hash_ipport.c | |||
| @@ -27,7 +27,8 @@ | |||
| 27 | #define IPSET_TYPE_REV_MIN 0 | 27 | #define IPSET_TYPE_REV_MIN 0 |
| 28 | /* 1 SCTP and UDPLITE support added */ | 28 | /* 1 SCTP and UDPLITE support added */ |
| 29 | /* 2 Counters support added */ | 29 | /* 2 Counters support added */ |
| 30 | #define IPSET_TYPE_REV_MAX 3 /* Comments support added */ | 30 | /* 3 Comments support added */ |
| 31 | #define IPSET_TYPE_REV_MAX 4 /* Forceadd support added */ | ||
| 31 | 32 | ||
| 32 | MODULE_LICENSE("GPL"); | 33 | MODULE_LICENSE("GPL"); |
| 33 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); | 34 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); |
diff --git a/net/netfilter/ipset/ip_set_hash_ipportip.c b/net/netfilter/ipset/ip_set_hash_ipportip.c index f5636631466e..672655ffd573 100644 --- a/net/netfilter/ipset/ip_set_hash_ipportip.c +++ b/net/netfilter/ipset/ip_set_hash_ipportip.c | |||
| @@ -27,7 +27,8 @@ | |||
| 27 | #define IPSET_TYPE_REV_MIN 0 | 27 | #define IPSET_TYPE_REV_MIN 0 |
| 28 | /* 1 SCTP and UDPLITE support added */ | 28 | /* 1 SCTP and UDPLITE support added */ |
| 29 | /* 2 Counters support added */ | 29 | /* 2 Counters support added */ |
| 30 | #define IPSET_TYPE_REV_MAX 3 /* Comments support added */ | 30 | /* 3 Comments support added */ |
| 31 | #define IPSET_TYPE_REV_MAX 4 /* Forceadd support added */ | ||
| 31 | 32 | ||
| 32 | MODULE_LICENSE("GPL"); | 33 | MODULE_LICENSE("GPL"); |
| 33 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); | 34 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); |
diff --git a/net/netfilter/ipset/ip_set_hash_ipportnet.c b/net/netfilter/ipset/ip_set_hash_ipportnet.c index 5d87fe8a41ff..7308d84f9277 100644 --- a/net/netfilter/ipset/ip_set_hash_ipportnet.c +++ b/net/netfilter/ipset/ip_set_hash_ipportnet.c | |||
| @@ -29,7 +29,8 @@ | |||
| 29 | /* 2 Range as input support for IPv4 added */ | 29 | /* 2 Range as input support for IPv4 added */ |
| 30 | /* 3 nomatch flag support added */ | 30 | /* 3 nomatch flag support added */ |
| 31 | /* 4 Counters support added */ | 31 | /* 4 Counters support added */ |
| 32 | #define IPSET_TYPE_REV_MAX 5 /* Comments support added */ | 32 | /* 5 Comments support added */ |
| 33 | #define IPSET_TYPE_REV_MAX 6 /* Forceadd support added */ | ||
| 33 | 34 | ||
| 34 | MODULE_LICENSE("GPL"); | 35 | MODULE_LICENSE("GPL"); |
| 35 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); | 36 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); |
diff --git a/net/netfilter/ipset/ip_set_hash_net.c b/net/netfilter/ipset/ip_set_hash_net.c index 8295cf4f9fdc..4c7d495783a3 100644 --- a/net/netfilter/ipset/ip_set_hash_net.c +++ b/net/netfilter/ipset/ip_set_hash_net.c | |||
| @@ -26,7 +26,8 @@ | |||
| 26 | /* 1 Range as input support for IPv4 added */ | 26 | /* 1 Range as input support for IPv4 added */ |
| 27 | /* 2 nomatch flag support added */ | 27 | /* 2 nomatch flag support added */ |
| 28 | /* 3 Counters support added */ | 28 | /* 3 Counters support added */ |
| 29 | #define IPSET_TYPE_REV_MAX 4 /* Comments support added */ | 29 | /* 4 Comments support added */ |
| 30 | #define IPSET_TYPE_REV_MAX 5 /* Forceadd support added */ | ||
| 30 | 31 | ||
| 31 | MODULE_LICENSE("GPL"); | 32 | MODULE_LICENSE("GPL"); |
| 32 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); | 33 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); |
diff --git a/net/netfilter/ipset/ip_set_hash_netiface.c b/net/netfilter/ipset/ip_set_hash_netiface.c index b827a0f1f351..db2606805b35 100644 --- a/net/netfilter/ipset/ip_set_hash_netiface.c +++ b/net/netfilter/ipset/ip_set_hash_netiface.c | |||
| @@ -27,7 +27,8 @@ | |||
| 27 | /* 1 nomatch flag support added */ | 27 | /* 1 nomatch flag support added */ |
| 28 | /* 2 /0 support added */ | 28 | /* 2 /0 support added */ |
| 29 | /* 3 Counters support added */ | 29 | /* 3 Counters support added */ |
| 30 | #define IPSET_TYPE_REV_MAX 4 /* Comments support added */ | 30 | /* 4 Comments support added */ |
| 31 | #define IPSET_TYPE_REV_MAX 5 /* Forceadd support added */ | ||
| 31 | 32 | ||
| 32 | MODULE_LICENSE("GPL"); | 33 | MODULE_LICENSE("GPL"); |
| 33 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); | 34 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); |
diff --git a/net/netfilter/ipset/ip_set_hash_netnet.c b/net/netfilter/ipset/ip_set_hash_netnet.c index 6226803fc490..3e99987e4bf2 100644 --- a/net/netfilter/ipset/ip_set_hash_netnet.c +++ b/net/netfilter/ipset/ip_set_hash_netnet.c | |||
| @@ -24,7 +24,7 @@ | |||
| 24 | #include <linux/netfilter/ipset/ip_set_hash.h> | 24 | #include <linux/netfilter/ipset/ip_set_hash.h> |
| 25 | 25 | ||
| 26 | #define IPSET_TYPE_REV_MIN 0 | 26 | #define IPSET_TYPE_REV_MIN 0 |
| 27 | #define IPSET_TYPE_REV_MAX 0 | 27 | #define IPSET_TYPE_REV_MAX 1 /* Forceadd support added */ |
| 28 | 28 | ||
| 29 | MODULE_LICENSE("GPL"); | 29 | MODULE_LICENSE("GPL"); |
| 30 | MODULE_AUTHOR("Oliver Smith <oliver@8.c.9.b.0.7.4.0.1.0.0.2.ip6.arpa>"); | 30 | MODULE_AUTHOR("Oliver Smith <oliver@8.c.9.b.0.7.4.0.1.0.0.2.ip6.arpa>"); |
| @@ -112,10 +112,10 @@ hash_netnet4_data_list(struct sk_buff *skb, | |||
| 112 | (flags && | 112 | (flags && |
| 113 | nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) | 113 | nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) |
| 114 | goto nla_put_failure; | 114 | goto nla_put_failure; |
| 115 | return 0; | 115 | return false; |
| 116 | 116 | ||
| 117 | nla_put_failure: | 117 | nla_put_failure: |
| 118 | return 1; | 118 | return true; |
| 119 | } | 119 | } |
| 120 | 120 | ||
| 121 | static inline void | 121 | static inline void |
| @@ -334,10 +334,10 @@ hash_netnet6_data_list(struct sk_buff *skb, | |||
| 334 | (flags && | 334 | (flags && |
| 335 | nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) | 335 | nla_put_net32(skb, IPSET_ATTR_CADT_FLAGS, htonl(flags)))) |
| 336 | goto nla_put_failure; | 336 | goto nla_put_failure; |
| 337 | return 0; | 337 | return false; |
| 338 | 338 | ||
| 339 | nla_put_failure: | 339 | nla_put_failure: |
| 340 | return 1; | 340 | return true; |
| 341 | } | 341 | } |
| 342 | 342 | ||
| 343 | static inline void | 343 | static inline void |
diff --git a/net/netfilter/ipset/ip_set_hash_netport.c b/net/netfilter/ipset/ip_set_hash_netport.c index 7097fb0141bf..1c645fbd09c7 100644 --- a/net/netfilter/ipset/ip_set_hash_netport.c +++ b/net/netfilter/ipset/ip_set_hash_netport.c | |||
| @@ -28,7 +28,8 @@ | |||
| 28 | /* 2 Range as input support for IPv4 added */ | 28 | /* 2 Range as input support for IPv4 added */ |
| 29 | /* 3 nomatch flag support added */ | 29 | /* 3 nomatch flag support added */ |
| 30 | /* 4 Counters support added */ | 30 | /* 4 Counters support added */ |
| 31 | #define IPSET_TYPE_REV_MAX 5 /* Comments support added */ | 31 | /* 5 Comments support added */ |
| 32 | #define IPSET_TYPE_REV_MAX 6 /* Forceadd support added */ | ||
| 32 | 33 | ||
| 33 | MODULE_LICENSE("GPL"); | 34 | MODULE_LICENSE("GPL"); |
| 34 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); | 35 | MODULE_AUTHOR("Jozsef Kadlecsik <kadlec@blackhole.kfki.hu>"); |
diff --git a/net/netfilter/ipset/ip_set_hash_netportnet.c b/net/netfilter/ipset/ip_set_hash_netportnet.c index 703d1192a6a2..c0d2ba73f8b2 100644 --- a/net/netfilter/ipset/ip_set_hash_netportnet.c +++ b/net/netfilter/ipset/ip_set_hash_netportnet.c | |||
| @@ -25,7 +25,8 @@ | |||
| 25 | #include <linux/netfilter/ipset/ip_set_hash.h> | 25 | #include <linux/netfilter/ipset/ip_set_hash.h> |
| 26 | 26 | ||
| 27 | #define IPSET_TYPE_REV_MIN 0 | 27 | #define IPSET_TYPE_REV_MIN 0 |
| 28 | #define IPSET_TYPE_REV_MAX 0 /* Comments support added */ | 28 | /* 0 Comments support added */ |
| 29 | #define IPSET_TYPE_REV_MAX 1 /* Forceadd support added */ | ||
| 29 | 30 | ||
| 30 | MODULE_LICENSE("GPL"); | 31 | MODULE_LICENSE("GPL"); |
| 31 | MODULE_AUTHOR("Oliver Smith <oliver@8.c.9.b.0.7.4.0.1.0.0.2.ip6.arpa>"); | 32 | MODULE_AUTHOR("Oliver Smith <oliver@8.c.9.b.0.7.4.0.1.0.0.2.ip6.arpa>"); |
diff --git a/net/netfilter/ipset/pfxlen.c b/net/netfilter/ipset/pfxlen.c index 4f29fa97044b..04d15fdc99ee 100644 --- a/net/netfilter/ipset/pfxlen.c +++ b/net/netfilter/ipset/pfxlen.c | |||
| @@ -7,8 +7,8 @@ | |||
| 7 | 7 | ||
| 8 | #define E(a, b, c, d) \ | 8 | #define E(a, b, c, d) \ |
| 9 | {.ip6 = { \ | 9 | {.ip6 = { \ |
| 10 | __constant_htonl(a), __constant_htonl(b), \ | 10 | htonl(a), htonl(b), \ |
| 11 | __constant_htonl(c), __constant_htonl(d), \ | 11 | htonl(c), htonl(d), \ |
| 12 | } } | 12 | } } |
| 13 | 13 | ||
| 14 | /* | 14 | /* |
diff --git a/net/netfilter/ipvs/ip_vs_ctl.c b/net/netfilter/ipvs/ip_vs_ctl.c index 35be035ee0ce..c42e83d2751c 100644 --- a/net/netfilter/ipvs/ip_vs_ctl.c +++ b/net/netfilter/ipvs/ip_vs_ctl.c | |||
| @@ -2177,10 +2177,10 @@ static int ip_vs_stats_percpu_show(struct seq_file *seq, void *v) | |||
| 2177 | __u64 inbytes, outbytes; | 2177 | __u64 inbytes, outbytes; |
| 2178 | 2178 | ||
| 2179 | do { | 2179 | do { |
| 2180 | start = u64_stats_fetch_begin_bh(&u->syncp); | 2180 | start = u64_stats_fetch_begin_irq(&u->syncp); |
| 2181 | inbytes = u->ustats.inbytes; | 2181 | inbytes = u->ustats.inbytes; |
| 2182 | outbytes = u->ustats.outbytes; | 2182 | outbytes = u->ustats.outbytes; |
| 2183 | } while (u64_stats_fetch_retry_bh(&u->syncp, start)); | 2183 | } while (u64_stats_fetch_retry_irq(&u->syncp, start)); |
| 2184 | 2184 | ||
| 2185 | seq_printf(seq, "%3X %8X %8X %8X %16LX %16LX\n", | 2185 | seq_printf(seq, "%3X %8X %8X %8X %16LX %16LX\n", |
| 2186 | i, u->ustats.conns, u->ustats.inpkts, | 2186 | i, u->ustats.conns, u->ustats.inpkts, |
| @@ -3580,7 +3580,7 @@ out: | |||
| 3580 | } | 3580 | } |
| 3581 | 3581 | ||
| 3582 | 3582 | ||
| 3583 | static const struct genl_ops ip_vs_genl_ops[] __read_mostly = { | 3583 | static const struct genl_ops ip_vs_genl_ops[] = { |
| 3584 | { | 3584 | { |
| 3585 | .cmd = IPVS_CMD_NEW_SERVICE, | 3585 | .cmd = IPVS_CMD_NEW_SERVICE, |
| 3586 | .flags = GENL_ADMIN_PERM, | 3586 | .flags = GENL_ADMIN_PERM, |
diff --git a/net/netfilter/ipvs/ip_vs_lblc.c b/net/netfilter/ipvs/ip_vs_lblc.c index ca056a331e60..547ff33c1efd 100644 --- a/net/netfilter/ipvs/ip_vs_lblc.c +++ b/net/netfilter/ipvs/ip_vs_lblc.c | |||
| @@ -238,7 +238,7 @@ static void ip_vs_lblc_flush(struct ip_vs_service *svc) | |||
| 238 | 238 | ||
| 239 | spin_lock_bh(&svc->sched_lock); | 239 | spin_lock_bh(&svc->sched_lock); |
| 240 | tbl->dead = 1; | 240 | tbl->dead = 1; |
| 241 | for (i=0; i<IP_VS_LBLC_TAB_SIZE; i++) { | 241 | for (i = 0; i < IP_VS_LBLC_TAB_SIZE; i++) { |
| 242 | hlist_for_each_entry_safe(en, next, &tbl->bucket[i], list) { | 242 | hlist_for_each_entry_safe(en, next, &tbl->bucket[i], list) { |
| 243 | ip_vs_lblc_del(en); | 243 | ip_vs_lblc_del(en); |
| 244 | atomic_dec(&tbl->entries); | 244 | atomic_dec(&tbl->entries); |
| @@ -265,7 +265,7 @@ static inline void ip_vs_lblc_full_check(struct ip_vs_service *svc) | |||
| 265 | unsigned long now = jiffies; | 265 | unsigned long now = jiffies; |
| 266 | int i, j; | 266 | int i, j; |
| 267 | 267 | ||
| 268 | for (i=0, j=tbl->rover; i<IP_VS_LBLC_TAB_SIZE; i++) { | 268 | for (i = 0, j = tbl->rover; i < IP_VS_LBLC_TAB_SIZE; i++) { |
| 269 | j = (j + 1) & IP_VS_LBLC_TAB_MASK; | 269 | j = (j + 1) & IP_VS_LBLC_TAB_MASK; |
| 270 | 270 | ||
| 271 | spin_lock(&svc->sched_lock); | 271 | spin_lock(&svc->sched_lock); |
| @@ -321,7 +321,7 @@ static void ip_vs_lblc_check_expire(unsigned long data) | |||
| 321 | if (goal > tbl->max_size/2) | 321 | if (goal > tbl->max_size/2) |
| 322 | goal = tbl->max_size/2; | 322 | goal = tbl->max_size/2; |
| 323 | 323 | ||
| 324 | for (i=0, j=tbl->rover; i<IP_VS_LBLC_TAB_SIZE; i++) { | 324 | for (i = 0, j = tbl->rover; i < IP_VS_LBLC_TAB_SIZE; i++) { |
| 325 | j = (j + 1) & IP_VS_LBLC_TAB_MASK; | 325 | j = (j + 1) & IP_VS_LBLC_TAB_MASK; |
| 326 | 326 | ||
| 327 | spin_lock(&svc->sched_lock); | 327 | spin_lock(&svc->sched_lock); |
| @@ -340,7 +340,7 @@ static void ip_vs_lblc_check_expire(unsigned long data) | |||
| 340 | tbl->rover = j; | 340 | tbl->rover = j; |
| 341 | 341 | ||
| 342 | out: | 342 | out: |
| 343 | mod_timer(&tbl->periodic_timer, jiffies+CHECK_EXPIRE_INTERVAL); | 343 | mod_timer(&tbl->periodic_timer, jiffies + CHECK_EXPIRE_INTERVAL); |
| 344 | } | 344 | } |
| 345 | 345 | ||
| 346 | 346 | ||
| @@ -363,7 +363,7 @@ static int ip_vs_lblc_init_svc(struct ip_vs_service *svc) | |||
| 363 | /* | 363 | /* |
| 364 | * Initialize the hash buckets | 364 | * Initialize the hash buckets |
| 365 | */ | 365 | */ |
| 366 | for (i=0; i<IP_VS_LBLC_TAB_SIZE; i++) { | 366 | for (i = 0; i < IP_VS_LBLC_TAB_SIZE; i++) { |
| 367 | INIT_HLIST_HEAD(&tbl->bucket[i]); | 367 | INIT_HLIST_HEAD(&tbl->bucket[i]); |
| 368 | } | 368 | } |
| 369 | tbl->max_size = IP_VS_LBLC_TAB_SIZE*16; | 369 | tbl->max_size = IP_VS_LBLC_TAB_SIZE*16; |
| @@ -536,8 +536,7 @@ out: | |||
| 536 | /* | 536 | /* |
| 537 | * IPVS LBLC Scheduler structure | 537 | * IPVS LBLC Scheduler structure |
| 538 | */ | 538 | */ |
| 539 | static struct ip_vs_scheduler ip_vs_lblc_scheduler = | 539 | static struct ip_vs_scheduler ip_vs_lblc_scheduler = { |
| 540 | { | ||
| 541 | .name = "lblc", | 540 | .name = "lblc", |
| 542 | .refcnt = ATOMIC_INIT(0), | 541 | .refcnt = ATOMIC_INIT(0), |
| 543 | .module = THIS_MODULE, | 542 | .module = THIS_MODULE, |
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c index 356bef519fe5..75421f2ba8be 100644 --- a/net/netfilter/nf_conntrack_core.c +++ b/net/netfilter/nf_conntrack_core.c | |||
| @@ -60,8 +60,59 @@ int (*nfnetlink_parse_nat_setup_hook)(struct nf_conn *ct, | |||
| 60 | const struct nlattr *attr) __read_mostly; | 60 | const struct nlattr *attr) __read_mostly; |
| 61 | EXPORT_SYMBOL_GPL(nfnetlink_parse_nat_setup_hook); | 61 | EXPORT_SYMBOL_GPL(nfnetlink_parse_nat_setup_hook); |
| 62 | 62 | ||
| 63 | DEFINE_SPINLOCK(nf_conntrack_lock); | 63 | __cacheline_aligned_in_smp spinlock_t nf_conntrack_locks[CONNTRACK_LOCKS]; |
| 64 | EXPORT_SYMBOL_GPL(nf_conntrack_lock); | 64 | EXPORT_SYMBOL_GPL(nf_conntrack_locks); |
| 65 | |||
| 66 | __cacheline_aligned_in_smp DEFINE_SPINLOCK(nf_conntrack_expect_lock); | ||
| 67 | EXPORT_SYMBOL_GPL(nf_conntrack_expect_lock); | ||
| 68 | |||
| 69 | static void nf_conntrack_double_unlock(unsigned int h1, unsigned int h2) | ||
| 70 | { | ||
| 71 | h1 %= CONNTRACK_LOCKS; | ||
| 72 | h2 %= CONNTRACK_LOCKS; | ||
| 73 | spin_unlock(&nf_conntrack_locks[h1]); | ||
| 74 | if (h1 != h2) | ||
| 75 | spin_unlock(&nf_conntrack_locks[h2]); | ||
| 76 | } | ||
| 77 | |||
| 78 | /* return true if we need to recompute hashes (in case hash table was resized) */ | ||
| 79 | static bool nf_conntrack_double_lock(struct net *net, unsigned int h1, | ||
| 80 | unsigned int h2, unsigned int sequence) | ||
| 81 | { | ||
| 82 | h1 %= CONNTRACK_LOCKS; | ||
| 83 | h2 %= CONNTRACK_LOCKS; | ||
| 84 | if (h1 <= h2) { | ||
| 85 | spin_lock(&nf_conntrack_locks[h1]); | ||
| 86 | if (h1 != h2) | ||
| 87 | spin_lock_nested(&nf_conntrack_locks[h2], | ||
| 88 | SINGLE_DEPTH_NESTING); | ||
| 89 | } else { | ||
| 90 | spin_lock(&nf_conntrack_locks[h2]); | ||
| 91 | spin_lock_nested(&nf_conntrack_locks[h1], | ||
| 92 | SINGLE_DEPTH_NESTING); | ||
| 93 | } | ||
| 94 | if (read_seqcount_retry(&net->ct.generation, sequence)) { | ||
| 95 | nf_conntrack_double_unlock(h1, h2); | ||
| 96 | return true; | ||
| 97 | } | ||
| 98 | return false; | ||
| 99 | } | ||
| 100 | |||
| 101 | static void nf_conntrack_all_lock(void) | ||
| 102 | { | ||
| 103 | int i; | ||
| 104 | |||
| 105 | for (i = 0; i < CONNTRACK_LOCKS; i++) | ||
| 106 | spin_lock_nested(&nf_conntrack_locks[i], i); | ||
| 107 | } | ||
| 108 | |||
| 109 | static void nf_conntrack_all_unlock(void) | ||
| 110 | { | ||
| 111 | int i; | ||
| 112 | |||
| 113 | for (i = 0; i < CONNTRACK_LOCKS; i++) | ||
| 114 | spin_unlock(&nf_conntrack_locks[i]); | ||
| 115 | } | ||
| 65 | 116 | ||
| 66 | unsigned int nf_conntrack_htable_size __read_mostly; | 117 | unsigned int nf_conntrack_htable_size __read_mostly; |
| 67 | EXPORT_SYMBOL_GPL(nf_conntrack_htable_size); | 118 | EXPORT_SYMBOL_GPL(nf_conntrack_htable_size); |
| @@ -192,6 +243,50 @@ clean_from_lists(struct nf_conn *ct) | |||
| 192 | nf_ct_remove_expectations(ct); | 243 | nf_ct_remove_expectations(ct); |
| 193 | } | 244 | } |
| 194 | 245 | ||
| 246 | /* must be called with local_bh_disable */ | ||
| 247 | static void nf_ct_add_to_dying_list(struct nf_conn *ct) | ||
| 248 | { | ||
| 249 | struct ct_pcpu *pcpu; | ||
| 250 | |||
| 251 | /* add this conntrack to the (per cpu) dying list */ | ||
| 252 | ct->cpu = smp_processor_id(); | ||
| 253 | pcpu = per_cpu_ptr(nf_ct_net(ct)->ct.pcpu_lists, ct->cpu); | ||
| 254 | |||
| 255 | spin_lock(&pcpu->lock); | ||
| 256 | hlist_nulls_add_head(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode, | ||
| 257 | &pcpu->dying); | ||
| 258 | spin_unlock(&pcpu->lock); | ||
| 259 | } | ||
| 260 | |||
| 261 | /* must be called with local_bh_disable */ | ||
| 262 | static void nf_ct_add_to_unconfirmed_list(struct nf_conn *ct) | ||
| 263 | { | ||
| 264 | struct ct_pcpu *pcpu; | ||
| 265 | |||
| 266 | /* add this conntrack to the (per cpu) unconfirmed list */ | ||
| 267 | ct->cpu = smp_processor_id(); | ||
| 268 | pcpu = per_cpu_ptr(nf_ct_net(ct)->ct.pcpu_lists, ct->cpu); | ||
| 269 | |||
| 270 | spin_lock(&pcpu->lock); | ||
| 271 | hlist_nulls_add_head(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode, | ||
| 272 | &pcpu->unconfirmed); | ||
| 273 | spin_unlock(&pcpu->lock); | ||
| 274 | } | ||
| 275 | |||
| 276 | /* must be called with local_bh_disable */ | ||
| 277 | static void nf_ct_del_from_dying_or_unconfirmed_list(struct nf_conn *ct) | ||
| 278 | { | ||
| 279 | struct ct_pcpu *pcpu; | ||
| 280 | |||
| 281 | /* We overload first tuple to link into unconfirmed or dying list.*/ | ||
| 282 | pcpu = per_cpu_ptr(nf_ct_net(ct)->ct.pcpu_lists, ct->cpu); | ||
| 283 | |||
| 284 | spin_lock(&pcpu->lock); | ||
| 285 | BUG_ON(hlist_nulls_unhashed(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode)); | ||
| 286 | hlist_nulls_del_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode); | ||
| 287 | spin_unlock(&pcpu->lock); | ||
| 288 | } | ||
| 289 | |||
| 195 | static void | 290 | static void |
| 196 | destroy_conntrack(struct nf_conntrack *nfct) | 291 | destroy_conntrack(struct nf_conntrack *nfct) |
| 197 | { | 292 | { |
| @@ -203,9 +298,6 @@ destroy_conntrack(struct nf_conntrack *nfct) | |||
| 203 | NF_CT_ASSERT(atomic_read(&nfct->use) == 0); | 298 | NF_CT_ASSERT(atomic_read(&nfct->use) == 0); |
| 204 | NF_CT_ASSERT(!timer_pending(&ct->timeout)); | 299 | NF_CT_ASSERT(!timer_pending(&ct->timeout)); |
| 205 | 300 | ||
| 206 | /* To make sure we don't get any weird locking issues here: | ||
| 207 | * destroy_conntrack() MUST NOT be called with a write lock | ||
| 208 | * to nf_conntrack_lock!!! -HW */ | ||
| 209 | rcu_read_lock(); | 301 | rcu_read_lock(); |
| 210 | l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct)); | 302 | l4proto = __nf_ct_l4proto_find(nf_ct_l3num(ct), nf_ct_protonum(ct)); |
| 211 | if (l4proto && l4proto->destroy) | 303 | if (l4proto && l4proto->destroy) |
| @@ -213,19 +305,18 @@ destroy_conntrack(struct nf_conntrack *nfct) | |||
| 213 | 305 | ||
| 214 | rcu_read_unlock(); | 306 | rcu_read_unlock(); |
| 215 | 307 | ||
| 216 | spin_lock_bh(&nf_conntrack_lock); | 308 | local_bh_disable(); |
| 217 | /* Expectations will have been removed in clean_from_lists, | 309 | /* Expectations will have been removed in clean_from_lists, |
| 218 | * except TFTP can create an expectation on the first packet, | 310 | * except TFTP can create an expectation on the first packet, |
| 219 | * before connection is in the list, so we need to clean here, | 311 | * before connection is in the list, so we need to clean here, |
| 220 | * too. */ | 312 | * too. |
| 313 | */ | ||
| 221 | nf_ct_remove_expectations(ct); | 314 | nf_ct_remove_expectations(ct); |
| 222 | 315 | ||
| 223 | /* We overload first tuple to link into unconfirmed or dying list.*/ | 316 | nf_ct_del_from_dying_or_unconfirmed_list(ct); |
| 224 | BUG_ON(hlist_nulls_unhashed(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode)); | ||
| 225 | hlist_nulls_del_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode); | ||
| 226 | 317 | ||
| 227 | NF_CT_STAT_INC(net, delete); | 318 | NF_CT_STAT_INC(net, delete); |
| 228 | spin_unlock_bh(&nf_conntrack_lock); | 319 | local_bh_enable(); |
| 229 | 320 | ||
| 230 | if (ct->master) | 321 | if (ct->master) |
| 231 | nf_ct_put(ct->master); | 322 | nf_ct_put(ct->master); |
| @@ -237,17 +328,28 @@ destroy_conntrack(struct nf_conntrack *nfct) | |||
| 237 | static void nf_ct_delete_from_lists(struct nf_conn *ct) | 328 | static void nf_ct_delete_from_lists(struct nf_conn *ct) |
| 238 | { | 329 | { |
| 239 | struct net *net = nf_ct_net(ct); | 330 | struct net *net = nf_ct_net(ct); |
| 331 | unsigned int hash, reply_hash; | ||
| 332 | u16 zone = nf_ct_zone(ct); | ||
| 333 | unsigned int sequence; | ||
| 240 | 334 | ||
| 241 | nf_ct_helper_destroy(ct); | 335 | nf_ct_helper_destroy(ct); |
| 242 | spin_lock_bh(&nf_conntrack_lock); | 336 | |
| 243 | /* Inside lock so preempt is disabled on module removal path. | 337 | local_bh_disable(); |
| 244 | * Otherwise we can get spurious warnings. */ | 338 | do { |
| 245 | NF_CT_STAT_INC(net, delete_list); | 339 | sequence = read_seqcount_begin(&net->ct.generation); |
| 340 | hash = hash_conntrack(net, zone, | ||
| 341 | &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); | ||
| 342 | reply_hash = hash_conntrack(net, zone, | ||
| 343 | &ct->tuplehash[IP_CT_DIR_REPLY].tuple); | ||
| 344 | } while (nf_conntrack_double_lock(net, hash, reply_hash, sequence)); | ||
| 345 | |||
| 246 | clean_from_lists(ct); | 346 | clean_from_lists(ct); |
| 247 | /* add this conntrack to the dying list */ | 347 | nf_conntrack_double_unlock(hash, reply_hash); |
| 248 | hlist_nulls_add_head(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode, | 348 | |
| 249 | &net->ct.dying); | 349 | nf_ct_add_to_dying_list(ct); |
| 250 | spin_unlock_bh(&nf_conntrack_lock); | 350 | |
| 351 | NF_CT_STAT_INC(net, delete_list); | ||
| 352 | local_bh_enable(); | ||
| 251 | } | 353 | } |
| 252 | 354 | ||
| 253 | static void death_by_event(unsigned long ul_conntrack) | 355 | static void death_by_event(unsigned long ul_conntrack) |
| @@ -331,8 +433,6 @@ nf_ct_key_equal(struct nf_conntrack_tuple_hash *h, | |||
| 331 | * Warning : | 433 | * Warning : |
| 332 | * - Caller must take a reference on returned object | 434 | * - Caller must take a reference on returned object |
| 333 | * and recheck nf_ct_tuple_equal(tuple, &h->tuple) | 435 | * and recheck nf_ct_tuple_equal(tuple, &h->tuple) |
| 334 | * OR | ||
| 335 | * - Caller must lock nf_conntrack_lock before calling this function | ||
| 336 | */ | 436 | */ |
| 337 | static struct nf_conntrack_tuple_hash * | 437 | static struct nf_conntrack_tuple_hash * |
| 338 | ____nf_conntrack_find(struct net *net, u16 zone, | 438 | ____nf_conntrack_find(struct net *net, u16 zone, |
| @@ -408,32 +508,36 @@ EXPORT_SYMBOL_GPL(nf_conntrack_find_get); | |||
| 408 | 508 | ||
| 409 | static void __nf_conntrack_hash_insert(struct nf_conn *ct, | 509 | static void __nf_conntrack_hash_insert(struct nf_conn *ct, |
| 410 | unsigned int hash, | 510 | unsigned int hash, |
| 411 | unsigned int repl_hash) | 511 | unsigned int reply_hash) |
| 412 | { | 512 | { |
| 413 | struct net *net = nf_ct_net(ct); | 513 | struct net *net = nf_ct_net(ct); |
| 414 | 514 | ||
| 415 | hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode, | 515 | hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode, |
| 416 | &net->ct.hash[hash]); | 516 | &net->ct.hash[hash]); |
| 417 | hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_REPLY].hnnode, | 517 | hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_REPLY].hnnode, |
| 418 | &net->ct.hash[repl_hash]); | 518 | &net->ct.hash[reply_hash]); |
| 419 | } | 519 | } |
| 420 | 520 | ||
| 421 | int | 521 | int |
| 422 | nf_conntrack_hash_check_insert(struct nf_conn *ct) | 522 | nf_conntrack_hash_check_insert(struct nf_conn *ct) |
| 423 | { | 523 | { |
| 424 | struct net *net = nf_ct_net(ct); | 524 | struct net *net = nf_ct_net(ct); |
| 425 | unsigned int hash, repl_hash; | 525 | unsigned int hash, reply_hash; |
| 426 | struct nf_conntrack_tuple_hash *h; | 526 | struct nf_conntrack_tuple_hash *h; |
| 427 | struct hlist_nulls_node *n; | 527 | struct hlist_nulls_node *n; |
| 428 | u16 zone; | 528 | u16 zone; |
| 529 | unsigned int sequence; | ||
| 429 | 530 | ||
| 430 | zone = nf_ct_zone(ct); | 531 | zone = nf_ct_zone(ct); |
| 431 | hash = hash_conntrack(net, zone, | ||
| 432 | &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); | ||
| 433 | repl_hash = hash_conntrack(net, zone, | ||
| 434 | &ct->tuplehash[IP_CT_DIR_REPLY].tuple); | ||
| 435 | 532 | ||
| 436 | spin_lock_bh(&nf_conntrack_lock); | 533 | local_bh_disable(); |
| 534 | do { | ||
| 535 | sequence = read_seqcount_begin(&net->ct.generation); | ||
| 536 | hash = hash_conntrack(net, zone, | ||
| 537 | &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple); | ||
| 538 | reply_hash = hash_conntrack(net, zone, | ||
| 539 | &ct->tuplehash[IP_CT_DIR_REPLY].tuple); | ||
| 540 | } while (nf_conntrack_double_lock(net, hash, reply_hash, sequence)); | ||
| 437 | 541 | ||
| 438 | /* See if there's one in the list already, including reverse */ | 542 | /* See if there's one in the list already, including reverse */ |
| 439 | hlist_nulls_for_each_entry(h, n, &net->ct.hash[hash], hnnode) | 543 | hlist_nulls_for_each_entry(h, n, &net->ct.hash[hash], hnnode) |
| @@ -441,7 +545,7 @@ nf_conntrack_hash_check_insert(struct nf_conn *ct) | |||
| 441 | &h->tuple) && | 545 | &h->tuple) && |
| 442 | zone == nf_ct_zone(nf_ct_tuplehash_to_ctrack(h))) | 546 | zone == nf_ct_zone(nf_ct_tuplehash_to_ctrack(h))) |
| 443 | goto out; | 547 | goto out; |
| 444 | hlist_nulls_for_each_entry(h, n, &net->ct.hash[repl_hash], hnnode) | 548 | hlist_nulls_for_each_entry(h, n, &net->ct.hash[reply_hash], hnnode) |
| 445 | if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple, | 549 | if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple, |
| 446 | &h->tuple) && | 550 | &h->tuple) && |
| 447 | zone == nf_ct_zone(nf_ct_tuplehash_to_ctrack(h))) | 551 | zone == nf_ct_zone(nf_ct_tuplehash_to_ctrack(h))) |
| @@ -451,15 +555,16 @@ nf_conntrack_hash_check_insert(struct nf_conn *ct) | |||
| 451 | smp_wmb(); | 555 | smp_wmb(); |
| 452 | /* The caller holds a reference to this object */ | 556 | /* The caller holds a reference to this object */ |
| 453 | atomic_set(&ct->ct_general.use, 2); | 557 | atomic_set(&ct->ct_general.use, 2); |
| 454 | __nf_conntrack_hash_insert(ct, hash, repl_hash); | 558 | __nf_conntrack_hash_insert(ct, hash, reply_hash); |
| 559 | nf_conntrack_double_unlock(hash, reply_hash); | ||
| 455 | NF_CT_STAT_INC(net, insert); | 560 | NF_CT_STAT_INC(net, insert); |
| 456 | spin_unlock_bh(&nf_conntrack_lock); | 561 | local_bh_enable(); |
| 457 | |||
| 458 | return 0; | 562 | return 0; |
| 459 | 563 | ||
| 460 | out: | 564 | out: |
| 565 | nf_conntrack_double_unlock(hash, reply_hash); | ||
| 461 | NF_CT_STAT_INC(net, insert_failed); | 566 | NF_CT_STAT_INC(net, insert_failed); |
| 462 | spin_unlock_bh(&nf_conntrack_lock); | 567 | local_bh_enable(); |
| 463 | return -EEXIST; | 568 | return -EEXIST; |
| 464 | } | 569 | } |
| 465 | EXPORT_SYMBOL_GPL(nf_conntrack_hash_check_insert); | 570 | EXPORT_SYMBOL_GPL(nf_conntrack_hash_check_insert); |
| @@ -467,15 +572,22 @@ EXPORT_SYMBOL_GPL(nf_conntrack_hash_check_insert); | |||
| 467 | /* deletion from this larval template list happens via nf_ct_put() */ | 572 | /* deletion from this larval template list happens via nf_ct_put() */ |
| 468 | void nf_conntrack_tmpl_insert(struct net *net, struct nf_conn *tmpl) | 573 | void nf_conntrack_tmpl_insert(struct net *net, struct nf_conn *tmpl) |
| 469 | { | 574 | { |
| 575 | struct ct_pcpu *pcpu; | ||
| 576 | |||
| 470 | __set_bit(IPS_TEMPLATE_BIT, &tmpl->status); | 577 | __set_bit(IPS_TEMPLATE_BIT, &tmpl->status); |
| 471 | __set_bit(IPS_CONFIRMED_BIT, &tmpl->status); | 578 | __set_bit(IPS_CONFIRMED_BIT, &tmpl->status); |
| 472 | nf_conntrack_get(&tmpl->ct_general); | 579 | nf_conntrack_get(&tmpl->ct_general); |
| 473 | 580 | ||
| 474 | spin_lock_bh(&nf_conntrack_lock); | 581 | /* add this conntrack to the (per cpu) tmpl list */ |
| 582 | local_bh_disable(); | ||
| 583 | tmpl->cpu = smp_processor_id(); | ||
| 584 | pcpu = per_cpu_ptr(nf_ct_net(tmpl)->ct.pcpu_lists, tmpl->cpu); | ||
| 585 | |||
| 586 | spin_lock(&pcpu->lock); | ||
| 475 | /* Overload tuple linked list to put us in template list. */ | 587 | /* Overload tuple linked list to put us in template list. */ |
| 476 | hlist_nulls_add_head_rcu(&tmpl->tuplehash[IP_CT_DIR_ORIGINAL].hnnode, | 588 | hlist_nulls_add_head_rcu(&tmpl->tuplehash[IP_CT_DIR_ORIGINAL].hnnode, |
| 477 | &net->ct.tmpl); | 589 | &pcpu->tmpl); |
| 478 | spin_unlock_bh(&nf_conntrack_lock); | 590 | spin_unlock_bh(&pcpu->lock); |
| 479 | } | 591 | } |
| 480 | EXPORT_SYMBOL_GPL(nf_conntrack_tmpl_insert); | 592 | EXPORT_SYMBOL_GPL(nf_conntrack_tmpl_insert); |
| 481 | 593 | ||
| @@ -483,7 +595,7 @@ EXPORT_SYMBOL_GPL(nf_conntrack_tmpl_insert); | |||
| 483 | int | 595 | int |
| 484 | __nf_conntrack_confirm(struct sk_buff *skb) | 596 | __nf_conntrack_confirm(struct sk_buff *skb) |
| 485 | { | 597 | { |
| 486 | unsigned int hash, repl_hash; | 598 | unsigned int hash, reply_hash; |
| 487 | struct nf_conntrack_tuple_hash *h; | 599 | struct nf_conntrack_tuple_hash *h; |
| 488 | struct nf_conn *ct; | 600 | struct nf_conn *ct; |
| 489 | struct nf_conn_help *help; | 601 | struct nf_conn_help *help; |
| @@ -492,6 +604,7 @@ __nf_conntrack_confirm(struct sk_buff *skb) | |||
| 492 | enum ip_conntrack_info ctinfo; | 604 | enum ip_conntrack_info ctinfo; |
| 493 | struct net *net; | 605 | struct net *net; |
| 494 | u16 zone; | 606 | u16 zone; |
| 607 | unsigned int sequence; | ||
| 495 | 608 | ||
| 496 | ct = nf_ct_get(skb, &ctinfo); | 609 | ct = nf_ct_get(skb, &ctinfo); |
| 497 | net = nf_ct_net(ct); | 610 | net = nf_ct_net(ct); |
| @@ -504,31 +617,37 @@ __nf_conntrack_confirm(struct sk_buff *skb) | |||
| 504 | return NF_ACCEPT; | 617 | return NF_ACCEPT; |
| 505 | 618 | ||
| 506 | zone = nf_ct_zone(ct); | 619 | zone = nf_ct_zone(ct); |
| 507 | /* reuse the hash saved before */ | 620 | local_bh_disable(); |
| 508 | hash = *(unsigned long *)&ct->tuplehash[IP_CT_DIR_REPLY].hnnode.pprev; | 621 | |
| 509 | hash = hash_bucket(hash, net); | 622 | do { |
| 510 | repl_hash = hash_conntrack(net, zone, | 623 | sequence = read_seqcount_begin(&net->ct.generation); |
| 511 | &ct->tuplehash[IP_CT_DIR_REPLY].tuple); | 624 | /* reuse the hash saved before */ |
| 625 | hash = *(unsigned long *)&ct->tuplehash[IP_CT_DIR_REPLY].hnnode.pprev; | ||
| 626 | hash = hash_bucket(hash, net); | ||
| 627 | reply_hash = hash_conntrack(net, zone, | ||
| 628 | &ct->tuplehash[IP_CT_DIR_REPLY].tuple); | ||
| 629 | |||
| 630 | } while (nf_conntrack_double_lock(net, hash, reply_hash, sequence)); | ||
| 512 | 631 | ||
| 513 | /* We're not in hash table, and we refuse to set up related | 632 | /* We're not in hash table, and we refuse to set up related |
| 514 | connections for unconfirmed conns. But packet copies and | 633 | * connections for unconfirmed conns. But packet copies and |
| 515 | REJECT will give spurious warnings here. */ | 634 | * REJECT will give spurious warnings here. |
| 635 | */ | ||
| 516 | /* NF_CT_ASSERT(atomic_read(&ct->ct_general.use) == 1); */ | 636 | /* NF_CT_ASSERT(atomic_read(&ct->ct_general.use) == 1); */ |
| 517 | 637 | ||
| 518 | /* No external references means no one else could have | 638 | /* No external references means no one else could have |
| 519 | confirmed us. */ | 639 | * confirmed us. |
| 640 | */ | ||
| 520 | NF_CT_ASSERT(!nf_ct_is_confirmed(ct)); | 641 | NF_CT_ASSERT(!nf_ct_is_confirmed(ct)); |
| 521 | pr_debug("Confirming conntrack %p\n", ct); | 642 | pr_debug("Confirming conntrack %p\n", ct); |
| 522 | |||
| 523 | spin_lock_bh(&nf_conntrack_lock); | ||
| 524 | |||
| 525 | /* We have to check the DYING flag inside the lock to prevent | 643 | /* We have to check the DYING flag inside the lock to prevent |
| 526 | a race against nf_ct_get_next_corpse() possibly called from | 644 | a race against nf_ct_get_next_corpse() possibly called from |
| 527 | user context, else we insert an already 'dead' hash, blocking | 645 | user context, else we insert an already 'dead' hash, blocking |
| 528 | further use of that particular connection -JM */ | 646 | further use of that particular connection -JM */ |
| 529 | 647 | ||
| 530 | if (unlikely(nf_ct_is_dying(ct))) { | 648 | if (unlikely(nf_ct_is_dying(ct))) { |
| 531 | spin_unlock_bh(&nf_conntrack_lock); | 649 | nf_conntrack_double_unlock(hash, reply_hash); |
| 650 | local_bh_enable(); | ||
| 532 | return NF_ACCEPT; | 651 | return NF_ACCEPT; |
| 533 | } | 652 | } |
| 534 | 653 | ||
| @@ -540,14 +659,13 @@ __nf_conntrack_confirm(struct sk_buff *skb) | |||
| 540 | &h->tuple) && | 659 | &h->tuple) && |
| 541 | zone == nf_ct_zone(nf_ct_tuplehash_to_ctrack(h))) | 660 | zone == nf_ct_zone(nf_ct_tuplehash_to_ctrack(h))) |
| 542 | goto out; | 661 | goto out; |
| 543 | hlist_nulls_for_each_entry(h, n, &net->ct.hash[repl_hash], hnnode) | 662 | hlist_nulls_for_each_entry(h, n, &net->ct.hash[reply_hash], hnnode) |
| 544 | if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple, | 663 | if (nf_ct_tuple_equal(&ct->tuplehash[IP_CT_DIR_REPLY].tuple, |
| 545 | &h->tuple) && | 664 | &h->tuple) && |
| 546 | zone == nf_ct_zone(nf_ct_tuplehash_to_ctrack(h))) | 665 | zone == nf_ct_zone(nf_ct_tuplehash_to_ctrack(h))) |
| 547 | goto out; | 666 | goto out; |
| 548 | 667 | ||
| 549 | /* Remove from unconfirmed list */ | 668 | nf_ct_del_from_dying_or_unconfirmed_list(ct); |
| 550 | hlist_nulls_del_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode); | ||
| 551 | 669 | ||
| 552 | /* Timer relative to confirmation time, not original | 670 | /* Timer relative to confirmation time, not original |
| 553 | setting time, otherwise we'd get timer wrap in | 671 | setting time, otherwise we'd get timer wrap in |
| @@ -570,9 +688,10 @@ __nf_conntrack_confirm(struct sk_buff *skb) | |||
| 570 | * guarantee that no other CPU can find the conntrack before the above | 688 | * guarantee that no other CPU can find the conntrack before the above |
| 571 | * stores are visible. | 689 | * stores are visible. |
| 572 | */ | 690 | */ |
| 573 | __nf_conntrack_hash_insert(ct, hash, repl_hash); | 691 | __nf_conntrack_hash_insert(ct, hash, reply_hash); |
| 692 | nf_conntrack_double_unlock(hash, reply_hash); | ||
| 574 | NF_CT_STAT_INC(net, insert); | 693 | NF_CT_STAT_INC(net, insert); |
| 575 | spin_unlock_bh(&nf_conntrack_lock); | 694 | local_bh_enable(); |
| 576 | 695 | ||
| 577 | help = nfct_help(ct); | 696 | help = nfct_help(ct); |
| 578 | if (help && help->helper) | 697 | if (help && help->helper) |
| @@ -583,8 +702,9 @@ __nf_conntrack_confirm(struct sk_buff *skb) | |||
| 583 | return NF_ACCEPT; | 702 | return NF_ACCEPT; |
| 584 | 703 | ||
| 585 | out: | 704 | out: |
| 705 | nf_conntrack_double_unlock(hash, reply_hash); | ||
| 586 | NF_CT_STAT_INC(net, insert_failed); | 706 | NF_CT_STAT_INC(net, insert_failed); |
| 587 | spin_unlock_bh(&nf_conntrack_lock); | 707 | local_bh_enable(); |
| 588 | return NF_DROP; | 708 | return NF_DROP; |
| 589 | } | 709 | } |
| 590 | EXPORT_SYMBOL_GPL(__nf_conntrack_confirm); | 710 | EXPORT_SYMBOL_GPL(__nf_conntrack_confirm); |
| @@ -627,39 +747,48 @@ EXPORT_SYMBOL_GPL(nf_conntrack_tuple_taken); | |||
| 627 | 747 | ||
| 628 | /* There's a small race here where we may free a just-assured | 748 | /* There's a small race here where we may free a just-assured |
| 629 | connection. Too bad: we're in trouble anyway. */ | 749 | connection. Too bad: we're in trouble anyway. */ |
| 630 | static noinline int early_drop(struct net *net, unsigned int hash) | 750 | static noinline int early_drop(struct net *net, unsigned int _hash) |
| 631 | { | 751 | { |
| 632 | /* Use oldest entry, which is roughly LRU */ | 752 | /* Use oldest entry, which is roughly LRU */ |
| 633 | struct nf_conntrack_tuple_hash *h; | 753 | struct nf_conntrack_tuple_hash *h; |
| 634 | struct nf_conn *ct = NULL, *tmp; | 754 | struct nf_conn *ct = NULL, *tmp; |
| 635 | struct hlist_nulls_node *n; | 755 | struct hlist_nulls_node *n; |
| 636 | unsigned int i, cnt = 0; | 756 | unsigned int i = 0, cnt = 0; |
| 637 | int dropped = 0; | 757 | int dropped = 0; |
| 758 | unsigned int hash, sequence; | ||
| 759 | spinlock_t *lockp; | ||
| 638 | 760 | ||
| 639 | rcu_read_lock(); | 761 | local_bh_disable(); |
| 640 | for (i = 0; i < net->ct.htable_size; i++) { | 762 | restart: |
| 763 | sequence = read_seqcount_begin(&net->ct.generation); | ||
| 764 | hash = hash_bucket(_hash, net); | ||
| 765 | for (; i < net->ct.htable_size; i++) { | ||
| 766 | lockp = &nf_conntrack_locks[hash % CONNTRACK_LOCKS]; | ||
| 767 | spin_lock(lockp); | ||
| 768 | if (read_seqcount_retry(&net->ct.generation, sequence)) { | ||
| 769 | spin_unlock(lockp); | ||
| 770 | goto restart; | ||
| 771 | } | ||
| 641 | hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[hash], | 772 | hlist_nulls_for_each_entry_rcu(h, n, &net->ct.hash[hash], |
| 642 | hnnode) { | 773 | hnnode) { |
| 643 | tmp = nf_ct_tuplehash_to_ctrack(h); | 774 | tmp = nf_ct_tuplehash_to_ctrack(h); |
| 644 | if (!test_bit(IPS_ASSURED_BIT, &tmp->status)) | 775 | if (!test_bit(IPS_ASSURED_BIT, &tmp->status) && |
| 776 | !nf_ct_is_dying(tmp) && | ||
| 777 | atomic_inc_not_zero(&tmp->ct_general.use)) { | ||
| 645 | ct = tmp; | 778 | ct = tmp; |
| 779 | break; | ||
| 780 | } | ||
| 646 | cnt++; | 781 | cnt++; |
| 647 | } | 782 | } |
| 648 | 783 | ||
| 649 | if (ct != NULL) { | 784 | hash = (hash + 1) % net->ct.htable_size; |
| 650 | if (likely(!nf_ct_is_dying(ct) && | 785 | spin_unlock(lockp); |
| 651 | atomic_inc_not_zero(&ct->ct_general.use))) | ||
| 652 | break; | ||
| 653 | else | ||
| 654 | ct = NULL; | ||
| 655 | } | ||
| 656 | 786 | ||
| 657 | if (cnt >= NF_CT_EVICTION_RANGE) | 787 | if (ct || cnt >= NF_CT_EVICTION_RANGE) |
| 658 | break; | 788 | break; |
| 659 | 789 | ||
| 660 | hash = (hash + 1) % net->ct.htable_size; | ||
| 661 | } | 790 | } |
| 662 | rcu_read_unlock(); | 791 | local_bh_enable(); |
| 663 | 792 | ||
| 664 | if (!ct) | 793 | if (!ct) |
| 665 | return dropped; | 794 | return dropped; |
| @@ -708,7 +837,7 @@ __nf_conntrack_alloc(struct net *net, u16 zone, | |||
| 708 | 837 | ||
| 709 | if (nf_conntrack_max && | 838 | if (nf_conntrack_max && |
| 710 | unlikely(atomic_read(&net->ct.count) > nf_conntrack_max)) { | 839 | unlikely(atomic_read(&net->ct.count) > nf_conntrack_max)) { |
| 711 | if (!early_drop(net, hash_bucket(hash, net))) { | 840 | if (!early_drop(net, hash)) { |
| 712 | atomic_dec(&net->ct.count); | 841 | atomic_dec(&net->ct.count); |
| 713 | net_warn_ratelimited("nf_conntrack: table full, dropping packet\n"); | 842 | net_warn_ratelimited("nf_conntrack: table full, dropping packet\n"); |
| 714 | return ERR_PTR(-ENOMEM); | 843 | return ERR_PTR(-ENOMEM); |
| @@ -805,7 +934,7 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, | |||
| 805 | struct nf_conn_help *help; | 934 | struct nf_conn_help *help; |
| 806 | struct nf_conntrack_tuple repl_tuple; | 935 | struct nf_conntrack_tuple repl_tuple; |
| 807 | struct nf_conntrack_ecache *ecache; | 936 | struct nf_conntrack_ecache *ecache; |
| 808 | struct nf_conntrack_expect *exp; | 937 | struct nf_conntrack_expect *exp = NULL; |
| 809 | u16 zone = tmpl ? nf_ct_zone(tmpl) : NF_CT_DEFAULT_ZONE; | 938 | u16 zone = tmpl ? nf_ct_zone(tmpl) : NF_CT_DEFAULT_ZONE; |
| 810 | struct nf_conn_timeout *timeout_ext; | 939 | struct nf_conn_timeout *timeout_ext; |
| 811 | unsigned int *timeouts; | 940 | unsigned int *timeouts; |
| @@ -849,42 +978,44 @@ init_conntrack(struct net *net, struct nf_conn *tmpl, | |||
| 849 | ecache ? ecache->expmask : 0, | 978 | ecache ? ecache->expmask : 0, |
| 850 | GFP_ATOMIC); | 979 | GFP_ATOMIC); |
| 851 | 980 | ||
| 852 | spin_lock_bh(&nf_conntrack_lock); | 981 | local_bh_disable(); |
| 853 | exp = nf_ct_find_expectation(net, zone, tuple); | 982 | if (net->ct.expect_count) { |
| 854 | if (exp) { | 983 | spin_lock(&nf_conntrack_expect_lock); |
| 855 | pr_debug("conntrack: expectation arrives ct=%p exp=%p\n", | 984 | exp = nf_ct_find_expectation(net, zone, tuple); |
| 856 | ct, exp); | 985 | if (exp) { |
| 857 | /* Welcome, Mr. Bond. We've been expecting you... */ | 986 | pr_debug("conntrack: expectation arrives ct=%p exp=%p\n", |
| 858 | __set_bit(IPS_EXPECTED_BIT, &ct->status); | 987 | ct, exp); |
| 859 | ct->master = exp->master; | 988 | /* Welcome, Mr. Bond. We've been expecting you... */ |
| 860 | if (exp->helper) { | 989 | __set_bit(IPS_EXPECTED_BIT, &ct->status); |
| 861 | help = nf_ct_helper_ext_add(ct, exp->helper, | 990 | /* exp->master safe, refcnt bumped in nf_ct_find_expectation */ |
| 862 | GFP_ATOMIC); | 991 | ct->master = exp->master; |
| 863 | if (help) | 992 | if (exp->helper) { |
| 864 | rcu_assign_pointer(help->helper, exp->helper); | 993 | help = nf_ct_helper_ext_add(ct, exp->helper, |
| 865 | } | 994 | GFP_ATOMIC); |
| 995 | if (help) | ||
| 996 | rcu_assign_pointer(help->helper, exp->helper); | ||
| 997 | } | ||
| 866 | 998 | ||
| 867 | #ifdef CONFIG_NF_CONNTRACK_MARK | 999 | #ifdef CONFIG_NF_CONNTRACK_MARK |
| 868 | ct->mark = exp->master->mark; | 1000 | ct->mark = exp->master->mark; |
| 869 | #endif | 1001 | #endif |
| 870 | #ifdef CONFIG_NF_CONNTRACK_SECMARK | 1002 | #ifdef CONFIG_NF_CONNTRACK_SECMARK |
| 871 | ct->secmark = exp->master->secmark; | 1003 | ct->secmark = exp->master->secmark; |
| 872 | #endif | 1004 | #endif |
| 873 | nf_conntrack_get(&ct->master->ct_general); | 1005 | NF_CT_STAT_INC(net, expect_new); |
| 874 | NF_CT_STAT_INC(net, expect_new); | 1006 | } |
| 875 | } else { | 1007 | spin_unlock(&nf_conntrack_expect_lock); |
| 1008 | } | ||
| 1009 | if (!exp) { | ||
| 876 | __nf_ct_try_assign_helper(ct, tmpl, GFP_ATOMIC); | 1010 | __nf_ct_try_assign_helper(ct, tmpl, GFP_ATOMIC); |
| 877 | NF_CT_STAT_INC(net, new); | 1011 | NF_CT_STAT_INC(net, new); |
| 878 | } | 1012 | } |
| 879 | 1013 | ||
| 880 | /* Now it is inserted into the unconfirmed list, bump refcount */ | 1014 | /* Now it is inserted into the unconfirmed list, bump refcount */ |
| 881 | nf_conntrack_get(&ct->ct_general); | 1015 | nf_conntrack_get(&ct->ct_general); |
| 1016 | nf_ct_add_to_unconfirmed_list(ct); | ||
| 882 | 1017 | ||
| 883 | /* Overload tuple linked list to put us in unconfirmed list. */ | 1018 | local_bh_enable(); |
| 884 | hlist_nulls_add_head_rcu(&ct->tuplehash[IP_CT_DIR_ORIGINAL].hnnode, | ||
| 885 | &net->ct.unconfirmed); | ||
| 886 | |||
| 887 | spin_unlock_bh(&nf_conntrack_lock); | ||
| 888 | 1019 | ||
| 889 | if (exp) { | 1020 | if (exp) { |
| 890 | if (exp->expectfn) | 1021 | if (exp->expectfn) |
| @@ -1254,27 +1385,42 @@ get_next_corpse(struct net *net, int (*iter)(struct nf_conn *i, void *data), | |||
| 1254 | struct nf_conntrack_tuple_hash *h; | 1385 | struct nf_conntrack_tuple_hash *h; |
| 1255 | struct nf_conn *ct; | 1386 | struct nf_conn *ct; |
| 1256 | struct hlist_nulls_node *n; | 1387 | struct hlist_nulls_node *n; |
| 1388 | int cpu; | ||
| 1389 | spinlock_t *lockp; | ||
| 1257 | 1390 | ||
| 1258 | spin_lock_bh(&nf_conntrack_lock); | ||
| 1259 | for (; *bucket < net->ct.htable_size; (*bucket)++) { | 1391 | for (; *bucket < net->ct.htable_size; (*bucket)++) { |
| 1260 | hlist_nulls_for_each_entry(h, n, &net->ct.hash[*bucket], hnnode) { | 1392 | lockp = &nf_conntrack_locks[*bucket % CONNTRACK_LOCKS]; |
| 1261 | if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL) | 1393 | local_bh_disable(); |
| 1262 | continue; | 1394 | spin_lock(lockp); |
| 1395 | if (*bucket < net->ct.htable_size) { | ||
| 1396 | hlist_nulls_for_each_entry(h, n, &net->ct.hash[*bucket], hnnode) { | ||
| 1397 | if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL) | ||
| 1398 | continue; | ||
| 1399 | ct = nf_ct_tuplehash_to_ctrack(h); | ||
| 1400 | if (iter(ct, data)) | ||
| 1401 | goto found; | ||
| 1402 | } | ||
| 1403 | } | ||
| 1404 | spin_unlock(lockp); | ||
| 1405 | local_bh_enable(); | ||
| 1406 | } | ||
| 1407 | |||
| 1408 | for_each_possible_cpu(cpu) { | ||
| 1409 | struct ct_pcpu *pcpu = per_cpu_ptr(net->ct.pcpu_lists, cpu); | ||
| 1410 | |||
| 1411 | spin_lock_bh(&pcpu->lock); | ||
| 1412 | hlist_nulls_for_each_entry(h, n, &pcpu->unconfirmed, hnnode) { | ||
| 1263 | ct = nf_ct_tuplehash_to_ctrack(h); | 1413 | ct = nf_ct_tuplehash_to_ctrack(h); |
| 1264 | if (iter(ct, data)) | 1414 | if (iter(ct, data)) |
| 1265 | goto found; | 1415 | set_bit(IPS_DYING_BIT, &ct->status); |
| 1266 | } | 1416 | } |
| 1417 | spin_unlock_bh(&pcpu->lock); | ||
| 1267 | } | 1418 | } |
| 1268 | hlist_nulls_for_each_entry(h, n, &net->ct.unconfirmed, hnnode) { | ||
| 1269 | ct = nf_ct_tuplehash_to_ctrack(h); | ||
| 1270 | if (iter(ct, data)) | ||
| 1271 | set_bit(IPS_DYING_BIT, &ct->status); | ||
| 1272 | } | ||
| 1273 | spin_unlock_bh(&nf_conntrack_lock); | ||
| 1274 | return NULL; | 1419 | return NULL; |
| 1275 | found: | 1420 | found: |
| 1276 | atomic_inc(&ct->ct_general.use); | 1421 | atomic_inc(&ct->ct_general.use); |
| 1277 | spin_unlock_bh(&nf_conntrack_lock); | 1422 | spin_unlock(lockp); |
| 1423 | local_bh_enable(); | ||
| 1278 | return ct; | 1424 | return ct; |
| 1279 | } | 1425 | } |
| 1280 | 1426 | ||
| @@ -1323,14 +1469,19 @@ static void nf_ct_release_dying_list(struct net *net) | |||
| 1323 | struct nf_conntrack_tuple_hash *h; | 1469 | struct nf_conntrack_tuple_hash *h; |
| 1324 | struct nf_conn *ct; | 1470 | struct nf_conn *ct; |
| 1325 | struct hlist_nulls_node *n; | 1471 | struct hlist_nulls_node *n; |
| 1472 | int cpu; | ||
| 1326 | 1473 | ||
| 1327 | spin_lock_bh(&nf_conntrack_lock); | 1474 | for_each_possible_cpu(cpu) { |
| 1328 | hlist_nulls_for_each_entry(h, n, &net->ct.dying, hnnode) { | 1475 | struct ct_pcpu *pcpu = per_cpu_ptr(net->ct.pcpu_lists, cpu); |
| 1329 | ct = nf_ct_tuplehash_to_ctrack(h); | 1476 | |
| 1330 | /* never fails to remove them, no listeners at this point */ | 1477 | spin_lock_bh(&pcpu->lock); |
| 1331 | nf_ct_kill(ct); | 1478 | hlist_nulls_for_each_entry(h, n, &pcpu->dying, hnnode) { |
| 1479 | ct = nf_ct_tuplehash_to_ctrack(h); | ||
| 1480 | /* never fails to remove them, no listeners at this point */ | ||
| 1481 | nf_ct_kill(ct); | ||
| 1482 | } | ||
| 1483 | spin_unlock_bh(&pcpu->lock); | ||
| 1332 | } | 1484 | } |
| 1333 | spin_unlock_bh(&nf_conntrack_lock); | ||
| 1334 | } | 1485 | } |
| 1335 | 1486 | ||
| 1336 | static int untrack_refs(void) | 1487 | static int untrack_refs(void) |
| @@ -1417,6 +1568,7 @@ i_see_dead_people: | |||
| 1417 | kmem_cache_destroy(net->ct.nf_conntrack_cachep); | 1568 | kmem_cache_destroy(net->ct.nf_conntrack_cachep); |
| 1418 | kfree(net->ct.slabname); | 1569 | kfree(net->ct.slabname); |
| 1419 | free_percpu(net->ct.stat); | 1570 | free_percpu(net->ct.stat); |
| 1571 | free_percpu(net->ct.pcpu_lists); | ||
| 1420 | } | 1572 | } |
| 1421 | } | 1573 | } |
| 1422 | 1574 | ||
| @@ -1469,12 +1621,16 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp) | |||
| 1469 | if (!hash) | 1621 | if (!hash) |
| 1470 | return -ENOMEM; | 1622 | return -ENOMEM; |
| 1471 | 1623 | ||
| 1624 | local_bh_disable(); | ||
| 1625 | nf_conntrack_all_lock(); | ||
| 1626 | write_seqcount_begin(&init_net.ct.generation); | ||
| 1627 | |||
| 1472 | /* Lookups in the old hash might happen in parallel, which means we | 1628 | /* Lookups in the old hash might happen in parallel, which means we |
| 1473 | * might get false negatives during connection lookup. New connections | 1629 | * might get false negatives during connection lookup. New connections |
| 1474 | * created because of a false negative won't make it into the hash | 1630 | * created because of a false negative won't make it into the hash |
| 1475 | * though since that required taking the lock. | 1631 | * though since that required taking the locks. |
| 1476 | */ | 1632 | */ |
| 1477 | spin_lock_bh(&nf_conntrack_lock); | 1633 | |
| 1478 | for (i = 0; i < init_net.ct.htable_size; i++) { | 1634 | for (i = 0; i < init_net.ct.htable_size; i++) { |
| 1479 | while (!hlist_nulls_empty(&init_net.ct.hash[i])) { | 1635 | while (!hlist_nulls_empty(&init_net.ct.hash[i])) { |
| 1480 | h = hlist_nulls_entry(init_net.ct.hash[i].first, | 1636 | h = hlist_nulls_entry(init_net.ct.hash[i].first, |
| @@ -1491,7 +1647,10 @@ int nf_conntrack_set_hashsize(const char *val, struct kernel_param *kp) | |||
| 1491 | 1647 | ||
| 1492 | init_net.ct.htable_size = nf_conntrack_htable_size = hashsize; | 1648 | init_net.ct.htable_size = nf_conntrack_htable_size = hashsize; |
| 1493 | init_net.ct.hash = hash; | 1649 | init_net.ct.hash = hash; |
| 1494 | spin_unlock_bh(&nf_conntrack_lock); | 1650 | |
| 1651 | write_seqcount_end(&init_net.ct.generation); | ||
| 1652 | nf_conntrack_all_unlock(); | ||
| 1653 | local_bh_enable(); | ||
| 1495 | 1654 | ||
| 1496 | nf_ct_free_hashtable(old_hash, old_size); | 1655 | nf_ct_free_hashtable(old_hash, old_size); |
| 1497 | return 0; | 1656 | return 0; |
| @@ -1513,7 +1672,10 @@ EXPORT_SYMBOL_GPL(nf_ct_untracked_status_or); | |||
| 1513 | int nf_conntrack_init_start(void) | 1672 | int nf_conntrack_init_start(void) |
| 1514 | { | 1673 | { |
| 1515 | int max_factor = 8; | 1674 | int max_factor = 8; |
| 1516 | int ret, cpu; | 1675 | int i, ret, cpu; |
| 1676 | |||
| 1677 | for (i = 0; i < CONNTRACK_LOCKS; i++) | ||
| 1678 | spin_lock_init(&nf_conntrack_locks[i]); | ||
| 1517 | 1679 | ||
| 1518 | /* Idea from tcp.c: use 1/16384 of memory. On i386: 32MB | 1680 | /* Idea from tcp.c: use 1/16384 of memory. On i386: 32MB |
| 1519 | * machine has 512 buckets. >= 1GB machines have 16384 buckets. */ | 1681 | * machine has 512 buckets. >= 1GB machines have 16384 buckets. */ |
| @@ -1629,37 +1791,44 @@ void nf_conntrack_init_end(void) | |||
| 1629 | 1791 | ||
| 1630 | int nf_conntrack_init_net(struct net *net) | 1792 | int nf_conntrack_init_net(struct net *net) |
| 1631 | { | 1793 | { |
| 1632 | int ret; | 1794 | int ret = -ENOMEM; |
| 1795 | int cpu; | ||
| 1633 | 1796 | ||
| 1634 | atomic_set(&net->ct.count, 0); | 1797 | atomic_set(&net->ct.count, 0); |
| 1635 | INIT_HLIST_NULLS_HEAD(&net->ct.unconfirmed, UNCONFIRMED_NULLS_VAL); | 1798 | seqcount_init(&net->ct.generation); |
| 1636 | INIT_HLIST_NULLS_HEAD(&net->ct.dying, DYING_NULLS_VAL); | 1799 | |
| 1637 | INIT_HLIST_NULLS_HEAD(&net->ct.tmpl, TEMPLATE_NULLS_VAL); | 1800 | net->ct.pcpu_lists = alloc_percpu(struct ct_pcpu); |
| 1638 | net->ct.stat = alloc_percpu(struct ip_conntrack_stat); | 1801 | if (!net->ct.pcpu_lists) |
| 1639 | if (!net->ct.stat) { | ||
| 1640 | ret = -ENOMEM; | ||
| 1641 | goto err_stat; | 1802 | goto err_stat; |
| 1803 | |||
| 1804 | for_each_possible_cpu(cpu) { | ||
| 1805 | struct ct_pcpu *pcpu = per_cpu_ptr(net->ct.pcpu_lists, cpu); | ||
| 1806 | |||
| 1807 | spin_lock_init(&pcpu->lock); | ||
| 1808 | INIT_HLIST_NULLS_HEAD(&pcpu->unconfirmed, UNCONFIRMED_NULLS_VAL); | ||
| 1809 | INIT_HLIST_NULLS_HEAD(&pcpu->dying, DYING_NULLS_VAL); | ||
| 1810 | INIT_HLIST_NULLS_HEAD(&pcpu->tmpl, TEMPLATE_NULLS_VAL); | ||
| 1642 | } | 1811 | } |
| 1643 | 1812 | ||
| 1813 | net->ct.stat = alloc_percpu(struct ip_conntrack_stat); | ||
| 1814 | if (!net->ct.stat) | ||
| 1815 | goto err_pcpu_lists; | ||
| 1816 | |||
| 1644 | net->ct.slabname = kasprintf(GFP_KERNEL, "nf_conntrack_%p", net); | 1817 | net->ct.slabname = kasprintf(GFP_KERNEL, "nf_conntrack_%p", net); |
| 1645 | if (!net->ct.slabname) { | 1818 | if (!net->ct.slabname) |
| 1646 | ret = -ENOMEM; | ||
| 1647 | goto err_slabname; | 1819 | goto err_slabname; |
| 1648 | } | ||
| 1649 | 1820 | ||
| 1650 | net->ct.nf_conntrack_cachep = kmem_cache_create(net->ct.slabname, | 1821 | net->ct.nf_conntrack_cachep = kmem_cache_create(net->ct.slabname, |
| 1651 | sizeof(struct nf_conn), 0, | 1822 | sizeof(struct nf_conn), 0, |
| 1652 | SLAB_DESTROY_BY_RCU, NULL); | 1823 | SLAB_DESTROY_BY_RCU, NULL); |
| 1653 | if (!net->ct.nf_conntrack_cachep) { | 1824 | if (!net->ct.nf_conntrack_cachep) { |
| 1654 | printk(KERN_ERR "Unable to create nf_conn slab cache\n"); | 1825 | printk(KERN_ERR "Unable to create nf_conn slab cache\n"); |
| 1655 | ret = -ENOMEM; | ||
| 1656 | goto err_cache; | 1826 | goto err_cache; |
| 1657 | } | 1827 | } |
| 1658 | 1828 | ||
| 1659 | net->ct.htable_size = nf_conntrack_htable_size; | 1829 | net->ct.htable_size = nf_conntrack_htable_size; |
| 1660 | net->ct.hash = nf_ct_alloc_hashtable(&net->ct.htable_size, 1); | 1830 | net->ct.hash = nf_ct_alloc_hashtable(&net->ct.htable_size, 1); |
| 1661 | if (!net->ct.hash) { | 1831 | if (!net->ct.hash) { |
| 1662 | ret = -ENOMEM; | ||
| 1663 | printk(KERN_ERR "Unable to create nf_conntrack_hash\n"); | 1832 | printk(KERN_ERR "Unable to create nf_conntrack_hash\n"); |
| 1664 | goto err_hash; | 1833 | goto err_hash; |
| 1665 | } | 1834 | } |
| @@ -1701,6 +1870,8 @@ err_cache: | |||
| 1701 | kfree(net->ct.slabname); | 1870 | kfree(net->ct.slabname); |
| 1702 | err_slabname: | 1871 | err_slabname: |
| 1703 | free_percpu(net->ct.stat); | 1872 | free_percpu(net->ct.stat); |
| 1873 | err_pcpu_lists: | ||
| 1874 | free_percpu(net->ct.pcpu_lists); | ||
| 1704 | err_stat: | 1875 | err_stat: |
| 1705 | return ret; | 1876 | return ret; |
| 1706 | } | 1877 | } |
diff --git a/net/netfilter/nf_conntrack_expect.c b/net/netfilter/nf_conntrack_expect.c index 4fd1ca94fd4a..f87e8f68ad45 100644 --- a/net/netfilter/nf_conntrack_expect.c +++ b/net/netfilter/nf_conntrack_expect.c | |||
| @@ -66,9 +66,9 @@ static void nf_ct_expectation_timed_out(unsigned long ul_expect) | |||
| 66 | { | 66 | { |
| 67 | struct nf_conntrack_expect *exp = (void *)ul_expect; | 67 | struct nf_conntrack_expect *exp = (void *)ul_expect; |
| 68 | 68 | ||
| 69 | spin_lock_bh(&nf_conntrack_lock); | 69 | spin_lock_bh(&nf_conntrack_expect_lock); |
| 70 | nf_ct_unlink_expect(exp); | 70 | nf_ct_unlink_expect(exp); |
| 71 | spin_unlock_bh(&nf_conntrack_lock); | 71 | spin_unlock_bh(&nf_conntrack_expect_lock); |
| 72 | nf_ct_expect_put(exp); | 72 | nf_ct_expect_put(exp); |
| 73 | } | 73 | } |
| 74 | 74 | ||
| @@ -155,6 +155,18 @@ nf_ct_find_expectation(struct net *net, u16 zone, | |||
| 155 | if (!nf_ct_is_confirmed(exp->master)) | 155 | if (!nf_ct_is_confirmed(exp->master)) |
| 156 | return NULL; | 156 | return NULL; |
| 157 | 157 | ||
| 158 | /* Avoid race with other CPUs, that for exp->master ct, is | ||
| 159 | * about to invoke ->destroy(), or nf_ct_delete() via timeout | ||
| 160 | * or early_drop(). | ||
| 161 | * | ||
| 162 | * The atomic_inc_not_zero() check tells: If that fails, we | ||
| 163 | * know that the ct is being destroyed. If it succeeds, we | ||
| 164 | * can be sure the ct cannot disappear underneath. | ||
| 165 | */ | ||
| 166 | if (unlikely(nf_ct_is_dying(exp->master) || | ||
| 167 | !atomic_inc_not_zero(&exp->master->ct_general.use))) | ||
| 168 | return NULL; | ||
| 169 | |||
| 158 | if (exp->flags & NF_CT_EXPECT_PERMANENT) { | 170 | if (exp->flags & NF_CT_EXPECT_PERMANENT) { |
| 159 | atomic_inc(&exp->use); | 171 | atomic_inc(&exp->use); |
| 160 | return exp; | 172 | return exp; |
| @@ -162,6 +174,8 @@ nf_ct_find_expectation(struct net *net, u16 zone, | |||
| 162 | nf_ct_unlink_expect(exp); | 174 | nf_ct_unlink_expect(exp); |
| 163 | return exp; | 175 | return exp; |
| 164 | } | 176 | } |
| 177 | /* Undo exp->master refcnt increase, if del_timer() failed */ | ||
| 178 | nf_ct_put(exp->master); | ||
| 165 | 179 | ||
| 166 | return NULL; | 180 | return NULL; |
| 167 | } | 181 | } |
| @@ -177,12 +191,14 @@ void nf_ct_remove_expectations(struct nf_conn *ct) | |||
| 177 | if (!help) | 191 | if (!help) |
| 178 | return; | 192 | return; |
| 179 | 193 | ||
| 194 | spin_lock_bh(&nf_conntrack_expect_lock); | ||
| 180 | hlist_for_each_entry_safe(exp, next, &help->expectations, lnode) { | 195 | hlist_for_each_entry_safe(exp, next, &help->expectations, lnode) { |
| 181 | if (del_timer(&exp->timeout)) { | 196 | if (del_timer(&exp->timeout)) { |
| 182 | nf_ct_unlink_expect(exp); | 197 | nf_ct_unlink_expect(exp); |
| 183 | nf_ct_expect_put(exp); | 198 | nf_ct_expect_put(exp); |
| 184 | } | 199 | } |
| 185 | } | 200 | } |
| 201 | spin_unlock_bh(&nf_conntrack_expect_lock); | ||
| 186 | } | 202 | } |
| 187 | EXPORT_SYMBOL_GPL(nf_ct_remove_expectations); | 203 | EXPORT_SYMBOL_GPL(nf_ct_remove_expectations); |
| 188 | 204 | ||
| @@ -217,12 +233,12 @@ static inline int expect_matches(const struct nf_conntrack_expect *a, | |||
| 217 | /* Generally a bad idea to call this: could have matched already. */ | 233 | /* Generally a bad idea to call this: could have matched already. */ |
| 218 | void nf_ct_unexpect_related(struct nf_conntrack_expect *exp) | 234 | void nf_ct_unexpect_related(struct nf_conntrack_expect *exp) |
| 219 | { | 235 | { |
| 220 | spin_lock_bh(&nf_conntrack_lock); | 236 | spin_lock_bh(&nf_conntrack_expect_lock); |
| 221 | if (del_timer(&exp->timeout)) { | 237 | if (del_timer(&exp->timeout)) { |
| 222 | nf_ct_unlink_expect(exp); | 238 | nf_ct_unlink_expect(exp); |
| 223 | nf_ct_expect_put(exp); | 239 | nf_ct_expect_put(exp); |
| 224 | } | 240 | } |
| 225 | spin_unlock_bh(&nf_conntrack_lock); | 241 | spin_unlock_bh(&nf_conntrack_expect_lock); |
| 226 | } | 242 | } |
| 227 | EXPORT_SYMBOL_GPL(nf_ct_unexpect_related); | 243 | EXPORT_SYMBOL_GPL(nf_ct_unexpect_related); |
| 228 | 244 | ||
| @@ -335,7 +351,7 @@ static int nf_ct_expect_insert(struct nf_conntrack_expect *exp) | |||
| 335 | setup_timer(&exp->timeout, nf_ct_expectation_timed_out, | 351 | setup_timer(&exp->timeout, nf_ct_expectation_timed_out, |
| 336 | (unsigned long)exp); | 352 | (unsigned long)exp); |
| 337 | helper = rcu_dereference_protected(master_help->helper, | 353 | helper = rcu_dereference_protected(master_help->helper, |
| 338 | lockdep_is_held(&nf_conntrack_lock)); | 354 | lockdep_is_held(&nf_conntrack_expect_lock)); |
| 339 | if (helper) { | 355 | if (helper) { |
| 340 | exp->timeout.expires = jiffies + | 356 | exp->timeout.expires = jiffies + |
| 341 | helper->expect_policy[exp->class].timeout * HZ; | 357 | helper->expect_policy[exp->class].timeout * HZ; |
| @@ -395,7 +411,7 @@ static inline int __nf_ct_expect_check(struct nf_conntrack_expect *expect) | |||
| 395 | } | 411 | } |
| 396 | /* Will be over limit? */ | 412 | /* Will be over limit? */ |
| 397 | helper = rcu_dereference_protected(master_help->helper, | 413 | helper = rcu_dereference_protected(master_help->helper, |
| 398 | lockdep_is_held(&nf_conntrack_lock)); | 414 | lockdep_is_held(&nf_conntrack_expect_lock)); |
| 399 | if (helper) { | 415 | if (helper) { |
| 400 | p = &helper->expect_policy[expect->class]; | 416 | p = &helper->expect_policy[expect->class]; |
| 401 | if (p->max_expected && | 417 | if (p->max_expected && |
| @@ -417,12 +433,12 @@ out: | |||
| 417 | return ret; | 433 | return ret; |
| 418 | } | 434 | } |
| 419 | 435 | ||
| 420 | int nf_ct_expect_related_report(struct nf_conntrack_expect *expect, | 436 | int nf_ct_expect_related_report(struct nf_conntrack_expect *expect, |
| 421 | u32 portid, int report) | 437 | u32 portid, int report) |
| 422 | { | 438 | { |
| 423 | int ret; | 439 | int ret; |
| 424 | 440 | ||
| 425 | spin_lock_bh(&nf_conntrack_lock); | 441 | spin_lock_bh(&nf_conntrack_expect_lock); |
| 426 | ret = __nf_ct_expect_check(expect); | 442 | ret = __nf_ct_expect_check(expect); |
| 427 | if (ret <= 0) | 443 | if (ret <= 0) |
| 428 | goto out; | 444 | goto out; |
| @@ -430,11 +446,11 @@ int nf_ct_expect_related_report(struct nf_conntrack_expect *expect, | |||
| 430 | ret = nf_ct_expect_insert(expect); | 446 | ret = nf_ct_expect_insert(expect); |
| 431 | if (ret < 0) | 447 | if (ret < 0) |
| 432 | goto out; | 448 | goto out; |
| 433 | spin_unlock_bh(&nf_conntrack_lock); | 449 | spin_unlock_bh(&nf_conntrack_expect_lock); |
| 434 | nf_ct_expect_event_report(IPEXP_NEW, expect, portid, report); | 450 | nf_ct_expect_event_report(IPEXP_NEW, expect, portid, report); |
| 435 | return ret; | 451 | return ret; |
| 436 | out: | 452 | out: |
| 437 | spin_unlock_bh(&nf_conntrack_lock); | 453 | spin_unlock_bh(&nf_conntrack_expect_lock); |
| 438 | return ret; | 454 | return ret; |
| 439 | } | 455 | } |
| 440 | EXPORT_SYMBOL_GPL(nf_ct_expect_related_report); | 456 | EXPORT_SYMBOL_GPL(nf_ct_expect_related_report); |
diff --git a/net/netfilter/nf_conntrack_h323_main.c b/net/netfilter/nf_conntrack_h323_main.c index 70866d192efc..3a3a60b126e0 100644 --- a/net/netfilter/nf_conntrack_h323_main.c +++ b/net/netfilter/nf_conntrack_h323_main.c | |||
| @@ -1476,7 +1476,7 @@ static int process_rcf(struct sk_buff *skb, struct nf_conn *ct, | |||
| 1476 | nf_ct_refresh(ct, skb, info->timeout * HZ); | 1476 | nf_ct_refresh(ct, skb, info->timeout * HZ); |
| 1477 | 1477 | ||
| 1478 | /* Set expect timeout */ | 1478 | /* Set expect timeout */ |
| 1479 | spin_lock_bh(&nf_conntrack_lock); | 1479 | spin_lock_bh(&nf_conntrack_expect_lock); |
| 1480 | exp = find_expect(ct, &ct->tuplehash[dir].tuple.dst.u3, | 1480 | exp = find_expect(ct, &ct->tuplehash[dir].tuple.dst.u3, |
| 1481 | info->sig_port[!dir]); | 1481 | info->sig_port[!dir]); |
| 1482 | if (exp) { | 1482 | if (exp) { |
| @@ -1486,7 +1486,7 @@ static int process_rcf(struct sk_buff *skb, struct nf_conn *ct, | |||
| 1486 | nf_ct_dump_tuple(&exp->tuple); | 1486 | nf_ct_dump_tuple(&exp->tuple); |
| 1487 | set_expect_timeout(exp, info->timeout); | 1487 | set_expect_timeout(exp, info->timeout); |
| 1488 | } | 1488 | } |
| 1489 | spin_unlock_bh(&nf_conntrack_lock); | 1489 | spin_unlock_bh(&nf_conntrack_expect_lock); |
| 1490 | } | 1490 | } |
| 1491 | 1491 | ||
| 1492 | return 0; | 1492 | return 0; |
diff --git a/net/netfilter/nf_conntrack_helper.c b/net/netfilter/nf_conntrack_helper.c index 974a2a4adefa..5b3eae7d4c9a 100644 --- a/net/netfilter/nf_conntrack_helper.c +++ b/net/netfilter/nf_conntrack_helper.c | |||
| @@ -250,16 +250,14 @@ out: | |||
| 250 | } | 250 | } |
| 251 | EXPORT_SYMBOL_GPL(__nf_ct_try_assign_helper); | 251 | EXPORT_SYMBOL_GPL(__nf_ct_try_assign_helper); |
| 252 | 252 | ||
| 253 | /* appropiate ct lock protecting must be taken by caller */ | ||
| 253 | static inline int unhelp(struct nf_conntrack_tuple_hash *i, | 254 | static inline int unhelp(struct nf_conntrack_tuple_hash *i, |
| 254 | const struct nf_conntrack_helper *me) | 255 | const struct nf_conntrack_helper *me) |
| 255 | { | 256 | { |
| 256 | struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(i); | 257 | struct nf_conn *ct = nf_ct_tuplehash_to_ctrack(i); |
| 257 | struct nf_conn_help *help = nfct_help(ct); | 258 | struct nf_conn_help *help = nfct_help(ct); |
| 258 | 259 | ||
| 259 | if (help && rcu_dereference_protected( | 260 | if (help && rcu_dereference_raw(help->helper) == me) { |
| 260 | help->helper, | ||
| 261 | lockdep_is_held(&nf_conntrack_lock) | ||
| 262 | ) == me) { | ||
| 263 | nf_conntrack_event(IPCT_HELPER, ct); | 261 | nf_conntrack_event(IPCT_HELPER, ct); |
| 264 | RCU_INIT_POINTER(help->helper, NULL); | 262 | RCU_INIT_POINTER(help->helper, NULL); |
| 265 | } | 263 | } |
| @@ -284,17 +282,17 @@ static LIST_HEAD(nf_ct_helper_expectfn_list); | |||
| 284 | 282 | ||
| 285 | void nf_ct_helper_expectfn_register(struct nf_ct_helper_expectfn *n) | 283 | void nf_ct_helper_expectfn_register(struct nf_ct_helper_expectfn *n) |
| 286 | { | 284 | { |
| 287 | spin_lock_bh(&nf_conntrack_lock); | 285 | spin_lock_bh(&nf_conntrack_expect_lock); |
| 288 | list_add_rcu(&n->head, &nf_ct_helper_expectfn_list); | 286 | list_add_rcu(&n->head, &nf_ct_helper_expectfn_list); |
| 289 | spin_unlock_bh(&nf_conntrack_lock); | 287 | spin_unlock_bh(&nf_conntrack_expect_lock); |
| 290 | } | 288 | } |
| 291 | EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_register); | 289 | EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_register); |
| 292 | 290 | ||
| 293 | void nf_ct_helper_expectfn_unregister(struct nf_ct_helper_expectfn *n) | 291 | void nf_ct_helper_expectfn_unregister(struct nf_ct_helper_expectfn *n) |
| 294 | { | 292 | { |
| 295 | spin_lock_bh(&nf_conntrack_lock); | 293 | spin_lock_bh(&nf_conntrack_expect_lock); |
| 296 | list_del_rcu(&n->head); | 294 | list_del_rcu(&n->head); |
| 297 | spin_unlock_bh(&nf_conntrack_lock); | 295 | spin_unlock_bh(&nf_conntrack_expect_lock); |
| 298 | } | 296 | } |
| 299 | EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_unregister); | 297 | EXPORT_SYMBOL_GPL(nf_ct_helper_expectfn_unregister); |
| 300 | 298 | ||
| @@ -396,15 +394,17 @@ static void __nf_conntrack_helper_unregister(struct nf_conntrack_helper *me, | |||
| 396 | const struct hlist_node *next; | 394 | const struct hlist_node *next; |
| 397 | const struct hlist_nulls_node *nn; | 395 | const struct hlist_nulls_node *nn; |
| 398 | unsigned int i; | 396 | unsigned int i; |
| 397 | int cpu; | ||
| 399 | 398 | ||
| 400 | /* Get rid of expectations */ | 399 | /* Get rid of expectations */ |
| 400 | spin_lock_bh(&nf_conntrack_expect_lock); | ||
| 401 | for (i = 0; i < nf_ct_expect_hsize; i++) { | 401 | for (i = 0; i < nf_ct_expect_hsize; i++) { |
| 402 | hlist_for_each_entry_safe(exp, next, | 402 | hlist_for_each_entry_safe(exp, next, |
| 403 | &net->ct.expect_hash[i], hnode) { | 403 | &net->ct.expect_hash[i], hnode) { |
| 404 | struct nf_conn_help *help = nfct_help(exp->master); | 404 | struct nf_conn_help *help = nfct_help(exp->master); |
| 405 | if ((rcu_dereference_protected( | 405 | if ((rcu_dereference_protected( |
| 406 | help->helper, | 406 | help->helper, |
| 407 | lockdep_is_held(&nf_conntrack_lock) | 407 | lockdep_is_held(&nf_conntrack_expect_lock) |
| 408 | ) == me || exp->helper == me) && | 408 | ) == me || exp->helper == me) && |
| 409 | del_timer(&exp->timeout)) { | 409 | del_timer(&exp->timeout)) { |
| 410 | nf_ct_unlink_expect(exp); | 410 | nf_ct_unlink_expect(exp); |
| @@ -412,14 +412,27 @@ static void __nf_conntrack_helper_unregister(struct nf_conntrack_helper *me, | |||
| 412 | } | 412 | } |
| 413 | } | 413 | } |
| 414 | } | 414 | } |
| 415 | spin_unlock_bh(&nf_conntrack_expect_lock); | ||
| 415 | 416 | ||
| 416 | /* Get rid of expecteds, set helpers to NULL. */ | 417 | /* Get rid of expecteds, set helpers to NULL. */ |
| 417 | hlist_nulls_for_each_entry(h, nn, &net->ct.unconfirmed, hnnode) | 418 | for_each_possible_cpu(cpu) { |
| 418 | unhelp(h, me); | 419 | struct ct_pcpu *pcpu = per_cpu_ptr(net->ct.pcpu_lists, cpu); |
| 419 | for (i = 0; i < net->ct.htable_size; i++) { | 420 | |
| 420 | hlist_nulls_for_each_entry(h, nn, &net->ct.hash[i], hnnode) | 421 | spin_lock_bh(&pcpu->lock); |
| 422 | hlist_nulls_for_each_entry(h, nn, &pcpu->unconfirmed, hnnode) | ||
| 421 | unhelp(h, me); | 423 | unhelp(h, me); |
| 424 | spin_unlock_bh(&pcpu->lock); | ||
| 425 | } | ||
| 426 | local_bh_disable(); | ||
| 427 | for (i = 0; i < net->ct.htable_size; i++) { | ||
| 428 | spin_lock(&nf_conntrack_locks[i % CONNTRACK_LOCKS]); | ||
| 429 | if (i < net->ct.htable_size) { | ||
| 430 | hlist_nulls_for_each_entry(h, nn, &net->ct.hash[i], hnnode) | ||
| 431 | unhelp(h, me); | ||
| 432 | } | ||
| 433 | spin_unlock(&nf_conntrack_locks[i % CONNTRACK_LOCKS]); | ||
| 422 | } | 434 | } |
| 435 | local_bh_enable(); | ||
| 423 | } | 436 | } |
| 424 | 437 | ||
| 425 | void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) | 438 | void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) |
| @@ -437,10 +450,8 @@ void nf_conntrack_helper_unregister(struct nf_conntrack_helper *me) | |||
| 437 | synchronize_rcu(); | 450 | synchronize_rcu(); |
| 438 | 451 | ||
| 439 | rtnl_lock(); | 452 | rtnl_lock(); |
| 440 | spin_lock_bh(&nf_conntrack_lock); | ||
| 441 | for_each_net(net) | 453 | for_each_net(net) |
| 442 | __nf_conntrack_helper_unregister(me, net); | 454 | __nf_conntrack_helper_unregister(me, net); |
| 443 | spin_unlock_bh(&nf_conntrack_lock); | ||
| 444 | rtnl_unlock(); | 455 | rtnl_unlock(); |
| 445 | } | 456 | } |
| 446 | EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister); | 457 | EXPORT_SYMBOL_GPL(nf_conntrack_helper_unregister); |
diff --git a/net/netfilter/nf_conntrack_netlink.c b/net/netfilter/nf_conntrack_netlink.c index b9f0e0374322..ccc46fa5edbc 100644 --- a/net/netfilter/nf_conntrack_netlink.c +++ b/net/netfilter/nf_conntrack_netlink.c | |||
| @@ -764,14 +764,23 @@ ctnetlink_dump_table(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 764 | struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); | 764 | struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); |
| 765 | u_int8_t l3proto = nfmsg->nfgen_family; | 765 | u_int8_t l3proto = nfmsg->nfgen_family; |
| 766 | int res; | 766 | int res; |
| 767 | spinlock_t *lockp; | ||
| 768 | |||
| 767 | #ifdef CONFIG_NF_CONNTRACK_MARK | 769 | #ifdef CONFIG_NF_CONNTRACK_MARK |
| 768 | const struct ctnetlink_dump_filter *filter = cb->data; | 770 | const struct ctnetlink_dump_filter *filter = cb->data; |
| 769 | #endif | 771 | #endif |
| 770 | 772 | ||
| 771 | spin_lock_bh(&nf_conntrack_lock); | ||
| 772 | last = (struct nf_conn *)cb->args[1]; | 773 | last = (struct nf_conn *)cb->args[1]; |
| 774 | |||
| 775 | local_bh_disable(); | ||
| 773 | for (; cb->args[0] < net->ct.htable_size; cb->args[0]++) { | 776 | for (; cb->args[0] < net->ct.htable_size; cb->args[0]++) { |
| 774 | restart: | 777 | restart: |
| 778 | lockp = &nf_conntrack_locks[cb->args[0] % CONNTRACK_LOCKS]; | ||
| 779 | spin_lock(lockp); | ||
| 780 | if (cb->args[0] >= net->ct.htable_size) { | ||
| 781 | spin_unlock(lockp); | ||
| 782 | goto out; | ||
| 783 | } | ||
| 775 | hlist_nulls_for_each_entry(h, n, &net->ct.hash[cb->args[0]], | 784 | hlist_nulls_for_each_entry(h, n, &net->ct.hash[cb->args[0]], |
| 776 | hnnode) { | 785 | hnnode) { |
| 777 | if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL) | 786 | if (NF_CT_DIRECTION(h) != IP_CT_DIR_ORIGINAL) |
| @@ -803,16 +812,18 @@ restart: | |||
| 803 | if (res < 0) { | 812 | if (res < 0) { |
| 804 | nf_conntrack_get(&ct->ct_general); | 813 | nf_conntrack_get(&ct->ct_general); |
| 805 | cb->args[1] = (unsigned long)ct; | 814 | cb->args[1] = (unsigned long)ct; |
| 815 | spin_unlock(lockp); | ||
| 806 | goto out; | 816 | goto out; |
| 807 | } | 817 | } |
| 808 | } | 818 | } |
| 819 | spin_unlock(lockp); | ||
| 809 | if (cb->args[1]) { | 820 | if (cb->args[1]) { |
| 810 | cb->args[1] = 0; | 821 | cb->args[1] = 0; |
| 811 | goto restart; | 822 | goto restart; |
| 812 | } | 823 | } |
| 813 | } | 824 | } |
| 814 | out: | 825 | out: |
| 815 | spin_unlock_bh(&nf_conntrack_lock); | 826 | local_bh_enable(); |
| 816 | if (last) | 827 | if (last) |
| 817 | nf_ct_put(last); | 828 | nf_ct_put(last); |
| 818 | 829 | ||
| @@ -966,7 +977,6 @@ ctnetlink_parse_help(const struct nlattr *attr, char **helper_name, | |||
| 966 | return 0; | 977 | return 0; |
| 967 | } | 978 | } |
| 968 | 979 | ||
| 969 | #define __CTA_LABELS_MAX_LENGTH ((XT_CONNLABEL_MAXBIT + 1) / BITS_PER_BYTE) | ||
| 970 | static const struct nla_policy ct_nla_policy[CTA_MAX+1] = { | 980 | static const struct nla_policy ct_nla_policy[CTA_MAX+1] = { |
| 971 | [CTA_TUPLE_ORIG] = { .type = NLA_NESTED }, | 981 | [CTA_TUPLE_ORIG] = { .type = NLA_NESTED }, |
| 972 | [CTA_TUPLE_REPLY] = { .type = NLA_NESTED }, | 982 | [CTA_TUPLE_REPLY] = { .type = NLA_NESTED }, |
| @@ -984,9 +994,9 @@ static const struct nla_policy ct_nla_policy[CTA_MAX+1] = { | |||
| 984 | [CTA_ZONE] = { .type = NLA_U16 }, | 994 | [CTA_ZONE] = { .type = NLA_U16 }, |
| 985 | [CTA_MARK_MASK] = { .type = NLA_U32 }, | 995 | [CTA_MARK_MASK] = { .type = NLA_U32 }, |
| 986 | [CTA_LABELS] = { .type = NLA_BINARY, | 996 | [CTA_LABELS] = { .type = NLA_BINARY, |
| 987 | .len = __CTA_LABELS_MAX_LENGTH }, | 997 | .len = NF_CT_LABELS_MAX_SIZE }, |
| 988 | [CTA_LABELS_MASK] = { .type = NLA_BINARY, | 998 | [CTA_LABELS_MASK] = { .type = NLA_BINARY, |
| 989 | .len = __CTA_LABELS_MAX_LENGTH }, | 999 | .len = NF_CT_LABELS_MAX_SIZE }, |
| 990 | }; | 1000 | }; |
| 991 | 1001 | ||
| 992 | static int | 1002 | static int |
| @@ -1138,50 +1148,65 @@ static int ctnetlink_done_list(struct netlink_callback *cb) | |||
| 1138 | } | 1148 | } |
| 1139 | 1149 | ||
| 1140 | static int | 1150 | static int |
| 1141 | ctnetlink_dump_list(struct sk_buff *skb, struct netlink_callback *cb, | 1151 | ctnetlink_dump_list(struct sk_buff *skb, struct netlink_callback *cb, bool dying) |
| 1142 | struct hlist_nulls_head *list) | ||
| 1143 | { | 1152 | { |
| 1144 | struct nf_conn *ct, *last; | 1153 | struct nf_conn *ct, *last = NULL; |
| 1145 | struct nf_conntrack_tuple_hash *h; | 1154 | struct nf_conntrack_tuple_hash *h; |
| 1146 | struct hlist_nulls_node *n; | 1155 | struct hlist_nulls_node *n; |
| 1147 | struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); | 1156 | struct nfgenmsg *nfmsg = nlmsg_data(cb->nlh); |
| 1148 | u_int8_t l3proto = nfmsg->nfgen_family; | 1157 | u_int8_t l3proto = nfmsg->nfgen_family; |
| 1149 | int res; | 1158 | int res; |
| 1159 | int cpu; | ||
| 1160 | struct hlist_nulls_head *list; | ||
| 1161 | struct net *net = sock_net(skb->sk); | ||
| 1150 | 1162 | ||
| 1151 | if (cb->args[2]) | 1163 | if (cb->args[2]) |
| 1152 | return 0; | 1164 | return 0; |
| 1153 | 1165 | ||
| 1154 | spin_lock_bh(&nf_conntrack_lock); | 1166 | if (cb->args[0] == nr_cpu_ids) |
| 1155 | last = (struct nf_conn *)cb->args[1]; | 1167 | return 0; |
| 1156 | restart: | 1168 | |
| 1157 | hlist_nulls_for_each_entry(h, n, list, hnnode) { | 1169 | for (cpu = cb->args[0]; cpu < nr_cpu_ids; cpu++) { |
| 1158 | ct = nf_ct_tuplehash_to_ctrack(h); | 1170 | struct ct_pcpu *pcpu; |
| 1159 | if (l3proto && nf_ct_l3num(ct) != l3proto) | 1171 | |
| 1172 | if (!cpu_possible(cpu)) | ||
| 1160 | continue; | 1173 | continue; |
| 1161 | if (cb->args[1]) { | 1174 | |
| 1162 | if (ct != last) | 1175 | pcpu = per_cpu_ptr(net->ct.pcpu_lists, cpu); |
| 1176 | spin_lock_bh(&pcpu->lock); | ||
| 1177 | last = (struct nf_conn *)cb->args[1]; | ||
| 1178 | list = dying ? &pcpu->dying : &pcpu->unconfirmed; | ||
| 1179 | restart: | ||
| 1180 | hlist_nulls_for_each_entry(h, n, list, hnnode) { | ||
| 1181 | ct = nf_ct_tuplehash_to_ctrack(h); | ||
| 1182 | if (l3proto && nf_ct_l3num(ct) != l3proto) | ||
| 1163 | continue; | 1183 | continue; |
| 1164 | cb->args[1] = 0; | 1184 | if (cb->args[1]) { |
| 1165 | } | 1185 | if (ct != last) |
| 1166 | rcu_read_lock(); | 1186 | continue; |
| 1167 | res = ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).portid, | 1187 | cb->args[1] = 0; |
| 1168 | cb->nlh->nlmsg_seq, | 1188 | } |
| 1169 | NFNL_MSG_TYPE(cb->nlh->nlmsg_type), | 1189 | rcu_read_lock(); |
| 1170 | ct); | 1190 | res = ctnetlink_fill_info(skb, NETLINK_CB(cb->skb).portid, |
| 1171 | rcu_read_unlock(); | 1191 | cb->nlh->nlmsg_seq, |
| 1172 | if (res < 0) { | 1192 | NFNL_MSG_TYPE(cb->nlh->nlmsg_type), |
| 1173 | nf_conntrack_get(&ct->ct_general); | 1193 | ct); |
| 1174 | cb->args[1] = (unsigned long)ct; | 1194 | rcu_read_unlock(); |
| 1175 | goto out; | 1195 | if (res < 0) { |
| 1196 | nf_conntrack_get(&ct->ct_general); | ||
| 1197 | cb->args[1] = (unsigned long)ct; | ||
| 1198 | spin_unlock_bh(&pcpu->lock); | ||
| 1199 | goto out; | ||
| 1200 | } | ||
| 1176 | } | 1201 | } |
| 1202 | if (cb->args[1]) { | ||
| 1203 | cb->args[1] = 0; | ||
| 1204 | goto restart; | ||
| 1205 | } else | ||
| 1206 | cb->args[2] = 1; | ||
| 1207 | spin_unlock_bh(&pcpu->lock); | ||
| 1177 | } | 1208 | } |
| 1178 | if (cb->args[1]) { | ||
| 1179 | cb->args[1] = 0; | ||
| 1180 | goto restart; | ||
| 1181 | } else | ||
| 1182 | cb->args[2] = 1; | ||
| 1183 | out: | 1209 | out: |
| 1184 | spin_unlock_bh(&nf_conntrack_lock); | ||
| 1185 | if (last) | 1210 | if (last) |
| 1186 | nf_ct_put(last); | 1211 | nf_ct_put(last); |
| 1187 | 1212 | ||
| @@ -1191,9 +1216,7 @@ out: | |||
| 1191 | static int | 1216 | static int |
| 1192 | ctnetlink_dump_dying(struct sk_buff *skb, struct netlink_callback *cb) | 1217 | ctnetlink_dump_dying(struct sk_buff *skb, struct netlink_callback *cb) |
| 1193 | { | 1218 | { |
| 1194 | struct net *net = sock_net(skb->sk); | 1219 | return ctnetlink_dump_list(skb, cb, true); |
| 1195 | |||
| 1196 | return ctnetlink_dump_list(skb, cb, &net->ct.dying); | ||
| 1197 | } | 1220 | } |
| 1198 | 1221 | ||
| 1199 | static int | 1222 | static int |
| @@ -1215,9 +1238,7 @@ ctnetlink_get_ct_dying(struct sock *ctnl, struct sk_buff *skb, | |||
| 1215 | static int | 1238 | static int |
| 1216 | ctnetlink_dump_unconfirmed(struct sk_buff *skb, struct netlink_callback *cb) | 1239 | ctnetlink_dump_unconfirmed(struct sk_buff *skb, struct netlink_callback *cb) |
| 1217 | { | 1240 | { |
| 1218 | struct net *net = sock_net(skb->sk); | 1241 | return ctnetlink_dump_list(skb, cb, false); |
| 1219 | |||
| 1220 | return ctnetlink_dump_list(skb, cb, &net->ct.unconfirmed); | ||
| 1221 | } | 1242 | } |
| 1222 | 1243 | ||
| 1223 | static int | 1244 | static int |
| @@ -1361,14 +1382,14 @@ ctnetlink_change_helper(struct nf_conn *ct, const struct nlattr * const cda[]) | |||
| 1361 | nf_ct_protonum(ct)); | 1382 | nf_ct_protonum(ct)); |
| 1362 | if (helper == NULL) { | 1383 | if (helper == NULL) { |
| 1363 | #ifdef CONFIG_MODULES | 1384 | #ifdef CONFIG_MODULES |
| 1364 | spin_unlock_bh(&nf_conntrack_lock); | 1385 | spin_unlock_bh(&nf_conntrack_expect_lock); |
| 1365 | 1386 | ||
| 1366 | if (request_module("nfct-helper-%s", helpname) < 0) { | 1387 | if (request_module("nfct-helper-%s", helpname) < 0) { |
| 1367 | spin_lock_bh(&nf_conntrack_lock); | 1388 | spin_lock_bh(&nf_conntrack_expect_lock); |
| 1368 | return -EOPNOTSUPP; | 1389 | return -EOPNOTSUPP; |
| 1369 | } | 1390 | } |
| 1370 | 1391 | ||
| 1371 | spin_lock_bh(&nf_conntrack_lock); | 1392 | spin_lock_bh(&nf_conntrack_expect_lock); |
| 1372 | helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct), | 1393 | helper = __nf_conntrack_helper_find(helpname, nf_ct_l3num(ct), |
| 1373 | nf_ct_protonum(ct)); | 1394 | nf_ct_protonum(ct)); |
| 1374 | if (helper) | 1395 | if (helper) |
| @@ -1804,9 +1825,9 @@ ctnetlink_new_conntrack(struct sock *ctnl, struct sk_buff *skb, | |||
| 1804 | err = -EEXIST; | 1825 | err = -EEXIST; |
| 1805 | ct = nf_ct_tuplehash_to_ctrack(h); | 1826 | ct = nf_ct_tuplehash_to_ctrack(h); |
| 1806 | if (!(nlh->nlmsg_flags & NLM_F_EXCL)) { | 1827 | if (!(nlh->nlmsg_flags & NLM_F_EXCL)) { |
| 1807 | spin_lock_bh(&nf_conntrack_lock); | 1828 | spin_lock_bh(&nf_conntrack_expect_lock); |
| 1808 | err = ctnetlink_change_conntrack(ct, cda); | 1829 | err = ctnetlink_change_conntrack(ct, cda); |
| 1809 | spin_unlock_bh(&nf_conntrack_lock); | 1830 | spin_unlock_bh(&nf_conntrack_expect_lock); |
| 1810 | if (err == 0) { | 1831 | if (err == 0) { |
| 1811 | nf_conntrack_eventmask_report((1 << IPCT_REPLY) | | 1832 | nf_conntrack_eventmask_report((1 << IPCT_REPLY) | |
| 1812 | (1 << IPCT_ASSURED) | | 1833 | (1 << IPCT_ASSURED) | |
| @@ -2135,9 +2156,9 @@ ctnetlink_nfqueue_parse(const struct nlattr *attr, struct nf_conn *ct) | |||
| 2135 | if (ret < 0) | 2156 | if (ret < 0) |
| 2136 | return ret; | 2157 | return ret; |
| 2137 | 2158 | ||
| 2138 | spin_lock_bh(&nf_conntrack_lock); | 2159 | spin_lock_bh(&nf_conntrack_expect_lock); |
| 2139 | ret = ctnetlink_nfqueue_parse_ct((const struct nlattr **)cda, ct); | 2160 | ret = ctnetlink_nfqueue_parse_ct((const struct nlattr **)cda, ct); |
| 2140 | spin_unlock_bh(&nf_conntrack_lock); | 2161 | spin_unlock_bh(&nf_conntrack_expect_lock); |
| 2141 | 2162 | ||
| 2142 | return ret; | 2163 | return ret; |
| 2143 | } | 2164 | } |
| @@ -2692,13 +2713,13 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, | |||
| 2692 | } | 2713 | } |
| 2693 | 2714 | ||
| 2694 | /* after list removal, usage count == 1 */ | 2715 | /* after list removal, usage count == 1 */ |
| 2695 | spin_lock_bh(&nf_conntrack_lock); | 2716 | spin_lock_bh(&nf_conntrack_expect_lock); |
| 2696 | if (del_timer(&exp->timeout)) { | 2717 | if (del_timer(&exp->timeout)) { |
| 2697 | nf_ct_unlink_expect_report(exp, NETLINK_CB(skb).portid, | 2718 | nf_ct_unlink_expect_report(exp, NETLINK_CB(skb).portid, |
| 2698 | nlmsg_report(nlh)); | 2719 | nlmsg_report(nlh)); |
| 2699 | nf_ct_expect_put(exp); | 2720 | nf_ct_expect_put(exp); |
| 2700 | } | 2721 | } |
| 2701 | spin_unlock_bh(&nf_conntrack_lock); | 2722 | spin_unlock_bh(&nf_conntrack_expect_lock); |
| 2702 | /* have to put what we 'get' above. | 2723 | /* have to put what we 'get' above. |
| 2703 | * after this line usage count == 0 */ | 2724 | * after this line usage count == 0 */ |
| 2704 | nf_ct_expect_put(exp); | 2725 | nf_ct_expect_put(exp); |
| @@ -2707,7 +2728,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, | |||
| 2707 | struct nf_conn_help *m_help; | 2728 | struct nf_conn_help *m_help; |
| 2708 | 2729 | ||
| 2709 | /* delete all expectations for this helper */ | 2730 | /* delete all expectations for this helper */ |
| 2710 | spin_lock_bh(&nf_conntrack_lock); | 2731 | spin_lock_bh(&nf_conntrack_expect_lock); |
| 2711 | for (i = 0; i < nf_ct_expect_hsize; i++) { | 2732 | for (i = 0; i < nf_ct_expect_hsize; i++) { |
| 2712 | hlist_for_each_entry_safe(exp, next, | 2733 | hlist_for_each_entry_safe(exp, next, |
| 2713 | &net->ct.expect_hash[i], | 2734 | &net->ct.expect_hash[i], |
| @@ -2722,10 +2743,10 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, | |||
| 2722 | } | 2743 | } |
| 2723 | } | 2744 | } |
| 2724 | } | 2745 | } |
| 2725 | spin_unlock_bh(&nf_conntrack_lock); | 2746 | spin_unlock_bh(&nf_conntrack_expect_lock); |
| 2726 | } else { | 2747 | } else { |
| 2727 | /* This basically means we have to flush everything*/ | 2748 | /* This basically means we have to flush everything*/ |
| 2728 | spin_lock_bh(&nf_conntrack_lock); | 2749 | spin_lock_bh(&nf_conntrack_expect_lock); |
| 2729 | for (i = 0; i < nf_ct_expect_hsize; i++) { | 2750 | for (i = 0; i < nf_ct_expect_hsize; i++) { |
| 2730 | hlist_for_each_entry_safe(exp, next, | 2751 | hlist_for_each_entry_safe(exp, next, |
| 2731 | &net->ct.expect_hash[i], | 2752 | &net->ct.expect_hash[i], |
| @@ -2738,7 +2759,7 @@ ctnetlink_del_expect(struct sock *ctnl, struct sk_buff *skb, | |||
| 2738 | } | 2759 | } |
| 2739 | } | 2760 | } |
| 2740 | } | 2761 | } |
| 2741 | spin_unlock_bh(&nf_conntrack_lock); | 2762 | spin_unlock_bh(&nf_conntrack_expect_lock); |
| 2742 | } | 2763 | } |
| 2743 | 2764 | ||
| 2744 | return 0; | 2765 | return 0; |
| @@ -2964,11 +2985,11 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb, | |||
| 2964 | if (err < 0) | 2985 | if (err < 0) |
| 2965 | return err; | 2986 | return err; |
| 2966 | 2987 | ||
| 2967 | spin_lock_bh(&nf_conntrack_lock); | 2988 | spin_lock_bh(&nf_conntrack_expect_lock); |
| 2968 | exp = __nf_ct_expect_find(net, zone, &tuple); | 2989 | exp = __nf_ct_expect_find(net, zone, &tuple); |
| 2969 | 2990 | ||
| 2970 | if (!exp) { | 2991 | if (!exp) { |
| 2971 | spin_unlock_bh(&nf_conntrack_lock); | 2992 | spin_unlock_bh(&nf_conntrack_expect_lock); |
| 2972 | err = -ENOENT; | 2993 | err = -ENOENT; |
| 2973 | if (nlh->nlmsg_flags & NLM_F_CREATE) { | 2994 | if (nlh->nlmsg_flags & NLM_F_CREATE) { |
| 2974 | err = ctnetlink_create_expect(net, zone, cda, | 2995 | err = ctnetlink_create_expect(net, zone, cda, |
| @@ -2982,7 +3003,7 @@ ctnetlink_new_expect(struct sock *ctnl, struct sk_buff *skb, | |||
| 2982 | err = -EEXIST; | 3003 | err = -EEXIST; |
| 2983 | if (!(nlh->nlmsg_flags & NLM_F_EXCL)) | 3004 | if (!(nlh->nlmsg_flags & NLM_F_EXCL)) |
| 2984 | err = ctnetlink_change_expect(exp, cda); | 3005 | err = ctnetlink_change_expect(exp, cda); |
| 2985 | spin_unlock_bh(&nf_conntrack_lock); | 3006 | spin_unlock_bh(&nf_conntrack_expect_lock); |
| 2986 | 3007 | ||
| 2987 | return err; | 3008 | return err; |
| 2988 | } | 3009 | } |
diff --git a/net/netfilter/nf_conntrack_pptp.c b/net/netfilter/nf_conntrack_pptp.c index 7bd03decd36c..825c3e3f8305 100644 --- a/net/netfilter/nf_conntrack_pptp.c +++ b/net/netfilter/nf_conntrack_pptp.c | |||
| @@ -605,32 +605,14 @@ static struct nf_conntrack_helper pptp __read_mostly = { | |||
| 605 | .expect_policy = &pptp_exp_policy, | 605 | .expect_policy = &pptp_exp_policy, |
| 606 | }; | 606 | }; |
| 607 | 607 | ||
| 608 | static void nf_conntrack_pptp_net_exit(struct net *net) | ||
| 609 | { | ||
| 610 | nf_ct_gre_keymap_flush(net); | ||
| 611 | } | ||
| 612 | |||
| 613 | static struct pernet_operations nf_conntrack_pptp_net_ops = { | ||
| 614 | .exit = nf_conntrack_pptp_net_exit, | ||
| 615 | }; | ||
| 616 | |||
| 617 | static int __init nf_conntrack_pptp_init(void) | 608 | static int __init nf_conntrack_pptp_init(void) |
| 618 | { | 609 | { |
| 619 | int rv; | 610 | return nf_conntrack_helper_register(&pptp); |
| 620 | |||
| 621 | rv = nf_conntrack_helper_register(&pptp); | ||
| 622 | if (rv < 0) | ||
| 623 | return rv; | ||
| 624 | rv = register_pernet_subsys(&nf_conntrack_pptp_net_ops); | ||
| 625 | if (rv < 0) | ||
| 626 | nf_conntrack_helper_unregister(&pptp); | ||
| 627 | return rv; | ||
| 628 | } | 611 | } |
| 629 | 612 | ||
| 630 | static void __exit nf_conntrack_pptp_fini(void) | 613 | static void __exit nf_conntrack_pptp_fini(void) |
| 631 | { | 614 | { |
| 632 | nf_conntrack_helper_unregister(&pptp); | 615 | nf_conntrack_helper_unregister(&pptp); |
| 633 | unregister_pernet_subsys(&nf_conntrack_pptp_net_ops); | ||
| 634 | } | 616 | } |
| 635 | 617 | ||
| 636 | module_init(nf_conntrack_pptp_init); | 618 | module_init(nf_conntrack_pptp_init); |
diff --git a/net/netfilter/nf_conntrack_proto_gre.c b/net/netfilter/nf_conntrack_proto_gre.c index 9d9c0dade602..d5665739e3b1 100644 --- a/net/netfilter/nf_conntrack_proto_gre.c +++ b/net/netfilter/nf_conntrack_proto_gre.c | |||
| @@ -66,7 +66,7 @@ static inline struct netns_proto_gre *gre_pernet(struct net *net) | |||
| 66 | return net_generic(net, proto_gre_net_id); | 66 | return net_generic(net, proto_gre_net_id); |
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | void nf_ct_gre_keymap_flush(struct net *net) | 69 | static void nf_ct_gre_keymap_flush(struct net *net) |
| 70 | { | 70 | { |
| 71 | struct netns_proto_gre *net_gre = gre_pernet(net); | 71 | struct netns_proto_gre *net_gre = gre_pernet(net); |
| 72 | struct nf_ct_gre_keymap *km, *tmp; | 72 | struct nf_ct_gre_keymap *km, *tmp; |
| @@ -78,7 +78,6 @@ void nf_ct_gre_keymap_flush(struct net *net) | |||
| 78 | } | 78 | } |
| 79 | write_unlock_bh(&net_gre->keymap_lock); | 79 | write_unlock_bh(&net_gre->keymap_lock); |
| 80 | } | 80 | } |
| 81 | EXPORT_SYMBOL(nf_ct_gre_keymap_flush); | ||
| 82 | 81 | ||
| 83 | static inline int gre_key_cmpfn(const struct nf_ct_gre_keymap *km, | 82 | static inline int gre_key_cmpfn(const struct nf_ct_gre_keymap *km, |
| 84 | const struct nf_conntrack_tuple *t) | 83 | const struct nf_conntrack_tuple *t) |
diff --git a/net/netfilter/nf_conntrack_sip.c b/net/netfilter/nf_conntrack_sip.c index 466410eaa482..4c3ba1c8d682 100644 --- a/net/netfilter/nf_conntrack_sip.c +++ b/net/netfilter/nf_conntrack_sip.c | |||
| @@ -800,7 +800,7 @@ static int refresh_signalling_expectation(struct nf_conn *ct, | |||
| 800 | struct hlist_node *next; | 800 | struct hlist_node *next; |
| 801 | int found = 0; | 801 | int found = 0; |
| 802 | 802 | ||
| 803 | spin_lock_bh(&nf_conntrack_lock); | 803 | spin_lock_bh(&nf_conntrack_expect_lock); |
| 804 | hlist_for_each_entry_safe(exp, next, &help->expectations, lnode) { | 804 | hlist_for_each_entry_safe(exp, next, &help->expectations, lnode) { |
| 805 | if (exp->class != SIP_EXPECT_SIGNALLING || | 805 | if (exp->class != SIP_EXPECT_SIGNALLING || |
| 806 | !nf_inet_addr_cmp(&exp->tuple.dst.u3, addr) || | 806 | !nf_inet_addr_cmp(&exp->tuple.dst.u3, addr) || |
| @@ -815,7 +815,7 @@ static int refresh_signalling_expectation(struct nf_conn *ct, | |||
| 815 | found = 1; | 815 | found = 1; |
| 816 | break; | 816 | break; |
| 817 | } | 817 | } |
| 818 | spin_unlock_bh(&nf_conntrack_lock); | 818 | spin_unlock_bh(&nf_conntrack_expect_lock); |
| 819 | return found; | 819 | return found; |
| 820 | } | 820 | } |
| 821 | 821 | ||
| @@ -825,7 +825,7 @@ static void flush_expectations(struct nf_conn *ct, bool media) | |||
| 825 | struct nf_conntrack_expect *exp; | 825 | struct nf_conntrack_expect *exp; |
| 826 | struct hlist_node *next; | 826 | struct hlist_node *next; |
| 827 | 827 | ||
| 828 | spin_lock_bh(&nf_conntrack_lock); | 828 | spin_lock_bh(&nf_conntrack_expect_lock); |
| 829 | hlist_for_each_entry_safe(exp, next, &help->expectations, lnode) { | 829 | hlist_for_each_entry_safe(exp, next, &help->expectations, lnode) { |
| 830 | if ((exp->class != SIP_EXPECT_SIGNALLING) ^ media) | 830 | if ((exp->class != SIP_EXPECT_SIGNALLING) ^ media) |
| 831 | continue; | 831 | continue; |
| @@ -836,7 +836,7 @@ static void flush_expectations(struct nf_conn *ct, bool media) | |||
| 836 | if (!media) | 836 | if (!media) |
| 837 | break; | 837 | break; |
| 838 | } | 838 | } |
| 839 | spin_unlock_bh(&nf_conntrack_lock); | 839 | spin_unlock_bh(&nf_conntrack_expect_lock); |
| 840 | } | 840 | } |
| 841 | 841 | ||
| 842 | static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int protoff, | 842 | static int set_expected_rtp_rtcp(struct sk_buff *skb, unsigned int protoff, |
diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index adce01e8bb57..3fd159db9f06 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c | |||
| @@ -152,8 +152,8 @@ nf_tables_chain_type_lookup(const struct nft_af_info *afi, | |||
| 152 | #ifdef CONFIG_MODULES | 152 | #ifdef CONFIG_MODULES |
| 153 | if (autoload) { | 153 | if (autoload) { |
| 154 | nfnl_unlock(NFNL_SUBSYS_NFTABLES); | 154 | nfnl_unlock(NFNL_SUBSYS_NFTABLES); |
| 155 | request_module("nft-chain-%u-%*.s", afi->family, | 155 | request_module("nft-chain-%u-%.*s", afi->family, |
| 156 | nla_len(nla)-1, (const char *)nla_data(nla)); | 156 | nla_len(nla), (const char *)nla_data(nla)); |
| 157 | nfnl_lock(NFNL_SUBSYS_NFTABLES); | 157 | nfnl_lock(NFNL_SUBSYS_NFTABLES); |
| 158 | type = __nf_tables_chain_type_lookup(afi->family, nla); | 158 | type = __nf_tables_chain_type_lookup(afi->family, nla); |
| 159 | if (type != NULL) | 159 | if (type != NULL) |
| @@ -794,9 +794,8 @@ nf_tables_counters(struct nft_base_chain *chain, const struct nlattr *attr) | |||
| 794 | stats->pkts = be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_PACKETS])); | 794 | stats->pkts = be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_PACKETS])); |
| 795 | 795 | ||
| 796 | if (chain->stats) { | 796 | if (chain->stats) { |
| 797 | /* nfnl_lock is held, add some nfnl function for this, later */ | ||
| 798 | struct nft_stats __percpu *oldstats = | 797 | struct nft_stats __percpu *oldstats = |
| 799 | rcu_dereference_protected(chain->stats, 1); | 798 | nft_dereference(chain->stats); |
| 800 | 799 | ||
| 801 | rcu_assign_pointer(chain->stats, newstats); | 800 | rcu_assign_pointer(chain->stats, newstats); |
| 802 | synchronize_rcu(); | 801 | synchronize_rcu(); |
| @@ -1254,10 +1253,11 @@ err1: | |||
| 1254 | return err; | 1253 | return err; |
| 1255 | } | 1254 | } |
| 1256 | 1255 | ||
| 1257 | static void nf_tables_expr_destroy(struct nft_expr *expr) | 1256 | static void nf_tables_expr_destroy(const struct nft_ctx *ctx, |
| 1257 | struct nft_expr *expr) | ||
| 1258 | { | 1258 | { |
| 1259 | if (expr->ops->destroy) | 1259 | if (expr->ops->destroy) |
| 1260 | expr->ops->destroy(expr); | 1260 | expr->ops->destroy(ctx, expr); |
| 1261 | module_put(expr->ops->type->owner); | 1261 | module_put(expr->ops->type->owner); |
| 1262 | } | 1262 | } |
| 1263 | 1263 | ||
| @@ -1296,6 +1296,8 @@ static const struct nla_policy nft_rule_policy[NFTA_RULE_MAX + 1] = { | |||
| 1296 | [NFTA_RULE_EXPRESSIONS] = { .type = NLA_NESTED }, | 1296 | [NFTA_RULE_EXPRESSIONS] = { .type = NLA_NESTED }, |
| 1297 | [NFTA_RULE_COMPAT] = { .type = NLA_NESTED }, | 1297 | [NFTA_RULE_COMPAT] = { .type = NLA_NESTED }, |
| 1298 | [NFTA_RULE_POSITION] = { .type = NLA_U64 }, | 1298 | [NFTA_RULE_POSITION] = { .type = NLA_U64 }, |
| 1299 | [NFTA_RULE_USERDATA] = { .type = NLA_BINARY, | ||
| 1300 | .len = NFT_USERDATA_MAXLEN }, | ||
| 1299 | }; | 1301 | }; |
| 1300 | 1302 | ||
| 1301 | static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq, | 1303 | static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq, |
| @@ -1348,6 +1350,10 @@ static int nf_tables_fill_rule_info(struct sk_buff *skb, u32 portid, u32 seq, | |||
| 1348 | } | 1350 | } |
| 1349 | nla_nest_end(skb, list); | 1351 | nla_nest_end(skb, list); |
| 1350 | 1352 | ||
| 1353 | if (rule->ulen && | ||
| 1354 | nla_put(skb, NFTA_RULE_USERDATA, rule->ulen, nft_userdata(rule))) | ||
| 1355 | goto nla_put_failure; | ||
| 1356 | |||
| 1351 | return nlmsg_end(skb, nlh); | 1357 | return nlmsg_end(skb, nlh); |
| 1352 | 1358 | ||
| 1353 | nla_put_failure: | 1359 | nla_put_failure: |
| @@ -1531,7 +1537,8 @@ err: | |||
| 1531 | return err; | 1537 | return err; |
| 1532 | } | 1538 | } |
| 1533 | 1539 | ||
| 1534 | static void nf_tables_rule_destroy(struct nft_rule *rule) | 1540 | static void nf_tables_rule_destroy(const struct nft_ctx *ctx, |
| 1541 | struct nft_rule *rule) | ||
| 1535 | { | 1542 | { |
| 1536 | struct nft_expr *expr; | 1543 | struct nft_expr *expr; |
| 1537 | 1544 | ||
| @@ -1541,7 +1548,7 @@ static void nf_tables_rule_destroy(struct nft_rule *rule) | |||
| 1541 | */ | 1548 | */ |
| 1542 | expr = nft_expr_first(rule); | 1549 | expr = nft_expr_first(rule); |
| 1543 | while (expr->ops && expr != nft_expr_last(rule)) { | 1550 | while (expr->ops && expr != nft_expr_last(rule)) { |
| 1544 | nf_tables_expr_destroy(expr); | 1551 | nf_tables_expr_destroy(ctx, expr); |
| 1545 | expr = nft_expr_next(expr); | 1552 | expr = nft_expr_next(expr); |
| 1546 | } | 1553 | } |
| 1547 | kfree(rule); | 1554 | kfree(rule); |
| @@ -1552,7 +1559,7 @@ static void nf_tables_rule_destroy(struct nft_rule *rule) | |||
| 1552 | static struct nft_expr_info *info; | 1559 | static struct nft_expr_info *info; |
| 1553 | 1560 | ||
| 1554 | static struct nft_rule_trans * | 1561 | static struct nft_rule_trans * |
| 1555 | nf_tables_trans_add(struct nft_rule *rule, const struct nft_ctx *ctx) | 1562 | nf_tables_trans_add(struct nft_ctx *ctx, struct nft_rule *rule) |
| 1556 | { | 1563 | { |
| 1557 | struct nft_rule_trans *rupd; | 1564 | struct nft_rule_trans *rupd; |
| 1558 | 1565 | ||
| @@ -1560,11 +1567,8 @@ nf_tables_trans_add(struct nft_rule *rule, const struct nft_ctx *ctx) | |||
| 1560 | if (rupd == NULL) | 1567 | if (rupd == NULL) |
| 1561 | return NULL; | 1568 | return NULL; |
| 1562 | 1569 | ||
| 1563 | rupd->chain = ctx->chain; | 1570 | rupd->ctx = *ctx; |
| 1564 | rupd->table = ctx->table; | ||
| 1565 | rupd->rule = rule; | 1571 | rupd->rule = rule; |
| 1566 | rupd->family = ctx->afi->family; | ||
| 1567 | rupd->nlh = ctx->nlh; | ||
| 1568 | list_add_tail(&rupd->list, &ctx->net->nft.commit_list); | 1572 | list_add_tail(&rupd->list, &ctx->net->nft.commit_list); |
| 1569 | 1573 | ||
| 1570 | return rupd; | 1574 | return rupd; |
| @@ -1584,7 +1588,7 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb, | |||
| 1584 | struct nft_expr *expr; | 1588 | struct nft_expr *expr; |
| 1585 | struct nft_ctx ctx; | 1589 | struct nft_ctx ctx; |
| 1586 | struct nlattr *tmp; | 1590 | struct nlattr *tmp; |
| 1587 | unsigned int size, i, n; | 1591 | unsigned int size, i, n, ulen = 0; |
| 1588 | int err, rem; | 1592 | int err, rem; |
| 1589 | bool create; | 1593 | bool create; |
| 1590 | u64 handle, pos_handle; | 1594 | u64 handle, pos_handle; |
| @@ -1650,8 +1654,11 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb, | |||
| 1650 | } | 1654 | } |
| 1651 | } | 1655 | } |
| 1652 | 1656 | ||
| 1657 | if (nla[NFTA_RULE_USERDATA]) | ||
| 1658 | ulen = nla_len(nla[NFTA_RULE_USERDATA]); | ||
| 1659 | |||
| 1653 | err = -ENOMEM; | 1660 | err = -ENOMEM; |
| 1654 | rule = kzalloc(sizeof(*rule) + size, GFP_KERNEL); | 1661 | rule = kzalloc(sizeof(*rule) + size + ulen, GFP_KERNEL); |
| 1655 | if (rule == NULL) | 1662 | if (rule == NULL) |
| 1656 | goto err1; | 1663 | goto err1; |
| 1657 | 1664 | ||
| @@ -1659,6 +1666,10 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb, | |||
| 1659 | 1666 | ||
| 1660 | rule->handle = handle; | 1667 | rule->handle = handle; |
| 1661 | rule->dlen = size; | 1668 | rule->dlen = size; |
| 1669 | rule->ulen = ulen; | ||
| 1670 | |||
| 1671 | if (ulen) | ||
| 1672 | nla_memcpy(nft_userdata(rule), nla[NFTA_RULE_USERDATA], ulen); | ||
| 1662 | 1673 | ||
| 1663 | expr = nft_expr_first(rule); | 1674 | expr = nft_expr_first(rule); |
| 1664 | for (i = 0; i < n; i++) { | 1675 | for (i = 0; i < n; i++) { |
| @@ -1671,7 +1682,7 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb, | |||
| 1671 | 1682 | ||
| 1672 | if (nlh->nlmsg_flags & NLM_F_REPLACE) { | 1683 | if (nlh->nlmsg_flags & NLM_F_REPLACE) { |
| 1673 | if (nft_rule_is_active_next(net, old_rule)) { | 1684 | if (nft_rule_is_active_next(net, old_rule)) { |
| 1674 | repl = nf_tables_trans_add(old_rule, &ctx); | 1685 | repl = nf_tables_trans_add(&ctx, old_rule); |
| 1675 | if (repl == NULL) { | 1686 | if (repl == NULL) { |
| 1676 | err = -ENOMEM; | 1687 | err = -ENOMEM; |
| 1677 | goto err2; | 1688 | goto err2; |
| @@ -1694,7 +1705,7 @@ static int nf_tables_newrule(struct sock *nlsk, struct sk_buff *skb, | |||
| 1694 | list_add_rcu(&rule->list, &chain->rules); | 1705 | list_add_rcu(&rule->list, &chain->rules); |
| 1695 | } | 1706 | } |
| 1696 | 1707 | ||
| 1697 | if (nf_tables_trans_add(rule, &ctx) == NULL) { | 1708 | if (nf_tables_trans_add(&ctx, rule) == NULL) { |
| 1698 | err = -ENOMEM; | 1709 | err = -ENOMEM; |
| 1699 | goto err3; | 1710 | goto err3; |
| 1700 | } | 1711 | } |
| @@ -1709,7 +1720,7 @@ err3: | |||
| 1709 | kfree(repl); | 1720 | kfree(repl); |
| 1710 | } | 1721 | } |
| 1711 | err2: | 1722 | err2: |
| 1712 | nf_tables_rule_destroy(rule); | 1723 | nf_tables_rule_destroy(&ctx, rule); |
| 1713 | err1: | 1724 | err1: |
| 1714 | for (i = 0; i < n; i++) { | 1725 | for (i = 0; i < n; i++) { |
| 1715 | if (info[i].ops != NULL) | 1726 | if (info[i].ops != NULL) |
| @@ -1723,7 +1734,7 @@ nf_tables_delrule_one(struct nft_ctx *ctx, struct nft_rule *rule) | |||
| 1723 | { | 1734 | { |
| 1724 | /* You cannot delete the same rule twice */ | 1735 | /* You cannot delete the same rule twice */ |
| 1725 | if (nft_rule_is_active_next(ctx->net, rule)) { | 1736 | if (nft_rule_is_active_next(ctx->net, rule)) { |
| 1726 | if (nf_tables_trans_add(rule, ctx) == NULL) | 1737 | if (nf_tables_trans_add(ctx, rule) == NULL) |
| 1727 | return -ENOMEM; | 1738 | return -ENOMEM; |
| 1728 | nft_rule_disactivate_next(ctx->net, rule); | 1739 | nft_rule_disactivate_next(ctx->net, rule); |
| 1729 | return 0; | 1740 | return 0; |
| @@ -1819,10 +1830,10 @@ static int nf_tables_commit(struct sk_buff *skb) | |||
| 1819 | */ | 1830 | */ |
| 1820 | if (nft_rule_is_active(net, rupd->rule)) { | 1831 | if (nft_rule_is_active(net, rupd->rule)) { |
| 1821 | nft_rule_clear(net, rupd->rule); | 1832 | nft_rule_clear(net, rupd->rule); |
| 1822 | nf_tables_rule_notify(skb, rupd->nlh, rupd->table, | 1833 | nf_tables_rule_notify(skb, rupd->ctx.nlh, |
| 1823 | rupd->chain, rupd->rule, | 1834 | rupd->ctx.table, rupd->ctx.chain, |
| 1824 | NFT_MSG_NEWRULE, 0, | 1835 | rupd->rule, NFT_MSG_NEWRULE, 0, |
| 1825 | rupd->family); | 1836 | rupd->ctx.afi->family); |
| 1826 | list_del(&rupd->list); | 1837 | list_del(&rupd->list); |
| 1827 | kfree(rupd); | 1838 | kfree(rupd); |
| 1828 | continue; | 1839 | continue; |
| @@ -1830,9 +1841,10 @@ static int nf_tables_commit(struct sk_buff *skb) | |||
| 1830 | 1841 | ||
| 1831 | /* This rule is in the past, get rid of it */ | 1842 | /* This rule is in the past, get rid of it */ |
| 1832 | list_del_rcu(&rupd->rule->list); | 1843 | list_del_rcu(&rupd->rule->list); |
| 1833 | nf_tables_rule_notify(skb, rupd->nlh, rupd->table, rupd->chain, | 1844 | nf_tables_rule_notify(skb, rupd->ctx.nlh, |
| 1845 | rupd->ctx.table, rupd->ctx.chain, | ||
| 1834 | rupd->rule, NFT_MSG_DELRULE, 0, | 1846 | rupd->rule, NFT_MSG_DELRULE, 0, |
| 1835 | rupd->family); | 1847 | rupd->ctx.afi->family); |
| 1836 | } | 1848 | } |
| 1837 | 1849 | ||
| 1838 | /* Make sure we don't see any packet traversing old rules */ | 1850 | /* Make sure we don't see any packet traversing old rules */ |
| @@ -1840,7 +1852,7 @@ static int nf_tables_commit(struct sk_buff *skb) | |||
| 1840 | 1852 | ||
| 1841 | /* Now we can safely release unused old rules */ | 1853 | /* Now we can safely release unused old rules */ |
| 1842 | list_for_each_entry_safe(rupd, tmp, &net->nft.commit_list, list) { | 1854 | list_for_each_entry_safe(rupd, tmp, &net->nft.commit_list, list) { |
| 1843 | nf_tables_rule_destroy(rupd->rule); | 1855 | nf_tables_rule_destroy(&rupd->ctx, rupd->rule); |
| 1844 | list_del(&rupd->list); | 1856 | list_del(&rupd->list); |
| 1845 | kfree(rupd); | 1857 | kfree(rupd); |
| 1846 | } | 1858 | } |
| @@ -1869,7 +1881,7 @@ static int nf_tables_abort(struct sk_buff *skb) | |||
| 1869 | synchronize_rcu(); | 1881 | synchronize_rcu(); |
| 1870 | 1882 | ||
| 1871 | list_for_each_entry_safe(rupd, tmp, &net->nft.commit_list, list) { | 1883 | list_for_each_entry_safe(rupd, tmp, &net->nft.commit_list, list) { |
| 1872 | nf_tables_rule_destroy(rupd->rule); | 1884 | nf_tables_rule_destroy(&rupd->ctx, rupd->rule); |
| 1873 | list_del(&rupd->list); | 1885 | list_del(&rupd->list); |
| 1874 | kfree(rupd); | 1886 | kfree(rupd); |
| 1875 | } | 1887 | } |
| @@ -1934,7 +1946,8 @@ static const struct nft_set_ops *nft_select_set_ops(const struct nlattr * const | |||
| 1934 | 1946 | ||
| 1935 | static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = { | 1947 | static const struct nla_policy nft_set_policy[NFTA_SET_MAX + 1] = { |
| 1936 | [NFTA_SET_TABLE] = { .type = NLA_STRING }, | 1948 | [NFTA_SET_TABLE] = { .type = NLA_STRING }, |
| 1937 | [NFTA_SET_NAME] = { .type = NLA_STRING }, | 1949 | [NFTA_SET_NAME] = { .type = NLA_STRING, |
| 1950 | .len = IFNAMSIZ - 1 }, | ||
| 1938 | [NFTA_SET_FLAGS] = { .type = NLA_U32 }, | 1951 | [NFTA_SET_FLAGS] = { .type = NLA_U32 }, |
| 1939 | [NFTA_SET_KEY_TYPE] = { .type = NLA_U32 }, | 1952 | [NFTA_SET_KEY_TYPE] = { .type = NLA_U32 }, |
| 1940 | [NFTA_SET_KEY_LEN] = { .type = NLA_U32 }, | 1953 | [NFTA_SET_KEY_LEN] = { .type = NLA_U32 }, |
| @@ -2430,8 +2443,7 @@ err1: | |||
| 2430 | static void nf_tables_set_destroy(const struct nft_ctx *ctx, struct nft_set *set) | 2443 | static void nf_tables_set_destroy(const struct nft_ctx *ctx, struct nft_set *set) |
| 2431 | { | 2444 | { |
| 2432 | list_del(&set->list); | 2445 | list_del(&set->list); |
| 2433 | if (!(set->flags & NFT_SET_ANONYMOUS)) | 2446 | nf_tables_set_notify(ctx, set, NFT_MSG_DELSET); |
| 2434 | nf_tables_set_notify(ctx, set, NFT_MSG_DELSET); | ||
| 2435 | 2447 | ||
| 2436 | set->ops->destroy(set); | 2448 | set->ops->destroy(set); |
| 2437 | module_put(set->ops->owner); | 2449 | module_put(set->ops->owner); |
| @@ -3175,9 +3187,16 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data, | |||
| 3175 | data->verdict = ntohl(nla_get_be32(tb[NFTA_VERDICT_CODE])); | 3187 | data->verdict = ntohl(nla_get_be32(tb[NFTA_VERDICT_CODE])); |
| 3176 | 3188 | ||
| 3177 | switch (data->verdict) { | 3189 | switch (data->verdict) { |
| 3178 | case NF_ACCEPT: | 3190 | default: |
| 3179 | case NF_DROP: | 3191 | switch (data->verdict & NF_VERDICT_MASK) { |
| 3180 | case NF_QUEUE: | 3192 | case NF_ACCEPT: |
| 3193 | case NF_DROP: | ||
| 3194 | case NF_QUEUE: | ||
| 3195 | break; | ||
| 3196 | default: | ||
| 3197 | return -EINVAL; | ||
| 3198 | } | ||
| 3199 | /* fall through */ | ||
| 3181 | case NFT_CONTINUE: | 3200 | case NFT_CONTINUE: |
| 3182 | case NFT_BREAK: | 3201 | case NFT_BREAK: |
| 3183 | case NFT_RETURN: | 3202 | case NFT_RETURN: |
| @@ -3198,8 +3217,6 @@ static int nft_verdict_init(const struct nft_ctx *ctx, struct nft_data *data, | |||
| 3198 | data->chain = chain; | 3217 | data->chain = chain; |
| 3199 | desc->len = sizeof(data); | 3218 | desc->len = sizeof(data); |
| 3200 | break; | 3219 | break; |
| 3201 | default: | ||
| 3202 | return -EINVAL; | ||
| 3203 | } | 3220 | } |
| 3204 | 3221 | ||
| 3205 | desc->type = NFT_DATA_VERDICT; | 3222 | desc->type = NFT_DATA_VERDICT; |
diff --git a/net/netfilter/nf_tables_core.c b/net/netfilter/nf_tables_core.c index 90998a6ff8b9..804105391b9a 100644 --- a/net/netfilter/nf_tables_core.c +++ b/net/netfilter/nf_tables_core.c | |||
| @@ -25,9 +25,8 @@ static void nft_cmp_fast_eval(const struct nft_expr *expr, | |||
| 25 | struct nft_data data[NFT_REG_MAX + 1]) | 25 | struct nft_data data[NFT_REG_MAX + 1]) |
| 26 | { | 26 | { |
| 27 | const struct nft_cmp_fast_expr *priv = nft_expr_priv(expr); | 27 | const struct nft_cmp_fast_expr *priv = nft_expr_priv(expr); |
| 28 | u32 mask; | 28 | u32 mask = nft_cmp_fast_mask(priv->len); |
| 29 | 29 | ||
| 30 | mask = ~0U >> (sizeof(priv->data) * BITS_PER_BYTE - priv->len); | ||
| 31 | if ((data[priv->sreg].data[0] & mask) == priv->data) | 30 | if ((data[priv->sreg].data[0] & mask) == priv->data) |
| 32 | return; | 31 | return; |
| 33 | data[NFT_REG_VERDICT].verdict = NFT_BREAK; | 32 | data[NFT_REG_VERDICT].verdict = NFT_BREAK; |
diff --git a/net/netfilter/nfnetlink.c b/net/netfilter/nfnetlink.c index 046aa13b4fea..e8138da4c14f 100644 --- a/net/netfilter/nfnetlink.c +++ b/net/netfilter/nfnetlink.c | |||
| @@ -61,6 +61,14 @@ void nfnl_unlock(__u8 subsys_id) | |||
| 61 | } | 61 | } |
| 62 | EXPORT_SYMBOL_GPL(nfnl_unlock); | 62 | EXPORT_SYMBOL_GPL(nfnl_unlock); |
| 63 | 63 | ||
| 64 | #ifdef CONFIG_PROVE_LOCKING | ||
| 65 | int lockdep_nfnl_is_held(u8 subsys_id) | ||
| 66 | { | ||
| 67 | return lockdep_is_held(&table[subsys_id].mutex); | ||
| 68 | } | ||
| 69 | EXPORT_SYMBOL_GPL(lockdep_nfnl_is_held); | ||
| 70 | #endif | ||
| 71 | |||
| 64 | int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n) | 72 | int nfnetlink_subsys_register(const struct nfnetlink_subsystem *n) |
| 65 | { | 73 | { |
| 66 | nfnl_lock(n->subsys_id); | 74 | nfnl_lock(n->subsys_id); |
diff --git a/net/netfilter/nfnetlink_log.c b/net/netfilter/nfnetlink_log.c index a155d19a225e..d292c8d286eb 100644 --- a/net/netfilter/nfnetlink_log.c +++ b/net/netfilter/nfnetlink_log.c | |||
| @@ -28,8 +28,6 @@ | |||
| 28 | #include <linux/proc_fs.h> | 28 | #include <linux/proc_fs.h> |
| 29 | #include <linux/security.h> | 29 | #include <linux/security.h> |
| 30 | #include <linux/list.h> | 30 | #include <linux/list.h> |
| 31 | #include <linux/jhash.h> | ||
| 32 | #include <linux/random.h> | ||
| 33 | #include <linux/slab.h> | 31 | #include <linux/slab.h> |
| 34 | #include <net/sock.h> | 32 | #include <net/sock.h> |
| 35 | #include <net/netfilter/nf_log.h> | 33 | #include <net/netfilter/nf_log.h> |
| @@ -75,7 +73,6 @@ struct nfulnl_instance { | |||
| 75 | }; | 73 | }; |
| 76 | 74 | ||
| 77 | #define INSTANCE_BUCKETS 16 | 75 | #define INSTANCE_BUCKETS 16 |
| 78 | static unsigned int hash_init; | ||
| 79 | 76 | ||
| 80 | static int nfnl_log_net_id __read_mostly; | 77 | static int nfnl_log_net_id __read_mostly; |
| 81 | 78 | ||
| @@ -1067,11 +1064,6 @@ static int __init nfnetlink_log_init(void) | |||
| 1067 | { | 1064 | { |
| 1068 | int status = -ENOMEM; | 1065 | int status = -ENOMEM; |
| 1069 | 1066 | ||
| 1070 | /* it's not really all that important to have a random value, so | ||
| 1071 | * we can do this from the init function, even if there hasn't | ||
| 1072 | * been that much entropy yet */ | ||
| 1073 | get_random_bytes(&hash_init, sizeof(hash_init)); | ||
| 1074 | |||
| 1075 | netlink_register_notifier(&nfulnl_rtnl_notifier); | 1067 | netlink_register_notifier(&nfulnl_rtnl_notifier); |
| 1076 | status = nfnetlink_subsys_register(&nfulnl_subsys); | 1068 | status = nfnetlink_subsys_register(&nfulnl_subsys); |
| 1077 | if (status < 0) { | 1069 | if (status < 0) { |
diff --git a/net/netfilter/nft_cmp.c b/net/netfilter/nft_cmp.c index 954925db414d..e2b3f51c81f1 100644 --- a/net/netfilter/nft_cmp.c +++ b/net/netfilter/nft_cmp.c | |||
| @@ -128,7 +128,7 @@ static int nft_cmp_fast_init(const struct nft_ctx *ctx, | |||
| 128 | BUG_ON(err < 0); | 128 | BUG_ON(err < 0); |
| 129 | desc.len *= BITS_PER_BYTE; | 129 | desc.len *= BITS_PER_BYTE; |
| 130 | 130 | ||
| 131 | mask = ~0U >> (sizeof(priv->data) * BITS_PER_BYTE - desc.len); | 131 | mask = nft_cmp_fast_mask(desc.len); |
| 132 | priv->data = data.data[0] & mask; | 132 | priv->data = data.data[0] & mask; |
| 133 | priv->len = desc.len; | 133 | priv->len = desc.len; |
| 134 | return 0; | 134 | return 0; |
diff --git a/net/netfilter/nft_compat.c b/net/netfilter/nft_compat.c index 82cb8236f8a1..8a779be832fb 100644 --- a/net/netfilter/nft_compat.c +++ b/net/netfilter/nft_compat.c | |||
| @@ -192,7 +192,7 @@ err: | |||
| 192 | } | 192 | } |
| 193 | 193 | ||
| 194 | static void | 194 | static void |
| 195 | nft_target_destroy(const struct nft_expr *expr) | 195 | nft_target_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr) |
| 196 | { | 196 | { |
| 197 | struct xt_target *target = expr->ops->data; | 197 | struct xt_target *target = expr->ops->data; |
| 198 | 198 | ||
| @@ -379,7 +379,7 @@ err: | |||
| 379 | } | 379 | } |
| 380 | 380 | ||
| 381 | static void | 381 | static void |
| 382 | nft_match_destroy(const struct nft_expr *expr) | 382 | nft_match_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr) |
| 383 | { | 383 | { |
| 384 | struct xt_match *match = expr->ops->data; | 384 | struct xt_match *match = expr->ops->data; |
| 385 | 385 | ||
diff --git a/net/netfilter/nft_ct.c b/net/netfilter/nft_ct.c index 46e275403838..bd0d41e69341 100644 --- a/net/netfilter/nft_ct.c +++ b/net/netfilter/nft_ct.c | |||
| @@ -19,15 +19,15 @@ | |||
| 19 | #include <net/netfilter/nf_conntrack_tuple.h> | 19 | #include <net/netfilter/nf_conntrack_tuple.h> |
| 20 | #include <net/netfilter/nf_conntrack_helper.h> | 20 | #include <net/netfilter/nf_conntrack_helper.h> |
| 21 | #include <net/netfilter/nf_conntrack_ecache.h> | 21 | #include <net/netfilter/nf_conntrack_ecache.h> |
| 22 | #include <net/netfilter/nf_conntrack_labels.h> | ||
| 22 | 23 | ||
| 23 | struct nft_ct { | 24 | struct nft_ct { |
| 24 | enum nft_ct_keys key:8; | 25 | enum nft_ct_keys key:8; |
| 25 | enum ip_conntrack_dir dir:8; | 26 | enum ip_conntrack_dir dir:8; |
| 26 | union{ | 27 | union { |
| 27 | enum nft_registers dreg:8; | 28 | enum nft_registers dreg:8; |
| 28 | enum nft_registers sreg:8; | 29 | enum nft_registers sreg:8; |
| 29 | }; | 30 | }; |
| 30 | uint8_t family; | ||
| 31 | }; | 31 | }; |
| 32 | 32 | ||
| 33 | static void nft_ct_get_eval(const struct nft_expr *expr, | 33 | static void nft_ct_get_eval(const struct nft_expr *expr, |
| @@ -97,6 +97,26 @@ static void nft_ct_get_eval(const struct nft_expr *expr, | |||
| 97 | goto err; | 97 | goto err; |
| 98 | strncpy((char *)dest->data, helper->name, sizeof(dest->data)); | 98 | strncpy((char *)dest->data, helper->name, sizeof(dest->data)); |
| 99 | return; | 99 | return; |
| 100 | #ifdef CONFIG_NF_CONNTRACK_LABELS | ||
| 101 | case NFT_CT_LABELS: { | ||
| 102 | struct nf_conn_labels *labels = nf_ct_labels_find(ct); | ||
| 103 | unsigned int size; | ||
| 104 | |||
| 105 | if (!labels) { | ||
| 106 | memset(dest->data, 0, sizeof(dest->data)); | ||
| 107 | return; | ||
| 108 | } | ||
| 109 | |||
| 110 | BUILD_BUG_ON(NF_CT_LABELS_MAX_SIZE > sizeof(dest->data)); | ||
| 111 | size = labels->words * sizeof(long); | ||
| 112 | |||
| 113 | memcpy(dest->data, labels->bits, size); | ||
| 114 | if (size < sizeof(dest->data)) | ||
| 115 | memset(((char *) dest->data) + size, 0, | ||
| 116 | sizeof(dest->data) - size); | ||
| 117 | return; | ||
| 118 | } | ||
| 119 | #endif | ||
| 100 | } | 120 | } |
| 101 | 121 | ||
| 102 | tuple = &ct->tuplehash[priv->dir].tuple; | 122 | tuple = &ct->tuplehash[priv->dir].tuple; |
| @@ -221,6 +241,9 @@ static int nft_ct_init_validate_get(const struct nft_expr *expr, | |||
| 221 | #ifdef CONFIG_NF_CONNTRACK_SECMARK | 241 | #ifdef CONFIG_NF_CONNTRACK_SECMARK |
| 222 | case NFT_CT_SECMARK: | 242 | case NFT_CT_SECMARK: |
| 223 | #endif | 243 | #endif |
| 244 | #ifdef CONFIG_NF_CONNTRACK_LABELS | ||
| 245 | case NFT_CT_LABELS: | ||
| 246 | #endif | ||
| 224 | case NFT_CT_EXPIRATION: | 247 | case NFT_CT_EXPIRATION: |
| 225 | case NFT_CT_HELPER: | 248 | case NFT_CT_HELPER: |
| 226 | if (tb[NFTA_CT_DIRECTION] != NULL) | 249 | if (tb[NFTA_CT_DIRECTION] != NULL) |
| @@ -292,16 +315,13 @@ static int nft_ct_init(const struct nft_ctx *ctx, | |||
| 292 | if (err < 0) | 315 | if (err < 0) |
| 293 | return err; | 316 | return err; |
| 294 | 317 | ||
| 295 | priv->family = ctx->afi->family; | ||
| 296 | |||
| 297 | return 0; | 318 | return 0; |
| 298 | } | 319 | } |
| 299 | 320 | ||
| 300 | static void nft_ct_destroy(const struct nft_expr *expr) | 321 | static void nft_ct_destroy(const struct nft_ctx *ctx, |
| 322 | const struct nft_expr *expr) | ||
| 301 | { | 323 | { |
| 302 | struct nft_ct *priv = nft_expr_priv(expr); | 324 | nft_ct_l3proto_module_put(ctx->afi->family); |
| 303 | |||
| 304 | nft_ct_l3proto_module_put(priv->family); | ||
| 305 | } | 325 | } |
| 306 | 326 | ||
| 307 | static int nft_ct_get_dump(struct sk_buff *skb, const struct nft_expr *expr) | 327 | static int nft_ct_get_dump(struct sk_buff *skb, const struct nft_expr *expr) |
diff --git a/net/netfilter/nft_hash.c b/net/netfilter/nft_hash.c index 3d3f8fce10a5..3b1ad876d6b0 100644 --- a/net/netfilter/nft_hash.c +++ b/net/netfilter/nft_hash.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * Copyright (c) 2008-2009 Patrick McHardy <kaber@trash.net> | 2 | * Copyright (c) 2008-2014 Patrick McHardy <kaber@trash.net> |
| 3 | * | 3 | * |
| 4 | * This program is free software; you can redistribute it and/or modify | 4 | * This program is free software; you can redistribute it and/or modify |
| 5 | * it under the terms of the GNU General Public License version 2 as | 5 | * it under the terms of the GNU General Public License version 2 as |
| @@ -14,21 +14,34 @@ | |||
| 14 | #include <linux/list.h> | 14 | #include <linux/list.h> |
| 15 | #include <linux/jhash.h> | 15 | #include <linux/jhash.h> |
| 16 | #include <linux/netlink.h> | 16 | #include <linux/netlink.h> |
| 17 | #include <linux/vmalloc.h> | ||
| 17 | #include <linux/netfilter.h> | 18 | #include <linux/netfilter.h> |
| 18 | #include <linux/netfilter/nf_tables.h> | 19 | #include <linux/netfilter/nf_tables.h> |
| 19 | #include <net/netfilter/nf_tables.h> | 20 | #include <net/netfilter/nf_tables.h> |
| 20 | 21 | ||
| 22 | #define NFT_HASH_MIN_SIZE 4 | ||
| 23 | |||
| 21 | struct nft_hash { | 24 | struct nft_hash { |
| 22 | struct hlist_head *hash; | 25 | struct nft_hash_table __rcu *tbl; |
| 23 | unsigned int hsize; | 26 | }; |
| 27 | |||
| 28 | struct nft_hash_table { | ||
| 29 | unsigned int size; | ||
| 30 | unsigned int elements; | ||
| 31 | struct nft_hash_elem __rcu *buckets[]; | ||
| 24 | }; | 32 | }; |
| 25 | 33 | ||
| 26 | struct nft_hash_elem { | 34 | struct nft_hash_elem { |
| 27 | struct hlist_node hnode; | 35 | struct nft_hash_elem __rcu *next; |
| 28 | struct nft_data key; | 36 | struct nft_data key; |
| 29 | struct nft_data data[]; | 37 | struct nft_data data[]; |
| 30 | }; | 38 | }; |
| 31 | 39 | ||
| 40 | #define nft_hash_for_each_entry(i, head) \ | ||
| 41 | for (i = nft_dereference(head); i != NULL; i = nft_dereference(i->next)) | ||
| 42 | #define nft_hash_for_each_entry_rcu(i, head) \ | ||
| 43 | for (i = rcu_dereference(head); i != NULL; i = rcu_dereference(i->next)) | ||
| 44 | |||
| 32 | static u32 nft_hash_rnd __read_mostly; | 45 | static u32 nft_hash_rnd __read_mostly; |
| 33 | static bool nft_hash_rnd_initted __read_mostly; | 46 | static bool nft_hash_rnd_initted __read_mostly; |
| 34 | 47 | ||
| @@ -38,7 +51,7 @@ static unsigned int nft_hash_data(const struct nft_data *data, | |||
| 38 | unsigned int h; | 51 | unsigned int h; |
| 39 | 52 | ||
| 40 | h = jhash(data->data, len, nft_hash_rnd); | 53 | h = jhash(data->data, len, nft_hash_rnd); |
| 41 | return ((u64)h * hsize) >> 32; | 54 | return h & (hsize - 1); |
| 42 | } | 55 | } |
| 43 | 56 | ||
| 44 | static bool nft_hash_lookup(const struct nft_set *set, | 57 | static bool nft_hash_lookup(const struct nft_set *set, |
| @@ -46,11 +59,12 @@ static bool nft_hash_lookup(const struct nft_set *set, | |||
| 46 | struct nft_data *data) | 59 | struct nft_data *data) |
| 47 | { | 60 | { |
| 48 | const struct nft_hash *priv = nft_set_priv(set); | 61 | const struct nft_hash *priv = nft_set_priv(set); |
| 62 | const struct nft_hash_table *tbl = rcu_dereference(priv->tbl); | ||
| 49 | const struct nft_hash_elem *he; | 63 | const struct nft_hash_elem *he; |
| 50 | unsigned int h; | 64 | unsigned int h; |
| 51 | 65 | ||
| 52 | h = nft_hash_data(key, priv->hsize, set->klen); | 66 | h = nft_hash_data(key, tbl->size, set->klen); |
| 53 | hlist_for_each_entry(he, &priv->hash[h], hnode) { | 67 | nft_hash_for_each_entry_rcu(he, tbl->buckets[h]) { |
| 54 | if (nft_data_cmp(&he->key, key, set->klen)) | 68 | if (nft_data_cmp(&he->key, key, set->klen)) |
| 55 | continue; | 69 | continue; |
| 56 | if (set->flags & NFT_SET_MAP) | 70 | if (set->flags & NFT_SET_MAP) |
| @@ -60,19 +74,148 @@ static bool nft_hash_lookup(const struct nft_set *set, | |||
| 60 | return false; | 74 | return false; |
| 61 | } | 75 | } |
| 62 | 76 | ||
| 63 | static void nft_hash_elem_destroy(const struct nft_set *set, | 77 | static void nft_hash_tbl_free(const struct nft_hash_table *tbl) |
| 64 | struct nft_hash_elem *he) | ||
| 65 | { | 78 | { |
| 66 | nft_data_uninit(&he->key, NFT_DATA_VALUE); | 79 | if (is_vmalloc_addr(tbl)) |
| 67 | if (set->flags & NFT_SET_MAP) | 80 | vfree(tbl); |
| 68 | nft_data_uninit(he->data, set->dtype); | 81 | else |
| 69 | kfree(he); | 82 | kfree(tbl); |
| 83 | } | ||
| 84 | |||
| 85 | static struct nft_hash_table *nft_hash_tbl_alloc(unsigned int nbuckets) | ||
| 86 | { | ||
| 87 | struct nft_hash_table *tbl; | ||
| 88 | size_t size; | ||
| 89 | |||
| 90 | size = sizeof(*tbl) + nbuckets * sizeof(tbl->buckets[0]); | ||
| 91 | tbl = kzalloc(size, GFP_KERNEL | __GFP_REPEAT | __GFP_NOWARN); | ||
| 92 | if (tbl == NULL) | ||
| 93 | tbl = vzalloc(size); | ||
| 94 | if (tbl == NULL) | ||
| 95 | return NULL; | ||
| 96 | tbl->size = nbuckets; | ||
| 97 | |||
| 98 | return tbl; | ||
| 99 | } | ||
| 100 | |||
| 101 | static void nft_hash_chain_unzip(const struct nft_set *set, | ||
| 102 | const struct nft_hash_table *ntbl, | ||
| 103 | struct nft_hash_table *tbl, unsigned int n) | ||
| 104 | { | ||
| 105 | struct nft_hash_elem *he, *last, *next; | ||
| 106 | unsigned int h; | ||
| 107 | |||
| 108 | he = nft_dereference(tbl->buckets[n]); | ||
| 109 | if (he == NULL) | ||
| 110 | return; | ||
| 111 | h = nft_hash_data(&he->key, ntbl->size, set->klen); | ||
| 112 | |||
| 113 | /* Find last element of first chain hashing to bucket h */ | ||
| 114 | last = he; | ||
| 115 | nft_hash_for_each_entry(he, he->next) { | ||
| 116 | if (nft_hash_data(&he->key, ntbl->size, set->klen) != h) | ||
| 117 | break; | ||
| 118 | last = he; | ||
| 119 | } | ||
| 120 | |||
| 121 | /* Unlink first chain from the old table */ | ||
| 122 | RCU_INIT_POINTER(tbl->buckets[n], last->next); | ||
| 123 | |||
| 124 | /* If end of chain reached, done */ | ||
| 125 | if (he == NULL) | ||
| 126 | return; | ||
| 127 | |||
| 128 | /* Find first element of second chain hashing to bucket h */ | ||
| 129 | next = NULL; | ||
| 130 | nft_hash_for_each_entry(he, he->next) { | ||
| 131 | if (nft_hash_data(&he->key, ntbl->size, set->klen) != h) | ||
| 132 | continue; | ||
| 133 | next = he; | ||
| 134 | break; | ||
| 135 | } | ||
| 136 | |||
| 137 | /* Link the two chains */ | ||
| 138 | RCU_INIT_POINTER(last->next, next); | ||
| 139 | } | ||
| 140 | |||
| 141 | static int nft_hash_tbl_expand(const struct nft_set *set, struct nft_hash *priv) | ||
| 142 | { | ||
| 143 | struct nft_hash_table *tbl = nft_dereference(priv->tbl), *ntbl; | ||
| 144 | struct nft_hash_elem *he; | ||
| 145 | unsigned int i, h; | ||
| 146 | bool complete; | ||
| 147 | |||
| 148 | ntbl = nft_hash_tbl_alloc(tbl->size * 2); | ||
| 149 | if (ntbl == NULL) | ||
| 150 | return -ENOMEM; | ||
| 151 | |||
| 152 | /* Link new table's buckets to first element in the old table | ||
| 153 | * hashing to the new bucket. | ||
| 154 | */ | ||
| 155 | for (i = 0; i < ntbl->size; i++) { | ||
| 156 | h = i < tbl->size ? i : i - tbl->size; | ||
| 157 | nft_hash_for_each_entry(he, tbl->buckets[h]) { | ||
| 158 | if (nft_hash_data(&he->key, ntbl->size, set->klen) != i) | ||
| 159 | continue; | ||
| 160 | RCU_INIT_POINTER(ntbl->buckets[i], he); | ||
| 161 | break; | ||
| 162 | } | ||
| 163 | } | ||
| 164 | ntbl->elements = tbl->elements; | ||
| 165 | |||
| 166 | /* Publish new table */ | ||
| 167 | rcu_assign_pointer(priv->tbl, ntbl); | ||
| 168 | |||
| 169 | /* Unzip interleaved hash chains */ | ||
| 170 | do { | ||
| 171 | /* Wait for readers to use new table/unzipped chains */ | ||
| 172 | synchronize_rcu(); | ||
| 173 | |||
| 174 | complete = true; | ||
| 175 | for (i = 0; i < tbl->size; i++) { | ||
| 176 | nft_hash_chain_unzip(set, ntbl, tbl, i); | ||
| 177 | if (tbl->buckets[i] != NULL) | ||
| 178 | complete = false; | ||
| 179 | } | ||
| 180 | } while (!complete); | ||
| 181 | |||
| 182 | nft_hash_tbl_free(tbl); | ||
| 183 | return 0; | ||
| 184 | } | ||
| 185 | |||
| 186 | static int nft_hash_tbl_shrink(const struct nft_set *set, struct nft_hash *priv) | ||
| 187 | { | ||
| 188 | struct nft_hash_table *tbl = nft_dereference(priv->tbl), *ntbl; | ||
| 189 | struct nft_hash_elem __rcu **pprev; | ||
| 190 | unsigned int i; | ||
| 191 | |||
| 192 | ntbl = nft_hash_tbl_alloc(tbl->size / 2); | ||
| 193 | if (ntbl == NULL) | ||
| 194 | return -ENOMEM; | ||
| 195 | |||
| 196 | for (i = 0; i < ntbl->size; i++) { | ||
| 197 | ntbl->buckets[i] = tbl->buckets[i]; | ||
| 198 | |||
| 199 | for (pprev = &ntbl->buckets[i]; *pprev != NULL; | ||
| 200 | pprev = &nft_dereference(*pprev)->next) | ||
| 201 | ; | ||
| 202 | RCU_INIT_POINTER(*pprev, tbl->buckets[i + ntbl->size]); | ||
| 203 | } | ||
| 204 | ntbl->elements = tbl->elements; | ||
| 205 | |||
| 206 | /* Publish new table */ | ||
| 207 | rcu_assign_pointer(priv->tbl, ntbl); | ||
| 208 | synchronize_rcu(); | ||
| 209 | |||
| 210 | nft_hash_tbl_free(tbl); | ||
| 211 | return 0; | ||
| 70 | } | 212 | } |
| 71 | 213 | ||
| 72 | static int nft_hash_insert(const struct nft_set *set, | 214 | static int nft_hash_insert(const struct nft_set *set, |
| 73 | const struct nft_set_elem *elem) | 215 | const struct nft_set_elem *elem) |
| 74 | { | 216 | { |
| 75 | struct nft_hash *priv = nft_set_priv(set); | 217 | struct nft_hash *priv = nft_set_priv(set); |
| 218 | struct nft_hash_table *tbl = nft_dereference(priv->tbl); | ||
| 76 | struct nft_hash_elem *he; | 219 | struct nft_hash_elem *he; |
| 77 | unsigned int size, h; | 220 | unsigned int size, h; |
| 78 | 221 | ||
| @@ -91,33 +234,66 @@ static int nft_hash_insert(const struct nft_set *set, | |||
| 91 | if (set->flags & NFT_SET_MAP) | 234 | if (set->flags & NFT_SET_MAP) |
| 92 | nft_data_copy(he->data, &elem->data); | 235 | nft_data_copy(he->data, &elem->data); |
| 93 | 236 | ||
| 94 | h = nft_hash_data(&he->key, priv->hsize, set->klen); | 237 | h = nft_hash_data(&he->key, tbl->size, set->klen); |
| 95 | hlist_add_head_rcu(&he->hnode, &priv->hash[h]); | 238 | RCU_INIT_POINTER(he->next, tbl->buckets[h]); |
| 239 | rcu_assign_pointer(tbl->buckets[h], he); | ||
| 240 | tbl->elements++; | ||
| 241 | |||
| 242 | /* Expand table when exceeding 75% load */ | ||
| 243 | if (tbl->elements > tbl->size / 4 * 3) | ||
| 244 | nft_hash_tbl_expand(set, priv); | ||
| 245 | |||
| 96 | return 0; | 246 | return 0; |
| 97 | } | 247 | } |
| 98 | 248 | ||
| 249 | static void nft_hash_elem_destroy(const struct nft_set *set, | ||
| 250 | struct nft_hash_elem *he) | ||
| 251 | { | ||
| 252 | nft_data_uninit(&he->key, NFT_DATA_VALUE); | ||
| 253 | if (set->flags & NFT_SET_MAP) | ||
| 254 | nft_data_uninit(he->data, set->dtype); | ||
| 255 | kfree(he); | ||
| 256 | } | ||
| 257 | |||
| 99 | static void nft_hash_remove(const struct nft_set *set, | 258 | static void nft_hash_remove(const struct nft_set *set, |
| 100 | const struct nft_set_elem *elem) | 259 | const struct nft_set_elem *elem) |
| 101 | { | 260 | { |
| 102 | struct nft_hash_elem *he = elem->cookie; | 261 | struct nft_hash *priv = nft_set_priv(set); |
| 262 | struct nft_hash_table *tbl = nft_dereference(priv->tbl); | ||
| 263 | struct nft_hash_elem *he, __rcu **pprev; | ||
| 103 | 264 | ||
| 104 | hlist_del_rcu(&he->hnode); | 265 | pprev = elem->cookie; |
| 266 | he = nft_dereference((*pprev)); | ||
| 267 | |||
| 268 | RCU_INIT_POINTER(*pprev, he->next); | ||
| 269 | synchronize_rcu(); | ||
| 105 | kfree(he); | 270 | kfree(he); |
| 271 | tbl->elements--; | ||
| 272 | |||
| 273 | /* Shrink table beneath 30% load */ | ||
| 274 | if (tbl->elements < tbl->size * 3 / 10 && | ||
| 275 | tbl->size > NFT_HASH_MIN_SIZE) | ||
| 276 | nft_hash_tbl_shrink(set, priv); | ||
| 106 | } | 277 | } |
| 107 | 278 | ||
| 108 | static int nft_hash_get(const struct nft_set *set, struct nft_set_elem *elem) | 279 | static int nft_hash_get(const struct nft_set *set, struct nft_set_elem *elem) |
| 109 | { | 280 | { |
| 110 | const struct nft_hash *priv = nft_set_priv(set); | 281 | const struct nft_hash *priv = nft_set_priv(set); |
| 282 | const struct nft_hash_table *tbl = nft_dereference(priv->tbl); | ||
| 283 | struct nft_hash_elem __rcu * const *pprev; | ||
| 111 | struct nft_hash_elem *he; | 284 | struct nft_hash_elem *he; |
| 112 | unsigned int h; | 285 | unsigned int h; |
| 113 | 286 | ||
| 114 | h = nft_hash_data(&elem->key, priv->hsize, set->klen); | 287 | h = nft_hash_data(&elem->key, tbl->size, set->klen); |
| 115 | hlist_for_each_entry(he, &priv->hash[h], hnode) { | 288 | pprev = &tbl->buckets[h]; |
| 116 | if (nft_data_cmp(&he->key, &elem->key, set->klen)) | 289 | nft_hash_for_each_entry(he, tbl->buckets[h]) { |
| 290 | if (nft_data_cmp(&he->key, &elem->key, set->klen)) { | ||
| 291 | pprev = &he->next; | ||
| 117 | continue; | 292 | continue; |
| 293 | } | ||
| 118 | 294 | ||
| 119 | elem->cookie = he; | 295 | elem->cookie = (void *)pprev; |
| 120 | elem->flags = 0; | 296 | elem->flags = 0; |
| 121 | if (set->flags & NFT_SET_MAP) | 297 | if (set->flags & NFT_SET_MAP) |
| 122 | nft_data_copy(&elem->data, he->data); | 298 | nft_data_copy(&elem->data, he->data); |
| 123 | return 0; | 299 | return 0; |
| @@ -129,12 +305,13 @@ static void nft_hash_walk(const struct nft_ctx *ctx, const struct nft_set *set, | |||
| 129 | struct nft_set_iter *iter) | 305 | struct nft_set_iter *iter) |
| 130 | { | 306 | { |
| 131 | const struct nft_hash *priv = nft_set_priv(set); | 307 | const struct nft_hash *priv = nft_set_priv(set); |
| 308 | const struct nft_hash_table *tbl = nft_dereference(priv->tbl); | ||
| 132 | const struct nft_hash_elem *he; | 309 | const struct nft_hash_elem *he; |
| 133 | struct nft_set_elem elem; | 310 | struct nft_set_elem elem; |
| 134 | unsigned int i; | 311 | unsigned int i; |
| 135 | 312 | ||
| 136 | for (i = 0; i < priv->hsize; i++) { | 313 | for (i = 0; i < tbl->size; i++) { |
| 137 | hlist_for_each_entry(he, &priv->hash[i], hnode) { | 314 | nft_hash_for_each_entry(he, tbl->buckets[i]) { |
| 138 | if (iter->count < iter->skip) | 315 | if (iter->count < iter->skip) |
| 139 | goto cont; | 316 | goto cont; |
| 140 | 317 | ||
| @@ -161,43 +338,35 @@ static int nft_hash_init(const struct nft_set *set, | |||
| 161 | const struct nlattr * const tb[]) | 338 | const struct nlattr * const tb[]) |
| 162 | { | 339 | { |
| 163 | struct nft_hash *priv = nft_set_priv(set); | 340 | struct nft_hash *priv = nft_set_priv(set); |
| 164 | unsigned int cnt, i; | 341 | struct nft_hash_table *tbl; |
| 165 | 342 | ||
| 166 | if (unlikely(!nft_hash_rnd_initted)) { | 343 | if (unlikely(!nft_hash_rnd_initted)) { |
| 167 | get_random_bytes(&nft_hash_rnd, 4); | 344 | get_random_bytes(&nft_hash_rnd, 4); |
| 168 | nft_hash_rnd_initted = true; | 345 | nft_hash_rnd_initted = true; |
| 169 | } | 346 | } |
| 170 | 347 | ||
| 171 | /* Aim for a load factor of 0.75 */ | 348 | tbl = nft_hash_tbl_alloc(NFT_HASH_MIN_SIZE); |
| 172 | // FIXME: temporarily broken until we have set descriptions | 349 | if (tbl == NULL) |
| 173 | cnt = 100; | ||
| 174 | cnt = cnt * 4 / 3; | ||
| 175 | |||
| 176 | priv->hash = kcalloc(cnt, sizeof(struct hlist_head), GFP_KERNEL); | ||
| 177 | if (priv->hash == NULL) | ||
| 178 | return -ENOMEM; | 350 | return -ENOMEM; |
| 179 | priv->hsize = cnt; | 351 | RCU_INIT_POINTER(priv->tbl, tbl); |
| 180 | |||
| 181 | for (i = 0; i < cnt; i++) | ||
| 182 | INIT_HLIST_HEAD(&priv->hash[i]); | ||
| 183 | |||
| 184 | return 0; | 352 | return 0; |
| 185 | } | 353 | } |
| 186 | 354 | ||
| 187 | static void nft_hash_destroy(const struct nft_set *set) | 355 | static void nft_hash_destroy(const struct nft_set *set) |
| 188 | { | 356 | { |
| 189 | const struct nft_hash *priv = nft_set_priv(set); | 357 | const struct nft_hash *priv = nft_set_priv(set); |
| 190 | const struct hlist_node *next; | 358 | const struct nft_hash_table *tbl = nft_dereference(priv->tbl); |
| 191 | struct nft_hash_elem *elem; | 359 | struct nft_hash_elem *he, *next; |
| 192 | unsigned int i; | 360 | unsigned int i; |
| 193 | 361 | ||
| 194 | for (i = 0; i < priv->hsize; i++) { | 362 | for (i = 0; i < tbl->size; i++) { |
| 195 | hlist_for_each_entry_safe(elem, next, &priv->hash[i], hnode) { | 363 | for (he = nft_dereference(tbl->buckets[i]); he != NULL; |
| 196 | hlist_del(&elem->hnode); | 364 | he = next) { |
| 197 | nft_hash_elem_destroy(set, elem); | 365 | next = nft_dereference(he->next); |
| 366 | nft_hash_elem_destroy(set, he); | ||
| 198 | } | 367 | } |
| 199 | } | 368 | } |
| 200 | kfree(priv->hash); | 369 | kfree(tbl); |
| 201 | } | 370 | } |
| 202 | 371 | ||
| 203 | static struct nft_set_ops nft_hash_ops __read_mostly = { | 372 | static struct nft_set_ops nft_hash_ops __read_mostly = { |
diff --git a/net/netfilter/nft_immediate.c b/net/netfilter/nft_immediate.c index f169501f1ad4..810385eb7249 100644 --- a/net/netfilter/nft_immediate.c +++ b/net/netfilter/nft_immediate.c | |||
| @@ -70,7 +70,8 @@ err1: | |||
| 70 | return err; | 70 | return err; |
| 71 | } | 71 | } |
| 72 | 72 | ||
| 73 | static void nft_immediate_destroy(const struct nft_expr *expr) | 73 | static void nft_immediate_destroy(const struct nft_ctx *ctx, |
| 74 | const struct nft_expr *expr) | ||
| 74 | { | 75 | { |
| 75 | const struct nft_immediate_expr *priv = nft_expr_priv(expr); | 76 | const struct nft_immediate_expr *priv = nft_expr_priv(expr); |
| 76 | return nft_data_uninit(&priv->data, nft_dreg_to_type(priv->dreg)); | 77 | return nft_data_uninit(&priv->data, nft_dreg_to_type(priv->dreg)); |
diff --git a/net/netfilter/nft_log.c b/net/netfilter/nft_log.c index 26c5154e05f3..10cfb156cdf4 100644 --- a/net/netfilter/nft_log.c +++ b/net/netfilter/nft_log.c | |||
| @@ -74,7 +74,8 @@ static int nft_log_init(const struct nft_ctx *ctx, | |||
| 74 | return 0; | 74 | return 0; |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | static void nft_log_destroy(const struct nft_expr *expr) | 77 | static void nft_log_destroy(const struct nft_ctx *ctx, |
| 78 | const struct nft_expr *expr) | ||
| 78 | { | 79 | { |
| 79 | struct nft_log *priv = nft_expr_priv(expr); | 80 | struct nft_log *priv = nft_expr_priv(expr); |
| 80 | 81 | ||
diff --git a/net/netfilter/nft_lookup.c b/net/netfilter/nft_lookup.c index bb4ef4cccb6e..7fd2bea8aa23 100644 --- a/net/netfilter/nft_lookup.c +++ b/net/netfilter/nft_lookup.c | |||
| @@ -89,11 +89,12 @@ static int nft_lookup_init(const struct nft_ctx *ctx, | |||
| 89 | return 0; | 89 | return 0; |
| 90 | } | 90 | } |
| 91 | 91 | ||
| 92 | static void nft_lookup_destroy(const struct nft_expr *expr) | 92 | static void nft_lookup_destroy(const struct nft_ctx *ctx, |
| 93 | const struct nft_expr *expr) | ||
| 93 | { | 94 | { |
| 94 | struct nft_lookup *priv = nft_expr_priv(expr); | 95 | struct nft_lookup *priv = nft_expr_priv(expr); |
| 95 | 96 | ||
| 96 | nf_tables_unbind_set(NULL, priv->set, &priv->binding); | 97 | nf_tables_unbind_set(ctx, priv->set, &priv->binding); |
| 97 | } | 98 | } |
| 98 | 99 | ||
| 99 | static int nft_lookup_dump(struct sk_buff *skb, const struct nft_expr *expr) | 100 | static int nft_lookup_dump(struct sk_buff *skb, const struct nft_expr *expr) |
diff --git a/net/netfilter/nft_nat.c b/net/netfilter/nft_nat.c index d3b1ffe26181..a0195d28bcfc 100644 --- a/net/netfilter/nft_nat.c +++ b/net/netfilter/nft_nat.c | |||
| @@ -31,8 +31,8 @@ struct nft_nat { | |||
| 31 | enum nft_registers sreg_addr_max:8; | 31 | enum nft_registers sreg_addr_max:8; |
| 32 | enum nft_registers sreg_proto_min:8; | 32 | enum nft_registers sreg_proto_min:8; |
| 33 | enum nft_registers sreg_proto_max:8; | 33 | enum nft_registers sreg_proto_max:8; |
| 34 | int family; | 34 | enum nf_nat_manip_type type:8; |
| 35 | enum nf_nat_manip_type type; | 35 | u8 family; |
| 36 | }; | 36 | }; |
| 37 | 37 | ||
| 38 | static void nft_nat_eval(const struct nft_expr *expr, | 38 | static void nft_nat_eval(const struct nft_expr *expr, |
| @@ -88,6 +88,7 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr, | |||
| 88 | const struct nlattr * const tb[]) | 88 | const struct nlattr * const tb[]) |
| 89 | { | 89 | { |
| 90 | struct nft_nat *priv = nft_expr_priv(expr); | 90 | struct nft_nat *priv = nft_expr_priv(expr); |
| 91 | u32 family; | ||
| 91 | int err; | 92 | int err; |
| 92 | 93 | ||
| 93 | if (tb[NFTA_NAT_TYPE] == NULL) | 94 | if (tb[NFTA_NAT_TYPE] == NULL) |
| @@ -107,9 +108,12 @@ static int nft_nat_init(const struct nft_ctx *ctx, const struct nft_expr *expr, | |||
| 107 | if (tb[NFTA_NAT_FAMILY] == NULL) | 108 | if (tb[NFTA_NAT_FAMILY] == NULL) |
| 108 | return -EINVAL; | 109 | return -EINVAL; |
| 109 | 110 | ||
| 110 | priv->family = ntohl(nla_get_be32(tb[NFTA_NAT_FAMILY])); | 111 | family = ntohl(nla_get_be32(tb[NFTA_NAT_FAMILY])); |
| 111 | if (priv->family != AF_INET && priv->family != AF_INET6) | 112 | if (family != AF_INET && family != AF_INET6) |
| 112 | return -EINVAL; | 113 | return -EAFNOSUPPORT; |
| 114 | if (family != ctx->afi->family) | ||
| 115 | return -EOPNOTSUPP; | ||
| 116 | priv->family = family; | ||
| 113 | 117 | ||
| 114 | if (tb[NFTA_NAT_REG_ADDR_MIN]) { | 118 | if (tb[NFTA_NAT_REG_ADDR_MIN]) { |
| 115 | priv->sreg_addr_min = ntohl(nla_get_be32( | 119 | priv->sreg_addr_min = ntohl(nla_get_be32( |
| @@ -202,13 +206,7 @@ static struct nft_expr_type nft_nat_type __read_mostly = { | |||
| 202 | 206 | ||
| 203 | static int __init nft_nat_module_init(void) | 207 | static int __init nft_nat_module_init(void) |
| 204 | { | 208 | { |
| 205 | int err; | 209 | return nft_register_expr(&nft_nat_type); |
| 206 | |||
| 207 | err = nft_register_expr(&nft_nat_type); | ||
| 208 | if (err < 0) | ||
| 209 | return err; | ||
| 210 | |||
| 211 | return 0; | ||
| 212 | } | 210 | } |
| 213 | 211 | ||
| 214 | static void __exit nft_nat_module_exit(void) | 212 | static void __exit nft_nat_module_exit(void) |
diff --git a/net/netfilter/xt_AUDIT.c b/net/netfilter/xt_AUDIT.c index 3228d7f24eb4..4973cbddc446 100644 --- a/net/netfilter/xt_AUDIT.c +++ b/net/netfilter/xt_AUDIT.c | |||
| @@ -146,11 +146,11 @@ audit_tg(struct sk_buff *skb, const struct xt_action_param *par) | |||
| 146 | 146 | ||
| 147 | if (par->family == NFPROTO_BRIDGE) { | 147 | if (par->family == NFPROTO_BRIDGE) { |
| 148 | switch (eth_hdr(skb)->h_proto) { | 148 | switch (eth_hdr(skb)->h_proto) { |
| 149 | case __constant_htons(ETH_P_IP): | 149 | case htons(ETH_P_IP): |
| 150 | audit_ip4(ab, skb); | 150 | audit_ip4(ab, skb); |
| 151 | break; | 151 | break; |
| 152 | 152 | ||
| 153 | case __constant_htons(ETH_P_IPV6): | 153 | case htons(ETH_P_IPV6): |
| 154 | audit_ip6(ab, skb); | 154 | audit_ip6(ab, skb); |
| 155 | break; | 155 | break; |
| 156 | } | 156 | } |
diff --git a/net/netfilter/xt_cgroup.c b/net/netfilter/xt_cgroup.c index 9a8e77e7f8d4..f4e833005320 100644 --- a/net/netfilter/xt_cgroup.c +++ b/net/netfilter/xt_cgroup.c | |||
| @@ -54,7 +54,8 @@ static struct xt_match cgroup_mt_reg __read_mostly = { | |||
| 54 | .matchsize = sizeof(struct xt_cgroup_info), | 54 | .matchsize = sizeof(struct xt_cgroup_info), |
| 55 | .me = THIS_MODULE, | 55 | .me = THIS_MODULE, |
| 56 | .hooks = (1 << NF_INET_LOCAL_OUT) | | 56 | .hooks = (1 << NF_INET_LOCAL_OUT) | |
| 57 | (1 << NF_INET_POST_ROUTING), | 57 | (1 << NF_INET_POST_ROUTING) | |
| 58 | (1 << NF_INET_LOCAL_IN), | ||
| 58 | }; | 59 | }; |
| 59 | 60 | ||
| 60 | static int __init cgroup_mt_init(void) | 61 | static int __init cgroup_mt_init(void) |
diff --git a/net/netfilter/xt_connlimit.c b/net/netfilter/xt_connlimit.c index c40b2695633b..fbc66bb250d5 100644 --- a/net/netfilter/xt_connlimit.c +++ b/net/netfilter/xt_connlimit.c | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include <linux/jhash.h> | 19 | #include <linux/jhash.h> |
| 20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
| 21 | #include <linux/list.h> | 21 | #include <linux/list.h> |
| 22 | #include <linux/rbtree.h> | ||
| 22 | #include <linux/module.h> | 23 | #include <linux/module.h> |
| 23 | #include <linux/random.h> | 24 | #include <linux/random.h> |
| 24 | #include <linux/skbuff.h> | 25 | #include <linux/skbuff.h> |
| @@ -31,6 +32,16 @@ | |||
| 31 | #include <net/netfilter/nf_conntrack_tuple.h> | 32 | #include <net/netfilter/nf_conntrack_tuple.h> |
| 32 | #include <net/netfilter/nf_conntrack_zones.h> | 33 | #include <net/netfilter/nf_conntrack_zones.h> |
| 33 | 34 | ||
| 35 | #define CONNLIMIT_SLOTS 256U | ||
| 36 | |||
| 37 | #ifdef CONFIG_LOCKDEP | ||
| 38 | #define CONNLIMIT_LOCK_SLOTS 8U | ||
| 39 | #else | ||
| 40 | #define CONNLIMIT_LOCK_SLOTS 256U | ||
| 41 | #endif | ||
| 42 | |||
| 43 | #define CONNLIMIT_GC_MAX_NODES 8 | ||
| 44 | |||
| 34 | /* we will save the tuples of all connections we care about */ | 45 | /* we will save the tuples of all connections we care about */ |
| 35 | struct xt_connlimit_conn { | 46 | struct xt_connlimit_conn { |
| 36 | struct hlist_node node; | 47 | struct hlist_node node; |
| @@ -38,16 +49,27 @@ struct xt_connlimit_conn { | |||
| 38 | union nf_inet_addr addr; | 49 | union nf_inet_addr addr; |
| 39 | }; | 50 | }; |
| 40 | 51 | ||
| 52 | struct xt_connlimit_rb { | ||
| 53 | struct rb_node node; | ||
| 54 | struct hlist_head hhead; /* connections/hosts in same subnet */ | ||
| 55 | union nf_inet_addr addr; /* search key */ | ||
| 56 | }; | ||
| 57 | |||
| 58 | static spinlock_t xt_connlimit_locks[CONNLIMIT_LOCK_SLOTS] __cacheline_aligned_in_smp; | ||
| 59 | |||
| 41 | struct xt_connlimit_data { | 60 | struct xt_connlimit_data { |
| 42 | struct hlist_head iphash[256]; | 61 | struct rb_root climit_root4[CONNLIMIT_SLOTS]; |
| 43 | spinlock_t lock; | 62 | struct rb_root climit_root6[CONNLIMIT_SLOTS]; |
| 44 | }; | 63 | }; |
| 45 | 64 | ||
| 46 | static u_int32_t connlimit_rnd __read_mostly; | 65 | static u_int32_t connlimit_rnd __read_mostly; |
| 66 | static struct kmem_cache *connlimit_rb_cachep __read_mostly; | ||
| 67 | static struct kmem_cache *connlimit_conn_cachep __read_mostly; | ||
| 47 | 68 | ||
| 48 | static inline unsigned int connlimit_iphash(__be32 addr) | 69 | static inline unsigned int connlimit_iphash(__be32 addr) |
| 49 | { | 70 | { |
| 50 | return jhash_1word((__force __u32)addr, connlimit_rnd) & 0xFF; | 71 | return jhash_1word((__force __u32)addr, |
| 72 | connlimit_rnd) % CONNLIMIT_SLOTS; | ||
| 51 | } | 73 | } |
| 52 | 74 | ||
| 53 | static inline unsigned int | 75 | static inline unsigned int |
| @@ -60,7 +82,8 @@ connlimit_iphash6(const union nf_inet_addr *addr, | |||
| 60 | for (i = 0; i < ARRAY_SIZE(addr->ip6); ++i) | 82 | for (i = 0; i < ARRAY_SIZE(addr->ip6); ++i) |
| 61 | res.ip6[i] = addr->ip6[i] & mask->ip6[i]; | 83 | res.ip6[i] = addr->ip6[i] & mask->ip6[i]; |
| 62 | 84 | ||
| 63 | return jhash2((u32 *)res.ip6, ARRAY_SIZE(res.ip6), connlimit_rnd) & 0xFF; | 85 | return jhash2((u32 *)res.ip6, ARRAY_SIZE(res.ip6), |
| 86 | connlimit_rnd) % CONNLIMIT_SLOTS; | ||
| 64 | } | 87 | } |
| 65 | 88 | ||
| 66 | static inline bool already_closed(const struct nf_conn *conn) | 89 | static inline bool already_closed(const struct nf_conn *conn) |
| @@ -72,13 +95,14 @@ static inline bool already_closed(const struct nf_conn *conn) | |||
| 72 | return 0; | 95 | return 0; |
| 73 | } | 96 | } |
| 74 | 97 | ||
| 75 | static inline unsigned int | 98 | static int |
| 76 | same_source_net(const union nf_inet_addr *addr, | 99 | same_source_net(const union nf_inet_addr *addr, |
| 77 | const union nf_inet_addr *mask, | 100 | const union nf_inet_addr *mask, |
| 78 | const union nf_inet_addr *u3, u_int8_t family) | 101 | const union nf_inet_addr *u3, u_int8_t family) |
| 79 | { | 102 | { |
| 80 | if (family == NFPROTO_IPV4) { | 103 | if (family == NFPROTO_IPV4) { |
| 81 | return (addr->ip & mask->ip) == (u3->ip & mask->ip); | 104 | return ntohl(addr->ip & mask->ip) - |
| 105 | ntohl(u3->ip & mask->ip); | ||
| 82 | } else { | 106 | } else { |
| 83 | union nf_inet_addr lh, rh; | 107 | union nf_inet_addr lh, rh; |
| 84 | unsigned int i; | 108 | unsigned int i; |
| @@ -88,89 +112,205 @@ same_source_net(const union nf_inet_addr *addr, | |||
| 88 | rh.ip6[i] = u3->ip6[i] & mask->ip6[i]; | 112 | rh.ip6[i] = u3->ip6[i] & mask->ip6[i]; |
| 89 | } | 113 | } |
| 90 | 114 | ||
| 91 | return memcmp(&lh.ip6, &rh.ip6, sizeof(lh.ip6)) == 0; | 115 | return memcmp(&lh.ip6, &rh.ip6, sizeof(lh.ip6)); |
| 92 | } | 116 | } |
| 93 | } | 117 | } |
| 94 | 118 | ||
| 95 | static int count_them(struct net *net, | 119 | static bool add_hlist(struct hlist_head *head, |
| 96 | struct xt_connlimit_data *data, | ||
| 97 | const struct nf_conntrack_tuple *tuple, | 120 | const struct nf_conntrack_tuple *tuple, |
| 98 | const union nf_inet_addr *addr, | 121 | const union nf_inet_addr *addr) |
| 99 | const union nf_inet_addr *mask, | 122 | { |
| 100 | u_int8_t family) | 123 | struct xt_connlimit_conn *conn; |
| 124 | |||
| 125 | conn = kmem_cache_alloc(connlimit_conn_cachep, GFP_ATOMIC); | ||
| 126 | if (conn == NULL) | ||
| 127 | return false; | ||
| 128 | conn->tuple = *tuple; | ||
| 129 | conn->addr = *addr; | ||
| 130 | hlist_add_head(&conn->node, head); | ||
| 131 | return true; | ||
| 132 | } | ||
| 133 | |||
| 134 | static unsigned int check_hlist(struct net *net, | ||
| 135 | struct hlist_head *head, | ||
| 136 | const struct nf_conntrack_tuple *tuple, | ||
| 137 | bool *addit) | ||
| 101 | { | 138 | { |
| 102 | const struct nf_conntrack_tuple_hash *found; | 139 | const struct nf_conntrack_tuple_hash *found; |
| 103 | struct xt_connlimit_conn *conn; | 140 | struct xt_connlimit_conn *conn; |
| 104 | struct hlist_node *n; | 141 | struct hlist_node *n; |
| 105 | struct nf_conn *found_ct; | 142 | struct nf_conn *found_ct; |
| 106 | struct hlist_head *hash; | 143 | unsigned int length = 0; |
| 107 | bool addit = true; | ||
| 108 | int matches = 0; | ||
| 109 | |||
| 110 | if (family == NFPROTO_IPV6) | ||
| 111 | hash = &data->iphash[connlimit_iphash6(addr, mask)]; | ||
| 112 | else | ||
| 113 | hash = &data->iphash[connlimit_iphash(addr->ip & mask->ip)]; | ||
| 114 | 144 | ||
| 145 | *addit = true; | ||
| 115 | rcu_read_lock(); | 146 | rcu_read_lock(); |
| 116 | 147 | ||
| 117 | /* check the saved connections */ | 148 | /* check the saved connections */ |
| 118 | hlist_for_each_entry_safe(conn, n, hash, node) { | 149 | hlist_for_each_entry_safe(conn, n, head, node) { |
| 119 | found = nf_conntrack_find_get(net, NF_CT_DEFAULT_ZONE, | 150 | found = nf_conntrack_find_get(net, NF_CT_DEFAULT_ZONE, |
| 120 | &conn->tuple); | 151 | &conn->tuple); |
| 121 | found_ct = NULL; | 152 | if (found == NULL) { |
| 153 | hlist_del(&conn->node); | ||
| 154 | kmem_cache_free(connlimit_conn_cachep, conn); | ||
| 155 | continue; | ||
| 156 | } | ||
| 122 | 157 | ||
| 123 | if (found != NULL) | 158 | found_ct = nf_ct_tuplehash_to_ctrack(found); |
| 124 | found_ct = nf_ct_tuplehash_to_ctrack(found); | ||
| 125 | 159 | ||
| 126 | if (found_ct != NULL && | 160 | if (nf_ct_tuple_equal(&conn->tuple, tuple)) { |
| 127 | nf_ct_tuple_equal(&conn->tuple, tuple) && | ||
| 128 | !already_closed(found_ct)) | ||
| 129 | /* | 161 | /* |
| 130 | * Just to be sure we have it only once in the list. | 162 | * Just to be sure we have it only once in the list. |
| 131 | * We should not see tuples twice unless someone hooks | 163 | * We should not see tuples twice unless someone hooks |
| 132 | * this into a table without "-p tcp --syn". | 164 | * this into a table without "-p tcp --syn". |
| 133 | */ | 165 | */ |
| 134 | addit = false; | 166 | *addit = false; |
| 135 | 167 | } else if (already_closed(found_ct)) { | |
| 136 | if (found == NULL) { | ||
| 137 | /* this one is gone */ | ||
| 138 | hlist_del(&conn->node); | ||
| 139 | kfree(conn); | ||
| 140 | continue; | ||
| 141 | } | ||
| 142 | |||
| 143 | if (already_closed(found_ct)) { | ||
| 144 | /* | 168 | /* |
| 145 | * we do not care about connections which are | 169 | * we do not care about connections which are |
| 146 | * closed already -> ditch it | 170 | * closed already -> ditch it |
| 147 | */ | 171 | */ |
| 148 | nf_ct_put(found_ct); | 172 | nf_ct_put(found_ct); |
| 149 | hlist_del(&conn->node); | 173 | hlist_del(&conn->node); |
| 150 | kfree(conn); | 174 | kmem_cache_free(connlimit_conn_cachep, conn); |
| 151 | continue; | 175 | continue; |
| 152 | } | 176 | } |
| 153 | 177 | ||
| 154 | if (same_source_net(addr, mask, &conn->addr, family)) | ||
| 155 | /* same source network -> be counted! */ | ||
| 156 | ++matches; | ||
| 157 | nf_ct_put(found_ct); | 178 | nf_ct_put(found_ct); |
| 179 | length++; | ||
| 158 | } | 180 | } |
| 159 | 181 | ||
| 160 | rcu_read_unlock(); | 182 | rcu_read_unlock(); |
| 161 | 183 | ||
| 162 | if (addit) { | 184 | return length; |
| 163 | /* save the new connection in our list */ | 185 | } |
| 164 | conn = kmalloc(sizeof(*conn), GFP_ATOMIC); | 186 | |
| 165 | if (conn == NULL) | 187 | static void tree_nodes_free(struct rb_root *root, |
| 166 | return -ENOMEM; | 188 | struct xt_connlimit_rb *gc_nodes[], |
| 167 | conn->tuple = *tuple; | 189 | unsigned int gc_count) |
| 168 | conn->addr = *addr; | 190 | { |
| 169 | hlist_add_head(&conn->node, hash); | 191 | struct xt_connlimit_rb *rbconn; |
| 170 | ++matches; | 192 | |
| 193 | while (gc_count) { | ||
| 194 | rbconn = gc_nodes[--gc_count]; | ||
| 195 | rb_erase(&rbconn->node, root); | ||
| 196 | kmem_cache_free(connlimit_rb_cachep, rbconn); | ||
| 197 | } | ||
| 198 | } | ||
| 199 | |||
| 200 | static unsigned int | ||
| 201 | count_tree(struct net *net, struct rb_root *root, | ||
| 202 | const struct nf_conntrack_tuple *tuple, | ||
| 203 | const union nf_inet_addr *addr, const union nf_inet_addr *mask, | ||
| 204 | u8 family) | ||
| 205 | { | ||
| 206 | struct xt_connlimit_rb *gc_nodes[CONNLIMIT_GC_MAX_NODES]; | ||
| 207 | struct rb_node **rbnode, *parent; | ||
| 208 | struct xt_connlimit_rb *rbconn; | ||
| 209 | struct xt_connlimit_conn *conn; | ||
| 210 | unsigned int gc_count; | ||
| 211 | bool no_gc = false; | ||
| 212 | |||
| 213 | restart: | ||
| 214 | gc_count = 0; | ||
| 215 | parent = NULL; | ||
| 216 | rbnode = &(root->rb_node); | ||
| 217 | while (*rbnode) { | ||
| 218 | int diff; | ||
| 219 | bool addit; | ||
| 220 | |||
| 221 | rbconn = container_of(*rbnode, struct xt_connlimit_rb, node); | ||
| 222 | |||
| 223 | parent = *rbnode; | ||
| 224 | diff = same_source_net(addr, mask, &rbconn->addr, family); | ||
| 225 | if (diff < 0) { | ||
| 226 | rbnode = &((*rbnode)->rb_left); | ||
| 227 | } else if (diff > 0) { | ||
| 228 | rbnode = &((*rbnode)->rb_right); | ||
| 229 | } else { | ||
| 230 | /* same source network -> be counted! */ | ||
| 231 | unsigned int count; | ||
| 232 | count = check_hlist(net, &rbconn->hhead, tuple, &addit); | ||
| 233 | |||
| 234 | tree_nodes_free(root, gc_nodes, gc_count); | ||
| 235 | if (!addit) | ||
| 236 | return count; | ||
| 237 | |||
| 238 | if (!add_hlist(&rbconn->hhead, tuple, addr)) | ||
| 239 | return 0; /* hotdrop */ | ||
| 240 | |||
| 241 | return count + 1; | ||
| 242 | } | ||
| 243 | |||
| 244 | if (no_gc || gc_count >= ARRAY_SIZE(gc_nodes)) | ||
| 245 | continue; | ||
| 246 | |||
| 247 | /* only used for GC on hhead, retval and 'addit' ignored */ | ||
| 248 | check_hlist(net, &rbconn->hhead, tuple, &addit); | ||
| 249 | if (hlist_empty(&rbconn->hhead)) | ||
| 250 | gc_nodes[gc_count++] = rbconn; | ||
| 251 | } | ||
| 252 | |||
| 253 | if (gc_count) { | ||
| 254 | no_gc = true; | ||
| 255 | tree_nodes_free(root, gc_nodes, gc_count); | ||
| 256 | /* tree_node_free before new allocation permits | ||
| 257 | * allocator to re-use newly free'd object. | ||
| 258 | * | ||
| 259 | * This is a rare event; in most cases we will find | ||
| 260 | * existing node to re-use. (or gc_count is 0). | ||
| 261 | */ | ||
| 262 | goto restart; | ||
| 263 | } | ||
| 264 | |||
| 265 | /* no match, need to insert new node */ | ||
| 266 | rbconn = kmem_cache_alloc(connlimit_rb_cachep, GFP_ATOMIC); | ||
| 267 | if (rbconn == NULL) | ||
| 268 | return 0; | ||
| 269 | |||
| 270 | conn = kmem_cache_alloc(connlimit_conn_cachep, GFP_ATOMIC); | ||
| 271 | if (conn == NULL) { | ||
| 272 | kmem_cache_free(connlimit_rb_cachep, rbconn); | ||
| 273 | return 0; | ||
| 274 | } | ||
| 275 | |||
| 276 | conn->tuple = *tuple; | ||
| 277 | conn->addr = *addr; | ||
| 278 | rbconn->addr = *addr; | ||
| 279 | |||
| 280 | INIT_HLIST_HEAD(&rbconn->hhead); | ||
| 281 | hlist_add_head(&conn->node, &rbconn->hhead); | ||
| 282 | |||
| 283 | rb_link_node(&rbconn->node, parent, rbnode); | ||
| 284 | rb_insert_color(&rbconn->node, root); | ||
| 285 | return 1; | ||
| 286 | } | ||
| 287 | |||
| 288 | static int count_them(struct net *net, | ||
| 289 | struct xt_connlimit_data *data, | ||
| 290 | const struct nf_conntrack_tuple *tuple, | ||
| 291 | const union nf_inet_addr *addr, | ||
| 292 | const union nf_inet_addr *mask, | ||
| 293 | u_int8_t family) | ||
| 294 | { | ||
| 295 | struct rb_root *root; | ||
| 296 | int count; | ||
| 297 | u32 hash; | ||
| 298 | |||
| 299 | if (family == NFPROTO_IPV6) { | ||
| 300 | hash = connlimit_iphash6(addr, mask); | ||
| 301 | root = &data->climit_root6[hash]; | ||
| 302 | } else { | ||
| 303 | hash = connlimit_iphash(addr->ip & mask->ip); | ||
| 304 | root = &data->climit_root4[hash]; | ||
| 171 | } | 305 | } |
| 172 | 306 | ||
| 173 | return matches; | 307 | spin_lock_bh(&xt_connlimit_locks[hash % CONNLIMIT_LOCK_SLOTS]); |
| 308 | |||
| 309 | count = count_tree(net, root, tuple, addr, mask, family); | ||
| 310 | |||
| 311 | spin_unlock_bh(&xt_connlimit_locks[hash % CONNLIMIT_LOCK_SLOTS]); | ||
| 312 | |||
| 313 | return count; | ||
| 174 | } | 314 | } |
| 175 | 315 | ||
| 176 | static bool | 316 | static bool |
| @@ -183,7 +323,7 @@ connlimit_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 183 | const struct nf_conntrack_tuple *tuple_ptr = &tuple; | 323 | const struct nf_conntrack_tuple *tuple_ptr = &tuple; |
| 184 | enum ip_conntrack_info ctinfo; | 324 | enum ip_conntrack_info ctinfo; |
| 185 | const struct nf_conn *ct; | 325 | const struct nf_conn *ct; |
| 186 | int connections; | 326 | unsigned int connections; |
| 187 | 327 | ||
| 188 | ct = nf_ct_get(skb, &ctinfo); | 328 | ct = nf_ct_get(skb, &ctinfo); |
| 189 | if (ct != NULL) | 329 | if (ct != NULL) |
| @@ -202,12 +342,9 @@ connlimit_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 202 | iph->daddr : iph->saddr; | 342 | iph->daddr : iph->saddr; |
| 203 | } | 343 | } |
| 204 | 344 | ||
| 205 | spin_lock_bh(&info->data->lock); | ||
| 206 | connections = count_them(net, info->data, tuple_ptr, &addr, | 345 | connections = count_them(net, info->data, tuple_ptr, &addr, |
| 207 | &info->mask, par->family); | 346 | &info->mask, par->family); |
| 208 | spin_unlock_bh(&info->data->lock); | 347 | if (connections == 0) |
| 209 | |||
| 210 | if (connections < 0) | ||
| 211 | /* kmalloc failed, drop it entirely */ | 348 | /* kmalloc failed, drop it entirely */ |
| 212 | goto hotdrop; | 349 | goto hotdrop; |
| 213 | 350 | ||
| @@ -247,29 +384,44 @@ static int connlimit_mt_check(const struct xt_mtchk_param *par) | |||
| 247 | return -ENOMEM; | 384 | return -ENOMEM; |
| 248 | } | 385 | } |
| 249 | 386 | ||
| 250 | spin_lock_init(&info->data->lock); | 387 | for (i = 0; i < ARRAY_SIZE(info->data->climit_root4); ++i) |
| 251 | for (i = 0; i < ARRAY_SIZE(info->data->iphash); ++i) | 388 | info->data->climit_root4[i] = RB_ROOT; |
| 252 | INIT_HLIST_HEAD(&info->data->iphash[i]); | 389 | for (i = 0; i < ARRAY_SIZE(info->data->climit_root6); ++i) |
| 390 | info->data->climit_root6[i] = RB_ROOT; | ||
| 253 | 391 | ||
| 254 | return 0; | 392 | return 0; |
| 255 | } | 393 | } |
| 256 | 394 | ||
| 257 | static void connlimit_mt_destroy(const struct xt_mtdtor_param *par) | 395 | static void destroy_tree(struct rb_root *r) |
| 258 | { | 396 | { |
| 259 | const struct xt_connlimit_info *info = par->matchinfo; | ||
| 260 | struct xt_connlimit_conn *conn; | 397 | struct xt_connlimit_conn *conn; |
| 398 | struct xt_connlimit_rb *rbconn; | ||
| 261 | struct hlist_node *n; | 399 | struct hlist_node *n; |
| 262 | struct hlist_head *hash = info->data->iphash; | 400 | struct rb_node *node; |
| 401 | |||
| 402 | while ((node = rb_first(r)) != NULL) { | ||
| 403 | rbconn = container_of(node, struct xt_connlimit_rb, node); | ||
| 404 | |||
| 405 | rb_erase(node, r); | ||
| 406 | |||
| 407 | hlist_for_each_entry_safe(conn, n, &rbconn->hhead, node) | ||
| 408 | kmem_cache_free(connlimit_conn_cachep, conn); | ||
| 409 | |||
| 410 | kmem_cache_free(connlimit_rb_cachep, rbconn); | ||
| 411 | } | ||
| 412 | } | ||
| 413 | |||
| 414 | static void connlimit_mt_destroy(const struct xt_mtdtor_param *par) | ||
| 415 | { | ||
| 416 | const struct xt_connlimit_info *info = par->matchinfo; | ||
| 263 | unsigned int i; | 417 | unsigned int i; |
| 264 | 418 | ||
| 265 | nf_ct_l3proto_module_put(par->family); | 419 | nf_ct_l3proto_module_put(par->family); |
| 266 | 420 | ||
| 267 | for (i = 0; i < ARRAY_SIZE(info->data->iphash); ++i) { | 421 | for (i = 0; i < ARRAY_SIZE(info->data->climit_root4); ++i) |
| 268 | hlist_for_each_entry_safe(conn, n, &hash[i], node) { | 422 | destroy_tree(&info->data->climit_root4[i]); |
| 269 | hlist_del(&conn->node); | 423 | for (i = 0; i < ARRAY_SIZE(info->data->climit_root6); ++i) |
| 270 | kfree(conn); | 424 | destroy_tree(&info->data->climit_root6[i]); |
| 271 | } | ||
| 272 | } | ||
| 273 | 425 | ||
| 274 | kfree(info->data); | 426 | kfree(info->data); |
| 275 | } | 427 | } |
| @@ -287,12 +439,40 @@ static struct xt_match connlimit_mt_reg __read_mostly = { | |||
| 287 | 439 | ||
| 288 | static int __init connlimit_mt_init(void) | 440 | static int __init connlimit_mt_init(void) |
| 289 | { | 441 | { |
| 290 | return xt_register_match(&connlimit_mt_reg); | 442 | int ret, i; |
| 443 | |||
| 444 | BUILD_BUG_ON(CONNLIMIT_LOCK_SLOTS > CONNLIMIT_SLOTS); | ||
| 445 | BUILD_BUG_ON((CONNLIMIT_SLOTS % CONNLIMIT_LOCK_SLOTS) != 0); | ||
| 446 | |||
| 447 | for (i = 0; i < CONNLIMIT_LOCK_SLOTS; ++i) | ||
| 448 | spin_lock_init(&xt_connlimit_locks[i]); | ||
| 449 | |||
| 450 | connlimit_conn_cachep = kmem_cache_create("xt_connlimit_conn", | ||
| 451 | sizeof(struct xt_connlimit_conn), | ||
| 452 | 0, 0, NULL); | ||
| 453 | if (!connlimit_conn_cachep) | ||
| 454 | return -ENOMEM; | ||
| 455 | |||
| 456 | connlimit_rb_cachep = kmem_cache_create("xt_connlimit_rb", | ||
| 457 | sizeof(struct xt_connlimit_rb), | ||
| 458 | 0, 0, NULL); | ||
| 459 | if (!connlimit_rb_cachep) { | ||
| 460 | kmem_cache_destroy(connlimit_conn_cachep); | ||
| 461 | return -ENOMEM; | ||
| 462 | } | ||
| 463 | ret = xt_register_match(&connlimit_mt_reg); | ||
| 464 | if (ret != 0) { | ||
| 465 | kmem_cache_destroy(connlimit_conn_cachep); | ||
| 466 | kmem_cache_destroy(connlimit_rb_cachep); | ||
| 467 | } | ||
| 468 | return ret; | ||
| 291 | } | 469 | } |
| 292 | 470 | ||
| 293 | static void __exit connlimit_mt_exit(void) | 471 | static void __exit connlimit_mt_exit(void) |
| 294 | { | 472 | { |
| 295 | xt_unregister_match(&connlimit_mt_reg); | 473 | xt_unregister_match(&connlimit_mt_reg); |
| 474 | kmem_cache_destroy(connlimit_conn_cachep); | ||
| 475 | kmem_cache_destroy(connlimit_rb_cachep); | ||
| 296 | } | 476 | } |
| 297 | 477 | ||
| 298 | module_init(connlimit_mt_init); | 478 | module_init(connlimit_mt_init); |
diff --git a/net/netfilter/xt_ipcomp.c b/net/netfilter/xt_ipcomp.c index a4c7561698c5..89d53104c6b3 100644 --- a/net/netfilter/xt_ipcomp.c +++ b/net/netfilter/xt_ipcomp.c | |||
| @@ -60,7 +60,7 @@ static bool comp_mt(const struct sk_buff *skb, struct xt_action_param *par) | |||
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | return spi_match(compinfo->spis[0], compinfo->spis[1], | 62 | return spi_match(compinfo->spis[0], compinfo->spis[1], |
| 63 | ntohl(chdr->cpi << 16), | 63 | ntohs(chdr->cpi), |
| 64 | !!(compinfo->invflags & XT_IPCOMP_INV_SPI)); | 64 | !!(compinfo->invflags & XT_IPCOMP_INV_SPI)); |
| 65 | } | 65 | } |
| 66 | 66 | ||
diff --git a/net/netfilter/xt_osf.c b/net/netfilter/xt_osf.c index 7174611bd672..c529161cdbf8 100644 --- a/net/netfilter/xt_osf.c +++ b/net/netfilter/xt_osf.c | |||
| @@ -422,4 +422,6 @@ module_exit(xt_osf_fini); | |||
| 422 | MODULE_LICENSE("GPL"); | 422 | MODULE_LICENSE("GPL"); |
| 423 | MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>"); | 423 | MODULE_AUTHOR("Evgeniy Polyakov <zbr@ioremap.net>"); |
| 424 | MODULE_DESCRIPTION("Passive OS fingerprint matching."); | 424 | MODULE_DESCRIPTION("Passive OS fingerprint matching."); |
| 425 | MODULE_ALIAS("ipt_osf"); | ||
| 426 | MODULE_ALIAS("ip6t_osf"); | ||
| 425 | MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_OSF); | 427 | MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_OSF); |
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index 04748ab649c2..894cda0206bb 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c | |||
| @@ -1460,7 +1460,7 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, | |||
| 1460 | if (nlk->netlink_bind && nlk->groups[0]) { | 1460 | if (nlk->netlink_bind && nlk->groups[0]) { |
| 1461 | int i; | 1461 | int i; |
| 1462 | 1462 | ||
| 1463 | for (i=0; i<nlk->ngroups; i++) { | 1463 | for (i = 0; i < nlk->ngroups; i++) { |
| 1464 | if (test_bit(i, nlk->groups)) | 1464 | if (test_bit(i, nlk->groups)) |
| 1465 | nlk->netlink_bind(i); | 1465 | nlk->netlink_bind(i); |
| 1466 | } | 1466 | } |
| @@ -1653,7 +1653,7 @@ static int __netlink_sendskb(struct sock *sk, struct sk_buff *skb) | |||
| 1653 | else | 1653 | else |
| 1654 | #endif /* CONFIG_NETLINK_MMAP */ | 1654 | #endif /* CONFIG_NETLINK_MMAP */ |
| 1655 | skb_queue_tail(&sk->sk_receive_queue, skb); | 1655 | skb_queue_tail(&sk->sk_receive_queue, skb); |
| 1656 | sk->sk_data_ready(sk, len); | 1656 | sk->sk_data_ready(sk); |
| 1657 | return len; | 1657 | return len; |
| 1658 | } | 1658 | } |
| 1659 | 1659 | ||
| @@ -2343,6 +2343,11 @@ static int netlink_recvmsg(struct kiocb *kiocb, struct socket *sock, | |||
| 2343 | } | 2343 | } |
| 2344 | #endif | 2344 | #endif |
| 2345 | 2345 | ||
| 2346 | /* Record the max length of recvmsg() calls for future allocations */ | ||
| 2347 | nlk->max_recvmsg_len = max(nlk->max_recvmsg_len, len); | ||
| 2348 | nlk->max_recvmsg_len = min_t(size_t, nlk->max_recvmsg_len, | ||
| 2349 | 16384); | ||
| 2350 | |||
| 2346 | copied = data_skb->len; | 2351 | copied = data_skb->len; |
| 2347 | if (len < copied) { | 2352 | if (len < copied) { |
| 2348 | msg->msg_flags |= MSG_TRUNC; | 2353 | msg->msg_flags |= MSG_TRUNC; |
| @@ -2389,7 +2394,7 @@ out: | |||
| 2389 | return err ? : copied; | 2394 | return err ? : copied; |
| 2390 | } | 2395 | } |
| 2391 | 2396 | ||
| 2392 | static void netlink_data_ready(struct sock *sk, int len) | 2397 | static void netlink_data_ready(struct sock *sk) |
| 2393 | { | 2398 | { |
| 2394 | BUG(); | 2399 | BUG(); |
| 2395 | } | 2400 | } |
| @@ -2549,7 +2554,7 @@ __nlmsg_put(struct sk_buff *skb, u32 portid, u32 seq, int type, int len, int fla | |||
| 2549 | struct nlmsghdr *nlh; | 2554 | struct nlmsghdr *nlh; |
| 2550 | int size = nlmsg_msg_size(len); | 2555 | int size = nlmsg_msg_size(len); |
| 2551 | 2556 | ||
| 2552 | nlh = (struct nlmsghdr*)skb_put(skb, NLMSG_ALIGN(size)); | 2557 | nlh = (struct nlmsghdr *)skb_put(skb, NLMSG_ALIGN(size)); |
| 2553 | nlh->nlmsg_type = type; | 2558 | nlh->nlmsg_type = type; |
| 2554 | nlh->nlmsg_len = size; | 2559 | nlh->nlmsg_len = size; |
| 2555 | nlh->nlmsg_flags = flags; | 2560 | nlh->nlmsg_flags = flags; |
| @@ -2587,7 +2592,27 @@ static int netlink_dump(struct sock *sk) | |||
| 2587 | if (!netlink_rx_is_mmaped(sk) && | 2592 | if (!netlink_rx_is_mmaped(sk) && |
| 2588 | atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf) | 2593 | atomic_read(&sk->sk_rmem_alloc) >= sk->sk_rcvbuf) |
| 2589 | goto errout_skb; | 2594 | goto errout_skb; |
| 2590 | skb = netlink_alloc_skb(sk, alloc_size, nlk->portid, GFP_KERNEL); | 2595 | |
| 2596 | /* NLMSG_GOODSIZE is small to avoid high order allocations being | ||
| 2597 | * required, but it makes sense to _attempt_ a 16K bytes allocation | ||
| 2598 | * to reduce number of system calls on dump operations, if user | ||
| 2599 | * ever provided a big enough buffer. | ||
| 2600 | */ | ||
| 2601 | if (alloc_size < nlk->max_recvmsg_len) { | ||
| 2602 | skb = netlink_alloc_skb(sk, | ||
| 2603 | nlk->max_recvmsg_len, | ||
| 2604 | nlk->portid, | ||
| 2605 | GFP_KERNEL | | ||
| 2606 | __GFP_NOWARN | | ||
| 2607 | __GFP_NORETRY); | ||
| 2608 | /* available room should be exact amount to avoid MSG_TRUNC */ | ||
| 2609 | if (skb) | ||
| 2610 | skb_reserve(skb, skb_tailroom(skb) - | ||
| 2611 | nlk->max_recvmsg_len); | ||
| 2612 | } | ||
| 2613 | if (!skb) | ||
| 2614 | skb = netlink_alloc_skb(sk, alloc_size, nlk->portid, | ||
| 2615 | GFP_KERNEL); | ||
| 2591 | if (!skb) | 2616 | if (!skb) |
| 2592 | goto errout_skb; | 2617 | goto errout_skb; |
| 2593 | netlink_skb_set_owner_r(skb, sk); | 2618 | netlink_skb_set_owner_r(skb, sk); |
diff --git a/net/netlink/af_netlink.h b/net/netlink/af_netlink.h index acbd774eeb7c..ed13a790b00e 100644 --- a/net/netlink/af_netlink.h +++ b/net/netlink/af_netlink.h | |||
| @@ -31,6 +31,7 @@ struct netlink_sock { | |||
| 31 | u32 ngroups; | 31 | u32 ngroups; |
| 32 | unsigned long *groups; | 32 | unsigned long *groups; |
| 33 | unsigned long state; | 33 | unsigned long state; |
| 34 | size_t max_recvmsg_len; | ||
| 34 | wait_queue_head_t wait; | 35 | wait_queue_head_t wait; |
| 35 | bool cb_running; | 36 | bool cb_running; |
| 36 | struct netlink_callback cb; | 37 | struct netlink_callback cb; |
diff --git a/net/netrom/af_netrom.c b/net/netrom/af_netrom.c index b74aa0755521..ede50d197e10 100644 --- a/net/netrom/af_netrom.c +++ b/net/netrom/af_netrom.c | |||
| @@ -1011,7 +1011,7 @@ int nr_rx_frame(struct sk_buff *skb, struct net_device *dev) | |||
| 1011 | skb_queue_head(&sk->sk_receive_queue, skb); | 1011 | skb_queue_head(&sk->sk_receive_queue, skb); |
| 1012 | 1012 | ||
| 1013 | if (!sock_flag(sk, SOCK_DEAD)) | 1013 | if (!sock_flag(sk, SOCK_DEAD)) |
| 1014 | sk->sk_data_ready(sk, skb->len); | 1014 | sk->sk_data_ready(sk); |
| 1015 | 1015 | ||
| 1016 | bh_unlock_sock(sk); | 1016 | bh_unlock_sock(sk); |
| 1017 | 1017 | ||
diff --git a/net/nfc/core.c b/net/nfc/core.c index ca1e65f4b133..819b87702b70 100644 --- a/net/nfc/core.c +++ b/net/nfc/core.c | |||
| @@ -280,9 +280,6 @@ static struct nfc_target *nfc_find_target(struct nfc_dev *dev, u32 target_idx) | |||
| 280 | { | 280 | { |
| 281 | int i; | 281 | int i; |
| 282 | 282 | ||
| 283 | if (dev->n_targets == 0) | ||
| 284 | return NULL; | ||
| 285 | |||
| 286 | for (i = 0; i < dev->n_targets; i++) { | 283 | for (i = 0; i < dev->n_targets; i++) { |
| 287 | if (dev->targets[i].idx == target_idx) | 284 | if (dev->targets[i].idx == target_idx) |
| 288 | return &dev->targets[i]; | 285 | return &dev->targets[i]; |
| @@ -546,9 +543,9 @@ error: | |||
| 546 | 543 | ||
| 547 | struct nfc_se *nfc_find_se(struct nfc_dev *dev, u32 se_idx) | 544 | struct nfc_se *nfc_find_se(struct nfc_dev *dev, u32 se_idx) |
| 548 | { | 545 | { |
| 549 | struct nfc_se *se, *n; | 546 | struct nfc_se *se; |
| 550 | 547 | ||
| 551 | list_for_each_entry_safe(se, n, &dev->secure_elements, list) | 548 | list_for_each_entry(se, &dev->secure_elements, list) |
| 552 | if (se->idx == se_idx) | 549 | if (se->idx == se_idx) |
| 553 | return se; | 550 | return se; |
| 554 | 551 | ||
| @@ -655,9 +652,6 @@ int nfc_set_remote_general_bytes(struct nfc_dev *dev, u8 *gb, u8 gb_len) | |||
| 655 | { | 652 | { |
| 656 | pr_debug("dev_name=%s gb_len=%d\n", dev_name(&dev->dev), gb_len); | 653 | pr_debug("dev_name=%s gb_len=%d\n", dev_name(&dev->dev), gb_len); |
| 657 | 654 | ||
| 658 | if (gb_len > NFC_MAX_GT_LEN) | ||
| 659 | return -EINVAL; | ||
| 660 | |||
| 661 | return nfc_llcp_set_remote_gb(dev, gb, gb_len); | 655 | return nfc_llcp_set_remote_gb(dev, gb, gb_len); |
| 662 | } | 656 | } |
| 663 | EXPORT_SYMBOL(nfc_set_remote_general_bytes); | 657 | EXPORT_SYMBOL(nfc_set_remote_general_bytes); |
diff --git a/net/nfc/digital.h b/net/nfc/digital.h index 08b29b55ea63..3759add68b1b 100644 --- a/net/nfc/digital.h +++ b/net/nfc/digital.h | |||
| @@ -72,6 +72,12 @@ void digital_poll_next_tech(struct nfc_digital_dev *ddev); | |||
| 72 | 72 | ||
| 73 | int digital_in_send_sens_req(struct nfc_digital_dev *ddev, u8 rf_tech); | 73 | int digital_in_send_sens_req(struct nfc_digital_dev *ddev, u8 rf_tech); |
| 74 | int digital_in_send_sensf_req(struct nfc_digital_dev *ddev, u8 rf_tech); | 74 | int digital_in_send_sensf_req(struct nfc_digital_dev *ddev, u8 rf_tech); |
| 75 | int digital_in_send_iso15693_inv_req(struct nfc_digital_dev *ddev, u8 rf_tech); | ||
| 76 | |||
| 77 | int digital_in_iso_dep_pull_sod(struct nfc_digital_dev *ddev, | ||
| 78 | struct sk_buff *skb); | ||
| 79 | int digital_in_iso_dep_push_sod(struct nfc_digital_dev *ddev, | ||
| 80 | struct sk_buff *skb); | ||
| 75 | 81 | ||
| 76 | int digital_target_found(struct nfc_digital_dev *ddev, | 82 | int digital_target_found(struct nfc_digital_dev *ddev, |
| 77 | struct nfc_target *target, u8 protocol); | 83 | struct nfc_target *target, u8 protocol); |
diff --git a/net/nfc/digital_core.c b/net/nfc/digital_core.c index c129d1571ca6..e01e15dbf1ab 100644 --- a/net/nfc/digital_core.c +++ b/net/nfc/digital_core.c | |||
| @@ -25,6 +25,8 @@ | |||
| 25 | #define DIGITAL_PROTO_NFCF_RF_TECH \ | 25 | #define DIGITAL_PROTO_NFCF_RF_TECH \ |
| 26 | (NFC_PROTO_FELICA_MASK | NFC_PROTO_NFC_DEP_MASK) | 26 | (NFC_PROTO_FELICA_MASK | NFC_PROTO_NFC_DEP_MASK) |
| 27 | 27 | ||
| 28 | #define DIGITAL_PROTO_ISO15693_RF_TECH NFC_PROTO_ISO15693_MASK | ||
| 29 | |||
| 28 | struct digital_cmd { | 30 | struct digital_cmd { |
| 29 | struct list_head queue; | 31 | struct list_head queue; |
| 30 | 32 | ||
| @@ -331,6 +333,18 @@ int digital_target_found(struct nfc_digital_dev *ddev, | |||
| 331 | } | 333 | } |
| 332 | break; | 334 | break; |
| 333 | 335 | ||
| 336 | case NFC_PROTO_ISO15693: | ||
| 337 | framing = NFC_DIGITAL_FRAMING_ISO15693_T5T; | ||
| 338 | check_crc = digital_skb_check_crc_b; | ||
| 339 | add_crc = digital_skb_add_crc_b; | ||
| 340 | break; | ||
| 341 | |||
| 342 | case NFC_PROTO_ISO14443: | ||
| 343 | framing = NFC_DIGITAL_FRAMING_NFCA_T4T; | ||
| 344 | check_crc = digital_skb_check_crc_a; | ||
| 345 | add_crc = digital_skb_add_crc_a; | ||
| 346 | break; | ||
| 347 | |||
| 334 | default: | 348 | default: |
| 335 | pr_err("Invalid protocol %d\n", protocol); | 349 | pr_err("Invalid protocol %d\n", protocol); |
| 336 | return -EINVAL; | 350 | return -EINVAL; |
| @@ -461,7 +475,7 @@ static int digital_start_poll(struct nfc_dev *nfc_dev, __u32 im_protocols, | |||
| 461 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_106A, | 475 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_106A, |
| 462 | digital_in_send_sens_req); | 476 | digital_in_send_sens_req); |
| 463 | 477 | ||
| 464 | if (im_protocols & DIGITAL_PROTO_NFCF_RF_TECH) { | 478 | if (matching_im_protocols & DIGITAL_PROTO_NFCF_RF_TECH) { |
| 465 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_212F, | 479 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_212F, |
| 466 | digital_in_send_sensf_req); | 480 | digital_in_send_sensf_req); |
| 467 | 481 | ||
| @@ -469,7 +483,11 @@ static int digital_start_poll(struct nfc_dev *nfc_dev, __u32 im_protocols, | |||
| 469 | digital_in_send_sensf_req); | 483 | digital_in_send_sensf_req); |
| 470 | } | 484 | } |
| 471 | 485 | ||
| 472 | if (tm_protocols & NFC_PROTO_NFC_DEP_MASK) { | 486 | if (matching_im_protocols & DIGITAL_PROTO_ISO15693_RF_TECH) |
| 487 | digital_add_poll_tech(ddev, NFC_DIGITAL_RF_TECH_ISO15693, | ||
| 488 | digital_in_send_iso15693_inv_req); | ||
| 489 | |||
| 490 | if (matching_tm_protocols & NFC_PROTO_NFC_DEP_MASK) { | ||
| 473 | if (ddev->ops->tg_listen_mdaa) { | 491 | if (ddev->ops->tg_listen_mdaa) { |
| 474 | digital_add_poll_tech(ddev, 0, | 492 | digital_add_poll_tech(ddev, 0, |
| 475 | digital_tg_listen_mdaa); | 493 | digital_tg_listen_mdaa); |
| @@ -607,20 +625,30 @@ static void digital_in_send_complete(struct nfc_digital_dev *ddev, void *arg, | |||
| 607 | 625 | ||
| 608 | if (IS_ERR(resp)) { | 626 | if (IS_ERR(resp)) { |
| 609 | rc = PTR_ERR(resp); | 627 | rc = PTR_ERR(resp); |
| 628 | resp = NULL; | ||
| 610 | goto done; | 629 | goto done; |
| 611 | } | 630 | } |
| 612 | 631 | ||
| 613 | if (ddev->curr_protocol == NFC_PROTO_MIFARE) | 632 | if (ddev->curr_protocol == NFC_PROTO_MIFARE) { |
| 614 | rc = digital_in_recv_mifare_res(resp); | 633 | rc = digital_in_recv_mifare_res(resp); |
| 615 | else | 634 | /* crc check is done in digital_in_recv_mifare_res() */ |
| 616 | rc = ddev->skb_check_crc(resp); | 635 | goto done; |
| 636 | } | ||
| 617 | 637 | ||
| 638 | if (ddev->curr_protocol == NFC_PROTO_ISO14443) { | ||
| 639 | rc = digital_in_iso_dep_pull_sod(ddev, resp); | ||
| 640 | if (rc) | ||
| 641 | goto done; | ||
| 642 | } | ||
| 643 | |||
| 644 | rc = ddev->skb_check_crc(resp); | ||
| 645 | |||
| 646 | done: | ||
| 618 | if (rc) { | 647 | if (rc) { |
| 619 | kfree_skb(resp); | 648 | kfree_skb(resp); |
| 620 | resp = NULL; | 649 | resp = NULL; |
| 621 | } | 650 | } |
| 622 | 651 | ||
| 623 | done: | ||
| 624 | data_exch->cb(data_exch->cb_context, resp, rc); | 652 | data_exch->cb(data_exch->cb_context, resp, rc); |
| 625 | 653 | ||
| 626 | kfree(data_exch); | 654 | kfree(data_exch); |
| @@ -632,6 +660,7 @@ static int digital_in_send(struct nfc_dev *nfc_dev, struct nfc_target *target, | |||
| 632 | { | 660 | { |
| 633 | struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev); | 661 | struct nfc_digital_dev *ddev = nfc_get_drvdata(nfc_dev); |
| 634 | struct digital_data_exch *data_exch; | 662 | struct digital_data_exch *data_exch; |
| 663 | int rc; | ||
| 635 | 664 | ||
| 636 | data_exch = kzalloc(sizeof(struct digital_data_exch), GFP_KERNEL); | 665 | data_exch = kzalloc(sizeof(struct digital_data_exch), GFP_KERNEL); |
| 637 | if (!data_exch) { | 666 | if (!data_exch) { |
| @@ -642,13 +671,27 @@ static int digital_in_send(struct nfc_dev *nfc_dev, struct nfc_target *target, | |||
| 642 | data_exch->cb = cb; | 671 | data_exch->cb = cb; |
| 643 | data_exch->cb_context = cb_context; | 672 | data_exch->cb_context = cb_context; |
| 644 | 673 | ||
| 645 | if (ddev->curr_protocol == NFC_PROTO_NFC_DEP) | 674 | if (ddev->curr_protocol == NFC_PROTO_NFC_DEP) { |
| 646 | return digital_in_send_dep_req(ddev, target, skb, data_exch); | 675 | rc = digital_in_send_dep_req(ddev, target, skb, data_exch); |
| 676 | goto exit; | ||
| 677 | } | ||
| 678 | |||
| 679 | if (ddev->curr_protocol == NFC_PROTO_ISO14443) { | ||
| 680 | rc = digital_in_iso_dep_push_sod(ddev, skb); | ||
| 681 | if (rc) | ||
| 682 | goto exit; | ||
| 683 | } | ||
| 647 | 684 | ||
| 648 | ddev->skb_add_crc(skb); | 685 | ddev->skb_add_crc(skb); |
| 649 | 686 | ||
| 650 | return digital_in_send_cmd(ddev, skb, 500, digital_in_send_complete, | 687 | rc = digital_in_send_cmd(ddev, skb, 500, digital_in_send_complete, |
| 651 | data_exch); | 688 | data_exch); |
| 689 | |||
| 690 | exit: | ||
| 691 | if (rc) | ||
| 692 | kfree(data_exch); | ||
| 693 | |||
| 694 | return rc; | ||
| 652 | } | 695 | } |
| 653 | 696 | ||
| 654 | static struct nfc_ops digital_nfc_ops = { | 697 | static struct nfc_ops digital_nfc_ops = { |
| @@ -700,6 +743,10 @@ struct nfc_digital_dev *nfc_digital_allocate_device(struct nfc_digital_ops *ops, | |||
| 700 | ddev->protocols |= NFC_PROTO_FELICA_MASK; | 743 | ddev->protocols |= NFC_PROTO_FELICA_MASK; |
| 701 | if (supported_protocols & NFC_PROTO_NFC_DEP_MASK) | 744 | if (supported_protocols & NFC_PROTO_NFC_DEP_MASK) |
| 702 | ddev->protocols |= NFC_PROTO_NFC_DEP_MASK; | 745 | ddev->protocols |= NFC_PROTO_NFC_DEP_MASK; |
| 746 | if (supported_protocols & NFC_PROTO_ISO15693_MASK) | ||
| 747 | ddev->protocols |= NFC_PROTO_ISO15693_MASK; | ||
| 748 | if (supported_protocols & NFC_PROTO_ISO14443_MASK) | ||
| 749 | ddev->protocols |= NFC_PROTO_ISO14443_MASK; | ||
| 703 | 750 | ||
| 704 | ddev->tx_headroom = tx_headroom + DIGITAL_MAX_HEADER_LEN; | 751 | ddev->tx_headroom = tx_headroom + DIGITAL_MAX_HEADER_LEN; |
| 705 | ddev->tx_tailroom = tx_tailroom + DIGITAL_CRC_LEN; | 752 | ddev->tx_tailroom = tx_tailroom + DIGITAL_CRC_LEN; |
diff --git a/net/nfc/digital_technology.c b/net/nfc/digital_technology.c index 251c8c753ebe..278c3fed27e0 100644 --- a/net/nfc/digital_technology.c +++ b/net/nfc/digital_technology.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | 30 | ||
| 31 | #define DIGITAL_SEL_RES_NFCID1_COMPLETE(sel_res) (!((sel_res) & 0x04)) | 31 | #define DIGITAL_SEL_RES_NFCID1_COMPLETE(sel_res) (!((sel_res) & 0x04)) |
| 32 | #define DIGITAL_SEL_RES_IS_T2T(sel_res) (!((sel_res) & 0x60)) | 32 | #define DIGITAL_SEL_RES_IS_T2T(sel_res) (!((sel_res) & 0x60)) |
| 33 | #define DIGITAL_SEL_RES_IS_T4T(sel_res) ((sel_res) & 0x20) | ||
| 33 | #define DIGITAL_SEL_RES_IS_NFC_DEP(sel_res) ((sel_res) & 0x40) | 34 | #define DIGITAL_SEL_RES_IS_NFC_DEP(sel_res) ((sel_res) & 0x40) |
| 34 | 35 | ||
| 35 | #define DIGITAL_SENS_RES_IS_T1T(sens_res) (((sens_res) & 0x0C00) == 0x0C00) | 36 | #define DIGITAL_SENS_RES_IS_T1T(sens_res) (((sens_res) & 0x0C00) == 0x0C00) |
| @@ -51,6 +52,34 @@ | |||
| 51 | #define DIGITAL_SENSF_REQ_RC_SC 1 | 52 | #define DIGITAL_SENSF_REQ_RC_SC 1 |
| 52 | #define DIGITAL_SENSF_REQ_RC_AP 2 | 53 | #define DIGITAL_SENSF_REQ_RC_AP 2 |
| 53 | 54 | ||
| 55 | #define DIGITAL_CMD_ISO15693_INVENTORY_REQ 0x01 | ||
| 56 | |||
| 57 | #define DIGITAL_ISO15693_REQ_FLAG_DATA_RATE BIT(1) | ||
| 58 | #define DIGITAL_ISO15693_REQ_FLAG_INVENTORY BIT(2) | ||
| 59 | #define DIGITAL_ISO15693_REQ_FLAG_NB_SLOTS BIT(5) | ||
| 60 | #define DIGITAL_ISO15693_RES_FLAG_ERROR BIT(0) | ||
| 61 | #define DIGITAL_ISO15693_RES_IS_VALID(flags) \ | ||
| 62 | (!((flags) & DIGITAL_ISO15693_RES_FLAG_ERROR)) | ||
| 63 | |||
| 64 | #define DIGITAL_ISO_DEP_I_PCB 0x02 | ||
| 65 | #define DIGITAL_ISO_DEP_PNI(pni) ((pni) & 0x01) | ||
| 66 | |||
| 67 | #define DIGITAL_ISO_DEP_PCB_TYPE(pcb) ((pcb) & 0xC0) | ||
| 68 | |||
| 69 | #define DIGITAL_ISO_DEP_I_BLOCK 0x00 | ||
| 70 | |||
| 71 | #define DIGITAL_ISO_DEP_BLOCK_HAS_DID(pcb) ((pcb) & 0x08) | ||
| 72 | |||
| 73 | static const u8 digital_ats_fsc[] = { | ||
| 74 | 16, 24, 32, 40, 48, 64, 96, 128, | ||
| 75 | }; | ||
| 76 | |||
| 77 | #define DIGITAL_ATS_FSCI(t0) ((t0) & 0x0F) | ||
| 78 | #define DIGITAL_ATS_MAX_FSC 256 | ||
| 79 | |||
| 80 | #define DIGITAL_RATS_BYTE1 0xE0 | ||
| 81 | #define DIGITAL_RATS_PARAM 0x80 | ||
| 82 | |||
| 54 | struct digital_sdd_res { | 83 | struct digital_sdd_res { |
| 55 | u8 nfcid1[4]; | 84 | u8 nfcid1[4]; |
| 56 | u8 bcc; | 85 | u8 bcc; |
| @@ -82,9 +111,127 @@ struct digital_sensf_res { | |||
| 82 | u8 rd[2]; | 111 | u8 rd[2]; |
| 83 | } __packed; | 112 | } __packed; |
| 84 | 113 | ||
| 114 | struct digital_iso15693_inv_req { | ||
| 115 | u8 flags; | ||
| 116 | u8 cmd; | ||
| 117 | u8 mask_len; | ||
| 118 | u64 mask; | ||
| 119 | } __packed; | ||
| 120 | |||
| 121 | struct digital_iso15693_inv_res { | ||
| 122 | u8 flags; | ||
| 123 | u8 dsfid; | ||
| 124 | u64 uid; | ||
| 125 | } __packed; | ||
| 126 | |||
| 85 | static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev, | 127 | static int digital_in_send_sdd_req(struct nfc_digital_dev *ddev, |
| 86 | struct nfc_target *target); | 128 | struct nfc_target *target); |
| 87 | 129 | ||
| 130 | int digital_in_iso_dep_pull_sod(struct nfc_digital_dev *ddev, | ||
| 131 | struct sk_buff *skb) | ||
| 132 | { | ||
| 133 | u8 pcb; | ||
| 134 | u8 block_type; | ||
| 135 | |||
| 136 | if (skb->len < 1) | ||
| 137 | return -EIO; | ||
| 138 | |||
| 139 | pcb = *skb->data; | ||
| 140 | block_type = DIGITAL_ISO_DEP_PCB_TYPE(pcb); | ||
| 141 | |||
| 142 | /* No support fo R-block nor S-block */ | ||
| 143 | if (block_type != DIGITAL_ISO_DEP_I_BLOCK) { | ||
| 144 | pr_err("ISO_DEP R-block and S-block not supported\n"); | ||
| 145 | return -EIO; | ||
| 146 | } | ||
| 147 | |||
| 148 | if (DIGITAL_ISO_DEP_BLOCK_HAS_DID(pcb)) { | ||
| 149 | pr_err("DID field in ISO_DEP PCB not supported\n"); | ||
| 150 | return -EIO; | ||
| 151 | } | ||
| 152 | |||
| 153 | skb_pull(skb, 1); | ||
| 154 | |||
| 155 | return 0; | ||
| 156 | } | ||
| 157 | |||
| 158 | int digital_in_iso_dep_push_sod(struct nfc_digital_dev *ddev, | ||
| 159 | struct sk_buff *skb) | ||
| 160 | { | ||
| 161 | /* | ||
| 162 | * Chaining not supported so skb->len + 1 PCB byte + 2 CRC bytes must | ||
| 163 | * not be greater than remote FSC | ||
| 164 | */ | ||
| 165 | if (skb->len + 3 > ddev->target_fsc) | ||
| 166 | return -EIO; | ||
| 167 | |||
| 168 | skb_push(skb, 1); | ||
| 169 | |||
| 170 | *skb->data = DIGITAL_ISO_DEP_I_PCB | ddev->curr_nfc_dep_pni; | ||
| 171 | |||
| 172 | ddev->curr_nfc_dep_pni = | ||
| 173 | DIGITAL_ISO_DEP_PNI(ddev->curr_nfc_dep_pni + 1); | ||
| 174 | |||
| 175 | return 0; | ||
| 176 | } | ||
| 177 | |||
| 178 | static void digital_in_recv_ats(struct nfc_digital_dev *ddev, void *arg, | ||
| 179 | struct sk_buff *resp) | ||
| 180 | { | ||
| 181 | struct nfc_target *target = arg; | ||
| 182 | u8 fsdi; | ||
| 183 | int rc; | ||
| 184 | |||
| 185 | if (IS_ERR(resp)) { | ||
| 186 | rc = PTR_ERR(resp); | ||
| 187 | resp = NULL; | ||
| 188 | goto exit; | ||
| 189 | } | ||
| 190 | |||
| 191 | if (resp->len < 2) { | ||
| 192 | rc = -EIO; | ||
| 193 | goto exit; | ||
| 194 | } | ||
| 195 | |||
| 196 | fsdi = DIGITAL_ATS_FSCI(resp->data[1]); | ||
| 197 | if (fsdi >= 8) | ||
| 198 | ddev->target_fsc = DIGITAL_ATS_MAX_FSC; | ||
| 199 | else | ||
| 200 | ddev->target_fsc = digital_ats_fsc[fsdi]; | ||
| 201 | |||
| 202 | ddev->curr_nfc_dep_pni = 0; | ||
| 203 | |||
| 204 | rc = digital_target_found(ddev, target, NFC_PROTO_ISO14443); | ||
| 205 | |||
| 206 | exit: | ||
| 207 | dev_kfree_skb(resp); | ||
| 208 | kfree(target); | ||
| 209 | |||
| 210 | if (rc) | ||
| 211 | digital_poll_next_tech(ddev); | ||
| 212 | } | ||
| 213 | |||
| 214 | static int digital_in_send_rats(struct nfc_digital_dev *ddev, | ||
| 215 | struct nfc_target *target) | ||
| 216 | { | ||
| 217 | int rc; | ||
| 218 | struct sk_buff *skb; | ||
| 219 | |||
| 220 | skb = digital_skb_alloc(ddev, 2); | ||
| 221 | if (!skb) | ||
| 222 | return -ENOMEM; | ||
| 223 | |||
| 224 | *skb_put(skb, 1) = DIGITAL_RATS_BYTE1; | ||
| 225 | *skb_put(skb, 1) = DIGITAL_RATS_PARAM; | ||
| 226 | |||
| 227 | rc = digital_in_send_cmd(ddev, skb, 30, digital_in_recv_ats, | ||
| 228 | target); | ||
| 229 | if (rc) | ||
| 230 | kfree_skb(skb); | ||
| 231 | |||
| 232 | return rc; | ||
| 233 | } | ||
| 234 | |||
| 88 | static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg, | 235 | static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg, |
| 89 | struct sk_buff *resp) | 236 | struct sk_buff *resp) |
| 90 | { | 237 | { |
| @@ -122,8 +269,19 @@ static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg, | |||
| 122 | goto exit_free_skb; | 269 | goto exit_free_skb; |
| 123 | } | 270 | } |
| 124 | 271 | ||
| 272 | target->sel_res = sel_res; | ||
| 273 | |||
| 125 | if (DIGITAL_SEL_RES_IS_T2T(sel_res)) { | 274 | if (DIGITAL_SEL_RES_IS_T2T(sel_res)) { |
| 126 | nfc_proto = NFC_PROTO_MIFARE; | 275 | nfc_proto = NFC_PROTO_MIFARE; |
| 276 | } else if (DIGITAL_SEL_RES_IS_T4T(sel_res)) { | ||
| 277 | rc = digital_in_send_rats(ddev, target); | ||
| 278 | if (rc) | ||
| 279 | goto exit; | ||
| 280 | /* | ||
| 281 | * Skip target_found and don't free it for now. This will be | ||
| 282 | * done when receiving the ATS | ||
| 283 | */ | ||
| 284 | goto exit_free_skb; | ||
| 127 | } else if (DIGITAL_SEL_RES_IS_NFC_DEP(sel_res)) { | 285 | } else if (DIGITAL_SEL_RES_IS_NFC_DEP(sel_res)) { |
| 128 | nfc_proto = NFC_PROTO_NFC_DEP; | 286 | nfc_proto = NFC_PROTO_NFC_DEP; |
| 129 | } else { | 287 | } else { |
| @@ -131,8 +289,6 @@ static void digital_in_recv_sel_res(struct nfc_digital_dev *ddev, void *arg, | |||
| 131 | goto exit; | 289 | goto exit; |
| 132 | } | 290 | } |
| 133 | 291 | ||
| 134 | target->sel_res = sel_res; | ||
| 135 | |||
| 136 | rc = digital_target_found(ddev, target, nfc_proto); | 292 | rc = digital_target_found(ddev, target, nfc_proto); |
| 137 | 293 | ||
| 138 | exit: | 294 | exit: |
| @@ -473,6 +629,93 @@ int digital_in_send_sensf_req(struct nfc_digital_dev *ddev, u8 rf_tech) | |||
| 473 | return rc; | 629 | return rc; |
| 474 | } | 630 | } |
| 475 | 631 | ||
| 632 | static void digital_in_recv_iso15693_inv_res(struct nfc_digital_dev *ddev, | ||
| 633 | void *arg, struct sk_buff *resp) | ||
| 634 | { | ||
| 635 | struct digital_iso15693_inv_res *res; | ||
| 636 | struct nfc_target *target = NULL; | ||
| 637 | int rc; | ||
| 638 | |||
| 639 | if (IS_ERR(resp)) { | ||
| 640 | rc = PTR_ERR(resp); | ||
| 641 | resp = NULL; | ||
| 642 | goto out_free_skb; | ||
| 643 | } | ||
| 644 | |||
| 645 | if (resp->len != sizeof(*res)) { | ||
| 646 | rc = -EIO; | ||
| 647 | goto out_free_skb; | ||
| 648 | } | ||
| 649 | |||
| 650 | res = (struct digital_iso15693_inv_res *)resp->data; | ||
| 651 | |||
| 652 | if (!DIGITAL_ISO15693_RES_IS_VALID(res->flags)) { | ||
| 653 | PROTOCOL_ERR("ISO15693 - 10.3.1"); | ||
| 654 | rc = -EINVAL; | ||
| 655 | goto out_free_skb; | ||
| 656 | } | ||
| 657 | |||
| 658 | target = kzalloc(sizeof(*target), GFP_KERNEL); | ||
| 659 | if (!target) { | ||
| 660 | rc = -ENOMEM; | ||
| 661 | goto out_free_skb; | ||
| 662 | } | ||
| 663 | |||
| 664 | target->is_iso15693 = 1; | ||
| 665 | target->iso15693_dsfid = res->dsfid; | ||
| 666 | memcpy(target->iso15693_uid, &res->uid, sizeof(target->iso15693_uid)); | ||
| 667 | |||
| 668 | rc = digital_target_found(ddev, target, NFC_PROTO_ISO15693); | ||
| 669 | |||
| 670 | kfree(target); | ||
| 671 | |||
| 672 | out_free_skb: | ||
| 673 | dev_kfree_skb(resp); | ||
| 674 | |||
| 675 | if (rc) | ||
| 676 | digital_poll_next_tech(ddev); | ||
| 677 | } | ||
| 678 | |||
| 679 | int digital_in_send_iso15693_inv_req(struct nfc_digital_dev *ddev, u8 rf_tech) | ||
| 680 | { | ||
| 681 | struct digital_iso15693_inv_req *req; | ||
| 682 | struct sk_buff *skb; | ||
| 683 | int rc; | ||
| 684 | |||
| 685 | rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_RF_TECH, | ||
| 686 | NFC_DIGITAL_RF_TECH_ISO15693); | ||
| 687 | if (rc) | ||
| 688 | return rc; | ||
| 689 | |||
| 690 | rc = digital_in_configure_hw(ddev, NFC_DIGITAL_CONFIG_FRAMING, | ||
| 691 | NFC_DIGITAL_FRAMING_ISO15693_INVENTORY); | ||
| 692 | if (rc) | ||
| 693 | return rc; | ||
| 694 | |||
| 695 | skb = digital_skb_alloc(ddev, sizeof(*req)); | ||
| 696 | if (!skb) | ||
| 697 | return -ENOMEM; | ||
| 698 | |||
| 699 | skb_put(skb, sizeof(*req) - sizeof(req->mask)); /* No mask */ | ||
| 700 | req = (struct digital_iso15693_inv_req *)skb->data; | ||
| 701 | |||
| 702 | /* Single sub-carrier, high data rate, no AFI, single slot | ||
| 703 | * Inventory command | ||
| 704 | */ | ||
| 705 | req->flags = DIGITAL_ISO15693_REQ_FLAG_DATA_RATE | | ||
| 706 | DIGITAL_ISO15693_REQ_FLAG_INVENTORY | | ||
| 707 | DIGITAL_ISO15693_REQ_FLAG_NB_SLOTS; | ||
| 708 | req->cmd = DIGITAL_CMD_ISO15693_INVENTORY_REQ; | ||
| 709 | req->mask_len = 0; | ||
| 710 | |||
| 711 | rc = digital_in_send_cmd(ddev, skb, 30, | ||
| 712 | digital_in_recv_iso15693_inv_res, NULL); | ||
| 713 | if (rc) | ||
| 714 | kfree_skb(skb); | ||
| 715 | |||
| 716 | return rc; | ||
| 717 | } | ||
| 718 | |||
| 476 | static int digital_tg_send_sel_res(struct nfc_digital_dev *ddev) | 719 | static int digital_tg_send_sel_res(struct nfc_digital_dev *ddev) |
| 477 | { | 720 | { |
| 478 | struct sk_buff *skb; | 721 | struct sk_buff *skb; |
diff --git a/net/nfc/hci/llc.c b/net/nfc/hci/llc.c index a07d2b818487..1b90c0531852 100644 --- a/net/nfc/hci/llc.c +++ b/net/nfc/hci/llc.c | |||
| @@ -20,14 +20,12 @@ | |||
| 20 | 20 | ||
| 21 | #include "llc.h" | 21 | #include "llc.h" |
| 22 | 22 | ||
| 23 | static struct list_head llc_engines; | 23 | static LIST_HEAD(llc_engines); |
| 24 | 24 | ||
| 25 | int nfc_llc_init(void) | 25 | int nfc_llc_init(void) |
| 26 | { | 26 | { |
| 27 | int r; | 27 | int r; |
| 28 | 28 | ||
| 29 | INIT_LIST_HEAD(&llc_engines); | ||
| 30 | |||
| 31 | r = nfc_llc_nop_register(); | 29 | r = nfc_llc_nop_register(); |
| 32 | if (r) | 30 | if (r) |
| 33 | goto exit; | 31 | goto exit; |
diff --git a/net/nfc/llcp_core.c b/net/nfc/llcp_core.c index 6184bd1fba3a..b4671958fcf9 100644 --- a/net/nfc/llcp_core.c +++ b/net/nfc/llcp_core.c | |||
| @@ -27,7 +27,7 @@ | |||
| 27 | 27 | ||
| 28 | static u8 llcp_magic[3] = {0x46, 0x66, 0x6d}; | 28 | static u8 llcp_magic[3] = {0x46, 0x66, 0x6d}; |
| 29 | 29 | ||
| 30 | static struct list_head llcp_devices; | 30 | static LIST_HEAD(llcp_devices); |
| 31 | 31 | ||
| 32 | static void nfc_llcp_rx_skb(struct nfc_llcp_local *local, struct sk_buff *skb); | 32 | static void nfc_llcp_rx_skb(struct nfc_llcp_local *local, struct sk_buff *skb); |
| 33 | 33 | ||
| @@ -293,9 +293,9 @@ static void nfc_llcp_sdreq_timer(unsigned long data) | |||
| 293 | 293 | ||
| 294 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev) | 294 | struct nfc_llcp_local *nfc_llcp_find_local(struct nfc_dev *dev) |
| 295 | { | 295 | { |
| 296 | struct nfc_llcp_local *local, *n; | 296 | struct nfc_llcp_local *local; |
| 297 | 297 | ||
| 298 | list_for_each_entry_safe(local, n, &llcp_devices, list) | 298 | list_for_each_entry(local, &llcp_devices, list) |
| 299 | if (local->dev == dev) | 299 | if (local->dev == dev) |
| 300 | return local; | 300 | return local; |
| 301 | 301 | ||
| @@ -609,14 +609,16 @@ u8 *nfc_llcp_general_bytes(struct nfc_dev *dev, size_t *general_bytes_len) | |||
| 609 | 609 | ||
| 610 | int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len) | 610 | int nfc_llcp_set_remote_gb(struct nfc_dev *dev, u8 *gb, u8 gb_len) |
| 611 | { | 611 | { |
| 612 | struct nfc_llcp_local *local = nfc_llcp_find_local(dev); | 612 | struct nfc_llcp_local *local; |
| 613 | |||
| 614 | if (gb_len < 3 || gb_len > NFC_MAX_GT_LEN) | ||
| 615 | return -EINVAL; | ||
| 613 | 616 | ||
| 617 | local = nfc_llcp_find_local(dev); | ||
| 614 | if (local == NULL) { | 618 | if (local == NULL) { |
| 615 | pr_err("No LLCP device\n"); | 619 | pr_err("No LLCP device\n"); |
| 616 | return -ENODEV; | 620 | return -ENODEV; |
| 617 | } | 621 | } |
| 618 | if (gb_len < 3) | ||
| 619 | return -EINVAL; | ||
| 620 | 622 | ||
| 621 | memset(local->remote_gb, 0, NFC_MAX_GT_LEN); | 623 | memset(local->remote_gb, 0, NFC_MAX_GT_LEN); |
| 622 | memcpy(local->remote_gb, gb, gb_len); | 624 | memcpy(local->remote_gb, gb, gb_len); |
| @@ -974,7 +976,7 @@ static void nfc_llcp_recv_connect(struct nfc_llcp_local *local, | |||
| 974 | new_sk->sk_state = LLCP_CONNECTED; | 976 | new_sk->sk_state = LLCP_CONNECTED; |
| 975 | 977 | ||
| 976 | /* Wake the listening processes */ | 978 | /* Wake the listening processes */ |
| 977 | parent->sk_data_ready(parent, 0); | 979 | parent->sk_data_ready(parent); |
| 978 | 980 | ||
| 979 | /* Send CC */ | 981 | /* Send CC */ |
| 980 | nfc_llcp_send_cc(new_sock); | 982 | nfc_llcp_send_cc(new_sock); |
| @@ -1622,8 +1624,6 @@ void nfc_llcp_unregister_device(struct nfc_dev *dev) | |||
| 1622 | 1624 | ||
| 1623 | int __init nfc_llcp_init(void) | 1625 | int __init nfc_llcp_init(void) |
| 1624 | { | 1626 | { |
| 1625 | INIT_LIST_HEAD(&llcp_devices); | ||
| 1626 | |||
| 1627 | return nfc_llcp_sock_init(); | 1627 | return nfc_llcp_sock_init(); |
| 1628 | } | 1628 | } |
| 1629 | 1629 | ||
diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index 56db888b1cd5..6c34ac978501 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c | |||
| @@ -74,7 +74,7 @@ static int __nci_request(struct nci_dev *ndev, | |||
| 74 | 74 | ||
| 75 | ndev->req_status = NCI_REQ_PEND; | 75 | ndev->req_status = NCI_REQ_PEND; |
| 76 | 76 | ||
| 77 | init_completion(&ndev->req_completion); | 77 | reinit_completion(&ndev->req_completion); |
| 78 | req(ndev, opt); | 78 | req(ndev, opt); |
| 79 | completion_rc = | 79 | completion_rc = |
| 80 | wait_for_completion_interruptible_timeout(&ndev->req_completion, | 80 | wait_for_completion_interruptible_timeout(&ndev->req_completion, |
| @@ -709,6 +709,7 @@ struct nci_dev *nci_allocate_device(struct nci_ops *ops, | |||
| 709 | ndev->ops = ops; | 709 | ndev->ops = ops; |
| 710 | ndev->tx_headroom = tx_headroom; | 710 | ndev->tx_headroom = tx_headroom; |
| 711 | ndev->tx_tailroom = tx_tailroom; | 711 | ndev->tx_tailroom = tx_tailroom; |
| 712 | init_completion(&ndev->req_completion); | ||
| 712 | 713 | ||
| 713 | ndev->nfc_dev = nfc_allocate_device(&nci_nfc_ops, | 714 | ndev->nfc_dev = nfc_allocate_device(&nci_nfc_ops, |
| 714 | supported_protocols, | 715 | supported_protocols, |
diff --git a/net/nfc/nci/spi.c b/net/nfc/nci/spi.c index f1d426f10cce..ec250e77763a 100644 --- a/net/nfc/nci/spi.c +++ b/net/nfc/nci/spi.c | |||
| @@ -105,7 +105,7 @@ int nci_spi_send(struct nci_spi *nspi, | |||
| 105 | if (ret != 0 || nspi->acknowledge_mode == NCI_SPI_CRC_DISABLED) | 105 | if (ret != 0 || nspi->acknowledge_mode == NCI_SPI_CRC_DISABLED) |
| 106 | goto done; | 106 | goto done; |
| 107 | 107 | ||
| 108 | init_completion(&nspi->req_completion); | 108 | reinit_completion(&nspi->req_completion); |
| 109 | completion_rc = wait_for_completion_interruptible_timeout( | 109 | completion_rc = wait_for_completion_interruptible_timeout( |
| 110 | &nspi->req_completion, | 110 | &nspi->req_completion, |
| 111 | NCI_SPI_SEND_TIMEOUT); | 111 | NCI_SPI_SEND_TIMEOUT); |
| @@ -145,6 +145,7 @@ struct nci_spi *nci_spi_allocate_spi(struct spi_device *spi, | |||
| 145 | 145 | ||
| 146 | nspi->spi = spi; | 146 | nspi->spi = spi; |
| 147 | nspi->ndev = ndev; | 147 | nspi->ndev = ndev; |
| 148 | init_completion(&nspi->req_completion); | ||
| 148 | 149 | ||
| 149 | return nspi; | 150 | return nspi; |
| 150 | } | 151 | } |
diff --git a/net/nfc/netlink.c b/net/nfc/netlink.c index ebbf6fb88b35..43cb1c17e267 100644 --- a/net/nfc/netlink.c +++ b/net/nfc/netlink.c | |||
| @@ -94,6 +94,14 @@ static int nfc_genl_send_target(struct sk_buff *msg, struct nfc_target *target, | |||
| 94 | target->sensf_res)) | 94 | target->sensf_res)) |
| 95 | goto nla_put_failure; | 95 | goto nla_put_failure; |
| 96 | 96 | ||
| 97 | if (target->is_iso15693) { | ||
| 98 | if (nla_put_u8(msg, NFC_ATTR_TARGET_ISO15693_DSFID, | ||
| 99 | target->iso15693_dsfid) || | ||
| 100 | nla_put(msg, NFC_ATTR_TARGET_ISO15693_UID, | ||
| 101 | sizeof(target->iso15693_uid), target->iso15693_uid)) | ||
| 102 | goto nla_put_failure; | ||
| 103 | } | ||
| 104 | |||
| 97 | return genlmsg_end(msg, hdr); | 105 | return genlmsg_end(msg, hdr); |
| 98 | 106 | ||
| 99 | nla_put_failure: | 107 | nla_put_failure: |
diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 270b77dfac30..a3276e3c4feb 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c | |||
| @@ -256,10 +256,10 @@ void ovs_dp_process_received_packet(struct vport *p, struct sk_buff *skb) | |||
| 256 | 256 | ||
| 257 | out: | 257 | out: |
| 258 | /* Update datapath statistics. */ | 258 | /* Update datapath statistics. */ |
| 259 | u64_stats_update_begin(&stats->sync); | 259 | u64_stats_update_begin(&stats->syncp); |
| 260 | (*stats_counter)++; | 260 | (*stats_counter)++; |
| 261 | stats->n_mask_hit += n_mask_hit; | 261 | stats->n_mask_hit += n_mask_hit; |
| 262 | u64_stats_update_end(&stats->sync); | 262 | u64_stats_update_end(&stats->syncp); |
| 263 | } | 263 | } |
| 264 | 264 | ||
| 265 | static struct genl_family dp_packet_genl_family = { | 265 | static struct genl_family dp_packet_genl_family = { |
| @@ -295,9 +295,9 @@ int ovs_dp_upcall(struct datapath *dp, struct sk_buff *skb, | |||
| 295 | err: | 295 | err: |
| 296 | stats = this_cpu_ptr(dp->stats_percpu); | 296 | stats = this_cpu_ptr(dp->stats_percpu); |
| 297 | 297 | ||
| 298 | u64_stats_update_begin(&stats->sync); | 298 | u64_stats_update_begin(&stats->syncp); |
| 299 | stats->n_lost++; | 299 | stats->n_lost++; |
| 300 | u64_stats_update_end(&stats->sync); | 300 | u64_stats_update_end(&stats->syncp); |
| 301 | 301 | ||
| 302 | return err; | 302 | return err; |
| 303 | } | 303 | } |
| @@ -610,9 +610,9 @@ static void get_dp_stats(struct datapath *dp, struct ovs_dp_stats *stats, | |||
| 610 | percpu_stats = per_cpu_ptr(dp->stats_percpu, i); | 610 | percpu_stats = per_cpu_ptr(dp->stats_percpu, i); |
| 611 | 611 | ||
| 612 | do { | 612 | do { |
| 613 | start = u64_stats_fetch_begin_bh(&percpu_stats->sync); | 613 | start = u64_stats_fetch_begin_irq(&percpu_stats->syncp); |
| 614 | local_stats = *percpu_stats; | 614 | local_stats = *percpu_stats; |
| 615 | } while (u64_stats_fetch_retry_bh(&percpu_stats->sync, start)); | 615 | } while (u64_stats_fetch_retry_irq(&percpu_stats->syncp, start)); |
| 616 | 616 | ||
| 617 | stats->n_hit += local_stats.n_hit; | 617 | stats->n_hit += local_stats.n_hit; |
| 618 | stats->n_missed += local_stats.n_missed; | 618 | stats->n_missed += local_stats.n_missed; |
| @@ -1219,18 +1219,12 @@ static int ovs_dp_cmd_new(struct sk_buff *skb, struct genl_info *info) | |||
| 1219 | if (err) | 1219 | if (err) |
| 1220 | goto err_free_dp; | 1220 | goto err_free_dp; |
| 1221 | 1221 | ||
| 1222 | dp->stats_percpu = alloc_percpu(struct dp_stats_percpu); | 1222 | dp->stats_percpu = netdev_alloc_pcpu_stats(struct dp_stats_percpu); |
| 1223 | if (!dp->stats_percpu) { | 1223 | if (!dp->stats_percpu) { |
| 1224 | err = -ENOMEM; | 1224 | err = -ENOMEM; |
| 1225 | goto err_destroy_table; | 1225 | goto err_destroy_table; |
| 1226 | } | 1226 | } |
| 1227 | 1227 | ||
| 1228 | for_each_possible_cpu(i) { | ||
| 1229 | struct dp_stats_percpu *dpath_stats; | ||
| 1230 | dpath_stats = per_cpu_ptr(dp->stats_percpu, i); | ||
| 1231 | u64_stats_init(&dpath_stats->sync); | ||
| 1232 | } | ||
| 1233 | |||
| 1234 | dp->ports = kmalloc(DP_VPORT_HASH_BUCKETS * sizeof(struct hlist_head), | 1228 | dp->ports = kmalloc(DP_VPORT_HASH_BUCKETS * sizeof(struct hlist_head), |
| 1235 | GFP_KERNEL); | 1229 | GFP_KERNEL); |
| 1236 | if (!dp->ports) { | 1230 | if (!dp->ports) { |
diff --git a/net/openvswitch/datapath.h b/net/openvswitch/datapath.h index 6be9fbb5e9cb..05317380fc03 100644 --- a/net/openvswitch/datapath.h +++ b/net/openvswitch/datapath.h | |||
| @@ -55,7 +55,7 @@ struct dp_stats_percpu { | |||
| 55 | u64 n_missed; | 55 | u64 n_missed; |
| 56 | u64 n_lost; | 56 | u64 n_lost; |
| 57 | u64 n_mask_hit; | 57 | u64 n_mask_hit; |
| 58 | struct u64_stats_sync sync; | 58 | struct u64_stats_sync syncp; |
| 59 | }; | 59 | }; |
| 60 | 60 | ||
| 61 | /** | 61 | /** |
diff --git a/net/openvswitch/vport-gre.c b/net/openvswitch/vport-gre.c index a3d6951602db..ebb6e2442554 100644 --- a/net/openvswitch/vport-gre.c +++ b/net/openvswitch/vport-gre.c | |||
| @@ -174,7 +174,7 @@ static int gre_tnl_send(struct vport *vport, struct sk_buff *skb) | |||
| 174 | 174 | ||
| 175 | skb->local_df = 1; | 175 | skb->local_df = 1; |
| 176 | 176 | ||
| 177 | return iptunnel_xmit(rt, skb, fl.saddr, | 177 | return iptunnel_xmit(skb->sk, rt, skb, fl.saddr, |
| 178 | OVS_CB(skb)->tun_key->ipv4_dst, IPPROTO_GRE, | 178 | OVS_CB(skb)->tun_key->ipv4_dst, IPPROTO_GRE, |
| 179 | OVS_CB(skb)->tun_key->ipv4_tos, | 179 | OVS_CB(skb)->tun_key->ipv4_tos, |
| 180 | OVS_CB(skb)->tun_key->ipv4_ttl, df, false); | 180 | OVS_CB(skb)->tun_key->ipv4_ttl, df, false); |
diff --git a/net/openvswitch/vport.c b/net/openvswitch/vport.c index 208dd9a26dd1..42c0f4a0b78c 100644 --- a/net/openvswitch/vport.c +++ b/net/openvswitch/vport.c | |||
| @@ -121,7 +121,6 @@ struct vport *ovs_vport_alloc(int priv_size, const struct vport_ops *ops, | |||
| 121 | { | 121 | { |
| 122 | struct vport *vport; | 122 | struct vport *vport; |
| 123 | size_t alloc_size; | 123 | size_t alloc_size; |
| 124 | int i; | ||
| 125 | 124 | ||
| 126 | alloc_size = sizeof(struct vport); | 125 | alloc_size = sizeof(struct vport); |
| 127 | if (priv_size) { | 126 | if (priv_size) { |
| @@ -139,19 +138,12 @@ struct vport *ovs_vport_alloc(int priv_size, const struct vport_ops *ops, | |||
| 139 | vport->ops = ops; | 138 | vport->ops = ops; |
| 140 | INIT_HLIST_NODE(&vport->dp_hash_node); | 139 | INIT_HLIST_NODE(&vport->dp_hash_node); |
| 141 | 140 | ||
| 142 | vport->percpu_stats = alloc_percpu(struct pcpu_sw_netstats); | 141 | vport->percpu_stats = netdev_alloc_pcpu_stats(struct pcpu_sw_netstats); |
| 143 | if (!vport->percpu_stats) { | 142 | if (!vport->percpu_stats) { |
| 144 | kfree(vport); | 143 | kfree(vport); |
| 145 | return ERR_PTR(-ENOMEM); | 144 | return ERR_PTR(-ENOMEM); |
| 146 | } | 145 | } |
| 147 | 146 | ||
| 148 | for_each_possible_cpu(i) { | ||
| 149 | struct pcpu_sw_netstats *vport_stats; | ||
| 150 | vport_stats = per_cpu_ptr(vport->percpu_stats, i); | ||
| 151 | u64_stats_init(&vport_stats->syncp); | ||
| 152 | } | ||
| 153 | |||
| 154 | |||
| 155 | spin_lock_init(&vport->stats_lock); | 147 | spin_lock_init(&vport->stats_lock); |
| 156 | 148 | ||
| 157 | return vport; | 149 | return vport; |
| @@ -285,9 +277,9 @@ void ovs_vport_get_stats(struct vport *vport, struct ovs_vport_stats *stats) | |||
| 285 | percpu_stats = per_cpu_ptr(vport->percpu_stats, i); | 277 | percpu_stats = per_cpu_ptr(vport->percpu_stats, i); |
| 286 | 278 | ||
| 287 | do { | 279 | do { |
| 288 | start = u64_stats_fetch_begin_bh(&percpu_stats->syncp); | 280 | start = u64_stats_fetch_begin_irq(&percpu_stats->syncp); |
| 289 | local_stats = *percpu_stats; | 281 | local_stats = *percpu_stats; |
| 290 | } while (u64_stats_fetch_retry_bh(&percpu_stats->syncp, start)); | 282 | } while (u64_stats_fetch_retry_irq(&percpu_stats->syncp, start)); |
| 291 | 283 | ||
| 292 | stats->rx_bytes += local_stats.rx_bytes; | 284 | stats->rx_bytes += local_stats.rx_bytes; |
| 293 | stats->rx_packets += local_stats.rx_packets; | 285 | stats->rx_packets += local_stats.rx_packets; |
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c index 48a6a93db296..b85c67ccb797 100644 --- a/net/packet/af_packet.c +++ b/net/packet/af_packet.c | |||
| @@ -243,40 +243,41 @@ static int packet_direct_xmit(struct sk_buff *skb) | |||
| 243 | const struct net_device_ops *ops = dev->netdev_ops; | 243 | const struct net_device_ops *ops = dev->netdev_ops; |
| 244 | netdev_features_t features; | 244 | netdev_features_t features; |
| 245 | struct netdev_queue *txq; | 245 | struct netdev_queue *txq; |
| 246 | int ret = NETDEV_TX_BUSY; | ||
| 246 | u16 queue_map; | 247 | u16 queue_map; |
| 247 | int ret; | ||
| 248 | 248 | ||
| 249 | if (unlikely(!netif_running(dev) || | 249 | if (unlikely(!netif_running(dev) || |
| 250 | !netif_carrier_ok(dev))) { | 250 | !netif_carrier_ok(dev))) |
| 251 | kfree_skb(skb); | 251 | goto drop; |
| 252 | return NET_XMIT_DROP; | ||
| 253 | } | ||
| 254 | 252 | ||
| 255 | features = netif_skb_features(skb); | 253 | features = netif_skb_features(skb); |
| 256 | if (skb_needs_linearize(skb, features) && | 254 | if (skb_needs_linearize(skb, features) && |
| 257 | __skb_linearize(skb)) { | 255 | __skb_linearize(skb)) |
| 258 | kfree_skb(skb); | 256 | goto drop; |
| 259 | return NET_XMIT_DROP; | ||
| 260 | } | ||
| 261 | 257 | ||
| 262 | queue_map = skb_get_queue_mapping(skb); | 258 | queue_map = skb_get_queue_mapping(skb); |
| 263 | txq = netdev_get_tx_queue(dev, queue_map); | 259 | txq = netdev_get_tx_queue(dev, queue_map); |
| 264 | 260 | ||
| 265 | __netif_tx_lock_bh(txq); | 261 | local_bh_disable(); |
| 266 | if (unlikely(netif_xmit_frozen_or_stopped(txq))) { | 262 | |
| 267 | ret = NETDEV_TX_BUSY; | 263 | HARD_TX_LOCK(dev, txq, smp_processor_id()); |
| 268 | kfree_skb(skb); | 264 | if (!netif_xmit_frozen_or_drv_stopped(txq)) { |
| 269 | goto out; | 265 | ret = ops->ndo_start_xmit(skb, dev); |
| 266 | if (ret == NETDEV_TX_OK) | ||
| 267 | txq_trans_update(txq); | ||
| 270 | } | 268 | } |
| 269 | HARD_TX_UNLOCK(dev, txq); | ||
| 271 | 270 | ||
| 272 | ret = ops->ndo_start_xmit(skb, dev); | 271 | local_bh_enable(); |
| 273 | if (likely(dev_xmit_complete(ret))) | 272 | |
| 274 | txq_trans_update(txq); | 273 | if (!dev_xmit_complete(ret)) |
| 275 | else | ||
| 276 | kfree_skb(skb); | 274 | kfree_skb(skb); |
| 277 | out: | 275 | |
| 278 | __netif_tx_unlock_bh(txq); | ||
| 279 | return ret; | 276 | return ret; |
| 277 | drop: | ||
| 278 | atomic_long_inc(&dev->tx_dropped); | ||
| 279 | kfree_skb(skb); | ||
| 280 | return NET_XMIT_DROP; | ||
| 280 | } | 281 | } |
| 281 | 282 | ||
| 282 | static struct net_device *packet_cached_dev_get(struct packet_sock *po) | 283 | static struct net_device *packet_cached_dev_get(struct packet_sock *po) |
| @@ -1277,7 +1278,7 @@ static unsigned int fanout_demux_hash(struct packet_fanout *f, | |||
| 1277 | struct sk_buff *skb, | 1278 | struct sk_buff *skb, |
| 1278 | unsigned int num) | 1279 | unsigned int num) |
| 1279 | { | 1280 | { |
| 1280 | return reciprocal_scale(skb->rxhash, num); | 1281 | return reciprocal_scale(skb_get_hash(skb), num); |
| 1281 | } | 1282 | } |
| 1282 | 1283 | ||
| 1283 | static unsigned int fanout_demux_lb(struct packet_fanout *f, | 1284 | static unsigned int fanout_demux_lb(struct packet_fanout *f, |
| @@ -1362,7 +1363,6 @@ static int packet_rcv_fanout(struct sk_buff *skb, struct net_device *dev, | |||
| 1362 | if (!skb) | 1363 | if (!skb) |
| 1363 | return 0; | 1364 | return 0; |
| 1364 | } | 1365 | } |
| 1365 | skb_get_hash(skb); | ||
| 1366 | idx = fanout_demux_hash(f, skb, num); | 1366 | idx = fanout_demux_hash(f, skb, num); |
| 1367 | break; | 1367 | break; |
| 1368 | case PACKET_FANOUT_LB: | 1368 | case PACKET_FANOUT_LB: |
| @@ -1848,7 +1848,7 @@ static int packet_rcv(struct sk_buff *skb, struct net_device *dev, | |||
| 1848 | skb->dropcount = atomic_read(&sk->sk_drops); | 1848 | skb->dropcount = atomic_read(&sk->sk_drops); |
| 1849 | __skb_queue_tail(&sk->sk_receive_queue, skb); | 1849 | __skb_queue_tail(&sk->sk_receive_queue, skb); |
| 1850 | spin_unlock(&sk->sk_receive_queue.lock); | 1850 | spin_unlock(&sk->sk_receive_queue.lock); |
| 1851 | sk->sk_data_ready(sk, skb->len); | 1851 | sk->sk_data_ready(sk); |
| 1852 | return 0; | 1852 | return 0; |
| 1853 | 1853 | ||
| 1854 | drop_n_acct: | 1854 | drop_n_acct: |
| @@ -2054,7 +2054,7 @@ static int tpacket_rcv(struct sk_buff *skb, struct net_device *dev, | |||
| 2054 | else | 2054 | else |
| 2055 | prb_clear_blk_fill_status(&po->rx_ring); | 2055 | prb_clear_blk_fill_status(&po->rx_ring); |
| 2056 | 2056 | ||
| 2057 | sk->sk_data_ready(sk, 0); | 2057 | sk->sk_data_ready(sk); |
| 2058 | 2058 | ||
| 2059 | drop_n_restore: | 2059 | drop_n_restore: |
| 2060 | if (skb_head != skb->data && skb_shared(skb)) { | 2060 | if (skb_head != skb->data && skb_shared(skb)) { |
| @@ -2069,7 +2069,7 @@ ring_is_full: | |||
| 2069 | po->stats.stats1.tp_drops++; | 2069 | po->stats.stats1.tp_drops++; |
| 2070 | spin_unlock(&sk->sk_receive_queue.lock); | 2070 | spin_unlock(&sk->sk_receive_queue.lock); |
| 2071 | 2071 | ||
| 2072 | sk->sk_data_ready(sk, 0); | 2072 | sk->sk_data_ready(sk); |
| 2073 | kfree_skb(copy_skb); | 2073 | kfree_skb(copy_skb); |
| 2074 | goto drop_n_restore; | 2074 | goto drop_n_restore; |
| 2075 | } | 2075 | } |
| @@ -2257,8 +2257,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) | |||
| 2257 | if (unlikely(!(dev->flags & IFF_UP))) | 2257 | if (unlikely(!(dev->flags & IFF_UP))) |
| 2258 | goto out_put; | 2258 | goto out_put; |
| 2259 | 2259 | ||
| 2260 | reserve = dev->hard_header_len; | 2260 | reserve = dev->hard_header_len + VLAN_HLEN; |
| 2261 | |||
| 2262 | size_max = po->tx_ring.frame_size | 2261 | size_max = po->tx_ring.frame_size |
| 2263 | - (po->tp_hdrlen - sizeof(struct sockaddr_ll)); | 2262 | - (po->tp_hdrlen - sizeof(struct sockaddr_ll)); |
| 2264 | 2263 | ||
| @@ -2285,8 +2284,19 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg) | |||
| 2285 | goto out_status; | 2284 | goto out_status; |
| 2286 | 2285 | ||
| 2287 | tp_len = tpacket_fill_skb(po, skb, ph, dev, size_max, proto, | 2286 | tp_len = tpacket_fill_skb(po, skb, ph, dev, size_max, proto, |
| 2288 | addr, hlen); | 2287 | addr, hlen); |
| 2288 | if (tp_len > dev->mtu + dev->hard_header_len) { | ||
| 2289 | struct ethhdr *ehdr; | ||
| 2290 | /* Earlier code assumed this would be a VLAN pkt, | ||
| 2291 | * double-check this now that we have the actual | ||
| 2292 | * packet in hand. | ||
| 2293 | */ | ||
| 2289 | 2294 | ||
| 2295 | skb_reset_mac_header(skb); | ||
| 2296 | ehdr = eth_hdr(skb); | ||
| 2297 | if (ehdr->h_proto != htons(ETH_P_8021Q)) | ||
| 2298 | tp_len = -EMSGSIZE; | ||
| 2299 | } | ||
| 2290 | if (unlikely(tp_len < 0)) { | 2300 | if (unlikely(tp_len < 0)) { |
| 2291 | if (po->tp_loss) { | 2301 | if (po->tp_loss) { |
| 2292 | __packet_set_status(po, ph, | 2302 | __packet_set_status(po, ph, |
diff --git a/net/phonet/pep-gprs.c b/net/phonet/pep-gprs.c index a2fba7edfd1f..66dc65e7c6a1 100644 --- a/net/phonet/pep-gprs.c +++ b/net/phonet/pep-gprs.c | |||
| @@ -37,7 +37,7 @@ | |||
| 37 | struct gprs_dev { | 37 | struct gprs_dev { |
| 38 | struct sock *sk; | 38 | struct sock *sk; |
| 39 | void (*old_state_change)(struct sock *); | 39 | void (*old_state_change)(struct sock *); |
| 40 | void (*old_data_ready)(struct sock *, int); | 40 | void (*old_data_ready)(struct sock *); |
| 41 | void (*old_write_space)(struct sock *); | 41 | void (*old_write_space)(struct sock *); |
| 42 | 42 | ||
| 43 | struct net_device *dev; | 43 | struct net_device *dev; |
| @@ -146,7 +146,7 @@ drop: | |||
| 146 | return err; | 146 | return err; |
| 147 | } | 147 | } |
| 148 | 148 | ||
| 149 | static void gprs_data_ready(struct sock *sk, int len) | 149 | static void gprs_data_ready(struct sock *sk) |
| 150 | { | 150 | { |
| 151 | struct gprs_dev *gp = sk->sk_user_data; | 151 | struct gprs_dev *gp = sk->sk_user_data; |
| 152 | struct sk_buff *skb; | 152 | struct sk_buff *skb; |
diff --git a/net/phonet/pep.c b/net/phonet/pep.c index e77411735de8..70a547ea5177 100644 --- a/net/phonet/pep.c +++ b/net/phonet/pep.c | |||
| @@ -462,10 +462,9 @@ out: | |||
| 462 | queue: | 462 | queue: |
| 463 | skb->dev = NULL; | 463 | skb->dev = NULL; |
| 464 | skb_set_owner_r(skb, sk); | 464 | skb_set_owner_r(skb, sk); |
| 465 | err = skb->len; | ||
| 466 | skb_queue_tail(queue, skb); | 465 | skb_queue_tail(queue, skb); |
| 467 | if (!sock_flag(sk, SOCK_DEAD)) | 466 | if (!sock_flag(sk, SOCK_DEAD)) |
| 468 | sk->sk_data_ready(sk, err); | 467 | sk->sk_data_ready(sk); |
| 469 | return NET_RX_SUCCESS; | 468 | return NET_RX_SUCCESS; |
| 470 | } | 469 | } |
| 471 | 470 | ||
| @@ -587,10 +586,9 @@ static int pipe_handler_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
| 587 | pn->rx_credits--; | 586 | pn->rx_credits--; |
| 588 | skb->dev = NULL; | 587 | skb->dev = NULL; |
| 589 | skb_set_owner_r(skb, sk); | 588 | skb_set_owner_r(skb, sk); |
| 590 | err = skb->len; | ||
| 591 | skb_queue_tail(&sk->sk_receive_queue, skb); | 589 | skb_queue_tail(&sk->sk_receive_queue, skb); |
| 592 | if (!sock_flag(sk, SOCK_DEAD)) | 590 | if (!sock_flag(sk, SOCK_DEAD)) |
| 593 | sk->sk_data_ready(sk, err); | 591 | sk->sk_data_ready(sk); |
| 594 | return NET_RX_SUCCESS; | 592 | return NET_RX_SUCCESS; |
| 595 | 593 | ||
| 596 | case PNS_PEP_CONNECT_RESP: | 594 | case PNS_PEP_CONNECT_RESP: |
| @@ -698,7 +696,7 @@ static int pep_do_rcv(struct sock *sk, struct sk_buff *skb) | |||
| 698 | skb_queue_head(&sk->sk_receive_queue, skb); | 696 | skb_queue_head(&sk->sk_receive_queue, skb); |
| 699 | sk_acceptq_added(sk); | 697 | sk_acceptq_added(sk); |
| 700 | if (!sock_flag(sk, SOCK_DEAD)) | 698 | if (!sock_flag(sk, SOCK_DEAD)) |
| 701 | sk->sk_data_ready(sk, 0); | 699 | sk->sk_data_ready(sk); |
| 702 | return NET_RX_SUCCESS; | 700 | return NET_RX_SUCCESS; |
| 703 | 701 | ||
| 704 | case PNS_PEP_DISCONNECT_REQ: | 702 | case PNS_PEP_DISCONNECT_REQ: |
diff --git a/net/rds/iw.c b/net/rds/iw.c index 7826d46baa70..589935661d66 100644 --- a/net/rds/iw.c +++ b/net/rds/iw.c | |||
| @@ -239,7 +239,8 @@ static int rds_iw_laddr_check(__be32 addr) | |||
| 239 | ret = rdma_bind_addr(cm_id, (struct sockaddr *)&sin); | 239 | ret = rdma_bind_addr(cm_id, (struct sockaddr *)&sin); |
| 240 | /* due to this, we will claim to support IB devices unless we | 240 | /* due to this, we will claim to support IB devices unless we |
| 241 | check node_type. */ | 241 | check node_type. */ |
| 242 | if (ret || cm_id->device->node_type != RDMA_NODE_RNIC) | 242 | if (ret || !cm_id->device || |
| 243 | cm_id->device->node_type != RDMA_NODE_RNIC) | ||
| 243 | ret = -EADDRNOTAVAIL; | 244 | ret = -EADDRNOTAVAIL; |
| 244 | 245 | ||
| 245 | rdsdebug("addr %pI4 ret %d node type %d\n", | 246 | rdsdebug("addr %pI4 ret %d node type %d\n", |
diff --git a/net/rds/tcp.h b/net/rds/tcp.h index 9cf2927d0021..65637491f728 100644 --- a/net/rds/tcp.h +++ b/net/rds/tcp.h | |||
| @@ -61,12 +61,12 @@ void rds_tcp_state_change(struct sock *sk); | |||
| 61 | /* tcp_listen.c */ | 61 | /* tcp_listen.c */ |
| 62 | int rds_tcp_listen_init(void); | 62 | int rds_tcp_listen_init(void); |
| 63 | void rds_tcp_listen_stop(void); | 63 | void rds_tcp_listen_stop(void); |
| 64 | void rds_tcp_listen_data_ready(struct sock *sk, int bytes); | 64 | void rds_tcp_listen_data_ready(struct sock *sk); |
| 65 | 65 | ||
| 66 | /* tcp_recv.c */ | 66 | /* tcp_recv.c */ |
| 67 | int rds_tcp_recv_init(void); | 67 | int rds_tcp_recv_init(void); |
| 68 | void rds_tcp_recv_exit(void); | 68 | void rds_tcp_recv_exit(void); |
| 69 | void rds_tcp_data_ready(struct sock *sk, int bytes); | 69 | void rds_tcp_data_ready(struct sock *sk); |
| 70 | int rds_tcp_recv(struct rds_connection *conn); | 70 | int rds_tcp_recv(struct rds_connection *conn); |
| 71 | void rds_tcp_inc_free(struct rds_incoming *inc); | 71 | void rds_tcp_inc_free(struct rds_incoming *inc); |
| 72 | int rds_tcp_inc_copy_to_user(struct rds_incoming *inc, struct iovec *iov, | 72 | int rds_tcp_inc_copy_to_user(struct rds_incoming *inc, struct iovec *iov, |
diff --git a/net/rds/tcp_listen.c b/net/rds/tcp_listen.c index 7787537e9c2e..4e638f851185 100644 --- a/net/rds/tcp_listen.c +++ b/net/rds/tcp_listen.c | |||
| @@ -108,9 +108,9 @@ static void rds_tcp_accept_worker(struct work_struct *work) | |||
| 108 | cond_resched(); | 108 | cond_resched(); |
| 109 | } | 109 | } |
| 110 | 110 | ||
| 111 | void rds_tcp_listen_data_ready(struct sock *sk, int bytes) | 111 | void rds_tcp_listen_data_ready(struct sock *sk) |
| 112 | { | 112 | { |
| 113 | void (*ready)(struct sock *sk, int bytes); | 113 | void (*ready)(struct sock *sk); |
| 114 | 114 | ||
| 115 | rdsdebug("listen data ready sk %p\n", sk); | 115 | rdsdebug("listen data ready sk %p\n", sk); |
| 116 | 116 | ||
| @@ -132,7 +132,7 @@ void rds_tcp_listen_data_ready(struct sock *sk, int bytes) | |||
| 132 | 132 | ||
| 133 | out: | 133 | out: |
| 134 | read_unlock(&sk->sk_callback_lock); | 134 | read_unlock(&sk->sk_callback_lock); |
| 135 | ready(sk, bytes); | 135 | ready(sk); |
| 136 | } | 136 | } |
| 137 | 137 | ||
| 138 | int rds_tcp_listen_init(void) | 138 | int rds_tcp_listen_init(void) |
diff --git a/net/rds/tcp_recv.c b/net/rds/tcp_recv.c index 4fac4f2bb9dc..9ae6e0a264ec 100644 --- a/net/rds/tcp_recv.c +++ b/net/rds/tcp_recv.c | |||
| @@ -314,13 +314,13 @@ int rds_tcp_recv(struct rds_connection *conn) | |||
| 314 | return ret; | 314 | return ret; |
| 315 | } | 315 | } |
| 316 | 316 | ||
| 317 | void rds_tcp_data_ready(struct sock *sk, int bytes) | 317 | void rds_tcp_data_ready(struct sock *sk) |
| 318 | { | 318 | { |
| 319 | void (*ready)(struct sock *sk, int bytes); | 319 | void (*ready)(struct sock *sk); |
| 320 | struct rds_connection *conn; | 320 | struct rds_connection *conn; |
| 321 | struct rds_tcp_connection *tc; | 321 | struct rds_tcp_connection *tc; |
| 322 | 322 | ||
| 323 | rdsdebug("data ready sk %p bytes %d\n", sk, bytes); | 323 | rdsdebug("data ready sk %p\n", sk); |
| 324 | 324 | ||
| 325 | read_lock(&sk->sk_callback_lock); | 325 | read_lock(&sk->sk_callback_lock); |
| 326 | conn = sk->sk_user_data; | 326 | conn = sk->sk_user_data; |
| @@ -337,7 +337,7 @@ void rds_tcp_data_ready(struct sock *sk, int bytes) | |||
| 337 | queue_delayed_work(rds_wq, &conn->c_recv_w, 0); | 337 | queue_delayed_work(rds_wq, &conn->c_recv_w, 0); |
| 338 | out: | 338 | out: |
| 339 | read_unlock(&sk->sk_callback_lock); | 339 | read_unlock(&sk->sk_callback_lock); |
| 340 | ready(sk, bytes); | 340 | ready(sk); |
| 341 | } | 341 | } |
| 342 | 342 | ||
| 343 | int rds_tcp_recv_init(void) | 343 | int rds_tcp_recv_init(void) |
diff --git a/net/rfkill/core.c b/net/rfkill/core.c index ed7e0b4e7f90..b3b16c070a7f 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c | |||
| @@ -789,7 +789,8 @@ void rfkill_resume_polling(struct rfkill *rfkill) | |||
| 789 | if (!rfkill->ops->poll) | 789 | if (!rfkill->ops->poll) |
| 790 | return; | 790 | return; |
| 791 | 791 | ||
| 792 | schedule_work(&rfkill->poll_work.work); | 792 | queue_delayed_work(system_power_efficient_wq, |
| 793 | &rfkill->poll_work, 0); | ||
| 793 | } | 794 | } |
| 794 | EXPORT_SYMBOL(rfkill_resume_polling); | 795 | EXPORT_SYMBOL(rfkill_resume_polling); |
| 795 | 796 | ||
| @@ -894,7 +895,8 @@ static void rfkill_poll(struct work_struct *work) | |||
| 894 | */ | 895 | */ |
| 895 | rfkill->ops->poll(rfkill, rfkill->data); | 896 | rfkill->ops->poll(rfkill, rfkill->data); |
| 896 | 897 | ||
| 897 | schedule_delayed_work(&rfkill->poll_work, | 898 | queue_delayed_work(system_power_efficient_wq, |
| 899 | &rfkill->poll_work, | ||
| 898 | round_jiffies_relative(POLL_INTERVAL)); | 900 | round_jiffies_relative(POLL_INTERVAL)); |
| 899 | } | 901 | } |
| 900 | 902 | ||
| @@ -958,7 +960,8 @@ int __must_check rfkill_register(struct rfkill *rfkill) | |||
| 958 | INIT_WORK(&rfkill->sync_work, rfkill_sync_work); | 960 | INIT_WORK(&rfkill->sync_work, rfkill_sync_work); |
| 959 | 961 | ||
| 960 | if (rfkill->ops->poll) | 962 | if (rfkill->ops->poll) |
| 961 | schedule_delayed_work(&rfkill->poll_work, | 963 | queue_delayed_work(system_power_efficient_wq, |
| 964 | &rfkill->poll_work, | ||
| 962 | round_jiffies_relative(POLL_INTERVAL)); | 965 | round_jiffies_relative(POLL_INTERVAL)); |
| 963 | 966 | ||
| 964 | if (!rfkill->persistent || rfkill_epo_lock_active) { | 967 | if (!rfkill->persistent || rfkill_epo_lock_active) { |
diff --git a/net/rose/af_rose.c b/net/rose/af_rose.c index c2cca2ee6aef..8451c8cdc9de 100644 --- a/net/rose/af_rose.c +++ b/net/rose/af_rose.c | |||
| @@ -1041,7 +1041,7 @@ int rose_rx_call_request(struct sk_buff *skb, struct net_device *dev, struct ros | |||
| 1041 | rose_start_heartbeat(make); | 1041 | rose_start_heartbeat(make); |
| 1042 | 1042 | ||
| 1043 | if (!sock_flag(sk, SOCK_DEAD)) | 1043 | if (!sock_flag(sk, SOCK_DEAD)) |
| 1044 | sk->sk_data_ready(sk, skb->len); | 1044 | sk->sk_data_ready(sk); |
| 1045 | 1045 | ||
| 1046 | return 1; | 1046 | return 1; |
| 1047 | } | 1047 | } |
diff --git a/net/rxrpc/Makefile b/net/rxrpc/Makefile index d1c3429b69ed..ec126f91276b 100644 --- a/net/rxrpc/Makefile +++ b/net/rxrpc/Makefile | |||
| @@ -20,9 +20,8 @@ af-rxrpc-y := \ | |||
| 20 | ar-skbuff.o \ | 20 | ar-skbuff.o \ |
| 21 | ar-transport.o | 21 | ar-transport.o |
| 22 | 22 | ||
| 23 | ifeq ($(CONFIG_PROC_FS),y) | 23 | af-rxrpc-$(CONFIG_PROC_FS) += ar-proc.o |
| 24 | af-rxrpc-y += ar-proc.o | 24 | af-rxrpc-$(CONFIG_SYSCTL) += sysctl.o |
| 25 | endif | ||
| 26 | 25 | ||
| 27 | obj-$(CONFIG_AF_RXRPC) += af-rxrpc.o | 26 | obj-$(CONFIG_AF_RXRPC) += af-rxrpc.o |
| 28 | 27 | ||
diff --git a/net/rxrpc/af_rxrpc.c b/net/rxrpc/af_rxrpc.c index e61aa6001c65..7b1670489638 100644 --- a/net/rxrpc/af_rxrpc.c +++ b/net/rxrpc/af_rxrpc.c | |||
| @@ -838,6 +838,12 @@ static int __init af_rxrpc_init(void) | |||
| 838 | goto error_key_type_s; | 838 | goto error_key_type_s; |
| 839 | } | 839 | } |
| 840 | 840 | ||
| 841 | ret = rxrpc_sysctl_init(); | ||
| 842 | if (ret < 0) { | ||
| 843 | printk(KERN_CRIT "RxRPC: Cannot register sysctls\n"); | ||
| 844 | goto error_sysctls; | ||
| 845 | } | ||
| 846 | |||
| 841 | #ifdef CONFIG_PROC_FS | 847 | #ifdef CONFIG_PROC_FS |
| 842 | proc_create("rxrpc_calls", 0, init_net.proc_net, &rxrpc_call_seq_fops); | 848 | proc_create("rxrpc_calls", 0, init_net.proc_net, &rxrpc_call_seq_fops); |
| 843 | proc_create("rxrpc_conns", 0, init_net.proc_net, | 849 | proc_create("rxrpc_conns", 0, init_net.proc_net, |
| @@ -845,6 +851,8 @@ static int __init af_rxrpc_init(void) | |||
| 845 | #endif | 851 | #endif |
| 846 | return 0; | 852 | return 0; |
| 847 | 853 | ||
| 854 | error_sysctls: | ||
| 855 | unregister_key_type(&key_type_rxrpc_s); | ||
| 848 | error_key_type_s: | 856 | error_key_type_s: |
| 849 | unregister_key_type(&key_type_rxrpc); | 857 | unregister_key_type(&key_type_rxrpc); |
| 850 | error_key_type: | 858 | error_key_type: |
| @@ -865,6 +873,7 @@ error_call_jar: | |||
| 865 | static void __exit af_rxrpc_exit(void) | 873 | static void __exit af_rxrpc_exit(void) |
| 866 | { | 874 | { |
| 867 | _enter(""); | 875 | _enter(""); |
| 876 | rxrpc_sysctl_exit(); | ||
| 868 | unregister_key_type(&key_type_rxrpc_s); | 877 | unregister_key_type(&key_type_rxrpc_s); |
| 869 | unregister_key_type(&key_type_rxrpc); | 878 | unregister_key_type(&key_type_rxrpc); |
| 870 | sock_unregister(PF_RXRPC); | 879 | sock_unregister(PF_RXRPC); |
diff --git a/net/rxrpc/ar-ack.c b/net/rxrpc/ar-ack.c index cd97a0ce48d8..c6be17a959a6 100644 --- a/net/rxrpc/ar-ack.c +++ b/net/rxrpc/ar-ack.c | |||
| @@ -19,7 +19,49 @@ | |||
| 19 | #include <net/af_rxrpc.h> | 19 | #include <net/af_rxrpc.h> |
| 20 | #include "ar-internal.h" | 20 | #include "ar-internal.h" |
| 21 | 21 | ||
| 22 | static unsigned int rxrpc_ack_defer = 1; | 22 | /* |
| 23 | * How long to wait before scheduling ACK generation after seeing a | ||
| 24 | * packet with RXRPC_REQUEST_ACK set (in jiffies). | ||
| 25 | */ | ||
| 26 | unsigned rxrpc_requested_ack_delay = 1; | ||
| 27 | |||
| 28 | /* | ||
| 29 | * How long to wait before scheduling an ACK with subtype DELAY (in jiffies). | ||
| 30 | * | ||
| 31 | * We use this when we've received new data packets. If those packets aren't | ||
| 32 | * all consumed within this time we will send a DELAY ACK if an ACK was not | ||
| 33 | * requested to let the sender know it doesn't need to resend. | ||
| 34 | */ | ||
| 35 | unsigned rxrpc_soft_ack_delay = 1 * HZ; | ||
| 36 | |||
| 37 | /* | ||
| 38 | * How long to wait before scheduling an ACK with subtype IDLE (in jiffies). | ||
| 39 | * | ||
| 40 | * We use this when we've consumed some previously soft-ACK'd packets when | ||
| 41 | * further packets aren't immediately received to decide when to send an IDLE | ||
| 42 | * ACK let the other end know that it can free up its Tx buffer space. | ||
| 43 | */ | ||
| 44 | unsigned rxrpc_idle_ack_delay = 0.5 * HZ; | ||
| 45 | |||
| 46 | /* | ||
| 47 | * Receive window size in packets. This indicates the maximum number of | ||
| 48 | * unconsumed received packets we're willing to retain in memory. Once this | ||
| 49 | * limit is hit, we should generate an EXCEEDS_WINDOW ACK and discard further | ||
| 50 | * packets. | ||
| 51 | */ | ||
| 52 | unsigned rxrpc_rx_window_size = 32; | ||
| 53 | |||
| 54 | /* | ||
| 55 | * Maximum Rx MTU size. This indicates to the sender the size of jumbo packet | ||
| 56 | * made by gluing normal packets together that we're willing to handle. | ||
| 57 | */ | ||
| 58 | unsigned rxrpc_rx_mtu = 5692; | ||
| 59 | |||
| 60 | /* | ||
| 61 | * The maximum number of fragments in a received jumbo packet that we tell the | ||
| 62 | * sender that we're willing to handle. | ||
| 63 | */ | ||
| 64 | unsigned rxrpc_rx_jumbo_max = 4; | ||
| 23 | 65 | ||
| 24 | static const char *rxrpc_acks(u8 reason) | 66 | static const char *rxrpc_acks(u8 reason) |
| 25 | { | 67 | { |
| @@ -82,24 +124,23 @@ void __rxrpc_propose_ACK(struct rxrpc_call *call, u8 ack_reason, | |||
| 82 | switch (ack_reason) { | 124 | switch (ack_reason) { |
| 83 | case RXRPC_ACK_DELAY: | 125 | case RXRPC_ACK_DELAY: |
| 84 | _debug("run delay timer"); | 126 | _debug("run delay timer"); |
| 85 | call->ack_timer.expires = jiffies + rxrpc_ack_timeout * HZ; | 127 | expiry = rxrpc_soft_ack_delay; |
| 86 | add_timer(&call->ack_timer); | 128 | goto run_timer; |
| 87 | return; | ||
| 88 | 129 | ||
| 89 | case RXRPC_ACK_IDLE: | 130 | case RXRPC_ACK_IDLE: |
| 90 | if (!immediate) { | 131 | if (!immediate) { |
| 91 | _debug("run defer timer"); | 132 | _debug("run defer timer"); |
| 92 | expiry = 1; | 133 | expiry = rxrpc_idle_ack_delay; |
| 93 | goto run_timer; | 134 | goto run_timer; |
| 94 | } | 135 | } |
| 95 | goto cancel_timer; | 136 | goto cancel_timer; |
| 96 | 137 | ||
| 97 | case RXRPC_ACK_REQUESTED: | 138 | case RXRPC_ACK_REQUESTED: |
| 98 | if (!rxrpc_ack_defer) | 139 | expiry = rxrpc_requested_ack_delay; |
| 140 | if (!expiry) | ||
| 99 | goto cancel_timer; | 141 | goto cancel_timer; |
| 100 | if (!immediate || serial == cpu_to_be32(1)) { | 142 | if (!immediate || serial == cpu_to_be32(1)) { |
| 101 | _debug("run defer timer"); | 143 | _debug("run defer timer"); |
| 102 | expiry = rxrpc_ack_defer; | ||
| 103 | goto run_timer; | 144 | goto run_timer; |
| 104 | } | 145 | } |
| 105 | 146 | ||
| @@ -1174,11 +1215,11 @@ send_ACK: | |||
| 1174 | mtu = call->conn->trans->peer->if_mtu; | 1215 | mtu = call->conn->trans->peer->if_mtu; |
| 1175 | mtu -= call->conn->trans->peer->hdrsize; | 1216 | mtu -= call->conn->trans->peer->hdrsize; |
| 1176 | ackinfo.maxMTU = htonl(mtu); | 1217 | ackinfo.maxMTU = htonl(mtu); |
| 1177 | ackinfo.rwind = htonl(32); | 1218 | ackinfo.rwind = htonl(rxrpc_rx_window_size); |
| 1178 | 1219 | ||
| 1179 | /* permit the peer to send us jumbo packets if it wants to */ | 1220 | /* permit the peer to send us jumbo packets if it wants to */ |
| 1180 | ackinfo.rxMTU = htonl(5692); | 1221 | ackinfo.rxMTU = htonl(rxrpc_rx_mtu); |
| 1181 | ackinfo.jumbo_max = htonl(4); | 1222 | ackinfo.jumbo_max = htonl(rxrpc_rx_jumbo_max); |
| 1182 | 1223 | ||
| 1183 | hdr.serial = htonl(atomic_inc_return(&call->conn->serial)); | 1224 | hdr.serial = htonl(atomic_inc_return(&call->conn->serial)); |
| 1184 | _proto("Tx ACK %%%u { m=%hu f=#%u p=#%u s=%%%u r=%s n=%u }", | 1225 | _proto("Tx ACK %%%u { m=%hu f=#%u p=#%u s=%%%u r=%s n=%u }", |
diff --git a/net/rxrpc/ar-call.c b/net/rxrpc/ar-call.c index a3bbb360a3f9..a9e05db0f5d5 100644 --- a/net/rxrpc/ar-call.c +++ b/net/rxrpc/ar-call.c | |||
| @@ -12,10 +12,22 @@ | |||
| 12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
| 13 | #include <linux/module.h> | 13 | #include <linux/module.h> |
| 14 | #include <linux/circ_buf.h> | 14 | #include <linux/circ_buf.h> |
| 15 | #include <linux/hashtable.h> | ||
| 16 | #include <linux/spinlock_types.h> | ||
| 15 | #include <net/sock.h> | 17 | #include <net/sock.h> |
| 16 | #include <net/af_rxrpc.h> | 18 | #include <net/af_rxrpc.h> |
| 17 | #include "ar-internal.h" | 19 | #include "ar-internal.h" |
| 18 | 20 | ||
| 21 | /* | ||
| 22 | * Maximum lifetime of a call (in jiffies). | ||
| 23 | */ | ||
| 24 | unsigned rxrpc_max_call_lifetime = 60 * HZ; | ||
| 25 | |||
| 26 | /* | ||
| 27 | * Time till dead call expires after last use (in jiffies). | ||
| 28 | */ | ||
| 29 | unsigned rxrpc_dead_call_expiry = 2 * HZ; | ||
| 30 | |||
| 19 | const char *const rxrpc_call_states[] = { | 31 | const char *const rxrpc_call_states[] = { |
| 20 | [RXRPC_CALL_CLIENT_SEND_REQUEST] = "ClSndReq", | 32 | [RXRPC_CALL_CLIENT_SEND_REQUEST] = "ClSndReq", |
| 21 | [RXRPC_CALL_CLIENT_AWAIT_REPLY] = "ClAwtRpl", | 33 | [RXRPC_CALL_CLIENT_AWAIT_REPLY] = "ClAwtRpl", |
| @@ -38,8 +50,6 @@ const char *const rxrpc_call_states[] = { | |||
| 38 | struct kmem_cache *rxrpc_call_jar; | 50 | struct kmem_cache *rxrpc_call_jar; |
| 39 | LIST_HEAD(rxrpc_calls); | 51 | LIST_HEAD(rxrpc_calls); |
| 40 | DEFINE_RWLOCK(rxrpc_call_lock); | 52 | DEFINE_RWLOCK(rxrpc_call_lock); |
| 41 | static unsigned int rxrpc_call_max_lifetime = 60; | ||
| 42 | static unsigned int rxrpc_dead_call_timeout = 2; | ||
| 43 | 53 | ||
| 44 | static void rxrpc_destroy_call(struct work_struct *work); | 54 | static void rxrpc_destroy_call(struct work_struct *work); |
| 45 | static void rxrpc_call_life_expired(unsigned long _call); | 55 | static void rxrpc_call_life_expired(unsigned long _call); |
| @@ -47,6 +57,145 @@ static void rxrpc_dead_call_expired(unsigned long _call); | |||
| 47 | static void rxrpc_ack_time_expired(unsigned long _call); | 57 | static void rxrpc_ack_time_expired(unsigned long _call); |
| 48 | static void rxrpc_resend_time_expired(unsigned long _call); | 58 | static void rxrpc_resend_time_expired(unsigned long _call); |
| 49 | 59 | ||
| 60 | static DEFINE_SPINLOCK(rxrpc_call_hash_lock); | ||
| 61 | static DEFINE_HASHTABLE(rxrpc_call_hash, 10); | ||
| 62 | |||
| 63 | /* | ||
| 64 | * Hash function for rxrpc_call_hash | ||
| 65 | */ | ||
| 66 | static unsigned long rxrpc_call_hashfunc( | ||
| 67 | u8 clientflag, | ||
| 68 | __be32 cid, | ||
| 69 | __be32 call_id, | ||
| 70 | __be32 epoch, | ||
| 71 | __be16 service_id, | ||
| 72 | sa_family_t proto, | ||
| 73 | void *localptr, | ||
| 74 | unsigned int addr_size, | ||
| 75 | const u8 *peer_addr) | ||
| 76 | { | ||
| 77 | const u16 *p; | ||
| 78 | unsigned int i; | ||
| 79 | unsigned long key; | ||
| 80 | u32 hcid = ntohl(cid); | ||
| 81 | |||
| 82 | _enter(""); | ||
| 83 | |||
| 84 | key = (unsigned long)localptr; | ||
| 85 | /* We just want to add up the __be32 values, so forcing the | ||
| 86 | * cast should be okay. | ||
| 87 | */ | ||
| 88 | key += (__force u32)epoch; | ||
| 89 | key += (__force u16)service_id; | ||
| 90 | key += (__force u32)call_id; | ||
| 91 | key += (hcid & RXRPC_CIDMASK) >> RXRPC_CIDSHIFT; | ||
| 92 | key += hcid & RXRPC_CHANNELMASK; | ||
| 93 | key += clientflag; | ||
| 94 | key += proto; | ||
| 95 | /* Step through the peer address in 16-bit portions for speed */ | ||
| 96 | for (i = 0, p = (const u16 *)peer_addr; i < addr_size >> 1; i++, p++) | ||
| 97 | key += *p; | ||
| 98 | _leave(" key = 0x%lx", key); | ||
| 99 | return key; | ||
| 100 | } | ||
| 101 | |||
| 102 | /* | ||
| 103 | * Add a call to the hashtable | ||
| 104 | */ | ||
| 105 | static void rxrpc_call_hash_add(struct rxrpc_call *call) | ||
| 106 | { | ||
| 107 | unsigned long key; | ||
| 108 | unsigned int addr_size = 0; | ||
| 109 | |||
| 110 | _enter(""); | ||
| 111 | switch (call->proto) { | ||
| 112 | case AF_INET: | ||
| 113 | addr_size = sizeof(call->peer_ip.ipv4_addr); | ||
| 114 | break; | ||
| 115 | case AF_INET6: | ||
| 116 | addr_size = sizeof(call->peer_ip.ipv6_addr); | ||
| 117 | break; | ||
| 118 | default: | ||
| 119 | break; | ||
| 120 | } | ||
| 121 | key = rxrpc_call_hashfunc(call->in_clientflag, call->cid, | ||
| 122 | call->call_id, call->epoch, | ||
| 123 | call->service_id, call->proto, | ||
| 124 | call->conn->trans->local, addr_size, | ||
| 125 | call->peer_ip.ipv6_addr); | ||
| 126 | /* Store the full key in the call */ | ||
| 127 | call->hash_key = key; | ||
| 128 | spin_lock(&rxrpc_call_hash_lock); | ||
| 129 | hash_add_rcu(rxrpc_call_hash, &call->hash_node, key); | ||
| 130 | spin_unlock(&rxrpc_call_hash_lock); | ||
| 131 | _leave(""); | ||
| 132 | } | ||
| 133 | |||
| 134 | /* | ||
| 135 | * Remove a call from the hashtable | ||
| 136 | */ | ||
| 137 | static void rxrpc_call_hash_del(struct rxrpc_call *call) | ||
| 138 | { | ||
| 139 | _enter(""); | ||
| 140 | spin_lock(&rxrpc_call_hash_lock); | ||
| 141 | hash_del_rcu(&call->hash_node); | ||
| 142 | spin_unlock(&rxrpc_call_hash_lock); | ||
| 143 | _leave(""); | ||
| 144 | } | ||
| 145 | |||
| 146 | /* | ||
| 147 | * Find a call in the hashtable and return it, or NULL if it | ||
| 148 | * isn't there. | ||
| 149 | */ | ||
| 150 | struct rxrpc_call *rxrpc_find_call_hash( | ||
| 151 | u8 clientflag, | ||
| 152 | __be32 cid, | ||
| 153 | __be32 call_id, | ||
| 154 | __be32 epoch, | ||
| 155 | __be16 service_id, | ||
| 156 | void *localptr, | ||
| 157 | sa_family_t proto, | ||
| 158 | const u8 *peer_addr) | ||
| 159 | { | ||
| 160 | unsigned long key; | ||
| 161 | unsigned int addr_size = 0; | ||
| 162 | struct rxrpc_call *call = NULL; | ||
| 163 | struct rxrpc_call *ret = NULL; | ||
| 164 | |||
| 165 | _enter(""); | ||
| 166 | switch (proto) { | ||
| 167 | case AF_INET: | ||
| 168 | addr_size = sizeof(call->peer_ip.ipv4_addr); | ||
| 169 | break; | ||
| 170 | case AF_INET6: | ||
| 171 | addr_size = sizeof(call->peer_ip.ipv6_addr); | ||
| 172 | break; | ||
| 173 | default: | ||
| 174 | break; | ||
| 175 | } | ||
| 176 | |||
| 177 | key = rxrpc_call_hashfunc(clientflag, cid, call_id, epoch, | ||
| 178 | service_id, proto, localptr, addr_size, | ||
| 179 | peer_addr); | ||
| 180 | hash_for_each_possible_rcu(rxrpc_call_hash, call, hash_node, key) { | ||
| 181 | if (call->hash_key == key && | ||
| 182 | call->call_id == call_id && | ||
| 183 | call->cid == cid && | ||
| 184 | call->in_clientflag == clientflag && | ||
| 185 | call->service_id == service_id && | ||
| 186 | call->proto == proto && | ||
| 187 | call->local == localptr && | ||
| 188 | memcmp(call->peer_ip.ipv6_addr, peer_addr, | ||
| 189 | addr_size) == 0 && | ||
| 190 | call->epoch == epoch) { | ||
| 191 | ret = call; | ||
| 192 | break; | ||
| 193 | } | ||
| 194 | } | ||
| 195 | _leave(" = %p", ret); | ||
| 196 | return ret; | ||
| 197 | } | ||
| 198 | |||
| 50 | /* | 199 | /* |
| 51 | * allocate a new call | 200 | * allocate a new call |
| 52 | */ | 201 | */ |
| @@ -91,7 +240,7 @@ static struct rxrpc_call *rxrpc_alloc_call(gfp_t gfp) | |||
| 91 | call->rx_data_expect = 1; | 240 | call->rx_data_expect = 1; |
| 92 | call->rx_data_eaten = 0; | 241 | call->rx_data_eaten = 0; |
| 93 | call->rx_first_oos = 0; | 242 | call->rx_first_oos = 0; |
| 94 | call->ackr_win_top = call->rx_data_eaten + 1 + RXRPC_MAXACKS; | 243 | call->ackr_win_top = call->rx_data_eaten + 1 + rxrpc_rx_window_size; |
| 95 | call->creation_jif = jiffies; | 244 | call->creation_jif = jiffies; |
| 96 | return call; | 245 | return call; |
| 97 | } | 246 | } |
| @@ -128,11 +277,31 @@ static struct rxrpc_call *rxrpc_alloc_client_call( | |||
| 128 | return ERR_PTR(ret); | 277 | return ERR_PTR(ret); |
| 129 | } | 278 | } |
| 130 | 279 | ||
| 280 | /* Record copies of information for hashtable lookup */ | ||
| 281 | call->proto = rx->proto; | ||
| 282 | call->local = trans->local; | ||
| 283 | switch (call->proto) { | ||
| 284 | case AF_INET: | ||
| 285 | call->peer_ip.ipv4_addr = | ||
| 286 | trans->peer->srx.transport.sin.sin_addr.s_addr; | ||
| 287 | break; | ||
| 288 | case AF_INET6: | ||
| 289 | memcpy(call->peer_ip.ipv6_addr, | ||
| 290 | trans->peer->srx.transport.sin6.sin6_addr.in6_u.u6_addr8, | ||
| 291 | sizeof(call->peer_ip.ipv6_addr)); | ||
| 292 | break; | ||
| 293 | } | ||
| 294 | call->epoch = call->conn->epoch; | ||
| 295 | call->service_id = call->conn->service_id; | ||
| 296 | call->in_clientflag = call->conn->in_clientflag; | ||
| 297 | /* Add the new call to the hashtable */ | ||
| 298 | rxrpc_call_hash_add(call); | ||
| 299 | |||
| 131 | spin_lock(&call->conn->trans->peer->lock); | 300 | spin_lock(&call->conn->trans->peer->lock); |
| 132 | list_add(&call->error_link, &call->conn->trans->peer->error_targets); | 301 | list_add(&call->error_link, &call->conn->trans->peer->error_targets); |
| 133 | spin_unlock(&call->conn->trans->peer->lock); | 302 | spin_unlock(&call->conn->trans->peer->lock); |
| 134 | 303 | ||
| 135 | call->lifetimer.expires = jiffies + rxrpc_call_max_lifetime * HZ; | 304 | call->lifetimer.expires = jiffies + rxrpc_max_call_lifetime; |
| 136 | add_timer(&call->lifetimer); | 305 | add_timer(&call->lifetimer); |
| 137 | 306 | ||
| 138 | _leave(" = %p", call); | 307 | _leave(" = %p", call); |
| @@ -320,9 +489,12 @@ struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *rx, | |||
| 320 | parent = *p; | 489 | parent = *p; |
| 321 | call = rb_entry(parent, struct rxrpc_call, conn_node); | 490 | call = rb_entry(parent, struct rxrpc_call, conn_node); |
| 322 | 491 | ||
| 323 | if (call_id < call->call_id) | 492 | /* The tree is sorted in order of the __be32 value without |
| 493 | * turning it into host order. | ||
| 494 | */ | ||
| 495 | if ((__force u32)call_id < (__force u32)call->call_id) | ||
| 324 | p = &(*p)->rb_left; | 496 | p = &(*p)->rb_left; |
| 325 | else if (call_id > call->call_id) | 497 | else if ((__force u32)call_id > (__force u32)call->call_id) |
| 326 | p = &(*p)->rb_right; | 498 | p = &(*p)->rb_right; |
| 327 | else | 499 | else |
| 328 | goto old_call; | 500 | goto old_call; |
| @@ -347,9 +519,31 @@ struct rxrpc_call *rxrpc_incoming_call(struct rxrpc_sock *rx, | |||
| 347 | list_add_tail(&call->link, &rxrpc_calls); | 519 | list_add_tail(&call->link, &rxrpc_calls); |
| 348 | write_unlock_bh(&rxrpc_call_lock); | 520 | write_unlock_bh(&rxrpc_call_lock); |
| 349 | 521 | ||
| 522 | /* Record copies of information for hashtable lookup */ | ||
| 523 | call->proto = rx->proto; | ||
| 524 | call->local = conn->trans->local; | ||
| 525 | switch (call->proto) { | ||
| 526 | case AF_INET: | ||
| 527 | call->peer_ip.ipv4_addr = | ||
| 528 | conn->trans->peer->srx.transport.sin.sin_addr.s_addr; | ||
| 529 | break; | ||
| 530 | case AF_INET6: | ||
| 531 | memcpy(call->peer_ip.ipv6_addr, | ||
| 532 | conn->trans->peer->srx.transport.sin6.sin6_addr.in6_u.u6_addr8, | ||
| 533 | sizeof(call->peer_ip.ipv6_addr)); | ||
| 534 | break; | ||
| 535 | default: | ||
| 536 | break; | ||
| 537 | } | ||
| 538 | call->epoch = conn->epoch; | ||
| 539 | call->service_id = conn->service_id; | ||
| 540 | call->in_clientflag = conn->in_clientflag; | ||
| 541 | /* Add the new call to the hashtable */ | ||
| 542 | rxrpc_call_hash_add(call); | ||
| 543 | |||
| 350 | _net("CALL incoming %d on CONN %d", call->debug_id, call->conn->debug_id); | 544 | _net("CALL incoming %d on CONN %d", call->debug_id, call->conn->debug_id); |
| 351 | 545 | ||
| 352 | call->lifetimer.expires = jiffies + rxrpc_call_max_lifetime * HZ; | 546 | call->lifetimer.expires = jiffies + rxrpc_max_call_lifetime; |
| 353 | add_timer(&call->lifetimer); | 547 | add_timer(&call->lifetimer); |
| 354 | _leave(" = %p {%d} [new]", call, call->debug_id); | 548 | _leave(" = %p {%d} [new]", call, call->debug_id); |
| 355 | return call; | 549 | return call; |
| @@ -533,7 +727,7 @@ void rxrpc_release_call(struct rxrpc_call *call) | |||
| 533 | del_timer_sync(&call->resend_timer); | 727 | del_timer_sync(&call->resend_timer); |
| 534 | del_timer_sync(&call->ack_timer); | 728 | del_timer_sync(&call->ack_timer); |
| 535 | del_timer_sync(&call->lifetimer); | 729 | del_timer_sync(&call->lifetimer); |
| 536 | call->deadspan.expires = jiffies + rxrpc_dead_call_timeout * HZ; | 730 | call->deadspan.expires = jiffies + rxrpc_dead_call_expiry; |
| 537 | add_timer(&call->deadspan); | 731 | add_timer(&call->deadspan); |
| 538 | 732 | ||
| 539 | _leave(""); | 733 | _leave(""); |
| @@ -665,6 +859,9 @@ static void rxrpc_cleanup_call(struct rxrpc_call *call) | |||
| 665 | rxrpc_put_connection(call->conn); | 859 | rxrpc_put_connection(call->conn); |
| 666 | } | 860 | } |
| 667 | 861 | ||
| 862 | /* Remove the call from the hash */ | ||
| 863 | rxrpc_call_hash_del(call); | ||
| 864 | |||
| 668 | if (call->acks_window) { | 865 | if (call->acks_window) { |
| 669 | _debug("kill Tx window %d", | 866 | _debug("kill Tx window %d", |
| 670 | CIRC_CNT(call->acks_head, call->acks_tail, | 867 | CIRC_CNT(call->acks_head, call->acks_tail, |
diff --git a/net/rxrpc/ar-connection.c b/net/rxrpc/ar-connection.c index 7bf5b5b9e8b9..6631f4f1e39b 100644 --- a/net/rxrpc/ar-connection.c +++ b/net/rxrpc/ar-connection.c | |||
| @@ -18,11 +18,15 @@ | |||
| 18 | #include <net/af_rxrpc.h> | 18 | #include <net/af_rxrpc.h> |
| 19 | #include "ar-internal.h" | 19 | #include "ar-internal.h" |
| 20 | 20 | ||
| 21 | /* | ||
| 22 | * Time till a connection expires after last use (in seconds). | ||
| 23 | */ | ||
| 24 | unsigned rxrpc_connection_expiry = 10 * 60; | ||
| 25 | |||
| 21 | static void rxrpc_connection_reaper(struct work_struct *work); | 26 | static void rxrpc_connection_reaper(struct work_struct *work); |
| 22 | 27 | ||
| 23 | LIST_HEAD(rxrpc_connections); | 28 | LIST_HEAD(rxrpc_connections); |
| 24 | DEFINE_RWLOCK(rxrpc_connection_lock); | 29 | DEFINE_RWLOCK(rxrpc_connection_lock); |
| 25 | static unsigned long rxrpc_connection_timeout = 10 * 60; | ||
| 26 | static DECLARE_DELAYED_WORK(rxrpc_connection_reap, rxrpc_connection_reaper); | 30 | static DECLARE_DELAYED_WORK(rxrpc_connection_reap, rxrpc_connection_reaper); |
| 27 | 31 | ||
| 28 | /* | 32 | /* |
| @@ -862,7 +866,7 @@ static void rxrpc_connection_reaper(struct work_struct *work) | |||
| 862 | 866 | ||
| 863 | spin_lock(&conn->trans->client_lock); | 867 | spin_lock(&conn->trans->client_lock); |
| 864 | write_lock(&conn->trans->conn_lock); | 868 | write_lock(&conn->trans->conn_lock); |
| 865 | reap_time = conn->put_time + rxrpc_connection_timeout; | 869 | reap_time = conn->put_time + rxrpc_connection_expiry; |
| 866 | 870 | ||
| 867 | if (atomic_read(&conn->usage) > 0) { | 871 | if (atomic_read(&conn->usage) > 0) { |
| 868 | ; | 872 | ; |
| @@ -916,7 +920,7 @@ void __exit rxrpc_destroy_all_connections(void) | |||
| 916 | { | 920 | { |
| 917 | _enter(""); | 921 | _enter(""); |
| 918 | 922 | ||
| 919 | rxrpc_connection_timeout = 0; | 923 | rxrpc_connection_expiry = 0; |
| 920 | cancel_delayed_work(&rxrpc_connection_reap); | 924 | cancel_delayed_work(&rxrpc_connection_reap); |
| 921 | rxrpc_queue_delayed_work(&rxrpc_connection_reap, 0); | 925 | rxrpc_queue_delayed_work(&rxrpc_connection_reap, 0); |
| 922 | 926 | ||
diff --git a/net/rxrpc/ar-error.c b/net/rxrpc/ar-error.c index a9206087b4d7..db57458c824c 100644 --- a/net/rxrpc/ar-error.c +++ b/net/rxrpc/ar-error.c | |||
| @@ -83,6 +83,7 @@ void rxrpc_UDP_error_report(struct sock *sk) | |||
| 83 | 83 | ||
| 84 | if (mtu == 0) { | 84 | if (mtu == 0) { |
| 85 | /* they didn't give us a size, estimate one */ | 85 | /* they didn't give us a size, estimate one */ |
| 86 | mtu = peer->if_mtu; | ||
| 86 | if (mtu > 1500) { | 87 | if (mtu > 1500) { |
| 87 | mtu >>= 1; | 88 | mtu >>= 1; |
| 88 | if (mtu < 1500) | 89 | if (mtu < 1500) |
diff --git a/net/rxrpc/ar-input.c b/net/rxrpc/ar-input.c index 529572f18d1f..63b21e580de9 100644 --- a/net/rxrpc/ar-input.c +++ b/net/rxrpc/ar-input.c | |||
| @@ -25,8 +25,6 @@ | |||
| 25 | #include <net/net_namespace.h> | 25 | #include <net/net_namespace.h> |
| 26 | #include "ar-internal.h" | 26 | #include "ar-internal.h" |
| 27 | 27 | ||
| 28 | unsigned long rxrpc_ack_timeout = 1; | ||
| 29 | |||
| 30 | const char *rxrpc_pkts[] = { | 28 | const char *rxrpc_pkts[] = { |
| 31 | "?00", | 29 | "?00", |
| 32 | "DATA", "ACK", "BUSY", "ABORT", "ACKALL", "CHALL", "RESP", "DEBUG", | 30 | "DATA", "ACK", "BUSY", "ABORT", "ACKALL", "CHALL", "RESP", "DEBUG", |
| @@ -115,7 +113,7 @@ int rxrpc_queue_rcv_skb(struct rxrpc_call *call, struct sk_buff *skb, | |||
| 115 | spin_unlock_bh(&sk->sk_receive_queue.lock); | 113 | spin_unlock_bh(&sk->sk_receive_queue.lock); |
| 116 | 114 | ||
| 117 | if (!sock_flag(sk, SOCK_DEAD)) | 115 | if (!sock_flag(sk, SOCK_DEAD)) |
| 118 | sk->sk_data_ready(sk, skb_len); | 116 | sk->sk_data_ready(sk); |
| 119 | } | 117 | } |
| 120 | skb = NULL; | 118 | skb = NULL; |
| 121 | } else { | 119 | } else { |
| @@ -349,8 +347,7 @@ void rxrpc_fast_process_packet(struct rxrpc_call *call, struct sk_buff *skb) | |||
| 349 | * it */ | 347 | * it */ |
| 350 | if (sp->hdr.flags & RXRPC_REQUEST_ACK) { | 348 | if (sp->hdr.flags & RXRPC_REQUEST_ACK) { |
| 351 | _proto("ACK Requested on %%%u", serial); | 349 | _proto("ACK Requested on %%%u", serial); |
| 352 | rxrpc_propose_ACK(call, RXRPC_ACK_REQUESTED, sp->hdr.serial, | 350 | rxrpc_propose_ACK(call, RXRPC_ACK_REQUESTED, sp->hdr.serial, false); |
| 353 | !(sp->hdr.flags & RXRPC_MORE_PACKETS)); | ||
| 354 | } | 351 | } |
| 355 | 352 | ||
| 356 | switch (sp->hdr.type) { | 353 | switch (sp->hdr.type) { |
| @@ -526,36 +523,38 @@ protocol_error: | |||
| 526 | * post an incoming packet to the appropriate call/socket to deal with | 523 | * post an incoming packet to the appropriate call/socket to deal with |
| 527 | * - must get rid of the sk_buff, either by freeing it or by queuing it | 524 | * - must get rid of the sk_buff, either by freeing it or by queuing it |
| 528 | */ | 525 | */ |
| 529 | static void rxrpc_post_packet_to_call(struct rxrpc_connection *conn, | 526 | static void rxrpc_post_packet_to_call(struct rxrpc_call *call, |
| 530 | struct sk_buff *skb) | 527 | struct sk_buff *skb) |
| 531 | { | 528 | { |
| 532 | struct rxrpc_skb_priv *sp; | 529 | struct rxrpc_skb_priv *sp; |
| 533 | struct rxrpc_call *call; | ||
| 534 | struct rb_node *p; | ||
| 535 | __be32 call_id; | ||
| 536 | |||
| 537 | _enter("%p,%p", conn, skb); | ||
| 538 | 530 | ||
| 539 | read_lock_bh(&conn->lock); | 531 | _enter("%p,%p", call, skb); |
| 540 | 532 | ||
| 541 | sp = rxrpc_skb(skb); | 533 | sp = rxrpc_skb(skb); |
| 542 | 534 | ||
| 543 | /* look at extant calls by channel number first */ | ||
| 544 | call = conn->channels[ntohl(sp->hdr.cid) & RXRPC_CHANNELMASK]; | ||
| 545 | if (!call || call->call_id != sp->hdr.callNumber) | ||
| 546 | goto call_not_extant; | ||
| 547 | |||
| 548 | _debug("extant call [%d]", call->state); | 535 | _debug("extant call [%d]", call->state); |
| 549 | ASSERTCMP(call->conn, ==, conn); | ||
| 550 | 536 | ||
| 551 | read_lock(&call->state_lock); | 537 | read_lock(&call->state_lock); |
| 552 | switch (call->state) { | 538 | switch (call->state) { |
| 553 | case RXRPC_CALL_LOCALLY_ABORTED: | 539 | case RXRPC_CALL_LOCALLY_ABORTED: |
| 554 | if (!test_and_set_bit(RXRPC_CALL_ABORT, &call->events)) | 540 | if (!test_and_set_bit(RXRPC_CALL_ABORT, &call->events)) { |
| 555 | rxrpc_queue_call(call); | 541 | rxrpc_queue_call(call); |
| 542 | goto free_unlock; | ||
| 543 | } | ||
| 556 | case RXRPC_CALL_REMOTELY_ABORTED: | 544 | case RXRPC_CALL_REMOTELY_ABORTED: |
| 557 | case RXRPC_CALL_NETWORK_ERROR: | 545 | case RXRPC_CALL_NETWORK_ERROR: |
| 558 | case RXRPC_CALL_DEAD: | 546 | case RXRPC_CALL_DEAD: |
| 547 | goto dead_call; | ||
| 548 | case RXRPC_CALL_COMPLETE: | ||
| 549 | case RXRPC_CALL_CLIENT_FINAL_ACK: | ||
| 550 | /* complete server call */ | ||
| 551 | if (call->conn->in_clientflag) | ||
| 552 | goto dead_call; | ||
| 553 | /* resend last packet of a completed call */ | ||
| 554 | _debug("final ack again"); | ||
| 555 | rxrpc_get_call(call); | ||
| 556 | set_bit(RXRPC_CALL_ACK_FINAL, &call->events); | ||
| 557 | rxrpc_queue_call(call); | ||
| 559 | goto free_unlock; | 558 | goto free_unlock; |
| 560 | default: | 559 | default: |
| 561 | break; | 560 | break; |
| @@ -563,7 +562,6 @@ static void rxrpc_post_packet_to_call(struct rxrpc_connection *conn, | |||
| 563 | 562 | ||
| 564 | read_unlock(&call->state_lock); | 563 | read_unlock(&call->state_lock); |
| 565 | rxrpc_get_call(call); | 564 | rxrpc_get_call(call); |
| 566 | read_unlock_bh(&conn->lock); | ||
| 567 | 565 | ||
| 568 | if (sp->hdr.type == RXRPC_PACKET_TYPE_DATA && | 566 | if (sp->hdr.type == RXRPC_PACKET_TYPE_DATA && |
| 569 | sp->hdr.flags & RXRPC_JUMBO_PACKET) | 567 | sp->hdr.flags & RXRPC_JUMBO_PACKET) |
| @@ -574,78 +572,16 @@ static void rxrpc_post_packet_to_call(struct rxrpc_connection *conn, | |||
| 574 | rxrpc_put_call(call); | 572 | rxrpc_put_call(call); |
| 575 | goto done; | 573 | goto done; |
| 576 | 574 | ||
| 577 | call_not_extant: | ||
| 578 | /* search the completed calls in case what we're dealing with is | ||
| 579 | * there */ | ||
| 580 | _debug("call not extant"); | ||
| 581 | |||
| 582 | call_id = sp->hdr.callNumber; | ||
| 583 | p = conn->calls.rb_node; | ||
| 584 | while (p) { | ||
| 585 | call = rb_entry(p, struct rxrpc_call, conn_node); | ||
| 586 | |||
| 587 | if (call_id < call->call_id) | ||
| 588 | p = p->rb_left; | ||
| 589 | else if (call_id > call->call_id) | ||
| 590 | p = p->rb_right; | ||
| 591 | else | ||
| 592 | goto found_completed_call; | ||
| 593 | } | ||
| 594 | |||
| 595 | dead_call: | 575 | dead_call: |
| 596 | /* it's a either a really old call that we no longer remember or its a | 576 | if (sp->hdr.type != RXRPC_PACKET_TYPE_ABORT) { |
| 597 | * new incoming call */ | 577 | skb->priority = RX_CALL_DEAD; |
| 598 | read_unlock_bh(&conn->lock); | 578 | rxrpc_reject_packet(call->conn->trans->local, skb); |
| 599 | 579 | goto unlock; | |
| 600 | if (sp->hdr.flags & RXRPC_CLIENT_INITIATED && | ||
| 601 | sp->hdr.seq == cpu_to_be32(1)) { | ||
| 602 | _debug("incoming call"); | ||
| 603 | skb_queue_tail(&conn->trans->local->accept_queue, skb); | ||
| 604 | rxrpc_queue_work(&conn->trans->local->acceptor); | ||
| 605 | goto done; | ||
| 606 | } | ||
| 607 | |||
| 608 | _debug("dead call"); | ||
| 609 | skb->priority = RX_CALL_DEAD; | ||
| 610 | rxrpc_reject_packet(conn->trans->local, skb); | ||
| 611 | goto done; | ||
| 612 | |||
| 613 | /* resend last packet of a completed call | ||
| 614 | * - client calls may have been aborted or ACK'd | ||
| 615 | * - server calls may have been aborted | ||
| 616 | */ | ||
| 617 | found_completed_call: | ||
| 618 | _debug("completed call"); | ||
| 619 | |||
| 620 | if (atomic_read(&call->usage) == 0) | ||
| 621 | goto dead_call; | ||
| 622 | |||
| 623 | /* synchronise any state changes */ | ||
| 624 | read_lock(&call->state_lock); | ||
| 625 | ASSERTIFCMP(call->state != RXRPC_CALL_CLIENT_FINAL_ACK, | ||
| 626 | call->state, >=, RXRPC_CALL_COMPLETE); | ||
| 627 | |||
| 628 | if (call->state == RXRPC_CALL_LOCALLY_ABORTED || | ||
| 629 | call->state == RXRPC_CALL_REMOTELY_ABORTED || | ||
| 630 | call->state == RXRPC_CALL_DEAD) { | ||
| 631 | read_unlock(&call->state_lock); | ||
| 632 | goto dead_call; | ||
| 633 | } | ||
| 634 | |||
| 635 | if (call->conn->in_clientflag) { | ||
| 636 | read_unlock(&call->state_lock); | ||
| 637 | goto dead_call; /* complete server call */ | ||
| 638 | } | 580 | } |
| 639 | |||
| 640 | _debug("final ack again"); | ||
| 641 | rxrpc_get_call(call); | ||
| 642 | set_bit(RXRPC_CALL_ACK_FINAL, &call->events); | ||
| 643 | rxrpc_queue_call(call); | ||
| 644 | |||
| 645 | free_unlock: | 581 | free_unlock: |
| 646 | read_unlock(&call->state_lock); | ||
| 647 | read_unlock_bh(&conn->lock); | ||
| 648 | rxrpc_free_skb(skb); | 582 | rxrpc_free_skb(skb); |
| 583 | unlock: | ||
| 584 | read_unlock(&call->state_lock); | ||
| 649 | done: | 585 | done: |
| 650 | _leave(""); | 586 | _leave(""); |
| 651 | } | 587 | } |
| @@ -664,21 +600,46 @@ static void rxrpc_post_packet_to_conn(struct rxrpc_connection *conn, | |||
| 664 | rxrpc_queue_conn(conn); | 600 | rxrpc_queue_conn(conn); |
| 665 | } | 601 | } |
| 666 | 602 | ||
| 603 | static struct rxrpc_connection *rxrpc_conn_from_local(struct rxrpc_local *local, | ||
| 604 | struct sk_buff *skb, | ||
| 605 | struct rxrpc_skb_priv *sp) | ||
| 606 | { | ||
| 607 | struct rxrpc_peer *peer; | ||
| 608 | struct rxrpc_transport *trans; | ||
| 609 | struct rxrpc_connection *conn; | ||
| 610 | |||
| 611 | peer = rxrpc_find_peer(local, ip_hdr(skb)->saddr, | ||
| 612 | udp_hdr(skb)->source); | ||
| 613 | if (IS_ERR(peer)) | ||
| 614 | goto cant_find_conn; | ||
| 615 | |||
| 616 | trans = rxrpc_find_transport(local, peer); | ||
| 617 | rxrpc_put_peer(peer); | ||
| 618 | if (!trans) | ||
| 619 | goto cant_find_conn; | ||
| 620 | |||
| 621 | conn = rxrpc_find_connection(trans, &sp->hdr); | ||
| 622 | rxrpc_put_transport(trans); | ||
| 623 | if (!conn) | ||
| 624 | goto cant_find_conn; | ||
| 625 | |||
| 626 | return conn; | ||
| 627 | cant_find_conn: | ||
| 628 | return NULL; | ||
| 629 | } | ||
| 630 | |||
| 667 | /* | 631 | /* |
| 668 | * handle data received on the local endpoint | 632 | * handle data received on the local endpoint |
| 669 | * - may be called in interrupt context | 633 | * - may be called in interrupt context |
| 670 | */ | 634 | */ |
| 671 | void rxrpc_data_ready(struct sock *sk, int count) | 635 | void rxrpc_data_ready(struct sock *sk) |
| 672 | { | 636 | { |
| 673 | struct rxrpc_connection *conn; | ||
| 674 | struct rxrpc_transport *trans; | ||
| 675 | struct rxrpc_skb_priv *sp; | 637 | struct rxrpc_skb_priv *sp; |
| 676 | struct rxrpc_local *local; | 638 | struct rxrpc_local *local; |
| 677 | struct rxrpc_peer *peer; | ||
| 678 | struct sk_buff *skb; | 639 | struct sk_buff *skb; |
| 679 | int ret; | 640 | int ret; |
| 680 | 641 | ||
| 681 | _enter("%p, %d", sk, count); | 642 | _enter("%p", sk); |
| 682 | 643 | ||
| 683 | ASSERT(!irqs_disabled()); | 644 | ASSERT(!irqs_disabled()); |
| 684 | 645 | ||
| @@ -749,27 +710,34 @@ void rxrpc_data_ready(struct sock *sk, int count) | |||
| 749 | (sp->hdr.callNumber == 0 || sp->hdr.seq == 0)) | 710 | (sp->hdr.callNumber == 0 || sp->hdr.seq == 0)) |
| 750 | goto bad_message; | 711 | goto bad_message; |
| 751 | 712 | ||
| 752 | peer = rxrpc_find_peer(local, ip_hdr(skb)->saddr, udp_hdr(skb)->source); | 713 | if (sp->hdr.callNumber == 0) { |
| 753 | if (IS_ERR(peer)) | 714 | /* This is a connection-level packet. These should be |
| 754 | goto cant_route_call; | 715 | * fairly rare, so the extra overhead of looking them up the |
| 716 | * old-fashioned way doesn't really hurt */ | ||
| 717 | struct rxrpc_connection *conn; | ||
| 755 | 718 | ||
| 756 | trans = rxrpc_find_transport(local, peer); | 719 | conn = rxrpc_conn_from_local(local, skb, sp); |
| 757 | rxrpc_put_peer(peer); | 720 | if (!conn) |
| 758 | if (!trans) | 721 | goto cant_route_call; |
| 759 | goto cant_route_call; | ||
| 760 | 722 | ||
| 761 | conn = rxrpc_find_connection(trans, &sp->hdr); | 723 | _debug("CONN %p {%d}", conn, conn->debug_id); |
| 762 | rxrpc_put_transport(trans); | ||
| 763 | if (!conn) | ||
| 764 | goto cant_route_call; | ||
| 765 | |||
| 766 | _debug("CONN %p {%d}", conn, conn->debug_id); | ||
| 767 | |||
| 768 | if (sp->hdr.callNumber == 0) | ||
| 769 | rxrpc_post_packet_to_conn(conn, skb); | 724 | rxrpc_post_packet_to_conn(conn, skb); |
| 770 | else | 725 | rxrpc_put_connection(conn); |
| 771 | rxrpc_post_packet_to_call(conn, skb); | 726 | } else { |
| 772 | rxrpc_put_connection(conn); | 727 | struct rxrpc_call *call; |
| 728 | u8 in_clientflag = 0; | ||
| 729 | |||
| 730 | if (sp->hdr.flags & RXRPC_CLIENT_INITIATED) | ||
| 731 | in_clientflag = RXRPC_CLIENT_INITIATED; | ||
| 732 | call = rxrpc_find_call_hash(in_clientflag, sp->hdr.cid, | ||
| 733 | sp->hdr.callNumber, sp->hdr.epoch, | ||
| 734 | sp->hdr.serviceId, local, AF_INET, | ||
| 735 | (u8 *)&ip_hdr(skb)->saddr); | ||
| 736 | if (call) | ||
| 737 | rxrpc_post_packet_to_call(call, skb); | ||
| 738 | else | ||
| 739 | goto cant_route_call; | ||
| 740 | } | ||
| 773 | rxrpc_put_local(local); | 741 | rxrpc_put_local(local); |
| 774 | return; | 742 | return; |
| 775 | 743 | ||
| @@ -790,8 +758,10 @@ cant_route_call: | |||
| 790 | skb->priority = RX_CALL_DEAD; | 758 | skb->priority = RX_CALL_DEAD; |
| 791 | } | 759 | } |
| 792 | 760 | ||
| 793 | _debug("reject"); | 761 | if (sp->hdr.type != RXRPC_PACKET_TYPE_ABORT) { |
| 794 | rxrpc_reject_packet(local, skb); | 762 | _debug("reject type %d",sp->hdr.type); |
| 763 | rxrpc_reject_packet(local, skb); | ||
| 764 | } | ||
| 795 | rxrpc_put_local(local); | 765 | rxrpc_put_local(local); |
| 796 | _leave(" [no call]"); | 766 | _leave(" [no call]"); |
| 797 | return; | 767 | return; |
diff --git a/net/rxrpc/ar-internal.h b/net/rxrpc/ar-internal.h index 5f43675ee1df..ba9fd36d3f15 100644 --- a/net/rxrpc/ar-internal.h +++ b/net/rxrpc/ar-internal.h | |||
| @@ -396,9 +396,20 @@ struct rxrpc_call { | |||
| 396 | #define RXRPC_ACKR_WINDOW_ASZ DIV_ROUND_UP(RXRPC_MAXACKS, BITS_PER_LONG) | 396 | #define RXRPC_ACKR_WINDOW_ASZ DIV_ROUND_UP(RXRPC_MAXACKS, BITS_PER_LONG) |
| 397 | unsigned long ackr_window[RXRPC_ACKR_WINDOW_ASZ + 1]; | 397 | unsigned long ackr_window[RXRPC_ACKR_WINDOW_ASZ + 1]; |
| 398 | 398 | ||
| 399 | struct hlist_node hash_node; | ||
| 400 | unsigned long hash_key; /* Full hash key */ | ||
| 401 | u8 in_clientflag; /* Copy of conn->in_clientflag for hashing */ | ||
| 402 | struct rxrpc_local *local; /* Local endpoint. Used for hashing. */ | ||
| 403 | sa_family_t proto; /* Frame protocol */ | ||
| 399 | /* the following should all be in net order */ | 404 | /* the following should all be in net order */ |
| 400 | __be32 cid; /* connection ID + channel index */ | 405 | __be32 cid; /* connection ID + channel index */ |
| 401 | __be32 call_id; /* call ID on connection */ | 406 | __be32 call_id; /* call ID on connection */ |
| 407 | __be32 epoch; /* epoch of this connection */ | ||
| 408 | __be16 service_id; /* service ID */ | ||
| 409 | union { /* Peer IP address for hashing */ | ||
| 410 | __be32 ipv4_addr; | ||
| 411 | __u8 ipv6_addr[16]; /* Anticipates eventual IPv6 support */ | ||
| 412 | } peer_ip; | ||
| 402 | }; | 413 | }; |
| 403 | 414 | ||
| 404 | /* | 415 | /* |
| @@ -433,6 +444,13 @@ int rxrpc_reject_call(struct rxrpc_sock *); | |||
| 433 | /* | 444 | /* |
| 434 | * ar-ack.c | 445 | * ar-ack.c |
| 435 | */ | 446 | */ |
| 447 | extern unsigned rxrpc_requested_ack_delay; | ||
| 448 | extern unsigned rxrpc_soft_ack_delay; | ||
| 449 | extern unsigned rxrpc_idle_ack_delay; | ||
| 450 | extern unsigned rxrpc_rx_window_size; | ||
| 451 | extern unsigned rxrpc_rx_mtu; | ||
| 452 | extern unsigned rxrpc_rx_jumbo_max; | ||
| 453 | |||
| 436 | void __rxrpc_propose_ACK(struct rxrpc_call *, u8, __be32, bool); | 454 | void __rxrpc_propose_ACK(struct rxrpc_call *, u8, __be32, bool); |
| 437 | void rxrpc_propose_ACK(struct rxrpc_call *, u8, __be32, bool); | 455 | void rxrpc_propose_ACK(struct rxrpc_call *, u8, __be32, bool); |
| 438 | void rxrpc_process_call(struct work_struct *); | 456 | void rxrpc_process_call(struct work_struct *); |
| @@ -440,10 +458,14 @@ void rxrpc_process_call(struct work_struct *); | |||
| 440 | /* | 458 | /* |
| 441 | * ar-call.c | 459 | * ar-call.c |
| 442 | */ | 460 | */ |
| 461 | extern unsigned rxrpc_max_call_lifetime; | ||
| 462 | extern unsigned rxrpc_dead_call_expiry; | ||
| 443 | extern struct kmem_cache *rxrpc_call_jar; | 463 | extern struct kmem_cache *rxrpc_call_jar; |
| 444 | extern struct list_head rxrpc_calls; | 464 | extern struct list_head rxrpc_calls; |
| 445 | extern rwlock_t rxrpc_call_lock; | 465 | extern rwlock_t rxrpc_call_lock; |
| 446 | 466 | ||
| 467 | struct rxrpc_call *rxrpc_find_call_hash(u8, __be32, __be32, __be32, | ||
| 468 | __be16, void *, sa_family_t, const u8 *); | ||
| 447 | struct rxrpc_call *rxrpc_get_client_call(struct rxrpc_sock *, | 469 | struct rxrpc_call *rxrpc_get_client_call(struct rxrpc_sock *, |
| 448 | struct rxrpc_transport *, | 470 | struct rxrpc_transport *, |
| 449 | struct rxrpc_conn_bundle *, | 471 | struct rxrpc_conn_bundle *, |
| @@ -460,6 +482,7 @@ void __exit rxrpc_destroy_all_calls(void); | |||
| 460 | /* | 482 | /* |
| 461 | * ar-connection.c | 483 | * ar-connection.c |
| 462 | */ | 484 | */ |
| 485 | extern unsigned rxrpc_connection_expiry; | ||
| 463 | extern struct list_head rxrpc_connections; | 486 | extern struct list_head rxrpc_connections; |
| 464 | extern rwlock_t rxrpc_connection_lock; | 487 | extern rwlock_t rxrpc_connection_lock; |
| 465 | 488 | ||
| @@ -493,10 +516,9 @@ void rxrpc_UDP_error_handler(struct work_struct *); | |||
| 493 | /* | 516 | /* |
| 494 | * ar-input.c | 517 | * ar-input.c |
| 495 | */ | 518 | */ |
| 496 | extern unsigned long rxrpc_ack_timeout; | ||
| 497 | extern const char *rxrpc_pkts[]; | 519 | extern const char *rxrpc_pkts[]; |
| 498 | 520 | ||
| 499 | void rxrpc_data_ready(struct sock *, int); | 521 | void rxrpc_data_ready(struct sock *); |
| 500 | int rxrpc_queue_rcv_skb(struct rxrpc_call *, struct sk_buff *, bool, bool); | 522 | int rxrpc_queue_rcv_skb(struct rxrpc_call *, struct sk_buff *, bool, bool); |
| 501 | void rxrpc_fast_process_packet(struct rxrpc_call *, struct sk_buff *); | 523 | void rxrpc_fast_process_packet(struct rxrpc_call *, struct sk_buff *); |
| 502 | 524 | ||
| @@ -504,6 +526,7 @@ void rxrpc_fast_process_packet(struct rxrpc_call *, struct sk_buff *); | |||
| 504 | * ar-local.c | 526 | * ar-local.c |
| 505 | */ | 527 | */ |
| 506 | extern rwlock_t rxrpc_local_lock; | 528 | extern rwlock_t rxrpc_local_lock; |
| 529 | |||
| 507 | struct rxrpc_local *rxrpc_lookup_local(struct sockaddr_rxrpc *); | 530 | struct rxrpc_local *rxrpc_lookup_local(struct sockaddr_rxrpc *); |
| 508 | void rxrpc_put_local(struct rxrpc_local *); | 531 | void rxrpc_put_local(struct rxrpc_local *); |
| 509 | void __exit rxrpc_destroy_all_locals(void); | 532 | void __exit rxrpc_destroy_all_locals(void); |
| @@ -522,7 +545,7 @@ int rxrpc_get_server_data_key(struct rxrpc_connection *, const void *, time_t, | |||
| 522 | /* | 545 | /* |
| 523 | * ar-output.c | 546 | * ar-output.c |
| 524 | */ | 547 | */ |
| 525 | extern int rxrpc_resend_timeout; | 548 | extern unsigned rxrpc_resend_timeout; |
| 526 | 549 | ||
| 527 | int rxrpc_send_packet(struct rxrpc_transport *, struct sk_buff *); | 550 | int rxrpc_send_packet(struct rxrpc_transport *, struct sk_buff *); |
| 528 | int rxrpc_client_sendmsg(struct kiocb *, struct rxrpc_sock *, | 551 | int rxrpc_client_sendmsg(struct kiocb *, struct rxrpc_sock *, |
| @@ -572,6 +595,8 @@ void rxrpc_packet_destructor(struct sk_buff *); | |||
| 572 | /* | 595 | /* |
| 573 | * ar-transport.c | 596 | * ar-transport.c |
| 574 | */ | 597 | */ |
| 598 | extern unsigned rxrpc_transport_expiry; | ||
| 599 | |||
| 575 | struct rxrpc_transport *rxrpc_get_transport(struct rxrpc_local *, | 600 | struct rxrpc_transport *rxrpc_get_transport(struct rxrpc_local *, |
| 576 | struct rxrpc_peer *, gfp_t); | 601 | struct rxrpc_peer *, gfp_t); |
| 577 | void rxrpc_put_transport(struct rxrpc_transport *); | 602 | void rxrpc_put_transport(struct rxrpc_transport *); |
| @@ -580,6 +605,17 @@ struct rxrpc_transport *rxrpc_find_transport(struct rxrpc_local *, | |||
| 580 | struct rxrpc_peer *); | 605 | struct rxrpc_peer *); |
| 581 | 606 | ||
| 582 | /* | 607 | /* |
| 608 | * sysctl.c | ||
| 609 | */ | ||
| 610 | #ifdef CONFIG_SYSCTL | ||
| 611 | extern int __init rxrpc_sysctl_init(void); | ||
| 612 | extern void rxrpc_sysctl_exit(void); | ||
| 613 | #else | ||
| 614 | static inline int __init rxrpc_sysctl_init(void) { return 0; } | ||
| 615 | static inline void rxrpc_sysctl_exit(void) {} | ||
| 616 | #endif | ||
| 617 | |||
| 618 | /* | ||
| 583 | * debug tracing | 619 | * debug tracing |
| 584 | */ | 620 | */ |
| 585 | extern unsigned int rxrpc_debug; | 621 | extern unsigned int rxrpc_debug; |
diff --git a/net/rxrpc/ar-output.c b/net/rxrpc/ar-output.c index d0e8f1c1898a..0b4b9a79f5ab 100644 --- a/net/rxrpc/ar-output.c +++ b/net/rxrpc/ar-output.c | |||
| @@ -18,7 +18,10 @@ | |||
| 18 | #include <net/af_rxrpc.h> | 18 | #include <net/af_rxrpc.h> |
| 19 | #include "ar-internal.h" | 19 | #include "ar-internal.h" |
| 20 | 20 | ||
| 21 | int rxrpc_resend_timeout = 4; | 21 | /* |
| 22 | * Time till packet resend (in jiffies). | ||
| 23 | */ | ||
| 24 | unsigned rxrpc_resend_timeout = 4 * HZ; | ||
| 22 | 25 | ||
| 23 | static int rxrpc_send_data(struct kiocb *iocb, | 26 | static int rxrpc_send_data(struct kiocb *iocb, |
| 24 | struct rxrpc_sock *rx, | 27 | struct rxrpc_sock *rx, |
| @@ -487,7 +490,7 @@ static void rxrpc_queue_packet(struct rxrpc_call *call, struct sk_buff *skb, | |||
| 487 | ntohl(sp->hdr.serial), ntohl(sp->hdr.seq)); | 490 | ntohl(sp->hdr.serial), ntohl(sp->hdr.seq)); |
| 488 | 491 | ||
| 489 | sp->need_resend = false; | 492 | sp->need_resend = false; |
| 490 | sp->resend_at = jiffies + rxrpc_resend_timeout * HZ; | 493 | sp->resend_at = jiffies + rxrpc_resend_timeout; |
| 491 | if (!test_and_set_bit(RXRPC_CALL_RUN_RTIMER, &call->flags)) { | 494 | if (!test_and_set_bit(RXRPC_CALL_RUN_RTIMER, &call->flags)) { |
| 492 | _debug("run timer"); | 495 | _debug("run timer"); |
| 493 | call->resend_timer.expires = sp->resend_at; | 496 | call->resend_timer.expires = sp->resend_at; |
| @@ -666,6 +669,7 @@ static int rxrpc_send_data(struct kiocb *iocb, | |||
| 666 | /* add the packet to the send queue if it's now full */ | 669 | /* add the packet to the send queue if it's now full */ |
| 667 | if (sp->remain <= 0 || (segment == 0 && !more)) { | 670 | if (sp->remain <= 0 || (segment == 0 && !more)) { |
| 668 | struct rxrpc_connection *conn = call->conn; | 671 | struct rxrpc_connection *conn = call->conn; |
| 672 | uint32_t seq; | ||
| 669 | size_t pad; | 673 | size_t pad; |
| 670 | 674 | ||
| 671 | /* pad out if we're using security */ | 675 | /* pad out if we're using security */ |
| @@ -678,11 +682,12 @@ static int rxrpc_send_data(struct kiocb *iocb, | |||
| 678 | memset(skb_put(skb, pad), 0, pad); | 682 | memset(skb_put(skb, pad), 0, pad); |
| 679 | } | 683 | } |
| 680 | 684 | ||
| 685 | seq = atomic_inc_return(&call->sequence); | ||
| 686 | |||
| 681 | sp->hdr.epoch = conn->epoch; | 687 | sp->hdr.epoch = conn->epoch; |
| 682 | sp->hdr.cid = call->cid; | 688 | sp->hdr.cid = call->cid; |
| 683 | sp->hdr.callNumber = call->call_id; | 689 | sp->hdr.callNumber = call->call_id; |
| 684 | sp->hdr.seq = | 690 | sp->hdr.seq = htonl(seq); |
| 685 | htonl(atomic_inc_return(&call->sequence)); | ||
| 686 | sp->hdr.serial = | 691 | sp->hdr.serial = |
| 687 | htonl(atomic_inc_return(&conn->serial)); | 692 | htonl(atomic_inc_return(&conn->serial)); |
| 688 | sp->hdr.type = RXRPC_PACKET_TYPE_DATA; | 693 | sp->hdr.type = RXRPC_PACKET_TYPE_DATA; |
| @@ -697,6 +702,8 @@ static int rxrpc_send_data(struct kiocb *iocb, | |||
| 697 | else if (CIRC_SPACE(call->acks_head, call->acks_tail, | 702 | else if (CIRC_SPACE(call->acks_head, call->acks_tail, |
| 698 | call->acks_winsz) > 1) | 703 | call->acks_winsz) > 1) |
| 699 | sp->hdr.flags |= RXRPC_MORE_PACKETS; | 704 | sp->hdr.flags |= RXRPC_MORE_PACKETS; |
| 705 | if (more && seq & 1) | ||
| 706 | sp->hdr.flags |= RXRPC_REQUEST_ACK; | ||
| 700 | 707 | ||
| 701 | ret = rxrpc_secure_packet( | 708 | ret = rxrpc_secure_packet( |
| 702 | call, skb, skb->mark, | 709 | call, skb, skb->mark, |
diff --git a/net/rxrpc/ar-recvmsg.c b/net/rxrpc/ar-recvmsg.c index 34b5490dde65..e9aaa65c0778 100644 --- a/net/rxrpc/ar-recvmsg.c +++ b/net/rxrpc/ar-recvmsg.c | |||
| @@ -180,16 +180,7 @@ int rxrpc_recvmsg(struct kiocb *iocb, struct socket *sock, | |||
| 180 | if (copy > len - copied) | 180 | if (copy > len - copied) |
| 181 | copy = len - copied; | 181 | copy = len - copied; |
| 182 | 182 | ||
| 183 | if (skb->ip_summed == CHECKSUM_UNNECESSARY || | 183 | ret = skb_copy_datagram_iovec(skb, offset, msg->msg_iov, copy); |
| 184 | skb->ip_summed == CHECKSUM_PARTIAL) { | ||
| 185 | ret = skb_copy_datagram_iovec(skb, offset, | ||
| 186 | msg->msg_iov, copy); | ||
| 187 | } else { | ||
| 188 | ret = skb_copy_and_csum_datagram_iovec(skb, offset, | ||
| 189 | msg->msg_iov); | ||
| 190 | if (ret == -EINVAL) | ||
| 191 | goto csum_copy_error; | ||
| 192 | } | ||
| 193 | 184 | ||
| 194 | if (ret < 0) | 185 | if (ret < 0) |
| 195 | goto copy_error; | 186 | goto copy_error; |
| @@ -348,20 +339,6 @@ copy_error: | |||
| 348 | _leave(" = %d", ret); | 339 | _leave(" = %d", ret); |
| 349 | return ret; | 340 | return ret; |
| 350 | 341 | ||
| 351 | csum_copy_error: | ||
| 352 | _debug("csum error"); | ||
| 353 | release_sock(&rx->sk); | ||
| 354 | if (continue_call) | ||
| 355 | rxrpc_put_call(continue_call); | ||
| 356 | rxrpc_kill_skb(skb); | ||
| 357 | if (!(flags & MSG_PEEK)) { | ||
| 358 | if (skb_dequeue(&rx->sk.sk_receive_queue) != skb) | ||
| 359 | BUG(); | ||
| 360 | } | ||
| 361 | skb_kill_datagram(&rx->sk, skb, flags); | ||
| 362 | rxrpc_put_call(call); | ||
| 363 | return -EAGAIN; | ||
| 364 | |||
| 365 | wait_interrupted: | 342 | wait_interrupted: |
| 366 | ret = sock_intr_errno(timeo); | 343 | ret = sock_intr_errno(timeo); |
| 367 | wait_error: | 344 | wait_error: |
diff --git a/net/rxrpc/ar-skbuff.c b/net/rxrpc/ar-skbuff.c index de755e04d29c..4cfab49e329d 100644 --- a/net/rxrpc/ar-skbuff.c +++ b/net/rxrpc/ar-skbuff.c | |||
| @@ -83,9 +83,14 @@ static void rxrpc_hard_ACK_data(struct rxrpc_call *call, | |||
| 83 | rxrpc_request_final_ACK(call); | 83 | rxrpc_request_final_ACK(call); |
| 84 | } else if (atomic_dec_and_test(&call->ackr_not_idle) && | 84 | } else if (atomic_dec_and_test(&call->ackr_not_idle) && |
| 85 | test_and_clear_bit(RXRPC_CALL_TX_SOFT_ACK, &call->flags)) { | 85 | test_and_clear_bit(RXRPC_CALL_TX_SOFT_ACK, &call->flags)) { |
| 86 | /* We previously soft-ACK'd some received packets that have now | ||
| 87 | * been consumed, so send a hard-ACK if no more packets are | ||
| 88 | * immediately forthcoming to allow the transmitter to free up | ||
| 89 | * its Tx bufferage. | ||
| 90 | */ | ||
| 86 | _debug("send Rx idle ACK"); | 91 | _debug("send Rx idle ACK"); |
| 87 | __rxrpc_propose_ACK(call, RXRPC_ACK_IDLE, sp->hdr.serial, | 92 | __rxrpc_propose_ACK(call, RXRPC_ACK_IDLE, sp->hdr.serial, |
| 88 | true); | 93 | false); |
| 89 | } | 94 | } |
| 90 | 95 | ||
| 91 | spin_unlock_bh(&call->lock); | 96 | spin_unlock_bh(&call->lock); |
diff --git a/net/rxrpc/ar-transport.c b/net/rxrpc/ar-transport.c index 92df566930b9..1976dec84f29 100644 --- a/net/rxrpc/ar-transport.c +++ b/net/rxrpc/ar-transport.c | |||
| @@ -17,11 +17,15 @@ | |||
| 17 | #include <net/af_rxrpc.h> | 17 | #include <net/af_rxrpc.h> |
| 18 | #include "ar-internal.h" | 18 | #include "ar-internal.h" |
| 19 | 19 | ||
| 20 | /* | ||
| 21 | * Time after last use at which transport record is cleaned up. | ||
| 22 | */ | ||
| 23 | unsigned rxrpc_transport_expiry = 3600 * 24; | ||
| 24 | |||
| 20 | static void rxrpc_transport_reaper(struct work_struct *work); | 25 | static void rxrpc_transport_reaper(struct work_struct *work); |
| 21 | 26 | ||
| 22 | static LIST_HEAD(rxrpc_transports); | 27 | static LIST_HEAD(rxrpc_transports); |
| 23 | static DEFINE_RWLOCK(rxrpc_transport_lock); | 28 | static DEFINE_RWLOCK(rxrpc_transport_lock); |
| 24 | static unsigned long rxrpc_transport_timeout = 3600 * 24; | ||
| 25 | static DECLARE_DELAYED_WORK(rxrpc_transport_reap, rxrpc_transport_reaper); | 29 | static DECLARE_DELAYED_WORK(rxrpc_transport_reap, rxrpc_transport_reaper); |
| 26 | 30 | ||
| 27 | /* | 31 | /* |
| @@ -235,7 +239,7 @@ static void rxrpc_transport_reaper(struct work_struct *work) | |||
| 235 | if (likely(atomic_read(&trans->usage) > 0)) | 239 | if (likely(atomic_read(&trans->usage) > 0)) |
| 236 | continue; | 240 | continue; |
| 237 | 241 | ||
| 238 | reap_time = trans->put_time + rxrpc_transport_timeout; | 242 | reap_time = trans->put_time + rxrpc_transport_expiry; |
| 239 | if (reap_time <= now) | 243 | if (reap_time <= now) |
| 240 | list_move_tail(&trans->link, &graveyard); | 244 | list_move_tail(&trans->link, &graveyard); |
| 241 | else if (reap_time < earliest) | 245 | else if (reap_time < earliest) |
| @@ -271,7 +275,7 @@ void __exit rxrpc_destroy_all_transports(void) | |||
| 271 | { | 275 | { |
| 272 | _enter(""); | 276 | _enter(""); |
| 273 | 277 | ||
| 274 | rxrpc_transport_timeout = 0; | 278 | rxrpc_transport_expiry = 0; |
| 275 | cancel_delayed_work(&rxrpc_transport_reap); | 279 | cancel_delayed_work(&rxrpc_transport_reap); |
| 276 | rxrpc_queue_delayed_work(&rxrpc_transport_reap, 0); | 280 | rxrpc_queue_delayed_work(&rxrpc_transport_reap, 0); |
| 277 | 281 | ||
diff --git a/net/rxrpc/sysctl.c b/net/rxrpc/sysctl.c new file mode 100644 index 000000000000..50a98a910eb1 --- /dev/null +++ b/net/rxrpc/sysctl.c | |||
| @@ -0,0 +1,146 @@ | |||
| 1 | /* sysctls for configuring RxRPC operating parameters | ||
| 2 | * | ||
| 3 | * Copyright (C) 2014 Red Hat, Inc. All Rights Reserved. | ||
| 4 | * Written by David Howells (dhowells@redhat.com) | ||
| 5 | * | ||
| 6 | * This program is free software; you can redistribute it and/or | ||
| 7 | * modify it under the terms of the GNU General Public Licence | ||
| 8 | * as published by the Free Software Foundation; either version | ||
| 9 | * 2 of the Licence, or (at your option) any later version. | ||
| 10 | */ | ||
| 11 | |||
| 12 | #include <linux/sysctl.h> | ||
| 13 | #include <net/sock.h> | ||
| 14 | #include <net/af_rxrpc.h> | ||
| 15 | #include "ar-internal.h" | ||
| 16 | |||
| 17 | static struct ctl_table_header *rxrpc_sysctl_reg_table; | ||
| 18 | static const unsigned zero = 0; | ||
| 19 | static const unsigned one = 1; | ||
| 20 | static const unsigned four = 4; | ||
| 21 | static const unsigned n_65535 = 65535; | ||
| 22 | static const unsigned n_max_acks = RXRPC_MAXACKS; | ||
| 23 | |||
| 24 | /* | ||
| 25 | * RxRPC operating parameters. | ||
| 26 | * | ||
| 27 | * See Documentation/networking/rxrpc.txt and the variable definitions for more | ||
| 28 | * information on the individual parameters. | ||
| 29 | */ | ||
| 30 | static struct ctl_table rxrpc_sysctl_table[] = { | ||
| 31 | /* Values measured in milliseconds */ | ||
| 32 | { | ||
| 33 | .procname = "req_ack_delay", | ||
| 34 | .data = &rxrpc_requested_ack_delay, | ||
| 35 | .maxlen = sizeof(unsigned), | ||
| 36 | .mode = 0644, | ||
| 37 | .proc_handler = proc_dointvec_ms_jiffies, | ||
| 38 | .extra1 = (void *)&zero, | ||
| 39 | }, | ||
| 40 | { | ||
| 41 | .procname = "soft_ack_delay", | ||
| 42 | .data = &rxrpc_soft_ack_delay, | ||
| 43 | .maxlen = sizeof(unsigned), | ||
| 44 | .mode = 0644, | ||
| 45 | .proc_handler = proc_dointvec_ms_jiffies, | ||
| 46 | .extra1 = (void *)&one, | ||
| 47 | }, | ||
| 48 | { | ||
| 49 | .procname = "idle_ack_delay", | ||
| 50 | .data = &rxrpc_idle_ack_delay, | ||
| 51 | .maxlen = sizeof(unsigned), | ||
| 52 | .mode = 0644, | ||
| 53 | .proc_handler = proc_dointvec_ms_jiffies, | ||
| 54 | .extra1 = (void *)&one, | ||
| 55 | }, | ||
| 56 | { | ||
| 57 | .procname = "resend_timeout", | ||
| 58 | .data = &rxrpc_resend_timeout, | ||
| 59 | .maxlen = sizeof(unsigned), | ||
| 60 | .mode = 0644, | ||
| 61 | .proc_handler = proc_dointvec_ms_jiffies, | ||
| 62 | .extra1 = (void *)&one, | ||
| 63 | }, | ||
| 64 | |||
| 65 | /* Values measured in seconds but used in jiffies */ | ||
| 66 | { | ||
| 67 | .procname = "max_call_lifetime", | ||
| 68 | .data = &rxrpc_max_call_lifetime, | ||
| 69 | .maxlen = sizeof(unsigned), | ||
| 70 | .mode = 0644, | ||
| 71 | .proc_handler = proc_dointvec_jiffies, | ||
| 72 | .extra1 = (void *)&one, | ||
| 73 | }, | ||
| 74 | { | ||
| 75 | .procname = "dead_call_expiry", | ||
| 76 | .data = &rxrpc_dead_call_expiry, | ||
| 77 | .maxlen = sizeof(unsigned), | ||
| 78 | .mode = 0644, | ||
| 79 | .proc_handler = proc_dointvec_jiffies, | ||
| 80 | .extra1 = (void *)&one, | ||
| 81 | }, | ||
| 82 | |||
| 83 | /* Values measured in seconds */ | ||
| 84 | { | ||
| 85 | .procname = "connection_expiry", | ||
| 86 | .data = &rxrpc_connection_expiry, | ||
| 87 | .maxlen = sizeof(unsigned), | ||
| 88 | .mode = 0644, | ||
| 89 | .proc_handler = proc_dointvec_minmax, | ||
| 90 | .extra1 = (void *)&one, | ||
| 91 | }, | ||
| 92 | { | ||
| 93 | .procname = "transport_expiry", | ||
| 94 | .data = &rxrpc_transport_expiry, | ||
| 95 | .maxlen = sizeof(unsigned), | ||
| 96 | .mode = 0644, | ||
| 97 | .proc_handler = proc_dointvec_minmax, | ||
| 98 | .extra1 = (void *)&one, | ||
| 99 | }, | ||
| 100 | |||
| 101 | /* Non-time values */ | ||
| 102 | { | ||
| 103 | .procname = "rx_window_size", | ||
| 104 | .data = &rxrpc_rx_window_size, | ||
| 105 | .maxlen = sizeof(unsigned), | ||
| 106 | .mode = 0644, | ||
| 107 | .proc_handler = proc_dointvec_minmax, | ||
| 108 | .extra1 = (void *)&one, | ||
| 109 | .extra2 = (void *)&n_max_acks, | ||
| 110 | }, | ||
| 111 | { | ||
| 112 | .procname = "rx_mtu", | ||
| 113 | .data = &rxrpc_rx_mtu, | ||
| 114 | .maxlen = sizeof(unsigned), | ||
| 115 | .mode = 0644, | ||
| 116 | .proc_handler = proc_dointvec_minmax, | ||
| 117 | .extra1 = (void *)&one, | ||
| 118 | .extra1 = (void *)&n_65535, | ||
| 119 | }, | ||
| 120 | { | ||
| 121 | .procname = "rx_jumbo_max", | ||
| 122 | .data = &rxrpc_rx_jumbo_max, | ||
| 123 | .maxlen = sizeof(unsigned), | ||
| 124 | .mode = 0644, | ||
| 125 | .proc_handler = proc_dointvec_minmax, | ||
| 126 | .extra1 = (void *)&one, | ||
| 127 | .extra2 = (void *)&four, | ||
| 128 | }, | ||
| 129 | |||
| 130 | { } | ||
| 131 | }; | ||
| 132 | |||
| 133 | int __init rxrpc_sysctl_init(void) | ||
| 134 | { | ||
| 135 | rxrpc_sysctl_reg_table = register_net_sysctl(&init_net, "net/rxrpc", | ||
| 136 | rxrpc_sysctl_table); | ||
| 137 | if (!rxrpc_sysctl_reg_table) | ||
| 138 | return -ENOMEM; | ||
| 139 | return 0; | ||
| 140 | } | ||
| 141 | |||
| 142 | void rxrpc_sysctl_exit(void) | ||
| 143 | { | ||
| 144 | if (rxrpc_sysctl_reg_table) | ||
| 145 | unregister_net_sysctl_table(rxrpc_sysctl_reg_table); | ||
| 146 | } | ||
diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 72bdc7166345..8a5ba5add4bc 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c | |||
| @@ -27,8 +27,11 @@ | |||
| 27 | #include <net/act_api.h> | 27 | #include <net/act_api.h> |
| 28 | #include <net/netlink.h> | 28 | #include <net/netlink.h> |
| 29 | 29 | ||
| 30 | void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo) | 30 | void tcf_hash_destroy(struct tc_action *a) |
| 31 | { | 31 | { |
| 32 | struct tcf_common *p = a->priv; | ||
| 33 | struct tcf_hashinfo *hinfo = a->ops->hinfo; | ||
| 34 | |||
| 32 | spin_lock_bh(&hinfo->lock); | 35 | spin_lock_bh(&hinfo->lock); |
| 33 | hlist_del(&p->tcfc_head); | 36 | hlist_del(&p->tcfc_head); |
| 34 | spin_unlock_bh(&hinfo->lock); | 37 | spin_unlock_bh(&hinfo->lock); |
| @@ -42,18 +45,22 @@ void tcf_hash_destroy(struct tcf_common *p, struct tcf_hashinfo *hinfo) | |||
| 42 | } | 45 | } |
| 43 | EXPORT_SYMBOL(tcf_hash_destroy); | 46 | EXPORT_SYMBOL(tcf_hash_destroy); |
| 44 | 47 | ||
| 45 | int tcf_hash_release(struct tcf_common *p, int bind, | 48 | int tcf_hash_release(struct tc_action *a, int bind) |
| 46 | struct tcf_hashinfo *hinfo) | ||
| 47 | { | 49 | { |
| 50 | struct tcf_common *p = a->priv; | ||
| 48 | int ret = 0; | 51 | int ret = 0; |
| 49 | 52 | ||
| 50 | if (p) { | 53 | if (p) { |
| 51 | if (bind) | 54 | if (bind) |
| 52 | p->tcfc_bindcnt--; | 55 | p->tcfc_bindcnt--; |
| 56 | else if (p->tcfc_bindcnt > 0) | ||
| 57 | return -EPERM; | ||
| 53 | 58 | ||
| 54 | p->tcfc_refcnt--; | 59 | p->tcfc_refcnt--; |
| 55 | if (p->tcfc_bindcnt <= 0 && p->tcfc_refcnt <= 0) { | 60 | if (p->tcfc_bindcnt <= 0 && p->tcfc_refcnt <= 0) { |
| 56 | tcf_hash_destroy(p, hinfo); | 61 | if (a->ops->cleanup) |
| 62 | a->ops->cleanup(a, bind); | ||
| 63 | tcf_hash_destroy(a); | ||
| 57 | ret = 1; | 64 | ret = 1; |
| 58 | } | 65 | } |
| 59 | } | 66 | } |
| @@ -118,6 +125,7 @@ static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a) | |||
| 118 | struct tcf_common *p; | 125 | struct tcf_common *p; |
| 119 | struct nlattr *nest; | 126 | struct nlattr *nest; |
| 120 | int i = 0, n_i = 0; | 127 | int i = 0, n_i = 0; |
| 128 | int ret = -EINVAL; | ||
| 121 | 129 | ||
| 122 | nest = nla_nest_start(skb, a->order); | 130 | nest = nla_nest_start(skb, a->order); |
| 123 | if (nest == NULL) | 131 | if (nest == NULL) |
| @@ -127,10 +135,13 @@ static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a) | |||
| 127 | for (i = 0; i < (hinfo->hmask + 1); i++) { | 135 | for (i = 0; i < (hinfo->hmask + 1); i++) { |
| 128 | head = &hinfo->htab[tcf_hash(i, hinfo->hmask)]; | 136 | head = &hinfo->htab[tcf_hash(i, hinfo->hmask)]; |
| 129 | hlist_for_each_entry_safe(p, n, head, tcfc_head) { | 137 | hlist_for_each_entry_safe(p, n, head, tcfc_head) { |
| 130 | if (ACT_P_DELETED == tcf_hash_release(p, 0, hinfo)) { | 138 | a->priv = p; |
| 139 | ret = tcf_hash_release(a, 0); | ||
| 140 | if (ret == ACT_P_DELETED) { | ||
| 131 | module_put(a->ops->owner); | 141 | module_put(a->ops->owner); |
| 132 | n_i++; | 142 | n_i++; |
| 133 | } | 143 | } else if (ret < 0) |
| 144 | goto nla_put_failure; | ||
| 134 | } | 145 | } |
| 135 | } | 146 | } |
| 136 | if (nla_put_u32(skb, TCA_FCNT, n_i)) | 147 | if (nla_put_u32(skb, TCA_FCNT, n_i)) |
| @@ -140,7 +151,7 @@ static int tcf_del_walker(struct sk_buff *skb, struct tc_action *a) | |||
| 140 | return n_i; | 151 | return n_i; |
| 141 | nla_put_failure: | 152 | nla_put_failure: |
| 142 | nla_nest_cancel(skb, nest); | 153 | nla_nest_cancel(skb, nest); |
| 143 | return -EINVAL; | 154 | return ret; |
| 144 | } | 155 | } |
| 145 | 156 | ||
| 146 | static int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb, | 157 | static int tcf_generic_walker(struct sk_buff *skb, struct netlink_callback *cb, |
| @@ -198,7 +209,7 @@ int tcf_hash_search(struct tc_action *a, u32 index) | |||
| 198 | } | 209 | } |
| 199 | EXPORT_SYMBOL(tcf_hash_search); | 210 | EXPORT_SYMBOL(tcf_hash_search); |
| 200 | 211 | ||
| 201 | struct tcf_common *tcf_hash_check(u32 index, struct tc_action *a, int bind) | 212 | int tcf_hash_check(u32 index, struct tc_action *a, int bind) |
| 202 | { | 213 | { |
| 203 | struct tcf_hashinfo *hinfo = a->ops->hinfo; | 214 | struct tcf_hashinfo *hinfo = a->ops->hinfo; |
| 204 | struct tcf_common *p = NULL; | 215 | struct tcf_common *p = NULL; |
| @@ -207,19 +218,30 @@ struct tcf_common *tcf_hash_check(u32 index, struct tc_action *a, int bind) | |||
| 207 | p->tcfc_bindcnt++; | 218 | p->tcfc_bindcnt++; |
| 208 | p->tcfc_refcnt++; | 219 | p->tcfc_refcnt++; |
| 209 | a->priv = p; | 220 | a->priv = p; |
| 221 | return 1; | ||
| 210 | } | 222 | } |
| 211 | return p; | 223 | return 0; |
| 212 | } | 224 | } |
| 213 | EXPORT_SYMBOL(tcf_hash_check); | 225 | EXPORT_SYMBOL(tcf_hash_check); |
| 214 | 226 | ||
| 215 | struct tcf_common *tcf_hash_create(u32 index, struct nlattr *est, | 227 | void tcf_hash_cleanup(struct tc_action *a, struct nlattr *est) |
| 216 | struct tc_action *a, int size, int bind) | 228 | { |
| 229 | struct tcf_common *pc = a->priv; | ||
| 230 | if (est) | ||
| 231 | gen_kill_estimator(&pc->tcfc_bstats, | ||
| 232 | &pc->tcfc_rate_est); | ||
| 233 | kfree_rcu(pc, tcfc_rcu); | ||
| 234 | } | ||
| 235 | EXPORT_SYMBOL(tcf_hash_cleanup); | ||
| 236 | |||
| 237 | int tcf_hash_create(u32 index, struct nlattr *est, struct tc_action *a, | ||
| 238 | int size, int bind) | ||
| 217 | { | 239 | { |
| 218 | struct tcf_hashinfo *hinfo = a->ops->hinfo; | 240 | struct tcf_hashinfo *hinfo = a->ops->hinfo; |
| 219 | struct tcf_common *p = kzalloc(size, GFP_KERNEL); | 241 | struct tcf_common *p = kzalloc(size, GFP_KERNEL); |
| 220 | 242 | ||
| 221 | if (unlikely(!p)) | 243 | if (unlikely(!p)) |
| 222 | return ERR_PTR(-ENOMEM); | 244 | return -ENOMEM; |
| 223 | p->tcfc_refcnt = 1; | 245 | p->tcfc_refcnt = 1; |
| 224 | if (bind) | 246 | if (bind) |
| 225 | p->tcfc_bindcnt = 1; | 247 | p->tcfc_bindcnt = 1; |
| @@ -234,17 +256,19 @@ struct tcf_common *tcf_hash_create(u32 index, struct nlattr *est, | |||
| 234 | &p->tcfc_lock, est); | 256 | &p->tcfc_lock, est); |
| 235 | if (err) { | 257 | if (err) { |
| 236 | kfree(p); | 258 | kfree(p); |
| 237 | return ERR_PTR(err); | 259 | return err; |
| 238 | } | 260 | } |
| 239 | } | 261 | } |
| 240 | 262 | ||
| 241 | a->priv = (void *) p; | 263 | a->priv = (void *) p; |
| 242 | return p; | 264 | return 0; |
| 243 | } | 265 | } |
| 244 | EXPORT_SYMBOL(tcf_hash_create); | 266 | EXPORT_SYMBOL(tcf_hash_create); |
| 245 | 267 | ||
| 246 | void tcf_hash_insert(struct tcf_common *p, struct tcf_hashinfo *hinfo) | 268 | void tcf_hash_insert(struct tc_action *a) |
| 247 | { | 269 | { |
| 270 | struct tcf_common *p = a->priv; | ||
| 271 | struct tcf_hashinfo *hinfo = a->ops->hinfo; | ||
| 248 | unsigned int h = tcf_hash(p->tcfc_index, hinfo->hmask); | 272 | unsigned int h = tcf_hash(p->tcfc_index, hinfo->hmask); |
| 249 | 273 | ||
| 250 | spin_lock_bh(&hinfo->lock); | 274 | spin_lock_bh(&hinfo->lock); |
| @@ -256,12 +280,13 @@ EXPORT_SYMBOL(tcf_hash_insert); | |||
| 256 | static LIST_HEAD(act_base); | 280 | static LIST_HEAD(act_base); |
| 257 | static DEFINE_RWLOCK(act_mod_lock); | 281 | static DEFINE_RWLOCK(act_mod_lock); |
| 258 | 282 | ||
| 259 | int tcf_register_action(struct tc_action_ops *act) | 283 | int tcf_register_action(struct tc_action_ops *act, unsigned int mask) |
| 260 | { | 284 | { |
| 261 | struct tc_action_ops *a; | 285 | struct tc_action_ops *a; |
| 286 | int err; | ||
| 262 | 287 | ||
| 263 | /* Must supply act, dump, cleanup and init */ | 288 | /* Must supply act, dump and init */ |
| 264 | if (!act->act || !act->dump || !act->cleanup || !act->init) | 289 | if (!act->act || !act->dump || !act->init) |
| 265 | return -EINVAL; | 290 | return -EINVAL; |
| 266 | 291 | ||
| 267 | /* Supply defaults */ | 292 | /* Supply defaults */ |
| @@ -270,10 +295,21 @@ int tcf_register_action(struct tc_action_ops *act) | |||
| 270 | if (!act->walk) | 295 | if (!act->walk) |
| 271 | act->walk = tcf_generic_walker; | 296 | act->walk = tcf_generic_walker; |
| 272 | 297 | ||
| 298 | act->hinfo = kmalloc(sizeof(struct tcf_hashinfo), GFP_KERNEL); | ||
| 299 | if (!act->hinfo) | ||
| 300 | return -ENOMEM; | ||
| 301 | err = tcf_hashinfo_init(act->hinfo, mask); | ||
| 302 | if (err) { | ||
| 303 | kfree(act->hinfo); | ||
| 304 | return err; | ||
| 305 | } | ||
| 306 | |||
| 273 | write_lock(&act_mod_lock); | 307 | write_lock(&act_mod_lock); |
| 274 | list_for_each_entry(a, &act_base, head) { | 308 | list_for_each_entry(a, &act_base, head) { |
| 275 | if (act->type == a->type || (strcmp(act->kind, a->kind) == 0)) { | 309 | if (act->type == a->type || (strcmp(act->kind, a->kind) == 0)) { |
| 276 | write_unlock(&act_mod_lock); | 310 | write_unlock(&act_mod_lock); |
| 311 | tcf_hashinfo_destroy(act->hinfo); | ||
| 312 | kfree(act->hinfo); | ||
| 277 | return -EEXIST; | 313 | return -EEXIST; |
| 278 | } | 314 | } |
| 279 | } | 315 | } |
| @@ -292,6 +328,8 @@ int tcf_unregister_action(struct tc_action_ops *act) | |||
| 292 | list_for_each_entry(a, &act_base, head) { | 328 | list_for_each_entry(a, &act_base, head) { |
| 293 | if (a == act) { | 329 | if (a == act) { |
| 294 | list_del(&act->head); | 330 | list_del(&act->head); |
| 331 | tcf_hashinfo_destroy(act->hinfo); | ||
| 332 | kfree(act->hinfo); | ||
| 295 | err = 0; | 333 | err = 0; |
| 296 | break; | 334 | break; |
| 297 | } | 335 | } |
| @@ -368,16 +406,21 @@ exec_done: | |||
| 368 | } | 406 | } |
| 369 | EXPORT_SYMBOL(tcf_action_exec); | 407 | EXPORT_SYMBOL(tcf_action_exec); |
| 370 | 408 | ||
| 371 | void tcf_action_destroy(struct list_head *actions, int bind) | 409 | int tcf_action_destroy(struct list_head *actions, int bind) |
| 372 | { | 410 | { |
| 373 | struct tc_action *a, *tmp; | 411 | struct tc_action *a, *tmp; |
| 412 | int ret = 0; | ||
| 374 | 413 | ||
| 375 | list_for_each_entry_safe(a, tmp, actions, list) { | 414 | list_for_each_entry_safe(a, tmp, actions, list) { |
| 376 | if (a->ops->cleanup(a, bind) == ACT_P_DELETED) | 415 | ret = tcf_hash_release(a, bind); |
| 416 | if (ret == ACT_P_DELETED) | ||
| 377 | module_put(a->ops->owner); | 417 | module_put(a->ops->owner); |
| 418 | else if (ret < 0) | ||
| 419 | return ret; | ||
| 378 | list_del(&a->list); | 420 | list_del(&a->list); |
| 379 | kfree(a); | 421 | kfree(a); |
| 380 | } | 422 | } |
| 423 | return ret; | ||
| 381 | } | 424 | } |
| 382 | 425 | ||
| 383 | int | 426 | int |
| @@ -642,6 +685,20 @@ act_get_notify(struct net *net, u32 portid, struct nlmsghdr *n, | |||
| 642 | return rtnl_unicast(skb, net, portid); | 685 | return rtnl_unicast(skb, net, portid); |
| 643 | } | 686 | } |
| 644 | 687 | ||
| 688 | static struct tc_action *create_a(int i) | ||
| 689 | { | ||
| 690 | struct tc_action *act; | ||
| 691 | |||
| 692 | act = kzalloc(sizeof(*act), GFP_KERNEL); | ||
| 693 | if (act == NULL) { | ||
| 694 | pr_debug("create_a: failed to alloc!\n"); | ||
| 695 | return NULL; | ||
| 696 | } | ||
| 697 | act->order = i; | ||
| 698 | INIT_LIST_HEAD(&act->list); | ||
| 699 | return act; | ||
| 700 | } | ||
| 701 | |||
| 645 | static struct tc_action * | 702 | static struct tc_action * |
| 646 | tcf_action_get_1(struct nlattr *nla, struct nlmsghdr *n, u32 portid) | 703 | tcf_action_get_1(struct nlattr *nla, struct nlmsghdr *n, u32 portid) |
| 647 | { | 704 | { |
| @@ -661,11 +718,10 @@ tcf_action_get_1(struct nlattr *nla, struct nlmsghdr *n, u32 portid) | |||
| 661 | index = nla_get_u32(tb[TCA_ACT_INDEX]); | 718 | index = nla_get_u32(tb[TCA_ACT_INDEX]); |
| 662 | 719 | ||
| 663 | err = -ENOMEM; | 720 | err = -ENOMEM; |
| 664 | a = kzalloc(sizeof(struct tc_action), GFP_KERNEL); | 721 | a = create_a(0); |
| 665 | if (a == NULL) | 722 | if (a == NULL) |
| 666 | goto err_out; | 723 | goto err_out; |
| 667 | 724 | ||
| 668 | INIT_LIST_HEAD(&a->list); | ||
| 669 | err = -EINVAL; | 725 | err = -EINVAL; |
| 670 | a->ops = tc_lookup_action(tb[TCA_ACT_KIND]); | 726 | a->ops = tc_lookup_action(tb[TCA_ACT_KIND]); |
| 671 | if (a->ops == NULL) /* could happen in batch of actions */ | 727 | if (a->ops == NULL) /* could happen in batch of actions */ |
| @@ -695,20 +751,6 @@ static void cleanup_a(struct list_head *actions) | |||
| 695 | } | 751 | } |
| 696 | } | 752 | } |
| 697 | 753 | ||
| 698 | static struct tc_action *create_a(int i) | ||
| 699 | { | ||
| 700 | struct tc_action *act; | ||
| 701 | |||
| 702 | act = kzalloc(sizeof(*act), GFP_KERNEL); | ||
| 703 | if (act == NULL) { | ||
| 704 | pr_debug("create_a: failed to alloc!\n"); | ||
| 705 | return NULL; | ||
| 706 | } | ||
| 707 | act->order = i; | ||
| 708 | INIT_LIST_HEAD(&act->list); | ||
| 709 | return act; | ||
| 710 | } | ||
| 711 | |||
| 712 | static int tca_action_flush(struct net *net, struct nlattr *nla, | 754 | static int tca_action_flush(struct net *net, struct nlattr *nla, |
| 713 | struct nlmsghdr *n, u32 portid) | 755 | struct nlmsghdr *n, u32 portid) |
| 714 | { | 756 | { |
| @@ -720,18 +762,12 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, | |||
| 720 | struct nlattr *nest; | 762 | struct nlattr *nest; |
| 721 | struct nlattr *tb[TCA_ACT_MAX + 1]; | 763 | struct nlattr *tb[TCA_ACT_MAX + 1]; |
| 722 | struct nlattr *kind; | 764 | struct nlattr *kind; |
| 723 | struct tc_action *a = create_a(0); | 765 | struct tc_action a; |
| 724 | int err = -ENOMEM; | 766 | int err = -ENOMEM; |
| 725 | 767 | ||
| 726 | if (a == NULL) { | ||
| 727 | pr_debug("tca_action_flush: couldnt create tc_action\n"); | ||
| 728 | return err; | ||
| 729 | } | ||
| 730 | |||
| 731 | skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); | 768 | skb = alloc_skb(NLMSG_GOODSIZE, GFP_KERNEL); |
| 732 | if (!skb) { | 769 | if (!skb) { |
| 733 | pr_debug("tca_action_flush: failed skb alloc\n"); | 770 | pr_debug("tca_action_flush: failed skb alloc\n"); |
| 734 | kfree(a); | ||
| 735 | return err; | 771 | return err; |
| 736 | } | 772 | } |
| 737 | 773 | ||
| @@ -743,8 +779,10 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, | |||
| 743 | 779 | ||
| 744 | err = -EINVAL; | 780 | err = -EINVAL; |
| 745 | kind = tb[TCA_ACT_KIND]; | 781 | kind = tb[TCA_ACT_KIND]; |
| 746 | a->ops = tc_lookup_action(kind); | 782 | memset(&a, 0, sizeof(struct tc_action)); |
| 747 | if (a->ops == NULL) /*some idjot trying to flush unknown action */ | 783 | INIT_LIST_HEAD(&a.list); |
| 784 | a.ops = tc_lookup_action(kind); | ||
| 785 | if (a.ops == NULL) /*some idjot trying to flush unknown action */ | ||
| 748 | goto err_out; | 786 | goto err_out; |
| 749 | 787 | ||
| 750 | nlh = nlmsg_put(skb, portid, n->nlmsg_seq, RTM_DELACTION, sizeof(*t), 0); | 788 | nlh = nlmsg_put(skb, portid, n->nlmsg_seq, RTM_DELACTION, sizeof(*t), 0); |
| @@ -759,7 +797,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, | |||
| 759 | if (nest == NULL) | 797 | if (nest == NULL) |
| 760 | goto out_module_put; | 798 | goto out_module_put; |
| 761 | 799 | ||
| 762 | err = a->ops->walk(skb, &dcb, RTM_DELACTION, a); | 800 | err = a.ops->walk(skb, &dcb, RTM_DELACTION, &a); |
| 763 | if (err < 0) | 801 | if (err < 0) |
| 764 | goto out_module_put; | 802 | goto out_module_put; |
| 765 | if (err == 0) | 803 | if (err == 0) |
| @@ -769,8 +807,7 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, | |||
| 769 | 807 | ||
| 770 | nlh->nlmsg_len = skb_tail_pointer(skb) - b; | 808 | nlh->nlmsg_len = skb_tail_pointer(skb) - b; |
| 771 | nlh->nlmsg_flags |= NLM_F_ROOT; | 809 | nlh->nlmsg_flags |= NLM_F_ROOT; |
| 772 | module_put(a->ops->owner); | 810 | module_put(a.ops->owner); |
| 773 | kfree(a); | ||
| 774 | err = rtnetlink_send(skb, net, portid, RTNLGRP_TC, | 811 | err = rtnetlink_send(skb, net, portid, RTNLGRP_TC, |
| 775 | n->nlmsg_flags & NLM_F_ECHO); | 812 | n->nlmsg_flags & NLM_F_ECHO); |
| 776 | if (err > 0) | 813 | if (err > 0) |
| @@ -779,11 +816,10 @@ static int tca_action_flush(struct net *net, struct nlattr *nla, | |||
| 779 | return err; | 816 | return err; |
| 780 | 817 | ||
| 781 | out_module_put: | 818 | out_module_put: |
| 782 | module_put(a->ops->owner); | 819 | module_put(a.ops->owner); |
| 783 | err_out: | 820 | err_out: |
| 784 | noflush_out: | 821 | noflush_out: |
| 785 | kfree_skb(skb); | 822 | kfree_skb(skb); |
| 786 | kfree(a); | ||
| 787 | return err; | 823 | return err; |
| 788 | } | 824 | } |
| 789 | 825 | ||
| @@ -805,7 +841,11 @@ tcf_del_notify(struct net *net, struct nlmsghdr *n, struct list_head *actions, | |||
| 805 | } | 841 | } |
| 806 | 842 | ||
| 807 | /* now do the delete */ | 843 | /* now do the delete */ |
| 808 | tcf_action_destroy(actions, 0); | 844 | ret = tcf_action_destroy(actions, 0); |
| 845 | if (ret < 0) { | ||
| 846 | kfree_skb(skb); | ||
| 847 | return ret; | ||
| 848 | } | ||
| 809 | 849 | ||
| 810 | ret = rtnetlink_send(skb, net, portid, RTNLGRP_TC, | 850 | ret = rtnetlink_send(skb, net, portid, RTNLGRP_TC, |
| 811 | n->nlmsg_flags & NLM_F_ECHO); | 851 | n->nlmsg_flags & NLM_F_ECHO); |
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c index 2210187c45c2..edbf40dac709 100644 --- a/net/sched/act_csum.c +++ b/net/sched/act_csum.c | |||
| @@ -37,7 +37,6 @@ | |||
| 37 | #include <net/tc_act/tc_csum.h> | 37 | #include <net/tc_act/tc_csum.h> |
| 38 | 38 | ||
| 39 | #define CSUM_TAB_MASK 15 | 39 | #define CSUM_TAB_MASK 15 |
| 40 | static struct tcf_hashinfo csum_hash_info; | ||
| 41 | 40 | ||
| 42 | static const struct nla_policy csum_policy[TCA_CSUM_MAX + 1] = { | 41 | static const struct nla_policy csum_policy[TCA_CSUM_MAX + 1] = { |
| 43 | [TCA_CSUM_PARMS] = { .len = sizeof(struct tc_csum), }, | 42 | [TCA_CSUM_PARMS] = { .len = sizeof(struct tc_csum), }, |
| @@ -48,7 +47,6 @@ static int tcf_csum_init(struct net *n, struct nlattr *nla, struct nlattr *est, | |||
| 48 | { | 47 | { |
| 49 | struct nlattr *tb[TCA_CSUM_MAX + 1]; | 48 | struct nlattr *tb[TCA_CSUM_MAX + 1]; |
| 50 | struct tc_csum *parm; | 49 | struct tc_csum *parm; |
| 51 | struct tcf_common *pc; | ||
| 52 | struct tcf_csum *p; | 50 | struct tcf_csum *p; |
| 53 | int ret = 0, err; | 51 | int ret = 0, err; |
| 54 | 52 | ||
| @@ -63,38 +61,31 @@ static int tcf_csum_init(struct net *n, struct nlattr *nla, struct nlattr *est, | |||
| 63 | return -EINVAL; | 61 | return -EINVAL; |
| 64 | parm = nla_data(tb[TCA_CSUM_PARMS]); | 62 | parm = nla_data(tb[TCA_CSUM_PARMS]); |
| 65 | 63 | ||
| 66 | pc = tcf_hash_check(parm->index, a, bind); | 64 | if (!tcf_hash_check(parm->index, a, bind)) { |
| 67 | if (!pc) { | 65 | ret = tcf_hash_create(parm->index, est, a, sizeof(*p), bind); |
| 68 | pc = tcf_hash_create(parm->index, est, a, sizeof(*p), bind); | 66 | if (ret) |
| 69 | if (IS_ERR(pc)) | 67 | return ret; |
| 70 | return PTR_ERR(pc); | ||
| 71 | ret = ACT_P_CREATED; | 68 | ret = ACT_P_CREATED; |
| 72 | } else { | 69 | } else { |
| 73 | if (bind)/* dont override defaults */ | 70 | if (bind)/* dont override defaults */ |
| 74 | return 0; | 71 | return 0; |
| 75 | tcf_hash_release(pc, bind, a->ops->hinfo); | 72 | tcf_hash_release(a, bind); |
| 76 | if (!ovr) | 73 | if (!ovr) |
| 77 | return -EEXIST; | 74 | return -EEXIST; |
| 78 | } | 75 | } |
| 79 | 76 | ||
| 80 | p = to_tcf_csum(pc); | 77 | p = to_tcf_csum(a); |
| 81 | spin_lock_bh(&p->tcf_lock); | 78 | spin_lock_bh(&p->tcf_lock); |
| 82 | p->tcf_action = parm->action; | 79 | p->tcf_action = parm->action; |
| 83 | p->update_flags = parm->update_flags; | 80 | p->update_flags = parm->update_flags; |
| 84 | spin_unlock_bh(&p->tcf_lock); | 81 | spin_unlock_bh(&p->tcf_lock); |
| 85 | 82 | ||
| 86 | if (ret == ACT_P_CREATED) | 83 | if (ret == ACT_P_CREATED) |
| 87 | tcf_hash_insert(pc, a->ops->hinfo); | 84 | tcf_hash_insert(a); |
| 88 | 85 | ||
| 89 | return ret; | 86 | return ret; |
| 90 | } | 87 | } |
| 91 | 88 | ||
| 92 | static int tcf_csum_cleanup(struct tc_action *a, int bind) | ||
| 93 | { | ||
| 94 | struct tcf_csum *p = a->priv; | ||
| 95 | return tcf_hash_release(&p->common, bind, &csum_hash_info); | ||
| 96 | } | ||
| 97 | |||
| 98 | /** | 89 | /** |
| 99 | * tcf_csum_skb_nextlayer - Get next layer pointer | 90 | * tcf_csum_skb_nextlayer - Get next layer pointer |
| 100 | * @skb: sk_buff to use | 91 | * @skb: sk_buff to use |
| @@ -569,12 +560,10 @@ nla_put_failure: | |||
| 569 | 560 | ||
| 570 | static struct tc_action_ops act_csum_ops = { | 561 | static struct tc_action_ops act_csum_ops = { |
| 571 | .kind = "csum", | 562 | .kind = "csum", |
| 572 | .hinfo = &csum_hash_info, | ||
| 573 | .type = TCA_ACT_CSUM, | 563 | .type = TCA_ACT_CSUM, |
| 574 | .owner = THIS_MODULE, | 564 | .owner = THIS_MODULE, |
| 575 | .act = tcf_csum, | 565 | .act = tcf_csum, |
| 576 | .dump = tcf_csum_dump, | 566 | .dump = tcf_csum_dump, |
| 577 | .cleanup = tcf_csum_cleanup, | ||
| 578 | .init = tcf_csum_init, | 567 | .init = tcf_csum_init, |
| 579 | }; | 568 | }; |
| 580 | 569 | ||
| @@ -583,11 +572,7 @@ MODULE_LICENSE("GPL"); | |||
| 583 | 572 | ||
| 584 | static int __init csum_init_module(void) | 573 | static int __init csum_init_module(void) |
| 585 | { | 574 | { |
| 586 | int err = tcf_hashinfo_init(&csum_hash_info, CSUM_TAB_MASK); | 575 | return tcf_register_action(&act_csum_ops, CSUM_TAB_MASK); |
| 587 | if (err) | ||
| 588 | return err; | ||
| 589 | |||
| 590 | return tcf_register_action(&act_csum_ops); | ||
| 591 | } | 576 | } |
| 592 | 577 | ||
| 593 | static void __exit csum_cleanup_module(void) | 578 | static void __exit csum_cleanup_module(void) |
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c index a0eed30d5811..d6bcbd9f7791 100644 --- a/net/sched/act_gact.c +++ b/net/sched/act_gact.c | |||
| @@ -24,7 +24,6 @@ | |||
| 24 | #include <net/tc_act/tc_gact.h> | 24 | #include <net/tc_act/tc_gact.h> |
| 25 | 25 | ||
| 26 | #define GACT_TAB_MASK 15 | 26 | #define GACT_TAB_MASK 15 |
| 27 | static struct tcf_hashinfo gact_hash_info; | ||
| 28 | 27 | ||
| 29 | #ifdef CONFIG_GACT_PROB | 28 | #ifdef CONFIG_GACT_PROB |
| 30 | static int gact_net_rand(struct tcf_gact *gact) | 29 | static int gact_net_rand(struct tcf_gact *gact) |
| @@ -57,7 +56,6 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla, | |||
| 57 | struct nlattr *tb[TCA_GACT_MAX + 1]; | 56 | struct nlattr *tb[TCA_GACT_MAX + 1]; |
| 58 | struct tc_gact *parm; | 57 | struct tc_gact *parm; |
| 59 | struct tcf_gact *gact; | 58 | struct tcf_gact *gact; |
| 60 | struct tcf_common *pc; | ||
| 61 | int ret = 0; | 59 | int ret = 0; |
| 62 | int err; | 60 | int err; |
| 63 | #ifdef CONFIG_GACT_PROB | 61 | #ifdef CONFIG_GACT_PROB |
| @@ -86,21 +84,20 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla, | |||
| 86 | } | 84 | } |
| 87 | #endif | 85 | #endif |
| 88 | 86 | ||
| 89 | pc = tcf_hash_check(parm->index, a, bind); | 87 | if (!tcf_hash_check(parm->index, a, bind)) { |
| 90 | if (!pc) { | 88 | ret = tcf_hash_create(parm->index, est, a, sizeof(*gact), bind); |
| 91 | pc = tcf_hash_create(parm->index, est, a, sizeof(*gact), bind); | 89 | if (ret) |
| 92 | if (IS_ERR(pc)) | 90 | return ret; |
| 93 | return PTR_ERR(pc); | ||
| 94 | ret = ACT_P_CREATED; | 91 | ret = ACT_P_CREATED; |
| 95 | } else { | 92 | } else { |
| 96 | if (bind)/* dont override defaults */ | 93 | if (bind)/* dont override defaults */ |
| 97 | return 0; | 94 | return 0; |
| 98 | tcf_hash_release(pc, bind, a->ops->hinfo); | 95 | tcf_hash_release(a, bind); |
| 99 | if (!ovr) | 96 | if (!ovr) |
| 100 | return -EEXIST; | 97 | return -EEXIST; |
| 101 | } | 98 | } |
| 102 | 99 | ||
| 103 | gact = to_gact(pc); | 100 | gact = to_gact(a); |
| 104 | 101 | ||
| 105 | spin_lock_bh(&gact->tcf_lock); | 102 | spin_lock_bh(&gact->tcf_lock); |
| 106 | gact->tcf_action = parm->action; | 103 | gact->tcf_action = parm->action; |
| @@ -113,19 +110,10 @@ static int tcf_gact_init(struct net *net, struct nlattr *nla, | |||
| 113 | #endif | 110 | #endif |
| 114 | spin_unlock_bh(&gact->tcf_lock); | 111 | spin_unlock_bh(&gact->tcf_lock); |
| 115 | if (ret == ACT_P_CREATED) | 112 | if (ret == ACT_P_CREATED) |
| 116 | tcf_hash_insert(pc, a->ops->hinfo); | 113 | tcf_hash_insert(a); |
| 117 | return ret; | 114 | return ret; |
| 118 | } | 115 | } |
| 119 | 116 | ||
| 120 | static int tcf_gact_cleanup(struct tc_action *a, int bind) | ||
| 121 | { | ||
| 122 | struct tcf_gact *gact = a->priv; | ||
| 123 | |||
| 124 | if (gact) | ||
| 125 | return tcf_hash_release(&gact->common, bind, a->ops->hinfo); | ||
| 126 | return 0; | ||
| 127 | } | ||
| 128 | |||
| 129 | static int tcf_gact(struct sk_buff *skb, const struct tc_action *a, | 117 | static int tcf_gact(struct sk_buff *skb, const struct tc_action *a, |
| 130 | struct tcf_result *res) | 118 | struct tcf_result *res) |
| 131 | { | 119 | { |
| @@ -191,12 +179,10 @@ nla_put_failure: | |||
| 191 | 179 | ||
| 192 | static struct tc_action_ops act_gact_ops = { | 180 | static struct tc_action_ops act_gact_ops = { |
| 193 | .kind = "gact", | 181 | .kind = "gact", |
| 194 | .hinfo = &gact_hash_info, | ||
| 195 | .type = TCA_ACT_GACT, | 182 | .type = TCA_ACT_GACT, |
| 196 | .owner = THIS_MODULE, | 183 | .owner = THIS_MODULE, |
| 197 | .act = tcf_gact, | 184 | .act = tcf_gact, |
| 198 | .dump = tcf_gact_dump, | 185 | .dump = tcf_gact_dump, |
| 199 | .cleanup = tcf_gact_cleanup, | ||
| 200 | .init = tcf_gact_init, | 186 | .init = tcf_gact_init, |
| 201 | }; | 187 | }; |
| 202 | 188 | ||
| @@ -206,21 +192,17 @@ MODULE_LICENSE("GPL"); | |||
| 206 | 192 | ||
| 207 | static int __init gact_init_module(void) | 193 | static int __init gact_init_module(void) |
| 208 | { | 194 | { |
| 209 | int err = tcf_hashinfo_init(&gact_hash_info, GACT_TAB_MASK); | ||
| 210 | if (err) | ||
| 211 | return err; | ||
| 212 | #ifdef CONFIG_GACT_PROB | 195 | #ifdef CONFIG_GACT_PROB |
| 213 | pr_info("GACT probability on\n"); | 196 | pr_info("GACT probability on\n"); |
| 214 | #else | 197 | #else |
| 215 | pr_info("GACT probability NOT on\n"); | 198 | pr_info("GACT probability NOT on\n"); |
| 216 | #endif | 199 | #endif |
| 217 | return tcf_register_action(&act_gact_ops); | 200 | return tcf_register_action(&act_gact_ops, GACT_TAB_MASK); |
| 218 | } | 201 | } |
| 219 | 202 | ||
| 220 | static void __exit gact_cleanup_module(void) | 203 | static void __exit gact_cleanup_module(void) |
| 221 | { | 204 | { |
| 222 | tcf_unregister_action(&act_gact_ops); | 205 | tcf_unregister_action(&act_gact_ops); |
| 223 | tcf_hashinfo_destroy(&gact_hash_info); | ||
| 224 | } | 206 | } |
| 225 | 207 | ||
| 226 | module_init(gact_init_module); | 208 | module_init(gact_init_module); |
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c index 0a6d62174027..8a64a0734aee 100644 --- a/net/sched/act_ipt.c +++ b/net/sched/act_ipt.c | |||
| @@ -29,7 +29,6 @@ | |||
| 29 | 29 | ||
| 30 | 30 | ||
| 31 | #define IPT_TAB_MASK 15 | 31 | #define IPT_TAB_MASK 15 |
| 32 | static struct tcf_hashinfo ipt_hash_info; | ||
| 33 | 32 | ||
| 34 | static int ipt_init_target(struct xt_entry_target *t, char *table, unsigned int hook) | 33 | static int ipt_init_target(struct xt_entry_target *t, char *table, unsigned int hook) |
| 35 | { | 34 | { |
| @@ -69,22 +68,12 @@ static void ipt_destroy_target(struct xt_entry_target *t) | |||
| 69 | module_put(par.target->me); | 68 | module_put(par.target->me); |
| 70 | } | 69 | } |
| 71 | 70 | ||
| 72 | static int tcf_ipt_release(struct tcf_ipt *ipt, int bind) | 71 | static void tcf_ipt_release(struct tc_action *a, int bind) |
| 73 | { | 72 | { |
| 74 | int ret = 0; | 73 | struct tcf_ipt *ipt = to_ipt(a); |
| 75 | if (ipt) { | 74 | ipt_destroy_target(ipt->tcfi_t); |
| 76 | if (bind) | 75 | kfree(ipt->tcfi_tname); |
| 77 | ipt->tcf_bindcnt--; | 76 | kfree(ipt->tcfi_t); |
| 78 | ipt->tcf_refcnt--; | ||
| 79 | if (ipt->tcf_bindcnt <= 0 && ipt->tcf_refcnt <= 0) { | ||
| 80 | ipt_destroy_target(ipt->tcfi_t); | ||
| 81 | kfree(ipt->tcfi_tname); | ||
| 82 | kfree(ipt->tcfi_t); | ||
| 83 | tcf_hash_destroy(&ipt->common, &ipt_hash_info); | ||
| 84 | ret = ACT_P_DELETED; | ||
| 85 | } | ||
| 86 | } | ||
| 87 | return ret; | ||
| 88 | } | 77 | } |
| 89 | 78 | ||
| 90 | static const struct nla_policy ipt_policy[TCA_IPT_MAX + 1] = { | 79 | static const struct nla_policy ipt_policy[TCA_IPT_MAX + 1] = { |
| @@ -99,7 +88,6 @@ static int tcf_ipt_init(struct net *net, struct nlattr *nla, struct nlattr *est, | |||
| 99 | { | 88 | { |
| 100 | struct nlattr *tb[TCA_IPT_MAX + 1]; | 89 | struct nlattr *tb[TCA_IPT_MAX + 1]; |
| 101 | struct tcf_ipt *ipt; | 90 | struct tcf_ipt *ipt; |
| 102 | struct tcf_common *pc; | ||
| 103 | struct xt_entry_target *td, *t; | 91 | struct xt_entry_target *td, *t; |
| 104 | char *tname; | 92 | char *tname; |
| 105 | int ret = 0, err; | 93 | int ret = 0, err; |
| @@ -125,21 +113,20 @@ static int tcf_ipt_init(struct net *net, struct nlattr *nla, struct nlattr *est, | |||
| 125 | if (tb[TCA_IPT_INDEX] != NULL) | 113 | if (tb[TCA_IPT_INDEX] != NULL) |
| 126 | index = nla_get_u32(tb[TCA_IPT_INDEX]); | 114 | index = nla_get_u32(tb[TCA_IPT_INDEX]); |
| 127 | 115 | ||
| 128 | pc = tcf_hash_check(index, a, bind); | 116 | if (!tcf_hash_check(index, a, bind) ) { |
| 129 | if (!pc) { | 117 | ret = tcf_hash_create(index, est, a, sizeof(*ipt), bind); |
| 130 | pc = tcf_hash_create(index, est, a, sizeof(*ipt), bind); | 118 | if (ret) |
| 131 | if (IS_ERR(pc)) | 119 | return ret; |
| 132 | return PTR_ERR(pc); | ||
| 133 | ret = ACT_P_CREATED; | 120 | ret = ACT_P_CREATED; |
| 134 | } else { | 121 | } else { |
| 135 | if (bind)/* dont override defaults */ | 122 | if (bind)/* dont override defaults */ |
| 136 | return 0; | 123 | return 0; |
| 137 | tcf_ipt_release(to_ipt(pc), bind); | 124 | tcf_hash_release(a, bind); |
| 138 | 125 | ||
| 139 | if (!ovr) | 126 | if (!ovr) |
| 140 | return -EEXIST; | 127 | return -EEXIST; |
| 141 | } | 128 | } |
| 142 | ipt = to_ipt(pc); | 129 | ipt = to_ipt(a); |
| 143 | 130 | ||
| 144 | hook = nla_get_u32(tb[TCA_IPT_HOOK]); | 131 | hook = nla_get_u32(tb[TCA_IPT_HOOK]); |
| 145 | 132 | ||
| @@ -170,7 +157,7 @@ static int tcf_ipt_init(struct net *net, struct nlattr *nla, struct nlattr *est, | |||
| 170 | ipt->tcfi_hook = hook; | 157 | ipt->tcfi_hook = hook; |
| 171 | spin_unlock_bh(&ipt->tcf_lock); | 158 | spin_unlock_bh(&ipt->tcf_lock); |
| 172 | if (ret == ACT_P_CREATED) | 159 | if (ret == ACT_P_CREATED) |
| 173 | tcf_hash_insert(pc, a->ops->hinfo); | 160 | tcf_hash_insert(a); |
| 174 | return ret; | 161 | return ret; |
| 175 | 162 | ||
| 176 | err3: | 163 | err3: |
| @@ -178,21 +165,11 @@ err3: | |||
| 178 | err2: | 165 | err2: |
| 179 | kfree(tname); | 166 | kfree(tname); |
| 180 | err1: | 167 | err1: |
| 181 | if (ret == ACT_P_CREATED) { | 168 | if (ret == ACT_P_CREATED) |
| 182 | if (est) | 169 | tcf_hash_cleanup(a, est); |
| 183 | gen_kill_estimator(&pc->tcfc_bstats, | ||
| 184 | &pc->tcfc_rate_est); | ||
| 185 | kfree_rcu(pc, tcfc_rcu); | ||
| 186 | } | ||
| 187 | return err; | 170 | return err; |
| 188 | } | 171 | } |
| 189 | 172 | ||
| 190 | static int tcf_ipt_cleanup(struct tc_action *a, int bind) | ||
| 191 | { | ||
| 192 | struct tcf_ipt *ipt = a->priv; | ||
| 193 | return tcf_ipt_release(ipt, bind); | ||
| 194 | } | ||
| 195 | |||
| 196 | static int tcf_ipt(struct sk_buff *skb, const struct tc_action *a, | 173 | static int tcf_ipt(struct sk_buff *skb, const struct tc_action *a, |
| 197 | struct tcf_result *res) | 174 | struct tcf_result *res) |
| 198 | { | 175 | { |
| @@ -284,23 +261,21 @@ nla_put_failure: | |||
| 284 | 261 | ||
| 285 | static struct tc_action_ops act_ipt_ops = { | 262 | static struct tc_action_ops act_ipt_ops = { |
| 286 | .kind = "ipt", | 263 | .kind = "ipt", |
| 287 | .hinfo = &ipt_hash_info, | ||
| 288 | .type = TCA_ACT_IPT, | 264 | .type = TCA_ACT_IPT, |
| 289 | .owner = THIS_MODULE, | 265 | .owner = THIS_MODULE, |
| 290 | .act = tcf_ipt, | 266 | .act = tcf_ipt, |
| 291 | .dump = tcf_ipt_dump, | 267 | .dump = tcf_ipt_dump, |
| 292 | .cleanup = tcf_ipt_cleanup, | 268 | .cleanup = tcf_ipt_release, |
| 293 | .init = tcf_ipt_init, | 269 | .init = tcf_ipt_init, |
| 294 | }; | 270 | }; |
| 295 | 271 | ||
| 296 | static struct tc_action_ops act_xt_ops = { | 272 | static struct tc_action_ops act_xt_ops = { |
| 297 | .kind = "xt", | 273 | .kind = "xt", |
| 298 | .hinfo = &ipt_hash_info, | ||
| 299 | .type = TCA_ACT_XT, | 274 | .type = TCA_ACT_XT, |
| 300 | .owner = THIS_MODULE, | 275 | .owner = THIS_MODULE, |
| 301 | .act = tcf_ipt, | 276 | .act = tcf_ipt, |
| 302 | .dump = tcf_ipt_dump, | 277 | .dump = tcf_ipt_dump, |
| 303 | .cleanup = tcf_ipt_cleanup, | 278 | .cleanup = tcf_ipt_release, |
| 304 | .init = tcf_ipt_init, | 279 | .init = tcf_ipt_init, |
| 305 | }; | 280 | }; |
| 306 | 281 | ||
| @@ -311,20 +286,16 @@ MODULE_ALIAS("act_xt"); | |||
| 311 | 286 | ||
| 312 | static int __init ipt_init_module(void) | 287 | static int __init ipt_init_module(void) |
| 313 | { | 288 | { |
| 314 | int ret1, ret2, err; | 289 | int ret1, ret2; |
| 315 | err = tcf_hashinfo_init(&ipt_hash_info, IPT_TAB_MASK); | ||
| 316 | if (err) | ||
| 317 | return err; | ||
| 318 | 290 | ||
| 319 | ret1 = tcf_register_action(&act_xt_ops); | 291 | ret1 = tcf_register_action(&act_xt_ops, IPT_TAB_MASK); |
| 320 | if (ret1 < 0) | 292 | if (ret1 < 0) |
| 321 | printk("Failed to load xt action\n"); | 293 | printk("Failed to load xt action\n"); |
| 322 | ret2 = tcf_register_action(&act_ipt_ops); | 294 | ret2 = tcf_register_action(&act_ipt_ops, IPT_TAB_MASK); |
| 323 | if (ret2 < 0) | 295 | if (ret2 < 0) |
| 324 | printk("Failed to load ipt action\n"); | 296 | printk("Failed to load ipt action\n"); |
| 325 | 297 | ||
| 326 | if (ret1 < 0 && ret2 < 0) { | 298 | if (ret1 < 0 && ret2 < 0) { |
| 327 | tcf_hashinfo_destroy(&ipt_hash_info); | ||
| 328 | return ret1; | 299 | return ret1; |
| 329 | } else | 300 | } else |
| 330 | return 0; | 301 | return 0; |
| @@ -334,7 +305,6 @@ static void __exit ipt_cleanup_module(void) | |||
| 334 | { | 305 | { |
| 335 | tcf_unregister_action(&act_xt_ops); | 306 | tcf_unregister_action(&act_xt_ops); |
| 336 | tcf_unregister_action(&act_ipt_ops); | 307 | tcf_unregister_action(&act_ipt_ops); |
| 337 | tcf_hashinfo_destroy(&ipt_hash_info); | ||
| 338 | } | 308 | } |
| 339 | 309 | ||
| 340 | module_init(ipt_init_module); | 310 | module_init(ipt_init_module); |
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c index 0b2c6d39d396..4f912c0e225b 100644 --- a/net/sched/act_mirred.c +++ b/net/sched/act_mirred.c | |||
| @@ -31,23 +31,13 @@ | |||
| 31 | 31 | ||
| 32 | #define MIRRED_TAB_MASK 7 | 32 | #define MIRRED_TAB_MASK 7 |
| 33 | static LIST_HEAD(mirred_list); | 33 | static LIST_HEAD(mirred_list); |
| 34 | static struct tcf_hashinfo mirred_hash_info; | ||
| 35 | 34 | ||
| 36 | static int tcf_mirred_release(struct tcf_mirred *m, int bind) | 35 | static void tcf_mirred_release(struct tc_action *a, int bind) |
| 37 | { | 36 | { |
| 38 | if (m) { | 37 | struct tcf_mirred *m = to_mirred(a); |
| 39 | if (bind) | 38 | list_del(&m->tcfm_list); |
| 40 | m->tcf_bindcnt--; | 39 | if (m->tcfm_dev) |
| 41 | m->tcf_refcnt--; | 40 | dev_put(m->tcfm_dev); |
| 42 | if (!m->tcf_bindcnt && m->tcf_refcnt <= 0) { | ||
| 43 | list_del(&m->tcfm_list); | ||
| 44 | if (m->tcfm_dev) | ||
| 45 | dev_put(m->tcfm_dev); | ||
| 46 | tcf_hash_destroy(&m->common, &mirred_hash_info); | ||
| 47 | return 1; | ||
| 48 | } | ||
| 49 | } | ||
| 50 | return 0; | ||
| 51 | } | 41 | } |
| 52 | 42 | ||
| 53 | static const struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = { | 43 | static const struct nla_policy mirred_policy[TCA_MIRRED_MAX + 1] = { |
| @@ -61,7 +51,6 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, | |||
| 61 | struct nlattr *tb[TCA_MIRRED_MAX + 1]; | 51 | struct nlattr *tb[TCA_MIRRED_MAX + 1]; |
| 62 | struct tc_mirred *parm; | 52 | struct tc_mirred *parm; |
| 63 | struct tcf_mirred *m; | 53 | struct tcf_mirred *m; |
| 64 | struct tcf_common *pc; | ||
| 65 | struct net_device *dev; | 54 | struct net_device *dev; |
| 66 | int ret, ok_push = 0; | 55 | int ret, ok_push = 0; |
| 67 | 56 | ||
| @@ -101,21 +90,20 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, | |||
| 101 | dev = NULL; | 90 | dev = NULL; |
| 102 | } | 91 | } |
| 103 | 92 | ||
| 104 | pc = tcf_hash_check(parm->index, a, bind); | 93 | if (!tcf_hash_check(parm->index, a, bind)) { |
| 105 | if (!pc) { | ||
| 106 | if (dev == NULL) | 94 | if (dev == NULL) |
| 107 | return -EINVAL; | 95 | return -EINVAL; |
| 108 | pc = tcf_hash_create(parm->index, est, a, sizeof(*m), bind); | 96 | ret = tcf_hash_create(parm->index, est, a, sizeof(*m), bind); |
| 109 | if (IS_ERR(pc)) | 97 | if (ret) |
| 110 | return PTR_ERR(pc); | 98 | return ret; |
| 111 | ret = ACT_P_CREATED; | 99 | ret = ACT_P_CREATED; |
| 112 | } else { | 100 | } else { |
| 113 | if (!ovr) { | 101 | if (!ovr) { |
| 114 | tcf_mirred_release(to_mirred(pc), bind); | 102 | tcf_hash_release(a, bind); |
| 115 | return -EEXIST; | 103 | return -EEXIST; |
| 116 | } | 104 | } |
| 117 | } | 105 | } |
| 118 | m = to_mirred(pc); | 106 | m = to_mirred(a); |
| 119 | 107 | ||
| 120 | spin_lock_bh(&m->tcf_lock); | 108 | spin_lock_bh(&m->tcf_lock); |
| 121 | m->tcf_action = parm->action; | 109 | m->tcf_action = parm->action; |
| @@ -131,21 +119,12 @@ static int tcf_mirred_init(struct net *net, struct nlattr *nla, | |||
| 131 | spin_unlock_bh(&m->tcf_lock); | 119 | spin_unlock_bh(&m->tcf_lock); |
| 132 | if (ret == ACT_P_CREATED) { | 120 | if (ret == ACT_P_CREATED) { |
| 133 | list_add(&m->tcfm_list, &mirred_list); | 121 | list_add(&m->tcfm_list, &mirred_list); |
| 134 | tcf_hash_insert(pc, a->ops->hinfo); | 122 | tcf_hash_insert(a); |
| 135 | } | 123 | } |
| 136 | 124 | ||
| 137 | return ret; | 125 | return ret; |
| 138 | } | 126 | } |
| 139 | 127 | ||
| 140 | static int tcf_mirred_cleanup(struct tc_action *a, int bind) | ||
| 141 | { | ||
| 142 | struct tcf_mirred *m = a->priv; | ||
| 143 | |||
| 144 | if (m) | ||
| 145 | return tcf_mirred_release(m, bind); | ||
| 146 | return 0; | ||
| 147 | } | ||
| 148 | |||
| 149 | static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a, | 128 | static int tcf_mirred(struct sk_buff *skb, const struct tc_action *a, |
| 150 | struct tcf_result *res) | 129 | struct tcf_result *res) |
| 151 | { | 130 | { |
| @@ -254,12 +233,11 @@ static struct notifier_block mirred_device_notifier = { | |||
| 254 | 233 | ||
| 255 | static struct tc_action_ops act_mirred_ops = { | 234 | static struct tc_action_ops act_mirred_ops = { |
| 256 | .kind = "mirred", | 235 | .kind = "mirred", |
| 257 | .hinfo = &mirred_hash_info, | ||
| 258 | .type = TCA_ACT_MIRRED, | 236 | .type = TCA_ACT_MIRRED, |
| 259 | .owner = THIS_MODULE, | 237 | .owner = THIS_MODULE, |
| 260 | .act = tcf_mirred, | 238 | .act = tcf_mirred, |
| 261 | .dump = tcf_mirred_dump, | 239 | .dump = tcf_mirred_dump, |
| 262 | .cleanup = tcf_mirred_cleanup, | 240 | .cleanup = tcf_mirred_release, |
| 263 | .init = tcf_mirred_init, | 241 | .init = tcf_mirred_init, |
| 264 | }; | 242 | }; |
| 265 | 243 | ||
| @@ -273,19 +251,13 @@ static int __init mirred_init_module(void) | |||
| 273 | if (err) | 251 | if (err) |
| 274 | return err; | 252 | return err; |
| 275 | 253 | ||
| 276 | err = tcf_hashinfo_init(&mirred_hash_info, MIRRED_TAB_MASK); | ||
| 277 | if (err) { | ||
| 278 | unregister_netdevice_notifier(&mirred_device_notifier); | ||
| 279 | return err; | ||
| 280 | } | ||
| 281 | pr_info("Mirror/redirect action on\n"); | 254 | pr_info("Mirror/redirect action on\n"); |
| 282 | return tcf_register_action(&act_mirred_ops); | 255 | return tcf_register_action(&act_mirred_ops, MIRRED_TAB_MASK); |
| 283 | } | 256 | } |
| 284 | 257 | ||
| 285 | static void __exit mirred_cleanup_module(void) | 258 | static void __exit mirred_cleanup_module(void) |
| 286 | { | 259 | { |
| 287 | tcf_unregister_action(&act_mirred_ops); | 260 | tcf_unregister_action(&act_mirred_ops); |
| 288 | tcf_hashinfo_destroy(&mirred_hash_info); | ||
| 289 | unregister_netdevice_notifier(&mirred_device_notifier); | 261 | unregister_netdevice_notifier(&mirred_device_notifier); |
| 290 | } | 262 | } |
| 291 | 263 | ||
diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c index 81f0404bb335..270a030d5fd0 100644 --- a/net/sched/act_nat.c +++ b/net/sched/act_nat.c | |||
| @@ -31,8 +31,6 @@ | |||
| 31 | 31 | ||
| 32 | #define NAT_TAB_MASK 15 | 32 | #define NAT_TAB_MASK 15 |
| 33 | 33 | ||
| 34 | static struct tcf_hashinfo nat_hash_info; | ||
| 35 | |||
| 36 | static const struct nla_policy nat_policy[TCA_NAT_MAX + 1] = { | 34 | static const struct nla_policy nat_policy[TCA_NAT_MAX + 1] = { |
| 37 | [TCA_NAT_PARMS] = { .len = sizeof(struct tc_nat) }, | 35 | [TCA_NAT_PARMS] = { .len = sizeof(struct tc_nat) }, |
| 38 | }; | 36 | }; |
| @@ -44,7 +42,6 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est, | |||
| 44 | struct tc_nat *parm; | 42 | struct tc_nat *parm; |
| 45 | int ret = 0, err; | 43 | int ret = 0, err; |
| 46 | struct tcf_nat *p; | 44 | struct tcf_nat *p; |
| 47 | struct tcf_common *pc; | ||
| 48 | 45 | ||
| 49 | if (nla == NULL) | 46 | if (nla == NULL) |
| 50 | return -EINVAL; | 47 | return -EINVAL; |
| @@ -57,20 +54,19 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est, | |||
| 57 | return -EINVAL; | 54 | return -EINVAL; |
| 58 | parm = nla_data(tb[TCA_NAT_PARMS]); | 55 | parm = nla_data(tb[TCA_NAT_PARMS]); |
| 59 | 56 | ||
| 60 | pc = tcf_hash_check(parm->index, a, bind); | 57 | if (!tcf_hash_check(parm->index, a, bind)) { |
| 61 | if (!pc) { | 58 | ret = tcf_hash_create(parm->index, est, a, sizeof(*p), bind); |
| 62 | pc = tcf_hash_create(parm->index, est, a, sizeof(*p), bind); | 59 | if (ret) |
| 63 | if (IS_ERR(pc)) | 60 | return ret; |
| 64 | return PTR_ERR(pc); | ||
| 65 | ret = ACT_P_CREATED; | 61 | ret = ACT_P_CREATED; |
| 66 | } else { | 62 | } else { |
| 67 | if (bind) | 63 | if (bind) |
| 68 | return 0; | 64 | return 0; |
| 69 | tcf_hash_release(pc, bind, a->ops->hinfo); | 65 | tcf_hash_release(a, bind); |
| 70 | if (!ovr) | 66 | if (!ovr) |
| 71 | return -EEXIST; | 67 | return -EEXIST; |
| 72 | } | 68 | } |
| 73 | p = to_tcf_nat(pc); | 69 | p = to_tcf_nat(a); |
| 74 | 70 | ||
| 75 | spin_lock_bh(&p->tcf_lock); | 71 | spin_lock_bh(&p->tcf_lock); |
| 76 | p->old_addr = parm->old_addr; | 72 | p->old_addr = parm->old_addr; |
| @@ -82,18 +78,11 @@ static int tcf_nat_init(struct net *net, struct nlattr *nla, struct nlattr *est, | |||
| 82 | spin_unlock_bh(&p->tcf_lock); | 78 | spin_unlock_bh(&p->tcf_lock); |
| 83 | 79 | ||
| 84 | if (ret == ACT_P_CREATED) | 80 | if (ret == ACT_P_CREATED) |
| 85 | tcf_hash_insert(pc, a->ops->hinfo); | 81 | tcf_hash_insert(a); |
| 86 | 82 | ||
| 87 | return ret; | 83 | return ret; |
| 88 | } | 84 | } |
| 89 | 85 | ||
| 90 | static int tcf_nat_cleanup(struct tc_action *a, int bind) | ||
| 91 | { | ||
| 92 | struct tcf_nat *p = a->priv; | ||
| 93 | |||
| 94 | return tcf_hash_release(&p->common, bind, &nat_hash_info); | ||
| 95 | } | ||
| 96 | |||
| 97 | static int tcf_nat(struct sk_buff *skb, const struct tc_action *a, | 86 | static int tcf_nat(struct sk_buff *skb, const struct tc_action *a, |
| 98 | struct tcf_result *res) | 87 | struct tcf_result *res) |
| 99 | { | 88 | { |
| @@ -293,12 +282,10 @@ nla_put_failure: | |||
| 293 | 282 | ||
| 294 | static struct tc_action_ops act_nat_ops = { | 283 | static struct tc_action_ops act_nat_ops = { |
| 295 | .kind = "nat", | 284 | .kind = "nat", |
| 296 | .hinfo = &nat_hash_info, | ||
| 297 | .type = TCA_ACT_NAT, | 285 | .type = TCA_ACT_NAT, |
| 298 | .owner = THIS_MODULE, | 286 | .owner = THIS_MODULE, |
| 299 | .act = tcf_nat, | 287 | .act = tcf_nat, |
| 300 | .dump = tcf_nat_dump, | 288 | .dump = tcf_nat_dump, |
| 301 | .cleanup = tcf_nat_cleanup, | ||
| 302 | .init = tcf_nat_init, | 289 | .init = tcf_nat_init, |
| 303 | }; | 290 | }; |
| 304 | 291 | ||
| @@ -307,16 +294,12 @@ MODULE_LICENSE("GPL"); | |||
| 307 | 294 | ||
| 308 | static int __init nat_init_module(void) | 295 | static int __init nat_init_module(void) |
| 309 | { | 296 | { |
| 310 | int err = tcf_hashinfo_init(&nat_hash_info, NAT_TAB_MASK); | 297 | return tcf_register_action(&act_nat_ops, NAT_TAB_MASK); |
| 311 | if (err) | ||
| 312 | return err; | ||
| 313 | return tcf_register_action(&act_nat_ops); | ||
| 314 | } | 298 | } |
| 315 | 299 | ||
| 316 | static void __exit nat_cleanup_module(void) | 300 | static void __exit nat_cleanup_module(void) |
| 317 | { | 301 | { |
| 318 | tcf_unregister_action(&act_nat_ops); | 302 | tcf_unregister_action(&act_nat_ops); |
| 319 | tcf_hashinfo_destroy(&nat_hash_info); | ||
| 320 | } | 303 | } |
| 321 | 304 | ||
| 322 | module_init(nat_init_module); | 305 | module_init(nat_init_module); |
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c index be3f0f6875bb..5f9bcb2e080b 100644 --- a/net/sched/act_pedit.c +++ b/net/sched/act_pedit.c | |||
| @@ -25,8 +25,6 @@ | |||
| 25 | 25 | ||
| 26 | #define PEDIT_TAB_MASK 15 | 26 | #define PEDIT_TAB_MASK 15 |
| 27 | 27 | ||
| 28 | static struct tcf_hashinfo pedit_hash_info; | ||
| 29 | |||
| 30 | static const struct nla_policy pedit_policy[TCA_PEDIT_MAX + 1] = { | 28 | static const struct nla_policy pedit_policy[TCA_PEDIT_MAX + 1] = { |
| 31 | [TCA_PEDIT_PARMS] = { .len = sizeof(struct tc_pedit) }, | 29 | [TCA_PEDIT_PARMS] = { .len = sizeof(struct tc_pedit) }, |
| 32 | }; | 30 | }; |
| @@ -39,7 +37,6 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla, | |||
| 39 | struct tc_pedit *parm; | 37 | struct tc_pedit *parm; |
| 40 | int ret = 0, err; | 38 | int ret = 0, err; |
| 41 | struct tcf_pedit *p; | 39 | struct tcf_pedit *p; |
| 42 | struct tcf_common *pc; | ||
| 43 | struct tc_pedit_key *keys = NULL; | 40 | struct tc_pedit_key *keys = NULL; |
| 44 | int ksize; | 41 | int ksize; |
| 45 | 42 | ||
| @@ -57,26 +54,22 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla, | |||
| 57 | if (nla_len(tb[TCA_PEDIT_PARMS]) < sizeof(*parm) + ksize) | 54 | if (nla_len(tb[TCA_PEDIT_PARMS]) < sizeof(*parm) + ksize) |
| 58 | return -EINVAL; | 55 | return -EINVAL; |
| 59 | 56 | ||
| 60 | pc = tcf_hash_check(parm->index, a, bind); | 57 | if (!tcf_hash_check(parm->index, a, bind)) { |
| 61 | if (!pc) { | ||
| 62 | if (!parm->nkeys) | 58 | if (!parm->nkeys) |
| 63 | return -EINVAL; | 59 | return -EINVAL; |
| 64 | pc = tcf_hash_create(parm->index, est, a, sizeof(*p), bind); | 60 | ret = tcf_hash_create(parm->index, est, a, sizeof(*p), bind); |
| 65 | if (IS_ERR(pc)) | 61 | if (ret) |
| 66 | return PTR_ERR(pc); | 62 | return ret; |
| 67 | p = to_pedit(pc); | 63 | p = to_pedit(a); |
| 68 | keys = kmalloc(ksize, GFP_KERNEL); | 64 | keys = kmalloc(ksize, GFP_KERNEL); |
| 69 | if (keys == NULL) { | 65 | if (keys == NULL) { |
| 70 | if (est) | 66 | tcf_hash_cleanup(a, est); |
| 71 | gen_kill_estimator(&pc->tcfc_bstats, | ||
| 72 | &pc->tcfc_rate_est); | ||
| 73 | kfree_rcu(pc, tcfc_rcu); | ||
| 74 | return -ENOMEM; | 67 | return -ENOMEM; |
| 75 | } | 68 | } |
| 76 | ret = ACT_P_CREATED; | 69 | ret = ACT_P_CREATED; |
| 77 | } else { | 70 | } else { |
| 78 | p = to_pedit(pc); | 71 | p = to_pedit(a); |
| 79 | tcf_hash_release(pc, bind, a->ops->hinfo); | 72 | tcf_hash_release(a, bind); |
| 80 | if (bind) | 73 | if (bind) |
| 81 | return 0; | 74 | return 0; |
| 82 | if (!ovr) | 75 | if (!ovr) |
| @@ -100,22 +93,15 @@ static int tcf_pedit_init(struct net *net, struct nlattr *nla, | |||
| 100 | memcpy(p->tcfp_keys, parm->keys, ksize); | 93 | memcpy(p->tcfp_keys, parm->keys, ksize); |
| 101 | spin_unlock_bh(&p->tcf_lock); | 94 | spin_unlock_bh(&p->tcf_lock); |
| 102 | if (ret == ACT_P_CREATED) | 95 | if (ret == ACT_P_CREATED) |
| 103 | tcf_hash_insert(pc, a->ops->hinfo); | 96 | tcf_hash_insert(a); |
| 104 | return ret; | 97 | return ret; |
| 105 | } | 98 | } |
| 106 | 99 | ||
| 107 | static int tcf_pedit_cleanup(struct tc_action *a, int bind) | 100 | static void tcf_pedit_cleanup(struct tc_action *a, int bind) |
| 108 | { | 101 | { |
| 109 | struct tcf_pedit *p = a->priv; | 102 | struct tcf_pedit *p = a->priv; |
| 110 | 103 | struct tc_pedit_key *keys = p->tcfp_keys; | |
| 111 | if (p) { | 104 | kfree(keys); |
| 112 | struct tc_pedit_key *keys = p->tcfp_keys; | ||
| 113 | if (tcf_hash_release(&p->common, bind, &pedit_hash_info)) { | ||
| 114 | kfree(keys); | ||
| 115 | return 1; | ||
| 116 | } | ||
| 117 | } | ||
| 118 | return 0; | ||
| 119 | } | 105 | } |
| 120 | 106 | ||
| 121 | static int tcf_pedit(struct sk_buff *skb, const struct tc_action *a, | 107 | static int tcf_pedit(struct sk_buff *skb, const struct tc_action *a, |
| @@ -230,7 +216,6 @@ nla_put_failure: | |||
| 230 | 216 | ||
| 231 | static struct tc_action_ops act_pedit_ops = { | 217 | static struct tc_action_ops act_pedit_ops = { |
| 232 | .kind = "pedit", | 218 | .kind = "pedit", |
| 233 | .hinfo = &pedit_hash_info, | ||
| 234 | .type = TCA_ACT_PEDIT, | 219 | .type = TCA_ACT_PEDIT, |
| 235 | .owner = THIS_MODULE, | 220 | .owner = THIS_MODULE, |
| 236 | .act = tcf_pedit, | 221 | .act = tcf_pedit, |
| @@ -245,15 +230,11 @@ MODULE_LICENSE("GPL"); | |||
| 245 | 230 | ||
| 246 | static int __init pedit_init_module(void) | 231 | static int __init pedit_init_module(void) |
| 247 | { | 232 | { |
| 248 | int err = tcf_hashinfo_init(&pedit_hash_info, PEDIT_TAB_MASK); | 233 | return tcf_register_action(&act_pedit_ops, PEDIT_TAB_MASK); |
| 249 | if (err) | ||
| 250 | return err; | ||
| 251 | return tcf_register_action(&act_pedit_ops); | ||
| 252 | } | 234 | } |
| 253 | 235 | ||
| 254 | static void __exit pedit_cleanup_module(void) | 236 | static void __exit pedit_cleanup_module(void) |
| 255 | { | 237 | { |
| 256 | tcf_hashinfo_destroy(&pedit_hash_info); | ||
| 257 | tcf_unregister_action(&act_pedit_ops); | 238 | tcf_unregister_action(&act_pedit_ops); |
| 258 | } | 239 | } |
| 259 | 240 | ||
diff --git a/net/sched/act_police.c b/net/sched/act_police.c index 1778209a332f..0566e4606a4a 100644 --- a/net/sched/act_police.c +++ b/net/sched/act_police.c | |||
| @@ -41,7 +41,6 @@ struct tcf_police { | |||
| 41 | container_of(pc, struct tcf_police, common) | 41 | container_of(pc, struct tcf_police, common) |
| 42 | 42 | ||
| 43 | #define POL_TAB_MASK 15 | 43 | #define POL_TAB_MASK 15 |
| 44 | static struct tcf_hashinfo police_hash_info; | ||
| 45 | 44 | ||
| 46 | /* old policer structure from before tc actions */ | 45 | /* old policer structure from before tc actions */ |
| 47 | struct tc_police_compat { | 46 | struct tc_police_compat { |
| @@ -234,7 +233,7 @@ override: | |||
| 234 | 233 | ||
| 235 | police->tcfp_t_c = ktime_to_ns(ktime_get()); | 234 | police->tcfp_t_c = ktime_to_ns(ktime_get()); |
| 236 | police->tcf_index = parm->index ? parm->index : | 235 | police->tcf_index = parm->index ? parm->index : |
| 237 | tcf_hash_new_index(a->ops->hinfo); | 236 | tcf_hash_new_index(hinfo); |
| 238 | h = tcf_hash(police->tcf_index, POL_TAB_MASK); | 237 | h = tcf_hash(police->tcf_index, POL_TAB_MASK); |
| 239 | spin_lock_bh(&hinfo->lock); | 238 | spin_lock_bh(&hinfo->lock); |
| 240 | hlist_add_head(&police->tcf_head, &hinfo->htab[h]); | 239 | hlist_add_head(&police->tcf_head, &hinfo->htab[h]); |
| @@ -253,14 +252,6 @@ failure: | |||
| 253 | return err; | 252 | return err; |
| 254 | } | 253 | } |
| 255 | 254 | ||
| 256 | static int tcf_act_police_cleanup(struct tc_action *a, int bind) | ||
| 257 | { | ||
| 258 | struct tcf_police *p = a->priv; | ||
| 259 | if (p) | ||
| 260 | return tcf_hash_release(&p->common, bind, &police_hash_info); | ||
| 261 | return 0; | ||
| 262 | } | ||
| 263 | |||
| 264 | static int tcf_act_police(struct sk_buff *skb, const struct tc_action *a, | 255 | static int tcf_act_police(struct sk_buff *skb, const struct tc_action *a, |
| 265 | struct tcf_result *res) | 256 | struct tcf_result *res) |
| 266 | { | 257 | { |
| @@ -357,12 +348,10 @@ MODULE_LICENSE("GPL"); | |||
| 357 | 348 | ||
| 358 | static struct tc_action_ops act_police_ops = { | 349 | static struct tc_action_ops act_police_ops = { |
| 359 | .kind = "police", | 350 | .kind = "police", |
| 360 | .hinfo = &police_hash_info, | ||
| 361 | .type = TCA_ID_POLICE, | 351 | .type = TCA_ID_POLICE, |
| 362 | .owner = THIS_MODULE, | 352 | .owner = THIS_MODULE, |
| 363 | .act = tcf_act_police, | 353 | .act = tcf_act_police, |
| 364 | .dump = tcf_act_police_dump, | 354 | .dump = tcf_act_police_dump, |
| 365 | .cleanup = tcf_act_police_cleanup, | ||
| 366 | .init = tcf_act_police_locate, | 355 | .init = tcf_act_police_locate, |
| 367 | .walk = tcf_act_police_walker | 356 | .walk = tcf_act_police_walker |
| 368 | }; | 357 | }; |
| @@ -370,19 +359,12 @@ static struct tc_action_ops act_police_ops = { | |||
| 370 | static int __init | 359 | static int __init |
| 371 | police_init_module(void) | 360 | police_init_module(void) |
| 372 | { | 361 | { |
| 373 | int err = tcf_hashinfo_init(&police_hash_info, POL_TAB_MASK); | 362 | return tcf_register_action(&act_police_ops, POL_TAB_MASK); |
| 374 | if (err) | ||
| 375 | return err; | ||
| 376 | err = tcf_register_action(&act_police_ops); | ||
| 377 | if (err) | ||
| 378 | tcf_hashinfo_destroy(&police_hash_info); | ||
| 379 | return err; | ||
| 380 | } | 363 | } |
| 381 | 364 | ||
| 382 | static void __exit | 365 | static void __exit |
| 383 | police_cleanup_module(void) | 366 | police_cleanup_module(void) |
| 384 | { | 367 | { |
| 385 | tcf_hashinfo_destroy(&police_hash_info); | ||
| 386 | tcf_unregister_action(&act_police_ops); | 368 | tcf_unregister_action(&act_police_ops); |
| 387 | } | 369 | } |
| 388 | 370 | ||
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c index 8ef2f1fcbfba..992c2317ce88 100644 --- a/net/sched/act_simple.c +++ b/net/sched/act_simple.c | |||
| @@ -25,7 +25,6 @@ | |||
| 25 | #include <net/tc_act/tc_defact.h> | 25 | #include <net/tc_act/tc_defact.h> |
| 26 | 26 | ||
| 27 | #define SIMP_TAB_MASK 7 | 27 | #define SIMP_TAB_MASK 7 |
| 28 | static struct tcf_hashinfo simp_hash_info; | ||
| 29 | 28 | ||
| 30 | #define SIMP_MAX_DATA 32 | 29 | #define SIMP_MAX_DATA 32 |
| 31 | static int tcf_simp(struct sk_buff *skb, const struct tc_action *a, | 30 | static int tcf_simp(struct sk_buff *skb, const struct tc_action *a, |
| @@ -47,20 +46,10 @@ static int tcf_simp(struct sk_buff *skb, const struct tc_action *a, | |||
| 47 | return d->tcf_action; | 46 | return d->tcf_action; |
| 48 | } | 47 | } |
| 49 | 48 | ||
| 50 | static int tcf_simp_release(struct tcf_defact *d, int bind) | 49 | static void tcf_simp_release(struct tc_action *a, int bind) |
| 51 | { | 50 | { |
| 52 | int ret = 0; | 51 | struct tcf_defact *d = to_defact(a); |
| 53 | if (d) { | 52 | kfree(d->tcfd_defdata); |
| 54 | if (bind) | ||
| 55 | d->tcf_bindcnt--; | ||
| 56 | d->tcf_refcnt--; | ||
| 57 | if (d->tcf_bindcnt <= 0 && d->tcf_refcnt <= 0) { | ||
| 58 | kfree(d->tcfd_defdata); | ||
| 59 | tcf_hash_destroy(&d->common, &simp_hash_info); | ||
| 60 | ret = 1; | ||
| 61 | } | ||
| 62 | } | ||
| 63 | return ret; | ||
| 64 | } | 53 | } |
| 65 | 54 | ||
| 66 | static int alloc_defdata(struct tcf_defact *d, char *defdata) | 55 | static int alloc_defdata(struct tcf_defact *d, char *defdata) |
| @@ -94,7 +83,6 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla, | |||
| 94 | struct nlattr *tb[TCA_DEF_MAX + 1]; | 83 | struct nlattr *tb[TCA_DEF_MAX + 1]; |
| 95 | struct tc_defact *parm; | 84 | struct tc_defact *parm; |
| 96 | struct tcf_defact *d; | 85 | struct tcf_defact *d; |
| 97 | struct tcf_common *pc; | ||
| 98 | char *defdata; | 86 | char *defdata; |
| 99 | int ret = 0, err; | 87 | int ret = 0, err; |
| 100 | 88 | ||
| @@ -114,29 +102,25 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla, | |||
| 114 | parm = nla_data(tb[TCA_DEF_PARMS]); | 102 | parm = nla_data(tb[TCA_DEF_PARMS]); |
| 115 | defdata = nla_data(tb[TCA_DEF_DATA]); | 103 | defdata = nla_data(tb[TCA_DEF_DATA]); |
| 116 | 104 | ||
| 117 | pc = tcf_hash_check(parm->index, a, bind); | 105 | if (!tcf_hash_check(parm->index, a, bind)) { |
| 118 | if (!pc) { | 106 | ret = tcf_hash_create(parm->index, est, a, sizeof(*d), bind); |
| 119 | pc = tcf_hash_create(parm->index, est, a, sizeof(*d), bind); | 107 | if (ret) |
| 120 | if (IS_ERR(pc)) | 108 | return ret; |
| 121 | return PTR_ERR(pc); | ||
| 122 | 109 | ||
| 123 | d = to_defact(pc); | 110 | d = to_defact(a); |
| 124 | ret = alloc_defdata(d, defdata); | 111 | ret = alloc_defdata(d, defdata); |
| 125 | if (ret < 0) { | 112 | if (ret < 0) { |
| 126 | if (est) | 113 | tcf_hash_cleanup(a, est); |
| 127 | gen_kill_estimator(&pc->tcfc_bstats, | ||
| 128 | &pc->tcfc_rate_est); | ||
| 129 | kfree_rcu(pc, tcfc_rcu); | ||
| 130 | return ret; | 114 | return ret; |
| 131 | } | 115 | } |
| 132 | d->tcf_action = parm->action; | 116 | d->tcf_action = parm->action; |
| 133 | ret = ACT_P_CREATED; | 117 | ret = ACT_P_CREATED; |
| 134 | } else { | 118 | } else { |
| 135 | d = to_defact(pc); | 119 | d = to_defact(a); |
| 136 | 120 | ||
| 137 | if (bind) | 121 | if (bind) |
| 138 | return 0; | 122 | return 0; |
| 139 | tcf_simp_release(d, bind); | 123 | tcf_hash_release(a, bind); |
| 140 | if (!ovr) | 124 | if (!ovr) |
| 141 | return -EEXIST; | 125 | return -EEXIST; |
| 142 | 126 | ||
| @@ -144,19 +128,10 @@ static int tcf_simp_init(struct net *net, struct nlattr *nla, | |||
| 144 | } | 128 | } |
| 145 | 129 | ||
| 146 | if (ret == ACT_P_CREATED) | 130 | if (ret == ACT_P_CREATED) |
| 147 | tcf_hash_insert(pc, a->ops->hinfo); | 131 | tcf_hash_insert(a); |
| 148 | return ret; | 132 | return ret; |
| 149 | } | 133 | } |
| 150 | 134 | ||
| 151 | static int tcf_simp_cleanup(struct tc_action *a, int bind) | ||
| 152 | { | ||
| 153 | struct tcf_defact *d = a->priv; | ||
| 154 | |||
| 155 | if (d) | ||
| 156 | return tcf_simp_release(d, bind); | ||
| 157 | return 0; | ||
| 158 | } | ||
| 159 | |||
| 160 | static int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a, | 135 | static int tcf_simp_dump(struct sk_buff *skb, struct tc_action *a, |
| 161 | int bind, int ref) | 136 | int bind, int ref) |
| 162 | { | 137 | { |
| @@ -187,12 +162,11 @@ nla_put_failure: | |||
| 187 | 162 | ||
| 188 | static struct tc_action_ops act_simp_ops = { | 163 | static struct tc_action_ops act_simp_ops = { |
| 189 | .kind = "simple", | 164 | .kind = "simple", |
| 190 | .hinfo = &simp_hash_info, | ||
| 191 | .type = TCA_ACT_SIMP, | 165 | .type = TCA_ACT_SIMP, |
| 192 | .owner = THIS_MODULE, | 166 | .owner = THIS_MODULE, |
| 193 | .act = tcf_simp, | 167 | .act = tcf_simp, |
| 194 | .dump = tcf_simp_dump, | 168 | .dump = tcf_simp_dump, |
| 195 | .cleanup = tcf_simp_cleanup, | 169 | .cleanup = tcf_simp_release, |
| 196 | .init = tcf_simp_init, | 170 | .init = tcf_simp_init, |
| 197 | }; | 171 | }; |
| 198 | 172 | ||
| @@ -202,23 +176,15 @@ MODULE_LICENSE("GPL"); | |||
| 202 | 176 | ||
| 203 | static int __init simp_init_module(void) | 177 | static int __init simp_init_module(void) |
| 204 | { | 178 | { |
| 205 | int err, ret; | 179 | int ret; |
| 206 | err = tcf_hashinfo_init(&simp_hash_info, SIMP_TAB_MASK); | 180 | ret = tcf_register_action(&act_simp_ops, SIMP_TAB_MASK); |
| 207 | if (err) | ||
| 208 | return err; | ||
| 209 | |||
| 210 | ret = tcf_register_action(&act_simp_ops); | ||
| 211 | if (!ret) | 181 | if (!ret) |
| 212 | pr_info("Simple TC action Loaded\n"); | 182 | pr_info("Simple TC action Loaded\n"); |
| 213 | else | ||
| 214 | tcf_hashinfo_destroy(&simp_hash_info); | ||
| 215 | |||
| 216 | return ret; | 183 | return ret; |
| 217 | } | 184 | } |
| 218 | 185 | ||
| 219 | static void __exit simp_cleanup_module(void) | 186 | static void __exit simp_cleanup_module(void) |
| 220 | { | 187 | { |
| 221 | tcf_hashinfo_destroy(&simp_hash_info); | ||
| 222 | tcf_unregister_action(&act_simp_ops); | 188 | tcf_unregister_action(&act_simp_ops); |
| 223 | } | 189 | } |
| 224 | 190 | ||
diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c index 98725080b5aa..fcfeeaf838be 100644 --- a/net/sched/act_skbedit.c +++ b/net/sched/act_skbedit.c | |||
| @@ -28,7 +28,6 @@ | |||
| 28 | #include <net/tc_act/tc_skbedit.h> | 28 | #include <net/tc_act/tc_skbedit.h> |
| 29 | 29 | ||
| 30 | #define SKBEDIT_TAB_MASK 15 | 30 | #define SKBEDIT_TAB_MASK 15 |
| 31 | static struct tcf_hashinfo skbedit_hash_info; | ||
| 32 | 31 | ||
| 33 | static int tcf_skbedit(struct sk_buff *skb, const struct tc_action *a, | 32 | static int tcf_skbedit(struct sk_buff *skb, const struct tc_action *a, |
| 34 | struct tcf_result *res) | 33 | struct tcf_result *res) |
| @@ -65,7 +64,6 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla, | |||
| 65 | struct nlattr *tb[TCA_SKBEDIT_MAX + 1]; | 64 | struct nlattr *tb[TCA_SKBEDIT_MAX + 1]; |
| 66 | struct tc_skbedit *parm; | 65 | struct tc_skbedit *parm; |
| 67 | struct tcf_skbedit *d; | 66 | struct tcf_skbedit *d; |
| 68 | struct tcf_common *pc; | ||
| 69 | u32 flags = 0, *priority = NULL, *mark = NULL; | 67 | u32 flags = 0, *priority = NULL, *mark = NULL; |
| 70 | u16 *queue_mapping = NULL; | 68 | u16 *queue_mapping = NULL; |
| 71 | int ret = 0, err; | 69 | int ret = 0, err; |
| @@ -100,19 +98,18 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla, | |||
| 100 | 98 | ||
| 101 | parm = nla_data(tb[TCA_SKBEDIT_PARMS]); | 99 | parm = nla_data(tb[TCA_SKBEDIT_PARMS]); |
| 102 | 100 | ||
| 103 | pc = tcf_hash_check(parm->index, a, bind); | 101 | if (!tcf_hash_check(parm->index, a, bind)) { |
| 104 | if (!pc) { | 102 | ret = tcf_hash_create(parm->index, est, a, sizeof(*d), bind); |
| 105 | pc = tcf_hash_create(parm->index, est, a, sizeof(*d), bind); | 103 | if (ret) |
| 106 | if (IS_ERR(pc)) | 104 | return ret; |
| 107 | return PTR_ERR(pc); | ||
| 108 | 105 | ||
| 109 | d = to_skbedit(pc); | 106 | d = to_skbedit(a); |
| 110 | ret = ACT_P_CREATED; | 107 | ret = ACT_P_CREATED; |
| 111 | } else { | 108 | } else { |
| 112 | d = to_skbedit(pc); | 109 | d = to_skbedit(a); |
| 113 | if (bind) | 110 | if (bind) |
| 114 | return 0; | 111 | return 0; |
| 115 | tcf_hash_release(pc, bind, a->ops->hinfo); | 112 | tcf_hash_release(a, bind); |
| 116 | if (!ovr) | 113 | if (!ovr) |
| 117 | return -EEXIST; | 114 | return -EEXIST; |
| 118 | } | 115 | } |
| @@ -132,19 +129,10 @@ static int tcf_skbedit_init(struct net *net, struct nlattr *nla, | |||
| 132 | spin_unlock_bh(&d->tcf_lock); | 129 | spin_unlock_bh(&d->tcf_lock); |
| 133 | 130 | ||
| 134 | if (ret == ACT_P_CREATED) | 131 | if (ret == ACT_P_CREATED) |
| 135 | tcf_hash_insert(pc, a->ops->hinfo); | 132 | tcf_hash_insert(a); |
| 136 | return ret; | 133 | return ret; |
| 137 | } | 134 | } |
| 138 | 135 | ||
| 139 | static int tcf_skbedit_cleanup(struct tc_action *a, int bind) | ||
| 140 | { | ||
| 141 | struct tcf_skbedit *d = a->priv; | ||
| 142 | |||
| 143 | if (d) | ||
| 144 | return tcf_hash_release(&d->common, bind, &skbedit_hash_info); | ||
| 145 | return 0; | ||
| 146 | } | ||
| 147 | |||
| 148 | static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a, | 136 | static int tcf_skbedit_dump(struct sk_buff *skb, struct tc_action *a, |
| 149 | int bind, int ref) | 137 | int bind, int ref) |
| 150 | { | 138 | { |
| @@ -186,12 +174,10 @@ nla_put_failure: | |||
| 186 | 174 | ||
| 187 | static struct tc_action_ops act_skbedit_ops = { | 175 | static struct tc_action_ops act_skbedit_ops = { |
| 188 | .kind = "skbedit", | 176 | .kind = "skbedit", |
| 189 | .hinfo = &skbedit_hash_info, | ||
| 190 | .type = TCA_ACT_SKBEDIT, | 177 | .type = TCA_ACT_SKBEDIT, |
| 191 | .owner = THIS_MODULE, | 178 | .owner = THIS_MODULE, |
| 192 | .act = tcf_skbedit, | 179 | .act = tcf_skbedit, |
| 193 | .dump = tcf_skbedit_dump, | 180 | .dump = tcf_skbedit_dump, |
| 194 | .cleanup = tcf_skbedit_cleanup, | ||
| 195 | .init = tcf_skbedit_init, | 181 | .init = tcf_skbedit_init, |
| 196 | }; | 182 | }; |
| 197 | 183 | ||
| @@ -201,15 +187,11 @@ MODULE_LICENSE("GPL"); | |||
| 201 | 187 | ||
| 202 | static int __init skbedit_init_module(void) | 188 | static int __init skbedit_init_module(void) |
| 203 | { | 189 | { |
| 204 | int err = tcf_hashinfo_init(&skbedit_hash_info, SKBEDIT_TAB_MASK); | 190 | return tcf_register_action(&act_skbedit_ops, SKBEDIT_TAB_MASK); |
| 205 | if (err) | ||
| 206 | return err; | ||
| 207 | return tcf_register_action(&act_skbedit_ops); | ||
| 208 | } | 191 | } |
| 209 | 192 | ||
| 210 | static void __exit skbedit_cleanup_module(void) | 193 | static void __exit skbedit_cleanup_module(void) |
| 211 | { | 194 | { |
| 212 | tcf_hashinfo_destroy(&skbedit_hash_info); | ||
| 213 | tcf_unregister_action(&act_skbedit_ops); | 195 | tcf_unregister_action(&act_skbedit_ops); |
| 214 | } | 196 | } |
| 215 | 197 | ||
diff --git a/net/sched/cls_fw.c b/net/sched/cls_fw.c index a366537f82c6..63a3ce75c02e 100644 --- a/net/sched/cls_fw.c +++ b/net/sched/cls_fw.c | |||
| @@ -29,11 +29,11 @@ | |||
| 29 | #include <net/act_api.h> | 29 | #include <net/act_api.h> |
| 30 | #include <net/pkt_cls.h> | 30 | #include <net/pkt_cls.h> |
| 31 | 31 | ||
| 32 | #define HTSIZE (PAGE_SIZE/sizeof(struct fw_filter *)) | 32 | #define HTSIZE 256 |
| 33 | 33 | ||
| 34 | struct fw_head { | 34 | struct fw_head { |
| 35 | struct fw_filter *ht[HTSIZE]; | 35 | u32 mask; |
| 36 | u32 mask; | 36 | struct fw_filter *ht[HTSIZE]; |
| 37 | }; | 37 | }; |
| 38 | 38 | ||
| 39 | struct fw_filter { | 39 | struct fw_filter { |
| @@ -46,30 +46,11 @@ struct fw_filter { | |||
| 46 | struct tcf_exts exts; | 46 | struct tcf_exts exts; |
| 47 | }; | 47 | }; |
| 48 | 48 | ||
| 49 | static inline int fw_hash(u32 handle) | 49 | static u32 fw_hash(u32 handle) |
| 50 | { | 50 | { |
| 51 | if (HTSIZE == 4096) | 51 | handle ^= (handle >> 16); |
| 52 | return ((handle >> 24) & 0xFFF) ^ | 52 | handle ^= (handle >> 8); |
| 53 | ((handle >> 12) & 0xFFF) ^ | 53 | return handle % HTSIZE; |
| 54 | (handle & 0xFFF); | ||
| 55 | else if (HTSIZE == 2048) | ||
| 56 | return ((handle >> 22) & 0x7FF) ^ | ||
| 57 | ((handle >> 11) & 0x7FF) ^ | ||
| 58 | (handle & 0x7FF); | ||
| 59 | else if (HTSIZE == 1024) | ||
| 60 | return ((handle >> 20) & 0x3FF) ^ | ||
| 61 | ((handle >> 10) & 0x3FF) ^ | ||
| 62 | (handle & 0x3FF); | ||
| 63 | else if (HTSIZE == 512) | ||
| 64 | return (handle >> 27) ^ | ||
| 65 | ((handle >> 18) & 0x1FF) ^ | ||
| 66 | ((handle >> 9) & 0x1FF) ^ | ||
| 67 | (handle & 0x1FF); | ||
| 68 | else if (HTSIZE == 256) { | ||
| 69 | u8 *t = (u8 *) &handle; | ||
| 70 | return t[0] ^ t[1] ^ t[2] ^ t[3]; | ||
| 71 | } else | ||
| 72 | return handle & (HTSIZE - 1); | ||
| 73 | } | 54 | } |
| 74 | 55 | ||
| 75 | static int fw_classify(struct sk_buff *skb, const struct tcf_proto *tp, | 56 | static int fw_classify(struct sk_buff *skb, const struct tcf_proto *tp, |
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c index a07d55e75698..a0b84e0e22de 100644 --- a/net/sched/sch_api.c +++ b/net/sched/sch_api.c | |||
| @@ -1304,6 +1304,7 @@ static int tc_fill_qdisc(struct sk_buff *skb, struct Qdisc *q, u32 clid, | |||
| 1304 | struct gnet_dump d; | 1304 | struct gnet_dump d; |
| 1305 | struct qdisc_size_table *stab; | 1305 | struct qdisc_size_table *stab; |
| 1306 | 1306 | ||
| 1307 | cond_resched(); | ||
| 1307 | nlh = nlmsg_put(skb, portid, seq, event, sizeof(*tcm), flags); | 1308 | nlh = nlmsg_put(skb, portid, seq, event, sizeof(*tcm), flags); |
| 1308 | if (!nlh) | 1309 | if (!nlh) |
| 1309 | goto out_nlmsg_trim; | 1310 | goto out_nlmsg_trim; |
| @@ -1435,9 +1436,9 @@ static int tc_dump_qdisc(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 1435 | s_idx = cb->args[0]; | 1436 | s_idx = cb->args[0]; |
| 1436 | s_q_idx = q_idx = cb->args[1]; | 1437 | s_q_idx = q_idx = cb->args[1]; |
| 1437 | 1438 | ||
| 1438 | rcu_read_lock(); | ||
| 1439 | idx = 0; | 1439 | idx = 0; |
| 1440 | for_each_netdev_rcu(net, dev) { | 1440 | ASSERT_RTNL(); |
| 1441 | for_each_netdev(net, dev) { | ||
| 1441 | struct netdev_queue *dev_queue; | 1442 | struct netdev_queue *dev_queue; |
| 1442 | 1443 | ||
| 1443 | if (idx < s_idx) | 1444 | if (idx < s_idx) |
| @@ -1460,8 +1461,6 @@ cont: | |||
| 1460 | } | 1461 | } |
| 1461 | 1462 | ||
| 1462 | done: | 1463 | done: |
| 1463 | rcu_read_unlock(); | ||
| 1464 | |||
| 1465 | cb->args[0] = idx; | 1464 | cb->args[0] = idx; |
| 1466 | cb->args[1] = q_idx; | 1465 | cb->args[1] = q_idx; |
| 1467 | 1466 | ||
| @@ -1618,6 +1617,7 @@ static int tc_fill_tclass(struct sk_buff *skb, struct Qdisc *q, | |||
| 1618 | struct gnet_dump d; | 1617 | struct gnet_dump d; |
| 1619 | const struct Qdisc_class_ops *cl_ops = q->ops->cl_ops; | 1618 | const struct Qdisc_class_ops *cl_ops = q->ops->cl_ops; |
| 1620 | 1619 | ||
| 1620 | cond_resched(); | ||
| 1621 | nlh = nlmsg_put(skb, portid, seq, event, sizeof(*tcm), flags); | 1621 | nlh = nlmsg_put(skb, portid, seq, event, sizeof(*tcm), flags); |
| 1622 | if (!nlh) | 1622 | if (!nlh) |
| 1623 | goto out_nlmsg_trim; | 1623 | goto out_nlmsg_trim; |
diff --git a/net/sched/sch_atm.c b/net/sched/sch_atm.c index 1f9c31411f19..8449b337f9e3 100644 --- a/net/sched/sch_atm.c +++ b/net/sched/sch_atm.c | |||
| @@ -623,8 +623,7 @@ static int atm_tc_dump_class(struct Qdisc *sch, unsigned long cl, | |||
| 623 | if (nla_put_u32(skb, TCA_ATM_EXCESS, 0)) | 623 | if (nla_put_u32(skb, TCA_ATM_EXCESS, 0)) |
| 624 | goto nla_put_failure; | 624 | goto nla_put_failure; |
| 625 | } | 625 | } |
| 626 | nla_nest_end(skb, nest); | 626 | return nla_nest_end(skb, nest); |
| 627 | return skb->len; | ||
| 628 | 627 | ||
| 629 | nla_put_failure: | 628 | nla_put_failure: |
| 630 | nla_nest_cancel(skb, nest); | 629 | nla_nest_cancel(skb, nest); |
diff --git a/net/sched/sch_cbq.c b/net/sched/sch_cbq.c index 2f80d01d42a6..ead526467cca 100644 --- a/net/sched/sch_cbq.c +++ b/net/sched/sch_cbq.c | |||
| @@ -1563,8 +1563,7 @@ static int cbq_dump(struct Qdisc *sch, struct sk_buff *skb) | |||
| 1563 | goto nla_put_failure; | 1563 | goto nla_put_failure; |
| 1564 | if (cbq_dump_attr(skb, &q->link) < 0) | 1564 | if (cbq_dump_attr(skb, &q->link) < 0) |
| 1565 | goto nla_put_failure; | 1565 | goto nla_put_failure; |
| 1566 | nla_nest_end(skb, nest); | 1566 | return nla_nest_end(skb, nest); |
| 1567 | return skb->len; | ||
| 1568 | 1567 | ||
| 1569 | nla_put_failure: | 1568 | nla_put_failure: |
| 1570 | nla_nest_cancel(skb, nest); | 1569 | nla_nest_cancel(skb, nest); |
| @@ -1599,8 +1598,7 @@ cbq_dump_class(struct Qdisc *sch, unsigned long arg, | |||
| 1599 | goto nla_put_failure; | 1598 | goto nla_put_failure; |
| 1600 | if (cbq_dump_attr(skb, cl) < 0) | 1599 | if (cbq_dump_attr(skb, cl) < 0) |
| 1601 | goto nla_put_failure; | 1600 | goto nla_put_failure; |
| 1602 | nla_nest_end(skb, nest); | 1601 | return nla_nest_end(skb, nest); |
| 1603 | return skb->len; | ||
| 1604 | 1602 | ||
| 1605 | nla_put_failure: | 1603 | nla_put_failure: |
| 1606 | nla_nest_cancel(skb, nest); | 1604 | nla_nest_cancel(skb, nest); |
diff --git a/net/sched/sch_fq.c b/net/sched/sch_fq.c index 21e251766eb1..23c682b42f99 100644 --- a/net/sched/sch_fq.c +++ b/net/sched/sch_fq.c | |||
| @@ -781,8 +781,7 @@ static int fq_dump(struct Qdisc *sch, struct sk_buff *skb) | |||
| 781 | nla_put_u32(skb, TCA_FQ_BUCKETS_LOG, q->fq_trees_log)) | 781 | nla_put_u32(skb, TCA_FQ_BUCKETS_LOG, q->fq_trees_log)) |
| 782 | goto nla_put_failure; | 782 | goto nla_put_failure; |
| 783 | 783 | ||
| 784 | nla_nest_end(skb, opts); | 784 | return nla_nest_end(skb, opts); |
| 785 | return skb->len; | ||
| 786 | 785 | ||
| 787 | nla_put_failure: | 786 | nla_put_failure: |
| 788 | return -1; | 787 | return -1; |
diff --git a/net/sched/sch_fq_codel.c b/net/sched/sch_fq_codel.c index ba5bc929eac7..0bf432c782c1 100644 --- a/net/sched/sch_fq_codel.c +++ b/net/sched/sch_fq_codel.c | |||
| @@ -450,8 +450,7 @@ static int fq_codel_dump(struct Qdisc *sch, struct sk_buff *skb) | |||
| 450 | q->flows_cnt)) | 450 | q->flows_cnt)) |
| 451 | goto nla_put_failure; | 451 | goto nla_put_failure; |
| 452 | 452 | ||
| 453 | nla_nest_end(skb, opts); | 453 | return nla_nest_end(skb, opts); |
| 454 | return skb->len; | ||
| 455 | 454 | ||
| 456 | nla_put_failure: | 455 | nla_put_failure: |
| 457 | return -1; | 456 | return -1; |
diff --git a/net/sched/sch_generic.c b/net/sched/sch_generic.c index e82e43b69c33..e1543b03e39d 100644 --- a/net/sched/sch_generic.c +++ b/net/sched/sch_generic.c | |||
| @@ -310,6 +310,7 @@ void netif_carrier_on(struct net_device *dev) | |||
| 310 | if (test_and_clear_bit(__LINK_STATE_NOCARRIER, &dev->state)) { | 310 | if (test_and_clear_bit(__LINK_STATE_NOCARRIER, &dev->state)) { |
| 311 | if (dev->reg_state == NETREG_UNINITIALIZED) | 311 | if (dev->reg_state == NETREG_UNINITIALIZED) |
| 312 | return; | 312 | return; |
| 313 | atomic_inc(&dev->carrier_changes); | ||
| 313 | linkwatch_fire_event(dev); | 314 | linkwatch_fire_event(dev); |
| 314 | if (netif_running(dev)) | 315 | if (netif_running(dev)) |
| 315 | __netdev_watchdog_up(dev); | 316 | __netdev_watchdog_up(dev); |
| @@ -328,6 +329,7 @@ void netif_carrier_off(struct net_device *dev) | |||
| 328 | if (!test_and_set_bit(__LINK_STATE_NOCARRIER, &dev->state)) { | 329 | if (!test_and_set_bit(__LINK_STATE_NOCARRIER, &dev->state)) { |
| 329 | if (dev->reg_state == NETREG_UNINITIALIZED) | 330 | if (dev->reg_state == NETREG_UNINITIALIZED) |
| 330 | return; | 331 | return; |
| 332 | atomic_inc(&dev->carrier_changes); | ||
| 331 | linkwatch_fire_event(dev); | 333 | linkwatch_fire_event(dev); |
| 332 | } | 334 | } |
| 333 | } | 335 | } |
diff --git a/net/sched/sch_hfsc.c b/net/sched/sch_hfsc.c index c4075610502c..ec8aeaac1dd7 100644 --- a/net/sched/sch_hfsc.c +++ b/net/sched/sch_hfsc.c | |||
| @@ -1353,8 +1353,7 @@ hfsc_dump_class(struct Qdisc *sch, unsigned long arg, struct sk_buff *skb, | |||
| 1353 | goto nla_put_failure; | 1353 | goto nla_put_failure; |
| 1354 | if (hfsc_dump_curves(skb, cl) < 0) | 1354 | if (hfsc_dump_curves(skb, cl) < 0) |
| 1355 | goto nla_put_failure; | 1355 | goto nla_put_failure; |
| 1356 | nla_nest_end(skb, nest); | 1356 | return nla_nest_end(skb, nest); |
| 1357 | return skb->len; | ||
| 1358 | 1357 | ||
| 1359 | nla_put_failure: | 1358 | nla_put_failure: |
| 1360 | nla_nest_cancel(skb, nest); | 1359 | nla_nest_cancel(skb, nest); |
diff --git a/net/sched/sch_hhf.c b/net/sched/sch_hhf.c index 647680b1c625..edee03d922e2 100644 --- a/net/sched/sch_hhf.c +++ b/net/sched/sch_hhf.c | |||
| @@ -691,8 +691,7 @@ static int hhf_dump(struct Qdisc *sch, struct sk_buff *skb) | |||
| 691 | nla_put_u32(skb, TCA_HHF_NON_HH_WEIGHT, q->hhf_non_hh_weight)) | 691 | nla_put_u32(skb, TCA_HHF_NON_HH_WEIGHT, q->hhf_non_hh_weight)) |
| 692 | goto nla_put_failure; | 692 | goto nla_put_failure; |
| 693 | 693 | ||
| 694 | nla_nest_end(skb, opts); | 694 | return nla_nest_end(skb, opts); |
| 695 | return skb->len; | ||
| 696 | 695 | ||
| 697 | nla_put_failure: | 696 | nla_put_failure: |
| 698 | return -1; | 697 | return -1; |
diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 722e137df244..9f949abcacef 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c | |||
| @@ -1062,12 +1062,13 @@ static int htb_init(struct Qdisc *sch, struct nlattr *opt) | |||
| 1062 | 1062 | ||
| 1063 | static int htb_dump(struct Qdisc *sch, struct sk_buff *skb) | 1063 | static int htb_dump(struct Qdisc *sch, struct sk_buff *skb) |
| 1064 | { | 1064 | { |
| 1065 | spinlock_t *root_lock = qdisc_root_sleeping_lock(sch); | ||
| 1066 | struct htb_sched *q = qdisc_priv(sch); | 1065 | struct htb_sched *q = qdisc_priv(sch); |
| 1067 | struct nlattr *nest; | 1066 | struct nlattr *nest; |
| 1068 | struct tc_htb_glob gopt; | 1067 | struct tc_htb_glob gopt; |
| 1069 | 1068 | ||
| 1070 | spin_lock_bh(root_lock); | 1069 | /* Its safe to not acquire qdisc lock. As we hold RTNL, |
| 1070 | * no change can happen on the qdisc parameters. | ||
| 1071 | */ | ||
| 1071 | 1072 | ||
| 1072 | gopt.direct_pkts = q->direct_pkts; | 1073 | gopt.direct_pkts = q->direct_pkts; |
| 1073 | gopt.version = HTB_VER; | 1074 | gopt.version = HTB_VER; |
| @@ -1081,13 +1082,10 @@ static int htb_dump(struct Qdisc *sch, struct sk_buff *skb) | |||
| 1081 | if (nla_put(skb, TCA_HTB_INIT, sizeof(gopt), &gopt) || | 1082 | if (nla_put(skb, TCA_HTB_INIT, sizeof(gopt), &gopt) || |
| 1082 | nla_put_u32(skb, TCA_HTB_DIRECT_QLEN, q->direct_qlen)) | 1083 | nla_put_u32(skb, TCA_HTB_DIRECT_QLEN, q->direct_qlen)) |
| 1083 | goto nla_put_failure; | 1084 | goto nla_put_failure; |
| 1084 | nla_nest_end(skb, nest); | ||
| 1085 | 1085 | ||
| 1086 | spin_unlock_bh(root_lock); | 1086 | return nla_nest_end(skb, nest); |
| 1087 | return skb->len; | ||
| 1088 | 1087 | ||
| 1089 | nla_put_failure: | 1088 | nla_put_failure: |
| 1090 | spin_unlock_bh(root_lock); | ||
| 1091 | nla_nest_cancel(skb, nest); | 1089 | nla_nest_cancel(skb, nest); |
| 1092 | return -1; | 1090 | return -1; |
| 1093 | } | 1091 | } |
| @@ -1096,11 +1094,12 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg, | |||
| 1096 | struct sk_buff *skb, struct tcmsg *tcm) | 1094 | struct sk_buff *skb, struct tcmsg *tcm) |
| 1097 | { | 1095 | { |
| 1098 | struct htb_class *cl = (struct htb_class *)arg; | 1096 | struct htb_class *cl = (struct htb_class *)arg; |
| 1099 | spinlock_t *root_lock = qdisc_root_sleeping_lock(sch); | ||
| 1100 | struct nlattr *nest; | 1097 | struct nlattr *nest; |
| 1101 | struct tc_htb_opt opt; | 1098 | struct tc_htb_opt opt; |
| 1102 | 1099 | ||
| 1103 | spin_lock_bh(root_lock); | 1100 | /* Its safe to not acquire qdisc lock. As we hold RTNL, |
| 1101 | * no change can happen on the class parameters. | ||
| 1102 | */ | ||
| 1104 | tcm->tcm_parent = cl->parent ? cl->parent->common.classid : TC_H_ROOT; | 1103 | tcm->tcm_parent = cl->parent ? cl->parent->common.classid : TC_H_ROOT; |
| 1105 | tcm->tcm_handle = cl->common.classid; | 1104 | tcm->tcm_handle = cl->common.classid; |
| 1106 | if (!cl->level && cl->un.leaf.q) | 1105 | if (!cl->level && cl->un.leaf.q) |
| @@ -1128,12 +1127,9 @@ static int htb_dump_class(struct Qdisc *sch, unsigned long arg, | |||
| 1128 | nla_put_u64(skb, TCA_HTB_CEIL64, cl->ceil.rate_bytes_ps)) | 1127 | nla_put_u64(skb, TCA_HTB_CEIL64, cl->ceil.rate_bytes_ps)) |
| 1129 | goto nla_put_failure; | 1128 | goto nla_put_failure; |
| 1130 | 1129 | ||
| 1131 | nla_nest_end(skb, nest); | 1130 | return nla_nest_end(skb, nest); |
| 1132 | spin_unlock_bh(root_lock); | ||
| 1133 | return skb->len; | ||
| 1134 | 1131 | ||
| 1135 | nla_put_failure: | 1132 | nla_put_failure: |
| 1136 | spin_unlock_bh(root_lock); | ||
| 1137 | nla_nest_cancel(skb, nest); | 1133 | nla_nest_cancel(skb, nest); |
| 1138 | return -1; | 1134 | return -1; |
| 1139 | } | 1135 | } |
diff --git a/net/sched/sch_ingress.c b/net/sched/sch_ingress.c index bce1665239b8..62871c14e1f9 100644 --- a/net/sched/sch_ingress.c +++ b/net/sched/sch_ingress.c | |||
| @@ -100,8 +100,7 @@ static int ingress_dump(struct Qdisc *sch, struct sk_buff *skb) | |||
| 100 | nest = nla_nest_start(skb, TCA_OPTIONS); | 100 | nest = nla_nest_start(skb, TCA_OPTIONS); |
| 101 | if (nest == NULL) | 101 | if (nest == NULL) |
| 102 | goto nla_put_failure; | 102 | goto nla_put_failure; |
| 103 | nla_nest_end(skb, nest); | 103 | return nla_nest_end(skb, nest); |
| 104 | return skb->len; | ||
| 105 | 104 | ||
| 106 | nla_put_failure: | 105 | nla_put_failure: |
| 107 | nla_nest_cancel(skb, nest); | 106 | nla_nest_cancel(skb, nest); |
diff --git a/net/sched/sch_netem.c b/net/sched/sch_netem.c index de1059af6da1..f1669a00f571 100644 --- a/net/sched/sch_netem.c +++ b/net/sched/sch_netem.c | |||
| @@ -117,6 +117,11 @@ struct netem_sched_data { | |||
| 117 | LOST_IN_BURST_PERIOD, | 117 | LOST_IN_BURST_PERIOD, |
| 118 | } _4_state_model; | 118 | } _4_state_model; |
| 119 | 119 | ||
| 120 | enum { | ||
| 121 | GOOD_STATE = 1, | ||
| 122 | BAD_STATE, | ||
| 123 | } GE_state_model; | ||
| 124 | |||
| 120 | /* Correlated Loss Generation models */ | 125 | /* Correlated Loss Generation models */ |
| 121 | struct clgstate { | 126 | struct clgstate { |
| 122 | /* state of the Markov chain */ | 127 | /* state of the Markov chain */ |
| @@ -272,15 +277,15 @@ static bool loss_gilb_ell(struct netem_sched_data *q) | |||
| 272 | struct clgstate *clg = &q->clg; | 277 | struct clgstate *clg = &q->clg; |
| 273 | 278 | ||
| 274 | switch (clg->state) { | 279 | switch (clg->state) { |
| 275 | case 1: | 280 | case GOOD_STATE: |
| 276 | if (prandom_u32() < clg->a1) | 281 | if (prandom_u32() < clg->a1) |
| 277 | clg->state = 2; | 282 | clg->state = BAD_STATE; |
| 278 | if (prandom_u32() < clg->a4) | 283 | if (prandom_u32() < clg->a4) |
| 279 | return true; | 284 | return true; |
| 280 | break; | 285 | break; |
| 281 | case 2: | 286 | case BAD_STATE: |
| 282 | if (prandom_u32() < clg->a2) | 287 | if (prandom_u32() < clg->a2) |
| 283 | clg->state = 1; | 288 | clg->state = GOOD_STATE; |
| 284 | if (prandom_u32() > clg->a3) | 289 | if (prandom_u32() > clg->a3) |
| 285 | return true; | 290 | return true; |
| 286 | } | 291 | } |
| @@ -689,9 +694,8 @@ static int get_dist_table(struct Qdisc *sch, const struct nlattr *attr) | |||
| 689 | return 0; | 694 | return 0; |
| 690 | } | 695 | } |
| 691 | 696 | ||
| 692 | static void get_correlation(struct Qdisc *sch, const struct nlattr *attr) | 697 | static void get_correlation(struct netem_sched_data *q, const struct nlattr *attr) |
| 693 | { | 698 | { |
| 694 | struct netem_sched_data *q = qdisc_priv(sch); | ||
| 695 | const struct tc_netem_corr *c = nla_data(attr); | 699 | const struct tc_netem_corr *c = nla_data(attr); |
| 696 | 700 | ||
| 697 | init_crandom(&q->delay_cor, c->delay_corr); | 701 | init_crandom(&q->delay_cor, c->delay_corr); |
| @@ -699,27 +703,24 @@ static void get_correlation(struct Qdisc *sch, const struct nlattr *attr) | |||
| 699 | init_crandom(&q->dup_cor, c->dup_corr); | 703 | init_crandom(&q->dup_cor, c->dup_corr); |
| 700 | } | 704 | } |
| 701 | 705 | ||
| 702 | static void get_reorder(struct Qdisc *sch, const struct nlattr *attr) | 706 | static void get_reorder(struct netem_sched_data *q, const struct nlattr *attr) |
| 703 | { | 707 | { |
| 704 | struct netem_sched_data *q = qdisc_priv(sch); | ||
| 705 | const struct tc_netem_reorder *r = nla_data(attr); | 708 | const struct tc_netem_reorder *r = nla_data(attr); |
| 706 | 709 | ||
| 707 | q->reorder = r->probability; | 710 | q->reorder = r->probability; |
| 708 | init_crandom(&q->reorder_cor, r->correlation); | 711 | init_crandom(&q->reorder_cor, r->correlation); |
| 709 | } | 712 | } |
| 710 | 713 | ||
| 711 | static void get_corrupt(struct Qdisc *sch, const struct nlattr *attr) | 714 | static void get_corrupt(struct netem_sched_data *q, const struct nlattr *attr) |
| 712 | { | 715 | { |
| 713 | struct netem_sched_data *q = qdisc_priv(sch); | ||
| 714 | const struct tc_netem_corrupt *r = nla_data(attr); | 716 | const struct tc_netem_corrupt *r = nla_data(attr); |
| 715 | 717 | ||
| 716 | q->corrupt = r->probability; | 718 | q->corrupt = r->probability; |
| 717 | init_crandom(&q->corrupt_cor, r->correlation); | 719 | init_crandom(&q->corrupt_cor, r->correlation); |
| 718 | } | 720 | } |
| 719 | 721 | ||
| 720 | static void get_rate(struct Qdisc *sch, const struct nlattr *attr) | 722 | static void get_rate(struct netem_sched_data *q, const struct nlattr *attr) |
| 721 | { | 723 | { |
| 722 | struct netem_sched_data *q = qdisc_priv(sch); | ||
| 723 | const struct tc_netem_rate *r = nla_data(attr); | 724 | const struct tc_netem_rate *r = nla_data(attr); |
| 724 | 725 | ||
| 725 | q->rate = r->rate; | 726 | q->rate = r->rate; |
| @@ -732,9 +733,8 @@ static void get_rate(struct Qdisc *sch, const struct nlattr *attr) | |||
| 732 | q->cell_size_reciprocal = (struct reciprocal_value) { 0 }; | 733 | q->cell_size_reciprocal = (struct reciprocal_value) { 0 }; |
| 733 | } | 734 | } |
| 734 | 735 | ||
| 735 | static int get_loss_clg(struct Qdisc *sch, const struct nlattr *attr) | 736 | static int get_loss_clg(struct netem_sched_data *q, const struct nlattr *attr) |
| 736 | { | 737 | { |
| 737 | struct netem_sched_data *q = qdisc_priv(sch); | ||
| 738 | const struct nlattr *la; | 738 | const struct nlattr *la; |
| 739 | int rem; | 739 | int rem; |
| 740 | 740 | ||
| @@ -752,7 +752,7 @@ static int get_loss_clg(struct Qdisc *sch, const struct nlattr *attr) | |||
| 752 | 752 | ||
| 753 | q->loss_model = CLG_4_STATES; | 753 | q->loss_model = CLG_4_STATES; |
| 754 | 754 | ||
| 755 | q->clg.state = 1; | 755 | q->clg.state = TX_IN_GAP_PERIOD; |
| 756 | q->clg.a1 = gi->p13; | 756 | q->clg.a1 = gi->p13; |
| 757 | q->clg.a2 = gi->p31; | 757 | q->clg.a2 = gi->p31; |
| 758 | q->clg.a3 = gi->p32; | 758 | q->clg.a3 = gi->p32; |
| @@ -770,7 +770,7 @@ static int get_loss_clg(struct Qdisc *sch, const struct nlattr *attr) | |||
| 770 | } | 770 | } |
| 771 | 771 | ||
| 772 | q->loss_model = CLG_GILB_ELL; | 772 | q->loss_model = CLG_GILB_ELL; |
| 773 | q->clg.state = 1; | 773 | q->clg.state = GOOD_STATE; |
| 774 | q->clg.a1 = ge->p; | 774 | q->clg.a1 = ge->p; |
| 775 | q->clg.a2 = ge->r; | 775 | q->clg.a2 = ge->r; |
| 776 | q->clg.a3 = ge->h; | 776 | q->clg.a3 = ge->h; |
| @@ -821,6 +821,8 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt) | |||
| 821 | struct netem_sched_data *q = qdisc_priv(sch); | 821 | struct netem_sched_data *q = qdisc_priv(sch); |
| 822 | struct nlattr *tb[TCA_NETEM_MAX + 1]; | 822 | struct nlattr *tb[TCA_NETEM_MAX + 1]; |
| 823 | struct tc_netem_qopt *qopt; | 823 | struct tc_netem_qopt *qopt; |
| 824 | struct clgstate old_clg; | ||
| 825 | int old_loss_model = CLG_RANDOM; | ||
| 824 | int ret; | 826 | int ret; |
| 825 | 827 | ||
| 826 | if (opt == NULL) | 828 | if (opt == NULL) |
| @@ -831,6 +833,33 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt) | |||
| 831 | if (ret < 0) | 833 | if (ret < 0) |
| 832 | return ret; | 834 | return ret; |
| 833 | 835 | ||
| 836 | /* backup q->clg and q->loss_model */ | ||
| 837 | old_clg = q->clg; | ||
| 838 | old_loss_model = q->loss_model; | ||
| 839 | |||
| 840 | if (tb[TCA_NETEM_LOSS]) { | ||
| 841 | ret = get_loss_clg(q, tb[TCA_NETEM_LOSS]); | ||
| 842 | if (ret) { | ||
| 843 | q->loss_model = old_loss_model; | ||
| 844 | return ret; | ||
| 845 | } | ||
| 846 | } else { | ||
| 847 | q->loss_model = CLG_RANDOM; | ||
| 848 | } | ||
| 849 | |||
| 850 | if (tb[TCA_NETEM_DELAY_DIST]) { | ||
| 851 | ret = get_dist_table(sch, tb[TCA_NETEM_DELAY_DIST]); | ||
| 852 | if (ret) { | ||
| 853 | /* recover clg and loss_model, in case of | ||
| 854 | * q->clg and q->loss_model were modified | ||
| 855 | * in get_loss_clg() | ||
| 856 | */ | ||
| 857 | q->clg = old_clg; | ||
| 858 | q->loss_model = old_loss_model; | ||
| 859 | return ret; | ||
| 860 | } | ||
| 861 | } | ||
| 862 | |||
| 834 | sch->limit = qopt->limit; | 863 | sch->limit = qopt->limit; |
| 835 | 864 | ||
| 836 | q->latency = qopt->latency; | 865 | q->latency = qopt->latency; |
| @@ -848,22 +877,16 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt) | |||
| 848 | q->reorder = ~0; | 877 | q->reorder = ~0; |
| 849 | 878 | ||
| 850 | if (tb[TCA_NETEM_CORR]) | 879 | if (tb[TCA_NETEM_CORR]) |
| 851 | get_correlation(sch, tb[TCA_NETEM_CORR]); | 880 | get_correlation(q, tb[TCA_NETEM_CORR]); |
| 852 | |||
| 853 | if (tb[TCA_NETEM_DELAY_DIST]) { | ||
| 854 | ret = get_dist_table(sch, tb[TCA_NETEM_DELAY_DIST]); | ||
| 855 | if (ret) | ||
| 856 | return ret; | ||
| 857 | } | ||
| 858 | 881 | ||
| 859 | if (tb[TCA_NETEM_REORDER]) | 882 | if (tb[TCA_NETEM_REORDER]) |
| 860 | get_reorder(sch, tb[TCA_NETEM_REORDER]); | 883 | get_reorder(q, tb[TCA_NETEM_REORDER]); |
| 861 | 884 | ||
| 862 | if (tb[TCA_NETEM_CORRUPT]) | 885 | if (tb[TCA_NETEM_CORRUPT]) |
| 863 | get_corrupt(sch, tb[TCA_NETEM_CORRUPT]); | 886 | get_corrupt(q, tb[TCA_NETEM_CORRUPT]); |
| 864 | 887 | ||
| 865 | if (tb[TCA_NETEM_RATE]) | 888 | if (tb[TCA_NETEM_RATE]) |
| 866 | get_rate(sch, tb[TCA_NETEM_RATE]); | 889 | get_rate(q, tb[TCA_NETEM_RATE]); |
| 867 | 890 | ||
| 868 | if (tb[TCA_NETEM_RATE64]) | 891 | if (tb[TCA_NETEM_RATE64]) |
| 869 | q->rate = max_t(u64, q->rate, | 892 | q->rate = max_t(u64, q->rate, |
| @@ -872,10 +895,6 @@ static int netem_change(struct Qdisc *sch, struct nlattr *opt) | |||
| 872 | if (tb[TCA_NETEM_ECN]) | 895 | if (tb[TCA_NETEM_ECN]) |
| 873 | q->ecn = nla_get_u32(tb[TCA_NETEM_ECN]); | 896 | q->ecn = nla_get_u32(tb[TCA_NETEM_ECN]); |
| 874 | 897 | ||
| 875 | q->loss_model = CLG_RANDOM; | ||
| 876 | if (tb[TCA_NETEM_LOSS]) | ||
| 877 | ret = get_loss_clg(sch, tb[TCA_NETEM_LOSS]); | ||
| 878 | |||
| 879 | return ret; | 898 | return ret; |
| 880 | } | 899 | } |
| 881 | 900 | ||
diff --git a/net/sched/sch_tbf.c b/net/sched/sch_tbf.c index 4f505a006896..18ff63433709 100644 --- a/net/sched/sch_tbf.c +++ b/net/sched/sch_tbf.c | |||
| @@ -101,12 +101,11 @@ | |||
| 101 | struct tbf_sched_data { | 101 | struct tbf_sched_data { |
| 102 | /* Parameters */ | 102 | /* Parameters */ |
| 103 | u32 limit; /* Maximal length of backlog: bytes */ | 103 | u32 limit; /* Maximal length of backlog: bytes */ |
| 104 | u32 max_size; | ||
| 104 | s64 buffer; /* Token bucket depth/rate: MUST BE >= MTU/B */ | 105 | s64 buffer; /* Token bucket depth/rate: MUST BE >= MTU/B */ |
| 105 | s64 mtu; | 106 | s64 mtu; |
| 106 | u32 max_size; | ||
| 107 | struct psched_ratecfg rate; | 107 | struct psched_ratecfg rate; |
| 108 | struct psched_ratecfg peak; | 108 | struct psched_ratecfg peak; |
| 109 | bool peak_present; | ||
| 110 | 109 | ||
| 111 | /* Variables */ | 110 | /* Variables */ |
| 112 | s64 tokens; /* Current number of B tokens */ | 111 | s64 tokens; /* Current number of B tokens */ |
| @@ -222,6 +221,11 @@ static unsigned int tbf_drop(struct Qdisc *sch) | |||
| 222 | return len; | 221 | return len; |
| 223 | } | 222 | } |
| 224 | 223 | ||
| 224 | static bool tbf_peak_present(const struct tbf_sched_data *q) | ||
| 225 | { | ||
| 226 | return q->peak.rate_bytes_ps; | ||
| 227 | } | ||
| 228 | |||
| 225 | static struct sk_buff *tbf_dequeue(struct Qdisc *sch) | 229 | static struct sk_buff *tbf_dequeue(struct Qdisc *sch) |
| 226 | { | 230 | { |
| 227 | struct tbf_sched_data *q = qdisc_priv(sch); | 231 | struct tbf_sched_data *q = qdisc_priv(sch); |
| @@ -238,7 +242,7 @@ static struct sk_buff *tbf_dequeue(struct Qdisc *sch) | |||
| 238 | now = ktime_to_ns(ktime_get()); | 242 | now = ktime_to_ns(ktime_get()); |
| 239 | toks = min_t(s64, now - q->t_c, q->buffer); | 243 | toks = min_t(s64, now - q->t_c, q->buffer); |
| 240 | 244 | ||
| 241 | if (q->peak_present) { | 245 | if (tbf_peak_present(q)) { |
| 242 | ptoks = toks + q->ptokens; | 246 | ptoks = toks + q->ptokens; |
| 243 | if (ptoks > q->mtu) | 247 | if (ptoks > q->mtu) |
| 244 | ptoks = q->mtu; | 248 | ptoks = q->mtu; |
| @@ -366,6 +370,8 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt) | |||
| 366 | } else { | 370 | } else { |
| 367 | max_size = min_t(u64, max_size, psched_ns_t2l(&peak, mtu)); | 371 | max_size = min_t(u64, max_size, psched_ns_t2l(&peak, mtu)); |
| 368 | } | 372 | } |
| 373 | } else { | ||
| 374 | memset(&peak, 0, sizeof(peak)); | ||
| 369 | } | 375 | } |
| 370 | 376 | ||
| 371 | if (max_size < psched_mtu(qdisc_dev(sch))) | 377 | if (max_size < psched_mtu(qdisc_dev(sch))) |
| @@ -410,12 +416,7 @@ static int tbf_change(struct Qdisc *sch, struct nlattr *opt) | |||
| 410 | q->ptokens = q->mtu; | 416 | q->ptokens = q->mtu; |
| 411 | 417 | ||
| 412 | memcpy(&q->rate, &rate, sizeof(struct psched_ratecfg)); | 418 | memcpy(&q->rate, &rate, sizeof(struct psched_ratecfg)); |
| 413 | if (qopt->peakrate.rate) { | 419 | memcpy(&q->peak, &peak, sizeof(struct psched_ratecfg)); |
| 414 | memcpy(&q->peak, &peak, sizeof(struct psched_ratecfg)); | ||
| 415 | q->peak_present = true; | ||
| 416 | } else { | ||
| 417 | q->peak_present = false; | ||
| 418 | } | ||
| 419 | 420 | ||
| 420 | sch_tree_unlock(sch); | 421 | sch_tree_unlock(sch); |
| 421 | err = 0; | 422 | err = 0; |
| @@ -458,7 +459,7 @@ static int tbf_dump(struct Qdisc *sch, struct sk_buff *skb) | |||
| 458 | 459 | ||
| 459 | opt.limit = q->limit; | 460 | opt.limit = q->limit; |
| 460 | psched_ratecfg_getrate(&opt.rate, &q->rate); | 461 | psched_ratecfg_getrate(&opt.rate, &q->rate); |
| 461 | if (q->peak_present) | 462 | if (tbf_peak_present(q)) |
| 462 | psched_ratecfg_getrate(&opt.peakrate, &q->peak); | 463 | psched_ratecfg_getrate(&opt.peakrate, &q->peak); |
| 463 | else | 464 | else |
| 464 | memset(&opt.peakrate, 0, sizeof(opt.peakrate)); | 465 | memset(&opt.peakrate, 0, sizeof(opt.peakrate)); |
| @@ -469,13 +470,12 @@ static int tbf_dump(struct Qdisc *sch, struct sk_buff *skb) | |||
| 469 | if (q->rate.rate_bytes_ps >= (1ULL << 32) && | 470 | if (q->rate.rate_bytes_ps >= (1ULL << 32) && |
| 470 | nla_put_u64(skb, TCA_TBF_RATE64, q->rate.rate_bytes_ps)) | 471 | nla_put_u64(skb, TCA_TBF_RATE64, q->rate.rate_bytes_ps)) |
| 471 | goto nla_put_failure; | 472 | goto nla_put_failure; |
| 472 | if (q->peak_present && | 473 | if (tbf_peak_present(q) && |
| 473 | q->peak.rate_bytes_ps >= (1ULL << 32) && | 474 | q->peak.rate_bytes_ps >= (1ULL << 32) && |
| 474 | nla_put_u64(skb, TCA_TBF_PRATE64, q->peak.rate_bytes_ps)) | 475 | nla_put_u64(skb, TCA_TBF_PRATE64, q->peak.rate_bytes_ps)) |
| 475 | goto nla_put_failure; | 476 | goto nla_put_failure; |
| 476 | 477 | ||
| 477 | nla_nest_end(skb, nest); | 478 | return nla_nest_end(skb, nest); |
| 478 | return skb->len; | ||
| 479 | 479 | ||
| 480 | nla_put_failure: | 480 | nla_put_failure: |
| 481 | nla_nest_cancel(skb, nest); | 481 | nla_nest_cancel(skb, nest); |
diff --git a/net/sctp/associola.c b/net/sctp/associola.c index ee13d28d39d1..39579c3e0d14 100644 --- a/net/sctp/associola.c +++ b/net/sctp/associola.c | |||
| @@ -1319,8 +1319,7 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc) | |||
| 1319 | break; | 1319 | break; |
| 1320 | } | 1320 | } |
| 1321 | 1321 | ||
| 1322 | if (trans_next != NULL) | 1322 | asoc->peer.retran_path = trans_next; |
| 1323 | asoc->peer.retran_path = trans_next; | ||
| 1324 | 1323 | ||
| 1325 | pr_debug("%s: association:%p updated new path to addr:%pISpc\n", | 1324 | pr_debug("%s: association:%p updated new path to addr:%pISpc\n", |
| 1326 | __func__, asoc, &asoc->peer.retran_path->ipaddr.sa); | 1325 | __func__, asoc, &asoc->peer.retran_path->ipaddr.sa); |
| @@ -1396,35 +1395,44 @@ static inline bool sctp_peer_needs_update(struct sctp_association *asoc) | |||
| 1396 | return false; | 1395 | return false; |
| 1397 | } | 1396 | } |
| 1398 | 1397 | ||
| 1399 | /* Update asoc's rwnd for the approximated state in the buffer, | 1398 | /* Increase asoc's rwnd by len and send any window update SACK if needed. */ |
| 1400 | * and check whether SACK needs to be sent. | 1399 | void sctp_assoc_rwnd_increase(struct sctp_association *asoc, unsigned int len) |
| 1401 | */ | ||
| 1402 | void sctp_assoc_rwnd_update(struct sctp_association *asoc, bool update_peer) | ||
| 1403 | { | 1400 | { |
| 1404 | int rx_count; | ||
| 1405 | struct sctp_chunk *sack; | 1401 | struct sctp_chunk *sack; |
| 1406 | struct timer_list *timer; | 1402 | struct timer_list *timer; |
| 1407 | 1403 | ||
| 1408 | if (asoc->ep->rcvbuf_policy) | 1404 | if (asoc->rwnd_over) { |
| 1409 | rx_count = atomic_read(&asoc->rmem_alloc); | 1405 | if (asoc->rwnd_over >= len) { |
| 1410 | else | 1406 | asoc->rwnd_over -= len; |
| 1411 | rx_count = atomic_read(&asoc->base.sk->sk_rmem_alloc); | 1407 | } else { |
| 1408 | asoc->rwnd += (len - asoc->rwnd_over); | ||
| 1409 | asoc->rwnd_over = 0; | ||
| 1410 | } | ||
| 1411 | } else { | ||
| 1412 | asoc->rwnd += len; | ||
| 1413 | } | ||
| 1412 | 1414 | ||
| 1413 | if ((asoc->base.sk->sk_rcvbuf - rx_count) > 0) | 1415 | /* If we had window pressure, start recovering it |
| 1414 | asoc->rwnd = (asoc->base.sk->sk_rcvbuf - rx_count) >> 1; | 1416 | * once our rwnd had reached the accumulated pressure |
| 1415 | else | 1417 | * threshold. The idea is to recover slowly, but up |
| 1416 | asoc->rwnd = 0; | 1418 | * to the initial advertised window. |
| 1419 | */ | ||
| 1420 | if (asoc->rwnd_press && asoc->rwnd >= asoc->rwnd_press) { | ||
| 1421 | int change = min(asoc->pathmtu, asoc->rwnd_press); | ||
| 1422 | asoc->rwnd += change; | ||
| 1423 | asoc->rwnd_press -= change; | ||
| 1424 | } | ||
| 1417 | 1425 | ||
| 1418 | pr_debug("%s: asoc:%p rwnd=%u, rx_count=%d, sk_rcvbuf=%d\n", | 1426 | pr_debug("%s: asoc:%p rwnd increased by %d to (%u, %u) - %u\n", |
| 1419 | __func__, asoc, asoc->rwnd, rx_count, | 1427 | __func__, asoc, len, asoc->rwnd, asoc->rwnd_over, |
| 1420 | asoc->base.sk->sk_rcvbuf); | 1428 | asoc->a_rwnd); |
| 1421 | 1429 | ||
| 1422 | /* Send a window update SACK if the rwnd has increased by at least the | 1430 | /* Send a window update SACK if the rwnd has increased by at least the |
| 1423 | * minimum of the association's PMTU and half of the receive buffer. | 1431 | * minimum of the association's PMTU and half of the receive buffer. |
| 1424 | * The algorithm used is similar to the one described in | 1432 | * The algorithm used is similar to the one described in |
| 1425 | * Section 4.2.3.3 of RFC 1122. | 1433 | * Section 4.2.3.3 of RFC 1122. |
| 1426 | */ | 1434 | */ |
| 1427 | if (update_peer && sctp_peer_needs_update(asoc)) { | 1435 | if (sctp_peer_needs_update(asoc)) { |
| 1428 | asoc->a_rwnd = asoc->rwnd; | 1436 | asoc->a_rwnd = asoc->rwnd; |
| 1429 | 1437 | ||
| 1430 | pr_debug("%s: sending window update SACK- asoc:%p rwnd:%u " | 1438 | pr_debug("%s: sending window update SACK- asoc:%p rwnd:%u " |
| @@ -1446,6 +1454,45 @@ void sctp_assoc_rwnd_update(struct sctp_association *asoc, bool update_peer) | |||
| 1446 | } | 1454 | } |
| 1447 | } | 1455 | } |
| 1448 | 1456 | ||
| 1457 | /* Decrease asoc's rwnd by len. */ | ||
| 1458 | void sctp_assoc_rwnd_decrease(struct sctp_association *asoc, unsigned int len) | ||
| 1459 | { | ||
| 1460 | int rx_count; | ||
| 1461 | int over = 0; | ||
| 1462 | |||
| 1463 | if (unlikely(!asoc->rwnd || asoc->rwnd_over)) | ||
| 1464 | pr_debug("%s: association:%p has asoc->rwnd:%u, " | ||
| 1465 | "asoc->rwnd_over:%u!\n", __func__, asoc, | ||
| 1466 | asoc->rwnd, asoc->rwnd_over); | ||
| 1467 | |||
| 1468 | if (asoc->ep->rcvbuf_policy) | ||
| 1469 | rx_count = atomic_read(&asoc->rmem_alloc); | ||
| 1470 | else | ||
| 1471 | rx_count = atomic_read(&asoc->base.sk->sk_rmem_alloc); | ||
| 1472 | |||
| 1473 | /* If we've reached or overflowed our receive buffer, announce | ||
| 1474 | * a 0 rwnd if rwnd would still be positive. Store the | ||
| 1475 | * the potential pressure overflow so that the window can be restored | ||
| 1476 | * back to original value. | ||
| 1477 | */ | ||
| 1478 | if (rx_count >= asoc->base.sk->sk_rcvbuf) | ||
| 1479 | over = 1; | ||
| 1480 | |||
| 1481 | if (asoc->rwnd >= len) { | ||
| 1482 | asoc->rwnd -= len; | ||
| 1483 | if (over) { | ||
| 1484 | asoc->rwnd_press += asoc->rwnd; | ||
| 1485 | asoc->rwnd = 0; | ||
| 1486 | } | ||
| 1487 | } else { | ||
| 1488 | asoc->rwnd_over = len - asoc->rwnd; | ||
| 1489 | asoc->rwnd = 0; | ||
| 1490 | } | ||
| 1491 | |||
| 1492 | pr_debug("%s: asoc:%p rwnd decreased by %d to (%u, %u, %u)\n", | ||
| 1493 | __func__, asoc, len, asoc->rwnd, asoc->rwnd_over, | ||
| 1494 | asoc->rwnd_press); | ||
| 1495 | } | ||
| 1449 | 1496 | ||
| 1450 | /* Build the bind address list for the association based on info from the | 1497 | /* Build the bind address list for the association based on info from the |
| 1451 | * local endpoint and the remote peer. | 1498 | * local endpoint and the remote peer. |
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c index 4e1d0fcb028e..c09757fbf803 100644 --- a/net/sctp/protocol.c +++ b/net/sctp/protocol.c | |||
| @@ -957,7 +957,7 @@ static inline int sctp_v4_xmit(struct sk_buff *skb, | |||
| 957 | 957 | ||
| 958 | SCTP_INC_STATS(sock_net(&inet->sk), SCTP_MIB_OUTSCTPPACKS); | 958 | SCTP_INC_STATS(sock_net(&inet->sk), SCTP_MIB_OUTSCTPPACKS); |
| 959 | 959 | ||
| 960 | return ip_queue_xmit(skb, &transport->fl); | 960 | return ip_queue_xmit(&inet->sk, skb, &transport->fl); |
| 961 | } | 961 | } |
| 962 | 962 | ||
| 963 | static struct sctp_af sctp_af_inet; | 963 | static struct sctp_af sctp_af_inet; |
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c index 01e002430c85..ae9fbeba40b0 100644 --- a/net/sctp/sm_statefuns.c +++ b/net/sctp/sm_statefuns.c | |||
| @@ -6178,7 +6178,7 @@ static int sctp_eat_data(const struct sctp_association *asoc, | |||
| 6178 | * PMTU. In cases, such as loopback, this might be a rather | 6178 | * PMTU. In cases, such as loopback, this might be a rather |
| 6179 | * large spill over. | 6179 | * large spill over. |
| 6180 | */ | 6180 | */ |
| 6181 | if ((!chunk->data_accepted) && (!asoc->rwnd || | 6181 | if ((!chunk->data_accepted) && (!asoc->rwnd || asoc->rwnd_over || |
| 6182 | (datalen > asoc->rwnd + asoc->frag_point))) { | 6182 | (datalen > asoc->rwnd + asoc->frag_point))) { |
| 6183 | 6183 | ||
| 6184 | /* If this is the next TSN, consider reneging to make | 6184 | /* If this is the next TSN, consider reneging to make |
diff --git a/net/sctp/socket.c b/net/sctp/socket.c index 981aaf8b6ace..ff20e2dbbbc7 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c | |||
| @@ -2115,6 +2115,12 @@ static int sctp_recvmsg(struct kiocb *iocb, struct sock *sk, | |||
| 2115 | sctp_skb_pull(skb, copied); | 2115 | sctp_skb_pull(skb, copied); |
| 2116 | skb_queue_head(&sk->sk_receive_queue, skb); | 2116 | skb_queue_head(&sk->sk_receive_queue, skb); |
| 2117 | 2117 | ||
| 2118 | /* When only partial message is copied to the user, increase | ||
| 2119 | * rwnd by that amount. If all the data in the skb is read, | ||
| 2120 | * rwnd is updated when the event is freed. | ||
| 2121 | */ | ||
| 2122 | if (!sctp_ulpevent_is_notification(event)) | ||
| 2123 | sctp_assoc_rwnd_increase(event->asoc, copied); | ||
| 2118 | goto out; | 2124 | goto out; |
| 2119 | } else if ((event->msg_flags & MSG_NOTIFICATION) || | 2125 | } else if ((event->msg_flags & MSG_NOTIFICATION) || |
| 2120 | (event->msg_flags & MSG_EOR)) | 2126 | (event->msg_flags & MSG_EOR)) |
| @@ -6593,6 +6599,46 @@ static void __sctp_write_space(struct sctp_association *asoc) | |||
| 6593 | } | 6599 | } |
| 6594 | } | 6600 | } |
| 6595 | 6601 | ||
| 6602 | static void sctp_wake_up_waiters(struct sock *sk, | ||
| 6603 | struct sctp_association *asoc) | ||
| 6604 | { | ||
| 6605 | struct sctp_association *tmp = asoc; | ||
| 6606 | |||
| 6607 | /* We do accounting for the sndbuf space per association, | ||
| 6608 | * so we only need to wake our own association. | ||
| 6609 | */ | ||
| 6610 | if (asoc->ep->sndbuf_policy) | ||
| 6611 | return __sctp_write_space(asoc); | ||
| 6612 | |||
| 6613 | /* If association goes down and is just flushing its | ||
| 6614 | * outq, then just normally notify others. | ||
| 6615 | */ | ||
| 6616 | if (asoc->base.dead) | ||
| 6617 | return sctp_write_space(sk); | ||
| 6618 | |||
| 6619 | /* Accounting for the sndbuf space is per socket, so we | ||
| 6620 | * need to wake up others, try to be fair and in case of | ||
| 6621 | * other associations, let them have a go first instead | ||
| 6622 | * of just doing a sctp_write_space() call. | ||
| 6623 | * | ||
| 6624 | * Note that we reach sctp_wake_up_waiters() only when | ||
| 6625 | * associations free up queued chunks, thus we are under | ||
| 6626 | * lock and the list of associations on a socket is | ||
| 6627 | * guaranteed not to change. | ||
| 6628 | */ | ||
| 6629 | for (tmp = list_next_entry(tmp, asocs); 1; | ||
| 6630 | tmp = list_next_entry(tmp, asocs)) { | ||
| 6631 | /* Manually skip the head element. */ | ||
| 6632 | if (&tmp->asocs == &((sctp_sk(sk))->ep->asocs)) | ||
| 6633 | continue; | ||
| 6634 | /* Wake up association. */ | ||
| 6635 | __sctp_write_space(tmp); | ||
| 6636 | /* We've reached the end. */ | ||
| 6637 | if (tmp == asoc) | ||
| 6638 | break; | ||
| 6639 | } | ||
| 6640 | } | ||
| 6641 | |||
| 6596 | /* Do accounting for the sndbuf space. | 6642 | /* Do accounting for the sndbuf space. |
| 6597 | * Decrement the used sndbuf space of the corresponding association by the | 6643 | * Decrement the used sndbuf space of the corresponding association by the |
| 6598 | * data size which was just transmitted(freed). | 6644 | * data size which was just transmitted(freed). |
| @@ -6620,7 +6666,7 @@ static void sctp_wfree(struct sk_buff *skb) | |||
| 6620 | sk_mem_uncharge(sk, skb->truesize); | 6666 | sk_mem_uncharge(sk, skb->truesize); |
| 6621 | 6667 | ||
| 6622 | sock_wfree(skb); | 6668 | sock_wfree(skb); |
| 6623 | __sctp_write_space(asoc); | 6669 | sctp_wake_up_waiters(sk, asoc); |
| 6624 | 6670 | ||
| 6625 | sctp_association_put(asoc); | 6671 | sctp_association_put(asoc); |
| 6626 | } | 6672 | } |
| @@ -6705,7 +6751,7 @@ do_nonblock: | |||
| 6705 | goto out; | 6751 | goto out; |
| 6706 | } | 6752 | } |
| 6707 | 6753 | ||
| 6708 | void sctp_data_ready(struct sock *sk, int len) | 6754 | void sctp_data_ready(struct sock *sk) |
| 6709 | { | 6755 | { |
| 6710 | struct socket_wq *wq; | 6756 | struct socket_wq *wq; |
| 6711 | 6757 | ||
diff --git a/net/sctp/transport.c b/net/sctp/transport.c index d0810dc5f079..1d348d15b33d 100644 --- a/net/sctp/transport.c +++ b/net/sctp/transport.c | |||
| @@ -652,5 +652,4 @@ void sctp_transport_immediate_rtx(struct sctp_transport *t) | |||
| 652 | if (!mod_timer(&t->T3_rtx_timer, jiffies + t->rto)) | 652 | if (!mod_timer(&t->T3_rtx_timer, jiffies + t->rto)) |
| 653 | sctp_transport_hold(t); | 653 | sctp_transport_hold(t); |
| 654 | } | 654 | } |
| 655 | return; | ||
| 656 | } | 655 | } |
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c index 8d198ae03606..85c64658bd0b 100644 --- a/net/sctp/ulpevent.c +++ b/net/sctp/ulpevent.c | |||
| @@ -989,7 +989,7 @@ static void sctp_ulpevent_receive_data(struct sctp_ulpevent *event, | |||
| 989 | skb = sctp_event2skb(event); | 989 | skb = sctp_event2skb(event); |
| 990 | /* Set the owner and charge rwnd for bytes received. */ | 990 | /* Set the owner and charge rwnd for bytes received. */ |
| 991 | sctp_ulpevent_set_owner(event, asoc); | 991 | sctp_ulpevent_set_owner(event, asoc); |
| 992 | sctp_assoc_rwnd_update(asoc, false); | 992 | sctp_assoc_rwnd_decrease(asoc, skb_headlen(skb)); |
| 993 | 993 | ||
| 994 | if (!skb->data_len) | 994 | if (!skb->data_len) |
| 995 | return; | 995 | return; |
| @@ -1011,7 +1011,6 @@ static void sctp_ulpevent_release_data(struct sctp_ulpevent *event) | |||
| 1011 | { | 1011 | { |
| 1012 | struct sk_buff *skb, *frag; | 1012 | struct sk_buff *skb, *frag; |
| 1013 | unsigned int len; | 1013 | unsigned int len; |
| 1014 | struct sctp_association *asoc; | ||
| 1015 | 1014 | ||
| 1016 | /* Current stack structures assume that the rcv buffer is | 1015 | /* Current stack structures assume that the rcv buffer is |
| 1017 | * per socket. For UDP style sockets this is not true as | 1016 | * per socket. For UDP style sockets this is not true as |
| @@ -1036,11 +1035,8 @@ static void sctp_ulpevent_release_data(struct sctp_ulpevent *event) | |||
| 1036 | } | 1035 | } |
| 1037 | 1036 | ||
| 1038 | done: | 1037 | done: |
| 1039 | asoc = event->asoc; | 1038 | sctp_assoc_rwnd_increase(event->asoc, len); |
| 1040 | sctp_association_hold(asoc); | ||
| 1041 | sctp_ulpevent_release_owner(event); | 1039 | sctp_ulpevent_release_owner(event); |
| 1042 | sctp_assoc_rwnd_update(asoc, true); | ||
| 1043 | sctp_association_put(asoc); | ||
| 1044 | } | 1040 | } |
| 1045 | 1041 | ||
| 1046 | static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event) | 1042 | static void sctp_ulpevent_release_frag_data(struct sctp_ulpevent *event) |
diff --git a/net/sctp/ulpqueue.c b/net/sctp/ulpqueue.c index 5dc94117e9d4..7144eb6a1b95 100644 --- a/net/sctp/ulpqueue.c +++ b/net/sctp/ulpqueue.c | |||
| @@ -259,7 +259,7 @@ int sctp_ulpq_tail_event(struct sctp_ulpq *ulpq, struct sctp_ulpevent *event) | |||
| 259 | sctp_ulpq_clear_pd(ulpq); | 259 | sctp_ulpq_clear_pd(ulpq); |
| 260 | 260 | ||
| 261 | if (queue == &sk->sk_receive_queue) | 261 | if (queue == &sk->sk_receive_queue) |
| 262 | sk->sk_data_ready(sk, 0); | 262 | sk->sk_data_ready(sk); |
| 263 | return 1; | 263 | return 1; |
| 264 | 264 | ||
| 265 | out_free: | 265 | out_free: |
| @@ -1135,5 +1135,5 @@ void sctp_ulpq_abort_pd(struct sctp_ulpq *ulpq, gfp_t gfp) | |||
| 1135 | 1135 | ||
| 1136 | /* If there is data waiting, send it up the socket now. */ | 1136 | /* If there is data waiting, send it up the socket now. */ |
| 1137 | if (sctp_ulpq_clear_pd(ulpq) || ev) | 1137 | if (sctp_ulpq_clear_pd(ulpq) || ev) |
| 1138 | sk->sk_data_ready(sk, 0); | 1138 | sk->sk_data_ready(sk); |
| 1139 | } | 1139 | } |
diff --git a/net/socket.c b/net/socket.c index a19ae1968d37..1b1e7e6a960f 100644 --- a/net/socket.c +++ b/net/socket.c | |||
| @@ -72,6 +72,7 @@ | |||
| 72 | #include <linux/if_bridge.h> | 72 | #include <linux/if_bridge.h> |
| 73 | #include <linux/if_frad.h> | 73 | #include <linux/if_frad.h> |
| 74 | #include <linux/if_vlan.h> | 74 | #include <linux/if_vlan.h> |
| 75 | #include <linux/ptp_classify.h> | ||
| 75 | #include <linux/init.h> | 76 | #include <linux/init.h> |
| 76 | #include <linux/poll.h> | 77 | #include <linux/poll.h> |
| 77 | #include <linux/cache.h> | 78 | #include <linux/cache.h> |
| @@ -594,7 +595,7 @@ void sock_release(struct socket *sock) | |||
| 594 | } | 595 | } |
| 595 | 596 | ||
| 596 | if (rcu_dereference_protected(sock->wq, 1)->fasync_list) | 597 | if (rcu_dereference_protected(sock->wq, 1)->fasync_list) |
| 597 | printk(KERN_ERR "sock_release: fasync list not empty!\n"); | 598 | pr_err("%s: fasync list not empty!\n", __func__); |
| 598 | 599 | ||
| 599 | if (test_bit(SOCK_EXTERNALLY_ALLOCATED, &sock->flags)) | 600 | if (test_bit(SOCK_EXTERNALLY_ALLOCATED, &sock->flags)) |
| 600 | return; | 601 | return; |
| @@ -1266,8 +1267,8 @@ int __sock_create(struct net *net, int family, int type, int protocol, | |||
| 1266 | static int warned; | 1267 | static int warned; |
| 1267 | if (!warned) { | 1268 | if (!warned) { |
| 1268 | warned = 1; | 1269 | warned = 1; |
| 1269 | printk(KERN_INFO "%s uses obsolete (PF_INET,SOCK_PACKET)\n", | 1270 | pr_info("%s uses obsolete (PF_INET,SOCK_PACKET)\n", |
| 1270 | current->comm); | 1271 | current->comm); |
| 1271 | } | 1272 | } |
| 1272 | family = PF_PACKET; | 1273 | family = PF_PACKET; |
| 1273 | } | 1274 | } |
| @@ -2600,8 +2601,7 @@ int sock_register(const struct net_proto_family *ops) | |||
| 2600 | int err; | 2601 | int err; |
| 2601 | 2602 | ||
| 2602 | if (ops->family >= NPROTO) { | 2603 | if (ops->family >= NPROTO) { |
| 2603 | printk(KERN_CRIT "protocol %d >= NPROTO(%d)\n", ops->family, | 2604 | pr_crit("protocol %d >= NPROTO(%d)\n", ops->family, NPROTO); |
| 2604 | NPROTO); | ||
| 2605 | return -ENOBUFS; | 2605 | return -ENOBUFS; |
| 2606 | } | 2606 | } |
| 2607 | 2607 | ||
| @@ -2615,7 +2615,7 @@ int sock_register(const struct net_proto_family *ops) | |||
| 2615 | } | 2615 | } |
| 2616 | spin_unlock(&net_family_lock); | 2616 | spin_unlock(&net_family_lock); |
| 2617 | 2617 | ||
| 2618 | printk(KERN_INFO "NET: Registered protocol family %d\n", ops->family); | 2618 | pr_info("NET: Registered protocol family %d\n", ops->family); |
| 2619 | return err; | 2619 | return err; |
| 2620 | } | 2620 | } |
| 2621 | EXPORT_SYMBOL(sock_register); | 2621 | EXPORT_SYMBOL(sock_register); |
| @@ -2643,7 +2643,7 @@ void sock_unregister(int family) | |||
| 2643 | 2643 | ||
| 2644 | synchronize_rcu(); | 2644 | synchronize_rcu(); |
| 2645 | 2645 | ||
| 2646 | printk(KERN_INFO "NET: Unregistered protocol family %d\n", family); | 2646 | pr_info("NET: Unregistered protocol family %d\n", family); |
| 2647 | } | 2647 | } |
| 2648 | EXPORT_SYMBOL(sock_unregister); | 2648 | EXPORT_SYMBOL(sock_unregister); |
| 2649 | 2649 | ||
| @@ -2686,9 +2686,7 @@ static int __init sock_init(void) | |||
| 2686 | goto out; | 2686 | goto out; |
| 2687 | #endif | 2687 | #endif |
| 2688 | 2688 | ||
| 2689 | #ifdef CONFIG_NETWORK_PHY_TIMESTAMPING | 2689 | ptp_classifier_init(); |
| 2690 | skb_timestamping_init(); | ||
| 2691 | #endif | ||
| 2692 | 2690 | ||
| 2693 | out: | 2691 | out: |
| 2694 | return err; | 2692 | return err; |
diff --git a/net/sunrpc/Kconfig b/net/sunrpc/Kconfig index 241b54f30204..0754d0f466d2 100644 --- a/net/sunrpc/Kconfig +++ b/net/sunrpc/Kconfig | |||
| @@ -9,19 +9,6 @@ config SUNRPC_BACKCHANNEL | |||
| 9 | bool | 9 | bool |
| 10 | depends on SUNRPC | 10 | depends on SUNRPC |
| 11 | 11 | ||
| 12 | config SUNRPC_XPRT_RDMA | ||
| 13 | tristate | ||
| 14 | depends on SUNRPC && INFINIBAND && INFINIBAND_ADDR_TRANS | ||
| 15 | default SUNRPC && INFINIBAND | ||
| 16 | help | ||
| 17 | This option allows the NFS client and server to support | ||
| 18 | an RDMA-enabled transport. | ||
| 19 | |||
| 20 | To compile RPC client RDMA transport support as a module, | ||
| 21 | choose M here: the module will be called xprtrdma. | ||
| 22 | |||
| 23 | If unsure, say N. | ||
| 24 | |||
| 25 | config SUNRPC_SWAP | 12 | config SUNRPC_SWAP |
| 26 | bool | 13 | bool |
| 27 | depends on SUNRPC | 14 | depends on SUNRPC |
| @@ -57,3 +44,29 @@ config SUNRPC_DEBUG | |||
| 57 | but makes troubleshooting NFS issues significantly harder. | 44 | but makes troubleshooting NFS issues significantly harder. |
| 58 | 45 | ||
| 59 | If unsure, say Y. | 46 | If unsure, say Y. |
| 47 | |||
| 48 | config SUNRPC_XPRT_RDMA_CLIENT | ||
| 49 | tristate "RPC over RDMA Client Support" | ||
| 50 | depends on SUNRPC && INFINIBAND && INFINIBAND_ADDR_TRANS | ||
| 51 | default SUNRPC && INFINIBAND | ||
| 52 | help | ||
| 53 | This option allows the NFS client to support an RDMA-enabled | ||
| 54 | transport. | ||
| 55 | |||
| 56 | To compile RPC client RDMA transport support as a module, | ||
| 57 | choose M here: the module will be called xprtrdma. | ||
| 58 | |||
| 59 | If unsure, say N. | ||
| 60 | |||
| 61 | config SUNRPC_XPRT_RDMA_SERVER | ||
| 62 | tristate "RPC over RDMA Server Support" | ||
| 63 | depends on SUNRPC && INFINIBAND && INFINIBAND_ADDR_TRANS | ||
| 64 | default SUNRPC && INFINIBAND | ||
| 65 | help | ||
| 66 | This option allows the NFS server to support an RDMA-enabled | ||
| 67 | transport. | ||
| 68 | |||
| 69 | To compile RPC server RDMA transport support as a module, | ||
| 70 | choose M here: the module will be called svcrdma. | ||
| 71 | |||
| 72 | If unsure, say N. | ||
diff --git a/net/sunrpc/Makefile b/net/sunrpc/Makefile index 8209a0411bca..e5a7a1cac8f3 100644 --- a/net/sunrpc/Makefile +++ b/net/sunrpc/Makefile | |||
| @@ -5,7 +5,8 @@ | |||
| 5 | 5 | ||
| 6 | obj-$(CONFIG_SUNRPC) += sunrpc.o | 6 | obj-$(CONFIG_SUNRPC) += sunrpc.o |
| 7 | obj-$(CONFIG_SUNRPC_GSS) += auth_gss/ | 7 | obj-$(CONFIG_SUNRPC_GSS) += auth_gss/ |
| 8 | obj-$(CONFIG_SUNRPC_XPRT_RDMA) += xprtrdma/ | 8 | |
| 9 | obj-y += xprtrdma/ | ||
| 9 | 10 | ||
| 10 | sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \ | 11 | sunrpc-y := clnt.o xprt.o socklib.o xprtsock.o sched.o \ |
| 11 | auth.o auth_null.o auth_unix.o auth_generic.o \ | 12 | auth.o auth_null.o auth_unix.o auth_generic.o \ |
diff --git a/net/sunrpc/backchannel_rqst.c b/net/sunrpc/backchannel_rqst.c index e860d4f7ed2a..3513d559bc45 100644 --- a/net/sunrpc/backchannel_rqst.c +++ b/net/sunrpc/backchannel_rqst.c | |||
| @@ -212,39 +212,23 @@ out: | |||
| 212 | } | 212 | } |
| 213 | EXPORT_SYMBOL_GPL(xprt_destroy_backchannel); | 213 | EXPORT_SYMBOL_GPL(xprt_destroy_backchannel); |
| 214 | 214 | ||
| 215 | /* | 215 | static struct rpc_rqst *xprt_alloc_bc_request(struct rpc_xprt *xprt, __be32 xid) |
| 216 | * One or more rpc_rqst structure have been preallocated during the | ||
| 217 | * backchannel setup. Buffer space for the send and private XDR buffers | ||
| 218 | * has been preallocated as well. Use xprt_alloc_bc_request to allocate | ||
| 219 | * to this request. Use xprt_free_bc_request to return it. | ||
| 220 | * | ||
| 221 | * We know that we're called in soft interrupt context, grab the spin_lock | ||
| 222 | * since there is no need to grab the bottom half spin_lock. | ||
| 223 | * | ||
| 224 | * Return an available rpc_rqst, otherwise NULL if non are available. | ||
| 225 | */ | ||
| 226 | struct rpc_rqst *xprt_alloc_bc_request(struct rpc_xprt *xprt) | ||
| 227 | { | 216 | { |
| 228 | struct rpc_rqst *req; | 217 | struct rpc_rqst *req = NULL; |
| 229 | 218 | ||
| 230 | dprintk("RPC: allocate a backchannel request\n"); | 219 | dprintk("RPC: allocate a backchannel request\n"); |
| 231 | spin_lock(&xprt->bc_pa_lock); | 220 | if (list_empty(&xprt->bc_pa_list)) |
| 232 | if (!list_empty(&xprt->bc_pa_list)) { | 221 | goto not_found; |
| 233 | req = list_first_entry(&xprt->bc_pa_list, struct rpc_rqst, | ||
| 234 | rq_bc_pa_list); | ||
| 235 | list_del(&req->rq_bc_pa_list); | ||
| 236 | } else { | ||
| 237 | req = NULL; | ||
| 238 | } | ||
| 239 | spin_unlock(&xprt->bc_pa_lock); | ||
| 240 | 222 | ||
| 241 | if (req != NULL) { | 223 | req = list_first_entry(&xprt->bc_pa_list, struct rpc_rqst, |
| 242 | set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state); | 224 | rq_bc_pa_list); |
| 243 | req->rq_reply_bytes_recvd = 0; | 225 | req->rq_reply_bytes_recvd = 0; |
| 244 | req->rq_bytes_sent = 0; | 226 | req->rq_bytes_sent = 0; |
| 245 | memcpy(&req->rq_private_buf, &req->rq_rcv_buf, | 227 | memcpy(&req->rq_private_buf, &req->rq_rcv_buf, |
| 246 | sizeof(req->rq_private_buf)); | 228 | sizeof(req->rq_private_buf)); |
| 247 | } | 229 | req->rq_xid = xid; |
| 230 | req->rq_connect_cookie = xprt->connect_cookie; | ||
| 231 | not_found: | ||
| 248 | dprintk("RPC: backchannel req=%p\n", req); | 232 | dprintk("RPC: backchannel req=%p\n", req); |
| 249 | return req; | 233 | return req; |
| 250 | } | 234 | } |
| @@ -259,6 +243,7 @@ void xprt_free_bc_request(struct rpc_rqst *req) | |||
| 259 | 243 | ||
| 260 | dprintk("RPC: free backchannel req=%p\n", req); | 244 | dprintk("RPC: free backchannel req=%p\n", req); |
| 261 | 245 | ||
| 246 | req->rq_connect_cookie = xprt->connect_cookie - 1; | ||
| 262 | smp_mb__before_clear_bit(); | 247 | smp_mb__before_clear_bit(); |
| 263 | WARN_ON_ONCE(!test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state)); | 248 | WARN_ON_ONCE(!test_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state)); |
| 264 | clear_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state); | 249 | clear_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state); |
| @@ -281,7 +266,57 @@ void xprt_free_bc_request(struct rpc_rqst *req) | |||
| 281 | * may be reused by a new callback request. | 266 | * may be reused by a new callback request. |
| 282 | */ | 267 | */ |
| 283 | spin_lock_bh(&xprt->bc_pa_lock); | 268 | spin_lock_bh(&xprt->bc_pa_lock); |
| 284 | list_add(&req->rq_bc_pa_list, &xprt->bc_pa_list); | 269 | list_add_tail(&req->rq_bc_pa_list, &xprt->bc_pa_list); |
| 285 | spin_unlock_bh(&xprt->bc_pa_lock); | 270 | spin_unlock_bh(&xprt->bc_pa_lock); |
| 286 | } | 271 | } |
| 287 | 272 | ||
| 273 | /* | ||
| 274 | * One or more rpc_rqst structure have been preallocated during the | ||
| 275 | * backchannel setup. Buffer space for the send and private XDR buffers | ||
| 276 | * has been preallocated as well. Use xprt_alloc_bc_request to allocate | ||
| 277 | * to this request. Use xprt_free_bc_request to return it. | ||
| 278 | * | ||
| 279 | * We know that we're called in soft interrupt context, grab the spin_lock | ||
| 280 | * since there is no need to grab the bottom half spin_lock. | ||
| 281 | * | ||
| 282 | * Return an available rpc_rqst, otherwise NULL if non are available. | ||
| 283 | */ | ||
| 284 | struct rpc_rqst *xprt_lookup_bc_request(struct rpc_xprt *xprt, __be32 xid) | ||
| 285 | { | ||
| 286 | struct rpc_rqst *req; | ||
| 287 | |||
| 288 | spin_lock(&xprt->bc_pa_lock); | ||
| 289 | list_for_each_entry(req, &xprt->bc_pa_list, rq_bc_pa_list) { | ||
| 290 | if (req->rq_connect_cookie != xprt->connect_cookie) | ||
| 291 | continue; | ||
| 292 | if (req->rq_xid == xid) | ||
| 293 | goto found; | ||
| 294 | } | ||
| 295 | req = xprt_alloc_bc_request(xprt, xid); | ||
| 296 | found: | ||
| 297 | spin_unlock(&xprt->bc_pa_lock); | ||
| 298 | return req; | ||
| 299 | } | ||
| 300 | |||
| 301 | /* | ||
| 302 | * Add callback request to callback list. The callback | ||
| 303 | * service sleeps on the sv_cb_waitq waiting for new | ||
| 304 | * requests. Wake it up after adding enqueing the | ||
| 305 | * request. | ||
| 306 | */ | ||
| 307 | void xprt_complete_bc_request(struct rpc_rqst *req, uint32_t copied) | ||
| 308 | { | ||
| 309 | struct rpc_xprt *xprt = req->rq_xprt; | ||
| 310 | struct svc_serv *bc_serv = xprt->bc_serv; | ||
| 311 | |||
| 312 | req->rq_private_buf.len = copied; | ||
| 313 | set_bit(RPC_BC_PA_IN_USE, &req->rq_bc_pa_state); | ||
| 314 | |||
| 315 | dprintk("RPC: add callback request to list\n"); | ||
| 316 | spin_lock(&bc_serv->sv_cb_lock); | ||
| 317 | list_del(&req->rq_bc_pa_list); | ||
| 318 | list_add(&req->rq_bc_list, &bc_serv->sv_cb_list); | ||
| 319 | wake_up(&bc_serv->sv_cb_waitq); | ||
| 320 | spin_unlock(&bc_serv->sv_cb_lock); | ||
| 321 | } | ||
| 322 | |||
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 0edada973434..2e6ab10734f6 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
| @@ -438,6 +438,38 @@ out_no_rpciod: | |||
| 438 | return ERR_PTR(err); | 438 | return ERR_PTR(err); |
| 439 | } | 439 | } |
| 440 | 440 | ||
| 441 | struct rpc_clnt *rpc_create_xprt(struct rpc_create_args *args, | ||
| 442 | struct rpc_xprt *xprt) | ||
| 443 | { | ||
| 444 | struct rpc_clnt *clnt = NULL; | ||
| 445 | |||
| 446 | clnt = rpc_new_client(args, xprt, NULL); | ||
| 447 | if (IS_ERR(clnt)) | ||
| 448 | return clnt; | ||
| 449 | |||
| 450 | if (!(args->flags & RPC_CLNT_CREATE_NOPING)) { | ||
| 451 | int err = rpc_ping(clnt); | ||
| 452 | if (err != 0) { | ||
| 453 | rpc_shutdown_client(clnt); | ||
| 454 | return ERR_PTR(err); | ||
| 455 | } | ||
| 456 | } | ||
| 457 | |||
| 458 | clnt->cl_softrtry = 1; | ||
| 459 | if (args->flags & RPC_CLNT_CREATE_HARDRTRY) | ||
| 460 | clnt->cl_softrtry = 0; | ||
| 461 | |||
| 462 | if (args->flags & RPC_CLNT_CREATE_AUTOBIND) | ||
| 463 | clnt->cl_autobind = 1; | ||
| 464 | if (args->flags & RPC_CLNT_CREATE_DISCRTRY) | ||
| 465 | clnt->cl_discrtry = 1; | ||
| 466 | if (!(args->flags & RPC_CLNT_CREATE_QUIET)) | ||
| 467 | clnt->cl_chatty = 1; | ||
| 468 | |||
| 469 | return clnt; | ||
| 470 | } | ||
| 471 | EXPORT_SYMBOL_GPL(rpc_create_xprt); | ||
| 472 | |||
| 441 | /** | 473 | /** |
| 442 | * rpc_create - create an RPC client and transport with one call | 474 | * rpc_create - create an RPC client and transport with one call |
| 443 | * @args: rpc_clnt create argument structure | 475 | * @args: rpc_clnt create argument structure |
| @@ -451,7 +483,6 @@ out_no_rpciod: | |||
| 451 | struct rpc_clnt *rpc_create(struct rpc_create_args *args) | 483 | struct rpc_clnt *rpc_create(struct rpc_create_args *args) |
| 452 | { | 484 | { |
| 453 | struct rpc_xprt *xprt; | 485 | struct rpc_xprt *xprt; |
| 454 | struct rpc_clnt *clnt; | ||
| 455 | struct xprt_create xprtargs = { | 486 | struct xprt_create xprtargs = { |
| 456 | .net = args->net, | 487 | .net = args->net, |
| 457 | .ident = args->protocol, | 488 | .ident = args->protocol, |
| @@ -515,30 +546,7 @@ struct rpc_clnt *rpc_create(struct rpc_create_args *args) | |||
| 515 | if (args->flags & RPC_CLNT_CREATE_NONPRIVPORT) | 546 | if (args->flags & RPC_CLNT_CREATE_NONPRIVPORT) |
| 516 | xprt->resvport = 0; | 547 | xprt->resvport = 0; |
| 517 | 548 | ||
| 518 | clnt = rpc_new_client(args, xprt, NULL); | 549 | return rpc_create_xprt(args, xprt); |
| 519 | if (IS_ERR(clnt)) | ||
| 520 | return clnt; | ||
| 521 | |||
| 522 | if (!(args->flags & RPC_CLNT_CREATE_NOPING)) { | ||
| 523 | int err = rpc_ping(clnt); | ||
| 524 | if (err != 0) { | ||
| 525 | rpc_shutdown_client(clnt); | ||
| 526 | return ERR_PTR(err); | ||
| 527 | } | ||
| 528 | } | ||
| 529 | |||
| 530 | clnt->cl_softrtry = 1; | ||
| 531 | if (args->flags & RPC_CLNT_CREATE_HARDRTRY) | ||
| 532 | clnt->cl_softrtry = 0; | ||
| 533 | |||
| 534 | if (args->flags & RPC_CLNT_CREATE_AUTOBIND) | ||
| 535 | clnt->cl_autobind = 1; | ||
| 536 | if (args->flags & RPC_CLNT_CREATE_DISCRTRY) | ||
| 537 | clnt->cl_discrtry = 1; | ||
| 538 | if (!(args->flags & RPC_CLNT_CREATE_QUIET)) | ||
| 539 | clnt->cl_chatty = 1; | ||
| 540 | |||
| 541 | return clnt; | ||
| 542 | } | 550 | } |
| 543 | EXPORT_SYMBOL_GPL(rpc_create); | 551 | EXPORT_SYMBOL_GPL(rpc_create); |
| 544 | 552 | ||
| @@ -1363,6 +1371,7 @@ rpc_restart_call_prepare(struct rpc_task *task) | |||
| 1363 | if (RPC_ASSASSINATED(task)) | 1371 | if (RPC_ASSASSINATED(task)) |
| 1364 | return 0; | 1372 | return 0; |
| 1365 | task->tk_action = call_start; | 1373 | task->tk_action = call_start; |
| 1374 | task->tk_status = 0; | ||
| 1366 | if (task->tk_ops->rpc_call_prepare != NULL) | 1375 | if (task->tk_ops->rpc_call_prepare != NULL) |
| 1367 | task->tk_action = rpc_prepare_task; | 1376 | task->tk_action = rpc_prepare_task; |
| 1368 | return 1; | 1377 | return 1; |
| @@ -1379,6 +1388,7 @@ rpc_restart_call(struct rpc_task *task) | |||
| 1379 | if (RPC_ASSASSINATED(task)) | 1388 | if (RPC_ASSASSINATED(task)) |
| 1380 | return 0; | 1389 | return 0; |
| 1381 | task->tk_action = call_start; | 1390 | task->tk_action = call_start; |
| 1391 | task->tk_status = 0; | ||
| 1382 | return 1; | 1392 | return 1; |
| 1383 | } | 1393 | } |
| 1384 | EXPORT_SYMBOL_GPL(rpc_restart_call); | 1394 | EXPORT_SYMBOL_GPL(rpc_restart_call); |
| @@ -1728,9 +1738,7 @@ call_bind_status(struct rpc_task *task) | |||
| 1728 | case -EPROTONOSUPPORT: | 1738 | case -EPROTONOSUPPORT: |
| 1729 | dprintk("RPC: %5u remote rpcbind version unavailable, retrying\n", | 1739 | dprintk("RPC: %5u remote rpcbind version unavailable, retrying\n", |
| 1730 | task->tk_pid); | 1740 | task->tk_pid); |
| 1731 | task->tk_status = 0; | 1741 | goto retry_timeout; |
| 1732 | task->tk_action = call_bind; | ||
| 1733 | return; | ||
| 1734 | case -ECONNREFUSED: /* connection problems */ | 1742 | case -ECONNREFUSED: /* connection problems */ |
| 1735 | case -ECONNRESET: | 1743 | case -ECONNRESET: |
| 1736 | case -ECONNABORTED: | 1744 | case -ECONNABORTED: |
| @@ -1756,6 +1764,7 @@ call_bind_status(struct rpc_task *task) | |||
| 1756 | return; | 1764 | return; |
| 1757 | 1765 | ||
| 1758 | retry_timeout: | 1766 | retry_timeout: |
| 1767 | task->tk_status = 0; | ||
| 1759 | task->tk_action = call_timeout; | 1768 | task->tk_action = call_timeout; |
| 1760 | } | 1769 | } |
| 1761 | 1770 | ||
| @@ -1798,21 +1807,19 @@ call_connect_status(struct rpc_task *task) | |||
| 1798 | trace_rpc_connect_status(task, status); | 1807 | trace_rpc_connect_status(task, status); |
| 1799 | task->tk_status = 0; | 1808 | task->tk_status = 0; |
| 1800 | switch (status) { | 1809 | switch (status) { |
| 1801 | /* if soft mounted, test if we've timed out */ | ||
| 1802 | case -ETIMEDOUT: | ||
| 1803 | task->tk_action = call_timeout; | ||
| 1804 | return; | ||
| 1805 | case -ECONNREFUSED: | 1810 | case -ECONNREFUSED: |
| 1806 | case -ECONNRESET: | 1811 | case -ECONNRESET: |
| 1807 | case -ECONNABORTED: | 1812 | case -ECONNABORTED: |
| 1808 | case -ENETUNREACH: | 1813 | case -ENETUNREACH: |
| 1809 | case -EHOSTUNREACH: | 1814 | case -EHOSTUNREACH: |
| 1810 | /* retry with existing socket, after a delay */ | ||
| 1811 | rpc_delay(task, 3*HZ); | ||
| 1812 | if (RPC_IS_SOFTCONN(task)) | 1815 | if (RPC_IS_SOFTCONN(task)) |
| 1813 | break; | 1816 | break; |
| 1817 | /* retry with existing socket, after a delay */ | ||
| 1818 | rpc_delay(task, 3*HZ); | ||
| 1814 | case -EAGAIN: | 1819 | case -EAGAIN: |
| 1815 | task->tk_action = call_bind; | 1820 | /* Check for timeouts before looping back to call_bind */ |
| 1821 | case -ETIMEDOUT: | ||
| 1822 | task->tk_action = call_timeout; | ||
| 1816 | return; | 1823 | return; |
| 1817 | case 0: | 1824 | case 0: |
| 1818 | clnt->cl_stats->netreconn++; | 1825 | clnt->cl_stats->netreconn++; |
| @@ -2007,6 +2014,10 @@ call_status(struct rpc_task *task) | |||
| 2007 | case -EHOSTDOWN: | 2014 | case -EHOSTDOWN: |
| 2008 | case -EHOSTUNREACH: | 2015 | case -EHOSTUNREACH: |
| 2009 | case -ENETUNREACH: | 2016 | case -ENETUNREACH: |
| 2017 | if (RPC_IS_SOFTCONN(task)) { | ||
| 2018 | rpc_exit(task, status); | ||
| 2019 | break; | ||
| 2020 | } | ||
| 2010 | /* | 2021 | /* |
| 2011 | * Delay any retries for 3 seconds, then handle as if it | 2022 | * Delay any retries for 3 seconds, then handle as if it |
| 2012 | * were a timeout. | 2023 | * were a timeout. |
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c index ff3cc4bf4b24..25578afe1548 100644 --- a/net/sunrpc/sched.c +++ b/net/sunrpc/sched.c | |||
| @@ -637,7 +637,8 @@ static void __rpc_queue_timer_fn(unsigned long ptr) | |||
| 637 | 637 | ||
| 638 | static void __rpc_atrun(struct rpc_task *task) | 638 | static void __rpc_atrun(struct rpc_task *task) |
| 639 | { | 639 | { |
| 640 | task->tk_status = 0; | 640 | if (task->tk_status == -ETIMEDOUT) |
| 641 | task->tk_status = 0; | ||
| 641 | } | 642 | } |
| 642 | 643 | ||
| 643 | /* | 644 | /* |
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index b6e59f0a9475..43bcb4699d69 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
| @@ -60,7 +60,7 @@ | |||
| 60 | 60 | ||
| 61 | static struct svc_sock *svc_setup_socket(struct svc_serv *, struct socket *, | 61 | static struct svc_sock *svc_setup_socket(struct svc_serv *, struct socket *, |
| 62 | int flags); | 62 | int flags); |
| 63 | static void svc_udp_data_ready(struct sock *, int); | 63 | static void svc_udp_data_ready(struct sock *); |
| 64 | static int svc_udp_recvfrom(struct svc_rqst *); | 64 | static int svc_udp_recvfrom(struct svc_rqst *); |
| 65 | static int svc_udp_sendto(struct svc_rqst *); | 65 | static int svc_udp_sendto(struct svc_rqst *); |
| 66 | static void svc_sock_detach(struct svc_xprt *); | 66 | static void svc_sock_detach(struct svc_xprt *); |
| @@ -403,14 +403,14 @@ static void svc_sock_setbufsize(struct socket *sock, unsigned int snd, | |||
| 403 | /* | 403 | /* |
| 404 | * INET callback when data has been received on the socket. | 404 | * INET callback when data has been received on the socket. |
| 405 | */ | 405 | */ |
| 406 | static void svc_udp_data_ready(struct sock *sk, int count) | 406 | static void svc_udp_data_ready(struct sock *sk) |
| 407 | { | 407 | { |
| 408 | struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data; | 408 | struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data; |
| 409 | wait_queue_head_t *wq = sk_sleep(sk); | 409 | wait_queue_head_t *wq = sk_sleep(sk); |
| 410 | 410 | ||
| 411 | if (svsk) { | 411 | if (svsk) { |
| 412 | dprintk("svc: socket %p(inet %p), count=%d, busy=%d\n", | 412 | dprintk("svc: socket %p(inet %p), busy=%d\n", |
| 413 | svsk, sk, count, | 413 | svsk, sk, |
| 414 | test_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags)); | 414 | test_bit(XPT_BUSY, &svsk->sk_xprt.xpt_flags)); |
| 415 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); | 415 | set_bit(XPT_DATA, &svsk->sk_xprt.xpt_flags); |
| 416 | svc_xprt_enqueue(&svsk->sk_xprt); | 416 | svc_xprt_enqueue(&svsk->sk_xprt); |
| @@ -731,7 +731,7 @@ static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv) | |||
| 731 | * A data_ready event on a listening socket means there's a connection | 731 | * A data_ready event on a listening socket means there's a connection |
| 732 | * pending. Do not use state_change as a substitute for it. | 732 | * pending. Do not use state_change as a substitute for it. |
| 733 | */ | 733 | */ |
| 734 | static void svc_tcp_listen_data_ready(struct sock *sk, int count_unused) | 734 | static void svc_tcp_listen_data_ready(struct sock *sk) |
| 735 | { | 735 | { |
| 736 | struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data; | 736 | struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data; |
| 737 | wait_queue_head_t *wq; | 737 | wait_queue_head_t *wq; |
| @@ -783,7 +783,7 @@ static void svc_tcp_state_change(struct sock *sk) | |||
| 783 | wake_up_interruptible_all(wq); | 783 | wake_up_interruptible_all(wq); |
| 784 | } | 784 | } |
| 785 | 785 | ||
| 786 | static void svc_tcp_data_ready(struct sock *sk, int count) | 786 | static void svc_tcp_data_ready(struct sock *sk) |
| 787 | { | 787 | { |
| 788 | struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data; | 788 | struct svc_sock *svsk = (struct svc_sock *)sk->sk_user_data; |
| 789 | wait_queue_head_t *wq = sk_sleep(sk); | 789 | wait_queue_head_t *wq = sk_sleep(sk); |
| @@ -1397,6 +1397,22 @@ static struct svc_sock *svc_setup_socket(struct svc_serv *serv, | |||
| 1397 | return svsk; | 1397 | return svsk; |
| 1398 | } | 1398 | } |
| 1399 | 1399 | ||
| 1400 | bool svc_alien_sock(struct net *net, int fd) | ||
| 1401 | { | ||
| 1402 | int err; | ||
| 1403 | struct socket *sock = sockfd_lookup(fd, &err); | ||
| 1404 | bool ret = false; | ||
| 1405 | |||
| 1406 | if (!sock) | ||
| 1407 | goto out; | ||
| 1408 | if (sock_net(sock->sk) != net) | ||
| 1409 | ret = true; | ||
| 1410 | sockfd_put(sock); | ||
| 1411 | out: | ||
| 1412 | return ret; | ||
| 1413 | } | ||
| 1414 | EXPORT_SYMBOL_GPL(svc_alien_sock); | ||
| 1415 | |||
| 1400 | /** | 1416 | /** |
| 1401 | * svc_addsock - add a listener socket to an RPC service | 1417 | * svc_addsock - add a listener socket to an RPC service |
| 1402 | * @serv: pointer to RPC service to which to add a new listener | 1418 | * @serv: pointer to RPC service to which to add a new listener |
diff --git a/net/sunrpc/xdr.c b/net/sunrpc/xdr.c index 1504bb11e4f3..dd97ba3c4456 100644 --- a/net/sunrpc/xdr.c +++ b/net/sunrpc/xdr.c | |||
| @@ -833,8 +833,20 @@ xdr_buf_from_iov(struct kvec *iov, struct xdr_buf *buf) | |||
| 833 | } | 833 | } |
| 834 | EXPORT_SYMBOL_GPL(xdr_buf_from_iov); | 834 | EXPORT_SYMBOL_GPL(xdr_buf_from_iov); |
| 835 | 835 | ||
| 836 | /* Sets subbuf to the portion of buf of length len beginning base bytes | 836 | /** |
| 837 | * from the start of buf. Returns -1 if base of length are out of bounds. */ | 837 | * xdr_buf_subsegment - set subbuf to a portion of buf |
| 838 | * @buf: an xdr buffer | ||
| 839 | * @subbuf: the result buffer | ||
| 840 | * @base: beginning of range in bytes | ||
| 841 | * @len: length of range in bytes | ||
| 842 | * | ||
| 843 | * sets @subbuf to an xdr buffer representing the portion of @buf of | ||
| 844 | * length @len starting at offset @base. | ||
| 845 | * | ||
| 846 | * @buf and @subbuf may be pointers to the same struct xdr_buf. | ||
| 847 | * | ||
| 848 | * Returns -1 if base of length are out of bounds. | ||
| 849 | */ | ||
| 838 | int | 850 | int |
| 839 | xdr_buf_subsegment(struct xdr_buf *buf, struct xdr_buf *subbuf, | 851 | xdr_buf_subsegment(struct xdr_buf *buf, struct xdr_buf *subbuf, |
| 840 | unsigned int base, unsigned int len) | 852 | unsigned int base, unsigned int len) |
| @@ -847,9 +859,8 @@ xdr_buf_subsegment(struct xdr_buf *buf, struct xdr_buf *subbuf, | |||
| 847 | len -= subbuf->head[0].iov_len; | 859 | len -= subbuf->head[0].iov_len; |
| 848 | base = 0; | 860 | base = 0; |
| 849 | } else { | 861 | } else { |
| 850 | subbuf->head[0].iov_base = NULL; | ||
| 851 | subbuf->head[0].iov_len = 0; | ||
| 852 | base -= buf->head[0].iov_len; | 862 | base -= buf->head[0].iov_len; |
| 863 | subbuf->head[0].iov_len = 0; | ||
| 853 | } | 864 | } |
| 854 | 865 | ||
| 855 | if (base < buf->page_len) { | 866 | if (base < buf->page_len) { |
| @@ -871,9 +882,8 @@ xdr_buf_subsegment(struct xdr_buf *buf, struct xdr_buf *subbuf, | |||
| 871 | len -= subbuf->tail[0].iov_len; | 882 | len -= subbuf->tail[0].iov_len; |
| 872 | base = 0; | 883 | base = 0; |
| 873 | } else { | 884 | } else { |
| 874 | subbuf->tail[0].iov_base = NULL; | ||
| 875 | subbuf->tail[0].iov_len = 0; | ||
| 876 | base -= buf->tail[0].iov_len; | 885 | base -= buf->tail[0].iov_len; |
| 886 | subbuf->tail[0].iov_len = 0; | ||
| 877 | } | 887 | } |
| 878 | 888 | ||
| 879 | if (base || len) | 889 | if (base || len) |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index 7d4df99f761f..d173f79947c6 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
| @@ -1383,15 +1383,3 @@ void xprt_put(struct rpc_xprt *xprt) | |||
| 1383 | if (atomic_dec_and_test(&xprt->count)) | 1383 | if (atomic_dec_and_test(&xprt->count)) |
| 1384 | xprt_destroy(xprt); | 1384 | xprt_destroy(xprt); |
| 1385 | } | 1385 | } |
| 1386 | |||
| 1387 | /** | ||
| 1388 | * xprt_get - return a reference to an RPC transport. | ||
| 1389 | * @xprt: pointer to the transport | ||
| 1390 | * | ||
| 1391 | */ | ||
| 1392 | struct rpc_xprt *xprt_get(struct rpc_xprt *xprt) | ||
| 1393 | { | ||
| 1394 | if (atomic_inc_not_zero(&xprt->count)) | ||
| 1395 | return xprt; | ||
| 1396 | return NULL; | ||
| 1397 | } | ||
diff --git a/net/sunrpc/xprtrdma/Makefile b/net/sunrpc/xprtrdma/Makefile index 5a8f268bdd30..da5136fd5694 100644 --- a/net/sunrpc/xprtrdma/Makefile +++ b/net/sunrpc/xprtrdma/Makefile | |||
| @@ -1,8 +1,8 @@ | |||
| 1 | obj-$(CONFIG_SUNRPC_XPRT_RDMA) += xprtrdma.o | 1 | obj-$(CONFIG_SUNRPC_XPRT_RDMA_CLIENT) += xprtrdma.o |
| 2 | 2 | ||
| 3 | xprtrdma-y := transport.o rpc_rdma.o verbs.o | 3 | xprtrdma-y := transport.o rpc_rdma.o verbs.o |
| 4 | 4 | ||
| 5 | obj-$(CONFIG_SUNRPC_XPRT_RDMA) += svcrdma.o | 5 | obj-$(CONFIG_SUNRPC_XPRT_RDMA_SERVER) += svcrdma.o |
| 6 | 6 | ||
| 7 | svcrdma-y := svc_rdma.o svc_rdma_transport.o \ | 7 | svcrdma-y := svc_rdma.o svc_rdma_transport.o \ |
| 8 | svc_rdma_marshal.o svc_rdma_sendto.o svc_rdma_recvfrom.o | 8 | svc_rdma_marshal.o svc_rdma_sendto.o svc_rdma_recvfrom.o |
diff --git a/net/sunrpc/xprtrdma/rpc_rdma.c b/net/sunrpc/xprtrdma/rpc_rdma.c index e03725bfe2b8..96ead526b125 100644 --- a/net/sunrpc/xprtrdma/rpc_rdma.c +++ b/net/sunrpc/xprtrdma/rpc_rdma.c | |||
| @@ -649,9 +649,7 @@ rpcrdma_inline_fixup(struct rpc_rqst *rqst, char *srcp, int copy_len, int pad) | |||
| 649 | break; | 649 | break; |
| 650 | page_base = 0; | 650 | page_base = 0; |
| 651 | } | 651 | } |
| 652 | rqst->rq_rcv_buf.page_len = olen - copy_len; | 652 | } |
| 653 | } else | ||
| 654 | rqst->rq_rcv_buf.page_len = 0; | ||
| 655 | 653 | ||
| 656 | if (copy_len && rqst->rq_rcv_buf.tail[0].iov_len) { | 654 | if (copy_len && rqst->rq_rcv_buf.tail[0].iov_len) { |
| 657 | curlen = copy_len; | 655 | curlen = copy_len; |
diff --git a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c index 0ce75524ed21..8d904e4eef15 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c +++ b/net/sunrpc/xprtrdma/svc_rdma_recvfrom.c | |||
| @@ -90,6 +90,7 @@ static void rdma_build_arg_xdr(struct svc_rqst *rqstp, | |||
| 90 | sge_no++; | 90 | sge_no++; |
| 91 | } | 91 | } |
| 92 | rqstp->rq_respages = &rqstp->rq_pages[sge_no]; | 92 | rqstp->rq_respages = &rqstp->rq_pages[sge_no]; |
| 93 | rqstp->rq_next_page = rqstp->rq_respages + 1; | ||
| 93 | 94 | ||
| 94 | /* We should never run out of SGE because the limit is defined to | 95 | /* We should never run out of SGE because the limit is defined to |
| 95 | * support the max allowed RPC data length | 96 | * support the max allowed RPC data length |
| @@ -169,6 +170,7 @@ static int map_read_chunks(struct svcxprt_rdma *xprt, | |||
| 169 | */ | 170 | */ |
| 170 | head->arg.pages[page_no] = rqstp->rq_arg.pages[page_no]; | 171 | head->arg.pages[page_no] = rqstp->rq_arg.pages[page_no]; |
| 171 | rqstp->rq_respages = &rqstp->rq_arg.pages[page_no+1]; | 172 | rqstp->rq_respages = &rqstp->rq_arg.pages[page_no+1]; |
| 173 | rqstp->rq_next_page = rqstp->rq_respages + 1; | ||
| 172 | 174 | ||
| 173 | byte_count -= sge_bytes; | 175 | byte_count -= sge_bytes; |
| 174 | ch_bytes -= sge_bytes; | 176 | ch_bytes -= sge_bytes; |
| @@ -276,6 +278,7 @@ static int fast_reg_read_chunks(struct svcxprt_rdma *xprt, | |||
| 276 | 278 | ||
| 277 | /* rq_respages points one past arg pages */ | 279 | /* rq_respages points one past arg pages */ |
| 278 | rqstp->rq_respages = &rqstp->rq_arg.pages[page_no]; | 280 | rqstp->rq_respages = &rqstp->rq_arg.pages[page_no]; |
| 281 | rqstp->rq_next_page = rqstp->rq_respages + 1; | ||
| 279 | 282 | ||
| 280 | /* Create the reply and chunk maps */ | 283 | /* Create the reply and chunk maps */ |
| 281 | offset = 0; | 284 | offset = 0; |
| @@ -520,13 +523,6 @@ next_sge: | |||
| 520 | for (ch_no = 0; &rqstp->rq_pages[ch_no] < rqstp->rq_respages; ch_no++) | 523 | for (ch_no = 0; &rqstp->rq_pages[ch_no] < rqstp->rq_respages; ch_no++) |
| 521 | rqstp->rq_pages[ch_no] = NULL; | 524 | rqstp->rq_pages[ch_no] = NULL; |
| 522 | 525 | ||
| 523 | /* | ||
| 524 | * Detach res pages. If svc_release sees any it will attempt to | ||
| 525 | * put them. | ||
| 526 | */ | ||
| 527 | while (rqstp->rq_next_page != rqstp->rq_respages) | ||
| 528 | *(--rqstp->rq_next_page) = NULL; | ||
| 529 | |||
| 530 | return err; | 526 | return err; |
| 531 | } | 527 | } |
| 532 | 528 | ||
| @@ -550,7 +546,7 @@ static int rdma_read_complete(struct svc_rqst *rqstp, | |||
| 550 | 546 | ||
| 551 | /* rq_respages starts after the last arg page */ | 547 | /* rq_respages starts after the last arg page */ |
| 552 | rqstp->rq_respages = &rqstp->rq_arg.pages[page_no]; | 548 | rqstp->rq_respages = &rqstp->rq_arg.pages[page_no]; |
| 553 | rqstp->rq_next_page = &rqstp->rq_arg.pages[page_no]; | 549 | rqstp->rq_next_page = rqstp->rq_respages + 1; |
| 554 | 550 | ||
| 555 | /* Rebuild rq_arg head and tail. */ | 551 | /* Rebuild rq_arg head and tail. */ |
| 556 | rqstp->rq_arg.head[0] = head->arg.head[0]; | 552 | rqstp->rq_arg.head[0] = head->arg.head[0]; |
diff --git a/net/sunrpc/xprtrdma/svc_rdma_sendto.c b/net/sunrpc/xprtrdma/svc_rdma_sendto.c index c1d124dc772b..7e024a51617e 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_sendto.c +++ b/net/sunrpc/xprtrdma/svc_rdma_sendto.c | |||
| @@ -265,6 +265,7 @@ static dma_addr_t dma_map_xdr(struct svcxprt_rdma *xprt, | |||
| 265 | xdr_off -= xdr->head[0].iov_len; | 265 | xdr_off -= xdr->head[0].iov_len; |
| 266 | if (xdr_off < xdr->page_len) { | 266 | if (xdr_off < xdr->page_len) { |
| 267 | /* This offset is in the page list */ | 267 | /* This offset is in the page list */ |
| 268 | xdr_off += xdr->page_base; | ||
| 268 | page = xdr->pages[xdr_off >> PAGE_SHIFT]; | 269 | page = xdr->pages[xdr_off >> PAGE_SHIFT]; |
| 269 | xdr_off &= ~PAGE_MASK; | 270 | xdr_off &= ~PAGE_MASK; |
| 270 | } else { | 271 | } else { |
| @@ -625,6 +626,7 @@ static int send_reply(struct svcxprt_rdma *rdma, | |||
| 625 | if (page_no+1 >= sge_no) | 626 | if (page_no+1 >= sge_no) |
| 626 | ctxt->sge[page_no+1].length = 0; | 627 | ctxt->sge[page_no+1].length = 0; |
| 627 | } | 628 | } |
| 629 | rqstp->rq_next_page = rqstp->rq_respages + 1; | ||
| 628 | BUG_ON(sge_no > rdma->sc_max_sge); | 630 | BUG_ON(sge_no > rdma->sc_max_sge); |
| 629 | memset(&send_wr, 0, sizeof send_wr); | 631 | memset(&send_wr, 0, sizeof send_wr); |
| 630 | ctxt->wr_op = IB_WR_SEND; | 632 | ctxt->wr_op = IB_WR_SEND; |
diff --git a/net/sunrpc/xprtrdma/svc_rdma_transport.c b/net/sunrpc/xprtrdma/svc_rdma_transport.c index 62e4f9bcc387..25688fa2207f 100644 --- a/net/sunrpc/xprtrdma/svc_rdma_transport.c +++ b/net/sunrpc/xprtrdma/svc_rdma_transport.c | |||
| @@ -477,8 +477,7 @@ struct page *svc_rdma_get_page(void) | |||
| 477 | 477 | ||
| 478 | while ((page = alloc_page(GFP_KERNEL)) == NULL) { | 478 | while ((page = alloc_page(GFP_KERNEL)) == NULL) { |
| 479 | /* If we can't get memory, wait a bit and try again */ | 479 | /* If we can't get memory, wait a bit and try again */ |
| 480 | printk(KERN_INFO "svcrdma: out of memory...retrying in 1000 " | 480 | printk(KERN_INFO "svcrdma: out of memory...retrying in 1s\n"); |
| 481 | "jiffies.\n"); | ||
| 482 | schedule_timeout_uninterruptible(msecs_to_jiffies(1000)); | 481 | schedule_timeout_uninterruptible(msecs_to_jiffies(1000)); |
| 483 | } | 482 | } |
| 484 | return page; | 483 | return page; |
diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c index 285dc0884115..1eb9c468d0c9 100644 --- a/net/sunrpc/xprtrdma/transport.c +++ b/net/sunrpc/xprtrdma/transport.c | |||
| @@ -733,7 +733,7 @@ static void __exit xprt_rdma_cleanup(void) | |||
| 733 | { | 733 | { |
| 734 | int rc; | 734 | int rc; |
| 735 | 735 | ||
| 736 | dprintk(KERN_INFO "RPCRDMA Module Removed, deregister RPC RDMA transport\n"); | 736 | dprintk("RPCRDMA Module Removed, deregister RPC RDMA transport\n"); |
| 737 | #ifdef RPC_DEBUG | 737 | #ifdef RPC_DEBUG |
| 738 | if (sunrpc_table_header) { | 738 | if (sunrpc_table_header) { |
| 739 | unregister_sysctl_table(sunrpc_table_header); | 739 | unregister_sysctl_table(sunrpc_table_header); |
| @@ -755,14 +755,14 @@ static int __init xprt_rdma_init(void) | |||
| 755 | if (rc) | 755 | if (rc) |
| 756 | return rc; | 756 | return rc; |
| 757 | 757 | ||
| 758 | dprintk(KERN_INFO "RPCRDMA Module Init, register RPC RDMA transport\n"); | 758 | dprintk("RPCRDMA Module Init, register RPC RDMA transport\n"); |
| 759 | 759 | ||
| 760 | dprintk(KERN_INFO "Defaults:\n"); | 760 | dprintk("Defaults:\n"); |
| 761 | dprintk(KERN_INFO "\tSlots %d\n" | 761 | dprintk("\tSlots %d\n" |
| 762 | "\tMaxInlineRead %d\n\tMaxInlineWrite %d\n", | 762 | "\tMaxInlineRead %d\n\tMaxInlineWrite %d\n", |
| 763 | xprt_rdma_slot_table_entries, | 763 | xprt_rdma_slot_table_entries, |
| 764 | xprt_rdma_max_inline_read, xprt_rdma_max_inline_write); | 764 | xprt_rdma_max_inline_read, xprt_rdma_max_inline_write); |
| 765 | dprintk(KERN_INFO "\tPadding %d\n\tMemreg %d\n", | 765 | dprintk("\tPadding %d\n\tMemreg %d\n", |
| 766 | xprt_rdma_inline_write_padding, xprt_rdma_memreg_strategy); | 766 | xprt_rdma_inline_write_padding, xprt_rdma_memreg_strategy); |
| 767 | 767 | ||
| 768 | #ifdef RPC_DEBUG | 768 | #ifdef RPC_DEBUG |
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 0addefca8e77..25a3dcf15cae 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
| @@ -254,7 +254,7 @@ struct sock_xprt { | |||
| 254 | /* | 254 | /* |
| 255 | * Saved socket callback addresses | 255 | * Saved socket callback addresses |
| 256 | */ | 256 | */ |
| 257 | void (*old_data_ready)(struct sock *, int); | 257 | void (*old_data_ready)(struct sock *); |
| 258 | void (*old_state_change)(struct sock *); | 258 | void (*old_state_change)(struct sock *); |
| 259 | void (*old_write_space)(struct sock *); | 259 | void (*old_write_space)(struct sock *); |
| 260 | void (*old_error_report)(struct sock *); | 260 | void (*old_error_report)(struct sock *); |
| @@ -909,6 +909,12 @@ static void xs_tcp_close(struct rpc_xprt *xprt) | |||
| 909 | xs_tcp_shutdown(xprt); | 909 | xs_tcp_shutdown(xprt); |
| 910 | } | 910 | } |
| 911 | 911 | ||
| 912 | static void xs_xprt_free(struct rpc_xprt *xprt) | ||
| 913 | { | ||
| 914 | xs_free_peer_addresses(xprt); | ||
| 915 | xprt_free(xprt); | ||
| 916 | } | ||
| 917 | |||
| 912 | /** | 918 | /** |
| 913 | * xs_destroy - prepare to shutdown a transport | 919 | * xs_destroy - prepare to shutdown a transport |
| 914 | * @xprt: doomed transport | 920 | * @xprt: doomed transport |
| @@ -919,8 +925,7 @@ static void xs_destroy(struct rpc_xprt *xprt) | |||
| 919 | dprintk("RPC: xs_destroy xprt %p\n", xprt); | 925 | dprintk("RPC: xs_destroy xprt %p\n", xprt); |
| 920 | 926 | ||
| 921 | xs_close(xprt); | 927 | xs_close(xprt); |
| 922 | xs_free_peer_addresses(xprt); | 928 | xs_xprt_free(xprt); |
| 923 | xprt_free(xprt); | ||
| 924 | module_put(THIS_MODULE); | 929 | module_put(THIS_MODULE); |
| 925 | } | 930 | } |
| 926 | 931 | ||
| @@ -946,7 +951,7 @@ static int xs_local_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb) | |||
| 946 | * | 951 | * |
| 947 | * Currently this assumes we can read the whole reply in a single gulp. | 952 | * Currently this assumes we can read the whole reply in a single gulp. |
| 948 | */ | 953 | */ |
| 949 | static void xs_local_data_ready(struct sock *sk, int len) | 954 | static void xs_local_data_ready(struct sock *sk) |
| 950 | { | 955 | { |
| 951 | struct rpc_task *task; | 956 | struct rpc_task *task; |
| 952 | struct rpc_xprt *xprt; | 957 | struct rpc_xprt *xprt; |
| @@ -1009,7 +1014,7 @@ static void xs_local_data_ready(struct sock *sk, int len) | |||
| 1009 | * @len: how much data to read | 1014 | * @len: how much data to read |
| 1010 | * | 1015 | * |
| 1011 | */ | 1016 | */ |
| 1012 | static void xs_udp_data_ready(struct sock *sk, int len) | 1017 | static void xs_udp_data_ready(struct sock *sk) |
| 1013 | { | 1018 | { |
| 1014 | struct rpc_task *task; | 1019 | struct rpc_task *task; |
| 1015 | struct rpc_xprt *xprt; | 1020 | struct rpc_xprt *xprt; |
| @@ -1306,41 +1311,29 @@ static inline int xs_tcp_read_reply(struct rpc_xprt *xprt, | |||
| 1306 | * If we're unable to obtain the rpc_rqst we schedule the closing of the | 1311 | * If we're unable to obtain the rpc_rqst we schedule the closing of the |
| 1307 | * connection and return -1. | 1312 | * connection and return -1. |
| 1308 | */ | 1313 | */ |
| 1309 | static inline int xs_tcp_read_callback(struct rpc_xprt *xprt, | 1314 | static int xs_tcp_read_callback(struct rpc_xprt *xprt, |
| 1310 | struct xdr_skb_reader *desc) | 1315 | struct xdr_skb_reader *desc) |
| 1311 | { | 1316 | { |
| 1312 | struct sock_xprt *transport = | 1317 | struct sock_xprt *transport = |
| 1313 | container_of(xprt, struct sock_xprt, xprt); | 1318 | container_of(xprt, struct sock_xprt, xprt); |
| 1314 | struct rpc_rqst *req; | 1319 | struct rpc_rqst *req; |
| 1315 | 1320 | ||
| 1316 | req = xprt_alloc_bc_request(xprt); | 1321 | /* Look up and lock the request corresponding to the given XID */ |
| 1322 | spin_lock(&xprt->transport_lock); | ||
| 1323 | req = xprt_lookup_bc_request(xprt, transport->tcp_xid); | ||
| 1317 | if (req == NULL) { | 1324 | if (req == NULL) { |
| 1325 | spin_unlock(&xprt->transport_lock); | ||
| 1318 | printk(KERN_WARNING "Callback slot table overflowed\n"); | 1326 | printk(KERN_WARNING "Callback slot table overflowed\n"); |
| 1319 | xprt_force_disconnect(xprt); | 1327 | xprt_force_disconnect(xprt); |
| 1320 | return -1; | 1328 | return -1; |
| 1321 | } | 1329 | } |
| 1322 | 1330 | ||
| 1323 | req->rq_xid = transport->tcp_xid; | ||
| 1324 | dprintk("RPC: read callback XID %08x\n", ntohl(req->rq_xid)); | 1331 | dprintk("RPC: read callback XID %08x\n", ntohl(req->rq_xid)); |
| 1325 | xs_tcp_read_common(xprt, desc, req); | 1332 | xs_tcp_read_common(xprt, desc, req); |
| 1326 | 1333 | ||
| 1327 | if (!(transport->tcp_flags & TCP_RCV_COPY_DATA)) { | 1334 | if (!(transport->tcp_flags & TCP_RCV_COPY_DATA)) |
| 1328 | struct svc_serv *bc_serv = xprt->bc_serv; | 1335 | xprt_complete_bc_request(req, transport->tcp_copied); |
| 1329 | 1336 | spin_unlock(&xprt->transport_lock); | |
| 1330 | /* | ||
| 1331 | * Add callback request to callback list. The callback | ||
| 1332 | * service sleeps on the sv_cb_waitq waiting for new | ||
| 1333 | * requests. Wake it up after adding enqueing the | ||
| 1334 | * request. | ||
| 1335 | */ | ||
| 1336 | dprintk("RPC: add callback request to list\n"); | ||
| 1337 | spin_lock(&bc_serv->sv_cb_lock); | ||
| 1338 | list_add(&req->rq_bc_list, &bc_serv->sv_cb_list); | ||
| 1339 | spin_unlock(&bc_serv->sv_cb_lock); | ||
| 1340 | wake_up(&bc_serv->sv_cb_waitq); | ||
| 1341 | } | ||
| 1342 | |||
| 1343 | req->rq_private_buf.len = transport->tcp_copied; | ||
| 1344 | 1337 | ||
| 1345 | return 0; | 1338 | return 0; |
| 1346 | } | 1339 | } |
| @@ -1444,7 +1437,7 @@ static int xs_tcp_data_recv(read_descriptor_t *rd_desc, struct sk_buff *skb, uns | |||
| 1444 | * @bytes: how much data to read | 1437 | * @bytes: how much data to read |
| 1445 | * | 1438 | * |
| 1446 | */ | 1439 | */ |
| 1447 | static void xs_tcp_data_ready(struct sock *sk, int bytes) | 1440 | static void xs_tcp_data_ready(struct sock *sk) |
| 1448 | { | 1441 | { |
| 1449 | struct rpc_xprt *xprt; | 1442 | struct rpc_xprt *xprt; |
| 1450 | read_descriptor_t rd_desc; | 1443 | read_descriptor_t rd_desc; |
| @@ -2544,6 +2537,10 @@ static void bc_close(struct rpc_xprt *xprt) | |||
| 2544 | 2537 | ||
| 2545 | static void bc_destroy(struct rpc_xprt *xprt) | 2538 | static void bc_destroy(struct rpc_xprt *xprt) |
| 2546 | { | 2539 | { |
| 2540 | dprintk("RPC: bc_destroy xprt %p\n", xprt); | ||
| 2541 | |||
| 2542 | xs_xprt_free(xprt); | ||
| 2543 | module_put(THIS_MODULE); | ||
| 2547 | } | 2544 | } |
| 2548 | 2545 | ||
| 2549 | static struct rpc_xprt_ops xs_local_ops = { | 2546 | static struct rpc_xprt_ops xs_local_ops = { |
| @@ -2744,7 +2741,7 @@ static struct rpc_xprt *xs_setup_local(struct xprt_create *args) | |||
| 2744 | return xprt; | 2741 | return xprt; |
| 2745 | ret = ERR_PTR(-EINVAL); | 2742 | ret = ERR_PTR(-EINVAL); |
| 2746 | out_err: | 2743 | out_err: |
| 2747 | xprt_free(xprt); | 2744 | xs_xprt_free(xprt); |
| 2748 | return ret; | 2745 | return ret; |
| 2749 | } | 2746 | } |
| 2750 | 2747 | ||
| @@ -2822,7 +2819,7 @@ static struct rpc_xprt *xs_setup_udp(struct xprt_create *args) | |||
| 2822 | return xprt; | 2819 | return xprt; |
| 2823 | ret = ERR_PTR(-EINVAL); | 2820 | ret = ERR_PTR(-EINVAL); |
| 2824 | out_err: | 2821 | out_err: |
| 2825 | xprt_free(xprt); | 2822 | xs_xprt_free(xprt); |
| 2826 | return ret; | 2823 | return ret; |
| 2827 | } | 2824 | } |
| 2828 | 2825 | ||
| @@ -2897,12 +2894,11 @@ static struct rpc_xprt *xs_setup_tcp(struct xprt_create *args) | |||
| 2897 | xprt->address_strings[RPC_DISPLAY_ADDR], | 2894 | xprt->address_strings[RPC_DISPLAY_ADDR], |
| 2898 | xprt->address_strings[RPC_DISPLAY_PROTO]); | 2895 | xprt->address_strings[RPC_DISPLAY_PROTO]); |
| 2899 | 2896 | ||
| 2900 | |||
| 2901 | if (try_module_get(THIS_MODULE)) | 2897 | if (try_module_get(THIS_MODULE)) |
| 2902 | return xprt; | 2898 | return xprt; |
| 2903 | ret = ERR_PTR(-EINVAL); | 2899 | ret = ERR_PTR(-EINVAL); |
| 2904 | out_err: | 2900 | out_err: |
| 2905 | xprt_free(xprt); | 2901 | xs_xprt_free(xprt); |
| 2906 | return ret; | 2902 | return ret; |
| 2907 | } | 2903 | } |
| 2908 | 2904 | ||
| @@ -2919,15 +2915,6 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args) | |||
| 2919 | struct svc_sock *bc_sock; | 2915 | struct svc_sock *bc_sock; |
| 2920 | struct rpc_xprt *ret; | 2916 | struct rpc_xprt *ret; |
| 2921 | 2917 | ||
| 2922 | if (args->bc_xprt->xpt_bc_xprt) { | ||
| 2923 | /* | ||
| 2924 | * This server connection already has a backchannel | ||
| 2925 | * transport; we can't create a new one, as we wouldn't | ||
| 2926 | * be able to match replies based on xid any more. So, | ||
| 2927 | * reuse the already-existing one: | ||
| 2928 | */ | ||
| 2929 | return args->bc_xprt->xpt_bc_xprt; | ||
| 2930 | } | ||
| 2931 | xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries, | 2918 | xprt = xs_setup_xprt(args, xprt_tcp_slot_table_entries, |
| 2932 | xprt_tcp_slot_table_entries); | 2919 | xprt_tcp_slot_table_entries); |
| 2933 | if (IS_ERR(xprt)) | 2920 | if (IS_ERR(xprt)) |
| @@ -2985,13 +2972,14 @@ static struct rpc_xprt *xs_setup_bc_tcp(struct xprt_create *args) | |||
| 2985 | */ | 2972 | */ |
| 2986 | xprt_set_connected(xprt); | 2973 | xprt_set_connected(xprt); |
| 2987 | 2974 | ||
| 2988 | |||
| 2989 | if (try_module_get(THIS_MODULE)) | 2975 | if (try_module_get(THIS_MODULE)) |
| 2990 | return xprt; | 2976 | return xprt; |
| 2977 | |||
| 2978 | args->bc_xprt->xpt_bc_xprt = NULL; | ||
| 2991 | xprt_put(xprt); | 2979 | xprt_put(xprt); |
| 2992 | ret = ERR_PTR(-EINVAL); | 2980 | ret = ERR_PTR(-EINVAL); |
| 2993 | out_err: | 2981 | out_err: |
| 2994 | xprt_free(xprt); | 2982 | xs_xprt_free(xprt); |
| 2995 | return ret; | 2983 | return ret; |
| 2996 | } | 2984 | } |
| 2997 | 2985 | ||
diff --git a/net/tipc/addr.h b/net/tipc/addr.h index 60b00ab93d74..a74acf9ee804 100644 --- a/net/tipc/addr.h +++ b/net/tipc/addr.h | |||
| @@ -37,6 +37,8 @@ | |||
| 37 | #ifndef _TIPC_ADDR_H | 37 | #ifndef _TIPC_ADDR_H |
| 38 | #define _TIPC_ADDR_H | 38 | #define _TIPC_ADDR_H |
| 39 | 39 | ||
| 40 | #include "core.h" | ||
| 41 | |||
| 40 | #define TIPC_ZONE_MASK 0xff000000u | 42 | #define TIPC_ZONE_MASK 0xff000000u |
| 41 | #define TIPC_CLUSTER_MASK 0xfffff000u | 43 | #define TIPC_CLUSTER_MASK 0xfffff000u |
| 42 | 44 | ||
diff --git a/net/tipc/bcast.c b/net/tipc/bcast.c index bf860d9e75af..95ab5ef92920 100644 --- a/net/tipc/bcast.c +++ b/net/tipc/bcast.c | |||
| @@ -41,9 +41,9 @@ | |||
| 41 | #include "bcast.h" | 41 | #include "bcast.h" |
| 42 | #include "name_distr.h" | 42 | #include "name_distr.h" |
| 43 | 43 | ||
| 44 | #define MAX_PKT_DEFAULT_MCAST 1500 /* bcast link max packet size (fixed) */ | 44 | #define MAX_PKT_DEFAULT_MCAST 1500 /* bcast link max packet size (fixed) */ |
| 45 | 45 | #define BCLINK_WIN_DEFAULT 20 /* bcast link window size (default) */ | |
| 46 | #define BCLINK_WIN_DEFAULT 20 /* bcast link window size (default) */ | 46 | #define BCBEARER MAX_BEARERS |
| 47 | 47 | ||
| 48 | /** | 48 | /** |
| 49 | * struct tipc_bcbearer_pair - a pair of bearers used by broadcast link | 49 | * struct tipc_bcbearer_pair - a pair of bearers used by broadcast link |
| @@ -356,9 +356,9 @@ static void bclink_peek_nack(struct tipc_msg *msg) | |||
| 356 | } | 356 | } |
| 357 | 357 | ||
| 358 | /* | 358 | /* |
| 359 | * tipc_bclink_send_msg - broadcast a packet to all nodes in cluster | 359 | * tipc_bclink_xmit - broadcast a packet to all nodes in cluster |
| 360 | */ | 360 | */ |
| 361 | int tipc_bclink_send_msg(struct sk_buff *buf) | 361 | int tipc_bclink_xmit(struct sk_buff *buf) |
| 362 | { | 362 | { |
| 363 | int res; | 363 | int res; |
| 364 | 364 | ||
| @@ -370,7 +370,7 @@ int tipc_bclink_send_msg(struct sk_buff *buf) | |||
| 370 | goto exit; | 370 | goto exit; |
| 371 | } | 371 | } |
| 372 | 372 | ||
| 373 | res = tipc_link_send_buf(bcl, buf); | 373 | res = __tipc_link_xmit(bcl, buf); |
| 374 | if (likely(res >= 0)) { | 374 | if (likely(res >= 0)) { |
| 375 | bclink_set_last_sent(); | 375 | bclink_set_last_sent(); |
| 376 | bcl->stats.queue_sz_counts++; | 376 | bcl->stats.queue_sz_counts++; |
| @@ -399,19 +399,18 @@ static void bclink_accept_pkt(struct tipc_node *node, u32 seqno) | |||
| 399 | */ | 399 | */ |
| 400 | 400 | ||
| 401 | if (((seqno - tipc_own_addr) % TIPC_MIN_LINK_WIN) == 0) { | 401 | if (((seqno - tipc_own_addr) % TIPC_MIN_LINK_WIN) == 0) { |
| 402 | tipc_link_send_proto_msg( | 402 | tipc_link_proto_xmit(node->active_links[node->addr & 1], |
| 403 | node->active_links[node->addr & 1], | 403 | STATE_MSG, 0, 0, 0, 0, 0); |
| 404 | STATE_MSG, 0, 0, 0, 0, 0); | ||
| 405 | bcl->stats.sent_acks++; | 404 | bcl->stats.sent_acks++; |
| 406 | } | 405 | } |
| 407 | } | 406 | } |
| 408 | 407 | ||
| 409 | /** | 408 | /** |
| 410 | * tipc_bclink_recv_pkt - receive a broadcast packet, and deliver upwards | 409 | * tipc_bclink_rcv - receive a broadcast packet, and deliver upwards |
| 411 | * | 410 | * |
| 412 | * tipc_net_lock is read_locked, no other locks set | 411 | * tipc_net_lock is read_locked, no other locks set |
| 413 | */ | 412 | */ |
| 414 | void tipc_bclink_recv_pkt(struct sk_buff *buf) | 413 | void tipc_bclink_rcv(struct sk_buff *buf) |
| 415 | { | 414 | { |
| 416 | struct tipc_msg *msg = buf_msg(buf); | 415 | struct tipc_msg *msg = buf_msg(buf); |
| 417 | struct tipc_node *node; | 416 | struct tipc_node *node; |
| @@ -468,7 +467,7 @@ receive: | |||
| 468 | spin_unlock_bh(&bc_lock); | 467 | spin_unlock_bh(&bc_lock); |
| 469 | tipc_node_unlock(node); | 468 | tipc_node_unlock(node); |
| 470 | if (likely(msg_mcast(msg))) | 469 | if (likely(msg_mcast(msg))) |
| 471 | tipc_port_recv_mcast(buf, NULL); | 470 | tipc_port_mcast_rcv(buf, NULL); |
| 472 | else | 471 | else |
| 473 | kfree_skb(buf); | 472 | kfree_skb(buf); |
| 474 | } else if (msg_user(msg) == MSG_BUNDLER) { | 473 | } else if (msg_user(msg) == MSG_BUNDLER) { |
| @@ -478,12 +477,12 @@ receive: | |||
| 478 | bcl->stats.recv_bundled += msg_msgcnt(msg); | 477 | bcl->stats.recv_bundled += msg_msgcnt(msg); |
| 479 | spin_unlock_bh(&bc_lock); | 478 | spin_unlock_bh(&bc_lock); |
| 480 | tipc_node_unlock(node); | 479 | tipc_node_unlock(node); |
| 481 | tipc_link_recv_bundle(buf); | 480 | tipc_link_bundle_rcv(buf); |
| 482 | } else if (msg_user(msg) == MSG_FRAGMENTER) { | 481 | } else if (msg_user(msg) == MSG_FRAGMENTER) { |
| 483 | int ret; | 482 | int ret; |
| 484 | ret = tipc_link_recv_fragment(&node->bclink.reasm_head, | 483 | ret = tipc_link_frag_rcv(&node->bclink.reasm_head, |
| 485 | &node->bclink.reasm_tail, | 484 | &node->bclink.reasm_tail, |
| 486 | &buf); | 485 | &buf); |
| 487 | if (ret == LINK_REASM_ERROR) | 486 | if (ret == LINK_REASM_ERROR) |
| 488 | goto unlock; | 487 | goto unlock; |
| 489 | spin_lock_bh(&bc_lock); | 488 | spin_lock_bh(&bc_lock); |
| @@ -503,7 +502,7 @@ receive: | |||
| 503 | bclink_accept_pkt(node, seqno); | 502 | bclink_accept_pkt(node, seqno); |
| 504 | spin_unlock_bh(&bc_lock); | 503 | spin_unlock_bh(&bc_lock); |
| 505 | tipc_node_unlock(node); | 504 | tipc_node_unlock(node); |
| 506 | tipc_named_recv(buf); | 505 | tipc_named_rcv(buf); |
| 507 | } else { | 506 | } else { |
| 508 | spin_lock_bh(&bc_lock); | 507 | spin_lock_bh(&bc_lock); |
| 509 | bclink_accept_pkt(node, seqno); | 508 | bclink_accept_pkt(node, seqno); |
| @@ -669,9 +668,8 @@ void tipc_bcbearer_sort(void) | |||
| 669 | memset(bp_temp, 0, sizeof(bcbearer->bpairs_temp)); | 668 | memset(bp_temp, 0, sizeof(bcbearer->bpairs_temp)); |
| 670 | 669 | ||
| 671 | for (b_index = 0; b_index < MAX_BEARERS; b_index++) { | 670 | for (b_index = 0; b_index < MAX_BEARERS; b_index++) { |
| 672 | struct tipc_bearer *b = &tipc_bearers[b_index]; | 671 | struct tipc_bearer *b = bearer_list[b_index]; |
| 673 | 672 | if (!b || !b->nodes.count) | |
| 674 | if (!b->active || !b->nodes.count) | ||
| 675 | continue; | 673 | continue; |
| 676 | 674 | ||
| 677 | if (!bp_temp[b->priority].primary) | 675 | if (!bp_temp[b->priority].primary) |
| @@ -785,8 +783,8 @@ void tipc_bclink_init(void) | |||
| 785 | bcl->owner = &bclink->node; | 783 | bcl->owner = &bclink->node; |
| 786 | bcl->max_pkt = MAX_PKT_DEFAULT_MCAST; | 784 | bcl->max_pkt = MAX_PKT_DEFAULT_MCAST; |
| 787 | tipc_link_set_queue_limits(bcl, BCLINK_WIN_DEFAULT); | 785 | tipc_link_set_queue_limits(bcl, BCLINK_WIN_DEFAULT); |
| 788 | spin_lock_init(&bcbearer->bearer.lock); | ||
| 789 | bcl->b_ptr = &bcbearer->bearer; | 786 | bcl->b_ptr = &bcbearer->bearer; |
| 787 | bearer_list[BCBEARER] = &bcbearer->bearer; | ||
| 790 | bcl->state = WORKING_WORKING; | 788 | bcl->state = WORKING_WORKING; |
| 791 | strlcpy(bcl->name, tipc_bclink_name, TIPC_MAX_LINK_NAME); | 789 | strlcpy(bcl->name, tipc_bclink_name, TIPC_MAX_LINK_NAME); |
| 792 | } | 790 | } |
| @@ -797,6 +795,7 @@ void tipc_bclink_stop(void) | |||
| 797 | tipc_link_purge_queues(bcl); | 795 | tipc_link_purge_queues(bcl); |
| 798 | spin_unlock_bh(&bc_lock); | 796 | spin_unlock_bh(&bc_lock); |
| 799 | 797 | ||
| 798 | bearer_list[BCBEARER] = NULL; | ||
| 800 | memset(bclink, 0, sizeof(*bclink)); | 799 | memset(bclink, 0, sizeof(*bclink)); |
| 801 | memset(bcbearer, 0, sizeof(*bcbearer)); | 800 | memset(bcbearer, 0, sizeof(*bcbearer)); |
| 802 | } | 801 | } |
diff --git a/net/tipc/bcast.h b/net/tipc/bcast.h index 6ee587b469fd..a80ef54b818e 100644 --- a/net/tipc/bcast.h +++ b/net/tipc/bcast.h | |||
| @@ -90,8 +90,8 @@ void tipc_bclink_add_node(u32 addr); | |||
| 90 | void tipc_bclink_remove_node(u32 addr); | 90 | void tipc_bclink_remove_node(u32 addr); |
| 91 | struct tipc_node *tipc_bclink_retransmit_to(void); | 91 | struct tipc_node *tipc_bclink_retransmit_to(void); |
| 92 | void tipc_bclink_acknowledge(struct tipc_node *n_ptr, u32 acked); | 92 | void tipc_bclink_acknowledge(struct tipc_node *n_ptr, u32 acked); |
| 93 | int tipc_bclink_send_msg(struct sk_buff *buf); | 93 | int tipc_bclink_xmit(struct sk_buff *buf); |
| 94 | void tipc_bclink_recv_pkt(struct sk_buff *buf); | 94 | void tipc_bclink_rcv(struct sk_buff *buf); |
| 95 | u32 tipc_bclink_get_last_sent(void); | 95 | u32 tipc_bclink_get_last_sent(void); |
| 96 | u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr); | 96 | u32 tipc_bclink_acks_missing(struct tipc_node *n_ptr); |
| 97 | void tipc_bclink_update_link_state(struct tipc_node *n_ptr, u32 last_sent); | 97 | void tipc_bclink_update_link_state(struct tipc_node *n_ptr, u32 last_sent); |
diff --git a/net/tipc/bearer.c b/net/tipc/bearer.c index 574b86193b15..3fef7eb776dc 100644 --- a/net/tipc/bearer.c +++ b/net/tipc/bearer.c | |||
| @@ -49,9 +49,9 @@ static struct tipc_media * const media_info_array[] = { | |||
| 49 | NULL | 49 | NULL |
| 50 | }; | 50 | }; |
| 51 | 51 | ||
| 52 | struct tipc_bearer tipc_bearers[MAX_BEARERS]; | 52 | struct tipc_bearer *bearer_list[MAX_BEARERS + 1]; |
| 53 | 53 | ||
| 54 | static void bearer_disable(struct tipc_bearer *b_ptr); | 54 | static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down); |
| 55 | 55 | ||
| 56 | /** | 56 | /** |
| 57 | * tipc_media_find - locates specified media object by name | 57 | * tipc_media_find - locates specified media object by name |
| @@ -177,8 +177,9 @@ struct tipc_bearer *tipc_bearer_find(const char *name) | |||
| 177 | struct tipc_bearer *b_ptr; | 177 | struct tipc_bearer *b_ptr; |
| 178 | u32 i; | 178 | u32 i; |
| 179 | 179 | ||
| 180 | for (i = 0, b_ptr = tipc_bearers; i < MAX_BEARERS; i++, b_ptr++) { | 180 | for (i = 0; i < MAX_BEARERS; i++) { |
| 181 | if (b_ptr->active && (!strcmp(b_ptr->name, name))) | 181 | b_ptr = bearer_list[i]; |
| 182 | if (b_ptr && (!strcmp(b_ptr->name, name))) | ||
| 182 | return b_ptr; | 183 | return b_ptr; |
| 183 | } | 184 | } |
| 184 | return NULL; | 185 | return NULL; |
| @@ -200,8 +201,10 @@ struct sk_buff *tipc_bearer_get_names(void) | |||
| 200 | read_lock_bh(&tipc_net_lock); | 201 | read_lock_bh(&tipc_net_lock); |
| 201 | for (i = 0; media_info_array[i] != NULL; i++) { | 202 | for (i = 0; media_info_array[i] != NULL; i++) { |
| 202 | for (j = 0; j < MAX_BEARERS; j++) { | 203 | for (j = 0; j < MAX_BEARERS; j++) { |
| 203 | b = &tipc_bearers[j]; | 204 | b = bearer_list[j]; |
| 204 | if (b->active && (b->media == media_info_array[i])) { | 205 | if (!b) |
| 206 | continue; | ||
| 207 | if (b->media == media_info_array[i]) { | ||
| 205 | tipc_cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME, | 208 | tipc_cfg_append_tlv(buf, TIPC_TLV_BEARER_NAME, |
| 206 | b->name, | 209 | b->name, |
| 207 | strlen(b->name) + 1); | 210 | strlen(b->name) + 1); |
| @@ -284,16 +287,17 @@ restart: | |||
| 284 | bearer_id = MAX_BEARERS; | 287 | bearer_id = MAX_BEARERS; |
| 285 | with_this_prio = 1; | 288 | with_this_prio = 1; |
| 286 | for (i = MAX_BEARERS; i-- != 0; ) { | 289 | for (i = MAX_BEARERS; i-- != 0; ) { |
| 287 | if (!tipc_bearers[i].active) { | 290 | b_ptr = bearer_list[i]; |
| 291 | if (!b_ptr) { | ||
| 288 | bearer_id = i; | 292 | bearer_id = i; |
| 289 | continue; | 293 | continue; |
| 290 | } | 294 | } |
| 291 | if (!strcmp(name, tipc_bearers[i].name)) { | 295 | if (!strcmp(name, b_ptr->name)) { |
| 292 | pr_warn("Bearer <%s> rejected, already enabled\n", | 296 | pr_warn("Bearer <%s> rejected, already enabled\n", |
| 293 | name); | 297 | name); |
| 294 | goto exit; | 298 | goto exit; |
| 295 | } | 299 | } |
| 296 | if ((tipc_bearers[i].priority == priority) && | 300 | if ((b_ptr->priority == priority) && |
| 297 | (++with_this_prio > 2)) { | 301 | (++with_this_prio > 2)) { |
| 298 | if (priority-- == 0) { | 302 | if (priority-- == 0) { |
| 299 | pr_warn("Bearer <%s> rejected, duplicate priority\n", | 303 | pr_warn("Bearer <%s> rejected, duplicate priority\n", |
| @@ -311,7 +315,11 @@ restart: | |||
| 311 | goto exit; | 315 | goto exit; |
| 312 | } | 316 | } |
| 313 | 317 | ||
| 314 | b_ptr = &tipc_bearers[bearer_id]; | 318 | b_ptr = kzalloc(sizeof(*b_ptr), GFP_ATOMIC); |
| 319 | if (!b_ptr) { | ||
| 320 | res = -ENOMEM; | ||
| 321 | goto exit; | ||
| 322 | } | ||
| 315 | strcpy(b_ptr->name, name); | 323 | strcpy(b_ptr->name, name); |
| 316 | b_ptr->media = m_ptr; | 324 | b_ptr->media = m_ptr; |
| 317 | res = m_ptr->enable_media(b_ptr); | 325 | res = m_ptr->enable_media(b_ptr); |
| @@ -324,19 +332,20 @@ restart: | |||
| 324 | b_ptr->identity = bearer_id; | 332 | b_ptr->identity = bearer_id; |
| 325 | b_ptr->tolerance = m_ptr->tolerance; | 333 | b_ptr->tolerance = m_ptr->tolerance; |
| 326 | b_ptr->window = m_ptr->window; | 334 | b_ptr->window = m_ptr->window; |
| 335 | b_ptr->domain = disc_domain; | ||
| 327 | b_ptr->net_plane = bearer_id + 'A'; | 336 | b_ptr->net_plane = bearer_id + 'A'; |
| 328 | b_ptr->active = 1; | ||
| 329 | b_ptr->priority = priority; | 337 | b_ptr->priority = priority; |
| 330 | INIT_LIST_HEAD(&b_ptr->links); | ||
| 331 | spin_lock_init(&b_ptr->lock); | ||
| 332 | 338 | ||
| 333 | res = tipc_disc_create(b_ptr, &b_ptr->bcast_addr, disc_domain); | 339 | res = tipc_disc_create(b_ptr, &b_ptr->bcast_addr); |
| 334 | if (res) { | 340 | if (res) { |
| 335 | bearer_disable(b_ptr); | 341 | bearer_disable(b_ptr, false); |
| 336 | pr_warn("Bearer <%s> rejected, discovery object creation failed\n", | 342 | pr_warn("Bearer <%s> rejected, discovery object creation failed\n", |
| 337 | name); | 343 | name); |
| 338 | goto exit; | 344 | goto exit; |
| 339 | } | 345 | } |
| 346 | |||
| 347 | bearer_list[bearer_id] = b_ptr; | ||
| 348 | |||
| 340 | pr_info("Enabled bearer <%s>, discovery domain %s, priority %u\n", | 349 | pr_info("Enabled bearer <%s>, discovery domain %s, priority %u\n", |
| 341 | name, | 350 | name, |
| 342 | tipc_addr_string_fill(addr_string, disc_domain), priority); | 351 | tipc_addr_string_fill(addr_string, disc_domain), priority); |
| @@ -350,20 +359,11 @@ exit: | |||
| 350 | */ | 359 | */ |
| 351 | static int tipc_reset_bearer(struct tipc_bearer *b_ptr) | 360 | static int tipc_reset_bearer(struct tipc_bearer *b_ptr) |
| 352 | { | 361 | { |
| 353 | struct tipc_link *l_ptr; | ||
| 354 | struct tipc_link *temp_l_ptr; | ||
| 355 | |||
| 356 | read_lock_bh(&tipc_net_lock); | 362 | read_lock_bh(&tipc_net_lock); |
| 357 | pr_info("Resetting bearer <%s>\n", b_ptr->name); | 363 | pr_info("Resetting bearer <%s>\n", b_ptr->name); |
| 358 | spin_lock_bh(&b_ptr->lock); | 364 | tipc_disc_delete(b_ptr->link_req); |
| 359 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { | 365 | tipc_link_reset_list(b_ptr->identity); |
| 360 | struct tipc_node *n_ptr = l_ptr->owner; | 366 | tipc_disc_create(b_ptr, &b_ptr->bcast_addr); |
| 361 | |||
| 362 | spin_lock_bh(&n_ptr->lock); | ||
| 363 | tipc_link_reset(l_ptr); | ||
| 364 | spin_unlock_bh(&n_ptr->lock); | ||
| 365 | } | ||
| 366 | spin_unlock_bh(&b_ptr->lock); | ||
| 367 | read_unlock_bh(&tipc_net_lock); | 367 | read_unlock_bh(&tipc_net_lock); |
| 368 | return 0; | 368 | return 0; |
| 369 | } | 369 | } |
| @@ -373,26 +373,24 @@ static int tipc_reset_bearer(struct tipc_bearer *b_ptr) | |||
| 373 | * | 373 | * |
| 374 | * Note: This routine assumes caller holds tipc_net_lock. | 374 | * Note: This routine assumes caller holds tipc_net_lock. |
| 375 | */ | 375 | */ |
| 376 | static void bearer_disable(struct tipc_bearer *b_ptr) | 376 | static void bearer_disable(struct tipc_bearer *b_ptr, bool shutting_down) |
| 377 | { | 377 | { |
| 378 | struct tipc_link *l_ptr; | 378 | u32 i; |
| 379 | struct tipc_link *temp_l_ptr; | ||
| 380 | struct tipc_link_req *temp_req; | ||
| 381 | 379 | ||
| 382 | pr_info("Disabling bearer <%s>\n", b_ptr->name); | 380 | pr_info("Disabling bearer <%s>\n", b_ptr->name); |
| 383 | spin_lock_bh(&b_ptr->lock); | ||
| 384 | b_ptr->media->disable_media(b_ptr); | 381 | b_ptr->media->disable_media(b_ptr); |
| 385 | list_for_each_entry_safe(l_ptr, temp_l_ptr, &b_ptr->links, link_list) { | ||
| 386 | tipc_link_delete(l_ptr); | ||
| 387 | } | ||
| 388 | temp_req = b_ptr->link_req; | ||
| 389 | b_ptr->link_req = NULL; | ||
| 390 | spin_unlock_bh(&b_ptr->lock); | ||
| 391 | 382 | ||
| 392 | if (temp_req) | 383 | tipc_link_delete_list(b_ptr->identity, shutting_down); |
| 393 | tipc_disc_delete(temp_req); | 384 | if (b_ptr->link_req) |
| 385 | tipc_disc_delete(b_ptr->link_req); | ||
| 394 | 386 | ||
| 395 | memset(b_ptr, 0, sizeof(struct tipc_bearer)); | 387 | for (i = 0; i < MAX_BEARERS; i++) { |
| 388 | if (b_ptr == bearer_list[i]) { | ||
| 389 | bearer_list[i] = NULL; | ||
| 390 | break; | ||
| 391 | } | ||
| 392 | } | ||
| 393 | kfree(b_ptr); | ||
| 396 | } | 394 | } |
| 397 | 395 | ||
| 398 | int tipc_disable_bearer(const char *name) | 396 | int tipc_disable_bearer(const char *name) |
| @@ -406,7 +404,7 @@ int tipc_disable_bearer(const char *name) | |||
| 406 | pr_warn("Attempt to disable unknown bearer <%s>\n", name); | 404 | pr_warn("Attempt to disable unknown bearer <%s>\n", name); |
| 407 | res = -EINVAL; | 405 | res = -EINVAL; |
| 408 | } else { | 406 | } else { |
| 409 | bearer_disable(b_ptr); | 407 | bearer_disable(b_ptr, false); |
| 410 | res = 0; | 408 | res = 0; |
| 411 | } | 409 | } |
| 412 | write_unlock_bh(&tipc_net_lock); | 410 | write_unlock_bh(&tipc_net_lock); |
| @@ -585,7 +583,11 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt, | |||
| 585 | break; | 583 | break; |
| 586 | case NETDEV_DOWN: | 584 | case NETDEV_DOWN: |
| 587 | case NETDEV_CHANGEMTU: | 585 | case NETDEV_CHANGEMTU: |
| 586 | tipc_reset_bearer(b_ptr); | ||
| 587 | break; | ||
| 588 | case NETDEV_CHANGEADDR: | 588 | case NETDEV_CHANGEADDR: |
| 589 | tipc_l2_media_addr_set(b_ptr, &b_ptr->addr, | ||
| 590 | (char *)dev->dev_addr); | ||
| 589 | tipc_reset_bearer(b_ptr); | 591 | tipc_reset_bearer(b_ptr); |
| 590 | break; | 592 | break; |
| 591 | case NETDEV_UNREGISTER: | 593 | case NETDEV_UNREGISTER: |
| @@ -599,7 +601,7 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt, | |||
| 599 | } | 601 | } |
| 600 | 602 | ||
| 601 | static struct packet_type tipc_packet_type __read_mostly = { | 603 | static struct packet_type tipc_packet_type __read_mostly = { |
| 602 | .type = __constant_htons(ETH_P_TIPC), | 604 | .type = htons(ETH_P_TIPC), |
| 603 | .func = tipc_l2_rcv_msg, | 605 | .func = tipc_l2_rcv_msg, |
| 604 | }; | 606 | }; |
| 605 | 607 | ||
| @@ -627,10 +629,14 @@ void tipc_bearer_cleanup(void) | |||
| 627 | 629 | ||
| 628 | void tipc_bearer_stop(void) | 630 | void tipc_bearer_stop(void) |
| 629 | { | 631 | { |
| 632 | struct tipc_bearer *b_ptr; | ||
| 630 | u32 i; | 633 | u32 i; |
| 631 | 634 | ||
| 632 | for (i = 0; i < MAX_BEARERS; i++) { | 635 | for (i = 0; i < MAX_BEARERS; i++) { |
| 633 | if (tipc_bearers[i].active) | 636 | b_ptr = bearer_list[i]; |
| 634 | bearer_disable(&tipc_bearers[i]); | 637 | if (b_ptr) { |
| 638 | bearer_disable(b_ptr, true); | ||
| 639 | bearer_list[i] = NULL; | ||
| 640 | } | ||
| 635 | } | 641 | } |
| 636 | } | 642 | } |
diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index 4f5db9ad5bf6..ba48145e871d 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h | |||
| @@ -107,10 +107,8 @@ struct tipc_media { | |||
| 107 | 107 | ||
| 108 | /** | 108 | /** |
| 109 | * struct tipc_bearer - Generic TIPC bearer structure | 109 | * struct tipc_bearer - Generic TIPC bearer structure |
| 110 | * @dev: ptr to associated network device | 110 | * @media_ptr: pointer to additional media-specific information about bearer |
| 111 | * @usr_handle: pointer to additional media-specific information about bearer | ||
| 112 | * @mtu: max packet size bearer can support | 111 | * @mtu: max packet size bearer can support |
| 113 | * @lock: spinlock for controlling access to bearer | ||
| 114 | * @addr: media-specific address associated with bearer | 112 | * @addr: media-specific address associated with bearer |
| 115 | * @name: bearer name (format = media:interface) | 113 | * @name: bearer name (format = media:interface) |
| 116 | * @media: ptr to media structure associated with bearer | 114 | * @media: ptr to media structure associated with bearer |
| @@ -118,10 +116,9 @@ struct tipc_media { | |||
| 118 | * @priority: default link priority for bearer | 116 | * @priority: default link priority for bearer |
| 119 | * @window: default window size for bearer | 117 | * @window: default window size for bearer |
| 120 | * @tolerance: default link tolerance for bearer | 118 | * @tolerance: default link tolerance for bearer |
| 119 | * @domain: network domain to which links can be established | ||
| 121 | * @identity: array index of this bearer within TIPC bearer array | 120 | * @identity: array index of this bearer within TIPC bearer array |
| 122 | * @link_req: ptr to (optional) structure making periodic link setup requests | 121 | * @link_req: ptr to (optional) structure making periodic link setup requests |
| 123 | * @links: list of non-congested links associated with bearer | ||
| 124 | * @active: non-zero if bearer structure is represents a bearer | ||
| 125 | * @net_plane: network plane ('A' through 'H') currently associated with bearer | 122 | * @net_plane: network plane ('A' through 'H') currently associated with bearer |
| 126 | * @nodes: indicates which nodes in cluster can be reached through bearer | 123 | * @nodes: indicates which nodes in cluster can be reached through bearer |
| 127 | * | 124 | * |
| @@ -134,16 +131,14 @@ struct tipc_bearer { | |||
| 134 | u32 mtu; /* initalized by media */ | 131 | u32 mtu; /* initalized by media */ |
| 135 | struct tipc_media_addr addr; /* initalized by media */ | 132 | struct tipc_media_addr addr; /* initalized by media */ |
| 136 | char name[TIPC_MAX_BEARER_NAME]; | 133 | char name[TIPC_MAX_BEARER_NAME]; |
| 137 | spinlock_t lock; | ||
| 138 | struct tipc_media *media; | 134 | struct tipc_media *media; |
| 139 | struct tipc_media_addr bcast_addr; | 135 | struct tipc_media_addr bcast_addr; |
| 140 | u32 priority; | 136 | u32 priority; |
| 141 | u32 window; | 137 | u32 window; |
| 142 | u32 tolerance; | 138 | u32 tolerance; |
| 139 | u32 domain; | ||
| 143 | u32 identity; | 140 | u32 identity; |
| 144 | struct tipc_link_req *link_req; | 141 | struct tipc_link_req *link_req; |
| 145 | struct list_head links; | ||
| 146 | int active; | ||
| 147 | char net_plane; | 142 | char net_plane; |
| 148 | struct tipc_node_map nodes; | 143 | struct tipc_node_map nodes; |
| 149 | }; | 144 | }; |
| @@ -155,7 +150,7 @@ struct tipc_bearer_names { | |||
| 155 | 150 | ||
| 156 | struct tipc_link; | 151 | struct tipc_link; |
| 157 | 152 | ||
| 158 | extern struct tipc_bearer tipc_bearers[]; | 153 | extern struct tipc_bearer *bearer_list[]; |
| 159 | 154 | ||
| 160 | /* | 155 | /* |
| 161 | * TIPC routines available to supported media types | 156 | * TIPC routines available to supported media types |
diff --git a/net/tipc/config.c b/net/tipc/config.c index e6d721692ae0..4b981c053823 100644 --- a/net/tipc/config.c +++ b/net/tipc/config.c | |||
| @@ -43,13 +43,11 @@ | |||
| 43 | #define REPLY_TRUNCATED "<truncated>\n" | 43 | #define REPLY_TRUNCATED "<truncated>\n" |
| 44 | 44 | ||
| 45 | static DEFINE_MUTEX(config_mutex); | 45 | static DEFINE_MUTEX(config_mutex); |
| 46 | static struct tipc_server cfgsrv; | ||
| 47 | 46 | ||
| 48 | static const void *req_tlv_area; /* request message TLV area */ | 47 | static const void *req_tlv_area; /* request message TLV area */ |
| 49 | static int req_tlv_space; /* request message TLV area size */ | 48 | static int req_tlv_space; /* request message TLV area size */ |
| 50 | static int rep_headroom; /* reply message headroom to use */ | 49 | static int rep_headroom; /* reply message headroom to use */ |
| 51 | 50 | ||
| 52 | |||
| 53 | struct sk_buff *tipc_cfg_reply_alloc(int payload_size) | 51 | struct sk_buff *tipc_cfg_reply_alloc(int payload_size) |
| 54 | { | 52 | { |
| 55 | struct sk_buff *buf; | 53 | struct sk_buff *buf; |
| @@ -185,18 +183,6 @@ static struct sk_buff *cfg_set_own_addr(void) | |||
| 185 | return tipc_cfg_reply_none(); | 183 | return tipc_cfg_reply_none(); |
| 186 | } | 184 | } |
| 187 | 185 | ||
| 188 | static struct sk_buff *cfg_set_remote_mng(void) | ||
| 189 | { | ||
| 190 | u32 value; | ||
| 191 | |||
| 192 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_UNSIGNED)) | ||
| 193 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | ||
| 194 | |||
| 195 | value = ntohl(*(__be32 *)TLV_DATA(req_tlv_area)); | ||
| 196 | tipc_remote_management = (value != 0); | ||
| 197 | return tipc_cfg_reply_none(); | ||
| 198 | } | ||
| 199 | |||
| 200 | static struct sk_buff *cfg_set_max_ports(void) | 186 | static struct sk_buff *cfg_set_max_ports(void) |
| 201 | { | 187 | { |
| 202 | u32 value; | 188 | u32 value; |
| @@ -247,21 +233,10 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area | |||
| 247 | /* Check command authorization */ | 233 | /* Check command authorization */ |
| 248 | if (likely(in_own_node(orig_node))) { | 234 | if (likely(in_own_node(orig_node))) { |
| 249 | /* command is permitted */ | 235 | /* command is permitted */ |
| 250 | } else if (cmd >= 0x8000) { | 236 | } else { |
| 251 | rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 237 | rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
| 252 | " (cannot be done remotely)"); | 238 | " (cannot be done remotely)"); |
| 253 | goto exit; | 239 | goto exit; |
| 254 | } else if (!tipc_remote_management) { | ||
| 255 | rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NO_REMOTE); | ||
| 256 | goto exit; | ||
| 257 | } else if (cmd >= 0x4000) { | ||
| 258 | u32 domain = 0; | ||
| 259 | |||
| 260 | if ((tipc_nametbl_translate(TIPC_ZM_SRV, 0, &domain) == 0) || | ||
| 261 | (domain != orig_node)) { | ||
| 262 | rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_ZONE_MSTR); | ||
| 263 | goto exit; | ||
| 264 | } | ||
| 265 | } | 240 | } |
| 266 | 241 | ||
| 267 | /* Call appropriate processing routine */ | 242 | /* Call appropriate processing routine */ |
| @@ -310,18 +285,12 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area | |||
| 310 | case TIPC_CMD_SET_NODE_ADDR: | 285 | case TIPC_CMD_SET_NODE_ADDR: |
| 311 | rep_tlv_buf = cfg_set_own_addr(); | 286 | rep_tlv_buf = cfg_set_own_addr(); |
| 312 | break; | 287 | break; |
| 313 | case TIPC_CMD_SET_REMOTE_MNG: | ||
| 314 | rep_tlv_buf = cfg_set_remote_mng(); | ||
| 315 | break; | ||
| 316 | case TIPC_CMD_SET_MAX_PORTS: | 288 | case TIPC_CMD_SET_MAX_PORTS: |
| 317 | rep_tlv_buf = cfg_set_max_ports(); | 289 | rep_tlv_buf = cfg_set_max_ports(); |
| 318 | break; | 290 | break; |
| 319 | case TIPC_CMD_SET_NETID: | 291 | case TIPC_CMD_SET_NETID: |
| 320 | rep_tlv_buf = cfg_set_netid(); | 292 | rep_tlv_buf = cfg_set_netid(); |
| 321 | break; | 293 | break; |
| 322 | case TIPC_CMD_GET_REMOTE_MNG: | ||
| 323 | rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_remote_management); | ||
| 324 | break; | ||
| 325 | case TIPC_CMD_GET_MAX_PORTS: | 294 | case TIPC_CMD_GET_MAX_PORTS: |
| 326 | rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_ports); | 295 | rep_tlv_buf = tipc_cfg_reply_unsigned(tipc_max_ports); |
| 327 | break; | 296 | break; |
| @@ -345,6 +314,8 @@ struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, const void *request_area | |||
| 345 | case TIPC_CMD_SET_MAX_PUBL: | 314 | case TIPC_CMD_SET_MAX_PUBL: |
| 346 | case TIPC_CMD_GET_MAX_PUBL: | 315 | case TIPC_CMD_GET_MAX_PUBL: |
| 347 | case TIPC_CMD_SET_LOG_SIZE: | 316 | case TIPC_CMD_SET_LOG_SIZE: |
| 317 | case TIPC_CMD_SET_REMOTE_MNG: | ||
| 318 | case TIPC_CMD_GET_REMOTE_MNG: | ||
| 348 | case TIPC_CMD_DUMP_LOG: | 319 | case TIPC_CMD_DUMP_LOG: |
| 349 | rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 320 | rep_tlv_buf = tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
| 350 | " (obsolete command)"); | 321 | " (obsolete command)"); |
| @@ -369,75 +340,3 @@ exit: | |||
| 369 | mutex_unlock(&config_mutex); | 340 | mutex_unlock(&config_mutex); |
| 370 | return rep_tlv_buf; | 341 | return rep_tlv_buf; |
| 371 | } | 342 | } |
| 372 | |||
| 373 | static void cfg_conn_msg_event(int conid, struct sockaddr_tipc *addr, | ||
| 374 | void *usr_data, void *buf, size_t len) | ||
| 375 | { | ||
| 376 | struct tipc_cfg_msg_hdr *req_hdr; | ||
| 377 | struct tipc_cfg_msg_hdr *rep_hdr; | ||
| 378 | struct sk_buff *rep_buf; | ||
| 379 | |||
| 380 | /* Validate configuration message header (ignore invalid message) */ | ||
| 381 | req_hdr = (struct tipc_cfg_msg_hdr *)buf; | ||
| 382 | if ((len < sizeof(*req_hdr)) || | ||
| 383 | (len != TCM_ALIGN(ntohl(req_hdr->tcm_len))) || | ||
| 384 | (ntohs(req_hdr->tcm_flags) != TCM_F_REQUEST)) { | ||
| 385 | pr_warn("Invalid configuration message discarded\n"); | ||
| 386 | return; | ||
| 387 | } | ||
| 388 | |||
| 389 | /* Generate reply for request (if can't, return request) */ | ||
| 390 | rep_buf = tipc_cfg_do_cmd(addr->addr.id.node, ntohs(req_hdr->tcm_type), | ||
| 391 | buf + sizeof(*req_hdr), | ||
| 392 | len - sizeof(*req_hdr), | ||
| 393 | BUF_HEADROOM + MAX_H_SIZE + sizeof(*rep_hdr)); | ||
| 394 | if (rep_buf) { | ||
| 395 | skb_push(rep_buf, sizeof(*rep_hdr)); | ||
| 396 | rep_hdr = (struct tipc_cfg_msg_hdr *)rep_buf->data; | ||
| 397 | memcpy(rep_hdr, req_hdr, sizeof(*rep_hdr)); | ||
| 398 | rep_hdr->tcm_len = htonl(rep_buf->len); | ||
| 399 | rep_hdr->tcm_flags &= htons(~TCM_F_REQUEST); | ||
| 400 | tipc_conn_sendmsg(&cfgsrv, conid, addr, rep_buf->data, | ||
| 401 | rep_buf->len); | ||
| 402 | kfree_skb(rep_buf); | ||
| 403 | } | ||
| 404 | } | ||
| 405 | |||
| 406 | static struct sockaddr_tipc cfgsrv_addr __read_mostly = { | ||
| 407 | .family = AF_TIPC, | ||
| 408 | .addrtype = TIPC_ADDR_NAMESEQ, | ||
| 409 | .addr.nameseq.type = TIPC_CFG_SRV, | ||
| 410 | .addr.nameseq.lower = 0, | ||
| 411 | .addr.nameseq.upper = 0, | ||
| 412 | .scope = TIPC_ZONE_SCOPE | ||
| 413 | }; | ||
| 414 | |||
| 415 | static struct tipc_server cfgsrv __read_mostly = { | ||
| 416 | .saddr = &cfgsrv_addr, | ||
| 417 | .imp = TIPC_CRITICAL_IMPORTANCE, | ||
| 418 | .type = SOCK_RDM, | ||
| 419 | .max_rcvbuf_size = 64 * 1024, | ||
| 420 | .name = "cfg_server", | ||
| 421 | .tipc_conn_recvmsg = cfg_conn_msg_event, | ||
| 422 | .tipc_conn_new = NULL, | ||
| 423 | .tipc_conn_shutdown = NULL | ||
| 424 | }; | ||
| 425 | |||
| 426 | int tipc_cfg_init(void) | ||
| 427 | { | ||
| 428 | return tipc_server_start(&cfgsrv); | ||
| 429 | } | ||
| 430 | |||
| 431 | void tipc_cfg_reinit(void) | ||
| 432 | { | ||
| 433 | tipc_server_stop(&cfgsrv); | ||
| 434 | |||
| 435 | cfgsrv_addr.addr.nameseq.lower = tipc_own_addr; | ||
| 436 | cfgsrv_addr.addr.nameseq.upper = tipc_own_addr; | ||
| 437 | tipc_server_start(&cfgsrv); | ||
| 438 | } | ||
| 439 | |||
| 440 | void tipc_cfg_stop(void) | ||
| 441 | { | ||
| 442 | tipc_server_stop(&cfgsrv); | ||
| 443 | } | ||
diff --git a/net/tipc/config.h b/net/tipc/config.h index 1f252f3fa058..47b1bf181612 100644 --- a/net/tipc/config.h +++ b/net/tipc/config.h | |||
| @@ -64,9 +64,4 @@ static inline struct sk_buff *tipc_cfg_reply_ultra_string(char *string) | |||
| 64 | struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, | 64 | struct sk_buff *tipc_cfg_do_cmd(u32 orig_node, u16 cmd, |
| 65 | const void *req_tlv_area, int req_tlv_space, | 65 | const void *req_tlv_area, int req_tlv_space, |
| 66 | int headroom); | 66 | int headroom); |
| 67 | |||
| 68 | int tipc_cfg_init(void); | ||
| 69 | void tipc_cfg_reinit(void); | ||
| 70 | void tipc_cfg_stop(void); | ||
| 71 | |||
| 72 | #endif | 67 | #endif |
diff --git a/net/tipc/core.c b/net/tipc/core.c index 80c20647b3d2..50d57429ebca 100644 --- a/net/tipc/core.c +++ b/net/tipc/core.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * net/tipc/core.c: TIPC module code | 2 | * net/tipc/core.c: TIPC module code |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2003-2006, Ericsson AB | 4 | * Copyright (c) 2003-2006, 2013, Ericsson AB |
| 5 | * Copyright (c) 2005-2006, 2010-2013, Wind River Systems | 5 | * Copyright (c) 2005-2006, 2010-2013, Wind River Systems |
| 6 | * All rights reserved. | 6 | * All rights reserved. |
| 7 | * | 7 | * |
| @@ -50,7 +50,6 @@ int tipc_random __read_mostly; | |||
| 50 | u32 tipc_own_addr __read_mostly; | 50 | u32 tipc_own_addr __read_mostly; |
| 51 | int tipc_max_ports __read_mostly; | 51 | int tipc_max_ports __read_mostly; |
| 52 | int tipc_net_id __read_mostly; | 52 | int tipc_net_id __read_mostly; |
| 53 | int tipc_remote_management __read_mostly; | ||
| 54 | int sysctl_tipc_rmem[3] __read_mostly; /* min/default/max */ | 53 | int sysctl_tipc_rmem[3] __read_mostly; /* min/default/max */ |
| 55 | 54 | ||
| 56 | /** | 55 | /** |
| @@ -85,7 +84,6 @@ static void tipc_core_stop(void) | |||
| 85 | tipc_net_stop(); | 84 | tipc_net_stop(); |
| 86 | tipc_bearer_cleanup(); | 85 | tipc_bearer_cleanup(); |
| 87 | tipc_netlink_stop(); | 86 | tipc_netlink_stop(); |
| 88 | tipc_cfg_stop(); | ||
| 89 | tipc_subscr_stop(); | 87 | tipc_subscr_stop(); |
| 90 | tipc_nametbl_stop(); | 88 | tipc_nametbl_stop(); |
| 91 | tipc_ref_table_stop(); | 89 | tipc_ref_table_stop(); |
| @@ -130,18 +128,12 @@ static int tipc_core_start(void) | |||
| 130 | if (err) | 128 | if (err) |
| 131 | goto out_subscr; | 129 | goto out_subscr; |
| 132 | 130 | ||
| 133 | err = tipc_cfg_init(); | ||
| 134 | if (err) | ||
| 135 | goto out_cfg; | ||
| 136 | |||
| 137 | err = tipc_bearer_setup(); | 131 | err = tipc_bearer_setup(); |
| 138 | if (err) | 132 | if (err) |
| 139 | goto out_bearer; | 133 | goto out_bearer; |
| 140 | 134 | ||
| 141 | return 0; | 135 | return 0; |
| 142 | out_bearer: | 136 | out_bearer: |
| 143 | tipc_cfg_stop(); | ||
| 144 | out_cfg: | ||
| 145 | tipc_subscr_stop(); | 137 | tipc_subscr_stop(); |
| 146 | out_subscr: | 138 | out_subscr: |
| 147 | tipc_unregister_sysctl(); | 139 | tipc_unregister_sysctl(); |
| @@ -166,7 +158,6 @@ static int __init tipc_init(void) | |||
| 166 | pr_info("Activated (version " TIPC_MOD_VER ")\n"); | 158 | pr_info("Activated (version " TIPC_MOD_VER ")\n"); |
| 167 | 159 | ||
| 168 | tipc_own_addr = 0; | 160 | tipc_own_addr = 0; |
| 169 | tipc_remote_management = 1; | ||
| 170 | tipc_max_ports = CONFIG_TIPC_PORTS; | 161 | tipc_max_ports = CONFIG_TIPC_PORTS; |
| 171 | tipc_net_id = 4711; | 162 | tipc_net_id = 4711; |
| 172 | 163 | ||
diff --git a/net/tipc/core.h b/net/tipc/core.h index 4dfe137587bb..8985bbcb942b 100644 --- a/net/tipc/core.h +++ b/net/tipc/core.h | |||
| @@ -79,7 +79,6 @@ int tipc_snprintf(char *buf, int len, const char *fmt, ...); | |||
| 79 | extern u32 tipc_own_addr __read_mostly; | 79 | extern u32 tipc_own_addr __read_mostly; |
| 80 | extern int tipc_max_ports __read_mostly; | 80 | extern int tipc_max_ports __read_mostly; |
| 81 | extern int tipc_net_id __read_mostly; | 81 | extern int tipc_net_id __read_mostly; |
| 82 | extern int tipc_remote_management __read_mostly; | ||
| 83 | extern int sysctl_tipc_rmem[3] __read_mostly; | 82 | extern int sysctl_tipc_rmem[3] __read_mostly; |
| 84 | 83 | ||
| 85 | /* | 84 | /* |
diff --git a/net/tipc/discover.c b/net/tipc/discover.c index 412ff41b8611..542fe3413dc4 100644 --- a/net/tipc/discover.c +++ b/net/tipc/discover.c | |||
| @@ -48,7 +48,6 @@ | |||
| 48 | * struct tipc_link_req - information about an ongoing link setup request | 48 | * struct tipc_link_req - information about an ongoing link setup request |
| 49 | * @bearer: bearer issuing requests | 49 | * @bearer: bearer issuing requests |
| 50 | * @dest: destination address for request messages | 50 | * @dest: destination address for request messages |
| 51 | * @domain: network domain to which links can be established | ||
| 52 | * @num_nodes: number of nodes currently discovered (i.e. with an active link) | 51 | * @num_nodes: number of nodes currently discovered (i.e. with an active link) |
| 53 | * @lock: spinlock for controlling access to requests | 52 | * @lock: spinlock for controlling access to requests |
| 54 | * @buf: request message to be (repeatedly) sent | 53 | * @buf: request message to be (repeatedly) sent |
| @@ -58,7 +57,6 @@ | |||
| 58 | struct tipc_link_req { | 57 | struct tipc_link_req { |
| 59 | struct tipc_bearer *bearer; | 58 | struct tipc_bearer *bearer; |
| 60 | struct tipc_media_addr dest; | 59 | struct tipc_media_addr dest; |
| 61 | u32 domain; | ||
| 62 | int num_nodes; | 60 | int num_nodes; |
| 63 | spinlock_t lock; | 61 | spinlock_t lock; |
| 64 | struct sk_buff *buf; | 62 | struct sk_buff *buf; |
| @@ -69,14 +67,13 @@ struct tipc_link_req { | |||
| 69 | /** | 67 | /** |
| 70 | * tipc_disc_init_msg - initialize a link setup message | 68 | * tipc_disc_init_msg - initialize a link setup message |
| 71 | * @type: message type (request or response) | 69 | * @type: message type (request or response) |
| 72 | * @dest_domain: network domain of node(s) which should respond to message | ||
| 73 | * @b_ptr: ptr to bearer issuing message | 70 | * @b_ptr: ptr to bearer issuing message |
| 74 | */ | 71 | */ |
| 75 | static struct sk_buff *tipc_disc_init_msg(u32 type, u32 dest_domain, | 72 | static struct sk_buff *tipc_disc_init_msg(u32 type, struct tipc_bearer *b_ptr) |
| 76 | struct tipc_bearer *b_ptr) | ||
| 77 | { | 73 | { |
| 78 | struct sk_buff *buf = tipc_buf_acquire(INT_H_SIZE); | 74 | struct sk_buff *buf = tipc_buf_acquire(INT_H_SIZE); |
| 79 | struct tipc_msg *msg; | 75 | struct tipc_msg *msg; |
| 76 | u32 dest_domain = b_ptr->domain; | ||
| 80 | 77 | ||
| 81 | if (buf) { | 78 | if (buf) { |
| 82 | msg = buf_msg(buf); | 79 | msg = buf_msg(buf); |
| @@ -110,11 +107,11 @@ static void disc_dupl_alert(struct tipc_bearer *b_ptr, u32 node_addr, | |||
| 110 | } | 107 | } |
| 111 | 108 | ||
| 112 | /** | 109 | /** |
| 113 | * tipc_disc_recv_msg - handle incoming link setup message (request or response) | 110 | * tipc_disc_rcv - handle incoming link setup message (request or response) |
| 114 | * @buf: buffer containing message | 111 | * @buf: buffer containing message |
| 115 | * @b_ptr: bearer that message arrived on | 112 | * @b_ptr: bearer that message arrived on |
| 116 | */ | 113 | */ |
| 117 | void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr) | 114 | void tipc_disc_rcv(struct sk_buff *buf, struct tipc_bearer *b_ptr) |
| 118 | { | 115 | { |
| 119 | struct tipc_node *n_ptr; | 116 | struct tipc_node *n_ptr; |
| 120 | struct tipc_link *link; | 117 | struct tipc_link *link; |
| @@ -149,7 +146,7 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr) | |||
| 149 | } | 146 | } |
| 150 | if (!tipc_in_scope(dest, tipc_own_addr)) | 147 | if (!tipc_in_scope(dest, tipc_own_addr)) |
| 151 | return; | 148 | return; |
| 152 | if (!tipc_in_scope(b_ptr->link_req->domain, orig)) | 149 | if (!tipc_in_scope(b_ptr->domain, orig)) |
| 153 | return; | 150 | return; |
| 154 | 151 | ||
| 155 | /* Locate structure corresponding to requesting node */ | 152 | /* Locate structure corresponding to requesting node */ |
| @@ -242,7 +239,7 @@ void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr) | |||
| 242 | link_fully_up = link_working_working(link); | 239 | link_fully_up = link_working_working(link); |
| 243 | 240 | ||
| 244 | if ((type == DSC_REQ_MSG) && !link_fully_up) { | 241 | if ((type == DSC_REQ_MSG) && !link_fully_up) { |
| 245 | rbuf = tipc_disc_init_msg(DSC_RESP_MSG, orig, b_ptr); | 242 | rbuf = tipc_disc_init_msg(DSC_RESP_MSG, b_ptr); |
| 246 | if (rbuf) { | 243 | if (rbuf) { |
| 247 | tipc_bearer_send(b_ptr, rbuf, &media_addr); | 244 | tipc_bearer_send(b_ptr, rbuf, &media_addr); |
| 248 | kfree_skb(rbuf); | 245 | kfree_skb(rbuf); |
| @@ -306,7 +303,7 @@ static void disc_timeout(struct tipc_link_req *req) | |||
| 306 | spin_lock_bh(&req->lock); | 303 | spin_lock_bh(&req->lock); |
| 307 | 304 | ||
| 308 | /* Stop searching if only desired node has been found */ | 305 | /* Stop searching if only desired node has been found */ |
| 309 | if (tipc_node(req->domain) && req->num_nodes) { | 306 | if (tipc_node(req->bearer->domain) && req->num_nodes) { |
| 310 | req->timer_intv = TIPC_LINK_REQ_INACTIVE; | 307 | req->timer_intv = TIPC_LINK_REQ_INACTIVE; |
| 311 | goto exit; | 308 | goto exit; |
| 312 | } | 309 | } |
| @@ -342,8 +339,7 @@ exit: | |||
| 342 | * | 339 | * |
| 343 | * Returns 0 if successful, otherwise -errno. | 340 | * Returns 0 if successful, otherwise -errno. |
| 344 | */ | 341 | */ |
| 345 | int tipc_disc_create(struct tipc_bearer *b_ptr, struct tipc_media_addr *dest, | 342 | int tipc_disc_create(struct tipc_bearer *b_ptr, struct tipc_media_addr *dest) |
| 346 | u32 dest_domain) | ||
| 347 | { | 343 | { |
| 348 | struct tipc_link_req *req; | 344 | struct tipc_link_req *req; |
| 349 | 345 | ||
| @@ -351,7 +347,7 @@ int tipc_disc_create(struct tipc_bearer *b_ptr, struct tipc_media_addr *dest, | |||
| 351 | if (!req) | 347 | if (!req) |
| 352 | return -ENOMEM; | 348 | return -ENOMEM; |
| 353 | 349 | ||
| 354 | req->buf = tipc_disc_init_msg(DSC_REQ_MSG, dest_domain, b_ptr); | 350 | req->buf = tipc_disc_init_msg(DSC_REQ_MSG, b_ptr); |
| 355 | if (!req->buf) { | 351 | if (!req->buf) { |
| 356 | kfree(req); | 352 | kfree(req); |
| 357 | return -ENOMSG; | 353 | return -ENOMSG; |
| @@ -359,7 +355,6 @@ int tipc_disc_create(struct tipc_bearer *b_ptr, struct tipc_media_addr *dest, | |||
| 359 | 355 | ||
| 360 | memcpy(&req->dest, dest, sizeof(*dest)); | 356 | memcpy(&req->dest, dest, sizeof(*dest)); |
| 361 | req->bearer = b_ptr; | 357 | req->bearer = b_ptr; |
| 362 | req->domain = dest_domain; | ||
| 363 | req->num_nodes = 0; | 358 | req->num_nodes = 0; |
| 364 | req->timer_intv = TIPC_LINK_REQ_INIT; | 359 | req->timer_intv = TIPC_LINK_REQ_INIT; |
| 365 | spin_lock_init(&req->lock); | 360 | spin_lock_init(&req->lock); |
diff --git a/net/tipc/discover.h b/net/tipc/discover.h index 75b67c403aa3..07f34729459d 100644 --- a/net/tipc/discover.h +++ b/net/tipc/discover.h | |||
| @@ -39,11 +39,10 @@ | |||
| 39 | 39 | ||
| 40 | struct tipc_link_req; | 40 | struct tipc_link_req; |
| 41 | 41 | ||
| 42 | int tipc_disc_create(struct tipc_bearer *b_ptr, struct tipc_media_addr *dest, | 42 | int tipc_disc_create(struct tipc_bearer *b_ptr, struct tipc_media_addr *dest); |
| 43 | u32 dest_domain); | ||
| 44 | void tipc_disc_delete(struct tipc_link_req *req); | 43 | void tipc_disc_delete(struct tipc_link_req *req); |
| 45 | void tipc_disc_add_dest(struct tipc_link_req *req); | 44 | void tipc_disc_add_dest(struct tipc_link_req *req); |
| 46 | void tipc_disc_remove_dest(struct tipc_link_req *req); | 45 | void tipc_disc_remove_dest(struct tipc_link_req *req); |
| 47 | void tipc_disc_recv_msg(struct sk_buff *buf, struct tipc_bearer *b_ptr); | 46 | void tipc_disc_rcv(struct sk_buff *buf, struct tipc_bearer *b_ptr); |
| 48 | 47 | ||
| 49 | #endif | 48 | #endif |
diff --git a/net/tipc/link.c b/net/tipc/link.c index da6018beb6eb..c5190ab75290 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c | |||
| @@ -77,19 +77,19 @@ static const char *link_unk_evt = "Unknown link event "; | |||
| 77 | 77 | ||
| 78 | static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr, | 78 | static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr, |
| 79 | struct sk_buff *buf); | 79 | struct sk_buff *buf); |
| 80 | static void link_recv_proto_msg(struct tipc_link *l_ptr, struct sk_buff *buf); | 80 | static void tipc_link_proto_rcv(struct tipc_link *l_ptr, struct sk_buff *buf); |
| 81 | static int tipc_link_tunnel_rcv(struct tipc_link **l_ptr, | 81 | static int tipc_link_tunnel_rcv(struct tipc_node *n_ptr, |
| 82 | struct sk_buff **buf); | 82 | struct sk_buff **buf); |
| 83 | static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tolerance); | 83 | static void link_set_supervision_props(struct tipc_link *l_ptr, u32 tolerance); |
| 84 | static int link_send_sections_long(struct tipc_port *sender, | 84 | static int tipc_link_iovec_long_xmit(struct tipc_port *sender, |
| 85 | struct iovec const *msg_sect, | 85 | struct iovec const *msg_sect, |
| 86 | unsigned int len, u32 destnode); | 86 | unsigned int len, u32 destnode); |
| 87 | static void link_state_event(struct tipc_link *l_ptr, u32 event); | 87 | static void link_state_event(struct tipc_link *l_ptr, u32 event); |
| 88 | static void link_reset_statistics(struct tipc_link *l_ptr); | 88 | static void link_reset_statistics(struct tipc_link *l_ptr); |
| 89 | static void link_print(struct tipc_link *l_ptr, const char *str); | 89 | static void link_print(struct tipc_link *l_ptr, const char *str); |
| 90 | static int link_send_long_buf(struct tipc_link *l_ptr, struct sk_buff *buf); | 90 | static int tipc_link_frag_xmit(struct tipc_link *l_ptr, struct sk_buff *buf); |
| 91 | static void tipc_link_send_sync(struct tipc_link *l); | 91 | static void tipc_link_sync_xmit(struct tipc_link *l); |
| 92 | static void tipc_link_recv_sync(struct tipc_node *n, struct sk_buff *buf); | 92 | static void tipc_link_sync_rcv(struct tipc_node *n, struct sk_buff *buf); |
| 93 | 93 | ||
| 94 | /* | 94 | /* |
| 95 | * Simple link routines | 95 | * Simple link routines |
| @@ -147,11 +147,6 @@ int tipc_link_is_active(struct tipc_link *l_ptr) | |||
| 147 | /** | 147 | /** |
| 148 | * link_timeout - handle expiration of link timer | 148 | * link_timeout - handle expiration of link timer |
| 149 | * @l_ptr: pointer to link | 149 | * @l_ptr: pointer to link |
| 150 | * | ||
| 151 | * This routine must not grab "tipc_net_lock" to avoid a potential deadlock conflict | ||
| 152 | * with tipc_link_delete(). (There is no risk that the node will be deleted by | ||
| 153 | * another thread because tipc_link_delete() always cancels the link timer before | ||
| 154 | * tipc_node_delete() is called.) | ||
| 155 | */ | 150 | */ |
| 156 | static void link_timeout(struct tipc_link *l_ptr) | 151 | static void link_timeout(struct tipc_link *l_ptr) |
| 157 | { | 152 | { |
| @@ -213,8 +208,8 @@ static void link_set_timer(struct tipc_link *l_ptr, u32 time) | |||
| 213 | * Returns pointer to link. | 208 | * Returns pointer to link. |
| 214 | */ | 209 | */ |
| 215 | struct tipc_link *tipc_link_create(struct tipc_node *n_ptr, | 210 | struct tipc_link *tipc_link_create(struct tipc_node *n_ptr, |
| 216 | struct tipc_bearer *b_ptr, | 211 | struct tipc_bearer *b_ptr, |
| 217 | const struct tipc_media_addr *media_addr) | 212 | const struct tipc_media_addr *media_addr) |
| 218 | { | 213 | { |
| 219 | struct tipc_link *l_ptr; | 214 | struct tipc_link *l_ptr; |
| 220 | struct tipc_msg *msg; | 215 | struct tipc_msg *msg; |
| @@ -279,41 +274,44 @@ struct tipc_link *tipc_link_create(struct tipc_node *n_ptr, | |||
| 279 | 274 | ||
| 280 | k_init_timer(&l_ptr->timer, (Handler)link_timeout, | 275 | k_init_timer(&l_ptr->timer, (Handler)link_timeout, |
| 281 | (unsigned long)l_ptr); | 276 | (unsigned long)l_ptr); |
| 282 | list_add_tail(&l_ptr->link_list, &b_ptr->links); | ||
| 283 | 277 | ||
| 284 | link_state_event(l_ptr, STARTING_EVT); | 278 | link_state_event(l_ptr, STARTING_EVT); |
| 285 | 279 | ||
| 286 | return l_ptr; | 280 | return l_ptr; |
| 287 | } | 281 | } |
| 288 | 282 | ||
| 289 | /** | 283 | void tipc_link_delete_list(unsigned int bearer_id, bool shutting_down) |
| 290 | * tipc_link_delete - delete a link | ||
| 291 | * @l_ptr: pointer to link | ||
| 292 | * | ||
| 293 | * Note: 'tipc_net_lock' is write_locked, bearer is locked. | ||
| 294 | * This routine must not grab the node lock until after link timer cancellation | ||
| 295 | * to avoid a potential deadlock situation. | ||
| 296 | */ | ||
| 297 | void tipc_link_delete(struct tipc_link *l_ptr) | ||
| 298 | { | 284 | { |
| 299 | if (!l_ptr) { | 285 | struct tipc_link *l_ptr; |
| 300 | pr_err("Attempt to delete non-existent link\n"); | 286 | struct tipc_node *n_ptr; |
| 301 | return; | ||
| 302 | } | ||
| 303 | |||
| 304 | k_cancel_timer(&l_ptr->timer); | ||
| 305 | 287 | ||
| 306 | tipc_node_lock(l_ptr->owner); | 288 | rcu_read_lock(); |
| 307 | tipc_link_reset(l_ptr); | 289 | list_for_each_entry_rcu(n_ptr, &tipc_node_list, list) { |
| 308 | tipc_node_detach_link(l_ptr->owner, l_ptr); | 290 | spin_lock_bh(&n_ptr->lock); |
| 309 | tipc_link_purge_queues(l_ptr); | 291 | l_ptr = n_ptr->links[bearer_id]; |
| 310 | list_del_init(&l_ptr->link_list); | 292 | if (l_ptr) { |
| 311 | tipc_node_unlock(l_ptr->owner); | 293 | tipc_link_reset(l_ptr); |
| 312 | k_term_timer(&l_ptr->timer); | 294 | if (shutting_down || !tipc_node_is_up(n_ptr)) { |
| 313 | kfree(l_ptr); | 295 | tipc_node_detach_link(l_ptr->owner, l_ptr); |
| 296 | tipc_link_reset_fragments(l_ptr); | ||
| 297 | spin_unlock_bh(&n_ptr->lock); | ||
| 298 | |||
| 299 | /* Nobody else can access this link now: */ | ||
| 300 | del_timer_sync(&l_ptr->timer); | ||
| 301 | kfree(l_ptr); | ||
| 302 | } else { | ||
| 303 | /* Detach/delete when failover is finished: */ | ||
| 304 | l_ptr->flags |= LINK_STOPPED; | ||
| 305 | spin_unlock_bh(&n_ptr->lock); | ||
| 306 | del_timer_sync(&l_ptr->timer); | ||
| 307 | } | ||
| 308 | continue; | ||
| 309 | } | ||
| 310 | spin_unlock_bh(&n_ptr->lock); | ||
| 311 | } | ||
| 312 | rcu_read_unlock(); | ||
| 314 | } | 313 | } |
| 315 | 314 | ||
| 316 | |||
| 317 | /** | 315 | /** |
| 318 | * link_schedule_port - schedule port for deferred sending | 316 | * link_schedule_port - schedule port for deferred sending |
| 319 | * @l_ptr: pointer to link | 317 | * @l_ptr: pointer to link |
| @@ -330,8 +328,6 @@ static int link_schedule_port(struct tipc_link *l_ptr, u32 origport, u32 sz) | |||
| 330 | spin_lock_bh(&tipc_port_list_lock); | 328 | spin_lock_bh(&tipc_port_list_lock); |
| 331 | p_ptr = tipc_port_lock(origport); | 329 | p_ptr = tipc_port_lock(origport); |
| 332 | if (p_ptr) { | 330 | if (p_ptr) { |
| 333 | if (!p_ptr->wakeup) | ||
| 334 | goto exit; | ||
| 335 | if (!list_empty(&p_ptr->wait_list)) | 331 | if (!list_empty(&p_ptr->wait_list)) |
| 336 | goto exit; | 332 | goto exit; |
| 337 | p_ptr->congested = 1; | 333 | p_ptr->congested = 1; |
| @@ -366,7 +362,7 @@ void tipc_link_wakeup_ports(struct tipc_link *l_ptr, int all) | |||
| 366 | list_del_init(&p_ptr->wait_list); | 362 | list_del_init(&p_ptr->wait_list); |
| 367 | spin_lock_bh(p_ptr->lock); | 363 | spin_lock_bh(p_ptr->lock); |
| 368 | p_ptr->congested = 0; | 364 | p_ptr->congested = 0; |
| 369 | p_ptr->wakeup(p_ptr); | 365 | tipc_port_wakeup(p_ptr); |
| 370 | win -= p_ptr->waiting_pkts; | 366 | win -= p_ptr->waiting_pkts; |
| 371 | spin_unlock_bh(p_ptr->lock); | 367 | spin_unlock_bh(p_ptr->lock); |
| 372 | } | 368 | } |
| @@ -461,6 +457,21 @@ void tipc_link_reset(struct tipc_link *l_ptr) | |||
| 461 | link_reset_statistics(l_ptr); | 457 | link_reset_statistics(l_ptr); |
| 462 | } | 458 | } |
| 463 | 459 | ||
| 460 | void tipc_link_reset_list(unsigned int bearer_id) | ||
| 461 | { | ||
| 462 | struct tipc_link *l_ptr; | ||
| 463 | struct tipc_node *n_ptr; | ||
| 464 | |||
| 465 | rcu_read_lock(); | ||
| 466 | list_for_each_entry_rcu(n_ptr, &tipc_node_list, list) { | ||
| 467 | spin_lock_bh(&n_ptr->lock); | ||
| 468 | l_ptr = n_ptr->links[bearer_id]; | ||
| 469 | if (l_ptr) | ||
| 470 | tipc_link_reset(l_ptr); | ||
| 471 | spin_unlock_bh(&n_ptr->lock); | ||
| 472 | } | ||
| 473 | rcu_read_unlock(); | ||
| 474 | } | ||
| 464 | 475 | ||
| 465 | static void link_activate(struct tipc_link *l_ptr) | 476 | static void link_activate(struct tipc_link *l_ptr) |
| 466 | { | 477 | { |
| @@ -479,7 +490,10 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event) | |||
| 479 | struct tipc_link *other; | 490 | struct tipc_link *other; |
| 480 | u32 cont_intv = l_ptr->continuity_interval; | 491 | u32 cont_intv = l_ptr->continuity_interval; |
| 481 | 492 | ||
| 482 | if (!l_ptr->started && (event != STARTING_EVT)) | 493 | if (l_ptr->flags & LINK_STOPPED) |
| 494 | return; | ||
| 495 | |||
| 496 | if (!(l_ptr->flags & LINK_STARTED) && (event != STARTING_EVT)) | ||
| 483 | return; /* Not yet. */ | 497 | return; /* Not yet. */ |
| 484 | 498 | ||
| 485 | /* Check whether changeover is going on */ | 499 | /* Check whether changeover is going on */ |
| @@ -499,12 +513,12 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event) | |||
| 499 | if (l_ptr->next_in_no != l_ptr->checkpoint) { | 513 | if (l_ptr->next_in_no != l_ptr->checkpoint) { |
| 500 | l_ptr->checkpoint = l_ptr->next_in_no; | 514 | l_ptr->checkpoint = l_ptr->next_in_no; |
| 501 | if (tipc_bclink_acks_missing(l_ptr->owner)) { | 515 | if (tipc_bclink_acks_missing(l_ptr->owner)) { |
| 502 | tipc_link_send_proto_msg(l_ptr, STATE_MSG, | 516 | tipc_link_proto_xmit(l_ptr, STATE_MSG, |
| 503 | 0, 0, 0, 0, 0); | 517 | 0, 0, 0, 0, 0); |
| 504 | l_ptr->fsm_msg_cnt++; | 518 | l_ptr->fsm_msg_cnt++; |
| 505 | } else if (l_ptr->max_pkt < l_ptr->max_pkt_target) { | 519 | } else if (l_ptr->max_pkt < l_ptr->max_pkt_target) { |
| 506 | tipc_link_send_proto_msg(l_ptr, STATE_MSG, | 520 | tipc_link_proto_xmit(l_ptr, STATE_MSG, |
| 507 | 1, 0, 0, 0, 0); | 521 | 1, 0, 0, 0, 0); |
| 508 | l_ptr->fsm_msg_cnt++; | 522 | l_ptr->fsm_msg_cnt++; |
| 509 | } | 523 | } |
| 510 | link_set_timer(l_ptr, cont_intv); | 524 | link_set_timer(l_ptr, cont_intv); |
| @@ -512,7 +526,7 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event) | |||
| 512 | } | 526 | } |
| 513 | l_ptr->state = WORKING_UNKNOWN; | 527 | l_ptr->state = WORKING_UNKNOWN; |
| 514 | l_ptr->fsm_msg_cnt = 0; | 528 | l_ptr->fsm_msg_cnt = 0; |
| 515 | tipc_link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0); | 529 | tipc_link_proto_xmit(l_ptr, STATE_MSG, 1, 0, 0, 0, 0); |
| 516 | l_ptr->fsm_msg_cnt++; | 530 | l_ptr->fsm_msg_cnt++; |
| 517 | link_set_timer(l_ptr, cont_intv / 4); | 531 | link_set_timer(l_ptr, cont_intv / 4); |
| 518 | break; | 532 | break; |
| @@ -522,7 +536,8 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event) | |||
| 522 | tipc_link_reset(l_ptr); | 536 | tipc_link_reset(l_ptr); |
| 523 | l_ptr->state = RESET_RESET; | 537 | l_ptr->state = RESET_RESET; |
| 524 | l_ptr->fsm_msg_cnt = 0; | 538 | l_ptr->fsm_msg_cnt = 0; |
| 525 | tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0); | 539 | tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG, |
| 540 | 0, 0, 0, 0, 0); | ||
| 526 | l_ptr->fsm_msg_cnt++; | 541 | l_ptr->fsm_msg_cnt++; |
| 527 | link_set_timer(l_ptr, cont_intv); | 542 | link_set_timer(l_ptr, cont_intv); |
| 528 | break; | 543 | break; |
| @@ -544,7 +559,8 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event) | |||
| 544 | tipc_link_reset(l_ptr); | 559 | tipc_link_reset(l_ptr); |
| 545 | l_ptr->state = RESET_RESET; | 560 | l_ptr->state = RESET_RESET; |
| 546 | l_ptr->fsm_msg_cnt = 0; | 561 | l_ptr->fsm_msg_cnt = 0; |
| 547 | tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0); | 562 | tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG, |
| 563 | 0, 0, 0, 0, 0); | ||
| 548 | l_ptr->fsm_msg_cnt++; | 564 | l_ptr->fsm_msg_cnt++; |
| 549 | link_set_timer(l_ptr, cont_intv); | 565 | link_set_timer(l_ptr, cont_intv); |
| 550 | break; | 566 | break; |
| @@ -554,14 +570,14 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event) | |||
| 554 | l_ptr->fsm_msg_cnt = 0; | 570 | l_ptr->fsm_msg_cnt = 0; |
| 555 | l_ptr->checkpoint = l_ptr->next_in_no; | 571 | l_ptr->checkpoint = l_ptr->next_in_no; |
| 556 | if (tipc_bclink_acks_missing(l_ptr->owner)) { | 572 | if (tipc_bclink_acks_missing(l_ptr->owner)) { |
| 557 | tipc_link_send_proto_msg(l_ptr, STATE_MSG, | 573 | tipc_link_proto_xmit(l_ptr, STATE_MSG, |
| 558 | 0, 0, 0, 0, 0); | 574 | 0, 0, 0, 0, 0); |
| 559 | l_ptr->fsm_msg_cnt++; | 575 | l_ptr->fsm_msg_cnt++; |
| 560 | } | 576 | } |
| 561 | link_set_timer(l_ptr, cont_intv); | 577 | link_set_timer(l_ptr, cont_intv); |
| 562 | } else if (l_ptr->fsm_msg_cnt < l_ptr->abort_limit) { | 578 | } else if (l_ptr->fsm_msg_cnt < l_ptr->abort_limit) { |
| 563 | tipc_link_send_proto_msg(l_ptr, STATE_MSG, | 579 | tipc_link_proto_xmit(l_ptr, STATE_MSG, |
| 564 | 1, 0, 0, 0, 0); | 580 | 1, 0, 0, 0, 0); |
| 565 | l_ptr->fsm_msg_cnt++; | 581 | l_ptr->fsm_msg_cnt++; |
| 566 | link_set_timer(l_ptr, cont_intv / 4); | 582 | link_set_timer(l_ptr, cont_intv / 4); |
| 567 | } else { /* Link has failed */ | 583 | } else { /* Link has failed */ |
| @@ -570,8 +586,8 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event) | |||
| 570 | tipc_link_reset(l_ptr); | 586 | tipc_link_reset(l_ptr); |
| 571 | l_ptr->state = RESET_UNKNOWN; | 587 | l_ptr->state = RESET_UNKNOWN; |
| 572 | l_ptr->fsm_msg_cnt = 0; | 588 | l_ptr->fsm_msg_cnt = 0; |
| 573 | tipc_link_send_proto_msg(l_ptr, RESET_MSG, | 589 | tipc_link_proto_xmit(l_ptr, RESET_MSG, |
| 574 | 0, 0, 0, 0, 0); | 590 | 0, 0, 0, 0, 0); |
| 575 | l_ptr->fsm_msg_cnt++; | 591 | l_ptr->fsm_msg_cnt++; |
| 576 | link_set_timer(l_ptr, cont_intv); | 592 | link_set_timer(l_ptr, cont_intv); |
| 577 | } | 593 | } |
| @@ -591,24 +607,25 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event) | |||
| 591 | l_ptr->state = WORKING_WORKING; | 607 | l_ptr->state = WORKING_WORKING; |
| 592 | l_ptr->fsm_msg_cnt = 0; | 608 | l_ptr->fsm_msg_cnt = 0; |
| 593 | link_activate(l_ptr); | 609 | link_activate(l_ptr); |
| 594 | tipc_link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0); | 610 | tipc_link_proto_xmit(l_ptr, STATE_MSG, 1, 0, 0, 0, 0); |
| 595 | l_ptr->fsm_msg_cnt++; | 611 | l_ptr->fsm_msg_cnt++; |
| 596 | if (l_ptr->owner->working_links == 1) | 612 | if (l_ptr->owner->working_links == 1) |
| 597 | tipc_link_send_sync(l_ptr); | 613 | tipc_link_sync_xmit(l_ptr); |
| 598 | link_set_timer(l_ptr, cont_intv); | 614 | link_set_timer(l_ptr, cont_intv); |
| 599 | break; | 615 | break; |
| 600 | case RESET_MSG: | 616 | case RESET_MSG: |
| 601 | l_ptr->state = RESET_RESET; | 617 | l_ptr->state = RESET_RESET; |
| 602 | l_ptr->fsm_msg_cnt = 0; | 618 | l_ptr->fsm_msg_cnt = 0; |
| 603 | tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 1, 0, 0, 0, 0); | 619 | tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG, |
| 620 | 1, 0, 0, 0, 0); | ||
| 604 | l_ptr->fsm_msg_cnt++; | 621 | l_ptr->fsm_msg_cnt++; |
| 605 | link_set_timer(l_ptr, cont_intv); | 622 | link_set_timer(l_ptr, cont_intv); |
| 606 | break; | 623 | break; |
| 607 | case STARTING_EVT: | 624 | case STARTING_EVT: |
| 608 | l_ptr->started = 1; | 625 | l_ptr->flags |= LINK_STARTED; |
| 609 | /* fall through */ | 626 | /* fall through */ |
| 610 | case TIMEOUT_EVT: | 627 | case TIMEOUT_EVT: |
| 611 | tipc_link_send_proto_msg(l_ptr, RESET_MSG, 0, 0, 0, 0, 0); | 628 | tipc_link_proto_xmit(l_ptr, RESET_MSG, 0, 0, 0, 0, 0); |
| 612 | l_ptr->fsm_msg_cnt++; | 629 | l_ptr->fsm_msg_cnt++; |
| 613 | link_set_timer(l_ptr, cont_intv); | 630 | link_set_timer(l_ptr, cont_intv); |
| 614 | break; | 631 | break; |
| @@ -626,16 +643,17 @@ static void link_state_event(struct tipc_link *l_ptr, unsigned int event) | |||
| 626 | l_ptr->state = WORKING_WORKING; | 643 | l_ptr->state = WORKING_WORKING; |
| 627 | l_ptr->fsm_msg_cnt = 0; | 644 | l_ptr->fsm_msg_cnt = 0; |
| 628 | link_activate(l_ptr); | 645 | link_activate(l_ptr); |
| 629 | tipc_link_send_proto_msg(l_ptr, STATE_MSG, 1, 0, 0, 0, 0); | 646 | tipc_link_proto_xmit(l_ptr, STATE_MSG, 1, 0, 0, 0, 0); |
| 630 | l_ptr->fsm_msg_cnt++; | 647 | l_ptr->fsm_msg_cnt++; |
| 631 | if (l_ptr->owner->working_links == 1) | 648 | if (l_ptr->owner->working_links == 1) |
| 632 | tipc_link_send_sync(l_ptr); | 649 | tipc_link_sync_xmit(l_ptr); |
| 633 | link_set_timer(l_ptr, cont_intv); | 650 | link_set_timer(l_ptr, cont_intv); |
| 634 | break; | 651 | break; |
| 635 | case RESET_MSG: | 652 | case RESET_MSG: |
| 636 | break; | 653 | break; |
| 637 | case TIMEOUT_EVT: | 654 | case TIMEOUT_EVT: |
| 638 | tipc_link_send_proto_msg(l_ptr, ACTIVATE_MSG, 0, 0, 0, 0, 0); | 655 | tipc_link_proto_xmit(l_ptr, ACTIVATE_MSG, |
| 656 | 0, 0, 0, 0, 0); | ||
| 639 | l_ptr->fsm_msg_cnt++; | 657 | l_ptr->fsm_msg_cnt++; |
| 640 | link_set_timer(l_ptr, cont_intv); | 658 | link_set_timer(l_ptr, cont_intv); |
| 641 | break; | 659 | break; |
| @@ -721,11 +739,11 @@ static void link_add_chain_to_outqueue(struct tipc_link *l_ptr, | |||
| 721 | } | 739 | } |
| 722 | 740 | ||
| 723 | /* | 741 | /* |
| 724 | * tipc_link_send_buf() is the 'full path' for messages, called from | 742 | * tipc_link_xmit() is the 'full path' for messages, called from |
| 725 | * inside TIPC when the 'fast path' in tipc_send_buf | 743 | * inside TIPC when the 'fast path' in tipc_send_xmit |
| 726 | * has failed, and from link_send() | 744 | * has failed, and from link_send() |
| 727 | */ | 745 | */ |
| 728 | int tipc_link_send_buf(struct tipc_link *l_ptr, struct sk_buff *buf) | 746 | int __tipc_link_xmit(struct tipc_link *l_ptr, struct sk_buff *buf) |
| 729 | { | 747 | { |
| 730 | struct tipc_msg *msg = buf_msg(buf); | 748 | struct tipc_msg *msg = buf_msg(buf); |
| 731 | u32 size = msg_size(msg); | 749 | u32 size = msg_size(msg); |
| @@ -753,7 +771,7 @@ int tipc_link_send_buf(struct tipc_link *l_ptr, struct sk_buff *buf) | |||
| 753 | 771 | ||
| 754 | /* Fragmentation needed ? */ | 772 | /* Fragmentation needed ? */ |
| 755 | if (size > max_packet) | 773 | if (size > max_packet) |
| 756 | return link_send_long_buf(l_ptr, buf); | 774 | return tipc_link_frag_xmit(l_ptr, buf); |
| 757 | 775 | ||
| 758 | /* Packet can be queued or sent. */ | 776 | /* Packet can be queued or sent. */ |
| 759 | if (likely(!link_congested(l_ptr))) { | 777 | if (likely(!link_congested(l_ptr))) { |
| @@ -797,11 +815,11 @@ int tipc_link_send_buf(struct tipc_link *l_ptr, struct sk_buff *buf) | |||
| 797 | } | 815 | } |
| 798 | 816 | ||
| 799 | /* | 817 | /* |
| 800 | * tipc_link_send(): same as tipc_link_send_buf(), but the link to use has | 818 | * tipc_link_xmit(): same as __tipc_link_xmit(), but the link to use |
| 801 | * not been selected yet, and the the owner node is not locked | 819 | * has not been selected yet, and the the owner node is not locked |
| 802 | * Called by TIPC internal users, e.g. the name distributor | 820 | * Called by TIPC internal users, e.g. the name distributor |
| 803 | */ | 821 | */ |
| 804 | int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector) | 822 | int tipc_link_xmit(struct sk_buff *buf, u32 dest, u32 selector) |
| 805 | { | 823 | { |
| 806 | struct tipc_link *l_ptr; | 824 | struct tipc_link *l_ptr; |
| 807 | struct tipc_node *n_ptr; | 825 | struct tipc_node *n_ptr; |
| @@ -813,7 +831,7 @@ int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector) | |||
| 813 | tipc_node_lock(n_ptr); | 831 | tipc_node_lock(n_ptr); |
| 814 | l_ptr = n_ptr->active_links[selector & 1]; | 832 | l_ptr = n_ptr->active_links[selector & 1]; |
| 815 | if (l_ptr) | 833 | if (l_ptr) |
| 816 | res = tipc_link_send_buf(l_ptr, buf); | 834 | res = __tipc_link_xmit(l_ptr, buf); |
| 817 | else | 835 | else |
| 818 | kfree_skb(buf); | 836 | kfree_skb(buf); |
| 819 | tipc_node_unlock(n_ptr); | 837 | tipc_node_unlock(n_ptr); |
| @@ -825,14 +843,14 @@ int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector) | |||
| 825 | } | 843 | } |
| 826 | 844 | ||
| 827 | /* | 845 | /* |
| 828 | * tipc_link_send_sync - synchronize broadcast link endpoints. | 846 | * tipc_link_sync_xmit - synchronize broadcast link endpoints. |
| 829 | * | 847 | * |
| 830 | * Give a newly added peer node the sequence number where it should | 848 | * Give a newly added peer node the sequence number where it should |
| 831 | * start receiving and acking broadcast packets. | 849 | * start receiving and acking broadcast packets. |
| 832 | * | 850 | * |
| 833 | * Called with node locked | 851 | * Called with node locked |
| 834 | */ | 852 | */ |
| 835 | static void tipc_link_send_sync(struct tipc_link *l) | 853 | static void tipc_link_sync_xmit(struct tipc_link *l) |
| 836 | { | 854 | { |
| 837 | struct sk_buff *buf; | 855 | struct sk_buff *buf; |
| 838 | struct tipc_msg *msg; | 856 | struct tipc_msg *msg; |
| @@ -849,14 +867,14 @@ static void tipc_link_send_sync(struct tipc_link *l) | |||
| 849 | } | 867 | } |
| 850 | 868 | ||
| 851 | /* | 869 | /* |
| 852 | * tipc_link_recv_sync - synchronize broadcast link endpoints. | 870 | * tipc_link_sync_rcv - synchronize broadcast link endpoints. |
| 853 | * Receive the sequence number where we should start receiving and | 871 | * Receive the sequence number where we should start receiving and |
| 854 | * acking broadcast packets from a newly added peer node, and open | 872 | * acking broadcast packets from a newly added peer node, and open |
| 855 | * up for reception of such packets. | 873 | * up for reception of such packets. |
| 856 | * | 874 | * |
| 857 | * Called with node locked | 875 | * Called with node locked |
| 858 | */ | 876 | */ |
| 859 | static void tipc_link_recv_sync(struct tipc_node *n, struct sk_buff *buf) | 877 | static void tipc_link_sync_rcv(struct tipc_node *n, struct sk_buff *buf) |
| 860 | { | 878 | { |
| 861 | struct tipc_msg *msg = buf_msg(buf); | 879 | struct tipc_msg *msg = buf_msg(buf); |
| 862 | 880 | ||
| @@ -866,7 +884,7 @@ static void tipc_link_recv_sync(struct tipc_node *n, struct sk_buff *buf) | |||
| 866 | } | 884 | } |
| 867 | 885 | ||
| 868 | /* | 886 | /* |
| 869 | * tipc_link_send_names - send name table entries to new neighbor | 887 | * tipc_link_names_xmit - send name table entries to new neighbor |
| 870 | * | 888 | * |
| 871 | * Send routine for bulk delivery of name table messages when contact | 889 | * Send routine for bulk delivery of name table messages when contact |
| 872 | * with a new neighbor occurs. No link congestion checking is performed | 890 | * with a new neighbor occurs. No link congestion checking is performed |
| @@ -874,7 +892,7 @@ static void tipc_link_recv_sync(struct tipc_node *n, struct sk_buff *buf) | |||
| 874 | * small enough not to require fragmentation. | 892 | * small enough not to require fragmentation. |
| 875 | * Called without any locks held. | 893 | * Called without any locks held. |
| 876 | */ | 894 | */ |
| 877 | void tipc_link_send_names(struct list_head *message_list, u32 dest) | 895 | void tipc_link_names_xmit(struct list_head *message_list, u32 dest) |
| 878 | { | 896 | { |
| 879 | struct tipc_node *n_ptr; | 897 | struct tipc_node *n_ptr; |
| 880 | struct tipc_link *l_ptr; | 898 | struct tipc_link *l_ptr; |
| @@ -909,13 +927,13 @@ void tipc_link_send_names(struct list_head *message_list, u32 dest) | |||
| 909 | } | 927 | } |
| 910 | 928 | ||
| 911 | /* | 929 | /* |
| 912 | * link_send_buf_fast: Entry for data messages where the | 930 | * tipc_link_xmit_fast: Entry for data messages where the |
| 913 | * destination link is known and the header is complete, | 931 | * destination link is known and the header is complete, |
| 914 | * inclusive total message length. Very time critical. | 932 | * inclusive total message length. Very time critical. |
| 915 | * Link is locked. Returns user data length. | 933 | * Link is locked. Returns user data length. |
| 916 | */ | 934 | */ |
| 917 | static int link_send_buf_fast(struct tipc_link *l_ptr, struct sk_buff *buf, | 935 | static int tipc_link_xmit_fast(struct tipc_link *l_ptr, struct sk_buff *buf, |
| 918 | u32 *used_max_pkt) | 936 | u32 *used_max_pkt) |
| 919 | { | 937 | { |
| 920 | struct tipc_msg *msg = buf_msg(buf); | 938 | struct tipc_msg *msg = buf_msg(buf); |
| 921 | int res = msg_data_sz(msg); | 939 | int res = msg_data_sz(msg); |
| @@ -931,18 +949,18 @@ static int link_send_buf_fast(struct tipc_link *l_ptr, struct sk_buff *buf, | |||
| 931 | else | 949 | else |
| 932 | *used_max_pkt = l_ptr->max_pkt; | 950 | *used_max_pkt = l_ptr->max_pkt; |
| 933 | } | 951 | } |
| 934 | return tipc_link_send_buf(l_ptr, buf); /* All other cases */ | 952 | return __tipc_link_xmit(l_ptr, buf); /* All other cases */ |
| 935 | } | 953 | } |
| 936 | 954 | ||
| 937 | /* | 955 | /* |
| 938 | * tipc_link_send_sections_fast: Entry for messages where the | 956 | * tipc_link_iovec_xmit_fast: Entry for messages where the |
| 939 | * destination processor is known and the header is complete, | 957 | * destination processor is known and the header is complete, |
| 940 | * except for total message length. | 958 | * except for total message length. |
| 941 | * Returns user data length or errno. | 959 | * Returns user data length or errno. |
| 942 | */ | 960 | */ |
| 943 | int tipc_link_send_sections_fast(struct tipc_port *sender, | 961 | int tipc_link_iovec_xmit_fast(struct tipc_port *sender, |
| 944 | struct iovec const *msg_sect, | 962 | struct iovec const *msg_sect, |
| 945 | unsigned int len, u32 destaddr) | 963 | unsigned int len, u32 destaddr) |
| 946 | { | 964 | { |
| 947 | struct tipc_msg *hdr = &sender->phdr; | 965 | struct tipc_msg *hdr = &sender->phdr; |
| 948 | struct tipc_link *l_ptr; | 966 | struct tipc_link *l_ptr; |
| @@ -968,8 +986,8 @@ again: | |||
| 968 | l_ptr = node->active_links[selector]; | 986 | l_ptr = node->active_links[selector]; |
| 969 | if (likely(l_ptr)) { | 987 | if (likely(l_ptr)) { |
| 970 | if (likely(buf)) { | 988 | if (likely(buf)) { |
| 971 | res = link_send_buf_fast(l_ptr, buf, | 989 | res = tipc_link_xmit_fast(l_ptr, buf, |
| 972 | &sender->max_pkt); | 990 | &sender->max_pkt); |
| 973 | exit: | 991 | exit: |
| 974 | tipc_node_unlock(node); | 992 | tipc_node_unlock(node); |
| 975 | read_unlock_bh(&tipc_net_lock); | 993 | read_unlock_bh(&tipc_net_lock); |
| @@ -995,24 +1013,21 @@ exit: | |||
| 995 | if ((msg_hdr_sz(hdr) + res) <= sender->max_pkt) | 1013 | if ((msg_hdr_sz(hdr) + res) <= sender->max_pkt) |
| 996 | goto again; | 1014 | goto again; |
| 997 | 1015 | ||
| 998 | return link_send_sections_long(sender, msg_sect, len, | 1016 | return tipc_link_iovec_long_xmit(sender, msg_sect, |
| 999 | destaddr); | 1017 | len, destaddr); |
| 1000 | } | 1018 | } |
| 1001 | tipc_node_unlock(node); | 1019 | tipc_node_unlock(node); |
| 1002 | } | 1020 | } |
| 1003 | read_unlock_bh(&tipc_net_lock); | 1021 | read_unlock_bh(&tipc_net_lock); |
| 1004 | 1022 | ||
| 1005 | /* Couldn't find a link to the destination node */ | 1023 | /* Couldn't find a link to the destination node */ |
| 1006 | if (buf) | 1024 | kfree_skb(buf); |
| 1007 | return tipc_reject_msg(buf, TIPC_ERR_NO_NODE); | 1025 | tipc_port_iovec_reject(sender, hdr, msg_sect, len, TIPC_ERR_NO_NODE); |
| 1008 | if (res >= 0) | 1026 | return -ENETUNREACH; |
| 1009 | return tipc_port_reject_sections(sender, hdr, msg_sect, | ||
| 1010 | len, TIPC_ERR_NO_NODE); | ||
| 1011 | return res; | ||
| 1012 | } | 1027 | } |
| 1013 | 1028 | ||
| 1014 | /* | 1029 | /* |
| 1015 | * link_send_sections_long(): Entry for long messages where the | 1030 | * tipc_link_iovec_long_xmit(): Entry for long messages where the |
| 1016 | * destination node is known and the header is complete, | 1031 | * destination node is known and the header is complete, |
| 1017 | * inclusive total message length. | 1032 | * inclusive total message length. |
| 1018 | * Link and bearer congestion status have been checked to be ok, | 1033 | * Link and bearer congestion status have been checked to be ok, |
| @@ -1025,9 +1040,9 @@ exit: | |||
| 1025 | * | 1040 | * |
| 1026 | * Returns user data length or errno. | 1041 | * Returns user data length or errno. |
| 1027 | */ | 1042 | */ |
| 1028 | static int link_send_sections_long(struct tipc_port *sender, | 1043 | static int tipc_link_iovec_long_xmit(struct tipc_port *sender, |
| 1029 | struct iovec const *msg_sect, | 1044 | struct iovec const *msg_sect, |
| 1030 | unsigned int len, u32 destaddr) | 1045 | unsigned int len, u32 destaddr) |
| 1031 | { | 1046 | { |
| 1032 | struct tipc_link *l_ptr; | 1047 | struct tipc_link *l_ptr; |
| 1033 | struct tipc_node *node; | 1048 | struct tipc_node *node; |
| @@ -1146,8 +1161,9 @@ error: | |||
| 1146 | } else { | 1161 | } else { |
| 1147 | reject: | 1162 | reject: |
| 1148 | kfree_skb_list(buf_chain); | 1163 | kfree_skb_list(buf_chain); |
| 1149 | return tipc_port_reject_sections(sender, hdr, msg_sect, | 1164 | tipc_port_iovec_reject(sender, hdr, msg_sect, len, |
| 1150 | len, TIPC_ERR_NO_NODE); | 1165 | TIPC_ERR_NO_NODE); |
| 1166 | return -ENETUNREACH; | ||
| 1151 | } | 1167 | } |
| 1152 | 1168 | ||
| 1153 | /* Append chain of fragments to send queue & send them */ | 1169 | /* Append chain of fragments to send queue & send them */ |
| @@ -1441,15 +1457,10 @@ void tipc_rcv(struct sk_buff *head, struct tipc_bearer *b_ptr) | |||
| 1441 | u32 seq_no; | 1457 | u32 seq_no; |
| 1442 | u32 ackd; | 1458 | u32 ackd; |
| 1443 | u32 released = 0; | 1459 | u32 released = 0; |
| 1444 | int type; | ||
| 1445 | 1460 | ||
| 1446 | head = head->next; | 1461 | head = head->next; |
| 1447 | buf->next = NULL; | 1462 | buf->next = NULL; |
| 1448 | 1463 | ||
| 1449 | /* Ensure bearer is still enabled */ | ||
| 1450 | if (unlikely(!b_ptr->active)) | ||
| 1451 | goto discard; | ||
| 1452 | |||
| 1453 | /* Ensure message is well-formed */ | 1464 | /* Ensure message is well-formed */ |
| 1454 | if (unlikely(!link_recv_buf_validate(buf))) | 1465 | if (unlikely(!link_recv_buf_validate(buf))) |
| 1455 | goto discard; | 1466 | goto discard; |
| @@ -1463,9 +1474,9 @@ void tipc_rcv(struct sk_buff *head, struct tipc_bearer *b_ptr) | |||
| 1463 | 1474 | ||
| 1464 | if (unlikely(msg_non_seq(msg))) { | 1475 | if (unlikely(msg_non_seq(msg))) { |
| 1465 | if (msg_user(msg) == LINK_CONFIG) | 1476 | if (msg_user(msg) == LINK_CONFIG) |
| 1466 | tipc_disc_recv_msg(buf, b_ptr); | 1477 | tipc_disc_rcv(buf, b_ptr); |
| 1467 | else | 1478 | else |
| 1468 | tipc_bclink_recv_pkt(buf); | 1479 | tipc_bclink_rcv(buf); |
| 1469 | continue; | 1480 | continue; |
| 1470 | } | 1481 | } |
| 1471 | 1482 | ||
| @@ -1489,7 +1500,7 @@ void tipc_rcv(struct sk_buff *head, struct tipc_bearer *b_ptr) | |||
| 1489 | if ((n_ptr->block_setup & WAIT_PEER_DOWN) && | 1500 | if ((n_ptr->block_setup & WAIT_PEER_DOWN) && |
| 1490 | msg_user(msg) == LINK_PROTOCOL && | 1501 | msg_user(msg) == LINK_PROTOCOL && |
| 1491 | (msg_type(msg) == RESET_MSG || | 1502 | (msg_type(msg) == RESET_MSG || |
| 1492 | msg_type(msg) == ACTIVATE_MSG) && | 1503 | msg_type(msg) == ACTIVATE_MSG) && |
| 1493 | !msg_redundant_link(msg)) | 1504 | !msg_redundant_link(msg)) |
| 1494 | n_ptr->block_setup &= ~WAIT_PEER_DOWN; | 1505 | n_ptr->block_setup &= ~WAIT_PEER_DOWN; |
| 1495 | 1506 | ||
| @@ -1508,7 +1519,6 @@ void tipc_rcv(struct sk_buff *head, struct tipc_bearer *b_ptr) | |||
| 1508 | while ((crs != l_ptr->next_out) && | 1519 | while ((crs != l_ptr->next_out) && |
| 1509 | less_eq(buf_seqno(crs), ackd)) { | 1520 | less_eq(buf_seqno(crs), ackd)) { |
| 1510 | struct sk_buff *next = crs->next; | 1521 | struct sk_buff *next = crs->next; |
| 1511 | |||
| 1512 | kfree_skb(crs); | 1522 | kfree_skb(crs); |
| 1513 | crs = next; | 1523 | crs = next; |
| 1514 | released++; | 1524 | released++; |
| @@ -1521,18 +1531,19 @@ void tipc_rcv(struct sk_buff *head, struct tipc_bearer *b_ptr) | |||
| 1521 | /* Try sending any messages link endpoint has pending */ | 1531 | /* Try sending any messages link endpoint has pending */ |
| 1522 | if (unlikely(l_ptr->next_out)) | 1532 | if (unlikely(l_ptr->next_out)) |
| 1523 | tipc_link_push_queue(l_ptr); | 1533 | tipc_link_push_queue(l_ptr); |
| 1534 | |||
| 1524 | if (unlikely(!list_empty(&l_ptr->waiting_ports))) | 1535 | if (unlikely(!list_empty(&l_ptr->waiting_ports))) |
| 1525 | tipc_link_wakeup_ports(l_ptr, 0); | 1536 | tipc_link_wakeup_ports(l_ptr, 0); |
| 1537 | |||
| 1526 | if (unlikely(++l_ptr->unacked_window >= TIPC_MIN_LINK_WIN)) { | 1538 | if (unlikely(++l_ptr->unacked_window >= TIPC_MIN_LINK_WIN)) { |
| 1527 | l_ptr->stats.sent_acks++; | 1539 | l_ptr->stats.sent_acks++; |
| 1528 | tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); | 1540 | tipc_link_proto_xmit(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); |
| 1529 | } | 1541 | } |
| 1530 | 1542 | ||
| 1531 | /* Now (finally!) process the incoming message */ | 1543 | /* Process the incoming packet */ |
| 1532 | protocol_check: | ||
| 1533 | if (unlikely(!link_working_working(l_ptr))) { | 1544 | if (unlikely(!link_working_working(l_ptr))) { |
| 1534 | if (msg_user(msg) == LINK_PROTOCOL) { | 1545 | if (msg_user(msg) == LINK_PROTOCOL) { |
| 1535 | link_recv_proto_msg(l_ptr, buf); | 1546 | tipc_link_proto_rcv(l_ptr, buf); |
| 1536 | head = link_insert_deferred_queue(l_ptr, head); | 1547 | head = link_insert_deferred_queue(l_ptr, head); |
| 1537 | tipc_node_unlock(n_ptr); | 1548 | tipc_node_unlock(n_ptr); |
| 1538 | continue; | 1549 | continue; |
| @@ -1561,67 +1572,65 @@ protocol_check: | |||
| 1561 | l_ptr->next_in_no++; | 1572 | l_ptr->next_in_no++; |
| 1562 | if (unlikely(l_ptr->oldest_deferred_in)) | 1573 | if (unlikely(l_ptr->oldest_deferred_in)) |
| 1563 | head = link_insert_deferred_queue(l_ptr, head); | 1574 | head = link_insert_deferred_queue(l_ptr, head); |
| 1564 | deliver: | 1575 | |
| 1565 | if (likely(msg_isdata(msg))) { | 1576 | /* Deliver packet/message to correct user: */ |
| 1566 | tipc_node_unlock(n_ptr); | 1577 | if (unlikely(msg_user(msg) == CHANGEOVER_PROTOCOL)) { |
| 1567 | tipc_port_recv_msg(buf); | 1578 | if (!tipc_link_tunnel_rcv(n_ptr, &buf)) { |
| 1568 | continue; | 1579 | tipc_node_unlock(n_ptr); |
| 1580 | continue; | ||
| 1581 | } | ||
| 1582 | msg = buf_msg(buf); | ||
| 1583 | } else if (msg_user(msg) == MSG_FRAGMENTER) { | ||
| 1584 | int rc; | ||
| 1585 | |||
| 1586 | l_ptr->stats.recv_fragments++; | ||
| 1587 | rc = tipc_link_frag_rcv(&l_ptr->reasm_head, | ||
| 1588 | &l_ptr->reasm_tail, | ||
| 1589 | &buf); | ||
| 1590 | if (rc == LINK_REASM_COMPLETE) { | ||
| 1591 | l_ptr->stats.recv_fragmented++; | ||
| 1592 | msg = buf_msg(buf); | ||
| 1593 | } else { | ||
| 1594 | if (rc == LINK_REASM_ERROR) | ||
| 1595 | tipc_link_reset(l_ptr); | ||
| 1596 | tipc_node_unlock(n_ptr); | ||
| 1597 | continue; | ||
| 1598 | } | ||
| 1569 | } | 1599 | } |
| 1600 | |||
| 1570 | switch (msg_user(msg)) { | 1601 | switch (msg_user(msg)) { |
| 1571 | int ret; | 1602 | case TIPC_LOW_IMPORTANCE: |
| 1603 | case TIPC_MEDIUM_IMPORTANCE: | ||
| 1604 | case TIPC_HIGH_IMPORTANCE: | ||
| 1605 | case TIPC_CRITICAL_IMPORTANCE: | ||
| 1606 | tipc_node_unlock(n_ptr); | ||
| 1607 | tipc_port_rcv(buf); | ||
| 1608 | continue; | ||
| 1572 | case MSG_BUNDLER: | 1609 | case MSG_BUNDLER: |
| 1573 | l_ptr->stats.recv_bundles++; | 1610 | l_ptr->stats.recv_bundles++; |
| 1574 | l_ptr->stats.recv_bundled += msg_msgcnt(msg); | 1611 | l_ptr->stats.recv_bundled += msg_msgcnt(msg); |
| 1575 | tipc_node_unlock(n_ptr); | 1612 | tipc_node_unlock(n_ptr); |
| 1576 | tipc_link_recv_bundle(buf); | 1613 | tipc_link_bundle_rcv(buf); |
| 1577 | continue; | 1614 | continue; |
| 1578 | case NAME_DISTRIBUTOR: | 1615 | case NAME_DISTRIBUTOR: |
| 1579 | n_ptr->bclink.recv_permitted = true; | 1616 | n_ptr->bclink.recv_permitted = true; |
| 1580 | tipc_node_unlock(n_ptr); | 1617 | tipc_node_unlock(n_ptr); |
| 1581 | tipc_named_recv(buf); | 1618 | tipc_named_rcv(buf); |
| 1582 | continue; | ||
| 1583 | case BCAST_PROTOCOL: | ||
| 1584 | tipc_link_recv_sync(n_ptr, buf); | ||
| 1585 | tipc_node_unlock(n_ptr); | ||
| 1586 | continue; | 1619 | continue; |
| 1587 | case CONN_MANAGER: | 1620 | case CONN_MANAGER: |
| 1588 | tipc_node_unlock(n_ptr); | 1621 | tipc_node_unlock(n_ptr); |
| 1589 | tipc_port_recv_proto_msg(buf); | 1622 | tipc_port_proto_rcv(buf); |
| 1590 | continue; | 1623 | continue; |
| 1591 | case MSG_FRAGMENTER: | 1624 | case BCAST_PROTOCOL: |
| 1592 | l_ptr->stats.recv_fragments++; | 1625 | tipc_link_sync_rcv(n_ptr, buf); |
| 1593 | ret = tipc_link_recv_fragment(&l_ptr->reasm_head, | ||
| 1594 | &l_ptr->reasm_tail, | ||
| 1595 | &buf); | ||
| 1596 | if (ret == LINK_REASM_COMPLETE) { | ||
| 1597 | l_ptr->stats.recv_fragmented++; | ||
| 1598 | msg = buf_msg(buf); | ||
| 1599 | goto deliver; | ||
| 1600 | } | ||
| 1601 | if (ret == LINK_REASM_ERROR) | ||
| 1602 | tipc_link_reset(l_ptr); | ||
| 1603 | tipc_node_unlock(n_ptr); | ||
| 1604 | continue; | ||
| 1605 | case CHANGEOVER_PROTOCOL: | ||
| 1606 | type = msg_type(msg); | ||
| 1607 | if (tipc_link_tunnel_rcv(&l_ptr, &buf)) { | ||
| 1608 | msg = buf_msg(buf); | ||
| 1609 | seq_no = msg_seqno(msg); | ||
| 1610 | if (type == ORIGINAL_MSG) | ||
| 1611 | goto deliver; | ||
| 1612 | goto protocol_check; | ||
| 1613 | } | ||
| 1614 | break; | 1626 | break; |
| 1615 | default: | 1627 | default: |
| 1616 | kfree_skb(buf); | 1628 | kfree_skb(buf); |
| 1617 | buf = NULL; | ||
| 1618 | break; | 1629 | break; |
| 1619 | } | 1630 | } |
| 1620 | tipc_node_unlock(n_ptr); | 1631 | tipc_node_unlock(n_ptr); |
| 1621 | tipc_net_route_msg(buf); | ||
| 1622 | continue; | 1632 | continue; |
| 1623 | unlock_discard: | 1633 | unlock_discard: |
| 1624 | |||
| 1625 | tipc_node_unlock(n_ptr); | 1634 | tipc_node_unlock(n_ptr); |
| 1626 | discard: | 1635 | discard: |
| 1627 | kfree_skb(buf); | 1636 | kfree_skb(buf); |
| @@ -1688,7 +1697,7 @@ static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr, | |||
| 1688 | u32 seq_no = buf_seqno(buf); | 1697 | u32 seq_no = buf_seqno(buf); |
| 1689 | 1698 | ||
| 1690 | if (likely(msg_user(buf_msg(buf)) == LINK_PROTOCOL)) { | 1699 | if (likely(msg_user(buf_msg(buf)) == LINK_PROTOCOL)) { |
| 1691 | link_recv_proto_msg(l_ptr, buf); | 1700 | tipc_link_proto_rcv(l_ptr, buf); |
| 1692 | return; | 1701 | return; |
| 1693 | } | 1702 | } |
| 1694 | 1703 | ||
| @@ -1711,7 +1720,7 @@ static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr, | |||
| 1711 | l_ptr->stats.deferred_recv++; | 1720 | l_ptr->stats.deferred_recv++; |
| 1712 | TIPC_SKB_CB(buf)->deferred = true; | 1721 | TIPC_SKB_CB(buf)->deferred = true; |
| 1713 | if ((l_ptr->deferred_inqueue_sz % 16) == 1) | 1722 | if ((l_ptr->deferred_inqueue_sz % 16) == 1) |
| 1714 | tipc_link_send_proto_msg(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); | 1723 | tipc_link_proto_xmit(l_ptr, STATE_MSG, 0, 0, 0, 0, 0); |
| 1715 | } else | 1724 | } else |
| 1716 | l_ptr->stats.duplicates++; | 1725 | l_ptr->stats.duplicates++; |
| 1717 | } | 1726 | } |
| @@ -1719,9 +1728,8 @@ static void link_handle_out_of_seq_msg(struct tipc_link *l_ptr, | |||
| 1719 | /* | 1728 | /* |
| 1720 | * Send protocol message to the other endpoint. | 1729 | * Send protocol message to the other endpoint. |
| 1721 | */ | 1730 | */ |
| 1722 | void tipc_link_send_proto_msg(struct tipc_link *l_ptr, u32 msg_typ, | 1731 | void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int probe_msg, |
| 1723 | int probe_msg, u32 gap, u32 tolerance, | 1732 | u32 gap, u32 tolerance, u32 priority, u32 ack_mtu) |
| 1724 | u32 priority, u32 ack_mtu) | ||
| 1725 | { | 1733 | { |
| 1726 | struct sk_buff *buf = NULL; | 1734 | struct sk_buff *buf = NULL; |
| 1727 | struct tipc_msg *msg = l_ptr->pmsg; | 1735 | struct tipc_msg *msg = l_ptr->pmsg; |
| @@ -1820,7 +1828,7 @@ void tipc_link_send_proto_msg(struct tipc_link *l_ptr, u32 msg_typ, | |||
| 1820 | * Note that network plane id propagates through the network, and may | 1828 | * Note that network plane id propagates through the network, and may |
| 1821 | * change at any time. The node with lowest address rules | 1829 | * change at any time. The node with lowest address rules |
| 1822 | */ | 1830 | */ |
| 1823 | static void link_recv_proto_msg(struct tipc_link *l_ptr, struct sk_buff *buf) | 1831 | static void tipc_link_proto_rcv(struct tipc_link *l_ptr, struct sk_buff *buf) |
| 1824 | { | 1832 | { |
| 1825 | u32 rec_gap = 0; | 1833 | u32 rec_gap = 0; |
| 1826 | u32 max_pkt_info; | 1834 | u32 max_pkt_info; |
| @@ -1939,8 +1947,8 @@ static void link_recv_proto_msg(struct tipc_link *l_ptr, struct sk_buff *buf) | |||
| 1939 | msg_last_bcast(msg)); | 1947 | msg_last_bcast(msg)); |
| 1940 | 1948 | ||
| 1941 | if (rec_gap || (msg_probe(msg))) { | 1949 | if (rec_gap || (msg_probe(msg))) { |
| 1942 | tipc_link_send_proto_msg(l_ptr, STATE_MSG, | 1950 | tipc_link_proto_xmit(l_ptr, STATE_MSG, 0, rec_gap, 0, |
| 1943 | 0, rec_gap, 0, 0, max_pkt_ack); | 1951 | 0, max_pkt_ack); |
| 1944 | } | 1952 | } |
| 1945 | if (msg_seq_gap(msg)) { | 1953 | if (msg_seq_gap(msg)) { |
| 1946 | l_ptr->stats.recv_nacks++; | 1954 | l_ptr->stats.recv_nacks++; |
| @@ -1979,7 +1987,7 @@ static void tipc_link_tunnel_xmit(struct tipc_link *l_ptr, | |||
| 1979 | } | 1987 | } |
| 1980 | skb_copy_to_linear_data(buf, tunnel_hdr, INT_H_SIZE); | 1988 | skb_copy_to_linear_data(buf, tunnel_hdr, INT_H_SIZE); |
| 1981 | skb_copy_to_linear_data_offset(buf, INT_H_SIZE, msg, length); | 1989 | skb_copy_to_linear_data_offset(buf, INT_H_SIZE, msg, length); |
| 1982 | tipc_link_send_buf(tunnel, buf); | 1990 | __tipc_link_xmit(tunnel, buf); |
| 1983 | } | 1991 | } |
| 1984 | 1992 | ||
| 1985 | 1993 | ||
| @@ -2012,7 +2020,7 @@ void tipc_link_failover_send_queue(struct tipc_link *l_ptr) | |||
| 2012 | if (buf) { | 2020 | if (buf) { |
| 2013 | skb_copy_to_linear_data(buf, &tunnel_hdr, INT_H_SIZE); | 2021 | skb_copy_to_linear_data(buf, &tunnel_hdr, INT_H_SIZE); |
| 2014 | msg_set_size(&tunnel_hdr, INT_H_SIZE); | 2022 | msg_set_size(&tunnel_hdr, INT_H_SIZE); |
| 2015 | tipc_link_send_buf(tunnel, buf); | 2023 | __tipc_link_xmit(tunnel, buf); |
| 2016 | } else { | 2024 | } else { |
| 2017 | pr_warn("%sunable to send changeover msg\n", | 2025 | pr_warn("%sunable to send changeover msg\n", |
| 2018 | link_co_err); | 2026 | link_co_err); |
| @@ -2046,7 +2054,7 @@ void tipc_link_failover_send_queue(struct tipc_link *l_ptr) | |||
| 2046 | } | 2054 | } |
| 2047 | } | 2055 | } |
| 2048 | 2056 | ||
| 2049 | /* tipc_link_dup_send_queue(): A second link has become active. Tunnel a | 2057 | /* tipc_link_dup_queue_xmit(): A second link has become active. Tunnel a |
| 2050 | * duplicate of the first link's send queue via the new link. This way, we | 2058 | * duplicate of the first link's send queue via the new link. This way, we |
| 2051 | * are guaranteed that currently queued packets from a socket are delivered | 2059 | * are guaranteed that currently queued packets from a socket are delivered |
| 2052 | * before future traffic from the same socket, even if this is using the | 2060 | * before future traffic from the same socket, even if this is using the |
| @@ -2055,7 +2063,7 @@ void tipc_link_failover_send_queue(struct tipc_link *l_ptr) | |||
| 2055 | * and sequence order is preserved per sender/receiver socket pair. | 2063 | * and sequence order is preserved per sender/receiver socket pair. |
| 2056 | * Owner node is locked. | 2064 | * Owner node is locked. |
| 2057 | */ | 2065 | */ |
| 2058 | void tipc_link_dup_send_queue(struct tipc_link *l_ptr, | 2066 | void tipc_link_dup_queue_xmit(struct tipc_link *l_ptr, |
| 2059 | struct tipc_link *tunnel) | 2067 | struct tipc_link *tunnel) |
| 2060 | { | 2068 | { |
| 2061 | struct sk_buff *iter; | 2069 | struct sk_buff *iter; |
| @@ -2085,7 +2093,7 @@ void tipc_link_dup_send_queue(struct tipc_link *l_ptr, | |||
| 2085 | skb_copy_to_linear_data(outbuf, &tunnel_hdr, INT_H_SIZE); | 2093 | skb_copy_to_linear_data(outbuf, &tunnel_hdr, INT_H_SIZE); |
| 2086 | skb_copy_to_linear_data_offset(outbuf, INT_H_SIZE, iter->data, | 2094 | skb_copy_to_linear_data_offset(outbuf, INT_H_SIZE, iter->data, |
| 2087 | length); | 2095 | length); |
| 2088 | tipc_link_send_buf(tunnel, outbuf); | 2096 | __tipc_link_xmit(tunnel, outbuf); |
| 2089 | if (!tipc_link_is_up(l_ptr)) | 2097 | if (!tipc_link_is_up(l_ptr)) |
| 2090 | return; | 2098 | return; |
| 2091 | iter = iter->next; | 2099 | iter = iter->next; |
| @@ -2112,89 +2120,114 @@ static struct sk_buff *buf_extract(struct sk_buff *skb, u32 from_pos) | |||
| 2112 | return eb; | 2120 | return eb; |
| 2113 | } | 2121 | } |
| 2114 | 2122 | ||
| 2115 | /* tipc_link_tunnel_rcv(): Receive a tunneled packet, sent | 2123 | |
| 2116 | * via other link as result of a failover (ORIGINAL_MSG) or | 2124 | |
| 2117 | * a new active link (DUPLICATE_MSG). Failover packets are | 2125 | /* tipc_link_dup_rcv(): Receive a tunnelled DUPLICATE_MSG packet. |
| 2118 | * returned to the active link for delivery upwards. | 2126 | * Owner node is locked. |
| 2127 | */ | ||
| 2128 | static void tipc_link_dup_rcv(struct tipc_link *l_ptr, | ||
| 2129 | struct sk_buff *t_buf) | ||
| 2130 | { | ||
| 2131 | struct sk_buff *buf; | ||
| 2132 | |||
| 2133 | if (!tipc_link_is_up(l_ptr)) | ||
| 2134 | return; | ||
| 2135 | |||
| 2136 | buf = buf_extract(t_buf, INT_H_SIZE); | ||
| 2137 | if (buf == NULL) { | ||
| 2138 | pr_warn("%sfailed to extract inner dup pkt\n", link_co_err); | ||
| 2139 | return; | ||
| 2140 | } | ||
| 2141 | |||
| 2142 | /* Add buffer to deferred queue, if applicable: */ | ||
| 2143 | link_handle_out_of_seq_msg(l_ptr, buf); | ||
| 2144 | } | ||
| 2145 | |||
| 2146 | /* tipc_link_failover_rcv(): Receive a tunnelled ORIGINAL_MSG packet | ||
| 2119 | * Owner node is locked. | 2147 | * Owner node is locked. |
| 2120 | */ | 2148 | */ |
| 2121 | static int tipc_link_tunnel_rcv(struct tipc_link **l_ptr, | 2149 | static struct sk_buff *tipc_link_failover_rcv(struct tipc_link *l_ptr, |
| 2122 | struct sk_buff **buf) | 2150 | struct sk_buff *t_buf) |
| 2123 | { | 2151 | { |
| 2124 | struct sk_buff *tunnel_buf = *buf; | 2152 | struct tipc_msg *t_msg = buf_msg(t_buf); |
| 2125 | struct tipc_link *dest_link; | 2153 | struct sk_buff *buf = NULL; |
| 2126 | struct tipc_msg *msg; | 2154 | struct tipc_msg *msg; |
| 2127 | struct tipc_msg *tunnel_msg = buf_msg(tunnel_buf); | ||
| 2128 | u32 msg_typ = msg_type(tunnel_msg); | ||
| 2129 | u32 msg_count = msg_msgcnt(tunnel_msg); | ||
| 2130 | u32 bearer_id = msg_bearer_id(tunnel_msg); | ||
| 2131 | 2155 | ||
| 2132 | if (bearer_id >= MAX_BEARERS) | 2156 | if (tipc_link_is_up(l_ptr)) |
| 2133 | goto exit; | 2157 | tipc_link_reset(l_ptr); |
| 2134 | dest_link = (*l_ptr)->owner->links[bearer_id]; | ||
| 2135 | if (!dest_link) | ||
| 2136 | goto exit; | ||
| 2137 | if (dest_link == *l_ptr) { | ||
| 2138 | pr_err("Unexpected changeover message on link <%s>\n", | ||
| 2139 | (*l_ptr)->name); | ||
| 2140 | goto exit; | ||
| 2141 | } | ||
| 2142 | *l_ptr = dest_link; | ||
| 2143 | msg = msg_get_wrapped(tunnel_msg); | ||
| 2144 | 2158 | ||
| 2145 | if (msg_typ == DUPLICATE_MSG) { | 2159 | /* First failover packet? */ |
| 2146 | if (less(msg_seqno(msg), mod(dest_link->next_in_no))) | 2160 | if (l_ptr->exp_msg_count == START_CHANGEOVER) |
| 2147 | goto exit; | 2161 | l_ptr->exp_msg_count = msg_msgcnt(t_msg); |
| 2148 | *buf = buf_extract(tunnel_buf, INT_H_SIZE); | 2162 | |
| 2149 | if (*buf == NULL) { | 2163 | /* Should there be an inner packet? */ |
| 2150 | pr_warn("%sduplicate msg dropped\n", link_co_err); | 2164 | if (l_ptr->exp_msg_count) { |
| 2165 | l_ptr->exp_msg_count--; | ||
| 2166 | buf = buf_extract(t_buf, INT_H_SIZE); | ||
| 2167 | if (buf == NULL) { | ||
| 2168 | pr_warn("%sno inner failover pkt\n", link_co_err); | ||
| 2151 | goto exit; | 2169 | goto exit; |
| 2152 | } | 2170 | } |
| 2153 | kfree_skb(tunnel_buf); | 2171 | msg = buf_msg(buf); |
| 2154 | return 1; | ||
| 2155 | } | ||
| 2156 | 2172 | ||
| 2157 | /* First original message ?: */ | 2173 | if (less(msg_seqno(msg), l_ptr->reset_checkpoint)) { |
| 2158 | if (tipc_link_is_up(dest_link)) { | 2174 | kfree_skb(buf); |
| 2159 | pr_info("%s<%s>, changeover initiated by peer\n", link_rst_msg, | 2175 | buf = NULL; |
| 2160 | dest_link->name); | ||
| 2161 | tipc_link_reset(dest_link); | ||
| 2162 | dest_link->exp_msg_count = msg_count; | ||
| 2163 | if (!msg_count) | ||
| 2164 | goto exit; | ||
| 2165 | } else if (dest_link->exp_msg_count == START_CHANGEOVER) { | ||
| 2166 | dest_link->exp_msg_count = msg_count; | ||
| 2167 | if (!msg_count) | ||
| 2168 | goto exit; | 2176 | goto exit; |
| 2177 | } | ||
| 2178 | if (msg_user(msg) == MSG_FRAGMENTER) { | ||
| 2179 | l_ptr->stats.recv_fragments++; | ||
| 2180 | tipc_link_frag_rcv(&l_ptr->reasm_head, | ||
| 2181 | &l_ptr->reasm_tail, | ||
| 2182 | &buf); | ||
| 2183 | } | ||
| 2184 | } | ||
| 2185 | exit: | ||
| 2186 | if ((l_ptr->exp_msg_count == 0) && (l_ptr->flags & LINK_STOPPED)) { | ||
| 2187 | tipc_node_detach_link(l_ptr->owner, l_ptr); | ||
| 2188 | kfree(l_ptr); | ||
| 2169 | } | 2189 | } |
| 2190 | return buf; | ||
| 2191 | } | ||
| 2170 | 2192 | ||
| 2171 | /* Receive original message */ | 2193 | /* tipc_link_tunnel_rcv(): Receive a tunnelled packet, sent |
| 2172 | if (dest_link->exp_msg_count == 0) { | 2194 | * via other link as result of a failover (ORIGINAL_MSG) or |
| 2173 | pr_warn("%sgot too many tunnelled messages\n", link_co_err); | 2195 | * a new active link (DUPLICATE_MSG). Failover packets are |
| 2196 | * returned to the active link for delivery upwards. | ||
| 2197 | * Owner node is locked. | ||
| 2198 | */ | ||
| 2199 | static int tipc_link_tunnel_rcv(struct tipc_node *n_ptr, | ||
| 2200 | struct sk_buff **buf) | ||
| 2201 | { | ||
| 2202 | struct sk_buff *t_buf = *buf; | ||
| 2203 | struct tipc_link *l_ptr; | ||
| 2204 | struct tipc_msg *t_msg = buf_msg(t_buf); | ||
| 2205 | u32 bearer_id = msg_bearer_id(t_msg); | ||
| 2206 | |||
| 2207 | *buf = NULL; | ||
| 2208 | |||
| 2209 | if (bearer_id >= MAX_BEARERS) | ||
| 2174 | goto exit; | 2210 | goto exit; |
| 2175 | } | 2211 | |
| 2176 | dest_link->exp_msg_count--; | 2212 | l_ptr = n_ptr->links[bearer_id]; |
| 2177 | if (less(msg_seqno(msg), dest_link->reset_checkpoint)) { | 2213 | if (!l_ptr) |
| 2178 | goto exit; | 2214 | goto exit; |
| 2179 | } else { | 2215 | |
| 2180 | *buf = buf_extract(tunnel_buf, INT_H_SIZE); | 2216 | if (msg_type(t_msg) == DUPLICATE_MSG) |
| 2181 | if (*buf != NULL) { | 2217 | tipc_link_dup_rcv(l_ptr, t_buf); |
| 2182 | kfree_skb(tunnel_buf); | 2218 | else if (msg_type(t_msg) == ORIGINAL_MSG) |
| 2183 | return 1; | 2219 | *buf = tipc_link_failover_rcv(l_ptr, t_buf); |
| 2184 | } else { | 2220 | else |
| 2185 | pr_warn("%soriginal msg dropped\n", link_co_err); | 2221 | pr_warn("%sunknown tunnel pkt received\n", link_co_err); |
| 2186 | } | ||
| 2187 | } | ||
| 2188 | exit: | 2222 | exit: |
| 2189 | *buf = NULL; | 2223 | kfree_skb(t_buf); |
| 2190 | kfree_skb(tunnel_buf); | 2224 | return *buf != NULL; |
| 2191 | return 0; | ||
| 2192 | } | 2225 | } |
| 2193 | 2226 | ||
| 2194 | /* | 2227 | /* |
| 2195 | * Bundler functionality: | 2228 | * Bundler functionality: |
| 2196 | */ | 2229 | */ |
| 2197 | void tipc_link_recv_bundle(struct sk_buff *buf) | 2230 | void tipc_link_bundle_rcv(struct sk_buff *buf) |
| 2198 | { | 2231 | { |
| 2199 | u32 msgcount = msg_msgcnt(buf_msg(buf)); | 2232 | u32 msgcount = msg_msgcnt(buf_msg(buf)); |
| 2200 | u32 pos = INT_H_SIZE; | 2233 | u32 pos = INT_H_SIZE; |
| @@ -2217,11 +2250,11 @@ void tipc_link_recv_bundle(struct sk_buff *buf) | |||
| 2217 | */ | 2250 | */ |
| 2218 | 2251 | ||
| 2219 | /* | 2252 | /* |
| 2220 | * link_send_long_buf: Entry for buffers needing fragmentation. | 2253 | * tipc_link_frag_xmit: Entry for buffers needing fragmentation. |
| 2221 | * The buffer is complete, inclusive total message length. | 2254 | * The buffer is complete, inclusive total message length. |
| 2222 | * Returns user data length. | 2255 | * Returns user data length. |
| 2223 | */ | 2256 | */ |
| 2224 | static int link_send_long_buf(struct tipc_link *l_ptr, struct sk_buff *buf) | 2257 | static int tipc_link_frag_xmit(struct tipc_link *l_ptr, struct sk_buff *buf) |
| 2225 | { | 2258 | { |
| 2226 | struct sk_buff *buf_chain = NULL; | 2259 | struct sk_buff *buf_chain = NULL; |
| 2227 | struct sk_buff *buf_chain_tail = (struct sk_buff *)&buf_chain; | 2260 | struct sk_buff *buf_chain_tail = (struct sk_buff *)&buf_chain; |
| @@ -2284,12 +2317,11 @@ static int link_send_long_buf(struct tipc_link *l_ptr, struct sk_buff *buf) | |||
| 2284 | return dsz; | 2317 | return dsz; |
| 2285 | } | 2318 | } |
| 2286 | 2319 | ||
| 2287 | /* | 2320 | /* tipc_link_frag_rcv(): Called with node lock on. Returns |
| 2288 | * tipc_link_recv_fragment(): Called with node lock on. Returns | ||
| 2289 | * the reassembled buffer if message is complete. | 2321 | * the reassembled buffer if message is complete. |
| 2290 | */ | 2322 | */ |
| 2291 | int tipc_link_recv_fragment(struct sk_buff **head, struct sk_buff **tail, | 2323 | int tipc_link_frag_rcv(struct sk_buff **head, struct sk_buff **tail, |
| 2292 | struct sk_buff **fbuf) | 2324 | struct sk_buff **fbuf) |
| 2293 | { | 2325 | { |
| 2294 | struct sk_buff *frag = *fbuf; | 2326 | struct sk_buff *frag = *fbuf; |
| 2295 | struct tipc_msg *msg = buf_msg(frag); | 2327 | struct tipc_msg *msg = buf_msg(frag); |
| @@ -2303,6 +2335,7 @@ int tipc_link_recv_fragment(struct sk_buff **head, struct sk_buff **tail, | |||
| 2303 | goto out_free; | 2335 | goto out_free; |
| 2304 | *head = frag; | 2336 | *head = frag; |
| 2305 | skb_frag_list_init(*head); | 2337 | skb_frag_list_init(*head); |
| 2338 | *fbuf = NULL; | ||
| 2306 | return 0; | 2339 | return 0; |
| 2307 | } else if (*head && | 2340 | } else if (*head && |
| 2308 | skb_try_coalesce(*head, frag, &headstolen, &delta)) { | 2341 | skb_try_coalesce(*head, frag, &headstolen, &delta)) { |
| @@ -2322,10 +2355,12 @@ int tipc_link_recv_fragment(struct sk_buff **head, struct sk_buff **tail, | |||
| 2322 | *tail = *head = NULL; | 2355 | *tail = *head = NULL; |
| 2323 | return LINK_REASM_COMPLETE; | 2356 | return LINK_REASM_COMPLETE; |
| 2324 | } | 2357 | } |
| 2358 | *fbuf = NULL; | ||
| 2325 | return 0; | 2359 | return 0; |
| 2326 | out_free: | 2360 | out_free: |
| 2327 | pr_warn_ratelimited("Link unable to reassemble fragmented message\n"); | 2361 | pr_warn_ratelimited("Link unable to reassemble fragmented message\n"); |
| 2328 | kfree_skb(*fbuf); | 2362 | kfree_skb(*fbuf); |
| 2363 | *fbuf = NULL; | ||
| 2329 | return LINK_REASM_ERROR; | 2364 | return LINK_REASM_ERROR; |
| 2330 | } | 2365 | } |
| 2331 | 2366 | ||
| @@ -2359,35 +2394,41 @@ void tipc_link_set_queue_limits(struct tipc_link *l_ptr, u32 window) | |||
| 2359 | l_ptr->queue_limit[MSG_FRAGMENTER] = 4000; | 2394 | l_ptr->queue_limit[MSG_FRAGMENTER] = 4000; |
| 2360 | } | 2395 | } |
| 2361 | 2396 | ||
| 2362 | /** | 2397 | /* tipc_link_find_owner - locate owner node of link by link's name |
| 2363 | * link_find_link - locate link by name | 2398 | * @name: pointer to link name string |
| 2364 | * @name: ptr to link name string | 2399 | * @bearer_id: pointer to index in 'node->links' array where the link was found. |
| 2365 | * @node: ptr to area to be filled with ptr to associated node | ||
| 2366 | * | ||
| 2367 | * Caller must hold 'tipc_net_lock' to ensure node and bearer are not deleted; | 2400 | * Caller must hold 'tipc_net_lock' to ensure node and bearer are not deleted; |
| 2368 | * this also prevents link deletion. | 2401 | * this also prevents link deletion. |
| 2369 | * | 2402 | * |
| 2370 | * Returns pointer to link (or 0 if invalid link name). | 2403 | * Returns pointer to node owning the link, or 0 if no matching link is found. |
| 2371 | */ | 2404 | */ |
| 2372 | static struct tipc_link *link_find_link(const char *name, | 2405 | static struct tipc_node *tipc_link_find_owner(const char *link_name, |
| 2373 | struct tipc_node **node) | 2406 | unsigned int *bearer_id) |
| 2374 | { | 2407 | { |
| 2375 | struct tipc_link *l_ptr; | 2408 | struct tipc_link *l_ptr; |
| 2376 | struct tipc_node *n_ptr; | 2409 | struct tipc_node *n_ptr; |
| 2410 | struct tipc_node *found_node = 0; | ||
| 2377 | int i; | 2411 | int i; |
| 2378 | 2412 | ||
| 2379 | list_for_each_entry(n_ptr, &tipc_node_list, list) { | 2413 | *bearer_id = 0; |
| 2414 | rcu_read_lock(); | ||
| 2415 | list_for_each_entry_rcu(n_ptr, &tipc_node_list, list) { | ||
| 2416 | tipc_node_lock(n_ptr); | ||
| 2380 | for (i = 0; i < MAX_BEARERS; i++) { | 2417 | for (i = 0; i < MAX_BEARERS; i++) { |
| 2381 | l_ptr = n_ptr->links[i]; | 2418 | l_ptr = n_ptr->links[i]; |
| 2382 | if (l_ptr && !strcmp(l_ptr->name, name)) | 2419 | if (l_ptr && !strcmp(l_ptr->name, link_name)) { |
| 2383 | goto found; | 2420 | *bearer_id = i; |
| 2421 | found_node = n_ptr; | ||
| 2422 | break; | ||
| 2423 | } | ||
| 2384 | } | 2424 | } |
| 2425 | tipc_node_unlock(n_ptr); | ||
| 2426 | if (found_node) | ||
| 2427 | break; | ||
| 2385 | } | 2428 | } |
| 2386 | l_ptr = NULL; | 2429 | rcu_read_unlock(); |
| 2387 | n_ptr = NULL; | 2430 | |
| 2388 | found: | 2431 | return found_node; |
| 2389 | *node = n_ptr; | ||
| 2390 | return l_ptr; | ||
| 2391 | } | 2432 | } |
| 2392 | 2433 | ||
| 2393 | /** | 2434 | /** |
| @@ -2429,32 +2470,33 @@ static int link_cmd_set_value(const char *name, u32 new_value, u16 cmd) | |||
| 2429 | struct tipc_link *l_ptr; | 2470 | struct tipc_link *l_ptr; |
| 2430 | struct tipc_bearer *b_ptr; | 2471 | struct tipc_bearer *b_ptr; |
| 2431 | struct tipc_media *m_ptr; | 2472 | struct tipc_media *m_ptr; |
| 2473 | int bearer_id; | ||
| 2432 | int res = 0; | 2474 | int res = 0; |
| 2433 | 2475 | ||
| 2434 | l_ptr = link_find_link(name, &node); | 2476 | node = tipc_link_find_owner(name, &bearer_id); |
| 2435 | if (l_ptr) { | 2477 | if (node) { |
| 2436 | /* | ||
| 2437 | * acquire node lock for tipc_link_send_proto_msg(). | ||
| 2438 | * see "TIPC locking policy" in net.c. | ||
| 2439 | */ | ||
| 2440 | tipc_node_lock(node); | 2478 | tipc_node_lock(node); |
| 2441 | switch (cmd) { | 2479 | l_ptr = node->links[bearer_id]; |
| 2442 | case TIPC_CMD_SET_LINK_TOL: | 2480 | |
| 2443 | link_set_supervision_props(l_ptr, new_value); | 2481 | if (l_ptr) { |
| 2444 | tipc_link_send_proto_msg(l_ptr, | 2482 | switch (cmd) { |
| 2445 | STATE_MSG, 0, 0, new_value, 0, 0); | 2483 | case TIPC_CMD_SET_LINK_TOL: |
| 2446 | break; | 2484 | link_set_supervision_props(l_ptr, new_value); |
| 2447 | case TIPC_CMD_SET_LINK_PRI: | 2485 | tipc_link_proto_xmit(l_ptr, STATE_MSG, 0, 0, |
| 2448 | l_ptr->priority = new_value; | 2486 | new_value, 0, 0); |
| 2449 | tipc_link_send_proto_msg(l_ptr, | 2487 | break; |
| 2450 | STATE_MSG, 0, 0, 0, new_value, 0); | 2488 | case TIPC_CMD_SET_LINK_PRI: |
| 2451 | break; | 2489 | l_ptr->priority = new_value; |
| 2452 | case TIPC_CMD_SET_LINK_WINDOW: | 2490 | tipc_link_proto_xmit(l_ptr, STATE_MSG, 0, 0, |
| 2453 | tipc_link_set_queue_limits(l_ptr, new_value); | 2491 | 0, new_value, 0); |
| 2454 | break; | 2492 | break; |
| 2455 | default: | 2493 | case TIPC_CMD_SET_LINK_WINDOW: |
| 2456 | res = -EINVAL; | 2494 | tipc_link_set_queue_limits(l_ptr, new_value); |
| 2457 | break; | 2495 | break; |
| 2496 | default: | ||
| 2497 | res = -EINVAL; | ||
| 2498 | break; | ||
| 2499 | } | ||
| 2458 | } | 2500 | } |
| 2459 | tipc_node_unlock(node); | 2501 | tipc_node_unlock(node); |
| 2460 | return res; | 2502 | return res; |
| @@ -2549,6 +2591,7 @@ struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_ | |||
| 2549 | char *link_name; | 2591 | char *link_name; |
| 2550 | struct tipc_link *l_ptr; | 2592 | struct tipc_link *l_ptr; |
| 2551 | struct tipc_node *node; | 2593 | struct tipc_node *node; |
| 2594 | unsigned int bearer_id; | ||
| 2552 | 2595 | ||
| 2553 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME)) | 2596 | if (!TLV_CHECK(req_tlv_area, req_tlv_space, TIPC_TLV_LINK_NAME)) |
| 2554 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); | 2597 | return tipc_cfg_reply_error_string(TIPC_CFG_TLV_ERROR); |
| @@ -2559,15 +2602,19 @@ struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area, int req_tlv_ | |||
| 2559 | return tipc_cfg_reply_error_string("link not found"); | 2602 | return tipc_cfg_reply_error_string("link not found"); |
| 2560 | return tipc_cfg_reply_none(); | 2603 | return tipc_cfg_reply_none(); |
| 2561 | } | 2604 | } |
| 2562 | |||
| 2563 | read_lock_bh(&tipc_net_lock); | 2605 | read_lock_bh(&tipc_net_lock); |
| 2564 | l_ptr = link_find_link(link_name, &node); | 2606 | node = tipc_link_find_owner(link_name, &bearer_id); |
| 2565 | if (!l_ptr) { | 2607 | if (!node) { |
| 2566 | read_unlock_bh(&tipc_net_lock); | 2608 | read_unlock_bh(&tipc_net_lock); |
| 2567 | return tipc_cfg_reply_error_string("link not found"); | 2609 | return tipc_cfg_reply_error_string("link not found"); |
| 2568 | } | 2610 | } |
| 2569 | |||
| 2570 | tipc_node_lock(node); | 2611 | tipc_node_lock(node); |
| 2612 | l_ptr = node->links[bearer_id]; | ||
| 2613 | if (!l_ptr) { | ||
| 2614 | tipc_node_unlock(node); | ||
| 2615 | read_unlock_bh(&tipc_net_lock); | ||
| 2616 | return tipc_cfg_reply_error_string("link not found"); | ||
| 2617 | } | ||
| 2571 | link_reset_statistics(l_ptr); | 2618 | link_reset_statistics(l_ptr); |
| 2572 | tipc_node_unlock(node); | 2619 | tipc_node_unlock(node); |
| 2573 | read_unlock_bh(&tipc_net_lock); | 2620 | read_unlock_bh(&tipc_net_lock); |
| @@ -2597,18 +2644,27 @@ static int tipc_link_stats(const char *name, char *buf, const u32 buf_size) | |||
| 2597 | struct tipc_node *node; | 2644 | struct tipc_node *node; |
| 2598 | char *status; | 2645 | char *status; |
| 2599 | u32 profile_total = 0; | 2646 | u32 profile_total = 0; |
| 2647 | unsigned int bearer_id; | ||
| 2600 | int ret; | 2648 | int ret; |
| 2601 | 2649 | ||
| 2602 | if (!strcmp(name, tipc_bclink_name)) | 2650 | if (!strcmp(name, tipc_bclink_name)) |
| 2603 | return tipc_bclink_stats(buf, buf_size); | 2651 | return tipc_bclink_stats(buf, buf_size); |
| 2604 | 2652 | ||
| 2605 | read_lock_bh(&tipc_net_lock); | 2653 | read_lock_bh(&tipc_net_lock); |
| 2606 | l = link_find_link(name, &node); | 2654 | node = tipc_link_find_owner(name, &bearer_id); |
| 2607 | if (!l) { | 2655 | if (!node) { |
| 2608 | read_unlock_bh(&tipc_net_lock); | 2656 | read_unlock_bh(&tipc_net_lock); |
| 2609 | return 0; | 2657 | return 0; |
| 2610 | } | 2658 | } |
| 2611 | tipc_node_lock(node); | 2659 | tipc_node_lock(node); |
| 2660 | |||
| 2661 | l = node->links[bearer_id]; | ||
| 2662 | if (!l) { | ||
| 2663 | tipc_node_unlock(node); | ||
| 2664 | read_unlock_bh(&tipc_net_lock); | ||
| 2665 | return 0; | ||
| 2666 | } | ||
| 2667 | |||
| 2612 | s = &l->stats; | 2668 | s = &l->stats; |
| 2613 | 2669 | ||
| 2614 | if (tipc_link_is_active(l)) | 2670 | if (tipc_link_is_active(l)) |
diff --git a/net/tipc/link.h b/net/tipc/link.h index 3b6aa65b608c..8c0b49b5b2ee 100644 --- a/net/tipc/link.h +++ b/net/tipc/link.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * net/tipc/link.h: Include file for TIPC link code | 2 | * net/tipc/link.h: Include file for TIPC link code |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 1995-2006, Ericsson AB | 4 | * Copyright (c) 1995-2006, 2013, Ericsson AB |
| 5 | * Copyright (c) 2004-2005, 2010-2011, Wind River Systems | 5 | * Copyright (c) 2004-2005, 2010-2011, Wind River Systems |
| 6 | * All rights reserved. | 6 | * All rights reserved. |
| 7 | * | 7 | * |
| @@ -40,27 +40,28 @@ | |||
| 40 | #include "msg.h" | 40 | #include "msg.h" |
| 41 | #include "node.h" | 41 | #include "node.h" |
| 42 | 42 | ||
| 43 | /* | 43 | /* Link reassembly status codes |
| 44 | * Link reassembly status codes | ||
| 45 | */ | 44 | */ |
| 46 | #define LINK_REASM_ERROR -1 | 45 | #define LINK_REASM_ERROR -1 |
| 47 | #define LINK_REASM_COMPLETE 1 | 46 | #define LINK_REASM_COMPLETE 1 |
| 48 | 47 | ||
| 49 | /* | 48 | /* Out-of-range value for link sequence numbers |
| 50 | * Out-of-range value for link sequence numbers | ||
| 51 | */ | 49 | */ |
| 52 | #define INVALID_LINK_SEQ 0x10000 | 50 | #define INVALID_LINK_SEQ 0x10000 |
| 53 | 51 | ||
| 54 | /* | 52 | /* Link working states |
| 55 | * Link states | ||
| 56 | */ | 53 | */ |
| 57 | #define WORKING_WORKING 560810u | 54 | #define WORKING_WORKING 560810u |
| 58 | #define WORKING_UNKNOWN 560811u | 55 | #define WORKING_UNKNOWN 560811u |
| 59 | #define RESET_UNKNOWN 560812u | 56 | #define RESET_UNKNOWN 560812u |
| 60 | #define RESET_RESET 560813u | 57 | #define RESET_RESET 560813u |
| 61 | 58 | ||
| 62 | /* | 59 | /* Link endpoint execution states |
| 63 | * Starting value for maximum packet size negotiation on unicast links | 60 | */ |
| 61 | #define LINK_STARTED 0x0001 | ||
| 62 | #define LINK_STOPPED 0x0002 | ||
| 63 | |||
| 64 | /* Starting value for maximum packet size negotiation on unicast links | ||
| 64 | * (unless bearer MTU is less) | 65 | * (unless bearer MTU is less) |
| 65 | */ | 66 | */ |
| 66 | #define MAX_PKT_DEFAULT 1500 | 67 | #define MAX_PKT_DEFAULT 1500 |
| @@ -102,8 +103,7 @@ struct tipc_stats { | |||
| 102 | * @media_addr: media address to use when sending messages over link | 103 | * @media_addr: media address to use when sending messages over link |
| 103 | * @timer: link timer | 104 | * @timer: link timer |
| 104 | * @owner: pointer to peer node | 105 | * @owner: pointer to peer node |
| 105 | * @link_list: adjacent links in bearer's list of links | 106 | * @flags: execution state flags for link endpoint instance |
| 106 | * @started: indicates if link has been started | ||
| 107 | * @checkpoint: reference point for triggering link continuity checking | 107 | * @checkpoint: reference point for triggering link continuity checking |
| 108 | * @peer_session: link session # being used by peer end of link | 108 | * @peer_session: link session # being used by peer end of link |
| 109 | * @peer_bearer_id: bearer id used by link's peer endpoint | 109 | * @peer_bearer_id: bearer id used by link's peer endpoint |
| @@ -149,10 +149,9 @@ struct tipc_link { | |||
| 149 | struct tipc_media_addr media_addr; | 149 | struct tipc_media_addr media_addr; |
| 150 | struct timer_list timer; | 150 | struct timer_list timer; |
| 151 | struct tipc_node *owner; | 151 | struct tipc_node *owner; |
| 152 | struct list_head link_list; | ||
| 153 | 152 | ||
| 154 | /* Management and link supervision data */ | 153 | /* Management and link supervision data */ |
| 155 | int started; | 154 | unsigned int flags; |
| 156 | u32 checkpoint; | 155 | u32 checkpoint; |
| 157 | u32 peer_session; | 156 | u32 peer_session; |
| 158 | u32 peer_bearer_id; | 157 | u32 peer_bearer_id; |
| @@ -215,10 +214,9 @@ struct tipc_port; | |||
| 215 | struct tipc_link *tipc_link_create(struct tipc_node *n_ptr, | 214 | struct tipc_link *tipc_link_create(struct tipc_node *n_ptr, |
| 216 | struct tipc_bearer *b_ptr, | 215 | struct tipc_bearer *b_ptr, |
| 217 | const struct tipc_media_addr *media_addr); | 216 | const struct tipc_media_addr *media_addr); |
| 218 | void tipc_link_delete(struct tipc_link *l_ptr); | 217 | void tipc_link_delete_list(unsigned int bearer_id, bool shutting_down); |
| 219 | void tipc_link_failover_send_queue(struct tipc_link *l_ptr); | 218 | void tipc_link_failover_send_queue(struct tipc_link *l_ptr); |
| 220 | void tipc_link_dup_send_queue(struct tipc_link *l_ptr, | 219 | void tipc_link_dup_queue_xmit(struct tipc_link *l_ptr, struct tipc_link *dest); |
| 221 | struct tipc_link *dest); | ||
| 222 | void tipc_link_reset_fragments(struct tipc_link *l_ptr); | 220 | void tipc_link_reset_fragments(struct tipc_link *l_ptr); |
| 223 | int tipc_link_is_up(struct tipc_link *l_ptr); | 221 | int tipc_link_is_up(struct tipc_link *l_ptr); |
| 224 | int tipc_link_is_active(struct tipc_link *l_ptr); | 222 | int tipc_link_is_active(struct tipc_link *l_ptr); |
| @@ -231,23 +229,24 @@ struct sk_buff *tipc_link_cmd_show_stats(const void *req_tlv_area, | |||
| 231 | struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area, | 229 | struct sk_buff *tipc_link_cmd_reset_stats(const void *req_tlv_area, |
| 232 | int req_tlv_space); | 230 | int req_tlv_space); |
| 233 | void tipc_link_reset(struct tipc_link *l_ptr); | 231 | void tipc_link_reset(struct tipc_link *l_ptr); |
| 234 | int tipc_link_send(struct sk_buff *buf, u32 dest, u32 selector); | 232 | void tipc_link_reset_list(unsigned int bearer_id); |
| 235 | void tipc_link_send_names(struct list_head *message_list, u32 dest); | 233 | int tipc_link_xmit(struct sk_buff *buf, u32 dest, u32 selector); |
| 234 | void tipc_link_names_xmit(struct list_head *message_list, u32 dest); | ||
| 235 | int __tipc_link_xmit(struct tipc_link *l_ptr, struct sk_buff *buf); | ||
| 236 | int tipc_link_send_buf(struct tipc_link *l_ptr, struct sk_buff *buf); | 236 | int tipc_link_send_buf(struct tipc_link *l_ptr, struct sk_buff *buf); |
| 237 | u32 tipc_link_get_max_pkt(u32 dest, u32 selector); | 237 | u32 tipc_link_get_max_pkt(u32 dest, u32 selector); |
| 238 | int tipc_link_send_sections_fast(struct tipc_port *sender, | 238 | int tipc_link_iovec_xmit_fast(struct tipc_port *sender, |
| 239 | struct iovec const *msg_sect, | 239 | struct iovec const *msg_sect, |
| 240 | unsigned int len, u32 destnode); | 240 | unsigned int len, u32 destnode); |
| 241 | void tipc_link_recv_bundle(struct sk_buff *buf); | 241 | void tipc_link_bundle_rcv(struct sk_buff *buf); |
| 242 | int tipc_link_recv_fragment(struct sk_buff **reasm_head, | 242 | int tipc_link_frag_rcv(struct sk_buff **reasm_head, |
| 243 | struct sk_buff **reasm_tail, | 243 | struct sk_buff **reasm_tail, |
| 244 | struct sk_buff **fbuf); | 244 | struct sk_buff **fbuf); |
| 245 | void tipc_link_send_proto_msg(struct tipc_link *l_ptr, u32 msg_typ, int prob, | 245 | void tipc_link_proto_xmit(struct tipc_link *l_ptr, u32 msg_typ, int prob, |
| 246 | u32 gap, u32 tolerance, u32 priority, | 246 | u32 gap, u32 tolerance, u32 priority, u32 acked_mtu); |
| 247 | u32 acked_mtu); | ||
| 248 | void tipc_link_push_queue(struct tipc_link *l_ptr); | 247 | void tipc_link_push_queue(struct tipc_link *l_ptr); |
| 249 | u32 tipc_link_defer_pkt(struct sk_buff **head, struct sk_buff **tail, | 248 | u32 tipc_link_defer_pkt(struct sk_buff **head, struct sk_buff **tail, |
| 250 | struct sk_buff *buf); | 249 | struct sk_buff *buf); |
| 251 | void tipc_link_wakeup_ports(struct tipc_link *l_ptr, int all); | 250 | void tipc_link_wakeup_ports(struct tipc_link *l_ptr, int all); |
| 252 | void tipc_link_set_queue_limits(struct tipc_link *l_ptr, u32 window); | 251 | void tipc_link_set_queue_limits(struct tipc_link *l_ptr, u32 window); |
| 253 | void tipc_link_retransmit(struct tipc_link *l_ptr, | 252 | void tipc_link_retransmit(struct tipc_link *l_ptr, |
diff --git a/net/tipc/name_distr.c b/net/tipc/name_distr.c index e0d08055754e..aff8041dc157 100644 --- a/net/tipc/name_distr.c +++ b/net/tipc/name_distr.c | |||
| @@ -131,16 +131,24 @@ static void named_cluster_distribute(struct sk_buff *buf) | |||
| 131 | { | 131 | { |
| 132 | struct sk_buff *buf_copy; | 132 | struct sk_buff *buf_copy; |
| 133 | struct tipc_node *n_ptr; | 133 | struct tipc_node *n_ptr; |
| 134 | struct tipc_link *l_ptr; | ||
| 134 | 135 | ||
| 135 | list_for_each_entry(n_ptr, &tipc_node_list, list) { | 136 | rcu_read_lock(); |
| 136 | if (tipc_node_active_links(n_ptr)) { | 137 | list_for_each_entry_rcu(n_ptr, &tipc_node_list, list) { |
| 138 | spin_lock_bh(&n_ptr->lock); | ||
| 139 | l_ptr = n_ptr->active_links[n_ptr->addr & 1]; | ||
| 140 | if (l_ptr) { | ||
| 137 | buf_copy = skb_copy(buf, GFP_ATOMIC); | 141 | buf_copy = skb_copy(buf, GFP_ATOMIC); |
| 138 | if (!buf_copy) | 142 | if (!buf_copy) { |
| 143 | spin_unlock_bh(&n_ptr->lock); | ||
| 139 | break; | 144 | break; |
| 145 | } | ||
| 140 | msg_set_destnode(buf_msg(buf_copy), n_ptr->addr); | 146 | msg_set_destnode(buf_msg(buf_copy), n_ptr->addr); |
| 141 | tipc_link_send(buf_copy, n_ptr->addr, n_ptr->addr); | 147 | __tipc_link_xmit(l_ptr, buf_copy); |
| 142 | } | 148 | } |
| 149 | spin_unlock_bh(&n_ptr->lock); | ||
| 143 | } | 150 | } |
| 151 | rcu_read_unlock(); | ||
| 144 | 152 | ||
| 145 | kfree_skb(buf); | 153 | kfree_skb(buf); |
| 146 | } | 154 | } |
| @@ -262,7 +270,7 @@ void tipc_named_node_up(unsigned long nodearg) | |||
| 262 | named_distribute(&message_list, node, &publ_zone, max_item_buf); | 270 | named_distribute(&message_list, node, &publ_zone, max_item_buf); |
| 263 | read_unlock_bh(&tipc_nametbl_lock); | 271 | read_unlock_bh(&tipc_nametbl_lock); |
| 264 | 272 | ||
| 265 | tipc_link_send_names(&message_list, node); | 273 | tipc_link_names_xmit(&message_list, node); |
| 266 | } | 274 | } |
| 267 | 275 | ||
| 268 | /** | 276 | /** |
| @@ -293,9 +301,9 @@ static void named_purge_publ(struct publication *publ) | |||
| 293 | } | 301 | } |
| 294 | 302 | ||
| 295 | /** | 303 | /** |
| 296 | * tipc_named_recv - process name table update message sent by another node | 304 | * tipc_named_rcv - process name table update message sent by another node |
| 297 | */ | 305 | */ |
| 298 | void tipc_named_recv(struct sk_buff *buf) | 306 | void tipc_named_rcv(struct sk_buff *buf) |
| 299 | { | 307 | { |
| 300 | struct publication *publ; | 308 | struct publication *publ; |
| 301 | struct tipc_msg *msg = buf_msg(buf); | 309 | struct tipc_msg *msg = buf_msg(buf); |
diff --git a/net/tipc/name_distr.h b/net/tipc/name_distr.h index 1e41bdd4f255..9b312ccfd43e 100644 --- a/net/tipc/name_distr.h +++ b/net/tipc/name_distr.h | |||
| @@ -42,7 +42,7 @@ | |||
| 42 | void tipc_named_publish(struct publication *publ); | 42 | void tipc_named_publish(struct publication *publ); |
| 43 | void tipc_named_withdraw(struct publication *publ); | 43 | void tipc_named_withdraw(struct publication *publ); |
| 44 | void tipc_named_node_up(unsigned long node); | 44 | void tipc_named_node_up(unsigned long node); |
| 45 | void tipc_named_recv(struct sk_buff *buf); | 45 | void tipc_named_rcv(struct sk_buff *buf); |
| 46 | void tipc_named_reinit(void); | 46 | void tipc_named_reinit(void); |
| 47 | 47 | ||
| 48 | #endif | 48 | #endif |
diff --git a/net/tipc/net.c b/net/tipc/net.c index 7d305ecc09c2..4c564eb69e1a 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c | |||
| @@ -146,19 +146,19 @@ void tipc_net_route_msg(struct sk_buff *buf) | |||
| 146 | if (tipc_in_scope(dnode, tipc_own_addr)) { | 146 | if (tipc_in_scope(dnode, tipc_own_addr)) { |
| 147 | if (msg_isdata(msg)) { | 147 | if (msg_isdata(msg)) { |
| 148 | if (msg_mcast(msg)) | 148 | if (msg_mcast(msg)) |
| 149 | tipc_port_recv_mcast(buf, NULL); | 149 | tipc_port_mcast_rcv(buf, NULL); |
| 150 | else if (msg_destport(msg)) | 150 | else if (msg_destport(msg)) |
| 151 | tipc_port_recv_msg(buf); | 151 | tipc_port_rcv(buf); |
| 152 | else | 152 | else |
| 153 | net_route_named_msg(buf); | 153 | net_route_named_msg(buf); |
| 154 | return; | 154 | return; |
| 155 | } | 155 | } |
| 156 | switch (msg_user(msg)) { | 156 | switch (msg_user(msg)) { |
| 157 | case NAME_DISTRIBUTOR: | 157 | case NAME_DISTRIBUTOR: |
| 158 | tipc_named_recv(buf); | 158 | tipc_named_rcv(buf); |
| 159 | break; | 159 | break; |
| 160 | case CONN_MANAGER: | 160 | case CONN_MANAGER: |
| 161 | tipc_port_recv_proto_msg(buf); | 161 | tipc_port_proto_rcv(buf); |
| 162 | break; | 162 | break; |
| 163 | default: | 163 | default: |
| 164 | kfree_skb(buf); | 164 | kfree_skb(buf); |
| @@ -168,7 +168,7 @@ void tipc_net_route_msg(struct sk_buff *buf) | |||
| 168 | 168 | ||
| 169 | /* Handle message for another node */ | 169 | /* Handle message for another node */ |
| 170 | skb_trim(buf, msg_size(msg)); | 170 | skb_trim(buf, msg_size(msg)); |
| 171 | tipc_link_send(buf, dnode, msg_link_selector(msg)); | 171 | tipc_link_xmit(buf, dnode, msg_link_selector(msg)); |
| 172 | } | 172 | } |
| 173 | 173 | ||
| 174 | void tipc_net_start(u32 addr) | 174 | void tipc_net_start(u32 addr) |
| @@ -182,8 +182,8 @@ void tipc_net_start(u32 addr) | |||
| 182 | tipc_bclink_init(); | 182 | tipc_bclink_init(); |
| 183 | write_unlock_bh(&tipc_net_lock); | 183 | write_unlock_bh(&tipc_net_lock); |
| 184 | 184 | ||
| 185 | tipc_cfg_reinit(); | 185 | tipc_nametbl_publish(TIPC_CFG_SRV, tipc_own_addr, tipc_own_addr, |
| 186 | 186 | TIPC_ZONE_SCOPE, 0, tipc_own_addr); | |
| 187 | pr_info("Started in network mode\n"); | 187 | pr_info("Started in network mode\n"); |
| 188 | pr_info("Own node address %s, network identity %u\n", | 188 | pr_info("Own node address %s, network identity %u\n", |
| 189 | tipc_addr_string_fill(addr_string, tipc_own_addr), tipc_net_id); | 189 | tipc_addr_string_fill(addr_string, tipc_own_addr), tipc_net_id); |
| @@ -191,15 +191,15 @@ void tipc_net_start(u32 addr) | |||
| 191 | 191 | ||
| 192 | void tipc_net_stop(void) | 192 | void tipc_net_stop(void) |
| 193 | { | 193 | { |
| 194 | struct tipc_node *node, *t_node; | ||
| 195 | |||
| 196 | if (!tipc_own_addr) | 194 | if (!tipc_own_addr) |
| 197 | return; | 195 | return; |
| 196 | |||
| 197 | tipc_nametbl_withdraw(TIPC_CFG_SRV, tipc_own_addr, 0, tipc_own_addr); | ||
| 198 | write_lock_bh(&tipc_net_lock); | 198 | write_lock_bh(&tipc_net_lock); |
| 199 | tipc_bearer_stop(); | 199 | tipc_bearer_stop(); |
| 200 | tipc_bclink_stop(); | 200 | tipc_bclink_stop(); |
| 201 | list_for_each_entry_safe(node, t_node, &tipc_node_list, list) | 201 | tipc_node_stop(); |
| 202 | tipc_node_delete(node); | ||
| 203 | write_unlock_bh(&tipc_net_lock); | 202 | write_unlock_bh(&tipc_net_lock); |
| 203 | |||
| 204 | pr_info("Left network mode\n"); | 204 | pr_info("Left network mode\n"); |
| 205 | } | 205 | } |
diff --git a/net/tipc/node.c b/net/tipc/node.c index efe4d41bf11b..1d3a4999a70f 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * net/tipc/node.c: TIPC node management routines | 2 | * net/tipc/node.c: TIPC node management routines |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2000-2006, 2012 Ericsson AB | 4 | * Copyright (c) 2000-2006, 2012 Ericsson AB |
| 5 | * Copyright (c) 2005-2006, 2010-2011, Wind River Systems | 5 | * Copyright (c) 2005-2006, 2010-2014, Wind River Systems |
| 6 | * All rights reserved. | 6 | * All rights reserved. |
| 7 | * | 7 | * |
| 8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
| @@ -44,13 +44,11 @@ | |||
| 44 | static void node_lost_contact(struct tipc_node *n_ptr); | 44 | static void node_lost_contact(struct tipc_node *n_ptr); |
| 45 | static void node_established_contact(struct tipc_node *n_ptr); | 45 | static void node_established_contact(struct tipc_node *n_ptr); |
| 46 | 46 | ||
| 47 | static DEFINE_SPINLOCK(node_create_lock); | ||
| 48 | |||
| 49 | static struct hlist_head node_htable[NODE_HTABLE_SIZE]; | 47 | static struct hlist_head node_htable[NODE_HTABLE_SIZE]; |
| 50 | LIST_HEAD(tipc_node_list); | 48 | LIST_HEAD(tipc_node_list); |
| 51 | static u32 tipc_num_nodes; | 49 | static u32 tipc_num_nodes; |
| 52 | 50 | static u32 tipc_num_links; | |
| 53 | static atomic_t tipc_num_links = ATOMIC_INIT(0); | 51 | static DEFINE_SPINLOCK(node_list_lock); |
| 54 | 52 | ||
| 55 | /* | 53 | /* |
| 56 | * A trivial power-of-two bitmask technique is used for speed, since this | 54 | * A trivial power-of-two bitmask technique is used for speed, since this |
| @@ -73,37 +71,26 @@ struct tipc_node *tipc_node_find(u32 addr) | |||
| 73 | if (unlikely(!in_own_cluster_exact(addr))) | 71 | if (unlikely(!in_own_cluster_exact(addr))) |
| 74 | return NULL; | 72 | return NULL; |
| 75 | 73 | ||
| 76 | hlist_for_each_entry(node, &node_htable[tipc_hashfn(addr)], hash) { | 74 | rcu_read_lock(); |
| 77 | if (node->addr == addr) | 75 | hlist_for_each_entry_rcu(node, &node_htable[tipc_hashfn(addr)], hash) { |
| 76 | if (node->addr == addr) { | ||
| 77 | rcu_read_unlock(); | ||
| 78 | return node; | 78 | return node; |
| 79 | } | ||
| 79 | } | 80 | } |
| 81 | rcu_read_unlock(); | ||
| 80 | return NULL; | 82 | return NULL; |
| 81 | } | 83 | } |
| 82 | 84 | ||
| 83 | /** | ||
| 84 | * tipc_node_create - create neighboring node | ||
| 85 | * | ||
| 86 | * Currently, this routine is called by neighbor discovery code, which holds | ||
| 87 | * net_lock for reading only. We must take node_create_lock to ensure a node | ||
| 88 | * isn't created twice if two different bearers discover the node at the same | ||
| 89 | * time. (It would be preferable to switch to holding net_lock in write mode, | ||
| 90 | * but this is a non-trivial change.) | ||
| 91 | */ | ||
| 92 | struct tipc_node *tipc_node_create(u32 addr) | 85 | struct tipc_node *tipc_node_create(u32 addr) |
| 93 | { | 86 | { |
| 94 | struct tipc_node *n_ptr, *temp_node; | 87 | struct tipc_node *n_ptr, *temp_node; |
| 95 | 88 | ||
| 96 | spin_lock_bh(&node_create_lock); | 89 | spin_lock_bh(&node_list_lock); |
| 97 | |||
| 98 | n_ptr = tipc_node_find(addr); | ||
| 99 | if (n_ptr) { | ||
| 100 | spin_unlock_bh(&node_create_lock); | ||
| 101 | return n_ptr; | ||
| 102 | } | ||
| 103 | 90 | ||
| 104 | n_ptr = kzalloc(sizeof(*n_ptr), GFP_ATOMIC); | 91 | n_ptr = kzalloc(sizeof(*n_ptr), GFP_ATOMIC); |
| 105 | if (!n_ptr) { | 92 | if (!n_ptr) { |
| 106 | spin_unlock_bh(&node_create_lock); | 93 | spin_unlock_bh(&node_list_lock); |
| 107 | pr_warn("Node creation failed, no memory\n"); | 94 | pr_warn("Node creation failed, no memory\n"); |
| 108 | return NULL; | 95 | return NULL; |
| 109 | } | 96 | } |
| @@ -114,31 +101,41 @@ struct tipc_node *tipc_node_create(u32 addr) | |||
| 114 | INIT_LIST_HEAD(&n_ptr->list); | 101 | INIT_LIST_HEAD(&n_ptr->list); |
| 115 | INIT_LIST_HEAD(&n_ptr->nsub); | 102 | INIT_LIST_HEAD(&n_ptr->nsub); |
| 116 | 103 | ||
| 117 | hlist_add_head(&n_ptr->hash, &node_htable[tipc_hashfn(addr)]); | 104 | hlist_add_head_rcu(&n_ptr->hash, &node_htable[tipc_hashfn(addr)]); |
| 118 | 105 | ||
| 119 | list_for_each_entry(temp_node, &tipc_node_list, list) { | 106 | list_for_each_entry_rcu(temp_node, &tipc_node_list, list) { |
| 120 | if (n_ptr->addr < temp_node->addr) | 107 | if (n_ptr->addr < temp_node->addr) |
| 121 | break; | 108 | break; |
| 122 | } | 109 | } |
| 123 | list_add_tail(&n_ptr->list, &temp_node->list); | 110 | list_add_tail_rcu(&n_ptr->list, &temp_node->list); |
| 124 | n_ptr->block_setup = WAIT_PEER_DOWN; | 111 | n_ptr->block_setup = WAIT_PEER_DOWN; |
| 125 | n_ptr->signature = INVALID_NODE_SIG; | 112 | n_ptr->signature = INVALID_NODE_SIG; |
| 126 | 113 | ||
| 127 | tipc_num_nodes++; | 114 | tipc_num_nodes++; |
| 128 | 115 | ||
| 129 | spin_unlock_bh(&node_create_lock); | 116 | spin_unlock_bh(&node_list_lock); |
| 130 | return n_ptr; | 117 | return n_ptr; |
| 131 | } | 118 | } |
| 132 | 119 | ||
| 133 | void tipc_node_delete(struct tipc_node *n_ptr) | 120 | static void tipc_node_delete(struct tipc_node *n_ptr) |
| 134 | { | 121 | { |
| 135 | list_del(&n_ptr->list); | 122 | list_del_rcu(&n_ptr->list); |
| 136 | hlist_del(&n_ptr->hash); | 123 | hlist_del_rcu(&n_ptr->hash); |
| 137 | kfree(n_ptr); | 124 | kfree_rcu(n_ptr, rcu); |
| 138 | 125 | ||
| 139 | tipc_num_nodes--; | 126 | tipc_num_nodes--; |
| 140 | } | 127 | } |
| 141 | 128 | ||
| 129 | void tipc_node_stop(void) | ||
| 130 | { | ||
| 131 | struct tipc_node *node, *t_node; | ||
| 132 | |||
| 133 | spin_lock_bh(&node_list_lock); | ||
| 134 | list_for_each_entry_safe(node, t_node, &tipc_node_list, list) | ||
| 135 | tipc_node_delete(node); | ||
| 136 | spin_unlock_bh(&node_list_lock); | ||
| 137 | } | ||
| 138 | |||
| 142 | /** | 139 | /** |
| 143 | * tipc_node_link_up - handle addition of link | 140 | * tipc_node_link_up - handle addition of link |
| 144 | * | 141 | * |
| @@ -162,7 +159,7 @@ void tipc_node_link_up(struct tipc_node *n_ptr, struct tipc_link *l_ptr) | |||
| 162 | pr_info("New link <%s> becomes standby\n", l_ptr->name); | 159 | pr_info("New link <%s> becomes standby\n", l_ptr->name); |
| 163 | return; | 160 | return; |
| 164 | } | 161 | } |
| 165 | tipc_link_dup_send_queue(active[0], l_ptr); | 162 | tipc_link_dup_queue_xmit(active[0], l_ptr); |
| 166 | if (l_ptr->priority == active[0]->priority) { | 163 | if (l_ptr->priority == active[0]->priority) { |
| 167 | active[0] = l_ptr; | 164 | active[0] = l_ptr; |
| 168 | return; | 165 | return; |
| @@ -243,15 +240,25 @@ int tipc_node_is_up(struct tipc_node *n_ptr) | |||
| 243 | void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr) | 240 | void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr) |
| 244 | { | 241 | { |
| 245 | n_ptr->links[l_ptr->b_ptr->identity] = l_ptr; | 242 | n_ptr->links[l_ptr->b_ptr->identity] = l_ptr; |
| 246 | atomic_inc(&tipc_num_links); | 243 | spin_lock_bh(&node_list_lock); |
| 244 | tipc_num_links++; | ||
| 245 | spin_unlock_bh(&node_list_lock); | ||
| 247 | n_ptr->link_cnt++; | 246 | n_ptr->link_cnt++; |
| 248 | } | 247 | } |
| 249 | 248 | ||
| 250 | void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr) | 249 | void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr) |
| 251 | { | 250 | { |
| 252 | n_ptr->links[l_ptr->b_ptr->identity] = NULL; | 251 | int i; |
| 253 | atomic_dec(&tipc_num_links); | 252 | |
| 254 | n_ptr->link_cnt--; | 253 | for (i = 0; i < MAX_BEARERS; i++) { |
| 254 | if (l_ptr != n_ptr->links[i]) | ||
| 255 | continue; | ||
| 256 | n_ptr->links[i] = NULL; | ||
| 257 | spin_lock_bh(&node_list_lock); | ||
| 258 | tipc_num_links--; | ||
| 259 | spin_unlock_bh(&node_list_lock); | ||
| 260 | n_ptr->link_cnt--; | ||
| 261 | } | ||
| 255 | } | 262 | } |
| 256 | 263 | ||
| 257 | static void node_established_contact(struct tipc_node *n_ptr) | 264 | static void node_established_contact(struct tipc_node *n_ptr) |
| @@ -335,27 +342,28 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) | |||
| 335 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE | 342 | return tipc_cfg_reply_error_string(TIPC_CFG_INVALID_VALUE |
| 336 | " (network address)"); | 343 | " (network address)"); |
| 337 | 344 | ||
| 338 | read_lock_bh(&tipc_net_lock); | 345 | spin_lock_bh(&node_list_lock); |
| 339 | if (!tipc_num_nodes) { | 346 | if (!tipc_num_nodes) { |
| 340 | read_unlock_bh(&tipc_net_lock); | 347 | spin_unlock_bh(&node_list_lock); |
| 341 | return tipc_cfg_reply_none(); | 348 | return tipc_cfg_reply_none(); |
| 342 | } | 349 | } |
| 343 | 350 | ||
| 344 | /* For now, get space for all other nodes */ | 351 | /* For now, get space for all other nodes */ |
| 345 | payload_size = TLV_SPACE(sizeof(node_info)) * tipc_num_nodes; | 352 | payload_size = TLV_SPACE(sizeof(node_info)) * tipc_num_nodes; |
| 346 | if (payload_size > 32768u) { | 353 | if (payload_size > 32768u) { |
| 347 | read_unlock_bh(&tipc_net_lock); | 354 | spin_unlock_bh(&node_list_lock); |
| 348 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 355 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
| 349 | " (too many nodes)"); | 356 | " (too many nodes)"); |
| 350 | } | 357 | } |
| 358 | spin_unlock_bh(&node_list_lock); | ||
| 359 | |||
| 351 | buf = tipc_cfg_reply_alloc(payload_size); | 360 | buf = tipc_cfg_reply_alloc(payload_size); |
| 352 | if (!buf) { | 361 | if (!buf) |
| 353 | read_unlock_bh(&tipc_net_lock); | ||
| 354 | return NULL; | 362 | return NULL; |
| 355 | } | ||
| 356 | 363 | ||
| 357 | /* Add TLVs for all nodes in scope */ | 364 | /* Add TLVs for all nodes in scope */ |
| 358 | list_for_each_entry(n_ptr, &tipc_node_list, list) { | 365 | rcu_read_lock(); |
| 366 | list_for_each_entry_rcu(n_ptr, &tipc_node_list, list) { | ||
| 359 | if (!tipc_in_scope(domain, n_ptr->addr)) | 367 | if (!tipc_in_scope(domain, n_ptr->addr)) |
| 360 | continue; | 368 | continue; |
| 361 | node_info.addr = htonl(n_ptr->addr); | 369 | node_info.addr = htonl(n_ptr->addr); |
| @@ -363,8 +371,7 @@ struct sk_buff *tipc_node_get_nodes(const void *req_tlv_area, int req_tlv_space) | |||
| 363 | tipc_cfg_append_tlv(buf, TIPC_TLV_NODE_INFO, | 371 | tipc_cfg_append_tlv(buf, TIPC_TLV_NODE_INFO, |
| 364 | &node_info, sizeof(node_info)); | 372 | &node_info, sizeof(node_info)); |
| 365 | } | 373 | } |
| 366 | 374 | rcu_read_unlock(); | |
| 367 | read_unlock_bh(&tipc_net_lock); | ||
| 368 | return buf; | 375 | return buf; |
| 369 | } | 376 | } |
| 370 | 377 | ||
| @@ -387,21 +394,19 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) | |||
| 387 | if (!tipc_own_addr) | 394 | if (!tipc_own_addr) |
| 388 | return tipc_cfg_reply_none(); | 395 | return tipc_cfg_reply_none(); |
| 389 | 396 | ||
| 390 | read_lock_bh(&tipc_net_lock); | 397 | spin_lock_bh(&node_list_lock); |
| 391 | |||
| 392 | /* Get space for all unicast links + broadcast link */ | 398 | /* Get space for all unicast links + broadcast link */ |
| 393 | payload_size = TLV_SPACE(sizeof(link_info)) * | 399 | payload_size = TLV_SPACE((sizeof(link_info)) * (tipc_num_links + 1)); |
| 394 | (atomic_read(&tipc_num_links) + 1); | ||
| 395 | if (payload_size > 32768u) { | 400 | if (payload_size > 32768u) { |
| 396 | read_unlock_bh(&tipc_net_lock); | 401 | spin_unlock_bh(&node_list_lock); |
| 397 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED | 402 | return tipc_cfg_reply_error_string(TIPC_CFG_NOT_SUPPORTED |
| 398 | " (too many links)"); | 403 | " (too many links)"); |
| 399 | } | 404 | } |
| 405 | spin_unlock_bh(&node_list_lock); | ||
| 406 | |||
| 400 | buf = tipc_cfg_reply_alloc(payload_size); | 407 | buf = tipc_cfg_reply_alloc(payload_size); |
| 401 | if (!buf) { | 408 | if (!buf) |
| 402 | read_unlock_bh(&tipc_net_lock); | ||
| 403 | return NULL; | 409 | return NULL; |
| 404 | } | ||
| 405 | 410 | ||
| 406 | /* Add TLV for broadcast link */ | 411 | /* Add TLV for broadcast link */ |
| 407 | link_info.dest = htonl(tipc_cluster_mask(tipc_own_addr)); | 412 | link_info.dest = htonl(tipc_cluster_mask(tipc_own_addr)); |
| @@ -410,7 +415,8 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) | |||
| 410 | tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info)); | 415 | tipc_cfg_append_tlv(buf, TIPC_TLV_LINK_INFO, &link_info, sizeof(link_info)); |
| 411 | 416 | ||
| 412 | /* Add TLVs for any other links in scope */ | 417 | /* Add TLVs for any other links in scope */ |
| 413 | list_for_each_entry(n_ptr, &tipc_node_list, list) { | 418 | rcu_read_lock(); |
| 419 | list_for_each_entry_rcu(n_ptr, &tipc_node_list, list) { | ||
| 414 | u32 i; | 420 | u32 i; |
| 415 | 421 | ||
| 416 | if (!tipc_in_scope(domain, n_ptr->addr)) | 422 | if (!tipc_in_scope(domain, n_ptr->addr)) |
| @@ -427,7 +433,6 @@ struct sk_buff *tipc_node_get_links(const void *req_tlv_area, int req_tlv_space) | |||
| 427 | } | 433 | } |
| 428 | tipc_node_unlock(n_ptr); | 434 | tipc_node_unlock(n_ptr); |
| 429 | } | 435 | } |
| 430 | 436 | rcu_read_unlock(); | |
| 431 | read_unlock_bh(&tipc_net_lock); | ||
| 432 | return buf; | 437 | return buf; |
| 433 | } | 438 | } |
diff --git a/net/tipc/node.h b/net/tipc/node.h index 63e2e8ead2fe..7cbb8cec1a93 100644 --- a/net/tipc/node.h +++ b/net/tipc/node.h | |||
| @@ -2,7 +2,7 @@ | |||
| 2 | * net/tipc/node.h: Include file for TIPC node management routines | 2 | * net/tipc/node.h: Include file for TIPC node management routines |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2000-2006, Ericsson AB | 4 | * Copyright (c) 2000-2006, Ericsson AB |
| 5 | * Copyright (c) 2005, 2010-2011, Wind River Systems | 5 | * Copyright (c) 2005, 2010-2014, Wind River Systems |
| 6 | * All rights reserved. | 6 | * All rights reserved. |
| 7 | * | 7 | * |
| 8 | * Redistribution and use in source and binary forms, with or without | 8 | * Redistribution and use in source and binary forms, with or without |
| @@ -66,6 +66,7 @@ | |||
| 66 | * @link_cnt: number of links to node | 66 | * @link_cnt: number of links to node |
| 67 | * @signature: node instance identifier | 67 | * @signature: node instance identifier |
| 68 | * @bclink: broadcast-related info | 68 | * @bclink: broadcast-related info |
| 69 | * @rcu: rcu struct for tipc_node | ||
| 69 | * @acked: sequence # of last outbound b'cast message acknowledged by node | 70 | * @acked: sequence # of last outbound b'cast message acknowledged by node |
| 70 | * @last_in: sequence # of last in-sequence b'cast message received from node | 71 | * @last_in: sequence # of last in-sequence b'cast message received from node |
| 71 | * @last_sent: sequence # of last b'cast message sent by node | 72 | * @last_sent: sequence # of last b'cast message sent by node |
| @@ -89,6 +90,7 @@ struct tipc_node { | |||
| 89 | int working_links; | 90 | int working_links; |
| 90 | int block_setup; | 91 | int block_setup; |
| 91 | u32 signature; | 92 | u32 signature; |
| 93 | struct rcu_head rcu; | ||
| 92 | struct { | 94 | struct { |
| 93 | u32 acked; | 95 | u32 acked; |
| 94 | u32 last_in; | 96 | u32 last_in; |
| @@ -107,7 +109,7 @@ extern struct list_head tipc_node_list; | |||
| 107 | 109 | ||
| 108 | struct tipc_node *tipc_node_find(u32 addr); | 110 | struct tipc_node *tipc_node_find(u32 addr); |
| 109 | struct tipc_node *tipc_node_create(u32 addr); | 111 | struct tipc_node *tipc_node_create(u32 addr); |
| 110 | void tipc_node_delete(struct tipc_node *n_ptr); | 112 | void tipc_node_stop(void); |
| 111 | void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr); | 113 | void tipc_node_attach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr); |
| 112 | void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr); | 114 | void tipc_node_detach_link(struct tipc_node *n_ptr, struct tipc_link *l_ptr); |
| 113 | void tipc_node_link_down(struct tipc_node *n_ptr, struct tipc_link *l_ptr); | 115 | void tipc_node_link_down(struct tipc_node *n_ptr, struct tipc_link *l_ptr); |
diff --git a/net/tipc/port.c b/net/tipc/port.c index b742b2654525..5c14c7801ee6 100644 --- a/net/tipc/port.c +++ b/net/tipc/port.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * net/tipc/port.c: TIPC port code | 2 | * net/tipc/port.c: TIPC port code |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 1992-2007, Ericsson AB | 4 | * Copyright (c) 1992-2007, 2014, Ericsson AB |
| 5 | * Copyright (c) 2004-2008, 2010-2013, Wind River Systems | 5 | * Copyright (c) 2004-2008, 2010-2013, Wind River Systems |
| 6 | * All rights reserved. | 6 | * All rights reserved. |
| 7 | * | 7 | * |
| @@ -38,6 +38,7 @@ | |||
| 38 | #include "config.h" | 38 | #include "config.h" |
| 39 | #include "port.h" | 39 | #include "port.h" |
| 40 | #include "name_table.h" | 40 | #include "name_table.h" |
| 41 | #include "socket.h" | ||
| 41 | 42 | ||
| 42 | /* Connection management: */ | 43 | /* Connection management: */ |
| 43 | #define PROBING_INTERVAL 3600000 /* [ms] => 1 h */ | 44 | #define PROBING_INTERVAL 3600000 /* [ms] => 1 h */ |
| @@ -54,17 +55,6 @@ static struct sk_buff *port_build_self_abort_msg(struct tipc_port *, u32 err); | |||
| 54 | static struct sk_buff *port_build_peer_abort_msg(struct tipc_port *, u32 err); | 55 | static struct sk_buff *port_build_peer_abort_msg(struct tipc_port *, u32 err); |
| 55 | static void port_timeout(unsigned long ref); | 56 | static void port_timeout(unsigned long ref); |
| 56 | 57 | ||
| 57 | |||
| 58 | static u32 port_peernode(struct tipc_port *p_ptr) | ||
| 59 | { | ||
| 60 | return msg_destnode(&p_ptr->phdr); | ||
| 61 | } | ||
| 62 | |||
| 63 | static u32 port_peerport(struct tipc_port *p_ptr) | ||
| 64 | { | ||
| 65 | return msg_destport(&p_ptr->phdr); | ||
| 66 | } | ||
| 67 | |||
| 68 | /** | 58 | /** |
| 69 | * tipc_port_peer_msg - verify message was sent by connected port's peer | 59 | * tipc_port_peer_msg - verify message was sent by connected port's peer |
| 70 | * | 60 | * |
| @@ -76,33 +66,32 @@ int tipc_port_peer_msg(struct tipc_port *p_ptr, struct tipc_msg *msg) | |||
| 76 | u32 peernode; | 66 | u32 peernode; |
| 77 | u32 orignode; | 67 | u32 orignode; |
| 78 | 68 | ||
| 79 | if (msg_origport(msg) != port_peerport(p_ptr)) | 69 | if (msg_origport(msg) != tipc_port_peerport(p_ptr)) |
| 80 | return 0; | 70 | return 0; |
| 81 | 71 | ||
| 82 | orignode = msg_orignode(msg); | 72 | orignode = msg_orignode(msg); |
| 83 | peernode = port_peernode(p_ptr); | 73 | peernode = tipc_port_peernode(p_ptr); |
| 84 | return (orignode == peernode) || | 74 | return (orignode == peernode) || |
| 85 | (!orignode && (peernode == tipc_own_addr)) || | 75 | (!orignode && (peernode == tipc_own_addr)) || |
| 86 | (!peernode && (orignode == tipc_own_addr)); | 76 | (!peernode && (orignode == tipc_own_addr)); |
| 87 | } | 77 | } |
| 88 | 78 | ||
| 89 | /** | 79 | /** |
| 90 | * tipc_multicast - send a multicast message to local and remote destinations | 80 | * tipc_port_mcast_xmit - send a multicast message to local and remote |
| 81 | * destinations | ||
| 91 | */ | 82 | */ |
| 92 | int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, | 83 | int tipc_port_mcast_xmit(struct tipc_port *oport, |
| 93 | struct iovec const *msg_sect, unsigned int len) | 84 | struct tipc_name_seq const *seq, |
| 85 | struct iovec const *msg_sect, | ||
| 86 | unsigned int len) | ||
| 94 | { | 87 | { |
| 95 | struct tipc_msg *hdr; | 88 | struct tipc_msg *hdr; |
| 96 | struct sk_buff *buf; | 89 | struct sk_buff *buf; |
| 97 | struct sk_buff *ibuf = NULL; | 90 | struct sk_buff *ibuf = NULL; |
| 98 | struct tipc_port_list dports = {0, NULL, }; | 91 | struct tipc_port_list dports = {0, NULL, }; |
| 99 | struct tipc_port *oport = tipc_port_deref(ref); | ||
| 100 | int ext_targets; | 92 | int ext_targets; |
| 101 | int res; | 93 | int res; |
| 102 | 94 | ||
| 103 | if (unlikely(!oport)) | ||
| 104 | return -EINVAL; | ||
| 105 | |||
| 106 | /* Create multicast message */ | 95 | /* Create multicast message */ |
| 107 | hdr = &oport->phdr; | 96 | hdr = &oport->phdr; |
| 108 | msg_set_type(hdr, TIPC_MCAST_MSG); | 97 | msg_set_type(hdr, TIPC_MCAST_MSG); |
| @@ -131,7 +120,7 @@ int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, | |||
| 131 | return -ENOMEM; | 120 | return -ENOMEM; |
| 132 | } | 121 | } |
| 133 | } | 122 | } |
| 134 | res = tipc_bclink_send_msg(buf); | 123 | res = tipc_bclink_xmit(buf); |
| 135 | if ((res < 0) && (dports.count != 0)) | 124 | if ((res < 0) && (dports.count != 0)) |
| 136 | kfree_skb(ibuf); | 125 | kfree_skb(ibuf); |
| 137 | } else { | 126 | } else { |
| @@ -140,7 +129,7 @@ int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, | |||
| 140 | 129 | ||
| 141 | if (res >= 0) { | 130 | if (res >= 0) { |
| 142 | if (ibuf) | 131 | if (ibuf) |
| 143 | tipc_port_recv_mcast(ibuf, &dports); | 132 | tipc_port_mcast_rcv(ibuf, &dports); |
| 144 | } else { | 133 | } else { |
| 145 | tipc_port_list_free(&dports); | 134 | tipc_port_list_free(&dports); |
| 146 | } | 135 | } |
| @@ -148,11 +137,11 @@ int tipc_multicast(u32 ref, struct tipc_name_seq const *seq, | |||
| 148 | } | 137 | } |
| 149 | 138 | ||
| 150 | /** | 139 | /** |
| 151 | * tipc_port_recv_mcast - deliver multicast message to all destination ports | 140 | * tipc_port_mcast_rcv - deliver multicast message to all destination ports |
| 152 | * | 141 | * |
| 153 | * If there is no port list, perform a lookup to create one | 142 | * If there is no port list, perform a lookup to create one |
| 154 | */ | 143 | */ |
| 155 | void tipc_port_recv_mcast(struct sk_buff *buf, struct tipc_port_list *dp) | 144 | void tipc_port_mcast_rcv(struct sk_buff *buf, struct tipc_port_list *dp) |
| 156 | { | 145 | { |
| 157 | struct tipc_msg *msg; | 146 | struct tipc_msg *msg; |
| 158 | struct tipc_port_list dports = {0, NULL, }; | 147 | struct tipc_port_list dports = {0, NULL, }; |
| @@ -176,7 +165,7 @@ void tipc_port_recv_mcast(struct sk_buff *buf, struct tipc_port_list *dp) | |||
| 176 | msg_set_destnode(msg, tipc_own_addr); | 165 | msg_set_destnode(msg, tipc_own_addr); |
| 177 | if (dp->count == 1) { | 166 | if (dp->count == 1) { |
| 178 | msg_set_destport(msg, dp->ports[0]); | 167 | msg_set_destport(msg, dp->ports[0]); |
| 179 | tipc_port_recv_msg(buf); | 168 | tipc_port_rcv(buf); |
| 180 | tipc_port_list_free(dp); | 169 | tipc_port_list_free(dp); |
| 181 | return; | 170 | return; |
| 182 | } | 171 | } |
| @@ -191,7 +180,7 @@ void tipc_port_recv_mcast(struct sk_buff *buf, struct tipc_port_list *dp) | |||
| 191 | if ((index == 0) && (cnt != 0)) | 180 | if ((index == 0) && (cnt != 0)) |
| 192 | item = item->next; | 181 | item = item->next; |
| 193 | msg_set_destport(buf_msg(b), item->ports[index]); | 182 | msg_set_destport(buf_msg(b), item->ports[index]); |
| 194 | tipc_port_recv_msg(b); | 183 | tipc_port_rcv(b); |
| 195 | } | 184 | } |
| 196 | } | 185 | } |
| 197 | exit: | 186 | exit: |
| @@ -199,40 +188,32 @@ exit: | |||
| 199 | tipc_port_list_free(dp); | 188 | tipc_port_list_free(dp); |
| 200 | } | 189 | } |
| 201 | 190 | ||
| 202 | /** | 191 | |
| 203 | * tipc_createport - create a generic TIPC port | 192 | void tipc_port_wakeup(struct tipc_port *port) |
| 193 | { | ||
| 194 | tipc_sock_wakeup(tipc_port_to_sock(port)); | ||
| 195 | } | ||
| 196 | |||
| 197 | /* tipc_port_init - intiate TIPC port and lock it | ||
| 204 | * | 198 | * |
| 205 | * Returns pointer to (locked) TIPC port, or NULL if unable to create it | 199 | * Returns obtained reference if initialization is successful, zero otherwise |
| 206 | */ | 200 | */ |
| 207 | struct tipc_port *tipc_createport(struct sock *sk, | 201 | u32 tipc_port_init(struct tipc_port *p_ptr, |
| 208 | u32 (*dispatcher)(struct tipc_port *, | 202 | const unsigned int importance) |
| 209 | struct sk_buff *), | ||
| 210 | void (*wakeup)(struct tipc_port *), | ||
| 211 | const u32 importance) | ||
| 212 | { | 203 | { |
| 213 | struct tipc_port *p_ptr; | ||
| 214 | struct tipc_msg *msg; | 204 | struct tipc_msg *msg; |
| 215 | u32 ref; | 205 | u32 ref; |
| 216 | 206 | ||
| 217 | p_ptr = kzalloc(sizeof(*p_ptr), GFP_ATOMIC); | ||
| 218 | if (!p_ptr) { | ||
| 219 | pr_warn("Port creation failed, no memory\n"); | ||
| 220 | return NULL; | ||
| 221 | } | ||
| 222 | ref = tipc_ref_acquire(p_ptr, &p_ptr->lock); | 207 | ref = tipc_ref_acquire(p_ptr, &p_ptr->lock); |
| 223 | if (!ref) { | 208 | if (!ref) { |
| 224 | pr_warn("Port creation failed, ref. table exhausted\n"); | 209 | pr_warn("Port registration failed, ref. table exhausted\n"); |
| 225 | kfree(p_ptr); | 210 | return 0; |
| 226 | return NULL; | ||
| 227 | } | 211 | } |
| 228 | 212 | ||
| 229 | p_ptr->sk = sk; | ||
| 230 | p_ptr->max_pkt = MAX_PKT_DEFAULT; | 213 | p_ptr->max_pkt = MAX_PKT_DEFAULT; |
| 231 | p_ptr->ref = ref; | 214 | p_ptr->ref = ref; |
| 232 | INIT_LIST_HEAD(&p_ptr->wait_list); | 215 | INIT_LIST_HEAD(&p_ptr->wait_list); |
| 233 | INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list); | 216 | INIT_LIST_HEAD(&p_ptr->subscription.nodesub_list); |
| 234 | p_ptr->dispatcher = dispatcher; | ||
| 235 | p_ptr->wakeup = wakeup; | ||
| 236 | k_init_timer(&p_ptr->timer, (Handler)port_timeout, ref); | 217 | k_init_timer(&p_ptr->timer, (Handler)port_timeout, ref); |
| 237 | INIT_LIST_HEAD(&p_ptr->publications); | 218 | INIT_LIST_HEAD(&p_ptr->publications); |
| 238 | INIT_LIST_HEAD(&p_ptr->port_list); | 219 | INIT_LIST_HEAD(&p_ptr->port_list); |
| @@ -248,10 +229,10 @@ struct tipc_port *tipc_createport(struct sock *sk, | |||
| 248 | msg_set_origport(msg, ref); | 229 | msg_set_origport(msg, ref); |
| 249 | list_add_tail(&p_ptr->port_list, &ports); | 230 | list_add_tail(&p_ptr->port_list, &ports); |
| 250 | spin_unlock_bh(&tipc_port_list_lock); | 231 | spin_unlock_bh(&tipc_port_list_lock); |
| 251 | return p_ptr; | 232 | return ref; |
| 252 | } | 233 | } |
| 253 | 234 | ||
| 254 | int tipc_deleteport(struct tipc_port *p_ptr) | 235 | void tipc_port_destroy(struct tipc_port *p_ptr) |
| 255 | { | 236 | { |
| 256 | struct sk_buff *buf = NULL; | 237 | struct sk_buff *buf = NULL; |
| 257 | 238 | ||
| @@ -272,67 +253,7 @@ int tipc_deleteport(struct tipc_port *p_ptr) | |||
| 272 | list_del(&p_ptr->wait_list); | 253 | list_del(&p_ptr->wait_list); |
| 273 | spin_unlock_bh(&tipc_port_list_lock); | 254 | spin_unlock_bh(&tipc_port_list_lock); |
| 274 | k_term_timer(&p_ptr->timer); | 255 | k_term_timer(&p_ptr->timer); |
| 275 | kfree(p_ptr); | ||
| 276 | tipc_net_route_msg(buf); | 256 | tipc_net_route_msg(buf); |
| 277 | return 0; | ||
| 278 | } | ||
| 279 | |||
| 280 | static int port_unreliable(struct tipc_port *p_ptr) | ||
| 281 | { | ||
| 282 | return msg_src_droppable(&p_ptr->phdr); | ||
| 283 | } | ||
| 284 | |||
| 285 | int tipc_portunreliable(u32 ref, unsigned int *isunreliable) | ||
| 286 | { | ||
| 287 | struct tipc_port *p_ptr; | ||
| 288 | |||
| 289 | p_ptr = tipc_port_lock(ref); | ||
| 290 | if (!p_ptr) | ||
| 291 | return -EINVAL; | ||
| 292 | *isunreliable = port_unreliable(p_ptr); | ||
| 293 | tipc_port_unlock(p_ptr); | ||
| 294 | return 0; | ||
| 295 | } | ||
| 296 | |||
| 297 | int tipc_set_portunreliable(u32 ref, unsigned int isunreliable) | ||
| 298 | { | ||
| 299 | struct tipc_port *p_ptr; | ||
| 300 | |||
| 301 | p_ptr = tipc_port_lock(ref); | ||
| 302 | if (!p_ptr) | ||
| 303 | return -EINVAL; | ||
| 304 | msg_set_src_droppable(&p_ptr->phdr, (isunreliable != 0)); | ||
| 305 | tipc_port_unlock(p_ptr); | ||
| 306 | return 0; | ||
| 307 | } | ||
| 308 | |||
| 309 | static int port_unreturnable(struct tipc_port *p_ptr) | ||
| 310 | { | ||
| 311 | return msg_dest_droppable(&p_ptr->phdr); | ||
| 312 | } | ||
| 313 | |||
| 314 | int tipc_portunreturnable(u32 ref, unsigned int *isunrejectable) | ||
| 315 | { | ||
| 316 | struct tipc_port *p_ptr; | ||
| 317 | |||
| 318 | p_ptr = tipc_port_lock(ref); | ||
| 319 | if (!p_ptr) | ||
| 320 | return -EINVAL; | ||
| 321 | *isunrejectable = port_unreturnable(p_ptr); | ||
| 322 | tipc_port_unlock(p_ptr); | ||
| 323 | return 0; | ||
| 324 | } | ||
| 325 | |||
| 326 | int tipc_set_portunreturnable(u32 ref, unsigned int isunrejectable) | ||
| 327 | { | ||
| 328 | struct tipc_port *p_ptr; | ||
| 329 | |||
| 330 | p_ptr = tipc_port_lock(ref); | ||
| 331 | if (!p_ptr) | ||
| 332 | return -EINVAL; | ||
| 333 | msg_set_dest_droppable(&p_ptr->phdr, (isunrejectable != 0)); | ||
| 334 | tipc_port_unlock(p_ptr); | ||
| 335 | return 0; | ||
| 336 | } | 257 | } |
| 337 | 258 | ||
| 338 | /* | 259 | /* |
| @@ -350,8 +271,8 @@ static struct sk_buff *port_build_proto_msg(struct tipc_port *p_ptr, | |||
| 350 | if (buf) { | 271 | if (buf) { |
| 351 | msg = buf_msg(buf); | 272 | msg = buf_msg(buf); |
| 352 | tipc_msg_init(msg, CONN_MANAGER, type, INT_H_SIZE, | 273 | tipc_msg_init(msg, CONN_MANAGER, type, INT_H_SIZE, |
| 353 | port_peernode(p_ptr)); | 274 | tipc_port_peernode(p_ptr)); |
| 354 | msg_set_destport(msg, port_peerport(p_ptr)); | 275 | msg_set_destport(msg, tipc_port_peerport(p_ptr)); |
| 355 | msg_set_origport(msg, p_ptr->ref); | 276 | msg_set_origport(msg, p_ptr->ref); |
| 356 | msg_set_msgcnt(msg, ack); | 277 | msg_set_msgcnt(msg, ack); |
| 357 | } | 278 | } |
| @@ -422,17 +343,17 @@ int tipc_reject_msg(struct sk_buff *buf, u32 err) | |||
| 422 | /* send returned message & dispose of rejected message */ | 343 | /* send returned message & dispose of rejected message */ |
| 423 | src_node = msg_prevnode(msg); | 344 | src_node = msg_prevnode(msg); |
| 424 | if (in_own_node(src_node)) | 345 | if (in_own_node(src_node)) |
| 425 | tipc_port_recv_msg(rbuf); | 346 | tipc_port_rcv(rbuf); |
| 426 | else | 347 | else |
| 427 | tipc_link_send(rbuf, src_node, msg_link_selector(rmsg)); | 348 | tipc_link_xmit(rbuf, src_node, msg_link_selector(rmsg)); |
| 428 | exit: | 349 | exit: |
| 429 | kfree_skb(buf); | 350 | kfree_skb(buf); |
| 430 | return data_sz; | 351 | return data_sz; |
| 431 | } | 352 | } |
| 432 | 353 | ||
| 433 | int tipc_port_reject_sections(struct tipc_port *p_ptr, struct tipc_msg *hdr, | 354 | int tipc_port_iovec_reject(struct tipc_port *p_ptr, struct tipc_msg *hdr, |
| 434 | struct iovec const *msg_sect, unsigned int len, | 355 | struct iovec const *msg_sect, unsigned int len, |
| 435 | int err) | 356 | int err) |
| 436 | { | 357 | { |
| 437 | struct sk_buff *buf; | 358 | struct sk_buff *buf; |
| 438 | int res; | 359 | int res; |
| @@ -519,7 +440,7 @@ static struct sk_buff *port_build_peer_abort_msg(struct tipc_port *p_ptr, u32 er | |||
| 519 | return buf; | 440 | return buf; |
| 520 | } | 441 | } |
| 521 | 442 | ||
| 522 | void tipc_port_recv_proto_msg(struct sk_buff *buf) | 443 | void tipc_port_proto_rcv(struct sk_buff *buf) |
| 523 | { | 444 | { |
| 524 | struct tipc_msg *msg = buf_msg(buf); | 445 | struct tipc_msg *msg = buf_msg(buf); |
| 525 | struct tipc_port *p_ptr; | 446 | struct tipc_port *p_ptr; |
| @@ -547,13 +468,12 @@ void tipc_port_recv_proto_msg(struct sk_buff *buf) | |||
| 547 | /* Process protocol message sent by peer */ | 468 | /* Process protocol message sent by peer */ |
| 548 | switch (msg_type(msg)) { | 469 | switch (msg_type(msg)) { |
| 549 | case CONN_ACK: | 470 | case CONN_ACK: |
| 550 | wakeable = tipc_port_congested(p_ptr) && p_ptr->congested && | 471 | wakeable = tipc_port_congested(p_ptr) && p_ptr->congested; |
| 551 | p_ptr->wakeup; | ||
| 552 | p_ptr->acked += msg_msgcnt(msg); | 472 | p_ptr->acked += msg_msgcnt(msg); |
| 553 | if (!tipc_port_congested(p_ptr)) { | 473 | if (!tipc_port_congested(p_ptr)) { |
| 554 | p_ptr->congested = 0; | 474 | p_ptr->congested = 0; |
| 555 | if (wakeable) | 475 | if (wakeable) |
| 556 | p_ptr->wakeup(p_ptr); | 476 | tipc_port_wakeup(p_ptr); |
| 557 | } | 477 | } |
| 558 | break; | 478 | break; |
| 559 | case CONN_PROBE: | 479 | case CONN_PROBE: |
| @@ -584,8 +504,8 @@ static int port_print(struct tipc_port *p_ptr, char *buf, int len, int full_id) | |||
| 584 | ret = tipc_snprintf(buf, len, "%-10u:", p_ptr->ref); | 504 | ret = tipc_snprintf(buf, len, "%-10u:", p_ptr->ref); |
| 585 | 505 | ||
| 586 | if (p_ptr->connected) { | 506 | if (p_ptr->connected) { |
| 587 | u32 dport = port_peerport(p_ptr); | 507 | u32 dport = tipc_port_peerport(p_ptr); |
| 588 | u32 destnode = port_peernode(p_ptr); | 508 | u32 destnode = tipc_port_peernode(p_ptr); |
| 589 | 509 | ||
| 590 | ret += tipc_snprintf(buf + ret, len - ret, | 510 | ret += tipc_snprintf(buf + ret, len - ret, |
| 591 | " connected to <%u.%u.%u:%u>", | 511 | " connected to <%u.%u.%u:%u>", |
| @@ -673,34 +593,6 @@ void tipc_acknowledge(u32 ref, u32 ack) | |||
| 673 | tipc_net_route_msg(buf); | 593 | tipc_net_route_msg(buf); |
| 674 | } | 594 | } |
| 675 | 595 | ||
| 676 | int tipc_portimportance(u32 ref, unsigned int *importance) | ||
| 677 | { | ||
| 678 | struct tipc_port *p_ptr; | ||
| 679 | |||
| 680 | p_ptr = tipc_port_lock(ref); | ||
| 681 | if (!p_ptr) | ||
| 682 | return -EINVAL; | ||
| 683 | *importance = (unsigned int)msg_importance(&p_ptr->phdr); | ||
| 684 | tipc_port_unlock(p_ptr); | ||
| 685 | return 0; | ||
| 686 | } | ||
| 687 | |||
| 688 | int tipc_set_portimportance(u32 ref, unsigned int imp) | ||
| 689 | { | ||
| 690 | struct tipc_port *p_ptr; | ||
| 691 | |||
| 692 | if (imp > TIPC_CRITICAL_IMPORTANCE) | ||
| 693 | return -EINVAL; | ||
| 694 | |||
| 695 | p_ptr = tipc_port_lock(ref); | ||
| 696 | if (!p_ptr) | ||
| 697 | return -EINVAL; | ||
| 698 | msg_set_importance(&p_ptr->phdr, (u32)imp); | ||
| 699 | tipc_port_unlock(p_ptr); | ||
| 700 | return 0; | ||
| 701 | } | ||
| 702 | |||
| 703 | |||
| 704 | int tipc_publish(struct tipc_port *p_ptr, unsigned int scope, | 596 | int tipc_publish(struct tipc_port *p_ptr, unsigned int scope, |
| 705 | struct tipc_name_seq const *seq) | 597 | struct tipc_name_seq const *seq) |
| 706 | { | 598 | { |
| @@ -760,7 +652,7 @@ int tipc_withdraw(struct tipc_port *p_ptr, unsigned int scope, | |||
| 760 | return res; | 652 | return res; |
| 761 | } | 653 | } |
| 762 | 654 | ||
| 763 | int tipc_connect(u32 ref, struct tipc_portid const *peer) | 655 | int tipc_port_connect(u32 ref, struct tipc_portid const *peer) |
| 764 | { | 656 | { |
| 765 | struct tipc_port *p_ptr; | 657 | struct tipc_port *p_ptr; |
| 766 | int res; | 658 | int res; |
| @@ -768,17 +660,17 @@ int tipc_connect(u32 ref, struct tipc_portid const *peer) | |||
| 768 | p_ptr = tipc_port_lock(ref); | 660 | p_ptr = tipc_port_lock(ref); |
| 769 | if (!p_ptr) | 661 | if (!p_ptr) |
| 770 | return -EINVAL; | 662 | return -EINVAL; |
| 771 | res = __tipc_connect(ref, p_ptr, peer); | 663 | res = __tipc_port_connect(ref, p_ptr, peer); |
| 772 | tipc_port_unlock(p_ptr); | 664 | tipc_port_unlock(p_ptr); |
| 773 | return res; | 665 | return res; |
| 774 | } | 666 | } |
| 775 | 667 | ||
| 776 | /* | 668 | /* |
| 777 | * __tipc_connect - connect to a remote peer | 669 | * __tipc_port_connect - connect to a remote peer |
| 778 | * | 670 | * |
| 779 | * Port must be locked. | 671 | * Port must be locked. |
| 780 | */ | 672 | */ |
| 781 | int __tipc_connect(u32 ref, struct tipc_port *p_ptr, | 673 | int __tipc_port_connect(u32 ref, struct tipc_port *p_ptr, |
| 782 | struct tipc_portid const *peer) | 674 | struct tipc_portid const *peer) |
| 783 | { | 675 | { |
| 784 | struct tipc_msg *msg; | 676 | struct tipc_msg *msg; |
| @@ -815,7 +707,7 @@ exit: | |||
| 815 | * | 707 | * |
| 816 | * Port must be locked. | 708 | * Port must be locked. |
| 817 | */ | 709 | */ |
| 818 | int __tipc_disconnect(struct tipc_port *tp_ptr) | 710 | int __tipc_port_disconnect(struct tipc_port *tp_ptr) |
| 819 | { | 711 | { |
| 820 | if (tp_ptr->connected) { | 712 | if (tp_ptr->connected) { |
| 821 | tp_ptr->connected = 0; | 713 | tp_ptr->connected = 0; |
| @@ -828,10 +720,10 @@ int __tipc_disconnect(struct tipc_port *tp_ptr) | |||
| 828 | } | 720 | } |
| 829 | 721 | ||
| 830 | /* | 722 | /* |
| 831 | * tipc_disconnect(): Disconnect port form peer. | 723 | * tipc_port_disconnect(): Disconnect port form peer. |
| 832 | * This is a node local operation. | 724 | * This is a node local operation. |
| 833 | */ | 725 | */ |
| 834 | int tipc_disconnect(u32 ref) | 726 | int tipc_port_disconnect(u32 ref) |
| 835 | { | 727 | { |
| 836 | struct tipc_port *p_ptr; | 728 | struct tipc_port *p_ptr; |
| 837 | int res; | 729 | int res; |
| @@ -839,15 +731,15 @@ int tipc_disconnect(u32 ref) | |||
| 839 | p_ptr = tipc_port_lock(ref); | 731 | p_ptr = tipc_port_lock(ref); |
| 840 | if (!p_ptr) | 732 | if (!p_ptr) |
| 841 | return -EINVAL; | 733 | return -EINVAL; |
| 842 | res = __tipc_disconnect(p_ptr); | 734 | res = __tipc_port_disconnect(p_ptr); |
| 843 | tipc_port_unlock(p_ptr); | 735 | tipc_port_unlock(p_ptr); |
| 844 | return res; | 736 | return res; |
| 845 | } | 737 | } |
| 846 | 738 | ||
| 847 | /* | 739 | /* |
| 848 | * tipc_shutdown(): Send a SHUTDOWN msg to peer and disconnect | 740 | * tipc_port_shutdown(): Send a SHUTDOWN msg to peer and disconnect |
| 849 | */ | 741 | */ |
| 850 | int tipc_shutdown(u32 ref) | 742 | int tipc_port_shutdown(u32 ref) |
| 851 | { | 743 | { |
| 852 | struct tipc_port *p_ptr; | 744 | struct tipc_port *p_ptr; |
| 853 | struct sk_buff *buf = NULL; | 745 | struct sk_buff *buf = NULL; |
| @@ -859,13 +751,13 @@ int tipc_shutdown(u32 ref) | |||
| 859 | buf = port_build_peer_abort_msg(p_ptr, TIPC_CONN_SHUTDOWN); | 751 | buf = port_build_peer_abort_msg(p_ptr, TIPC_CONN_SHUTDOWN); |
| 860 | tipc_port_unlock(p_ptr); | 752 | tipc_port_unlock(p_ptr); |
| 861 | tipc_net_route_msg(buf); | 753 | tipc_net_route_msg(buf); |
| 862 | return tipc_disconnect(ref); | 754 | return tipc_port_disconnect(ref); |
| 863 | } | 755 | } |
| 864 | 756 | ||
| 865 | /** | 757 | /** |
| 866 | * tipc_port_recv_msg - receive message from lower layer and deliver to port user | 758 | * tipc_port_rcv - receive message from lower layer and deliver to port user |
| 867 | */ | 759 | */ |
| 868 | int tipc_port_recv_msg(struct sk_buff *buf) | 760 | int tipc_port_rcv(struct sk_buff *buf) |
| 869 | { | 761 | { |
| 870 | struct tipc_port *p_ptr; | 762 | struct tipc_port *p_ptr; |
| 871 | struct tipc_msg *msg = buf_msg(buf); | 763 | struct tipc_msg *msg = buf_msg(buf); |
| @@ -882,7 +774,7 @@ int tipc_port_recv_msg(struct sk_buff *buf) | |||
| 882 | /* validate destination & pass to port, otherwise reject message */ | 774 | /* validate destination & pass to port, otherwise reject message */ |
| 883 | p_ptr = tipc_port_lock(destport); | 775 | p_ptr = tipc_port_lock(destport); |
| 884 | if (likely(p_ptr)) { | 776 | if (likely(p_ptr)) { |
| 885 | err = p_ptr->dispatcher(p_ptr, buf); | 777 | err = tipc_sk_rcv(&tipc_port_to_sock(p_ptr)->sk, buf); |
| 886 | tipc_port_unlock(p_ptr); | 778 | tipc_port_unlock(p_ptr); |
| 887 | if (likely(!err)) | 779 | if (likely(!err)) |
| 888 | return dsz; | 780 | return dsz; |
| @@ -894,43 +786,43 @@ int tipc_port_recv_msg(struct sk_buff *buf) | |||
| 894 | } | 786 | } |
| 895 | 787 | ||
| 896 | /* | 788 | /* |
| 897 | * tipc_port_recv_sections(): Concatenate and deliver sectioned | 789 | * tipc_port_iovec_rcv: Concatenate and deliver sectioned |
| 898 | * message for this node. | 790 | * message for this node. |
| 899 | */ | 791 | */ |
| 900 | static int tipc_port_recv_sections(struct tipc_port *sender, | 792 | static int tipc_port_iovec_rcv(struct tipc_port *sender, |
| 901 | struct iovec const *msg_sect, | 793 | struct iovec const *msg_sect, |
| 902 | unsigned int len) | 794 | unsigned int len) |
| 903 | { | 795 | { |
| 904 | struct sk_buff *buf; | 796 | struct sk_buff *buf; |
| 905 | int res; | 797 | int res; |
| 906 | 798 | ||
| 907 | res = tipc_msg_build(&sender->phdr, msg_sect, len, MAX_MSG_SIZE, &buf); | 799 | res = tipc_msg_build(&sender->phdr, msg_sect, len, MAX_MSG_SIZE, &buf); |
| 908 | if (likely(buf)) | 800 | if (likely(buf)) |
| 909 | tipc_port_recv_msg(buf); | 801 | tipc_port_rcv(buf); |
| 910 | return res; | 802 | return res; |
| 911 | } | 803 | } |
| 912 | 804 | ||
| 913 | /** | 805 | /** |
| 914 | * tipc_send - send message sections on connection | 806 | * tipc_send - send message sections on connection |
| 915 | */ | 807 | */ |
| 916 | int tipc_send(u32 ref, struct iovec const *msg_sect, unsigned int len) | 808 | int tipc_send(struct tipc_port *p_ptr, |
| 809 | struct iovec const *msg_sect, | ||
| 810 | unsigned int len) | ||
| 917 | { | 811 | { |
| 918 | struct tipc_port *p_ptr; | ||
| 919 | u32 destnode; | 812 | u32 destnode; |
| 920 | int res; | 813 | int res; |
| 921 | 814 | ||
| 922 | p_ptr = tipc_port_deref(ref); | 815 | if (!p_ptr->connected) |
| 923 | if (!p_ptr || !p_ptr->connected) | ||
| 924 | return -EINVAL; | 816 | return -EINVAL; |
| 925 | 817 | ||
| 926 | p_ptr->congested = 1; | 818 | p_ptr->congested = 1; |
| 927 | if (!tipc_port_congested(p_ptr)) { | 819 | if (!tipc_port_congested(p_ptr)) { |
| 928 | destnode = port_peernode(p_ptr); | 820 | destnode = tipc_port_peernode(p_ptr); |
| 929 | if (likely(!in_own_node(destnode))) | 821 | if (likely(!in_own_node(destnode))) |
| 930 | res = tipc_link_send_sections_fast(p_ptr, msg_sect, | 822 | res = tipc_link_iovec_xmit_fast(p_ptr, msg_sect, len, |
| 931 | len, destnode); | 823 | destnode); |
| 932 | else | 824 | else |
| 933 | res = tipc_port_recv_sections(p_ptr, msg_sect, len); | 825 | res = tipc_port_iovec_rcv(p_ptr, msg_sect, len); |
| 934 | 826 | ||
| 935 | if (likely(res != -ELINKCONG)) { | 827 | if (likely(res != -ELINKCONG)) { |
| 936 | p_ptr->congested = 0; | 828 | p_ptr->congested = 0; |
| @@ -939,7 +831,7 @@ int tipc_send(u32 ref, struct iovec const *msg_sect, unsigned int len) | |||
| 939 | return res; | 831 | return res; |
| 940 | } | 832 | } |
| 941 | } | 833 | } |
| 942 | if (port_unreliable(p_ptr)) { | 834 | if (tipc_port_unreliable(p_ptr)) { |
| 943 | p_ptr->congested = 0; | 835 | p_ptr->congested = 0; |
| 944 | return len; | 836 | return len; |
| 945 | } | 837 | } |
| @@ -949,17 +841,18 @@ int tipc_send(u32 ref, struct iovec const *msg_sect, unsigned int len) | |||
| 949 | /** | 841 | /** |
| 950 | * tipc_send2name - send message sections to port name | 842 | * tipc_send2name - send message sections to port name |
| 951 | */ | 843 | */ |
| 952 | int tipc_send2name(u32 ref, struct tipc_name const *name, unsigned int domain, | 844 | int tipc_send2name(struct tipc_port *p_ptr, |
| 953 | struct iovec const *msg_sect, unsigned int len) | 845 | struct tipc_name const *name, |
| 846 | unsigned int domain, | ||
| 847 | struct iovec const *msg_sect, | ||
| 848 | unsigned int len) | ||
| 954 | { | 849 | { |
| 955 | struct tipc_port *p_ptr; | ||
| 956 | struct tipc_msg *msg; | 850 | struct tipc_msg *msg; |
| 957 | u32 destnode = domain; | 851 | u32 destnode = domain; |
| 958 | u32 destport; | 852 | u32 destport; |
| 959 | int res; | 853 | int res; |
| 960 | 854 | ||
| 961 | p_ptr = tipc_port_deref(ref); | 855 | if (p_ptr->connected) |
| 962 | if (!p_ptr || p_ptr->connected) | ||
| 963 | return -EINVAL; | 856 | return -EINVAL; |
| 964 | 857 | ||
| 965 | msg = &p_ptr->phdr; | 858 | msg = &p_ptr->phdr; |
| @@ -974,39 +867,39 @@ int tipc_send2name(u32 ref, struct tipc_name const *name, unsigned int domain, | |||
| 974 | 867 | ||
| 975 | if (likely(destport || destnode)) { | 868 | if (likely(destport || destnode)) { |
| 976 | if (likely(in_own_node(destnode))) | 869 | if (likely(in_own_node(destnode))) |
| 977 | res = tipc_port_recv_sections(p_ptr, msg_sect, len); | 870 | res = tipc_port_iovec_rcv(p_ptr, msg_sect, len); |
| 978 | else if (tipc_own_addr) | 871 | else if (tipc_own_addr) |
| 979 | res = tipc_link_send_sections_fast(p_ptr, msg_sect, | 872 | res = tipc_link_iovec_xmit_fast(p_ptr, msg_sect, len, |
| 980 | len, destnode); | 873 | destnode); |
| 981 | else | 874 | else |
| 982 | res = tipc_port_reject_sections(p_ptr, msg, msg_sect, | 875 | res = tipc_port_iovec_reject(p_ptr, msg, msg_sect, |
| 983 | len, TIPC_ERR_NO_NODE); | 876 | len, TIPC_ERR_NO_NODE); |
| 984 | if (likely(res != -ELINKCONG)) { | 877 | if (likely(res != -ELINKCONG)) { |
| 985 | if (res > 0) | 878 | if (res > 0) |
| 986 | p_ptr->sent++; | 879 | p_ptr->sent++; |
| 987 | return res; | 880 | return res; |
| 988 | } | 881 | } |
| 989 | if (port_unreliable(p_ptr)) { | 882 | if (tipc_port_unreliable(p_ptr)) |
| 990 | return len; | 883 | return len; |
| 991 | } | 884 | |
| 992 | return -ELINKCONG; | 885 | return -ELINKCONG; |
| 993 | } | 886 | } |
| 994 | return tipc_port_reject_sections(p_ptr, msg, msg_sect, len, | 887 | return tipc_port_iovec_reject(p_ptr, msg, msg_sect, len, |
| 995 | TIPC_ERR_NO_NAME); | 888 | TIPC_ERR_NO_NAME); |
| 996 | } | 889 | } |
| 997 | 890 | ||
| 998 | /** | 891 | /** |
| 999 | * tipc_send2port - send message sections to port identity | 892 | * tipc_send2port - send message sections to port identity |
| 1000 | */ | 893 | */ |
| 1001 | int tipc_send2port(u32 ref, struct tipc_portid const *dest, | 894 | int tipc_send2port(struct tipc_port *p_ptr, |
| 1002 | struct iovec const *msg_sect, unsigned int len) | 895 | struct tipc_portid const *dest, |
| 896 | struct iovec const *msg_sect, | ||
| 897 | unsigned int len) | ||
| 1003 | { | 898 | { |
| 1004 | struct tipc_port *p_ptr; | ||
| 1005 | struct tipc_msg *msg; | 899 | struct tipc_msg *msg; |
| 1006 | int res; | 900 | int res; |
| 1007 | 901 | ||
| 1008 | p_ptr = tipc_port_deref(ref); | 902 | if (p_ptr->connected) |
| 1009 | if (!p_ptr || p_ptr->connected) | ||
| 1010 | return -EINVAL; | 903 | return -EINVAL; |
| 1011 | 904 | ||
| 1012 | msg = &p_ptr->phdr; | 905 | msg = &p_ptr->phdr; |
| @@ -1017,20 +910,20 @@ int tipc_send2port(u32 ref, struct tipc_portid const *dest, | |||
| 1017 | msg_set_hdr_sz(msg, BASIC_H_SIZE); | 910 | msg_set_hdr_sz(msg, BASIC_H_SIZE); |
| 1018 | 911 | ||
| 1019 | if (in_own_node(dest->node)) | 912 | if (in_own_node(dest->node)) |
| 1020 | res = tipc_port_recv_sections(p_ptr, msg_sect, len); | 913 | res = tipc_port_iovec_rcv(p_ptr, msg_sect, len); |
| 1021 | else if (tipc_own_addr) | 914 | else if (tipc_own_addr) |
| 1022 | res = tipc_link_send_sections_fast(p_ptr, msg_sect, len, | 915 | res = tipc_link_iovec_xmit_fast(p_ptr, msg_sect, len, |
| 1023 | dest->node); | 916 | dest->node); |
| 1024 | else | 917 | else |
| 1025 | res = tipc_port_reject_sections(p_ptr, msg, msg_sect, len, | 918 | res = tipc_port_iovec_reject(p_ptr, msg, msg_sect, len, |
| 1026 | TIPC_ERR_NO_NODE); | 919 | TIPC_ERR_NO_NODE); |
| 1027 | if (likely(res != -ELINKCONG)) { | 920 | if (likely(res != -ELINKCONG)) { |
| 1028 | if (res > 0) | 921 | if (res > 0) |
| 1029 | p_ptr->sent++; | 922 | p_ptr->sent++; |
| 1030 | return res; | 923 | return res; |
| 1031 | } | 924 | } |
| 1032 | if (port_unreliable(p_ptr)) { | 925 | if (tipc_port_unreliable(p_ptr)) |
| 1033 | return len; | 926 | return len; |
| 1034 | } | 927 | |
| 1035 | return -ELINKCONG; | 928 | return -ELINKCONG; |
| 1036 | } | 929 | } |
diff --git a/net/tipc/port.h b/net/tipc/port.h index 34f12bd4074e..a00397393bd1 100644 --- a/net/tipc/port.h +++ b/net/tipc/port.h | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * net/tipc/port.h: Include file for TIPC port code | 2 | * net/tipc/port.h: Include file for TIPC port code |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 1994-2007, Ericsson AB | 4 | * Copyright (c) 1994-2007, 2014, Ericsson AB |
| 5 | * Copyright (c) 2004-2007, 2010-2013, Wind River Systems | 5 | * Copyright (c) 2004-2007, 2010-2013, Wind River Systems |
| 6 | * All rights reserved. | 6 | * All rights reserved. |
| 7 | * | 7 | * |
| @@ -48,7 +48,6 @@ | |||
| 48 | 48 | ||
| 49 | /** | 49 | /** |
| 50 | * struct tipc_port - TIPC port structure | 50 | * struct tipc_port - TIPC port structure |
| 51 | * @sk: pointer to socket handle | ||
| 52 | * @lock: pointer to spinlock for controlling access to port | 51 | * @lock: pointer to spinlock for controlling access to port |
| 53 | * @connected: non-zero if port is currently connected to a peer port | 52 | * @connected: non-zero if port is currently connected to a peer port |
| 54 | * @conn_type: TIPC type used when connection was established | 53 | * @conn_type: TIPC type used when connection was established |
| @@ -60,8 +59,6 @@ | |||
| 60 | * @ref: unique reference to port in TIPC object registry | 59 | * @ref: unique reference to port in TIPC object registry |
| 61 | * @phdr: preformatted message header used when sending messages | 60 | * @phdr: preformatted message header used when sending messages |
| 62 | * @port_list: adjacent ports in TIPC's global list of ports | 61 | * @port_list: adjacent ports in TIPC's global list of ports |
| 63 | * @dispatcher: ptr to routine which handles received messages | ||
| 64 | * @wakeup: ptr to routine to call when port is no longer congested | ||
| 65 | * @wait_list: adjacent ports in list of ports waiting on link congestion | 62 | * @wait_list: adjacent ports in list of ports waiting on link congestion |
| 66 | * @waiting_pkts: | 63 | * @waiting_pkts: |
| 67 | * @sent: # of non-empty messages sent by port | 64 | * @sent: # of non-empty messages sent by port |
| @@ -74,7 +71,6 @@ | |||
| 74 | * @subscription: "node down" subscription used to terminate failed connections | 71 | * @subscription: "node down" subscription used to terminate failed connections |
| 75 | */ | 72 | */ |
| 76 | struct tipc_port { | 73 | struct tipc_port { |
| 77 | struct sock *sk; | ||
| 78 | spinlock_t *lock; | 74 | spinlock_t *lock; |
| 79 | int connected; | 75 | int connected; |
| 80 | u32 conn_type; | 76 | u32 conn_type; |
| @@ -86,8 +82,6 @@ struct tipc_port { | |||
| 86 | u32 ref; | 82 | u32 ref; |
| 87 | struct tipc_msg phdr; | 83 | struct tipc_msg phdr; |
| 88 | struct list_head port_list; | 84 | struct list_head port_list; |
| 89 | u32 (*dispatcher)(struct tipc_port *, struct sk_buff *); | ||
| 90 | void (*wakeup)(struct tipc_port *); | ||
| 91 | struct list_head wait_list; | 85 | struct list_head wait_list; |
| 92 | u32 waiting_pkts; | 86 | u32 waiting_pkts; |
| 93 | u32 sent; | 87 | u32 sent; |
| @@ -106,68 +100,71 @@ struct tipc_port_list; | |||
| 106 | /* | 100 | /* |
| 107 | * TIPC port manipulation routines | 101 | * TIPC port manipulation routines |
| 108 | */ | 102 | */ |
| 109 | struct tipc_port *tipc_createport(struct sock *sk, | 103 | u32 tipc_port_init(struct tipc_port *p_ptr, |
| 110 | u32 (*dispatcher)(struct tipc_port *, | 104 | const unsigned int importance); |
| 111 | struct sk_buff *), | ||
| 112 | void (*wakeup)(struct tipc_port *), | ||
| 113 | const u32 importance); | ||
| 114 | 105 | ||
| 115 | int tipc_reject_msg(struct sk_buff *buf, u32 err); | 106 | int tipc_reject_msg(struct sk_buff *buf, u32 err); |
| 116 | 107 | ||
| 117 | void tipc_acknowledge(u32 port_ref, u32 ack); | 108 | void tipc_acknowledge(u32 port_ref, u32 ack); |
| 118 | 109 | ||
| 119 | int tipc_deleteport(struct tipc_port *p_ptr); | 110 | void tipc_port_destroy(struct tipc_port *p_ptr); |
| 120 | |||
| 121 | int tipc_portimportance(u32 portref, unsigned int *importance); | ||
| 122 | int tipc_set_portimportance(u32 portref, unsigned int importance); | ||
| 123 | |||
| 124 | int tipc_portunreliable(u32 portref, unsigned int *isunreliable); | ||
| 125 | int tipc_set_portunreliable(u32 portref, unsigned int isunreliable); | ||
| 126 | |||
| 127 | int tipc_portunreturnable(u32 portref, unsigned int *isunreturnable); | ||
| 128 | int tipc_set_portunreturnable(u32 portref, unsigned int isunreturnable); | ||
| 129 | 111 | ||
| 130 | int tipc_publish(struct tipc_port *p_ptr, unsigned int scope, | 112 | int tipc_publish(struct tipc_port *p_ptr, unsigned int scope, |
| 131 | struct tipc_name_seq const *name_seq); | 113 | struct tipc_name_seq const *name_seq); |
| 114 | |||
| 132 | int tipc_withdraw(struct tipc_port *p_ptr, unsigned int scope, | 115 | int tipc_withdraw(struct tipc_port *p_ptr, unsigned int scope, |
| 133 | struct tipc_name_seq const *name_seq); | 116 | struct tipc_name_seq const *name_seq); |
| 134 | 117 | ||
| 135 | int tipc_connect(u32 portref, struct tipc_portid const *port); | 118 | int tipc_port_connect(u32 portref, struct tipc_portid const *port); |
| 136 | 119 | ||
| 137 | int tipc_disconnect(u32 portref); | 120 | int tipc_port_disconnect(u32 portref); |
| 138 | 121 | ||
| 139 | int tipc_shutdown(u32 ref); | 122 | int tipc_port_shutdown(u32 ref); |
| 140 | 123 | ||
| 124 | void tipc_port_wakeup(struct tipc_port *port); | ||
| 141 | 125 | ||
| 142 | /* | 126 | /* |
| 143 | * The following routines require that the port be locked on entry | 127 | * The following routines require that the port be locked on entry |
| 144 | */ | 128 | */ |
| 145 | int __tipc_disconnect(struct tipc_port *tp_ptr); | 129 | int __tipc_port_disconnect(struct tipc_port *tp_ptr); |
| 146 | int __tipc_connect(u32 ref, struct tipc_port *p_ptr, | 130 | int __tipc_port_connect(u32 ref, struct tipc_port *p_ptr, |
| 147 | struct tipc_portid const *peer); | 131 | struct tipc_portid const *peer); |
| 148 | int tipc_port_peer_msg(struct tipc_port *p_ptr, struct tipc_msg *msg); | 132 | int tipc_port_peer_msg(struct tipc_port *p_ptr, struct tipc_msg *msg); |
| 149 | 133 | ||
| 150 | /* | 134 | /* |
| 151 | * TIPC messaging routines | 135 | * TIPC messaging routines |
| 152 | */ | 136 | */ |
| 153 | int tipc_port_recv_msg(struct sk_buff *buf); | 137 | int tipc_port_rcv(struct sk_buff *buf); |
| 154 | int tipc_send(u32 portref, struct iovec const *msg_sect, unsigned int len); | 138 | |
| 155 | 139 | int tipc_send(struct tipc_port *port, | |
| 156 | int tipc_send2name(u32 portref, struct tipc_name const *name, u32 domain, | 140 | struct iovec const *msg_sect, |
| 157 | struct iovec const *msg_sect, unsigned int len); | 141 | unsigned int len); |
| 142 | |||
| 143 | int tipc_send2name(struct tipc_port *port, | ||
| 144 | struct tipc_name const *name, | ||
| 145 | u32 domain, | ||
| 146 | struct iovec const *msg_sect, | ||
| 147 | unsigned int len); | ||
| 148 | |||
| 149 | int tipc_send2port(struct tipc_port *port, | ||
| 150 | struct tipc_portid const *dest, | ||
| 151 | struct iovec const *msg_sect, | ||
| 152 | unsigned int len); | ||
| 153 | |||
| 154 | int tipc_port_mcast_xmit(struct tipc_port *port, | ||
| 155 | struct tipc_name_seq const *seq, | ||
| 156 | struct iovec const *msg, | ||
| 157 | unsigned int len); | ||
| 158 | |||
| 159 | int tipc_port_iovec_reject(struct tipc_port *p_ptr, | ||
| 160 | struct tipc_msg *hdr, | ||
| 161 | struct iovec const *msg_sect, | ||
| 162 | unsigned int len, | ||
| 163 | int err); | ||
| 158 | 164 | ||
| 159 | int tipc_send2port(u32 portref, struct tipc_portid const *dest, | ||
| 160 | struct iovec const *msg_sect, unsigned int len); | ||
| 161 | |||
| 162 | int tipc_multicast(u32 portref, struct tipc_name_seq const *seq, | ||
| 163 | struct iovec const *msg, unsigned int len); | ||
| 164 | |||
| 165 | int tipc_port_reject_sections(struct tipc_port *p_ptr, struct tipc_msg *hdr, | ||
| 166 | struct iovec const *msg_sect, unsigned int len, | ||
| 167 | int err); | ||
| 168 | struct sk_buff *tipc_port_get_ports(void); | 165 | struct sk_buff *tipc_port_get_ports(void); |
| 169 | void tipc_port_recv_proto_msg(struct sk_buff *buf); | 166 | void tipc_port_proto_rcv(struct sk_buff *buf); |
| 170 | void tipc_port_recv_mcast(struct sk_buff *buf, struct tipc_port_list *dp); | 167 | void tipc_port_mcast_rcv(struct sk_buff *buf, struct tipc_port_list *dp); |
| 171 | void tipc_port_reinit(void); | 168 | void tipc_port_reinit(void); |
| 172 | 169 | ||
| 173 | /** | 170 | /** |
| @@ -188,14 +185,53 @@ static inline void tipc_port_unlock(struct tipc_port *p_ptr) | |||
| 188 | spin_unlock_bh(p_ptr->lock); | 185 | spin_unlock_bh(p_ptr->lock); |
| 189 | } | 186 | } |
| 190 | 187 | ||
| 191 | static inline struct tipc_port *tipc_port_deref(u32 ref) | 188 | static inline int tipc_port_congested(struct tipc_port *p_ptr) |
| 192 | { | 189 | { |
| 193 | return (struct tipc_port *)tipc_ref_deref(ref); | 190 | return (p_ptr->sent - p_ptr->acked) >= (TIPC_FLOW_CONTROL_WIN * 2); |
| 194 | } | 191 | } |
| 195 | 192 | ||
| 196 | static inline int tipc_port_congested(struct tipc_port *p_ptr) | 193 | |
| 194 | static inline u32 tipc_port_peernode(struct tipc_port *p_ptr) | ||
| 197 | { | 195 | { |
| 198 | return (p_ptr->sent - p_ptr->acked) >= (TIPC_FLOW_CONTROL_WIN * 2); | 196 | return msg_destnode(&p_ptr->phdr); |
| 197 | } | ||
| 198 | |||
| 199 | static inline u32 tipc_port_peerport(struct tipc_port *p_ptr) | ||
| 200 | { | ||
| 201 | return msg_destport(&p_ptr->phdr); | ||
| 202 | } | ||
| 203 | |||
| 204 | static inline bool tipc_port_unreliable(struct tipc_port *port) | ||
| 205 | { | ||
| 206 | return msg_src_droppable(&port->phdr) != 0; | ||
| 207 | } | ||
| 208 | |||
| 209 | static inline void tipc_port_set_unreliable(struct tipc_port *port, | ||
| 210 | bool unreliable) | ||
| 211 | { | ||
| 212 | msg_set_src_droppable(&port->phdr, unreliable ? 1 : 0); | ||
| 213 | } | ||
| 214 | |||
| 215 | static inline bool tipc_port_unreturnable(struct tipc_port *port) | ||
| 216 | { | ||
| 217 | return msg_dest_droppable(&port->phdr) != 0; | ||
| 218 | } | ||
| 219 | |||
| 220 | static inline void tipc_port_set_unreturnable(struct tipc_port *port, | ||
| 221 | bool unreturnable) | ||
| 222 | { | ||
| 223 | msg_set_dest_droppable(&port->phdr, unreturnable ? 1 : 0); | ||
| 224 | } | ||
| 225 | |||
| 226 | |||
| 227 | static inline int tipc_port_importance(struct tipc_port *port) | ||
| 228 | { | ||
| 229 | return msg_importance(&port->phdr); | ||
| 230 | } | ||
| 231 | |||
| 232 | static inline void tipc_port_set_importance(struct tipc_port *port, int imp) | ||
| 233 | { | ||
| 234 | msg_set_importance(&port->phdr, (u32)imp); | ||
| 199 | } | 235 | } |
| 200 | 236 | ||
| 201 | #endif | 237 | #endif |
diff --git a/net/tipc/ref.c b/net/tipc/ref.c index de3d593e2fee..3d4ecd754eee 100644 --- a/net/tipc/ref.c +++ b/net/tipc/ref.c | |||
| @@ -89,7 +89,7 @@ struct ref_table { | |||
| 89 | 89 | ||
| 90 | static struct ref_table tipc_ref_table; | 90 | static struct ref_table tipc_ref_table; |
| 91 | 91 | ||
| 92 | static DEFINE_RWLOCK(ref_table_lock); | 92 | static DEFINE_SPINLOCK(ref_table_lock); |
| 93 | 93 | ||
| 94 | /** | 94 | /** |
| 95 | * tipc_ref_table_init - create reference table for objects | 95 | * tipc_ref_table_init - create reference table for objects |
| @@ -159,7 +159,7 @@ u32 tipc_ref_acquire(void *object, spinlock_t **lock) | |||
| 159 | } | 159 | } |
| 160 | 160 | ||
| 161 | /* take a free entry, if available; otherwise initialize a new entry */ | 161 | /* take a free entry, if available; otherwise initialize a new entry */ |
| 162 | write_lock_bh(&ref_table_lock); | 162 | spin_lock_bh(&ref_table_lock); |
| 163 | if (tipc_ref_table.first_free) { | 163 | if (tipc_ref_table.first_free) { |
| 164 | index = tipc_ref_table.first_free; | 164 | index = tipc_ref_table.first_free; |
| 165 | entry = &(tipc_ref_table.entries[index]); | 165 | entry = &(tipc_ref_table.entries[index]); |
| @@ -175,7 +175,7 @@ u32 tipc_ref_acquire(void *object, spinlock_t **lock) | |||
| 175 | } else { | 175 | } else { |
| 176 | ref = 0; | 176 | ref = 0; |
| 177 | } | 177 | } |
| 178 | write_unlock_bh(&ref_table_lock); | 178 | spin_unlock_bh(&ref_table_lock); |
| 179 | 179 | ||
| 180 | /* | 180 | /* |
| 181 | * Grab the lock so no one else can modify this entry | 181 | * Grab the lock so no one else can modify this entry |
| @@ -216,7 +216,7 @@ void tipc_ref_discard(u32 ref) | |||
| 216 | index = ref & index_mask; | 216 | index = ref & index_mask; |
| 217 | entry = &(tipc_ref_table.entries[index]); | 217 | entry = &(tipc_ref_table.entries[index]); |
| 218 | 218 | ||
| 219 | write_lock_bh(&ref_table_lock); | 219 | spin_lock_bh(&ref_table_lock); |
| 220 | 220 | ||
| 221 | if (!entry->object) { | 221 | if (!entry->object) { |
| 222 | pr_err("Attempt to discard ref. to non-existent obj\n"); | 222 | pr_err("Attempt to discard ref. to non-existent obj\n"); |
| @@ -242,7 +242,7 @@ void tipc_ref_discard(u32 ref) | |||
| 242 | tipc_ref_table.last_free = index; | 242 | tipc_ref_table.last_free = index; |
| 243 | 243 | ||
| 244 | exit: | 244 | exit: |
| 245 | write_unlock_bh(&ref_table_lock); | 245 | spin_unlock_bh(&ref_table_lock); |
| 246 | } | 246 | } |
| 247 | 247 | ||
| 248 | /** | 248 | /** |
| @@ -264,20 +264,3 @@ void *tipc_ref_lock(u32 ref) | |||
| 264 | } | 264 | } |
| 265 | return NULL; | 265 | return NULL; |
| 266 | } | 266 | } |
| 267 | |||
| 268 | |||
| 269 | /** | ||
| 270 | * tipc_ref_deref - return pointer referenced object (without locking it) | ||
| 271 | */ | ||
| 272 | void *tipc_ref_deref(u32 ref) | ||
| 273 | { | ||
| 274 | if (likely(tipc_ref_table.entries)) { | ||
| 275 | struct reference *entry; | ||
| 276 | |||
| 277 | entry = &tipc_ref_table.entries[ref & | ||
| 278 | tipc_ref_table.index_mask]; | ||
| 279 | if (likely(entry->ref == ref)) | ||
| 280 | return entry->object; | ||
| 281 | } | ||
| 282 | return NULL; | ||
| 283 | } | ||
diff --git a/net/tipc/ref.h b/net/tipc/ref.h index 5bc8e7ab84de..d01aa1df63b8 100644 --- a/net/tipc/ref.h +++ b/net/tipc/ref.h | |||
| @@ -44,6 +44,5 @@ u32 tipc_ref_acquire(void *object, spinlock_t **lock); | |||
| 44 | void tipc_ref_discard(u32 ref); | 44 | void tipc_ref_discard(u32 ref); |
| 45 | 45 | ||
| 46 | void *tipc_ref_lock(u32 ref); | 46 | void *tipc_ref_lock(u32 ref); |
| 47 | void *tipc_ref_deref(u32 ref); | ||
| 48 | 47 | ||
| 49 | #endif | 48 | #endif |
diff --git a/net/tipc/server.c b/net/tipc/server.c index 646a930eefbf..a538a02f869b 100644 --- a/net/tipc/server.c +++ b/net/tipc/server.c | |||
| @@ -119,7 +119,7 @@ static struct tipc_conn *tipc_conn_lookup(struct tipc_server *s, int conid) | |||
| 119 | return con; | 119 | return con; |
| 120 | } | 120 | } |
| 121 | 121 | ||
| 122 | static void sock_data_ready(struct sock *sk, int unused) | 122 | static void sock_data_ready(struct sock *sk) |
| 123 | { | 123 | { |
| 124 | struct tipc_conn *con; | 124 | struct tipc_conn *con; |
| 125 | 125 | ||
| @@ -297,7 +297,7 @@ static int tipc_accept_from_sock(struct tipc_conn *con) | |||
| 297 | newcon->usr_data = s->tipc_conn_new(newcon->conid); | 297 | newcon->usr_data = s->tipc_conn_new(newcon->conid); |
| 298 | 298 | ||
| 299 | /* Wake up receive process in case of 'SYN+' message */ | 299 | /* Wake up receive process in case of 'SYN+' message */ |
| 300 | newsock->sk->sk_data_ready(newsock->sk, 0); | 300 | newsock->sk->sk_data_ready(newsock->sk); |
| 301 | return ret; | 301 | return ret; |
| 302 | } | 302 | } |
| 303 | 303 | ||
diff --git a/net/tipc/socket.c b/net/tipc/socket.c index 0ed0eaa62f29..3c0256962f7d 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c | |||
| @@ -1,7 +1,7 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * net/tipc/socket.c: TIPC socket API | 2 | * net/tipc/socket.c: TIPC socket API |
| 3 | * | 3 | * |
| 4 | * Copyright (c) 2001-2007, 2012 Ericsson AB | 4 | * Copyright (c) 2001-2007, 2012-2014, Ericsson AB |
| 5 | * Copyright (c) 2004-2008, 2010-2013, Wind River Systems | 5 | * Copyright (c) 2004-2008, 2010-2013, Wind River Systems |
| 6 | * All rights reserved. | 6 | * All rights reserved. |
| 7 | * | 7 | * |
| @@ -38,30 +38,17 @@ | |||
| 38 | #include "port.h" | 38 | #include "port.h" |
| 39 | 39 | ||
| 40 | #include <linux/export.h> | 40 | #include <linux/export.h> |
| 41 | #include <net/sock.h> | ||
| 42 | 41 | ||
| 43 | #define SS_LISTENING -1 /* socket is listening */ | 42 | #define SS_LISTENING -1 /* socket is listening */ |
| 44 | #define SS_READY -2 /* socket is connectionless */ | 43 | #define SS_READY -2 /* socket is connectionless */ |
| 45 | 44 | ||
| 46 | #define CONN_TIMEOUT_DEFAULT 8000 /* default connect timeout = 8s */ | 45 | #define CONN_TIMEOUT_DEFAULT 8000 /* default connect timeout = 8s */ |
| 47 | 46 | ||
| 48 | struct tipc_sock { | ||
| 49 | struct sock sk; | ||
| 50 | struct tipc_port *p; | ||
| 51 | struct tipc_portid peer_name; | ||
| 52 | unsigned int conn_timeout; | ||
| 53 | }; | ||
| 54 | |||
| 55 | #define tipc_sk(sk) ((struct tipc_sock *)(sk)) | ||
| 56 | #define tipc_sk_port(sk) (tipc_sk(sk)->p) | ||
| 57 | |||
| 58 | static int backlog_rcv(struct sock *sk, struct sk_buff *skb); | 47 | static int backlog_rcv(struct sock *sk, struct sk_buff *skb); |
| 59 | static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf); | 48 | static void tipc_data_ready(struct sock *sk); |
| 60 | static void wakeupdispatch(struct tipc_port *tport); | ||
| 61 | static void tipc_data_ready(struct sock *sk, int len); | ||
| 62 | static void tipc_write_space(struct sock *sk); | 49 | static void tipc_write_space(struct sock *sk); |
| 63 | static int release(struct socket *sock); | 50 | static int tipc_release(struct socket *sock); |
| 64 | static int accept(struct socket *sock, struct socket *new_sock, int flags); | 51 | static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags); |
| 65 | 52 | ||
| 66 | static const struct proto_ops packet_ops; | 53 | static const struct proto_ops packet_ops; |
| 67 | static const struct proto_ops stream_ops; | 54 | static const struct proto_ops stream_ops; |
| @@ -115,6 +102,8 @@ static struct proto tipc_proto_kern; | |||
| 115 | * - port reference | 102 | * - port reference |
| 116 | */ | 103 | */ |
| 117 | 104 | ||
| 105 | #include "socket.h" | ||
| 106 | |||
| 118 | /** | 107 | /** |
| 119 | * advance_rx_queue - discard first buffer in socket receive queue | 108 | * advance_rx_queue - discard first buffer in socket receive queue |
| 120 | * | 109 | * |
| @@ -150,13 +139,15 @@ static void reject_rx_queue(struct sock *sk) | |||
| 150 | * | 139 | * |
| 151 | * Returns 0 on success, errno otherwise | 140 | * Returns 0 on success, errno otherwise |
| 152 | */ | 141 | */ |
| 153 | static int tipc_sk_create(struct net *net, struct socket *sock, int protocol, | 142 | static int tipc_sk_create(struct net *net, struct socket *sock, |
| 154 | int kern) | 143 | int protocol, int kern) |
| 155 | { | 144 | { |
| 156 | const struct proto_ops *ops; | 145 | const struct proto_ops *ops; |
| 157 | socket_state state; | 146 | socket_state state; |
| 158 | struct sock *sk; | 147 | struct sock *sk; |
| 159 | struct tipc_port *tp_ptr; | 148 | struct tipc_sock *tsk; |
| 149 | struct tipc_port *port; | ||
| 150 | u32 ref; | ||
| 160 | 151 | ||
| 161 | /* Validate arguments */ | 152 | /* Validate arguments */ |
| 162 | if (unlikely(protocol != 0)) | 153 | if (unlikely(protocol != 0)) |
| @@ -189,10 +180,12 @@ static int tipc_sk_create(struct net *net, struct socket *sock, int protocol, | |||
| 189 | if (sk == NULL) | 180 | if (sk == NULL) |
| 190 | return -ENOMEM; | 181 | return -ENOMEM; |
| 191 | 182 | ||
| 192 | /* Allocate TIPC port for socket to use */ | 183 | tsk = tipc_sk(sk); |
| 193 | tp_ptr = tipc_createport(sk, &dispatch, &wakeupdispatch, | 184 | port = &tsk->port; |
| 194 | TIPC_LOW_IMPORTANCE); | 185 | |
| 195 | if (unlikely(!tp_ptr)) { | 186 | ref = tipc_port_init(port, TIPC_LOW_IMPORTANCE); |
| 187 | if (!ref) { | ||
| 188 | pr_warn("Socket registration failed, ref. table exhausted\n"); | ||
| 196 | sk_free(sk); | 189 | sk_free(sk); |
| 197 | return -ENOMEM; | 190 | return -ENOMEM; |
| 198 | } | 191 | } |
| @@ -206,17 +199,14 @@ static int tipc_sk_create(struct net *net, struct socket *sock, int protocol, | |||
| 206 | sk->sk_rcvbuf = sysctl_tipc_rmem[1]; | 199 | sk->sk_rcvbuf = sysctl_tipc_rmem[1]; |
| 207 | sk->sk_data_ready = tipc_data_ready; | 200 | sk->sk_data_ready = tipc_data_ready; |
| 208 | sk->sk_write_space = tipc_write_space; | 201 | sk->sk_write_space = tipc_write_space; |
| 209 | tipc_sk(sk)->p = tp_ptr; | ||
| 210 | tipc_sk(sk)->conn_timeout = CONN_TIMEOUT_DEFAULT; | 202 | tipc_sk(sk)->conn_timeout = CONN_TIMEOUT_DEFAULT; |
| 211 | 203 | tipc_port_unlock(port); | |
| 212 | spin_unlock_bh(tp_ptr->lock); | ||
| 213 | 204 | ||
| 214 | if (sock->state == SS_READY) { | 205 | if (sock->state == SS_READY) { |
| 215 | tipc_set_portunreturnable(tp_ptr->ref, 1); | 206 | tipc_port_set_unreturnable(port, true); |
| 216 | if (sock->type == SOCK_DGRAM) | 207 | if (sock->type == SOCK_DGRAM) |
| 217 | tipc_set_portunreliable(tp_ptr->ref, 1); | 208 | tipc_port_set_unreliable(port, true); |
| 218 | } | 209 | } |
| 219 | |||
| 220 | return 0; | 210 | return 0; |
| 221 | } | 211 | } |
| 222 | 212 | ||
| @@ -254,7 +244,7 @@ int tipc_sock_create_local(int type, struct socket **res) | |||
| 254 | */ | 244 | */ |
| 255 | void tipc_sock_release_local(struct socket *sock) | 245 | void tipc_sock_release_local(struct socket *sock) |
| 256 | { | 246 | { |
| 257 | release(sock); | 247 | tipc_release(sock); |
| 258 | sock->ops = NULL; | 248 | sock->ops = NULL; |
| 259 | sock_release(sock); | 249 | sock_release(sock); |
| 260 | } | 250 | } |
| @@ -280,7 +270,7 @@ int tipc_sock_accept_local(struct socket *sock, struct socket **newsock, | |||
| 280 | if (ret < 0) | 270 | if (ret < 0) |
| 281 | return ret; | 271 | return ret; |
| 282 | 272 | ||
| 283 | ret = accept(sock, *newsock, flags); | 273 | ret = tipc_accept(sock, *newsock, flags); |
| 284 | if (ret < 0) { | 274 | if (ret < 0) { |
| 285 | sock_release(*newsock); | 275 | sock_release(*newsock); |
| 286 | return ret; | 276 | return ret; |
| @@ -290,7 +280,7 @@ int tipc_sock_accept_local(struct socket *sock, struct socket **newsock, | |||
| 290 | } | 280 | } |
| 291 | 281 | ||
| 292 | /** | 282 | /** |
| 293 | * release - destroy a TIPC socket | 283 | * tipc_release - destroy a TIPC socket |
| 294 | * @sock: socket to destroy | 284 | * @sock: socket to destroy |
| 295 | * | 285 | * |
| 296 | * This routine cleans up any messages that are still queued on the socket. | 286 | * This routine cleans up any messages that are still queued on the socket. |
| @@ -305,12 +295,12 @@ int tipc_sock_accept_local(struct socket *sock, struct socket **newsock, | |||
| 305 | * | 295 | * |
| 306 | * Returns 0 on success, errno otherwise | 296 | * Returns 0 on success, errno otherwise |
| 307 | */ | 297 | */ |
| 308 | static int release(struct socket *sock) | 298 | static int tipc_release(struct socket *sock) |
| 309 | { | 299 | { |
| 310 | struct sock *sk = sock->sk; | 300 | struct sock *sk = sock->sk; |
| 311 | struct tipc_port *tport; | 301 | struct tipc_sock *tsk; |
| 302 | struct tipc_port *port; | ||
| 312 | struct sk_buff *buf; | 303 | struct sk_buff *buf; |
| 313 | int res; | ||
| 314 | 304 | ||
| 315 | /* | 305 | /* |
| 316 | * Exit if socket isn't fully initialized (occurs when a failed accept() | 306 | * Exit if socket isn't fully initialized (occurs when a failed accept() |
| @@ -319,7 +309,8 @@ static int release(struct socket *sock) | |||
| 319 | if (sk == NULL) | 309 | if (sk == NULL) |
| 320 | return 0; | 310 | return 0; |
| 321 | 311 | ||
| 322 | tport = tipc_sk_port(sk); | 312 | tsk = tipc_sk(sk); |
| 313 | port = &tsk->port; | ||
| 323 | lock_sock(sk); | 314 | lock_sock(sk); |
| 324 | 315 | ||
| 325 | /* | 316 | /* |
| @@ -336,17 +327,16 @@ static int release(struct socket *sock) | |||
| 336 | if ((sock->state == SS_CONNECTING) || | 327 | if ((sock->state == SS_CONNECTING) || |
| 337 | (sock->state == SS_CONNECTED)) { | 328 | (sock->state == SS_CONNECTED)) { |
| 338 | sock->state = SS_DISCONNECTING; | 329 | sock->state = SS_DISCONNECTING; |
| 339 | tipc_disconnect(tport->ref); | 330 | tipc_port_disconnect(port->ref); |
| 340 | } | 331 | } |
| 341 | tipc_reject_msg(buf, TIPC_ERR_NO_PORT); | 332 | tipc_reject_msg(buf, TIPC_ERR_NO_PORT); |
| 342 | } | 333 | } |
| 343 | } | 334 | } |
| 344 | 335 | ||
| 345 | /* | 336 | /* Destroy TIPC port; also disconnects an active connection and |
| 346 | * Delete TIPC port; this ensures no more messages are queued | 337 | * sends a 'FIN-' to peer. |
| 347 | * (also disconnects an active connection & sends a 'FIN-' to peer) | ||
| 348 | */ | 338 | */ |
| 349 | res = tipc_deleteport(tport); | 339 | tipc_port_destroy(port); |
| 350 | 340 | ||
| 351 | /* Discard any remaining (connection-based) messages in receive queue */ | 341 | /* Discard any remaining (connection-based) messages in receive queue */ |
| 352 | __skb_queue_purge(&sk->sk_receive_queue); | 342 | __skb_queue_purge(&sk->sk_receive_queue); |
| @@ -358,11 +348,11 @@ static int release(struct socket *sock) | |||
| 358 | sock_put(sk); | 348 | sock_put(sk); |
| 359 | sock->sk = NULL; | 349 | sock->sk = NULL; |
| 360 | 350 | ||
| 361 | return res; | 351 | return 0; |
| 362 | } | 352 | } |
| 363 | 353 | ||
| 364 | /** | 354 | /** |
| 365 | * bind - associate or disassocate TIPC name(s) with a socket | 355 | * tipc_bind - associate or disassocate TIPC name(s) with a socket |
| 366 | * @sock: socket structure | 356 | * @sock: socket structure |
| 367 | * @uaddr: socket address describing name(s) and desired operation | 357 | * @uaddr: socket address describing name(s) and desired operation |
| 368 | * @uaddr_len: size of socket address data structure | 358 | * @uaddr_len: size of socket address data structure |
| @@ -376,16 +366,17 @@ static int release(struct socket *sock) | |||
| 376 | * NOTE: This routine doesn't need to take the socket lock since it doesn't | 366 | * NOTE: This routine doesn't need to take the socket lock since it doesn't |
| 377 | * access any non-constant socket information. | 367 | * access any non-constant socket information. |
| 378 | */ | 368 | */ |
| 379 | static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len) | 369 | static int tipc_bind(struct socket *sock, struct sockaddr *uaddr, |
| 370 | int uaddr_len) | ||
| 380 | { | 371 | { |
| 381 | struct sock *sk = sock->sk; | 372 | struct sock *sk = sock->sk; |
| 382 | struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr; | 373 | struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr; |
| 383 | struct tipc_port *tport = tipc_sk_port(sock->sk); | 374 | struct tipc_sock *tsk = tipc_sk(sk); |
| 384 | int res = -EINVAL; | 375 | int res = -EINVAL; |
| 385 | 376 | ||
| 386 | lock_sock(sk); | 377 | lock_sock(sk); |
| 387 | if (unlikely(!uaddr_len)) { | 378 | if (unlikely(!uaddr_len)) { |
| 388 | res = tipc_withdraw(tport, 0, NULL); | 379 | res = tipc_withdraw(&tsk->port, 0, NULL); |
| 389 | goto exit; | 380 | goto exit; |
| 390 | } | 381 | } |
| 391 | 382 | ||
| @@ -413,15 +404,15 @@ static int bind(struct socket *sock, struct sockaddr *uaddr, int uaddr_len) | |||
| 413 | } | 404 | } |
| 414 | 405 | ||
| 415 | res = (addr->scope > 0) ? | 406 | res = (addr->scope > 0) ? |
| 416 | tipc_publish(tport, addr->scope, &addr->addr.nameseq) : | 407 | tipc_publish(&tsk->port, addr->scope, &addr->addr.nameseq) : |
| 417 | tipc_withdraw(tport, -addr->scope, &addr->addr.nameseq); | 408 | tipc_withdraw(&tsk->port, -addr->scope, &addr->addr.nameseq); |
| 418 | exit: | 409 | exit: |
| 419 | release_sock(sk); | 410 | release_sock(sk); |
| 420 | return res; | 411 | return res; |
| 421 | } | 412 | } |
| 422 | 413 | ||
| 423 | /** | 414 | /** |
| 424 | * get_name - get port ID of socket or peer socket | 415 | * tipc_getname - get port ID of socket or peer socket |
| 425 | * @sock: socket structure | 416 | * @sock: socket structure |
| 426 | * @uaddr: area for returned socket address | 417 | * @uaddr: area for returned socket address |
| 427 | * @uaddr_len: area for returned length of socket address | 418 | * @uaddr_len: area for returned length of socket address |
| @@ -433,21 +424,21 @@ exit: | |||
| 433 | * accesses socket information that is unchanging (or which changes in | 424 | * accesses socket information that is unchanging (or which changes in |
| 434 | * a completely predictable manner). | 425 | * a completely predictable manner). |
| 435 | */ | 426 | */ |
| 436 | static int get_name(struct socket *sock, struct sockaddr *uaddr, | 427 | static int tipc_getname(struct socket *sock, struct sockaddr *uaddr, |
| 437 | int *uaddr_len, int peer) | 428 | int *uaddr_len, int peer) |
| 438 | { | 429 | { |
| 439 | struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr; | 430 | struct sockaddr_tipc *addr = (struct sockaddr_tipc *)uaddr; |
| 440 | struct tipc_sock *tsock = tipc_sk(sock->sk); | 431 | struct tipc_sock *tsk = tipc_sk(sock->sk); |
| 441 | 432 | ||
| 442 | memset(addr, 0, sizeof(*addr)); | 433 | memset(addr, 0, sizeof(*addr)); |
| 443 | if (peer) { | 434 | if (peer) { |
| 444 | if ((sock->state != SS_CONNECTED) && | 435 | if ((sock->state != SS_CONNECTED) && |
| 445 | ((peer != 2) || (sock->state != SS_DISCONNECTING))) | 436 | ((peer != 2) || (sock->state != SS_DISCONNECTING))) |
| 446 | return -ENOTCONN; | 437 | return -ENOTCONN; |
| 447 | addr->addr.id.ref = tsock->peer_name.ref; | 438 | addr->addr.id.ref = tipc_port_peerport(&tsk->port); |
| 448 | addr->addr.id.node = tsock->peer_name.node; | 439 | addr->addr.id.node = tipc_port_peernode(&tsk->port); |
| 449 | } else { | 440 | } else { |
| 450 | addr->addr.id.ref = tsock->p->ref; | 441 | addr->addr.id.ref = tsk->port.ref; |
| 451 | addr->addr.id.node = tipc_own_addr; | 442 | addr->addr.id.node = tipc_own_addr; |
| 452 | } | 443 | } |
| 453 | 444 | ||
| @@ -461,7 +452,7 @@ static int get_name(struct socket *sock, struct sockaddr *uaddr, | |||
| 461 | } | 452 | } |
| 462 | 453 | ||
| 463 | /** | 454 | /** |
| 464 | * poll - read and possibly block on pollmask | 455 | * tipc_poll - read and possibly block on pollmask |
| 465 | * @file: file structure associated with the socket | 456 | * @file: file structure associated with the socket |
| 466 | * @sock: socket for which to calculate the poll bits | 457 | * @sock: socket for which to calculate the poll bits |
| 467 | * @wait: ??? | 458 | * @wait: ??? |
| @@ -500,22 +491,23 @@ static int get_name(struct socket *sock, struct sockaddr *uaddr, | |||
| 500 | * imply that the operation will succeed, merely that it should be performed | 491 | * imply that the operation will succeed, merely that it should be performed |
| 501 | * and will not block. | 492 | * and will not block. |
| 502 | */ | 493 | */ |
| 503 | static unsigned int poll(struct file *file, struct socket *sock, | 494 | static unsigned int tipc_poll(struct file *file, struct socket *sock, |
| 504 | poll_table *wait) | 495 | poll_table *wait) |
| 505 | { | 496 | { |
| 506 | struct sock *sk = sock->sk; | 497 | struct sock *sk = sock->sk; |
| 498 | struct tipc_sock *tsk = tipc_sk(sk); | ||
| 507 | u32 mask = 0; | 499 | u32 mask = 0; |
| 508 | 500 | ||
| 509 | sock_poll_wait(file, sk_sleep(sk), wait); | 501 | sock_poll_wait(file, sk_sleep(sk), wait); |
| 510 | 502 | ||
| 511 | switch ((int)sock->state) { | 503 | switch ((int)sock->state) { |
| 512 | case SS_UNCONNECTED: | 504 | case SS_UNCONNECTED: |
| 513 | if (!tipc_sk_port(sk)->congested) | 505 | if (!tsk->port.congested) |
| 514 | mask |= POLLOUT; | 506 | mask |= POLLOUT; |
| 515 | break; | 507 | break; |
| 516 | case SS_READY: | 508 | case SS_READY: |
| 517 | case SS_CONNECTED: | 509 | case SS_CONNECTED: |
| 518 | if (!tipc_sk_port(sk)->congested) | 510 | if (!tsk->port.congested) |
| 519 | mask |= POLLOUT; | 511 | mask |= POLLOUT; |
| 520 | /* fall thru' */ | 512 | /* fall thru' */ |
| 521 | case SS_CONNECTING: | 513 | case SS_CONNECTING: |
| @@ -565,7 +557,7 @@ static int dest_name_check(struct sockaddr_tipc *dest, struct msghdr *m) | |||
| 565 | static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p) | 557 | static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p) |
| 566 | { | 558 | { |
| 567 | struct sock *sk = sock->sk; | 559 | struct sock *sk = sock->sk; |
| 568 | struct tipc_port *tport = tipc_sk_port(sk); | 560 | struct tipc_sock *tsk = tipc_sk(sk); |
| 569 | DEFINE_WAIT(wait); | 561 | DEFINE_WAIT(wait); |
| 570 | int done; | 562 | int done; |
| 571 | 563 | ||
| @@ -581,14 +573,15 @@ static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p) | |||
| 581 | return sock_intr_errno(*timeo_p); | 573 | return sock_intr_errno(*timeo_p); |
| 582 | 574 | ||
| 583 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | 575 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 584 | done = sk_wait_event(sk, timeo_p, !tport->congested); | 576 | done = sk_wait_event(sk, timeo_p, !tsk->port.congested); |
| 585 | finish_wait(sk_sleep(sk), &wait); | 577 | finish_wait(sk_sleep(sk), &wait); |
| 586 | } while (!done); | 578 | } while (!done); |
| 587 | return 0; | 579 | return 0; |
| 588 | } | 580 | } |
| 589 | 581 | ||
| 582 | |||
| 590 | /** | 583 | /** |
| 591 | * send_msg - send message in connectionless manner | 584 | * tipc_sendmsg - send message in connectionless manner |
| 592 | * @iocb: if NULL, indicates that socket lock is already held | 585 | * @iocb: if NULL, indicates that socket lock is already held |
| 593 | * @sock: socket structure | 586 | * @sock: socket structure |
| 594 | * @m: message to send | 587 | * @m: message to send |
| @@ -601,11 +594,12 @@ static int tipc_wait_for_sndmsg(struct socket *sock, long *timeo_p) | |||
| 601 | * | 594 | * |
| 602 | * Returns the number of bytes sent on success, or errno otherwise | 595 | * Returns the number of bytes sent on success, or errno otherwise |
| 603 | */ | 596 | */ |
| 604 | static int send_msg(struct kiocb *iocb, struct socket *sock, | 597 | static int tipc_sendmsg(struct kiocb *iocb, struct socket *sock, |
| 605 | struct msghdr *m, size_t total_len) | 598 | struct msghdr *m, size_t total_len) |
| 606 | { | 599 | { |
| 607 | struct sock *sk = sock->sk; | 600 | struct sock *sk = sock->sk; |
| 608 | struct tipc_port *tport = tipc_sk_port(sk); | 601 | struct tipc_sock *tsk = tipc_sk(sk); |
| 602 | struct tipc_port *port = &tsk->port; | ||
| 609 | DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name); | 603 | DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name); |
| 610 | int needs_conn; | 604 | int needs_conn; |
| 611 | long timeo; | 605 | long timeo; |
| @@ -632,13 +626,13 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, | |||
| 632 | res = -EISCONN; | 626 | res = -EISCONN; |
| 633 | goto exit; | 627 | goto exit; |
| 634 | } | 628 | } |
| 635 | if (tport->published) { | 629 | if (tsk->port.published) { |
| 636 | res = -EOPNOTSUPP; | 630 | res = -EOPNOTSUPP; |
| 637 | goto exit; | 631 | goto exit; |
| 638 | } | 632 | } |
| 639 | if (dest->addrtype == TIPC_ADDR_NAME) { | 633 | if (dest->addrtype == TIPC_ADDR_NAME) { |
| 640 | tport->conn_type = dest->addr.name.name.type; | 634 | tsk->port.conn_type = dest->addr.name.name.type; |
| 641 | tport->conn_instance = dest->addr.name.name.instance; | 635 | tsk->port.conn_instance = dest->addr.name.name.instance; |
| 642 | } | 636 | } |
| 643 | 637 | ||
| 644 | /* Abort any pending connection attempts (very unlikely) */ | 638 | /* Abort any pending connection attempts (very unlikely) */ |
| @@ -651,13 +645,13 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, | |||
| 651 | res = dest_name_check(dest, m); | 645 | res = dest_name_check(dest, m); |
| 652 | if (res) | 646 | if (res) |
| 653 | break; | 647 | break; |
| 654 | res = tipc_send2name(tport->ref, | 648 | res = tipc_send2name(port, |
| 655 | &dest->addr.name.name, | 649 | &dest->addr.name.name, |
| 656 | dest->addr.name.domain, | 650 | dest->addr.name.domain, |
| 657 | m->msg_iov, | 651 | m->msg_iov, |
| 658 | total_len); | 652 | total_len); |
| 659 | } else if (dest->addrtype == TIPC_ADDR_ID) { | 653 | } else if (dest->addrtype == TIPC_ADDR_ID) { |
| 660 | res = tipc_send2port(tport->ref, | 654 | res = tipc_send2port(port, |
| 661 | &dest->addr.id, | 655 | &dest->addr.id, |
| 662 | m->msg_iov, | 656 | m->msg_iov, |
| 663 | total_len); | 657 | total_len); |
| @@ -669,10 +663,10 @@ static int send_msg(struct kiocb *iocb, struct socket *sock, | |||
| 669 | res = dest_name_check(dest, m); | 663 | res = dest_name_check(dest, m); |
| 670 | if (res) | 664 | if (res) |
| 671 | break; | 665 | break; |
| 672 | res = tipc_multicast(tport->ref, | 666 | res = tipc_port_mcast_xmit(port, |
| 673 | &dest->addr.nameseq, | 667 | &dest->addr.nameseq, |
| 674 | m->msg_iov, | 668 | m->msg_iov, |
| 675 | total_len); | 669 | total_len); |
| 676 | } | 670 | } |
| 677 | if (likely(res != -ELINKCONG)) { | 671 | if (likely(res != -ELINKCONG)) { |
| 678 | if (needs_conn && (res >= 0)) | 672 | if (needs_conn && (res >= 0)) |
| @@ -693,7 +687,8 @@ exit: | |||
| 693 | static int tipc_wait_for_sndpkt(struct socket *sock, long *timeo_p) | 687 | static int tipc_wait_for_sndpkt(struct socket *sock, long *timeo_p) |
| 694 | { | 688 | { |
| 695 | struct sock *sk = sock->sk; | 689 | struct sock *sk = sock->sk; |
| 696 | struct tipc_port *tport = tipc_sk_port(sk); | 690 | struct tipc_sock *tsk = tipc_sk(sk); |
| 691 | struct tipc_port *port = &tsk->port; | ||
| 697 | DEFINE_WAIT(wait); | 692 | DEFINE_WAIT(wait); |
| 698 | int done; | 693 | int done; |
| 699 | 694 | ||
| @@ -712,14 +707,14 @@ static int tipc_wait_for_sndpkt(struct socket *sock, long *timeo_p) | |||
| 712 | 707 | ||
| 713 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); | 708 | prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE); |
| 714 | done = sk_wait_event(sk, timeo_p, | 709 | done = sk_wait_event(sk, timeo_p, |
| 715 | (!tport->congested || !tport->connected)); | 710 | (!port->congested || !port->connected)); |
| 716 | finish_wait(sk_sleep(sk), &wait); | 711 | finish_wait(sk_sleep(sk), &wait); |
| 717 | } while (!done); | 712 | } while (!done); |
| 718 | return 0; | 713 | return 0; |
| 719 | } | 714 | } |
| 720 | 715 | ||
| 721 | /** | 716 | /** |
| 722 | * send_packet - send a connection-oriented message | 717 | * tipc_send_packet - send a connection-oriented message |
| 723 | * @iocb: if NULL, indicates that socket lock is already held | 718 | * @iocb: if NULL, indicates that socket lock is already held |
| 724 | * @sock: socket structure | 719 | * @sock: socket structure |
| 725 | * @m: message to send | 720 | * @m: message to send |
| @@ -729,18 +724,18 @@ static int tipc_wait_for_sndpkt(struct socket *sock, long *timeo_p) | |||
| 729 | * | 724 | * |
| 730 | * Returns the number of bytes sent on success, or errno otherwise | 725 | * Returns the number of bytes sent on success, or errno otherwise |
| 731 | */ | 726 | */ |
| 732 | static int send_packet(struct kiocb *iocb, struct socket *sock, | 727 | static int tipc_send_packet(struct kiocb *iocb, struct socket *sock, |
| 733 | struct msghdr *m, size_t total_len) | 728 | struct msghdr *m, size_t total_len) |
| 734 | { | 729 | { |
| 735 | struct sock *sk = sock->sk; | 730 | struct sock *sk = sock->sk; |
| 736 | struct tipc_port *tport = tipc_sk_port(sk); | 731 | struct tipc_sock *tsk = tipc_sk(sk); |
| 737 | DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name); | 732 | DECLARE_SOCKADDR(struct sockaddr_tipc *, dest, m->msg_name); |
| 738 | int res = -EINVAL; | 733 | int res = -EINVAL; |
| 739 | long timeo; | 734 | long timeo; |
| 740 | 735 | ||
| 741 | /* Handle implied connection establishment */ | 736 | /* Handle implied connection establishment */ |
| 742 | if (unlikely(dest)) | 737 | if (unlikely(dest)) |
| 743 | return send_msg(iocb, sock, m, total_len); | 738 | return tipc_sendmsg(iocb, sock, m, total_len); |
| 744 | 739 | ||
| 745 | if (total_len > TIPC_MAX_USER_MSG_SIZE) | 740 | if (total_len > TIPC_MAX_USER_MSG_SIZE) |
| 746 | return -EMSGSIZE; | 741 | return -EMSGSIZE; |
| @@ -758,7 +753,7 @@ static int send_packet(struct kiocb *iocb, struct socket *sock, | |||
| 758 | 753 | ||
| 759 | timeo = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); | 754 | timeo = sock_sndtimeo(sk, m->msg_flags & MSG_DONTWAIT); |
| 760 | do { | 755 | do { |
| 761 | res = tipc_send(tport->ref, m->msg_iov, total_len); | 756 | res = tipc_send(&tsk->port, m->msg_iov, total_len); |
| 762 | if (likely(res != -ELINKCONG)) | 757 | if (likely(res != -ELINKCONG)) |
| 763 | break; | 758 | break; |
| 764 | res = tipc_wait_for_sndpkt(sock, &timeo); | 759 | res = tipc_wait_for_sndpkt(sock, &timeo); |
| @@ -772,7 +767,7 @@ exit: | |||
| 772 | } | 767 | } |
| 773 | 768 | ||
| 774 | /** | 769 | /** |
| 775 | * send_stream - send stream-oriented data | 770 | * tipc_send_stream - send stream-oriented data |
| 776 | * @iocb: (unused) | 771 | * @iocb: (unused) |
| 777 | * @sock: socket structure | 772 | * @sock: socket structure |
| 778 | * @m: data to send | 773 | * @m: data to send |
| @@ -783,11 +778,11 @@ exit: | |||
| 783 | * Returns the number of bytes sent on success (or partial success), | 778 | * Returns the number of bytes sent on success (or partial success), |
| 784 | * or errno if no data sent | 779 | * or errno if no data sent |
| 785 | */ | 780 | */ |
| 786 | static int send_stream(struct kiocb *iocb, struct socket *sock, | 781 | static int tipc_send_stream(struct kiocb *iocb, struct socket *sock, |
| 787 | struct msghdr *m, size_t total_len) | 782 | struct msghdr *m, size_t total_len) |
| 788 | { | 783 | { |
| 789 | struct sock *sk = sock->sk; | 784 | struct sock *sk = sock->sk; |
| 790 | struct tipc_port *tport = tipc_sk_port(sk); | 785 | struct tipc_sock *tsk = tipc_sk(sk); |
| 791 | struct msghdr my_msg; | 786 | struct msghdr my_msg; |
| 792 | struct iovec my_iov; | 787 | struct iovec my_iov; |
| 793 | struct iovec *curr_iov; | 788 | struct iovec *curr_iov; |
| @@ -804,7 +799,7 @@ static int send_stream(struct kiocb *iocb, struct socket *sock, | |||
| 804 | /* Handle special cases where there is no connection */ | 799 | /* Handle special cases where there is no connection */ |
| 805 | if (unlikely(sock->state != SS_CONNECTED)) { | 800 | if (unlikely(sock->state != SS_CONNECTED)) { |
| 806 | if (sock->state == SS_UNCONNECTED) | 801 | if (sock->state == SS_UNCONNECTED) |
| 807 | res = send_packet(NULL, sock, m, total_len); | 802 | res = tipc_send_packet(NULL, sock, m, total_len); |
| 808 | else | 803 | else |
| 809 | res = sock->state == SS_DISCONNECTING ? -EPIPE : -ENOTCONN; | 804 | res = sock->state == SS_DISCONNECTING ? -EPIPE : -ENOTCONN; |
| 810 | goto exit; | 805 | goto exit; |
| @@ -835,21 +830,22 @@ static int send_stream(struct kiocb *iocb, struct socket *sock, | |||
| 835 | my_msg.msg_name = NULL; | 830 | my_msg.msg_name = NULL; |
| 836 | bytes_sent = 0; | 831 | bytes_sent = 0; |
| 837 | 832 | ||
| 838 | hdr_size = msg_hdr_sz(&tport->phdr); | 833 | hdr_size = msg_hdr_sz(&tsk->port.phdr); |
| 839 | 834 | ||
| 840 | while (curr_iovlen--) { | 835 | while (curr_iovlen--) { |
| 841 | curr_start = curr_iov->iov_base; | 836 | curr_start = curr_iov->iov_base; |
| 842 | curr_left = curr_iov->iov_len; | 837 | curr_left = curr_iov->iov_len; |
| 843 | 838 | ||
| 844 | while (curr_left) { | 839 | while (curr_left) { |
| 845 | bytes_to_send = tport->max_pkt - hdr_size; | 840 | bytes_to_send = tsk->port.max_pkt - hdr_size; |
| 846 | if (bytes_to_send > TIPC_MAX_USER_MSG_SIZE) | 841 | if (bytes_to_send > TIPC_MAX_USER_MSG_SIZE) |
| 847 | bytes_to_send = TIPC_MAX_USER_MSG_SIZE; | 842 | bytes_to_send = TIPC_MAX_USER_MSG_SIZE; |
| 848 | if (curr_left < bytes_to_send) | 843 | if (curr_left < bytes_to_send) |
| 849 | bytes_to_send = curr_left; | 844 | bytes_to_send = curr_left; |
| 850 | my_iov.iov_base = curr_start; | 845 | my_iov.iov_base = curr_start; |
| 851 | my_iov.iov_len = bytes_to_send; | 846 | my_iov.iov_len = bytes_to_send; |
| 852 | res = send_packet(NULL, sock, &my_msg, bytes_to_send); | 847 | res = tipc_send_packet(NULL, sock, &my_msg, |
| 848 | bytes_to_send); | ||
| 853 | if (res < 0) { | 849 | if (res < 0) { |
| 854 | if (bytes_sent) | 850 | if (bytes_sent) |
| 855 | res = bytes_sent; | 851 | res = bytes_sent; |
| @@ -870,27 +866,25 @@ exit: | |||
| 870 | 866 | ||
| 871 | /** | 867 | /** |
| 872 | * auto_connect - complete connection setup to a remote port | 868 | * auto_connect - complete connection setup to a remote port |
| 873 | * @sock: socket structure | 869 | * @tsk: tipc socket structure |
| 874 | * @msg: peer's response message | 870 | * @msg: peer's response message |
| 875 | * | 871 | * |
| 876 | * Returns 0 on success, errno otherwise | 872 | * Returns 0 on success, errno otherwise |
| 877 | */ | 873 | */ |
| 878 | static int auto_connect(struct socket *sock, struct tipc_msg *msg) | 874 | static int auto_connect(struct tipc_sock *tsk, struct tipc_msg *msg) |
| 879 | { | 875 | { |
| 880 | struct tipc_sock *tsock = tipc_sk(sock->sk); | 876 | struct tipc_port *port = &tsk->port; |
| 881 | struct tipc_port *p_ptr; | 877 | struct socket *sock = tsk->sk.sk_socket; |
| 878 | struct tipc_portid peer; | ||
| 882 | 879 | ||
| 883 | tsock->peer_name.ref = msg_origport(msg); | 880 | peer.ref = msg_origport(msg); |
| 884 | tsock->peer_name.node = msg_orignode(msg); | 881 | peer.node = msg_orignode(msg); |
| 885 | p_ptr = tipc_port_deref(tsock->p->ref); | ||
| 886 | if (!p_ptr) | ||
| 887 | return -EINVAL; | ||
| 888 | 882 | ||
| 889 | __tipc_connect(tsock->p->ref, p_ptr, &tsock->peer_name); | 883 | __tipc_port_connect(port->ref, port, &peer); |
| 890 | 884 | ||
| 891 | if (msg_importance(msg) > TIPC_CRITICAL_IMPORTANCE) | 885 | if (msg_importance(msg) > TIPC_CRITICAL_IMPORTANCE) |
| 892 | return -EINVAL; | 886 | return -EINVAL; |
| 893 | msg_set_importance(&p_ptr->phdr, (u32)msg_importance(msg)); | 887 | msg_set_importance(&port->phdr, (u32)msg_importance(msg)); |
| 894 | sock->state = SS_CONNECTED; | 888 | sock->state = SS_CONNECTED; |
| 895 | return 0; | 889 | return 0; |
| 896 | } | 890 | } |
| @@ -1021,7 +1015,7 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long timeo) | |||
| 1021 | } | 1015 | } |
| 1022 | 1016 | ||
| 1023 | /** | 1017 | /** |
| 1024 | * recv_msg - receive packet-oriented message | 1018 | * tipc_recvmsg - receive packet-oriented message |
| 1025 | * @iocb: (unused) | 1019 | * @iocb: (unused) |
| 1026 | * @m: descriptor for message info | 1020 | * @m: descriptor for message info |
| 1027 | * @buf_len: total size of user buffer area | 1021 | * @buf_len: total size of user buffer area |
| @@ -1032,11 +1026,12 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long timeo) | |||
| 1032 | * | 1026 | * |
| 1033 | * Returns size of returned message data, errno otherwise | 1027 | * Returns size of returned message data, errno otherwise |
| 1034 | */ | 1028 | */ |
| 1035 | static int recv_msg(struct kiocb *iocb, struct socket *sock, | 1029 | static int tipc_recvmsg(struct kiocb *iocb, struct socket *sock, |
| 1036 | struct msghdr *m, size_t buf_len, int flags) | 1030 | struct msghdr *m, size_t buf_len, int flags) |
| 1037 | { | 1031 | { |
| 1038 | struct sock *sk = sock->sk; | 1032 | struct sock *sk = sock->sk; |
| 1039 | struct tipc_port *tport = tipc_sk_port(sk); | 1033 | struct tipc_sock *tsk = tipc_sk(sk); |
| 1034 | struct tipc_port *port = &tsk->port; | ||
| 1040 | struct sk_buff *buf; | 1035 | struct sk_buff *buf; |
| 1041 | struct tipc_msg *msg; | 1036 | struct tipc_msg *msg; |
| 1042 | long timeo; | 1037 | long timeo; |
| @@ -1079,7 +1074,7 @@ restart: | |||
| 1079 | set_orig_addr(m, msg); | 1074 | set_orig_addr(m, msg); |
| 1080 | 1075 | ||
| 1081 | /* Capture ancillary data (optional) */ | 1076 | /* Capture ancillary data (optional) */ |
| 1082 | res = anc_data_recv(m, msg, tport); | 1077 | res = anc_data_recv(m, msg, port); |
| 1083 | if (res) | 1078 | if (res) |
| 1084 | goto exit; | 1079 | goto exit; |
| 1085 | 1080 | ||
| @@ -1105,8 +1100,8 @@ restart: | |||
| 1105 | /* Consume received message (optional) */ | 1100 | /* Consume received message (optional) */ |
| 1106 | if (likely(!(flags & MSG_PEEK))) { | 1101 | if (likely(!(flags & MSG_PEEK))) { |
| 1107 | if ((sock->state != SS_READY) && | 1102 | if ((sock->state != SS_READY) && |
| 1108 | (++tport->conn_unacked >= TIPC_FLOW_CONTROL_WIN)) | 1103 | (++port->conn_unacked >= TIPC_FLOW_CONTROL_WIN)) |
| 1109 | tipc_acknowledge(tport->ref, tport->conn_unacked); | 1104 | tipc_acknowledge(port->ref, port->conn_unacked); |
| 1110 | advance_rx_queue(sk); | 1105 | advance_rx_queue(sk); |
| 1111 | } | 1106 | } |
| 1112 | exit: | 1107 | exit: |
| @@ -1115,7 +1110,7 @@ exit: | |||
| 1115 | } | 1110 | } |
| 1116 | 1111 | ||
| 1117 | /** | 1112 | /** |
| 1118 | * recv_stream - receive stream-oriented data | 1113 | * tipc_recv_stream - receive stream-oriented data |
| 1119 | * @iocb: (unused) | 1114 | * @iocb: (unused) |
| 1120 | * @m: descriptor for message info | 1115 | * @m: descriptor for message info |
| 1121 | * @buf_len: total size of user buffer area | 1116 | * @buf_len: total size of user buffer area |
| @@ -1126,11 +1121,12 @@ exit: | |||
| 1126 | * | 1121 | * |
| 1127 | * Returns size of returned message data, errno otherwise | 1122 | * Returns size of returned message data, errno otherwise |
| 1128 | */ | 1123 | */ |
| 1129 | static int recv_stream(struct kiocb *iocb, struct socket *sock, | 1124 | static int tipc_recv_stream(struct kiocb *iocb, struct socket *sock, |
| 1130 | struct msghdr *m, size_t buf_len, int flags) | 1125 | struct msghdr *m, size_t buf_len, int flags) |
| 1131 | { | 1126 | { |
| 1132 | struct sock *sk = sock->sk; | 1127 | struct sock *sk = sock->sk; |
| 1133 | struct tipc_port *tport = tipc_sk_port(sk); | 1128 | struct tipc_sock *tsk = tipc_sk(sk); |
| 1129 | struct tipc_port *port = &tsk->port; | ||
| 1134 | struct sk_buff *buf; | 1130 | struct sk_buff *buf; |
| 1135 | struct tipc_msg *msg; | 1131 | struct tipc_msg *msg; |
| 1136 | long timeo; | 1132 | long timeo; |
| @@ -1175,7 +1171,7 @@ restart: | |||
| 1175 | /* Optionally capture sender's address & ancillary data of first msg */ | 1171 | /* Optionally capture sender's address & ancillary data of first msg */ |
| 1176 | if (sz_copied == 0) { | 1172 | if (sz_copied == 0) { |
| 1177 | set_orig_addr(m, msg); | 1173 | set_orig_addr(m, msg); |
| 1178 | res = anc_data_recv(m, msg, tport); | 1174 | res = anc_data_recv(m, msg, port); |
| 1179 | if (res) | 1175 | if (res) |
| 1180 | goto exit; | 1176 | goto exit; |
| 1181 | } | 1177 | } |
| @@ -1213,8 +1209,8 @@ restart: | |||
| 1213 | 1209 | ||
| 1214 | /* Consume received message (optional) */ | 1210 | /* Consume received message (optional) */ |
| 1215 | if (likely(!(flags & MSG_PEEK))) { | 1211 | if (likely(!(flags & MSG_PEEK))) { |
| 1216 | if (unlikely(++tport->conn_unacked >= TIPC_FLOW_CONTROL_WIN)) | 1212 | if (unlikely(++port->conn_unacked >= TIPC_FLOW_CONTROL_WIN)) |
| 1217 | tipc_acknowledge(tport->ref, tport->conn_unacked); | 1213 | tipc_acknowledge(port->ref, port->conn_unacked); |
| 1218 | advance_rx_queue(sk); | 1214 | advance_rx_queue(sk); |
| 1219 | } | 1215 | } |
| 1220 | 1216 | ||
| @@ -1252,7 +1248,7 @@ static void tipc_write_space(struct sock *sk) | |||
| 1252 | * @sk: socket | 1248 | * @sk: socket |
| 1253 | * @len: the length of messages | 1249 | * @len: the length of messages |
| 1254 | */ | 1250 | */ |
| 1255 | static void tipc_data_ready(struct sock *sk, int len) | 1251 | static void tipc_data_ready(struct sock *sk) |
| 1256 | { | 1252 | { |
| 1257 | struct socket_wq *wq; | 1253 | struct socket_wq *wq; |
| 1258 | 1254 | ||
| @@ -1266,17 +1262,19 @@ static void tipc_data_ready(struct sock *sk, int len) | |||
| 1266 | 1262 | ||
| 1267 | /** | 1263 | /** |
| 1268 | * filter_connect - Handle all incoming messages for a connection-based socket | 1264 | * filter_connect - Handle all incoming messages for a connection-based socket |
| 1269 | * @tsock: TIPC socket | 1265 | * @tsk: TIPC socket |
| 1270 | * @msg: message | 1266 | * @msg: message |
| 1271 | * | 1267 | * |
| 1272 | * Returns TIPC error status code and socket error status code | 1268 | * Returns TIPC error status code and socket error status code |
| 1273 | * once it encounters some errors | 1269 | * once it encounters some errors |
| 1274 | */ | 1270 | */ |
| 1275 | static u32 filter_connect(struct tipc_sock *tsock, struct sk_buff **buf) | 1271 | static u32 filter_connect(struct tipc_sock *tsk, struct sk_buff **buf) |
| 1276 | { | 1272 | { |
| 1277 | struct socket *sock = tsock->sk.sk_socket; | 1273 | struct sock *sk = &tsk->sk; |
| 1274 | struct tipc_port *port = &tsk->port; | ||
| 1275 | struct socket *sock = sk->sk_socket; | ||
| 1278 | struct tipc_msg *msg = buf_msg(*buf); | 1276 | struct tipc_msg *msg = buf_msg(*buf); |
| 1279 | struct sock *sk = &tsock->sk; | 1277 | |
| 1280 | u32 retval = TIPC_ERR_NO_PORT; | 1278 | u32 retval = TIPC_ERR_NO_PORT; |
| 1281 | int res; | 1279 | int res; |
| 1282 | 1280 | ||
| @@ -1286,10 +1284,10 @@ static u32 filter_connect(struct tipc_sock *tsock, struct sk_buff **buf) | |||
| 1286 | switch ((int)sock->state) { | 1284 | switch ((int)sock->state) { |
| 1287 | case SS_CONNECTED: | 1285 | case SS_CONNECTED: |
| 1288 | /* Accept only connection-based messages sent by peer */ | 1286 | /* Accept only connection-based messages sent by peer */ |
| 1289 | if (msg_connected(msg) && tipc_port_peer_msg(tsock->p, msg)) { | 1287 | if (msg_connected(msg) && tipc_port_peer_msg(port, msg)) { |
| 1290 | if (unlikely(msg_errcode(msg))) { | 1288 | if (unlikely(msg_errcode(msg))) { |
| 1291 | sock->state = SS_DISCONNECTING; | 1289 | sock->state = SS_DISCONNECTING; |
| 1292 | __tipc_disconnect(tsock->p); | 1290 | __tipc_port_disconnect(port); |
| 1293 | } | 1291 | } |
| 1294 | retval = TIPC_OK; | 1292 | retval = TIPC_OK; |
| 1295 | } | 1293 | } |
| @@ -1306,7 +1304,7 @@ static u32 filter_connect(struct tipc_sock *tsock, struct sk_buff **buf) | |||
| 1306 | if (unlikely(!msg_connected(msg))) | 1304 | if (unlikely(!msg_connected(msg))) |
| 1307 | break; | 1305 | break; |
| 1308 | 1306 | ||
| 1309 | res = auto_connect(sock, msg); | 1307 | res = auto_connect(tsk, msg); |
| 1310 | if (res) { | 1308 | if (res) { |
| 1311 | sock->state = SS_DISCONNECTING; | 1309 | sock->state = SS_DISCONNECTING; |
| 1312 | sk->sk_err = -res; | 1310 | sk->sk_err = -res; |
| @@ -1385,6 +1383,7 @@ static unsigned int rcvbuf_limit(struct sock *sk, struct sk_buff *buf) | |||
| 1385 | static u32 filter_rcv(struct sock *sk, struct sk_buff *buf) | 1383 | static u32 filter_rcv(struct sock *sk, struct sk_buff *buf) |
| 1386 | { | 1384 | { |
| 1387 | struct socket *sock = sk->sk_socket; | 1385 | struct socket *sock = sk->sk_socket; |
| 1386 | struct tipc_sock *tsk = tipc_sk(sk); | ||
| 1388 | struct tipc_msg *msg = buf_msg(buf); | 1387 | struct tipc_msg *msg = buf_msg(buf); |
| 1389 | unsigned int limit = rcvbuf_limit(sk, buf); | 1388 | unsigned int limit = rcvbuf_limit(sk, buf); |
| 1390 | u32 res = TIPC_OK; | 1389 | u32 res = TIPC_OK; |
| @@ -1397,7 +1396,7 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf) | |||
| 1397 | if (msg_connected(msg)) | 1396 | if (msg_connected(msg)) |
| 1398 | return TIPC_ERR_NO_PORT; | 1397 | return TIPC_ERR_NO_PORT; |
| 1399 | } else { | 1398 | } else { |
| 1400 | res = filter_connect(tipc_sk(sk), &buf); | 1399 | res = filter_connect(tsk, &buf); |
| 1401 | if (res != TIPC_OK || buf == NULL) | 1400 | if (res != TIPC_OK || buf == NULL) |
| 1402 | return res; | 1401 | return res; |
| 1403 | } | 1402 | } |
| @@ -1411,7 +1410,7 @@ static u32 filter_rcv(struct sock *sk, struct sk_buff *buf) | |||
| 1411 | __skb_queue_tail(&sk->sk_receive_queue, buf); | 1410 | __skb_queue_tail(&sk->sk_receive_queue, buf); |
| 1412 | skb_set_owner_r(buf, sk); | 1411 | skb_set_owner_r(buf, sk); |
| 1413 | 1412 | ||
| 1414 | sk->sk_data_ready(sk, 0); | 1413 | sk->sk_data_ready(sk); |
| 1415 | return TIPC_OK; | 1414 | return TIPC_OK; |
| 1416 | } | 1415 | } |
| 1417 | 1416 | ||
| @@ -1435,17 +1434,16 @@ static int backlog_rcv(struct sock *sk, struct sk_buff *buf) | |||
| 1435 | } | 1434 | } |
| 1436 | 1435 | ||
| 1437 | /** | 1436 | /** |
| 1438 | * dispatch - handle incoming message | 1437 | * tipc_sk_rcv - handle incoming message |
| 1439 | * @tport: TIPC port that received message | 1438 | * @sk: socket receiving message |
| 1440 | * @buf: message | 1439 | * @buf: message |
| 1441 | * | 1440 | * |
| 1442 | * Called with port lock already taken. | 1441 | * Called with port lock already taken. |
| 1443 | * | 1442 | * |
| 1444 | * Returns TIPC error status code (TIPC_OK if message is not to be rejected) | 1443 | * Returns TIPC error status code (TIPC_OK if message is not to be rejected) |
| 1445 | */ | 1444 | */ |
| 1446 | static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf) | 1445 | u32 tipc_sk_rcv(struct sock *sk, struct sk_buff *buf) |
| 1447 | { | 1446 | { |
| 1448 | struct sock *sk = tport->sk; | ||
| 1449 | u32 res; | 1447 | u32 res; |
| 1450 | 1448 | ||
| 1451 | /* | 1449 | /* |
| @@ -1468,19 +1466,6 @@ static u32 dispatch(struct tipc_port *tport, struct sk_buff *buf) | |||
| 1468 | return res; | 1466 | return res; |
| 1469 | } | 1467 | } |
| 1470 | 1468 | ||
| 1471 | /** | ||
| 1472 | * wakeupdispatch - wake up port after congestion | ||
| 1473 | * @tport: port to wakeup | ||
| 1474 | * | ||
| 1475 | * Called with port lock already taken. | ||
| 1476 | */ | ||
| 1477 | static void wakeupdispatch(struct tipc_port *tport) | ||
| 1478 | { | ||
| 1479 | struct sock *sk = tport->sk; | ||
| 1480 | |||
| 1481 | sk->sk_write_space(sk); | ||
| 1482 | } | ||
| 1483 | |||
| 1484 | static int tipc_wait_for_connect(struct socket *sock, long *timeo_p) | 1469 | static int tipc_wait_for_connect(struct socket *sock, long *timeo_p) |
| 1485 | { | 1470 | { |
| 1486 | struct sock *sk = sock->sk; | 1471 | struct sock *sk = sock->sk; |
| @@ -1504,7 +1489,7 @@ static int tipc_wait_for_connect(struct socket *sock, long *timeo_p) | |||
| 1504 | } | 1489 | } |
| 1505 | 1490 | ||
| 1506 | /** | 1491 | /** |
| 1507 | * connect - establish a connection to another TIPC port | 1492 | * tipc_connect - establish a connection to another TIPC port |
| 1508 | * @sock: socket structure | 1493 | * @sock: socket structure |
| 1509 | * @dest: socket address for destination port | 1494 | * @dest: socket address for destination port |
| 1510 | * @destlen: size of socket address data structure | 1495 | * @destlen: size of socket address data structure |
| @@ -1512,8 +1497,8 @@ static int tipc_wait_for_connect(struct socket *sock, long *timeo_p) | |||
| 1512 | * | 1497 | * |
| 1513 | * Returns 0 on success, errno otherwise | 1498 | * Returns 0 on success, errno otherwise |
| 1514 | */ | 1499 | */ |
| 1515 | static int connect(struct socket *sock, struct sockaddr *dest, int destlen, | 1500 | static int tipc_connect(struct socket *sock, struct sockaddr *dest, |
| 1516 | int flags) | 1501 | int destlen, int flags) |
| 1517 | { | 1502 | { |
| 1518 | struct sock *sk = sock->sk; | 1503 | struct sock *sk = sock->sk; |
| 1519 | struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest; | 1504 | struct sockaddr_tipc *dst = (struct sockaddr_tipc *)dest; |
| @@ -1554,7 +1539,7 @@ static int connect(struct socket *sock, struct sockaddr *dest, int destlen, | |||
| 1554 | if (!timeout) | 1539 | if (!timeout) |
| 1555 | m.msg_flags = MSG_DONTWAIT; | 1540 | m.msg_flags = MSG_DONTWAIT; |
| 1556 | 1541 | ||
| 1557 | res = send_msg(NULL, sock, &m, 0); | 1542 | res = tipc_sendmsg(NULL, sock, &m, 0); |
| 1558 | if ((res < 0) && (res != -EWOULDBLOCK)) | 1543 | if ((res < 0) && (res != -EWOULDBLOCK)) |
| 1559 | goto exit; | 1544 | goto exit; |
| 1560 | 1545 | ||
| @@ -1585,13 +1570,13 @@ exit: | |||
| 1585 | } | 1570 | } |
| 1586 | 1571 | ||
| 1587 | /** | 1572 | /** |
| 1588 | * listen - allow socket to listen for incoming connections | 1573 | * tipc_listen - allow socket to listen for incoming connections |
| 1589 | * @sock: socket structure | 1574 | * @sock: socket structure |
| 1590 | * @len: (unused) | 1575 | * @len: (unused) |
| 1591 | * | 1576 | * |
| 1592 | * Returns 0 on success, errno otherwise | 1577 | * Returns 0 on success, errno otherwise |
| 1593 | */ | 1578 | */ |
| 1594 | static int listen(struct socket *sock, int len) | 1579 | static int tipc_listen(struct socket *sock, int len) |
| 1595 | { | 1580 | { |
| 1596 | struct sock *sk = sock->sk; | 1581 | struct sock *sk = sock->sk; |
| 1597 | int res; | 1582 | int res; |
| @@ -1646,20 +1631,20 @@ static int tipc_wait_for_accept(struct socket *sock, long timeo) | |||
| 1646 | } | 1631 | } |
| 1647 | 1632 | ||
| 1648 | /** | 1633 | /** |
| 1649 | * accept - wait for connection request | 1634 | * tipc_accept - wait for connection request |
| 1650 | * @sock: listening socket | 1635 | * @sock: listening socket |
| 1651 | * @newsock: new socket that is to be connected | 1636 | * @newsock: new socket that is to be connected |
| 1652 | * @flags: file-related flags associated with socket | 1637 | * @flags: file-related flags associated with socket |
| 1653 | * | 1638 | * |
| 1654 | * Returns 0 on success, errno otherwise | 1639 | * Returns 0 on success, errno otherwise |
| 1655 | */ | 1640 | */ |
| 1656 | static int accept(struct socket *sock, struct socket *new_sock, int flags) | 1641 | static int tipc_accept(struct socket *sock, struct socket *new_sock, int flags) |
| 1657 | { | 1642 | { |
| 1658 | struct sock *new_sk, *sk = sock->sk; | 1643 | struct sock *new_sk, *sk = sock->sk; |
| 1659 | struct sk_buff *buf; | 1644 | struct sk_buff *buf; |
| 1660 | struct tipc_sock *new_tsock; | 1645 | struct tipc_port *new_port; |
| 1661 | struct tipc_port *new_tport; | ||
| 1662 | struct tipc_msg *msg; | 1646 | struct tipc_msg *msg; |
| 1647 | struct tipc_portid peer; | ||
| 1663 | u32 new_ref; | 1648 | u32 new_ref; |
| 1664 | long timeo; | 1649 | long timeo; |
| 1665 | int res; | 1650 | int res; |
| @@ -1670,7 +1655,6 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags) | |||
| 1670 | res = -EINVAL; | 1655 | res = -EINVAL; |
| 1671 | goto exit; | 1656 | goto exit; |
| 1672 | } | 1657 | } |
| 1673 | |||
| 1674 | timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); | 1658 | timeo = sock_rcvtimeo(sk, flags & O_NONBLOCK); |
| 1675 | res = tipc_wait_for_accept(sock, timeo); | 1659 | res = tipc_wait_for_accept(sock, timeo); |
| 1676 | if (res) | 1660 | if (res) |
| @@ -1683,9 +1667,8 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags) | |||
| 1683 | goto exit; | 1667 | goto exit; |
| 1684 | 1668 | ||
| 1685 | new_sk = new_sock->sk; | 1669 | new_sk = new_sock->sk; |
| 1686 | new_tsock = tipc_sk(new_sk); | 1670 | new_port = &tipc_sk(new_sk)->port; |
| 1687 | new_tport = new_tsock->p; | 1671 | new_ref = new_port->ref; |
| 1688 | new_ref = new_tport->ref; | ||
| 1689 | msg = buf_msg(buf); | 1672 | msg = buf_msg(buf); |
| 1690 | 1673 | ||
| 1691 | /* we lock on new_sk; but lockdep sees the lock on sk */ | 1674 | /* we lock on new_sk; but lockdep sees the lock on sk */ |
| @@ -1698,15 +1681,15 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags) | |||
| 1698 | reject_rx_queue(new_sk); | 1681 | reject_rx_queue(new_sk); |
| 1699 | 1682 | ||
| 1700 | /* Connect new socket to it's peer */ | 1683 | /* Connect new socket to it's peer */ |
| 1701 | new_tsock->peer_name.ref = msg_origport(msg); | 1684 | peer.ref = msg_origport(msg); |
| 1702 | new_tsock->peer_name.node = msg_orignode(msg); | 1685 | peer.node = msg_orignode(msg); |
| 1703 | tipc_connect(new_ref, &new_tsock->peer_name); | 1686 | tipc_port_connect(new_ref, &peer); |
| 1704 | new_sock->state = SS_CONNECTED; | 1687 | new_sock->state = SS_CONNECTED; |
| 1705 | 1688 | ||
| 1706 | tipc_set_portimportance(new_ref, msg_importance(msg)); | 1689 | tipc_port_set_importance(new_port, msg_importance(msg)); |
| 1707 | if (msg_named(msg)) { | 1690 | if (msg_named(msg)) { |
| 1708 | new_tport->conn_type = msg_nametype(msg); | 1691 | new_port->conn_type = msg_nametype(msg); |
| 1709 | new_tport->conn_instance = msg_nameinst(msg); | 1692 | new_port->conn_instance = msg_nameinst(msg); |
| 1710 | } | 1693 | } |
| 1711 | 1694 | ||
| 1712 | /* | 1695 | /* |
| @@ -1717,21 +1700,20 @@ static int accept(struct socket *sock, struct socket *new_sock, int flags) | |||
| 1717 | struct msghdr m = {NULL,}; | 1700 | struct msghdr m = {NULL,}; |
| 1718 | 1701 | ||
| 1719 | advance_rx_queue(sk); | 1702 | advance_rx_queue(sk); |
| 1720 | send_packet(NULL, new_sock, &m, 0); | 1703 | tipc_send_packet(NULL, new_sock, &m, 0); |
| 1721 | } else { | 1704 | } else { |
| 1722 | __skb_dequeue(&sk->sk_receive_queue); | 1705 | __skb_dequeue(&sk->sk_receive_queue); |
| 1723 | __skb_queue_head(&new_sk->sk_receive_queue, buf); | 1706 | __skb_queue_head(&new_sk->sk_receive_queue, buf); |
| 1724 | skb_set_owner_r(buf, new_sk); | 1707 | skb_set_owner_r(buf, new_sk); |
| 1725 | } | 1708 | } |
| 1726 | release_sock(new_sk); | 1709 | release_sock(new_sk); |
| 1727 | |||
| 1728 | exit: | 1710 | exit: |
| 1729 | release_sock(sk); | 1711 | release_sock(sk); |
| 1730 | return res; | 1712 | return res; |
| 1731 | } | 1713 | } |
| 1732 | 1714 | ||
| 1733 | /** | 1715 | /** |
| 1734 | * shutdown - shutdown socket connection | 1716 | * tipc_shutdown - shutdown socket connection |
| 1735 | * @sock: socket structure | 1717 | * @sock: socket structure |
| 1736 | * @how: direction to close (must be SHUT_RDWR) | 1718 | * @how: direction to close (must be SHUT_RDWR) |
| 1737 | * | 1719 | * |
| @@ -1739,10 +1721,11 @@ exit: | |||
| 1739 | * | 1721 | * |
| 1740 | * Returns 0 on success, errno otherwise | 1722 | * Returns 0 on success, errno otherwise |
| 1741 | */ | 1723 | */ |
| 1742 | static int shutdown(struct socket *sock, int how) | 1724 | static int tipc_shutdown(struct socket *sock, int how) |
| 1743 | { | 1725 | { |
| 1744 | struct sock *sk = sock->sk; | 1726 | struct sock *sk = sock->sk; |
| 1745 | struct tipc_port *tport = tipc_sk_port(sk); | 1727 | struct tipc_sock *tsk = tipc_sk(sk); |
| 1728 | struct tipc_port *port = &tsk->port; | ||
| 1746 | struct sk_buff *buf; | 1729 | struct sk_buff *buf; |
| 1747 | int res; | 1730 | int res; |
| 1748 | 1731 | ||
| @@ -1763,10 +1746,10 @@ restart: | |||
| 1763 | kfree_skb(buf); | 1746 | kfree_skb(buf); |
| 1764 | goto restart; | 1747 | goto restart; |
| 1765 | } | 1748 | } |
| 1766 | tipc_disconnect(tport->ref); | 1749 | tipc_port_disconnect(port->ref); |
| 1767 | tipc_reject_msg(buf, TIPC_CONN_SHUTDOWN); | 1750 | tipc_reject_msg(buf, TIPC_CONN_SHUTDOWN); |
| 1768 | } else { | 1751 | } else { |
| 1769 | tipc_shutdown(tport->ref); | 1752 | tipc_port_shutdown(port->ref); |
| 1770 | } | 1753 | } |
| 1771 | 1754 | ||
| 1772 | sock->state = SS_DISCONNECTING; | 1755 | sock->state = SS_DISCONNECTING; |
| @@ -1792,7 +1775,7 @@ restart: | |||
| 1792 | } | 1775 | } |
| 1793 | 1776 | ||
| 1794 | /** | 1777 | /** |
| 1795 | * setsockopt - set socket option | 1778 | * tipc_setsockopt - set socket option |
| 1796 | * @sock: socket structure | 1779 | * @sock: socket structure |
| 1797 | * @lvl: option level | 1780 | * @lvl: option level |
| 1798 | * @opt: option identifier | 1781 | * @opt: option identifier |
| @@ -1804,11 +1787,12 @@ restart: | |||
| 1804 | * | 1787 | * |
| 1805 | * Returns 0 on success, errno otherwise | 1788 | * Returns 0 on success, errno otherwise |
| 1806 | */ | 1789 | */ |
| 1807 | static int setsockopt(struct socket *sock, int lvl, int opt, char __user *ov, | 1790 | static int tipc_setsockopt(struct socket *sock, int lvl, int opt, |
| 1808 | unsigned int ol) | 1791 | char __user *ov, unsigned int ol) |
| 1809 | { | 1792 | { |
| 1810 | struct sock *sk = sock->sk; | 1793 | struct sock *sk = sock->sk; |
| 1811 | struct tipc_port *tport = tipc_sk_port(sk); | 1794 | struct tipc_sock *tsk = tipc_sk(sk); |
| 1795 | struct tipc_port *port = &tsk->port; | ||
| 1812 | u32 value; | 1796 | u32 value; |
| 1813 | int res; | 1797 | int res; |
| 1814 | 1798 | ||
| @@ -1826,16 +1810,16 @@ static int setsockopt(struct socket *sock, int lvl, int opt, char __user *ov, | |||
| 1826 | 1810 | ||
| 1827 | switch (opt) { | 1811 | switch (opt) { |
| 1828 | case TIPC_IMPORTANCE: | 1812 | case TIPC_IMPORTANCE: |
| 1829 | res = tipc_set_portimportance(tport->ref, value); | 1813 | tipc_port_set_importance(port, value); |
| 1830 | break; | 1814 | break; |
| 1831 | case TIPC_SRC_DROPPABLE: | 1815 | case TIPC_SRC_DROPPABLE: |
| 1832 | if (sock->type != SOCK_STREAM) | 1816 | if (sock->type != SOCK_STREAM) |
| 1833 | res = tipc_set_portunreliable(tport->ref, value); | 1817 | tipc_port_set_unreliable(port, value); |
| 1834 | else | 1818 | else |
| 1835 | res = -ENOPROTOOPT; | 1819 | res = -ENOPROTOOPT; |
| 1836 | break; | 1820 | break; |
| 1837 | case TIPC_DEST_DROPPABLE: | 1821 | case TIPC_DEST_DROPPABLE: |
| 1838 | res = tipc_set_portunreturnable(tport->ref, value); | 1822 | tipc_port_set_unreturnable(port, value); |
| 1839 | break; | 1823 | break; |
| 1840 | case TIPC_CONN_TIMEOUT: | 1824 | case TIPC_CONN_TIMEOUT: |
| 1841 | tipc_sk(sk)->conn_timeout = value; | 1825 | tipc_sk(sk)->conn_timeout = value; |
| @@ -1851,7 +1835,7 @@ static int setsockopt(struct socket *sock, int lvl, int opt, char __user *ov, | |||
| 1851 | } | 1835 | } |
| 1852 | 1836 | ||
| 1853 | /** | 1837 | /** |
| 1854 | * getsockopt - get socket option | 1838 | * tipc_getsockopt - get socket option |
| 1855 | * @sock: socket structure | 1839 | * @sock: socket structure |
| 1856 | * @lvl: option level | 1840 | * @lvl: option level |
| 1857 | * @opt: option identifier | 1841 | * @opt: option identifier |
| @@ -1863,11 +1847,12 @@ static int setsockopt(struct socket *sock, int lvl, int opt, char __user *ov, | |||
| 1863 | * | 1847 | * |
| 1864 | * Returns 0 on success, errno otherwise | 1848 | * Returns 0 on success, errno otherwise |
| 1865 | */ | 1849 | */ |
| 1866 | static int getsockopt(struct socket *sock, int lvl, int opt, char __user *ov, | 1850 | static int tipc_getsockopt(struct socket *sock, int lvl, int opt, |
| 1867 | int __user *ol) | 1851 | char __user *ov, int __user *ol) |
| 1868 | { | 1852 | { |
| 1869 | struct sock *sk = sock->sk; | 1853 | struct sock *sk = sock->sk; |
| 1870 | struct tipc_port *tport = tipc_sk_port(sk); | 1854 | struct tipc_sock *tsk = tipc_sk(sk); |
| 1855 | struct tipc_port *port = &tsk->port; | ||
| 1871 | int len; | 1856 | int len; |
| 1872 | u32 value; | 1857 | u32 value; |
| 1873 | int res; | 1858 | int res; |
| @@ -1884,13 +1869,13 @@ static int getsockopt(struct socket *sock, int lvl, int opt, char __user *ov, | |||
| 1884 | 1869 | ||
| 1885 | switch (opt) { | 1870 | switch (opt) { |
| 1886 | case TIPC_IMPORTANCE: | 1871 | case TIPC_IMPORTANCE: |
| 1887 | res = tipc_portimportance(tport->ref, &value); | 1872 | value = tipc_port_importance(port); |
| 1888 | break; | 1873 | break; |
| 1889 | case TIPC_SRC_DROPPABLE: | 1874 | case TIPC_SRC_DROPPABLE: |
| 1890 | res = tipc_portunreliable(tport->ref, &value); | 1875 | value = tipc_port_unreliable(port); |
| 1891 | break; | 1876 | break; |
| 1892 | case TIPC_DEST_DROPPABLE: | 1877 | case TIPC_DEST_DROPPABLE: |
| 1893 | res = tipc_portunreturnable(tport->ref, &value); | 1878 | value = tipc_port_unreturnable(port); |
| 1894 | break; | 1879 | break; |
| 1895 | case TIPC_CONN_TIMEOUT: | 1880 | case TIPC_CONN_TIMEOUT: |
| 1896 | value = tipc_sk(sk)->conn_timeout; | 1881 | value = tipc_sk(sk)->conn_timeout; |
| @@ -1925,20 +1910,20 @@ static int getsockopt(struct socket *sock, int lvl, int opt, char __user *ov, | |||
| 1925 | static const struct proto_ops msg_ops = { | 1910 | static const struct proto_ops msg_ops = { |
| 1926 | .owner = THIS_MODULE, | 1911 | .owner = THIS_MODULE, |
| 1927 | .family = AF_TIPC, | 1912 | .family = AF_TIPC, |
| 1928 | .release = release, | 1913 | .release = tipc_release, |
| 1929 | .bind = bind, | 1914 | .bind = tipc_bind, |
| 1930 | .connect = connect, | 1915 | .connect = tipc_connect, |
| 1931 | .socketpair = sock_no_socketpair, | 1916 | .socketpair = sock_no_socketpair, |
| 1932 | .accept = sock_no_accept, | 1917 | .accept = sock_no_accept, |
| 1933 | .getname = get_name, | 1918 | .getname = tipc_getname, |
| 1934 | .poll = poll, | 1919 | .poll = tipc_poll, |
| 1935 | .ioctl = sock_no_ioctl, | 1920 | .ioctl = sock_no_ioctl, |
| 1936 | .listen = sock_no_listen, | 1921 | .listen = sock_no_listen, |
| 1937 | .shutdown = shutdown, | 1922 | .shutdown = tipc_shutdown, |
| 1938 | .setsockopt = setsockopt, | 1923 | .setsockopt = tipc_setsockopt, |
| 1939 | .getsockopt = getsockopt, | 1924 | .getsockopt = tipc_getsockopt, |
| 1940 | .sendmsg = send_msg, | 1925 | .sendmsg = tipc_sendmsg, |
| 1941 | .recvmsg = recv_msg, | 1926 | .recvmsg = tipc_recvmsg, |
| 1942 | .mmap = sock_no_mmap, | 1927 | .mmap = sock_no_mmap, |
| 1943 | .sendpage = sock_no_sendpage | 1928 | .sendpage = sock_no_sendpage |
| 1944 | }; | 1929 | }; |
| @@ -1946,20 +1931,20 @@ static const struct proto_ops msg_ops = { | |||
| 1946 | static const struct proto_ops packet_ops = { | 1931 | static const struct proto_ops packet_ops = { |
| 1947 | .owner = THIS_MODULE, | 1932 | .owner = THIS_MODULE, |
| 1948 | .family = AF_TIPC, | 1933 | .family = AF_TIPC, |
| 1949 | .release = release, | 1934 | .release = tipc_release, |
| 1950 | .bind = bind, | 1935 | .bind = tipc_bind, |
| 1951 | .connect = connect, | 1936 | .connect = tipc_connect, |
| 1952 | .socketpair = sock_no_socketpair, | 1937 | .socketpair = sock_no_socketpair, |
| 1953 | .accept = accept, | 1938 | .accept = tipc_accept, |
| 1954 | .getname = get_name, | 1939 | .getname = tipc_getname, |
| 1955 | .poll = poll, | 1940 | .poll = tipc_poll, |
| 1956 | .ioctl = sock_no_ioctl, | 1941 | .ioctl = sock_no_ioctl, |
| 1957 | .listen = listen, | 1942 | .listen = tipc_listen, |
| 1958 | .shutdown = shutdown, | 1943 | .shutdown = tipc_shutdown, |
| 1959 | .setsockopt = setsockopt, | 1944 | .setsockopt = tipc_setsockopt, |
| 1960 | .getsockopt = getsockopt, | 1945 | .getsockopt = tipc_getsockopt, |
| 1961 | .sendmsg = send_packet, | 1946 | .sendmsg = tipc_send_packet, |
| 1962 | .recvmsg = recv_msg, | 1947 | .recvmsg = tipc_recvmsg, |
| 1963 | .mmap = sock_no_mmap, | 1948 | .mmap = sock_no_mmap, |
| 1964 | .sendpage = sock_no_sendpage | 1949 | .sendpage = sock_no_sendpage |
| 1965 | }; | 1950 | }; |
| @@ -1967,20 +1952,20 @@ static const struct proto_ops packet_ops = { | |||
| 1967 | static const struct proto_ops stream_ops = { | 1952 | static const struct proto_ops stream_ops = { |
| 1968 | .owner = THIS_MODULE, | 1953 | .owner = THIS_MODULE, |
| 1969 | .family = AF_TIPC, | 1954 | .family = AF_TIPC, |
| 1970 | .release = release, | 1955 | .release = tipc_release, |
| 1971 | .bind = bind, | 1956 | .bind = tipc_bind, |
| 1972 | .connect = connect, | 1957 | .connect = tipc_connect, |
| 1973 | .socketpair = sock_no_socketpair, | 1958 | .socketpair = sock_no_socketpair, |
| 1974 | .accept = accept, | 1959 | .accept = tipc_accept, |
| 1975 | .getname = get_name, | 1960 | .getname = tipc_getname, |
| 1976 | .poll = poll, | 1961 | .poll = tipc_poll, |
| 1977 | .ioctl = sock_no_ioctl, | 1962 | .ioctl = sock_no_ioctl, |
| 1978 | .listen = listen, | 1963 | .listen = tipc_listen, |
| 1979 | .shutdown = shutdown, | 1964 | .shutdown = tipc_shutdown, |
| 1980 | .setsockopt = setsockopt, | 1965 | .setsockopt = tipc_setsockopt, |
| 1981 | .getsockopt = getsockopt, | 1966 | .getsockopt = tipc_getsockopt, |
| 1982 | .sendmsg = send_stream, | 1967 | .sendmsg = tipc_send_stream, |
| 1983 | .recvmsg = recv_stream, | 1968 | .recvmsg = tipc_recv_stream, |
| 1984 | .mmap = sock_no_mmap, | 1969 | .mmap = sock_no_mmap, |
| 1985 | .sendpage = sock_no_sendpage | 1970 | .sendpage = sock_no_sendpage |
| 1986 | }; | 1971 | }; |
diff --git a/net/tipc/socket.h b/net/tipc/socket.h new file mode 100644 index 000000000000..74e5c7f195a6 --- /dev/null +++ b/net/tipc/socket.h | |||
| @@ -0,0 +1,72 @@ | |||
| 1 | /* net/tipc/socket.h: Include file for TIPC socket code | ||
| 2 | * | ||
| 3 | * Copyright (c) 2014, Ericsson AB | ||
| 4 | * All rights reserved. | ||
| 5 | * | ||
| 6 | * Redistribution and use in source and binary forms, with or without | ||
| 7 | * modification, are permitted provided that the following conditions are met: | ||
| 8 | * | ||
| 9 | * 1. Redistributions of source code must retain the above copyright | ||
| 10 | * notice, this list of conditions and the following disclaimer. | ||
| 11 | * 2. Redistributions in binary form must reproduce the above copyright | ||
| 12 | * notice, this list of conditions and the following disclaimer in the | ||
| 13 | * documentation and/or other materials provided with the distribution. | ||
| 14 | * 3. Neither the names of the copyright holders nor the names of its | ||
| 15 | * contributors may be used to endorse or promote products derived from | ||
| 16 | * this software without specific prior written permission. | ||
| 17 | * | ||
| 18 | * Alternatively, this software may be distributed under the terms of the | ||
| 19 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
| 20 | * Software Foundation. | ||
| 21 | * | ||
| 22 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | ||
| 23 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||
| 24 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||
| 25 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE | ||
| 26 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR | ||
| 27 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF | ||
| 28 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS | ||
| 29 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN | ||
| 30 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | ||
| 31 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
| 32 | * POSSIBILITY OF SUCH DAMAGE. | ||
| 33 | */ | ||
| 34 | |||
| 35 | #ifndef _TIPC_SOCK_H | ||
| 36 | #define _TIPC_SOCK_H | ||
| 37 | |||
| 38 | #include "port.h" | ||
| 39 | #include <net/sock.h> | ||
| 40 | |||
| 41 | /** | ||
| 42 | * struct tipc_sock - TIPC socket structure | ||
| 43 | * @sk: socket - interacts with 'port' and with user via the socket API | ||
| 44 | * @port: port - interacts with 'sk' and with the rest of the TIPC stack | ||
| 45 | * @peer_name: the peer of the connection, if any | ||
| 46 | * @conn_timeout: the time we can wait for an unresponded setup request | ||
| 47 | */ | ||
| 48 | |||
| 49 | struct tipc_sock { | ||
| 50 | struct sock sk; | ||
| 51 | struct tipc_port port; | ||
| 52 | unsigned int conn_timeout; | ||
| 53 | }; | ||
| 54 | |||
| 55 | static inline struct tipc_sock *tipc_sk(const struct sock *sk) | ||
| 56 | { | ||
| 57 | return container_of(sk, struct tipc_sock, sk); | ||
| 58 | } | ||
| 59 | |||
| 60 | static inline struct tipc_sock *tipc_port_to_sock(const struct tipc_port *port) | ||
| 61 | { | ||
| 62 | return container_of(port, struct tipc_sock, port); | ||
| 63 | } | ||
| 64 | |||
| 65 | static inline void tipc_sock_wakeup(struct tipc_sock *tsk) | ||
| 66 | { | ||
| 67 | tsk->sk.sk_write_space(&tsk->sk); | ||
| 68 | } | ||
| 69 | |||
| 70 | u32 tipc_sk_rcv(struct sock *sk, struct sk_buff *buf); | ||
| 71 | |||
| 72 | #endif | ||
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c index 94404f19f9de..bb7e8ba821f4 100644 --- a/net/unix/af_unix.c +++ b/net/unix/af_unix.c | |||
| @@ -1217,7 +1217,7 @@ restart: | |||
| 1217 | __skb_queue_tail(&other->sk_receive_queue, skb); | 1217 | __skb_queue_tail(&other->sk_receive_queue, skb); |
| 1218 | spin_unlock(&other->sk_receive_queue.lock); | 1218 | spin_unlock(&other->sk_receive_queue.lock); |
| 1219 | unix_state_unlock(other); | 1219 | unix_state_unlock(other); |
| 1220 | other->sk_data_ready(other, 0); | 1220 | other->sk_data_ready(other); |
| 1221 | sock_put(other); | 1221 | sock_put(other); |
| 1222 | return 0; | 1222 | return 0; |
| 1223 | 1223 | ||
| @@ -1600,7 +1600,7 @@ restart: | |||
| 1600 | if (max_level > unix_sk(other)->recursion_level) | 1600 | if (max_level > unix_sk(other)->recursion_level) |
| 1601 | unix_sk(other)->recursion_level = max_level; | 1601 | unix_sk(other)->recursion_level = max_level; |
| 1602 | unix_state_unlock(other); | 1602 | unix_state_unlock(other); |
| 1603 | other->sk_data_ready(other, len); | 1603 | other->sk_data_ready(other); |
| 1604 | sock_put(other); | 1604 | sock_put(other); |
| 1605 | scm_destroy(siocb->scm); | 1605 | scm_destroy(siocb->scm); |
| 1606 | return len; | 1606 | return len; |
| @@ -1706,7 +1706,7 @@ static int unix_stream_sendmsg(struct kiocb *kiocb, struct socket *sock, | |||
| 1706 | if (max_level > unix_sk(other)->recursion_level) | 1706 | if (max_level > unix_sk(other)->recursion_level) |
| 1707 | unix_sk(other)->recursion_level = max_level; | 1707 | unix_sk(other)->recursion_level = max_level; |
| 1708 | unix_state_unlock(other); | 1708 | unix_state_unlock(other); |
| 1709 | other->sk_data_ready(other, size); | 1709 | other->sk_data_ready(other); |
| 1710 | sent += size; | 1710 | sent += size; |
| 1711 | } | 1711 | } |
| 1712 | 1712 | ||
diff --git a/net/vmw_vsock/vmci_transport_notify.c b/net/vmw_vsock/vmci_transport_notify.c index 9a730744e7bc..9b7f207f2bee 100644 --- a/net/vmw_vsock/vmci_transport_notify.c +++ b/net/vmw_vsock/vmci_transport_notify.c | |||
| @@ -315,7 +315,7 @@ vmci_transport_handle_wrote(struct sock *sk, | |||
| 315 | struct vsock_sock *vsk = vsock_sk(sk); | 315 | struct vsock_sock *vsk = vsock_sk(sk); |
| 316 | PKT_FIELD(vsk, sent_waiting_read) = false; | 316 | PKT_FIELD(vsk, sent_waiting_read) = false; |
| 317 | #endif | 317 | #endif |
| 318 | sk->sk_data_ready(sk, 0); | 318 | sk->sk_data_ready(sk); |
| 319 | } | 319 | } |
| 320 | 320 | ||
| 321 | static void vmci_transport_notify_pkt_socket_init(struct sock *sk) | 321 | static void vmci_transport_notify_pkt_socket_init(struct sock *sk) |
diff --git a/net/vmw_vsock/vmci_transport_notify_qstate.c b/net/vmw_vsock/vmci_transport_notify_qstate.c index 622bd7aa1016..dc9c7929a2f9 100644 --- a/net/vmw_vsock/vmci_transport_notify_qstate.c +++ b/net/vmw_vsock/vmci_transport_notify_qstate.c | |||
| @@ -92,7 +92,7 @@ vmci_transport_handle_wrote(struct sock *sk, | |||
| 92 | bool bottom_half, | 92 | bool bottom_half, |
| 93 | struct sockaddr_vm *dst, struct sockaddr_vm *src) | 93 | struct sockaddr_vm *dst, struct sockaddr_vm *src) |
| 94 | { | 94 | { |
| 95 | sk->sk_data_ready(sk, 0); | 95 | sk->sk_data_ready(sk); |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | static void vsock_block_update_write_window(struct sock *sk) | 98 | static void vsock_block_update_write_window(struct sock *sk) |
| @@ -290,7 +290,7 @@ vmci_transport_notify_pkt_recv_post_dequeue( | |||
| 290 | /* See the comment in | 290 | /* See the comment in |
| 291 | * vmci_transport_notify_pkt_send_post_enqueue(). | 291 | * vmci_transport_notify_pkt_send_post_enqueue(). |
| 292 | */ | 292 | */ |
| 293 | sk->sk_data_ready(sk, 0); | 293 | sk->sk_data_ready(sk); |
| 294 | } | 294 | } |
| 295 | 295 | ||
| 296 | return err; | 296 | return err; |
diff --git a/net/wireless/ap.c b/net/wireless/ap.c index 11ee4ed04f73..3e02ade508d8 100644 --- a/net/wireless/ap.c +++ b/net/wireless/ap.c | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | 7 | ||
| 8 | 8 | ||
| 9 | static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, | 9 | static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, |
| 10 | struct net_device *dev) | 10 | struct net_device *dev, bool notify) |
| 11 | { | 11 | { |
| 12 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 12 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 13 | int err; | 13 | int err; |
| @@ -27,22 +27,24 @@ static int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev, | |||
| 27 | err = rdev_stop_ap(rdev, dev); | 27 | err = rdev_stop_ap(rdev, dev); |
| 28 | if (!err) { | 28 | if (!err) { |
| 29 | wdev->beacon_interval = 0; | 29 | wdev->beacon_interval = 0; |
| 30 | wdev->channel = NULL; | 30 | memset(&wdev->chandef, 0, sizeof(wdev->chandef)); |
| 31 | wdev->ssid_len = 0; | 31 | wdev->ssid_len = 0; |
| 32 | rdev_set_qos_map(rdev, dev, NULL); | 32 | rdev_set_qos_map(rdev, dev, NULL); |
| 33 | if (notify) | ||
| 34 | nl80211_send_ap_stopped(wdev); | ||
| 33 | } | 35 | } |
| 34 | 36 | ||
| 35 | return err; | 37 | return err; |
| 36 | } | 38 | } |
| 37 | 39 | ||
| 38 | int cfg80211_stop_ap(struct cfg80211_registered_device *rdev, | 40 | int cfg80211_stop_ap(struct cfg80211_registered_device *rdev, |
| 39 | struct net_device *dev) | 41 | struct net_device *dev, bool notify) |
| 40 | { | 42 | { |
| 41 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 43 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 42 | int err; | 44 | int err; |
| 43 | 45 | ||
| 44 | wdev_lock(wdev); | 46 | wdev_lock(wdev); |
| 45 | err = __cfg80211_stop_ap(rdev, dev); | 47 | err = __cfg80211_stop_ap(rdev, dev, notify); |
| 46 | wdev_unlock(wdev); | 48 | wdev_unlock(wdev); |
| 47 | 49 | ||
| 48 | return err; | 50 | return err; |
diff --git a/net/wireless/chan.c b/net/wireless/chan.c index 78559b5bbd1f..9c9501a35fb5 100644 --- a/net/wireless/chan.c +++ b/net/wireless/chan.c | |||
| @@ -490,6 +490,62 @@ static bool cfg80211_chandef_dfs_available(struct wiphy *wiphy, | |||
| 490 | return r; | 490 | return r; |
| 491 | } | 491 | } |
| 492 | 492 | ||
| 493 | static unsigned int cfg80211_get_chans_dfs_cac_time(struct wiphy *wiphy, | ||
| 494 | u32 center_freq, | ||
| 495 | u32 bandwidth) | ||
| 496 | { | ||
| 497 | struct ieee80211_channel *c; | ||
| 498 | u32 start_freq, end_freq, freq; | ||
| 499 | unsigned int dfs_cac_ms = 0; | ||
| 500 | |||
| 501 | start_freq = cfg80211_get_start_freq(center_freq, bandwidth); | ||
| 502 | end_freq = cfg80211_get_end_freq(center_freq, bandwidth); | ||
| 503 | |||
| 504 | for (freq = start_freq; freq <= end_freq; freq += 20) { | ||
| 505 | c = ieee80211_get_channel(wiphy, freq); | ||
| 506 | if (!c) | ||
| 507 | return 0; | ||
| 508 | |||
| 509 | if (c->flags & IEEE80211_CHAN_DISABLED) | ||
| 510 | return 0; | ||
| 511 | |||
| 512 | if (!(c->flags & IEEE80211_CHAN_RADAR)) | ||
| 513 | continue; | ||
| 514 | |||
| 515 | if (c->dfs_cac_ms > dfs_cac_ms) | ||
| 516 | dfs_cac_ms = c->dfs_cac_ms; | ||
| 517 | } | ||
| 518 | |||
| 519 | return dfs_cac_ms; | ||
| 520 | } | ||
| 521 | |||
| 522 | unsigned int | ||
| 523 | cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy, | ||
| 524 | const struct cfg80211_chan_def *chandef) | ||
| 525 | { | ||
| 526 | int width; | ||
| 527 | unsigned int t1 = 0, t2 = 0; | ||
| 528 | |||
| 529 | if (WARN_ON(!cfg80211_chandef_valid(chandef))) | ||
| 530 | return 0; | ||
| 531 | |||
| 532 | width = cfg80211_chandef_get_width(chandef); | ||
| 533 | if (width < 0) | ||
| 534 | return 0; | ||
| 535 | |||
| 536 | t1 = cfg80211_get_chans_dfs_cac_time(wiphy, | ||
| 537 | chandef->center_freq1, | ||
| 538 | width); | ||
| 539 | |||
| 540 | if (!chandef->center_freq2) | ||
| 541 | return t1; | ||
| 542 | |||
| 543 | t2 = cfg80211_get_chans_dfs_cac_time(wiphy, | ||
| 544 | chandef->center_freq2, | ||
| 545 | width); | ||
| 546 | |||
| 547 | return max(t1, t2); | ||
| 548 | } | ||
| 493 | 549 | ||
| 494 | static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, | 550 | static bool cfg80211_secondary_chans_ok(struct wiphy *wiphy, |
| 495 | u32 center_freq, u32 bandwidth, | 551 | u32 center_freq, u32 bandwidth, |
| @@ -642,7 +698,8 @@ int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, | |||
| 642 | void | 698 | void |
| 643 | cfg80211_get_chan_state(struct wireless_dev *wdev, | 699 | cfg80211_get_chan_state(struct wireless_dev *wdev, |
| 644 | struct ieee80211_channel **chan, | 700 | struct ieee80211_channel **chan, |
| 645 | enum cfg80211_chan_mode *chanmode) | 701 | enum cfg80211_chan_mode *chanmode, |
| 702 | u8 *radar_detect) | ||
| 646 | { | 703 | { |
| 647 | *chan = NULL; | 704 | *chan = NULL; |
| 648 | *chanmode = CHAN_MODE_UNDEFINED; | 705 | *chanmode = CHAN_MODE_UNDEFINED; |
| @@ -660,6 +717,11 @@ cfg80211_get_chan_state(struct wireless_dev *wdev, | |||
| 660 | !wdev->ibss_dfs_possible) | 717 | !wdev->ibss_dfs_possible) |
| 661 | ? CHAN_MODE_SHARED | 718 | ? CHAN_MODE_SHARED |
| 662 | : CHAN_MODE_EXCLUSIVE; | 719 | : CHAN_MODE_EXCLUSIVE; |
| 720 | |||
| 721 | /* consider worst-case - IBSS can try to return to the | ||
| 722 | * original user-specified channel as creator */ | ||
| 723 | if (wdev->ibss_dfs_possible) | ||
| 724 | *radar_detect |= BIT(wdev->chandef.width); | ||
| 663 | return; | 725 | return; |
| 664 | } | 726 | } |
| 665 | break; | 727 | break; |
| @@ -674,33 +736,36 @@ cfg80211_get_chan_state(struct wireless_dev *wdev, | |||
| 674 | case NL80211_IFTYPE_AP: | 736 | case NL80211_IFTYPE_AP: |
| 675 | case NL80211_IFTYPE_P2P_GO: | 737 | case NL80211_IFTYPE_P2P_GO: |
| 676 | if (wdev->cac_started) { | 738 | if (wdev->cac_started) { |
| 677 | *chan = wdev->channel; | 739 | *chan = wdev->chandef.chan; |
| 678 | *chanmode = CHAN_MODE_SHARED; | 740 | *chanmode = CHAN_MODE_SHARED; |
| 741 | *radar_detect |= BIT(wdev->chandef.width); | ||
| 679 | } else if (wdev->beacon_interval) { | 742 | } else if (wdev->beacon_interval) { |
| 680 | *chan = wdev->channel; | 743 | *chan = wdev->chandef.chan; |
| 681 | *chanmode = CHAN_MODE_SHARED; | 744 | *chanmode = CHAN_MODE_SHARED; |
| 745 | |||
| 746 | if (cfg80211_chandef_dfs_required(wdev->wiphy, | ||
| 747 | &wdev->chandef)) | ||
| 748 | *radar_detect |= BIT(wdev->chandef.width); | ||
| 682 | } | 749 | } |
| 683 | return; | 750 | return; |
| 684 | case NL80211_IFTYPE_MESH_POINT: | 751 | case NL80211_IFTYPE_MESH_POINT: |
| 685 | if (wdev->mesh_id_len) { | 752 | if (wdev->mesh_id_len) { |
| 686 | *chan = wdev->channel; | 753 | *chan = wdev->chandef.chan; |
| 687 | *chanmode = CHAN_MODE_SHARED; | 754 | *chanmode = CHAN_MODE_SHARED; |
| 755 | |||
| 756 | if (cfg80211_chandef_dfs_required(wdev->wiphy, | ||
| 757 | &wdev->chandef)) | ||
| 758 | *radar_detect |= BIT(wdev->chandef.width); | ||
| 688 | } | 759 | } |
| 689 | return; | 760 | return; |
| 690 | case NL80211_IFTYPE_MONITOR: | 761 | case NL80211_IFTYPE_MONITOR: |
| 691 | case NL80211_IFTYPE_AP_VLAN: | 762 | case NL80211_IFTYPE_AP_VLAN: |
| 692 | case NL80211_IFTYPE_WDS: | 763 | case NL80211_IFTYPE_WDS: |
| 693 | /* these interface types don't really have a channel */ | ||
| 694 | return; | ||
| 695 | case NL80211_IFTYPE_P2P_DEVICE: | 764 | case NL80211_IFTYPE_P2P_DEVICE: |
| 696 | if (wdev->wiphy->features & | 765 | /* these interface types don't really have a channel */ |
| 697 | NL80211_FEATURE_P2P_DEVICE_NEEDS_CHANNEL) | ||
| 698 | *chanmode = CHAN_MODE_EXCLUSIVE; | ||
| 699 | return; | 766 | return; |
| 700 | case NL80211_IFTYPE_UNSPECIFIED: | 767 | case NL80211_IFTYPE_UNSPECIFIED: |
| 701 | case NUM_NL80211_IFTYPES: | 768 | case NUM_NL80211_IFTYPES: |
| 702 | WARN_ON(1); | 769 | WARN_ON(1); |
| 703 | } | 770 | } |
| 704 | |||
| 705 | return; | ||
| 706 | } | 771 | } |
diff --git a/net/wireless/core.c b/net/wireless/core.c index a3bf18d11609..086cddd03ba6 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
| @@ -737,7 +737,7 @@ void cfg80211_unregister_wdev(struct wireless_dev *wdev) | |||
| 737 | } | 737 | } |
| 738 | EXPORT_SYMBOL(cfg80211_unregister_wdev); | 738 | EXPORT_SYMBOL(cfg80211_unregister_wdev); |
| 739 | 739 | ||
| 740 | static struct device_type wiphy_type = { | 740 | static const struct device_type wiphy_type = { |
| 741 | .name = "wlan", | 741 | .name = "wlan", |
| 742 | }; | 742 | }; |
| 743 | 743 | ||
| @@ -783,7 +783,7 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev, | |||
| 783 | break; | 783 | break; |
| 784 | case NL80211_IFTYPE_AP: | 784 | case NL80211_IFTYPE_AP: |
| 785 | case NL80211_IFTYPE_P2P_GO: | 785 | case NL80211_IFTYPE_P2P_GO: |
| 786 | cfg80211_stop_ap(rdev, dev); | 786 | cfg80211_stop_ap(rdev, dev, true); |
| 787 | break; | 787 | break; |
| 788 | default: | 788 | default: |
| 789 | break; | 789 | break; |
diff --git a/net/wireless/core.h b/net/wireless/core.h index f1d193b557b6..5b1fdcadd469 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
| @@ -166,7 +166,6 @@ static inline void wdev_unlock(struct wireless_dev *wdev) | |||
| 166 | mutex_unlock(&wdev->mtx); | 166 | mutex_unlock(&wdev->mtx); |
| 167 | } | 167 | } |
| 168 | 168 | ||
| 169 | #define ASSERT_RDEV_LOCK(rdev) ASSERT_RTNL() | ||
| 170 | #define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx) | 169 | #define ASSERT_WDEV_LOCK(wdev) lockdep_assert_held(&(wdev)->mtx) |
| 171 | 170 | ||
| 172 | static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev) | 171 | static inline bool cfg80211_has_monitors_only(struct cfg80211_registered_device *rdev) |
| @@ -211,6 +210,7 @@ struct cfg80211_event { | |||
| 211 | } dc; | 210 | } dc; |
| 212 | struct { | 211 | struct { |
| 213 | u8 bssid[ETH_ALEN]; | 212 | u8 bssid[ETH_ALEN]; |
| 213 | struct ieee80211_channel *channel; | ||
| 214 | } ij; | 214 | } ij; |
| 215 | }; | 215 | }; |
| 216 | }; | 216 | }; |
| @@ -245,10 +245,6 @@ void cfg80211_bss_age(struct cfg80211_registered_device *dev, | |||
| 245 | unsigned long age_secs); | 245 | unsigned long age_secs); |
| 246 | 246 | ||
| 247 | /* IBSS */ | 247 | /* IBSS */ |
| 248 | int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | ||
| 249 | struct net_device *dev, | ||
| 250 | struct cfg80211_ibss_params *params, | ||
| 251 | struct cfg80211_cached_keys *connkeys); | ||
| 252 | int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | 248 | int cfg80211_join_ibss(struct cfg80211_registered_device *rdev, |
| 253 | struct net_device *dev, | 249 | struct net_device *dev, |
| 254 | struct cfg80211_ibss_params *params, | 250 | struct cfg80211_ibss_params *params, |
| @@ -258,7 +254,8 @@ int __cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, | |||
| 258 | struct net_device *dev, bool nowext); | 254 | struct net_device *dev, bool nowext); |
| 259 | int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, | 255 | int cfg80211_leave_ibss(struct cfg80211_registered_device *rdev, |
| 260 | struct net_device *dev, bool nowext); | 256 | struct net_device *dev, bool nowext); |
| 261 | void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid); | 257 | void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, |
| 258 | struct ieee80211_channel *channel); | ||
| 262 | int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, | 259 | int cfg80211_ibss_wext_join(struct cfg80211_registered_device *rdev, |
| 263 | struct wireless_dev *wdev); | 260 | struct wireless_dev *wdev); |
| 264 | 261 | ||
| @@ -281,7 +278,7 @@ int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev, | |||
| 281 | 278 | ||
| 282 | /* AP */ | 279 | /* AP */ |
| 283 | int cfg80211_stop_ap(struct cfg80211_registered_device *rdev, | 280 | int cfg80211_stop_ap(struct cfg80211_registered_device *rdev, |
| 284 | struct net_device *dev); | 281 | struct net_device *dev, bool notify); |
| 285 | 282 | ||
| 286 | /* MLME */ | 283 | /* MLME */ |
| 287 | int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, | 284 | int cfg80211_mlme_auth(struct cfg80211_registered_device *rdev, |
| @@ -400,6 +397,9 @@ void cfg80211_set_dfs_state(struct wiphy *wiphy, | |||
| 400 | 397 | ||
| 401 | void cfg80211_dfs_channels_update_work(struct work_struct *work); | 398 | void cfg80211_dfs_channels_update_work(struct work_struct *work); |
| 402 | 399 | ||
| 400 | unsigned int | ||
| 401 | cfg80211_chandef_dfs_cac_time(struct wiphy *wiphy, | ||
| 402 | const struct cfg80211_chan_def *chandef); | ||
| 403 | 403 | ||
| 404 | static inline int | 404 | static inline int |
| 405 | cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, | 405 | cfg80211_can_change_interface(struct cfg80211_registered_device *rdev, |
| @@ -443,7 +443,8 @@ static inline unsigned int elapsed_jiffies_msecs(unsigned long start) | |||
| 443 | void | 443 | void |
| 444 | cfg80211_get_chan_state(struct wireless_dev *wdev, | 444 | cfg80211_get_chan_state(struct wireless_dev *wdev, |
| 445 | struct ieee80211_channel **chan, | 445 | struct ieee80211_channel **chan, |
| 446 | enum cfg80211_chan_mode *chanmode); | 446 | enum cfg80211_chan_mode *chanmode, |
| 447 | u8 *radar_detect); | ||
| 447 | 448 | ||
| 448 | int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, | 449 | int cfg80211_set_monitor_channel(struct cfg80211_registered_device *rdev, |
| 449 | struct cfg80211_chan_def *chandef); | 450 | struct cfg80211_chan_def *chandef); |
diff --git a/net/wireless/genregdb.awk b/net/wireless/genregdb.awk index 9a8217d2a908..b35da8dc85de 100644 --- a/net/wireless/genregdb.awk +++ b/net/wireless/genregdb.awk | |||
| @@ -66,6 +66,7 @@ function parse_reg_rule() | |||
| 66 | units = $8 | 66 | units = $8 |
| 67 | sub(/\)/, "", units) | 67 | sub(/\)/, "", units) |
| 68 | sub(/,/, "", units) | 68 | sub(/,/, "", units) |
| 69 | dfs_cac = $9 | ||
| 69 | if (units == "mW") { | 70 | if (units == "mW") { |
| 70 | if (power == 100) { | 71 | if (power == 100) { |
| 71 | power = 20 | 72 | power = 20 |
| @@ -78,7 +79,12 @@ function parse_reg_rule() | |||
| 78 | } else { | 79 | } else { |
| 79 | print "Unknown power value in database!" | 80 | print "Unknown power value in database!" |
| 80 | } | 81 | } |
| 82 | } else { | ||
| 83 | dfs_cac = $8 | ||
| 81 | } | 84 | } |
| 85 | sub(/,/, "", dfs_cac) | ||
| 86 | sub(/\(/, "", dfs_cac) | ||
| 87 | sub(/\)/, "", dfs_cac) | ||
| 82 | flagstr = "" | 88 | flagstr = "" |
| 83 | for (i=8; i<=NF; i++) | 89 | for (i=8; i<=NF; i++) |
| 84 | flagstr = flagstr $i | 90 | flagstr = flagstr $i |
| @@ -105,11 +111,13 @@ function parse_reg_rule() | |||
| 105 | flags = flags "\n\t\t\tNL80211_RRF_NO_IR | " | 111 | flags = flags "\n\t\t\tNL80211_RRF_NO_IR | " |
| 106 | } else if (flagarray[arg] == "NO-IR") { | 112 | } else if (flagarray[arg] == "NO-IR") { |
| 107 | flags = flags "\n\t\t\tNL80211_RRF_NO_IR | " | 113 | flags = flags "\n\t\t\tNL80211_RRF_NO_IR | " |
| 114 | } else if (flagarray[arg] == "AUTO-BW") { | ||
| 115 | flags = flags "\n\t\t\tNL80211_RRF_AUTO_BW | " | ||
| 108 | } | 116 | } |
| 109 | 117 | ||
| 110 | } | 118 | } |
| 111 | flags = flags "0" | 119 | flags = flags "0" |
| 112 | printf "\t\tREG_RULE(%d, %d, %d, %d, %d, %s),\n", start, end, bw, gain, power, flags | 120 | printf "\t\tREG_RULE_EXT(%d, %d, %d, %d, %d, %d, %s),\n", start, end, bw, gain, power, dfs_cac, flags |
| 113 | rules++ | 121 | rules++ |
| 114 | } | 122 | } |
| 115 | 123 | ||
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c index f911c5f9f903..a6b5bdad039c 100644 --- a/net/wireless/ibss.c +++ b/net/wireless/ibss.c | |||
| @@ -14,7 +14,8 @@ | |||
| 14 | #include "rdev-ops.h" | 14 | #include "rdev-ops.h" |
| 15 | 15 | ||
| 16 | 16 | ||
| 17 | void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid) | 17 | void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, |
| 18 | struct ieee80211_channel *channel) | ||
| 18 | { | 19 | { |
| 19 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 20 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 20 | struct cfg80211_bss *bss; | 21 | struct cfg80211_bss *bss; |
| @@ -28,8 +29,7 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid) | |||
| 28 | if (!wdev->ssid_len) | 29 | if (!wdev->ssid_len) |
| 29 | return; | 30 | return; |
| 30 | 31 | ||
| 31 | bss = cfg80211_get_bss(wdev->wiphy, NULL, bssid, | 32 | bss = cfg80211_get_bss(wdev->wiphy, channel, bssid, NULL, 0, |
| 32 | wdev->ssid, wdev->ssid_len, | ||
| 33 | WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS); | 33 | WLAN_CAPABILITY_IBSS, WLAN_CAPABILITY_IBSS); |
| 34 | 34 | ||
| 35 | if (WARN_ON(!bss)) | 35 | if (WARN_ON(!bss)) |
| @@ -54,21 +54,26 @@ void __cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid) | |||
| 54 | #endif | 54 | #endif |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp) | 57 | void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, |
| 58 | struct ieee80211_channel *channel, gfp_t gfp) | ||
| 58 | { | 59 | { |
| 59 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 60 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 60 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); | 61 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy); |
| 61 | struct cfg80211_event *ev; | 62 | struct cfg80211_event *ev; |
| 62 | unsigned long flags; | 63 | unsigned long flags; |
| 63 | 64 | ||
| 64 | trace_cfg80211_ibss_joined(dev, bssid); | 65 | trace_cfg80211_ibss_joined(dev, bssid, channel); |
| 66 | |||
| 67 | if (WARN_ON(!channel)) | ||
| 68 | return; | ||
| 65 | 69 | ||
| 66 | ev = kzalloc(sizeof(*ev), gfp); | 70 | ev = kzalloc(sizeof(*ev), gfp); |
| 67 | if (!ev) | 71 | if (!ev) |
| 68 | return; | 72 | return; |
| 69 | 73 | ||
| 70 | ev->type = EVENT_IBSS_JOINED; | 74 | ev->type = EVENT_IBSS_JOINED; |
| 71 | memcpy(ev->cr.bssid, bssid, ETH_ALEN); | 75 | memcpy(ev->ij.bssid, bssid, ETH_ALEN); |
| 76 | ev->ij.channel = channel; | ||
| 72 | 77 | ||
| 73 | spin_lock_irqsave(&wdev->event_lock, flags); | 78 | spin_lock_irqsave(&wdev->event_lock, flags); |
| 74 | list_add_tail(&ev->list, &wdev->event_list); | 79 | list_add_tail(&ev->list, &wdev->event_list); |
| @@ -77,10 +82,10 @@ void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp) | |||
| 77 | } | 82 | } |
| 78 | EXPORT_SYMBOL(cfg80211_ibss_joined); | 83 | EXPORT_SYMBOL(cfg80211_ibss_joined); |
| 79 | 84 | ||
| 80 | int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | 85 | static int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, |
| 81 | struct net_device *dev, | 86 | struct net_device *dev, |
| 82 | struct cfg80211_ibss_params *params, | 87 | struct cfg80211_ibss_params *params, |
| 83 | struct cfg80211_cached_keys *connkeys) | 88 | struct cfg80211_cached_keys *connkeys) |
| 84 | { | 89 | { |
| 85 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 90 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 86 | struct ieee80211_channel *check_chan; | 91 | struct ieee80211_channel *check_chan; |
| @@ -117,17 +122,17 @@ int __cfg80211_join_ibss(struct cfg80211_registered_device *rdev, | |||
| 117 | 122 | ||
| 118 | wdev->ibss_fixed = params->channel_fixed; | 123 | wdev->ibss_fixed = params->channel_fixed; |
| 119 | wdev->ibss_dfs_possible = params->userspace_handles_dfs; | 124 | wdev->ibss_dfs_possible = params->userspace_handles_dfs; |
| 125 | wdev->chandef = params->chandef; | ||
| 120 | #ifdef CONFIG_CFG80211_WEXT | 126 | #ifdef CONFIG_CFG80211_WEXT |
| 121 | wdev->wext.ibss.chandef = params->chandef; | 127 | wdev->wext.ibss.chandef = params->chandef; |
| 122 | #endif | 128 | #endif |
| 123 | check_chan = params->chandef.chan; | 129 | check_chan = params->chandef.chan; |
| 124 | if (params->userspace_handles_dfs) { | 130 | if (params->userspace_handles_dfs) { |
| 125 | /* use channel NULL to check for radar even if the current | 131 | /* Check for radar even if the current channel is not |
| 126 | * channel is not a radar channel - it might decide to change | 132 | * a radar channel - it might decide to change to DFS |
| 127 | * to DFS channel later. | 133 | * channel later. |
| 128 | */ | 134 | */ |
| 129 | radar_detect_width = BIT(params->chandef.width); | 135 | radar_detect_width = BIT(params->chandef.width); |
| 130 | check_chan = NULL; | ||
| 131 | } | 136 | } |
| 132 | 137 | ||
| 133 | err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, | 138 | err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, |
| @@ -200,6 +205,7 @@ static void __cfg80211_clear_ibss(struct net_device *dev, bool nowext) | |||
| 200 | 205 | ||
| 201 | wdev->current_bss = NULL; | 206 | wdev->current_bss = NULL; |
| 202 | wdev->ssid_len = 0; | 207 | wdev->ssid_len = 0; |
| 208 | memset(&wdev->chandef, 0, sizeof(wdev->chandef)); | ||
| 203 | #ifdef CONFIG_CFG80211_WEXT | 209 | #ifdef CONFIG_CFG80211_WEXT |
| 204 | if (!nowext) | 210 | if (!nowext) |
| 205 | wdev->wext.ibss.ssid_len = 0; | 211 | wdev->wext.ibss.ssid_len = 0; |
diff --git a/net/wireless/mesh.c b/net/wireless/mesh.c index 885862447b63..5af5cc6b2c4c 100644 --- a/net/wireless/mesh.c +++ b/net/wireless/mesh.c | |||
| @@ -195,7 +195,7 @@ int __cfg80211_join_mesh(struct cfg80211_registered_device *rdev, | |||
| 195 | if (!err) { | 195 | if (!err) { |
| 196 | memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len); | 196 | memcpy(wdev->ssid, setup->mesh_id, setup->mesh_id_len); |
| 197 | wdev->mesh_id_len = setup->mesh_id_len; | 197 | wdev->mesh_id_len = setup->mesh_id_len; |
| 198 | wdev->channel = setup->chandef.chan; | 198 | wdev->chandef = setup->chandef; |
| 199 | } | 199 | } |
| 200 | 200 | ||
| 201 | return err; | 201 | return err; |
| @@ -236,6 +236,12 @@ int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev, | |||
| 236 | if (!netif_running(wdev->netdev)) | 236 | if (!netif_running(wdev->netdev)) |
| 237 | return -ENETDOWN; | 237 | return -ENETDOWN; |
| 238 | 238 | ||
| 239 | /* cfg80211_can_use_chan() calls | ||
| 240 | * cfg80211_can_use_iftype_chan() with no radar | ||
| 241 | * detection, so if we're trying to use a radar | ||
| 242 | * channel here, something is wrong. | ||
| 243 | */ | ||
| 244 | WARN_ON_ONCE(chandef->chan->flags & IEEE80211_CHAN_RADAR); | ||
| 239 | err = cfg80211_can_use_chan(rdev, wdev, chandef->chan, | 245 | err = cfg80211_can_use_chan(rdev, wdev, chandef->chan, |
| 240 | CHAN_MODE_SHARED); | 246 | CHAN_MODE_SHARED); |
| 241 | if (err) | 247 | if (err) |
| @@ -244,7 +250,7 @@ int cfg80211_set_mesh_channel(struct cfg80211_registered_device *rdev, | |||
| 244 | err = rdev_libertas_set_mesh_channel(rdev, wdev->netdev, | 250 | err = rdev_libertas_set_mesh_channel(rdev, wdev->netdev, |
| 245 | chandef->chan); | 251 | chandef->chan); |
| 246 | if (!err) | 252 | if (!err) |
| 247 | wdev->channel = chandef->chan; | 253 | wdev->chandef = *chandef; |
| 248 | 254 | ||
| 249 | return err; | 255 | return err; |
| 250 | } | 256 | } |
| @@ -276,7 +282,7 @@ static int __cfg80211_leave_mesh(struct cfg80211_registered_device *rdev, | |||
| 276 | err = rdev_leave_mesh(rdev, dev); | 282 | err = rdev_leave_mesh(rdev, dev); |
| 277 | if (!err) { | 283 | if (!err) { |
| 278 | wdev->mesh_id_len = 0; | 284 | wdev->mesh_id_len = 0; |
| 279 | wdev->channel = NULL; | 285 | memset(&wdev->chandef, 0, sizeof(wdev->chandef)); |
| 280 | rdev_set_qos_map(rdev, dev, NULL); | 286 | rdev_set_qos_map(rdev, dev, NULL); |
| 281 | } | 287 | } |
| 282 | 288 | ||
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c index 52cca05044a8..c52ff59a3e96 100644 --- a/net/wireless/mlme.c +++ b/net/wireless/mlme.c | |||
| @@ -772,13 +772,13 @@ void cfg80211_cac_event(struct net_device *netdev, | |||
| 772 | if (WARN_ON(!wdev->cac_started)) | 772 | if (WARN_ON(!wdev->cac_started)) |
| 773 | return; | 773 | return; |
| 774 | 774 | ||
| 775 | if (WARN_ON(!wdev->channel)) | 775 | if (WARN_ON(!wdev->chandef.chan)) |
| 776 | return; | 776 | return; |
| 777 | 777 | ||
| 778 | switch (event) { | 778 | switch (event) { |
| 779 | case NL80211_RADAR_CAC_FINISHED: | 779 | case NL80211_RADAR_CAC_FINISHED: |
| 780 | timeout = wdev->cac_start_time + | 780 | timeout = wdev->cac_start_time + |
| 781 | msecs_to_jiffies(IEEE80211_DFS_MIN_CAC_TIME_MS); | 781 | msecs_to_jiffies(wdev->cac_time_ms); |
| 782 | WARN_ON(!time_after_eq(jiffies, timeout)); | 782 | WARN_ON(!time_after_eq(jiffies, timeout)); |
| 783 | cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE); | 783 | cfg80211_set_dfs_state(wiphy, chandef, NL80211_DFS_AVAILABLE); |
| 784 | break; | 784 | break; |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 4fe2e6e2bc76..052c1bf8ffac 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
| @@ -382,6 +382,9 @@ static const struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] = { | |||
| 382 | [NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY }, | 382 | [NL80211_ATTR_VENDOR_DATA] = { .type = NLA_BINARY }, |
| 383 | [NL80211_ATTR_QOS_MAP] = { .type = NLA_BINARY, | 383 | [NL80211_ATTR_QOS_MAP] = { .type = NLA_BINARY, |
| 384 | .len = IEEE80211_QOS_MAP_LEN_MAX }, | 384 | .len = IEEE80211_QOS_MAP_LEN_MAX }, |
| 385 | [NL80211_ATTR_MAC_HINT] = { .len = ETH_ALEN }, | ||
| 386 | [NL80211_ATTR_WIPHY_FREQ_HINT] = { .type = NLA_U32 }, | ||
| 387 | [NL80211_ATTR_TDLS_PEER_CAPABILITY] = { .type = NLA_U32 }, | ||
| 385 | }; | 388 | }; |
| 386 | 389 | ||
| 387 | /* policy for the key attributes */ | 390 | /* policy for the key attributes */ |
| @@ -590,6 +593,10 @@ static int nl80211_msg_put_channel(struct sk_buff *msg, | |||
| 590 | if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME, | 593 | if (nla_put_u32(msg, NL80211_FREQUENCY_ATTR_DFS_TIME, |
| 591 | time)) | 594 | time)) |
| 592 | goto nla_put_failure; | 595 | goto nla_put_failure; |
| 596 | if (nla_put_u32(msg, | ||
| 597 | NL80211_FREQUENCY_ATTR_DFS_CAC_TIME, | ||
| 598 | chan->dfs_cac_ms)) | ||
| 599 | goto nla_put_failure; | ||
| 593 | } | 600 | } |
| 594 | } | 601 | } |
| 595 | 602 | ||
| @@ -855,6 +862,19 @@ static int nl80211_key_allowed(struct wireless_dev *wdev) | |||
| 855 | return 0; | 862 | return 0; |
| 856 | } | 863 | } |
| 857 | 864 | ||
| 865 | static struct ieee80211_channel *nl80211_get_valid_chan(struct wiphy *wiphy, | ||
| 866 | struct nlattr *tb) | ||
| 867 | { | ||
| 868 | struct ieee80211_channel *chan; | ||
| 869 | |||
| 870 | if (tb == NULL) | ||
| 871 | return NULL; | ||
| 872 | chan = ieee80211_get_channel(wiphy, nla_get_u32(tb)); | ||
| 873 | if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) | ||
| 874 | return NULL; | ||
| 875 | return chan; | ||
| 876 | } | ||
| 877 | |||
| 858 | static int nl80211_put_iftypes(struct sk_buff *msg, u32 attr, u16 ifmodes) | 878 | static int nl80211_put_iftypes(struct sk_buff *msg, u32 attr, u16 ifmodes) |
| 859 | { | 879 | { |
| 860 | struct nlattr *nl_modes = nla_nest_start(msg, attr); | 880 | struct nlattr *nl_modes = nla_nest_start(msg, attr); |
| @@ -1586,6 +1606,12 @@ static int nl80211_send_wiphy(struct cfg80211_registered_device *dev, | |||
| 1586 | (nla_put_flag(msg, NL80211_ATTR_SUPPORT_5_MHZ) || | 1606 | (nla_put_flag(msg, NL80211_ATTR_SUPPORT_5_MHZ) || |
| 1587 | nla_put_flag(msg, NL80211_ATTR_SUPPORT_10_MHZ))) | 1607 | nla_put_flag(msg, NL80211_ATTR_SUPPORT_10_MHZ))) |
| 1588 | goto nla_put_failure; | 1608 | goto nla_put_failure; |
| 1609 | |||
| 1610 | if (dev->wiphy.max_ap_assoc_sta && | ||
| 1611 | nla_put_u32(msg, NL80211_ATTR_MAX_AP_ASSOC_STA, | ||
| 1612 | dev->wiphy.max_ap_assoc_sta)) | ||
| 1613 | goto nla_put_failure; | ||
| 1614 | |||
| 1589 | state->split_start++; | 1615 | state->split_start++; |
| 1590 | break; | 1616 | break; |
| 1591 | case 11: | 1617 | case 11: |
| @@ -2035,10 +2061,12 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
| 2035 | nla_for_each_nested(nl_txq_params, | 2061 | nla_for_each_nested(nl_txq_params, |
| 2036 | info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS], | 2062 | info->attrs[NL80211_ATTR_WIPHY_TXQ_PARAMS], |
| 2037 | rem_txq_params) { | 2063 | rem_txq_params) { |
| 2038 | nla_parse(tb, NL80211_TXQ_ATTR_MAX, | 2064 | result = nla_parse(tb, NL80211_TXQ_ATTR_MAX, |
| 2039 | nla_data(nl_txq_params), | 2065 | nla_data(nl_txq_params), |
| 2040 | nla_len(nl_txq_params), | 2066 | nla_len(nl_txq_params), |
| 2041 | txq_params_policy); | 2067 | txq_params_policy); |
| 2068 | if (result) | ||
| 2069 | return result; | ||
| 2042 | result = parse_txq_params(tb, &txq_params); | 2070 | result = parse_txq_params(tb, &txq_params); |
| 2043 | if (result) | 2071 | if (result) |
| 2044 | return result; | 2072 | return result; |
| @@ -3259,7 +3287,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) | |||
| 3259 | if (!err) { | 3287 | if (!err) { |
| 3260 | wdev->preset_chandef = params.chandef; | 3288 | wdev->preset_chandef = params.chandef; |
| 3261 | wdev->beacon_interval = params.beacon_interval; | 3289 | wdev->beacon_interval = params.beacon_interval; |
| 3262 | wdev->channel = params.chandef.chan; | 3290 | wdev->chandef = params.chandef; |
| 3263 | wdev->ssid_len = params.ssid_len; | 3291 | wdev->ssid_len = params.ssid_len; |
| 3264 | memcpy(wdev->ssid, params.ssid, wdev->ssid_len); | 3292 | memcpy(wdev->ssid, params.ssid, wdev->ssid_len); |
| 3265 | } | 3293 | } |
| @@ -3304,7 +3332,7 @@ static int nl80211_stop_ap(struct sk_buff *skb, struct genl_info *info) | |||
| 3304 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 3332 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
| 3305 | struct net_device *dev = info->user_ptr[1]; | 3333 | struct net_device *dev = info->user_ptr[1]; |
| 3306 | 3334 | ||
| 3307 | return cfg80211_stop_ap(rdev, dev); | 3335 | return cfg80211_stop_ap(rdev, dev, false); |
| 3308 | } | 3336 | } |
| 3309 | 3337 | ||
| 3310 | static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { | 3338 | static const struct nla_policy sta_flags_policy[NL80211_STA_FLAG_MAX + 1] = { |
| @@ -3902,8 +3930,8 @@ static struct net_device *get_vlan(struct genl_info *info, | |||
| 3902 | return ERR_PTR(ret); | 3930 | return ERR_PTR(ret); |
| 3903 | } | 3931 | } |
| 3904 | 3932 | ||
| 3905 | static struct nla_policy | 3933 | static const struct nla_policy |
| 3906 | nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] __read_mostly = { | 3934 | nl80211_sta_wme_policy[NL80211_STA_WME_MAX + 1] = { |
| 3907 | [NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 }, | 3935 | [NL80211_STA_WME_UAPSD_QUEUES] = { .type = NLA_U8 }, |
| 3908 | [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 }, | 3936 | [NL80211_STA_WME_MAX_SP] = { .type = NLA_U8 }, |
| 3909 | }; | 3937 | }; |
| @@ -4590,6 +4618,7 @@ static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = | |||
| 4590 | [NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 }, | 4618 | [NL80211_ATTR_FREQ_RANGE_MAX_BW] = { .type = NLA_U32 }, |
| 4591 | [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 }, | 4619 | [NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN] = { .type = NLA_U32 }, |
| 4592 | [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 }, | 4620 | [NL80211_ATTR_POWER_RULE_MAX_EIRP] = { .type = NLA_U32 }, |
| 4621 | [NL80211_ATTR_DFS_CAC_TIME] = { .type = NLA_U32 }, | ||
| 4593 | }; | 4622 | }; |
| 4594 | 4623 | ||
| 4595 | static int parse_reg_rule(struct nlattr *tb[], | 4624 | static int parse_reg_rule(struct nlattr *tb[], |
| @@ -4625,6 +4654,10 @@ static int parse_reg_rule(struct nlattr *tb[], | |||
| 4625 | power_rule->max_antenna_gain = | 4654 | power_rule->max_antenna_gain = |
| 4626 | nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]); | 4655 | nla_get_u32(tb[NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN]); |
| 4627 | 4656 | ||
| 4657 | if (tb[NL80211_ATTR_DFS_CAC_TIME]) | ||
| 4658 | reg_rule->dfs_cac_ms = | ||
| 4659 | nla_get_u32(tb[NL80211_ATTR_DFS_CAC_TIME]); | ||
| 4660 | |||
| 4628 | return 0; | 4661 | return 0; |
| 4629 | } | 4662 | } |
| 4630 | 4663 | ||
| @@ -5086,6 +5119,7 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) | |||
| 5086 | const struct ieee80211_reg_rule *reg_rule; | 5119 | const struct ieee80211_reg_rule *reg_rule; |
| 5087 | const struct ieee80211_freq_range *freq_range; | 5120 | const struct ieee80211_freq_range *freq_range; |
| 5088 | const struct ieee80211_power_rule *power_rule; | 5121 | const struct ieee80211_power_rule *power_rule; |
| 5122 | unsigned int max_bandwidth_khz; | ||
| 5089 | 5123 | ||
| 5090 | reg_rule = ®dom->reg_rules[i]; | 5124 | reg_rule = ®dom->reg_rules[i]; |
| 5091 | freq_range = ®_rule->freq_range; | 5125 | freq_range = ®_rule->freq_range; |
| @@ -5095,6 +5129,11 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) | |||
| 5095 | if (!nl_reg_rule) | 5129 | if (!nl_reg_rule) |
| 5096 | goto nla_put_failure_rcu; | 5130 | goto nla_put_failure_rcu; |
| 5097 | 5131 | ||
| 5132 | max_bandwidth_khz = freq_range->max_bandwidth_khz; | ||
| 5133 | if (!max_bandwidth_khz) | ||
| 5134 | max_bandwidth_khz = reg_get_max_bandwidth(regdom, | ||
| 5135 | reg_rule); | ||
| 5136 | |||
| 5098 | if (nla_put_u32(msg, NL80211_ATTR_REG_RULE_FLAGS, | 5137 | if (nla_put_u32(msg, NL80211_ATTR_REG_RULE_FLAGS, |
| 5099 | reg_rule->flags) || | 5138 | reg_rule->flags) || |
| 5100 | nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_START, | 5139 | nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_START, |
| @@ -5102,11 +5141,13 @@ static int nl80211_get_reg(struct sk_buff *skb, struct genl_info *info) | |||
| 5102 | nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_END, | 5141 | nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_END, |
| 5103 | freq_range->end_freq_khz) || | 5142 | freq_range->end_freq_khz) || |
| 5104 | nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_MAX_BW, | 5143 | nla_put_u32(msg, NL80211_ATTR_FREQ_RANGE_MAX_BW, |
| 5105 | freq_range->max_bandwidth_khz) || | 5144 | max_bandwidth_khz) || |
| 5106 | nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN, | 5145 | nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_ANT_GAIN, |
| 5107 | power_rule->max_antenna_gain) || | 5146 | power_rule->max_antenna_gain) || |
| 5108 | nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP, | 5147 | nla_put_u32(msg, NL80211_ATTR_POWER_RULE_MAX_EIRP, |
| 5109 | power_rule->max_eirp)) | 5148 | power_rule->max_eirp) || |
| 5149 | nla_put_u32(msg, NL80211_ATTR_DFS_CAC_TIME, | ||
| 5150 | reg_rule->dfs_cac_ms)) | ||
| 5110 | goto nla_put_failure_rcu; | 5151 | goto nla_put_failure_rcu; |
| 5111 | 5152 | ||
| 5112 | nla_nest_end(msg, nl_reg_rule); | 5153 | nla_nest_end(msg, nl_reg_rule); |
| @@ -5178,9 +5219,11 @@ static int nl80211_set_reg(struct sk_buff *skb, struct genl_info *info) | |||
| 5178 | 5219 | ||
| 5179 | nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES], | 5220 | nla_for_each_nested(nl_reg_rule, info->attrs[NL80211_ATTR_REG_RULES], |
| 5180 | rem_reg_rules) { | 5221 | rem_reg_rules) { |
| 5181 | nla_parse(tb, NL80211_REG_RULE_ATTR_MAX, | 5222 | r = nla_parse(tb, NL80211_REG_RULE_ATTR_MAX, |
| 5182 | nla_data(nl_reg_rule), nla_len(nl_reg_rule), | 5223 | nla_data(nl_reg_rule), nla_len(nl_reg_rule), |
| 5183 | reg_rule_policy); | 5224 | reg_rule_policy); |
| 5225 | if (r) | ||
| 5226 | goto bad_reg; | ||
| 5184 | r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]); | 5227 | r = parse_reg_rule(tb, &rd->reg_rules[rule_idx]); |
| 5185 | if (r) | 5228 | if (r) |
| 5186 | goto bad_reg; | 5229 | goto bad_reg; |
| @@ -5443,6 +5486,7 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, | |||
| 5443 | enum ieee80211_band band; | 5486 | enum ieee80211_band band; |
| 5444 | size_t ie_len; | 5487 | size_t ie_len; |
| 5445 | struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1]; | 5488 | struct nlattr *tb[NL80211_SCHED_SCAN_MATCH_ATTR_MAX + 1]; |
| 5489 | s32 default_match_rssi = NL80211_SCAN_RSSI_THOLD_OFF; | ||
| 5446 | 5490 | ||
| 5447 | if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) || | 5491 | if (!(rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_SCHED_SCAN) || |
| 5448 | !rdev->ops->sched_scan_start) | 5492 | !rdev->ops->sched_scan_start) |
| @@ -5477,11 +5521,40 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, | |||
| 5477 | if (n_ssids > wiphy->max_sched_scan_ssids) | 5521 | if (n_ssids > wiphy->max_sched_scan_ssids) |
| 5478 | return -EINVAL; | 5522 | return -EINVAL; |
| 5479 | 5523 | ||
| 5480 | if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) | 5524 | /* |
| 5525 | * First, count the number of 'real' matchsets. Due to an issue with | ||
| 5526 | * the old implementation, matchsets containing only the RSSI attribute | ||
| 5527 | * (NL80211_SCHED_SCAN_MATCH_ATTR_RSSI) are considered as the 'default' | ||
| 5528 | * RSSI for all matchsets, rather than their own matchset for reporting | ||
| 5529 | * all APs with a strong RSSI. This is needed to be compatible with | ||
| 5530 | * older userspace that treated a matchset with only the RSSI as the | ||
| 5531 | * global RSSI for all other matchsets - if there are other matchsets. | ||
| 5532 | */ | ||
| 5533 | if (info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH]) { | ||
| 5481 | nla_for_each_nested(attr, | 5534 | nla_for_each_nested(attr, |
| 5482 | info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH], | 5535 | info->attrs[NL80211_ATTR_SCHED_SCAN_MATCH], |
| 5483 | tmp) | 5536 | tmp) { |
| 5484 | n_match_sets++; | 5537 | struct nlattr *rssi; |
| 5538 | |||
| 5539 | err = nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX, | ||
| 5540 | nla_data(attr), nla_len(attr), | ||
| 5541 | nl80211_match_policy); | ||
| 5542 | if (err) | ||
| 5543 | return err; | ||
| 5544 | /* add other standalone attributes here */ | ||
| 5545 | if (tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID]) { | ||
| 5546 | n_match_sets++; | ||
| 5547 | continue; | ||
| 5548 | } | ||
| 5549 | rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI]; | ||
| 5550 | if (rssi) | ||
| 5551 | default_match_rssi = nla_get_s32(rssi); | ||
| 5552 | } | ||
| 5553 | } | ||
| 5554 | |||
| 5555 | /* However, if there's no other matchset, add the RSSI one */ | ||
| 5556 | if (!n_match_sets && default_match_rssi != NL80211_SCAN_RSSI_THOLD_OFF) | ||
| 5557 | n_match_sets = 1; | ||
| 5485 | 5558 | ||
| 5486 | if (n_match_sets > wiphy->max_match_sets) | 5559 | if (n_match_sets > wiphy->max_match_sets) |
| 5487 | return -EINVAL; | 5560 | return -EINVAL; |
| @@ -5602,11 +5675,22 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, | |||
| 5602 | tmp) { | 5675 | tmp) { |
| 5603 | struct nlattr *ssid, *rssi; | 5676 | struct nlattr *ssid, *rssi; |
| 5604 | 5677 | ||
| 5605 | nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX, | 5678 | err = nla_parse(tb, NL80211_SCHED_SCAN_MATCH_ATTR_MAX, |
| 5606 | nla_data(attr), nla_len(attr), | 5679 | nla_data(attr), nla_len(attr), |
| 5607 | nl80211_match_policy); | 5680 | nl80211_match_policy); |
| 5681 | if (err) | ||
| 5682 | goto out_free; | ||
| 5608 | ssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID]; | 5683 | ssid = tb[NL80211_SCHED_SCAN_MATCH_ATTR_SSID]; |
| 5609 | if (ssid) { | 5684 | if (ssid) { |
| 5685 | if (WARN_ON(i >= n_match_sets)) { | ||
| 5686 | /* this indicates a programming error, | ||
| 5687 | * the loop above should have verified | ||
| 5688 | * things properly | ||
| 5689 | */ | ||
| 5690 | err = -EINVAL; | ||
| 5691 | goto out_free; | ||
| 5692 | } | ||
| 5693 | |||
| 5610 | if (nla_len(ssid) > IEEE80211_MAX_SSID_LEN) { | 5694 | if (nla_len(ssid) > IEEE80211_MAX_SSID_LEN) { |
| 5611 | err = -EINVAL; | 5695 | err = -EINVAL; |
| 5612 | goto out_free; | 5696 | goto out_free; |
| @@ -5615,19 +5699,32 @@ static int nl80211_start_sched_scan(struct sk_buff *skb, | |||
| 5615 | nla_data(ssid), nla_len(ssid)); | 5699 | nla_data(ssid), nla_len(ssid)); |
| 5616 | request->match_sets[i].ssid.ssid_len = | 5700 | request->match_sets[i].ssid.ssid_len = |
| 5617 | nla_len(ssid); | 5701 | nla_len(ssid); |
| 5702 | /* special attribute - old implemenation w/a */ | ||
| 5703 | request->match_sets[i].rssi_thold = | ||
| 5704 | default_match_rssi; | ||
| 5705 | rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI]; | ||
| 5706 | if (rssi) | ||
| 5707 | request->match_sets[i].rssi_thold = | ||
| 5708 | nla_get_s32(rssi); | ||
| 5618 | } | 5709 | } |
| 5619 | rssi = tb[NL80211_SCHED_SCAN_MATCH_ATTR_RSSI]; | ||
| 5620 | if (rssi) | ||
| 5621 | request->rssi_thold = nla_get_u32(rssi); | ||
| 5622 | else | ||
| 5623 | request->rssi_thold = | ||
| 5624 | NL80211_SCAN_RSSI_THOLD_OFF; | ||
| 5625 | i++; | 5710 | i++; |
| 5626 | } | 5711 | } |
| 5712 | |||
| 5713 | /* there was no other matchset, so the RSSI one is alone */ | ||
| 5714 | if (i == 0) | ||
| 5715 | request->match_sets[0].rssi_thold = default_match_rssi; | ||
| 5716 | |||
| 5717 | request->min_rssi_thold = INT_MAX; | ||
| 5718 | for (i = 0; i < n_match_sets; i++) | ||
| 5719 | request->min_rssi_thold = | ||
| 5720 | min(request->match_sets[i].rssi_thold, | ||
| 5721 | request->min_rssi_thold); | ||
| 5722 | } else { | ||
| 5723 | request->min_rssi_thold = NL80211_SCAN_RSSI_THOLD_OFF; | ||
| 5627 | } | 5724 | } |
| 5628 | 5725 | ||
| 5629 | if (info->attrs[NL80211_ATTR_IE]) { | 5726 | if (ie_len) { |
| 5630 | request->ie_len = nla_len(info->attrs[NL80211_ATTR_IE]); | 5727 | request->ie_len = ie_len; |
| 5631 | memcpy((void *)request->ie, | 5728 | memcpy((void *)request->ie, |
| 5632 | nla_data(info->attrs[NL80211_ATTR_IE]), | 5729 | nla_data(info->attrs[NL80211_ATTR_IE]), |
| 5633 | request->ie_len); | 5730 | request->ie_len); |
| @@ -5682,6 +5779,7 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, | |||
| 5682 | struct wireless_dev *wdev = dev->ieee80211_ptr; | 5779 | struct wireless_dev *wdev = dev->ieee80211_ptr; |
| 5683 | struct cfg80211_chan_def chandef; | 5780 | struct cfg80211_chan_def chandef; |
| 5684 | enum nl80211_dfs_regions dfs_region; | 5781 | enum nl80211_dfs_regions dfs_region; |
| 5782 | unsigned int cac_time_ms; | ||
| 5685 | int err; | 5783 | int err; |
| 5686 | 5784 | ||
| 5687 | dfs_region = reg_get_dfs_region(wdev->wiphy); | 5785 | dfs_region = reg_get_dfs_region(wdev->wiphy); |
| @@ -5717,11 +5815,17 @@ static int nl80211_start_radar_detection(struct sk_buff *skb, | |||
| 5717 | if (err) | 5815 | if (err) |
| 5718 | return err; | 5816 | return err; |
| 5719 | 5817 | ||
| 5720 | err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef); | 5818 | cac_time_ms = cfg80211_chandef_dfs_cac_time(&rdev->wiphy, &chandef); |
| 5819 | if (WARN_ON(!cac_time_ms)) | ||
| 5820 | cac_time_ms = IEEE80211_DFS_MIN_CAC_TIME_MS; | ||
| 5821 | |||
| 5822 | err = rdev->ops->start_radar_detection(&rdev->wiphy, dev, &chandef, | ||
| 5823 | cac_time_ms); | ||
| 5721 | if (!err) { | 5824 | if (!err) { |
| 5722 | wdev->channel = chandef.chan; | 5825 | wdev->chandef = chandef; |
| 5723 | wdev->cac_started = true; | 5826 | wdev->cac_started = true; |
| 5724 | wdev->cac_start_time = jiffies; | 5827 | wdev->cac_start_time = jiffies; |
| 5828 | wdev->cac_time_ms = cac_time_ms; | ||
| 5725 | } | 5829 | } |
| 5726 | return err; | 5830 | return err; |
| 5727 | } | 5831 | } |
| @@ -5751,10 +5855,15 @@ static int nl80211_channel_switch(struct sk_buff *skb, struct genl_info *info) | |||
| 5751 | 5855 | ||
| 5752 | /* useless if AP is not running */ | 5856 | /* useless if AP is not running */ |
| 5753 | if (!wdev->beacon_interval) | 5857 | if (!wdev->beacon_interval) |
| 5754 | return -EINVAL; | 5858 | return -ENOTCONN; |
| 5755 | break; | 5859 | break; |
| 5756 | case NL80211_IFTYPE_ADHOC: | 5860 | case NL80211_IFTYPE_ADHOC: |
| 5861 | if (!wdev->ssid_len) | ||
| 5862 | return -ENOTCONN; | ||
| 5863 | break; | ||
| 5757 | case NL80211_IFTYPE_MESH_POINT: | 5864 | case NL80211_IFTYPE_MESH_POINT: |
| 5865 | if (!wdev->mesh_id_len) | ||
| 5866 | return -ENOTCONN; | ||
| 5758 | break; | 5867 | break; |
| 5759 | default: | 5868 | default: |
| 5760 | return -EOPNOTSUPP; | 5869 | return -EOPNOTSUPP; |
| @@ -5822,17 +5931,22 @@ skip_beacons: | |||
| 5822 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef)) | 5931 | if (!cfg80211_reg_can_beacon(&rdev->wiphy, ¶ms.chandef)) |
| 5823 | return -EINVAL; | 5932 | return -EINVAL; |
| 5824 | 5933 | ||
| 5825 | if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP || | 5934 | switch (dev->ieee80211_ptr->iftype) { |
| 5826 | dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_GO || | 5935 | case NL80211_IFTYPE_AP: |
| 5827 | dev->ieee80211_ptr->iftype == NL80211_IFTYPE_ADHOC) { | 5936 | case NL80211_IFTYPE_P2P_GO: |
| 5937 | case NL80211_IFTYPE_ADHOC: | ||
| 5938 | case NL80211_IFTYPE_MESH_POINT: | ||
| 5828 | err = cfg80211_chandef_dfs_required(wdev->wiphy, | 5939 | err = cfg80211_chandef_dfs_required(wdev->wiphy, |
| 5829 | ¶ms.chandef); | 5940 | ¶ms.chandef); |
| 5830 | if (err < 0) { | 5941 | if (err < 0) |
| 5831 | return err; | 5942 | return err; |
| 5832 | } else if (err) { | 5943 | if (err) { |
| 5833 | radar_detect_width = BIT(params.chandef.width); | 5944 | radar_detect_width = BIT(params.chandef.width); |
| 5834 | params.radar_required = true; | 5945 | params.radar_required = true; |
| 5835 | } | 5946 | } |
| 5947 | break; | ||
| 5948 | default: | ||
| 5949 | break; | ||
| 5836 | } | 5950 | } |
| 5837 | 5951 | ||
| 5838 | err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, | 5952 | err = cfg80211_can_use_iftype_chan(rdev, wdev, wdev->iftype, |
| @@ -6192,9 +6306,9 @@ static int nl80211_authenticate(struct sk_buff *skb, struct genl_info *info) | |||
| 6192 | return -EOPNOTSUPP; | 6306 | return -EOPNOTSUPP; |
| 6193 | 6307 | ||
| 6194 | bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); | 6308 | bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); |
| 6195 | chan = ieee80211_get_channel(&rdev->wiphy, | 6309 | chan = nl80211_get_valid_chan(&rdev->wiphy, |
| 6196 | nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); | 6310 | info->attrs[NL80211_ATTR_WIPHY_FREQ]); |
| 6197 | if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED)) | 6311 | if (!chan) |
| 6198 | return -EINVAL; | 6312 | return -EINVAL; |
| 6199 | 6313 | ||
| 6200 | ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); | 6314 | ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); |
| @@ -6347,9 +6461,9 @@ static int nl80211_associate(struct sk_buff *skb, struct genl_info *info) | |||
| 6347 | 6461 | ||
| 6348 | bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); | 6462 | bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); |
| 6349 | 6463 | ||
| 6350 | chan = ieee80211_get_channel(&rdev->wiphy, | 6464 | chan = nl80211_get_valid_chan(&rdev->wiphy, |
| 6351 | nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); | 6465 | info->attrs[NL80211_ATTR_WIPHY_FREQ]); |
| 6352 | if (!chan || (chan->flags & IEEE80211_CHAN_DISABLED)) | 6466 | if (!chan) |
| 6353 | return -EINVAL; | 6467 | return -EINVAL; |
| 6354 | 6468 | ||
| 6355 | ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); | 6469 | ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); |
| @@ -6985,6 +7099,9 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) | |||
| 6985 | 7099 | ||
| 6986 | if (info->attrs[NL80211_ATTR_MAC]) | 7100 | if (info->attrs[NL80211_ATTR_MAC]) |
| 6987 | connect.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); | 7101 | connect.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]); |
| 7102 | else if (info->attrs[NL80211_ATTR_MAC_HINT]) | ||
| 7103 | connect.bssid_hint = | ||
| 7104 | nla_data(info->attrs[NL80211_ATTR_MAC_HINT]); | ||
| 6988 | connect.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); | 7105 | connect.ssid = nla_data(info->attrs[NL80211_ATTR_SSID]); |
| 6989 | connect.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); | 7106 | connect.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]); |
| 6990 | 7107 | ||
| @@ -7003,11 +7120,14 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info) | |||
| 7003 | } | 7120 | } |
| 7004 | 7121 | ||
| 7005 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { | 7122 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { |
| 7006 | connect.channel = | 7123 | connect.channel = nl80211_get_valid_chan( |
| 7007 | ieee80211_get_channel(wiphy, | 7124 | wiphy, info->attrs[NL80211_ATTR_WIPHY_FREQ]); |
| 7008 | nla_get_u32(info->attrs[NL80211_ATTR_WIPHY_FREQ])); | 7125 | if (!connect.channel) |
| 7009 | if (!connect.channel || | 7126 | return -EINVAL; |
| 7010 | connect.channel->flags & IEEE80211_CHAN_DISABLED) | 7127 | } else if (info->attrs[NL80211_ATTR_WIPHY_FREQ_HINT]) { |
| 7128 | connect.channel_hint = nl80211_get_valid_chan( | ||
| 7129 | wiphy, info->attrs[NL80211_ATTR_WIPHY_FREQ_HINT]); | ||
| 7130 | if (!connect.channel_hint) | ||
| 7011 | return -EINVAL; | 7131 | return -EINVAL; |
| 7012 | } | 7132 | } |
| 7013 | 7133 | ||
| @@ -7174,6 +7294,7 @@ static int nl80211_tdls_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
| 7174 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; | 7294 | struct cfg80211_registered_device *rdev = info->user_ptr[0]; |
| 7175 | struct net_device *dev = info->user_ptr[1]; | 7295 | struct net_device *dev = info->user_ptr[1]; |
| 7176 | u8 action_code, dialog_token; | 7296 | u8 action_code, dialog_token; |
| 7297 | u32 peer_capability = 0; | ||
| 7177 | u16 status_code; | 7298 | u16 status_code; |
| 7178 | u8 *peer; | 7299 | u8 *peer; |
| 7179 | 7300 | ||
| @@ -7192,9 +7313,12 @@ static int nl80211_tdls_mgmt(struct sk_buff *skb, struct genl_info *info) | |||
| 7192 | action_code = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_ACTION]); | 7313 | action_code = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_ACTION]); |
| 7193 | status_code = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]); | 7314 | status_code = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]); |
| 7194 | dialog_token = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN]); | 7315 | dialog_token = nla_get_u8(info->attrs[NL80211_ATTR_TDLS_DIALOG_TOKEN]); |
| 7316 | if (info->attrs[NL80211_ATTR_TDLS_PEER_CAPABILITY]) | ||
| 7317 | peer_capability = | ||
| 7318 | nla_get_u32(info->attrs[NL80211_ATTR_TDLS_PEER_CAPABILITY]); | ||
| 7195 | 7319 | ||
| 7196 | return rdev_tdls_mgmt(rdev, dev, peer, action_code, | 7320 | return rdev_tdls_mgmt(rdev, dev, peer, action_code, |
| 7197 | dialog_token, status_code, | 7321 | dialog_token, status_code, peer_capability, |
| 7198 | nla_data(info->attrs[NL80211_ATTR_IE]), | 7322 | nla_data(info->attrs[NL80211_ATTR_IE]), |
| 7199 | nla_len(info->attrs[NL80211_ATTR_IE])); | 7323 | nla_len(info->attrs[NL80211_ATTR_IE])); |
| 7200 | } | 7324 | } |
| @@ -7421,6 +7545,7 @@ static const struct nla_policy nl80211_txattr_policy[NL80211_TXRATE_MAX + 1] = { | |||
| 7421 | [NL80211_TXRATE_HT] = { .type = NLA_BINARY, | 7545 | [NL80211_TXRATE_HT] = { .type = NLA_BINARY, |
| 7422 | .len = NL80211_MAX_SUPP_HT_RATES }, | 7546 | .len = NL80211_MAX_SUPP_HT_RATES }, |
| 7423 | [NL80211_TXRATE_VHT] = { .len = sizeof(struct nl80211_txrate_vht)}, | 7547 | [NL80211_TXRATE_VHT] = { .len = sizeof(struct nl80211_txrate_vht)}, |
| 7548 | [NL80211_TXRATE_GI] = { .type = NLA_U8 }, | ||
| 7424 | }; | 7549 | }; |
| 7425 | 7550 | ||
| 7426 | static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, | 7551 | static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, |
| @@ -7467,16 +7592,19 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, | |||
| 7467 | * directly to the enum ieee80211_band values used in cfg80211. | 7592 | * directly to the enum ieee80211_band values used in cfg80211. |
| 7468 | */ | 7593 | */ |
| 7469 | BUILD_BUG_ON(NL80211_MAX_SUPP_HT_RATES > IEEE80211_HT_MCS_MASK_LEN * 8); | 7594 | BUILD_BUG_ON(NL80211_MAX_SUPP_HT_RATES > IEEE80211_HT_MCS_MASK_LEN * 8); |
| 7470 | nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem) | 7595 | nla_for_each_nested(tx_rates, info->attrs[NL80211_ATTR_TX_RATES], rem) { |
| 7471 | { | ||
| 7472 | enum ieee80211_band band = nla_type(tx_rates); | 7596 | enum ieee80211_band band = nla_type(tx_rates); |
| 7597 | int err; | ||
| 7598 | |||
| 7473 | if (band < 0 || band >= IEEE80211_NUM_BANDS) | 7599 | if (band < 0 || band >= IEEE80211_NUM_BANDS) |
| 7474 | return -EINVAL; | 7600 | return -EINVAL; |
| 7475 | sband = rdev->wiphy.bands[band]; | 7601 | sband = rdev->wiphy.bands[band]; |
| 7476 | if (sband == NULL) | 7602 | if (sband == NULL) |
| 7477 | return -EINVAL; | 7603 | return -EINVAL; |
| 7478 | nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates), | 7604 | err = nla_parse(tb, NL80211_TXRATE_MAX, nla_data(tx_rates), |
| 7479 | nla_len(tx_rates), nl80211_txattr_policy); | 7605 | nla_len(tx_rates), nl80211_txattr_policy); |
| 7606 | if (err) | ||
| 7607 | return err; | ||
| 7480 | if (tb[NL80211_TXRATE_LEGACY]) { | 7608 | if (tb[NL80211_TXRATE_LEGACY]) { |
| 7481 | mask.control[band].legacy = rateset_to_mask( | 7609 | mask.control[band].legacy = rateset_to_mask( |
| 7482 | sband, | 7610 | sband, |
| @@ -7501,6 +7629,12 @@ static int nl80211_set_tx_bitrate_mask(struct sk_buff *skb, | |||
| 7501 | mask.control[band].vht_mcs)) | 7629 | mask.control[band].vht_mcs)) |
| 7502 | return -EINVAL; | 7630 | return -EINVAL; |
| 7503 | } | 7631 | } |
| 7632 | if (tb[NL80211_TXRATE_GI]) { | ||
| 7633 | mask.control[band].gi = | ||
| 7634 | nla_get_u8(tb[NL80211_TXRATE_GI]); | ||
| 7635 | if (mask.control[band].gi > NL80211_TXRATE_FORCE_LGI) | ||
| 7636 | return -EINVAL; | ||
| 7637 | } | ||
| 7504 | 7638 | ||
| 7505 | if (mask.control[band].legacy == 0) { | 7639 | if (mask.control[band].legacy == 0) { |
| 7506 | /* don't allow empty legacy rates if HT or VHT | 7640 | /* don't allow empty legacy rates if HT or VHT |
| @@ -7777,8 +7911,8 @@ static int nl80211_get_power_save(struct sk_buff *skb, struct genl_info *info) | |||
| 7777 | return err; | 7911 | return err; |
| 7778 | } | 7912 | } |
| 7779 | 7913 | ||
| 7780 | static struct nla_policy | 7914 | static const struct nla_policy |
| 7781 | nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] __read_mostly = { | 7915 | nl80211_attr_cqm_policy[NL80211_ATTR_CQM_MAX + 1] = { |
| 7782 | [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 }, | 7916 | [NL80211_ATTR_CQM_RSSI_THOLD] = { .type = NLA_U32 }, |
| 7783 | [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 }, | 7917 | [NL80211_ATTR_CQM_RSSI_HYST] = { .type = NLA_U32 }, |
| 7784 | [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 }, | 7918 | [NL80211_ATTR_CQM_RSSI_THRESHOLD_EVENT] = { .type = NLA_U32 }, |
| @@ -11107,7 +11241,8 @@ void cfg80211_ch_switch_notify(struct net_device *dev, | |||
| 11107 | wdev->iftype != NL80211_IFTYPE_MESH_POINT)) | 11241 | wdev->iftype != NL80211_IFTYPE_MESH_POINT)) |
| 11108 | return; | 11242 | return; |
| 11109 | 11243 | ||
| 11110 | wdev->channel = chandef->chan; | 11244 | wdev->chandef = *chandef; |
| 11245 | wdev->preset_chandef = *chandef; | ||
| 11111 | nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL); | 11246 | nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL); |
| 11112 | } | 11247 | } |
| 11113 | EXPORT_SYMBOL(cfg80211_ch_switch_notify); | 11248 | EXPORT_SYMBOL(cfg80211_ch_switch_notify); |
| @@ -11621,6 +11756,35 @@ void cfg80211_crit_proto_stopped(struct wireless_dev *wdev, gfp_t gfp) | |||
| 11621 | } | 11756 | } |
| 11622 | EXPORT_SYMBOL(cfg80211_crit_proto_stopped); | 11757 | EXPORT_SYMBOL(cfg80211_crit_proto_stopped); |
| 11623 | 11758 | ||
| 11759 | void nl80211_send_ap_stopped(struct wireless_dev *wdev) | ||
| 11760 | { | ||
| 11761 | struct wiphy *wiphy = wdev->wiphy; | ||
| 11762 | struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy); | ||
| 11763 | struct sk_buff *msg; | ||
| 11764 | void *hdr; | ||
| 11765 | |||
| 11766 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
| 11767 | if (!msg) | ||
| 11768 | return; | ||
| 11769 | |||
| 11770 | hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_STOP_AP); | ||
| 11771 | if (!hdr) | ||
| 11772 | goto out; | ||
| 11773 | |||
| 11774 | if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || | ||
| 11775 | nla_put_u32(msg, NL80211_ATTR_IFINDEX, wdev->netdev->ifindex) || | ||
| 11776 | nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev))) | ||
| 11777 | goto out; | ||
| 11778 | |||
| 11779 | genlmsg_end(msg, hdr); | ||
| 11780 | |||
| 11781 | genlmsg_multicast_netns(&nl80211_fam, wiphy_net(wiphy), msg, 0, | ||
| 11782 | NL80211_MCGRP_MLME, GFP_KERNEL); | ||
| 11783 | return; | ||
| 11784 | out: | ||
| 11785 | nlmsg_free(msg); | ||
| 11786 | } | ||
| 11787 | |||
| 11624 | /* initialisation/exit functions */ | 11788 | /* initialisation/exit functions */ |
| 11625 | 11789 | ||
| 11626 | int nl80211_init(void) | 11790 | int nl80211_init(void) |
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index 75799746d845..1e6df9630f42 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
| @@ -74,6 +74,8 @@ nl80211_radar_notify(struct cfg80211_registered_device *rdev, | |||
| 74 | enum nl80211_radar_event event, | 74 | enum nl80211_radar_event event, |
| 75 | struct net_device *netdev, gfp_t gfp); | 75 | struct net_device *netdev, gfp_t gfp); |
| 76 | 76 | ||
| 77 | void nl80211_send_ap_stopped(struct wireless_dev *wdev); | ||
| 78 | |||
| 77 | void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev); | 79 | void cfg80211_rdev_free_coalesce(struct cfg80211_registered_device *rdev); |
| 78 | 80 | ||
| 79 | #endif /* __NET_WIRELESS_NL80211_H */ | 81 | #endif /* __NET_WIRELESS_NL80211_H */ |
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h index c8e225947adb..74d97d33c938 100644 --- a/net/wireless/rdev-ops.h +++ b/net/wireless/rdev-ops.h | |||
| @@ -769,13 +769,16 @@ static inline int rdev_set_rekey_data(struct cfg80211_registered_device *rdev, | |||
| 769 | static inline int rdev_tdls_mgmt(struct cfg80211_registered_device *rdev, | 769 | static inline int rdev_tdls_mgmt(struct cfg80211_registered_device *rdev, |
| 770 | struct net_device *dev, u8 *peer, | 770 | struct net_device *dev, u8 *peer, |
| 771 | u8 action_code, u8 dialog_token, | 771 | u8 action_code, u8 dialog_token, |
| 772 | u16 status_code, const u8 *buf, size_t len) | 772 | u16 status_code, u32 peer_capability, |
| 773 | const u8 *buf, size_t len) | ||
| 773 | { | 774 | { |
| 774 | int ret; | 775 | int ret; |
| 775 | trace_rdev_tdls_mgmt(&rdev->wiphy, dev, peer, action_code, | 776 | trace_rdev_tdls_mgmt(&rdev->wiphy, dev, peer, action_code, |
| 776 | dialog_token, status_code, buf, len); | 777 | dialog_token, status_code, peer_capability, |
| 778 | buf, len); | ||
| 777 | ret = rdev->ops->tdls_mgmt(&rdev->wiphy, dev, peer, action_code, | 779 | ret = rdev->ops->tdls_mgmt(&rdev->wiphy, dev, peer, action_code, |
| 778 | dialog_token, status_code, buf, len); | 780 | dialog_token, status_code, peer_capability, |
| 781 | buf, len); | ||
| 779 | trace_rdev_return_int(&rdev->wiphy, ret); | 782 | trace_rdev_return_int(&rdev->wiphy, ret); |
| 780 | return ret; | 783 | return ret; |
| 781 | } | 784 | } |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index f0541370e68e..f59aaac586f8 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
| @@ -91,10 +91,6 @@ static struct regulatory_request __rcu *last_request = | |||
| 91 | /* To trigger userspace events */ | 91 | /* To trigger userspace events */ |
| 92 | static struct platform_device *reg_pdev; | 92 | static struct platform_device *reg_pdev; |
| 93 | 93 | ||
| 94 | static struct device_type reg_device_type = { | ||
| 95 | .uevent = reg_device_uevent, | ||
| 96 | }; | ||
| 97 | |||
| 98 | /* | 94 | /* |
| 99 | * Central wireless core regulatory domains, we only need two, | 95 | * Central wireless core regulatory domains, we only need two, |
| 100 | * the current one and a world regulatory domain in case we have no | 96 | * the current one and a world regulatory domain in case we have no |
| @@ -244,19 +240,21 @@ static char user_alpha2[2]; | |||
| 244 | module_param(ieee80211_regdom, charp, 0444); | 240 | module_param(ieee80211_regdom, charp, 0444); |
| 245 | MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); | 241 | MODULE_PARM_DESC(ieee80211_regdom, "IEEE 802.11 regulatory domain code"); |
| 246 | 242 | ||
| 247 | static void reg_kfree_last_request(void) | 243 | static void reg_free_request(struct regulatory_request *lr) |
| 248 | { | 244 | { |
| 249 | struct regulatory_request *lr; | ||
| 250 | |||
| 251 | lr = get_last_request(); | ||
| 252 | |||
| 253 | if (lr != &core_request_world && lr) | 245 | if (lr != &core_request_world && lr) |
| 254 | kfree_rcu(lr, rcu_head); | 246 | kfree_rcu(lr, rcu_head); |
| 255 | } | 247 | } |
| 256 | 248 | ||
| 257 | static void reg_update_last_request(struct regulatory_request *request) | 249 | static void reg_update_last_request(struct regulatory_request *request) |
| 258 | { | 250 | { |
| 259 | reg_kfree_last_request(); | 251 | struct regulatory_request *lr; |
| 252 | |||
| 253 | lr = get_last_request(); | ||
| 254 | if (lr == request) | ||
| 255 | return; | ||
| 256 | |||
| 257 | reg_free_request(lr); | ||
| 260 | rcu_assign_pointer(last_request, request); | 258 | rcu_assign_pointer(last_request, request); |
| 261 | } | 259 | } |
| 262 | 260 | ||
| @@ -487,11 +485,16 @@ static inline void reg_regdb_query(const char *alpha2) {} | |||
| 487 | 485 | ||
| 488 | /* | 486 | /* |
| 489 | * This lets us keep regulatory code which is updated on a regulatory | 487 | * This lets us keep regulatory code which is updated on a regulatory |
| 490 | * basis in userspace. Country information is filled in by | 488 | * basis in userspace. |
| 491 | * reg_device_uevent | ||
| 492 | */ | 489 | */ |
| 493 | static int call_crda(const char *alpha2) | 490 | static int call_crda(const char *alpha2) |
| 494 | { | 491 | { |
| 492 | char country[12]; | ||
| 493 | char *env[] = { country, NULL }; | ||
| 494 | |||
| 495 | snprintf(country, sizeof(country), "COUNTRY=%c%c", | ||
| 496 | alpha2[0], alpha2[1]); | ||
| 497 | |||
| 495 | if (!is_world_regdom((char *) alpha2)) | 498 | if (!is_world_regdom((char *) alpha2)) |
| 496 | pr_info("Calling CRDA for country: %c%c\n", | 499 | pr_info("Calling CRDA for country: %c%c\n", |
| 497 | alpha2[0], alpha2[1]); | 500 | alpha2[0], alpha2[1]); |
| @@ -501,7 +504,7 @@ static int call_crda(const char *alpha2) | |||
| 501 | /* query internal regulatory database (if it exists) */ | 504 | /* query internal regulatory database (if it exists) */ |
| 502 | reg_regdb_query(alpha2); | 505 | reg_regdb_query(alpha2); |
| 503 | 506 | ||
| 504 | return kobject_uevent(®_pdev->dev.kobj, KOBJ_CHANGE); | 507 | return kobject_uevent_env(®_pdev->dev.kobj, KOBJ_CHANGE, env); |
| 505 | } | 508 | } |
| 506 | 509 | ||
| 507 | static enum reg_request_treatment | 510 | static enum reg_request_treatment |
| @@ -522,6 +525,71 @@ bool reg_is_valid_request(const char *alpha2) | |||
| 522 | return alpha2_equal(lr->alpha2, alpha2); | 525 | return alpha2_equal(lr->alpha2, alpha2); |
| 523 | } | 526 | } |
| 524 | 527 | ||
| 528 | static const struct ieee80211_regdomain *reg_get_regdomain(struct wiphy *wiphy) | ||
| 529 | { | ||
| 530 | struct regulatory_request *lr = get_last_request(); | ||
| 531 | |||
| 532 | /* | ||
| 533 | * Follow the driver's regulatory domain, if present, unless a country | ||
| 534 | * IE has been processed or a user wants to help complaince further | ||
| 535 | */ | ||
| 536 | if (lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && | ||
| 537 | lr->initiator != NL80211_REGDOM_SET_BY_USER && | ||
| 538 | wiphy->regd) | ||
| 539 | return get_wiphy_regdom(wiphy); | ||
| 540 | |||
| 541 | return get_cfg80211_regdom(); | ||
| 542 | } | ||
| 543 | |||
| 544 | unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd, | ||
| 545 | const struct ieee80211_reg_rule *rule) | ||
| 546 | { | ||
| 547 | const struct ieee80211_freq_range *freq_range = &rule->freq_range; | ||
| 548 | const struct ieee80211_freq_range *freq_range_tmp; | ||
| 549 | const struct ieee80211_reg_rule *tmp; | ||
| 550 | u32 start_freq, end_freq, idx, no; | ||
| 551 | |||
| 552 | for (idx = 0; idx < rd->n_reg_rules; idx++) | ||
| 553 | if (rule == &rd->reg_rules[idx]) | ||
| 554 | break; | ||
| 555 | |||
| 556 | if (idx == rd->n_reg_rules) | ||
| 557 | return 0; | ||
| 558 | |||
| 559 | /* get start_freq */ | ||
| 560 | no = idx; | ||
| 561 | |||
| 562 | while (no) { | ||
| 563 | tmp = &rd->reg_rules[--no]; | ||
| 564 | freq_range_tmp = &tmp->freq_range; | ||
| 565 | |||
| 566 | if (freq_range_tmp->end_freq_khz < freq_range->start_freq_khz) | ||
| 567 | break; | ||
| 568 | |||
| 569 | freq_range = freq_range_tmp; | ||
| 570 | } | ||
| 571 | |||
| 572 | start_freq = freq_range->start_freq_khz; | ||
| 573 | |||
| 574 | /* get end_freq */ | ||
| 575 | freq_range = &rule->freq_range; | ||
| 576 | no = idx; | ||
| 577 | |||
| 578 | while (no < rd->n_reg_rules - 1) { | ||
| 579 | tmp = &rd->reg_rules[++no]; | ||
| 580 | freq_range_tmp = &tmp->freq_range; | ||
| 581 | |||
| 582 | if (freq_range_tmp->start_freq_khz > freq_range->end_freq_khz) | ||
| 583 | break; | ||
| 584 | |||
| 585 | freq_range = freq_range_tmp; | ||
| 586 | } | ||
| 587 | |||
| 588 | end_freq = freq_range->end_freq_khz; | ||
| 589 | |||
| 590 | return end_freq - start_freq; | ||
| 591 | } | ||
| 592 | |||
| 525 | /* Sanity check on a regulatory rule */ | 593 | /* Sanity check on a regulatory rule */ |
| 526 | static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule) | 594 | static bool is_valid_reg_rule(const struct ieee80211_reg_rule *rule) |
| 527 | { | 595 | { |
| @@ -630,7 +698,9 @@ reg_intersect_dfs_region(const enum nl80211_dfs_regions dfs_region1, | |||
| 630 | * Helper for regdom_intersect(), this does the real | 698 | * Helper for regdom_intersect(), this does the real |
| 631 | * mathematical intersection fun | 699 | * mathematical intersection fun |
| 632 | */ | 700 | */ |
| 633 | static int reg_rules_intersect(const struct ieee80211_reg_rule *rule1, | 701 | static int reg_rules_intersect(const struct ieee80211_regdomain *rd1, |
| 702 | const struct ieee80211_regdomain *rd2, | ||
| 703 | const struct ieee80211_reg_rule *rule1, | ||
| 634 | const struct ieee80211_reg_rule *rule2, | 704 | const struct ieee80211_reg_rule *rule2, |
| 635 | struct ieee80211_reg_rule *intersected_rule) | 705 | struct ieee80211_reg_rule *intersected_rule) |
| 636 | { | 706 | { |
| @@ -638,7 +708,7 @@ static int reg_rules_intersect(const struct ieee80211_reg_rule *rule1, | |||
| 638 | struct ieee80211_freq_range *freq_range; | 708 | struct ieee80211_freq_range *freq_range; |
| 639 | const struct ieee80211_power_rule *power_rule1, *power_rule2; | 709 | const struct ieee80211_power_rule *power_rule1, *power_rule2; |
| 640 | struct ieee80211_power_rule *power_rule; | 710 | struct ieee80211_power_rule *power_rule; |
| 641 | u32 freq_diff; | 711 | u32 freq_diff, max_bandwidth1, max_bandwidth2; |
| 642 | 712 | ||
| 643 | freq_range1 = &rule1->freq_range; | 713 | freq_range1 = &rule1->freq_range; |
| 644 | freq_range2 = &rule2->freq_range; | 714 | freq_range2 = &rule2->freq_range; |
| @@ -652,8 +722,32 @@ static int reg_rules_intersect(const struct ieee80211_reg_rule *rule1, | |||
| 652 | freq_range2->start_freq_khz); | 722 | freq_range2->start_freq_khz); |
| 653 | freq_range->end_freq_khz = min(freq_range1->end_freq_khz, | 723 | freq_range->end_freq_khz = min(freq_range1->end_freq_khz, |
| 654 | freq_range2->end_freq_khz); | 724 | freq_range2->end_freq_khz); |
| 655 | freq_range->max_bandwidth_khz = min(freq_range1->max_bandwidth_khz, | 725 | |
| 656 | freq_range2->max_bandwidth_khz); | 726 | max_bandwidth1 = freq_range1->max_bandwidth_khz; |
| 727 | max_bandwidth2 = freq_range2->max_bandwidth_khz; | ||
| 728 | |||
| 729 | if (rule1->flags & NL80211_RRF_AUTO_BW) | ||
| 730 | max_bandwidth1 = reg_get_max_bandwidth(rd1, rule1); | ||
| 731 | if (rule2->flags & NL80211_RRF_AUTO_BW) | ||
| 732 | max_bandwidth2 = reg_get_max_bandwidth(rd2, rule2); | ||
| 733 | |||
| 734 | freq_range->max_bandwidth_khz = min(max_bandwidth1, max_bandwidth2); | ||
| 735 | |||
| 736 | intersected_rule->flags = rule1->flags | rule2->flags; | ||
| 737 | |||
| 738 | /* | ||
| 739 | * In case NL80211_RRF_AUTO_BW requested for both rules | ||
| 740 | * set AUTO_BW in intersected rule also. Next we will | ||
| 741 | * calculate BW correctly in handle_channel function. | ||
| 742 | * In other case remove AUTO_BW flag while we calculate | ||
| 743 | * maximum bandwidth correctly and auto calculation is | ||
| 744 | * not required. | ||
| 745 | */ | ||
| 746 | if ((rule1->flags & NL80211_RRF_AUTO_BW) && | ||
| 747 | (rule2->flags & NL80211_RRF_AUTO_BW)) | ||
| 748 | intersected_rule->flags |= NL80211_RRF_AUTO_BW; | ||
| 749 | else | ||
| 750 | intersected_rule->flags &= ~NL80211_RRF_AUTO_BW; | ||
| 657 | 751 | ||
| 658 | freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz; | 752 | freq_diff = freq_range->end_freq_khz - freq_range->start_freq_khz; |
| 659 | if (freq_range->max_bandwidth_khz > freq_diff) | 753 | if (freq_range->max_bandwidth_khz > freq_diff) |
| @@ -664,7 +758,8 @@ static int reg_rules_intersect(const struct ieee80211_reg_rule *rule1, | |||
| 664 | power_rule->max_antenna_gain = min(power_rule1->max_antenna_gain, | 758 | power_rule->max_antenna_gain = min(power_rule1->max_antenna_gain, |
| 665 | power_rule2->max_antenna_gain); | 759 | power_rule2->max_antenna_gain); |
| 666 | 760 | ||
| 667 | intersected_rule->flags = rule1->flags | rule2->flags; | 761 | intersected_rule->dfs_cac_ms = max(rule1->dfs_cac_ms, |
| 762 | rule2->dfs_cac_ms); | ||
| 668 | 763 | ||
| 669 | if (!is_valid_reg_rule(intersected_rule)) | 764 | if (!is_valid_reg_rule(intersected_rule)) |
| 670 | return -EINVAL; | 765 | return -EINVAL; |
| @@ -713,7 +808,8 @@ regdom_intersect(const struct ieee80211_regdomain *rd1, | |||
| 713 | rule1 = &rd1->reg_rules[x]; | 808 | rule1 = &rd1->reg_rules[x]; |
| 714 | for (y = 0; y < rd2->n_reg_rules; y++) { | 809 | for (y = 0; y < rd2->n_reg_rules; y++) { |
| 715 | rule2 = &rd2->reg_rules[y]; | 810 | rule2 = &rd2->reg_rules[y]; |
| 716 | if (!reg_rules_intersect(rule1, rule2, &dummy_rule)) | 811 | if (!reg_rules_intersect(rd1, rd2, rule1, rule2, |
| 812 | &dummy_rule)) | ||
| 717 | num_rules++; | 813 | num_rules++; |
| 718 | } | 814 | } |
| 719 | } | 815 | } |
| @@ -738,7 +834,8 @@ regdom_intersect(const struct ieee80211_regdomain *rd1, | |||
| 738 | * a memcpy() | 834 | * a memcpy() |
| 739 | */ | 835 | */ |
| 740 | intersected_rule = &rd->reg_rules[rule_idx]; | 836 | intersected_rule = &rd->reg_rules[rule_idx]; |
| 741 | r = reg_rules_intersect(rule1, rule2, intersected_rule); | 837 | r = reg_rules_intersect(rd1, rd2, rule1, rule2, |
| 838 | intersected_rule); | ||
| 742 | /* | 839 | /* |
| 743 | * No need to memset here the intersected rule here as | 840 | * No need to memset here the intersected rule here as |
| 744 | * we're not using the stack anymore | 841 | * we're not using the stack anymore |
| @@ -821,18 +918,8 @@ const struct ieee80211_reg_rule *freq_reg_info(struct wiphy *wiphy, | |||
| 821 | u32 center_freq) | 918 | u32 center_freq) |
| 822 | { | 919 | { |
| 823 | const struct ieee80211_regdomain *regd; | 920 | const struct ieee80211_regdomain *regd; |
| 824 | struct regulatory_request *lr = get_last_request(); | ||
| 825 | 921 | ||
| 826 | /* | 922 | regd = reg_get_regdomain(wiphy); |
| 827 | * Follow the driver's regulatory domain, if present, unless a country | ||
| 828 | * IE has been processed or a user wants to help complaince further | ||
| 829 | */ | ||
| 830 | if (lr->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && | ||
| 831 | lr->initiator != NL80211_REGDOM_SET_BY_USER && | ||
| 832 | wiphy->regd) | ||
| 833 | regd = get_wiphy_regdom(wiphy); | ||
| 834 | else | ||
| 835 | regd = get_cfg80211_regdom(); | ||
| 836 | 923 | ||
| 837 | return freq_reg_info_regd(wiphy, center_freq, regd); | 924 | return freq_reg_info_regd(wiphy, center_freq, regd); |
| 838 | } | 925 | } |
| @@ -857,31 +944,42 @@ const char *reg_initiator_name(enum nl80211_reg_initiator initiator) | |||
| 857 | EXPORT_SYMBOL(reg_initiator_name); | 944 | EXPORT_SYMBOL(reg_initiator_name); |
| 858 | 945 | ||
| 859 | #ifdef CONFIG_CFG80211_REG_DEBUG | 946 | #ifdef CONFIG_CFG80211_REG_DEBUG |
| 860 | static void chan_reg_rule_print_dbg(struct ieee80211_channel *chan, | 947 | static void chan_reg_rule_print_dbg(const struct ieee80211_regdomain *regd, |
| 948 | struct ieee80211_channel *chan, | ||
| 861 | const struct ieee80211_reg_rule *reg_rule) | 949 | const struct ieee80211_reg_rule *reg_rule) |
| 862 | { | 950 | { |
| 863 | const struct ieee80211_power_rule *power_rule; | 951 | const struct ieee80211_power_rule *power_rule; |
| 864 | const struct ieee80211_freq_range *freq_range; | 952 | const struct ieee80211_freq_range *freq_range; |
| 865 | char max_antenna_gain[32]; | 953 | char max_antenna_gain[32], bw[32]; |
| 866 | 954 | ||
| 867 | power_rule = ®_rule->power_rule; | 955 | power_rule = ®_rule->power_rule; |
| 868 | freq_range = ®_rule->freq_range; | 956 | freq_range = ®_rule->freq_range; |
| 869 | 957 | ||
| 870 | if (!power_rule->max_antenna_gain) | 958 | if (!power_rule->max_antenna_gain) |
| 871 | snprintf(max_antenna_gain, 32, "N/A"); | 959 | snprintf(max_antenna_gain, sizeof(max_antenna_gain), "N/A"); |
| 872 | else | 960 | else |
| 873 | snprintf(max_antenna_gain, 32, "%d", power_rule->max_antenna_gain); | 961 | snprintf(max_antenna_gain, sizeof(max_antenna_gain), "%d", |
| 962 | power_rule->max_antenna_gain); | ||
| 963 | |||
| 964 | if (reg_rule->flags & NL80211_RRF_AUTO_BW) | ||
| 965 | snprintf(bw, sizeof(bw), "%d KHz, %d KHz AUTO", | ||
| 966 | freq_range->max_bandwidth_khz, | ||
| 967 | reg_get_max_bandwidth(regd, reg_rule)); | ||
| 968 | else | ||
| 969 | snprintf(bw, sizeof(bw), "%d KHz", | ||
| 970 | freq_range->max_bandwidth_khz); | ||
| 874 | 971 | ||
| 875 | REG_DBG_PRINT("Updating information on frequency %d MHz with regulatory rule:\n", | 972 | REG_DBG_PRINT("Updating information on frequency %d MHz with regulatory rule:\n", |
| 876 | chan->center_freq); | 973 | chan->center_freq); |
| 877 | 974 | ||
| 878 | REG_DBG_PRINT("%d KHz - %d KHz @ %d KHz), (%s mBi, %d mBm)\n", | 975 | REG_DBG_PRINT("%d KHz - %d KHz @ %s), (%s mBi, %d mBm)\n", |
| 879 | freq_range->start_freq_khz, freq_range->end_freq_khz, | 976 | freq_range->start_freq_khz, freq_range->end_freq_khz, |
| 880 | freq_range->max_bandwidth_khz, max_antenna_gain, | 977 | bw, max_antenna_gain, |
| 881 | power_rule->max_eirp); | 978 | power_rule->max_eirp); |
| 882 | } | 979 | } |
| 883 | #else | 980 | #else |
| 884 | static void chan_reg_rule_print_dbg(struct ieee80211_channel *chan, | 981 | static void chan_reg_rule_print_dbg(const struct ieee80211_regdomain *regd, |
| 982 | struct ieee80211_channel *chan, | ||
| 885 | const struct ieee80211_reg_rule *reg_rule) | 983 | const struct ieee80211_reg_rule *reg_rule) |
| 886 | { | 984 | { |
| 887 | return; | 985 | return; |
| @@ -903,6 +1001,8 @@ static void handle_channel(struct wiphy *wiphy, | |||
| 903 | const struct ieee80211_freq_range *freq_range = NULL; | 1001 | const struct ieee80211_freq_range *freq_range = NULL; |
| 904 | struct wiphy *request_wiphy = NULL; | 1002 | struct wiphy *request_wiphy = NULL; |
| 905 | struct regulatory_request *lr = get_last_request(); | 1003 | struct regulatory_request *lr = get_last_request(); |
| 1004 | const struct ieee80211_regdomain *regd; | ||
| 1005 | u32 max_bandwidth_khz; | ||
| 906 | 1006 | ||
| 907 | request_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx); | 1007 | request_wiphy = wiphy_idx_to_wiphy(lr->wiphy_idx); |
| 908 | 1008 | ||
| @@ -939,16 +1039,22 @@ static void handle_channel(struct wiphy *wiphy, | |||
| 939 | return; | 1039 | return; |
| 940 | } | 1040 | } |
| 941 | 1041 | ||
| 942 | chan_reg_rule_print_dbg(chan, reg_rule); | 1042 | regd = reg_get_regdomain(wiphy); |
| 1043 | chan_reg_rule_print_dbg(regd, chan, reg_rule); | ||
| 943 | 1044 | ||
| 944 | power_rule = ®_rule->power_rule; | 1045 | power_rule = ®_rule->power_rule; |
| 945 | freq_range = ®_rule->freq_range; | 1046 | freq_range = ®_rule->freq_range; |
| 946 | 1047 | ||
| 947 | if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40)) | 1048 | max_bandwidth_khz = freq_range->max_bandwidth_khz; |
| 1049 | /* Check if auto calculation requested */ | ||
| 1050 | if (reg_rule->flags & NL80211_RRF_AUTO_BW) | ||
| 1051 | max_bandwidth_khz = reg_get_max_bandwidth(regd, reg_rule); | ||
| 1052 | |||
| 1053 | if (max_bandwidth_khz < MHZ_TO_KHZ(40)) | ||
| 948 | bw_flags = IEEE80211_CHAN_NO_HT40; | 1054 | bw_flags = IEEE80211_CHAN_NO_HT40; |
| 949 | if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(80)) | 1055 | if (max_bandwidth_khz < MHZ_TO_KHZ(80)) |
| 950 | bw_flags |= IEEE80211_CHAN_NO_80MHZ; | 1056 | bw_flags |= IEEE80211_CHAN_NO_80MHZ; |
| 951 | if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(160)) | 1057 | if (max_bandwidth_khz < MHZ_TO_KHZ(160)) |
| 952 | bw_flags |= IEEE80211_CHAN_NO_160MHZ; | 1058 | bw_flags |= IEEE80211_CHAN_NO_160MHZ; |
| 953 | 1059 | ||
| 954 | if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER && | 1060 | if (lr->initiator == NL80211_REGDOM_SET_BY_DRIVER && |
| @@ -977,6 +1083,14 @@ static void handle_channel(struct wiphy *wiphy, | |||
| 977 | min_t(int, chan->orig_mag, | 1083 | min_t(int, chan->orig_mag, |
| 978 | MBI_TO_DBI(power_rule->max_antenna_gain)); | 1084 | MBI_TO_DBI(power_rule->max_antenna_gain)); |
| 979 | chan->max_reg_power = (int) MBM_TO_DBM(power_rule->max_eirp); | 1085 | chan->max_reg_power = (int) MBM_TO_DBM(power_rule->max_eirp); |
| 1086 | |||
| 1087 | if (chan->flags & IEEE80211_CHAN_RADAR) { | ||
| 1088 | if (reg_rule->dfs_cac_ms) | ||
| 1089 | chan->dfs_cac_ms = reg_rule->dfs_cac_ms; | ||
| 1090 | else | ||
| 1091 | chan->dfs_cac_ms = IEEE80211_DFS_MIN_CAC_TIME_MS; | ||
| 1092 | } | ||
| 1093 | |||
| 980 | if (chan->orig_mpwr) { | 1094 | if (chan->orig_mpwr) { |
| 981 | /* | 1095 | /* |
| 982 | * Devices that use REGULATORY_COUNTRY_IE_FOLLOW_POWER | 1096 | * Devices that use REGULATORY_COUNTRY_IE_FOLLOW_POWER |
| @@ -1334,6 +1448,7 @@ static void handle_channel_custom(struct wiphy *wiphy, | |||
| 1334 | const struct ieee80211_reg_rule *reg_rule = NULL; | 1448 | const struct ieee80211_reg_rule *reg_rule = NULL; |
| 1335 | const struct ieee80211_power_rule *power_rule = NULL; | 1449 | const struct ieee80211_power_rule *power_rule = NULL; |
| 1336 | const struct ieee80211_freq_range *freq_range = NULL; | 1450 | const struct ieee80211_freq_range *freq_range = NULL; |
| 1451 | u32 max_bandwidth_khz; | ||
| 1337 | 1452 | ||
| 1338 | reg_rule = freq_reg_info_regd(wiphy, MHZ_TO_KHZ(chan->center_freq), | 1453 | reg_rule = freq_reg_info_regd(wiphy, MHZ_TO_KHZ(chan->center_freq), |
| 1339 | regd); | 1454 | regd); |
| @@ -1346,16 +1461,21 @@ static void handle_channel_custom(struct wiphy *wiphy, | |||
| 1346 | return; | 1461 | return; |
| 1347 | } | 1462 | } |
| 1348 | 1463 | ||
| 1349 | chan_reg_rule_print_dbg(chan, reg_rule); | 1464 | chan_reg_rule_print_dbg(regd, chan, reg_rule); |
| 1350 | 1465 | ||
| 1351 | power_rule = ®_rule->power_rule; | 1466 | power_rule = ®_rule->power_rule; |
| 1352 | freq_range = ®_rule->freq_range; | 1467 | freq_range = ®_rule->freq_range; |
| 1353 | 1468 | ||
| 1354 | if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(40)) | 1469 | max_bandwidth_khz = freq_range->max_bandwidth_khz; |
| 1470 | /* Check if auto calculation requested */ | ||
| 1471 | if (reg_rule->flags & NL80211_RRF_AUTO_BW) | ||
| 1472 | max_bandwidth_khz = reg_get_max_bandwidth(regd, reg_rule); | ||
| 1473 | |||
| 1474 | if (max_bandwidth_khz < MHZ_TO_KHZ(40)) | ||
| 1355 | bw_flags = IEEE80211_CHAN_NO_HT40; | 1475 | bw_flags = IEEE80211_CHAN_NO_HT40; |
| 1356 | if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(80)) | 1476 | if (max_bandwidth_khz < MHZ_TO_KHZ(80)) |
| 1357 | bw_flags |= IEEE80211_CHAN_NO_80MHZ; | 1477 | bw_flags |= IEEE80211_CHAN_NO_80MHZ; |
| 1358 | if (freq_range->max_bandwidth_khz < MHZ_TO_KHZ(160)) | 1478 | if (max_bandwidth_khz < MHZ_TO_KHZ(160)) |
| 1359 | bw_flags |= IEEE80211_CHAN_NO_160MHZ; | 1479 | bw_flags |= IEEE80211_CHAN_NO_160MHZ; |
| 1360 | 1480 | ||
| 1361 | chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags; | 1481 | chan->flags |= map_regdom_flags(reg_rule->flags) | bw_flags; |
| @@ -1683,17 +1803,9 @@ static void reg_process_hint(struct regulatory_request *reg_request) | |||
| 1683 | struct wiphy *wiphy = NULL; | 1803 | struct wiphy *wiphy = NULL; |
| 1684 | enum reg_request_treatment treatment; | 1804 | enum reg_request_treatment treatment; |
| 1685 | 1805 | ||
| 1686 | if (WARN_ON(!reg_request->alpha2)) | ||
| 1687 | return; | ||
| 1688 | |||
| 1689 | if (reg_request->wiphy_idx != WIPHY_IDX_INVALID) | 1806 | if (reg_request->wiphy_idx != WIPHY_IDX_INVALID) |
| 1690 | wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx); | 1807 | wiphy = wiphy_idx_to_wiphy(reg_request->wiphy_idx); |
| 1691 | 1808 | ||
| 1692 | if (reg_request->initiator == NL80211_REGDOM_SET_BY_DRIVER && !wiphy) { | ||
| 1693 | kfree(reg_request); | ||
| 1694 | return; | ||
| 1695 | } | ||
| 1696 | |||
| 1697 | switch (reg_request->initiator) { | 1809 | switch (reg_request->initiator) { |
| 1698 | case NL80211_REGDOM_SET_BY_CORE: | 1810 | case NL80211_REGDOM_SET_BY_CORE: |
| 1699 | reg_process_hint_core(reg_request); | 1811 | reg_process_hint_core(reg_request); |
| @@ -1703,23 +1815,33 @@ static void reg_process_hint(struct regulatory_request *reg_request) | |||
| 1703 | if (treatment == REG_REQ_IGNORE || | 1815 | if (treatment == REG_REQ_IGNORE || |
| 1704 | treatment == REG_REQ_ALREADY_SET) | 1816 | treatment == REG_REQ_ALREADY_SET) |
| 1705 | return; | 1817 | return; |
| 1706 | schedule_delayed_work(®_timeout, msecs_to_jiffies(3142)); | 1818 | queue_delayed_work(system_power_efficient_wq, |
| 1819 | ®_timeout, msecs_to_jiffies(3142)); | ||
| 1707 | return; | 1820 | return; |
| 1708 | case NL80211_REGDOM_SET_BY_DRIVER: | 1821 | case NL80211_REGDOM_SET_BY_DRIVER: |
| 1822 | if (!wiphy) | ||
| 1823 | goto out_free; | ||
| 1709 | treatment = reg_process_hint_driver(wiphy, reg_request); | 1824 | treatment = reg_process_hint_driver(wiphy, reg_request); |
| 1710 | break; | 1825 | break; |
| 1711 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: | 1826 | case NL80211_REGDOM_SET_BY_COUNTRY_IE: |
| 1827 | if (!wiphy) | ||
| 1828 | goto out_free; | ||
| 1712 | treatment = reg_process_hint_country_ie(wiphy, reg_request); | 1829 | treatment = reg_process_hint_country_ie(wiphy, reg_request); |
| 1713 | break; | 1830 | break; |
| 1714 | default: | 1831 | default: |
| 1715 | WARN(1, "invalid initiator %d\n", reg_request->initiator); | 1832 | WARN(1, "invalid initiator %d\n", reg_request->initiator); |
| 1716 | return; | 1833 | goto out_free; |
| 1717 | } | 1834 | } |
| 1718 | 1835 | ||
| 1719 | /* This is required so that the orig_* parameters are saved */ | 1836 | /* This is required so that the orig_* parameters are saved */ |
| 1720 | if (treatment == REG_REQ_ALREADY_SET && wiphy && | 1837 | if (treatment == REG_REQ_ALREADY_SET && wiphy && |
| 1721 | wiphy->regulatory_flags & REGULATORY_STRICT_REG) | 1838 | wiphy->regulatory_flags & REGULATORY_STRICT_REG) |
| 1722 | wiphy_update_regulatory(wiphy, reg_request->initiator); | 1839 | wiphy_update_regulatory(wiphy, reg_request->initiator); |
| 1840 | |||
| 1841 | return; | ||
| 1842 | |||
| 1843 | out_free: | ||
| 1844 | kfree(reg_request); | ||
| 1723 | } | 1845 | } |
| 1724 | 1846 | ||
| 1725 | /* | 1847 | /* |
| @@ -2147,31 +2269,49 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd) | |||
| 2147 | const struct ieee80211_reg_rule *reg_rule = NULL; | 2269 | const struct ieee80211_reg_rule *reg_rule = NULL; |
| 2148 | const struct ieee80211_freq_range *freq_range = NULL; | 2270 | const struct ieee80211_freq_range *freq_range = NULL; |
| 2149 | const struct ieee80211_power_rule *power_rule = NULL; | 2271 | const struct ieee80211_power_rule *power_rule = NULL; |
| 2272 | char bw[32], cac_time[32]; | ||
| 2150 | 2273 | ||
| 2151 | pr_info(" (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp)\n"); | 2274 | pr_info(" (start_freq - end_freq @ bandwidth), (max_antenna_gain, max_eirp), (dfs_cac_time)\n"); |
| 2152 | 2275 | ||
| 2153 | for (i = 0; i < rd->n_reg_rules; i++) { | 2276 | for (i = 0; i < rd->n_reg_rules; i++) { |
| 2154 | reg_rule = &rd->reg_rules[i]; | 2277 | reg_rule = &rd->reg_rules[i]; |
| 2155 | freq_range = ®_rule->freq_range; | 2278 | freq_range = ®_rule->freq_range; |
| 2156 | power_rule = ®_rule->power_rule; | 2279 | power_rule = ®_rule->power_rule; |
| 2157 | 2280 | ||
| 2281 | if (reg_rule->flags & NL80211_RRF_AUTO_BW) | ||
| 2282 | snprintf(bw, sizeof(bw), "%d KHz, %d KHz AUTO", | ||
| 2283 | freq_range->max_bandwidth_khz, | ||
| 2284 | reg_get_max_bandwidth(rd, reg_rule)); | ||
| 2285 | else | ||
| 2286 | snprintf(bw, sizeof(bw), "%d KHz", | ||
| 2287 | freq_range->max_bandwidth_khz); | ||
| 2288 | |||
| 2289 | if (reg_rule->flags & NL80211_RRF_DFS) | ||
| 2290 | scnprintf(cac_time, sizeof(cac_time), "%u s", | ||
| 2291 | reg_rule->dfs_cac_ms/1000); | ||
| 2292 | else | ||
| 2293 | scnprintf(cac_time, sizeof(cac_time), "N/A"); | ||
| 2294 | |||
| 2295 | |||
| 2158 | /* | 2296 | /* |
| 2159 | * There may not be documentation for max antenna gain | 2297 | * There may not be documentation for max antenna gain |
| 2160 | * in certain regions | 2298 | * in certain regions |
| 2161 | */ | 2299 | */ |
| 2162 | if (power_rule->max_antenna_gain) | 2300 | if (power_rule->max_antenna_gain) |
| 2163 | pr_info(" (%d KHz - %d KHz @ %d KHz), (%d mBi, %d mBm)\n", | 2301 | pr_info(" (%d KHz - %d KHz @ %s), (%d mBi, %d mBm), (%s)\n", |
| 2164 | freq_range->start_freq_khz, | 2302 | freq_range->start_freq_khz, |
| 2165 | freq_range->end_freq_khz, | 2303 | freq_range->end_freq_khz, |
| 2166 | freq_range->max_bandwidth_khz, | 2304 | bw, |
| 2167 | power_rule->max_antenna_gain, | 2305 | power_rule->max_antenna_gain, |
| 2168 | power_rule->max_eirp); | 2306 | power_rule->max_eirp, |
| 2307 | cac_time); | ||
| 2169 | else | 2308 | else |
| 2170 | pr_info(" (%d KHz - %d KHz @ %d KHz), (N/A, %d mBm)\n", | 2309 | pr_info(" (%d KHz - %d KHz @ %s), (N/A, %d mBm), (%s)\n", |
| 2171 | freq_range->start_freq_khz, | 2310 | freq_range->start_freq_khz, |
| 2172 | freq_range->end_freq_khz, | 2311 | freq_range->end_freq_khz, |
| 2173 | freq_range->max_bandwidth_khz, | 2312 | bw, |
| 2174 | power_rule->max_eirp); | 2313 | power_rule->max_eirp, |
| 2314 | cac_time); | ||
| 2175 | } | 2315 | } |
| 2176 | } | 2316 | } |
| 2177 | 2317 | ||
| @@ -2244,9 +2384,6 @@ static int reg_set_rd_user(const struct ieee80211_regdomain *rd, | |||
| 2244 | { | 2384 | { |
| 2245 | const struct ieee80211_regdomain *intersected_rd = NULL; | 2385 | const struct ieee80211_regdomain *intersected_rd = NULL; |
| 2246 | 2386 | ||
| 2247 | if (is_world_regdom(rd->alpha2)) | ||
| 2248 | return -EINVAL; | ||
| 2249 | |||
| 2250 | if (!regdom_changes(rd->alpha2)) | 2387 | if (!regdom_changes(rd->alpha2)) |
| 2251 | return -EALREADY; | 2388 | return -EALREADY; |
| 2252 | 2389 | ||
| @@ -2294,7 +2431,8 @@ static int reg_set_rd_driver(const struct ieee80211_regdomain *rd, | |||
| 2294 | 2431 | ||
| 2295 | request_wiphy = wiphy_idx_to_wiphy(driver_request->wiphy_idx); | 2432 | request_wiphy = wiphy_idx_to_wiphy(driver_request->wiphy_idx); |
| 2296 | if (!request_wiphy) { | 2433 | if (!request_wiphy) { |
| 2297 | schedule_delayed_work(®_timeout, 0); | 2434 | queue_delayed_work(system_power_efficient_wq, |
| 2435 | ®_timeout, 0); | ||
| 2298 | return -ENODEV; | 2436 | return -ENODEV; |
| 2299 | } | 2437 | } |
| 2300 | 2438 | ||
| @@ -2354,7 +2492,8 @@ static int reg_set_rd_country_ie(const struct ieee80211_regdomain *rd, | |||
| 2354 | 2492 | ||
| 2355 | request_wiphy = wiphy_idx_to_wiphy(country_ie_request->wiphy_idx); | 2493 | request_wiphy = wiphy_idx_to_wiphy(country_ie_request->wiphy_idx); |
| 2356 | if (!request_wiphy) { | 2494 | if (!request_wiphy) { |
| 2357 | schedule_delayed_work(®_timeout, 0); | 2495 | queue_delayed_work(system_power_efficient_wq, |
| 2496 | ®_timeout, 0); | ||
| 2358 | return -ENODEV; | 2497 | return -ENODEV; |
| 2359 | } | 2498 | } |
| 2360 | 2499 | ||
| @@ -2433,26 +2572,6 @@ int set_regdom(const struct ieee80211_regdomain *rd) | |||
| 2433 | return 0; | 2572 | return 0; |
| 2434 | } | 2573 | } |
| 2435 | 2574 | ||
| 2436 | int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env) | ||
| 2437 | { | ||
| 2438 | struct regulatory_request *lr; | ||
| 2439 | u8 alpha2[2]; | ||
| 2440 | bool add = false; | ||
| 2441 | |||
| 2442 | rcu_read_lock(); | ||
| 2443 | lr = get_last_request(); | ||
| 2444 | if (lr && !lr->processed) { | ||
| 2445 | memcpy(alpha2, lr->alpha2, 2); | ||
| 2446 | add = true; | ||
| 2447 | } | ||
| 2448 | rcu_read_unlock(); | ||
| 2449 | |||
| 2450 | if (add) | ||
| 2451 | return add_uevent_var(env, "COUNTRY=%c%c", | ||
| 2452 | alpha2[0], alpha2[1]); | ||
| 2453 | return 0; | ||
| 2454 | } | ||
| 2455 | |||
| 2456 | void wiphy_regulatory_register(struct wiphy *wiphy) | 2575 | void wiphy_regulatory_register(struct wiphy *wiphy) |
| 2457 | { | 2576 | { |
| 2458 | struct regulatory_request *lr; | 2577 | struct regulatory_request *lr; |
| @@ -2503,8 +2622,6 @@ int __init regulatory_init(void) | |||
| 2503 | if (IS_ERR(reg_pdev)) | 2622 | if (IS_ERR(reg_pdev)) |
| 2504 | return PTR_ERR(reg_pdev); | 2623 | return PTR_ERR(reg_pdev); |
| 2505 | 2624 | ||
| 2506 | reg_pdev->dev.type = ®_device_type; | ||
| 2507 | |||
| 2508 | spin_lock_init(®_requests_lock); | 2625 | spin_lock_init(®_requests_lock); |
| 2509 | spin_lock_init(®_pending_beacons_lock); | 2626 | spin_lock_init(®_pending_beacons_lock); |
| 2510 | 2627 | ||
diff --git a/net/wireless/reg.h b/net/wireless/reg.h index 02bd8f4b0921..37c180df34b7 100644 --- a/net/wireless/reg.h +++ b/net/wireless/reg.h | |||
| @@ -26,7 +26,6 @@ enum nl80211_dfs_regions reg_get_dfs_region(struct wiphy *wiphy); | |||
| 26 | int regulatory_hint_user(const char *alpha2, | 26 | int regulatory_hint_user(const char *alpha2, |
| 27 | enum nl80211_user_reg_hint_type user_reg_hint_type); | 27 | enum nl80211_user_reg_hint_type user_reg_hint_type); |
| 28 | 28 | ||
| 29 | int reg_device_uevent(struct device *dev, struct kobj_uevent_env *env); | ||
| 30 | void wiphy_regulatory_register(struct wiphy *wiphy); | 29 | void wiphy_regulatory_register(struct wiphy *wiphy); |
| 31 | void wiphy_regulatory_deregister(struct wiphy *wiphy); | 30 | void wiphy_regulatory_deregister(struct wiphy *wiphy); |
| 32 | 31 | ||
| @@ -34,6 +33,8 @@ int __init regulatory_init(void); | |||
| 34 | void regulatory_exit(void); | 33 | void regulatory_exit(void); |
| 35 | 34 | ||
| 36 | int set_regdom(const struct ieee80211_regdomain *rd); | 35 | int set_regdom(const struct ieee80211_regdomain *rd); |
| 36 | unsigned int reg_get_max_bandwidth(const struct ieee80211_regdomain *rd, | ||
| 37 | const struct ieee80211_reg_rule *rule); | ||
| 37 | 38 | ||
| 38 | bool reg_last_request_cell_base(void); | 39 | bool reg_last_request_cell_base(void); |
| 39 | 40 | ||
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index d1ed4aebbbb7..7d09a712cb1f 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
| @@ -659,9 +659,6 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *dev, | |||
| 659 | continue; | 659 | continue; |
| 660 | if (ssidlen && ie[1] != ssidlen) | 660 | if (ssidlen && ie[1] != ssidlen) |
| 661 | continue; | 661 | continue; |
| 662 | /* that would be odd ... */ | ||
| 663 | if (bss->pub.beacon_ies) | ||
| 664 | continue; | ||
| 665 | if (WARN_ON_ONCE(bss->pub.hidden_beacon_bss)) | 662 | if (WARN_ON_ONCE(bss->pub.hidden_beacon_bss)) |
| 666 | continue; | 663 | continue; |
| 667 | if (WARN_ON_ONCE(!list_empty(&bss->hidden_list))) | 664 | if (WARN_ON_ONCE(!list_empty(&bss->hidden_list))) |
| @@ -680,7 +677,8 @@ static bool cfg80211_combine_bsses(struct cfg80211_registered_device *dev, | |||
| 680 | /* Returned bss is reference counted and must be cleaned up appropriately. */ | 677 | /* Returned bss is reference counted and must be cleaned up appropriately. */ |
| 681 | static struct cfg80211_internal_bss * | 678 | static struct cfg80211_internal_bss * |
| 682 | cfg80211_bss_update(struct cfg80211_registered_device *dev, | 679 | cfg80211_bss_update(struct cfg80211_registered_device *dev, |
| 683 | struct cfg80211_internal_bss *tmp) | 680 | struct cfg80211_internal_bss *tmp, |
| 681 | bool signal_valid) | ||
| 684 | { | 682 | { |
| 685 | struct cfg80211_internal_bss *found = NULL; | 683 | struct cfg80211_internal_bss *found = NULL; |
| 686 | 684 | ||
| @@ -765,7 +763,12 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev, | |||
| 765 | } | 763 | } |
| 766 | 764 | ||
| 767 | found->pub.beacon_interval = tmp->pub.beacon_interval; | 765 | found->pub.beacon_interval = tmp->pub.beacon_interval; |
| 768 | found->pub.signal = tmp->pub.signal; | 766 | /* |
| 767 | * don't update the signal if beacon was heard on | ||
| 768 | * adjacent channel. | ||
| 769 | */ | ||
| 770 | if (signal_valid) | ||
| 771 | found->pub.signal = tmp->pub.signal; | ||
| 769 | found->pub.capability = tmp->pub.capability; | 772 | found->pub.capability = tmp->pub.capability; |
| 770 | found->ts = tmp->ts; | 773 | found->ts = tmp->ts; |
| 771 | } else { | 774 | } else { |
| @@ -869,13 +872,14 @@ cfg80211_get_bss_channel(struct wiphy *wiphy, const u8 *ie, size_t ielen, | |||
| 869 | /* Returned bss is reference counted and must be cleaned up appropriately. */ | 872 | /* Returned bss is reference counted and must be cleaned up appropriately. */ |
| 870 | struct cfg80211_bss* | 873 | struct cfg80211_bss* |
| 871 | cfg80211_inform_bss_width(struct wiphy *wiphy, | 874 | cfg80211_inform_bss_width(struct wiphy *wiphy, |
| 872 | struct ieee80211_channel *channel, | 875 | struct ieee80211_channel *rx_channel, |
| 873 | enum nl80211_bss_scan_width scan_width, | 876 | enum nl80211_bss_scan_width scan_width, |
| 874 | const u8 *bssid, u64 tsf, u16 capability, | 877 | const u8 *bssid, u64 tsf, u16 capability, |
| 875 | u16 beacon_interval, const u8 *ie, size_t ielen, | 878 | u16 beacon_interval, const u8 *ie, size_t ielen, |
| 876 | s32 signal, gfp_t gfp) | 879 | s32 signal, gfp_t gfp) |
| 877 | { | 880 | { |
| 878 | struct cfg80211_bss_ies *ies; | 881 | struct cfg80211_bss_ies *ies; |
| 882 | struct ieee80211_channel *channel; | ||
| 879 | struct cfg80211_internal_bss tmp = {}, *res; | 883 | struct cfg80211_internal_bss tmp = {}, *res; |
| 880 | 884 | ||
| 881 | if (WARN_ON(!wiphy)) | 885 | if (WARN_ON(!wiphy)) |
| @@ -885,7 +889,7 @@ cfg80211_inform_bss_width(struct wiphy *wiphy, | |||
| 885 | (signal < 0 || signal > 100))) | 889 | (signal < 0 || signal > 100))) |
| 886 | return NULL; | 890 | return NULL; |
| 887 | 891 | ||
| 888 | channel = cfg80211_get_bss_channel(wiphy, ie, ielen, channel); | 892 | channel = cfg80211_get_bss_channel(wiphy, ie, ielen, rx_channel); |
| 889 | if (!channel) | 893 | if (!channel) |
| 890 | return NULL; | 894 | return NULL; |
| 891 | 895 | ||
| @@ -913,7 +917,8 @@ cfg80211_inform_bss_width(struct wiphy *wiphy, | |||
| 913 | rcu_assign_pointer(tmp.pub.beacon_ies, ies); | 917 | rcu_assign_pointer(tmp.pub.beacon_ies, ies); |
| 914 | rcu_assign_pointer(tmp.pub.ies, ies); | 918 | rcu_assign_pointer(tmp.pub.ies, ies); |
| 915 | 919 | ||
| 916 | res = cfg80211_bss_update(wiphy_to_dev(wiphy), &tmp); | 920 | res = cfg80211_bss_update(wiphy_to_dev(wiphy), &tmp, |
| 921 | rx_channel == channel); | ||
| 917 | if (!res) | 922 | if (!res) |
| 918 | return NULL; | 923 | return NULL; |
| 919 | 924 | ||
| @@ -929,20 +934,21 @@ EXPORT_SYMBOL(cfg80211_inform_bss_width); | |||
| 929 | /* Returned bss is reference counted and must be cleaned up appropriately. */ | 934 | /* Returned bss is reference counted and must be cleaned up appropriately. */ |
| 930 | struct cfg80211_bss * | 935 | struct cfg80211_bss * |
| 931 | cfg80211_inform_bss_width_frame(struct wiphy *wiphy, | 936 | cfg80211_inform_bss_width_frame(struct wiphy *wiphy, |
| 932 | struct ieee80211_channel *channel, | 937 | struct ieee80211_channel *rx_channel, |
| 933 | enum nl80211_bss_scan_width scan_width, | 938 | enum nl80211_bss_scan_width scan_width, |
| 934 | struct ieee80211_mgmt *mgmt, size_t len, | 939 | struct ieee80211_mgmt *mgmt, size_t len, |
| 935 | s32 signal, gfp_t gfp) | 940 | s32 signal, gfp_t gfp) |
| 936 | { | 941 | { |
| 937 | struct cfg80211_internal_bss tmp = {}, *res; | 942 | struct cfg80211_internal_bss tmp = {}, *res; |
| 938 | struct cfg80211_bss_ies *ies; | 943 | struct cfg80211_bss_ies *ies; |
| 944 | struct ieee80211_channel *channel; | ||
| 939 | size_t ielen = len - offsetof(struct ieee80211_mgmt, | 945 | size_t ielen = len - offsetof(struct ieee80211_mgmt, |
| 940 | u.probe_resp.variable); | 946 | u.probe_resp.variable); |
| 941 | 947 | ||
| 942 | BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) != | 948 | BUILD_BUG_ON(offsetof(struct ieee80211_mgmt, u.probe_resp.variable) != |
| 943 | offsetof(struct ieee80211_mgmt, u.beacon.variable)); | 949 | offsetof(struct ieee80211_mgmt, u.beacon.variable)); |
| 944 | 950 | ||
| 945 | trace_cfg80211_inform_bss_width_frame(wiphy, channel, scan_width, mgmt, | 951 | trace_cfg80211_inform_bss_width_frame(wiphy, rx_channel, scan_width, mgmt, |
| 946 | len, signal); | 952 | len, signal); |
| 947 | 953 | ||
| 948 | if (WARN_ON(!mgmt)) | 954 | if (WARN_ON(!mgmt)) |
| @@ -959,7 +965,7 @@ cfg80211_inform_bss_width_frame(struct wiphy *wiphy, | |||
| 959 | return NULL; | 965 | return NULL; |
| 960 | 966 | ||
| 961 | channel = cfg80211_get_bss_channel(wiphy, mgmt->u.beacon.variable, | 967 | channel = cfg80211_get_bss_channel(wiphy, mgmt->u.beacon.variable, |
| 962 | ielen, channel); | 968 | ielen, rx_channel); |
| 963 | if (!channel) | 969 | if (!channel) |
| 964 | return NULL; | 970 | return NULL; |
| 965 | 971 | ||
| @@ -983,7 +989,8 @@ cfg80211_inform_bss_width_frame(struct wiphy *wiphy, | |||
| 983 | tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); | 989 | tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int); |
| 984 | tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); | 990 | tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info); |
| 985 | 991 | ||
| 986 | res = cfg80211_bss_update(wiphy_to_dev(wiphy), &tmp); | 992 | res = cfg80211_bss_update(wiphy_to_dev(wiphy), &tmp, |
| 993 | rx_channel == channel); | ||
| 987 | if (!res) | 994 | if (!res) |
| 988 | return NULL; | 995 | return NULL; |
| 989 | 996 | ||
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index f04d4c32e96e..acdcb4a81817 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
| @@ -64,7 +64,6 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev) | |||
| 64 | int n_channels, err; | 64 | int n_channels, err; |
| 65 | 65 | ||
| 66 | ASSERT_RTNL(); | 66 | ASSERT_RTNL(); |
| 67 | ASSERT_RDEV_LOCK(rdev); | ||
| 68 | ASSERT_WDEV_LOCK(wdev); | 67 | ASSERT_WDEV_LOCK(wdev); |
| 69 | 68 | ||
| 70 | if (rdev->scan_req || rdev->scan_msg) | 69 | if (rdev->scan_req || rdev->scan_msg) |
diff --git a/net/wireless/trace.h b/net/wireless/trace.h index fbcc23edee54..aabccf13e07b 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h | |||
| @@ -1468,9 +1468,10 @@ TRACE_EVENT(rdev_sched_scan_start, | |||
| 1468 | TRACE_EVENT(rdev_tdls_mgmt, | 1468 | TRACE_EVENT(rdev_tdls_mgmt, |
| 1469 | TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, | 1469 | TP_PROTO(struct wiphy *wiphy, struct net_device *netdev, |
| 1470 | u8 *peer, u8 action_code, u8 dialog_token, | 1470 | u8 *peer, u8 action_code, u8 dialog_token, |
| 1471 | u16 status_code, const u8 *buf, size_t len), | 1471 | u16 status_code, u32 peer_capability, |
| 1472 | const u8 *buf, size_t len), | ||
| 1472 | TP_ARGS(wiphy, netdev, peer, action_code, dialog_token, status_code, | 1473 | TP_ARGS(wiphy, netdev, peer, action_code, dialog_token, status_code, |
| 1473 | buf, len), | 1474 | peer_capability, buf, len), |
| 1474 | TP_STRUCT__entry( | 1475 | TP_STRUCT__entry( |
| 1475 | WIPHY_ENTRY | 1476 | WIPHY_ENTRY |
| 1476 | NETDEV_ENTRY | 1477 | NETDEV_ENTRY |
| @@ -1478,6 +1479,7 @@ TRACE_EVENT(rdev_tdls_mgmt, | |||
| 1478 | __field(u8, action_code) | 1479 | __field(u8, action_code) |
| 1479 | __field(u8, dialog_token) | 1480 | __field(u8, dialog_token) |
| 1480 | __field(u16, status_code) | 1481 | __field(u16, status_code) |
| 1482 | __field(u32, peer_capability) | ||
| 1481 | __dynamic_array(u8, buf, len) | 1483 | __dynamic_array(u8, buf, len) |
| 1482 | ), | 1484 | ), |
| 1483 | TP_fast_assign( | 1485 | TP_fast_assign( |
| @@ -1487,13 +1489,15 @@ TRACE_EVENT(rdev_tdls_mgmt, | |||
| 1487 | __entry->action_code = action_code; | 1489 | __entry->action_code = action_code; |
| 1488 | __entry->dialog_token = dialog_token; | 1490 | __entry->dialog_token = dialog_token; |
| 1489 | __entry->status_code = status_code; | 1491 | __entry->status_code = status_code; |
| 1492 | __entry->peer_capability = peer_capability; | ||
| 1490 | memcpy(__get_dynamic_array(buf), buf, len); | 1493 | memcpy(__get_dynamic_array(buf), buf, len); |
| 1491 | ), | 1494 | ), |
| 1492 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT ", action_code: %u, " | 1495 | TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", " MAC_PR_FMT ", action_code: %u, " |
| 1493 | "dialog_token: %u, status_code: %u, buf: %#.2x ", | 1496 | "dialog_token: %u, status_code: %u, peer_capability: %u buf: %#.2x ", |
| 1494 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer), | 1497 | WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(peer), |
| 1495 | __entry->action_code, __entry->dialog_token, | 1498 | __entry->action_code, __entry->dialog_token, |
| 1496 | __entry->status_code, ((u8 *)__get_dynamic_array(buf))[0]) | 1499 | __entry->status_code, __entry->peer_capability, |
| 1500 | ((u8 *)__get_dynamic_array(buf))[0]) | ||
| 1497 | ); | 1501 | ); |
| 1498 | 1502 | ||
| 1499 | TRACE_EVENT(rdev_dump_survey, | 1503 | TRACE_EVENT(rdev_dump_survey, |
| @@ -2278,11 +2282,6 @@ DECLARE_EVENT_CLASS(cfg80211_rx_evt, | |||
| 2278 | TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT, NETDEV_PR_ARG, MAC_PR_ARG(addr)) | 2282 | TP_printk(NETDEV_PR_FMT ", " MAC_PR_FMT, NETDEV_PR_ARG, MAC_PR_ARG(addr)) |
| 2279 | ); | 2283 | ); |
| 2280 | 2284 | ||
| 2281 | DEFINE_EVENT(cfg80211_rx_evt, cfg80211_ibss_joined, | ||
| 2282 | TP_PROTO(struct net_device *netdev, const u8 *addr), | ||
| 2283 | TP_ARGS(netdev, addr) | ||
| 2284 | ); | ||
| 2285 | |||
| 2286 | DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_spurious_frame, | 2285 | DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_spurious_frame, |
| 2287 | TP_PROTO(struct net_device *netdev, const u8 *addr), | 2286 | TP_PROTO(struct net_device *netdev, const u8 *addr), |
| 2288 | TP_ARGS(netdev, addr) | 2287 | TP_ARGS(netdev, addr) |
| @@ -2293,6 +2292,24 @@ DEFINE_EVENT(cfg80211_rx_evt, cfg80211_rx_unexpected_4addr_frame, | |||
| 2293 | TP_ARGS(netdev, addr) | 2292 | TP_ARGS(netdev, addr) |
| 2294 | ); | 2293 | ); |
| 2295 | 2294 | ||
| 2295 | TRACE_EVENT(cfg80211_ibss_joined, | ||
| 2296 | TP_PROTO(struct net_device *netdev, const u8 *bssid, | ||
| 2297 | struct ieee80211_channel *channel), | ||
| 2298 | TP_ARGS(netdev, bssid, channel), | ||
| 2299 | TP_STRUCT__entry( | ||
| 2300 | NETDEV_ENTRY | ||
| 2301 | MAC_ENTRY(bssid) | ||
| 2302 | CHAN_ENTRY | ||
| 2303 | ), | ||
| 2304 | TP_fast_assign( | ||
| 2305 | NETDEV_ASSIGN; | ||
| 2306 | MAC_ASSIGN(bssid, bssid); | ||
| 2307 | CHAN_ASSIGN(channel); | ||
| 2308 | ), | ||
| 2309 | TP_printk(NETDEV_PR_FMT ", bssid: " MAC_PR_FMT ", " CHAN_PR_FMT, | ||
| 2310 | NETDEV_PR_ARG, MAC_PR_ARG(bssid), CHAN_PR_ARG) | ||
| 2311 | ); | ||
| 2312 | |||
| 2296 | TRACE_EVENT(cfg80211_probe_status, | 2313 | TRACE_EVENT(cfg80211_probe_status, |
| 2297 | TP_PROTO(struct net_device *netdev, const u8 *addr, u64 cookie, | 2314 | TP_PROTO(struct net_device *netdev, const u8 *addr, u64 cookie, |
| 2298 | bool acked), | 2315 | bool acked), |
diff --git a/net/wireless/util.c b/net/wireless/util.c index d39c37104ae2..e5872ff2c27c 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c | |||
| @@ -11,6 +11,7 @@ | |||
| 11 | #include <net/ip.h> | 11 | #include <net/ip.h> |
| 12 | #include <net/dsfield.h> | 12 | #include <net/dsfield.h> |
| 13 | #include <linux/if_vlan.h> | 13 | #include <linux/if_vlan.h> |
| 14 | #include <linux/mpls.h> | ||
| 14 | #include "core.h" | 15 | #include "core.h" |
| 15 | #include "rdev-ops.h" | 16 | #include "rdev-ops.h" |
| 16 | 17 | ||
| @@ -717,6 +718,21 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb, | |||
| 717 | case htons(ETH_P_IPV6): | 718 | case htons(ETH_P_IPV6): |
| 718 | dscp = ipv6_get_dsfield(ipv6_hdr(skb)) & 0xfc; | 719 | dscp = ipv6_get_dsfield(ipv6_hdr(skb)) & 0xfc; |
| 719 | break; | 720 | break; |
| 721 | case htons(ETH_P_MPLS_UC): | ||
| 722 | case htons(ETH_P_MPLS_MC): { | ||
| 723 | struct mpls_label mpls_tmp, *mpls; | ||
| 724 | |||
| 725 | mpls = skb_header_pointer(skb, sizeof(struct ethhdr), | ||
| 726 | sizeof(*mpls), &mpls_tmp); | ||
| 727 | if (!mpls) | ||
| 728 | return 0; | ||
| 729 | |||
| 730 | return (ntohl(mpls->entry) & MPLS_LS_TC_MASK) | ||
| 731 | >> MPLS_LS_TC_SHIFT; | ||
| 732 | } | ||
| 733 | case htons(ETH_P_80221): | ||
| 734 | /* 802.21 is always network control traffic */ | ||
| 735 | return 7; | ||
| 720 | default: | 736 | default: |
| 721 | return 0; | 737 | return 0; |
| 722 | } | 738 | } |
| @@ -820,7 +836,8 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev) | |||
| 820 | ev->dc.reason, true); | 836 | ev->dc.reason, true); |
| 821 | break; | 837 | break; |
| 822 | case EVENT_IBSS_JOINED: | 838 | case EVENT_IBSS_JOINED: |
| 823 | __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid); | 839 | __cfg80211_ibss_joined(wdev->netdev, ev->ij.bssid, |
| 840 | ev->ij.channel); | ||
| 824 | break; | 841 | break; |
| 825 | } | 842 | } |
| 826 | wdev_unlock(wdev); | 843 | wdev_unlock(wdev); |
| @@ -837,7 +854,6 @@ void cfg80211_process_rdev_events(struct cfg80211_registered_device *rdev) | |||
| 837 | struct wireless_dev *wdev; | 854 | struct wireless_dev *wdev; |
| 838 | 855 | ||
| 839 | ASSERT_RTNL(); | 856 | ASSERT_RTNL(); |
| 840 | ASSERT_RDEV_LOCK(rdev); | ||
| 841 | 857 | ||
| 842 | list_for_each_entry(wdev, &rdev->wdev_list, list) | 858 | list_for_each_entry(wdev, &rdev->wdev_list, list) |
| 843 | cfg80211_process_wdev_events(wdev); | 859 | cfg80211_process_wdev_events(wdev); |
| @@ -850,7 +866,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | |||
| 850 | int err; | 866 | int err; |
| 851 | enum nl80211_iftype otype = dev->ieee80211_ptr->iftype; | 867 | enum nl80211_iftype otype = dev->ieee80211_ptr->iftype; |
| 852 | 868 | ||
| 853 | ASSERT_RDEV_LOCK(rdev); | 869 | ASSERT_RTNL(); |
| 854 | 870 | ||
| 855 | /* don't support changing VLANs, you just re-create them */ | 871 | /* don't support changing VLANs, you just re-create them */ |
| 856 | if (otype == NL80211_IFTYPE_AP_VLAN) | 872 | if (otype == NL80211_IFTYPE_AP_VLAN) |
| @@ -885,7 +901,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev, | |||
| 885 | 901 | ||
| 886 | switch (otype) { | 902 | switch (otype) { |
| 887 | case NL80211_IFTYPE_AP: | 903 | case NL80211_IFTYPE_AP: |
| 888 | cfg80211_stop_ap(rdev, dev); | 904 | cfg80211_stop_ap(rdev, dev, true); |
| 889 | break; | 905 | break; |
| 890 | case NL80211_IFTYPE_ADHOC: | 906 | case NL80211_IFTYPE_ADHOC: |
| 891 | cfg80211_leave_ibss(rdev, dev, false); | 907 | cfg80211_leave_ibss(rdev, dev, false); |
| @@ -1268,7 +1284,6 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | |||
| 1268 | enum cfg80211_chan_mode chmode; | 1284 | enum cfg80211_chan_mode chmode; |
| 1269 | int num_different_channels = 0; | 1285 | int num_different_channels = 0; |
| 1270 | int total = 1; | 1286 | int total = 1; |
| 1271 | bool radar_required = false; | ||
| 1272 | int i, j; | 1287 | int i, j; |
| 1273 | 1288 | ||
| 1274 | ASSERT_RTNL(); | 1289 | ASSERT_RTNL(); |
| @@ -1276,35 +1291,7 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | |||
| 1276 | if (WARN_ON(hweight32(radar_detect) > 1)) | 1291 | if (WARN_ON(hweight32(radar_detect) > 1)) |
| 1277 | return -EINVAL; | 1292 | return -EINVAL; |
| 1278 | 1293 | ||
| 1279 | switch (iftype) { | 1294 | if (WARN_ON(iftype >= NUM_NL80211_IFTYPES)) |
| 1280 | case NL80211_IFTYPE_ADHOC: | ||
| 1281 | case NL80211_IFTYPE_AP: | ||
| 1282 | case NL80211_IFTYPE_AP_VLAN: | ||
| 1283 | case NL80211_IFTYPE_MESH_POINT: | ||
| 1284 | case NL80211_IFTYPE_P2P_GO: | ||
| 1285 | case NL80211_IFTYPE_WDS: | ||
| 1286 | /* if the interface could potentially choose a DFS channel, | ||
| 1287 | * then mark DFS as required. | ||
| 1288 | */ | ||
| 1289 | if (!chan) { | ||
| 1290 | if (chanmode != CHAN_MODE_UNDEFINED && radar_detect) | ||
| 1291 | radar_required = true; | ||
| 1292 | break; | ||
| 1293 | } | ||
| 1294 | radar_required = !!(chan->flags & IEEE80211_CHAN_RADAR); | ||
| 1295 | break; | ||
| 1296 | case NL80211_IFTYPE_P2P_CLIENT: | ||
| 1297 | case NL80211_IFTYPE_STATION: | ||
| 1298 | case NL80211_IFTYPE_P2P_DEVICE: | ||
| 1299 | case NL80211_IFTYPE_MONITOR: | ||
| 1300 | break; | ||
| 1301 | case NUM_NL80211_IFTYPES: | ||
| 1302 | case NL80211_IFTYPE_UNSPECIFIED: | ||
| 1303 | default: | ||
| 1304 | return -EINVAL; | ||
| 1305 | } | ||
| 1306 | |||
| 1307 | if (radar_required && !radar_detect) | ||
| 1308 | return -EINVAL; | 1295 | return -EINVAL; |
| 1309 | 1296 | ||
| 1310 | /* Always allow software iftypes */ | 1297 | /* Always allow software iftypes */ |
| @@ -1356,7 +1343,7 @@ int cfg80211_can_use_iftype_chan(struct cfg80211_registered_device *rdev, | |||
| 1356 | */ | 1343 | */ |
| 1357 | mutex_lock_nested(&wdev_iter->mtx, 1); | 1344 | mutex_lock_nested(&wdev_iter->mtx, 1); |
| 1358 | __acquire(wdev_iter->mtx); | 1345 | __acquire(wdev_iter->mtx); |
| 1359 | cfg80211_get_chan_state(wdev_iter, &ch, &chmode); | 1346 | cfg80211_get_chan_state(wdev_iter, &ch, &chmode, &radar_detect); |
| 1360 | wdev_unlock(wdev_iter); | 1347 | wdev_unlock(wdev_iter); |
| 1361 | 1348 | ||
| 1362 | switch (chmode) { | 1349 | switch (chmode) { |
diff --git a/net/wireless/wext-sme.c b/net/wireless/wext-sme.c index 14c9a2583ba0..86c331a65664 100644 --- a/net/wireless/wext-sme.c +++ b/net/wireless/wext-sme.c | |||
| @@ -21,7 +21,7 @@ int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev, | |||
| 21 | const u8 *prev_bssid = NULL; | 21 | const u8 *prev_bssid = NULL; |
| 22 | int err, i; | 22 | int err, i; |
| 23 | 23 | ||
| 24 | ASSERT_RDEV_LOCK(rdev); | 24 | ASSERT_RTNL(); |
| 25 | ASSERT_WDEV_LOCK(wdev); | 25 | ASSERT_WDEV_LOCK(wdev); |
| 26 | 26 | ||
| 27 | if (!netif_running(wdev->netdev)) | 27 | if (!netif_running(wdev->netdev)) |
diff --git a/net/x25/af_x25.c b/net/x25/af_x25.c index 6177479c7de9..5ad4418ef093 100644 --- a/net/x25/af_x25.c +++ b/net/x25/af_x25.c | |||
| @@ -1064,7 +1064,7 @@ int x25_rx_call_request(struct sk_buff *skb, struct x25_neigh *nb, | |||
| 1064 | x25_start_heartbeat(make); | 1064 | x25_start_heartbeat(make); |
| 1065 | 1065 | ||
| 1066 | if (!sock_flag(sk, SOCK_DEAD)) | 1066 | if (!sock_flag(sk, SOCK_DEAD)) |
| 1067 | sk->sk_data_ready(sk, skb->len); | 1067 | sk->sk_data_ready(sk); |
| 1068 | rc = 1; | 1068 | rc = 1; |
| 1069 | sock_put(sk); | 1069 | sock_put(sk); |
| 1070 | out: | 1070 | out: |
diff --git a/net/x25/x25_in.c b/net/x25/x25_in.c index d1b0dc79bb6f..7ac50098a375 100644 --- a/net/x25/x25_in.c +++ b/net/x25/x25_in.c | |||
| @@ -79,7 +79,7 @@ static int x25_queue_rx_frame(struct sock *sk, struct sk_buff *skb, int more) | |||
| 79 | skb_set_owner_r(skbn, sk); | 79 | skb_set_owner_r(skbn, sk); |
| 80 | skb_queue_tail(&sk->sk_receive_queue, skbn); | 80 | skb_queue_tail(&sk->sk_receive_queue, skbn); |
| 81 | if (!sock_flag(sk, SOCK_DEAD)) | 81 | if (!sock_flag(sk, SOCK_DEAD)) |
| 82 | sk->sk_data_ready(sk, skbn->len); | 82 | sk->sk_data_ready(sk); |
| 83 | 83 | ||
| 84 | return 0; | 84 | return 0; |
| 85 | } | 85 | } |
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c index 6c7ac016ce3a..85d1d4764612 100644 --- a/net/xfrm/xfrm_input.c +++ b/net/xfrm/xfrm_input.c | |||
| @@ -16,6 +16,81 @@ | |||
| 16 | 16 | ||
| 17 | static struct kmem_cache *secpath_cachep __read_mostly; | 17 | static struct kmem_cache *secpath_cachep __read_mostly; |
| 18 | 18 | ||
| 19 | static DEFINE_SPINLOCK(xfrm_input_afinfo_lock); | ||
| 20 | static struct xfrm_input_afinfo __rcu *xfrm_input_afinfo[NPROTO]; | ||
| 21 | |||
| 22 | int xfrm_input_register_afinfo(struct xfrm_input_afinfo *afinfo) | ||
| 23 | { | ||
| 24 | int err = 0; | ||
| 25 | |||
| 26 | if (unlikely(afinfo == NULL)) | ||
| 27 | return -EINVAL; | ||
| 28 | if (unlikely(afinfo->family >= NPROTO)) | ||
| 29 | return -EAFNOSUPPORT; | ||
| 30 | spin_lock_bh(&xfrm_input_afinfo_lock); | ||
| 31 | if (unlikely(xfrm_input_afinfo[afinfo->family] != NULL)) | ||
| 32 | err = -ENOBUFS; | ||
| 33 | else | ||
| 34 | rcu_assign_pointer(xfrm_input_afinfo[afinfo->family], afinfo); | ||
| 35 | spin_unlock_bh(&xfrm_input_afinfo_lock); | ||
| 36 | return err; | ||
| 37 | } | ||
| 38 | EXPORT_SYMBOL(xfrm_input_register_afinfo); | ||
| 39 | |||
| 40 | int xfrm_input_unregister_afinfo(struct xfrm_input_afinfo *afinfo) | ||
| 41 | { | ||
| 42 | int err = 0; | ||
| 43 | |||
| 44 | if (unlikely(afinfo == NULL)) | ||
| 45 | return -EINVAL; | ||
| 46 | if (unlikely(afinfo->family >= NPROTO)) | ||
| 47 | return -EAFNOSUPPORT; | ||
| 48 | spin_lock_bh(&xfrm_input_afinfo_lock); | ||
| 49 | if (likely(xfrm_input_afinfo[afinfo->family] != NULL)) { | ||
| 50 | if (unlikely(xfrm_input_afinfo[afinfo->family] != afinfo)) | ||
| 51 | err = -EINVAL; | ||
| 52 | else | ||
| 53 | RCU_INIT_POINTER(xfrm_input_afinfo[afinfo->family], NULL); | ||
| 54 | } | ||
| 55 | spin_unlock_bh(&xfrm_input_afinfo_lock); | ||
| 56 | synchronize_rcu(); | ||
| 57 | return err; | ||
| 58 | } | ||
| 59 | EXPORT_SYMBOL(xfrm_input_unregister_afinfo); | ||
| 60 | |||
| 61 | static struct xfrm_input_afinfo *xfrm_input_get_afinfo(unsigned int family) | ||
| 62 | { | ||
| 63 | struct xfrm_input_afinfo *afinfo; | ||
| 64 | |||
| 65 | if (unlikely(family >= NPROTO)) | ||
| 66 | return NULL; | ||
| 67 | rcu_read_lock(); | ||
| 68 | afinfo = rcu_dereference(xfrm_input_afinfo[family]); | ||
| 69 | if (unlikely(!afinfo)) | ||
| 70 | rcu_read_unlock(); | ||
| 71 | return afinfo; | ||
| 72 | } | ||
| 73 | |||
| 74 | static void xfrm_input_put_afinfo(struct xfrm_input_afinfo *afinfo) | ||
| 75 | { | ||
| 76 | rcu_read_unlock(); | ||
| 77 | } | ||
| 78 | |||
| 79 | static int xfrm_rcv_cb(struct sk_buff *skb, unsigned int family, u8 protocol, | ||
| 80 | int err) | ||
| 81 | { | ||
| 82 | int ret; | ||
| 83 | struct xfrm_input_afinfo *afinfo = xfrm_input_get_afinfo(family); | ||
| 84 | |||
| 85 | if (!afinfo) | ||
| 86 | return -EAFNOSUPPORT; | ||
| 87 | |||
| 88 | ret = afinfo->callback(skb, protocol, err); | ||
| 89 | xfrm_input_put_afinfo(afinfo); | ||
| 90 | |||
| 91 | return ret; | ||
| 92 | } | ||
| 93 | |||
| 19 | void __secpath_destroy(struct sec_path *sp) | 94 | void __secpath_destroy(struct sec_path *sp) |
| 20 | { | 95 | { |
| 21 | int i; | 96 | int i; |
| @@ -108,7 +183,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) | |||
| 108 | int err; | 183 | int err; |
| 109 | __be32 seq; | 184 | __be32 seq; |
| 110 | __be32 seq_hi; | 185 | __be32 seq_hi; |
| 111 | struct xfrm_state *x; | 186 | struct xfrm_state *x = NULL; |
| 112 | xfrm_address_t *daddr; | 187 | xfrm_address_t *daddr; |
| 113 | struct xfrm_mode *inner_mode; | 188 | struct xfrm_mode *inner_mode; |
| 114 | unsigned int family; | 189 | unsigned int family; |
| @@ -120,9 +195,14 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) | |||
| 120 | async = 1; | 195 | async = 1; |
| 121 | x = xfrm_input_state(skb); | 196 | x = xfrm_input_state(skb); |
| 122 | seq = XFRM_SKB_CB(skb)->seq.input.low; | 197 | seq = XFRM_SKB_CB(skb)->seq.input.low; |
| 198 | family = x->outer_mode->afinfo->family; | ||
| 123 | goto resume; | 199 | goto resume; |
| 124 | } | 200 | } |
| 125 | 201 | ||
| 202 | daddr = (xfrm_address_t *)(skb_network_header(skb) + | ||
| 203 | XFRM_SPI_SKB_CB(skb)->daddroff); | ||
| 204 | family = XFRM_SPI_SKB_CB(skb)->family; | ||
| 205 | |||
| 126 | /* Allocate new secpath or COW existing one. */ | 206 | /* Allocate new secpath or COW existing one. */ |
| 127 | if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) { | 207 | if (!skb->sp || atomic_read(&skb->sp->refcnt) != 1) { |
| 128 | struct sec_path *sp; | 208 | struct sec_path *sp; |
| @@ -137,10 +217,6 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) | |||
| 137 | skb->sp = sp; | 217 | skb->sp = sp; |
| 138 | } | 218 | } |
| 139 | 219 | ||
| 140 | daddr = (xfrm_address_t *)(skb_network_header(skb) + | ||
| 141 | XFRM_SPI_SKB_CB(skb)->daddroff); | ||
| 142 | family = XFRM_SPI_SKB_CB(skb)->family; | ||
| 143 | |||
| 144 | seq = 0; | 220 | seq = 0; |
| 145 | if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) { | 221 | if (!spi && (err = xfrm_parse_spi(skb, nexthdr, &spi, &seq)) != 0) { |
| 146 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINHDRERROR); | 222 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINHDRERROR); |
| @@ -162,6 +238,11 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) | |||
| 162 | 238 | ||
| 163 | skb->sp->xvec[skb->sp->len++] = x; | 239 | skb->sp->xvec[skb->sp->len++] = x; |
| 164 | 240 | ||
| 241 | if (xfrm_tunnel_check(skb, x, family)) { | ||
| 242 | XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATEMODEERROR); | ||
| 243 | goto drop; | ||
| 244 | } | ||
| 245 | |||
| 165 | spin_lock(&x->lock); | 246 | spin_lock(&x->lock); |
| 166 | if (unlikely(x->km.state == XFRM_STATE_ACQ)) { | 247 | if (unlikely(x->km.state == XFRM_STATE_ACQ)) { |
| 167 | XFRM_INC_STATS(net, LINUX_MIB_XFRMACQUIREERROR); | 248 | XFRM_INC_STATS(net, LINUX_MIB_XFRMACQUIREERROR); |
| @@ -201,7 +282,6 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type) | |||
| 201 | 282 | ||
| 202 | if (nexthdr == -EINPROGRESS) | 283 | if (nexthdr == -EINPROGRESS) |
| 203 | return 0; | 284 | return 0; |
| 204 | |||
| 205 | resume: | 285 | resume: |
| 206 | spin_lock(&x->lock); | 286 | spin_lock(&x->lock); |
| 207 | if (nexthdr <= 0) { | 287 | if (nexthdr <= 0) { |
| @@ -263,6 +343,10 @@ resume: | |||
| 263 | } | 343 | } |
| 264 | } while (!err); | 344 | } while (!err); |
| 265 | 345 | ||
| 346 | err = xfrm_rcv_cb(skb, family, x->type->proto, 0); | ||
| 347 | if (err) | ||
| 348 | goto drop; | ||
| 349 | |||
| 266 | nf_reset(skb); | 350 | nf_reset(skb); |
| 267 | 351 | ||
| 268 | if (decaps) { | 352 | if (decaps) { |
| @@ -276,6 +360,7 @@ resume: | |||
| 276 | drop_unlock: | 360 | drop_unlock: |
| 277 | spin_unlock(&x->lock); | 361 | spin_unlock(&x->lock); |
| 278 | drop: | 362 | drop: |
| 363 | xfrm_rcv_cb(skb, family, x && x->type ? x->type->proto : nexthdr, -1); | ||
| 279 | kfree_skb(skb); | 364 | kfree_skb(skb); |
| 280 | return 0; | 365 | return 0; |
| 281 | } | 366 | } |
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index 1d5c7bf29938..c08fbd11ceff 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c | |||
| @@ -39,8 +39,6 @@ | |||
| 39 | #define XFRM_QUEUE_TMO_MAX ((unsigned)(60*HZ)) | 39 | #define XFRM_QUEUE_TMO_MAX ((unsigned)(60*HZ)) |
| 40 | #define XFRM_MAX_QUEUE_LEN 100 | 40 | #define XFRM_MAX_QUEUE_LEN 100 |
| 41 | 41 | ||
| 42 | static struct dst_entry *xfrm_policy_sk_bundles; | ||
| 43 | |||
| 44 | static DEFINE_SPINLOCK(xfrm_policy_afinfo_lock); | 42 | static DEFINE_SPINLOCK(xfrm_policy_afinfo_lock); |
| 45 | static struct xfrm_policy_afinfo __rcu *xfrm_policy_afinfo[NPROTO] | 43 | static struct xfrm_policy_afinfo __rcu *xfrm_policy_afinfo[NPROTO] |
| 46 | __read_mostly; | 44 | __read_mostly; |
| @@ -661,7 +659,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl) | |||
| 661 | hlist_add_head(&policy->bydst, chain); | 659 | hlist_add_head(&policy->bydst, chain); |
| 662 | xfrm_pol_hold(policy); | 660 | xfrm_pol_hold(policy); |
| 663 | net->xfrm.policy_count[dir]++; | 661 | net->xfrm.policy_count[dir]++; |
| 664 | atomic_inc(&flow_cache_genid); | 662 | atomic_inc(&net->xfrm.flow_cache_genid); |
| 665 | 663 | ||
| 666 | /* After previous checking, family can either be AF_INET or AF_INET6 */ | 664 | /* After previous checking, family can either be AF_INET or AF_INET6 */ |
| 667 | if (policy->family == AF_INET) | 665 | if (policy->family == AF_INET) |
| @@ -1844,7 +1842,7 @@ purge_queue: | |||
| 1844 | xfrm_pol_put(pol); | 1842 | xfrm_pol_put(pol); |
| 1845 | } | 1843 | } |
| 1846 | 1844 | ||
| 1847 | static int xdst_queue_output(struct sk_buff *skb) | 1845 | static int xdst_queue_output(struct sock *sk, struct sk_buff *skb) |
| 1848 | { | 1846 | { |
| 1849 | unsigned long sched_next; | 1847 | unsigned long sched_next; |
| 1850 | struct dst_entry *dst = skb_dst(skb); | 1848 | struct dst_entry *dst = skb_dst(skb); |
| @@ -2109,13 +2107,6 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, | |||
| 2109 | goto no_transform; | 2107 | goto no_transform; |
| 2110 | } | 2108 | } |
| 2111 | 2109 | ||
| 2112 | dst_hold(&xdst->u.dst); | ||
| 2113 | |||
| 2114 | spin_lock_bh(&net->xfrm.xfrm_policy_sk_bundle_lock); | ||
| 2115 | xdst->u.dst.next = xfrm_policy_sk_bundles; | ||
| 2116 | xfrm_policy_sk_bundles = &xdst->u.dst; | ||
| 2117 | spin_unlock_bh(&net->xfrm.xfrm_policy_sk_bundle_lock); | ||
| 2118 | |||
| 2119 | route = xdst->route; | 2110 | route = xdst->route; |
| 2120 | } | 2111 | } |
| 2121 | } | 2112 | } |
| @@ -2549,33 +2540,15 @@ static struct dst_entry *xfrm_negative_advice(struct dst_entry *dst) | |||
| 2549 | return dst; | 2540 | return dst; |
| 2550 | } | 2541 | } |
| 2551 | 2542 | ||
| 2552 | static void __xfrm_garbage_collect(struct net *net) | ||
| 2553 | { | ||
| 2554 | struct dst_entry *head, *next; | ||
| 2555 | |||
| 2556 | spin_lock_bh(&net->xfrm.xfrm_policy_sk_bundle_lock); | ||
| 2557 | head = xfrm_policy_sk_bundles; | ||
| 2558 | xfrm_policy_sk_bundles = NULL; | ||
| 2559 | spin_unlock_bh(&net->xfrm.xfrm_policy_sk_bundle_lock); | ||
| 2560 | |||
| 2561 | while (head) { | ||
| 2562 | next = head->next; | ||
| 2563 | dst_free(head); | ||
| 2564 | head = next; | ||
| 2565 | } | ||
| 2566 | } | ||
| 2567 | |||
| 2568 | void xfrm_garbage_collect(struct net *net) | 2543 | void xfrm_garbage_collect(struct net *net) |
| 2569 | { | 2544 | { |
| 2570 | flow_cache_flush(); | 2545 | flow_cache_flush(net); |
| 2571 | __xfrm_garbage_collect(net); | ||
| 2572 | } | 2546 | } |
| 2573 | EXPORT_SYMBOL(xfrm_garbage_collect); | 2547 | EXPORT_SYMBOL(xfrm_garbage_collect); |
| 2574 | 2548 | ||
| 2575 | static void xfrm_garbage_collect_deferred(struct net *net) | 2549 | static void xfrm_garbage_collect_deferred(struct net *net) |
| 2576 | { | 2550 | { |
| 2577 | flow_cache_flush_deferred(); | 2551 | flow_cache_flush_deferred(net); |
| 2578 | __xfrm_garbage_collect(net); | ||
| 2579 | } | 2552 | } |
| 2580 | 2553 | ||
| 2581 | static void xfrm_init_pmtu(struct dst_entry *dst) | 2554 | static void xfrm_init_pmtu(struct dst_entry *dst) |
| @@ -2940,15 +2913,19 @@ static int __net_init xfrm_net_init(struct net *net) | |||
| 2940 | rv = xfrm_sysctl_init(net); | 2913 | rv = xfrm_sysctl_init(net); |
| 2941 | if (rv < 0) | 2914 | if (rv < 0) |
| 2942 | goto out_sysctl; | 2915 | goto out_sysctl; |
| 2916 | rv = flow_cache_init(net); | ||
| 2917 | if (rv < 0) | ||
| 2918 | goto out; | ||
| 2943 | 2919 | ||
| 2944 | /* Initialize the per-net locks here */ | 2920 | /* Initialize the per-net locks here */ |
| 2945 | spin_lock_init(&net->xfrm.xfrm_state_lock); | 2921 | spin_lock_init(&net->xfrm.xfrm_state_lock); |
| 2946 | rwlock_init(&net->xfrm.xfrm_policy_lock); | 2922 | rwlock_init(&net->xfrm.xfrm_policy_lock); |
| 2947 | spin_lock_init(&net->xfrm.xfrm_policy_sk_bundle_lock); | ||
| 2948 | mutex_init(&net->xfrm.xfrm_cfg_mutex); | 2923 | mutex_init(&net->xfrm.xfrm_cfg_mutex); |
| 2949 | 2924 | ||
| 2950 | return 0; | 2925 | return 0; |
| 2951 | 2926 | ||
| 2927 | out: | ||
| 2928 | xfrm_sysctl_fini(net); | ||
| 2952 | out_sysctl: | 2929 | out_sysctl: |
| 2953 | xfrm_policy_fini(net); | 2930 | xfrm_policy_fini(net); |
| 2954 | out_policy: | 2931 | out_policy: |
| @@ -2961,6 +2938,7 @@ out_statistics: | |||
| 2961 | 2938 | ||
| 2962 | static void __net_exit xfrm_net_exit(struct net *net) | 2939 | static void __net_exit xfrm_net_exit(struct net *net) |
| 2963 | { | 2940 | { |
| 2941 | flow_cache_fini(net); | ||
| 2964 | xfrm_sysctl_fini(net); | 2942 | xfrm_sysctl_fini(net); |
| 2965 | xfrm_policy_fini(net); | 2943 | xfrm_policy_fini(net); |
| 2966 | xfrm_state_fini(net); | 2944 | xfrm_state_fini(net); |
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index 40f1b3e92e78..8e9c781a6bba 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c | |||
| @@ -161,6 +161,7 @@ static DEFINE_SPINLOCK(xfrm_state_gc_lock); | |||
| 161 | int __xfrm_state_delete(struct xfrm_state *x); | 161 | int __xfrm_state_delete(struct xfrm_state *x); |
| 162 | 162 | ||
| 163 | int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol); | 163 | int km_query(struct xfrm_state *x, struct xfrm_tmpl *t, struct xfrm_policy *pol); |
| 164 | bool km_is_alive(const struct km_event *c); | ||
| 164 | void km_state_expired(struct xfrm_state *x, int hard, u32 portid); | 165 | void km_state_expired(struct xfrm_state *x, int hard, u32 portid); |
| 165 | 166 | ||
| 166 | static DEFINE_SPINLOCK(xfrm_type_lock); | 167 | static DEFINE_SPINLOCK(xfrm_type_lock); |
| @@ -788,6 +789,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr, | |||
| 788 | struct xfrm_state *best = NULL; | 789 | struct xfrm_state *best = NULL; |
| 789 | u32 mark = pol->mark.v & pol->mark.m; | 790 | u32 mark = pol->mark.v & pol->mark.m; |
| 790 | unsigned short encap_family = tmpl->encap_family; | 791 | unsigned short encap_family = tmpl->encap_family; |
| 792 | struct km_event c; | ||
| 791 | 793 | ||
| 792 | to_put = NULL; | 794 | to_put = NULL; |
| 793 | 795 | ||
| @@ -832,6 +834,17 @@ found: | |||
| 832 | error = -EEXIST; | 834 | error = -EEXIST; |
| 833 | goto out; | 835 | goto out; |
| 834 | } | 836 | } |
| 837 | |||
| 838 | c.net = net; | ||
| 839 | /* If the KMs have no listeners (yet...), avoid allocating an SA | ||
| 840 | * for each and every packet - garbage collection might not | ||
| 841 | * handle the flood. | ||
| 842 | */ | ||
| 843 | if (!km_is_alive(&c)) { | ||
| 844 | error = -ESRCH; | ||
| 845 | goto out; | ||
| 846 | } | ||
| 847 | |||
| 835 | x = xfrm_state_alloc(net); | 848 | x = xfrm_state_alloc(net); |
| 836 | if (x == NULL) { | 849 | if (x == NULL) { |
| 837 | error = -ENOMEM; | 850 | error = -ENOMEM; |
| @@ -1135,10 +1148,9 @@ out: | |||
| 1135 | EXPORT_SYMBOL(xfrm_state_add); | 1148 | EXPORT_SYMBOL(xfrm_state_add); |
| 1136 | 1149 | ||
| 1137 | #ifdef CONFIG_XFRM_MIGRATE | 1150 | #ifdef CONFIG_XFRM_MIGRATE |
| 1138 | static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp) | 1151 | static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig) |
| 1139 | { | 1152 | { |
| 1140 | struct net *net = xs_net(orig); | 1153 | struct net *net = xs_net(orig); |
| 1141 | int err = -ENOMEM; | ||
| 1142 | struct xfrm_state *x = xfrm_state_alloc(net); | 1154 | struct xfrm_state *x = xfrm_state_alloc(net); |
| 1143 | if (!x) | 1155 | if (!x) |
| 1144 | goto out; | 1156 | goto out; |
| @@ -1192,15 +1204,13 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp) | |||
| 1192 | } | 1204 | } |
| 1193 | 1205 | ||
| 1194 | if (orig->replay_esn) { | 1206 | if (orig->replay_esn) { |
| 1195 | err = xfrm_replay_clone(x, orig); | 1207 | if (xfrm_replay_clone(x, orig)) |
| 1196 | if (err) | ||
| 1197 | goto error; | 1208 | goto error; |
| 1198 | } | 1209 | } |
| 1199 | 1210 | ||
| 1200 | memcpy(&x->mark, &orig->mark, sizeof(x->mark)); | 1211 | memcpy(&x->mark, &orig->mark, sizeof(x->mark)); |
| 1201 | 1212 | ||
| 1202 | err = xfrm_init_state(x); | 1213 | if (xfrm_init_state(x) < 0) |
| 1203 | if (err) | ||
| 1204 | goto error; | 1214 | goto error; |
| 1205 | 1215 | ||
| 1206 | x->props.flags = orig->props.flags; | 1216 | x->props.flags = orig->props.flags; |
| @@ -1218,8 +1228,6 @@ static struct xfrm_state *xfrm_state_clone(struct xfrm_state *orig, int *errp) | |||
| 1218 | error: | 1228 | error: |
| 1219 | xfrm_state_put(x); | 1229 | xfrm_state_put(x); |
| 1220 | out: | 1230 | out: |
| 1221 | if (errp) | ||
| 1222 | *errp = err; | ||
| 1223 | return NULL; | 1231 | return NULL; |
| 1224 | } | 1232 | } |
| 1225 | 1233 | ||
| @@ -1274,9 +1282,8 @@ struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x, | |||
| 1274 | struct xfrm_migrate *m) | 1282 | struct xfrm_migrate *m) |
| 1275 | { | 1283 | { |
| 1276 | struct xfrm_state *xc; | 1284 | struct xfrm_state *xc; |
| 1277 | int err; | ||
| 1278 | 1285 | ||
| 1279 | xc = xfrm_state_clone(x, &err); | 1286 | xc = xfrm_state_clone(x); |
| 1280 | if (!xc) | 1287 | if (!xc) |
| 1281 | return NULL; | 1288 | return NULL; |
| 1282 | 1289 | ||
| @@ -1289,7 +1296,7 @@ struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x, | |||
| 1289 | state is to be updated as it is a part of triplet */ | 1296 | state is to be updated as it is a part of triplet */ |
| 1290 | xfrm_state_insert(xc); | 1297 | xfrm_state_insert(xc); |
| 1291 | } else { | 1298 | } else { |
| 1292 | if ((err = xfrm_state_add(xc)) < 0) | 1299 | if (xfrm_state_add(xc) < 0) |
| 1293 | goto error; | 1300 | goto error; |
| 1294 | } | 1301 | } |
| 1295 | 1302 | ||
| @@ -1601,6 +1608,23 @@ unlock: | |||
| 1601 | } | 1608 | } |
| 1602 | EXPORT_SYMBOL(xfrm_alloc_spi); | 1609 | EXPORT_SYMBOL(xfrm_alloc_spi); |
| 1603 | 1610 | ||
| 1611 | static bool __xfrm_state_filter_match(struct xfrm_state *x, | ||
| 1612 | struct xfrm_address_filter *filter) | ||
| 1613 | { | ||
| 1614 | if (filter) { | ||
| 1615 | if ((filter->family == AF_INET || | ||
| 1616 | filter->family == AF_INET6) && | ||
| 1617 | x->props.family != filter->family) | ||
| 1618 | return false; | ||
| 1619 | |||
| 1620 | return addr_match(&x->props.saddr, &filter->saddr, | ||
| 1621 | filter->splen) && | ||
| 1622 | addr_match(&x->id.daddr, &filter->daddr, | ||
| 1623 | filter->dplen); | ||
| 1624 | } | ||
| 1625 | return true; | ||
| 1626 | } | ||
| 1627 | |||
| 1604 | int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk, | 1628 | int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk, |
| 1605 | int (*func)(struct xfrm_state *, int, void*), | 1629 | int (*func)(struct xfrm_state *, int, void*), |
| 1606 | void *data) | 1630 | void *data) |
| @@ -1623,6 +1647,8 @@ int xfrm_state_walk(struct net *net, struct xfrm_state_walk *walk, | |||
| 1623 | state = container_of(x, struct xfrm_state, km); | 1647 | state = container_of(x, struct xfrm_state, km); |
| 1624 | if (!xfrm_id_proto_match(state->id.proto, walk->proto)) | 1648 | if (!xfrm_id_proto_match(state->id.proto, walk->proto)) |
| 1625 | continue; | 1649 | continue; |
| 1650 | if (!__xfrm_state_filter_match(state, walk->filter)) | ||
| 1651 | continue; | ||
| 1626 | err = func(state, walk->seq, data); | 1652 | err = func(state, walk->seq, data); |
| 1627 | if (err) { | 1653 | if (err) { |
| 1628 | list_move_tail(&walk->all, &x->all); | 1654 | list_move_tail(&walk->all, &x->all); |
| @@ -1641,17 +1667,21 @@ out: | |||
| 1641 | } | 1667 | } |
| 1642 | EXPORT_SYMBOL(xfrm_state_walk); | 1668 | EXPORT_SYMBOL(xfrm_state_walk); |
| 1643 | 1669 | ||
| 1644 | void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto) | 1670 | void xfrm_state_walk_init(struct xfrm_state_walk *walk, u8 proto, |
| 1671 | struct xfrm_address_filter *filter) | ||
| 1645 | { | 1672 | { |
| 1646 | INIT_LIST_HEAD(&walk->all); | 1673 | INIT_LIST_HEAD(&walk->all); |
| 1647 | walk->proto = proto; | 1674 | walk->proto = proto; |
| 1648 | walk->state = XFRM_STATE_DEAD; | 1675 | walk->state = XFRM_STATE_DEAD; |
| 1649 | walk->seq = 0; | 1676 | walk->seq = 0; |
| 1677 | walk->filter = filter; | ||
| 1650 | } | 1678 | } |
| 1651 | EXPORT_SYMBOL(xfrm_state_walk_init); | 1679 | EXPORT_SYMBOL(xfrm_state_walk_init); |
| 1652 | 1680 | ||
| 1653 | void xfrm_state_walk_done(struct xfrm_state_walk *walk, struct net *net) | 1681 | void xfrm_state_walk_done(struct xfrm_state_walk *walk, struct net *net) |
| 1654 | { | 1682 | { |
| 1683 | kfree(walk->filter); | ||
| 1684 | |||
| 1655 | if (list_empty(&walk->all)) | 1685 | if (list_empty(&walk->all)) |
| 1656 | return; | 1686 | return; |
| 1657 | 1687 | ||
| @@ -1804,6 +1834,24 @@ int km_report(struct net *net, u8 proto, struct xfrm_selector *sel, xfrm_address | |||
| 1804 | } | 1834 | } |
| 1805 | EXPORT_SYMBOL(km_report); | 1835 | EXPORT_SYMBOL(km_report); |
| 1806 | 1836 | ||
| 1837 | bool km_is_alive(const struct km_event *c) | ||
| 1838 | { | ||
| 1839 | struct xfrm_mgr *km; | ||
| 1840 | bool is_alive = false; | ||
| 1841 | |||
| 1842 | rcu_read_lock(); | ||
| 1843 | list_for_each_entry_rcu(km, &xfrm_km_list, list) { | ||
| 1844 | if (km->is_alive && km->is_alive(c)) { | ||
| 1845 | is_alive = true; | ||
| 1846 | break; | ||
| 1847 | } | ||
| 1848 | } | ||
| 1849 | rcu_read_unlock(); | ||
| 1850 | |||
| 1851 | return is_alive; | ||
| 1852 | } | ||
| 1853 | EXPORT_SYMBOL(km_is_alive); | ||
| 1854 | |||
| 1807 | int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen) | 1855 | int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen) |
| 1808 | { | 1856 | { |
| 1809 | int err; | 1857 | int err; |
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index 2f7ddc3a59b4..8f131c10a6f3 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
| @@ -137,7 +137,8 @@ static inline int verify_replay(struct xfrm_usersa_info *p, | |||
| 137 | if (!rt) | 137 | if (!rt) |
| 138 | return 0; | 138 | return 0; |
| 139 | 139 | ||
| 140 | if (p->id.proto != IPPROTO_ESP) | 140 | /* As only ESP and AH support ESN feature. */ |
| 141 | if ((p->id.proto != IPPROTO_ESP) && (p->id.proto != IPPROTO_AH)) | ||
| 141 | return -EINVAL; | 142 | return -EINVAL; |
| 142 | 143 | ||
| 143 | if (p->replay_window != 0) | 144 | if (p->replay_window != 0) |
| @@ -881,6 +882,7 @@ static int xfrm_dump_sa_done(struct netlink_callback *cb) | |||
| 881 | return 0; | 882 | return 0; |
| 882 | } | 883 | } |
| 883 | 884 | ||
| 885 | static const struct nla_policy xfrma_policy[XFRMA_MAX+1]; | ||
| 884 | static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb) | 886 | static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb) |
| 885 | { | 887 | { |
| 886 | struct net *net = sock_net(skb->sk); | 888 | struct net *net = sock_net(skb->sk); |
| @@ -896,8 +898,31 @@ static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 896 | info.nlmsg_flags = NLM_F_MULTI; | 898 | info.nlmsg_flags = NLM_F_MULTI; |
| 897 | 899 | ||
| 898 | if (!cb->args[0]) { | 900 | if (!cb->args[0]) { |
| 901 | struct nlattr *attrs[XFRMA_MAX+1]; | ||
| 902 | struct xfrm_address_filter *filter = NULL; | ||
| 903 | u8 proto = 0; | ||
| 904 | int err; | ||
| 905 | |||
| 899 | cb->args[0] = 1; | 906 | cb->args[0] = 1; |
| 900 | xfrm_state_walk_init(walk, 0); | 907 | |
| 908 | err = nlmsg_parse(cb->nlh, 0, attrs, XFRMA_MAX, | ||
| 909 | xfrma_policy); | ||
| 910 | if (err < 0) | ||
| 911 | return err; | ||
| 912 | |||
| 913 | if (attrs[XFRMA_ADDRESS_FILTER]) { | ||
| 914 | filter = kmalloc(sizeof(*filter), GFP_KERNEL); | ||
| 915 | if (filter == NULL) | ||
| 916 | return -ENOMEM; | ||
| 917 | |||
| 918 | memcpy(filter, nla_data(attrs[XFRMA_ADDRESS_FILTER]), | ||
| 919 | sizeof(*filter)); | ||
| 920 | } | ||
| 921 | |||
| 922 | if (attrs[XFRMA_PROTO]) | ||
| 923 | proto = nla_get_u8(attrs[XFRMA_PROTO]); | ||
| 924 | |||
| 925 | xfrm_state_walk_init(walk, proto, filter); | ||
| 901 | } | 926 | } |
| 902 | 927 | ||
| 903 | (void) xfrm_state_walk(net, walk, dump_one_state, &info); | 928 | (void) xfrm_state_walk(net, walk, dump_one_state, &info); |
| @@ -2303,6 +2328,8 @@ static const struct nla_policy xfrma_policy[XFRMA_MAX+1] = { | |||
| 2303 | [XFRMA_TFCPAD] = { .type = NLA_U32 }, | 2328 | [XFRMA_TFCPAD] = { .type = NLA_U32 }, |
| 2304 | [XFRMA_REPLAY_ESN_VAL] = { .len = sizeof(struct xfrm_replay_state_esn) }, | 2329 | [XFRMA_REPLAY_ESN_VAL] = { .len = sizeof(struct xfrm_replay_state_esn) }, |
| 2305 | [XFRMA_SA_EXTRA_FLAGS] = { .type = NLA_U32 }, | 2330 | [XFRMA_SA_EXTRA_FLAGS] = { .type = NLA_U32 }, |
| 2331 | [XFRMA_PROTO] = { .type = NLA_U8 }, | ||
| 2332 | [XFRMA_ADDRESS_FILTER] = { .len = sizeof(struct xfrm_address_filter) }, | ||
| 2306 | }; | 2333 | }; |
| 2307 | 2334 | ||
| 2308 | static const struct xfrm_link { | 2335 | static const struct xfrm_link { |
| @@ -2976,6 +3003,11 @@ static int xfrm_send_mapping(struct xfrm_state *x, xfrm_address_t *ipaddr, | |||
| 2976 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_MAPPING, GFP_ATOMIC); | 3003 | return nlmsg_multicast(net->xfrm.nlsk, skb, 0, XFRMNLGRP_MAPPING, GFP_ATOMIC); |
| 2977 | } | 3004 | } |
| 2978 | 3005 | ||
| 3006 | static bool xfrm_is_alive(const struct km_event *c) | ||
| 3007 | { | ||
| 3008 | return (bool)xfrm_acquire_is_on(c->net); | ||
| 3009 | } | ||
| 3010 | |||
| 2979 | static struct xfrm_mgr netlink_mgr = { | 3011 | static struct xfrm_mgr netlink_mgr = { |
| 2980 | .id = "netlink", | 3012 | .id = "netlink", |
| 2981 | .notify = xfrm_send_state_notify, | 3013 | .notify = xfrm_send_state_notify, |
| @@ -2985,6 +3017,7 @@ static struct xfrm_mgr netlink_mgr = { | |||
| 2985 | .report = xfrm_send_report, | 3017 | .report = xfrm_send_report, |
| 2986 | .migrate = xfrm_send_migrate, | 3018 | .migrate = xfrm_send_migrate, |
| 2987 | .new_mapping = xfrm_send_mapping, | 3019 | .new_mapping = xfrm_send_mapping, |
| 3020 | .is_alive = xfrm_is_alive, | ||
| 2988 | }; | 3021 | }; |
| 2989 | 3022 | ||
| 2990 | static int __net_init xfrm_user_net_init(struct net *net) | 3023 | static int __net_init xfrm_user_net_init(struct net *net) |
