/*
* WiMedia Logical Link Control Protocol (WLP)
*
* Copyright (C) 2007 Intel Corporation
* Reinette Chatre <reinette.chatre@intel.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.
*
*
* Implementation of the WLP association protocol.
*
* FIXME: Docs
*
* A UWB network interface will configure a WSS through wlp_wss_setup() after
* the interface has been assigned a MAC address, typically after
* "ifconfig" has been called. When the interface goes down it should call
* wlp_wss_remove().
*
* When the WSS is ready for use the user interacts via sysfs to create,
* discover, and activate WSS.
*
* wlp_wss_enroll_activate()
*
* wlp_wss_create_activate()
* wlp_wss_set_wssid_hash()
* wlp_wss_comp_wssid_hash()
* wlp_wss_sel_bcast_addr()
* wlp_wss_sysfs_add()
*
* Called when no more references to WSS exist:
* wlp_wss_release()
* wlp_wss_reset()
*/
#include <linux/etherdevice.h> /* for is_valid_ether_addr */
#include <linux/skbuff.h>
#include <linux/wlp.h>
#define D_LOCAL 5
#include <linux/uwb/debug.h>
#include "wlp-internal.h"
size_t wlp_wss_key_print(char *buf, size_t bufsize, u8 *key)
{
size_t result;
result = scnprintf(buf, bufsize,
"%02x %02x %02x %02x %02x %02x "
"%02x %02x %02x %02x %02x %02x "
"%02x %02x %02x %02x",
key[0], key[1], key[2], key[3],
key[4], key[5], key[6], key[7],
key[8], key[9], key[10], key[11],
key[12], key[13], key[14], key[15]);
return result;
}
/**
* Compute WSSID hash
* WLP Draft 0.99 [7.2.1]
*
* The WSSID hash for a WSSID is the result of an octet-wise exclusive-OR
* of all octets in the WSSID.
*/
static
u8 wlp_wss_comp_wssid_hash(struct wlp_uuid *wssid)
{
return wssid->data[0] ^ wssid->data[1] ^ wssid->data[2]
^ wssid->data[3] ^ wssid->data[4] ^ wssid->data[5]
^ wssid->data[6] ^ wssid->data[7] ^ wssid->data[8]
^ wssid->data[9] ^ wssid->data[10] ^ wssid->data[11]
^ wssid->data[12] ^ wssid->data[13] ^ wssid->data[14]
^ wssid->data[15];
}
/**
* Select a multicast EUI-48 for the WSS broadcast address.
* WLP Draft 0.99 [7.2.1]
*
* Selected based on the WiMedia Alliance OUI, 00-13-88, within the WLP
* range, [01-13-88-00-01-00, 01-13-88-00-01-FF] inclusive.
*
* This address is currently hardcoded.
* FIXME?
*/
static
struct uwb_mac_addr wlp_wss_sel_bcast_addr(struct wlp_wss *wss)
{
struct uwb_mac_addr bcast = {
.data = { 0x01, 0x13, 0x88, 0x00, 0x01, 0x00 }
};
return bcast;
}
/**
* Clear the contents of the WSS structure - all except kobj, mutex, virtual
*
* We do not want to reinitialize - the internal kobj should not change as
* it still points to the parent received during setup. The mutex should
* remain also. We thus just reset values individually.
* The virutal address assigned to WSS will remain the same for the
* lifetime of the WSS. We only reset the fields that can change during its
* lifetime.
*/
void wlp_wss_reset(struct wlp_wss *wss)
{
struct wlp *wlp = container_of(wss, struct wlp, wss);
struct device *dev = &wlp->rc->uwb_dev.dev;
d_fnstart(5, dev, "wss (%p) \n", wss);
memset(&wss->wssid, 0, sizeof(wss->wssid));
wss->hash = 0;
memset(&wss->name[0], 0, sizeof(wss->name));
memset(&wss->bcast, 0, sizeof(wss->bcast));
wss->secure_status = WLP_WSS_UNSECURE;
memset(&wss->master_key[0], 0, sizeof(wss->master_key));
wss->tag = 0;
wss->state = WLP_WSS_STATE_NONE;
d_fnend(5, dev, "wss (%p) \n", wss);
}
/**
* Create sysfs infrastructure for WSS
*
* The WSS is configured to have the interface as parent (see wlp_wss_setup())
* a new sysfs directory that includes wssid as its name is created in the
* interface's sysfs directory. The group of files interacting with WSS are
* created also.
*/
static
int wlp_wss_sysfs_add(struct wlp_wss *wss, char *wssid_str)
{
struct wlp *wlp = container_of(wss, struct wlp, wss);
struct device *dev = &wlp->rc->uwb_dev.dev