GUI: Fix Tomato RAF theme for all builds. Compilation typo.
[tomato.git] / release / src-rt-6.x.4708 / linux / linux-2.6.36 / drivers / uwb / wlp / messages.c
blob4281063eeafbdf8355f36717bfd2a4696c88366c
3 #include <linux/wlp.h>
4 #include <linux/slab.h>
6 #include "wlp-internal.h"
8 static
9 const 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",
29 static const char *wlp_assoc_frame_str(unsigned id)
31 if (id >= ARRAY_SIZE(__wlp_assoc_frame))
32 return "unknown association frame";
33 return __wlp_assoc_frame[id];
36 static 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",
54 static const char *wlp_assc_error_str(unsigned id)
56 if (id >= ARRAY_SIZE(__wlp_assc_error))
57 return "unknown WLP association error";
58 return __wlp_assc_error[id];
61 static inline void wlp_set_attr_hdr(struct wlp_attr_hdr *hdr, unsigned type,
62 size_t len)
64 hdr->type = cpu_to_le16(type);
65 hdr->length = cpu_to_le16(len);
69 * Populate fields of a constant sized attribute
71 * @returns: total size of attribute including size of new value
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.
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.
82 #define wlp_set(type, type_code, name) \
83 static 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); \
91 #define wlp_pset(type, type_code, name) \
92 static 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); \
101 * Populate fields of a variable attribute
103 * @returns: total size of attribute including size of new value
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.
109 #define wlp_vset(type, type_code, name) \
110 static size_t wlp_set_##name(struct wlp_attr_##name *attr, type value, \
111 size_t len) \
113 wlp_set_attr_hdr(&attr->hdr, type_code, len); \
114 memcpy(attr->name, value, len); \
115 return sizeof(*attr) + len; \
118 wlp_vset(char *, WLP_ATTR_DEV_NAME, dev_name)
119 wlp_vset(char *, WLP_ATTR_MANUF, manufacturer)
120 wlp_set(enum wlp_assoc_type, WLP_ATTR_MSG_TYPE, msg_type)
121 wlp_vset(char *, WLP_ATTR_MODEL_NAME, model_name)
122 wlp_vset(char *, WLP_ATTR_MODEL_NR, model_nr)
123 wlp_vset(char *, WLP_ATTR_SERIAL, serial)
124 wlp_vset(char *, WLP_ATTR_WSS_NAME, wss_name)
125 wlp_pset(struct wlp_uuid *, WLP_ATTR_UUID_E, uuid_e)
126 wlp_pset(struct wlp_uuid *, WLP_ATTR_UUID_R, uuid_r)
127 wlp_pset(struct wlp_uuid *, WLP_ATTR_WSSID, wssid)
128 wlp_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)*/
130 wlp_set(u8, WLP_ATTR_WLP_VER, version)
131 wlp_set(enum wlp_assc_error, WLP_ATTR_WLP_ASSC_ERR, wlp_assc_err)
132 wlp_set(enum wlp_wss_sel_mthd, WLP_ATTR_WSS_SEL_MTHD, wss_sel_mthd)
133 wlp_set(u8, WLP_ATTR_ACC_ENRL, accept_enrl)
134 wlp_set(u8, WLP_ATTR_WSS_SEC_STAT, wss_sec_status)
135 wlp_pset(struct uwb_mac_addr *, WLP_ATTR_WSS_BCAST, wss_bcast)
136 wlp_pset(struct wlp_nonce *, WLP_ATTR_ENRL_NONCE, enonce)
137 wlp_pset(struct wlp_nonce *, WLP_ATTR_REG_NONCE, rnonce)
138 wlp_set(u8, WLP_ATTR_WSS_TAG, wss_tag)
139 wlp_pset(struct uwb_mac_addr *, WLP_ATTR_WSS_VIRT, wss_virt)
142 * Fill in the WSS information attributes
144 * We currently only support one WSS, and this is assumed in this function
145 * that can populate only one WSS information attribute.
147 static size_t wlp_set_wss_info(struct wlp_attr_wss_info *attr,
148 struct wlp_wss *wss)
150 size_t datalen;
151 void *ptr = attr->wss_info;
152 size_t used = sizeof(*attr);
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;
165 * Verify attribute header
167 * @hdr: Pointer to attribute header that will be verified.
168 * @type: Expected attribute type.
169 * @len: Expected length of attribute value (excluding header).
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.
175 static int wlp_check_attr_hdr(struct wlp *wlp, struct wlp_attr_hdr *hdr,
176 enum wlp_attr_type type, unsigned len)
178 struct device *dev = &wlp->rc->uwb_dev.dev;
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;
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;
190 return 0;
194 * Check if header of WSS information attribute valid
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
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.
208 static int wlp_check_wss_info_attr_hdr(struct wlp *wlp,
209 struct wlp_attr_hdr *hdr, size_t buflen)
211 struct device *dev = &wlp->rc->uwb_dev.dev;
212 size_t len;
213 int result = 0;
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;
221 if (le16_to_cpu(hdr->type) != WLP_ATTR_WSS_INFO) {
222 /* WSS information is optional */
223 result = -ENODATA;
224 goto out;
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;
234 result = len;
235 out:
236 return result;
240 static 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)
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;
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;
258 memcpy(value, (void *)attr_hdr + sizeof(*attr_hdr), value_len);
259 return attr_len;
262 static 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)
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;
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;
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;
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;
293 memcpy(value, (void *)attr_hdr + sizeof(*attr_hdr), len);
294 return sizeof(*attr_hdr) + len;
298 * Get value of attribute from fixed size attribute field.
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.
306 * The size and type of the value is known by the type of the attribute.
308 #define wlp_get(type, type_code, name) \
309 ssize_t wlp_get_##name(struct wlp *wlp, struct wlp_attr_##name *attr, \
310 type *value, ssize_t buflen) \
312 return wlp_get_attribute(wlp, (type_code), &attr->hdr, \
313 value, sizeof(*value), buflen); \
316 #define wlp_get_sparse(type, type_code, name) \
317 static wlp_get(type, type_code, name)
320 * Get value of attribute from variable sized attribute field.
322 * @max: The maximum size of this attribute. This value is dictated by
323 * the maximum value from the WLP specification.
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.
332 #define wlp_vget(type_val, type_code, name, max) \
333 static ssize_t wlp_get_##name(struct wlp *wlp, \
334 struct wlp_attr_##name *attr, \
335 type_val *value, ssize_t buflen) \
337 return wlp_vget_attribute(wlp, (type_code), &attr->hdr, \
338 value, (max), buflen); \
341 wlp_get(u8, WLP_ATTR_WLP_VER, version)
342 wlp_get_sparse(enum wlp_wss_sel_mthd, WLP_ATTR_WSS_SEL_MTHD, wss_sel_mthd)
343 wlp_get_sparse(struct wlp_dev_type, WLP_ATTR_PRI_DEV_TYPE, prim_dev_type)
344 wlp_get_sparse(enum wlp_assc_error, WLP_ATTR_WLP_ASSC_ERR, wlp_assc_err)
345 wlp_get_sparse(struct wlp_uuid, WLP_ATTR_UUID_E, uuid_e)
346 wlp_get_sparse(struct wlp_uuid, WLP_ATTR_UUID_R, uuid_r)
347 wlp_get(struct wlp_uuid, WLP_ATTR_WSSID, wssid)
348 wlp_get_sparse(u8, WLP_ATTR_ACC_ENRL, accept_enrl)
349 wlp_get_sparse(u8, WLP_ATTR_WSS_SEC_STAT, wss_sec_status)
350 wlp_get_sparse(struct uwb_mac_addr, WLP_ATTR_WSS_BCAST, wss_bcast)
351 wlp_get_sparse(u8, WLP_ATTR_WSS_TAG, wss_tag)
352 wlp_get_sparse(struct uwb_mac_addr, WLP_ATTR_WSS_VIRT, wss_virt)
353 wlp_get_sparse(struct wlp_nonce, WLP_ATTR_ENRL_NONCE, enonce)
354 wlp_get_sparse(struct wlp_nonce, WLP_ATTR_REG_NONCE, rnonce)
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.
364 wlp_vget(char, WLP_ATTR_WSS_NAME, wss_name,
365 FIELD_SIZEOF(struct wlp_wss, name) - 1)
366 wlp_vget(char, WLP_ATTR_DEV_NAME, dev_name,
367 FIELD_SIZEOF(struct wlp_device_info, name) - 1)
368 wlp_vget(char, WLP_ATTR_MANUF, manufacturer,
369 FIELD_SIZEOF(struct wlp_device_info, manufacturer) - 1)
370 wlp_vget(char, WLP_ATTR_MODEL_NAME, model_name,
371 FIELD_SIZEOF(struct wlp_device_info, model_name) - 1)
372 wlp_vget(char, WLP_ATTR_MODEL_NR, model_nr,
373 FIELD_SIZEOF(struct wlp_device_info, model_nr) - 1)
374 wlp_vget(char, WLP_ATTR_SERIAL, serial,
375 FIELD_SIZEOF(struct wlp_device_info, serial) - 1)
378 * Retrieve WSS Name, Accept enroll, Secure status, Broadcast from WSS info
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
385 * Although the WSSID attribute forms part of the WSS info attribute it is
386 * retrieved separately and stored in a different location.
388 static 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)
393 struct device *dev = &wlp->rc->uwb_dev.dev;
394 void *ptr = attr;
395 size_t used = 0;
396 ssize_t result = -EINVAL;
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;
404 used += result;
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;
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;
419 used += result;
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;
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;
434 used += result;
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;
443 used += result;
444 result = used;
445 error_parse:
446 return result;
450 * Create a new WSSID entry for the neighbor, allocate temporary storage
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.
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.
460 static struct wlp_wssid_e *wlp_create_wssid_e(struct wlp *wlp,
461 struct wlp_neighbor_e *neighbor)
463 struct device *dev = &wlp->rc->uwb_dev.dev;
464 struct wlp_wssid_e *wssid_e;
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;
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;
480 list_add(&wssid_e->node, &neighbor->wssid);
481 error_alloc:
482 return wssid_e;
486 * Parse WSS information attribute
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
494 * memory for @wssid and @wss_info must be allocated when calling this
496 static 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)
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;
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;
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;
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;
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;
535 result = used;
536 out:
537 return result;
541 * Retrieve WSS info from association frame
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
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.
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.
562 * Association frame is process with nbmutex held. The list access is safe.
564 static 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)
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];
579 if (buflen < 0)
580 goto out;
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;
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;
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;
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;
628 wssid_e->wssid = wssid;
629 *wssid_e->info = wss_info;
631 used += result;
633 result = used;
634 error_parse:
635 if (result < 0 && !enroll) /* this was a discovery */
636 wlp_remove_neighbor_tmp_info(neighbor);
637 out:
638 return result;
643 * Parse WSS information attributes into cache for discovery
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
649 static 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)
654 return wlp_get_all_wss_info(wlp, attr, neighbor, NULL, buflen);
658 * Parse WSS information attributes into WSS struct for enrollment
660 * @attr: the first WSS information attribute in message
661 * @wss: the WSS that will be enrolled
662 * @buflen: size of the input buffer
664 static 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)
668 return wlp_get_all_wss_info(wlp, attr, NULL, wss, buflen);
672 * Construct a D1 association frame
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).
681 static int wlp_build_assoc_d1(struct wlp *wlp, struct wlp_wss *wss,
682 struct sk_buff **skb)
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;
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;
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;
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;
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;
747 error:
748 return result;
752 * Construct a D2 association frame
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).
761 static
762 int wlp_build_assoc_d2(struct wlp *wlp, struct wlp_wss *wss,
763 struct sk_buff **skb, struct wlp_uuid *uuid_e)
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;
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;
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;
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;
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;
836 error:
837 return result;
841 * Allocate memory for and populate fields of F0 association frame
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.
847 static
848 int wlp_build_assoc_f0(struct wlp *wlp, struct sk_buff **skb,
849 enum wlp_assc_error error)
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;
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;
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;
881 error_alloc:
882 return result;
886 * Parse F0 frame
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.
892 int wlp_parse_f0(struct wlp *wlp, struct sk_buff *skb)
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];
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;
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;
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;
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;
932 error_parse:
933 return result;
937 * Retrieve variable device information from association message
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.
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.
949 static
950 int wlp_get_variable_info(struct wlp *wlp, void *data,
951 struct wlp_device_info *dev_info, ssize_t len)
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
1063 out:
1064 return used;
1065 error_parse:
1066 return -EINVAL;
1070 * Parse incoming D1 frame, populate attribute values
1072 * Caller provides pointers to memory already allocated for attributes
1073 * expected in the D1 frame. These variables will be populated.
1075 static
1076 int 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)
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;
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;
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;
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;
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;
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;
1125 result = 0;
1126 error_parse:
1127 return result;
1130 * Handle incoming D1 frame
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.
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.
1139 void wlp_handle_d1_frame(struct work_struct *ws)
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;
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;
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;
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;
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 */
1197 out:
1198 kfree(frame_ctx);
1199 mutex_unlock(&wlp->mutex);
1200 mutex_unlock(&wss->mutex);
1204 * Parse incoming D2 frame, create and populate temporary cache
1206 * @skb: socket buffer in which D2 frame can be found
1207 * @neighbor: the neighbor that sent the D2 frame
1209 * Will allocate memory for temporary storage of information learned during
1210 * discovery.
1212 int wlp_parse_d2_frame_to_cache(struct wlp *wlp, struct sk_buff *skb,
1213 struct wlp_neighbor_e *neighbor)
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;
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;
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;
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;
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;
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;
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;
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;
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;
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;
1288 result = 0;
1289 error_parse:
1290 if (result < 0)
1291 wlp_remove_neighbor_tmp_info(neighbor);
1292 return result;
1296 * Parse incoming D2 frame, populate attribute values of WSS bein enrolled in
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
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.
1309 int 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)
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];
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;
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;
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;
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;
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;
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;
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;
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;
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;
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);
1400 result = -EINVAL;
1401 goto error_parse;
1403 result = 0;
1404 error_parse:
1405 return result;
1409 * Parse C3/C4 frame into provided variables
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.
1416 * Calling function has to allocate memory for these values.
1418 * skb contains a valid C3/C4 frame, return the individual fields of this
1419 * frame in the provided variables.
1421 int 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)
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;
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;
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;
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;
1454 error_parse:
1455 return result;
1459 * Allocate memory for and populate fields of C1 or C2 association frame
1461 * The C1 and C2 association frames appear identical - except for the type.
1463 static
1464 int wlp_build_assoc_c1c2(struct wlp *wlp, struct wlp_wss *wss,
1465 struct sk_buff **skb, enum wlp_assoc_type type)
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;
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;
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;
1491 error_alloc:
1492 return result;
1496 static
1497 int wlp_build_assoc_c1(struct wlp *wlp, struct wlp_wss *wss,
1498 struct sk_buff **skb)
1500 return wlp_build_assoc_c1c2(wlp, wss, skb, WLP_ASSOC_C1);
1503 static
1504 int wlp_build_assoc_c2(struct wlp *wlp, struct wlp_wss *wss,
1505 struct sk_buff **skb)
1507 return wlp_build_assoc_c1c2(wlp, wss, skb, WLP_ASSOC_C2);
1512 * Allocate memory for and populate fields of C3 or C4 association frame
1514 * The C3 and C4 association frames appear identical - except for the type.
1516 static
1517 int wlp_build_assoc_c3c4(struct wlp *wlp, struct wlp_wss *wss,
1518 struct sk_buff **skb, enum wlp_assoc_type type)
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;
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;
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;
1548 error_alloc:
1549 return result;
1552 static
1553 int wlp_build_assoc_c3(struct wlp *wlp, struct wlp_wss *wss,
1554 struct sk_buff **skb)
1556 return wlp_build_assoc_c3c4(wlp, wss, skb, WLP_ASSOC_C3);
1559 static
1560 int wlp_build_assoc_c4(struct wlp *wlp, struct wlp_wss *wss,
1561 struct sk_buff **skb)
1563 return wlp_build_assoc_c3c4(wlp, wss, skb, WLP_ASSOC_C4);
1567 #define wlp_send_assoc(type, id) \
1568 static int wlp_send_assoc_##type(struct wlp *wlp, struct wlp_wss *wss, \
1569 struct uwb_dev_addr *dev_addr) \
1571 struct device *dev = &wlp->rc->uwb_dev.dev; \
1572 int result; \
1573 struct sk_buff *skb = NULL; \
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; \
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; \
1594 return 0; \
1595 error_xmit: \
1596 /* We could try again ... */ \
1597 dev_kfree_skb_any(skb);/*we need to free if tx fails*/ \
1598 error_build_assoc: \
1599 return result; \
1602 wlp_send_assoc(d1, WLP_ASSOC_D1)
1603 wlp_send_assoc(c1, WLP_ASSOC_C1)
1604 wlp_send_assoc(c3, WLP_ASSOC_C3)
1606 int wlp_send_assoc_frame(struct wlp *wlp, struct wlp_wss *wss,
1607 struct uwb_dev_addr *dev_addr,
1608 enum wlp_assoc_type type)
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;
1628 return result;
1632 * Handle incoming C1 frame
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.
1638 void wlp_handle_c1_frame(struct work_struct *ws)
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;
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;
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;
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;
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 */
1688 out:
1689 kfree_skb(frame_ctx->skb);
1690 kfree(frame_ctx);
1691 mutex_unlock(&wss->mutex);
1695 * Handle incoming C3 frame
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).
1702 void wlp_handle_c3_frame(struct work_struct *ws)
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;
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;
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;
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;
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;
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 */
1769 out:
1770 kfree_skb(frame_ctx->skb);
1771 kfree(frame_ctx);
1772 mutex_unlock(&wss->mutex);