Commit e6278d92 authored by Phoebe Buckheister's avatar Phoebe Buckheister Committed by David S. Miller

mac802154: use header operations to create/parse headers

Use the operations on 802.15.4 header structs introduced in a previous
patch to create and parse all headers in the mac802154 stack. This patch
reduces code duplication between different parts of the mac802154 stack
that needed information from headers, and also fixes a few bugs that
seem to have gone unnoticed until now:

 * 802.15.4 dgram sockets would return a slightly incorrect value for
   the SIOCINQ ioctl
 * mac802154 would not drop frames with the "security enabled" bit set,
   even though it does not support security, in violation of the
   standard
Signed-off-by: default avatarPhoebe Buckheister <phoebe.buckheister@itwm.fraunhofer.de>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 94b4f6c2
...@@ -216,23 +216,17 @@ static inline struct ieee802154_mac_cb *mac_cb(struct sk_buff *skb) ...@@ -216,23 +216,17 @@ static inline struct ieee802154_mac_cb *mac_cb(struct sk_buff *skb)
#define MAC_CB_FLAG_ACKREQ (1 << 3) #define MAC_CB_FLAG_ACKREQ (1 << 3)
#define MAC_CB_FLAG_SECEN (1 << 4) #define MAC_CB_FLAG_SECEN (1 << 4)
#define MAC_CB_FLAG_INTRAPAN (1 << 5)
static inline int mac_cb_is_ackreq(struct sk_buff *skb) static inline bool mac_cb_is_ackreq(struct sk_buff *skb)
{ {
return mac_cb(skb)->flags & MAC_CB_FLAG_ACKREQ; return mac_cb(skb)->flags & MAC_CB_FLAG_ACKREQ;
} }
static inline int mac_cb_is_secen(struct sk_buff *skb) static inline bool mac_cb_is_secen(struct sk_buff *skb)
{ {
return mac_cb(skb)->flags & MAC_CB_FLAG_SECEN; return mac_cb(skb)->flags & MAC_CB_FLAG_SECEN;
} }
static inline int mac_cb_is_intrapan(struct sk_buff *skb)
{
return mac_cb(skb)->flags & MAC_CB_FLAG_INTRAPAN;
}
static inline int mac_cb_type(struct sk_buff *skb) static inline int mac_cb_type(struct sk_buff *skb)
{ {
return mac_cb(skb)->flags & MAC_CB_FLAG_TYPEMASK; return mac_cb(skb)->flags & MAC_CB_FLAG_TYPEMASK;
......
...@@ -91,7 +91,7 @@ static int lowpan_header_create(struct sk_buff *skb, ...@@ -91,7 +91,7 @@ static int lowpan_header_create(struct sk_buff *skb,
{ {
const u8 *saddr = _saddr; const u8 *saddr = _saddr;
const u8 *daddr = _daddr; const u8 *daddr = _daddr;
struct ieee802154_addr_sa sa, da; struct ieee802154_addr sa, da;
/* TODO: /* TODO:
* if this package isn't ipv6 one, where should it be routed? * if this package isn't ipv6 one, where should it be routed?
...@@ -119,10 +119,10 @@ static int lowpan_header_create(struct sk_buff *skb, ...@@ -119,10 +119,10 @@ static int lowpan_header_create(struct sk_buff *skb,
mac_cb(skb)->seq = ieee802154_mlme_ops(dev)->get_dsn(dev); mac_cb(skb)->seq = ieee802154_mlme_ops(dev)->get_dsn(dev);
/* prepare wpan address data */ /* prepare wpan address data */
sa.addr_type = IEEE802154_ADDR_LONG; sa.mode = IEEE802154_ADDR_LONG;
sa.pan_id = le16_to_cpu(ieee802154_mlme_ops(dev)->get_pan_id(dev)); sa.pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
sa.extended_addr = ieee802154_devaddr_from_raw(saddr);
memcpy(&(sa.hwaddr), saddr, 8);
/* intra-PAN communications */ /* intra-PAN communications */
da.pan_id = sa.pan_id; da.pan_id = sa.pan_id;
...@@ -130,11 +130,11 @@ static int lowpan_header_create(struct sk_buff *skb, ...@@ -130,11 +130,11 @@ static int lowpan_header_create(struct sk_buff *skb,
* corresponding short address * corresponding short address
*/ */
if (lowpan_is_addr_broadcast(daddr)) { if (lowpan_is_addr_broadcast(daddr)) {
da.addr_type = IEEE802154_ADDR_SHORT; da.mode = IEEE802154_ADDR_SHORT;
da.short_addr = IEEE802154_ADDR_BROADCAST; da.short_addr = cpu_to_le16(IEEE802154_ADDR_BROADCAST);
} else { } else {
da.addr_type = IEEE802154_ADDR_LONG; da.mode = IEEE802154_ADDR_LONG;
memcpy(&(da.hwaddr), daddr, IEEE802154_ADDR_LEN); da.extended_addr = ieee802154_devaddr_from_raw(daddr);
/* request acknowledgment */ /* request acknowledgment */
mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ; mac_cb(skb)->flags |= MAC_CB_FLAG_ACKREQ;
......
...@@ -25,12 +25,13 @@ ...@@ -25,12 +25,13 @@
#define AF802154_H #define AF802154_H
struct sk_buff; struct sk_buff;
struct net_devce; struct net_device;
struct ieee802154_addr;
extern struct proto ieee802154_raw_prot; extern struct proto ieee802154_raw_prot;
extern struct proto ieee802154_dgram_prot; extern struct proto ieee802154_dgram_prot;
void ieee802154_raw_deliver(struct net_device *dev, struct sk_buff *skb); void ieee802154_raw_deliver(struct net_device *dev, struct sk_buff *skb);
int ieee802154_dgram_deliver(struct net_device *dev, struct sk_buff *skb); int ieee802154_dgram_deliver(struct net_device *dev, struct sk_buff *skb);
struct net_device *ieee802154_get_dev(struct net *net, struct net_device *ieee802154_get_dev(struct net *net,
struct ieee802154_addr_sa *addr); const struct ieee802154_addr *addr);
#endif #endif
...@@ -43,25 +43,27 @@ ...@@ -43,25 +43,27 @@
/* /*
* Utility function for families * Utility function for families
*/ */
struct net_device *ieee802154_get_dev(struct net *net, struct net_device*
struct ieee802154_addr_sa *addr) ieee802154_get_dev(struct net *net, const struct ieee802154_addr *addr)
{ {
struct net_device *dev = NULL; struct net_device *dev = NULL;
struct net_device *tmp; struct net_device *tmp;
__le16 pan_id, short_addr; __le16 pan_id, short_addr;
u8 hwaddr[IEEE802154_ADDR_LEN];
switch (addr->addr_type) { switch (addr->mode) {
case IEEE802154_ADDR_LONG: case IEEE802154_ADDR_LONG:
ieee802154_devaddr_to_raw(hwaddr, addr->extended_addr);
rcu_read_lock(); rcu_read_lock();
dev = dev_getbyhwaddr_rcu(net, ARPHRD_IEEE802154, addr->hwaddr); dev = dev_getbyhwaddr_rcu(net, ARPHRD_IEEE802154, hwaddr);
if (dev) if (dev)
dev_hold(dev); dev_hold(dev);
rcu_read_unlock(); rcu_read_unlock();
break; break;
case IEEE802154_ADDR_SHORT: case IEEE802154_ADDR_SHORT:
if (addr->pan_id == IEEE802154_PANID_BROADCAST || if (addr->pan_id == cpu_to_le16(IEEE802154_PANID_BROADCAST) ||
addr->short_addr == IEEE802154_ADDR_UNDEF || addr->short_addr == cpu_to_le16(IEEE802154_ADDR_UNDEF) ||
addr->short_addr == IEEE802154_ADDR_UNDEF) addr->short_addr == cpu_to_le16(IEEE802154_ADDR_UNDEF))
break; break;
rtnl_lock(); rtnl_lock();
...@@ -74,8 +76,8 @@ struct net_device *ieee802154_get_dev(struct net *net, ...@@ -74,8 +76,8 @@ struct net_device *ieee802154_get_dev(struct net *net,
short_addr = short_addr =
ieee802154_mlme_ops(tmp)->get_short_addr(tmp); ieee802154_mlme_ops(tmp)->get_short_addr(tmp);
if (le16_to_cpu(pan_id) == addr->pan_id && if (pan_id == addr->pan_id &&
le16_to_cpu(short_addr) == addr->short_addr) { short_addr == addr->short_addr) {
dev = tmp; dev = tmp;
dev_hold(dev); dev_hold(dev);
break; break;
...@@ -86,7 +88,7 @@ struct net_device *ieee802154_get_dev(struct net *net, ...@@ -86,7 +88,7 @@ struct net_device *ieee802154_get_dev(struct net *net,
break; break;
default: default:
pr_warning("Unsupported ieee802154 address type: %d\n", pr_warning("Unsupported ieee802154 address type: %d\n",
addr->addr_type); addr->mode);
break; break;
} }
......
...@@ -41,8 +41,8 @@ static DEFINE_RWLOCK(dgram_lock); ...@@ -41,8 +41,8 @@ static DEFINE_RWLOCK(dgram_lock);
struct dgram_sock { struct dgram_sock {
struct sock sk; struct sock sk;
struct ieee802154_addr_sa src_addr; struct ieee802154_addr src_addr;
struct ieee802154_addr_sa dst_addr; struct ieee802154_addr dst_addr;
unsigned int bound:1; unsigned int bound:1;
unsigned int want_ack:1; unsigned int want_ack:1;
...@@ -73,10 +73,10 @@ static int dgram_init(struct sock *sk) ...@@ -73,10 +73,10 @@ static int dgram_init(struct sock *sk)
{ {
struct dgram_sock *ro = dgram_sk(sk); struct dgram_sock *ro = dgram_sk(sk);
ro->dst_addr.addr_type = IEEE802154_ADDR_LONG; ro->dst_addr.mode = IEEE802154_ADDR_LONG;
ro->dst_addr.pan_id = 0xffff; ro->dst_addr.pan_id = cpu_to_le16(IEEE802154_ADDR_BROADCAST);
ro->want_ack = 1; ro->want_ack = 1;
memset(&ro->dst_addr.hwaddr, 0xff, sizeof(ro->dst_addr.hwaddr)); memset(&ro->dst_addr.extended_addr, 0xff, IEEE802154_ADDR_LEN);
return 0; return 0;
} }
...@@ -88,6 +88,7 @@ static void dgram_close(struct sock *sk, long timeout) ...@@ -88,6 +88,7 @@ static void dgram_close(struct sock *sk, long timeout)
static int dgram_bind(struct sock *sk, struct sockaddr *uaddr, int len) static int dgram_bind(struct sock *sk, struct sockaddr *uaddr, int len)
{ {
struct sockaddr_ieee802154 *addr = (struct sockaddr_ieee802154 *)uaddr; struct sockaddr_ieee802154 *addr = (struct sockaddr_ieee802154 *)uaddr;
struct ieee802154_addr haddr;
struct dgram_sock *ro = dgram_sk(sk); struct dgram_sock *ro = dgram_sk(sk);
int err = -EINVAL; int err = -EINVAL;
struct net_device *dev; struct net_device *dev;
...@@ -102,7 +103,8 @@ static int dgram_bind(struct sock *sk, struct sockaddr *uaddr, int len) ...@@ -102,7 +103,8 @@ static int dgram_bind(struct sock *sk, struct sockaddr *uaddr, int len)
if (addr->family != AF_IEEE802154) if (addr->family != AF_IEEE802154)
goto out; goto out;
dev = ieee802154_get_dev(sock_net(sk), &addr->addr); ieee802154_addr_from_sa(&haddr, &addr->addr);
dev = ieee802154_get_dev(sock_net(sk), &haddr);
if (!dev) { if (!dev) {
err = -ENODEV; err = -ENODEV;
goto out; goto out;
...@@ -113,7 +115,7 @@ static int dgram_bind(struct sock *sk, struct sockaddr *uaddr, int len) ...@@ -113,7 +115,7 @@ static int dgram_bind(struct sock *sk, struct sockaddr *uaddr, int len)
goto out_put; goto out_put;
} }
memcpy(&ro->src_addr, &addr->addr, sizeof(struct ieee802154_addr_sa)); ro->src_addr = haddr;
ro->bound = 1; ro->bound = 1;
err = 0; err = 0;
...@@ -149,8 +151,7 @@ static int dgram_ioctl(struct sock *sk, int cmd, unsigned long arg) ...@@ -149,8 +151,7 @@ static int dgram_ioctl(struct sock *sk, int cmd, unsigned long arg)
* of this packet since that is all * of this packet since that is all
* that will be read. * that will be read.
*/ */
/* FIXME: parse the header for more correct value */ amount = skb->len - ieee802154_hdr_length(skb);
amount = skb->len - (3+8+8);
} }
spin_unlock_bh(&sk->sk_receive_queue.lock); spin_unlock_bh(&sk->sk_receive_queue.lock);
return put_user(amount, (int __user *)arg); return put_user(amount, (int __user *)arg);
...@@ -181,7 +182,7 @@ static int dgram_connect(struct sock *sk, struct sockaddr *uaddr, ...@@ -181,7 +182,7 @@ static int dgram_connect(struct sock *sk, struct sockaddr *uaddr,
goto out; goto out;
} }
memcpy(&ro->dst_addr, &addr->addr, sizeof(struct ieee802154_addr_sa)); ieee802154_addr_from_sa(&ro->dst_addr, &addr->addr);
out: out:
release_sock(sk); release_sock(sk);
...@@ -194,8 +195,8 @@ static int dgram_disconnect(struct sock *sk, int flags) ...@@ -194,8 +195,8 @@ static int dgram_disconnect(struct sock *sk, int flags)
lock_sock(sk); lock_sock(sk);
ro->dst_addr.addr_type = IEEE802154_ADDR_LONG; ro->dst_addr.mode = IEEE802154_ADDR_LONG;
memset(&ro->dst_addr.hwaddr, 0xff, sizeof(ro->dst_addr.hwaddr)); memset(&ro->dst_addr.extended_addr, 0xff, IEEE802154_ADDR_LEN);
release_sock(sk); release_sock(sk);
...@@ -336,40 +337,43 @@ static int dgram_rcv_skb(struct sock *sk, struct sk_buff *skb) ...@@ -336,40 +337,43 @@ static int dgram_rcv_skb(struct sock *sk, struct sk_buff *skb)
return NET_RX_SUCCESS; return NET_RX_SUCCESS;
} }
static inline int ieee802154_match_sock(u8 *hw_addr, u16 pan_id, static inline bool
u16 short_addr, struct dgram_sock *ro) ieee802154_match_sock(__le64 hw_addr, __le16 pan_id, __le16 short_addr,
struct dgram_sock *ro)
{ {
if (!ro->bound) if (!ro->bound)
return 1; return true;
if (ro->src_addr.addr_type == IEEE802154_ADDR_LONG && if (ro->src_addr.mode == IEEE802154_ADDR_LONG &&
!memcmp(ro->src_addr.hwaddr, hw_addr, IEEE802154_ADDR_LEN)) hw_addr == ro->src_addr.extended_addr)
return 1; return true;
if (ro->src_addr.addr_type == IEEE802154_ADDR_SHORT && if (ro->src_addr.mode == IEEE802154_ADDR_SHORT &&
pan_id == ro->src_addr.pan_id && pan_id == ro->src_addr.pan_id &&
short_addr == ro->src_addr.short_addr) short_addr == ro->src_addr.short_addr)
return 1; return true;
return 0; return false;
} }
int ieee802154_dgram_deliver(struct net_device *dev, struct sk_buff *skb) int ieee802154_dgram_deliver(struct net_device *dev, struct sk_buff *skb)
{ {
struct sock *sk, *prev = NULL; struct sock *sk, *prev = NULL;
int ret = NET_RX_SUCCESS; int ret = NET_RX_SUCCESS;
u16 pan_id, short_addr; __le16 pan_id, short_addr;
__le64 hw_addr;
/* Data frame processing */ /* Data frame processing */
BUG_ON(dev->type != ARPHRD_IEEE802154); BUG_ON(dev->type != ARPHRD_IEEE802154);
pan_id = le16_to_cpu(ieee802154_mlme_ops(dev)->get_pan_id(dev)); pan_id = ieee802154_mlme_ops(dev)->get_pan_id(dev);
short_addr = le16_to_cpu(ieee802154_mlme_ops(dev)->get_short_addr(dev)); short_addr = ieee802154_mlme_ops(dev)->get_short_addr(dev);
hw_addr = ieee802154_devaddr_from_raw(dev->dev_addr);
read_lock(&dgram_lock); read_lock(&dgram_lock);
sk_for_each(sk, &dgram_head) { sk_for_each(sk, &dgram_head) {
if (ieee802154_match_sock(dev->dev_addr, pan_id, short_addr, if (ieee802154_match_sock(hw_addr, pan_id, short_addr,
dgram_sk(sk))) { dgram_sk(sk))) {
if (prev) { if (prev) {
struct sk_buff *clone; struct sk_buff *clone;
clone = skb_clone(skb, GFP_ATOMIC); clone = skb_clone(skb, GFP_ATOMIC);
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <linux/slab.h> #include <linux/slab.h>
#include <net/sock.h> #include <net/sock.h>
#include <net/af_ieee802154.h> #include <net/af_ieee802154.h>
#include <net/ieee802154_netdev.h>
#include "af802154.h" #include "af802154.h"
...@@ -55,21 +56,24 @@ static void raw_close(struct sock *sk, long timeout) ...@@ -55,21 +56,24 @@ static void raw_close(struct sock *sk, long timeout)
sk_common_release(sk); sk_common_release(sk);
} }
static int raw_bind(struct sock *sk, struct sockaddr *uaddr, int len) static int raw_bind(struct sock *sk, struct sockaddr *_uaddr, int len)
{ {
struct sockaddr_ieee802154 *addr = (struct sockaddr_ieee802154 *)uaddr; struct ieee802154_addr addr;
struct sockaddr_ieee802154 *uaddr = (struct sockaddr_ieee802154 *)_uaddr;
int err = 0; int err = 0;
struct net_device *dev = NULL; struct net_device *dev = NULL;
if (len < sizeof(*addr)) if (len < sizeof(*uaddr))
return -EINVAL; return -EINVAL;
if (addr->family != AF_IEEE802154) uaddr = (struct sockaddr_ieee802154 *)_uaddr;
if (uaddr->family != AF_IEEE802154)
return -EINVAL; return -EINVAL;
lock_sock(sk); lock_sock(sk);
dev = ieee802154_get_dev(sock_net(sk), &addr->addr); ieee802154_addr_from_sa(&addr, &uaddr->addr);
dev = ieee802154_get_dev(sock_net(sk), &addr);
if (!dev) { if (!dev) {
err = -ENODEV; err = -ENODEV;
goto out; goto out;
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <net/mac802154.h> #include <net/mac802154.h>
#include <net/ieee802154_netdev.h> #include <net/ieee802154_netdev.h>
#include <net/wpan-phy.h> #include <net/wpan-phy.h>
#include <net/ieee802154_netdev.h>
#include "mac802154.h" #include "mac802154.h"
...@@ -115,13 +116,12 @@ void mac802154_dev_set_ieee_addr(struct net_device *dev) ...@@ -115,13 +116,12 @@ void mac802154_dev_set_ieee_addr(struct net_device *dev)
{ {
struct mac802154_sub_if_data *priv = netdev_priv(dev); struct mac802154_sub_if_data *priv = netdev_priv(dev);
struct mac802154_priv *mac = priv->hw; struct mac802154_priv *mac = priv->hw;
__le64 addr;
addr = ieee802154_devaddr_from_raw(dev->dev_addr); priv->extended_addr = ieee802154_devaddr_from_raw(dev->dev_addr);
priv->extended_addr = addr;
if (mac->ops->set_hw_addr_filt && mac->hw.hw_filt.ieee_addr != addr) { if (mac->ops->set_hw_addr_filt &&
mac->hw.hw_filt.ieee_addr = addr; mac->hw.hw_filt.ieee_addr != priv->extended_addr) {
mac->hw.hw_filt.ieee_addr = priv->extended_addr;
set_hw_addr_filt(dev, IEEE802515_AFILT_IEEEADDR_CHANGED); set_hw_addr_filt(dev, IEEE802515_AFILT_IEEEADDR_CHANGED);
} }
} }
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment