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