.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | Copyright (c) 2013-2014 Intel Corp. |
---|
3 | 4 | |
---|
4 | | - This program is free software; you can redistribute it and/or modify |
---|
5 | | - it under the terms of the GNU General Public License version 2 and |
---|
6 | | - only version 2 as published by the Free Software Foundation. |
---|
7 | | - |
---|
8 | | - This program is distributed in the hope that it will be useful, |
---|
9 | | - but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
10 | | - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
11 | | - GNU General Public License for more details. |
---|
12 | 5 | */ |
---|
13 | 6 | |
---|
14 | 7 | #include <linux/if_arp.h> |
---|
.. | .. |
---|
168 | 161 | struct in6_addr *daddr, |
---|
169 | 162 | struct sk_buff *skb) |
---|
170 | 163 | { |
---|
171 | | - struct lowpan_peer *peer; |
---|
172 | | - struct in6_addr *nexthop; |
---|
173 | 164 | struct rt6_info *rt = (struct rt6_info *)skb_dst(skb); |
---|
174 | 165 | int count = atomic_read(&dev->peer_count); |
---|
| 166 | + const struct in6_addr *nexthop; |
---|
| 167 | + struct lowpan_peer *peer; |
---|
| 168 | + struct neighbour *neigh; |
---|
175 | 169 | |
---|
176 | 170 | BT_DBG("peers %d addr %pI6c rt %p", count, daddr, rt); |
---|
177 | | - |
---|
178 | | - /* If we have multiple 6lowpan peers, then check where we should |
---|
179 | | - * send the packet. If only one peer exists, then we can send the |
---|
180 | | - * packet right away. |
---|
181 | | - */ |
---|
182 | | - if (count == 1) { |
---|
183 | | - rcu_read_lock(); |
---|
184 | | - peer = list_first_or_null_rcu(&dev->peers, struct lowpan_peer, |
---|
185 | | - list); |
---|
186 | | - rcu_read_unlock(); |
---|
187 | | - return peer; |
---|
188 | | - } |
---|
189 | 171 | |
---|
190 | 172 | if (!rt) { |
---|
191 | 173 | if (ipv6_addr_any(&lowpan_cb(skb)->gw)) { |
---|
.. | .. |
---|
221 | 203 | rcu_read_unlock(); |
---|
222 | 204 | return peer; |
---|
223 | 205 | } |
---|
| 206 | + } |
---|
| 207 | + |
---|
| 208 | + /* use the neighbour cache for matching addresses assigned by SLAAC |
---|
| 209 | + */ |
---|
| 210 | + neigh = __ipv6_neigh_lookup(dev->netdev, nexthop); |
---|
| 211 | + if (neigh) { |
---|
| 212 | + list_for_each_entry_rcu(peer, &dev->peers, list) { |
---|
| 213 | + if (!memcmp(neigh->ha, peer->lladdr, ETH_ALEN)) { |
---|
| 214 | + neigh_release(neigh); |
---|
| 215 | + rcu_read_unlock(); |
---|
| 216 | + return peer; |
---|
| 217 | + } |
---|
| 218 | + } |
---|
| 219 | + neigh_release(neigh); |
---|
224 | 220 | } |
---|
225 | 221 | |
---|
226 | 222 | rcu_read_unlock(); |
---|
.. | .. |
---|
474 | 470 | iv.iov_len = skb->len; |
---|
475 | 471 | |
---|
476 | 472 | memset(&msg, 0, sizeof(msg)); |
---|
477 | | - iov_iter_kvec(&msg.msg_iter, WRITE | ITER_KVEC, &iv, 1, skb->len); |
---|
| 473 | + iov_iter_kvec(&msg.msg_iter, WRITE, &iv, 1, skb->len); |
---|
478 | 474 | |
---|
479 | 475 | err = l2cap_chan_send(chan, &msg, skb->len); |
---|
480 | 476 | if (err > 0) { |
---|
.. | .. |
---|
588 | 584 | .ndo_start_xmit = bt_xmit, |
---|
589 | 585 | }; |
---|
590 | 586 | |
---|
591 | | -static struct header_ops header_ops = { |
---|
| 587 | +static const struct header_ops header_ops = { |
---|
592 | 588 | .create = header_create, |
---|
593 | 589 | }; |
---|
594 | 590 | |
---|
.. | .. |
---|
614 | 610 | int err; |
---|
615 | 611 | |
---|
616 | 612 | rtnl_lock(); |
---|
617 | | - err = dev_open(netdev); |
---|
| 613 | + err = dev_open(netdev, NULL); |
---|
618 | 614 | if (err < 0) |
---|
619 | 615 | BT_INFO("iface %s cannot be opened (%d)", netdev->name, err); |
---|
620 | 616 | rtnl_unlock(); |
---|
.. | .. |
---|
1014 | 1010 | hci_dev_lock(hdev); |
---|
1015 | 1011 | hcon = hci_conn_hash_lookup_le(hdev, addr, *addr_type); |
---|
1016 | 1012 | hci_dev_unlock(hdev); |
---|
| 1013 | + hci_dev_put(hdev); |
---|
1017 | 1014 | |
---|
1018 | 1015 | if (!hcon) |
---|
1019 | 1016 | return -ENOENT; |
---|
.. | .. |
---|
1117 | 1114 | return 0; |
---|
1118 | 1115 | } |
---|
1119 | 1116 | |
---|
1120 | | -DEFINE_SIMPLE_ATTRIBUTE(lowpan_enable_fops, lowpan_enable_get, |
---|
1121 | | - lowpan_enable_set, "%llu\n"); |
---|
| 1117 | +DEFINE_DEBUGFS_ATTRIBUTE(lowpan_enable_fops, lowpan_enable_get, |
---|
| 1118 | + lowpan_enable_set, "%llu\n"); |
---|
1122 | 1119 | |
---|
1123 | 1120 | static ssize_t lowpan_control_write(struct file *fp, |
---|
1124 | 1121 | const char __user *user_buffer, |
---|
.. | .. |
---|
1289 | 1286 | |
---|
1290 | 1287 | static int __init bt_6lowpan_init(void) |
---|
1291 | 1288 | { |
---|
1292 | | - lowpan_enable_debugfs = debugfs_create_file("6lowpan_enable", 0644, |
---|
1293 | | - bt_debugfs, NULL, |
---|
1294 | | - &lowpan_enable_fops); |
---|
| 1289 | + lowpan_enable_debugfs = debugfs_create_file_unsafe("6lowpan_enable", |
---|
| 1290 | + 0644, bt_debugfs, |
---|
| 1291 | + NULL, |
---|
| 1292 | + &lowpan_enable_fops); |
---|
1295 | 1293 | lowpan_control_debugfs = debugfs_create_file("6lowpan_control", 0644, |
---|
1296 | 1294 | bt_debugfs, NULL, |
---|
1297 | 1295 | &lowpan_control_fops); |
---|