0.5.11 release
[wpasupplicant] / src / wps / wps_dev_attr.c
1 /*
2  * Wi-Fi Protected Setup - device attributes
3  * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * Alternatively, this software may be distributed under the terms of BSD
10  * license.
11  *
12  * See README and COPYING for more details.
13  */
14
15 #include "includes.h"
16
17 #include "common.h"
18 #include "wps_i.h"
19 #include "wps_dev_attr.h"
20
21
22 static int wps_build_manufacturer(struct wps_device_data *dev,
23                                   struct wpabuf *msg)
24 {
25         size_t len;
26         wpa_printf(MSG_DEBUG, "WPS:  * Manufacturer");
27         wpabuf_put_be16(msg, ATTR_MANUFACTURER);
28         len = dev->manufacturer ? os_strlen(dev->manufacturer) : 0;
29         wpabuf_put_be16(msg, len);
30         wpabuf_put_data(msg, dev->manufacturer, len);
31         return 0;
32 }
33
34
35 static int wps_build_model_name(struct wps_device_data *dev,
36                                 struct wpabuf *msg)
37 {
38         size_t len;
39         wpa_printf(MSG_DEBUG, "WPS:  * Model Name");
40         wpabuf_put_be16(msg, ATTR_MODEL_NAME);
41         len = dev->model_name ? os_strlen(dev->model_name) : 0;
42         wpabuf_put_be16(msg, len);
43         wpabuf_put_data(msg, dev->model_name, len);
44         return 0;
45 }
46
47
48 static int wps_build_model_number(struct wps_device_data *dev,
49                                   struct wpabuf *msg)
50 {
51         size_t len;
52         wpa_printf(MSG_DEBUG, "WPS:  * Model Number");
53         wpabuf_put_be16(msg, ATTR_MODEL_NUMBER);
54         len = dev->model_number ? os_strlen(dev->model_number) : 0;
55         wpabuf_put_be16(msg, len);
56         wpabuf_put_data(msg, dev->model_number, len);
57         return 0;
58 }
59
60
61 static int wps_build_serial_number(struct wps_device_data *dev,
62                                    struct wpabuf *msg)
63 {
64         size_t len;
65         wpa_printf(MSG_DEBUG, "WPS:  * Serial Number");
66         wpabuf_put_be16(msg, ATTR_SERIAL_NUMBER);
67         len = dev->serial_number ? os_strlen(dev->serial_number) : 0;
68         wpabuf_put_be16(msg, len);
69         wpabuf_put_data(msg, dev->serial_number, len);
70         return 0;
71 }
72
73
74 static int wps_build_primary_dev_type(struct wps_device_data *dev,
75                                       struct wpabuf *msg)
76 {
77         struct wps_dev_type *d;
78         wpa_printf(MSG_DEBUG, "WPS:  * Primary Device Type");
79         wpabuf_put_be16(msg, ATTR_PRIMARY_DEV_TYPE);
80         wpabuf_put_be16(msg, sizeof(*d));
81         d = wpabuf_put(msg, sizeof(*d));
82         WPA_PUT_BE16(d->categ_id, dev->categ);
83         WPA_PUT_BE32(d->oui, dev->oui);
84         WPA_PUT_BE16(d->sub_categ_id, dev->sub_categ);
85         return 0;
86 }
87
88
89 static int wps_build_dev_name(struct wps_device_data *dev, struct wpabuf *msg)
90 {
91         size_t len;
92         wpa_printf(MSG_DEBUG, "WPS:  * Device Name");
93         wpabuf_put_be16(msg, ATTR_DEV_NAME);
94         len = dev->device_name ? os_strlen(dev->device_name) : 0;
95         wpabuf_put_be16(msg, len);
96         wpabuf_put_data(msg, dev->device_name, len);
97         return 0;
98 }
99
100
101 int wps_build_device_attrs(struct wps_device_data *dev, struct wpabuf *msg)
102 {
103         if (wps_build_manufacturer(dev, msg) ||
104             wps_build_model_name(dev, msg) ||
105             wps_build_model_number(dev, msg) ||
106             wps_build_serial_number(dev, msg) ||
107             wps_build_primary_dev_type(dev, msg) ||
108             wps_build_dev_name(dev, msg))
109                 return -1;
110         return 0;
111 }
112
113
114 int wps_build_os_version(struct wps_device_data *dev, struct wpabuf *msg)
115 {
116         wpa_printf(MSG_DEBUG, "WPS:  * OS Version");
117         wpabuf_put_be16(msg, ATTR_OS_VERSION);
118         wpabuf_put_be16(msg, 4);
119         wpabuf_put_be32(msg, 0x80000000 | dev->os_version);
120         return 0;
121 }
122
123
124 static int wps_process_manufacturer(struct wps_device_data *dev, const u8 *str,
125                                     size_t str_len)
126 {
127         if (str == NULL) {
128                 wpa_printf(MSG_DEBUG, "WPS: No Manufacturer received");
129                 return -1;
130         }
131
132         wpa_hexdump_ascii(MSG_DEBUG, "WPS: Manufacturer", str, str_len);
133
134         os_free(dev->manufacturer);
135         dev->manufacturer = os_malloc(str_len + 1);
136         if (dev->manufacturer == NULL)
137                 return -1;
138         os_memcpy(dev->manufacturer, str, str_len);
139         dev->manufacturer[str_len] = '\0';
140
141         return 0;
142 }
143
144
145 static int wps_process_model_name(struct wps_device_data *dev, const u8 *str,
146                                   size_t str_len)
147 {
148         if (str == NULL) {
149                 wpa_printf(MSG_DEBUG, "WPS: No Model Name received");
150                 return -1;
151         }
152
153         wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Name", str, str_len);
154
155         os_free(dev->model_name);
156         dev->model_name = os_malloc(str_len + 1);
157         if (dev->model_name == NULL)
158                 return -1;
159         os_memcpy(dev->model_name, str, str_len);
160         dev->model_name[str_len] = '\0';
161
162         return 0;
163 }
164
165
166 static int wps_process_model_number(struct wps_device_data *dev, const u8 *str,
167                                     size_t str_len)
168 {
169         if (str == NULL) {
170                 wpa_printf(MSG_DEBUG, "WPS: No Model Number received");
171                 return -1;
172         }
173
174         wpa_hexdump_ascii(MSG_DEBUG, "WPS: Model Number", str, str_len);
175
176         os_free(dev->model_number);
177         dev->model_number = os_malloc(str_len + 1);
178         if (dev->model_number == NULL)
179                 return -1;
180         os_memcpy(dev->model_number, str, str_len);
181         dev->model_number[str_len] = '\0';
182
183         return 0;
184 }
185
186
187 static int wps_process_serial_number(struct wps_device_data *dev,
188                                      const u8 *str, size_t str_len)
189 {
190         if (str == NULL) {
191                 wpa_printf(MSG_DEBUG, "WPS: No Serial Number received");
192                 return -1;
193         }
194
195         wpa_hexdump_ascii(MSG_DEBUG, "WPS: Serial Number", str, str_len);
196
197         os_free(dev->serial_number);
198         dev->serial_number = os_malloc(str_len + 1);
199         if (dev->serial_number == NULL)
200                 return -1;
201         os_memcpy(dev->serial_number, str, str_len);
202         dev->serial_number[str_len] = '\0';
203
204         return 0;
205 }
206
207
208 static int wps_process_dev_name(struct wps_device_data *dev, const u8 *str,
209                                 size_t str_len)
210 {
211         if (str == NULL) {
212                 wpa_printf(MSG_DEBUG, "WPS: No Device Name received");
213                 return -1;
214         }
215
216         wpa_hexdump_ascii(MSG_DEBUG, "WPS: Device Name", str, str_len);
217
218         os_free(dev->device_name);
219         dev->device_name = os_malloc(str_len + 1);
220         if (dev->device_name == NULL)
221                 return -1;
222         os_memcpy(dev->device_name, str, str_len);
223         dev->device_name[str_len] = '\0';
224
225         return 0;
226 }
227
228
229 static int wps_process_primary_dev_type(struct wps_device_data *dev,
230                                         const u8 *dev_type)
231 {
232         struct wps_dev_type *d;
233
234         if (dev_type == NULL) {
235                 wpa_printf(MSG_DEBUG, "WPS: No Primary Device Type received");
236                 return -1;
237         }
238
239         d = (struct wps_dev_type *) dev_type;
240         dev->categ = WPA_GET_BE16(d->categ_id);
241         dev->oui = WPA_GET_BE32(d->oui);
242         dev->sub_categ = WPA_GET_BE16(d->sub_categ_id);
243
244         wpa_printf(MSG_DEBUG, "WPS: Primary Device Type: category %d "
245                    "OUI %08x sub-category %d",
246                    dev->categ, dev->oui, dev->sub_categ);
247
248         return 0;
249 }
250
251
252 int wps_process_device_attrs(struct wps_device_data *dev,
253                              struct wps_parse_attr *attr)
254 {
255         if (wps_process_manufacturer(dev, attr->manufacturer,
256                                      attr->manufacturer_len) ||
257             wps_process_model_name(dev, attr->model_name,
258                                    attr->model_name_len) ||
259             wps_process_model_number(dev, attr->model_number,
260                                      attr->model_number_len) ||
261             wps_process_serial_number(dev, attr->serial_number,
262                                       attr->serial_number_len) ||
263             wps_process_primary_dev_type(dev, attr->primary_dev_type) ||
264             wps_process_dev_name(dev, attr->dev_name, attr->dev_name_len))
265                 return -1;
266         return 0;
267 }
268
269
270 int wps_process_os_version(struct wps_device_data *dev, const u8 *ver)
271 {
272         if (ver == NULL) {
273                 wpa_printf(MSG_DEBUG, "WPS: No OS Version received");
274                 return -1;
275         }
276
277         dev->os_version = WPA_GET_BE32(ver);
278         wpa_printf(MSG_DEBUG, "WPS: OS Version %08x", dev->os_version);
279
280         return 0;
281 }
282
283
284 void wps_device_data_dup(struct wps_device_data *dst,
285                          const struct wps_device_data *src)
286 {
287         if (src->device_name)
288                 dst->device_name = os_strdup(src->device_name);
289         if (src->manufacturer)
290                 dst->manufacturer = os_strdup(src->manufacturer);
291         if (src->model_name)
292                 dst->model_name = os_strdup(src->model_name);
293         if (src->model_number)
294                 dst->model_number = os_strdup(src->model_number);
295         if (src->serial_number)
296                 dst->serial_number = os_strdup(src->serial_number);
297         dst->categ = src->categ;
298         dst->oui = src->oui;
299         dst->sub_categ = src->sub_categ;
300         dst->os_version = src->os_version;
301 }
302
303
304 void wps_device_data_free(struct wps_device_data *dev)
305 {
306         os_free(dev->device_name);
307         dev->device_name = NULL;
308         os_free(dev->manufacturer);
309         dev->manufacturer = NULL;
310         os_free(dev->model_name);
311         dev->model_name = NULL;
312         os_free(dev->model_number);
313         dev->model_number = NULL;
314         os_free(dev->serial_number);
315         dev->serial_number = NULL;
316 }