2 * NDEF(NFC Data Exchange Format) routines for Wi-Fi Protected Setup
3 * Reference is "NFCForum-TS-NDEF_1.0 2006-07-24".
4 * Copyright (c) 2009, Masashi Honma <honma@ictec.co.jp>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
10 * Alternatively, this software may be distributed under the terms of BSD
13 * See README and COPYING for more details.
19 #include "wps/wps_i.h"
21 #define FLAG_MESSAGE_BEGIN (1 << 7)
22 #define FLAG_MESSAGE_END (1 << 6)
23 #define FLAG_CHUNK (1 << 5)
24 #define FLAG_SHORT_RECORD (1 << 4)
25 #define FLAG_ID_LENGTH_PRESENT (1 << 3)
26 #define FLAG_TNF_RFC2046 (0x02)
38 static char wifi_handover_type
[] = "application/vnd.wfa.wsc";
40 static int ndef_parse_record(u8
*data
, u32 size
, struct ndef_record
*record
)
46 record
->type_length
= *pos
++;
47 if (data
[0] & FLAG_SHORT_RECORD
) {
50 record
->payload_length
= *pos
++;
54 record
->payload_length
= ntohl(*(u32
*)pos
);
58 if (data
[0] & FLAG_ID_LENGTH_PRESENT
) {
59 if ((int) size
< pos
- data
+ 1)
61 record
->id_length
= *pos
++;
63 record
->id_length
= 0;
65 record
->type
= record
->type_length
== 0 ? NULL
: pos
;
66 pos
+= record
->type_length
;
68 record
->id
= record
->id_length
== 0 ? NULL
: pos
;
69 pos
+= record
->id_length
;
71 record
->payload
= record
->payload_length
== 0 ? NULL
: pos
;
72 pos
+= record
->payload_length
;
74 record
->total_length
= pos
- data
;
75 if (record
->total_length
> size
)
81 static struct wpabuf
* ndef_parse_records(struct wpabuf
*buf
,
82 int (*filter
)(struct ndef_record
*))
84 struct ndef_record record
;
85 int len
= wpabuf_len(buf
);
86 u8
*data
= wpabuf_mhead(buf
);
89 if (ndef_parse_record(data
, len
, &record
) < 0) {
90 wpa_printf(MSG_ERROR
, "NDEF : Failed to parse");
93 if (filter
== NULL
|| filter(&record
))
94 return wpabuf_alloc_copy(record
.payload
,
95 record
.payload_length
);
96 data
+= record
.total_length
;
97 len
-= record
.total_length
;
99 wpa_printf(MSG_ERROR
, "NDEF : Record not found");
104 static struct wpabuf
* ndef_build_record(u8 flags
, void *type
,
105 u8 type_length
, void *id
,
106 u8 id_length
, void *payload
,
109 struct wpabuf
*record
;
114 short_record
= payload_length
< 256 ? 1 : 0;
116 total_len
= 2; /* flag + type length */
118 total_len
+= short_record
? sizeof(u8
) : sizeof(u32
);
121 total_len
+= type_length
+ id_length
+ payload_length
;
122 record
= wpabuf_alloc(total_len
);
123 if (record
== NULL
) {
124 wpa_printf(MSG_ERROR
, "NDEF : Failed to allocate "
131 local_flag
|= FLAG_ID_LENGTH_PRESENT
;
133 local_flag
|= FLAG_SHORT_RECORD
;
134 wpabuf_put_u8(record
, local_flag
);
136 wpabuf_put_u8(record
, type_length
);
139 wpabuf_put_u8(record
, payload_length
);
141 wpabuf_put_be32(record
, payload_length
);
144 wpabuf_put_u8(record
, id_length
);
145 wpabuf_put_data(record
, type
, type_length
);
146 wpabuf_put_data(record
, id
, id_length
);
147 wpabuf_put_data(record
, payload
, payload_length
);
152 static int wifi_filter(struct ndef_record
*record
)
154 if (record
->type_length
!= os_strlen(wifi_handover_type
))
156 if (os_memcmp(record
->type
, wifi_handover_type
,
157 os_strlen(wifi_handover_type
)) != 0)
163 struct wpabuf
* ndef_parse_wifi(struct wpabuf
*buf
)
165 return ndef_parse_records(buf
, wifi_filter
);
169 struct wpabuf
* ndef_build_wifi(struct wpabuf
*buf
)
171 return ndef_build_record(FLAG_MESSAGE_BEGIN
| FLAG_MESSAGE_END
|
172 FLAG_TNF_RFC2046
, wifi_handover_type
,
173 os_strlen(wifi_handover_type
), NULL
, 0,
174 wpabuf_mhead(buf
), wpabuf_len(buf
));