/*
* Copyright 2011, Siemens AG
* written by Alexander Smirnov <alex.bluesman.smirnov@gmail.com>
*/
/*
* Based on patches from Jon Smirl <jonsmirl@gmail.com>
* Copyright (c) 2011 Jon Smirl <jonsmirl@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* Jon's code is based on 6lowpan implementation for Contiki which is:
* Copyright (c) 2008, Swedish Institute of Computer Science.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of the Institute nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
#include <linux/bitops.h>
#include <linux/if_arp.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/netdevice.h>
#include <linux/etherdevice.h>
#include <net/af_ieee802154.h>
#include <net/ieee802154.h>
#include <net/ieee802154_netdev.h>
#include <net/ipv6.h>
#include "6lowpan.h"
/* TTL uncompression values */
static const u8 lowpan_ttl_values[] = {0, 1, 64, 255};
static LIST_HEAD(lowpan_devices);
/*
* Uncompression of linklocal:
* 0 -> 16 bytes from packet
* 1 -> 2 bytes from prefix - bunch of zeroes and 8 from packet
* 2 -> 2 bytes from prefix - zeroes + 2 from packet
* 3 -> 2 bytes from prefix - infer 8 bytes from lladdr
*
* NOTE: => the uncompress function does change 0xf to 0x10
* NOTE: 0x00 => no-autoconfig => unspecified
*/
static const u8 lowpan_unc_llconf[] = {0x0f, 0x28, 0x22, 0x20};
/*
* Uncompression of ctx-based:
* 0 -> 0 bits from packet [unspecified / reserved]
* 1 -> 8 bytes from prefix - bunch of zeroes and 8 from packet
* 2 -> 8 bytes from prefix - zeroes + 2 from packet
* 3 -> 8 bytes from prefix - infer 8 bytes from lladdr
*/
static const u8 lowpan_unc_ctxconf[] = {0x00, 0x88, 0x82, 0x80};
/*
* Uncompression of ctx-base
* 0 -> 0 bits from packet
* 1 -> 2 bytes from prefix - bunch of zeroes 5 from packet
* 2 -> 2 bytes from prefix - zeroes + 3 from packet
* 3 -> 2 bytes from prefix - infer 1 bytes from lladdr
*/
static const u8 lowpan_unc_mxconf[] = {0x0f, 0x25, 0x23, 0x21};
/* Link local prefix */
static const u8 lowpan_llprefix[] = {0xfe, 0x80};
/* private device info */
struct lowpan_dev_info {
struct net_device *real_dev; /* real WPAN device ptr */
struct mutex dev_list_mtx; /* mutex for list ops */
};
struct lowpan_dev_record {
struct net_device *ldev;
struct list_head list;
};
struct lowpan_fragment {
struct sk_buff *skb; /* skb to be assembled */
spinlock_t lock; /* concurency lock */
u16 length; /* length to be assemled */
u32 bytes_rcv; /* bytes received */
u16 tag; /* current fragment tag */
struct timer_list timer; /* assembling timer */
struct list_head list; /* fragments list */
};
static unsigned short fragment_tag;
static LIST_HEAD(lowpan_fragments);
spinlock_t flist_lock;
static inline struct
lowpan_dev_info *lowpan_dev_info(const struct net_device *dev)
{
return netdev_priv(dev);
}
static inline void lowpan_address_flip