2 * WiMedia Logical Link Control Protocol (WLP)
3 * Message construction and parsing
5 * Copyright (C) 2007 Intel Corporation
6 * Reinette Chatre <reinette.chatre@intel.com>
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.
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.
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
26 #include <linux/wlp.h>
28 #include "wlp-internal.h"
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",
51 static const char *wlp_assoc_frame_str(unsigned id)
53 if (id >= ARRAY_SIZE(__wlp_assoc_frame))
54 return "unknown association frame";
55 return __wlp_assoc_frame[id];
58 static const char *__wlp_assc_error[] = {
60 "Authenticator Failure",
61 "Rogue activity suspected",
64 "Registrar not ready",
65 "Invalid WSS selection",
67 "Enrollment session timeout",
68 "Device password invalid",
69 "Unsupported version",
72 "Numeric comparison failure",
73 "Waiting for user input",
76 static const char *wlp_assc_error_str(unsigned id)
78 if (id >= ARRAY_SIZE(__wlp_assc_error))
79 return "unknown WLP association error";
80 return __wlp_assc_error[id];
83 static inline void wlp_set_attr_hdr(struct wlp_attr_hdr *hdr, unsigned type,
86 hdr->type = cpu_to_le16(type);
87 hdr->length = cpu_to_le16(len);
91 * Populate fields of a constant sized attribute
93 * @returns: total size of attribute including size of new value
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
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.
104 #define wlp_set(type, type_code, name) \
105 static size_t wlp_set_##name(struct wlp_attr_##name *attr, type value) \
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); \
113 #define wlp_pset(type, type_code, name) \
114 static size_t wlp_set_##name(struct wlp_attr_##name *attr, type value) \
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); \
123 * Populate fields of a variable attribute
125 * @returns: total size of attribute including size of new value
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.
131 #define wlp_vset(type, type_code, name) \
132 static size_t wlp_set_##name(struct wlp_attr_##name *attr, type value, \
135 wlp_set_attr_hdr(&attr->hdr, type_code, len); \
136 memcpy(attr->name, value, len); \
137 return sizeof(*attr) + len; \
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)
164 * Fill in the WSS information attributes
166 * We currently only support one WSS, and this is assumed in this function
167 * that can populate only one WSS information attribute.
169 static size_t wlp_set_wss_info(struct wlp_attr_wss_info *attr,
173 void *ptr = attr->wss_info;
174 size_t used = sizeof(*attr);
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;
187 * Verify attribute header
189 * @hdr: Pointer to attribute header that will be verified.
190 * @type: Expected attribute type.
191 * @len: Expected length of attribute value (excluding header).
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.
197 static int wlp_check_attr_hdr(struct wlp *wlp, struct wlp_attr_hdr *hdr,
198 enum wlp_attr_type type, unsigned len)
200 struct device *dev = &wlp->rc->uwb_dev.dev;
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));
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));
216 * Check if header of WSS information attribute valid
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
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.
230 static int wlp_check_wss_info_attr_hdr(struct wlp *wlp,
231 struct wlp_attr_hdr *hdr, size_t buflen)
233 struct device *dev = &wlp->rc->uwb_dev.dev;
237 if (buflen < sizeof(*hdr)) {
238 dev_err(dev, "WLP: Not enough space in buffer to parse"
239 " WSS information attribute header.\n");
243 if (le16_to_cpu(hdr->type) != WLP_ATTR_WSS_INFO) {
244 /* WSS information is optional */
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));
263 * Get value of attribute from fixed size attribute field.
265 * @attr: Pointer to attribute field.
266 * @value: Pointer to variable in which attribute value will be placed.
267 * @buflen: Size of buffer in which attribute field (including header)
269 * @returns: Amount of given buffer consumed by parsing for this attribute.
271 * The size and type of the value is known by the type of the attribute.
273 #define wlp_get(type, type_code, name) \
274 ssize_t wlp_get_##name(struct wlp *wlp, struct wlp_attr_##name *attr, \
275 type *value, ssize_t buflen) \
277 struct device *dev = &wlp->rc->uwb_dev.dev; \
280 if (buflen < sizeof(*attr)) { \
281 dev_err(dev, "WLP: Not enough space in buffer to parse" \
282 " attribute field. Need %d, received %zu\n", \
283 (int)sizeof(*attr), buflen); \
286 if (wlp_check_attr_hdr(wlp, &attr->hdr, type_code, \
287 sizeof(attr->name)) < 0) { \
288 dev_err(dev, "WLP: Header verification failed. \n"); \
291 *value = attr->name; \
292 return sizeof(*attr); \
295 #define wlp_get_sparse(type, type_code, name) \
296 static wlp_get(type, type_code, name)
299 * Get value of attribute from variable sized attribute field.
301 * @max: The maximum size of this attribute. This value is dictated by
302 * the maximum value from the WLP specification.
304 * @attr: Pointer to attribute field.
305 * @value: Pointer to variable that will contain the value. The memory
306 * must already have been allocated for this value.
307 * @buflen: Size of buffer in which attribute field (including header)
309 * @returns: Amount of given bufferconsumed by parsing for this attribute.
311 #define wlp_vget(type_val, type_code, name, max) \
312 static ssize_t wlp_get_##name(struct wlp *wlp, \
313 struct wlp_attr_##name *attr, \
314 type_val *value, ssize_t buflen) \
316 struct device *dev = &wlp->rc->uwb_dev.dev; \
320 if (buflen < sizeof(*attr)) { \
321 dev_err(dev, "WLP: Not enough space in buffer to parse" \
325 if (le16_to_cpu(attr->hdr.type) != type_code) { \
326 dev_err(dev, "WLP: Unexpected attribute type. Got %u, " \
327 "expected %u.\n", le16_to_cpu(attr->hdr.type), \
331 len = le16_to_cpu(attr->hdr.length); \
333 dev_err(dev, "WLP: Attribute larger than maximum " \
334 "allowed. Received %zu, max is %d.\n", len, \
338 if (buflen < sizeof(*attr) + len) { \
339 dev_err(dev, "WLP: Not enough space in buffer to parse "\
340 "variable data.\n"); \
343 memcpy(value, (void *) attr + sizeof(*attr), len); \
344 return sizeof(*attr) + len; \
347 wlp_get(u8, WLP_ATTR_WLP_VER, version)
348 wlp_get_sparse(enum wlp_wss_sel_mthd, WLP_ATTR_WSS_SEL_MTHD, wss_sel_mthd)
349 wlp_get_sparse(struct wlp_dev_type, WLP_ATTR_PRI_DEV_TYPE, prim_dev_type)
350 wlp_get_sparse(enum wlp_assc_error, WLP_ATTR_WLP_ASSC_ERR, wlp_assc_err)
351 wlp_get_sparse(struct wlp_uuid, WLP_ATTR_UUID_E, uuid_e)
352 wlp_get_sparse(struct wlp_uuid, WLP_ATTR_UUID_R, uuid_r)
353 wlp_get(struct wlp_uuid, WLP_ATTR_WSSID, wssid)
354 wlp_get_sparse(u8, WLP_ATTR_ACC_ENRL, accept_enrl)
355 wlp_get_sparse(u8, WLP_ATTR_WSS_SEC_STAT, wss_sec_status)
356 wlp_get_sparse(struct uwb_mac_addr, WLP_ATTR_WSS_BCAST, wss_bcast)
357 wlp_get_sparse(u8, WLP_ATTR_WSS_TAG, wss_tag)
358 wlp_get_sparse(struct uwb_mac_addr, WLP_ATTR_WSS_VIRT, wss_virt)
359 wlp_get_sparse(struct wlp_nonce, WLP_ATTR_ENRL_NONCE, enonce)
360 wlp_get_sparse(struct wlp_nonce, WLP_ATTR_REG_NONCE, rnonce)
362 /* The buffers for the device info attributes can be found in the
363 * wlp_device_info struct. These buffers contain one byte more than the
364 * max allowed by the spec - this is done to be able to add the
365 * terminating \0 for user display. This terminating byte is not required
366 * in the actual attribute field (because it has a length field) so the
367 * maximum allowed for this value is one less than its size in the
370 wlp_vget(char, WLP_ATTR_WSS_NAME, wss_name,
371 FIELD_SIZEOF(struct wlp_wss, name) - 1)
372 wlp_vget(char, WLP_ATTR_DEV_NAME, dev_name,
373 FIELD_SIZEOF(struct wlp_device_info, name) - 1)
374 wlp_vget(char, WLP_ATTR_MANUF, manufacturer,
375 FIELD_SIZEOF(struct wlp_device_info, manufacturer) - 1)
376 wlp_vget(char, WLP_ATTR_MODEL_NAME, model_name,
377 FIELD_SIZEOF(struct wlp_device_info, model_name) - 1)
378 wlp_vget(char, WLP_ATTR_MODEL_NR, model_nr,
379 FIELD_SIZEOF(struct wlp_device_info, model_nr) - 1)
380 wlp_vget(char, WLP_ATTR_SERIAL, serial,
381 FIELD_SIZEOF(struct wlp_device_info, serial) - 1)
384 * Retrieve WSS Name, Accept enroll, Secure status, Broadcast from WSS info
386 * @attr: pointer to WSS name attribute in WSS information attribute field
387 * @info: structure that will be populated with data from WSS information
388 * field (WSS name, Accept enroll, secure status, broadcast address)
389 * @buflen: size of buffer
391 * Although the WSSID attribute forms part of the WSS info attribute it is
392 * retrieved separately and stored in a different location.
394 static ssize_t wlp_get_wss_info_attrs(struct wlp *wlp,
395 struct wlp_attr_hdr *attr,
396 struct wlp_wss_tmp_info *info,
399 struct device *dev = &wlp->rc->uwb_dev.dev;
402 ssize_t result = -EINVAL;
404 result = wlp_get_wss_name(wlp, ptr, info->name, buflen);
406 dev_err(dev, "WLP: unable to obtain WSS name from "
407 "WSS info in D2 message.\n");
412 result = wlp_get_accept_enrl(wlp, ptr + used, &info->accept_enroll,
415 dev_err(dev, "WLP: unable to obtain accepting "
416 "enrollment from WSS info in D2 message.\n");
419 if (info->accept_enroll != 0 && info->accept_enroll != 1) {
420 dev_err(dev, "WLP: invalid value for accepting "
421 "enrollment in D2 message.\n");
427 result = wlp_get_wss_sec_status(wlp, ptr + used, &info->sec_status,
430 dev_err(dev, "WLP: unable to obtain secure "
431 "status from WSS info in D2 message.\n");
434 if (info->sec_status != 0 && info->sec_status != 1) {
435 dev_err(dev, "WLP: invalid value for secure "
436 "status in D2 message.\n");
442 result = wlp_get_wss_bcast(wlp, ptr + used, &info->bcast,
445 dev_err(dev, "WLP: unable to obtain broadcast "
446 "address from WSS info in D2 message.\n");
456 * Create a new WSSID entry for the neighbor, allocate temporary storage
458 * Each neighbor can have many WSS active. We maintain a list of WSSIDs
459 * advertised by neighbor. During discovery we also cache information about
460 * these WSS in temporary storage.
462 * The temporary storage will be removed after it has been used (eg.
463 * displayed to user), the wssid element will be removed from the list when
464 * the neighbor is rediscovered or when it disappears.
466 static struct wlp_wssid_e *wlp_create_wssid_e(struct wlp *wlp,
467 struct wlp_neighbor_e *neighbor)
469 struct device *dev = &wlp->rc->uwb_dev.dev;
470 struct wlp_wssid_e *wssid_e;
472 wssid_e = kzalloc(sizeof(*wssid_e), GFP_KERNEL);
473 if (wssid_e == NULL) {
474 dev_err(dev, "WLP: unable to allocate memory "
475 "for WSS information.\n");
478 wssid_e->info = kzalloc(sizeof(struct wlp_wss_tmp_info), GFP_KERNEL);
479 if (wssid_e->info == NULL) {
480 dev_err(dev, "WLP: unable to allocate memory "
481 "for temporary WSS information.\n");
486 list_add(&wssid_e->node, &neighbor->wssid);
492 * Parse WSS information attribute
494 * @attr: pointer to WSS information attribute header
495 * @buflen: size of buffer in which WSS information attribute appears
496 * @wssid: will place wssid from WSS info attribute in this location
497 * @wss_info: will place other information from WSS information attribute
500 * memory for @wssid and @wss_info must be allocated when calling this
502 static ssize_t wlp_get_wss_info(struct wlp *wlp, struct wlp_attr_wss_info *attr,
503 size_t buflen, struct wlp_uuid *wssid,
504 struct wlp_wss_tmp_info *wss_info)
506 struct device *dev = &wlp->rc->uwb_dev.dev;
512 result = wlp_check_wss_info_attr_hdr(wlp, (struct wlp_attr_hdr *)attr,
517 used = sizeof(*attr);
520 result = wlp_get_wssid(wlp, ptr + used, wssid, buflen - used);
522 dev_err(dev, "WLP: unable to obtain WSSID from WSS info.\n");
526 result = wlp_get_wss_info_attrs(wlp, ptr + used, wss_info,
529 dev_err(dev, "WLP: unable to obtain WSS information "
530 "from WSS information attributes. \n");
534 if (len + sizeof(*attr) != used) {
535 dev_err(dev, "WLP: Amount of data parsed does not "
536 "match length field. Parsed %zu, length "
537 "field %zu. \n", used, len);
547 * Retrieve WSS info from association frame
549 * @attr: pointer to WSS information attribute
550 * @neighbor: ptr to neighbor being discovered, NULL if enrollment in
552 * @wss: ptr to WSS being enrolled in, NULL if discovery in progress
553 * @buflen: size of buffer in which WSS information appears
555 * The WSS information attribute appears in the D2 association message.
556 * This message is used in two ways: to discover all neighbors or to enroll
557 * into a WSS activated by a neighbor. During discovery we only want to
558 * store the WSS info in a cache, to be deleted right after it has been
559 * used (eg. displayed to the user). During enrollment we store the WSS
560 * information for the lifetime of enrollment.
562 * During discovery we are interested in all WSS information, during
563 * enrollment we are only interested in the WSS being enrolled in. Even so,
564 * when in enrollment we keep parsing the message after finding the WSS of
565 * interest, this simplifies the calling routine in that it can be sure
566 * that all WSS information attributes have been parsed out of the message.
568 * Association frame is process with nbmutex held. The list access is safe.
570 static ssize_t wlp_get_all_wss_info(struct wlp *wlp,
571 struct wlp_attr_wss_info *attr,
572 struct wlp_neighbor_e *neighbor,
573 struct wlp_wss *wss, ssize_t buflen)
575 struct device *dev = &wlp->rc->uwb_dev.dev;
577 ssize_t result = -EINVAL;
578 struct wlp_attr_wss_info *cur;
579 struct wlp_uuid wssid;
580 struct wlp_wss_tmp_info wss_info;
581 unsigned enroll; /* 0 - discovery to cache, 1 - enrollment */
582 struct wlp_wssid_e *wssid_e;
583 char buf[WLP_WSS_UUID_STRSIZE];
588 if (neighbor != NULL && wss == NULL)
589 enroll = 0; /* discovery */
590 else if (wss != NULL && neighbor == NULL)
591 enroll = 1; /* enrollment */
596 while (buflen - used > 0) {
597 memset(&wss_info, 0, sizeof(wss_info));
598 cur = (void *)cur + used;
599 result = wlp_get_wss_info(wlp, cur, buflen - used, &wssid,
601 if (result == -ENODATA) {
604 } else if (result < 0) {
605 dev_err(dev, "WLP: Unable to parse WSS information "
606 "from WSS information attribute. \n");
610 if (enroll && !memcmp(&wssid, &wss->wssid, sizeof(wssid))) {
611 if (wss_info.accept_enroll != 1) {
612 dev_err(dev, "WLP: Requested WSS does "
613 "not accept enrollment.\n");
617 memcpy(wss->name, wss_info.name, sizeof(wss->name));
618 wss->bcast = wss_info.bcast;
619 wss->secure_status = wss_info.sec_status;
620 wss->accept_enroll = wss_info.accept_enroll;
621 wss->state = WLP_WSS_STATE_PART_ENROLLED;
622 wlp_wss_uuid_print(buf, sizeof(buf), &wssid);
623 dev_dbg(dev, "WLP: Found WSS %s. Enrolling.\n", buf);
625 wssid_e = wlp_create_wssid_e(wlp, neighbor);
626 if (wssid_e == NULL) {
627 dev_err(dev, "WLP: Cannot create new WSSID "
628 "entry for neighbor %02x:%02x.\n",
629 neighbor->uwb_dev->dev_addr.data[1],
630 neighbor->uwb_dev->dev_addr.data[0]);
634 wssid_e->wssid = wssid;
635 *wssid_e->info = wss_info;
641 if (result < 0 && !enroll) /* this was a discovery */
642 wlp_remove_neighbor_tmp_info(neighbor);
649 * Parse WSS information attributes into cache for discovery
651 * @attr: the first WSS information attribute in message
652 * @neighbor: the neighbor whose cache will be populated
653 * @buflen: size of the input buffer
655 static ssize_t wlp_get_wss_info_to_cache(struct wlp *wlp,
656 struct wlp_attr_wss_info *attr,
657 struct wlp_neighbor_e *neighbor,
660 return wlp_get_all_wss_info(wlp, attr, neighbor, NULL, buflen);
664 * Parse WSS information attributes into WSS struct for enrollment
666 * @attr: the first WSS information attribute in message
667 * @wss: the WSS that will be enrolled
668 * @buflen: size of the input buffer
670 static ssize_t wlp_get_wss_info_to_enroll(struct wlp *wlp,
671 struct wlp_attr_wss_info *attr,
672 struct wlp_wss *wss, ssize_t buflen)
674 return wlp_get_all_wss_info(wlp, attr, NULL, wss, buflen);
678 * Construct a D1 association frame
680 * We use the radio control functions to determine the values of the device
681 * properties. These are of variable length and the total space needed is
682 * tallied first before we start constructing the message. The radio
683 * control functions return strings that are terminated with \0. This
684 * character should not be included in the message (there is a length field
685 * accompanying it in the attribute).
687 static int wlp_build_assoc_d1(struct wlp *wlp, struct wlp_wss *wss,
688 struct sk_buff **skb)
691 struct device *dev = &wlp->rc->uwb_dev.dev;
693 struct wlp_device_info *info;
695 struct wlp_frame_assoc *_d1;
696 struct sk_buff *_skb;
699 if (wlp->dev_info == NULL) {
700 result = __wlp_setup_device_info(wlp);
702 dev_err(dev, "WLP: Unable to setup device "
703 "information for D1 message.\n");
707 info = wlp->dev_info;
708 _skb = dev_alloc_skb(sizeof(*_d1)
709 + sizeof(struct wlp_attr_uuid_e)
710 + sizeof(struct wlp_attr_wss_sel_mthd)
711 + sizeof(struct wlp_attr_dev_name)
713 + sizeof(struct wlp_attr_manufacturer)
714 + strlen(info->manufacturer)
715 + sizeof(struct wlp_attr_model_name)
716 + strlen(info->model_name)
717 + sizeof(struct wlp_attr_model_nr)
718 + strlen(info->model_nr)
719 + sizeof(struct wlp_attr_serial)
720 + strlen(info->serial)
721 + sizeof(struct wlp_attr_prim_dev_type)
722 + sizeof(struct wlp_attr_wlp_assc_err));
724 dev_err(dev, "WLP: Cannot allocate memory for association "
729 _d1 = (void *) _skb->data;
730 _d1->hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID);
731 _d1->hdr.type = WLP_FRAME_ASSOCIATION;
732 _d1->type = WLP_ASSOC_D1;
734 wlp_set_version(&_d1->version, WLP_VERSION);
735 wlp_set_msg_type(&_d1->msg_type, WLP_ASSOC_D1);
737 used = wlp_set_uuid_e(d1_itr, &wlp->uuid);
738 used += wlp_set_wss_sel_mthd(d1_itr + used, WLP_WSS_REG_SELECT);
739 used += wlp_set_dev_name(d1_itr + used, info->name,
741 used += wlp_set_manufacturer(d1_itr + used, info->manufacturer,
742 strlen(info->manufacturer));
743 used += wlp_set_model_name(d1_itr + used, info->model_name,
744 strlen(info->model_name));
745 used += wlp_set_model_nr(d1_itr + used, info->model_nr,
746 strlen(info->model_nr));
747 used += wlp_set_serial(d1_itr + used, info->serial,
748 strlen(info->serial));
749 used += wlp_set_prim_dev_type(d1_itr + used, &info->prim_dev_type);
750 used += wlp_set_wlp_assc_err(d1_itr + used, WLP_ASSOC_ERROR_NONE);
751 skb_put(_skb, sizeof(*_d1) + used);
758 * Construct a D2 association frame
760 * We use the radio control functions to determine the values of the device
761 * properties. These are of variable length and the total space needed is
762 * tallied first before we start constructing the message. The radio
763 * control functions return strings that are terminated with \0. This
764 * character should not be included in the message (there is a length field
765 * accompanying it in the attribute).
768 int wlp_build_assoc_d2(struct wlp *wlp, struct wlp_wss *wss,
769 struct sk_buff **skb, struct wlp_uuid *uuid_e)
772 struct device *dev = &wlp->rc->uwb_dev.dev;
774 struct wlp_device_info *info;
776 struct wlp_frame_assoc *_d2;
777 struct sk_buff *_skb;
781 if (wlp->dev_info == NULL) {
782 result = __wlp_setup_device_info(wlp);
784 dev_err(dev, "WLP: Unable to setup device "
785 "information for D2 message.\n");
789 info = wlp->dev_info;
790 mem_needed = sizeof(*_d2)
791 + sizeof(struct wlp_attr_uuid_e)
792 + sizeof(struct wlp_attr_uuid_r)
793 + sizeof(struct wlp_attr_dev_name)
795 + sizeof(struct wlp_attr_manufacturer)
796 + strlen(info->manufacturer)
797 + sizeof(struct wlp_attr_model_name)
798 + strlen(info->model_name)
799 + sizeof(struct wlp_attr_model_nr)
800 + strlen(info->model_nr)
801 + sizeof(struct wlp_attr_serial)
802 + strlen(info->serial)
803 + sizeof(struct wlp_attr_prim_dev_type)
804 + sizeof(struct wlp_attr_wlp_assc_err);
805 if (wlp->wss.state >= WLP_WSS_STATE_ACTIVE)
806 mem_needed += sizeof(struct wlp_attr_wss_info)
807 + sizeof(struct wlp_wss_info)
808 + strlen(wlp->wss.name);
809 _skb = dev_alloc_skb(mem_needed);
811 dev_err(dev, "WLP: Cannot allocate memory for association "
816 _d2 = (void *) _skb->data;
817 _d2->hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID);
818 _d2->hdr.type = WLP_FRAME_ASSOCIATION;
819 _d2->type = WLP_ASSOC_D2;
821 wlp_set_version(&_d2->version, WLP_VERSION);
822 wlp_set_msg_type(&_d2->msg_type, WLP_ASSOC_D2);
824 used = wlp_set_uuid_e(d2_itr, uuid_e);
825 used += wlp_set_uuid_r(d2_itr + used, &wlp->uuid);
826 if (wlp->wss.state >= WLP_WSS_STATE_ACTIVE)
827 used += wlp_set_wss_info(d2_itr + used, &wlp->wss);
828 used += wlp_set_dev_name(d2_itr + used, info->name,
830 used += wlp_set_manufacturer(d2_itr + used, info->manufacturer,
831 strlen(info->manufacturer));
832 used += wlp_set_model_name(d2_itr + used, info->model_name,
833 strlen(info->model_name));
834 used += wlp_set_model_nr(d2_itr + used, info->model_nr,
835 strlen(info->model_nr));
836 used += wlp_set_serial(d2_itr + used, info->serial,
837 strlen(info->serial));
838 used += wlp_set_prim_dev_type(d2_itr + used, &info->prim_dev_type);
839 used += wlp_set_wlp_assc_err(d2_itr + used, WLP_ASSOC_ERROR_NONE);
840 skb_put(_skb, sizeof(*_d2) + used);
847 * Allocate memory for and populate fields of F0 association frame
849 * Currently (while focusing on unsecure enrollment) we ignore the
850 * nonce's that could be placed in the message. Only the error field is
851 * populated by the value provided by the caller.
854 int wlp_build_assoc_f0(struct wlp *wlp, struct sk_buff **skb,
855 enum wlp_assc_error error)
857 struct device *dev = &wlp->rc->uwb_dev.dev;
858 int result = -ENOMEM;
860 struct wlp_frame_assoc f0_hdr;
861 struct wlp_attr_enonce enonce;
862 struct wlp_attr_rnonce rnonce;
863 struct wlp_attr_wlp_assc_err assc_err;
865 struct sk_buff *_skb;
866 struct wlp_nonce tmp;
868 _skb = dev_alloc_skb(sizeof(*f0));
870 dev_err(dev, "WLP: Unable to allocate memory for F0 "
871 "association frame. \n");
874 f0 = (void *) _skb->data;
875 f0->f0_hdr.hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID);
876 f0->f0_hdr.hdr.type = WLP_FRAME_ASSOCIATION;
877 f0->f0_hdr.type = WLP_ASSOC_F0;
878 wlp_set_version(&f0->f0_hdr.version, WLP_VERSION);
879 wlp_set_msg_type(&f0->f0_hdr.msg_type, WLP_ASSOC_F0);
880 memset(&tmp, 0, sizeof(tmp));
881 wlp_set_enonce(&f0->enonce, &tmp);
882 wlp_set_rnonce(&f0->rnonce, &tmp);
883 wlp_set_wlp_assc_err(&f0->assc_err, error);
884 skb_put(_skb, sizeof(*f0));
894 * We just retrieve the values and print it as an error to the user.
895 * Calling function already knows an error occured (F0 indicates error), so
896 * we just parse the content as debug for higher layers.
898 int wlp_parse_f0(struct wlp *wlp, struct sk_buff *skb)
900 struct device *dev = &wlp->rc->uwb_dev.dev;
901 struct wlp_frame_assoc *f0 = (void *) skb->data;
902 void *ptr = skb->data;
903 size_t len = skb->len;
906 struct wlp_nonce enonce, rnonce;
907 enum wlp_assc_error assc_err;
908 char enonce_buf[WLP_WSS_NONCE_STRSIZE];
909 char rnonce_buf[WLP_WSS_NONCE_STRSIZE];
912 result = wlp_get_enonce(wlp, ptr + used, &enonce, len - used);
914 dev_err(dev, "WLP: unable to obtain Enrollee nonce "
915 "attribute from F0 message.\n");
919 result = wlp_get_rnonce(wlp, ptr + used, &rnonce, len - used);
921 dev_err(dev, "WLP: unable to obtain Registrar nonce "
922 "attribute from F0 message.\n");
926 result = wlp_get_wlp_assc_err(wlp, ptr + used, &assc_err, len - used);
928 dev_err(dev, "WLP: unable to obtain WLP Association error "
929 "attribute from F0 message.\n");
932 wlp_wss_nonce_print(enonce_buf, sizeof(enonce_buf), &enonce);
933 wlp_wss_nonce_print(rnonce_buf, sizeof(rnonce_buf), &rnonce);
934 dev_err(dev, "WLP: Received F0 error frame from neighbor. Enrollee "
935 "nonce: %s, Registrar nonce: %s, WLP Association error: %s.\n",
936 enonce_buf, rnonce_buf, wlp_assc_error_str(assc_err));
943 * Retrieve variable device information from association message
945 * The device information parsed is not required in any message. This
946 * routine will thus not fail if an attribute is not present.
947 * The attributes are expected in a certain order, even if all are not
948 * present. The "attribute type" value is used to ensure the attributes
949 * are parsed in the correct order.
951 * If an error is encountered during parsing the function will return an
952 * error code, when this happens the given device_info structure may be
956 int wlp_get_variable_info(struct wlp *wlp, void *data,
957 struct wlp_device_info *dev_info, ssize_t len)
959 struct device *dev = &wlp->rc->uwb_dev.dev;
961 struct wlp_attr_hdr *hdr;
965 while (len - used > 0) {
966 if (len - used < sizeof(*hdr)) {
967 dev_err(dev, "WLP: Partial data in frame, cannot "
972 switch (le16_to_cpu(hdr->type)) {
974 if (last >= WLP_ATTR_MANUF) {
975 dev_err(dev, "WLP: Incorrect order of "
976 "attribute values in D1 msg.\n");
979 result = wlp_get_manufacturer(wlp, data + used,
980 dev_info->manufacturer,
983 dev_err(dev, "WLP: Unable to obtain "
984 "Manufacturer attribute from D1 "
988 last = WLP_ATTR_MANUF;
991 case WLP_ATTR_MODEL_NAME:
992 if (last >= WLP_ATTR_MODEL_NAME) {
993 dev_err(dev, "WLP: Incorrect order of "
994 "attribute values in D1 msg.\n");
997 result = wlp_get_model_name(wlp, data + used,
998 dev_info->model_name,
1001 dev_err(dev, "WLP: Unable to obtain Model "
1002 "name attribute from D1 message.\n");
1005 last = WLP_ATTR_MODEL_NAME;
1008 case WLP_ATTR_MODEL_NR:
1009 if (last >= WLP_ATTR_MODEL_NR) {
1010 dev_err(dev, "WLP: Incorrect order of "
1011 "attribute values in D1 msg.\n");
1014 result = wlp_get_model_nr(wlp, data + used,
1018 dev_err(dev, "WLP: Unable to obtain Model "
1019 "number attribute from D1 message.\n");
1022 last = WLP_ATTR_MODEL_NR;
1025 case WLP_ATTR_SERIAL:
1026 if (last >= WLP_ATTR_SERIAL) {
1027 dev_err(dev, "WLP: Incorrect order of "
1028 "attribute values in D1 msg.\n");
1031 result = wlp_get_serial(wlp, data + used,
1032 dev_info->serial, len - used);
1034 dev_err(dev, "WLP: Unable to obtain Serial "
1035 "number attribute from D1 message.\n");
1038 last = WLP_ATTR_SERIAL;
1041 case WLP_ATTR_PRI_DEV_TYPE:
1042 if (last >= WLP_ATTR_PRI_DEV_TYPE) {
1043 dev_err(dev, "WLP: Incorrect order of "
1044 "attribute values in D1 msg.\n");
1047 result = wlp_get_prim_dev_type(wlp, data + used,
1048 &dev_info->prim_dev_type,
1051 dev_err(dev, "WLP: Unable to obtain Primary "
1052 "device type attribute from D1 "
1056 dev_info->prim_dev_type.category =
1057 le16_to_cpu(dev_info->prim_dev_type.category);
1058 dev_info->prim_dev_type.subID =
1059 le16_to_cpu(dev_info->prim_dev_type.subID);
1060 last = WLP_ATTR_PRI_DEV_TYPE;
1064 /* This is not variable device information. */
1076 * Parse incoming D1 frame, populate attribute values
1078 * Caller provides pointers to memory already allocated for attributes
1079 * expected in the D1 frame. These variables will be populated.
1082 int wlp_parse_d1_frame(struct wlp *wlp, struct sk_buff *skb,
1083 struct wlp_uuid *uuid_e,
1084 enum wlp_wss_sel_mthd *sel_mthd,
1085 struct wlp_device_info *dev_info,
1086 enum wlp_assc_error *assc_err)
1088 struct device *dev = &wlp->rc->uwb_dev.dev;
1089 struct wlp_frame_assoc *d1 = (void *) skb->data;
1090 void *ptr = skb->data;
1091 size_t len = skb->len;
1096 result = wlp_get_uuid_e(wlp, ptr + used, uuid_e, len - used);
1098 dev_err(dev, "WLP: unable to obtain UUID-E attribute from D1 "
1103 result = wlp_get_wss_sel_mthd(wlp, ptr + used, sel_mthd, len - used);
1105 dev_err(dev, "WLP: unable to obtain WSS selection method "
1106 "from D1 message.\n");
1110 result = wlp_get_dev_name(wlp, ptr + used, dev_info->name,
1113 dev_err(dev, "WLP: unable to obtain Device Name from D1 "
1118 result = wlp_get_variable_info(wlp, ptr + used, dev_info, len - used);
1120 dev_err(dev, "WLP: unable to obtain Device Information from "
1125 result = wlp_get_wlp_assc_err(wlp, ptr + used, assc_err, len - used);
1127 dev_err(dev, "WLP: unable to obtain WLP Association Error "
1128 "Information from D1 message.\n");
1136 * Handle incoming D1 frame
1138 * The frame has already been verified to contain an Association header with
1139 * the correct version number. Parse the incoming frame, construct and send
1140 * a D2 frame in response.
1142 * It is not clear what to do with most fields in the incoming D1 frame. We
1143 * retrieve and discard the information here for now.
1145 void wlp_handle_d1_frame(struct work_struct *ws)
1147 struct wlp_assoc_frame_ctx *frame_ctx = container_of(ws,
1148 struct wlp_assoc_frame_ctx,
1150 struct wlp *wlp = frame_ctx->wlp;
1151 struct wlp_wss *wss = &wlp->wss;
1152 struct sk_buff *skb = frame_ctx->skb;
1153 struct uwb_dev_addr *src = &frame_ctx->src;
1155 struct device *dev = &wlp->rc->uwb_dev.dev;
1156 struct wlp_uuid uuid_e;
1157 enum wlp_wss_sel_mthd sel_mthd = 0;
1158 struct wlp_device_info dev_info;
1159 enum wlp_assc_error assc_err;
1160 struct sk_buff *resp = NULL;
1162 /* Parse D1 frame */
1163 mutex_lock(&wss->mutex);
1164 mutex_lock(&wlp->mutex); /* to access wlp->uuid */
1165 memset(&dev_info, 0, sizeof(dev_info));
1166 result = wlp_parse_d1_frame(wlp, skb, &uuid_e, &sel_mthd, &dev_info,
1169 dev_err(dev, "WLP: Unable to parse incoming D1 frame.\n");
1175 if (!wlp_uuid_is_set(&wlp->uuid)) {
1176 dev_err(dev, "WLP: UUID is not set. Set via sysfs to "
1177 "proceed. Respong to D1 message with error F0.\n");
1178 result = wlp_build_assoc_f0(wlp, &resp,
1179 WLP_ASSOC_ERROR_NOT_READY);
1181 dev_err(dev, "WLP: Unable to construct F0 message.\n");
1185 /* Construct D2 frame */
1186 result = wlp_build_assoc_d2(wlp, wss, &resp, &uuid_e);
1188 dev_err(dev, "WLP: Unable to construct D2 message.\n");
1193 BUG_ON(wlp->xmit_frame == NULL);
1194 result = wlp->xmit_frame(wlp, resp, src);
1196 dev_err(dev, "WLP: Unable to transmit D2 association "
1197 "message: %d\n", result);
1198 if (result == -ENXIO)
1199 dev_err(dev, "WLP: Is network interface up? \n");
1200 /* We could try again ... */
1201 dev_kfree_skb_any(resp); /* we need to free if tx fails */
1205 mutex_unlock(&wlp->mutex);
1206 mutex_unlock(&wss->mutex);
1210 * Parse incoming D2 frame, create and populate temporary cache
1212 * @skb: socket buffer in which D2 frame can be found
1213 * @neighbor: the neighbor that sent the D2 frame
1215 * Will allocate memory for temporary storage of information learned during
1218 int wlp_parse_d2_frame_to_cache(struct wlp *wlp, struct sk_buff *skb,
1219 struct wlp_neighbor_e *neighbor)
1221 struct device *dev = &wlp->rc->uwb_dev.dev;
1222 struct wlp_frame_assoc *d2 = (void *) skb->data;
1223 void *ptr = skb->data;
1224 size_t len = skb->len;
1227 struct wlp_uuid uuid_e;
1228 struct wlp_device_info *nb_info;
1229 enum wlp_assc_error assc_err;
1232 result = wlp_get_uuid_e(wlp, ptr + used, &uuid_e, len - used);
1234 dev_err(dev, "WLP: unable to obtain UUID-E attribute from D2 "
1238 if (memcmp(&uuid_e, &wlp->uuid, sizeof(uuid_e))) {
1239 dev_err(dev, "WLP: UUID-E in incoming D2 does not match "
1240 "local UUID sent in D1. \n");
1244 result = wlp_get_uuid_r(wlp, ptr + used, &neighbor->uuid, len - used);
1246 dev_err(dev, "WLP: unable to obtain UUID-R attribute from D2 "
1251 result = wlp_get_wss_info_to_cache(wlp, ptr + used, neighbor,
1254 dev_err(dev, "WLP: unable to obtain WSS information "
1255 "from D2 message.\n");
1259 neighbor->info = kzalloc(sizeof(struct wlp_device_info), GFP_KERNEL);
1260 if (neighbor->info == NULL) {
1261 dev_err(dev, "WLP: cannot allocate memory to store device "
1266 nb_info = neighbor->info;
1267 result = wlp_get_dev_name(wlp, ptr + used, nb_info->name,
1270 dev_err(dev, "WLP: unable to obtain Device Name from D2 "
1275 result = wlp_get_variable_info(wlp, ptr + used, nb_info, len - used);
1277 dev_err(dev, "WLP: unable to obtain Device Information from "
1282 result = wlp_get_wlp_assc_err(wlp, ptr + used, &assc_err, len - used);
1284 dev_err(dev, "WLP: unable to obtain WLP Association Error "
1285 "Information from D2 message.\n");
1288 if (assc_err != WLP_ASSOC_ERROR_NONE) {
1289 dev_err(dev, "WLP: neighbor device returned association "
1290 "error %d\n", assc_err);
1297 wlp_remove_neighbor_tmp_info(neighbor);
1302 * Parse incoming D2 frame, populate attribute values of WSS bein enrolled in
1304 * @wss: our WSS that will be enrolled
1305 * @skb: socket buffer in which D2 frame can be found
1306 * @neighbor: the neighbor that sent the D2 frame
1307 * @wssid: the wssid of the WSS in which we want to enroll
1309 * Forms part of enrollment sequence. We are trying to enroll in WSS with
1310 * @wssid by using @neighbor as registrar. A D1 message was sent to
1311 * @neighbor and now we need to parse the D2 response. The neighbor's
1312 * response is searched for the requested WSS and if found (and it accepts
1313 * enrollment), we store the information.
1315 int wlp_parse_d2_frame_to_enroll(struct wlp_wss *wss, struct sk_buff *skb,
1316 struct wlp_neighbor_e *neighbor,
1317 struct wlp_uuid *wssid)
1319 struct wlp *wlp = container_of(wss, struct wlp, wss);
1320 struct device *dev = &wlp->rc->uwb_dev.dev;
1321 void *ptr = skb->data;
1322 size_t len = skb->len;
1325 struct wlp_uuid uuid_e;
1326 struct wlp_uuid uuid_r;
1327 struct wlp_device_info nb_info;
1328 enum wlp_assc_error assc_err;
1329 char uuid_bufA[WLP_WSS_UUID_STRSIZE];
1330 char uuid_bufB[WLP_WSS_UUID_STRSIZE];
1332 used = sizeof(struct wlp_frame_assoc);
1333 result = wlp_get_uuid_e(wlp, ptr + used, &uuid_e, len - used);
1335 dev_err(dev, "WLP: unable to obtain UUID-E attribute from D2 "
1339 if (memcmp(&uuid_e, &wlp->uuid, sizeof(uuid_e))) {
1340 dev_err(dev, "WLP: UUID-E in incoming D2 does not match "
1341 "local UUID sent in D1. \n");
1345 result = wlp_get_uuid_r(wlp, ptr + used, &uuid_r, len - used);
1347 dev_err(dev, "WLP: unable to obtain UUID-R attribute from D2 "
1351 if (memcmp(&uuid_r, &neighbor->uuid, sizeof(uuid_r))) {
1352 wlp_wss_uuid_print(uuid_bufA, sizeof(uuid_bufA),
1354 wlp_wss_uuid_print(uuid_bufB, sizeof(uuid_bufB), &uuid_r);
1355 dev_err(dev, "WLP: UUID of neighbor does not match UUID "
1356 "learned during discovery. Originally discovered: %s, "
1357 "now from D2 message: %s\n", uuid_bufA, uuid_bufB);
1362 wss->wssid = *wssid;
1363 result = wlp_get_wss_info_to_enroll(wlp, ptr + used, wss, len - used);
1365 dev_err(dev, "WLP: unable to obtain WSS information "
1366 "from D2 message.\n");
1369 if (wss->state != WLP_WSS_STATE_PART_ENROLLED) {
1370 dev_err(dev, "WLP: D2 message did not contain information "
1371 "for successful enrollment. \n");
1376 /* Place device information on stack to continue parsing of message */
1377 result = wlp_get_dev_name(wlp, ptr + used, nb_info.name,
1380 dev_err(dev, "WLP: unable to obtain Device Name from D2 "
1385 result = wlp_get_variable_info(wlp, ptr + used, &nb_info, len - used);
1387 dev_err(dev, "WLP: unable to obtain Device Information from "
1392 result = wlp_get_wlp_assc_err(wlp, ptr + used, &assc_err, len - used);
1394 dev_err(dev, "WLP: unable to obtain WLP Association Error "
1395 "Information from D2 message.\n");
1398 if (assc_err != WLP_ASSOC_ERROR_NONE) {
1399 dev_err(dev, "WLP: neighbor device returned association "
1400 "error %d\n", assc_err);
1401 if (wss->state == WLP_WSS_STATE_PART_ENROLLED) {
1402 dev_err(dev, "WLP: Enrolled in WSS (should not "
1403 "happen according to spec). Undoing. \n");
1415 * Parse C3/C4 frame into provided variables
1417 * @wssid: will point to copy of wssid retrieved from C3/C4 frame
1418 * @tag: will point to copy of tag retrieved from C3/C4 frame
1419 * @virt_addr: will point to copy of virtual address retrieved from C3/C4
1422 * Calling function has to allocate memory for these values.
1424 * skb contains a valid C3/C4 frame, return the individual fields of this
1425 * frame in the provided variables.
1427 int wlp_parse_c3c4_frame(struct wlp *wlp, struct sk_buff *skb,
1428 struct wlp_uuid *wssid, u8 *tag,
1429 struct uwb_mac_addr *virt_addr)
1431 struct device *dev = &wlp->rc->uwb_dev.dev;
1433 void *ptr = skb->data;
1434 size_t len = skb->len;
1436 struct wlp_frame_assoc *assoc = ptr;
1438 used = sizeof(*assoc);
1439 result = wlp_get_wssid(wlp, ptr + used, wssid, len - used);
1441 dev_err(dev, "WLP: unable to obtain WSSID attribute from "
1442 "%s message.\n", wlp_assoc_frame_str(assoc->type));
1446 result = wlp_get_wss_tag(wlp, ptr + used, tag, len - used);
1448 dev_err(dev, "WLP: unable to obtain WSS tag attribute from "
1449 "%s message.\n", wlp_assoc_frame_str(assoc->type));
1453 result = wlp_get_wss_virt(wlp, ptr + used, virt_addr, len - used);
1455 dev_err(dev, "WLP: unable to obtain WSS virtual address "
1456 "attribute from %s message.\n",
1457 wlp_assoc_frame_str(assoc->type));
1465 * Allocate memory for and populate fields of C1 or C2 association frame
1467 * The C1 and C2 association frames appear identical - except for the type.
1470 int wlp_build_assoc_c1c2(struct wlp *wlp, struct wlp_wss *wss,
1471 struct sk_buff **skb, enum wlp_assoc_type type)
1473 struct device *dev = &wlp->rc->uwb_dev.dev;
1474 int result = -ENOMEM;
1476 struct wlp_frame_assoc c_hdr;
1477 struct wlp_attr_wssid wssid;
1479 struct sk_buff *_skb;
1481 _skb = dev_alloc_skb(sizeof(*c));
1483 dev_err(dev, "WLP: Unable to allocate memory for C1/C2 "
1484 "association frame. \n");
1487 c = (void *) _skb->data;
1488 c->c_hdr.hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID);
1489 c->c_hdr.hdr.type = WLP_FRAME_ASSOCIATION;
1490 c->c_hdr.type = type;
1491 wlp_set_version(&c->c_hdr.version, WLP_VERSION);
1492 wlp_set_msg_type(&c->c_hdr.msg_type, type);
1493 wlp_set_wssid(&c->wssid, &wss->wssid);
1494 skb_put(_skb, sizeof(*c));
1503 int wlp_build_assoc_c1(struct wlp *wlp, struct wlp_wss *wss,
1504 struct sk_buff **skb)
1506 return wlp_build_assoc_c1c2(wlp, wss, skb, WLP_ASSOC_C1);
1510 int wlp_build_assoc_c2(struct wlp *wlp, struct wlp_wss *wss,
1511 struct sk_buff **skb)
1513 return wlp_build_assoc_c1c2(wlp, wss, skb, WLP_ASSOC_C2);
1518 * Allocate memory for and populate fields of C3 or C4 association frame
1520 * The C3 and C4 association frames appear identical - except for the type.
1523 int wlp_build_assoc_c3c4(struct wlp *wlp, struct wlp_wss *wss,
1524 struct sk_buff **skb, enum wlp_assoc_type type)
1526 struct device *dev = &wlp->rc->uwb_dev.dev;
1527 int result = -ENOMEM;
1529 struct wlp_frame_assoc c_hdr;
1530 struct wlp_attr_wssid wssid;
1531 struct wlp_attr_wss_tag wss_tag;
1532 struct wlp_attr_wss_virt wss_virt;
1534 struct sk_buff *_skb;
1536 _skb = dev_alloc_skb(sizeof(*c));
1538 dev_err(dev, "WLP: Unable to allocate memory for C3/C4 "
1539 "association frame. \n");
1542 c = (void *) _skb->data;
1543 c->c_hdr.hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID);
1544 c->c_hdr.hdr.type = WLP_FRAME_ASSOCIATION;
1545 c->c_hdr.type = type;
1546 wlp_set_version(&c->c_hdr.version, WLP_VERSION);
1547 wlp_set_msg_type(&c->c_hdr.msg_type, type);
1548 wlp_set_wssid(&c->wssid, &wss->wssid);
1549 wlp_set_wss_tag(&c->wss_tag, wss->tag);
1550 wlp_set_wss_virt(&c->wss_virt, &wss->virtual_addr);
1551 skb_put(_skb, sizeof(*c));
1559 int wlp_build_assoc_c3(struct wlp *wlp, struct wlp_wss *wss,
1560 struct sk_buff **skb)
1562 return wlp_build_assoc_c3c4(wlp, wss, skb, WLP_ASSOC_C3);
1566 int wlp_build_assoc_c4(struct wlp *wlp, struct wlp_wss *wss,
1567 struct sk_buff **skb)
1569 return wlp_build_assoc_c3c4(wlp, wss, skb, WLP_ASSOC_C4);
1573 #define wlp_send_assoc(type, id) \
1574 static int wlp_send_assoc_##type(struct wlp *wlp, struct wlp_wss *wss, \
1575 struct uwb_dev_addr *dev_addr) \
1577 struct device *dev = &wlp->rc->uwb_dev.dev; \
1579 struct sk_buff *skb = NULL; \
1581 /* Build the frame */ \
1582 result = wlp_build_assoc_##type(wlp, wss, &skb); \
1584 dev_err(dev, "WLP: Unable to construct %s association " \
1585 "frame: %d\n", wlp_assoc_frame_str(id), result);\
1586 goto error_build_assoc; \
1588 /* Send the frame */ \
1589 BUG_ON(wlp->xmit_frame == NULL); \
1590 result = wlp->xmit_frame(wlp, skb, dev_addr); \
1592 dev_err(dev, "WLP: Unable to transmit %s association " \
1593 "message: %d\n", wlp_assoc_frame_str(id), \
1595 if (result == -ENXIO) \
1596 dev_err(dev, "WLP: Is network interface " \
1602 /* We could try again ... */ \
1603 dev_kfree_skb_any(skb);/*we need to free if tx fails*/ \
1604 error_build_assoc: \
1608 wlp_send_assoc(d1, WLP_ASSOC_D1)
1609 wlp_send_assoc(c1, WLP_ASSOC_C1)
1610 wlp_send_assoc(c3, WLP_ASSOC_C3)
1612 int wlp_send_assoc_frame(struct wlp *wlp, struct wlp_wss *wss,
1613 struct uwb_dev_addr *dev_addr,
1614 enum wlp_assoc_type type)
1617 struct device *dev = &wlp->rc->uwb_dev.dev;
1620 result = wlp_send_assoc_d1(wlp, wss, dev_addr);
1623 result = wlp_send_assoc_c1(wlp, wss, dev_addr);
1626 result = wlp_send_assoc_c3(wlp, wss, dev_addr);
1629 dev_err(dev, "WLP: Received request to send unknown "
1630 "association message.\n");
1638 * Handle incoming C1 frame
1640 * The frame has already been verified to contain an Association header with
1641 * the correct version number. Parse the incoming frame, construct and send
1642 * a C2 frame in response.
1644 void wlp_handle_c1_frame(struct work_struct *ws)
1646 struct wlp_assoc_frame_ctx *frame_ctx = container_of(ws,
1647 struct wlp_assoc_frame_ctx,
1649 struct wlp *wlp = frame_ctx->wlp;
1650 struct wlp_wss *wss = &wlp->wss;
1651 struct device *dev = &wlp->rc->uwb_dev.dev;
1652 struct wlp_frame_assoc *c1 = (void *) frame_ctx->skb->data;
1653 unsigned int len = frame_ctx->skb->len;
1654 struct uwb_dev_addr *src = &frame_ctx->src;
1656 struct wlp_uuid wssid;
1657 struct sk_buff *resp = NULL;
1659 /* Parse C1 frame */
1660 mutex_lock(&wss->mutex);
1661 result = wlp_get_wssid(wlp, (void *)c1 + sizeof(*c1), &wssid,
1664 dev_err(dev, "WLP: unable to obtain WSSID from C1 frame.\n");
1667 if (!memcmp(&wssid, &wss->wssid, sizeof(wssid))
1668 && wss->state == WLP_WSS_STATE_ACTIVE) {
1669 /* Construct C2 frame */
1670 result = wlp_build_assoc_c2(wlp, wss, &resp);
1672 dev_err(dev, "WLP: Unable to construct C2 message.\n");
1676 /* Construct F0 frame */
1677 result = wlp_build_assoc_f0(wlp, &resp, WLP_ASSOC_ERROR_INV);
1679 dev_err(dev, "WLP: Unable to construct F0 message.\n");
1684 BUG_ON(wlp->xmit_frame == NULL);
1685 result = wlp->xmit_frame(wlp, resp, src);
1687 dev_err(dev, "WLP: Unable to transmit response association "
1688 "message: %d\n", result);
1689 if (result == -ENXIO)
1690 dev_err(dev, "WLP: Is network interface up? \n");
1691 /* We could try again ... */
1692 dev_kfree_skb_any(resp); /* we need to free if tx fails */
1695 kfree_skb(frame_ctx->skb);
1697 mutex_unlock(&wss->mutex);
1701 * Handle incoming C3 frame
1703 * The frame has already been verified to contain an Association header with
1704 * the correct version number. Parse the incoming frame, construct and send
1705 * a C4 frame in response. If the C3 frame identifies a WSS that is locally
1706 * active then we connect to this neighbor (add it to our EDA cache).
1708 void wlp_handle_c3_frame(struct work_struct *ws)
1710 struct wlp_assoc_frame_ctx *frame_ctx = container_of(ws,
1711 struct wlp_assoc_frame_ctx,
1713 struct wlp *wlp = frame_ctx->wlp;
1714 struct wlp_wss *wss = &wlp->wss;
1715 struct device *dev = &wlp->rc->uwb_dev.dev;
1716 struct sk_buff *skb = frame_ctx->skb;
1717 struct uwb_dev_addr *src = &frame_ctx->src;
1719 struct sk_buff *resp = NULL;
1720 struct wlp_uuid wssid;
1722 struct uwb_mac_addr virt_addr;
1724 /* Parse C3 frame */
1725 mutex_lock(&wss->mutex);
1726 result = wlp_parse_c3c4_frame(wlp, skb, &wssid, &tag, &virt_addr);
1728 dev_err(dev, "WLP: unable to obtain values from C3 frame.\n");
1731 if (!memcmp(&wssid, &wss->wssid, sizeof(wssid))
1732 && wss->state >= WLP_WSS_STATE_ACTIVE) {
1733 result = wlp_eda_update_node(&wlp->eda, src, wss,
1734 (void *) virt_addr.data, tag,
1737 dev_err(dev, "WLP: Unable to update EDA cache "
1738 "with new connected neighbor information.\n");
1739 result = wlp_build_assoc_f0(wlp, &resp,
1740 WLP_ASSOC_ERROR_INT);
1742 dev_err(dev, "WLP: Unable to construct F0 "
1747 wss->state = WLP_WSS_STATE_CONNECTED;
1748 /* Construct C4 frame */
1749 result = wlp_build_assoc_c4(wlp, wss, &resp);
1751 dev_err(dev, "WLP: Unable to construct C4 "
1757 /* Construct F0 frame */
1758 result = wlp_build_assoc_f0(wlp, &resp, WLP_ASSOC_ERROR_INV);
1760 dev_err(dev, "WLP: Unable to construct F0 message.\n");
1765 BUG_ON(wlp->xmit_frame == NULL);
1766 result = wlp->xmit_frame(wlp, resp, src);
1768 dev_err(dev, "WLP: Unable to transmit response association "
1769 "message: %d\n", result);
1770 if (result == -ENXIO)
1771 dev_err(dev, "WLP: Is network interface up? \n");
1772 /* We could try again ... */
1773 dev_kfree_skb_any(resp); /* we need to free if tx fails */
1776 kfree_skb(frame_ctx->skb);
1778 mutex_unlock(&wss->mutex);