• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/linux/linux-2.6/drivers/uwb/wlp/
1
2
3#include <linux/wlp.h>
4#include <linux/slab.h>
5
6#include "wlp-internal.h"
7
8static
9const char *__wlp_assoc_frame[] = {
10	[WLP_ASSOC_D1] = "WLP_ASSOC_D1",
11	[WLP_ASSOC_D2] = "WLP_ASSOC_D2",
12	[WLP_ASSOC_M1] = "WLP_ASSOC_M1",
13	[WLP_ASSOC_M2] = "WLP_ASSOC_M2",
14	[WLP_ASSOC_M3] = "WLP_ASSOC_M3",
15	[WLP_ASSOC_M4] = "WLP_ASSOC_M4",
16	[WLP_ASSOC_M5] = "WLP_ASSOC_M5",
17	[WLP_ASSOC_M6] = "WLP_ASSOC_M6",
18	[WLP_ASSOC_M7] = "WLP_ASSOC_M7",
19	[WLP_ASSOC_M8] = "WLP_ASSOC_M8",
20	[WLP_ASSOC_F0] = "WLP_ASSOC_F0",
21	[WLP_ASSOC_E1] = "WLP_ASSOC_E1",
22	[WLP_ASSOC_E2] = "WLP_ASSOC_E2",
23	[WLP_ASSOC_C1] = "WLP_ASSOC_C1",
24	[WLP_ASSOC_C2] = "WLP_ASSOC_C2",
25	[WLP_ASSOC_C3] = "WLP_ASSOC_C3",
26	[WLP_ASSOC_C4] = "WLP_ASSOC_C4",
27};
28
29static const char *wlp_assoc_frame_str(unsigned id)
30{
31	if (id >= ARRAY_SIZE(__wlp_assoc_frame))
32		return "unknown association frame";
33	return __wlp_assoc_frame[id];
34}
35
36static const char *__wlp_assc_error[] = {
37	"none",
38	"Authenticator Failure",
39	"Rogue activity suspected",
40	"Device busy",
41	"Setup Locked",
42	"Registrar not ready",
43	"Invalid WSS selection",
44	"Message timeout",
45	"Enrollment session timeout",
46	"Device password invalid",
47	"Unsupported version",
48	"Internal error",
49	"Undefined error",
50	"Numeric comparison failure",
51	"Waiting for user input",
52};
53
54static const char *wlp_assc_error_str(unsigned id)
55{
56	if (id >= ARRAY_SIZE(__wlp_assc_error))
57		return "unknown WLP association error";
58	return __wlp_assc_error[id];
59}
60
61static inline void wlp_set_attr_hdr(struct wlp_attr_hdr *hdr, unsigned type,
62				    size_t len)
63{
64	hdr->type = cpu_to_le16(type);
65	hdr->length = cpu_to_le16(len);
66}
67
68/*
69 * Populate fields of a constant sized attribute
70 *
71 * @returns: total size of attribute including size of new value
72 *
73 * We have two instances of this function (wlp_pset and wlp_set): one takes
74 * the value as a parameter, the other takes a pointer to the value as
75 * parameter. They thus only differ in how the value is assigned to the
76 * attribute.
77 *
78 * We use sizeof(*attr) - sizeof(struct wlp_attr_hdr) instead of
79 * sizeof(type) to be able to use this same code for the structures that
80 * contain 8bit enum values and be able to deal with pointer types.
81 */
82#define wlp_set(type, type_code, name)					\
83static size_t wlp_set_##name(struct wlp_attr_##name *attr, type value)	\
84{									\
85	wlp_set_attr_hdr(&attr->hdr, type_code,				\
86			 sizeof(*attr) - sizeof(struct wlp_attr_hdr));	\
87	attr->name = value;						\
88	return sizeof(*attr);						\
89}
90
91#define wlp_pset(type, type_code, name)					\
92static size_t wlp_set_##name(struct wlp_attr_##name *attr, type value)	\
93{									\
94	wlp_set_attr_hdr(&attr->hdr, type_code,				\
95			 sizeof(*attr) - sizeof(struct wlp_attr_hdr));	\
96	attr->name = *value;						\
97	return sizeof(*attr);						\
98}
99
100/**
101 * Populate fields of a variable attribute
102 *
103 * @returns: total size of attribute including size of new value
104 *
105 * Provided with a pointer to the memory area reserved for the
106 * attribute structure, the field is populated with the value. The
107 * reserved memory has to contain enough space for the value.
108 */
109#define wlp_vset(type, type_code, name)					\
110static size_t wlp_set_##name(struct wlp_attr_##name *attr, type value,	\
111				size_t len)				\
112{									\
113	wlp_set_attr_hdr(&attr->hdr, type_code, len);			\
114	memcpy(attr->name, value, len);					\
115	return sizeof(*attr) + len;					\
116}
117
118wlp_vset(char *, WLP_ATTR_DEV_NAME, dev_name)
119wlp_vset(char *, WLP_ATTR_MANUF, manufacturer)
120wlp_set(enum wlp_assoc_type, WLP_ATTR_MSG_TYPE, msg_type)
121wlp_vset(char *, WLP_ATTR_MODEL_NAME, model_name)
122wlp_vset(char *, WLP_ATTR_MODEL_NR, model_nr)
123wlp_vset(char *, WLP_ATTR_SERIAL, serial)
124wlp_vset(char *, WLP_ATTR_WSS_NAME, wss_name)
125wlp_pset(struct wlp_uuid *, WLP_ATTR_UUID_E, uuid_e)
126wlp_pset(struct wlp_uuid *, WLP_ATTR_UUID_R, uuid_r)
127wlp_pset(struct wlp_uuid *, WLP_ATTR_WSSID, wssid)
128wlp_pset(struct wlp_dev_type *, WLP_ATTR_PRI_DEV_TYPE, prim_dev_type)
129/*wlp_pset(struct wlp_dev_type *, WLP_ATTR_SEC_DEV_TYPE, sec_dev_type)*/
130wlp_set(u8, WLP_ATTR_WLP_VER, version)
131wlp_set(enum wlp_assc_error, WLP_ATTR_WLP_ASSC_ERR, wlp_assc_err)
132wlp_set(enum wlp_wss_sel_mthd, WLP_ATTR_WSS_SEL_MTHD, wss_sel_mthd)
133wlp_set(u8, WLP_ATTR_ACC_ENRL, accept_enrl)
134wlp_set(u8, WLP_ATTR_WSS_SEC_STAT, wss_sec_status)
135wlp_pset(struct uwb_mac_addr *, WLP_ATTR_WSS_BCAST, wss_bcast)
136wlp_pset(struct wlp_nonce *, WLP_ATTR_ENRL_NONCE, enonce)
137wlp_pset(struct wlp_nonce *, WLP_ATTR_REG_NONCE, rnonce)
138wlp_set(u8, WLP_ATTR_WSS_TAG, wss_tag)
139wlp_pset(struct uwb_mac_addr *, WLP_ATTR_WSS_VIRT, wss_virt)
140
141/**
142 * Fill in the WSS information attributes
143 *
144 * We currently only support one WSS, and this is assumed in this function
145 * that can populate only one WSS information attribute.
146 */
147static size_t wlp_set_wss_info(struct wlp_attr_wss_info *attr,
148			       struct wlp_wss *wss)
149{
150	size_t datalen;
151	void *ptr = attr->wss_info;
152	size_t used = sizeof(*attr);
153
154	datalen = sizeof(struct wlp_wss_info) + strlen(wss->name);
155	wlp_set_attr_hdr(&attr->hdr, WLP_ATTR_WSS_INFO, datalen);
156	used = wlp_set_wssid(ptr, &wss->wssid);
157	used += wlp_set_wss_name(ptr + used, wss->name, strlen(wss->name));
158	used += wlp_set_accept_enrl(ptr + used, wss->accept_enroll);
159	used += wlp_set_wss_sec_status(ptr + used, wss->secure_status);
160	used += wlp_set_wss_bcast(ptr + used, &wss->bcast);
161	return sizeof(*attr) + used;
162}
163
164/**
165 * Verify attribute header
166 *
167 * @hdr:     Pointer to attribute header that will be verified.
168 * @type:    Expected attribute type.
169 * @len:     Expected length of attribute value (excluding header).
170 *
171 * Most attribute values have a known length even when they do have a
172 * length field. This knowledge can be used via this function to verify
173 * that the length field matches the expected value.
174 */
175static int wlp_check_attr_hdr(struct wlp *wlp, struct wlp_attr_hdr *hdr,
176		       enum wlp_attr_type type, unsigned len)
177{
178	struct device *dev = &wlp->rc->uwb_dev.dev;
179
180	if (le16_to_cpu(hdr->type) != type) {
181		dev_err(dev, "WLP: unexpected header type. Expected "
182			"%u, got %u.\n", type, le16_to_cpu(hdr->type));
183		return -EINVAL;
184	}
185	if (le16_to_cpu(hdr->length) != len) {
186		dev_err(dev, "WLP: unexpected length in header. Expected "
187			"%u, got %u.\n", len, le16_to_cpu(hdr->length));
188		return -EINVAL;
189	}
190	return 0;
191}
192
193/**
194 * Check if header of WSS information attribute valid
195 *
196 * @returns: length of WSS attributes (value of length attribute field) if
197 *             valid WSS information attribute found
198 *           -ENODATA if no WSS information attribute found
199 *           -EIO other error occured
200 *
201 * The WSS information attribute is optional. The function will be provided
202 * with a pointer to data that could _potentially_ be a WSS information
203 * attribute. If a valid WSS information attribute is found it will return
204 * 0, if no WSS information attribute is found it will return -ENODATA, and
205 * another error will be returned if it is a WSS information attribute, but
206 * some parsing failure occured.
207 */
208static int wlp_check_wss_info_attr_hdr(struct wlp *wlp,
209				       struct wlp_attr_hdr *hdr, size_t buflen)
210{
211	struct device *dev = &wlp->rc->uwb_dev.dev;
212	size_t len;
213	int result = 0;
214
215	if (buflen < sizeof(*hdr)) {
216		dev_err(dev, "WLP: Not enough space in buffer to parse"
217			" WSS information attribute header.\n");
218		result = -EIO;
219		goto out;
220	}
221	if (le16_to_cpu(hdr->type) != WLP_ATTR_WSS_INFO) {
222		/* WSS information is optional */
223		result = -ENODATA;
224		goto out;
225	}
226	len = le16_to_cpu(hdr->length);
227	if (buflen < sizeof(*hdr) + len) {
228		dev_err(dev, "WLP: Not enough space in buffer to parse "
229			"variable data. Got %d, expected %d.\n",
230			(int)buflen, (int)(sizeof(*hdr) + len));
231		result = -EIO;
232		goto out;
233	}
234	result = len;
235out:
236	return result;
237}
238
239
240static ssize_t wlp_get_attribute(struct wlp *wlp, u16 type_code,
241	struct wlp_attr_hdr *attr_hdr, void *value, ssize_t value_len,
242	ssize_t buflen)
243{
244	struct device *dev = &wlp->rc->uwb_dev.dev;
245	ssize_t attr_len = sizeof(*attr_hdr) + value_len;
246	if (buflen < 0)
247		return -EINVAL;
248	if (buflen < attr_len) {
249		dev_err(dev, "WLP: Not enough space in buffer to parse"
250			" attribute field. Need %d, received %zu\n",
251			(int)attr_len, buflen);
252		return -EIO;
253	}
254	if (wlp_check_attr_hdr(wlp, attr_hdr, type_code, value_len) < 0) {
255		dev_err(dev, "WLP: Header verification failed. \n");
256		return -EINVAL;
257	}
258	memcpy(value, (void *)attr_hdr + sizeof(*attr_hdr), value_len);
259	return attr_len;
260}
261
262static ssize_t wlp_vget_attribute(struct wlp *wlp, u16 type_code,
263	struct wlp_attr_hdr *attr_hdr, void *value, ssize_t max_value_len,
264	ssize_t buflen)
265{
266	struct device *dev = &wlp->rc->uwb_dev.dev;
267	size_t len;
268	if (buflen < 0)
269		return -EINVAL;
270	if (buflen < sizeof(*attr_hdr)) {
271		dev_err(dev, "WLP: Not enough space in buffer to parse"
272			" header.\n");
273		return -EIO;
274	}
275	if (le16_to_cpu(attr_hdr->type) != type_code) {
276		dev_err(dev, "WLP: Unexpected attribute type. Got %u, "
277			"expected %u.\n", le16_to_cpu(attr_hdr->type),
278			type_code);
279		return -EINVAL;
280	}
281	len = le16_to_cpu(attr_hdr->length);
282	if (len > max_value_len) {
283		dev_err(dev, "WLP: Attribute larger than maximum "
284			"allowed. Received %zu, max is %d.\n", len,
285			(int)max_value_len);
286		return -EFBIG;
287	}
288	if (buflen < sizeof(*attr_hdr) + len) {
289		dev_err(dev, "WLP: Not enough space in buffer to parse "
290			"variable data.\n");
291		return -EIO;
292	}
293	memcpy(value, (void *)attr_hdr + sizeof(*attr_hdr), len);
294	return sizeof(*attr_hdr) + len;
295}
296
297/**
298 * Get value of attribute from fixed size attribute field.
299 *
300 * @attr:    Pointer to attribute field.
301 * @value:   Pointer to variable in which attribute value will be placed.
302 * @buflen:  Size of buffer in which attribute field (including header)
303 *           can be found.
304 * @returns: Amount of given buffer consumed by parsing for this attribute.
305 *
306 * The size and type of the value is known by the type of the attribute.
307 */
308#define wlp_get(type, type_code, name)					\
309ssize_t wlp_get_##name(struct wlp *wlp, struct wlp_attr_##name *attr,	\
310		      type *value, ssize_t buflen)			\
311{									\
312	return wlp_get_attribute(wlp, (type_code), &attr->hdr,		\
313				 value, sizeof(*value), buflen);	\
314}
315
316#define wlp_get_sparse(type, type_code, name) \
317	static wlp_get(type, type_code, name)
318
319/**
320 * Get value of attribute from variable sized attribute field.
321 *
322 * @max:     The maximum size of this attribute. This value is dictated by
323 *           the maximum value from the WLP specification.
324 *
325 * @attr:    Pointer to attribute field.
326 * @value:   Pointer to variable that will contain the value. The memory
327 *           must already have been allocated for this value.
328 * @buflen:  Size of buffer in which attribute field (including header)
329 *           can be found.
330 * @returns: Amount of given bufferconsumed by parsing for this attribute.
331 */
332#define wlp_vget(type_val, type_code, name, max)			\
333static ssize_t wlp_get_##name(struct wlp *wlp,				\
334			      struct wlp_attr_##name *attr,		\
335			      type_val *value, ssize_t buflen)		\
336{									\
337	return wlp_vget_attribute(wlp, (type_code), &attr->hdr, 	\
338			      value, (max), buflen);			\
339}
340
341wlp_get(u8, WLP_ATTR_WLP_VER, version)
342wlp_get_sparse(enum wlp_wss_sel_mthd, WLP_ATTR_WSS_SEL_MTHD, wss_sel_mthd)
343wlp_get_sparse(struct wlp_dev_type, WLP_ATTR_PRI_DEV_TYPE, prim_dev_type)
344wlp_get_sparse(enum wlp_assc_error, WLP_ATTR_WLP_ASSC_ERR, wlp_assc_err)
345wlp_get_sparse(struct wlp_uuid, WLP_ATTR_UUID_E, uuid_e)
346wlp_get_sparse(struct wlp_uuid, WLP_ATTR_UUID_R, uuid_r)
347wlp_get(struct wlp_uuid, WLP_ATTR_WSSID, wssid)
348wlp_get_sparse(u8, WLP_ATTR_ACC_ENRL, accept_enrl)
349wlp_get_sparse(u8, WLP_ATTR_WSS_SEC_STAT, wss_sec_status)
350wlp_get_sparse(struct uwb_mac_addr, WLP_ATTR_WSS_BCAST, wss_bcast)
351wlp_get_sparse(u8, WLP_ATTR_WSS_TAG, wss_tag)
352wlp_get_sparse(struct uwb_mac_addr, WLP_ATTR_WSS_VIRT, wss_virt)
353wlp_get_sparse(struct wlp_nonce, WLP_ATTR_ENRL_NONCE, enonce)
354wlp_get_sparse(struct wlp_nonce, WLP_ATTR_REG_NONCE, rnonce)
355
356/* The buffers for the device info attributes can be found in the
357 * wlp_device_info struct. These buffers contain one byte more than the
358 * max allowed by the spec - this is done to be able to add the
359 * terminating \0 for user display. This terminating byte is not required
360 * in the actual attribute field (because it has a length field) so the
361 * maximum allowed for this value is one less than its size in the
362 * structure.
363 */
364wlp_vget(char, WLP_ATTR_WSS_NAME, wss_name,
365	 FIELD_SIZEOF(struct wlp_wss, name) - 1)
366wlp_vget(char, WLP_ATTR_DEV_NAME, dev_name,
367	 FIELD_SIZEOF(struct wlp_device_info, name) - 1)
368wlp_vget(char, WLP_ATTR_MANUF, manufacturer,
369	 FIELD_SIZEOF(struct wlp_device_info, manufacturer) - 1)
370wlp_vget(char, WLP_ATTR_MODEL_NAME, model_name,
371	 FIELD_SIZEOF(struct wlp_device_info, model_name) - 1)
372wlp_vget(char, WLP_ATTR_MODEL_NR, model_nr,
373	 FIELD_SIZEOF(struct wlp_device_info, model_nr) - 1)
374wlp_vget(char, WLP_ATTR_SERIAL, serial,
375	 FIELD_SIZEOF(struct wlp_device_info, serial) - 1)
376
377/**
378 * Retrieve WSS Name, Accept enroll, Secure status, Broadcast from WSS info
379 *
380 * @attr: pointer to WSS name attribute in WSS information attribute field
381 * @info: structure that will be populated with data from WSS information
382 *        field (WSS name, Accept enroll, secure status, broadcast address)
383 * @buflen: size of buffer
384 *
385 * Although the WSSID attribute forms part of the WSS info attribute it is
386 * retrieved separately and stored in a different location.
387 */
388static ssize_t wlp_get_wss_info_attrs(struct wlp *wlp,
389				      struct wlp_attr_hdr *attr,
390				      struct wlp_wss_tmp_info *info,
391				      ssize_t buflen)
392{
393	struct device *dev = &wlp->rc->uwb_dev.dev;
394	void *ptr = attr;
395	size_t used = 0;
396	ssize_t result = -EINVAL;
397
398	result = wlp_get_wss_name(wlp, ptr, info->name, buflen);
399	if (result < 0) {
400		dev_err(dev, "WLP: unable to obtain WSS name from "
401			"WSS info in D2 message.\n");
402		goto error_parse;
403	}
404	used += result;
405
406	result = wlp_get_accept_enrl(wlp, ptr + used, &info->accept_enroll,
407				     buflen - used);
408	if (result < 0) {
409		dev_err(dev, "WLP: unable to obtain accepting "
410			"enrollment from WSS info in D2 message.\n");
411		goto error_parse;
412	}
413	if (info->accept_enroll != 0 && info->accept_enroll != 1) {
414		dev_err(dev, "WLP: invalid value for accepting "
415			"enrollment in D2 message.\n");
416		result = -EINVAL;
417		goto error_parse;
418	}
419	used += result;
420
421	result = wlp_get_wss_sec_status(wlp, ptr + used, &info->sec_status,
422					buflen - used);
423	if (result < 0) {
424		dev_err(dev, "WLP: unable to obtain secure "
425			"status from WSS info in D2 message.\n");
426		goto error_parse;
427	}
428	if (info->sec_status != 0 && info->sec_status != 1) {
429		dev_err(dev, "WLP: invalid value for secure "
430			"status in D2 message.\n");
431		result = -EINVAL;
432		goto error_parse;
433	}
434	used += result;
435
436	result = wlp_get_wss_bcast(wlp, ptr + used, &info->bcast,
437				   buflen - used);
438	if (result < 0) {
439		dev_err(dev, "WLP: unable to obtain broadcast "
440			"address from WSS info in D2 message.\n");
441		goto error_parse;
442	}
443	used += result;
444	result = used;
445error_parse:
446	return result;
447}
448
449/**
450 * Create a new WSSID entry for the neighbor, allocate temporary storage
451 *
452 * Each neighbor can have many WSS active. We maintain a list of WSSIDs
453 * advertised by neighbor. During discovery we also cache information about
454 * these WSS in temporary storage.
455 *
456 * The temporary storage will be removed after it has been used (eg.
457 * displayed to user), the wssid element will be removed from the list when
458 * the neighbor is rediscovered or when it disappears.
459 */
460static struct wlp_wssid_e *wlp_create_wssid_e(struct wlp *wlp,
461					      struct wlp_neighbor_e *neighbor)
462{
463	struct device *dev = &wlp->rc->uwb_dev.dev;
464	struct wlp_wssid_e *wssid_e;
465
466	wssid_e = kzalloc(sizeof(*wssid_e), GFP_KERNEL);
467	if (wssid_e == NULL) {
468		dev_err(dev, "WLP: unable to allocate memory "
469			"for WSS information.\n");
470		goto error_alloc;
471	}
472	wssid_e->info = kzalloc(sizeof(struct wlp_wss_tmp_info), GFP_KERNEL);
473	if (wssid_e->info == NULL) {
474		dev_err(dev, "WLP: unable to allocate memory "
475			"for temporary WSS information.\n");
476		kfree(wssid_e);
477		wssid_e = NULL;
478		goto error_alloc;
479	}
480	list_add(&wssid_e->node, &neighbor->wssid);
481error_alloc:
482	return wssid_e;
483}
484
485/**
486 * Parse WSS information attribute
487 *
488 * @attr: pointer to WSS information attribute header
489 * @buflen: size of buffer in which WSS information attribute appears
490 * @wssid: will place wssid from WSS info attribute in this location
491 * @wss_info: will place other information from WSS information attribute
492 * in this location
493 *
494 * memory for @wssid and @wss_info must be allocated when calling this
495 */
496static ssize_t wlp_get_wss_info(struct wlp *wlp, struct wlp_attr_wss_info *attr,
497				size_t buflen, struct wlp_uuid *wssid,
498				struct wlp_wss_tmp_info *wss_info)
499{
500	struct device *dev = &wlp->rc->uwb_dev.dev;
501	ssize_t result;
502	size_t len;
503	size_t used = 0;
504	void *ptr;
505
506	result = wlp_check_wss_info_attr_hdr(wlp, (struct wlp_attr_hdr *)attr,
507					     buflen);
508	if (result < 0)
509		goto out;
510	len = result;
511	used = sizeof(*attr);
512	ptr = attr;
513
514	result = wlp_get_wssid(wlp, ptr + used, wssid, buflen - used);
515	if (result < 0) {
516		dev_err(dev, "WLP: unable to obtain WSSID from WSS info.\n");
517		goto out;
518	}
519	used += result;
520	result = wlp_get_wss_info_attrs(wlp, ptr + used, wss_info,
521					buflen - used);
522	if (result < 0) {
523		dev_err(dev, "WLP: unable to obtain WSS information "
524			"from WSS information attributes. \n");
525		goto out;
526	}
527	used += result;
528	if (len + sizeof(*attr) != used) {
529		dev_err(dev, "WLP: Amount of data parsed does not "
530			"match length field. Parsed %zu, length "
531			"field %zu. \n", used, len);
532		result = -EINVAL;
533		goto out;
534	}
535	result = used;
536out:
537	return result;
538}
539
540/**
541 * Retrieve WSS info from association frame
542 *
543 * @attr:     pointer to WSS information attribute
544 * @neighbor: ptr to neighbor being discovered, NULL if enrollment in
545 *            progress
546 * @wss:      ptr to WSS being enrolled in, NULL if discovery in progress
547 * @buflen:   size of buffer in which WSS information appears
548 *
549 * The WSS information attribute appears in the D2 association message.
550 * This message is used in two ways: to discover all neighbors or to enroll
551 * into a WSS activated by a neighbor. During discovery we only want to
552 * store the WSS info in a cache, to be deleted right after it has been
553 * used (eg. displayed to the user). During enrollment we store the WSS
554 * information for the lifetime of enrollment.
555 *
556 * During discovery we are interested in all WSS information, during
557 * enrollment we are only interested in the WSS being enrolled in. Even so,
558 * when in enrollment we keep parsing the message after finding the WSS of
559 * interest, this simplifies the calling routine in that it can be sure
560 * that all WSS information attributes have been parsed out of the message.
561 *
562 * Association frame is process with nbmutex held. The list access is safe.
563 */
564static ssize_t wlp_get_all_wss_info(struct wlp *wlp,
565				    struct wlp_attr_wss_info *attr,
566				    struct wlp_neighbor_e *neighbor,
567				    struct wlp_wss *wss, ssize_t buflen)
568{
569	struct device *dev = &wlp->rc->uwb_dev.dev;
570	size_t used = 0;
571	ssize_t result = -EINVAL;
572	struct wlp_attr_wss_info *cur;
573	struct wlp_uuid wssid;
574	struct wlp_wss_tmp_info wss_info;
575	unsigned enroll; /* 0 - discovery to cache, 1 - enrollment */
576	struct wlp_wssid_e *wssid_e;
577	char buf[WLP_WSS_UUID_STRSIZE];
578
579	if (buflen < 0)
580		goto out;
581
582	if (neighbor != NULL && wss == NULL)
583		enroll = 0; /* discovery */
584	else if (wss != NULL && neighbor == NULL)
585		enroll = 1; /* enrollment */
586	else
587		goto out;
588
589	cur = attr;
590	while (buflen - used > 0) {
591		memset(&wss_info, 0, sizeof(wss_info));
592		cur = (void *)cur + used;
593		result = wlp_get_wss_info(wlp, cur, buflen - used, &wssid,
594					  &wss_info);
595		if (result == -ENODATA) {
596			result = used;
597			goto out;
598		} else if (result < 0) {
599			dev_err(dev, "WLP: Unable to parse WSS information "
600				"from WSS information attribute. \n");
601			result = -EINVAL;
602			goto error_parse;
603		}
604		if (enroll && !memcmp(&wssid, &wss->wssid, sizeof(wssid))) {
605			if (wss_info.accept_enroll != 1) {
606				dev_err(dev, "WLP: Requested WSS does "
607					"not accept enrollment.\n");
608				result = -EINVAL;
609				goto out;
610			}
611			memcpy(wss->name, wss_info.name, sizeof(wss->name));
612			wss->bcast = wss_info.bcast;
613			wss->secure_status = wss_info.sec_status;
614			wss->accept_enroll = wss_info.accept_enroll;
615			wss->state = WLP_WSS_STATE_PART_ENROLLED;
616			wlp_wss_uuid_print(buf, sizeof(buf), &wssid);
617			dev_dbg(dev, "WLP: Found WSS %s. Enrolling.\n", buf);
618		} else {
619			wssid_e = wlp_create_wssid_e(wlp, neighbor);
620			if (wssid_e == NULL) {
621				dev_err(dev, "WLP: Cannot create new WSSID "
622					"entry for neighbor %02x:%02x.\n",
623					neighbor->uwb_dev->dev_addr.data[1],
624					neighbor->uwb_dev->dev_addr.data[0]);
625				result = -ENOMEM;
626				goto out;
627			}
628			wssid_e->wssid = wssid;
629			*wssid_e->info = wss_info;
630		}
631		used += result;
632	}
633	result = used;
634error_parse:
635	if (result < 0 && !enroll) /* this was a discovery */
636		wlp_remove_neighbor_tmp_info(neighbor);
637out:
638	return result;
639
640}
641
642/**
643 * Parse WSS information attributes into cache for discovery
644 *
645 * @attr: the first WSS information attribute in message
646 * @neighbor: the neighbor whose cache will be populated
647 * @buflen: size of the input buffer
648 */
649static ssize_t wlp_get_wss_info_to_cache(struct wlp *wlp,
650					 struct wlp_attr_wss_info *attr,
651					 struct wlp_neighbor_e *neighbor,
652					 ssize_t buflen)
653{
654	return wlp_get_all_wss_info(wlp, attr, neighbor, NULL, buflen);
655}
656
657/**
658 * Parse WSS information attributes into WSS struct for enrollment
659 *
660 * @attr: the first WSS information attribute in message
661 * @wss: the WSS that will be enrolled
662 * @buflen: size of the input buffer
663 */
664static ssize_t wlp_get_wss_info_to_enroll(struct wlp *wlp,
665					  struct wlp_attr_wss_info *attr,
666					  struct wlp_wss *wss, ssize_t buflen)
667{
668	return wlp_get_all_wss_info(wlp, attr, NULL, wss, buflen);
669}
670
671/**
672 * Construct a D1 association frame
673 *
674 * We use the radio control functions to determine the values of the device
675 * properties. These are of variable length and the total space needed is
676 * tallied first before we start constructing the message. The radio
677 * control functions return strings that are terminated with \0. This
678 * character should not be included in the message (there is a length field
679 * accompanying it in the attribute).
680 */
681static int wlp_build_assoc_d1(struct wlp *wlp, struct wlp_wss *wss,
682			      struct sk_buff **skb)
683{
684
685	struct device *dev = &wlp->rc->uwb_dev.dev;
686	int result = 0;
687	struct wlp_device_info *info;
688	size_t used = 0;
689	struct wlp_frame_assoc *_d1;
690	struct sk_buff *_skb;
691	void *d1_itr;
692
693	if (wlp->dev_info == NULL) {
694		result = __wlp_setup_device_info(wlp);
695		if (result < 0) {
696			dev_err(dev, "WLP: Unable to setup device "
697				"information for D1 message.\n");
698			goto error;
699		}
700	}
701	info = wlp->dev_info;
702	_skb = dev_alloc_skb(sizeof(*_d1)
703		      + sizeof(struct wlp_attr_uuid_e)
704		      + sizeof(struct wlp_attr_wss_sel_mthd)
705		      + sizeof(struct wlp_attr_dev_name)
706		      + strlen(info->name)
707		      + sizeof(struct wlp_attr_manufacturer)
708		      + strlen(info->manufacturer)
709		      + sizeof(struct wlp_attr_model_name)
710		      + strlen(info->model_name)
711		      + sizeof(struct wlp_attr_model_nr)
712		      + strlen(info->model_nr)
713		      + sizeof(struct wlp_attr_serial)
714		      + strlen(info->serial)
715		      + sizeof(struct wlp_attr_prim_dev_type)
716		      + sizeof(struct wlp_attr_wlp_assc_err));
717	if (_skb == NULL) {
718		dev_err(dev, "WLP: Cannot allocate memory for association "
719			"message.\n");
720		result = -ENOMEM;
721		goto error;
722	}
723	_d1 = (void *) _skb->data;
724	_d1->hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID);
725	_d1->hdr.type = WLP_FRAME_ASSOCIATION;
726	_d1->type = WLP_ASSOC_D1;
727
728	wlp_set_version(&_d1->version, WLP_VERSION);
729	wlp_set_msg_type(&_d1->msg_type, WLP_ASSOC_D1);
730	d1_itr = _d1->attr;
731	used = wlp_set_uuid_e(d1_itr, &wlp->uuid);
732	used += wlp_set_wss_sel_mthd(d1_itr + used, WLP_WSS_REG_SELECT);
733	used += wlp_set_dev_name(d1_itr + used, info->name,
734				 strlen(info->name));
735	used += wlp_set_manufacturer(d1_itr + used, info->manufacturer,
736				     strlen(info->manufacturer));
737	used += wlp_set_model_name(d1_itr + used, info->model_name,
738				   strlen(info->model_name));
739	used += wlp_set_model_nr(d1_itr + used, info->model_nr,
740				 strlen(info->model_nr));
741	used += wlp_set_serial(d1_itr + used, info->serial,
742			       strlen(info->serial));
743	used += wlp_set_prim_dev_type(d1_itr + used, &info->prim_dev_type);
744	used += wlp_set_wlp_assc_err(d1_itr + used, WLP_ASSOC_ERROR_NONE);
745	skb_put(_skb, sizeof(*_d1) + used);
746	*skb = _skb;
747error:
748	return result;
749}
750
751/**
752 * Construct a D2 association frame
753 *
754 * We use the radio control functions to determine the values of the device
755 * properties. These are of variable length and the total space needed is
756 * tallied first before we start constructing the message. The radio
757 * control functions return strings that are terminated with \0. This
758 * character should not be included in the message (there is a length field
759 * accompanying it in the attribute).
760 */
761static
762int wlp_build_assoc_d2(struct wlp *wlp, struct wlp_wss *wss,
763		       struct sk_buff **skb, struct wlp_uuid *uuid_e)
764{
765
766	struct device *dev = &wlp->rc->uwb_dev.dev;
767	int result = 0;
768	struct wlp_device_info *info;
769	size_t used = 0;
770	struct wlp_frame_assoc *_d2;
771	struct sk_buff *_skb;
772	void *d2_itr;
773	size_t mem_needed;
774
775	if (wlp->dev_info == NULL) {
776		result = __wlp_setup_device_info(wlp);
777		if (result < 0) {
778			dev_err(dev, "WLP: Unable to setup device "
779				"information for D2 message.\n");
780			goto error;
781		}
782	}
783	info = wlp->dev_info;
784	mem_needed = sizeof(*_d2)
785		      + sizeof(struct wlp_attr_uuid_e)
786		      + sizeof(struct wlp_attr_uuid_r)
787		      + sizeof(struct wlp_attr_dev_name)
788		      + strlen(info->name)
789		      + sizeof(struct wlp_attr_manufacturer)
790		      + strlen(info->manufacturer)
791		      + sizeof(struct wlp_attr_model_name)
792		      + strlen(info->model_name)
793		      + sizeof(struct wlp_attr_model_nr)
794		      + strlen(info->model_nr)
795		      + sizeof(struct wlp_attr_serial)
796		      + strlen(info->serial)
797		      + sizeof(struct wlp_attr_prim_dev_type)
798		      + sizeof(struct wlp_attr_wlp_assc_err);
799	if (wlp->wss.state >= WLP_WSS_STATE_ACTIVE)
800		mem_needed += sizeof(struct wlp_attr_wss_info)
801			      + sizeof(struct wlp_wss_info)
802			      + strlen(wlp->wss.name);
803	_skb = dev_alloc_skb(mem_needed);
804	if (_skb == NULL) {
805		dev_err(dev, "WLP: Cannot allocate memory for association "
806			"message.\n");
807		result = -ENOMEM;
808		goto error;
809	}
810	_d2 = (void *) _skb->data;
811	_d2->hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID);
812	_d2->hdr.type = WLP_FRAME_ASSOCIATION;
813	_d2->type = WLP_ASSOC_D2;
814
815	wlp_set_version(&_d2->version, WLP_VERSION);
816	wlp_set_msg_type(&_d2->msg_type, WLP_ASSOC_D2);
817	d2_itr = _d2->attr;
818	used = wlp_set_uuid_e(d2_itr, uuid_e);
819	used += wlp_set_uuid_r(d2_itr + used, &wlp->uuid);
820	if (wlp->wss.state >= WLP_WSS_STATE_ACTIVE)
821		used += wlp_set_wss_info(d2_itr + used, &wlp->wss);
822	used += wlp_set_dev_name(d2_itr + used, info->name,
823				 strlen(info->name));
824	used += wlp_set_manufacturer(d2_itr + used, info->manufacturer,
825				     strlen(info->manufacturer));
826	used += wlp_set_model_name(d2_itr + used, info->model_name,
827				   strlen(info->model_name));
828	used += wlp_set_model_nr(d2_itr + used, info->model_nr,
829				 strlen(info->model_nr));
830	used += wlp_set_serial(d2_itr + used, info->serial,
831			       strlen(info->serial));
832	used += wlp_set_prim_dev_type(d2_itr + used, &info->prim_dev_type);
833	used += wlp_set_wlp_assc_err(d2_itr + used, WLP_ASSOC_ERROR_NONE);
834	skb_put(_skb, sizeof(*_d2) + used);
835	*skb = _skb;
836error:
837	return result;
838}
839
840/**
841 * Allocate memory for and populate fields of F0 association frame
842 *
843 * Currently (while focusing on unsecure enrollment) we ignore the
844 * nonce's that could be placed in the message. Only the error field is
845 * populated by the value provided by the caller.
846 */
847static
848int wlp_build_assoc_f0(struct wlp *wlp, struct sk_buff **skb,
849		       enum wlp_assc_error error)
850{
851	struct device *dev = &wlp->rc->uwb_dev.dev;
852	int result = -ENOMEM;
853	struct {
854		struct wlp_frame_assoc f0_hdr;
855		struct wlp_attr_enonce enonce;
856		struct wlp_attr_rnonce rnonce;
857		struct wlp_attr_wlp_assc_err assc_err;
858	} *f0;
859	struct sk_buff *_skb;
860	struct wlp_nonce tmp;
861
862	_skb = dev_alloc_skb(sizeof(*f0));
863	if (_skb == NULL) {
864		dev_err(dev, "WLP: Unable to allocate memory for F0 "
865			"association frame. \n");
866		goto error_alloc;
867	}
868	f0 = (void *) _skb->data;
869	f0->f0_hdr.hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID);
870	f0->f0_hdr.hdr.type = WLP_FRAME_ASSOCIATION;
871	f0->f0_hdr.type = WLP_ASSOC_F0;
872	wlp_set_version(&f0->f0_hdr.version, WLP_VERSION);
873	wlp_set_msg_type(&f0->f0_hdr.msg_type, WLP_ASSOC_F0);
874	memset(&tmp, 0, sizeof(tmp));
875	wlp_set_enonce(&f0->enonce, &tmp);
876	wlp_set_rnonce(&f0->rnonce, &tmp);
877	wlp_set_wlp_assc_err(&f0->assc_err, error);
878	skb_put(_skb, sizeof(*f0));
879	*skb = _skb;
880	result = 0;
881error_alloc:
882	return result;
883}
884
885/**
886 * Parse F0 frame
887 *
888 * We just retrieve the values and print it as an error to the user.
889 * Calling function already knows an error occured (F0 indicates error), so
890 * we just parse the content as debug for higher layers.
891 */
892int wlp_parse_f0(struct wlp *wlp, struct sk_buff *skb)
893{
894	struct device *dev = &wlp->rc->uwb_dev.dev;
895	struct wlp_frame_assoc *f0 = (void *) skb->data;
896	void *ptr = skb->data;
897	size_t len = skb->len;
898	size_t used;
899	ssize_t result;
900	struct wlp_nonce enonce, rnonce;
901	enum wlp_assc_error assc_err;
902	char enonce_buf[WLP_WSS_NONCE_STRSIZE];
903	char rnonce_buf[WLP_WSS_NONCE_STRSIZE];
904
905	used = sizeof(*f0);
906	result = wlp_get_enonce(wlp, ptr + used, &enonce, len - used);
907	if (result < 0) {
908		dev_err(dev, "WLP: unable to obtain Enrollee nonce "
909			"attribute from F0 message.\n");
910		goto error_parse;
911	}
912	used += result;
913	result = wlp_get_rnonce(wlp, ptr + used, &rnonce, len - used);
914	if (result < 0) {
915		dev_err(dev, "WLP: unable to obtain Registrar nonce "
916			"attribute from F0 message.\n");
917		goto error_parse;
918	}
919	used += result;
920	result = wlp_get_wlp_assc_err(wlp, ptr + used, &assc_err, len - used);
921	if (result < 0) {
922		dev_err(dev, "WLP: unable to obtain WLP Association error "
923			"attribute from F0 message.\n");
924		goto error_parse;
925	}
926	wlp_wss_nonce_print(enonce_buf, sizeof(enonce_buf), &enonce);
927	wlp_wss_nonce_print(rnonce_buf, sizeof(rnonce_buf), &rnonce);
928	dev_err(dev, "WLP: Received F0 error frame from neighbor. Enrollee "
929		"nonce: %s, Registrar nonce: %s, WLP Association error: %s.\n",
930		enonce_buf, rnonce_buf, wlp_assc_error_str(assc_err));
931	result = 0;
932error_parse:
933	return result;
934}
935
936/**
937 * Retrieve variable device information from association message
938 *
939 * The device information parsed is not required in any message. This
940 * routine will thus not fail if an attribute is not present.
941 * The attributes are expected in a certain order, even if all are not
942 * present. The "attribute type" value is used to ensure the attributes
943 * are parsed in the correct order.
944 *
945 * If an error is encountered during parsing the function will return an
946 * error code, when this happens the given device_info structure may be
947 * partially filled.
948 */
949static
950int wlp_get_variable_info(struct wlp *wlp, void *data,
951			  struct wlp_device_info *dev_info, ssize_t len)
952{
953	struct device *dev = &wlp->rc->uwb_dev.dev;
954	size_t used = 0;
955	struct wlp_attr_hdr *hdr;
956	ssize_t result = 0;
957	unsigned last = 0;
958
959	while (len - used > 0) {
960		if (len - used < sizeof(*hdr)) {
961			dev_err(dev, "WLP: Partial data in frame, cannot "
962				"parse. \n");
963			goto error_parse;
964		}
965		hdr = data + used;
966		switch (le16_to_cpu(hdr->type)) {
967		case WLP_ATTR_MANUF:
968			if (last >= WLP_ATTR_MANUF) {
969				dev_err(dev, "WLP: Incorrect order of "
970					"attribute values in D1 msg.\n");
971				goto error_parse;
972			}
973			result = wlp_get_manufacturer(wlp, data + used,
974						      dev_info->manufacturer,
975						      len - used);
976			if (result < 0) {
977				dev_err(dev, "WLP: Unable to obtain "
978					"Manufacturer attribute from D1 "
979					"message.\n");
980				goto error_parse;
981			}
982			last = WLP_ATTR_MANUF;
983			used += result;
984			break;
985		case WLP_ATTR_MODEL_NAME:
986			if (last >= WLP_ATTR_MODEL_NAME) {
987				dev_err(dev, "WLP: Incorrect order of "
988					"attribute values in D1 msg.\n");
989				goto error_parse;
990			}
991			result = wlp_get_model_name(wlp, data + used,
992						    dev_info->model_name,
993						    len - used);
994			if (result < 0) {
995				dev_err(dev, "WLP: Unable to obtain Model "
996					"name attribute from D1 message.\n");
997				goto error_parse;
998			}
999			last = WLP_ATTR_MODEL_NAME;
1000			used += result;
1001			break;
1002		case WLP_ATTR_MODEL_NR:
1003			if (last >= WLP_ATTR_MODEL_NR) {
1004				dev_err(dev, "WLP: Incorrect order of "
1005					"attribute values in D1 msg.\n");
1006				goto error_parse;
1007			}
1008			result = wlp_get_model_nr(wlp, data + used,
1009						  dev_info->model_nr,
1010						  len - used);
1011			if (result < 0) {
1012				dev_err(dev, "WLP: Unable to obtain Model "
1013					"number attribute from D1 message.\n");
1014				goto error_parse;
1015			}
1016			last = WLP_ATTR_MODEL_NR;
1017			used += result;
1018			break;
1019		case WLP_ATTR_SERIAL:
1020			if (last >= WLP_ATTR_SERIAL) {
1021				dev_err(dev, "WLP: Incorrect order of "
1022					"attribute values in D1 msg.\n");
1023				goto error_parse;
1024			}
1025			result = wlp_get_serial(wlp, data + used,
1026						dev_info->serial, len - used);
1027			if (result < 0) {
1028				dev_err(dev, "WLP: Unable to obtain Serial "
1029					"number attribute from D1 message.\n");
1030				goto error_parse;
1031			}
1032			last = WLP_ATTR_SERIAL;
1033			used += result;
1034			break;
1035		case WLP_ATTR_PRI_DEV_TYPE:
1036			if (last >= WLP_ATTR_PRI_DEV_TYPE) {
1037				dev_err(dev, "WLP: Incorrect order of "
1038					"attribute values in D1 msg.\n");
1039				goto error_parse;
1040			}
1041			result = wlp_get_prim_dev_type(wlp, data + used,
1042						       &dev_info->prim_dev_type,
1043						       len - used);
1044			if (result < 0) {
1045				dev_err(dev, "WLP: Unable to obtain Primary "
1046					"device type attribute from D1 "
1047					"message.\n");
1048				goto error_parse;
1049			}
1050			dev_info->prim_dev_type.category =
1051				le16_to_cpu(dev_info->prim_dev_type.category);
1052			dev_info->prim_dev_type.subID =
1053				le16_to_cpu(dev_info->prim_dev_type.subID);
1054			last = WLP_ATTR_PRI_DEV_TYPE;
1055			used += result;
1056			break;
1057		default:
1058			/* This is not variable device information. */
1059			goto out;
1060			break;
1061		}
1062	}
1063out:
1064	return used;
1065error_parse:
1066	return -EINVAL;
1067}
1068
1069/**
1070 * Parse incoming D1 frame, populate attribute values
1071 *
1072 * Caller provides pointers to memory already allocated for attributes
1073 * expected in the D1 frame. These variables will be populated.
1074 */
1075static
1076int wlp_parse_d1_frame(struct wlp *wlp, struct sk_buff *skb,
1077		       struct wlp_uuid *uuid_e,
1078		       enum wlp_wss_sel_mthd *sel_mthd,
1079		       struct wlp_device_info *dev_info,
1080		       enum wlp_assc_error *assc_err)
1081{
1082	struct device *dev = &wlp->rc->uwb_dev.dev;
1083	struct wlp_frame_assoc *d1 = (void *) skb->data;
1084	void *ptr = skb->data;
1085	size_t len = skb->len;
1086	size_t used;
1087	ssize_t result;
1088
1089	used = sizeof(*d1);
1090	result = wlp_get_uuid_e(wlp, ptr + used, uuid_e, len - used);
1091	if (result < 0) {
1092		dev_err(dev, "WLP: unable to obtain UUID-E attribute from D1 "
1093			"message.\n");
1094		goto error_parse;
1095	}
1096	used += result;
1097	result = wlp_get_wss_sel_mthd(wlp, ptr + used, sel_mthd, len - used);
1098	if (result < 0) {
1099		dev_err(dev, "WLP: unable to obtain WSS selection method "
1100			"from D1 message.\n");
1101		goto error_parse;
1102	}
1103	used += result;
1104	result = wlp_get_dev_name(wlp, ptr + used, dev_info->name,
1105				     len - used);
1106	if (result < 0) {
1107		dev_err(dev, "WLP: unable to obtain Device Name from D1 "
1108			"message.\n");
1109		goto error_parse;
1110	}
1111	used += result;
1112	result = wlp_get_variable_info(wlp, ptr + used, dev_info, len - used);
1113	if (result < 0) {
1114		dev_err(dev, "WLP: unable to obtain Device Information from "
1115			"D1 message.\n");
1116		goto error_parse;
1117	}
1118	used += result;
1119	result = wlp_get_wlp_assc_err(wlp, ptr + used, assc_err, len - used);
1120	if (result < 0) {
1121		dev_err(dev, "WLP: unable to obtain WLP Association Error "
1122			"Information from D1 message.\n");
1123		goto error_parse;
1124	}
1125	result = 0;
1126error_parse:
1127	return result;
1128}
1129/**
1130 * Handle incoming D1 frame
1131 *
1132 * The frame has already been verified to contain an Association header with
1133 * the correct version number. Parse the incoming frame, construct and send
1134 * a D2 frame in response.
1135 *
1136 * It is not clear what to do with most fields in the incoming D1 frame. We
1137 * retrieve and discard the information here for now.
1138 */
1139void wlp_handle_d1_frame(struct work_struct *ws)
1140{
1141	struct wlp_assoc_frame_ctx *frame_ctx = container_of(ws,
1142						  struct wlp_assoc_frame_ctx,
1143						  ws);
1144	struct wlp *wlp = frame_ctx->wlp;
1145	struct wlp_wss *wss = &wlp->wss;
1146	struct sk_buff *skb = frame_ctx->skb;
1147	struct uwb_dev_addr *src = &frame_ctx->src;
1148	int result;
1149	struct device *dev = &wlp->rc->uwb_dev.dev;
1150	struct wlp_uuid uuid_e;
1151	enum wlp_wss_sel_mthd sel_mthd = 0;
1152	struct wlp_device_info dev_info;
1153	enum wlp_assc_error assc_err;
1154	struct sk_buff *resp = NULL;
1155
1156	/* Parse D1 frame */
1157	mutex_lock(&wss->mutex);
1158	mutex_lock(&wlp->mutex); /* to access wlp->uuid */
1159	memset(&dev_info, 0, sizeof(dev_info));
1160	result = wlp_parse_d1_frame(wlp, skb, &uuid_e, &sel_mthd, &dev_info,
1161				    &assc_err);
1162	if (result < 0) {
1163		dev_err(dev, "WLP: Unable to parse incoming D1 frame.\n");
1164		kfree_skb(skb);
1165		goto out;
1166	}
1167
1168	kfree_skb(skb);
1169	if (!wlp_uuid_is_set(&wlp->uuid)) {
1170		dev_err(dev, "WLP: UUID is not set. Set via sysfs to "
1171			"proceed. Respong to D1 message with error F0.\n");
1172		result = wlp_build_assoc_f0(wlp, &resp,
1173					    WLP_ASSOC_ERROR_NOT_READY);
1174		if (result < 0) {
1175			dev_err(dev, "WLP: Unable to construct F0 message.\n");
1176			goto out;
1177		}
1178	} else {
1179		/* Construct D2 frame */
1180		result = wlp_build_assoc_d2(wlp, wss, &resp, &uuid_e);
1181		if (result < 0) {
1182			dev_err(dev, "WLP: Unable to construct D2 message.\n");
1183			goto out;
1184		}
1185	}
1186	/* Send D2 frame */
1187	BUG_ON(wlp->xmit_frame == NULL);
1188	result = wlp->xmit_frame(wlp, resp, src);
1189	if (result < 0) {
1190		dev_err(dev, "WLP: Unable to transmit D2 association "
1191			"message: %d\n", result);
1192		if (result == -ENXIO)
1193			dev_err(dev, "WLP: Is network interface up? \n");
1194		/* We could try again ... */
1195		dev_kfree_skb_any(resp); /* we need to free if tx fails */
1196	}
1197out:
1198	kfree(frame_ctx);
1199	mutex_unlock(&wlp->mutex);
1200	mutex_unlock(&wss->mutex);
1201}
1202
1203/**
1204 * Parse incoming D2 frame, create and populate temporary cache
1205 *
1206 * @skb: socket buffer in which D2 frame can be found
1207 * @neighbor: the neighbor that sent the D2 frame
1208 *
1209 * Will allocate memory for temporary storage of information learned during
1210 * discovery.
1211 */
1212int wlp_parse_d2_frame_to_cache(struct wlp *wlp, struct sk_buff *skb,
1213				struct wlp_neighbor_e *neighbor)
1214{
1215	struct device *dev = &wlp->rc->uwb_dev.dev;
1216	struct wlp_frame_assoc *d2 = (void *) skb->data;
1217	void *ptr = skb->data;
1218	size_t len = skb->len;
1219	size_t used;
1220	ssize_t result;
1221	struct wlp_uuid uuid_e;
1222	struct wlp_device_info *nb_info;
1223	enum wlp_assc_error assc_err;
1224
1225	used = sizeof(*d2);
1226	result = wlp_get_uuid_e(wlp, ptr + used, &uuid_e, len - used);
1227	if (result < 0) {
1228		dev_err(dev, "WLP: unable to obtain UUID-E attribute from D2 "
1229			"message.\n");
1230		goto error_parse;
1231	}
1232	if (memcmp(&uuid_e, &wlp->uuid, sizeof(uuid_e))) {
1233		dev_err(dev, "WLP: UUID-E in incoming D2 does not match "
1234			"local UUID sent in D1. \n");
1235		goto error_parse;
1236	}
1237	used += result;
1238	result = wlp_get_uuid_r(wlp, ptr + used, &neighbor->uuid, len - used);
1239	if (result < 0) {
1240		dev_err(dev, "WLP: unable to obtain UUID-R attribute from D2 "
1241			"message.\n");
1242		goto error_parse;
1243	}
1244	used += result;
1245	result = wlp_get_wss_info_to_cache(wlp, ptr + used, neighbor,
1246					   len - used);
1247	if (result < 0) {
1248		dev_err(dev, "WLP: unable to obtain WSS information "
1249			"from D2 message.\n");
1250		goto error_parse;
1251	}
1252	used += result;
1253	neighbor->info = kzalloc(sizeof(struct wlp_device_info), GFP_KERNEL);
1254	if (neighbor->info == NULL) {
1255		dev_err(dev, "WLP: cannot allocate memory to store device "
1256			"info.\n");
1257		result = -ENOMEM;
1258		goto error_parse;
1259	}
1260	nb_info = neighbor->info;
1261	result = wlp_get_dev_name(wlp, ptr + used, nb_info->name,
1262				  len - used);
1263	if (result < 0) {
1264		dev_err(dev, "WLP: unable to obtain Device Name from D2 "
1265			"message.\n");
1266		goto error_parse;
1267	}
1268	used += result;
1269	result = wlp_get_variable_info(wlp, ptr + used, nb_info, len - used);
1270	if (result < 0) {
1271		dev_err(dev, "WLP: unable to obtain Device Information from "
1272			"D2 message.\n");
1273		goto error_parse;
1274	}
1275	used += result;
1276	result = wlp_get_wlp_assc_err(wlp, ptr + used, &assc_err, len - used);
1277	if (result < 0) {
1278		dev_err(dev, "WLP: unable to obtain WLP Association Error "
1279			"Information from D2 message.\n");
1280		goto error_parse;
1281	}
1282	if (assc_err != WLP_ASSOC_ERROR_NONE) {
1283		dev_err(dev, "WLP: neighbor device returned association "
1284			"error %d\n", assc_err);
1285		result = -EINVAL;
1286		goto error_parse;
1287	}
1288	result = 0;
1289error_parse:
1290	if (result < 0)
1291		wlp_remove_neighbor_tmp_info(neighbor);
1292	return result;
1293}
1294
1295/**
1296 * Parse incoming D2 frame, populate attribute values of WSS bein enrolled in
1297 *
1298 * @wss: our WSS that will be enrolled
1299 * @skb: socket buffer in which D2 frame can be found
1300 * @neighbor: the neighbor that sent the D2 frame
1301 * @wssid: the wssid of the WSS in which we want to enroll
1302 *
1303 * Forms part of enrollment sequence. We are trying to enroll in WSS with
1304 * @wssid by using @neighbor as registrar. A D1 message was sent to
1305 * @neighbor and now we need to parse the D2 response. The neighbor's
1306 * response is searched for the requested WSS and if found (and it accepts
1307 * enrollment), we store the information.
1308 */
1309int wlp_parse_d2_frame_to_enroll(struct wlp_wss *wss, struct sk_buff *skb,
1310				 struct wlp_neighbor_e *neighbor,
1311				 struct wlp_uuid *wssid)
1312{
1313	struct wlp *wlp = container_of(wss, struct wlp, wss);
1314	struct device *dev = &wlp->rc->uwb_dev.dev;
1315	void *ptr = skb->data;
1316	size_t len = skb->len;
1317	size_t used;
1318	ssize_t result;
1319	struct wlp_uuid uuid_e;
1320	struct wlp_uuid uuid_r;
1321	struct wlp_device_info nb_info;
1322	enum wlp_assc_error assc_err;
1323	char uuid_bufA[WLP_WSS_UUID_STRSIZE];
1324	char uuid_bufB[WLP_WSS_UUID_STRSIZE];
1325
1326	used = sizeof(struct wlp_frame_assoc);
1327	result = wlp_get_uuid_e(wlp, ptr + used, &uuid_e, len - used);
1328	if (result < 0) {
1329		dev_err(dev, "WLP: unable to obtain UUID-E attribute from D2 "
1330			"message.\n");
1331		goto error_parse;
1332	}
1333	if (memcmp(&uuid_e, &wlp->uuid, sizeof(uuid_e))) {
1334		dev_err(dev, "WLP: UUID-E in incoming D2 does not match "
1335			"local UUID sent in D1. \n");
1336		goto error_parse;
1337	}
1338	used += result;
1339	result = wlp_get_uuid_r(wlp, ptr + used, &uuid_r, len - used);
1340	if (result < 0) {
1341		dev_err(dev, "WLP: unable to obtain UUID-R attribute from D2 "
1342			"message.\n");
1343		goto error_parse;
1344	}
1345	if (memcmp(&uuid_r, &neighbor->uuid, sizeof(uuid_r))) {
1346		wlp_wss_uuid_print(uuid_bufA, sizeof(uuid_bufA),
1347				   &neighbor->uuid);
1348		wlp_wss_uuid_print(uuid_bufB, sizeof(uuid_bufB), &uuid_r);
1349		dev_err(dev, "WLP: UUID of neighbor does not match UUID "
1350			"learned during discovery. Originally discovered: %s, "
1351			"now from D2 message: %s\n", uuid_bufA, uuid_bufB);
1352		result = -EINVAL;
1353		goto error_parse;
1354	}
1355	used += result;
1356	wss->wssid = *wssid;
1357	result = wlp_get_wss_info_to_enroll(wlp, ptr + used, wss, len - used);
1358	if (result < 0) {
1359		dev_err(dev, "WLP: unable to obtain WSS information "
1360			"from D2 message.\n");
1361		goto error_parse;
1362	}
1363	if (wss->state != WLP_WSS_STATE_PART_ENROLLED) {
1364		dev_err(dev, "WLP: D2 message did not contain information "
1365			"for successful enrollment. \n");
1366		result = -EINVAL;
1367		goto error_parse;
1368	}
1369	used += result;
1370	/* Place device information on stack to continue parsing of message */
1371	result = wlp_get_dev_name(wlp, ptr + used, nb_info.name,
1372				  len - used);
1373	if (result < 0) {
1374		dev_err(dev, "WLP: unable to obtain Device Name from D2 "
1375			"message.\n");
1376		goto error_parse;
1377	}
1378	used += result;
1379	result = wlp_get_variable_info(wlp, ptr + used, &nb_info, len - used);
1380	if (result < 0) {
1381		dev_err(dev, "WLP: unable to obtain Device Information from "
1382			"D2 message.\n");
1383		goto error_parse;
1384	}
1385	used += result;
1386	result = wlp_get_wlp_assc_err(wlp, ptr + used, &assc_err, len - used);
1387	if (result < 0) {
1388		dev_err(dev, "WLP: unable to obtain WLP Association Error "
1389			"Information from D2 message.\n");
1390		goto error_parse;
1391	}
1392	if (assc_err != WLP_ASSOC_ERROR_NONE) {
1393		dev_err(dev, "WLP: neighbor device returned association "
1394			"error %d\n", assc_err);
1395		if (wss->state == WLP_WSS_STATE_PART_ENROLLED) {
1396			dev_err(dev, "WLP: Enrolled in WSS (should not "
1397				"happen according to spec). Undoing. \n");
1398			wlp_wss_reset(wss);
1399		}
1400		result = -EINVAL;
1401		goto error_parse;
1402	}
1403	result = 0;
1404error_parse:
1405	return result;
1406}
1407
1408/**
1409 * Parse C3/C4 frame into provided variables
1410 *
1411 * @wssid: will point to copy of wssid retrieved from C3/C4 frame
1412 * @tag:   will point to copy of tag retrieved from C3/C4 frame
1413 * @virt_addr: will point to copy of virtual address retrieved from C3/C4
1414 * frame.
1415 *
1416 * Calling function has to allocate memory for these values.
1417 *
1418 * skb contains a valid C3/C4 frame, return the individual fields of this
1419 * frame in the provided variables.
1420 */
1421int wlp_parse_c3c4_frame(struct wlp *wlp, struct sk_buff *skb,
1422		       struct wlp_uuid *wssid, u8 *tag,
1423		       struct uwb_mac_addr *virt_addr)
1424{
1425	struct device *dev = &wlp->rc->uwb_dev.dev;
1426	int result;
1427	void *ptr = skb->data;
1428	size_t len = skb->len;
1429	size_t used;
1430	struct wlp_frame_assoc *assoc = ptr;
1431
1432	used = sizeof(*assoc);
1433	result = wlp_get_wssid(wlp, ptr + used, wssid, len - used);
1434	if (result < 0) {
1435		dev_err(dev, "WLP: unable to obtain WSSID attribute from "
1436			"%s message.\n", wlp_assoc_frame_str(assoc->type));
1437		goto error_parse;
1438	}
1439	used += result;
1440	result = wlp_get_wss_tag(wlp, ptr + used, tag, len - used);
1441	if (result < 0) {
1442		dev_err(dev, "WLP: unable to obtain WSS tag attribute from "
1443			"%s message.\n", wlp_assoc_frame_str(assoc->type));
1444		goto error_parse;
1445	}
1446	used += result;
1447	result = wlp_get_wss_virt(wlp, ptr + used, virt_addr, len - used);
1448	if (result < 0) {
1449		dev_err(dev, "WLP: unable to obtain WSS virtual address "
1450			"attribute from %s message.\n",
1451			wlp_assoc_frame_str(assoc->type));
1452		goto error_parse;
1453	}
1454error_parse:
1455	return result;
1456}
1457
1458/**
1459 * Allocate memory for and populate fields of C1 or C2 association frame
1460 *
1461 * The C1 and C2 association frames appear identical - except for the type.
1462 */
1463static
1464int wlp_build_assoc_c1c2(struct wlp *wlp, struct wlp_wss *wss,
1465			 struct sk_buff **skb, enum wlp_assoc_type type)
1466{
1467	struct device *dev = &wlp->rc->uwb_dev.dev;
1468	int result  = -ENOMEM;
1469	struct {
1470		struct wlp_frame_assoc c_hdr;
1471		struct wlp_attr_wssid wssid;
1472	} *c;
1473	struct sk_buff *_skb;
1474
1475	_skb = dev_alloc_skb(sizeof(*c));
1476	if (_skb == NULL) {
1477		dev_err(dev, "WLP: Unable to allocate memory for C1/C2 "
1478			"association frame. \n");
1479		goto error_alloc;
1480	}
1481	c = (void *) _skb->data;
1482	c->c_hdr.hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID);
1483	c->c_hdr.hdr.type = WLP_FRAME_ASSOCIATION;
1484	c->c_hdr.type = type;
1485	wlp_set_version(&c->c_hdr.version, WLP_VERSION);
1486	wlp_set_msg_type(&c->c_hdr.msg_type, type);
1487	wlp_set_wssid(&c->wssid, &wss->wssid);
1488	skb_put(_skb, sizeof(*c));
1489	*skb = _skb;
1490	result = 0;
1491error_alloc:
1492	return result;
1493}
1494
1495
1496static
1497int wlp_build_assoc_c1(struct wlp *wlp, struct wlp_wss *wss,
1498		       struct sk_buff **skb)
1499{
1500	return wlp_build_assoc_c1c2(wlp, wss, skb, WLP_ASSOC_C1);
1501}
1502
1503static
1504int wlp_build_assoc_c2(struct wlp *wlp, struct wlp_wss *wss,
1505		       struct sk_buff **skb)
1506{
1507	return wlp_build_assoc_c1c2(wlp, wss, skb, WLP_ASSOC_C2);
1508}
1509
1510
1511/**
1512 * Allocate memory for and populate fields of C3 or C4 association frame
1513 *
1514 * The C3 and C4 association frames appear identical - except for the type.
1515 */
1516static
1517int wlp_build_assoc_c3c4(struct wlp *wlp, struct wlp_wss *wss,
1518			 struct sk_buff **skb, enum wlp_assoc_type type)
1519{
1520	struct device *dev = &wlp->rc->uwb_dev.dev;
1521	int result  = -ENOMEM;
1522	struct {
1523		struct wlp_frame_assoc c_hdr;
1524		struct wlp_attr_wssid wssid;
1525		struct wlp_attr_wss_tag wss_tag;
1526		struct wlp_attr_wss_virt wss_virt;
1527	} *c;
1528	struct sk_buff *_skb;
1529
1530	_skb = dev_alloc_skb(sizeof(*c));
1531	if (_skb == NULL) {
1532		dev_err(dev, "WLP: Unable to allocate memory for C3/C4 "
1533			"association frame. \n");
1534		goto error_alloc;
1535	}
1536	c = (void *) _skb->data;
1537	c->c_hdr.hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID);
1538	c->c_hdr.hdr.type = WLP_FRAME_ASSOCIATION;
1539	c->c_hdr.type = type;
1540	wlp_set_version(&c->c_hdr.version, WLP_VERSION);
1541	wlp_set_msg_type(&c->c_hdr.msg_type, type);
1542	wlp_set_wssid(&c->wssid, &wss->wssid);
1543	wlp_set_wss_tag(&c->wss_tag, wss->tag);
1544	wlp_set_wss_virt(&c->wss_virt, &wss->virtual_addr);
1545	skb_put(_skb, sizeof(*c));
1546	*skb = _skb;
1547	result = 0;
1548error_alloc:
1549	return result;
1550}
1551
1552static
1553int wlp_build_assoc_c3(struct wlp *wlp, struct wlp_wss *wss,
1554		       struct sk_buff **skb)
1555{
1556	return wlp_build_assoc_c3c4(wlp, wss, skb, WLP_ASSOC_C3);
1557}
1558
1559static
1560int wlp_build_assoc_c4(struct wlp *wlp, struct wlp_wss *wss,
1561		       struct sk_buff **skb)
1562{
1563	return wlp_build_assoc_c3c4(wlp, wss, skb, WLP_ASSOC_C4);
1564}
1565
1566
1567#define wlp_send_assoc(type, id)					\
1568static int wlp_send_assoc_##type(struct wlp *wlp, struct wlp_wss *wss,	\
1569				 struct uwb_dev_addr *dev_addr)		\
1570{									\
1571	struct device *dev = &wlp->rc->uwb_dev.dev;			\
1572	int result;							\
1573	struct sk_buff *skb = NULL;					\
1574									\
1575	/* Build the frame */						\
1576	result = wlp_build_assoc_##type(wlp, wss, &skb);		\
1577	if (result < 0) {						\
1578		dev_err(dev, "WLP: Unable to construct %s association "	\
1579			"frame: %d\n", wlp_assoc_frame_str(id), result);\
1580		goto error_build_assoc;					\
1581	}								\
1582	/* Send the frame */						\
1583	BUG_ON(wlp->xmit_frame == NULL);				\
1584	result = wlp->xmit_frame(wlp, skb, dev_addr);			\
1585	if (result < 0) {						\
1586		dev_err(dev, "WLP: Unable to transmit %s association "	\
1587			"message: %d\n", wlp_assoc_frame_str(id),	\
1588			result);					\
1589		if (result == -ENXIO)					\
1590			dev_err(dev, "WLP: Is network interface "	\
1591				"up? \n");				\
1592		goto error_xmit;					\
1593	}								\
1594	return 0;							\
1595error_xmit:								\
1596	/* We could try again ... */					\
1597	dev_kfree_skb_any(skb);/*we need to free if tx fails*/		\
1598error_build_assoc:							\
1599	return result;							\
1600}
1601
1602wlp_send_assoc(d1, WLP_ASSOC_D1)
1603wlp_send_assoc(c1, WLP_ASSOC_C1)
1604wlp_send_assoc(c3, WLP_ASSOC_C3)
1605
1606int wlp_send_assoc_frame(struct wlp *wlp, struct wlp_wss *wss,
1607			 struct uwb_dev_addr *dev_addr,
1608			 enum wlp_assoc_type type)
1609{
1610	int result = 0;
1611	struct device *dev = &wlp->rc->uwb_dev.dev;
1612	switch (type) {
1613	case WLP_ASSOC_D1:
1614		result = wlp_send_assoc_d1(wlp, wss, dev_addr);
1615		break;
1616	case WLP_ASSOC_C1:
1617		result = wlp_send_assoc_c1(wlp, wss, dev_addr);
1618		break;
1619	case WLP_ASSOC_C3:
1620		result = wlp_send_assoc_c3(wlp, wss, dev_addr);
1621		break;
1622	default:
1623		dev_err(dev, "WLP: Received request to send unknown "
1624			"association message.\n");
1625		result = -EINVAL;
1626		break;
1627	}
1628	return result;
1629}
1630
1631/**
1632 * Handle incoming C1 frame
1633 *
1634 * The frame has already been verified to contain an Association header with
1635 * the correct version number. Parse the incoming frame, construct and send
1636 * a C2 frame in response.
1637 */
1638void wlp_handle_c1_frame(struct work_struct *ws)
1639{
1640	struct wlp_assoc_frame_ctx *frame_ctx = container_of(ws,
1641						  struct wlp_assoc_frame_ctx,
1642						  ws);
1643	struct wlp *wlp = frame_ctx->wlp;
1644	struct wlp_wss *wss = &wlp->wss;
1645	struct device *dev = &wlp->rc->uwb_dev.dev;
1646	struct wlp_frame_assoc *c1 = (void *) frame_ctx->skb->data;
1647	unsigned int len = frame_ctx->skb->len;
1648	struct uwb_dev_addr *src = &frame_ctx->src;
1649	int result;
1650	struct wlp_uuid wssid;
1651	struct sk_buff *resp = NULL;
1652
1653	/* Parse C1 frame */
1654	mutex_lock(&wss->mutex);
1655	result = wlp_get_wssid(wlp, (void *)c1 + sizeof(*c1), &wssid,
1656			       len - sizeof(*c1));
1657	if (result < 0) {
1658		dev_err(dev, "WLP: unable to obtain WSSID from C1 frame.\n");
1659		goto out;
1660	}
1661	if (!memcmp(&wssid, &wss->wssid, sizeof(wssid))
1662	    && wss->state == WLP_WSS_STATE_ACTIVE) {
1663		/* Construct C2 frame */
1664		result = wlp_build_assoc_c2(wlp, wss, &resp);
1665		if (result < 0) {
1666			dev_err(dev, "WLP: Unable to construct C2 message.\n");
1667			goto out;
1668		}
1669	} else {
1670		/* Construct F0 frame */
1671		result = wlp_build_assoc_f0(wlp, &resp, WLP_ASSOC_ERROR_INV);
1672		if (result < 0) {
1673			dev_err(dev, "WLP: Unable to construct F0 message.\n");
1674			goto out;
1675		}
1676	}
1677	/* Send C2 frame */
1678	BUG_ON(wlp->xmit_frame == NULL);
1679	result = wlp->xmit_frame(wlp, resp, src);
1680	if (result < 0) {
1681		dev_err(dev, "WLP: Unable to transmit response association "
1682			"message: %d\n", result);
1683		if (result == -ENXIO)
1684			dev_err(dev, "WLP: Is network interface up? \n");
1685		/* We could try again ... */
1686		dev_kfree_skb_any(resp); /* we need to free if tx fails */
1687	}
1688out:
1689	kfree_skb(frame_ctx->skb);
1690	kfree(frame_ctx);
1691	mutex_unlock(&wss->mutex);
1692}
1693
1694/**
1695 * Handle incoming C3 frame
1696 *
1697 * The frame has already been verified to contain an Association header with
1698 * the correct version number. Parse the incoming frame, construct and send
1699 * a C4 frame in response. If the C3 frame identifies a WSS that is locally
1700 * active then we connect to this neighbor (add it to our EDA cache).
1701 */
1702void wlp_handle_c3_frame(struct work_struct *ws)
1703{
1704	struct wlp_assoc_frame_ctx *frame_ctx = container_of(ws,
1705						  struct wlp_assoc_frame_ctx,
1706						  ws);
1707	struct wlp *wlp = frame_ctx->wlp;
1708	struct wlp_wss *wss = &wlp->wss;
1709	struct device *dev = &wlp->rc->uwb_dev.dev;
1710	struct sk_buff *skb = frame_ctx->skb;
1711	struct uwb_dev_addr *src = &frame_ctx->src;
1712	int result;
1713	struct sk_buff *resp = NULL;
1714	struct wlp_uuid wssid;
1715	u8 tag;
1716	struct uwb_mac_addr virt_addr;
1717
1718	/* Parse C3 frame */
1719	mutex_lock(&wss->mutex);
1720	result = wlp_parse_c3c4_frame(wlp, skb, &wssid, &tag, &virt_addr);
1721	if (result < 0) {
1722		dev_err(dev, "WLP: unable to obtain values from C3 frame.\n");
1723		goto out;
1724	}
1725	if (!memcmp(&wssid, &wss->wssid, sizeof(wssid))
1726	    && wss->state >= WLP_WSS_STATE_ACTIVE) {
1727		result = wlp_eda_update_node(&wlp->eda, src, wss,
1728					     (void *) virt_addr.data, tag,
1729					     WLP_WSS_CONNECTED);
1730		if (result < 0) {
1731			dev_err(dev, "WLP: Unable to update EDA cache "
1732				"with new connected neighbor information.\n");
1733			result = wlp_build_assoc_f0(wlp, &resp,
1734						    WLP_ASSOC_ERROR_INT);
1735			if (result < 0) {
1736				dev_err(dev, "WLP: Unable to construct F0 "
1737					"message.\n");
1738				goto out;
1739			}
1740		} else {
1741			wss->state = WLP_WSS_STATE_CONNECTED;
1742			/* Construct C4 frame */
1743			result = wlp_build_assoc_c4(wlp, wss, &resp);
1744			if (result < 0) {
1745				dev_err(dev, "WLP: Unable to construct C4 "
1746					"message.\n");
1747				goto out;
1748			}
1749		}
1750	} else {
1751		/* Construct F0 frame */
1752		result = wlp_build_assoc_f0(wlp, &resp, WLP_ASSOC_ERROR_INV);
1753		if (result < 0) {
1754			dev_err(dev, "WLP: Unable to construct F0 message.\n");
1755			goto out;
1756		}
1757	}
1758	/* Send C4 frame */
1759	BUG_ON(wlp->xmit_frame == NULL);
1760	result = wlp->xmit_frame(wlp, resp, src);
1761	if (result < 0) {
1762		dev_err(dev, "WLP: Unable to transmit response association "
1763			"message: %d\n", result);
1764		if (result == -ENXIO)
1765			dev_err(dev, "WLP: Is network interface up? \n");
1766		/* We could try again ... */
1767		dev_kfree_skb_any(resp); /* we need to free if tx fails */
1768	}
1769out:
1770	kfree_skb(frame_ctx->skb);
1771	kfree(frame_ctx);
1772	mutex_unlock(&wss->mutex);
1773}
1774