cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

core.c (7796B)


      1/* Copyright 2011, Siemens AG
      2 * written by Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
      3 */
      4
      5/* Based on patches from Jon Smirl <jonsmirl@gmail.com>
      6 * Copyright (c) 2011 Jon Smirl <jonsmirl@gmail.com>
      7 *
      8 * This program is free software; you can redistribute it and/or modify
      9 * it under the terms of the GNU General Public License version 2
     10 * as published by the Free Software Foundation.
     11 *
     12 * This program is distributed in the hope that it will be useful,
     13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15 * GNU General Public License for more details.
     16 */
     17
     18/* Jon's code is based on 6lowpan implementation for Contiki which is:
     19 * Copyright (c) 2008, Swedish Institute of Computer Science.
     20 * All rights reserved.
     21 *
     22 * Redistribution and use in source and binary forms, with or without
     23 * modification, are permitted provided that the following conditions
     24 * are met:
     25 * 1. Redistributions of source code must retain the above copyright
     26 *    notice, this list of conditions and the following disclaimer.
     27 * 2. Redistributions in binary form must reproduce the above copyright
     28 *    notice, this list of conditions and the following disclaimer in the
     29 *    documentation and/or other materials provided with the distribution.
     30 * 3. Neither the name of the Institute nor the names of its contributors
     31 *    may be used to endorse or promote products derived from this software
     32 *    without specific prior written permission.
     33 *
     34 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
     35 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     36 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     37 * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
     38 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     39 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     40 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     41 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     42 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     43 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     44 * SUCH DAMAGE.
     45 */
     46
     47#include <linux/module.h>
     48#include <linux/netdevice.h>
     49#include <linux/ieee802154.h>
     50#include <linux/if_arp.h>
     51
     52#include <net/ipv6.h>
     53
     54#include "6lowpan_i.h"
     55
     56static int open_count;
     57
     58static const struct header_ops lowpan_header_ops = {
     59	.create	= lowpan_header_create,
     60};
     61
     62static int lowpan_dev_init(struct net_device *ldev)
     63{
     64	netdev_lockdep_set_classes(ldev);
     65
     66	return 0;
     67}
     68
     69static int lowpan_open(struct net_device *dev)
     70{
     71	if (!open_count)
     72		lowpan_rx_init();
     73	open_count++;
     74	return 0;
     75}
     76
     77static int lowpan_stop(struct net_device *dev)
     78{
     79	open_count--;
     80	if (!open_count)
     81		lowpan_rx_exit();
     82	return 0;
     83}
     84
     85static int lowpan_neigh_construct(struct net_device *dev, struct neighbour *n)
     86{
     87	struct lowpan_802154_neigh *neigh = lowpan_802154_neigh(neighbour_priv(n));
     88
     89	/* default no short_addr is available for a neighbour */
     90	neigh->short_addr = cpu_to_le16(IEEE802154_ADDR_SHORT_UNSPEC);
     91	return 0;
     92}
     93
     94static int lowpan_get_iflink(const struct net_device *dev)
     95{
     96	return lowpan_802154_dev(dev)->wdev->ifindex;
     97}
     98
     99static const struct net_device_ops lowpan_netdev_ops = {
    100	.ndo_init		= lowpan_dev_init,
    101	.ndo_start_xmit		= lowpan_xmit,
    102	.ndo_open		= lowpan_open,
    103	.ndo_stop		= lowpan_stop,
    104	.ndo_neigh_construct    = lowpan_neigh_construct,
    105	.ndo_get_iflink         = lowpan_get_iflink,
    106};
    107
    108static void lowpan_setup(struct net_device *ldev)
    109{
    110	memset(ldev->broadcast, 0xff, IEEE802154_ADDR_LEN);
    111	/* We need an ipv6hdr as minimum len when calling xmit */
    112	ldev->hard_header_len	= sizeof(struct ipv6hdr);
    113	ldev->flags		= IFF_BROADCAST | IFF_MULTICAST;
    114	ldev->priv_flags	|= IFF_NO_QUEUE;
    115
    116	ldev->netdev_ops	= &lowpan_netdev_ops;
    117	ldev->header_ops	= &lowpan_header_ops;
    118	ldev->needs_free_netdev	= true;
    119	ldev->features		|= NETIF_F_NETNS_LOCAL;
    120}
    121
    122static int lowpan_validate(struct nlattr *tb[], struct nlattr *data[],
    123			   struct netlink_ext_ack *extack)
    124{
    125	if (tb[IFLA_ADDRESS]) {
    126		if (nla_len(tb[IFLA_ADDRESS]) != IEEE802154_ADDR_LEN)
    127			return -EINVAL;
    128	}
    129	return 0;
    130}
    131
    132static int lowpan_newlink(struct net *src_net, struct net_device *ldev,
    133			  struct nlattr *tb[], struct nlattr *data[],
    134			  struct netlink_ext_ack *extack)
    135{
    136	struct net_device *wdev;
    137	int ret;
    138
    139	ASSERT_RTNL();
    140
    141	pr_debug("adding new link\n");
    142
    143	if (!tb[IFLA_LINK])
    144		return -EINVAL;
    145	/* find and hold wpan device */
    146	wdev = dev_get_by_index(dev_net(ldev), nla_get_u32(tb[IFLA_LINK]));
    147	if (!wdev)
    148		return -ENODEV;
    149	if (wdev->type != ARPHRD_IEEE802154) {
    150		dev_put(wdev);
    151		return -EINVAL;
    152	}
    153
    154	if (wdev->ieee802154_ptr->lowpan_dev) {
    155		dev_put(wdev);
    156		return -EBUSY;
    157	}
    158
    159	lowpan_802154_dev(ldev)->wdev = wdev;
    160	/* Set the lowpan hardware address to the wpan hardware address. */
    161	__dev_addr_set(ldev, wdev->dev_addr, IEEE802154_ADDR_LEN);
    162	/* We need headroom for possible wpan_dev_hard_header call and tailroom
    163	 * for encryption/fcs handling. The lowpan interface will replace
    164	 * the IPv6 header with 6LoWPAN header. At worst case the 6LoWPAN
    165	 * header has LOWPAN_IPHC_MAX_HEADER_LEN more bytes than the IPv6
    166	 * header.
    167	 */
    168	ldev->needed_headroom = LOWPAN_IPHC_MAX_HEADER_LEN +
    169				wdev->needed_headroom;
    170	ldev->needed_tailroom = wdev->needed_tailroom;
    171
    172	ldev->neigh_priv_len = sizeof(struct lowpan_802154_neigh);
    173
    174	ret = lowpan_register_netdevice(ldev, LOWPAN_LLTYPE_IEEE802154);
    175	if (ret < 0) {
    176		dev_put(wdev);
    177		return ret;
    178	}
    179
    180	wdev->ieee802154_ptr->lowpan_dev = ldev;
    181	return 0;
    182}
    183
    184static void lowpan_dellink(struct net_device *ldev, struct list_head *head)
    185{
    186	struct net_device *wdev = lowpan_802154_dev(ldev)->wdev;
    187
    188	ASSERT_RTNL();
    189
    190	wdev->ieee802154_ptr->lowpan_dev = NULL;
    191	lowpan_unregister_netdevice(ldev);
    192	dev_put(wdev);
    193}
    194
    195static struct rtnl_link_ops lowpan_link_ops __read_mostly = {
    196	.kind		= "lowpan",
    197	.priv_size	= LOWPAN_PRIV_SIZE(sizeof(struct lowpan_802154_dev)),
    198	.setup		= lowpan_setup,
    199	.newlink	= lowpan_newlink,
    200	.dellink	= lowpan_dellink,
    201	.validate	= lowpan_validate,
    202};
    203
    204static inline int __init lowpan_netlink_init(void)
    205{
    206	return rtnl_link_register(&lowpan_link_ops);
    207}
    208
    209static inline void lowpan_netlink_fini(void)
    210{
    211	rtnl_link_unregister(&lowpan_link_ops);
    212}
    213
    214static int lowpan_device_event(struct notifier_block *unused,
    215			       unsigned long event, void *ptr)
    216{
    217	struct net_device *ndev = netdev_notifier_info_to_dev(ptr);
    218	struct wpan_dev *wpan_dev;
    219
    220	if (ndev->type != ARPHRD_IEEE802154)
    221		return NOTIFY_DONE;
    222	wpan_dev = ndev->ieee802154_ptr;
    223	if (!wpan_dev)
    224		return NOTIFY_DONE;
    225
    226	switch (event) {
    227	case NETDEV_UNREGISTER:
    228		/* Check if wpan interface is unregistered that we
    229		 * also delete possible lowpan interfaces which belongs
    230		 * to the wpan interface.
    231		 */
    232		if (wpan_dev->lowpan_dev)
    233			lowpan_dellink(wpan_dev->lowpan_dev, NULL);
    234		break;
    235	default:
    236		return NOTIFY_DONE;
    237	}
    238
    239	return NOTIFY_OK;
    240}
    241
    242static struct notifier_block lowpan_dev_notifier = {
    243	.notifier_call = lowpan_device_event,
    244};
    245
    246static int __init lowpan_init_module(void)
    247{
    248	int err = 0;
    249
    250	err = lowpan_net_frag_init();
    251	if (err < 0)
    252		goto out;
    253
    254	err = lowpan_netlink_init();
    255	if (err < 0)
    256		goto out_frag;
    257
    258	err = register_netdevice_notifier(&lowpan_dev_notifier);
    259	if (err < 0)
    260		goto out_pack;
    261
    262	return 0;
    263
    264out_pack:
    265	lowpan_netlink_fini();
    266out_frag:
    267	lowpan_net_frag_exit();
    268out:
    269	return err;
    270}
    271
    272static void __exit lowpan_cleanup_module(void)
    273{
    274	lowpan_netlink_fini();
    275
    276	lowpan_net_frag_exit();
    277
    278	unregister_netdevice_notifier(&lowpan_dev_notifier);
    279}
    280
    281module_init(lowpan_init_module);
    282module_exit(lowpan_cleanup_module);
    283MODULE_LICENSE("GPL");
    284MODULE_ALIAS_RTNL_LINK("lowpan");