This source file includes following definitions.
- lowpan_open
- lowpan_stop
- lowpan_neigh_construct
- lowpan_get_iflink
- lowpan_setup
- lowpan_validate
- lowpan_newlink
- lowpan_dellink
- lowpan_netlink_init
- lowpan_netlink_fini
- lowpan_device_event
- lowpan_init_module
- lowpan_cleanup_module
   1 
   2 
   3 
   4 
   5 
   6 
   7 
   8 
   9 
  10 
  11 
  12 
  13 
  14 
  15 
  16 
  17 
  18 
  19 
  20 
  21 
  22 
  23 
  24 
  25 
  26 
  27 
  28 
  29 
  30 
  31 
  32 
  33 
  34 
  35 
  36 
  37 
  38 
  39 
  40 
  41 
  42 
  43 
  44 
  45 
  46 
  47 #include <linux/module.h>
  48 #include <linux/netdevice.h>
  49 #include <linux/ieee802154.h>
  50 
  51 #include <net/ipv6.h>
  52 
  53 #include "6lowpan_i.h"
  54 
  55 static int open_count;
  56 
  57 static const struct header_ops lowpan_header_ops = {
  58         .create = lowpan_header_create,
  59 };
  60 
  61 static int lowpan_open(struct net_device *dev)
  62 {
  63         if (!open_count)
  64                 lowpan_rx_init();
  65         open_count++;
  66         return 0;
  67 }
  68 
  69 static int lowpan_stop(struct net_device *dev)
  70 {
  71         open_count--;
  72         if (!open_count)
  73                 lowpan_rx_exit();
  74         return 0;
  75 }
  76 
  77 static int lowpan_neigh_construct(struct net_device *dev, struct neighbour *n)
  78 {
  79         struct lowpan_802154_neigh *neigh = lowpan_802154_neigh(neighbour_priv(n));
  80 
  81         
  82         neigh->short_addr = cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC);
  83         return 0;
  84 }
  85 
  86 static int lowpan_get_iflink(const struct net_device *dev)
  87 {
  88         return lowpan_802154_dev(dev)->wdev->ifindex;
  89 }
  90 
  91 static const struct net_device_ops lowpan_netdev_ops = {
  92         .ndo_start_xmit         = lowpan_xmit,
  93         .ndo_open               = lowpan_open,
  94         .ndo_stop               = lowpan_stop,
  95         .ndo_neigh_construct    = lowpan_neigh_construct,
  96         .ndo_get_iflink         = lowpan_get_iflink,
  97 };
  98 
  99 static void lowpan_setup(struct net_device *ldev)
 100 {
 101         memset(ldev->broadcast, 0xff, IEEE802154_ADDR_LEN);
 102         
 103         ldev->hard_header_len   = sizeof(struct ipv6hdr);
 104         ldev->flags             = IFF_BROADCAST | IFF_MULTICAST;
 105         ldev->priv_flags        |= IFF_NO_QUEUE;
 106 
 107         ldev->netdev_ops        = &lowpan_netdev_ops;
 108         ldev->header_ops        = &lowpan_header_ops;
 109         ldev->needs_free_netdev = true;
 110         ldev->features          |= NETIF_F_NETNS_LOCAL;
 111 }
 112 
 113 static int lowpan_validate(struct nlattr *tb[], struct nlattr *data[],
 114                            struct netlink_ext_ack *extack)
 115 {
 116         if (tb[IFLA_ADDRESS]) {
 117                 if (nla_len(tb[IFLA_ADDRESS]) != IEEE802154_ADDR_LEN)
 118                         return -EINVAL;
 119         }
 120         return 0;
 121 }
 122 
 123 static int lowpan_newlink(struct net *src_net, struct net_device *ldev,
 124                           struct nlattr *tb[], struct nlattr *data[],
 125                           struct netlink_ext_ack *extack)
 126 {
 127         struct net_device *wdev;
 128         int ret;
 129 
 130         ASSERT_RTNL();
 131 
 132         pr_debug("adding new link\n");
 133 
 134         if (!tb[IFLA_LINK])
 135                 return -EINVAL;
 136         
 137         wdev = dev_get_by_index(dev_net(ldev), nla_get_u32(tb[IFLA_LINK]));
 138         if (!wdev)
 139                 return -ENODEV;
 140         if (wdev->type != ARPHRD_IEEE802154) {
 141                 dev_put(wdev);
 142                 return -EINVAL;
 143         }
 144 
 145         if (wdev->ieee802154_ptr->lowpan_dev) {
 146                 dev_put(wdev);
 147                 return -EBUSY;
 148         }
 149 
 150         lowpan_802154_dev(ldev)->wdev = wdev;
 151         
 152         memcpy(ldev->dev_addr, wdev->dev_addr, IEEE802154_ADDR_LEN);
 153         
 154 
 155 
 156 
 157 
 158 
 159         ldev->needed_headroom = LOWPAN_IPHC_MAX_HEADER_LEN +
 160                                 wdev->needed_headroom;
 161         ldev->needed_tailroom = wdev->needed_tailroom;
 162 
 163         ldev->neigh_priv_len = sizeof(struct lowpan_802154_neigh);
 164 
 165         ret = lowpan_register_netdevice(ldev, LOWPAN_LLTYPE_IEEE802154);
 166         if (ret < 0) {
 167                 dev_put(wdev);
 168                 return ret;
 169         }
 170 
 171         wdev->ieee802154_ptr->lowpan_dev = ldev;
 172         return 0;
 173 }
 174 
 175 static void lowpan_dellink(struct net_device *ldev, struct list_head *head)
 176 {
 177         struct net_device *wdev = lowpan_802154_dev(ldev)->wdev;
 178 
 179         ASSERT_RTNL();
 180 
 181         wdev->ieee802154_ptr->lowpan_dev = NULL;
 182         lowpan_unregister_netdevice(ldev);
 183         dev_put(wdev);
 184 }
 185 
 186 static struct rtnl_link_ops lowpan_link_ops __read_mostly = {
 187         .kind           = "lowpan",
 188         .priv_size      = LOWPAN_PRIV_SIZE(sizeof(struct lowpan_802154_dev)),
 189         .setup          = lowpan_setup,
 190         .newlink        = lowpan_newlink,
 191         .dellink        = lowpan_dellink,
 192         .validate       = lowpan_validate,
 193 };
 194 
 195 static inline int __init lowpan_netlink_init(void)
 196 {
 197         return rtnl_link_register(&lowpan_link_ops);
 198 }
 199 
 200 static inline void lowpan_netlink_fini(void)
 201 {
 202         rtnl_link_unregister(&lowpan_link_ops);
 203 }
 204 
 205 static int lowpan_device_event(struct notifier_block *unused,
 206                                unsigned long event, void *ptr)
 207 {
 208         struct net_device *ndev = netdev_notifier_info_to_dev(ptr);
 209         struct wpan_dev *wpan_dev;
 210 
 211         if (ndev->type != ARPHRD_IEEE802154)
 212                 return NOTIFY_DONE;
 213         wpan_dev = ndev->ieee802154_ptr;
 214         if (!wpan_dev)
 215                 return NOTIFY_DONE;
 216 
 217         switch (event) {
 218         case NETDEV_UNREGISTER:
 219                 
 220 
 221 
 222 
 223                 if (wpan_dev->lowpan_dev)
 224                         lowpan_dellink(wpan_dev->lowpan_dev, NULL);
 225                 break;
 226         default:
 227                 return NOTIFY_DONE;
 228         }
 229 
 230         return NOTIFY_OK;
 231 }
 232 
 233 static struct notifier_block lowpan_dev_notifier = {
 234         .notifier_call = lowpan_device_event,
 235 };
 236 
 237 static int __init lowpan_init_module(void)
 238 {
 239         int err = 0;
 240 
 241         err = lowpan_net_frag_init();
 242         if (err < 0)
 243                 goto out;
 244 
 245         err = lowpan_netlink_init();
 246         if (err < 0)
 247                 goto out_frag;
 248 
 249         err = register_netdevice_notifier(&lowpan_dev_notifier);
 250         if (err < 0)
 251                 goto out_pack;
 252 
 253         return 0;
 254 
 255 out_pack:
 256         lowpan_netlink_fini();
 257 out_frag:
 258         lowpan_net_frag_exit();
 259 out:
 260         return err;
 261 }
 262 
 263 static void __exit lowpan_cleanup_module(void)
 264 {
 265         lowpan_netlink_fini();
 266 
 267         lowpan_net_frag_exit();
 268 
 269         unregister_netdevice_notifier(&lowpan_dev_notifier);
 270 }
 271 
 272 module_init(lowpan_init_module);
 273 module_exit(lowpan_cleanup_module);
 274 MODULE_LICENSE("GPL");
 275 MODULE_ALIAS_RTNL_LINK("lowpan");