aboutsummaryrefslogtreecommitdiffstats
path: root/net/bluetooth
diff options
context:
space:
mode:
Diffstat (limited to 'net/bluetooth')
-rw-r--r--net/bluetooth/6lowpan.c65
1 files changed, 63 insertions, 2 deletions
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index b229aed3bf9a..0920cb6ed572 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -39,6 +39,7 @@ static struct dentry *lowpan_control_debugfs;
39 39
40struct skb_cb { 40struct skb_cb {
41 struct in6_addr addr; 41 struct in6_addr addr;
42 struct in6_addr gw;
42 struct l2cap_chan *chan; 43 struct l2cap_chan *chan;
43 int status; 44 int status;
44}; 45};
@@ -158,6 +159,54 @@ static inline struct lowpan_peer *peer_lookup_conn(struct lowpan_dev *dev,
158 return NULL; 159 return NULL;
159} 160}
160 161
162static inline struct lowpan_peer *peer_lookup_dst(struct lowpan_dev *dev,
163 struct in6_addr *daddr,
164 struct sk_buff *skb)
165{
166 struct lowpan_peer *peer, *tmp;
167 struct in6_addr *nexthop;
168 struct rt6_info *rt = (struct rt6_info *)skb_dst(skb);
169 int count = atomic_read(&dev->peer_count);
170
171 BT_DBG("peers %d addr %pI6c rt %p", count, daddr, rt);
172
173 /* If we have multiple 6lowpan peers, then check where we should
174 * send the packet. If only one peer exists, then we can send the
175 * packet right away.
176 */
177 if (count == 1)
178 return list_first_entry(&dev->peers, struct lowpan_peer,
179 list);
180
181 if (!rt) {
182 nexthop = &lowpan_cb(skb)->gw;
183
184 if (ipv6_addr_any(nexthop))
185 return NULL;
186 } else {
187 nexthop = rt6_nexthop(rt);
188
189 /* We need to remember the address because it is needed
190 * by bt_xmit() when sending the packet. In bt_xmit(), the
191 * destination routing info is not set.
192 */
193 memcpy(&lowpan_cb(skb)->gw, nexthop, sizeof(struct in6_addr));
194 }
195
196 BT_DBG("gw %pI6c", nexthop);
197
198 list_for_each_entry_safe(peer, tmp, &dev->peers, list) {
199 BT_DBG("dst addr %pMR dst type %d ip %pI6c",
200 &peer->chan->dst, peer->chan->dst_type,
201 &peer->peer_addr);
202
203 if (!ipv6_addr_cmp(&peer->peer_addr, nexthop))
204 return peer;
205 }
206
207 return NULL;
208}
209
161static struct lowpan_peer *lookup_peer(struct l2cap_conn *conn) 210static struct lowpan_peer *lookup_peer(struct l2cap_conn *conn)
162{ 211{
163 struct lowpan_dev *entry, *tmp; 212 struct lowpan_dev *entry, *tmp;
@@ -415,8 +464,18 @@ static int header_create(struct sk_buff *skb, struct net_device *netdev,
415 read_unlock_irqrestore(&devices_lock, flags); 464 read_unlock_irqrestore(&devices_lock, flags);
416 465
417 if (!peer) { 466 if (!peer) {
418 BT_DBG("no such peer %pMR found", &addr); 467 /* The packet might be sent to 6lowpan interface
419 return -ENOENT; 468 * because of routing (either via default route
469 * or user set route) so get peer according to
470 * the destination address.
471 */
472 read_lock_irqsave(&devices_lock, flags);
473 peer = peer_lookup_dst(dev, &hdr->daddr, skb);
474 read_unlock_irqrestore(&devices_lock, flags);
475 if (!peer) {
476 BT_DBG("no such peer %pMR found", &addr);
477 return -ENOENT;
478 }
420 } 479 }
421 480
422 daddr = peer->eui64_addr; 481 daddr = peer->eui64_addr;
@@ -520,6 +579,8 @@ static netdev_tx_t bt_xmit(struct sk_buff *skb, struct net_device *netdev)
520 579
521 read_lock_irqsave(&devices_lock, flags); 580 read_lock_irqsave(&devices_lock, flags);
522 peer = peer_lookup_ba(dev, &addr, addr_type); 581 peer = peer_lookup_ba(dev, &addr, addr_type);
582 if (!peer)
583 peer = peer_lookup_dst(dev, &lowpan_cb(skb)->addr, skb);
523 read_unlock_irqrestore(&devices_lock, flags); 584 read_unlock_irqrestore(&devices_lock, flags);
524 585
525 BT_DBG("xmit %s to %pMR type %d IP %pI6c peer %p", 586 BT_DBG("xmit %s to %pMR type %d IP %pI6c peer %p",