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 <linux/uwb/debug.h>
29 #include "wlp-internal.h"
32 const char *__wlp_assoc_frame[] = {
33 [WLP_ASSOC_D1] = "WLP_ASSOC_D1",
34 [WLP_ASSOC_D2] = "WLP_ASSOC_D2",
35 [WLP_ASSOC_M1] = "WLP_ASSOC_M1",
36 [WLP_ASSOC_M2] = "WLP_ASSOC_M2",
37 [WLP_ASSOC_M3] = "WLP_ASSOC_M3",
38 [WLP_ASSOC_M4] = "WLP_ASSOC_M4",
39 [WLP_ASSOC_M5] = "WLP_ASSOC_M5",
40 [WLP_ASSOC_M6] = "WLP_ASSOC_M6",
41 [WLP_ASSOC_M7] = "WLP_ASSOC_M7",
42 [WLP_ASSOC_M8] = "WLP_ASSOC_M8",
43 [WLP_ASSOC_F0] = "WLP_ASSOC_F0",
44 [WLP_ASSOC_E1] = "WLP_ASSOC_E1",
45 [WLP_ASSOC_E2] = "WLP_ASSOC_E2",
46 [WLP_ASSOC_C1] = "WLP_ASSOC_C1",
47 [WLP_ASSOC_C2] = "WLP_ASSOC_C2",
48 [WLP_ASSOC_C3] = "WLP_ASSOC_C3",
49 [WLP_ASSOC_C4] = "WLP_ASSOC_C4",
52 static const char *wlp_assoc_frame_str(unsigned id)
54 if (id >= ARRAY_SIZE(__wlp_assoc_frame))
55 return "unknown association frame";
56 return __wlp_assoc_frame[id];
59 static const char *__wlp_assc_error[] = {
61 "Authenticator Failure",
62 "Rogue activity suspected",
65 "Registrar not ready",
66 "Invalid WSS selection",
68 "Enrollment session timeout",
69 "Device password invalid",
70 "Unsupported version",
73 "Numeric comparison failure",
74 "Waiting for user input",
77 static const char *wlp_assc_error_str(unsigned id)
79 if (id >= ARRAY_SIZE(__wlp_assc_error))
80 return "unknown WLP association error";
81 return __wlp_assc_error[id];
84 static inline void wlp_set_attr_hdr(struct wlp_attr_hdr *hdr, unsigned type,
87 hdr->type = cpu_to_le16(type);
88 hdr->length = cpu_to_le16(len);
92 * Populate fields of a constant sized attribute
94 * @returns: total size of attribute including size of new value
96 * We have two instances of this function (wlp_pset and wlp_set): one takes
97 * the value as a parameter, the other takes a pointer to the value as
98 * parameter. They thus only differ in how the value is assigned to the
101 * We use sizeof(*attr) - sizeof(struct wlp_attr_hdr) instead of
102 * sizeof(type) to be able to use this same code for the structures that
103 * contain 8bit enum values and be able to deal with pointer types.
105 #define wlp_set(type, type_code, name) \
106 static size_t wlp_set_##name(struct wlp_attr_##name *attr, type value) \
108 d_fnstart(6, NULL, "(attribute %p)\n", attr); \
109 wlp_set_attr_hdr(&attr->hdr, type_code, \
110 sizeof(*attr) - sizeof(struct wlp_attr_hdr)); \
111 attr->name = value; \
112 d_dump(6, NULL, attr, sizeof(*attr)); \
113 d_fnend(6, NULL, "(attribute %p)\n", attr); \
114 return sizeof(*attr); \
117 #define wlp_pset(type, type_code, name) \
118 static size_t wlp_set_##name(struct wlp_attr_##name *attr, type value) \
120 d_fnstart(6, NULL, "(attribute %p)\n", attr); \
121 wlp_set_attr_hdr(&attr->hdr, type_code, \
122 sizeof(*attr) - sizeof(struct wlp_attr_hdr)); \
123 attr->name = *value; \
124 d_dump(6, NULL, attr, sizeof(*attr)); \
125 d_fnend(6, NULL, "(attribute %p)\n", attr); \
126 return sizeof(*attr); \
130 * Populate fields of a variable attribute
132 * @returns: total size of attribute including size of new value
134 * Provided with a pointer to the memory area reserved for the
135 * attribute structure, the field is populated with the value. The
136 * reserved memory has to contain enough space for the value.
138 #define wlp_vset(type, type_code, name) \
139 static size_t wlp_set_##name(struct wlp_attr_##name *attr, type value, \
142 d_fnstart(6, NULL, "(attribute %p)\n", attr); \
143 wlp_set_attr_hdr(&attr->hdr, type_code, len); \
144 memcpy(attr->name, value, len); \
145 d_dump(6, NULL, attr, sizeof(*attr) + len); \
146 d_fnend(6, NULL, "(attribute %p)\n", attr); \
147 return sizeof(*attr) + len; \
150 wlp_vset(char *, WLP_ATTR_DEV_NAME, dev_name)
151 wlp_vset(char *, WLP_ATTR_MANUF, manufacturer)
152 wlp_set(enum wlp_assoc_type, WLP_ATTR_MSG_TYPE, msg_type)
153 wlp_vset(char *, WLP_ATTR_MODEL_NAME, model_name)
154 wlp_vset(char *, WLP_ATTR_MODEL_NR, model_nr)
155 wlp_vset(char *, WLP_ATTR_SERIAL, serial)
156 wlp_vset(char *, WLP_ATTR_WSS_NAME, wss_name)
157 wlp_pset(struct wlp_uuid *, WLP_ATTR_UUID_E, uuid_e)
158 wlp_pset(struct wlp_uuid *, WLP_ATTR_UUID_R, uuid_r)
159 wlp_pset(struct wlp_uuid *, WLP_ATTR_WSSID, wssid)
160 wlp_pset(struct wlp_dev_type *, WLP_ATTR_PRI_DEV_TYPE, prim_dev_type)
161 /*wlp_pset(struct wlp_dev_type *, WLP_ATTR_SEC_DEV_TYPE, sec_dev_type)*/
162 wlp_set(u8, WLP_ATTR_WLP_VER, version)
163 wlp_set(enum wlp_assc_error, WLP_ATTR_WLP_ASSC_ERR, wlp_assc_err)
164 wlp_set(enum wlp_wss_sel_mthd, WLP_ATTR_WSS_SEL_MTHD, wss_sel_mthd)
165 wlp_set(u8, WLP_ATTR_ACC_ENRL, accept_enrl)
166 wlp_set(u8, WLP_ATTR_WSS_SEC_STAT, wss_sec_status)
167 wlp_pset(struct uwb_mac_addr *, WLP_ATTR_WSS_BCAST, wss_bcast)
168 wlp_pset(struct wlp_nonce *, WLP_ATTR_ENRL_NONCE, enonce)
169 wlp_pset(struct wlp_nonce *, WLP_ATTR_REG_NONCE, rnonce)
170 wlp_set(u8, WLP_ATTR_WSS_TAG, wss_tag)
171 wlp_pset(struct uwb_mac_addr *, WLP_ATTR_WSS_VIRT, wss_virt)
174 * Fill in the WSS information attributes
176 * We currently only support one WSS, and this is assumed in this function
177 * that can populate only one WSS information attribute.
179 static size_t wlp_set_wss_info(struct wlp_attr_wss_info *attr,
183 void *ptr = attr->wss_info;
184 size_t used = sizeof(*attr);
185 d_fnstart(6, NULL, "(attribute %p)\n", attr);
186 datalen = sizeof(struct wlp_wss_info) + strlen(wss->name);
187 wlp_set_attr_hdr(&attr->hdr, WLP_ATTR_WSS_INFO, datalen);
188 used = wlp_set_wssid(ptr, &wss->wssid);
189 used += wlp_set_wss_name(ptr + used, wss->name, strlen(wss->name));
190 used += wlp_set_accept_enrl(ptr + used, wss->accept_enroll);
191 used += wlp_set_wss_sec_status(ptr + used, wss->secure_status);
192 used += wlp_set_wss_bcast(ptr + used, &wss->bcast);
193 d_dump(6, NULL, attr, sizeof(*attr) + datalen);
194 d_fnend(6, NULL, "(attribute %p, used %d)\n",
195 attr, (int)(sizeof(*attr) + used));
196 return sizeof(*attr) + used;
200 * Verify attribute header
202 * @hdr: Pointer to attribute header that will be verified.
203 * @type: Expected attribute type.
204 * @len: Expected length of attribute value (excluding header).
206 * Most attribute values have a known length even when they do have a
207 * length field. This knowledge can be used via this function to verify
208 * that the length field matches the expected value.
210 static int wlp_check_attr_hdr(struct wlp *wlp, struct wlp_attr_hdr *hdr,
211 enum wlp_attr_type type, unsigned len)
213 struct device *dev = &wlp->rc->uwb_dev.dev;
215 if (le16_to_cpu(hdr->type) != type) {
216 dev_err(dev, "WLP: unexpected header type. Expected "
217 "%u, got %u.\n", type, le16_to_cpu(hdr->type));
220 if (le16_to_cpu(hdr->length) != len) {
221 dev_err(dev, "WLP: unexpected length in header. Expected "
222 "%u, got %u.\n", len, le16_to_cpu(hdr->length));
229 * Check if header of WSS information attribute valid
231 * @returns: length of WSS attributes (value of length attribute field) if
232 * valid WSS information attribute found
233 * -ENODATA if no WSS information attribute found
234 * -EIO other error occured
236 * The WSS information attribute is optional. The function will be provided
237 * with a pointer to data that could _potentially_ be a WSS information
238 * attribute. If a valid WSS information attribute is found it will return
239 * 0, if no WSS information attribute is found it will return -ENODATA, and
240 * another error will be returned if it is a WSS information attribute, but
241 * some parsing failure occured.
243 static int wlp_check_wss_info_attr_hdr(struct wlp *wlp,
244 struct wlp_attr_hdr *hdr, size_t buflen)
246 struct device *dev = &wlp->rc->uwb_dev.dev;
250 if (buflen < sizeof(*hdr)) {
251 dev_err(dev, "WLP: Not enough space in buffer to parse"
252 " WSS information attribute header.\n");
256 if (le16_to_cpu(hdr->type) != WLP_ATTR_WSS_INFO) {
257 /* WSS information is optional */
261 len = le16_to_cpu(hdr->length);
262 if (buflen < sizeof(*hdr) + len) {
263 dev_err(dev, "WLP: Not enough space in buffer to parse "
264 "variable data. Got %d, expected %d.\n",
265 (int)buflen, (int)(sizeof(*hdr) + len));
276 * Get value of attribute from fixed size attribute field.
278 * @attr: Pointer to attribute field.
279 * @value: Pointer to variable in which attribute value will be placed.
280 * @buflen: Size of buffer in which attribute field (including header)
282 * @returns: Amount of given buffer consumed by parsing for this attribute.
284 * The size and type of the value is known by the type of the attribute.
286 #define wlp_get(type, type_code, name) \
287 ssize_t wlp_get_##name(struct wlp *wlp, struct wlp_attr_##name *attr, \
288 type *value, ssize_t buflen) \
290 struct device *dev = &wlp->rc->uwb_dev.dev; \
293 if (buflen < sizeof(*attr)) { \
294 dev_err(dev, "WLP: Not enough space in buffer to parse" \
295 " attribute field. Need %d, received %zu\n", \
296 (int)sizeof(*attr), buflen); \
299 if (wlp_check_attr_hdr(wlp, &attr->hdr, type_code, \
300 sizeof(attr->name)) < 0) { \
301 dev_err(dev, "WLP: Header verification failed. \n"); \
304 *value = attr->name; \
305 return sizeof(*attr); \
308 #define wlp_get_sparse(type, type_code, name) \
309 static wlp_get(type, type_code, name)
312 * Get value of attribute from variable sized attribute field.
314 * @max: The maximum size of this attribute. This value is dictated by
315 * the maximum value from the WLP specification.
317 * @attr: Pointer to attribute field.
318 * @value: Pointer to variable that will contain the value. The memory
319 * must already have been allocated for this value.
320 * @buflen: Size of buffer in which attribute field (including header)
322 * @returns: Amount of given bufferconsumed by parsing for this attribute.
324 #define wlp_vget(type_val, type_code, name, max) \
325 static ssize_t wlp_get_##name(struct wlp *wlp, \
326 struct wlp_attr_##name *attr, \
327 type_val *value, ssize_t buflen) \
329 struct device *dev = &wlp->rc->uwb_dev.dev; \
333 if (buflen < sizeof(*attr)) { \
334 dev_err(dev, "WLP: Not enough space in buffer to parse" \
338 if (le16_to_cpu(attr->hdr.type) != type_code) { \
339 dev_err(dev, "WLP: Unexpected attribute type. Got %u, " \
340 "expected %u.\n", le16_to_cpu(attr->hdr.type), \
344 len = le16_to_cpu(attr->hdr.length); \
346 dev_err(dev, "WLP: Attribute larger than maximum " \
347 "allowed. Received %zu, max is %d.\n", len, \
351 if (buflen < sizeof(*attr) + len) { \
352 dev_err(dev, "WLP: Not enough space in buffer to parse "\
353 "variable data.\n"); \
356 memcpy(value, (void *) attr + sizeof(*attr), len); \
357 return sizeof(*attr) + len; \
360 wlp_get(u8, WLP_ATTR_WLP_VER, version)
361 wlp_get_sparse(enum wlp_wss_sel_mthd, WLP_ATTR_WSS_SEL_MTHD, wss_sel_mthd)
362 wlp_get_sparse(struct wlp_dev_type, WLP_ATTR_PRI_DEV_TYPE, prim_dev_type)
363 wlp_get_sparse(enum wlp_assc_error, WLP_ATTR_WLP_ASSC_ERR, wlp_assc_err)
364 wlp_get_sparse(struct wlp_uuid, WLP_ATTR_UUID_E, uuid_e)
365 wlp_get_sparse(struct wlp_uuid, WLP_ATTR_UUID_R, uuid_r)
366 wlp_get(struct wlp_uuid, WLP_ATTR_WSSID, wssid)
367 wlp_get_sparse(u8, WLP_ATTR_ACC_ENRL, accept_enrl)
368 wlp_get_sparse(u8, WLP_ATTR_WSS_SEC_STAT, wss_sec_status)
369 wlp_get_sparse(struct uwb_mac_addr, WLP_ATTR_WSS_BCAST, wss_bcast)
370 wlp_get_sparse(u8, WLP_ATTR_WSS_TAG, wss_tag)
371 wlp_get_sparse(struct uwb_mac_addr, WLP_ATTR_WSS_VIRT, wss_virt)
372 wlp_get_sparse(struct wlp_nonce, WLP_ATTR_ENRL_NONCE, enonce)
373 wlp_get_sparse(struct wlp_nonce, WLP_ATTR_REG_NONCE, rnonce)
375 /* The buffers for the device info attributes can be found in the
376 * wlp_device_info struct. These buffers contain one byte more than the
377 * max allowed by the spec - this is done to be able to add the
378 * terminating \0 for user display. This terminating byte is not required
379 * in the actual attribute field (because it has a length field) so the
380 * maximum allowed for this value is one less than its size in the
383 wlp_vget(char, WLP_ATTR_WSS_NAME, wss_name,
384 FIELD_SIZEOF(struct wlp_wss, name) - 1)
385 wlp_vget(char, WLP_ATTR_DEV_NAME, dev_name,
386 FIELD_SIZEOF(struct wlp_device_info, name) - 1)
387 wlp_vget(char, WLP_ATTR_MANUF, manufacturer,
388 FIELD_SIZEOF(struct wlp_device_info, manufacturer) - 1)
389 wlp_vget(char, WLP_ATTR_MODEL_NAME, model_name,
390 FIELD_SIZEOF(struct wlp_device_info, model_name) - 1)
391 wlp_vget(char, WLP_ATTR_MODEL_NR, model_nr,
392 FIELD_SIZEOF(struct wlp_device_info, model_nr) - 1)
393 wlp_vget(char, WLP_ATTR_SERIAL, serial,
394 FIELD_SIZEOF(struct wlp_device_info, serial) - 1)
397 * Retrieve WSS Name, Accept enroll, Secure status, Broadcast from WSS info
399 * @attr: pointer to WSS name attribute in WSS information attribute field
400 * @info: structure that will be populated with data from WSS information
401 * field (WSS name, Accept enroll, secure status, broadcast address)
402 * @buflen: size of buffer
404 * Although the WSSID attribute forms part of the WSS info attribute it is
405 * retrieved separately and stored in a different location.
407 static ssize_t wlp_get_wss_info_attrs(struct wlp *wlp,
408 struct wlp_attr_hdr *attr,
409 struct wlp_wss_tmp_info *info,
412 struct device *dev = &wlp->rc->uwb_dev.dev;
415 ssize_t result = -EINVAL;
417 d_printf(6, dev, "WLP: WSS info: Retrieving WSS name\n");
418 result = wlp_get_wss_name(wlp, ptr, info->name, buflen);
420 dev_err(dev, "WLP: unable to obtain WSS name from "
421 "WSS info in D2 message.\n");
425 d_printf(6, dev, "WLP: WSS info: Retrieving accept enroll\n");
426 result = wlp_get_accept_enrl(wlp, ptr + used, &info->accept_enroll,
429 dev_err(dev, "WLP: unable to obtain accepting "
430 "enrollment from WSS info in D2 message.\n");
433 if (info->accept_enroll != 0 && info->accept_enroll != 1) {
434 dev_err(dev, "WLP: invalid value for accepting "
435 "enrollment in D2 message.\n");
440 d_printf(6, dev, "WLP: WSS info: Retrieving secure status\n");
441 result = wlp_get_wss_sec_status(wlp, ptr + used, &info->sec_status,
444 dev_err(dev, "WLP: unable to obtain secure "
445 "status from WSS info in D2 message.\n");
448 if (info->sec_status != 0 && info->sec_status != 1) {
449 dev_err(dev, "WLP: invalid value for secure "
450 "status in D2 message.\n");
455 d_printf(6, dev, "WLP: WSS info: Retrieving broadcast\n");
456 result = wlp_get_wss_bcast(wlp, ptr + used, &info->bcast,
459 dev_err(dev, "WLP: unable to obtain broadcast "
460 "address from WSS info in D2 message.\n");
470 * Create a new WSSID entry for the neighbor, allocate temporary storage
472 * Each neighbor can have many WSS active. We maintain a list of WSSIDs
473 * advertised by neighbor. During discovery we also cache information about
474 * these WSS in temporary storage.
476 * The temporary storage will be removed after it has been used (eg.
477 * displayed to user), the wssid element will be removed from the list when
478 * the neighbor is rediscovered or when it disappears.
480 static struct wlp_wssid_e *wlp_create_wssid_e(struct wlp *wlp,
481 struct wlp_neighbor_e *neighbor)
483 struct device *dev = &wlp->rc->uwb_dev.dev;
484 struct wlp_wssid_e *wssid_e;
486 wssid_e = kzalloc(sizeof(*wssid_e), GFP_KERNEL);
487 if (wssid_e == NULL) {
488 dev_err(dev, "WLP: unable to allocate memory "
489 "for WSS information.\n");
492 wssid_e->info = kzalloc(sizeof(struct wlp_wss_tmp_info), GFP_KERNEL);
493 if (wssid_e->info == NULL) {
494 dev_err(dev, "WLP: unable to allocate memory "
495 "for temporary WSS information.\n");
500 list_add(&wssid_e->node, &neighbor->wssid);
506 * Parse WSS information attribute
508 * @attr: pointer to WSS information attribute header
509 * @buflen: size of buffer in which WSS information attribute appears
510 * @wssid: will place wssid from WSS info attribute in this location
511 * @wss_info: will place other information from WSS information attribute
514 * memory for @wssid and @wss_info must be allocated when calling this
516 static ssize_t wlp_get_wss_info(struct wlp *wlp, struct wlp_attr_wss_info *attr,
517 size_t buflen, struct wlp_uuid *wssid,
518 struct wlp_wss_tmp_info *wss_info)
520 struct device *dev = &wlp->rc->uwb_dev.dev;
526 result = wlp_check_wss_info_attr_hdr(wlp, (struct wlp_attr_hdr *)attr,
531 used = sizeof(*attr);
533 d_printf(6, dev, "WLP: WSS info: Retrieving WSSID\n");
534 result = wlp_get_wssid(wlp, ptr + used, wssid, buflen - used);
536 dev_err(dev, "WLP: unable to obtain WSSID from WSS info.\n");
540 result = wlp_get_wss_info_attrs(wlp, ptr + used, wss_info,
543 dev_err(dev, "WLP: unable to obtain WSS information "
544 "from WSS information attributes. \n");
548 if (len + sizeof(*attr) != used) {
549 dev_err(dev, "WLP: Amount of data parsed does not "
550 "match length field. Parsed %zu, length "
551 "field %zu. \n", used, len);
556 d_printf(6, dev, "WLP: Successfully parsed WLP information "
557 "attribute. used %zu bytes\n", used);
563 * Retrieve WSS info from association frame
565 * @attr: pointer to WSS information attribute
566 * @neighbor: ptr to neighbor being discovered, NULL if enrollment in
568 * @wss: ptr to WSS being enrolled in, NULL if discovery in progress
569 * @buflen: size of buffer in which WSS information appears
571 * The WSS information attribute appears in the D2 association message.
572 * This message is used in two ways: to discover all neighbors or to enroll
573 * into a WSS activated by a neighbor. During discovery we only want to
574 * store the WSS info in a cache, to be deleted right after it has been
575 * used (eg. displayed to the user). During enrollment we store the WSS
576 * information for the lifetime of enrollment.
578 * During discovery we are interested in all WSS information, during
579 * enrollment we are only interested in the WSS being enrolled in. Even so,
580 * when in enrollment we keep parsing the message after finding the WSS of
581 * interest, this simplifies the calling routine in that it can be sure
582 * that all WSS information attributes have been parsed out of the message.
584 * Association frame is process with nbmutex held. The list access is safe.
586 static ssize_t wlp_get_all_wss_info(struct wlp *wlp,
587 struct wlp_attr_wss_info *attr,
588 struct wlp_neighbor_e *neighbor,
589 struct wlp_wss *wss, ssize_t buflen)
591 struct device *dev = &wlp->rc->uwb_dev.dev;
593 ssize_t result = -EINVAL;
594 struct wlp_attr_wss_info *cur;
595 struct wlp_uuid wssid;
596 struct wlp_wss_tmp_info wss_info;
597 unsigned enroll; /* 0 - discovery to cache, 1 - enrollment */
598 struct wlp_wssid_e *wssid_e;
599 char buf[WLP_WSS_UUID_STRSIZE];
601 d_fnstart(6, dev, "wlp %p, attr %p, neighbor %p, wss %p, buflen %d \n",
602 wlp, attr, neighbor, wss, (int)buflen);
606 if (neighbor != NULL && wss == NULL)
607 enroll = 0; /* discovery */
608 else if (wss != NULL && neighbor == NULL)
609 enroll = 1; /* enrollment */
614 while (buflen - used > 0) {
615 memset(&wss_info, 0, sizeof(wss_info));
616 cur = (void *)cur + used;
617 result = wlp_get_wss_info(wlp, cur, buflen - used, &wssid,
619 if (result == -ENODATA) {
622 } else if (result < 0) {
623 dev_err(dev, "WLP: Unable to parse WSS information "
624 "from WSS information attribute. \n");
628 if (enroll && !memcmp(&wssid, &wss->wssid, sizeof(wssid))) {
629 if (wss_info.accept_enroll != 1) {
630 dev_err(dev, "WLP: Requested WSS does "
631 "not accept enrollment.\n");
635 memcpy(wss->name, wss_info.name, sizeof(wss->name));
636 wss->bcast = wss_info.bcast;
637 wss->secure_status = wss_info.sec_status;
638 wss->accept_enroll = wss_info.accept_enroll;
639 wss->state = WLP_WSS_STATE_PART_ENROLLED;
640 wlp_wss_uuid_print(buf, sizeof(buf), &wssid);
641 d_printf(2, dev, "WLP: Found WSS %s. Enrolling.\n",
644 wssid_e = wlp_create_wssid_e(wlp, neighbor);
645 if (wssid_e == NULL) {
646 dev_err(dev, "WLP: Cannot create new WSSID "
647 "entry for neighbor %02x:%02x.\n",
648 neighbor->uwb_dev->dev_addr.data[1],
649 neighbor->uwb_dev->dev_addr.data[0]);
653 wssid_e->wssid = wssid;
654 *wssid_e->info = wss_info;
660 if (result < 0 && !enroll) /* this was a discovery */
661 wlp_remove_neighbor_tmp_info(neighbor);
663 d_fnend(6, dev, "wlp %p, attr %p, neighbor %p, wss %p, buflen %d, "
664 "result %d \n", wlp, attr, neighbor, wss, (int)buflen,
671 * Parse WSS information attributes into cache for discovery
673 * @attr: the first WSS information attribute in message
674 * @neighbor: the neighbor whose cache will be populated
675 * @buflen: size of the input buffer
677 static ssize_t wlp_get_wss_info_to_cache(struct wlp *wlp,
678 struct wlp_attr_wss_info *attr,
679 struct wlp_neighbor_e *neighbor,
682 return wlp_get_all_wss_info(wlp, attr, neighbor, NULL, buflen);
686 * Parse WSS information attributes into WSS struct for enrollment
688 * @attr: the first WSS information attribute in message
689 * @wss: the WSS that will be enrolled
690 * @buflen: size of the input buffer
692 static ssize_t wlp_get_wss_info_to_enroll(struct wlp *wlp,
693 struct wlp_attr_wss_info *attr,
694 struct wlp_wss *wss, ssize_t buflen)
696 return wlp_get_all_wss_info(wlp, attr, NULL, wss, buflen);
700 * Construct a D1 association frame
702 * We use the radio control functions to determine the values of the device
703 * properties. These are of variable length and the total space needed is
704 * tallied first before we start constructing the message. The radio
705 * control functions return strings that are terminated with \0. This
706 * character should not be included in the message (there is a length field
707 * accompanying it in the attribute).
709 static int wlp_build_assoc_d1(struct wlp *wlp, struct wlp_wss *wss,
710 struct sk_buff **skb)
713 struct device *dev = &wlp->rc->uwb_dev.dev;
715 struct wlp_device_info *info;
717 struct wlp_frame_assoc *_d1;
718 struct sk_buff *_skb;
721 d_fnstart(6, dev, "wlp %p\n", wlp);
722 if (wlp->dev_info == NULL) {
723 result = __wlp_setup_device_info(wlp);
725 dev_err(dev, "WLP: Unable to setup device "
726 "information for D1 message.\n");
730 info = wlp->dev_info;
731 d_printf(6, dev, "Local properties:\n"
732 "Device name (%d bytes): %s\n"
733 "Model name (%d bytes): %s\n"
734 "Manufacturer (%d bytes): %s\n"
735 "Model number (%d bytes): %s\n"
736 "Serial number (%d bytes): %s\n"
737 "Primary device type: \n"
739 " OUI: %02x:%02x:%02x \n"
740 " OUI Subdivision: %u \n",
741 (int)strlen(info->name), info->name,
742 (int)strlen(info->model_name), info->model_name,
743 (int)strlen(info->manufacturer), info->manufacturer,
744 (int)strlen(info->model_nr), info->model_nr,
745 (int)strlen(info->serial), info->serial,
746 info->prim_dev_type.category,
747 info->prim_dev_type.OUI[0], info->prim_dev_type.OUI[1],
748 info->prim_dev_type.OUI[2], info->prim_dev_type.OUIsubdiv);
749 _skb = dev_alloc_skb(sizeof(*_d1)
750 + sizeof(struct wlp_attr_uuid_e)
751 + sizeof(struct wlp_attr_wss_sel_mthd)
752 + sizeof(struct wlp_attr_dev_name)
754 + sizeof(struct wlp_attr_manufacturer)
755 + strlen(info->manufacturer)
756 + sizeof(struct wlp_attr_model_name)
757 + strlen(info->model_name)
758 + sizeof(struct wlp_attr_model_nr)
759 + strlen(info->model_nr)
760 + sizeof(struct wlp_attr_serial)
761 + strlen(info->serial)
762 + sizeof(struct wlp_attr_prim_dev_type)
763 + sizeof(struct wlp_attr_wlp_assc_err));
765 dev_err(dev, "WLP: Cannot allocate memory for association "
770 _d1 = (void *) _skb->data;
771 d_printf(6, dev, "D1 starts at %p \n", _d1);
772 _d1->hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID);
773 _d1->hdr.type = WLP_FRAME_ASSOCIATION;
774 _d1->type = WLP_ASSOC_D1;
776 wlp_set_version(&_d1->version, WLP_VERSION);
777 wlp_set_msg_type(&_d1->msg_type, WLP_ASSOC_D1);
779 used = wlp_set_uuid_e(d1_itr, &wlp->uuid);
780 used += wlp_set_wss_sel_mthd(d1_itr + used, WLP_WSS_REG_SELECT);
781 used += wlp_set_dev_name(d1_itr + used, info->name,
783 used += wlp_set_manufacturer(d1_itr + used, info->manufacturer,
784 strlen(info->manufacturer));
785 used += wlp_set_model_name(d1_itr + used, info->model_name,
786 strlen(info->model_name));
787 used += wlp_set_model_nr(d1_itr + used, info->model_nr,
788 strlen(info->model_nr));
789 used += wlp_set_serial(d1_itr + used, info->serial,
790 strlen(info->serial));
791 used += wlp_set_prim_dev_type(d1_itr + used, &info->prim_dev_type);
792 used += wlp_set_wlp_assc_err(d1_itr + used, WLP_ASSOC_ERROR_NONE);
793 skb_put(_skb, sizeof(*_d1) + used);
794 d_printf(6, dev, "D1 message:\n");
795 d_dump(6, dev, _d1, sizeof(*_d1)
796 + sizeof(struct wlp_attr_uuid_e)
797 + sizeof(struct wlp_attr_wss_sel_mthd)
798 + sizeof(struct wlp_attr_dev_name)
800 + sizeof(struct wlp_attr_manufacturer)
801 + strlen(info->manufacturer)
802 + sizeof(struct wlp_attr_model_name)
803 + strlen(info->model_name)
804 + sizeof(struct wlp_attr_model_nr)
805 + strlen(info->model_nr)
806 + sizeof(struct wlp_attr_serial)
807 + strlen(info->serial)
808 + sizeof(struct wlp_attr_prim_dev_type)
809 + sizeof(struct wlp_attr_wlp_assc_err));
812 d_fnend(6, dev, "wlp %p, result = %d\n", wlp, result);
817 * Construct a D2 association frame
819 * We use the radio control functions to determine the values of the device
820 * properties. These are of variable length and the total space needed is
821 * tallied first before we start constructing the message. The radio
822 * control functions return strings that are terminated with \0. This
823 * character should not be included in the message (there is a length field
824 * accompanying it in the attribute).
827 int wlp_build_assoc_d2(struct wlp *wlp, struct wlp_wss *wss,
828 struct sk_buff **skb, struct wlp_uuid *uuid_e)
831 struct device *dev = &wlp->rc->uwb_dev.dev;
833 struct wlp_device_info *info;
835 struct wlp_frame_assoc *_d2;
836 struct sk_buff *_skb;
840 d_fnstart(6, dev, "wlp %p\n", wlp);
841 if (wlp->dev_info == NULL) {
842 result = __wlp_setup_device_info(wlp);
844 dev_err(dev, "WLP: Unable to setup device "
845 "information for D2 message.\n");
849 info = wlp->dev_info;
850 d_printf(6, dev, "Local properties:\n"
851 "Device name (%d bytes): %s\n"
852 "Model name (%d bytes): %s\n"
853 "Manufacturer (%d bytes): %s\n"
854 "Model number (%d bytes): %s\n"
855 "Serial number (%d bytes): %s\n"
856 "Primary device type: \n"
858 " OUI: %02x:%02x:%02x \n"
859 " OUI Subdivision: %u \n",
860 (int)strlen(info->name), info->name,
861 (int)strlen(info->model_name), info->model_name,
862 (int)strlen(info->manufacturer), info->manufacturer,
863 (int)strlen(info->model_nr), info->model_nr,
864 (int)strlen(info->serial), info->serial,
865 info->prim_dev_type.category,
866 info->prim_dev_type.OUI[0], info->prim_dev_type.OUI[1],
867 info->prim_dev_type.OUI[2], info->prim_dev_type.OUIsubdiv);
868 mem_needed = sizeof(*_d2)
869 + sizeof(struct wlp_attr_uuid_e)
870 + sizeof(struct wlp_attr_uuid_r)
871 + sizeof(struct wlp_attr_dev_name)
873 + sizeof(struct wlp_attr_manufacturer)
874 + strlen(info->manufacturer)
875 + sizeof(struct wlp_attr_model_name)
876 + strlen(info->model_name)
877 + sizeof(struct wlp_attr_model_nr)
878 + strlen(info->model_nr)
879 + sizeof(struct wlp_attr_serial)
880 + strlen(info->serial)
881 + sizeof(struct wlp_attr_prim_dev_type)
882 + sizeof(struct wlp_attr_wlp_assc_err);
883 if (wlp->wss.state >= WLP_WSS_STATE_ACTIVE)
884 mem_needed += sizeof(struct wlp_attr_wss_info)
885 + sizeof(struct wlp_wss_info)
886 + strlen(wlp->wss.name);
887 _skb = dev_alloc_skb(mem_needed);
889 dev_err(dev, "WLP: Cannot allocate memory for association "
894 _d2 = (void *) _skb->data;
895 d_printf(6, dev, "D2 starts at %p \n", _d2);
896 _d2->hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID);
897 _d2->hdr.type = WLP_FRAME_ASSOCIATION;
898 _d2->type = WLP_ASSOC_D2;
900 wlp_set_version(&_d2->version, WLP_VERSION);
901 wlp_set_msg_type(&_d2->msg_type, WLP_ASSOC_D2);
903 used = wlp_set_uuid_e(d2_itr, uuid_e);
904 used += wlp_set_uuid_r(d2_itr + used, &wlp->uuid);
905 if (wlp->wss.state >= WLP_WSS_STATE_ACTIVE)
906 used += wlp_set_wss_info(d2_itr + used, &wlp->wss);
907 used += wlp_set_dev_name(d2_itr + used, info->name,
909 used += wlp_set_manufacturer(d2_itr + used, info->manufacturer,
910 strlen(info->manufacturer));
911 used += wlp_set_model_name(d2_itr + used, info->model_name,
912 strlen(info->model_name));
913 used += wlp_set_model_nr(d2_itr + used, info->model_nr,
914 strlen(info->model_nr));
915 used += wlp_set_serial(d2_itr + used, info->serial,
916 strlen(info->serial));
917 used += wlp_set_prim_dev_type(d2_itr + used, &info->prim_dev_type);
918 used += wlp_set_wlp_assc_err(d2_itr + used, WLP_ASSOC_ERROR_NONE);
919 skb_put(_skb, sizeof(*_d2) + used);
920 d_printf(6, dev, "D2 message:\n");
921 d_dump(6, dev, _d2, mem_needed);
924 d_fnend(6, dev, "wlp %p, result = %d\n", wlp, result);
929 * Allocate memory for and populate fields of F0 association frame
931 * Currently (while focusing on unsecure enrollment) we ignore the
932 * nonce's that could be placed in the message. Only the error field is
933 * populated by the value provided by the caller.
936 int wlp_build_assoc_f0(struct wlp *wlp, struct sk_buff **skb,
937 enum wlp_assc_error error)
939 struct device *dev = &wlp->rc->uwb_dev.dev;
940 int result = -ENOMEM;
942 struct wlp_frame_assoc f0_hdr;
943 struct wlp_attr_enonce enonce;
944 struct wlp_attr_rnonce rnonce;
945 struct wlp_attr_wlp_assc_err assc_err;
947 struct sk_buff *_skb;
948 struct wlp_nonce tmp;
950 d_fnstart(6, dev, "wlp %p\n", wlp);
951 _skb = dev_alloc_skb(sizeof(*f0));
953 dev_err(dev, "WLP: Unable to allocate memory for F0 "
954 "association frame. \n");
957 f0 = (void *) _skb->data;
958 d_printf(6, dev, "F0 starts at %p \n", f0);
959 f0->f0_hdr.hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID);
960 f0->f0_hdr.hdr.type = WLP_FRAME_ASSOCIATION;
961 f0->f0_hdr.type = WLP_ASSOC_F0;
962 wlp_set_version(&f0->f0_hdr.version, WLP_VERSION);
963 wlp_set_msg_type(&f0->f0_hdr.msg_type, WLP_ASSOC_F0);
964 memset(&tmp, 0, sizeof(tmp));
965 wlp_set_enonce(&f0->enonce, &tmp);
966 wlp_set_rnonce(&f0->rnonce, &tmp);
967 wlp_set_wlp_assc_err(&f0->assc_err, error);
968 skb_put(_skb, sizeof(*f0));
972 d_fnend(6, dev, "wlp %p, result %d \n", wlp, result);
979 * We just retrieve the values and print it as an error to the user.
980 * Calling function already knows an error occured (F0 indicates error), so
981 * we just parse the content as debug for higher layers.
983 int wlp_parse_f0(struct wlp *wlp, struct sk_buff *skb)
985 struct device *dev = &wlp->rc->uwb_dev.dev;
986 struct wlp_frame_assoc *f0 = (void *) skb->data;
987 void *ptr = skb->data;
988 size_t len = skb->len;
991 struct wlp_nonce enonce, rnonce;
992 enum wlp_assc_error assc_err;
993 char enonce_buf[WLP_WSS_NONCE_STRSIZE];
994 char rnonce_buf[WLP_WSS_NONCE_STRSIZE];
997 result = wlp_get_enonce(wlp, ptr + used, &enonce, len - used);
999 dev_err(dev, "WLP: unable to obtain Enrollee nonce "
1000 "attribute from F0 message.\n");
1004 result = wlp_get_rnonce(wlp, ptr + used, &rnonce, len - used);
1006 dev_err(dev, "WLP: unable to obtain Registrar nonce "
1007 "attribute from F0 message.\n");
1011 result = wlp_get_wlp_assc_err(wlp, ptr + used, &assc_err, len - used);
1013 dev_err(dev, "WLP: unable to obtain WLP Association error "
1014 "attribute from F0 message.\n");
1017 wlp_wss_nonce_print(enonce_buf, sizeof(enonce_buf), &enonce);
1018 wlp_wss_nonce_print(rnonce_buf, sizeof(rnonce_buf), &rnonce);
1019 dev_err(dev, "WLP: Received F0 error frame from neighbor. Enrollee "
1020 "nonce: %s, Registrar nonce: %s, WLP Association error: %s.\n",
1021 enonce_buf, rnonce_buf, wlp_assc_error_str(assc_err));
1028 * Retrieve variable device information from association message
1030 * The device information parsed is not required in any message. This
1031 * routine will thus not fail if an attribute is not present.
1032 * The attributes are expected in a certain order, even if all are not
1033 * present. The "attribute type" value is used to ensure the attributes
1034 * are parsed in the correct order.
1036 * If an error is encountered during parsing the function will return an
1037 * error code, when this happens the given device_info structure may be
1041 int wlp_get_variable_info(struct wlp *wlp, void *data,
1042 struct wlp_device_info *dev_info, ssize_t len)
1044 struct device *dev = &wlp->rc->uwb_dev.dev;
1046 struct wlp_attr_hdr *hdr;
1050 while (len - used > 0) {
1051 if (len - used < sizeof(*hdr)) {
1052 dev_err(dev, "WLP: Partial data in frame, cannot "
1057 switch (le16_to_cpu(hdr->type)) {
1058 case WLP_ATTR_MANUF:
1059 if (last >= WLP_ATTR_MANUF) {
1060 dev_err(dev, "WLP: Incorrect order of "
1061 "attribute values in D1 msg.\n");
1064 result = wlp_get_manufacturer(wlp, data + used,
1065 dev_info->manufacturer,
1068 dev_err(dev, "WLP: Unable to obtain "
1069 "Manufacturer attribute from D1 "
1073 last = WLP_ATTR_MANUF;
1076 case WLP_ATTR_MODEL_NAME:
1077 if (last >= WLP_ATTR_MODEL_NAME) {
1078 dev_err(dev, "WLP: Incorrect order of "
1079 "attribute values in D1 msg.\n");
1082 result = wlp_get_model_name(wlp, data + used,
1083 dev_info->model_name,
1086 dev_err(dev, "WLP: Unable to obtain Model "
1087 "name attribute from D1 message.\n");
1090 last = WLP_ATTR_MODEL_NAME;
1093 case WLP_ATTR_MODEL_NR:
1094 if (last >= WLP_ATTR_MODEL_NR) {
1095 dev_err(dev, "WLP: Incorrect order of "
1096 "attribute values in D1 msg.\n");
1099 result = wlp_get_model_nr(wlp, data + used,
1103 dev_err(dev, "WLP: Unable to obtain Model "
1104 "number attribute from D1 message.\n");
1107 last = WLP_ATTR_MODEL_NR;
1110 case WLP_ATTR_SERIAL:
1111 if (last >= WLP_ATTR_SERIAL) {
1112 dev_err(dev, "WLP: Incorrect order of "
1113 "attribute values in D1 msg.\n");
1116 result = wlp_get_serial(wlp, data + used,
1117 dev_info->serial, len - used);
1119 dev_err(dev, "WLP: Unable to obtain Serial "
1120 "number attribute from D1 message.\n");
1123 last = WLP_ATTR_SERIAL;
1126 case WLP_ATTR_PRI_DEV_TYPE:
1127 if (last >= WLP_ATTR_PRI_DEV_TYPE) {
1128 dev_err(dev, "WLP: Incorrect order of "
1129 "attribute values in D1 msg.\n");
1132 result = wlp_get_prim_dev_type(wlp, data + used,
1133 &dev_info->prim_dev_type,
1136 dev_err(dev, "WLP: Unable to obtain Primary "
1137 "device type attribute from D1 "
1141 dev_info->prim_dev_type.category =
1142 le16_to_cpu(dev_info->prim_dev_type.category);
1143 dev_info->prim_dev_type.subID =
1144 le16_to_cpu(dev_info->prim_dev_type.subID);
1145 last = WLP_ATTR_PRI_DEV_TYPE;
1149 /* This is not variable device information. */
1161 * Parse incoming D1 frame, populate attribute values
1163 * Caller provides pointers to memory already allocated for attributes
1164 * expected in the D1 frame. These variables will be populated.
1167 int wlp_parse_d1_frame(struct wlp *wlp, struct sk_buff *skb,
1168 struct wlp_uuid *uuid_e,
1169 enum wlp_wss_sel_mthd *sel_mthd,
1170 struct wlp_device_info *dev_info,
1171 enum wlp_assc_error *assc_err)
1173 struct device *dev = &wlp->rc->uwb_dev.dev;
1174 struct wlp_frame_assoc *d1 = (void *) skb->data;
1175 void *ptr = skb->data;
1176 size_t len = skb->len;
1181 result = wlp_get_uuid_e(wlp, ptr + used, uuid_e, len - used);
1183 dev_err(dev, "WLP: unable to obtain UUID-E attribute from D1 "
1188 result = wlp_get_wss_sel_mthd(wlp, ptr + used, sel_mthd, len - used);
1190 dev_err(dev, "WLP: unable to obtain WSS selection method "
1191 "from D1 message.\n");
1195 result = wlp_get_dev_name(wlp, ptr + used, dev_info->name,
1198 dev_err(dev, "WLP: unable to obtain Device Name from D1 "
1203 result = wlp_get_variable_info(wlp, ptr + used, dev_info, len - used);
1205 dev_err(dev, "WLP: unable to obtain Device Information from "
1210 result = wlp_get_wlp_assc_err(wlp, ptr + used, assc_err, len - used);
1212 dev_err(dev, "WLP: unable to obtain WLP Association Error "
1213 "Information from D1 message.\n");
1221 * Handle incoming D1 frame
1223 * The frame has already been verified to contain an Association header with
1224 * the correct version number. Parse the incoming frame, construct and send
1225 * a D2 frame in response.
1227 * It is not clear what to do with most fields in the incoming D1 frame. We
1228 * retrieve and discard the information here for now.
1230 void wlp_handle_d1_frame(struct work_struct *ws)
1232 struct wlp_assoc_frame_ctx *frame_ctx = container_of(ws,
1233 struct wlp_assoc_frame_ctx,
1235 struct wlp *wlp = frame_ctx->wlp;
1236 struct wlp_wss *wss = &wlp->wss;
1237 struct sk_buff *skb = frame_ctx->skb;
1238 struct uwb_dev_addr *src = &frame_ctx->src;
1240 struct device *dev = &wlp->rc->uwb_dev.dev;
1241 struct wlp_uuid uuid_e;
1242 enum wlp_wss_sel_mthd sel_mthd = 0;
1243 struct wlp_device_info dev_info;
1244 enum wlp_assc_error assc_err;
1245 char uuid[WLP_WSS_UUID_STRSIZE];
1246 struct sk_buff *resp = NULL;
1248 /* Parse D1 frame */
1249 d_fnstart(6, dev, "WLP: handle D1 frame. wlp = %p, skb = %p\n",
1251 mutex_lock(&wss->mutex);
1252 mutex_lock(&wlp->mutex); /* to access wlp->uuid */
1253 memset(&dev_info, 0, sizeof(dev_info));
1254 result = wlp_parse_d1_frame(wlp, skb, &uuid_e, &sel_mthd, &dev_info,
1257 dev_err(dev, "WLP: Unable to parse incoming D1 frame.\n");
1261 wlp_wss_uuid_print(uuid, sizeof(uuid), &uuid_e);
1262 d_printf(6, dev, "From D1 frame:\n"
1264 "Selection method: %d\n"
1265 "Device name (%d bytes): %s\n"
1266 "Model name (%d bytes): %s\n"
1267 "Manufacturer (%d bytes): %s\n"
1268 "Model number (%d bytes): %s\n"
1269 "Serial number (%d bytes): %s\n"
1270 "Primary device type: \n"
1272 " OUI: %02x:%02x:%02x \n"
1273 " OUI Subdivision: %u \n",
1275 (int)strlen(dev_info.name), dev_info.name,
1276 (int)strlen(dev_info.model_name), dev_info.model_name,
1277 (int)strlen(dev_info.manufacturer), dev_info.manufacturer,
1278 (int)strlen(dev_info.model_nr), dev_info.model_nr,
1279 (int)strlen(dev_info.serial), dev_info.serial,
1280 dev_info.prim_dev_type.category,
1281 dev_info.prim_dev_type.OUI[0],
1282 dev_info.prim_dev_type.OUI[1],
1283 dev_info.prim_dev_type.OUI[2],
1284 dev_info.prim_dev_type.OUIsubdiv);
1287 if (!wlp_uuid_is_set(&wlp->uuid)) {
1288 dev_err(dev, "WLP: UUID is not set. Set via sysfs to "
1289 "proceed. Respong to D1 message with error F0.\n");
1290 result = wlp_build_assoc_f0(wlp, &resp,
1291 WLP_ASSOC_ERROR_NOT_READY);
1293 dev_err(dev, "WLP: Unable to construct F0 message.\n");
1297 /* Construct D2 frame */
1298 result = wlp_build_assoc_d2(wlp, wss, &resp, &uuid_e);
1300 dev_err(dev, "WLP: Unable to construct D2 message.\n");
1305 BUG_ON(wlp->xmit_frame == NULL);
1306 result = wlp->xmit_frame(wlp, resp, src);
1308 dev_err(dev, "WLP: Unable to transmit D2 association "
1309 "message: %d\n", result);
1310 if (result == -ENXIO)
1311 dev_err(dev, "WLP: Is network interface up? \n");
1312 /* We could try again ... */
1313 dev_kfree_skb_any(resp); /* we need to free if tx fails */
1317 mutex_unlock(&wlp->mutex);
1318 mutex_unlock(&wss->mutex);
1319 d_fnend(6, dev, "WLP: handle D1 frame. wlp = %p\n", wlp);
1323 * Parse incoming D2 frame, create and populate temporary cache
1325 * @skb: socket buffer in which D2 frame can be found
1326 * @neighbor: the neighbor that sent the D2 frame
1328 * Will allocate memory for temporary storage of information learned during
1331 int wlp_parse_d2_frame_to_cache(struct wlp *wlp, struct sk_buff *skb,
1332 struct wlp_neighbor_e *neighbor)
1334 struct device *dev = &wlp->rc->uwb_dev.dev;
1335 struct wlp_frame_assoc *d2 = (void *) skb->data;
1336 void *ptr = skb->data;
1337 size_t len = skb->len;
1340 struct wlp_uuid uuid_e;
1341 struct wlp_device_info *nb_info;
1342 enum wlp_assc_error assc_err;
1345 result = wlp_get_uuid_e(wlp, ptr + used, &uuid_e, len - used);
1347 dev_err(dev, "WLP: unable to obtain UUID-E attribute from D2 "
1351 if (memcmp(&uuid_e, &wlp->uuid, sizeof(uuid_e))) {
1352 dev_err(dev, "WLP: UUID-E in incoming D2 does not match "
1353 "local UUID sent in D1. \n");
1357 result = wlp_get_uuid_r(wlp, ptr + used, &neighbor->uuid, len - used);
1359 dev_err(dev, "WLP: unable to obtain UUID-R attribute from D2 "
1364 result = wlp_get_wss_info_to_cache(wlp, ptr + used, neighbor,
1367 dev_err(dev, "WLP: unable to obtain WSS information "
1368 "from D2 message.\n");
1372 neighbor->info = kzalloc(sizeof(struct wlp_device_info), GFP_KERNEL);
1373 if (neighbor->info == NULL) {
1374 dev_err(dev, "WLP: cannot allocate memory to store device "
1379 nb_info = neighbor->info;
1380 result = wlp_get_dev_name(wlp, ptr + used, nb_info->name,
1383 dev_err(dev, "WLP: unable to obtain Device Name from D2 "
1388 result = wlp_get_variable_info(wlp, ptr + used, nb_info, len - used);
1390 dev_err(dev, "WLP: unable to obtain Device Information from "
1395 result = wlp_get_wlp_assc_err(wlp, ptr + used, &assc_err, len - used);
1397 dev_err(dev, "WLP: unable to obtain WLP Association Error "
1398 "Information from D2 message.\n");
1401 if (assc_err != WLP_ASSOC_ERROR_NONE) {
1402 dev_err(dev, "WLP: neighbor device returned association "
1403 "error %d\n", assc_err);
1410 wlp_remove_neighbor_tmp_info(neighbor);
1415 * Parse incoming D2 frame, populate attribute values of WSS bein enrolled in
1417 * @wss: our WSS that will be enrolled
1418 * @skb: socket buffer in which D2 frame can be found
1419 * @neighbor: the neighbor that sent the D2 frame
1420 * @wssid: the wssid of the WSS in which we want to enroll
1422 * Forms part of enrollment sequence. We are trying to enroll in WSS with
1423 * @wssid by using @neighbor as registrar. A D1 message was sent to
1424 * @neighbor and now we need to parse the D2 response. The neighbor's
1425 * response is searched for the requested WSS and if found (and it accepts
1426 * enrollment), we store the information.
1428 int wlp_parse_d2_frame_to_enroll(struct wlp_wss *wss, struct sk_buff *skb,
1429 struct wlp_neighbor_e *neighbor,
1430 struct wlp_uuid *wssid)
1432 struct wlp *wlp = container_of(wss, struct wlp, wss);
1433 struct device *dev = &wlp->rc->uwb_dev.dev;
1434 void *ptr = skb->data;
1435 size_t len = skb->len;
1438 struct wlp_uuid uuid_e;
1439 struct wlp_uuid uuid_r;
1440 struct wlp_device_info nb_info;
1441 enum wlp_assc_error assc_err;
1442 char uuid_bufA[WLP_WSS_UUID_STRSIZE];
1443 char uuid_bufB[WLP_WSS_UUID_STRSIZE];
1445 used = sizeof(struct wlp_frame_assoc);
1446 result = wlp_get_uuid_e(wlp, ptr + used, &uuid_e, len - used);
1448 dev_err(dev, "WLP: unable to obtain UUID-E attribute from D2 "
1452 if (memcmp(&uuid_e, &wlp->uuid, sizeof(uuid_e))) {
1453 dev_err(dev, "WLP: UUID-E in incoming D2 does not match "
1454 "local UUID sent in D1. \n");
1458 result = wlp_get_uuid_r(wlp, ptr + used, &uuid_r, len - used);
1460 dev_err(dev, "WLP: unable to obtain UUID-R attribute from D2 "
1464 if (memcmp(&uuid_r, &neighbor->uuid, sizeof(uuid_r))) {
1465 wlp_wss_uuid_print(uuid_bufA, sizeof(uuid_bufA),
1467 wlp_wss_uuid_print(uuid_bufB, sizeof(uuid_bufB), &uuid_r);
1468 dev_err(dev, "WLP: UUID of neighbor does not match UUID "
1469 "learned during discovery. Originally discovered: %s, "
1470 "now from D2 message: %s\n", uuid_bufA, uuid_bufB);
1475 wss->wssid = *wssid;
1476 result = wlp_get_wss_info_to_enroll(wlp, ptr + used, wss, len - used);
1478 dev_err(dev, "WLP: unable to obtain WSS information "
1479 "from D2 message.\n");
1482 if (wss->state != WLP_WSS_STATE_PART_ENROLLED) {
1483 dev_err(dev, "WLP: D2 message did not contain information "
1484 "for successful enrollment. \n");
1489 /* Place device information on stack to continue parsing of message */
1490 result = wlp_get_dev_name(wlp, ptr + used, nb_info.name,
1493 dev_err(dev, "WLP: unable to obtain Device Name from D2 "
1498 result = wlp_get_variable_info(wlp, ptr + used, &nb_info, len - used);
1500 dev_err(dev, "WLP: unable to obtain Device Information from "
1505 result = wlp_get_wlp_assc_err(wlp, ptr + used, &assc_err, len - used);
1507 dev_err(dev, "WLP: unable to obtain WLP Association Error "
1508 "Information from D2 message.\n");
1511 if (assc_err != WLP_ASSOC_ERROR_NONE) {
1512 dev_err(dev, "WLP: neighbor device returned association "
1513 "error %d\n", assc_err);
1514 if (wss->state == WLP_WSS_STATE_PART_ENROLLED) {
1515 dev_err(dev, "WLP: Enrolled in WSS (should not "
1516 "happen according to spec). Undoing. \n");
1528 * Parse C3/C4 frame into provided variables
1530 * @wssid: will point to copy of wssid retrieved from C3/C4 frame
1531 * @tag: will point to copy of tag retrieved from C3/C4 frame
1532 * @virt_addr: will point to copy of virtual address retrieved from C3/C4
1535 * Calling function has to allocate memory for these values.
1537 * skb contains a valid C3/C4 frame, return the individual fields of this
1538 * frame in the provided variables.
1540 int wlp_parse_c3c4_frame(struct wlp *wlp, struct sk_buff *skb,
1541 struct wlp_uuid *wssid, u8 *tag,
1542 struct uwb_mac_addr *virt_addr)
1544 struct device *dev = &wlp->rc->uwb_dev.dev;
1546 void *ptr = skb->data;
1547 size_t len = skb->len;
1549 char buf[WLP_WSS_UUID_STRSIZE];
1550 struct wlp_frame_assoc *assoc = ptr;
1552 d_fnstart(6, dev, "wlp %p, skb %p \n", wlp, skb);
1553 used = sizeof(*assoc);
1554 result = wlp_get_wssid(wlp, ptr + used, wssid, len - used);
1556 dev_err(dev, "WLP: unable to obtain WSSID attribute from "
1557 "%s message.\n", wlp_assoc_frame_str(assoc->type));
1561 result = wlp_get_wss_tag(wlp, ptr + used, tag, len - used);
1563 dev_err(dev, "WLP: unable to obtain WSS tag attribute from "
1564 "%s message.\n", wlp_assoc_frame_str(assoc->type));
1568 result = wlp_get_wss_virt(wlp, ptr + used, virt_addr, len - used);
1570 dev_err(dev, "WLP: unable to obtain WSS virtual address "
1571 "attribute from %s message.\n",
1572 wlp_assoc_frame_str(assoc->type));
1575 wlp_wss_uuid_print(buf, sizeof(buf), wssid);
1576 d_printf(6, dev, "WLP: parsed: WSSID %s, tag 0x%02x, virt "
1577 "%02x:%02x:%02x:%02x:%02x:%02x \n", buf, *tag,
1578 virt_addr->data[0], virt_addr->data[1], virt_addr->data[2],
1579 virt_addr->data[3], virt_addr->data[4], virt_addr->data[5]);
1582 d_fnend(6, dev, "wlp %p, skb %p, result = %d \n", wlp, skb, result);
1587 * Allocate memory for and populate fields of C1 or C2 association frame
1589 * The C1 and C2 association frames appear identical - except for the type.
1592 int wlp_build_assoc_c1c2(struct wlp *wlp, struct wlp_wss *wss,
1593 struct sk_buff **skb, enum wlp_assoc_type type)
1595 struct device *dev = &wlp->rc->uwb_dev.dev;
1596 int result = -ENOMEM;
1598 struct wlp_frame_assoc c_hdr;
1599 struct wlp_attr_wssid wssid;
1601 struct sk_buff *_skb;
1603 d_fnstart(6, dev, "wlp %p, wss %p \n", wlp, wss);
1604 _skb = dev_alloc_skb(sizeof(*c));
1606 dev_err(dev, "WLP: Unable to allocate memory for C1/C2 "
1607 "association frame. \n");
1610 c = (void *) _skb->data;
1611 d_printf(6, dev, "C1/C2 starts at %p \n", c);
1612 c->c_hdr.hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID);
1613 c->c_hdr.hdr.type = WLP_FRAME_ASSOCIATION;
1614 c->c_hdr.type = type;
1615 wlp_set_version(&c->c_hdr.version, WLP_VERSION);
1616 wlp_set_msg_type(&c->c_hdr.msg_type, type);
1617 wlp_set_wssid(&c->wssid, &wss->wssid);
1618 skb_put(_skb, sizeof(*c));
1619 d_printf(6, dev, "C1/C2 message:\n");
1620 d_dump(6, dev, c, sizeof(*c));
1624 d_fnend(6, dev, "wlp %p, wss %p, result %d \n", wlp, wss, result);
1630 int wlp_build_assoc_c1(struct wlp *wlp, struct wlp_wss *wss,
1631 struct sk_buff **skb)
1633 return wlp_build_assoc_c1c2(wlp, wss, skb, WLP_ASSOC_C1);
1637 int wlp_build_assoc_c2(struct wlp *wlp, struct wlp_wss *wss,
1638 struct sk_buff **skb)
1640 return wlp_build_assoc_c1c2(wlp, wss, skb, WLP_ASSOC_C2);
1645 * Allocate memory for and populate fields of C3 or C4 association frame
1647 * The C3 and C4 association frames appear identical - except for the type.
1650 int wlp_build_assoc_c3c4(struct wlp *wlp, struct wlp_wss *wss,
1651 struct sk_buff **skb, enum wlp_assoc_type type)
1653 struct device *dev = &wlp->rc->uwb_dev.dev;
1654 int result = -ENOMEM;
1656 struct wlp_frame_assoc c_hdr;
1657 struct wlp_attr_wssid wssid;
1658 struct wlp_attr_wss_tag wss_tag;
1659 struct wlp_attr_wss_virt wss_virt;
1661 struct sk_buff *_skb;
1663 d_fnstart(6, dev, "wlp %p, wss %p \n", wlp, wss);
1664 _skb = dev_alloc_skb(sizeof(*c));
1666 dev_err(dev, "WLP: Unable to allocate memory for C3/C4 "
1667 "association frame. \n");
1670 c = (void *) _skb->data;
1671 d_printf(6, dev, "C3/C4 starts at %p \n", c);
1672 c->c_hdr.hdr.mux_hdr = cpu_to_le16(WLP_PROTOCOL_ID);
1673 c->c_hdr.hdr.type = WLP_FRAME_ASSOCIATION;
1674 c->c_hdr.type = type;
1675 wlp_set_version(&c->c_hdr.version, WLP_VERSION);
1676 wlp_set_msg_type(&c->c_hdr.msg_type, type);
1677 wlp_set_wssid(&c->wssid, &wss->wssid);
1678 wlp_set_wss_tag(&c->wss_tag, wss->tag);
1679 wlp_set_wss_virt(&c->wss_virt, &wss->virtual_addr);
1680 skb_put(_skb, sizeof(*c));
1681 d_printf(6, dev, "C3/C4 message:\n");
1682 d_dump(6, dev, c, sizeof(*c));
1686 d_fnend(6, dev, "wlp %p, wss %p, result %d \n", wlp, wss, result);
1691 int wlp_build_assoc_c3(struct wlp *wlp, struct wlp_wss *wss,
1692 struct sk_buff **skb)
1694 return wlp_build_assoc_c3c4(wlp, wss, skb, WLP_ASSOC_C3);
1698 int wlp_build_assoc_c4(struct wlp *wlp, struct wlp_wss *wss,
1699 struct sk_buff **skb)
1701 return wlp_build_assoc_c3c4(wlp, wss, skb, WLP_ASSOC_C4);
1705 #define wlp_send_assoc(type, id) \
1706 static int wlp_send_assoc_##type(struct wlp *wlp, struct wlp_wss *wss, \
1707 struct uwb_dev_addr *dev_addr) \
1709 struct device *dev = &wlp->rc->uwb_dev.dev; \
1711 struct sk_buff *skb = NULL; \
1712 d_fnstart(6, dev, "wlp %p, wss %p, neighbor: %02x:%02x\n", \
1713 wlp, wss, dev_addr->data[1], dev_addr->data[0]); \
1714 d_printf(6, dev, "WLP: Constructing %s frame. \n", \
1715 wlp_assoc_frame_str(id)); \
1716 /* Build the frame */ \
1717 result = wlp_build_assoc_##type(wlp, wss, &skb); \
1719 dev_err(dev, "WLP: Unable to construct %s association " \
1720 "frame: %d\n", wlp_assoc_frame_str(id), result);\
1721 goto error_build_assoc; \
1723 /* Send the frame */ \
1724 d_printf(6, dev, "Transmitting %s frame to %02x:%02x \n", \
1725 wlp_assoc_frame_str(id), \
1726 dev_addr->data[1], dev_addr->data[0]); \
1727 BUG_ON(wlp->xmit_frame == NULL); \
1728 result = wlp->xmit_frame(wlp, skb, dev_addr); \
1730 dev_err(dev, "WLP: Unable to transmit %s association " \
1731 "message: %d\n", wlp_assoc_frame_str(id), \
1733 if (result == -ENXIO) \
1734 dev_err(dev, "WLP: Is network interface " \
1740 /* We could try again ... */ \
1741 dev_kfree_skb_any(skb);/*we need to free if tx fails*/ \
1742 error_build_assoc: \
1743 d_fnend(6, dev, "wlp %p, wss %p, neighbor: %02x:%02x\n", \
1744 wlp, wss, dev_addr->data[1], dev_addr->data[0]); \
1748 wlp_send_assoc(d1, WLP_ASSOC_D1)
1749 wlp_send_assoc(c1, WLP_ASSOC_C1)
1750 wlp_send_assoc(c3, WLP_ASSOC_C3)
1752 int wlp_send_assoc_frame(struct wlp *wlp, struct wlp_wss *wss,
1753 struct uwb_dev_addr *dev_addr,
1754 enum wlp_assoc_type type)
1757 struct device *dev = &wlp->rc->uwb_dev.dev;
1760 result = wlp_send_assoc_d1(wlp, wss, dev_addr);
1763 result = wlp_send_assoc_c1(wlp, wss, dev_addr);
1766 result = wlp_send_assoc_c3(wlp, wss, dev_addr);
1769 dev_err(dev, "WLP: Received request to send unknown "
1770 "association message.\n");
1778 * Handle incoming C1 frame
1780 * The frame has already been verified to contain an Association header with
1781 * the correct version number. Parse the incoming frame, construct and send
1782 * a C2 frame in response.
1784 void wlp_handle_c1_frame(struct work_struct *ws)
1786 struct wlp_assoc_frame_ctx *frame_ctx = container_of(ws,
1787 struct wlp_assoc_frame_ctx,
1789 struct wlp *wlp = frame_ctx->wlp;
1790 struct wlp_wss *wss = &wlp->wss;
1791 struct device *dev = &wlp->rc->uwb_dev.dev;
1792 struct wlp_frame_assoc *c1 = (void *) frame_ctx->skb->data;
1793 unsigned int len = frame_ctx->skb->len;
1794 struct uwb_dev_addr *src = &frame_ctx->src;
1796 struct wlp_uuid wssid;
1797 char buf[WLP_WSS_UUID_STRSIZE];
1798 struct sk_buff *resp = NULL;
1800 /* Parse C1 frame */
1801 d_fnstart(6, dev, "WLP: handle C1 frame. wlp = %p, c1 = %p\n",
1803 mutex_lock(&wss->mutex);
1804 result = wlp_get_wssid(wlp, (void *)c1 + sizeof(*c1), &wssid,
1807 dev_err(dev, "WLP: unable to obtain WSSID from C1 frame.\n");
1810 wlp_wss_uuid_print(buf, sizeof(buf), &wssid);
1811 d_printf(6, dev, "Received C1 frame with WSSID %s \n", buf);
1812 if (!memcmp(&wssid, &wss->wssid, sizeof(wssid))
1813 && wss->state == WLP_WSS_STATE_ACTIVE) {
1814 d_printf(6, dev, "WSSID from C1 frame is known locally "
1816 /* Construct C2 frame */
1817 result = wlp_build_assoc_c2(wlp, wss, &resp);
1819 dev_err(dev, "WLP: Unable to construct C2 message.\n");
1823 d_printf(6, dev, "WSSID from C1 frame is not known locally "
1824 "or is not active\n");
1825 /* Construct F0 frame */
1826 result = wlp_build_assoc_f0(wlp, &resp, WLP_ASSOC_ERROR_INV);
1828 dev_err(dev, "WLP: Unable to construct F0 message.\n");
1833 d_printf(6, dev, "Transmitting response (C2/F0) frame to %02x:%02x \n",
1834 src->data[1], src->data[0]);
1835 BUG_ON(wlp->xmit_frame == NULL);
1836 result = wlp->xmit_frame(wlp, resp, src);
1838 dev_err(dev, "WLP: Unable to transmit response association "
1839 "message: %d\n", result);
1840 if (result == -ENXIO)
1841 dev_err(dev, "WLP: Is network interface up? \n");
1842 /* We could try again ... */
1843 dev_kfree_skb_any(resp); /* we need to free if tx fails */
1846 kfree_skb(frame_ctx->skb);
1848 mutex_unlock(&wss->mutex);
1849 d_fnend(6, dev, "WLP: handle C1 frame. wlp = %p\n", wlp);
1853 * Handle incoming C3 frame
1855 * The frame has already been verified to contain an Association header with
1856 * the correct version number. Parse the incoming frame, construct and send
1857 * a C4 frame in response. If the C3 frame identifies a WSS that is locally
1858 * active then we connect to this neighbor (add it to our EDA cache).
1860 void wlp_handle_c3_frame(struct work_struct *ws)
1862 struct wlp_assoc_frame_ctx *frame_ctx = container_of(ws,
1863 struct wlp_assoc_frame_ctx,
1865 struct wlp *wlp = frame_ctx->wlp;
1866 struct wlp_wss *wss = &wlp->wss;
1867 struct device *dev = &wlp->rc->uwb_dev.dev;
1868 struct sk_buff *skb = frame_ctx->skb;
1869 struct uwb_dev_addr *src = &frame_ctx->src;
1871 char buf[WLP_WSS_UUID_STRSIZE];
1872 struct sk_buff *resp = NULL;
1873 struct wlp_uuid wssid;
1875 struct uwb_mac_addr virt_addr;
1877 /* Parse C3 frame */
1878 d_fnstart(6, dev, "WLP: handle C3 frame. wlp = %p, skb = %p\n",
1880 mutex_lock(&wss->mutex);
1881 result = wlp_parse_c3c4_frame(wlp, skb, &wssid, &tag, &virt_addr);
1883 dev_err(dev, "WLP: unable to obtain values from C3 frame.\n");
1886 wlp_wss_uuid_print(buf, sizeof(buf), &wssid);
1887 d_printf(6, dev, "Received C3 frame with WSSID %s \n", buf);
1888 if (!memcmp(&wssid, &wss->wssid, sizeof(wssid))
1889 && wss->state >= WLP_WSS_STATE_ACTIVE) {
1890 d_printf(6, dev, "WSSID from C3 frame is known locally "
1892 result = wlp_eda_update_node(&wlp->eda, src, wss,
1893 (void *) virt_addr.data, tag,
1896 dev_err(dev, "WLP: Unable to update EDA cache "
1897 "with new connected neighbor information.\n");
1898 result = wlp_build_assoc_f0(wlp, &resp,
1899 WLP_ASSOC_ERROR_INT);
1901 dev_err(dev, "WLP: Unable to construct F0 "
1906 wss->state = WLP_WSS_STATE_CONNECTED;
1907 /* Construct C4 frame */
1908 result = wlp_build_assoc_c4(wlp, wss, &resp);
1910 dev_err(dev, "WLP: Unable to construct C4 "
1916 d_printf(6, dev, "WSSID from C3 frame is not known locally "
1917 "or is not active\n");
1918 /* Construct F0 frame */
1919 result = wlp_build_assoc_f0(wlp, &resp, WLP_ASSOC_ERROR_INV);
1921 dev_err(dev, "WLP: Unable to construct F0 message.\n");
1926 d_printf(6, dev, "Transmitting response (C4/F0) frame to %02x:%02x \n",
1927 src->data[1], src->data[0]);
1928 BUG_ON(wlp->xmit_frame == NULL);
1929 result = wlp->xmit_frame(wlp, resp, src);
1931 dev_err(dev, "WLP: Unable to transmit response association "
1932 "message: %d\n", result);
1933 if (result == -ENXIO)
1934 dev_err(dev, "WLP: Is network interface up? \n");
1935 /* We could try again ... */
1936 dev_kfree_skb_any(resp); /* we need to free if tx fails */
1939 kfree_skb(frame_ctx->skb);
1941 mutex_unlock(&wss->mutex);
1942 d_fnend(6, dev, "WLP: handle C3 frame. wlp = %p, skb = %p\n",